No public description

PiperOrigin-RevId: 590720690
Change-Id: Ie6278c1f06064e2ee64cf68eb82a3e0f21368673
diff --git a/LICENSE b/LICENSE
index d244392..e4499b0 100644
--- a/LICENSE
+++ b/LICENSE
@@ -340,10 +340,7 @@
 THE SOFTWARE.
 
 -----------------------------------------------------------
-GNU General Public License, version 2,
-with the Classpath Exception
-
-The GNU General Public License (GPL)
+GNU General Public License
 
 Version 2, June 1991
 
@@ -1851,8 +1848,7 @@
 Copyright (c) 1997, 1998, 1999, 2004 The NetBSD Foundation, Inc.
 All rights reserved.
 
-This code is derived from software contributed to The NetBSD Foundation
-by Luke Mewburn.
+This code is derived from software contributed to The NetBSD Foundation by
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
@@ -1887,10 +1883,6 @@
 -------------------------------------------------------------------
 Unlicense
 
-Code written by Trevor Perrin, Kees Bos, Sam Rushing, Dimitris Moraitis,
-Marcelo Fernandez, Martin von Loewis, Dave Baggett, and Yngve Pettersen is 
-available under the following terms:
-
 This is free and unencumbered software released into the public domain.
 
 Anyone is free to copy, modify, publish, use, compile, sell, or distribute
@@ -1911,6 +1903,8 @@
 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+For more information, please refer to <https://unlicense.org>
+
 -------------------------------------------------------------------
 University of Illinois/NCSA
 Open Source License
@@ -2521,3 +2515,4038 @@
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
+-------------------------------------------------------------------
+Mozilla Public License, version 2.0
+
+1. Definitions
+
+1.1. "Contributor"
+
+     means each individual or legal entity that creates, contributes to the
+     creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+
+     means the combination of the Contributions of others (if any) used by a
+     Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+
+     means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+
+     means Source Code Form to which the initial Contributor has attached the
+     notice in Exhibit A, the Executable Form of such Source Code Form, and
+     Modifications of such Source Code Form, in each case including portions
+     thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+     means
+
+     a. that the initial Contributor has attached the notice described in
+        Exhibit B to the Covered Software; or
+
+     b. that the Covered Software was made available under the terms of
+        version 1.1 or earlier of the License, but not also under the terms of
+        a Secondary License.
+
+1.6. "Executable Form"
+
+     means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+
+     means a work that combines Covered Software with other material, in a
+     separate file or files, that is not Covered Software.
+
+1.8. "License"
+
+     means this document.
+
+1.9. "Licensable"
+
+     means having the right to grant, to the maximum extent possible, whether
+     at the time of the initial grant or subsequently, any and all of the
+     rights conveyed by this License.
+
+1.10. "Modifications"
+
+     means any of the following:
+
+     a. any file in Source Code Form that results from an addition to,
+        deletion from, or modification of the contents of Covered Software; or
+
+     b. any new file in Source Code Form that contains any Covered Software.
+
+1.11. "Patent Claims" of a Contributor
+
+      means any patent claim(s), including without limitation, method,
+      process, and apparatus claims, in any patent Licensable by such
+      Contributor that would be infringed, but for the grant of the License,
+      by the making, using, selling, offering for sale, having made, import,
+      or transfer of either its Contributions or its Contributor Version.
+
+1.12. "Secondary License"
+
+      means either the GNU General Public License, Version 2.0, the GNU Lesser
+      General Public License, Version 2.1, the GNU Affero General Public
+      License, Version 3.0, or any later versions of those licenses.
+
+1.13. "Source Code Form"
+
+      means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+
+      means an individual or a legal entity exercising rights under this
+      License. For legal entities, "You" includes any entity that controls, is
+      controlled by, or is under common control with You. For purposes of this
+      definition, "control" means (a) the power, direct or indirect, to cause
+      the direction or management of such entity, whether by contract or
+      otherwise, or (b) ownership of more than fifty percent (50%) of the
+      outstanding shares or beneficial ownership of such entity.
+
+
+2. License Grants and Conditions
+
+2.1. Grants
+
+     Each Contributor hereby grants You a world-wide, royalty-free,
+     non-exclusive license:
+
+     a. under intellectual property rights (other than patent or trademark)
+        Licensable by such Contributor to use, reproduce, make available,
+        modify, display, perform, distribute, and otherwise exploit its
+        Contributions, either on an unmodified basis, with Modifications, or
+        as part of a Larger Work; and
+
+     b. under Patent Claims of such Contributor to make, use, sell, offer for
+        sale, have made, import, and otherwise transfer either its
+        Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+     The licenses granted in Section 2.1 with respect to any Contribution
+     become effective for each Contribution on the date the Contributor first
+     distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+     The licenses granted in this Section 2 are the only rights granted under
+     this License. No additional rights or licenses will be implied from the
+     distribution or licensing of Covered Software under this License.
+     Notwithstanding Section 2.1(b) above, no patent license is granted by a
+     Contributor:
+
+     a. for any code that a Contributor has removed from Covered Software; or
+
+     b. for infringements caused by: (i) Your and any other third party's
+        modifications of Covered Software, or (ii) the combination of its
+        Contributions with other software (except as part of its Contributor
+        Version); or
+
+     c. under Patent Claims infringed by Covered Software in the absence of
+        its Contributions.
+
+     This License does not grant any rights in the trademarks, service marks,
+     or logos of any Contributor (except as may be necessary to comply with
+     the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+     No Contributor makes additional grants as a result of Your choice to
+     distribute the Covered Software under a subsequent version of this
+     License (see Section 10.2) or under the terms of a Secondary License (if
+     permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+     Each Contributor represents that the Contributor believes its
+     Contributions are its original creation(s) or it has sufficient rights to
+     grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+     This License is not intended to limit any rights You have under
+     applicable copyright doctrines of fair use, fair dealing, or other
+     equivalents.
+
+2.7. Conditions
+
+     Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
+     Section 2.1.
+
+
+3. Responsibilities
+
+3.1. Distribution of Source Form
+
+     All distribution of Covered Software in Source Code Form, including any
+     Modifications that You create or to which You contribute, must be under
+     the terms of this License. You must inform recipients that the Source
+     Code Form of the Covered Software is governed by the terms of this
+     License, and how they can obtain a copy of this License. You may not
+     attempt to alter or restrict the recipients' rights in the Source Code
+     Form.
+
+3.2. Distribution of Executable Form
+
+     If You distribute Covered Software in Executable Form then:
+
+     a. such Covered Software must also be made available in Source Code Form,
+        as described in Section 3.1, and You must inform recipients of the
+        Executable Form how they can obtain a copy of such Source Code Form by
+        reasonable means in a timely manner, at a charge no more than the cost
+        of distribution to the recipient; and
+
+     b. You may distribute such Executable Form under the terms of this
+        License, or sublicense it under different terms, provided that the
+        license for the Executable Form does not attempt to limit or alter the
+        recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+     You may create and distribute a Larger Work under terms of Your choice,
+     provided that You also comply with the requirements of this License for
+     the Covered Software. If the Larger Work is a combination of Covered
+     Software with a work governed by one or more Secondary Licenses, and the
+     Covered Software is not Incompatible With Secondary Licenses, this
+     License permits You to additionally distribute such Covered Software
+     under the terms of such Secondary License(s), so that the recipient of
+     the Larger Work may, at their option, further distribute the Covered
+     Software under the terms of either this License or such Secondary
+     License(s).
+
+3.4. Notices
+
+     You may not remove or alter the substance of any license notices
+     (including copyright notices, patent notices, disclaimers of warranty, or
+     limitations of liability) contained within the Source Code Form of the
+     Covered Software, except that You may alter any license notices to the
+     extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+     You may choose to offer, and to charge a fee for, warranty, support,
+     indemnity or liability obligations to one or more recipients of Covered
+     Software. However, You may do so only on Your own behalf, and not on
+     behalf of any Contributor. You must make it absolutely clear that any
+     such warranty, support, indemnity, or liability obligation is offered by
+     You alone, and You hereby agree to indemnify every Contributor for any
+     liability incurred by such Contributor as a result of warranty, support,
+     indemnity or liability terms You offer. You may include additional
+     disclaimers of warranty and limitations of liability specific to any
+     jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+
+   If it is impossible for You to comply with any of the terms of this License
+   with respect to some or all of the Covered Software due to statute,
+   judicial order, or regulation then You must: (a) comply with the terms of
+   this License to the maximum extent possible; and (b) describe the
+   limitations and the code they affect. Such description must be placed in a
+   text file included with all distributions of the Covered Software under
+   this License. Except to the extent prohibited by statute or regulation,
+   such description must be sufficiently detailed for a recipient of ordinary
+   skill to be able to understand it.
+
+5. Termination
+
+5.1. The rights granted under this License will terminate automatically if You
+     fail to comply with any of its terms. However, if You become compliant,
+     then the rights granted under this License from a particular Contributor
+     are reinstated (a) provisionally, unless and until such Contributor
+     explicitly and finally terminates Your grants, and (b) on an ongoing
+     basis, if such Contributor fails to notify You of the non-compliance by
+     some reasonable means prior to 60 days after You have come back into
+     compliance. Moreover, Your grants from a particular Contributor are
+     reinstated on an ongoing basis if such Contributor notifies You of the
+     non-compliance by some reasonable means, this is the first time You have
+     received notice of non-compliance with this License from such
+     Contributor, and You become compliant prior to 30 days after Your receipt
+     of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+     infringement claim (excluding declaratory judgment actions,
+     counter-claims, and cross-claims) alleging that a Contributor Version
+     directly or indirectly infringes any patent, then the rights granted to
+     You by any and all Contributors for the Covered Software under Section
+     2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
+     license agreements (excluding distributors and resellers) which have been
+     validly granted by You or Your distributors under this License prior to
+     termination shall survive termination.
+
+6. Disclaimer of Warranty
+
+   Covered Software is provided under this License on an "as is" basis,
+   without warranty of any kind, either expressed, implied, or statutory,
+   including, without limitation, warranties that the Covered Software is free
+   of defects, merchantable, fit for a particular purpose or non-infringing.
+   The entire risk as to the quality and performance of the Covered Software
+   is with You. Should any Covered Software prove defective in any respect,
+   You (not any Contributor) assume the cost of any necessary servicing,
+   repair, or correction. This disclaimer of warranty constitutes an essential
+   part of this License. No use of  any Covered Software is authorized under
+   this License except under this disclaimer.
+
+7. Limitation of Liability
+
+   Under no circumstances and under no legal theory, whether tort (including
+   negligence), contract, or otherwise, shall any Contributor, or anyone who
+   distributes Covered Software as permitted above, be liable to You for any
+   direct, indirect, special, incidental, or consequential damages of any
+   character including, without limitation, damages for lost profits, loss of
+   goodwill, work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses, even if such party shall have been
+   informed of the possibility of such damages. This limitation of liability
+   shall not apply to liability for death or personal injury resulting from
+   such party's negligence to the extent applicable law prohibits such
+   limitation. Some jurisdictions do not allow the exclusion or limitation of
+   incidental or consequential damages, so this exclusion and limitation may
+   not apply to You.
+
+8. Litigation
+
+   Any litigation relating to this License may be brought only in the courts
+   of a jurisdiction where the defendant maintains its principal place of
+   business and such litigation shall be governed by laws of that
+   jurisdiction, without reference to its conflict-of-law provisions. Nothing
+   in this Section shall prevent a party's ability to bring cross-claims or
+   counter-claims.
+
+9. Miscellaneous
+
+   This License represents the complete agreement concerning the subject
+   matter hereof. If any provision of this License is held to be
+   unenforceable, such provision shall be reformed only to the extent
+   necessary to make it enforceable. Any law or regulation which provides that
+   the language of a contract shall be construed against the drafter shall not
+   be used to construe this License against a Contributor.
+
+
+10. Versions of the License
+
+10.1. New Versions
+
+      Mozilla Foundation is the license steward. Except as provided in Section
+      10.3, no one other than the license steward has the right to modify or
+      publish new versions of this License. Each version will be given a
+      distinguishing version number.
+
+10.2. Effect of New Versions
+
+      You may distribute the Covered Software under the terms of the version
+      of the License under which You originally received the Covered Software,
+      or under the terms of any subsequent version published by the license
+      steward.
+
+10.3. Modified Versions
+
+      If you create software not governed by this License, and you want to
+      create a new license for such software, you may create and use a
+      modified version of this License if you rename the license and remove
+      any references to the name of the license steward (except to note that
+      such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+      Licenses If You choose to distribute Source Code Form that is
+      Incompatible With Secondary Licenses under the terms of this version of
+      the License, the notice described in Exhibit B of this License must be
+      attached.
+
+Exhibit A - Source Code Form License Notice
+
+      This Source Code Form is subject to the
+      terms of the Mozilla Public License, v.
+      2.0. If a copy of the MPL was not
+      distributed with this file, You can
+      obtain one at
+      http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular file,
+then You may include the notice in a location (such as a LICENSE file in a
+relevant directory) where a recipient would be likely to look for such a
+notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+
+      This Source Code Form is "Incompatible
+      With Secondary Licenses", as defined by
+      the Mozilla Public License, v. 2.0.
+-------------------------------------------------------------------
+BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL
+licensing. Files that are completely new have a Google copyright and an ISC
+license. This license is reproduced at the bottom of this file.
+
+Contributors to BoringSSL are required to follow the CLA rules for Chromium:
+https://cla.developers.google.com/clas
+
+Files in third_party/ have their own licenses, as described therein. The MIT
+license, for third_party/fiat, which, unlike other third_party directories, is
+compiled into non-test libraries, is included below.
+
+The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the
+OpenSSL License and the original SSLeay license apply to the toolkit. See below
+for the actual license texts. Actually both licenses are BSD-style Open Source
+licenses. In case of any license issues related to OpenSSL please contact
+openssl-core@openssl.org.
+
+The following are Google-internal bug numbers where explicit permission from
+some authors is recorded for use of their work. (This is purely for our own
+record keeping.)
+  27287199
+  27287880
+  27287883
+
+  OpenSSL License
+  ---------------
+
+/* ====================================================================
+ * Copyright (c) 1998-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+ Original SSLeay License
+ -----------------------
+
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+-------------------------------------------------------------------
+                    The FreeType Project LICENSE
+                    ----------------------------
+
+                            2006-Jan-27
+
+                    Copyright 1996-2002, 2006 by
+          David Turner, Robert Wilhelm, and Werner Lemberg
+
+
+
+Introduction
+============
+
+  The FreeType  Project is distributed in  several archive packages;
+  some of them may contain, in addition to the FreeType font engine,
+  various tools and  contributions which rely on, or  relate to, the
+  FreeType Project.
+
+  This  license applies  to all  files found  in such  packages, and
+  which do not  fall under their own explicit  license.  The license
+  affects  thus  the  FreeType   font  engine,  the  test  programs,
+  documentation and makefiles, at the very least.
+
+  This  license   was  inspired  by  the  BSD,   Artistic,  and  IJG
+  (Independent JPEG  Group) licenses, which  all encourage inclusion
+  and  use of  free  software in  commercial  and freeware  products
+  alike.  As a consequence, its main points are that:
+
+    o We don't promise that this software works. However, we will be
+      interested in any kind of bug reports. (`as is' distribution)
+
+    o You can  use this software for whatever you  want, in parts or
+      full form, without having to pay us. (`royalty-free' usage)
+
+    o You may not pretend that  you wrote this software.  If you use
+      it, or  only parts of it,  in a program,  you must acknowledge
+      somewhere  in  your  documentation  that  you  have  used  the
+      FreeType code. (`credits')
+
+  We  specifically  permit  and  encourage  the  inclusion  of  this
+  software, with  or without modifications,  in commercial products.
+  We  disclaim  all warranties  covering  The  FreeType Project  and
+  assume no liability related to The FreeType Project.
+
+
+  Finally,  many  people  asked  us  for  a  preferred  form  for  a
+  credit/disclaimer to use in compliance with this license.  We thus
+  encourage you to use the following text:
+
+   """
+    Portions of this software are copyright © &lt;year&gt; The FreeType
+    Project (www.freetype.org).  All rights reserved.
+   """
+
+  Please replace &lt;year&gt; with the value from the FreeType version you
+  actually use.
+
+
+Legal Terms
+===========
+
+0. Definitions
+--------------
+
+  Throughout this license,  the terms `package', `FreeType Project',
+  and  `FreeType  archive' refer  to  the  set  of files  originally
+  distributed  by the  authors  (David Turner,  Robert Wilhelm,  and
+  Werner Lemberg) as the `FreeType Project', be they named as alpha,
+  beta or final release.
+
+  `You' refers to  the licensee, or person using  the project, where
+  `using' is a generic term including compiling the project's source
+  code as  well as linking it  to form a  `program' or `executable'.
+  This  program is  referred to  as  `a program  using the  FreeType
+  engine'.
+
+  This  license applies  to all  files distributed  in  the original
+  FreeType  Project,   including  all  source   code,  binaries  and
+  documentation,  unless  otherwise  stated   in  the  file  in  its
+  original, unmodified form as  distributed in the original archive.
+  If you are  unsure whether or not a particular  file is covered by
+  this license, you must contact us to verify this.
+
+  The FreeType  Project is copyright (C) 1996-2000  by David Turner,
+  Robert Wilhelm, and Werner Lemberg.  All rights reserved except as
+  specified below.
+
+1. No Warranty
+--------------
+
+  THE FREETYPE PROJECT  IS PROVIDED `AS IS' WITHOUT  WARRANTY OF ANY
+  KIND, EITHER  EXPRESS OR IMPLIED,  INCLUDING, BUT NOT  LIMITED TO,
+  WARRANTIES  OF  MERCHANTABILITY   AND  FITNESS  FOR  A  PARTICULAR
+  PURPOSE.  IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS
+  BE LIABLE  FOR ANY DAMAGES CAUSED  BY THE USE OR  THE INABILITY TO
+  USE, OF THE FREETYPE PROJECT.
+
+2. Redistribution
+-----------------
+
+  This  license  grants  a  worldwide, royalty-free,  perpetual  and
+  irrevocable right  and license to use,  execute, perform, compile,
+  display,  copy,   create  derivative  works   of,  distribute  and
+  sublicense the  FreeType Project (in  both source and  object code
+  forms)  and  derivative works  thereof  for  any  purpose; and  to
+  authorize others  to exercise  some or all  of the  rights granted
+  herein, subject to the following conditions:
+
+    o Redistribution of  source code  must retain this  license file
+      (`FTL.TXT') unaltered; any  additions, deletions or changes to
+      the original  files must be clearly  indicated in accompanying
+      documentation.   The  copyright   notices  of  the  unaltered,
+      original  files must  be  preserved in  all  copies of  source
+      files.
+
+    o Redistribution in binary form must provide a  disclaimer  that
+      states  that  the software is based in part of the work of the
+      FreeType Team,  in  the  distribution  documentation.  We also
+      encourage you to put an URL to the FreeType web page  in  your
+      documentation, though this isn't mandatory.
+
+  These conditions  apply to any  software derived from or  based on
+  the FreeType Project,  not just the unmodified files.   If you use
+  our work, you  must acknowledge us.  However, no  fee need be paid
+  to us.
+
+3. Advertising
+--------------
+
+  Neither the  FreeType authors and  contributors nor you  shall use
+  the name of the  other for commercial, advertising, or promotional
+  purposes without specific prior written permission.
+
+  We suggest,  but do not require, that  you use one or  more of the
+  following phrases to refer  to this software in your documentation
+  or advertising  materials: `FreeType Project',  `FreeType Engine',
+  `FreeType library', or `FreeType Distribution'.
+
+  As  you have  not signed  this license,  you are  not  required to
+  accept  it.   However,  as  the FreeType  Project  is  copyrighted
+  material, only  this license, or  another one contracted  with the
+  authors, grants you  the right to use, distribute,  and modify it.
+  Therefore,  by  using,  distributing,  or modifying  the  FreeType
+  Project, you indicate that you understand and accept all the terms
+  of this license.
+
+4. Contacts
+-----------
+
+  There are two mailing lists related to FreeType:
+
+    o freetype@nongnu.org
+
+      Discusses general use and applications of FreeType, as well as
+      future and  wanted additions to the  library and distribution.
+      If  you are looking  for support,  start in  this list  if you
+      haven't found anything to help you in the documentation.
+
+    o freetype-devel@nongnu.org
+
+      Discusses bugs,  as well  as engine internals,  design issues,
+      specific licenses, porting, etc.
+
+  Our home page can be found at
+
+    https://www.freetype.org
+-------------------------------------------------------------------
+COPYRIGHT AND PERMISSION NOTICE (ICU 58 and later)
+
+Copyright © 1991-2020 Unicode, Inc. All rights reserved.
+Distributed under the Terms of Use in https://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Unicode data files and any associated documentation
+(the "Data Files") or Unicode software and any associated documentation
+(the "Software") to deal in the Data Files or Software
+without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, and/or sell copies of
+the Data Files or Software, and to permit persons to whom the Data Files
+or Software are furnished to do so, provided that either
+(a) this copyright and permission notice appear with all copies
+of the Data Files or Software, or
+(b) this copyright and permission notice appear in associated
+Documentation.
+
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
+NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
+DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in these Data Files or Software without prior
+written authorization of the copyright holder.
+-------------------------------------------------------------------
+The 'UnicodeData-9.0.0.txt' file is from the Unicode Character Database.
+It is available at http://www.unicode.org/Public/zipped/9.0.0/UCD.zip and
+is made available under the following license by Unicode, Inc:
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright © 1991-2016 Unicode, Inc. All rights reserved.
+Distributed under the Terms of Use in
+http://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Unicode data files and any associated documentation
+(the "Data Files") or Unicode software and any associated documentation
+(the "Software") to deal in the Data Files or Software
+without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, and/or sell copies of
+the Data Files or Software, and to permit persons to whom the Data Files
+or Software are furnished to do so, provided that
+(a) this copyright and permission notice appear with all copies
+of the Data Files or Software,
+(b) this copyright and permission notice appear in associated
+documentation, and
+(c) there is clear notice in each modified Data File or in the Software
+as well as in the documentation associated with the Data File(s) or
+Software that the data or software has been modified.
+
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
+NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
+DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in these Data Files or Software without prior
+written authorization of the copyright holder.
+-------------------------------------------------------------------
+SGI FREE SOFTWARE LICENSE B
+(Version 2.0, Sept. 18, 2008)
+
+Copyright (C) [dates of first publication] Silicon Graphics, Inc. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice including the dates of first publication and either this permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Silicon Graphics, Inc. shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Silicon Graphics, Inc.
+-------------------------------------------------------------------
+Copyright (c) 2013  Julien Pommier ( pommier@modartt.com )
+
+Based on original fortran 77 code from FFTPACKv4 from NETLIB,
+authored by Dr Paul Swarztrauber of NCAR, in 1985.
+
+As confirmed by the NCAR fftpack software curators, the following
+FFTPACKv5 license applies to FFTPACKv4 sources. My changes are
+released under the same terms.
+
+FFTPACK license:
+
+http://www.cisl.ucar.edu/css/software/fftpack5/ftpk.html
+
+Copyright (c) 2004 the University Corporation for Atmospheric
+Research ("UCAR"). All rights reserved. Developed by NCAR's
+Computational and Information Systems Laboratory, UCAR,
+www.cisl.ucar.edu.
+
+Redistribution and use of the Software in source and binary forms,
+with or without modification, is permitted provided that the
+following conditions are met:
+
+- Neither the names of NCAR's Computational and Information Systems
+Laboratory, the University Corporation for Atmospheric Research,
+nor the names of its sponsors or contributors may be used to
+endorse or promote products derived from this Software without
+specific prior written permission.
+
+- Redistributions of source code must retain the above copyright
+notices, this list of conditions, and the disclaimer below.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions, and the disclaimer below in the
+documentation and/or other materials provided with the
+distribution.
+
+THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+-------------------------------------------------------------------
+APPLE PUBLIC SOURCE LICENSE
+Version 2.0 -  August 6, 2003
+
+Please read this License carefully before downloading this software.  By downloading or using this software, you are agreeing to be bound by the terms of this License.  If you do not or cannot agree to the terms of this License, please do not download or use the software.
+
+Apple Note:  In January 2007, Apple changed its corporate name from "Apple Computer, Inc." to "Apple Inc."  This change has been reflected below and copyright years updated, but no other changes have been made to the APSL 2.0.
+
+1.	General; Definitions.  This License applies to any program or other work which Apple Inc. ("Apple") makes publicly available and which contains a notice placed by Apple identifying such program or work as "Original Code" and stating that it is subject to the terms of this Apple Public Source License version 2.0 ("License").  As used in this License:
+
+1.1	 "Applicable Patent Rights" mean:  (a) in the case where Apple is the grantor of rights, (i) claims of patents that are now or hereafter acquired, owned by or assigned to Apple and (ii) that cover subject matter contained in the Original Code, but only to the extent necessary to use, reproduce and/or distribute the Original Code without infringement; and (b) in the case where You are the grantor of rights, (i) claims of patents that are now or hereafter acquired, owned by or assigned to You and (ii) that cover subject matter in Your Modifications, taken alone or in combination with Original Code.
+
+1.2	"Contributor" means any person or entity that creates or contributes to the creation of Modifications.
+
+1.3	 "Covered Code" means the Original Code, Modifications, the combination of Original Code and any Modifications, and/or any respective portions thereof.
+
+1.4	"Externally Deploy" means: (a) to sublicense, distribute or otherwise make Covered Code available, directly or indirectly, to anyone other than You; and/or (b) to use Covered Code, alone or as part of a Larger Work, in any way to provide a service, including but not limited to delivery of content, through electronic communication with a client other than You.
+
+1.5	"Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License.
+
+1.6	"Modifications" mean any addition to, deletion from, and/or change to, the substance and/or structure of the Original Code, any previous Modifications, the combination of Original Code and any previous Modifications, and/or any respective portions thereof.  When code is released as a series of files, a Modification is:  (a) any addition to or deletion from the contents of a file containing Covered Code; and/or (b) any new file or other representation of computer program statements that contains any part of Covered Code.
+
+1.7	"Original Code" means (a) the Source Code of a program or other work as originally made available by Apple under this License, including the Source Code of any updates or upgrades to such programs or works made available by Apple under this License, and that has been expressly identified by Apple as such in the header file(s) of such work; and (b) the object code compiled from such Source Code and originally made available by Apple under this License
+
+1.8	"Source Code" means the human readable form of a program or other work that is suitable for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an executable (object code).
+
+1.9	"You" or "Your" means an individual or a legal entity exercising rights under this License.  For legal entities, "You" or "Your" includes any entity which controls, is controlled by, or is under common control with, You, where "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such entity.
+
+2.	Permitted Uses; Conditions & Restrictions.   Subject to the terms and conditions of this License, Apple hereby grants You, effective on the date You accept this License and download the Original Code, a world-wide, royalty-free, non-exclusive license, to the extent of Apple's Applicable Patent Rights and copyrights covering the Original Code, to do the following:
+
+2.1	Unmodified Code.  You may use, reproduce, display, perform, internally distribute within Your organization, and Externally Deploy verbatim, unmodified copies of the Original Code, for commercial or non-commercial purposes, provided that in each instance:
+
+(a)	You must retain and reproduce in all copies of Original Code the copyright and other proprietary notices and disclaimers of Apple as they appear in the Original Code, and keep intact all notices in the Original Code that refer to this License; and
+
+(b) 	You must include a copy of this License with every copy of Source Code of Covered Code and documentation You distribute or Externally Deploy, and You may not offer or impose any terms on such Source Code that alter or restrict this License or the recipients' rights hereunder, except as permitted under Section 6.
+
+2.2	Modified Code.  You may modify Covered Code and use, reproduce, display, perform, internally distribute within Your organization, and Externally Deploy Your Modifications and Covered Code, for commercial or non-commercial purposes, provided that in each instance You also meet all of these conditions:
+
+(a)	You must satisfy all the conditions of Section 2.1 with respect to the Source Code of the Covered Code;
+
+(b)	You must duplicate, to the extent it does not already exist, the notice in Exhibit A in each file of the Source Code of all Your Modifications, and cause the modified files to carry prominent notices stating that You changed the files and the date of any change; and
+
+(c)	If You Externally Deploy Your Modifications, You must make Source Code of all Your Externally Deployed Modifications either available to those to whom You have Externally Deployed Your Modifications, or publicly available.  Source Code of Your Externally Deployed Modifications must be released under the terms set forth in this License, including the license grants set forth in Section 3 below, for as long as you Externally Deploy the Covered Code or twelve (12) months from the date of initial External Deployment, whichever is longer. You should preferably distribute the Source Code of Your Externally Deployed Modifications electronically (e.g. download from a web site).
+
+2.3	Distribution of Executable Versions.  In addition, if You Externally Deploy Covered Code (Original Code and/or Modifications) in object code, executable form only, You must include a prominent notice, in the code itself as well as in related documentation, stating that Source Code of the Covered Code is available under the terms of this License with information on how and where to obtain such Source Code.
+
+2.4	Third Party Rights.  You expressly acknowledge and agree that although Apple and each Contributor grants the licenses to their respective portions of the Covered Code set forth herein, no assurances are provided by Apple or any Contributor that the Covered Code does not infringe the patent or other intellectual property rights of any other entity. Apple and each Contributor disclaim any liability to You for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, You hereby assume sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow You to distribute the Covered Code, it is Your responsibility to acquire that license before distributing the Covered Code.
+
+3.	Your Grants.  In consideration of, and as a condition to, the licenses granted to You under this License, You hereby grant to any person or entity receiving or distributing Covered Code under this License a non-exclusive, royalty-free, perpetual, irrevocable license, under Your Applicable Patent Rights and other intellectual property rights (other than patent) owned or controlled by You, to use, reproduce, display, perform, modify, sublicense, distribute and Externally Deploy Your Modifications of the same scope and extent as Apple's licenses under Sections 2.1 and 2.2 above.
+
+4.	Larger Works.  You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product.  In each such instance, You must make sure the requirements of this License are fulfilled for the Covered Code or any portion thereof.
+
+5.	Limitations on Patent License.   Except as expressly stated in Section 2, no other patent rights, express or implied, are granted by Apple herein.  Modifications and/or Larger Works may require additional patent licenses from Apple which Apple may grant in its sole discretion.
+
+6.	Additional Terms.  You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations and/or other rights consistent with the scope of the license granted herein ("Additional Terms") to one or more recipients of Covered Code. However, You may do so only on Your own behalf and as Your sole responsibility, and not on behalf of Apple or any Contributor. You must obtain the recipient's agreement that any such Additional Terms are offered by You alone, and You hereby agree to indemnify, defend and hold Apple and every Contributor harmless for any liability incurred by or claims asserted against Apple or such Contributor by reason of any such Additional Terms.
+
+7.	Versions of the License.  Apple may publish revised and/or new versions of this License from time to time.  Each version will be given a distinguishing version number.  Once Original Code has been published under a particular version of this License, You may continue to use it under the terms of that version. You may also choose to use such Original Code under the terms of any subsequent version of this License published by Apple.  No one other than Apple has the right to modify the terms applicable to Covered Code created under this License.
+
+8.	NO WARRANTY OR SUPPORT.  The Covered Code may contain in whole or in part pre-release, untested, or not fully tested works.  The Covered Code may contain errors that could cause failures or loss of data, and may be incomplete or contain inaccuracies.  You expressly acknowledge and agree that use of the Covered Code, or any portion thereof, is at Your sole and entire risk.  THE COVERED CODE IS PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS, THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED.  NO ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY.  You acknowledge that the Covered Code is not intended for use in the operation of nuclear facilities, aircraft navigation, communication systems, or air traffic control machines in which case the failure of the Covered Code could lead to death, personal injury, or severe physical or environmental damage.
+
+9.	LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY TO YOU. In no event shall Apple's total liability to You for all damages (other than as may be required by applicable law) under this License exceed the amount of fifty dollars ($50.00).
+
+10.	Trademarks.  This License does not grant any rights to use the trademarks or trade names  "Apple", "Mac", "Mac OS", "QuickTime", "QuickTime Streaming Server" or any other trademarks, service marks, logos or trade names belonging to Apple (collectively "Apple Marks") or to any trademark, service mark, logo or trade name belonging to any Contributor.  You agree not to use any Apple Marks in or as part of the name of products derived from the Original Code or to endorse or promote products derived from the Original Code other than as expressly permitted by and in strict compliance at all times with Apple's third party trademark usage guidelines which are posted at http://www.apple.com/legal/guidelinesfor3rdparties.html.
+
+11.	Ownership. Subject to the licenses granted under this License, each Contributor retains all rights, title and interest in and to any Modifications made by such Contributor.  Apple retains all rights, title and interest in and to the Original Code and any Modifications made by or on behalf of Apple ("Apple Modifications"), and such Apple Modifications will not be automatically subject to this License.  Apple may, at its sole discretion, choose to license such Apple Modifications under this License, or on different terms from those contained in this License or may choose not to license them at all.
+
+12.	Termination.
+
+12.1	Termination.  This License and the rights granted hereunder will terminate:
+
+(a)	automatically without notice from Apple if You fail to comply with any term(s) of this License and fail to cure such breach within 30 days of becoming aware of such breach;
+(b)	immediately in the event of the circumstances described in Section 13.5(b); or
+(c)	automatically without notice from Apple if You, at any time during the term of this License, commence an action for patent infringement against Apple; provided that Apple did not first commence an action for patent infringement against You in that instance.
+
+12.2	Effect of Termination.  Upon termination, You agree to immediately stop any further use, reproduction, modification, sublicensing and distribution of the Covered Code.  All sublicenses to the Covered Code which have been properly granted prior to termination shall survive any termination of this License.  Provisions which, by their nature, should remain in effect beyond the termination of this License shall survive, including but not limited to Sections 3, 5, 8, 9, 10, 11, 12.2 and 13.  No party will be liable to any other for compensation, indemnity or damages of any sort solely as a result of terminating this License in accordance with its terms, and termination of this License will be without prejudice to any other right or remedy of any party.
+
+13. 	Miscellaneous.
+
+13.1	Government End Users.   The Covered Code is a "commercial item" as defined in FAR 2.101.  Government software and technical data rights in the Covered Code include only those rights customarily provided to the public as defined in this License. This customary commercial license in technical data and software is provided in accordance with FAR 12.211 (Technical Data) and 12.212 (Computer Software) and, for Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- Commercial Items) and 227.7202-3 (Rights in Commercial Computer Software or Computer Software Documentation).  Accordingly, all U.S. Government End Users acquire Covered Code with only those rights set forth herein.
+
+13.2	Relationship of Parties.  This License will not be construed as creating an agency, partnership, joint venture or any other form of legal association between or among You, Apple or any Contributor, and You will not represent to the contrary, whether expressly, by implication, appearance or otherwise.
+
+13.3	Independent Development.   Nothing in this License will impair Apple's right to acquire, license, develop, have others develop for it, market and/or distribute technology or products that perform the same or similar functions as, or otherwise compete with, Modifications, Larger Works, technology or products that You may develop, produce, market or distribute.
+
+13.4	Waiver; Construction.  Failure by Apple or any Contributor to enforce any provision of this License will not be deemed a waiver of future enforcement of that or any other provision.  Any law or regulation which provides that the language of a contract shall be construed against the drafter will not apply to this License.
+
+13.5	Severability.  (a) If for any reason a court of competent jurisdiction finds any provision of this License, or portion thereof, to be unenforceable, that provision of the License will be enforced to the maximum extent permissible so as to effect the economic benefits and intent of the parties, and the remainder of this License will continue in full force and effect.  (b) Notwithstanding the foregoing, if applicable law prohibits or restricts You from fully and/or specifically complying with Sections 2 and/or 3 or prevents the enforceability of either of those Sections, this License will immediately terminate and You must immediately discontinue any use of the Covered Code and destroy all copies of it that are in your possession or control.
+
+13.6	Dispute Resolution.  Any litigation or other dispute resolution between You and Apple relating to this License shall take place in the Northern District of California, and You and Apple hereby consent to the personal jurisdiction of, and venue in, the state and federal courts within that District with respect to this License. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded.
+
+13.7	Entire Agreement; Governing Law.  This License constitutes the entire agreement between the parties with respect to the subject matter hereof.  This License shall be governed by the laws of the United States and the State of California, except that body of California law concerning conflicts of law.
+
+Where You are located in the province of Quebec, Canada, the following clause applies:  The parties hereby confirm that they have requested that this License and all related documents be drafted in English.  Les parties ont exigé que le présent contrat et tous les documents connexes soient rédigés en anglais.
+
+EXHIBIT A.
+
+"Portions Copyright (c) 1999-2007 Apple Inc.  All Rights Reserved.
+
+This file contains Original Code and/or Modifications of Original Code as defined in and that are subject to the Apple Public Source License Version 2.0 (the 'License').  You may not use this file except in compliance with the License.  Please obtain a copy of the License at http://www.opensource.apple.com/apsl/ and read it before using this file.
+
+The Original Code and all software distributed under the License are distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.  Please see the License for the specific language governing rights and limitations under the License."
+-------------------------------------------------------------------
+MOZILLA PUBLIC LICENSE
+Version 1.1
+
+---------------
+
+1. Definitions.
+
+1.0.1. "Commercial Use" means distribution or otherwise making the
+Covered Code available to a third party.
+
+1.1. "Contributor" means each entity that creates or contributes to
+the creation of Modifications.
+
+1.2. "Contributor Version" means the combination of the Original
+Code, prior Modifications used by a Contributor, and the Modifications
+made by that particular Contributor.
+
+1.3. "Covered Code" means the Original Code or Modifications or the
+combination of the Original Code and Modifications, in each case
+including portions thereof.
+
+1.4. "Electronic Distribution Mechanism" means a mechanism generally
+accepted in the software development community for the electronic
+transfer of data.
+
+1.5. "Executable" means Covered Code in any form other than Source
+Code.
+
+1.6. "Initial Developer" means the individual or entity identified
+as the Initial Developer in the Source Code notice required by Exhibit
+A.
+
+1.7. "Larger Work" means a work which combines Covered Code or
+portions thereof with code not governed by the terms of this License.
+
+1.8. "License" means this document.
+
+1.8.1. "Licensable" means having the right to grant, to the maximum
+extent possible, whether at the time of the initial grant or
+subsequently acquired, any and all of the rights conveyed herein.
+
+1.9. "Modifications" means any addition to or deletion from the
+substance or structure of either the Original Code or any previous
+Modifications. When Covered Code is released as a series of files, a
+Modification is:
+A. Any addition to or deletion from the contents of a file
+containing Original Code or previous Modifications.
+
+B. Any new file that contains any part of the Original Code or
+previous Modifications.
+
+1.10. "Original Code" means Source Code of computer software code
+which is described in the Source Code notice required by Exhibit A as
+Original Code, and which, at the time of its release under this
+License is not already Covered Code governed by this License.
+
+1.10.1. "Patent Claims" means any patent claim(s), now owned or
+hereafter acquired, including without limitation,  method, process,
+and apparatus claims, in any patent Licensable by grantor.
+
+1.11. "Source Code" means the preferred form of the Covered Code for
+making modifications to it, including all modules it contains, plus
+any associated interface definition files, scripts used to control
+compilation and installation of an Executable, or source code
+differential comparisons against either the Original Code or another
+well known, available Covered Code of the Contributor's choice. The
+Source Code can be in a compressed or archival form, provided the
+appropriate decompression or de-archiving software is widely available
+for no charge.
+
+1.12. "You" (or "Your")  means an individual or a legal entity
+exercising rights under, and complying with all of the terms of, this
+License or a future version of this License issued under Section 6.1.
+For legal entities, "You" includes any entity which controls, is
+controlled by, or is under common control with You. For purposes of
+this definition, "control" means (a) the power, direct or indirect,
+to cause the direction or management of such entity, whether by
+contract or otherwise, or (b) ownership of more than fifty percent
+(50%) of the outstanding shares or beneficial ownership of such
+entity.
+
+2. Source Code License.
+
+2.1. The Initial Developer Grant.
+The Initial Developer hereby grants You a world-wide, royalty-free,
+non-exclusive license, subject to third party intellectual property
+claims:
+(a)  under intellectual property rights (other than patent or
+trademark) Licensable by Initial Developer to use, reproduce,
+modify, display, perform, sublicense and distribute the Original
+Code (or portions thereof) with or without Modifications, and/or
+as part of a Larger Work; and
+
+(b) under Patents Claims infringed by the making, using or
+selling of Original Code, to make, have made, use, practice,
+sell, and offer for sale, and/or otherwise dispose of the
+Original Code (or portions thereof).
+
+(c) the licenses granted in this Section 2.1(a) and (b) are
+effective on the date Initial Developer first distributes
+Original Code under the terms of this License.
+
+(d) Notwithstanding Section 2.1(b) above, no patent license is
+granted: 1) for code that You delete from the Original Code; 2)
+separate from the Original Code;  or 3) for infringements caused
+by: i) the modification of the Original Code or ii) the
+combination of the Original Code with other software or devices.
+
+2.2. Contributor Grant.
+Subject to third party intellectual property claims, each Contributor
+hereby grants You a world-wide, royalty-free, non-exclusive license
+
+(a)  under intellectual property rights (other than patent or
+trademark) Licensable by Contributor, to use, reproduce, modify,
+display, perform, sublicense and distribute the Modifications
+created by such Contributor (or portions thereof) either on an
+unmodified basis, with other Modifications, as Covered Code
+and/or as part of a Larger Work; and
+
+(b) under Patent Claims infringed by the making, using, or
+selling of  Modifications made by that Contributor either alone
+and/or in combination with its Contributor Version (or portions
+of such combination), to make, use, sell, offer for sale, have
+made, and/or otherwise dispose of: 1) Modifications made by that
+Contributor (or portions thereof); and 2) the combination of
+Modifications made by that Contributor with its Contributor
+Version (or portions of such combination).
+
+(c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+effective on the date Contributor first makes Commercial Use of
+the Covered Code.
+
+(d)    Notwithstanding Section 2.2(b) above, no patent license is
+granted: 1) for any code that Contributor has deleted from the
+Contributor Version; 2)  separate from the Contributor Version;
+3)  for infringements caused by: i) third party modifications of
+Contributor Version or ii)  the combination of Modifications made
+by that Contributor with other software  (except as part of the
+Contributor Version) or other devices; or 4) under Patent Claims
+infringed by Covered Code in the absence of Modifications made by
+that Contributor.
+
+3. Distribution Obligations.
+
+3.1. Application of License.
+The Modifications which You create or to which You contribute are
+governed by the terms of this License, including without limitation
+Section 2.2. The Source Code version of Covered Code may be
+distributed only under the terms of this License or a future version
+of this License released under Section 6.1, and You must include a
+copy of this License with every copy of the Source Code You
+distribute. You may not offer or impose any terms on any Source Code
+version that alters or restricts the applicable version of this
+License or the recipients' rights hereunder. However, You may include
+an additional document offering the additional rights described in
+Section 3.5.
+
+3.2. Availability of Source Code.
+Any Modification which You create or to which You contribute must be
+made available in Source Code form under the terms of this License
+either on the same media as an Executable version or via an accepted
+Electronic Distribution Mechanism to anyone to whom you made an
+Executable version available; and if made available via Electronic
+Distribution Mechanism, must remain available for at least twelve (12)
+months after the date it initially became available, or at least six
+(6) months after a subsequent version of that particular Modification
+has been made available to such recipients. You are responsible for
+ensuring that the Source Code version remains available even if the
+Electronic Distribution Mechanism is maintained by a third party.
+
+3.3. Description of Modifications.
+You must cause all Covered Code to which You contribute to contain a
+file documenting the changes You made to create that Covered Code and
+the date of any change. You must include a prominent statement that
+the Modification is derived, directly or indirectly, from Original
+Code provided by the Initial Developer and including the name of the
+Initial Developer in (a) the Source Code, and (b) in any notice in an
+Executable version or related documentation in which You describe the
+origin or ownership of the Covered Code.
+
+3.4. Intellectual Property Matters
+(a) Third Party Claims.
+If Contributor has knowledge that a license under a third party's
+intellectual property rights is required to exercise the rights
+granted by such Contributor under Sections 2.1 or 2.2,
+Contributor must include a text file with the Source Code
+distribution titled "LEGAL" which describes the claim and the
+party making the claim in sufficient detail that a recipient will
+know whom to contact. If Contributor obtains such knowledge after
+the Modification is made available as described in Section 3.2,
+Contributor shall promptly modify the LEGAL file in all copies
+Contributor makes available thereafter and shall take other steps
+(such as notifying appropriate mailing lists or newsgroups)
+reasonably calculated to inform those who received the Covered
+Code that new knowledge has been obtained.
+
+(b) Contributor APIs.
+If Contributor's Modifications include an application programming
+interface and Contributor has knowledge of patent licenses which
+are reasonably necessary to implement that API, Contributor must
+also include this information in the LEGAL file.
+
+(c)    Representations.
+Contributor represents that, except as disclosed pursuant to
+Section 3.4(a) above, Contributor believes that Contributor's
+Modifications are Contributor's original creation(s) and/or
+Contributor has sufficient rights to grant the rights conveyed by
+this License.
+
+3.5. Required Notices.
+You must duplicate the notice in Exhibit A in each file of the Source
+Code.  If it is not possible to put such notice in a particular Source
+Code file due to its structure, then You must include such notice in a
+location (such as a relevant directory) where a user would be likely
+to look for such a notice.  If You created one or more Modification(s)
+You may add your name as a Contributor to the notice described in
+Exhibit A.  You must also duplicate this License in any documentation
+for the Source Code where You describe recipients' rights or ownership
+rights relating to Covered Code.  You may choose to offer, and to
+charge a fee for, warranty, support, indemnity or liability
+obligations to one or more recipients of Covered Code. However, You
+may do so only on Your own behalf, and not on behalf of the Initial
+Developer or any Contributor. You must make it absolutely clear than
+any such warranty, support, indemnity or liability obligation is
+offered by You alone, and You hereby agree to indemnify the Initial
+Developer and every Contributor for any liability incurred by the
+Initial Developer or such Contributor as a result of warranty,
+support, indemnity or liability terms You offer.
+
+3.6. Distribution of Executable Versions.
+You may distribute Covered Code in Executable form only if the
+requirements of Section 3.1-3.5 have been met for that Covered Code,
+and if You include a notice stating that the Source Code version of
+the Covered Code is available under the terms of this License,
+including a description of how and where You have fulfilled the
+obligations of Section 3.2. The notice must be conspicuously included
+in any notice in an Executable version, related documentation or
+collateral in which You describe recipients' rights relating to the
+Covered Code. You may distribute the Executable version of Covered
+Code or ownership rights under a license of Your choice, which may
+contain terms different from this License, provided that You are in
+compliance with the terms of this License and that the license for the
+Executable version does not attempt to limit or alter the recipient's
+rights in the Source Code version from the rights set forth in this
+License. If You distribute the Executable version under a different
+license You must make it absolutely clear that any terms which differ
+from this License are offered by You alone, not by the Initial
+Developer or any Contributor. You hereby agree to indemnify the
+Initial Developer and every Contributor for any liability incurred by
+the Initial Developer or such Contributor as a result of any such
+terms You offer.
+
+3.7. Larger Works.
+You may create a Larger Work by combining Covered Code with other code
+not governed by the terms of this License and distribute the Larger
+Work as a single product. In such a case, You must make sure the
+requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Code due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description
+must be included in the LEGAL file described in Section 3.4 and must
+be included with all distributions of the Source Code. Except to the
+extent prohibited by statute or regulation, such description must be
+sufficiently detailed for a recipient of ordinary skill to be able to
+understand it.
+
+5. Application of this License.
+
+This License applies to code to which the Initial Developer has
+attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+6.1. New Versions.
+Netscape Communications Corporation ("Netscape") may publish revised
+and/or new versions of the License from time to time. Each version
+will be given a distinguishing version number.
+
+6.2. Effect of New Versions.
+Once Covered Code has been published under a particular version of the
+License, You may always continue to use it under the terms of that
+version. You may also choose to use such Covered Code under the terms
+of any subsequent version of the License published by Netscape. No one
+other than Netscape has the right to modify the terms applicable to
+Covered Code created under this License.
+
+6.3. Derivative Works.
+If You create or use a modified version of this License (which you may
+only do in order to apply it to code which is not already Covered Code
+governed by this License), You must (a) rename Your license so that
+the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+"MPL", "NPL" or any confusingly similar phrase do not appear in your
+license (except to note that your license differs from this License)
+and (b) otherwise make it clear that Your version of the license
+contains terms which differ from the Mozilla Public License and
+Netscape Public License. (Filling in the name of the Initial
+Developer, Original Code or Contributor in the notice described in
+Exhibit A shall not of themselves be deemed to be modifications of
+this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+8.1.  This License and the rights granted hereunder will terminate
+automatically if You fail to comply with terms herein and fail to cure
+such breach within 30 days of becoming aware of the breach. All
+sublicenses to the Covered Code which are properly granted shall
+survive any termination of this License. Provisions which, by their
+nature, must remain in effect beyond the termination of this License
+shall survive.
+
+8.2.  If You initiate litigation by asserting a patent infringement
+claim (excluding declatory judgment actions) against Initial Developer
+or a Contributor (the Initial Developer or Contributor against whom
+You file such action is referred to as "Participant")  alleging that:
+
+(a)  such Participant's Contributor Version directly or indirectly
+infringes any patent, then any and all rights granted by such
+Participant to You under Sections 2.1 and/or 2.2 of this License
+shall, upon 60 days notice from Participant terminate prospectively,
+unless if within 60 days after receipt of notice You either: (i)
+agree in writing to pay Participant a mutually agreeable reasonable
+royalty for Your past and future use of Modifications made by such
+Participant, or (ii) withdraw Your litigation claim with respect to
+the Contributor Version against such Participant.  If within 60 days
+of notice, a reasonable royalty and payment arrangement are not
+mutually agreed upon in writing by the parties or the litigation claim
+is not withdrawn, the rights granted by Participant to You under
+Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+the 60 day notice period specified above.
+
+(b)  any software, hardware, or device, other than such Participant's
+Contributor Version, directly or indirectly infringes any patent, then
+any rights granted to You by such Participant under Sections 2.1(b)
+and 2.2(b) are revoked effective as of the date You first made, used,
+sold, distributed, or had made, Modifications made by that
+Participant.
+
+8.3.  If You assert a patent infringement claim against Participant
+alleging that such Participant's Contributor Version directly or
+indirectly infringes any patent where such claim is resolved (such as
+by license or settlement) prior to the initiation of patent
+infringement litigation, then the reasonable value of the licenses
+granted by such Participant under Sections 2.1 or 2.2 shall be taken
+into account in determining the amount or value of any payment or
+license.
+
+8.4.  In the event of termination under Sections 8.1 or 8.2 above,
+all end user license agreements (excluding distributors and resellers)
+which have been validly granted by You or any distributor hereunder
+prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+(INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+The Covered Code is a "commercial item," as that term is defined in
+48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+software" and "commercial computer software documentation," as such
+terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+all U.S. Government End Users acquire Covered Code with only those
+rights set forth herein.
+
+11. MISCELLANEOUS.
+
+This License represents the complete agreement concerning subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. This License shall be governed by
+California law provisions (except to the extent applicable law, if
+any, provides otherwise), excluding its conflict-of-law provisions.
+With respect to disputes in which at least one party is a citizen of,
+or an entity chartered or registered to do business in the United
+States of America, any litigation relating to this License shall be
+subject to the jurisdiction of the Federal Courts of the Northern
+District of California, with venue lying in Santa Clara County,
+California, with the losing party responsible for costs, including
+without limitation, court costs and reasonable attorneys' fees and
+expenses. The application of the United Nations Convention on
+Contracts for the International Sale of Goods is expressly excluded.
+Any law or regulation which provides that the language of a contract
+shall be construed against the drafter shall not apply to this
+License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+As between Initial Developer and the Contributors, each party is
+responsible for claims and damages arising, directly or indirectly,
+out of its utilization of rights under this License and You agree to
+work with Initial Developer and Contributors to distribute such
+responsibility on an equitable basis. Nothing herein is intended or
+shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+Initial Developer may designate portions of the Covered Code as
+"Multiple-Licensed".  "Multiple-Licensed" means that the Initial
+Developer permits you to utilize portions of the Covered Code under
+Your choice of the NPL or the alternative licenses, if any, specified
+by the Initial Developer in the file described in Exhibit A.
+
+EXHIBIT A -Mozilla Public License.
+The contents of this file are subject to the Mozilla Public License Version
+1.1 (the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+for the specific language governing rights and limitations under the
+License.
+
+The Original Code is the Netscape Portable Runtime (NSPR).
+
+The Initial Developer of the Original Code is
+Netscape Communications Corporation.
+Portions created by the Initial Developer are Copyright (C) 1998-2000
+the Initial Developer. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms of
+either the GNU General Public License Version 2 or later (the "GPL"), or
+the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+in which case the provisions of the GPL or the LGPL are applicable instead
+of those above. If you wish to allow use of your version of this file only
+under the terms of either the GPL or the LGPL, and not to allow others to
+use your version of this file under the terms of the MPL, indicate your
+decision by deleting the provisions above and replace them with the notice
+and other provisions required by the GPL or the LGPL. If you do not delete
+the provisions above, a recipient may use your version of this file under
+the terms of any one of the MPL, the GPL or the LGPL.
+
+-------------------------------------------------------------------
+1. ICU License - ICU 1.8.1 to ICU 57.1
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 1995-2016 International Business Machines Corporation and others
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+All trademarks and registered trademarks mentioned herein are the
+property of their respective owners.
+-------------------------------------------------------------------
+2-dim General Purpose FFT (Fast Fourier/Cosine/Sine Transform) Package
+
+Copyright(C) 1997,2001 Takuya OOURA (email: ooura@kurims.kyoto-u.ac.jp).
+You may use, copy, modify this code for any purpose and
+without fee. You may distribute this ORIGINAL package.
+-------------------------------------------------------------------
+ARM_NEON_2_x86_SSE
+
+<pre>created by Victoria Zhislina, the Senior Application Engineer, Intel Corporation,  victoria.zhislina@intel.com
+
+*** Copyright (C) 2012-2020 Intel Corporation.  All rights reserved.
+
+IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+
+By downloading, copying, installing or using the software you agree to this license.
+If you do not agree to this license, do not download, install, copy or use the software.
+
+                             License Agreement
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+ * The name of the copyright holders may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+This software is provided by the copyright holders and contributors &quot;as is&quot; and
+any express or implied warranties, including, but not limited to, the implied
+warranties of merchantability and fitness for a particular purpose are disclaimed.
+In no event shall the Intel Corporation or contributors be liable for any direct,
+indirect, incidental, special, exemplary, or consequential damages
+(including, but not limited to, procurement of substitute goods or services;
+loss of use, data, or profits; or business interruption) however caused
+and on any theory of liability, whether in contract, strict liability,
+or tort (including negligence or otherwise) arising in any way out of
+the use of this software, even if advised of the possibility of such damage.
+</pre>
+
+-------------------------------------------------------------------
+Breakpad, An open-source multi-platform crash reporting system
+
+Copyright (c) 2006, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+&quot;AS IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 1996 - 2011, Daniel Stenberg, &lt;daniel@haxx.se&gt;.
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software for any purpose
+with or without fee is hereby granted, provided that the above copyright
+notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
+NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization of the copyright holder.
+
+
+Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+
+@APPLE_LICENSE_HEADER_START@
+
+This file contains Original Code and/or Modifications of Original Code
+as defined in and that are subject to the Apple Public Source License
+Version 2.0 (the &#x27;License&#x27;). You may not use this file except in
+compliance with the License. Please obtain a copy of the License at
+http://www.opensource.apple.com/apsl/ and read it before using this
+file.
+
+The Original Code and all software distributed under the License are
+distributed on an &#x27;AS IS&#x27; basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+Please see the License for the specific language governing rights and
+limitations under the License.
+
+@APPLE_LICENSE_HEADER_END@
+
+
+Copyright 2007-2008 Google Inc.
+
+Licensed under the Apache License, Version 2.0 (the &quot;License&quot;); you may not
+use this file except in compliance with the License.  You may obtain a copy
+of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an &quot;AS IS&quot; BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+License for the specific language governing permissions and limitations under
+the License.
+-------------------------------------------------------------------
+harfbuzz-ng
+
+HarfBuzz is licensed under the so-called &quot;Old MIT&quot; license.  Details follow.
+For parts of HarfBuzz that are licensed under different licenses see individual
+files names COPYING in subdirectories where applicable.
+
+Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020  Google, Inc.
+Copyright © 2018,2019,2020  Ebrahim Byagowi
+Copyright © 2019,2020  Facebook, Inc.
+Copyright © 2012  Mozilla Foundation
+Copyright © 2011  Codethink Limited
+Copyright © 2008,2010  Nokia Corporation and/or its subsidiary(-ies)
+Copyright © 2009  Keith Stribley
+Copyright © 2009  Martin Hosken and SIL International
+Copyright © 2007  Chris Wilson
+Copyright © 2005,2006,2020,2021  Behdad Esfahbod
+Copyright © 2005  David Turner
+Copyright © 2004,2007,2008,2009,2010  Red Hat, Inc.
+Copyright © 1998-2004  David Turner and Werner Lemberg
+
+For full copyright notices consult the individual files in the package.
+
+
+Permission is hereby granted, without written agreement and without
+license or royalty fees, to use, copy, modify, and distribute this
+software and its documentation for any purpose, provided that the
+above copyright notice and the following two paragraphs appear in
+all copies of this software.
+
+IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ON AN &quot;AS IS&quot; BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+-------------------------------------------------------------------
+icu
+
+UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
+
+See Terms of Use <https://www.unicode.org/copyright.html>
+for definitions of Unicode Inc.’s Data Files and Software.
+
+NOTICE TO USER: Carefully read the following legal agreement.
+BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S
+DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"),
+YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
+TERMS AND CONDITIONS OF THIS AGREEMENT.
+IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE
+THE DATA FILES OR SOFTWARE.
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright © 1991-2022 Unicode, Inc. All rights reserved.
+Distributed under the Terms of Use in https://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Unicode data files and any associated documentation
+(the "Data Files") or Unicode software and any associated documentation
+(the "Software") to deal in the Data Files or Software
+without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, and/or sell copies of
+the Data Files or Software, and to permit persons to whom the Data Files
+or Software are furnished to do so, provided that either
+(a) this copyright and permission notice appear with all copies
+of the Data Files or Software, or
+(b) this copyright and permission notice appear in associated
+Documentation.
+
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
+NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
+DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in these Data Files or Software without prior
+written authorization of the copyright holder.
+
+----------------------------------------------------------------------
+
+Third-Party Software Licenses
+
+This section contains third-party software notices and/or additional
+terms for licensed third-party software components included within ICU
+libraries.
+
+----------------------------------------------------------------------
+
+ICU License - ICU 1.8.1 to ICU 57.1
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 1995-2016 International Business Machines Corporation and others
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+All trademarks and registered trademarks mentioned herein are the
+property of their respective owners.
+
+----------------------------------------------------------------------
+
+Chinese/Japanese Word Break Dictionary Data (cjdict.txt)
+
+ #     The Google Chrome software developed by Google is licensed under
+ # the BSD license. Other software included in this distribution is
+ # provided under other licenses, as set forth below.
+ #
+ #  The BSD License
+ #  http://opensource.org/licenses/bsd-license.php
+ #  Copyright (C) 2006-2008, Google Inc.
+ #
+ #  All rights reserved.
+ #
+ #  Redistribution and use in source and binary forms, with or without
+ # modification, are permitted provided that the following conditions are met:
+ #
+ #  Redistributions of source code must retain the above copyright notice,
+ # this list of conditions and the following disclaimer.
+ #  Redistributions in binary form must reproduce the above
+ # copyright notice, this list of conditions and the following
+ # disclaimer in the documentation and/or other materials provided with
+ # the distribution.
+ #  Neither the name of  Google Inc. nor the names of its
+ # contributors may be used to endorse or promote products derived from
+ # this software without specific prior written permission.
+ #
+ #
+ #  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ #
+ #
+ #  The word list in cjdict.txt are generated by combining three word lists
+ # listed below with further processing for compound word breaking. The
+ # frequency is generated with an iterative training against Google web
+ # corpora.
+ #
+ #  * Libtabe (Chinese)
+ #    - https://sourceforge.net/project/?group_id=1519
+ #    - Its license terms and conditions are shown below.
+ #
+ #  * IPADIC (Japanese)
+ #    - http://chasen.aist-nara.ac.jp/chasen/distribution.html
+ #    - Its license terms and conditions are shown below.
+ #
+ #  ---------COPYING.libtabe ---- BEGIN--------------------
+ #
+ #  /*
+ #   * Copyright (c) 1999 TaBE Project.
+ #   * Copyright (c) 1999 Pai-Hsiang Hsiao.
+ #   * All rights reserved.
+ #   *
+ #   * Redistribution and use in source and binary forms, with or without
+ #   * modification, are permitted provided that the following conditions
+ #   * are met:
+ #   *
+ #   * . Redistributions of source code must retain the above copyright
+ #   *   notice, this list of conditions and the following disclaimer.
+ #   * . Redistributions in binary form must reproduce the above copyright
+ #   *   notice, this list of conditions and the following disclaimer in
+ #   *   the documentation and/or other materials provided with the
+ #   *   distribution.
+ #   * . Neither the name of the TaBE Project nor the names of its
+ #   *   contributors may be used to endorse or promote products derived
+ #   *   from this software without specific prior written permission.
+ #   *
+ #   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ #   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ #   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ #   * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ #   * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ #   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ #   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ #   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ #   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ #   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ #   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ #   * OF THE POSSIBILITY OF SUCH DAMAGE.
+ #   */
+ #
+ #  /*
+ #   * Copyright (c) 1999 Computer Systems and Communication Lab,
+ #   *                    Institute of Information Science, Academia
+ #       *                    Sinica. All rights reserved.
+ #   *
+ #   * Redistribution and use in source and binary forms, with or without
+ #   * modification, are permitted provided that the following conditions
+ #   * are met:
+ #   *
+ #   * . Redistributions of source code must retain the above copyright
+ #   *   notice, this list of conditions and the following disclaimer.
+ #   * . Redistributions in binary form must reproduce the above copyright
+ #   *   notice, this list of conditions and the following disclaimer in
+ #   *   the documentation and/or other materials provided with the
+ #   *   distribution.
+ #   * . Neither the name of the Computer Systems and Communication Lab
+ #   *   nor the names of its contributors may be used to endorse or
+ #   *   promote products derived from this software without specific
+ #   *   prior written permission.
+ #   *
+ #   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ #   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ #   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ #   * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ #   * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ #   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ #   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ #   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ #   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ #   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ #   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ #   * OF THE POSSIBILITY OF SUCH DAMAGE.
+ #   */
+ #
+ #  Copyright 1996 Chih-Hao Tsai @ Beckman Institute,
+ #      University of Illinois
+ #  c-tsai4@uiuc.edu  http://casper.beckman.uiuc.edu/~c-tsai4
+ #
+ #  ---------------COPYING.libtabe-----END--------------------------------
+ #
+ #
+ #  ---------------COPYING.ipadic-----BEGIN-------------------------------
+ #
+ #  Copyright 2000, 2001, 2002, 2003 Nara Institute of Science
+ #  and Technology.  All Rights Reserved.
+ #
+ #  Use, reproduction, and distribution of this software is permitted.
+ #  Any copy of this software, whether in its original form or modified,
+ #  must include both the above copyright notice and the following
+ #  paragraphs.
+ #
+ #  Nara Institute of Science and Technology (NAIST),
+ #  the copyright holders, disclaims all warranties with regard to this
+ #  software, including all implied warranties of merchantability and
+ #  fitness, in no event shall NAIST be liable for
+ #  any special, indirect or consequential damages or any damages
+ #  whatsoever resulting from loss of use, data or profits, whether in an
+ #  action of contract, negligence or other tortuous action, arising out
+ #  of or in connection with the use or performance of this software.
+ #
+ #  A large portion of the dictionary entries
+ #  originate from ICOT Free Software.  The following conditions for ICOT
+ #  Free Software applies to the current dictionary as well.
+ #
+ #  Each User may also freely distribute the Program, whether in its
+ #  original form or modified, to any third party or parties, PROVIDED
+ #  that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear
+ #  on, or be attached to, the Program, which is distributed substantially
+ #  in the same form as set out herein and that such intended
+ #  distribution, if actually made, will neither violate or otherwise
+ #  contravene any of the laws and regulations of the countries having
+ #  jurisdiction over the User or the intended distribution itself.
+ #
+ #  NO WARRANTY
+ #
+ #  The program was produced on an experimental basis in the course of the
+ #  research and development conducted during the project and is provided
+ #  to users as so produced on an experimental basis.  Accordingly, the
+ #  program is provided without any warranty whatsoever, whether express,
+ #  implied, statutory or otherwise.  The term "warranty" used herein
+ #  includes, but is not limited to, any warranty of the quality,
+ #  performance, merchantability and fitness for a particular purpose of
+ #  the program and the nonexistence of any infringement or violation of
+ #  any right of any third party.
+ #
+ #  Each user of the program will agree and understand, and be deemed to
+ #  have agreed and understood, that there is no warranty whatsoever for
+ #  the program and, accordingly, the entire risk arising from or
+ #  otherwise connected with the program is assumed by the user.
+ #
+ #  Therefore, neither ICOT, the copyright holder, or any other
+ #  organization that participated in or was otherwise related to the
+ #  development of the program and their respective officials, directors,
+ #  officers and other employees shall be held liable for any and all
+ #  damages, including, without limitation, general, special, incidental
+ #  and consequential damages, arising out of or otherwise in connection
+ #  with the use or inability to use the program or any product, material
+ #  or result produced or otherwise obtained by using the program,
+ #  regardless of whether they have been advised of, or otherwise had
+ #  knowledge of, the possibility of such damages at any time during the
+ #  project or thereafter.  Each user will be deemed to have agreed to the
+ #  foregoing by his or her commencement of use of the program.  The term
+ #  "use" as used herein includes, but is not limited to, the use,
+ #  modification, copying and distribution of the program and the
+ #  production of secondary products from the program.
+ #
+ #  In the case where the program, whether in its original form or
+ #  modified, was distributed or delivered to or received by a user from
+ #  any person, organization or entity other than ICOT, unless it makes or
+ #  grants independently of ICOT any specific warranty to the user in
+ #  writing, such person, organization or entity, will also be exempted
+ #  from and not be held liable to the user for any such damages as noted
+ #  above as far as the program is concerned.
+ #
+ #  ---------------COPYING.ipadic-----END----------------------------------
+
+----------------------------------------------------------------------
+
+Lao Word Break Dictionary Data (laodict.txt)
+
+ # Copyright (C) 2016 and later: Unicode, Inc. and others.
+ # License & terms of use: http://www.unicode.org/copyright.html
+ # Copyright (c) 2015 International Business Machines Corporation
+ # and others. All Rights Reserved.
+ #
+ # Project: https://github.com/rober42539/lao-dictionary
+ # Dictionary: https://github.com/rober42539/lao-dictionary/laodict.txt
+ # License: https://github.com/rober42539/lao-dictionary/LICENSE.txt
+ #          (copied below)
+ #
+ #	This file is derived from the above dictionary version of Nov 22, 2020
+ #  ----------------------------------------------------------------------
+ #  Copyright (C) 2013 Brian Eugene Wilson, Robert Martin Campbell.
+ #  All rights reserved.
+ #
+ #  Redistribution and use in source and binary forms, with or without
+ #  modification, are permitted provided that the following conditions are met:
+ #
+ #  Redistributions of source code must retain the above copyright notice, this
+ #  list of conditions and the following disclaimer. Redistributions in binary
+ #  form must reproduce the above copyright notice, this list of conditions and
+ #  the following disclaimer in the documentation and/or other materials
+ #  provided with the distribution.
+ #
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ # OF THE POSSIBILITY OF SUCH DAMAGE.
+ #  --------------------------------------------------------------------------
+
+----------------------------------------------------------------------
+
+Burmese Word Break Dictionary Data (burmesedict.txt)
+
+ #  Copyright (c) 2014 International Business Machines Corporation
+ #  and others. All Rights Reserved.
+ #
+ #  This list is part of a project hosted at:
+ #    github.com/kanyawtech/myanmar-karen-word-lists
+ #
+ #  --------------------------------------------------------------------------
+ #  Copyright (c) 2013, LeRoy Benjamin Sharon
+ #  All rights reserved.
+ #
+ #  Redistribution and use in source and binary forms, with or without
+ #  modification, are permitted provided that the following conditions
+ #  are met: Redistributions of source code must retain the above
+ #  copyright notice, this list of conditions and the following
+ #  disclaimer.  Redistributions in binary form must reproduce the
+ #  above copyright notice, this list of conditions and the following
+ #  disclaimer in the documentation and/or other materials provided
+ #  with the distribution.
+ #
+ #    Neither the name Myanmar Karen Word Lists, nor the names of its
+ #    contributors may be used to endorse or promote products derived
+ #    from this software without specific prior written permission.
+ #
+ #  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ #  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ #  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ #  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ #  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+ #  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ #  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ #  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ #  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ #  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ #  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ #  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ #  SUCH DAMAGE.
+ #  --------------------------------------------------------------------------
+
+----------------------------------------------------------------------
+
+Time Zone Database
+
+  ICU uses the public domain data and code derived from Time Zone
+Database for its time zone support. The ownership of the TZ database
+is explained in BCP 175: Procedure for Maintaining the Time Zone
+Database section 7.
+
+ # 7.  Database Ownership
+ #
+ #    The TZ database itself is not an IETF Contribution or an IETF
+ #    document.  Rather it is a pre-existing and regularly updated work
+ #    that is in the public domain, and is intended to remain in the
+ #    public domain.  Therefore, BCPs 78 [RFC5378] and 79 [RFC3979] do
+ #    not apply to the TZ Database or contributions that individuals make
+ #    to it.  Should any claims be made and substantiated against the TZ
+ #    Database, the organization that is providing the IANA
+ #    Considerations defined in this RFC, under the memorandum of
+ #    understanding with the IETF, currently ICANN, may act in accordance
+ #    with all competent court orders.  No ownership claims will be made
+ #    by ICANN or the IETF Trust on the database or the code.  Any person
+ #    making a contribution to the database or code waives all rights to
+ #    future claims in that contribution or in the TZ Database.
+
+----------------------------------------------------------------------
+
+Google double-conversion
+
+Copyright 2006-2011, the V8 project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+
+File: aclocal.m4 (only for ICU4C)
+Section: pkg.m4 - Macros to locate and utilise pkg-config.
+
+
+Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+
+As a special exception to the GNU General Public License, if you
+distribute this file as part of a program that contains a
+configuration script generated by Autoconf, you may include it under
+the same distribution terms that you use for the rest of that
+program.
+
+
+(The condition for the exception is fulfilled because
+ICU4C includes a configuration script generated by Autoconf,
+namely the `configure` script.)
+
+----------------------------------------------------------------------
+
+File: config.guess (only for ICU4C)
+
+
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+AUTOCONF CONFIGURE SCRIPT EXCEPTION
+
+Version 3.0, 18 August 2009
+
+Copyright © 2009 Free Software Foundation, Inc. <http://fsf.org/>
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+This Exception is an additional permission under section 7 of the GNU General
+Public License, version 3 ("GPLv3"). It applies to a given file that bears a
+notice placed by the copyright holder of the file stating that the file is
+governed by GPLv3 along with this Exception.
+
+The purpose of this Exception is to allow distribution of Autoconf&apos;s
+typical output under terms of the recipient&apos;s choice (including
+proprietary).
+
+0. Definitions.   
+"Covered Code" is the source or object code of a version of Autoconf that is a
+covered work under this License.
+
+"Normally Copied Code" for a version of Autoconf means all parts of its
+Covered Code which that version can copy from its code (i.e., not from its
+input file) into its minimally verbose, non-debugging and non-tracing output.
+
+"Ineligible Code" is Covered Code that is not Normally Copied Code.
+
+1. Grant of Additional Permission.   
+You have permission to propagate output of Autoconf, even if such propagation
+would otherwise violate the terms of GPLv3. However, if by modifying Autoconf
+you cause any Ineligible Code of the version you received to become Normally
+Copied Code of your modified version, then you void this Exception for the
+resulting covered work. If you convey that resulting covered work, you must
+remove this Exception in accordance with the second paragraph of Section 7 of
+GPLv3.
+
+2. No Weakening of Autoconf Copyleft.   
+The availability of this Exception does not imply any general presumption that
+third-party software is unaffected by the copyleft requirements of the license
+of Autoconf.
+
+
+(The condition for the exception is fulfilled because
+ICU4C includes a configuration script generated by Autoconf,
+namely the `configure` script.)
+
+----------------------------------------------------------------------
+
+File: install-sh (only for ICU4C)
+
+
+Copyright 1991 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission.  M.I.T. makes no representations about the
+suitability of this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+-------------------------------------------------------------------
+libcxx
+
+==============================================================================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+==============================================================================
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+    1. Definitions.
+
+      &quot;License&quot; shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      &quot;Licensor&quot; shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      &quot;Legal Entity&quot; shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      &quot;control&quot; means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      &quot;You&quot; (or &quot;Your&quot;) shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      &quot;Source&quot; form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      &quot;Object&quot; form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      &quot;Work&quot; shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      &quot;Derivative Works&quot; shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      &quot;Contribution&quot; shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, &quot;submitted&quot;
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as &quot;Not a Contribution.&quot;
+
+      &quot;Contributor&quot; shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+    2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+    3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+    4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a &quot;NOTICE&quot; text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+    5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+    6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+    7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an &quot;AS IS&quot; BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+    8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+    9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+    END OF TERMS AND CONDITIONS
+
+    APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets &quot;[]&quot;
+      replaced with your own identifying information. (Don&#x27;t include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same &quot;printed page&quot; as the copyright notice for easier
+      identification within third-party archives.
+
+    Copyright [yyyy] [name of copyright owner]
+
+    Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 (&quot;Combined Software&quot;) and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+==============================================================================
+Software from third parties included in the LLVM Project:
+==============================================================================
+The LLVM Project contains third party software which is under different license
+terms. All such code will be identified clearly using at least one of two
+mechanisms:
+1) It will be in a separate directory tree with its own `LICENSE.txt` or
+   `LICENSE` file at the top containing the specific license and restrictions
+   which apply to that software, or
+2) It will contain specific license and restriction terms at the top of every
+   file.
+
+==============================================================================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+==============================================================================
+
+The libc++ library is dual licensed under both the University of Illinois
+&quot;BSD-Like&quot; license and the MIT license.  As a user of this code you may choose
+to use it under either license.  As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
+
+==============================================================================
+
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+All rights reserved.
+
+Developed by:
+
+    LLVM Team
+
+    University of Illinois at Urbana-Champaign
+
+    http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the &quot;Software&quot;), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the LLVM Team, University of Illinois at
+      Urbana-Champaign, nor the names of its contributors may be used to
+      endorse or promote products derived from this Software without specific
+      prior written permission.
+
+THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+
+Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the &quot;Software&quot;), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-------------------------------------------------------------------
+libpng
+
+COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
+=========================================
+
+PNG Reference Library License version 2
+---------------------------------------
+
+ * Copyright (c) 1995-2019 The PNG Reference Library Authors.
+ * Copyright (c) 2018-2019 Cosmin Truta.
+ * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
+ * Copyright (c) 1996-1997 Andreas Dilger.
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+
+The software is supplied &quot;as is&quot;, without warranty of any kind,
+express or implied, including, without limitation, the warranties
+of merchantability, fitness for a particular purpose, title, and
+non-infringement.  In no event shall the Copyright owners, or
+anyone distributing the software, be liable for any damages or
+other liability, whether in contract, tort or otherwise, arising
+from, out of, or in connection with the software, or the use or
+other dealings in the software, even if advised of the possibility
+of such damage.
+
+Permission is hereby granted to use, copy, modify, and distribute
+this software, or portions hereof, for any purpose, without fee,
+subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you
+    must not claim that you wrote the original software.  If you
+    use this software in a product, an acknowledgment in the product
+    documentation would be appreciated, but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must
+    not be misrepresented as being the original software.
+
+ 3. This Copyright notice may not be removed or altered from any
+    source or altered source distribution.
+
+
+PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
+-----------------------------------------------------------------------
+
+libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
+Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
+derived from libpng-1.0.6, and are distributed according to the same
+disclaimer and license as libpng-1.0.6 with the following individuals
+added to the list of Contributing Authors:
+
+    Simon-Pierre Cadieux
+    Eric S. Raymond
+    Mans Rullgard
+    Cosmin Truta
+    Gilles Vollant
+    James Yu
+    Mandar Sahastrabuddhe
+    Google Inc.
+    Vadim Barkov
+
+and with the following additions to the disclaimer:
+
+    There is no warranty against interference with your enjoyment of
+    the library or against infringement.  There is no warranty that our
+    efforts or the library will fulfill any of your particular purposes
+    or needs.  This library is provided with all faults, and the entire
+    risk of satisfactory quality, performance, accuracy, and effort is
+    with the user.
+
+Some files in the &quot;contrib&quot; directory and some configure-generated
+files that are distributed with libpng have other copyright owners, and
+are released under other open source licenses.
+
+libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
+Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
+libpng-0.96, and are distributed according to the same disclaimer and
+license as libpng-0.96, with the following individuals added to the
+list of Contributing Authors:
+
+    Tom Lane
+    Glenn Randers-Pehrson
+    Willem van Schaik
+
+libpng versions 0.89, June 1996, through 0.96, May 1997, are
+Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
+and are distributed according to the same disclaimer and license as
+libpng-0.88, with the following individuals added to the list of
+Contributing Authors:
+
+    John Bowler
+    Kevin Bracey
+    Sam Bushell
+    Magnus Holmgren
+    Greg Roelofs
+    Tom Tanner
+
+Some files in the &quot;scripts&quot; directory have other copyright owners,
+but are released under this license.
+
+libpng versions 0.5, May 1995, through 0.88, January 1996, are
+Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+
+For the purposes of this copyright and license, &quot;Contributing Authors&quot;
+is defined as the following set of individuals:
+
+    Andreas Dilger
+    Dave Martindale
+    Guy Eric Schalnat
+    Paul Schmidt
+    Tim Wegner
+
+The PNG Reference Library is supplied &quot;AS IS&quot;.  The Contributing
+Authors and Group 42, Inc. disclaim all warranties, expressed or
+implied, including, without limitation, the warranties of
+merchantability and of fitness for any purpose.  The Contributing
+Authors and Group 42, Inc. assume no liability for direct, indirect,
+incidental, special, exemplary, or consequential damages, which may
+result from the use of the PNG Reference Library, even if advised of
+the possibility of such damage.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+source code, or portions hereof, for any purpose, without fee, subject
+to the following restrictions:
+
+ 1. The origin of this source code must not be misrepresented.
+
+ 2. Altered versions must be plainly marked as such and must not
+    be misrepresented as being the original source.
+
+ 3. This Copyright notice may not be removed or altered from any
+    source or altered source distribution.
+
+The Contributing Authors and Group 42, Inc. specifically permit,
+without fee, and encourage the use of this source code as a component
+to supporting the PNG file format in commercial products.  If you use
+this source code in a product, acknowledgment is not required but would
+be appreciated.
+-------------------------------------------------------------------
+SPIRV-Headers
+
+Copyright (c) 2015-2018 The Khronos Group Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and/or associated documentation files (the
+&quot;Materials&quot;), to deal in the Materials without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Materials, and to
+permit persons to whom the Materials are furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Materials.
+
+MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+   https://www.khronos.org/registry/
+
+THE MATERIALS ARE PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+-------------------------------------------------------------------
+V8 fork of fdlibm
+
+Copyright (C) 1993-2004 by Sun Microsystems, Inc. All rights reserved.
+
+Developed at SunSoft, a Sun Microsystems, Inc. business.
+Permission to use, copy, modify, and distribute this
+software is freely granted, provided that this notice
+is preserved.
+-------------------------------------------------------------------
+Blackmagic DeckLink SDK - Mac
+
+Extracted from mac/include/DeckLinkAPI.h:
+
+** Copyright (c) 2014 Blackmagic Design
+**
+** Permission is hereby granted, free of charge, to any person or organization
+** obtaining a copy of the software and accompanying documentation covered by
+** this license (the &quot;Software&quot;) to use, reproduce, display, distribute,
+** execute, and transmit the Software, and to prepare derivative works of the
+** Software, and to permit third-parties to whom the Software is furnished to
+** do so, all subject to the following:
+**
+** The copyright notices in the Software and this entire statement, including
+** the above license grant, this restriction and the following disclaimer,
+** must be included in all copies of the Software, in whole or in part, and
+** all derivative works of the Software, unless such copies or derivative
+** works are solely in the form of machine-executable object code generated by
+** a source language processor.
+**
+** THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+** DEALINGS IN THE SOFTWARE.
+-------------------------------------------------------------------
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+Autoconf Exception
+
+As a special exception, the Free Software Foundation gives unlimited
+permission to copy, distribute and modify the configure scripts that are the
+output of Autoconf. You need not follow the terms of the GNU General Public
+License when using or distributing such scripts, even though portions of the
+text of Autoconf appear in them. The GNU General Public License (GPL) does
+govern all other use of the material that constitutes the Autoconf program.
+
+Certain portions of the Autoconf source text are designed to be copied (in
+certain cases, depending on the input) into the output of Autoconf. We call
+these the "data" portions. The rest of the Autoconf source text consists of
+comments plus executable code that decides which of the data portions to
+output in any given case. We call these comments and executable code the "non-
+data" portions. Autoconf never copies any of the non-data portions into its
+output.
+
+This special exception to the GPL applies to versions of Autoconf released by
+the Free Software Foundation. When you make and distribute a modified version
+of Autoconf, you may extend this special exception to the GPL to apply to your
+modified version as well, *unless* your modified version has the potential to
+copy into its output some of the text that was the non-data portion of the
+version that you started with. (In other words, unless your change moves or
+copies text from the non-data portions to the data portions.) If your
+modification has such potential, you must delete any notice of this special
+exception to the GPL from your modified version.
+
+                     END OF TERMS AND CONDITIONS
+-------------------------------------------------------------------
+AUTOCONF CONFIGURE SCRIPT EXCEPTION
+
+Version 3.0, 18 August 2009
+
+Copyright © 2009 Free Software Foundation, Inc. <http://fsf.org/>
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+This Exception is an additional permission under section 7 of the GNU General
+Public License, version 3 ("GPLv3"). It applies to a given file that bears a
+notice placed by the copyright holder of the file stating that the file is
+governed by GPLv3 along with this Exception.
+
+The purpose of this Exception is to allow distribution of Autoconf&apos;s
+typical output under terms of the recipient&apos;s choice (including
+proprietary).
+
+0. Definitions.
+"Covered Code" is the source or object code of a version of Autoconf that is a
+covered work under this License.
+
+"Normally Copied Code" for a version of Autoconf means all parts of its
+Covered Code which that version can copy from its code (i.e., not from its
+input file) into its minimally verbose, non-debugging and non-tracing output.
+
+"Ineligible Code" is Covered Code that is not Normally Copied Code.
+
+1. Grant of Additional Permission.
+You have permission to propagate output of Autoconf, even if such propagation
+would otherwise violate the terms of GPLv3. However, if by modifying Autoconf
+you cause any Ineligible Code of the version you received to become Normally
+Copied Code of your modified version, then you void this Exception for the
+resulting covered work. If you convey that resulting covered work, you must
+remove this Exception in accordance with the second paragraph of Section 7 of
+GPLv3.
+
+2. No Weakening of Autoconf Copyleft.
+The availability of this Exception does not imply any general presumption that
+third-party software is unaffected by the copyleft requirements of the license
+of Autoconf.
+-------------------------------------------------------------------
+iccjpeg
+
+(Copied from the README.)
+
+--------------------------------------------------------------------------------
+
+LICENSE extracted from IJG&#x27;s jpeg distribution:
+-----------------------------------------------
+
+In plain English:
+
+1. We don&#x27;t promise that this software works.  (But if you find any bugs,
+   please let us know!)
+2. You can use this software for whatever you want.  You don&#x27;t have to pay us.
+3. You may not pretend that you wrote this software.  If you use it in a
+   program, you must acknowledge somewhere in your documentation that
+   you&#x27;ve used the IJG code.
+
+In legalese:
+
+The authors make NO WARRANTY or representation, either express or implied,
+with respect to this software, its quality, accuracy, merchantability, or
+fitness for a particular purpose.  This software is provided &quot;AS IS&quot;, and you,
+its user, assume the entire risk as to its quality and accuracy.
+
+This software is copyright (C) 1991-1998, Thomas G. Lane.
+All Rights Reserved except as specified below.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+software (or portions thereof) for any purpose, without fee, subject to these
+conditions:
+(1) If any part of the source code for this software is distributed, then this
+README file must be included, with this copyright and no-warranty notice
+unaltered; and any additions, deletions, or changes to the original files
+must be clearly indicated in accompanying documentation.
+(2) If only executable code is distributed, then the accompanying
+documentation must state that &quot;this software is based in part on the work of
+the Independent JPEG Group&quot;.
+(3) Permission for use of this software is granted only if the user accepts
+full responsibility for any undesirable consequences; the authors accept
+NO LIABILITY for damages of any kind.
+
+These conditions apply to any software derived from or based on the IJG code,
+not just to the unmodified library.  If you use our work, you ought to
+acknowledge us.
+
+Permission is NOT granted for the use of any IJG author&#x27;s name or company name
+in advertising or publicity relating to this software or products derived from
+it.  This software may be referred to only as &quot;the Independent JPEG Group&#x27;s
+software&quot;.
+
+We specifically permit and encourage the use of this software as the basis of
+commercial products, provided that all warranty or liability claims are
+assumed by the product vendor.
+-------------------------------------------------------------------
+The JsonCpp library&#x27;s source code, including accompanying documentation, 
+tests and demonstration applications, are licensed under the following
+conditions...
+
+The author (Baptiste Lepilleur) explicitly disclaims copyright in all 
+jurisdictions which recognize such a disclaimer. In such jurisdictions, 
+this software is released into the Public Domain.
+
+In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
+2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
+released under the terms of the MIT License (see below).
+
+In jurisdictions which recognize Public Domain property, the user of this 
+software may choose to accept it either as 1) Public Domain, 2) under the 
+conditions of the MIT License (see below), or 3) under the terms of dual 
+Public Domain/MIT License conditions described here, as they choose.
+
+The MIT License is about as close to Public Domain as a license can get, and is
+described in clear, concise terms at:
+
+   http://en.wikipedia.org/wiki/MIT_License
+   
+The full text of the MIT License follows:
+
+========================================================================
+Copyright (c) 2007-2010 Baptiste Lepilleur
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the &quot;Software&quot;), to deal in the Software without
+restriction, including without limitation the rights to use, copy,
+modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+========================================================================
+(END LICENSE TEXT)
+
+The MIT license is compatible with both the GPL and commercial
+software, affording one all of the rights of Public Domain with the
+minor nuisance of being required to keep the above copyright notice
+and license text in the source code. Note also that by accepting the
+Public Domain &quot;license&quot; you can re-license your copy using whatever
+license you like.
+-------------------------------------------------------------------
+libjpeg-turbo Licenses
+======================
+
+libjpeg-turbo is covered by three compatible BSD-style open source licenses:
+
+- The IJG (Independent JPEG Group) License, which is listed in
+  [README.ijg](README.ijg)
+
+  This license applies to the libjpeg API library and associated programs
+  (any code inherited from libjpeg, and any modifications to that code.)
+
+- The Modified (3-clause) BSD License, which is listed below
+
+  This license covers the TurboJPEG API library and associated programs, as
+  well as the build system.
+
+- The [zlib License](https://opensource.org/licenses/Zlib)
+
+  This license is a subset of the other two, and it covers the libjpeg-turbo
+  SIMD extensions.
+
+
+Complying with the libjpeg-turbo Licenses
+=========================================
+
+This section provides a roll-up of the libjpeg-turbo licensing terms, to the
+best of our understanding.
+
+1.  If you are distributing a modified version of the libjpeg-turbo source,
+    then:
+
+    1.  You cannot alter or remove any existing copyright or license notices
+        from the source.
+
+        **Origin**
+        - Clause 1 of the IJG License
+        - Clause 1 of the Modified BSD License
+        - Clauses 1 and 3 of the zlib License
+
+    2.  You must add your own copyright notice to the header of each source
+        file you modified, so others can tell that you modified that file (if
+        there is not an existing copyright header in that file, then you can
+        simply add a notice stating that you modified the file.)
+
+        **Origin**
+        - Clause 1 of the IJG License
+        - Clause 2 of the zlib License
+
+    3.  You must include the IJG README file, and you must not alter any of the
+        copyright or license text in that file.
+
+        **Origin**
+        - Clause 1 of the IJG License
+
+2.  If you are distributing only libjpeg-turbo binaries without the source, or
+    if you are distributing an application that statically links with
+    libjpeg-turbo, then:
+
+    1.  Your product documentation must include a message stating:
+
+        This software is based in part on the work of the Independent JPEG
+        Group.
+
+        **Origin**
+        - Clause 2 of the IJG license
+
+    2.  If your binary distribution includes or uses the TurboJPEG API, then
+        your product documentation must include the text of the Modified BSD
+        License (see below.)
+
+        **Origin**
+        - Clause 2 of the Modified BSD License
+
+3.  You cannot use the name of the IJG or The libjpeg-turbo Project or the
+    contributors thereof in advertising, publicity, etc.
+
+    **Origin**
+    - IJG License
+    - Clause 3 of the Modified BSD License
+
+4.  The IJG and The libjpeg-turbo Project do not warrant libjpeg-turbo to be
+    free of defects, nor do we accept any liability for undesirable
+    consequences resulting from your use of the software.
+
+    **Origin**
+    - IJG License
+    - Modified BSD License
+    - zlib License
+-------------------------------------------------------------------
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the &quot;Software&quot;), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is fur-
+nished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+DANIEL VEILLARD BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
+NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Daniel Veillard shall not
+be used in advertising or otherwise to promote the sale, use or other deal-
+ings in this Software without prior written authorization from him.
+-------------------------------------------------------------------
+LZMA SDK is placed in the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute the
+original LZMA SDK code, either in source code form or as a compiled binary,
+for any purpose, commercial or non-commercial, and by any means.
+-------------------------------------------------------------------
+ ******    *****   ******   UnRAR - free utility for RAR archives
+ **   **  **   **  **   **  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ******   *******  ******    License for use and distribution of
+ **   **  **   **  **   **   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ **   **  **   **  **   **         FREE portable version
+                                   ~~~~~~~~~~~~~~~~~~~~~
+
+      The source code of UnRAR utility is freeware. This means:
+
+   1. All copyrights to RAR and the utility UnRAR are exclusively
+      owned by the author - Alexander Roshal.
+
+   2. UnRAR source code may be used in any software to handle
+      RAR archives without limitations free of charge, but cannot be
+      used to develop RAR (WinRAR) compatible archiver and to
+      re-create RAR compression algorithm, which is proprietary.
+      Distribution of modified UnRAR source code in separate form
+      or as a part of other software is permitted, provided that
+      full text of this paragraph, starting from &quot;UnRAR source code&quot;
+      words, is included in license, or in documentation if license
+      is not available, and in source code comments of resulting package.
+
+   3. The UnRAR utility may be freely distributed. It is allowed
+      to distribute UnRAR inside of other software packages.
+
+   4. THE RAR ARCHIVER AND THE UnRAR UTILITY ARE DISTRIBUTED &quot;AS IS&quot;.
+      NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED.  YOU USE AT 
+      YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS, 
+      DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
+      OR MISUSING THIS SOFTWARE.
+
+   5. Installing and using the UnRAR utility signifies acceptance of
+      these terms and conditions of the license.
+
+   6. If you don&#x27;t agree with terms of the license you must remove
+      UnRAR files from your storage devices and cease to use the
+      utility.
+
+      Thank you for your interest in RAR and UnRAR.
+
+
+                                            Alexander L. Roshal
+-------------------------------------------------------------------
+Additional IP Rights Grant (Patents)
+------------------------------------
+
+&quot;These implementations&quot; means the copyrightable works that implement the WebM
+codecs distributed by Google as part of the WebM Project.
+
+Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge,
+royalty-free, irrevocable (except as stated in this section) patent license to
+make, have made, use, offer to sell, sell, import, transfer, and otherwise
+run, modify and propagate the contents of these implementations of WebM, where
+such license applies only to those patent claims, both currently owned by
+Google and acquired in the future, licensable by Google that are necessarily
+infringed by these implementations of WebM. This grant does not include claims
+that would be infringed only as a consequence of further modification of these
+implementations. If you or your agent or exclusive licensee institute or order
+or agree to the institution of patent litigation or any other patent
+enforcement activity against any entity (including a cross-claim or
+counterclaim in a lawsuit) alleging that any of these implementations of WebM
+or any code incorporated within any of these implementations of WebM
+constitute direct or contributory patent infringement, or inducement of
+patent infringement, then any patent rights granted to you under this License
+for these implementations of WebM shall terminate as of the date such
+litigation is filed.
+-------------------------------------------------------------------
+
+Copyright (C) 1997 Gregory Pietsch
+
+[These files] are hereby placed in the public domain without restrictions. Just
+give the author credit, don&#x27;t claim you wrote it or prevent anyone else from
+using it.
+
+-------------------------------------------------------------------
+
+Copyright 2001-2011 Xiph.Org, Skype Limited, Octasic,
+                    Jean-Marc Valin, Timothy B. Terriberry,
+                    CSIRO, Gregory Maxwell, Mark Borgerding,
+                    Erik de Castro Lopo
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS&#x27;&#x27; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Opus is subject to the royalty-free patent licenses which are
+specified at:
+
+Xiph.Org Foundation:
+https://datatracker.ietf.org/ipr/1524/
+
+Microsoft Corporation:
+https://datatracker.ietf.org/ipr/1914/
+
+Broadcom Corporation:
+https://datatracker.ietf.org/ipr/1526/
+
+-------------------------------------------------------------------
+
+(WebKit doesn&#x27;t distribute an explicit license.  This LICENSE is derived from
+license text in the source.)
+
+Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+2006, 2007 Alexander Kellett, Alexey Proskuryakov, Alex Mathews, Allan
+Sandfeld Jensen, Alp Toker, Anders Carlsson, Andrew Wellington, Antti
+Koivisto, Apple Inc., Arthur Langereis, Baron Schwartz, Bjoern Graf,
+Brent Fulgham, Cameron Zwarich, Charles Samuels, Christian Dywan,
+Collabora Ltd., Cyrus Patel, Daniel Molkentin, Dave Maclachlan, David
+Smith, Dawit Alemayehu, Dirk Mueller, Dirk Schulze, Don Gibson, Enrico
+Ros, Eric Seidel, Frederik Holljen, Frerich Raabe, Friedmann Kleint,
+George Staikos, Google Inc., Graham Dennis, Harri Porten, Henry Mason,
+Hiroyuki Ikezoe, Holger Hans Peter Freyther, IBM, James G. Speth, Jan
+Alonzo, Jean-Loup Gailly, John Reis, Jonas Witt, Jon Shier, Jonas
+Witt, Julien Chaffraix, Justin Haygood, Kevin Ollivier, Kevin Watters,
+Kimmo Kinnunen, Kouhei Sutou, Krzysztof Kowalczyk, Lars Knoll, Luca
+Bruno, Maks Orlovich, Malte Starostik, Mark Adler, Martin Jones,
+Marvin Decker, Matt Lilek, Michael Emmel, Mitz Pettel, mozilla.org,
+Netscape Communications Corporation, Nicholas Shanks, Nikolas
+Zimmermann, Nokia, Oliver Hunt, Opened Hand, Paul Johnston, Peter
+Kelly, Pioneer Research Center USA, Rich Moore, Rob Buis, Robin Dunn,
+Ronald Tschalär, Samuel Weinig, Simon Hausmann, Staikos Computing
+Services Inc., Stefan Schimanski, Symantec Corporation, The Dojo
+Foundation, The Karbon Developers, Thomas Boyer, Tim Copperfield,
+Tobias Anton, Torben Weis, Trolltech, University of Cambridge, Vaclav
+Slavik, Waldo Bastian, Xan Lopez, Zack Rusin
+
+The terms and conditions vary from file to file, but are one of:
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the
+   distribution.
+
+*OR*
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the
+   distribution.
+3. Neither the name of Apple Computer, Inc. (&quot;Apple&quot;) nor the names of
+   its contributors may be used to endorse or promote products derived
+   from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS&#x27;&#x27; AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
diff --git a/patch/METADATA b/patch/METADATA
new file mode 100644
index 0000000..f4da3b2
--- /dev/null
+++ b/patch/METADATA
@@ -0,0 +1,9 @@
+# go/google3metadata
+# proto-file: devtools/metadata/metadata.proto
+# proto-message: MetaData
+name: "cef/patch"
+description: "Patches used to build CEF"
+
+third_party: {
+  type: GOOGLE_INTERNAL
+}
diff --git a/patch/patch.cfg b/patch/patch.cfg
index 635abaa..4221df5 100755
--- a/patch/patch.cfg
+++ b/patch/patch.cfg
@@ -91,11 +91,29 @@
     'path': 'cef',
   },
   {
-    # Disregard the preprocessor symbol limits included in the CEF build. We hit
-    # this limit in our Windows sandbox build starting on the 4280 branch, but
-    # don't know why.
+    # Allow early git checkout cleanup to reduce local disk consumption, taking
+    # the checkout information from make_distrib.py's caller instead.
     #
     # Bug: b/175682493
-    'name': 'symbol_limit'
+    'name': 'allow_git_cleanup',
+    'path': 'cef',
   },
+  {
+    # Skip installing python-numpy
+    #
+    # Bug: b/197539635
+    'name': 'skip_numpy',
+  },
+  {
+    # Skip installing snapcraft
+    #
+    # Bug: b/261616949
+    'name': 'skip_snapcraft',
+  },
+  {
+    # Build the credits file based on the GN target we consume.
+    #
+    # Bug: b/204770246
+    'name': 'credits_target',
+  }
 )
diff --git a/patch/patches/allow_git_cleanup.patch b/patch/patches/allow_git_cleanup.patch
new file mode 100644
index 0000000..2e9ceed
--- /dev/null
+++ b/patch/patches/allow_git_cleanup.patch
@@ -0,0 +1,41 @@
+diff --git tools/make_distrib.py tools/make_distrib.py
+--- tools/make_distrib.py
++++ tools/make_distrib.py
+@@ -542,6 +542,18 @@
+     dest='quiet',
+     default=False,
+     help='do not output detailed status information')
++parser.add_option(
++    '--chromium-url',
++    dest='chromium_url',
++    metavar='URL',
++    help='Chromium checkout URL',
++    default='Unknown')
++parser.add_option(
++    '--chromium-rev',
++    dest='chromium_rev',
++    metavar='REVISION',
++    help='Chromium checkout revision',
++    default='Unknown')
+ (options, args) = parser.parse_args()
+ 
+ # Test the operating system.
+@@ -599,12 +611,13 @@
+ cef_rev = git.get_hash(cef_dir)
+ cef_commit_number = git.get_commit_number(cef_dir)
+ 
++# retrieve information for Chromium
+ if not git.is_checkout(src_dir):
+-  raise Exception('Not a valid checkout: %s' % (src_dir))
+-
+-# retrieve information for Chromium
+-chromium_url = git.get_url(src_dir)
+-chromium_rev = git.get_hash(src_dir)
++  chromium_url = options.chromium_url
++  chromium_rev = options.chromium_rev
++else:
++  chromium_url = git.get_url(src_dir)
++  chromium_rev = git.get_hash(src_dir)
+ 
+ date = get_date()
+ 
diff --git a/patch/patches/credits_target.patch b/patch/patches/credits_target.patch
new file mode 100644
index 0000000..a9895df
--- /dev/null
+++ b/patch/patches/credits_target.patch
@@ -0,0 +1,12 @@
+diff --git components/resources/BUILD.gn components/resources/BUILD.gn
+--- components/resources/BUILD.gn
++++ components/resources/BUILD.gn
+@@ -96,6 +96,8 @@ action("about_credits") {
+ 
+   args = [
+     "--target-os=$target_os",
++    "--gn-target=//cef:libcef_static",
++    "--gn-out-dir=.",
+     "--depfile",
+     rebase_path(depfile, root_build_dir),
+     "credits",
diff --git a/patch/patches/google3_compatibility.patch b/patch/patches/google3_compatibility.patch
index 7886668..c508a3d 100644
--- a/patch/patches/google3_compatibility.patch
+++ b/patch/patches/google3_compatibility.patch
@@ -1,108 +1,8 @@
-diff --git include/base/cef_atomicops.h include/base/cef_atomicops.h
-index 96aebab..501788f 100644
---- include/base/cef_atomicops.h
-+++ include/base/cef_atomicops.h
-@@ -54,7 +54,7 @@
- #define CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_
- #pragma once
- 
--#if defined(BASE_ATOMICOPS_H_)
-+#if defined(BASE_ATOMICOPS_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
-@@ -92,9 +92,13 @@
- // http://code.google.com/p/nativeclient/issues/detail?id=1162
- typedef int64_t Atomic64;
- #else
-+#if defined(USING_GOOGLE3_INCLUDES)
-+typedef int64_t Atomic64;
-+#else
- typedef intptr_t Atomic64;
- #endif
- #endif
-+#endif
- 
- // Use AtomicWord for a machine-sized pointer.  It will use the Atomic32 or
- // Atomic64 routines below, depending on your architecture.
-diff --git include/base/cef_basictypes.h include/base/cef_basictypes.h
-index e38f4f729..fcb0a5916 100644
---- include/base/cef_basictypes.h
-+++ include/base/cef_basictypes.h
-@@ -37,6 +37,11 @@
- 
- #include "include/base/cef_build.h"
- 
-+#if defined(USING_GOOGLE3_INCLUDES)
-+// When building CEF in google3, use the google3 header directly.
-+#include "base/integral_types.h"
-+#else  // !USING_GOOGLE3_INCLUDES
-+
- // The NSPR system headers define 64-bit as |long| when possible, except on
- // Mac OS X.  In order to not have typedef mismatches, we do the same on LP64.
- //
-@@ -74,6 +79,8 @@ typedef short int16;
- typedef unsigned short uint16;
- #endif
- 
-+#endif  // !USING_GOOGLE3_INCLUDES
-+
- // UTF-16 character type.
- // This should be kept synchronized with base/strings/string16.h
- #ifndef char16
-diff --git include/base/cef_bind.h include/base/cef_bind.h
-index 77c9c5573..a917a1887 100644
---- include/base/cef_bind.h
-+++ include/base/cef_bind.h
-@@ -32,7 +32,7 @@
- #define CEF_INCLUDE_BASE_CEF_BIND_H_
- #pragma once
- 
--#if defined(BASE_BIND_H_)
-+#if defined(BASE_BIND_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
-diff --git include/base/cef_bind_helpers.h include/base/cef_bind_helpers.h
-index 2b4798b2c..b220b9934 100644
---- include/base/cef_bind_helpers.h
-+++ include/base/cef_bind_helpers.h
-@@ -170,7 +170,7 @@
- #define CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_
- #pragma once
- 
--#if defined(BASE_BIND_HELPERS_H_)
-+#if defined(BASE_BIND_HELPERS_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
-diff --git include/base/cef_callback.h include/base/cef_callback.h
-index 16e238a97..83cb0ebe4 100644
---- include/base/cef_callback.h
-+++ include/base/cef_callback.h
-@@ -32,7 +32,7 @@
- #define CEF_INCLUDE_BASE_CEF_CALLBACK_H_
- #pragma once
- 
--#if defined(BASE_CALLBACK_H_)
-+#if defined(BASE_CALLBACK_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
 diff --git include/base/cef_callback_forward.h include/base/cef_callback_forward.h
-index d604d7cfa..e434bd12f 100644
+index 2d2277433..efd45fd0a 100644
 --- include/base/cef_callback_forward.h
 +++ include/base/cef_callback_forward.h
-@@ -32,7 +32,7 @@
- #define INCLUDE_BASE_CEF_CALLBACK_FORWARD_H_
- #pragma once
- 
--#if defined(BASE_CALLBACK_FORWARD_H_)
-+#if defined(BASE_CALLBACK_FORWARD_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
-@@ -54,6 +54,27 @@ typedef Callback<void(void)> Closure;
+@@ -58,6 +58,27 @@ using RepeatingClosure = RepeatingCallback<void()>;
  
  }  // namespace base
  
@@ -130,63 +30,12 @@
  #endif  // !!USING_CHROMIUM_INCLUDES
  
  #endif  // INCLUDE_BASE_CEF_CALLBACK_FORWARD_H_
-diff --git include/base/cef_callback_helpers.h include/base/cef_callback_helpers.h
-index ebe074a1f..1692cfde5 100644
---- include/base/cef_callback_helpers.h
-+++ include/base/cef_callback_helpers.h
-@@ -41,7 +41,7 @@
- #define CEF_INCLUDE_BASE_CEF_CALLBACK_HELPERS_H_
- #pragma once
- 
--#if defined(BASE_CALLBACK_HELPERS_H_)
-+#if defined(BASE_CALLBACK_HELPERS_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
-diff --git include/base/cef_callback_list.h include/base/cef_callback_list.h
-index e0ef3665b..8e0a5d6e5 100644
---- include/base/cef_callback_list.h
-+++ include/base/cef_callback_list.h
-@@ -32,7 +32,7 @@
- #define CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_
- #pragma once
- 
--#if defined(BASE_CALLBACK_LIST_H_)
-+#if defined(BASE_CALLBACK_LIST_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
-diff --git include/base/cef_cancelable_callback.h include/base/cef_cancelable_callback.h
-index febce3a32..c1cfbf03d 100644
---- include/base/cef_cancelable_callback.h
-+++ include/base/cef_cancelable_callback.h
-@@ -69,7 +69,7 @@
- #define CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_
- #pragma once
- 
--#if defined(BASE_CANCELABLE_CALLBACK_H_)
-+#if defined(BASE_CANCELABLE_CALLBACK_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
-diff --git include/base/cef_lock.h include/base/cef_lock.h
-index 6909bd6f2..cc122cafd 100644
---- include/base/cef_lock.h
-+++ include/base/cef_lock.h
-@@ -32,7 +32,7 @@
- #define CEF_INCLUDE_BASE_CEF_LOCK_H_
- #pragma once
- 
--#if defined(BASE_SYNCHRONIZATION_LOCK_H_)
-+#if defined(BASE_SYNCHRONIZATION_LOCK_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
 diff --git include/base/cef_logging.h include/base/cef_logging.h
-index 8d8bb889e..fef75d78b 100644
+diff --git include/base/cef_logging.h include/base/cef_logging.h
+index 31adf2151..8b40bd876 100644
 --- include/base/cef_logging.h
 +++ include/base/cef_logging.h
-@@ -140,7 +140,7 @@
+@@ -160,7 +160,7 @@
  // When building CEF include the Chromium header directly.
  #include "base/logging.h"
  #include "base/notreached.h"
@@ -195,7 +44,7 @@
  // Do nothing if the macros provided by this header already exist.
  // This can happen in cases where Chromium code is used directly by the
  // client application. When using Chromium code directly always include
-@@ -163,6 +163,12 @@
+@@ -183,6 +183,12 @@
  #include <sstream>
  #include <string>
  
@@ -206,9 +55,9 @@
 +#endif  // USING_GOOGLE3_INCLUDES
 +
  #include "include/base/cef_build.h"
- #include "include/base/cef_macros.h"
  #include "include/internal/cef_logging_internal.h"
-@@ -199,6 +205,8 @@
+ 
+@@ -218,6 +224,8 @@ const LogSeverity LOG_DFATAL = LOG_ERROR;
  const LogSeverity LOG_DFATAL = LOG_FATAL;
  #endif
  
@@ -217,7 +66,7 @@
  // A few definitions of macros that don't generate much code. These are used
  // by LOG() and LOG_IF, etc. Since these are used all over our code, it's
  // better to have compact code for these operations.
-@@ -356,6 +364,8 @@
+@@ -375,6 +383,8 @@ const LogSeverity LOG_0 = LOG_ERROR;
            (val1), (val2), #val1 " " #op " " #val2))           \
    cef::logging::LogMessage(__FILE__, __LINE__, _result).stream()
  
@@ -226,7 +75,7 @@
  // Build the error message string.  This is separate from the "Impl"
  // function template because it is not performance critical and so can
  // be out of line, while the "Impl" code should be inline.  Caller
-@@ -393,6 +403,8 @@
+@@ -412,6 +422,8 @@ extern template std::string* MakeCheckOpString<std::string, std::string>(
      const char* name);
  #endif
  
@@ -235,7 +84,7 @@
  // Helper functions for CHECK_OP macro.
  // The (int, int) specialization works around the issue that the compiler
  // will not instantiate the template version of the function on values of
-@@ -433,12 +445,16 @@
+@@ -452,12 +464,16 @@ DEFINE_CHECK_OP_IMPL(GT, >)
  #define ENABLE_DLOG 1
  #endif
  
@@ -252,18 +101,13 @@
  // Definitions for DLOG et al.
  
  #if ENABLE_DLOG
-@@ -554,6 +570,8 @@
+@@ -573,12 +589,18 @@ const LogSeverity LOG_DCHECK = LOG_INFO;
  #define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2)
  #define DCHECK_GT(val1, val2) DCHECK_OP(GT, >, val1, val2)
  
 +#endif  // !USING_GOOGLE3_INCLUDES
 +
- #if defined(NDEBUG) && defined(OS_CHROMEOS)
- #define NOTREACHED() \
-   LOG(ERROR) << "NOTREACHED() hit in " << __FUNCTION__ << ". "
-@@ -561,10 +579,14 @@
  #define NOTREACHED() DCHECK(false)
- #endif
  
 +#if !defined(USING_GOOGLE3_INCLUDES)
 +
@@ -276,16 +120,16 @@
  // This class more or less represents a particular log message.  You
  // create an instance of LogMessage and then stream stuff to it.
  // When you finish streaming to it, ~LogMessage is called and the
-@@ -707,6 +729,8 @@
-   return out << wstr.c_str();
+@@ -731,6 +753,8 @@ inline std::ostream& operator<<(std::ostream& out, const char16_t* wstr) {
  }
+ #endif
  
 +#if !defined(USING_GOOGLE3_INCLUDES)
 +
  // The NOTIMPLEMENTED() macro annotates codepaths which have
  // not been implemented yet.
  //
-@@ -756,6 +780,8 @@
+@@ -780,6 +804,8 @@ inline std::ostream& operator<<(std::ostream& out, const char16_t* wstr) {
    EAT_STREAM_PARAMETERS
  #endif
  
@@ -295,123 +139,27 @@
  
  #endif  // CEF_INCLUDE_BASE_CEF_LOGGING_H_
 diff --git include/base/cef_macros.h include/base/cef_macros.h
-index e714529cd..67588c615 100644
+index f5517f9cb..64adf3132 100644
 --- include/base/cef_macros.h
 +++ include/base/cef_macros.h
-@@ -35,8 +35,10 @@
- #if defined(USING_CHROMIUM_INCLUDES)
- // When building CEF include the Chromium header directly.
- #include "base/macros.h"
--
--#else  // !USING_CHROMIUM_INCLUDES
-+#elif defined(USING_GOOGLE3_INCLUDES)
+@@ -33,6 +33,11 @@
+ #pragma once
+ 
+ #if !defined(USING_CHROMIUM_INCLUDES)
++#if defined(USING_GOOGLE3_INCLUDES)
 +// When building CEF in google3, use the google3 header directly.
 +#include "base/macros.h"
 +#else  // !USING_GOOGLE3_INCLUDES
++
  // The following is substantially similar to the Chromium implementation.
  // If the Chromium implementation diverges the below implementation should be
  // updated to match.
-diff --git include/base/cef_platform_thread.h include/base/cef_platform_thread.h
-index d3fdd798e..15cb0951b 100644
---- include/base/cef_platform_thread.h
-+++ include/base/cef_platform_thread.h
-@@ -35,7 +35,7 @@
- #ifndef CEF_INCLUDE_BASE_PLATFORM_THREAD_H_
- #define CEF_INCLUDE_BASE_PLATFORM_THREAD_H_
+@@ -58,6 +63,8 @@
+   TypeName() = delete;                           \
+   DISALLOW_COPY_AND_ASSIGN(TypeName)
  
--#if defined(BASE_THREADING_PLATFORM_THREAD_H_)
-+#if defined(BASE_THREADING_PLATFORM_THREAD_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
-diff --git include/base/cef_ref_counted.h include/base/cef_ref_counted.h
-index 7a687070c..93d8cbeaa 100644
---- include/base/cef_ref_counted.h
-+++ include/base/cef_ref_counted.h
-@@ -33,7 +33,7 @@
- #define CEF_INCLUDE_BASE_CEF_REF_COUNTED_H_
- #pragma once
++#endif  // !USING_GOOGLE3_INCLUDES
++
+ #endif  // !USING_CHROMIUM_INCLUDES
  
--#if defined(BASE_MEMORY_REF_COUNTED_H_)
-+#if defined(BASE_MEMORY_REF_COUNTED_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
-diff --git include/base/cef_scoped_ptr.h include/base/cef_scoped_ptr.h
-index eb9e0e29b..6efc7ca85 100644
---- include/base/cef_scoped_ptr.h
-+++ include/base/cef_scoped_ptr.h
-@@ -114,7 +114,7 @@
- #define CEF_INCLUDE_BASE_CEF_MEMORY_SCOPED_PTR_H_
- #pragma once
- 
--#if defined(BASE_MEMORY_SCOPED_PTR_H_)
-+#if defined(BASE_MEMORY_SCOPED_PTR_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
-diff --git include/base/cef_string16.h include/base/cef_string16.h
-index 6afcb79bd..e5cbaa861 100644
---- include/base/cef_string16.h
-+++ include/base/cef_string16.h
-@@ -32,7 +32,7 @@
- #define CEF_INCLUDE_BASE_CEF_STRING16_H_
- #pragma once
- 
--#if defined(BASE_STRINGS_STRING16_H_)
-+#if defined(BASE_STRINGS_STRING16_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
-diff --git include/base/cef_template_util.h include/base/cef_template_util.h
-index 38fa5839c..6c70dd2ac 100644
---- include/base/cef_template_util.h
-+++ include/base/cef_template_util.h
-@@ -32,7 +32,7 @@
- #define CEF_INCLUDE_BASE_CEF_TEMPLATE_UTIL_H_
- #pragma once
- 
--#if defined(BASE_TEMPLATE_UTIL_H_)
-+#if defined(BASE_TEMPLATE_UTIL_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
-diff --git include/base/cef_thread_checker.h include/base/cef_thread_checker.h
-index e48c8d033..c582e1377 100644
---- include/base/cef_thread_checker.h
-+++ include/base/cef_thread_checker.h
-@@ -32,7 +32,7 @@
- #define CEF_INCLUDE_BASE_THREAD_CHECKER_H_
- #pragma once
- 
--#if defined(BASE_THREADING_THREAD_CHECKER_H_)
-+#if defined(BASE_THREADING_THREAD_CHECKER_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
-diff --git include/base/cef_tuple.h include/base/cef_tuple.h
-index aeb6e9cea..f6b86167f 100644
---- include/base/cef_tuple.h
-+++ include/base/cef_tuple.h
-@@ -56,7 +56,7 @@
- #define CEF_INCLUDE_BASE_CEF_TUPLE_H_
- #pragma once
- 
--#if defined(BASE_TUPLE_H_)
-+#if defined(BASE_TUPLE_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
-diff --git include/base/cef_weak_ptr.h include/base/cef_weak_ptr.h
-index 1ba34b9db..2cf2f1787 100644
---- include/base/cef_weak_ptr.h
-+++ include/base/cef_weak_ptr.h
-@@ -96,7 +96,7 @@
- #define CEF_INCLUDE_BASE_CEF_WEAK_PTR_H_
- #pragma once
- 
--#if defined(BASE_MEMORY_WEAK_PTR_H_)
-+#if defined(BASE_MEMORY_WEAK_PTR_H_) && !defined(USING_GOOGLE3_INCLUDES)
- // Do nothing if the Chromium header has already been included.
- // This can happen in cases where Chromium code is used directly by the
- // client application. When using Chromium code directly always include
+ #endif  // CEF_INCLUDE_BASE_CEF_MACROS_H_
diff --git a/patch/patches/mac_toolchain_creds.patch b/patch/patches/mac_toolchain_creds.patch
index c6a53bb..25f76f0 100644
--- a/patch/patches/mac_toolchain_creds.patch
+++ b/patch/patches/mac_toolchain_creds.patch
@@ -1,11 +1,11 @@
 diff --git build/mac_toolchain.py build/mac_toolchain.py
-index 866b5f8..56f640c 100755
+index 43d336cf2f0b7..b029b66da2e6a 100755
 --- build/mac_toolchain.py
 +++ build/mac_toolchain.py
-@@ -107,6 +107,13 @@
-       'cipd', 'ensure', '-root', binaries_root, '-ensure-file', '-'
-   ]
- 
+@@ -119,6 +119,13 @@ def InstallXcodeBinaries():
+   # 'cipd ensure' is idempotent.
+   args = ['cipd', 'ensure', '-root', binaries_root, '-ensure-file', '-']
+
 +  # Buildbot slaves need to use explicit credentials. LUCI bots should NOT set
 +  # this variable. This is temporary code used to make official Xcode bots
 +  # happy. https://crbug.com/986488
@@ -13,6 +13,6 @@
 +  if creds:
 +    args.extend(['--service-account-json', creds])
 +
-   p = subprocess.Popen(
-       args, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
-       stderr=subprocess.PIPE)
+   p = subprocess.Popen(args,
+                        universal_newlines=True,
+                        stdin=subprocess.PIPE,
diff --git a/patch/patches/skip_numpy.patch b/patch/patches/skip_numpy.patch
new file mode 100644
index 0000000..35aa7d1
--- /dev/null
+++ b/patch/patches/skip_numpy.patch
@@ -0,0 +1,14 @@
+diff --git build/install-build-deps.py build/install-build-deps.py
+index 9d927e6320b78..e5e9d5ce80047 100755
+--- build/install-build-deps.py
++++ build/install-build-deps.py
+@@ -550,9 +550,6 @@ def backwards_compatible_list(options):
+   if package_exists("python-crypto"):
+     packages.append("python-crypto")
+ 
+-  if package_exists("python-numpy"):
+-    packages.append("python-numpy")
+-
+   if package_exists("python-openssl"):
+     packages.append("python-openssl")
+ 
diff --git a/patch/patches/skip_snapcraft.patch b/patch/patches/skip_snapcraft.patch
new file mode 100644
index 0000000..ac97c46
--- /dev/null
+++ b/patch/patches/skip_snapcraft.patch
@@ -0,0 +1,13 @@
+diff --git build/install-build-deps.py build/install-build-deps.py
+index 9d927e6320..ce1e435764 100755
+--- build/install-build-deps.py
++++ build/install-build-deps.py
+@@ -533,7 +533,6 @@ def backwards_compatible_list(options):
+       "msttcorefonts",
+       "python-dev",
+       "python-setuptools",
+-      "snapcraft",
+       "ttf-dejavu-core",
+       "ttf-indic-fonts",
+       "ttf-kochi-gothic",
+ 
\ No newline at end of file
diff --git a/patch/patches/symbol_limit.patch b/patch/patches/symbol_limit.patch
deleted file mode 100644
index 2068e57..0000000
--- a/patch/patches/symbol_limit.patch
+++ /dev/null
@@ -1,17 +0,0 @@
-diff --git build/config/compiler/BUILD.gn build/config/compiler/BUILD.gn
---- build/config/compiler/BUILD.gn
-+++ build/config/compiler/BUILD.gn
-@@ -1566,12 +1566,7 @@
-           "-Wno-implicit-fallthrough",
-         ]
- 
-+        cflags += [ "-Wno-max-tokens" ]
--        if (enable_wmax_tokens) {
--          cflags += [ "-Wmax-tokens" ]
--        } else {
--          # TODO(https://crbug.com/1049569): Remove after Clang 87b235db.
--          cflags += [ "-Wno-max-tokens" ]
--        }
-       }
-     }
-   }
diff --git a/src/.github/ISSUE_TEMPLATE/bug_report.md b/src/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..b66ff24
--- /dev/null
+++ b/src/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,35 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: bug
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen and what happened instead.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Versions (please complete the following information):**
+ - OS: [e.g. Windows 10, MacOS 13.2, Ubuntu 22.10]
+ - CEF Version: [e.g. 111.2.2]
+
+**Additional context**
+Does the problem reproduce with the cefclient or cefsimple sample application at the same version?
+
+Does the problem reproduce with Google Chrome at the same version?
+
+Add any other context about the problem here.
diff --git a/src/.github/ISSUE_TEMPLATE/feature_request.md b/src/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..11fc491
--- /dev/null
+++ b/src/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: enhancement
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/src/BUILD.gn b/src/BUILD.gn
index 2722b23..b2c95fa 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -96,9 +96,9 @@
 import("//base/allocator/allocator.gni")
 import("//build/config/features.gni")
 import("//build/config/locales.gni")
+import("//build/config/ozone.gni")
 import("//build/config/sanitizers/sanitizers.gni")
 import("//build/config/ui.gni")
-import("//cef/cef_repack_locales.gni")
 import("//chrome/common/features.gni")
 import("//content/public/app/mac_helpers.gni")
 import("//extensions/buildflags/buildflags.gni")
@@ -106,6 +106,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 import("//ppapi/buildflags/buildflags.gni")
 import("//printing/buildflags/buildflags.gni")
+import("//rlz/buildflags/buildflags.gni")
 import("//testing/test.gni")
 import("//third_party/icu/config.gni")
 import("//third_party/widevine/cdm/widevine.gni")
@@ -122,11 +123,10 @@
   import("//third_party/fontconfig/fontconfig.gni")
 }
 if (is_mac) {
+  import("//build/apple/tweak_info_plist.gni")
   import("//build/config/mac/rules.gni")
-  import("//build/mac/tweak_info_plist.gni")
-  import("//build/util/version.gni")
+  import("//chrome/version.gni")
   import("//media/cdm/library_cdm/cdm_paths.gni")
-  import("//build/config/mac/base_rules.gni")
 
   # Template to compile .xib and .storyboard files.
   #
@@ -258,17 +258,22 @@
 # Enable support for Widevine CDM.
 assert(enable_widevine)
 
+if (is_mac || is_win) {
+  # Enable Widevine CDM host verification and storage ID.
+  assert(enable_cdm_host_verification)
+  assert(enable_cdm_storage_id)
+  assert(alternate_cdm_storage_id_key != "")
+  assert(enable_rlz)
+}
+
+# Enable Views UI framework.
+assert(toolkit_views)
+
 if (is_clang) {
   # Don't use the chrome style plugin.
   assert(!clang_use_chrome_plugins)
 }
 
-if (is_mac) {
-  # Always generate dSYM files. The make_distrib script will fail if
-  # enable_dsyms=true is not explicitly set when is_official_build=false.
-  assert(enable_dsyms)
-}
-
 
 #
 # Local variables.
@@ -314,16 +319,12 @@
     ":libcef_static_unittests",
   ]
 
-  if (!is_linux || use_x11) {
+  if (!is_linux || ozone_platform_x11) {
     deps += [ ":cefclient" ]
   }
 }
 
 
-#
-# libcef static target.
-#
-
 if (is_win) {
   # Target for building code that accesses chrome_elf internals. Included from
   # the //chrome_elf:crash target. Defined as a static_library instead of a
@@ -365,19 +366,32 @@
 
       # Required by content_switches.cc
       "//media:media_buildflags",
+
+      # Required by crash_keys.cc (from base/stl_util.h)
+      "//third_party/abseil-cpp:absl",
     ]
   }
 }
 
-# libcef_static source files that have unit tests.
+
+#
+# Test support targets.
+#
+
+# Source files that are linked into libcef and cef_framework and tested by
+# libcef_static_unittests. These sources provide libcef-internal functionality
+# that is limited in scope (e.g. utility classes/methods).
 source_set("libcef_static_unittested") {
   sources = [
     "libcef/browser/devtools/devtools_util.cc",
     "libcef/browser/devtools/devtools_util.h",
+    "libcef/browser/geometry_util.h",
+    "libcef/browser/geometry_util.cc",
   ]
 
   deps = [
     "//base",
+    "//ui/gfx/geometry",
   ]
 
   configs += [
@@ -386,10 +400,14 @@
   ]
 }
 
-# Executable target for libcef_static unit tests.
+# Executable target that provides test coverage for libcef_static_unittested
+# source files.
 test("libcef_static_unittests") {
+  testonly = true
+
   sources = [
     "libcef/browser/devtools/devtools_util_unittest.cc",
+    "libcef/browser/geometry_util_unittest.cc",
   ]
 
   deps = [
@@ -404,25 +422,84 @@
   ]
 }
 
-static_library("libcef_static") {
+# Source files that are linked into libcef and cef_framework and implement
+# interfaces exposed to ceftests via the include/test directory. These sources
+# may access Chromium/CEF internals. This is defined as a separate target from
+# libcef_static to avoid introducing testonly dependencies there.
+source_set("libcef_test_support") {
+  testonly = true
+
+  sources = [
+    "libcef/browser/test/test_helpers_impl.cc",
+    "libcef/browser/test/test_server_impl.cc",
+    "libcef/browser/test/test_server_impl.h",
+    "libcef/common/test/translator_test_impl.cc",
+  ]
+
+  deps = [
+    ":libcef_static",
+    "//net:test_support",
+
+    # Support for UI input events.
+    "//ui/views:test_support",
+  ]
+}
+
+
+#
+# libcef_static target.
+#
+
+source_set("libcef_static") {
   sources = includes_common +
             gypi_paths.autogen_cpp_includes + [
+    "libcef/browser/alloy/alloy_browser_context.cc",
+    "libcef/browser/alloy/alloy_browser_context.h",
+    "libcef/browser/alloy/alloy_browser_host_impl.cc",
+    "libcef/browser/alloy/alloy_browser_host_impl.h",
+    "libcef/browser/alloy/alloy_browser_main.cc",
+    "libcef/browser/alloy/alloy_browser_main.h",
+    "libcef/browser/alloy/alloy_content_browser_client.cc",
+    "libcef/browser/alloy/alloy_content_browser_client.h",
+    "libcef/browser/alloy/alloy_download_util.cc",
+    "libcef/browser/alloy/alloy_download_util.h",
+    "libcef/browser/alloy/alloy_web_contents_view_delegate.cc",
+    "libcef/browser/alloy/alloy_web_contents_view_delegate.h",
+    "libcef/browser/alloy/browser_platform_delegate_alloy.cc",
+    "libcef/browser/alloy/browser_platform_delegate_alloy.h",
+    "libcef/browser/alloy/dialogs/alloy_constrained_window_views_client.cc",
+    "libcef/browser/alloy/dialogs/alloy_constrained_window_views_client.h",
+    "libcef/browser/alloy/dialogs/alloy_javascript_dialog_manager_delegate.cc",
+    "libcef/browser/alloy/dialogs/alloy_javascript_dialog_manager_delegate.h",
+    "libcef/browser/alloy/dialogs/alloy_web_contents_dialog_helper.cc",
+    "libcef/browser/alloy/dialogs/alloy_web_contents_dialog_helper.h",
+    "libcef/browser/alloy/chrome_browser_process_alloy.cc",
+    "libcef/browser/alloy/chrome_browser_process_alloy.h",
+    "libcef/browser/alloy/chrome_profile_manager_alloy.cc",
+    "libcef/browser/alloy/chrome_profile_manager_alloy.h",
+    "libcef/browser/alloy/chrome_profile_alloy.cc",
+    "libcef/browser/alloy/chrome_profile_alloy.h",
     "libcef/browser/audio_capturer.cc",
     "libcef/browser/audio_capturer.h",
+    "libcef/browser/audio_loopback_stream_creator.cc",
+    "libcef/browser/audio_loopback_stream_creator.h",
+    "libcef/browser/browser_contents_delegate.cc",
+    "libcef/browser/browser_contents_delegate.h",
     "libcef/browser/browser_context.cc",
     "libcef/browser/browser_context.h",
     "libcef/browser/browser_context_keyed_service_factories.cc",
     "libcef/browser/browser_context_keyed_service_factories.h",
-    "libcef/browser/browser_host_impl.cc",
-    "libcef/browser/browser_host_impl.h",
+    "libcef/browser/browser_frame.cc",
+    "libcef/browser/browser_frame.h",
+    "libcef/browser/browser_host_base.cc",
+    "libcef/browser/browser_host_base.h",
+    "libcef/browser/browser_host_create.cc",
     "libcef/browser/browser_info.cc",
     "libcef/browser/browser_info.h",
     "libcef/browser/browser_info_manager.cc",
     "libcef/browser/browser_info_manager.h",
-    "libcef/browser/browser_main.cc",
-    "libcef/browser/browser_main.h",
-    "libcef/browser/browser_message_filter.cc",
-    "libcef/browser/browser_message_filter.h",
+    "libcef/browser/browser_manager.cc",
+    "libcef/browser/browser_manager.h",
     "libcef/browser/browser_message_loop.cc",
     "libcef/browser/browser_message_loop.h",
     "libcef/browser/browser_platform_delegate.cc",
@@ -430,15 +507,42 @@
     "libcef/browser/browser_platform_delegate_create.cc",
     "libcef/browser/browser_util.cc",
     "libcef/browser/browser_util.h",
-    "libcef/browser/chrome_browser_process_stub.cc",
-    "libcef/browser/chrome_browser_process_stub.h",
+    "libcef/browser/certificate_query.cc",
+    "libcef/browser/certificate_query.h",
+    "libcef/browser/chrome/browser_delegate.h",
+    "libcef/browser/chrome/browser_platform_delegate_chrome.cc",
+    "libcef/browser/chrome/browser_platform_delegate_chrome.h",
+    "libcef/browser/chrome/chrome_browser_context.cc",
+    "libcef/browser/chrome/chrome_browser_context.h",
+    "libcef/browser/chrome/chrome_browser_delegate.cc",
+    "libcef/browser/chrome/chrome_browser_delegate.h",
+    "libcef/browser/chrome/chrome_browser_host_impl.cc",
+    "libcef/browser/chrome/chrome_browser_host_impl.h",
+    "libcef/browser/chrome/chrome_browser_main_extra_parts_cef.cc",
+    "libcef/browser/chrome/chrome_browser_main_extra_parts_cef.h",
+    "libcef/browser/chrome/chrome_content_browser_client_cef.cc",
+    "libcef/browser/chrome/chrome_content_browser_client_cef.h",
+    "libcef/browser/chrome/chrome_context_menu_handler.cc",
+    "libcef/browser/chrome/chrome_context_menu_handler.h",
     "libcef/browser/chrome_crash_reporter_client_stub.cc",
-    "libcef/browser/chrome_profile_manager_stub.cc",
-    "libcef/browser/chrome_profile_manager_stub.h",
-    "libcef/browser/chrome_profile_stub.cc",
-    "libcef/browser/chrome_profile_stub.h",
-    "libcef/browser/content_browser_client.cc",
-    "libcef/browser/content_browser_client.h",
+    "libcef/browser/chrome/extensions/chrome_mime_handler_view_guest_delegate_cef.cc",
+    "libcef/browser/chrome/extensions/chrome_mime_handler_view_guest_delegate_cef.h",
+    "libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.cc",
+    "libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.h",
+    "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.cc",
+    "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h",
+    "libcef/browser/chrome/views/chrome_browser_frame.cc",
+    "libcef/browser/chrome/views/chrome_browser_frame.h",
+    "libcef/browser/chrome/views/chrome_browser_view.cc",
+    "libcef/browser/chrome/views/chrome_browser_view.h",
+    "libcef/browser/chrome/views/chrome_child_window.cc",
+    "libcef/browser/chrome/views/chrome_child_window.h",
+    "libcef/browser/chrome/views/chrome_views_util.cc",
+    "libcef/browser/chrome/views/chrome_views_util.h",
+    "libcef/browser/chrome/views/toolbar_view_impl.cc",
+    "libcef/browser/chrome/views/toolbar_view_impl.h",
+    "libcef/browser/chrome/views/toolbar_view_view.cc",
+    "libcef/browser/chrome/views/toolbar_view_view.h",
     "libcef/browser/context.cc",
     "libcef/browser/context.h",
     "libcef/browser/context_menu_params_impl.cc",
@@ -459,10 +563,14 @@
     "libcef/browser/download_manager_delegate.h",
     "libcef/browser/extension_impl.cc",
     "libcef/browser/extension_impl.h",
+    "libcef/browser/extensions/api/file_system/cef_file_system_delegate.cc",
+    "libcef/browser/extensions/api/file_system/cef_file_system_delegate.h",
     "libcef/browser/extensions/api/storage/sync_value_store_cache.cc",
     "libcef/browser/extensions/api/storage/sync_value_store_cache.h",
     "libcef/browser/extensions/api/tabs/tabs_api.cc",
     "libcef/browser/extensions/api/tabs/tabs_api.h",
+    "libcef/browser/extensions/alloy_extensions_util.cc",
+    "libcef/browser/extensions/alloy_extensions_util.h",
     "libcef/browser/extensions/browser_extensions_util.cc",
     "libcef/browser/extensions/browser_extensions_util.h",
     "libcef/browser/extensions/browser_platform_delegate_background.cc",
@@ -493,24 +601,30 @@
     "libcef/browser/extensions/extension_web_contents_observer.h",
     "libcef/browser/extensions/mime_handler_view_guest_delegate.cc",
     "libcef/browser/extensions/mime_handler_view_guest_delegate.h",
-    "libcef/browser/extensions/pdf_extension_util.cc",
-    "libcef/browser/extensions/pdf_extension_util.h",
-    "libcef/browser/extensions/pdf_web_contents_helper_client.cc",
-    "libcef/browser/extensions/pdf_web_contents_helper_client.h",
     "libcef/browser/extensions/value_store/cef_value_store.cc",
     "libcef/browser/extensions/value_store/cef_value_store.h",
     "libcef/browser/extensions/value_store/cef_value_store_factory.cc",
     "libcef/browser/extensions/value_store/cef_value_store_factory.h",
-    "libcef/browser/file_dialog_runner.h",
     "libcef/browser/file_dialog_manager.cc",
     "libcef/browser/file_dialog_manager.h",
+    "libcef/browser/file_dialog_runner.cc",
+    "libcef/browser/file_dialog_runner.h",
     "libcef/browser/frame_host_impl.cc",
     "libcef/browser/frame_host_impl.h",
+    "libcef/browser/frame_service_base.h",
+    "libcef/browser/global_preference_manager_impl.cc",
+    "libcef/browser/global_preference_manager_impl.h",
     "libcef/browser/image_impl.cc",
     "libcef/browser/image_impl.h",
+    "libcef/browser/iothread_state.cc",
+    "libcef/browser/iothread_state.h",
     "libcef/browser/javascript_dialog_runner.h",
     "libcef/browser/javascript_dialog_manager.cc",
     "libcef/browser/javascript_dialog_manager.h",
+    "libcef/browser/main_runner.cc",
+    "libcef/browser/main_runner.h",
+    "libcef/browser/media_access_query.cc",
+    "libcef/browser/media_access_query.h",
     "libcef/browser/media_capture_devices_dispatcher.cc",
     "libcef/browser/media_capture_devices_dispatcher.h",
     "libcef/browser/media_router/media_route_impl.cc",
@@ -523,6 +637,8 @@
     "libcef/browser/media_router/media_sink_impl.h",
     "libcef/browser/media_router/media_source_impl.cc",
     "libcef/browser/media_router/media_source_impl.h",
+    "libcef/browser/media_stream_registrar.cc",
+    "libcef/browser/media_stream_registrar.h",
     "libcef/browser/menu_manager.cc",
     "libcef/browser/menu_manager.h",
     "libcef/browser/menu_model_impl.cc",
@@ -530,8 +646,10 @@
     "libcef/browser/menu_runner.h",
     "libcef/browser/native/browser_platform_delegate_native.cc",
     "libcef/browser/native/browser_platform_delegate_native.h",
-    "libcef/browser/navigate_params.cc",
-    "libcef/browser/navigate_params.h",
+    "libcef/browser/native/cursor_util.h",
+    "libcef/browser/native/cursor_util.cc",
+    "libcef/browser/native/window_delegate_view.cc",
+    "libcef/browser/native/window_delegate_view.h",
     "libcef/browser/navigation_entry_impl.cc",
     "libcef/browser/navigation_entry_impl.h",
     "libcef/browser/net/chrome_scheme_handler.cc",
@@ -543,6 +661,8 @@
     "libcef/browser/net/internal_scheme_handler.h",
     "libcef/browser/net/scheme_handler.cc",
     "libcef/browser/net/scheme_handler.h",
+    "libcef/browser/net/throttle_handler.cc",
+    "libcef/browser/net/throttle_handler.h",
     "libcef/browser/net_service/browser_urlrequest_impl.cc",
     "libcef/browser/net_service/browser_urlrequest_impl.h",
     "libcef/browser/net_service/cookie_helper.cc",
@@ -579,30 +699,32 @@
     "libcef/browser/osr/render_widget_host_view_osr.h",
     "libcef/browser/osr/synthetic_gesture_target_osr.cc",
     "libcef/browser/osr/synthetic_gesture_target_osr.h",
+    "libcef/browser/osr/touch_handle_drawable_osr.cc",
+    "libcef/browser/osr/touch_handle_drawable_osr.h",
+    "libcef/browser/osr/touch_selection_controller_client_osr.cc",
+    "libcef/browser/osr/touch_selection_controller_client_osr.h",
     "libcef/browser/osr/video_consumer_osr.cc",
     "libcef/browser/osr/video_consumer_osr.h",
     "libcef/browser/osr/web_contents_view_osr.cc",
     "libcef/browser/osr/web_contents_view_osr.h",
     "libcef/browser/path_util_impl.cc",
-    "libcef/browser/plugins/plugin_service_filter.cc",
-    "libcef/browser/plugins/plugin_service_filter.h",
+    "libcef/browser/permission_prompt.cc",
+    "libcef/browser/permission_prompt.h",
     "libcef/browser/prefs/browser_prefs.cc",
     "libcef/browser/prefs/browser_prefs.h",
+    "libcef/browser/prefs/pref_helper.cc",
+    "libcef/browser/prefs/pref_helper.h",
+    "libcef/browser/prefs/pref_registrar.cc",
+    "libcef/browser/prefs/pref_registrar.h",
     "libcef/browser/prefs/pref_store.cc",
     "libcef/browser/prefs/pref_store.h",
     "libcef/browser/prefs/renderer_prefs.cc",
     "libcef/browser/prefs/renderer_prefs.h",
     "libcef/browser/print_settings_impl.cc",
     "libcef/browser/print_settings_impl.h",
-    "libcef/browser/printing/constrained_window_views_client.cc",
-    "libcef/browser/printing/constrained_window_views_client.h",
-    "libcef/browser/printing/printing_message_filter.cc",
-    "libcef/browser/printing/printing_message_filter.h",
-    "libcef/browser/printing/print_view_manager.cc",
-    "libcef/browser/printing/print_view_manager.h",
+    "libcef/browser/printing/print_util.cc",
+    "libcef/browser/printing/print_util.h",
     "libcef/browser/process_util_impl.cc",
-    "libcef/browser/resource_context.cc",
-    "libcef/browser/resource_context.h",
     "libcef/browser/request_context_handler_map.cc",
     "libcef/browser/request_context_handler_map.h",
     "libcef/browser/request_context_impl.cc",
@@ -610,6 +732,8 @@
     "libcef/browser/scheme_impl.cc",
     "libcef/browser/server_impl.cc",
     "libcef/browser/server_impl.h",
+    "libcef/browser/simple_menu_model_impl.cc",
+    "libcef/browser/simple_menu_model_impl.h",
     "libcef/browser/speech_recognition_manager_delegate.cc",
     "libcef/browser/speech_recognition_manager_delegate.h",
     "libcef/browser/ssl_host_state_delegate.cc",
@@ -624,10 +748,64 @@
     "libcef/browser/trace_subscriber.cc",
     "libcef/browser/trace_subscriber.h",
     "libcef/browser/thread_util.h",
-    "libcef/browser/web_contents_dialog_helper.cc",
-    "libcef/browser/web_contents_dialog_helper.h",
-    "libcef/browser/web_plugin_impl.cc",
-    "libcef/browser/web_plugin_impl.h",
+    "libcef/browser/views/basic_label_button_impl.cc",
+    "libcef/browser/views/basic_label_button_impl.h",
+    "libcef/browser/views/basic_label_button_view.cc",
+    "libcef/browser/views/basic_label_button_view.h",
+    "libcef/browser/views/basic_panel_impl.cc",
+    "libcef/browser/views/basic_panel_impl.h",
+    "libcef/browser/views/basic_panel_view.cc",
+    "libcef/browser/views/basic_panel_view.h",
+    "libcef/browser/views/box_layout_impl.cc",
+    "libcef/browser/views/box_layout_impl.h",
+    "libcef/browser/views/browser_platform_delegate_views.cc",
+    "libcef/browser/views/browser_platform_delegate_views.h",
+    "libcef/browser/views/browser_view_impl.cc",
+    "libcef/browser/views/browser_view_impl.h",
+    "libcef/browser/views/browser_view_view.cc",
+    "libcef/browser/views/browser_view_view.h",
+    "libcef/browser/views/button_impl.h",
+    "libcef/browser/views/button_view.h",
+    "libcef/browser/views/display_impl.cc",
+    "libcef/browser/views/display_impl.h",
+    "libcef/browser/views/fill_layout_impl.cc",
+    "libcef/browser/views/fill_layout_impl.h",
+    "libcef/browser/views/label_button_impl.h",
+    "libcef/browser/views/label_button_view.h",
+    "libcef/browser/views/layout_impl.h",
+    "libcef/browser/views/layout_adapter.cc",
+    "libcef/browser/views/layout_adapter.h",
+    "libcef/browser/views/layout_util.cc",
+    "libcef/browser/views/layout_util.h",
+    "libcef/browser/views/menu_button_impl.cc",
+    "libcef/browser/views/menu_button_impl.h",
+    "libcef/browser/views/menu_button_view.cc",
+    "libcef/browser/views/menu_button_view.h",
+    "libcef/browser/views/menu_runner_views.cc",
+    "libcef/browser/views/menu_runner_views.h",
+    "libcef/browser/views/overlay_view_host.cc",
+    "libcef/browser/views/overlay_view_host.h",
+    "libcef/browser/views/panel_impl.h",
+    "libcef/browser/views/panel_view.h",
+    "libcef/browser/views/scroll_view_impl.cc",
+    "libcef/browser/views/scroll_view_impl.h",
+    "libcef/browser/views/scroll_view_view.cc",
+    "libcef/browser/views/scroll_view_view.h",
+    "libcef/browser/views/textfield_impl.cc",
+    "libcef/browser/views/textfield_impl.h",
+    "libcef/browser/views/textfield_view.cc",
+    "libcef/browser/views/textfield_view.h",
+    "libcef/browser/views/view_adapter.cc",
+    "libcef/browser/views/view_adapter.h",
+    "libcef/browser/views/view_impl.h",
+    "libcef/browser/views/view_util.cc",
+    "libcef/browser/views/view_util.h",
+    "libcef/browser/views/view_view.h",
+    "libcef/browser/views/widget_destruction_observer.h",
+    "libcef/browser/views/window_impl.cc",
+    "libcef/browser/views/window_impl.h",
+    "libcef/browser/views/window_view.cc",
+    "libcef/browser/views/window_view.h",
     "libcef/browser/x509_certificate_impl.cc",
     "libcef/browser/x509_certificate_impl.h",
     "libcef/browser/x509_cert_principal_impl.cc",
@@ -636,17 +814,25 @@
     "libcef/browser/xml_reader_impl.h",
     "libcef/browser/zip_reader_impl.cc",
     "libcef/browser/zip_reader_impl.h",
+    "libcef/common/alloy/alloy_content_client.cc",
+    "libcef/common/alloy/alloy_content_client.h",
+    "libcef/common/alloy/alloy_main_delegate.cc",
+    "libcef/common/alloy/alloy_main_delegate.h",
+    "libcef/common/alloy/alloy_main_runner_delegate.cc",
+    "libcef/common/alloy/alloy_main_runner_delegate.h",
+    "libcef/common/app_manager.cc",
+    "libcef/common/app_manager.h",
     "libcef/common/base_impl.cc",
-    "libcef/common/cef_message_generator.cc",
-    "libcef/common/cef_message_generator.h",
-    "libcef/common/cef_messages.cc",
-    "libcef/common/cef_messages.h",
     "libcef/common/cef_switches.cc",
     "libcef/common/cef_switches.h",
+    "libcef/common/chrome/chrome_content_client_cef.cc",
+    "libcef/common/chrome/chrome_content_client_cef.h",
+    "libcef/common/chrome/chrome_main_delegate_cef.cc",
+    "libcef/common/chrome/chrome_main_delegate_cef.h",
+    "libcef/common/chrome/chrome_main_runner_delegate.cc",
+    "libcef/common/chrome/chrome_main_runner_delegate.h",
     "libcef/common/command_line_impl.cc",
     "libcef/common/command_line_impl.h",
-    "libcef/common/content_client.cc",
-    "libcef/common/content_client.h",
     "libcef/common/crash_reporter_client.cc",
     "libcef/common/crash_reporter_client.h",
     "libcef/common/crash_reporting.cc",
@@ -664,44 +850,48 @@
     "libcef/common/file_util_impl.cc",
     "libcef/common/frame_util.cc",
     "libcef/common/frame_util.h",
+    "libcef/common/i18n_util_impl.cc",
     "libcef/common/json_impl.cc",
-    "libcef/common/main_delegate.cc",
-    "libcef/common/main_delegate.h",
+    "libcef/common/main_runner_delegate.h",
+    "libcef/common/main_runner_handler.h",
     "libcef/common/net/http_header_utils.cc",
     "libcef/common/net/http_header_utils.h",
     "libcef/common/net/net_resource_provider.cc",
     "libcef/common/net/net_resource_provider.h",
     "libcef/common/net/scheme_registration.cc",
     "libcef/common/net/scheme_registration.h",
-    "libcef/common/net/upload_data.cc",
-    "libcef/common/net/upload_data.h",
-    "libcef/common/net/upload_element.cc",
-    "libcef/common/net/upload_element.h",
+    "libcef/common/net/url_util.cc",
+    "libcef/common/net/url_util.h",
     "libcef/common/net_service/net_service_util.cc",
     "libcef/common/net_service/net_service_util.h",
     "libcef/common/parser_impl.cc",
     "libcef/common/process_message_impl.cc",
     "libcef/common/process_message_impl.h",
+    "libcef/common/process_message_smr_impl.cc",
+    "libcef/common/process_message_smr_impl.h",
     "libcef/common/request_impl.cc",
     "libcef/common/request_impl.h",
     "libcef/common/resource_bundle_delegate.cc",
     "libcef/common/resource_bundle_delegate.h",
     "libcef/common/resource_bundle_impl.cc",
     "libcef/common/resource_bundle_impl.h",
+    "libcef/common/resource_util.cc",
+    "libcef/common/resource_util.h",
     "libcef/common/response_impl.cc",
     "libcef/common/response_impl.h",
-    "libcef/common/response_manager.cc",
-    "libcef/common/response_manager.h",
     "libcef/common/scheme_registrar_impl.cc",
     "libcef/common/scheme_registrar_impl.h",
     "libcef/common/string_list_impl.cc",
     "libcef/common/string_map_impl.cc",
     "libcef/common/string_multimap_impl.cc",
     "libcef/common/string_types_impl.cc",
+    "libcef/common/string_util.cc",
+    "libcef/common/string_util.h",
     "libcef/common/task_impl.cc",
     "libcef/common/task_runner_impl.cc",
     "libcef/common/task_runner_impl.h",
-    "libcef/common/test/translator_test_impl.cc",
+    "libcef/common/task_runner_manager.cc",
+    "libcef/common/task_runner_manager.h",
     "libcef/common/thread_impl.cc",
     "libcef/common/thread_impl.h",
     "libcef/common/time_impl.cc",
@@ -715,12 +905,18 @@
     "libcef/common/values_impl.h",
     "libcef/common/waitable_event_impl.cc",
     "libcef/common/waitable_event_impl.h",
-    "libcef/common/widevine_loader.cc",
-    "libcef/common/widevine_loader.h",
+    "libcef/features/runtime.h",
+    "libcef/features/runtime_checks.h",
+    "libcef/renderer/alloy/alloy_content_renderer_client.cc",
+    "libcef/renderer/alloy/alloy_content_renderer_client.h",
+    "libcef/renderer/alloy/alloy_render_thread_observer.cc",
+    "libcef/renderer/alloy/alloy_render_thread_observer.h",
+    "libcef/renderer/alloy/url_loader_throttle_provider_impl.cc",
+    "libcef/renderer/alloy/url_loader_throttle_provider_impl.h",
     "libcef/renderer/browser_impl.cc",
     "libcef/renderer/browser_impl.h",
-    "libcef/renderer/content_renderer_client.cc",
-    "libcef/renderer/content_renderer_client.h",
+    "libcef/renderer/chrome/chrome_content_renderer_client_cef.cc",
+    "libcef/renderer/chrome/chrome_content_renderer_client_cef.h",
     "libcef/renderer/dom_document_impl.cc",
     "libcef/renderer/dom_document_impl.h",
     "libcef/renderer/dom_node_impl.cc",
@@ -737,23 +933,20 @@
     "libcef/renderer/render_frame_observer.h",
     "libcef/renderer/render_frame_util.cc",
     "libcef/renderer/render_frame_util.h",
-    "libcef/renderer/render_thread_observer.cc",
-    "libcef/renderer/render_thread_observer.h",
-    "libcef/renderer/render_urlrequest_impl.cc",
-    "libcef/renderer/render_urlrequest_impl.h",
+    "libcef/renderer/render_manager.cc",
+    "libcef/renderer/render_manager.h",
     "libcef/renderer/thread_util.h",
-    "libcef/renderer/url_loader_throttle_provider_impl.cc",
-    "libcef/renderer/url_loader_throttle_provider_impl.h",
     "libcef/renderer/v8_impl.cc",
     "libcef/renderer/v8_impl.h",
+
+    # For Chrome runtime support.
+    "//chrome/app/chrome_main_delegate.cc",
+    "//chrome/app/chrome_main_delegate.h",
   ]
 
   configs += [
     "libcef/features:config",
     "//build/config:precompiled_headers",
-
-    # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
-    "//build/config/compiler:no_size_t_to_int_warning",
   ]
 
   public_configs = [
@@ -768,11 +961,13 @@
   public_deps = [
     # Bring in feature flag defines.
     "//cef/libcef/features",
+    # Support relative include paths.
+    "//third_party/abseil-cpp:absl",
   ]
 
   deps = [
     ":cef_make_headers",
-    ":cef_service_manifests",
+    "libcef/common/mojom",
 
     ":libcef_static_unittested",
 
@@ -788,23 +983,24 @@
     "//base:base_static",
     "//base/third_party/dynamic_annotations",
     "//cc",
-    "//chrome/browser",
-    "//chrome/child",
-    "//chrome/common",
-    "//chrome/renderer",
+    "//chrome:dependencies",
+    "//chrome:packed_resources",
+    "//chrome:resources",
+    "//chrome:strings",
+    "//chrome/common:buildflags",
     "//chrome/services/printing:lib",
-    "//chrome/utility",
     "//components/cdm/renderer",
     "//components/certificate_transparency",
+    "//components/component_updater",
     "//components/content_settings/core/browser",
     "//components/content_settings/core/common",
     "//components/crx_file",
-    "//components/data_use_measurement/core",
     "//components/google/core/common",
     "//components/keyed_service/content:content",
     "//components/keyed_service/core:core",
+    "//components/media_router/common/mojom:media_router",
     "//components/navigation_interception",
-    "//components/network_session_configurator/browser",
+    "//components/network_session_configurator/common",
     "//components/pdf/browser",
     "//components/pdf/renderer",
     "//components/plugins/renderer",
@@ -813,7 +1009,6 @@
     "//components/printing/common",
     "//components/printing/renderer",
     "//components/proxy_config",
-    "//components/safe_browsing/core/db:test_database_manager",
     "//components/services/print_compositor/public/cpp",
     "//components/services/print_compositor/public/mojom",
     "//components/update_client",
@@ -825,7 +1020,7 @@
     "//components/visitedlink/renderer",
     "//components/viz/service",
     "//components/web_cache/renderer",
-    "//content/public/app:both",
+    "//content/public/app",
     "//content/public/browser",
     "//content/public/child",
     "//content/public/common",
@@ -835,7 +1030,6 @@
     "//crypto",
     "//device/base",
     "//extensions/browser",
-    "//extensions/browser:core_api_provider",
     "//extensions/buildflags",
     "//extensions/common/api",
     "//extensions/common:core_api_provider",
@@ -843,20 +1037,19 @@
     "//gpu",
     "//ipc",
     "//media",
-    "//media/blink",
     "//net",
     "//pdf",
     "//ppapi/buildflags",
     "//printing/buildflags",
     "//services/network:network_service",
     "//services/network/public/cpp",
-    "//services/service_manager/embedder",
     "//services/service_manager/public/cpp",
     "//skia",
     "//storage/browser",
     "//third_party/blink/public:blink",
     "//third_party/brotli:dec",
     "//third_party/cld_3/src/src:cld_3",
+    "//third_party/crashpad/crashpad/handler",
     "//third_party/hunspell",
     "//third_party/leveldatabase",
     "//third_party/libxml:libxml",
@@ -866,6 +1059,7 @@
     "//third_party/zlib:minizip",
     "//ui/base",
     "//ui/base/ime",
+    "//ui/events",
     "//ui/events:events_base",
     "//ui/gfx",
     "//ui/gfx/geometry",
@@ -873,33 +1067,20 @@
     "//ui/gfx/ipc/geometry",
     "//ui/gfx/ipc/skia",
     "//ui/gl",
+    "//ui/strings",
+    "//ui/views",
+    "//ui/views/controls/webview",
     "//url",
     "//v8",
   ]
 
   if (is_win) {
     sources += includes_win + [
-      "libcef/browser/browser_main_win.cc",
+      "libcef/browser/alloy/alloy_browser_main_win.cc",
       "libcef/browser/native/browser_platform_delegate_native_win.cc",
       "libcef/browser/native/browser_platform_delegate_native_win.h",
-      "libcef/browser/native/file_dialog_runner_win.cc",
-      "libcef/browser/native/file_dialog_runner_win.h",
-      "libcef/browser/native/javascript_dialog_runner_win.cc",
-      "libcef/browser/native/javascript_dialog_runner_win.h",
-      "libcef/browser/native/menu_2.cc",
-      "libcef/browser/native/menu_2.h",
-      "libcef/browser/native/menu_runner_win.cc",
-      "libcef/browser/native/menu_runner_win.h",
-      "libcef/browser/native/menu_wrapper.h",
-      "libcef/browser/native/native_menu_win.cc",
-      "libcef/browser/native/native_menu_win.h",
       "libcef/browser/osr/browser_platform_delegate_osr_win.cc",
       "libcef/browser/osr/browser_platform_delegate_osr_win.h",
-      "libcef/browser/osr/render_widget_host_view_osr_win.cc",
-
-      # Part of //chrome/utility.
-      "//chrome/utility/printing_handler.cc",
-      "//chrome/utility/printing_handler.h",
     ]
 
     deps += [
@@ -926,16 +1107,15 @@
     sources += includes_linux + [
       "libcef/browser/native/browser_platform_delegate_native_linux.cc",
       "libcef/browser/native/browser_platform_delegate_native_linux.h",
-      "libcef/browser/native/menu_runner_linux.cc",
-      "libcef/browser/native/menu_runner_linux.h",
       "libcef/browser/osr/browser_platform_delegate_osr_linux.cc",
       "libcef/browser/osr/browser_platform_delegate_osr_linux.h",
-      "libcef/browser/osr/render_widget_host_view_osr_linux.cc",
       "libcef/browser/printing/print_dialog_linux.cc",
       "libcef/browser/printing/print_dialog_linux.h",
+      "libcef/common/util_linux.h",
+      "libcef/common/util_linux.cc",
     ]
 
-    if (use_x11) {
+    if (ozone_platform_x11) {
       sources += [
         "libcef/browser/native/window_x11.cc",
         "libcef/browser/native/window_x11.h",
@@ -947,7 +1127,7 @@
       "//third_party/fontconfig",
     ]
 
-    if (is_linux && !use_x11) {
+    if (is_linux && !ozone_platform_x11) {
       deps += [
         "//third_party/angle:libEGL",
       ]
@@ -958,194 +1138,56 @@
     sources += includes_mac + [
       "libcef/browser/native/browser_platform_delegate_native_mac.h",
       "libcef/browser/native/browser_platform_delegate_native_mac.mm",
-      "libcef/browser/native/file_dialog_runner_mac.h",
-      "libcef/browser/native/file_dialog_runner_mac.mm",
+      "libcef/browser/native/cursor_util_mac.mm",
       "libcef/browser/native/javascript_dialog_runner_mac.h",
       "libcef/browser/native/javascript_dialog_runner_mac.mm",
       "libcef/browser/native/menu_runner_mac.h",
       "libcef/browser/native/menu_runner_mac.mm",
       "libcef/browser/osr/browser_platform_delegate_osr_mac.h",
       "libcef/browser/osr/browser_platform_delegate_osr_mac.mm",
+      "libcef/browser/views/native_widget_mac.h",
+      "libcef/browser/views/native_widget_mac.mm",
+      "libcef/browser/views/ns_window.h",
+      "libcef/browser/views/ns_window.mm",
+      "libcef/browser/views/view_util_mac.mm",
       "libcef/common/util_mac.h",
       "libcef/common/util_mac.mm",
+
+      # For Chrome runtime support.
+      "//chrome/app/chrome_main_mac.h",
+      "//chrome/app/chrome_main_mac.mm",
     ]
   }
 
-  if (is_win || is_mac) {
-    deps += [ "//third_party/crashpad/crashpad/handler" ]
-  }
-
-  if (use_x11) {
+  if (ozone_platform_x11) {
     deps += [ "//ui/events/devices/x11" ]
   }
 
-  if (is_posix && !is_mac) {
-    sources += [
-      "libcef/common/cef_crash_report_utils.cc",
-      "libcef/common/cef_crash_report_utils.h",
-    ]
-
-    deps += [
-      "//components/crash/core/app",
-      "//components/crash/content/browser",
-    ]
-  }
-
   if (v8_use_external_startup_data && use_v8_context_snapshot) {
     deps += [ "//tools/v8_context_snapshot" ]
   }
 
-  if (toolkit_views) {
-    deps += [
-      "//ui/views",
-    ]
-  }
-
   if (use_aura) {
     sources += [
-      "libcef/browser/native/window_delegate_view.cc",
-      "libcef/browser/native/window_delegate_view.h",
-      "libcef/browser/views/basic_label_button_impl.cc",
-      "libcef/browser/views/basic_label_button_impl.h",
-      "libcef/browser/views/basic_label_button_view.cc",
-      "libcef/browser/views/basic_label_button_view.h",
-      "libcef/browser/views/basic_panel_impl.cc",
-      "libcef/browser/views/basic_panel_impl.h",
-      "libcef/browser/views/basic_panel_view.cc",
-      "libcef/browser/views/basic_panel_view.h",
-      "libcef/browser/views/box_layout_impl.cc",
-      "libcef/browser/views/box_layout_impl.h",
-      "libcef/browser/views/browser_platform_delegate_views.cc",
-      "libcef/browser/views/browser_platform_delegate_views.h",
-      "libcef/browser/views/browser_view_impl.cc",
-      "libcef/browser/views/browser_view_impl.h",
-      "libcef/browser/views/browser_view_view.cc",
-      "libcef/browser/views/browser_view_view.h",
-      "libcef/browser/views/button_impl.h",
-      "libcef/browser/views/button_view.h",
-      "libcef/browser/views/display_impl.cc",
-      "libcef/browser/views/display_impl.h",
-      "libcef/browser/views/fill_layout_impl.cc",
-      "libcef/browser/views/fill_layout_impl.h",
-      "libcef/browser/views/label_button_impl.h",
-      "libcef/browser/views/label_button_view.h",
-      "libcef/browser/views/layout_impl.h",
-      "libcef/browser/views/layout_adapter.cc",
-      "libcef/browser/views/layout_adapter.h",
-      "libcef/browser/views/layout_util.cc",
-      "libcef/browser/views/layout_util.h",
-      "libcef/browser/views/menu_button_impl.cc",
-      "libcef/browser/views/menu_button_impl.h",
-      "libcef/browser/views/menu_button_view.cc",
-      "libcef/browser/views/menu_button_view.h",
-      "libcef/browser/views/menu_runner_views.cc",
-      "libcef/browser/views/menu_runner_views.h",
-      "libcef/browser/views/panel_impl.h",
-      "libcef/browser/views/panel_view.h",
-      "libcef/browser/views/scroll_view_impl.cc",
-      "libcef/browser/views/scroll_view_impl.h",
-      "libcef/browser/views/scroll_view_view.cc",
-      "libcef/browser/views/scroll_view_view.h",
-      "libcef/browser/views/textfield_impl.cc",
-      "libcef/browser/views/textfield_impl.h",
-      "libcef/browser/views/textfield_view.cc",
-      "libcef/browser/views/textfield_view.h",
-      "libcef/browser/views/view_adapter.cc",
-      "libcef/browser/views/view_adapter.h",
-      "libcef/browser/views/view_impl.h",
-      "libcef/browser/views/view_util.cc",
-      "libcef/browser/views/view_util.h",
-      "libcef/browser/views/view_view.h",
-      "libcef/browser/views/window_impl.cc",
-      "libcef/browser/views/window_impl.h",
-      "libcef/browser/views/window_view.cc",
-      "libcef/browser/views/window_view.h",
-
-      # Part of //ui/views:test_support which is testingonly.
-      "//ui/views/test/desktop_test_views_delegate.h",
-      "//ui/views/test/desktop_test_views_delegate_aura.cc",
-      "//ui/views/test/test_views_delegate.h",
-      "//ui/views/test/test_views_delegate_aura.cc",
-
-      # Support for UI input events.
-      # Part of //ui/base:test_support which is testingonly.
-      "//ui/base/test/ui_controls.h",
-      "//ui/base/test/ui_controls_aura.cc",
-      "//ui/aura/test/ui_controls_factory_aura.h",
+      "libcef/browser/native/browser_platform_delegate_native_aura.cc",
+      "libcef/browser/native/browser_platform_delegate_native_aura.h",
+      "libcef/browser/native/cursor_util_aura.cc",
+      "libcef/browser/native/menu_runner_views_aura.cc",
+      "libcef/browser/native/menu_runner_views_aura.h",
+      "libcef/browser/views/view_util_aura.cc",
     ]
 
-    if (is_linux && !use_x11) {
-      sources += [
-        "//ui/aura/test/ui_controls_factory_ozone.cc",
-        "//ui/events/test/events_test_utils.cc"
-      ]
-    }
-
     deps += [
       "//ui/aura",
-      "//ui/events",
-      "//ui/strings",
       "//ui/wm",
       "//ui/wm/public",
     ]
+  }
 
-    if (toolkit_views) {
-      deps += [
-        "//ui/views/controls/webview",
-      ]
-    }
-    
-    if (is_win) {
-      sources += [
-        # Support for UI input events.
-        # Part of //base/test:test_config which is testingonly.
-        "//base/test/test_switches.cc",
-        "//base/test/test_switches.h",
-        "//base/test/test_timeouts.cc",
-        "//base/test/test_timeouts.h",
-        # Part of //ui/aura:test_support which is testingonly.
-        "//ui/aura/test/ui_controls_factory_aurawin.cc",
-        # Part of //ui/base:test_support which is testingonly.
-        "//ui/base/test/ui_controls_internal_win.cc",
-        "//ui/base/test/ui_controls_internal_win.h",
-      ]
-    }
-
-    if (is_linux) {
-      sources += [
-        # Support for UI input events.
-        # Part of //ui/aura:test_support which is testingonly.
-        "//ui/aura/test/aura_test_utils.cc",
-        "//ui/aura/test/aura_test_utils.h",
-        # Part of //ui/events:test_support which is testingonly.
-        "//ui/events/test/x11_event_waiter.cc",
-        "//ui/events/test/x11_event_waiter.h",
-      ]
-
-      if (use_x11) {
-        sources += [
-          # Support for UI input events.
-          # Part of //ui/aura:test_support which is testingonly.
-          "//ui/aura/test/ui_controls_factory_aurax11.cc",
-          "//ui/aura/test/x11_event_sender.cc",
-          "//ui/aura/test/x11_event_sender.h",
-          # Part of //ui/views:test_support which is testingonly.
-          "//ui/views/test/ui_controls_factory_desktop_aurax11.cc",
-          "//ui/views/test/ui_controls_factory_desktop_aurax11.h",
-        ]
-      }
-    }
-
-    if (is_win || is_linux) {
-      sources += [
-        "libcef/browser/native/browser_platform_delegate_native_aura.cc",
-        "libcef/browser/native/browser_platform_delegate_native_aura.h",
-      ]
-    }
-  } else {
+  if (enable_cdm_host_verification) {
     sources += [
-      # Provides stub implementations for the views static methods.
-      "libcef_dll/views_stub.cc",
+      "libcef/common/cdm_host_file_path.cc",
+      "libcef/common/cdm_host_file_path.h",
     ]
   }
 }
@@ -1155,6 +1197,16 @@
 # libcef_dll_wrapper static targets.
 #
 
+# Configuration that will be applied to all targets that build autogen files.
+config("libcef_autogen_config") {
+  if (is_clang) {
+    cflags = [
+      # Disable clang warnings related to CEF's translation layer templates.
+      "-Wno-undefined-var-template",
+    ]
+  }
+}
+
 # Configuration that will be applied to all targets that depend on
 # libcef_dll_wrapper.
 config("libcef_dll_wrapper_config") {
@@ -1165,6 +1217,23 @@
     # They will be copied to the include/ directory in the binary distribution.
     "$root_out_dir/includes",
   ]
+
+  configs = [ ":libcef_autogen_config" ]
+
+  if (is_win) {
+    if (current_cpu == "x86") {
+      # Set the initial stack size to 0.5MiB, instead of the 1.5MiB minimum
+      # needed by CEF's main thread. This saves significant memory on threads
+      # (like those in the Windows thread pool, and others) whose stack size we
+      # can only control through this setting. The main thread (in 32-bit builds
+      # only) uses fibers to switch to a 4MiB stack at runtime via
+      # CefRunWinMainWithPreferredStackSize().
+      ldflags = [ "/STACK:0x80000" ]
+    } else {
+      # Increase the initial stack size to 8MiB from the default 1MiB.
+      ldflags = [ "/STACK:0x800000" ]
+    }
+  }
 }
 
 # libcef_dll_wrapper target.
@@ -1186,6 +1255,8 @@
 
   configs += [ ":libcef_dll_wrapper_config" ]
   public_configs = [ ":libcef_dll_wrapper_config" ]
+
+  deps = [ ":cef_make_headers" ]
 }
 
 
@@ -1198,7 +1269,7 @@
     sources = [ "libcef_dll/sandbox/sandbox_win.cc" ]
     # CEF sources use include paths relative to the CEF root directory.
     include_dirs = [ "." ]
-    deps = [ "//sandbox" ]
+    deps = [ "libcef/features", "//sandbox" ]
   }
 }
 
@@ -1207,199 +1278,31 @@
     sources = [ "libcef_dll/sandbox/sandbox_mac.mm" ]
     # CEF sources use include paths relative to the CEF root directory.
     include_dirs = [ "." ]
-    deps = [ "//sandbox/mac:seatbelt" ]
+    deps = [
+      "//build/config:executable_deps",
+      "//sandbox/mac:seatbelt"
+    ]
   }
 }
 
 #
-# Service manifests.
-#
-
-source_set("cef_content_browser_overlay_manifest") {
-  sources = [
-    "libcef/common/service_manifests/cef_content_browser_overlay_manifest.cc",
-    "libcef/common/service_manifests/cef_content_browser_overlay_manifest.h",
-  ]
-
-  configs += [
-    "libcef/features:config"
-  ]
-
-  deps = [
-    "//base",
-    "//extensions/buildflags",
-    "//extensions/common:mojom",
-    "//extensions/common/api:mojom",
-    "//services/service_manager/public/cpp",
-    "//third_party/blink/public/common",
-  ]
-}
-
-source_set("cef_content_renderer_overlay_manifest") {
-  sources = [
-    "libcef/common/service_manifests/cef_content_renderer_overlay_manifest.h",
-  ]
-
-  configs += [
-    "libcef/features:config"
-  ]
-
-  deps = [
-    "//base",
-    "//components/subresource_filter/content/mojom",
-    "//extensions/buildflags",
-    "//extensions/common:mojom",
-    "//services/service_manager/public/cpp",
-    "//third_party/blink/public/common",
-  ]
-}
-
-source_set("cef_service_manifests") {
-  public_deps = [
-    ":cef_content_browser_overlay_manifest",
-    ":cef_content_renderer_overlay_manifest",
-  ]
-}
-
-#
 # Resource grit/pack targets.
 #
 
-# Helper for generating scaled resource packs.
-template("cef_pak_scaled") {
-  percent = invoker.percent
-
-  repack("pak_${target_name}") {
-    # Each input pak file should also have a deps line for completeness.
-    # Add associated .h files in the make_pack_header("resources") target.
-    sources = [
-      "$root_gen_dir/chrome/renderer_resources_${percent}_percent.pak",
-      "$root_gen_dir/components/components_resources_${percent}_percent.pak",
-      "$root_gen_dir/content/app/resources/content_resources_${percent}_percent.pak",
-      "$root_gen_dir/extensions/extensions_browser_resources_${percent}_percent.pak",
-      "$root_gen_dir/third_party/blink/public/resources/blink_scaled_resources_${percent}_percent.pak",
-      "$root_gen_dir/ui/resources/ui_resources_${percent}_percent.pak",
-    ]
-
-    # Use public_deps so that generated grit headers are discoverable from
-    # the libcef_static target. Grit deps that generate .cc files must be
-    # listed both here and in the libcef_static target.
-    public_deps = [
-      "//chrome/renderer:resources",
-      "//components/resources:components_scaled_resources",
-      "//content/app/resources",
-      "//extensions:extensions_browser_resources",
-      "//third_party/blink/public:scaled_resources",
-      "//ui/resources:ui_resources_grd",
-    ]
-
-    deps = [
-      # This repack target generates the blink_scaled_resources_*_percent.pak
-      # file but doesn't expose the public_deps required by make_pack_header.
-      "//third_party/blink/public:scaled_resources_${percent}_percent",
-    ]
-
-    if (toolkit_views) {
-      sources += [
-        "$root_gen_dir/ui/views/resources/views_resources_${percent}_percent.pak"
-      ]
-
-      public_deps += [
-        "//ui/views/resources:resources_grd"
-      ]
-    }
-
-    output = "$root_out_dir/cef_${percent}_percent.pak"
-  }
-}
-
-# Generate cef_100_percent.pak.
-cef_pak_scaled("100_percent") {
-  percent = "100"
-}
-
-# Generate cef_200_percent.pak.
-cef_pak_scaled("200_percent") {
-  percent = "200"
-}
-
-# Generate devtools_resources.pak.
-repack("pak_devtools") {
-  # Each input pak file should also have a deps line for completeness.
-  # Add associated .h files in the make_pack_header("resources") target.
-  sources = [
-    "$root_gen_dir/content/browser/devtools/devtools_resources.pak",
-  ]
-
-  # Use public_deps so that generated grit headers are discoverable from
-  # the libcef_static target. Grit deps that generate .cc files must be
-  # listed both here and in the libcef_static target.
-  public_deps = [
-    "//content/browser/devtools:resources",
-  ]
-
-  output = "$root_out_dir/devtools_resources.pak"
-}
-
-# Generate cef_extensions.pak.
-repack("pak_extensions") {
-  # Each input pak file should also have a deps line for completeness.
-  # Add associated .h files in the make_pack_header("resources") target.
-  sources = [
-    "$root_gen_dir/chrome/component_extension_resources.pak",
-    "$root_gen_dir/content/browser/resources/media/media_internals_resources.pak",
-    "$root_gen_dir/content/browser/webrtc/resources/webrtc_internals_resources.pak",
-    "$root_gen_dir/extensions/extensions_renderer_resources.pak",
-    "$root_gen_dir/extensions/extensions_resources.pak",
-    "$root_gen_dir/mojo/public/js/mojo_bindings_resources.pak",
-    "$root_gen_dir/ui/resources/webui_resources.pak",
-  ]
-
-  # Use public_deps so that generated grit headers are discoverable from
-  # the libcef_static target. Grit deps that generate .cc files must be
-  # listed both here and in the libcef_static target.
-  public_deps = [
-    "//chrome/browser/resources:component_extension_resources",
-    "//content/browser/resources/media:media_internals_resources",
-    "//content/browser/webrtc/resources",
-    "//extensions:extensions_renderer_resources",
-    "//extensions:extensions_resources_grd",
-    "//mojo/public/js:resources",
-    "//ui/resources:webui_resources_grd",
-  ]
-
-  output = "$root_out_dir/cef_extensions.pak"
-}
-
+# Included in locales/*.pak via //chrome/chrome_repack_locales.gni.
 grit("cef_strings") {
-  visibility = [ ":*" ]
-
   source = "libcef/resources/cef_strings.grd"
   outputs = [
     "grit/cef_strings.h",
   ]
-  all_locales = locales + [ "fake-bidi" ]
+  all_locales = platform_pak_locales + [ "fake-bidi" ]
   foreach(locale, all_locales) {
     outputs += [ "cef_strings_${locale}.pak" ]
   }
 }
 
-# Generate locales/<locale>.pak.
-# See cef_repack_locales.gni for the list of input pak files and deps.
-cef_repack_locales("repack_locales_pack") {
-  visibility = [ ":*" ]
-
-  input_locales = locales
-
-  if (is_mac) {
-    output_locales = locales_as_mac_outputs
-  } else {
-    output_locales = locales
-  }
-}
-
+# Included in resources.pak via //chrome/chrome_paks.gni.
 grit("cef_resources") {
-  visibility = [ ":*" ]
   source = "libcef/resources/cef_resources.grd"
   outputs = [
     "grit/cef_resources.h",
@@ -1411,48 +1314,6 @@
   ]
 }
 
-# Generate cef.pak.
-repack("pak") {
-  # Each input pak file should also have a deps line for completeness.
-  # Add associated .h files in the make_pack_header("resources") target.
-  sources = [
-    "$root_gen_dir/chrome/browser_resources.pak",
-    "$root_gen_dir/chrome/dev_ui_browser_resources.pak",
-    "$root_gen_dir/chrome/net_internals_resources.pak",
-    "$root_gen_dir/chrome/print_preview_resources.pak",
-    "$root_gen_dir/chrome/common_resources.pak",
-    "$root_gen_dir/components/components_resources.pak",
-    "$root_gen_dir/components/dev_ui_components_resources.pak",
-    "$root_gen_dir/cef/cef_resources.pak",
-    "$root_gen_dir/content/browser/tracing/tracing_resources.pak",
-    "$root_gen_dir/content/content_resources.pak",
-    "$root_gen_dir/content/dev_ui_content_resources.pak",
-    "$root_gen_dir/net/net_resources.pak",
-    "$root_gen_dir/third_party/blink/public/resources/blink_resources.pak",
-  ]
-
-  # Use public_deps so that generated grit headers are discoverable from
-  # the libcef_static target. Grit deps that generate .cc files must be
-  # listed both here and in the libcef_static target.
-  public_deps = [
-    "//chrome/browser:dev_ui_browser_resources",
-    "//chrome/browser:resources",
-    "//chrome/browser/resources/net_internals:net_internals_resources",
-    "//chrome/browser/resources:print_preview_resources",
-    "//chrome/common:resources",
-    "//components/resources:components_resources",
-    "//components/resources:dev_ui_components_resources",
-    ":cef_resources",
-    "//content/browser/tracing:resources",
-    "//content:content_resources",
-    "//content:dev_ui_content_resources",
-    "//net:net_resources",
-    "//third_party/blink/public:resources",
-  ]
-
-  output = "$root_out_dir/cef.pak"
-}
-
 # Helper for generating pack header files.
 template("make_pack_header") {
   assert(defined(invoker.header))
@@ -1467,16 +1328,9 @@
     args = rebase_path(outputs, root_build_dir) +
            rebase_path(inputs, root_build_dir)
 
-    deps = [
-      # List all targets that generate pack files here. The grit targets that
-      # generate |inputs| will be picked up via public_deps.
-      ":pak",
-      ":pak_100_percent",
-      ":pak_200_percent",
-      ":pak_devtools",
-      ":pak_extensions",
-      ":repack_locales_pack",
-    ]
+    if (defined(invoker.deps)) {
+      deps = invoker.deps
+    }
   }
 }
 
@@ -1484,28 +1338,64 @@
 make_pack_header("resources") {
   header = "$root_out_dir/includes/include/cef_pack_resources.h"
   inputs = [
+    "$root_gen_dir/base/tracing/protos/grit/tracing_proto_resources.h",
     "$root_gen_dir/cef/grit/cef_resources.h",
     "$root_gen_dir/chrome/grit/browser_resources.h",
     "$root_gen_dir/chrome/grit/common_resources.h",
     "$root_gen_dir/chrome/grit/component_extension_resources.h",
     "$root_gen_dir/chrome/grit/dev_ui_browser_resources.h",
-    "$root_gen_dir/chrome/grit/net_internals_resources.h",
+    "$root_gen_dir/chrome/grit/pdf_resources.h",
     "$root_gen_dir/chrome/grit/renderer_resources.h",
     "$root_gen_dir/components/grit/components_resources.h",
     "$root_gen_dir/components/grit/dev_ui_components_resources.h",
     "$root_gen_dir/content/browser/devtools/grit/devtools_resources.h",
     "$root_gen_dir/content/browser/tracing/grit/tracing_resources.h",
+    "$root_gen_dir/content/browser/webrtc/resources/grit/webrtc_internals_resources.h",
     "$root_gen_dir/content/grit/content_resources.h",
-    "$root_gen_dir/content/grit/dev_ui_content_resources.h",
+    "$root_gen_dir/content/grit/gpu_resources.h",
+    "$root_gen_dir/content/grit/histograms_resources.h",
+    "$root_gen_dir/content/grit/process_resources.h",
+    "$root_gen_dir/content/grit/service_worker_resources.h",
     "$root_gen_dir/extensions/grit/extensions_browser_resources.h",
     "$root_gen_dir/extensions/grit/extensions_renderer_resources.h",
     "$root_gen_dir/extensions/grit/extensions_resources.h",
+    "$root_gen_dir/mojo/public/js/grit/mojo_bindings_resources.h",
     "$root_gen_dir/net/grit/net_resources.h",
     "$root_gen_dir/third_party/blink/public/resources/grit/blink_resources.h",
     "$root_gen_dir/ui/resources/grit/ui_resources.h",
     "$root_gen_dir/ui/resources/grit/webui_resources.h",
     "$root_gen_dir/ui/views/resources/grit/views_resources.h",
   ]
+
+  deps = [
+    ":cef_resources",
+    "//base/tracing/protos:chrome_track_event_resources",
+    "//chrome/browser:dev_ui_browser_resources",
+    "//chrome/browser:resources",
+    "//chrome/browser/resources:component_extension_resources",
+    "//chrome/browser/resources/pdf:resources",
+    "//chrome/common:resources",
+    "//chrome/renderer:resources",
+    "//components/resources:components_resources",
+    "//components/resources:dev_ui_components_resources",
+    "//content/browser/devtools:devtools_resources",
+    "//content/browser/resources/gpu:resources",
+    "//content/browser/resources/histograms:resources",
+    "//content/browser/resources/process:resources",
+    "//content/browser/resources/service_worker:resources",
+    "//content/browser/tracing:resources",
+    "//content/browser/webrtc/resources",
+    "//content:content_resources",
+    "//extensions:extensions_browser_resources",
+    "//extensions:extensions_renderer_resources",
+    "//extensions:extensions_resources_grd",
+    "//mojo/public/js:resources",
+    "//net:net_resources",
+    "//third_party/blink/public:resources",
+    "//ui/resources:ui_resources_grd",
+    "//ui/resources:webui_resources_grd",
+    "//ui/views/resources:resources_grd",
+  ]
 }
 
 # Generate cef_pack_strings.h.
@@ -1513,16 +1403,45 @@
   header = "$root_out_dir/includes/include/cef_pack_strings.h"
   inputs = [
     "$root_gen_dir/cef/grit/cef_strings.h",
-    "$root_gen_dir/chrome/grit/chromium_strings.h",
+    "$root_gen_dir/chrome/grit/branded_strings.h",
     "$root_gen_dir/chrome/grit/generated_resources.h",
     "$root_gen_dir/chrome/grit/locale_settings.h",
     "$root_gen_dir/chrome/grit/platform_locale_settings.h",
+    "$root_gen_dir/components/omnibox/resources/grit/omnibox_pedal_synonyms.h",
+    "$root_gen_dir/components/strings/grit/components_branded_strings.h",
     "$root_gen_dir/components/strings/grit/components_strings.h",
     "$root_gen_dir/extensions/strings/grit/extensions_strings.h",
     "$root_gen_dir/services/strings/grit/services_strings.h",
+    "$root_gen_dir/third_party/blink/public/strings/grit/blink_accessibility_strings.h",
     "$root_gen_dir/third_party/blink/public/strings/grit/blink_strings.h",
     "$root_gen_dir/ui/strings/grit/ui_strings.h",
   ]
+
+  deps = [
+    ":cef_strings",
+    "//chrome/app:branded_strings",
+    "//chrome/app:generated_resources",
+    "//chrome/app/resources:locale_settings",
+    "//chrome/app/resources:platform_locale_settings",
+    "//components/omnibox/resources:omnibox_pedal_synonyms",
+    "//components/strings:components_branded_strings",
+    "//components/strings:components_locale_settings",
+    "//components/strings:components_strings",
+    "//extensions/strings",
+    "//services/strings",
+    "//third_party/blink/public/strings",
+    "//third_party/blink/public/strings:accessibility_strings",
+    "//ui/strings:app_locale_settings",
+    "//ui/strings:ui_strings",
+  ]
+}
+
+# Generate cef_command_ids.h.
+make_pack_header("command_ids") {
+  header = "$root_out_dir/includes/include/cef_command_ids.h"
+  inputs = [
+    "//chrome/app/chrome_command_ids.h",
+  ]
 }
 
 # Generate cef_api_hash.h.
@@ -1542,12 +1461,23 @@
   args = rebase_path(outputs + include_dir, root_build_dir)
 }
 
+# Generate cef_config.h.
+action("make_config_header") {
+  script = "tools/make_config_header.py"
+
+  outputs = [ "$root_out_dir/includes/include/cef_config.h" ]
+
+  args = rebase_path(outputs + [ "$root_out_dir/args.gn" ], root_build_dir)
+}
+
 # Generate pack files and associated CEF header files.
 group("cef_make_headers") {
   deps = [
     ":make_pack_header_resources",
     ":make_pack_header_strings",
+    ":make_pack_header_command_ids",
     ":make_api_hash_header",
+    ":make_config_header",
   ]
 }
 
@@ -1572,50 +1502,24 @@
     ]
   }
 
-  bundle_data("cef_framework_locales") {
-    sources = []
-    foreach(locale, locales_as_mac_outputs) {
-      sources += [ "$root_gen_dir/repack/locales/$locale.pak" ]
-    }
-
-    public_deps = [
-      ":repack_locales_pack",
-    ]
-
-    outputs = [
-      "{{bundle_resources_dir}}/{{source_name_part}}.lproj/locale.pak",
-    ]
-  }
-
   bundle_data("cef_framework_resources") {
-    sources = [
-      "$root_out_dir/cef.pak",
-      "$root_out_dir/cef_100_percent.pak",
-      "$root_out_dir/cef_200_percent.pak",
-      "$root_out_dir/cef_extensions.pak",
-      "$root_out_dir/devtools_resources.pak",
-    ]
-
-    public_deps = [
-      ":pak",
-      ":pak_100_percent",
-      ":pak_200_percent",
-      ":pak_devtools",
-      ":pak_extensions",
-    ]
+    sources = []
+    public_deps = []
 
     if (icu_use_data_file) {
       sources += [ "$root_out_dir/icudtl.dat" ]
       public_deps += [ "//third_party/icu:icudata", ]
     }
 
+    sources += [ "//ui/gl/resources/angle-metal/gpu_shader_cache.bin" ]
+
     if (v8_use_external_startup_data) {
       sources += [
         "$root_out_dir/snapshot_blob.bin",
       ]
       public_deps += [ "//v8" ]
       if (use_v8_context_snapshot) {
-        sources += [ "$root_out_dir/v8_context_snapshot.bin" ]
+        sources += [ "$root_out_dir/$v8_context_snapshot_filename" ]
         public_deps += [ "//tools/v8_context_snapshot" ]
       }
     }
@@ -1643,8 +1547,6 @@
     # Add the SwiftShader .dylibs in the MODULE_DIR of the Framework app bundle.
     bundle_data("cef_framework_swiftshader_binaries") {
       sources = [
-        "$root_out_dir/egl_intermediates/libswiftshader_libEGL.dylib",
-        "$root_out_dir/egl_intermediates/libswiftshader_libGLESv2.dylib",
         "$root_out_dir/vk_intermediates/libvk_swiftshader.dylib",
         "$root_out_dir/vk_intermediates/vk_swiftshader_icd.json",
       ]
@@ -1652,7 +1554,6 @@
         "{{bundle_contents_dir}}/Libraries/{{source_file_part}}",
       ]
       public_deps = [
-        "//ui/gl:swiftshader_egl_library_copy",
         "//ui/gl:swiftshader_vk_library_copy",
       ]
     }
@@ -1675,6 +1576,9 @@
   }
 
   mac_framework_bundle("cef_framework") {
+    # Necessary because the libcef_test_support target is testonly.
+    testonly = true
+
     output_name = cef_framework_name
 
     framework_version = "A"
@@ -1691,16 +1595,16 @@
               gypi_paths2.libcef_sources_common +
               gypi_paths.autogen_library_side
 
-    # TODO(rsesek): Handle these missing pieces:
-    #   - crash_inspector
-    #   - crash_report_sender.app
-
     deps = [
       ":cef_framework_angle_library",
-      ":cef_framework_locales",
       ":cef_framework_resources",
       ":cef_framework_swiftshader_library",
       ":libcef_static",
+      ":libcef_test_support",
+    ]
+
+    configs += [
+      ":libcef_autogen_config",
     ]
 
     # We don't link the framework so just use the path from the main executable.
@@ -1726,7 +1630,19 @@
     info_plist_target = ":cef_framework_plist"
   }
 } else {
+  config("pdb_larger_than_4gb") {
+    if (is_win && symbol_level == 2) {
+      # These binaries create PDBs larger than 4 GiB. Increasing the PDB page
+      # size allows larger PDBs, but not all tools can handle such large PDBs
+      # yet.
+      ldflags = [ "/pdbpagesize:8192" ]
+    }
+  }
+
   shared_library("libcef") {
+    # Necessary because the libcef_test_support target is testonly.
+    testonly = true
+
     sources = includes_common +
               gypi_paths.autogen_cpp_includes +
               gypi_paths2.includes_capi +
@@ -1736,6 +1652,12 @@
 
     deps = [
       ":libcef_static",
+      ":libcef_test_support",
+    ]
+
+    configs += [
+      ":libcef_autogen_config",
+      ":pdb_larger_than_4gb",
     ]
 
     if (is_win) {
@@ -1743,15 +1665,19 @@
         "libcef_dll/libcef_dll.rc",
       ]
 
-      deps += [ 
+      deps += [
         # Bring in ui_unscaled_resources.rc which contains custom cursors.
         # TODO(cef): Remove this once custom cursors can be loaded via
         # ResourceBundle. See crbug.com/147663.
         "//ui/resources:ui_unscaled_resources_grd",
       ]
+
+      # Delay-load as many DLLs as possible for sandbox and startup perf
+      # improvements.
+      configs += [ "//build/config/win:delayloads" ]
     }
 
-    if (is_linux && !is_debug && use_allocator=="none") {
+    if (is_linux && !is_debug && !use_partition_alloc_as_malloc) {
       # Only export necessary symbols from libcef.so.
       # Don't do this in Debug builds because it causes the resulting
       # application to crash.
@@ -1768,6 +1694,29 @@
 # Executable/app targets.
 #
 
+# Source files for TeamCity GTest integration.
+# See tests/gtest/teamcity/README.cef for details.
+source_set("gtest_teamcity") {
+  testonly = true
+
+  sources = [
+    "tests/gtest/teamcity/include/teamcity_gtest.h",
+    "tests/gtest/teamcity/src/teamcity_gtest.cpp",
+    "tests/gtest/teamcity/src/teamcity_gtest.h",
+    "tests/gtest/teamcity/src/teamcity_messages.cpp",
+    "tests/gtest/teamcity/src/teamcity_messages.h",
+  ]
+
+  deps = [
+    "//testing/gtest",
+  ]
+
+  configs += [
+    "libcef/features:config",
+    "//build/config:precompiled_headers",
+  ]
+}
+
 if (is_mac) {
   # Helper for generating the CEF app bundle.
   template("cef_app") {
@@ -1825,13 +1774,30 @@
 
         info_plist_target = ":${app_name}_helper_plist"
 
+        if (defined(invoker.helper_frameworks)) {
+          frameworks = invoker.helper_frameworks
+        }
+
         if (defined(invoker.helper_defines)) {
           defines = invoker.helper_defines
         }
       }
     }
 
-    foreach(helper_params, content_mac_helpers) {
+    # From //chrome/BUILD.gn:
+    # Helper app to display alert notifications. This is necessary as an app can
+    # only display either banner or alert style notifications and the main app
+    # will display banners.
+    alert_helper_params = [
+      "alerts",
+      ".alerts",
+      " (Alerts)",
+    ]
+
+    # Merge all helper apps needed by //content and //chrome.
+    chrome_mac_helpers = content_mac_helpers + [ alert_helper_params ]
+
+    foreach(helper_params, chrome_mac_helpers) {
       _helper_target = helper_params[0]
       _helper_bundle_id = helper_params[1]
       _helper_suffix = helper_params[2]
@@ -1840,6 +1806,9 @@
         if (defined(invoker.helper_deps)) {
           helper_deps = invoker.helper_deps
         }
+        if (defined(invoker.helper_frameworks)) {
+          helper_frameworks = invoker.helper_frameworks
+        }
         if (defined(invoker.helper_defines)) {
           helper_defines = invoker.helper_defines
         }
@@ -1859,7 +1828,7 @@
         ":cef_framework",
       ]
 
-      foreach(helper_params, content_mac_helpers) {
+      foreach(helper_params, chrome_mac_helpers) {
         sources += [
           "$root_out_dir/${app_helper_name}${helper_params[2]}.app",
         ]
@@ -1887,7 +1856,9 @@
 
       sources = invoker.sources
 
+      public_deps = [ ":libcef_dll_wrapper" ]
       deps = [
+        ":cef_make_headers",
         ":libcef_dll_wrapper",
         ":${app_name}_framework_bundle_data",
       ]
@@ -1895,8 +1866,8 @@
         deps += invoker.deps
       }
 
-      if (defined(invoker.libs)) {
-        libs = invoker.libs
+      if (defined(invoker.frameworks)) {
+        frameworks = invoker.frameworks
       }
 
       if (defined(invoker.defines)) {
@@ -1949,6 +1920,9 @@
   }
 
   cef_app("cefclient") {
+    # Necessary because the cef_framework target is testonly.
+    testonly = true
+
     helper_info_plist = "tests/cefclient/resources/mac/helper-Info.plist"
     helper_sources = includes_common +
                      includes_mac +
@@ -1980,7 +1954,7 @@
       ":cefclient_resources_bundle_data_english",
       ":cefclient_xibs",
     ]
-    libs = [
+    frameworks = [
       "AppKit.framework",
       "OpenGL.framework",
     ]
@@ -2022,6 +1996,9 @@
   }
 
   cef_app("cefsimple") {
+    # Necessary because the cef_framework target is testonly.
+    testonly = true
+
     helper_info_plist = "tests/cefsimple/mac/helper-Info.plist"
     helper_sources = includes_common +
                      includes_mac +
@@ -2044,7 +2021,7 @@
       ":cefsimple_resources_bundle_data_english",
       ":cefsimple_xibs",
     ]
-    libs = [
+    frameworks = [
       "AppKit.framework",
     ]
     defines = [
@@ -2093,10 +2070,15 @@
                      gypi_paths2.shared_sources_mac_helper +
                      gypi_paths2.ceftests_sources_mac_helper
     helper_deps = [
+      ":gtest_teamcity",
       "//testing/gtest",
     ]
+    helper_frameworks = [
+      "AppKit.framework",
+    ]
     helper_defines = [
       "CEF_USE_SANDBOX",
+      "CEF_TESTS_IN_SRC_DIRECTORY",
     ]
 
     info_plist = "tests/ceftests/resources/mac/Info.plist"
@@ -2113,13 +2095,15 @@
       ":ceftests_resources_bundle_data",
       ":ceftests_resources_bundle_data_english",
       ":ceftests_xibs",
+      ":gtest_teamcity",
       "//testing/gtest",
     ]
-    libs = [
+    frameworks = [
       "AppKit.framework",
     ]
     defines = [
       "CEF_USE_SANDBOX",
+      "CEF_TESTS_IN_SRC_DIRECTORY",
     ]
   }
 } else {
@@ -2141,18 +2125,12 @@
     pkg_config("gtk") {
       packages = [
         "gmodule-2.0",
-        "gtk+-2.0",
+        "gtk+-3.0",
         "gthread-2.0",
-        "gtk+-unix-print-2.0",
+        "gtk+-unix-print-3.0",
         "xi",
       ]
     }
-
-    pkg_config("gtkglext") {
-      packages = [
-        "gtkglext-1.0",
-      ]
-    }
   }
 
   if (is_linux) {
@@ -2169,6 +2147,9 @@
   }
 
   executable("cefclient") {
+    # Necessary because the libcef target is testonly.
+    testonly = true
+
     sources = includes_common +
               gypi_paths2.includes_wrapper +
               gypi_paths2.shared_sources_browser +
@@ -2196,6 +2177,10 @@
       configs -= [ "//build/config/win:console" ]
       configs += [ "//build/config/win:windowed" ]
 
+      # Delay-load as many DLLs as possible for sandbox and startup perf
+      # improvements.
+      configs += [ "//build/config/win:delayloads" ]
+
       defines += [
         "CEF_USE_ATL",
       ]
@@ -2233,23 +2218,21 @@
       ]
 
       libs = [
+        "GL",
         "X11",
       ]
 
       if (cef_use_gtk) {
         configs += [
           ":gtk",
-          ":gtkglext",
+        ]
+        cflags = [
+          # Don't warn about deprecated GDK/GTK functions.
+          "-Wno-deprecated-declarations",
         ]
       }
 
-      if (is_component_build) {
-        if (use_allocator=="tcmalloc") {
-          # Link to base to initialize tcmalloc allocator shims, otherwise
-          # base::allocator::IsAllocatorInitialized check fails
-          deps += [ "//base" ]
-        }
-      } else {
+      if (!is_component_build) {
         # Set rpath to find our own libfreetype even in a non-component build.
         configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
       }
@@ -2262,6 +2245,9 @@
   #
 
   executable("cefsimple") {
+    # Necessary because the libcef target is testonly.
+    testonly = true
+
     sources = includes_common +
               gypi_paths2.includes_wrapper +
               gypi_paths2.cefsimple_sources_common
@@ -2283,6 +2269,10 @@
       configs -= [ "//build/config/win:console" ]
       configs += [ "//build/config/win:windowed" ]
 
+      # Delay-load as many DLLs as possible for sandbox and startup perf
+      # improvements.
+      configs += [ "//build/config/win:delayloads" ]
+
       deps += [
         ":cef_sandbox",
         "//build/win:default_exe_manifest",
@@ -2299,7 +2289,7 @@
       sources += includes_linux +
                  gypi_paths2.cefsimple_sources_linux
 
-      if (use_x11) {
+      if (ozone_platform_x11) {
         libs = [
           "X11",
         ]
@@ -2316,7 +2306,7 @@
   #
   # ceftests targets.
   #
-  
+
   if (is_linux) {
     copy("copy_ceftests_files") {
       sources = gypi_paths2.shared_sources_resources
@@ -2332,23 +2322,28 @@
               gypi_paths2.shared_sources_browser +
               gypi_paths2.shared_sources_common +
               gypi_paths2.shared_sources_renderer +
-              gypi_paths2.ceftests_sources_common +
-              gypi_paths2.ceftests_sources_views
+              gypi_paths2.ceftests_sources_common
 
     deps = [
       ":libcef",
       ":libcef_dll_wrapper",
+      ":gtest_teamcity",
       "//testing/gtest",
     ]
 
     defines = [
       "CEF_USE_SANDBOX",
+      "CEF_TESTS_IN_SRC_DIRECTORY",
     ]
 
     if (is_win) {
       sources += gypi_paths2.shared_sources_win +
                  gypi_paths2.ceftests_sources_win
 
+      # Delay-load as many DLLs as possible for sandbox and startup perf
+      # improvements.
+      configs += [ "//build/config/win:delayloads" ]
+
       deps += [
         ":cef_sandbox",
         "//build/win:default_exe_manifest",
@@ -2359,7 +2354,7 @@
       sources += gypi_paths2.shared_sources_linux +
                  gypi_paths2.ceftests_sources_linux
 
-      if (use_x11) {
+      if (ozone_platform_x11) {
         libs = [
           "X11",
         ]
diff --git a/src/CHROMIUM_BUILD_COMPATIBILITY.txt b/src/CHROMIUM_BUILD_COMPATIBILITY.txt
index a9d0b66..212d6c6 100644
--- a/src/CHROMIUM_BUILD_COMPATIBILITY.txt
+++ b/src/CHROMIUM_BUILD_COMPATIBILITY.txt
@@ -7,6 +7,6 @@
 # https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding
 
 {
-  'chromium_checkout': 'refs/tags/83.0.4103.106',
-  'depot_tools_checkout': 'fc5e103221'
+  'chromium_checkout': 'refs/tags/119.0.6045.199',
+  'depot_tools_checkout': '744bfd2a7b'
 }
diff --git a/src/CHROMIUM_UPDATE.txt b/src/CHROMIUM_UPDATE.txt
index 4c31f4e..5bac2ff 100644
--- a/src/CHROMIUM_UPDATE.txt
+++ b/src/CHROMIUM_UPDATE.txt
@@ -27,16 +27,12 @@
   # Files in the chromium/src directory that should be evaluated for changes.
   # Similar changes may need to be applied to the CEF source code.
   'files': [
-    'chrome/app/chrome_*_manifest.*',
-    'chrome/app/chrome_*_manifests.*',
     'chrome/browser/browser_process.h',
     'chrome/browser/extensions/api/tabs/tabs_api.*',
     'chrome/browser/extensions/chrome_component_extension_resource_manager.*',
     'chrome/browser/extensions/chrome_extension_web_contents_observer.*',
     'chrome/browser/extensions/component_loader.*',
     'chrome/browser/extensions/extension_service.*',
-    'chrome/browser/printing/print_view_manager*',
-    'chrome/browser/printing/printing_message_filter*',
     'chrome/browser/profiles/profile.h',
     'chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.*',
     'chrome/common/extensions/api/*_features.json',
@@ -45,7 +41,6 @@
     'content/browser/renderer_host/render_widget_host_view_base.*',
     'content/public/browser/content_browser_client.*',
     'content/public/browser/render_widget_host_view.h',
-    'content/public/browser/storage_partition.h',
     'content/public/browser/web_contents_delegate.h',
     'content/public/common/content_features.cc',
     'content/shell/BUILD.gn',
diff --git a/src/CMakeLists.txt.in b/src/CMakeLists.txt.in
index 120db2b..93b5f3e 100644
--- a/src/CMakeLists.txt.in
+++ b/src/CMakeLists.txt.in
@@ -11,9 +11,9 @@
 # CMake-generated project formats that have been tested with this CEF binary
 # distribution include:
 #
-# Linux:      Ninja, Unix Makefiles
-# Mac OS X:   Ninja, Xcode 5+
-# Windows:    Ninja, Visual Studio 2010+
+# Linux:      Ninja, GCC 7.5.0+, Unix Makefiles
+# MacOS:      Ninja, Xcode 12.2 to 15.0
+# Windows:    Ninja, Visual Studio 2022
 #
 # Ninja is a cross-platform open-source tool for running fast builds using
 # pre-installed platform toolchains (GNU, clang, Xcode or MSVC). It can be
@@ -36,25 +36,27 @@
 #
 # The below requirements must be met to build this CEF binary distribution.
 #
-# - CMake version 2.8.12.1 or newer.
+# - CMake version 3.21 or newer.
 #
 # - Linux requirements:
-#   Currently supported distributions include Debian Wheezy, Ubuntu Precise, and
-#   related. Ubuntu 14.04 64-bit is recommended. Newer versions will likely also
-#   work but may not have been tested.
+#   Currently supported distributions include Debian 10 (Buster), Ubuntu 18
+#   (Bionic Beaver), and related. Ubuntu 18.04 64-bit with GCC 7.5.0+ is
+#   recommended. Newer versions will likely also work but may not have been
+#   tested.
 #   Required packages include:
 #     build-essential
-#     libgtk2.0-dev     (required by the cefclient target only)
-#     libgtkglext1-dev  (required by the cefclient target only)
+#     libgtk3.0-dev     (required by the cefclient target only)
 #
-# - Mac OS X requirements:
-#   Xcode 5 or newer building on Mac OS X 10.9 (Mavericks) or newer. Xcode 8.3
-#   and OS X 10.12 are recommended. The Xcode command-line tools must also be
-#   installed. Only 64-bit builds are supported on OS X.
+# - MacOS requirements:
+#   Xcode 12.2 to 15.0 building on MacOS 10.15.4 (Catalina) or newer. Only
+#   64-bit builds are supported. The Xcode command-line tools must also be
+#   installed. Newer Xcode versions may not have been been tested and are not
+#   recommended.
 #
 # - Windows requirements:
-#   Visual Studio 2010 or newer building on Windows 7 or newer. Visual Studio
-#   2015 Update 3 and Windows 10 64-bit are recommended.
+#   Visual Studio 2022 building on Windows 10 or newer. Windows 10/11 64-bit is
+#   recommended. Newer versions will likely also work but may not have been
+#   tested.
 #
 # BUILD EXAMPLES
 #
@@ -75,7 +77,7 @@
 #     > cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug ..
 #     > ninja cefclient cefsimple
 #
-# To perform a Mac OS X build using a 64-bit CEF binary distribution:
+# To perform a MacOS build using a 64-bit CEF binary distribution:
 #   Using the Xcode IDE:
 #     > cmake -G "Xcode" -DPROJECT_ARCH="x86_64" ..
 #     Open build\cef.xcodeproj in Xcode and select Product > Build.
@@ -84,33 +86,54 @@
 #     > cmake -G "Ninja" -DPROJECT_ARCH="x86_64" -DCMAKE_BUILD_TYPE=Debug ..
 #     > ninja cefclient cefsimple
 #
+# To perform a MacOS build using an ARM64 CEF binary distribution:
+#   Using the Xcode IDE:
+#     > cmake -G "Xcode" -DPROJECT_ARCH="arm64" ..
+#     Open build\cef.xcodeproj in Xcode and select Product > Build.
+#
+#   Using Ninja:
+#     > cmake -G "Ninja" -DPROJECT_ARCH="arm64" -DCMAKE_BUILD_TYPE=Debug ..
+#     > ninja cefclient cefsimple
+#
 # To perform a Windows build using a 32-bit CEF binary distribution:
-#   Using the Visual Studio 2015 IDE:
-#     > cmake -G "Visual Studio 14" ..
+#   Using the Visual Studio 2022 IDE:
+#     > cmake -G "Visual Studio 17" -A Win32 ..
 #     Open build\cef.sln in Visual Studio and select Build > Build Solution.
 #
-#   Using Ninja with Visual Studio 2015 command-line tools:
+#   Using Ninja with Visual Studio 2022 command-line tools:
 #     (this path may be different depending on your Visual Studio installation)
-#     > "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\vcvars32.bat"
+#     > "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvars32.bat"
 #     > cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug ..
 #     > ninja cefclient cefsimple
 #
 # To perform a Windows build using a 64-bit CEF binary distribution:
-#   Using the Visual Studio 2015 IDE:
-#     > cmake -G "Visual Studio 14 Win64" ..
+#   Using the Visual Studio 2022 IDE:
+#     > cmake -G "Visual Studio 17" -A x64 ..
 #     Open build\cef.sln in Visual Studio and select Build > Build Solution.
 #
-#   Using Ninja with Visual Studio 2015 command-line tools:
+#   Using Ninja with Visual Studio 2022 command-line tools:
 #     (this path may be different depending on your Visual Studio installation)
-#     > "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat"
+#     > "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvars64.bat"
 #     > cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug ..
 #     > ninja cefclient cefsimple
+#
+# To perform a Windows build using an ARM64 CEF binary distribution:
+#   Using the Visual Studio 2022 IDE:
+#     > cmake -G "Visual Studio 17" -A arm64 ..
+#     Open build\cef.sln in Visual Studio and select Build > Build Solution.
+#
+#   Using Ninja with Visual Studio 2022 command-line tools:
+#     (this path may be different depending on your Visual Studio installation)
+#     > "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvarsamd64_arm64.bat"
+#     > cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug ..
+#     > ninja cefsimple
 
 #
 # Global setup.
 #
 
-cmake_minimum_required(VERSION 2.8.12.1)
+# For VS2022 and Xcode 12+ support.
+cmake_minimum_required(VERSION 3.21)
 
 # Only generate Debug and Release configuration types.
 set(CMAKE_CONFIGURATION_TYPES Debug Release)
@@ -211,3 +234,22 @@
 
 # Display configuration settings.
 PRINT_CEF_CONFIG()
+
+
+#
+# Define the API documentation target.
+#
+
+find_package(Doxygen)
+if(DOXYGEN_FOUND)
+  add_custom_target(apidocs ALL
+    # Generate documentation in the docs/html directory.
+    COMMAND "${DOXYGEN_EXECUTABLE}" Doxyfile
+    # Write a docs/index.html file.
+    COMMAND ${CMAKE_COMMAND} -E echo "<html><head><meta http-equiv=\"refresh\" content=\"0;URL='html/index.html'\"/></head></html>" > docs/index.html
+    WORKING_DIRECTORY "${CEF_ROOT}"
+    COMMENT "Generating API documentation with Doxygen..."
+    VERBATIM )
+else()
+  message(WARNING "Doxygen must be installed to generate API documentation.")
+endif()
diff --git a/src/Doxyfile b/src/Doxyfile
new file mode 100644
index 0000000..affddfb
--- /dev/null
+++ b/src/Doxyfile
@@ -0,0 +1,2782 @@
+# Doxyfile 1.9.5
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+#
+# Note:
+#
+# Use doxygen to compare the used configuration file with the template
+# configuration file:
+# doxygen -x [configFile]
+# Use doxygen to compare the used configuration file with the template
+# configuration file without replacing the environment variables or CMake type
+# replacement variables:
+# doxygen -x_noenv [configFile]
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = "Chromium Embedded Framework (CEF)"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         = $(PROJECT_NUMBER)
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = docs
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
+# sub-directories (in 2 levels) under the output directory of each output format
+# and will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to
+# control the number of sub-directories.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# Controls the number of sub-directories that will be created when
+# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
+# level increment doubles the number of directories, resulting in 4096
+# directories at level 8 which is the default and also the maximum value. The
+# sub-directories are organized in 2 levels, the first level always has a fixed
+# numer of 16 directories.
+# Minimum value: 0, maximum value: 8, default value: 8.
+# This tag requires that the tag CREATE_SUBDIRS is set to YES.
+
+CREATE_SUBDIRS_LEVEL   = 8
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES    = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,
+# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English
+# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,
+# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with
+# English messages), Korean, Korean-en (Korean with English messages), Latvian,
+# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese,
+# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish,
+# Swedish, Turkish, Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    = .
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = YES
+
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER         = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING       = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 2
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:^^"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". Note that you cannot put \n's in the value part of an alias
+# to insert newlines (in the resulting output). You can put ^^ in the value part
+# of an alias to insert a newline as if a physical newline was in the original
+# file. When you need a literal { or } or , in the value part of an alias you
+# have to escape them by means of a backslash (\), this can lead to conflicts
+# with the commands \{ and \} for these it is advised to use the version @{ and
+# @} or use a double escape (\\{ and \\})
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE  = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
+
+EXTENSION_MAPPING      =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS   = 5
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = YES
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which effectively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS       = 1
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL   = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
+# Possible values are: SYSTEM, NO and YES.
+# The default value is: SYSTEM.
+
+CASE_SENSE_NAMES       = SYSTEM
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
+# will show which file needs to be included to use the class.
+# The default value is: YES.
+
+SHOW_HEADERFILE        = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = YES
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file. See also section "Changing the
+# layout of pages" for information.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as documenting some parameters in
+# a documented function twice, or documenting parameters that don't exist or
+# using markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
+# function parameter documentation. If set to NO, doxygen will accept that some
+# parameters have no documentation without warning.
+# The default value is: YES.
+
+WARN_IF_INCOMPLETE_DOC = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong parameter
+# documentation, but not about the absence of documentation. If EXTRACT_ALL is
+# set to YES then this flag will automatically be disabled. See also
+# WARN_IF_INCOMPLETE_DOC
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
+# The default value is: NO.
+
+WARN_AS_ERROR          = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# See also: WARN_LINE_FORMAT
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# In the $text part of the WARN_FORMAT command it is possible that a reference
+# to a more specific place is given. To make it easier to jump to this place
+# (outside of doxygen) the user can define a custom "cut" / "paste" string.
+# Example:
+# WARN_LINE_FORMAT = "'vi $file +$line'"
+# See also: WARN_FORMAT
+# The default value is: at line $line of file $file.
+
+WARN_LINE_FORMAT       = "at line $line of file $file"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr). In case the file specified cannot be opened for writing the
+# warning and error messages are written to standard error. When as file - is
+# specified the warning and error messages are written to standard output
+# (stdout).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  = README.md \
+                         include
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
+# See also: INPUT_FILE_ENCODING
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify
+# character encoding on a per file pattern basis. Doxygen will compare the file
+# name with each pattern and apply the encoding instead of the default
+# INPUT_ENCODING) if there is a match. The character encodings are a list of the
+# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding
+# "INPUT_ENCODING" for further information on supported encodings.
+
+INPUT_FILE_ENCODING    =
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
+# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
+# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
+# *.vhdl, *.ucf, *.qsf and *.ice.
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.idl \
+                         *.ddl \
+                         *.odl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.l \
+                         *.cs \
+                         *.d \
+                         *.php \
+                         *.php4 \
+                         *.php5 \
+                         *.phtml \
+                         *.inc \
+                         *.m \
+                         *.markdown \
+                         *.md \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.pyw \
+                         *.f90 \
+                         *.f95 \
+                         *.f03 \
+                         *.f08 \
+                         *.f18 \
+                         *.f \
+                         *.for \
+                         *.vhd \
+                         *.vhdl \
+                         *.ucf \
+                         *.qsf \
+                         *.ice
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                = include/capi \
+                         include/test \
+                         include/base/internal
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = *_internal.h
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# ANamespace::AClass, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        = base::cef_subtle \
+                         base::internal \
+                         cef_trace_event \
+                         cef::logging
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that doxygen will use the data processed and written to standard output
+# for further processing, therefore nothing else, like debug statements or used
+# commands (so in case of a Windows batch file always use @echo OFF), should be
+# written to standard output.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE = README.md
+
+# The Fortran standard specifies that for fixed formatted Fortran code all
+# characters from position 72 are to be considered as comment. A common
+# extension is to allow longer lines before the automatic comment starts. The
+# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can
+# be processed before the automatic comment starts.
+# Minimum value: 7, maximum value: 10000, default value: 72.
+
+FORTRAN_COMMENT_AFTER  = 72
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# entity all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = NO
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see https://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = NO
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see:
+# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
+# performance. This can be particularly helpful with template rich C++ code for
+# which doxygen's built-in parser lacks the necessary type information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS
+# tag is set to YES then doxygen will add the directory of each input to the
+# include path.
+# The default value is: YES.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_ADD_INC_PATHS    = YES
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS          =
+
+# If clang assisted parsing is enabled you can provide the clang parser with the
+# path to the directory containing a file called compile_commands.json. This
+# file is the compilation database (see:
+# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
+# options used when the source files were built. This is equivalent to
+# specifying the -p option to a clang tool, such as clang-check. These options
+# will then be passed to the parser. Any options specified with CLANG_OPTIONS
+# will be added as well.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+
+CLANG_DATABASE_PATH    =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          = Cef \
+                         cef_
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
+# should be rendered with a dark or light theme. Default setting AUTO_LIGHT
+# enables light output unless the user preference is dark output. Other options
+# are DARK to always use dark mode, LIGHT to always use light mode, AUTO_DARK to
+# default to dark mode unless the user prefers light mode, and TOGGLE to let the
+# user toggle between dark and light mode via a button.
+# Possible values are: LIGHT Always generate light output., DARK Always generate
+# dark output., AUTO_LIGHT Automatically set the mode according to the user
+# preference, use light mode if no preference is set (the default)., AUTO_DARK
+# Automatically set the mode according to the user preference, use dark mode if
+# no preference is set. and TOGGLE Allow to user to switch between light and
+# dark mode via a button..
+# The default value is: AUTO_LIGHT.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE        = AUTO_LIGHT
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a color-wheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use gray-scales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = NO
+
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see:
+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
+# create a documentation set, doxygen will generate a Makefile in the HTML
+# output directory. Running make will produce the docset in that directory and
+# running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag determines the URL of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDURL         =
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# on Windows. In the beginning of 2021 Microsoft took the original page, with
+# a.o. the download links, offline the HTML help workshop was already many years
+# in maintenance mode). You can download the HTML help workshop from the web
+# archives at Installation executable (see:
+# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
+# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the main .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = YES
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine tune the look of the index (see "Fine-tuning the output"). As an
+# example, the default style sheet generated by doxygen has an example that
+# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
+# Since the tree basically has the same information as the tab index, you could
+# consider setting DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = YES
+
+# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
+# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
+# area (value NO) or if it should extend to the full height of the window (value
+# YES). Setting this to YES gives a layout similar to
+# https://docs.readthedocs.io with more room for contents, but less room for the
+# project logo, title, and description. If either GENERATE_TREEVIEW or
+# DISABLE_INDEX is set to NO, this option has no effect.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FULL_SIDEBAR           = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
+# addresses.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+OBFUSCATE_EMAILS       = YES
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT    = png
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
+
+FORMULA_MACROFILE      =
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
+# Note that the different versions of MathJax have different requirements with
+# regards to the different settings, so it is possible that also other MathJax
+# settings have to be changed when switching between the different MathJax
+# versions.
+# Possible values are: MathJax_2 and MathJax_3.
+# The default value is: MathJax_2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_VERSION        = MathJax_2
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. For more details about the output format see MathJax
+# version 2 (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
+# (see:
+# http://docs.mathjax.org/en/latest/web/components/output.html).
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility. This is the name for Mathjax version 2, for MathJax version 3
+# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
+# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
+# is the name for Mathjax version 3, for MathJax version 2 this will be
+# translated into HTML-CSS) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from https://www.mathjax.org before deployment. The default value is:
+# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
+# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        =
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# for MathJax version 2 (see
+# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# For example for MathJax version 3 (see
+# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
+# MATHJAX_EXTENSIONS = ams
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using JavaScript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         =
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD    = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
+# the generated LaTeX document. The header should contain everything until the
+# first chapter. If it is left blank doxygen will generate a standard header. It
+# is highly recommended to start with a default header using
+# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
+# and then modify the file new_header.tex. See also section "Doxygen usage" for
+# information on how to generate the default header that doxygen normally uses.
+#
+# Note: Only use a user-defined header if you know what you are doing!
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. The following
+# commands have a special meaning inside the header (and footer): For a
+# description of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
+# the generated LaTeX document. The footer should contain everything after the
+# last chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer. See also section "Doxygen
+# usage" for information on how to generate the default footer that doxygen
+# normally uses. Note: Only use a user-defined footer if you know what you are
+# doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP        = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR             =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to Sqlite3 output
+#---------------------------------------------------------------------------
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
+# RECURSIVE has no effect here.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             = USING_CEF_SHARED \
+                         __cplusplus \
+                         OS_WIN \
+                         OS_LINUX \
+                         CEF_X11 \
+                         OS_MAC \
+                         ARCH_CPU_32_BITS
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
+# subgraphs. When you want a differently looking font in the dot files that
+# doxygen generates you can specify fontname, fontcolor and fontsize attributes.
+# For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node,
+# Edge and Graph Attributes specification</a> You need to make sure dot is able
+# to find the font, which can be done by putting it in a standard location or by
+# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font. Default graphviz fontsize is 14.
+# The default value is: fontname=Helvetica,fontsize=10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_COMMON_ATTR        = "fontname=Helvetica,fontsize=10"
+
+# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can
+# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a
+# href=https://graphviz.org/doc/info/arrows.html>Complete documentation about
+# arrows shapes.</a>
+# The default value is: labelfontname=Helvetica,labelfontsize=10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_EDGE_ATTR          = "labelfontname=Helvetica,labelfontsize=10"
+
+# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes
+# around nodes set 'shape=plain' or 'shape=plaintext' <a
+# href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a>
+# The default value is: shape=box,height=0.2,width=0.4.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NODE_ATTR          = "shape=box,height=0.2,width=0.4"
+
+# You can set the path where dot can find font specified with fontname in
+# DOT_COMMON_ATTR and others dot attributes.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
+# graph for each documented class showing the direct and indirect inheritance
+# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
+# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
+# to TEXT the direct and indirect inheritance relations will be shown as texts /
+# links.
+# Possible values are: NO, YES, TEXT and GRAPH.
+# The default value is: YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies. See also the chapter Grouping
+# in the manual.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS        = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD     = 17
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
+# of child directories generated in directory dependency graphs by dot.
+# Minimum value: 1, maximum value: 25, default value: 1.
+# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
+
+DIR_GRAPH_MAX_DEPTH    = 1
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file or to the filename of jar file
+# to be used. If left blank, it is assumed PlantUML is not used or called during
+# a preprocessing step. Doxygen will generate a warning when it encounters a
+# \startuml command in this case and will not generate output for the diagram.
+
+PLANTUML_JAR_PATH      =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE      =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH  =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
+# graphical representation for inheritance and collaboration diagrams is used.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
+# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc temporary
+# files.
+# The default value is: YES.
+
+DOT_CLEANUP            = YES
diff --git a/src/README.md b/src/README.md
index 9b69d59..ff44f17 100644
--- a/src/README.md
+++ b/src/README.md
@@ -9,9 +9,9 @@
 * Branches and Building - https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding

 * Announcements - https://groups.google.com/forum/#!forum/cef-announce

 * Support Forum - http://www.magpcss.org/ceforum/

-* CEF1 C++ API Docs - http://magpcss.org/ceforum/apidocs/

-* CEF3 C++ API Docs - http://magpcss.org/ceforum/apidocs3/

-* Downloads - http://opensource.spotify.com/cefbuilds/index.html

+* Issue Tracker - https://github.com/chromiumembedded/cef/issues

+* C++ API Docs - [Stable release docs](https://cef-builds.spotifycdn.com/docs/stable.html) / [Beta release docs](https://cef-builds.spotifycdn.com/docs/beta.html)

+* Downloads - https://cef-builds.spotifycdn.com/index.html

 * Donations - http://www.magpcss.org/ceforum/donate.php

 

 # Introduction

@@ -29,11 +29,11 @@
 

 # Getting Started

 

-Users new to CEF development should start by reading the [Tutorial](https://bitbucket.org/chromiumembedded/cef/wiki/Tutorial) Wiki page for an overview of CEF usage and then proceed to the [GeneralUsage](https://bitbucket.org/chromiumembedded/cef/wiki/GeneralUsage) Wiki page for a more in-depth discussion or architectural and usage issues. Complete API documentation is available [here](http://magpcss.org/ceforum/apidocs3/). CEF support and related discussion is available on the [CEF Forum](http://www.magpcss.org/ceforum/).

+Users new to CEF development should start by reading the [Tutorial](https://bitbucket.org/chromiumembedded/cef/wiki/Tutorial) Wiki page for an overview of CEF usage and then proceed to the [GeneralUsage](https://bitbucket.org/chromiumembedded/cef/wiki/GeneralUsage) Wiki page for a more in-depth discussion or architectural and usage issues. Complete API documentation is available [here](https://cef-builds.spotifycdn.com/docs/stable.html). CEF support and related discussion is available on the [CEF Forum](http://www.magpcss.org/ceforum/).

 

 # Binary Distributions

 

-Binary distributions, which include all files necessary to build a CEF-based application, are available on the [Downloads](http://opensource.spotify.com/cefbuilds/index.html) page. Binary distributions are stand-alone and do not require the download of CEF or Chromium source code. Symbol files for debugging binary distributions of libcef can also be downloaded from the above links.

+Binary distributions, which include all files necessary to build a CEF-based application, are available on the [Downloads](https://cef-builds.spotifycdn.com/index.html) page. Binary distributions are stand-alone and do not require the download of CEF or Chromium source code. Symbol files for debugging binary distributions of libcef can also be downloaded from the above links.

 

 # Source Distributions

 

@@ -45,15 +45,12 @@
 

 * .Net (CEF3) - https://github.com/cefsharp/CefSharp

 * .Net (CEF1) - https://bitbucket.org/fddima/cefglue

-* .Net/Mono (CEF3) - https://bitbucket.org/xilium/xilium.cefglue

-* .Net (CEF3) - https://bitbucket.org/chromiumfx/chromiumfx

-* Delphi (CEF1) - http://code.google.com/p/delphichromiumembedded/

-* Delphi (CEF3) - https://github.com/hgourvest/dcef3

-* Delphi (CEF3) - https://github.com/salvadordf/CEF4Delphi

-* Go - https://github.com/richardwilkes/cef

+* .Net/Mono (CEF3) - https://gitlab.com/xiliumhq/chromiumembedded/cefglue

+* Delphi - https://github.com/hgourvest/dcef3

+* Delphi - https://github.com/salvadordf/CEF4Delphi

 * Go - https://github.com/CzarekTomczak/cef2go

+* Go - https://github.com/energye/energy

 * Java - https://bitbucket.org/chromiumembedded/java-cef

-* Java - http://code.google.com/p/javacef/

 * Python - http://code.google.com/p/cefpython/

 

 If you're the maintainer of a project not listed above and would like your project listed here please either post to the [CEF Forum](http://www.magpcss.org/ceforum/) or contact Marshall directly.

@@ -62,7 +59,7 @@
 

 CEF is still very much a work in progress. Some ways that you can help out:

 

-\- Vote for issues in the [CEF issue tracker](https://bitbucket.org/chromiumembedded/cef/issues?status=new&status=open) that are important to you. This helps with development prioritization.

+\- Vote for issues in the [CEF issue tracker](https://github.com/chromiumembedded/cef/issues) that are important to you. This helps with development prioritization.

 

 \- Report any bugs that you find or feature requests that are important to you. Make sure to first search for existing issues before creating new ones. Please use the [CEF Forum](http://magpcss.org/ceforum) and not the issue tracker for usage questions. Each CEF issue should:

 

@@ -73,7 +70,7 @@
 

 \- Write unit tests for new or existing functionality.

 

-\- Pull requests and patches are welcome. View open issues in the [CEF issue tracker](https://bitbucket.org/chromiumembedded/cef/issues?status=new&status=open) or search for TODO(cef) in the source code for ideas.

+\- Pull requests and patches are welcome. View open issues in the [CEF issue tracker](https://github.com/chromiumembedded/cef/issues) or search for TODO(cef) in the source code for ideas.

 

 If you would like to contribute source code changes to CEF please follow the below guidelines:

 

@@ -82,6 +79,6 @@
 \- Submit a [pull request](https://bitbucket.org/chromiumembedded/cef/wiki/ContributingWithGit) or create a patch with your changes and attach it to the CEF issue. Changes should:

 

 * Be submitted against the current [CEF master branch](https://bitbucket.org/chromiumembedded/cef/src/?at=master) unless explicitly fixing a bug in a CEF release branch.

-* Follow the style of existing CEF source files. In general CEF uses the [Chromium coding style](http://www.chromium.org/developers/coding-style).

+* Follow the style of existing CEF source files. In general CEF uses the [Chromium C++ style guide](https://chromium.googlesource.com/chromium/src/+/master/styleguide/c++/c++.md).

 * Include new or modified unit tests as appropriate to the functionality.

 * Not include unnecessary or unrelated changes.

diff --git a/src/cef_create_projects.bat b/src/cef_create_projects.bat
index 8dc7784..bc1e48b 100644
--- a/src/cef_create_projects.bat
+++ b/src/cef_create_projects.bat
@@ -1,2 +1,2 @@
 @echo off

-python.bat tools\gclient_hook.py

+python3.bat tools\gclient_hook.py

diff --git a/src/cef_create_projects.sh b/src/cef_create_projects.sh
index a9c94cd..d77c9a1 100755
--- a/src/cef_create_projects.sh
+++ b/src/cef_create_projects.sh
@@ -1,2 +1,2 @@
 #!/bin/sh
-python tools/gclient_hook.py
+python3 tools/gclient_hook.py
diff --git a/src/cef_paths.gypi b/src/cef_paths.gypi
index a972dea..6adc138 100644
--- a/src/cef_paths.gypi
+++ b/src/cef_paths.gypi
@@ -1,4 +1,4 @@
-# Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+# Copyright (c) 2023 The Chromium Embedded Framework 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,7 +8,7 @@
 # by hand. See the translator.README.txt file in the tools directory for
 # more information.
 #
-# $hash=72268a78a76d7d91b8ad47f6b6e9f6d9cb04d9cf$
+# $hash=ab931540f6f4d80336123acea6cf51e701f5a63a$
 #
 
 {
@@ -22,6 +22,7 @@
       'include/cef_browser_process_handler.h',
       'include/cef_callback.h',
       'include/cef_client.h',
+      'include/cef_command_handler.h',
       'include/cef_command_line.h',
       'include/cef_context_menu_handler.h',
       'include/cef_cookie.h',
@@ -40,6 +41,8 @@
       'include/cef_find_handler.h',
       'include/cef_focus_handler.h',
       'include/cef_frame.h',
+      'include/cef_frame_handler.h',
+      'include/cef_i18n_util.h',
       'include/cef_image.h',
       'include/cef_jsdialog_handler.h',
       'include/cef_keyboard_handler.h',
@@ -52,6 +55,8 @@
       'include/cef_origin_whitelist.h',
       'include/cef_parser.h',
       'include/cef_path_util.h',
+      'include/cef_permission_handler.h',
+      'include/cef_preference.h',
       'include/cef_print_handler.h',
       'include/cef_print_settings.h',
       'include/cef_process_message.h',
@@ -60,7 +65,6 @@
       'include/cef_render_handler.h',
       'include/cef_render_process_handler.h',
       'include/cef_request.h',
-      'include/cef_request_callback.h',
       'include/cef_request_context.h',
       'include/cef_request_context_handler.h',
       'include/cef_request_handler.h',
@@ -72,6 +76,8 @@
       'include/cef_response_filter.h',
       'include/cef_scheme.h',
       'include/cef_server.h',
+      'include/cef_shared_memory_region.h',
+      'include/cef_shared_process_message_builder.h',
       'include/cef_ssl_info.h',
       'include/cef_ssl_status.h',
       'include/cef_stream.h',
@@ -83,11 +89,11 @@
       'include/cef_v8.h',
       'include/cef_values.h',
       'include/cef_waitable_event.h',
-      'include/cef_web_plugin.h',
       'include/cef_x509_certificate.h',
       'include/cef_xml_reader.h',
       'include/cef_zip_reader.h',
       'include/test/cef_test_helpers.h',
+      'include/test/cef_test_server.h',
       'include/test/cef_translator_test.h',
       'include/views/cef_box_layout.h',
       'include/views/cef_browser_view.h',
@@ -100,6 +106,7 @@
       'include/views/cef_layout.h',
       'include/views/cef_menu_button.h',
       'include/views/cef_menu_button_delegate.h',
+      'include/views/cef_overlay_controller.h',
       'include/views/cef_panel.h',
       'include/views/cef_panel_delegate.h',
       'include/views/cef_scroll_view.h',
@@ -119,6 +126,7 @@
       'include/capi/cef_browser_process_handler_capi.h',
       'include/capi/cef_callback_capi.h',
       'include/capi/cef_client_capi.h',
+      'include/capi/cef_command_handler_capi.h',
       'include/capi/cef_command_line_capi.h',
       'include/capi/cef_context_menu_handler_capi.h',
       'include/capi/cef_cookie_capi.h',
@@ -137,6 +145,8 @@
       'include/capi/cef_find_handler_capi.h',
       'include/capi/cef_focus_handler_capi.h',
       'include/capi/cef_frame_capi.h',
+      'include/capi/cef_frame_handler_capi.h',
+      'include/capi/cef_i18n_util_capi.h',
       'include/capi/cef_image_capi.h',
       'include/capi/cef_jsdialog_handler_capi.h',
       'include/capi/cef_keyboard_handler_capi.h',
@@ -149,6 +159,8 @@
       'include/capi/cef_origin_whitelist_capi.h',
       'include/capi/cef_parser_capi.h',
       'include/capi/cef_path_util_capi.h',
+      'include/capi/cef_permission_handler_capi.h',
+      'include/capi/cef_preference_capi.h',
       'include/capi/cef_print_handler_capi.h',
       'include/capi/cef_print_settings_capi.h',
       'include/capi/cef_process_message_capi.h',
@@ -157,7 +169,6 @@
       'include/capi/cef_render_handler_capi.h',
       'include/capi/cef_render_process_handler_capi.h',
       'include/capi/cef_request_capi.h',
-      'include/capi/cef_request_callback_capi.h',
       'include/capi/cef_request_context_capi.h',
       'include/capi/cef_request_context_handler_capi.h',
       'include/capi/cef_request_handler_capi.h',
@@ -169,6 +180,8 @@
       'include/capi/cef_response_filter_capi.h',
       'include/capi/cef_scheme_capi.h',
       'include/capi/cef_server_capi.h',
+      'include/capi/cef_shared_memory_region_capi.h',
+      'include/capi/cef_shared_process_message_builder_capi.h',
       'include/capi/cef_ssl_info_capi.h',
       'include/capi/cef_ssl_status_capi.h',
       'include/capi/cef_stream_capi.h',
@@ -180,11 +193,11 @@
       'include/capi/cef_v8_capi.h',
       'include/capi/cef_values_capi.h',
       'include/capi/cef_waitable_event_capi.h',
-      'include/capi/cef_web_plugin_capi.h',
       'include/capi/cef_x509_certificate_capi.h',
       'include/capi/cef_xml_reader_capi.h',
       'include/capi/cef_zip_reader_capi.h',
       'include/capi/test/cef_test_helpers_capi.h',
+      'include/capi/test/cef_test_server_capi.h',
       'include/capi/test/cef_translator_test_capi.h',
       'include/capi/views/cef_box_layout_capi.h',
       'include/capi/views/cef_browser_view_capi.h',
@@ -197,6 +210,7 @@
       'include/capi/views/cef_layout_capi.h',
       'include/capi/views/cef_menu_button_capi.h',
       'include/capi/views/cef_menu_button_delegate_capi.h',
+      'include/capi/views/cef_overlay_controller_capi.h',
       'include/capi/views/cef_panel_capi.h',
       'include/capi/views/cef_panel_delegate_capi.h',
       'include/capi/views/cef_scroll_view_capi.h',
@@ -240,6 +254,8 @@
       'libcef_dll/cpptoc/callback_cpptoc.h',
       'libcef_dll/ctocpp/client_ctocpp.cc',
       'libcef_dll/ctocpp/client_ctocpp.h',
+      'libcef_dll/ctocpp/command_handler_ctocpp.cc',
+      'libcef_dll/ctocpp/command_handler_ctocpp.h',
       'libcef_dll/cpptoc/command_line_cpptoc.cc',
       'libcef_dll/cpptoc/command_line_cpptoc.h',
       'libcef_dll/ctocpp/completion_callback_ctocpp.cc',
@@ -300,6 +316,8 @@
       'libcef_dll/ctocpp/focus_handler_ctocpp.h',
       'libcef_dll/cpptoc/frame_cpptoc.cc',
       'libcef_dll/cpptoc/frame_cpptoc.h',
+      'libcef_dll/ctocpp/frame_handler_ctocpp.cc',
+      'libcef_dll/ctocpp/frame_handler_ctocpp.h',
       'libcef_dll/cpptoc/get_extension_resource_callback_cpptoc.cc',
       'libcef_dll/cpptoc/get_extension_resource_callback_cpptoc.h',
       'libcef_dll/cpptoc/image_cpptoc.cc',
@@ -320,6 +338,8 @@
       'libcef_dll/cpptoc/list_value_cpptoc.h',
       'libcef_dll/ctocpp/load_handler_ctocpp.cc',
       'libcef_dll/ctocpp/load_handler_ctocpp.h',
+      'libcef_dll/cpptoc/media_access_callback_cpptoc.cc',
+      'libcef_dll/cpptoc/media_access_callback_cpptoc.h',
       'libcef_dll/ctocpp/media_observer_ctocpp.cc',
       'libcef_dll/ctocpp/media_observer_ctocpp.h',
       'libcef_dll/cpptoc/media_route_cpptoc.cc',
@@ -348,16 +368,26 @@
       'libcef_dll/cpptoc/navigation_entry_cpptoc.h',
       'libcef_dll/ctocpp/navigation_entry_visitor_ctocpp.cc',
       'libcef_dll/ctocpp/navigation_entry_visitor_ctocpp.h',
+      'libcef_dll/cpptoc/views/overlay_controller_cpptoc.cc',
+      'libcef_dll/cpptoc/views/overlay_controller_cpptoc.h',
       'libcef_dll/cpptoc/views/panel_cpptoc.cc',
       'libcef_dll/cpptoc/views/panel_cpptoc.h',
       'libcef_dll/ctocpp/views/panel_delegate_ctocpp.cc',
       'libcef_dll/ctocpp/views/panel_delegate_ctocpp.h',
       'libcef_dll/ctocpp/pdf_print_callback_ctocpp.cc',
       'libcef_dll/ctocpp/pdf_print_callback_ctocpp.h',
+      'libcef_dll/ctocpp/permission_handler_ctocpp.cc',
+      'libcef_dll/ctocpp/permission_handler_ctocpp.h',
+      'libcef_dll/cpptoc/permission_prompt_callback_cpptoc.cc',
+      'libcef_dll/cpptoc/permission_prompt_callback_cpptoc.h',
       'libcef_dll/cpptoc/post_data_cpptoc.cc',
       'libcef_dll/cpptoc/post_data_cpptoc.h',
       'libcef_dll/cpptoc/post_data_element_cpptoc.cc',
       'libcef_dll/cpptoc/post_data_element_cpptoc.h',
+      'libcef_dll/cpptoc/preference_manager_cpptoc.cc',
+      'libcef_dll/cpptoc/preference_manager_cpptoc.h',
+      'libcef_dll/cpptoc/preference_registrar_cpptoc.cc',
+      'libcef_dll/cpptoc/preference_registrar_cpptoc.h',
       'libcef_dll/cpptoc/print_dialog_callback_cpptoc.cc',
       'libcef_dll/cpptoc/print_dialog_callback_cpptoc.h',
       'libcef_dll/ctocpp/print_handler_ctocpp.cc',
@@ -370,8 +400,6 @@
       'libcef_dll/cpptoc/process_message_cpptoc.h',
       'libcef_dll/ctocpp/read_handler_ctocpp.cc',
       'libcef_dll/ctocpp/read_handler_ctocpp.h',
-      'libcef_dll/ctocpp/register_cdm_callback_ctocpp.cc',
-      'libcef_dll/ctocpp/register_cdm_callback_ctocpp.h',
       'libcef_dll/cpptoc/registration_cpptoc.cc',
       'libcef_dll/cpptoc/registration_cpptoc.h',
       'libcef_dll/ctocpp/render_handler_ctocpp.cc',
@@ -380,8 +408,6 @@
       'libcef_dll/ctocpp/render_process_handler_ctocpp.h',
       'libcef_dll/cpptoc/request_cpptoc.cc',
       'libcef_dll/cpptoc/request_cpptoc.h',
-      'libcef_dll/cpptoc/request_callback_cpptoc.cc',
-      'libcef_dll/cpptoc/request_callback_cpptoc.h',
       'libcef_dll/cpptoc/request_context_cpptoc.cc',
       'libcef_dll/cpptoc/request_context_cpptoc.h',
       'libcef_dll/ctocpp/request_context_handler_ctocpp.cc',
@@ -410,6 +436,8 @@
       'libcef_dll/cpptoc/run_context_menu_callback_cpptoc.h',
       'libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.cc',
       'libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h',
+      'libcef_dll/cpptoc/run_quick_menu_callback_cpptoc.cc',
+      'libcef_dll/cpptoc/run_quick_menu_callback_cpptoc.h',
       'libcef_dll/cpptoc/sslinfo_cpptoc.cc',
       'libcef_dll/cpptoc/sslinfo_cpptoc.h',
       'libcef_dll/cpptoc/sslstatus_cpptoc.cc',
@@ -428,6 +456,10 @@
       'libcef_dll/ctocpp/server_handler_ctocpp.h',
       'libcef_dll/ctocpp/set_cookie_callback_ctocpp.cc',
       'libcef_dll/ctocpp/set_cookie_callback_ctocpp.h',
+      'libcef_dll/cpptoc/shared_memory_region_cpptoc.cc',
+      'libcef_dll/cpptoc/shared_memory_region_cpptoc.h',
+      'libcef_dll/cpptoc/shared_process_message_builder_cpptoc.cc',
+      'libcef_dll/cpptoc/shared_process_message_builder_cpptoc.h',
       'libcef_dll/cpptoc/stream_reader_cpptoc.cc',
       'libcef_dll/cpptoc/stream_reader_cpptoc.h',
       'libcef_dll/cpptoc/stream_writer_cpptoc.cc',
@@ -438,6 +470,12 @@
       'libcef_dll/ctocpp/task_ctocpp.h',
       'libcef_dll/cpptoc/task_runner_cpptoc.cc',
       'libcef_dll/cpptoc/task_runner_cpptoc.h',
+      'libcef_dll/cpptoc/test/test_server_cpptoc.cc',
+      'libcef_dll/cpptoc/test/test_server_cpptoc.h',
+      'libcef_dll/cpptoc/test/test_server_connection_cpptoc.cc',
+      'libcef_dll/cpptoc/test/test_server_connection_cpptoc.h',
+      'libcef_dll/ctocpp/test/test_server_handler_ctocpp.cc',
+      'libcef_dll/ctocpp/test/test_server_handler_ctocpp.h',
       'libcef_dll/cpptoc/views/textfield_cpptoc.cc',
       'libcef_dll/cpptoc/views/textfield_cpptoc.h',
       'libcef_dll/ctocpp/views/textfield_delegate_ctocpp.cc',
@@ -496,12 +534,6 @@
       'libcef_dll/ctocpp/views/view_delegate_ctocpp.h',
       'libcef_dll/cpptoc/waitable_event_cpptoc.cc',
       'libcef_dll/cpptoc/waitable_event_cpptoc.h',
-      'libcef_dll/cpptoc/web_plugin_info_cpptoc.cc',
-      'libcef_dll/cpptoc/web_plugin_info_cpptoc.h',
-      'libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.cc',
-      'libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.h',
-      'libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.cc',
-      'libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.h',
       'libcef_dll/cpptoc/views/window_cpptoc.cc',
       'libcef_dll/cpptoc/views/window_cpptoc.h',
       'libcef_dll/ctocpp/views/window_delegate_ctocpp.cc',
@@ -550,6 +582,8 @@
       'libcef_dll/ctocpp/callback_ctocpp.h',
       'libcef_dll/cpptoc/client_cpptoc.cc',
       'libcef_dll/cpptoc/client_cpptoc.h',
+      'libcef_dll/cpptoc/command_handler_cpptoc.cc',
+      'libcef_dll/cpptoc/command_handler_cpptoc.h',
       'libcef_dll/ctocpp/command_line_ctocpp.cc',
       'libcef_dll/ctocpp/command_line_ctocpp.h',
       'libcef_dll/cpptoc/completion_callback_cpptoc.cc',
@@ -610,6 +644,8 @@
       'libcef_dll/cpptoc/focus_handler_cpptoc.h',
       'libcef_dll/ctocpp/frame_ctocpp.cc',
       'libcef_dll/ctocpp/frame_ctocpp.h',
+      'libcef_dll/cpptoc/frame_handler_cpptoc.cc',
+      'libcef_dll/cpptoc/frame_handler_cpptoc.h',
       'libcef_dll/ctocpp/get_extension_resource_callback_ctocpp.cc',
       'libcef_dll/ctocpp/get_extension_resource_callback_ctocpp.h',
       'libcef_dll/ctocpp/image_ctocpp.cc',
@@ -630,6 +666,8 @@
       'libcef_dll/ctocpp/list_value_ctocpp.h',
       'libcef_dll/cpptoc/load_handler_cpptoc.cc',
       'libcef_dll/cpptoc/load_handler_cpptoc.h',
+      'libcef_dll/ctocpp/media_access_callback_ctocpp.cc',
+      'libcef_dll/ctocpp/media_access_callback_ctocpp.h',
       'libcef_dll/cpptoc/media_observer_cpptoc.cc',
       'libcef_dll/cpptoc/media_observer_cpptoc.h',
       'libcef_dll/ctocpp/media_route_ctocpp.cc',
@@ -658,16 +696,26 @@
       'libcef_dll/ctocpp/navigation_entry_ctocpp.h',
       'libcef_dll/cpptoc/navigation_entry_visitor_cpptoc.cc',
       'libcef_dll/cpptoc/navigation_entry_visitor_cpptoc.h',
+      'libcef_dll/ctocpp/views/overlay_controller_ctocpp.cc',
+      'libcef_dll/ctocpp/views/overlay_controller_ctocpp.h',
       'libcef_dll/ctocpp/views/panel_ctocpp.cc',
       'libcef_dll/ctocpp/views/panel_ctocpp.h',
       'libcef_dll/cpptoc/views/panel_delegate_cpptoc.cc',
       'libcef_dll/cpptoc/views/panel_delegate_cpptoc.h',
       'libcef_dll/cpptoc/pdf_print_callback_cpptoc.cc',
       'libcef_dll/cpptoc/pdf_print_callback_cpptoc.h',
+      'libcef_dll/cpptoc/permission_handler_cpptoc.cc',
+      'libcef_dll/cpptoc/permission_handler_cpptoc.h',
+      'libcef_dll/ctocpp/permission_prompt_callback_ctocpp.cc',
+      'libcef_dll/ctocpp/permission_prompt_callback_ctocpp.h',
       'libcef_dll/ctocpp/post_data_ctocpp.cc',
       'libcef_dll/ctocpp/post_data_ctocpp.h',
       'libcef_dll/ctocpp/post_data_element_ctocpp.cc',
       'libcef_dll/ctocpp/post_data_element_ctocpp.h',
+      'libcef_dll/ctocpp/preference_manager_ctocpp.cc',
+      'libcef_dll/ctocpp/preference_manager_ctocpp.h',
+      'libcef_dll/ctocpp/preference_registrar_ctocpp.cc',
+      'libcef_dll/ctocpp/preference_registrar_ctocpp.h',
       'libcef_dll/ctocpp/print_dialog_callback_ctocpp.cc',
       'libcef_dll/ctocpp/print_dialog_callback_ctocpp.h',
       'libcef_dll/cpptoc/print_handler_cpptoc.cc',
@@ -680,8 +728,6 @@
       'libcef_dll/ctocpp/process_message_ctocpp.h',
       'libcef_dll/cpptoc/read_handler_cpptoc.cc',
       'libcef_dll/cpptoc/read_handler_cpptoc.h',
-      'libcef_dll/cpptoc/register_cdm_callback_cpptoc.cc',
-      'libcef_dll/cpptoc/register_cdm_callback_cpptoc.h',
       'libcef_dll/ctocpp/registration_ctocpp.cc',
       'libcef_dll/ctocpp/registration_ctocpp.h',
       'libcef_dll/cpptoc/render_handler_cpptoc.cc',
@@ -690,8 +736,6 @@
       'libcef_dll/cpptoc/render_process_handler_cpptoc.h',
       'libcef_dll/ctocpp/request_ctocpp.cc',
       'libcef_dll/ctocpp/request_ctocpp.h',
-      'libcef_dll/ctocpp/request_callback_ctocpp.cc',
-      'libcef_dll/ctocpp/request_callback_ctocpp.h',
       'libcef_dll/ctocpp/request_context_ctocpp.cc',
       'libcef_dll/ctocpp/request_context_ctocpp.h',
       'libcef_dll/cpptoc/request_context_handler_cpptoc.cc',
@@ -720,6 +764,8 @@
       'libcef_dll/ctocpp/run_context_menu_callback_ctocpp.h',
       'libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.cc',
       'libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h',
+      'libcef_dll/ctocpp/run_quick_menu_callback_ctocpp.cc',
+      'libcef_dll/ctocpp/run_quick_menu_callback_ctocpp.h',
       'libcef_dll/ctocpp/sslinfo_ctocpp.cc',
       'libcef_dll/ctocpp/sslinfo_ctocpp.h',
       'libcef_dll/ctocpp/sslstatus_ctocpp.cc',
@@ -738,6 +784,10 @@
       'libcef_dll/cpptoc/server_handler_cpptoc.h',
       'libcef_dll/cpptoc/set_cookie_callback_cpptoc.cc',
       'libcef_dll/cpptoc/set_cookie_callback_cpptoc.h',
+      'libcef_dll/ctocpp/shared_memory_region_ctocpp.cc',
+      'libcef_dll/ctocpp/shared_memory_region_ctocpp.h',
+      'libcef_dll/ctocpp/shared_process_message_builder_ctocpp.cc',
+      'libcef_dll/ctocpp/shared_process_message_builder_ctocpp.h',
       'libcef_dll/ctocpp/stream_reader_ctocpp.cc',
       'libcef_dll/ctocpp/stream_reader_ctocpp.h',
       'libcef_dll/ctocpp/stream_writer_ctocpp.cc',
@@ -748,6 +798,12 @@
       'libcef_dll/cpptoc/task_cpptoc.h',
       'libcef_dll/ctocpp/task_runner_ctocpp.cc',
       'libcef_dll/ctocpp/task_runner_ctocpp.h',
+      'libcef_dll/ctocpp/test/test_server_ctocpp.cc',
+      'libcef_dll/ctocpp/test/test_server_ctocpp.h',
+      'libcef_dll/ctocpp/test/test_server_connection_ctocpp.cc',
+      'libcef_dll/ctocpp/test/test_server_connection_ctocpp.h',
+      'libcef_dll/cpptoc/test/test_server_handler_cpptoc.cc',
+      'libcef_dll/cpptoc/test/test_server_handler_cpptoc.h',
       'libcef_dll/ctocpp/views/textfield_ctocpp.cc',
       'libcef_dll/ctocpp/views/textfield_ctocpp.h',
       'libcef_dll/cpptoc/views/textfield_delegate_cpptoc.cc',
@@ -806,12 +862,6 @@
       'libcef_dll/cpptoc/views/view_delegate_cpptoc.h',
       'libcef_dll/ctocpp/waitable_event_ctocpp.cc',
       'libcef_dll/ctocpp/waitable_event_ctocpp.h',
-      'libcef_dll/ctocpp/web_plugin_info_ctocpp.cc',
-      'libcef_dll/ctocpp/web_plugin_info_ctocpp.h',
-      'libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.cc',
-      'libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.h',
-      'libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.cc',
-      'libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.h',
       'libcef_dll/ctocpp/views/window_ctocpp.cc',
       'libcef_dll/ctocpp/views/window_ctocpp.h',
       'libcef_dll/cpptoc/views/window_delegate_cpptoc.cc',
diff --git a/src/cef_paths2.gypi b/src/cef_paths2.gypi
index 0d5d3c3..9a5b227 100644
--- a/src/cef_paths2.gypi
+++ b/src/cef_paths2.gypi
@@ -5,26 +5,24 @@
 {
   'variables': {
     'includes_common': [
+      'include/base/cef_atomic_flag.h',
       'include/base/cef_atomic_ref_count.h',
-      'include/base/cef_atomicops.h',
-      'include/base/cef_basictypes.h',
+      'include/base/cef_auto_reset.h',
       'include/base/cef_bind.h',
-      'include/base/cef_bind_helpers.h',
       'include/base/cef_build.h',
       'include/base/cef_callback.h',
       'include/base/cef_callback_forward.h',
       'include/base/cef_callback_helpers.h',
       'include/base/cef_callback_list.h',
       'include/base/cef_cancelable_callback.h',
+      'include/base/cef_compiler_specific.h',
       'include/base/cef_lock.h',
       'include/base/cef_logging.h',
       'include/base/cef_macros.h',
-      'include/base/cef_move.h',
       'include/base/cef_platform_thread.h',
+      'include/base/cef_ptr_util.h',
       'include/base/cef_ref_counted.h',
-      'include/base/cef_scoped_ptr.h',
-      'include/base/cef_string16.h',
-      'include/base/cef_template_util.h',
+      'include/base/cef_scoped_refptr.h',
       'include/base/cef_thread_checker.h',
       'include/base/cef_trace_event.h',
       'include/base/cef_tuple.h',
@@ -33,14 +31,15 @@
       'include/base/internal/cef_callback_internal.h',
       'include/base/internal/cef_lock_impl.h',
       'include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h',
+      'include/base/internal/cef_scoped_policy.h',
       'include/base/internal/cef_thread_checker_impl.h',
       'include/cef_api_hash.h',
       'include/cef_base.h',
-      'include/cef_config.h',
       'include/cef_version.h',
       'include/internal/cef_export.h',
       'include/internal/cef_ptr.h',
       'include/internal/cef_string_wrappers.h',
+      'include/internal/cef_time_wrappers.h',
       'include/internal/cef_types_wrappers.h',
     ],
     'includes_common_capi': [
@@ -54,6 +53,8 @@
       'include/internal/cef_time.h',
       'include/internal/cef_trace_event_internal.h',
       'include/internal/cef_types.h',
+      'include/internal/cef_types_content_settings.h',
+      'include/internal/cef_types_geometry.h',
     ],
     'includes_capi': [
       'include/capi/cef_base_capi.h',
@@ -73,18 +74,16 @@
       'include/wrapper/cef_library_loader.h',
     ],
     'includes_win': [
-      'include/base/internal/cef_atomicops_arm64_msvc.h',
-      'include/base/internal/cef_atomicops_x86_msvc.h',
-      'include/base/internal/cef_bind_internal_win.h',
       'include/cef_sandbox_win.h',
       'include/internal/cef_win.h',
     ],
     'includes_win_capi': [
+      'include/internal/cef_app_win.h',
       'include/internal/cef_types_win.h',
     ],
     'includes_mac': [
-      'include/base/internal/cef_atomicops_atomicword_compat.h',
-      'include/base/internal/cef_atomicops_mac.h',
+      'include/base/cef_scoped_typeref_mac.h',
+      'include/base/internal/cef_scoped_block_mac.h',
       'include/cef_application_mac.h',
       'include/cef_sandbox_mac.h',
       'include/internal/cef_mac.h',
@@ -93,10 +92,6 @@
       'include/internal/cef_types_mac.h',
     ],
     'includes_linux': [
-      'include/base/internal/cef_atomicops_atomicword_compat.h',
-      'include/base/internal/cef_atomicops_arm_gcc.h',
-      'include/base/internal/cef_atomicops_arm64_gcc.h',
-      'include/base/internal/cef_atomicops_x86_gcc.h',
       'include/internal/cef_linux.h',
     ],
     'includes_linux_capi': [
@@ -117,20 +112,19 @@
       'libcef_dll/resource.h',
       'libcef_dll/shutdown_checker.cc',
       'libcef_dll/shutdown_checker.h',
+      'libcef_dll/template_util.h',
       'libcef_dll/transfer_util.cc',
       'libcef_dll/transfer_util.h',
       'libcef_dll/wrapper_types.h',
     ],
     'libcef_dll_wrapper_sources_base': [
-      'libcef_dll/base/cef_atomicops_x86_gcc.cc',
-      'libcef_dll/base/cef_bind_helpers.cc',
+      'libcef_dll/base/cef_atomic_flag.cc',
       'libcef_dll/base/cef_callback_helpers.cc',
       'libcef_dll/base/cef_callback_internal.cc',
       'libcef_dll/base/cef_lock.cc',
       'libcef_dll/base/cef_lock_impl.cc',
       'libcef_dll/base/cef_logging.cc',
       'libcef_dll/base/cef_ref_counted.cc',
-      'libcef_dll/base/cef_string16.cc',
       'libcef_dll/base/cef_thread_checker_impl.cc',
       'libcef_dll/base/cef_weak_ptr.cc',
     ],
@@ -143,9 +137,9 @@
       'libcef_dll/cpptoc/cpptoc_scoped.h',
       'libcef_dll/ctocpp/ctocpp_ref_counted.h',
       'libcef_dll/ctocpp/ctocpp_scoped.h',
-      'libcef_dll/ptr_util.h',
       'libcef_dll/shutdown_checker.cc',
       'libcef_dll/shutdown_checker.h',
+      'libcef_dll/template_util.h',
       'libcef_dll/transfer_util.cc',
       'libcef_dll/transfer_util.h',
       'libcef_dll/wrapper_types.h',
@@ -153,6 +147,8 @@
       'libcef_dll/wrapper/cef_byte_read_handler.cc',
       'libcef_dll/wrapper/cef_closure_task.cc',
       'libcef_dll/wrapper/cef_message_router.cc',
+      'libcef_dll/wrapper/cef_message_router_utils.cc',
+      'libcef_dll/wrapper/cef_message_router_utils.h',
       'libcef_dll/wrapper/cef_resource_manager.cc',
       'libcef_dll/wrapper/cef_scoped_temp_dir.cc',
       'libcef_dll/wrapper/cef_stream_resource_handler.cc',
@@ -183,12 +179,16 @@
       'tests/shared/browser/resource_util.h',
     ],
     'shared_sources_common': [
+      'tests/shared/common/binary_value_utils.cc',
+      'tests/shared/common/binary_value_utils.h',
       'tests/shared/common/client_app.cc',
       'tests/shared/common/client_app.h',
       'tests/shared/common/client_app_other.cc',
       'tests/shared/common/client_app_other.h',
       'tests/shared/common/client_switches.cc',
       'tests/shared/common/client_switches.h',
+      'tests/shared/common/string_util.cc',
+      'tests/shared/common/string_util.h',
     ],
     'shared_sources_renderer': [
       'tests/shared/renderer/client_app_renderer.cc',
@@ -220,6 +220,8 @@
       'tests/shared/browser/util_win.h',
     ],
     'cefclient_sources_browser': [
+      'tests/cefclient/browser/binary_transfer_test.cc',
+      'tests/cefclient/browser/binary_transfer_test.h',
       'tests/cefclient/browser/binding_test.cc',
       'tests/cefclient/browser/binding_test.h',
       'tests/cefclient/browser/browser_window.cc',
@@ -235,11 +237,13 @@
       'tests/cefclient/browser/client_handler_osr.h',
       'tests/cefclient/browser/client_handler_std.cc',
       'tests/cefclient/browser/client_handler_std.h',
+      'tests/cefclient/browser/client_prefs.cc',
+      'tests/cefclient/browser/client_prefs.h',
       'tests/cefclient/browser/client_types.h',
+      'tests/cefclient/browser/default_client_handler.cc',
+      'tests/cefclient/browser/default_client_handler.h',
       'tests/cefclient/browser/dialog_test.cc',
       'tests/cefclient/browser/dialog_test.h',
-      'tests/cefclient/browser/drm_test.cc',
-      'tests/cefclient/browser/drm_test.h',
       'tests/cefclient/browser/image_cache.cc',
       'tests/cefclient/browser/image_cache.h',
       'tests/cefclient/browser/main_context.cc',
@@ -262,6 +266,8 @@
       'tests/cefclient/browser/root_window_create.cc',
       'tests/cefclient/browser/root_window_manager.cc',
       'tests/cefclient/browser/root_window_manager.h',
+      'tests/cefclient/browser/root_window_views.cc',
+      'tests/cefclient/browser/root_window_views.h',
       'tests/cefclient/browser/scheme_test.cc',
       'tests/cefclient/browser/scheme_test.h',
       'tests/cefclient/browser/server_test.cc',
@@ -271,10 +277,20 @@
       'tests/cefclient/browser/test_runner.h',
       'tests/cefclient/browser/urlrequest_test.cc',
       'tests/cefclient/browser/urlrequest_test.h',
+      'tests/cefclient/browser/views_menu_bar.cc',
+      'tests/cefclient/browser/views_menu_bar.h',
+      'tests/cefclient/browser/views_overlay_controls.cc',
+      'tests/cefclient/browser/views_overlay_controls.h',
+      'tests/cefclient/browser/views_style.cc',
+      'tests/cefclient/browser/views_style.h',
+      'tests/cefclient/browser/views_window.cc',
+      'tests/cefclient/browser/views_window.h',
       'tests/cefclient/browser/window_test.cc',
       'tests/cefclient/browser/window_test.h',
       'tests/cefclient/browser/window_test_runner.cc',
       'tests/cefclient/browser/window_test_runner.h',
+      'tests/cefclient/browser/window_test_runner_views.cc',
+      'tests/cefclient/browser/window_test_runner_views.h',
     ],
     'cefclient_sources_common': [
       'tests/cefclient/common/client_app_delegates_common.cc',
@@ -285,6 +301,8 @@
       'tests/cefclient/renderer/client_app_delegates_renderer.cc',
       'tests/cefclient/renderer/client_renderer.cc',
       'tests/cefclient/renderer/client_renderer.h',
+      'tests/cefclient/renderer/ipc_performance_test.cc',
+      'tests/cefclient/renderer/ipc_performance_test.h',
       'tests/cefclient/renderer/performance_test.cc',
       'tests/cefclient/renderer/performance_test.h',
       'tests/cefclient/renderer/performance_test_setup.h',
@@ -294,7 +312,8 @@
       'tests/cefclient/resources/binding.html',
       'tests/cefclient/resources/dialogs.html',
       'tests/cefclient/resources/draggable.html',
-      'tests/cefclient/resources/drm.html',
+      'tests/cefclient/resources/ipc_performance.html',
+      'tests/cefclient/resources/binary_transfer.html',
       'tests/cefclient/resources/localstorage.html',
       'tests/cefclient/resources/logo.png',
       'tests/cefclient/resources/media_router.html',
@@ -347,20 +366,10 @@
       'tests/cefclient/browser/osr_window_win.cc',
       'tests/cefclient/browser/osr_window_win.h',
       'tests/cefclient/browser/resource_util_win_idmap.cc',
-      'tests/cefclient/browser/root_window_views.cc',
-      'tests/cefclient/browser/root_window_views.h',
       'tests/cefclient/browser/root_window_win.cc',
       'tests/cefclient/browser/root_window_win.h',
       'tests/cefclient/browser/temp_window_win.cc',
       'tests/cefclient/browser/temp_window_win.h',
-      'tests/cefclient/browser/views_menu_bar.cc',
-      'tests/cefclient/browser/views_menu_bar.h',
-      'tests/cefclient/browser/views_style.cc',
-      'tests/cefclient/browser/views_style.h',
-      'tests/cefclient/browser/views_window.cc',
-      'tests/cefclient/browser/views_window.h',
-      'tests/cefclient/browser/window_test_runner_views.cc',
-      'tests/cefclient/browser/window_test_runner_views.h',
       'tests/cefclient/browser/window_test_runner_win.cc',
       'tests/cefclient/browser/window_test_runner_win.h',
       'tests/cefclient/cefclient_win.cc',
@@ -388,6 +397,7 @@
       'tests/cefclient/browser/temp_window_mac.mm',
       'tests/cefclient/browser/text_input_client_osr_mac.h',
       'tests/cefclient/browser/text_input_client_osr_mac.mm',
+      'tests/cefclient/browser/views_window_mac.mm',
       'tests/cefclient/browser/window_test_runner_mac.h',
       'tests/cefclient/browser/window_test_runner_mac.mm',
       'tests/cefclient/cefclient_mac.mm',
@@ -413,22 +423,12 @@
       'tests/cefclient/browser/resource_util_linux.cc',
       'tests/cefclient/browser/root_window_gtk.cc',
       'tests/cefclient/browser/root_window_gtk.h',
-      'tests/cefclient/browser/root_window_views.cc',
-      'tests/cefclient/browser/root_window_views.h',
       'tests/cefclient/browser/temp_window_x11.cc',
       'tests/cefclient/browser/temp_window_x11.h',
       'tests/cefclient/browser/util_gtk.cc',
       'tests/cefclient/browser/util_gtk.h',
-      'tests/cefclient/browser/views_menu_bar.cc',
-      'tests/cefclient/browser/views_menu_bar.h',
-      'tests/cefclient/browser/views_style.cc',
-      'tests/cefclient/browser/views_style.h',
-      'tests/cefclient/browser/views_window.cc',
-      'tests/cefclient/browser/views_window.h',
       'tests/cefclient/browser/window_test_runner_gtk.cc',
       'tests/cefclient/browser/window_test_runner_gtk.h',
-      'tests/cefclient/browser/window_test_runner_views.cc',
-      'tests/cefclient/browser/window_test_runner_views.h',
       'tests/cefclient/cefclient_gtk.cc',
     ],
     'cefsimple_sources_common': [
@@ -465,11 +465,19 @@
       'tests/cefsimple/cefsimple_linux.cc',
       'tests/cefsimple/simple_handler_linux.cc',
     ],
+    'ceftests_data_resources': [
+      'tests/ceftests/resources/net/data/ssl/certificates/expired_cert.pem',
+      'tests/ceftests/resources/net/data/ssl/certificates/localhost_cert.pem',
+      'tests/ceftests/resources/net/data/ssl/certificates/ok_cert.pem',
+      'tests/ceftests/resources/net/data/ssl/certificates/root_ca_cert.pem',
+    ],
     'ceftests_sources_common': [
       'tests/ceftests/audio_output_unittest.cc',
       'tests/ceftests/browser_info_map_unittest.cc',
+      'tests/ceftests/certificate_error_unittest.cc',
       'tests/ceftests/command_line_unittest.cc',
       'tests/ceftests/cookie_unittest.cc',
+      'tests/ceftests/cors_unittest.cc',
       'tests/ceftests/devtools_message_unittest.cc',
       'tests/ceftests/dialog_unittest.cc',
       'tests/ceftests/display_unittest.cc',
@@ -484,19 +492,29 @@
       'tests/ceftests/extensions/extension_test_handler.h',
       'tests/ceftests/extensions/view_unittest.cc',
       'tests/ceftests/file_util_unittest.cc',
+      'tests/ceftests/frame_handler_unittest.cc',
       'tests/ceftests/frame_unittest.cc',
+      'tests/ceftests/hsts_redirect_unittest.cc',
       'tests/ceftests/image_unittest.cc',
       'tests/ceftests/image_util.cc',
       'tests/ceftests/image_util.h',
       'tests/ceftests/jsdialog_unittest.cc',
       'tests/ceftests/life_span_unittest.cc',
-      'tests/ceftests/message_router_unittest.cc',
+      'tests/ceftests/media_access_unittest.cc',
+      'tests/ceftests/message_router_binary_unittest.cc',
+      'tests/ceftests/message_router_harness_unittest.cc',
+      'tests/ceftests/message_router_multi_query_unittest.cc',
+      'tests/ceftests/message_router_single_query_unittest.cc',
+      'tests/ceftests/message_router_threshold_unittest.cc',
+      'tests/ceftests/message_router_unittest_utils.cc',
+      'tests/ceftests/message_router_unittest_utils.h',
       'tests/ceftests/navigation_unittest.cc',
       'tests/ceftests/os_rendering_unittest.cc',
       'tests/ceftests/osr_accessibility_unittest.cc',
       'tests/ceftests/osr_display_unittest.cc',
       'tests/ceftests/parser_unittest.cc',
-      'tests/ceftests/plugin_unittest.cc',
+      'tests/ceftests/pdf_viewer_unittest.cc',
+      'tests/ceftests/permission_prompt_unittest.cc',
       'tests/ceftests/preference_unittest.cc',
       'tests/ceftests/print_unittest.cc',
       'tests/ceftests/process_message_unittest.cc',
@@ -513,6 +531,8 @@
       'tests/ceftests/scheme_handler_unittest.cc',
       'tests/ceftests/scoped_temp_dir_unittest.cc',
       'tests/ceftests/server_unittest.cc',
+      'tests/ceftests/send_shared_process_message_unittest.cc',
+      "tests/ceftests/shared_process_message_unittest.cc",
       'tests/ceftests/stream_unittest.cc',
       'tests/ceftests/stream_resource_handler_unittest.cc',
       'tests/ceftests/string_unittest.cc',
@@ -520,25 +540,35 @@
       'tests/ceftests/task_unittest.cc',
       'tests/ceftests/test_handler.cc',
       'tests/ceftests/test_handler.h',
+      'tests/ceftests/test_request.cc',
+      'tests/ceftests/test_request.h',
+      'tests/ceftests/test_server.cc',
+      'tests/ceftests/test_server.h',
+      'tests/ceftests/test_server_observer.h',
+      'tests/ceftests/test_server_observer.cc',
+      'tests/ceftests/test_server_observer_unittest.cc',
+      'tests/ceftests/test_server_manager.h',
+      'tests/ceftests/test_server_manager.cc',
+      'tests/ceftests/test_server_runner.h',
+      'tests/ceftests/test_server_runner.cc',
+      'tests/ceftests/test_server_runner_normal.cc',
+      'tests/ceftests/test_server_runner_test.cc',
+      'tests/ceftests/test_server_unittest.cc',
       'tests/ceftests/test_suite.cc',
       'tests/ceftests/test_suite.h',
       'tests/ceftests/test_util.cc',
       'tests/ceftests/test_util.h',
+      'tests/ceftests/time_unittest.cc',
       'tests/ceftests/thread_helper.cc',
       'tests/ceftests/thread_helper.h',
       'tests/ceftests/thread_unittest.cc',
       'tests/ceftests/tracing_unittest.cc',
+      'tests/ceftests/track_callback.h',
       'tests/ceftests/translator_unittest.cc',
       'tests/ceftests/urlrequest_unittest.cc',
       'tests/ceftests/v8_unittest.cc',
       'tests/ceftests/values_unittest.cc',
       'tests/ceftests/version_unittest.cc',
-      'tests/ceftests/waitable_event_unittest.cc',
-      'tests/ceftests/webui_unittest.cc',
-      'tests/ceftests/xml_reader_unittest.cc',
-      'tests/ceftests/zip_reader_unittest.cc',
-    ],
-    'ceftests_sources_views': [
       'tests/ceftests/views/button_unittest.cc',
       'tests/ceftests/views/panel_unittest.cc',
       'tests/ceftests/views/scroll_view_unittest.cc',
@@ -546,8 +576,13 @@
       'tests/ceftests/views/test_window_delegate.h',
       'tests/ceftests/views/textfield_unittest.cc',
       'tests/ceftests/views/window_unittest.cc',
+      'tests/ceftests/waitable_event_unittest.cc',
+      'tests/ceftests/webui_unittest.cc',
+      'tests/ceftests/xml_reader_unittest.cc',
+      'tests/ceftests/zip_reader_unittest.cc',
     ],
     'ceftests_sources_win': [
+      'tests/ceftests/resource_util_win_dir.cc',
       'tests/ceftests/resource_util_win_idmap.cc',
       'tests/ceftests/resources/win/ceftests.rc',
     ],
@@ -570,11 +605,20 @@
       'tests/ceftests/audio_output_unittest.cc',
       'tests/ceftests/client_app_delegates.cc',
       'tests/ceftests/cookie_unittest.cc',
+      'tests/ceftests/cors_unittest.cc',
       'tests/ceftests/dom_unittest.cc',
       'tests/ceftests/frame_unittest.cc',
-      'tests/ceftests/message_router_unittest.cc',
+      'tests/ceftests/media_access_unittest.cc',
+      'tests/ceftests/message_router_binary_unittest.cc',
+      'tests/ceftests/message_router_harness_unittest.cc',
+      'tests/ceftests/message_router_multi_query_unittest.cc',
+      'tests/ceftests/message_router_single_query_unittest.cc',
+      'tests/ceftests/message_router_threshold_unittest.cc',
+      'tests/ceftests/message_router_unittest_utils.cc',
+      'tests/ceftests/message_router_unittest_utils.h',
       'tests/ceftests/navigation_unittest.cc',
-      'tests/ceftests/plugin_unittest.cc',
+      'tests/ceftests/pdf_viewer_unittest.cc',
+      'tests/ceftests/permission_prompt_unittest.cc',
       'tests/ceftests/preference_unittest.cc',
       'tests/ceftests/process_message_unittest.cc',
       'tests/ceftests/request_handler_unittest.cc',
@@ -584,13 +628,28 @@
       'tests/ceftests/routing_test_handler.cc',
       'tests/ceftests/routing_test_handler.h',
       'tests/ceftests/scheme_handler_unittest.cc',
+      'tests/ceftests/send_shared_process_message_unittest.cc',
+      "tests/ceftests/shared_process_message_unittest.cc",
       'tests/ceftests/urlrequest_unittest.cc',
       'tests/ceftests/test_handler.cc',
       'tests/ceftests/test_handler.h',
+      'tests/ceftests/test_request.cc',
+      'tests/ceftests/test_request.h',
+      'tests/ceftests/test_server.cc',
+      'tests/ceftests/test_server.h',
+      'tests/ceftests/test_server_observer.h',
+      'tests/ceftests/test_server_observer.cc',
+      'tests/ceftests/test_server_manager.h',
+      'tests/ceftests/test_server_manager.cc',
+      'tests/ceftests/test_server_runner.h',
+      'tests/ceftests/test_server_runner.cc',
+      'tests/ceftests/test_server_runner_normal.cc',
+      'tests/ceftests/test_server_runner_test.cc',
       'tests/ceftests/test_suite.cc',
       'tests/ceftests/test_suite.h',
       'tests/ceftests/test_util.cc',
       'tests/ceftests/test_util.h',
+      'tests/ceftests/track_callback.h',
       'tests/ceftests/thread_helper.cc',
       'tests/ceftests/thread_helper.h',
       'tests/ceftests/thread_unittest.cc',
diff --git a/src/cef_repack_locales.gni b/src/cef_repack_locales.gni
deleted file mode 100644
index 51e9189..0000000
--- a/src/cef_repack_locales.gni
+++ /dev/null
@@ -1,132 +0,0 @@
-# Copyright 2016 The Chromium Embedded Framework Authors. Portions copyright
-# 2014 the Chromium Authors. All rights reserved. Use of this source code is
-# governed by a BSD-style license that can be found in the LICENSE file.
-#
-# This is a copy of src/chrome/chrome_repack_locales.gni with the necessary
-# modifications to meet CEF's requirements.
-
-import("//build/config/chrome_build.gni")
-import("//build/config/features.gni")
-import("//build/config/ui.gni")
-import("//tools/grit/repack.gni")
-
-# Arguments:
-#
-#   locale
-#       Internal name of locale. e.g. "pt-BR"
-#
-#   output
-#       Output file name.
-#
-#   visibility
-#       Normal meaning.
-template("_repack_one_locale") {
-  locale = invoker.locale
-
-  repack(target_name) {
-    visibility = invoker.visibility
-
-    # Each input pak file should also have a deps line for completeness.
-    # Add associated .h files in the make_pack_header("strings") target.
-    sources = [
-      "${root_gen_dir}/cef/cef_strings_${locale}.pak",
-      "${root_gen_dir}/chrome/chromium_strings_${locale}.pak",
-      "${root_gen_dir}/chrome/generated_resources_${locale}.pak",
-      "${root_gen_dir}/chrome/locale_settings_${locale}.pak",
-      "${root_gen_dir}/chrome/platform_locale_settings_${locale}.pak",
-      "${root_gen_dir}/components/strings/components_locale_settings_${locale}.pak",
-      "${root_gen_dir}/components/strings/components_strings_${locale}.pak",
-      "${root_gen_dir}/extensions/strings/extensions_strings_${locale}.pak",
-      "${root_gen_dir}/services/strings/services_strings_${locale}.pak",
-      "${root_gen_dir}/third_party/blink/public/strings/blink_strings_${locale}.pak",
-      "${root_gen_dir}/ui/strings/app_locale_settings_${locale}.pak",
-      "${root_gen_dir}/ui/strings/ui_strings_${locale}.pak",
-    ]
-
-    # Use public_deps so that generated grit headers are discoverable from
-    # the libcef_static target. Grit deps that generate .cc files must be
-    # listed both here and in the libcef_static target.
-    public_deps = [
-      ":cef_strings",
-      "//chrome/app:chromium_strings",
-      "//chrome/app:generated_resources",
-      "//chrome/app/resources:locale_settings",
-      "//chrome/app/resources:platform_locale_settings",
-      "//components/strings:components_locale_settings",
-      "//components/strings:components_strings",
-      "//extensions/strings",
-      "//services/strings",
-      "//third_party/blink/public/strings",
-      "//ui/strings:app_locale_settings",
-      "//ui/strings:ui_strings",
-    ]
-
-    output = invoker.output
-  }
-}
-
-# Creates an action to call the repack_locales script.
-#
-# The GYP version generates the locales in the "gen" directory and then copies
-# it to the root build directory. This isn't easy to express in a GN copy
-# rule since the files on Mac have a complex structure. So we generate the
-# files into the final place and skip the "gen" directory.
-#
-# This template uses GN's looping constructs to avoid the complex call to
-# chrome/tools/build/repack_locales.py which wraps the repack commands in the
-# GYP build.
-#
-# Arguments
-#
-#   input_locales
-#       List of locale names to use as inputs.
-#
-#   output_locales
-#       A list containing the corresponding output names for each of the
-#       input names. Mac uses different names in some cases.
-#
-#   visibility
-template("cef_repack_locales") {
-  # This is the name of the group below that will collect all the invidual
-  # locale targets. External targets will depend on this.
-  group_target_name = target_name
-
-  # GN's subscript is too stupid to do invoker.output_locales[foo] so we need
-  # to make a copy and do output_locales[foo].
-  output_locales = invoker.output_locales
-
-  # Collects all targets the loop generates.
-  locale_targets = []
-
-  # This loop iterates over the input locales and also keeps a counter so it
-  # can simultaneously iterate over the output locales (using GN's very
-  # limited looping capabilities).
-  current_index = 0
-  foreach(input_locale, invoker.input_locales) {
-    output_locale = output_locales[current_index]
-
-    # Compute the name of the target for the current file. Save it for the deps.
-    current_name = "${target_name}_${input_locale}"
-    locale_targets += [ ":$current_name" ]
-
-    _repack_one_locale(current_name) {
-      visibility = [ ":$group_target_name" ]
-      locale = input_locale
-
-      # Compute the output name. Mac uses a different location.
-      if (is_mac || is_ios) {
-        output = "${root_gen_dir}/repack/locales/${output_locale}.pak"
-      } else {
-        output = "${root_out_dir}/locales/${output_locale}.pak"
-      }
-    }
-
-    current_index = current_index + 1
-  }
-
-  # The group that external targets depend on which collects all deps.
-  group(group_target_name) {
-    forward_variables_from(invoker, [ "visibility" ])
-    public_deps = locale_targets
-  }
-}
diff --git a/src/cmake/cef_macros.cmake.in b/src/cmake/cef_macros.cmake.in
index 1b667e1..f357d06 100644
--- a/src/cmake/cef_macros.cmake.in
+++ b/src/cmake/cef_macros.cmake.in
@@ -25,7 +25,7 @@
 
   message(STATUS "Binary distribution root:     ${_CEF_ROOT}")
 
-  if(OS_MACOSX)
+  if(OS_MAC)
     message(STATUS "Base SDK:                     ${CMAKE_OSX_SYSROOT}")
     message(STATUS "Target SDK:                   ${CEF_TARGET_SDK}")
   endif()
@@ -75,8 +75,8 @@
   if(OS_WINDOWS AND ${name_of_list}_WINDOWS)
     list(APPEND ${name_of_list} ${${name_of_list}_WINDOWS})
   endif()
-  if(OS_MACOSX AND ${name_of_list}_MACOSX)
-    list(APPEND ${name_of_list} ${${name_of_list}_MACOSX})
+  if(OS_MAC AND ${name_of_list}_MAC)
+    list(APPEND ${name_of_list} ${${name_of_list}_MAC})
   endif()
 endmacro()
 
@@ -95,43 +95,64 @@
   endif()
 endmacro()
 
-# Copy a list of files from one directory to another. Relative files paths are maintained.
-# The path component of the source |file_list| will be removed.
+# Copy a list of files from one directory to another. Relative file paths are maintained.
 macro(COPY_FILES target file_list source_dir target_dir)
   foreach(FILENAME ${file_list})
     set(source_file ${source_dir}/${FILENAME})
+
+    # Remove the target file path component.
     get_filename_component(target_name ${FILENAME} NAME)
     set(target_file ${target_dir}/${target_name})
 
-    string(FIND ${source_file} "$<CONFIGURATION>" _pos)
-    if(NOT ${_pos} EQUAL -1)
-      # Must test with an actual configuration directory.
-      string(REPLACE "$<CONFIGURATION>" "Release" existing_source_file ${source_file})
-      if(NOT EXISTS ${existing_source_file})
-        string(REPLACE "$<CONFIGURATION>" "Debug" existing_source_file ${source_file})
-      endif()
-    else()
-      set(existing_source_file ${source_file})
-    endif()
-
-    if(IS_DIRECTORY ${existing_source_file})
-      add_custom_command(
-        TARGET ${target}
-        POST_BUILD
-        COMMAND ${CMAKE_COMMAND} -E copy_directory "${source_file}" "${target_file}"
-        VERBATIM
-        )
-    else()
-      add_custom_command(
-        TARGET ${target}
-        POST_BUILD
-        COMMAND ${CMAKE_COMMAND} -E copy_if_different "${source_file}" "${target_file}"
-        VERBATIM
-        )
-    endif()
+    COPY_SINGLE_FILE(${target} ${source_file} ${target_file})
   endforeach()
 endmacro()
 
+# Copy a list of files from one directory to another. Relative file paths are maintained.
+macro(COPY_RESOURCES target file_list prefix_list source_dir target_dir)
+  foreach(FILENAME ${file_list})
+    set(source_file ${source_dir}/${FILENAME})
+
+    # Remove one or more prefixes from the source paths.
+    set(TARGET_FILENAME "${FILENAME}")
+    foreach(PREFIX ${prefix_list})
+      string(REGEX REPLACE "^.*${PREFIX}" "" TARGET_FILENAME ${TARGET_FILENAME})
+    endforeach()
+    set(target_file ${target_dir}/${TARGET_FILENAME})
+
+    COPY_SINGLE_FILE(${target} ${source_file} ${target_file})
+  endforeach()
+endmacro()
+
+macro(COPY_SINGLE_FILE target source_file target_file)
+  string(FIND ${source_file} "$<CONFIGURATION>" _pos)
+  if(NOT ${_pos} EQUAL -1)
+    # Must test with an actual configuration directory.
+    string(REPLACE "$<CONFIGURATION>" "Release" existing_source_file ${source_file})
+    if(NOT EXISTS ${existing_source_file})
+      string(REPLACE "$<CONFIGURATION>" "Debug" existing_source_file ${source_file})
+    endif()
+  else()
+    set(existing_source_file ${source_file})
+  endif()
+
+  if(IS_DIRECTORY ${existing_source_file})
+    add_custom_command(
+      TARGET ${target}
+      POST_BUILD
+      COMMAND ${CMAKE_COMMAND} -E copy_directory "${source_file}" "${target_file}"
+      VERBATIM
+      )
+  else()
+    add_custom_command(
+      TARGET ${target}
+      POST_BUILD
+      COMMAND ${CMAKE_COMMAND} -E copy_if_different "${source_file}" "${target_file}"
+      VERBATIM
+      )
+  endif()
+endmacro()
+
 
 #
 # Linux macros.
@@ -184,10 +205,10 @@
 # Mac OS X macros.
 #
 
-if(OS_MACOSX)
+if(OS_MAC)
 
 # Manually process and copy over resource files.
-macro(COPY_MACOSX_RESOURCES resource_list prefix_list target source_dir app_path)
+macro(COPY_MAC_RESOURCES resource_list prefix_list target source_dir app_path)
   foreach(FILENAME ${resource_list})
     # Remove one or more prefixes from the source paths.
     set(TARGET_FILENAME "${FILENAME}")
@@ -229,7 +250,7 @@
   endforeach()
 endmacro()
 
-endif(OS_MACOSX)
+endif(OS_MAC)
 
 
 #
@@ -298,7 +319,7 @@
     set_property(TARGET ${target} PROPERTY LINK_FLAGS_RELEASE ${_flags_str})
   endif()
 
-  if(OS_MACOSX)
+  if(OS_MAC)
     # Set Xcode target properties.
     set_target_properties(${target} PROPERTIES
       XCODE_ATTRIBUTE_ALWAYS_SEARCH_USER_PATHS                    NO
diff --git a/src/cmake/cef_variables.cmake.in b/src/cmake/cef_variables.cmake.in
index 4b3b58d..e8c0ada 100644
--- a/src/cmake/cef_variables.cmake.in
+++ b/src/cmake/cef_variables.cmake.in
@@ -14,7 +14,8 @@
 
 # Determine the platform.
 if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
-  set(OS_MACOSX 1)
+  set(OS_MAC 1)
+  set(OS_MACOSX 1)  # For backwards compatibility.
   set(OS_POSIX 1)
 elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
   set(OS_LINUX 1)
@@ -25,16 +26,14 @@
 
 # Determine the project architecture.
 if(NOT DEFINED PROJECT_ARCH)
-  if(CMAKE_SIZEOF_VOID_P MATCHES 8)
+  if(("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "arm64") OR
+     ("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM64"))
+    set(PROJECT_ARCH "arm64")
+  elseif(CMAKE_SIZEOF_VOID_P MATCHES 8)
     set(PROJECT_ARCH "x86_64")
   else()
     set(PROJECT_ARCH "x86")
   endif()
-
-  if(OS_MACOSX)
-    # PROJECT_ARCH should be specified on Mac OS X.
-    message(WARNING "No PROJECT_ARCH value specified, using ${PROJECT_ARCH}")
-  endif()
 endif()
 
 if(${CMAKE_GENERATOR} STREQUAL "Ninja")
@@ -92,6 +91,7 @@
     -Wno-unused-parameter           # Don't warn about unused parameters
     -Wno-error=comment              # Don't warn about code in comments
     -Wno-comment                    # Don't warn about code in comments
+    -Wno-deprecated-declarations    # Don't warn about using deprecated methods
     )
   list(APPEND CEF_C_COMPILER_FLAGS
     -std=c99                        # Use the C99 language standard
@@ -101,7 +101,7 @@
     -fno-rtti                       # Disable real-time type information
     -fno-threadsafe-statics         # Don't generate thread-safe statics
     -fvisibility-inlines-hidden     # Give hidden visibility to inlined class member functions
-    -std=gnu++11                    # Use the C++11 language standard including GNU extensions
+    -std=c++17                      # Use the C++17 language standard
     -Wsign-compare                  # Warn about mixed signed/unsigned type comparisons
     )
   list(APPEND CEF_COMPILER_FLAGS_DEBUG
@@ -218,18 +218,18 @@
     libcef.so
     libEGL.so
     libGLESv2.so
+    libvk_swiftshader.so
+    libvulkan.so.1
     snapshot_blob.bin
     v8_context_snapshot.bin
-    swiftshader
+    vk_swiftshader_icd.json
     )
 
   # List of CEF resource files.
   set(CEF_RESOURCE_FILES
-    cef.pak
-    cef_100_percent.pak
-    cef_200_percent.pak
-    cef_extensions.pak
-    devtools_resources.pak
+    chrome_100_percent.pak
+    chrome_200_percent.pak
+    resources.pak
     icudtl.dat
     locales
     )
@@ -246,7 +246,7 @@
 # Mac OS X configuration.
 #
 
-if(OS_MACOSX)
+if(OS_MAC)
   # Platform-specific compiler/linker flags.
   # See also Xcode target properties in cef_macros.cmake.
   set(CEF_LIBTYPE SHARED)
@@ -272,7 +272,7 @@
     -fno-threadsafe-statics         # Don't generate thread-safe statics
     -fobjc-call-cxx-cdtors          # Call the constructor/destructor of C++ instance variables in ObjC objects
     -fvisibility-inlines-hidden     # Give hidden visibility to inlined class member functions
-    -std=gnu++11                    # Use the C++11 language standard including GNU extensions
+    -std=c++17                      # Use the C++17 language standard
     -Wno-narrowing                  # Don't warn about type narrowing
     -Wsign-compare                  # Warn about mixed signed/unsigned type comparisons
     )
@@ -310,7 +310,7 @@
 
   # Find the newest available base SDK.
   execute_process(COMMAND xcode-select --print-path OUTPUT_VARIABLE XCODE_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
-  foreach(OS_VERSION 10.11 10.10 10.9)
+  foreach(OS_VERSION 10.15 10.14 10.13)
     set(SDK "${XCODE_PATH}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX${OS_VERSION}.sdk")
     if(NOT "${CMAKE_OSX_SYSROOT}" AND EXISTS "${SDK}" AND IS_DIRECTORY "${SDK}")
       set(CMAKE_OSX_SYSROOT ${SDK})
@@ -318,7 +318,7 @@
   endforeach()
 
   # Target SDK.
-  set(CEF_TARGET_SDK               "10.9")
+  set(CEF_TARGET_SDK               "10.13")
   list(APPEND CEF_COMPILER_FLAGS
     -mmacosx-version-min=${CEF_TARGET_SDK}
   )
@@ -327,6 +327,8 @@
   # Target architecture.
   if(PROJECT_ARCH STREQUAL "x86_64")
     set(CMAKE_OSX_ARCHITECTURES "x86_64")
+  elseif(PROJECT_ARCH STREQUAL "arm64")
+    set(CMAKE_OSX_ARCHITECTURES "arm64")
   else()
     set(CMAKE_OSX_ARCHITECTURES "i386")
   endif()
@@ -344,6 +346,10 @@
       CEF_USE_SANDBOX   # Used by apps to test if the sandbox is enabled
       )
 
+    list(APPEND CEF_STANDARD_LIBS
+      -lsandbox
+      )
+
     # CEF sandbox library paths.
     set(CEF_SANDBOX_LIB_DEBUG "${CEF_BINARY_DIR_DEBUG}/cef_sandbox.a")
     set(CEF_SANDBOX_LIB_RELEASE "${CEF_BINARY_DIR_RELEASE}/cef_sandbox.a")
@@ -353,6 +359,7 @@
   # Format is "<name suffix>:<target suffix>:<plist suffix>".
   set(CEF_HELPER_APP_SUFFIXES
     "::"
+    " (Alerts):_alerts:.alerts"
     " (GPU):_gpu:.gpu"
     " (Plugin):_plugin:.plugin"
     " (Renderer):_renderer:.renderer"
@@ -375,25 +382,8 @@
 
   if(USE_SANDBOX)
     # Check if the current MSVC version is compatible with the cef_sandbox.lib
-    # static library. For a list of all version numbers see
-    # https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering
-    list(APPEND supported_msvc_versions
-      1900  # VS2015 and updates 1, 2, & 3
-      1910  # VS2017 version 15.1 & 15.2
-      1911  # VS2017 version 15.3 & 15.4
-      1912  # VS2017 version 15.5
-      1913  # VS2017 version 15.6
-      1914  # VS2017 version 15.7
-      1915  # VS2017 version 15.8
-      1916  # VS2017 version 15.9
-      1920  # VS2019 version 16.0
-      1921  # VS2019 version 16.1
-      1922  # VS2019 version 16.2
-      1923  # VS2019 version 16.3
-      1924  # VS2019 version 16.4
-      )
-    list(FIND supported_msvc_versions ${MSVC_VERSION} _index)
-    if (${_index} EQUAL -1)
+    # static library. We require VS2015 or newer.
+    if(MSVC_VERSION LESS 1900)
       message(WARNING "CEF sandbox is not compatible with the current MSVC version (${MSVC_VERSION})")
       set(USE_SANDBOX OFF)
     endif()
@@ -420,6 +410,7 @@
     /wd4100       # Ignore "unreferenced formal parameter" warning
     /wd4127       # Ignore "conditional expression is constant" warning
     /wd4244       # Ignore "conversion possible loss of data" warning
+    /wd4324       # Ignore "structure was padded due to alignment specifier" warning
     /wd4481       # Ignore "nonstandard extension used: override" warning
     /wd4512       # Ignore "assignment operator could not be generated" warning
     /wd4701       # Ignore "potentially uninitialized local variable" warning
@@ -436,17 +427,75 @@
     /Ob2          # Inline any suitable function
     /GF           # Enable string pooling
     )
+  list(APPEND CEF_CXX_COMPILER_FLAGS
+    /std:c++17    # Use the C++17 language standard
+    )
   list(APPEND CEF_LINKER_FLAGS_DEBUG
     /DEBUG        # Generate debug information
     )
   list(APPEND CEF_EXE_LINKER_FLAGS
     /MANIFEST:NO        # No default manifest (see ADD_WINDOWS_MANIFEST macro usage)
     /LARGEADDRESSAWARE  # Allow 32-bit processes to access 3GB of RAM
+
+    # Delayload most libraries as the dlls are simply not required at startup (or
+    # at all, depending on the process type). Some dlls open handles when they are
+    # loaded, and we may not want them to be loaded in renderers or other sandboxed
+    # processes. Conversely, some dlls must be loaded before sandbox lockdown. In
+    # unsandboxed processes they will load when first needed. The linker will
+    # automatically ignore anything which is not linked to the binary at all (it is
+    # harmless to have an unmatched /delayload). This list should be kept in sync
+    # with Chromium's "delayloads" target from the //build/config/win/BUILD.gn file.
+    /DELAYLOAD:api-ms-win-core-winrt-error-l1-1-0.dll
+    /DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll
+    /DELAYLOAD:api-ms-win-core-winrt-string-l1-1-0.dll
+    /DELAYLOAD:advapi32.dll
+    /DELAYLOAD:comctl32.dll
+    /DELAYLOAD:comdlg32.dll
+    /DELAYLOAD:credui.dll
+    /DELAYLOAD:cryptui.dll
+    /DELAYLOAD:d3d11.dll
+    /DELAYLOAD:d3d9.dll
+    /DELAYLOAD:dwmapi.dll
+    /DELAYLOAD:dxgi.dll
+    /DELAYLOAD:dxva2.dll
+    /DELAYLOAD:esent.dll
+    /DELAYLOAD:gdi32.dll
+    /DELAYLOAD:hid.dll
+    /DELAYLOAD:imagehlp.dll
+    /DELAYLOAD:imm32.dll
+    /DELAYLOAD:msi.dll
+    /DELAYLOAD:netapi32.dll
+    /DELAYLOAD:ncrypt.dll
+    /DELAYLOAD:ole32.dll
+    /DELAYLOAD:oleacc.dll
+    /DELAYLOAD:propsys.dll
+    /DELAYLOAD:psapi.dll
+    /DELAYLOAD:rpcrt4.dll
+    /DELAYLOAD:rstrtmgr.dll
+    /DELAYLOAD:setupapi.dll
+    /DELAYLOAD:shell32.dll
+    /DELAYLOAD:shlwapi.dll
+    /DELAYLOAD:uiautomationcore.dll
+    /DELAYLOAD:urlmon.dll
+    /DELAYLOAD:user32.dll
+    /DELAYLOAD:usp10.dll
+    /DELAYLOAD:uxtheme.dll
+    /DELAYLOAD:wer.dll
+    /DELAYLOAD:wevtapi.dll
+    /DELAYLOAD:wininet.dll
+    /DELAYLOAD:winusb.dll
+    /DELAYLOAD:wsock32.dll
+    /DELAYLOAD:wtsapi32.dll
     )
   list(APPEND CEF_COMPILER_DEFINES
     WIN32 _WIN32 _WINDOWS             # Windows platform
     UNICODE _UNICODE                  # Unicode build
-    WINVER=0x0601 _WIN32_WINNT=0x601  # Targeting Windows 7
+    # Targeting Windows 10. We can't say `=_WIN32_WINNT_WIN10` here because
+    # some files do `#if WINVER < 0x0600` without including windows.h before,
+    # and then _WIN32_WINNT_WIN10 isn't yet known to be 0x0A00.
+    WINVER=0x0A00
+    _WIN32_WINNT=0x0A00
+    NTDDI_VERSION=NTDDI_WIN10_FE
     NOMINMAX                          # Use the standard's templated min/max
     WIN32_LEAN_AND_MEAN               # Exclude less common API declarations
     _HAS_EXCEPTIONS=0                 # Disable exceptions
@@ -455,9 +504,27 @@
     NDEBUG _NDEBUG                    # Not a debug build
     )
 
+  if(PROJECT_ARCH STREQUAL "x86")
+    # Set the initial stack size to 0.5MiB, instead of the 1.5MiB minimum
+    # needed by CEF's main thread. This saves significant memory on threads
+    # (like those in the Windows thread pool, and others) whose stack size we
+    # can only control through this setting. The main thread (in 32-bit builds
+    # only) uses fibers to switch to a 4MiB stack at runtime via
+    # CefRunWinMainWithPreferredStackSize().
+    list(APPEND CEF_EXE_LINKER_FLAGS
+      /STACK:0x80000
+      )
+  else()
+    # Increase the initial stack size to 8MiB from the default 1MiB.
+    list(APPEND CEF_EXE_LINKER_FLAGS
+      /STACK:0x800000
+      )
+  endif()
+
   # Standard libraries.
   set(CEF_STANDARD_LIBS
     comctl32.lib
+    gdi32.lib
     rpcrt4.lib
     shlwapi.lib
     ws2_32.lib
@@ -482,16 +549,16 @@
     libGLESv2.dll
     snapshot_blob.bin
     v8_context_snapshot.bin
-    swiftshader
+    vk_swiftshader.dll
+    vk_swiftshader_icd.json
+    vulkan-1.dll
     )
 
   # List of CEF resource files.
   set(CEF_RESOURCE_FILES
-    cef.pak
-    cef_100_percent.pak
-    cef_200_percent.pak
-    cef_extensions.pak
-    devtools_resources.pak
+    chrome_100_percent.pak
+    chrome_200_percent.pak
+    resources.pak
     icudtl.dat
     locales
     )
@@ -501,17 +568,27 @@
       PSAPI_VERSION=1   # Required by cef_sandbox.lib
       CEF_USE_SANDBOX   # Used by apps to test if the sandbox is enabled
       )
+    list(APPEND CEF_COMPILER_DEFINES_DEBUG
+      _HAS_ITERATOR_DEBUGGING=0   # Disable iterator debugging
+      )
 
     # Libraries required by cef_sandbox.lib.
     set(CEF_SANDBOX_STANDARD_LIBS
+      Advapi32.lib
       dbghelp.lib
       Delayimp.lib
+      ntdll.lib
+      OleAut32.lib
       PowrProf.lib
       Propsys.lib
       psapi.lib
       SetupAPI.lib
+      Shell32.lib
+      Shcore.lib
+      Userenv.lib
       version.lib
       wbemuuid.lib
+      WindowsApp.lib
       winmm.lib
       )
 
diff --git a/src/include/base/cef_atomic_flag.h b/src/include/base/cef_atomic_flag.h
new file mode 100644
index 0000000..3a2fdbc
--- /dev/null
+++ b/src/include/base/cef_atomic_flag.h
@@ -0,0 +1,97 @@
+// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
+// Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CEF_INCLUDE_BASE_CEF_ATOMIC_FLAG_H_
+#define CEF_INCLUDE_BASE_CEF_ATOMIC_FLAG_H_
+#pragma once
+
+#if defined(USING_CHROMIUM_INCLUDES)
+// When building CEF include the Chromium header directly.
+#include "base/synchronization/atomic_flag.h"
+
+#else  // !USING_CHROMIUM_INCLUDES
+// The following is substantially similar to the Chromium implementation.
+// If the Chromium implementation diverges the below implementation should be
+// updated to match.
+
+#include <stdint.h>
+
+#include <atomic>
+
+#include "include/base/cef_thread_checker.h"
+
+namespace base {
+
+///
+/// A flag that can safely be set from one thread and read from other threads.
+///
+/// This class IS NOT intended for synchronization between threads.
+///
+class AtomicFlag {
+ public:
+  AtomicFlag();
+
+  AtomicFlag(const AtomicFlag&) = delete;
+  AtomicFlag& operator=(const AtomicFlag&) = delete;
+
+  ~AtomicFlag();
+
+  ///
+  /// Set the flag. Must always be called from the same thread.
+  ///
+  void Set();
+
+  ///
+  /// Returns true iff the flag was set. If this returns true, the current
+  /// thread is guaranteed to be synchronized with all memory operations on the
+  /// thread which invoked Set() up until at least the first call to Set() on
+  /// it.
+  ///
+  bool IsSet() const {
+    // Inline here: this has a measurable performance impact on base::WeakPtr.
+    return flag_.load(std::memory_order_acquire) != 0;
+  }
+
+  ///
+  /// Resets the flag. Be careful when using this: callers might not expect
+  /// IsSet() to return false after returning true once.
+  ///
+  void UnsafeResetForTesting();
+
+ private:
+  std::atomic<uint_fast8_t> flag_{0};
+  base::ThreadChecker set_thread_checker_;
+};
+
+}  // namespace base
+
+#endif  // !USING_CHROMIUM_INCLUDES
+
+#endif  // CEF_INCLUDE_BASE_CEF_ATOMIC_FLAG_H_
diff --git a/src/include/base/cef_atomic_ref_count.h b/src/include/base/cef_atomic_ref_count.h
index 4d67779..38e8f93 100644
--- a/src/include/base/cef_atomic_ref_count.h
+++ b/src/include/base/cef_atomic_ref_count.h
@@ -43,120 +43,78 @@
 // When building CEF include the Chromium header directly.
 #include "base/atomic_ref_count.h"
 
-// Used when declaring a base::AtomicRefCount value. This is an object type with
-// Chromium headers.
-#define ATOMIC_DECLARATION (0)
-
-// Maintaining compatibility with AtompicRefCount* functions that were removed
-// from Chromium in http://crrev.com/ee96d561.
-namespace base {
-
-// Increment a reference count by 1.
-inline void AtomicRefCountInc(volatile AtomicRefCount* ptr) {
-  const_cast<AtomicRefCount*>(ptr)->Increment();
-}
-
-// Decrement a reference count by 1 and return whether the result is non-zero.
-// Insert barriers to ensure that state written before the reference count
-// became zero will be visible to a thread that has just made the count zero.
-inline bool AtomicRefCountDec(volatile AtomicRefCount* ptr) {
-  return const_cast<AtomicRefCount*>(ptr)->Decrement();
-}
-
-// Return whether the reference count is one.  If the reference count is used
-// in the conventional way, a refrerence count of 1 implies that the current
-// thread owns the reference and no other thread shares it.  This call performs
-// the test for a reference count of one, and performs the memory barrier
-// needed for the owning thread to act on the object, knowing that it has
-// exclusive access to the object.
-inline bool AtomicRefCountIsOne(volatile AtomicRefCount* ptr) {
-  return const_cast<AtomicRefCount*>(ptr)->IsOne();
-}
-
-// Return whether the reference count is zero.  With conventional object
-// referencing counting, the object will be destroyed, so the reference count
-// should never be zero.  Hence this is generally used for a debug check.
-inline bool AtomicRefCountIsZero(volatile AtomicRefCount* ptr) {
-  return const_cast<AtomicRefCount*>(ptr)->IsZero();
-}
-
-}  // namespace base
-
 #else  // !USING_CHROMIUM_INCLUDES
 // The following is substantially similar to the Chromium implementation.
 // If the Chromium implementation diverges the below implementation should be
 // updated to match.
 
-#include "include/base/cef_atomicops.h"
-
-// Annotations are not currently supported.
-#define ANNOTATE_HAPPENS_BEFORE(obj) /* empty */
-#define ANNOTATE_HAPPENS_AFTER(obj)  /* empty */
-
-// Used when declaring a base::AtomicRefCount value. This is an integer/ptr type
-// with CEF headers.
-#define ATOMIC_DECLARATION = 0
+#include <atomic>
 
 namespace base {
 
-typedef subtle::Atomic32 AtomicRefCount;
+class AtomicRefCount {
+ public:
+  constexpr AtomicRefCount() : ref_count_(0) {}
+  explicit constexpr AtomicRefCount(int initial_value)
+      : ref_count_(initial_value) {}
 
-// Increment a reference count by "increment", which must exceed 0.
-inline void AtomicRefCountIncN(volatile AtomicRefCount* ptr,
-                               AtomicRefCount increment) {
-  subtle::NoBarrier_AtomicIncrement(ptr, increment);
-}
+  ///
+  /// Increment a reference count.
+  /// Returns the previous value of the count.
+  ///
+  int Increment() { return Increment(1); }
 
-// Decrement a reference count by "decrement", which must exceed 0,
-// and return whether the result is non-zero.
-// Insert barriers to ensure that state written before the reference count
-// became zero will be visible to a thread that has just made the count zero.
-inline bool AtomicRefCountDecN(volatile AtomicRefCount* ptr,
-                               AtomicRefCount decrement) {
-  ANNOTATE_HAPPENS_BEFORE(ptr);
-  bool res = (subtle::Barrier_AtomicIncrement(ptr, -decrement) != 0);
-  if (!res) {
-    ANNOTATE_HAPPENS_AFTER(ptr);
+  ///
+  /// Increment a reference count by "increment", which must exceed 0.
+  /// Returns the previous value of the count.
+  ///
+  int Increment(int increment) {
+    return ref_count_.fetch_add(increment, std::memory_order_relaxed);
   }
-  return res;
-}
 
-// Increment a reference count by 1.
-inline void AtomicRefCountInc(volatile AtomicRefCount* ptr) {
-  base::AtomicRefCountIncN(ptr, 1);
-}
-
-// Decrement a reference count by 1 and return whether the result is non-zero.
-// Insert barriers to ensure that state written before the reference count
-// became zero will be visible to a thread that has just made the count zero.
-inline bool AtomicRefCountDec(volatile AtomicRefCount* ptr) {
-  return base::AtomicRefCountDecN(ptr, 1);
-}
-
-// Return whether the reference count is one.  If the reference count is used
-// in the conventional way, a refrerence count of 1 implies that the current
-// thread owns the reference and no other thread shares it.  This call performs
-// the test for a reference count of one, and performs the memory barrier
-// needed for the owning thread to act on the object, knowing that it has
-// exclusive access to the object.
-inline bool AtomicRefCountIsOne(volatile AtomicRefCount* ptr) {
-  bool res = (subtle::Acquire_Load(ptr) == 1);
-  if (res) {
-    ANNOTATE_HAPPENS_AFTER(ptr);
+  ///
+  /// Decrement a reference count, and return whether the result is non-zero.
+  /// Insert barriers to ensure that state written before the reference count
+  /// became zero will be visible to a thread that has just made the count zero.
+  ///
+  bool Decrement() {
+    // TODO(jbroman): Technically this doesn't need to be an acquire operation
+    // unless the result is 1 (i.e., the ref count did indeed reach zero).
+    // However, there are toolchain issues that make that not work as well at
+    // present (notably TSAN doesn't like it).
+    return ref_count_.fetch_sub(1, std::memory_order_acq_rel) != 1;
   }
-  return res;
-}
 
-// Return whether the reference count is zero.  With conventional object
-// referencing counting, the object will be destroyed, so the reference count
-// should never be zero.  Hence this is generally used for a debug check.
-inline bool AtomicRefCountIsZero(volatile AtomicRefCount* ptr) {
-  bool res = (subtle::Acquire_Load(ptr) == 0);
-  if (res) {
-    ANNOTATE_HAPPENS_AFTER(ptr);
+  ///
+  /// Return whether the reference count is one.  If the reference count is used
+  /// in the conventional way, a refrerence count of 1 implies that the current
+  /// thread owns the reference and no other thread shares it.  This call
+  /// performs the test for a reference count of one, and performs the memory
+  /// barrier needed for the owning thread to act on the object, knowing that it
+  /// has exclusive access to the object.
+  ///
+  bool IsOne() const { return ref_count_.load(std::memory_order_acquire) == 1; }
+
+  ///
+  /// Return whether the reference count is zero.  With conventional object
+  /// referencing counting, the object will be destroyed, so the reference count
+  /// should never be zero.  Hence this is generally used for a debug check.
+  ///
+  bool IsZero() const {
+    return ref_count_.load(std::memory_order_acquire) == 0;
   }
-  return res;
-}
+
+  ///
+  /// Returns the current reference count (with no barriers). This is subtle,
+  /// and should be used only for debugging.
+  ///
+  int SubtleRefCountForDebug() const {
+    return ref_count_.load(std::memory_order_relaxed);
+  }
+
+ private:
+  std::atomic_int ref_count_;
+};
 
 }  // namespace base
 
diff --git a/src/include/base/cef_atomicops.h b/src/include/base/cef_atomicops.h
deleted file mode 100644
index a5b6459..0000000
--- a/src/include/base/cef_atomicops.h
+++ /dev/null
@@ -1,203 +0,0 @@
-// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
-// Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// For atomic operations on reference counts, see cef_atomic_ref_count.h.
-
-// The routines exported by this module are subtle.  If you use them, even if
-// you get the code right, it will depend on careful reasoning about atomicity
-// and memory ordering; it will be less readable, and harder to maintain.  If
-// you plan to use these routines, you should have a good reason, such as solid
-// evidence that performance would otherwise suffer, or there being no
-// alternative.  You should assume only properties explicitly guaranteed by the
-// specifications in this file.  You are almost certainly _not_ writing code
-// just for the x86; if you assume x86 semantics, x86 hardware bugs and
-// implementations on other archtectures will cause your code to break.  If you
-// do not know what you are doing, avoid these routines, and use a Mutex.
-//
-// It is incorrect to make direct assignments to/from an atomic variable.
-// You should use one of the Load or Store routines.  The NoBarrier
-// versions are provided when no barriers are needed:
-//   NoBarrier_Store()
-//   NoBarrier_Load()
-// Although there are currently no compiler enforcement, you are encouraged
-// to use these.
-//
-
-#ifndef CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_
-#define CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_
-#pragma once
-
-#if defined(BASE_ATOMICOPS_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
-// When building CEF include the Chromium header directly.
-#include "base/atomicops.h"
-#else  // !USING_CHROMIUM_INCLUDES
-// The following is substantially similar to the Chromium implementation.
-// If the Chromium implementation diverges the below implementation should be
-// updated to match.
-
-#include <stdint.h>
-
-#include "include/base/cef_build.h"
-
-#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
-// windows.h #defines this (only on x64). This causes problems because the
-// public API also uses MemoryBarrier at the public name for this fence. So, on
-// X64, undef it, and call its documented
-// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
-// implementation directly.
-#undef MemoryBarrier
-#endif
-
-namespace base {
-namespace subtle {
-
-typedef int32_t Atomic32;
-#ifdef ARCH_CPU_64_BITS
-// We need to be able to go between Atomic64 and AtomicWord implicitly.  This
-// means Atomic64 and AtomicWord should be the same type on 64-bit.
-#if defined(__ILP32__) || defined(OS_NACL)
-// NaCl's intptr_t is not actually 64-bits on 64-bit!
-// http://code.google.com/p/nativeclient/issues/detail?id=1162
-typedef int64_t Atomic64;
-#else
-typedef intptr_t Atomic64;
-#endif
-#endif
-
-// Use AtomicWord for a machine-sized pointer.  It will use the Atomic32 or
-// Atomic64 routines below, depending on your architecture.
-typedef intptr_t AtomicWord;
-
-// Atomically execute:
-//      result = *ptr;
-//      if (*ptr == old_value)
-//        *ptr = new_value;
-//      return result;
-//
-// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
-// Always return the old value of "*ptr"
-//
-// This routine implies no memory barriers.
-Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
-                                  Atomic32 old_value,
-                                  Atomic32 new_value);
-
-// Atomically store new_value into *ptr, returning the previous value held in
-// *ptr.  This routine implies no memory barriers.
-Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
-
-// Atomically increment *ptr by "increment".  Returns the new value of
-// *ptr with the increment applied.  This routine implies no memory barriers.
-Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
-
-Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
-
-// These following lower-level operations are typically useful only to people
-// implementing higher-level synchronization operations like spinlocks,
-// mutexes, and condition-variables.  They combine CompareAndSwap(), a load, or
-// a store with appropriate memory-ordering instructions.  "Acquire" operations
-// ensure that no later memory access can be reordered ahead of the operation.
-// "Release" operations ensure that no previous memory access can be reordered
-// after the operation.  "Barrier" operations have both "Acquire" and "Release"
-// semantics.   A MemoryBarrier() has "Barrier" semantics, but does no memory
-// access.
-Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
-                                Atomic32 old_value,
-                                Atomic32 new_value);
-Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
-                                Atomic32 old_value,
-                                Atomic32 new_value);
-
-void MemoryBarrier();
-void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value);
-void Acquire_Store(volatile Atomic32* ptr, Atomic32 value);
-void Release_Store(volatile Atomic32* ptr, Atomic32 value);
-
-Atomic32 NoBarrier_Load(volatile const Atomic32* ptr);
-Atomic32 Acquire_Load(volatile const Atomic32* ptr);
-Atomic32 Release_Load(volatile const Atomic32* ptr);
-
-// 64-bit atomic operations (only available on 64-bit processors).
-#ifdef ARCH_CPU_64_BITS
-Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
-                                  Atomic64 old_value,
-                                  Atomic64 new_value);
-Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value);
-Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
-Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
-
-Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
-                                Atomic64 old_value,
-                                Atomic64 new_value);
-Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
-                                Atomic64 old_value,
-                                Atomic64 new_value);
-void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value);
-void Acquire_Store(volatile Atomic64* ptr, Atomic64 value);
-void Release_Store(volatile Atomic64* ptr, Atomic64 value);
-Atomic64 NoBarrier_Load(volatile const Atomic64* ptr);
-Atomic64 Acquire_Load(volatile const Atomic64* ptr);
-Atomic64 Release_Load(volatile const Atomic64* ptr);
-#endif  // ARCH_CPU_64_BITS
-
-}  // namespace subtle
-}  // namespace base
-
-// Include our platform specific implementation.
-#if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY)
-#include "include/base/internal/cef_atomicops_x86_msvc.h"
-#elif defined(OS_WIN) && (defined(__ARM_ARCH_ISA_A64) || defined(_M_ARM64))
-#include "include/base/internal/cef_atomicops_arm64_msvc.h"
-#elif defined(OS_MACOSX)
-#include "include/base/internal/cef_atomicops_mac.h"
-#elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
-#include "include/base/internal/cef_atomicops_x86_gcc.h"
-#elif defined(COMPILER_GCC) && defined(__ARM_ARCH_ISA_A64)
-#include "include/base/internal/cef_atomicops_arm64_gcc.h"
-#elif defined(COMPILER_GCC) && defined(__ARM_ARCH)
-#include "include/base/internal/cef_atomicops_arm_gcc.h"
-#else
-#error "Atomic operations are not supported on your platform"
-#endif
-
-// On some platforms we need additional declarations to make
-// AtomicWord compatible with our other Atomic* types.
-#if defined(OS_MACOSX) || defined(OS_OPENBSD)
-#include "include/base/internal/cef_atomicops_atomicword_compat.h"
-#endif
-
-#endif  // !USING_CHROMIUM_INCLUDES
-
-#endif  // CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_
diff --git a/src/include/base/cef_auto_reset.h b/src/include/base/cef_auto_reset.h
new file mode 100644
index 0000000..be3a05d
--- /dev/null
+++ b/src/include/base/cef_auto_reset.h
@@ -0,0 +1,90 @@
+// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
+// Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// base::AutoReset<> is useful for setting a variable to a new value only within
+// a particular scope. An base::AutoReset<> object resets a variable to its
+// original value upon destruction, making it an alternative to writing
+// "var = false;" or "var = old_val;" at all of a block's exit points.
+//
+// This should be obvious, but note that an base::AutoReset<> instance should
+// have a shorter lifetime than its scoped_variable, to prevent invalid memory
+// writes when the base::AutoReset<> object is destroyed.
+
+#ifndef CEF_INCLUDE_BASE_CEF_AUTO_RESET_H_
+#define CEF_INCLUDE_BASE_CEF_AUTO_RESET_H_
+#pragma once
+
+#if defined(USING_CHROMIUM_INCLUDES)
+// When building CEF include the Chromium header directly.
+#include "base/auto_reset.h"
+#else  // !USING_CHROMIUM_INCLUDES
+// The following is substantially similar to the Chromium implementation.
+// If the Chromium implementation diverges the below implementation should be
+// updated to match.
+
+#include <utility>
+
+namespace base {
+
+template <typename T>
+class AutoReset {
+ public:
+  template <typename U>
+  AutoReset(T* scoped_variable, U&& new_value)
+      : scoped_variable_(scoped_variable),
+        original_value_(
+            std::exchange(*scoped_variable_, std::forward<U>(new_value))) {}
+
+  AutoReset(AutoReset&& other)
+      : scoped_variable_(std::exchange(other.scoped_variable_, nullptr)),
+        original_value_(std::move(other.original_value_)) {}
+
+  AutoReset& operator=(AutoReset&& rhs) {
+    scoped_variable_ = std::exchange(rhs.scoped_variable_, nullptr);
+    original_value_ = std::move(rhs.original_value_);
+    return *this;
+  }
+
+  ~AutoReset() {
+    if (scoped_variable_) {
+      *scoped_variable_ = std::move(original_value_);
+    }
+  }
+
+ private:
+  T* scoped_variable_;
+  T original_value_;
+};
+
+}  // namespace base
+
+#endif  // !USING_CHROMIUM_INCLUDES
+
+#endif  // CEF_INCLUDE_BASE_CEF_AUTO_RESET_H_
diff --git a/src/include/base/cef_basictypes.h b/src/include/base/cef_basictypes.h
deleted file mode 100644
index e38f4f7..0000000
--- a/src/include/base/cef_basictypes.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
-// Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef CEF_INCLUDE_BASE_CEF_BASICTYPES_H_
-#define CEF_INCLUDE_BASE_CEF_BASICTYPES_H_
-#pragma once
-
-#include <limits.h>  // For UINT_MAX
-#include <stddef.h>  // For size_t
-
-#include "include/base/cef_build.h"
-
-// The NSPR system headers define 64-bit as |long| when possible, except on
-// Mac OS X.  In order to not have typedef mismatches, we do the same on LP64.
-//
-// On Mac OS X, |long long| is used for 64-bit types for compatibility with
-// <inttypes.h> format macros even in the LP64 model.
-#if defined(__LP64__) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
-typedef long int64;
-typedef unsigned long uint64;
-#else
-typedef long long int64;
-typedef unsigned long long uint64;
-#endif
-
-// TODO: Remove these type guards.  These are to avoid conflicts with
-// obsolete/protypes.h in the Gecko SDK.
-#ifndef _INT32
-#define _INT32
-typedef int int32;
-#endif
-
-// TODO: Remove these type guards.  These are to avoid conflicts with
-// obsolete/protypes.h in the Gecko SDK.
-#ifndef _UINT32
-#define _UINT32
-typedef unsigned int uint32;
-#endif
-
-#ifndef _INT16
-#define _INT16
-typedef short int16;
-#endif
-
-#ifndef _UINT16
-#define _UINT16
-typedef unsigned short uint16;
-#endif
-
-// UTF-16 character type.
-// This should be kept synchronized with base/strings/string16.h
-#ifndef char16
-#if defined(WCHAR_T_IS_UTF16)
-typedef wchar_t char16;
-#elif defined(WCHAR_T_IS_UTF32)
-typedef unsigned short char16;
-#endif
-#endif
-
-#endif  // CEF_INCLUDE_BASE_CEF_BASICTYPES_H_
diff --git a/src/include/base/cef_bind.h b/src/include/base/cef_bind.h
index 77c9c55..e879b56 100644
--- a/src/include/base/cef_bind.h
+++ b/src/include/base/cef_bind.h
@@ -28,546 +28,361 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+///
+/// \file
+/// base::BindOnce() and base::BindRepeating() are helpers for creating
+/// base::OnceCallback and base::RepeatingCallback objects respectively.
+///
+/// For a runnable object of n-arity, the base::Bind*() family allows partial
+/// application of the first m arguments. The remaining n - m arguments must be
+/// passed when invoking the callback with Run().
+///
+/// <pre>
+///   // The first argument is bound at callback creation; the remaining
+///   // two must be passed when calling Run() on the callback object.
+///   base::OnceCallback<long(int, long)> cb = base::BindOnce(
+///       [](short x, int y, long z) { return x * y * z; }, 42);
+/// </pre>
+///
+/// When binding to a method, the receiver object must also be specified at
+/// callback creation time. When Run() is invoked, the method will be invoked on
+/// the specified receiver object.
+///
+/// <pre>
+///   class C : public base::RefCounted<C> { void F(); };
+///   auto instance = base::MakeRefCounted<C>();
+///   auto cb = base::BindOnce(&C::F, instance);
+///   std::move(cb).Run();  // Identical to instance->F()
+/// </pre>
+///
+/// See https://chromium.googlesource.com/chromium/src/+/lkgr/docs/callback.md
+/// for the full documentation.
+///
+
+// Implementation notes
+//
+// If you're reading the implementation, before proceeding further, you should
+// read the top comment of base/internal/cef_bind_internal.h for a definition
+// of common terms and concepts.
+
 #ifndef CEF_INCLUDE_BASE_CEF_BIND_H_
 #define CEF_INCLUDE_BASE_CEF_BIND_H_
 #pragma once
 
-#if defined(BASE_BIND_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
+#if defined(USING_CHROMIUM_INCLUDES)
 // When building CEF include the Chromium header directly.
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #else  // !USING_CHROMIUM_INCLUDES
 // The following is substantially similar to the Chromium implementation.
 // If the Chromium implementation diverges the below implementation should be
 // updated to match.
 
-#include "include/base/internal/cef_bind_internal.h"
-#include "include/base/internal/cef_callback_internal.h"
+#include <functional>
+#include <memory>
+#include <type_traits>
+#include <utility>
 
-// -----------------------------------------------------------------------------
-// Usage documentation
-// -----------------------------------------------------------------------------
-//
-// See base/cef_callback.h for documentation.
-//
-//
-// -----------------------------------------------------------------------------
-// Implementation notes
-// -----------------------------------------------------------------------------
-//
-// If you're reading the implementation, before proceeding further, you should
-// read the top comment of base/bind_internal.h for a definition of common
-// terms and concepts.
-//
-// RETURN TYPES
-//
-// Though Bind()'s result is meant to be stored in a Callback<> type, it
-// cannot actually return the exact type without requiring a large amount
-// of extra template specializations. The problem is that in order to
-// discern the correct specialization of Callback<>, Bind would need to
-// unwrap the function signature to determine the signature's arity, and
-// whether or not it is a method.
-//
-// Each unique combination of (arity, function_type, num_prebound) where
-// function_type is one of {function, method, const_method} would require
-// one specialization.  We eventually have to do a similar number of
-// specializations anyways in the implementation (see the Invoker<>,
-// classes).  However, it is avoidable in Bind if we return the result
-// via an indirection like we do below.
-//
-// TODO(ajwong): We might be able to avoid this now, but need to test.
-//
-// It is possible to move most of the COMPILE_ASSERT asserts into BindState<>,
-// but it feels a little nicer to have the asserts here so people do not
-// need to crack open bind_internal.h.  On the other hand, it makes Bind()
-// harder to read.
+#include "include/base/cef_build.h"
+#include "include/base/cef_compiler_specific.h"
+#include "include/base/internal/cef_bind_internal.h"
+
+#if defined(OS_APPLE) && !HAS_FEATURE(objc_arc)
+#include "include/base/internal/cef_scoped_block_mac.h"
+#endif
 
 namespace base {
 
-template <typename Functor>
-base::Callback<typename cef_internal::BindState<
-    typename cef_internal::FunctorTraits<Functor>::RunnableType,
-    typename cef_internal::FunctorTraits<Functor>::RunType,
-    void()>::UnboundRunType>
-Bind(Functor functor) {
-  // Typedefs for how to store and run the functor.
-  typedef
-      typename cef_internal::FunctorTraits<Functor>::RunnableType RunnableType;
-  typedef typename cef_internal::FunctorTraits<Functor>::RunType RunType;
+///
+/// Bind as OnceCallback.
+///
+template <typename Functor, typename... Args>
+inline OnceCallback<cef_internal::MakeUnboundRunType<Functor, Args...>>
+BindOnce(Functor&& functor, Args&&... args) {
+  static_assert(!cef_internal::IsOnceCallback<std::decay_t<Functor>>() ||
+                    (std::is_rvalue_reference<Functor&&>() &&
+                     !std::is_const<std::remove_reference_t<Functor>>()),
+                "BindOnce requires non-const rvalue for OnceCallback binding."
+                " I.e.: base::BindOnce(std::move(callback)).");
+  static_assert(
+      std::conjunction<cef_internal::AssertBindArgIsNotBasePassed<
+          std::decay_t<Args>>...>::value,
+      "Use std::move() instead of base::Passed() with base::BindOnce()");
 
-  typedef cef_internal::BindState<RunnableType, RunType, void()> BindState;
-
-  return Callback<typename BindState::UnboundRunType>(
-      new BindState(cef_internal::MakeRunnable(functor)));
+  return cef_internal::BindImpl<OnceCallback>(std::forward<Functor>(functor),
+                                              std::forward<Args>(args)...);
 }
 
-template <typename Functor, typename P1>
-base::Callback<typename cef_internal::BindState<
-    typename cef_internal::FunctorTraits<Functor>::RunnableType,
-    typename cef_internal::FunctorTraits<Functor>::RunType,
-    void(typename cef_internal::CallbackParamTraits<P1>::StorageType)>::
-                   UnboundRunType>
-Bind(Functor functor, const P1& p1) {
-  // Typedefs for how to store and run the functor.
-  typedef
-      typename cef_internal::FunctorTraits<Functor>::RunnableType RunnableType;
-  typedef typename cef_internal::FunctorTraits<Functor>::RunType RunType;
+///
+/// Bind as RepeatingCallback.
+///
+template <typename Functor, typename... Args>
+inline RepeatingCallback<cef_internal::MakeUnboundRunType<Functor, Args...>>
+BindRepeating(Functor&& functor, Args&&... args) {
+  static_assert(
+      !cef_internal::IsOnceCallback<std::decay_t<Functor>>(),
+      "BindRepeating cannot bind OnceCallback. Use BindOnce with std::move().");
 
-  // Use RunnableType::RunType instead of RunType above because our
-  // checks should below for bound references need to know what the actual
-  // functor is going to interpret the argument as.
-  typedef cef_internal::FunctionTraits<typename RunnableType::RunType>
-      BoundFunctorTraits;
-
-  // Do not allow binding a non-const reference parameter. Non-const reference
-  // parameters are disallowed by the Google style guide.  Also, binding a
-  // non-const reference parameter can make for subtle bugs because the
-  // invoked function will receive a reference to the stored copy of the
-  // argument and not the original.
-  COMPILE_ASSERT(
-      !(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value),
-      do_not_bind_functions_with_nonconst_ref);
-
-  // For methods, we need to be careful for parameter 1.  We do not require
-  // a scoped_refptr because BindState<> itself takes care of AddRef() for
-  // methods. We also disallow binding of an array as the method's target
-  // object.
-  COMPILE_ASSERT(cef_internal::HasIsMethodTag<RunnableType>::value ||
-                     !cef_internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
-                 p1_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::HasIsMethodTag<RunnableType>::value ||
-                     !is_array<P1>::value,
-                 first_bound_argument_to_method_cannot_be_array);
-  typedef cef_internal::BindState<
-      RunnableType, RunType,
-      void(typename cef_internal::CallbackParamTraits<P1>::StorageType)>
-      BindState;
-
-  return Callback<typename BindState::UnboundRunType>(
-      new BindState(cef_internal::MakeRunnable(functor), p1));
+  return cef_internal::BindImpl<RepeatingCallback>(
+      std::forward<Functor>(functor), std::forward<Args>(args)...);
 }
 
-template <typename Functor, typename P1, typename P2>
-base::Callback<typename cef_internal::BindState<
-    typename cef_internal::FunctorTraits<Functor>::RunnableType,
-    typename cef_internal::FunctorTraits<Functor>::RunType,
-    void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
-         typename cef_internal::CallbackParamTraits<P2>::StorageType)>::
-                   UnboundRunType>
-Bind(Functor functor, const P1& p1, const P2& p2) {
-  // Typedefs for how to store and run the functor.
-  typedef
-      typename cef_internal::FunctorTraits<Functor>::RunnableType RunnableType;
-  typedef typename cef_internal::FunctorTraits<Functor>::RunType RunType;
-
-  // Use RunnableType::RunType instead of RunType above because our
-  // checks should below for bound references need to know what the actual
-  // functor is going to interpret the argument as.
-  typedef cef_internal::FunctionTraits<typename RunnableType::RunType>
-      BoundFunctorTraits;
-
-  // Do not allow binding a non-const reference parameter. Non-const reference
-  // parameters are disallowed by the Google style guide.  Also, binding a
-  // non-const reference parameter can make for subtle bugs because the
-  // invoked function will receive a reference to the stored copy of the
-  // argument and not the original.
-  COMPILE_ASSERT(
-      !(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A2Type>::value),
-      do_not_bind_functions_with_nonconst_ref);
-
-  // For methods, we need to be careful for parameter 1.  We do not require
-  // a scoped_refptr because BindState<> itself takes care of AddRef() for
-  // methods. We also disallow binding of an array as the method's target
-  // object.
-  COMPILE_ASSERT(cef_internal::HasIsMethodTag<RunnableType>::value ||
-                     !cef_internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
-                 p1_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::HasIsMethodTag<RunnableType>::value ||
-                     !is_array<P1>::value,
-                 first_bound_argument_to_method_cannot_be_array);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
-                 p2_is_refcounted_type_and_needs_scoped_refptr);
-  typedef cef_internal::BindState<
-      RunnableType, RunType,
-      void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
-           typename cef_internal::CallbackParamTraits<P2>::StorageType)>
-      BindState;
-
-  return Callback<typename BindState::UnboundRunType>(
-      new BindState(cef_internal::MakeRunnable(functor), p1, p2));
+///
+/// Special cases for binding to a base::Callback without extra bound arguments.
+/// We CHECK() the validity of callback to guard against null pointers
+/// accidentally ending up in posted tasks, causing hard-to-debug crashes.
+///
+template <typename Signature>
+OnceCallback<Signature> BindOnce(OnceCallback<Signature> callback) {
+  CHECK(callback);
+  return callback;
 }
 
-template <typename Functor, typename P1, typename P2, typename P3>
-base::Callback<typename cef_internal::BindState<
-    typename cef_internal::FunctorTraits<Functor>::RunnableType,
-    typename cef_internal::FunctorTraits<Functor>::RunType,
-    void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
-         typename cef_internal::CallbackParamTraits<P2>::StorageType,
-         typename cef_internal::CallbackParamTraits<P3>::StorageType)>::
-                   UnboundRunType>
-Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3) {
-  // Typedefs for how to store and run the functor.
-  typedef
-      typename cef_internal::FunctorTraits<Functor>::RunnableType RunnableType;
-  typedef typename cef_internal::FunctorTraits<Functor>::RunType RunType;
-
-  // Use RunnableType::RunType instead of RunType above because our
-  // checks should below for bound references need to know what the actual
-  // functor is going to interpret the argument as.
-  typedef cef_internal::FunctionTraits<typename RunnableType::RunType>
-      BoundFunctorTraits;
-
-  // Do not allow binding a non-const reference parameter. Non-const reference
-  // parameters are disallowed by the Google style guide.  Also, binding a
-  // non-const reference parameter can make for subtle bugs because the
-  // invoked function will receive a reference to the stored copy of the
-  // argument and not the original.
-  COMPILE_ASSERT(
-      !(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A3Type>::value),
-      do_not_bind_functions_with_nonconst_ref);
-
-  // For methods, we need to be careful for parameter 1.  We do not require
-  // a scoped_refptr because BindState<> itself takes care of AddRef() for
-  // methods. We also disallow binding of an array as the method's target
-  // object.
-  COMPILE_ASSERT(cef_internal::HasIsMethodTag<RunnableType>::value ||
-                     !cef_internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
-                 p1_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::HasIsMethodTag<RunnableType>::value ||
-                     !is_array<P1>::value,
-                 first_bound_argument_to_method_cannot_be_array);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
-                 p2_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
-                 p3_is_refcounted_type_and_needs_scoped_refptr);
-  typedef cef_internal::BindState<
-      RunnableType, RunType,
-      void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
-           typename cef_internal::CallbackParamTraits<P2>::StorageType,
-           typename cef_internal::CallbackParamTraits<P3>::StorageType)>
-      BindState;
-
-  return Callback<typename BindState::UnboundRunType>(
-      new BindState(cef_internal::MakeRunnable(functor), p1, p2, p3));
+template <typename Signature>
+OnceCallback<Signature> BindOnce(RepeatingCallback<Signature> callback) {
+  CHECK(callback);
+  return callback;
 }
 
-template <typename Functor, typename P1, typename P2, typename P3, typename P4>
-base::Callback<typename cef_internal::BindState<
-    typename cef_internal::FunctorTraits<Functor>::RunnableType,
-    typename cef_internal::FunctorTraits<Functor>::RunType,
-    void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
-         typename cef_internal::CallbackParamTraits<P2>::StorageType,
-         typename cef_internal::CallbackParamTraits<P3>::StorageType,
-         typename cef_internal::CallbackParamTraits<P4>::StorageType)>::
-                   UnboundRunType>
-Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4) {
-  // Typedefs for how to store and run the functor.
-  typedef
-      typename cef_internal::FunctorTraits<Functor>::RunnableType RunnableType;
-  typedef typename cef_internal::FunctorTraits<Functor>::RunType RunType;
-
-  // Use RunnableType::RunType instead of RunType above because our
-  // checks should below for bound references need to know what the actual
-  // functor is going to interpret the argument as.
-  typedef cef_internal::FunctionTraits<typename RunnableType::RunType>
-      BoundFunctorTraits;
-
-  // Do not allow binding a non-const reference parameter. Non-const reference
-  // parameters are disallowed by the Google style guide.  Also, binding a
-  // non-const reference parameter can make for subtle bugs because the
-  // invoked function will receive a reference to the stored copy of the
-  // argument and not the original.
-  COMPILE_ASSERT(
-      !(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A4Type>::value),
-      do_not_bind_functions_with_nonconst_ref);
-
-  // For methods, we need to be careful for parameter 1.  We do not require
-  // a scoped_refptr because BindState<> itself takes care of AddRef() for
-  // methods. We also disallow binding of an array as the method's target
-  // object.
-  COMPILE_ASSERT(cef_internal::HasIsMethodTag<RunnableType>::value ||
-                     !cef_internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
-                 p1_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::HasIsMethodTag<RunnableType>::value ||
-                     !is_array<P1>::value,
-                 first_bound_argument_to_method_cannot_be_array);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
-                 p2_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
-                 p3_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
-                 p4_is_refcounted_type_and_needs_scoped_refptr);
-  typedef cef_internal::BindState<
-      RunnableType, RunType,
-      void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
-           typename cef_internal::CallbackParamTraits<P2>::StorageType,
-           typename cef_internal::CallbackParamTraits<P3>::StorageType,
-           typename cef_internal::CallbackParamTraits<P4>::StorageType)>
-      BindState;
-
-  return Callback<typename BindState::UnboundRunType>(
-      new BindState(cef_internal::MakeRunnable(functor), p1, p2, p3, p4));
+template <typename Signature>
+RepeatingCallback<Signature> BindRepeating(
+    RepeatingCallback<Signature> callback) {
+  CHECK(callback);
+  return callback;
 }
 
-template <typename Functor,
-          typename P1,
-          typename P2,
-          typename P3,
-          typename P4,
-          typename P5>
-base::Callback<typename cef_internal::BindState<
-    typename cef_internal::FunctorTraits<Functor>::RunnableType,
-    typename cef_internal::FunctorTraits<Functor>::RunType,
-    void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
-         typename cef_internal::CallbackParamTraits<P2>::StorageType,
-         typename cef_internal::CallbackParamTraits<P3>::StorageType,
-         typename cef_internal::CallbackParamTraits<P4>::StorageType,
-         typename cef_internal::CallbackParamTraits<P5>::StorageType)>::
-                   UnboundRunType>
-Bind(Functor functor,
-     const P1& p1,
-     const P2& p2,
-     const P3& p3,
-     const P4& p4,
-     const P5& p5) {
-  // Typedefs for how to store and run the functor.
-  typedef
-      typename cef_internal::FunctorTraits<Functor>::RunnableType RunnableType;
-  typedef typename cef_internal::FunctorTraits<Functor>::RunType RunType;
-
-  // Use RunnableType::RunType instead of RunType above because our
-  // checks should below for bound references need to know what the actual
-  // functor is going to interpret the argument as.
-  typedef cef_internal::FunctionTraits<typename RunnableType::RunType>
-      BoundFunctorTraits;
-
-  // Do not allow binding a non-const reference parameter. Non-const reference
-  // parameters are disallowed by the Google style guide.  Also, binding a
-  // non-const reference parameter can make for subtle bugs because the
-  // invoked function will receive a reference to the stored copy of the
-  // argument and not the original.
-  COMPILE_ASSERT(
-      !(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A4Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A5Type>::value),
-      do_not_bind_functions_with_nonconst_ref);
-
-  // For methods, we need to be careful for parameter 1.  We do not require
-  // a scoped_refptr because BindState<> itself takes care of AddRef() for
-  // methods. We also disallow binding of an array as the method's target
-  // object.
-  COMPILE_ASSERT(cef_internal::HasIsMethodTag<RunnableType>::value ||
-                     !cef_internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
-                 p1_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::HasIsMethodTag<RunnableType>::value ||
-                     !is_array<P1>::value,
-                 first_bound_argument_to_method_cannot_be_array);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
-                 p2_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
-                 p3_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
-                 p4_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P5>::value,
-                 p5_is_refcounted_type_and_needs_scoped_refptr);
-  typedef cef_internal::BindState<
-      RunnableType, RunType,
-      void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
-           typename cef_internal::CallbackParamTraits<P2>::StorageType,
-           typename cef_internal::CallbackParamTraits<P3>::StorageType,
-           typename cef_internal::CallbackParamTraits<P4>::StorageType,
-           typename cef_internal::CallbackParamTraits<P5>::StorageType)>
-      BindState;
-
-  return Callback<typename BindState::UnboundRunType>(
-      new BindState(cef_internal::MakeRunnable(functor), p1, p2, p3, p4, p5));
+///
+/// Unretained() allows binding a non-refcounted class, and to disable
+/// refcounting on arguments that are refcounted objects.
+///
+/// EXAMPLE OF Unretained():
+///
+/// <pre>
+///   class Foo {
+///    public:
+///     void func() { cout << "Foo:f" << endl; }
+///   };
+///
+///   // In some function somewhere.
+///   Foo foo;
+///   OnceClosure foo_callback =
+///       BindOnce(&Foo::func, Unretained(&foo));
+///   std::move(foo_callback).Run();  // Prints "Foo:f".
+/// </pre>
+///
+/// Without the Unretained() wrapper on |&foo|, the above call would fail
+/// to compile because Foo does not support the AddRef() and Release() methods.
+///
+template <typename T>
+inline cef_internal::UnretainedWrapper<T> Unretained(T* o) {
+  return cef_internal::UnretainedWrapper<T>(o);
 }
 
-template <typename Functor,
-          typename P1,
-          typename P2,
-          typename P3,
-          typename P4,
-          typename P5,
-          typename P6>
-base::Callback<typename cef_internal::BindState<
-    typename cef_internal::FunctorTraits<Functor>::RunnableType,
-    typename cef_internal::FunctorTraits<Functor>::RunType,
-    void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
-         typename cef_internal::CallbackParamTraits<P2>::StorageType,
-         typename cef_internal::CallbackParamTraits<P3>::StorageType,
-         typename cef_internal::CallbackParamTraits<P4>::StorageType,
-         typename cef_internal::CallbackParamTraits<P5>::StorageType,
-         typename cef_internal::CallbackParamTraits<P6>::StorageType)>::
-                   UnboundRunType>
-Bind(Functor functor,
-     const P1& p1,
-     const P2& p2,
-     const P3& p3,
-     const P4& p4,
-     const P5& p5,
-     const P6& p6) {
-  // Typedefs for how to store and run the functor.
-  typedef
-      typename cef_internal::FunctorTraits<Functor>::RunnableType RunnableType;
-  typedef typename cef_internal::FunctorTraits<Functor>::RunType RunType;
-
-  // Use RunnableType::RunType instead of RunType above because our
-  // checks should below for bound references need to know what the actual
-  // functor is going to interpret the argument as.
-  typedef cef_internal::FunctionTraits<typename RunnableType::RunType>
-      BoundFunctorTraits;
-
-  // Do not allow binding a non-const reference parameter. Non-const reference
-  // parameters are disallowed by the Google style guide.  Also, binding a
-  // non-const reference parameter can make for subtle bugs because the
-  // invoked function will receive a reference to the stored copy of the
-  // argument and not the original.
-  COMPILE_ASSERT(
-      !(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A4Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A5Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A6Type>::value),
-      do_not_bind_functions_with_nonconst_ref);
-
-  // For methods, we need to be careful for parameter 1.  We do not require
-  // a scoped_refptr because BindState<> itself takes care of AddRef() for
-  // methods. We also disallow binding of an array as the method's target
-  // object.
-  COMPILE_ASSERT(cef_internal::HasIsMethodTag<RunnableType>::value ||
-                     !cef_internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
-                 p1_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::HasIsMethodTag<RunnableType>::value ||
-                     !is_array<P1>::value,
-                 first_bound_argument_to_method_cannot_be_array);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
-                 p2_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
-                 p3_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
-                 p4_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P5>::value,
-                 p5_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P6>::value,
-                 p6_is_refcounted_type_and_needs_scoped_refptr);
-  typedef cef_internal::BindState<
-      RunnableType, RunType,
-      void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
-           typename cef_internal::CallbackParamTraits<P2>::StorageType,
-           typename cef_internal::CallbackParamTraits<P3>::StorageType,
-           typename cef_internal::CallbackParamTraits<P4>::StorageType,
-           typename cef_internal::CallbackParamTraits<P5>::StorageType,
-           typename cef_internal::CallbackParamTraits<P6>::StorageType)>
-      BindState;
-
-  return Callback<typename BindState::UnboundRunType>(new BindState(
-      cef_internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6));
+///
+/// RetainedRef() accepts a ref counted object and retains a reference to it.
+/// When the callback is called, the object is passed as a raw pointer.
+///
+/// EXAMPLE OF RetainedRef():
+///
+/// <pre>
+///    void foo(RefCountedBytes* bytes) {}
+///
+///    scoped_refptr<RefCountedBytes> bytes = ...;
+///    OnceClosure callback = BindOnce(&foo, base::RetainedRef(bytes));
+///    std::move(callback).Run();
+/// </pre>
+///
+/// Without RetainedRef, the scoped_refptr would try to implicitly convert to
+/// a raw pointer and fail compilation:
+///
+/// <pre>
+///    OnceClosure callback = BindOnce(&foo, bytes); // ERROR!
+/// </pre>
+///
+template <typename T>
+inline cef_internal::RetainedRefWrapper<T> RetainedRef(T* o) {
+  return cef_internal::RetainedRefWrapper<T>(o);
+}
+template <typename T>
+inline cef_internal::RetainedRefWrapper<T> RetainedRef(scoped_refptr<T> o) {
+  return cef_internal::RetainedRefWrapper<T>(std::move(o));
 }
 
-template <typename Functor,
-          typename P1,
-          typename P2,
-          typename P3,
-          typename P4,
-          typename P5,
-          typename P6,
-          typename P7>
-base::Callback<typename cef_internal::BindState<
-    typename cef_internal::FunctorTraits<Functor>::RunnableType,
-    typename cef_internal::FunctorTraits<Functor>::RunType,
-    void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
-         typename cef_internal::CallbackParamTraits<P2>::StorageType,
-         typename cef_internal::CallbackParamTraits<P3>::StorageType,
-         typename cef_internal::CallbackParamTraits<P4>::StorageType,
-         typename cef_internal::CallbackParamTraits<P5>::StorageType,
-         typename cef_internal::CallbackParamTraits<P6>::StorageType,
-         typename cef_internal::CallbackParamTraits<P7>::StorageType)>::
-                   UnboundRunType>
-Bind(Functor functor,
-     const P1& p1,
-     const P2& p2,
-     const P3& p3,
-     const P4& p4,
-     const P5& p5,
-     const P6& p6,
-     const P7& p7) {
-  // Typedefs for how to store and run the functor.
-  typedef
-      typename cef_internal::FunctorTraits<Functor>::RunnableType RunnableType;
-  typedef typename cef_internal::FunctorTraits<Functor>::RunType RunType;
-
-  // Use RunnableType::RunType instead of RunType above because our
-  // checks should below for bound references need to know what the actual
-  // functor is going to interpret the argument as.
-  typedef cef_internal::FunctionTraits<typename RunnableType::RunType>
-      BoundFunctorTraits;
-
-  // Do not allow binding a non-const reference parameter. Non-const reference
-  // parameters are disallowed by the Google style guide.  Also, binding a
-  // non-const reference parameter can make for subtle bugs because the
-  // invoked function will receive a reference to the stored copy of the
-  // argument and not the original.
-  COMPILE_ASSERT(
-      !(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A4Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A5Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A6Type>::value ||
-        is_non_const_reference<typename BoundFunctorTraits::A7Type>::value),
-      do_not_bind_functions_with_nonconst_ref);
-
-  // For methods, we need to be careful for parameter 1.  We do not require
-  // a scoped_refptr because BindState<> itself takes care of AddRef() for
-  // methods. We also disallow binding of an array as the method's target
-  // object.
-  COMPILE_ASSERT(cef_internal::HasIsMethodTag<RunnableType>::value ||
-                     !cef_internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
-                 p1_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::HasIsMethodTag<RunnableType>::value ||
-                     !is_array<P1>::value,
-                 first_bound_argument_to_method_cannot_be_array);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
-                 p2_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
-                 p3_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
-                 p4_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P5>::value,
-                 p5_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P6>::value,
-                 p6_is_refcounted_type_and_needs_scoped_refptr);
-  COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr<P7>::value,
-                 p7_is_refcounted_type_and_needs_scoped_refptr);
-  typedef cef_internal::BindState<
-      RunnableType, RunType,
-      void(typename cef_internal::CallbackParamTraits<P1>::StorageType,
-           typename cef_internal::CallbackParamTraits<P2>::StorageType,
-           typename cef_internal::CallbackParamTraits<P3>::StorageType,
-           typename cef_internal::CallbackParamTraits<P4>::StorageType,
-           typename cef_internal::CallbackParamTraits<P5>::StorageType,
-           typename cef_internal::CallbackParamTraits<P6>::StorageType,
-           typename cef_internal::CallbackParamTraits<P7>::StorageType)>
-      BindState;
-
-  return Callback<typename BindState::UnboundRunType>(new BindState(
-      cef_internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6, p7));
+///
+/// Owned() transfers ownership of an object to the callback resulting from
+/// bind; the object will be deleted when the callback is deleted.
+///
+/// EXAMPLE OF Owned():
+///
+/// <pre>
+///   void foo(int* arg) { cout << *arg << endl }
+///
+///   int* pn = new int(1);
+///   RepeatingClosure foo_callback = BindRepeating(&foo, Owned(pn));
+///
+///   foo_callback.Run();  // Prints "1"
+///   foo_callback.Run();  // Prints "1"
+///   *pn = 2;
+///   foo_callback.Run();  // Prints "2"
+///
+///   foo_callback.Reset();  // |pn| is deleted.  Also will happen when
+///                          // |foo_callback| goes out of scope.
+/// </pre>
+///
+/// Without Owned(), someone would have to know to delete |pn| when the last
+/// reference to the callback is deleted.
+///
+template <typename T>
+inline cef_internal::OwnedWrapper<T> Owned(T* o) {
+  return cef_internal::OwnedWrapper<T>(o);
 }
 
+template <typename T, typename Deleter>
+inline cef_internal::OwnedWrapper<T, Deleter> Owned(
+    std::unique_ptr<T, Deleter>&& ptr) {
+  return cef_internal::OwnedWrapper<T, Deleter>(std::move(ptr));
+}
+
+///
+/// OwnedRef() stores an object in the callback resulting from
+/// bind and passes a reference to the object to the bound function.
+///
+/// EXAMPLE OF OwnedRef():
+///
+/// <pre>
+///   void foo(int& arg) { cout << ++arg << endl }
+///
+///   int counter = 0;
+///   RepeatingClosure foo_callback = BindRepeating(&foo, OwnedRef(counter));
+///
+///   foo_callback.Run();  // Prints "1"
+///   foo_callback.Run();  // Prints "2"
+///   foo_callback.Run();  // Prints "3"
+///
+///   cout << counter;     // Prints "0", OwnedRef creates a copy of counter.
+/// </pre>
+///
+///  Supports OnceCallbacks as well, useful to pass placeholder arguments:
+///
+/// <pre>
+///   void bar(int& ignore, const std::string& s) { cout << s << endl }
+///
+///   OnceClosure bar_callback = BindOnce(&bar, OwnedRef(0), "Hello");
+///
+///   std::move(bar_callback).Run(); // Prints "Hello"
+/// </pre>
+///
+/// Without OwnedRef() it would not be possible to pass a mutable reference to
+/// an object owned by the callback.
+///
+template <typename T>
+cef_internal::OwnedRefWrapper<std::decay_t<T>> OwnedRef(T&& t) {
+  return cef_internal::OwnedRefWrapper<std::decay_t<T>>(std::forward<T>(t));
+}
+
+///
+/// Passed() is for transferring movable-but-not-copyable types (eg. unique_ptr)
+/// through a RepeatingCallback. Logically, this signifies a destructive
+/// transfer of the state of the argument into the target function. Invoking
+/// RepeatingCallback::Run() twice on a callback that was created with a
+/// Passed() argument will CHECK() because the first invocation would have
+/// already transferred ownership to the target function.
+///
+/// Note that Passed() is not necessary with BindOnce(), as std::move() does the
+/// same thing. Avoid Passed() in favor of std::move() with BindOnce().
+///
+/// EXAMPLE OF Passed():
+///
+/// <pre>
+///   void TakesOwnership(std::unique_ptr<Foo> arg) { }
+///   std::unique_ptr<Foo> CreateFoo() { return std::make_unique<Foo>();
+///   }
+///
+///   auto f = std::make_unique<Foo>();
+///
+///   // |cb| is given ownership of Foo(). |f| is now NULL.
+///   // You can use std::move(f) in place of &f, but it's more verbose.
+///   RepeatingClosure cb = BindRepeating(&TakesOwnership, Passed(&f));
+///
+///   // Run was never called so |cb| still owns Foo() and deletes
+///   // it on Reset().
+///   cb.Reset();
+///
+///   // |cb| is given a new Foo created by CreateFoo().
+///   cb = BindRepeating(&TakesOwnership, Passed(CreateFoo()));
+///
+///   // |arg| in TakesOwnership() is given ownership of Foo(). |cb|
+///   // no longer owns Foo() and, if reset, would not delete Foo().
+///   cb.Run();  // Foo() is now transferred to |arg| and deleted.
+///   cb.Run();  // This CHECK()s since Foo() already been used once.
+/// </pre>
+///
+/// We offer 2 syntaxes for calling Passed(). The first takes an rvalue and is
+/// best suited for use with the return value of a function or other temporary
+/// rvalues. The second takes a pointer to the scoper and is just syntactic
+/// sugar to avoid having to write Passed(std::move(scoper)).
+///
+/// Both versions of Passed() prevent T from being an lvalue reference. The
+/// first via use of enable_if, and the second takes a T* which will not bind to
+/// T&.
+///
+template <typename T,
+          std::enable_if_t<!std::is_lvalue_reference<T>::value>* = nullptr>
+inline cef_internal::PassedWrapper<T> Passed(T&& scoper) {
+  return cef_internal::PassedWrapper<T>(std::move(scoper));
+}
+template <typename T>
+inline cef_internal::PassedWrapper<T> Passed(T* scoper) {
+  return cef_internal::PassedWrapper<T>(std::move(*scoper));
+}
+
+///
+/// IgnoreResult() is used to adapt a function or callback with a return type to
+/// one with a void return. This is most useful if you have a function with,
+/// say, a pesky ignorable bool return that you want to use with PostTask or
+/// something else that expect a callback with a void return.
+///
+/// EXAMPLE OF IgnoreResult():
+///
+/// <pre>
+///   int DoSomething(int arg) { cout << arg << endl; }
+///
+///   // Assign to a callback with a void return type.
+///   OnceCallback<void(int)> cb = BindOnce(IgnoreResult(&DoSomething));
+///   std::move(cb).Run(1);  // Prints "1".
+///
+///   // Prints "2" on |ml|.
+///   ml->PostTask(FROM_HERE, BindOnce(IgnoreResult(&DoSomething), 2);
+/// </pre>
+///
+template <typename T>
+inline cef_internal::IgnoreResultHelper<T> IgnoreResult(T data) {
+  return cef_internal::IgnoreResultHelper<T>(std::move(data));
+}
+
+#if defined(OS_APPLE) && !HAS_FEATURE(objc_arc)
+
+///
+/// RetainBlock() is used to adapt an Objective-C block when Automated Reference
+/// Counting (ARC) is disabled. This is unnecessary when ARC is enabled, as the
+/// BindOnce and BindRepeating already support blocks then.
+///
+/// EXAMPLE OF RetainBlock():
+///
+/// <pre>
+///   // Wrap the block and bind it to a callback.
+///   OnceCallback<void(int)> cb =
+///       BindOnce(RetainBlock(^(int n) { NSLog(@"%d", n); }));
+///   std::move(cb).Run(1);  // Logs "1".
+/// </pre>
+///
+template <typename R, typename... Args>
+base::mac::ScopedBlock<R (^)(Args...)> RetainBlock(R (^block)(Args...)) {
+  return base::mac::ScopedBlock<R (^)(Args...)>(block,
+                                                base::scoped_policy::RETAIN);
+}
+
+#endif  // defined(OS_APPLE) && !HAS_FEATURE(objc_arc)
+
 }  // namespace base
 
 #endif  // !USING_CHROMIUM_INCLUDES
diff --git a/src/include/base/cef_bind_helpers.h b/src/include/base/cef_bind_helpers.h
deleted file mode 100644
index 2b4798b..0000000
--- a/src/include/base/cef_bind_helpers.h
+++ /dev/null
@@ -1,579 +0,0 @@
-// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
-// Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This defines a set of argument wrappers and related factory methods that
-// can be used specify the refcounting and reference semantics of arguments
-// that are bound by the Bind() function in base/bind.h.
-//
-// It also defines a set of simple functions and utilities that people want
-// when using Callback<> and Bind().
-//
-//
-// ARGUMENT BINDING WRAPPERS
-//
-// The wrapper functions are base::Unretained(), base::Owned(), base::Passed(),
-// base::ConstRef(), and base::IgnoreResult().
-//
-// Unretained() allows Bind() to bind a non-refcounted class, and to disable
-// refcounting on arguments that are refcounted objects.
-//
-// Owned() transfers ownership of an object to the Callback resulting from
-// bind; the object will be deleted when the Callback is deleted.
-//
-// Passed() is for transferring movable-but-not-copyable types (eg. scoped_ptr)
-// through a Callback. Logically, this signifies a destructive transfer of
-// the state of the argument into the target function.  Invoking
-// Callback::Run() twice on a Callback that was created with a Passed()
-// argument will CHECK() because the first invocation would have already
-// transferred ownership to the target function.
-//
-// ConstRef() allows binding a constant reference to an argument rather
-// than a copy.
-//
-// IgnoreResult() is used to adapt a function or Callback with a return type to
-// one with a void return. This is most useful if you have a function with,
-// say, a pesky ignorable bool return that you want to use with PostTask or
-// something else that expect a Callback with a void return.
-//
-// EXAMPLE OF Unretained():
-//
-//   class Foo {
-//    public:
-//     void func() { cout << "Foo:f" << endl; }
-//   };
-//
-//   // In some function somewhere.
-//   Foo foo;
-//   Closure foo_callback =
-//       Bind(&Foo::func, Unretained(&foo));
-//   foo_callback.Run();  // Prints "Foo:f".
-//
-// Without the Unretained() wrapper on |&foo|, the above call would fail
-// to compile because Foo does not support the AddRef() and Release() methods.
-//
-//
-// EXAMPLE OF Owned():
-//
-//   void foo(int* arg) { cout << *arg << endl }
-//
-//   int* pn = new int(1);
-//   Closure foo_callback = Bind(&foo, Owned(pn));
-//
-//   foo_callback.Run();  // Prints "1"
-//   foo_callback.Run();  // Prints "1"
-//   *n = 2;
-//   foo_callback.Run();  // Prints "2"
-//
-//   foo_callback.Reset();  // |pn| is deleted.  Also will happen when
-//                          // |foo_callback| goes out of scope.
-//
-// Without Owned(), someone would have to know to delete |pn| when the last
-// reference to the Callback is deleted.
-//
-//
-// EXAMPLE OF ConstRef():
-//
-//   void foo(int arg) { cout << arg << endl }
-//
-//   int n = 1;
-//   Closure no_ref = Bind(&foo, n);
-//   Closure has_ref = Bind(&foo, ConstRef(n));
-//
-//   no_ref.Run();  // Prints "1"
-//   has_ref.Run();  // Prints "1"
-//
-//   n = 2;
-//   no_ref.Run();  // Prints "1"
-//   has_ref.Run();  // Prints "2"
-//
-// Note that because ConstRef() takes a reference on |n|, |n| must outlive all
-// its bound callbacks.
-//
-//
-// EXAMPLE OF IgnoreResult():
-//
-//   int DoSomething(int arg) { cout << arg << endl; }
-//
-//   // Assign to a Callback with a void return type.
-//   Callback<void(int)> cb = Bind(IgnoreResult(&DoSomething));
-//   cb->Run(1);  // Prints "1".
-//
-//   // Prints "1" on |ml|.
-//   ml->PostTask(FROM_HERE, Bind(IgnoreResult(&DoSomething), 1);
-//
-//
-// EXAMPLE OF Passed():
-//
-//   void TakesOwnership(scoped_ptr<Foo> arg) { }
-//   scoped_ptr<Foo> CreateFoo() { return scoped_ptr<Foo>(new Foo()); }
-//
-//   scoped_ptr<Foo> f(new Foo());
-//
-//   // |cb| is given ownership of Foo(). |f| is now NULL.
-//   // You can use f.Pass() in place of &f, but it's more verbose.
-//   Closure cb = Bind(&TakesOwnership, Passed(&f));
-//
-//   // Run was never called so |cb| still owns Foo() and deletes
-//   // it on Reset().
-//   cb.Reset();
-//
-//   // |cb| is given a new Foo created by CreateFoo().
-//   cb = Bind(&TakesOwnership, Passed(CreateFoo()));
-//
-//   // |arg| in TakesOwnership() is given ownership of Foo(). |cb|
-//   // no longer owns Foo() and, if reset, would not delete Foo().
-//   cb.Run();  // Foo() is now transferred to |arg| and deleted.
-//   cb.Run();  // This CHECK()s since Foo() already been used once.
-//
-// Passed() is particularly useful with PostTask() when you are transferring
-// ownership of an argument into a task, but don't necessarily know if the
-// task will always be executed. This can happen if the task is cancellable
-// or if it is posted to a MessageLoopProxy.
-//
-//
-// SIMPLE FUNCTIONS AND UTILITIES.
-//
-//   DoNothing() - Useful for creating a Closure that does nothing when called.
-//   DeletePointer<T>() - Useful for creating a Closure that will delete a
-//                        pointer when invoked. Only use this when necessary.
-//                        In most cases MessageLoop::DeleteSoon() is a better
-//                        fit.
-
-#ifndef CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_
-#define CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_
-#pragma once
-
-#if defined(BASE_BIND_HELPERS_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
-// When building CEF include the Chromium header directly.
-#include "base/bind_helpers.h"
-#else  // !USING_CHROMIUM_INCLUDES
-// The following is substantially similar to the Chromium implementation.
-// If the Chromium implementation diverges the below implementation should be
-// updated to match.
-
-#include "include/base/cef_basictypes.h"
-#include "include/base/cef_callback.h"
-#include "include/base/cef_template_util.h"
-#include "include/base/cef_weak_ptr.h"
-
-namespace base {
-namespace cef_internal {
-
-// Use the Substitution Failure Is Not An Error (SFINAE) trick to inspect T
-// for the existence of AddRef() and Release() functions of the correct
-// signature.
-//
-// http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
-// http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence
-// http://stackoverflow.com/questions/4358584/sfinae-approach-comparison
-// http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions
-//
-// The last link in particular show the method used below.
-//
-// For SFINAE to work with inherited methods, we need to pull some extra tricks
-// with multiple inheritance.  In the more standard formulation, the overloads
-// of Check would be:
-//
-//   template <typename C>
-//   Yes NotTheCheckWeWant(Helper<&C::TargetFunc>*);
-//
-//   template <typename C>
-//   No NotTheCheckWeWant(...);
-//
-//   static const bool value = sizeof(NotTheCheckWeWant<T>(0)) == sizeof(Yes);
-//
-// The problem here is that template resolution will not match
-// C::TargetFunc if TargetFunc does not exist directly in C.  That is, if
-// TargetFunc in inherited from an ancestor, &C::TargetFunc will not match,
-// |value| will be false.  This formulation only checks for whether or
-// not TargetFunc exist directly in the class being introspected.
-//
-// To get around this, we play a dirty trick with multiple inheritance.
-// First, We create a class BaseMixin that declares each function that we
-// want to probe for.  Then we create a class Base that inherits from both T
-// (the class we wish to probe) and BaseMixin.  Note that the function
-// signature in BaseMixin does not need to match the signature of the function
-// we are probing for; thus it's easiest to just use void(void).
-//
-// Now, if TargetFunc exists somewhere in T, then &Base::TargetFunc has an
-// ambiguous resolution between BaseMixin and T.  This lets us write the
-// following:
-//
-//   template <typename C>
-//   No GoodCheck(Helper<&C::TargetFunc>*);
-//
-//   template <typename C>
-//   Yes GoodCheck(...);
-//
-//   static const bool value = sizeof(GoodCheck<Base>(0)) == sizeof(Yes);
-//
-// Notice here that the variadic version of GoodCheck() returns Yes here
-// instead of No like the previous one. Also notice that we calculate |value|
-// by specializing GoodCheck() on Base instead of T.
-//
-// We've reversed the roles of the variadic, and Helper overloads.
-// GoodCheck(Helper<&C::TargetFunc>*), when C = Base, fails to be a valid
-// substitution if T::TargetFunc exists. Thus GoodCheck<Base>(0) will resolve
-// to the variadic version if T has TargetFunc.  If T::TargetFunc does not
-// exist, then &C::TargetFunc is not ambiguous, and the overload resolution
-// will prefer GoodCheck(Helper<&C::TargetFunc>*).
-//
-// This method of SFINAE will correctly probe for inherited names, but it cannot
-// typecheck those names.  It's still a good enough sanity check though.
-//
-// Works on gcc-4.2, gcc-4.4, and Visual Studio 2008.
-//
-// TODO(ajwong): Move to ref_counted.h or template_util.h when we've vetted
-// this works well.
-//
-// TODO(ajwong): Make this check for Release() as well.
-// See http://crbug.com/82038.
-template <typename T>
-class SupportsAddRefAndRelease {
-  typedef char Yes[1];
-  typedef char No[2];
-
-  struct BaseMixin {
-    void AddRef();
-  };
-
-// MSVC warns when you try to use Base if T has a private destructor, the
-// common pattern for refcounted types. It does this even though no attempt to
-// instantiate Base is made.  We disable the warning for this definition.
-#if defined(OS_WIN)
-#pragma warning(push)
-#pragma warning(disable : 4624)
-#endif
-  struct Base : public T, public BaseMixin {};
-#if defined(OS_WIN)
-#pragma warning(pop)
-#endif
-
-  template <void (BaseMixin::*)(void)>
-  struct Helper {};
-
-  template <typename C>
-  static No& Check(Helper<&C::AddRef>*);
-
-  template <typename>
-  static Yes& Check(...);
-
- public:
-  static const bool value = sizeof(Check<Base>(0)) == sizeof(Yes);
-};
-
-// Helpers to assert that arguments of a recounted type are bound with a
-// scoped_refptr.
-template <bool IsClasstype, typename T>
-struct UnsafeBindtoRefCountedArgHelper : false_type {};
-
-template <typename T>
-struct UnsafeBindtoRefCountedArgHelper<true, T>
-    : integral_constant<bool, SupportsAddRefAndRelease<T>::value> {};
-
-template <typename T>
-struct UnsafeBindtoRefCountedArg : false_type {};
-
-template <typename T>
-struct UnsafeBindtoRefCountedArg<T*>
-    : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> {};
-
-template <typename T>
-class HasIsMethodTag {
-  typedef char Yes[1];
-  typedef char No[2];
-
-  template <typename U>
-  static Yes& Check(typename U::IsMethod*);
-
-  template <typename U>
-  static No& Check(...);
-
- public:
-  static const bool value = sizeof(Check<T>(0)) == sizeof(Yes);
-};
-
-template <typename T>
-class UnretainedWrapper {
- public:
-  explicit UnretainedWrapper(T* o) : ptr_(o) {}
-  T* get() const { return ptr_; }
-
- private:
-  T* ptr_;
-};
-
-template <typename T>
-class ConstRefWrapper {
- public:
-  explicit ConstRefWrapper(const T& o) : ptr_(&o) {}
-  const T& get() const { return *ptr_; }
-
- private:
-  const T* ptr_;
-};
-
-template <typename T>
-struct IgnoreResultHelper {
-  explicit IgnoreResultHelper(T functor) : functor_(functor) {}
-
-  T functor_;
-};
-
-template <typename T>
-struct IgnoreResultHelper<Callback<T>> {
-  explicit IgnoreResultHelper(const Callback<T>& functor) : functor_(functor) {}
-
-  const Callback<T>& functor_;
-};
-
-// An alternate implementation is to avoid the destructive copy, and instead
-// specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to
-// a class that is essentially a scoped_ptr<>.
-//
-// The current implementation has the benefit though of leaving ParamTraits<>
-// fully in callback_internal.h as well as avoiding type conversions during
-// storage.
-template <typename T>
-class OwnedWrapper {
- public:
-  explicit OwnedWrapper(T* o) : ptr_(o) {}
-  ~OwnedWrapper() { delete ptr_; }
-  T* get() const { return ptr_; }
-  OwnedWrapper(const OwnedWrapper& other) {
-    ptr_ = other.ptr_;
-    other.ptr_ = NULL;
-  }
-
- private:
-  mutable T* ptr_;
-};
-
-// PassedWrapper is a copyable adapter for a scoper that ignores const.
-//
-// It is needed to get around the fact that Bind() takes a const reference to
-// all its arguments.  Because Bind() takes a const reference to avoid
-// unnecessary copies, it is incompatible with movable-but-not-copyable
-// types; doing a destructive "move" of the type into Bind() would violate
-// the const correctness.
-//
-// This conundrum cannot be solved without either C++11 rvalue references or
-// a O(2^n) blowup of Bind() templates to handle each combination of regular
-// types and movable-but-not-copyable types.  Thus we introduce a wrapper type
-// that is copyable to transmit the correct type information down into
-// BindState<>. Ignoring const in this type makes sense because it is only
-// created when we are explicitly trying to do a destructive move.
-//
-// Two notes:
-//  1) PassedWrapper supports any type that has a "Pass()" function.
-//     This is intentional. The whitelisting of which specific types we
-//     support is maintained by CallbackParamTraits<>.
-//  2) is_valid_ is distinct from NULL because it is valid to bind a "NULL"
-//     scoper to a Callback and allow the Callback to execute once.
-template <typename T>
-class PassedWrapper {
- public:
-  explicit PassedWrapper(T scoper) : is_valid_(true), scoper_(scoper.Pass()) {}
-  PassedWrapper(const PassedWrapper& other)
-      : is_valid_(other.is_valid_), scoper_(other.scoper_.Pass()) {}
-  T Pass() const {
-    CHECK(is_valid_);
-    is_valid_ = false;
-    return scoper_.Pass();
-  }
-
- private:
-  mutable bool is_valid_;
-  mutable T scoper_;
-};
-
-// Unwrap the stored parameters for the wrappers above.
-template <typename T>
-struct UnwrapTraits {
-  typedef const T& ForwardType;
-  static ForwardType Unwrap(const T& o) { return o; }
-};
-
-template <typename T>
-struct UnwrapTraits<UnretainedWrapper<T>> {
-  typedef T* ForwardType;
-  static ForwardType Unwrap(UnretainedWrapper<T> unretained) {
-    return unretained.get();
-  }
-};
-
-template <typename T>
-struct UnwrapTraits<ConstRefWrapper<T>> {
-  typedef const T& ForwardType;
-  static ForwardType Unwrap(ConstRefWrapper<T> const_ref) {
-    return const_ref.get();
-  }
-};
-
-template <typename T>
-struct UnwrapTraits<scoped_refptr<T>> {
-  typedef T* ForwardType;
-  static ForwardType Unwrap(const scoped_refptr<T>& o) { return o.get(); }
-};
-
-template <typename T>
-struct UnwrapTraits<WeakPtr<T>> {
-  typedef const WeakPtr<T>& ForwardType;
-  static ForwardType Unwrap(const WeakPtr<T>& o) { return o; }
-};
-
-template <typename T>
-struct UnwrapTraits<OwnedWrapper<T>> {
-  typedef T* ForwardType;
-  static ForwardType Unwrap(const OwnedWrapper<T>& o) { return o.get(); }
-};
-
-template <typename T>
-struct UnwrapTraits<PassedWrapper<T>> {
-  typedef T ForwardType;
-  static T Unwrap(PassedWrapper<T>& o) { return o.Pass(); }
-};
-
-// Utility for handling different refcounting semantics in the Bind()
-// function.
-template <bool is_method, typename T>
-struct MaybeRefcount;
-
-template <typename T>
-struct MaybeRefcount<false, T> {
-  static void AddRef(const T&) {}
-  static void Release(const T&) {}
-};
-
-template <typename T, size_t n>
-struct MaybeRefcount<false, T[n]> {
-  static void AddRef(const T*) {}
-  static void Release(const T*) {}
-};
-
-template <typename T>
-struct MaybeRefcount<true, T> {
-  static void AddRef(const T&) {}
-  static void Release(const T&) {}
-};
-
-template <typename T>
-struct MaybeRefcount<true, T*> {
-  static void AddRef(T* o) { o->AddRef(); }
-  static void Release(T* o) { o->Release(); }
-};
-
-// No need to additionally AddRef() and Release() since we are storing a
-// scoped_refptr<> inside the storage object already.
-template <typename T>
-struct MaybeRefcount<true, scoped_refptr<T>> {
-  static void AddRef(const scoped_refptr<T>& o) {}
-  static void Release(const scoped_refptr<T>& o) {}
-};
-
-template <typename T>
-struct MaybeRefcount<true, const T*> {
-  static void AddRef(const T* o) { o->AddRef(); }
-  static void Release(const T* o) { o->Release(); }
-};
-
-// IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a
-// method.  It is used internally by Bind() to select the correct
-// InvokeHelper that will no-op itself in the event the WeakPtr<> for
-// the target object is invalidated.
-//
-// P1 should be the type of the object that will be received of the method.
-template <bool IsMethod, typename P1>
-struct IsWeakMethod : public false_type {};
-
-template <typename T>
-struct IsWeakMethod<true, WeakPtr<T>> : public true_type {};
-
-template <typename T>
-struct IsWeakMethod<true, ConstRefWrapper<WeakPtr<T>>> : public true_type {};
-
-}  // namespace cef_internal
-
-template <typename T>
-static inline cef_internal::UnretainedWrapper<T> Unretained(T* o) {
-  return cef_internal::UnretainedWrapper<T>(o);
-}
-
-template <typename T>
-static inline cef_internal::ConstRefWrapper<T> ConstRef(const T& o) {
-  return cef_internal::ConstRefWrapper<T>(o);
-}
-
-template <typename T>
-static inline cef_internal::OwnedWrapper<T> Owned(T* o) {
-  return cef_internal::OwnedWrapper<T>(o);
-}
-
-// We offer 2 syntaxes for calling Passed().  The first takes a temporary and
-// is best suited for use with the return value of a function. The second
-// takes a pointer to the scoper and is just syntactic sugar to avoid having
-// to write Passed(scoper.Pass()).
-template <typename T>
-static inline cef_internal::PassedWrapper<T> Passed(T scoper) {
-  return cef_internal::PassedWrapper<T>(scoper.Pass());
-}
-template <typename T>
-static inline cef_internal::PassedWrapper<T> Passed(T* scoper) {
-  return cef_internal::PassedWrapper<T>(scoper->Pass());
-}
-
-template <typename T>
-static inline cef_internal::IgnoreResultHelper<T> IgnoreResult(T data) {
-  return cef_internal::IgnoreResultHelper<T>(data);
-}
-
-template <typename T>
-static inline cef_internal::IgnoreResultHelper<Callback<T>> IgnoreResult(
-    const Callback<T>& data) {
-  return cef_internal::IgnoreResultHelper<Callback<T>>(data);
-}
-
-void DoNothing();
-
-template <typename T>
-void DeletePointer(T* obj) {
-  delete obj;
-}
-
-}  // namespace base
-
-#endif  // !USING_CHROMIUM_INCLUDES
-
-#endif  // CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_
diff --git a/src/include/base/cef_build.h b/src/include/base/cef_build.h
index 61dc317..d32c617 100644
--- a/src/include/base/cef_build.h
+++ b/src/include/base/cef_build.h
@@ -27,53 +27,132 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+/// \file
+/// This file adds defines about the platform we're currently building on.
+///
+/// <pre>
+///  Operating System:
+///    OS_AIX / OS_ANDROID / OS_ASMJS / OS_FREEBSD / OS_FUCHSIA / OS_IOS /
+///    OS_LINUX / OS_MAC / OS_NACL (SFI or NONSFI) / OS_NETBSD / OS_OPENBSD /
+///    OS_QNX / OS_SOLARIS / OS_WIN
+///  Operating System family:
+///    OS_APPLE: IOS or MAC
+///    OS_BSD: FREEBSD or NETBSD or OPENBSD
+///    OS_POSIX: AIX or ANDROID or ASMJS or CHROMEOS or FREEBSD or IOS or LINUX
+///              or MAC or NACL or NETBSD or OPENBSD or QNX or SOLARIS
+///
+///  /!\ Note: OS_CHROMEOS is set by the build system, not this file
+///
+///  Compiler:
+///    COMPILER_MSVC / COMPILER_GCC
+///
+///  Processor:
+///    ARCH_CPU_ARM64 / ARCH_CPU_ARMEL / ARCH_CPU_MIPS / ARCH_CPU_MIPS64 /
+///    ARCH_CPU_MIPS64EL / ARCH_CPU_MIPSEL / ARCH_CPU_PPC64 / ARCH_CPU_S390 /
+///    ARCH_CPU_S390X / ARCH_CPU_X86 / ARCH_CPU_X86_64
+///  Processor family:
+///    ARCH_CPU_ARM_FAMILY: ARMEL or ARM64
+///    ARCH_CPU_MIPS_FAMILY: MIPS64EL or MIPSEL or MIPS64 or MIPS
+///    ARCH_CPU_PPC64_FAMILY: PPC64
+///    ARCH_CPU_S390_FAMILY: S390 or S390X
+///    ARCH_CPU_X86_FAMILY: X86 or X86_64
+///  Processor features:
+///    ARCH_CPU_31_BITS / ARCH_CPU_32_BITS / ARCH_CPU_64_BITS
+///    ARCH_CPU_BIG_ENDIAN / ARCH_CPU_LITTLE_ENDIAN
+/// </pre>
+///
+
 #ifndef CEF_INCLUDE_BASE_CEF_BUILD_H_
 #define CEF_INCLUDE_BASE_CEF_BUILD_H_
 #pragma once
 
 #if defined(USING_CHROMIUM_INCLUDES)
 // When building CEF include the Chromium header directly.
-#include "base/compiler_specific.h"
+#include "build/build_config.h"
 #else  // !USING_CHROMIUM_INCLUDES
 // The following is substantially similar to the Chromium implementation.
 // If the Chromium implementation diverges the below implementation should be
 // updated to match.
 
-#if defined(_WIN32)
-#ifndef OS_WIN
-#define OS_WIN 1
-#endif
+// A set of macros to use for platform detection.
+#if defined(ANDROID)
+#define OS_ANDROID 1
 #elif defined(__APPLE__)
-#ifndef OS_MACOSX
-#define OS_MACOSX 1
-#endif
-#elif defined(__linux__)
-#ifndef OS_LINUX
-#define OS_LINUX 1
-#endif
+// Only include TargetConditionals after testing ANDROID as some Android builds
+// on the Mac have this header available and it's not needed unless the target
+// is really an Apple platform.
+#include <TargetConditionals.h>
+#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
+#define OS_IOS 1
 #else
-#error Please add support for your platform in cef_build.h
+#define OS_MAC 1
+// For backwards compatibility.
+#define OS_MACOSX 1
+#endif  // defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
+#elif defined(__linux__)
+#if !defined(OS_CHROMEOS)
+// Do not define OS_LINUX on Chrome OS build.
+// The OS_CHROMEOS macro is defined in GN.
+#define OS_LINUX 1
+#endif  // !defined(OS_CHROMEOS)
+// Include a system header to pull in features.h for glibc/uclibc macros.
+#include <unistd.h>
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
+// We really are using glibc, not uClibc pretending to be glibc.
+#define LIBC_GLIBC 1
+#endif
+#elif defined(_WIN32)
+#define OS_WIN 1
+#elif defined(__Fuchsia__)
+#define OS_FUCHSIA 1
+#elif defined(__FreeBSD__)
+#define OS_FREEBSD 1
+#elif defined(__NetBSD__)
+#define OS_NETBSD 1
+#elif defined(__OpenBSD__)
+#define OS_OPENBSD 1
+#elif defined(__sun)
+#define OS_SOLARIS 1
+#elif defined(__QNXNTO__)
+#define OS_QNX 1
+#elif defined(_AIX)
+#define OS_AIX 1
+#elif defined(__asmjs__) || defined(__wasm__)
+#define OS_ASMJS 1
+#else
+#error Please add support for your platform in include/base/cef_build.h
+#endif
+// NOTE: Adding a new port? Please follow
+// https://chromium.googlesource.com/chromium/src/+/master/docs/new_port_policy.md
+
+#if defined(OS_MAC) || defined(OS_IOS)
+#define OS_APPLE 1
+#endif
+
+// For access to standard BSD features, use OS_BSD instead of a
+// more specific macro.
+#if defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_OPENBSD)
+#define OS_BSD 1
 #endif
 
 // For access to standard POSIXish features, use OS_POSIX instead of a
 // more specific macro.
-#if defined(OS_MACOSX) || defined(OS_LINUX)
-#ifndef OS_POSIX
+#if defined(OS_AIX) || defined(OS_ANDROID) || defined(OS_ASMJS) ||  \
+    defined(OS_FREEBSD) || defined(OS_IOS) || defined(OS_LINUX) ||  \
+    defined(OS_CHROMEOS) || defined(OS_MAC) || defined(OS_NACL) ||  \
+    defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_QNX) || \
+    defined(OS_SOLARIS)
 #define OS_POSIX 1
 #endif
-#endif
 
-// Compiler detection.
+// Compiler detection. Note: clang masquerades as GCC on POSIX and as MSVC on
+// Windows.
 #if defined(__GNUC__)
-#ifndef COMPILER_GCC
 #define COMPILER_GCC 1
-#endif
 #elif defined(_MSC_VER)
-#ifndef COMPILER_MSVC
 #define COMPILER_MSVC 1
-#endif
 #else
-#error Please add support for your compiler in cef_build.h
+#error Please add support for your compiler in build/build_config.h
 #endif
 
 // Processor architecture detection.  For more info on what's defined, see:
@@ -90,6 +169,26 @@
 #define ARCH_CPU_X86 1
 #define ARCH_CPU_32_BITS 1
 #define ARCH_CPU_LITTLE_ENDIAN 1
+#elif defined(__s390x__)
+#define ARCH_CPU_S390_FAMILY 1
+#define ARCH_CPU_S390X 1
+#define ARCH_CPU_64_BITS 1
+#define ARCH_CPU_BIG_ENDIAN 1
+#elif defined(__s390__)
+#define ARCH_CPU_S390_FAMILY 1
+#define ARCH_CPU_S390 1
+#define ARCH_CPU_31_BITS 1
+#define ARCH_CPU_BIG_ENDIAN 1
+#elif (defined(__PPC64__) || defined(__PPC__)) && defined(__BIG_ENDIAN__)
+#define ARCH_CPU_PPC64_FAMILY 1
+#define ARCH_CPU_PPC64 1
+#define ARCH_CPU_64_BITS 1
+#define ARCH_CPU_BIG_ENDIAN 1
+#elif defined(__PPC64__)
+#define ARCH_CPU_PPC64_FAMILY 1
+#define ARCH_CPU_PPC64 1
+#define ARCH_CPU_64_BITS 1
+#define ARCH_CPU_LITTLE_ENDIAN 1
 #elif defined(__ARMEL__)
 #define ARCH_CPU_ARM_FAMILY 1
 #define ARCH_CPU_ARMEL 1
@@ -100,21 +199,42 @@
 #define ARCH_CPU_ARM64 1
 #define ARCH_CPU_64_BITS 1
 #define ARCH_CPU_LITTLE_ENDIAN 1
-#elif defined(__pnacl__)
+#elif defined(__pnacl__) || defined(__asmjs__) || defined(__wasm__)
 #define ARCH_CPU_32_BITS 1
 #define ARCH_CPU_LITTLE_ENDIAN 1
 #elif defined(__MIPSEL__)
+#if defined(__LP64__)
+#define ARCH_CPU_MIPS_FAMILY 1
+#define ARCH_CPU_MIPS64EL 1
+#define ARCH_CPU_64_BITS 1
+#define ARCH_CPU_LITTLE_ENDIAN 1
+#else
 #define ARCH_CPU_MIPS_FAMILY 1
 #define ARCH_CPU_MIPSEL 1
 #define ARCH_CPU_32_BITS 1
 #define ARCH_CPU_LITTLE_ENDIAN 1
+#endif
+#elif defined(__MIPSEB__)
+#if defined(__LP64__)
+#define ARCH_CPU_MIPS_FAMILY 1
+#define ARCH_CPU_MIPS64 1
+#define ARCH_CPU_64_BITS 1
+#define ARCH_CPU_BIG_ENDIAN 1
 #else
-#error Please add support for your architecture in cef_build.h
+#define ARCH_CPU_MIPS_FAMILY 1
+#define ARCH_CPU_MIPS 1
+#define ARCH_CPU_32_BITS 1
+#define ARCH_CPU_BIG_ENDIAN 1
+#endif
+#else
+#error Please add support for your architecture in include/base/cef_build.h
 #endif
 
 // Type detection for wchar_t.
 #if defined(OS_WIN)
 #define WCHAR_T_IS_UTF16
+#elif defined(OS_FUCHSIA)
+#define WCHAR_T_IS_UTF32
 #elif defined(OS_POSIX) && defined(COMPILER_GCC) && defined(__WCHAR_MAX__) && \
     (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
 #define WCHAR_T_IS_UTF32
@@ -126,82 +246,18 @@
 // short wchar works for them.
 #define WCHAR_T_IS_UTF16
 #else
-#error Please add support for your compiler in cef_build.h
+#error Please add support for your compiler in include/base/cef_build.h
 #endif
 
-// Annotate a function indicating the caller must examine the return value.
-// Use like:
-//   int foo() WARN_UNUSED_RESULT;
-// To explicitly ignore a result, see |ignore_result()| in <base/macros.h>.
-#ifndef WARN_UNUSED_RESULT
-#if defined(COMPILER_GCC)
-#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
-#else
-#define WARN_UNUSED_RESULT
-#endif
-#endif  // WARN_UNUSED_RESULT
-
-// Annotate a typedef or function indicating it's ok if it's not used.
-// Use like:
-//   typedef Foo Bar ALLOW_UNUSED_TYPE;
-#ifndef ALLOW_UNUSED_TYPE
-#if defined(COMPILER_GCC)
-#define ALLOW_UNUSED_TYPE __attribute__((unused))
-#else
-#define ALLOW_UNUSED_TYPE
-#endif
-#endif  // ALLOW_UNUSED_TYPE
-
-// Annotate a variable indicating it's ok if the variable is not used.
-// (Typically used to silence a compiler warning when the assignment
-// is important for some other reason.)
-// Use like:
-//   int x = ...;
-//   ALLOW_UNUSED_LOCAL(x);
-#ifndef ALLOW_UNUSED_LOCAL
-#define ALLOW_UNUSED_LOCAL(x) false ? (void)x : (void)0
-#endif
-
-// Sanitizers annotations.
-#if defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-#define NO_SANITIZE(what) __attribute__((no_sanitize(what)))
-#endif
-#endif
-#if !defined(NO_SANITIZE)
-#define NO_SANITIZE(what)
+#if defined(OS_ANDROID)
+// The compiler thinks std::string::const_iterator and "const char*" are
+// equivalent types.
+#define STD_STRING_ITERATOR_IS_CHAR_POINTER
+// The compiler thinks std::u16string::const_iterator and "char16_t*" are
+// equivalent types.
+#define BASE_STRING16_ITERATOR_IS_CHAR16_POINTER
 #endif
 
 #endif  // !USING_CHROMIUM_INCLUDES
 
-// Annotate a virtual method indicating it must be overriding a virtual method
-// in the parent class.
-// Use like:
-//   void foo() OVERRIDE;
-// NOTE: This define should only be used in classes exposed to the client since
-// C++11 support may not be enabled in client applications. CEF internal classes
-// should use the `override` keyword directly.
-#ifndef OVERRIDE
-#if defined(__clang__)
-#define OVERRIDE override
-#elif defined(COMPILER_MSVC) && _MSC_VER >= 1600
-// Visual Studio 2010 and later support override.
-#define OVERRIDE override
-#elif defined(COMPILER_GCC) && __cplusplus >= 201103 && \
-    (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40700
-// GCC 4.7 supports explicit virtual overrides when C++11 support is enabled.
-#define OVERRIDE override
-#else
-#define OVERRIDE
-#endif
-#endif  // OVERRIDE
-
-// Check for C++11 template alias support which was added in VS2013 and GCC4.7.
-// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf
-#if __cplusplus > 199711L || (defined(_MSC_VER) && _MSC_VER >= 1800) || \
-    (defined(__GNUC__) &&                                               \
-     (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ >= 40700))
-#define HAS_CPP11_TEMPLATE_ALIAS_SUPPORT
-#endif
-
 #endif  // CEF_INCLUDE_BASE_CEF_BUILD_H_
diff --git a/src/include/base/cef_callback.h b/src/include/base/cef_callback.h
index 16e238a..bcfe499 100644
--- a/src/include/base/cef_callback.h
+++ b/src/include/base/cef_callback.h
@@ -28,772 +28,221 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+/// \file
+/// A callback is similar in concept to a function pointer: it wraps a runnable
+/// object such as a function, method, lambda, or even another callback,
+/// allowing the runnable object to be invoked later via the callback object.
+///
+/// Unlike function pointers, callbacks are created with base::BindOnce() or
+/// base::BindRepeating() and support partial function application.
+///
+/// A base::OnceCallback may be Run() at most once; a base::RepeatingCallback
+/// may be Run() any number of times. |is_null()| is guaranteed to return true
+/// for a moved-from callback.
+///
+/// <pre>
+///   // The lambda takes two arguments, but the first argument |x| is bound at
+///   // callback creation.
+///   base::OnceCallback<int(int)> cb = base::BindOnce([] (int x, int y) {
+///     return x + y;
+///   }, 1);
+///   // Run() only needs the remaining unbound argument |y|.
+///   printf("1 + 2 = %d\n", std::move(cb).Run(2));  // Prints 3
+///   printf("cb is null? %s\n",
+///          cb.is_null() ? "true" : "false");  // Prints true
+///   std::move(cb).Run(2);  // Crashes since |cb| has already run.
+/// </pre>
+///
+/// Callbacks also support cancellation. A common use is binding the receiver
+/// object as a WeakPtr<T>. If that weak pointer is invalidated, calling Run()
+/// will be a no-op. Note that |IsCancelled()| and |is_null()| are distinct:
+/// simply cancelling a callback will not also make it null.
+///
+/// See https://chromium.googlesource.com/chromium/src/+/lkgr/docs/callback.md
+/// for the full documentation.
+
 #ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_H_
 #define CEF_INCLUDE_BASE_CEF_CALLBACK_H_
 #pragma once
 
-#if defined(BASE_CALLBACK_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
+#if defined(USING_CHROMIUM_INCLUDES)
 // When building CEF include the Chromium header directly.
-#include "base/callback.h"
+#include "base/functional/callback.h"
 #else  // !USING_CHROMIUM_INCLUDES
 // The following is substantially similar to the Chromium implementation.
 // If the Chromium implementation diverges the below implementation should be
 // updated to match.
 
+#include <stddef.h>
+
+#include "include/base/cef_bind.h"
 #include "include/base/cef_callback_forward.h"
-#include "include/base/cef_template_util.h"
+#include "include/base/cef_logging.h"
 #include "include/base/internal/cef_callback_internal.h"
 
-// NOTE: Header files that do not require the full definition of Callback or
-// Closure should #include "base/cef_callback_forward.h" instead of this file.
-
-// -----------------------------------------------------------------------------
-// Introduction
-// -----------------------------------------------------------------------------
-//
-// The templated Callback class is a generalized function object. Together
-// with the Bind() function in bind.h, they provide a type-safe method for
-// performing partial application of functions.
-//
-// Partial application (or "currying") is the process of binding a subset of
-// a function's arguments to produce another function that takes fewer
-// arguments. This can be used to pass around a unit of delayed execution,
-// much like lexical closures are used in other languages. For example, it
-// is used in Chromium code to schedule tasks on different MessageLoops.
-//
-// A callback with no unbound input parameters (base::Callback<void(void)>)
-// is called a base::Closure. Note that this is NOT the same as what other
-// languages refer to as a closure -- it does not retain a reference to its
-// enclosing environment.
-//
-// MEMORY MANAGEMENT AND PASSING
-//
-// The Callback objects themselves should be passed by const-reference, and
-// stored by copy. They internally store their state via a refcounted class
-// and thus do not need to be deleted.
-//
-// The reason to pass via a const-reference is to avoid unnecessary
-// AddRef/Release pairs to the internal state.
-//
-//
-// -----------------------------------------------------------------------------
-// Quick reference for basic stuff
-// -----------------------------------------------------------------------------
-//
-// BINDING A BARE FUNCTION
-//
-//   int Return5() { return 5; }
-//   base::Callback<int(void)> func_cb = base::Bind(&Return5);
-//   LOG(INFO) << func_cb.Run();  // Prints 5.
-//
-// BINDING A CLASS METHOD
-//
-//   The first argument to bind is the member function to call, the second is
-//   the object on which to call it.
-//
-//   class Ref : public base::RefCountedThreadSafe<Ref> {
-//    public:
-//     int Foo() { return 3; }
-//     void PrintBye() { LOG(INFO) << "bye."; }
-//   };
-//   scoped_refptr<Ref> ref = new Ref();
-//   base::Callback<void(void)> ref_cb = base::Bind(&Ref::Foo, ref);
-//   LOG(INFO) << ref_cb.Run();  // Prints out 3.
-//
-//   By default the object must support RefCounted or you will get a compiler
-//   error. If you're passing between threads, be sure it's
-//   RefCountedThreadSafe! See "Advanced binding of member functions" below if
-//   you don't want to use reference counting.
-//
-// RUNNING A CALLBACK
-//
-//   Callbacks can be run with their "Run" method, which has the same
-//   signature as the template argument to the callback.
-//
-//   void DoSomething(const base::Callback<void(int, std::string)>& callback) {
-//     callback.Run(5, "hello");
-//   }
-//
-//   Callbacks can be run more than once (they don't get deleted or marked when
-//   run). However, this precludes using base::Passed (see below).
-//
-//   void DoSomething(const base::Callback<double(double)>& callback) {
-//     double myresult = callback.Run(3.14159);
-//     myresult += callback.Run(2.71828);
-//   }
-//
-// PASSING UNBOUND INPUT PARAMETERS
-//
-//   Unbound parameters are specified at the time a callback is Run(). They are
-//   specified in the Callback template type:
-//
-//   void MyFunc(int i, const std::string& str) {}
-//   base::Callback<void(int, const std::string&)> cb = base::Bind(&MyFunc);
-//   cb.Run(23, "hello, world");
-//
-// PASSING BOUND INPUT PARAMETERS
-//
-//   Bound parameters are specified when you create thee callback as arguments
-//   to Bind(). They will be passed to the function and the Run()ner of the
-//   callback doesn't see those values or even know that the function it's
-//   calling.
-//
-//   void MyFunc(int i, const std::string& str) {}
-//   base::Callback<void(void)> cb = base::Bind(&MyFunc, 23, "hello world");
-//   cb.Run();
-//
-//   A callback with no unbound input parameters (base::Callback<void(void)>)
-//   is called a base::Closure. So we could have also written:
-//
-//   base::Closure cb = base::Bind(&MyFunc, 23, "hello world");
-//
-//   When calling member functions, bound parameters just go after the object
-//   pointer.
-//
-//   base::Closure cb = base::Bind(&MyClass::MyFunc, this, 23, "hello world");
-//
-// PARTIAL BINDING OF PARAMETERS
-//
-//   You can specify some parameters when you create the callback, and specify
-//   the rest when you execute the callback.
-//
-//   void MyFunc(int i, const std::string& str) {}
-//   base::Callback<void(const std::string&)> cb = base::Bind(&MyFunc, 23);
-//   cb.Run("hello world");
-//
-//   When calling a function bound parameters are first, followed by unbound
-//   parameters.
-//
-//
-// -----------------------------------------------------------------------------
-// Quick reference for advanced binding
-// -----------------------------------------------------------------------------
-//
-// BINDING A CLASS METHOD WITH WEAK POINTERS
-//
-//   base::Bind(&MyClass::Foo, GetWeakPtr());
-//
-//   The callback will not be run if the object has already been destroyed.
-//   DANGER: weak pointers are not threadsafe, so don't use this
-//   when passing between threads!
-//
-// BINDING A CLASS METHOD WITH MANUAL LIFETIME MANAGEMENT
-//
-//   base::Bind(&MyClass::Foo, base::Unretained(this));
-//
-//   This disables all lifetime management on the object. You're responsible
-//   for making sure the object is alive at the time of the call. You break it,
-//   you own it!
-//
-// BINDING A CLASS METHOD AND HAVING THE CALLBACK OWN THE CLASS
-//
-//   MyClass* myclass = new MyClass;
-//   base::Bind(&MyClass::Foo, base::Owned(myclass));
-//
-//   The object will be deleted when the callback is destroyed, even if it's
-//   not run (like if you post a task during shutdown). Potentially useful for
-//   "fire and forget" cases.
-//
-// IGNORING RETURN VALUES
-//
-//   Sometimes you want to call a function that returns a value in a callback
-//   that doesn't expect a return value.
-//
-//   int DoSomething(int arg) { cout << arg << endl; }
-//   base::Callback<void<int>) cb =
-//       base::Bind(base::IgnoreResult(&DoSomething));
-//
-//
-// -----------------------------------------------------------------------------
-// Quick reference for binding parameters to Bind()
-// -----------------------------------------------------------------------------
-//
-// Bound parameters are specified as arguments to Bind() and are passed to the
-// function. A callback with no parameters or no unbound parameters is called a
-// Closure (base::Callback<void(void)> and base::Closure are the same thing).
-//
-// PASSING PARAMETERS OWNED BY THE CALLBACK
-//
-//   void Foo(int* arg) { cout << *arg << endl; }
-//   int* pn = new int(1);
-//   base::Closure foo_callback = base::Bind(&foo, base::Owned(pn));
-//
-//   The parameter will be deleted when the callback is destroyed, even if it's
-//   not run (like if you post a task during shutdown).
-//
-// PASSING PARAMETERS AS A scoped_ptr
-//
-//   void TakesOwnership(scoped_ptr<Foo> arg) {}
-//   scoped_ptr<Foo> f(new Foo);
-//   // f becomes null during the following call.
-//   base::Closure cb = base::Bind(&TakesOwnership, base::Passed(&f));
-//
-//   Ownership of the parameter will be with the callback until the it is run,
-//   when ownership is passed to the callback function. This means the callback
-//   can only be run once. If the callback is never run, it will delete the
-//   object when it's destroyed.
-//
-// PASSING PARAMETERS AS A scoped_refptr
-//
-//   void TakesOneRef(scoped_refptr<Foo> arg) {}
-//   scoped_refptr<Foo> f(new Foo)
-//   base::Closure cb = base::Bind(&TakesOneRef, f);
-//
-//   This should "just work." The closure will take a reference as long as it
-//   is alive, and another reference will be taken for the called function.
-//
-// PASSING PARAMETERS BY REFERENCE
-//
-//   Const references are *copied* unless ConstRef is used. Example:
-//
-//   void foo(const int& arg) { printf("%d %p\n", arg, &arg); }
-//   int n = 1;
-//   base::Closure has_copy = base::Bind(&foo, n);
-//   base::Closure has_ref = base::Bind(&foo, base::ConstRef(n));
-//   n = 2;
-//   foo(n);                        // Prints "2 0xaaaaaaaaaaaa"
-//   has_copy.Run();                // Prints "1 0xbbbbbbbbbbbb"
-//   has_ref.Run();                 // Prints "2 0xaaaaaaaaaaaa"
-//
-//   Normally parameters are copied in the closure. DANGER: ConstRef stores a
-//   const reference instead, referencing the original parameter. This means
-//   that you must ensure the object outlives the callback!
-//
-//
-// -----------------------------------------------------------------------------
-// Implementation notes
-// -----------------------------------------------------------------------------
-//
-// WHERE IS THIS DESIGN FROM:
-//
-// The design Callback and Bind is heavily influenced by C++'s
-// tr1::function/tr1::bind, and by the "Google Callback" system used inside
-// Google.
-//
-//
-// HOW THE IMPLEMENTATION WORKS:
-//
-// There are three main components to the system:
-//   1) The Callback classes.
-//   2) The Bind() functions.
-//   3) The arguments wrappers (e.g., Unretained() and ConstRef()).
-//
-// The Callback classes represent a generic function pointer. Internally,
-// it stores a refcounted piece of state that represents the target function
-// and all its bound parameters.  Each Callback specialization has a templated
-// constructor that takes an BindState<>*.  In the context of the constructor,
-// the static type of this BindState<> pointer uniquely identifies the
-// function it is representing, all its bound parameters, and a Run() method
-// that is capable of invoking the target.
-//
-// Callback's constructor takes the BindState<>* that has the full static type
-// and erases the target function type as well as the types of the bound
-// parameters.  It does this by storing a pointer to the specific Run()
-// function, and upcasting the state of BindState<>* to a
-// BindStateBase*. This is safe as long as this BindStateBase pointer
-// is only used with the stored Run() pointer.
-//
-// To BindState<> objects are created inside the Bind() functions.
-// These functions, along with a set of internal templates, are responsible for
-//
-//  - Unwrapping the function signature into return type, and parameters
-//  - Determining the number of parameters that are bound
-//  - Creating the BindState storing the bound parameters
-//  - Performing compile-time asserts to avoid error-prone behavior
-//  - Returning an Callback<> with an arity matching the number of unbound
-//    parameters and that knows the correct refcounting semantics for the
-//    target object if we are binding a method.
-//
-// The Bind functions do the above using type-inference, and template
-// specializations.
-//
-// By default Bind() will store copies of all bound parameters, and attempt
-// to refcount a target object if the function being bound is a class method.
-// These copies are created even if the function takes parameters as const
-// references. (Binding to non-const references is forbidden, see bind.h.)
-//
-// To change this behavior, we introduce a set of argument wrappers
-// (e.g., Unretained(), and ConstRef()).  These are simple container templates
-// that are passed by value, and wrap a pointer to argument.  See the
-// file-level comment in base/bind_helpers.h for more info.
-//
-// These types are passed to the Unwrap() functions, and the MaybeRefcount()
-// functions respectively to modify the behavior of Bind().  The Unwrap()
-// and MaybeRefcount() functions change behavior by doing partial
-// specialization based on whether or not a parameter is a wrapper type.
-//
-// ConstRef() is similar to tr1::cref.  Unretained() is specific to Chromium.
-//
-//
-// WHY NOT TR1 FUNCTION/BIND?
-//
-// Direct use of tr1::function and tr1::bind was considered, but ultimately
-// rejected because of the number of copy constructors invocations involved
-// in the binding of arguments during construction, and the forwarding of
-// arguments during invocation.  These copies will no longer be an issue in
-// C++0x because C++0x will support rvalue reference allowing for the compiler
-// to avoid these copies.  However, waiting for C++0x is not an option.
-//
-// Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the
-// tr1::bind call itself will invoke a non-trivial copy constructor three times
-// for each bound parameter.  Also, each when passing a tr1::function, each
-// bound argument will be copied again.
-//
-// In addition to the copies taken at binding and invocation, copying a
-// tr1::function causes a copy to be made of all the bound parameters and
-// state.
-//
-// Furthermore, in Chromium, it is desirable for the Callback to take a
-// reference on a target object when representing a class method call.  This
-// is not supported by tr1.
-//
-// Lastly, tr1::function and tr1::bind has a more general and flexible API.
-// This includes things like argument reordering by use of
-// tr1::bind::placeholder, support for non-const reference parameters, and some
-// limited amount of subtyping of the tr1::function object (e.g.,
-// tr1::function<int(int)> is convertible to tr1::function<void(int)>).
-//
-// These are not features that are required in Chromium. Some of them, such as
-// allowing for reference parameters, and subtyping of functions, may actually
-// become a source of errors. Removing support for these features actually
-// allows for a simpler implementation, and a terser Currying API.
-//
-//
-// WHY NOT GOOGLE CALLBACKS?
-//
-// The Google callback system also does not support refcounting.  Furthermore,
-// its implementation has a number of strange edge cases with respect to type
-// conversion of its arguments.  In particular, the argument's constness must
-// at times match exactly the function signature, or the type-inference might
-// break.  Given the above, writing a custom solution was easier.
-//
-//
-// MISSING FUNCTIONALITY
-//  - Invoking the return of Bind.  Bind(&foo).Run() does not work;
-//  - Binding arrays to functions that take a non-const pointer.
-//    Example:
-//      void Foo(const char* ptr);
-//      void Bar(char* ptr);
-//      Bind(&Foo, "test");
-//      Bind(&Bar, "test");  // This fails because ptr is not const.
-
 namespace base {
 
-// First, we forward declare the Callback class template. This informs the
-// compiler that the template only has 1 type parameter which is the function
-// signature that the Callback is representing.
-//
-// After this, create template specializations for 0-7 parameters. Note that
-// even though the template typelist grows, the specialization still
-// only has one type: the function signature.
-//
-// If you are thinking of forward declaring Callback in your own header file,
-// please include "base/callback_forward.h" instead.
-template <typename Sig>
-class Callback;
-
-namespace cef_internal {
-template <typename Runnable, typename RunType, typename BoundArgsType>
-struct BindState;
-}  // namespace cef_internal
-
-template <typename R>
-class Callback<R(void)> : public cef_internal::CallbackBase {
+template <typename R, typename... Args>
+class OnceCallback<R(Args...)> : public cef_internal::CallbackBase {
  public:
-  typedef R(RunType)();
+  using ResultType = R;
+  using RunType = R(Args...);
+  using PolymorphicInvoke = R (*)(cef_internal::BindStateBase*,
+                                  cef_internal::PassingType<Args>...);
 
-  Callback() : CallbackBase(NULL) {}
+  constexpr OnceCallback() = default;
+  OnceCallback(std::nullptr_t) = delete;
 
-  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
-  // return the exact Callback<> type.  See base/bind.h for details.
-  template <typename Runnable, typename BindRunType, typename BoundArgsType>
-  Callback(
-      cef_internal::BindState<Runnable, BindRunType, BoundArgsType>* bind_state)
-      : CallbackBase(bind_state) {
-    // Force the assignment to a local variable of PolymorphicInvoke
-    // so the compiler will typecheck that the passed in Run() method has
-    // the correct type.
-    PolymorphicInvoke invoke_func =
-        &cef_internal::BindState<Runnable, BindRunType,
-                                 BoundArgsType>::InvokerType::Run;
-    polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
+  explicit OnceCallback(cef_internal::BindStateBase* bind_state)
+      : cef_internal::CallbackBase(bind_state) {}
+
+  OnceCallback(const OnceCallback&) = delete;
+  OnceCallback& operator=(const OnceCallback&) = delete;
+
+  OnceCallback(OnceCallback&&) noexcept = default;
+  OnceCallback& operator=(OnceCallback&&) noexcept = default;
+
+  OnceCallback(RepeatingCallback<RunType> other)
+      : cef_internal::CallbackBase(std::move(other)) {}
+
+  OnceCallback& operator=(RepeatingCallback<RunType> other) {
+    static_cast<cef_internal::CallbackBase&>(*this) = std::move(other);
+    return *this;
   }
 
-  bool Equals(const Callback& other) const {
-    return CallbackBase::Equals(other);
+  R Run(Args... args) const& {
+    static_assert(!sizeof(*this),
+                  "OnceCallback::Run() may only be invoked on a non-const "
+                  "rvalue, i.e. std::move(callback).Run().");
+    NOTREACHED();
   }
 
-  R Run() const {
+  R Run(Args... args) && {
+    // Move the callback instance into a local variable before the invocation,
+    // that ensures the internal state is cleared after the invocation.
+    // It's not safe to touch |this| after the invocation, since running the
+    // bound function may destroy |this|.
+    OnceCallback cb = std::move(*this);
     PolymorphicInvoke f =
-        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
-
-    return f(bind_state_.get());
+        reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke());
+    return f(cb.bind_state_.get(), std::forward<Args>(args)...);
   }
 
- private:
-  typedef R (*PolymorphicInvoke)(cef_internal::BindStateBase*);
+  // Then() returns a new OnceCallback that receives the same arguments as
+  // |this|, and with the return type of |then|. The returned callback will:
+  // 1) Run the functor currently bound to |this| callback.
+  // 2) Run the |then| callback with the result from step 1 as its single
+  //    argument.
+  // 3) Return the value from running the |then| callback.
+  //
+  // Since this method generates a callback that is a replacement for `this`,
+  // `this` will be consumed and reset to a null callback to ensure the
+  // originally-bound functor can be run at most once.
+  template <typename ThenR, typename... ThenArgs>
+  OnceCallback<ThenR(Args...)> Then(OnceCallback<ThenR(ThenArgs...)> then) && {
+    CHECK(then);
+    return BindOnce(
+        cef_internal::ThenHelper<
+            OnceCallback, OnceCallback<ThenR(ThenArgs...)>>::CreateTrampoline(),
+        std::move(*this), std::move(then));
+  }
+
+  // This overload is required; even though RepeatingCallback is implicitly
+  // convertible to OnceCallback, that conversion will not used when matching
+  // for template argument deduction.
+  template <typename ThenR, typename... ThenArgs>
+  OnceCallback<ThenR(Args...)> Then(
+      RepeatingCallback<ThenR(ThenArgs...)> then) && {
+    CHECK(then);
+    return BindOnce(
+        cef_internal::ThenHelper<
+            OnceCallback,
+            RepeatingCallback<ThenR(ThenArgs...)>>::CreateTrampoline(),
+        std::move(*this), std::move(then));
+  }
 };
 
-template <typename R, typename A1>
-class Callback<R(A1)> : public cef_internal::CallbackBase {
+template <typename R, typename... Args>
+class RepeatingCallback<R(Args...)>
+    : public cef_internal::CallbackBaseCopyable {
  public:
-  typedef R(RunType)(A1);
+  using ResultType = R;
+  using RunType = R(Args...);
+  using PolymorphicInvoke = R (*)(cef_internal::BindStateBase*,
+                                  cef_internal::PassingType<Args>...);
 
-  Callback() : CallbackBase(NULL) {}
+  constexpr RepeatingCallback() = default;
+  RepeatingCallback(std::nullptr_t) = delete;
 
-  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
-  // return the exact Callback<> type.  See base/bind.h for details.
-  template <typename Runnable, typename BindRunType, typename BoundArgsType>
-  Callback(
-      cef_internal::BindState<Runnable, BindRunType, BoundArgsType>* bind_state)
-      : CallbackBase(bind_state) {
-    // Force the assignment to a local variable of PolymorphicInvoke
-    // so the compiler will typecheck that the passed in Run() method has
-    // the correct type.
-    PolymorphicInvoke invoke_func =
-        &cef_internal::BindState<Runnable, BindRunType,
-                                 BoundArgsType>::InvokerType::Run;
-    polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
+  explicit RepeatingCallback(cef_internal::BindStateBase* bind_state)
+      : cef_internal::CallbackBaseCopyable(bind_state) {}
+
+  // Copyable and movable.
+  RepeatingCallback(const RepeatingCallback&) = default;
+  RepeatingCallback& operator=(const RepeatingCallback&) = default;
+  RepeatingCallback(RepeatingCallback&&) noexcept = default;
+  RepeatingCallback& operator=(RepeatingCallback&&) noexcept = default;
+
+  bool operator==(const RepeatingCallback& other) const {
+    return EqualsInternal(other);
   }
 
-  bool Equals(const Callback& other) const {
-    return CallbackBase::Equals(other);
+  bool operator!=(const RepeatingCallback& other) const {
+    return !operator==(other);
   }
 
-  R Run(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1) const {
+  R Run(Args... args) const& {
     PolymorphicInvoke f =
-        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
-
-    return f(bind_state_.get(), cef_internal::CallbackForward(a1));
+        reinterpret_cast<PolymorphicInvoke>(this->polymorphic_invoke());
+    return f(this->bind_state_.get(), std::forward<Args>(args)...);
   }
 
- private:
-  typedef R (*PolymorphicInvoke)(
-      cef_internal::BindStateBase*,
-      typename cef_internal::CallbackParamTraits<A1>::ForwardType);
-};
-
-template <typename R, typename A1, typename A2>
-class Callback<R(A1, A2)> : public cef_internal::CallbackBase {
- public:
-  typedef R(RunType)(A1, A2);
-
-  Callback() : CallbackBase(NULL) {}
-
-  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
-  // return the exact Callback<> type.  See base/bind.h for details.
-  template <typename Runnable, typename BindRunType, typename BoundArgsType>
-  Callback(
-      cef_internal::BindState<Runnable, BindRunType, BoundArgsType>* bind_state)
-      : CallbackBase(bind_state) {
-    // Force the assignment to a local variable of PolymorphicInvoke
-    // so the compiler will typecheck that the passed in Run() method has
-    // the correct type.
-    PolymorphicInvoke invoke_func =
-        &cef_internal::BindState<Runnable, BindRunType,
-                                 BoundArgsType>::InvokerType::Run;
-    polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
-  }
-
-  bool Equals(const Callback& other) const {
-    return CallbackBase::Equals(other);
-  }
-
-  R Run(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
-        typename cef_internal::CallbackParamTraits<A2>::ForwardType a2) const {
+  R Run(Args... args) && {
+    // Move the callback instance into a local variable before the invocation,
+    // that ensures the internal state is cleared after the invocation.
+    // It's not safe to touch |this| after the invocation, since running the
+    // bound function may destroy |this|.
+    RepeatingCallback cb = std::move(*this);
     PolymorphicInvoke f =
-        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
-
-    return f(bind_state_.get(), cef_internal::CallbackForward(a1),
-             cef_internal::CallbackForward(a2));
+        reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke());
+    return f(std::move(cb).bind_state_.get(), std::forward<Args>(args)...);
   }
 
- private:
-  typedef R (*PolymorphicInvoke)(
-      cef_internal::BindStateBase*,
-      typename cef_internal::CallbackParamTraits<A1>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A2>::ForwardType);
+  // Then() returns a new RepeatingCallback that receives the same arguments as
+  // |this|, and with the return type of |then|. The
+  // returned callback will:
+  // 1) Run the functor currently bound to |this| callback.
+  // 2) Run the |then| callback with the result from step 1 as its single
+  //    argument.
+  // 3) Return the value from running the |then| callback.
+  //
+  // If called on an rvalue (e.g. std::move(cb).Then(...)), this method
+  // generates a callback that is a replacement for `this`. Therefore, `this`
+  // will be consumed and reset to a null callback to ensure the
+  // originally-bound functor will be run at most once.
+  template <typename ThenR, typename... ThenArgs>
+  RepeatingCallback<ThenR(Args...)> Then(
+      RepeatingCallback<ThenR(ThenArgs...)> then) const& {
+    CHECK(then);
+    return BindRepeating(
+        cef_internal::ThenHelper<
+            RepeatingCallback,
+            RepeatingCallback<ThenR(ThenArgs...)>>::CreateTrampoline(),
+        *this, std::move(then));
+  }
+
+  template <typename ThenR, typename... ThenArgs>
+  RepeatingCallback<ThenR(Args...)> Then(
+      RepeatingCallback<ThenR(ThenArgs...)> then) && {
+    CHECK(then);
+    return BindRepeating(
+        cef_internal::ThenHelper<
+            RepeatingCallback,
+            RepeatingCallback<ThenR(ThenArgs...)>>::CreateTrampoline(),
+        std::move(*this), std::move(then));
+  }
 };
 
-template <typename R, typename A1, typename A2, typename A3>
-class Callback<R(A1, A2, A3)> : public cef_internal::CallbackBase {
- public:
-  typedef R(RunType)(A1, A2, A3);
-
-  Callback() : CallbackBase(NULL) {}
-
-  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
-  // return the exact Callback<> type.  See base/bind.h for details.
-  template <typename Runnable, typename BindRunType, typename BoundArgsType>
-  Callback(
-      cef_internal::BindState<Runnable, BindRunType, BoundArgsType>* bind_state)
-      : CallbackBase(bind_state) {
-    // Force the assignment to a local variable of PolymorphicInvoke
-    // so the compiler will typecheck that the passed in Run() method has
-    // the correct type.
-    PolymorphicInvoke invoke_func =
-        &cef_internal::BindState<Runnable, BindRunType,
-                                 BoundArgsType>::InvokerType::Run;
-    polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
-  }
-
-  bool Equals(const Callback& other) const {
-    return CallbackBase::Equals(other);
-  }
-
-  R Run(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
-        typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
-        typename cef_internal::CallbackParamTraits<A3>::ForwardType a3) const {
-    PolymorphicInvoke f =
-        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
-
-    return f(bind_state_.get(), cef_internal::CallbackForward(a1),
-             cef_internal::CallbackForward(a2),
-             cef_internal::CallbackForward(a3));
-  }
-
- private:
-  typedef R (*PolymorphicInvoke)(
-      cef_internal::BindStateBase*,
-      typename cef_internal::CallbackParamTraits<A1>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A2>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A3>::ForwardType);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4>
-class Callback<R(A1, A2, A3, A4)> : public cef_internal::CallbackBase {
- public:
-  typedef R(RunType)(A1, A2, A3, A4);
-
-  Callback() : CallbackBase(NULL) {}
-
-  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
-  // return the exact Callback<> type.  See base/bind.h for details.
-  template <typename Runnable, typename BindRunType, typename BoundArgsType>
-  Callback(
-      cef_internal::BindState<Runnable, BindRunType, BoundArgsType>* bind_state)
-      : CallbackBase(bind_state) {
-    // Force the assignment to a local variable of PolymorphicInvoke
-    // so the compiler will typecheck that the passed in Run() method has
-    // the correct type.
-    PolymorphicInvoke invoke_func =
-        &cef_internal::BindState<Runnable, BindRunType,
-                                 BoundArgsType>::InvokerType::Run;
-    polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
-  }
-
-  bool Equals(const Callback& other) const {
-    return CallbackBase::Equals(other);
-  }
-
-  R Run(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
-        typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
-        typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
-        typename cef_internal::CallbackParamTraits<A4>::ForwardType a4) const {
-    PolymorphicInvoke f =
-        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
-
-    return f(bind_state_.get(), cef_internal::CallbackForward(a1),
-             cef_internal::CallbackForward(a2),
-             cef_internal::CallbackForward(a3),
-             cef_internal::CallbackForward(a4));
-  }
-
- private:
-  typedef R (*PolymorphicInvoke)(
-      cef_internal::BindStateBase*,
-      typename cef_internal::CallbackParamTraits<A1>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A2>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A3>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A4>::ForwardType);
-};
-
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5>
-class Callback<R(A1, A2, A3, A4, A5)> : public cef_internal::CallbackBase {
- public:
-  typedef R(RunType)(A1, A2, A3, A4, A5);
-
-  Callback() : CallbackBase(NULL) {}
-
-  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
-  // return the exact Callback<> type.  See base/bind.h for details.
-  template <typename Runnable, typename BindRunType, typename BoundArgsType>
-  Callback(
-      cef_internal::BindState<Runnable, BindRunType, BoundArgsType>* bind_state)
-      : CallbackBase(bind_state) {
-    // Force the assignment to a local variable of PolymorphicInvoke
-    // so the compiler will typecheck that the passed in Run() method has
-    // the correct type.
-    PolymorphicInvoke invoke_func =
-        &cef_internal::BindState<Runnable, BindRunType,
-                                 BoundArgsType>::InvokerType::Run;
-    polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
-  }
-
-  bool Equals(const Callback& other) const {
-    return CallbackBase::Equals(other);
-  }
-
-  R Run(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
-        typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
-        typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
-        typename cef_internal::CallbackParamTraits<A4>::ForwardType a4,
-        typename cef_internal::CallbackParamTraits<A5>::ForwardType a5) const {
-    PolymorphicInvoke f =
-        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
-
-    return f(
-        bind_state_.get(), cef_internal::CallbackForward(a1),
-        cef_internal::CallbackForward(a2), cef_internal::CallbackForward(a3),
-        cef_internal::CallbackForward(a4), cef_internal::CallbackForward(a5));
-  }
-
- private:
-  typedef R (*PolymorphicInvoke)(
-      cef_internal::BindStateBase*,
-      typename cef_internal::CallbackParamTraits<A1>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A2>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A3>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A4>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A5>::ForwardType);
-};
-
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6>
-class Callback<R(A1, A2, A3, A4, A5, A6)> : public cef_internal::CallbackBase {
- public:
-  typedef R(RunType)(A1, A2, A3, A4, A5, A6);
-
-  Callback() : CallbackBase(NULL) {}
-
-  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
-  // return the exact Callback<> type.  See base/bind.h for details.
-  template <typename Runnable, typename BindRunType, typename BoundArgsType>
-  Callback(
-      cef_internal::BindState<Runnable, BindRunType, BoundArgsType>* bind_state)
-      : CallbackBase(bind_state) {
-    // Force the assignment to a local variable of PolymorphicInvoke
-    // so the compiler will typecheck that the passed in Run() method has
-    // the correct type.
-    PolymorphicInvoke invoke_func =
-        &cef_internal::BindState<Runnable, BindRunType,
-                                 BoundArgsType>::InvokerType::Run;
-    polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
-  }
-
-  bool Equals(const Callback& other) const {
-    return CallbackBase::Equals(other);
-  }
-
-  R Run(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
-        typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
-        typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
-        typename cef_internal::CallbackParamTraits<A4>::ForwardType a4,
-        typename cef_internal::CallbackParamTraits<A5>::ForwardType a5,
-        typename cef_internal::CallbackParamTraits<A6>::ForwardType a6) const {
-    PolymorphicInvoke f =
-        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
-
-    return f(
-        bind_state_.get(), cef_internal::CallbackForward(a1),
-        cef_internal::CallbackForward(a2), cef_internal::CallbackForward(a3),
-        cef_internal::CallbackForward(a4), cef_internal::CallbackForward(a5),
-        cef_internal::CallbackForward(a6));
-  }
-
- private:
-  typedef R (*PolymorphicInvoke)(
-      cef_internal::BindStateBase*,
-      typename cef_internal::CallbackParamTraits<A1>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A2>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A3>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A4>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A5>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A6>::ForwardType);
-};
-
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6,
-          typename A7>
-class Callback<R(A1, A2, A3, A4, A5, A6, A7)>
-    : public cef_internal::CallbackBase {
- public:
-  typedef R(RunType)(A1, A2, A3, A4, A5, A6, A7);
-
-  Callback() : CallbackBase(NULL) {}
-
-  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
-  // return the exact Callback<> type.  See base/bind.h for details.
-  template <typename Runnable, typename BindRunType, typename BoundArgsType>
-  Callback(
-      cef_internal::BindState<Runnable, BindRunType, BoundArgsType>* bind_state)
-      : CallbackBase(bind_state) {
-    // Force the assignment to a local variable of PolymorphicInvoke
-    // so the compiler will typecheck that the passed in Run() method has
-    // the correct type.
-    PolymorphicInvoke invoke_func =
-        &cef_internal::BindState<Runnable, BindRunType,
-                                 BoundArgsType>::InvokerType::Run;
-    polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
-  }
-
-  bool Equals(const Callback& other) const {
-    return CallbackBase::Equals(other);
-  }
-
-  R Run(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
-        typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
-        typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
-        typename cef_internal::CallbackParamTraits<A4>::ForwardType a4,
-        typename cef_internal::CallbackParamTraits<A5>::ForwardType a5,
-        typename cef_internal::CallbackParamTraits<A6>::ForwardType a6,
-        typename cef_internal::CallbackParamTraits<A7>::ForwardType a7) const {
-    PolymorphicInvoke f =
-        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
-
-    return f(
-        bind_state_.get(), cef_internal::CallbackForward(a1),
-        cef_internal::CallbackForward(a2), cef_internal::CallbackForward(a3),
-        cef_internal::CallbackForward(a4), cef_internal::CallbackForward(a5),
-        cef_internal::CallbackForward(a6), cef_internal::CallbackForward(a7));
-  }
-
- private:
-  typedef R (*PolymorphicInvoke)(
-      cef_internal::BindStateBase*,
-      typename cef_internal::CallbackParamTraits<A1>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A2>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A3>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A4>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A5>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A6>::ForwardType,
-      typename cef_internal::CallbackParamTraits<A7>::ForwardType);
-};
-
-// Syntactic sugar to make Callbacks<void(void)> easier to declare since it
-// will be used in a lot of APIs with delayed execution.
-typedef Callback<void(void)> Closure;
-
 }  // namespace base
 
 #endif  // !USING_CHROMIUM_INCLUDES
diff --git a/src/include/base/cef_callback_forward.h b/src/include/base/cef_callback_forward.h
index d604d7c..2d22774 100644
--- a/src/include/base/cef_callback_forward.h
+++ b/src/include/base/cef_callback_forward.h
@@ -32,14 +32,9 @@
 #define INCLUDE_BASE_CEF_CALLBACK_FORWARD_H_
 #pragma once
 
-#if defined(BASE_CALLBACK_FORWARD_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
+#if defined(USING_CHROMIUM_INCLUDES)
 // When building CEF include the Chromium header directly.
-#include "base/callback_forward.h"
+#include "base/functional/callback_forward.h"
 #else  // !USING_CHROMIUM_INCLUDES
 // The following is substantially similar to the Chromium implementation.
 // If the Chromium implementation diverges the below implementation should be
@@ -47,10 +42,19 @@
 
 namespace base {
 
-template <typename Sig>
-class Callback;
+template <typename Signature>
+class OnceCallback;
 
-typedef Callback<void(void)> Closure;
+template <typename Signature>
+class RepeatingCallback;
+
+///
+/// Syntactic sugar to make OnceClosure<void()> and RepeatingClosure<void()>
+/// easier to declare since they will be used in a lot of APIs with delayed
+/// execution.
+///
+using OnceClosure = OnceCallback<void()>;
+using RepeatingClosure = RepeatingCallback<void()>;
 
 }  // namespace base
 
diff --git a/src/include/base/cef_callback_helpers.h b/src/include/base/cef_callback_helpers.h
index ebe074a..5e38644 100644
--- a/src/include/base/cef_callback_helpers.h
+++ b/src/include/base/cef_callback_helpers.h
@@ -32,60 +32,228 @@
 // are implemented using templates, with a class per callback signature, adding
 // methods to Callback<> itself is unattractive (lots of extra code gets
 // generated).  Instead, consider adding methods here.
-//
-// ResetAndReturn(&cb) is like cb.Reset() but allows executing a callback (via a
-// copy) after the original callback is Reset().  This can be handy if Run()
-// reads/writes the variable holding the Callback.
 
 #ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_HELPERS_H_
 #define CEF_INCLUDE_BASE_CEF_CALLBACK_HELPERS_H_
 #pragma once
 
-#if defined(BASE_CALLBACK_HELPERS_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
+#if defined(USING_CHROMIUM_INCLUDES)
 // When building CEF include the Chromium header directly.
-#include "base/callback_helpers.h"
+#include "base/functional/callback_helpers.h"
 #else  // !USING_CHROMIUM_INCLUDES
 // The following is substantially similar to the Chromium implementation.
 // If the Chromium implementation diverges the below implementation should be
 // updated to match.
 
-#include "include/base/cef_basictypes.h"
-#include "include/base/cef_build.h"
+#include <atomic>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+#include "include/base/cef_bind.h"
 #include "include/base/cef_callback.h"
-#include "include/base/cef_macros.h"
+#include "include/base/cef_logging.h"
 
 namespace base {
 
-template <typename Sig>
-base::Callback<Sig> ResetAndReturn(base::Callback<Sig>* cb) {
-  base::Callback<Sig> ret(*cb);
-  cb->Reset();
-  return ret;
+namespace internal {
+
+template <typename T>
+struct IsBaseCallbackImpl : std::false_type {};
+
+template <typename R, typename... Args>
+struct IsBaseCallbackImpl<OnceCallback<R(Args...)>> : std::true_type {};
+
+template <typename R, typename... Args>
+struct IsBaseCallbackImpl<RepeatingCallback<R(Args...)>> : std::true_type {};
+
+template <typename T>
+struct IsOnceCallbackImpl : std::false_type {};
+
+template <typename R, typename... Args>
+struct IsOnceCallbackImpl<OnceCallback<R(Args...)>> : std::true_type {};
+
+}  // namespace internal
+
+///
+/// IsBaseCallback<T>::value is true when T is any of the Closure or Callback
+/// family of types.
+///
+template <typename T>
+using IsBaseCallback = internal::IsBaseCallbackImpl<std::decay_t<T>>;
+
+///
+/// IsOnceCallback<T>::value is true when T is a OnceClosure or OnceCallback
+/// type.
+///
+template <typename T>
+using IsOnceCallback = internal::IsOnceCallbackImpl<std::decay_t<T>>;
+
+///
+/// SFINAE friendly enabler allowing to overload methods for both Repeating and
+/// OnceCallbacks.
+///
+/// Usage:
+/// <pre>
+///   template <template <typename> class CallbackType,
+///             ... other template args ...,
+///             typename = EnableIfIsBaseCallback<CallbackType>>
+///   void DoStuff(CallbackType<...> cb, ...);
+/// </pre>
+///
+template <template <typename> class CallbackType>
+using EnableIfIsBaseCallback =
+    std::enable_if_t<IsBaseCallback<CallbackType<void()>>::value>;
+
+namespace internal {
+
+template <typename... Args>
+class OnceCallbackHolder final {
+ public:
+  OnceCallbackHolder(OnceCallback<void(Args...)> callback,
+                     bool ignore_extra_runs)
+      : callback_(std::move(callback)), ignore_extra_runs_(ignore_extra_runs) {
+    DCHECK(callback_);
+  }
+  OnceCallbackHolder(const OnceCallbackHolder&) = delete;
+  OnceCallbackHolder& operator=(const OnceCallbackHolder&) = delete;
+
+  void Run(Args... args) {
+    if (has_run_.exchange(true)) {
+      CHECK(ignore_extra_runs_) << "Both OnceCallbacks returned by "
+                                   "base::SplitOnceCallback() were run. "
+                                   "At most one of the pair should be run.";
+      return;
+    }
+    DCHECK(callback_);
+    std::move(callback_).Run(std::forward<Args>(args)...);
+  }
+
+ private:
+  volatile std::atomic_bool has_run_{false};
+  base::OnceCallback<void(Args...)> callback_;
+  const bool ignore_extra_runs_;
+};
+
+}  // namespace internal
+
+///
+/// Wraps the given OnceCallback into a RepeatingCallback that relays its
+/// invocation to the original OnceCallback on the first invocation. The
+/// following invocations are just ignored.
+///
+/// Note that this deliberately subverts the Once/Repeating paradigm of
+/// Callbacks but helps ease the migration from old-style Callbacks. Avoid if
+/// possible; use if necessary for migration.
+///
+// TODO(tzik): Remove it. https://crbug.com/730593
+template <typename... Args>
+RepeatingCallback<void(Args...)> AdaptCallbackForRepeating(
+    OnceCallback<void(Args...)> callback) {
+  using Helper = internal::OnceCallbackHolder<Args...>;
+  return base::BindRepeating(
+      &Helper::Run, std::make_unique<Helper>(std::move(callback),
+                                             /*ignore_extra_runs=*/true));
 }
 
-// ScopedClosureRunner is akin to scoped_ptr for Closures. It ensures that the
-// Closure is executed and deleted no matter how the current scope exits.
+///
+/// Wraps the given OnceCallback and returns two OnceCallbacks with an identical
+/// signature. On first invokation of either returned callbacks, the original
+/// callback is invoked. Invoking the remaining callback results in a crash.
+///
+template <typename... Args>
+std::pair<OnceCallback<void(Args...)>, OnceCallback<void(Args...)>>
+SplitOnceCallback(OnceCallback<void(Args...)> callback) {
+  using Helper = internal::OnceCallbackHolder<Args...>;
+  auto wrapped_once = base::BindRepeating(
+      &Helper::Run, std::make_unique<Helper>(std::move(callback),
+                                             /*ignore_extra_runs=*/false));
+  return std::make_pair(wrapped_once, wrapped_once);
+}
+
+///
+/// ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures
+/// that the Closure is executed no matter how the current scope exits.
+/// If you are looking for "ScopedCallback", "CallbackRunner", or
+/// "CallbackScoper" this is the class you want.
+///
 class ScopedClosureRunner {
  public:
   ScopedClosureRunner();
-  explicit ScopedClosureRunner(const Closure& closure);
+  explicit ScopedClosureRunner(OnceClosure closure);
+  ScopedClosureRunner(ScopedClosureRunner&& other);
+  // Runs the current closure if it's set, then replaces it with the closure
+  // from |other|. This is akin to how unique_ptr frees the contained pointer in
+  // its move assignment operator. If you need to explicitly avoid running any
+  // current closure, use ReplaceClosure().
+  ScopedClosureRunner& operator=(ScopedClosureRunner&& other);
   ~ScopedClosureRunner();
 
-  void Reset();
-  void Reset(const Closure& closure);
-  Closure Release() WARN_UNUSED_RESULT;
+  explicit operator bool() const { return !!closure_; }
+
+  // Calls the current closure and resets it, so it wont be called again.
+  void RunAndReset();
+
+  // Replaces closure with the new one releasing the old one without calling it.
+  void ReplaceClosure(OnceClosure closure);
+
+  // Releases the Closure without calling.
+  [[nodiscard]] OnceClosure Release();
 
  private:
-  Closure closure_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedClosureRunner);
+  OnceClosure closure_;
 };
 
+///
+/// Creates a null callback.
+///
+class NullCallback {
+ public:
+  template <typename R, typename... Args>
+  operator RepeatingCallback<R(Args...)>() const {
+    return RepeatingCallback<R(Args...)>();
+  }
+  template <typename R, typename... Args>
+  operator OnceCallback<R(Args...)>() const {
+    return OnceCallback<R(Args...)>();
+  }
+};
+
+///
+/// Creates a callback that does nothing when called.
+///
+class DoNothing {
+ public:
+  template <typename... Args>
+  operator RepeatingCallback<void(Args...)>() const {
+    return Repeatedly<Args...>();
+  }
+  template <typename... Args>
+  operator OnceCallback<void(Args...)>() const {
+    return Once<Args...>();
+  }
+  // Explicit way of specifying a specific callback type when the compiler can't
+  // deduce it.
+  template <typename... Args>
+  static RepeatingCallback<void(Args...)> Repeatedly() {
+    return BindRepeating([](Args... args) {});
+  }
+  template <typename... Args>
+  static OnceCallback<void(Args...)> Once() {
+    return BindOnce([](Args... args) {});
+  }
+};
+
+///
+/// Useful for creating a Closure that will delete a pointer when invoked. Only
+/// use this when necessary. In most cases MessageLoop::DeleteSoon() is a better
+/// fit.
+///
+template <typename T>
+void DeletePointer(T* obj) {
+  delete obj;
+}
+
 }  // namespace base
 
 #endif  // !USING_CHROMIUM_INCLUDES
diff --git a/src/include/base/cef_callback_list.h b/src/include/base/cef_callback_list.h
index e0ef366..2038acb 100644
--- a/src/include/base/cef_callback_list.h
+++ b/src/include/base/cef_callback_list.h
@@ -28,419 +28,373 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+///
+/// \file
+/// A container for a list of callbacks. Provides callers the ability to
+/// manually or automatically unregister callbacks at any time, including during
+/// callback notification.
+///
+/// TYPICAL USAGE:
+///
+/// <pre>
+/// class MyWidget {
+///  public:
+///   using CallbackList = base::RepeatingCallbackList<void(const Foo&)>;
+///
+///   // Registers |cb| to be called whenever NotifyFoo() is executed.
+///   CallbackListSubscription RegisterCallback(CallbackList::CallbackType cb) {
+///     return callback_list_.Add(std::move(cb));
+///   }
+///
+///  private:
+///   // Calls all registered callbacks, with |foo| as the supplied arg.
+///   void NotifyFoo(const Foo& foo) {
+///     callback_list_.Notify(foo);
+///   }
+///
+///   CallbackList callback_list_;
+/// };
+///
+///
+/// class MyWidgetListener {
+///  private:
+///   void OnFoo(const Foo& foo) {
+///     // Called whenever MyWidget::NotifyFoo() is executed, unless
+///     // |foo_subscription_| has been destroyed.
+///   }
+///
+///   // Automatically deregisters the callback when deleted (e.g. in
+///   // ~MyWidgetListener()).  Unretained(this) is safe here since the
+///   // ScopedClosureRunner does not outlive |this|.
+///   CallbackListSubscription foo_subscription_ =
+///       MyWidget::Get()->RegisterCallback(
+///           base::BindRepeating(&MyWidgetListener::OnFoo,
+///                               base::Unretained(this)));
+/// };
+/// </pre>
+///
+/// UNSUPPORTED:
+///
+/// * Destroying the CallbackList during callback notification.
+///
+/// This is possible to support, but not currently necessary.
+///
+
 #ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_
 #define CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_
 #pragma once
 
-#if defined(BASE_CALLBACK_LIST_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
+#if defined(USING_CHROMIUM_INCLUDES)
 // When building CEF include the Chromium header directly.
-#include "base/callback_list.h"
+#include "base/functional/callback_list.h"
 #else  // !USING_CHROMIUM_INCLUDES
 // The following is substantially similar to the Chromium implementation.
 // If the Chromium implementation diverges the below implementation should be
 // updated to match.
 
+#include <algorithm>
 #include <list>
+#include <memory>
+#include <utility>
 
-#include "include/base/cef_basictypes.h"
-#include "include/base/cef_build.h"
+#include "include/base/cef_auto_reset.h"
+#include "include/base/cef_bind.h"
 #include "include/base/cef_callback.h"
+#include "include/base/cef_callback_helpers.h"
 #include "include/base/cef_logging.h"
-#include "include/base/cef_macros.h"
-#include "include/base/cef_scoped_ptr.h"
-#include "include/base/internal/cef_callback_internal.h"
-
-// OVERVIEW:
-//
-// A container for a list of callbacks.  Unlike a normal STL vector or list,
-// this container can be modified during iteration without invalidating the
-// iterator. It safely handles the case of a callback removing itself
-// or another callback from the list while callbacks are being run.
-//
-// TYPICAL USAGE:
-//
-// class MyWidget {
-//  public:
-//   ...
-//
-//   typedef base::Callback<void(const Foo&)> OnFooCallback;
-//
-//   scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
-//   RegisterCallback(const OnFooCallback& cb) {
-//     return callback_list_.Add(cb);
-//   }
-//
-//  private:
-//   void NotifyFoo(const Foo& foo) {
-//      callback_list_.Notify(foo);
-//   }
-//
-//   base::CallbackList<void(const Foo&)> callback_list_;
-//
-//   DISALLOW_COPY_AND_ASSIGN(MyWidget);
-// };
-//
-//
-// class MyWidgetListener {
-//  public:
-//   MyWidgetListener::MyWidgetListener() {
-//     foo_subscription_ = MyWidget::GetCurrent()->RegisterCallback(
-//             base::Bind(&MyWidgetListener::OnFoo, this)));
-//   }
-//
-//   MyWidgetListener::~MyWidgetListener() {
-//      // Subscription gets deleted automatically and will deregister
-//      // the callback in the process.
-//   }
-//
-//  private:
-//   void OnFoo(const Foo& foo) {
-//     // Do something.
-//   }
-//
-//   scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription>
-//       foo_subscription_;
-//
-//   DISALLOW_COPY_AND_ASSIGN(MyWidgetListener);
-// };
+#include "include/base/cef_weak_ptr.h"
 
 namespace base {
+namespace internal {
+template <typename CallbackListImpl>
+class CallbackListBase;
+}  // namespace internal
 
-namespace cef_internal {
+template <typename Signature>
+class OnceCallbackList;
 
-template <typename CallbackType>
+template <typename Signature>
+class RepeatingCallbackList;
+
+// A trimmed-down version of ScopedClosureRunner that can be used to guarantee a
+// closure is run on destruction. This is designed to be used by
+// CallbackListBase to run CancelCallback() when this subscription dies;
+// consumers can avoid callbacks on dead objects by ensuring the subscription
+// returned by CallbackListBase::Add() does not outlive the bound object in the
+// callback. A typical way to do this is to bind a callback to a member function
+// on `this` and store the returned subscription as a member variable.
+class CallbackListSubscription {
+ public:
+  CallbackListSubscription();
+  CallbackListSubscription(CallbackListSubscription&& subscription);
+  CallbackListSubscription& operator=(CallbackListSubscription&& subscription);
+  ~CallbackListSubscription();
+
+  explicit operator bool() const { return !!closure_; }
+
+ private:
+  template <typename T>
+  friend class internal::CallbackListBase;
+
+  explicit CallbackListSubscription(base::OnceClosure closure);
+
+  void Run();
+
+  OnceClosure closure_;
+};
+
+namespace internal {
+
+// From base/stl_util.h.
+template <class T, class Allocator, class Predicate>
+size_t EraseIf(std::list<T, Allocator>& container, Predicate pred) {
+  size_t old_size = container.size();
+  container.remove_if(pred);
+  return old_size - container.size();
+}
+
+// A traits class to break circular type dependencies between CallbackListBase
+// and its subclasses.
+template <typename CallbackList>
+struct CallbackListTraits;
+
+// NOTE: It's important that Callbacks provide iterator stability when items are
+// added to the end, so e.g. a std::vector<> is not suitable here.
+template <typename Signature>
+struct CallbackListTraits<OnceCallbackList<Signature>> {
+  using CallbackType = OnceCallback<Signature>;
+  using Callbacks = std::list<CallbackType>;
+};
+template <typename Signature>
+struct CallbackListTraits<RepeatingCallbackList<Signature>> {
+  using CallbackType = RepeatingCallback<Signature>;
+  using Callbacks = std::list<CallbackType>;
+};
+
+template <typename CallbackListImpl>
 class CallbackListBase {
  public:
-  class Subscription {
-   public:
-    Subscription(CallbackListBase<CallbackType>* list,
-                 typename std::list<CallbackType>::iterator iter)
-        : list_(list), iter_(iter) {}
+  using CallbackType =
+      typename CallbackListTraits<CallbackListImpl>::CallbackType;
+  static_assert(IsBaseCallback<CallbackType>::value, "");
 
-    ~Subscription() {
-      if (list_->active_iterator_count_) {
-        iter_->Reset();
-      } else {
-        list_->callbacks_.erase(iter_);
-        if (!list_->removal_callback_.is_null())
-          list_->removal_callback_.Run();
+  // TODO(crbug.com/1103086): Update references to use this directly and by
+  // value, then remove.
+  using Subscription = CallbackListSubscription;
+
+  CallbackListBase() = default;
+  CallbackListBase(const CallbackListBase&) = delete;
+  CallbackListBase& operator=(const CallbackListBase&) = delete;
+
+  ~CallbackListBase() {
+    // Destroying the list during iteration is unsupported and will cause a UAF.
+    CHECK(!iterating_);
+  }
+
+  // Registers |cb| for future notifications. Returns a CallbackListSubscription
+  // whose destruction will cancel |cb|.
+  [[nodiscard]] CallbackListSubscription Add(CallbackType cb) {
+    DCHECK(!cb.is_null());
+    return CallbackListSubscription(base::BindOnce(
+        &CallbackListBase::CancelCallback, weak_ptr_factory_.GetWeakPtr(),
+        callbacks_.insert(callbacks_.end(), std::move(cb))));
+  }
+
+  // Registers |cb| for future notifications. Provides no way for the caller to
+  // cancel, so this is only safe for cases where the callback is guaranteed to
+  // live at least as long as this list (e.g. if it's bound on the same object
+  // that owns the list).
+  // TODO(pkasting): Attempt to use Add() instead and see if callers can relax
+  // other lifetime/ordering mechanisms as a result.
+  void AddUnsafe(CallbackType cb) {
+    DCHECK(!cb.is_null());
+    callbacks_.push_back(std::move(cb));
+  }
+
+  // Registers |removal_callback| to be run after elements are removed from the
+  // list of registered callbacks.
+  void set_removal_callback(const RepeatingClosure& removal_callback) {
+    removal_callback_ = removal_callback;
+  }
+
+  // Returns whether the list of registered callbacks is empty (from an external
+  // perspective -- meaning no remaining callbacks are live).
+  bool empty() const {
+    return std::all_of(callbacks_.cbegin(), callbacks_.cend(),
+                       [](const auto& callback) { return callback.is_null(); });
+  }
+
+  // Calls all registered callbacks that are not canceled beforehand. If any
+  // callbacks are unregistered, notifies any registered removal callback at the
+  // end.
+  //
+  // Arguments must be copyable, since they must be supplied to all callbacks.
+  // Move-only types would be destructively modified by passing them to the
+  // first callback and not reach subsequent callbacks as intended.
+  //
+  // Notify() may be called re-entrantly, in which case the nested call
+  // completes before the outer one continues. Callbacks are only ever added at
+  // the end and canceled callbacks are not pruned from the list until the
+  // outermost iteration completes, so existing iterators should never be
+  // invalidated. However, this does mean that a callback added during a nested
+  // call can be notified by outer calls -- meaning it will be notified about
+  // things that happened before it was added -- if its subscription outlives
+  // the reentrant Notify() call.
+  template <typename... RunArgs>
+  void Notify(RunArgs&&... args) {
+    if (empty()) {
+      return;  // Nothing to do.
+    }
+
+    {
+      AutoReset<bool> iterating(&iterating_, true);
+
+      // Skip any callbacks that are canceled during iteration.
+      // NOTE: Since RunCallback() may call Add(), it's not safe to cache the
+      // value of callbacks_.end() across loop iterations.
+      const auto next_valid = [this](const auto it) {
+        return std::find_if_not(it, callbacks_.end(), [](const auto& callback) {
+          return callback.is_null();
+        });
+      };
+      for (auto it = next_valid(callbacks_.begin()); it != callbacks_.end();
+           it = next_valid(it)) {
+        // NOTE: Intentionally does not call std::forward<RunArgs>(args)...,
+        // since that would allow move-only arguments.
+        static_cast<CallbackListImpl*>(this)->RunCallback(it++, args...);
       }
     }
 
-   private:
-    CallbackListBase<CallbackType>* list_;
-    typename std::list<CallbackType>::iterator iter_;
+    // Re-entrant invocations shouldn't prune anything from the list. This can
+    // invalidate iterators from underneath higher call frames. It's safe to
+    // simply do nothing, since the outermost frame will continue through here
+    // and prune all null callbacks below.
+    if (iterating_) {
+      return;
+    }
 
-    DISALLOW_COPY_AND_ASSIGN(Subscription);
-  };
+    // Any null callbacks remaining in the list were canceled due to
+    // Subscription destruction during iteration, and can safely be erased now.
+    const size_t erased_callbacks =
+        EraseIf(callbacks_, [](const auto& cb) { return cb.is_null(); });
 
-  // Add a callback to the list. The callback will remain registered until the
-  // returned Subscription is destroyed, which must occur before the
-  // CallbackList is destroyed.
-  scoped_ptr<Subscription> Add(const CallbackType& cb) WARN_UNUSED_RESULT {
-    DCHECK(!cb.is_null());
-    return scoped_ptr<Subscription>(
-        new Subscription(this, callbacks_.insert(callbacks_.end(), cb)));
-  }
-
-  // Sets a callback which will be run when a subscription list is changed.
-  void set_removal_callback(const Closure& callback) {
-    removal_callback_ = callback;
-  }
-
-  // Returns true if there are no subscriptions. This is only valid to call when
-  // not looping through the list.
-  bool empty() {
-    DCHECK_EQ(0, active_iterator_count_);
-    return callbacks_.empty();
+    // Run |removal_callback_| if any callbacks were canceled. Note that we
+    // cannot simply compare list sizes before and after iterating, since
+    // notification may result in Add()ing new callbacks as well as canceling
+    // them. Also note that if this is a OnceCallbackList, the OnceCallbacks
+    // that were executed above have all been removed regardless of whether
+    // they're counted in |erased_callbacks_|.
+    if (removal_callback_ &&
+        (erased_callbacks || IsOnceCallback<CallbackType>::value)) {
+      removal_callback_.Run();  // May delete |this|!
+    }
   }
 
  protected:
-  // An iterator class that can be used to access the list of callbacks.
-  class Iterator {
-   public:
-    explicit Iterator(CallbackListBase<CallbackType>* list)
-        : list_(list), list_iter_(list_->callbacks_.begin()) {
-      ++list_->active_iterator_count_;
+  using Callbacks = typename CallbackListTraits<CallbackListImpl>::Callbacks;
+
+  // Holds non-null callbacks, which will be called during Notify().
+  Callbacks callbacks_;
+
+ private:
+  // Cancels the callback pointed to by |it|, which is guaranteed to be valid.
+  void CancelCallback(const typename Callbacks::iterator& it) {
+    if (static_cast<CallbackListImpl*>(this)->CancelNullCallback(it)) {
+      return;
     }
 
-    Iterator(const Iterator& iter)
-        : list_(iter.list_), list_iter_(iter.list_iter_) {
-      ++list_->active_iterator_count_;
-    }
-
-    ~Iterator() {
-      if (list_ && --list_->active_iterator_count_ == 0) {
-        list_->Compact();
+    if (iterating_) {
+      // Calling erase() here is unsafe, since the loop in Notify() may be
+      // referencing this same iterator, e.g. if adjacent callbacks'
+      // Subscriptions are both destroyed when the first one is Run().  Just
+      // reset the callback and let Notify() clean it up at the end.
+      it->Reset();
+    } else {
+      callbacks_.erase(it);
+      if (removal_callback_) {
+        removal_callback_.Run();  // May delete |this|!
       }
     }
-
-    CallbackType* GetNext() {
-      while ((list_iter_ != list_->callbacks_.end()) && list_iter_->is_null())
-        ++list_iter_;
-
-      CallbackType* cb = NULL;
-      if (list_iter_ != list_->callbacks_.end()) {
-        cb = &(*list_iter_);
-        ++list_iter_;
-      }
-      return cb;
-    }
-
-   private:
-    CallbackListBase<CallbackType>* list_;
-    typename std::list<CallbackType>::iterator list_iter_;
-  };
-
-  CallbackListBase() : active_iterator_count_(0) {}
-
-  ~CallbackListBase() {
-    DCHECK_EQ(0, active_iterator_count_);
-    DCHECK_EQ(0U, callbacks_.size());
   }
 
-  // Returns an instance of a CallbackListBase::Iterator which can be used
-  // to run callbacks.
-  Iterator GetIterator() { return Iterator(this); }
+  // Set while Notify() is traversing |callbacks_|.  Used primarily to avoid
+  // invalidating iterators that may be in use.
+  bool iterating_ = false;
 
-  // Compact the list: remove any entries which were NULLed out during
-  // iteration.
-  void Compact() {
-    typename std::list<CallbackType>::iterator it = callbacks_.begin();
-    bool updated = false;
-    while (it != callbacks_.end()) {
-      if ((*it).is_null()) {
-        updated = true;
-        it = callbacks_.erase(it);
-      } else {
-        ++it;
-      }
+  // Called after elements are removed from |callbacks_|.
+  RepeatingClosure removal_callback_;
 
-      if (updated && !removal_callback_.is_null())
-        removal_callback_.Run();
-    }
-  }
-
- private:
-  std::list<CallbackType> callbacks_;
-  int active_iterator_count_;
-  Closure removal_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(CallbackListBase);
+  WeakPtrFactory<CallbackListBase> weak_ptr_factory_{this};
 };
 
-}  // namespace cef_internal
+}  // namespace internal
 
-template <typename Sig>
-class CallbackList;
+template <typename Signature>
+class OnceCallbackList
+    : public internal::CallbackListBase<OnceCallbackList<Signature>> {
+ private:
+  friend internal::CallbackListBase<OnceCallbackList>;
+  using Traits = internal::CallbackListTraits<OnceCallbackList>;
 
-template <>
-class CallbackList<void(void)>
-    : public cef_internal::CallbackListBase<Callback<void(void)>> {
- public:
-  typedef Callback<void(void)> CallbackType;
+  // Runs the current callback, which may cancel it or any other callbacks.
+  template <typename... RunArgs>
+  void RunCallback(typename Traits::Callbacks::iterator it, RunArgs&&... args) {
+    // OnceCallbacks still have Subscriptions with outstanding iterators;
+    // splice() removes them from |callbacks_| without invalidating those.
+    null_callbacks_.splice(null_callbacks_.end(), this->callbacks_, it);
 
-  CallbackList() {}
-
-  void Notify() {
-    cef_internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-    CallbackType* cb;
-    while ((cb = it.GetNext()) != NULL) {
-      cb->Run();
-    }
+    // NOTE: Intentionally does not call std::forward<RunArgs>(args)...; see
+    // comments in Notify().
+    std::move(*it).Run(args...);
   }
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(CallbackList);
-};
-
-template <typename A1>
-class CallbackList<void(A1)>
-    : public cef_internal::CallbackListBase<Callback<void(A1)>> {
- public:
-  typedef Callback<void(A1)> CallbackType;
-
-  CallbackList() {}
-
-  void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1) {
-    typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-    CallbackType* cb;
-    while ((cb = it.GetNext()) != NULL) {
-      cb->Run(a1);
+  // If |it| refers to an already-canceled callback, does any necessary cleanup
+  // and returns true.  Otherwise returns false.
+  bool CancelNullCallback(const typename Traits::Callbacks::iterator& it) {
+    if (it->is_null()) {
+      null_callbacks_.erase(it);
+      return true;
     }
+    return false;
   }
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(CallbackList);
+  // Holds null callbacks whose Subscriptions are still alive, so the
+  // Subscriptions will still contain valid iterators.  Only needed for
+  // OnceCallbacks, since RepeatingCallbacks are not canceled except by
+  // Subscription destruction.
+  typename Traits::Callbacks null_callbacks_;
 };
 
-template <typename A1, typename A2>
-class CallbackList<void(A1, A2)>
-    : public cef_internal::CallbackListBase<Callback<void(A1, A2)>> {
- public:
-  typedef Callback<void(A1, A2)> CallbackType;
-
-  CallbackList() {}
-
-  void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
-              typename cef_internal::CallbackParamTraits<A2>::ForwardType a2) {
-    typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-    CallbackType* cb;
-    while ((cb = it.GetNext()) != NULL) {
-      cb->Run(a1, a2);
-    }
+template <typename Signature>
+class RepeatingCallbackList
+    : public internal::CallbackListBase<RepeatingCallbackList<Signature>> {
+ private:
+  friend internal::CallbackListBase<RepeatingCallbackList>;
+  using Traits = internal::CallbackListTraits<RepeatingCallbackList>;
+  // Runs the current callback, which may cancel it or any other callbacks.
+  template <typename... RunArgs>
+  void RunCallback(typename Traits::Callbacks::iterator it, RunArgs&&... args) {
+    // NOTE: Intentionally does not call std::forward<RunArgs>(args)...; see
+    // comments in Notify().
+    it->Run(args...);
   }
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(CallbackList);
-};
-
-template <typename A1, typename A2, typename A3>
-class CallbackList<void(A1, A2, A3)>
-    : public cef_internal::CallbackListBase<Callback<void(A1, A2, A3)>> {
- public:
-  typedef Callback<void(A1, A2, A3)> CallbackType;
-
-  CallbackList() {}
-
-  void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
-              typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
-              typename cef_internal::CallbackParamTraits<A3>::ForwardType a3) {
-    typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-    CallbackType* cb;
-    while ((cb = it.GetNext()) != NULL) {
-      cb->Run(a1, a2, a3);
-    }
+  // If |it| refers to an already-canceled callback, does any necessary cleanup
+  // and returns true.  Otherwise returns false.
+  bool CancelNullCallback(const typename Traits::Callbacks::iterator& it) {
+    // Because at most one Subscription can point to a given callback, and
+    // RepeatingCallbacks are only reset by CancelCallback(), no one should be
+    // able to request cancellation of a canceled RepeatingCallback.
+    DCHECK(!it->is_null());
+    return false;
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CallbackList);
 };
 
-template <typename A1, typename A2, typename A3, typename A4>
-class CallbackList<void(A1, A2, A3, A4)>
-    : public cef_internal::CallbackListBase<Callback<void(A1, A2, A3, A4)>> {
- public:
-  typedef Callback<void(A1, A2, A3, A4)> CallbackType;
-
-  CallbackList() {}
-
-  void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
-              typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
-              typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
-              typename cef_internal::CallbackParamTraits<A4>::ForwardType a4) {
-    typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-    CallbackType* cb;
-    while ((cb = it.GetNext()) != NULL) {
-      cb->Run(a1, a2, a3, a4);
-    }
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CallbackList);
-};
-
-template <typename A1, typename A2, typename A3, typename A4, typename A5>
-class CallbackList<void(A1, A2, A3, A4, A5)>
-    : public cef_internal::CallbackListBase<
-          Callback<void(A1, A2, A3, A4, A5)>> {
- public:
-  typedef Callback<void(A1, A2, A3, A4, A5)> CallbackType;
-
-  CallbackList() {}
-
-  void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
-              typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
-              typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
-              typename cef_internal::CallbackParamTraits<A4>::ForwardType a4,
-              typename cef_internal::CallbackParamTraits<A5>::ForwardType a5) {
-    typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-    CallbackType* cb;
-    while ((cb = it.GetNext()) != NULL) {
-      cb->Run(a1, a2, a3, a4, a5);
-    }
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CallbackList);
-};
-
-template <typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6>
-class CallbackList<void(A1, A2, A3, A4, A5, A6)>
-    : public cef_internal::CallbackListBase<
-          Callback<void(A1, A2, A3, A4, A5, A6)>> {
- public:
-  typedef Callback<void(A1, A2, A3, A4, A5, A6)> CallbackType;
-
-  CallbackList() {}
-
-  void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
-              typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
-              typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
-              typename cef_internal::CallbackParamTraits<A4>::ForwardType a4,
-              typename cef_internal::CallbackParamTraits<A5>::ForwardType a5,
-              typename cef_internal::CallbackParamTraits<A6>::ForwardType a6) {
-    typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-    CallbackType* cb;
-    while ((cb = it.GetNext()) != NULL) {
-      cb->Run(a1, a2, a3, a4, a5, a6);
-    }
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CallbackList);
-};
-
-template <typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6,
-          typename A7>
-class CallbackList<void(A1, A2, A3, A4, A5, A6, A7)>
-    : public cef_internal::CallbackListBase<
-          Callback<void(A1, A2, A3, A4, A5, A6, A7)>> {
- public:
-  typedef Callback<void(A1, A2, A3, A4, A5, A6, A7)> CallbackType;
-
-  CallbackList() {}
-
-  void Notify(typename cef_internal::CallbackParamTraits<A1>::ForwardType a1,
-              typename cef_internal::CallbackParamTraits<A2>::ForwardType a2,
-              typename cef_internal::CallbackParamTraits<A3>::ForwardType a3,
-              typename cef_internal::CallbackParamTraits<A4>::ForwardType a4,
-              typename cef_internal::CallbackParamTraits<A5>::ForwardType a5,
-              typename cef_internal::CallbackParamTraits<A6>::ForwardType a6,
-              typename cef_internal::CallbackParamTraits<A7>::ForwardType a7) {
-    typename cef_internal::CallbackListBase<CallbackType>::Iterator it =
-        this->GetIterator();
-    CallbackType* cb;
-    while ((cb = it.GetNext()) != NULL) {
-      cb->Run(a1, a2, a3, a4, a5, a6, a7);
-    }
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CallbackList);
-};
+///
+/// Syntactic sugar to parallel that used for Callbacks.
+///
+using OnceClosureList = OnceCallbackList<void()>;
+using RepeatingClosureList = RepeatingCallbackList<void()>;
 
 }  // namespace base
 
diff --git a/src/include/base/cef_cancelable_callback.h b/src/include/base/cef_cancelable_callback.h
index febce3a..3563149 100644
--- a/src/include/base/cef_cancelable_callback.h
+++ b/src/include/base/cef_cancelable_callback.h
@@ -27,54 +27,58 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// CancelableCallback is a wrapper around base::Callback that allows
-// cancellation of a callback. CancelableCallback takes a reference on the
-// wrapped callback until this object is destroyed or Reset()/Cancel() are
-// called.
-//
-// NOTE:
-//
-// Calling CancelableCallback::Cancel() brings the object back to its natural,
-// default-constructed state, i.e., CancelableCallback::callback() will return
-// a null callback.
-//
-// THREAD-SAFETY:
-//
-// CancelableCallback objects must be created on, posted to, cancelled on, and
-// destroyed on the same thread.
-//
-//
-// EXAMPLE USAGE:
-//
-// In the following example, the test is verifying that RunIntensiveTest()
-// Quit()s the message loop within 4 seconds. The cancelable callback is posted
-// to the message loop, the intensive test runs, the message loop is run,
-// then the callback is cancelled.
-//
-// void TimeoutCallback(const std::string& timeout_message) {
-//   FAIL() << timeout_message;
-//   MessageLoop::current()->QuitWhenIdle();
-// }
-//
-// CancelableClosure timeout(base::Bind(&TimeoutCallback, "Test timed out."));
-// MessageLoop::current()->PostDelayedTask(FROM_HERE, timeout.callback(),
-//                                         4000)  // 4 seconds to run.
-// RunIntensiveTest();
-// MessageLoop::current()->Run();
-// timeout.Cancel();  // Hopefully this is hit before the timeout callback runs.
-//
+
+///
+/// \file
+/// CancelableCallback is a wrapper around base::Callback that allows
+/// cancellation of a callback. CancelableCallback takes a reference on the
+/// wrapped callback until this object is destroyed or Reset()/Cancel() are
+/// called.
+///
+/// NOTE:
+///
+/// Calling CancelableCallback::Cancel() brings the object back to its natural,
+/// default-constructed state, i.e., CancelableCallback::callback() will return
+/// a null callback.
+///
+/// THREAD-SAFETY:
+///
+/// CancelableCallback objects must be created on, posted to, cancelled on, and
+/// destroyed on the same thread.
+///
+///
+/// EXAMPLE USAGE:
+///
+/// In the following example, the test is verifying that RunIntensiveTest()
+/// Quit()s the message loop within 4 seconds. The cancelable callback is posted
+/// to the message loop, the intensive test runs, the message loop is run,
+/// then the callback is cancelled.
+///
+/// <pre>
+///   RunLoop run_loop;
+///
+///   void TimeoutCallback(const std::string& timeout_message) {
+///     FAIL() << timeout_message;
+///     run_loop.QuitWhenIdle();
+///   }
+///
+///   CancelableOnceClosure timeout(
+///       base::BindOnce(&TimeoutCallback, "Test timed out."));
+///   ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE,
+///                                                  timeout.callback(),
+///                                                  TimeDelta::FromSeconds(4));
+///   RunIntensiveTest();
+///   run_loop.Run();
+///   // Hopefully this is hit before the timeout callback runs.
+///   timeout.Cancel();
+/// </pre>
+///
 
 #ifndef CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_
 #define CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_
 #pragma once
 
-#if defined(BASE_CANCELABLE_CALLBACK_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
+#if defined(USING_CHROMIUM_INCLUDES)
 // When building CEF include the Chromium header directly.
 #include "base/cancelable_callback.h"
 #else  // !USING_CHROMIUM_INCLUDES
@@ -82,37 +86,36 @@
 // If the Chromium implementation diverges the below implementation should be
 // updated to match.
 
+#include <utility>
+
 #include "include/base/cef_bind.h"
-#include "include/base/cef_build.h"
 #include "include/base/cef_callback.h"
+#include "include/base/cef_compiler_specific.h"
 #include "include/base/cef_logging.h"
-#include "include/base/cef_macros.h"
 #include "include/base/cef_weak_ptr.h"
 #include "include/base/internal/cef_callback_internal.h"
 
 namespace base {
+namespace internal {
 
-template <typename Sig>
-class CancelableCallback;
-
-template <>
-class CancelableCallback<void(void)> {
+template <typename CallbackType>
+class CancelableCallbackImpl {
  public:
-  CancelableCallback() : weak_factory_(this) {}
+  CancelableCallbackImpl() = default;
+  CancelableCallbackImpl(const CancelableCallbackImpl&) = delete;
+  CancelableCallbackImpl& operator=(const CancelableCallbackImpl&) = delete;
 
   // |callback| must not be null.
-  explicit CancelableCallback(const base::Callback<void(void)>& callback)
-      : weak_factory_(this), callback_(callback) {
-    DCHECK(!callback.is_null());
-    InitializeForwarder();
+  explicit CancelableCallbackImpl(CallbackType callback)
+      : callback_(std::move(callback)) {
+    DCHECK(callback_);
   }
 
-  ~CancelableCallback() {}
+  ~CancelableCallbackImpl() = default;
 
   // Cancels and drops the reference to the wrapped callback.
   void Cancel() {
-    weak_factory_.InvalidateWeakPtrs();
-    forwarder_.Reset();
+    weak_ptr_factory_.InvalidateWeakPtrs();
     callback_.Reset();
   }
 
@@ -121,170 +124,69 @@
 
   // Sets |callback| as the closure that may be cancelled. |callback| may not
   // be null. Outstanding and any previously wrapped callbacks are cancelled.
-  void Reset(const base::Callback<void(void)>& callback) {
-    DCHECK(!callback.is_null());
-
+  void Reset(CallbackType callback) {
+    DCHECK(callback);
     // Outstanding tasks (e.g., posted to a message loop) must not be called.
     Cancel();
-
-    // |forwarder_| is no longer valid after Cancel(), so re-bind.
-    InitializeForwarder();
-
-    callback_ = callback;
+    callback_ = std::move(callback);
   }
 
   // Returns a callback that can be disabled by calling Cancel().
-  const base::Callback<void(void)>& callback() const { return forwarder_; }
+  CallbackType callback() const {
+    if (!callback_) {
+      return CallbackType();
+    }
+    CallbackType forwarder;
+    MakeForwarder(&forwarder);
+    return forwarder;
+  }
 
  private:
-  void Forward() { callback_.Run(); }
-
-  // Helper method to bind |forwarder_| using a weak pointer from
-  // |weak_factory_|.
-  void InitializeForwarder() {
-    forwarder_ = base::Bind(&CancelableCallback<void(void)>::Forward,
-                            weak_factory_.GetWeakPtr());
+  template <typename... Args>
+  void MakeForwarder(RepeatingCallback<void(Args...)>* out) const {
+    using ForwarderType = void (CancelableCallbackImpl::*)(Args...);
+    ForwarderType forwarder = &CancelableCallbackImpl::ForwardRepeating;
+    *out = BindRepeating(forwarder, weak_ptr_factory_.GetWeakPtr());
   }
 
-  // Used to ensure Forward() is not run when this object is destroyed.
-  base::WeakPtrFactory<CancelableCallback<void(void)>> weak_factory_;
+  template <typename... Args>
+  void MakeForwarder(OnceCallback<void(Args...)>* out) const {
+    using ForwarderType = void (CancelableCallbackImpl::*)(Args...);
+    ForwarderType forwarder = &CancelableCallbackImpl::ForwardOnce;
+    *out = BindOnce(forwarder, weak_ptr_factory_.GetWeakPtr());
+  }
 
-  // The wrapper closure.
-  base::Callback<void(void)> forwarder_;
+  template <typename... Args>
+  void ForwardRepeating(Args... args) {
+    callback_.Run(std::forward<Args>(args)...);
+  }
+
+  template <typename... Args>
+  void ForwardOnce(Args... args) {
+    weak_ptr_factory_.InvalidateWeakPtrs();
+    std::move(callback_).Run(std::forward<Args>(args)...);
+  }
 
   // The stored closure that may be cancelled.
-  base::Callback<void(void)> callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(CancelableCallback);
+  CallbackType callback_;
+  mutable base::WeakPtrFactory<CancelableCallbackImpl> weak_ptr_factory_{this};
 };
 
-template <typename A1>
-class CancelableCallback<void(A1)> {
- public:
-  CancelableCallback() : weak_factory_(this) {}
+}  // namespace internal
 
-  // |callback| must not be null.
-  explicit CancelableCallback(const base::Callback<void(A1)>& callback)
-      : weak_factory_(this), callback_(callback) {
-    DCHECK(!callback.is_null());
-    InitializeForwarder();
-  }
+///
+/// Consider using base::WeakPtr directly instead of base::CancelableCallback
+/// for the task cancellation.
+///
+template <typename Signature>
+using CancelableOnceCallback =
+    internal::CancelableCallbackImpl<OnceCallback<Signature>>;
+using CancelableOnceClosure = CancelableOnceCallback<void()>;
 
-  ~CancelableCallback() {}
-
-  // Cancels and drops the reference to the wrapped callback.
-  void Cancel() {
-    weak_factory_.InvalidateWeakPtrs();
-    forwarder_.Reset();
-    callback_.Reset();
-  }
-
-  // Returns true if the wrapped callback has been cancelled.
-  bool IsCancelled() const { return callback_.is_null(); }
-
-  // Sets |callback| as the closure that may be cancelled. |callback| may not
-  // be null. Outstanding and any previously wrapped callbacks are cancelled.
-  void Reset(const base::Callback<void(A1)>& callback) {
-    DCHECK(!callback.is_null());
-
-    // Outstanding tasks (e.g., posted to a message loop) must not be called.
-    Cancel();
-
-    // |forwarder_| is no longer valid after Cancel(), so re-bind.
-    InitializeForwarder();
-
-    callback_ = callback;
-  }
-
-  // Returns a callback that can be disabled by calling Cancel().
-  const base::Callback<void(A1)>& callback() const { return forwarder_; }
-
- private:
-  void Forward(A1 a1) const { callback_.Run(a1); }
-
-  // Helper method to bind |forwarder_| using a weak pointer from
-  // |weak_factory_|.
-  void InitializeForwarder() {
-    forwarder_ = base::Bind(&CancelableCallback<void(A1)>::Forward,
-                            weak_factory_.GetWeakPtr());
-  }
-
-  // Used to ensure Forward() is not run when this object is destroyed.
-  base::WeakPtrFactory<CancelableCallback<void(A1)>> weak_factory_;
-
-  // The wrapper closure.
-  base::Callback<void(A1)> forwarder_;
-
-  // The stored closure that may be cancelled.
-  base::Callback<void(A1)> callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(CancelableCallback);
-};
-
-template <typename A1, typename A2>
-class CancelableCallback<void(A1, A2)> {
- public:
-  CancelableCallback() : weak_factory_(this) {}
-
-  // |callback| must not be null.
-  explicit CancelableCallback(const base::Callback<void(A1, A2)>& callback)
-      : weak_factory_(this), callback_(callback) {
-    DCHECK(!callback.is_null());
-    InitializeForwarder();
-  }
-
-  ~CancelableCallback() {}
-
-  // Cancels and drops the reference to the wrapped callback.
-  void Cancel() {
-    weak_factory_.InvalidateWeakPtrs();
-    forwarder_.Reset();
-    callback_.Reset();
-  }
-
-  // Returns true if the wrapped callback has been cancelled.
-  bool IsCancelled() const { return callback_.is_null(); }
-
-  // Sets |callback| as the closure that may be cancelled. |callback| may not
-  // be null. Outstanding and any previously wrapped callbacks are cancelled.
-  void Reset(const base::Callback<void(A1, A2)>& callback) {
-    DCHECK(!callback.is_null());
-
-    // Outstanding tasks (e.g., posted to a message loop) must not be called.
-    Cancel();
-
-    // |forwarder_| is no longer valid after Cancel(), so re-bind.
-    InitializeForwarder();
-
-    callback_ = callback;
-  }
-
-  // Returns a callback that can be disabled by calling Cancel().
-  const base::Callback<void(A1, A2)>& callback() const { return forwarder_; }
-
- private:
-  void Forward(A1 a1, A2 a2) const { callback_.Run(a1, a2); }
-
-  // Helper method to bind |forwarder_| using a weak pointer from
-  // |weak_factory_|.
-  void InitializeForwarder() {
-    forwarder_ = base::Bind(&CancelableCallback<void(A1, A2)>::Forward,
-                            weak_factory_.GetWeakPtr());
-  }
-
-  // Used to ensure Forward() is not run when this object is destroyed.
-  base::WeakPtrFactory<CancelableCallback<void(A1, A2)>> weak_factory_;
-
-  // The wrapper closure.
-  base::Callback<void(A1, A2)> forwarder_;
-
-  // The stored closure that may be cancelled.
-  base::Callback<void(A1, A2)> callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(CancelableCallback);
-};
-
-typedef CancelableCallback<void(void)> CancelableClosure;
+template <typename Signature>
+using CancelableRepeatingCallback =
+    internal::CancelableCallbackImpl<RepeatingCallback<Signature>>;
+using CancelableRepeatingClosure = CancelableRepeatingCallback<void()>;
 
 }  // namespace base
 
diff --git a/src/include/base/cef_compiler_specific.h b/src/include/base/cef_compiler_specific.h
new file mode 100644
index 0000000..24bcfb2
--- /dev/null
+++ b/src/include/base/cef_compiler_specific.h
@@ -0,0 +1,382 @@
+// Copyright (c) 2021 Marshall A. Greenblatt. Portions copyright (c) 2012
+// Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CEF_INCLUDE_BASE_CEF_COMPILER_SPECIFIC_H_
+#define CEF_INCLUDE_BASE_CEF_COMPILER_SPECIFIC_H_
+#pragma once
+
+#if defined(USING_CHROMIUM_INCLUDES)
+// When building CEF include the Chromium header directly.
+#include "base/compiler_specific.h"
+#else  // !USING_CHROMIUM_INCLUDES
+// The following is substantially similar to the Chromium implementation.
+// If the Chromium implementation diverges the below implementation should be
+// updated to match.
+
+#include "include/base/cef_build.h"
+
+// This is a wrapper around `__has_cpp_attribute`, which can be used to test for
+// the presence of an attribute. In case the compiler does not support this
+// macro it will simply evaluate to 0.
+//
+// References:
+// https://wg21.link/sd6#testing-for-the-presence-of-an-attribute-__has_cpp_attribute
+// https://wg21.link/cpp.cond#:__has_cpp_attribute
+#if defined(__has_cpp_attribute)
+#define HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
+#else
+#define HAS_CPP_ATTRIBUTE(x) 0
+#endif
+
+// A wrapper around `__has_builtin`, similar to HAS_CPP_ATTRIBUTE.
+#if defined(__has_builtin)
+#define HAS_BUILTIN(x) __has_builtin(x)
+#else
+#define HAS_BUILTIN(x) 0
+#endif
+
+// __has_feature and __has_attribute don't exist for MSVC.
+#if !defined(__has_feature)
+#define __has_feature(x) 0
+#endif  // !defined(__has_feature)
+
+#if !defined(__has_attribute)
+#define __has_attribute(x) 0
+#endif  // !defined(__has_attribute)
+
+// Annotate a function indicating it should not be inlined.
+// Use like:
+//   NOINLINE void DoStuff() { ... }
+#if defined(COMPILER_GCC)
+#define NOINLINE __attribute__((noinline))
+#elif defined(COMPILER_MSVC)
+#define NOINLINE __declspec(noinline)
+#else
+#define NOINLINE
+#endif
+
+#if defined(COMPILER_GCC) && defined(NDEBUG)
+#define ALWAYS_INLINE inline __attribute__((__always_inline__))
+#elif defined(COMPILER_MSVC) && defined(NDEBUG)
+#define ALWAYS_INLINE __forceinline
+#else
+#define ALWAYS_INLINE inline
+#endif
+
+// Annotate a function indicating it should never be tail called. Useful to make
+// sure callers of the annotated function are never omitted from call-stacks.
+// To provide the complementary behavior (prevent the annotated function from
+// being omitted) look at NOINLINE. Also note that this doesn't prevent code
+// folding of multiple identical caller functions into a single signature. To
+// prevent code folding, see NO_CODE_FOLDING() in base/debug/alias.h.
+// Use like:
+//   void NOT_TAIL_CALLED FooBar();
+#if defined(__clang__) && __has_attribute(not_tail_called)
+#define NOT_TAIL_CALLED __attribute__((not_tail_called))
+#else
+#define NOT_TAIL_CALLED
+#endif
+
+// Specify memory alignment for structs, classes, etc.
+// Use like:
+//   class ALIGNAS(16) MyClass { ... }
+//   ALIGNAS(16) int array[4];
+//
+// In most places you can use the C++11 keyword "alignas", which is preferred.
+//
+// But compilers have trouble mixing __attribute__((...)) syntax with
+// alignas(...) syntax.
+//
+// Doesn't work in clang or gcc:
+//   struct alignas(16) __attribute__((packed)) S { char c; };
+// Works in clang but not gcc:
+//   struct __attribute__((packed)) alignas(16) S2 { char c; };
+// Works in clang and gcc:
+//   struct alignas(16) S3 { char c; } __attribute__((packed));
+//
+// There are also some attributes that must be specified *before* a class
+// definition: visibility (used for exporting functions/classes) is one of
+// these attributes. This means that it is not possible to use alignas() with a
+// class that is marked as exported.
+#if defined(COMPILER_MSVC)
+#define ALIGNAS(byte_alignment) __declspec(align(byte_alignment))
+#elif defined(COMPILER_GCC)
+#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
+#endif
+
+// In case the compiler supports it NO_UNIQUE_ADDRESS evaluates to the C++20
+// attribute [[no_unique_address]]. This allows annotating data members so that
+// they need not have an address distinct from all other non-static data members
+// of its class.
+//
+// References:
+// * https://en.cppreference.com/w/cpp/language/attributes/no_unique_address
+// * https://wg21.link/dcl.attr.nouniqueaddr
+#if HAS_CPP_ATTRIBUTE(no_unique_address)
+#define NO_UNIQUE_ADDRESS [[no_unique_address]]
+#else
+#define NO_UNIQUE_ADDRESS
+#endif
+
+// Tell the compiler a function is using a printf-style format string.
+// |format_param| is the one-based index of the format string parameter;
+// |dots_param| is the one-based index of the "..." parameter.
+// For v*printf functions (which take a va_list), pass 0 for dots_param.
+// (This is undocumented but matches what the system C headers do.)
+// For member functions, the implicit this parameter counts as index 1.
+#if defined(COMPILER_GCC) || defined(__clang__)
+#define PRINTF_FORMAT(format_param, dots_param) \
+  __attribute__((format(printf, format_param, dots_param)))
+#else
+#define PRINTF_FORMAT(format_param, dots_param)
+#endif
+
+// WPRINTF_FORMAT is the same, but for wide format strings.
+// This doesn't appear to yet be implemented in any compiler.
+// See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38308 .
+#define WPRINTF_FORMAT(format_param, dots_param)
+// If available, it would look like:
+//   __attribute__((format(wprintf, format_param, dots_param)))
+
+// Sanitizers annotations.
+#if defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+#define NO_SANITIZE(what) __attribute__((no_sanitize(what)))
+#endif
+#endif
+#if !defined(NO_SANITIZE)
+#define NO_SANITIZE(what)
+#endif
+
+// MemorySanitizer annotations.
+#if defined(MEMORY_SANITIZER) && !defined(OS_NACL)
+#include <sanitizer/msan_interface.h>
+
+// Mark a memory region fully initialized.
+// Use this to annotate code that deliberately reads uninitialized data, for
+// example a GC scavenging root set pointers from the stack.
+#define MSAN_UNPOISON(p, size) __msan_unpoison(p, size)
+
+// Check a memory region for initializedness, as if it was being used here.
+// If any bits are uninitialized, crash with an MSan report.
+// Use this to sanitize data which MSan won't be able to track, e.g. before
+// passing data to another process via shared memory.
+#define MSAN_CHECK_MEM_IS_INITIALIZED(p, size) \
+  __msan_check_mem_is_initialized(p, size)
+#else  // MEMORY_SANITIZER
+#define MSAN_UNPOISON(p, size)
+#define MSAN_CHECK_MEM_IS_INITIALIZED(p, size)
+#endif  // MEMORY_SANITIZER
+
+// DISABLE_CFI_PERF -- Disable Control Flow Integrity for perf reasons.
+#if !defined(DISABLE_CFI_PERF)
+#if defined(__clang__) && defined(OFFICIAL_BUILD)
+#define DISABLE_CFI_PERF __attribute__((no_sanitize("cfi")))
+#else
+#define DISABLE_CFI_PERF
+#endif
+#endif
+
+// DISABLE_CFI_ICALL -- Disable Control Flow Integrity indirect call checks.
+#if !defined(DISABLE_CFI_ICALL)
+#if defined(OS_WIN)
+// Windows also needs __declspec(guard(nocf)).
+#define DISABLE_CFI_ICALL NO_SANITIZE("cfi-icall") __declspec(guard(nocf))
+#else
+#define DISABLE_CFI_ICALL NO_SANITIZE("cfi-icall")
+#endif
+#endif
+#if !defined(DISABLE_CFI_ICALL)
+#define DISABLE_CFI_ICALL
+#endif
+
+// Macro useful for writing cross-platform function pointers.
+#if !defined(CDECL)
+#if defined(OS_WIN)
+#define CDECL __cdecl
+#else  // defined(OS_WIN)
+#define CDECL
+#endif  // defined(OS_WIN)
+#endif  // !defined(CDECL)
+
+// Macro for hinting that an expression is likely to be false.
+#if !defined(UNLIKELY)
+#if defined(COMPILER_GCC) || defined(__clang__)
+#define UNLIKELY(x) __builtin_expect(!!(x), 0)
+#else
+#define UNLIKELY(x) (x)
+#endif  // defined(COMPILER_GCC)
+#endif  // !defined(UNLIKELY)
+
+#if !defined(LIKELY)
+#if defined(COMPILER_GCC) || defined(__clang__)
+#define LIKELY(x) __builtin_expect(!!(x), 1)
+#else
+#define LIKELY(x) (x)
+#endif  // defined(COMPILER_GCC)
+#endif  // !defined(LIKELY)
+
+// Compiler feature-detection.
+// clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension
+#if defined(__has_feature)
+#define HAS_FEATURE(FEATURE) __has_feature(FEATURE)
+#else
+#define HAS_FEATURE(FEATURE) 0
+#endif
+
+#if defined(COMPILER_GCC)
+#define PRETTY_FUNCTION __PRETTY_FUNCTION__
+#elif defined(COMPILER_MSVC)
+#define PRETTY_FUNCTION __FUNCSIG__
+#else
+// See https://en.cppreference.com/w/c/language/function_definition#func
+#define PRETTY_FUNCTION __func__
+#endif
+
+#if !defined(CPU_ARM_NEON)
+#if defined(__arm__)
+#if !defined(__ARMEB__) && !defined(__ARM_EABI__) && !defined(__EABI__) && \
+    !defined(__VFP_FP__) && !defined(_WIN32_WCE) && !defined(ANDROID)
+#error Chromium does not support middle endian architecture
+#endif
+#if defined(__ARM_NEON__)
+#define CPU_ARM_NEON 1
+#endif
+#endif  // defined(__arm__)
+#endif  // !defined(CPU_ARM_NEON)
+
+#if !defined(HAVE_MIPS_MSA_INTRINSICS)
+#if defined(__mips_msa) && defined(__mips_isa_rev) && (__mips_isa_rev >= 5)
+#define HAVE_MIPS_MSA_INTRINSICS 1
+#endif
+#endif
+
+#if defined(__clang__) && __has_attribute(uninitialized)
+// Attribute "uninitialized" disables -ftrivial-auto-var-init=pattern for
+// the specified variable.
+// Library-wide alternative is
+// 'configs -= [ "//build/config/compiler:default_init_stack_vars" ]' in .gn
+// file.
+//
+// See "init_stack_vars" in build/config/compiler/BUILD.gn and
+// http://crbug.com/977230
+// "init_stack_vars" is enabled for non-official builds and we hope to enable it
+// in official build in 2020 as well. The flag writes fixed pattern into
+// uninitialized parts of all local variables. In rare cases such initialization
+// is undesirable and attribute can be used:
+//   1. Degraded performance
+// In most cases compiler is able to remove additional stores. E.g. if memory is
+// never accessed or properly initialized later. Preserved stores mostly will
+// not affect program performance. However if compiler failed on some
+// performance critical code we can get a visible regression in a benchmark.
+//   2. memset, memcpy calls
+// Compiler may replaces some memory writes with memset or memcpy calls. This is
+// not -ftrivial-auto-var-init specific, but it can happen more likely with the
+// flag. It can be a problem if code is not linked with C run-time library.
+//
+// Note: The flag is security risk mitigation feature. So in future the
+// attribute uses should be avoided when possible. However to enable this
+// mitigation on the most of the code we need to be less strict now and minimize
+// number of exceptions later. So if in doubt feel free to use attribute, but
+// please document the problem for someone who is going to cleanup it later.
+// E.g. platform, bot, benchmark or test name in patch description or next to
+// the attribute.
+#define STACK_UNINITIALIZED __attribute__((uninitialized))
+#else
+#define STACK_UNINITIALIZED
+#endif
+
+// The ANALYZER_ASSUME_TRUE(bool arg) macro adds compiler-specific hints
+// to Clang which control what code paths are statically analyzed,
+// and is meant to be used in conjunction with assert & assert-like functions.
+// The expression is passed straight through if analysis isn't enabled.
+//
+// ANALYZER_SKIP_THIS_PATH() suppresses static analysis for the current
+// codepath and any other branching codepaths that might follow.
+#if defined(__clang_analyzer__)
+
+inline constexpr bool AnalyzerNoReturn() __attribute__((analyzer_noreturn)) {
+  return false;
+}
+
+inline constexpr bool AnalyzerAssumeTrue(bool arg) {
+  // AnalyzerNoReturn() is invoked and analysis is terminated if |arg| is
+  // false.
+  return arg || AnalyzerNoReturn();
+}
+
+#define ANALYZER_ASSUME_TRUE(arg) ::AnalyzerAssumeTrue(!!(arg))
+#define ANALYZER_SKIP_THIS_PATH() static_cast<void>(::AnalyzerNoReturn())
+#define ANALYZER_ALLOW_UNUSED(var) static_cast<void>(var);
+
+#else  // !defined(__clang_analyzer__)
+
+#define ANALYZER_ASSUME_TRUE(arg) (arg)
+#define ANALYZER_SKIP_THIS_PATH()
+#define ANALYZER_ALLOW_UNUSED(var) static_cast<void>(var);
+
+#endif  // defined(__clang_analyzer__)
+
+// Use nomerge attribute to disable optimization of merging multiple same calls.
+#if defined(__clang__) && __has_attribute(nomerge)
+#define NOMERGE [[clang::nomerge]]
+#else
+#define NOMERGE
+#endif
+
+// Marks a type as being eligible for the "trivial" ABI despite having a
+// non-trivial destructor or copy/move constructor. Such types can be relocated
+// after construction by simply copying their memory, which makes them eligible
+// to be passed in registers. The canonical example is std::unique_ptr.
+//
+// Use with caution; this has some subtle effects on constructor/destructor
+// ordering and will be very incorrect if the type relies on its address
+// remaining constant. When used as a function argument (by value), the value
+// may be constructed in the caller's stack frame, passed in a register, and
+// then used and destructed in the callee's stack frame. A similar thing can
+// occur when values are returned.
+//
+// TRIVIAL_ABI is not needed for types which have a trivial destructor and
+// copy/move constructors, such as base::TimeTicks and other POD.
+//
+// It is also not likely to be effective on types too large to be passed in one
+// or two registers on typical target ABIs.
+//
+// See also:
+//   https://clang.llvm.org/docs/AttributeReference.html#trivial-abi
+//   https://libcxx.llvm.org/docs/DesignDocs/UniquePtrTrivialAbi.html
+#if defined(__clang__) && __has_attribute(trivial_abi)
+#define TRIVIAL_ABI [[clang::trivial_abi]]
+#else
+#define TRIVIAL_ABI
+#endif
+
+#endif  // !USING_CHROMIUM_INCLUDES
+#endif  // CEF_INCLUDE_BASE_CEF_COMPILER_SPECIFIC_H_
diff --git a/src/include/base/cef_lock.h b/src/include/base/cef_lock.h
index 6909bd6..27af8ae 100644
--- a/src/include/base/cef_lock.h
+++ b/src/include/base/cef_lock.h
@@ -32,12 +32,7 @@
 #define CEF_INCLUDE_BASE_CEF_LOCK_H_
 #pragma once
 
-#if defined(BASE_SYNCHRONIZATION_LOCK_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
+#if defined(USING_CHROMIUM_INCLUDES)
 // When building CEF include the Chromium header directly.
 #include "base/synchronization/lock.h"
 #else  // !USING_CHROMIUM_INCLUDES
@@ -46,28 +41,35 @@
 // updated to match.
 
 #include "include/base/cef_logging.h"
-#include "include/base/cef_macros.h"
 #include "include/base/cef_platform_thread.h"
 #include "include/base/internal/cef_lock_impl.h"
 
 namespace base {
 namespace cef_internal {
 
-// A convenient wrapper for an OS specific critical section.  The only real
-// intelligence in this class is in debug mode for the support for the
-// AssertAcquired() method.
+///
+/// A convenient wrapper for an OS specific critical section.  The only real
+/// intelligence in this class is in debug mode for the support for the
+/// AssertAcquired() method.
+///
 class Lock {
  public:
 #if !DCHECK_IS_ON()  // Optimized wrapper implementation
   Lock() : lock_() {}
+
+  Lock(const Lock&) = delete;
+  Lock& operator=(const Lock&) = delete;
+
   ~Lock() {}
   void Acquire() { lock_.Lock(); }
   void Release() { lock_.Unlock(); }
 
-  // If the lock is not held, take it and return true. If the lock is already
-  // held by another thread, immediately return false. This must not be called
-  // by a thread already holding the lock (what happens is undefined and an
-  // assertion may fail).
+  ///
+  /// If the lock is not held, take it and return true. If the lock is already
+  /// held by another thread, immediately return false. This must not be called
+  /// by a thread already holding the lock (what happens is undefined and an
+  /// assertion may fail).
+  ///
   bool Try() { return lock_.Try(); }
 
   // Null implementation if not debug.
@@ -116,11 +118,11 @@
 
   // Platform specific underlying lock implementation.
   LockImpl lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(Lock);
 };
 
-// A helper class that acquires the given Lock while the AutoLock is in scope.
+///
+/// A helper class that acquires the given Lock while the AutoLock is in scope.
+///
 class AutoLock {
  public:
   struct AlreadyAcquired {};
@@ -131,6 +133,9 @@
     lock_.AssertAcquired();
   }
 
+  AutoLock(const AutoLock&) = delete;
+  AutoLock& operator=(const AutoLock&) = delete;
+
   ~AutoLock() {
     lock_.AssertAcquired();
     lock_.Release();
@@ -138,11 +143,12 @@
 
  private:
   Lock& lock_;
-  DISALLOW_COPY_AND_ASSIGN(AutoLock);
 };
 
-// AutoUnlock is a helper that will Release() the |lock| argument in the
-// constructor, and re-Acquire() it in the destructor.
+///
+/// AutoUnlock is a helper that will Release() the |lock| argument in the
+/// constructor, and re-Acquire() it in the destructor.
+///
 class AutoUnlock {
  public:
   explicit AutoUnlock(Lock& lock) : lock_(lock) {
@@ -151,11 +157,13 @@
     lock_.Release();
   }
 
+  AutoUnlock(const AutoUnlock&) = delete;
+  AutoUnlock& operator=(const AutoUnlock&) = delete;
+
   ~AutoUnlock() { lock_.Acquire(); }
 
  private:
   Lock& lock_;
-  DISALLOW_COPY_AND_ASSIGN(AutoUnlock);
 };
 
 }  // namespace cef_internal
@@ -163,9 +171,9 @@
 // Implement classes in the cef_internal namespace and then expose them to the
 // base namespace. This avoids conflicts with the base.lib implementation when
 // linking sandbox support on Windows.
-using cef_internal::Lock;
 using cef_internal::AutoLock;
 using cef_internal::AutoUnlock;
+using cef_internal::Lock;
 
 }  // namespace base
 
diff --git a/src/include/base/cef_logging.h b/src/include/base/cef_logging.h
index ba93097..31adf21 100644
--- a/src/include/base/cef_logging.h
+++ b/src/include/base/cef_logging.h
@@ -27,116 +27,140 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// ---------------------------------------------------------------------------
-//
-// The contents of this file are only available to applications that link
-// against the libcef_dll_wrapper target.
-//
-// WARNING: Logging macros should not be used in the main/browser process before
-// calling CefInitialize or in sub-processes before calling CefExecuteProcess.
-//
-// Instructions
-// ------------
-//
-// Make a bunch of macros for logging.  The way to log things is to stream
-// things to LOG(<a particular severity level>).  E.g.,
-//
-//   LOG(INFO) << "Found " << num_cookies << " cookies";
-//
-// You can also do conditional logging:
-//
-//   LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
-//
-// The CHECK(condition) macro is active in both debug and release builds and
-// effectively performs a LOG(FATAL) which terminates the process and
-// generates a crashdump unless a debugger is attached.
-//
-// There are also "debug mode" logging macros like the ones above:
-//
-//   DLOG(INFO) << "Found cookies";
-//
-//   DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
-//
-// All "debug mode" logging is compiled away to nothing for non-debug mode
-// compiles.  LOG_IF and development flags also work well together
-// because the code can be compiled away sometimes.
-//
-// We also have
-//
-//   LOG_ASSERT(assertion);
-//   DLOG_ASSERT(assertion);
-//
-// which is syntactic sugar for {,D}LOG_IF(FATAL, assert fails) << assertion;
-//
-// There are "verbose level" logging macros.  They look like
-//
-//   VLOG(1) << "I'm printed when you run the program with --v=1 or more";
-//   VLOG(2) << "I'm printed when you run the program with --v=2 or more";
-//
-// These always log at the INFO log level (when they log at all).
-// The verbose logging can also be turned on module-by-module.  For instance,
-//    --vmodule=profile=2,icon_loader=1,browser_*=3,*/chromeos/*=4 --v=0
-// will cause:
-//   a. VLOG(2) and lower messages to be printed from profile.{h,cc}
-//   b. VLOG(1) and lower messages to be printed from icon_loader.{h,cc}
-//   c. VLOG(3) and lower messages to be printed from files prefixed with
-//      "browser"
-//   d. VLOG(4) and lower messages to be printed from files under a
-//     "chromeos" directory.
-//   e. VLOG(0) and lower messages to be printed from elsewhere
-//
-// The wildcarding functionality shown by (c) supports both '*' (match
-// 0 or more characters) and '?' (match any single character)
-// wildcards.  Any pattern containing a forward or backward slash will
-// be tested against the whole pathname and not just the module.
-// E.g., "*/foo/bar/*=2" would change the logging level for all code
-// in source files under a "foo/bar" directory.
-//
-// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as
-//
-//   if (VLOG_IS_ON(2)) {
-//     // do some logging preparation and logging
-//     // that can't be accomplished with just VLOG(2) << ...;
-//   }
-//
-// There is also a VLOG_IF "verbose level" condition macro for sample
-// cases, when some extra computation and preparation for logs is not
-// needed.
-//
-//   VLOG_IF(1, (size > 1024))
-//      << "I'm printed when size is more than 1024 and when you run the "
-//         "program with --v=1 or more";
-//
-// We also override the standard 'assert' to use 'DLOG_ASSERT'.
-//
-// Lastly, there is:
-//
-//   PLOG(ERROR) << "Couldn't do foo";
-//   DPLOG(ERROR) << "Couldn't do foo";
-//   PLOG_IF(ERROR, cond) << "Couldn't do foo";
-//   DPLOG_IF(ERROR, cond) << "Couldn't do foo";
-//   PCHECK(condition) << "Couldn't do foo";
-//   DPCHECK(condition) << "Couldn't do foo";
-//
-// which append the last system error to the message in string form (taken from
-// GetLastError() on Windows and errno on POSIX).
-//
-// The supported severity levels for macros that allow you to specify one
-// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL.
-//
-// Very important: logging a message at the FATAL severity level causes
-// the program to terminate (after the message is logged).
-//
-// There is the special severity of DFATAL, which logs FATAL in debug mode,
-// ERROR in normal mode.
-//
+
+///
+/// \file
+/// A bunch of macros for logging.
+///
+/// NOTE: The contents of this file are only available to applications that link
+/// against the libcef_dll_wrapper target.
+///
+/// WARNING: Logging macros should not be used in the main/browser process
+/// before calling CefInitialize or in sub-processes before calling
+/// CefExecuteProcess.
+///
+/// INSTRUCTIONS:
+///
+/// The way to log things is to stream things to LOG(<a particular severity
+/// level>). E.g.,
+///
+/// <pre>
+///   LOG(INFO) << "Found " << num_cookies << " cookies";
+/// </pre>
+///
+/// You can also do conditional logging:
+///
+/// <pre>
+///   LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
+/// </pre>
+///
+/// The CHECK(condition) macro is active in both debug and release builds and
+/// effectively performs a LOG(FATAL) which terminates the process and
+/// generates a crashdump unless a debugger is attached.
+///
+/// There are also "debug mode" logging macros like the ones above:
+///
+/// <pre>
+///   DLOG(INFO) << "Found cookies";
+///
+///   DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
+/// </pre>
+///
+/// All "debug mode" logging is compiled away to nothing for non-debug mode
+/// compiles.  LOG_IF and development flags also work well together
+/// because the code can be compiled away sometimes.
+///
+/// We also have
+///
+/// <pre>
+///   LOG_ASSERT(assertion);
+///   DLOG_ASSERT(assertion);
+/// </pre>
+///
+/// which is syntactic sugar for "{,D}LOG_IF(FATAL, assert fails) << assertion;"
+///
+/// There are "verbose level" logging macros.  They look like
+///
+/// <pre>
+///   VLOG(1) << "I'm printed when you run the program with --v=1 or more";
+///   VLOG(2) << "I'm printed when you run the program with --v=2 or more";
+/// </pre>
+///
+/// These always log at the INFO log level (when they log at all).
+/// The verbose logging can also be turned on module-by-module.  For instance,
+/// <pre>
+///    --vmodule=profile=2,icon_loader=1,browser_*=3,*/chromeos/*=4 --v=0
+/// </pre>
+/// will cause:
+/// 1. VLOG(2) and lower messages to be printed from profile.{h,cc}
+/// 2. VLOG(1) and lower messages to be printed from icon_loader.{h,cc}
+/// 3. VLOG(3) and lower messages to be printed from files prefixed with
+///    "browser"
+/// 4. VLOG(4) and lower messages to be printed from files under a
+///    "chromeos" directory.
+/// 5. VLOG(0) and lower messages to be printed from elsewhere
+///
+/// The wildcarding functionality shown by (c) supports both '*' (match
+/// 0 or more characters) and '?' (match any single character)
+/// wildcards.  Any pattern containing a forward or backward slash will
+/// be tested against the whole pathname and not just the module.
+/// E.g., "*/foo/bar/*=2" would change the logging level for all code
+/// in source files under a "foo/bar" directory.
+///
+/// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as
+///
+/// <pre>
+///   if (VLOG_IS_ON(2)) {
+///     // do some logging preparation and logging
+///     // that can't be accomplished with just VLOG(2) << ...;
+///   }
+/// </pre>
+///
+/// There is also a VLOG_IF "verbose level" condition macro for sample
+/// cases, when some extra computation and preparation for logs is not
+/// needed.
+///
+/// <pre>
+///   VLOG_IF(1, (size > 1024))
+///      << "I'm printed when size is more than 1024 and when you run the "
+///         "program with --v=1 or more";
+/// </pre>
+///
+/// We also override the standard 'assert' to use 'DLOG_ASSERT'.
+///
+/// Lastly, there is:
+///
+/// <pre>
+///   PLOG(ERROR) << "Couldn't do foo";
+///   DPLOG(ERROR) << "Couldn't do foo";
+///   PLOG_IF(ERROR, cond) << "Couldn't do foo";
+///   DPLOG_IF(ERROR, cond) << "Couldn't do foo";
+///   PCHECK(condition) << "Couldn't do foo";
+///   DPCHECK(condition) << "Couldn't do foo";
+/// </pre>
+///
+/// which append the last system error to the message in string form (taken from
+/// GetLastError() on Windows and errno on POSIX).
+///
+/// The supported severity levels for macros that allow you to specify one
+/// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL.
+///
+/// Very important: logging a message at the FATAL severity level causes
+/// the program to terminate (after the message is logged).
+///
+/// There is the special severity of DFATAL, which logs FATAL in debug mode,
+/// ERROR in normal mode.
+///
 
 #ifndef CEF_INCLUDE_BASE_CEF_LOGGING_H_
 #define CEF_INCLUDE_BASE_CEF_LOGGING_H_
 #pragma once
 
-#if defined(DCHECK)
+#if defined(USING_CHROMIUM_INCLUDES)
+// When building CEF include the Chromium header directly.
+#include "base/logging.h"
+#include "base/notreached.h"
+#elif defined(DCHECK)
 // Do nothing if the macros provided by this header already exist.
 // This can happen in cases where Chromium code is used directly by the
 // client application. When using Chromium code directly always include
@@ -149,10 +173,7 @@
 #define DCHECK_IS_ON() true
 #endif
 
-#elif defined(USING_CHROMIUM_INCLUDES)
-// When building CEF include the Chromium header directly.
-#include "base/logging.h"
-#else  // !USING_CHROMIUM_INCLUDES
+#else  // !defined(DCHECK)
 // The following is substantially similar to the Chromium implementation.
 // If the Chromium implementation diverges the below implementation should be
 // updated to match.
@@ -163,7 +184,6 @@
 #include <string>
 
 #include "include/base/cef_build.h"
-#include "include/base/cef_macros.h"
 #include "include/internal/cef_logging_internal.h"
 
 namespace cef {
@@ -201,21 +221,21 @@
 // A few definitions of macros that don't generate much code. These are used
 // by LOG() and LOG_IF, etc. Since these are used all over our code, it's
 // better to have compact code for these operations.
-#define COMPACT_GOOGLE_LOG_EX_INFO(ClassName, ...)                    \
-  cef::logging::ClassName(__FILE__, __LINE__, cef::logging::LOG_INFO, \
-                          ##__VA_ARGS__)
-#define COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...)                    \
-  cef::logging::ClassName(__FILE__, __LINE__, cef::logging::LOG_WARNING, \
-                          ##__VA_ARGS__)
-#define COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ...)                    \
-  cef::logging::ClassName(__FILE__, __LINE__, cef::logging::LOG_ERROR, \
-                          ##__VA_ARGS__)
-#define COMPACT_GOOGLE_LOG_EX_FATAL(ClassName, ...)                    \
-  cef::logging::ClassName(__FILE__, __LINE__, cef::logging::LOG_FATAL, \
-                          ##__VA_ARGS__)
-#define COMPACT_GOOGLE_LOG_EX_DFATAL(ClassName, ...)                    \
-  cef::logging::ClassName(__FILE__, __LINE__, cef::logging::LOG_DFATAL, \
-                          ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_EX_INFO(ClassName, ...)                        \
+  ::cef::logging::ClassName(__FILE__, __LINE__, ::cef::logging::LOG_INFO, \
+                            ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...)                        \
+  ::cef::logging::ClassName(__FILE__, __LINE__, ::cef::logging::LOG_WARNING, \
+                            ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ...)                        \
+  ::cef::logging::ClassName(__FILE__, __LINE__, ::cef::logging::LOG_ERROR, \
+                            ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_EX_FATAL(ClassName, ...)                        \
+  ::cef::logging::ClassName(__FILE__, __LINE__, ::cef::logging::LOG_FATAL, \
+                            ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_EX_DFATAL(ClassName, ...)                        \
+  ::cef::logging::ClassName(__FILE__, __LINE__, ::cef::logging::LOG_DFATAL, \
+                            ##__VA_ARGS__)
 
 #define COMPACT_GOOGLE_LOG_INFO COMPACT_GOOGLE_LOG_EX_INFO(LogMessage)
 #define COMPACT_GOOGLE_LOG_WARNING COMPACT_GOOGLE_LOG_EX_WARNING(LogMessage)
@@ -553,12 +573,7 @@
 #define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2)
 #define DCHECK_GT(val1, val2) DCHECK_OP(GT, >, val1, val2)
 
-#if defined(NDEBUG) && defined(OS_CHROMEOS)
-#define NOTREACHED() \
-  LOG(ERROR) << "NOTREACHED() hit in " << __FUNCTION__ << ". "
-#else
 #define NOTREACHED() DCHECK(false)
-#endif
 
 // Redefine the standard assert to use our nice log files
 #undef assert
@@ -587,6 +602,9 @@
              LogSeverity severity,
              std::string* result);
 
+  LogMessage(const LogMessage&) = delete;
+  LogMessage& operator=(const LogMessage&) = delete;
+
   ~LogMessage();
 
   std::ostream& stream() { return stream_; }
@@ -618,8 +636,6 @@
 
   SaveLastError last_error_;
 #endif
-
-  DISALLOW_COPY_AND_ASSIGN(LogMessage);
 };
 
 // A non-macro interface to the log facility; (useful
@@ -659,6 +675,9 @@
                        LogSeverity severity,
                        SystemErrorCode err);
 
+  Win32ErrorLogMessage(const Win32ErrorLogMessage&) = delete;
+  Win32ErrorLogMessage& operator=(const Win32ErrorLogMessage&) = delete;
+
   // Appends the error message before destructing the encapsulated class.
   ~Win32ErrorLogMessage();
 
@@ -667,8 +686,6 @@
  private:
   SystemErrorCode err_;
   LogMessage log_message_;
-
-  DISALLOW_COPY_AND_ASSIGN(Win32ErrorLogMessage);
 };
 #elif defined(OS_POSIX)
 // Appends a formatted system message of the errno type
@@ -679,6 +696,9 @@
                   LogSeverity severity,
                   SystemErrorCode err);
 
+  ErrnoLogMessage(const ErrnoLogMessage&) = delete;
+  ErrnoLogMessage& operator=(const ErrnoLogMessage&) = delete;
+
   // Appends the error message before destructing the encapsulated class.
   ~ErrnoLogMessage();
 
@@ -687,8 +707,6 @@
  private:
   SystemErrorCode err_;
   LogMessage log_message_;
-
-  DISALLOW_COPY_AND_ASSIGN(ErrnoLogMessage);
 };
 #endif  // OS_WIN
 
@@ -705,6 +723,13 @@
 inline std::ostream& operator<<(std::ostream& out, const std::wstring& wstr) {
   return out << wstr.c_str();
 }
+#if defined(WCHAR_T_IS_UTF32)
+std::ostream& operator<<(std::ostream& out, const char16_t* wstr);
+#elif defined(WCHAR_T_IS_UTF16)
+inline std::ostream& operator<<(std::ostream& out, const char16_t* wstr) {
+  return operator<<(out, reinterpret_cast<const wchar_t*>(wstr));
+}
+#endif
 
 // The NOTIMPLEMENTED() macro annotates codepaths which have
 // not been implemented yet.
diff --git a/src/include/base/cef_macros.h b/src/include/base/cef_macros.h
index e714529..f5517f9 100644
--- a/src/include/base/cef_macros.h
+++ b/src/include/base/cef_macros.h
@@ -32,189 +32,32 @@
 #define CEF_INCLUDE_BASE_CEF_MACROS_H_
 #pragma once
 
-#if defined(USING_CHROMIUM_INCLUDES)
-// When building CEF include the Chromium header directly.
-#include "base/macros.h"
-
-#else  // !USING_CHROMIUM_INCLUDES
+#if !defined(USING_CHROMIUM_INCLUDES)
 // The following is substantially similar to the Chromium implementation.
 // If the Chromium implementation diverges the below implementation should be
 // updated to match.
 
-#include <stddef.h>                  // For size_t.
-#include "include/base/cef_build.h"  // For COMPILER_MSVC
+// ALL DISALLOW_xxx MACROS ARE DEPRECATED; DO NOT USE IN NEW CODE.
+// Use explicit deletions instead. For more information see
+// https://chromium.googlesource.com/chromium/src/+/lkgr/styleguide/c++/c++-dos-and-donts.md#explicitly-declare-class-copyability_movability
 
-#if !defined(arraysize)
+// DEPRECATED: See above. Makes a class uncopyable.
+#define DISALLOW_COPY(TypeName) TypeName(const TypeName&) = delete
 
-// The arraysize(arr) macro returns the # of elements in an array arr.
-// The expression is a compile-time constant, and therefore can be
-// used in defining new arrays, for example.  If you use arraysize on
-// a pointer by mistake, you will get a compile-time error.
-//
-// One caveat is that arraysize() doesn't accept any array of an
-// anonymous type or a type defined inside a function.  In these rare
-// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below.  This is
-// due to a limitation in C++'s template system.  The limitation might
-// eventually be removed, but it hasn't happened yet.
+// DEPRECATED: See above. Makes a class unassignable.
+#define DISALLOW_ASSIGN(TypeName) TypeName& operator=(const TypeName&) = delete
 
-// This template function declaration is used in defining arraysize.
-// Note that the function doesn't need an implementation, as we only
-// use its type.
-template <typename T, size_t N>
-char (&ArraySizeHelper(T (&array)[N]))[N];
-
-// That gcc wants both of these prototypes seems mysterious. VC, for
-// its part, can't decide which to use (another mystery). Matching of
-// template overloads: the final frontier.
-#ifndef _MSC_VER
-template <typename T, size_t N>
-char (&ArraySizeHelper(const T (&array)[N]))[N];
-#endif
-
-#define arraysize(array) (sizeof(ArraySizeHelper(array)))
-
-#endif  // !arraysize
-
-#if !defined(DISALLOW_COPY_AND_ASSIGN)
-
-// A macro to disallow the copy constructor and operator= functions
-// This should be used in the private: declarations for a class
+// DEPRECATED: See above. Makes a class uncopyable and unassignable.
 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
-  TypeName(const TypeName&);               \
-  void operator=(const TypeName&)
+  DISALLOW_COPY(TypeName);                 \
+  DISALLOW_ASSIGN(TypeName)
 
-#endif  // !DISALLOW_COPY_AND_ASSIGN
-
-#if !defined(DISALLOW_IMPLICIT_CONSTRUCTORS)
-
-// A macro to disallow all the implicit constructors, namely the
+// DEPRECATED: See above. Disallow all implicit constructors, namely the
 // default constructor, copy constructor and operator= functions.
-//
-// This should be used in the private: declarations for a class
-// that wants to prevent anyone from instantiating it. This is
-// especially useful for classes containing only static methods.
 #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
-  TypeName();                                    \
+  TypeName() = delete;                           \
   DISALLOW_COPY_AND_ASSIGN(TypeName)
 
-#endif  // !DISALLOW_IMPLICIT_CONSTRUCTORS
-
-#if !defined(COMPILE_ASSERT)
-
-// The COMPILE_ASSERT macro can be used to verify that a compile time
-// expression is true. For example, you could use it to verify the
-// size of a static array:
-//
-//   COMPILE_ASSERT(ARRAYSIZE_UNSAFE(content_type_names) == CONTENT_NUM_TYPES,
-//                  content_type_names_incorrect_size);
-//
-// or to make sure a struct is smaller than a certain size:
-//
-//   COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
-//
-// The second argument to the macro is the name of the variable. If
-// the expression is false, most compilers will issue a warning/error
-// containing the name of the variable.
-
-#if __cplusplus >= 201103L
-
-// Under C++11, just use static_assert.
-#define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
-
-#else
-
-namespace cef {
-
-template <bool>
-struct CompileAssert {};
-
-}  // namespace cef
-
-#define COMPILE_ASSERT(expr, msg)          \
-  typedef cef::CompileAssert<(bool(expr))> \
-      msg[bool(expr) ? 1 : -1] ALLOW_UNUSED_TYPE
-
-// Implementation details of COMPILE_ASSERT:
-//
-// - COMPILE_ASSERT works by defining an array type that has -1
-//   elements (and thus is invalid) when the expression is false.
-//
-// - The simpler definition
-//
-//     #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
-//
-//   does not work, as gcc supports variable-length arrays whose sizes
-//   are determined at run-time (this is gcc's extension and not part
-//   of the C++ standard).  As a result, gcc fails to reject the
-//   following code with the simple definition:
-//
-//     int foo;
-//     COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
-//                               // not a compile-time constant.
-//
-// - By using the type CompileAssert<(bool(expr))>, we ensures that
-//   expr is a compile-time constant.  (Template arguments must be
-//   determined at compile-time.)
-//
-// - The outer parentheses in CompileAssert<(bool(expr))> are necessary
-//   to work around a bug in gcc 3.4.4 and 4.0.1.  If we had written
-//
-//     CompileAssert<bool(expr)>
-//
-//   instead, these compilers will refuse to compile
-//
-//     COMPILE_ASSERT(5 > 0, some_message);
-//
-//   (They seem to think the ">" in "5 > 0" marks the end of the
-//   template argument list.)
-//
-// - The array size is (bool(expr) ? 1 : -1), instead of simply
-//
-//     ((expr) ? 1 : -1).
-//
-//   This is to avoid running into a bug in MS VC 7.1, which
-//   causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
-
-#endif  // !(__cplusplus >= 201103L)
-
-#endif  // !defined(COMPILE_ASSERT)
-
 #endif  // !USING_CHROMIUM_INCLUDES
 
-#if !defined(MSVC_PUSH_DISABLE_WARNING) && defined(COMPILER_MSVC)
-
-// MSVC_PUSH_DISABLE_WARNING pushes |n| onto a stack of warnings to be disabled.
-// The warning remains disabled until popped by MSVC_POP_WARNING.
-#define MSVC_PUSH_DISABLE_WARNING(n) \
-  __pragma(warning(push)) __pragma(warning(disable : n))
-
-// MSVC_PUSH_WARNING_LEVEL pushes |n| as the global warning level.  The level
-// remains in effect until popped by MSVC_POP_WARNING().  Use 0 to disable all
-// warnings.
-#define MSVC_PUSH_WARNING_LEVEL(n) __pragma(warning(push, n))
-
-// Pop effects of innermost MSVC_PUSH_* macro.
-#define MSVC_POP_WARNING() __pragma(warning(pop))
-
-#endif  // !defined(MSVC_PUSH_DISABLE_WARNING) && defined(COMPILER_MSVC)
-
-#if !defined(ALLOW_THIS_IN_INITIALIZER_LIST)
-#if defined(COMPILER_MSVC)
-// Allows |this| to be passed as an argument in constructor initializer lists.
-// This uses push/pop instead of the seemingly simpler suppress feature to avoid
-// having the warning be disabled for more than just |code|.
-//
-// Example usage:
-// Foo::Foo() : x(NULL), ALLOW_THIS_IN_INITIALIZER_LIST(y(this)), z(3) {}
-//
-// Compiler warning C4355: 'this': used in base member initializer list:
-// http://msdn.microsoft.com/en-us/library/3c594ae3(VS.80).aspx
-#define ALLOW_THIS_IN_INITIALIZER_LIST(code) \
-  MSVC_PUSH_DISABLE_WARNING(4355)            \
-  code MSVC_POP_WARNING()
-#else  // !COMPILER_MSVC
-#define ALLOW_THIS_IN_INITIALIZER_LIST(code) code
-#endif  // !COMPILER_MSVC
-#endif  // !ALLOW_THIS_IN_INITIALIZER_LIST
-
 #endif  // CEF_INCLUDE_BASE_CEF_MACROS_H_
diff --git a/src/include/base/cef_move.h b/src/include/base/cef_move.h
deleted file mode 100644
index da47d2d..0000000
--- a/src/include/base/cef_move.h
+++ /dev/null
@@ -1,261 +0,0 @@
-// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
-// Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef CEF_INCLUDE_BASE_CEF_MOVE_H_
-#define CEF_INCLUDE_BASE_CEF_MOVE_H_
-
-#if defined(MOVE_ONLY_TYPE_FOR_CPP_03)
-// Do nothing if the macro in this header has already been defined.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
-// When building CEF include the Chromium header directly.
-#include "base/move.h"
-#else  // !USING_CHROMIUM_INCLUDES
-// The following is substantially similar to the Chromium implementation.
-// If the Chromium implementation diverges the below implementation should be
-// updated to match.
-
-// Macro with the boilerplate that makes a type move-only in C++03.
-//
-// USAGE
-//
-// This macro should be used instead of DISALLOW_COPY_AND_ASSIGN to create
-// a "move-only" type.  Unlike DISALLOW_COPY_AND_ASSIGN, this macro should be
-// the first line in a class declaration.
-//
-// A class using this macro must call .Pass() (or somehow be an r-value already)
-// before it can be:
-//
-//   * Passed as a function argument
-//   * Used as the right-hand side of an assignment
-//   * Returned from a function
-//
-// Each class will still need to define their own "move constructor" and "move
-// operator=" to make this useful.  Here's an example of the macro, the move
-// constructor, and the move operator= from the scoped_ptr class:
-//
-//  template <typename T>
-//  class scoped_ptr {
-//     MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
-//   public:
-//    scoped_ptr(RValue& other) : ptr_(other.release()) { }
-//    scoped_ptr& operator=(RValue& other) {
-//      swap(other);
-//      return *this;
-//    }
-//  };
-//
-// Note that the constructor must NOT be marked explicit.
-//
-// For consistency, the second parameter to the macro should always be RValue
-// unless you have a strong reason to do otherwise.  It is only exposed as a
-// macro parameter so that the move constructor and move operator= don't look
-// like they're using a phantom type.
-//
-//
-// HOW THIS WORKS
-//
-// For a thorough explanation of this technique, see:
-//
-//   http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Move_Constructor
-//
-// The summary is that we take advantage of 2 properties:
-//
-//   1) non-const references will not bind to r-values.
-//   2) C++ can apply one user-defined conversion when initializing a
-//      variable.
-//
-// The first lets us disable the copy constructor and assignment operator
-// by declaring private version of them with a non-const reference parameter.
-//
-// For l-values, direct initialization still fails like in
-// DISALLOW_COPY_AND_ASSIGN because the copy constructor and assignment
-// operators are private.
-//
-// For r-values, the situation is different. The copy constructor and
-// assignment operator are not viable due to (1), so we are trying to call
-// a non-existent constructor and non-existing operator= rather than a private
-// one.  Since we have not committed an error quite yet, we can provide an
-// alternate conversion sequence and a constructor.  We add
-//
-//   * a private struct named "RValue"
-//   * a user-defined conversion "operator RValue()"
-//   * a "move constructor" and "move operator=" that take the RValue& as
-//     their sole parameter.
-//
-// Only r-values will trigger this sequence and execute our "move constructor"
-// or "move operator=."  L-values will match the private copy constructor and
-// operator= first giving a "private in this context" error.  This combination
-// gives us a move-only type.
-//
-// For signaling a destructive transfer of data from an l-value, we provide a
-// method named Pass() which creates an r-value for the current instance
-// triggering the move constructor or move operator=.
-//
-// Other ways to get r-values is to use the result of an expression like a
-// function call.
-//
-// Here's an example with comments explaining what gets triggered where:
-//
-//    class Foo {
-//      MOVE_ONLY_TYPE_FOR_CPP_03(Foo, RValue);
-//
-//     public:
-//       ... API ...
-//       Foo(RValue other);           // Move constructor.
-//       Foo& operator=(RValue rhs);  // Move operator=
-//    };
-//
-//    Foo MakeFoo();  // Function that returns a Foo.
-//
-//    Foo f;
-//    Foo f_copy(f);  // ERROR: Foo(Foo&) is private in this context.
-//    Foo f_assign;
-//    f_assign = f;   // ERROR: operator=(Foo&) is private in this context.
-//
-//
-//    Foo f(MakeFoo());      // R-value so alternate conversion executed.
-//    Foo f_copy(f.Pass());  // R-value so alternate conversion executed.
-//    f = f_copy.Pass();     // R-value so alternate conversion executed.
-//
-//
-// IMPLEMENTATION SUBTLETIES WITH RValue
-//
-// The RValue struct is just a container for a pointer back to the original
-// object. It should only ever be created as a temporary, and no external
-// class should ever declare it or use it in a parameter.
-//
-// It is tempting to want to use the RValue type in function parameters, but
-// excluding the limited usage here for the move constructor and move
-// operator=, doing so would mean that the function could take both r-values
-// and l-values equially which is unexpected.  See COMPARED To Boost.Move for
-// more details.
-//
-// An alternate, and incorrect, implementation of the RValue class used by
-// Boost.Move makes RValue a fieldless child of the move-only type. RValue&
-// is then used in place of RValue in the various operators.  The RValue& is
-// "created" by doing *reinterpret_cast<RValue*>(this).  This has the appeal
-// of never creating a temporary RValue struct even with optimizations
-// disabled.  Also, by virtue of inheritance you can treat the RValue
-// reference as if it were the move-only type itself.  Unfortunately,
-// using the result of this reinterpret_cast<> is actually undefined behavior
-// due to C++98 5.2.10.7. In certain compilers (e.g., NaCl) the optimizer
-// will generate non-working code.
-//
-// In optimized builds, both implementations generate the same assembly so we
-// choose the one that adheres to the standard.
-//
-//
-// WHY HAVE typedef void MoveOnlyTypeForCPP03
-//
-// Callback<>/Bind() needs to understand movable-but-not-copyable semantics
-// to call .Pass() appropriately when it is expected to transfer the value.
-// The cryptic typedef MoveOnlyTypeForCPP03 is added to make this check
-// easy and automatic in helper templates for Callback<>/Bind().
-// See IsMoveOnlyType template and its usage in base/callback_internal.h
-// for more details.
-//
-//
-// COMPARED TO C++11
-//
-// In C++11, you would implement this functionality using an r-value reference
-// and our .Pass() method would be replaced with a call to std::move().
-//
-// This emulation also has a deficiency where it uses up the single
-// user-defined conversion allowed by C++ during initialization.  This can
-// cause problems in some API edge cases.  For instance, in scoped_ptr, it is
-// impossible to make a function "void Foo(scoped_ptr<Parent> p)" accept a
-// value of type scoped_ptr<Child> even if you add a constructor to
-// scoped_ptr<> that would make it look like it should work.  C++11 does not
-// have this deficiency.
-//
-//
-// COMPARED TO Boost.Move
-//
-// Our implementation similar to Boost.Move, but we keep the RValue struct
-// private to the move-only type, and we don't use the reinterpret_cast<> hack.
-//
-// In Boost.Move, RValue is the boost::rv<> template.  This type can be used
-// when writing APIs like:
-//
-//   void MyFunc(boost::rv<Foo>& f)
-//
-// that can take advantage of rv<> to avoid extra copies of a type.  However you
-// would still be able to call this version of MyFunc with an l-value:
-//
-//   Foo f;
-//   MyFunc(f);  // Uh oh, we probably just destroyed |f| w/o calling Pass().
-//
-// unless someone is very careful to also declare a parallel override like:
-//
-//   void MyFunc(const Foo& f)
-//
-// that would catch the l-values first.  This was declared unsafe in C++11 and
-// a C++11 compiler will explicitly fail MyFunc(f).  Unfortunately, we cannot
-// ensure this in C++03.
-//
-// Since we have no need for writing such APIs yet, our implementation keeps
-// RValue private and uses a .Pass() method to do the conversion instead of
-// trying to write a version of "std::move()." Writing an API like std::move()
-// would require the RValue struct to be public.
-//
-//
-// CAVEATS
-//
-// If you include a move-only type as a field inside a class that does not
-// explicitly declare a copy constructor, the containing class's implicit
-// copy constructor will change from Containing(const Containing&) to
-// Containing(Containing&).  This can cause some unexpected errors.
-//
-//   http://llvm.org/bugs/show_bug.cgi?id=11528
-//
-// The workaround is to explicitly declare your copy constructor.
-//
-#define MOVE_ONLY_TYPE_FOR_CPP_03(type, rvalue_type)       \
- private:                                                  \
-  struct rvalue_type {                                     \
-    explicit rvalue_type(type* object) : object(object) {} \
-    type* object;                                          \
-  };                                                       \
-  type(type&);                                             \
-  void operator=(type&);                                   \
-                                                           \
- public:                                                   \
-  operator rvalue_type() { return rvalue_type(this); }     \
-  type Pass() { return type(rvalue_type(this)); }          \
-  typedef void MoveOnlyTypeForCPP03;                       \
-                                                           \
- private:
-
-#endif  // !USING_CHROMIUM_INCLUDES
-
-#endif  // CEF_INCLUDE_BASE_CEF_MOVE_H_
diff --git a/src/include/base/cef_platform_thread.h b/src/include/base/cef_platform_thread.h
index d3fdd79..8e6dd05 100644
--- a/src/include/base/cef_platform_thread.h
+++ b/src/include/base/cef_platform_thread.h
@@ -35,12 +35,7 @@
 #ifndef CEF_INCLUDE_BASE_PLATFORM_THREAD_H_
 #define CEF_INCLUDE_BASE_PLATFORM_THREAD_H_
 
-#if defined(BASE_THREADING_PLATFORM_THREAD_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
+#if defined(USING_CHROMIUM_INCLUDES)
 // When building CEF include the Chromium header directly.
 #include "base/threading/platform_thread.h"
 #else  // !USING_CHROMIUM_INCLUDES
@@ -48,23 +43,26 @@
 // If the Chromium implementation diverges the below implementation should be
 // updated to match.
 
-#include "include/base/cef_basictypes.h"
 #include "include/base/cef_build.h"
 #include "include/internal/cef_thread_internal.h"
 
 namespace base {
 
-// Used for logging. Always an integer value.
+///
+/// Used for logging. Always an integer value.
+///
 typedef cef_platform_thread_id_t PlatformThreadId;
 
-// Used for thread checking and debugging.
-// Meant to be as fast as possible.
-// These are produced by PlatformThread::CurrentRef(), and used to later
-// check if we are on the same thread or not by using ==. These are safe
-// to copy between threads, but can't be copied to another process as they
-// have no meaning there. Also, the internal identifier can be re-used
-// after a thread dies, so a PlatformThreadRef cannot be reliably used
-// to distinguish a new thread from an old, dead thread.
+///
+/// Used for thread checking and debugging.
+/// Meant to be as fast as possible.
+/// These are produced by PlatformThread::CurrentRef(), and used to later
+/// check if we are on the same thread or not by using ==. These are safe
+/// to copy between threads, but can't be copied to another process as they
+/// have no meaning there. Also, the internal identifier can be re-used
+/// after a thread dies, so a PlatformThreadRef cannot be reliably used
+/// to distinguish a new thread from an old, dead thread.
+///
 class PlatformThreadRef {
  public:
   typedef cef_platform_thread_handle_t RefType;
@@ -81,18 +79,24 @@
   RefType id_;
 };
 
-// A namespace for low-level thread functions.
-// Chromium uses a class with static methods but CEF uses an actual namespace
-// to avoid linker problems with the sandbox libaries on Windows.
+///
+/// A namespace for low-level thread functions.
+/// Chromium uses a class with static methods but CEF uses an actual namespace
+/// to avoid linker problems with the sandbox libaries on Windows.
+///
 namespace PlatformThread {
 
-// Gets the current thread id, which may be useful for logging purposes.
+///
+/// Gets the current thread id, which may be useful for logging purposes.
+///
 inline PlatformThreadId CurrentId() {
   return cef_get_current_platform_thread_id();
 }
 
-// Gets the current thread reference, which can be used to check if
-// we're on the right thread quickly.
+///
+/// Gets the current thread reference, which can be used to check if
+/// we're on the right thread quickly.
+///
 inline PlatformThreadRef CurrentRef() {
   return PlatformThreadRef(cef_get_current_platform_thread_handle());
 }
diff --git a/src/include/cef_request_callback.h b/src/include/base/cef_ptr_util.h
similarity index 61%
copy from src/include/cef_request_callback.h
copy to src/include/base/cef_ptr_util.h
index 68094de..082b87a 100644
--- a/src/include/cef_request_callback.h
+++ b/src/include/base/cef_ptr_util.h
@@ -1,4 +1,5 @@
-// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2021 Marshall A. Greenblatt. Portions copyright (c) 2015
+// Google Inc. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -26,38 +27,34 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// ---------------------------------------------------------------------------
-//
-// The contents of this file must follow a specific format in order to
-// support the CEF translator tool. See the translator.README.txt file in the
-// tools directory for more information.
-//
 
-#ifndef CEF_INCLUDE_CEF_REQUEST_CALLBACK_H_
-#define CEF_INCLUDE_CEF_REQUEST_CALLBACK_H_
+#ifndef INCLUDE_BASE_CEF_PTR_UTIL_H_
+#define INCLUDE_BASE_CEF_PTR_UTIL_H_
 #pragma once
 
-#include "include/cef_base.h"
+#if defined(USING_CHROMIUM_INCLUDES)
+// When building CEF include the Chromium header directly.
+#include "base/memory/ptr_util.h"
+#else  // !USING_CHROMIUM_INCLUDES
+// The following is substantially similar to the Chromium implementation.
+// If the Chromium implementation diverges the below implementation should be
+// updated to match.
+
+#include <memory>
+#include <utility>
+
+namespace base {
 
 ///
-// Callback interface used for asynchronous continuation of url requests.
+/// Helper to transfer ownership of a raw pointer to a std::unique_ptr<T>.
+/// Note that std::unique_ptr<T> has very different semantics from
+/// std::unique_ptr<T[]>: do not use this helper for array allocations.
 ///
-/*--cef(source=library)--*/
-class CefRequestCallback : public virtual CefBaseRefCounted {
- public:
-  ///
-  // Continue the url request. If |allow| is true the request will be continued.
-  // Otherwise, the request will be canceled.
-  ///
-  /*--cef(capi_name=cont)--*/
-  virtual void Continue(bool allow) = 0;
+template <typename T>
+std::unique_ptr<T> WrapUnique(T* ptr) {
+  return std::unique_ptr<T>(ptr);
+}
 
-  ///
-  // Cancel the url request.
-  ///
-  /*--cef()--*/
-  virtual void Cancel() = 0;
-};
+}  // namespace base
 
-#endif  // CEF_INCLUDE_CEF_REQUEST_CALLBACK_H_
+#endif  // INCLUDE_BASE_CEF_PTR_UTIL_H_
diff --git a/src/include/base/cef_ref_counted.h b/src/include/base/cef_ref_counted.h
index 7a68707..58c40d8 100644
--- a/src/include/base/cef_ref_counted.h
+++ b/src/include/base/cef_ref_counted.h
@@ -33,12 +33,7 @@
 #define CEF_INCLUDE_BASE_CEF_REF_COUNTED_H_
 #pragma once
 
-#if defined(BASE_MEMORY_REF_COUNTED_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
+#if defined(USING_CHROMIUM_INCLUDES)
 // When building CEF include the Chromium header directly.
 #include "base/memory/ref_counted.h"
 #else  // !USING_CHROMIUM_INCLUDES
@@ -46,15 +41,18 @@
 // If the Chromium implementation diverges the below implementation should be
 // updated to match.
 
-#include <cassert>
+#include <stddef.h>
+
+#include <utility>
 
 #include "include/base/cef_atomic_ref_count.h"
 #include "include/base/cef_build.h"
+#include "include/base/cef_compiler_specific.h"
 #include "include/base/cef_logging.h"
-#include "include/base/cef_macros.h"
+#include "include/base/cef_scoped_refptr.h"
+#include "include/base/cef_thread_checker.h"
 
 namespace base {
-
 namespace cef_subtle {
 
 class RefCountedBase {
@@ -63,15 +61,22 @@
   bool HasAtLeastOneRef() const { return ref_count_ >= 1; }
 
  protected:
-  RefCountedBase()
-      : ref_count_(0)
+  explicit RefCountedBase(StartRefCountFromZeroTag) {
 #if DCHECK_IS_ON()
-        ,
-        in_dtor_(false)
+    thread_checker_.DetachFromThread();
 #endif
-  {
   }
 
+  explicit RefCountedBase(StartRefCountFromOneTag) : ref_count_(1) {
+#if DCHECK_IS_ON()
+    needs_adopt_ref_ = true;
+    thread_checker_.DetachFromThread();
+#endif
+  }
+
+  RefCountedBase(const RefCountedBase&) = delete;
+  RefCountedBase& operator=(const RefCountedBase&) = delete;
+
   ~RefCountedBase() {
 #if DCHECK_IS_ON()
     DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
@@ -81,31 +86,92 @@
   void AddRef() const {
 #if DCHECK_IS_ON()
     DCHECK(!in_dtor_);
+    DCHECK(!needs_adopt_ref_)
+        << "This RefCounted object is created with non-zero reference count."
+        << " The first reference to such a object has to be made by AdoptRef or"
+        << " MakeRefCounted.";
+    if (ref_count_ >= 1) {
+      DCHECK(CalledOnValidThread());
+    }
 #endif
-    ++ref_count_;
+
+    AddRefImpl();
   }
 
   // Returns true if the object should self-delete.
   bool Release() const {
+    ReleaseImpl();
+
 #if DCHECK_IS_ON()
     DCHECK(!in_dtor_);
-#endif
-    if (--ref_count_ == 0) {
-#if DCHECK_IS_ON()
+    if (ref_count_ == 0) {
       in_dtor_ = true;
-#endif
-      return true;
     }
-    return false;
+
+    if (ref_count_ >= 1) {
+      DCHECK(CalledOnValidThread());
+    }
+    if (ref_count_ == 1) {
+      thread_checker_.DetachFromThread();
+    }
+#endif
+
+    return ref_count_ == 0;
+  }
+
+  // Returns true if it is safe to read or write the object, from a thread
+  // safety standpoint. Should be DCHECK'd from the methods of RefCounted
+  // classes if there is a danger of objects being shared across threads.
+  //
+  // This produces fewer false positives than adding a separate ThreadChecker
+  // into the subclass, because it automatically detaches from the thread when
+  // the reference count is 1 (and never fails if there is only one reference).
+  //
+  // This means unlike a separate ThreadChecker, it will permit a singly
+  // referenced object to be passed between threads (not holding a reference on
+  // the sending thread), but will trap if the sending thread holds onto a
+  // reference, or if the object is accessed from multiple threads
+  // simultaneously.
+  bool IsOnValidThread() const {
+#if DCHECK_IS_ON()
+    return ref_count_ <= 1 || CalledOnValidThread();
+#else
+    return true;
+#endif
   }
 
  private:
-  mutable int ref_count_;
+  template <typename U>
+  friend scoped_refptr<U> base::AdoptRef(U*);
+
+  void Adopted() const {
 #if DCHECK_IS_ON()
-  mutable bool in_dtor_;
+    DCHECK(needs_adopt_ref_);
+    needs_adopt_ref_ = false;
+#endif
+  }
+
+#if defined(ARCH_CPU_64_BITS)
+  void AddRefImpl() const;
+  void ReleaseImpl() const;
+#else
+  void AddRefImpl() const { ++ref_count_; }
+  void ReleaseImpl() const { --ref_count_; }
 #endif
 
-  DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
+#if DCHECK_IS_ON()
+  bool CalledOnValidThread() const;
+#endif
+
+  mutable uint32_t ref_count_ = 0;
+  static_assert(std::is_unsigned<decltype(ref_count_)>::value,
+                "ref_count_ must be an unsigned type.");
+
+#if DCHECK_IS_ON()
+  mutable bool needs_adopt_ref_ = false;
+  mutable bool in_dtor_ = false;
+  mutable ThreadChecker thread_checker_;
+#endif
 };
 
 class RefCountedThreadSafeBase {
@@ -114,65 +180,227 @@
   bool HasAtLeastOneRef() const;
 
  protected:
-  RefCountedThreadSafeBase();
-  ~RefCountedThreadSafeBase();
-
-  void AddRef() const;
-
-  // Returns true if the object should self-delete.
-  bool Release() const;
-
- private:
-  mutable AtomicRefCount ref_count_;
+  explicit constexpr RefCountedThreadSafeBase(StartRefCountFromZeroTag) {}
+  explicit constexpr RefCountedThreadSafeBase(StartRefCountFromOneTag)
+      : ref_count_(1) {
 #if DCHECK_IS_ON()
-  mutable bool in_dtor_;
+    needs_adopt_ref_ = true;
+#endif
+  }
+
+  RefCountedThreadSafeBase(const RefCountedThreadSafeBase&) = delete;
+  RefCountedThreadSafeBase& operator=(const RefCountedThreadSafeBase&) = delete;
+
+#if DCHECK_IS_ON()
+  ~RefCountedThreadSafeBase();
+#else
+  ~RefCountedThreadSafeBase() = default;
 #endif
 
-  DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase);
+// Release and AddRef are suitable for inlining on X86 because they generate
+// very small code threads. On other platforms (ARM), it causes a size
+// regression and is probably not worth it.
+#if defined(ARCH_CPU_X86_FAMILY)
+  // Returns true if the object should self-delete.
+  bool Release() const { return ReleaseImpl(); }
+  void AddRef() const { AddRefImpl(); }
+  void AddRefWithCheck() const { AddRefWithCheckImpl(); }
+#else
+  // Returns true if the object should self-delete.
+  bool Release() const;
+  void AddRef() const;
+  void AddRefWithCheck() const;
+#endif
+
+ private:
+  template <typename U>
+  friend scoped_refptr<U> base::AdoptRef(U*);
+
+  void Adopted() const {
+#if DCHECK_IS_ON()
+    DCHECK(needs_adopt_ref_);
+    needs_adopt_ref_ = false;
+#endif
+  }
+
+  ALWAYS_INLINE void AddRefImpl() const {
+#if DCHECK_IS_ON()
+    DCHECK(!in_dtor_);
+    DCHECK(!needs_adopt_ref_)
+        << "This RefCounted object is created with non-zero reference count."
+        << " The first reference to such a object has to be made by AdoptRef or"
+        << " MakeRefCounted.";
+#endif
+    ref_count_.Increment();
+  }
+
+  ALWAYS_INLINE void AddRefWithCheckImpl() const {
+#if DCHECK_IS_ON()
+    DCHECK(!in_dtor_);
+    DCHECK(!needs_adopt_ref_)
+        << "This RefCounted object is created with non-zero reference count."
+        << " The first reference to such a object has to be made by AdoptRef or"
+        << " MakeRefCounted.";
+#endif
+    CHECK(ref_count_.Increment() > 0);
+  }
+
+  ALWAYS_INLINE bool ReleaseImpl() const {
+#if DCHECK_IS_ON()
+    DCHECK(!in_dtor_);
+    DCHECK(!ref_count_.IsZero());
+#endif
+    if (!ref_count_.Decrement()) {
+#if DCHECK_IS_ON()
+      in_dtor_ = true;
+#endif
+      return true;
+    }
+    return false;
+  }
+
+  mutable AtomicRefCount ref_count_{0};
+#if DCHECK_IS_ON()
+  mutable bool needs_adopt_ref_ = false;
+  mutable bool in_dtor_ = false;
+#endif
+};
+
+// ScopedAllowCrossThreadRefCountAccess disables the check documented on
+// RefCounted below for rare pre-existing use cases where thread-safety was
+// guaranteed through other means (e.g. explicit sequencing of calls across
+// execution threads when bouncing between threads in order). New callers
+// should refrain from using this (callsites handling thread-safety through
+// locks should use RefCountedThreadSafe per the overhead of its atomics being
+// negligible compared to locks anyways and callsites doing explicit sequencing
+// should properly std::move() the ref to avoid hitting this check).
+// TODO(tzik): Cleanup existing use cases and remove
+// ScopedAllowCrossThreadRefCountAccess.
+class ScopedAllowCrossThreadRefCountAccess final {
+ public:
+#if DCHECK_IS_ON()
+  ScopedAllowCrossThreadRefCountAccess();
+  ~ScopedAllowCrossThreadRefCountAccess();
+#else
+  ScopedAllowCrossThreadRefCountAccess() {}
+  ~ScopedAllowCrossThreadRefCountAccess() {}
+#endif
 };
 
 }  // namespace cef_subtle
 
-//
-// A base class for reference counted classes.  Otherwise, known as a cheap
-// knock-off of WebKit's RefCounted<T> class.  To use this guy just extend your
-// class from it like so:
-//
-//   class MyFoo : public base::RefCounted<MyFoo> {
-//    ...
-//    private:
-//     friend class base::RefCounted<MyFoo>;
-//     ~MyFoo();
-//   };
-//
-// You should always make your destructor private, to avoid any code deleting
-// the object accidently while there are references to it.
-template <class T>
+using ScopedAllowCrossThreadRefCountAccess =
+    cef_subtle::ScopedAllowCrossThreadRefCountAccess;
+
+///
+/// The reference count starts from zero by default, and we intended to migrate
+/// to start-from-one ref count. Put REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() to
+/// the ref counted class to opt-in.
+///
+/// If an object has start-from-one ref count, the first scoped_refptr need to
+/// be created by base::AdoptRef() or base::MakeRefCounted(). We can use
+/// base::MakeRefCounted() to create create both type of ref counted object.
+///
+/// The motivations to use start-from-one ref count are:
+///  - Start-from-one ref count doesn't need the ref count increment for the
+///    first reference.
+///  - It can detect an invalid object acquisition for a being-deleted object
+///    that has zero ref count. That tends to happen on custom deleter that
+///    delays the deletion.
+///    TODO(tzik): Implement invalid acquisition detection.
+///  - Behavior parity to Blink's WTF::RefCounted, whose count starts from one.
+///    And start-from-one ref count is a step to merge WTF::RefCounted into
+///    base::RefCounted.
+///
+#define REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE()                 \
+  static constexpr ::base::cef_subtle::StartRefCountFromOneTag \
+      kRefCountPreference = ::base::cef_subtle::kStartRefCountFromOneTag
+
+template <class T, typename Traits>
+class RefCounted;
+
+///
+/// Default traits for RefCounted<T>.  Deletes the object when its ref count
+/// reaches 0. Overload to delete it on a different thread etc.
+///
+template <typename T>
+struct DefaultRefCountedTraits {
+  static void Destruct(const T* x) {
+    RefCounted<T, DefaultRefCountedTraits>::DeleteInternal(x);
+  }
+};
+
+///
+/// A base class for reference counted classes. Otherwise, known as a cheap
+/// knock-off of WebKit's RefCounted<T> class. To use this, just extend your
+/// class from it like so:
+///
+/// <pre>
+///   class MyFoo : public base::RefCounted<MyFoo> {
+///    ...
+///    private:
+///     friend class base::RefCounted<MyFoo>;
+///     ~MyFoo();
+///   };
+/// </pre>
+///
+/// Usage Notes:
+/// 1. You should always make your destructor non-public, to avoid any code
+///    deleting the object accidentally while there are references to it.
+/// 2. You should always make the ref-counted base class a friend of your class,
+///    so that it can access the destructor.
+///
+/// The ref count manipulation to RefCounted is NOT thread safe and has DCHECKs
+/// to trap unsafe cross thread usage. A subclass instance of RefCounted can be
+/// passed to another execution thread only when its ref count is 1. If the ref
+/// count is more than 1, the RefCounted class verifies the ref updates are made
+/// on the same execution thread as the previous ones. The subclass can also
+/// manually call IsOnValidThread to trap other non-thread-safe accesses; see
+/// the documentation for that method.
+///
+template <class T, typename Traits = DefaultRefCountedTraits<T>>
 class RefCounted : public cef_subtle::RefCountedBase {
  public:
-  RefCounted() {}
+  static constexpr cef_subtle::StartRefCountFromZeroTag kRefCountPreference =
+      cef_subtle::kStartRefCountFromZeroTag;
+
+  RefCounted() : cef_subtle::RefCountedBase(T::kRefCountPreference) {}
+
+  RefCounted(const RefCounted&) = delete;
+  RefCounted& operator=(const RefCounted&) = delete;
 
   void AddRef() const { cef_subtle::RefCountedBase::AddRef(); }
 
   void Release() const {
     if (cef_subtle::RefCountedBase::Release()) {
-      delete static_cast<const T*>(this);
+      // Prune the code paths which the static analyzer may take to simulate
+      // object destruction. Use-after-free errors aren't possible given the
+      // lifetime guarantees of the refcounting system.
+      ANALYZER_SKIP_THIS_PATH();
+
+      Traits::Destruct(static_cast<const T*>(this));
     }
   }
 
  protected:
-  ~RefCounted() {}
+  ~RefCounted() = default;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
+  friend struct DefaultRefCountedTraits<T>;
+  template <typename U>
+  static void DeleteInternal(const U* x) {
+    delete x;
+  }
 };
 
 // Forward declaration.
 template <class T, typename Traits>
 class RefCountedThreadSafe;
 
-// Default traits for RefCountedThreadSafe<T>.  Deletes the object when its ref
-// count reaches 0.  Overload to delete it on a different thread etc.
+///
+/// Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref
+/// count reaches 0. Overload to delete it on a different thread etc.
+///
 template <typename T>
 struct DefaultRefCountedThreadSafeTraits {
   static void Destruct(const T* x) {
@@ -184,187 +412,100 @@
   }
 };
 
-//
-// A thread-safe variant of RefCounted<T>
-//
-//   class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
-//    ...
-//   };
-//
-// If you're using the default trait, then you should add compile time
-// asserts that no one else is deleting your object.  i.e.
-//    private:
-//     friend class base::RefCountedThreadSafe<MyFoo>;
-//     ~MyFoo();
+///
+/// A thread-safe variant of RefCounted<T>
+///
+/// <pre>
+///   class MyFoo : public base::RefCountedThreadSafe<MyFoo> {
+///    ...
+///   };
+/// </pre>
+///
+/// If you're using the default trait, then you should add compile time
+/// asserts that no one else is deleting your object.  i.e.
+/// <pre>
+///    private:
+///     friend class base::RefCountedThreadSafe<MyFoo>;
+///     ~MyFoo();
+/// </pre>
+///
+/// We can use REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() with RefCountedThreadSafe
+/// too. See the comment above the RefCounted definition for details.
+///
 template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T>>
 class RefCountedThreadSafe : public cef_subtle::RefCountedThreadSafeBase {
  public:
-  RefCountedThreadSafe() {}
+  static constexpr cef_subtle::StartRefCountFromZeroTag kRefCountPreference =
+      cef_subtle::kStartRefCountFromZeroTag;
 
-  void AddRef() const { cef_subtle::RefCountedThreadSafeBase::AddRef(); }
+  explicit RefCountedThreadSafe()
+      : cef_subtle::RefCountedThreadSafeBase(T::kRefCountPreference) {}
+
+  RefCountedThreadSafe(const RefCountedThreadSafe&) = delete;
+  RefCountedThreadSafe& operator=(const RefCountedThreadSafe&) = delete;
+
+  void AddRef() const { AddRefImpl(T::kRefCountPreference); }
 
   void Release() const {
     if (cef_subtle::RefCountedThreadSafeBase::Release()) {
+      ANALYZER_SKIP_THIS_PATH();
       Traits::Destruct(static_cast<const T*>(this));
     }
   }
 
  protected:
-  ~RefCountedThreadSafe() {}
+  ~RefCountedThreadSafe() = default;
 
  private:
   friend struct DefaultRefCountedThreadSafeTraits<T>;
-  static void DeleteInternal(const T* x) { delete x; }
+  template <typename U>
+  static void DeleteInternal(const U* x) {
+    delete x;
+  }
 
-  DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe);
+  void AddRefImpl(cef_subtle::StartRefCountFromZeroTag) const {
+    cef_subtle::RefCountedThreadSafeBase::AddRef();
+  }
+
+  void AddRefImpl(cef_subtle::StartRefCountFromOneTag) const {
+    cef_subtle::RefCountedThreadSafeBase::AddRefWithCheck();
+  }
 };
 
-//
-// A thread-safe wrapper for some piece of data so we can place other
-// things in scoped_refptrs<>.
-//
+///
+/// A thread-safe wrapper for some piece of data so we can place other
+/// things in scoped_refptrs<>.
+///
 template <typename T>
 class RefCountedData
     : public base::RefCountedThreadSafe<base::RefCountedData<T>> {
  public:
   RefCountedData() : data() {}
   RefCountedData(const T& in_value) : data(in_value) {}
+  RefCountedData(T&& in_value) : data(std::move(in_value)) {}
+  template <typename... Args>
+  explicit RefCountedData(std::in_place_t, Args&&... args)
+      : data(std::forward<Args>(args)...) {}
 
   T data;
 
  private:
   friend class base::RefCountedThreadSafe<base::RefCountedData<T>>;
-  ~RefCountedData() {}
+  ~RefCountedData() = default;
 };
 
+template <typename T>
+bool operator==(const RefCountedData<T>& lhs, const RefCountedData<T>& rhs) {
+  return lhs.data == rhs.data;
+}
+
+template <typename T>
+bool operator!=(const RefCountedData<T>& lhs, const RefCountedData<T>& rhs) {
+  return !(lhs == rhs);
+}
+
 }  // namespace base
 
-//
-// A smart pointer class for reference counted objects.  Use this class instead
-// of calling AddRef and Release manually on a reference counted object to
-// avoid common memory leaks caused by forgetting to Release an object
-// reference.  Sample usage:
-//
-//   class MyFoo : public RefCounted<MyFoo> {
-//    ...
-//   };
-//
-//   void some_function() {
-//     scoped_refptr<MyFoo> foo = new MyFoo();
-//     foo->Method(param);
-//     // |foo| is released when this function returns
-//   }
-//
-//   void some_other_function() {
-//     scoped_refptr<MyFoo> foo = new MyFoo();
-//     ...
-//     foo = NULL;  // explicitly releases |foo|
-//     ...
-//     if (foo)
-//       foo->Method(param);
-//   }
-//
-// The above examples show how scoped_refptr<T> acts like a pointer to T.
-// Given two scoped_refptr<T> classes, it is also possible to exchange
-// references between the two objects, like so:
-//
-//   {
-//     scoped_refptr<MyFoo> a = new MyFoo();
-//     scoped_refptr<MyFoo> b;
-//
-//     b.swap(a);
-//     // now, |b| references the MyFoo object, and |a| references NULL.
-//   }
-//
-// To make both |a| and |b| in the above example reference the same MyFoo
-// object, simply use the assignment operator:
-//
-//   {
-//     scoped_refptr<MyFoo> a = new MyFoo();
-//     scoped_refptr<MyFoo> b;
-//
-//     b = a;
-//     // now, |a| and |b| each own a reference to the same MyFoo object.
-//   }
-//
-template <class T>
-class scoped_refptr {
- public:
-  typedef T element_type;
-
-  scoped_refptr() : ptr_(NULL) {}
-
-  scoped_refptr(T* p) : ptr_(p) {
-    if (ptr_)
-      ptr_->AddRef();
-  }
-
-  scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
-    if (ptr_)
-      ptr_->AddRef();
-  }
-
-  template <typename U>
-  scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
-    if (ptr_)
-      ptr_->AddRef();
-  }
-
-  ~scoped_refptr() {
-    if (ptr_)
-      ptr_->Release();
-  }
-
-  T* get() const { return ptr_; }
-
-  // Allow scoped_refptr<C> to be used in boolean expression
-  // and comparison operations.
-  operator T*() const { return ptr_; }
-
-  T* operator->() const {
-    assert(ptr_ != NULL);
-    return ptr_;
-  }
-
-  scoped_refptr<T>& operator=(T* p) {
-    // AddRef first so that self assignment should work
-    if (p)
-      p->AddRef();
-    T* old_ptr = ptr_;
-    ptr_ = p;
-    if (old_ptr)
-      old_ptr->Release();
-    return *this;
-  }
-
-  scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
-    return *this = r.ptr_;
-  }
-
-  template <typename U>
-  scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
-    return *this = r.get();
-  }
-
-  void swap(T** pp) {
-    T* p = ptr_;
-    ptr_ = *pp;
-    *pp = p;
-  }
-
-  void swap(scoped_refptr<T>& r) { swap(&r.ptr_); }
-
- protected:
-  T* ptr_;
-};
-
-// Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
-// having to retype all the template arguments
-template <typename T>
-scoped_refptr<T> make_scoped_refptr(T* t) {
-  return scoped_refptr<T>(t);
-}
-
 #endif  // !USING_CHROMIUM_INCLUDES
 
 #endif  // CEF_INCLUDE_BASE_CEF_REF_COUNTED_H_
diff --git a/src/include/base/cef_scoped_ptr.h b/src/include/base/cef_scoped_ptr.h
deleted file mode 100644
index eb9e0e2..0000000
--- a/src/include/base/cef_scoped_ptr.h
+++ /dev/null
@@ -1,625 +0,0 @@
-// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
-// Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Scopers help you manage ownership of a pointer, helping you easily manage a
-// pointer within a scope, and automatically destroying the pointer at the end
-// of a scope.  There are two main classes you will use, which correspond to the
-// operators new/delete and new[]/delete[].
-//
-// Example usage (scoped_ptr<T>):
-//   {
-//     scoped_ptr<Foo> foo(new Foo("wee"));
-//   }  // foo goes out of scope, releasing the pointer with it.
-//
-//   {
-//     scoped_ptr<Foo> foo;          // No pointer managed.
-//     foo.reset(new Foo("wee"));    // Now a pointer is managed.
-//     foo.reset(new Foo("wee2"));   // Foo("wee") was destroyed.
-//     foo.reset(new Foo("wee3"));   // Foo("wee2") was destroyed.
-//     foo->Method();                // Foo::Method() called.
-//     foo.get()->Method();          // Foo::Method() called.
-//     SomeFunc(foo.release());      // SomeFunc takes ownership, foo no longer
-//                                   // manages a pointer.
-//     foo.reset(new Foo("wee4"));   // foo manages a pointer again.
-//     foo.reset();                  // Foo("wee4") destroyed, foo no longer
-//                                   // manages a pointer.
-//   }  // foo wasn't managing a pointer, so nothing was destroyed.
-//
-// Example usage (scoped_ptr<T[]>):
-//   {
-//     scoped_ptr<Foo[]> foo(new Foo[100]);
-//     foo.get()->Method();  // Foo::Method on the 0th element.
-//     foo[10].Method();     // Foo::Method on the 10th element.
-//   }
-//
-// These scopers also implement part of the functionality of C++11 unique_ptr
-// in that they are "movable but not copyable."  You can use the scopers in
-// the parameter and return types of functions to signify ownership transfer
-// in to and out of a function.  When calling a function that has a scoper
-// as the argument type, it must be called with the result of an analogous
-// scoper's Pass() function or another function that generates a temporary;
-// passing by copy will NOT work.  Here is an example using scoped_ptr:
-//
-//   void TakesOwnership(scoped_ptr<Foo> arg) {
-//     // Do something with arg
-//   }
-//   scoped_ptr<Foo> CreateFoo() {
-//     // No need for calling Pass() because we are constructing a temporary
-//     // for the return value.
-//     return scoped_ptr<Foo>(new Foo("new"));
-//   }
-//   scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) {
-//     return arg.Pass();
-//   }
-//
-//   {
-//     scoped_ptr<Foo> ptr(new Foo("yay"));  // ptr manages Foo("yay").
-//     TakesOwnership(ptr.Pass());           // ptr no longer owns Foo("yay").
-//     scoped_ptr<Foo> ptr2 = CreateFoo();   // ptr2 owns the return Foo.
-//     scoped_ptr<Foo> ptr3 =                // ptr3 now owns what was in ptr2.
-//         PassThru(ptr2.Pass());            // ptr2 is correspondingly NULL.
-//   }
-//
-// Notice that if you do not call Pass() when returning from PassThru(), or
-// when invoking TakesOwnership(), the code will not compile because scopers
-// are not copyable; they only implement move semantics which require calling
-// the Pass() function to signify a destructive transfer of state. CreateFoo()
-// is different though because we are constructing a temporary on the return
-// line and thus can avoid needing to call Pass().
-//
-// Pass() properly handles upcast in initialization, i.e. you can use a
-// scoped_ptr<Child> to initialize a scoped_ptr<Parent>:
-//
-//   scoped_ptr<Foo> foo(new Foo());
-//   scoped_ptr<FooParent> parent(foo.Pass());
-//
-// PassAs<>() should be used to upcast return value in return statement:
-//
-//   scoped_ptr<Foo> CreateFoo() {
-//     scoped_ptr<FooChild> result(new FooChild());
-//     return result.PassAs<Foo>();
-//   }
-//
-// Note that PassAs<>() is implemented only for scoped_ptr<T>, but not for
-// scoped_ptr<T[]>. This is because casting array pointers may not be safe.
-
-#ifndef CEF_INCLUDE_BASE_CEF_MEMORY_SCOPED_PTR_H_
-#define CEF_INCLUDE_BASE_CEF_MEMORY_SCOPED_PTR_H_
-#pragma once
-
-#if defined(BASE_MEMORY_SCOPED_PTR_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
-// Do nothing when building CEF.
-#else  // !USING_CHROMIUM_INCLUDES
-// The following is substantially similar to the Chromium implementation.
-// If the Chromium implementation diverges the below implementation should be
-// updated to match.
-
-// This is an implementation designed to match the anticipated future TR2
-// implementation of the scoped_ptr class.
-
-#include <assert.h>
-#include <stddef.h>
-#include <stdlib.h>
-
-#include <algorithm>  // For std::swap().
-
-#include "include/base/cef_basictypes.h"
-#include "include/base/cef_build.h"
-#include "include/base/cef_macros.h"
-#include "include/base/cef_move.h"
-#include "include/base/cef_template_util.h"
-
-namespace base {
-
-namespace subtle {
-class RefCountedBase;
-class RefCountedThreadSafeBase;
-}  // namespace subtle
-
-// Function object which deletes its parameter, which must be a pointer.
-// If C is an array type, invokes 'delete[]' on the parameter; otherwise,
-// invokes 'delete'. The default deleter for scoped_ptr<T>.
-template <class T>
-struct DefaultDeleter {
-  DefaultDeleter() {}
-  template <typename U>
-  DefaultDeleter(const DefaultDeleter<U>& other) {
-    // IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor
-    // if U* is implicitly convertible to T* and U is not an array type.
-    //
-    // Correct implementation should use SFINAE to disable this
-    // constructor. However, since there are no other 1-argument constructors,
-    // using a COMPILE_ASSERT() based on is_convertible<> and requiring
-    // complete types is simpler and will cause compile failures for equivalent
-    // misuses.
-    //
-    // Note, the is_convertible<U*, T*> check also ensures that U is not an
-    // array. T is guaranteed to be a non-array, so any U* where U is an array
-    // cannot convert to T*.
-    enum { T_must_be_complete = sizeof(T) };
-    enum { U_must_be_complete = sizeof(U) };
-    COMPILE_ASSERT((base::is_convertible<U*, T*>::value),
-                   U_ptr_must_implicitly_convert_to_T_ptr);
-  }
-  inline void operator()(T* ptr) const {
-    enum { type_must_be_complete = sizeof(T) };
-    delete ptr;
-  }
-};
-
-// Specialization of DefaultDeleter for array types.
-template <class T>
-struct DefaultDeleter<T[]> {
-  inline void operator()(T* ptr) const {
-    enum { type_must_be_complete = sizeof(T) };
-    delete[] ptr;
-  }
-
- private:
-  // Disable this operator for any U != T because it is undefined to execute
-  // an array delete when the static type of the array mismatches the dynamic
-  // type.
-  //
-  // References:
-  //   C++98 [expr.delete]p3
-  //   http://cplusplus.github.com/LWG/lwg-defects.html#938
-  template <typename U>
-  void operator()(U* array) const;
-};
-
-template <class T, int n>
-struct DefaultDeleter<T[n]> {
-  // Never allow someone to declare something like scoped_ptr<int[10]>.
-  COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type);
-};
-
-// Function object which invokes 'free' on its parameter, which must be
-// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr:
-//
-// scoped_ptr<int, base::FreeDeleter> foo_ptr(
-//     static_cast<int*>(malloc(sizeof(int))));
-struct FreeDeleter {
-  inline void operator()(void* ptr) const { free(ptr); }
-};
-
-namespace cef_internal {
-
-template <typename T>
-struct IsNotRefCounted {
-  enum {
-    value =
-        !base::is_convertible<T*, base::subtle::RefCountedBase*>::value &&
-        !base::is_convertible<T*,
-                              base::subtle::RefCountedThreadSafeBase*>::value
-  };
-};
-
-// Minimal implementation of the core logic of scoped_ptr, suitable for
-// reuse in both scoped_ptr and its specializations.
-template <class T, class D>
-class scoped_ptr_impl {
- public:
-  explicit scoped_ptr_impl(T* p) : data_(p) {}
-
-  // Initializer for deleters that have data parameters.
-  scoped_ptr_impl(T* p, const D& d) : data_(p, d) {}
-
-  // Templated constructor that destructively takes the value from another
-  // scoped_ptr_impl.
-  template <typename U, typename V>
-  scoped_ptr_impl(scoped_ptr_impl<U, V>* other)
-      : data_(other->release(), other->get_deleter()) {
-    // We do not support move-only deleters.  We could modify our move
-    // emulation to have base::subtle::move() and base::subtle::forward()
-    // functions that are imperfect emulations of their C++11 equivalents,
-    // but until there's a requirement, just assume deleters are copyable.
-  }
-
-  template <typename U, typename V>
-  void TakeState(scoped_ptr_impl<U, V>* other) {
-    // See comment in templated constructor above regarding lack of support
-    // for move-only deleters.
-    reset(other->release());
-    get_deleter() = other->get_deleter();
-  }
-
-  ~scoped_ptr_impl() {
-    if (data_.ptr != NULL) {
-      // Not using get_deleter() saves one function call in non-optimized
-      // builds.
-      static_cast<D&>(data_)(data_.ptr);
-    }
-  }
-
-  void reset(T* p) {
-    // This is a self-reset, which is no longer allowed: http://crbug.com/162971
-    if (p != NULL && p == data_.ptr)
-      abort();
-
-    // Note that running data_.ptr = p can lead to undefined behavior if
-    // get_deleter()(get()) deletes this. In order to prevent this, reset()
-    // should update the stored pointer before deleting its old value.
-    //
-    // However, changing reset() to use that behavior may cause current code to
-    // break in unexpected ways. If the destruction of the owned object
-    // dereferences the scoped_ptr when it is destroyed by a call to reset(),
-    // then it will incorrectly dispatch calls to |p| rather than the original
-    // value of |data_.ptr|.
-    //
-    // During the transition period, set the stored pointer to NULL while
-    // deleting the object. Eventually, this safety check will be removed to
-    // prevent the scenario initially described from occuring and
-    // http://crbug.com/176091 can be closed.
-    T* old = data_.ptr;
-    data_.ptr = NULL;
-    if (old != NULL)
-      static_cast<D&>(data_)(old);
-    data_.ptr = p;
-  }
-
-  T* get() const { return data_.ptr; }
-
-  D& get_deleter() { return data_; }
-  const D& get_deleter() const { return data_; }
-
-  void swap(scoped_ptr_impl& p2) {
-    // Standard swap idiom: 'using std::swap' ensures that std::swap is
-    // present in the overload set, but we call swap unqualified so that
-    // any more-specific overloads can be used, if available.
-    using std::swap;
-    swap(static_cast<D&>(data_), static_cast<D&>(p2.data_));
-    swap(data_.ptr, p2.data_.ptr);
-  }
-
-  T* release() {
-    T* old_ptr = data_.ptr;
-    data_.ptr = NULL;
-    return old_ptr;
-  }
-
- private:
-  // Needed to allow type-converting constructor.
-  template <typename U, typename V>
-  friend class scoped_ptr_impl;
-
-  // Use the empty base class optimization to allow us to have a D
-  // member, while avoiding any space overhead for it when D is an
-  // empty class.  See e.g. http://www.cantrip.org/emptyopt.html for a good
-  // discussion of this technique.
-  struct Data : public D {
-    explicit Data(T* ptr_in) : ptr(ptr_in) {}
-    Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {}
-    T* ptr;
-  };
-
-  Data data_;
-
-  DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl);
-};
-
-}  // namespace cef_internal
-
-}  // namespace base
-
-// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
-// automatically deletes the pointer it holds (if any).
-// That is, scoped_ptr<T> owns the T object that it points to.
-// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
-// Also like T*, scoped_ptr<T> is thread-compatible, and once you
-// dereference it, you get the thread safety guarantees of T.
-//
-// The size of scoped_ptr is small. On most compilers, when using the
-// DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will
-// increase the size proportional to whatever state they need to have. See
-// comments inside scoped_ptr_impl<> for details.
-//
-// Current implementation targets having a strict subset of  C++11's
-// unique_ptr<> features. Known deficiencies include not supporting move-only
-// deleteres, function pointers as deleters, and deleters with reference
-// types.
-template <class T, class D = base::DefaultDeleter<T>>
-class scoped_ptr {
-  MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
-
-  COMPILE_ASSERT(base::cef_internal::IsNotRefCounted<T>::value,
-                 T_is_refcounted_type_and_needs_scoped_refptr);
-
- public:
-  // The element and deleter types.
-  typedef T element_type;
-  typedef D deleter_type;
-
-  // Constructor.  Defaults to initializing with NULL.
-  scoped_ptr() : impl_(NULL) {}
-
-  // Constructor.  Takes ownership of p.
-  explicit scoped_ptr(element_type* p) : impl_(p) {}
-
-  // Constructor.  Allows initialization of a stateful deleter.
-  scoped_ptr(element_type* p, const D& d) : impl_(p, d) {}
-
-  // Constructor.  Allows construction from a scoped_ptr rvalue for a
-  // convertible type and deleter.
-  //
-  // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct
-  // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor
-  // has different post-conditions if D is a reference type. Since this
-  // implementation does not support deleters with reference type,
-  // we do not need a separate move constructor allowing us to avoid one
-  // use of SFINAE. You only need to care about this if you modify the
-  // implementation of scoped_ptr.
-  template <typename U, typename V>
-  scoped_ptr(scoped_ptr<U, V> other) : impl_(&other.impl_) {
-    COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array);
-  }
-
-  // Constructor.  Move constructor for C++03 move emulation of this type.
-  scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) {}
-
-  // operator=.  Allows assignment from a scoped_ptr rvalue for a convertible
-  // type and deleter.
-  //
-  // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from
-  // the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated
-  // form has different requirements on for move-only Deleters. Since this
-  // implementation does not support move-only Deleters, we do not need a
-  // separate move assignment operator allowing us to avoid one use of SFINAE.
-  // You only need to care about this if you modify the implementation of
-  // scoped_ptr.
-  template <typename U, typename V>
-  scoped_ptr& operator=(scoped_ptr<U, V> rhs) {
-    COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array);
-    impl_.TakeState(&rhs.impl_);
-    return *this;
-  }
-
-  // Reset.  Deletes the currently owned object, if any.
-  // Then takes ownership of a new object, if given.
-  void reset(element_type* p = NULL) { impl_.reset(p); }
-
-  // Accessors to get the owned object.
-  // operator* and operator-> will assert() if there is no current object.
-  element_type& operator*() const {
-    assert(impl_.get() != NULL);
-    return *impl_.get();
-  }
-  element_type* operator->() const {
-    assert(impl_.get() != NULL);
-    return impl_.get();
-  }
-  element_type* get() const { return impl_.get(); }
-
-  // Access to the deleter.
-  deleter_type& get_deleter() { return impl_.get_deleter(); }
-  const deleter_type& get_deleter() const { return impl_.get_deleter(); }
-
-  // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
-  // implicitly convertible to a real bool (which is dangerous).
-  //
-  // Note that this trick is only safe when the == and != operators
-  // are declared explicitly, as otherwise "scoped_ptr1 ==
-  // scoped_ptr2" will compile but do the wrong thing (i.e., convert
-  // to Testable and then do the comparison).
- private:
-  typedef base::cef_internal::scoped_ptr_impl<element_type, deleter_type>
-      scoped_ptr::*Testable;
-
- public:
-  operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }
-
-  // Comparison operators.
-  // These return whether two scoped_ptr refer to the same object, not just to
-  // two different but equal objects.
-  bool operator==(const element_type* p) const { return impl_.get() == p; }
-  bool operator!=(const element_type* p) const { return impl_.get() != p; }
-
-  // Swap two scoped pointers.
-  void swap(scoped_ptr& p2) { impl_.swap(p2.impl_); }
-
-  // Release a pointer.
-  // The return value is the current pointer held by this object.
-  // If this object holds a NULL pointer, the return value is NULL.
-  // After this operation, this object will hold a NULL pointer,
-  // and will not own the object any more.
-  element_type* release() WARN_UNUSED_RESULT { return impl_.release(); }
-
-  // C++98 doesn't support functions templates with default parameters which
-  // makes it hard to write a PassAs() that understands converting the deleter
-  // while preserving simple calling semantics.
-  //
-  // Until there is a use case for PassAs() with custom deleters, just ignore
-  // the custom deleter.
-  template <typename PassAsType>
-  scoped_ptr<PassAsType> PassAs() {
-    return scoped_ptr<PassAsType>(Pass());
-  }
-
- private:
-  // Needed to reach into |impl_| in the constructor.
-  template <typename U, typename V>
-  friend class scoped_ptr;
-  base::cef_internal::scoped_ptr_impl<element_type, deleter_type> impl_;
-
-  // Forbidden for API compatibility with std::unique_ptr.
-  explicit scoped_ptr(int disallow_construction_from_null);
-
-  // Forbid comparison of scoped_ptr types.  If U != T, it totally
-  // doesn't make sense, and if U == T, it still doesn't make sense
-  // because you should never have the same object owned by two different
-  // scoped_ptrs.
-  template <class U>
-  bool operator==(scoped_ptr<U> const& p2) const;
-  template <class U>
-  bool operator!=(scoped_ptr<U> const& p2) const;
-};
-
-template <class T, class D>
-class scoped_ptr<T[], D> {
-  MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
-
- public:
-  // The element and deleter types.
-  typedef T element_type;
-  typedef D deleter_type;
-
-  // Constructor.  Defaults to initializing with NULL.
-  scoped_ptr() : impl_(NULL) {}
-
-  // Constructor. Stores the given array. Note that the argument's type
-  // must exactly match T*. In particular:
-  // - it cannot be a pointer to a type derived from T, because it is
-  //   inherently unsafe in the general case to access an array through a
-  //   pointer whose dynamic type does not match its static type (eg., if
-  //   T and the derived types had different sizes access would be
-  //   incorrectly calculated). Deletion is also always undefined
-  //   (C++98 [expr.delete]p3). If you're doing this, fix your code.
-  // - it cannot be NULL, because NULL is an integral expression, not a
-  //   pointer to T. Use the no-argument version instead of explicitly
-  //   passing NULL.
-  // - it cannot be const-qualified differently from T per unique_ptr spec
-  //   (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting
-  //   to work around this may use implicit_cast<const T*>().
-  //   However, because of the first bullet in this comment, users MUST
-  //   NOT use implicit_cast<Base*>() to upcast the static type of the array.
-  explicit scoped_ptr(element_type* array) : impl_(array) {}
-
-  // Constructor.  Move constructor for C++03 move emulation of this type.
-  scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) {}
-
-  // operator=.  Move operator= for C++03 move emulation of this type.
-  scoped_ptr& operator=(RValue rhs) {
-    impl_.TakeState(&rhs.object->impl_);
-    return *this;
-  }
-
-  // Reset.  Deletes the currently owned array, if any.
-  // Then takes ownership of a new object, if given.
-  void reset(element_type* array = NULL) { impl_.reset(array); }
-
-  // Accessors to get the owned array.
-  element_type& operator[](size_t i) const {
-    assert(impl_.get() != NULL);
-    return impl_.get()[i];
-  }
-  element_type* get() const { return impl_.get(); }
-
-  // Access to the deleter.
-  deleter_type& get_deleter() { return impl_.get_deleter(); }
-  const deleter_type& get_deleter() const { return impl_.get_deleter(); }
-
-  // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
-  // implicitly convertible to a real bool (which is dangerous).
- private:
-  typedef base::cef_internal::scoped_ptr_impl<element_type, deleter_type>
-      scoped_ptr::*Testable;
-
- public:
-  operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }
-
-  // Comparison operators.
-  // These return whether two scoped_ptr refer to the same object, not just to
-  // two different but equal objects.
-  bool operator==(element_type* array) const { return impl_.get() == array; }
-  bool operator!=(element_type* array) const { return impl_.get() != array; }
-
-  // Swap two scoped pointers.
-  void swap(scoped_ptr& p2) { impl_.swap(p2.impl_); }
-
-  // Release a pointer.
-  // The return value is the current pointer held by this object.
-  // If this object holds a NULL pointer, the return value is NULL.
-  // After this operation, this object will hold a NULL pointer,
-  // and will not own the object any more.
-  element_type* release() WARN_UNUSED_RESULT { return impl_.release(); }
-
- private:
-  // Force element_type to be a complete type.
-  enum { type_must_be_complete = sizeof(element_type) };
-
-  // Actually hold the data.
-  base::cef_internal::scoped_ptr_impl<element_type, deleter_type> impl_;
-
-  // Disable initialization from any type other than element_type*, by
-  // providing a constructor that matches such an initialization, but is
-  // private and has no definition. This is disabled because it is not safe to
-  // call delete[] on an array whose static type does not match its dynamic
-  // type.
-  template <typename U>
-  explicit scoped_ptr(U* array);
-  explicit scoped_ptr(int disallow_construction_from_null);
-
-  // Disable reset() from any type other than element_type*, for the same
-  // reasons as the constructor above.
-  template <typename U>
-  void reset(U* array);
-  void reset(int disallow_reset_from_null);
-
-  // Forbid comparison of scoped_ptr types.  If U != T, it totally
-  // doesn't make sense, and if U == T, it still doesn't make sense
-  // because you should never have the same object owned by two different
-  // scoped_ptrs.
-  template <class U>
-  bool operator==(scoped_ptr<U> const& p2) const;
-  template <class U>
-  bool operator!=(scoped_ptr<U> const& p2) const;
-};
-
-// Free functions
-template <class T, class D>
-void swap(scoped_ptr<T, D>& p1, scoped_ptr<T, D>& p2) {
-  p1.swap(p2);
-}
-
-template <class T, class D>
-bool operator==(T* p1, const scoped_ptr<T, D>& p2) {
-  return p1 == p2.get();
-}
-
-template <class T, class D>
-bool operator!=(T* p1, const scoped_ptr<T, D>& p2) {
-  return p1 != p2.get();
-}
-
-// A function to convert T* into scoped_ptr<T>
-// Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation
-// for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
-template <typename T>
-scoped_ptr<T> make_scoped_ptr(T* ptr) {
-  return scoped_ptr<T>(ptr);
-}
-
-#endif  // !USING_CHROMIUM_INCLUDES
-
-#endif  // CEF_INCLUDE_BASE_CEF_MEMORY_SCOPED_PTR_H_
diff --git a/src/include/base/cef_scoped_refptr.h b/src/include/base/cef_scoped_refptr.h
new file mode 100644
index 0000000..9269039
--- /dev/null
+++ b/src/include/base/cef_scoped_refptr.h
@@ -0,0 +1,420 @@
+// Copyright (c) 2017 Marshall A. Greenblatt. Portions copyright (c) 2011
+// Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CEF_INCLUDE_BASE_CEF_SCOPED_REFPTR_H_
+#define CEF_INCLUDE_BASE_CEF_SCOPED_REFPTR_H_
+#pragma once
+
+#if defined(USING_CHROMIUM_INCLUDES)
+// When building CEF include the Chromium header directly.
+#include "base/memory/scoped_refptr.h"
+#else  // !USING_CHROMIUM_INCLUDES
+// The following is substantially similar to the Chromium implementation.
+// If the Chromium implementation diverges the below implementation should be
+// updated to match.
+
+#include <stddef.h>
+
+#include <iosfwd>
+#include <type_traits>
+#include <utility>
+
+#include "include/base/cef_logging.h"
+
+template <class T>
+class scoped_refptr;
+
+namespace base {
+
+template <class, typename>
+class RefCounted;
+template <class, typename>
+class RefCountedThreadSafe;
+class SequencedTaskRunner;
+class WrappedPromise;
+
+template <typename T>
+scoped_refptr<T> AdoptRef(T* t);
+
+namespace internal {
+
+class BasePromise;
+
+}  // namespace internal
+
+namespace cef_subtle {
+
+enum AdoptRefTag { kAdoptRefTag };
+enum StartRefCountFromZeroTag { kStartRefCountFromZeroTag };
+enum StartRefCountFromOneTag { kStartRefCountFromOneTag };
+
+template <typename T, typename U, typename V>
+constexpr bool IsRefCountPreferenceOverridden(const T*,
+                                              const RefCounted<U, V>*) {
+  return !std::is_same<std::decay_t<decltype(T::kRefCountPreference)>,
+                       std::decay_t<decltype(U::kRefCountPreference)>>::value;
+}
+
+template <typename T, typename U, typename V>
+constexpr bool IsRefCountPreferenceOverridden(
+    const T*,
+    const RefCountedThreadSafe<U, V>*) {
+  return !std::is_same<std::decay_t<decltype(T::kRefCountPreference)>,
+                       std::decay_t<decltype(U::kRefCountPreference)>>::value;
+}
+
+constexpr bool IsRefCountPreferenceOverridden(...) {
+  return false;
+}
+
+}  // namespace cef_subtle
+
+// Creates a scoped_refptr from a raw pointer without incrementing the reference
+// count. Use this only for a newly created object whose reference count starts
+// from 1 instead of 0.
+template <typename T>
+scoped_refptr<T> AdoptRef(T* obj) {
+  using Tag = std::decay_t<decltype(T::kRefCountPreference)>;
+  static_assert(std::is_same<cef_subtle::StartRefCountFromOneTag, Tag>::value,
+                "Use AdoptRef only if the reference count starts from one.");
+
+  DCHECK(obj);
+  DCHECK(obj->HasOneRef());
+  obj->Adopted();
+  return scoped_refptr<T>(obj, cef_subtle::kAdoptRefTag);
+}
+
+namespace cef_subtle {
+
+template <typename T>
+scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromZeroTag) {
+  return scoped_refptr<T>(obj);
+}
+
+template <typename T>
+scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromOneTag) {
+  return AdoptRef(obj);
+}
+
+}  // namespace cef_subtle
+
+// Constructs an instance of T, which is a ref counted type, and wraps the
+// object into a scoped_refptr<T>.
+template <typename T, typename... Args>
+scoped_refptr<T> MakeRefCounted(Args&&... args) {
+  T* obj = new T(std::forward<Args>(args)...);
+  return cef_subtle::AdoptRefIfNeeded(obj, T::kRefCountPreference);
+}
+
+// Takes an instance of T, which is a ref counted type, and wraps the object
+// into a scoped_refptr<T>.
+template <typename T>
+scoped_refptr<T> WrapRefCounted(T* t) {
+  return scoped_refptr<T>(t);
+}
+
+}  // namespace base
+
+///
+/// A smart pointer class for reference counted objects.  Use this class instead
+/// of calling AddRef and Release manually on a reference counted object to
+/// avoid common memory leaks caused by forgetting to Release an object
+/// reference. Sample usage:
+///
+/// <pre>
+///   class MyFoo : public RefCounted<MyFoo> {
+///    ...
+///    private:
+///     friend class RefCounted<MyFoo>;  // Allow destruction by RefCounted<>.
+///     ~MyFoo();                        // Destructor must be
+///     private/protected.
+///   };
+///
+///   void some_function() {
+///     scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>();
+///     foo->Method(param);
+///     // |foo| is released when this function returns
+///   }
+///
+///   void some_other_function() {
+///     scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>();
+///     ...
+///     foo.reset();  // explicitly releases |foo|
+///     ...
+///     if (foo)
+///       foo->Method(param);
+///   }
+/// </pre>
+///
+/// The above examples show how scoped_refptr<T> acts like a pointer to T.
+/// Given two scoped_refptr<T> classes, it is also possible to exchange
+/// references between the two objects, like so:
+///
+/// <pre>
+///   {
+///     scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>();
+///     scoped_refptr<MyFoo> b;
+///
+///     b.swap(a);
+///     // now, |b| references the MyFoo object, and |a| references nullptr.
+///   }
+/// </pre>
+///
+/// To make both |a| and |b| in the above example reference the same MyFoo
+/// object, simply use the assignment operator:
+///
+/// <pre>
+///   {
+///     scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>();
+///     scoped_refptr<MyFoo> b;
+///
+///     b = a;
+///     // now, |a| and |b| each own a reference to the same MyFoo object.
+///   }
+/// </pre>
+///
+/// Also see Chromium's ownership and calling conventions:
+/// https://chromium.googlesource.com/chromium/src/+/lkgr/styleguide/c++/c++.md#object-ownership-and-calling-conventions
+/// Specifically:
+///   If the function (at least sometimes) takes a ref on a refcounted object,
+///   declare the param as scoped_refptr<T>. The caller can decide whether it
+///   wishes to transfer ownership (by calling std::move(t) when passing t) or
+///   retain its ref (by simply passing t directly).
+///   In other words, use scoped_refptr like you would a std::unique_ptr except
+///   in the odd case where it's required to hold on to a ref while handing one
+///   to another component (if a component merely needs to use t on the stack
+///   without keeping a ref: pass t as a raw T*).
+///
+template <class T>
+class TRIVIAL_ABI scoped_refptr {
+ public:
+  typedef T element_type;
+
+  constexpr scoped_refptr() = default;
+
+  // Allow implicit construction from nullptr.
+  constexpr scoped_refptr(std::nullptr_t) {}
+
+  // Constructs from a raw pointer. Note that this constructor allows implicit
+  // conversion from T* to scoped_refptr<T> which is strongly discouraged. If
+  // you are creating a new ref-counted object please use
+  // base::MakeRefCounted<T>() or base::WrapRefCounted<T>(). Otherwise you
+  // should move or copy construct from an existing scoped_refptr<T> to the
+  // ref-counted object.
+  scoped_refptr(T* p) : ptr_(p) {
+    if (ptr_) {
+      AddRef(ptr_);
+    }
+  }
+
+  // Copy constructor. This is required in addition to the copy conversion
+  // constructor below.
+  scoped_refptr(const scoped_refptr& r) : scoped_refptr(r.ptr_) {}
+
+  // Copy conversion constructor.
+  template <typename U,
+            typename = typename std::enable_if<
+                std::is_convertible<U*, T*>::value>::type>
+  scoped_refptr(const scoped_refptr<U>& r) : scoped_refptr(r.ptr_) {}
+
+  // Move constructor. This is required in addition to the move conversion
+  // constructor below.
+  scoped_refptr(scoped_refptr&& r) noexcept : ptr_(r.ptr_) { r.ptr_ = nullptr; }
+
+  // Move conversion constructor.
+  template <typename U,
+            typename = typename std::enable_if<
+                std::is_convertible<U*, T*>::value>::type>
+  scoped_refptr(scoped_refptr<U>&& r) noexcept : ptr_(r.ptr_) {
+    r.ptr_ = nullptr;
+  }
+
+  ~scoped_refptr() {
+    static_assert(!base::cef_subtle::IsRefCountPreferenceOverridden(
+                      static_cast<T*>(nullptr), static_cast<T*>(nullptr)),
+                  "It's unsafe to override the ref count preference."
+                  " Please remove REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE"
+                  " from subclasses.");
+    if (ptr_) {
+      Release(ptr_);
+    }
+  }
+
+  T* get() const { return ptr_; }
+
+  T& operator*() const {
+    DCHECK(ptr_);
+    return *ptr_;
+  }
+
+  T* operator->() const {
+    DCHECK(ptr_);
+    return ptr_;
+  }
+
+  scoped_refptr& operator=(std::nullptr_t) {
+    reset();
+    return *this;
+  }
+
+  scoped_refptr& operator=(T* p) { return *this = scoped_refptr(p); }
+
+  // Unified assignment operator.
+  scoped_refptr& operator=(scoped_refptr r) noexcept {
+    swap(r);
+    return *this;
+  }
+
+  // Sets managed object to null and releases reference to the previous managed
+  // object, if it existed.
+  void reset() { scoped_refptr().swap(*this); }
+
+  // Returns the owned pointer (if any), releasing ownership to the caller. The
+  // caller is responsible for managing the lifetime of the reference.
+  [[nodiscard]] T* release();
+
+  void swap(scoped_refptr& r) noexcept { std::swap(ptr_, r.ptr_); }
+
+  explicit operator bool() const { return ptr_ != nullptr; }
+
+  template <typename U>
+  bool operator==(const scoped_refptr<U>& rhs) const {
+    return ptr_ == rhs.get();
+  }
+
+  template <typename U>
+  bool operator!=(const scoped_refptr<U>& rhs) const {
+    return !operator==(rhs);
+  }
+
+  template <typename U>
+  bool operator<(const scoped_refptr<U>& rhs) const {
+    return ptr_ < rhs.get();
+  }
+
+ protected:
+  T* ptr_ = nullptr;
+
+ private:
+  template <typename U>
+  friend scoped_refptr<U> base::AdoptRef(U*);
+  friend class ::base::SequencedTaskRunner;
+
+  // Friend access so these classes can use the constructor below as part of a
+  // binary size optimization.
+  friend class ::base::internal::BasePromise;
+  friend class ::base::WrappedPromise;
+
+  scoped_refptr(T* p, base::cef_subtle::AdoptRefTag) : ptr_(p) {}
+
+  // Friend required for move constructors that set r.ptr_ to null.
+  template <typename U>
+  friend class scoped_refptr;
+
+  // Non-inline helpers to allow:
+  //     class Opaque;
+  //     extern template class scoped_refptr<Opaque>;
+  // Otherwise the compiler will complain that Opaque is an incomplete type.
+  static void AddRef(T* ptr);
+  static void Release(T* ptr);
+};
+
+template <typename T>
+T* scoped_refptr<T>::release() {
+  T* ptr = ptr_;
+  ptr_ = nullptr;
+  return ptr;
+}
+
+// static
+template <typename T>
+void scoped_refptr<T>::AddRef(T* ptr) {
+  ptr->AddRef();
+}
+
+// static
+template <typename T>
+void scoped_refptr<T>::Release(T* ptr) {
+  ptr->Release();
+}
+
+template <typename T, typename U>
+bool operator==(const scoped_refptr<T>& lhs, const U* rhs) {
+  return lhs.get() == rhs;
+}
+
+template <typename T, typename U>
+bool operator==(const T* lhs, const scoped_refptr<U>& rhs) {
+  return lhs == rhs.get();
+}
+
+template <typename T>
+bool operator==(const scoped_refptr<T>& lhs, std::nullptr_t null) {
+  return !static_cast<bool>(lhs);
+}
+
+template <typename T>
+bool operator==(std::nullptr_t null, const scoped_refptr<T>& rhs) {
+  return !static_cast<bool>(rhs);
+}
+
+template <typename T, typename U>
+bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) {
+  return !operator==(lhs, rhs);
+}
+
+template <typename T, typename U>
+bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) {
+  return !operator==(lhs, rhs);
+}
+
+template <typename T>
+bool operator!=(const scoped_refptr<T>& lhs, std::nullptr_t null) {
+  return !operator==(lhs, null);
+}
+
+template <typename T>
+bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) {
+  return !operator==(null, rhs);
+}
+
+template <typename T>
+std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) {
+  return out << p.get();
+}
+
+template <typename T>
+void swap(scoped_refptr<T>& lhs, scoped_refptr<T>& rhs) noexcept {
+  lhs.swap(rhs);
+}
+
+#endif  // !USING_CHROMIUM_INCLUDES
+
+#endif  // CEF_INCLUDE_BASE_CEF_SCOPED_REFPTR_H_
diff --git a/src/include/base/cef_scoped_typeref_mac.h b/src/include/base/cef_scoped_typeref_mac.h
new file mode 100644
index 0000000..65d16a1
--- /dev/null
+++ b/src/include/base/cef_scoped_typeref_mac.h
@@ -0,0 +1,190 @@
+// Copyright (c) 2021 Marshall A. Greenblatt. Portions copyright (c) 2013
+// Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CEF_INCLUDE_BASE_CEF_SCOPED_TYPEREF_MAC_H_
+#define CEF_INCLUDE_BASE_CEF_SCOPED_TYPEREF_MAC_H_
+#pragma once
+
+#if defined(USING_CHROMIUM_INCLUDES)
+// When building CEF include the Chromium header directly.
+#include "base/mac/scoped_typeref.h"
+#else  // !USING_CHROMIUM_INCLUDES
+// The following is substantially similar to the Chromium implementation.
+// If the Chromium implementation diverges the below implementation should be
+// updated to match.
+
+#include "include/base/cef_logging.h"
+#include "include/base/internal/cef_scoped_policy.h"
+
+namespace base {
+
+template <typename T>
+struct ScopedTypeRefTraits;
+
+///
+/// ScopedTypeRef<> is patterned after std::unique_ptr<>, but maintains
+/// ownership of a reference to any type that is maintained by Retain and
+/// Release methods.
+///
+/// The Traits structure must provide the Retain and Release methods for type T.
+/// A default ScopedTypeRefTraits is used but not defined, and should be defined
+/// for each type to use this interface. For example, an appropriate definition
+/// of ScopedTypeRefTraits for CGLContextObj would be:
+///
+/// <pre>
+///   template<>
+///   struct ScopedTypeRefTraits<CGLContextObj> {
+///     static CGLContextObj InvalidValue() { return nullptr; }
+///     static CGLContextObj Retain(CGLContextObj object) {
+///       CGLContextRetain(object);
+///       return object;
+///     }
+///     static void Release(CGLContextObj object) { CGLContextRelease(object); }
+///   };
+/// </pre>
+///
+/// For the many types that have pass-by-pointer create functions, the function
+/// InitializeInto() is provided to allow direct initialization and assumption
+/// of ownership of the object. For example, continuing to use the above
+/// CGLContextObj specialization:
+///
+/// <pre>
+///   base::ScopedTypeRef<CGLContextObj> context;
+///   CGLCreateContext(pixel_format, share_group, context.InitializeInto());
+/// </pre>
+///
+/// For initialization with an existing object, the caller may specify whether
+/// the ScopedTypeRef<> being initialized is assuming the caller's existing
+/// ownership of the object (and should not call Retain in initialization) or if
+/// it should not assume this ownership and must create its own (by calling
+/// Retain in initialization). This behavior is based on the |policy| parameter,
+/// with |ASSUME| for the former and |RETAIN| for the latter. The default policy
+/// is to |ASSUME|.
+///
+template <typename T, typename Traits = ScopedTypeRefTraits<T>>
+class ScopedTypeRef {
+ public:
+  using element_type = T;
+
+  explicit constexpr ScopedTypeRef(
+      element_type object = Traits::InvalidValue(),
+      base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME)
+      : object_(object) {
+    if (object_ && policy == base::scoped_policy::RETAIN) {
+      object_ = Traits::Retain(object_);
+    }
+  }
+
+  ScopedTypeRef(const ScopedTypeRef<T, Traits>& that) : object_(that.object_) {
+    if (object_) {
+      object_ = Traits::Retain(object_);
+    }
+  }
+
+  // This allows passing an object to a function that takes its superclass.
+  template <typename R, typename RTraits>
+  explicit ScopedTypeRef(const ScopedTypeRef<R, RTraits>& that_as_subclass)
+      : object_(that_as_subclass.get()) {
+    if (object_) {
+      object_ = Traits::Retain(object_);
+    }
+  }
+
+  ScopedTypeRef(ScopedTypeRef<T, Traits>&& that) : object_(that.object_) {
+    that.object_ = Traits::InvalidValue();
+  }
+
+  ~ScopedTypeRef() {
+    if (object_) {
+      Traits::Release(object_);
+    }
+  }
+
+  ScopedTypeRef& operator=(const ScopedTypeRef<T, Traits>& that) {
+    reset(that.get(), base::scoped_policy::RETAIN);
+    return *this;
+  }
+
+  // This is to be used only to take ownership of objects that are created
+  // by pass-by-pointer create functions. To enforce this, require that the
+  // object be reset to NULL before this may be used.
+  [[nodiscard]] element_type* InitializeInto() {
+    DCHECK(!object_);
+    return &object_;
+  }
+
+  void reset(const ScopedTypeRef<T, Traits>& that) {
+    reset(that.get(), base::scoped_policy::RETAIN);
+  }
+
+  void reset(element_type object = Traits::InvalidValue(),
+             base::scoped_policy::OwnershipPolicy policy =
+                 base::scoped_policy::ASSUME) {
+    if (object && policy == base::scoped_policy::RETAIN) {
+      object = Traits::Retain(object);
+    }
+    if (object_) {
+      Traits::Release(object_);
+    }
+    object_ = object;
+  }
+
+  bool operator==(const element_type& that) const { return object_ == that; }
+
+  bool operator!=(const element_type& that) const { return object_ != that; }
+
+  operator element_type() const { return object_; }
+
+  element_type get() const { return object_; }
+
+  void swap(ScopedTypeRef& that) {
+    element_type temp = that.object_;
+    that.object_ = object_;
+    object_ = temp;
+  }
+
+  // ScopedTypeRef<>::release() is like std::unique_ptr<>::release.  It is NOT
+  // a wrapper for Release().  To force a ScopedTypeRef<> object to call
+  // Release(), use ScopedTypeRef<>::reset().
+  [[nodiscard]] element_type release() {
+    element_type temp = object_;
+    object_ = Traits::InvalidValue();
+    return temp;
+  }
+
+ private:
+  element_type object_;
+};
+
+}  // namespace base
+
+#endif  // !USING_CHROMIUM_INCLUDES
+
+#endif  // CEF_INCLUDE_BASE_CEF_SCOPED_TYPEREF_MAC_H_
diff --git a/src/include/base/cef_string16.h b/src/include/base/cef_string16.h
deleted file mode 100644
index 6afcb79..0000000
--- a/src/include/base/cef_string16.h
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2013
-// Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef CEF_INCLUDE_BASE_CEF_STRING16_H_
-#define CEF_INCLUDE_BASE_CEF_STRING16_H_
-#pragma once
-
-#if defined(BASE_STRINGS_STRING16_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
-// When building CEF include the Chromium header directly.
-#include "base/strings/string16.h"
-#else  // !USING_CHROMIUM_INCLUDES
-// The following is substantially similar to the Chromium implementation.
-// If the Chromium implementation diverges the below implementation should be
-// updated to match.
-// WHAT:
-// A version of std::basic_string that provides 2-byte characters even when
-// wchar_t is not implemented as a 2-byte type. You can access this class as
-// string16. We also define char16, which string16 is based upon.
-//
-// WHY:
-// On Windows, wchar_t is 2 bytes, and it can conveniently handle UTF-16/UCS-2
-// data. Plenty of existing code operates on strings encoded as UTF-16.
-//
-// On many other platforms, sizeof(wchar_t) is 4 bytes by default. We can make
-// it 2 bytes by using the GCC flag -fshort-wchar. But then std::wstring fails
-// at run time, because it calls some functions (like wcslen) that come from
-// the system's native C library -- which was built with a 4-byte wchar_t!
-// It's wasteful to use 4-byte wchar_t strings to carry UTF-16 data, and it's
-// entirely improper on those systems where the encoding of wchar_t is defined
-// as UTF-32.
-//
-// Here, we define string16, which is similar to std::wstring but replaces all
-// libc functions with custom, 2-byte-char compatible routines. It is capable
-// of carrying UTF-16-encoded data.
-
-#include <stdio.h>
-#include <string>
-
-#include "include/base/cef_basictypes.h"
-
-#if defined(WCHAR_T_IS_UTF16)
-
-namespace base {
-
-typedef wchar_t char16;
-typedef std::wstring string16;
-typedef std::char_traits<wchar_t> string16_char_traits;
-
-}  // namespace base
-
-#elif defined(WCHAR_T_IS_UTF32)
-
-#include <stdint.h>  // For uint16_t
-
-#include "include/base/cef_macros.h"
-
-namespace cef {
-namespace base {
-
-typedef uint16_t char16;
-
-// char16 versions of the functions required by string16_char_traits; these
-// are based on the wide character functions of similar names ("w" or "wcs"
-// instead of "c16").
-int c16memcmp(const char16* s1, const char16* s2, size_t n);
-size_t c16len(const char16* s);
-const char16* c16memchr(const char16* s, char16 c, size_t n);
-char16* c16memmove(char16* s1, const char16* s2, size_t n);
-char16* c16memcpy(char16* s1, const char16* s2, size_t n);
-char16* c16memset(char16* s, char16 c, size_t n);
-
-struct string16_char_traits {
-  typedef char16 char_type;
-  typedef int int_type;
-
-  // int_type needs to be able to hold each possible value of char_type, and in
-  // addition, the distinct value of eof().
-  COMPILE_ASSERT(sizeof(int_type) > sizeof(char_type), unexpected_type_width);
-
-  typedef std::streamoff off_type;
-  typedef mbstate_t state_type;
-  typedef std::fpos<state_type> pos_type;
-
-  static void assign(char_type& c1, const char_type& c2) { c1 = c2; }
-
-  static bool eq(const char_type& c1, const char_type& c2) { return c1 == c2; }
-  static bool lt(const char_type& c1, const char_type& c2) { return c1 < c2; }
-
-  static int compare(const char_type* s1, const char_type* s2, size_t n) {
-    return c16memcmp(s1, s2, n);
-  }
-
-  static size_t length(const char_type* s) { return c16len(s); }
-
-  static const char_type* find(const char_type* s,
-                               size_t n,
-                               const char_type& a) {
-    return c16memchr(s, a, n);
-  }
-
-  static char_type* move(char_type* s1, const char_type* s2, int_type n) {
-    return c16memmove(s1, s2, n);
-  }
-
-  static char_type* copy(char_type* s1, const char_type* s2, size_t n) {
-    return c16memcpy(s1, s2, n);
-  }
-
-  static char_type* assign(char_type* s, size_t n, char_type a) {
-    return c16memset(s, a, n);
-  }
-
-  static int_type not_eof(const int_type& c) {
-    return eq_int_type(c, eof()) ? 0 : c;
-  }
-
-  static char_type to_char_type(const int_type& c) { return char_type(c); }
-
-  static int_type to_int_type(const char_type& c) { return int_type(c); }
-
-  static bool eq_int_type(const int_type& c1, const int_type& c2) {
-    return c1 == c2;
-  }
-
-  static int_type eof() { return static_cast<int_type>(EOF); }
-};
-
-typedef std::basic_string<char16, string16_char_traits> string16;
-
-}  // namespace base
-}  // namespace cef
-
-namespace base {
-
-typedef cef::base::char16 char16;
-typedef cef::base::string16 string16;
-
-extern std::ostream& operator<<(std::ostream& out, const string16& str);
-
-// This is required by googletest to print a readable output on test failures.
-extern void PrintTo(const string16& str, std::ostream* out);
-
-}  // namespace base
-
-// The string class will be explicitly instantiated only once, in string16.cc.
-//
-// std::basic_string<> in GNU libstdc++ contains a static data member,
-// _S_empty_rep_storage, to represent empty strings.  When an operation such
-// as assignment or destruction is performed on a string, causing its existing
-// data member to be invalidated, it must not be freed if this static data
-// member is being used.  Otherwise, it counts as an attempt to free static
-// (and not allocated) data, which is a memory error.
-//
-// Generally, due to C++ template magic, _S_empty_rep_storage will be marked
-// as a coalesced symbol, meaning that the linker will combine multiple
-// instances into a single one when generating output.
-//
-// If a string class is used by multiple shared libraries, a problem occurs.
-// Each library will get its own copy of _S_empty_rep_storage.  When strings
-// are passed across a library boundary for alteration or destruction, memory
-// errors will result.  GNU libstdc++ contains a configuration option,
-// --enable-fully-dynamic-string (_GLIBCXX_FULLY_DYNAMIC_STRING), which
-// disables the static data member optimization, but it's a good optimization
-// and non-STL code is generally at the mercy of the system's STL
-// configuration.  Fully-dynamic strings are not the default for GNU libstdc++
-// libstdc++ itself or for the libstdc++ installations on the systems we care
-// about, such as Mac OS X and relevant flavors of Linux.
-//
-// See also http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24196 .
-//
-// To avoid problems, string classes need to be explicitly instantiated only
-// once, in exactly one library.  All other string users see it via an "extern"
-// declaration.  This is precisely how GNU libstdc++ handles
-// std::basic_string<char> (string) and std::basic_string<wchar_t> (wstring).
-//
-// This also works around a Mac OS X linker bug in ld64-85.2.1 (Xcode 3.1.2),
-// in which the linker does not fully coalesce symbols when dead code
-// stripping is enabled.  This bug causes the memory errors described above
-// to occur even when a std::basic_string<> does not cross shared library
-// boundaries, such as in statically-linked executables.
-//
-// TODO(mark): File this bug with Apple and update this note with a bug number.
-
-extern template class std::basic_string<cef::base::char16,
-                                        cef::base::string16_char_traits>;
-
-#endif  // WCHAR_T_IS_UTF32
-
-#endif  // !USING_CHROMIUM_INCLUDES
-
-#endif  // CEF_INCLUDE_BASE_CEF_STRING16_H_
diff --git a/src/include/base/cef_template_util.h b/src/include/base/cef_template_util.h
deleted file mode 100644
index 38fa583..0000000
--- a/src/include/base/cef_template_util.h
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
-// Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef CEF_INCLUDE_BASE_CEF_TEMPLATE_UTIL_H_
-#define CEF_INCLUDE_BASE_CEF_TEMPLATE_UTIL_H_
-#pragma once
-
-#if defined(BASE_TEMPLATE_UTIL_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
-// When building CEF include the Chromium header directly.
-#include "base/template_util.h"
-#else  // !USING_CHROMIUM_INCLUDES
-// The following is substantially similar to the Chromium implementation.
-// If the Chromium implementation diverges the below implementation should be
-// updated to match.
-
-#include <cstddef>  // For size_t.
-
-#include "include/base/cef_build.h"
-
-namespace base {
-
-// template definitions from tr1
-
-template <class T, T v>
-struct integral_constant {
-  static const T value = v;
-  typedef T value_type;
-  typedef integral_constant<T, v> type;
-};
-
-template <class T, T v>
-const T integral_constant<T, v>::value;
-
-typedef integral_constant<bool, true> true_type;
-typedef integral_constant<bool, false> false_type;
-
-template <class T>
-struct is_pointer : false_type {};
-template <class T>
-struct is_pointer<T*> : true_type {};
-
-// Member function pointer detection up to four params. Add more as needed
-// below. This is built-in to C++ 11, and we can remove this when we switch.
-template <typename T>
-struct is_member_function_pointer : false_type {};
-
-template <typename R, typename Z>
-struct is_member_function_pointer<R (Z::*)()> : true_type {};
-template <typename R, typename Z>
-struct is_member_function_pointer<R (Z::*)() const> : true_type {};
-
-template <typename R, typename Z, typename A>
-struct is_member_function_pointer<R (Z::*)(A)> : true_type {};
-template <typename R, typename Z, typename A>
-struct is_member_function_pointer<R (Z::*)(A) const> : true_type {};
-
-template <typename R, typename Z, typename A, typename B>
-struct is_member_function_pointer<R (Z::*)(A, B)> : true_type {};
-template <typename R, typename Z, typename A, typename B>
-struct is_member_function_pointer<R (Z::*)(A, B) const> : true_type {};
-
-template <typename R, typename Z, typename A, typename B, typename C>
-struct is_member_function_pointer<R (Z::*)(A, B, C)> : true_type {};
-template <typename R, typename Z, typename A, typename B, typename C>
-struct is_member_function_pointer<R (Z::*)(A, B, C) const> : true_type {};
-
-template <typename R,
-          typename Z,
-          typename A,
-          typename B,
-          typename C,
-          typename D>
-struct is_member_function_pointer<R (Z::*)(A, B, C, D)> : true_type {};
-template <typename R,
-          typename Z,
-          typename A,
-          typename B,
-          typename C,
-          typename D>
-struct is_member_function_pointer<R (Z::*)(A, B, C, D) const> : true_type {};
-
-template <class T, class U>
-struct is_same : public false_type {};
-template <class T>
-struct is_same<T, T> : true_type {};
-
-template <class>
-struct is_array : public false_type {};
-template <class T, size_t n>
-struct is_array<T[n]> : public true_type {};
-template <class T>
-struct is_array<T[]> : public true_type {};
-
-template <class T>
-struct is_non_const_reference : false_type {};
-template <class T>
-struct is_non_const_reference<T&> : true_type {};
-template <class T>
-struct is_non_const_reference<const T&> : false_type {};
-
-template <class T>
-struct is_const : false_type {};
-template <class T>
-struct is_const<const T> : true_type {};
-
-template <class T>
-struct is_void : false_type {};
-template <>
-struct is_void<void> : true_type {};
-
-namespace cef_internal {
-
-// Types YesType and NoType are guaranteed such that sizeof(YesType) <
-// sizeof(NoType).
-typedef char YesType;
-
-struct NoType {
-  YesType dummy[2];
-};
-
-// This class is an implementation detail for is_convertible, and you
-// don't need to know how it works to use is_convertible. For those
-// who care: we declare two different functions, one whose argument is
-// of type To and one with a variadic argument list. We give them
-// return types of different size, so we can use sizeof to trick the
-// compiler into telling us which function it would have chosen if we
-// had called it with an argument of type From.  See Alexandrescu's
-// _Modern C++ Design_ for more details on this sort of trick.
-
-struct ConvertHelper {
-  template <typename To>
-  static YesType Test(To);
-
-  template <typename To>
-  static NoType Test(...);
-
-  template <typename From>
-  static From& Create();
-};
-
-// Used to determine if a type is a struct/union/class. Inspired by Boost's
-// is_class type_trait implementation.
-struct IsClassHelper {
-  template <typename C>
-  static YesType Test(void (C::*)(void));
-
-  template <typename C>
-  static NoType Test(...);
-};
-
-}  // namespace cef_internal
-
-// Inherits from true_type if From is convertible to To, false_type otherwise.
-//
-// Note that if the type is convertible, this will be a true_type REGARDLESS
-// of whether or not the conversion would emit a warning.
-template <typename From, typename To>
-struct is_convertible
-    : integral_constant<bool,
-                        sizeof(cef_internal::ConvertHelper::Test<To>(
-                            cef_internal::ConvertHelper::Create<From>())) ==
-                            sizeof(cef_internal::YesType)> {};
-
-template <typename T>
-struct is_class
-    : integral_constant<bool,
-                        sizeof(cef_internal::IsClassHelper::Test<T>(0)) ==
-                            sizeof(cef_internal::YesType)> {};
-
-template <bool B, class T = void>
-struct enable_if {};
-
-template <class T>
-struct enable_if<true, T> {
-  typedef T type;
-};
-
-}  // namespace base
-
-#endif  // !USING_CHROMIUM_INCLUDES
-
-#endif  // CEF_INCLUDE_BASE_CEF_TEMPLATE_UTIL_H_
diff --git a/src/include/base/cef_thread_checker.h b/src/include/base/cef_thread_checker.h
index e48c8d0..6f21c69 100644
--- a/src/include/base/cef_thread_checker.h
+++ b/src/include/base/cef_thread_checker.h
@@ -32,12 +32,7 @@
 #define CEF_INCLUDE_BASE_THREAD_CHECKER_H_
 #pragma once
 
-#if defined(BASE_THREADING_THREAD_CHECKER_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
+#if defined(USING_CHROMIUM_INCLUDES)
 // When building CEF include the Chromium header directly.
 #include "base/threading/thread_checker.h"
 #else  // !USING_CHROMIUM_INCLUDES
@@ -48,10 +43,12 @@
 #include "include/base/cef_logging.h"
 #include "include/base/internal/cef_thread_checker_impl.h"
 
-// Apart from debug builds, we also enable the thread checker in
-// builds with DCHECK_ALWAYS_ON so that trybots and waterfall bots
-// with this define will get the same level of thread checking as
-// debug bots.
+///
+/// Apart from debug builds, we also enable the thread checker in
+/// builds with DCHECK_ALWAYS_ON so that trybots and waterfall bots
+/// with this define will get the same level of thread checking as
+/// debug bots.
+///
 #if DCHECK_IS_ON()
 #define ENABLE_THREAD_CHECKER 1
 #else
@@ -62,10 +59,12 @@
 
 namespace cef_internal {
 
-// Do nothing implementation, for use in release mode.
-//
-// Note: You should almost always use the ThreadChecker class to get the
-// right version for your build configuration.
+///
+/// Do nothing implementation, for use in release mode.
+///
+/// Note: You should almost always use the ThreadChecker class to get the
+/// right version for your build configuration.
+///
 class ThreadCheckerDoNothing {
  public:
   bool CalledOnValidThread() const { return true; }
@@ -75,37 +74,42 @@
 
 }  // namespace cef_internal
 
-// ThreadChecker is a helper class used to help verify that some methods of a
-// class are called from the same thread. It provides identical functionality to
-// base::NonThreadSafe, but it is meant to be held as a member variable, rather
-// than inherited from base::NonThreadSafe.
-//
-// While inheriting from base::NonThreadSafe may give a clear indication about
-// the thread-safety of a class, it may also lead to violations of the style
-// guide with regard to multiple inheritance. The choice between having a
-// ThreadChecker member and inheriting from base::NonThreadSafe should be based
-// on whether:
-//  - Derived classes need to know the thread they belong to, as opposed to
-//    having that functionality fully encapsulated in the base class.
-//  - Derived classes should be able to reassign the base class to another
-//    thread, via DetachFromThread.
-//
-// If neither of these are true, then having a ThreadChecker member and calling
-// CalledOnValidThread is the preferable solution.
-//
-// Example:
-// class MyClass {
-//  public:
-//   void Foo() {
-//     DCHECK(thread_checker_.CalledOnValidThread());
-//     ... (do stuff) ...
-//   }
-//
-//  private:
-//   ThreadChecker thread_checker_;
-// }
-//
-// In Release mode, CalledOnValidThread will always return true.
+///
+/// ThreadChecker is a helper class used to help verify that some methods of a
+/// class are called from the same thread. It provides identical functionality
+/// to base::NonThreadSafe, but it is meant to be held as a member variable,
+/// rather than inherited from base::NonThreadSafe.
+///
+/// While inheriting from base::NonThreadSafe may give a clear indication about
+/// the thread-safety of a class, it may also lead to violations of the style
+/// guide with regard to multiple inheritance. The choice between having a
+/// ThreadChecker member and inheriting from base::NonThreadSafe should be based
+/// on whether:
+///  - Derived classes need to know the thread they belong to, as opposed to
+///    having that functionality fully encapsulated in the base class.
+///  - Derived classes should be able to reassign the base class to another
+///    thread, via DetachFromThread.
+///
+/// If neither of these are true, then having a ThreadChecker member and calling
+/// CalledOnValidThread is the preferable solution.
+///
+/// Example:
+///
+/// <pre>
+///   class MyClass {
+///    public:
+///     void Foo() {
+///       DCHECK(thread_checker_.CalledOnValidThread());
+///       ... (do stuff) ...
+///     }
+///
+///    private:
+///     ThreadChecker thread_checker_;
+///   }
+/// </pre>
+///
+/// In Release mode, CalledOnValidThread will always return true.
+///
 #if ENABLE_THREAD_CHECKER
 class ThreadChecker : public cef_internal::ThreadCheckerImpl {};
 #else
diff --git a/src/include/base/cef_trace_event.h b/src/include/base/cef_trace_event.h
index 1b2cad0..30e31af 100644
--- a/src/include/base/cef_trace_event.h
+++ b/src/include/base/cef_trace_event.h
@@ -29,124 +29,133 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ///
-// Trace events are for tracking application performance and resource usage.
-// Macros are provided to track:
-//    Begin and end of function calls
-//    Counters
-//
-// Events are issued against categories. Whereas LOG's categories are statically
-// defined, TRACE categories are created implicitly with a string. For example:
-//   TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent")
-//
-// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope:
-//   TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly")
-//   doSomethingCostly()
-//   TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly")
-// Note: Our tools can't always determine the correct BEGIN/END pairs unless
-// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you
-// need them to be in separate scopes.
-//
-// A common use case is to trace entire function scopes. This issues a trace
-// BEGIN and END automatically:
-//   void doSomethingCostly() {
-//     TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly");
-//     ...
-//   }
-//
-// Additional parameters can be associated with an event:
-//   void doSomethingCostly2(int howMuch) {
-//     TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly",
-//         "howMuch", howMuch);
-//     ...
-//   }
-//
-// The trace system will automatically add to this information the current
-// process id, thread id, and a timestamp in microseconds.
-//
-// To trace an asynchronous procedure such as an IPC send/receive, use
-// ASYNC_BEGIN and ASYNC_END:
-//   [single threaded sender code]
-//     static int send_count = 0;
-//     ++send_count;
-//     TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count);
-//     Send(new MyMessage(send_count));
-//   [receive code]
-//     void OnMyMessage(send_count) {
-//       TRACE_EVENT_ASYNC_END0("ipc", "message", send_count);
-//     }
-// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs.
-// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process.
-// Pointers can be used for the ID parameter, and they will be mangled
-// internally so that the same pointer on two different processes will not
-// match. For example:
-//   class MyTracedClass {
-//    public:
-//     MyTracedClass() {
-//       TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this);
-//     }
-//     ~MyTracedClass() {
-//       TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this);
-//     }
-//   }
-//
-// The trace event also supports counters, which is a way to track a quantity
-// as it varies over time. Counters are created with the following macro:
-//   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue);
-//
-// Counters are process-specific. The macro itself can be issued from any
-// thread, however.
-//
-// Sometimes, you want to track two counters at once. You can do this with two
-// counter macros:
-//   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]);
-//   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]);
-// Or you can do it with a combined macro:
-//   TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter",
-//       "bytesPinned", g_myCounterValue[0],
-//       "bytesAllocated", g_myCounterValue[1]);
-// This indicates to the tracing UI that these counters should be displayed
-// in a single graph, as a summed area chart.
-//
-// Since counters are in a global namespace, you may want to disembiguate with a
-// unique ID, by using the TRACE_COUNTER_ID* variations.
-//
-// By default, trace collection is compiled in, but turned off at runtime.
-// Collecting trace data is the responsibility of the embedding application. In
-// CEF's case, calling BeginTracing will turn on tracing on all active
-// processes.
-//
-//
-// Memory scoping note:
-// Tracing copies the pointers, not the string content, of the strings passed
-// in for category, name, and arg_names.  Thus, the following code will cause
-// problems:
-//     char* str = strdup("impprtantName");
-//     TRACE_EVENT_INSTANT0("SUBSYSTEM", str);  // BAD!
-//     free(str);                   // Trace system now has dangling pointer
-//
-// To avoid this issue with the |name| and |arg_name| parameters, use the
-// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime
-// overhead.
-// Notes: The category must always be in a long-lived char* (i.e. static const).
-//        The |arg_values|, when used, are always deep copied with the _COPY
-//        macros.
-//
-//
-// Thread Safety:
-// All macros are thread safe and can be used from any process.
+/// \file
+/// Trace events are for tracking application performance and resource usage.
+/// Macros are provided to track:
+///    Begin and end of function calls
+///    Counters
+///
+/// Events are issued against categories. Whereas LOG's categories are
+/// statically defined, TRACE categories are created implicitly with a string.
+/// For example: <pre>
+///   TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent")
+/// </pre>
+///
+/// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope:
+/// <pre>
+///   TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly")
+///   doSomethingCostly()
+///   TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly")
+/// </pre>
+/// Note: Our tools can't always determine the correct BEGIN/END pairs unless
+/// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you
+/// need them to be in separate scopes.
+///
+/// A common use case is to trace entire function scopes. This issues a trace
+/// BEGIN and END automatically:
+/// <pre>
+///   void doSomethingCostly() {
+///     TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly");
+///     ...
+///   }
+/// </pre>
+///
+/// Additional parameters can be associated with an event:
+/// <pre>
+///   void doSomethingCostly2(int howMuch) {
+///     TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly",
+///         "howMuch", howMuch);
+///     ...
+///   }
+/// </pre>
+///
+/// The trace system will automatically add to this information the current
+/// process id, thread id, and a timestamp in microseconds.
+///
+/// To trace an asynchronous procedure such as an IPC send/receive, use
+/// ASYNC_BEGIN and ASYNC_END:
+/// <pre>
+///   [single threaded sender code]
+///     static int send_count = 0;
+///     ++send_count;
+///     TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count);
+///     Send(new MyMessage(send_count));
+///   [receive code]
+///     void OnMyMessage(send_count) {
+///       TRACE_EVENT_ASYNC_END0("ipc", "message", send_count);
+///     }
+/// </pre>
+/// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs.
+/// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process.
+/// Pointers can be used for the ID parameter, and they will be mangled
+/// internally so that the same pointer on two different processes will not
+/// match. For example:
+/// <pre>
+///   class MyTracedClass {
+///    public:
+///     MyTracedClass() {
+///       TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this);
+///     }
+///     ~MyTracedClass() {
+///       TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this);
+///     }
+///   }
+/// </pre>
+///
+/// The trace event also supports counters, which is a way to track a quantity
+/// as it varies over time. Counters are created with the following macro:
+/// <pre>
+///   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue);
+/// </pre>
+///
+/// Counters are process-specific. The macro itself can be issued from any
+/// thread, however.
+///
+/// Sometimes, you want to track two counters at once. You can do this with two
+/// counter macros:
+/// <pre>
+///   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]);
+///   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]);
+/// </pre>
+/// Or you can do it with a combined macro:
+/// <pre>
+///   TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter",
+///       "bytesPinned", g_myCounterValue[0],
+///       "bytesAllocated", g_myCounterValue[1]);
+/// </pre>
+/// This indicates to the tracing UI that these counters should be displayed
+/// in a single graph, as a summed area chart.
+///
+/// Since counters are in a global namespace, you may want to disembiguate with
+/// a unique ID, by using the TRACE_COUNTER_ID* variations.
+///
+/// By default, trace collection is compiled in, but turned off at runtime.
+/// Collecting trace data is the responsibility of the embedding application. In
+/// CEF's case, calling BeginTracing will turn on tracing on all active
+/// processes.
+///
+///
+/// Memory scoping note:
+/// Tracing copies the pointers, not the string content, of the strings passed
+/// in for category, name, and arg_names.  Thus, the following code will cause
+/// problems:
+/// <pre>
+///     char* str = strdup("impprtantName");
+///     TRACE_EVENT_INSTANT0("SUBSYSTEM", str);  // BAD!
+///     free(str);                   // Trace system now has dangling pointer
+/// </pre>
+///
+///
+/// Thread Safety:
+/// All macros are thread safe and can be used from any process.
 ///
 
 #ifndef CEF_INCLUDE_BASE_CEF_TRACE_EVENT_H_
 #define CEF_INCLUDE_BASE_CEF_TRACE_EVENT_H_
 #pragma once
 
-#if defined(TRACE_EVENT0)
-// Do nothing if the macros provided by this header already exist.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
-// When building CEF include the Chromium header directly.
+#if defined(USING_CHROMIUM_INCLUDES)
+/// When building CEF include the Chromium header directly.
 #include "base/trace_event/trace_event.h"
 #else  // !USING_CHROMIUM_INCLUDES
 // The following is substantially similar to the Chromium implementation.
@@ -155,20 +164,22 @@
 
 #include "include/internal/cef_trace_event_internal.h"
 
-// Records a pair of begin and end events called "name" for the current
-// scope, with 0, 1 or 2 associated arguments. If the category is not
-// enabled, then this does nothing.
-// - category and name strings must have application lifetime (statics or
-//   literals). They may not include " chars.
-#define TRACE_EVENT0(category, name)                              \
-  cef_trace_event_begin(category, name, NULL, 0, NULL, 0, false); \
+///
+/// Records a pair of begin and end events called "name" for the current
+/// scope, with 0, 1 or 2 associated arguments. If the category is not
+/// enabled, then this does nothing.
+/// - category and name strings must have application lifetime (statics or
+///   literals). They may not include " chars.
+///
+#define TRACE_EVENT0(category, name)                       \
+  cef_trace_event_begin(category, name, NULL, 0, NULL, 0); \
   CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name)
-#define TRACE_EVENT1(category, name, arg1_name, arg1_val)                     \
-  cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, false); \
+#define TRACE_EVENT1(category, name, arg1_name, arg1_val)              \
+  cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0); \
   CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name)
 #define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, arg2_val) \
   cef_trace_event_begin(category, name, arg1_name, arg1_val, arg2_name,        \
-                        arg2_val, false);                                      \
+                        arg2_val);                                             \
   CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name)
 
 // Implementation detail: trace event macros create temporary variable names.
@@ -184,228 +195,181 @@
   cef_trace_event::CefTraceEndOnScopeClose CEF_INTERNAL_TRACE_EVENT_UID( \
       profileScope)(category, name)
 
-// Records a single event called "name" immediately, with 0, 1 or 2
-// associated arguments. If the category is not enabled, then this
-// does nothing.
-// - category and name strings must have application lifetime (statics or
-//   literals). They may not include " chars.
+///
+/// Records a single event called "name" immediately, with 0, 1 or 2
+/// associated arguments. If the category is not enabled, then this
+/// does nothing.
+/// - category and name strings must have application lifetime (statics or
+///   literals). They may not include " chars.
+///
 #define TRACE_EVENT_INSTANT0(category, name) \
-  cef_trace_event_instant(category, name, NULL, 0, NULL, 0, false)
+  cef_trace_event_instant(category, name, NULL, 0, NULL, 0)
 #define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \
-  cef_trace_event_instant(category, name, arg1_name, arg1_val, NULL, 0, false)
+  cef_trace_event_instant(category, name, arg1_name, arg1_val, NULL, 0)
 #define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, arg2_name, \
                              arg2_val)                                       \
   cef_trace_event_instant(category, name, arg1_name, arg1_val, arg2_name,    \
-                          arg2_val, false)
-#define TRACE_EVENT_COPY_INSTANT0(category, name) \
-  cef_trace_event_instant(category, name, NULL, 0, NULL, 0, true)
-#define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \
-  cef_trace_event_instant(category, name, arg1_name, arg1_val, NULL, 0, true)
-#define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val,    \
-                                  arg2_name, arg2_val)                    \
-  cef_trace_event_instant(category, name, arg1_name, arg1_val, arg2_name, \
-                          arg2_val, true)
+                          arg2_val)
 
-// Records a single BEGIN event called "name" immediately, with 0, 1 or 2
-// associated arguments. If the category is not enabled, then this
-// does nothing.
-// - category and name strings must have application lifetime (statics or
-//   literals). They may not include " chars.
+///
+/// Records a single BEGIN event called "name" immediately, with 0, 1 or 2
+/// associated arguments. If the category is not enabled, then this
+/// does nothing.
+/// - category and name strings must have application lifetime (statics or
+///   literals). They may not include " chars.
+///
 #define TRACE_EVENT_BEGIN0(category, name) \
-  cef_trace_event_begin(category, name, NULL, 0, NULL, 0, false)
+  cef_trace_event_begin(category, name, NULL, 0, NULL, 0)
 #define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \
-  cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, false)
+  cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0)
 #define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, arg2_name, \
                            arg2_val)                                       \
   cef_trace_event_begin(category, name, arg1_name, arg1_val, arg2_name,    \
-                        arg2_val, false)
-#define TRACE_EVENT_COPY_BEGIN0(category, name) \
-  cef_trace_event_begin(category, name, NULL, 0, NULL, 0, true)
-#define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \
-  cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, true)
-#define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val,    \
-                                arg2_name, arg2_val)                    \
-  cef_trace_event_begin(category, name, arg1_name, arg1_val, arg2_name, \
-                        arg2_val, true)
+                        arg2_val)
 
-// Records a single END event for "name" immediately. If the category
-// is not enabled, then this does nothing.
-// - category and name strings must have application lifetime (statics or
-//   literals). They may not include " chars.
+///
+/// Records a single END event for "name" immediately. If the category
+/// is not enabled, then this does nothing.
+/// - category and name strings must have application lifetime (statics or
+///   literals). They may not include " chars.
+///
 #define TRACE_EVENT_END0(category, name) \
-  cef_trace_event_end(category, name, NULL, 0, NULL, 0, false)
+  cef_trace_event_end(category, name, NULL, 0, NULL, 0)
 #define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \
-  cef_trace_event_end(category, name, arg1_name, arg1_val, NULL, 0, false)
+  cef_trace_event_end(category, name, arg1_name, arg1_val, NULL, 0)
 #define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, arg2_name, \
                          arg2_val)                                       \
-  cef_trace_event_end(category, name, arg1_name, arg1_val, arg2_name,    \
-                      arg2_val, false)
-#define TRACE_EVENT_COPY_END0(category, name) \
-  cef_trace_event_end(category, name, NULL, 0, NULL, 0, true)
-#define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \
-  cef_trace_event_end(category, name, arg1_name, arg1_val, NULL, 0, true)
-#define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, arg2_name, \
-                              arg2_val)                                       \
-  cef_trace_event_end(category, name, arg1_name, arg1_val, arg2_name,         \
-                      arg2_val, true)
+  cef_trace_event_end(category, name, arg1_name, arg1_val, arg2_name, arg2_val)
 
-// Records the value of a counter called "name" immediately. Value
-// must be representable as a 32 bit integer.
-// - category and name strings must have application lifetime (statics or
-//   literals). They may not include " chars.
+///
+/// Records the value of a counter called "name" immediately. Value
+/// must be representable as a 32 bit integer.
+/// - category and name strings must have application lifetime (statics or
+///   literals). They may not include " chars.
+///
 #define TRACE_COUNTER1(category, name, value) \
-  cef_trace_counter(category, name, NULL, value, NULL, 0, false)
-#define TRACE_COPY_COUNTER1(category, name, value) \
-  cef_trace_counter(category, name, NULL, value, NULL, 0, true)
+  cef_trace_counter(category, name, NULL, value, NULL, 0)
 
-// Records the values of a multi-parted counter called "name" immediately.
-// The UI will treat value1 and value2 as parts of a whole, displaying their
-// values as a stacked-bar chart.
-// - category and name strings must have application lifetime (statics or
-//   literals). They may not include " chars.
+///
+/// Records the values of a multi-parted counter called "name" immediately.
+/// The UI will treat value1 and value2 as parts of a whole, displaying their
+/// values as a stacked-bar chart.
+/// - category and name strings must have application lifetime (statics or
+///   literals). They may not include " chars.
+///
 #define TRACE_COUNTER2(category, name, value1_name, value1_val, value2_name, \
                        value2_val)                                           \
   cef_trace_counter(category, name, value1_name, value1_val, value2_name,    \
-                    value2_val, false)
-#define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val,      \
-                            value2_name, value2_val)                      \
-  cef_trace_counter(category, name, value1_name, value1_val, value2_name, \
-                    value2_val, true)
+                    value2_val)
 
-// Records the value of a counter called "name" immediately. Value
-// must be representable as a 32 bit integer.
-// - category and name strings must have application lifetime (statics or
-//   literals). They may not include " chars.
-// - |id| is used to disambiguate counters with the same name. It must either
-//   be a pointer or an integer value up to 64 bits. If it's a pointer, the
-//   bits will be xored with a hash of the process ID so that the same pointer
-//   on two different processes will not collide.
+///
+/// Records the value of a counter called "name" immediately. Value
+/// must be representable as a 32 bit integer.
+/// - category and name strings must have application lifetime (statics or
+///   literals). They may not include " chars.
+/// - |id| is used to disambiguate counters with the same name. It must either
+///   be a pointer or an integer value up to 64 bits. If it's a pointer, the
+///   bits will be xored with a hash of the process ID so that the same pointer
+///   on two different processes will not collide.
+///
 #define TRACE_COUNTER_ID1(category, name, id, value) \
-  cef_trace_counter_id(category, name, id, NULL, value, NULL, 0, false)
-#define TRACE_COPY_COUNTER_ID1(category, name, id, value) \
-  cef_trace_counter_id(category, name, id, NULL, value, NULL, 0, true)
+  cef_trace_counter_id(category, name, id, NULL, value, NULL, 0)
 
-// Records the values of a multi-parted counter called "name" immediately.
-// The UI will treat value1 and value2 as parts of a whole, displaying their
-// values as a stacked-bar chart.
-// - category and name strings must have application lifetime (statics or
-//   literals). They may not include " chars.
-// - |id| is used to disambiguate counters with the same name. It must either
-//   be a pointer or an integer value up to 64 bits. If it's a pointer, the
-//   bits will be xored with a hash of the process ID so that the same pointer
-//   on two different processes will not collide.
+///
+/// Records the values of a multi-parted counter called "name" immediately.
+/// The UI will treat value1 and value2 as parts of a whole, displaying their
+/// values as a stacked-bar chart.
+/// - category and name strings must have application lifetime (statics or
+///   literals). They may not include " chars.
+/// - |id| is used to disambiguate counters with the same name. It must either
+///   be a pointer or an integer value up to 64 bits. If it's a pointer, the
+///   bits will be xored with a hash of the process ID so that the same pointer
+///   on two different processes will not collide.
+///
 #define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \
                           value2_name, value2_val)                     \
   cef_trace_counter_id(category, name, id, value1_name, value1_val,    \
-                       value2_name, value2_val, false)
-#define TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, value1_val, \
-                               value2_name, value2_val)                     \
-  cef_trace_counter_id(category, name, id, value1_name, value1_val,         \
-                       value2_name, value2_val, true)
+                       value2_name, value2_val)
 
-// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2
-// associated arguments. If the category is not enabled, then this
-// does nothing.
-// - category and name strings must have application lifetime (statics or
-//   literals). They may not include " chars.
-// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event.
-//   ASYNC events are considered to match if their category, name and id values
-//   all match. |id| must either be a pointer or an integer value up to 64
-//   bits. If it's a pointer, the bits will be xored with a hash of the process
-//   ID sothat the same pointer on two different processes will not collide.
-// An asynchronous operation can consist of multiple phases. The first phase is
-// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the
-// ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END.
-// An async operation can span threads and processes, but all events in that
-// operation must use the same |name| and |id|. Each event can have its own
-// args.
+///
+/// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2
+/// associated arguments. If the category is not enabled, then this
+/// does nothing.
+/// - category and name strings must have application lifetime (statics or
+///   literals). They may not include " chars.
+/// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event.
+///   ASYNC events are considered to match if their category, name and id values
+///   all match. |id| must either be a pointer or an integer value up to 64
+///   bits. If it's a pointer, the bits will be xored with a hash of the process
+///   ID sothat the same pointer on two different processes will not collide.
+/// An asynchronous operation can consist of multiple phases. The first phase is
+/// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the
+/// ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END.
+/// An async operation can span threads and processes, but all events in that
+/// operation must use the same |name| and |id|. Each event can have its own
+/// args.
+///
 #define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \
-  cef_trace_event_async_begin(category, name, id, NULL, 0, NULL, 0, false)
-#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val)    \
-  cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, NULL, \
-                              0, false)
+  cef_trace_event_async_begin(category, name, id, NULL, 0, NULL, 0)
+#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
+  cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, NULL, 0)
 #define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
                                  arg2_name, arg2_val)                     \
   cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val,    \
-                              arg2_name, arg2_val, false)
-#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \
-  cef_trace_event_async_begin(category, name, id, NULL, 0, NULL, 0, true)
-#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
-  cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, NULL,   \
-                              0, true)
-#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
-                                      arg2_name, arg2_val)                     \
-  cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val,         \
-                              arg2_name, arg2_val, true)
+                              arg2_name, arg2_val)
 
-// Records a single ASYNC_STEP_INTO event for |step| immediately. If the
-// category is not enabled, then this does nothing. The |name| and |id| must
-// match the ASYNC_BEGIN event above. The |step| param identifies this step
-// within the async event. This should be called at the beginning of the next
-// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any
-// ASYNC_STEP_PAST events.
+///
+/// Records a single ASYNC_STEP_INTO event for |step| immediately. If the
+/// category is not enabled, then this does nothing. The |name| and |id| must
+/// match the ASYNC_BEGIN event above. The |step| param identifies this step
+/// within the async event. This should be called at the beginning of the next
+/// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any
+/// ASYNC_STEP_PAST events.
+///
 #define TRACE_EVENT_ASYNC_STEP_INTO0(category, name, id, step) \
-  cef_trace_event_async_step_into(category, name, id, step, NULL, 0, false)
+  cef_trace_event_async_step_into(category, name, id, step, NULL, 0)
 #define TRACE_EVENT_ASYNC_STEP_INTO1(category, name, id, step, arg1_name, \
                                      arg1_val)                            \
-  cef_trace_event_async_step_into(category, name, id, step, arg1_name,    \
-                                  arg1_val, false)
-#define TRACE_EVENT_COPY_ASYNC_STEP_INTO0(category, name, id, step) \
-  cef_trace_event_async_step_into(category, name, id, step, NULL, 0, true)
-#define TRACE_EVENT_COPY_ASYNC_STEP_INTO1(category, name, id, step, arg1_name, \
-                                          arg1_val)                            \
-  cef_trace_event_async_step_into(category, name, id, step, arg1_name,         \
-                                  arg1_val, true)
+  cef_trace_event_async_step_into(category, name, id, step, arg1_name, arg1_val)
 
-// Records a single ASYNC_STEP_PAST event for |step| immediately. If the
-// category is not enabled, then this does nothing. The |name| and |id| must
-// match the ASYNC_BEGIN event above. The |step| param identifies this step
-// within the async event. This should be called at the beginning of the next
-// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any
-// ASYNC_STEP_INTO events.
+///
+/// Records a single ASYNC_STEP_PAST event for |step| immediately. If the
+/// category is not enabled, then this does nothing. The |name| and |id| must
+/// match the ASYNC_BEGIN event above. The |step| param identifies this step
+/// within the async event. This should be called at the beginning of the next
+/// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any
+/// ASYNC_STEP_INTO events.
+///
 #define TRACE_EVENT_ASYNC_STEP_PAST0(category, name, id, step) \
-  cef_trace_event_async_step_past(category, name, id, step, NULL, 0, false)
+  cef_trace_event_async_step_past(category, name, id, step, NULL, 0)
 #define TRACE_EVENT_ASYNC_STEP_PAST1(category, name, id, step, arg1_name, \
                                      arg1_val)                            \
-  cef_trace_event_async_step_past(category, name, id, step, arg1_name,    \
-                                  arg1_val, false)
-#define TRACE_EVENT_COPY_ASYNC_STEP_PAST0(category, name, id, step) \
-  cef_trace_event_async_step_past(category, name, id, step, NULL, 0, true)
-#define TRACE_EVENT_COPY_ASYNC_STEP_PAST1(category, name, id, step, arg1_name, \
-                                          arg1_val)                            \
-  cef_trace_event_async_step_past(category, name, id, step, arg1_name,         \
-                                  arg1_val, true)
+  cef_trace_event_async_step_past(category, name, id, step, arg1_name, arg1_val)
 
-// Records a single ASYNC_END event for "name" immediately. If the category
-// is not enabled, then this does nothing.
+///
+/// Records a single ASYNC_END event for "name" immediately. If the category
+/// is not enabled, then this does nothing.
+///
 #define TRACE_EVENT_ASYNC_END0(category, name, id) \
-  cef_trace_event_async_end(category, name, id, NULL, 0, NULL, 0, false)
-#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val)       \
-  cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, NULL, 0, \
-                            false)
+  cef_trace_event_async_end(category, name, id, NULL, 0, NULL, 0)
+#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
+  cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, NULL, 0)
 #define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
                                arg2_name, arg2_val)                     \
   cef_trace_event_async_end(category, name, id, arg1_name, arg1_val,    \
-                            arg2_name, arg2_val, false)
-#define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \
-  cef_trace_event_async_end(category, name, id, NULL, 0, NULL, 0, true)
-#define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, arg1_val)  \
-  cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, NULL, 0, \
-                            true)
-#define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
-                                    arg2_name, arg2_val)                     \
-  cef_trace_event_async_end(category, name, id, arg1_name, arg1_val,         \
-                            arg2_name, arg2_val, true)
+                            arg2_name, arg2_val)
 
 namespace cef_trace_event {
 
-// Used by TRACE_EVENTx macro. Do not use directly.
+///
+/// Used by TRACE_EVENTx macro. Do not use directly.
+///
 class CefTraceEndOnScopeClose {
  public:
   CefTraceEndOnScopeClose(const char* category, const char* name)
       : category_(category), name_(name) {}
   ~CefTraceEndOnScopeClose() {
-    cef_trace_event_end(category_, name_, NULL, 0, NULL, 0, false);
+    cef_trace_event_end(category_, name_, NULL, 0, NULL, 0);
   }
 
  private:
@@ -413,7 +377,7 @@
   const char* name_;
 };
 
-}  // cef_trace_event
+}  // namespace cef_trace_event
 
 #endif  // !USING_CHROMIUM_INCLUDES
 
diff --git a/src/include/base/cef_tuple.h b/src/include/base/cef_tuple.h
index aeb6e9c..ae438d3 100644
--- a/src/include/base/cef_tuple.h
+++ b/src/include/base/cef_tuple.h
@@ -28,40 +28,36 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// A Tuple is a generic templatized container, similar in concept to std::pair.
-// There are classes Tuple0 to Tuple6, cooresponding to the number of elements
-// it contains.  The convenient MakeTuple() function takes 0 to 6 arguments,
-// and will construct and return the appropriate Tuple object.  The functions
-// DispatchToMethod and DispatchToFunction take a function pointer or instance
-// and method pointer, and unpack a tuple into arguments to the call.
-//
-// Tuple elements are copied by value, and stored in the tuple.  See the unit
-// tests for more details of how/when the values are copied.
-//
-// Example usage:
-//   // These two methods of creating a Tuple are identical.
-//   Tuple2<int, const char*> tuple_a(1, "wee");
-//   Tuple2<int, const char*> tuple_b = MakeTuple(1, "wee");
-//
-//   void SomeFunc(int a, const char* b) { }
-//   DispatchToFunction(&SomeFunc, tuple_a);  // SomeFunc(1, "wee")
-//   DispatchToFunction(
-//       &SomeFunc, MakeTuple(10, "foo"));    // SomeFunc(10, "foo")
-//
-//   struct { void SomeMeth(int a, int b, int c) { } } foo;
-//   DispatchToMethod(&foo, &Foo::SomeMeth, MakeTuple(1, 2, 3));
-//   // foo->SomeMeth(1, 2, 3);
+///
+/// \file
+/// Use std::tuple as tuple type. This file contains helper functions for
+/// working with std::tuples.
+/// The functions DispatchToMethod and DispatchToFunction take a function
+/// pointer or instance and method pointer, and unpack a tuple into arguments to
+/// the call.
+///
+/// Example usage:
+/// <pre>
+///   // These two methods of creating a Tuple are identical.
+///   std::tuple<int, const char*> tuple_a(1, "wee");
+///   std::tuple<int, const char*> tuple_b = std::make_tuple(1, "wee");
+///
+///   void SomeFunc(int a, const char* b) { }
+///   DispatchToFunction(&SomeFunc, tuple_a);  // SomeFunc(1, "wee")
+///   DispatchToFunction(
+///       &SomeFunc, std::make_tuple(10, "foo"));    // SomeFunc(10, "foo")
+///
+///   struct { void SomeMeth(int a, int b, int c) { } } foo;
+///   DispatchToMethod(&foo, &Foo::SomeMeth, std::make_tuple(1, 2, 3));
+///   // foo->SomeMeth(1, 2, 3);
+/// </pre>
+///
 
 #ifndef CEF_INCLUDE_BASE_CEF_TUPLE_H_
 #define CEF_INCLUDE_BASE_CEF_TUPLE_H_
 #pragma once
 
-#if defined(BASE_TUPLE_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
+#if defined(USING_CHROMIUM_INCLUDES)
 // When building CEF include the Chromium header directly.
 #include "base/tuple.h"
 #else  // !USING_CHROMIUM_INCLUDES
@@ -69,559 +65,14 @@
 // If the Chromium implementation diverges the below implementation should be
 // updated to match.
 
-#include "include/base/cef_bind_helpers.h"
+#include <stddef.h>
+#include <tuple>
+#include <utility>
+
+#include "include/base/cef_build.h"
 
 namespace base {
 
-// Traits ----------------------------------------------------------------------
-//
-// A simple traits class for tuple arguments.
-//
-// ValueType: the bare, nonref version of a type (same as the type for nonrefs).
-// RefType: the ref version of a type (same as the type for refs).
-// ParamType: what type to pass to functions (refs should not be constified).
-
-template <class P>
-struct TupleTraits {
-  typedef P ValueType;
-  typedef P& RefType;
-  typedef const P& ParamType;
-};
-
-template <class P>
-struct TupleTraits<P&> {
-  typedef P ValueType;
-  typedef P& RefType;
-  typedef P& ParamType;
-};
-
-template <class P>
-struct TupleTypes {};
-
-// Tuple -----------------------------------------------------------------------
-//
-// This set of classes is useful for bundling 0 or more heterogeneous data types
-// into a single variable.  The advantage of this is that it greatly simplifies
-// function objects that need to take an arbitrary number of parameters; see
-// RunnableMethod and IPC::MessageWithTuple.
-//
-// Tuple0 is supplied to act as a 'void' type.  It can be used, for example,
-// when dispatching to a function that accepts no arguments (see the
-// Dispatchers below).
-// Tuple1<A> is rarely useful.  One such use is when A is non-const ref that you
-// want filled by the dispatchee, and the tuple is merely a container for that
-// output (a "tier").  See MakeRefTuple and its usages.
-
-struct Tuple0 {
-  typedef Tuple0 ValueTuple;
-  typedef Tuple0 RefTuple;
-  typedef Tuple0 ParamTuple;
-};
-
-template <class A>
-struct Tuple1 {
- public:
-  typedef A TypeA;
-
-  Tuple1() {}
-  explicit Tuple1(typename TupleTraits<A>::ParamType a) : a(a) {}
-
-  A a;
-};
-
-template <class A, class B>
-struct Tuple2 {
- public:
-  typedef A TypeA;
-  typedef B TypeB;
-
-  Tuple2() {}
-  Tuple2(typename TupleTraits<A>::ParamType a,
-         typename TupleTraits<B>::ParamType b)
-      : a(a), b(b) {}
-
-  A a;
-  B b;
-};
-
-template <class A, class B, class C>
-struct Tuple3 {
- public:
-  typedef A TypeA;
-  typedef B TypeB;
-  typedef C TypeC;
-
-  Tuple3() {}
-  Tuple3(typename TupleTraits<A>::ParamType a,
-         typename TupleTraits<B>::ParamType b,
-         typename TupleTraits<C>::ParamType c)
-      : a(a), b(b), c(c) {}
-
-  A a;
-  B b;
-  C c;
-};
-
-template <class A, class B, class C, class D>
-struct Tuple4 {
- public:
-  typedef A TypeA;
-  typedef B TypeB;
-  typedef C TypeC;
-  typedef D TypeD;
-
-  Tuple4() {}
-  Tuple4(typename TupleTraits<A>::ParamType a,
-         typename TupleTraits<B>::ParamType b,
-         typename TupleTraits<C>::ParamType c,
-         typename TupleTraits<D>::ParamType d)
-      : a(a), b(b), c(c), d(d) {}
-
-  A a;
-  B b;
-  C c;
-  D d;
-};
-
-template <class A, class B, class C, class D, class E>
-struct Tuple5 {
- public:
-  typedef A TypeA;
-  typedef B TypeB;
-  typedef C TypeC;
-  typedef D TypeD;
-  typedef E TypeE;
-
-  Tuple5() {}
-  Tuple5(typename TupleTraits<A>::ParamType a,
-         typename TupleTraits<B>::ParamType b,
-         typename TupleTraits<C>::ParamType c,
-         typename TupleTraits<D>::ParamType d,
-         typename TupleTraits<E>::ParamType e)
-      : a(a), b(b), c(c), d(d), e(e) {}
-
-  A a;
-  B b;
-  C c;
-  D d;
-  E e;
-};
-
-template <class A, class B, class C, class D, class E, class F>
-struct Tuple6 {
- public:
-  typedef A TypeA;
-  typedef B TypeB;
-  typedef C TypeC;
-  typedef D TypeD;
-  typedef E TypeE;
-  typedef F TypeF;
-
-  Tuple6() {}
-  Tuple6(typename TupleTraits<A>::ParamType a,
-         typename TupleTraits<B>::ParamType b,
-         typename TupleTraits<C>::ParamType c,
-         typename TupleTraits<D>::ParamType d,
-         typename TupleTraits<E>::ParamType e,
-         typename TupleTraits<F>::ParamType f)
-      : a(a), b(b), c(c), d(d), e(e), f(f) {}
-
-  A a;
-  B b;
-  C c;
-  D d;
-  E e;
-  F f;
-};
-
-template <class A, class B, class C, class D, class E, class F, class G>
-struct Tuple7 {
- public:
-  typedef A TypeA;
-  typedef B TypeB;
-  typedef C TypeC;
-  typedef D TypeD;
-  typedef E TypeE;
-  typedef F TypeF;
-  typedef G TypeG;
-
-  Tuple7() {}
-  Tuple7(typename TupleTraits<A>::ParamType a,
-         typename TupleTraits<B>::ParamType b,
-         typename TupleTraits<C>::ParamType c,
-         typename TupleTraits<D>::ParamType d,
-         typename TupleTraits<E>::ParamType e,
-         typename TupleTraits<F>::ParamType f,
-         typename TupleTraits<G>::ParamType g)
-      : a(a), b(b), c(c), d(d), e(e), f(f), g(g) {}
-
-  A a;
-  B b;
-  C c;
-  D d;
-  E e;
-  F f;
-  G g;
-};
-
-template <class A,
-          class B,
-          class C,
-          class D,
-          class E,
-          class F,
-          class G,
-          class H>
-struct Tuple8 {
- public:
-  typedef A TypeA;
-  typedef B TypeB;
-  typedef C TypeC;
-  typedef D TypeD;
-  typedef E TypeE;
-  typedef F TypeF;
-  typedef G TypeG;
-  typedef H TypeH;
-
-  Tuple8() {}
-  Tuple8(typename TupleTraits<A>::ParamType a,
-         typename TupleTraits<B>::ParamType b,
-         typename TupleTraits<C>::ParamType c,
-         typename TupleTraits<D>::ParamType d,
-         typename TupleTraits<E>::ParamType e,
-         typename TupleTraits<F>::ParamType f,
-         typename TupleTraits<G>::ParamType g,
-         typename TupleTraits<H>::ParamType h)
-      : a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h) {}
-
-  A a;
-  B b;
-  C c;
-  D d;
-  E e;
-  F f;
-  G g;
-  H h;
-};
-
-// Tuple types ----------------------------------------------------------------
-//
-// Allows for selection of ValueTuple/RefTuple/ParamTuple without needing the
-// definitions of class types the tuple takes as parameters.
-
-template <>
-struct TupleTypes<Tuple0> {
-  typedef Tuple0 ValueTuple;
-  typedef Tuple0 RefTuple;
-  typedef Tuple0 ParamTuple;
-};
-
-template <class A>
-struct TupleTypes<Tuple1<A>> {
-  typedef Tuple1<typename TupleTraits<A>::ValueType> ValueTuple;
-  typedef Tuple1<typename TupleTraits<A>::RefType> RefTuple;
-  typedef Tuple1<typename TupleTraits<A>::ParamType> ParamTuple;
-};
-
-template <class A, class B>
-struct TupleTypes<Tuple2<A, B>> {
-  typedef Tuple2<typename TupleTraits<A>::ValueType,
-                 typename TupleTraits<B>::ValueType>
-      ValueTuple;
-  typedef Tuple2<typename TupleTraits<A>::RefType,
-                 typename TupleTraits<B>::RefType>
-      RefTuple;
-  typedef Tuple2<typename TupleTraits<A>::ParamType,
-                 typename TupleTraits<B>::ParamType>
-      ParamTuple;
-};
-
-template <class A, class B, class C>
-struct TupleTypes<Tuple3<A, B, C>> {
-  typedef Tuple3<typename TupleTraits<A>::ValueType,
-                 typename TupleTraits<B>::ValueType,
-                 typename TupleTraits<C>::ValueType>
-      ValueTuple;
-  typedef Tuple3<typename TupleTraits<A>::RefType,
-                 typename TupleTraits<B>::RefType,
-                 typename TupleTraits<C>::RefType>
-      RefTuple;
-  typedef Tuple3<typename TupleTraits<A>::ParamType,
-                 typename TupleTraits<B>::ParamType,
-                 typename TupleTraits<C>::ParamType>
-      ParamTuple;
-};
-
-template <class A, class B, class C, class D>
-struct TupleTypes<Tuple4<A, B, C, D>> {
-  typedef Tuple4<typename TupleTraits<A>::ValueType,
-                 typename TupleTraits<B>::ValueType,
-                 typename TupleTraits<C>::ValueType,
-                 typename TupleTraits<D>::ValueType>
-      ValueTuple;
-  typedef Tuple4<typename TupleTraits<A>::RefType,
-                 typename TupleTraits<B>::RefType,
-                 typename TupleTraits<C>::RefType,
-                 typename TupleTraits<D>::RefType>
-      RefTuple;
-  typedef Tuple4<typename TupleTraits<A>::ParamType,
-                 typename TupleTraits<B>::ParamType,
-                 typename TupleTraits<C>::ParamType,
-                 typename TupleTraits<D>::ParamType>
-      ParamTuple;
-};
-
-template <class A, class B, class C, class D, class E>
-struct TupleTypes<Tuple5<A, B, C, D, E>> {
-  typedef Tuple5<typename TupleTraits<A>::ValueType,
-                 typename TupleTraits<B>::ValueType,
-                 typename TupleTraits<C>::ValueType,
-                 typename TupleTraits<D>::ValueType,
-                 typename TupleTraits<E>::ValueType>
-      ValueTuple;
-  typedef Tuple5<typename TupleTraits<A>::RefType,
-                 typename TupleTraits<B>::RefType,
-                 typename TupleTraits<C>::RefType,
-                 typename TupleTraits<D>::RefType,
-                 typename TupleTraits<E>::RefType>
-      RefTuple;
-  typedef Tuple5<typename TupleTraits<A>::ParamType,
-                 typename TupleTraits<B>::ParamType,
-                 typename TupleTraits<C>::ParamType,
-                 typename TupleTraits<D>::ParamType,
-                 typename TupleTraits<E>::ParamType>
-      ParamTuple;
-};
-
-template <class A, class B, class C, class D, class E, class F>
-struct TupleTypes<Tuple6<A, B, C, D, E, F>> {
-  typedef Tuple6<typename TupleTraits<A>::ValueType,
-                 typename TupleTraits<B>::ValueType,
-                 typename TupleTraits<C>::ValueType,
-                 typename TupleTraits<D>::ValueType,
-                 typename TupleTraits<E>::ValueType,
-                 typename TupleTraits<F>::ValueType>
-      ValueTuple;
-  typedef Tuple6<typename TupleTraits<A>::RefType,
-                 typename TupleTraits<B>::RefType,
-                 typename TupleTraits<C>::RefType,
-                 typename TupleTraits<D>::RefType,
-                 typename TupleTraits<E>::RefType,
-                 typename TupleTraits<F>::RefType>
-      RefTuple;
-  typedef Tuple6<typename TupleTraits<A>::ParamType,
-                 typename TupleTraits<B>::ParamType,
-                 typename TupleTraits<C>::ParamType,
-                 typename TupleTraits<D>::ParamType,
-                 typename TupleTraits<E>::ParamType,
-                 typename TupleTraits<F>::ParamType>
-      ParamTuple;
-};
-
-template <class A, class B, class C, class D, class E, class F, class G>
-struct TupleTypes<Tuple7<A, B, C, D, E, F, G>> {
-  typedef Tuple7<typename TupleTraits<A>::ValueType,
-                 typename TupleTraits<B>::ValueType,
-                 typename TupleTraits<C>::ValueType,
-                 typename TupleTraits<D>::ValueType,
-                 typename TupleTraits<E>::ValueType,
-                 typename TupleTraits<F>::ValueType,
-                 typename TupleTraits<G>::ValueType>
-      ValueTuple;
-  typedef Tuple7<typename TupleTraits<A>::RefType,
-                 typename TupleTraits<B>::RefType,
-                 typename TupleTraits<C>::RefType,
-                 typename TupleTraits<D>::RefType,
-                 typename TupleTraits<E>::RefType,
-                 typename TupleTraits<F>::RefType,
-                 typename TupleTraits<G>::RefType>
-      RefTuple;
-  typedef Tuple7<typename TupleTraits<A>::ParamType,
-                 typename TupleTraits<B>::ParamType,
-                 typename TupleTraits<C>::ParamType,
-                 typename TupleTraits<D>::ParamType,
-                 typename TupleTraits<E>::ParamType,
-                 typename TupleTraits<F>::ParamType,
-                 typename TupleTraits<G>::ParamType>
-      ParamTuple;
-};
-
-template <class A,
-          class B,
-          class C,
-          class D,
-          class E,
-          class F,
-          class G,
-          class H>
-struct TupleTypes<Tuple8<A, B, C, D, E, F, G, H>> {
-  typedef Tuple8<typename TupleTraits<A>::ValueType,
-                 typename TupleTraits<B>::ValueType,
-                 typename TupleTraits<C>::ValueType,
-                 typename TupleTraits<D>::ValueType,
-                 typename TupleTraits<E>::ValueType,
-                 typename TupleTraits<F>::ValueType,
-                 typename TupleTraits<G>::ValueType,
-                 typename TupleTraits<H>::ValueType>
-      ValueTuple;
-  typedef Tuple8<typename TupleTraits<A>::RefType,
-                 typename TupleTraits<B>::RefType,
-                 typename TupleTraits<C>::RefType,
-                 typename TupleTraits<D>::RefType,
-                 typename TupleTraits<E>::RefType,
-                 typename TupleTraits<F>::RefType,
-                 typename TupleTraits<G>::RefType,
-                 typename TupleTraits<H>::RefType>
-      RefTuple;
-  typedef Tuple8<typename TupleTraits<A>::ParamType,
-                 typename TupleTraits<B>::ParamType,
-                 typename TupleTraits<C>::ParamType,
-                 typename TupleTraits<D>::ParamType,
-                 typename TupleTraits<E>::ParamType,
-                 typename TupleTraits<F>::ParamType,
-                 typename TupleTraits<G>::ParamType,
-                 typename TupleTraits<H>::ParamType>
-      ParamTuple;
-};
-
-// Tuple creators -------------------------------------------------------------
-//
-// Helper functions for constructing tuples while inferring the template
-// argument types.
-
-inline Tuple0 MakeTuple() {
-  return Tuple0();
-}
-
-template <class A>
-inline Tuple1<A> MakeTuple(const A& a) {
-  return Tuple1<A>(a);
-}
-
-template <class A, class B>
-inline Tuple2<A, B> MakeTuple(const A& a, const B& b) {
-  return Tuple2<A, B>(a, b);
-}
-
-template <class A, class B, class C>
-inline Tuple3<A, B, C> MakeTuple(const A& a, const B& b, const C& c) {
-  return Tuple3<A, B, C>(a, b, c);
-}
-
-template <class A, class B, class C, class D>
-inline Tuple4<A, B, C, D> MakeTuple(const A& a,
-                                    const B& b,
-                                    const C& c,
-                                    const D& d) {
-  return Tuple4<A, B, C, D>(a, b, c, d);
-}
-
-template <class A, class B, class C, class D, class E>
-inline Tuple5<A, B, C, D, E> MakeTuple(const A& a,
-                                       const B& b,
-                                       const C& c,
-                                       const D& d,
-                                       const E& e) {
-  return Tuple5<A, B, C, D, E>(a, b, c, d, e);
-}
-
-template <class A, class B, class C, class D, class E, class F>
-inline Tuple6<A, B, C, D, E, F> MakeTuple(const A& a,
-                                          const B& b,
-                                          const C& c,
-                                          const D& d,
-                                          const E& e,
-                                          const F& f) {
-  return Tuple6<A, B, C, D, E, F>(a, b, c, d, e, f);
-}
-
-template <class A, class B, class C, class D, class E, class F, class G>
-inline Tuple7<A, B, C, D, E, F, G> MakeTuple(const A& a,
-                                             const B& b,
-                                             const C& c,
-                                             const D& d,
-                                             const E& e,
-                                             const F& f,
-                                             const G& g) {
-  return Tuple7<A, B, C, D, E, F, G>(a, b, c, d, e, f, g);
-}
-
-template <class A,
-          class B,
-          class C,
-          class D,
-          class E,
-          class F,
-          class G,
-          class H>
-inline Tuple8<A, B, C, D, E, F, G, H> MakeTuple(const A& a,
-                                                const B& b,
-                                                const C& c,
-                                                const D& d,
-                                                const E& e,
-                                                const F& f,
-                                                const G& g,
-                                                const H& h) {
-  return Tuple8<A, B, C, D, E, F, G, H>(a, b, c, d, e, f, g, h);
-}
-
-// The following set of helpers make what Boost refers to as "Tiers" - a tuple
-// of references.
-
-template <class A>
-inline Tuple1<A&> MakeRefTuple(A& a) {
-  return Tuple1<A&>(a);
-}
-
-template <class A, class B>
-inline Tuple2<A&, B&> MakeRefTuple(A& a, B& b) {
-  return Tuple2<A&, B&>(a, b);
-}
-
-template <class A, class B, class C>
-inline Tuple3<A&, B&, C&> MakeRefTuple(A& a, B& b, C& c) {
-  return Tuple3<A&, B&, C&>(a, b, c);
-}
-
-template <class A, class B, class C, class D>
-inline Tuple4<A&, B&, C&, D&> MakeRefTuple(A& a, B& b, C& c, D& d) {
-  return Tuple4<A&, B&, C&, D&>(a, b, c, d);
-}
-
-template <class A, class B, class C, class D, class E>
-inline Tuple5<A&, B&, C&, D&, E&> MakeRefTuple(A& a, B& b, C& c, D& d, E& e) {
-  return Tuple5<A&, B&, C&, D&, E&>(a, b, c, d, e);
-}
-
-template <class A, class B, class C, class D, class E, class F>
-inline Tuple6<A&, B&, C&, D&, E&, F&> MakeRefTuple(A& a,
-                                                   B& b,
-                                                   C& c,
-                                                   D& d,
-                                                   E& e,
-                                                   F& f) {
-  return Tuple6<A&, B&, C&, D&, E&, F&>(a, b, c, d, e, f);
-}
-
-template <class A, class B, class C, class D, class E, class F, class G>
-inline Tuple7<A&, B&, C&, D&, E&, F&, G&>
-MakeRefTuple(A& a, B& b, C& c, D& d, E& e, F& f, G& g) {
-  return Tuple7<A&, B&, C&, D&, E&, F&, G&>(a, b, c, d, e, f, g);
-}
-
-template <class A,
-          class B,
-          class C,
-          class D,
-          class E,
-          class F,
-          class G,
-          class H>
-inline Tuple8<A&, B&, C&, D&, E&, F&, G&, H&>
-MakeRefTuple(A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h) {
-  return Tuple8<A&, B&, C&, D&, E&, F&, G&, H&>(a, b, c, d, e, f, g, h);
-}
-
 // Dispatchers ----------------------------------------------------------------
 //
 // Helper functions that call the given method on an object, with the unpacked
@@ -633,974 +84,65 @@
 
 // Non-Static Dispatchers with no out params.
 
-template <class ObjT, class Method>
-inline void DispatchToMethod(ObjT* obj, Method method, const Tuple0& arg) {
-  (obj->*method)();
+template <typename ObjT, typename Method, typename Tuple, size_t... Ns>
+inline void DispatchToMethodImpl(const ObjT& obj,
+                                 Method method,
+                                 Tuple&& args,
+                                 std::index_sequence<Ns...>) {
+  (obj->*method)(std::get<Ns>(std::forward<Tuple>(args))...);
 }
 
-template <class ObjT, class Method, class A>
-inline void DispatchToMethod(ObjT* obj, Method method, const A& arg) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg));
-}
-
-template <class ObjT, class Method, class A>
-inline void DispatchToMethod(ObjT* obj, Method method, const Tuple1<A>& arg) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a));
-}
-
-template <class ObjT, class Method, class A, class B>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple2<A, B>& arg) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-                 base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b));
-}
-
-template <class ObjT, class Method, class A, class B, class C>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple3<A, B, C>& arg) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-                 base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b),
-                 base::cef_internal::UnwrapTraits<C>::Unwrap(arg.c));
-}
-
-template <class ObjT, class Method, class A, class B, class C, class D>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple4<A, B, C, D>& arg) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-                 base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b),
-                 base::cef_internal::UnwrapTraits<C>::Unwrap(arg.c),
-                 base::cef_internal::UnwrapTraits<D>::Unwrap(arg.d));
-}
-
-template <class ObjT, class Method, class A, class B, class C, class D, class E>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple5<A, B, C, D, E>& arg) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-                 base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b),
-                 base::cef_internal::UnwrapTraits<C>::Unwrap(arg.c),
-                 base::cef_internal::UnwrapTraits<D>::Unwrap(arg.d),
-                 base::cef_internal::UnwrapTraits<E>::Unwrap(arg.e));
-}
-
-template <class ObjT,
-          class Method,
-          class A,
-          class B,
-          class C,
-          class D,
-          class E,
-          class F>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple6<A, B, C, D, E, F>& arg) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-                 base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b),
-                 base::cef_internal::UnwrapTraits<C>::Unwrap(arg.c),
-                 base::cef_internal::UnwrapTraits<D>::Unwrap(arg.d),
-                 base::cef_internal::UnwrapTraits<E>::Unwrap(arg.e),
-                 base::cef_internal::UnwrapTraits<F>::Unwrap(arg.f));
-}
-
-template <class ObjT,
-          class Method,
-          class A,
-          class B,
-          class C,
-          class D,
-          class E,
-          class F,
-          class G>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple7<A, B, C, D, E, F, G>& arg) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-                 base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b),
-                 base::cef_internal::UnwrapTraits<C>::Unwrap(arg.c),
-                 base::cef_internal::UnwrapTraits<D>::Unwrap(arg.d),
-                 base::cef_internal::UnwrapTraits<E>::Unwrap(arg.e),
-                 base::cef_internal::UnwrapTraits<F>::Unwrap(arg.f),
-                 base::cef_internal::UnwrapTraits<G>::Unwrap(arg.g));
-}
-
-template <class ObjT,
-          class Method,
-          class A,
-          class B,
-          class C,
-          class D,
-          class E,
-          class F,
-          class G,
-          class H>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple8<A, B, C, D, E, F, G, H>& arg) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-                 base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b),
-                 base::cef_internal::UnwrapTraits<C>::Unwrap(arg.c),
-                 base::cef_internal::UnwrapTraits<D>::Unwrap(arg.d),
-                 base::cef_internal::UnwrapTraits<E>::Unwrap(arg.e),
-                 base::cef_internal::UnwrapTraits<F>::Unwrap(arg.f),
-                 base::cef_internal::UnwrapTraits<G>::Unwrap(arg.g),
-                 base::cef_internal::UnwrapTraits<H>::Unwrap(arg.h));
+template <typename ObjT, typename Method, typename Tuple>
+inline void DispatchToMethod(const ObjT& obj, Method method, Tuple&& args) {
+  constexpr size_t size = std::tuple_size<std::decay_t<Tuple>>::value;
+  DispatchToMethodImpl(obj, method, std::forward<Tuple>(args),
+                       std::make_index_sequence<size>());
 }
 
 // Static Dispatchers with no out params.
 
-template <class Function>
-inline void DispatchToFunction(Function function, const Tuple0& arg) {
-  (*function)();
+template <typename Function, typename Tuple, size_t... Ns>
+inline void DispatchToFunctionImpl(Function function,
+                                   Tuple&& args,
+                                   std::index_sequence<Ns...>) {
+  (*function)(std::get<Ns>(std::forward<Tuple>(args))...);
 }
 
-template <class Function, class A>
-inline void DispatchToFunction(Function function, const A& arg) {
-  (*function)(arg);
+template <typename Function, typename Tuple>
+inline void DispatchToFunction(Function function, Tuple&& args) {
+  constexpr size_t size = std::tuple_size<std::decay_t<Tuple>>::value;
+  DispatchToFunctionImpl(function, std::forward<Tuple>(args),
+                         std::make_index_sequence<size>());
 }
 
-template <class Function, class A>
-inline void DispatchToFunction(Function function, const Tuple1<A>& arg) {
-  (*function)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a));
+// Dispatchers with out parameters.
+
+template <typename ObjT,
+          typename Method,
+          typename InTuple,
+          typename OutTuple,
+          size_t... InNs,
+          size_t... OutNs>
+inline void DispatchToMethodImpl(const ObjT& obj,
+                                 Method method,
+                                 InTuple&& in,
+                                 OutTuple* out,
+                                 std::index_sequence<InNs...>,
+                                 std::index_sequence<OutNs...>) {
+  (obj->*method)(std::get<InNs>(std::forward<InTuple>(in))...,
+                 &std::get<OutNs>(*out)...);
 }
 
-template <class Function, class A, class B>
-inline void DispatchToFunction(Function function, const Tuple2<A, B>& arg) {
-  (*function)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-              base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b));
-}
-
-template <class Function, class A, class B, class C>
-inline void DispatchToFunction(Function function, const Tuple3<A, B, C>& arg) {
-  (*function)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-              base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b),
-              base::cef_internal::UnwrapTraits<C>::Unwrap(arg.c));
-}
-
-template <class Function, class A, class B, class C, class D>
-inline void DispatchToFunction(Function function,
-                               const Tuple4<A, B, C, D>& arg) {
-  (*function)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-              base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b),
-              base::cef_internal::UnwrapTraits<C>::Unwrap(arg.c),
-              base::cef_internal::UnwrapTraits<D>::Unwrap(arg.d));
-}
-
-template <class Function, class A, class B, class C, class D, class E>
-inline void DispatchToFunction(Function function,
-                               const Tuple5<A, B, C, D, E>& arg) {
-  (*function)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-              base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b),
-              base::cef_internal::UnwrapTraits<C>::Unwrap(arg.c),
-              base::cef_internal::UnwrapTraits<D>::Unwrap(arg.d),
-              base::cef_internal::UnwrapTraits<E>::Unwrap(arg.e));
-}
-
-template <class Function, class A, class B, class C, class D, class E, class F>
-inline void DispatchToFunction(Function function,
-                               const Tuple6<A, B, C, D, E, F>& arg) {
-  (*function)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-              base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b),
-              base::cef_internal::UnwrapTraits<C>::Unwrap(arg.c),
-              base::cef_internal::UnwrapTraits<D>::Unwrap(arg.d),
-              base::cef_internal::UnwrapTraits<E>::Unwrap(arg.e),
-              base::cef_internal::UnwrapTraits<F>::Unwrap(arg.f));
-}
-
-template <class Function,
-          class A,
-          class B,
-          class C,
-          class D,
-          class E,
-          class F,
-          class G>
-inline void DispatchToFunction(Function function,
-                               const Tuple7<A, B, C, D, E, F, G>& arg) {
-  (*function)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-              base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b),
-              base::cef_internal::UnwrapTraits<C>::Unwrap(arg.c),
-              base::cef_internal::UnwrapTraits<D>::Unwrap(arg.d),
-              base::cef_internal::UnwrapTraits<E>::Unwrap(arg.e),
-              base::cef_internal::UnwrapTraits<F>::Unwrap(arg.f),
-              base::cef_internal::UnwrapTraits<G>::Unwrap(arg.g));
-}
-
-template <class Function,
-          class A,
-          class B,
-          class C,
-          class D,
-          class E,
-          class F,
-          class G,
-          class H>
-inline void DispatchToFunction(Function function,
-                               const Tuple8<A, B, C, D, E, F, G, H>& arg) {
-  (*function)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-              base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b),
-              base::cef_internal::UnwrapTraits<C>::Unwrap(arg.c),
-              base::cef_internal::UnwrapTraits<D>::Unwrap(arg.d),
-              base::cef_internal::UnwrapTraits<E>::Unwrap(arg.e),
-              base::cef_internal::UnwrapTraits<F>::Unwrap(arg.f),
-              base::cef_internal::UnwrapTraits<G>::Unwrap(arg.g),
-              base::cef_internal::UnwrapTraits<H>::Unwrap(arg.h));
-}
-
-// Dispatchers with 0 out param (as a Tuple0).
-
-template <class ObjT, class Method>
-inline void DispatchToMethod(ObjT* obj,
+template <typename ObjT, typename Method, typename InTuple, typename OutTuple>
+inline void DispatchToMethod(const ObjT& obj,
                              Method method,
-                             const Tuple0& arg,
-                             Tuple0*) {
-  (obj->*method)();
-}
-
-template <class ObjT, class Method, class A>
-inline void DispatchToMethod(ObjT* obj, Method method, const A& arg, Tuple0*) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg));
-}
-
-template <class ObjT, class Method, class A>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple1<A>& arg,
-                             Tuple0*) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a));
-}
-
-template <class ObjT, class Method, class A, class B>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple2<A, B>& arg,
-                             Tuple0*) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-                 base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b));
-}
-
-template <class ObjT, class Method, class A, class B, class C>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple3<A, B, C>& arg,
-                             Tuple0*) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-                 base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b),
-                 base::cef_internal::UnwrapTraits<C>::Unwrap(arg.c));
-}
-
-template <class ObjT, class Method, class A, class B, class C, class D>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple4<A, B, C, D>& arg,
-                             Tuple0*) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-                 base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b),
-                 base::cef_internal::UnwrapTraits<C>::Unwrap(arg.c),
-                 base::cef_internal::UnwrapTraits<D>::Unwrap(arg.d));
-}
-
-template <class ObjT, class Method, class A, class B, class C, class D, class E>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple5<A, B, C, D, E>& arg,
-                             Tuple0*) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-                 base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b),
-                 base::cef_internal::UnwrapTraits<C>::Unwrap(arg.c),
-                 base::cef_internal::UnwrapTraits<D>::Unwrap(arg.d),
-                 base::cef_internal::UnwrapTraits<E>::Unwrap(arg.e));
-}
-
-template <class ObjT,
-          class Method,
-          class A,
-          class B,
-          class C,
-          class D,
-          class E,
-          class F>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple6<A, B, C, D, E, F>& arg,
-                             Tuple0*) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<A>::Unwrap(arg.a),
-                 base::cef_internal::UnwrapTraits<B>::Unwrap(arg.b),
-                 base::cef_internal::UnwrapTraits<C>::Unwrap(arg.c),
-                 base::cef_internal::UnwrapTraits<D>::Unwrap(arg.d),
-                 base::cef_internal::UnwrapTraits<E>::Unwrap(arg.e),
-                 base::cef_internal::UnwrapTraits<F>::Unwrap(arg.f));
-}
-
-// Dispatchers with 1 out param.
-
-template <class ObjT, class Method, class OutA>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple0& in,
-                             Tuple1<OutA>* out) {
-  (obj->*method)(&out->a);
-}
-
-template <class ObjT, class Method, class InA, class OutA>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const InA& in,
-                             Tuple1<OutA>* out) {
-  (obj->*method)(in, &out->a);
-}
-
-template <class ObjT, class Method, class InA, class OutA>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple1<InA>& in,
-                             Tuple1<OutA>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a), &out->a);
-}
-
-template <class ObjT, class Method, class InA, class InB, class OutA>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple2<InA, InB>& in,
-                             Tuple1<OutA>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b), &out->a);
-}
-
-template <class ObjT, class Method, class InA, class InB, class InC, class OutA>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple3<InA, InB, InC>& in,
-                             Tuple1<OutA>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c), &out->a);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class InD,
-          class OutA>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple4<InA, InB, InC, InD>& in,
-                             Tuple1<OutA>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c),
-                 base::cef_internal::UnwrapTraits<InD>::Unwrap(in.d), &out->a);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class InD,
-          class InE,
-          class OutA>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple5<InA, InB, InC, InD, InE>& in,
-                             Tuple1<OutA>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c),
-                 base::cef_internal::UnwrapTraits<InD>::Unwrap(in.d),
-                 base::cef_internal::UnwrapTraits<InE>::Unwrap(in.e), &out->a);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class InD,
-          class InE,
-          class InF,
-          class OutA>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple6<InA, InB, InC, InD, InE, InF>& in,
-                             Tuple1<OutA>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c),
-                 base::cef_internal::UnwrapTraits<InD>::Unwrap(in.d),
-                 base::cef_internal::UnwrapTraits<InE>::Unwrap(in.e),
-                 base::cef_internal::UnwrapTraits<InF>::Unwrap(in.f), &out->a);
-}
-
-// Dispatchers with 2 out params.
-
-template <class ObjT, class Method, class OutA, class OutB>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple0& in,
-                             Tuple2<OutA, OutB>* out) {
-  (obj->*method)(&out->a, &out->b);
-}
-
-template <class ObjT, class Method, class InA, class OutA, class OutB>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const InA& in,
-                             Tuple2<OutA, OutB>* out) {
-  (obj->*method)(in, &out->a, &out->b);
-}
-
-template <class ObjT, class Method, class InA, class OutA, class OutB>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple1<InA>& in,
-                             Tuple2<OutA, OutB>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a), &out->a,
-                 &out->b);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class OutA,
-          class OutB>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple2<InA, InB>& in,
-                             Tuple2<OutA, OutB>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b), &out->a,
-                 &out->b);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class OutA,
-          class OutB>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple3<InA, InB, InC>& in,
-                             Tuple2<OutA, OutB>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c), &out->a,
-                 &out->b);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class InD,
-          class OutA,
-          class OutB>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple4<InA, InB, InC, InD>& in,
-                             Tuple2<OutA, OutB>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c),
-                 base::cef_internal::UnwrapTraits<InD>::Unwrap(in.d), &out->a,
-                 &out->b);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class InD,
-          class InE,
-          class OutA,
-          class OutB>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple5<InA, InB, InC, InD, InE>& in,
-                             Tuple2<OutA, OutB>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c),
-                 base::cef_internal::UnwrapTraits<InD>::Unwrap(in.d),
-                 base::cef_internal::UnwrapTraits<InE>::Unwrap(in.e), &out->a,
-                 &out->b);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class InD,
-          class InE,
-          class InF,
-          class OutA,
-          class OutB>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple6<InA, InB, InC, InD, InE, InF>& in,
-                             Tuple2<OutA, OutB>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c),
-                 base::cef_internal::UnwrapTraits<InD>::Unwrap(in.d),
-                 base::cef_internal::UnwrapTraits<InE>::Unwrap(in.e),
-                 base::cef_internal::UnwrapTraits<InF>::Unwrap(in.f), &out->a,
-                 &out->b);
-}
-
-// Dispatchers with 3 out params.
-
-template <class ObjT, class Method, class OutA, class OutB, class OutC>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple0& in,
-                             Tuple3<OutA, OutB, OutC>* out) {
-  (obj->*method)(&out->a, &out->b, &out->c);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class OutA,
-          class OutB,
-          class OutC>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const InA& in,
-                             Tuple3<OutA, OutB, OutC>* out) {
-  (obj->*method)(in, &out->a, &out->b, &out->c);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class OutA,
-          class OutB,
-          class OutC>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple1<InA>& in,
-                             Tuple3<OutA, OutB, OutC>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a), &out->a,
-                 &out->b, &out->c);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class OutA,
-          class OutB,
-          class OutC>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple2<InA, InB>& in,
-                             Tuple3<OutA, OutB, OutC>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b), &out->a,
-                 &out->b, &out->c);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class OutA,
-          class OutB,
-          class OutC>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple3<InA, InB, InC>& in,
-                             Tuple3<OutA, OutB, OutC>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c), &out->a,
-                 &out->b, &out->c);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class InD,
-          class OutA,
-          class OutB,
-          class OutC>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple4<InA, InB, InC, InD>& in,
-                             Tuple3<OutA, OutB, OutC>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c),
-                 base::cef_internal::UnwrapTraits<InD>::Unwrap(in.d), &out->a,
-                 &out->b, &out->c);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class InD,
-          class InE,
-          class OutA,
-          class OutB,
-          class OutC>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple5<InA, InB, InC, InD, InE>& in,
-                             Tuple3<OutA, OutB, OutC>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c),
-                 base::cef_internal::UnwrapTraits<InD>::Unwrap(in.d),
-                 base::cef_internal::UnwrapTraits<InE>::Unwrap(in.e), &out->a,
-                 &out->b, &out->c);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class InD,
-          class InE,
-          class InF,
-          class OutA,
-          class OutB,
-          class OutC>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple6<InA, InB, InC, InD, InE, InF>& in,
-                             Tuple3<OutA, OutB, OutC>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c),
-                 base::cef_internal::UnwrapTraits<InD>::Unwrap(in.d),
-                 base::cef_internal::UnwrapTraits<InE>::Unwrap(in.e),
-                 base::cef_internal::UnwrapTraits<InF>::Unwrap(in.f), &out->a,
-                 &out->b, &out->c);
-}
-
-// Dispatchers with 4 out params.
-
-template <class ObjT,
-          class Method,
-          class OutA,
-          class OutB,
-          class OutC,
-          class OutD>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple0& in,
-                             Tuple4<OutA, OutB, OutC, OutD>* out) {
-  (obj->*method)(&out->a, &out->b, &out->c, &out->d);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class OutA,
-          class OutB,
-          class OutC,
-          class OutD>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const InA& in,
-                             Tuple4<OutA, OutB, OutC, OutD>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in), &out->a,
-                 &out->b, &out->c, &out->d);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class OutA,
-          class OutB,
-          class OutC,
-          class OutD>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple1<InA>& in,
-                             Tuple4<OutA, OutB, OutC, OutD>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a), &out->a,
-                 &out->b, &out->c, &out->d);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class OutA,
-          class OutB,
-          class OutC,
-          class OutD>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple2<InA, InB>& in,
-                             Tuple4<OutA, OutB, OutC, OutD>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b), &out->a,
-                 &out->b, &out->c, &out->d);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class OutA,
-          class OutB,
-          class OutC,
-          class OutD>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple3<InA, InB, InC>& in,
-                             Tuple4<OutA, OutB, OutC, OutD>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c), &out->a,
-                 &out->b, &out->c, &out->d);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class InD,
-          class OutA,
-          class OutB,
-          class OutC,
-          class OutD>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple4<InA, InB, InC, InD>& in,
-                             Tuple4<OutA, OutB, OutC, OutD>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c),
-                 base::cef_internal::UnwrapTraits<InD>::Unwrap(in.d), &out->a,
-                 &out->b, &out->c, &out->d);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class InD,
-          class InE,
-          class OutA,
-          class OutB,
-          class OutC,
-          class OutD>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple5<InA, InB, InC, InD, InE>& in,
-                             Tuple4<OutA, OutB, OutC, OutD>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c),
-                 base::cef_internal::UnwrapTraits<InD>::Unwrap(in.d),
-                 base::cef_internal::UnwrapTraits<InE>::Unwrap(in.e), &out->a,
-                 &out->b, &out->c, &out->d);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class InD,
-          class InE,
-          class InF,
-          class OutA,
-          class OutB,
-          class OutC,
-          class OutD>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple6<InA, InB, InC, InD, InE, InF>& in,
-                             Tuple4<OutA, OutB, OutC, OutD>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c),
-                 base::cef_internal::UnwrapTraits<InD>::Unwrap(in.d),
-                 base::cef_internal::UnwrapTraits<InE>::Unwrap(in.e),
-                 base::cef_internal::UnwrapTraits<InF>::Unwrap(in.f), &out->a,
-                 &out->b, &out->c, &out->d);
-}
-
-// Dispatchers with 5 out params.
-
-template <class ObjT,
-          class Method,
-          class OutA,
-          class OutB,
-          class OutC,
-          class OutD,
-          class OutE>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple0& in,
-                             Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
-  (obj->*method)(&out->a, &out->b, &out->c, &out->d, &out->e);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class OutA,
-          class OutB,
-          class OutC,
-          class OutD,
-          class OutE>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const InA& in,
-                             Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in), &out->a,
-                 &out->b, &out->c, &out->d, &out->e);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class OutA,
-          class OutB,
-          class OutC,
-          class OutD,
-          class OutE>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple1<InA>& in,
-                             Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a), &out->a,
-                 &out->b, &out->c, &out->d, &out->e);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class OutA,
-          class OutB,
-          class OutC,
-          class OutD,
-          class OutE>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple2<InA, InB>& in,
-                             Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b), &out->a,
-                 &out->b, &out->c, &out->d, &out->e);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class OutA,
-          class OutB,
-          class OutC,
-          class OutD,
-          class OutE>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple3<InA, InB, InC>& in,
-                             Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c), &out->a,
-                 &out->b, &out->c, &out->d, &out->e);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class InD,
-          class OutA,
-          class OutB,
-          class OutC,
-          class OutD,
-          class OutE>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple4<InA, InB, InC, InD>& in,
-                             Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c),
-                 base::cef_internal::UnwrapTraits<InD>::Unwrap(in.d), &out->a,
-                 &out->b, &out->c, &out->d, &out->e);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class InD,
-          class InE,
-          class OutA,
-          class OutB,
-          class OutC,
-          class OutD,
-          class OutE>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple5<InA, InB, InC, InD, InE>& in,
-                             Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c),
-                 base::cef_internal::UnwrapTraits<InD>::Unwrap(in.d),
-                 base::cef_internal::UnwrapTraits<InE>::Unwrap(in.e), &out->a,
-                 &out->b, &out->c, &out->d, &out->e);
-}
-
-template <class ObjT,
-          class Method,
-          class InA,
-          class InB,
-          class InC,
-          class InD,
-          class InE,
-          class InF,
-          class OutA,
-          class OutB,
-          class OutC,
-          class OutD,
-          class OutE>
-inline void DispatchToMethod(ObjT* obj,
-                             Method method,
-                             const Tuple6<InA, InB, InC, InD, InE, InF>& in,
-                             Tuple5<OutA, OutB, OutC, OutD, OutE>* out) {
-  (obj->*method)(base::cef_internal::UnwrapTraits<InA>::Unwrap(in.a),
-                 base::cef_internal::UnwrapTraits<InB>::Unwrap(in.b),
-                 base::cef_internal::UnwrapTraits<InC>::Unwrap(in.c),
-                 base::cef_internal::UnwrapTraits<InD>::Unwrap(in.d),
-                 base::cef_internal::UnwrapTraits<InE>::Unwrap(in.e),
-                 base::cef_internal::UnwrapTraits<InF>::Unwrap(in.f), &out->a,
-                 &out->b, &out->c, &out->d, &out->e);
+                             InTuple&& in,
+                             OutTuple* out) {
+  constexpr size_t in_size = std::tuple_size<std::decay_t<InTuple>>::value;
+  constexpr size_t out_size = std::tuple_size<OutTuple>::value;
+  DispatchToMethodImpl(obj, method, std::forward<InTuple>(in), out,
+                       std::make_index_sequence<in_size>(),
+                       std::make_index_sequence<out_size>());
 }
 
 }  // namespace base
diff --git a/src/include/base/cef_weak_ptr.h b/src/include/base/cef_weak_ptr.h
index 1ba34b9..2946689 100644
--- a/src/include/base/cef_weak_ptr.h
+++ b/src/include/base/cef_weak_ptr.h
@@ -28,80 +28,79 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Weak pointers are pointers to an object that do not affect its lifetime,
-// and which may be invalidated (i.e. reset to NULL) by the object, or its
-// owner, at any time, most commonly when the object is about to be deleted.
-
-// Weak pointers are useful when an object needs to be accessed safely by one
-// or more objects other than its owner, and those callers can cope with the
-// object vanishing and e.g. tasks posted to it being silently dropped.
-// Reference-counting such an object would complicate the ownership graph and
-// make it harder to reason about the object's lifetime.
-
-// EXAMPLE:
-//
-//  class Controller {
-//   public:
-//    Controller() : weak_factory_(this) {}
-//    void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); }
-//    void WorkComplete(const Result& result) { ... }
-//   private:
-//    // Member variables should appear before the WeakPtrFactory, to ensure
-//    // that any WeakPtrs to Controller are invalidated before its members
-//    // variable's destructors are executed, rendering them invalid.
-//    WeakPtrFactory<Controller> weak_factory_;
-//  };
-//
-//  class Worker {
-//   public:
-//    static void StartNew(const WeakPtr<Controller>& controller) {
-//      Worker* worker = new Worker(controller);
-//      // Kick off asynchronous processing...
-//    }
-//   private:
-//    Worker(const WeakPtr<Controller>& controller)
-//        : controller_(controller) {}
-//    void DidCompleteAsynchronousProcessing(const Result& result) {
-//      if (controller_)
-//        controller_->WorkComplete(result);
-//    }
-//    WeakPtr<Controller> controller_;
-//  };
-//
-// With this implementation a caller may use SpawnWorker() to dispatch multiple
-// Workers and subsequently delete the Controller, without waiting for all
-// Workers to have completed.
-
-// ------------------------- IMPORTANT: Thread-safety -------------------------
-
-// Weak pointers may be passed safely between threads, but must always be
-// dereferenced and invalidated on the same thread otherwise checking the
-// pointer would be racey.
-//
-// To ensure correct use, the first time a WeakPtr issued by a WeakPtrFactory
-// is dereferenced, the factory and its WeakPtrs become bound to the calling
-// thread, and cannot be dereferenced or invalidated on any other thread. Bound
-// WeakPtrs can still be handed off to other threads, e.g. to use to post tasks
-// back to object on the bound thread.
-//
-// If all WeakPtr objects are destroyed or invalidated then the factory is
-// unbound from the SequencedTaskRunner/Thread. The WeakPtrFactory may then be
-// destroyed, or new WeakPtr objects may be used, from a different sequence.
-//
-// Thus, at least one WeakPtr object must exist and have been dereferenced on
-// the correct thread to enforce that other WeakPtr objects will enforce they
-// are used on the desired thread.
+///
+/// \file
+/// Weak pointers are pointers to an object that do not affect its lifetime.
+/// They may be invalidated (i.e. reset to nullptr) by the object, or its
+/// owner, at any time, most commonly when the object is about to be deleted.
+///
+/// Weak pointers are useful when an object needs to be accessed safely by one
+/// or more objects other than its owner, and those callers can cope with the
+/// object vanishing and e.g. tasks posted to it being silently dropped.
+/// Reference-counting such an object would complicate the ownership graph and
+/// make it harder to reason about the object's lifetime.
+///
+/// EXAMPLE:
+///
+/// <pre>
+///  class Controller {
+///   public:
+///    void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); }
+///    void WorkComplete(const Result& result) { ... }
+///   private:
+///    // Member variables should appear before the WeakPtrFactory, to ensure
+///    // that any WeakPtrs to Controller are invalidated before its members
+///    // variable's destructors are executed, rendering them invalid.
+///    WeakPtrFactory<Controller> weak_factory_{this};
+///  };
+///
+///  class Worker {
+///   public:
+///    static void StartNew(WeakPtr<Controller> controller) {
+///      Worker* worker = new Worker(std::move(controller));
+///      // Kick off asynchronous processing...
+///    }
+///   private:
+///    Worker(WeakPtr<Controller> controller)
+///        : controller_(std::move(controller)) {}
+///    void DidCompleteAsynchronousProcessing(const Result& result) {
+///      if (controller_)
+///        controller_->WorkComplete(result);
+///    }
+///    WeakPtr<Controller> controller_;
+///  };
+/// </pre>
+///
+/// With this implementation a caller may use SpawnWorker() to dispatch multiple
+/// Workers and subsequently delete the Controller, without waiting for all
+/// Workers to have completed.
+///
+/// <b>IMPORTANT: Thread-safety</b>
+///
+/// Weak pointers may be passed safely between threads, but must always be
+/// dereferenced and invalidated on the same ThreaddTaskRunner otherwise
+/// checking the pointer would be racey.
+///
+/// To ensure correct use, the first time a WeakPtr issued by a WeakPtrFactory
+/// is dereferenced, the factory and its WeakPtrs become bound to the calling
+/// thread or current ThreaddWorkerPool token, and cannot be dereferenced or
+/// invalidated on any other task runner. Bound WeakPtrs can still be handed
+/// off to other task runners, e.g. to use to post tasks back to object on the
+/// bound thread.
+///
+/// If all WeakPtr objects are destroyed or invalidated then the factory is
+/// unbound from the ThreadedTaskRunner/Thread. The WeakPtrFactory may then be
+/// destroyed, or new WeakPtr objects may be used, from a different thread.
+///
+/// Thus, at least one WeakPtr object must exist and have been dereferenced on
+/// the correct thread to enforce that other WeakPtr objects will enforce they
+/// are used on the desired thread.
 
 #ifndef CEF_INCLUDE_BASE_CEF_WEAK_PTR_H_
 #define CEF_INCLUDE_BASE_CEF_WEAK_PTR_H_
 #pragma once
 
-#if defined(BASE_MEMORY_WEAK_PTR_H_)
-// Do nothing if the Chromium header has already been included.
-// This can happen in cases where Chromium code is used directly by the
-// client application. When using Chromium code directly always include
-// the Chromium header first to avoid type conflicts.
-#elif defined(USING_CHROMIUM_INCLUDES)
+#if defined(USING_CHROMIUM_INCLUDES)
 // When building CEF include the Chromium header directly.
 #include "base/memory/weak_ptr.h"
 #else  // !USING_CHROMIUM_INCLUDES
@@ -109,10 +108,12 @@
 // If the Chromium implementation diverges the below implementation should be
 // updated to match.
 
-#include "include/base/cef_basictypes.h"
+#include <cstddef>
+#include <type_traits>
+
+#include "include/base/cef_atomic_flag.h"
 #include "include/base/cef_logging.h"
 #include "include/base/cef_ref_counted.h"
-#include "include/base/cef_template_util.h"
 #include "include/base/cef_thread_checker.h"
 
 namespace base {
@@ -128,8 +129,8 @@
 
 class WeakReference {
  public:
-  // Although Flag is bound to a specific thread, it may be deleted from another
-  // via base::WeakPtr::~WeakPtr().
+  // Although Flag is bound to a specific ThreaddTaskRunner, it may be
+  // deleted from another via base::WeakPtr::~WeakPtr().
   class Flag : public RefCountedThreadSafe<Flag> {
    public:
     Flag();
@@ -137,23 +138,30 @@
     void Invalidate();
     bool IsValid() const;
 
+    bool MaybeValid() const;
+
+    void DetachFromThread();
+
    private:
     friend class base::RefCountedThreadSafe<Flag>;
 
     ~Flag();
 
-    // The current Chromium implementation uses SequenceChecker instead of
-    // ThreadChecker to support SequencedWorkerPools. CEF does not yet expose
-    // the concept of SequencedWorkerPools.
-    ThreadChecker thread_checker_;
-    bool is_valid_;
+    base::ThreadChecker thread_checker_;
+    AtomicFlag invalidated_;
   };
 
   WeakReference();
-  explicit WeakReference(const Flag* flag);
+  explicit WeakReference(const scoped_refptr<Flag>& flag);
   ~WeakReference();
 
-  bool is_valid() const;
+  WeakReference(WeakReference&& other) noexcept;
+  WeakReference(const WeakReference& other);
+  WeakReference& operator=(WeakReference&& other) noexcept = default;
+  WeakReference& operator=(const WeakReference& other) = default;
+
+  bool IsValid() const;
+  bool MaybeValid() const;
 
  private:
   scoped_refptr<const Flag> flag_;
@@ -166,12 +174,12 @@
 
   WeakReference GetRef() const;
 
-  bool HasRefs() const { return flag_.get() && !flag_->HasOneRef(); }
+  bool HasRefs() const { return !flag_->HasOneRef(); }
 
   void Invalidate();
 
  private:
-  mutable scoped_refptr<WeakReference::Flag> flag_;
+  scoped_refptr<WeakReference::Flag> flag_;
 };
 
 // This class simplifies the implementation of WeakPtr's type conversion
@@ -183,10 +191,24 @@
   WeakPtrBase();
   ~WeakPtrBase();
 
+  WeakPtrBase(const WeakPtrBase& other) = default;
+  WeakPtrBase(WeakPtrBase&& other) noexcept = default;
+  WeakPtrBase& operator=(const WeakPtrBase& other) = default;
+  WeakPtrBase& operator=(WeakPtrBase&& other) noexcept = default;
+
+  void reset() {
+    ref_ = cef_internal::WeakReference();
+    ptr_ = 0;
+  }
+
  protected:
-  explicit WeakPtrBase(const WeakReference& ref);
+  WeakPtrBase(const WeakReference& ref, uintptr_t ptr);
 
   WeakReference ref_;
+
+  // This pointer is only valid when ref_.is_valid() is true.  Otherwise, its
+  // value is undefined (as opposed to nullptr).
+  uintptr_t ptr_;
 };
 
 // This class provides a common implementation of common functions that would
@@ -198,13 +220,14 @@
   // conversion will only compile if there is exists a Base which inherits
   // from SupportsWeakPtr<Base>. See base::AsWeakPtr() below for a helper
   // function that makes calling this easier.
+  //
+  // Precondition: t != nullptr
   template <typename Derived>
   static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) {
-    typedef is_convertible<Derived, cef_internal::SupportsWeakPtrBase&>
-        convertible;
-    COMPILE_ASSERT(convertible::value,
-                   AsWeakPtr_argument_inherits_from_SupportsWeakPtr);
-    return AsWeakPtrImpl<Derived>(t, *t);
+    static_assert(
+        std::is_base_of<cef_internal::SupportsWeakPtrBase, Derived>::value,
+        "AsWeakPtr argument must inherit from SupportsWeakPtr");
+    return AsWeakPtrImpl<Derived>(t);
   }
 
  private:
@@ -212,10 +235,10 @@
   // which is an instance of SupportsWeakPtr<Base>. We can then safely
   // static_cast the Base* to a Derived*.
   template <typename Derived, typename Base>
-  static WeakPtr<Derived> AsWeakPtrImpl(Derived* t,
-                                        const SupportsWeakPtr<Base>&) {
-    WeakPtr<Base> ptr = t->Base::AsWeakPtr();
-    return WeakPtr<Derived>(ptr.ref_, static_cast<Derived*>(ptr.ptr_));
+  static WeakPtr<Derived> AsWeakPtrImpl(SupportsWeakPtr<Base>* t) {
+    WeakPtr<Base> ptr = t->AsWeakPtr();
+    return WeakPtr<Derived>(
+        ptr.ref_, static_cast<Derived*>(reinterpret_cast<Base*>(ptr.ptr_)));
   }
 };
 
@@ -224,66 +247,84 @@
 template <typename T>
 class WeakPtrFactory;
 
-// The WeakPtr class holds a weak reference to |T*|.
-//
-// This class is designed to be used like a normal pointer.  You should always
-// null-test an object of this class before using it or invoking a method that
-// may result in the underlying object being destroyed.
-//
-// EXAMPLE:
-//
-//   class Foo { ... };
-//   WeakPtr<Foo> foo;
-//   if (foo)
-//     foo->method();
-//
+///
+/// The WeakPtr class holds a weak reference to |T*|.
+///
+/// This class is designed to be used like a normal pointer.  You should always
+/// null-test an object of this class before using it or invoking a method that
+/// may result in the underlying object being destroyed.
+///
+/// EXAMPLE:
+///
+/// <pre>
+///   class Foo { ... };
+///   WeakPtr<Foo> foo;
+///   if (foo)
+///     foo->method();
+/// </pre>
+///
 template <typename T>
 class WeakPtr : public cef_internal::WeakPtrBase {
  public:
-  WeakPtr() : ptr_(NULL) {}
+  WeakPtr() = default;
+  WeakPtr(std::nullptr_t) {}
 
-  // Allow conversion from U to T provided U "is a" T. Note that this
-  // is separate from the (implicit) copy constructor.
+  ///
+  /// Allow conversion from U to T provided U "is a" T. Note that this
+  /// is separate from the (implicit) copy and move constructors.
+  ///
   template <typename U>
-  WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other), ptr_(other.ptr_) {}
+  WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other) {
+    // Need to cast from U* to T* to do pointer adjustment in case of multiple
+    // inheritance. This also enforces the "U is a T" rule.
+    T* t = reinterpret_cast<U*>(other.ptr_);
+    ptr_ = reinterpret_cast<uintptr_t>(t);
+  }
+  template <typename U>
+  WeakPtr(WeakPtr<U>&& other) noexcept : WeakPtrBase(std::move(other)) {
+    // Need to cast from U* to T* to do pointer adjustment in case of multiple
+    // inheritance. This also enforces the "U is a T" rule.
+    T* t = reinterpret_cast<U*>(other.ptr_);
+    ptr_ = reinterpret_cast<uintptr_t>(t);
+  }
 
-  T* get() const { return ref_.is_valid() ? ptr_ : NULL; }
+  T* get() const {
+    return ref_.IsValid() ? reinterpret_cast<T*>(ptr_) : nullptr;
+  }
 
   T& operator*() const {
-    DCHECK(get() != NULL);
+    CHECK(ref_.IsValid());
     return *get();
   }
   T* operator->() const {
-    DCHECK(get() != NULL);
+    CHECK(ref_.IsValid());
     return get();
   }
 
-  // Allow WeakPtr<element_type> to be used in boolean expressions, but not
-  // implicitly convertible to a real bool (which is dangerous).
-  //
-  // Note that this trick is only safe when the == and != operators
-  // are declared explicitly, as otherwise "weak_ptr1 == weak_ptr2"
-  // will compile but do the wrong thing (i.e., convert to Testable
-  // and then do the comparison).
- private:
-  typedef T* WeakPtr::*Testable;
+  ///
+  /// Allow conditionals to test validity, e.g. `if (weak_ptr) {...}`;
+  ///
+  explicit operator bool() const { return get() != nullptr; }
 
- public:
-  operator Testable() const { return get() ? &WeakPtr::ptr_ : NULL; }
+  ///
+  /// Returns false if the WeakPtr is confirmed to be invalid. This call is safe
+  /// to make from any thread, e.g. to optimize away unnecessary work, but
+  /// operator bool() must always be called, on the correct thread, before
+  /// actually using the pointer.
+  ///
+  /// Warning: as with any object, this call is only thread-safe if the WeakPtr
+  /// instance isn't being re-assigned or reset() racily with this call.
+  ///
+  bool MaybeValid() const { return ref_.MaybeValid(); }
 
-  void reset() {
-    ref_ = cef_internal::WeakReference();
-    ptr_ = NULL;
-  }
+  ///
+  /// Returns whether the object |this| points to has been invalidated. This can
+  /// be used to distinguish a WeakPtr to a destroyed object from one that has
+  /// been explicitly set to null.
+  ///
+  bool WasInvalidated() const { return ptr_ && !ref_.IsValid(); }
 
  private:
-  // Explicitly declare comparison operators as required by the bool
-  // trick, but keep them private.
-  template <class U>
-  bool operator==(WeakPtr<U> const&) const;
-  template <class U>
-  bool operator!=(WeakPtr<U> const&) const;
-
   friend class cef_internal::SupportsWeakPtrBase;
   template <typename U>
   friend class WeakPtr;
@@ -291,88 +332,131 @@
   friend class WeakPtrFactory<T>;
 
   WeakPtr(const cef_internal::WeakReference& ref, T* ptr)
-      : WeakPtrBase(ref), ptr_(ptr) {}
-
-  // This pointer is only valid when ref_.is_valid() is true.  Otherwise, its
-  // value is undefined (as opposed to NULL).
-  T* ptr_;
+      : WeakPtrBase(ref, reinterpret_cast<uintptr_t>(ptr)) {}
 };
 
-// A class may be composed of a WeakPtrFactory and thereby
-// control how it exposes weak pointers to itself.  This is helpful if you only
-// need weak pointers within the implementation of a class.  This class is also
-// useful when working with primitive types.  For example, you could have a
-// WeakPtrFactory<bool> that is used to pass around a weak reference to a bool.
+///
+/// Allow callers to compare WeakPtrs against nullptr to test validity.
+///
 template <class T>
-class WeakPtrFactory {
+bool operator!=(const WeakPtr<T>& weak_ptr, std::nullptr_t) {
+  return !(weak_ptr == nullptr);
+}
+template <class T>
+bool operator!=(std::nullptr_t, const WeakPtr<T>& weak_ptr) {
+  return weak_ptr != nullptr;
+}
+template <class T>
+bool operator==(const WeakPtr<T>& weak_ptr, std::nullptr_t) {
+  return weak_ptr.get() == nullptr;
+}
+template <class T>
+bool operator==(std::nullptr_t, const WeakPtr<T>& weak_ptr) {
+  return weak_ptr == nullptr;
+}
+
+namespace cef_internal {
+class WeakPtrFactoryBase {
+ protected:
+  WeakPtrFactoryBase(uintptr_t ptr);
+  ~WeakPtrFactoryBase();
+  cef_internal::WeakReferenceOwner weak_reference_owner_;
+  uintptr_t ptr_;
+};
+}  // namespace cef_internal
+
+///
+/// A class may be composed of a WeakPtrFactory and thereby control how it
+/// exposes weak pointers to itself.  This is helpful if you only need weak
+/// pointers within the implementation of a class.  This class is also useful
+/// when working with primitive types.  For example, you could have a
+/// WeakPtrFactory<bool> that is used to pass around a weak reference to a
+/// bool.
+///
+template <class T>
+class WeakPtrFactory : public cef_internal::WeakPtrFactoryBase {
  public:
-  explicit WeakPtrFactory(T* ptr) : ptr_(ptr) {}
+  WeakPtrFactory() = delete;
 
-  ~WeakPtrFactory() { ptr_ = NULL; }
+  explicit WeakPtrFactory(T* ptr)
+      : WeakPtrFactoryBase(reinterpret_cast<uintptr_t>(ptr)) {}
 
-  WeakPtr<T> GetWeakPtr() {
-    DCHECK(ptr_);
-    return WeakPtr<T>(weak_reference_owner_.GetRef(), ptr_);
+  WeakPtrFactory(const WeakPtrFactory&) = delete;
+  WeakPtrFactory& operator=(const WeakPtrFactory&) = delete;
+
+  ~WeakPtrFactory() = default;
+
+  WeakPtr<T> GetWeakPtr() const {
+    return WeakPtr<T>(weak_reference_owner_.GetRef(),
+                      reinterpret_cast<T*>(ptr_));
   }
 
-  // Call this method to invalidate all existing weak pointers.
+  ///
+  /// Call this method to invalidate all existing weak pointers.
+  ///
   void InvalidateWeakPtrs() {
     DCHECK(ptr_);
     weak_reference_owner_.Invalidate();
   }
 
-  // Call this method to determine if any weak pointers exist.
+  ///
+  /// Call this method to determine if any weak pointers exist.
+  ///
   bool HasWeakPtrs() const {
     DCHECK(ptr_);
     return weak_reference_owner_.HasRefs();
   }
-
- private:
-  cef_internal::WeakReferenceOwner weak_reference_owner_;
-  T* ptr_;
-  DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory);
 };
 
-// A class may extend from SupportsWeakPtr to let others take weak pointers to
-// it. This avoids the class itself implementing boilerplate to dispense weak
-// pointers.  However, since SupportsWeakPtr's destructor won't invalidate
-// weak pointers to the class until after the derived class' members have been
-// destroyed, its use can lead to subtle use-after-destroy issues.
+///
+/// A class may extend from SupportsWeakPtr to let others take weak pointers to
+/// it. This avoids the class itself implementing boilerplate to dispense weak
+/// pointers.  However, since SupportsWeakPtr's destructor won't invalidate
+/// weak pointers to the class until after the derived class' members have been
+/// destroyed, its use can lead to subtle use-after-destroy issues.
+///
 template <class T>
 class SupportsWeakPtr : public cef_internal::SupportsWeakPtrBase {
  public:
-  SupportsWeakPtr() {}
+  SupportsWeakPtr() = default;
+
+  SupportsWeakPtr(const SupportsWeakPtr&) = delete;
+  SupportsWeakPtr& operator=(const SupportsWeakPtr&) = delete;
 
   WeakPtr<T> AsWeakPtr() {
     return WeakPtr<T>(weak_reference_owner_.GetRef(), static_cast<T*>(this));
   }
 
  protected:
-  ~SupportsWeakPtr() {}
+  ~SupportsWeakPtr() = default;
 
  private:
   cef_internal::WeakReferenceOwner weak_reference_owner_;
-  DISALLOW_COPY_AND_ASSIGN(SupportsWeakPtr);
 };
 
-// Helper function that uses type deduction to safely return a WeakPtr<Derived>
-// when Derived doesn't directly extend SupportsWeakPtr<Derived>, instead it
-// extends a Base that extends SupportsWeakPtr<Base>.
-//
-// EXAMPLE:
-//   class Base : public base::SupportsWeakPtr<Producer> {};
-//   class Derived : public Base {};
-//
-//   Derived derived;
-//   base::WeakPtr<Derived> ptr = base::AsWeakPtr(&derived);
-//
-// Note that the following doesn't work (invalid type conversion) since
-// Derived::AsWeakPtr() is WeakPtr<Base> SupportsWeakPtr<Base>::AsWeakPtr(),
-// and there's no way to safely cast WeakPtr<Base> to WeakPtr<Derived> at
-// the caller.
-//
-//   base::WeakPtr<Derived> ptr = derived.AsWeakPtr();  // Fails.
-
+///
+/// Helper function that uses type deduction to safely return a WeakPtr<Derived>
+/// when Derived doesn't directly extend SupportsWeakPtr<Derived>, instead it
+/// extends a Base that extends SupportsWeakPtr<Base>.
+///
+/// EXAMPLE:
+/// <pre>
+///   class Base : public base::SupportsWeakPtr<Producer> {};
+///   class Derived : public Base {};
+///
+///   Derived derived;
+///   base::WeakPtr<Derived> ptr = base::AsWeakPtr(&derived);
+/// </pre>
+///
+/// Note that the following doesn't work (invalid type conversion) since
+/// Derived::AsWeakPtr() is WeakPtr<Base> SupportsWeakPtr<Base>::AsWeakPtr(),
+/// and there's no way to safely cast WeakPtr<Base> to WeakPtr<Derived> at
+/// the caller.
+///
+/// <pre>
+///   base::WeakPtr<Derived> ptr = derived.AsWeakPtr();  // Fails.
+/// </pre>
+///
 template <typename Derived>
 WeakPtr<Derived> AsWeakPtr(Derived* t) {
   return cef_internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t);
diff --git a/src/include/base/internal/cef_atomicops_arm64_gcc.h b/src/include/base/internal/cef_atomicops_arm64_gcc.h
deleted file mode 100644
index 787b3ca..0000000
--- a/src/include/base/internal/cef_atomicops_arm64_gcc.h
+++ /dev/null
@@ -1,335 +0,0 @@
-// Copyright (c) 2012 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Do not include this header file directly. Use base/cef_atomicops.h
-// instead.
-
-#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ARM64_GCC_H_
-#define CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ARM64_GCC_H_
-
-namespace base {
-namespace subtle {
-
-inline void MemoryBarrier() {
-  __asm__ __volatile__ ("dmb ish" ::: "memory");  // NOLINT
-}
-
-// NoBarrier versions of the operation include "memory" in the clobber list.
-// This is not required for direct usage of the NoBarrier versions of the
-// operations. However this is required for correctness when they are used as
-// part of the Acquire or Release versions, to ensure that nothing from outside
-// the call is reordered between the operation and the memory barrier. This does
-// not change the code generated, so has no or minimal impact on the
-// NoBarrier operations.
-
-inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
-                                         Atomic32 old_value,
-                                         Atomic32 new_value) {
-  Atomic32 prev;
-  int32_t temp;
-
-  __asm__ __volatile__ (  // NOLINT
-    "0:                                    \n\t"
-    "ldxr %w[prev], %[ptr]                 \n\t"  // Load the previous value.
-    "cmp %w[prev], %w[old_value]           \n\t"
-    "bne 1f                                \n\t"
-    "stxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
-    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
-    "1:                                    \n\t"
-    : [prev]"=&r" (prev),
-      [temp]"=&r" (temp),
-      [ptr]"+Q" (*ptr)
-    : [old_value]"IJr" (old_value),
-      [new_value]"r" (new_value)
-    : "cc", "memory"
-  );  // NOLINT
-
-  return prev;
-}
-
-inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
-                                         Atomic32 new_value) {
-  Atomic32 result;
-  int32_t temp;
-
-  __asm__ __volatile__ (  // NOLINT
-    "0:                                    \n\t"
-    "ldxr %w[result], %[ptr]               \n\t"  // Load the previous value.
-    "stxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
-    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
-    : [result]"=&r" (result),
-      [temp]"=&r" (temp),
-      [ptr]"+Q" (*ptr)
-    : [new_value]"r" (new_value)
-    : "memory"
-  );  // NOLINT
-
-  return result;
-}
-
-inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
-                                          Atomic32 increment) {
-  Atomic32 result;
-  int32_t temp;
-
-  __asm__ __volatile__ (  // NOLINT
-    "0:                                       \n\t"
-    "ldxr %w[result], %[ptr]                  \n\t"  // Load the previous value.
-    "add %w[result], %w[result], %w[increment]\n\t"
-    "stxr %w[temp], %w[result], %[ptr]        \n\t"  // Try to store the result.
-    "cbnz %w[temp], 0b                        \n\t"  // Retry on failure.
-    : [result]"=&r" (result),
-      [temp]"=&r" (temp),
-      [ptr]"+Q" (*ptr)
-    : [increment]"IJr" (increment)
-    : "memory"
-  );  // NOLINT
-
-  return result;
-}
-
-inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
-                                        Atomic32 increment) {
-  Atomic32 result;
-
-  MemoryBarrier();
-  result = NoBarrier_AtomicIncrement(ptr, increment);
-  MemoryBarrier();
-
-  return result;
-}
-
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
-                                       Atomic32 old_value,
-                                       Atomic32 new_value) {
-  Atomic32 prev;
-
-  prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-  MemoryBarrier();
-
-  return prev;
-}
-
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
-                                       Atomic32 old_value,
-                                       Atomic32 new_value) {
-  Atomic32 prev;
-
-  MemoryBarrier();
-  prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-
-  return prev;
-}
-
-inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
-  *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
-  *ptr = value;
-  MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
-  __asm__ __volatile__ (  // NOLINT
-    "stlr %w[value], %[ptr]  \n\t"
-    : [ptr]"=Q" (*ptr)
-    : [value]"r" (value)
-    : "memory"
-  );  // NOLINT
-}
-
-inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
-  return *ptr;
-}
-
-inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
-  Atomic32 value;
-
-  __asm__ __volatile__ (  // NOLINT
-    "ldar %w[value], %[ptr]  \n\t"
-    : [value]"=r" (value)
-    : [ptr]"Q" (*ptr)
-    : "memory"
-  );  // NOLINT
-
-  return value;
-}
-
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
-  MemoryBarrier();
-  return *ptr;
-}
-
-// 64-bit versions of the operations.
-// See the 32-bit versions for comments.
-
-inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
-                                         Atomic64 old_value,
-                                         Atomic64 new_value) {
-  Atomic64 prev;
-  int32_t temp;
-
-  __asm__ __volatile__ (  // NOLINT
-    "0:                                    \n\t"
-    "ldxr %[prev], %[ptr]                  \n\t"
-    "cmp %[prev], %[old_value]             \n\t"
-    "bne 1f                                \n\t"
-    "stxr %w[temp], %[new_value], %[ptr]   \n\t"
-    "cbnz %w[temp], 0b                     \n\t"
-    "1:                                    \n\t"
-    : [prev]"=&r" (prev),
-      [temp]"=&r" (temp),
-      [ptr]"+Q" (*ptr)
-    : [old_value]"IJr" (old_value),
-      [new_value]"r" (new_value)
-    : "cc", "memory"
-  );  // NOLINT
-
-  return prev;
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
-                                         Atomic64 new_value) {
-  Atomic64 result;
-  int32_t temp;
-
-  __asm__ __volatile__ (  // NOLINT
-    "0:                                    \n\t"
-    "ldxr %[result], %[ptr]                \n\t"
-    "stxr %w[temp], %[new_value], %[ptr]   \n\t"
-    "cbnz %w[temp], 0b                     \n\t"
-    : [result]"=&r" (result),
-      [temp]"=&r" (temp),
-      [ptr]"+Q" (*ptr)
-    : [new_value]"r" (new_value)
-    : "memory"
-  );  // NOLINT
-
-  return result;
-}
-
-inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
-                                          Atomic64 increment) {
-  Atomic64 result;
-  int32_t temp;
-
-  __asm__ __volatile__ (  // NOLINT
-    "0:                                     \n\t"
-    "ldxr %[result], %[ptr]                 \n\t"
-    "add %[result], %[result], %[increment] \n\t"
-    "stxr %w[temp], %[result], %[ptr]       \n\t"
-    "cbnz %w[temp], 0b                      \n\t"
-    : [result]"=&r" (result),
-      [temp]"=&r" (temp),
-      [ptr]"+Q" (*ptr)
-    : [increment]"IJr" (increment)
-    : "memory"
-  );  // NOLINT
-
-  return result;
-}
-
-inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
-                                        Atomic64 increment) {
-  Atomic64 result;
-
-  MemoryBarrier();
-  result = NoBarrier_AtomicIncrement(ptr, increment);
-  MemoryBarrier();
-
-  return result;
-}
-
-inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
-                                       Atomic64 old_value,
-                                       Atomic64 new_value) {
-  Atomic64 prev;
-
-  prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-  MemoryBarrier();
-
-  return prev;
-}
-
-inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
-                                       Atomic64 old_value,
-                                       Atomic64 new_value) {
-  Atomic64 prev;
-
-  MemoryBarrier();
-  prev = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-
-  return prev;
-}
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
-  *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
-  *ptr = value;
-  MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
-  __asm__ __volatile__ (  // NOLINT
-    "stlr %x[value], %[ptr]  \n\t"
-    : [ptr]"=Q" (*ptr)
-    : [value]"r" (value)
-    : "memory"
-  );  // NOLINT
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
-  return *ptr;
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
-  Atomic64 value;
-
-  __asm__ __volatile__ (  // NOLINT
-    "ldar %x[value], %[ptr]  \n\t"
-    : [value]"=r" (value)
-    : [ptr]"Q" (*ptr)
-    : "memory"
-  );  // NOLINT
-
-  return value;
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
-  MemoryBarrier();
-  return *ptr;
-}
-
-} }  // namespace base::subtle
-
-#endif  // CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ARM64_GCC_H_
-
diff --git a/src/include/base/internal/cef_atomicops_arm64_msvc.h b/src/include/base/internal/cef_atomicops_arm64_msvc.h
deleted file mode 100644
index 86d950f..0000000
--- a/src/include/base/internal/cef_atomicops_arm64_msvc.h
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright (c) 2008 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Do not include this header file directly. Use base/cef_atomicops.h
-// instead.
-
-#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ARM64_MSVC_H_
-#define CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ARM64_MSVC_H_
-
-#include <windows.h>
-
-#include <intrin.h>
-
-#include "include/base/cef_macros.h"
-
-namespace base {
-namespace subtle {
-
-inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
-                                         Atomic32 old_value,
-                                         Atomic32 new_value) {
-  LONG result = _InterlockedCompareExchange(
-      reinterpret_cast<volatile LONG*>(ptr), static_cast<LONG>(new_value),
-      static_cast<LONG>(old_value));
-  return static_cast<Atomic32>(result);
-}
-
-inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
-                                         Atomic32 new_value) {
-  LONG result = _InterlockedExchange(reinterpret_cast<volatile LONG*>(ptr),
-                                     static_cast<LONG>(new_value));
-  return static_cast<Atomic32>(result);
-}
-
-inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
-                                        Atomic32 increment) {
-  return _InterlockedExchangeAdd(reinterpret_cast<volatile LONG*>(ptr),
-                                 static_cast<LONG>(increment)) +
-         increment;
-}
-
-inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
-                                          Atomic32 increment) {
-  return Barrier_AtomicIncrement(ptr, increment);
-}
-
-#if !(defined(_MSC_VER) && _MSC_VER >= 1400)
-#error "We require at least vs2005 for MemoryBarrier"
-#endif
-
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
-                                       Atomic32 old_value,
-                                       Atomic32 new_value) {
-  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
-                                       Atomic32 old_value,
-                                       Atomic32 new_value) {
-  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
-  *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
-  NoBarrier_AtomicExchange(ptr, value);
-  // acts as a barrier in this implementation
-}
-
-inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
-  *ptr = value;
-  // See comments in Atomic64 version of Release_Store() below.
-}
-
-inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
-  return *ptr;
-}
-
-inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
-  Atomic32 value = *ptr;
-  return value;
-}
-
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
-  MemoryBarrier();
-  return *ptr;
-}
-
-#if defined(_WIN64)
-
-// 64-bit low-level operations on 64-bit platform.
-
-COMPILE_ASSERT(sizeof(Atomic64) == sizeof(PVOID), atomic_word_is_atomic);
-
-inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
-                                         Atomic64 old_value,
-                                         Atomic64 new_value) {
-  PVOID result = InterlockedCompareExchangePointer(
-      reinterpret_cast<volatile PVOID*>(ptr),
-      reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value));
-  return reinterpret_cast<Atomic64>(result);
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
-                                         Atomic64 new_value) {
-  PVOID result =
-      InterlockedExchangePointer(reinterpret_cast<volatile PVOID*>(ptr),
-                                 reinterpret_cast<PVOID>(new_value));
-  return reinterpret_cast<Atomic64>(result);
-}
-
-inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
-                                        Atomic64 increment) {
-  return InterlockedExchangeAdd64(reinterpret_cast<volatile LONGLONG*>(ptr),
-                                  static_cast<LONGLONG>(increment)) +
-         increment;
-}
-
-inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
-                                          Atomic64 increment) {
-  return Barrier_AtomicIncrement(ptr, increment);
-}
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
-  *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
-  NoBarrier_AtomicExchange(ptr, value);
-  // acts as a barrier in this implementation
-}
-
-inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
-  *ptr = value;
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
-  return *ptr;
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
-  Atomic64 value = *ptr;
-  return value;
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
-  MemoryBarrier();
-  return *ptr;
-}
-
-inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
-                                       Atomic64 old_value,
-                                       Atomic64 new_value) {
-  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
-                                       Atomic64 old_value,
-                                       Atomic64 new_value) {
-  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-#endif  // defined(_WIN64)
-
-}  // namespace base::subtle
-}  // namespace base
-
-#endif  // CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ARM64_MSVC_H_
-
diff --git a/src/include/base/internal/cef_atomicops_arm_gcc.h b/src/include/base/internal/cef_atomicops_arm_gcc.h
deleted file mode 100644
index 2e39ce3..0000000
--- a/src/include/base/internal/cef_atomicops_arm_gcc.h
+++ /dev/null
@@ -1,325 +0,0 @@
-// Copyright (c) 2013 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Do not include this header file directly. Use base/cef_atomicops.h
-// instead.
-//
-// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears.
-
-#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ARM_GCC_H_
-#define CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ARM_GCC_H_
-
-#if defined(OS_QNX)
-#include <sys/cpuinline.h>
-#endif
-
-namespace base {
-namespace subtle {
-
-// Memory barriers on ARM are funky, but the kernel is here to help:
-//
-// * ARMv5 didn't support SMP, there is no memory barrier instruction at
-//   all on this architecture, or when targeting its machine code.
-//
-// * Some ARMv6 CPUs support SMP. A full memory barrier can be produced by
-//   writing a random value to a very specific coprocessor register.
-//
-// * On ARMv7, the "dmb" instruction is used to perform a full memory
-//   barrier (though writing to the co-processor will still work).
-//   However, on single core devices (e.g. Nexus One, or Nexus S),
-//   this instruction will take up to 200 ns, which is huge, even though
-//   it's completely un-needed on these devices.
-//
-// * There is no easy way to determine at runtime if the device is
-//   single or multi-core. However, the kernel provides a useful helper
-//   function at a fixed memory address (0xffff0fa0), which will always
-//   perform a memory barrier in the most efficient way. I.e. on single
-//   core devices, this is an empty function that exits immediately.
-//   On multi-core devices, it implements a full memory barrier.
-//
-// * This source could be compiled to ARMv5 machine code that runs on a
-//   multi-core ARMv6 or ARMv7 device. In this case, memory barriers
-//   are needed for correct execution. Always call the kernel helper, even
-//   when targeting ARMv5TE.
-//
-
-inline void MemoryBarrier() {
-#if defined(OS_LINUX) || defined(OS_ANDROID)
-  // Note: This is a function call, which is also an implicit compiler barrier.
-  typedef void (*KernelMemoryBarrierFunc)();
-  ((KernelMemoryBarrierFunc)0xffff0fa0)();
-#elif defined(OS_QNX)
-  __cpu_membarrier();
-#else
-#error MemoryBarrier() is not implemented on this platform.
-#endif
-}
-
-// An ARM toolchain would only define one of these depending on which
-// variant of the target architecture is being used. This tests against
-// any known ARMv6 or ARMv7 variant, where it is possible to directly
-// use ldrex/strex instructions to implement fast atomic operations.
-#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) ||  \
-    defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || \
-    defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) ||  \
-    defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \
-    defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__)
-
-inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
-                                         Atomic32 old_value,
-                                         Atomic32 new_value) {
-  Atomic32 prev_value;
-  int reloop;
-  do {
-    // The following is equivalent to:
-    //
-    //   prev_value = LDREX(ptr)
-    //   reloop = 0
-    //   if (prev_value != old_value)
-    //      reloop = STREX(ptr, new_value)
-    __asm__ __volatile__(
-        "    ldrex %0, [%3]\n"
-        "    mov %1, #0\n"
-        "    cmp %0, %4\n"
-#ifdef __thumb2__
-        "    it eq\n"
-#endif
-        "    strexeq %1, %5, [%3]\n"
-        : "=&r"(prev_value), "=&r"(reloop), "+m"(*ptr)
-        : "r"(ptr), "r"(old_value), "r"(new_value)
-        : "cc", "memory");
-  } while (reloop != 0);
-  return prev_value;
-}
-
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
-                                       Atomic32 old_value,
-                                       Atomic32 new_value) {
-  Atomic32 result = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-  MemoryBarrier();
-  return result;
-}
-
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
-                                       Atomic32 old_value,
-                                       Atomic32 new_value) {
-  MemoryBarrier();
-  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
-                                          Atomic32 increment) {
-  Atomic32 value;
-  int reloop;
-  do {
-    // Equivalent to:
-    //
-    //  value = LDREX(ptr)
-    //  value += increment
-    //  reloop = STREX(ptr, value)
-    //
-    __asm__ __volatile__(
-        "    ldrex %0, [%3]\n"
-        "    add %0, %0, %4\n"
-        "    strex %1, %0, [%3]\n"
-        : "=&r"(value), "=&r"(reloop), "+m"(*ptr)
-        : "r"(ptr), "r"(increment)
-        : "cc", "memory");
-  } while (reloop);
-  return value;
-}
-
-inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
-                                        Atomic32 increment) {
-  // TODO(digit): Investigate if it's possible to implement this with
-  // a single MemoryBarrier() operation between the LDREX and STREX.
-  // See http://crbug.com/246514
-  MemoryBarrier();
-  Atomic32 result = NoBarrier_AtomicIncrement(ptr, increment);
-  MemoryBarrier();
-  return result;
-}
-
-inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
-                                         Atomic32 new_value) {
-  Atomic32 old_value;
-  int reloop;
-  do {
-    // old_value = LDREX(ptr)
-    // reloop = STREX(ptr, new_value)
-    __asm__ __volatile__(
-        "   ldrex %0, [%3]\n"
-        "   strex %1, %4, [%3]\n"
-        : "=&r"(old_value), "=&r"(reloop), "+m"(*ptr)
-        : "r"(ptr), "r"(new_value)
-        : "cc", "memory");
-  } while (reloop != 0);
-  return old_value;
-}
-
-// This tests against any known ARMv5 variant.
-#elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \
-    defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__)
-
-// The kernel also provides a helper function to perform an atomic
-// compare-and-swap operation at the hard-wired address 0xffff0fc0.
-// On ARMv5, this is implemented by a special code path that the kernel
-// detects and treats specially when thread pre-emption happens.
-// On ARMv6 and higher, it uses LDREX/STREX instructions instead.
-//
-// Note that this always perform a full memory barrier, there is no
-// need to add calls MemoryBarrier() before or after it. It also
-// returns 0 on success, and 1 on exit.
-//
-// Available and reliable since Linux 2.6.24. Both Android and ChromeOS
-// use newer kernel revisions, so this should not be a concern.
-namespace {
-
-inline int LinuxKernelCmpxchg(Atomic32 old_value,
-                              Atomic32 new_value,
-                              volatile Atomic32* ptr) {
-  typedef int (*KernelCmpxchgFunc)(Atomic32, Atomic32, volatile Atomic32*);
-  return ((KernelCmpxchgFunc)0xffff0fc0)(old_value, new_value, ptr);
-}
-
-}  // namespace
-
-inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
-                                         Atomic32 old_value,
-                                         Atomic32 new_value) {
-  Atomic32 prev_value;
-  for (;;) {
-    prev_value = *ptr;
-    if (prev_value != old_value)
-      return prev_value;
-    if (!LinuxKernelCmpxchg(old_value, new_value, ptr))
-      return old_value;
-  }
-}
-
-inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
-                                         Atomic32 new_value) {
-  Atomic32 old_value;
-  do {
-    old_value = *ptr;
-  } while (LinuxKernelCmpxchg(old_value, new_value, ptr));
-  return old_value;
-}
-
-inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
-                                          Atomic32 increment) {
-  return Barrier_AtomicIncrement(ptr, increment);
-}
-
-inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
-                                        Atomic32 increment) {
-  for (;;) {
-    // Atomic exchange the old value with an incremented one.
-    Atomic32 old_value = *ptr;
-    Atomic32 new_value = old_value + increment;
-    if (!LinuxKernelCmpxchg(old_value, new_value, ptr)) {
-      // The exchange took place as expected.
-      return new_value;
-    }
-    // Otherwise, *ptr changed mid-loop and we need to retry.
-  }
-}
-
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
-                                       Atomic32 old_value,
-                                       Atomic32 new_value) {
-  Atomic32 prev_value;
-  for (;;) {
-    prev_value = *ptr;
-    if (prev_value != old_value) {
-      // Always ensure acquire semantics.
-      MemoryBarrier();
-      return prev_value;
-    }
-    if (!LinuxKernelCmpxchg(old_value, new_value, ptr))
-      return old_value;
-  }
-}
-
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
-                                       Atomic32 old_value,
-                                       Atomic32 new_value) {
-  // This could be implemented as:
-  //    MemoryBarrier();
-  //    return NoBarrier_CompareAndSwap();
-  //
-  // But would use 3 barriers per succesful CAS. To save performance,
-  // use Acquire_CompareAndSwap(). Its implementation guarantees that:
-  // - A succesful swap uses only 2 barriers (in the kernel helper).
-  // - An early return due to (prev_value != old_value) performs
-  //   a memory barrier with no store, which is equivalent to the
-  //   generic implementation above.
-  return Acquire_CompareAndSwap(ptr, old_value, new_value);
-}
-
-#else
-#error "Your CPU's ARM architecture is not supported yet"
-#endif
-
-// NOTE: Atomicity of the following load and store operations is only
-// guaranteed in case of 32-bit alignement of |ptr| values.
-
-inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
-  *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
-  *ptr = value;
-  MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
-  MemoryBarrier();
-  *ptr = value;
-}
-
-inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
-  return *ptr;
-}
-
-inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
-  Atomic32 value = *ptr;
-  MemoryBarrier();
-  return value;
-}
-
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
-  MemoryBarrier();
-  return *ptr;
-}
-
-}  // namespace base::subtle
-}  // namespace base
-
-#endif  // CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ARM_GCC_H_
diff --git a/src/include/base/internal/cef_atomicops_atomicword_compat.h b/src/include/base/internal/cef_atomicops_atomicword_compat.h
deleted file mode 100644
index f905de8..0000000
--- a/src/include/base/internal/cef_atomicops_atomicword_compat.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (c) 2011 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Do not include this header file directly. Use base/cef_atomicops.h
-// instead.
-
-#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ATOMICWORD_COMPAT_H_
-#define CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ATOMICWORD_COMPAT_H_
-
-// AtomicWord is a synonym for intptr_t, and Atomic32 is a synonym for int32,
-// which in turn means int. On some LP32 platforms, intptr_t is an int, but
-// on others, it's a long. When AtomicWord and Atomic32 are based on different
-// fundamental types, their pointers are incompatible.
-//
-// This file defines function overloads to allow both AtomicWord and Atomic32
-// data to be used with this interface.
-//
-// On LP64 platforms, AtomicWord and Atomic64 are both always long,
-// so this problem doesn't occur.
-
-#if !defined(ARCH_CPU_64_BITS)
-
-namespace base {
-namespace subtle {
-
-inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr,
-                                           AtomicWord old_value,
-                                           AtomicWord new_value) {
-  return NoBarrier_CompareAndSwap(reinterpret_cast<volatile Atomic32*>(ptr),
-                                  old_value, new_value);
-}
-
-inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr,
-                                           AtomicWord new_value) {
-  return NoBarrier_AtomicExchange(reinterpret_cast<volatile Atomic32*>(ptr),
-                                  new_value);
-}
-
-inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr,
-                                            AtomicWord increment) {
-  return NoBarrier_AtomicIncrement(reinterpret_cast<volatile Atomic32*>(ptr),
-                                   increment);
-}
-
-inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr,
-                                          AtomicWord increment) {
-  return Barrier_AtomicIncrement(reinterpret_cast<volatile Atomic32*>(ptr),
-                                 increment);
-}
-
-inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr,
-                                         AtomicWord old_value,
-                                         AtomicWord new_value) {
-  return base::subtle::Acquire_CompareAndSwap(
-      reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value);
-}
-
-inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr,
-                                         AtomicWord old_value,
-                                         AtomicWord new_value) {
-  return base::subtle::Release_CompareAndSwap(
-      reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value);
-}
-
-inline void NoBarrier_Store(volatile AtomicWord* ptr, AtomicWord value) {
-  NoBarrier_Store(reinterpret_cast<volatile Atomic32*>(ptr), value);
-}
-
-inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
-  return base::subtle::Acquire_Store(reinterpret_cast<volatile Atomic32*>(ptr),
-                                     value);
-}
-
-inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
-  return base::subtle::Release_Store(reinterpret_cast<volatile Atomic32*>(ptr),
-                                     value);
-}
-
-inline AtomicWord NoBarrier_Load(volatile const AtomicWord* ptr) {
-  return NoBarrier_Load(reinterpret_cast<volatile const Atomic32*>(ptr));
-}
-
-inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
-  return base::subtle::Acquire_Load(
-      reinterpret_cast<volatile const Atomic32*>(ptr));
-}
-
-inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
-  return base::subtle::Release_Load(
-      reinterpret_cast<volatile const Atomic32*>(ptr));
-}
-
-}  // namespace base::subtle
-}  // namespace base
-
-#endif  // !defined(ARCH_CPU_64_BITS)
-
-#endif  // CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ATOMICWORD_COMPAT_H_
diff --git a/src/include/base/internal/cef_atomicops_mac.h b/src/include/base/internal/cef_atomicops_mac.h
deleted file mode 100644
index 374ae35..0000000
--- a/src/include/base/internal/cef_atomicops_mac.h
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright (c) 2012 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Do not include this header file directly. Use base/cef_atomicops.h
-// instead.
-
-#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_MAC_H_
-#define CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_MAC_H_
-
-#include <libkern/OSAtomic.h>
-
-namespace base {
-namespace subtle {
-
-inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
-                                         Atomic32 old_value,
-                                         Atomic32 new_value) {
-  Atomic32 prev_value;
-  do {
-    if (OSAtomicCompareAndSwap32(old_value, new_value,
-                                 const_cast<Atomic32*>(ptr))) {
-      return old_value;
-    }
-    prev_value = *ptr;
-  } while (prev_value == old_value);
-  return prev_value;
-}
-
-inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
-                                         Atomic32 new_value) {
-  Atomic32 old_value;
-  do {
-    old_value = *ptr;
-  } while (!OSAtomicCompareAndSwap32(old_value, new_value,
-                                     const_cast<Atomic32*>(ptr)));
-  return old_value;
-}
-
-inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
-                                          Atomic32 increment) {
-  return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr));
-}
-
-inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
-                                        Atomic32 increment) {
-  return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr));
-}
-
-inline void MemoryBarrier() {
-  OSMemoryBarrier();
-}
-
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
-                                       Atomic32 old_value,
-                                       Atomic32 new_value) {
-  Atomic32 prev_value;
-  do {
-    if (OSAtomicCompareAndSwap32Barrier(old_value, new_value,
-                                        const_cast<Atomic32*>(ptr))) {
-      return old_value;
-    }
-    prev_value = *ptr;
-  } while (prev_value == old_value);
-  return prev_value;
-}
-
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
-                                       Atomic32 old_value,
-                                       Atomic32 new_value) {
-  return Acquire_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
-  *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
-  *ptr = value;
-  MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
-  MemoryBarrier();
-  *ptr = value;
-}
-
-inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
-  return *ptr;
-}
-
-inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
-  Atomic32 value = *ptr;
-  MemoryBarrier();
-  return value;
-}
-
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
-  MemoryBarrier();
-  return *ptr;
-}
-
-#ifdef __LP64__
-
-// 64-bit implementation on 64-bit platform
-
-inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
-                                         Atomic64 old_value,
-                                         Atomic64 new_value) {
-  Atomic64 prev_value;
-  do {
-    if (OSAtomicCompareAndSwap64(old_value, new_value,
-                                 reinterpret_cast<volatile int64_t*>(ptr))) {
-      return old_value;
-    }
-    prev_value = *ptr;
-  } while (prev_value == old_value);
-  return prev_value;
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
-                                         Atomic64 new_value) {
-  Atomic64 old_value;
-  do {
-    old_value = *ptr;
-  } while (!OSAtomicCompareAndSwap64(old_value, new_value,
-                                     reinterpret_cast<volatile int64_t*>(ptr)));
-  return old_value;
-}
-
-inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
-                                          Atomic64 increment) {
-  return OSAtomicAdd64(increment, reinterpret_cast<volatile int64_t*>(ptr));
-}
-
-inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
-                                        Atomic64 increment) {
-  return OSAtomicAdd64Barrier(increment,
-                              reinterpret_cast<volatile int64_t*>(ptr));
-}
-
-inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
-                                       Atomic64 old_value,
-                                       Atomic64 new_value) {
-  Atomic64 prev_value;
-  do {
-    if (OSAtomicCompareAndSwap64Barrier(
-            old_value, new_value, reinterpret_cast<volatile int64_t*>(ptr))) {
-      return old_value;
-    }
-    prev_value = *ptr;
-  } while (prev_value == old_value);
-  return prev_value;
-}
-
-inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
-                                       Atomic64 old_value,
-                                       Atomic64 new_value) {
-  // The lib kern interface does not distinguish between
-  // Acquire and Release memory barriers; they are equivalent.
-  return Acquire_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
-  *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
-  *ptr = value;
-  MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
-  MemoryBarrier();
-  *ptr = value;
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
-  return *ptr;
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
-  Atomic64 value = *ptr;
-  MemoryBarrier();
-  return value;
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
-  MemoryBarrier();
-  return *ptr;
-}
-
-#endif  // defined(__LP64__)
-
-}  // namespace base::subtle
-}  // namespace base
-
-#endif  // CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_MAC_H_
diff --git a/src/include/base/internal/cef_atomicops_x86_gcc.h b/src/include/base/internal/cef_atomicops_x86_gcc.h
deleted file mode 100644
index b93df21..0000000
--- a/src/include/base/internal/cef_atomicops_x86_gcc.h
+++ /dev/null
@@ -1,268 +0,0 @@
-// Copyright (c) 2011 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Do not include this header file directly. Use base/cef_atomicops.h
-// instead.
-
-#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_GCC_H_
-#define CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_GCC_H_
-
-// This struct is not part of the public API of this module; clients may not
-// use it.
-// Features of this x86.  Values may not be correct before main() is run,
-// but are set conservatively.
-struct AtomicOps_x86CPUFeatureStruct {
-  bool has_amd_lock_mb_bug;  // Processor has AMD memory-barrier bug; do lfence
-                             // after acquire compare-and-swap.
-};
-extern struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures;
-
-#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
-
-namespace base {
-namespace subtle {
-
-// 32-bit low-level operations on any platform.
-
-inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
-                                         Atomic32 old_value,
-                                         Atomic32 new_value) {
-  Atomic32 prev;
-  __asm__ __volatile__("lock; cmpxchgl %1,%2"
-                       : "=a"(prev)
-                       : "q"(new_value), "m"(*ptr), "0"(old_value)
-                       : "memory");
-  return prev;
-}
-
-inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
-                                         Atomic32 new_value) {
-  __asm__ __volatile__("xchgl %1,%0"  // The lock prefix is implicit for xchg.
-                       : "=r"(new_value)
-                       : "m"(*ptr), "0"(new_value)
-                       : "memory");
-  return new_value;  // Now it's the previous value.
-}
-
-inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
-                                          Atomic32 increment) {
-  Atomic32 temp = increment;
-  __asm__ __volatile__("lock; xaddl %0,%1"
-                       : "+r"(temp), "+m"(*ptr)
-                       :
-                       : "memory");
-  // temp now holds the old value of *ptr
-  return temp + increment;
-}
-
-inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
-                                        Atomic32 increment) {
-  Atomic32 temp = increment;
-  __asm__ __volatile__("lock; xaddl %0,%1"
-                       : "+r"(temp), "+m"(*ptr)
-                       :
-                       : "memory");
-  // temp now holds the old value of *ptr
-  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
-    __asm__ __volatile__("lfence" : : : "memory");
-  }
-  return temp + increment;
-}
-
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
-                                       Atomic32 old_value,
-                                       Atomic32 new_value) {
-  Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
-    __asm__ __volatile__("lfence" : : : "memory");
-  }
-  return x;
-}
-
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
-                                       Atomic32 old_value,
-                                       Atomic32 new_value) {
-  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
-  *ptr = value;
-}
-
-inline void MemoryBarrier() {
-  __asm__ __volatile__("mfence" : : : "memory");
-}
-
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
-  *ptr = value;
-  MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
-  ATOMICOPS_COMPILER_BARRIER();
-  *ptr = value;  // An x86 store acts as a release barrier.
-  // See comments in Atomic64 version of Release_Store(), below.
-}
-
-inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
-  return *ptr;
-}
-
-inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
-  Atomic32 value = *ptr;  // An x86 load acts as a acquire barrier.
-  // See comments in Atomic64 version of Release_Store(), below.
-  ATOMICOPS_COMPILER_BARRIER();
-  return value;
-}
-
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
-  MemoryBarrier();
-  return *ptr;
-}
-
-#if defined(__x86_64__)
-
-// 64-bit low-level operations on 64-bit platform.
-
-inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
-                                         Atomic64 old_value,
-                                         Atomic64 new_value) {
-  Atomic64 prev;
-  __asm__ __volatile__("lock; cmpxchgq %1,%2"
-                       : "=a"(prev)
-                       : "q"(new_value), "m"(*ptr), "0"(old_value)
-                       : "memory");
-  return prev;
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
-                                         Atomic64 new_value) {
-  __asm__ __volatile__("xchgq %1,%0"  // The lock prefix is implicit for xchg.
-                       : "=r"(new_value)
-                       : "m"(*ptr), "0"(new_value)
-                       : "memory");
-  return new_value;  // Now it's the previous value.
-}
-
-inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
-                                          Atomic64 increment) {
-  Atomic64 temp = increment;
-  __asm__ __volatile__("lock; xaddq %0,%1"
-                       : "+r"(temp), "+m"(*ptr)
-                       :
-                       : "memory");
-  // temp now contains the previous value of *ptr
-  return temp + increment;
-}
-
-inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
-                                        Atomic64 increment) {
-  Atomic64 temp = increment;
-  __asm__ __volatile__("lock; xaddq %0,%1"
-                       : "+r"(temp), "+m"(*ptr)
-                       :
-                       : "memory");
-  // temp now contains the previous value of *ptr
-  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
-    __asm__ __volatile__("lfence" : : : "memory");
-  }
-  return temp + increment;
-}
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
-  *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
-  *ptr = value;
-  MemoryBarrier();
-}
-
-inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
-  ATOMICOPS_COMPILER_BARRIER();
-
-  *ptr = value;  // An x86 store acts as a release barrier
-                 // for current AMD/Intel chips as of Jan 2008.
-                 // See also Acquire_Load(), below.
-
-  // When new chips come out, check:
-  //  IA-32 Intel Architecture Software Developer's Manual, Volume 3:
-  //  System Programming Guide, Chatper 7: Multiple-processor management,
-  //  Section 7.2, Memory Ordering.
-  // Last seen at:
-  //   http://developer.intel.com/design/pentium4/manuals/index_new.htm
-  //
-  // x86 stores/loads fail to act as barriers for a few instructions (clflush
-  // maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are
-  // not generated by the compiler, and are rare.  Users of these instructions
-  // need to know about cache behaviour in any case since all of these involve
-  // either flushing cache lines or non-temporal cache hints.
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
-  return *ptr;
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
-  Atomic64 value = *ptr;  // An x86 load acts as a acquire barrier,
-                          // for current AMD/Intel chips as of Jan 2008.
-                          // See also Release_Store(), above.
-  ATOMICOPS_COMPILER_BARRIER();
-  return value;
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
-  MemoryBarrier();
-  return *ptr;
-}
-
-inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
-                                       Atomic64 old_value,
-                                       Atomic64 new_value) {
-  Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-  if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
-    __asm__ __volatile__("lfence" : : : "memory");
-  }
-  return x;
-}
-
-inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
-                                       Atomic64 old_value,
-                                       Atomic64 new_value) {
-  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-#endif  // defined(__x86_64__)
-
-}  // namespace base::subtle
-}  // namespace base
-
-#undef ATOMICOPS_COMPILER_BARRIER
-
-#endif  // CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_GCC_H_
diff --git a/src/include/base/internal/cef_atomicops_x86_msvc.h b/src/include/base/internal/cef_atomicops_x86_msvc.h
deleted file mode 100644
index a262c81..0000000
--- a/src/include/base/internal/cef_atomicops_x86_msvc.h
+++ /dev/null
@@ -1,221 +0,0 @@
-// Copyright (c) 2008 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Do not include this header file directly. Use base/cef_atomicops.h
-// instead.
-
-#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_MSVC_H_
-#define CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_MSVC_H_
-
-#include <windows.h>
-
-#include <intrin.h>
-
-#include "include/base/cef_macros.h"
-
-#if defined(ARCH_CPU_64_BITS)
-// windows.h #defines this (only on x64). This causes problems because the
-// public API also uses MemoryBarrier at the public name for this fence. So, on
-// X64, undef it, and call its documented
-// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
-// implementation directly.
-#undef MemoryBarrier
-#endif
-
-namespace base {
-namespace subtle {
-
-inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
-                                         Atomic32 old_value,
-                                         Atomic32 new_value) {
-  LONG result = _InterlockedCompareExchange(
-      reinterpret_cast<volatile LONG*>(ptr), static_cast<LONG>(new_value),
-      static_cast<LONG>(old_value));
-  return static_cast<Atomic32>(result);
-}
-
-inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
-                                         Atomic32 new_value) {
-  LONG result = _InterlockedExchange(reinterpret_cast<volatile LONG*>(ptr),
-                                     static_cast<LONG>(new_value));
-  return static_cast<Atomic32>(result);
-}
-
-inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
-                                        Atomic32 increment) {
-  return _InterlockedExchangeAdd(reinterpret_cast<volatile LONG*>(ptr),
-                                 static_cast<LONG>(increment)) +
-         increment;
-}
-
-inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
-                                          Atomic32 increment) {
-  return Barrier_AtomicIncrement(ptr, increment);
-}
-
-#if !(defined(_MSC_VER) && _MSC_VER >= 1400)
-#error "We require at least vs2005 for MemoryBarrier"
-#endif
-inline void MemoryBarrier() {
-#if defined(ARCH_CPU_64_BITS)
-  // See #undef and note at the top of this file.
-  __faststorefence();
-#else
-  // We use MemoryBarrier from WinNT.h
-  ::MemoryBarrier();
-#endif
-}
-
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
-                                       Atomic32 old_value,
-                                       Atomic32 new_value) {
-  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
-                                       Atomic32 old_value,
-                                       Atomic32 new_value) {
-  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
-  *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
-  NoBarrier_AtomicExchange(ptr, value);
-  // acts as a barrier in this implementation
-}
-
-inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
-  *ptr = value;  // works w/o barrier for current Intel chips as of June 2005
-  // See comments in Atomic64 version of Release_Store() below.
-}
-
-inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
-  return *ptr;
-}
-
-inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
-  Atomic32 value = *ptr;
-  return value;
-}
-
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
-  MemoryBarrier();
-  return *ptr;
-}
-
-#if defined(_WIN64)
-
-// 64-bit low-level operations on 64-bit platform.
-
-COMPILE_ASSERT(sizeof(Atomic64) == sizeof(PVOID), atomic_word_is_atomic);
-
-inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
-                                         Atomic64 old_value,
-                                         Atomic64 new_value) {
-  PVOID result = InterlockedCompareExchangePointer(
-      reinterpret_cast<volatile PVOID*>(ptr),
-      reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value));
-  return reinterpret_cast<Atomic64>(result);
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
-                                         Atomic64 new_value) {
-  PVOID result =
-      InterlockedExchangePointer(reinterpret_cast<volatile PVOID*>(ptr),
-                                 reinterpret_cast<PVOID>(new_value));
-  return reinterpret_cast<Atomic64>(result);
-}
-
-inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
-                                        Atomic64 increment) {
-  return InterlockedExchangeAdd64(reinterpret_cast<volatile LONGLONG*>(ptr),
-                                  static_cast<LONGLONG>(increment)) +
-         increment;
-}
-
-inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
-                                          Atomic64 increment) {
-  return Barrier_AtomicIncrement(ptr, increment);
-}
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
-  *ptr = value;
-}
-
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
-  NoBarrier_AtomicExchange(ptr, value);
-  // acts as a barrier in this implementation
-}
-
-inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
-  *ptr = value;  // works w/o barrier for current Intel chips as of June 2005
-
-  // When new chips come out, check:
-  //  IA-32 Intel Architecture Software Developer's Manual, Volume 3:
-  //  System Programming Guide, Chatper 7: Multiple-processor management,
-  //  Section 7.2, Memory Ordering.
-  // Last seen at:
-  //   http://developer.intel.com/design/pentium4/manuals/index_new.htm
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
-  return *ptr;
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
-  Atomic64 value = *ptr;
-  return value;
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
-  MemoryBarrier();
-  return *ptr;
-}
-
-inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
-                                       Atomic64 old_value,
-                                       Atomic64 new_value) {
-  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
-                                       Atomic64 old_value,
-                                       Atomic64 new_value) {
-  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
-}
-
-#endif  // defined(_WIN64)
-
-}  // namespace base::subtle
-}  // namespace base
-
-#endif  // CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_MSVC_H_
diff --git a/src/include/base/internal/cef_bind_internal.h b/src/include/base/internal/cef_bind_internal.h
index 64eeb3f..fddfec0 100644
--- a/src/include/base/internal/cef_bind_internal.h
+++ b/src/include/base/internal/cef_bind_internal.h
@@ -29,769 +29,340 @@
 
 // Do not include this header file directly. Use base/cef_bind.h instead.
 
+// See base/cef_callback.h for user documentation.
+//
+//
+// CONCEPTS:
+//  Functor -- A movable type representing something that should be called.
+//             All function pointers and Callback<> are functors even if the
+//             invocation syntax differs.
+//  RunType -- A function type (as opposed to function _pointer_ type) for
+//             a Callback<>::Run().  Usually just a convenience typedef.
+//  (Bound)Args -- A set of types that stores the arguments.
+//
+// Types:
+//  ForceVoidReturn<> -- Helper class for translating function signatures to
+//                       equivalent forms with a "void" return type.
+//  FunctorTraits<> -- Type traits used to determine the correct RunType and
+//                     invocation manner for a Functor.  This is where function
+//                     signature adapters are applied.
+//  InvokeHelper<> -- Take a Functor + arguments and actully invokes it.
+//                    Handle the differing syntaxes needed for WeakPtr<>
+//                    support.  This is separate from Invoker to avoid creating
+//                    multiple version of Invoker<>.
+//  Invoker<> -- Unwraps the curried parameters and executes the Functor.
+//  BindState<> -- Stores the curried parameters, and is the main entry point
+//                 into the Bind() system.
+
 #ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_H_
 #define CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_H_
 
-#include "include/base/cef_bind_helpers.h"
+#include <stddef.h>
+
+#include <functional>
+#include <memory>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
 #include "include/base/cef_build.h"
-#include "include/base/cef_template_util.h"
+#include "include/base/cef_compiler_specific.h"
+#include "include/base/cef_logging.h"
 #include "include/base/cef_weak_ptr.h"
 #include "include/base/internal/cef_callback_internal.h"
 #include "include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h"
 
+#if defined(OS_APPLE) && !HAS_FEATURE(objc_arc)
+#include "include/base/internal/cef_scoped_block_mac.h"
+#endif
+
 #if defined(OS_WIN)
-#include "include/base/internal/cef_bind_internal_win.h"
+namespace Microsoft {
+namespace WRL {
+template <typename>
+class ComPtr;
+}  // namespace WRL
+}  // namespace Microsoft
 #endif
 
 namespace base {
+
+template <typename T>
+struct IsWeakReceiver;
+
+template <typename>
+struct BindUnwrapTraits;
+
+template <typename Functor, typename BoundArgsTuple, typename SFINAE = void>
+struct CallbackCancellationTraits;
+
 namespace cef_internal {
 
-// See base/callback.h for user documentation.
+template <typename Functor, typename SFINAE = void>
+struct FunctorTraits;
+
+template <typename T>
+class UnretainedWrapper {
+ public:
+  explicit UnretainedWrapper(T* o) : ptr_(o) {}
+  T* get() const { return ptr_; }
+
+ private:
+  T* ptr_;
+};
+
+template <typename T>
+class RetainedRefWrapper {
+ public:
+  explicit RetainedRefWrapper(T* o) : ptr_(o) {}
+  explicit RetainedRefWrapper(scoped_refptr<T> o) : ptr_(std::move(o)) {}
+  T* get() const { return ptr_.get(); }
+
+ private:
+  scoped_refptr<T> ptr_;
+};
+
+template <typename T>
+struct IgnoreResultHelper {
+  explicit IgnoreResultHelper(T functor) : functor_(std::move(functor)) {}
+  explicit operator bool() const { return !!functor_; }
+
+  T functor_;
+};
+
+template <typename T, typename Deleter = std::default_delete<T>>
+class OwnedWrapper {
+ public:
+  explicit OwnedWrapper(T* o) : ptr_(o) {}
+  explicit OwnedWrapper(std::unique_ptr<T, Deleter>&& ptr)
+      : ptr_(std::move(ptr)) {}
+  T* get() const { return ptr_.get(); }
+
+ private:
+  std::unique_ptr<T, Deleter> ptr_;
+};
+
+template <typename T>
+class OwnedRefWrapper {
+ public:
+  explicit OwnedRefWrapper(const T& t) : t_(t) {}
+  explicit OwnedRefWrapper(T&& t) : t_(std::move(t)) {}
+  T& get() const { return t_; }
+
+ private:
+  mutable T t_;
+};
+
+// PassedWrapper is a copyable adapter for a scoper that ignores const.
 //
+// It is needed to get around the fact that Bind() takes a const reference to
+// all its arguments.  Because Bind() takes a const reference to avoid
+// unnecessary copies, it is incompatible with movable-but-not-copyable
+// types; doing a destructive "move" of the type into Bind() would violate
+// the const correctness.
 //
-// CONCEPTS:
-//  Runnable -- A type (really a type class) that has a single Run() method
-//              and a RunType typedef that corresponds to the type of Run().
-//              A Runnable can declare that it should treated like a method
-//              call by including a typedef named IsMethod.  The value of
-//              this typedef is NOT inspected, only the existence.  When a
-//              Runnable declares itself a method, Bind() will enforce special
-//              refcounting + WeakPtr handling semantics for the first
-//              parameter which is expected to be an object.
-//  Functor -- A copyable type representing something that should be called.
-//             All function pointers, Callback<>, and Runnables are functors
-//             even if the invocation syntax differs.
-//  RunType -- A function type (as opposed to function _pointer_ type) for
-//             a Run() function.  Usually just a convenience typedef.
-//  (Bound)ArgsType -- A function type that is being (ab)used to store the
-//                     types of set of arguments.  The "return" type is always
-//                     void here.  We use this hack so that we do not need
-//                     a new type name for each arity of type. (eg.,
-//                     BindState1, BindState2).  This makes forward
-//                     declarations and friending much much easier.
+// This conundrum cannot be solved without either C++11 rvalue references or
+// a O(2^n) blowup of Bind() templates to handle each combination of regular
+// types and movable-but-not-copyable types.  Thus we introduce a wrapper type
+// that is copyable to transmit the correct type information down into
+// BindState<>. Ignoring const in this type makes sense because it is only
+// created when we are explicitly trying to do a destructive move.
 //
-// Types:
-//  RunnableAdapter<> -- Wraps the various "function" pointer types into an
-//                       object that adheres to the Runnable interface.
-//                       There are |3*ARITY| RunnableAdapter types.
-//  FunctionTraits<> -- Type traits that unwrap a function signature into a
-//                      a set of easier to use typedefs.  Used mainly for
-//                      compile time asserts.
-//                      There are |ARITY| FunctionTraits types.
-//  ForceVoidReturn<> -- Helper class for translating function signatures to
-//                       equivalent forms with a "void" return type.
-//                    There are |ARITY| ForceVoidReturn types.
-//  FunctorTraits<> -- Type traits used determine the correct RunType and
-//                     RunnableType for a Functor.  This is where function
-//                     signature adapters are applied.
-//                    There are |ARITY| ForceVoidReturn types.
-//  MakeRunnable<> -- Takes a Functor and returns an object in the Runnable
-//                    type class that represents the underlying Functor.
-//                    There are |O(1)| MakeRunnable types.
-//  InvokeHelper<> -- Take a Runnable + arguments and actully invokes it.
-// Handle the differing syntaxes needed for WeakPtr<> support,
-//                    and for ignoring return values.  This is separate from
-//                    Invoker to avoid creating multiple version of Invoker<>
-//                    which grows at O(n^2) with the arity.
-//                    There are |k*ARITY| InvokeHelper types.
-//  Invoker<> -- Unwraps the curried parameters and executes the Runnable.
-//               There are |(ARITY^2 + ARITY)/2| Invoketypes.
-//  BindState<> -- Stores the curried parameters, and is the main entry point
-//                 into the Bind() system, doing most of the type resolution.
-//                 There are ARITY BindState types.
+// Two notes:
+//  1) PassedWrapper supports any type that has a move constructor, however
+//     the type will need to be specifically allowed in order for it to be
+//     bound to a Callback. We guard this explicitly at the call of Passed()
+//     to make for clear errors. Things not given to Passed() will be forwarded
+//     and stored by value which will not work for general move-only types.
+//  2) is_valid_ is distinct from NULL because it is valid to bind a "NULL"
+//     scoper to a Callback and allow the Callback to execute once.
+template <typename T>
+class PassedWrapper {
+ public:
+  explicit PassedWrapper(T&& scoper)
+      : is_valid_(true), scoper_(std::move(scoper)) {}
+  PassedWrapper(PassedWrapper&& other)
+      : is_valid_(other.is_valid_), scoper_(std::move(other.scoper_)) {}
+  T Take() const {
+    CHECK(is_valid_);
+    is_valid_ = false;
+    return std::move(scoper_);
+  }
 
-// RunnableAdapter<>
+ private:
+  mutable bool is_valid_;
+  mutable T scoper_;
+};
+
+template <typename T>
+using Unwrapper = BindUnwrapTraits<std::decay_t<T>>;
+
+template <typename T>
+decltype(auto) Unwrap(T&& o) {
+  return Unwrapper<T>::Unwrap(std::forward<T>(o));
+}
+
+// IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a
+// method.  It is used internally by Bind() to select the correct
+// InvokeHelper that will no-op itself in the event the WeakPtr<> for
+// the target object is invalidated.
 //
-// The RunnableAdapter<> templates provide a uniform interface for invoking
-// a function pointer, method pointer, or const method pointer. The adapter
-// exposes a Run() method with an appropriate signature. Using this wrapper
-// allows for writing code that supports all three pointer types without
-// undue repetition.  Without it, a lot of code would need to be repeated 3
-// times.
+// The first argument should be the type of the object that will be received by
+// the method.
+template <bool is_method, typename... Args>
+struct IsWeakMethod : std::false_type {};
+
+template <typename T, typename... Args>
+struct IsWeakMethod<true, T, Args...> : IsWeakReceiver<T> {};
+
+// Packs a list of types to hold them in a single type.
+template <typename... Types>
+struct TypeList {};
+
+// Used for DropTypeListItem implementation.
+template <size_t n, typename List>
+struct DropTypeListItemImpl;
+
+// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure.
+template <size_t n, typename T, typename... List>
+struct DropTypeListItemImpl<n, TypeList<T, List...>>
+    : DropTypeListItemImpl<n - 1, TypeList<List...>> {};
+
+template <typename T, typename... List>
+struct DropTypeListItemImpl<0, TypeList<T, List...>> {
+  using Type = TypeList<T, List...>;
+};
+
+template <>
+struct DropTypeListItemImpl<0, TypeList<>> {
+  using Type = TypeList<>;
+};
+
+// A type-level function that drops |n| list item from given TypeList.
+template <size_t n, typename List>
+using DropTypeListItem = typename DropTypeListItemImpl<n, List>::Type;
+
+// Used for TakeTypeListItem implementation.
+template <size_t n, typename List, typename... Accum>
+struct TakeTypeListItemImpl;
+
+// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure.
+template <size_t n, typename T, typename... List, typename... Accum>
+struct TakeTypeListItemImpl<n, TypeList<T, List...>, Accum...>
+    : TakeTypeListItemImpl<n - 1, TypeList<List...>, Accum..., T> {};
+
+template <typename T, typename... List, typename... Accum>
+struct TakeTypeListItemImpl<0, TypeList<T, List...>, Accum...> {
+  using Type = TypeList<Accum...>;
+};
+
+template <typename... Accum>
+struct TakeTypeListItemImpl<0, TypeList<>, Accum...> {
+  using Type = TypeList<Accum...>;
+};
+
+// A type-level function that takes first |n| list item from given TypeList.
+// E.g. TakeTypeListItem<3, TypeList<A, B, C, D>> is evaluated to
+// TypeList<A, B, C>.
+template <size_t n, typename List>
+using TakeTypeListItem = typename TakeTypeListItemImpl<n, List>::Type;
+
+// Used for ConcatTypeLists implementation.
+template <typename List1, typename List2>
+struct ConcatTypeListsImpl;
+
+template <typename... Types1, typename... Types2>
+struct ConcatTypeListsImpl<TypeList<Types1...>, TypeList<Types2...>> {
+  using Type = TypeList<Types1..., Types2...>;
+};
+
+// A type-level function that concats two TypeLists.
+template <typename List1, typename List2>
+using ConcatTypeLists = typename ConcatTypeListsImpl<List1, List2>::Type;
+
+// Used for MakeFunctionType implementation.
+template <typename R, typename ArgList>
+struct MakeFunctionTypeImpl;
+
+template <typename R, typename... Args>
+struct MakeFunctionTypeImpl<R, TypeList<Args...>> {
+  // MSVC 2013 doesn't support Type Alias of function types.
+  // Revisit this after we update it to newer version.
+  typedef R Type(Args...);
+};
+
+// A type-level function that constructs a function type that has |R| as its
+// return type and has TypeLists items as its arguments.
+template <typename R, typename ArgList>
+using MakeFunctionType = typename MakeFunctionTypeImpl<R, ArgList>::Type;
+
+// Used for ExtractArgs and ExtractReturnType.
+template <typename Signature>
+struct ExtractArgsImpl;
+
+template <typename R, typename... Args>
+struct ExtractArgsImpl<R(Args...)> {
+  using ReturnType = R;
+  using ArgsList = TypeList<Args...>;
+};
+
+// A type-level function that extracts function arguments into a TypeList.
+// E.g. ExtractArgs<R(A, B, C)> is evaluated to TypeList<A, B, C>.
+template <typename Signature>
+using ExtractArgs = typename ExtractArgsImpl<Signature>::ArgsList;
+
+// A type-level function that extracts the return type of a function.
+// E.g. ExtractReturnType<R(A, B, C)> is evaluated to R.
+template <typename Signature>
+using ExtractReturnType = typename ExtractArgsImpl<Signature>::ReturnType;
+
+template <typename Callable,
+          typename Signature = decltype(&Callable::operator())>
+struct ExtractCallableRunTypeImpl;
+
+template <typename Callable, typename R, typename... Args>
+struct ExtractCallableRunTypeImpl<Callable, R (Callable::*)(Args...)> {
+  using Type = R(Args...);
+};
+
+template <typename Callable, typename R, typename... Args>
+struct ExtractCallableRunTypeImpl<Callable, R (Callable::*)(Args...) const> {
+  using Type = R(Args...);
+};
+
+// Evaluated to RunType of the given callable type.
+// Example:
+//   auto f = [](int, char*) { return 0.1; };
+//   ExtractCallableRunType<decltype(f)>
+//   is evaluated to
+//   double(int, char*);
+template <typename Callable>
+using ExtractCallableRunType =
+    typename ExtractCallableRunTypeImpl<Callable>::Type;
+
+// IsCallableObject<Functor> is std::true_type if |Functor| has operator().
+// Otherwise, it's std::false_type.
+// Example:
+//   IsCallableObject<void(*)()>::value is false.
 //
-// For method pointers and const method pointers the first argument to Run()
-// is considered to be the received of the method.  This is similar to STL's
-// mem_fun().
+//   struct Foo {};
+//   IsCallableObject<void(Foo::*)()>::value is false.
 //
-// This class also exposes a RunType typedef that is the function type of the
-// Run() function.
-//
-// If and only if the wrapper contains a method or const method pointer, an
-// IsMethod typedef is exposed.  The existence of this typedef (NOT the value)
-// marks that the wrapper should be considered a method wrapper.
+//   int i = 0;
+//   auto f = [i]() {};
+//   IsCallableObject<decltype(f)>::value is false.
+template <typename Functor, typename SFINAE = void>
+struct IsCallableObject : std::false_type {};
 
-template <typename Functor>
-class RunnableAdapter;
+template <typename Callable>
+struct IsCallableObject<Callable, std::void_t<decltype(&Callable::operator())>>
+    : std::true_type {};
 
-// Function: Arity 0.
-template <typename R>
-class RunnableAdapter<R (*)()> {
- public:
-  typedef R(RunType)();
-
-  explicit RunnableAdapter(R (*function)()) : function_(function) {}
-
-  R Run() { return function_(); }
-
- private:
-  R (*function_)();
-};
-
-// Method: Arity 0.
-template <typename R, typename T>
-class RunnableAdapter<R (T::*)()> {
- public:
-  typedef R(RunType)(T*);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R (T::*method)()) : method_(method) {}
-
-  R Run(T* object) { return (object->*method_)(); }
-
- private:
-  R (T::*method_)();
-};
-
-// Const Method: Arity 0.
-template <typename R, typename T>
-class RunnableAdapter<R (T::*)() const> {
- public:
-  typedef R(RunType)(const T*);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R (T::*method)() const) : method_(method) {}
-
-  R Run(const T* object) { return (object->*method_)(); }
-
- private:
-  R (T::*method_)() const;
-};
-
-// Function: Arity 1.
-template <typename R, typename A1>
-class RunnableAdapter<R (*)(A1)> {
- public:
-  typedef R(RunType)(A1);
-
-  explicit RunnableAdapter(R (*function)(A1)) : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1) {
-    return function_(CallbackForward(a1));
-  }
-
- private:
-  R (*function_)(A1);
-};
-
-// Method: Arity 1.
-template <typename R, typename T, typename A1>
-class RunnableAdapter<R (T::*)(A1)> {
- public:
-  typedef R(RunType)(T*, A1);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R (T::*method)(A1)) : method_(method) {}
-
-  R Run(T* object, typename CallbackParamTraits<A1>::ForwardType a1) {
-    return (object->*method_)(CallbackForward(a1));
-  }
-
- private:
-  R (T::*method_)(A1);
-};
-
-// Const Method: Arity 1.
-template <typename R, typename T, typename A1>
-class RunnableAdapter<R (T::*)(A1) const> {
- public:
-  typedef R(RunType)(const T*, A1);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R (T::*method)(A1) const) : method_(method) {}
-
-  R Run(const T* object, typename CallbackParamTraits<A1>::ForwardType a1) {
-    return (object->*method_)(CallbackForward(a1));
-  }
-
- private:
-  R (T::*method_)(A1) const;
-};
-
-// Function: Arity 2.
-template <typename R, typename A1, typename A2>
-class RunnableAdapter<R (*)(A1, A2)> {
- public:
-  typedef R(RunType)(A1, A2);
-
-  explicit RunnableAdapter(R (*function)(A1, A2)) : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2) {
-    return function_(CallbackForward(a1), CallbackForward(a2));
-  }
-
- private:
-  R (*function_)(A1, A2);
-};
-
-// Method: Arity 2.
-template <typename R, typename T, typename A1, typename A2>
-class RunnableAdapter<R (T::*)(A1, A2)> {
- public:
-  typedef R(RunType)(T*, A1, A2);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R (T::*method)(A1, A2)) : method_(method) {}
-
-  R Run(T* object,
-        typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2));
-  }
-
- private:
-  R (T::*method_)(A1, A2);
-};
-
-// Const Method: Arity 2.
-template <typename R, typename T, typename A1, typename A2>
-class RunnableAdapter<R (T::*)(A1, A2) const> {
- public:
-  typedef R(RunType)(const T*, A1, A2);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R (T::*method)(A1, A2) const) : method_(method) {}
-
-  R Run(const T* object,
-        typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2));
-  }
-
- private:
-  R (T::*method_)(A1, A2) const;
-};
-
-// Function: Arity 3.
-template <typename R, typename A1, typename A2, typename A3>
-class RunnableAdapter<R (*)(A1, A2, A3)> {
- public:
-  typedef R(RunType)(A1, A2, A3);
-
-  explicit RunnableAdapter(R (*function)(A1, A2, A3)) : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3) {
-    return function_(CallbackForward(a1), CallbackForward(a2),
-                     CallbackForward(a3));
-  }
-
- private:
-  R (*function_)(A1, A2, A3);
-};
-
-// Method: Arity 3.
-template <typename R, typename T, typename A1, typename A2, typename A3>
-class RunnableAdapter<R (T::*)(A1, A2, A3)> {
- public:
-  typedef R(RunType)(T*, A1, A2, A3);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R (T::*method)(A1, A2, A3)) : method_(method) {}
-
-  R Run(T* object,
-        typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-                              CallbackForward(a3));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3);
-};
-
-// Const Method: Arity 3.
-template <typename R, typename T, typename A1, typename A2, typename A3>
-class RunnableAdapter<R (T::*)(A1, A2, A3) const> {
- public:
-  typedef R(RunType)(const T*, A1, A2, A3);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R (T::*method)(A1, A2, A3) const)
-      : method_(method) {}
-
-  R Run(const T* object,
-        typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-                              CallbackForward(a3));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3) const;
-};
-
-// Function: Arity 4.
-template <typename R, typename A1, typename A2, typename A3, typename A4>
-class RunnableAdapter<R (*)(A1, A2, A3, A4)> {
- public:
-  typedef R(RunType)(A1, A2, A3, A4);
-
-  explicit RunnableAdapter(R (*function)(A1, A2, A3, A4))
-      : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4) {
-    return function_(CallbackForward(a1), CallbackForward(a2),
-                     CallbackForward(a3), CallbackForward(a4));
-  }
-
- private:
-  R (*function_)(A1, A2, A3, A4);
-};
-
-// Method: Arity 4.
-template <typename R,
-          typename T,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4>
-class RunnableAdapter<R (T::*)(A1, A2, A3, A4)> {
- public:
-  typedef R(RunType)(T*, A1, A2, A3, A4);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R (T::*method)(A1, A2, A3, A4)) : method_(method) {}
-
-  R Run(T* object,
-        typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-                              CallbackForward(a3), CallbackForward(a4));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3, A4);
-};
-
-// Const Method: Arity 4.
-template <typename R,
-          typename T,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4>
-class RunnableAdapter<R (T::*)(A1, A2, A3, A4) const> {
- public:
-  typedef R(RunType)(const T*, A1, A2, A3, A4);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R (T::*method)(A1, A2, A3, A4) const)
-      : method_(method) {}
-
-  R Run(const T* object,
-        typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-                              CallbackForward(a3), CallbackForward(a4));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3, A4) const;
-};
-
-// Function: Arity 5.
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5>
-class RunnableAdapter<R (*)(A1, A2, A3, A4, A5)> {
- public:
-  typedef R(RunType)(A1, A2, A3, A4, A5);
-
-  explicit RunnableAdapter(R (*function)(A1, A2, A3, A4, A5))
-      : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4,
-        typename CallbackParamTraits<A5>::ForwardType a5) {
-    return function_(CallbackForward(a1), CallbackForward(a2),
-                     CallbackForward(a3), CallbackForward(a4),
-                     CallbackForward(a5));
-  }
-
- private:
-  R (*function_)(A1, A2, A3, A4, A5);
-};
-
-// Method: Arity 5.
-template <typename R,
-          typename T,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5>
-class RunnableAdapter<R (T::*)(A1, A2, A3, A4, A5)> {
- public:
-  typedef R(RunType)(T*, A1, A2, A3, A4, A5);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R (T::*method)(A1, A2, A3, A4, A5))
-      : method_(method) {}
-
-  R Run(T* object,
-        typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4,
-        typename CallbackParamTraits<A5>::ForwardType a5) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-                              CallbackForward(a3), CallbackForward(a4),
-                              CallbackForward(a5));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3, A4, A5);
-};
-
-// Const Method: Arity 5.
-template <typename R,
-          typename T,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5>
-class RunnableAdapter<R (T::*)(A1, A2, A3, A4, A5) const> {
- public:
-  typedef R(RunType)(const T*, A1, A2, A3, A4, A5);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R (T::*method)(A1, A2, A3, A4, A5) const)
-      : method_(method) {}
-
-  R Run(const T* object,
-        typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4,
-        typename CallbackParamTraits<A5>::ForwardType a5) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-                              CallbackForward(a3), CallbackForward(a4),
-                              CallbackForward(a5));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3, A4, A5) const;
-};
-
-// Function: Arity 6.
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6>
-class RunnableAdapter<R (*)(A1, A2, A3, A4, A5, A6)> {
- public:
-  typedef R(RunType)(A1, A2, A3, A4, A5, A6);
-
-  explicit RunnableAdapter(R (*function)(A1, A2, A3, A4, A5, A6))
-      : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4,
-        typename CallbackParamTraits<A5>::ForwardType a5,
-        typename CallbackParamTraits<A6>::ForwardType a6) {
-    return function_(CallbackForward(a1), CallbackForward(a2),
-                     CallbackForward(a3), CallbackForward(a4),
-                     CallbackForward(a5), CallbackForward(a6));
-  }
-
- private:
-  R (*function_)(A1, A2, A3, A4, A5, A6);
-};
-
-// Method: Arity 6.
-template <typename R,
-          typename T,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6>
-class RunnableAdapter<R (T::*)(A1, A2, A3, A4, A5, A6)> {
- public:
-  typedef R(RunType)(T*, A1, A2, A3, A4, A5, A6);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R (T::*method)(A1, A2, A3, A4, A5, A6))
-      : method_(method) {}
-
-  R Run(T* object,
-        typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4,
-        typename CallbackParamTraits<A5>::ForwardType a5,
-        typename CallbackParamTraits<A6>::ForwardType a6) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-                              CallbackForward(a3), CallbackForward(a4),
-                              CallbackForward(a5), CallbackForward(a6));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3, A4, A5, A6);
-};
-
-// Const Method: Arity 6.
-template <typename R,
-          typename T,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6>
-class RunnableAdapter<R (T::*)(A1, A2, A3, A4, A5, A6) const> {
- public:
-  typedef R(RunType)(const T*, A1, A2, A3, A4, A5, A6);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R (T::*method)(A1, A2, A3, A4, A5, A6) const)
-      : method_(method) {}
-
-  R Run(const T* object,
-        typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4,
-        typename CallbackParamTraits<A5>::ForwardType a5,
-        typename CallbackParamTraits<A6>::ForwardType a6) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-                              CallbackForward(a3), CallbackForward(a4),
-                              CallbackForward(a5), CallbackForward(a6));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3, A4, A5, A6) const;
-};
-
-// Function: Arity 7.
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6,
-          typename A7>
-class RunnableAdapter<R (*)(A1, A2, A3, A4, A5, A6, A7)> {
- public:
-  typedef R(RunType)(A1, A2, A3, A4, A5, A6, A7);
-
-  explicit RunnableAdapter(R (*function)(A1, A2, A3, A4, A5, A6, A7))
-      : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4,
-        typename CallbackParamTraits<A5>::ForwardType a5,
-        typename CallbackParamTraits<A6>::ForwardType a6,
-        typename CallbackParamTraits<A7>::ForwardType a7) {
-    return function_(CallbackForward(a1), CallbackForward(a2),
-                     CallbackForward(a3), CallbackForward(a4),
-                     CallbackForward(a5), CallbackForward(a6),
-                     CallbackForward(a7));
-  }
-
- private:
-  R (*function_)(A1, A2, A3, A4, A5, A6, A7);
-};
-
-// Method: Arity 7.
-template <typename R,
-          typename T,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6,
-          typename A7>
-class RunnableAdapter<R (T::*)(A1, A2, A3, A4, A5, A6, A7)> {
- public:
-  typedef R(RunType)(T*, A1, A2, A3, A4, A5, A6, A7);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R (T::*method)(A1, A2, A3, A4, A5, A6, A7))
-      : method_(method) {}
-
-  R Run(T* object,
-        typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4,
-        typename CallbackParamTraits<A5>::ForwardType a5,
-        typename CallbackParamTraits<A6>::ForwardType a6,
-        typename CallbackParamTraits<A7>::ForwardType a7) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-                              CallbackForward(a3), CallbackForward(a4),
-                              CallbackForward(a5), CallbackForward(a6),
-                              CallbackForward(a7));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3, A4, A5, A6, A7);
-};
-
-// Const Method: Arity 7.
-template <typename R,
-          typename T,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6,
-          typename A7>
-class RunnableAdapter<R (T::*)(A1, A2, A3, A4, A5, A6, A7) const> {
- public:
-  typedef R(RunType)(const T*, A1, A2, A3, A4, A5, A6, A7);
-  typedef true_type IsMethod;
-
-  explicit RunnableAdapter(R (T::*method)(A1, A2, A3, A4, A5, A6, A7) const)
-      : method_(method) {}
-
-  R Run(const T* object,
-        typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4,
-        typename CallbackParamTraits<A5>::ForwardType a5,
-        typename CallbackParamTraits<A6>::ForwardType a6,
-        typename CallbackParamTraits<A7>::ForwardType a7) {
-    return (object->*method_)(CallbackForward(a1), CallbackForward(a2),
-                              CallbackForward(a3), CallbackForward(a4),
-                              CallbackForward(a5), CallbackForward(a6),
-                              CallbackForward(a7));
-  }
-
- private:
-  R (T::*method_)(A1, A2, A3, A4, A5, A6, A7) const;
-};
-
-// FunctionTraits<>
-//
-// Breaks a function signature apart into typedefs for easier introspection.
-template <typename Sig>
-struct FunctionTraits;
-
-template <typename R>
-struct FunctionTraits<R()> {
-  typedef R ReturnType;
-};
-
-template <typename R, typename A1>
-struct FunctionTraits<R(A1)> {
-  typedef R ReturnType;
-  typedef A1 A1Type;
-};
-
-template <typename R, typename A1, typename A2>
-struct FunctionTraits<R(A1, A2)> {
-  typedef R ReturnType;
-  typedef A1 A1Type;
-  typedef A2 A2Type;
-};
-
-template <typename R, typename A1, typename A2, typename A3>
-struct FunctionTraits<R(A1, A2, A3)> {
-  typedef R ReturnType;
-  typedef A1 A1Type;
-  typedef A2 A2Type;
-  typedef A3 A3Type;
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4>
-struct FunctionTraits<R(A1, A2, A3, A4)> {
-  typedef R ReturnType;
-  typedef A1 A1Type;
-  typedef A2 A2Type;
-  typedef A3 A3Type;
-  typedef A4 A4Type;
-};
-
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5>
-struct FunctionTraits<R(A1, A2, A3, A4, A5)> {
-  typedef R ReturnType;
-  typedef A1 A1Type;
-  typedef A2 A2Type;
-  typedef A3 A3Type;
-  typedef A4 A4Type;
-  typedef A5 A5Type;
-};
-
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6>
-struct FunctionTraits<R(A1, A2, A3, A4, A5, A6)> {
-  typedef R ReturnType;
-  typedef A1 A1Type;
-  typedef A2 A2Type;
-  typedef A3 A3Type;
-  typedef A4 A4Type;
-  typedef A5 A5Type;
-  typedef A6 A6Type;
-};
-
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6,
-          typename A7>
-struct FunctionTraits<R(A1, A2, A3, A4, A5, A6, A7)> {
-  typedef R ReturnType;
-  typedef A1 A1Type;
-  typedef A2 A2Type;
-  typedef A3 A3Type;
-  typedef A4 A4Type;
-  typedef A5 A5Type;
-  typedef A6 A6Type;
-  typedef A7 A7Type;
-};
+// HasRefCountedTypeAsRawPtr inherits from true_type when any of the |Args| is a
+// raw pointer to a RefCounted type.
+template <typename... Ts>
+struct HasRefCountedTypeAsRawPtr
+    : std::disjunction<NeedsScopedRefptrButGetsRawPtr<Ts>...> {};
 
 // ForceVoidReturn<>
 //
@@ -799,2392 +370,1045 @@
 template <typename Sig>
 struct ForceVoidReturn;
 
-template <typename R>
-struct ForceVoidReturn<R()> {
-  typedef void(RunType)();
-};
-
-template <typename R, typename A1>
-struct ForceVoidReturn<R(A1)> {
-  typedef void(RunType)(A1);
-};
-
-template <typename R, typename A1, typename A2>
-struct ForceVoidReturn<R(A1, A2)> {
-  typedef void(RunType)(A1, A2);
-};
-
-template <typename R, typename A1, typename A2, typename A3>
-struct ForceVoidReturn<R(A1, A2, A3)> {
-  typedef void(RunType)(A1, A2, A3);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4>
-struct ForceVoidReturn<R(A1, A2, A3, A4)> {
-  typedef void(RunType)(A1, A2, A3, A4);
-};
-
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5>
-struct ForceVoidReturn<R(A1, A2, A3, A4, A5)> {
-  typedef void(RunType)(A1, A2, A3, A4, A5);
-};
-
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6>
-struct ForceVoidReturn<R(A1, A2, A3, A4, A5, A6)> {
-  typedef void(RunType)(A1, A2, A3, A4, A5, A6);
-};
-
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6,
-          typename A7>
-struct ForceVoidReturn<R(A1, A2, A3, A4, A5, A6, A7)> {
-  typedef void(RunType)(A1, A2, A3, A4, A5, A6, A7);
+template <typename R, typename... Args>
+struct ForceVoidReturn<R(Args...)> {
+  using RunType = void(Args...);
 };
 
 // FunctorTraits<>
 //
 // See description at top of file.
-template <typename T>
-struct FunctorTraits {
-  typedef RunnableAdapter<T> RunnableType;
-  typedef typename RunnableType::RunType RunType;
-};
+template <typename Functor, typename SFINAE>
+struct FunctorTraits;
 
-template <typename T>
-struct FunctorTraits<IgnoreResultHelper<T>> {
-  typedef typename FunctorTraits<T>::RunnableType RunnableType;
-  typedef
-      typename ForceVoidReturn<typename RunnableType::RunType>::RunType RunType;
-};
-
-template <typename T>
-struct FunctorTraits<Callback<T>> {
-  typedef Callback<T> RunnableType;
-  typedef typename Callback<T>::RunType RunType;
-};
-
-// MakeRunnable<>
+// For empty callable types.
+// This specialization is intended to allow binding captureless lambdas, based
+// on the fact that captureless lambdas are empty while capturing lambdas are
+// not. This also allows any functors as far as it's an empty class.
+// Example:
 //
-// Converts a passed in functor to a RunnableType using type inference.
+//   // Captureless lambdas are allowed.
+//   []() {return 42;};
+//
+//   // Capturing lambdas are *not* allowed.
+//   int x;
+//   [x]() {return x;};
+//
+//   // Any empty class with operator() is allowed.
+//   struct Foo {
+//     void operator()() const {}
+//     // No non-static member variable and no virtual functions.
+//   };
+template <typename Functor>
+struct FunctorTraits<Functor,
+                     std::enable_if_t<IsCallableObject<Functor>::value &&
+                                      std::is_empty<Functor>::value>> {
+  using RunType = ExtractCallableRunType<Functor>;
+  static constexpr bool is_method = false;
+  static constexpr bool is_nullable = false;
+  static constexpr bool is_callback = false;
 
-template <typename T>
-typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) {
-  return RunnableAdapter<T>(t);
-}
+  template <typename RunFunctor, typename... RunArgs>
+  static ExtractReturnType<RunType> Invoke(RunFunctor&& functor,
+                                           RunArgs&&... args) {
+    return std::forward<RunFunctor>(functor)(std::forward<RunArgs>(args)...);
+  }
+};
 
-template <typename T>
-typename FunctorTraits<T>::RunnableType MakeRunnable(
-    const IgnoreResultHelper<T>& t) {
-  return MakeRunnable(t.functor_);
-}
+// For functions.
+template <typename R, typename... Args>
+struct FunctorTraits<R (*)(Args...)> {
+  using RunType = R(Args...);
+  static constexpr bool is_method = false;
+  static constexpr bool is_nullable = true;
+  static constexpr bool is_callback = false;
 
+  template <typename Function, typename... RunArgs>
+  static R Invoke(Function&& function, RunArgs&&... args) {
+    return std::forward<Function>(function)(std::forward<RunArgs>(args)...);
+  }
+};
+
+#if defined(OS_WIN) && !defined(ARCH_CPU_64_BITS)
+
+// For functions.
+template <typename R, typename... Args>
+struct FunctorTraits<R(__stdcall*)(Args...)> {
+  using RunType = R(Args...);
+  static constexpr bool is_method = false;
+  static constexpr bool is_nullable = true;
+  static constexpr bool is_callback = false;
+
+  template <typename... RunArgs>
+  static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) {
+    return function(std::forward<RunArgs>(args)...);
+  }
+};
+
+// For functions.
+template <typename R, typename... Args>
+struct FunctorTraits<R(__fastcall*)(Args...)> {
+  using RunType = R(Args...);
+  static constexpr bool is_method = false;
+  static constexpr bool is_nullable = true;
+  static constexpr bool is_callback = false;
+
+  template <typename... RunArgs>
+  static R Invoke(R(__fastcall* function)(Args...), RunArgs&&... args) {
+    return function(std::forward<RunArgs>(args)...);
+  }
+};
+
+#endif  // defined(OS_WIN) && !defined(ARCH_CPU_64_BITS)
+
+#if defined(OS_APPLE)
+
+// Support for Objective-C blocks. There are two implementation depending
+// on whether Automated Reference Counting (ARC) is enabled. When ARC is
+// enabled, then the block itself can be bound as the compiler will ensure
+// its lifetime will be correctly managed. Otherwise, require the block to
+// be wrapped in a base::mac::ScopedBlock (via base::RetainBlock) that will
+// correctly manage the block lifetime.
+//
+// The two implementation ensure that the One Definition Rule (ODR) is not
+// broken (it is not possible to write a template base::RetainBlock that would
+// work correctly both with ARC enabled and disabled).
+
+#if HAS_FEATURE(objc_arc)
+
+template <typename R, typename... Args>
+struct FunctorTraits<R (^)(Args...)> {
+  using RunType = R(Args...);
+  static constexpr bool is_method = false;
+  static constexpr bool is_nullable = true;
+  static constexpr bool is_callback = false;
+
+  template <typename BlockType, typename... RunArgs>
+  static R Invoke(BlockType&& block, RunArgs&&... args) {
+    // According to LLVM documentation (6.3), "local variables of automatic
+    // storage duration do not have precise lifetime." Use objc_precise_lifetime
+    // to ensure that the Objective-C block is not deallocated until it has
+    // finished executing even if the Callback<> is destroyed during the block
+    // execution.
+    // https://clang.llvm.org/docs/AutomaticReferenceCounting.html#precise-lifetime-semantics
+    __attribute__((objc_precise_lifetime)) R (^scoped_block)(Args...) = block;
+    return scoped_block(std::forward<RunArgs>(args)...);
+  }
+};
+
+#else  // HAS_FEATURE(objc_arc)
+
+template <typename R, typename... Args>
+struct FunctorTraits<base::mac::ScopedBlock<R (^)(Args...)>> {
+  using RunType = R(Args...);
+  static constexpr bool is_method = false;
+  static constexpr bool is_nullable = true;
+  static constexpr bool is_callback = false;
+
+  template <typename BlockType, typename... RunArgs>
+  static R Invoke(BlockType&& block, RunArgs&&... args) {
+    // Copy the block to ensure that the Objective-C block is not deallocated
+    // until it has finished executing even if the Callback<> is destroyed
+    // during the block execution.
+    base::mac::ScopedBlock<R (^)(Args...)> scoped_block(block);
+    return scoped_block.get()(std::forward<RunArgs>(args)...);
+  }
+};
+
+#endif  // HAS_FEATURE(objc_arc)
+#endif  // defined(OS_APPLE)
+
+// For methods.
+template <typename R, typename Receiver, typename... Args>
+struct FunctorTraits<R (Receiver::*)(Args...)> {
+  using RunType = R(Receiver*, Args...);
+  static constexpr bool is_method = true;
+  static constexpr bool is_nullable = true;
+  static constexpr bool is_callback = false;
+
+  template <typename Method, typename ReceiverPtr, typename... RunArgs>
+  static R Invoke(Method method,
+                  ReceiverPtr&& receiver_ptr,
+                  RunArgs&&... args) {
+    return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
+  }
+};
+
+// For const methods.
+template <typename R, typename Receiver, typename... Args>
+struct FunctorTraits<R (Receiver::*)(Args...) const> {
+  using RunType = R(const Receiver*, Args...);
+  static constexpr bool is_method = true;
+  static constexpr bool is_nullable = true;
+  static constexpr bool is_callback = false;
+
+  template <typename Method, typename ReceiverPtr, typename... RunArgs>
+  static R Invoke(Method method,
+                  ReceiverPtr&& receiver_ptr,
+                  RunArgs&&... args) {
+    return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
+  }
+};
+
+#if defined(OS_WIN) && !defined(ARCH_CPU_64_BITS)
+
+// For __stdcall methods.
+template <typename R, typename Receiver, typename... Args>
+struct FunctorTraits<R (__stdcall Receiver::*)(Args...)> {
+  using RunType = R(Receiver*, Args...);
+  static constexpr bool is_method = true;
+  static constexpr bool is_nullable = true;
+  static constexpr bool is_callback = false;
+
+  template <typename Method, typename ReceiverPtr, typename... RunArgs>
+  static R Invoke(Method method,
+                  ReceiverPtr&& receiver_ptr,
+                  RunArgs&&... args) {
+    return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
+  }
+};
+
+// For __stdcall const methods.
+template <typename R, typename Receiver, typename... Args>
+struct FunctorTraits<R (__stdcall Receiver::*)(Args...) const> {
+  using RunType = R(const Receiver*, Args...);
+  static constexpr bool is_method = true;
+  static constexpr bool is_nullable = true;
+  static constexpr bool is_callback = false;
+
+  template <typename Method, typename ReceiverPtr, typename... RunArgs>
+  static R Invoke(Method method,
+                  ReceiverPtr&& receiver_ptr,
+                  RunArgs&&... args) {
+    return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
+  }
+};
+
+#endif  // defined(OS_WIN) && !defined(ARCH_CPU_64_BITS)
+
+#ifdef __cpp_noexcept_function_type
+// noexcept makes a distinct function type in C++17.
+// I.e. `void(*)()` and `void(*)() noexcept` are same in pre-C++17, and
+// different in C++17.
+template <typename R, typename... Args>
+struct FunctorTraits<R (*)(Args...) noexcept> : FunctorTraits<R (*)(Args...)> {
+};
+
+template <typename R, typename Receiver, typename... Args>
+struct FunctorTraits<R (Receiver::*)(Args...) noexcept>
+    : FunctorTraits<R (Receiver::*)(Args...)> {};
+
+template <typename R, typename Receiver, typename... Args>
+struct FunctorTraits<R (Receiver::*)(Args...) const noexcept>
+    : FunctorTraits<R (Receiver::*)(Args...) const> {};
+#endif
+
+// For IgnoreResults.
 template <typename T>
-const typename FunctorTraits<Callback<T>>::RunnableType& MakeRunnable(
-    const Callback<T>& t) {
-  DCHECK(!t.is_null());
-  return t;
-}
+struct FunctorTraits<IgnoreResultHelper<T>> : FunctorTraits<T> {
+  using RunType =
+      typename ForceVoidReturn<typename FunctorTraits<T>::RunType>::RunType;
+
+  template <typename IgnoreResultType, typename... RunArgs>
+  static void Invoke(IgnoreResultType&& ignore_result_helper,
+                     RunArgs&&... args) {
+    FunctorTraits<T>::Invoke(
+        std::forward<IgnoreResultType>(ignore_result_helper).functor_,
+        std::forward<RunArgs>(args)...);
+  }
+};
+
+// For OnceCallbacks.
+template <typename R, typename... Args>
+struct FunctorTraits<OnceCallback<R(Args...)>> {
+  using RunType = R(Args...);
+  static constexpr bool is_method = false;
+  static constexpr bool is_nullable = true;
+  static constexpr bool is_callback = true;
+
+  template <typename CallbackType, typename... RunArgs>
+  static R Invoke(CallbackType&& callback, RunArgs&&... args) {
+    DCHECK(!callback.is_null());
+    return std::forward<CallbackType>(callback).Run(
+        std::forward<RunArgs>(args)...);
+  }
+};
+
+// For RepeatingCallbacks.
+template <typename R, typename... Args>
+struct FunctorTraits<RepeatingCallback<R(Args...)>> {
+  using RunType = R(Args...);
+  static constexpr bool is_method = false;
+  static constexpr bool is_nullable = true;
+  static constexpr bool is_callback = true;
+
+  template <typename CallbackType, typename... RunArgs>
+  static R Invoke(CallbackType&& callback, RunArgs&&... args) {
+    DCHECK(!callback.is_null());
+    return std::forward<CallbackType>(callback).Run(
+        std::forward<RunArgs>(args)...);
+  }
+};
+
+template <typename Functor>
+using MakeFunctorTraits = FunctorTraits<std::decay_t<Functor>>;
 
 // InvokeHelper<>
 //
-// There are 3 logical InvokeHelper<> specializations: normal, void-return,
-// WeakCalls.
+// There are 2 logical InvokeHelper<> specializations: normal, WeakCalls.
 //
 // The normal type just calls the underlying runnable.
 //
-// We need a InvokeHelper to handle void return types in order to support
-// IgnoreResult().  Normally, if the Runnable's RunType had a void return,
-// the template system would just accept "return functor.Run()" ignoring
-// the fact that a void function is being used with return. This piece of
-// sugar breaks though when the Runnable's RunType is not void.  Thus, we
-// need a partial specialization to change the syntax to drop the "return"
-// from the invocation call.
-//
-// WeakCalls similarly need special syntax that is applied to the first
-// argument to check if they should no-op themselves.
-template <bool IsWeakCall,
-          typename ReturnType,
-          typename Runnable,
-          typename ArgsType>
+// WeakCalls need special syntax that is applied to the first argument to check
+// if they should no-op themselves.
+template <bool is_weak_call, typename ReturnType>
 struct InvokeHelper;
 
-template <typename ReturnType, typename Runnable>
-struct InvokeHelper<false, ReturnType, Runnable, void()> {
-  static ReturnType MakeItSo(Runnable runnable) { return runnable.Run(); }
-};
-
-template <typename Runnable>
-struct InvokeHelper<false, void, Runnable, void()> {
-  static void MakeItSo(Runnable runnable) { runnable.Run(); }
-};
-
-template <typename ReturnType, typename Runnable, typename A1>
-struct InvokeHelper<false, ReturnType, Runnable, void(A1)> {
-  static ReturnType MakeItSo(Runnable runnable, A1 a1) {
-    return runnable.Run(CallbackForward(a1));
+template <typename ReturnType>
+struct InvokeHelper<false, ReturnType> {
+  template <typename Functor, typename... RunArgs>
+  static inline ReturnType MakeItSo(Functor&& functor, RunArgs&&... args) {
+    using Traits = MakeFunctorTraits<Functor>;
+    return Traits::Invoke(std::forward<Functor>(functor),
+                          std::forward<RunArgs>(args)...);
   }
 };
 
-template <typename Runnable, typename A1>
-struct InvokeHelper<false, void, Runnable, void(A1)> {
-  static void MakeItSo(Runnable runnable, A1 a1) {
-    runnable.Run(CallbackForward(a1));
-  }
-};
-
-template <typename Runnable, typename BoundWeakPtr>
-struct InvokeHelper<true, void, Runnable, void(BoundWeakPtr)> {
-  static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr) {
-    if (!weak_ptr.get()) {
-      return;
-    }
-    runnable.Run(weak_ptr.get());
-  }
-};
-
-template <typename ReturnType, typename Runnable, typename A1, typename A2>
-struct InvokeHelper<false, ReturnType, Runnable, void(A1, A2)> {
-  static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2) {
-    return runnable.Run(CallbackForward(a1), CallbackForward(a2));
-  }
-};
-
-template <typename Runnable, typename A1, typename A2>
-struct InvokeHelper<false, void, Runnable, void(A1, A2)> {
-  static void MakeItSo(Runnable runnable, A1 a1, A2 a2) {
-    runnable.Run(CallbackForward(a1), CallbackForward(a2));
-  }
-};
-
-template <typename Runnable, typename BoundWeakPtr, typename A2>
-struct InvokeHelper<true, void, Runnable, void(BoundWeakPtr, A2)> {
-  static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2) {
-    if (!weak_ptr.get()) {
-      return;
-    }
-    runnable.Run(weak_ptr.get(), CallbackForward(a2));
-  }
-};
-
-template <typename ReturnType,
-          typename Runnable,
-          typename A1,
-          typename A2,
-          typename A3>
-struct InvokeHelper<false, ReturnType, Runnable, void(A1, A2, A3)> {
-  static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3) {
-    return runnable.Run(CallbackForward(a1), CallbackForward(a2),
-                        CallbackForward(a3));
-  }
-};
-
-template <typename Runnable, typename A1, typename A2, typename A3>
-struct InvokeHelper<false, void, Runnable, void(A1, A2, A3)> {
-  static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3) {
-    runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3));
-  }
-};
-
-template <typename Runnable, typename BoundWeakPtr, typename A2, typename A3>
-struct InvokeHelper<true, void, Runnable, void(BoundWeakPtr, A2, A3)> {
-  static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2, A3 a3) {
-    if (!weak_ptr.get()) {
-      return;
-    }
-    runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3));
-  }
-};
-
-template <typename ReturnType,
-          typename Runnable,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4>
-struct InvokeHelper<false, ReturnType, Runnable, void(A1, A2, A3, A4)> {
-  static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4) {
-    return runnable.Run(CallbackForward(a1), CallbackForward(a2),
-                        CallbackForward(a3), CallbackForward(a4));
-  }
-};
-
-template <typename Runnable, typename A1, typename A2, typename A3, typename A4>
-struct InvokeHelper<false, void, Runnable, void(A1, A2, A3, A4)> {
-  static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4) {
-    runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3),
-                 CallbackForward(a4));
-  }
-};
-
-template <typename Runnable,
-          typename BoundWeakPtr,
-          typename A2,
-          typename A3,
-          typename A4>
-struct InvokeHelper<true, void, Runnable, void(BoundWeakPtr, A2, A3, A4)> {
-  static void MakeItSo(Runnable runnable,
-                       BoundWeakPtr weak_ptr,
-                       A2 a2,
-                       A3 a3,
-                       A4 a4) {
-    if (!weak_ptr.get()) {
-      return;
-    }
-    runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3),
-                 CallbackForward(a4));
-  }
-};
-
-template <typename ReturnType,
-          typename Runnable,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5>
-struct InvokeHelper<false, ReturnType, Runnable, void(A1, A2, A3, A4, A5)> {
-  static ReturnType MakeItSo(Runnable runnable,
-                             A1 a1,
-                             A2 a2,
-                             A3 a3,
-                             A4 a4,
-                             A5 a5) {
-    return runnable.Run(CallbackForward(a1), CallbackForward(a2),
-                        CallbackForward(a3), CallbackForward(a4),
-                        CallbackForward(a5));
-  }
-};
-
-template <typename Runnable,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5>
-struct InvokeHelper<false, void, Runnable, void(A1, A2, A3, A4, A5)> {
-  static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
-    runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3),
-                 CallbackForward(a4), CallbackForward(a5));
-  }
-};
-
-template <typename Runnable,
-          typename BoundWeakPtr,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5>
-struct InvokeHelper<true, void, Runnable, void(BoundWeakPtr, A2, A3, A4, A5)> {
-  static void MakeItSo(Runnable runnable,
-                       BoundWeakPtr weak_ptr,
-                       A2 a2,
-                       A3 a3,
-                       A4 a4,
-                       A5 a5) {
-    if (!weak_ptr.get()) {
-      return;
-    }
-    runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3),
-                 CallbackForward(a4), CallbackForward(a5));
-  }
-};
-
-template <typename ReturnType,
-          typename Runnable,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6>
-struct InvokeHelper<false, ReturnType, Runnable, void(A1, A2, A3, A4, A5, A6)> {
-  static ReturnType
-  MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
-    return runnable.Run(CallbackForward(a1), CallbackForward(a2),
-                        CallbackForward(a3), CallbackForward(a4),
-                        CallbackForward(a5), CallbackForward(a6));
-  }
-};
-
-template <typename Runnable,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6>
-struct InvokeHelper<false, void, Runnable, void(A1, A2, A3, A4, A5, A6)> {
-  static void
-  MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
-    runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3),
-                 CallbackForward(a4), CallbackForward(a5), CallbackForward(a6));
-  }
-};
-
-template <typename Runnable,
-          typename BoundWeakPtr,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6>
-struct InvokeHelper<true,
-                    void,
-                    Runnable,
-                    void(BoundWeakPtr, A2, A3, A4, A5, A6)> {
-  static void MakeItSo(Runnable runnable,
-                       BoundWeakPtr weak_ptr,
-                       A2 a2,
-                       A3 a3,
-                       A4 a4,
-                       A5 a5,
-                       A6 a6) {
-    if (!weak_ptr.get()) {
-      return;
-    }
-    runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3),
-                 CallbackForward(a4), CallbackForward(a5), CallbackForward(a6));
-  }
-};
-
-template <typename ReturnType,
-          typename Runnable,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6,
-          typename A7>
-struct InvokeHelper<false,
-                    ReturnType,
-                    Runnable,
-                    void(A1, A2, A3, A4, A5, A6, A7)> {
-  static ReturnType
-  MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) {
-    return runnable.Run(CallbackForward(a1), CallbackForward(a2),
-                        CallbackForward(a3), CallbackForward(a4),
-                        CallbackForward(a5), CallbackForward(a6),
-                        CallbackForward(a7));
-  }
-};
-
-template <typename Runnable,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6,
-          typename A7>
-struct InvokeHelper<false, void, Runnable, void(A1, A2, A3, A4, A5, A6, A7)> {
-  static void
-  MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) {
-    runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3),
-                 CallbackForward(a4), CallbackForward(a5), CallbackForward(a6),
-                 CallbackForward(a7));
-  }
-};
-
-template <typename Runnable,
-          typename BoundWeakPtr,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6,
-          typename A7>
-struct InvokeHelper<true,
-                    void,
-                    Runnable,
-                    void(BoundWeakPtr, A2, A3, A4, A5, A6, A7)> {
-  static void MakeItSo(Runnable runnable,
-                       BoundWeakPtr weak_ptr,
-                       A2 a2,
-                       A3 a3,
-                       A4 a4,
-                       A5 a5,
-                       A6 a6,
-                       A7 a7) {
-    if (!weak_ptr.get()) {
-      return;
-    }
-    runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3),
-                 CallbackForward(a4), CallbackForward(a5), CallbackForward(a6),
-                 CallbackForward(a7));
-  }
-};
-
-#if !defined(_MSC_VER)
-
-template <typename ReturnType, typename Runnable, typename ArgsType>
-struct InvokeHelper<true, ReturnType, Runnable, ArgsType> {
+template <typename ReturnType>
+struct InvokeHelper<true, ReturnType> {
   // WeakCalls are only supported for functions with a void return type.
-  // Otherwise, the function result would be undefined if the the WeakPtr<>
+  // Otherwise, the function result would be undefined if the WeakPtr<>
   // is invalidated.
-  COMPILE_ASSERT(is_void<ReturnType>::value,
-                 weak_ptrs_can_only_bind_to_methods_without_return_values);
-};
+  static_assert(std::is_void<ReturnType>::value,
+                "weak_ptrs can only bind to methods without return values");
 
-#endif
+  template <typename Functor, typename BoundWeakPtr, typename... RunArgs>
+  static inline void MakeItSo(Functor&& functor,
+                              BoundWeakPtr&& weak_ptr,
+                              RunArgs&&... args) {
+    if (!weak_ptr) {
+      return;
+    }
+    using Traits = MakeFunctorTraits<Functor>;
+    Traits::Invoke(std::forward<Functor>(functor),
+                   std::forward<BoundWeakPtr>(weak_ptr),
+                   std::forward<RunArgs>(args)...);
+  }
+};
 
 // Invoker<>
 //
 // See description at the top of the file.
-template <int NumBound, typename Storage, typename RunType>
+template <typename StorageType, typename UnboundRunType>
 struct Invoker;
 
-// Arity 0 -> 0.
-template <typename StorageType, typename R>
-struct Invoker<0, StorageType, R()> {
-  typedef R(RunType)(BindStateBase*);
-
-  typedef R(UnboundRunType)();
-
-  static R Run(BindStateBase* base) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
+template <typename StorageType, typename R, typename... UnboundArgs>
+struct Invoker<StorageType, R(UnboundArgs...)> {
+  static R RunOnce(BindStateBase* base,
+                   PassingType<UnboundArgs>... unbound_args) {
     // Local references to make debugger stepping easier. If in a debugger,
     // you really want to warp ahead and step through the
     // InvokeHelper<>::MakeItSo() call below.
-
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void()>::MakeItSo(storage->runnable_);
-  }
-};
-
-// Arity 1 -> 1.
-template <typename StorageType, typename R, typename X1>
-struct Invoker<0, StorageType, R(X1)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X1>::ForwardType);
-
-  typedef R(UnboundRunType)(X1);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X1>::ForwardType x1) {
     StorageType* storage = static_cast<StorageType*>(base);
+    static constexpr size_t num_bound_args =
+        std::tuple_size<decltype(storage->bound_args_)>::value;
+    return RunImpl(std::move(storage->functor_),
+                   std::move(storage->bound_args_),
+                   std::make_index_sequence<num_bound_args>(),
+                   std::forward<UnboundArgs>(unbound_args)...);
+  }
 
+  static R Run(BindStateBase* base, PassingType<UnboundArgs>... unbound_args) {
     // Local references to make debugger stepping easier. If in a debugger,
     // you really want to warp ahead and step through the
     // InvokeHelper<>::MakeItSo() call below.
+    const StorageType* storage = static_cast<StorageType*>(base);
+    static constexpr size_t num_bound_args =
+        std::tuple_size<decltype(storage->bound_args_)>::value;
+    return RunImpl(storage->functor_, storage->bound_args_,
+                   std::make_index_sequence<num_bound_args>(),
+                   std::forward<UnboundArgs>(unbound_args)...);
+  }
 
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename CallbackParamTraits<X1>::ForwardType
-                                 x1)>::MakeItSo(storage->runnable_,
-                                                CallbackForward(x1));
+ private:
+  template <typename Functor, typename BoundArgsTuple, size_t... indices>
+  static inline R RunImpl(Functor&& functor,
+                          BoundArgsTuple&& bound,
+                          std::index_sequence<indices...>,
+                          UnboundArgs&&... unbound_args) {
+    static constexpr bool is_method = MakeFunctorTraits<Functor>::is_method;
+
+    using DecayedArgsTuple = std::decay_t<BoundArgsTuple>;
+    static constexpr bool is_weak_call =
+        IsWeakMethod<is_method,
+                     std::tuple_element_t<indices, DecayedArgsTuple>...>();
+
+    return InvokeHelper<is_weak_call, R>::MakeItSo(
+        std::forward<Functor>(functor),
+        Unwrap(std::get<indices>(std::forward<BoundArgsTuple>(bound)))...,
+        std::forward<UnboundArgs>(unbound_args)...);
   }
 };
 
-// Arity 1 -> 0.
-template <typename StorageType, typename R, typename X1>
-struct Invoker<1, StorageType, R(X1)> {
-  typedef R(RunType)(BindStateBase*);
+// Extracts necessary type info from Functor and BoundArgs.
+// Used to implement MakeUnboundRunType, BindOnce and BindRepeating.
+template <typename Functor, typename... BoundArgs>
+struct BindTypeHelper {
+  static constexpr size_t num_bounds = sizeof...(BoundArgs);
+  using FunctorTraits = MakeFunctorTraits<Functor>;
 
-  typedef R(UnboundRunType)();
+  // Example:
+  //   When Functor is `double (Foo::*)(int, const std::string&)`, and BoundArgs
+  //   is a template pack of `Foo*` and `int16_t`:
+  //    - RunType is `double(Foo*, int, const std::string&)`,
+  //    - ReturnType is `double`,
+  //    - RunParamsList is `TypeList<Foo*, int, const std::string&>`,
+  //    - BoundParamsList is `TypeList<Foo*, int>`,
+  //    - UnboundParamsList is `TypeList<const std::string&>`,
+  //    - BoundArgsList is `TypeList<Foo*, int16_t>`,
+  //    - UnboundRunType is `double(const std::string&)`.
+  using RunType = typename FunctorTraits::RunType;
+  using ReturnType = ExtractReturnType<RunType>;
 
-  static R Run(BindStateBase* base) {
-    StorageType* storage = static_cast<StorageType*>(base);
+  using RunParamsList = ExtractArgs<RunType>;
+  using BoundParamsList = TakeTypeListItem<num_bounds, RunParamsList>;
+  using UnboundParamsList = DropTypeListItem<num_bounds, RunParamsList>;
 
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
+  using BoundArgsList = TypeList<BoundArgs...>;
 
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename Bound1UnwrapTraits::ForwardType)>::
-        MakeItSo(storage->runnable_, CallbackForward(x1));
-  }
+  using UnboundRunType = MakeFunctionType<ReturnType, UnboundParamsList>;
 };
 
-// Arity 2 -> 2.
-template <typename StorageType, typename R, typename X1, typename X2>
-struct Invoker<0, StorageType, R(X1, X2)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X1>::ForwardType,
-                     typename CallbackParamTraits<X2>::ForwardType);
+template <typename Functor>
+std::enable_if_t<FunctorTraits<Functor>::is_nullable, bool> IsNull(
+    const Functor& functor) {
+  return !functor;
+}
 
-  typedef R(UnboundRunType)(X1, X2);
+template <typename Functor>
+std::enable_if_t<!FunctorTraits<Functor>::is_nullable, bool> IsNull(
+    const Functor&) {
+  return false;
+}
 
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X1>::ForwardType x1,
-               typename CallbackParamTraits<X2>::ForwardType x2) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename CallbackParamTraits<X1>::ForwardType x1,
-                             typename CallbackParamTraits<X2>::ForwardType
-                                 x2)>::MakeItSo(storage->runnable_,
-                                                CallbackForward(x1),
-                                                CallbackForward(x2));
+// Used by QueryCancellationTraits below.
+template <typename Functor, typename BoundArgsTuple, size_t... indices>
+bool QueryCancellationTraitsImpl(BindStateBase::CancellationQueryMode mode,
+                                 const Functor& functor,
+                                 const BoundArgsTuple& bound_args,
+                                 std::index_sequence<indices...>) {
+  switch (mode) {
+    case BindStateBase::IS_CANCELLED:
+      return CallbackCancellationTraits<Functor, BoundArgsTuple>::IsCancelled(
+          functor, std::get<indices>(bound_args)...);
+    case BindStateBase::MAYBE_VALID:
+      return CallbackCancellationTraits<Functor, BoundArgsTuple>::MaybeValid(
+          functor, std::get<indices>(bound_args)...);
   }
-};
+  NOTREACHED();
+  return false;
+}
 
-// Arity 2 -> 1.
-template <typename StorageType, typename R, typename X1, typename X2>
-struct Invoker<1, StorageType, R(X1, X2)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X2>::ForwardType);
+// Relays |base| to corresponding CallbackCancellationTraits<>::Run(). Returns
+// true if the callback |base| represents is canceled.
+template <typename BindStateType>
+bool QueryCancellationTraits(const BindStateBase* base,
+                             BindStateBase::CancellationQueryMode mode) {
+  const BindStateType* storage = static_cast<const BindStateType*>(base);
+  static constexpr size_t num_bound_args =
+      std::tuple_size<decltype(storage->bound_args_)>::value;
+  return QueryCancellationTraitsImpl(
+      mode, storage->functor_, storage->bound_args_,
+      std::make_index_sequence<num_bound_args>());
+}
 
-  typedef R(UnboundRunType)(X2);
+// The base case of BanUnconstructedRefCountedReceiver that checks nothing.
+template <typename Functor, typename Receiver, typename... Unused>
+std::enable_if_t<
+    !(MakeFunctorTraits<Functor>::is_method &&
+      std::is_pointer<std::decay_t<Receiver>>::value &&
+      IsRefCountedType<std::remove_pointer_t<std::decay_t<Receiver>>>::value)>
+BanUnconstructedRefCountedReceiver(const Receiver& receiver, Unused&&...) {}
 
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X2>::ForwardType x2) {
-    StorageType* storage = static_cast<StorageType*>(base);
+template <typename Functor>
+void BanUnconstructedRefCountedReceiver() {}
 
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
+// Asserts that Callback is not the first owner of a ref-counted receiver.
+template <typename Functor, typename Receiver, typename... Unused>
+std::enable_if_t<
+    MakeFunctorTraits<Functor>::is_method &&
+    std::is_pointer<std::decay_t<Receiver>>::value &&
+    IsRefCountedType<std::remove_pointer_t<std::decay_t<Receiver>>>::value>
+BanUnconstructedRefCountedReceiver(const Receiver& receiver, Unused&&...) {
+  DCHECK(receiver);
 
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename Bound1UnwrapTraits::ForwardType,
-                             typename CallbackParamTraits<X2>::ForwardType
-                                 x2)>::MakeItSo(storage->runnable_,
-                                                CallbackForward(x1),
-                                                CallbackForward(x2));
-  }
-};
-
-// Arity 2 -> 0.
-template <typename StorageType, typename R, typename X1, typename X2>
-struct Invoker<2, StorageType, R(X1, X2)> {
-  typedef R(RunType)(BindStateBase*);
-
-  typedef R(UnboundRunType)();
-
-  static R Run(BindStateBase* base) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename Bound1UnwrapTraits::ForwardType,
-                             typename Bound2UnwrapTraits::ForwardType)>::
-        MakeItSo(storage->runnable_, CallbackForward(x1), CallbackForward(x2));
-  }
-};
-
-// Arity 3 -> 3.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3>
-struct Invoker<0, StorageType, R(X1, X2, X3)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X1>::ForwardType,
-                     typename CallbackParamTraits<X2>::ForwardType,
-                     typename CallbackParamTraits<X3>::ForwardType);
-
-  typedef R(UnboundRunType)(X1, X2, X3);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X1>::ForwardType x1,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename CallbackParamTraits<X1>::ForwardType x1,
-                             typename CallbackParamTraits<X2>::ForwardType x2,
-                             typename CallbackParamTraits<X3>::ForwardType
-                                 x3)>::MakeItSo(storage->runnable_,
-                                                CallbackForward(x1),
-                                                CallbackForward(x2),
-                                                CallbackForward(x3));
-  }
-};
-
-// Arity 3 -> 2.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3>
-struct Invoker<1, StorageType, R(X1, X2, X3)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X2>::ForwardType,
-                     typename CallbackParamTraits<X3>::ForwardType);
-
-  typedef R(UnboundRunType)(X2, X3);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename Bound1UnwrapTraits::ForwardType,
-                             typename CallbackParamTraits<X2>::ForwardType x2,
-                             typename CallbackParamTraits<X3>::ForwardType
-                                 x3)>::MakeItSo(storage->runnable_,
-                                                CallbackForward(x1),
-                                                CallbackForward(x2),
-                                                CallbackForward(x3));
-  }
-};
-
-// Arity 3 -> 1.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3>
-struct Invoker<2, StorageType, R(X1, X2, X3)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X3>::ForwardType);
-
-  typedef R(UnboundRunType)(X3);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X3>::ForwardType x3) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename Bound1UnwrapTraits::ForwardType,
-                             typename Bound2UnwrapTraits::ForwardType,
-                             typename CallbackParamTraits<X3>::ForwardType
-                                 x3)>::MakeItSo(storage->runnable_,
-                                                CallbackForward(x1),
-                                                CallbackForward(x2),
-                                                CallbackForward(x3));
-  }
-};
-
-// Arity 3 -> 0.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3>
-struct Invoker<3, StorageType, R(X1, X2, X3)> {
-  typedef R(RunType)(BindStateBase*);
-
-  typedef R(UnboundRunType)();
-
-  static R Run(BindStateBase* base) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename Bound1UnwrapTraits::ForwardType,
-                             typename Bound2UnwrapTraits::ForwardType,
-                             typename Bound3UnwrapTraits::ForwardType)>::
-        MakeItSo(storage->runnable_, CallbackForward(x1), CallbackForward(x2),
-                 CallbackForward(x3));
-  }
-};
-
-// Arity 4 -> 4.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4>
-struct Invoker<0, StorageType, R(X1, X2, X3, X4)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X1>::ForwardType,
-                     typename CallbackParamTraits<X2>::ForwardType,
-                     typename CallbackParamTraits<X3>::ForwardType,
-                     typename CallbackParamTraits<X4>::ForwardType);
-
-  typedef R(UnboundRunType)(X1, X2, X3, X4);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X1>::ForwardType x1,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename CallbackParamTraits<X1>::ForwardType x1,
-                             typename CallbackParamTraits<X2>::ForwardType x2,
-                             typename CallbackParamTraits<X3>::ForwardType x3,
-                             typename CallbackParamTraits<X4>::ForwardType
-                                 x4)>::MakeItSo(storage->runnable_,
-                                                CallbackForward(x1),
-                                                CallbackForward(x2),
-                                                CallbackForward(x3),
-                                                CallbackForward(x4));
-  }
-};
-
-// Arity 4 -> 3.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4>
-struct Invoker<1, StorageType, R(X1, X2, X3, X4)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X2>::ForwardType,
-                     typename CallbackParamTraits<X3>::ForwardType,
-                     typename CallbackParamTraits<X4>::ForwardType);
-
-  typedef R(UnboundRunType)(X2, X3, X4);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename Bound1UnwrapTraits::ForwardType,
-                             typename CallbackParamTraits<X2>::ForwardType x2,
-                             typename CallbackParamTraits<X3>::ForwardType x3,
-                             typename CallbackParamTraits<X4>::ForwardType
-                                 x4)>::MakeItSo(storage->runnable_,
-                                                CallbackForward(x1),
-                                                CallbackForward(x2),
-                                                CallbackForward(x3),
-                                                CallbackForward(x4));
-  }
-};
-
-// Arity 4 -> 2.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4>
-struct Invoker<2, StorageType, R(X1, X2, X3, X4)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X3>::ForwardType,
-                     typename CallbackParamTraits<X4>::ForwardType);
-
-  typedef R(UnboundRunType)(X3, X4);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename Bound1UnwrapTraits::ForwardType,
-                             typename Bound2UnwrapTraits::ForwardType,
-                             typename CallbackParamTraits<X3>::ForwardType x3,
-                             typename CallbackParamTraits<X4>::ForwardType
-                                 x4)>::MakeItSo(storage->runnable_,
-                                                CallbackForward(x1),
-                                                CallbackForward(x2),
-                                                CallbackForward(x3),
-                                                CallbackForward(x4));
-  }
-};
-
-// Arity 4 -> 1.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4>
-struct Invoker<3, StorageType, R(X1, X2, X3, X4)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X4>::ForwardType);
-
-  typedef R(UnboundRunType)(X4);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X4>::ForwardType x4) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename Bound1UnwrapTraits::ForwardType,
-                             typename Bound2UnwrapTraits::ForwardType,
-                             typename Bound3UnwrapTraits::ForwardType,
-                             typename CallbackParamTraits<X4>::ForwardType
-                                 x4)>::MakeItSo(storage->runnable_,
-                                                CallbackForward(x1),
-                                                CallbackForward(x2),
-                                                CallbackForward(x3),
-                                                CallbackForward(x4));
-  }
-};
-
-// Arity 4 -> 0.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4>
-struct Invoker<4, StorageType, R(X1, X2, X3, X4)> {
-  typedef R(RunType)(BindStateBase*);
-
-  typedef R(UnboundRunType)();
-
-  static R Run(BindStateBase* base) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename Bound1UnwrapTraits::ForwardType,
-                             typename Bound2UnwrapTraits::ForwardType,
-                             typename Bound3UnwrapTraits::ForwardType,
-                             typename Bound4UnwrapTraits::ForwardType)>::
-        MakeItSo(storage->runnable_, CallbackForward(x1), CallbackForward(x2),
-                 CallbackForward(x3), CallbackForward(x4));
-  }
-};
-
-// Arity 5 -> 5.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5>
-struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X1>::ForwardType,
-                     typename CallbackParamTraits<X2>::ForwardType,
-                     typename CallbackParamTraits<X3>::ForwardType,
-                     typename CallbackParamTraits<X4>::ForwardType,
-                     typename CallbackParamTraits<X5>::ForwardType);
-
-  typedef R(UnboundRunType)(X1, X2, X3, X4, X5);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X1>::ForwardType x1,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename CallbackParamTraits<X1>::ForwardType x1,
-             typename CallbackParamTraits<X2>::ForwardType x2,
-             typename CallbackParamTraits<X3>::ForwardType x3,
-             typename CallbackParamTraits<X4>::ForwardType x4,
-             typename CallbackParamTraits<X5>::ForwardType
-                 x5)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5));
-  }
-};
-
-// Arity 5 -> 4.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5>
-struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X2>::ForwardType,
-                     typename CallbackParamTraits<X3>::ForwardType,
-                     typename CallbackParamTraits<X4>::ForwardType,
-                     typename CallbackParamTraits<X5>::ForwardType);
-
-  typedef R(UnboundRunType)(X2, X3, X4, X5);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename Bound1UnwrapTraits::ForwardType,
-             typename CallbackParamTraits<X2>::ForwardType x2,
-             typename CallbackParamTraits<X3>::ForwardType x3,
-             typename CallbackParamTraits<X4>::ForwardType x4,
-             typename CallbackParamTraits<X5>::ForwardType
-                 x5)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5));
-  }
-};
-
-// Arity 5 -> 3.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5>
-struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X3>::ForwardType,
-                     typename CallbackParamTraits<X4>::ForwardType,
-                     typename CallbackParamTraits<X5>::ForwardType);
-
-  typedef R(UnboundRunType)(X3, X4, X5);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename Bound1UnwrapTraits::ForwardType,
-             typename Bound2UnwrapTraits::ForwardType,
-             typename CallbackParamTraits<X3>::ForwardType x3,
-             typename CallbackParamTraits<X4>::ForwardType x4,
-             typename CallbackParamTraits<X5>::ForwardType
-                 x5)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5));
-  }
-};
-
-// Arity 5 -> 2.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5>
-struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X4>::ForwardType,
-                     typename CallbackParamTraits<X5>::ForwardType);
-
-  typedef R(UnboundRunType)(X4, X5);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename Bound1UnwrapTraits::ForwardType,
-             typename Bound2UnwrapTraits::ForwardType,
-             typename Bound3UnwrapTraits::ForwardType,
-             typename CallbackParamTraits<X4>::ForwardType x4,
-             typename CallbackParamTraits<X5>::ForwardType
-                 x5)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5));
-  }
-};
-
-// Arity 5 -> 1.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5>
-struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X5>::ForwardType);
-
-  typedef R(UnboundRunType)(X5);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X5>::ForwardType x5) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename Bound1UnwrapTraits::ForwardType,
-             typename Bound2UnwrapTraits::ForwardType,
-             typename Bound3UnwrapTraits::ForwardType,
-             typename Bound4UnwrapTraits::ForwardType,
-             typename CallbackParamTraits<X5>::ForwardType
-                 x5)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5));
-  }
-};
-
-// Arity 5 -> 0.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5>
-struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5)> {
-  typedef R(RunType)(BindStateBase*);
-
-  typedef R(UnboundRunType)();
-
-  static R Run(BindStateBase* base) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-    typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    typename Bound5UnwrapTraits::ForwardType x5 =
-        Bound5UnwrapTraits::Unwrap(storage->p5_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename Bound1UnwrapTraits::ForwardType,
-                             typename Bound2UnwrapTraits::ForwardType,
-                             typename Bound3UnwrapTraits::ForwardType,
-                             typename Bound4UnwrapTraits::ForwardType,
-                             typename Bound5UnwrapTraits::ForwardType)>::
-        MakeItSo(storage->runnable_, CallbackForward(x1), CallbackForward(x2),
-                 CallbackForward(x3), CallbackForward(x4), CallbackForward(x5));
-  }
-};
-
-// Arity 6 -> 6.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5,
-          typename X6>
-struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5, X6)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X1>::ForwardType,
-                     typename CallbackParamTraits<X2>::ForwardType,
-                     typename CallbackParamTraits<X3>::ForwardType,
-                     typename CallbackParamTraits<X4>::ForwardType,
-                     typename CallbackParamTraits<X5>::ForwardType,
-                     typename CallbackParamTraits<X6>::ForwardType);
-
-  typedef R(UnboundRunType)(X1, X2, X3, X4, X5, X6);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X1>::ForwardType x1,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename CallbackParamTraits<X1>::ForwardType x1,
-             typename CallbackParamTraits<X2>::ForwardType x2,
-             typename CallbackParamTraits<X3>::ForwardType x3,
-             typename CallbackParamTraits<X4>::ForwardType x4,
-             typename CallbackParamTraits<X5>::ForwardType x5,
-             typename CallbackParamTraits<X6>::ForwardType
-                 x6)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5),
-                                CallbackForward(x6));
-  }
-};
-
-// Arity 6 -> 5.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5,
-          typename X6>
-struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5, X6)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X2>::ForwardType,
-                     typename CallbackParamTraits<X3>::ForwardType,
-                     typename CallbackParamTraits<X4>::ForwardType,
-                     typename CallbackParamTraits<X5>::ForwardType,
-                     typename CallbackParamTraits<X6>::ForwardType);
-
-  typedef R(UnboundRunType)(X2, X3, X4, X5, X6);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename Bound1UnwrapTraits::ForwardType,
-             typename CallbackParamTraits<X2>::ForwardType x2,
-             typename CallbackParamTraits<X3>::ForwardType x3,
-             typename CallbackParamTraits<X4>::ForwardType x4,
-             typename CallbackParamTraits<X5>::ForwardType x5,
-             typename CallbackParamTraits<X6>::ForwardType
-                 x6)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5),
-                                CallbackForward(x6));
-  }
-};
-
-// Arity 6 -> 4.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5,
-          typename X6>
-struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5, X6)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X3>::ForwardType,
-                     typename CallbackParamTraits<X4>::ForwardType,
-                     typename CallbackParamTraits<X5>::ForwardType,
-                     typename CallbackParamTraits<X6>::ForwardType);
-
-  typedef R(UnboundRunType)(X3, X4, X5, X6);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename Bound1UnwrapTraits::ForwardType,
-             typename Bound2UnwrapTraits::ForwardType,
-             typename CallbackParamTraits<X3>::ForwardType x3,
-             typename CallbackParamTraits<X4>::ForwardType x4,
-             typename CallbackParamTraits<X5>::ForwardType x5,
-             typename CallbackParamTraits<X6>::ForwardType
-                 x6)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5),
-                                CallbackForward(x6));
-  }
-};
-
-// Arity 6 -> 3.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5,
-          typename X6>
-struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5, X6)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X4>::ForwardType,
-                     typename CallbackParamTraits<X5>::ForwardType,
-                     typename CallbackParamTraits<X6>::ForwardType);
-
-  typedef R(UnboundRunType)(X4, X5, X6);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename Bound1UnwrapTraits::ForwardType,
-             typename Bound2UnwrapTraits::ForwardType,
-             typename Bound3UnwrapTraits::ForwardType,
-             typename CallbackParamTraits<X4>::ForwardType x4,
-             typename CallbackParamTraits<X5>::ForwardType x5,
-             typename CallbackParamTraits<X6>::ForwardType
-                 x6)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5),
-                                CallbackForward(x6));
-  }
-};
-
-// Arity 6 -> 2.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5,
-          typename X6>
-struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5, X6)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X5>::ForwardType,
-                     typename CallbackParamTraits<X6>::ForwardType);
-
-  typedef R(UnboundRunType)(X5, X6);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename Bound1UnwrapTraits::ForwardType,
-             typename Bound2UnwrapTraits::ForwardType,
-             typename Bound3UnwrapTraits::ForwardType,
-             typename Bound4UnwrapTraits::ForwardType,
-             typename CallbackParamTraits<X5>::ForwardType x5,
-             typename CallbackParamTraits<X6>::ForwardType
-                 x6)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5),
-                                CallbackForward(x6));
-  }
-};
-
-// Arity 6 -> 1.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5,
-          typename X6>
-struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5, X6)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X6>::ForwardType);
-
-  typedef R(UnboundRunType)(X6);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X6>::ForwardType x6) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-    typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    typename Bound5UnwrapTraits::ForwardType x5 =
-        Bound5UnwrapTraits::Unwrap(storage->p5_);
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename Bound1UnwrapTraits::ForwardType,
-             typename Bound2UnwrapTraits::ForwardType,
-             typename Bound3UnwrapTraits::ForwardType,
-             typename Bound4UnwrapTraits::ForwardType,
-             typename Bound5UnwrapTraits::ForwardType,
-             typename CallbackParamTraits<X6>::ForwardType
-                 x6)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5),
-                                CallbackForward(x6));
-  }
-};
-
-// Arity 6 -> 0.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5,
-          typename X6>
-struct Invoker<6, StorageType, R(X1, X2, X3, X4, X5, X6)> {
-  typedef R(RunType)(BindStateBase*);
-
-  typedef R(UnboundRunType)();
-
-  static R Run(BindStateBase* base) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-    typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
-    typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    typename Bound5UnwrapTraits::ForwardType x5 =
-        Bound5UnwrapTraits::Unwrap(storage->p5_);
-    typename Bound6UnwrapTraits::ForwardType x6 =
-        Bound6UnwrapTraits::Unwrap(storage->p6_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename Bound1UnwrapTraits::ForwardType,
-                             typename Bound2UnwrapTraits::ForwardType,
-                             typename Bound3UnwrapTraits::ForwardType,
-                             typename Bound4UnwrapTraits::ForwardType,
-                             typename Bound5UnwrapTraits::ForwardType,
-                             typename Bound6UnwrapTraits::ForwardType)>::
-        MakeItSo(storage->runnable_, CallbackForward(x1), CallbackForward(x2),
-                 CallbackForward(x3), CallbackForward(x4), CallbackForward(x5),
-                 CallbackForward(x6));
-  }
-};
-
-// Arity 7 -> 7.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5,
-          typename X6,
-          typename X7>
-struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X1>::ForwardType,
-                     typename CallbackParamTraits<X2>::ForwardType,
-                     typename CallbackParamTraits<X3>::ForwardType,
-                     typename CallbackParamTraits<X4>::ForwardType,
-                     typename CallbackParamTraits<X5>::ForwardType,
-                     typename CallbackParamTraits<X6>::ForwardType,
-                     typename CallbackParamTraits<X7>::ForwardType);
-
-  typedef R(UnboundRunType)(X1, X2, X3, X4, X5, X6, X7);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X1>::ForwardType x1,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6,
-               typename CallbackParamTraits<X7>::ForwardType x7) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename CallbackParamTraits<X1>::ForwardType x1,
-             typename CallbackParamTraits<X2>::ForwardType x2,
-             typename CallbackParamTraits<X3>::ForwardType x3,
-             typename CallbackParamTraits<X4>::ForwardType x4,
-             typename CallbackParamTraits<X5>::ForwardType x5,
-             typename CallbackParamTraits<X6>::ForwardType x6,
-             typename CallbackParamTraits<X7>::ForwardType
-                 x7)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5),
-                                CallbackForward(x6), CallbackForward(x7));
-  }
-};
-
-// Arity 7 -> 6.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5,
-          typename X6,
-          typename X7>
-struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X2>::ForwardType,
-                     typename CallbackParamTraits<X3>::ForwardType,
-                     typename CallbackParamTraits<X4>::ForwardType,
-                     typename CallbackParamTraits<X5>::ForwardType,
-                     typename CallbackParamTraits<X6>::ForwardType,
-                     typename CallbackParamTraits<X7>::ForwardType);
-
-  typedef R(UnboundRunType)(X2, X3, X4, X5, X6, X7);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X2>::ForwardType x2,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6,
-               typename CallbackParamTraits<X7>::ForwardType x7) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename Bound1UnwrapTraits::ForwardType,
-             typename CallbackParamTraits<X2>::ForwardType x2,
-             typename CallbackParamTraits<X3>::ForwardType x3,
-             typename CallbackParamTraits<X4>::ForwardType x4,
-             typename CallbackParamTraits<X5>::ForwardType x5,
-             typename CallbackParamTraits<X6>::ForwardType x6,
-             typename CallbackParamTraits<X7>::ForwardType
-                 x7)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5),
-                                CallbackForward(x6), CallbackForward(x7));
-  }
-};
-
-// Arity 7 -> 5.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5,
-          typename X6,
-          typename X7>
-struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X3>::ForwardType,
-                     typename CallbackParamTraits<X4>::ForwardType,
-                     typename CallbackParamTraits<X5>::ForwardType,
-                     typename CallbackParamTraits<X6>::ForwardType,
-                     typename CallbackParamTraits<X7>::ForwardType);
-
-  typedef R(UnboundRunType)(X3, X4, X5, X6, X7);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X3>::ForwardType x3,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6,
-               typename CallbackParamTraits<X7>::ForwardType x7) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename Bound1UnwrapTraits::ForwardType,
-             typename Bound2UnwrapTraits::ForwardType,
-             typename CallbackParamTraits<X3>::ForwardType x3,
-             typename CallbackParamTraits<X4>::ForwardType x4,
-             typename CallbackParamTraits<X5>::ForwardType x5,
-             typename CallbackParamTraits<X6>::ForwardType x6,
-             typename CallbackParamTraits<X7>::ForwardType
-                 x7)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5),
-                                CallbackForward(x6), CallbackForward(x7));
-  }
-};
-
-// Arity 7 -> 4.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5,
-          typename X6,
-          typename X7>
-struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X4>::ForwardType,
-                     typename CallbackParamTraits<X5>::ForwardType,
-                     typename CallbackParamTraits<X6>::ForwardType,
-                     typename CallbackParamTraits<X7>::ForwardType);
-
-  typedef R(UnboundRunType)(X4, X5, X6, X7);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X4>::ForwardType x4,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6,
-               typename CallbackParamTraits<X7>::ForwardType x7) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename Bound1UnwrapTraits::ForwardType,
-             typename Bound2UnwrapTraits::ForwardType,
-             typename Bound3UnwrapTraits::ForwardType,
-             typename CallbackParamTraits<X4>::ForwardType x4,
-             typename CallbackParamTraits<X5>::ForwardType x5,
-             typename CallbackParamTraits<X6>::ForwardType x6,
-             typename CallbackParamTraits<X7>::ForwardType
-                 x7)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5),
-                                CallbackForward(x6), CallbackForward(x7));
-  }
-};
-
-// Arity 7 -> 3.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5,
-          typename X6,
-          typename X7>
-struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X5>::ForwardType,
-                     typename CallbackParamTraits<X6>::ForwardType,
-                     typename CallbackParamTraits<X7>::ForwardType);
-
-  typedef R(UnboundRunType)(X5, X6, X7);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X5>::ForwardType x5,
-               typename CallbackParamTraits<X6>::ForwardType x6,
-               typename CallbackParamTraits<X7>::ForwardType x7) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename Bound1UnwrapTraits::ForwardType,
-             typename Bound2UnwrapTraits::ForwardType,
-             typename Bound3UnwrapTraits::ForwardType,
-             typename Bound4UnwrapTraits::ForwardType,
-             typename CallbackParamTraits<X5>::ForwardType x5,
-             typename CallbackParamTraits<X6>::ForwardType x6,
-             typename CallbackParamTraits<X7>::ForwardType
-                 x7)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5),
-                                CallbackForward(x6), CallbackForward(x7));
-  }
-};
-
-// Arity 7 -> 2.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5,
-          typename X6,
-          typename X7>
-struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X6>::ForwardType,
-                     typename CallbackParamTraits<X7>::ForwardType);
-
-  typedef R(UnboundRunType)(X6, X7);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X6>::ForwardType x6,
-               typename CallbackParamTraits<X7>::ForwardType x7) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-    typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    typename Bound5UnwrapTraits::ForwardType x5 =
-        Bound5UnwrapTraits::Unwrap(storage->p5_);
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename Bound1UnwrapTraits::ForwardType,
-             typename Bound2UnwrapTraits::ForwardType,
-             typename Bound3UnwrapTraits::ForwardType,
-             typename Bound4UnwrapTraits::ForwardType,
-             typename Bound5UnwrapTraits::ForwardType,
-             typename CallbackParamTraits<X6>::ForwardType x6,
-             typename CallbackParamTraits<X7>::ForwardType
-                 x7)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5),
-                                CallbackForward(x6), CallbackForward(x7));
-  }
-};
-
-// Arity 7 -> 1.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5,
-          typename X6,
-          typename X7>
-struct Invoker<6, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
-  typedef R(RunType)(BindStateBase*,
-                     typename CallbackParamTraits<X7>::ForwardType);
-
-  typedef R(UnboundRunType)(X7);
-
-  static R Run(BindStateBase* base,
-               typename CallbackParamTraits<X7>::ForwardType x7) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-    typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
-    typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    typename Bound5UnwrapTraits::ForwardType x5 =
-        Bound5UnwrapTraits::Unwrap(storage->p5_);
-    typename Bound6UnwrapTraits::ForwardType x6 =
-        Bound6UnwrapTraits::Unwrap(storage->p6_);
-    return InvokeHelper<
-        StorageType::IsWeakCall::value, R, typename StorageType::RunnableType,
-        void(typename Bound1UnwrapTraits::ForwardType,
-             typename Bound2UnwrapTraits::ForwardType,
-             typename Bound3UnwrapTraits::ForwardType,
-             typename Bound4UnwrapTraits::ForwardType,
-             typename Bound5UnwrapTraits::ForwardType,
-             typename Bound6UnwrapTraits::ForwardType,
-             typename CallbackParamTraits<X7>::ForwardType
-                 x7)>::MakeItSo(storage->runnable_, CallbackForward(x1),
-                                CallbackForward(x2), CallbackForward(x3),
-                                CallbackForward(x4), CallbackForward(x5),
-                                CallbackForward(x6), CallbackForward(x7));
-  }
-};
-
-// Arity 7 -> 0.
-template <typename StorageType,
-          typename R,
-          typename X1,
-          typename X2,
-          typename X3,
-          typename X4,
-          typename X5,
-          typename X6,
-          typename X7>
-struct Invoker<7, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> {
-  typedef R(RunType)(BindStateBase*);
-
-  typedef R(UnboundRunType)();
-
-  static R Run(BindStateBase* base) {
-    StorageType* storage = static_cast<StorageType*>(base);
-
-    // Local references to make debugger stepping easier. If in a debugger,
-    // you really want to warp ahead and step through the
-    // InvokeHelper<>::MakeItSo() call below.
-    typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits;
-    typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits;
-    typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits;
-    typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits;
-    typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits;
-    typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits;
-    typedef typename StorageType::Bound7UnwrapTraits Bound7UnwrapTraits;
-
-    typename Bound1UnwrapTraits::ForwardType x1 =
-        Bound1UnwrapTraits::Unwrap(storage->p1_);
-    typename Bound2UnwrapTraits::ForwardType x2 =
-        Bound2UnwrapTraits::Unwrap(storage->p2_);
-    typename Bound3UnwrapTraits::ForwardType x3 =
-        Bound3UnwrapTraits::Unwrap(storage->p3_);
-    typename Bound4UnwrapTraits::ForwardType x4 =
-        Bound4UnwrapTraits::Unwrap(storage->p4_);
-    typename Bound5UnwrapTraits::ForwardType x5 =
-        Bound5UnwrapTraits::Unwrap(storage->p5_);
-    typename Bound6UnwrapTraits::ForwardType x6 =
-        Bound6UnwrapTraits::Unwrap(storage->p6_);
-    typename Bound7UnwrapTraits::ForwardType x7 =
-        Bound7UnwrapTraits::Unwrap(storage->p7_);
-    return InvokeHelper<StorageType::IsWeakCall::value, R,
-                        typename StorageType::RunnableType,
-                        void(typename Bound1UnwrapTraits::ForwardType,
-                             typename Bound2UnwrapTraits::ForwardType,
-                             typename Bound3UnwrapTraits::ForwardType,
-                             typename Bound4UnwrapTraits::ForwardType,
-                             typename Bound5UnwrapTraits::ForwardType,
-                             typename Bound6UnwrapTraits::ForwardType,
-                             typename Bound7UnwrapTraits::ForwardType)>::
-        MakeItSo(storage->runnable_, CallbackForward(x1), CallbackForward(x2),
-                 CallbackForward(x3), CallbackForward(x4), CallbackForward(x5),
-                 CallbackForward(x6), CallbackForward(x7));
-  }
-};
+  // It's error prone to make the implicit first reference to ref-counted types.
+  // In the example below, base::BindOnce() makes the implicit first reference
+  // to the ref-counted Foo. If PostTask() failed or the posted task ran fast
+  // enough, the newly created instance can be destroyed before |oo| makes
+  // another reference.
+  //   Foo::Foo() {
+  //     base::PostTask(FROM_HERE, base::BindOnce(&Foo::Bar, this));
+  //   }
+  //
+  //   scoped_refptr<Foo> oo = new Foo();
+  //
+  // Instead of doing like above, please consider adding a static constructor,
+  // and keep the first reference alive explicitly.
+  //   // static
+  //   scoped_refptr<Foo> Foo::Create() {
+  //     auto foo = base::WrapRefCounted(new Foo());
+  //     base::PostTask(FROM_HERE, base::BindOnce(&Foo::Bar, foo));
+  //     return foo;
+  //   }
+  //
+  //   Foo::Foo() {}
+  //
+  //   scoped_refptr<Foo> oo = Foo::Create();
+  DCHECK(receiver->HasAtLeastOneRef())
+      << "base::Bind{Once,Repeating}() refuses to create the first reference "
+         "to ref-counted objects. That typically happens around PostTask() in "
+         "their constructor, and such objects can be destroyed before `new` "
+         "returns if the task resolves fast enough.";
+}
 
 // BindState<>
 //
-// This stores all the state passed into Bind() and is also where most
-// of the template resolution magic occurs.
-//
-// Runnable is the functor we are binding arguments to.
-// RunType is type of the Run() function that the Invoker<> should use.
-// Normally, this is the same as the RunType of the Runnable, but it can
-// be different if an adapter like IgnoreResult() has been used.
-//
-// BoundArgsType contains the storage type for all the bound arguments by
-// (ab)using a function type.
-template <typename Runnable, typename RunType, typename BoundArgsType>
-struct BindState;
+// This stores all the state passed into Bind().
+template <typename Functor, typename... BoundArgs>
+struct BindState final : BindStateBase {
+  using IsCancellable = std::bool_constant<
+      CallbackCancellationTraits<Functor,
+                                 std::tuple<BoundArgs...>>::is_cancellable>;
+  template <typename ForwardFunctor, typename... ForwardBoundArgs>
+  static BindState* Create(BindStateBase::InvokeFuncStorage invoke_func,
+                           ForwardFunctor&& functor,
+                           ForwardBoundArgs&&... bound_args) {
+    // Ban ref counted receivers that were not yet fully constructed to avoid
+    // a common pattern of racy situation.
+    BanUnconstructedRefCountedReceiver<ForwardFunctor>(bound_args...);
 
-template <typename Runnable, typename RunType>
-struct BindState<Runnable, RunType, void()> : public BindStateBase {
-  typedef Runnable RunnableType;
-  typedef false_type IsWeakCall;
-  typedef Invoker<0, BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
-  explicit BindState(const Runnable& runnable)
-      : BindStateBase(&Destroy), runnable_(runnable) {}
-
-  ~BindState() {}
-
-  static void Destroy(BindStateBase* self) {
-    delete static_cast<BindState*>(self);
+    // IsCancellable is std::false_type if
+    // CallbackCancellationTraits<>::IsCancelled returns always false.
+    // Otherwise, it's std::true_type.
+    return new BindState(IsCancellable{}, invoke_func,
+                         std::forward<ForwardFunctor>(functor),
+                         std::forward<ForwardBoundArgs>(bound_args)...);
   }
 
-  RunnableType runnable_;
+  Functor functor_;
+  std::tuple<BoundArgs...> bound_args_;
+
+ private:
+  static constexpr bool is_nested_callback =
+      MakeFunctorTraits<Functor>::is_callback;
+
+  template <typename ForwardFunctor, typename... ForwardBoundArgs>
+  explicit BindState(std::true_type,
+                     BindStateBase::InvokeFuncStorage invoke_func,
+                     ForwardFunctor&& functor,
+                     ForwardBoundArgs&&... bound_args)
+      : BindStateBase(invoke_func,
+                      &Destroy,
+                      &QueryCancellationTraits<BindState>),
+        functor_(std::forward<ForwardFunctor>(functor)),
+        bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
+    // We check the validity of nested callbacks (e.g., Bind(callback, ...)) in
+    // release builds to avoid null pointers from ending up in posted tasks,
+    // causing hard-to-diagnose crashes. Ideally we'd do this for all functors
+    // here, but that would have a large binary size impact.
+    if (is_nested_callback) {
+      CHECK(!IsNull(functor_));
+    } else {
+      DCHECK(!IsNull(functor_));
+    }
+  }
+
+  template <typename ForwardFunctor, typename... ForwardBoundArgs>
+  explicit BindState(std::false_type,
+                     BindStateBase::InvokeFuncStorage invoke_func,
+                     ForwardFunctor&& functor,
+                     ForwardBoundArgs&&... bound_args)
+      : BindStateBase(invoke_func, &Destroy),
+        functor_(std::forward<ForwardFunctor>(functor)),
+        bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
+    // See above for CHECK/DCHECK rationale.
+    if (is_nested_callback) {
+      CHECK(!IsNull(functor_));
+    } else {
+      DCHECK(!IsNull(functor_));
+    }
+  }
+
+  ~BindState() = default;
+
+  static void Destroy(const BindStateBase* self) {
+    delete static_cast<const BindState*>(self);
+  }
 };
 
-template <typename Runnable, typename RunType, typename P1>
-struct BindState<Runnable, RunType, void(P1)> : public BindStateBase {
-  typedef Runnable RunnableType;
-  typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
-  typedef Invoker<1, BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
+// Used to implement MakeBindStateType.
+template <bool is_method, typename Functor, typename... BoundArgs>
+struct MakeBindStateTypeImpl;
 
-  // Convenience typedefs for bound argument types.
-  typedef UnwrapTraits<P1> Bound1UnwrapTraits;
-
-  BindState(const Runnable& runnable, const P1& p1)
-      : BindStateBase(&Destroy), runnable_(runnable), p1_(p1) {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
-  }
-
-  ~BindState() {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::Release(p1_);
-  }
-
-  static void Destroy(BindStateBase* self) {
-    delete static_cast<BindState*>(self);
-  }
-
-  RunnableType runnable_;
-  P1 p1_;
+template <typename Functor, typename... BoundArgs>
+struct MakeBindStateTypeImpl<false, Functor, BoundArgs...> {
+  static_assert(!HasRefCountedTypeAsRawPtr<std::decay_t<BoundArgs>...>::value,
+                "A parameter is a refcounted type and needs scoped_refptr.");
+  using Type = BindState<std::decay_t<Functor>, std::decay_t<BoundArgs>...>;
 };
 
-template <typename Runnable, typename RunType, typename P1, typename P2>
-struct BindState<Runnable, RunType, void(P1, P2)> : public BindStateBase {
-  typedef Runnable RunnableType;
-  typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
-  typedef Invoker<2, BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
-
-  // Convenience typedefs for bound argument types.
-  typedef UnwrapTraits<P1> Bound1UnwrapTraits;
-  typedef UnwrapTraits<P2> Bound2UnwrapTraits;
-
-  BindState(const Runnable& runnable, const P1& p1, const P2& p2)
-      : BindStateBase(&Destroy), runnable_(runnable), p1_(p1), p2_(p2) {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
-  }
-
-  ~BindState() {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::Release(p1_);
-  }
-
-  static void Destroy(BindStateBase* self) {
-    delete static_cast<BindState*>(self);
-  }
-
-  RunnableType runnable_;
-  P1 p1_;
-  P2 p2_;
+template <typename Functor>
+struct MakeBindStateTypeImpl<true, Functor> {
+  using Type = BindState<std::decay_t<Functor>>;
 };
 
-template <typename Runnable,
-          typename RunType,
-          typename P1,
-          typename P2,
-          typename P3>
-struct BindState<Runnable, RunType, void(P1, P2, P3)> : public BindStateBase {
-  typedef Runnable RunnableType;
-  typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
-  typedef Invoker<3, BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
+template <typename Functor, typename Receiver, typename... BoundArgs>
+struct MakeBindStateTypeImpl<true, Functor, Receiver, BoundArgs...> {
+ private:
+  using DecayedReceiver = std::decay_t<Receiver>;
 
-  // Convenience typedefs for bound argument types.
-  typedef UnwrapTraits<P1> Bound1UnwrapTraits;
-  typedef UnwrapTraits<P2> Bound2UnwrapTraits;
-  typedef UnwrapTraits<P3> Bound3UnwrapTraits;
+  static_assert(!std::is_array<std::remove_reference_t<Receiver>>::value,
+                "First bound argument to a method cannot be an array.");
+  static_assert(
+      !std::is_pointer<DecayedReceiver>::value ||
+          IsRefCountedType<std::remove_pointer_t<DecayedReceiver>>::value,
+      "Receivers may not be raw pointers. If using a raw pointer here is safe"
+      " and has no lifetime concerns, use base::Unretained() and document why"
+      " it's safe.");
+  static_assert(!HasRefCountedTypeAsRawPtr<std::decay_t<BoundArgs>...>::value,
+                "A parameter is a refcounted type and needs scoped_refptr.");
 
-  BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3)
-      : BindStateBase(&Destroy),
-        runnable_(runnable),
-        p1_(p1),
-        p2_(p2),
-        p3_(p3) {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
-  }
-
-  ~BindState() {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::Release(p1_);
-  }
-
-  static void Destroy(BindStateBase* self) {
-    delete static_cast<BindState*>(self);
-  }
-
-  RunnableType runnable_;
-  P1 p1_;
-  P2 p2_;
-  P3 p3_;
+ public:
+  using Type = BindState<
+      std::decay_t<Functor>,
+      std::conditional_t<std::is_pointer<DecayedReceiver>::value,
+                         scoped_refptr<std::remove_pointer_t<DecayedReceiver>>,
+                         DecayedReceiver>,
+      std::decay_t<BoundArgs>...>;
 };
 
-template <typename Runnable,
-          typename RunType,
-          typename P1,
-          typename P2,
-          typename P3,
-          typename P4>
-struct BindState<Runnable, RunType, void(P1, P2, P3, P4)>
-    : public BindStateBase {
-  typedef Runnable RunnableType;
-  typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
-  typedef Invoker<4, BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
+template <typename Functor, typename... BoundArgs>
+using MakeBindStateType =
+    typename MakeBindStateTypeImpl<MakeFunctorTraits<Functor>::is_method,
+                                   Functor,
+                                   BoundArgs...>::Type;
 
-  // Convenience typedefs for bound argument types.
-  typedef UnwrapTraits<P1> Bound1UnwrapTraits;
-  typedef UnwrapTraits<P2> Bound2UnwrapTraits;
-  typedef UnwrapTraits<P3> Bound3UnwrapTraits;
-  typedef UnwrapTraits<P4> Bound4UnwrapTraits;
+// Returns a RunType of bound functor.
+// E.g. MakeUnboundRunType<R(A, B, C), A, B> is evaluated to R(C).
+template <typename Functor, typename... BoundArgs>
+using MakeUnboundRunType =
+    typename BindTypeHelper<Functor, BoundArgs...>::UnboundRunType;
 
-  BindState(const Runnable& runnable,
-            const P1& p1,
-            const P2& p2,
-            const P3& p3,
-            const P4& p4)
-      : BindStateBase(&Destroy),
-        runnable_(runnable),
-        p1_(p1),
-        p2_(p2),
-        p3_(p3),
-        p4_(p4) {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
-  }
+// The implementation of TransformToUnwrappedType below.
+template <bool is_once, typename T>
+struct TransformToUnwrappedTypeImpl;
 
-  ~BindState() {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::Release(p1_);
-  }
-
-  static void Destroy(BindStateBase* self) {
-    delete static_cast<BindState*>(self);
-  }
-
-  RunnableType runnable_;
-  P1 p1_;
-  P2 p2_;
-  P3 p3_;
-  P4 p4_;
+template <typename T>
+struct TransformToUnwrappedTypeImpl<true, T> {
+  using StoredType = std::decay_t<T>;
+  using ForwardType = StoredType&&;
+  using Unwrapped = decltype(Unwrap(std::declval<ForwardType>()));
 };
 
-template <typename Runnable,
-          typename RunType,
-          typename P1,
-          typename P2,
-          typename P3,
-          typename P4,
-          typename P5>
-struct BindState<Runnable, RunType, void(P1, P2, P3, P4, P5)>
-    : public BindStateBase {
-  typedef Runnable RunnableType;
-  typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
-  typedef Invoker<5, BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
-
-  // Convenience typedefs for bound argument types.
-  typedef UnwrapTraits<P1> Bound1UnwrapTraits;
-  typedef UnwrapTraits<P2> Bound2UnwrapTraits;
-  typedef UnwrapTraits<P3> Bound3UnwrapTraits;
-  typedef UnwrapTraits<P4> Bound4UnwrapTraits;
-  typedef UnwrapTraits<P5> Bound5UnwrapTraits;
-
-  BindState(const Runnable& runnable,
-            const P1& p1,
-            const P2& p2,
-            const P3& p3,
-            const P4& p4,
-            const P5& p5)
-      : BindStateBase(&Destroy),
-        runnable_(runnable),
-        p1_(p1),
-        p2_(p2),
-        p3_(p3),
-        p4_(p4),
-        p5_(p5) {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
-  }
-
-  ~BindState() {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::Release(p1_);
-  }
-
-  static void Destroy(BindStateBase* self) {
-    delete static_cast<BindState*>(self);
-  }
-
-  RunnableType runnable_;
-  P1 p1_;
-  P2 p2_;
-  P3 p3_;
-  P4 p4_;
-  P5 p5_;
+template <typename T>
+struct TransformToUnwrappedTypeImpl<false, T> {
+  using StoredType = std::decay_t<T>;
+  using ForwardType = const StoredType&;
+  using Unwrapped = decltype(Unwrap(std::declval<ForwardType>()));
 };
 
-template <typename Runnable,
-          typename RunType,
-          typename P1,
-          typename P2,
-          typename P3,
-          typename P4,
-          typename P5,
-          typename P6>
-struct BindState<Runnable, RunType, void(P1, P2, P3, P4, P5, P6)>
-    : public BindStateBase {
-  typedef Runnable RunnableType;
-  typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
-  typedef Invoker<6, BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
+// Transform |T| into `Unwrapped` type, which is passed to the target function.
+// Example:
+//   In is_once == true case,
+//     `int&&` -> `int&&`,
+//     `const int&` -> `int&&`,
+//     `OwnedWrapper<int>&` -> `int*&&`.
+//   In is_once == false case,
+//     `int&&` -> `const int&`,
+//     `const int&` -> `const int&`,
+//     `OwnedWrapper<int>&` -> `int* const &`.
+template <bool is_once, typename T>
+using TransformToUnwrappedType =
+    typename TransformToUnwrappedTypeImpl<is_once, T>::Unwrapped;
 
-  // Convenience typedefs for bound argument types.
-  typedef UnwrapTraits<P1> Bound1UnwrapTraits;
-  typedef UnwrapTraits<P2> Bound2UnwrapTraits;
-  typedef UnwrapTraits<P3> Bound3UnwrapTraits;
-  typedef UnwrapTraits<P4> Bound4UnwrapTraits;
-  typedef UnwrapTraits<P5> Bound5UnwrapTraits;
-  typedef UnwrapTraits<P6> Bound6UnwrapTraits;
-
-  BindState(const Runnable& runnable,
-            const P1& p1,
-            const P2& p2,
-            const P3& p3,
-            const P4& p4,
-            const P5& p5,
-            const P6& p6)
-      : BindStateBase(&Destroy),
-        runnable_(runnable),
-        p1_(p1),
-        p2_(p2),
-        p3_(p3),
-        p4_(p4),
-        p5_(p5),
-        p6_(p6) {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
-  }
-
-  ~BindState() {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::Release(p1_);
-  }
-
-  static void Destroy(BindStateBase* self) {
-    delete static_cast<BindState*>(self);
-  }
-
-  RunnableType runnable_;
-  P1 p1_;
-  P2 p2_;
-  P3 p3_;
-  P4 p4_;
-  P5 p5_;
-  P6 p6_;
+// Transforms |Args| into `Unwrapped` types, and packs them into a TypeList.
+// If |is_method| is true, tries to dereference the first argument to support
+// smart pointers.
+template <bool is_once, bool is_method, typename... Args>
+struct MakeUnwrappedTypeListImpl {
+  using Type = TypeList<TransformToUnwrappedType<is_once, Args>...>;
 };
 
-template <typename Runnable,
-          typename RunType,
-          typename P1,
-          typename P2,
-          typename P3,
-          typename P4,
-          typename P5,
-          typename P6,
-          typename P7>
-struct BindState<Runnable, RunType, void(P1, P2, P3, P4, P5, P6, P7)>
-    : public BindStateBase {
-  typedef Runnable RunnableType;
-  typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
-  typedef Invoker<7, BindState, RunType> InvokerType;
-  typedef typename InvokerType::UnboundRunType UnboundRunType;
-
-  // Convenience typedefs for bound argument types.
-  typedef UnwrapTraits<P1> Bound1UnwrapTraits;
-  typedef UnwrapTraits<P2> Bound2UnwrapTraits;
-  typedef UnwrapTraits<P3> Bound3UnwrapTraits;
-  typedef UnwrapTraits<P4> Bound4UnwrapTraits;
-  typedef UnwrapTraits<P5> Bound5UnwrapTraits;
-  typedef UnwrapTraits<P6> Bound6UnwrapTraits;
-  typedef UnwrapTraits<P7> Bound7UnwrapTraits;
-
-  BindState(const Runnable& runnable,
-            const P1& p1,
-            const P2& p2,
-            const P3& p3,
-            const P4& p4,
-            const P5& p5,
-            const P6& p6,
-            const P7& p7)
-      : BindStateBase(&Destroy),
-        runnable_(runnable),
-        p1_(p1),
-        p2_(p2),
-        p3_(p3),
-        p4_(p4),
-        p5_(p5),
-        p6_(p6),
-        p7_(p7) {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
-  }
-
-  ~BindState() {
-    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::Release(p1_);
-  }
-
-  static void Destroy(BindStateBase* self) {
-    delete static_cast<BindState*>(self);
-  }
-
-  RunnableType runnable_;
-  P1 p1_;
-  P2 p2_;
-  P3 p3_;
-  P4 p4_;
-  P5 p5_;
-  P6 p6_;
-  P7 p7_;
+// Performs special handling for this pointers.
+// Example:
+//   int* -> int*,
+//   std::unique_ptr<int> -> int*.
+template <bool is_once, typename Receiver, typename... Args>
+struct MakeUnwrappedTypeListImpl<is_once, true, Receiver, Args...> {
+  using UnwrappedReceiver = TransformToUnwrappedType<is_once, Receiver>;
+  using Type = TypeList<decltype(&*std::declval<UnwrappedReceiver>()),
+                        TransformToUnwrappedType<is_once, Args>...>;
 };
 
+template <bool is_once, bool is_method, typename... Args>
+using MakeUnwrappedTypeList =
+    typename MakeUnwrappedTypeListImpl<is_once, is_method, Args...>::Type;
+
+// IsOnceCallback<T> is a std::true_type if |T| is a OnceCallback.
+template <typename T>
+struct IsOnceCallback : std::false_type {};
+
+template <typename Signature>
+struct IsOnceCallback<OnceCallback<Signature>> : std::true_type {};
+
+// Helpers to make error messages slightly more readable.
+template <int i>
+struct BindArgument {
+  template <typename ForwardingType>
+  struct ForwardedAs {
+    template <typename FunctorParamType>
+    struct ToParamWithType {
+      static constexpr bool kCanBeForwardedToBoundFunctor =
+          std::is_constructible<FunctorParamType, ForwardingType>::value;
+
+      // If the bound type can't be forwarded then test if `FunctorParamType` is
+      // a non-const lvalue reference and a reference to the unwrapped type
+      // *could* have been successfully forwarded.
+      static constexpr bool kNonConstRefParamMustBeWrapped =
+          kCanBeForwardedToBoundFunctor ||
+          !(std::is_lvalue_reference<FunctorParamType>::value &&
+            !std::is_const<std::remove_reference_t<FunctorParamType>>::value &&
+            std::is_convertible<std::decay_t<ForwardingType>&,
+                                FunctorParamType>::value);
+
+      // Note that this intentionally drops the const qualifier from
+      // `ForwardingType`, to test if it *could* have been successfully
+      // forwarded if `Passed()` had been used.
+      static constexpr bool kMoveOnlyTypeMustUseBasePassed =
+          kCanBeForwardedToBoundFunctor ||
+          !std::is_constructible<FunctorParamType,
+                                 std::decay_t<ForwardingType>&&>::value;
+    };
+  };
+
+  template <typename BoundAsType>
+  struct BoundAs {
+    template <typename StorageType>
+    struct StoredAs {
+      static constexpr bool kBindArgumentCanBeCaptured =
+          std::is_constructible<StorageType, BoundAsType>::value;
+      // Note that this intentionally drops the const qualifier from
+      // `BoundAsType`, to test if it *could* have been successfully bound if
+      // `std::move()` had been used.
+      static constexpr bool kMoveOnlyTypeMustUseStdMove =
+          kBindArgumentCanBeCaptured ||
+          !std::is_constructible<StorageType,
+                                 std::decay_t<BoundAsType>&&>::value;
+    };
+  };
+};
+
+// Helper to assert that parameter |i| of type |Arg| can be bound, which means:
+// - |Arg| can be retained internally as |Storage|.
+// - |Arg| can be forwarded as |Unwrapped| to |Param|.
+template <int i,
+          typename Arg,
+          typename Storage,
+          typename Unwrapped,
+          typename Param>
+struct AssertConstructible {
+ private:
+  // With `BindRepeating`, there are two decision points for how to handle a
+  // move-only type:
+  //
+  // 1. Whether the move-only argument should be moved into the internal
+  //    `BindState`. Either `std::move()` or `Passed` is sufficient to trigger
+  //    move-only semantics.
+  // 2. Whether or not the bound, move-only argument should be moved to the
+  //    bound functor when invoked. When the argument is bound with `Passed`,
+  //    invoking the callback will destructively move the bound, move-only
+  //    argument to the bound functor. In contrast, if the argument is bound
+  //    with `std::move()`, `RepeatingCallback` will attempt to call the bound
+  //    functor with a constant reference to the bound, move-only argument. This
+  //    will fail if the bound functor accepts that argument by value, since the
+  //    argument cannot be copied. It is this latter case that this
+  //    static_assert aims to catch.
+  //
+  // In contrast, `BindOnce()` only has one decision point. Once a move-only
+  // type is captured by value into the internal `BindState`, the bound,
+  // move-only argument will always be moved to the functor when invoked.
+  // Failure to use std::move will simply fail the `kMoveOnlyTypeMustUseStdMove`
+  // assert below instead.
+  //
+  // Note: `Passed()` is a legacy of supporting move-only types when repeating
+  // callbacks were the only callback type. A `RepeatingCallback` with a
+  // `Passed()` argument is really a `OnceCallback` and should eventually be
+  // migrated.
+  static_assert(
+      BindArgument<i>::template ForwardedAs<Unwrapped>::
+          template ToParamWithType<Param>::kMoveOnlyTypeMustUseBasePassed,
+      "base::BindRepeating() argument is a move-only type. Use base::Passed() "
+      "instead of std::move() to transfer ownership from the callback to the "
+      "bound functor.");
+  static_assert(
+      BindArgument<i>::template ForwardedAs<Unwrapped>::
+          template ToParamWithType<Param>::kNonConstRefParamMustBeWrapped,
+      "Bound argument for non-const reference parameter must be wrapped in "
+      "std::ref() or base::OwnedRef().");
+  static_assert(
+      BindArgument<i>::template ForwardedAs<Unwrapped>::
+          template ToParamWithType<Param>::kCanBeForwardedToBoundFunctor,
+      "Type mismatch between bound argument and bound functor's parameter.");
+
+  static_assert(BindArgument<i>::template BoundAs<Arg>::template StoredAs<
+                    Storage>::kMoveOnlyTypeMustUseStdMove,
+                "Attempting to bind a move-only type. Use std::move() to "
+                "transfer ownership to the created callback.");
+  // In practice, this static_assert should be quite rare as the storage type
+  // is deduced from the arguments passed to `BindOnce()`/`BindRepeating()`.
+  static_assert(
+      BindArgument<i>::template BoundAs<Arg>::template StoredAs<
+          Storage>::kBindArgumentCanBeCaptured,
+      "Cannot capture argument: is the argument copyable or movable?");
+};
+
+// Takes three same-length TypeLists, and applies AssertConstructible for each
+// triples.
+template <typename Index,
+          typename Args,
+          typename UnwrappedTypeList,
+          typename ParamsList>
+struct AssertBindArgsValidity;
+
+template <size_t... Ns,
+          typename... Args,
+          typename... Unwrapped,
+          typename... Params>
+struct AssertBindArgsValidity<std::index_sequence<Ns...>,
+                              TypeList<Args...>,
+                              TypeList<Unwrapped...>,
+                              TypeList<Params...>>
+    : AssertConstructible<static_cast<int>(Ns),
+                          Args,
+                          std::decay_t<Args>,
+                          Unwrapped,
+                          Params>... {
+  static constexpr bool ok = true;
+};
+
+template <typename T>
+struct AssertBindArgIsNotBasePassed : public std::true_type {};
+
+template <typename T>
+struct AssertBindArgIsNotBasePassed<PassedWrapper<T>> : public std::false_type {
+};
+
+// Used below in BindImpl to determine whether to use Invoker::Run or
+// Invoker::RunOnce.
+// Note: Simply using `kIsOnce ? &Invoker::RunOnce : &Invoker::Run` does not
+// work, since the compiler needs to check whether both expressions are
+// well-formed. Using `Invoker::Run` with a OnceCallback triggers a
+// static_assert, which is why the ternary expression does not compile.
+// TODO(crbug.com/752720): Remove this indirection once we have `if constexpr`.
+template <typename Invoker>
+constexpr auto GetInvokeFunc(std::true_type) {
+  return Invoker::RunOnce;
+}
+
+template <typename Invoker>
+constexpr auto GetInvokeFunc(std::false_type) {
+  return Invoker::Run;
+}
+
+template <template <typename> class CallbackT,
+          typename Functor,
+          typename... Args>
+decltype(auto) BindImpl(Functor&& functor, Args&&... args) {
+  // This block checks if each |args| matches to the corresponding params of the
+  // target function. This check does not affect the behavior of Bind, but its
+  // error message should be more readable.
+  static constexpr bool kIsOnce = IsOnceCallback<CallbackT<void()>>::value;
+  using Helper = BindTypeHelper<Functor, Args...>;
+  using FunctorTraits = typename Helper::FunctorTraits;
+  using BoundArgsList = typename Helper::BoundArgsList;
+  using UnwrappedArgsList =
+      MakeUnwrappedTypeList<kIsOnce, FunctorTraits::is_method, Args&&...>;
+  using BoundParamsList = typename Helper::BoundParamsList;
+  static_assert(
+      AssertBindArgsValidity<std::make_index_sequence<Helper::num_bounds>,
+                             BoundArgsList, UnwrappedArgsList,
+                             BoundParamsList>::ok,
+      "The bound args need to be convertible to the target params.");
+
+  using BindState = MakeBindStateType<Functor, Args...>;
+  using UnboundRunType = MakeUnboundRunType<Functor, Args...>;
+  using Invoker = Invoker<BindState, UnboundRunType>;
+  using CallbackType = CallbackT<UnboundRunType>;
+
+  // Store the invoke func into PolymorphicInvoke before casting it to
+  // InvokeFuncStorage, so that we can ensure its type matches to
+  // PolymorphicInvoke, to which CallbackType will cast back.
+  using PolymorphicInvoke = typename CallbackType::PolymorphicInvoke;
+  PolymorphicInvoke invoke_func =
+      GetInvokeFunc<Invoker>(std::bool_constant<kIsOnce>());
+
+  using InvokeFuncStorage = BindStateBase::InvokeFuncStorage;
+  return CallbackType(BindState::Create(
+      reinterpret_cast<InvokeFuncStorage>(invoke_func),
+      std::forward<Functor>(functor), std::forward<Args>(args)...));
+}
+
 }  // namespace cef_internal
+
+// An injection point to control |this| pointer behavior on a method invocation.
+// If IsWeakReceiver<> is true_type for |T| and |T| is used for a receiver of a
+// method, base::Bind cancels the method invocation if the receiver is tested as
+// false.
+// E.g. Foo::bar() is not called:
+//   struct Foo : base::SupportsWeakPtr<Foo> {
+//     void bar() {}
+//   };
+//
+//   WeakPtr<Foo> oo = nullptr;
+//   base::BindOnce(&Foo::bar, oo).Run();
+template <typename T>
+struct IsWeakReceiver : std::false_type {};
+
+template <typename T>
+struct IsWeakReceiver<std::reference_wrapper<T>> : IsWeakReceiver<T> {};
+
+template <typename T>
+struct IsWeakReceiver<WeakPtr<T>> : std::true_type {};
+
+// An injection point to control how objects are checked for maybe validity,
+// which is an optimistic thread-safe check for full validity.
+template <typename>
+struct MaybeValidTraits {
+  template <typename T>
+  static bool MaybeValid(const T& o) {
+    return o.MaybeValid();
+  }
+};
+
+// An injection point to control how bound objects passed to the target
+// function. BindUnwrapTraits<>::Unwrap() is called for each bound objects right
+// before the target function is invoked.
+template <typename>
+struct BindUnwrapTraits {
+  template <typename T>
+  static T&& Unwrap(T&& o) {
+    return std::forward<T>(o);
+  }
+};
+
+template <typename T>
+struct BindUnwrapTraits<cef_internal::UnretainedWrapper<T>> {
+  static T* Unwrap(const cef_internal::UnretainedWrapper<T>& o) {
+    return o.get();
+  }
+};
+
+template <typename T>
+struct BindUnwrapTraits<cef_internal::RetainedRefWrapper<T>> {
+  static T* Unwrap(const cef_internal::RetainedRefWrapper<T>& o) {
+    return o.get();
+  }
+};
+
+template <typename T, typename Deleter>
+struct BindUnwrapTraits<cef_internal::OwnedWrapper<T, Deleter>> {
+  static T* Unwrap(const cef_internal::OwnedWrapper<T, Deleter>& o) {
+    return o.get();
+  }
+};
+
+template <typename T>
+struct BindUnwrapTraits<cef_internal::OwnedRefWrapper<T>> {
+  static T& Unwrap(const cef_internal::OwnedRefWrapper<T>& o) {
+    return o.get();
+  }
+};
+
+template <typename T>
+struct BindUnwrapTraits<cef_internal::PassedWrapper<T>> {
+  static T Unwrap(const cef_internal::PassedWrapper<T>& o) { return o.Take(); }
+};
+
+#if defined(OS_WIN)
+template <typename T>
+struct BindUnwrapTraits<Microsoft::WRL::ComPtr<T>> {
+  static T* Unwrap(const Microsoft::WRL::ComPtr<T>& ptr) { return ptr.Get(); }
+};
+#endif
+
+// CallbackCancellationTraits allows customization of Callback's cancellation
+// semantics. By default, callbacks are not cancellable. A specialization should
+// set is_cancellable = true and implement an IsCancelled() that returns if the
+// callback should be cancelled.
+template <typename Functor, typename BoundArgsTuple, typename SFINAE>
+struct CallbackCancellationTraits {
+  static constexpr bool is_cancellable = false;
+};
+
+// Specialization for method bound to weak pointer receiver.
+template <typename Functor, typename... BoundArgs>
+struct CallbackCancellationTraits<
+    Functor,
+    std::tuple<BoundArgs...>,
+    std::enable_if_t<cef_internal::IsWeakMethod<
+        cef_internal::FunctorTraits<Functor>::is_method,
+        BoundArgs...>::value>> {
+  static constexpr bool is_cancellable = true;
+
+  template <typename Receiver, typename... Args>
+  static bool IsCancelled(const Functor&,
+                          const Receiver& receiver,
+                          const Args&...) {
+    return !receiver;
+  }
+
+  template <typename Receiver, typename... Args>
+  static bool MaybeValid(const Functor&,
+                         const Receiver& receiver,
+                         const Args&...) {
+    return MaybeValidTraits<Receiver>::MaybeValid(receiver);
+  }
+};
+
+// Specialization for a nested bind.
+template <typename Signature, typename... BoundArgs>
+struct CallbackCancellationTraits<OnceCallback<Signature>,
+                                  std::tuple<BoundArgs...>> {
+  static constexpr bool is_cancellable = true;
+
+  template <typename Functor>
+  static bool IsCancelled(const Functor& functor, const BoundArgs&...) {
+    return functor.IsCancelled();
+  }
+
+  template <typename Functor>
+  static bool MaybeValid(const Functor& functor, const BoundArgs&...) {
+    return MaybeValidTraits<Functor>::MaybeValid(functor);
+  }
+};
+
+template <typename Signature, typename... BoundArgs>
+struct CallbackCancellationTraits<RepeatingCallback<Signature>,
+                                  std::tuple<BoundArgs...>> {
+  static constexpr bool is_cancellable = true;
+
+  template <typename Functor>
+  static bool IsCancelled(const Functor& functor, const BoundArgs&...) {
+    return functor.IsCancelled();
+  }
+
+  template <typename Functor>
+  static bool MaybeValid(const Functor& functor, const BoundArgs&...) {
+    return MaybeValidTraits<Functor>::MaybeValid(functor);
+  }
+};
+
 }  // namespace base
 
 #endif  // CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_H_
diff --git a/src/include/base/internal/cef_bind_internal_win.h b/src/include/base/internal/cef_bind_internal_win.h
deleted file mode 100644
index 2d98fd1..0000000
--- a/src/include/base/internal/cef_bind_internal_win.h
+++ /dev/null
@@ -1,398 +0,0 @@
-// Copyright (c) 2011 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Do not include this header file directly. Use base/cef_bind.h instead.
-
-// Specializations of RunnableAdapter<> for Windows specific calling
-// conventions.  Please see base/bind_internal.h for more info.
-
-#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_WIN_H_
-#define CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_WIN_H_
-
-// In the x64 architecture in Windows, __fastcall, __stdcall, etc, are all
-// the same as __cdecl which would turn the following specializations into
-// multiple definitions.
-#if defined(ARCH_CPU_X86_FAMILY)
-#if defined(ARCH_CPU_32_BITS)
-
-namespace base {
-namespace cef_internal {
-
-template <typename Functor>
-class RunnableAdapter;
-
-// __stdcall Function: Arity 0.
-template <typename R>
-class RunnableAdapter<R(__stdcall*)()> {
- public:
-  typedef R(RunType)();
-
-  explicit RunnableAdapter(R(__stdcall* function)()) : function_(function) {}
-
-  R Run() { return function_(); }
-
- private:
-  R(__stdcall* function_)();
-};
-
-// __fastcall Function: Arity 0.
-template <typename R>
-class RunnableAdapter<R(__fastcall*)()> {
- public:
-  typedef R(RunType)();
-
-  explicit RunnableAdapter(R(__fastcall* function)()) : function_(function) {}
-
-  R Run() { return function_(); }
-
- private:
-  R(__fastcall* function_)();
-};
-
-// __stdcall Function: Arity 1.
-template <typename R, typename A1>
-class RunnableAdapter<R(__stdcall*)(A1)> {
- public:
-  typedef R(RunType)(A1);
-
-  explicit RunnableAdapter(R(__stdcall* function)(A1)) : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1) {
-    return function_(a1);
-  }
-
- private:
-  R(__stdcall* function_)(A1);
-};
-
-// __fastcall Function: Arity 1.
-template <typename R, typename A1>
-class RunnableAdapter<R(__fastcall*)(A1)> {
- public:
-  typedef R(RunType)(A1);
-
-  explicit RunnableAdapter(R(__fastcall* function)(A1)) : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1) {
-    return function_(a1);
-  }
-
- private:
-  R(__fastcall* function_)(A1);
-};
-
-// __stdcall Function: Arity 2.
-template <typename R, typename A1, typename A2>
-class RunnableAdapter<R(__stdcall*)(A1, A2)> {
- public:
-  typedef R(RunType)(A1, A2);
-
-  explicit RunnableAdapter(R(__stdcall* function)(A1, A2))
-      : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2) {
-    return function_(a1, a2);
-  }
-
- private:
-  R(__stdcall* function_)(A1, A2);
-};
-
-// __fastcall Function: Arity 2.
-template <typename R, typename A1, typename A2>
-class RunnableAdapter<R(__fastcall*)(A1, A2)> {
- public:
-  typedef R(RunType)(A1, A2);
-
-  explicit RunnableAdapter(R(__fastcall* function)(A1, A2))
-      : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2) {
-    return function_(a1, a2);
-  }
-
- private:
-  R(__fastcall* function_)(A1, A2);
-};
-
-// __stdcall Function: Arity 3.
-template <typename R, typename A1, typename A2, typename A3>
-class RunnableAdapter<R(__stdcall*)(A1, A2, A3)> {
- public:
-  typedef R(RunType)(A1, A2, A3);
-
-  explicit RunnableAdapter(R(__stdcall* function)(A1, A2, A3))
-      : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3) {
-    return function_(a1, a2, a3);
-  }
-
- private:
-  R(__stdcall* function_)(A1, A2, A3);
-};
-
-// __fastcall Function: Arity 3.
-template <typename R, typename A1, typename A2, typename A3>
-class RunnableAdapter<R(__fastcall*)(A1, A2, A3)> {
- public:
-  typedef R(RunType)(A1, A2, A3);
-
-  explicit RunnableAdapter(R(__fastcall* function)(A1, A2, A3))
-      : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3) {
-    return function_(a1, a2, a3);
-  }
-
- private:
-  R(__fastcall* function_)(A1, A2, A3);
-};
-
-// __stdcall Function: Arity 4.
-template <typename R, typename A1, typename A2, typename A3, typename A4>
-class RunnableAdapter<R(__stdcall*)(A1, A2, A3, A4)> {
- public:
-  typedef R(RunType)(A1, A2, A3, A4);
-
-  explicit RunnableAdapter(R(__stdcall* function)(A1, A2, A3, A4))
-      : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4) {
-    return function_(a1, a2, a3, a4);
-  }
-
- private:
-  R(__stdcall* function_)(A1, A2, A3, A4);
-};
-
-// __fastcall Function: Arity 4.
-template <typename R, typename A1, typename A2, typename A3, typename A4>
-class RunnableAdapter<R(__fastcall*)(A1, A2, A3, A4)> {
- public:
-  typedef R(RunType)(A1, A2, A3, A4);
-
-  explicit RunnableAdapter(R(__fastcall* function)(A1, A2, A3, A4))
-      : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4) {
-    return function_(a1, a2, a3, a4);
-  }
-
- private:
-  R(__fastcall* function_)(A1, A2, A3, A4);
-};
-
-// __stdcall Function: Arity 5.
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5>
-class RunnableAdapter<R(__stdcall*)(A1, A2, A3, A4, A5)> {
- public:
-  typedef R(RunType)(A1, A2, A3, A4, A5);
-
-  explicit RunnableAdapter(R(__stdcall* function)(A1, A2, A3, A4, A5))
-      : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4,
-        typename CallbackParamTraits<A5>::ForwardType a5) {
-    return function_(a1, a2, a3, a4, a5);
-  }
-
- private:
-  R(__stdcall* function_)(A1, A2, A3, A4, A5);
-};
-
-// __fastcall Function: Arity 5.
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5>
-class RunnableAdapter<R(__fastcall*)(A1, A2, A3, A4, A5)> {
- public:
-  typedef R(RunType)(A1, A2, A3, A4, A5);
-
-  explicit RunnableAdapter(R(__fastcall* function)(A1, A2, A3, A4, A5))
-      : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4,
-        typename CallbackParamTraits<A5>::ForwardType a5) {
-    return function_(a1, a2, a3, a4, a5);
-  }
-
- private:
-  R(__fastcall* function_)(A1, A2, A3, A4, A5);
-};
-
-// __stdcall Function: Arity 6.
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6>
-class RunnableAdapter<R(__stdcall*)(A1, A2, A3, A4, A5, A6)> {
- public:
-  typedef R(RunType)(A1, A2, A3, A4, A5, A6);
-
-  explicit RunnableAdapter(R(__stdcall* function)(A1, A2, A3, A4, A5, A6))
-      : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4,
-        typename CallbackParamTraits<A5>::ForwardType a5,
-        typename CallbackParamTraits<A6>::ForwardType a6) {
-    return function_(a1, a2, a3, a4, a5, a6);
-  }
-
- private:
-  R(__stdcall* function_)(A1, A2, A3, A4, A5, A6);
-};
-
-// __fastcall Function: Arity 6.
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6>
-class RunnableAdapter<R(__fastcall*)(A1, A2, A3, A4, A5, A6)> {
- public:
-  typedef R(RunType)(A1, A2, A3, A4, A5, A6);
-
-  explicit RunnableAdapter(R(__fastcall* function)(A1, A2, A3, A4, A5, A6))
-      : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4,
-        typename CallbackParamTraits<A5>::ForwardType a5,
-        typename CallbackParamTraits<A6>::ForwardType a6) {
-    return function_(a1, a2, a3, a4, a5, a6);
-  }
-
- private:
-  R(__fastcall* function_)(A1, A2, A3, A4, A5, A6);
-};
-
-// __stdcall Function: Arity 7.
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6,
-          typename A7>
-class RunnableAdapter<R(__stdcall*)(A1, A2, A3, A4, A5, A6, A7)> {
- public:
-  typedef R(RunType)(A1, A2, A3, A4, A5, A6, A7);
-
-  explicit RunnableAdapter(R(__stdcall* function)(A1, A2, A3, A4, A5, A6, A7))
-      : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4,
-        typename CallbackParamTraits<A5>::ForwardType a5,
-        typename CallbackParamTraits<A6>::ForwardType a6,
-        typename CallbackParamTraits<A7>::ForwardType a7) {
-    return function_(a1, a2, a3, a4, a5, a6, a7);
-  }
-
- private:
-  R(__stdcall* function_)(A1, A2, A3, A4, A5, A6, A7);
-};
-
-// __fastcall Function: Arity 7.
-template <typename R,
-          typename A1,
-          typename A2,
-          typename A3,
-          typename A4,
-          typename A5,
-          typename A6,
-          typename A7>
-class RunnableAdapter<R(__fastcall*)(A1, A2, A3, A4, A5, A6, A7)> {
- public:
-  typedef R(RunType)(A1, A2, A3, A4, A5, A6, A7);
-
-  explicit RunnableAdapter(R(__fastcall* function)(A1, A2, A3, A4, A5, A6, A7))
-      : function_(function) {}
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-        typename CallbackParamTraits<A2>::ForwardType a2,
-        typename CallbackParamTraits<A3>::ForwardType a3,
-        typename CallbackParamTraits<A4>::ForwardType a4,
-        typename CallbackParamTraits<A5>::ForwardType a5,
-        typename CallbackParamTraits<A6>::ForwardType a6,
-        typename CallbackParamTraits<A7>::ForwardType a7) {
-    return function_(a1, a2, a3, a4, a5, a6, a7);
-  }
-
- private:
-  R(__fastcall* function_)(A1, A2, A3, A4, A5, A6, A7);
-};
-
-}  // namespace cef_internal
-}  // namespace base
-
-#endif  // defined(ARCH_CPU_32_BITS)
-#endif  // defined(ARCH_CPU_X86_FAMILY)
-
-#endif  // CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_WIN_H_
diff --git a/src/include/base/internal/cef_callback_internal.h b/src/include/base/internal/cef_callback_internal.h
index 1f2e16c..f3435e9 100644
--- a/src/include/base/internal/cef_callback_internal.h
+++ b/src/include/base/internal/cef_callback_internal.h
@@ -36,72 +36,156 @@
 #ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_CALLBACK_INTERNAL_H_
 #define CEF_INCLUDE_BASE_INTERNAL_CEF_CALLBACK_INTERNAL_H_
 
-#include <stddef.h>
-
-#include "include/base/cef_atomic_ref_count.h"
-#include "include/base/cef_macros.h"
+#include "include/base/cef_callback_forward.h"
 #include "include/base/cef_ref_counted.h"
-#include "include/base/cef_scoped_ptr.h"
-#include "include/base/cef_template_util.h"
-
-template <typename T>
-class ScopedVector;
 
 namespace base {
-namespace cef_internal {
-class CallbackBase;
 
-// At the base level, the only task is to add reference counting data. Don't use
-// RefCountedThreadSafe since it requires the destructor to be a virtual method.
-// Creating a vtable for every BindState template instantiation results in a lot
-// of bloat. Its only task is to call the destructor which can be done with a
-// function pointer.
-class BindStateBase {
- protected:
-  explicit BindStateBase(void (*destructor)(BindStateBase*))
-      : ref_count_(0), destructor_(destructor) {}
-  ~BindStateBase() {}
+struct FakeBindState;
+
+namespace cef_internal {
+
+class BindStateBase;
+class FinallyExecutorCommon;
+class ThenAndCatchExecutorCommon;
+
+template <typename ReturnType>
+class PostTaskExecutor;
+
+template <typename Functor, typename... BoundArgs>
+struct BindState;
+
+class CallbackBase;
+class CallbackBaseCopyable;
+
+struct BindStateBaseRefCountTraits {
+  static void Destruct(const BindStateBase*);
+};
+
+template <typename T>
+using PassingType = std::conditional_t<std::is_scalar<T>::value, T, T&&>;
+
+// BindStateBase is used to provide an opaque handle that the Callback
+// class can use to represent a function object with bound arguments.  It
+// behaves as an existential type that is used by a corresponding
+// DoInvoke function to perform the function execution.  This allows
+// us to shield the Callback class from the types of the bound argument via
+// "type erasure."
+// At the base level, the only task is to add reference counting data. Avoid
+// using or inheriting any virtual functions. Creating a vtable for every
+// BindState template instantiation results in a lot of bloat. Its only task is
+// to call the destructor which can be done with a function pointer.
+class BindStateBase
+    : public RefCountedThreadSafe<BindStateBase, BindStateBaseRefCountTraits> {
+ public:
+  REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
+
+  enum CancellationQueryMode {
+    IS_CANCELLED,
+    MAYBE_VALID,
+  };
+
+  using InvokeFuncStorage = void (*)();
+
+  BindStateBase(const BindStateBase&) = delete;
+  BindStateBase& operator=(const BindStateBase&) = delete;
 
  private:
-  friend class scoped_refptr<BindStateBase>;
+  BindStateBase(InvokeFuncStorage polymorphic_invoke,
+                void (*destructor)(const BindStateBase*));
+  BindStateBase(InvokeFuncStorage polymorphic_invoke,
+                void (*destructor)(const BindStateBase*),
+                bool (*query_cancellation_traits)(const BindStateBase*,
+                                                  CancellationQueryMode mode));
+
+  ~BindStateBase() = default;
+
+  friend struct BindStateBaseRefCountTraits;
+  friend class RefCountedThreadSafe<BindStateBase, BindStateBaseRefCountTraits>;
+
   friend class CallbackBase;
+  friend class CallbackBaseCopyable;
 
-  void AddRef();
-  void Release();
+  // Allowlist subclasses that access the destructor of BindStateBase.
+  template <typename Functor, typename... BoundArgs>
+  friend struct BindState;
+  friend struct ::base::FakeBindState;
 
-  AtomicRefCount ref_count_;
+  bool IsCancelled() const {
+    return query_cancellation_traits_(this, IS_CANCELLED);
+  }
+
+  bool MaybeValid() const {
+    return query_cancellation_traits_(this, MAYBE_VALID);
+  }
+
+  // In C++, it is safe to cast function pointers to function pointers of
+  // another type. It is not okay to use void*. We create a InvokeFuncStorage
+  // that that can store our function pointer, and then cast it back to
+  // the original type on usage.
+  InvokeFuncStorage polymorphic_invoke_;
 
   // Pointer to a function that will properly destroy |this|.
-  void (*destructor_)(BindStateBase*);
-
-  DISALLOW_COPY_AND_ASSIGN(BindStateBase);
+  void (*destructor_)(const BindStateBase*);
+  bool (*query_cancellation_traits_)(const BindStateBase*,
+                                     CancellationQueryMode mode);
 };
 
 // Holds the Callback methods that don't require specialization to reduce
 // template bloat.
+// CallbackBase<MoveOnly> is a direct base class of MoveOnly callbacks, and
+// CallbackBase<Copyable> uses CallbackBase<MoveOnly> for its implementation.
 class CallbackBase {
  public:
+  inline CallbackBase(CallbackBase&& c) noexcept;
+  CallbackBase& operator=(CallbackBase&& c) noexcept;
+
+  explicit CallbackBase(const CallbackBaseCopyable& c);
+  CallbackBase& operator=(const CallbackBaseCopyable& c);
+
+  explicit CallbackBase(CallbackBaseCopyable&& c) noexcept;
+  CallbackBase& operator=(CallbackBaseCopyable&& c) noexcept;
+
   // Returns true if Callback is null (doesn't refer to anything).
-  bool is_null() const { return bind_state_.get() == NULL; }
+  bool is_null() const { return !bind_state_; }
+  explicit operator bool() const { return !is_null(); }
+
+  // Returns true if the callback invocation will be nop due to an cancellation.
+  // It's invalid to call this on uninitialized callback.
+  //
+  // Must be called on the Callback's destination sequence.
+  bool IsCancelled() const;
+
+  // If this returns false, the callback invocation will be a nop due to a
+  // cancellation. This may(!) still return true, even on a cancelled callback.
+  //
+  // This function is thread-safe.
+  bool MaybeValid() const;
 
   // Returns the Callback into an uninitialized state.
   void Reset();
 
  protected:
-  // In C++, it is safe to cast function pointers to function pointers of
-  // another type. It is not okay to use void*. We create a InvokeFuncStorage
-  // that that can store our function pointer, and then cast it back to
-  // the original type on usage.
-  typedef void (*InvokeFuncStorage)(void);
+  friend class FinallyExecutorCommon;
+  friend class ThenAndCatchExecutorCommon;
+
+  template <typename ReturnType>
+  friend class PostTaskExecutor;
+
+  using InvokeFuncStorage = BindStateBase::InvokeFuncStorage;
 
   // Returns true if this callback equals |other|. |other| may be null.
-  bool Equals(const CallbackBase& other) const;
+  bool EqualsInternal(const CallbackBase& other) const;
+
+  constexpr inline CallbackBase();
 
   // Allow initializing of |bind_state_| via the constructor to avoid default
-  // initialization of the scoped_refptr.  We do not also initialize
-  // |polymorphic_invoke_| here because doing a normal assignment in the
-  // derived Callback templates makes for much nicer compiler errors.
-  explicit CallbackBase(BindStateBase* bind_state);
+  // initialization of the scoped_refptr.
+  explicit inline CallbackBase(BindStateBase* bind_state);
+
+  InvokeFuncStorage polymorphic_invoke() const {
+    return bind_state_->polymorphic_invoke_;
+  }
 
   // Force the destructor to be instantiated inside this translation unit so
   // that our subclasses will not get inlined versions.  Avoids more template
@@ -109,115 +193,82 @@
   ~CallbackBase();
 
   scoped_refptr<BindStateBase> bind_state_;
-  InvokeFuncStorage polymorphic_invoke_;
 };
 
-// A helper template to determine if given type is non-const move-only-type,
-// i.e. if a value of the given type should be passed via .Pass() in a
-// destructive way.
-template <typename T>
-struct IsMoveOnlyType {
-  template <typename U>
-  static YesType Test(const typename U::MoveOnlyTypeForCPP03*);
+constexpr CallbackBase::CallbackBase() = default;
+CallbackBase::CallbackBase(CallbackBase&&) noexcept = default;
+CallbackBase::CallbackBase(BindStateBase* bind_state)
+    : bind_state_(AdoptRef(bind_state)) {}
 
-  template <typename U>
-  static NoType Test(...);
+// CallbackBase<Copyable> is a direct base class of Copyable Callbacks.
+class CallbackBaseCopyable : public CallbackBase {
+ public:
+  CallbackBaseCopyable(const CallbackBaseCopyable& c);
+  CallbackBaseCopyable(CallbackBaseCopyable&& c) noexcept = default;
+  CallbackBaseCopyable& operator=(const CallbackBaseCopyable& c);
+  CallbackBaseCopyable& operator=(CallbackBaseCopyable&& c) noexcept;
 
-  static const bool value =
-      sizeof(Test<T>(0)) == sizeof(YesType) && !is_const<T>::value;
+ protected:
+  constexpr CallbackBaseCopyable() = default;
+  explicit CallbackBaseCopyable(BindStateBase* bind_state)
+      : CallbackBase(bind_state) {}
+  ~CallbackBaseCopyable() = default;
 };
 
-// This is a typetraits object that's used to take an argument type, and
-// extract a suitable type for storing and forwarding arguments.
-//
-// In particular, it strips off references, and converts arrays to
-// pointers for storage; and it avoids accidentally trying to create a
-// "reference of a reference" if the argument is a reference type.
-//
-// This array type becomes an issue for storage because we are passing bound
-// parameters by const reference. In this case, we end up passing an actual
-// array type in the initializer list which C++ does not allow.  This will
-// break passing of C-string literals.
-template <typename T, bool is_move_only = IsMoveOnlyType<T>::value>
-struct CallbackParamTraits {
-  typedef const T& ForwardType;
-  typedef T StorageType;
+// Helpers for the `Then()` implementation.
+template <typename OriginalCallback, typename ThenCallback>
+struct ThenHelper;
+
+// Specialization when original callback returns `void`.
+template <template <typename> class OriginalCallback,
+          template <typename>
+          class ThenCallback,
+          typename... OriginalArgs,
+          typename ThenR,
+          typename... ThenArgs>
+struct ThenHelper<OriginalCallback<void(OriginalArgs...)>,
+                  ThenCallback<ThenR(ThenArgs...)>> {
+  static_assert(sizeof...(ThenArgs) == 0,
+                "|then| callback cannot accept parameters if |this| has a "
+                "void return type.");
+
+  static auto CreateTrampoline() {
+    return [](OriginalCallback<void(OriginalArgs...)> c1,
+              ThenCallback<ThenR(ThenArgs...)> c2, OriginalArgs... c1_args) {
+      std::move(c1).Run(std::forward<OriginalArgs>(c1_args)...);
+      return std::move(c2).Run();
+    };
+  }
 };
 
-// The Storage should almost be impossible to trigger unless someone manually
-// specifies type of the bind parameters.  However, in case they do,
-// this will guard against us accidentally storing a reference parameter.
-//
-// The ForwardType should only be used for unbound arguments.
-template <typename T>
-struct CallbackParamTraits<T&, false> {
-  typedef T& ForwardType;
-  typedef T StorageType;
+// Specialization when original callback returns a non-void type.
+template <template <typename> class OriginalCallback,
+          template <typename>
+          class ThenCallback,
+          typename OriginalR,
+          typename... OriginalArgs,
+          typename ThenR,
+          typename... ThenArgs>
+struct ThenHelper<OriginalCallback<OriginalR(OriginalArgs...)>,
+                  ThenCallback<ThenR(ThenArgs...)>> {
+  static_assert(sizeof...(ThenArgs) == 1,
+                "|then| callback must accept exactly one parameter if |this| "
+                "has a non-void return type.");
+  // TODO(dcheng): This should probably check is_convertible as well (same with
+  // `AssertBindArgsValidity`).
+  static_assert(std::is_constructible<ThenArgs..., OriginalR&&>::value,
+                "|then| callback's parameter must be constructible from "
+                "return type of |this|.");
+
+  static auto CreateTrampoline() {
+    return [](OriginalCallback<OriginalR(OriginalArgs...)> c1,
+              ThenCallback<ThenR(ThenArgs...)> c2, OriginalArgs... c1_args) {
+      return std::move(c2).Run(
+          std::move(c1).Run(std::forward<OriginalArgs>(c1_args)...));
+    };
+  }
 };
 
-// Note that for array types, we implicitly add a const in the conversion. This
-// means that it is not possible to bind array arguments to functions that take
-// a non-const pointer. Trying to specialize the template based on a "const
-// T[n]" does not seem to match correctly, so we are stuck with this
-// restriction.
-template <typename T, size_t n>
-struct CallbackParamTraits<T[n], false> {
-  typedef const T* ForwardType;
-  typedef const T* StorageType;
-};
-
-// See comment for CallbackParamTraits<T[n]>.
-template <typename T>
-struct CallbackParamTraits<T[], false> {
-  typedef const T* ForwardType;
-  typedef const T* StorageType;
-};
-
-// Parameter traits for movable-but-not-copyable scopers.
-//
-// Callback<>/Bind() understands movable-but-not-copyable semantics where
-// the type cannot be copied but can still have its state destructively
-// transferred (aka. moved) to another instance of the same type by calling a
-// helper function.  When used with Bind(), this signifies transferal of the
-// object's state to the target function.
-//
-// For these types, the ForwardType must not be a const reference, or a
-// reference.  A const reference is inappropriate, and would break const
-// correctness, because we are implementing a destructive move.  A non-const
-// reference cannot be used with temporaries which means the result of a
-// function or a cast would not be usable with Callback<> or Bind().
-template <typename T>
-struct CallbackParamTraits<T, true> {
-  typedef T ForwardType;
-  typedef T StorageType;
-};
-
-// CallbackForward() is a very limited simulation of C++11's std::forward()
-// used by the Callback/Bind system for a set of movable-but-not-copyable
-// types.  It is needed because forwarding a movable-but-not-copyable
-// argument to another function requires us to invoke the proper move
-// operator to create a rvalue version of the type.  The supported types are
-// whitelisted below as overloads of the CallbackForward() function. The
-// default template compiles out to be a no-op.
-//
-// In C++11, std::forward would replace all uses of this function.  However, it
-// is impossible to implement a general std::forward with C++11 due to a lack
-// of rvalue references.
-//
-// In addition to Callback/Bind, this is used by PostTaskAndReplyWithResult to
-// simulate std::forward() and forward the result of one Callback as a
-// parameter to another callback. This is to support Callbacks that return
-// the movable-but-not-copyable types whitelisted above.
-template <typename T>
-typename enable_if<!IsMoveOnlyType<T>::value, T>::type& CallbackForward(T& t) {
-  return t;
-}
-
-template <typename T>
-typename enable_if<IsMoveOnlyType<T>::value, T>::type CallbackForward(T& t) {
-  return t.Pass();
-}
-
 }  // namespace cef_internal
 }  // namespace base
 
diff --git a/src/include/base/internal/cef_lock_impl.h b/src/include/base/internal/cef_lock_impl.h
index 470547f..606e586 100644
--- a/src/include/base/internal/cef_lock_impl.h
+++ b/src/include/base/internal/cef_lock_impl.h
@@ -40,8 +40,6 @@
 #include <pthread.h>
 #endif
 
-#include "include/base/cef_macros.h"
-
 namespace base {
 namespace cef_internal {
 
@@ -57,6 +55,10 @@
 #endif
 
   LockImpl();
+
+  LockImpl(const LockImpl&) = delete;
+  LockImpl& operator=(const LockImpl&) = delete;
+
   ~LockImpl();
 
   // If the lock is not held, take it and return true.  If the lock is already
@@ -77,8 +79,6 @@
 
  private:
   NativeHandle native_handle_;
-
-  DISALLOW_COPY_AND_ASSIGN(LockImpl);
 };
 
 }  // namespace cef_internal
diff --git a/src/include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h b/src/include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h
index 9f2f932..078d89c 100644
--- a/src/include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h
+++ b/src/include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h
@@ -32,10 +32,7 @@
 #ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_
 #define CEF_INCLUDE_BASE_INTERNAL_CEF_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_
 
-#include "include/base/cef_build.h"
-#include "include/base/cef_ref_counted.h"
-#include "include/base/cef_template_util.h"
-#include "include/base/cef_tuple.h"
+#include <type_traits>
 
 // It is dangerous to post a task with a T* argument where T is a subtype of
 // RefCounted(Base|ThreadSafeBase), since by the time the parameter is used, the
@@ -46,132 +43,27 @@
 
 namespace base {
 
+// This is a base internal implementation file used by task.h and callback.h.
+// Not for public consumption, so we wrap it in namespace internal.
 namespace cef_internal {
 
+template <typename T, typename = void>
+struct IsRefCountedType : std::false_type {};
+
 template <typename T>
-struct NeedsScopedRefptrButGetsRawPtr {
-#if defined(OS_WIN)
-  enum { value = base::false_type::value };
-#else
-  enum {
-    // Human readable translation: you needed to be a scoped_refptr if you are a
-    // raw pointer type and are convertible to a RefCounted(Base|ThreadSafeBase)
-    // type.
-    value = (is_pointer<T>::value &&
-             (is_convertible<T, subtle::RefCountedBase*>::value ||
-              is_convertible<T, subtle::RefCountedThreadSafeBase*>::value))
-  };
-#endif
-};
+struct IsRefCountedType<T,
+                        std::void_t<decltype(std::declval<T*>()->AddRef()),
+                                    decltype(std::declval<T*>()->Release())>>
+    : std::true_type {};
 
-template <typename Params>
-struct ParamsUseScopedRefptrCorrectly {
-  enum { value = 0 };
-};
-
-template <>
-struct ParamsUseScopedRefptrCorrectly<Tuple0> {
-  enum { value = 1 };
-};
-
-template <typename A>
-struct ParamsUseScopedRefptrCorrectly<Tuple1<A>> {
-  enum { value = !NeedsScopedRefptrButGetsRawPtr<A>::value };
-};
-
-template <typename A, typename B>
-struct ParamsUseScopedRefptrCorrectly<Tuple2<A, B>> {
-  enum {
-    value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
-              NeedsScopedRefptrButGetsRawPtr<B>::value)
-  };
-};
-
-template <typename A, typename B, typename C>
-struct ParamsUseScopedRefptrCorrectly<Tuple3<A, B, C>> {
-  enum {
-    value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
-              NeedsScopedRefptrButGetsRawPtr<B>::value ||
-              NeedsScopedRefptrButGetsRawPtr<C>::value)
-  };
-};
-
-template <typename A, typename B, typename C, typename D>
-struct ParamsUseScopedRefptrCorrectly<Tuple4<A, B, C, D>> {
-  enum {
-    value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
-              NeedsScopedRefptrButGetsRawPtr<B>::value ||
-              NeedsScopedRefptrButGetsRawPtr<C>::value ||
-              NeedsScopedRefptrButGetsRawPtr<D>::value)
-  };
-};
-
-template <typename A, typename B, typename C, typename D, typename E>
-struct ParamsUseScopedRefptrCorrectly<Tuple5<A, B, C, D, E>> {
-  enum {
-    value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
-              NeedsScopedRefptrButGetsRawPtr<B>::value ||
-              NeedsScopedRefptrButGetsRawPtr<C>::value ||
-              NeedsScopedRefptrButGetsRawPtr<D>::value ||
-              NeedsScopedRefptrButGetsRawPtr<E>::value)
-  };
-};
-
-template <typename A,
-          typename B,
-          typename C,
-          typename D,
-          typename E,
-          typename F>
-struct ParamsUseScopedRefptrCorrectly<Tuple6<A, B, C, D, E, F>> {
-  enum {
-    value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
-              NeedsScopedRefptrButGetsRawPtr<B>::value ||
-              NeedsScopedRefptrButGetsRawPtr<C>::value ||
-              NeedsScopedRefptrButGetsRawPtr<D>::value ||
-              NeedsScopedRefptrButGetsRawPtr<E>::value ||
-              NeedsScopedRefptrButGetsRawPtr<F>::value)
-  };
-};
-
-template <typename A,
-          typename B,
-          typename C,
-          typename D,
-          typename E,
-          typename F,
-          typename G>
-struct ParamsUseScopedRefptrCorrectly<Tuple7<A, B, C, D, E, F, G>> {
-  enum {
-    value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
-              NeedsScopedRefptrButGetsRawPtr<B>::value ||
-              NeedsScopedRefptrButGetsRawPtr<C>::value ||
-              NeedsScopedRefptrButGetsRawPtr<D>::value ||
-              NeedsScopedRefptrButGetsRawPtr<E>::value ||
-              NeedsScopedRefptrButGetsRawPtr<F>::value ||
-              NeedsScopedRefptrButGetsRawPtr<G>::value)
-  };
-};
-
-template <typename A,
-          typename B,
-          typename C,
-          typename D,
-          typename E,
-          typename F,
-          typename G,
-          typename H>
-struct ParamsUseScopedRefptrCorrectly<Tuple8<A, B, C, D, E, F, G, H>> {
-  enum {
-    value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
-              NeedsScopedRefptrButGetsRawPtr<B>::value ||
-              NeedsScopedRefptrButGetsRawPtr<C>::value ||
-              NeedsScopedRefptrButGetsRawPtr<D>::value ||
-              NeedsScopedRefptrButGetsRawPtr<E>::value ||
-              NeedsScopedRefptrButGetsRawPtr<F>::value ||
-              NeedsScopedRefptrButGetsRawPtr<G>::value ||
-              NeedsScopedRefptrButGetsRawPtr<H>::value)
-  };
+// Human readable translation: you needed to be a scoped_refptr if you are a raw
+// pointer type and are convertible to a RefCounted(Base|ThreadSafeBase) type.
+template <typename T>
+struct NeedsScopedRefptrButGetsRawPtr
+    : std::conjunction<std::is_pointer<T>,
+                       IsRefCountedType<std::remove_pointer_t<T>>> {
+  static_assert(!std::is_reference<T>::value,
+                "NeedsScopedRefptrButGetsRawPtr requires non-reference type.");
 };
 
 }  // namespace cef_internal
diff --git a/src/include/base/internal/cef_scoped_block_mac.h b/src/include/base/internal/cef_scoped_block_mac.h
new file mode 100644
index 0000000..4e255d1
--- /dev/null
+++ b/src/include/base/internal/cef_scoped_block_mac.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2013 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Do not include this header file directly. Use base/mac/scoped_block.h
+// instead.
+
+#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_SCOPED_BLOCK_MAC_H_
+#define CEF_INCLUDE_BASE_INTERNAL_CEF_SCOPED_BLOCK_MAC_H_
+
+#include <Block.h>
+
+#include "include/base/cef_scoped_typeref_mac.h"
+
+#if defined(__has_feature) && __has_feature(objc_arc)
+#error \
+    "Cannot include include/base/internal/cef_scoped_block_mac.h in file built with ARC."
+#endif
+
+namespace base {
+namespace mac {
+
+namespace cef_internal {
+
+template <typename B>
+struct ScopedBlockTraits {
+  static B InvalidValue() { return nullptr; }
+  static B Retain(B block) { return Block_copy(block); }
+  static void Release(B block) { Block_release(block); }
+};
+
+}  // namespace cef_internal
+
+// ScopedBlock<> is patterned after ScopedCFTypeRef<>, but uses Block_copy() and
+// Block_release() instead of CFRetain() and CFRelease().
+template <typename B>
+using ScopedBlock = ScopedTypeRef<B, cef_internal::ScopedBlockTraits<B>>;
+
+}  // namespace mac
+}  // namespace base
+
+#endif  // CEF_INCLUDE_BASE_INTERNAL_CEF_SCOPED_BLOCK_MAC_H_
diff --git a/src/include/cef_request_callback.h b/src/include/base/internal/cef_scoped_policy.h
similarity index 60%
copy from src/include/cef_request_callback.h
copy to src/include/base/internal/cef_scoped_policy.h
index 68094de..8ef4fb2 100644
--- a/src/include/cef_request_callback.h
+++ b/src/include/base/internal/cef_scoped_policy.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2012 Google Inc. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -26,38 +26,28 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// ---------------------------------------------------------------------------
-//
-// The contents of this file must follow a specific format in order to
-// support the CEF translator tool. See the translator.README.txt file in the
-// tools directory for more information.
-//
 
-#ifndef CEF_INCLUDE_CEF_REQUEST_CALLBACK_H_
-#define CEF_INCLUDE_CEF_REQUEST_CALLBACK_H_
-#pragma once
+// Do not include this header file directly. Use base/memory/scoped_policy.h
+// instead.
 
-#include "include/cef_base.h"
+#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_SCOPED_POLICY_H_
+#define CEF_INCLUDE_BASE_INTERNAL_CEF_SCOPED_POLICY_H_
 
-///
-// Callback interface used for asynchronous continuation of url requests.
-///
-/*--cef(source=library)--*/
-class CefRequestCallback : public virtual CefBaseRefCounted {
- public:
-  ///
-  // Continue the url request. If |allow| is true the request will be continued.
-  // Otherwise, the request will be canceled.
-  ///
-  /*--cef(capi_name=cont)--*/
-  virtual void Continue(bool allow) = 0;
+namespace base {
+namespace scoped_policy {
 
-  ///
-  // Cancel the url request.
-  ///
-  /*--cef()--*/
-  virtual void Cancel() = 0;
+// Defines the ownership policy for a scoped object.
+enum OwnershipPolicy {
+  // The scoped object takes ownership of an object by taking over an existing
+  // ownership claim.
+  ASSUME,
+
+  // The scoped object will retain the object and any initial ownership is
+  // not changed.
+  RETAIN
 };
 
-#endif  // CEF_INCLUDE_CEF_REQUEST_CALLBACK_H_
+}  // namespace scoped_policy
+}  // namespace base
+
+#endif  // CEF_INCLUDE_BASE_INTERNAL_CEF_SCOPED_POLICY_H_
diff --git a/src/include/capi/cef_accessibility_handler_capi.h b/src/include/capi/cef_accessibility_handler_capi.h
index 3bb8363..120714a 100644
--- a/src/include/capi/cef_accessibility_handler_capi.h
+++ b/src/include/capi/cef_accessibility_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=00d5124d346e3f3cc3f53d67bcb766d1d798bf12$
+// $hash=0ac3c8ca887778a840c65108d56038d4d776e073$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_ACCESSIBILITY_HANDLER_CAPI_H_
@@ -47,27 +47,27 @@
 #endif
 
 ///
-// Implement this structure to receive accessibility notification when
-// accessibility events have been registered. The functions of this structure
-// will be called on the UI thread.
+/// Implement this structure to receive accessibility notification when
+/// accessibility events have been registered. The functions of this structure
+/// will be called on the UI thread.
 ///
 typedef struct _cef_accessibility_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called after renderer process sends accessibility tree changes to the
-  // browser process.
+  /// Called after renderer process sends accessibility tree changes to the
+  /// browser process.
   ///
   void(CEF_CALLBACK* on_accessibility_tree_change)(
       struct _cef_accessibility_handler_t* self,
       struct _cef_value_t* value);
 
   ///
-  // Called after renderer process sends accessibility location changes to the
-  // browser process.
+  /// Called after renderer process sends accessibility location changes to the
+  /// browser process.
   ///
   void(CEF_CALLBACK* on_accessibility_location_change)(
       struct _cef_accessibility_handler_t* self,
diff --git a/src/include/capi/cef_app_capi.h b/src/include/capi/cef_app_capi.h
index 033ebb0..f1b58c5 100644
--- a/src/include/capi/cef_app_capi.h
+++ b/src/include/capi/cef_app_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=04cfae434fe901644c1c78f1c30c0921518cc666$
+// $hash=9b523fbf312a8a0cb1c743a3c8aca7bc9cc22bbc$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_APP_CAPI_H_
@@ -54,25 +54,26 @@
 struct _cef_app_t;
 
 ///
-// Implement this structure to provide handler implementations. Methods will be
-// called by the process and/or thread indicated.
+/// Implement this structure to provide handler implementations. Methods will be
+/// called by the process and/or thread indicated.
 ///
 typedef struct _cef_app_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Provides an opportunity to view and/or modify command-line arguments before
-  // processing by CEF and Chromium. The |process_type| value will be NULL for
-  // the browser process. Do not keep a reference to the cef_command_line_t
-  // object passed to this function. The CefSettings.command_line_args_disabled
-  // value can be used to start with an NULL command-line object. Any values
-  // specified in CefSettings that equate to command-line arguments will be set
-  // before this function is called. Be cautious when using this function to
-  // modify command-line arguments for non-browser processes as this may result
-  // in undefined behavior including crashes.
+  /// Provides an opportunity to view and/or modify command-line arguments
+  /// before processing by CEF and Chromium. The |process_type| value will be
+  /// NULL for the browser process. Do not keep a reference to the
+  /// cef_command_line_t object passed to this function. The
+  /// cef_settings_t.command_line_args_disabled value can be used to start with
+  /// an NULL command-line object. Any values specified in CefSettings that
+  /// equate to command-line arguments will be set before this function is
+  /// called. Be cautious when using this function to modify command-line
+  /// arguments for non-browser processes as this may result in undefined
+  /// behavior including crashes.
   ///
   void(CEF_CALLBACK* on_before_command_line_processing)(
       struct _cef_app_t* self,
@@ -80,119 +81,107 @@
       struct _cef_command_line_t* command_line);
 
   ///
-  // Provides an opportunity to register custom schemes. Do not keep a reference
-  // to the |registrar| object. This function is called on the main thread for
-  // each process and the registered schemes should be the same across all
-  // processes.
+  /// Provides an opportunity to register custom schemes. Do not keep a
+  /// reference to the |registrar| object. This function is called on the main
+  /// thread for each process and the registered schemes should be the same
+  /// across all processes.
   ///
   void(CEF_CALLBACK* on_register_custom_schemes)(
       struct _cef_app_t* self,
       struct _cef_scheme_registrar_t* registrar);
 
   ///
-  // Return the handler for resource bundle events. If
-  // CefSettings.pack_loading_disabled is true (1) a handler must be returned.
-  // If no handler is returned resources will be loaded from pack files. This
-  // function is called by the browser and render processes on multiple threads.
+  /// Return the handler for resource bundle events. If
+  /// cef_settings_t.pack_loading_disabled is true (1) a handler must be
+  /// returned. If no handler is returned resources will be loaded from pack
+  /// files. This function is called by the browser and render processes on
+  /// multiple threads.
   ///
   struct _cef_resource_bundle_handler_t*(
       CEF_CALLBACK* get_resource_bundle_handler)(struct _cef_app_t* self);
 
   ///
-  // Return the handler for functionality specific to the browser process. This
-  // function is called on multiple threads in the browser process.
+  /// Return the handler for functionality specific to the browser process. This
+  /// function is called on multiple threads in the browser process.
   ///
   struct _cef_browser_process_handler_t*(
       CEF_CALLBACK* get_browser_process_handler)(struct _cef_app_t* self);
 
   ///
-  // Return the handler for functionality specific to the render process. This
-  // function is called on the render process main thread.
+  /// Return the handler for functionality specific to the render process. This
+  /// function is called on the render process main thread.
   ///
   struct _cef_render_process_handler_t*(
       CEF_CALLBACK* get_render_process_handler)(struct _cef_app_t* self);
 } cef_app_t;
 
 ///
-// This function should be called from the application entry point function to
-// execute a secondary process. It can be used to run secondary processes from
-// the browser client executable (default behavior) or from a separate
-// executable specified by the CefSettings.browser_subprocess_path value. If
-// called for the browser process (identified by no "type" command-line value)
-// it will return immediately with a value of -1. If called for a recognized
-// secondary process it will block until the process should exit and then return
-// the process exit code. The |application| parameter may be NULL. The
-// |windows_sandbox_info| parameter is only used on Windows and may be NULL (see
-// cef_sandbox_win.h for details).
+/// This function should be called from the application entry point function to
+/// execute a secondary process. It can be used to run secondary processes from
+/// the browser client executable (default behavior) or from a separate
+/// executable specified by the cef_settings_t.browser_subprocess_path value. If
+/// called for the browser process (identified by no "type" command-line value)
+/// it will return immediately with a value of -1. If called for a recognized
+/// secondary process it will block until the process should exit and then
+/// return the process exit code. The |application| parameter may be NULL. The
+/// |windows_sandbox_info| parameter is only used on Windows and may be NULL
+/// (see cef_sandbox_win.h for details).
 ///
-CEF_EXPORT int cef_execute_process(const struct _cef_main_args_t* args,
+CEF_EXPORT int cef_execute_process(const cef_main_args_t* args,
                                    cef_app_t* application,
                                    void* windows_sandbox_info);
 
 ///
-// This function should be called on the main application thread to initialize
-// the CEF browser process. The |application| parameter may be NULL. A return
-// value of true (1) indicates that it succeeded and false (0) indicates that it
-// failed. The |windows_sandbox_info| parameter is only used on Windows and may
-// be NULL (see cef_sandbox_win.h for details).
+/// This function should be called on the main application thread to initialize
+/// the CEF browser process. The |application| parameter may be NULL. A return
+/// value of true (1) indicates that it succeeded and false (0) indicates that
+/// it failed. The |windows_sandbox_info| parameter is only used on Windows and
+/// may be NULL (see cef_sandbox_win.h for details).
 ///
-CEF_EXPORT int cef_initialize(const struct _cef_main_args_t* args,
+CEF_EXPORT int cef_initialize(const cef_main_args_t* args,
                               const struct _cef_settings_t* settings,
                               cef_app_t* application,
                               void* windows_sandbox_info);
 
 ///
-// This function should be called on the main application thread to shut down
-// the CEF browser process before the application exits.
+/// This function should be called on the main application thread to shut down
+/// the CEF browser process before the application exits.
 ///
-CEF_EXPORT void cef_shutdown();
+CEF_EXPORT void cef_shutdown(void);
 
 ///
-// Perform a single iteration of CEF message loop processing. This function is
-// provided for cases where the CEF message loop must be integrated into an
-// existing application message loop. Use of this function is not recommended
-// for most users; use either the cef_run_message_loop() function or
-// CefSettings.multi_threaded_message_loop if possible. When using this function
-// care must be taken to balance performance against excessive CPU usage. It is
-// recommended to enable the CefSettings.external_message_pump option when using
-// this function so that
-// cef_browser_process_handler_t::on_schedule_message_pump_work() callbacks can
-// facilitate the scheduling process. This function should only be called on the
-// main application thread and only if cef_initialize() is called with a
-// CefSettings.multi_threaded_message_loop value of false (0). This function
-// will not block.
+/// Perform a single iteration of CEF message loop processing. This function is
+/// provided for cases where the CEF message loop must be integrated into an
+/// existing application message loop. Use of this function is not recommended
+/// for most users; use either the cef_run_message_loop() function or
+/// cef_settings_t.multi_threaded_message_loop if possible. When using this
+/// function care must be taken to balance performance against excessive CPU
+/// usage. It is recommended to enable the cef_settings_t.external_message_pump
+/// option when using this function so that
+/// cef_browser_process_handler_t::on_schedule_message_pump_work() callbacks can
+/// facilitate the scheduling process. This function should only be called on
+/// the main application thread and only if cef_initialize() is called with a
+/// cef_settings_t.multi_threaded_message_loop value of false (0). This function
+/// will not block.
 ///
-CEF_EXPORT void cef_do_message_loop_work();
+CEF_EXPORT void cef_do_message_loop_work(void);
 
 ///
-// Run the CEF message loop. Use this function instead of an application-
-// provided message loop to get the best balance between performance and CPU
-// usage. This function should only be called on the main application thread and
-// only if cef_initialize() is called with a
-// CefSettings.multi_threaded_message_loop value of false (0). This function
-// will block until a quit message is received by the system.
+/// Run the CEF message loop. Use this function instead of an application-
+/// provided message loop to get the best balance between performance and CPU
+/// usage. This function should only be called on the main application thread
+/// and only if cef_initialize() is called with a
+/// cef_settings_t.multi_threaded_message_loop value of false (0). This function
+/// will block until a quit message is received by the system.
 ///
-CEF_EXPORT void cef_run_message_loop();
+CEF_EXPORT void cef_run_message_loop(void);
 
 ///
-// Quit the CEF message loop that was started by calling cef_run_message_loop().
-// This function should only be called on the main application thread and only
-// if cef_run_message_loop() was used.
+/// Quit the CEF message loop that was started by calling
+/// cef_run_message_loop(). This function should only be called on the main
+/// application thread and only if cef_run_message_loop() was used.
 ///
-CEF_EXPORT void cef_quit_message_loop();
-
-///
-// Set to true (1) before calling Windows APIs like TrackPopupMenu that enter a
-// modal message loop. Set to false (0) after exiting the modal message loop.
-///
-CEF_EXPORT void cef_set_osmodal_loop(int osModalLoop);
-
-///
-// Call during process startup to enable High-DPI support on Windows 7 or newer.
-// Older versions of Windows should be left DPI-unaware because they do not
-// support DirectWrite and GDI fonts are kerned very badly.
-///
-CEF_EXPORT void cef_enable_highdpi_support();
+CEF_EXPORT void cef_quit_message_loop(void);
 
 #ifdef __cplusplus
 }
diff --git a/src/include/capi/cef_audio_handler_capi.h b/src/include/capi/cef_audio_handler_capi.h
index 1f6783b..03c9233 100644
--- a/src/include/capi/cef_audio_handler_capi.h
+++ b/src/include/capi/cef_audio_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=430877d950508a545d0baa18c8c8c0d2d183fec4$
+// $hash=932c3ecb22fd26322d96d0e01459122aadafd302$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_AUDIO_HANDLER_CAPI_H_
@@ -48,30 +48,30 @@
 #endif
 
 ///
-// Implement this structure to handle audio events.
+/// Implement this structure to handle audio events.
 ///
 typedef struct _cef_audio_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called on the UI thread to allow configuration of audio stream parameters.
-  // Return true (1) to proceed with audio stream capture, or false (0) to
-  // cancel it. All members of |params| can optionally be configured here, but
-  // they are also pre-filled with some sensible defaults.
+  /// Called on the UI thread to allow configuration of audio stream parameters.
+  /// Return true (1) to proceed with audio stream capture, or false (0) to
+  /// cancel it. All members of |params| can optionally be configured here, but
+  /// they are also pre-filled with some sensible defaults.
   ///
   int(CEF_CALLBACK* get_audio_parameters)(struct _cef_audio_handler_t* self,
                                           struct _cef_browser_t* browser,
                                           cef_audio_parameters_t* params);
 
   ///
-  // Called on a browser audio capture thread when the browser starts streaming
-  // audio. OnAudioSteamStopped will always be called after
-  // OnAudioStreamStarted; both functions may be called multiple times for the
-  // same browser. |params| contains the audio parameters like sample rate and
-  // channel layout. |channels| is the number of channels.
+  /// Called on a browser audio capture thread when the browser starts streaming
+  /// audio. OnAudioStreamStopped will always be called after
+  /// OnAudioStreamStarted; both functions may be called multiple times for the
+  /// same browser. |params| contains the audio parameters like sample rate and
+  /// channel layout. |channels| is the number of channels.
   ///
   void(CEF_CALLBACK* on_audio_stream_started)(
       struct _cef_audio_handler_t* self,
@@ -80,34 +80,34 @@
       int channels);
 
   ///
-  // Called on the audio stream thread when a PCM packet is received for the
-  // stream. |data| is an array representing the raw PCM data as a floating
-  // point type, i.e. 4-byte value(s). |frames| is the number of frames in the
-  // PCM packet. |pts| is the presentation timestamp (in milliseconds since the
-  // Unix Epoch) and represents the time at which the decompressed packet should
-  // be presented to the user. Based on |frames| and the |channel_layout| value
-  // passed to OnAudioStreamStarted you can calculate the size of the |data|
-  // array in bytes.
+  /// Called on the audio stream thread when a PCM packet is received for the
+  /// stream. |data| is an array representing the raw PCM data as a floating
+  /// point type, i.e. 4-byte value(s). |frames| is the number of frames in the
+  /// PCM packet. |pts| is the presentation timestamp (in milliseconds since the
+  /// Unix Epoch) and represents the time at which the decompressed packet
+  /// should be presented to the user. Based on |frames| and the
+  /// |channel_layout| value passed to OnAudioStreamStarted you can calculate
+  /// the size of the |data| array in bytes.
   ///
   void(CEF_CALLBACK* on_audio_stream_packet)(struct _cef_audio_handler_t* self,
                                              struct _cef_browser_t* browser,
                                              const float** data,
                                              int frames,
-                                             int64 pts);
+                                             int64_t pts);
 
   ///
-  // Called on the UI thread when the stream has stopped. OnAudioSteamStopped
-  // will always be called after OnAudioStreamStarted; both functions may be
-  // called multiple times for the same stream.
+  /// Called on the UI thread when the stream has stopped. OnAudioSteamStopped
+  /// will always be called after OnAudioStreamStarted; both functions may be
+  /// called multiple times for the same stream.
   ///
   void(CEF_CALLBACK* on_audio_stream_stopped)(struct _cef_audio_handler_t* self,
                                               struct _cef_browser_t* browser);
 
   ///
-  // Called on the UI or audio stream thread when an error occurred. During the
-  // stream creation phase this callback will be called on the UI thread while
-  // in the capturing phase it will be called on the audio stream thread. The
-  // stream will be stopped immediately.
+  /// Called on the UI or audio stream thread when an error occurred. During the
+  /// stream creation phase this callback will be called on the UI thread while
+  /// in the capturing phase it will be called on the audio stream thread. The
+  /// stream will be stopped immediately.
   ///
   void(CEF_CALLBACK* on_audio_stream_error)(struct _cef_audio_handler_t* self,
                                             struct _cef_browser_t* browser,
diff --git a/src/include/capi/cef_auth_callback_capi.h b/src/include/capi/cef_auth_callback_capi.h
index 5e7ea36..6e74c0a 100644
--- a/src/include/capi/cef_auth_callback_capi.h
+++ b/src/include/capi/cef_auth_callback_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=58be0e24b46373bbdad28031891396ea246f446c$
+// $hash=4b9c31ef9a23f899c6d8cd3da49934a41f1bd231$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_AUTH_CALLBACK_CAPI_H_
@@ -47,24 +47,24 @@
 #endif
 
 ///
-// Callback structure used for asynchronous continuation of authentication
-// requests.
+/// Callback structure used for asynchronous continuation of authentication
+/// requests.
 ///
 typedef struct _cef_auth_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Continue the authentication request.
+  /// Continue the authentication request.
   ///
   void(CEF_CALLBACK* cont)(struct _cef_auth_callback_t* self,
                            const cef_string_t* username,
                            const cef_string_t* password);
 
   ///
-  // Cancel the authentication request.
+  /// Cancel the authentication request.
   ///
   void(CEF_CALLBACK* cancel)(struct _cef_auth_callback_t* self);
 } cef_auth_callback_t;
diff --git a/src/include/capi/cef_browser_capi.h b/src/include/capi/cef_browser_capi.h
index 4336c8d..cf64c83 100644
--- a/src/include/capi/cef_browser_capi.h
+++ b/src/include/capi/cef_browser_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=6cb00a0fa3631a46903abb3a783f315895511db2$
+// $hash=eed525e9abcbf8e8b959067e0056ca470c5210c7$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_BROWSER_CAPI_H_
@@ -57,170 +57,179 @@
 struct _cef_client_t;
 
 ///
-// Structure used to represent a browser window. When used in the browser
-// process the functions of this structure may be called on any thread unless
-// otherwise indicated in the comments. When used in the render process the
-// functions of this structure may only be called on the main thread.
+/// Structure used to represent a browser. When used in the browser process the
+/// functions of this structure may be called on any thread unless otherwise
+/// indicated in the comments. When used in the render process the functions of
+/// this structure may only be called on the main thread.
 ///
 typedef struct _cef_browser_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the browser host object. This function can only be called in the
-  // browser process.
+  /// True if this object is currently valid. This will return false (0) after
+  /// cef_life_span_handler_t::OnBeforeClose is called.
+  ///
+  int(CEF_CALLBACK* is_valid)(struct _cef_browser_t* self);
+
+  ///
+  /// Returns the browser host object. This function can only be called in the
+  /// browser process.
   ///
   struct _cef_browser_host_t*(CEF_CALLBACK* get_host)(
       struct _cef_browser_t* self);
 
   ///
-  // Returns true (1) if the browser can navigate backwards.
+  /// Returns true (1) if the browser can navigate backwards.
   ///
   int(CEF_CALLBACK* can_go_back)(struct _cef_browser_t* self);
 
   ///
-  // Navigate backwards.
+  /// Navigate backwards.
   ///
   void(CEF_CALLBACK* go_back)(struct _cef_browser_t* self);
 
   ///
-  // Returns true (1) if the browser can navigate forwards.
+  /// Returns true (1) if the browser can navigate forwards.
   ///
   int(CEF_CALLBACK* can_go_forward)(struct _cef_browser_t* self);
 
   ///
-  // Navigate forwards.
+  /// Navigate forwards.
   ///
   void(CEF_CALLBACK* go_forward)(struct _cef_browser_t* self);
 
   ///
-  // Returns true (1) if the browser is currently loading.
+  /// Returns true (1) if the browser is currently loading.
   ///
   int(CEF_CALLBACK* is_loading)(struct _cef_browser_t* self);
 
   ///
-  // Reload the current page.
+  /// Reload the current page.
   ///
   void(CEF_CALLBACK* reload)(struct _cef_browser_t* self);
 
   ///
-  // Reload the current page ignoring any cached data.
+  /// Reload the current page ignoring any cached data.
   ///
   void(CEF_CALLBACK* reload_ignore_cache)(struct _cef_browser_t* self);
 
   ///
-  // Stop loading the page.
+  /// Stop loading the page.
   ///
   void(CEF_CALLBACK* stop_load)(struct _cef_browser_t* self);
 
   ///
-  // Returns the globally unique identifier for this browser. This value is also
-  // used as the tabId for extension APIs.
+  /// Returns the globally unique identifier for this browser. This value is
+  /// also used as the tabId for extension APIs.
   ///
   int(CEF_CALLBACK* get_identifier)(struct _cef_browser_t* self);
 
   ///
-  // Returns true (1) if this object is pointing to the same handle as |that|
-  // object.
+  /// Returns true (1) if this object is pointing to the same handle as |that|
+  /// object.
   ///
   int(CEF_CALLBACK* is_same)(struct _cef_browser_t* self,
                              struct _cef_browser_t* that);
 
   ///
-  // Returns true (1) if the window is a popup window.
+  /// Returns true (1) if the browser is a popup.
   ///
   int(CEF_CALLBACK* is_popup)(struct _cef_browser_t* self);
 
   ///
-  // Returns true (1) if a document has been loaded in the browser.
+  /// Returns true (1) if a document has been loaded in the browser.
   ///
   int(CEF_CALLBACK* has_document)(struct _cef_browser_t* self);
 
   ///
-  // Returns the main (top-level) frame for the browser window.
+  /// Returns the main (top-level) frame for the browser. In the browser process
+  /// this will return a valid object until after
+  /// cef_life_span_handler_t::OnBeforeClose is called. In the renderer process
+  /// this will return NULL if the main frame is hosted in a different renderer
+  /// process (e.g. for cross-origin sub-frames). The main frame object will
+  /// change during cross-origin navigation or re-navigation after renderer
+  /// process termination (due to crashes, etc).
   ///
   struct _cef_frame_t*(CEF_CALLBACK* get_main_frame)(
       struct _cef_browser_t* self);
 
   ///
-  // Returns the focused frame for the browser window.
+  /// Returns the focused frame for the browser.
   ///
   struct _cef_frame_t*(CEF_CALLBACK* get_focused_frame)(
       struct _cef_browser_t* self);
 
   ///
-  // Returns the frame with the specified identifier, or NULL if not found.
+  /// Returns the frame with the specified identifier, or NULL if not found.
   ///
   struct _cef_frame_t*(CEF_CALLBACK* get_frame_byident)(
       struct _cef_browser_t* self,
-      int64 identifier);
+      int64_t identifier);
 
   ///
-  // Returns the frame with the specified name, or NULL if not found.
+  /// Returns the frame with the specified name, or NULL if not found.
   ///
   struct _cef_frame_t*(CEF_CALLBACK* get_frame)(struct _cef_browser_t* self,
                                                 const cef_string_t* name);
 
   ///
-  // Returns the number of frames that currently exist.
+  /// Returns the number of frames that currently exist.
   ///
   size_t(CEF_CALLBACK* get_frame_count)(struct _cef_browser_t* self);
 
   ///
-  // Returns the identifiers of all existing frames.
+  /// Returns the identifiers of all existing frames.
   ///
   void(CEF_CALLBACK* get_frame_identifiers)(struct _cef_browser_t* self,
                                             size_t* identifiersCount,
-                                            int64* identifiers);
+                                            int64_t* identifiers);
 
   ///
-  // Returns the names of all existing frames.
+  /// Returns the names of all existing frames.
   ///
   void(CEF_CALLBACK* get_frame_names)(struct _cef_browser_t* self,
                                       cef_string_list_t names);
 } cef_browser_t;
 
 ///
-// Callback structure for cef_browser_host_t::RunFileDialog. The functions of
-// this structure will be called on the browser process UI thread.
+/// Callback structure for cef_browser_host_t::RunFileDialog. The functions of
+/// this structure will be called on the browser process UI thread.
 ///
 typedef struct _cef_run_file_dialog_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called asynchronously after the file dialog is dismissed.
-  // |selected_accept_filter| is the 0-based index of the value selected from
-  // the accept filters array passed to cef_browser_host_t::RunFileDialog.
-  // |file_paths| will be a single value or a list of values depending on the
-  // dialog mode. If the selection was cancelled |file_paths| will be NULL.
+  /// Called asynchronously after the file dialog is dismissed. |file_paths|
+  /// will be a single value or a list of values depending on the dialog mode.
+  /// If the selection was cancelled |file_paths| will be NULL.
   ///
   void(CEF_CALLBACK* on_file_dialog_dismissed)(
       struct _cef_run_file_dialog_callback_t* self,
-      int selected_accept_filter,
       cef_string_list_t file_paths);
 } cef_run_file_dialog_callback_t;
 
 ///
-// Callback structure for cef_browser_host_t::GetNavigationEntries. The
-// functions of this structure will be called on the browser process UI thread.
+/// Callback structure for cef_browser_host_t::GetNavigationEntries. The
+/// functions of this structure will be called on the browser process UI thread.
 ///
 typedef struct _cef_navigation_entry_visitor_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Method that will be executed. Do not keep a reference to |entry| outside of
-  // this callback. Return true (1) to continue visiting entries or false (0) to
-  // stop. |current| is true (1) if this entry is the currently loaded
-  // navigation entry. |index| is the 0-based index of this entry and |total| is
-  // the total number of entries.
+  /// Method that will be executed. Do not keep a reference to |entry| outside
+  /// of this callback. Return true (1) to continue visiting entries or false
+  /// (0) to stop. |current| is true (1) if this entry is the currently loaded
+  /// navigation entry. |index| is the 0-based index of this entry and |total|
+  /// is the total number of entries.
   ///
   int(CEF_CALLBACK* visit)(struct _cef_navigation_entry_visitor_t* self,
                            struct _cef_navigation_entry_t* entry,
@@ -230,19 +239,19 @@
 } cef_navigation_entry_visitor_t;
 
 ///
-// Callback structure for cef_browser_host_t::PrintToPDF. The functions of this
-// structure will be called on the browser process UI thread.
+/// Callback structure for cef_browser_host_t::PrintToPDF. The functions of this
+/// structure will be called on the browser process UI thread.
 ///
 typedef struct _cef_pdf_print_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Method that will be executed when the PDF printing has completed. |path| is
-  // the output path. |ok| will be true (1) if the printing completed
-  // successfully or false (0) otherwise.
+  /// Method that will be executed when the PDF printing has completed. |path|
+  /// is the output path. |ok| will be true (1) if the printing completed
+  /// successfully or false (0) otherwise.
   ///
   void(CEF_CALLBACK* on_pdf_print_finished)(
       struct _cef_pdf_print_callback_t* self,
@@ -251,20 +260,20 @@
 } cef_pdf_print_callback_t;
 
 ///
-// Callback structure for cef_browser_host_t::DownloadImage. The functions of
-// this structure will be called on the browser process UI thread.
+/// Callback structure for cef_browser_host_t::DownloadImage. The functions of
+/// this structure will be called on the browser process UI thread.
 ///
 typedef struct _cef_download_image_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Method that will be executed when the image download has completed.
-  // |image_url| is the URL that was downloaded and |http_status_code| is the
-  // resulting HTTP status code. |image| is the resulting image, possibly at
-  // multiple scale factors, or NULL if the download failed.
+  /// Method that will be executed when the image download has completed.
+  /// |image_url| is the URL that was downloaded and |http_status_code| is the
+  /// resulting HTTP status code. |image| is the resulting image, possibly at
+  /// multiple scale factors, or NULL if the download failed.
   ///
   void(CEF_CALLBACK* on_download_image_finished)(
       struct _cef_download_image_callback_t* self,
@@ -274,114 +283,139 @@
 } cef_download_image_callback_t;
 
 ///
-// Structure used to represent the browser process aspects of a browser window.
-// The functions of this structure can only be called in the browser process.
-// They may be called on any thread in that process unless otherwise indicated
-// in the comments.
+/// Structure used to represent the browser process aspects of a browser. The
+/// functions of this structure can only be called in the browser process. They
+/// may be called on any thread in that process unless otherwise indicated in
+/// the comments.
 ///
 typedef struct _cef_browser_host_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the hosted browser object.
+  /// Returns the hosted browser object.
   ///
   struct _cef_browser_t*(CEF_CALLBACK* get_browser)(
       struct _cef_browser_host_t* self);
 
   ///
-  // Request that the browser close. The JavaScript 'onbeforeunload' event will
-  // be fired. If |force_close| is false (0) the event handler, if any, will be
-  // allowed to prompt the user and the user can optionally cancel the close. If
-  // |force_close| is true (1) the prompt will not be displayed and the close
-  // will proceed. Results in a call to cef_life_span_handler_t::do_close() if
-  // the event handler allows the close or if |force_close| is true (1). See
-  // cef_life_span_handler_t::do_close() documentation for additional usage
-  // information.
+  /// Request that the browser close. The JavaScript 'onbeforeunload' event will
+  /// be fired. If |force_close| is false (0) the event handler, if any, will be
+  /// allowed to prompt the user and the user can optionally cancel the close.
+  /// If |force_close| is true (1) the prompt will not be displayed and the
+  /// close will proceed. Results in a call to
+  /// cef_life_span_handler_t::do_close() if the event handler allows the close
+  /// or if |force_close| is true (1). See cef_life_span_handler_t::do_close()
+  /// documentation for additional usage information.
   ///
   void(CEF_CALLBACK* close_browser)(struct _cef_browser_host_t* self,
                                     int force_close);
 
   ///
-  // Helper for closing a browser. Call this function from the top-level window
-  // close handler. Internally this calls CloseBrowser(false (0)) if the close
-  // has not yet been initiated. This function returns false (0) while the close
-  // is pending and true (1) after the close has completed. See close_browser()
-  // and cef_life_span_handler_t::do_close() documentation for additional usage
-  // information. This function must be called on the browser process UI thread.
+  /// Helper for closing a browser. Call this function from the top-level window
+  /// close handler (if any). Internally this calls CloseBrowser(false (0)) if
+  /// the close has not yet been initiated. This function returns false (0)
+  /// while the close is pending and true (1) after the close has completed. See
+  /// close_browser() and cef_life_span_handler_t::do_close() documentation for
+  /// additional usage information. This function must be called on the browser
+  /// process UI thread.
   ///
   int(CEF_CALLBACK* try_close_browser)(struct _cef_browser_host_t* self);
 
   ///
-  // Set whether the browser is focused.
+  /// Set whether the browser is focused.
   ///
   void(CEF_CALLBACK* set_focus)(struct _cef_browser_host_t* self, int focus);
 
   ///
-  // Retrieve the window handle for this browser. If this browser is wrapped in
-  // a cef_browser_view_t this function should be called on the browser process
-  // UI thread and it will return the handle for the top-level native window.
+  /// Retrieve the window handle (if any) for this browser. If this browser is
+  /// wrapped in a cef_browser_view_t this function should be called on the
+  /// browser process UI thread and it will return the handle for the top-level
+  /// native window.
   ///
   cef_window_handle_t(CEF_CALLBACK* get_window_handle)(
       struct _cef_browser_host_t* self);
 
   ///
-  // Retrieve the window handle of the browser that opened this browser. Will
-  // return NULL for non-popup windows or if this browser is wrapped in a
-  // cef_browser_view_t. This function can be used in combination with custom
-  // handling of modal windows.
+  /// Retrieve the window handle (if any) of the browser that opened this
+  /// browser. Will return NULL for non-popup browsers or if this browser is
+  /// wrapped in a cef_browser_view_t. This function can be used in combination
+  /// with custom handling of modal windows.
   ///
   cef_window_handle_t(CEF_CALLBACK* get_opener_window_handle)(
       struct _cef_browser_host_t* self);
 
   ///
-  // Returns true (1) if this browser is wrapped in a cef_browser_view_t.
+  /// Returns true (1) if this browser is wrapped in a cef_browser_view_t.
   ///
   int(CEF_CALLBACK* has_view)(struct _cef_browser_host_t* self);
 
   ///
-  // Returns the client for this browser.
+  /// Returns the client for this browser.
   ///
   struct _cef_client_t*(CEF_CALLBACK* get_client)(
       struct _cef_browser_host_t* self);
 
   ///
-  // Returns the request context for this browser.
+  /// Returns the request context for this browser.
   ///
   struct _cef_request_context_t*(CEF_CALLBACK* get_request_context)(
       struct _cef_browser_host_t* self);
 
   ///
-  // Get the current zoom level. The default zoom level is 0.0. This function
-  // can only be called on the UI thread.
+  /// Returns true (1) if this browser can execute the specified zoom command.
+  /// This function can only be called on the UI thread.
+  ///
+  int(CEF_CALLBACK* can_zoom)(struct _cef_browser_host_t* self,
+                              cef_zoom_command_t command);
+
+  ///
+  /// Execute a zoom command in this browser. If called on the UI thread the
+  /// change will be applied immediately. Otherwise, the change will be applied
+  /// asynchronously on the UI thread.
+  ///
+  void(CEF_CALLBACK* zoom)(struct _cef_browser_host_t* self,
+                           cef_zoom_command_t command);
+
+  ///
+  /// Get the default zoom level. This value will be 0.0 by default but can be
+  /// configured with the Chrome runtime. This function can only be called on
+  /// the UI thread.
+  ///
+  double(CEF_CALLBACK* get_default_zoom_level)(
+      struct _cef_browser_host_t* self);
+
+  ///
+  /// Get the current zoom level. This function can only be called on the UI
+  /// thread.
   ///
   double(CEF_CALLBACK* get_zoom_level)(struct _cef_browser_host_t* self);
 
   ///
-  // Change the zoom level to the specified value. Specify 0.0 to reset the zoom
-  // level. If called on the UI thread the change will be applied immediately.
-  // Otherwise, the change will be applied asynchronously on the UI thread.
+  /// Change the zoom level to the specified value. Specify 0.0 to reset the
+  /// zoom level to the default. If called on the UI thread the change will be
+  /// applied immediately. Otherwise, the change will be applied asynchronously
+  /// on the UI thread.
   ///
   void(CEF_CALLBACK* set_zoom_level)(struct _cef_browser_host_t* self,
                                      double zoomLevel);
 
   ///
-  // Call to run a file chooser dialog. Only a single file chooser dialog may be
-  // pending at any given time. |mode| represents the type of dialog to display.
-  // |title| to the title to be used for the dialog and may be NULL to show the
-  // default title ("Open" or "Save" depending on the mode). |default_file_path|
-  // is the path with optional directory and/or file name component that will be
-  // initially selected in the dialog. |accept_filters| are used to restrict the
-  // selectable file types and may any combination of (a) valid lower-cased MIME
-  // types (e.g. "text/*" or "image/*"), (b) individual file extensions (e.g.
-  // ".txt" or ".png"), or (c) combined description and file extension delimited
-  // using "|" and ";" (e.g. "Image Types|.png;.gif;.jpg").
-  // |selected_accept_filter| is the 0-based index of the filter that will be
-  // selected by default. |callback| will be executed after the dialog is
-  // dismissed or immediately if another dialog is already pending. The dialog
-  // will be initiated asynchronously on the UI thread.
+  /// Call to run a file chooser dialog. Only a single file chooser dialog may
+  /// be pending at any given time. |mode| represents the type of dialog to
+  /// display. |title| to the title to be used for the dialog and may be NULL to
+  /// show the default title ("Open" or "Save" depending on the mode).
+  /// |default_file_path| is the path with optional directory and/or file name
+  /// component that will be initially selected in the dialog. |accept_filters|
+  /// are used to restrict the selectable file types and may any combination of
+  /// (a) valid lower-cased MIME types (e.g. "text/*" or "image/*"), (b)
+  /// individual file extensions (e.g. ".txt" or ".png"), or (c) combined
+  /// description and file extension delimited using "|" and ";" (e.g. "Image
+  /// Types|.png;.gif;.jpg"). |callback| will be executed after the dialog is
+  /// dismissed or immediately if another dialog is already pending. The dialog
+  /// will be initiated asynchronously on the UI thread.
   ///
   void(CEF_CALLBACK* run_file_dialog)(
       struct _cef_browser_host_t* self,
@@ -389,45 +423,44 @@
       const cef_string_t* title,
       const cef_string_t* default_file_path,
       cef_string_list_t accept_filters,
-      int selected_accept_filter,
       struct _cef_run_file_dialog_callback_t* callback);
 
   ///
-  // Download the file at |url| using cef_download_handler_t.
+  /// Download the file at |url| using cef_download_handler_t.
   ///
   void(CEF_CALLBACK* start_download)(struct _cef_browser_host_t* self,
                                      const cef_string_t* url);
 
   ///
-  // Download |image_url| and execute |callback| on completion with the images
-  // received from the renderer. If |is_favicon| is true (1) then cookies are
-  // not sent and not accepted during download. Images with density independent
-  // pixel (DIP) sizes larger than |max_image_size| are filtered out from the
-  // image results. Versions of the image at different scale factors may be
-  // downloaded up to the maximum scale factor supported by the system. If there
-  // are no image results <= |max_image_size| then the smallest image is resized
-  // to |max_image_size| and is the only result. A |max_image_size| of 0 means
-  // unlimited. If |bypass_cache| is true (1) then |image_url| is requested from
-  // the server even if it is present in the browser cache.
+  /// Download |image_url| and execute |callback| on completion with the images
+  /// received from the renderer. If |is_favicon| is true (1) then cookies are
+  /// not sent and not accepted during download. Images with density independent
+  /// pixel (DIP) sizes larger than |max_image_size| are filtered out from the
+  /// image results. Versions of the image at different scale factors may be
+  /// downloaded up to the maximum scale factor supported by the system. If
+  /// there are no image results <= |max_image_size| then the smallest image is
+  /// resized to |max_image_size| and is the only result. A |max_image_size| of
+  /// 0 means unlimited. If |bypass_cache| is true (1) then |image_url| is
+  /// requested from the server even if it is present in the browser cache.
   ///
   void(CEF_CALLBACK* download_image)(
       struct _cef_browser_host_t* self,
       const cef_string_t* image_url,
       int is_favicon,
-      uint32 max_image_size,
+      uint32_t max_image_size,
       int bypass_cache,
       struct _cef_download_image_callback_t* callback);
 
   ///
-  // Print the current browser contents.
+  /// Print the current browser contents.
   ///
   void(CEF_CALLBACK* print)(struct _cef_browser_host_t* self);
 
   ///
-  // Print the current browser contents to the PDF file specified by |path| and
-  // execute |callback| on completion. The caller is responsible for deleting
-  // |path| when done. For PDF printing to work on Linux you must implement the
-  // cef_print_handler_t::GetPdfPaperSize function.
+  /// Print the current browser contents to the PDF file specified by |path| and
+  /// execute |callback| on completion. The caller is responsible for deleting
+  /// |path| when done. For PDF printing to work on Linux you must implement the
+  /// cef_print_handler_t::GetPdfPaperSize function.
   ///
   void(CEF_CALLBACK* print_to_pdf)(
       struct _cef_browser_host_t* self,
@@ -436,37 +469,34 @@
       struct _cef_pdf_print_callback_t* callback);
 
   ///
-  // Search for |searchText|. |identifier| must be a unique ID and these IDs
-  // must strictly increase so that newer requests always have greater IDs than
-  // older requests. If |identifier| is zero or less than the previous ID value
-  // then it will be automatically assigned a new valid ID. |forward| indicates
-  // whether to search forward or backward within the page. |matchCase|
-  // indicates whether the search should be case-sensitive. |findNext| indicates
-  // whether this is the first request or a follow-up. The cef_find_handler_t
-  // instance, if any, returned via cef_client_t::GetFindHandler will be called
-  // to report find results.
+  /// Search for |searchText|. |forward| indicates whether to search forward or
+  /// backward within the page. |matchCase| indicates whether the search should
+  /// be case-sensitive. |findNext| indicates whether this is the first request
+  /// or a follow-up. The search will be restarted if |searchText| or
+  /// |matchCase| change. The search will be stopped if |searchText| is NULL.
+  /// The cef_find_handler_t instance, if any, returned via
+  /// cef_client_t::GetFindHandler will be called to report find results.
   ///
   void(CEF_CALLBACK* find)(struct _cef_browser_host_t* self,
-                           int identifier,
                            const cef_string_t* searchText,
                            int forward,
                            int matchCase,
                            int findNext);
 
   ///
-  // Cancel all searches that are currently going on.
+  /// Cancel all searches that are currently going on.
   ///
   void(CEF_CALLBACK* stop_finding)(struct _cef_browser_host_t* self,
                                    int clearSelection);
 
   ///
-  // Open developer tools (DevTools) in its own browser. The DevTools browser
-  // will remain associated with this browser. If the DevTools browser is
-  // already open then it will be focused, in which case the |windowInfo|,
-  // |client| and |settings| parameters will be ignored. If |inspect_element_at|
-  // is non-NULL then the element at the specified (x,y) location will be
-  // inspected. The |windowInfo| parameter will be ignored if this browser is
-  // wrapped in a cef_browser_view_t.
+  /// Open developer tools (DevTools) in its own browser. The DevTools browser
+  /// will remain associated with this browser. If the DevTools browser is
+  /// already open then it will be focused, in which case the |windowInfo|,
+  /// |client| and |settings| parameters will be ignored. If
+  /// |inspect_element_at| is non-NULL then the element at the specified (x,y)
+  /// location will be inspected. The |windowInfo| parameter will be ignored if
+  /// this browser is wrapped in a cef_browser_view_t.
   ///
   void(CEF_CALLBACK* show_dev_tools)(
       struct _cef_browser_host_t* self,
@@ -476,64 +506,65 @@
       const cef_point_t* inspect_element_at);
 
   ///
-  // Explicitly close the associated DevTools browser, if any.
+  /// Explicitly close the associated DevTools browser, if any.
   ///
   void(CEF_CALLBACK* close_dev_tools)(struct _cef_browser_host_t* self);
 
   ///
-  // Returns true (1) if this browser currently has an associated DevTools
-  // browser. Must be called on the browser process UI thread.
+  /// Returns true (1) if this browser currently has an associated DevTools
+  /// browser. Must be called on the browser process UI thread.
   ///
   int(CEF_CALLBACK* has_dev_tools)(struct _cef_browser_host_t* self);
 
   ///
-  // Send a function call message over the DevTools protocol. |message| must be
-  // a UTF8-encoded JSON dictionary that contains "id" (int), "function"
-  // (string) and "params" (dictionary, optional) values. See the DevTools
-  // protocol documentation at https://chromedevtools.github.io/devtools-
-  // protocol/ for details of supported functions and the expected "params"
-  // dictionary contents. |message| will be copied if necessary. This function
-  // will return true (1) if called on the UI thread and the message was
-  // successfully submitted for validation, otherwise false (0). Validation will
-  // be applied asynchronously and any messages that fail due to formatting
-  // errors or missing parameters may be discarded without notification. Prefer
-  // ExecuteDevToolsMethod if a more structured approach to message formatting
-  // is desired.
-  //
-  // Every valid function call will result in an asynchronous function result or
-  // error message that references the sent message "id". Event messages are
-  // received while notifications are enabled (for example, between function
-  // calls for "Page.enable" and "Page.disable"). All received messages will be
-  // delivered to the observer(s) registered with AddDevToolsMessageObserver.
-  // See cef_dev_tools_message_observer_t::OnDevToolsMessage documentation for
-  // details of received message contents.
-  //
-  // Usage of the SendDevToolsMessage, ExecuteDevToolsMethod and
-  // AddDevToolsMessageObserver functions does not require an active DevTools
-  // front-end or remote-debugging session. Other active DevTools sessions will
-  // continue to function independently. However, any modification of global
-  // browser state by one session may not be reflected in the UI of other
-  // sessions.
-  //
-  // Communication with the DevTools front-end (when displayed) can be logged
-  // for development purposes by passing the `--devtools-protocol-log-
-  // file=<path>` command-line flag.
+  /// Send a function call message over the DevTools protocol. |message| must be
+  /// a UTF8-encoded JSON dictionary that contains "id" (int), "function"
+  /// (string) and "params" (dictionary, optional) values. See the DevTools
+  /// protocol documentation at https://chromedevtools.github.io/devtools-
+  /// protocol/ for details of supported functions and the expected "params"
+  /// dictionary contents. |message| will be copied if necessary. This function
+  /// will return true (1) if called on the UI thread and the message was
+  /// successfully submitted for validation, otherwise false (0). Validation
+  /// will be applied asynchronously and any messages that fail due to
+  /// formatting errors or missing parameters may be discarded without
+  /// notification. Prefer ExecuteDevToolsMethod if a more structured approach
+  /// to message formatting is desired.
+  ///
+  /// Every valid function call will result in an asynchronous function result
+  /// or error message that references the sent message "id". Event messages are
+  /// received while notifications are enabled (for example, between function
+  /// calls for "Page.enable" and "Page.disable"). All received messages will be
+  /// delivered to the observer(s) registered with AddDevToolsMessageObserver.
+  /// See cef_dev_tools_message_observer_t::OnDevToolsMessage documentation for
+  /// details of received message contents.
+  ///
+  /// Usage of the SendDevToolsMessage, ExecuteDevToolsMethod and
+  /// AddDevToolsMessageObserver functions does not require an active DevTools
+  /// front-end or remote-debugging session. Other active DevTools sessions will
+  /// continue to function independently. However, any modification of global
+  /// browser state by one session may not be reflected in the UI of other
+  /// sessions.
+  ///
+  /// Communication with the DevTools front-end (when displayed) can be logged
+  /// for development purposes by passing the `--devtools-protocol-log-
+  /// file=<path>` command-line flag.
   ///
   int(CEF_CALLBACK* send_dev_tools_message)(struct _cef_browser_host_t* self,
                                             const void* message,
                                             size_t message_size);
 
   ///
-  // Execute a function call over the DevTools protocol. This is a more
-  // structured version of SendDevToolsMessage. |message_id| is an incremental
-  // number that uniquely identifies the message (pass 0 to have the next number
-  // assigned automatically based on previous values). |function| is the
-  // function name. |params| are the function parameters, which may be NULL. See
-  // the DevTools protocol documentation (linked above) for details of supported
-  // functions and the expected |params| dictionary contents. This function will
-  // return the assigned message ID if called on the UI thread and the message
-  // was successfully submitted for validation, otherwise 0. See the
-  // SendDevToolsMessage documentation for additional usage information.
+  /// Execute a function call over the DevTools protocol. This is a more
+  /// structured version of SendDevToolsMessage. |message_id| is an incremental
+  /// number that uniquely identifies the message (pass 0 to have the next
+  /// number assigned automatically based on previous values). |function| is the
+  /// function name. |params| are the function parameters, which may be NULL.
+  /// See the DevTools protocol documentation (linked above) for details of
+  /// supported functions and the expected |params| dictionary contents. This
+  /// function will return the assigned message ID if called on the UI thread
+  /// and the message was successfully submitted for validation, otherwise 0.
+  /// See the SendDevToolsMessage documentation for additional usage
+  /// information.
   ///
   int(CEF_CALLBACK* execute_dev_tools_method)(
       struct _cef_browser_host_t* self,
@@ -542,20 +573,20 @@
       struct _cef_dictionary_value_t* params);
 
   ///
-  // Add an observer for DevTools protocol messages (function results and
-  // events). The observer will remain registered until the returned
-  // Registration object is destroyed. See the SendDevToolsMessage documentation
-  // for additional usage information.
+  /// Add an observer for DevTools protocol messages (function results and
+  /// events). The observer will remain registered until the returned
+  /// Registration object is destroyed. See the SendDevToolsMessage
+  /// documentation for additional usage information.
   ///
   struct _cef_registration_t*(CEF_CALLBACK* add_dev_tools_message_observer)(
       struct _cef_browser_host_t* self,
       struct _cef_dev_tools_message_observer_t* observer);
 
   ///
-  // Retrieve a snapshot of current navigation entries as values sent to the
-  // specified visitor. If |current_only| is true (1) only the current
-  // navigation entry will be sent, otherwise all navigation entries will be
-  // sent.
+  /// Retrieve a snapshot of current navigation entries as values sent to the
+  /// specified visitor. If |current_only| is true (1) only the current
+  /// navigation entry will be sent, otherwise all navigation entries will be
+  /// sent.
   ///
   void(CEF_CALLBACK* get_navigation_entries)(
       struct _cef_browser_host_t* self,
@@ -563,184 +594,166 @@
       int current_only);
 
   ///
-  // Set whether mouse cursor change is disabled.
-  ///
-  void(CEF_CALLBACK* set_mouse_cursor_change_disabled)(
-      struct _cef_browser_host_t* self,
-      int disabled);
-
-  ///
-  // Returns true (1) if mouse cursor change is disabled.
-  ///
-  int(CEF_CALLBACK* is_mouse_cursor_change_disabled)(
-      struct _cef_browser_host_t* self);
-
-  ///
-  // If a misspelled word is currently selected in an editable node calling this
-  // function will replace it with the specified |word|.
+  /// If a misspelled word is currently selected in an editable node calling
+  /// this function will replace it with the specified |word|.
   ///
   void(CEF_CALLBACK* replace_misspelling)(struct _cef_browser_host_t* self,
                                           const cef_string_t* word);
 
   ///
-  // Add the specified |word| to the spelling dictionary.
+  /// Add the specified |word| to the spelling dictionary.
   ///
   void(CEF_CALLBACK* add_word_to_dictionary)(struct _cef_browser_host_t* self,
                                              const cef_string_t* word);
 
   ///
-  // Returns true (1) if window rendering is disabled.
+  /// Returns true (1) if window rendering is disabled.
   ///
   int(CEF_CALLBACK* is_window_rendering_disabled)(
       struct _cef_browser_host_t* self);
 
   ///
-  // Notify the browser that the widget has been resized. The browser will first
-  // call cef_render_handler_t::GetViewRect to get the new size and then call
-  // cef_render_handler_t::OnPaint asynchronously with the updated regions. This
-  // function is only used when window rendering is disabled.
+  /// Notify the browser that the widget has been resized. The browser will
+  /// first call cef_render_handler_t::GetViewRect to get the new size and then
+  /// call cef_render_handler_t::OnPaint asynchronously with the updated
+  /// regions. This function is only used when window rendering is disabled.
   ///
   void(CEF_CALLBACK* was_resized)(struct _cef_browser_host_t* self);
 
   ///
-  // Notify the browser that it has been hidden or shown. Layouting and
-  // cef_render_handler_t::OnPaint notification will stop when the browser is
-  // hidden. This function is only used when window rendering is disabled.
+  /// Notify the browser that it has been hidden or shown. Layouting and
+  /// cef_render_handler_t::OnPaint notification will stop when the browser is
+  /// hidden. This function is only used when window rendering is disabled.
   ///
   void(CEF_CALLBACK* was_hidden)(struct _cef_browser_host_t* self, int hidden);
 
   ///
-  // Send a notification to the browser that the screen info has changed. The
-  // browser will then call cef_render_handler_t::GetScreenInfo to update the
-  // screen information with the new values. This simulates moving the webview
-  // window from one display to another, or changing the properties of the
-  // current display. This function is only used when window rendering is
-  // disabled.
+  /// Send a notification to the browser that the screen info has changed. The
+  /// browser will then call cef_render_handler_t::GetScreenInfo to update the
+  /// screen information with the new values. This simulates moving the webview
+  /// window from one display to another, or changing the properties of the
+  /// current display. This function is only used when window rendering is
+  /// disabled.
   ///
   void(CEF_CALLBACK* notify_screen_info_changed)(
       struct _cef_browser_host_t* self);
 
   ///
-  // Invalidate the view. The browser will call cef_render_handler_t::OnPaint
-  // asynchronously. This function is only used when window rendering is
-  // disabled.
+  /// Invalidate the view. The browser will call cef_render_handler_t::OnPaint
+  /// asynchronously. This function is only used when window rendering is
+  /// disabled.
   ///
   void(CEF_CALLBACK* invalidate)(struct _cef_browser_host_t* self,
                                  cef_paint_element_type_t type);
 
   ///
-  // Issue a BeginFrame request to Chromium.  Only valid when
-  // cef_window_tInfo::external_begin_frame_enabled is set to true (1).
+  /// Issue a BeginFrame request to Chromium.  Only valid when
+  /// cef_window_tInfo::external_begin_frame_enabled is set to true (1).
   ///
   void(CEF_CALLBACK* send_external_begin_frame)(
       struct _cef_browser_host_t* self);
 
   ///
-  // Send a key event to the browser.
+  /// Send a key event to the browser.
   ///
   void(CEF_CALLBACK* send_key_event)(struct _cef_browser_host_t* self,
-                                     const struct _cef_key_event_t* event);
+                                     const cef_key_event_t* event);
 
   ///
-  // Send a mouse click event to the browser. The |x| and |y| coordinates are
-  // relative to the upper-left corner of the view.
+  /// Send a mouse click event to the browser. The |x| and |y| coordinates are
+  /// relative to the upper-left corner of the view.
   ///
-  void(CEF_CALLBACK* send_mouse_click_event)(
-      struct _cef_browser_host_t* self,
-      const struct _cef_mouse_event_t* event,
-      cef_mouse_button_type_t type,
-      int mouseUp,
-      int clickCount);
+  void(CEF_CALLBACK* send_mouse_click_event)(struct _cef_browser_host_t* self,
+                                             const cef_mouse_event_t* event,
+                                             cef_mouse_button_type_t type,
+                                             int mouseUp,
+                                             int clickCount);
 
   ///
-  // Send a mouse move event to the browser. The |x| and |y| coordinates are
-  // relative to the upper-left corner of the view.
+  /// Send a mouse move event to the browser. The |x| and |y| coordinates are
+  /// relative to the upper-left corner of the view.
   ///
-  void(CEF_CALLBACK* send_mouse_move_event)(
-      struct _cef_browser_host_t* self,
-      const struct _cef_mouse_event_t* event,
-      int mouseLeave);
+  void(CEF_CALLBACK* send_mouse_move_event)(struct _cef_browser_host_t* self,
+                                            const cef_mouse_event_t* event,
+                                            int mouseLeave);
 
   ///
-  // Send a mouse wheel event to the browser. The |x| and |y| coordinates are
-  // relative to the upper-left corner of the view. The |deltaX| and |deltaY|
-  // values represent the movement delta in the X and Y directions respectively.
-  // In order to scroll inside select popups with window rendering disabled
-  // cef_render_handler_t::GetScreenPoint should be implemented properly.
+  /// Send a mouse wheel event to the browser. The |x| and |y| coordinates are
+  /// relative to the upper-left corner of the view. The |deltaX| and |deltaY|
+  /// values represent the movement delta in the X and Y directions
+  /// respectively. In order to scroll inside select popups with window
+  /// rendering disabled cef_render_handler_t::GetScreenPoint should be
+  /// implemented properly.
   ///
-  void(CEF_CALLBACK* send_mouse_wheel_event)(
-      struct _cef_browser_host_t* self,
-      const struct _cef_mouse_event_t* event,
-      int deltaX,
-      int deltaY);
+  void(CEF_CALLBACK* send_mouse_wheel_event)(struct _cef_browser_host_t* self,
+                                             const cef_mouse_event_t* event,
+                                             int deltaX,
+                                             int deltaY);
 
   ///
-  // Send a touch event to the browser for a windowless browser.
+  /// Send a touch event to the browser for a windowless browser.
   ///
   void(CEF_CALLBACK* send_touch_event)(struct _cef_browser_host_t* self,
-                                       const struct _cef_touch_event_t* event);
+                                       const cef_touch_event_t* event);
 
   ///
-  // Send a focus event to the browser.
-  ///
-  void(CEF_CALLBACK* send_focus_event)(struct _cef_browser_host_t* self,
-                                       int setFocus);
-
-  ///
-  // Send a capture lost event to the browser.
+  /// Send a capture lost event to the browser.
   ///
   void(CEF_CALLBACK* send_capture_lost_event)(struct _cef_browser_host_t* self);
 
   ///
-  // Notify the browser that the window hosting it is about to be moved or
-  // resized. This function is only used on Windows and Linux.
+  /// Notify the browser that the window hosting it is about to be moved or
+  /// resized. This function is only used on Windows and Linux.
   ///
   void(CEF_CALLBACK* notify_move_or_resize_started)(
       struct _cef_browser_host_t* self);
 
   ///
-  // Returns the maximum rate in frames per second (fps) that
-  // cef_render_handler_t:: OnPaint will be called for a windowless browser. The
-  // actual fps may be lower if the browser cannot generate frames at the
-  // requested rate. The minimum value is 1 and the maximum value is 60 (default
-  // 30). This function can only be called on the UI thread.
+  /// Returns the maximum rate in frames per second (fps) that
+  /// cef_render_handler_t::OnPaint will be called for a windowless browser. The
+  /// actual fps may be lower if the browser cannot generate frames at the
+  /// requested rate. The minimum value is 1 and the maximum value is 60
+  /// (default 30). This function can only be called on the UI thread.
   ///
   int(CEF_CALLBACK* get_windowless_frame_rate)(
       struct _cef_browser_host_t* self);
 
   ///
-  // Set the maximum rate in frames per second (fps) that cef_render_handler_t::
-  // OnPaint will be called for a windowless browser. The actual fps may be
-  // lower if the browser cannot generate frames at the requested rate. The
-  // minimum value is 1 and the maximum value is 60 (default 30). Can also be
-  // set at browser creation via cef_browser_tSettings.windowless_frame_rate.
+  /// Set the maximum rate in frames per second (fps) that
+  /// cef_render_handler_t:: OnPaint will be called for a windowless browser.
+  /// The actual fps may be lower if the browser cannot generate frames at the
+  /// requested rate. The minimum value is 1 and the maximum value is 60
+  /// (default 30). Can also be set at browser creation via
+  /// cef_browser_tSettings.windowless_frame_rate.
   ///
   void(CEF_CALLBACK* set_windowless_frame_rate)(
       struct _cef_browser_host_t* self,
       int frame_rate);
 
   ///
-  // Begins a new composition or updates the existing composition. Blink has a
-  // special node (a composition node) that allows the input function to change
-  // text without affecting other DOM nodes. |text| is the optional text that
-  // will be inserted into the composition node. |underlines| is an optional set
-  // of ranges that will be underlined in the resulting text.
-  // |replacement_range| is an optional range of the existing text that will be
-  // replaced. |selection_range| is an optional range of the resulting text that
-  // will be selected after insertion or replacement. The |replacement_range|
-  // value is only used on OS X.
-  //
-  // This function may be called multiple times as the composition changes. When
-  // the client is done making changes the composition should either be canceled
-  // or completed. To cancel the composition call ImeCancelComposition. To
-  // complete the composition call either ImeCommitText or
-  // ImeFinishComposingText. Completion is usually signaled when:
-  //   A. The client receives a WM_IME_COMPOSITION message with a GCS_RESULTSTR
-  //      flag (on Windows), or;
-  //   B. The client receives a "commit" signal of GtkIMContext (on Linux), or;
-  //   C. insertText of NSTextInput is called (on Mac).
-  //
-  // This function is only used when window rendering is disabled.
+  /// Begins a new composition or updates the existing composition. Blink has a
+  /// special node (a composition node) that allows the input function to change
+  /// text without affecting other DOM nodes. |text| is the optional text that
+  /// will be inserted into the composition node. |underlines| is an optional
+  /// set of ranges that will be underlined in the resulting text.
+  /// |replacement_range| is an optional range of the existing text that will be
+  /// replaced. |selection_range| is an optional range of the resulting text
+  /// that will be selected after insertion or replacement. The
+  /// |replacement_range| value is only used on OS X.
+  ///
+  /// This function may be called multiple times as the composition changes.
+  /// When the client is done making changes the composition should either be
+  /// canceled or completed. To cancel the composition call
+  /// ImeCancelComposition. To complete the composition call either
+  /// ImeCommitText or ImeFinishComposingText. Completion is usually signaled
+  /// when:
+  ///
+  /// 1. The client receives a WM_IME_COMPOSITION message with a GCS_RESULTSTR
+  ///    flag (on Windows), or;
+  /// 2. The client receives a "commit" signal of GtkIMContext (on Linux), or;
+  /// 3. insertText of NSTextInput is called (on Mac).
+  ///
+  /// This function is only used when window rendering is disabled.
   ///
   void(CEF_CALLBACK* ime_set_composition)(
       struct _cef_browser_host_t* self,
@@ -751,13 +764,13 @@
       const cef_range_t* selection_range);
 
   ///
-  // Completes the existing composition by optionally inserting the specified
-  // |text| into the composition node. |replacement_range| is an optional range
-  // of the existing text that will be replaced. |relative_cursor_pos| is where
-  // the cursor will be positioned relative to the current cursor position. See
-  // comments on ImeSetComposition for usage. The |replacement_range| and
-  // |relative_cursor_pos| values are only used on OS X. This function is only
-  // used when window rendering is disabled.
+  /// Completes the existing composition by optionally inserting the specified
+  /// |text| into the composition node. |replacement_range| is an optional range
+  /// of the existing text that will be replaced. |relative_cursor_pos| is where
+  /// the cursor will be positioned relative to the current cursor position. See
+  /// comments on ImeSetComposition for usage. The |replacement_range| and
+  /// |relative_cursor_pos| values are only used on OS X. This function is only
+  /// used when window rendering is disabled.
   ///
   void(CEF_CALLBACK* ime_commit_text)(struct _cef_browser_host_t* self,
                                       const cef_string_t* text,
@@ -765,73 +778,73 @@
                                       int relative_cursor_pos);
 
   ///
-  // Completes the existing composition by applying the current composition node
-  // contents. If |keep_selection| is false (0) the current selection, if any,
-  // will be discarded. See comments on ImeSetComposition for usage. This
-  // function is only used when window rendering is disabled.
+  /// Completes the existing composition by applying the current composition
+  /// node contents. If |keep_selection| is false (0) the current selection, if
+  /// any, will be discarded. See comments on ImeSetComposition for usage. This
+  /// function is only used when window rendering is disabled.
   ///
   void(CEF_CALLBACK* ime_finish_composing_text)(
       struct _cef_browser_host_t* self,
       int keep_selection);
 
   ///
-  // Cancels the existing composition and discards the composition node contents
-  // without applying them. See comments on ImeSetComposition for usage. This
-  // function is only used when window rendering is disabled.
+  /// Cancels the existing composition and discards the composition node
+  /// contents without applying them. See comments on ImeSetComposition for
+  /// usage. This function is only used when window rendering is disabled.
   ///
   void(CEF_CALLBACK* ime_cancel_composition)(struct _cef_browser_host_t* self);
 
   ///
-  // Call this function when the user drags the mouse into the web view (before
-  // calling DragTargetDragOver/DragTargetLeave/DragTargetDrop). |drag_data|
-  // should not contain file contents as this type of data is not allowed to be
-  // dragged into the web view. File contents can be removed using
-  // cef_drag_data_t::ResetFileContents (for example, if |drag_data| comes from
-  // cef_render_handler_t::StartDragging). This function is only used when
-  // window rendering is disabled.
+  /// Call this function when the user drags the mouse into the web view (before
+  /// calling DragTargetDragOver/DragTargetLeave/DragTargetDrop). |drag_data|
+  /// should not contain file contents as this type of data is not allowed to be
+  /// dragged into the web view. File contents can be removed using
+  /// cef_drag_data_t::ResetFileContents (for example, if |drag_data| comes from
+  /// cef_render_handler_t::StartDragging). This function is only used when
+  /// window rendering is disabled.
   ///
   void(CEF_CALLBACK* drag_target_drag_enter)(
       struct _cef_browser_host_t* self,
       struct _cef_drag_data_t* drag_data,
-      const struct _cef_mouse_event_t* event,
+      const cef_mouse_event_t* event,
       cef_drag_operations_mask_t allowed_ops);
 
   ///
-  // Call this function each time the mouse is moved across the web view during
-  // a drag operation (after calling DragTargetDragEnter and before calling
-  // DragTargetDragLeave/DragTargetDrop). This function is only used when window
-  // rendering is disabled.
+  /// Call this function each time the mouse is moved across the web view during
+  /// a drag operation (after calling DragTargetDragEnter and before calling
+  /// DragTargetDragLeave/DragTargetDrop). This function is only used when
+  /// window rendering is disabled.
   ///
   void(CEF_CALLBACK* drag_target_drag_over)(
       struct _cef_browser_host_t* self,
-      const struct _cef_mouse_event_t* event,
+      const cef_mouse_event_t* event,
       cef_drag_operations_mask_t allowed_ops);
 
   ///
-  // Call this function when the user drags the mouse out of the web view (after
-  // calling DragTargetDragEnter). This function is only used when window
-  // rendering is disabled.
+  /// Call this function when the user drags the mouse out of the web view
+  /// (after calling DragTargetDragEnter). This function is only used when
+  /// window rendering is disabled.
   ///
   void(CEF_CALLBACK* drag_target_drag_leave)(struct _cef_browser_host_t* self);
 
   ///
-  // Call this function when the user completes the drag operation by dropping
-  // the object onto the web view (after calling DragTargetDragEnter). The
-  // object being dropped is |drag_data|, given as an argument to the previous
-  // DragTargetDragEnter call. This function is only used when window rendering
-  // is disabled.
+  /// Call this function when the user completes the drag operation by dropping
+  /// the object onto the web view (after calling DragTargetDragEnter). The
+  /// object being dropped is |drag_data|, given as an argument to the previous
+  /// DragTargetDragEnter call. This function is only used when window rendering
+  /// is disabled.
   ///
   void(CEF_CALLBACK* drag_target_drop)(struct _cef_browser_host_t* self,
-                                       const struct _cef_mouse_event_t* event);
+                                       const cef_mouse_event_t* event);
 
   ///
-  // Call this function when the drag operation started by a
-  // cef_render_handler_t::StartDragging call has ended either in a drop or by
-  // being cancelled. |x| and |y| are mouse coordinates relative to the upper-
-  // left corner of the view. If the web view is both the drag source and the
-  // drag target then all DragTarget* functions should be called before
-  // DragSource* mthods. This function is only used when window rendering is
-  // disabled.
+  /// Call this function when the drag operation started by a
+  /// cef_render_handler_t::StartDragging call has ended either in a drop or by
+  /// being cancelled. |x| and |y| are mouse coordinates relative to the upper-
+  /// left corner of the view. If the web view is both the drag source and the
+  /// drag target then all DragTarget* functions should be called before
+  /// DragSource* mthods. This function is only used when window rendering is
+  /// disabled.
   ///
   void(CEF_CALLBACK* drag_source_ended_at)(struct _cef_browser_host_t* self,
                                            int x,
@@ -839,55 +852,55 @@
                                            cef_drag_operations_mask_t op);
 
   ///
-  // Call this function when the drag operation started by a
-  // cef_render_handler_t::StartDragging call has completed. This function may
-  // be called immediately without first calling DragSourceEndedAt to cancel a
-  // drag operation. If the web view is both the drag source and the drag target
-  // then all DragTarget* functions should be called before DragSource* mthods.
-  // This function is only used when window rendering is disabled.
+  /// Call this function when the drag operation started by a
+  /// cef_render_handler_t::StartDragging call has completed. This function may
+  /// be called immediately without first calling DragSourceEndedAt to cancel a
+  /// drag operation. If the web view is both the drag source and the drag
+  /// target then all DragTarget* functions should be called before DragSource*
+  /// mthods. This function is only used when window rendering is disabled.
   ///
   void(CEF_CALLBACK* drag_source_system_drag_ended)(
       struct _cef_browser_host_t* self);
 
   ///
-  // Returns the current visible navigation entry for this browser. This
-  // function can only be called on the UI thread.
+  /// Returns the current visible navigation entry for this browser. This
+  /// function can only be called on the UI thread.
   ///
   struct _cef_navigation_entry_t*(CEF_CALLBACK* get_visible_navigation_entry)(
       struct _cef_browser_host_t* self);
 
   ///
-  // Set accessibility state for all frames. |accessibility_state| may be
-  // default, enabled or disabled. If |accessibility_state| is STATE_DEFAULT
-  // then accessibility will be disabled by default and the state may be further
-  // controlled with the "force-renderer-accessibility" and "disable-renderer-
-  // accessibility" command-line switches. If |accessibility_state| is
-  // STATE_ENABLED then accessibility will be enabled. If |accessibility_state|
-  // is STATE_DISABLED then accessibility will be completely disabled.
-  //
-  // For windowed browsers accessibility will be enabled in Complete mode (which
-  // corresponds to kAccessibilityModeComplete in Chromium). In this mode all
-  // platform accessibility objects will be created and managed by Chromium's
-  // internal implementation. The client needs only to detect the screen reader
-  // and call this function appropriately. For example, on macOS the client can
-  // handle the @"AXEnhancedUserStructure" accessibility attribute to detect
-  // VoiceOver state changes and on Windows the client can handle WM_GETOBJECT
-  // with OBJID_CLIENT to detect accessibility readers.
-  //
-  // For windowless browsers accessibility will be enabled in TreeOnly mode
-  // (which corresponds to kAccessibilityModeWebContentsOnly in Chromium). In
-  // this mode renderer accessibility is enabled, the full tree is computed, and
-  // events are passed to CefAccessibiltyHandler, but platform accessibility
-  // objects are not created. The client may implement platform accessibility
-  // objects using CefAccessibiltyHandler callbacks if desired.
+  /// Set accessibility state for all frames. |accessibility_state| may be
+  /// default, enabled or disabled. If |accessibility_state| is STATE_DEFAULT
+  /// then accessibility will be disabled by default and the state may be
+  /// further controlled with the "force-renderer-accessibility" and "disable-
+  /// renderer-accessibility" command-line switches. If |accessibility_state| is
+  /// STATE_ENABLED then accessibility will be enabled. If |accessibility_state|
+  /// is STATE_DISABLED then accessibility will be completely disabled.
+  ///
+  /// For windowed browsers accessibility will be enabled in Complete mode
+  /// (which corresponds to kAccessibilityModeComplete in Chromium). In this
+  /// mode all platform accessibility objects will be created and managed by
+  /// Chromium's internal implementation. The client needs only to detect the
+  /// screen reader and call this function appropriately. For example, on macOS
+  /// the client can handle the @"AXEnhancedUserStructure" accessibility
+  /// attribute to detect VoiceOver state changes and on Windows the client can
+  /// handle WM_GETOBJECT with OBJID_CLIENT to detect accessibility readers.
+  ///
+  /// For windowless browsers accessibility will be enabled in TreeOnly mode
+  /// (which corresponds to kAccessibilityModeWebContentsOnly in Chromium). In
+  /// this mode renderer accessibility is enabled, the full tree is computed,
+  /// and events are passed to CefAccessibiltyHandler, but platform
+  /// accessibility objects are not created. The client may implement platform
+  /// accessibility objects using CefAccessibiltyHandler callbacks if desired.
   ///
   void(CEF_CALLBACK* set_accessibility_state)(struct _cef_browser_host_t* self,
                                               cef_state_t accessibility_state);
 
   ///
-  // Enable notifications of auto resize via
-  // cef_display_handler_t::OnAutoResize. Notifications are disabled by default.
-  // |min_size| and |max_size| define the range of allowed sizes.
+  /// Enable notifications of auto resize via
+  /// cef_display_handler_t::OnAutoResize. Notifications are disabled by
+  /// default. |min_size| and |max_size| define the range of allowed sizes.
   ///
   void(CEF_CALLBACK* set_auto_resize_enabled)(struct _cef_browser_host_t* self,
                                               int enabled,
@@ -895,41 +908,83 @@
                                               const cef_size_t* max_size);
 
   ///
-  // Returns the extension hosted in this browser or NULL if no extension is
-  // hosted. See cef_request_context_t::LoadExtension for details.
+  /// Returns the extension hosted in this browser or NULL if no extension is
+  /// hosted. See cef_request_context_t::LoadExtension for details.
   ///
   struct _cef_extension_t*(CEF_CALLBACK* get_extension)(
       struct _cef_browser_host_t* self);
 
   ///
-  // Returns true (1) if this browser is hosting an extension background script.
-  // Background hosts do not have a window and are not displayable. See
-  // cef_request_context_t::LoadExtension for details.
+  /// Returns true (1) if this browser is hosting an extension background
+  /// script. Background hosts do not have a window and are not displayable. See
+  /// cef_request_context_t::LoadExtension for details.
   ///
   int(CEF_CALLBACK* is_background_host)(struct _cef_browser_host_t* self);
 
   ///
-  //  Set whether the browser's audio is muted.
+  /// Set whether the browser's audio is muted.
   ///
   void(CEF_CALLBACK* set_audio_muted)(struct _cef_browser_host_t* self,
                                       int mute);
 
   ///
-  // Returns true (1) if the browser's audio is muted.  This function can only
-  // be called on the UI thread.
+  /// Returns true (1) if the browser's audio is muted.  This function can only
+  /// be called on the UI thread.
   ///
   int(CEF_CALLBACK* is_audio_muted)(struct _cef_browser_host_t* self);
+
+  ///
+  /// Returns true (1) if the renderer is currently in browser fullscreen. This
+  /// differs from window fullscreen in that browser fullscreen is entered using
+  /// the JavaScript Fullscreen API and modifies CSS attributes such as the
+  /// ::backdrop pseudo-element and :fullscreen pseudo-structure. This function
+  /// can only be called on the UI thread.
+  ///
+  int(CEF_CALLBACK* is_fullscreen)(struct _cef_browser_host_t* self);
+
+  ///
+  /// Requests the renderer to exit browser fullscreen. In most cases exiting
+  /// window fullscreen should also exit browser fullscreen. With the Alloy
+  /// runtime this function should be called in response to a user action such
+  /// as clicking the green traffic light button on MacOS
+  /// (cef_window_delegate_t::OnWindowFullscreenTransition callback) or pressing
+  /// the "ESC" key (cef_keyboard_handler_t::OnPreKeyEvent callback). With the
+  /// Chrome runtime these standard exit actions are handled internally but
+  /// new/additional user actions can use this function. Set |will_cause_resize|
+  /// to true (1) if exiting browser fullscreen will cause a view resize.
+  ///
+  void(CEF_CALLBACK* exit_fullscreen)(struct _cef_browser_host_t* self,
+                                      int will_cause_resize);
+
+  ///
+  /// Returns true (1) if a Chrome command is supported and enabled. Values for
+  /// |command_id| can be found in the cef_command_ids.h file. This function can
+  /// only be called on the UI thread. Only used with the Chrome runtime.
+  ///
+  int(CEF_CALLBACK* can_execute_chrome_command)(
+      struct _cef_browser_host_t* self,
+      int command_id);
+
+  ///
+  /// Execute a Chrome command. Values for |command_id| can be found in the
+  /// cef_command_ids.h file. |disposition| provides information about the
+  /// intended command target. Only used with the Chrome runtime.
+  ///
+  void(CEF_CALLBACK* execute_chrome_command)(
+      struct _cef_browser_host_t* self,
+      int command_id,
+      cef_window_open_disposition_t disposition);
 } cef_browser_host_t;
 
 ///
-// Create a new browser window using the window parameters specified by
-// |windowInfo|. All values will be copied internally and the actual window will
-// be created on the UI thread. If |request_context| is NULL the global request
-// context will be used. This function can be called on any browser process
-// thread and will not block. The optional |extra_info| parameter provides an
-// opportunity to specify extra information specific to the created browser that
-// will be passed to cef_render_process_handler_t::on_browser_created() in the
-// render process.
+/// Create a new browser using the window parameters specified by |windowInfo|.
+/// All values will be copied internally and the actual window (if any) will be
+/// created on the UI thread. If |request_context| is NULL the global request
+/// context will be used. This function can be called on any browser process
+/// thread and will not block. The optional |extra_info| parameter provides an
+/// opportunity to specify extra information specific to the created browser
+/// that will be passed to cef_render_process_handler_t::on_browser_created() in
+/// the render process.
 ///
 CEF_EXPORT int cef_browser_host_create_browser(
     const cef_window_info_t* windowInfo,
@@ -940,12 +995,12 @@
     struct _cef_request_context_t* request_context);
 
 ///
-// Create a new browser window using the window parameters specified by
-// |windowInfo|. If |request_context| is NULL the global request context will be
-// used. This function can only be called on the browser process UI thread. The
-// optional |extra_info| parameter provides an opportunity to specify extra
-// information specific to the created browser that will be passed to
-// cef_render_process_handler_t::on_browser_created() in the render process.
+/// Create a new browser using the window parameters specified by |windowInfo|.
+/// If |request_context| is NULL the global request context will be used. This
+/// function can only be called on the browser process UI thread. The optional
+/// |extra_info| parameter provides an opportunity to specify extra information
+/// specific to the created browser that will be passed to
+/// cef_render_process_handler_t::on_browser_created() in the render process.
 ///
 CEF_EXPORT cef_browser_t* cef_browser_host_create_browser_sync(
     const cef_window_info_t* windowInfo,
diff --git a/src/include/capi/cef_browser_process_handler_capi.h b/src/include/capi/cef_browser_process_handler_capi.h
index 2d9ee46..42324c0 100644
--- a/src/include/capi/cef_browser_process_handler_capi.h
+++ b/src/include/capi/cef_browser_process_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=b15ba2c750f5227b6b40fea59965817ba4431ee0$
+// $hash=a146316e075450f0a6f37cb45d14e15e0ac7be08$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_BROWSER_PROCESS_HANDLER_CAPI_H_
@@ -41,8 +41,9 @@
 #pragma once
 
 #include "include/capi/cef_base_capi.h"
+#include "include/capi/cef_client_capi.h"
 #include "include/capi/cef_command_line_capi.h"
-#include "include/capi/cef_print_handler_capi.h"
+#include "include/capi/cef_preference_capi.h"
 #include "include/capi/cef_values_capi.h"
 
 #ifdef __cplusplus
@@ -50,68 +51,87 @@
 #endif
 
 ///
-// Structure used to implement browser process callbacks. The functions of this
-// structure will be called on the browser process main thread unless otherwise
-// indicated.
+/// Structure used to implement browser process callbacks. The functions of this
+/// structure will be called on the browser process main thread unless otherwise
+/// indicated.
 ///
 typedef struct _cef_browser_process_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called on the browser process UI thread immediately after the CEF context
-  // has been initialized.
+  /// Provides an opportunity to register custom preferences prior to global and
+  /// request context initialization.
+  ///
+  /// If |type| is CEF_PREFERENCES_TYPE_GLOBAL the registered preferences can be
+  /// accessed via cef_preference_manager_t::GetGlobalPreferences after
+  /// OnContextInitialized is called. Global preferences are registered a single
+  /// time at application startup. See related cef_settings_t.cache_path and
+  /// cef_settings_t.persist_user_preferences configuration.
+  ///
+  /// If |type| is CEF_PREFERENCES_TYPE_REQUEST_CONTEXT the preferences can be
+  /// accessed via the cef_request_context_t after
+  /// cef_request_context_handler_t::OnRequestContextInitialized is called.
+  /// Request context preferences are registered each time a new
+  /// cef_request_context_t is created. It is intended but not required that all
+  /// request contexts have the same registered preferences. See related
+  /// cef_request_context_settings_t.cache_path and
+  /// cef_request_context_settings_t.persist_user_preferences configuration.
+  ///
+  /// Do not keep a reference to the |registrar| object. This function is called
+  /// on the browser process UI thread.
+  ///
+  void(CEF_CALLBACK* on_register_custom_preferences)(
+      struct _cef_browser_process_handler_t* self,
+      cef_preferences_type_t type,
+      struct _cef_preference_registrar_t* registrar);
+
+  ///
+  /// Called on the browser process UI thread immediately after the CEF context
+  /// has been initialized.
   ///
   void(CEF_CALLBACK* on_context_initialized)(
       struct _cef_browser_process_handler_t* self);
 
   ///
-  // Called before a child process is launched. Will be called on the browser
-  // process UI thread when launching a render process and on the browser
-  // process IO thread when launching a GPU or plugin process. Provides an
-  // opportunity to modify the child process command line. Do not keep a
-  // reference to |command_line| outside of this function.
+  /// Called before a child process is launched. Will be called on the browser
+  /// process UI thread when launching a render process and on the browser
+  /// process IO thread when launching a GPU process. Provides an opportunity to
+  /// modify the child process command line. Do not keep a reference to
+  /// |command_line| outside of this function.
   ///
   void(CEF_CALLBACK* on_before_child_process_launch)(
       struct _cef_browser_process_handler_t* self,
       struct _cef_command_line_t* command_line);
 
   ///
-  // Called on the browser process IO thread after the main thread has been
-  // created for a new render process. Provides an opportunity to specify extra
-  // information that will be passed to
-  // cef_render_process_handler_t::on_render_thread_created() in the render
-  // process. Do not keep a reference to |extra_info| outside of this function.
-  ///
-  void(CEF_CALLBACK* on_render_process_thread_created)(
-      struct _cef_browser_process_handler_t* self,
-      struct _cef_list_value_t* extra_info);
-
-  ///
-  // Return the handler for printing on Linux. If a print handler is not
-  // provided then printing will not be supported on the Linux platform.
-  ///
-  struct _cef_print_handler_t*(CEF_CALLBACK* get_print_handler)(
-      struct _cef_browser_process_handler_t* self);
-
-  ///
-  // Called from any thread when work has been scheduled for the browser process
-  // main (UI) thread. This callback is used in combination with CefSettings.
-  // external_message_pump and cef_do_message_loop_work() in cases where the CEF
-  // message loop must be integrated into an existing application message loop
-  // (see additional comments and warnings on CefDoMessageLoopWork). This
-  // callback should schedule a cef_do_message_loop_work() call to happen on the
-  // main (UI) thread. |delay_ms| is the requested delay in milliseconds. If
-  // |delay_ms| is <= 0 then the call should happen reasonably soon. If
-  // |delay_ms| is > 0 then the call should be scheduled to happen after the
-  // specified delay and any currently pending scheduled call should be
-  // cancelled.
+  /// Called from any thread when work has been scheduled for the browser
+  /// process main (UI) thread. This callback is used in combination with
+  /// cef_settings_t.external_message_pump and cef_do_message_loop_work() in
+  /// cases where the CEF message loop must be integrated into an existing
+  /// application message loop (see additional comments and warnings on
+  /// CefDoMessageLoopWork). This callback should schedule a
+  /// cef_do_message_loop_work() call to happen on the main (UI) thread.
+  /// |delay_ms| is the requested delay in milliseconds. If |delay_ms| is <= 0
+  /// then the call should happen reasonably soon. If |delay_ms| is > 0 then the
+  /// call should be scheduled to happen after the specified delay and any
+  /// currently pending scheduled call should be cancelled.
   ///
   void(CEF_CALLBACK* on_schedule_message_pump_work)(
       struct _cef_browser_process_handler_t* self,
-      int64 delay_ms);
+      int64_t delay_ms);
+
+  ///
+  /// Return the default client for use with a newly created browser window. If
+  /// null is returned the browser will be unmanaged (no callbacks will be
+  /// executed for that browser) and application shutdown will be blocked until
+  /// the browser window is closed manually. This function is currently only
+  /// used with the chrome runtime.
+  ///
+  struct _cef_client_t*(CEF_CALLBACK* get_default_client)(
+      struct _cef_browser_process_handler_t* self);
 } cef_browser_process_handler_t;
 
 #ifdef __cplusplus
diff --git a/src/include/capi/cef_callback_capi.h b/src/include/capi/cef_callback_capi.h
index 02b41ee..d5086aa 100644
--- a/src/include/capi/cef_callback_capi.h
+++ b/src/include/capi/cef_callback_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=5c540e617cf2782876defad365e85cd43932ffce$
+// $hash=4fd98ff68ecb42677c3344b75e26d4787161b0d2$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_CALLBACK_CAPI_H_
@@ -47,36 +47,36 @@
 #endif
 
 ///
-// Generic callback structure used for asynchronous continuation.
+/// Generic callback structure used for asynchronous continuation.
 ///
 typedef struct _cef_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Continue processing.
+  /// Continue processing.
   ///
   void(CEF_CALLBACK* cont)(struct _cef_callback_t* self);
 
   ///
-  // Cancel processing.
+  /// Cancel processing.
   ///
   void(CEF_CALLBACK* cancel)(struct _cef_callback_t* self);
 } cef_callback_t;
 
 ///
-// Generic callback structure used for asynchronous completion.
+/// Generic callback structure used for asynchronous completion.
 ///
 typedef struct _cef_completion_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Method that will be called once the task is complete.
+  /// Method that will be called once the task is complete.
   ///
   void(CEF_CALLBACK* on_complete)(struct _cef_completion_callback_t* self);
 } cef_completion_callback_t;
diff --git a/src/include/capi/cef_client_capi.h b/src/include/capi/cef_client_capi.h
index a7eb509..e85a33b 100644
--- a/src/include/capi/cef_client_capi.h
+++ b/src/include/capi/cef_client_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=8d4cb3e0bbf230804c93898daa4a8b2866a2c1ce$
+// $hash=eb9dcb574252483dfab12834af93ba14138d4089$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_CLIENT_CAPI_H_
@@ -42,6 +42,7 @@
 
 #include "include/capi/cef_audio_handler_capi.h"
 #include "include/capi/cef_base_capi.h"
+#include "include/capi/cef_command_handler_capi.h"
 #include "include/capi/cef_context_menu_handler_capi.h"
 #include "include/capi/cef_dialog_handler_capi.h"
 #include "include/capi/cef_display_handler_capi.h"
@@ -49,10 +50,13 @@
 #include "include/capi/cef_drag_handler_capi.h"
 #include "include/capi/cef_find_handler_capi.h"
 #include "include/capi/cef_focus_handler_capi.h"
+#include "include/capi/cef_frame_handler_capi.h"
 #include "include/capi/cef_jsdialog_handler_capi.h"
 #include "include/capi/cef_keyboard_handler_capi.h"
 #include "include/capi/cef_life_span_handler_capi.h"
 #include "include/capi/cef_load_handler_capi.h"
+#include "include/capi/cef_permission_handler_capi.h"
+#include "include/capi/cef_print_handler_capi.h"
 #include "include/capi/cef_process_message_capi.h"
 #include "include/capi/cef_render_handler_capi.h"
 #include "include/capi/cef_request_handler_capi.h"
@@ -62,106 +66,134 @@
 #endif
 
 ///
-// Implement this structure to provide handler implementations.
+/// Implement this structure to provide handler implementations.
 ///
 typedef struct _cef_client_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Return the handler for audio rendering events.
+  /// Return the handler for audio rendering events.
   ///
   struct _cef_audio_handler_t*(CEF_CALLBACK* get_audio_handler)(
       struct _cef_client_t* self);
 
   ///
-  // Return the handler for context menus. If no handler is provided the default
-  // implementation will be used.
+  /// Return the handler for commands. If no handler is provided the default
+  /// implementation will be used.
+  ///
+  struct _cef_command_handler_t*(CEF_CALLBACK* get_command_handler)(
+      struct _cef_client_t* self);
+
+  ///
+  /// Return the handler for context menus. If no handler is provided the
+  /// default implementation will be used.
   ///
   struct _cef_context_menu_handler_t*(CEF_CALLBACK* get_context_menu_handler)(
       struct _cef_client_t* self);
 
   ///
-  // Return the handler for dialogs. If no handler is provided the default
-  // implementation will be used.
+  /// Return the handler for dialogs. If no handler is provided the default
+  /// implementation will be used.
   ///
   struct _cef_dialog_handler_t*(CEF_CALLBACK* get_dialog_handler)(
       struct _cef_client_t* self);
 
   ///
-  // Return the handler for browser display state events.
+  /// Return the handler for browser display state events.
   ///
   struct _cef_display_handler_t*(CEF_CALLBACK* get_display_handler)(
       struct _cef_client_t* self);
 
   ///
-  // Return the handler for download events. If no handler is returned downloads
-  // will not be allowed.
+  /// Return the handler for download events. If no handler is returned
+  /// downloads will not be allowed.
   ///
   struct _cef_download_handler_t*(CEF_CALLBACK* get_download_handler)(
       struct _cef_client_t* self);
 
   ///
-  // Return the handler for drag events.
+  /// Return the handler for drag events.
   ///
   struct _cef_drag_handler_t*(CEF_CALLBACK* get_drag_handler)(
       struct _cef_client_t* self);
 
   ///
-  // Return the handler for find result events.
+  /// Return the handler for find result events.
   ///
   struct _cef_find_handler_t*(CEF_CALLBACK* get_find_handler)(
       struct _cef_client_t* self);
 
   ///
-  // Return the handler for focus events.
+  /// Return the handler for focus events.
   ///
   struct _cef_focus_handler_t*(CEF_CALLBACK* get_focus_handler)(
       struct _cef_client_t* self);
 
   ///
-  // Return the handler for JavaScript dialogs. If no handler is provided the
-  // default implementation will be used.
+  /// Return the handler for events related to cef_frame_t lifespan. This
+  /// function will be called once during cef_browser_t creation and the result
+  /// will be cached for performance reasons.
+  ///
+  struct _cef_frame_handler_t*(CEF_CALLBACK* get_frame_handler)(
+      struct _cef_client_t* self);
+
+  ///
+  /// Return the handler for permission requests.
+  ///
+  struct _cef_permission_handler_t*(CEF_CALLBACK* get_permission_handler)(
+      struct _cef_client_t* self);
+
+  ///
+  /// Return the handler for JavaScript dialogs. If no handler is provided the
+  /// default implementation will be used.
   ///
   struct _cef_jsdialog_handler_t*(CEF_CALLBACK* get_jsdialog_handler)(
       struct _cef_client_t* self);
 
   ///
-  // Return the handler for keyboard events.
+  /// Return the handler for keyboard events.
   ///
   struct _cef_keyboard_handler_t*(CEF_CALLBACK* get_keyboard_handler)(
       struct _cef_client_t* self);
 
   ///
-  // Return the handler for browser life span events.
+  /// Return the handler for browser life span events.
   ///
   struct _cef_life_span_handler_t*(CEF_CALLBACK* get_life_span_handler)(
       struct _cef_client_t* self);
 
   ///
-  // Return the handler for browser load status events.
+  /// Return the handler for browser load status events.
   ///
   struct _cef_load_handler_t*(CEF_CALLBACK* get_load_handler)(
       struct _cef_client_t* self);
 
   ///
-  // Return the handler for off-screen rendering events.
+  /// Return the handler for printing on Linux. If a print handler is not
+  /// provided then printing will not be supported on the Linux platform.
+  ///
+  struct _cef_print_handler_t*(CEF_CALLBACK* get_print_handler)(
+      struct _cef_client_t* self);
+
+  ///
+  /// Return the handler for off-screen rendering events.
   ///
   struct _cef_render_handler_t*(CEF_CALLBACK* get_render_handler)(
       struct _cef_client_t* self);
 
   ///
-  // Return the handler for browser request events.
+  /// Return the handler for browser request events.
   ///
   struct _cef_request_handler_t*(CEF_CALLBACK* get_request_handler)(
       struct _cef_client_t* self);
 
   ///
-  // Called when a new message is received from a different process. Return true
-  // (1) if the message was handled or false (0) otherwise. Do not keep a
-  // reference to or attempt to access the message outside of this callback.
+  /// Called when a new message is received from a different process. Return
+  /// true (1) if the message was handled or false (0) otherwise.  It is safe to
+  /// keep a reference to |message| outside of this callback.
   ///
   int(CEF_CALLBACK* on_process_message_received)(
       struct _cef_client_t* self,
diff --git a/src/include/capi/cef_command_handler_capi.h b/src/include/capi/cef_command_handler_capi.h
new file mode 100644
index 0000000..db3a793
--- /dev/null
+++ b/src/include/capi/cef_command_handler_capi.h
@@ -0,0 +1,120 @@
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool and should not edited
+// by hand. See the translator.README.txt file in the tools directory for
+// more information.
+//
+// $hash=0cbb756a64d2aca1075480b5188b36cae533864d$
+//
+
+#ifndef CEF_INCLUDE_CAPI_CEF_COMMAND_HANDLER_CAPI_H_
+#define CEF_INCLUDE_CAPI_CEF_COMMAND_HANDLER_CAPI_H_
+#pragma once
+
+#include "include/capi/cef_base_capi.h"
+#include "include/capi/cef_browser_capi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///
+/// Implement this structure to handle events related to commands. The functions
+/// of this structure will be called on the UI thread.
+///
+typedef struct _cef_command_handler_t {
+  ///
+  /// Base structure.
+  ///
+  cef_base_ref_counted_t base;
+
+  ///
+  /// Called to execute a Chrome command triggered via menu selection or
+  /// keyboard shortcut. Values for |command_id| can be found in the
+  /// cef_command_ids.h file. |disposition| provides information about the
+  /// intended command target. Return true (1) if the command was handled or
+  /// false (0) for the default implementation. For context menu commands this
+  /// will be called after cef_context_menu_handler_t::OnContextMenuCommand.
+  /// Only used with the Chrome runtime.
+  ///
+  int(CEF_CALLBACK* on_chrome_command)(
+      struct _cef_command_handler_t* self,
+      struct _cef_browser_t* browser,
+      int command_id,
+      cef_window_open_disposition_t disposition);
+
+  ///
+  /// Called to check if a Chrome app menu item should be visible. Values for
+  /// |command_id| can be found in the cef_command_ids.h file. Only called for
+  /// menu items that would be visible by default. Only used with the Chrome
+  /// runtime.
+  ///
+  int(CEF_CALLBACK* is_chrome_app_menu_item_visible)(
+      struct _cef_command_handler_t* self,
+      struct _cef_browser_t* browser,
+      int command_id);
+
+  ///
+  /// Called to check if a Chrome app menu item should be enabled. Values for
+  /// |command_id| can be found in the cef_command_ids.h file. Only called for
+  /// menu items that would be enabled by default. Only used with the Chrome
+  /// runtime.
+  ///
+  int(CEF_CALLBACK* is_chrome_app_menu_item_enabled)(
+      struct _cef_command_handler_t* self,
+      struct _cef_browser_t* browser,
+      int command_id);
+
+  ///
+  /// Called during browser creation to check if a Chrome page action icon
+  /// should be visible. Only called for icons that would be visible by default.
+  /// Only used with the Chrome runtime.
+  ///
+  int(CEF_CALLBACK* is_chrome_page_action_icon_visible)(
+      struct _cef_command_handler_t* self,
+      cef_chrome_page_action_icon_type_t icon_type);
+
+  ///
+  /// Called during browser creation to check if a Chrome toolbar button should
+  /// be visible. Only called for buttons that would be visible by default. Only
+  /// used with the Chrome runtime.
+  ///
+  int(CEF_CALLBACK* is_chrome_toolbar_button_visible)(
+      struct _cef_command_handler_t* self,
+      cef_chrome_toolbar_button_type_t button_type);
+} cef_command_handler_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // CEF_INCLUDE_CAPI_CEF_COMMAND_HANDLER_CAPI_H_
diff --git a/src/include/capi/cef_command_line_capi.h b/src/include/capi/cef_command_line_capi.h
index 3ffc030..3379baa 100644
--- a/src/include/capi/cef_command_line_capi.h
+++ b/src/include/capi/cef_command_line_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=72ba5fe0cc6fe8081ec7b2b556e9022d1c6e8c61$
+// $hash=ac8fd3a7da20cff1fe2f20a75b045bf27c0312f2$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_COMMAND_LINE_CAPI_H_
@@ -47,103 +47,104 @@
 #endif
 
 ///
-// Structure used to create and/or parse command line arguments. Arguments with
-// '--', '-' and, on Windows, '/' prefixes are considered switches. Switches
-// will always precede any arguments without switch prefixes. Switches can
-// optionally have a value specified using the '=' delimiter (e.g.
-// "-switch=value"). An argument of "--" will terminate switch parsing with all
-// subsequent tokens, regardless of prefix, being interpreted as non-switch
-// arguments. Switch names are considered case-insensitive. This structure can
-// be used before cef_initialize() is called.
+/// Structure used to create and/or parse command line arguments. Arguments with
+/// "--", "-" and, on Windows, "/" prefixes are considered switches. Switches
+/// will always precede any arguments without switch prefixes. Switches can
+/// optionally have a value specified using the "=" delimiter (e.g.
+/// "-switch=value"). An argument of "--" will terminate switch parsing with all
+/// subsequent tokens, regardless of prefix, being interpreted as non-switch
+/// arguments. Switch names should be lowercase ASCII and will be converted to
+/// such if necessary. Switch values will retain the original case and UTF8
+/// encoding. This structure can be used before cef_initialize() is called.
 ///
 typedef struct _cef_command_line_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if this object is valid. Do not call any other functions
-  // if this function returns false (0).
+  /// Returns true (1) if this object is valid. Do not call any other functions
+  /// if this function returns false (0).
   ///
   int(CEF_CALLBACK* is_valid)(struct _cef_command_line_t* self);
 
   ///
-  // Returns true (1) if the values of this object are read-only. Some APIs may
-  // expose read-only objects.
+  /// Returns true (1) if the values of this object are read-only. Some APIs may
+  /// expose read-only objects.
   ///
   int(CEF_CALLBACK* is_read_only)(struct _cef_command_line_t* self);
 
   ///
-  // Returns a writable copy of this object.
+  /// Returns a writable copy of this object.
   ///
   struct _cef_command_line_t*(CEF_CALLBACK* copy)(
       struct _cef_command_line_t* self);
 
   ///
-  // Initialize the command line with the specified |argc| and |argv| values.
-  // The first argument must be the name of the program. This function is only
-  // supported on non-Windows platforms.
+  /// Initialize the command line with the specified |argc| and |argv| values.
+  /// The first argument must be the name of the program. This function is only
+  /// supported on non-Windows platforms.
   ///
   void(CEF_CALLBACK* init_from_argv)(struct _cef_command_line_t* self,
                                      int argc,
                                      const char* const* argv);
 
   ///
-  // Initialize the command line with the string returned by calling
-  // GetCommandLineW(). This function is only supported on Windows.
+  /// Initialize the command line with the string returned by calling
+  /// GetCommandLineW(). This function is only supported on Windows.
   ///
   void(CEF_CALLBACK* init_from_string)(struct _cef_command_line_t* self,
                                        const cef_string_t* command_line);
 
   ///
-  // Reset the command-line switches and arguments but leave the program
-  // component unchanged.
+  /// Reset the command-line switches and arguments but leave the program
+  /// component unchanged.
   ///
   void(CEF_CALLBACK* reset)(struct _cef_command_line_t* self);
 
   ///
-  // Retrieve the original command line string as a vector of strings. The argv
-  // array: { program, [(--|-|/)switch[=value]]*, [--], [argument]* }
+  /// Retrieve the original command line string as a vector of strings. The argv
+  /// array: `{ program, [(--|-|/)switch[=value]]*, [--], [argument]* }`
   ///
   void(CEF_CALLBACK* get_argv)(struct _cef_command_line_t* self,
                                cef_string_list_t argv);
 
   ///
-  // Constructs and returns the represented command line string. Use this
-  // function cautiously because quoting behavior is unclear.
+  /// Constructs and returns the represented command line string. Use this
+  /// function cautiously because quoting behavior is unclear.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_command_line_string)(
       struct _cef_command_line_t* self);
 
   ///
-  // Get the program part of the command line string (the first item).
+  /// Get the program part of the command line string (the first item).
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_program)(
       struct _cef_command_line_t* self);
 
   ///
-  // Set the program part of the command line string (the first item).
+  /// Set the program part of the command line string (the first item).
   ///
   void(CEF_CALLBACK* set_program)(struct _cef_command_line_t* self,
                                   const cef_string_t* program);
 
   ///
-  // Returns true (1) if the command line has switches.
+  /// Returns true (1) if the command line has switches.
   ///
   int(CEF_CALLBACK* has_switches)(struct _cef_command_line_t* self);
 
   ///
-  // Returns true (1) if the command line contains the given switch.
+  /// Returns true (1) if the command line contains the given switch.
   ///
   int(CEF_CALLBACK* has_switch)(struct _cef_command_line_t* self,
                                 const cef_string_t* name);
 
   ///
-  // Returns the value associated with the given switch. If the switch has no
-  // value or isn't present this function returns the NULL string.
+  /// Returns the value associated with the given switch. If the switch has no
+  /// value or isn't present this function returns the NULL string.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_switch_value)(
@@ -151,61 +152,61 @@
       const cef_string_t* name);
 
   ///
-  // Returns the map of switch names and values. If a switch has no value an
-  // NULL string is returned.
+  /// Returns the map of switch names and values. If a switch has no value an
+  /// NULL string is returned.
   ///
   void(CEF_CALLBACK* get_switches)(struct _cef_command_line_t* self,
                                    cef_string_map_t switches);
 
   ///
-  // Add a switch to the end of the command line. If the switch has no value
-  // pass an NULL value string.
+  /// Add a switch to the end of the command line.
   ///
   void(CEF_CALLBACK* append_switch)(struct _cef_command_line_t* self,
                                     const cef_string_t* name);
 
   ///
-  // Add a switch with the specified value to the end of the command line.
+  /// Add a switch with the specified value to the end of the command line. If
+  /// the switch has no value pass an NULL value string.
   ///
   void(CEF_CALLBACK* append_switch_with_value)(struct _cef_command_line_t* self,
                                                const cef_string_t* name,
                                                const cef_string_t* value);
 
   ///
-  // True if there are remaining command line arguments.
+  /// True if there are remaining command line arguments.
   ///
   int(CEF_CALLBACK* has_arguments)(struct _cef_command_line_t* self);
 
   ///
-  // Get the remaining command line arguments.
+  /// Get the remaining command line arguments.
   ///
   void(CEF_CALLBACK* get_arguments)(struct _cef_command_line_t* self,
                                     cef_string_list_t arguments);
 
   ///
-  // Add an argument to the end of the command line.
+  /// Add an argument to the end of the command line.
   ///
   void(CEF_CALLBACK* append_argument)(struct _cef_command_line_t* self,
                                       const cef_string_t* argument);
 
   ///
-  // Insert a command before the current command. Common for debuggers, like
-  // "valgrind" or "gdb --args".
+  /// Insert a command before the current command. Common for debuggers, like
+  /// "valgrind" or "gdb --args".
   ///
   void(CEF_CALLBACK* prepend_wrapper)(struct _cef_command_line_t* self,
                                       const cef_string_t* wrapper);
 } cef_command_line_t;
 
 ///
-// Create a new cef_command_line_t instance.
+/// Create a new cef_command_line_t instance.
 ///
-CEF_EXPORT cef_command_line_t* cef_command_line_create();
+CEF_EXPORT cef_command_line_t* cef_command_line_create(void);
 
 ///
-// Returns the singleton global cef_command_line_t object. The returned object
-// will be read-only.
+/// Returns the singleton global cef_command_line_t object. The returned object
+/// will be read-only.
 ///
-CEF_EXPORT cef_command_line_t* cef_command_line_get_global();
+CEF_EXPORT cef_command_line_t* cef_command_line_get_global(void);
 
 #ifdef __cplusplus
 }
diff --git a/src/include/capi/cef_context_menu_handler_capi.h b/src/include/capi/cef_context_menu_handler_capi.h
index e4cb71b..bc27333 100644
--- a/src/include/capi/cef_context_menu_handler_capi.h
+++ b/src/include/capi/cef_context_menu_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=fcb0328c54e5f629c24bfd232d75c31c372ab6ac$
+// $hash=c82f41d81f5afa5ed6995693e012c13d2a609f88$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_CONTEXT_MENU_HANDLER_CAPI_H_
@@ -52,44 +52,67 @@
 struct _cef_context_menu_params_t;
 
 ///
-// Callback structure used for continuation of custom context menu display.
+/// Callback structure used for continuation of custom context menu display.
 ///
 typedef struct _cef_run_context_menu_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Complete context menu display by selecting the specified |command_id| and
-  // |event_flags|.
+  /// Complete context menu display by selecting the specified |command_id| and
+  /// |event_flags|.
   ///
   void(CEF_CALLBACK* cont)(struct _cef_run_context_menu_callback_t* self,
                            int command_id,
                            cef_event_flags_t event_flags);
 
   ///
-  // Cancel context menu display.
+  /// Cancel context menu display.
   ///
   void(CEF_CALLBACK* cancel)(struct _cef_run_context_menu_callback_t* self);
 } cef_run_context_menu_callback_t;
 
 ///
-// Implement this structure to handle context menu events. The functions of this
-// structure will be called on the UI thread.
+/// Callback structure used for continuation of custom quick menu display.
 ///
-typedef struct _cef_context_menu_handler_t {
+typedef struct _cef_run_quick_menu_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called before a context menu is displayed. |params| provides information
-  // about the context menu state. |model| initially contains the default
-  // context menu. The |model| can be cleared to show no context menu or
-  // modified to show a custom menu. Do not keep references to |params| or
-  // |model| outside of this callback.
+  /// Complete quick menu display by selecting the specified |command_id| and
+  /// |event_flags|.
+  ///
+  void(CEF_CALLBACK* cont)(struct _cef_run_quick_menu_callback_t* self,
+                           int command_id,
+                           cef_event_flags_t event_flags);
+
+  ///
+  /// Cancel quick menu display.
+  ///
+  void(CEF_CALLBACK* cancel)(struct _cef_run_quick_menu_callback_t* self);
+} cef_run_quick_menu_callback_t;
+
+///
+/// Implement this structure to handle context menu events. The functions of
+/// this structure will be called on the UI thread.
+///
+typedef struct _cef_context_menu_handler_t {
+  ///
+  /// Base structure.
+  ///
+  cef_base_ref_counted_t base;
+
+  ///
+  /// Called before a context menu is displayed. |params| provides information
+  /// about the context menu state. |model| initially contains the default
+  /// context menu. The |model| can be cleared to show no context menu or
+  /// modified to show a custom menu. Do not keep references to |params| or
+  /// |model| outside of this callback.
   ///
   void(CEF_CALLBACK* on_before_context_menu)(
       struct _cef_context_menu_handler_t* self,
@@ -99,12 +122,12 @@
       struct _cef_menu_model_t* model);
 
   ///
-  // Called to allow custom display of the context menu. |params| provides
-  // information about the context menu state. |model| contains the context menu
-  // model resulting from OnBeforeContextMenu. For custom display return true
-  // (1) and execute |callback| either synchronously or asynchronously with the
-  // selected command ID. For default display return false (0). Do not keep
-  // references to |params| or |model| outside of this callback.
+  /// Called to allow custom display of the context menu. |params| provides
+  /// information about the context menu state. |model| contains the context
+  /// menu model resulting from OnBeforeContextMenu. For custom display return
+  /// true (1) and execute |callback| either synchronously or asynchronously
+  /// with the selected command ID. For default display return false (0). Do not
+  /// keep references to |params| or |model| outside of this callback.
   ///
   int(CEF_CALLBACK* run_context_menu)(
       struct _cef_context_menu_handler_t* self,
@@ -115,13 +138,13 @@
       struct _cef_run_context_menu_callback_t* callback);
 
   ///
-  // Called to execute a command selected from the context menu. Return true (1)
-  // if the command was handled or false (0) for the default implementation. See
-  // cef_menu_id_t for the command ids that have default implementations. All
-  // user-defined command ids should be between MENU_ID_USER_FIRST and
-  // MENU_ID_USER_LAST. |params| will have the same values as what was passed to
-  // on_before_context_menu(). Do not keep a reference to |params| outside of
-  // this callback.
+  /// Called to execute a command selected from the context menu. Return true
+  /// (1) if the command was handled or false (0) for the default
+  /// implementation. See cef_menu_id_t for the command ids that have default
+  /// implementations. All user-defined command ids should be between
+  /// MENU_ID_USER_FIRST and MENU_ID_USER_LAST. |params| will have the same
+  /// values as what was passed to on_before_context_menu(). Do not keep a
+  /// reference to |params| outside of this callback.
   ///
   int(CEF_CALLBACK* on_context_menu_command)(
       struct _cef_context_menu_handler_t* self,
@@ -132,173 +155,209 @@
       cef_event_flags_t event_flags);
 
   ///
-  // Called when the context menu is dismissed irregardless of whether the menu
-  // was NULL or a command was selected.
+  /// Called when the context menu is dismissed irregardless of whether the menu
+  /// was canceled or a command was selected.
   ///
   void(CEF_CALLBACK* on_context_menu_dismissed)(
       struct _cef_context_menu_handler_t* self,
       struct _cef_browser_t* browser,
       struct _cef_frame_t* frame);
+
+  ///
+  /// Called to allow custom display of the quick menu for a windowless browser.
+  /// |location| is the top left corner of the selected region. |size| is the
+  /// size of the selected region. |edit_state_flags| is a combination of flags
+  /// that represent the state of the quick menu. Return true (1) if the menu
+  /// will be handled and execute |callback| either synchronously or
+  /// asynchronously with the selected command ID. Return false (0) to cancel
+  /// the menu.
+  ///
+  int(CEF_CALLBACK* run_quick_menu)(
+      struct _cef_context_menu_handler_t* self,
+      struct _cef_browser_t* browser,
+      struct _cef_frame_t* frame,
+      const cef_point_t* location,
+      const cef_size_t* size,
+      cef_quick_menu_edit_state_flags_t edit_state_flags,
+      struct _cef_run_quick_menu_callback_t* callback);
+
+  ///
+  /// Called to execute a command selected from the quick menu for a windowless
+  /// browser. Return true (1) if the command was handled or false (0) for the
+  /// default implementation. See cef_menu_id_t for command IDs that have
+  /// default implementations.
+  ///
+  int(CEF_CALLBACK* on_quick_menu_command)(
+      struct _cef_context_menu_handler_t* self,
+      struct _cef_browser_t* browser,
+      struct _cef_frame_t* frame,
+      int command_id,
+      cef_event_flags_t event_flags);
+
+  ///
+  /// Called when the quick menu for a windowless browser is dismissed
+  /// irregardless of whether the menu was canceled or a command was selected.
+  ///
+  void(CEF_CALLBACK* on_quick_menu_dismissed)(
+      struct _cef_context_menu_handler_t* self,
+      struct _cef_browser_t* browser,
+      struct _cef_frame_t* frame);
 } cef_context_menu_handler_t;
 
 ///
-// Provides information about the context menu state. The ethods of this
-// structure can only be accessed on browser process the UI thread.
+/// Provides information about the context menu state. The functions of this
+/// structure can only be accessed on browser process the UI thread.
 ///
 typedef struct _cef_context_menu_params_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the X coordinate of the mouse where the context menu was invoked.
-  // Coords are relative to the associated RenderView's origin.
+  /// Returns the X coordinate of the mouse where the context menu was invoked.
+  /// Coords are relative to the associated RenderView's origin.
   ///
   int(CEF_CALLBACK* get_xcoord)(struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns the Y coordinate of the mouse where the context menu was invoked.
-  // Coords are relative to the associated RenderView's origin.
+  /// Returns the Y coordinate of the mouse where the context menu was invoked.
+  /// Coords are relative to the associated RenderView's origin.
   ///
   int(CEF_CALLBACK* get_ycoord)(struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns flags representing the type of node that the context menu was
-  // invoked on.
+  /// Returns flags representing the type of node that the context menu was
+  /// invoked on.
   ///
   cef_context_menu_type_flags_t(CEF_CALLBACK* get_type_flags)(
       struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns the URL of the link, if any, that encloses the node that the
-  // context menu was invoked on.
+  /// Returns the URL of the link, if any, that encloses the node that the
+  /// context menu was invoked on.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_link_url)(
       struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns the link URL, if any, to be used ONLY for "copy link address". We
-  // don't validate this field in the frontend process.
+  /// Returns the link URL, if any, to be used ONLY for "copy link address". We
+  /// don't validate this field in the frontend process.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_unfiltered_link_url)(
       struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns the source URL, if any, for the element that the context menu was
-  // invoked on. Example of elements with source URLs are img, audio, and video.
+  /// Returns the source URL, if any, for the element that the context menu was
+  /// invoked on. Example of elements with source URLs are img, audio, and
+  /// video.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_source_url)(
       struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns true (1) if the context menu was invoked on an image which has non-
-  // NULL contents.
+  /// Returns true (1) if the context menu was invoked on an image which has
+  /// non-NULL contents.
   ///
   int(CEF_CALLBACK* has_image_contents)(
       struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns the title text or the alt text if the context menu was invoked on
-  // an image.
+  /// Returns the title text or the alt text if the context menu was invoked on
+  /// an image.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_title_text)(
       struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns the URL of the top level page that the context menu was invoked on.
+  /// Returns the URL of the top level page that the context menu was invoked
+  /// on.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_page_url)(
       struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns the URL of the subframe that the context menu was invoked on.
+  /// Returns the URL of the subframe that the context menu was invoked on.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_frame_url)(
       struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns the character encoding of the subframe that the context menu was
-  // invoked on.
+  /// Returns the character encoding of the subframe that the context menu was
+  /// invoked on.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_frame_charset)(
       struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns the type of context node that the context menu was invoked on.
+  /// Returns the type of context node that the context menu was invoked on.
   ///
   cef_context_menu_media_type_t(CEF_CALLBACK* get_media_type)(
       struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns flags representing the actions supported by the media element, if
-  // any, that the context menu was invoked on.
+  /// Returns flags representing the actions supported by the media element, if
+  /// any, that the context menu was invoked on.
   ///
   cef_context_menu_media_state_flags_t(CEF_CALLBACK* get_media_state_flags)(
       struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns the text of the selection, if any, that the context menu was
-  // invoked on.
+  /// Returns the text of the selection, if any, that the context menu was
+  /// invoked on.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_selection_text)(
       struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns the text of the misspelled word, if any, that the context menu was
-  // invoked on.
+  /// Returns the text of the misspelled word, if any, that the context menu was
+  /// invoked on.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_misspelled_word)(
       struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns true (1) if suggestions exist, false (0) otherwise. Fills in
-  // |suggestions| from the spell check service for the misspelled word if there
-  // is one.
+  /// Returns true (1) if suggestions exist, false (0) otherwise. Fills in
+  /// |suggestions| from the spell check service for the misspelled word if
+  /// there is one.
   ///
   int(CEF_CALLBACK* get_dictionary_suggestions)(
       struct _cef_context_menu_params_t* self,
       cef_string_list_t suggestions);
 
   ///
-  // Returns true (1) if the context menu was invoked on an editable node.
+  /// Returns true (1) if the context menu was invoked on an editable node.
   ///
   int(CEF_CALLBACK* is_editable)(struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns true (1) if the context menu was invoked on an editable node where
-  // spell-check is enabled.
+  /// Returns true (1) if the context menu was invoked on an editable node where
+  /// spell-check is enabled.
   ///
   int(CEF_CALLBACK* is_spell_check_enabled)(
       struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns flags representing the actions supported by the editable node, if
-  // any, that the context menu was invoked on.
+  /// Returns flags representing the actions supported by the editable node, if
+  /// any, that the context menu was invoked on.
   ///
   cef_context_menu_edit_state_flags_t(CEF_CALLBACK* get_edit_state_flags)(
       struct _cef_context_menu_params_t* self);
 
   ///
-  // Returns true (1) if the context menu contains items specified by the
-  // renderer process (for example, plugin placeholder or pepper plugin menu
-  // items).
+  /// Returns true (1) if the context menu contains items specified by the
+  /// renderer process.
   ///
   int(CEF_CALLBACK* is_custom_menu)(struct _cef_context_menu_params_t* self);
-
-  ///
-  // Returns true (1) if the context menu was invoked from a pepper plugin.
-  ///
-  int(CEF_CALLBACK* is_pepper_menu)(struct _cef_context_menu_params_t* self);
 } cef_context_menu_params_t;
 
 #ifdef __cplusplus
diff --git a/src/include/capi/cef_cookie_capi.h b/src/include/capi/cef_cookie_capi.h
index 7a4a13e..1be978b 100644
--- a/src/include/capi/cef_cookie_capi.h
+++ b/src/include/capi/cef_cookie_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=2f5721138da26a9d7cce300a635b58dae9f51a4a$
+// $hash=598c6f530b2e2553197d8c6a72ad9e2bf72b5443$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_COOKIE_CAPI_H_
@@ -52,44 +52,29 @@
 struct _cef_set_cookie_callback_t;
 
 ///
-// Structure used for managing cookies. The functions of this structure may be
-// called on any thread unless otherwise indicated.
+/// Structure used for managing cookies. The functions of this structure may be
+/// called on any thread unless otherwise indicated.
 ///
 typedef struct _cef_cookie_manager_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Set the schemes supported by this manager. If |include_defaults| is true
-  // (1) the default schemes ("http", "https", "ws" and "wss") will also be
-  // supported. Calling this function with an NULL |schemes| value and
-  // |include_defaults| set to false (0) will disable all loading and saving of
-  // cookies for this manager. If |callback| is non-NULL it will be executed
-  // asnychronously on the UI thread after the change has been applied. Must be
-  // called before any cookies are accessed.
-  ///
-  void(CEF_CALLBACK* set_supported_schemes)(
-      struct _cef_cookie_manager_t* self,
-      cef_string_list_t schemes,
-      int include_defaults,
-      struct _cef_completion_callback_t* callback);
-
-  ///
-  // Visit all cookies on the UI thread. The returned cookies are ordered by
-  // longest path, then by earliest creation date. Returns false (0) if cookies
-  // cannot be accessed.
+  /// Visit all cookies on the UI thread. The returned cookies are ordered by
+  /// longest path, then by earliest creation date. Returns false (0) if cookies
+  /// cannot be accessed.
   ///
   int(CEF_CALLBACK* visit_all_cookies)(struct _cef_cookie_manager_t* self,
                                        struct _cef_cookie_visitor_t* visitor);
 
   ///
-  // Visit a subset of cookies on the UI thread. The results are filtered by the
-  // given url scheme, host, domain and path. If |includeHttpOnly| is true (1)
-  // HTTP-only cookies will also be included in the results. The returned
-  // cookies are ordered by longest path, then by earliest creation date.
-  // Returns false (0) if cookies cannot be accessed.
+  /// Visit a subset of cookies on the UI thread. The results are filtered by
+  /// the given url scheme, host, domain and path. If |includeHttpOnly| is true
+  /// (1) HTTP-only cookies will also be included in the results. The returned
+  /// cookies are ordered by longest path, then by earliest creation date.
+  /// Returns false (0) if cookies cannot be accessed.
   ///
   int(CEF_CALLBACK* visit_url_cookies)(struct _cef_cookie_manager_t* self,
                                        const cef_string_t* url,
@@ -97,13 +82,13 @@
                                        struct _cef_cookie_visitor_t* visitor);
 
   ///
-  // Sets a cookie given a valid URL and explicit user-provided cookie
-  // attributes. This function expects each attribute to be well-formed. It will
-  // check for disallowed characters (e.g. the ';' character is disallowed
-  // within the cookie value attribute) and fail without setting the cookie if
-  // such characters are found. If |callback| is non-NULL it will be executed
-  // asnychronously on the UI thread after the cookie has been set. Returns
-  // false (0) if an invalid URL is specified or if cookies cannot be accessed.
+  /// Sets a cookie given a valid URL and explicit user-provided cookie
+  /// attributes. This function expects each attribute to be well-formed. It
+  /// will check for disallowed characters (e.g. the ';' character is disallowed
+  /// within the cookie value attribute) and fail without setting the cookie if
+  /// such characters are found. If |callback| is non-NULL it will be executed
+  /// asnychronously on the UI thread after the cookie has been set. Returns
+  /// false (0) if an invalid URL is specified or if cookies cannot be accessed.
   ///
   int(CEF_CALLBACK* set_cookie)(struct _cef_cookie_manager_t* self,
                                 const cef_string_t* url,
@@ -111,15 +96,15 @@
                                 struct _cef_set_cookie_callback_t* callback);
 
   ///
-  // Delete all cookies that match the specified parameters. If both |url| and
-  // |cookie_name| values are specified all host and domain cookies matching
-  // both will be deleted. If only |url| is specified all host cookies (but not
-  // domain cookies) irrespective of path will be deleted. If |url| is NULL all
-  // cookies for all hosts and domains will be deleted. If |callback| is non-
-  // NULL it will be executed asnychronously on the UI thread after the cookies
-  // have been deleted. Returns false (0) if a non-NULL invalid URL is specified
-  // or if cookies cannot be accessed. Cookies can alternately be deleted using
-  // the Visit*Cookies() functions.
+  /// Delete all cookies that match the specified parameters. If both |url| and
+  /// |cookie_name| values are specified all host and domain cookies matching
+  /// both will be deleted. If only |url| is specified all host cookies (but not
+  /// domain cookies) irrespective of path will be deleted. If |url| is NULL all
+  /// cookies for all hosts and domains will be deleted. If |callback| is non-
+  /// NULL it will be executed asnychronously on the UI thread after the cookies
+  /// have been deleted. Returns false (0) if a non-NULL invalid URL is
+  /// specified or if cookies cannot be accessed. Cookies can alternately be
+  /// deleted using the Visit*Cookies() functions.
   ///
   int(CEF_CALLBACK* delete_cookies)(
       struct _cef_cookie_manager_t* self,
@@ -128,41 +113,41 @@
       struct _cef_delete_cookies_callback_t* callback);
 
   ///
-  // Flush the backing store (if any) to disk. If |callback| is non-NULL it will
-  // be executed asnychronously on the UI thread after the flush is complete.
-  // Returns false (0) if cookies cannot be accessed.
+  /// Flush the backing store (if any) to disk. If |callback| is non-NULL it
+  /// will be executed asnychronously on the UI thread after the flush is
+  /// complete. Returns false (0) if cookies cannot be accessed.
   ///
   int(CEF_CALLBACK* flush_store)(struct _cef_cookie_manager_t* self,
                                  struct _cef_completion_callback_t* callback);
 } cef_cookie_manager_t;
 
 ///
-// Returns the global cookie manager. By default data will be stored at
-// CefSettings.cache_path if specified or in memory otherwise. If |callback| is
-// non-NULL it will be executed asnychronously on the UI thread after the
-// manager's storage has been initialized. Using this function is equivalent to
-// calling cef_request_context_t::cef_request_context_get_global_context()->GetD
-// efaultCookieManager().
+/// Returns the global cookie manager. By default data will be stored at
+/// cef_settings_t.cache_path if specified or in memory otherwise. If |callback|
+/// is non-NULL it will be executed asnychronously on the UI thread after the
+/// manager's storage has been initialized. Using this function is equivalent to
+/// calling cef_request_context_t::cef_request_context_get_global_context()->Get
+/// DefaultCookieManager().
 ///
 CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_get_global_manager(
     struct _cef_completion_callback_t* callback);
 
 ///
-// Structure to implement for visiting cookie values. The functions of this
-// structure will always be called on the UI thread.
+/// Structure to implement for visiting cookie values. The functions of this
+/// structure will always be called on the UI thread.
 ///
 typedef struct _cef_cookie_visitor_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Method that will be called once for each cookie. |count| is the 0-based
-  // index for the current cookie. |total| is the total number of cookies. Set
-  // |deleteCookie| to true (1) to delete the cookie currently being visited.
-  // Return false (0) to stop visiting cookies. This function may never be
-  // called if no cookies are found.
+  /// Method that will be called once for each cookie. |count| is the 0-based
+  /// index for the current cookie. |total| is the total number of cookies. Set
+  /// |deleteCookie| to true (1) to delete the cookie currently being visited.
+  /// Return false (0) to stop visiting cookies. This function may never be
+  /// called if no cookies are found.
   ///
   int(CEF_CALLBACK* visit)(struct _cef_cookie_visitor_t* self,
                            const struct _cef_cookie_t* cookie,
@@ -172,36 +157,36 @@
 } cef_cookie_visitor_t;
 
 ///
-// Structure to implement to be notified of asynchronous completion via
-// cef_cookie_manager_t::set_cookie().
+/// Structure to implement to be notified of asynchronous completion via
+/// cef_cookie_manager_t::set_cookie().
 ///
 typedef struct _cef_set_cookie_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Method that will be called upon completion. |success| will be true (1) if
-  // the cookie was set successfully.
+  /// Method that will be called upon completion. |success| will be true (1) if
+  /// the cookie was set successfully.
   ///
   void(CEF_CALLBACK* on_complete)(struct _cef_set_cookie_callback_t* self,
                                   int success);
 } cef_set_cookie_callback_t;
 
 ///
-// Structure to implement to be notified of asynchronous completion via
-// cef_cookie_manager_t::delete_cookies().
+/// Structure to implement to be notified of asynchronous completion via
+/// cef_cookie_manager_t::delete_cookies().
 ///
 typedef struct _cef_delete_cookies_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Method that will be called upon completion. |num_deleted| will be the
-  // number of cookies that were deleted.
+  /// Method that will be called upon completion. |num_deleted| will be the
+  /// number of cookies that were deleted.
   ///
   void(CEF_CALLBACK* on_complete)(struct _cef_delete_cookies_callback_t* self,
                                   int num_deleted);
diff --git a/src/include/capi/cef_crash_util_capi.h b/src/include/capi/cef_crash_util_capi.h
index 98a3be5..ce6ce04 100644
--- a/src/include/capi/cef_crash_util_capi.h
+++ b/src/include/capi/cef_crash_util_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=2b24c7d99c59c669719b822f5ea19763d140b001$
+// $hash=22cfd717df9032a01214d9abfe3e0e51949b3319$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_CRASH_UTIL_CAPI_H_
@@ -47,99 +47,102 @@
 #endif
 
 ///
-// Crash reporting is configured using an INI-style config file named
-// "crash_reporter.cfg". On Windows and Linux this file must be placed next to
-// the main application executable. On macOS this file must be placed in the
-// top-level app bundle Resources directory (e.g.
-// "<appname>.app/Contents/Resources"). File contents are as follows:
-//
-//  # Comments start with a hash character and must be on their own line.
-//
-//  [Config]
-//  ProductName=<Value of the "prod" crash key; defaults to "cef">
-//  ProductVersion=<Value of the "ver" crash key; defaults to the CEF version>
-//  AppName=<Windows only; App-specific folder name component for storing crash
-//           information; default to "CEF">
-//  ExternalHandler=<Windows only; Name of the external handler exe to use
-//                   instead of re-launching the main exe; default to empty>
-//  BrowserCrashForwardingEnabled=<macOS only; True if browser process crashes
-//                                 should be forwarded to the system crash
-//                                 reporter; default to false>
-//  ServerURL=<crash server URL; default to empty>
-//  RateLimitEnabled=<True if uploads should be rate limited; default to true>
-//  MaxUploadsPerDay=<Max uploads per 24 hours, used if rate limit is enabled;
-//                    default to 5>
-//  MaxDatabaseSizeInMb=<Total crash report disk usage greater than this value
-//                       will cause older reports to be deleted; default to 20>
-//  MaxDatabaseAgeInDays=<Crash reports older than this value will be deleted;
-//                        default to 5>
-//
-//  [CrashKeys]
-//  my_key1=<small|medium|large>
-//  my_key2=<small|medium|large>
-//
-// Config section:
-//
-// If "ProductName" and/or "ProductVersion" are set then the specified values
-// will be included in the crash dump metadata. On macOS if these values are set
-// to NULL then they will be retrieved from the Info.plist file using the
-// "CFBundleName" and "CFBundleShortVersionString" keys respectively.
-//
-// If "AppName" is set on Windows then crash report information (metrics,
-// database and dumps) will be stored locally on disk under the
-// "C:\Users\[CurrentUser]\AppData\Local\[AppName]\User Data" folder. On other
-// platforms the CefSettings.user_data_path value will be used.
-//
-// If "ExternalHandler" is set on Windows then the specified exe will be
-// launched as the crashpad-handler instead of re-launching the main process
-// exe. The value can be an absolute path or a path relative to the main exe
-// directory. On Linux the CefSettings.browser_subprocess_path value will be
-// used. On macOS the existing subprocess app bundle will be used.
-//
-// If "BrowserCrashForwardingEnabled" is set to true (1) on macOS then browser
-// process crashes will be forwarded to the system crash reporter. This results
-// in the crash UI dialog being displayed to the user and crash reports being
-// logged under "~/Library/Logs/DiagnosticReports". Forwarding of crash reports
-// from non-browser processes and Debug builds is always disabled.
-//
-// If "ServerURL" is set then crashes will be uploaded as a multi-part POST
-// request to the specified URL. Otherwise, reports will only be stored locally
-// on disk.
-//
-// If "RateLimitEnabled" is set to true (1) then crash report uploads will be
-// rate limited as follows:
-//  1. If "MaxUploadsPerDay" is set to a positive value then at most the
-//     specified number of crashes will be uploaded in each 24 hour period.
-//  2. If crash upload fails due to a network or server error then an
-//     incremental backoff delay up to a maximum of 24 hours will be applied for
-//     retries.
-//  3. If a backoff delay is applied and "MaxUploadsPerDay" is > 1 then the
-//     "MaxUploadsPerDay" value will be reduced to 1 until the client is
-//     restarted. This helps to avoid an upload flood when the network or
-//     server error is resolved.
-// Rate limiting is not supported on Linux.
-//
-// If "MaxDatabaseSizeInMb" is set to a positive value then crash report storage
-// on disk will be limited to that size in megabytes. For example, on Windows
-// each dump is about 600KB so a "MaxDatabaseSizeInMb" value of 20 equates to
-// about 34 crash reports stored on disk. Not supported on Linux.
-//
-// If "MaxDatabaseAgeInDays" is set to a positive value then crash reports older
-// than the specified age in days will be deleted. Not supported on Linux.
-//
-// CrashKeys section:
-//
-// A maximum of 26 crash keys of each size can be specified for use by the
-// application. Crash key values will be truncated based on the specified size
-// (small = 64 bytes, medium = 256 bytes, large = 1024 bytes). The value of
-// crash keys can be set from any thread or process using the
-// CefSetCrashKeyValue function. These key/value pairs will be sent to the crash
-// server along with the crash dump file.
+/// Crash reporting is configured using an INI-style config file named
+/// "crash_reporter.cfg". On Windows and Linux this file must be placed next to
+/// the main application executable. On macOS this file must be placed in the
+/// top-level app bundle Resources directory (e.g.
+/// "<appname>.app/Contents/Resources"). File contents are as follows:
 ///
-CEF_EXPORT int cef_crash_reporting_enabled();
+/// <pre>
+///  # Comments start with a hash character and must be on their own line.
+///
+///  [Config]
+///  ProductName=<Value of the "prod" crash key; defaults to "cef">
+///  ProductVersion=<Value of the "ver" crash key; defaults to the CEF version>
+///  AppName=<Windows only; App-specific folder name component for storing crash
+///           information; default to "CEF">
+///  ExternalHandler=<Windows only; Name of the external handler exe to use
+///                   instead of re-launching the main exe; default to empty>
+///  BrowserCrashForwardingEnabled=<macOS only; True if browser process crashes
+///                                 should be forwarded to the system crash
+///                                 reporter; default to false>
+///  ServerURL=<crash server URL; default to empty>
+///  RateLimitEnabled=<True if uploads should be rate limited; default to true>
+///  MaxUploadsPerDay=<Max uploads per 24 hours, used if rate limit is enabled;
+///                    default to 5>
+///  MaxDatabaseSizeInMb=<Total crash report disk usage greater than this value
+///                       will cause older reports to be deleted; default to 20>
+///  MaxDatabaseAgeInDays=<Crash reports older than this value will be deleted;
+///                        default to 5>
+///
+///  [CrashKeys]
+///  my_key1=<small|medium|large>
+///  my_key2=<small|medium|large>
+/// </pre>
+///
+/// <b>Config section:</b>
+///
+/// If "ProductName" and/or "ProductVersion" are set then the specified values
+/// will be included in the crash dump metadata. On macOS if these values are
+/// set to NULL then they will be retrieved from the Info.plist file using the
+/// "CFBundleName" and "CFBundleShortVersionString" keys respectively.
+///
+/// If "AppName" is set on Windows then crash report information (metrics,
+/// database and dumps) will be stored locally on disk under the
+/// "C:\Users\[CurrentUser]\AppData\Local\[AppName]\User Data" folder. On other
+/// platforms the cef_settings_t.root_cache_path value will be used.
+///
+/// If "ExternalHandler" is set on Windows then the specified exe will be
+/// launched as the crashpad-handler instead of re-launching the main process
+/// exe. The value can be an absolute path or a path relative to the main exe
+/// directory. On Linux the cef_settings_t.browser_subprocess_path value will be
+/// used. On macOS the existing subprocess app bundle will be used.
+///
+/// If "BrowserCrashForwardingEnabled" is set to true (1) on macOS then browser
+/// process crashes will be forwarded to the system crash reporter. This results
+/// in the crash UI dialog being displayed to the user and crash reports being
+/// logged under "~/Library/Logs/DiagnosticReports". Forwarding of crash reports
+/// from non-browser processes and Debug builds is always disabled.
+///
+/// If "ServerURL" is set then crashes will be uploaded as a multi-part POST
+/// request to the specified URL. Otherwise, reports will only be stored locally
+/// on disk.
+///
+/// If "RateLimitEnabled" is set to true (1) then crash report uploads will be
+/// rate limited as follows:
+///  1. If "MaxUploadsPerDay" is set to a positive value then at most the
+///     specified number of crashes will be uploaded in each 24 hour period.
+///  2. If crash upload fails due to a network or server error then an
+///     incremental backoff delay up to a maximum of 24 hours will be applied
+///     for retries.
+///  3. If a backoff delay is applied and "MaxUploadsPerDay" is > 1 then the
+///     "MaxUploadsPerDay" value will be reduced to 1 until the client is
+///     restarted. This helps to avoid an upload flood when the network or
+///     server error is resolved.
+/// Rate limiting is not supported on Linux.
+///
+/// If "MaxDatabaseSizeInMb" is set to a positive value then crash report
+/// storage on disk will be limited to that size in megabytes. For example, on
+/// Windows each dump is about 600KB so a "MaxDatabaseSizeInMb" value of 20
+/// equates to about 34 crash reports stored on disk. Not supported on Linux.
+///
+/// If "MaxDatabaseAgeInDays" is set to a positive value then crash reports
+/// older than the specified age in days will be deleted. Not supported on
+/// Linux.
+///
+/// <b>CrashKeys section:</b>
+///
+/// A maximum of 26 crash keys of each size can be specified for use by the
+/// application. Crash key values will be truncated based on the specified size
+/// (small = 64 bytes, medium = 256 bytes, large = 1024 bytes). The value of
+/// crash keys can be set from any thread or process using the
+/// CefSetCrashKeyValue function. These key/value pairs will be sent to the
+/// crash server along with the crash dump file.
+///
+CEF_EXPORT int cef_crash_reporting_enabled(void);
 
 ///
-// Sets or clears a specific key-value pair from the crash metadata.
+/// Sets or clears a specific key-value pair from the crash metadata.
 ///
 CEF_EXPORT void cef_set_crash_key_value(const cef_string_t* key,
                                         const cef_string_t* value);
diff --git a/src/include/capi/cef_devtools_message_observer_capi.h b/src/include/capi/cef_devtools_message_observer_capi.h
index bb0a21c..ee61835 100644
--- a/src/include/capi/cef_devtools_message_observer_capi.h
+++ b/src/include/capi/cef_devtools_message_observer_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=86906c2e971fea7e479738f59bbf85d71ce31953$
+// $hash=777485120b9a9df0f890579ee698d33f273819c5$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_DEVTOOLS_MESSAGE_OBSERVER_CAPI_H_
@@ -49,35 +49,36 @@
 struct _cef_browser_t;
 
 ///
-// Callback structure for cef_browser_host_t::AddDevToolsMessageObserver. The
-// functions of this structure will be called on the browser process UI thread.
+/// Callback structure for cef_browser_host_t::AddDevToolsMessageObserver. The
+/// functions of this structure will be called on the browser process UI thread.
 ///
 typedef struct _cef_dev_tools_message_observer_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Method that will be called on receipt of a DevTools protocol message.
-  // |browser| is the originating browser instance. |message| is a UTF8-encoded
-  // JSON dictionary representing either a function result or an event.
-  // |message| is only valid for the scope of this callback and should be copied
-  // if necessary. Return true (1) if the message was handled or false (0) if
-  // the message should be further processed and passed to the
-  // OnDevToolsMethodResult or OnDevToolsEvent functions as appropriate.
-  //
-  // Method result dictionaries include an "id" (int) value that identifies the
-  // orginating function call sent from cef_browser_host_t::SendDevToolsMessage,
-  // and optionally either a "result" (dictionary) or "error" (dictionary)
-  // value. The "error" dictionary will contain "code" (int) and "message"
-  // (string) values. Event dictionaries include a "function" (string) value and
-  // optionally a "params" (dictionary) value. See the DevTools protocol
-  // documentation at https://chromedevtools.github.io/devtools-protocol/ for
-  // details of supported function calls and the expected "result" or "params"
-  // dictionary contents. JSON dictionaries can be parsed using the CefParseJSON
-  // function if desired, however be aware of performance considerations when
-  // parsing large messages (some of which may exceed 1MB in size).
+  /// Method that will be called on receipt of a DevTools protocol message.
+  /// |browser| is the originating browser instance. |message| is a UTF8-encoded
+  /// JSON dictionary representing either a function result or an event.
+  /// |message| is only valid for the scope of this callback and should be
+  /// copied if necessary. Return true (1) if the message was handled or false
+  /// (0) if the message should be further processed and passed to the
+  /// OnDevToolsMethodResult or OnDevToolsEvent functions as appropriate.
+  ///
+  /// Method result dictionaries include an "id" (int) value that identifies the
+  /// orginating function call sent from
+  /// cef_browser_host_t::SendDevToolsMessage, and optionally either a "result"
+  /// (dictionary) or "error" (dictionary) value. The "error" dictionary will
+  /// contain "code" (int) and "message" (string) values. Event dictionaries
+  /// include a "function" (string) value and optionally a "params" (dictionary)
+  /// value. See the DevTools protocol documentation at
+  /// https://chromedevtools.github.io/devtools-protocol/ for details of
+  /// supported function calls and the expected "result" or "params" dictionary
+  /// contents. JSON dictionaries can be parsed using the CefParseJSON function
+  /// if desired, however be aware of performance considerations when parsing
+  /// large messages (some of which may exceed 1MB in size).
   ///
   int(CEF_CALLBACK* on_dev_tools_message)(
       struct _cef_dev_tools_message_observer_t* self,
@@ -86,16 +87,16 @@
       size_t message_size);
 
   ///
-  // Method that will be called after attempted execution of a DevTools protocol
-  // function. |browser| is the originating browser instance. |message_id| is
-  // the "id" value that identifies the originating function call message. If
-  // the function succeeded |success| will be true (1) and |result| will be the
-  // UTF8-encoded JSON "result" dictionary value (which may be NULL). If the
-  // function failed |success| will be false (0) and |result| will be the
-  // UTF8-encoded JSON "error" dictionary value. |result| is only valid for the
-  // scope of this callback and should be copied if necessary. See the
-  // OnDevToolsMessage documentation for additional details on |result|
-  // contents.
+  /// Method that will be called after attempted execution of a DevTools
+  /// protocol function. |browser| is the originating browser instance.
+  /// |message_id| is the "id" value that identifies the originating function
+  /// call message. If the function succeeded |success| will be true (1) and
+  /// |result| will be the UTF8-encoded JSON "result" dictionary value (which
+  /// may be NULL). If the function failed |success| will be false (0) and
+  /// |result| will be the UTF8-encoded JSON "error" dictionary value. |result|
+  /// is only valid for the scope of this callback and should be copied if
+  /// necessary. See the OnDevToolsMessage documentation for additional details
+  /// on |result| contents.
   ///
   void(CEF_CALLBACK* on_dev_tools_method_result)(
       struct _cef_dev_tools_message_observer_t* self,
@@ -106,12 +107,12 @@
       size_t result_size);
 
   ///
-  // Method that will be called on receipt of a DevTools protocol event.
-  // |browser| is the originating browser instance. |function| is the "function"
-  // value. |params| is the UTF8-encoded JSON "params" dictionary value (which
-  // may be NULL). |params| is only valid for the scope of this callback and
-  // should be copied if necessary. See the OnDevToolsMessage documentation for
-  // additional details on |params| contents.
+  /// Method that will be called on receipt of a DevTools protocol event.
+  /// |browser| is the originating browser instance. |function| is the
+  /// "function" value. |params| is the UTF8-encoded JSON "params" dictionary
+  /// value (which may be NULL). |params| is only valid for the scope of this
+  /// callback and should be copied if necessary. See the OnDevToolsMessage
+  /// documentation for additional details on |params| contents.
   ///
   void(CEF_CALLBACK* on_dev_tools_event)(
       struct _cef_dev_tools_message_observer_t* self,
@@ -121,19 +122,19 @@
       size_t params_size);
 
   ///
-  // Method that will be called when the DevTools agent has attached. |browser|
-  // is the originating browser instance. This will generally occur in response
-  // to the first message sent while the agent is detached.
+  /// Method that will be called when the DevTools agent has attached. |browser|
+  /// is the originating browser instance. This will generally occur in response
+  /// to the first message sent while the agent is detached.
   ///
   void(CEF_CALLBACK* on_dev_tools_agent_attached)(
       struct _cef_dev_tools_message_observer_t* self,
       struct _cef_browser_t* browser);
 
   ///
-  // Method that will be called when the DevTools agent has detached. |browser|
-  // is the originating browser instance. Any function results that were pending
-  // before the agent became detached will not be delivered, and any active
-  // event subscriptions will be canceled.
+  /// Method that will be called when the DevTools agent has detached. |browser|
+  /// is the originating browser instance. Any function results that were
+  /// pending before the agent became detached will not be delivered, and any
+  /// active event subscriptions will be canceled.
   ///
   void(CEF_CALLBACK* on_dev_tools_agent_detached)(
       struct _cef_dev_tools_message_observer_t* self,
diff --git a/src/include/capi/cef_dialog_handler_capi.h b/src/include/capi/cef_dialog_handler_capi.h
index 93258f1..82281ad 100644
--- a/src/include/capi/cef_dialog_handler_capi.h
+++ b/src/include/capi/cef_dialog_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=3253c217564ae9a85a1e971298c32a35e4cad136$
+// $hash=69545645f079f4593d9cbb6d8a36535c209245f7$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_DIALOG_HANDLER_CAPI_H_
@@ -48,55 +48,51 @@
 #endif
 
 ///
-// Callback structure for asynchronous continuation of file dialog requests.
+/// Callback structure for asynchronous continuation of file dialog requests.
 ///
 typedef struct _cef_file_dialog_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Continue the file selection. |selected_accept_filter| should be the 0-based
-  // index of the value selected from the accept filters array passed to
-  // cef_dialog_handler_t::OnFileDialog. |file_paths| should be a single value
-  // or a list of values depending on the dialog mode. An NULL |file_paths|
-  // value is treated the same as calling cancel().
+  /// Continue the file selection. |file_paths| should be a single value or a
+  /// list of values depending on the dialog mode. An NULL |file_paths| value is
+  /// treated the same as calling cancel().
   ///
   void(CEF_CALLBACK* cont)(struct _cef_file_dialog_callback_t* self,
-                           int selected_accept_filter,
                            cef_string_list_t file_paths);
 
   ///
-  // Cancel the file selection.
+  /// Cancel the file selection.
   ///
   void(CEF_CALLBACK* cancel)(struct _cef_file_dialog_callback_t* self);
 } cef_file_dialog_callback_t;
 
 ///
-// Implement this structure to handle dialog events. The functions of this
-// structure will be called on the browser process UI thread.
+/// Implement this structure to handle dialog events. The functions of this
+/// structure will be called on the browser process UI thread.
 ///
 typedef struct _cef_dialog_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called to run a file chooser dialog. |mode| represents the type of dialog
-  // to display. |title| to the title to be used for the dialog and may be NULL
-  // to show the default title ("Open" or "Save" depending on the mode).
-  // |default_file_path| is the path with optional directory and/or file name
-  // component that should be initially selected in the dialog. |accept_filters|
-  // are used to restrict the selectable file types and may any combination of
-  // (a) valid lower-cased MIME types (e.g. "text/*" or "image/*"), (b)
-  // individual file extensions (e.g. ".txt" or ".png"), or (c) combined
-  // description and file extension delimited using "|" and ";" (e.g. "Image
-  // Types|.png;.gif;.jpg"). |selected_accept_filter| is the 0-based index of
-  // the filter that should be selected by default. To display a custom dialog
-  // return true (1) and execute |callback| either inline or at a later time. To
-  // display the default dialog return false (0).
+  /// Called to run a file chooser dialog. |mode| represents the type of dialog
+  /// to display. |title| to the title to be used for the dialog and may be NULL
+  /// to show the default title ("Open" or "Save" depending on the mode).
+  /// |default_file_path| is the path with optional directory and/or file name
+  /// component that should be initially selected in the dialog.
+  /// |accept_filters| are used to restrict the selectable file types and may
+  /// any combination of (a) valid lower-cased MIME types (e.g. "text/*" or
+  /// "image/*"), (b) individual file extensions (e.g. ".txt" or ".png"), or (c)
+  /// combined description and file extension delimited using "|" and ";" (e.g.
+  /// "Image Types|.png;.gif;.jpg"). To display a custom dialog return true (1)
+  /// and execute |callback| either inline or at a later time. To display the
+  /// default dialog return false (0).
   ///
   int(CEF_CALLBACK* on_file_dialog)(
       struct _cef_dialog_handler_t* self,
@@ -105,7 +101,6 @@
       const cef_string_t* title,
       const cef_string_t* default_file_path,
       cef_string_list_t accept_filters,
-      int selected_accept_filter,
       struct _cef_file_dialog_callback_t* callback);
 } cef_dialog_handler_t;
 
diff --git a/src/include/capi/cef_display_handler_capi.h b/src/include/capi/cef_display_handler_capi.h
index d74f4a2..2b53b98 100644
--- a/src/include/capi/cef_display_handler_capi.h
+++ b/src/include/capi/cef_display_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=951c936c8070dbf9bd246cc766b81cdfe06a3d81$
+// $hash=5374127458a7cac3ee9b4d2b4ad8a6f5ca81ec52$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_DISPLAY_HANDLER_CAPI_H_
@@ -49,17 +49,17 @@
 #endif
 
 ///
-// Implement this structure to handle events related to browser display state.
-// The functions of this structure will be called on the UI thread.
+/// Implement this structure to handle events related to browser display state.
+/// The functions of this structure will be called on the UI thread.
 ///
 typedef struct _cef_display_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called when a frame's address has changed.
+  /// Called when a frame's address has changed.
   ///
   void(CEF_CALLBACK* on_address_change)(struct _cef_display_handler_t* self,
                                         struct _cef_browser_t* browser,
@@ -67,25 +67,30 @@
                                         const cef_string_t* url);
 
   ///
-  // Called when the page title changes.
+  /// Called when the page title changes.
   ///
   void(CEF_CALLBACK* on_title_change)(struct _cef_display_handler_t* self,
                                       struct _cef_browser_t* browser,
                                       const cef_string_t* title);
 
   ///
-  // Called when the page icon changes.
+  /// Called when the page icon changes.
   ///
   void(CEF_CALLBACK* on_favicon_urlchange)(struct _cef_display_handler_t* self,
                                            struct _cef_browser_t* browser,
                                            cef_string_list_t icon_urls);
 
   ///
-  // Called when web content in the page has toggled fullscreen mode. If
-  // |fullscreen| is true (1) the content will automatically be sized to fill
-  // the browser content area. If |fullscreen| is false (0) the content will
-  // automatically return to its original size and position. The client is
-  // responsible for resizing the browser if desired.
+  /// Called when web content in the page has toggled fullscreen mode. If
+  /// |fullscreen| is true (1) the content will automatically be sized to fill
+  /// the browser content area. If |fullscreen| is false (0) the content will
+  /// automatically return to its original size and position. With the Alloy
+  /// runtime the client is responsible for triggering the fullscreen transition
+  /// (for example, by calling cef_window_t::SetFullscreen when using Views).
+  /// With the Chrome runtime the fullscreen transition will be triggered
+  /// automatically. The cef_window_delegate_t::OnWindowFullscreenTransition
+  /// function will be called during the fullscreen transition for notification
+  /// purposes.
   ///
   void(CEF_CALLBACK* on_fullscreen_mode_change)(
       struct _cef_display_handler_t* self,
@@ -93,28 +98,28 @@
       int fullscreen);
 
   ///
-  // Called when the browser is about to display a tooltip. |text| contains the
-  // text that will be displayed in the tooltip. To handle the display of the
-  // tooltip yourself return true (1). Otherwise, you can optionally modify
-  // |text| and then return false (0) to allow the browser to display the
-  // tooltip. When window rendering is disabled the application is responsible
-  // for drawing tooltips and the return value is ignored.
+  /// Called when the browser is about to display a tooltip. |text| contains the
+  /// text that will be displayed in the tooltip. To handle the display of the
+  /// tooltip yourself return true (1). Otherwise, you can optionally modify
+  /// |text| and then return false (0) to allow the browser to display the
+  /// tooltip. When window rendering is disabled the application is responsible
+  /// for drawing tooltips and the return value is ignored.
   ///
   int(CEF_CALLBACK* on_tooltip)(struct _cef_display_handler_t* self,
                                 struct _cef_browser_t* browser,
                                 cef_string_t* text);
 
   ///
-  // Called when the browser receives a status message. |value| contains the
-  // text that will be displayed in the status message.
+  /// Called when the browser receives a status message. |value| contains the
+  /// text that will be displayed in the status message.
   ///
   void(CEF_CALLBACK* on_status_message)(struct _cef_display_handler_t* self,
                                         struct _cef_browser_t* browser,
                                         const cef_string_t* value);
 
   ///
-  // Called to display a console message. Return true (1) to stop the message
-  // from being output to the console.
+  /// Called to display a console message. Return true (1) to stop the message
+  /// from being output to the console.
   ///
   int(CEF_CALLBACK* on_console_message)(struct _cef_display_handler_t* self,
                                         struct _cef_browser_t* browser,
@@ -124,23 +129,46 @@
                                         int line);
 
   ///
-  // Called when auto-resize is enabled via
-  // cef_browser_host_t::SetAutoResizeEnabled and the contents have auto-
-  // resized. |new_size| will be the desired size in view coordinates. Return
-  // true (1) if the resize was handled or false (0) for default handling.
+  /// Called when auto-resize is enabled via
+  /// cef_browser_host_t::SetAutoResizeEnabled and the contents have auto-
+  /// resized. |new_size| will be the desired size in view coordinates. Return
+  /// true (1) if the resize was handled or false (0) for default handling.
   ///
   int(CEF_CALLBACK* on_auto_resize)(struct _cef_display_handler_t* self,
                                     struct _cef_browser_t* browser,
                                     const cef_size_t* new_size);
 
   ///
-  // Called when the overall page loading progress has changed. |progress|
-  // ranges from 0.0 to 1.0.
+  /// Called when the overall page loading progress has changed. |progress|
+  /// ranges from 0.0 to 1.0.
   ///
   void(CEF_CALLBACK* on_loading_progress_change)(
       struct _cef_display_handler_t* self,
       struct _cef_browser_t* browser,
       double progress);
+
+  ///
+  /// Called when the browser's cursor has changed. If |type| is CT_CUSTOM then
+  /// |custom_cursor_info| will be populated with the custom cursor information.
+  /// Return true (1) if the cursor change was handled or false (0) for default
+  /// handling.
+  ///
+  int(CEF_CALLBACK* on_cursor_change)(
+      struct _cef_display_handler_t* self,
+      struct _cef_browser_t* browser,
+      cef_cursor_handle_t cursor,
+      cef_cursor_type_t type,
+      const cef_cursor_info_t* custom_cursor_info);
+
+  ///
+  /// Called when the browser's access to an audio and/or video source has
+  /// changed.
+  ///
+  void(CEF_CALLBACK* on_media_access_change)(
+      struct _cef_display_handler_t* self,
+      struct _cef_browser_t* browser,
+      int has_video_access,
+      int has_audio_access);
 } cef_display_handler_t;
 
 #ifdef __cplusplus
diff --git a/src/include/capi/cef_dom_capi.h b/src/include/capi/cef_dom_capi.h
index 54122f4..3c15aef 100644
--- a/src/include/capi/cef_dom_capi.h
+++ b/src/include/capi/cef_dom_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=055c506e7950abba3ec1c12adbbb1a9989cf5ac5$
+// $hash=f18407bec715e682d5745aeb155a0113473723dd$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_DOM_CAPI_H_
@@ -50,120 +50,120 @@
 struct _cef_domnode_t;
 
 ///
-// Structure to implement for visiting the DOM. The functions of this structure
-// will be called on the render process main thread.
+/// Structure to implement for visiting the DOM. The functions of this structure
+/// will be called on the render process main thread.
 ///
 typedef struct _cef_domvisitor_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Method executed for visiting the DOM. The document object passed to this
-  // function represents a snapshot of the DOM at the time this function is
-  // executed. DOM objects are only valid for the scope of this function. Do not
-  // keep references to or attempt to access any DOM objects outside the scope
-  // of this function.
+  /// Method executed for visiting the DOM. The document object passed to this
+  /// function represents a snapshot of the DOM at the time this function is
+  /// executed. DOM objects are only valid for the scope of this function. Do
+  /// not keep references to or attempt to access any DOM objects outside the
+  /// scope of this function.
   ///
   void(CEF_CALLBACK* visit)(struct _cef_domvisitor_t* self,
                             struct _cef_domdocument_t* document);
 } cef_domvisitor_t;
 
 ///
-// Structure used to represent a DOM document. The functions of this structure
-// should only be called on the render process main thread thread.
+/// Structure used to represent a DOM document. The functions of this structure
+/// should only be called on the render process main thread thread.
 ///
 typedef struct _cef_domdocument_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the document type.
+  /// Returns the document type.
   ///
   cef_dom_document_type_t(CEF_CALLBACK* get_type)(
       struct _cef_domdocument_t* self);
 
   ///
-  // Returns the root document node.
+  /// Returns the root document node.
   ///
   struct _cef_domnode_t*(CEF_CALLBACK* get_document)(
       struct _cef_domdocument_t* self);
 
   ///
-  // Returns the BODY node of an HTML document.
+  /// Returns the BODY node of an HTML document.
   ///
   struct _cef_domnode_t*(CEF_CALLBACK* get_body)(
       struct _cef_domdocument_t* self);
 
   ///
-  // Returns the HEAD node of an HTML document.
+  /// Returns the HEAD node of an HTML document.
   ///
   struct _cef_domnode_t*(CEF_CALLBACK* get_head)(
       struct _cef_domdocument_t* self);
 
   ///
-  // Returns the title of an HTML document.
+  /// Returns the title of an HTML document.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_title)(
       struct _cef_domdocument_t* self);
 
   ///
-  // Returns the document element with the specified ID value.
+  /// Returns the document element with the specified ID value.
   ///
   struct _cef_domnode_t*(CEF_CALLBACK* get_element_by_id)(
       struct _cef_domdocument_t* self,
       const cef_string_t* id);
 
   ///
-  // Returns the node that currently has keyboard focus.
+  /// Returns the node that currently has keyboard focus.
   ///
   struct _cef_domnode_t*(CEF_CALLBACK* get_focused_node)(
       struct _cef_domdocument_t* self);
 
   ///
-  // Returns true (1) if a portion of the document is selected.
+  /// Returns true (1) if a portion of the document is selected.
   ///
   int(CEF_CALLBACK* has_selection)(struct _cef_domdocument_t* self);
 
   ///
-  // Returns the selection offset within the start node.
+  /// Returns the selection offset within the start node.
   ///
   int(CEF_CALLBACK* get_selection_start_offset)(
       struct _cef_domdocument_t* self);
 
   ///
-  // Returns the selection offset within the end node.
+  /// Returns the selection offset within the end node.
   ///
   int(CEF_CALLBACK* get_selection_end_offset)(struct _cef_domdocument_t* self);
 
   ///
-  // Returns the contents of this selection as markup.
+  /// Returns the contents of this selection as markup.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_selection_as_markup)(
       struct _cef_domdocument_t* self);
 
   ///
-  // Returns the contents of this selection as text.
+  /// Returns the contents of this selection as text.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_selection_as_text)(
       struct _cef_domdocument_t* self);
 
   ///
-  // Returns the base URL for the document.
+  /// Returns the base URL for the document.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_base_url)(
       struct _cef_domdocument_t* self);
 
   ///
-  // Returns a complete URL based on the document base URL and the specified
-  // partial URL.
+  /// Returns a complete URL based on the document base URL and the specified
+  /// partial URL.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_complete_url)(
@@ -172,141 +172,138 @@
 } cef_domdocument_t;
 
 ///
-// Structure used to represent a DOM node. The functions of this structure
-// should only be called on the render process main thread.
+/// Structure used to represent a DOM node. The functions of this structure
+/// should only be called on the render process main thread.
 ///
 typedef struct _cef_domnode_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the type for this node.
+  /// Returns the type for this node.
   ///
   cef_dom_node_type_t(CEF_CALLBACK* get_type)(struct _cef_domnode_t* self);
 
   ///
-  // Returns true (1) if this is a text node.
+  /// Returns true (1) if this is a text node.
   ///
   int(CEF_CALLBACK* is_text)(struct _cef_domnode_t* self);
 
   ///
-  // Returns true (1) if this is an element node.
+  /// Returns true (1) if this is an element node.
   ///
   int(CEF_CALLBACK* is_element)(struct _cef_domnode_t* self);
 
   ///
-  // Returns true (1) if this is an editable node.
+  /// Returns true (1) if this is an editable node.
   ///
   int(CEF_CALLBACK* is_editable)(struct _cef_domnode_t* self);
 
   ///
-  // Returns true (1) if this is a form control element node.
+  /// Returns true (1) if this is a form control element node.
   ///
   int(CEF_CALLBACK* is_form_control_element)(struct _cef_domnode_t* self);
 
   ///
-  // Returns the type of this form control element node.
+  /// Returns the type of this form control element node.
   ///
-  // The resulting string must be freed by calling cef_string_userfree_free().
-  cef_string_userfree_t(CEF_CALLBACK* get_form_control_element_type)(
+  cef_dom_form_control_type_t(CEF_CALLBACK* get_form_control_element_type)(
       struct _cef_domnode_t* self);
 
   ///
-  // Returns true (1) if this object is pointing to the same handle as |that|
-  // object.
+  /// Returns true (1) if this object is pointing to the same handle as |that|
+  /// object.
   ///
   int(CEF_CALLBACK* is_same)(struct _cef_domnode_t* self,
                              struct _cef_domnode_t* that);
 
   ///
-  // Returns the name of this node.
+  /// Returns the name of this node.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_name)(struct _cef_domnode_t* self);
 
   ///
-  // Returns the value of this node.
+  /// Returns the value of this node.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_value)(struct _cef_domnode_t* self);
 
   ///
-  // Set the value of this node. Returns true (1) on success.
+  /// Set the value of this node. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* set_value)(struct _cef_domnode_t* self,
                                const cef_string_t* value);
 
   ///
-  // Returns the contents of this node as markup.
+  /// Returns the contents of this node as markup.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_as_markup)(
       struct _cef_domnode_t* self);
 
   ///
-  // Returns the document associated with this node.
+  /// Returns the document associated with this node.
   ///
   struct _cef_domdocument_t*(CEF_CALLBACK* get_document)(
       struct _cef_domnode_t* self);
 
   ///
-  // Returns the parent node.
+  /// Returns the parent node.
   ///
   struct _cef_domnode_t*(CEF_CALLBACK* get_parent)(struct _cef_domnode_t* self);
 
   ///
-  // Returns the previous sibling node.
+  /// Returns the previous sibling node.
   ///
   struct _cef_domnode_t*(CEF_CALLBACK* get_previous_sibling)(
       struct _cef_domnode_t* self);
 
   ///
-  // Returns the next sibling node.
+  /// Returns the next sibling node.
   ///
   struct _cef_domnode_t*(CEF_CALLBACK* get_next_sibling)(
       struct _cef_domnode_t* self);
 
   ///
-  // Returns true (1) if this node has child nodes.
+  /// Returns true (1) if this node has child nodes.
   ///
   int(CEF_CALLBACK* has_children)(struct _cef_domnode_t* self);
 
   ///
-  // Return the first child node.
+  /// Return the first child node.
   ///
   struct _cef_domnode_t*(CEF_CALLBACK* get_first_child)(
       struct _cef_domnode_t* self);
 
   ///
-  // Returns the last child node.
+  /// Returns the last child node.
   ///
   struct _cef_domnode_t*(CEF_CALLBACK* get_last_child)(
       struct _cef_domnode_t* self);
 
-  // The following functions are valid only for element nodes.
-
   ///
-  // Returns the tag name of this element.
+  /// Returns the tag name of this element.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_element_tag_name)(
       struct _cef_domnode_t* self);
 
   ///
-  // Returns true (1) if this element has attributes.
+  /// Returns true (1) if this element has attributes.
   ///
   int(CEF_CALLBACK* has_element_attributes)(struct _cef_domnode_t* self);
 
   ///
-  // Returns true (1) if this element has an attribute named |attrName|.
+  /// Returns true (1) if this element has an attribute named |attrName|.
   ///
   int(CEF_CALLBACK* has_element_attribute)(struct _cef_domnode_t* self,
                                            const cef_string_t* attrName);
 
   ///
-  // Returns the element attribute named |attrName|.
+  /// Returns the element attribute named |attrName|.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_element_attribute)(
@@ -314,28 +311,29 @@
       const cef_string_t* attrName);
 
   ///
-  // Returns a map of all element attributes.
+  /// Returns a map of all element attributes.
   ///
   void(CEF_CALLBACK* get_element_attributes)(struct _cef_domnode_t* self,
                                              cef_string_map_t attrMap);
 
   ///
-  // Set the value for the element attribute named |attrName|. Returns true (1)
-  // on success.
+  /// Set the value for the element attribute named |attrName|. Returns true (1)
+  /// on success.
   ///
   int(CEF_CALLBACK* set_element_attribute)(struct _cef_domnode_t* self,
                                            const cef_string_t* attrName,
                                            const cef_string_t* value);
 
   ///
-  // Returns the inner text of the element.
+  /// Returns the inner text of the element.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_element_inner_text)(
       struct _cef_domnode_t* self);
 
   ///
-  // Returns the bounds of the element.
+  /// Returns the bounds of the element in device pixels. Use
+  /// "window.devicePixelRatio" to convert to/from CSS pixels.
   ///
   cef_rect_t(CEF_CALLBACK* get_element_bounds)(struct _cef_domnode_t* self);
 } cef_domnode_t;
diff --git a/src/include/capi/cef_download_handler_capi.h b/src/include/capi/cef_download_handler_capi.h
index bc57341..5979513 100644
--- a/src/include/capi/cef_download_handler_capi.h
+++ b/src/include/capi/cef_download_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=3399f17cc69d8fbd5c09f63f81680aa1f68454f0$
+// $hash=f1f6a110a7ce15611a7062b3d7fe8b5c630f2980$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_DOWNLOAD_HANDLER_CAPI_H_
@@ -49,19 +49,19 @@
 #endif
 
 ///
-// Callback structure used to asynchronously continue a download.
+/// Callback structure used to asynchronously continue a download.
 ///
 typedef struct _cef_before_download_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Call to continue the download. Set |download_path| to the full file path
-  // for the download including the file name or leave blank to use the
-  // suggested name and the default temp directory. Set |show_dialog| to true
-  // (1) if you do wish to show the default "Save As" dialog.
+  /// Call to continue the download. Set |download_path| to the full file path
+  /// for the download including the file name or leave blank to use the
+  /// suggested name and the default temp directory. Set |show_dialog| to true
+  /// (1) if you do wish to show the default "Save As" dialog.
   ///
   void(CEF_CALLBACK* cont)(struct _cef_before_download_callback_t* self,
                            const cef_string_t* download_path,
@@ -69,46 +69,58 @@
 } cef_before_download_callback_t;
 
 ///
-// Callback structure used to asynchronously cancel a download.
+/// Callback structure used to asynchronously cancel a download.
 ///
 typedef struct _cef_download_item_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Call to cancel the download.
+  /// Call to cancel the download.
   ///
   void(CEF_CALLBACK* cancel)(struct _cef_download_item_callback_t* self);
 
   ///
-  // Call to pause the download.
+  /// Call to pause the download.
   ///
   void(CEF_CALLBACK* pause)(struct _cef_download_item_callback_t* self);
 
   ///
-  // Call to resume the download.
+  /// Call to resume the download.
   ///
   void(CEF_CALLBACK* resume)(struct _cef_download_item_callback_t* self);
 } cef_download_item_callback_t;
 
 ///
-// Structure used to handle file downloads. The functions of this structure will
-// called on the browser process UI thread.
+/// Structure used to handle file downloads. The functions of this structure
+/// will called on the browser process UI thread.
 ///
 typedef struct _cef_download_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called before a download begins. |suggested_name| is the suggested name for
-  // the download file. By default the download will be canceled. Execute
-  // |callback| either asynchronously or in this function to continue the
-  // download if desired. Do not keep a reference to |download_item| outside of
-  // this function.
+  /// Called before a download begins in response to a user-initiated action
+  /// (e.g. alt + link click or link click that returns a `Content-Disposition:
+  /// attachment` response from the server). |url| is the target download URL
+  /// and |request_function| is the target function (GET, POST, etc). Return
+  /// true (1) to proceed with the download or false (0) to cancel the download.
+  ///
+  int(CEF_CALLBACK* can_download)(struct _cef_download_handler_t* self,
+                                  struct _cef_browser_t* browser,
+                                  const cef_string_t* url,
+                                  const cef_string_t* request_method);
+
+  ///
+  /// Called before a download begins. |suggested_name| is the suggested name
+  /// for the download file. By default the download will be canceled. Execute
+  /// |callback| either asynchronously or in this function to continue the
+  /// download if desired. Do not keep a reference to |download_item| outside of
+  /// this function.
   ///
   void(CEF_CALLBACK* on_before_download)(
       struct _cef_download_handler_t* self,
@@ -118,11 +130,11 @@
       struct _cef_before_download_callback_t* callback);
 
   ///
-  // Called when a download's status or progress information has been updated.
-  // This may be called multiple times before and after on_before_download().
-  // Execute |callback| either asynchronously or in this function to cancel the
-  // download if desired. Do not keep a reference to |download_item| outside of
-  // this function.
+  /// Called when a download's status or progress information has been updated.
+  /// This may be called multiple times before and after on_before_download().
+  /// Execute |callback| either asynchronously or in this function to cancel the
+  /// download if desired. Do not keep a reference to |download_item| outside of
+  /// this function.
   ///
   void(CEF_CALLBACK* on_download_updated)(
       struct _cef_download_handler_t* self,
diff --git a/src/include/capi/cef_download_item_capi.h b/src/include/capi/cef_download_item_capi.h
index e422cc1..059d962 100644
--- a/src/include/capi/cef_download_item_capi.h
+++ b/src/include/capi/cef_download_item_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=d6366977af5e2a3a71b4f57042208ff7ed524c6c$
+// $hash=c4ecfde5d6791400c4b3fd466e7d3676d51cf8d8$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_DOWNLOAD_ITEM_CAPI_H_
@@ -47,108 +47,120 @@
 #endif
 
 ///
-// Structure used to represent a download item.
+/// Structure used to represent a download item.
 ///
 typedef struct _cef_download_item_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if this object is valid. Do not call any other functions
-  // if this function returns false (0).
+  /// Returns true (1) if this object is valid. Do not call any other functions
+  /// if this function returns false (0).
   ///
   int(CEF_CALLBACK* is_valid)(struct _cef_download_item_t* self);
 
   ///
-  // Returns true (1) if the download is in progress.
+  /// Returns true (1) if the download is in progress.
   ///
   int(CEF_CALLBACK* is_in_progress)(struct _cef_download_item_t* self);
 
   ///
-  // Returns true (1) if the download is complete.
+  /// Returns true (1) if the download is complete.
   ///
   int(CEF_CALLBACK* is_complete)(struct _cef_download_item_t* self);
 
   ///
-  // Returns true (1) if the download has been canceled or interrupted.
+  /// Returns true (1) if the download has been canceled.
   ///
   int(CEF_CALLBACK* is_canceled)(struct _cef_download_item_t* self);
 
   ///
-  // Returns a simple speed estimate in bytes/s.
+  /// Returns true (1) if the download has been interrupted.
   ///
-  int64(CEF_CALLBACK* get_current_speed)(struct _cef_download_item_t* self);
+  int(CEF_CALLBACK* is_interrupted)(struct _cef_download_item_t* self);
 
   ///
-  // Returns the rough percent complete or -1 if the receive total size is
-  // unknown.
+  /// Returns the most recent interrupt reason.
+  ///
+  cef_download_interrupt_reason_t(CEF_CALLBACK* get_interrupt_reason)(
+      struct _cef_download_item_t* self);
+
+  ///
+  /// Returns a simple speed estimate in bytes/s.
+  ///
+  int64_t(CEF_CALLBACK* get_current_speed)(struct _cef_download_item_t* self);
+
+  ///
+  /// Returns the rough percent complete or -1 if the receive total size is
+  /// unknown.
   ///
   int(CEF_CALLBACK* get_percent_complete)(struct _cef_download_item_t* self);
 
   ///
-  // Returns the total number of bytes.
+  /// Returns the total number of bytes.
   ///
-  int64(CEF_CALLBACK* get_total_bytes)(struct _cef_download_item_t* self);
+  int64_t(CEF_CALLBACK* get_total_bytes)(struct _cef_download_item_t* self);
 
   ///
-  // Returns the number of received bytes.
+  /// Returns the number of received bytes.
   ///
-  int64(CEF_CALLBACK* get_received_bytes)(struct _cef_download_item_t* self);
+  int64_t(CEF_CALLBACK* get_received_bytes)(struct _cef_download_item_t* self);
 
   ///
-  // Returns the time that the download started.
+  /// Returns the time that the download started.
   ///
-  cef_time_t(CEF_CALLBACK* get_start_time)(struct _cef_download_item_t* self);
+  cef_basetime_t(CEF_CALLBACK* get_start_time)(
+      struct _cef_download_item_t* self);
 
   ///
-  // Returns the time that the download ended.
+  /// Returns the time that the download ended.
   ///
-  cef_time_t(CEF_CALLBACK* get_end_time)(struct _cef_download_item_t* self);
+  cef_basetime_t(CEF_CALLBACK* get_end_time)(struct _cef_download_item_t* self);
 
   ///
-  // Returns the full path to the downloaded or downloading file.
+  /// Returns the full path to the downloaded or downloading file.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_full_path)(
       struct _cef_download_item_t* self);
 
   ///
-  // Returns the unique identifier for this download.
+  /// Returns the unique identifier for this download.
   ///
-  uint32(CEF_CALLBACK* get_id)(struct _cef_download_item_t* self);
+  uint32_t(CEF_CALLBACK* get_id)(struct _cef_download_item_t* self);
 
   ///
-  // Returns the URL.
+  /// Returns the URL.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_url)(
       struct _cef_download_item_t* self);
 
   ///
-  // Returns the original URL before any redirections.
+  /// Returns the original URL before any redirections.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_original_url)(
       struct _cef_download_item_t* self);
 
   ///
-  // Returns the suggested file name.
+  /// Returns the suggested file name.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_suggested_file_name)(
       struct _cef_download_item_t* self);
 
   ///
-  // Returns the content disposition.
+  /// Returns the content disposition.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_content_disposition)(
       struct _cef_download_item_t* self);
 
   ///
-  // Returns the mime type.
+  /// Returns the mime type.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_mime_type)(
diff --git a/src/include/capi/cef_drag_data_capi.h b/src/include/capi/cef_drag_data_capi.h
index e181709..59ae13b 100644
--- a/src/include/capi/cef_drag_data_capi.h
+++ b/src/include/capi/cef_drag_data_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=6c8c654be3e69d872b3cfa6bdfb1adf615bff3ac$
+// $hash=8d00465ba004758f464cdb8b1fbd02cd26323ace$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_DRAG_DATA_CAPI_H_
@@ -49,177 +49,189 @@
 #endif
 
 ///
-// Structure used to represent drag data. The functions of this structure may be
-// called on any thread.
+/// Structure used to represent drag data. The functions of this structure may
+/// be called on any thread.
 ///
 typedef struct _cef_drag_data_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns a copy of the current object.
+  /// Returns a copy of the current object.
   ///
   struct _cef_drag_data_t*(CEF_CALLBACK* clone)(struct _cef_drag_data_t* self);
 
   ///
-  // Returns true (1) if this object is read-only.
+  /// Returns true (1) if this object is read-only.
   ///
   int(CEF_CALLBACK* is_read_only)(struct _cef_drag_data_t* self);
 
   ///
-  // Returns true (1) if the drag data is a link.
+  /// Returns true (1) if the drag data is a link.
   ///
   int(CEF_CALLBACK* is_link)(struct _cef_drag_data_t* self);
 
   ///
-  // Returns true (1) if the drag data is a text or html fragment.
+  /// Returns true (1) if the drag data is a text or html fragment.
   ///
   int(CEF_CALLBACK* is_fragment)(struct _cef_drag_data_t* self);
 
   ///
-  // Returns true (1) if the drag data is a file.
+  /// Returns true (1) if the drag data is a file.
   ///
   int(CEF_CALLBACK* is_file)(struct _cef_drag_data_t* self);
 
   ///
-  // Return the link URL that is being dragged.
+  /// Return the link URL that is being dragged.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_link_url)(
       struct _cef_drag_data_t* self);
 
   ///
-  // Return the title associated with the link being dragged.
+  /// Return the title associated with the link being dragged.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_link_title)(
       struct _cef_drag_data_t* self);
 
   ///
-  // Return the metadata, if any, associated with the link being dragged.
+  /// Return the metadata, if any, associated with the link being dragged.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_link_metadata)(
       struct _cef_drag_data_t* self);
 
   ///
-  // Return the plain text fragment that is being dragged.
+  /// Return the plain text fragment that is being dragged.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_fragment_text)(
       struct _cef_drag_data_t* self);
 
   ///
-  // Return the text/html fragment that is being dragged.
+  /// Return the text/html fragment that is being dragged.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_fragment_html)(
       struct _cef_drag_data_t* self);
 
   ///
-  // Return the base URL that the fragment came from. This value is used for
-  // resolving relative URLs and may be NULL.
+  /// Return the base URL that the fragment came from. This value is used for
+  /// resolving relative URLs and may be NULL.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_fragment_base_url)(
       struct _cef_drag_data_t* self);
 
   ///
-  // Return the name of the file being dragged out of the browser window.
+  /// Return the name of the file being dragged out of the browser window.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_file_name)(
       struct _cef_drag_data_t* self);
 
   ///
-  // Write the contents of the file being dragged out of the web view into
-  // |writer|. Returns the number of bytes sent to |writer|. If |writer| is NULL
-  // this function will return the size of the file contents in bytes. Call
-  // get_file_name() to get a suggested name for the file.
+  /// Write the contents of the file being dragged out of the web view into
+  /// |writer|. Returns the number of bytes sent to |writer|. If |writer| is
+  /// NULL this function will return the size of the file contents in bytes.
+  /// Call get_file_name() to get a suggested name for the file.
   ///
   size_t(CEF_CALLBACK* get_file_contents)(struct _cef_drag_data_t* self,
                                           struct _cef_stream_writer_t* writer);
 
   ///
-  // Retrieve the list of file names that are being dragged into the browser
-  // window.
+  /// Retrieve the list of file names that are being dragged into the browser
+  /// window.
   ///
   int(CEF_CALLBACK* get_file_names)(struct _cef_drag_data_t* self,
                                     cef_string_list_t names);
 
   ///
-  // Set the link URL that is being dragged.
+  /// Retrieve the list of file paths that are being dragged into the browser
+  /// window.
+  ///
+  int(CEF_CALLBACK* get_file_paths)(struct _cef_drag_data_t* self,
+                                    cef_string_list_t paths);
+
+  ///
+  /// Set the link URL that is being dragged.
   ///
   void(CEF_CALLBACK* set_link_url)(struct _cef_drag_data_t* self,
                                    const cef_string_t* url);
 
   ///
-  // Set the title associated with the link being dragged.
+  /// Set the title associated with the link being dragged.
   ///
   void(CEF_CALLBACK* set_link_title)(struct _cef_drag_data_t* self,
                                      const cef_string_t* title);
 
   ///
-  // Set the metadata associated with the link being dragged.
+  /// Set the metadata associated with the link being dragged.
   ///
   void(CEF_CALLBACK* set_link_metadata)(struct _cef_drag_data_t* self,
                                         const cef_string_t* data);
 
   ///
-  // Set the plain text fragment that is being dragged.
+  /// Set the plain text fragment that is being dragged.
   ///
   void(CEF_CALLBACK* set_fragment_text)(struct _cef_drag_data_t* self,
                                         const cef_string_t* text);
 
   ///
-  // Set the text/html fragment that is being dragged.
+  /// Set the text/html fragment that is being dragged.
   ///
   void(CEF_CALLBACK* set_fragment_html)(struct _cef_drag_data_t* self,
                                         const cef_string_t* html);
 
   ///
-  // Set the base URL that the fragment came from.
+  /// Set the base URL that the fragment came from.
   ///
   void(CEF_CALLBACK* set_fragment_base_url)(struct _cef_drag_data_t* self,
                                             const cef_string_t* base_url);
 
   ///
-  // Reset the file contents. You should do this before calling
-  // cef_browser_host_t::DragTargetDragEnter as the web view does not allow us
-  // to drag in this kind of data.
+  /// Reset the file contents. You should do this before calling
+  /// cef_browser_host_t::DragTargetDragEnter as the web view does not allow us
+  /// to drag in this kind of data.
   ///
   void(CEF_CALLBACK* reset_file_contents)(struct _cef_drag_data_t* self);
 
   ///
-  // Add a file that is being dragged into the webview.
+  /// Add a file that is being dragged into the webview.
   ///
   void(CEF_CALLBACK* add_file)(struct _cef_drag_data_t* self,
                                const cef_string_t* path,
                                const cef_string_t* display_name);
 
   ///
-  // Get the image representation of drag data. May return NULL if no image
-  // representation is available.
+  /// Clear list of filenames.
+  ///
+  void(CEF_CALLBACK* clear_filenames)(struct _cef_drag_data_t* self);
+
+  ///
+  /// Get the image representation of drag data. May return NULL if no image
+  /// representation is available.
   ///
   struct _cef_image_t*(CEF_CALLBACK* get_image)(struct _cef_drag_data_t* self);
 
   ///
-  // Get the image hotspot (drag start location relative to image dimensions).
+  /// Get the image hotspot (drag start location relative to image dimensions).
   ///
   cef_point_t(CEF_CALLBACK* get_image_hotspot)(struct _cef_drag_data_t* self);
 
   ///
-  // Returns true (1) if an image representation of drag data is available.
+  /// Returns true (1) if an image representation of drag data is available.
   ///
   int(CEF_CALLBACK* has_image)(struct _cef_drag_data_t* self);
 } cef_drag_data_t;
 
 ///
-// Create a new cef_drag_data_t object.
+/// Create a new cef_drag_data_t object.
 ///
-CEF_EXPORT cef_drag_data_t* cef_drag_data_create();
+CEF_EXPORT cef_drag_data_t* cef_drag_data_create(void);
 
 #ifdef __cplusplus
 }
diff --git a/src/include/capi/cef_drag_handler_capi.h b/src/include/capi/cef_drag_handler_capi.h
index 7a6430e..a5023e0 100644
--- a/src/include/capi/cef_drag_handler_capi.h
+++ b/src/include/capi/cef_drag_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=78022908355fbf836799545e67ce2e4663b85fdf$
+// $hash=ad16b0f4320d7b363efb152a65e3ce142882b9d9$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_DRAG_HANDLER_CAPI_H_
@@ -50,20 +50,20 @@
 #endif
 
 ///
-// Implement this structure to handle events related to dragging. The functions
-// of this structure will be called on the UI thread.
+/// Implement this structure to handle events related to dragging. The functions
+/// of this structure will be called on the UI thread.
 ///
 typedef struct _cef_drag_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called when an external drag event enters the browser window. |dragData|
-  // contains the drag event data and |mask| represents the type of drag
-  // operation. Return false (0) for default drag handling behavior or true (1)
-  // to cancel the drag event.
+  /// Called when an external drag event enters the browser window. |dragData|
+  /// contains the drag event data and |mask| represents the type of drag
+  /// operation. Return false (0) for default drag handling behavior or true (1)
+  /// to cancel the drag event.
   ///
   int(CEF_CALLBACK* on_drag_enter)(struct _cef_drag_handler_t* self,
                                    struct _cef_browser_t* browser,
@@ -71,11 +71,11 @@
                                    cef_drag_operations_mask_t mask);
 
   ///
-  // Called whenever draggable regions for the browser window change. These can
-  // be specified using the '-webkit-app-region: drag/no-drag' CSS-property. If
-  // draggable regions are never defined in a document this function will also
-  // never be called. If the last draggable region is removed from a document
-  // this function will be called with an NULL vector.
+  /// Called whenever draggable regions for the browser window change. These can
+  /// be specified using the '-webkit-app-region: drag/no-drag' CSS-property. If
+  /// draggable regions are never defined in a document this function will also
+  /// never be called. If the last draggable region is removed from a document
+  /// this function will be called with an NULL vector.
   ///
   void(CEF_CALLBACK* on_draggable_regions_changed)(
       struct _cef_drag_handler_t* self,
diff --git a/src/include/capi/cef_extension_capi.h b/src/include/capi/cef_extension_capi.h
index ccef427..a945b9b 100644
--- a/src/include/capi/cef_extension_capi.h
+++ b/src/include/capi/cef_extension_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=b50087959cb679e4132f0fccfd23f01f76079018$
+// $hash=c81a74622b987483e5fcd2c508aec5c13e12389b$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_EXTENSION_CAPI_H_
@@ -51,74 +51,74 @@
 struct _cef_request_context_t;
 
 ///
-// Object representing an extension. Methods may be called on any thread unless
-// otherwise indicated.
+/// Object representing an extension. Methods may be called on any thread unless
+/// otherwise indicated.
 ///
 typedef struct _cef_extension_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the unique extension identifier. This is calculated based on the
-  // extension public key, if available, or on the extension path. See
-  // https://developer.chrome.com/extensions/manifest/key for details.
+  /// Returns the unique extension identifier. This is calculated based on the
+  /// extension public key, if available, or on the extension path. See
+  /// https://developer.chrome.com/extensions/manifest/key for details.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_identifier)(
       struct _cef_extension_t* self);
 
   ///
-  // Returns the absolute path to the extension directory on disk. This value
-  // will be prefixed with PK_DIR_RESOURCES if a relative path was passed to
-  // cef_request_context_t::LoadExtension.
+  /// Returns the absolute path to the extension directory on disk. This value
+  /// will be prefixed with PK_DIR_RESOURCES if a relative path was passed to
+  /// cef_request_context_t::LoadExtension.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_path)(struct _cef_extension_t* self);
 
   ///
-  // Returns the extension manifest contents as a cef_dictionary_value_t object.
-  // See https://developer.chrome.com/extensions/manifest for details.
+  /// Returns the extension manifest contents as a cef_dictionary_value_t
+  /// object. See https://developer.chrome.com/extensions/manifest for details.
   ///
   struct _cef_dictionary_value_t*(CEF_CALLBACK* get_manifest)(
       struct _cef_extension_t* self);
 
   ///
-  // Returns true (1) if this object is the same extension as |that| object.
-  // Extensions are considered the same if identifier, path and loader context
-  // match.
+  /// Returns true (1) if this object is the same extension as |that| object.
+  /// Extensions are considered the same if identifier, path and loader context
+  /// match.
   ///
   int(CEF_CALLBACK* is_same)(struct _cef_extension_t* self,
                              struct _cef_extension_t* that);
 
   ///
-  // Returns the handler for this extension. Will return NULL for internal
-  // extensions or if no handler was passed to
-  // cef_request_context_t::LoadExtension.
+  /// Returns the handler for this extension. Will return NULL for internal
+  /// extensions or if no handler was passed to
+  /// cef_request_context_t::LoadExtension.
   ///
   struct _cef_extension_handler_t*(CEF_CALLBACK* get_handler)(
       struct _cef_extension_t* self);
 
   ///
-  // Returns the request context that loaded this extension. Will return NULL
-  // for internal extensions or if the extension has been unloaded. See the
-  // cef_request_context_t::LoadExtension documentation for more information
-  // about loader contexts. Must be called on the browser process UI thread.
+  /// Returns the request context that loaded this extension. Will return NULL
+  /// for internal extensions or if the extension has been unloaded. See the
+  /// cef_request_context_t::LoadExtension documentation for more information
+  /// about loader contexts. Must be called on the browser process UI thread.
   ///
   struct _cef_request_context_t*(CEF_CALLBACK* get_loader_context)(
       struct _cef_extension_t* self);
 
   ///
-  // Returns true (1) if this extension is currently loaded. Must be called on
-  // the browser process UI thread.
+  /// Returns true (1) if this extension is currently loaded. Must be called on
+  /// the browser process UI thread.
   ///
   int(CEF_CALLBACK* is_loaded)(struct _cef_extension_t* self);
 
   ///
-  // Unload this extension if it is not an internal extension and is currently
-  // loaded. Will result in a call to
-  // cef_extension_handler_t::OnExtensionUnloaded on success.
+  /// Unload this extension if it is not an internal extension and is currently
+  /// loaded. Will result in a call to
+  /// cef_extension_handler_t::OnExtensionUnloaded on success.
   ///
   void(CEF_CALLBACK* unload)(struct _cef_extension_t* self);
 } cef_extension_t;
diff --git a/src/include/capi/cef_extension_handler_capi.h b/src/include/capi/cef_extension_handler_capi.h
index 4b3dfde..ab29f34 100644
--- a/src/include/capi/cef_extension_handler_capi.h
+++ b/src/include/capi/cef_extension_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=a13b5b607d5a2108fac5fe75f5ebd2ede7eaef6a$
+// $hash=ad6d3845b150f22b88a71dafa601ef01c9579824$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_EXTENSION_HANDLER_CAPI_H_
@@ -52,75 +52,76 @@
 struct _cef_client_t;
 
 ///
-// Callback structure used for asynchronous continuation of
-// cef_extension_handler_t::GetExtensionResource.
+/// Callback structure used for asynchronous continuation of
+/// cef_extension_handler_t::GetExtensionResource.
 ///
 typedef struct _cef_get_extension_resource_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Continue the request. Read the resource contents from |stream|.
+  /// Continue the request. Read the resource contents from |stream|.
   ///
   void(CEF_CALLBACK* cont)(struct _cef_get_extension_resource_callback_t* self,
                            struct _cef_stream_reader_t* stream);
 
   ///
-  // Cancel the request.
+  /// Cancel the request.
   ///
   void(CEF_CALLBACK* cancel)(
       struct _cef_get_extension_resource_callback_t* self);
 } cef_get_extension_resource_callback_t;
 
 ///
-// Implement this structure to handle events related to browser extensions. The
-// functions of this structure will be called on the UI thread. See
-// cef_request_context_t::LoadExtension for information about extension loading.
+/// Implement this structure to handle events related to browser extensions. The
+/// functions of this structure will be called on the UI thread. See
+/// cef_request_context_t::LoadExtension for information about extension
+/// loading.
 ///
 typedef struct _cef_extension_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called if the cef_request_context_t::LoadExtension request fails. |result|
-  // will be the error code.
+  /// Called if the cef_request_context_t::LoadExtension request fails. |result|
+  /// will be the error code.
   ///
   void(CEF_CALLBACK* on_extension_load_failed)(
       struct _cef_extension_handler_t* self,
       cef_errorcode_t result);
 
   ///
-  // Called if the cef_request_context_t::LoadExtension request succeeds.
-  // |extension| is the loaded extension.
+  /// Called if the cef_request_context_t::LoadExtension request succeeds.
+  /// |extension| is the loaded extension.
   ///
   void(CEF_CALLBACK* on_extension_loaded)(struct _cef_extension_handler_t* self,
                                           struct _cef_extension_t* extension);
 
   ///
-  // Called after the cef_extension_t::Unload request has completed.
+  /// Called after the cef_extension_t::Unload request has completed.
   ///
   void(CEF_CALLBACK* on_extension_unloaded)(
       struct _cef_extension_handler_t* self,
       struct _cef_extension_t* extension);
 
   ///
-  // Called when an extension needs a browser to host a background script
-  // specified via the "background" manifest key. The browser will have no
-  // visible window and cannot be displayed. |extension| is the extension that
-  // is loading the background script. |url| is an internally generated
-  // reference to an HTML page that will be used to load the background script
-  // via a <script> src attribute. To allow creation of the browser optionally
-  // modify |client| and |settings| and return false (0). To cancel creation of
-  // the browser (and consequently cancel load of the background script) return
-  // true (1). Successful creation will be indicated by a call to
-  // cef_life_span_handler_t::OnAfterCreated, and
-  // cef_browser_host_t::IsBackgroundHost will return true (1) for the resulting
-  // browser. See https://developer.chrome.com/extensions/event_pages for more
-  // information about extension background script usage.
+  /// Called when an extension needs a browser to host a background script
+  /// specified via the "background" manifest key. The browser will have no
+  /// visible window and cannot be displayed. |extension| is the extension that
+  /// is loading the background script. |url| is an internally generated
+  /// reference to an HTML page that will be used to load the background script
+  /// via a "<script>" src attribute. To allow creation of the browser
+  /// optionally modify |client| and |settings| and return false (0). To cancel
+  /// creation of the browser (and consequently cancel load of the background
+  /// script) return true (1). Successful creation will be indicated by a call
+  /// to cef_life_span_handler_t::OnAfterCreated, and
+  /// cef_browser_host_t::IsBackgroundHost will return true (1) for the
+  /// resulting browser. See https://developer.chrome.com/extensions/event_pages
+  /// for more information about extension background script usage.
   ///
   int(CEF_CALLBACK* on_before_background_browser)(
       struct _cef_extension_handler_t* self,
@@ -130,19 +131,19 @@
       struct _cef_browser_settings_t* settings);
 
   ///
-  // Called when an extension API (e.g. chrome.tabs.create) requests creation of
-  // a new browser. |extension| and |browser| are the source of the API call.
-  // |active_browser| may optionally be specified via the windowId property or
-  // returned via the get_active_browser() callback and provides the default
-  // |client| and |settings| values for the new browser. |index| is the position
-  // value optionally specified via the index property. |url| is the URL that
-  // will be loaded in the browser. |active| is true (1) if the new browser
-  // should be active when opened.  To allow creation of the browser optionally
-  // modify |windowInfo|, |client| and |settings| and return false (0). To
-  // cancel creation of the browser return true (1). Successful creation will be
-  // indicated by a call to cef_life_span_handler_t::OnAfterCreated. Any
-  // modifications to |windowInfo| will be ignored if |active_browser| is
-  // wrapped in a cef_browser_view_t.
+  /// Called when an extension API (e.g. chrome.tabs.create) requests creation
+  /// of a new browser. |extension| and |browser| are the source of the API
+  /// call. |active_browser| may optionally be specified via the windowId
+  /// property or returned via the get_active_browser() callback and provides
+  /// the default |client| and |settings| values for the new browser. |index| is
+  /// the position value optionally specified via the index property. |url| is
+  /// the URL that will be loaded in the browser. |active| is true (1) if the
+  /// new browser should be active when opened.  To allow creation of the
+  /// browser optionally modify |windowInfo|, |client| and |settings| and return
+  /// false (0). To cancel creation of the browser return true (1). Successful
+  /// creation will be indicated by a call to
+  /// cef_life_span_handler_t::OnAfterCreated. Any modifications to |windowInfo|
+  /// will be ignored if |active_browser| is wrapped in a cef_browser_view_t.
   ///
   int(CEF_CALLBACK* on_before_browser)(
       struct _cef_extension_handler_t* self,
@@ -157,13 +158,13 @@
       struct _cef_browser_settings_t* settings);
 
   ///
-  // Called when no tabId is specified to an extension API call that accepts a
-  // tabId parameter (e.g. chrome.tabs.*). |extension| and |browser| are the
-  // source of the API call. Return the browser that will be acted on by the API
-  // call or return NULL to act on |browser|. The returned browser must share
-  // the same cef_request_context_t as |browser|. Incognito browsers should not
-  // be considered unless the source extension has incognito access enabled, in
-  // which case |include_incognito| will be true (1).
+  /// Called when no tabId is specified to an extension API call that accepts a
+  /// tabId parameter (e.g. chrome.tabs.*). |extension| and |browser| are the
+  /// source of the API call. Return the browser that will be acted on by the
+  /// API call or return NULL to act on |browser|. The returned browser must
+  /// share the same cef_request_context_t as |browser|. Incognito browsers
+  /// should not be considered unless the source extension has incognito access
+  /// enabled, in which case |include_incognito| will be true (1).
   ///
   struct _cef_browser_t*(CEF_CALLBACK* get_active_browser)(
       struct _cef_extension_handler_t* self,
@@ -172,12 +173,12 @@
       int include_incognito);
 
   ///
-  // Called when the tabId associated with |target_browser| is specified to an
-  // extension API call that accepts a tabId parameter (e.g. chrome.tabs.*).
-  // |extension| and |browser| are the source of the API call. Return true (1)
-  // to allow access of false (0) to deny access. Access to incognito browsers
-  // should not be allowed unless the source extension has incognito access
-  // enabled, in which case |include_incognito| will be true (1).
+  /// Called when the tabId associated with |target_browser| is specified to an
+  /// extension API call that accepts a tabId parameter (e.g. chrome.tabs.*).
+  /// |extension| and |browser| are the source of the API call. Return true (1)
+  /// to allow access of false (0) to deny access. Access to incognito browsers
+  /// should not be allowed unless the source extension has incognito access
+  /// enabled, in which case |include_incognito| will be true (1).
   ///
   int(CEF_CALLBACK* can_access_browser)(struct _cef_extension_handler_t* self,
                                         struct _cef_extension_t* extension,
@@ -186,14 +187,15 @@
                                         struct _cef_browser_t* target_browser);
 
   ///
-  // Called to retrieve an extension resource that would normally be loaded from
-  // disk (e.g. if a file parameter is specified to chrome.tabs.executeScript).
-  // |extension| and |browser| are the source of the resource request. |file| is
-  // the requested relative file path. To handle the resource request return
-  // true (1) and execute |callback| either synchronously or asynchronously. For
-  // the default behavior which reads the resource from the extension directory
-  // on disk return false (0). Localization substitutions will not be applied to
-  // resources handled via this function.
+  /// Called to retrieve an extension resource that would normally be loaded
+  /// from disk (e.g. if a file parameter is specified to
+  /// chrome.tabs.executeScript). |extension| and |browser| are the source of
+  /// the resource request. |file| is the requested relative file path. To
+  /// handle the resource request return true (1) and execute |callback| either
+  /// synchronously or asynchronously. For the default behavior which reads the
+  /// resource from the extension directory on disk return false (0).
+  /// Localization substitutions will not be applied to resources handled via
+  /// this function.
   ///
   int(CEF_CALLBACK* get_extension_resource)(
       struct _cef_extension_handler_t* self,
diff --git a/src/include/capi/cef_file_util_capi.h b/src/include/capi/cef_file_util_capi.h
index ce603b3..daad7a5 100644
--- a/src/include/capi/cef_file_util_capi.h
+++ b/src/include/capi/cef_file_util_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=c930140791b9e7d4238110e24fe17b9566a34ec9$
+// $hash=4e0e0abcb72327998df950e618b147b196e76b60$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_FILE_UTIL_CAPI_H_
@@ -47,40 +47,40 @@
 #endif
 
 ///
-// Creates a directory and all parent directories if they don't already exist.
-// Returns true (1) on successful creation or if the directory already exists.
-// The directory is only readable by the current user. Calling this function on
-// the browser process UI or IO threads is not allowed.
+/// Creates a directory and all parent directories if they don't already exist.
+/// Returns true (1) on successful creation or if the directory already exists.
+/// The directory is only readable by the current user. Calling this function on
+/// the browser process UI or IO threads is not allowed.
 ///
 CEF_EXPORT int cef_create_directory(const cef_string_t* full_path);
 
 ///
-// Get the temporary directory provided by the system.
-//
-// WARNING: In general, you should use the temp directory variants below instead
-// of this function. Those variants will ensure that the proper permissions are
-// set so that other users on the system can't edit them while they're open
-// (which could lead to security issues).
+/// Get the temporary directory provided by the system.
+///
+/// WARNING: In general, you should use the temp directory variants below
+/// instead of this function. Those variants will ensure that the proper
+/// permissions are set so that other users on the system can't edit them while
+/// they're open (which could lead to security issues).
 ///
 CEF_EXPORT int cef_get_temp_directory(cef_string_t* temp_dir);
 
 ///
-// Creates a new directory. On Windows if |prefix| is provided the new directory
-// name is in the format of "prefixyyyy". Returns true (1) on success and sets
-// |new_temp_path| to the full path of the directory that was created. The
-// directory is only readable by the current user. Calling this function on the
-// browser process UI or IO threads is not allowed.
+/// Creates a new directory. On Windows if |prefix| is provided the new
+/// directory name is in the format of "prefixyyyy". Returns true (1) on success
+/// and sets |new_temp_path| to the full path of the directory that was created.
+/// The directory is only readable by the current user. Calling this function on
+/// the browser process UI or IO threads is not allowed.
 ///
 CEF_EXPORT int cef_create_new_temp_directory(const cef_string_t* prefix,
                                              cef_string_t* new_temp_path);
 
 ///
-// Creates a directory within another directory. Extra characters will be
-// appended to |prefix| to ensure that the new directory does not have the same
-// name as an existing directory. Returns true (1) on success and sets |new_dir|
-// to the full path of the directory that was created. The directory is only
-// readable by the current user. Calling this function on the browser process UI
-// or IO threads is not allowed.
+/// Creates a directory within another directory. Extra characters will be
+/// appended to |prefix| to ensure that the new directory does not have the same
+/// name as an existing directory. Returns true (1) on success and sets
+/// |new_dir| to the full path of the directory that was created. The directory
+/// is only readable by the current user. Calling this function on the browser
+/// process UI or IO threads is not allowed.
 ///
 CEF_EXPORT int cef_create_temp_directory_in_directory(
     const cef_string_t* base_dir,
@@ -88,39 +88,40 @@
     cef_string_t* new_dir);
 
 ///
-// Returns true (1) if the given path exists and is a directory. Calling this
-// function on the browser process UI or IO threads is not allowed.
+/// Returns true (1) if the given path exists and is a directory. Calling this
+/// function on the browser process UI or IO threads is not allowed.
 ///
 CEF_EXPORT int cef_directory_exists(const cef_string_t* path);
 
 ///
-// Deletes the given path whether it's a file or a directory. If |path| is a
-// directory all contents will be deleted.  If |recursive| is true (1) any sub-
-// directories and their contents will also be deleted (equivalent to executing
-// "rm -rf", so use with caution). On POSIX environments if |path| is a symbolic
-// link then only the symlink will be deleted. Returns true (1) on successful
-// deletion or if |path| does not exist. Calling this function on the browser
-// process UI or IO threads is not allowed.
+/// Deletes the given path whether it's a file or a directory. If |path| is a
+/// directory all contents will be deleted.  If |recursive| is true (1) any sub-
+/// directories and their contents will also be deleted (equivalent to executing
+/// "rm -rf", so use with caution). On POSIX environments if |path| is a
+/// symbolic link then only the symlink will be deleted. Returns true (1) on
+/// successful deletion or if |path| does not exist. Calling this function on
+/// the browser process UI or IO threads is not allowed.
 ///
 CEF_EXPORT int cef_delete_file(const cef_string_t* path, int recursive);
 
 ///
-// Writes the contents of |src_dir| into a zip archive at |dest_file|. If
-// |include_hidden_files| is true (1) files starting with "." will be included.
-// Returns true (1) on success.  Calling this function on the browser process UI
-// or IO threads is not allowed.
+/// Writes the contents of |src_dir| into a zip archive at |dest_file|. If
+/// |include_hidden_files| is true (1) files starting with "." will be included.
+/// Returns true (1) on success.  Calling this function on the browser process
+/// UI or IO threads is not allowed.
 ///
 CEF_EXPORT int cef_zip_directory(const cef_string_t* src_dir,
                                  const cef_string_t* dest_file,
                                  int include_hidden_files);
 
 ///
-// Loads the existing "Certificate Revocation Lists" file that is managed by
-// Google Chrome. This file can generally be found in Chrome's User Data
-// directory (e.g. "C:\Users\[User]\AppData\Local\Google\Chrome\User Data\" on
-// Windows) and is updated periodically by Chrome's component updater service.
-// Must be called in the browser process after the context has been initialized.
-// See https://dev.chromium.org/Home/chromium-security/crlsets for background.
+/// Loads the existing "Certificate Revocation Lists" file that is managed by
+/// Google Chrome. This file can generally be found in Chrome's User Data
+/// directory (e.g. "C:\Users\[User]\AppData\Local\Google\Chrome\User Data\" on
+/// Windows) and is updated periodically by Chrome's component updater service.
+/// Must be called in the browser process after the context has been
+/// initialized. See https://dev.chromium.org/Home/chromium-security/crlsets for
+/// background.
 ///
 CEF_EXPORT void cef_load_crlsets_file(const cef_string_t* path);
 
diff --git a/src/include/capi/cef_find_handler_capi.h b/src/include/capi/cef_find_handler_capi.h
index c7be471..94450d2 100644
--- a/src/include/capi/cef_find_handler_capi.h
+++ b/src/include/capi/cef_find_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=2aa57426a91e10985a5e92830bc3bcd9287708d4$
+// $hash=8149c82dd6671d676ee62cb6749bf30b32a5832c$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_FIND_HANDLER_CAPI_H_
@@ -48,22 +48,23 @@
 #endif
 
 ///
-// Implement this structure to handle events related to find results. The
-// functions of this structure will be called on the UI thread.
+/// Implement this structure to handle events related to find results. The
+/// functions of this structure will be called on the UI thread.
 ///
 typedef struct _cef_find_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called to report find results returned by cef_browser_host_t::find().
-  // |identifer| is the identifier passed to find(), |count| is the number of
-  // matches currently identified, |selectionRect| is the location of where the
-  // match was found (in window coordinates), |activeMatchOrdinal| is the
-  // current position in the search results, and |finalUpdate| is true (1) if
-  // this is the last find notification.
+  /// Called to report find results returned by cef_browser_host_t::find().
+  /// |identifer| is a unique incremental identifier for the currently active
+  /// search, |count| is the number of matches currently identified,
+  /// |selectionRect| is the location of where the match was found (in window
+  /// coordinates), |activeMatchOrdinal| is the current position in the search
+  /// results, and |finalUpdate| is true (1) if this is the last find
+  /// notification.
   ///
   void(CEF_CALLBACK* on_find_result)(struct _cef_find_handler_t* self,
                                      struct _cef_browser_t* browser,
diff --git a/src/include/capi/cef_focus_handler_capi.h b/src/include/capi/cef_focus_handler_capi.h
index a5c2ecc..f7b699d 100644
--- a/src/include/capi/cef_focus_handler_capi.h
+++ b/src/include/capi/cef_focus_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=091dd994f37070e9d7c27d0e2f7411ea9cf068f5$
+// $hash=53ec33c8937c735f646f9e0a14a416218e32887c$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_FOCUS_HANDLER_CAPI_H_
@@ -50,36 +50,37 @@
 #endif
 
 ///
-// Implement this structure to handle events related to focus. The functions of
-// this structure will be called on the UI thread.
+/// Implement this structure to handle events related to focus. The functions of
+/// this structure will be called on the UI thread.
 ///
 typedef struct _cef_focus_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called when the browser component is about to loose focus. For instance, if
-  // focus was on the last HTML element and the user pressed the TAB key. |next|
-  // will be true (1) if the browser is giving focus to the next component and
-  // false (0) if the browser is giving focus to the previous component.
+  /// Called when the browser component is about to loose focus. For instance,
+  /// if focus was on the last HTML element and the user pressed the TAB key.
+  /// |next| will be true (1) if the browser is giving focus to the next
+  /// component and false (0) if the browser is giving focus to the previous
+  /// component.
   ///
   void(CEF_CALLBACK* on_take_focus)(struct _cef_focus_handler_t* self,
                                     struct _cef_browser_t* browser,
                                     int next);
 
   ///
-  // Called when the browser component is requesting focus. |source| indicates
-  // where the focus request is originating from. Return false (0) to allow the
-  // focus to be set or true (1) to cancel setting the focus.
+  /// Called when the browser component is requesting focus. |source| indicates
+  /// where the focus request is originating from. Return false (0) to allow the
+  /// focus to be set or true (1) to cancel setting the focus.
   ///
   int(CEF_CALLBACK* on_set_focus)(struct _cef_focus_handler_t* self,
                                   struct _cef_browser_t* browser,
                                   cef_focus_source_t source);
 
   ///
-  // Called when the browser component has received focus.
+  /// Called when the browser component has received focus.
   ///
   void(CEF_CALLBACK* on_got_focus)(struct _cef_focus_handler_t* self,
                                    struct _cef_browser_t* browser);
diff --git a/src/include/capi/cef_frame_capi.h b/src/include/capi/cef_frame_capi.h
index 3be029d..ae169cf 100644
--- a/src/include/capi/cef_frame_capi.h
+++ b/src/include/capi/cef_frame_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=d8f114b44d02d96b5da0ec399c99091b9ceb6871$
+// $hash=1ad87e4addc2f05497671bc59dc7fd315e0603f3$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_FRAME_CAPI_H_
@@ -57,100 +57,100 @@
 struct _cef_v8context_t;
 
 ///
-// Structure used to represent a frame in the browser window. When used in the
-// browser process the functions of this structure may be called on any thread
-// unless otherwise indicated in the comments. When used in the render process
-// the functions of this structure may only be called on the main thread.
+/// Structure used to represent a frame in the browser window. When used in the
+/// browser process the functions of this structure may be called on any thread
+/// unless otherwise indicated in the comments. When used in the render process
+/// the functions of this structure may only be called on the main thread.
 ///
 typedef struct _cef_frame_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // True if this object is currently attached to a valid frame.
+  /// True if this object is currently attached to a valid frame.
   ///
   int(CEF_CALLBACK* is_valid)(struct _cef_frame_t* self);
 
   ///
-  // Execute undo in this frame.
+  /// Execute undo in this frame.
   ///
   void(CEF_CALLBACK* undo)(struct _cef_frame_t* self);
 
   ///
-  // Execute redo in this frame.
+  /// Execute redo in this frame.
   ///
   void(CEF_CALLBACK* redo)(struct _cef_frame_t* self);
 
   ///
-  // Execute cut in this frame.
+  /// Execute cut in this frame.
   ///
   void(CEF_CALLBACK* cut)(struct _cef_frame_t* self);
 
   ///
-  // Execute copy in this frame.
+  /// Execute copy in this frame.
   ///
   void(CEF_CALLBACK* copy)(struct _cef_frame_t* self);
 
   ///
-  // Execute paste in this frame.
+  /// Execute paste in this frame.
   ///
   void(CEF_CALLBACK* paste)(struct _cef_frame_t* self);
 
   ///
-  // Execute delete in this frame.
+  /// Execute delete in this frame.
   ///
   void(CEF_CALLBACK* del)(struct _cef_frame_t* self);
 
   ///
-  // Execute select all in this frame.
+  /// Execute select all in this frame.
   ///
   void(CEF_CALLBACK* select_all)(struct _cef_frame_t* self);
 
   ///
-  // Save this frame's HTML source to a temporary file and open it in the
-  // default text viewing application. This function can only be called from the
-  // browser process.
+  /// Save this frame's HTML source to a temporary file and open it in the
+  /// default text viewing application. This function can only be called from
+  /// the browser process.
   ///
   void(CEF_CALLBACK* view_source)(struct _cef_frame_t* self);
 
   ///
-  // Retrieve this frame's HTML source as a string sent to the specified
-  // visitor.
+  /// Retrieve this frame's HTML source as a string sent to the specified
+  /// visitor.
   ///
   void(CEF_CALLBACK* get_source)(struct _cef_frame_t* self,
                                  struct _cef_string_visitor_t* visitor);
 
   ///
-  // Retrieve this frame's display text as a string sent to the specified
-  // visitor.
+  /// Retrieve this frame's display text as a string sent to the specified
+  /// visitor.
   ///
   void(CEF_CALLBACK* get_text)(struct _cef_frame_t* self,
                                struct _cef_string_visitor_t* visitor);
 
   ///
-  // Load the request represented by the |request| object.
-  //
-  // WARNING: This function will fail with "bad IPC message" reason
-  // INVALID_INITIATOR_ORIGIN (213) unless you first navigate to the request
-  // origin using some other mechanism (LoadURL, link click, etc).
+  /// Load the request represented by the |request| object.
+  ///
+  /// WARNING: This function will fail with "bad IPC message" reason
+  /// INVALID_INITIATOR_ORIGIN (213) unless you first navigate to the request
+  /// origin using some other mechanism (LoadURL, link click, etc).
   ///
   void(CEF_CALLBACK* load_request)(struct _cef_frame_t* self,
                                    struct _cef_request_t* request);
 
   ///
-  // Load the specified |url|.
+  /// Load the specified |url|.
   ///
   void(CEF_CALLBACK* load_url)(struct _cef_frame_t* self,
                                const cef_string_t* url);
 
   ///
-  // Execute a string of JavaScript code in this frame. The |script_url|
-  // parameter is the URL where the script in question can be found, if any. The
-  // renderer may request this URL to show the developer the source of the
-  // error.  The |start_line| parameter is the base line number to use for error
-  // reporting.
+  /// Execute a string of JavaScript code in this frame. The |script_url|
+  /// parameter is the URL where the script in question can be found, if any.
+  /// The renderer may request this URL to show the developer the source of the
+  /// error.  The |start_line| parameter is the base line number to use for
+  /// error reporting.
   ///
   void(CEF_CALLBACK* execute_java_script)(struct _cef_frame_t* self,
                                           const cef_string_t* code,
@@ -158,83 +158,76 @@
                                           int start_line);
 
   ///
-  // Returns true (1) if this is the main (top-level) frame.
+  /// Returns true (1) if this is the main (top-level) frame.
   ///
   int(CEF_CALLBACK* is_main)(struct _cef_frame_t* self);
 
   ///
-  // Returns true (1) if this is the focused frame.
+  /// Returns true (1) if this is the focused frame.
   ///
   int(CEF_CALLBACK* is_focused)(struct _cef_frame_t* self);
 
   ///
-  // Returns the name for this frame. If the frame has an assigned name (for
-  // example, set via the iframe "name" attribute) then that value will be
-  // returned. Otherwise a unique name will be constructed based on the frame
-  // parent hierarchy. The main (top-level) frame will always have an NULL name
-  // value.
+  /// Returns the name for this frame. If the frame has an assigned name (for
+  /// example, set via the iframe "name" attribute) then that value will be
+  /// returned. Otherwise a unique name will be constructed based on the frame
+  /// parent hierarchy. The main (top-level) frame will always have an NULL name
+  /// value.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_name)(struct _cef_frame_t* self);
 
   ///
-  // Returns the globally unique identifier for this frame or < 0 if the
-  // underlying frame does not yet exist.
+  /// Returns the globally unique identifier for this frame or < 0 if the
+  /// underlying frame does not yet exist.
   ///
-  int64(CEF_CALLBACK* get_identifier)(struct _cef_frame_t* self);
+  int64_t(CEF_CALLBACK* get_identifier)(struct _cef_frame_t* self);
 
   ///
-  // Returns the parent of this frame or NULL if this is the main (top-level)
-  // frame.
+  /// Returns the parent of this frame or NULL if this is the main (top-level)
+  /// frame.
   ///
   struct _cef_frame_t*(CEF_CALLBACK* get_parent)(struct _cef_frame_t* self);
 
   ///
-  // Returns the URL currently loaded in this frame.
+  /// Returns the URL currently loaded in this frame.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_url)(struct _cef_frame_t* self);
 
   ///
-  // Returns the browser that this frame belongs to.
+  /// Returns the browser that this frame belongs to.
   ///
   struct _cef_browser_t*(CEF_CALLBACK* get_browser)(struct _cef_frame_t* self);
 
   ///
-  // Get the V8 context associated with the frame. This function can only be
-  // called from the render process.
+  /// Get the V8 context associated with the frame. This function can only be
+  /// called from the render process.
   ///
   struct _cef_v8context_t*(CEF_CALLBACK* get_v8context)(
       struct _cef_frame_t* self);
 
   ///
-  // Visit the DOM document. This function can only be called from the render
-  // process.
+  /// Visit the DOM document. This function can only be called from the render
+  /// process.
   ///
   void(CEF_CALLBACK* visit_dom)(struct _cef_frame_t* self,
                                 struct _cef_domvisitor_t* visitor);
 
   ///
-  // Create a new URL request that will be treated as originating from this
-  // frame and the associated browser. This request may be intercepted by the
-  // client via cef_resource_request_handler_t or cef_scheme_handler_factory_t.
-  // Use cef_urlrequest_t::Create instead if you do not want the request to have
-  // this association, in which case it may be handled differently (see
-  // documentation on that function). Requests may originate from both the
-  // browser process and the render process.
-  //
-  // For requests originating from the browser process:
-  //   - POST data may only contain a single element of type PDE_TYPE_FILE or
-  //     PDE_TYPE_BYTES.
-  // For requests originating from the render process:
-  //   - POST data may only contain a single element of type PDE_TYPE_BYTES.
-  //   - If the response contains Content-Disposition or Mime-Type header values
-  //     that would not normally be rendered then the response may receive
-  //     special handling inside the browser (for example, via the file download
-  //     code path instead of the URL request code path).
-  //
-  // The |request| object will be marked as read-only after calling this
-  // function.
+  /// Create a new URL request that will be treated as originating from this
+  /// frame and the associated browser. Use cef_urlrequest_t::Create instead if
+  /// you do not want the request to have this association, in which case it may
+  /// be handled differently (see documentation on that function). A request
+  /// created with this function may only originate from the browser process,
+  /// and will behave as follows:
+  ///   - It may be intercepted by the client via CefResourceRequestHandler or
+  ///     CefSchemeHandlerFactory.
+  ///   - POST data may only contain a single element of type PDE_TYPE_FILE or
+  ///     PDE_TYPE_BYTES.
+  ///
+  /// The |request| object will be marked as read-only after calling this
+  /// function.
   ///
   struct _cef_urlrequest_t*(CEF_CALLBACK* create_urlrequest)(
       struct _cef_frame_t* self,
@@ -242,10 +235,12 @@
       struct _cef_urlrequest_client_t* client);
 
   ///
-  // Send a message to the specified |target_process|. Message delivery is not
-  // guaranteed in all cases (for example, if the browser is closing,
-  // navigating, or if the target process crashes). Send an ACK message back
-  // from the target process if confirmation is required.
+  /// Send a message to the specified |target_process|. Ownership of the message
+  /// contents will be transferred and the |message| reference will be
+  /// invalidated. Message delivery is not guaranteed in all cases (for example,
+  /// if the browser is closing, navigating, or if the target process crashes).
+  /// Send an ACK message back from the target process if confirmation is
+  /// required.
   ///
   void(CEF_CALLBACK* send_process_message)(
       struct _cef_frame_t* self,
diff --git a/src/include/capi/cef_frame_handler_capi.h b/src/include/capi/cef_frame_handler_capi.h
new file mode 100644
index 0000000..94b3b88
--- /dev/null
+++ b/src/include/capi/cef_frame_handler_capi.h
@@ -0,0 +1,202 @@
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool and should not edited
+// by hand. See the translator.README.txt file in the tools directory for
+// more information.
+//
+// $hash=4cdadeb6439415d60ec32249c3a0b6457dd586f7$
+//
+
+#ifndef CEF_INCLUDE_CAPI_CEF_FRAME_HANDLER_CAPI_H_
+#define CEF_INCLUDE_CAPI_CEF_FRAME_HANDLER_CAPI_H_
+#pragma once
+
+#include "include/capi/cef_base_capi.h"
+#include "include/capi/cef_browser_capi.h"
+#include "include/capi/cef_frame_capi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///
+/// Implement this structure to handle events related to cef_frame_t life span.
+/// The order of callbacks is:
+///
+/// (1) During initial cef_browser_host_t creation and navigation of the main
+/// frame: - cef_frame_handler_t::OnFrameCreated => The initial main frame
+/// object has been
+///   created. Any commands will be queued until the frame is attached.
+/// - cef_frame_handler_t::OnMainFrameChanged => The initial main frame object
+/// has
+///   been assigned to the browser.
+/// - cef_life_span_handler_t::OnAfterCreated => The browser is now valid and
+/// can be
+///   used.
+/// - cef_frame_handler_t::OnFrameAttached => The initial main frame object is
+/// now
+///   connected to its peer in the renderer process. Commands can be routed.
+///
+/// (2) During further cef_browser_host_t navigation/loading of the main frame
+///     and/or sub-frames:
+/// - cef_frame_handler_t::OnFrameCreated => A new main frame or sub-frame
+/// object
+///   has been created. Any commands will be queued until the frame is attached.
+/// - cef_frame_handler_t::OnFrameAttached => A new main frame or sub-frame
+/// object
+///   is now connected to its peer in the renderer process. Commands can be
+///   routed.
+/// - cef_frame_handler_t::OnFrameDetached => An existing main frame or sub-
+/// frame
+///   object has lost its connection to the renderer process. If multiple
+///   objects are detached at the same time then notifications will be sent for
+///   any sub-frame objects before the main frame object. Commands can no longer
+///   be routed and will be discarded.
+/// - cef_frame_handler_t::OnMainFrameChanged => A new main frame object has
+/// been
+///   assigned to the browser. This will only occur with cross-origin navigation
+///   or re-navigation after renderer process termination (due to crashes, etc).
+///
+/// (3) During final cef_browser_host_t destruction of the main frame: -
+/// cef_frame_handler_t::OnFrameDetached => Any sub-frame objects have lost
+/// their
+///   connection to the renderer process. Commands can no longer be routed and
+///   will be discarded.
+/// - cef_life_span_handler_t::OnBeforeClose => The browser has been destroyed.
+/// - cef_frame_handler_t::OnFrameDetached => The main frame object have lost
+/// its
+///   connection to the renderer process. Notifications will be sent for any
+///   sub-frame objects before the main frame object. Commands can no longer be
+///   routed and will be discarded.
+/// - cef_frame_handler_t::OnMainFrameChanged => The final main frame object has
+///   been removed from the browser.
+///
+/// Cross-origin navigation and/or loading receives special handling.
+///
+/// When the main frame navigates to a different origin the OnMainFrameChanged
+/// callback (2) will be executed with the old and new main frame objects.
+///
+/// When a new sub-frame is loaded in, or an existing sub-frame is navigated to,
+/// a different origin from the parent frame, a temporary sub-frame object will
+/// first be created in the parent's renderer process. That temporary sub-frame
+/// will then be discarded after the real cross-origin sub-frame is created in
+/// the new/target renderer process. The client will receive cross-origin
+/// navigation callbacks (2) for the transition from the temporary sub-frame to
+/// the real sub-frame. The temporary sub-frame will not recieve or execute
+/// commands during this transitional period (any sent commands will be
+/// discarded).
+///
+/// When a new popup browser is created in a different origin from the parent
+/// browser, a temporary main frame object for the popup will first be created
+/// in the parent's renderer process. That temporary main frame will then be
+/// discarded after the real cross-origin main frame is created in the
+/// new/target renderer process. The client will recieve creation and initial
+/// navigation callbacks (1) for the temporary main frame, followed by cross-
+/// origin navigation callbacks (2) for the transition from the temporary main
+/// frame to the real main frame. The temporary main frame may receive and
+/// execute commands during this transitional period (any sent commands may be
+/// executed, but the behavior is potentially undesirable since they execute in
+/// the parent browser's renderer process and not the new/target renderer
+/// process).
+///
+/// Callbacks will not be executed for placeholders that may be created during
+/// pre-commit navigation for sub-frames that do not yet exist in the renderer
+/// process. Placeholders will have cef_frame_t::get_identifier() == -4.
+///
+/// The functions of this structure will be called on the UI thread unless
+/// otherwise indicated.
+///
+typedef struct _cef_frame_handler_t {
+  ///
+  /// Base structure.
+  ///
+  cef_base_ref_counted_t base;
+
+  ///
+  /// Called when a new frame is created. This will be the first notification
+  /// that references |frame|. Any commands that require transport to the
+  /// associated renderer process (LoadRequest, SendProcessMessage, GetSource,
+  /// etc.) will be queued until OnFrameAttached is called for |frame|.
+  ///
+  void(CEF_CALLBACK* on_frame_created)(struct _cef_frame_handler_t* self,
+                                       struct _cef_browser_t* browser,
+                                       struct _cef_frame_t* frame);
+
+  ///
+  /// Called when a frame can begin routing commands to/from the associated
+  /// renderer process. |reattached| will be true (1) if the frame was re-
+  /// attached after exiting the BackForwardCache. Any commands that were queued
+  /// have now been dispatched.
+  ///
+  void(CEF_CALLBACK* on_frame_attached)(struct _cef_frame_handler_t* self,
+                                        struct _cef_browser_t* browser,
+                                        struct _cef_frame_t* frame,
+                                        int reattached);
+
+  ///
+  /// Called when a frame loses its connection to the renderer process and will
+  /// be destroyed. Any pending or future commands will be discarded and
+  /// cef_frame_t::is_valid() will now return false (0) for |frame|. If called
+  /// after cef_life_span_handler_t::on_before_close() during browser
+  /// destruction then cef_browser_t::is_valid() will return false (0) for
+  /// |browser|.
+  ///
+  void(CEF_CALLBACK* on_frame_detached)(struct _cef_frame_handler_t* self,
+                                        struct _cef_browser_t* browser,
+                                        struct _cef_frame_t* frame);
+
+  ///
+  /// Called when the main frame changes due to (a) initial browser creation,
+  /// (b) final browser destruction, (c) cross-origin navigation or (d) re-
+  /// navigation after renderer process termination (due to crashes, etc).
+  /// |old_frame| will be NULL and |new_frame| will be non-NULL when a main
+  /// frame is assigned to |browser| for the first time. |old_frame| will be
+  /// non-NULL and |new_frame| will be NULL and  when a main frame is removed
+  /// from |browser| for the last time. Both |old_frame| and |new_frame| will be
+  /// non-NULL for cross-origin navigations or re-navigation after renderer
+  /// process termination. This function will be called after on_frame_created()
+  /// for |new_frame| and/or after on_frame_detached() for |old_frame|. If
+  /// called after cef_life_span_handler_t::on_before_close() during browser
+  /// destruction then cef_browser_t::is_valid() will return false (0) for
+  /// |browser|.
+  ///
+  void(CEF_CALLBACK* on_main_frame_changed)(struct _cef_frame_handler_t* self,
+                                            struct _cef_browser_t* browser,
+                                            struct _cef_frame_t* old_frame,
+                                            struct _cef_frame_t* new_frame);
+} cef_frame_handler_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // CEF_INCLUDE_CAPI_CEF_FRAME_HANDLER_CAPI_H_
diff --git a/src/include/capi/cef_request_callback_capi.h b/src/include/capi/cef_i18n_util_capi.h
similarity index 70%
rename from src/include/capi/cef_request_callback_capi.h
rename to src/include/capi/cef_i18n_util_capi.h
index 36316e9..3aab714 100644
--- a/src/include/capi/cef_request_callback_capi.h
+++ b/src/include/capi/cef_i18n_util_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,11 +33,11 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=3efd81a4bfdfca579a77f14bd37b8192122ebda4$
+// $hash=c564ee1f32a0ef05fe49fc779af5bc0b0e1b36d6$
 //
 
-#ifndef CEF_INCLUDE_CAPI_CEF_REQUEST_CALLBACK_CAPI_H_
-#define CEF_INCLUDE_CAPI_CEF_REQUEST_CALLBACK_CAPI_H_
+#ifndef CEF_INCLUDE_CAPI_CEF_I18N_UTIL_CAPI_H_
+#define CEF_INCLUDE_CAPI_CEF_I18N_UTIL_CAPI_H_
 #pragma once
 
 #include "include/capi/cef_base_capi.h"
@@ -47,28 +47,12 @@
 #endif
 
 ///
-// Callback structure used for asynchronous continuation of url requests.
+/// Returns true (1) if the application text direction is right-to-left.
 ///
-typedef struct _cef_request_callback_t {
-  ///
-  // Base structure.
-  ///
-  cef_base_ref_counted_t base;
-
-  ///
-  // Continue the url request. If |allow| is true (1) the request will be
-  // continued. Otherwise, the request will be canceled.
-  ///
-  void(CEF_CALLBACK* cont)(struct _cef_request_callback_t* self, int allow);
-
-  ///
-  // Cancel the url request.
-  ///
-  void(CEF_CALLBACK* cancel)(struct _cef_request_callback_t* self);
-} cef_request_callback_t;
+CEF_EXPORT int cef_is_rtl(void);
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif  // CEF_INCLUDE_CAPI_CEF_REQUEST_CALLBACK_CAPI_H_
+#endif  // CEF_INCLUDE_CAPI_CEF_I18N_UTIL_CAPI_H_
diff --git a/src/include/capi/cef_image_capi.h b/src/include/capi/cef_image_capi.h
index d3836d6..9d4a0a9 100644
--- a/src/include/capi/cef_image_capi.h
+++ b/src/include/capi/cef_image_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=5afa8e95e6e7bddbd3c442e99b4c2843efb18c49$
+// $hash=99c94b208f9b184985220493bba4ea08e6786046$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_IMAGE_CAPI_H_
@@ -48,37 +48,37 @@
 #endif
 
 ///
-// Container for a single image represented at different scale factors. All
-// image representations should be the same size in density independent pixel
-// (DIP) units. For example, if the image at scale factor 1.0 is 100x100 pixels
-// then the image at scale factor 2.0 should be 200x200 pixels -- both images
-// will display with a DIP size of 100x100 units. The functions of this
-// structure can be called on any browser process thread.
+/// Container for a single image represented at different scale factors. All
+/// image representations should be the same size in density independent pixel
+/// (DIP) units. For example, if the image at scale factor 1.0 is 100x100 pixels
+/// then the image at scale factor 2.0 should be 200x200 pixels -- both images
+/// will display with a DIP size of 100x100 units. The functions of this
+/// structure can be called on any browser process thread.
 ///
 typedef struct _cef_image_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if this Image is NULL.
+  /// Returns true (1) if this Image is NULL.
   ///
   int(CEF_CALLBACK* is_empty)(struct _cef_image_t* self);
 
   ///
-  // Returns true (1) if this Image and |that| Image share the same underlying
-  // storage. Will also return true (1) if both images are NULL.
+  /// Returns true (1) if this Image and |that| Image share the same underlying
+  /// storage. Will also return true (1) if both images are NULL.
   ///
   int(CEF_CALLBACK* is_same)(struct _cef_image_t* self,
                              struct _cef_image_t* that);
 
   ///
-  // Add a bitmap image representation for |scale_factor|. Only 32-bit RGBA/BGRA
-  // formats are supported. |pixel_width| and |pixel_height| are the bitmap
-  // representation size in pixel coordinates. |pixel_data| is the array of
-  // pixel data and should be |pixel_width| x |pixel_height| x 4 bytes in size.
-  // |color_type| and |alpha_type| values specify the pixel format.
+  /// Add a bitmap image representation for |scale_factor|. Only 32-bit
+  /// RGBA/BGRA formats are supported. |pixel_width| and |pixel_height| are the
+  /// bitmap representation size in pixel coordinates. |pixel_data| is the array
+  /// of pixel data and should be |pixel_width| x |pixel_height| x 4 bytes in
+  /// size. |color_type| and |alpha_type| values specify the pixel format.
   ///
   int(CEF_CALLBACK* add_bitmap)(struct _cef_image_t* self,
                                 float scale_factor,
@@ -90,9 +90,9 @@
                                 size_t pixel_data_size);
 
   ///
-  // Add a PNG image representation for |scale_factor|. |png_data| is the image
-  // data of size |png_data_size|. Any alpha transparency in the PNG data will
-  // be maintained.
+  /// Add a PNG image representation for |scale_factor|. |png_data| is the image
+  /// data of size |png_data_size|. Any alpha transparency in the PNG data will
+  /// be maintained.
   ///
   int(CEF_CALLBACK* add_png)(struct _cef_image_t* self,
                              float scale_factor,
@@ -100,9 +100,9 @@
                              size_t png_data_size);
 
   ///
-  // Create a JPEG image representation for |scale_factor|. |jpeg_data| is the
-  // image data of size |jpeg_data_size|. The JPEG format does not support
-  // transparency so the alpha byte will be set to 0xFF for all pixels.
+  /// Create a JPEG image representation for |scale_factor|. |jpeg_data| is the
+  /// image data of size |jpeg_data_size|. The JPEG format does not support
+  /// transparency so the alpha byte will be set to 0xFF for all pixels.
   ///
   int(CEF_CALLBACK* add_jpeg)(struct _cef_image_t* self,
                               float scale_factor,
@@ -110,33 +110,34 @@
                               size_t jpeg_data_size);
 
   ///
-  // Returns the image width in density independent pixel (DIP) units.
+  /// Returns the image width in density independent pixel (DIP) units.
   ///
   size_t(CEF_CALLBACK* get_width)(struct _cef_image_t* self);
 
   ///
-  // Returns the image height in density independent pixel (DIP) units.
+  /// Returns the image height in density independent pixel (DIP) units.
   ///
   size_t(CEF_CALLBACK* get_height)(struct _cef_image_t* self);
 
   ///
-  // Returns true (1) if this image contains a representation for
-  // |scale_factor|.
+  /// Returns true (1) if this image contains a representation for
+  /// |scale_factor|.
   ///
   int(CEF_CALLBACK* has_representation)(struct _cef_image_t* self,
                                         float scale_factor);
 
   ///
-  // Removes the representation for |scale_factor|. Returns true (1) on success.
+  /// Removes the representation for |scale_factor|. Returns true (1) on
+  /// success.
   ///
   int(CEF_CALLBACK* remove_representation)(struct _cef_image_t* self,
                                            float scale_factor);
 
   ///
-  // Returns information for the representation that most closely matches
-  // |scale_factor|. |actual_scale_factor| is the actual scale factor for the
-  // representation. |pixel_width| and |pixel_height| are the representation
-  // size in pixel coordinates. Returns true (1) on success.
+  /// Returns information for the representation that most closely matches
+  /// |scale_factor|. |actual_scale_factor| is the actual scale factor for the
+  /// representation. |pixel_width| and |pixel_height| are the representation
+  /// size in pixel coordinates. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* get_representation_info)(struct _cef_image_t* self,
                                              float scale_factor,
@@ -145,12 +146,12 @@
                                              int* pixel_height);
 
   ///
-  // Returns the bitmap representation that most closely matches |scale_factor|.
-  // Only 32-bit RGBA/BGRA formats are supported. |color_type| and |alpha_type|
-  // values specify the desired output pixel format. |pixel_width| and
-  // |pixel_height| are the output representation size in pixel coordinates.
-  // Returns a cef_binary_value_t containing the pixel data on success or NULL
-  // on failure.
+  /// Returns the bitmap representation that most closely matches
+  /// |scale_factor|. Only 32-bit RGBA/BGRA formats are supported. |color_type|
+  /// and |alpha_type| values specify the desired output pixel format.
+  /// |pixel_width| and |pixel_height| are the output representation size in
+  /// pixel coordinates. Returns a cef_binary_value_t containing the pixel data
+  /// on success or NULL on failure.
   ///
   struct _cef_binary_value_t*(CEF_CALLBACK* get_as_bitmap)(
       struct _cef_image_t* self,
@@ -161,12 +162,12 @@
       int* pixel_height);
 
   ///
-  // Returns the PNG representation that most closely matches |scale_factor|. If
-  // |with_transparency| is true (1) any alpha transparency in the image will be
-  // represented in the resulting PNG data. |pixel_width| and |pixel_height| are
-  // the output representation size in pixel coordinates. Returns a
-  // cef_binary_value_t containing the PNG image data on success or NULL on
-  // failure.
+  /// Returns the PNG representation that most closely matches |scale_factor|.
+  /// If |with_transparency| is true (1) any alpha transparency in the image
+  /// will be represented in the resulting PNG data. |pixel_width| and
+  /// |pixel_height| are the output representation size in pixel coordinates.
+  /// Returns a cef_binary_value_t containing the PNG image data on success or
+  /// NULL on failure.
   ///
   struct _cef_binary_value_t*(CEF_CALLBACK* get_as_png)(
       struct _cef_image_t* self,
@@ -176,13 +177,13 @@
       int* pixel_height);
 
   ///
-  // Returns the JPEG representation that most closely matches |scale_factor|.
-  // |quality| determines the compression level with 0 == lowest and 100 ==
-  // highest. The JPEG format does not support alpha transparency and the alpha
-  // channel, if any, will be discarded. |pixel_width| and |pixel_height| are
-  // the output representation size in pixel coordinates. Returns a
-  // cef_binary_value_t containing the JPEG image data on success or NULL on
-  // failure.
+  /// Returns the JPEG representation that most closely matches |scale_factor|.
+  /// |quality| determines the compression level with 0 == lowest and 100 ==
+  /// highest. The JPEG format does not support alpha transparency and the alpha
+  /// channel, if any, will be discarded. |pixel_width| and |pixel_height| are
+  /// the output representation size in pixel coordinates. Returns a
+  /// cef_binary_value_t containing the JPEG image data on success or NULL on
+  /// failure.
   ///
   struct _cef_binary_value_t*(CEF_CALLBACK* get_as_jpeg)(
       struct _cef_image_t* self,
@@ -193,10 +194,10 @@
 } cef_image_t;
 
 ///
-// Create a new cef_image_t. It will initially be NULL. Use the Add*() functions
-// to add representations at different scale factors.
+/// Create a new cef_image_t. It will initially be NULL. Use the Add*()
+/// functions to add representations at different scale factors.
 ///
-CEF_EXPORT cef_image_t* cef_image_create();
+CEF_EXPORT cef_image_t* cef_image_create(void);
 
 #ifdef __cplusplus
 }
diff --git a/src/include/capi/cef_jsdialog_handler_capi.h b/src/include/capi/cef_jsdialog_handler_capi.h
index 0aed471..a490ddd 100644
--- a/src/include/capi/cef_jsdialog_handler_capi.h
+++ b/src/include/capi/cef_jsdialog_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=e68da1a5db612699b7b727edea2bb629f5d67103$
+// $hash=e9fb0354243611f3a4de508923a4e01dab42f82d$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_JSDIALOG_HANDLER_CAPI_H_
@@ -48,18 +48,19 @@
 #endif
 
 ///
-// Callback structure used for asynchronous continuation of JavaScript dialog
-// requests.
+/// Callback structure used for asynchronous continuation of JavaScript dialog
+/// requests.
 ///
 typedef struct _cef_jsdialog_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Continue the JS dialog request. Set |success| to true (1) if the OK button
-  // was pressed. The |user_input| value should be specified for prompt dialogs.
+  /// Continue the JS dialog request. Set |success| to true (1) if the OK button
+  /// was pressed. The |user_input| value should be specified for prompt
+  /// dialogs.
   ///
   void(CEF_CALLBACK* cont)(struct _cef_jsdialog_callback_t* self,
                            int success,
@@ -67,31 +68,31 @@
 } cef_jsdialog_callback_t;
 
 ///
-// Implement this structure to handle events related to JavaScript dialogs. The
-// functions of this structure will be called on the UI thread.
+/// Implement this structure to handle events related to JavaScript dialogs. The
+/// functions of this structure will be called on the UI thread.
 ///
 typedef struct _cef_jsdialog_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called to run a JavaScript dialog. If |origin_url| is non-NULL it can be
-  // passed to the CefFormatUrlForSecurityDisplay function to retrieve a secure
-  // and user-friendly display string. The |default_prompt_text| value will be
-  // specified for prompt dialogs only. Set |suppress_message| to true (1) and
-  // return false (0) to suppress the message (suppressing messages is
-  // preferable to immediately executing the callback as this is used to detect
-  // presumably malicious behavior like spamming alert messages in
-  // onbeforeunload). Set |suppress_message| to false (0) and return false (0)
-  // to use the default implementation (the default implementation will show one
-  // modal dialog at a time and suppress any additional dialog requests until
-  // the displayed dialog is dismissed). Return true (1) if the application will
-  // use a custom dialog or if the callback has been executed immediately.
-  // Custom dialogs may be either modal or modeless. If a custom dialog is used
-  // the application must execute |callback| once the custom dialog is
-  // dismissed.
+  /// Called to run a JavaScript dialog. If |origin_url| is non-NULL it can be
+  /// passed to the CefFormatUrlForSecurityDisplay function to retrieve a secure
+  /// and user-friendly display string. The |default_prompt_text| value will be
+  /// specified for prompt dialogs only. Set |suppress_message| to true (1) and
+  /// return false (0) to suppress the message (suppressing messages is
+  /// preferable to immediately executing the callback as this is used to detect
+  /// presumably malicious behavior like spamming alert messages in
+  /// onbeforeunload). Set |suppress_message| to false (0) and return false (0)
+  /// to use the default implementation (the default implementation will show
+  /// one modal dialog at a time and suppress any additional dialog requests
+  /// until the displayed dialog is dismissed). Return true (1) if the
+  /// application will use a custom dialog or if the callback has been executed
+  /// immediately. Custom dialogs may be either modal or modeless. If a custom
+  /// dialog is used the application must execute |callback| once the custom
+  /// dialog is dismissed.
   ///
   int(CEF_CALLBACK* on_jsdialog)(struct _cef_jsdialog_handler_t* self,
                                  struct _cef_browser_t* browser,
@@ -103,12 +104,12 @@
                                  int* suppress_message);
 
   ///
-  // Called to run a dialog asking the user if they want to leave a page. Return
-  // false (0) to use the default dialog implementation. Return true (1) if the
-  // application will use a custom dialog or if the callback has been executed
-  // immediately. Custom dialogs may be either modal or modeless. If a custom
-  // dialog is used the application must execute |callback| once the custom
-  // dialog is dismissed.
+  /// Called to run a dialog asking the user if they want to leave a page.
+  /// Return false (0) to use the default dialog implementation. Return true (1)
+  /// if the application will use a custom dialog or if the callback has been
+  /// executed immediately. Custom dialogs may be either modal or modeless. If a
+  /// custom dialog is used the application must execute |callback| once the
+  /// custom dialog is dismissed.
   ///
   int(CEF_CALLBACK* on_before_unload_dialog)(
       struct _cef_jsdialog_handler_t* self,
@@ -118,16 +119,16 @@
       struct _cef_jsdialog_callback_t* callback);
 
   ///
-  // Called to cancel any pending dialogs and reset any saved dialog state. Will
-  // be called due to events like page navigation irregardless of whether any
-  // dialogs are currently pending.
+  /// Called to cancel any pending dialogs and reset any saved dialog state.
+  /// Will be called due to events like page navigation irregardless of whether
+  /// any dialogs are currently pending.
   ///
   void(CEF_CALLBACK* on_reset_dialog_state)(
       struct _cef_jsdialog_handler_t* self,
       struct _cef_browser_t* browser);
 
   ///
-  // Called when the default implementation dialog is closed.
+  /// Called when the dialog is closed.
   ///
   void(CEF_CALLBACK* on_dialog_closed)(struct _cef_jsdialog_handler_t* self,
                                        struct _cef_browser_t* browser);
diff --git a/src/include/capi/cef_keyboard_handler_capi.h b/src/include/capi/cef_keyboard_handler_capi.h
index 356803d..7ff37b4 100644
--- a/src/include/capi/cef_keyboard_handler_capi.h
+++ b/src/include/capi/cef_keyboard_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=70108de432674485dee079e541e0dacd6a437961$
+// $hash=10fb708c5f550403205a976924abf1886bf3dfa7$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_KEYBOARD_HANDLER_CAPI_H_
@@ -48,37 +48,38 @@
 #endif
 
 ///
-// Implement this structure to handle events related to keyboard input. The
-// functions of this structure will be called on the UI thread.
+/// Implement this structure to handle events related to keyboard input. The
+/// functions of this structure will be called on the UI thread.
 ///
 typedef struct _cef_keyboard_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called before a keyboard event is sent to the renderer. |event| contains
-  // information about the keyboard event. |os_event| is the operating system
-  // event message, if any. Return true (1) if the event was handled or false
-  // (0) otherwise. If the event will be handled in on_key_event() as a keyboard
-  // shortcut set |is_keyboard_shortcut| to true (1) and return false (0).
+  /// Called before a keyboard event is sent to the renderer. |event| contains
+  /// information about the keyboard event. |os_event| is the operating system
+  /// event message, if any. Return true (1) if the event was handled or false
+  /// (0) otherwise. If the event will be handled in on_key_event() as a
+  /// keyboard shortcut set |is_keyboard_shortcut| to true (1) and return false
+  /// (0).
   ///
   int(CEF_CALLBACK* on_pre_key_event)(struct _cef_keyboard_handler_t* self,
                                       struct _cef_browser_t* browser,
-                                      const struct _cef_key_event_t* event,
+                                      const cef_key_event_t* event,
                                       cef_event_handle_t os_event,
                                       int* is_keyboard_shortcut);
 
   ///
-  // Called after the renderer and JavaScript in the page has had a chance to
-  // handle the event. |event| contains information about the keyboard event.
-  // |os_event| is the operating system event message, if any. Return true (1)
-  // if the keyboard event was handled or false (0) otherwise.
+  /// Called after the renderer and JavaScript in the page has had a chance to
+  /// handle the event. |event| contains information about the keyboard event.
+  /// |os_event| is the operating system event message, if any. Return true (1)
+  /// if the keyboard event was handled or false (0) otherwise.
   ///
   int(CEF_CALLBACK* on_key_event)(struct _cef_keyboard_handler_t* self,
                                   struct _cef_browser_t* browser,
-                                  const struct _cef_key_event_t* event,
+                                  const cef_key_event_t* event,
                                   cef_event_handle_t os_event);
 } cef_keyboard_handler_t;
 
diff --git a/src/include/capi/cef_life_span_handler_capi.h b/src/include/capi/cef_life_span_handler_capi.h
index c691fcf..a12b086 100644
--- a/src/include/capi/cef_life_span_handler_capi.h
+++ b/src/include/capi/cef_life_span_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=d6e91d55d41f729dca94ba5766f57849f29d0796$
+// $hash=32a0c21a71aa7137fa9660b942f597705bc8b05e$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_LIFE_SPAN_HANDLER_CAPI_H_
@@ -50,40 +50,40 @@
 struct _cef_client_t;
 
 ///
-// Implement this structure to handle events related to browser life span. The
-// functions of this structure will be called on the UI thread unless otherwise
-// indicated.
+/// Implement this structure to handle events related to browser life span. The
+/// functions of this structure will be called on the UI thread unless otherwise
+/// indicated.
 ///
 typedef struct _cef_life_span_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called on the UI thread before a new popup browser is created. The
-  // |browser| and |frame| values represent the source of the popup request. The
-  // |target_url| and |target_frame_name| values indicate where the popup
-  // browser should navigate and may be NULL if not specified with the request.
-  // The |target_disposition| value indicates where the user intended to open
-  // the popup (e.g. current tab, new tab, etc). The |user_gesture| value will
-  // be true (1) if the popup was opened via explicit user gesture (e.g.
-  // clicking a link) or false (0) if the popup opened automatically (e.g. via
-  // the DomContentLoaded event). The |popupFeatures| structure contains
-  // additional information about the requested popup window. To allow creation
-  // of the popup browser optionally modify |windowInfo|, |client|, |settings|
-  // and |no_javascript_access| and return false (0). To cancel creation of the
-  // popup browser return true (1). The |client| and |settings| values will
-  // default to the source browser's values. If the |no_javascript_access| value
-  // is set to false (0) the new browser will not be scriptable and may not be
-  // hosted in the same renderer process as the source browser. Any
-  // modifications to |windowInfo| will be ignored if the parent browser is
-  // wrapped in a cef_browser_view_t. Popup browser creation will be canceled if
-  // the parent browser is destroyed before the popup browser creation completes
-  // (indicated by a call to OnAfterCreated for the popup browser). The
-  // |extra_info| parameter provides an opportunity to specify extra information
-  // specific to the created popup browser that will be passed to
-  // cef_render_process_handler_t::on_browser_created() in the render process.
+  /// Called on the UI thread before a new popup browser is created. The
+  /// |browser| and |frame| values represent the source of the popup request.
+  /// The |target_url| and |target_frame_name| values indicate where the popup
+  /// browser should navigate and may be NULL if not specified with the request.
+  /// The |target_disposition| value indicates where the user intended to open
+  /// the popup (e.g. current tab, new tab, etc). The |user_gesture| value will
+  /// be true (1) if the popup was opened via explicit user gesture (e.g.
+  /// clicking a link) or false (0) if the popup opened automatically (e.g. via
+  /// the DomContentLoaded event). The |popupFeatures| structure contains
+  /// additional information about the requested popup window. To allow creation
+  /// of the popup browser optionally modify |windowInfo|, |client|, |settings|
+  /// and |no_javascript_access| and return false (0). To cancel creation of the
+  /// popup browser return true (1). The |client| and |settings| values will
+  /// default to the source browser's values. If the |no_javascript_access|
+  /// value is set to false (0) the new browser will not be scriptable and may
+  /// not be hosted in the same renderer process as the source browser. Any
+  /// modifications to |windowInfo| will be ignored if the parent browser is
+  /// wrapped in a cef_browser_view_t. Popup browser creation will be canceled
+  /// if the parent browser is destroyed before the popup browser creation
+  /// completes (indicated by a call to OnAfterCreated for the popup browser).
+  /// The |extra_info| parameter provides an opportunity to specify extra
+  /// information specific to the created popup browser that will be passed to
+  /// cef_render_process_handler_t::on_browser_created() in the render process.
   ///
   int(CEF_CALLBACK* on_before_popup)(
       struct _cef_life_span_handler_t* self,
@@ -93,7 +93,7 @@
       const cef_string_t* target_frame_name,
       cef_window_open_disposition_t target_disposition,
       int user_gesture,
-      const struct _cef_popup_features_t* popupFeatures,
+      const cef_popup_features_t* popupFeatures,
       struct _cef_window_info_t* windowInfo,
       struct _cef_client_t** client,
       struct _cef_browser_settings_t* settings,
@@ -101,114 +101,146 @@
       int* no_javascript_access);
 
   ///
-  // Called after a new browser is created. This callback will be the first
-  // notification that references |browser|.
+  /// Called on the UI thread before a new DevTools popup browser is created.
+  /// The |browser| value represents the source of the popup request. Optionally
+  /// modify |windowInfo|, |client|, |settings| and |extra_info| values. The
+  /// |client|, |settings| and |extra_info| values will default to the source
+  /// browser's values. Any modifications to |windowInfo| will be ignored if the
+  /// parent browser is Views-hosted (wrapped in a cef_browser_view_t).
+  ///
+  /// The |extra_info| parameter provides an opportunity to specify extra
+  /// information specific to the created popup browser that will be passed to
+  /// cef_render_process_handler_t::on_browser_created() in the render process.
+  /// The existing |extra_info| object, if any, will be read-only but may be
+  /// replaced with a new object.
+  ///
+  /// Views-hosted source browsers will create Views-hosted DevTools popups
+  /// unless |use_default_window| is set to to true (1). DevTools popups can be
+  /// blocked by returning true (1) from cef_command_handler_t::OnChromeCommand
+  /// for IDC_DEV_TOOLS. Only used with the Chrome runtime.
+  ///
+  void(CEF_CALLBACK* on_before_dev_tools_popup)(
+      struct _cef_life_span_handler_t* self,
+      struct _cef_browser_t* browser,
+      struct _cef_window_info_t* windowInfo,
+      struct _cef_client_t** client,
+      struct _cef_browser_settings_t* settings,
+      struct _cef_dictionary_value_t** extra_info,
+      int* use_default_window);
+
+  ///
+  /// Called after a new browser is created. It is now safe to begin performing
+  /// actions with |browser|. cef_frame_handler_t callbacks related to initial
+  /// main frame creation will arrive before this callback. See
+  /// cef_frame_handler_t documentation for additional usage information.
   ///
   void(CEF_CALLBACK* on_after_created)(struct _cef_life_span_handler_t* self,
                                        struct _cef_browser_t* browser);
 
   ///
-  // Called when a browser has recieved a request to close. This may result
-  // directly from a call to cef_browser_host_t::*close_browser() or indirectly
-  // if the browser is parented to a top-level window created by CEF and the
-  // user attempts to close that window (by clicking the 'X', for example). The
-  // do_close() function will be called after the JavaScript 'onunload' event
-  // has been fired.
-  //
-  // An application should handle top-level owner window close notifications by
-  // calling cef_browser_host_t::try_close_browser() or
-  // cef_browser_host_t::CloseBrowser(false (0)) instead of allowing the window
-  // to close immediately (see the examples below). This gives CEF an
-  // opportunity to process the 'onbeforeunload' event and optionally cancel the
-  // close before do_close() is called.
-  //
-  // When windowed rendering is enabled CEF will internally create a window or
-  // view to host the browser. In that case returning false (0) from do_close()
-  // will send the standard close notification to the browser's top-level owner
-  // window (e.g. WM_CLOSE on Windows, performClose: on OS X, "delete_event" on
-  // Linux or cef_window_delegate_t::can_close() callback from Views). If the
-  // browser's host window/view has already been destroyed (via view hierarchy
-  // tear-down, for example) then do_close() will not be called for that browser
-  // since is no longer possible to cancel the close.
-  //
-  // When windowed rendering is disabled returning false (0) from do_close()
-  // will cause the browser object to be destroyed immediately.
-  //
-  // If the browser's top-level owner window requires a non-standard close
-  // notification then send that notification from do_close() and return true
-  // (1).
-  //
-  // The cef_life_span_handler_t::on_before_close() function will be called
-  // after do_close() (if do_close() is called) and immediately before the
-  // browser object is destroyed. The application should only exit after
-  // on_before_close() has been called for all existing browsers.
-  //
-  // The below examples describe what should happen during window close when the
-  // browser is parented to an application-provided top-level window.
-  //
-  // Example 1: Using cef_browser_host_t::try_close_browser(). This is
-  // recommended for clients using standard close handling and windows created
-  // on the browser process UI thread. 1.  User clicks the window close button
-  // which sends a close notification to
-  //     the application's top-level window.
-  // 2.  Application's top-level window receives the close notification and
-  //     calls TryCloseBrowser() (which internally calls CloseBrowser(false)).
-  //     TryCloseBrowser() returns false so the client cancels the window close.
-  // 3.  JavaScript 'onbeforeunload' handler executes and shows the close
-  //     confirmation dialog (which can be overridden via
-  //     CefJSDialogHandler::OnBeforeUnloadDialog()).
-  // 4.  User approves the close. 5.  JavaScript 'onunload' handler executes. 6.
-  // CEF sends a close notification to the application's top-level window
-  //     (because DoClose() returned false by default).
-  // 7.  Application's top-level window receives the close notification and
-  //     calls TryCloseBrowser(). TryCloseBrowser() returns true so the client
-  //     allows the window close.
-  // 8.  Application's top-level window is destroyed. 9.  Application's
-  // on_before_close() handler is called and the browser object
-  //     is destroyed.
-  // 10. Application exits by calling cef_quit_message_loop() if no other
-  // browsers
-  //     exist.
-  //
-  // Example 2: Using cef_browser_host_t::CloseBrowser(false (0)) and
-  // implementing the do_close() callback. This is recommended for clients using
-  // non-standard close handling or windows that were not created on the browser
-  // process UI thread. 1.  User clicks the window close button which sends a
-  // close notification to
-  //     the application's top-level window.
-  // 2.  Application's top-level window receives the close notification and:
-  //     A. Calls CefBrowserHost::CloseBrowser(false).
-  //     B. Cancels the window close.
-  // 3.  JavaScript 'onbeforeunload' handler executes and shows the close
-  //     confirmation dialog (which can be overridden via
-  //     CefJSDialogHandler::OnBeforeUnloadDialog()).
-  // 4.  User approves the close. 5.  JavaScript 'onunload' handler executes. 6.
-  // Application's do_close() handler is called. Application will:
-  //     A. Set a flag to indicate that the next close attempt will be allowed.
-  //     B. Return false.
-  // 7.  CEF sends an close notification to the application's top-level window.
-  // 8.  Application's top-level window receives the close notification and
-  //     allows the window to close based on the flag from #6B.
-  // 9.  Application's top-level window is destroyed. 10. Application's
-  // on_before_close() handler is called and the browser object
-  //     is destroyed.
-  // 11. Application exits by calling cef_quit_message_loop() if no other
-  // browsers
-  //     exist.
+  /// Called when a browser has recieved a request to close. This may result
+  /// directly from a call to cef_browser_host_t::*close_browser() or indirectly
+  /// if the browser is parented to a top-level window created by CEF and the
+  /// user attempts to close that window (by clicking the 'X', for example). The
+  /// do_close() function will be called after the JavaScript 'onunload' event
+  /// has been fired.
+  ///
+  /// An application should handle top-level owner window close notifications by
+  /// calling cef_browser_host_t::try_close_browser() or
+  /// cef_browser_host_t::CloseBrowser(false (0)) instead of allowing the window
+  /// to close immediately (see the examples below). This gives CEF an
+  /// opportunity to process the 'onbeforeunload' event and optionally cancel
+  /// the close before do_close() is called.
+  ///
+  /// When windowed rendering is enabled CEF will internally create a window or
+  /// view to host the browser. In that case returning false (0) from do_close()
+  /// will send the standard close notification to the browser's top-level owner
+  /// window (e.g. WM_CLOSE on Windows, performClose: on OS X, "delete_event" on
+  /// Linux or cef_window_delegate_t::can_close() callback from Views). If the
+  /// browser's host window/view has already been destroyed (via view hierarchy
+  /// tear-down, for example) then do_close() will not be called for that
+  /// browser since is no longer possible to cancel the close.
+  ///
+  /// When windowed rendering is disabled returning false (0) from do_close()
+  /// will cause the browser object to be destroyed immediately.
+  ///
+  /// If the browser's top-level owner window requires a non-standard close
+  /// notification then send that notification from do_close() and return true
+  /// (1).
+  ///
+  /// The cef_life_span_handler_t::on_before_close() function will be called
+  /// after do_close() (if do_close() is called) and immediately before the
+  /// browser object is destroyed. The application should only exit after
+  /// on_before_close() has been called for all existing browsers.
+  ///
+  /// The below examples describe what should happen during window close when
+  /// the browser is parented to an application-provided top-level window.
+  ///
+  /// Example 1: Using cef_browser_host_t::try_close_browser(). This is
+  /// recommended for clients using standard close handling and windows created
+  /// on the browser process UI thread. 1.  User clicks the window close button
+  /// which sends a close notification
+  ///     to the application's top-level window.
+  /// 2.  Application's top-level window receives the close notification and
+  ///     calls TryCloseBrowser() (which internally calls CloseBrowser(false)).
+  ///     TryCloseBrowser() returns false so the client cancels the window
+  ///     close.
+  /// 3.  JavaScript 'onbeforeunload' handler executes and shows the close
+  ///     confirmation dialog (which can be overridden via
+  ///     CefJSDialogHandler::OnBeforeUnloadDialog()).
+  /// 4.  User approves the close. 5.  JavaScript 'onunload' handler executes.
+  /// 6.  CEF sends a close notification to the application's top-level window
+  ///     (because DoClose() returned false by default).
+  /// 7.  Application's top-level window receives the close notification and
+  ///     calls TryCloseBrowser(). TryCloseBrowser() returns true so the client
+  ///     allows the window close.
+  /// 8.  Application's top-level window is destroyed. 9.  Application's
+  /// on_before_close() handler is called and the browser object
+  ///     is destroyed.
+  /// 10. Application exits by calling cef_quit_message_loop() if no other
+  /// browsers
+  ///     exist.
+  ///
+  /// Example 2: Using cef_browser_host_t::CloseBrowser(false (0)) and
+  /// implementing the do_close() callback. This is recommended for clients
+  /// using non-standard close handling or windows that were not created on the
+  /// browser process UI thread. 1.  User clicks the window close button which
+  /// sends a close notification
+  ///     to the application's top-level window.
+  /// 2.  Application's top-level window receives the close notification and:
+  ///     A. Calls CefBrowserHost::CloseBrowser(false).
+  ///     B. Cancels the window close.
+  /// 3.  JavaScript 'onbeforeunload' handler executes and shows the close
+  ///     confirmation dialog (which can be overridden via
+  ///     CefJSDialogHandler::OnBeforeUnloadDialog()).
+  /// 4.  User approves the close. 5.  JavaScript 'onunload' handler executes.
+  /// 6.  Application's do_close() handler is called. Application will:
+  ///     A. Set a flag to indicate that the next close attempt will be allowed.
+  ///     B. Return false.
+  /// 7.  CEF sends an close notification to the application's top-level window.
+  /// 8.  Application's top-level window receives the close notification and
+  ///     allows the window to close based on the flag from #6B.
+  /// 9.  Application's top-level window is destroyed. 10. Application's
+  /// on_before_close() handler is called and the browser object
+  ///     is destroyed.
+  /// 11. Application exits by calling cef_quit_message_loop() if no other
+  /// browsers
+  ///     exist.
   ///
   int(CEF_CALLBACK* do_close)(struct _cef_life_span_handler_t* self,
                               struct _cef_browser_t* browser);
 
   ///
-  // Called just before a browser is destroyed. Release all references to the
-  // browser object and do not attempt to execute any functions on the browser
-  // object (other than GetIdentifier or IsSame) after this callback returns.
-  // This callback will be the last notification that references |browser| on
-  // the UI thread. Any in-progress network requests associated with |browser|
-  // will be aborted when the browser is destroyed, and
-  // cef_resource_request_handler_t callbacks related to those requests may
-  // still arrive on the IO thread after this function is called. See do_close()
-  // documentation for additional usage information.
+  /// Called just before a browser is destroyed. Release all references to the
+  /// browser object and do not attempt to execute any functions on the browser
+  /// object (other than IsValid, GetIdentifier or IsSame) after this callback
+  /// returns. cef_frame_handler_t callbacks related to final main frame
+  /// destruction will arrive after this callback and cef_browser_t::IsValid
+  /// will return false (0) at that time. Any in-progress network requests
+  /// associated with |browser| will be aborted when the browser is destroyed,
+  /// and cef_resource_request_handler_t callbacks related to those requests may
+  /// still arrive on the IO thread after this callback. See cef_frame_handler_t
+  /// and do_close() documentation for additional usage information.
   ///
   void(CEF_CALLBACK* on_before_close)(struct _cef_life_span_handler_t* self,
                                       struct _cef_browser_t* browser);
diff --git a/src/include/capi/cef_load_handler_capi.h b/src/include/capi/cef_load_handler_capi.h
index 186eea3..3667b86 100644
--- a/src/include/capi/cef_load_handler_capi.h
+++ b/src/include/capi/cef_load_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=fa3cb1461b9d363c6c7d961f9e291c2fe736170e$
+// $hash=1ee684174554f7d1cf8899992705d072c1c56ae7$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_LOAD_HANDLER_CAPI_H_
@@ -49,22 +49,22 @@
 #endif
 
 ///
-// Implement this structure to handle events related to browser load status. The
-// functions of this structure will be called on the browser process UI thread
-// or render process main thread (TID_RENDERER).
+/// Implement this structure to handle events related to browser load status.
+/// The functions of this structure will be called on the browser process UI
+/// thread or render process main thread (TID_RENDERER).
 ///
 typedef struct _cef_load_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called when the loading state has changed. This callback will be executed
-  // twice -- once when loading is initiated either programmatically or by user
-  // action, and once when loading is terminated due to completion, cancellation
-  // of failure. It will be called before any calls to OnLoadStart and after all
-  // calls to OnLoadError and/or OnLoadEnd.
+  /// Called when the loading state has changed. This callback will be executed
+  /// twice -- once when loading is initiated either programmatically or by user
+  /// action, and once when loading is terminated due to completion,
+  /// cancellation of failure. It will be called before any calls to OnLoadStart
+  /// and after all calls to OnLoadError and/or OnLoadEnd.
   ///
   void(CEF_CALLBACK* on_loading_state_change)(struct _cef_load_handler_t* self,
                                               struct _cef_browser_t* browser,
@@ -73,16 +73,16 @@
                                               int canGoForward);
 
   ///
-  // Called after a navigation has been committed and before the browser begins
-  // loading contents in the frame. The |frame| value will never be NULL -- call
-  // the is_main() function to check if this frame is the main frame.
-  // |transition_type| provides information about the source of the navigation
-  // and an accurate value is only available in the browser process. Multiple
-  // frames may be loading at the same time. Sub-frames may start or continue
-  // loading after the main frame load has ended. This function will not be
-  // called for same page navigations (fragments, history state, etc.) or for
-  // navigations that fail or are canceled before commit. For notification of
-  // overall browser load status use OnLoadingStateChange instead.
+  /// Called after a navigation has been committed and before the browser begins
+  /// loading contents in the frame. The |frame| value will never be NULL --
+  /// call the is_main() function to check if this frame is the main frame.
+  /// |transition_type| provides information about the source of the navigation
+  /// and an accurate value is only available in the browser process. Multiple
+  /// frames may be loading at the same time. Sub-frames may start or continue
+  /// loading after the main frame load has ended. This function will not be
+  /// called for same page navigations (fragments, history state, etc.) or for
+  /// navigations that fail or are canceled before commit. For notification of
+  /// overall browser load status use OnLoadingStateChange instead.
   ///
   void(CEF_CALLBACK* on_load_start)(struct _cef_load_handler_t* self,
                                     struct _cef_browser_t* browser,
@@ -90,14 +90,14 @@
                                     cef_transition_type_t transition_type);
 
   ///
-  // Called when the browser is done loading a frame. The |frame| value will
-  // never be NULL -- call the is_main() function to check if this frame is the
-  // main frame. Multiple frames may be loading at the same time. Sub-frames may
-  // start or continue loading after the main frame load has ended. This
-  // function will not be called for same page navigations (fragments, history
-  // state, etc.) or for navigations that fail or are canceled before commit.
-  // For notification of overall browser load status use OnLoadingStateChange
-  // instead.
+  /// Called when the browser is done loading a frame. The |frame| value will
+  /// never be NULL -- call the is_main() function to check if this frame is the
+  /// main frame. Multiple frames may be loading at the same time. Sub-frames
+  /// may start or continue loading after the main frame load has ended. This
+  /// function will not be called for same page navigations (fragments, history
+  /// state, etc.) or for navigations that fail or are canceled before commit.
+  /// For notification of overall browser load status use OnLoadingStateChange
+  /// instead.
   ///
   void(CEF_CALLBACK* on_load_end)(struct _cef_load_handler_t* self,
                                   struct _cef_browser_t* browser,
@@ -105,11 +105,11 @@
                                   int httpStatusCode);
 
   ///
-  // Called when a navigation fails or is canceled. This function may be called
-  // by itself if before commit or in combination with OnLoadStart/OnLoadEnd if
-  // after commit. |errorCode| is the error code number, |errorText| is the
-  // error text and |failedUrl| is the URL that failed to load. See
-  // net\base\net_error_list.h for complete descriptions of the error codes.
+  /// Called when a navigation fails or is canceled. This function may be called
+  /// by itself if before commit or in combination with OnLoadStart/OnLoadEnd if
+  /// after commit. |errorCode| is the error code number, |errorText| is the
+  /// error text and |failedUrl| is the URL that failed to load. See
+  /// net\base\net_error_list.h for complete descriptions of the error codes.
   ///
   void(CEF_CALLBACK* on_load_error)(struct _cef_load_handler_t* self,
                                     struct _cef_browser_t* browser,
diff --git a/src/include/capi/cef_media_access_handler_capi.h b/src/include/capi/cef_media_access_handler_capi.h
new file mode 100644
index 0000000..3b8c9a8
--- /dev/null
+++ b/src/include/capi/cef_media_access_handler_capi.h
@@ -0,0 +1,108 @@
+// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool and should not edited
+// by hand. See the translator.README.txt file in the tools directory for
+// more information.
+//
+// $hash=91101808168ec0faf1f39b1924579e31478a6616$
+//
+
+#ifndef CEF_INCLUDE_CAPI_CEF_MEDIA_ACCESS_HANDLER_CAPI_H_
+#define CEF_INCLUDE_CAPI_CEF_MEDIA_ACCESS_HANDLER_CAPI_H_
+#pragma once
+
+#include "include/capi/cef_base_capi.h"
+#include "include/capi/cef_browser_capi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///
+// Callback structure used for asynchronous continuation of media access
+// permission requests.
+///
+typedef struct _cef_media_access_callback_t {
+  ///
+  // Base structure.
+  ///
+  cef_base_ref_counted_t base;
+
+  ///
+  // Call to allow or deny media access. If this callback was initiated in
+  // response to a getUserMedia (indicated by
+  // CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE and/or
+  // CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE being set) the
+  // |allowed_permissions| are required to match those given in
+  // |required_permissions| in the OnRequestMediaAccessPermission.
+  ///
+  void(CEF_CALLBACK* cont)(struct _cef_media_access_callback_t* self,
+                           int allowed_permissions);
+
+  ///
+  // Cancel the media access request.
+  ///
+  void(CEF_CALLBACK* cancel)(struct _cef_media_access_callback_t* self);
+} cef_media_access_callback_t;
+
+///
+// Implement this structure to handle events related to media access permission
+// requests. The functions of this structure will be called on the browser
+// process UI thread.
+///
+typedef struct _cef_media_access_handler_t {
+  ///
+  // Base structure.
+  ///
+  cef_base_ref_counted_t base;
+
+  ///
+  // Called when a page requests permission to access media. |requesting_url| is
+  // the URL requesting permission. Return true (1) and call
+  // cef_media_access_callback_t::cont() either in this function or at a later
+  // time to continue or cancel the request. Return false (0) to cancel the
+  // request immediately.
+  ///
+  int(CEF_CALLBACK* on_request_media_access_permission)(
+      struct _cef_media_access_handler_t* self,
+      struct _cef_browser_t* browser,
+      struct _cef_frame_t* frame,
+      const cef_string_t* requesting_url,
+      int32_t requested_permissions,
+      struct _cef_media_access_callback_t* callback);
+} cef_media_access_handler_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // CEF_INCLUDE_CAPI_CEF_MEDIA_ACCESS_HANDLER_CAPI_H_
diff --git a/src/include/capi/cef_media_router_capi.h b/src/include/capi/cef_media_router_capi.h
index a26f12e..27f9d0e 100644
--- a/src/include/capi/cef_media_router_capi.h
+++ b/src/include/capi/cef_media_router_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=9d5077fdb3fe7fa0ff1141f839988ac821eba4bf$
+// $hash=de4a9b856c6951231f446991a9b1efb89096ad3b$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_MEDIA_ROUTER_CAPI_H_
@@ -41,6 +41,7 @@
 #pragma once
 
 #include "include/capi/cef_base_capi.h"
+#include "include/capi/cef_callback_capi.h"
 #include "include/capi/cef_registration_capi.h"
 
 #ifdef __cplusplus
@@ -55,46 +56,46 @@
 struct _cef_media_source_t;
 
 ///
-// Supports discovery of and communication with media devices on the local
-// network via the Cast and DIAL protocols. The functions of this structure may
-// be called on any browser process thread unless otherwise indicated.
+/// Supports discovery of and communication with media devices on the local
+/// network via the Cast and DIAL protocols. The functions of this structure may
+/// be called on any browser process thread unless otherwise indicated.
 ///
 typedef struct _cef_media_router_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Add an observer for MediaRouter events. The observer will remain registered
-  // until the returned Registration object is destroyed.
+  /// Add an observer for MediaRouter events. The observer will remain
+  /// registered until the returned Registration object is destroyed.
   ///
   struct _cef_registration_t*(CEF_CALLBACK* add_observer)(
       struct _cef_media_router_t* self,
       struct _cef_media_observer_t* observer);
 
   ///
-  // Returns a MediaSource object for the specified media source URN. Supported
-  // URN schemes include "cast:" and "dial:", and will be already known by the
-  // client application (e.g. "cast:<appId>?clientId=<clientId>").
+  /// Returns a MediaSource object for the specified media source URN. Supported
+  /// URN schemes include "cast:" and "dial:", and will be already known by the
+  /// client application (e.g. "cast:<appId>?clientId=<clientId>").
   ///
   struct _cef_media_source_t*(CEF_CALLBACK* get_source)(
       struct _cef_media_router_t* self,
       const cef_string_t* urn);
 
   ///
-  // Trigger an asynchronous call to cef_media_observer_t::OnSinks on all
-  // registered observers.
+  /// Trigger an asynchronous call to cef_media_observer_t::OnSinks on all
+  /// registered observers.
   ///
   void(CEF_CALLBACK* notify_current_sinks)(struct _cef_media_router_t* self);
 
   ///
-  // Create a new route between |source| and |sink|. Source and sink must be
-  // valid, compatible (as reported by cef_media_sink_t::IsCompatibleWith), and
-  // a route between them must not already exist. |callback| will be executed on
-  // success or failure. If route creation succeeds it will also trigger an
-  // asynchronous call to cef_media_observer_t::OnRoutes on all registered
-  // observers.
+  /// Create a new route between |source| and |sink|. Source and sink must be
+  /// valid, compatible (as reported by cef_media_sink_t::IsCompatibleWith), and
+  /// a route between them must not already exist. |callback| will be executed
+  /// on success or failure. If route creation succeeds it will also trigger an
+  /// asynchronous call to cef_media_observer_t::OnRoutes on all registered
+  /// observers.
   ///
   void(CEF_CALLBACK* create_route)(
       struct _cef_media_router_t* self,
@@ -103,48 +104,51 @@
       struct _cef_media_route_create_callback_t* callback);
 
   ///
-  // Trigger an asynchronous call to cef_media_observer_t::OnRoutes on all
-  // registered observers.
+  /// Trigger an asynchronous call to cef_media_observer_t::OnRoutes on all
+  /// registered observers.
   ///
   void(CEF_CALLBACK* notify_current_routes)(struct _cef_media_router_t* self);
 } cef_media_router_t;
 
 ///
-// Returns the MediaRouter object associated with the global request context.
-// Equivalent to calling cef_request_context_t::cef_request_context_get_global_c
-// ontext()->get_media_router().
+/// Returns the MediaRouter object associated with the global request context.
+/// If |callback| is non-NULL it will be executed asnychronously on the UI
+/// thread after the manager's storage has been initialized. Equivalent to
+/// calling cef_request_context_t::cef_request_context_get_global_context()->get
+/// _media_router().
 ///
-CEF_EXPORT cef_media_router_t* cef_media_router_get_global();
+CEF_EXPORT cef_media_router_t* cef_media_router_get_global(
+    struct _cef_completion_callback_t* callback);
 
 ///
-// Implemented by the client to observe MediaRouter events and registered via
-// cef_media_router_t::AddObserver. The functions of this structure will be
-// called on the browser process UI thread.
+/// Implemented by the client to observe MediaRouter events and registered via
+/// cef_media_router_t::AddObserver. The functions of this structure will be
+/// called on the browser process UI thread.
 ///
 typedef struct _cef_media_observer_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // The list of available media sinks has changed or
-  // cef_media_router_t::NotifyCurrentSinks was called.
+  /// The list of available media sinks has changed or
+  /// cef_media_router_t::NotifyCurrentSinks was called.
   ///
   void(CEF_CALLBACK* on_sinks)(struct _cef_media_observer_t* self,
                                size_t sinksCount,
                                struct _cef_media_sink_t* const* sinks);
 
   ///
-  // The list of available media routes has changed or
-  // cef_media_router_t::NotifyCurrentRoutes was called.
+  /// The list of available media routes has changed or
+  /// cef_media_router_t::NotifyCurrentRoutes was called.
   ///
   void(CEF_CALLBACK* on_routes)(struct _cef_media_observer_t* self,
                                 size_t routesCount,
                                 struct _cef_media_route_t* const* routes);
 
   ///
-  // The connection state of |route| has changed.
+  /// The connection state of |route| has changed.
   ///
   void(CEF_CALLBACK* on_route_state_changed)(
       struct _cef_media_observer_t* self,
@@ -152,8 +156,8 @@
       cef_media_route_connection_state_t state);
 
   ///
-  // A message was recieved over |route|. |message| is only valid for the scope
-  // of this callback and should be copied if necessary.
+  /// A message was recieved over |route|. |message| is only valid for the scope
+  /// of this callback and should be copied if necessary.
   ///
   void(CEF_CALLBACK* on_route_message_received)(
       struct _cef_media_observer_t* self,
@@ -163,65 +167,65 @@
 } cef_media_observer_t;
 
 ///
-// Represents the route between a media source and sink. Instances of this
-// object are created via cef_media_router_t::CreateRoute and retrieved via
-// cef_media_observer_t::OnRoutes. Contains the status and metadata of a routing
-// operation. The functions of this structure may be called on any browser
-// process thread unless otherwise indicated.
+/// Represents the route between a media source and sink. Instances of this
+/// object are created via cef_media_router_t::CreateRoute and retrieved via
+/// cef_media_observer_t::OnRoutes. Contains the status and metadata of a
+/// routing operation. The functions of this structure may be called on any
+/// browser process thread unless otherwise indicated.
 ///
 typedef struct _cef_media_route_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the ID for this route.
+  /// Returns the ID for this route.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_id)(struct _cef_media_route_t* self);
 
   ///
-  // Returns the source associated with this route.
+  /// Returns the source associated with this route.
   ///
   struct _cef_media_source_t*(CEF_CALLBACK* get_source)(
       struct _cef_media_route_t* self);
 
   ///
-  // Returns the sink associated with this route.
+  /// Returns the sink associated with this route.
   ///
   struct _cef_media_sink_t*(CEF_CALLBACK* get_sink)(
       struct _cef_media_route_t* self);
 
   ///
-  // Send a message over this route. |message| will be copied if necessary.
+  /// Send a message over this route. |message| will be copied if necessary.
   ///
   void(CEF_CALLBACK* send_route_message)(struct _cef_media_route_t* self,
                                          const void* message,
                                          size_t message_size);
 
   ///
-  // Terminate this route. Will result in an asynchronous call to
-  // cef_media_observer_t::OnRoutes on all registered observers.
+  /// Terminate this route. Will result in an asynchronous call to
+  /// cef_media_observer_t::OnRoutes on all registered observers.
   ///
   void(CEF_CALLBACK* terminate)(struct _cef_media_route_t* self);
 } cef_media_route_t;
 
 ///
-// Callback structure for cef_media_router_t::CreateRoute. The functions of this
-// structure will be called on the browser process UI thread.
+/// Callback structure for cef_media_router_t::CreateRoute. The functions of
+/// this structure will be called on the browser process UI thread.
 ///
 typedef struct _cef_media_route_create_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Method that will be executed when the route creation has finished. |result|
-  // will be CEF_MRCR_OK if the route creation succeeded. |error| will be a
-  // description of the error if the route creation failed. |route| is the
-  // resulting route, or NULL if the route creation failed.
+  /// Method that will be executed when the route creation has finished.
+  /// |result| will be CEF_MRCR_OK if the route creation succeeded. |error| will
+  /// be a description of the error if the route creation failed. |route| is the
+  /// resulting route, or NULL if the route creation failed.
   ///
   void(CEF_CALLBACK* on_media_route_create_finished)(
       struct _cef_media_route_create_callback_t* self,
@@ -231,83 +235,71 @@
 } cef_media_route_create_callback_t;
 
 ///
-// Represents a sink to which media can be routed. Instances of this object are
-// retrieved via cef_media_observer_t::OnSinks. The functions of this structure
-// may be called on any browser process thread unless otherwise indicated.
+/// Represents a sink to which media can be routed. Instances of this object are
+/// retrieved via cef_media_observer_t::OnSinks. The functions of this structure
+/// may be called on any browser process thread unless otherwise indicated.
 ///
 typedef struct _cef_media_sink_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the ID for this sink.
+  /// Returns the ID for this sink.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_id)(struct _cef_media_sink_t* self);
 
   ///
-  // Returns true (1) if this sink is valid.
-  ///
-  int(CEF_CALLBACK* is_valid)(struct _cef_media_sink_t* self);
-
-  ///
-  // Returns the name of this sink.
+  /// Returns the name of this sink.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_name)(struct _cef_media_sink_t* self);
 
   ///
-  // Returns the description of this sink.
-  ///
-  // The resulting string must be freed by calling cef_string_userfree_free().
-  cef_string_userfree_t(CEF_CALLBACK* get_description)(
-      struct _cef_media_sink_t* self);
-
-  ///
-  // Returns the icon type for this sink.
+  /// Returns the icon type for this sink.
   ///
   cef_media_sink_icon_type_t(CEF_CALLBACK* get_icon_type)(
       struct _cef_media_sink_t* self);
 
   ///
-  // Asynchronously retrieves device info.
+  /// Asynchronously retrieves device info.
   ///
   void(CEF_CALLBACK* get_device_info)(
       struct _cef_media_sink_t* self,
       struct _cef_media_sink_device_info_callback_t* callback);
 
   ///
-  // Returns true (1) if this sink accepts content via Cast.
+  /// Returns true (1) if this sink accepts content via Cast.
   ///
   int(CEF_CALLBACK* is_cast_sink)(struct _cef_media_sink_t* self);
 
   ///
-  // Returns true (1) if this sink accepts content via DIAL.
+  /// Returns true (1) if this sink accepts content via DIAL.
   ///
   int(CEF_CALLBACK* is_dial_sink)(struct _cef_media_sink_t* self);
 
   ///
-  // Returns true (1) if this sink is compatible with |source|.
+  /// Returns true (1) if this sink is compatible with |source|.
   ///
   int(CEF_CALLBACK* is_compatible_with)(struct _cef_media_sink_t* self,
                                         struct _cef_media_source_t* source);
 } cef_media_sink_t;
 
 ///
-// Callback structure for cef_media_sink_t::GetDeviceInfo. The functions of this
-// structure will be called on the browser process UI thread.
+/// Callback structure for cef_media_sink_t::GetDeviceInfo. The functions of
+/// this structure will be called on the browser process UI thread.
 ///
 typedef struct _cef_media_sink_device_info_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Method that will be executed asyncronously once device information has been
-  // retrieved.
+  /// Method that will be executed asyncronously once device information has
+  /// been retrieved.
   ///
   void(CEF_CALLBACK* on_media_sink_device_info)(
       struct _cef_media_sink_device_info_callback_t* self,
@@ -315,35 +307,30 @@
 } cef_media_sink_device_info_callback_t;
 
 ///
-// Represents a source from which media can be routed. Instances of this object
-// are retrieved via cef_media_router_t::GetSource. The functions of this
-// structure may be called on any browser process thread unless otherwise
-// indicated.
+/// Represents a source from which media can be routed. Instances of this object
+/// are retrieved via cef_media_router_t::GetSource. The functions of this
+/// structure may be called on any browser process thread unless otherwise
+/// indicated.
 ///
 typedef struct _cef_media_source_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the ID (media source URN or URL) for this source.
+  /// Returns the ID (media source URN or URL) for this source.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_id)(struct _cef_media_source_t* self);
 
   ///
-  // Returns true (1) if this source is valid.
-  ///
-  int(CEF_CALLBACK* is_valid)(struct _cef_media_source_t* self);
-
-  ///
-  // Returns true (1) if this source outputs its content via Cast.
+  /// Returns true (1) if this source outputs its content via Cast.
   ///
   int(CEF_CALLBACK* is_cast_source)(struct _cef_media_source_t* self);
 
   ///
-  // Returns true (1) if this source outputs its content via DIAL.
+  /// Returns true (1) if this source outputs its content via DIAL.
   ///
   int(CEF_CALLBACK* is_dial_source)(struct _cef_media_source_t* self);
 } cef_media_source_t;
diff --git a/src/include/capi/cef_menu_model_capi.h b/src/include/capi/cef_menu_model_capi.h
index 6af46d0..8b5bd66 100644
--- a/src/include/capi/cef_menu_model_capi.h
+++ b/src/include/capi/cef_menu_model_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=cce24dba079162b10f359769eea176c4009b5ce5$
+// $hash=d70b78b8108bb08b4f53b2627ed4ebfdffece7c1$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_MENU_MODEL_CAPI_H_
@@ -48,54 +48,54 @@
 #endif
 
 ///
-// Supports creation and modification of menus. See cef_menu_id_t for the
-// command ids that have default implementations. All user-defined command ids
-// should be between MENU_ID_USER_FIRST and MENU_ID_USER_LAST. The functions of
-// this structure can only be accessed on the browser process the UI thread.
+/// Supports creation and modification of menus. See cef_menu_id_t for the
+/// command ids that have default implementations. All user-defined command ids
+/// should be between MENU_ID_USER_FIRST and MENU_ID_USER_LAST. The functions of
+/// this structure can only be accessed on the browser process the UI thread.
 ///
 typedef struct _cef_menu_model_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if this menu is a submenu.
+  /// Returns true (1) if this menu is a submenu.
   ///
   int(CEF_CALLBACK* is_sub_menu)(struct _cef_menu_model_t* self);
 
   ///
-  // Clears the menu. Returns true (1) on success.
+  /// Clears the menu. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* clear)(struct _cef_menu_model_t* self);
 
   ///
-  // Returns the number of items in this menu.
+  /// Returns the number of items in this menu.
   ///
-  int(CEF_CALLBACK* get_count)(struct _cef_menu_model_t* self);
+  size_t(CEF_CALLBACK* get_count)(struct _cef_menu_model_t* self);
 
   ///
-  // Add a separator to the menu. Returns true (1) on success.
+  /// Add a separator to the menu. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* add_separator)(struct _cef_menu_model_t* self);
 
   ///
-  // Add an item to the menu. Returns true (1) on success.
+  /// Add an item to the menu. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* add_item)(struct _cef_menu_model_t* self,
                               int command_id,
                               const cef_string_t* label);
 
   ///
-  // Add a check item to the menu. Returns true (1) on success.
+  /// Add a check item to the menu. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* add_check_item)(struct _cef_menu_model_t* self,
                                     int command_id,
                                     const cef_string_t* label);
 
   ///
-  // Add a radio item to the menu. Only a single item with the specified
-  // |group_id| can be checked at a time. Returns true (1) on success.
+  /// Add a radio item to the menu. Only a single item with the specified
+  /// |group_id| can be checked at a time. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* add_radio_item)(struct _cef_menu_model_t* self,
                                     int command_id,
@@ -103,7 +103,7 @@
                                     int group_id);
 
   ///
-  // Add a sub-menu to the menu. The new sub-menu is returned.
+  /// Add a sub-menu to the menu. The new sub-menu is returned.
   ///
   struct _cef_menu_model_t*(CEF_CALLBACK* add_sub_menu)(
       struct _cef_menu_model_t* self,
@@ -111,260 +111,266 @@
       const cef_string_t* label);
 
   ///
-  // Insert a separator in the menu at the specified |index|. Returns true (1)
-  // on success.
+  /// Insert a separator in the menu at the specified |index|. Returns true (1)
+  /// on success.
   ///
   int(CEF_CALLBACK* insert_separator_at)(struct _cef_menu_model_t* self,
-                                         int index);
+                                         size_t index);
 
   ///
-  // Insert an item in the menu at the specified |index|. Returns true (1) on
-  // success.
+  /// Insert an item in the menu at the specified |index|. Returns true (1) on
+  /// success.
   ///
   int(CEF_CALLBACK* insert_item_at)(struct _cef_menu_model_t* self,
-                                    int index,
+                                    size_t index,
                                     int command_id,
                                     const cef_string_t* label);
 
   ///
-  // Insert a check item in the menu at the specified |index|. Returns true (1)
-  // on success.
+  /// Insert a check item in the menu at the specified |index|. Returns true (1)
+  /// on success.
   ///
   int(CEF_CALLBACK* insert_check_item_at)(struct _cef_menu_model_t* self,
-                                          int index,
+                                          size_t index,
                                           int command_id,
                                           const cef_string_t* label);
 
   ///
-  // Insert a radio item in the menu at the specified |index|. Only a single
-  // item with the specified |group_id| can be checked at a time. Returns true
-  // (1) on success.
+  /// Insert a radio item in the menu at the specified |index|. Only a single
+  /// item with the specified |group_id| can be checked at a time. Returns true
+  /// (1) on success.
   ///
   int(CEF_CALLBACK* insert_radio_item_at)(struct _cef_menu_model_t* self,
-                                          int index,
+                                          size_t index,
                                           int command_id,
                                           const cef_string_t* label,
                                           int group_id);
 
   ///
-  // Insert a sub-menu in the menu at the specified |index|. The new sub-menu is
-  // returned.
+  /// Insert a sub-menu in the menu at the specified |index|. The new sub-menu
+  /// is returned.
   ///
   struct _cef_menu_model_t*(CEF_CALLBACK* insert_sub_menu_at)(
       struct _cef_menu_model_t* self,
-      int index,
+      size_t index,
       int command_id,
       const cef_string_t* label);
 
   ///
-  // Removes the item with the specified |command_id|. Returns true (1) on
-  // success.
+  /// Removes the item with the specified |command_id|. Returns true (1) on
+  /// success.
   ///
   int(CEF_CALLBACK* remove)(struct _cef_menu_model_t* self, int command_id);
 
   ///
-  // Removes the item at the specified |index|. Returns true (1) on success.
+  /// Removes the item at the specified |index|. Returns true (1) on success.
   ///
-  int(CEF_CALLBACK* remove_at)(struct _cef_menu_model_t* self, int index);
+  int(CEF_CALLBACK* remove_at)(struct _cef_menu_model_t* self, size_t index);
 
   ///
-  // Returns the index associated with the specified |command_id| or -1 if not
-  // found due to the command id not existing in the menu.
+  /// Returns the index associated with the specified |command_id| or -1 if not
+  /// found due to the command id not existing in the menu.
   ///
   int(CEF_CALLBACK* get_index_of)(struct _cef_menu_model_t* self,
                                   int command_id);
 
   ///
-  // Returns the command id at the specified |index| or -1 if not found due to
-  // invalid range or the index being a separator.
+  /// Returns the command id at the specified |index| or -1 if not found due to
+  /// invalid range or the index being a separator.
   ///
   int(CEF_CALLBACK* get_command_id_at)(struct _cef_menu_model_t* self,
-                                       int index);
+                                       size_t index);
 
   ///
-  // Sets the command id at the specified |index|. Returns true (1) on success.
+  /// Sets the command id at the specified |index|. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* set_command_id_at)(struct _cef_menu_model_t* self,
-                                       int index,
+                                       size_t index,
                                        int command_id);
 
   ///
-  // Returns the label for the specified |command_id| or NULL if not found.
+  /// Returns the label for the specified |command_id| or NULL if not found.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_label)(struct _cef_menu_model_t* self,
                                                  int command_id);
 
   ///
-  // Returns the label at the specified |index| or NULL if not found due to
-  // invalid range or the index being a separator.
+  /// Returns the label at the specified |index| or NULL if not found due to
+  /// invalid range or the index being a separator.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(
-      CEF_CALLBACK* get_label_at)(struct _cef_menu_model_t* self, int index);
+      CEF_CALLBACK* get_label_at)(struct _cef_menu_model_t* self, size_t index);
 
   ///
-  // Sets the label for the specified |command_id|. Returns true (1) on success.
+  /// Sets the label for the specified |command_id|. Returns true (1) on
+  /// success.
   ///
   int(CEF_CALLBACK* set_label)(struct _cef_menu_model_t* self,
                                int command_id,
                                const cef_string_t* label);
 
   ///
-  // Set the label at the specified |index|. Returns true (1) on success.
+  /// Set the label at the specified |index|. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* set_label_at)(struct _cef_menu_model_t* self,
-                                  int index,
+                                  size_t index,
                                   const cef_string_t* label);
 
   ///
-  // Returns the item type for the specified |command_id|.
+  /// Returns the item type for the specified |command_id|.
   ///
   cef_menu_item_type_t(CEF_CALLBACK* get_type)(struct _cef_menu_model_t* self,
                                                int command_id);
 
   ///
-  // Returns the item type at the specified |index|.
+  /// Returns the item type at the specified |index|.
   ///
   cef_menu_item_type_t(
-      CEF_CALLBACK* get_type_at)(struct _cef_menu_model_t* self, int index);
+      CEF_CALLBACK* get_type_at)(struct _cef_menu_model_t* self, size_t index);
 
   ///
-  // Returns the group id for the specified |command_id| or -1 if invalid.
+  /// Returns the group id for the specified |command_id| or -1 if invalid.
   ///
   int(CEF_CALLBACK* get_group_id)(struct _cef_menu_model_t* self,
                                   int command_id);
 
   ///
-  // Returns the group id at the specified |index| or -1 if invalid.
+  /// Returns the group id at the specified |index| or -1 if invalid.
   ///
-  int(CEF_CALLBACK* get_group_id_at)(struct _cef_menu_model_t* self, int index);
+  int(CEF_CALLBACK* get_group_id_at)(struct _cef_menu_model_t* self,
+                                     size_t index);
 
   ///
-  // Sets the group id for the specified |command_id|. Returns true (1) on
-  // success.
+  /// Sets the group id for the specified |command_id|. Returns true (1) on
+  /// success.
   ///
   int(CEF_CALLBACK* set_group_id)(struct _cef_menu_model_t* self,
                                   int command_id,
                                   int group_id);
 
   ///
-  // Sets the group id at the specified |index|. Returns true (1) on success.
+  /// Sets the group id at the specified |index|. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* set_group_id_at)(struct _cef_menu_model_t* self,
-                                     int index,
+                                     size_t index,
                                      int group_id);
 
   ///
-  // Returns the submenu for the specified |command_id| or NULL if invalid.
+  /// Returns the submenu for the specified |command_id| or NULL if invalid.
   ///
   struct _cef_menu_model_t*(CEF_CALLBACK* get_sub_menu)(
       struct _cef_menu_model_t* self,
       int command_id);
 
   ///
-  // Returns the submenu at the specified |index| or NULL if invalid.
+  /// Returns the submenu at the specified |index| or NULL if invalid.
   ///
-  struct _cef_menu_model_t*(
-      CEF_CALLBACK* get_sub_menu_at)(struct _cef_menu_model_t* self, int index);
+  struct _cef_menu_model_t*(CEF_CALLBACK* get_sub_menu_at)(
+      struct _cef_menu_model_t* self,
+      size_t index);
 
   ///
-  // Returns true (1) if the specified |command_id| is visible.
+  /// Returns true (1) if the specified |command_id| is visible.
   ///
   int(CEF_CALLBACK* is_visible)(struct _cef_menu_model_t* self, int command_id);
 
   ///
-  // Returns true (1) if the specified |index| is visible.
+  /// Returns true (1) if the specified |index| is visible.
   ///
-  int(CEF_CALLBACK* is_visible_at)(struct _cef_menu_model_t* self, int index);
+  int(CEF_CALLBACK* is_visible_at)(struct _cef_menu_model_t* self,
+                                   size_t index);
 
   ///
-  // Change the visibility of the specified |command_id|. Returns true (1) on
-  // success.
+  /// Change the visibility of the specified |command_id|. Returns true (1) on
+  /// success.
   ///
   int(CEF_CALLBACK* set_visible)(struct _cef_menu_model_t* self,
                                  int command_id,
                                  int visible);
 
   ///
-  // Change the visibility at the specified |index|. Returns true (1) on
-  // success.
+  /// Change the visibility at the specified |index|. Returns true (1) on
+  /// success.
   ///
   int(CEF_CALLBACK* set_visible_at)(struct _cef_menu_model_t* self,
-                                    int index,
+                                    size_t index,
                                     int visible);
 
   ///
-  // Returns true (1) if the specified |command_id| is enabled.
+  /// Returns true (1) if the specified |command_id| is enabled.
   ///
   int(CEF_CALLBACK* is_enabled)(struct _cef_menu_model_t* self, int command_id);
 
   ///
-  // Returns true (1) if the specified |index| is enabled.
+  /// Returns true (1) if the specified |index| is enabled.
   ///
-  int(CEF_CALLBACK* is_enabled_at)(struct _cef_menu_model_t* self, int index);
+  int(CEF_CALLBACK* is_enabled_at)(struct _cef_menu_model_t* self,
+                                   size_t index);
 
   ///
-  // Change the enabled status of the specified |command_id|. Returns true (1)
-  // on success.
+  /// Change the enabled status of the specified |command_id|. Returns true (1)
+  /// on success.
   ///
   int(CEF_CALLBACK* set_enabled)(struct _cef_menu_model_t* self,
                                  int command_id,
                                  int enabled);
 
   ///
-  // Change the enabled status at the specified |index|. Returns true (1) on
-  // success.
+  /// Change the enabled status at the specified |index|. Returns true (1) on
+  /// success.
   ///
   int(CEF_CALLBACK* set_enabled_at)(struct _cef_menu_model_t* self,
-                                    int index,
+                                    size_t index,
                                     int enabled);
 
   ///
-  // Returns true (1) if the specified |command_id| is checked. Only applies to
-  // check and radio items.
+  /// Returns true (1) if the specified |command_id| is checked. Only applies to
+  /// check and radio items.
   ///
   int(CEF_CALLBACK* is_checked)(struct _cef_menu_model_t* self, int command_id);
 
   ///
-  // Returns true (1) if the specified |index| is checked. Only applies to check
-  // and radio items.
+  /// Returns true (1) if the specified |index| is checked. Only applies to
+  /// check and radio items.
   ///
-  int(CEF_CALLBACK* is_checked_at)(struct _cef_menu_model_t* self, int index);
+  int(CEF_CALLBACK* is_checked_at)(struct _cef_menu_model_t* self,
+                                   size_t index);
 
   ///
-  // Check the specified |command_id|. Only applies to check and radio items.
-  // Returns true (1) on success.
+  /// Check the specified |command_id|. Only applies to check and radio items.
+  /// Returns true (1) on success.
   ///
   int(CEF_CALLBACK* set_checked)(struct _cef_menu_model_t* self,
                                  int command_id,
                                  int checked);
 
   ///
-  // Check the specified |index|. Only applies to check and radio items. Returns
-  // true (1) on success.
+  /// Check the specified |index|. Only applies to check and radio items.
+  /// Returns true (1) on success.
   ///
   int(CEF_CALLBACK* set_checked_at)(struct _cef_menu_model_t* self,
-                                    int index,
+                                    size_t index,
                                     int checked);
 
   ///
-  // Returns true (1) if the specified |command_id| has a keyboard accelerator
-  // assigned.
+  /// Returns true (1) if the specified |command_id| has a keyboard accelerator
+  /// assigned.
   ///
   int(CEF_CALLBACK* has_accelerator)(struct _cef_menu_model_t* self,
                                      int command_id);
 
   ///
-  // Returns true (1) if the specified |index| has a keyboard accelerator
-  // assigned.
+  /// Returns true (1) if the specified |index| has a keyboard accelerator
+  /// assigned.
   ///
   int(CEF_CALLBACK* has_accelerator_at)(struct _cef_menu_model_t* self,
-                                        int index);
+                                        size_t index);
 
   ///
-  // Set the keyboard accelerator for the specified |command_id|. |key_code| can
-  // be any virtual key or character value. Returns true (1) on success.
+  /// Set the keyboard accelerator for the specified |command_id|. |key_code|
+  /// can be any virtual key or character value. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* set_accelerator)(struct _cef_menu_model_t* self,
                                      int command_id,
@@ -374,33 +380,33 @@
                                      int alt_pressed);
 
   ///
-  // Set the keyboard accelerator at the specified |index|. |key_code| can be
-  // any virtual key or character value. Returns true (1) on success.
+  /// Set the keyboard accelerator at the specified |index|. |key_code| can be
+  /// any virtual key or character value. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* set_accelerator_at)(struct _cef_menu_model_t* self,
-                                        int index,
+                                        size_t index,
                                         int key_code,
                                         int shift_pressed,
                                         int ctrl_pressed,
                                         int alt_pressed);
 
   ///
-  // Remove the keyboard accelerator for the specified |command_id|. Returns
-  // true (1) on success.
+  /// Remove the keyboard accelerator for the specified |command_id|. Returns
+  /// true (1) on success.
   ///
   int(CEF_CALLBACK* remove_accelerator)(struct _cef_menu_model_t* self,
                                         int command_id);
 
   ///
-  // Remove the keyboard accelerator at the specified |index|. Returns true (1)
-  // on success.
+  /// Remove the keyboard accelerator at the specified |index|. Returns true (1)
+  /// on success.
   ///
   int(CEF_CALLBACK* remove_accelerator_at)(struct _cef_menu_model_t* self,
-                                           int index);
+                                           size_t index);
 
   ///
-  // Retrieves the keyboard accelerator for the specified |command_id|. Returns
-  // true (1) on success.
+  /// Retrieves the keyboard accelerator for the specified |command_id|. Returns
+  /// true (1) on success.
   ///
   int(CEF_CALLBACK* get_accelerator)(struct _cef_menu_model_t* self,
                                      int command_id,
@@ -410,21 +416,21 @@
                                      int* alt_pressed);
 
   ///
-  // Retrieves the keyboard accelerator for the specified |index|. Returns true
-  // (1) on success.
+  /// Retrieves the keyboard accelerator for the specified |index|. Returns true
+  /// (1) on success.
   ///
   int(CEF_CALLBACK* get_accelerator_at)(struct _cef_menu_model_t* self,
-                                        int index,
+                                        size_t index,
                                         int* key_code,
                                         int* shift_pressed,
                                         int* ctrl_pressed,
                                         int* alt_pressed);
 
   ///
-  // Set the explicit color for |command_id| and |color_type| to |color|.
-  // Specify a |color| value of 0 to remove the explicit color. If no explicit
-  // color or default color is set for |color_type| then the system color will
-  // be used. Returns true (1) on success.
+  /// Set the explicit color for |command_id| and |color_type| to |color|.
+  /// Specify a |color| value of 0 to remove the explicit color. If no explicit
+  /// color or default color is set for |color_type| then the system color will
+  /// be used. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* set_color)(struct _cef_menu_model_t* self,
                                int command_id,
@@ -432,11 +438,11 @@
                                cef_color_t color);
 
   ///
-  // Set the explicit color for |command_id| and |index| to |color|. Specify a
-  // |color| value of 0 to remove the explicit color. Specify an |index| value
-  // of -1 to set the default color for items that do not have an explicit color
-  // set. If no explicit color or default color is set for |color_type| then the
-  // system color will be used. Returns true (1) on success.
+  /// Set the explicit color for |command_id| and |index| to |color|. Specify a
+  /// |color| value of 0 to remove the explicit color. Specify an |index| value
+  /// of -1 to set the default color for items that do not have an explicit
+  /// color set. If no explicit color or default color is set for |color_type|
+  /// then the system color will be used. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* set_color_at)(struct _cef_menu_model_t* self,
                                   int index,
@@ -444,9 +450,9 @@
                                   cef_color_t color);
 
   ///
-  // Returns in |color| the color that was explicitly set for |command_id| and
-  // |color_type|. If a color was not set then 0 will be returned in |color|.
-  // Returns true (1) on success.
+  /// Returns in |color| the color that was explicitly set for |command_id| and
+  /// |color_type|. If a color was not set then 0 will be returned in |color|.
+  /// Returns true (1) on success.
   ///
   int(CEF_CALLBACK* get_color)(struct _cef_menu_model_t* self,
                                int command_id,
@@ -454,10 +460,10 @@
                                cef_color_t* color);
 
   ///
-  // Returns in |color| the color that was explicitly set for |command_id| and
-  // |color_type|. Specify an |index| value of -1 to return the default color in
-  // |color|. If a color was not set then 0 will be returned in |color|. Returns
-  // true (1) on success.
+  /// Returns in |color| the color that was explicitly set for |command_id| and
+  /// |color_type|. Specify an |index| value of -1 to return the default color
+  /// in |color|. If a color was not set then 0 will be returned in |color|.
+  /// Returns true (1) on success.
   ///
   int(CEF_CALLBACK* get_color_at)(struct _cef_menu_model_t* self,
                                   int index,
@@ -465,33 +471,33 @@
                                   cef_color_t* color);
 
   ///
-  // Sets the font list for the specified |command_id|. If |font_list| is NULL
-  // the system font will be used. Returns true (1) on success. The format is
-  // "<FONT_FAMILY_LIST>,[STYLES] <SIZE>", where: - FONT_FAMILY_LIST is a comma-
-  // separated list of font family names, - STYLES is an optional space-
-  // separated list of style names (case-sensitive
-  //   "Bold" and "Italic" are supported), and
-  // - SIZE is an integer font size in pixels with the suffix "px".
-  //
-  // Here are examples of valid font description strings: - "Arial, Helvetica,
-  // Bold Italic 14px" - "Arial, 14px"
+  /// Sets the font list for the specified |command_id|. If |font_list| is NULL
+  /// the system font will be used. Returns true (1) on success. The format is
+  /// "<FONT_FAMILY_LIST>,[STYLES] <SIZE>", where: - FONT_FAMILY_LIST is a
+  /// comma-separated list of font family names, - STYLES is an optional space-
+  /// separated list of style names
+  ///   (case-sensitive "Bold" and "Italic" are supported), and
+  /// - SIZE is an integer font size in pixels with the suffix "px".
+  ///
+  /// Here are examples of valid font description strings: - "Arial, Helvetica,
+  /// Bold Italic 14px" - "Arial, 14px"
   ///
   int(CEF_CALLBACK* set_font_list)(struct _cef_menu_model_t* self,
                                    int command_id,
                                    const cef_string_t* font_list);
 
   ///
-  // Sets the font list for the specified |index|. Specify an |index| value of
-  // -1 to set the default font. If |font_list| is NULL the system font will be
-  // used. Returns true (1) on success. The format is
-  // "<FONT_FAMILY_LIST>,[STYLES] <SIZE>", where: - FONT_FAMILY_LIST is a comma-
-  // separated list of font family names, - STYLES is an optional space-
-  // separated list of style names (case-sensitive
-  //   "Bold" and "Italic" are supported), and
-  // - SIZE is an integer font size in pixels with the suffix "px".
-  //
-  // Here are examples of valid font description strings: - "Arial, Helvetica,
-  // Bold Italic 14px" - "Arial, 14px"
+  /// Sets the font list for the specified |index|. Specify an |index| value of
+  /// -1 to set the default font. If |font_list| is NULL the system font will be
+  /// used. Returns true (1) on success. The format is
+  /// "<FONT_FAMILY_LIST>,[STYLES] <SIZE>", where: - FONT_FAMILY_LIST is a
+  /// comma-separated list of font family names, - STYLES is an optional space-
+  /// separated list of style names
+  ///   (case-sensitive "Bold" and "Italic" are supported), and
+  /// - SIZE is an integer font size in pixels with the suffix "px".
+  ///
+  /// Here are examples of valid font description strings: - "Arial, Helvetica,
+  /// Bold Italic 14px" - "Arial, 14px"
   ///
   int(CEF_CALLBACK* set_font_list_at)(struct _cef_menu_model_t* self,
                                       int index,
@@ -499,7 +505,7 @@
 } cef_menu_model_t;
 
 ///
-// Create a new MenuModel with the specified |delegate|.
+/// Create a new MenuModel with the specified |delegate|.
 ///
 CEF_EXPORT cef_menu_model_t* cef_menu_model_create(
     struct _cef_menu_model_delegate_t* delegate);
diff --git a/src/include/capi/cef_menu_model_delegate_capi.h b/src/include/capi/cef_menu_model_delegate_capi.h
index 1d9b0f8..dd339c1 100644
--- a/src/include/capi/cef_menu_model_delegate_capi.h
+++ b/src/include/capi/cef_menu_model_delegate_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=071ec8a0e17d3b33acbf36c7ccc26d0995657cf3$
+// $hash=933a90dfb7b94a3aba7f2944e4540662dc8c79d7$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_MENU_MODEL_DELEGATE_CAPI_H_
@@ -49,19 +49,19 @@
 struct _cef_menu_model_t;
 
 ///
-// Implement this structure to handle menu model events. The functions of this
-// structure will be called on the browser process UI thread unless otherwise
-// indicated.
+/// Implement this structure to handle menu model events. The functions of this
+/// structure will be called on the browser process UI thread unless otherwise
+/// indicated.
 ///
 typedef struct _cef_menu_model_delegate_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Perform the action associated with the specified |command_id| and optional
-  // |event_flags|.
+  /// Perform the action associated with the specified |command_id| and optional
+  /// |event_flags|.
   ///
   void(CEF_CALLBACK* execute_command)(struct _cef_menu_model_delegate_t* self,
                                       struct _cef_menu_model_t* menu_model,
@@ -69,8 +69,8 @@
                                       cef_event_flags_t event_flags);
 
   ///
-  // Called when the user moves the mouse outside the menu and over the owning
-  // window.
+  /// Called when the user moves the mouse outside the menu and over the owning
+  /// window.
   ///
   void(CEF_CALLBACK* mouse_outside_menu)(
       struct _cef_menu_model_delegate_t* self,
@@ -78,8 +78,8 @@
       const cef_point_t* screen_point);
 
   ///
-  // Called on unhandled open submenu keyboard commands. |is_rtl| will be true
-  // (1) if the menu is displaying a right-to-left language.
+  /// Called on unhandled open submenu keyboard commands. |is_rtl| will be true
+  /// (1) if the menu is displaying a right-to-left language.
   ///
   void(CEF_CALLBACK* unhandled_open_submenu)(
       struct _cef_menu_model_delegate_t* self,
@@ -87,8 +87,8 @@
       int is_rtl);
 
   ///
-  // Called on unhandled close submenu keyboard commands. |is_rtl| will be true
-  // (1) if the menu is displaying a right-to-left language.
+  /// Called on unhandled close submenu keyboard commands. |is_rtl| will be true
+  /// (1) if the menu is displaying a right-to-left language.
   ///
   void(CEF_CALLBACK* unhandled_close_submenu)(
       struct _cef_menu_model_delegate_t* self,
@@ -96,20 +96,20 @@
       int is_rtl);
 
   ///
-  // The menu is about to show.
+  /// The menu is about to show.
   ///
   void(CEF_CALLBACK* menu_will_show)(struct _cef_menu_model_delegate_t* self,
                                      struct _cef_menu_model_t* menu_model);
 
   ///
-  // The menu has closed.
+  /// The menu has closed.
   ///
   void(CEF_CALLBACK* menu_closed)(struct _cef_menu_model_delegate_t* self,
                                   struct _cef_menu_model_t* menu_model);
 
   ///
-  // Optionally modify a menu item label. Return true (1) if |label| was
-  // modified.
+  /// Optionally modify a menu item label. Return true (1) if |label| was
+  /// modified.
   ///
   int(CEF_CALLBACK* format_label)(struct _cef_menu_model_delegate_t* self,
                                   struct _cef_menu_model_t* menu_model,
diff --git a/src/include/capi/cef_navigation_entry_capi.h b/src/include/capi/cef_navigation_entry_capi.h
index 6dc23c9..863c11d 100644
--- a/src/include/capi/cef_navigation_entry_capi.h
+++ b/src/include/capi/cef_navigation_entry_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=c6252024911652a4881d753aeeeb2615e6be3904$
+// $hash=d33771c31b7b0964aa2ccf1c2bc2ca1226194977$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_NAVIGATION_ENTRY_CAPI_H_
@@ -48,78 +48,79 @@
 #endif
 
 ///
-// Structure used to represent an entry in navigation history.
+/// Structure used to represent an entry in navigation history.
 ///
 typedef struct _cef_navigation_entry_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if this object is valid. Do not call any other functions
-  // if this function returns false (0).
+  /// Returns true (1) if this object is valid. Do not call any other functions
+  /// if this function returns false (0).
   ///
   int(CEF_CALLBACK* is_valid)(struct _cef_navigation_entry_t* self);
 
   ///
-  // Returns the actual URL of the page. For some pages this may be data: URL or
-  // similar. Use get_display_url() to return a display-friendly version.
+  /// Returns the actual URL of the page. For some pages this may be data: URL
+  /// or similar. Use get_display_url() to return a display-friendly version.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_url)(
       struct _cef_navigation_entry_t* self);
 
   ///
-  // Returns a display-friendly version of the URL.
+  /// Returns a display-friendly version of the URL.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_display_url)(
       struct _cef_navigation_entry_t* self);
 
   ///
-  // Returns the original URL that was entered by the user before any redirects.
+  /// Returns the original URL that was entered by the user before any
+  /// redirects.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_original_url)(
       struct _cef_navigation_entry_t* self);
 
   ///
-  // Returns the title set by the page. This value may be NULL.
+  /// Returns the title set by the page. This value may be NULL.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_title)(
       struct _cef_navigation_entry_t* self);
 
   ///
-  // Returns the transition type which indicates what the user did to move to
-  // this page from the previous page.
+  /// Returns the transition type which indicates what the user did to move to
+  /// this page from the previous page.
   ///
   cef_transition_type_t(CEF_CALLBACK* get_transition_type)(
       struct _cef_navigation_entry_t* self);
 
   ///
-  // Returns true (1) if this navigation includes post data.
+  /// Returns true (1) if this navigation includes post data.
   ///
   int(CEF_CALLBACK* has_post_data)(struct _cef_navigation_entry_t* self);
 
   ///
-  // Returns the time for the last known successful navigation completion. A
-  // navigation may be completed more than once if the page is reloaded. May be
-  // 0 if the navigation has not yet completed.
+  /// Returns the time for the last known successful navigation completion. A
+  /// navigation may be completed more than once if the page is reloaded. May be
+  /// 0 if the navigation has not yet completed.
   ///
-  cef_time_t(CEF_CALLBACK* get_completion_time)(
+  cef_basetime_t(CEF_CALLBACK* get_completion_time)(
       struct _cef_navigation_entry_t* self);
 
   ///
-  // Returns the HTTP status code for the last known successful navigation
-  // response. May be 0 if the response has not yet been received or if the
-  // navigation has not yet completed.
+  /// Returns the HTTP status code for the last known successful navigation
+  /// response. May be 0 if the response has not yet been received or if the
+  /// navigation has not yet completed.
   ///
   int(CEF_CALLBACK* get_http_status_code)(struct _cef_navigation_entry_t* self);
 
   ///
-  // Returns the SSL information for this navigation entry.
+  /// Returns the SSL information for this navigation entry.
   ///
   struct _cef_sslstatus_t*(CEF_CALLBACK* get_sslstatus)(
       struct _cef_navigation_entry_t* self);
diff --git a/src/include/capi/cef_origin_whitelist_capi.h b/src/include/capi/cef_origin_whitelist_capi.h
index 6742165..f10a37a 100644
--- a/src/include/capi/cef_origin_whitelist_capi.h
+++ b/src/include/capi/cef_origin_whitelist_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=8a26e2f8273298dcf44d6fbf32fd565f6aaa912c$
+// $hash=9330c709713a10c1e6b55278428e65c07f4c9dfb$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_ORIGIN_WHITELIST_CAPI_H_
@@ -47,40 +47,41 @@
 #endif
 
 ///
-// Add an entry to the cross-origin access whitelist.
-//
-// The same-origin policy restricts how scripts hosted from different origins
-// (scheme + domain + port) can communicate. By default, scripts can only access
-// resources with the same origin. Scripts hosted on the HTTP and HTTPS schemes
-// (but no other schemes) can use the "Access-Control-Allow-Origin" header to
-// allow cross-origin requests. For example, https://source.example.com can make
-// XMLHttpRequest requests on http://target.example.com if the
-// http://target.example.com request returns an "Access-Control-Allow-Origin:
-// https://source.example.com" response header.
-//
-// Scripts in separate frames or iframes and hosted from the same protocol and
-// domain suffix can execute cross-origin JavaScript if both pages set the
-// document.domain value to the same domain suffix. For example,
-// scheme://foo.example.com and scheme://bar.example.com can communicate using
-// JavaScript if both domains set document.domain="example.com".
-//
-// This function is used to allow access to origins that would otherwise violate
-// the same-origin policy. Scripts hosted underneath the fully qualified
-// |source_origin| URL (like http://www.example.com) will be allowed access to
-// all resources hosted on the specified |target_protocol| and |target_domain|.
-// If |target_domain| is non-NULL and |allow_target_subdomains| if false (0)
-// only exact domain matches will be allowed. If |target_domain| contains a top-
-// level domain component (like "example.com") and |allow_target_subdomains| is
-// true (1) sub-domain matches will be allowed. If |target_domain| is NULL and
-// |allow_target_subdomains| if true (1) all domains and IP addresses will be
-// allowed.
-//
-// This function cannot be used to bypass the restrictions on local or display
-// isolated schemes. See the comments on CefRegisterCustomScheme for more
-// information.
-//
-// This function may be called on any thread. Returns false (0) if
-// |source_origin| is invalid or the whitelist cannot be accessed.
+/// Add an entry to the cross-origin access whitelist.
+///
+/// The same-origin policy restricts how scripts hosted from different origins
+/// (scheme + domain + port) can communicate. By default, scripts can only
+/// access resources with the same origin. Scripts hosted on the HTTP and HTTPS
+/// schemes (but no other schemes) can use the "Access-Control-Allow-Origin"
+/// header to allow cross-origin requests. For example,
+/// https://source.example.com can make XMLHttpRequest requests on
+/// http://target.example.com if the http://target.example.com request returns
+/// an "Access-Control-Allow-Origin: https://source.example.com" response
+/// header.
+///
+/// Scripts in separate frames or iframes and hosted from the same protocol and
+/// domain suffix can execute cross-origin JavaScript if both pages set the
+/// document.domain value to the same domain suffix. For example,
+/// scheme://foo.example.com and scheme://bar.example.com can communicate using
+/// JavaScript if both domains set document.domain="example.com".
+///
+/// This function is used to allow access to origins that would otherwise
+/// violate the same-origin policy. Scripts hosted underneath the fully
+/// qualified |source_origin| URL (like http://www.example.com) will be allowed
+/// access to all resources hosted on the specified |target_protocol| and
+/// |target_domain|. If |target_domain| is non-NULL and
+/// |allow_target_subdomains| is false (0) only exact domain matches will be
+/// allowed. If |target_domain| contains a top- level domain component (like
+/// "example.com") and |allow_target_subdomains| is true (1) sub-domain matches
+/// will be allowed. If |target_domain| is NULL and |allow_target_subdomains| if
+/// true (1) all domains and IP addresses will be allowed.
+///
+/// This function cannot be used to bypass the restrictions on local or display
+/// isolated schemes. See the comments on CefRegisterCustomScheme for more
+/// information.
+///
+/// This function may be called on any thread. Returns false (0) if
+/// |source_origin| is invalid or the whitelist cannot be accessed.
 ///
 CEF_EXPORT int cef_add_cross_origin_whitelist_entry(
     const cef_string_t* source_origin,
@@ -89,8 +90,8 @@
     int allow_target_subdomains);
 
 ///
-// Remove an entry from the cross-origin access whitelist. Returns false (0) if
-// |source_origin| is invalid or the whitelist cannot be accessed.
+/// Remove an entry from the cross-origin access whitelist. Returns false (0) if
+/// |source_origin| is invalid or the whitelist cannot be accessed.
 ///
 CEF_EXPORT int cef_remove_cross_origin_whitelist_entry(
     const cef_string_t* source_origin,
@@ -99,10 +100,10 @@
     int allow_target_subdomains);
 
 ///
-// Remove all entries from the cross-origin access whitelist. Returns false (0)
-// if the whitelist cannot be accessed.
+/// Remove all entries from the cross-origin access whitelist. Returns false (0)
+/// if the whitelist cannot be accessed.
 ///
-CEF_EXPORT int cef_clear_cross_origin_whitelist();
+CEF_EXPORT int cef_clear_cross_origin_whitelist(void);
 
 #ifdef __cplusplus
 }
diff --git a/src/include/capi/cef_parser_capi.h b/src/include/capi/cef_parser_capi.h
index 51e51bb..a6410c2 100644
--- a/src/include/capi/cef_parser_capi.h
+++ b/src/include/capi/cef_parser_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=14cf03e02d8ca3416e65f756470afd8185c7bc78$
+// $hash=5d6dad4bfaeef0117d068b6e67a8da7490fe7c2d$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_PARSER_CAPI_H_
@@ -47,84 +47,92 @@
 #endif
 
 ///
-// Parse the specified |url| into its component parts. Returns false (0) if the
-// URL is NULL or invalid.
+/// Combines specified |base_url| and |relative_url| into |resolved_url|.
+/// Returns false (0) if one of the URLs is NULL or invalid.
+///
+CEF_EXPORT int cef_resolve_url(const cef_string_t* base_url,
+                               const cef_string_t* relative_url,
+                               cef_string_t* resolved_url);
+
+///
+/// Parse the specified |url| into its component parts. Returns false (0) if the
+/// URL is NULL or invalid.
 ///
 CEF_EXPORT int cef_parse_url(const cef_string_t* url,
                              struct _cef_urlparts_t* parts);
 
 ///
-// Creates a URL from the specified |parts|, which must contain a non-NULL spec
-// or a non-NULL host and path (at a minimum), but not both. Returns false (0)
-// if |parts| isn't initialized as described.
+/// Creates a URL from the specified |parts|, which must contain a non-NULL spec
+/// or a non-NULL host and path (at a minimum), but not both. Returns false (0)
+/// if |parts| isn't initialized as described.
 ///
 CEF_EXPORT int cef_create_url(const struct _cef_urlparts_t* parts,
                               cef_string_t* url);
 
 ///
-// This is a convenience function for formatting a URL in a concise and human-
-// friendly way to help users make security-related decisions (or in other
-// circumstances when people need to distinguish sites, origins, or otherwise-
-// simplified URLs from each other). Internationalized domain names (IDN) may be
-// presented in Unicode if the conversion is considered safe. The returned value
-// will (a) omit the path for standard schemes, excepting file and filesystem,
-// and (b) omit the port if it is the default for the scheme. Do not use this
-// for URLs which will be parsed or sent to other applications.
+/// This is a convenience function for formatting a URL in a concise and human-
+/// friendly way to help users make security-related decisions (or in other
+/// circumstances when people need to distinguish sites, origins, or otherwise-
+/// simplified URLs from each other). Internationalized domain names (IDN) may
+/// be presented in Unicode if the conversion is considered safe. The returned
+/// value will (a) omit the path for standard schemes, excepting file and
+/// filesystem, and (b) omit the port if it is the default for the scheme. Do
+/// not use this for URLs which will be parsed or sent to other applications.
 ///
 // The resulting string must be freed by calling cef_string_userfree_free().
 CEF_EXPORT cef_string_userfree_t
 cef_format_url_for_security_display(const cef_string_t* origin_url);
 
 ///
-// Returns the mime type for the specified file extension or an NULL string if
-// unknown.
+/// Returns the mime type for the specified file extension or an NULL string if
+/// unknown.
 ///
 // The resulting string must be freed by calling cef_string_userfree_free().
 CEF_EXPORT cef_string_userfree_t
 cef_get_mime_type(const cef_string_t* extension);
 
 ///
-// Get the extensions associated with the given mime type. This should be passed
-// in lower case. There could be multiple extensions for a given mime type, like
-// "html,htm" for "text/html", or "txt,text,html,..." for "text/*". Any existing
-// elements in the provided vector will not be erased.
+/// Get the extensions associated with the given mime type. This should be
+/// passed in lower case. There could be multiple extensions for a given mime
+/// type, like "html,htm" for "text/html", or "txt,text,html,..." for "text/*".
+/// Any existing elements in the provided vector will not be erased.
 ///
 CEF_EXPORT void cef_get_extensions_for_mime_type(const cef_string_t* mime_type,
                                                  cef_string_list_t extensions);
 
 ///
-// Encodes |data| as a base64 string.
+/// Encodes |data| as a base64 string.
 ///
 // The resulting string must be freed by calling cef_string_userfree_free().
 CEF_EXPORT cef_string_userfree_t cef_base64encode(const void* data,
                                                   size_t data_size);
 
 ///
-// Decodes the base64 encoded string |data|. The returned value will be NULL if
-// the decoding fails.
+/// Decodes the base64 encoded string |data|. The returned value will be NULL if
+/// the decoding fails.
 ///
 CEF_EXPORT struct _cef_binary_value_t* cef_base64decode(
     const cef_string_t* data);
 
 ///
-// Escapes characters in |text| which are unsuitable for use as a query
-// parameter value. Everything except alphanumerics and -_.!~*'() will be
-// converted to "%XX". If |use_plus| is true (1) spaces will change to "+". The
-// result is basically the same as encodeURIComponent in Javacript.
+/// Escapes characters in |text| which are unsuitable for use as a query
+/// parameter value. Everything except alphanumerics and -_.!~*'() will be
+/// converted to "%XX". If |use_plus| is true (1) spaces will change to "+". The
+/// result is basically the same as encodeURIComponent in Javacript.
 ///
 // The resulting string must be freed by calling cef_string_userfree_free().
 CEF_EXPORT cef_string_userfree_t cef_uriencode(const cef_string_t* text,
                                                int use_plus);
 
 ///
-// Unescapes |text| and returns the result. Unescaping consists of looking for
-// the exact pattern "%XX" where each X is a hex digit and converting to the
-// character with the numerical value of those digits (e.g. "i%20=%203%3b"
-// unescapes to "i = 3;"). If |convert_to_utf8| is true (1) this function will
-// attempt to interpret the initial decoded result as UTF-8. If the result is
-// convertable into UTF-8 it will be returned as converted. Otherwise the
-// initial decoded result will be returned.  The |unescape_rule| parameter
-// supports further customization the decoding process.
+/// Unescapes |text| and returns the result. Unescaping consists of looking for
+/// the exact pattern "%XX" where each X is a hex digit and converting to the
+/// character with the numerical value of those digits (e.g. "i%20=%203%3b"
+/// unescapes to "i = 3;"). If |convert_to_utf8| is true (1) this function will
+/// attempt to interpret the initial decoded result as UTF-8. If the result is
+/// convertable into UTF-8 it will be returned as converted. Otherwise the
+/// initial decoded result will be returned.  The |unescape_rule| parameter
+/// supports further customization the decoding process.
 ///
 // The resulting string must be freed by calling cef_string_userfree_free().
 CEF_EXPORT cef_string_userfree_t
@@ -133,17 +141,17 @@
               cef_uri_unescape_rule_t unescape_rule);
 
 ///
-// Parses the specified |json_string| and returns a dictionary or list
-// representation. If JSON parsing fails this function returns NULL.
+/// Parses the specified |json_string| and returns a dictionary or list
+/// representation. If JSON parsing fails this function returns NULL.
 ///
 CEF_EXPORT struct _cef_value_t* cef_parse_json(
     const cef_string_t* json_string,
     cef_json_parser_options_t options);
 
 ///
-// Parses the specified UTF8-encoded |json| buffer of size |json_size| and
-// returns a dictionary or list representation. If JSON parsing fails this
-// function returns NULL.
+/// Parses the specified UTF8-encoded |json| buffer of size |json_size| and
+/// returns a dictionary or list representation. If JSON parsing fails this
+/// function returns NULL.
 ///
 CEF_EXPORT struct _cef_value_t* cef_parse_json_buffer(
     const void* json,
@@ -151,21 +159,19 @@
     cef_json_parser_options_t options);
 
 ///
-// Parses the specified |json_string| and returns a dictionary or list
-// representation. If JSON parsing fails this function returns NULL and
-// populates |error_code_out| and |error_msg_out| with an error code and a
-// formatted error message respectively.
+/// Parses the specified |json_string| and returns a dictionary or list
+/// representation. If JSON parsing fails this function returns NULL and
+/// populates |error_msg_out| with a formatted error message.
 ///
 CEF_EXPORT struct _cef_value_t* cef_parse_jsonand_return_error(
     const cef_string_t* json_string,
     cef_json_parser_options_t options,
-    cef_json_parser_error_t* error_code_out,
     cef_string_t* error_msg_out);
 
 ///
-// Generates a JSON string from the specified root |node| which should be a
-// dictionary or list value. Returns an NULL string on failure. This function
-// requires exclusive access to |node| including any underlying data.
+/// Generates a JSON string from the specified root |node| which should be a
+/// dictionary or list value. Returns an NULL string on failure. This function
+/// requires exclusive access to |node| including any underlying data.
 ///
 // The resulting string must be freed by calling cef_string_userfree_free().
 CEF_EXPORT cef_string_userfree_t
diff --git a/src/include/capi/cef_path_util_capi.h b/src/include/capi/cef_path_util_capi.h
index f4405be..5706b83 100644
--- a/src/include/capi/cef_path_util_capi.h
+++ b/src/include/capi/cef_path_util_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=1b218a91d7f3ba0e68f0c3be21a0df91e515d28a$
+// $hash=70b306534b9cb8334c9ea260feacfd8f2f503292$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_PATH_UTIL_CAPI_H_
@@ -47,8 +47,8 @@
 #endif
 
 ///
-// Retrieve the path associated with the specified |key|. Returns true (1) on
-// success. Can be called on any thread in the browser process.
+/// Retrieve the path associated with the specified |key|. Returns true (1) on
+/// success. Can be called on any thread in the browser process.
 ///
 CEF_EXPORT int cef_get_path(cef_path_key_t key, cef_string_t* path);
 
diff --git a/src/include/capi/cef_permission_handler_capi.h b/src/include/capi/cef_permission_handler_capi.h
new file mode 100644
index 0000000..44f211a
--- /dev/null
+++ b/src/include/capi/cef_permission_handler_capi.h
@@ -0,0 +1,164 @@
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool and should not edited
+// by hand. See the translator.README.txt file in the tools directory for
+// more information.
+//
+// $hash=012d76416d19b590f29c013c44ceec1674593022$
+//
+
+#ifndef CEF_INCLUDE_CAPI_CEF_PERMISSION_HANDLER_CAPI_H_
+#define CEF_INCLUDE_CAPI_CEF_PERMISSION_HANDLER_CAPI_H_
+#pragma once
+
+#include "include/capi/cef_base_capi.h"
+#include "include/capi/cef_browser_capi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///
+/// Callback structure used for asynchronous continuation of media access
+/// permission requests.
+///
+typedef struct _cef_media_access_callback_t {
+  ///
+  /// Base structure.
+  ///
+  cef_base_ref_counted_t base;
+
+  ///
+  /// Call to allow or deny media access. If this callback was initiated in
+  /// response to a getUserMedia (indicated by
+  /// CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE and/or
+  /// CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE being set) then
+  /// |allowed_permissions| must match |required_permissions| passed to
+  /// OnRequestMediaAccessPermission.
+  ///
+  void(CEF_CALLBACK* cont)(struct _cef_media_access_callback_t* self,
+                           uint32_t allowed_permissions);
+
+  ///
+  /// Cancel the media access request.
+  ///
+  void(CEF_CALLBACK* cancel)(struct _cef_media_access_callback_t* self);
+} cef_media_access_callback_t;
+
+///
+/// Callback structure used for asynchronous continuation of permission prompts.
+///
+typedef struct _cef_permission_prompt_callback_t {
+  ///
+  /// Base structure.
+  ///
+  cef_base_ref_counted_t base;
+
+  ///
+  /// Complete the permissions request with the specified |result|.
+  ///
+  void(CEF_CALLBACK* cont)(struct _cef_permission_prompt_callback_t* self,
+                           cef_permission_request_result_t result);
+} cef_permission_prompt_callback_t;
+
+///
+/// Implement this structure to handle events related to permission requests.
+/// The functions of this structure will be called on the browser process UI
+/// thread.
+///
+typedef struct _cef_permission_handler_t {
+  ///
+  /// Base structure.
+  ///
+  cef_base_ref_counted_t base;
+
+  ///
+  /// Called when a page requests permission to access media.
+  /// |requesting_origin| is the URL origin requesting permission.
+  /// |requested_permissions| is a combination of values from
+  /// cef_media_access_permission_types_t that represent the requested
+  /// permissions. Return true (1) and call cef_media_access_callback_t
+  /// functions either in this function or at a later time to continue or cancel
+  /// the request. Return false (0) to proceed with default handling. With the
+  /// Chrome runtime, default handling will display the permission request UI.
+  /// With the Alloy runtime, default handling will deny the request. This
+  /// function will not be called if the "--enable-media-stream" command-line
+  /// switch is used to grant all permissions.
+  ///
+  int(CEF_CALLBACK* on_request_media_access_permission)(
+      struct _cef_permission_handler_t* self,
+      struct _cef_browser_t* browser,
+      struct _cef_frame_t* frame,
+      const cef_string_t* requesting_origin,
+      uint32_t requested_permissions,
+      struct _cef_media_access_callback_t* callback);
+
+  ///
+  /// Called when a page should show a permission prompt. |prompt_id| uniquely
+  /// identifies the prompt. |requesting_origin| is the URL origin requesting
+  /// permission. |requested_permissions| is a combination of values from
+  /// cef_permission_request_types_t that represent the requested permissions.
+  /// Return true (1) and call cef_permission_prompt_callback_t::Continue either
+  /// in this function or at a later time to continue or cancel the request.
+  /// Return false (0) to proceed with default handling. With the Chrome
+  /// runtime, default handling will display the permission prompt UI. With the
+  /// Alloy runtime, default handling is CEF_PERMISSION_RESULT_IGNORE.
+  ///
+  int(CEF_CALLBACK* on_show_permission_prompt)(
+      struct _cef_permission_handler_t* self,
+      struct _cef_browser_t* browser,
+      uint64_t prompt_id,
+      const cef_string_t* requesting_origin,
+      uint32_t requested_permissions,
+      struct _cef_permission_prompt_callback_t* callback);
+
+  ///
+  /// Called when a permission prompt handled via OnShowPermissionPrompt is
+  /// dismissed. |prompt_id| will match the value that was passed to
+  /// OnShowPermissionPrompt. |result| will be the value passed to
+  /// cef_permission_prompt_callback_t::Continue or CEF_PERMISSION_RESULT_IGNORE
+  /// if the dialog was dismissed for other reasons such as navigation, browser
+  /// closure, etc. This function will not be called if OnShowPermissionPrompt
+  /// returned false (0) for |prompt_id|.
+  ///
+  void(CEF_CALLBACK* on_dismiss_permission_prompt)(
+      struct _cef_permission_handler_t* self,
+      struct _cef_browser_t* browser,
+      uint64_t prompt_id,
+      cef_permission_request_result_t result);
+} cef_permission_handler_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // CEF_INCLUDE_CAPI_CEF_PERMISSION_HANDLER_CAPI_H_
diff --git a/src/include/capi/cef_preference_capi.h b/src/include/capi/cef_preference_capi.h
new file mode 100644
index 0000000..fa6d9bd
--- /dev/null
+++ b/src/include/capi/cef_preference_capi.h
@@ -0,0 +1,148 @@
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool and should not edited
+// by hand. See the translator.README.txt file in the tools directory for
+// more information.
+//
+// $hash=922659242ea25c52d02884a7cc5918d086cbfaca$
+//
+
+#ifndef CEF_INCLUDE_CAPI_CEF_PREFERENCE_CAPI_H_
+#define CEF_INCLUDE_CAPI_CEF_PREFERENCE_CAPI_H_
+#pragma once
+
+#include "include/capi/cef_base_capi.h"
+#include "include/capi/cef_values_capi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///
+/// Structure that manages custom preference registrations.
+///
+typedef struct _cef_preference_registrar_t {
+  ///
+  /// Base structure.
+  ///
+  cef_base_scoped_t base;
+
+  ///
+  /// Register a preference with the specified |name| and |default_value|. To
+  /// avoid conflicts with built-in preferences the |name| value should contain
+  /// an application-specific prefix followed by a period (e.g. "myapp.value").
+  /// The contents of |default_value| will be copied. The data type for the
+  /// preference will be inferred from |default_value|'s type and cannot be
+  /// changed after registration. Returns true (1) on success. Returns false (0)
+  /// if |name| is already registered or if |default_value| has an invalid type.
+  /// This function must be called from within the scope of the
+  /// cef_browser_process_handler_t::OnRegisterCustomPreferences callback.
+  ///
+  int(CEF_CALLBACK* add_preference)(struct _cef_preference_registrar_t* self,
+                                    const cef_string_t* name,
+                                    struct _cef_value_t* default_value);
+} cef_preference_registrar_t;
+
+///
+/// Manage access to preferences. Many built-in preferences are registered by
+/// Chromium. Custom preferences can be registered in
+/// cef_browser_process_handler_t::OnRegisterCustomPreferences.
+///
+typedef struct _cef_preference_manager_t {
+  ///
+  /// Base structure.
+  ///
+  cef_base_ref_counted_t base;
+
+  ///
+  /// Returns true (1) if a preference with the specified |name| exists. This
+  /// function must be called on the browser process UI thread.
+  ///
+  int(CEF_CALLBACK* has_preference)(struct _cef_preference_manager_t* self,
+                                    const cef_string_t* name);
+
+  ///
+  /// Returns the value for the preference with the specified |name|. Returns
+  /// NULL if the preference does not exist. The returned object contains a copy
+  /// of the underlying preference value and modifications to the returned
+  /// object will not modify the underlying preference value. This function must
+  /// be called on the browser process UI thread.
+  ///
+  struct _cef_value_t*(CEF_CALLBACK* get_preference)(
+      struct _cef_preference_manager_t* self,
+      const cef_string_t* name);
+
+  ///
+  /// Returns all preferences as a dictionary. If |include_defaults| is true (1)
+  /// then preferences currently at their default value will be included. The
+  /// returned object contains a copy of the underlying preference values and
+  /// modifications to the returned object will not modify the underlying
+  /// preference values. This function must be called on the browser process UI
+  /// thread.
+  ///
+  struct _cef_dictionary_value_t*(CEF_CALLBACK* get_all_preferences)(
+      struct _cef_preference_manager_t* self,
+      int include_defaults);
+
+  ///
+  /// Returns true (1) if the preference with the specified |name| can be
+  /// modified using SetPreference. As one example preferences set via the
+  /// command-line usually cannot be modified. This function must be called on
+  /// the browser process UI thread.
+  ///
+  int(CEF_CALLBACK* can_set_preference)(struct _cef_preference_manager_t* self,
+                                        const cef_string_t* name);
+
+  ///
+  /// Set the |value| associated with preference |name|. Returns true (1) if the
+  /// value is set successfully and false (0) otherwise. If |value| is NULL the
+  /// preference will be restored to its default value. If setting the
+  /// preference fails then |error| will be populated with a detailed
+  /// description of the problem. This function must be called on the browser
+  /// process UI thread.
+  ///
+  int(CEF_CALLBACK* set_preference)(struct _cef_preference_manager_t* self,
+                                    const cef_string_t* name,
+                                    struct _cef_value_t* value,
+                                    cef_string_t* error);
+} cef_preference_manager_t;
+
+///
+/// Returns the global preference manager object.
+///
+CEF_EXPORT cef_preference_manager_t* cef_preference_manager_get_global(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // CEF_INCLUDE_CAPI_CEF_PREFERENCE_CAPI_H_
diff --git a/src/include/capi/cef_preference_manager_capi.h b/src/include/capi/cef_preference_manager_capi.h
new file mode 100644
index 0000000..f3d979c
--- /dev/null
+++ b/src/include/capi/cef_preference_manager_capi.h
@@ -0,0 +1,116 @@
+// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool and should not edited
+// by hand. See the translator.README.txt file in the tools directory for
+// more information.
+//
+// $hash=1f5dd49cfc5aeb4b673c10750de01768f5cd2694$
+//
+
+#ifndef CEF_INCLUDE_CAPI_CEF_PREFERENCE_MANAGER_CAPI_H_
+#define CEF_INCLUDE_CAPI_CEF_PREFERENCE_MANAGER_CAPI_H_
+#pragma once
+
+#include "include/capi/cef_base_capi.h"
+#include "include/capi/cef_values_capi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///
+/// Manage access to preferences.
+///
+typedef struct _cef_preference_manager_t {
+  ///
+  /// Base structure.
+  ///
+  cef_base_ref_counted_t base;
+
+  ///
+  /// Returns true (1) if a preference with the specified |name| exists. This
+  /// function must be called on the browser process UI thread.
+  ///
+  int(CEF_CALLBACK* has_preference)(struct _cef_preference_manager_t* self,
+                                    const cef_string_t* name);
+
+  ///
+  /// Returns the value for the preference with the specified |name|. Returns
+  /// NULL if the preference does not exist. The returned object contains a copy
+  /// of the underlying preference value and modifications to the returned
+  /// object will not modify the underlying preference value. This function must
+  /// be called on the browser process UI thread.
+  ///
+  struct _cef_value_t*(CEF_CALLBACK* get_preference)(
+      struct _cef_preference_manager_t* self,
+      const cef_string_t* name);
+
+  ///
+  /// Returns all preferences as a dictionary. If |include_defaults| is true (1)
+  /// then preferences currently at their default value will be included. The
+  /// returned object contains a copy of the underlying preference values and
+  /// modifications to the returned object will not modify the underlying
+  /// preference values. This function must be called on the browser process UI
+  /// thread.
+  ///
+  struct _cef_dictionary_value_t*(CEF_CALLBACK* get_all_preferences)(
+      struct _cef_preference_manager_t* self,
+      int include_defaults);
+
+  ///
+  /// Returns true (1) if the preference with the specified |name| can be
+  /// modified using SetPreference. As one example preferences set via the
+  /// command-line usually cannot be modified. This function must be called on
+  /// the browser process UI thread.
+  ///
+  int(CEF_CALLBACK* can_set_preference)(struct _cef_preference_manager_t* self,
+                                        const cef_string_t* name);
+
+  ///
+  /// Set the |value| associated with preference |name|. Returns true (1) if the
+  /// value is set successfully and false (0) otherwise. If |value| is NULL the
+  /// preference will be restored to its default value. If setting the
+  /// preference fails then |error| will be populated with a detailed
+  /// description of the problem. This function must be called on the browser
+  /// process UI thread.
+  ///
+  int(CEF_CALLBACK* set_preference)(struct _cef_preference_manager_t* self,
+                                    const cef_string_t* name,
+                                    struct _cef_value_t* value,
+                                    cef_string_t* error);
+} cef_preference_manager_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // CEF_INCLUDE_CAPI_CEF_PREFERENCE_MANAGER_CAPI_H_
diff --git a/src/include/capi/cef_print_handler_capi.h b/src/include/capi/cef_print_handler_capi.h
index 8876ab6..47e69b1 100644
--- a/src/include/capi/cef_print_handler_capi.h
+++ b/src/include/capi/cef_print_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=b8d7be1399d3426a3f872b12bc1438e041a16308$
+// $hash=d09937fb047debd9da39c4072a434659b3c5682c$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_PRINT_HANDLER_CAPI_H_
@@ -49,65 +49,66 @@
 #endif
 
 ///
-// Callback structure for asynchronous continuation of print dialog requests.
+/// Callback structure for asynchronous continuation of print dialog requests.
 ///
 typedef struct _cef_print_dialog_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Continue printing with the specified |settings|.
+  /// Continue printing with the specified |settings|.
   ///
   void(CEF_CALLBACK* cont)(struct _cef_print_dialog_callback_t* self,
                            struct _cef_print_settings_t* settings);
 
   ///
-  // Cancel the printing.
+  /// Cancel the printing.
   ///
   void(CEF_CALLBACK* cancel)(struct _cef_print_dialog_callback_t* self);
 } cef_print_dialog_callback_t;
 
 ///
-// Callback structure for asynchronous continuation of print job requests.
+/// Callback structure for asynchronous continuation of print job requests.
 ///
 typedef struct _cef_print_job_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Indicate completion of the print job.
+  /// Indicate completion of the print job.
   ///
   void(CEF_CALLBACK* cont)(struct _cef_print_job_callback_t* self);
 } cef_print_job_callback_t;
 
 ///
-// Implement this structure to handle printing on Linux. Each browser will have
-// only one print job in progress at a time. The functions of this structure
-// will be called on the browser process UI thread.
+/// Implement this structure to handle printing on Linux. Each browser will have
+/// only one print job in progress at a time. The functions of this structure
+/// will be called on the browser process UI thread.
 ///
 typedef struct _cef_print_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called when printing has started for the specified |browser|. This function
-  // will be called before the other OnPrint*() functions and irrespective of
-  // how printing was initiated (e.g. cef_browser_host_t::print(), JavaScript
-  // window.print() or PDF extension print button).
+  /// Called when printing has started for the specified |browser|. This
+  /// function will be called before the other OnPrint*() functions and
+  /// irrespective of how printing was initiated (e.g.
+  /// cef_browser_host_t::print(), JavaScript window.print() or PDF extension
+  /// print button).
   ///
   void(CEF_CALLBACK* on_print_start)(struct _cef_print_handler_t* self,
                                      struct _cef_browser_t* browser);
 
   ///
-  // Synchronize |settings| with client state. If |get_defaults| is true (1)
-  // then populate |settings| with the default print settings. Do not keep a
-  // reference to |settings| outside of this callback.
+  /// Synchronize |settings| with client state. If |get_defaults| is true (1)
+  /// then populate |settings| with the default print settings. Do not keep a
+  /// reference to |settings| outside of this callback.
   ///
   void(CEF_CALLBACK* on_print_settings)(struct _cef_print_handler_t* self,
                                         struct _cef_browser_t* browser,
@@ -115,9 +116,9 @@
                                         int get_defaults);
 
   ///
-  // Show the print dialog. Execute |callback| once the dialog is dismissed.
-  // Return true (1) if the dialog will be displayed or false (0) to cancel the
-  // printing immediately.
+  /// Show the print dialog. Execute |callback| once the dialog is dismissed.
+  /// Return true (1) if the dialog will be displayed or false (0) to cancel the
+  /// printing immediately.
   ///
   int(CEF_CALLBACK* on_print_dialog)(
       struct _cef_print_handler_t* self,
@@ -126,9 +127,9 @@
       struct _cef_print_dialog_callback_t* callback);
 
   ///
-  // Send the print job to the printer. Execute |callback| once the job is
-  // completed. Return true (1) if the job will proceed or false (0) to cancel
-  // the job immediately.
+  /// Send the print job to the printer. Execute |callback| once the job is
+  /// completed. Return true (1) if the job will proceed or false (0) to cancel
+  /// the job immediately.
   ///
   int(CEF_CALLBACK* on_print_job)(struct _cef_print_handler_t* self,
                                   struct _cef_browser_t* browser,
@@ -137,17 +138,18 @@
                                   struct _cef_print_job_callback_t* callback);
 
   ///
-  // Reset client state related to printing.
+  /// Reset client state related to printing.
   ///
   void(CEF_CALLBACK* on_print_reset)(struct _cef_print_handler_t* self,
                                      struct _cef_browser_t* browser);
 
   ///
-  // Return the PDF paper size in device units. Used in combination with
-  // cef_browser_host_t::print_to_pdf().
+  /// Return the PDF paper size in device units. Used in combination with
+  /// cef_browser_host_t::print_to_pdf().
   ///
   cef_size_t(CEF_CALLBACK* get_pdf_paper_size)(
       struct _cef_print_handler_t* self,
+      struct _cef_browser_t* browser,
       int device_units_per_inch);
 } cef_print_handler_t;
 
diff --git a/src/include/capi/cef_print_settings_capi.h b/src/include/capi/cef_print_settings_capi.h
index 3b3d0c1..14a52f3 100644
--- a/src/include/capi/cef_print_settings_capi.h
+++ b/src/include/capi/cef_print_settings_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=8f7d7993691e07f4a8a42d63522c751cfba3c168$
+// $hash=46508464579e797d4684f4a7facdb39f9bdb312b$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_PRINT_SETTINGS_CAPI_H_
@@ -47,41 +47,41 @@
 #endif
 
 ///
-// Structure representing print settings.
+/// Structure representing print settings.
 ///
 typedef struct _cef_print_settings_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if this object is valid. Do not call any other functions
-  // if this function returns false (0).
+  /// Returns true (1) if this object is valid. Do not call any other functions
+  /// if this function returns false (0).
   ///
   int(CEF_CALLBACK* is_valid)(struct _cef_print_settings_t* self);
 
   ///
-  // Returns true (1) if the values of this object are read-only. Some APIs may
-  // expose read-only objects.
+  /// Returns true (1) if the values of this object are read-only. Some APIs may
+  /// expose read-only objects.
   ///
   int(CEF_CALLBACK* is_read_only)(struct _cef_print_settings_t* self);
 
   ///
-  // Set the page orientation.
+  /// Set the page orientation.
   ///
   void(CEF_CALLBACK* set_orientation)(struct _cef_print_settings_t* self,
                                       int landscape);
 
   ///
-  // Returns true (1) if the orientation is landscape.
+  /// Returns true (1) if the orientation is landscape.
   ///
   int(CEF_CALLBACK* is_landscape)(struct _cef_print_settings_t* self);
 
   ///
-  // Set the printer printable area in device units. Some platforms already
-  // provide flipped area. Set |landscape_needs_flip| to false (0) on those
-  // platforms to avoid double flipping.
+  /// Set the printer printable area in device units. Some platforms already
+  /// provide flipped area. Set |landscape_needs_flip| to false (0) on those
+  /// platforms to avoid double flipping.
   ///
   void(CEF_CALLBACK* set_printer_printable_area)(
       struct _cef_print_settings_t* self,
@@ -90,110 +90,110 @@
       int landscape_needs_flip);
 
   ///
-  // Set the device name.
+  /// Set the device name.
   ///
   void(CEF_CALLBACK* set_device_name)(struct _cef_print_settings_t* self,
                                       const cef_string_t* name);
 
   ///
-  // Get the device name.
+  /// Get the device name.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_device_name)(
       struct _cef_print_settings_t* self);
 
   ///
-  // Set the DPI (dots per inch).
+  /// Set the DPI (dots per inch).
   ///
   void(CEF_CALLBACK* set_dpi)(struct _cef_print_settings_t* self, int dpi);
 
   ///
-  // Get the DPI (dots per inch).
+  /// Get the DPI (dots per inch).
   ///
   int(CEF_CALLBACK* get_dpi)(struct _cef_print_settings_t* self);
 
   ///
-  // Set the page ranges.
+  /// Set the page ranges.
   ///
   void(CEF_CALLBACK* set_page_ranges)(struct _cef_print_settings_t* self,
                                       size_t rangesCount,
                                       cef_range_t const* ranges);
 
   ///
-  // Returns the number of page ranges that currently exist.
+  /// Returns the number of page ranges that currently exist.
   ///
   size_t(CEF_CALLBACK* get_page_ranges_count)(
       struct _cef_print_settings_t* self);
 
   ///
-  // Retrieve the page ranges.
+  /// Retrieve the page ranges.
   ///
   void(CEF_CALLBACK* get_page_ranges)(struct _cef_print_settings_t* self,
                                       size_t* rangesCount,
                                       cef_range_t* ranges);
 
   ///
-  // Set whether only the selection will be printed.
+  /// Set whether only the selection will be printed.
   ///
   void(CEF_CALLBACK* set_selection_only)(struct _cef_print_settings_t* self,
                                          int selection_only);
 
   ///
-  // Returns true (1) if only the selection will be printed.
+  /// Returns true (1) if only the selection will be printed.
   ///
   int(CEF_CALLBACK* is_selection_only)(struct _cef_print_settings_t* self);
 
   ///
-  // Set whether pages will be collated.
+  /// Set whether pages will be collated.
   ///
   void(CEF_CALLBACK* set_collate)(struct _cef_print_settings_t* self,
                                   int collate);
 
   ///
-  // Returns true (1) if pages will be collated.
+  /// Returns true (1) if pages will be collated.
   ///
   int(CEF_CALLBACK* will_collate)(struct _cef_print_settings_t* self);
 
   ///
-  // Set the color model.
+  /// Set the color model.
   ///
   void(CEF_CALLBACK* set_color_model)(struct _cef_print_settings_t* self,
                                       cef_color_model_t model);
 
   ///
-  // Get the color model.
+  /// Get the color model.
   ///
   cef_color_model_t(CEF_CALLBACK* get_color_model)(
       struct _cef_print_settings_t* self);
 
   ///
-  // Set the number of copies.
+  /// Set the number of copies.
   ///
   void(CEF_CALLBACK* set_copies)(struct _cef_print_settings_t* self,
                                  int copies);
 
   ///
-  // Get the number of copies.
+  /// Get the number of copies.
   ///
   int(CEF_CALLBACK* get_copies)(struct _cef_print_settings_t* self);
 
   ///
-  // Set the duplex mode.
+  /// Set the duplex mode.
   ///
   void(CEF_CALLBACK* set_duplex_mode)(struct _cef_print_settings_t* self,
                                       cef_duplex_mode_t mode);
 
   ///
-  // Get the duplex mode.
+  /// Get the duplex mode.
   ///
   cef_duplex_mode_t(CEF_CALLBACK* get_duplex_mode)(
       struct _cef_print_settings_t* self);
 } cef_print_settings_t;
 
 ///
-// Create a new cef_print_settings_t object.
+/// Create a new cef_print_settings_t object.
 ///
-CEF_EXPORT cef_print_settings_t* cef_print_settings_create();
+CEF_EXPORT cef_print_settings_t* cef_print_settings_create(void);
 
 #ifdef __cplusplus
 }
diff --git a/src/include/capi/cef_process_message_capi.h b/src/include/capi/cef_process_message_capi.h
index aff3b40..586014c 100644
--- a/src/include/capi/cef_process_message_capi.h
+++ b/src/include/capi/cef_process_message_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=79ec6d99ea47e1cf9b2cca0433704f205e14d3bd$
+// $hash=e20a8d6a5803dae5ba156adde40c8b964899b176$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_PROCESS_MESSAGE_CAPI_H_
@@ -41,6 +41,7 @@
 #pragma once
 
 #include "include/capi/cef_base_capi.h"
+#include "include/capi/cef_shared_memory_region_capi.h"
 #include "include/capi/cef_values_capi.h"
 
 #ifdef __cplusplus
@@ -48,48 +49,57 @@
 #endif
 
 ///
-// Structure representing a message. Can be used on any process and thread.
+/// Structure representing a message. Can be used on any process and thread.
 ///
 typedef struct _cef_process_message_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if this object is valid. Do not call any other functions
-  // if this function returns false (0).
+  /// Returns true (1) if this object is valid. Do not call any other functions
+  /// if this function returns false (0).
   ///
   int(CEF_CALLBACK* is_valid)(struct _cef_process_message_t* self);
 
   ///
-  // Returns true (1) if the values of this object are read-only. Some APIs may
-  // expose read-only objects.
+  /// Returns true (1) if the values of this object are read-only. Some APIs may
+  /// expose read-only objects.
   ///
   int(CEF_CALLBACK* is_read_only)(struct _cef_process_message_t* self);
 
   ///
-  // Returns a writable copy of this object.
+  /// Returns a writable copy of this object. Returns nullptr when message
+  /// contains a shared memory region.
   ///
   struct _cef_process_message_t*(CEF_CALLBACK* copy)(
       struct _cef_process_message_t* self);
 
   ///
-  // Returns the message name.
+  /// Returns the message name.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_name)(
       struct _cef_process_message_t* self);
 
   ///
-  // Returns the list of arguments.
+  /// Returns the list of arguments. Returns nullptr when message contains a
+  /// shared memory region.
   ///
   struct _cef_list_value_t*(CEF_CALLBACK* get_argument_list)(
       struct _cef_process_message_t* self);
+
+  ///
+  /// Returns the shared memory region. Returns nullptr when message contains an
+  /// argument list.
+  ///
+  struct _cef_shared_memory_region_t*(CEF_CALLBACK* get_shared_memory_region)(
+      struct _cef_process_message_t* self);
 } cef_process_message_t;
 
 ///
-// Create a new cef_process_message_t object with the specified name.
+/// Create a new cef_process_message_t object with the specified name.
 ///
 CEF_EXPORT cef_process_message_t* cef_process_message_create(
     const cef_string_t* name);
diff --git a/src/include/capi/cef_process_util_capi.h b/src/include/capi/cef_process_util_capi.h
index 1a8a003..2ae2c57 100644
--- a/src/include/capi/cef_process_util_capi.h
+++ b/src/include/capi/cef_process_util_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=75b16fd9d592c1d22b94d740e1deb61efe3afb97$
+// $hash=88c42c5f216798304b07bfe985296014cf65996c$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_PROCESS_UTIL_CAPI_H_
@@ -47,14 +47,14 @@
 #endif
 
 ///
-// Launches the process specified via |command_line|. Returns true (1) upon
-// success. Must be called on the browser process TID_PROCESS_LAUNCHER thread.
-//
-// Unix-specific notes: - All file descriptors open in the parent process will
-// be closed in the
-//   child process except for stdin, stdout, and stderr.
-// - If the first argument on the command line does not contain a slash,
-//   PATH will be searched. (See man execvp.)
+/// Launches the process specified via |command_line|. Returns true (1) upon
+/// success. Must be called on the browser process TID_PROCESS_LAUNCHER thread.
+///
+/// Unix-specific notes: - All file descriptors open in the parent process will
+/// be closed in the
+///   child process except for stdin, stdout, and stderr.
+/// - If the first argument on the command line does not contain a slash,
+///   PATH will be searched. (See man execvp.)
 ///
 CEF_EXPORT int cef_launch_process(struct _cef_command_line_t* command_line);
 
diff --git a/src/include/capi/cef_registration_capi.h b/src/include/capi/cef_registration_capi.h
index 8b7354a..4ac84d6 100644
--- a/src/include/capi/cef_registration_capi.h
+++ b/src/include/capi/cef_registration_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=029e237cf80f94a25453bac5a9b1e0765bb56f37$
+// $hash=b1b38a3171dd3626029e70e75b482dfa3531215b$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_REGISTRATION_CAPI_H_
@@ -47,11 +47,11 @@
 #endif
 
 ///
-// Generic callback structure used for managing the lifespan of a registration.
+/// Generic callback structure used for managing the lifespan of a registration.
 ///
 typedef struct _cef_registration_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 } cef_registration_t;
diff --git a/src/include/capi/cef_render_handler_capi.h b/src/include/capi/cef_render_handler_capi.h
index df7e88f..ccd3d23 100644
--- a/src/include/capi/cef_render_handler_capi.h
+++ b/src/include/capi/cef_render_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=e642fc1fe3b97a90c0eae7f0fc0a5cfd385e3e17$
+// $hash=32d8176f39b05487bae048990b2dee3212ae3b78$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_RENDER_HANDLER_CAPI_H_
@@ -50,42 +50,44 @@
 #endif
 
 ///
-// Implement this structure to handle events when window rendering is disabled.
-// The functions of this structure will be called on the UI thread.
+/// Implement this structure to handle events when window rendering is disabled.
+/// The functions of this structure will be called on the UI thread.
 ///
 typedef struct _cef_render_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Return the handler for accessibility notifications. If no handler is
-  // provided the default implementation will be used.
+  /// Return the handler for accessibility notifications. If no handler is
+  /// provided the default implementation will be used.
   ///
   struct _cef_accessibility_handler_t*(CEF_CALLBACK* get_accessibility_handler)(
       struct _cef_render_handler_t* self);
 
   ///
-  // Called to retrieve the root window rectangle in screen coordinates. Return
-  // true (1) if the rectangle was provided. If this function returns false (0)
-  // the rectangle from GetViewRect will be used.
+  /// Called to retrieve the root window rectangle in screen DIP coordinates.
+  /// Return true (1) if the rectangle was provided. If this function returns
+  /// false (0) the rectangle from GetViewRect will be used.
   ///
   int(CEF_CALLBACK* get_root_screen_rect)(struct _cef_render_handler_t* self,
                                           struct _cef_browser_t* browser,
                                           cef_rect_t* rect);
 
   ///
-  // Called to retrieve the view rectangle which is relative to screen
-  // coordinates. This function must always provide a non-NULL rectangle.
+  /// Called to retrieve the view rectangle in screen DIP coordinates. This
+  /// function must always provide a non-NULL rectangle.
   ///
   void(CEF_CALLBACK* get_view_rect)(struct _cef_render_handler_t* self,
                                     struct _cef_browser_t* browser,
                                     cef_rect_t* rect);
 
   ///
-  // Called to retrieve the translation from view coordinates to actual screen
-  // coordinates. Return true (1) if the screen coordinates were provided.
+  /// Called to retrieve the translation from view DIP coordinates to screen
+  /// coordinates. Windows/Linux should provide screen device (pixel)
+  /// coordinates and MacOS should provide screen DIP coordinates. Return true
+  /// (1) if the requested coordinates were provided.
   ///
   int(CEF_CALLBACK* get_screen_point)(struct _cef_render_handler_t* self,
                                       struct _cef_browser_t* browser,
@@ -95,44 +97,44 @@
                                       int* screenY);
 
   ///
-  // Called to allow the client to fill in the CefScreenInfo object with
-  // appropriate values. Return true (1) if the |screen_info| structure has been
-  // modified.
-  //
-  // If the screen info rectangle is left NULL the rectangle from GetViewRect
-  // will be used. If the rectangle is still NULL or invalid popups may not be
-  // drawn correctly.
+  /// Called to allow the client to fill in the CefScreenInfo object with
+  /// appropriate values. Return true (1) if the |screen_info| structure has
+  /// been modified.
+  ///
+  /// If the screen info rectangle is left NULL the rectangle from GetViewRect
+  /// will be used. If the rectangle is still NULL or invalid popups may not be
+  /// drawn correctly.
   ///
   int(CEF_CALLBACK* get_screen_info)(struct _cef_render_handler_t* self,
                                      struct _cef_browser_t* browser,
-                                     struct _cef_screen_info_t* screen_info);
+                                     cef_screen_info_t* screen_info);
 
   ///
-  // Called when the browser wants to show or hide the popup widget. The popup
-  // should be shown if |show| is true (1) and hidden if |show| is false (0).
+  /// Called when the browser wants to show or hide the popup widget. The popup
+  /// should be shown if |show| is true (1) and hidden if |show| is false (0).
   ///
   void(CEF_CALLBACK* on_popup_show)(struct _cef_render_handler_t* self,
                                     struct _cef_browser_t* browser,
                                     int show);
 
   ///
-  // Called when the browser wants to move or resize the popup widget. |rect|
-  // contains the new location and size in view coordinates.
+  /// Called when the browser wants to move or resize the popup widget. |rect|
+  /// contains the new location and size in view coordinates.
   ///
   void(CEF_CALLBACK* on_popup_size)(struct _cef_render_handler_t* self,
                                     struct _cef_browser_t* browser,
                                     const cef_rect_t* rect);
 
   ///
-  // Called when an element should be painted. Pixel values passed to this
-  // function are scaled relative to view coordinates based on the value of
-  // CefScreenInfo.device_scale_factor returned from GetScreenInfo. |type|
-  // indicates whether the element is the view or the popup widget. |buffer|
-  // contains the pixel data for the whole image. |dirtyRects| contains the set
-  // of rectangles in pixel coordinates that need to be repainted. |buffer| will
-  // be |width|*|height|*4 bytes in size and represents a BGRA image with an
-  // upper-left origin. This function is only called when
-  // cef_window_tInfo::shared_texture_enabled is set to false (0).
+  /// Called when an element should be painted. Pixel values passed to this
+  /// function are scaled relative to view coordinates based on the value of
+  /// CefScreenInfo.device_scale_factor returned from GetScreenInfo. |type|
+  /// indicates whether the element is the view or the popup widget. |buffer|
+  /// contains the pixel data for the whole image. |dirtyRects| contains the set
+  /// of rectangles in pixel coordinates that need to be repainted. |buffer|
+  /// will be |width|*|height|*4 bytes in size and represents a BGRA image with
+  /// an upper-left origin. This function is only called when
+  /// cef_window_tInfo::shared_texture_enabled is set to false (0).
   ///
   void(CEF_CALLBACK* on_paint)(struct _cef_render_handler_t* self,
                                struct _cef_browser_t* browser,
@@ -144,13 +146,13 @@
                                int height);
 
   ///
-  // Called when an element has been rendered to the shared texture handle.
-  // |type| indicates whether the element is the view or the popup widget.
-  // |dirtyRects| contains the set of rectangles in pixel coordinates that need
-  // to be repainted. |shared_handle| is the handle for a D3D11 Texture2D that
-  // can be accessed via ID3D11Device using the OpenSharedResource function.
-  // This function is only called when cef_window_tInfo::shared_texture_enabled
-  // is set to true (1), and is currently only supported on Windows.
+  /// Called when an element has been rendered to the shared texture handle.
+  /// |type| indicates whether the element is the view or the popup widget.
+  /// |dirtyRects| contains the set of rectangles in pixel coordinates that need
+  /// to be repainted. |shared_handle| is the handle for a D3D11 Texture2D that
+  /// can be accessed via ID3D11Device using the OpenSharedResource function.
+  /// This function is only called when cef_window_tInfo::shared_texture_enabled
+  /// is set to true (1), and is currently only supported on Windows.
   ///
   void(CEF_CALLBACK* on_accelerated_paint)(struct _cef_render_handler_t* self,
                                            struct _cef_browser_t* browser,
@@ -160,29 +162,37 @@
                                            void* shared_handle);
 
   ///
-  // Called when the browser's cursor has changed. If |type| is CT_CUSTOM then
-  // |custom_cursor_info| will be populated with the custom cursor information.
+  /// Called to retrieve the size of the touch handle for the specified
+  /// |orientation|.
   ///
-  void(CEF_CALLBACK* on_cursor_change)(
+  void(CEF_CALLBACK* get_touch_handle_size)(
       struct _cef_render_handler_t* self,
       struct _cef_browser_t* browser,
-      cef_cursor_handle_t cursor,
-      cef_cursor_type_t type,
-      const struct _cef_cursor_info_t* custom_cursor_info);
+      cef_horizontal_alignment_t orientation,
+      cef_size_t* size);
 
   ///
-  // Called when the user starts dragging content in the web view. Contextual
-  // information about the dragged content is supplied by |drag_data|. (|x|,
-  // |y|) is the drag start location in screen coordinates. OS APIs that run a
-  // system message loop may be used within the StartDragging call.
-  //
-  // Return false (0) to abort the drag operation. Don't call any of
-  // cef_browser_host_t::DragSource*Ended* functions after returning false (0).
-  //
-  // Return true (1) to handle the drag operation. Call
-  // cef_browser_host_t::DragSourceEndedAt and DragSourceSystemDragEnded either
-  // synchronously or asynchronously to inform the web view that the drag
-  // operation has ended.
+  /// Called when touch handle state is updated. The client is responsible for
+  /// rendering the touch handles.
+  ///
+  void(CEF_CALLBACK* on_touch_handle_state_changed)(
+      struct _cef_render_handler_t* self,
+      struct _cef_browser_t* browser,
+      const cef_touch_handle_state_t* state);
+
+  ///
+  /// Called when the user starts dragging content in the web view. Contextual
+  /// information about the dragged content is supplied by |drag_data|. (|x|,
+  /// |y|) is the drag start location in screen coordinates. OS APIs that run a
+  /// system message loop may be used within the StartDragging call.
+  ///
+  /// Return false (0) to abort the drag operation. Don't call any of
+  /// cef_browser_host_t::DragSource*Ended* functions after returning false (0).
+  ///
+  /// Return true (1) to handle the drag operation. Call
+  /// cef_browser_host_t::DragSourceEndedAt and DragSourceSystemDragEnded either
+  /// synchronously or asynchronously to inform the web view that the drag
+  /// operation has ended.
   ///
   int(CEF_CALLBACK* start_dragging)(struct _cef_render_handler_t* self,
                                     struct _cef_browser_t* browser,
@@ -192,16 +202,16 @@
                                     int y);
 
   ///
-  // Called when the web view wants to update the mouse cursor during a drag &
-  // drop operation. |operation| describes the allowed operation (none, move,
-  // copy, link).
+  /// Called when the web view wants to update the mouse cursor during a drag &
+  /// drop operation. |operation| describes the allowed operation (none, move,
+  /// copy, link).
   ///
   void(CEF_CALLBACK* update_drag_cursor)(struct _cef_render_handler_t* self,
                                          struct _cef_browser_t* browser,
                                          cef_drag_operations_mask_t operation);
 
   ///
-  // Called when the scroll offset has changed.
+  /// Called when the scroll offset has changed.
   ///
   void(CEF_CALLBACK* on_scroll_offset_changed)(
       struct _cef_render_handler_t* self,
@@ -210,9 +220,9 @@
       double y);
 
   ///
-  // Called when the IME composition range has changed. |selected_range| is the
-  // range of characters that have been selected. |character_bounds| is the
-  // bounds of each character in view coordinates.
+  /// Called when the IME composition range has changed. |selected_range| is the
+  /// range of characters that have been selected. |character_bounds| is the
+  /// bounds of each character in view coordinates.
   ///
   void(CEF_CALLBACK* on_ime_composition_range_changed)(
       struct _cef_render_handler_t* self,
@@ -222,9 +232,9 @@
       cef_rect_t const* character_bounds);
 
   ///
-  // Called when text selection has changed for the specified |browser|.
-  // |selected_text| is the currently selected text and |selected_range| is the
-  // character range.
+  /// Called when text selection has changed for the specified |browser|.
+  /// |selected_text| is the currently selected text and |selected_range| is the
+  /// character range.
   ///
   void(CEF_CALLBACK* on_text_selection_changed)(
       struct _cef_render_handler_t* self,
@@ -233,10 +243,10 @@
       const cef_range_t* selected_range);
 
   ///
-  // Called when an on-screen keyboard should be shown or hidden for the
-  // specified |browser|. |input_mode| specifies what kind of keyboard should be
-  // opened. If |input_mode| is CEF_TEXT_INPUT_MODE_NONE, any existing keyboard
-  // for this browser should be hidden.
+  /// Called when an on-screen keyboard should be shown or hidden for the
+  /// specified |browser|. |input_mode| specifies what kind of keyboard should
+  /// be opened. If |input_mode| is CEF_TEXT_INPUT_MODE_NONE, any existing
+  /// keyboard for this browser should be hidden.
   ///
   void(CEF_CALLBACK* on_virtual_keyboard_requested)(
       struct _cef_render_handler_t* self,
diff --git a/src/include/capi/cef_render_process_handler_capi.h b/src/include/capi/cef_render_process_handler_capi.h
index e23d499..f9c86c9 100644
--- a/src/include/capi/cef_render_process_handler_capi.h
+++ b/src/include/capi/cef_render_process_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=3630a82a4ea731b43ed4ba468a57c5dfe15f8679$
+// $hash=d807c7566ce3085243e9e7ea279fee7241acfc5f$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_RENDER_PROCESS_HANDLER_CAPI_H_
@@ -54,40 +54,30 @@
 #endif
 
 ///
-// Structure used to implement render process callbacks. The functions of this
-// structure will be called on the render process main thread (TID_RENDERER)
-// unless otherwise indicated.
+/// Structure used to implement render process callbacks. The functions of this
+/// structure will be called on the render process main thread (TID_RENDERER)
+/// unless otherwise indicated.
 ///
 typedef struct _cef_render_process_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called after the render process main thread has been created. |extra_info|
-  // is a read-only value originating from
-  // cef_browser_process_handler_t::on_render_process_thread_created(). Do not
-  // keep a reference to |extra_info| outside of this function.
-  ///
-  void(CEF_CALLBACK* on_render_thread_created)(
-      struct _cef_render_process_handler_t* self,
-      struct _cef_list_value_t* extra_info);
-
-  ///
-  // Called after WebKit has been initialized.
+  /// Called after WebKit has been initialized.
   ///
   void(CEF_CALLBACK* on_web_kit_initialized)(
       struct _cef_render_process_handler_t* self);
 
   ///
-  // Called after a browser has been created. When browsing cross-origin a new
-  // browser will be created before the old browser with the same identifier is
-  // destroyed. |extra_info| is a read-only value originating from
-  // cef_browser_host_t::cef_browser_host_create_browser(),
-  // cef_browser_host_t::cef_browser_host_create_browser_sync(),
-  // cef_life_span_handler_t::on_before_popup() or
-  // cef_browser_view_t::cef_browser_view_create().
+  /// Called after a browser has been created. When browsing cross-origin a new
+  /// browser will be created before the old browser with the same identifier is
+  /// destroyed. |extra_info| is an optional read-only value originating from
+  /// cef_browser_host_t::cef_browser_host_create_browser(),
+  /// cef_browser_host_t::cef_browser_host_create_browser_sync(),
+  /// cef_life_span_handler_t::on_before_popup() or
+  /// cef_browser_view_t::cef_browser_view_create().
   ///
   void(CEF_CALLBACK* on_browser_created)(
       struct _cef_render_process_handler_t* self,
@@ -95,25 +85,25 @@
       struct _cef_dictionary_value_t* extra_info);
 
   ///
-  // Called before a browser is destroyed.
+  /// Called before a browser is destroyed.
   ///
   void(CEF_CALLBACK* on_browser_destroyed)(
       struct _cef_render_process_handler_t* self,
       struct _cef_browser_t* browser);
 
   ///
-  // Return the handler for browser load status events.
+  /// Return the handler for browser load status events.
   ///
   struct _cef_load_handler_t*(CEF_CALLBACK* get_load_handler)(
       struct _cef_render_process_handler_t* self);
 
   ///
-  // Called immediately after the V8 context for a frame has been created. To
-  // retrieve the JavaScript 'window' object use the
-  // cef_v8context_t::get_global() function. V8 handles can only be accessed
-  // from the thread on which they are created. A task runner for posting tasks
-  // on the associated thread can be retrieved via the
-  // cef_v8context_t::get_task_runner() function.
+  /// Called immediately after the V8 context for a frame has been created. To
+  /// retrieve the JavaScript 'window' object use the
+  /// cef_v8context_t::get_global() function. V8 handles can only be accessed
+  /// from the thread on which they are created. A task runner for posting tasks
+  /// on the associated thread can be retrieved via the
+  /// cef_v8context_t::get_task_runner() function.
   ///
   void(CEF_CALLBACK* on_context_created)(
       struct _cef_render_process_handler_t* self,
@@ -122,8 +112,8 @@
       struct _cef_v8context_t* context);
 
   ///
-  // Called immediately before the V8 context for a frame is released. No
-  // references to the context should be kept after this function is called.
+  /// Called immediately before the V8 context for a frame is released. No
+  /// references to the context should be kept after this function is called.
   ///
   void(CEF_CALLBACK* on_context_released)(
       struct _cef_render_process_handler_t* self,
@@ -132,9 +122,9 @@
       struct _cef_v8context_t* context);
 
   ///
-  // Called for global uncaught exceptions in a frame. Execution of this
-  // callback is disabled by default. To enable set
-  // CefSettings.uncaught_exception_stack_size > 0.
+  /// Called for global uncaught exceptions in a frame. Execution of this
+  /// callback is disabled by default. To enable set
+  /// cef_settings_t.uncaught_exception_stack_size > 0.
   ///
   void(CEF_CALLBACK* on_uncaught_exception)(
       struct _cef_render_process_handler_t* self,
@@ -145,12 +135,12 @@
       struct _cef_v8stack_trace_t* stackTrace);
 
   ///
-  // Called when a new node in the the browser gets focus. The |node| value may
-  // be NULL if no specific node has gained focus. The node object passed to
-  // this function represents a snapshot of the DOM at the time this function is
-  // executed. DOM objects are only valid for the scope of this function. Do not
-  // keep references to or attempt to access any DOM objects outside the scope
-  // of this function.
+  /// Called when a new node in the the browser gets focus. The |node| value may
+  /// be NULL if no specific node has gained focus. The node object passed to
+  /// this function represents a snapshot of the DOM at the time this function
+  /// is executed. DOM objects are only valid for the scope of this function. Do
+  /// not keep references to or attempt to access any DOM objects outside the
+  /// scope of this function.
   ///
   void(CEF_CALLBACK* on_focused_node_changed)(
       struct _cef_render_process_handler_t* self,
@@ -159,9 +149,9 @@
       struct _cef_domnode_t* node);
 
   ///
-  // Called when a new message is received from a different process. Return true
-  // (1) if the message was handled or false (0) otherwise. Do not keep a
-  // reference to or attempt to access the message outside of this callback.
+  /// Called when a new message is received from a different process. Return
+  /// true (1) if the message was handled or false (0) otherwise. It is safe to
+  /// keep a reference to |message| outside of this callback.
   ///
   int(CEF_CALLBACK* on_process_message_received)(
       struct _cef_render_process_handler_t* self,
diff --git a/src/include/capi/cef_request_capi.h b/src/include/capi/cef_request_capi.h
index 9904974..50df9f0 100644
--- a/src/include/capi/cef_request_capi.h
+++ b/src/include/capi/cef_request_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=b3725b8fa4118936caacda69504dc597f3620d82$
+// $hash=241f8b8ba0a4555f8ad8ed1d60345ae83d4d62f4$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_REQUEST_CAPI_H_
@@ -50,96 +50,96 @@
 struct _cef_post_data_t;
 
 ///
-// Structure used to represent a web request. The functions of this structure
-// may be called on any thread.
+/// Structure used to represent a web request. The functions of this structure
+/// may be called on any thread.
 ///
 typedef struct _cef_request_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if this object is read-only.
+  /// Returns true (1) if this object is read-only.
   ///
   int(CEF_CALLBACK* is_read_only)(struct _cef_request_t* self);
 
   ///
-  // Get the fully qualified URL.
+  /// Get the fully qualified URL.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_url)(struct _cef_request_t* self);
 
   ///
-  // Set the fully qualified URL.
+  /// Set the fully qualified URL.
   ///
   void(CEF_CALLBACK* set_url)(struct _cef_request_t* self,
                               const cef_string_t* url);
 
   ///
-  // Get the request function type. The value will default to POST if post data
-  // is provided and GET otherwise.
+  /// Get the request function type. The value will default to POST if post data
+  /// is provided and GET otherwise.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_method)(struct _cef_request_t* self);
 
   ///
-  // Set the request function type.
+  /// Set the request function type.
   ///
   void(CEF_CALLBACK* set_method)(struct _cef_request_t* self,
                                  const cef_string_t* method);
 
   ///
-  // Set the referrer URL and policy. If non-NULL the referrer URL must be fully
-  // qualified with an HTTP or HTTPS scheme component. Any username, password or
-  // ref component will be removed.
+  /// Set the referrer URL and policy. If non-NULL the referrer URL must be
+  /// fully qualified with an HTTP or HTTPS scheme component. Any username,
+  /// password or ref component will be removed.
   ///
   void(CEF_CALLBACK* set_referrer)(struct _cef_request_t* self,
                                    const cef_string_t* referrer_url,
                                    cef_referrer_policy_t policy);
 
   ///
-  // Get the referrer URL.
+  /// Get the referrer URL.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_referrer_url)(
       struct _cef_request_t* self);
 
   ///
-  // Get the referrer policy.
+  /// Get the referrer policy.
   ///
   cef_referrer_policy_t(CEF_CALLBACK* get_referrer_policy)(
       struct _cef_request_t* self);
 
   ///
-  // Get the post data.
+  /// Get the post data.
   ///
   struct _cef_post_data_t*(CEF_CALLBACK* get_post_data)(
       struct _cef_request_t* self);
 
   ///
-  // Set the post data.
+  /// Set the post data.
   ///
   void(CEF_CALLBACK* set_post_data)(struct _cef_request_t* self,
                                     struct _cef_post_data_t* postData);
 
   ///
-  // Get the header values. Will not include the Referer value if any.
+  /// Get the header values. Will not include the Referer value if any.
   ///
   void(CEF_CALLBACK* get_header_map)(struct _cef_request_t* self,
                                      cef_string_multimap_t headerMap);
 
   ///
-  // Set the header values. If a Referer value exists in the header map it will
-  // be removed and ignored.
+  /// Set the header values. If a Referer value exists in the header map it will
+  /// be removed and ignored.
   ///
   void(CEF_CALLBACK* set_header_map)(struct _cef_request_t* self,
                                      cef_string_multimap_t headerMap);
 
   ///
-  // Returns the first header value for |name| or an NULL string if not found.
-  // Will not return the Referer value if any. Use GetHeaderMap instead if
-  // |name| might have multiple values.
+  /// Returns the first header value for |name| or an NULL string if not found.
+  /// Will not return the Referer value if any. Use GetHeaderMap instead if
+  /// |name| might have multiple values.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_header_by_name)(
@@ -147,10 +147,10 @@
       const cef_string_t* name);
 
   ///
-  // Set the header |name| to |value|. If |overwrite| is true (1) any existing
-  // values will be replaced with the new value. If |overwrite| is false (0) any
-  // existing values will not be overwritten. The Referer value cannot be set
-  // using this function.
+  /// Set the header |name| to |value|. If |overwrite| is true (1) any existing
+  /// values will be replaced with the new value. If |overwrite| is false (0)
+  /// any existing values will not be overwritten. The Referer value cannot be
+  /// set using this function.
   ///
   void(CEF_CALLBACK* set_header_by_name)(struct _cef_request_t* self,
                                          const cef_string_t* name,
@@ -158,7 +158,7 @@
                                          int overwrite);
 
   ///
-  // Set all values at one time.
+  /// Set all values at one time.
   ///
   void(CEF_CALLBACK* set)(struct _cef_request_t* self,
                           const cef_string_t* url,
@@ -167,174 +167,176 @@
                           cef_string_multimap_t headerMap);
 
   ///
-  // Get the flags used in combination with cef_urlrequest_t. See
-  // cef_urlrequest_flags_t for supported values.
+  /// Get the flags used in combination with cef_urlrequest_t. See
+  /// cef_urlrequest_flags_t for supported values.
   ///
   int(CEF_CALLBACK* get_flags)(struct _cef_request_t* self);
 
   ///
-  // Set the flags used in combination with cef_urlrequest_t.  See
-  // cef_urlrequest_flags_t for supported values.
+  /// Set the flags used in combination with cef_urlrequest_t.  See
+  /// cef_urlrequest_flags_t for supported values.
   ///
   void(CEF_CALLBACK* set_flags)(struct _cef_request_t* self, int flags);
 
   ///
-  // Get the URL to the first party for cookies used in combination with
-  // cef_urlrequest_t.
+  /// Get the URL to the first party for cookies used in combination with
+  /// cef_urlrequest_t.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_first_party_for_cookies)(
       struct _cef_request_t* self);
 
   ///
-  // Set the URL to the first party for cookies used in combination with
-  // cef_urlrequest_t.
+  /// Set the URL to the first party for cookies used in combination with
+  /// cef_urlrequest_t.
   ///
   void(CEF_CALLBACK* set_first_party_for_cookies)(struct _cef_request_t* self,
                                                   const cef_string_t* url);
 
   ///
-  // Get the resource type for this request. Only available in the browser
-  // process.
+  /// Get the resource type for this request. Only available in the browser
+  /// process.
   ///
   cef_resource_type_t(CEF_CALLBACK* get_resource_type)(
       struct _cef_request_t* self);
 
   ///
-  // Get the transition type for this request. Only available in the browser
-  // process and only applies to requests that represent a main frame or sub-
-  // frame navigation.
+  /// Get the transition type for this request. Only available in the browser
+  /// process and only applies to requests that represent a main frame or sub-
+  /// frame navigation.
   ///
   cef_transition_type_t(CEF_CALLBACK* get_transition_type)(
       struct _cef_request_t* self);
 
   ///
-  // Returns the globally unique identifier for this request or 0 if not
-  // specified. Can be used by cef_resource_request_handler_t implementations in
-  // the browser process to track a single request across multiple callbacks.
+  /// Returns the globally unique identifier for this request or 0 if not
+  /// specified. Can be used by cef_resource_request_handler_t implementations
+  /// in the browser process to track a single request across multiple
+  /// callbacks.
   ///
-  uint64(CEF_CALLBACK* get_identifier)(struct _cef_request_t* self);
+  uint64_t(CEF_CALLBACK* get_identifier)(struct _cef_request_t* self);
 } cef_request_t;
 
 ///
-// Create a new cef_request_t object.
+/// Create a new cef_request_t object.
 ///
-CEF_EXPORT cef_request_t* cef_request_create();
+CEF_EXPORT cef_request_t* cef_request_create(void);
 
 ///
-// Structure used to represent post data for a web request. The functions of
-// this structure may be called on any thread.
+/// Structure used to represent post data for a web request. The functions of
+/// this structure may be called on any thread.
 ///
 typedef struct _cef_post_data_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if this object is read-only.
+  /// Returns true (1) if this object is read-only.
   ///
   int(CEF_CALLBACK* is_read_only)(struct _cef_post_data_t* self);
 
   ///
-  // Returns true (1) if the underlying POST data includes elements that are not
-  // represented by this cef_post_data_t object (for example, multi-part file
-  // upload data). Modifying cef_post_data_t objects with excluded elements may
-  // result in the request failing.
+  /// Returns true (1) if the underlying POST data includes elements that are
+  /// not represented by this cef_post_data_t object (for example, multi-part
+  /// file upload data). Modifying cef_post_data_t objects with excluded
+  /// elements may result in the request failing.
   ///
   int(CEF_CALLBACK* has_excluded_elements)(struct _cef_post_data_t* self);
 
   ///
-  // Returns the number of existing post data elements.
+  /// Returns the number of existing post data elements.
   ///
   size_t(CEF_CALLBACK* get_element_count)(struct _cef_post_data_t* self);
 
   ///
-  // Retrieve the post data elements.
+  /// Retrieve the post data elements.
   ///
   void(CEF_CALLBACK* get_elements)(struct _cef_post_data_t* self,
                                    size_t* elementsCount,
                                    struct _cef_post_data_element_t** elements);
 
   ///
-  // Remove the specified post data element.  Returns true (1) if the removal
-  // succeeds.
+  /// Remove the specified post data element.  Returns true (1) if the removal
+  /// succeeds.
   ///
   int(CEF_CALLBACK* remove_element)(struct _cef_post_data_t* self,
                                     struct _cef_post_data_element_t* element);
 
   ///
-  // Add the specified post data element.  Returns true (1) if the add succeeds.
+  /// Add the specified post data element.  Returns true (1) if the add
+  /// succeeds.
   ///
   int(CEF_CALLBACK* add_element)(struct _cef_post_data_t* self,
                                  struct _cef_post_data_element_t* element);
 
   ///
-  // Remove all existing post data elements.
+  /// Remove all existing post data elements.
   ///
   void(CEF_CALLBACK* remove_elements)(struct _cef_post_data_t* self);
 } cef_post_data_t;
 
 ///
-// Create a new cef_post_data_t object.
+/// Create a new cef_post_data_t object.
 ///
-CEF_EXPORT cef_post_data_t* cef_post_data_create();
+CEF_EXPORT cef_post_data_t* cef_post_data_create(void);
 
 ///
-// Structure used to represent a single element in the request post data. The
-// functions of this structure may be called on any thread.
+/// Structure used to represent a single element in the request post data. The
+/// functions of this structure may be called on any thread.
 ///
 typedef struct _cef_post_data_element_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if this object is read-only.
+  /// Returns true (1) if this object is read-only.
   ///
   int(CEF_CALLBACK* is_read_only)(struct _cef_post_data_element_t* self);
 
   ///
-  // Remove all contents from the post data element.
+  /// Remove all contents from the post data element.
   ///
   void(CEF_CALLBACK* set_to_empty)(struct _cef_post_data_element_t* self);
 
   ///
-  // The post data element will represent a file.
+  /// The post data element will represent a file.
   ///
   void(CEF_CALLBACK* set_to_file)(struct _cef_post_data_element_t* self,
                                   const cef_string_t* fileName);
 
   ///
-  // The post data element will represent bytes.  The bytes passed in will be
-  // copied.
+  /// The post data element will represent bytes.  The bytes passed in will be
+  /// copied.
   ///
   void(CEF_CALLBACK* set_to_bytes)(struct _cef_post_data_element_t* self,
                                    size_t size,
                                    const void* bytes);
 
   ///
-  // Return the type of this post data element.
+  /// Return the type of this post data element.
   ///
   cef_postdataelement_type_t(CEF_CALLBACK* get_type)(
       struct _cef_post_data_element_t* self);
 
   ///
-  // Return the file name.
+  /// Return the file name.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_file)(
       struct _cef_post_data_element_t* self);
 
   ///
-  // Return the number of bytes.
+  /// Return the number of bytes.
   ///
   size_t(CEF_CALLBACK* get_bytes_count)(struct _cef_post_data_element_t* self);
 
   ///
-  // Read up to |size| bytes into |bytes| and return the number of bytes
-  // actually read.
+  /// Read up to |size| bytes into |bytes| and return the number of bytes
+  /// actually read.
   ///
   size_t(CEF_CALLBACK* get_bytes)(struct _cef_post_data_element_t* self,
                                   size_t size,
@@ -342,9 +344,9 @@
 } cef_post_data_element_t;
 
 ///
-// Create a new cef_post_data_element_t object.
+/// Create a new cef_post_data_element_t object.
 ///
-CEF_EXPORT cef_post_data_element_t* cef_post_data_element_create();
+CEF_EXPORT cef_post_data_element_t* cef_post_data_element_create(void);
 
 #ifdef __cplusplus
 }
diff --git a/src/include/capi/cef_request_context_capi.h b/src/include/capi/cef_request_context_capi.h
index 679204c..2222666 100644
--- a/src/include/capi/cef_request_context_capi.h
+++ b/src/include/capi/cef_request_context_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=7ce0953f069204a4dd2037c4a05ac9454c5e66a6$
+// $hash=1c3c3dfb4bde6cd45278c6a80fbc53f624017c44$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_REQUEST_CONTEXT_CAPI_H_
@@ -45,6 +45,7 @@
 #include "include/capi/cef_extension_capi.h"
 #include "include/capi/cef_extension_handler_capi.h"
 #include "include/capi/cef_media_router_capi.h"
+#include "include/capi/cef_preference_capi.h"
 #include "include/capi/cef_values_capi.h"
 
 #ifdef __cplusplus
@@ -55,18 +56,18 @@
 struct _cef_scheme_handler_factory_t;
 
 ///
-// Callback structure for cef_request_context_t::ResolveHost.
+/// Callback structure for cef_request_context_t::ResolveHost.
 ///
 typedef struct _cef_resolve_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called on the UI thread after the ResolveHost request has completed.
-  // |result| will be the result code. |resolved_ips| will be the list of
-  // resolved IP addresses or NULL if the resolution failed.
+  /// Called on the UI thread after the ResolveHost request has completed.
+  /// |result| will be the result code. |resolved_ips| will be the list of
+  /// resolved IP addresses or NULL if the resolution failed.
   ///
   void(CEF_CALLBACK* on_resolve_completed)(struct _cef_resolve_callback_t* self,
                                            cef_errorcode_t result,
@@ -74,83 +75,83 @@
 } cef_resolve_callback_t;
 
 ///
-// A request context provides request handling for a set of related browser or
-// URL request objects. A request context can be specified when creating a new
-// browser via the cef_browser_host_t static factory functions or when creating
-// a new URL request via the cef_urlrequest_t static factory functions. Browser
-// objects with different request contexts will never be hosted in the same
-// render process. Browser objects with the same request context may or may not
-// be hosted in the same render process depending on the process model. Browser
-// objects created indirectly via the JavaScript window.open function or
-// targeted links will share the same render process and the same request
-// context as the source browser. When running in single-process mode there is
-// only a single render process (the main process) and so all browsers created
-// in single-process mode will share the same request context. This will be the
-// first request context passed into a cef_browser_host_t static factory
-// function and all other request context objects will be ignored.
+/// A request context provides request handling for a set of related browser or
+/// URL request objects. A request context can be specified when creating a new
+/// browser via the cef_browser_host_t static factory functions or when creating
+/// a new URL request via the cef_urlrequest_t static factory functions. Browser
+/// objects with different request contexts will never be hosted in the same
+/// render process. Browser objects with the same request context may or may not
+/// be hosted in the same render process depending on the process model. Browser
+/// objects created indirectly via the JavaScript window.open function or
+/// targeted links will share the same render process and the same request
+/// context as the source browser. When running in single-process mode there is
+/// only a single render process (the main process) and so all browsers created
+/// in single-process mode will share the same request context. This will be the
+/// first request context passed into a cef_browser_host_t static factory
+/// function and all other request context objects will be ignored.
 ///
 typedef struct _cef_request_context_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
-  cef_base_ref_counted_t base;
+  cef_preference_manager_t base;
 
   ///
-  // Returns true (1) if this object is pointing to the same context as |that|
-  // object.
+  /// Returns true (1) if this object is pointing to the same context as |that|
+  /// object.
   ///
   int(CEF_CALLBACK* is_same)(struct _cef_request_context_t* self,
                              struct _cef_request_context_t* other);
 
   ///
-  // Returns true (1) if this object is sharing the same storage as |that|
-  // object.
+  /// Returns true (1) if this object is sharing the same storage as |that|
+  /// object.
   ///
   int(CEF_CALLBACK* is_sharing_with)(struct _cef_request_context_t* self,
                                      struct _cef_request_context_t* other);
 
   ///
-  // Returns true (1) if this object is the global context. The global context
-  // is used by default when creating a browser or URL request with a NULL
-  // context argument.
+  /// Returns true (1) if this object is the global context. The global context
+  /// is used by default when creating a browser or URL request with a NULL
+  /// context argument.
   ///
   int(CEF_CALLBACK* is_global)(struct _cef_request_context_t* self);
 
   ///
-  // Returns the handler for this context if any.
+  /// Returns the handler for this context if any.
   ///
   struct _cef_request_context_handler_t*(CEF_CALLBACK* get_handler)(
       struct _cef_request_context_t* self);
 
   ///
-  // Returns the cache path for this object. If NULL an "incognito mode" in-
-  // memory cache is being used.
+  /// Returns the cache path for this object. If NULL an "incognito mode" in-
+  /// memory cache is being used.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_cache_path)(
       struct _cef_request_context_t* self);
 
   ///
-  // Returns the cookie manager for this object. If |callback| is non-NULL it
-  // will be executed asnychronously on the IO thread after the manager's
-  // storage has been initialized.
+  /// Returns the cookie manager for this object. If |callback| is non-NULL it
+  /// will be executed asnychronously on the UI thread after the manager's
+  /// storage has been initialized.
   ///
   struct _cef_cookie_manager_t*(CEF_CALLBACK* get_cookie_manager)(
       struct _cef_request_context_t* self,
       struct _cef_completion_callback_t* callback);
 
   ///
-  // Register a scheme handler factory for the specified |scheme_name| and
-  // optional |domain_name|. An NULL |domain_name| value for a standard scheme
-  // will cause the factory to match all domain names. The |domain_name| value
-  // will be ignored for non-standard schemes. If |scheme_name| is a built-in
-  // scheme and no handler is returned by |factory| then the built-in scheme
-  // handler factory will be called. If |scheme_name| is a custom scheme then
-  // you must also implement the cef_app_t::on_register_custom_schemes()
-  // function in all processes. This function may be called multiple times to
-  // change or remove the factory that matches the specified |scheme_name| and
-  // optional |domain_name|. Returns false (0) if an error occurs. This function
-  // may be called on any thread in the browser process.
+  /// Register a scheme handler factory for the specified |scheme_name| and
+  /// optional |domain_name|. An NULL |domain_name| value for a standard scheme
+  /// will cause the factory to match all domain names. The |domain_name| value
+  /// will be ignored for non-standard schemes. If |scheme_name| is a built-in
+  /// scheme and no handler is returned by |factory| then the built-in scheme
+  /// handler factory will be called. If |scheme_name| is a custom scheme then
+  /// you must also implement the cef_app_t::on_register_custom_schemes()
+  /// function in all processes. This function may be called multiple times to
+  /// change or remove the factory that matches the specified |scheme_name| and
+  /// optional |domain_name|. Returns false (0) if an error occurs. This
+  /// function may be called on any thread in the browser process.
   ///
   int(CEF_CALLBACK* register_scheme_handler_factory)(
       struct _cef_request_context_t* self,
@@ -159,160 +160,98 @@
       struct _cef_scheme_handler_factory_t* factory);
 
   ///
-  // Clear all registered scheme handler factories. Returns false (0) on error.
-  // This function may be called on any thread in the browser process.
+  /// Clear all registered scheme handler factories. Returns false (0) on error.
+  /// This function may be called on any thread in the browser process.
   ///
   int(CEF_CALLBACK* clear_scheme_handler_factories)(
       struct _cef_request_context_t* self);
 
   ///
-  // Tells all renderer processes associated with this context to throw away
-  // their plugin list cache. If |reload_pages| is true (1) they will also
-  // reload all pages with plugins.
-  // cef_request_context_handler_t::OnBeforePluginLoad may be called to rebuild
-  // the plugin list cache.
-  ///
-  void(CEF_CALLBACK* purge_plugin_list_cache)(
-      struct _cef_request_context_t* self,
-      int reload_pages);
-
-  ///
-  // Returns true (1) if a preference with the specified |name| exists. This
-  // function must be called on the browser process UI thread.
-  ///
-  int(CEF_CALLBACK* has_preference)(struct _cef_request_context_t* self,
-                                    const cef_string_t* name);
-
-  ///
-  // Returns the value for the preference with the specified |name|. Returns
-  // NULL if the preference does not exist. The returned object contains a copy
-  // of the underlying preference value and modifications to the returned object
-  // will not modify the underlying preference value. This function must be
-  // called on the browser process UI thread.
-  ///
-  struct _cef_value_t*(CEF_CALLBACK* get_preference)(
-      struct _cef_request_context_t* self,
-      const cef_string_t* name);
-
-  ///
-  // Returns all preferences as a dictionary. If |include_defaults| is true (1)
-  // then preferences currently at their default value will be included. The
-  // returned object contains a copy of the underlying preference values and
-  // modifications to the returned object will not modify the underlying
-  // preference values. This function must be called on the browser process UI
-  // thread.
-  ///
-  struct _cef_dictionary_value_t*(CEF_CALLBACK* get_all_preferences)(
-      struct _cef_request_context_t* self,
-      int include_defaults);
-
-  ///
-  // Returns true (1) if the preference with the specified |name| can be
-  // modified using SetPreference. As one example preferences set via the
-  // command-line usually cannot be modified. This function must be called on
-  // the browser process UI thread.
-  ///
-  int(CEF_CALLBACK* can_set_preference)(struct _cef_request_context_t* self,
-                                        const cef_string_t* name);
-
-  ///
-  // Set the |value| associated with preference |name|. Returns true (1) if the
-  // value is set successfully and false (0) otherwise. If |value| is NULL the
-  // preference will be restored to its default value. If setting the preference
-  // fails then |error| will be populated with a detailed description of the
-  // problem. This function must be called on the browser process UI thread.
-  ///
-  int(CEF_CALLBACK* set_preference)(struct _cef_request_context_t* self,
-                                    const cef_string_t* name,
-                                    struct _cef_value_t* value,
-                                    cef_string_t* error);
-
-  ///
-  // Clears all certificate exceptions that were added as part of handling
-  // cef_request_handler_t::on_certificate_error(). If you call this it is
-  // recommended that you also call close_all_connections() or you risk not
-  // being prompted again for server certificates if you reconnect quickly. If
-  // |callback| is non-NULL it will be executed on the UI thread after
-  // completion.
+  /// Clears all certificate exceptions that were added as part of handling
+  /// cef_request_handler_t::on_certificate_error(). If you call this it is
+  /// recommended that you also call close_all_connections() or you risk not
+  /// being prompted again for server certificates if you reconnect quickly. If
+  /// |callback| is non-NULL it will be executed on the UI thread after
+  /// completion.
   ///
   void(CEF_CALLBACK* clear_certificate_exceptions)(
       struct _cef_request_context_t* self,
       struct _cef_completion_callback_t* callback);
 
   ///
-  // Clears all HTTP authentication credentials that were added as part of
-  // handling GetAuthCredentials. If |callback| is non-NULL it will be executed
-  // on the UI thread after completion.
+  /// Clears all HTTP authentication credentials that were added as part of
+  /// handling GetAuthCredentials. If |callback| is non-NULL it will be executed
+  /// on the UI thread after completion.
   ///
   void(CEF_CALLBACK* clear_http_auth_credentials)(
       struct _cef_request_context_t* self,
       struct _cef_completion_callback_t* callback);
 
   ///
-  // Clears all active and idle connections that Chromium currently has. This is
-  // only recommended if you have released all other CEF objects but don't yet
-  // want to call cef_shutdown(). If |callback| is non-NULL it will be executed
-  // on the UI thread after completion.
+  /// Clears all active and idle connections that Chromium currently has. This
+  /// is only recommended if you have released all other CEF objects but don't
+  /// yet want to call cef_shutdown(). If |callback| is non-NULL it will be
+  /// executed on the UI thread after completion.
   ///
   void(CEF_CALLBACK* close_all_connections)(
       struct _cef_request_context_t* self,
       struct _cef_completion_callback_t* callback);
 
   ///
-  // Attempts to resolve |origin| to a list of associated IP addresses.
-  // |callback| will be executed on the UI thread after completion.
+  /// Attempts to resolve |origin| to a list of associated IP addresses.
+  /// |callback| will be executed on the UI thread after completion.
   ///
   void(CEF_CALLBACK* resolve_host)(struct _cef_request_context_t* self,
                                    const cef_string_t* origin,
                                    struct _cef_resolve_callback_t* callback);
 
   ///
-  // Load an extension.
-  //
-  // If extension resources will be read from disk using the default load
-  // implementation then |root_directory| should be the absolute path to the
-  // extension resources directory and |manifest| should be NULL. If extension
-  // resources will be provided by the client (e.g. via cef_request_handler_t
-  // and/or cef_extension_handler_t) then |root_directory| should be a path
-  // component unique to the extension (if not absolute this will be internally
-  // prefixed with the PK_DIR_RESOURCES path) and |manifest| should contain the
-  // contents that would otherwise be read from the "manifest.json" file on
-  // disk.
-  //
-  // The loaded extension will be accessible in all contexts sharing the same
-  // storage (HasExtension returns true (1)). However, only the context on which
-  // this function was called is considered the loader (DidLoadExtension returns
-  // true (1)) and only the loader will receive cef_request_context_handler_t
-  // callbacks for the extension.
-  //
-  // cef_extension_handler_t::OnExtensionLoaded will be called on load success
-  // or cef_extension_handler_t::OnExtensionLoadFailed will be called on load
-  // failure.
-  //
-  // If the extension specifies a background script via the "background"
-  // manifest key then cef_extension_handler_t::OnBeforeBackgroundBrowser will
-  // be called to create the background browser. See that function for
-  // additional information about background scripts.
-  //
-  // For visible extension views the client application should evaluate the
-  // manifest to determine the correct extension URL to load and then pass that
-  // URL to the cef_browser_host_t::CreateBrowser* function after the extension
-  // has loaded. For example, the client can look for the "browser_action"
-  // manifest key as documented at
-  // https://developer.chrome.com/extensions/browserAction. Extension URLs take
-  // the form "chrome-extension://<extension_id>/<path>".
-  //
-  // Browsers that host extensions differ from normal browsers as follows:
-  //  - Can access chrome.* JavaScript APIs if allowed by the manifest. Visit
-  //    chrome://extensions-support for the list of extension APIs currently
-  //    supported by CEF.
-  //  - Main frame navigation to non-extension content is blocked.
-  //  - Pinch-zooming is disabled.
-  //  - CefBrowserHost::GetExtension returns the hosted extension.
-  //  - CefBrowserHost::IsBackgroundHost returns true for background hosts.
-  //
-  // See https://developer.chrome.com/extensions for extension implementation
-  // and usage documentation.
+  /// Load an extension.
+  ///
+  /// If extension resources will be read from disk using the default load
+  /// implementation then |root_directory| should be the absolute path to the
+  /// extension resources directory and |manifest| should be NULL. If extension
+  /// resources will be provided by the client (e.g. via cef_request_handler_t
+  /// and/or cef_extension_handler_t) then |root_directory| should be a path
+  /// component unique to the extension (if not absolute this will be internally
+  /// prefixed with the PK_DIR_RESOURCES path) and |manifest| should contain the
+  /// contents that would otherwise be read from the "manifest.json" file on
+  /// disk.
+  ///
+  /// The loaded extension will be accessible in all contexts sharing the same
+  /// storage (HasExtension returns true (1)). However, only the context on
+  /// which this function was called is considered the loader (DidLoadExtension
+  /// returns true (1)) and only the loader will receive
+  /// cef_request_context_handler_t callbacks for the extension.
+  ///
+  /// cef_extension_handler_t::OnExtensionLoaded will be called on load success
+  /// or cef_extension_handler_t::OnExtensionLoadFailed will be called on load
+  /// failure.
+  ///
+  /// If the extension specifies a background script via the "background"
+  /// manifest key then cef_extension_handler_t::OnBeforeBackgroundBrowser will
+  /// be called to create the background browser. See that function for
+  /// additional information about background scripts.
+  ///
+  /// For visible extension views the client application should evaluate the
+  /// manifest to determine the correct extension URL to load and then pass that
+  /// URL to the cef_browser_host_t::CreateBrowser* function after the extension
+  /// has loaded. For example, the client can look for the "browser_action"
+  /// manifest key as documented at
+  /// https://developer.chrome.com/extensions/browserAction. Extension URLs take
+  /// the form "chrome-extension://<extension_id>/<path>".
+  ///
+  /// Browsers that host extensions differ from normal browsers as follows:
+  ///  - Can access chrome.* JavaScript APIs if allowed by the manifest. Visit
+  ///    chrome://extensions-support for the list of extension APIs currently
+  ///    supported by CEF.
+  ///  - Main frame navigation to non-extension content is blocked.
+  ///  - Pinch-zooming is disabled.
+  ///  - CefBrowserHost::GetExtension returns the hosted extension.
+  ///  - CefBrowserHost::IsBackgroundHost returns true for background hosts.
+  ///
+  /// See https://developer.chrome.com/extensions for extension implementation
+  /// and usage documentation.
   ///
   void(CEF_CALLBACK* load_extension)(struct _cef_request_context_t* self,
                                      const cef_string_t* root_directory,
@@ -320,64 +259,133 @@
                                      struct _cef_extension_handler_t* handler);
 
   ///
-  // Returns true (1) if this context was used to load the extension identified
-  // by |extension_id|. Other contexts sharing the same storage will also have
-  // access to the extension (see HasExtension). This function must be called on
-  // the browser process UI thread.
+  /// Returns true (1) if this context was used to load the extension identified
+  /// by |extension_id|. Other contexts sharing the same storage will also have
+  /// access to the extension (see HasExtension). This function must be called
+  /// on the browser process UI thread.
   ///
   int(CEF_CALLBACK* did_load_extension)(struct _cef_request_context_t* self,
                                         const cef_string_t* extension_id);
 
   ///
-  // Returns true (1) if this context has access to the extension identified by
-  // |extension_id|. This may not be the context that was used to load the
-  // extension (see DidLoadExtension). This function must be called on the
-  // browser process UI thread.
+  /// Returns true (1) if this context has access to the extension identified by
+  /// |extension_id|. This may not be the context that was used to load the
+  /// extension (see DidLoadExtension). This function must be called on the
+  /// browser process UI thread.
   ///
   int(CEF_CALLBACK* has_extension)(struct _cef_request_context_t* self,
                                    const cef_string_t* extension_id);
 
   ///
-  // Retrieve the list of all extensions that this context has access to (see
-  // HasExtension). |extension_ids| will be populated with the list of extension
-  // ID values. Returns true (1) on success. This function must be called on the
-  // browser process UI thread.
+  /// Retrieve the list of all extensions that this context has access to (see
+  /// HasExtension). |extension_ids| will be populated with the list of
+  /// extension ID values. Returns true (1) on success. This function must be
+  /// called on the browser process UI thread.
   ///
   int(CEF_CALLBACK* get_extensions)(struct _cef_request_context_t* self,
                                     cef_string_list_t extension_ids);
 
   ///
-  // Returns the extension matching |extension_id| or NULL if no matching
-  // extension is accessible in this context (see HasExtension). This function
-  // must be called on the browser process UI thread.
+  /// Returns the extension matching |extension_id| or NULL if no matching
+  /// extension is accessible in this context (see HasExtension). This function
+  /// must be called on the browser process UI thread.
   ///
   struct _cef_extension_t*(CEF_CALLBACK* get_extension)(
       struct _cef_request_context_t* self,
       const cef_string_t* extension_id);
 
   ///
-  // Returns the MediaRouter object associated with this context.
+  /// Returns the MediaRouter object associated with this context.  If
+  /// |callback| is non-NULL it will be executed asnychronously on the UI thread
+  /// after the manager's context has been initialized.
   ///
   struct _cef_media_router_t*(CEF_CALLBACK* get_media_router)(
-      struct _cef_request_context_t* self);
+      struct _cef_request_context_t* self,
+      struct _cef_completion_callback_t* callback);
+
+  ///
+  /// Returns the current value for |content_type| that applies for the
+  /// specified URLs. If both URLs are NULL the default value will be returned.
+  /// Returns nullptr if no value is configured. Must be called on the browser
+  /// process UI thread.
+  ///
+  struct _cef_value_t*(CEF_CALLBACK* get_website_setting)(
+      struct _cef_request_context_t* self,
+      const cef_string_t* requesting_url,
+      const cef_string_t* top_level_url,
+      cef_content_setting_types_t content_type);
+
+  ///
+  /// Sets the current value for |content_type| for the specified URLs in the
+  /// default scope. If both URLs are NULL, and the context is not incognito,
+  /// the default value will be set. Pass nullptr for |value| to remove the
+  /// default value for this content type.
+  ///
+  /// WARNING: Incorrect usage of this function may cause instability or
+  /// security issues in Chromium. Make sure that you first understand the
+  /// potential impact of any changes to |content_type| by reviewing the related
+  /// source code in Chromium. For example, if you plan to modify
+  /// CEF_CONTENT_SETTING_TYPE_POPUPS, first review and understand the usage of
+  /// ContentSettingsType::POPUPS in Chromium:
+  /// https://source.chromium.org/search?q=ContentSettingsType::POPUPS
+  ///
+  void(CEF_CALLBACK* set_website_setting)(
+      struct _cef_request_context_t* self,
+      const cef_string_t* requesting_url,
+      const cef_string_t* top_level_url,
+      cef_content_setting_types_t content_type,
+      struct _cef_value_t* value);
+
+  ///
+  /// Returns the current value for |content_type| that applies for the
+  /// specified URLs. If both URLs are NULL the default value will be returned.
+  /// Returns CEF_CONTENT_SETTING_VALUE_DEFAULT if no value is configured. Must
+  /// be called on the browser process UI thread.
+  ///
+  cef_content_setting_values_t(CEF_CALLBACK* get_content_setting)(
+      struct _cef_request_context_t* self,
+      const cef_string_t* requesting_url,
+      const cef_string_t* top_level_url,
+      cef_content_setting_types_t content_type);
+
+  ///
+  /// Sets the current value for |content_type| for the specified URLs in the
+  /// default scope. If both URLs are NULL, and the context is not incognito,
+  /// the default value will be set. Pass CEF_CONTENT_SETTING_VALUE_DEFAULT for
+  /// |value| to use the default value for this content type.
+  ///
+  /// WARNING: Incorrect usage of this function may cause instability or
+  /// security issues in Chromium. Make sure that you first understand the
+  /// potential impact of any changes to |content_type| by reviewing the related
+  /// source code in Chromium. For example, if you plan to modify
+  /// CEF_CONTENT_SETTING_TYPE_POPUPS, first review and understand the usage of
+  /// ContentSettingsType::POPUPS in Chromium:
+  /// https://source.chromium.org/search?q=ContentSettingsType::POPUPS
+  ///
+  void(CEF_CALLBACK* set_content_setting)(
+      struct _cef_request_context_t* self,
+      const cef_string_t* requesting_url,
+      const cef_string_t* top_level_url,
+      cef_content_setting_types_t content_type,
+      cef_content_setting_values_t value);
 } cef_request_context_t;
 
 ///
-// Returns the global context object.
+/// Returns the global context object.
 ///
-CEF_EXPORT cef_request_context_t* cef_request_context_get_global_context();
+CEF_EXPORT cef_request_context_t* cef_request_context_get_global_context(void);
 
 ///
-// Creates a new context object with the specified |settings| and optional
-// |handler|.
+/// Creates a new context object with the specified |settings| and optional
+/// |handler|.
 ///
 CEF_EXPORT cef_request_context_t* cef_request_context_create_context(
     const struct _cef_request_context_settings_t* settings,
     struct _cef_request_context_handler_t* handler);
 
 ///
-// Creates a new context object that shares storage with |other| and uses an
-// optional |handler|.
+/// Creates a new context object that shares storage with |other| and uses an
+/// optional |handler|.
 ///
 CEF_EXPORT cef_request_context_t* cef_create_context_shared(
     cef_request_context_t* other,
diff --git a/src/include/capi/cef_request_context_handler_capi.h b/src/include/capi/cef_request_context_handler_capi.h
index 2d94686..d7e06f8 100644
--- a/src/include/capi/cef_request_context_handler_capi.h
+++ b/src/include/capi/cef_request_context_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=e758d8c53334b91bce818cc6e9f84915778d7827$
+// $hash=b0b532a12106d960adc446b980affeee12b93ae3$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_REQUEST_CONTEXT_HANDLER_CAPI_H_
@@ -43,78 +43,51 @@
 #include "include/capi/cef_base_capi.h"
 #include "include/capi/cef_browser_capi.h"
 #include "include/capi/cef_frame_capi.h"
+#include "include/capi/cef_preference_capi.h"
 #include "include/capi/cef_request_capi.h"
 #include "include/capi/cef_resource_request_handler_capi.h"
-#include "include/capi/cef_web_plugin_capi.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 ///
-// Implement this structure to provide handler implementations. The handler
-// instance will not be released until all objects related to the context have
-// been destroyed.
+/// Implement this structure to provide handler implementations. The handler
+/// instance will not be released until all objects related to the context have
+/// been destroyed.
 ///
 typedef struct _cef_request_context_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called on the browser process UI thread immediately after the request
-  // context has been initialized.
+  /// Called on the browser process UI thread immediately after the request
+  /// context has been initialized.
   ///
   void(CEF_CALLBACK* on_request_context_initialized)(
       struct _cef_request_context_handler_t* self,
       struct _cef_request_context_t* request_context);
 
   ///
-  // Called on multiple browser process threads before a plugin instance is
-  // loaded. |mime_type| is the mime type of the plugin that will be loaded.
-  // |plugin_url| is the content URL that the plugin will load and may be NULL.
-  // |is_main_frame| will be true (1) if the plugin is being loaded in the main
-  // (top-level) frame, |top_origin_url| is the URL for the top-level frame that
-  // contains the plugin when loading a specific plugin instance or NULL when
-  // building the initial list of enabled plugins for 'navigator.plugins'
-  // JavaScript state. |plugin_info| includes additional information about the
-  // plugin that will be loaded. |plugin_policy| is the recommended policy.
-  // Modify |plugin_policy| and return true (1) to change the policy. Return
-  // false (0) to use the recommended policy. The default plugin policy can be
-  // set at runtime using the `--plugin-policy=[allow|detect|block]` command-
-  // line flag. Decisions to mark a plugin as disabled by setting
-  // |plugin_policy| to PLUGIN_POLICY_DISABLED may be cached when
-  // |top_origin_url| is NULL. To purge the plugin list cache and potentially
-  // trigger new calls to this function call
-  // cef_request_context_t::PurgePluginListCache.
-  ///
-  int(CEF_CALLBACK* on_before_plugin_load)(
-      struct _cef_request_context_handler_t* self,
-      const cef_string_t* mime_type,
-      const cef_string_t* plugin_url,
-      int is_main_frame,
-      const cef_string_t* top_origin_url,
-      struct _cef_web_plugin_info_t* plugin_info,
-      cef_plugin_policy_t* plugin_policy);
-
-  ///
-  // Called on the browser process IO thread before a resource request is
-  // initiated. The |browser| and |frame| values represent the source of the
-  // request, and may be NULL for requests originating from service workers or
-  // cef_urlrequest_t. |request| represents the request contents and cannot be
-  // modified in this callback. |is_navigation| will be true (1) if the resource
-  // request is a navigation. |is_download| will be true (1) if the resource
-  // request is a download. |request_initiator| is the origin (scheme + domain)
-  // of the page that initiated the request. Set |disable_default_handling| to
-  // true (1) to disable default handling of the request, in which case it will
-  // need to be handled via cef_resource_request_handler_t::GetResourceHandler
-  // or it will be canceled. To allow the resource load to proceed with default
-  // handling return NULL. To specify a handler for the resource return a
-  // cef_resource_request_handler_t object. This function will not be called if
-  // the client associated with |browser| returns a non-NULL value from
-  // cef_request_handler_t::GetResourceRequestHandler for the same request
-  // (identified by cef_request_t::GetIdentifier).
+  /// Called on the browser process IO thread before a resource request is
+  /// initiated. The |browser| and |frame| values represent the source of the
+  /// request, and may be NULL for requests originating from service workers or
+  /// cef_urlrequest_t. |request| represents the request contents and cannot be
+  /// modified in this callback. |is_navigation| will be true (1) if the
+  /// resource request is a navigation. |is_download| will be true (1) if the
+  /// resource request is a download. |request_initiator| is the origin (scheme
+  /// + domain) of the page that initiated the request. Set
+  /// |disable_default_handling| to true (1) to disable default handling of the
+  /// request, in which case it will need to be handled via
+  /// cef_resource_request_handler_t::GetResourceHandler or it will be canceled.
+  /// To allow the resource load to proceed with default handling return NULL.
+  /// To specify a handler for the resource return a
+  /// cef_resource_request_handler_t object. This function will not be called if
+  /// the client associated with |browser| returns a non-NULL value from
+  /// cef_request_handler_t::GetResourceRequestHandler for the same request
+  /// (identified by cef_request_t::GetIdentifier).
   ///
   struct _cef_resource_request_handler_t*(
       CEF_CALLBACK* get_resource_request_handler)(
diff --git a/src/include/capi/cef_request_handler_capi.h b/src/include/capi/cef_request_handler_capi.h
index cd6be4f..9dd95a1 100644
--- a/src/include/capi/cef_request_handler_capi.h
+++ b/src/include/capi/cef_request_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=0167eb1abe614bd6391d273a8085fa3e53e7c217$
+// $hash=092d897e223273a940ed623547d82645f764519c$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_REQUEST_HANDLER_CAPI_H_
@@ -43,8 +43,8 @@
 #include "include/capi/cef_auth_callback_capi.h"
 #include "include/capi/cef_base_capi.h"
 #include "include/capi/cef_browser_capi.h"
+#include "include/capi/cef_callback_capi.h"
 #include "include/capi/cef_frame_capi.h"
-#include "include/capi/cef_request_callback_capi.h"
 #include "include/capi/cef_request_capi.h"
 #include "include/capi/cef_resource_request_handler_capi.h"
 #include "include/capi/cef_ssl_info_capi.h"
@@ -55,17 +55,17 @@
 #endif
 
 ///
-// Callback structure used to select a client certificate for authentication.
+/// Callback structure used to select a client certificate for authentication.
 ///
 typedef struct _cef_select_client_certificate_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Chooses the specified certificate for client certificate authentication.
-  // NULL value means that no client certificate should be used.
+  /// Chooses the specified certificate for client certificate authentication.
+  /// NULL value means that no client certificate should be used.
   ///
   void(CEF_CALLBACK* select)(
       struct _cef_select_client_certificate_callback_t* self,
@@ -73,26 +73,27 @@
 } cef_select_client_certificate_callback_t;
 
 ///
-// Implement this structure to handle events related to browser requests. The
-// functions of this structure will be called on the thread indicated.
+/// Implement this structure to handle events related to browser requests. The
+/// functions of this structure will be called on the thread indicated.
 ///
 typedef struct _cef_request_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called on the UI thread before browser navigation. Return true (1) to
-  // cancel the navigation or false (0) to allow the navigation to proceed. The
-  // |request| object cannot be modified in this callback.
-  // cef_load_handler_t::OnLoadingStateChange will be called twice in all cases.
-  // If the navigation is allowed cef_load_handler_t::OnLoadStart and
-  // cef_load_handler_t::OnLoadEnd will be called. If the navigation is canceled
-  // cef_load_handler_t::OnLoadError will be called with an |errorCode| value of
-  // ERR_ABORTED. The |user_gesture| value will be true (1) if the browser
-  // navigated via explicit user gesture (e.g. clicking a link) or false (0) if
-  // it navigated automatically (e.g. via the DomContentLoaded event).
+  /// Called on the UI thread before browser navigation. Return true (1) to
+  /// cancel the navigation or false (0) to allow the navigation to proceed. The
+  /// |request| object cannot be modified in this callback.
+  /// cef_load_handler_t::OnLoadingStateChange will be called twice in all
+  /// cases. If the navigation is allowed cef_load_handler_t::OnLoadStart and
+  /// cef_load_handler_t::OnLoadEnd will be called. If the navigation is
+  /// canceled cef_load_handler_t::OnLoadError will be called with an
+  /// |errorCode| value of ERR_ABORTED. The |user_gesture| value will be true
+  /// (1) if the browser navigated via explicit user gesture (e.g. clicking a
+  /// link) or false (0) if it navigated automatically (e.g. via the
+  /// DomContentLoaded event).
   ///
   int(CEF_CALLBACK* on_before_browse)(struct _cef_request_handler_t* self,
                                       struct _cef_browser_t* browser,
@@ -102,20 +103,20 @@
                                       int is_redirect);
 
   ///
-  // Called on the UI thread before OnBeforeBrowse in certain limited cases
-  // where navigating a new or different browser might be desirable. This
-  // includes user-initiated navigation that might open in a special way (e.g.
-  // links clicked via middle-click or ctrl + left-click) and certain types of
-  // cross-origin navigation initiated from the renderer process (e.g.
-  // navigating the top-level frame to/from a file URL). The |browser| and
-  // |frame| values represent the source of the navigation. The
-  // |target_disposition| value indicates where the user intended to navigate
-  // the browser based on standard Chromium behaviors (e.g. current tab, new
-  // tab, etc). The |user_gesture| value will be true (1) if the browser
-  // navigated via explicit user gesture (e.g. clicking a link) or false (0) if
-  // it navigated automatically (e.g. via the DomContentLoaded event). Return
-  // true (1) to cancel the navigation or false (0) to allow the navigation to
-  // proceed in the source browser's top-level frame.
+  /// Called on the UI thread before OnBeforeBrowse in certain limited cases
+  /// where navigating a new or different browser might be desirable. This
+  /// includes user-initiated navigation that might open in a special way (e.g.
+  /// links clicked via middle-click or ctrl + left-click) and certain types of
+  /// cross-origin navigation initiated from the renderer process (e.g.
+  /// navigating the top-level frame to/from a file URL). The |browser| and
+  /// |frame| values represent the source of the navigation. The
+  /// |target_disposition| value indicates where the user intended to navigate
+  /// the browser based on standard Chromium behaviors (e.g. current tab, new
+  /// tab, etc). The |user_gesture| value will be true (1) if the browser
+  /// navigated via explicit user gesture (e.g. clicking a link) or false (0) if
+  /// it navigated automatically (e.g. via the DomContentLoaded event). Return
+  /// true (1) to cancel the navigation or false (0) to allow the navigation to
+  /// proceed in the source browser's top-level frame.
   ///
   int(CEF_CALLBACK* on_open_urlfrom_tab)(
       struct _cef_request_handler_t* self,
@@ -126,20 +127,20 @@
       int user_gesture);
 
   ///
-  // Called on the browser process IO thread before a resource request is
-  // initiated. The |browser| and |frame| values represent the source of the
-  // request. |request| represents the request contents and cannot be modified
-  // in this callback. |is_navigation| will be true (1) if the resource request
-  // is a navigation. |is_download| will be true (1) if the resource request is
-  // a download. |request_initiator| is the origin (scheme + domain) of the page
-  // that initiated the request. Set |disable_default_handling| to true (1) to
-  // disable default handling of the request, in which case it will need to be
-  // handled via cef_resource_request_handler_t::GetResourceHandler or it will
-  // be canceled. To allow the resource load to proceed with default handling
-  // return NULL. To specify a handler for the resource return a
-  // cef_resource_request_handler_t object. If this callback returns NULL the
-  // same function will be called on the associated
-  // cef_request_context_handler_t, if any.
+  /// Called on the browser process IO thread before a resource request is
+  /// initiated. The |browser| and |frame| values represent the source of the
+  /// request. |request| represents the request contents and cannot be modified
+  /// in this callback. |is_navigation| will be true (1) if the resource request
+  /// is a navigation. |is_download| will be true (1) if the resource request is
+  /// a download. |request_initiator| is the origin (scheme + domain) of the
+  /// page that initiated the request. Set |disable_default_handling| to true
+  /// (1) to disable default handling of the request, in which case it will need
+  /// to be handled via cef_resource_request_handler_t::GetResourceHandler or it
+  /// will be canceled. To allow the resource load to proceed with default
+  /// handling return NULL. To specify a handler for the resource return a
+  /// cef_resource_request_handler_t object. If this callback returns NULL the
+  /// same function will be called on the associated
+  /// cef_request_context_handler_t, if any.
   ///
   struct _cef_resource_request_handler_t*(
       CEF_CALLBACK* get_resource_request_handler)(
@@ -153,16 +154,16 @@
       int* disable_default_handling);
 
   ///
-  // Called on the IO thread when the browser needs credentials from the user.
-  // |origin_url| is the origin making this authentication request. |isProxy|
-  // indicates whether the host is a proxy server. |host| contains the hostname
-  // and |port| contains the port number. |realm| is the realm of the challenge
-  // and may be NULL. |scheme| is the authentication scheme used, such as
-  // "basic" or "digest", and will be NULL if the source of the request is an
-  // FTP server. Return true (1) to continue the request and call
-  // cef_auth_callback_t::cont() either in this function or at a later time when
-  // the authentication information is available. Return false (0) to cancel the
-  // request immediately.
+  /// Called on the IO thread when the browser needs credentials from the user.
+  /// |origin_url| is the origin making this authentication request. |isProxy|
+  /// indicates whether the host is a proxy server. |host| contains the hostname
+  /// and |port| contains the port number. |realm| is the realm of the challenge
+  /// and may be NULL. |scheme| is the authentication scheme used, such as
+  /// "basic" or "digest", and will be NULL if the source of the request is an
+  /// FTP server. Return true (1) to continue the request and call
+  /// cef_auth_callback_t::cont() either in this function or at a later time
+  /// when the authentication information is available. Return false (0) to
+  /// cancel the request immediately.
   ///
   int(CEF_CALLBACK* get_auth_credentials)(
       struct _cef_request_handler_t* self,
@@ -176,48 +177,32 @@
       struct _cef_auth_callback_t* callback);
 
   ///
-  // Called on the IO thread when JavaScript requests a specific storage quota
-  // size via the webkitStorageInfo.requestQuota function. |origin_url| is the
-  // origin of the page making the request. |new_size| is the requested quota
-  // size in bytes. Return true (1) to continue the request and call
-  // cef_request_callback_t::cont() either in this function or at a later time
-  // to grant or deny the request. Return false (0) to cancel the request
-  // immediately.
+  /// Called on the UI thread to handle requests for URLs with an invalid SSL
+  /// certificate. Return true (1) and call cef_callback_t functions either in
+  /// this function or at a later time to continue or cancel the request. Return
+  /// false (0) to cancel the request immediately. If
+  /// cef_settings_t.ignore_certificate_errors is set all invalid certificates
+  /// will be accepted without calling this function.
   ///
-  int(CEF_CALLBACK* on_quota_request)(struct _cef_request_handler_t* self,
-                                      struct _cef_browser_t* browser,
-                                      const cef_string_t* origin_url,
-                                      int64 new_size,
-                                      struct _cef_request_callback_t* callback);
+  int(CEF_CALLBACK* on_certificate_error)(struct _cef_request_handler_t* self,
+                                          struct _cef_browser_t* browser,
+                                          cef_errorcode_t cert_error,
+                                          const cef_string_t* request_url,
+                                          struct _cef_sslinfo_t* ssl_info,
+                                          struct _cef_callback_t* callback);
 
   ///
-  // Called on the UI thread to handle requests for URLs with an invalid SSL
-  // certificate. Return true (1) and call cef_request_callback_t::cont() either
-  // in this function or at a later time to continue or cancel the request.
-  // Return false (0) to cancel the request immediately. If
-  // CefSettings.ignore_certificate_errors is set all invalid certificates will
-  // be accepted without calling this function.
-  ///
-  int(CEF_CALLBACK* on_certificate_error)(
-      struct _cef_request_handler_t* self,
-      struct _cef_browser_t* browser,
-      cef_errorcode_t cert_error,
-      const cef_string_t* request_url,
-      struct _cef_sslinfo_t* ssl_info,
-      struct _cef_request_callback_t* callback);
-
-  ///
-  // Called on the UI thread when a client certificate is being requested for
-  // authentication. Return false (0) to use the default behavior and
-  // automatically select the first certificate available. Return true (1) and
-  // call cef_select_client_certificate_callback_t::Select either in this
-  // function or at a later time to select a certificate. Do not call Select or
-  // call it with NULL to continue without using any certificate. |isProxy|
-  // indicates whether the host is an HTTPS proxy or the origin server. |host|
-  // and |port| contains the hostname and port of the SSL server. |certificates|
-  // is the list of certificates to choose from; this list has already been
-  // pruned by Chromium so that it only contains certificates from issuers that
-  // the server trusts.
+  /// Called on the UI thread when a client certificate is being requested for
+  /// authentication. Return false (0) to use the default behavior and
+  /// automatically select the first certificate available. Return true (1) and
+  /// call cef_select_client_certificate_callback_t::Select either in this
+  /// function or at a later time to select a certificate. Do not call Select or
+  /// call it with NULL to continue without using any certificate. |isProxy|
+  /// indicates whether the host is an HTTPS proxy or the origin server. |host|
+  /// and |port| contains the hostname and port of the SSL server.
+  /// |certificates| is the list of certificates to choose from; this list has
+  /// already been pruned by Chromium so that it only contains certificates from
+  /// issuers that the server trusts.
   ///
   int(CEF_CALLBACK* on_select_client_certificate)(
       struct _cef_request_handler_t* self,
@@ -230,24 +215,16 @@
       struct _cef_select_client_certificate_callback_t* callback);
 
   ///
-  // Called on the browser process UI thread when a plugin has crashed.
-  // |plugin_path| is the path of the plugin that crashed.
-  ///
-  void(CEF_CALLBACK* on_plugin_crashed)(struct _cef_request_handler_t* self,
-                                        struct _cef_browser_t* browser,
-                                        const cef_string_t* plugin_path);
-
-  ///
-  // Called on the browser process UI thread when the render view associated
-  // with |browser| is ready to receive/handle IPC messages in the render
-  // process.
+  /// Called on the browser process UI thread when the render view associated
+  /// with |browser| is ready to receive/handle IPC messages in the render
+  /// process.
   ///
   void(CEF_CALLBACK* on_render_view_ready)(struct _cef_request_handler_t* self,
                                            struct _cef_browser_t* browser);
 
   ///
-  // Called on the browser process UI thread when the render process terminates
-  // unexpectedly. |status| indicates how the process terminated.
+  /// Called on the browser process UI thread when the render process terminates
+  /// unexpectedly. |status| indicates how the process terminated.
   ///
   void(CEF_CALLBACK* on_render_process_terminated)(
       struct _cef_request_handler_t* self,
@@ -255,8 +232,8 @@
       cef_termination_status_t status);
 
   ///
-  // Called on the browser process UI thread when the window.document object of
-  // the main frame has been created.
+  /// Called on the browser process UI thread when the window.document object of
+  /// the main frame has been created.
   ///
   void(CEF_CALLBACK* on_document_available_in_main_frame)(
       struct _cef_request_handler_t* self,
diff --git a/src/include/capi/cef_resource_bundle_capi.h b/src/include/capi/cef_resource_bundle_capi.h
index 3a88870..b06728c 100644
--- a/src/include/capi/cef_resource_bundle_capi.h
+++ b/src/include/capi/cef_resource_bundle_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=b9577b495df3990284d4e4a3db2824196175dc91$
+// $hash=e8e8dd2730a47aad9414f7bfc2e6ad96aba2c875$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_RESOURCE_BUNDLE_CAPI_H_
@@ -41,28 +41,29 @@
 #pragma once
 
 #include "include/capi/cef_base_capi.h"
+#include "include/capi/cef_values_capi.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 ///
-// Structure used for retrieving resources from the resource bundle (*.pak)
-// files loaded by CEF during startup or via the cef_resource_bundle_handler_t
-// returned from cef_app_t::GetResourceBundleHandler. See CefSettings for
-// additional options related to resource bundle loading. The functions of this
-// structure may be called on any thread unless otherwise indicated.
+/// Structure used for retrieving resources from the resource bundle (*.pak)
+/// files loaded by CEF during startup or via the cef_resource_bundle_handler_t
+/// returned from cef_app_t::GetResourceBundleHandler. See CefSettings for
+/// additional options related to resource bundle loading. The functions of this
+/// structure may be called on any thread unless otherwise indicated.
 ///
 typedef struct _cef_resource_bundle_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the localized string for the specified |string_id| or an NULL
-  // string if the value is not found. Include cef_pack_strings.h for a listing
-  // of valid string ID values.
+  /// Returns the localized string for the specified |string_id| or an NULL
+  /// string if the value is not found. Include cef_pack_strings.h for a listing
+  /// of valid string ID values.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_localized_string)(
@@ -70,40 +71,31 @@
       int string_id);
 
   ///
-  // Retrieves the contents of the specified scale independent |resource_id|. If
-  // the value is found then |data| and |data_size| will be populated and this
-  // function will return true (1). If the value is not found then this function
-  // will return false (0). The returned |data| pointer will remain resident in
-  // memory and should not be freed. Include cef_pack_resources.h for a listing
-  // of valid resource ID values.
+  /// Returns a cef_binary_value_t containing the decompressed contents of the
+  /// specified scale independent |resource_id| or NULL if not found. Include
+  /// cef_pack_resources.h for a listing of valid resource ID values.
   ///
-  int(CEF_CALLBACK* get_data_resource)(struct _cef_resource_bundle_t* self,
-                                       int resource_id,
-                                       void** data,
-                                       size_t* data_size);
+  struct _cef_binary_value_t*(CEF_CALLBACK* get_data_resource)(
+      struct _cef_resource_bundle_t* self,
+      int resource_id);
 
   ///
-  // Retrieves the contents of the specified |resource_id| nearest the scale
-  // factor |scale_factor|. Use a |scale_factor| value of SCALE_FACTOR_NONE for
-  // scale independent resources or call GetDataResource instead. If the value
-  // is found then |data| and |data_size| will be populated and this function
-  // will return true (1). If the value is not found then this function will
-  // return false (0). The returned |data| pointer will remain resident in
-  // memory and should not be freed. Include cef_pack_resources.h for a listing
-  // of valid resource ID values.
+  /// Returns a cef_binary_value_t containing the decompressed contents of the
+  /// specified |resource_id| nearest the scale factor |scale_factor| or NULL if
+  /// not found. Use a |scale_factor| value of SCALE_FACTOR_NONE for scale
+  /// independent resources or call GetDataResource instead.Include
+  /// cef_pack_resources.h for a listing of valid resource ID values.
   ///
-  int(CEF_CALLBACK* get_data_resource_for_scale)(
+  struct _cef_binary_value_t*(CEF_CALLBACK* get_data_resource_for_scale)(
       struct _cef_resource_bundle_t* self,
       int resource_id,
-      cef_scale_factor_t scale_factor,
-      void** data,
-      size_t* data_size);
+      cef_scale_factor_t scale_factor);
 } cef_resource_bundle_t;
 
 ///
-// Returns the global resource bundle instance.
+/// Returns the global resource bundle instance.
 ///
-CEF_EXPORT cef_resource_bundle_t* cef_resource_bundle_get_global();
+CEF_EXPORT cef_resource_bundle_t* cef_resource_bundle_get_global(void);
 
 #ifdef __cplusplus
 }
diff --git a/src/include/capi/cef_resource_bundle_handler_capi.h b/src/include/capi/cef_resource_bundle_handler_capi.h
index 1cbae99..bc9eea5 100644
--- a/src/include/capi/cef_resource_bundle_handler_capi.h
+++ b/src/include/capi/cef_resource_bundle_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=fd90a707c59a8c04b1b1bfc6129a90e27934f501$
+// $hash=00023b2ec108ae6e4bd282d16e82032cdc99d548$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_RESOURCE_BUNDLE_HANDLER_CAPI_H_
@@ -47,21 +47,21 @@
 #endif
 
 ///
-// Structure used to implement a custom resource bundle structure. See
-// CefSettings for additional options related to resource bundle loading. The
-// functions of this structure may be called on multiple threads.
+/// Structure used to implement a custom resource bundle structure. See
+/// CefSettings for additional options related to resource bundle loading. The
+/// functions of this structure may be called on multiple threads.
 ///
 typedef struct _cef_resource_bundle_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called to retrieve a localized translation for the specified |string_id|.
-  // To provide the translation set |string| to the translation string and
-  // return true (1). To use the default translation return false (0). Include
-  // cef_pack_strings.h for a listing of valid string ID values.
+  /// Called to retrieve a localized translation for the specified |string_id|.
+  /// To provide the translation set |string| to the translation string and
+  /// return true (1). To use the default translation return false (0). Include
+  /// cef_pack_strings.h for a listing of valid string ID values.
   ///
   int(CEF_CALLBACK* get_localized_string)(
       struct _cef_resource_bundle_handler_t* self,
@@ -69,12 +69,12 @@
       cef_string_t* string);
 
   ///
-  // Called to retrieve data for the specified scale independent |resource_id|.
-  // To provide the resource data set |data| and |data_size| to the data pointer
-  // and size respectively and return true (1). To use the default resource data
-  // return false (0). The resource data will not be copied and must remain
-  // resident in memory. Include cef_pack_resources.h for a listing of valid
-  // resource ID values.
+  /// Called to retrieve data for the specified scale independent |resource_id|.
+  /// To provide the resource data set |data| and |data_size| to the data
+  /// pointer and size respectively and return true (1). To use the default
+  /// resource data return false (0). The resource data will not be copied and
+  /// must remain resident in memory. Include cef_pack_resources.h for a listing
+  /// of valid resource ID values.
   ///
   int(CEF_CALLBACK* get_data_resource)(
       struct _cef_resource_bundle_handler_t* self,
@@ -83,12 +83,12 @@
       size_t* data_size);
 
   ///
-  // Called to retrieve data for the specified |resource_id| nearest the scale
-  // factor |scale_factor|. To provide the resource data set |data| and
-  // |data_size| to the data pointer and size respectively and return true (1).
-  // To use the default resource data return false (0). The resource data will
-  // not be copied and must remain resident in memory. Include
-  // cef_pack_resources.h for a listing of valid resource ID values.
+  /// Called to retrieve data for the specified |resource_id| nearest the scale
+  /// factor |scale_factor|. To provide the resource data set |data| and
+  /// |data_size| to the data pointer and size respectively and return true (1).
+  /// To use the default resource data return false (0). The resource data will
+  /// not be copied and must remain resident in memory. Include
+  /// cef_pack_resources.h for a listing of valid resource ID values.
   ///
   int(CEF_CALLBACK* get_data_resource_for_scale)(
       struct _cef_resource_bundle_handler_t* self,
diff --git a/src/include/capi/cef_resource_handler_capi.h b/src/include/capi/cef_resource_handler_capi.h
index 1dc34f4..355fecc 100644
--- a/src/include/capi/cef_resource_handler_capi.h
+++ b/src/include/capi/cef_resource_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=5241e3dd5d3fa0b17dd6d6ea2f30734a32150c88$
+// $hash=ca5c224b373452158904b0f859f126f36c927f93$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_RESOURCE_HANDLER_CAPI_H_
@@ -52,63 +52,64 @@
 #endif
 
 ///
-// Callback for asynchronous continuation of cef_resource_handler_t::skip().
+/// Callback for asynchronous continuation of cef_resource_handler_t::skip().
 ///
 typedef struct _cef_resource_skip_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Callback for asynchronous continuation of skip(). If |bytes_skipped| > 0
-  // then either skip() will be called again until the requested number of bytes
-  // have been skipped or the request will proceed. If |bytes_skipped| <= 0 the
-  // request will fail with ERR_REQUEST_RANGE_NOT_SATISFIABLE.
+  /// Callback for asynchronous continuation of skip(). If |bytes_skipped| > 0
+  /// then either skip() will be called again until the requested number of
+  /// bytes have been skipped or the request will proceed. If |bytes_skipped| <=
+  /// 0 the request will fail with ERR_REQUEST_RANGE_NOT_SATISFIABLE.
   ///
   void(CEF_CALLBACK* cont)(struct _cef_resource_skip_callback_t* self,
-                           int64 bytes_skipped);
+                           int64_t bytes_skipped);
 } cef_resource_skip_callback_t;
 
 ///
-// Callback for asynchronous continuation of cef_resource_handler_t::read().
+/// Callback for asynchronous continuation of cef_resource_handler_t::read().
 ///
 typedef struct _cef_resource_read_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Callback for asynchronous continuation of read(). If |bytes_read| == 0 the
-  // response will be considered complete. If |bytes_read| > 0 then read() will
-  // be called again until the request is complete (based on either the result
-  // or the expected content length). If |bytes_read| < 0 then the request will
-  // fail and the |bytes_read| value will be treated as the error code.
+  /// Callback for asynchronous continuation of read(). If |bytes_read| == 0 the
+  /// response will be considered complete. If |bytes_read| > 0 then read() will
+  /// be called again until the request is complete (based on either the result
+  /// or the expected content length). If |bytes_read| < 0 then the request will
+  /// fail and the |bytes_read| value will be treated as the error code.
   ///
   void(CEF_CALLBACK* cont)(struct _cef_resource_read_callback_t* self,
                            int bytes_read);
 } cef_resource_read_callback_t;
 
 ///
-// Structure used to implement a custom request handler structure. The functions
-// of this structure will be called on the IO thread unless otherwise indicated.
+/// Structure used to implement a custom request handler structure. The
+/// functions of this structure will be called on the IO thread unless otherwise
+/// indicated.
 ///
 typedef struct _cef_resource_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Open the response stream. To handle the request immediately set
-  // |handle_request| to true (1) and return true (1). To decide at a later time
-  // set |handle_request| to false (0), return true (1), and execute |callback|
-  // to continue or cancel the request. To cancel the request immediately set
-  // |handle_request| to true (1) and return false (0). This function will be
-  // called in sequence but not from a dedicated thread. For backwards
-  // compatibility set |handle_request| to false (0) and return false (0) and
-  // the ProcessRequest function will be called.
+  /// Open the response stream. To handle the request immediately set
+  /// |handle_request| to true (1) and return true (1). To decide at a later
+  /// time set |handle_request| to false (0), return true (1), and execute
+  /// |callback| to continue or cancel the request. To cancel the request
+  /// immediately set |handle_request| to true (1) and return false (0). This
+  /// function will be called in sequence but not from a dedicated thread. For
+  /// backwards compatibility set |handle_request| to false (0) and return false
+  /// (0) and the ProcessRequest function will be called.
   ///
   int(CEF_CALLBACK* open)(struct _cef_resource_handler_t* self,
                           struct _cef_request_t* request,
@@ -116,64 +117,64 @@
                           struct _cef_callback_t* callback);
 
   ///
-  // Begin processing the request. To handle the request return true (1) and
-  // call cef_callback_t::cont() once the response header information is
-  // available (cef_callback_t::cont() can also be called from inside this
-  // function if header information is available immediately). To cancel the
-  // request return false (0).
-  //
-  // WARNING: This function is deprecated. Use Open instead.
+  /// Begin processing the request. To handle the request return true (1) and
+  /// call cef_callback_t::cont() once the response header information is
+  /// available (cef_callback_t::cont() can also be called from inside this
+  /// function if header information is available immediately). To cancel the
+  /// request return false (0).
+  ///
+  /// WARNING: This function is deprecated. Use Open instead.
   ///
   int(CEF_CALLBACK* process_request)(struct _cef_resource_handler_t* self,
                                      struct _cef_request_t* request,
                                      struct _cef_callback_t* callback);
 
   ///
-  // Retrieve response header information. If the response length is not known
-  // set |response_length| to -1 and read_response() will be called until it
-  // returns false (0). If the response length is known set |response_length| to
-  // a positive value and read_response() will be called until it returns false
-  // (0) or the specified number of bytes have been read. Use the |response|
-  // object to set the mime type, http status code and other optional header
-  // values. To redirect the request to a new URL set |redirectUrl| to the new
-  // URL. |redirectUrl| can be either a relative or fully qualified URL. It is
-  // also possible to set |response| to a redirect http status code and pass the
-  // new URL via a Location header. Likewise with |redirectUrl| it is valid to
-  // set a relative or fully qualified URL as the Location header value. If an
-  // error occured while setting up the request you can call set_error() on
-  // |response| to indicate the error condition.
+  /// Retrieve response header information. If the response length is not known
+  /// set |response_length| to -1 and read_response() will be called until it
+  /// returns false (0). If the response length is known set |response_length|
+  /// to a positive value and read_response() will be called until it returns
+  /// false (0) or the specified number of bytes have been read. Use the
+  /// |response| object to set the mime type, http status code and other
+  /// optional header values. To redirect the request to a new URL set
+  /// |redirectUrl| to the new URL. |redirectUrl| can be either a relative or
+  /// fully qualified URL. It is also possible to set |response| to a redirect
+  /// http status code and pass the new URL via a Location header. Likewise with
+  /// |redirectUrl| it is valid to set a relative or fully qualified URL as the
+  /// Location header value. If an error occured while setting up the request
+  /// you can call set_error() on |response| to indicate the error condition.
   ///
   void(CEF_CALLBACK* get_response_headers)(struct _cef_resource_handler_t* self,
                                            struct _cef_response_t* response,
-                                           int64* response_length,
+                                           int64_t* response_length,
                                            cef_string_t* redirectUrl);
 
   ///
-  // Skip response data when requested by a Range header. Skip over and discard
-  // |bytes_to_skip| bytes of response data. If data is available immediately
-  // set |bytes_skipped| to the number of bytes skipped and return true (1). To
-  // read the data at a later time set |bytes_skipped| to 0, return true (1) and
-  // execute |callback| when the data is available. To indicate failure set
-  // |bytes_skipped| to < 0 (e.g. -2 for ERR_FAILED) and return false (0). This
-  // function will be called in sequence but not from a dedicated thread.
+  /// Skip response data when requested by a Range header. Skip over and discard
+  /// |bytes_to_skip| bytes of response data. If data is available immediately
+  /// set |bytes_skipped| to the number of bytes skipped and return true (1). To
+  /// read the data at a later time set |bytes_skipped| to 0, return true (1)
+  /// and execute |callback| when the data is available. To indicate failure set
+  /// |bytes_skipped| to < 0 (e.g. -2 for ERR_FAILED) and return false (0). This
+  /// function will be called in sequence but not from a dedicated thread.
   ///
   int(CEF_CALLBACK* skip)(struct _cef_resource_handler_t* self,
-                          int64 bytes_to_skip,
-                          int64* bytes_skipped,
+                          int64_t bytes_to_skip,
+                          int64_t* bytes_skipped,
                           struct _cef_resource_skip_callback_t* callback);
 
   ///
-  // Read response data. If data is available immediately copy up to
-  // |bytes_to_read| bytes into |data_out|, set |bytes_read| to the number of
-  // bytes copied, and return true (1). To read the data at a later time keep a
-  // pointer to |data_out|, set |bytes_read| to 0, return true (1) and execute
-  // |callback| when the data is available (|data_out| will remain valid until
-  // the callback is executed). To indicate response completion set |bytes_read|
-  // to 0 and return false (0). To indicate failure set |bytes_read| to < 0
-  // (e.g. -2 for ERR_FAILED) and return false (0). This function will be called
-  // in sequence but not from a dedicated thread. For backwards compatibility
-  // set |bytes_read| to -1 and return false (0) and the ReadResponse function
-  // will be called.
+  /// Read response data. If data is available immediately copy up to
+  /// |bytes_to_read| bytes into |data_out|, set |bytes_read| to the number of
+  /// bytes copied, and return true (1). To read the data at a later time keep a
+  /// pointer to |data_out|, set |bytes_read| to 0, return true (1) and execute
+  /// |callback| when the data is available (|data_out| will remain valid until
+  /// the callback is executed). To indicate response completion set
+  /// |bytes_read| to 0 and return false (0). To indicate failure set
+  /// |bytes_read| to < 0 (e.g. -2 for ERR_FAILED) and return false (0). This
+  /// function will be called in sequence but not from a dedicated thread. For
+  /// backwards compatibility set |bytes_read| to -1 and return false (0) and
+  /// the ReadResponse function will be called.
   ///
   int(CEF_CALLBACK* read)(struct _cef_resource_handler_t* self,
                           void* data_out,
@@ -182,13 +183,13 @@
                           struct _cef_resource_read_callback_t* callback);
 
   ///
-  // Read response data. If data is available immediately copy up to
-  // |bytes_to_read| bytes into |data_out|, set |bytes_read| to the number of
-  // bytes copied, and return true (1). To read the data at a later time set
-  // |bytes_read| to 0, return true (1) and call cef_callback_t::cont() when the
-  // data is available. To indicate response completion return false (0).
-  //
-  // WARNING: This function is deprecated. Use Skip and Read instead.
+  /// Read response data. If data is available immediately copy up to
+  /// |bytes_to_read| bytes into |data_out|, set |bytes_read| to the number of
+  /// bytes copied, and return true (1). To read the data at a later time set
+  /// |bytes_read| to 0, return true (1) and call cef_callback_t::cont() when
+  /// the data is available. To indicate response completion return false (0).
+  ///
+  /// WARNING: This function is deprecated. Use Skip and Read instead.
   ///
   int(CEF_CALLBACK* read_response)(struct _cef_resource_handler_t* self,
                                    void* data_out,
@@ -197,7 +198,7 @@
                                    struct _cef_callback_t* callback);
 
   ///
-  // Request processing has been canceled.
+  /// Request processing has been canceled.
   ///
   void(CEF_CALLBACK* cancel)(struct _cef_resource_handler_t* self);
 } cef_resource_handler_t;
diff --git a/src/include/capi/cef_resource_request_handler_capi.h b/src/include/capi/cef_resource_request_handler_capi.h
index 428df69..b6b735c 100644
--- a/src/include/capi/cef_resource_request_handler_capi.h
+++ b/src/include/capi/cef_resource_request_handler_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=afc96f188710bd336d09ce479a650aaa3a55357a$
+// $hash=757155e6dbceef47938fd562f7f5f48a609ce288$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_RESOURCE_REQUEST_HANDLER_CAPI_H_
@@ -42,8 +42,8 @@
 
 #include "include/capi/cef_base_capi.h"
 #include "include/capi/cef_browser_capi.h"
+#include "include/capi/cef_callback_capi.h"
 #include "include/capi/cef_frame_capi.h"
-#include "include/capi/cef_request_callback_capi.h"
 #include "include/capi/cef_request_capi.h"
 #include "include/capi/cef_resource_handler_capi.h"
 #include "include/capi/cef_response_capi.h"
@@ -56,23 +56,23 @@
 struct _cef_cookie_access_filter_t;
 
 ///
-// Implement this structure to handle events related to browser requests. The
-// functions of this structure will be called on the IO thread unless otherwise
-// indicated.
+/// Implement this structure to handle events related to browser requests. The
+/// functions of this structure will be called on the IO thread unless otherwise
+/// indicated.
 ///
 typedef struct _cef_resource_request_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called on the IO thread before a resource request is loaded. The |browser|
-  // and |frame| values represent the source of the request, and may be NULL for
-  // requests originating from service workers or cef_urlrequest_t. To
-  // optionally filter cookies for the request return a
-  // cef_cookie_access_filter_t object. The |request| object cannot not be
-  // modified in this callback.
+  /// Called on the IO thread before a resource request is loaded. The |browser|
+  /// and |frame| values represent the source of the request, and may be NULL
+  /// for requests originating from service workers or cef_urlrequest_t. To
+  /// optionally filter cookies for the request return a
+  /// cef_cookie_access_filter_t object. The |request| object cannot not be
+  /// modified in this callback.
   ///
   struct _cef_cookie_access_filter_t*(CEF_CALLBACK* get_cookie_access_filter)(
       struct _cef_resource_request_handler_t* self,
@@ -81,30 +81,30 @@
       struct _cef_request_t* request);
 
   ///
-  // Called on the IO thread before a resource request is loaded. The |browser|
-  // and |frame| values represent the source of the request, and may be NULL for
-  // requests originating from service workers or cef_urlrequest_t. To redirect
-  // or change the resource load optionally modify |request|. Modification of
-  // the request URL will be treated as a redirect. Return RV_CONTINUE to
-  // continue the request immediately. Return RV_CONTINUE_ASYNC and call
-  // cef_request_callback_t:: cont() at a later time to continue or cancel the
-  // request asynchronously. Return RV_CANCEL to cancel the request immediately.
-  //
+  /// Called on the IO thread before a resource request is loaded. The |browser|
+  /// and |frame| values represent the source of the request, and may be NULL
+  /// for requests originating from service workers or cef_urlrequest_t. To
+  /// redirect or change the resource load optionally modify |request|.
+  /// Modification of the request URL will be treated as a redirect. Return
+  /// RV_CONTINUE to continue the request immediately. Return RV_CONTINUE_ASYNC
+  /// and call cef_callback_t functions at a later time to continue or cancel
+  /// the request asynchronously. Return RV_CANCEL to cancel the request
+  /// immediately.
   ///
   cef_return_value_t(CEF_CALLBACK* on_before_resource_load)(
       struct _cef_resource_request_handler_t* self,
       struct _cef_browser_t* browser,
       struct _cef_frame_t* frame,
       struct _cef_request_t* request,
-      struct _cef_request_callback_t* callback);
+      struct _cef_callback_t* callback);
 
   ///
-  // Called on the IO thread before a resource is loaded. The |browser| and
-  // |frame| values represent the source of the request, and may be NULL for
-  // requests originating from service workers or cef_urlrequest_t. To allow the
-  // resource to load using the default network loader return NULL. To specify a
-  // handler for the resource return a cef_resource_handler_t object. The
-  // |request| object cannot not be modified in this callback.
+  /// Called on the IO thread before a resource is loaded. The |browser| and
+  /// |frame| values represent the source of the request, and may be NULL for
+  /// requests originating from service workers or cef_urlrequest_t. To allow
+  /// the resource to load using the default network loader return NULL. To
+  /// specify a handler for the resource return a cef_resource_handler_t object.
+  /// The |request| object cannot not be modified in this callback.
   ///
   struct _cef_resource_handler_t*(CEF_CALLBACK* get_resource_handler)(
       struct _cef_resource_request_handler_t* self,
@@ -113,14 +113,14 @@
       struct _cef_request_t* request);
 
   ///
-  // Called on the IO thread when a resource load is redirected. The |browser|
-  // and |frame| values represent the source of the request, and may be NULL for
-  // requests originating from service workers or cef_urlrequest_t. The
-  // |request| parameter will contain the old URL and other request-related
-  // information. The |response| parameter will contain the response that
-  // resulted in the redirect. The |new_url| parameter will contain the new URL
-  // and can be changed if desired. The |request| and |response| objects cannot
-  // be modified in this callback.
+  /// Called on the IO thread when a resource load is redirected. The |browser|
+  /// and |frame| values represent the source of the request, and may be NULL
+  /// for requests originating from service workers or cef_urlrequest_t. The
+  /// |request| parameter will contain the old URL and other request-related
+  /// information. The |response| parameter will contain the response that
+  /// resulted in the redirect. The |new_url| parameter will contain the new URL
+  /// and can be changed if desired. The |request| and |response| objects cannot
+  /// be modified in this callback.
   ///
   void(CEF_CALLBACK* on_resource_redirect)(
       struct _cef_resource_request_handler_t* self,
@@ -131,17 +131,18 @@
       cef_string_t* new_url);
 
   ///
-  // Called on the IO thread when a resource response is received. The |browser|
-  // and |frame| values represent the source of the request, and may be NULL for
-  // requests originating from service workers or cef_urlrequest_t. To allow the
-  // resource load to proceed without modification return false (0). To redirect
-  // or retry the resource load optionally modify |request| and return true (1).
-  // Modification of the request URL will be treated as a redirect. Requests
-  // handled using the default network loader cannot be redirected in this
-  // callback. The |response| object cannot be modified in this callback.
-  //
-  // WARNING: Redirecting using this function is deprecated. Use
-  // OnBeforeResourceLoad or GetResourceHandler to perform redirects.
+  /// Called on the IO thread when a resource response is received. The
+  /// |browser| and |frame| values represent the source of the request, and may
+  /// be NULL for requests originating from service workers or cef_urlrequest_t.
+  /// To allow the resource load to proceed without modification return false
+  /// (0). To redirect or retry the resource load optionally modify |request|
+  /// and return true (1). Modification of the request URL will be treated as a
+  /// redirect. Requests handled using the default network loader cannot be
+  /// redirected in this callback. The |response| object cannot be modified in
+  /// this callback.
+  ///
+  /// WARNING: Redirecting using this function is deprecated. Use
+  /// OnBeforeResourceLoad or GetResourceHandler to perform redirects.
   ///
   int(CEF_CALLBACK* on_resource_response)(
       struct _cef_resource_request_handler_t* self,
@@ -151,11 +152,11 @@
       struct _cef_response_t* response);
 
   ///
-  // Called on the IO thread to optionally filter resource response content. The
-  // |browser| and |frame| values represent the source of the request, and may
-  // be NULL for requests originating from service workers or cef_urlrequest_t.
-  // |request| and |response| represent the request and response respectively
-  // and cannot be modified in this callback.
+  /// Called on the IO thread to optionally filter resource response content.
+  /// The |browser| and |frame| values represent the source of the request, and
+  /// may be NULL for requests originating from service workers or
+  /// cef_urlrequest_t. |request| and |response| represent the request and
+  /// response respectively and cannot be modified in this callback.
   ///
   struct _cef_response_filter_t*(CEF_CALLBACK* get_resource_response_filter)(
       struct _cef_resource_request_handler_t* self,
@@ -165,20 +166,20 @@
       struct _cef_response_t* response);
 
   ///
-  // Called on the IO thread when a resource load has completed. The |browser|
-  // and |frame| values represent the source of the request, and may be NULL for
-  // requests originating from service workers or cef_urlrequest_t. |request|
-  // and |response| represent the request and response respectively and cannot
-  // be modified in this callback. |status| indicates the load completion
-  // status. |received_content_length| is the number of response bytes actually
-  // read. This function will be called for all requests, including requests
-  // that are aborted due to CEF shutdown or destruction of the associated
-  // browser. In cases where the associated browser is destroyed this callback
-  // may arrive after the cef_life_span_handler_t::OnBeforeClose callback for
-  // that browser. The cef_frame_t::IsValid function can be used to test for
-  // this situation, and care should be taken not to call |browser| or |frame|
-  // functions that modify state (like LoadURL, SendProcessMessage, etc.) if the
-  // frame is invalid.
+  /// Called on the IO thread when a resource load has completed. The |browser|
+  /// and |frame| values represent the source of the request, and may be NULL
+  /// for requests originating from service workers or cef_urlrequest_t.
+  /// |request| and |response| represent the request and response respectively
+  /// and cannot be modified in this callback. |status| indicates the load
+  /// completion status. |received_content_length| is the number of response
+  /// bytes actually read. This function will be called for all requests,
+  /// including requests that are aborted due to CEF shutdown or destruction of
+  /// the associated browser. In cases where the associated browser is destroyed
+  /// this callback may arrive after the cef_life_span_handler_t::OnBeforeClose
+  /// callback for that browser. The cef_frame_t::IsValid function can be used
+  /// to test for this situation, and care should be taken not to call |browser|
+  /// or |frame| functions that modify state (like LoadURL, SendProcessMessage,
+  /// etc.) if the frame is invalid.
   ///
   void(CEF_CALLBACK* on_resource_load_complete)(
       struct _cef_resource_request_handler_t* self,
@@ -187,17 +188,17 @@
       struct _cef_request_t* request,
       struct _cef_response_t* response,
       cef_urlrequest_status_t status,
-      int64 received_content_length);
+      int64_t received_content_length);
 
   ///
-  // Called on the IO thread to handle requests for URLs with an unknown
-  // protocol component. The |browser| and |frame| values represent the source
-  // of the request, and may be NULL for requests originating from service
-  // workers or cef_urlrequest_t. |request| cannot be modified in this callback.
-  // Set |allow_os_execution| to true (1) to attempt execution via the
-  // registered OS protocol handler, if any. SECURITY WARNING: YOU SHOULD USE
-  // THIS METHOD TO ENFORCE RESTRICTIONS BASED ON SCHEME, HOST OR OTHER URL
-  // ANALYSIS BEFORE ALLOWING OS EXECUTION.
+  /// Called on the IO thread to handle requests for URLs with an unknown
+  /// protocol component. The |browser| and |frame| values represent the source
+  /// of the request, and may be NULL for requests originating from service
+  /// workers or cef_urlrequest_t. |request| cannot be modified in this
+  /// callback. Set |allow_os_execution| to true (1) to attempt execution via
+  /// the registered OS protocol handler, if any. SECURITY WARNING: YOU SHOULD
+  /// USE THIS METHOD TO ENFORCE RESTRICTIONS BASED ON SCHEME, HOST OR OTHER URL
+  /// ANALYSIS BEFORE ALLOWING OS EXECUTION.
   ///
   void(CEF_CALLBACK* on_protocol_execution)(
       struct _cef_resource_request_handler_t* self,
@@ -208,22 +209,22 @@
 } cef_resource_request_handler_t;
 
 ///
-// Implement this structure to filter cookies that may be sent or received from
-// resource requests. The functions of this structure will be called on the IO
-// thread unless otherwise indicated.
+/// Implement this structure to filter cookies that may be sent or received from
+/// resource requests. The functions of this structure will be called on the IO
+/// thread unless otherwise indicated.
 ///
 typedef struct _cef_cookie_access_filter_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called on the IO thread before a resource request is sent. The |browser|
-  // and |frame| values represent the source of the request, and may be NULL for
-  // requests originating from service workers or cef_urlrequest_t. |request|
-  // cannot be modified in this callback. Return true (1) if the specified
-  // cookie can be sent with the request or false (0) otherwise.
+  /// Called on the IO thread before a resource request is sent. The |browser|
+  /// and |frame| values represent the source of the request, and may be NULL
+  /// for requests originating from service workers or cef_urlrequest_t.
+  /// |request| cannot be modified in this callback. Return true (1) if the
+  /// specified cookie can be sent with the request or false (0) otherwise.
   ///
   int(CEF_CALLBACK* can_send_cookie)(struct _cef_cookie_access_filter_t* self,
                                      struct _cef_browser_t* browser,
@@ -232,12 +233,12 @@
                                      const struct _cef_cookie_t* cookie);
 
   ///
-  // Called on the IO thread after a resource response is received. The
-  // |browser| and |frame| values represent the source of the request, and may
-  // be NULL for requests originating from service workers or cef_urlrequest_t.
-  // |request| cannot be modified in this callback. Return true (1) if the
-  // specified cookie returned with the response can be saved or false (0)
-  // otherwise.
+  /// Called on the IO thread after a resource response is received. The
+  /// |browser| and |frame| values represent the source of the request, and may
+  /// be NULL for requests originating from service workers or cef_urlrequest_t.
+  /// |request| cannot be modified in this callback. Return true (1) if the
+  /// specified cookie returned with the response can be saved or false (0)
+  /// otherwise.
   ///
   int(CEF_CALLBACK* can_save_cookie)(struct _cef_cookie_access_filter_t* self,
                                      struct _cef_browser_t* browser,
diff --git a/src/include/capi/cef_response_capi.h b/src/include/capi/cef_response_capi.h
index d7b0da4..d8c4b65 100644
--- a/src/include/capi/cef_response_capi.h
+++ b/src/include/capi/cef_response_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=2bccae35945ecea55c4c79bba840b44a691f1aa3$
+// $hash=7fbcd399c08dc39e33a7d0400a49f2e3a551bd02$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_RESPONSE_CAPI_H_
@@ -47,83 +47,83 @@
 #endif
 
 ///
-// Structure used to represent a web response. The functions of this structure
-// may be called on any thread.
+/// Structure used to represent a web response. The functions of this structure
+/// may be called on any thread.
 ///
 typedef struct _cef_response_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if this object is read-only.
+  /// Returns true (1) if this object is read-only.
   ///
   int(CEF_CALLBACK* is_read_only)(struct _cef_response_t* self);
 
   ///
-  // Get the response error code. Returns ERR_NONE if there was no error.
+  /// Get the response error code. Returns ERR_NONE if there was no error.
   ///
   cef_errorcode_t(CEF_CALLBACK* get_error)(struct _cef_response_t* self);
 
   ///
-  // Set the response error code. This can be used by custom scheme handlers to
-  // return errors during initial request processing.
+  /// Set the response error code. This can be used by custom scheme handlers to
+  /// return errors during initial request processing.
   ///
   void(CEF_CALLBACK* set_error)(struct _cef_response_t* self,
                                 cef_errorcode_t error);
 
   ///
-  // Get the response status code.
+  /// Get the response status code.
   ///
   int(CEF_CALLBACK* get_status)(struct _cef_response_t* self);
 
   ///
-  // Set the response status code.
+  /// Set the response status code.
   ///
   void(CEF_CALLBACK* set_status)(struct _cef_response_t* self, int status);
 
   ///
-  // Get the response status text.
+  /// Get the response status text.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_status_text)(
       struct _cef_response_t* self);
 
   ///
-  // Set the response status text.
+  /// Set the response status text.
   ///
   void(CEF_CALLBACK* set_status_text)(struct _cef_response_t* self,
                                       const cef_string_t* statusText);
 
   ///
-  // Get the response mime type.
+  /// Get the response mime type.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_mime_type)(
       struct _cef_response_t* self);
 
   ///
-  // Set the response mime type.
+  /// Set the response mime type.
   ///
   void(CEF_CALLBACK* set_mime_type)(struct _cef_response_t* self,
                                     const cef_string_t* mimeType);
 
   ///
-  // Get the response charset.
+  /// Get the response charset.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_charset)(
       struct _cef_response_t* self);
 
   ///
-  // Set the response charset.
+  /// Set the response charset.
   ///
   void(CEF_CALLBACK* set_charset)(struct _cef_response_t* self,
                                   const cef_string_t* charset);
 
   ///
-  // Get the value for the specified response header field.
+  /// Get the value for the specified response header field.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_header_by_name)(
@@ -131,9 +131,9 @@
       const cef_string_t* name);
 
   ///
-  // Set the header |name| to |value|. If |overwrite| is true (1) any existing
-  // values will be replaced with the new value. If |overwrite| is false (0) any
-  // existing values will not be overwritten.
+  /// Set the header |name| to |value|. If |overwrite| is true (1) any existing
+  /// values will be replaced with the new value. If |overwrite| is false (0)
+  /// any existing values will not be overwritten.
   ///
   void(CEF_CALLBACK* set_header_by_name)(struct _cef_response_t* self,
                                          const cef_string_t* name,
@@ -141,34 +141,34 @@
                                          int overwrite);
 
   ///
-  // Get all response header fields.
+  /// Get all response header fields.
   ///
   void(CEF_CALLBACK* get_header_map)(struct _cef_response_t* self,
                                      cef_string_multimap_t headerMap);
 
   ///
-  // Set all response header fields.
+  /// Set all response header fields.
   ///
   void(CEF_CALLBACK* set_header_map)(struct _cef_response_t* self,
                                      cef_string_multimap_t headerMap);
 
   ///
-  // Get the resolved URL after redirects or changed as a result of HSTS.
+  /// Get the resolved URL after redirects or changed as a result of HSTS.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_url)(struct _cef_response_t* self);
 
   ///
-  // Set the resolved URL after redirects or changed as a result of HSTS.
+  /// Set the resolved URL after redirects or changed as a result of HSTS.
   ///
   void(CEF_CALLBACK* set_url)(struct _cef_response_t* self,
                               const cef_string_t* url);
 } cef_response_t;
 
 ///
-// Create a new cef_response_t object.
+/// Create a new cef_response_t object.
 ///
-CEF_EXPORT cef_response_t* cef_response_create();
+CEF_EXPORT cef_response_t* cef_response_create(void);
 
 #ifdef __cplusplus
 }
diff --git a/src/include/capi/cef_response_filter_capi.h b/src/include/capi/cef_response_filter_capi.h
index fcb4f3a..c8a57de 100644
--- a/src/include/capi/cef_response_filter_capi.h
+++ b/src/include/capi/cef_response_filter_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=5b2602702a13a71ac012808eecb09bb8b9494551$
+// $hash=2c9b14a86ee6777e4834eadcfc95802f2dedb11a$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_RESPONSE_FILTER_CAPI_H_
@@ -47,51 +47,51 @@
 #endif
 
 ///
-// Implement this structure to filter resource response content. The functions
-// of this structure will be called on the browser process IO thread.
+/// Implement this structure to filter resource response content. The functions
+/// of this structure will be called on the browser process IO thread.
 ///
 typedef struct _cef_response_filter_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Initialize the response filter. Will only be called a single time. The
-  // filter will not be installed if this function returns false (0).
+  /// Initialize the response filter. Will only be called a single time. The
+  /// filter will not be installed if this function returns false (0).
   ///
   int(CEF_CALLBACK* init_filter)(struct _cef_response_filter_t* self);
 
   ///
-  // Called to filter a chunk of data. Expected usage is as follows:
-  //
-  //  A. Read input data from |data_in| and set |data_in_read| to the number of
-  //     bytes that were read up to a maximum of |data_in_size|. |data_in| will
-  //     be NULL if |data_in_size| is zero.
-  //  B. Write filtered output data to |data_out| and set |data_out_written| to
-  //     the number of bytes that were written up to a maximum of
-  //     |data_out_size|. If no output data was written then all data must be
-  //     read from |data_in| (user must set |data_in_read| = |data_in_size|).
-  //  C. Return RESPONSE_FILTER_DONE if all output data was written or
-  //     RESPONSE_FILTER_NEED_MORE_DATA if output data is still pending.
-  //
-  // This function will be called repeatedly until the input buffer has been
-  // fully read (user sets |data_in_read| = |data_in_size|) and there is no more
-  // input data to filter (the resource response is complete). This function may
-  // then be called an additional time with an NULL input buffer if the user
-  // filled the output buffer (set |data_out_written| = |data_out_size|) and
-  // returned RESPONSE_FILTER_NEED_MORE_DATA to indicate that output data is
-  // still pending.
-  //
-  // Calls to this function will stop when one of the following conditions is
-  // met:
-  //
-  //  A. There is no more input data to filter (the resource response is
-  //     complete) and the user sets |data_out_written| = 0 or returns
-  //     RESPONSE_FILTER_DONE to indicate that all data has been written, or;
-  //  B. The user returns RESPONSE_FILTER_ERROR to indicate an error.
-  //
-  // Do not keep a reference to the buffers passed to this function.
+  /// Called to filter a chunk of data. Expected usage is as follows:
+  ///
+  ///  1. Read input data from |data_in| and set |data_in_read| to the number of
+  ///     bytes that were read up to a maximum of |data_in_size|. |data_in| will
+  ///     be NULL if |data_in_size| is zero.
+  ///  2. Write filtered output data to |data_out| and set |data_out_written| to
+  ///     the number of bytes that were written up to a maximum of
+  ///     |data_out_size|. If no output data was written then all data must be
+  ///     read from |data_in| (user must set |data_in_read| = |data_in_size|).
+  ///  3. Return RESPONSE_FILTER_DONE if all output data was written or
+  ///     RESPONSE_FILTER_NEED_MORE_DATA if output data is still pending.
+  ///
+  /// This function will be called repeatedly until the input buffer has been
+  /// fully read (user sets |data_in_read| = |data_in_size|) and there is no
+  /// more input data to filter (the resource response is complete). This
+  /// function may then be called an additional time with an NULL input buffer
+  /// if the user filled the output buffer (set |data_out_written| =
+  /// |data_out_size|) and returned RESPONSE_FILTER_NEED_MORE_DATA to indicate
+  /// that output data is still pending.
+  ///
+  /// Calls to this function will stop when one of the following conditions is
+  /// met:
+  ///
+  ///  1. There is no more input data to filter (the resource response is
+  ///     complete) and the user sets |data_out_written| = 0 or returns
+  ///     RESPONSE_FILTER_DONE to indicate that all data has been written, or;
+  ///  2. The user returns RESPONSE_FILTER_ERROR to indicate an error.
+  ///
+  /// Do not keep a reference to the buffers passed to this function.
   ///
   cef_response_filter_status_t(CEF_CALLBACK* filter)(
       struct _cef_response_filter_t* self,
diff --git a/src/include/capi/cef_scheme_capi.h b/src/include/capi/cef_scheme_capi.h
index d288091..5f87962 100644
--- a/src/include/capi/cef_scheme_capi.h
+++ b/src/include/capi/cef_scheme_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=d93b4ad0b71ffe0a05326b39c3ed0bdb26a73fac$
+// $hash=6b6a7f754abc9ee5d6f775ba9eee802d3244faf5$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_SCHEME_CAPI_H_
@@ -54,23 +54,23 @@
 struct _cef_scheme_handler_factory_t;
 
 ///
-// Structure that manages custom scheme registrations.
+/// Structure that manages custom scheme registrations.
 ///
 typedef struct _cef_scheme_registrar_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_scoped_t base;
 
   ///
-  // Register a custom scheme. This function should not be called for the built-
-  // in HTTP, HTTPS, FILE, FTP, ABOUT and DATA schemes.
-  //
-  // See cef_scheme_options_t for possible values for |options|.
-  //
-  // This function may be called on any thread. It should only be called once
-  // per unique |scheme_name| value. If |scheme_name| is already registered or
-  // if an error occurs this function will return false (0).
+  /// Register a custom scheme. This function should not be called for the
+  /// built-in HTTP, HTTPS, FILE, FTP, ABOUT and DATA schemes.
+  ///
+  /// See cef_scheme_options_t for possible values for |options|.
+  ///
+  /// This function may be called on any thread. It should only be called once
+  /// per unique |scheme_name| value. If |scheme_name| is already registered or
+  /// if an error occurs this function will return false (0).
   ///
   int(CEF_CALLBACK* add_custom_scheme)(struct _cef_scheme_registrar_t* self,
                                        const cef_string_t* scheme_name,
@@ -78,23 +78,23 @@
 } cef_scheme_registrar_t;
 
 ///
-// Structure that creates cef_resource_handler_t instances for handling scheme
-// requests. The functions of this structure will always be called on the IO
-// thread.
+/// Structure that creates cef_resource_handler_t instances for handling scheme
+/// requests. The functions of this structure will always be called on the IO
+/// thread.
 ///
 typedef struct _cef_scheme_handler_factory_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Return a new resource handler instance to handle the request or an NULL
-  // reference to allow default handling of the request. |browser| and |frame|
-  // will be the browser window and frame respectively that originated the
-  // request or NULL if the request did not originate from a browser window (for
-  // example, if the request came from cef_urlrequest_t). The |request| object
-  // passed to this function cannot be modified.
+  /// Return a new resource handler instance to handle the request or an NULL
+  /// reference to allow default handling of the request. |browser| and |frame|
+  /// will be the browser window and frame respectively that originated the
+  /// request or NULL if the request did not originate from a browser window
+  /// (for example, if the request came from cef_urlrequest_t). The |request|
+  /// object passed to this function cannot be modified.
   ///
   struct _cef_resource_handler_t*(CEF_CALLBACK* create)(
       struct _cef_scheme_handler_factory_t* self,
@@ -105,19 +105,19 @@
 } cef_scheme_handler_factory_t;
 
 ///
-// Register a scheme handler factory with the global request context. An NULL
-// |domain_name| value for a standard scheme will cause the factory to match all
-// domain names. The |domain_name| value will be ignored for non-standard
-// schemes. If |scheme_name| is a built-in scheme and no handler is returned by
-// |factory| then the built-in scheme handler factory will be called. If
-// |scheme_name| is a custom scheme then you must also implement the
-// cef_app_t::on_register_custom_schemes() function in all processes. This
-// function may be called multiple times to change or remove the factory that
-// matches the specified |scheme_name| and optional |domain_name|. Returns false
-// (0) if an error occurs. This function may be called on any thread in the
-// browser process. Using this function is equivalent to calling cef_request_con
-// text_t::cef_request_context_get_global_context()->register_scheme_handler_fac
-// tory().
+/// Register a scheme handler factory with the global request context. An NULL
+/// |domain_name| value for a standard scheme will cause the factory to match
+/// all domain names. The |domain_name| value will be ignored for non-standard
+/// schemes. If |scheme_name| is a built-in scheme and no handler is returned by
+/// |factory| then the built-in scheme handler factory will be called. If
+/// |scheme_name| is a custom scheme then you must also implement the
+/// cef_app_t::on_register_custom_schemes() function in all processes. This
+/// function may be called multiple times to change or remove the factory that
+/// matches the specified |scheme_name| and optional |domain_name|. Returns
+/// false (0) if an error occurs. This function may be called on any thread in
+/// the browser process. Using this function is equivalent to calling cef_reques
+/// t_context_t::cef_request_context_get_global_context()->register_scheme_handl
+/// er_factory().
 ///
 CEF_EXPORT int cef_register_scheme_handler_factory(
     const cef_string_t* scheme_name,
@@ -125,13 +125,13 @@
     cef_scheme_handler_factory_t* factory);
 
 ///
-// Clear all scheme handler factories registered with the global request
-// context. Returns false (0) on error. This function may be called on any
-// thread in the browser process. Using this function is equivalent to calling c
-// ef_request_context_t::cef_request_context_get_global_context()->clear_scheme_
-// handler_factories().
+/// Clear all scheme handler factories registered with the global request
+/// context. Returns false (0) on error. This function may be called on any
+/// thread in the browser process. Using this function is equivalent to calling
+/// cef_request_context_t::cef_request_context_get_global_context()->clear_schem
+/// e_handler_factories().
 ///
-CEF_EXPORT int cef_clear_scheme_handler_factories();
+CEF_EXPORT int cef_clear_scheme_handler_factories(void);
 
 #ifdef __cplusplus
 }
diff --git a/src/include/capi/cef_server_capi.h b/src/include/capi/cef_server_capi.h
index 86571db..a0644c1 100644
--- a/src/include/capi/cef_server_capi.h
+++ b/src/include/capi/cef_server_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=ffd489adc301ed88e1f30f8f38cec1730411a4b5$
+// $hash=d0563a0850f6118c850ab01c553142d2e890703e$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_SERVER_CAPI_H_
@@ -52,64 +52,64 @@
 struct _cef_server_handler_t;
 
 ///
-// Structure representing a server that supports HTTP and WebSocket requests.
-// Server capacity is limited and is intended to handle only a small number of
-// simultaneous connections (e.g. for communicating between applications on
-// localhost). The functions of this structure are safe to call from any thread
-// in the brower process unless otherwise indicated.
+/// Structure representing a server that supports HTTP and WebSocket requests.
+/// Server capacity is limited and is intended to handle only a small number of
+/// simultaneous connections (e.g. for communicating between applications on
+/// localhost). The functions of this structure are safe to call from any thread
+/// in the brower process unless otherwise indicated.
 ///
 typedef struct _cef_server_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the task runner for the dedicated server thread.
+  /// Returns the task runner for the dedicated server thread.
   ///
   struct _cef_task_runner_t*(CEF_CALLBACK* get_task_runner)(
       struct _cef_server_t* self);
 
   ///
-  // Stop the server and shut down the dedicated server thread. See
-  // cef_server_handler_t::OnServerCreated documentation for a description of
-  // server lifespan.
+  /// Stop the server and shut down the dedicated server thread. See
+  /// cef_server_handler_t::OnServerCreated documentation for a description of
+  /// server lifespan.
   ///
   void(CEF_CALLBACK* shutdown)(struct _cef_server_t* self);
 
   ///
-  // Returns true (1) if the server is currently running and accepting incoming
-  // connections. See cef_server_handler_t::OnServerCreated documentation for a
-  // description of server lifespan. This function must be called on the
-  // dedicated server thread.
+  /// Returns true (1) if the server is currently running and accepting incoming
+  /// connections. See cef_server_handler_t::OnServerCreated documentation for a
+  /// description of server lifespan. This function must be called on the
+  /// dedicated server thread.
   ///
   int(CEF_CALLBACK* is_running)(struct _cef_server_t* self);
 
   ///
-  // Returns the server address including the port number.
+  /// Returns the server address including the port number.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_address)(struct _cef_server_t* self);
 
   ///
-  // Returns true (1) if the server currently has a connection. This function
-  // must be called on the dedicated server thread.
+  /// Returns true (1) if the server currently has a connection. This function
+  /// must be called on the dedicated server thread.
   ///
   int(CEF_CALLBACK* has_connection)(struct _cef_server_t* self);
 
   ///
-  // Returns true (1) if |connection_id| represents a valid connection. This
-  // function must be called on the dedicated server thread.
+  /// Returns true (1) if |connection_id| represents a valid connection. This
+  /// function must be called on the dedicated server thread.
   ///
   int(CEF_CALLBACK* is_valid_connection)(struct _cef_server_t* self,
                                          int connection_id);
 
   ///
-  // Send an HTTP 200 "OK" response to the connection identified by
-  // |connection_id|. |content_type| is the response content type (e.g.
-  // "text/html"), |data| is the response content, and |data_size| is the size
-  // of |data| in bytes. The contents of |data| will be copied. The connection
-  // will be closed automatically after the response is sent.
+  /// Send an HTTP 200 "OK" response to the connection identified by
+  /// |connection_id|. |content_type| is the response content type (e.g.
+  /// "text/html"), |data| is the response content, and |data_size| is the size
+  /// of |data| in bytes. The contents of |data| will be copied. The connection
+  /// will be closed automatically after the response is sent.
   ///
   void(CEF_CALLBACK* send_http200response)(struct _cef_server_t* self,
                                            int connection_id,
@@ -118,51 +118,51 @@
                                            size_t data_size);
 
   ///
-  // Send an HTTP 404 "Not Found" response to the connection identified by
-  // |connection_id|. The connection will be closed automatically after the
-  // response is sent.
+  /// Send an HTTP 404 "Not Found" response to the connection identified by
+  /// |connection_id|. The connection will be closed automatically after the
+  /// response is sent.
   ///
   void(CEF_CALLBACK* send_http404response)(struct _cef_server_t* self,
                                            int connection_id);
 
   ///
-  // Send an HTTP 500 "Internal Server Error" response to the connection
-  // identified by |connection_id|. |error_message| is the associated error
-  // message. The connection will be closed automatically after the response is
-  // sent.
+  /// Send an HTTP 500 "Internal Server Error" response to the connection
+  /// identified by |connection_id|. |error_message| is the associated error
+  /// message. The connection will be closed automatically after the response is
+  /// sent.
   ///
   void(CEF_CALLBACK* send_http500response)(struct _cef_server_t* self,
                                            int connection_id,
                                            const cef_string_t* error_message);
 
   ///
-  // Send a custom HTTP response to the connection identified by
-  // |connection_id|. |response_code| is the HTTP response code sent in the
-  // status line (e.g. 200), |content_type| is the response content type sent as
-  // the "Content-Type" header (e.g. "text/html"), |content_length| is the
-  // expected content length, and |extra_headers| is the map of extra response
-  // headers. If |content_length| is >= 0 then the "Content-Length" header will
-  // be sent. If |content_length| is 0 then no content is expected and the
-  // connection will be closed automatically after the response is sent. If
-  // |content_length| is < 0 then no "Content-Length" header will be sent and
-  // the client will continue reading until the connection is closed. Use the
-  // SendRawData function to send the content, if applicable, and call
-  // CloseConnection after all content has been sent.
+  /// Send a custom HTTP response to the connection identified by
+  /// |connection_id|. |response_code| is the HTTP response code sent in the
+  /// status line (e.g. 200), |content_type| is the response content type sent
+  /// as the "Content-Type" header (e.g. "text/html"), |content_length| is the
+  /// expected content length, and |extra_headers| is the map of extra response
+  /// headers. If |content_length| is >= 0 then the "Content-Length" header will
+  /// be sent. If |content_length| is 0 then no content is expected and the
+  /// connection will be closed automatically after the response is sent. If
+  /// |content_length| is < 0 then no "Content-Length" header will be sent and
+  /// the client will continue reading until the connection is closed. Use the
+  /// SendRawData function to send the content, if applicable, and call
+  /// CloseConnection after all content has been sent.
   ///
   void(CEF_CALLBACK* send_http_response)(struct _cef_server_t* self,
                                          int connection_id,
                                          int response_code,
                                          const cef_string_t* content_type,
-                                         int64 content_length,
+                                         int64_t content_length,
                                          cef_string_multimap_t extra_headers);
 
   ///
-  // Send raw data directly to the connection identified by |connection_id|.
-  // |data| is the raw data and |data_size| is the size of |data| in bytes. The
-  // contents of |data| will be copied. No validation of |data| is performed
-  // internally so the client should be careful to send the amount indicated by
-  // the "Content-Length" header, if specified. See SendHttpResponse
-  // documentation for intended usage.
+  /// Send raw data directly to the connection identified by |connection_id|.
+  /// |data| is the raw data and |data_size| is the size of |data| in bytes. The
+  /// contents of |data| will be copied. No validation of |data| is performed
+  /// internally so the client should be careful to send the amount indicated by
+  /// the "Content-Length" header, if specified. See SendHttpResponse
+  /// documentation for intended usage.
   ///
   void(CEF_CALLBACK* send_raw_data)(struct _cef_server_t* self,
                                     int connection_id,
@@ -170,17 +170,17 @@
                                     size_t data_size);
 
   ///
-  // Close the connection identified by |connection_id|. See SendHttpResponse
-  // documentation for intended usage.
+  /// Close the connection identified by |connection_id|. See SendHttpResponse
+  /// documentation for intended usage.
   ///
   void(CEF_CALLBACK* close_connection)(struct _cef_server_t* self,
                                        int connection_id);
 
   ///
-  // Send a WebSocket message to the connection identified by |connection_id|.
-  // |data| is the response content and |data_size| is the size of |data| in
-  // bytes. The contents of |data| will be copied. See
-  // cef_server_handler_t::OnWebSocketRequest documentation for intended usage.
+  /// Send a WebSocket message to the connection identified by |connection_id|.
+  /// |data| is the response content and |data_size| is the size of |data| in
+  /// bytes. The contents of |data| will be copied. See
+  /// cef_server_handler_t::OnWebSocketRequest documentation for intended usage.
   ///
   void(CEF_CALLBACK* send_web_socket_message)(struct _cef_server_t* self,
                                               int connection_id,
@@ -189,85 +189,86 @@
 } cef_server_t;
 
 ///
-// Create a new server that binds to |address| and |port|. |address| must be a
-// valid IPv4 or IPv6 address (e.g. 127.0.0.1 or ::1) and |port| must be a port
-// number outside of the reserved range (e.g. between 1025 and 65535 on most
-// platforms). |backlog| is the maximum number of pending connections. A new
-// thread will be created for each CreateServer call (the "dedicated server
-// thread"). It is therefore recommended to use a different cef_server_handler_t
-// instance for each CreateServer call to avoid thread safety issues in the
-// cef_server_handler_t implementation. The
-// cef_server_handler_t::OnServerCreated function will be called on the
-// dedicated server thread to report success or failure. See
-// cef_server_handler_t::OnServerCreated documentation for a description of
-// server lifespan.
+/// Create a new server that binds to |address| and |port|. |address| must be a
+/// valid IPv4 or IPv6 address (e.g. 127.0.0.1 or ::1) and |port| must be a port
+/// number outside of the reserved range (e.g. between 1025 and 65535 on most
+/// platforms). |backlog| is the maximum number of pending connections. A new
+/// thread will be created for each CreateServer call (the "dedicated server
+/// thread"). It is therefore recommended to use a different
+/// cef_server_handler_t instance for each CreateServer call to avoid thread
+/// safety issues in the cef_server_handler_t implementation. The
+/// cef_server_handler_t::OnServerCreated function will be called on the
+/// dedicated server thread to report success or failure. See
+/// cef_server_handler_t::OnServerCreated documentation for a description of
+/// server lifespan.
 ///
 CEF_EXPORT void cef_server_create(const cef_string_t* address,
-                                  uint16 port,
+                                  uint16_t port,
                                   int backlog,
                                   struct _cef_server_handler_t* handler);
 
 ///
-// Implement this structure to handle HTTP server requests. A new thread will be
-// created for each cef_server_t::CreateServer call (the "dedicated server
-// thread"), and the functions of this structure will be called on that thread.
-// It is therefore recommended to use a different cef_server_handler_t instance
-// for each cef_server_t::CreateServer call to avoid thread safety issues in the
-// cef_server_handler_t implementation.
+/// Implement this structure to handle HTTP server requests. A new thread will
+/// be created for each cef_server_t::CreateServer call (the "dedicated server
+/// thread"), and the functions of this structure will be called on that thread.
+/// It is therefore recommended to use a different cef_server_handler_t instance
+/// for each cef_server_t::CreateServer call to avoid thread safety issues in
+/// the cef_server_handler_t implementation.
 ///
 typedef struct _cef_server_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called when |server| is created. If the server was started successfully
-  // then cef_server_t::IsRunning will return true (1). The server will continue
-  // running until cef_server_t::Shutdown is called, after which time
-  // OnServerDestroyed will be called. If the server failed to start then
-  // OnServerDestroyed will be called immediately after this function returns.
+  /// Called when |server| is created. If the server was started successfully
+  /// then cef_server_t::IsRunning will return true (1). The server will
+  /// continue running until cef_server_t::Shutdown is called, after which time
+  /// OnServerDestroyed will be called. If the server failed to start then
+  /// OnServerDestroyed will be called immediately after this function returns.
   ///
   void(CEF_CALLBACK* on_server_created)(struct _cef_server_handler_t* self,
                                         struct _cef_server_t* server);
 
   ///
-  // Called when |server| is destroyed. The server thread will be stopped after
-  // this function returns. The client should release any references to |server|
-  // when this function is called. See OnServerCreated documentation for a
-  // description of server lifespan.
+  /// Called when |server| is destroyed. The server thread will be stopped after
+  /// this function returns. The client should release any references to
+  /// |server| when this function is called. See OnServerCreated documentation
+  /// for a description of server lifespan.
   ///
   void(CEF_CALLBACK* on_server_destroyed)(struct _cef_server_handler_t* self,
                                           struct _cef_server_t* server);
 
   ///
-  // Called when a client connects to |server|. |connection_id| uniquely
-  // identifies the connection. Each call to this function will have a matching
-  // call to OnClientDisconnected.
+  /// Called when a client connects to |server|. |connection_id| uniquely
+  /// identifies the connection. Each call to this function will have a matching
+  /// call to OnClientDisconnected.
   ///
   void(CEF_CALLBACK* on_client_connected)(struct _cef_server_handler_t* self,
                                           struct _cef_server_t* server,
                                           int connection_id);
 
   ///
-  // Called when a client disconnects from |server|. |connection_id| uniquely
-  // identifies the connection. The client should release any data associated
-  // with |connection_id| when this function is called and |connection_id|
-  // should no longer be passed to cef_server_t functions. Disconnects can
-  // originate from either the client or the server. For example, the server
-  // will disconnect automatically after a cef_server_t::SendHttpXXXResponse
-  // function is called.
+  /// Called when a client disconnects from |server|. |connection_id| uniquely
+  /// identifies the connection. The client should release any data associated
+  /// with |connection_id| when this function is called and |connection_id|
+  /// should no longer be passed to cef_server_t functions. Disconnects can
+  /// originate from either the client or the server. For example, the server
+  /// will disconnect automatically after a cef_server_t::SendHttpXXXResponse
+  /// function is called.
   ///
   void(CEF_CALLBACK* on_client_disconnected)(struct _cef_server_handler_t* self,
                                              struct _cef_server_t* server,
                                              int connection_id);
 
   ///
-  // Called when |server| receives an HTTP request. |connection_id| uniquely
-  // identifies the connection, |client_address| is the requesting IPv4 or IPv6
-  // client address including port number, and |request| contains the request
-  // contents (URL, function, headers and optional POST data). Call cef_server_t
-  // functions either synchronously or asynchronusly to send a response.
+  /// Called when |server| receives an HTTP request. |connection_id| uniquely
+  /// identifies the connection, |client_address| is the requesting IPv4 or IPv6
+  /// client address including port number, and |request| contains the request
+  /// contents (URL, function, headers and optional POST data). Call
+  /// cef_server_t functions either synchronously or asynchronusly to send a
+  /// response.
   ///
   void(CEF_CALLBACK* on_http_request)(struct _cef_server_handler_t* self,
                                       struct _cef_server_t* server,
@@ -276,18 +277,18 @@
                                       struct _cef_request_t* request);
 
   ///
-  // Called when |server| receives a WebSocket request. |connection_id| uniquely
-  // identifies the connection, |client_address| is the requesting IPv4 or IPv6
-  // client address including port number, and |request| contains the request
-  // contents (URL, function, headers and optional POST data). Execute
-  // |callback| either synchronously or asynchronously to accept or decline the
-  // WebSocket connection. If the request is accepted then OnWebSocketConnected
-  // will be called after the WebSocket has connected and incoming messages will
-  // be delivered to the OnWebSocketMessage callback. If the request is declined
-  // then the client will be disconnected and OnClientDisconnected will be
-  // called. Call the cef_server_t::SendWebSocketMessage function after
-  // receiving the OnWebSocketConnected callback to respond with WebSocket
-  // messages.
+  /// Called when |server| receives a WebSocket request. |connection_id|
+  /// uniquely identifies the connection, |client_address| is the requesting
+  /// IPv4 or IPv6 client address including port number, and |request| contains
+  /// the request contents (URL, function, headers and optional POST data).
+  /// Execute |callback| either synchronously or asynchronously to accept or
+  /// decline the WebSocket connection. If the request is accepted then
+  /// OnWebSocketConnected will be called after the WebSocket has connected and
+  /// incoming messages will be delivered to the OnWebSocketMessage callback. If
+  /// the request is declined then the client will be disconnected and
+  /// OnClientDisconnected will be called. Call the
+  /// cef_server_t::SendWebSocketMessage function after receiving the
+  /// OnWebSocketConnected callback to respond with WebSocket messages.
   ///
   void(CEF_CALLBACK* on_web_socket_request)(struct _cef_server_handler_t* self,
                                             struct _cef_server_t* server,
@@ -297,9 +298,9 @@
                                             struct _cef_callback_t* callback);
 
   ///
-  // Called after the client has accepted the WebSocket connection for |server|
-  // and |connection_id| via the OnWebSocketRequest callback. See
-  // OnWebSocketRequest documentation for intended usage.
+  /// Called after the client has accepted the WebSocket connection for |server|
+  /// and |connection_id| via the OnWebSocketRequest callback. See
+  /// OnWebSocketRequest documentation for intended usage.
   ///
   void(CEF_CALLBACK* on_web_socket_connected)(
       struct _cef_server_handler_t* self,
@@ -307,11 +308,11 @@
       int connection_id);
 
   ///
-  // Called when |server| receives an WebSocket message. |connection_id|
-  // uniquely identifies the connection, |data| is the message content and
-  // |data_size| is the size of |data| in bytes. Do not keep a reference to
-  // |data| outside of this function. See OnWebSocketRequest documentation for
-  // intended usage.
+  /// Called when |server| receives an WebSocket message. |connection_id|
+  /// uniquely identifies the connection, |data| is the message content and
+  /// |data_size| is the size of |data| in bytes. Do not keep a reference to
+  /// |data| outside of this function. See OnWebSocketRequest documentation for
+  /// intended usage.
   ///
   void(CEF_CALLBACK* on_web_socket_message)(struct _cef_server_handler_t* self,
                                             struct _cef_server_t* server,
diff --git a/src/include/capi/cef_request_callback_capi.h b/src/include/capi/cef_shared_memory_region_capi.h
similarity index 67%
copy from src/include/capi/cef_request_callback_capi.h
copy to src/include/capi/cef_shared_memory_region_capi.h
index 36316e9..fbc1312 100644
--- a/src/include/capi/cef_request_callback_capi.h
+++ b/src/include/capi/cef_shared_memory_region_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,11 +33,11 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=3efd81a4bfdfca579a77f14bd37b8192122ebda4$
+// $hash=dfa2f2d57339e05592d7ee5f4c4c54dd0932cd94$
 //
 
-#ifndef CEF_INCLUDE_CAPI_CEF_REQUEST_CALLBACK_CAPI_H_
-#define CEF_INCLUDE_CAPI_CEF_REQUEST_CALLBACK_CAPI_H_
+#ifndef CEF_INCLUDE_CAPI_CEF_SHARED_MEMORY_REGION_CAPI_H_
+#define CEF_INCLUDE_CAPI_CEF_SHARED_MEMORY_REGION_CAPI_H_
 #pragma once
 
 #include "include/capi/cef_base_capi.h"
@@ -47,28 +47,33 @@
 #endif
 
 ///
-// Callback structure used for asynchronous continuation of url requests.
+/// Structure that wraps platform-dependent share memory region mapping.
 ///
-typedef struct _cef_request_callback_t {
+typedef struct _cef_shared_memory_region_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Continue the url request. If |allow| is true (1) the request will be
-  // continued. Otherwise, the request will be canceled.
+  /// Returns true (1) if the mapping is valid.
   ///
-  void(CEF_CALLBACK* cont)(struct _cef_request_callback_t* self, int allow);
+  int(CEF_CALLBACK* is_valid)(struct _cef_shared_memory_region_t* self);
 
   ///
-  // Cancel the url request.
+  /// Returns the size of the mapping in bytes. Returns 0 for invalid instances.
   ///
-  void(CEF_CALLBACK* cancel)(struct _cef_request_callback_t* self);
-} cef_request_callback_t;
+  size_t(CEF_CALLBACK* size)(struct _cef_shared_memory_region_t* self);
+
+  ///
+  /// Returns the pointer to the memory. Returns nullptr for invalid instances.
+  /// The returned pointer is only valid for the life span of this object.
+  ///
+  void*(CEF_CALLBACK* memory)(struct _cef_shared_memory_region_t* self);
+} cef_shared_memory_region_t;
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif  // CEF_INCLUDE_CAPI_CEF_REQUEST_CALLBACK_CAPI_H_
+#endif  // CEF_INCLUDE_CAPI_CEF_SHARED_MEMORY_REGION_CAPI_H_
diff --git a/src/include/capi/cef_shared_process_message_builder_capi.h b/src/include/capi/cef_shared_process_message_builder_capi.h
new file mode 100644
index 0000000..1b57064
--- /dev/null
+++ b/src/include/capi/cef_shared_process_message_builder_capi.h
@@ -0,0 +1,101 @@
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool and should not edited
+// by hand. See the translator.README.txt file in the tools directory for
+// more information.
+//
+// $hash=1a2d8806256d04362f181350db2835850cb3e0ae$
+//
+
+#ifndef CEF_INCLUDE_CAPI_CEF_SHARED_PROCESS_MESSAGE_BUILDER_CAPI_H_
+#define CEF_INCLUDE_CAPI_CEF_SHARED_PROCESS_MESSAGE_BUILDER_CAPI_H_
+#pragma once
+
+#include "include/capi/cef_process_message_capi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///
+/// Structure that builds a cef_process_message_t containing a shared memory
+/// region. This structure is not thread-safe but may be used exclusively on a
+/// different thread from the one which constructed it.
+///
+typedef struct _cef_shared_process_message_builder_t {
+  ///
+  /// Base structure.
+  ///
+  cef_base_ref_counted_t base;
+
+  ///
+  /// Returns true (1) if the builder is valid.
+  ///
+  int(CEF_CALLBACK* is_valid)(
+      struct _cef_shared_process_message_builder_t* self);
+
+  ///
+  /// Returns the size of the shared memory region in bytes. Returns 0 for
+  /// invalid instances.
+  ///
+  size_t(CEF_CALLBACK* size)(
+      struct _cef_shared_process_message_builder_t* self);
+
+  ///
+  /// Returns the pointer to the writable memory. Returns nullptr for invalid
+  /// instances. The returned pointer is only valid for the life span of this
+  /// object.
+  ///
+  void*(CEF_CALLBACK* memory)(
+      struct _cef_shared_process_message_builder_t* self);
+
+  ///
+  /// Creates a new cef_process_message_t from the data provided to the builder.
+  /// Returns nullptr for invalid instances. Invalidates the builder instance.
+  ///
+  struct _cef_process_message_t*(CEF_CALLBACK* build)(
+      struct _cef_shared_process_message_builder_t* self);
+} cef_shared_process_message_builder_t;
+
+///
+/// Creates a new cef_shared_process_message_builder_t with the specified |name|
+/// and shared memory region of specified |byte_size|.
+///
+CEF_EXPORT cef_shared_process_message_builder_t*
+cef_shared_process_message_builder_create(const cef_string_t* name,
+                                          size_t byte_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // CEF_INCLUDE_CAPI_CEF_SHARED_PROCESS_MESSAGE_BUILDER_CAPI_H_
diff --git a/src/include/capi/cef_ssl_info_capi.h b/src/include/capi/cef_ssl_info_capi.h
index da83e0b..54b2009 100644
--- a/src/include/capi/cef_ssl_info_capi.h
+++ b/src/include/capi/cef_ssl_info_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=badaadcff4641fea876fb626b8ffe5a6f34a376c$
+// $hash=99dff3042ea437ecf5771eff9b3cab4c22190534$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_SSL_INFO_CAPI_H_
@@ -49,29 +49,29 @@
 #endif
 
 ///
-// Structure representing SSL information.
+/// Structure representing SSL information.
 ///
 typedef struct _cef_sslinfo_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns a bitmask containing any and all problems verifying the server
-  // certificate.
+  /// Returns a bitmask containing any and all problems verifying the server
+  /// certificate.
   ///
   cef_cert_status_t(CEF_CALLBACK* get_cert_status)(struct _cef_sslinfo_t* self);
 
   ///
-  // Returns the X.509 certificate.
+  /// Returns the X.509 certificate.
   ///
   struct _cef_x509certificate_t*(CEF_CALLBACK* get_x509certificate)(
       struct _cef_sslinfo_t* self);
 } cef_sslinfo_t;
 
 ///
-// Returns true (1) if the certificate status represents an error.
+/// Returns true (1) if the certificate status represents an error.
 ///
 CEF_EXPORT int cef_is_cert_status_error(cef_cert_status_t status);
 
diff --git a/src/include/capi/cef_ssl_status_capi.h b/src/include/capi/cef_ssl_status_capi.h
index df49ac9..0c6c4b7 100644
--- a/src/include/capi/cef_ssl_status_capi.h
+++ b/src/include/capi/cef_ssl_status_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=3755121a7b89de52a67885ac1c6d12de23f4b657$
+// $hash=034a68aa4901cde95e12a7900cfc65753fbde345$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_SSL_STATUS_CAPI_H_
@@ -49,40 +49,40 @@
 #endif
 
 ///
-// Structure representing the SSL information for a navigation entry.
+/// Structure representing the SSL information for a navigation entry.
 ///
 typedef struct _cef_sslstatus_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if the status is related to a secure SSL/TLS connection.
+  /// Returns true (1) if the status is related to a secure SSL/TLS connection.
   ///
   int(CEF_CALLBACK* is_secure_connection)(struct _cef_sslstatus_t* self);
 
   ///
-  // Returns a bitmask containing any and all problems verifying the server
-  // certificate.
+  /// Returns a bitmask containing any and all problems verifying the server
+  /// certificate.
   ///
   cef_cert_status_t(CEF_CALLBACK* get_cert_status)(
       struct _cef_sslstatus_t* self);
 
   ///
-  // Returns the SSL version used for the SSL connection.
+  /// Returns the SSL version used for the SSL connection.
   ///
   cef_ssl_version_t(CEF_CALLBACK* get_sslversion)(
       struct _cef_sslstatus_t* self);
 
   ///
-  // Returns a bitmask containing the page security content status.
+  /// Returns a bitmask containing the page security content status.
   ///
   cef_ssl_content_status_t(CEF_CALLBACK* get_content_status)(
       struct _cef_sslstatus_t* self);
 
   ///
-  // Returns the X.509 certificate.
+  /// Returns the X.509 certificate.
   ///
   struct _cef_x509certificate_t*(CEF_CALLBACK* get_x509certificate)(
       struct _cef_sslstatus_t* self);
diff --git a/src/include/capi/cef_stream_capi.h b/src/include/capi/cef_stream_capi.h
index d1f779d..e3cd57b 100644
--- a/src/include/capi/cef_stream_capi.h
+++ b/src/include/capi/cef_stream_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=bd5bbcdc385f83512bf64304e180f1a05b765c16$
+// $hash=5632e62f83aac60e62db9d7f308563fed3285c65$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_STREAM_CAPI_H_
@@ -47,17 +47,17 @@
 #endif
 
 ///
-// Structure the client can implement to provide a custom stream reader. The
-// functions of this structure may be called on any thread.
+/// Structure the client can implement to provide a custom stream reader. The
+/// functions of this structure may be called on any thread.
 ///
 typedef struct _cef_read_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Read raw binary data.
+  /// Read raw binary data.
   ///
   size_t(CEF_CALLBACK* read)(struct _cef_read_handler_t* self,
                              void* ptr,
@@ -65,43 +65,44 @@
                              size_t n);
 
   ///
-  // Seek to the specified offset position. |whence| may be any one of SEEK_CUR,
-  // SEEK_END or SEEK_SET. Return zero on success and non-zero on failure.
+  /// Seek to the specified offset position. |whence| may be any one of
+  /// SEEK_CUR, SEEK_END or SEEK_SET. Return zero on success and non-zero on
+  /// failure.
   ///
   int(CEF_CALLBACK* seek)(struct _cef_read_handler_t* self,
-                          int64 offset,
+                          int64_t offset,
                           int whence);
 
   ///
-  // Return the current offset position.
+  /// Return the current offset position.
   ///
-  int64(CEF_CALLBACK* tell)(struct _cef_read_handler_t* self);
+  int64_t(CEF_CALLBACK* tell)(struct _cef_read_handler_t* self);
 
   ///
-  // Return non-zero if at end of file.
+  /// Return non-zero if at end of file.
   ///
   int(CEF_CALLBACK* eof)(struct _cef_read_handler_t* self);
 
   ///
-  // Return true (1) if this handler performs work like accessing the file
-  // system which may block. Used as a hint for determining the thread to access
-  // the handler from.
+  /// Return true (1) if this handler performs work like accessing the file
+  /// system which may block. Used as a hint for determining the thread to
+  /// access the handler from.
   ///
   int(CEF_CALLBACK* may_block)(struct _cef_read_handler_t* self);
 } cef_read_handler_t;
 
 ///
-// Structure used to read data from a stream. The functions of this structure
-// may be called on any thread.
+/// Structure used to read data from a stream. The functions of this structure
+/// may be called on any thread.
 ///
 typedef struct _cef_stream_reader_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Read raw binary data.
+  /// Read raw binary data.
   ///
   size_t(CEF_CALLBACK* read)(struct _cef_stream_reader_t* self,
                              void* ptr,
@@ -109,61 +110,62 @@
                              size_t n);
 
   ///
-  // Seek to the specified offset position. |whence| may be any one of SEEK_CUR,
-  // SEEK_END or SEEK_SET. Returns zero on success and non-zero on failure.
+  /// Seek to the specified offset position. |whence| may be any one of
+  /// SEEK_CUR, SEEK_END or SEEK_SET. Returns zero on success and non-zero on
+  /// failure.
   ///
   int(CEF_CALLBACK* seek)(struct _cef_stream_reader_t* self,
-                          int64 offset,
+                          int64_t offset,
                           int whence);
 
   ///
-  // Return the current offset position.
+  /// Return the current offset position.
   ///
-  int64(CEF_CALLBACK* tell)(struct _cef_stream_reader_t* self);
+  int64_t(CEF_CALLBACK* tell)(struct _cef_stream_reader_t* self);
 
   ///
-  // Return non-zero if at end of file.
+  /// Return non-zero if at end of file.
   ///
   int(CEF_CALLBACK* eof)(struct _cef_stream_reader_t* self);
 
   ///
-  // Returns true (1) if this reader performs work like accessing the file
-  // system which may block. Used as a hint for determining the thread to access
-  // the reader from.
+  /// Returns true (1) if this reader performs work like accessing the file
+  /// system which may block. Used as a hint for determining the thread to
+  /// access the reader from.
   ///
   int(CEF_CALLBACK* may_block)(struct _cef_stream_reader_t* self);
 } cef_stream_reader_t;
 
 ///
-// Create a new cef_stream_reader_t object from a file.
+/// Create a new cef_stream_reader_t object from a file.
 ///
 CEF_EXPORT cef_stream_reader_t* cef_stream_reader_create_for_file(
     const cef_string_t* fileName);
 
 ///
-// Create a new cef_stream_reader_t object from data.
+/// Create a new cef_stream_reader_t object from data.
 ///
 CEF_EXPORT cef_stream_reader_t* cef_stream_reader_create_for_data(void* data,
                                                                   size_t size);
 
 ///
-// Create a new cef_stream_reader_t object from a custom handler.
+/// Create a new cef_stream_reader_t object from a custom handler.
 ///
 CEF_EXPORT cef_stream_reader_t* cef_stream_reader_create_for_handler(
     cef_read_handler_t* handler);
 
 ///
-// Structure the client can implement to provide a custom stream writer. The
-// functions of this structure may be called on any thread.
+/// Structure the client can implement to provide a custom stream writer. The
+/// functions of this structure may be called on any thread.
 ///
 typedef struct _cef_write_handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Write raw binary data.
+  /// Write raw binary data.
   ///
   size_t(CEF_CALLBACK* write)(struct _cef_write_handler_t* self,
                               const void* ptr,
@@ -171,43 +173,44 @@
                               size_t n);
 
   ///
-  // Seek to the specified offset position. |whence| may be any one of SEEK_CUR,
-  // SEEK_END or SEEK_SET. Return zero on success and non-zero on failure.
+  /// Seek to the specified offset position. |whence| may be any one of
+  /// SEEK_CUR, SEEK_END or SEEK_SET. Return zero on success and non-zero on
+  /// failure.
   ///
   int(CEF_CALLBACK* seek)(struct _cef_write_handler_t* self,
-                          int64 offset,
+                          int64_t offset,
                           int whence);
 
   ///
-  // Return the current offset position.
+  /// Return the current offset position.
   ///
-  int64(CEF_CALLBACK* tell)(struct _cef_write_handler_t* self);
+  int64_t(CEF_CALLBACK* tell)(struct _cef_write_handler_t* self);
 
   ///
-  // Flush the stream.
+  /// Flush the stream.
   ///
   int(CEF_CALLBACK* flush)(struct _cef_write_handler_t* self);
 
   ///
-  // Return true (1) if this handler performs work like accessing the file
-  // system which may block. Used as a hint for determining the thread to access
-  // the handler from.
+  /// Return true (1) if this handler performs work like accessing the file
+  /// system which may block. Used as a hint for determining the thread to
+  /// access the handler from.
   ///
   int(CEF_CALLBACK* may_block)(struct _cef_write_handler_t* self);
 } cef_write_handler_t;
 
 ///
-// Structure used to write data to a stream. The functions of this structure may
-// be called on any thread.
+/// Structure used to write data to a stream. The functions of this structure
+/// may be called on any thread.
 ///
 typedef struct _cef_stream_writer_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Write raw binary data.
+  /// Write raw binary data.
   ///
   size_t(CEF_CALLBACK* write)(struct _cef_stream_writer_t* self,
                               const void* ptr,
@@ -215,39 +218,40 @@
                               size_t n);
 
   ///
-  // Seek to the specified offset position. |whence| may be any one of SEEK_CUR,
-  // SEEK_END or SEEK_SET. Returns zero on success and non-zero on failure.
+  /// Seek to the specified offset position. |whence| may be any one of
+  /// SEEK_CUR, SEEK_END or SEEK_SET. Returns zero on success and non-zero on
+  /// failure.
   ///
   int(CEF_CALLBACK* seek)(struct _cef_stream_writer_t* self,
-                          int64 offset,
+                          int64_t offset,
                           int whence);
 
   ///
-  // Return the current offset position.
+  /// Return the current offset position.
   ///
-  int64(CEF_CALLBACK* tell)(struct _cef_stream_writer_t* self);
+  int64_t(CEF_CALLBACK* tell)(struct _cef_stream_writer_t* self);
 
   ///
-  // Flush the stream.
+  /// Flush the stream.
   ///
   int(CEF_CALLBACK* flush)(struct _cef_stream_writer_t* self);
 
   ///
-  // Returns true (1) if this writer performs work like accessing the file
-  // system which may block. Used as a hint for determining the thread to access
-  // the writer from.
+  /// Returns true (1) if this writer performs work like accessing the file
+  /// system which may block. Used as a hint for determining the thread to
+  /// access the writer from.
   ///
   int(CEF_CALLBACK* may_block)(struct _cef_stream_writer_t* self);
 } cef_stream_writer_t;
 
 ///
-// Create a new cef_stream_writer_t object for a file.
+/// Create a new cef_stream_writer_t object for a file.
 ///
 CEF_EXPORT cef_stream_writer_t* cef_stream_writer_create_for_file(
     const cef_string_t* fileName);
 
 ///
-// Create a new cef_stream_writer_t object for a custom handler.
+/// Create a new cef_stream_writer_t object for a custom handler.
 ///
 CEF_EXPORT cef_stream_writer_t* cef_stream_writer_create_for_handler(
     cef_write_handler_t* handler);
diff --git a/src/include/capi/cef_string_visitor_capi.h b/src/include/capi/cef_string_visitor_capi.h
index 0a7ba35..5ea9b38 100644
--- a/src/include/capi/cef_string_visitor_capi.h
+++ b/src/include/capi/cef_string_visitor_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=bba3a9719860f9a81c63cbb052a4c501416b2ada$
+// $hash=6a22e5144c0254acb09656e6e41eedd05f2dd7e7$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_STRING_VISITOR_CAPI_H_
@@ -47,16 +47,16 @@
 #endif
 
 ///
-// Implement this structure to receive string values asynchronously.
+/// Implement this structure to receive string values asynchronously.
 ///
 typedef struct _cef_string_visitor_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Method that will be executed.
+  /// Method that will be executed.
   ///
   void(CEF_CALLBACK* visit)(struct _cef_string_visitor_t* self,
                             const cef_string_t* string);
diff --git a/src/include/capi/cef_task_capi.h b/src/include/capi/cef_task_capi.h
index c52a549..dbe5f44 100644
--- a/src/include/capi/cef_task_capi.h
+++ b/src/include/capi/cef_task_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=025daa5db3bf16029953da7703e3e5968bd97fe2$
+// $hash=fc609ce5aa3bc51e5cef1f9174dbfc5cff0a0689$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_TASK_CAPI_H_
@@ -47,109 +47,109 @@
 #endif
 
 ///
-// Implement this structure for asynchronous task execution. If the task is
-// posted successfully and if the associated message loop is still running then
-// the execute() function will be called on the target thread. If the task fails
-// to post then the task object may be destroyed on the source thread instead of
-// the target thread. For this reason be cautious when performing work in the
-// task object destructor.
+/// Implement this structure for asynchronous task execution. If the task is
+/// posted successfully and if the associated message loop is still running then
+/// the execute() function will be called on the target thread. If the task
+/// fails to post then the task object may be destroyed on the source thread
+/// instead of the target thread. For this reason be cautious when performing
+/// work in the task object destructor.
 ///
 typedef struct _cef_task_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Method that will be executed on the target thread.
+  /// Method that will be executed on the target thread.
   ///
   void(CEF_CALLBACK* execute)(struct _cef_task_t* self);
 } cef_task_t;
 
 ///
-// Structure that asynchronously executes tasks on the associated thread. It is
-// safe to call the functions of this structure on any thread.
-//
-// CEF maintains multiple internal threads that are used for handling different
-// types of tasks in different processes. The cef_thread_id_t definitions in
-// cef_types.h list the common CEF threads. Task runners are also available for
-// other CEF threads as appropriate (for example, V8 WebWorker threads).
+/// Structure that asynchronously executes tasks on the associated thread. It is
+/// safe to call the functions of this structure on any thread.
+///
+/// CEF maintains multiple internal threads that are used for handling different
+/// types of tasks in different processes. The cef_thread_id_t definitions in
+/// cef_types.h list the common CEF threads. Task runners are also available for
+/// other CEF threads as appropriate (for example, V8 WebWorker threads).
 ///
 typedef struct _cef_task_runner_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if this object is pointing to the same task runner as
-  // |that| object.
+  /// Returns true (1) if this object is pointing to the same task runner as
+  /// |that| object.
   ///
   int(CEF_CALLBACK* is_same)(struct _cef_task_runner_t* self,
                              struct _cef_task_runner_t* that);
 
   ///
-  // Returns true (1) if this task runner belongs to the current thread.
+  /// Returns true (1) if this task runner belongs to the current thread.
   ///
   int(CEF_CALLBACK* belongs_to_current_thread)(struct _cef_task_runner_t* self);
 
   ///
-  // Returns true (1) if this task runner is for the specified CEF thread.
+  /// Returns true (1) if this task runner is for the specified CEF thread.
   ///
   int(CEF_CALLBACK* belongs_to_thread)(struct _cef_task_runner_t* self,
                                        cef_thread_id_t threadId);
 
   ///
-  // Post a task for execution on the thread associated with this task runner.
-  // Execution will occur asynchronously.
+  /// Post a task for execution on the thread associated with this task runner.
+  /// Execution will occur asynchronously.
   ///
   int(CEF_CALLBACK* post_task)(struct _cef_task_runner_t* self,
                                struct _cef_task_t* task);
 
   ///
-  // Post a task for delayed execution on the thread associated with this task
-  // runner. Execution will occur asynchronously. Delayed tasks are not
-  // supported on V8 WebWorker threads and will be executed without the
-  // specified delay.
+  /// Post a task for delayed execution on the thread associated with this task
+  /// runner. Execution will occur asynchronously. Delayed tasks are not
+  /// supported on V8 WebWorker threads and will be executed without the
+  /// specified delay.
   ///
   int(CEF_CALLBACK* post_delayed_task)(struct _cef_task_runner_t* self,
                                        struct _cef_task_t* task,
-                                       int64 delay_ms);
+                                       int64_t delay_ms);
 } cef_task_runner_t;
 
 ///
-// Returns the task runner for the current thread. Only CEF threads will have
-// task runners. An NULL reference will be returned if this function is called
-// on an invalid thread.
+/// Returns the task runner for the current thread. Only CEF threads will have
+/// task runners. An NULL reference will be returned if this function is called
+/// on an invalid thread.
 ///
-CEF_EXPORT cef_task_runner_t* cef_task_runner_get_for_current_thread();
+CEF_EXPORT cef_task_runner_t* cef_task_runner_get_for_current_thread(void);
 
 ///
-// Returns the task runner for the specified CEF thread.
+/// Returns the task runner for the specified CEF thread.
 ///
 CEF_EXPORT cef_task_runner_t* cef_task_runner_get_for_thread(
     cef_thread_id_t threadId);
 
 ///
-// Returns true (1) if called on the specified thread. Equivalent to using
-// cef_task_runner_t::GetForThread(threadId)->belongs_to_current_thread().
+/// Returns true (1) if called on the specified thread. Equivalent to using
+/// cef_task_runner_t::GetForThread(threadId)->belongs_to_current_thread().
 ///
 CEF_EXPORT int cef_currently_on(cef_thread_id_t threadId);
 
 ///
-// Post a task for execution on the specified thread. Equivalent to using
-// cef_task_runner_t::GetForThread(threadId)->PostTask(task).
+/// Post a task for execution on the specified thread. Equivalent to using
+/// cef_task_runner_t::GetForThread(threadId)->PostTask(task).
 ///
 CEF_EXPORT int cef_post_task(cef_thread_id_t threadId, cef_task_t* task);
 
 ///
-// Post a task for delayed execution on the specified thread. Equivalent to
-// using cef_task_runner_t::GetForThread(threadId)->PostDelayedTask(task,
-// delay_ms).
+/// Post a task for delayed execution on the specified thread. Equivalent to
+/// using cef_task_runner_t::GetForThread(threadId)->PostDelayedTask(task,
+/// delay_ms).
 ///
 CEF_EXPORT int cef_post_delayed_task(cef_thread_id_t threadId,
                                      cef_task_t* task,
-                                     int64 delay_ms);
+                                     int64_t delay_ms);
 
 #ifdef __cplusplus
 }
diff --git a/src/include/capi/cef_thread_capi.h b/src/include/capi/cef_thread_capi.h
index 1a9e9a3..adfb79a 100644
--- a/src/include/capi/cef_thread_capi.h
+++ b/src/include/capi/cef_thread_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=370cdeaa3252a9ed0e1a627d858dcab23af24ee1$
+// $hash=b111114b291d3b91c526e6b3da5741959469ec4a$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_THREAD_CAPI_H_
@@ -48,60 +48,60 @@
 #endif
 
 ///
-// A simple thread abstraction that establishes a message loop on a new thread.
-// The consumer uses cef_task_runner_t to execute code on the thread's message
-// loop. The thread is terminated when the cef_thread_t object is destroyed or
-// stop() is called. All pending tasks queued on the thread's message loop will
-// run to completion before the thread is terminated. cef_thread_create() can be
-// called on any valid CEF thread in either the browser or render process. This
-// structure should only be used for tasks that require a dedicated thread. In
-// most cases you can post tasks to an existing CEF thread instead of creating a
-// new one; see cef_task.h for details.
+/// A simple thread abstraction that establishes a message loop on a new thread.
+/// The consumer uses cef_task_runner_t to execute code on the thread's message
+/// loop. The thread is terminated when the cef_thread_t object is destroyed or
+/// stop() is called. All pending tasks queued on the thread's message loop will
+/// run to completion before the thread is terminated. cef_thread_create() can
+/// be called on any valid CEF thread in either the browser or render process.
+/// This structure should only be used for tasks that require a dedicated
+/// thread. In most cases you can post tasks to an existing CEF thread instead
+/// of creating a new one; see cef_task.h for details.
 ///
 typedef struct _cef_thread_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the cef_task_runner_t that will execute code on this thread's
-  // message loop. This function is safe to call from any thread.
+  /// Returns the cef_task_runner_t that will execute code on this thread's
+  /// message loop. This function is safe to call from any thread.
   ///
   struct _cef_task_runner_t*(CEF_CALLBACK* get_task_runner)(
       struct _cef_thread_t* self);
 
   ///
-  // Returns the platform thread ID. It will return the same value after stop()
-  // is called. This function is safe to call from any thread.
+  /// Returns the platform thread ID. It will return the same value after stop()
+  /// is called. This function is safe to call from any thread.
   ///
   cef_platform_thread_id_t(CEF_CALLBACK* get_platform_thread_id)(
       struct _cef_thread_t* self);
 
   ///
-  // Stop and join the thread. This function must be called from the same thread
-  // that called cef_thread_create(). Do not call this function if
-  // cef_thread_create() was called with a |stoppable| value of false (0).
+  /// Stop and join the thread. This function must be called from the same
+  /// thread that called cef_thread_create(). Do not call this function if
+  /// cef_thread_create() was called with a |stoppable| value of false (0).
   ///
   void(CEF_CALLBACK* stop)(struct _cef_thread_t* self);
 
   ///
-  // Returns true (1) if the thread is currently running. This function must be
-  // called from the same thread that called cef_thread_create().
+  /// Returns true (1) if the thread is currently running. This function must be
+  /// called from the same thread that called cef_thread_create().
   ///
   int(CEF_CALLBACK* is_running)(struct _cef_thread_t* self);
 } cef_thread_t;
 
 ///
-// Create and start a new thread. This function does not block waiting for the
-// thread to run initialization. |display_name| is the name that will be used to
-// identify the thread. |priority| is the thread execution priority.
-// |message_loop_type| indicates the set of asynchronous events that the thread
-// can process. If |stoppable| is true (1) the thread will stopped and joined on
-// destruction or when stop() is called; otherwise, the the thread cannot be
-// stopped and will be leaked on shutdown. On Windows the |com_init_mode| value
-// specifies how COM will be initialized for the thread. If |com_init_mode| is
-// set to COM_INIT_MODE_STA then |message_loop_type| must be set to ML_TYPE_UI.
+/// Create and start a new thread. This function does not block waiting for the
+/// thread to run initialization. |display_name| is the name that will be used
+/// to identify the thread. |priority| is the thread execution priority.
+/// |message_loop_type| indicates the set of asynchronous events that the thread
+/// can process. If |stoppable| is true (1) the thread will stopped and joined
+/// on destruction or when stop() is called; otherwise, the thread cannot be
+/// stopped and will be leaked on shutdown. On Windows the |com_init_mode| value
+/// specifies how COM will be initialized for the thread. If |com_init_mode| is
+/// set to COM_INIT_MODE_STA then |message_loop_type| must be set to ML_TYPE_UI.
 ///
 CEF_EXPORT cef_thread_t* cef_thread_create(
     const cef_string_t* display_name,
diff --git a/src/include/capi/cef_trace_capi.h b/src/include/capi/cef_trace_capi.h
index 336e08b..7c3645d 100644
--- a/src/include/capi/cef_trace_capi.h
+++ b/src/include/capi/cef_trace_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=b1b96b7cb636afbd201b88bc1544afc58099c0b6$
+// $hash=28e2d2d86dffdfdad0f275a444656a0638b44d0e$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_TRACE_CAPI_H_
@@ -48,20 +48,20 @@
 #endif
 
 ///
-// Implement this structure to receive notification when tracing has completed.
-// The functions of this structure will be called on the browser process UI
-// thread.
+/// Implement this structure to receive notification when tracing has completed.
+/// The functions of this structure will be called on the browser process UI
+/// thread.
 ///
 typedef struct _cef_end_tracing_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called after all processes have sent their trace data. |tracing_file| is
-  // the path at which tracing data was written. The client is responsible for
-  // deleting |tracing_file|.
+  /// Called after all processes have sent their trace data. |tracing_file| is
+  /// the path at which tracing data was written. The client is responsible for
+  /// deleting |tracing_file|.
   ///
   void(CEF_CALLBACK* on_end_tracing_complete)(
       struct _cef_end_tracing_callback_t* self,
@@ -69,47 +69,47 @@
 } cef_end_tracing_callback_t;
 
 ///
-// Start tracing events on all processes. Tracing is initialized asynchronously
-// and |callback| will be executed on the UI thread after initialization is
-// complete.
-//
-// If CefBeginTracing was called previously, or if a CefEndTracingAsync call is
-// pending, CefBeginTracing will fail and return false (0).
-//
-// |categories| is a comma-delimited list of category wildcards. A category can
-// have an optional '-' prefix to make it an excluded category. Having both
-// included and excluded categories in the same list is not supported.
-//
-// Example: "test_MyTest*" Example: "test_MyTest*,test_OtherStuff" Example:
-// "-excluded_category1,-excluded_category2"
-//
-// This function must be called on the browser process UI thread.
+/// Start tracing events on all processes. Tracing is initialized asynchronously
+/// and |callback| will be executed on the UI thread after initialization is
+/// complete.
+///
+/// If CefBeginTracing was called previously, or if a CefEndTracingAsync call is
+/// pending, CefBeginTracing will fail and return false (0).
+///
+/// |categories| is a comma-delimited list of category wildcards. A category can
+/// have an optional '-' prefix to make it an excluded category. Having both
+/// included and excluded categories in the same list is not supported.
+///
+/// Examples: - "test_MyTest*" - "test_MyTest*,test_OtherStuff" -
+/// "-excluded_category1,-excluded_category2"
+///
+/// This function must be called on the browser process UI thread.
 ///
 CEF_EXPORT int cef_begin_tracing(const cef_string_t* categories,
                                  struct _cef_completion_callback_t* callback);
 
 ///
-// Stop tracing events on all processes.
-//
-// This function will fail and return false (0) if a previous call to
-// CefEndTracingAsync is already pending or if CefBeginTracing was not called.
-//
-// |tracing_file| is the path at which tracing data will be written and
-// |callback| is the callback that will be executed once all processes have sent
-// their trace data. If |tracing_file| is NULL a new temporary file path will be
-// used. If |callback| is NULL no trace data will be written.
-//
-// This function must be called on the browser process UI thread.
+/// Stop tracing events on all processes.
+///
+/// This function will fail and return false (0) if a previous call to
+/// CefEndTracingAsync is already pending or if CefBeginTracing was not called.
+///
+/// |tracing_file| is the path at which tracing data will be written and
+/// |callback| is the callback that will be executed once all processes have
+/// sent their trace data. If |tracing_file| is NULL a new temporary file path
+/// will be used. If |callback| is NULL no trace data will be written.
+///
+/// This function must be called on the browser process UI thread.
 ///
 CEF_EXPORT int cef_end_tracing(const cef_string_t* tracing_file,
                                cef_end_tracing_callback_t* callback);
 
 ///
-// Returns the current system trace time or, if none is defined, the current
-// high-res time. Can be used by clients to synchronize with the time
-// information in trace events.
+/// Returns the current system trace time or, if none is defined, the current
+/// high-res time. Can be used by clients to synchronize with the time
+/// information in trace events.
 ///
-CEF_EXPORT int64 cef_now_from_system_trace_time();
+CEF_EXPORT int64_t cef_now_from_system_trace_time(void);
 
 #ifdef __cplusplus
 }
diff --git a/src/include/capi/cef_urlrequest_capi.h b/src/include/capi/cef_urlrequest_capi.h
index 81eeaa6..6db921d 100644
--- a/src/include/capi/cef_urlrequest_capi.h
+++ b/src/include/capi/cef_urlrequest_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=63d875f5a922dd2c2e1efaaf0ddaa20475f79ef8$
+// $hash=b038ad859f1dad2d8ba63589da118898350b309c$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_URLREQUEST_CAPI_H_
@@ -53,84 +53,78 @@
 struct _cef_urlrequest_client_t;
 
 ///
-// Structure used to make a URL request. URL requests are not associated with a
-// browser instance so no cef_client_t callbacks will be executed. URL requests
-// can be created on any valid CEF thread in either the browser or render
-// process. Once created the functions of the URL request object must be
-// accessed on the same thread that created it.
+/// Structure used to make a URL request. URL requests are not associated with a
+/// browser instance so no cef_client_t callbacks will be executed. URL requests
+/// can be created on any valid CEF thread in either the browser or render
+/// process. Once created the functions of the URL request object must be
+/// accessed on the same thread that created it.
 ///
 typedef struct _cef_urlrequest_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the request object used to create this URL request. The returned
-  // object is read-only and should not be modified.
+  /// Returns the request object used to create this URL request. The returned
+  /// object is read-only and should not be modified.
   ///
   struct _cef_request_t*(CEF_CALLBACK* get_request)(
       struct _cef_urlrequest_t* self);
 
   ///
-  // Returns the client.
+  /// Returns the client.
   ///
   struct _cef_urlrequest_client_t*(CEF_CALLBACK* get_client)(
       struct _cef_urlrequest_t* self);
 
   ///
-  // Returns the request status.
+  /// Returns the request status.
   ///
   cef_urlrequest_status_t(CEF_CALLBACK* get_request_status)(
       struct _cef_urlrequest_t* self);
 
   ///
-  // Returns the request error if status is UR_CANCELED or UR_FAILED, or 0
-  // otherwise.
+  /// Returns the request error if status is UR_CANCELED or UR_FAILED, or 0
+  /// otherwise.
   ///
   cef_errorcode_t(CEF_CALLBACK* get_request_error)(
       struct _cef_urlrequest_t* self);
 
   ///
-  // Returns the response, or NULL if no response information is available.
-  // Response information will only be available after the upload has completed.
-  // The returned object is read-only and should not be modified.
+  /// Returns the response, or NULL if no response information is available.
+  /// Response information will only be available after the upload has
+  /// completed. The returned object is read-only and should not be modified.
   ///
   struct _cef_response_t*(CEF_CALLBACK* get_response)(
       struct _cef_urlrequest_t* self);
 
   ///
-  // Returns true (1) if the response body was served from the cache. This
-  // includes responses for which revalidation was required.
+  /// Returns true (1) if the response body was served from the cache. This
+  /// includes responses for which revalidation was required.
   ///
   int(CEF_CALLBACK* response_was_cached)(struct _cef_urlrequest_t* self);
 
   ///
-  // Cancel the request.
+  /// Cancel the request.
   ///
   void(CEF_CALLBACK* cancel)(struct _cef_urlrequest_t* self);
 } cef_urlrequest_t;
 
 ///
-// Create a new URL request that is not associated with a specific browser or
-// frame. Use cef_frame_t::CreateURLRequest instead if you want the request to
-// have this association, in which case it may be handled differently (see
-// documentation on that function). Requests may originate from the both browser
-// process and the render process.
-//
-// For requests originating from the browser process:
-//   - It may be intercepted by the client via CefResourceRequestHandler or
-//     CefSchemeHandlerFactory.
-//   - POST data may only contain only a single element of type PDE_TYPE_FILE
-//     or PDE_TYPE_BYTES.
-//   - If |request_context| is empty the global request context will be used.
-// For requests originating from the render process:
-//   - It cannot be intercepted by the client so only http(s) and blob schemes
-//     are supported.
-//   - POST data may only contain a single element of type PDE_TYPE_BYTES.
-//   - The |request_context| parameter must be NULL.
-//
-// The |request| object will be marked as read-only after calling this function.
+/// Create a new URL request that is not associated with a specific browser or
+/// frame. Use cef_frame_t::CreateURLRequest instead if you want the request to
+/// have this association, in which case it may be handled differently (see
+/// documentation on that function). A request created with this function may
+/// only originate from the browser process, and will behave as follows:
+///   - It may be intercepted by the client via CefResourceRequestHandler or
+///     CefSchemeHandlerFactory.
+///   - POST data may only contain only a single element of type PDE_TYPE_FILE
+///     or PDE_TYPE_BYTES.
+///   - If |request_context| is empty the global request context will be used.
+///
+/// The |request| object will be marked as read-only after calling this
+/// function.
 ///
 CEF_EXPORT cef_urlrequest_t* cef_urlrequest_create(
     struct _cef_request_t* request,
@@ -138,50 +132,50 @@
     struct _cef_request_context_t* request_context);
 
 ///
-// Structure that should be implemented by the cef_urlrequest_t client. The
-// functions of this structure will be called on the same thread that created
-// the request unless otherwise documented.
+/// Structure that should be implemented by the cef_urlrequest_t client. The
+/// functions of this structure will be called on the same thread that created
+/// the request unless otherwise documented.
 ///
 typedef struct _cef_urlrequest_client_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Notifies the client that the request has completed. Use the
-  // cef_urlrequest_t::GetRequestStatus function to determine if the request was
-  // successful or not.
+  /// Notifies the client that the request has completed. Use the
+  /// cef_urlrequest_t::GetRequestStatus function to determine if the request
+  /// was successful or not.
   ///
   void(CEF_CALLBACK* on_request_complete)(struct _cef_urlrequest_client_t* self,
                                           struct _cef_urlrequest_t* request);
 
   ///
-  // Notifies the client of upload progress. |current| denotes the number of
-  // bytes sent so far and |total| is the total size of uploading data (or -1 if
-  // chunked upload is enabled). This function will only be called if the
-  // UR_FLAG_REPORT_UPLOAD_PROGRESS flag is set on the request.
+  /// Notifies the client of upload progress. |current| denotes the number of
+  /// bytes sent so far and |total| is the total size of uploading data (or -1
+  /// if chunked upload is enabled). This function will only be called if the
+  /// UR_FLAG_REPORT_UPLOAD_PROGRESS flag is set on the request.
   ///
   void(CEF_CALLBACK* on_upload_progress)(struct _cef_urlrequest_client_t* self,
                                          struct _cef_urlrequest_t* request,
-                                         int64 current,
-                                         int64 total);
+                                         int64_t current,
+                                         int64_t total);
 
   ///
-  // Notifies the client of download progress. |current| denotes the number of
-  // bytes received up to the call and |total| is the expected total size of the
-  // response (or -1 if not determined).
+  /// Notifies the client of download progress. |current| denotes the number of
+  /// bytes received up to the call and |total| is the expected total size of
+  /// the response (or -1 if not determined).
   ///
   void(CEF_CALLBACK* on_download_progress)(
       struct _cef_urlrequest_client_t* self,
       struct _cef_urlrequest_t* request,
-      int64 current,
-      int64 total);
+      int64_t current,
+      int64_t total);
 
   ///
-  // Called when some part of the response is read. |data| contains the current
-  // bytes received since the last call. This function will not be called if the
-  // UR_FLAG_NO_DOWNLOAD_DATA flag is set on the request.
+  /// Called when some part of the response is read. |data| contains the current
+  /// bytes received since the last call. This function will not be called if
+  /// the UR_FLAG_NO_DOWNLOAD_DATA flag is set on the request.
   ///
   void(CEF_CALLBACK* on_download_data)(struct _cef_urlrequest_client_t* self,
                                        struct _cef_urlrequest_t* request,
@@ -189,15 +183,16 @@
                                        size_t data_length);
 
   ///
-  // Called on the IO thread when the browser needs credentials from the user.
-  // |isProxy| indicates whether the host is a proxy server. |host| contains the
-  // hostname and |port| contains the port number. Return true (1) to continue
-  // the request and call cef_auth_callback_t::cont() when the authentication
-  // information is available. If the request has an associated browser/frame
-  // then returning false (0) will result in a call to GetAuthCredentials on the
-  // cef_request_handler_t associated with that browser, if any. Otherwise,
-  // returning false (0) will cancel the request immediately. This function will
-  // only be called for requests initiated from the browser process.
+  /// Called on the IO thread when the browser needs credentials from the user.
+  /// |isProxy| indicates whether the host is a proxy server. |host| contains
+  /// the hostname and |port| contains the port number. Return true (1) to
+  /// continue the request and call cef_auth_callback_t::cont() when the
+  /// authentication information is available. If the request has an associated
+  /// browser/frame then returning false (0) will result in a call to
+  /// GetAuthCredentials on the cef_request_handler_t associated with that
+  /// browser, if any. Otherwise, returning false (0) will cancel the request
+  /// immediately. This function will only be called for requests initiated from
+  /// the browser process.
   ///
   int(CEF_CALLBACK* get_auth_credentials)(
       struct _cef_urlrequest_client_t* self,
diff --git a/src/include/capi/cef_v8_capi.h b/src/include/capi/cef_v8_capi.h
index c54f309..98cec92 100644
--- a/src/include/capi/cef_v8_capi.h
+++ b/src/include/capi/cef_v8_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=3bb8f9801a153172981120926c7a5629e08d7131$
+// $hash=865ca5bff4a0867d0c25cb41bd2aa808cf3fddbd$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_V8_CAPI_H_
@@ -55,82 +55,82 @@
 struct _cef_v8value_t;
 
 ///
-// Structure representing a V8 context handle. V8 handles can only be accessed
-// from the thread on which they are created. Valid threads for creating a V8
-// handle include the render process main thread (TID_RENDERER) and WebWorker
-// threads. A task runner for posting tasks on the associated thread can be
-// retrieved via the cef_v8context_t::get_task_runner() function.
+/// Structure representing a V8 context handle. V8 handles can only be accessed
+/// from the thread on which they are created. Valid threads for creating a V8
+/// handle include the render process main thread (TID_RENDERER) and WebWorker
+/// threads. A task runner for posting tasks on the associated thread can be
+/// retrieved via the cef_v8context_t::get_task_runner() function.
 ///
 typedef struct _cef_v8context_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the task runner associated with this context. V8 handles can only
-  // be accessed from the thread on which they are created. This function can be
-  // called on any render process thread.
+  /// Returns the task runner associated with this context. V8 handles can only
+  /// be accessed from the thread on which they are created. This function can
+  /// be called on any render process thread.
   ///
   struct _cef_task_runner_t*(CEF_CALLBACK* get_task_runner)(
       struct _cef_v8context_t* self);
 
   ///
-  // Returns true (1) if the underlying handle is valid and it can be accessed
-  // on the current thread. Do not call any other functions if this function
-  // returns false (0).
+  /// Returns true (1) if the underlying handle is valid and it can be accessed
+  /// on the current thread. Do not call any other functions if this function
+  /// returns false (0).
   ///
   int(CEF_CALLBACK* is_valid)(struct _cef_v8context_t* self);
 
   ///
-  // Returns the browser for this context. This function will return an NULL
-  // reference for WebWorker contexts.
+  /// Returns the browser for this context. This function will return an NULL
+  /// reference for WebWorker contexts.
   ///
   struct _cef_browser_t*(CEF_CALLBACK* get_browser)(
       struct _cef_v8context_t* self);
 
   ///
-  // Returns the frame for this context. This function will return an NULL
-  // reference for WebWorker contexts.
+  /// Returns the frame for this context. This function will return an NULL
+  /// reference for WebWorker contexts.
   ///
   struct _cef_frame_t*(CEF_CALLBACK* get_frame)(struct _cef_v8context_t* self);
 
   ///
-  // Returns the global object for this context. The context must be entered
-  // before calling this function.
+  /// Returns the global object for this context. The context must be entered
+  /// before calling this function.
   ///
   struct _cef_v8value_t*(CEF_CALLBACK* get_global)(
       struct _cef_v8context_t* self);
 
   ///
-  // Enter this context. A context must be explicitly entered before creating a
-  // V8 Object, Array, Function or Date asynchronously. exit() must be called
-  // the same number of times as enter() before releasing this context. V8
-  // objects belong to the context in which they are created. Returns true (1)
-  // if the scope was entered successfully.
+  /// Enter this context. A context must be explicitly entered before creating a
+  /// V8 Object, Array, Function or Date asynchronously. exit() must be called
+  /// the same number of times as enter() before releasing this context. V8
+  /// objects belong to the context in which they are created. Returns true (1)
+  /// if the scope was entered successfully.
   ///
   int(CEF_CALLBACK* enter)(struct _cef_v8context_t* self);
 
   ///
-  // Exit this context. Call this function only after calling enter(). Returns
-  // true (1) if the scope was exited successfully.
+  /// Exit this context. Call this function only after calling enter(). Returns
+  /// true (1) if the scope was exited successfully.
   ///
   int(CEF_CALLBACK* exit)(struct _cef_v8context_t* self);
 
   ///
-  // Returns true (1) if this object is pointing to the same handle as |that|
-  // object.
+  /// Returns true (1) if this object is pointing to the same handle as |that|
+  /// object.
   ///
   int(CEF_CALLBACK* is_same)(struct _cef_v8context_t* self,
                              struct _cef_v8context_t* that);
 
   ///
-  // Execute a string of JavaScript code in this V8 context. The |script_url|
-  // parameter is the URL where the script in question can be found, if any. The
-  // |start_line| parameter is the base line number to use for error reporting.
-  // On success |retval| will be set to the return value, if any, and the
-  // function will return true (1). On failure |exception| will be set to the
-  // exception, if any, and the function will return false (0).
+  /// Execute a string of JavaScript code in this V8 context. The |script_url|
+  /// parameter is the URL where the script in question can be found, if any.
+  /// The |start_line| parameter is the base line number to use for error
+  /// reporting. On success |retval| will be set to the return value, if any,
+  /// and the function will return true (1). On failure |exception| will be set
+  /// to the exception, if any, and the function will return false (0).
   ///
   int(CEF_CALLBACK* eval)(struct _cef_v8context_t* self,
                           const cef_string_t* code,
@@ -141,37 +141,37 @@
 } cef_v8context_t;
 
 ///
-// Returns the current (top) context object in the V8 context stack.
+/// Returns the current (top) context object in the V8 context stack.
 ///
-CEF_EXPORT cef_v8context_t* cef_v8context_get_current_context();
+CEF_EXPORT cef_v8context_t* cef_v8context_get_current_context(void);
 
 ///
-// Returns the entered (bottom) context object in the V8 context stack.
+/// Returns the entered (bottom) context object in the V8 context stack.
 ///
-CEF_EXPORT cef_v8context_t* cef_v8context_get_entered_context();
+CEF_EXPORT cef_v8context_t* cef_v8context_get_entered_context(void);
 
 ///
-// Returns true (1) if V8 is currently inside a context.
+/// Returns true (1) if V8 is currently inside a context.
 ///
-CEF_EXPORT int cef_v8context_in_context();
+CEF_EXPORT int cef_v8context_in_context(void);
 
 ///
-// Structure that should be implemented to handle V8 function calls. The
-// functions of this structure will be called on the thread associated with the
-// V8 function.
+/// Structure that should be implemented to handle V8 function calls. The
+/// functions of this structure will be called on the thread associated with the
+/// V8 function.
 ///
 typedef struct _cef_v8handler_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Handle execution of the function identified by |name|. |object| is the
-  // receiver ('this' object) of the function. |arguments| is the list of
-  // arguments passed to the function. If execution succeeds set |retval| to the
-  // function return value. If execution fails set |exception| to the exception
-  // that will be thrown. Return true (1) if execution was handled.
+  /// Handle execution of the function identified by |name|. |object| is the
+  /// receiver ('this' object) of the function. |arguments| is the list of
+  /// arguments passed to the function. If execution succeeds set |retval| to
+  /// the function return value. If execution fails set |exception| to the
+  /// exception that will be thrown. Return true (1) if execution was handled.
   ///
   int(CEF_CALLBACK* execute)(struct _cef_v8handler_t* self,
                              const cef_string_t* name,
@@ -183,23 +183,23 @@
 } cef_v8handler_t;
 
 ///
-// Structure that should be implemented to handle V8 accessor calls. Accessor
-// identifiers are registered by calling cef_v8value_t::set_value(). The
-// functions of this structure will be called on the thread associated with the
-// V8 accessor.
+/// Structure that should be implemented to handle V8 accessor calls. Accessor
+/// identifiers are registered by calling cef_v8value_t::set_value(). The
+/// functions of this structure will be called on the thread associated with the
+/// V8 accessor.
 ///
 typedef struct _cef_v8accessor_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Handle retrieval the accessor value identified by |name|. |object| is the
-  // receiver ('this' object) of the accessor. If retrieval succeeds set
-  // |retval| to the return value. If retrieval fails set |exception| to the
-  // exception that will be thrown. Return true (1) if accessor retrieval was
-  // handled.
+  /// Handle retrieval the accessor value identified by |name|. |object| is the
+  /// receiver ('this' object) of the accessor. If retrieval succeeds set
+  /// |retval| to the return value. If retrieval fails set |exception| to the
+  /// exception that will be thrown. Return true (1) if accessor retrieval was
+  /// handled.
   ///
   int(CEF_CALLBACK* get)(struct _cef_v8accessor_t* self,
                          const cef_string_t* name,
@@ -208,11 +208,11 @@
                          cef_string_t* exception);
 
   ///
-  // Handle assignment of the accessor value identified by |name|. |object| is
-  // the receiver ('this' object) of the accessor. |value| is the new value
-  // being assigned to the accessor. If assignment fails set |exception| to the
-  // exception that will be thrown. Return true (1) if accessor assignment was
-  // handled.
+  /// Handle assignment of the accessor value identified by |name|. |object| is
+  /// the receiver ('this' object) of the accessor. |value| is the new value
+  /// being assigned to the accessor. If assignment fails set |exception| to the
+  /// exception that will be thrown. Return true (1) if accessor assignment was
+  /// handled.
   ///
   int(CEF_CALLBACK* set)(struct _cef_v8accessor_t* self,
                          const cef_string_t* name,
@@ -222,27 +222,27 @@
 } cef_v8accessor_t;
 
 ///
-// Structure that should be implemented to handle V8 interceptor calls. The
-// functions of this structure will be called on the thread associated with the
-// V8 interceptor. Interceptor's named property handlers (with first argument of
-// type CefString) are called when object is indexed by string. Indexed property
-// handlers (with first argument of type int) are called when object is indexed
-// by integer.
+/// Structure that should be implemented to handle V8 interceptor calls. The
+/// functions of this structure will be called on the thread associated with the
+/// V8 interceptor. Interceptor's named property handlers (with first argument
+/// of type CefString) are called when object is indexed by string. Indexed
+/// property handlers (with first argument of type int) are called when object
+/// is indexed by integer.
 ///
 typedef struct _cef_v8interceptor_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Handle retrieval of the interceptor value identified by |name|. |object| is
-  // the receiver ('this' object) of the interceptor. If retrieval succeeds, set
-  // |retval| to the return value. If the requested value does not exist, don't
-  // set either |retval| or |exception|. If retrieval fails, set |exception| to
-  // the exception that will be thrown. If the property has an associated
-  // accessor, it will be called only if you don't set |retval|. Return true (1)
-  // if interceptor retrieval was handled, false (0) otherwise.
+  /// Handle retrieval of the interceptor value identified by |name|. |object|
+  /// is the receiver ('this' object) of the interceptor. If retrieval succeeds,
+  /// set |retval| to the return value. If the requested value does not exist,
+  /// don't set either |retval| or |exception|. If retrieval fails, set
+  /// |exception| to the exception that will be thrown. If the property has an
+  /// associated accessor, it will be called only if you don't set |retval|.
+  /// Return true (1) if interceptor retrieval was handled, false (0) otherwise.
   ///
   int(CEF_CALLBACK* get_byname)(struct _cef_v8interceptor_t* self,
                                 const cef_string_t* name,
@@ -251,12 +251,12 @@
                                 cef_string_t* exception);
 
   ///
-  // Handle retrieval of the interceptor value identified by |index|. |object|
-  // is the receiver ('this' object) of the interceptor. If retrieval succeeds,
-  // set |retval| to the return value. If the requested value does not exist,
-  // don't set either |retval| or |exception|. If retrieval fails, set
-  // |exception| to the exception that will be thrown. Return true (1) if
-  // interceptor retrieval was handled, false (0) otherwise.
+  /// Handle retrieval of the interceptor value identified by |index|. |object|
+  /// is the receiver ('this' object) of the interceptor. If retrieval succeeds,
+  /// set |retval| to the return value. If the requested value does not exist,
+  /// don't set either |retval| or |exception|. If retrieval fails, set
+  /// |exception| to the exception that will be thrown. Return true (1) if
+  /// interceptor retrieval was handled, false (0) otherwise.
   ///
   int(CEF_CALLBACK* get_byindex)(struct _cef_v8interceptor_t* self,
                                  int index,
@@ -265,12 +265,12 @@
                                  cef_string_t* exception);
 
   ///
-  // Handle assignment of the interceptor value identified by |name|. |object|
-  // is the receiver ('this' object) of the interceptor. |value| is the new
-  // value being assigned to the interceptor. If assignment fails, set
-  // |exception| to the exception that will be thrown. This setter will always
-  // be called, even when the property has an associated accessor. Return true
-  // (1) if interceptor assignment was handled, false (0) otherwise.
+  /// Handle assignment of the interceptor value identified by |name|. |object|
+  /// is the receiver ('this' object) of the interceptor. |value| is the new
+  /// value being assigned to the interceptor. If assignment fails, set
+  /// |exception| to the exception that will be thrown. This setter will always
+  /// be called, even when the property has an associated accessor. Return true
+  /// (1) if interceptor assignment was handled, false (0) otherwise.
   ///
   int(CEF_CALLBACK* set_byname)(struct _cef_v8interceptor_t* self,
                                 const cef_string_t* name,
@@ -279,11 +279,11 @@
                                 cef_string_t* exception);
 
   ///
-  // Handle assignment of the interceptor value identified by |index|. |object|
-  // is the receiver ('this' object) of the interceptor. |value| is the new
-  // value being assigned to the interceptor. If assignment fails, set
-  // |exception| to the exception that will be thrown. Return true (1) if
-  // interceptor assignment was handled, false (0) otherwise.
+  /// Handle assignment of the interceptor value identified by |index|. |object|
+  /// is the receiver ('this' object) of the interceptor. |value| is the new
+  /// value being assigned to the interceptor. If assignment fails, set
+  /// |exception| to the exception that will be thrown. Return true (1) if
+  /// interceptor assignment was handled, false (0) otherwise.
   ///
   int(CEF_CALLBACK* set_byindex)(struct _cef_v8interceptor_t* self,
                                  int index,
@@ -293,81 +293,81 @@
 } cef_v8interceptor_t;
 
 ///
-// Structure representing a V8 exception. The functions of this structure may be
-// called on any render process thread.
+/// Structure representing a V8 exception. The functions of this structure may
+/// be called on any render process thread.
 ///
 typedef struct _cef_v8exception_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the exception message.
+  /// Returns the exception message.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_message)(
       struct _cef_v8exception_t* self);
 
   ///
-  // Returns the line of source code that the exception occurred within.
+  /// Returns the line of source code that the exception occurred within.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_source_line)(
       struct _cef_v8exception_t* self);
 
   ///
-  // Returns the resource name for the script from where the function causing
-  // the error originates.
+  /// Returns the resource name for the script from where the function causing
+  /// the error originates.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_script_resource_name)(
       struct _cef_v8exception_t* self);
 
   ///
-  // Returns the 1-based number of the line where the error occurred or 0 if the
-  // line number is unknown.
+  /// Returns the 1-based number of the line where the error occurred or 0 if
+  /// the line number is unknown.
   ///
   int(CEF_CALLBACK* get_line_number)(struct _cef_v8exception_t* self);
 
   ///
-  // Returns the index within the script of the first character where the error
-  // occurred.
+  /// Returns the index within the script of the first character where the error
+  /// occurred.
   ///
   int(CEF_CALLBACK* get_start_position)(struct _cef_v8exception_t* self);
 
   ///
-  // Returns the index within the script of the last character where the error
-  // occurred.
+  /// Returns the index within the script of the last character where the error
+  /// occurred.
   ///
   int(CEF_CALLBACK* get_end_position)(struct _cef_v8exception_t* self);
 
   ///
-  // Returns the index within the line of the first character where the error
-  // occurred.
+  /// Returns the index within the line of the first character where the error
+  /// occurred.
   ///
   int(CEF_CALLBACK* get_start_column)(struct _cef_v8exception_t* self);
 
   ///
-  // Returns the index within the line of the last character where the error
-  // occurred.
+  /// Returns the index within the line of the last character where the error
+  /// occurred.
   ///
   int(CEF_CALLBACK* get_end_column)(struct _cef_v8exception_t* self);
 } cef_v8exception_t;
 
 ///
-// Callback structure that is passed to cef_v8value_t::CreateArrayBuffer.
+/// Callback structure that is passed to cef_v8value_t::CreateArrayBuffer.
 ///
 typedef struct _cef_v8array_buffer_release_callback_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Called to release |buffer| when the ArrayBuffer JS object is garbage
-  // collected. |buffer| is the value that was passed to CreateArrayBuffer along
-  // with this object.
+  /// Called to release |buffer| when the ArrayBuffer JS object is garbage
+  /// collected. |buffer| is the value that was passed to CreateArrayBuffer
+  /// along with this object.
   ///
   void(CEF_CALLBACK* release_buffer)(
       struct _cef_v8array_buffer_release_callback_t* self,
@@ -375,216 +375,217 @@
 } cef_v8array_buffer_release_callback_t;
 
 ///
-// Structure representing a V8 value handle. V8 handles can only be accessed
-// from the thread on which they are created. Valid threads for creating a V8
-// handle include the render process main thread (TID_RENDERER) and WebWorker
-// threads. A task runner for posting tasks on the associated thread can be
-// retrieved via the cef_v8context_t::get_task_runner() function.
+/// Structure representing a V8 value handle. V8 handles can only be accessed
+/// from the thread on which they are created. Valid threads for creating a V8
+/// handle include the render process main thread (TID_RENDERER) and WebWorker
+/// threads. A task runner for posting tasks on the associated thread can be
+/// retrieved via the cef_v8context_t::get_task_runner() function.
 ///
 typedef struct _cef_v8value_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if the underlying handle is valid and it can be accessed
-  // on the current thread. Do not call any other functions if this function
-  // returns false (0).
+  /// Returns true (1) if the underlying handle is valid and it can be accessed
+  /// on the current thread. Do not call any other functions if this function
+  /// returns false (0).
   ///
   int(CEF_CALLBACK* is_valid)(struct _cef_v8value_t* self);
 
   ///
-  // True if the value type is undefined.
+  /// True if the value type is undefined.
   ///
   int(CEF_CALLBACK* is_undefined)(struct _cef_v8value_t* self);
 
   ///
-  // True if the value type is null.
+  /// True if the value type is null.
   ///
   int(CEF_CALLBACK* is_null)(struct _cef_v8value_t* self);
 
   ///
-  // True if the value type is bool.
+  /// True if the value type is bool.
   ///
   int(CEF_CALLBACK* is_bool)(struct _cef_v8value_t* self);
 
   ///
-  // True if the value type is int.
+  /// True if the value type is int.
   ///
   int(CEF_CALLBACK* is_int)(struct _cef_v8value_t* self);
 
   ///
-  // True if the value type is unsigned int.
+  /// True if the value type is unsigned int.
   ///
   int(CEF_CALLBACK* is_uint)(struct _cef_v8value_t* self);
 
   ///
-  // True if the value type is double.
+  /// True if the value type is double.
   ///
   int(CEF_CALLBACK* is_double)(struct _cef_v8value_t* self);
 
   ///
-  // True if the value type is Date.
+  /// True if the value type is Date.
   ///
   int(CEF_CALLBACK* is_date)(struct _cef_v8value_t* self);
 
   ///
-  // True if the value type is string.
+  /// True if the value type is string.
   ///
   int(CEF_CALLBACK* is_string)(struct _cef_v8value_t* self);
 
   ///
-  // True if the value type is object.
+  /// True if the value type is object.
   ///
   int(CEF_CALLBACK* is_object)(struct _cef_v8value_t* self);
 
   ///
-  // True if the value type is array.
+  /// True if the value type is array.
   ///
   int(CEF_CALLBACK* is_array)(struct _cef_v8value_t* self);
 
   ///
-  // True if the value type is an ArrayBuffer.
+  /// True if the value type is an ArrayBuffer.
   ///
   int(CEF_CALLBACK* is_array_buffer)(struct _cef_v8value_t* self);
 
   ///
-  // True if the value type is function.
+  /// True if the value type is function.
   ///
   int(CEF_CALLBACK* is_function)(struct _cef_v8value_t* self);
 
   ///
-  // Returns true (1) if this object is pointing to the same handle as |that|
-  // object.
+  /// True if the value type is a Promise.
+  ///
+  int(CEF_CALLBACK* is_promise)(struct _cef_v8value_t* self);
+
+  ///
+  /// Returns true (1) if this object is pointing to the same handle as |that|
+  /// object.
   ///
   int(CEF_CALLBACK* is_same)(struct _cef_v8value_t* self,
                              struct _cef_v8value_t* that);
 
   ///
-  // Return a bool value.
+  /// Return a bool value.
   ///
   int(CEF_CALLBACK* get_bool_value)(struct _cef_v8value_t* self);
 
   ///
-  // Return an int value.
+  /// Return an int value.
   ///
-  int32(CEF_CALLBACK* get_int_value)(struct _cef_v8value_t* self);
+  int32_t(CEF_CALLBACK* get_int_value)(struct _cef_v8value_t* self);
 
   ///
-  // Return an unsigned int value.
+  /// Return an unsigned int value.
   ///
-  uint32(CEF_CALLBACK* get_uint_value)(struct _cef_v8value_t* self);
+  uint32_t(CEF_CALLBACK* get_uint_value)(struct _cef_v8value_t* self);
 
   ///
-  // Return a double value.
+  /// Return a double value.
   ///
   double(CEF_CALLBACK* get_double_value)(struct _cef_v8value_t* self);
 
   ///
-  // Return a Date value.
+  /// Return a Date value.
   ///
-  cef_time_t(CEF_CALLBACK* get_date_value)(struct _cef_v8value_t* self);
+  cef_basetime_t(CEF_CALLBACK* get_date_value)(struct _cef_v8value_t* self);
 
   ///
-  // Return a string value.
+  /// Return a string value.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_string_value)(
       struct _cef_v8value_t* self);
 
-  // OBJECT METHODS - These functions are only available on objects. Arrays and
-  // functions are also objects. String- and integer-based keys can be used
-  // interchangably with the framework converting between them as necessary.
-
   ///
-  // Returns true (1) if this is a user created object.
+  /// Returns true (1) if this is a user created object.
   ///
   int(CEF_CALLBACK* is_user_created)(struct _cef_v8value_t* self);
 
   ///
-  // Returns true (1) if the last function call resulted in an exception. This
-  // attribute exists only in the scope of the current CEF value object.
+  /// Returns true (1) if the last function call resulted in an exception. This
+  /// attribute exists only in the scope of the current CEF value object.
   ///
   int(CEF_CALLBACK* has_exception)(struct _cef_v8value_t* self);
 
   ///
-  // Returns the exception resulting from the last function call. This attribute
-  // exists only in the scope of the current CEF value object.
+  /// Returns the exception resulting from the last function call. This
+  /// attribute exists only in the scope of the current CEF value object.
   ///
   struct _cef_v8exception_t*(CEF_CALLBACK* get_exception)(
       struct _cef_v8value_t* self);
 
   ///
-  // Clears the last exception and returns true (1) on success.
+  /// Clears the last exception and returns true (1) on success.
   ///
   int(CEF_CALLBACK* clear_exception)(struct _cef_v8value_t* self);
 
   ///
-  // Returns true (1) if this object will re-throw future exceptions. This
-  // attribute exists only in the scope of the current CEF value object.
+  /// Returns true (1) if this object will re-throw future exceptions. This
+  /// attribute exists only in the scope of the current CEF value object.
   ///
   int(CEF_CALLBACK* will_rethrow_exceptions)(struct _cef_v8value_t* self);
 
   ///
-  // Set whether this object will re-throw future exceptions. By default
-  // exceptions are not re-thrown. If a exception is re-thrown the current
-  // context should not be accessed again until after the exception has been
-  // caught and not re-thrown. Returns true (1) on success. This attribute
-  // exists only in the scope of the current CEF value object.
+  /// Set whether this object will re-throw future exceptions. By default
+  /// exceptions are not re-thrown. If a exception is re-thrown the current
+  /// context should not be accessed again until after the exception has been
+  /// caught and not re-thrown. Returns true (1) on success. This attribute
+  /// exists only in the scope of the current CEF value object.
   ///
   int(CEF_CALLBACK* set_rethrow_exceptions)(struct _cef_v8value_t* self,
                                             int rethrow);
 
   ///
-  // Returns true (1) if the object has a value with the specified identifier.
+  /// Returns true (1) if the object has a value with the specified identifier.
   ///
   int(CEF_CALLBACK* has_value_bykey)(struct _cef_v8value_t* self,
                                      const cef_string_t* key);
 
   ///
-  // Returns true (1) if the object has a value with the specified identifier.
+  /// Returns true (1) if the object has a value with the specified identifier.
   ///
   int(CEF_CALLBACK* has_value_byindex)(struct _cef_v8value_t* self, int index);
 
   ///
-  // Deletes the value with the specified identifier and returns true (1) on
-  // success. Returns false (0) if this function is called incorrectly or an
-  // exception is thrown. For read-only and don't-delete values this function
-  // will return true (1) even though deletion failed.
+  /// Deletes the value with the specified identifier and returns true (1) on
+  /// success. Returns false (0) if this function is called incorrectly or an
+  /// exception is thrown. For read-only and don't-delete values this function
+  /// will return true (1) even though deletion failed.
   ///
   int(CEF_CALLBACK* delete_value_bykey)(struct _cef_v8value_t* self,
                                         const cef_string_t* key);
 
   ///
-  // Deletes the value with the specified identifier and returns true (1) on
-  // success. Returns false (0) if this function is called incorrectly, deletion
-  // fails or an exception is thrown. For read-only and don't-delete values this
-  // function will return true (1) even though deletion failed.
+  /// Deletes the value with the specified identifier and returns true (1) on
+  /// success. Returns false (0) if this function is called incorrectly,
+  /// deletion fails or an exception is thrown. For read-only and don't-delete
+  /// values this function will return true (1) even though deletion failed.
   ///
   int(CEF_CALLBACK* delete_value_byindex)(struct _cef_v8value_t* self,
                                           int index);
 
   ///
-  // Returns the value with the specified identifier on success. Returns NULL if
-  // this function is called incorrectly or an exception is thrown.
+  /// Returns the value with the specified identifier on success. Returns NULL
+  /// if this function is called incorrectly or an exception is thrown.
   ///
   struct _cef_v8value_t*(CEF_CALLBACK* get_value_bykey)(
       struct _cef_v8value_t* self,
       const cef_string_t* key);
 
   ///
-  // Returns the value with the specified identifier on success. Returns NULL if
-  // this function is called incorrectly or an exception is thrown.
+  /// Returns the value with the specified identifier on success. Returns NULL
+  /// if this function is called incorrectly or an exception is thrown.
   ///
   struct _cef_v8value_t*(
       CEF_CALLBACK* get_value_byindex)(struct _cef_v8value_t* self, int index);
 
   ///
-  // Associates a value with the specified identifier and returns true (1) on
-  // success. Returns false (0) if this function is called incorrectly or an
-  // exception is thrown. For read-only values this function will return true
-  // (1) even though assignment failed.
+  /// Associates a value with the specified identifier and returns true (1) on
+  /// success. Returns false (0) if this function is called incorrectly or an
+  /// exception is thrown. For read-only values this function will return true
+  /// (1) even though assignment failed.
   ///
   int(CEF_CALLBACK* set_value_bykey)(struct _cef_v8value_t* self,
                                      const cef_string_t* key,
@@ -592,21 +593,21 @@
                                      cef_v8_propertyattribute_t attribute);
 
   ///
-  // Associates a value with the specified identifier and returns true (1) on
-  // success. Returns false (0) if this function is called incorrectly or an
-  // exception is thrown. For read-only values this function will return true
-  // (1) even though assignment failed.
+  /// Associates a value with the specified identifier and returns true (1) on
+  /// success. Returns false (0) if this function is called incorrectly or an
+  /// exception is thrown. For read-only values this function will return true
+  /// (1) even though assignment failed.
   ///
   int(CEF_CALLBACK* set_value_byindex)(struct _cef_v8value_t* self,
                                        int index,
                                        struct _cef_v8value_t* value);
 
   ///
-  // Registers an identifier and returns true (1) on success. Access to the
-  // identifier will be forwarded to the cef_v8accessor_t instance passed to
-  // cef_v8value_t::cef_v8value_create_object(). Returns false (0) if this
-  // function is called incorrectly or an exception is thrown. For read-only
-  // values this function will return true (1) even though assignment failed.
+  /// Registers an identifier and returns true (1) on success. Access to the
+  /// identifier will be forwarded to the cef_v8accessor_t instance passed to
+  /// cef_v8value_t::cef_v8value_create_object(). Returns false (0) if this
+  /// function is called incorrectly or an exception is thrown. For read-only
+  /// values this function will return true (1) even though assignment failed.
   ///
   int(CEF_CALLBACK* set_value_byaccessor)(struct _cef_v8value_t* self,
                                           const cef_string_t* key,
@@ -614,99 +615,106 @@
                                           cef_v8_propertyattribute_t attribute);
 
   ///
-  // Read the keys for the object's values into the specified vector. Integer-
-  // based keys will also be returned as strings.
+  /// Read the keys for the object's values into the specified vector. Integer-
+  /// based keys will also be returned as strings.
   ///
   int(CEF_CALLBACK* get_keys)(struct _cef_v8value_t* self,
                               cef_string_list_t keys);
 
   ///
-  // Sets the user data for this object and returns true (1) on success. Returns
-  // false (0) if this function is called incorrectly. This function can only be
-  // called on user created objects.
+  /// Sets the user data for this object and returns true (1) on success.
+  /// Returns false (0) if this function is called incorrectly. This function
+  /// can only be called on user created objects.
   ///
   int(CEF_CALLBACK* set_user_data)(struct _cef_v8value_t* self,
                                    struct _cef_base_ref_counted_t* user_data);
 
   ///
-  // Returns the user data, if any, assigned to this object.
+  /// Returns the user data, if any, assigned to this object.
   ///
   struct _cef_base_ref_counted_t*(CEF_CALLBACK* get_user_data)(
       struct _cef_v8value_t* self);
 
   ///
-  // Returns the amount of externally allocated memory registered for the
-  // object.
+  /// Returns the amount of externally allocated memory registered for the
+  /// object.
   ///
   int(CEF_CALLBACK* get_externally_allocated_memory)(
       struct _cef_v8value_t* self);
 
   ///
-  // Adjusts the amount of registered external memory for the object. Used to
-  // give V8 an indication of the amount of externally allocated memory that is
-  // kept alive by JavaScript objects. V8 uses this information to decide when
-  // to perform global garbage collection. Each cef_v8value_t tracks the amount
-  // of external memory associated with it and automatically decreases the
-  // global total by the appropriate amount on its destruction.
-  // |change_in_bytes| specifies the number of bytes to adjust by. This function
-  // returns the number of bytes associated with the object after the
-  // adjustment. This function can only be called on user created objects.
+  /// Adjusts the amount of registered external memory for the object. Used to
+  /// give V8 an indication of the amount of externally allocated memory that is
+  /// kept alive by JavaScript objects. V8 uses this information to decide when
+  /// to perform global garbage collection. Each cef_v8value_t tracks the amount
+  /// of external memory associated with it and automatically decreases the
+  /// global total by the appropriate amount on its destruction.
+  /// |change_in_bytes| specifies the number of bytes to adjust by. This
+  /// function returns the number of bytes associated with the object after the
+  /// adjustment. This function can only be called on user created objects.
   ///
   int(CEF_CALLBACK* adjust_externally_allocated_memory)(
       struct _cef_v8value_t* self,
       int change_in_bytes);
 
-  // ARRAY METHODS - These functions are only available on arrays.
-
   ///
-  // Returns the number of elements in the array.
+  /// Returns the number of elements in the array.
   ///
   int(CEF_CALLBACK* get_array_length)(struct _cef_v8value_t* self);
 
-  // ARRAY BUFFER METHODS - These functions are only available on ArrayBuffers.
-
   ///
-  // Returns the ReleaseCallback object associated with the ArrayBuffer or NULL
-  // if the ArrayBuffer was not created with CreateArrayBuffer.
+  /// Returns the ReleaseCallback object associated with the ArrayBuffer or NULL
+  /// if the ArrayBuffer was not created with CreateArrayBuffer.
   ///
   struct _cef_v8array_buffer_release_callback_t*(
       CEF_CALLBACK* get_array_buffer_release_callback)(
       struct _cef_v8value_t* self);
 
   ///
-  // Prevent the ArrayBuffer from using it's memory block by setting the length
-  // to zero. This operation cannot be undone. If the ArrayBuffer was created
-  // with CreateArrayBuffer then
-  // cef_v8array_buffer_release_callback_t::ReleaseBuffer will be called to
-  // release the underlying buffer.
+  /// Prevent the ArrayBuffer from using it's memory block by setting the length
+  /// to zero. This operation cannot be undone. If the ArrayBuffer was created
+  /// with CreateArrayBuffer then
+  /// cef_v8array_buffer_release_callback_t::ReleaseBuffer will be called to
+  /// release the underlying buffer.
   ///
   int(CEF_CALLBACK* neuter_array_buffer)(struct _cef_v8value_t* self);
 
-  // FUNCTION METHODS - These functions are only available on functions.
+  ///
+  /// Returns the length (in bytes) of the ArrayBuffer.
+  ///
+  size_t(CEF_CALLBACK* get_array_buffer_byte_length)(
+      struct _cef_v8value_t* self);
 
   ///
-  // Returns the function name.
+  /// Returns a pointer to the beginning of the memory block for this
+  /// ArrayBuffer backing store. The returned pointer is valid as long as the
+  /// cef_v8value_t is alive.
+  ///
+  void*(CEF_CALLBACK* get_array_buffer_data)(struct _cef_v8value_t* self);
+
+  ///
+  /// Returns the function name.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_function_name)(
       struct _cef_v8value_t* self);
 
   ///
-  // Returns the function handler or NULL if not a CEF-created function.
+  /// Returns the function handler or NULL if not a CEF-created function.
   ///
   struct _cef_v8handler_t*(CEF_CALLBACK* get_function_handler)(
       struct _cef_v8value_t* self);
 
   ///
-  // Execute the function using the current V8 context. This function should
-  // only be called from within the scope of a cef_v8handler_t or
-  // cef_v8accessor_t callback, or in combination with calling enter() and
-  // exit() on a stored cef_v8context_t reference. |object| is the receiver
-  // ('this' object) of the function. If |object| is NULL the current context's
-  // global object will be used. |arguments| is the list of arguments that will
-  // be passed to the function. Returns the function return value on success.
-  // Returns NULL if this function is called incorrectly or an exception is
-  // thrown.
+  /// Execute the function using the current V8 context. This function should
+  /// only be called from within the scope of a cef_v8handler_t or
+  /// cef_v8accessor_t callback, or in combination with calling enter() and
+  /// exit() on a stored cef_v8context_t reference. |object| is the receiver
+  /// ('this' object) of the function. If |object| is NULL the current context's
+  /// global object will be used. |arguments| is the list of arguments that will
+  /// be passed to the function. Returns the function return value on success.
+  /// Returns NULL if this function is called incorrectly or an exception is
+  /// thrown.
   ///
   struct _cef_v8value_t*(CEF_CALLBACK* execute_function)(
       struct _cef_v8value_t* self,
@@ -715,12 +723,12 @@
       struct _cef_v8value_t* const* arguments);
 
   ///
-  // Execute the function using the specified V8 context. |object| is the
-  // receiver ('this' object) of the function. If |object| is NULL the specified
-  // context's global object will be used. |arguments| is the list of arguments
-  // that will be passed to the function. Returns the function return value on
-  // success. Returns NULL if this function is called incorrectly or an
-  // exception is thrown.
+  /// Execute the function using the specified V8 context. |object| is the
+  /// receiver ('this' object) of the function. If |object| is NULL the
+  /// specified context's global object will be used. |arguments| is the list of
+  /// arguments that will be passed to the function. Returns the function return
+  /// value on success. Returns NULL if this function is called incorrectly or
+  /// an exception is thrown.
   ///
   struct _cef_v8value_t*(CEF_CALLBACK* execute_function_with_context)(
       struct _cef_v8value_t* self,
@@ -728,81 +736,102 @@
       struct _cef_v8value_t* object,
       size_t argumentsCount,
       struct _cef_v8value_t* const* arguments);
+
+  ///
+  /// Resolve the Promise using the current V8 context. This function should
+  /// only be called from within the scope of a cef_v8handler_t or
+  /// cef_v8accessor_t callback, or in combination with calling enter() and
+  /// exit() on a stored cef_v8context_t reference. |arg| is the argument passed
+  /// to the resolved promise. Returns true (1) on success. Returns false (0) if
+  /// this function is called incorrectly or an exception is thrown.
+  ///
+  int(CEF_CALLBACK* resolve_promise)(struct _cef_v8value_t* self,
+                                     struct _cef_v8value_t* arg);
+
+  ///
+  /// Reject the Promise using the current V8 context. This function should only
+  /// be called from within the scope of a cef_v8handler_t or cef_v8accessor_t
+  /// callback, or in combination with calling enter() and exit() on a stored
+  /// cef_v8context_t reference. Returns true (1) on success. Returns false (0)
+  /// if this function is called incorrectly or an exception is thrown.
+  ///
+  int(CEF_CALLBACK* reject_promise)(struct _cef_v8value_t* self,
+                                    const cef_string_t* errorMsg);
 } cef_v8value_t;
 
 ///
-// Create a new cef_v8value_t object of type undefined.
+/// Create a new cef_v8value_t object of type undefined.
 ///
-CEF_EXPORT cef_v8value_t* cef_v8value_create_undefined();
+CEF_EXPORT cef_v8value_t* cef_v8value_create_undefined(void);
 
 ///
-// Create a new cef_v8value_t object of type null.
+/// Create a new cef_v8value_t object of type null.
 ///
-CEF_EXPORT cef_v8value_t* cef_v8value_create_null();
+CEF_EXPORT cef_v8value_t* cef_v8value_create_null(void);
 
 ///
-// Create a new cef_v8value_t object of type bool.
+/// Create a new cef_v8value_t object of type bool.
 ///
 CEF_EXPORT cef_v8value_t* cef_v8value_create_bool(int value);
 
 ///
-// Create a new cef_v8value_t object of type int.
+/// Create a new cef_v8value_t object of type int.
 ///
-CEF_EXPORT cef_v8value_t* cef_v8value_create_int(int32 value);
+CEF_EXPORT cef_v8value_t* cef_v8value_create_int(int32_t value);
 
 ///
-// Create a new cef_v8value_t object of type unsigned int.
+/// Create a new cef_v8value_t object of type unsigned int.
 ///
-CEF_EXPORT cef_v8value_t* cef_v8value_create_uint(uint32 value);
+CEF_EXPORT cef_v8value_t* cef_v8value_create_uint(uint32_t value);
 
 ///
-// Create a new cef_v8value_t object of type double.
+/// Create a new cef_v8value_t object of type double.
 ///
 CEF_EXPORT cef_v8value_t* cef_v8value_create_double(double value);
 
 ///
-// Create a new cef_v8value_t object of type Date. This function should only be
-// called from within the scope of a cef_render_process_handler_t,
-// cef_v8handler_t or cef_v8accessor_t callback, or in combination with calling
-// enter() and exit() on a stored cef_v8context_t reference.
+/// Create a new cef_v8value_t object of type Date. This function should only be
+/// called from within the scope of a cef_render_process_handler_t,
+/// cef_v8handler_t or cef_v8accessor_t callback, or in combination with calling
+/// enter() and exit() on a stored cef_v8context_t reference.
 ///
-CEF_EXPORT cef_v8value_t* cef_v8value_create_date(const cef_time_t* date);
+CEF_EXPORT cef_v8value_t* cef_v8value_create_date(cef_basetime_t date);
 
 ///
-// Create a new cef_v8value_t object of type string.
+/// Create a new cef_v8value_t object of type string.
 ///
 CEF_EXPORT cef_v8value_t* cef_v8value_create_string(const cef_string_t* value);
 
 ///
-// Create a new cef_v8value_t object of type object with optional accessor
-// and/or interceptor. This function should only be called from within the scope
-// of a cef_render_process_handler_t, cef_v8handler_t or cef_v8accessor_t
-// callback, or in combination with calling enter() and exit() on a stored
-// cef_v8context_t reference.
+/// Create a new cef_v8value_t object of type object with optional accessor
+/// and/or interceptor. This function should only be called from within the
+/// scope of a cef_render_process_handler_t, cef_v8handler_t or cef_v8accessor_t
+/// callback, or in combination with calling enter() and exit() on a stored
+/// cef_v8context_t reference.
 ///
 CEF_EXPORT cef_v8value_t* cef_v8value_create_object(
     cef_v8accessor_t* accessor,
     cef_v8interceptor_t* interceptor);
 
 ///
-// Create a new cef_v8value_t object of type array with the specified |length|.
-// If |length| is negative the returned array will have length 0. This function
-// should only be called from within the scope of a
-// cef_render_process_handler_t, cef_v8handler_t or cef_v8accessor_t callback,
-// or in combination with calling enter() and exit() on a stored cef_v8context_t
-// reference.
+/// Create a new cef_v8value_t object of type array with the specified |length|.
+/// If |length| is negative the returned array will have length 0. This function
+/// should only be called from within the scope of a
+/// cef_render_process_handler_t, cef_v8handler_t or cef_v8accessor_t callback,
+/// or in combination with calling enter() and exit() on a stored
+/// cef_v8context_t reference.
 ///
 CEF_EXPORT cef_v8value_t* cef_v8value_create_array(int length);
 
 ///
-// Create a new cef_v8value_t object of type ArrayBuffer which wraps the
-// provided |buffer| of size |length| bytes. The ArrayBuffer is externalized,
-// meaning that it does not own |buffer|. The caller is responsible for freeing
-// |buffer| when requested via a call to cef_v8array_buffer_release_callback_t::
-// ReleaseBuffer. This function should only be called from within the scope of a
-// cef_render_process_handler_t, cef_v8handler_t or cef_v8accessor_t callback,
-// or in combination with calling enter() and exit() on a stored cef_v8context_t
-// reference.
+/// Create a new cef_v8value_t object of type ArrayBuffer which wraps the
+/// provided |buffer| of size |length| bytes. The ArrayBuffer is externalized,
+/// meaning that it does not own |buffer|. The caller is responsible for freeing
+/// |buffer| when requested via a call to
+/// cef_v8array_buffer_release_callback_t::ReleaseBuffer. This function should
+/// only be called from within the scope of a cef_render_process_handler_t,
+/// cef_v8handler_t or cef_v8accessor_t callback, or in combination with calling
+/// enter() and exit() on a stored cef_v8context_t reference.
 ///
 CEF_EXPORT cef_v8value_t* cef_v8value_create_array_buffer(
     void* buffer,
@@ -810,172 +839,182 @@
     cef_v8array_buffer_release_callback_t* release_callback);
 
 ///
-// Create a new cef_v8value_t object of type function. This function should only
-// be called from within the scope of a cef_render_process_handler_t,
-// cef_v8handler_t or cef_v8accessor_t callback, or in combination with calling
-// enter() and exit() on a stored cef_v8context_t reference.
+/// Create a new cef_v8value_t object of type function. This function should
+/// only be called from within the scope of a cef_render_process_handler_t,
+/// cef_v8handler_t or cef_v8accessor_t callback, or in combination with calling
+/// enter() and exit() on a stored cef_v8context_t reference.
 ///
 CEF_EXPORT cef_v8value_t* cef_v8value_create_function(const cef_string_t* name,
                                                       cef_v8handler_t* handler);
 
 ///
-// Structure representing a V8 stack trace handle. V8 handles can only be
-// accessed from the thread on which they are created. Valid threads for
-// creating a V8 handle include the render process main thread (TID_RENDERER)
-// and WebWorker threads. A task runner for posting tasks on the associated
-// thread can be retrieved via the cef_v8context_t::get_task_runner() function.
+/// Create a new cef_v8value_t object of type Promise. This function should only
+/// be called from within the scope of a cef_render_process_handler_t,
+/// cef_v8handler_t or cef_v8accessor_t callback, or in combination with calling
+/// enter() and exit() on a stored cef_v8context_t reference.
+///
+CEF_EXPORT cef_v8value_t* cef_v8value_create_promise(void);
+
+///
+/// Structure representing a V8 stack trace handle. V8 handles can only be
+/// accessed from the thread on which they are created. Valid threads for
+/// creating a V8 handle include the render process main thread (TID_RENDERER)
+/// and WebWorker threads. A task runner for posting tasks on the associated
+/// thread can be retrieved via the cef_v8context_t::get_task_runner() function.
 ///
 typedef struct _cef_v8stack_trace_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if the underlying handle is valid and it can be accessed
-  // on the current thread. Do not call any other functions if this function
-  // returns false (0).
+  /// Returns true (1) if the underlying handle is valid and it can be accessed
+  /// on the current thread. Do not call any other functions if this function
+  /// returns false (0).
   ///
   int(CEF_CALLBACK* is_valid)(struct _cef_v8stack_trace_t* self);
 
   ///
-  // Returns the number of stack frames.
+  /// Returns the number of stack frames.
   ///
   int(CEF_CALLBACK* get_frame_count)(struct _cef_v8stack_trace_t* self);
 
   ///
-  // Returns the stack frame at the specified 0-based index.
+  /// Returns the stack frame at the specified 0-based index.
   ///
   struct _cef_v8stack_frame_t*(
       CEF_CALLBACK* get_frame)(struct _cef_v8stack_trace_t* self, int index);
 } cef_v8stack_trace_t;
 
 ///
-// Returns the stack trace for the currently active context. |frame_limit| is
-// the maximum number of frames that will be captured.
+/// Returns the stack trace for the currently active context. |frame_limit| is
+/// the maximum number of frames that will be captured.
 ///
 CEF_EXPORT cef_v8stack_trace_t* cef_v8stack_trace_get_current(int frame_limit);
 
 ///
-// Structure representing a V8 stack frame handle. V8 handles can only be
-// accessed from the thread on which they are created. Valid threads for
-// creating a V8 handle include the render process main thread (TID_RENDERER)
-// and WebWorker threads. A task runner for posting tasks on the associated
-// thread can be retrieved via the cef_v8context_t::get_task_runner() function.
+/// Structure representing a V8 stack frame handle. V8 handles can only be
+/// accessed from the thread on which they are created. Valid threads for
+/// creating a V8 handle include the render process main thread (TID_RENDERER)
+/// and WebWorker threads. A task runner for posting tasks on the associated
+/// thread can be retrieved via the cef_v8context_t::get_task_runner() function.
 ///
 typedef struct _cef_v8stack_frame_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if the underlying handle is valid and it can be accessed
-  // on the current thread. Do not call any other functions if this function
-  // returns false (0).
+  /// Returns true (1) if the underlying handle is valid and it can be accessed
+  /// on the current thread. Do not call any other functions if this function
+  /// returns false (0).
   ///
   int(CEF_CALLBACK* is_valid)(struct _cef_v8stack_frame_t* self);
 
   ///
-  // Returns the name of the resource script that contains the function.
+  /// Returns the name of the resource script that contains the function.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_script_name)(
       struct _cef_v8stack_frame_t* self);
 
   ///
-  // Returns the name of the resource script that contains the function or the
-  // sourceURL value if the script name is undefined and its source ends with a
-  // "//@ sourceURL=..." string.
+  /// Returns the name of the resource script that contains the function or the
+  /// sourceURL value if the script name is undefined and its source ends with a
+  /// "//@ sourceURL=..." string.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_script_name_or_source_url)(
       struct _cef_v8stack_frame_t* self);
 
   ///
-  // Returns the name of the function.
+  /// Returns the name of the function.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_function_name)(
       struct _cef_v8stack_frame_t* self);
 
   ///
-  // Returns the 1-based line number for the function call or 0 if unknown.
+  /// Returns the 1-based line number for the function call or 0 if unknown.
   ///
   int(CEF_CALLBACK* get_line_number)(struct _cef_v8stack_frame_t* self);
 
   ///
-  // Returns the 1-based column offset on the line for the function call or 0 if
-  // unknown.
+  /// Returns the 1-based column offset on the line for the function call or 0
+  /// if unknown.
   ///
   int(CEF_CALLBACK* get_column)(struct _cef_v8stack_frame_t* self);
 
   ///
-  // Returns true (1) if the function was compiled using eval().
+  /// Returns true (1) if the function was compiled using eval().
   ///
   int(CEF_CALLBACK* is_eval)(struct _cef_v8stack_frame_t* self);
 
   ///
-  // Returns true (1) if the function was called as a constructor via "new".
+  /// Returns true (1) if the function was called as a constructor via "new".
   ///
   int(CEF_CALLBACK* is_constructor)(struct _cef_v8stack_frame_t* self);
 } cef_v8stack_frame_t;
 
 ///
-// Register a new V8 extension with the specified JavaScript extension code and
-// handler. Functions implemented by the handler are prototyped using the
-// keyword 'native'. The calling of a native function is restricted to the scope
-// in which the prototype of the native function is defined. This function may
-// only be called on the render process main thread.
-//
-// Example JavaScript extension code: <pre>
-//   // create the 'example' global object if it doesn't already exist.
-//   if (!example)
-//     example = {};
-//   // create the 'example.test' global object if it doesn't already exist.
-//   if (!example.test)
-//     example.test = {};
-//   (function() {
-//     // Define the function 'example.test.myfunction'.
-//     example.test.myfunction = function() {
-//       // Call CefV8Handler::Execute() with the function name 'MyFunction'
-//       // and no arguments.
-//       native function MyFunction();
-//       return MyFunction();
-//     };
-//     // Define the getter function for parameter 'example.test.myparam'.
-//     example.test.__defineGetter__('myparam', function() {
-//       // Call CefV8Handler::Execute() with the function name 'GetMyParam'
-//       // and no arguments.
-//       native function GetMyParam();
-//       return GetMyParam();
-//     });
-//     // Define the setter function for parameter 'example.test.myparam'.
-//     example.test.__defineSetter__('myparam', function(b) {
-//       // Call CefV8Handler::Execute() with the function name 'SetMyParam'
-//       // and a single argument.
-//       native function SetMyParam();
-//       if(b) SetMyParam(b);
-//     });
-//
-//     // Extension definitions can also contain normal JavaScript variables
-//     // and functions.
-//     var myint = 0;
-//     example.test.increment = function() {
-//       myint += 1;
-//       return myint;
-//     };
-//   })();
-// </pre> Example usage in the page: <pre>
-//   // Call the function.
-//   example.test.myfunction();
-//   // Set the parameter.
-//   example.test.myparam = value;
-//   // Get the parameter.
-//   value = example.test.myparam;
-//   // Call another function.
-//   example.test.increment();
-// </pre>
+/// Register a new V8 extension with the specified JavaScript extension code and
+/// handler. Functions implemented by the handler are prototyped using the
+/// keyword 'native'. The calling of a native function is restricted to the
+/// scope in which the prototype of the native function is defined. This
+/// function may only be called on the render process main thread.
+///
+/// Example JavaScript extension code: <pre>
+///   // create the 'example' global object if it doesn't already exist.
+///   if (!example)
+///     example = {};
+///   // create the 'example.test' global object if it doesn't already exist.
+///   if (!example.test)
+///     example.test = {};
+///   (function() {
+///     // Define the function 'example.test.myfunction'.
+///     example.test.myfunction = function() {
+///       // Call CefV8Handler::Execute() with the function name 'MyFunction'
+///       // and no arguments.
+///       native function MyFunction();
+///       return MyFunction();
+///     };
+///     // Define the getter function for parameter 'example.test.myparam'.
+///     example.test.__defineGetter__('myparam', function() {
+///       // Call CefV8Handler::Execute() with the function name 'GetMyParam'
+///       // and no arguments.
+///       native function GetMyParam();
+///       return GetMyParam();
+///     });
+///     // Define the setter function for parameter 'example.test.myparam'.
+///     example.test.__defineSetter__('myparam', function(b) {
+///       // Call CefV8Handler::Execute() with the function name 'SetMyParam'
+///       // and a single argument.
+///       native function SetMyParam();
+///       if(b) SetMyParam(b);
+///     });
+///
+///     // Extension definitions can also contain normal JavaScript variables
+///     // and functions.
+///     var myint = 0;
+///     example.test.increment = function() {
+///       myint += 1;
+///       return myint;
+///     };
+///   })();
+/// </pre>
+///
+/// Example usage in the page: <pre>
+///   // Call the function.
+///   example.test.myfunction();
+///   // Set the parameter.
+///   example.test.myparam = value;
+///   // Get the parameter.
+///   value = example.test.myparam;
+///   // Call another function.
+///   example.test.increment();
+/// </pre>
 ///
 CEF_EXPORT int cef_register_extension(const cef_string_t* extension_name,
                                       const cef_string_t* javascript_code,
diff --git a/src/include/capi/cef_values_capi.h b/src/include/capi/cef_values_capi.h
index c12867b..0534745 100644
--- a/src/include/capi/cef_values_capi.h
+++ b/src/include/capi/cef_values_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=22f935968cd7f2549def42f5d84694311bde125e$
+// $hash=7b8fee9d4a0530782ed62f5741820708f110e24e$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_VALUES_CAPI_H_
@@ -51,226 +51,234 @@
 struct _cef_list_value_t;
 
 ///
-// Structure that wraps other data value types. Complex types (binary,
-// dictionary and list) will be referenced but not owned by this object. Can be
-// used on any process and thread.
+/// Structure that wraps other data value types. Complex types (binary,
+/// dictionary and list) will be referenced but not owned by this object. Can be
+/// used on any process and thread.
 ///
 typedef struct _cef_value_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if the underlying data is valid. This will always be true
-  // (1) for simple types. For complex types (binary, dictionary and list) the
-  // underlying data may become invalid if owned by another object (e.g. list or
-  // dictionary) and that other object is then modified or destroyed. This value
-  // object can be re-used by calling Set*() even if the underlying data is
-  // invalid.
+  /// Returns true (1) if the underlying data is valid. This will always be true
+  /// (1) for simple types. For complex types (binary, dictionary and list) the
+  /// underlying data may become invalid if owned by another object (e.g. list
+  /// or dictionary) and that other object is then modified or destroyed. This
+  /// value object can be re-used by calling Set*() even if the underlying data
+  /// is invalid.
   ///
   int(CEF_CALLBACK* is_valid)(struct _cef_value_t* self);
 
   ///
-  // Returns true (1) if the underlying data is owned by another object.
+  /// Returns true (1) if the underlying data is owned by another object.
   ///
   int(CEF_CALLBACK* is_owned)(struct _cef_value_t* self);
 
   ///
-  // Returns true (1) if the underlying data is read-only. Some APIs may expose
-  // read-only objects.
+  /// Returns true (1) if the underlying data is read-only. Some APIs may expose
+  /// read-only objects.
   ///
   int(CEF_CALLBACK* is_read_only)(struct _cef_value_t* self);
 
   ///
-  // Returns true (1) if this object and |that| object have the same underlying
-  // data. If true (1) modifications to this object will also affect |that|
-  // object and vice-versa.
+  /// Returns true (1) if this object and |that| object have the same underlying
+  /// data. If true (1) modifications to this object will also affect |that|
+  /// object and vice-versa.
   ///
   int(CEF_CALLBACK* is_same)(struct _cef_value_t* self,
                              struct _cef_value_t* that);
 
   ///
-  // Returns true (1) if this object and |that| object have an equivalent
-  // underlying value but are not necessarily the same object.
+  /// Returns true (1) if this object and |that| object have an equivalent
+  /// underlying value but are not necessarily the same object.
   ///
   int(CEF_CALLBACK* is_equal)(struct _cef_value_t* self,
                               struct _cef_value_t* that);
 
   ///
-  // Returns a copy of this object. The underlying data will also be copied.
+  /// Returns a copy of this object. The underlying data will also be copied.
   ///
   struct _cef_value_t*(CEF_CALLBACK* copy)(struct _cef_value_t* self);
 
   ///
-  // Returns the underlying value type.
+  /// Returns the underlying value type.
   ///
   cef_value_type_t(CEF_CALLBACK* get_type)(struct _cef_value_t* self);
 
   ///
-  // Returns the underlying value as type bool.
+  /// Returns the underlying value as type bool.
   ///
   int(CEF_CALLBACK* get_bool)(struct _cef_value_t* self);
 
   ///
-  // Returns the underlying value as type int.
+  /// Returns the underlying value as type int.
   ///
   int(CEF_CALLBACK* get_int)(struct _cef_value_t* self);
 
   ///
-  // Returns the underlying value as type double.
+  /// Returns the underlying value as type double.
   ///
   double(CEF_CALLBACK* get_double)(struct _cef_value_t* self);
 
   ///
-  // Returns the underlying value as type string.
+  /// Returns the underlying value as type string.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_string)(struct _cef_value_t* self);
 
   ///
-  // Returns the underlying value as type binary. The returned reference may
-  // become invalid if the value is owned by another object or if ownership is
-  // transferred to another object in the future. To maintain a reference to the
-  // value after assigning ownership to a dictionary or list pass this object to
-  // the set_value() function instead of passing the returned reference to
-  // set_binary().
+  /// Returns the underlying value as type binary. The returned reference may
+  /// become invalid if the value is owned by another object or if ownership is
+  /// transferred to another object in the future. To maintain a reference to
+  /// the value after assigning ownership to a dictionary or list pass this
+  /// object to the set_value() function instead of passing the returned
+  /// reference to set_binary().
   ///
   struct _cef_binary_value_t*(CEF_CALLBACK* get_binary)(
       struct _cef_value_t* self);
 
   ///
-  // Returns the underlying value as type dictionary. The returned reference may
-  // become invalid if the value is owned by another object or if ownership is
-  // transferred to another object in the future. To maintain a reference to the
-  // value after assigning ownership to a dictionary or list pass this object to
-  // the set_value() function instead of passing the returned reference to
-  // set_dictionary().
+  /// Returns the underlying value as type dictionary. The returned reference
+  /// may become invalid if the value is owned by another object or if ownership
+  /// is transferred to another object in the future. To maintain a reference to
+  /// the value after assigning ownership to a dictionary or list pass this
+  /// object to the set_value() function instead of passing the returned
+  /// reference to set_dictionary().
   ///
   struct _cef_dictionary_value_t*(CEF_CALLBACK* get_dictionary)(
       struct _cef_value_t* self);
 
   ///
-  // Returns the underlying value as type list. The returned reference may
-  // become invalid if the value is owned by another object or if ownership is
-  // transferred to another object in the future. To maintain a reference to the
-  // value after assigning ownership to a dictionary or list pass this object to
-  // the set_value() function instead of passing the returned reference to
-  // set_list().
+  /// Returns the underlying value as type list. The returned reference may
+  /// become invalid if the value is owned by another object or if ownership is
+  /// transferred to another object in the future. To maintain a reference to
+  /// the value after assigning ownership to a dictionary or list pass this
+  /// object to the set_value() function instead of passing the returned
+  /// reference to set_list().
   ///
   struct _cef_list_value_t*(CEF_CALLBACK* get_list)(struct _cef_value_t* self);
 
   ///
-  // Sets the underlying value as type null. Returns true (1) if the value was
-  // set successfully.
+  /// Sets the underlying value as type null. Returns true (1) if the value was
+  /// set successfully.
   ///
   int(CEF_CALLBACK* set_null)(struct _cef_value_t* self);
 
   ///
-  // Sets the underlying value as type bool. Returns true (1) if the value was
-  // set successfully.
+  /// Sets the underlying value as type bool. Returns true (1) if the value was
+  /// set successfully.
   ///
   int(CEF_CALLBACK* set_bool)(struct _cef_value_t* self, int value);
 
   ///
-  // Sets the underlying value as type int. Returns true (1) if the value was
-  // set successfully.
+  /// Sets the underlying value as type int. Returns true (1) if the value was
+  /// set successfully.
   ///
   int(CEF_CALLBACK* set_int)(struct _cef_value_t* self, int value);
 
   ///
-  // Sets the underlying value as type double. Returns true (1) if the value was
-  // set successfully.
+  /// Sets the underlying value as type double. Returns true (1) if the value
+  /// was set successfully.
   ///
   int(CEF_CALLBACK* set_double)(struct _cef_value_t* self, double value);
 
   ///
-  // Sets the underlying value as type string. Returns true (1) if the value was
-  // set successfully.
+  /// Sets the underlying value as type string. Returns true (1) if the value
+  /// was set successfully.
   ///
   int(CEF_CALLBACK* set_string)(struct _cef_value_t* self,
                                 const cef_string_t* value);
 
   ///
-  // Sets the underlying value as type binary. Returns true (1) if the value was
-  // set successfully. This object keeps a reference to |value| and ownership of
-  // the underlying data remains unchanged.
+  /// Sets the underlying value as type binary. Returns true (1) if the value
+  /// was set successfully. This object keeps a reference to |value| and
+  /// ownership of the underlying data remains unchanged.
   ///
   int(CEF_CALLBACK* set_binary)(struct _cef_value_t* self,
                                 struct _cef_binary_value_t* value);
 
   ///
-  // Sets the underlying value as type dict. Returns true (1) if the value was
-  // set successfully. This object keeps a reference to |value| and ownership of
-  // the underlying data remains unchanged.
+  /// Sets the underlying value as type dict. Returns true (1) if the value was
+  /// set successfully. This object keeps a reference to |value| and ownership
+  /// of the underlying data remains unchanged.
   ///
   int(CEF_CALLBACK* set_dictionary)(struct _cef_value_t* self,
                                     struct _cef_dictionary_value_t* value);
 
   ///
-  // Sets the underlying value as type list. Returns true (1) if the value was
-  // set successfully. This object keeps a reference to |value| and ownership of
-  // the underlying data remains unchanged.
+  /// Sets the underlying value as type list. Returns true (1) if the value was
+  /// set successfully. This object keeps a reference to |value| and ownership
+  /// of the underlying data remains unchanged.
   ///
   int(CEF_CALLBACK* set_list)(struct _cef_value_t* self,
                               struct _cef_list_value_t* value);
 } cef_value_t;
 
 ///
-// Creates a new object.
+/// Creates a new object.
 ///
-CEF_EXPORT cef_value_t* cef_value_create();
+CEF_EXPORT cef_value_t* cef_value_create(void);
 
 ///
-// Structure representing a binary value. Can be used on any process and thread.
+/// Structure representing a binary value. Can be used on any process and
+/// thread.
 ///
 typedef struct _cef_binary_value_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if this object is valid. This object may become invalid if
-  // the underlying data is owned by another object (e.g. list or dictionary)
-  // and that other object is then modified or destroyed. Do not call any other
-  // functions if this function returns false (0).
+  /// Returns true (1) if this object is valid. This object may become invalid
+  /// if the underlying data is owned by another object (e.g. list or
+  /// dictionary) and that other object is then modified or destroyed. Do not
+  /// call any other functions if this function returns false (0).
   ///
   int(CEF_CALLBACK* is_valid)(struct _cef_binary_value_t* self);
 
   ///
-  // Returns true (1) if this object is currently owned by another object.
+  /// Returns true (1) if this object is currently owned by another object.
   ///
   int(CEF_CALLBACK* is_owned)(struct _cef_binary_value_t* self);
 
   ///
-  // Returns true (1) if this object and |that| object have the same underlying
-  // data.
+  /// Returns true (1) if this object and |that| object have the same underlying
+  /// data.
   ///
   int(CEF_CALLBACK* is_same)(struct _cef_binary_value_t* self,
                              struct _cef_binary_value_t* that);
 
   ///
-  // Returns true (1) if this object and |that| object have an equivalent
-  // underlying value but are not necessarily the same object.
+  /// Returns true (1) if this object and |that| object have an equivalent
+  /// underlying value but are not necessarily the same object.
   ///
   int(CEF_CALLBACK* is_equal)(struct _cef_binary_value_t* self,
                               struct _cef_binary_value_t* that);
 
   ///
-  // Returns a copy of this object. The data in this object will also be copied.
+  /// Returns a copy of this object. The data in this object will also be
+  /// copied.
   ///
   struct _cef_binary_value_t*(CEF_CALLBACK* copy)(
       struct _cef_binary_value_t* self);
 
   ///
-  // Returns the data size.
+  /// Returns a pointer to the beginning of the memory block. The returned
+  /// pointer is valid as long as the cef_binary_value_t is alive.
+  ///
+  const void*(CEF_CALLBACK* get_raw_data)(struct _cef_binary_value_t* self);
+
+  ///
+  /// Returns the data size.
   ///
   size_t(CEF_CALLBACK* get_size)(struct _cef_binary_value_t* self);
 
   ///
-  // Read up to |buffer_size| number of bytes into |buffer|. Reading begins at
-  // the specified byte |data_offset|. Returns the number of bytes read.
+  /// Read up to |buffer_size| number of bytes into |buffer|. Reading begins at
+  /// the specified byte |data_offset|. Returns the number of bytes read.
   ///
   size_t(CEF_CALLBACK* get_data)(struct _cef_binary_value_t* self,
                                  void* buffer,
@@ -279,130 +287,130 @@
 } cef_binary_value_t;
 
 ///
-// Creates a new object that is not owned by any other object. The specified
-// |data| will be copied.
+/// Creates a new object that is not owned by any other object. The specified
+/// |data| will be copied.
 ///
 CEF_EXPORT cef_binary_value_t* cef_binary_value_create(const void* data,
                                                        size_t data_size);
 
 ///
-// Structure representing a dictionary value. Can be used on any process and
-// thread.
+/// Structure representing a dictionary value. Can be used on any process and
+/// thread.
 ///
 typedef struct _cef_dictionary_value_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if this object is valid. This object may become invalid if
-  // the underlying data is owned by another object (e.g. list or dictionary)
-  // and that other object is then modified or destroyed. Do not call any other
-  // functions if this function returns false (0).
+  /// Returns true (1) if this object is valid. This object may become invalid
+  /// if the underlying data is owned by another object (e.g. list or
+  /// dictionary) and that other object is then modified or destroyed. Do not
+  /// call any other functions if this function returns false (0).
   ///
   int(CEF_CALLBACK* is_valid)(struct _cef_dictionary_value_t* self);
 
   ///
-  // Returns true (1) if this object is currently owned by another object.
+  /// Returns true (1) if this object is currently owned by another object.
   ///
   int(CEF_CALLBACK* is_owned)(struct _cef_dictionary_value_t* self);
 
   ///
-  // Returns true (1) if the values of this object are read-only. Some APIs may
-  // expose read-only objects.
+  /// Returns true (1) if the values of this object are read-only. Some APIs may
+  /// expose read-only objects.
   ///
   int(CEF_CALLBACK* is_read_only)(struct _cef_dictionary_value_t* self);
 
   ///
-  // Returns true (1) if this object and |that| object have the same underlying
-  // data. If true (1) modifications to this object will also affect |that|
-  // object and vice-versa.
+  /// Returns true (1) if this object and |that| object have the same underlying
+  /// data. If true (1) modifications to this object will also affect |that|
+  /// object and vice-versa.
   ///
   int(CEF_CALLBACK* is_same)(struct _cef_dictionary_value_t* self,
                              struct _cef_dictionary_value_t* that);
 
   ///
-  // Returns true (1) if this object and |that| object have an equivalent
-  // underlying value but are not necessarily the same object.
+  /// Returns true (1) if this object and |that| object have an equivalent
+  /// underlying value but are not necessarily the same object.
   ///
   int(CEF_CALLBACK* is_equal)(struct _cef_dictionary_value_t* self,
                               struct _cef_dictionary_value_t* that);
 
   ///
-  // Returns a writable copy of this object. If |exclude_NULL_children| is true
-  // (1) any NULL dictionaries or lists will be excluded from the copy.
+  /// Returns a writable copy of this object. If |exclude_NULL_children| is true
+  /// (1) any NULL dictionaries or lists will be excluded from the copy.
   ///
   struct _cef_dictionary_value_t*(CEF_CALLBACK* copy)(
       struct _cef_dictionary_value_t* self,
       int exclude_empty_children);
 
   ///
-  // Returns the number of values.
+  /// Returns the number of values.
   ///
   size_t(CEF_CALLBACK* get_size)(struct _cef_dictionary_value_t* self);
 
   ///
-  // Removes all values. Returns true (1) on success.
+  /// Removes all values. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* clear)(struct _cef_dictionary_value_t* self);
 
   ///
-  // Returns true (1) if the current dictionary has a value for the given key.
+  /// Returns true (1) if the current dictionary has a value for the given key.
   ///
   int(CEF_CALLBACK* has_key)(struct _cef_dictionary_value_t* self,
                              const cef_string_t* key);
 
   ///
-  // Reads all keys for this dictionary into the specified vector.
+  /// Reads all keys for this dictionary into the specified vector.
   ///
   int(CEF_CALLBACK* get_keys)(struct _cef_dictionary_value_t* self,
                               cef_string_list_t keys);
 
   ///
-  // Removes the value at the specified key. Returns true (1) is the value was
-  // removed successfully.
+  /// Removes the value at the specified key. Returns true (1) is the value was
+  /// removed successfully.
   ///
   int(CEF_CALLBACK* remove)(struct _cef_dictionary_value_t* self,
                             const cef_string_t* key);
 
   ///
-  // Returns the value type for the specified key.
+  /// Returns the value type for the specified key.
   ///
   cef_value_type_t(CEF_CALLBACK* get_type)(struct _cef_dictionary_value_t* self,
                                            const cef_string_t* key);
 
   ///
-  // Returns the value at the specified key. For simple types the returned value
-  // will copy existing data and modifications to the value will not modify this
-  // object. For complex types (binary, dictionary and list) the returned value
-  // will reference existing data and modifications to the value will modify
-  // this object.
+  /// Returns the value at the specified key. For simple types the returned
+  /// value will copy existing data and modifications to the value will not
+  /// modify this object. For complex types (binary, dictionary and list) the
+  /// returned value will reference existing data and modifications to the value
+  /// will modify this object.
   ///
   struct _cef_value_t*(CEF_CALLBACK* get_value)(
       struct _cef_dictionary_value_t* self,
       const cef_string_t* key);
 
   ///
-  // Returns the value at the specified key as type bool.
+  /// Returns the value at the specified key as type bool.
   ///
   int(CEF_CALLBACK* get_bool)(struct _cef_dictionary_value_t* self,
                               const cef_string_t* key);
 
   ///
-  // Returns the value at the specified key as type int.
+  /// Returns the value at the specified key as type int.
   ///
   int(CEF_CALLBACK* get_int)(struct _cef_dictionary_value_t* self,
                              const cef_string_t* key);
 
   ///
-  // Returns the value at the specified key as type double.
+  /// Returns the value at the specified key as type double.
   ///
   double(CEF_CALLBACK* get_double)(struct _cef_dictionary_value_t* self,
                                    const cef_string_t* key);
 
   ///
-  // Returns the value at the specified key as type string.
+  /// Returns the value at the specified key as type string.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_string)(
@@ -410,110 +418,110 @@
       const cef_string_t* key);
 
   ///
-  // Returns the value at the specified key as type binary. The returned value
-  // will reference existing data.
+  /// Returns the value at the specified key as type binary. The returned value
+  /// will reference existing data.
   ///
   struct _cef_binary_value_t*(CEF_CALLBACK* get_binary)(
       struct _cef_dictionary_value_t* self,
       const cef_string_t* key);
 
   ///
-  // Returns the value at the specified key as type dictionary. The returned
-  // value will reference existing data and modifications to the value will
-  // modify this object.
+  /// Returns the value at the specified key as type dictionary. The returned
+  /// value will reference existing data and modifications to the value will
+  /// modify this object.
   ///
   struct _cef_dictionary_value_t*(CEF_CALLBACK* get_dictionary)(
       struct _cef_dictionary_value_t* self,
       const cef_string_t* key);
 
   ///
-  // Returns the value at the specified key as type list. The returned value
-  // will reference existing data and modifications to the value will modify
-  // this object.
+  /// Returns the value at the specified key as type list. The returned value
+  /// will reference existing data and modifications to the value will modify
+  /// this object.
   ///
   struct _cef_list_value_t*(CEF_CALLBACK* get_list)(
       struct _cef_dictionary_value_t* self,
       const cef_string_t* key);
 
   ///
-  // Sets the value at the specified key. Returns true (1) if the value was set
-  // successfully. If |value| represents simple data then the underlying data
-  // will be copied and modifications to |value| will not modify this object. If
-  // |value| represents complex data (binary, dictionary or list) then the
-  // underlying data will be referenced and modifications to |value| will modify
-  // this object.
+  /// Sets the value at the specified key. Returns true (1) if the value was set
+  /// successfully. If |value| represents simple data then the underlying data
+  /// will be copied and modifications to |value| will not modify this object.
+  /// If |value| represents complex data (binary, dictionary or list) then the
+  /// underlying data will be referenced and modifications to |value| will
+  /// modify this object.
   ///
   int(CEF_CALLBACK* set_value)(struct _cef_dictionary_value_t* self,
                                const cef_string_t* key,
                                struct _cef_value_t* value);
 
   ///
-  // Sets the value at the specified key as type null. Returns true (1) if the
-  // value was set successfully.
+  /// Sets the value at the specified key as type null. Returns true (1) if the
+  /// value was set successfully.
   ///
   int(CEF_CALLBACK* set_null)(struct _cef_dictionary_value_t* self,
                               const cef_string_t* key);
 
   ///
-  // Sets the value at the specified key as type bool. Returns true (1) if the
-  // value was set successfully.
+  /// Sets the value at the specified key as type bool. Returns true (1) if the
+  /// value was set successfully.
   ///
   int(CEF_CALLBACK* set_bool)(struct _cef_dictionary_value_t* self,
                               const cef_string_t* key,
                               int value);
 
   ///
-  // Sets the value at the specified key as type int. Returns true (1) if the
-  // value was set successfully.
+  /// Sets the value at the specified key as type int. Returns true (1) if the
+  /// value was set successfully.
   ///
   int(CEF_CALLBACK* set_int)(struct _cef_dictionary_value_t* self,
                              const cef_string_t* key,
                              int value);
 
   ///
-  // Sets the value at the specified key as type double. Returns true (1) if the
-  // value was set successfully.
+  /// Sets the value at the specified key as type double. Returns true (1) if
+  /// the value was set successfully.
   ///
   int(CEF_CALLBACK* set_double)(struct _cef_dictionary_value_t* self,
                                 const cef_string_t* key,
                                 double value);
 
   ///
-  // Sets the value at the specified key as type string. Returns true (1) if the
-  // value was set successfully.
+  /// Sets the value at the specified key as type string. Returns true (1) if
+  /// the value was set successfully.
   ///
   int(CEF_CALLBACK* set_string)(struct _cef_dictionary_value_t* self,
                                 const cef_string_t* key,
                                 const cef_string_t* value);
 
   ///
-  // Sets the value at the specified key as type binary. Returns true (1) if the
-  // value was set successfully. If |value| is currently owned by another object
-  // then the value will be copied and the |value| reference will not change.
-  // Otherwise, ownership will be transferred to this object and the |value|
-  // reference will be invalidated.
+  /// Sets the value at the specified key as type binary. Returns true (1) if
+  /// the value was set successfully. If |value| is currently owned by another
+  /// object then the value will be copied and the |value| reference will not
+  /// change. Otherwise, ownership will be transferred to this object and the
+  /// |value| reference will be invalidated.
   ///
   int(CEF_CALLBACK* set_binary)(struct _cef_dictionary_value_t* self,
                                 const cef_string_t* key,
                                 struct _cef_binary_value_t* value);
 
   ///
-  // Sets the value at the specified key as type dict. Returns true (1) if the
-  // value was set successfully. If |value| is currently owned by another object
-  // then the value will be copied and the |value| reference will not change.
-  // Otherwise, ownership will be transferred to this object and the |value|
-  // reference will be invalidated.
+  /// Sets the value at the specified key as type dict. Returns true (1) if the
+  /// value was set successfully. If |value| is currently owned by another
+  /// object then the value will be copied and the |value| reference will not
+  /// change. Otherwise, ownership will be transferred to this object and the
+  /// |value| reference will be invalidated.
   ///
   int(CEF_CALLBACK* set_dictionary)(struct _cef_dictionary_value_t* self,
                                     const cef_string_t* key,
                                     struct _cef_dictionary_value_t* value);
 
   ///
-  // Sets the value at the specified key as type list. Returns true (1) if the
-  // value was set successfully. If |value| is currently owned by another object
-  // then the value will be copied and the |value| reference will not change.
-  // Otherwise, ownership will be transferred to this object and the |value|
-  // reference will be invalidated.
+  /// Sets the value at the specified key as type list. Returns true (1) if the
+  /// value was set successfully. If |value| is currently owned by another
+  /// object then the value will be copied and the |value| reference will not
+  /// change. Otherwise, ownership will be transferred to this object and the
+  /// |value| reference will be invalidated.
   ///
   int(CEF_CALLBACK* set_list)(struct _cef_dictionary_value_t* self,
                               const cef_string_t* key,
@@ -521,220 +529,220 @@
 } cef_dictionary_value_t;
 
 ///
-// Creates a new object that is not owned by any other object.
+/// Creates a new object that is not owned by any other object.
 ///
-CEF_EXPORT cef_dictionary_value_t* cef_dictionary_value_create();
+CEF_EXPORT cef_dictionary_value_t* cef_dictionary_value_create(void);
 
 ///
-// Structure representing a list value. Can be used on any process and thread.
+/// Structure representing a list value. Can be used on any process and thread.
 ///
 typedef struct _cef_list_value_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns true (1) if this object is valid. This object may become invalid if
-  // the underlying data is owned by another object (e.g. list or dictionary)
-  // and that other object is then modified or destroyed. Do not call any other
-  // functions if this function returns false (0).
+  /// Returns true (1) if this object is valid. This object may become invalid
+  /// if the underlying data is owned by another object (e.g. list or
+  /// dictionary) and that other object is then modified or destroyed. Do not
+  /// call any other functions if this function returns false (0).
   ///
   int(CEF_CALLBACK* is_valid)(struct _cef_list_value_t* self);
 
   ///
-  // Returns true (1) if this object is currently owned by another object.
+  /// Returns true (1) if this object is currently owned by another object.
   ///
   int(CEF_CALLBACK* is_owned)(struct _cef_list_value_t* self);
 
   ///
-  // Returns true (1) if the values of this object are read-only. Some APIs may
-  // expose read-only objects.
+  /// Returns true (1) if the values of this object are read-only. Some APIs may
+  /// expose read-only objects.
   ///
   int(CEF_CALLBACK* is_read_only)(struct _cef_list_value_t* self);
 
   ///
-  // Returns true (1) if this object and |that| object have the same underlying
-  // data. If true (1) modifications to this object will also affect |that|
-  // object and vice-versa.
+  /// Returns true (1) if this object and |that| object have the same underlying
+  /// data. If true (1) modifications to this object will also affect |that|
+  /// object and vice-versa.
   ///
   int(CEF_CALLBACK* is_same)(struct _cef_list_value_t* self,
                              struct _cef_list_value_t* that);
 
   ///
-  // Returns true (1) if this object and |that| object have an equivalent
-  // underlying value but are not necessarily the same object.
+  /// Returns true (1) if this object and |that| object have an equivalent
+  /// underlying value but are not necessarily the same object.
   ///
   int(CEF_CALLBACK* is_equal)(struct _cef_list_value_t* self,
                               struct _cef_list_value_t* that);
 
   ///
-  // Returns a writable copy of this object.
+  /// Returns a writable copy of this object.
   ///
   struct _cef_list_value_t*(CEF_CALLBACK* copy)(struct _cef_list_value_t* self);
 
   ///
-  // Sets the number of values. If the number of values is expanded all new
-  // value slots will default to type null. Returns true (1) on success.
+  /// Sets the number of values. If the number of values is expanded all new
+  /// value slots will default to type null. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* set_size)(struct _cef_list_value_t* self, size_t size);
 
   ///
-  // Returns the number of values.
+  /// Returns the number of values.
   ///
   size_t(CEF_CALLBACK* get_size)(struct _cef_list_value_t* self);
 
   ///
-  // Removes all values. Returns true (1) on success.
+  /// Removes all values. Returns true (1) on success.
   ///
   int(CEF_CALLBACK* clear)(struct _cef_list_value_t* self);
 
   ///
-  // Removes the value at the specified index.
+  /// Removes the value at the specified index.
   ///
   int(CEF_CALLBACK* remove)(struct _cef_list_value_t* self, size_t index);
 
   ///
-  // Returns the value type at the specified index.
+  /// Returns the value type at the specified index.
   ///
   cef_value_type_t(CEF_CALLBACK* get_type)(struct _cef_list_value_t* self,
                                            size_t index);
 
   ///
-  // Returns the value at the specified index. For simple types the returned
-  // value will copy existing data and modifications to the value will not
-  // modify this object. For complex types (binary, dictionary and list) the
-  // returned value will reference existing data and modifications to the value
-  // will modify this object.
+  /// Returns the value at the specified index. For simple types the returned
+  /// value will copy existing data and modifications to the value will not
+  /// modify this object. For complex types (binary, dictionary and list) the
+  /// returned value will reference existing data and modifications to the value
+  /// will modify this object.
   ///
   struct _cef_value_t*(CEF_CALLBACK* get_value)(struct _cef_list_value_t* self,
                                                 size_t index);
 
   ///
-  // Returns the value at the specified index as type bool.
+  /// Returns the value at the specified index as type bool.
   ///
   int(CEF_CALLBACK* get_bool)(struct _cef_list_value_t* self, size_t index);
 
   ///
-  // Returns the value at the specified index as type int.
+  /// Returns the value at the specified index as type int.
   ///
   int(CEF_CALLBACK* get_int)(struct _cef_list_value_t* self, size_t index);
 
   ///
-  // Returns the value at the specified index as type double.
+  /// Returns the value at the specified index as type double.
   ///
   double(CEF_CALLBACK* get_double)(struct _cef_list_value_t* self,
                                    size_t index);
 
   ///
-  // Returns the value at the specified index as type string.
+  /// Returns the value at the specified index as type string.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(
       CEF_CALLBACK* get_string)(struct _cef_list_value_t* self, size_t index);
 
   ///
-  // Returns the value at the specified index as type binary. The returned value
-  // will reference existing data.
+  /// Returns the value at the specified index as type binary. The returned
+  /// value will reference existing data.
   ///
   struct _cef_binary_value_t*(
       CEF_CALLBACK* get_binary)(struct _cef_list_value_t* self, size_t index);
 
   ///
-  // Returns the value at the specified index as type dictionary. The returned
-  // value will reference existing data and modifications to the value will
-  // modify this object.
+  /// Returns the value at the specified index as type dictionary. The returned
+  /// value will reference existing data and modifications to the value will
+  /// modify this object.
   ///
   struct _cef_dictionary_value_t*(CEF_CALLBACK* get_dictionary)(
       struct _cef_list_value_t* self,
       size_t index);
 
   ///
-  // Returns the value at the specified index as type list. The returned value
-  // will reference existing data and modifications to the value will modify
-  // this object.
+  /// Returns the value at the specified index as type list. The returned value
+  /// will reference existing data and modifications to the value will modify
+  /// this object.
   ///
   struct _cef_list_value_t*(
       CEF_CALLBACK* get_list)(struct _cef_list_value_t* self, size_t index);
 
   ///
-  // Sets the value at the specified index. Returns true (1) if the value was
-  // set successfully. If |value| represents simple data then the underlying
-  // data will be copied and modifications to |value| will not modify this
-  // object. If |value| represents complex data (binary, dictionary or list)
-  // then the underlying data will be referenced and modifications to |value|
-  // will modify this object.
+  /// Sets the value at the specified index. Returns true (1) if the value was
+  /// set successfully. If |value| represents simple data then the underlying
+  /// data will be copied and modifications to |value| will not modify this
+  /// object. If |value| represents complex data (binary, dictionary or list)
+  /// then the underlying data will be referenced and modifications to |value|
+  /// will modify this object.
   ///
   int(CEF_CALLBACK* set_value)(struct _cef_list_value_t* self,
                                size_t index,
                                struct _cef_value_t* value);
 
   ///
-  // Sets the value at the specified index as type null. Returns true (1) if the
-  // value was set successfully.
+  /// Sets the value at the specified index as type null. Returns true (1) if
+  /// the value was set successfully.
   ///
   int(CEF_CALLBACK* set_null)(struct _cef_list_value_t* self, size_t index);
 
   ///
-  // Sets the value at the specified index as type bool. Returns true (1) if the
-  // value was set successfully.
+  /// Sets the value at the specified index as type bool. Returns true (1) if
+  /// the value was set successfully.
   ///
   int(CEF_CALLBACK* set_bool)(struct _cef_list_value_t* self,
                               size_t index,
                               int value);
 
   ///
-  // Sets the value at the specified index as type int. Returns true (1) if the
-  // value was set successfully.
+  /// Sets the value at the specified index as type int. Returns true (1) if the
+  /// value was set successfully.
   ///
   int(CEF_CALLBACK* set_int)(struct _cef_list_value_t* self,
                              size_t index,
                              int value);
 
   ///
-  // Sets the value at the specified index as type double. Returns true (1) if
-  // the value was set successfully.
+  /// Sets the value at the specified index as type double. Returns true (1) if
+  /// the value was set successfully.
   ///
   int(CEF_CALLBACK* set_double)(struct _cef_list_value_t* self,
                                 size_t index,
                                 double value);
 
   ///
-  // Sets the value at the specified index as type string. Returns true (1) if
-  // the value was set successfully.
+  /// Sets the value at the specified index as type string. Returns true (1) if
+  /// the value was set successfully.
   ///
   int(CEF_CALLBACK* set_string)(struct _cef_list_value_t* self,
                                 size_t index,
                                 const cef_string_t* value);
 
   ///
-  // Sets the value at the specified index as type binary. Returns true (1) if
-  // the value was set successfully. If |value| is currently owned by another
-  // object then the value will be copied and the |value| reference will not
-  // change. Otherwise, ownership will be transferred to this object and the
-  // |value| reference will be invalidated.
+  /// Sets the value at the specified index as type binary. Returns true (1) if
+  /// the value was set successfully. If |value| is currently owned by another
+  /// object then the value will be copied and the |value| reference will not
+  /// change. Otherwise, ownership will be transferred to this object and the
+  /// |value| reference will be invalidated.
   ///
   int(CEF_CALLBACK* set_binary)(struct _cef_list_value_t* self,
                                 size_t index,
                                 struct _cef_binary_value_t* value);
 
   ///
-  // Sets the value at the specified index as type dict. Returns true (1) if the
-  // value was set successfully. If |value| is currently owned by another object
-  // then the value will be copied and the |value| reference will not change.
-  // Otherwise, ownership will be transferred to this object and the |value|
-  // reference will be invalidated.
+  /// Sets the value at the specified index as type dict. Returns true (1) if
+  /// the value was set successfully. If |value| is currently owned by another
+  /// object then the value will be copied and the |value| reference will not
+  /// change. Otherwise, ownership will be transferred to this object and the
+  /// |value| reference will be invalidated.
   ///
   int(CEF_CALLBACK* set_dictionary)(struct _cef_list_value_t* self,
                                     size_t index,
                                     struct _cef_dictionary_value_t* value);
 
   ///
-  // Sets the value at the specified index as type list. Returns true (1) if the
-  // value was set successfully. If |value| is currently owned by another object
-  // then the value will be copied and the |value| reference will not change.
-  // Otherwise, ownership will be transferred to this object and the |value|
-  // reference will be invalidated.
+  /// Sets the value at the specified index as type list. Returns true (1) if
+  /// the value was set successfully. If |value| is currently owned by another
+  /// object then the value will be copied and the |value| reference will not
+  /// change. Otherwise, ownership will be transferred to this object and the
+  /// |value| reference will be invalidated.
   ///
   int(CEF_CALLBACK* set_list)(struct _cef_list_value_t* self,
                               size_t index,
@@ -742,9 +750,9 @@
 } cef_list_value_t;
 
 ///
-// Creates a new object that is not owned by any other object.
+/// Creates a new object that is not owned by any other object.
 ///
-CEF_EXPORT cef_list_value_t* cef_list_value_create();
+CEF_EXPORT cef_list_value_t* cef_list_value_create(void);
 
 #ifdef __cplusplus
 }
diff --git a/src/include/capi/cef_waitable_event_capi.h b/src/include/capi/cef_waitable_event_capi.h
index e046586..9e8bc1b 100644
--- a/src/include/capi/cef_waitable_event_capi.h
+++ b/src/include/capi/cef_waitable_event_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=aedfa5758cbf37dff244c065d55d273231470877$
+// $hash=be3741396459ccf1337f319965ba1dc509142536$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_WAITABLE_EVENT_CAPI_H_
@@ -47,64 +47,64 @@
 #endif
 
 ///
-// WaitableEvent is a thread synchronization tool that allows one thread to wait
-// for another thread to finish some work. This is equivalent to using a
-// Lock+ConditionVariable to protect a simple boolean value. However, using
-// WaitableEvent in conjunction with a Lock to wait for a more complex state
-// change (e.g., for an item to be added to a queue) is not recommended. In that
-// case consider using a ConditionVariable instead of a WaitableEvent. It is
-// safe to create and/or signal a WaitableEvent from any thread. Blocking on a
-// WaitableEvent by calling the *wait() functions is not allowed on the browser
-// process UI or IO threads.
+/// WaitableEvent is a thread synchronization tool that allows one thread to
+/// wait for another thread to finish some work. This is equivalent to using a
+/// Lock+ConditionVariable to protect a simple boolean value. However, using
+/// WaitableEvent in conjunction with a Lock to wait for a more complex state
+/// change (e.g., for an item to be added to a queue) is not recommended. In
+/// that case consider using a ConditionVariable instead of a WaitableEvent. It
+/// is safe to create and/or signal a WaitableEvent from any thread. Blocking on
+/// a WaitableEvent by calling the *wait() functions is not allowed on the
+/// browser process UI or IO threads.
 ///
 typedef struct _cef_waitable_event_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Put the event in the un-signaled state.
+  /// Put the event in the un-signaled state.
   ///
   void(CEF_CALLBACK* reset)(struct _cef_waitable_event_t* self);
 
   ///
-  // Put the event in the signaled state. This causes any thread blocked on Wait
-  // to be woken up.
+  /// Put the event in the signaled state. This causes any thread blocked on
+  /// Wait to be woken up.
   ///
   void(CEF_CALLBACK* signal)(struct _cef_waitable_event_t* self);
 
   ///
-  // Returns true (1) if the event is in the signaled state, else false (0). If
-  // the event was created with |automatic_reset| set to true (1) then calling
-  // this function will also cause a reset.
+  /// Returns true (1) if the event is in the signaled state, else false (0). If
+  /// the event was created with |automatic_reset| set to true (1) then calling
+  /// this function will also cause a reset.
   ///
   int(CEF_CALLBACK* is_signaled)(struct _cef_waitable_event_t* self);
 
   ///
-  // Wait indefinitely for the event to be signaled. This function will not
-  // return until after the call to signal() has completed. This function cannot
-  // be called on the browser process UI or IO threads.
+  /// Wait indefinitely for the event to be signaled. This function will not
+  /// return until after the call to signal() has completed. This function
+  /// cannot be called on the browser process UI or IO threads.
   ///
   void(CEF_CALLBACK* wait)(struct _cef_waitable_event_t* self);
 
   ///
-  // Wait up to |max_ms| milliseconds for the event to be signaled. Returns true
-  // (1) if the event was signaled. A return value of false (0) does not
-  // necessarily mean that |max_ms| was exceeded. This function will not return
-  // until after the call to signal() has completed. This function cannot be
-  // called on the browser process UI or IO threads.
+  /// Wait up to |max_ms| milliseconds for the event to be signaled. Returns
+  /// true (1) if the event was signaled. A return value of false (0) does not
+  /// necessarily mean that |max_ms| was exceeded. This function will not return
+  /// until after the call to signal() has completed. This function cannot be
+  /// called on the browser process UI or IO threads.
   ///
   int(CEF_CALLBACK* timed_wait)(struct _cef_waitable_event_t* self,
-                                int64 max_ms);
+                                int64_t max_ms);
 } cef_waitable_event_t;
 
 ///
-// Create a new waitable event. If |automatic_reset| is true (1) then the event
-// state is automatically reset to un-signaled after a single waiting thread has
-// been released; otherwise, the state remains signaled until reset() is called
-// manually. If |initially_signaled| is true (1) then the event will start in
-// the signaled state.
+/// Create a new waitable event. If |automatic_reset| is true (1) then the event
+/// state is automatically reset to un-signaled after a single waiting thread
+/// has been released; otherwise, the state remains signaled until reset() is
+/// called manually. If |initially_signaled| is true (1) then the event will
+/// start in the signaled state.
 ///
 CEF_EXPORT cef_waitable_event_t* cef_waitable_event_create(
     int automatic_reset,
diff --git a/src/include/capi/cef_web_plugin_capi.h b/src/include/capi/cef_web_plugin_capi.h
deleted file mode 100644
index 6cef957..0000000
--- a/src/include/capi/cef_web_plugin_capi.h
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool and should not edited
-// by hand. See the translator.README.txt file in the tools directory for
-// more information.
-//
-// $hash=f1b2b6203d45fdf76d72ea1e79fcef0bb2a26138$
-//
-
-#ifndef CEF_INCLUDE_CAPI_CEF_WEB_PLUGIN_CAPI_H_
-#define CEF_INCLUDE_CAPI_CEF_WEB_PLUGIN_CAPI_H_
-#pragma once
-
-#include "include/capi/cef_base_capi.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct _cef_browser_t;
-
-///
-// Information about a specific web plugin.
-///
-typedef struct _cef_web_plugin_info_t {
-  ///
-  // Base structure.
-  ///
-  cef_base_ref_counted_t base;
-
-  ///
-  // Returns the plugin name (i.e. Flash).
-  ///
-  // The resulting string must be freed by calling cef_string_userfree_free().
-  cef_string_userfree_t(CEF_CALLBACK* get_name)(
-      struct _cef_web_plugin_info_t* self);
-
-  ///
-  // Returns the plugin file path (DLL/bundle/library).
-  ///
-  // The resulting string must be freed by calling cef_string_userfree_free().
-  cef_string_userfree_t(CEF_CALLBACK* get_path)(
-      struct _cef_web_plugin_info_t* self);
-
-  ///
-  // Returns the version of the plugin (may be OS-specific).
-  ///
-  // The resulting string must be freed by calling cef_string_userfree_free().
-  cef_string_userfree_t(CEF_CALLBACK* get_version)(
-      struct _cef_web_plugin_info_t* self);
-
-  ///
-  // Returns a description of the plugin from the version information.
-  ///
-  // The resulting string must be freed by calling cef_string_userfree_free().
-  cef_string_userfree_t(CEF_CALLBACK* get_description)(
-      struct _cef_web_plugin_info_t* self);
-} cef_web_plugin_info_t;
-
-///
-// Structure to implement for visiting web plugin information. The functions of
-// this structure will be called on the browser process UI thread.
-///
-typedef struct _cef_web_plugin_info_visitor_t {
-  ///
-  // Base structure.
-  ///
-  cef_base_ref_counted_t base;
-
-  ///
-  // Method that will be called once for each plugin. |count| is the 0-based
-  // index for the current plugin. |total| is the total number of plugins.
-  // Return false (0) to stop visiting plugins. This function may never be
-  // called if no plugins are found.
-  ///
-  int(CEF_CALLBACK* visit)(struct _cef_web_plugin_info_visitor_t* self,
-                           struct _cef_web_plugin_info_t* info,
-                           int count,
-                           int total);
-} cef_web_plugin_info_visitor_t;
-
-///
-// Structure to implement for receiving unstable plugin information. The
-// functions of this structure will be called on the browser process IO thread.
-///
-typedef struct _cef_web_plugin_unstable_callback_t {
-  ///
-  // Base structure.
-  ///
-  cef_base_ref_counted_t base;
-
-  ///
-  // Method that will be called for the requested plugin. |unstable| will be
-  // true (1) if the plugin has reached the crash count threshold of 3 times in
-  // 120 seconds.
-  ///
-  void(CEF_CALLBACK* is_unstable)(
-      struct _cef_web_plugin_unstable_callback_t* self,
-      const cef_string_t* path,
-      int unstable);
-} cef_web_plugin_unstable_callback_t;
-
-///
-// Implement this structure to receive notification when CDM registration is
-// complete. The functions of this structure will be called on the browser
-// process UI thread.
-///
-typedef struct _cef_register_cdm_callback_t {
-  ///
-  // Base structure.
-  ///
-  cef_base_ref_counted_t base;
-
-  ///
-  // Method that will be called when CDM registration is complete. |result| will
-  // be CEF_CDM_REGISTRATION_ERROR_NONE if registration completed successfully.
-  // Otherwise, |result| and |error_message| will contain additional information
-  // about why registration failed.
-  ///
-  void(CEF_CALLBACK* on_cdm_registration_complete)(
-      struct _cef_register_cdm_callback_t* self,
-      cef_cdm_registration_error_t result,
-      const cef_string_t* error_message);
-} cef_register_cdm_callback_t;
-
-///
-// Visit web plugin information. Can be called on any thread in the browser
-// process.
-///
-CEF_EXPORT void cef_visit_web_plugin_info(
-    cef_web_plugin_info_visitor_t* visitor);
-
-///
-// Cause the plugin list to refresh the next time it is accessed regardless of
-// whether it has already been loaded. Can be called on any thread in the
-// browser process.
-///
-CEF_EXPORT void cef_refresh_web_plugins();
-
-///
-// Unregister an internal plugin. This may be undone the next time
-// cef_refresh_web_plugins() is called. Can be called on any thread in the
-// browser process.
-///
-CEF_EXPORT void cef_unregister_internal_web_plugin(const cef_string_t* path);
-
-///
-// Register a plugin crash. Can be called on any thread in the browser process
-// but will be executed on the IO thread.
-///
-CEF_EXPORT void cef_register_web_plugin_crash(const cef_string_t* path);
-
-///
-// Query if a plugin is unstable. Can be called on any thread in the browser
-// process.
-///
-CEF_EXPORT void cef_is_web_plugin_unstable(
-    const cef_string_t* path,
-    cef_web_plugin_unstable_callback_t* callback);
-
-///
-// Register the Widevine CDM plugin.
-//
-// The client application is responsible for downloading an appropriate
-// platform-specific CDM binary distribution from Google, extracting the
-// contents, and building the required directory structure on the local machine.
-// The cef_browser_host_t::StartDownload function and CefZipArchive structure
-// can be used to implement this functionality in CEF. Contact Google via
-// https://www.widevine.com/contact.html for details on CDM download.
-//
-// |path| is a directory that must contain the following files:
-//   1. manifest.json file from the CDM binary distribution (see below).
-//   2. widevinecdm file from the CDM binary distribution (e.g.
-//      widevinecdm.dll on on Windows, libwidevinecdm.dylib on OS X,
-//      libwidevinecdm.so on Linux).
-//
-// If any of these files are missing or if the manifest file has incorrect
-// contents the registration will fail and |callback| will receive a |result|
-// value of CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS.
-//
-// The manifest.json file must contain the following keys:
-//   A. "os": Supported OS (e.g. "mac", "win" or "linux").
-//   B. "arch": Supported architecture (e.g. "ia32" or "x64").
-//   C. "x-cdm-module-versions": Module API version (e.g. "4").
-//   D. "x-cdm-interface-versions": Interface API version (e.g. "8").
-//   E. "x-cdm-host-versions": Host API version (e.g. "8").
-//   F. "version": CDM version (e.g. "1.4.8.903").
-//   G. "x-cdm-codecs": List of supported codecs (e.g. "vp8,vp9.0,avc1").
-//
-// A through E are used to verify compatibility with the current Chromium
-// version. If the CDM is not compatible the registration will fail and
-// |callback| will receive a |result| value of
-// CEF_CDM_REGISTRATION_ERROR_INCOMPATIBLE.
-//
-// |callback| will be executed asynchronously once registration is complete.
-//
-// On Linux this function must be called before cef_initialize() and the
-// registration cannot be changed during runtime. If registration is not
-// supported at the time that cef_register_widevine_cdm() is called then
-// |callback| will receive a |result| value of
-// CEF_CDM_REGISTRATION_ERROR_NOT_SUPPORTED.
-///
-CEF_EXPORT void cef_register_widevine_cdm(
-    const cef_string_t* path,
-    cef_register_cdm_callback_t* callback);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif  // CEF_INCLUDE_CAPI_CEF_WEB_PLUGIN_CAPI_H_
diff --git a/src/include/capi/cef_x509_certificate_capi.h b/src/include/capi/cef_x509_certificate_capi.h
index f177f0a..de71ced 100644
--- a/src/include/capi/cef_x509_certificate_capi.h
+++ b/src/include/capi/cef_x509_certificate_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=2d04c2cc1791b90ddb9333fe830ad07042e9df2d$
+// $hash=a4b62b20f30552fef5d522bdd00ebf9a8f12464c$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_X509_CERTIFICATE_CAPI_H_
@@ -48,147 +48,133 @@
 #endif
 
 ///
-// Structure representing the issuer or subject field of an X.509 certificate.
+/// Structure representing the issuer or subject field of an X.509 certificate.
 ///
 typedef struct _cef_x509cert_principal_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns a name that can be used to represent the issuer. It tries in this
-  // order: Common Name (CN), Organization Name (O) and Organizational Unit Name
-  // (OU) and returns the first non-NULL one found.
+  /// Returns a name that can be used to represent the issuer. It tries in this
+  /// order: Common Name (CN), Organization Name (O) and Organizational Unit
+  /// Name (OU) and returns the first non-NULL one found.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_display_name)(
       struct _cef_x509cert_principal_t* self);
 
   ///
-  // Returns the common name.
+  /// Returns the common name.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_common_name)(
       struct _cef_x509cert_principal_t* self);
 
   ///
-  // Returns the locality name.
+  /// Returns the locality name.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_locality_name)(
       struct _cef_x509cert_principal_t* self);
 
   ///
-  // Returns the state or province name.
+  /// Returns the state or province name.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_state_or_province_name)(
       struct _cef_x509cert_principal_t* self);
 
   ///
-  // Returns the country name.
+  /// Returns the country name.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_country_name)(
       struct _cef_x509cert_principal_t* self);
 
   ///
-  // Retrieve the list of street addresses.
-  ///
-  void(CEF_CALLBACK* get_street_addresses)(
-      struct _cef_x509cert_principal_t* self,
-      cef_string_list_t addresses);
-
-  ///
-  // Retrieve the list of organization names.
+  /// Retrieve the list of organization names.
   ///
   void(CEF_CALLBACK* get_organization_names)(
       struct _cef_x509cert_principal_t* self,
       cef_string_list_t names);
 
   ///
-  // Retrieve the list of organization unit names.
+  /// Retrieve the list of organization unit names.
   ///
   void(CEF_CALLBACK* get_organization_unit_names)(
       struct _cef_x509cert_principal_t* self,
       cef_string_list_t names);
-
-  ///
-  // Retrieve the list of domain components.
-  ///
-  void(CEF_CALLBACK* get_domain_components)(
-      struct _cef_x509cert_principal_t* self,
-      cef_string_list_t components);
 } cef_x509cert_principal_t;
 
 ///
-// Structure representing a X.509 certificate.
+/// Structure representing a X.509 certificate.
 ///
 typedef struct _cef_x509certificate_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the subject of the X.509 certificate. For HTTPS server certificates
-  // this represents the web server.  The common name of the subject should
-  // match the host name of the web server.
+  /// Returns the subject of the X.509 certificate. For HTTPS server
+  /// certificates this represents the web server.  The common name of the
+  /// subject should match the host name of the web server.
   ///
   struct _cef_x509cert_principal_t*(CEF_CALLBACK* get_subject)(
       struct _cef_x509certificate_t* self);
 
   ///
-  // Returns the issuer of the X.509 certificate.
+  /// Returns the issuer of the X.509 certificate.
   ///
   struct _cef_x509cert_principal_t*(CEF_CALLBACK* get_issuer)(
       struct _cef_x509certificate_t* self);
 
   ///
-  // Returns the DER encoded serial number for the X.509 certificate. The value
-  // possibly includes a leading 00 byte.
+  /// Returns the DER encoded serial number for the X.509 certificate. The value
+  /// possibly includes a leading 00 byte.
   ///
   struct _cef_binary_value_t*(CEF_CALLBACK* get_serial_number)(
       struct _cef_x509certificate_t* self);
 
   ///
-  // Returns the date before which the X.509 certificate is invalid.
-  // CefTime.GetTimeT() will return 0 if no date was specified.
+  /// Returns the date before which the X.509 certificate is invalid.
+  /// CefBaseTime.GetTimeT() will return 0 if no date was specified.
   ///
-  cef_time_t(CEF_CALLBACK* get_valid_start)(
+  cef_basetime_t(CEF_CALLBACK* get_valid_start)(
       struct _cef_x509certificate_t* self);
 
   ///
-  // Returns the date after which the X.509 certificate is invalid.
-  // CefTime.GetTimeT() will return 0 if no date was specified.
+  /// Returns the date after which the X.509 certificate is invalid.
+  /// CefBaseTime.GetTimeT() will return 0 if no date was specified.
   ///
-  cef_time_t(CEF_CALLBACK* get_valid_expiry)(
+  cef_basetime_t(CEF_CALLBACK* get_valid_expiry)(
       struct _cef_x509certificate_t* self);
 
   ///
-  // Returns the DER encoded data for the X.509 certificate.
+  /// Returns the DER encoded data for the X.509 certificate.
   ///
   struct _cef_binary_value_t*(CEF_CALLBACK* get_derencoded)(
       struct _cef_x509certificate_t* self);
 
   ///
-  // Returns the PEM encoded data for the X.509 certificate.
+  /// Returns the PEM encoded data for the X.509 certificate.
   ///
   struct _cef_binary_value_t*(CEF_CALLBACK* get_pemencoded)(
       struct _cef_x509certificate_t* self);
 
   ///
-  // Returns the number of certificates in the issuer chain. If 0, the
-  // certificate is self-signed.
+  /// Returns the number of certificates in the issuer chain. If 0, the
+  /// certificate is self-signed.
   ///
   size_t(CEF_CALLBACK* get_issuer_chain_size)(
       struct _cef_x509certificate_t* self);
 
   ///
-  // Returns the DER encoded data for the certificate issuer chain. If we failed
-  // to encode a certificate in the chain it is still present in the array but
-  // is an NULL string.
+  /// Returns the DER encoded data for the certificate issuer chain. If we
+  /// failed to encode a certificate in the chain it is still present in the
+  /// array but is an NULL string.
   ///
   void(CEF_CALLBACK* get_derencoded_issuer_chain)(
       struct _cef_x509certificate_t* self,
@@ -196,9 +182,9 @@
       struct _cef_binary_value_t** chain);
 
   ///
-  // Returns the PEM encoded data for the certificate issuer chain. If we failed
-  // to encode a certificate in the chain it is still present in the array but
-  // is an NULL string.
+  /// Returns the PEM encoded data for the certificate issuer chain. If we
+  /// failed to encode a certificate in the chain it is still present in the
+  /// array but is an NULL string.
   ///
   void(CEF_CALLBACK* get_pemencoded_issuer_chain)(
       struct _cef_x509certificate_t* self,
diff --git a/src/include/capi/cef_xml_reader_capi.h b/src/include/capi/cef_xml_reader_capi.h
index 84a4554..3db9b94 100644
--- a/src/include/capi/cef_xml_reader_capi.h
+++ b/src/include/capi/cef_xml_reader_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=64f6b6477ec81b1d64517cf0af2e3b2121ff39bd$
+// $hash=366f872b03f7c25ef56677cc427a317bb529ad9c$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_XML_READER_CAPI_H_
@@ -48,132 +48,129 @@
 #endif
 
 ///
-// Structure that supports the reading of XML data via the libxml streaming API.
-// The functions of this structure should only be called on the thread that
-// creates the object.
+/// Structure that supports the reading of XML data via the libxml streaming
+/// API. The functions of this structure should only be called on the thread
+/// that creates the object.
 ///
 typedef struct _cef_xml_reader_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Moves the cursor to the next node in the document. This function must be
-  // called at least once to set the current cursor position. Returns true (1)
-  // if the cursor position was set successfully.
+  /// Moves the cursor to the next node in the document. This function must be
+  /// called at least once to set the current cursor position. Returns true (1)
+  /// if the cursor position was set successfully.
   ///
   int(CEF_CALLBACK* move_to_next_node)(struct _cef_xml_reader_t* self);
 
   ///
-  // Close the document. This should be called directly to ensure that cleanup
-  // occurs on the correct thread.
+  /// Close the document. This should be called directly to ensure that cleanup
+  /// occurs on the correct thread.
   ///
   int(CEF_CALLBACK* close)(struct _cef_xml_reader_t* self);
 
   ///
-  // Returns true (1) if an error has been reported by the XML parser.
+  /// Returns true (1) if an error has been reported by the XML parser.
   ///
   int(CEF_CALLBACK* has_error)(struct _cef_xml_reader_t* self);
 
   ///
-  // Returns the error string.
+  /// Returns the error string.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_error)(
       struct _cef_xml_reader_t* self);
 
-  // The below functions retrieve data for the node at the current cursor
-  // position.
-
   ///
-  // Returns the node type.
+  /// Returns the node type.
   ///
   cef_xml_node_type_t(CEF_CALLBACK* get_type)(struct _cef_xml_reader_t* self);
 
   ///
-  // Returns the node depth. Depth starts at 0 for the root node.
+  /// Returns the node depth. Depth starts at 0 for the root node.
   ///
   int(CEF_CALLBACK* get_depth)(struct _cef_xml_reader_t* self);
 
   ///
-  // Returns the local name. See http://www.w3.org/TR/REC-xml-names/#NT-
-  // LocalPart for additional details.
+  /// Returns the local name. See http://www.w3.org/TR/REC-xml-names/#NT-
+  /// LocalPart for additional details.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_local_name)(
       struct _cef_xml_reader_t* self);
 
   ///
-  // Returns the namespace prefix. See http://www.w3.org/TR/REC-xml-names/ for
-  // additional details.
+  /// Returns the namespace prefix. See http://www.w3.org/TR/REC-xml-names/ for
+  /// additional details.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_prefix)(
       struct _cef_xml_reader_t* self);
 
   ///
-  // Returns the qualified name, equal to (Prefix:)LocalName. See
-  // http://www.w3.org/TR/REC-xml-names/#ns-qualnames for additional details.
+  /// Returns the qualified name, equal to (Prefix:)LocalName. See
+  /// http://www.w3.org/TR/REC-xml-names/#ns-qualnames for additional details.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_qualified_name)(
       struct _cef_xml_reader_t* self);
 
   ///
-  // Returns the URI defining the namespace associated with the node. See
-  // http://www.w3.org/TR/REC-xml-names/ for additional details.
+  /// Returns the URI defining the namespace associated with the node. See
+  /// http://www.w3.org/TR/REC-xml-names/ for additional details.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_namespace_uri)(
       struct _cef_xml_reader_t* self);
 
   ///
-  // Returns the base URI of the node. See http://www.w3.org/TR/xmlbase/ for
-  // additional details.
+  /// Returns the base URI of the node. See http://www.w3.org/TR/xmlbase/ for
+  /// additional details.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_base_uri)(
       struct _cef_xml_reader_t* self);
 
   ///
-  // Returns the xml:lang scope within which the node resides. See
-  // http://www.w3.org/TR/REC-xml/#sec-lang-tag for additional details.
+  /// Returns the xml:lang scope within which the node resides. See
+  /// http://www.w3.org/TR/REC-xml/#sec-lang-tag for additional details.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_xml_lang)(
       struct _cef_xml_reader_t* self);
 
   ///
-  // Returns true (1) if the node represents an NULL element. <a/> is considered
-  // NULL but <a></a> is not.
+  /// Returns true (1) if the node represents an NULL element. "<a/>" is
+  /// considered NULL but "<a></a>" is not.
   ///
   int(CEF_CALLBACK* is_empty_element)(struct _cef_xml_reader_t* self);
 
   ///
-  // Returns true (1) if the node has a text value.
+  /// Returns true (1) if the node has a text value.
   ///
   int(CEF_CALLBACK* has_value)(struct _cef_xml_reader_t* self);
 
   ///
-  // Returns the text value.
+  /// Returns the text value.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_value)(
       struct _cef_xml_reader_t* self);
 
   ///
-  // Returns true (1) if the node has attributes.
+  /// Returns true (1) if the node has attributes.
   ///
   int(CEF_CALLBACK* has_attributes)(struct _cef_xml_reader_t* self);
 
   ///
-  // Returns the number of attributes.
+  /// Returns the number of attributes.
   ///
   size_t(CEF_CALLBACK* get_attribute_count)(struct _cef_xml_reader_t* self);
 
   ///
-  // Returns the value of the attribute at the specified 0-based index.
+  /// Returns the value of the attribute at the specified 0-based index.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_attribute_byindex)(
@@ -181,7 +178,7 @@
       int index);
 
   ///
-  // Returns the value of the attribute with the specified qualified name.
+  /// Returns the value of the attribute with the specified qualified name.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_attribute_byqname)(
@@ -189,8 +186,8 @@
       const cef_string_t* qualifiedName);
 
   ///
-  // Returns the value of the attribute with the specified local name and
-  // namespace URI.
+  /// Returns the value of the attribute with the specified local name and
+  /// namespace URI.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_attribute_bylname)(
@@ -199,48 +196,43 @@
       const cef_string_t* namespaceURI);
 
   ///
-  // Returns an XML representation of the current node's children.
+  /// Returns an XML representation of the current node's children.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_inner_xml)(
       struct _cef_xml_reader_t* self);
 
   ///
-  // Returns an XML representation of the current node including its children.
+  /// Returns an XML representation of the current node including its children.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_outer_xml)(
       struct _cef_xml_reader_t* self);
 
   ///
-  // Returns the line number for the current node.
+  /// Returns the line number for the current node.
   ///
   int(CEF_CALLBACK* get_line_number)(struct _cef_xml_reader_t* self);
 
-  // Attribute nodes are not traversed by default. The below functions can be
-  // used to move the cursor to an attribute node. move_to_carrying_element()
-  // can be called afterwards to return the cursor to the carrying element. The
-  // depth of an attribute node will be 1 + the depth of the carrying element.
-
   ///
-  // Moves the cursor to the attribute at the specified 0-based index. Returns
-  // true (1) if the cursor position was set successfully.
+  /// Moves the cursor to the attribute at the specified 0-based index. Returns
+  /// true (1) if the cursor position was set successfully.
   ///
   int(CEF_CALLBACK* move_to_attribute_byindex)(struct _cef_xml_reader_t* self,
                                                int index);
 
   ///
-  // Moves the cursor to the attribute with the specified qualified name.
-  // Returns true (1) if the cursor position was set successfully.
+  /// Moves the cursor to the attribute with the specified qualified name.
+  /// Returns true (1) if the cursor position was set successfully.
   ///
   int(CEF_CALLBACK* move_to_attribute_byqname)(
       struct _cef_xml_reader_t* self,
       const cef_string_t* qualifiedName);
 
   ///
-  // Moves the cursor to the attribute with the specified local name and
-  // namespace URI. Returns true (1) if the cursor position was set
-  // successfully.
+  /// Moves the cursor to the attribute with the specified local name and
+  /// namespace URI. Returns true (1) if the cursor position was set
+  /// successfully.
   ///
   int(CEF_CALLBACK* move_to_attribute_bylname)(
       struct _cef_xml_reader_t* self,
@@ -248,27 +240,27 @@
       const cef_string_t* namespaceURI);
 
   ///
-  // Moves the cursor to the first attribute in the current element. Returns
-  // true (1) if the cursor position was set successfully.
+  /// Moves the cursor to the first attribute in the current element. Returns
+  /// true (1) if the cursor position was set successfully.
   ///
   int(CEF_CALLBACK* move_to_first_attribute)(struct _cef_xml_reader_t* self);
 
   ///
-  // Moves the cursor to the next attribute in the current element. Returns true
-  // (1) if the cursor position was set successfully.
+  /// Moves the cursor to the next attribute in the current element. Returns
+  /// true (1) if the cursor position was set successfully.
   ///
   int(CEF_CALLBACK* move_to_next_attribute)(struct _cef_xml_reader_t* self);
 
   ///
-  // Moves the cursor back to the carrying element. Returns true (1) if the
-  // cursor position was set successfully.
+  /// Moves the cursor back to the carrying element. Returns true (1) if the
+  /// cursor position was set successfully.
   ///
   int(CEF_CALLBACK* move_to_carrying_element)(struct _cef_xml_reader_t* self);
 } cef_xml_reader_t;
 
 ///
-// Create a new cef_xml_reader_t object. The returned object's functions can
-// only be called from the thread that created the object.
+/// Create a new cef_xml_reader_t object. The returned object's functions can
+/// only be called from the thread that created the object.
 ///
 CEF_EXPORT cef_xml_reader_t* cef_xml_reader_create(
     struct _cef_stream_reader_t* stream,
diff --git a/src/include/capi/cef_zip_reader_capi.h b/src/include/capi/cef_zip_reader_capi.h
index 8138559..e5a2a7d 100644
--- a/src/include/capi/cef_zip_reader_capi.h
+++ b/src/include/capi/cef_zip_reader_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=f8b7ec1654c7d62153e2670b52ed18eb4c9c58d5$
+// $hash=d082d724164cb0b1da12d49b080c599934f08b9d$
 //
 
 #ifndef CEF_INCLUDE_CAPI_CEF_ZIP_READER_CAPI_H_
@@ -48,97 +48,95 @@
 #endif
 
 ///
-// Structure that supports the reading of zip archives via the zlib unzip API.
-// The functions of this structure should only be called on the thread that
-// creates the object.
+/// Structure that supports the reading of zip archives via the zlib unzip API.
+/// The functions of this structure should only be called on the thread that
+/// creates the object.
 ///
 typedef struct _cef_zip_reader_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Moves the cursor to the first file in the archive. Returns true (1) if the
-  // cursor position was set successfully.
+  /// Moves the cursor to the first file in the archive. Returns true (1) if the
+  /// cursor position was set successfully.
   ///
   int(CEF_CALLBACK* move_to_first_file)(struct _cef_zip_reader_t* self);
 
   ///
-  // Moves the cursor to the next file in the archive. Returns true (1) if the
-  // cursor position was set successfully.
+  /// Moves the cursor to the next file in the archive. Returns true (1) if the
+  /// cursor position was set successfully.
   ///
   int(CEF_CALLBACK* move_to_next_file)(struct _cef_zip_reader_t* self);
 
   ///
-  // Moves the cursor to the specified file in the archive. If |caseSensitive|
-  // is true (1) then the search will be case sensitive. Returns true (1) if the
-  // cursor position was set successfully.
+  /// Moves the cursor to the specified file in the archive. If |caseSensitive|
+  /// is true (1) then the search will be case sensitive. Returns true (1) if
+  /// the cursor position was set successfully.
   ///
   int(CEF_CALLBACK* move_to_file)(struct _cef_zip_reader_t* self,
                                   const cef_string_t* fileName,
                                   int caseSensitive);
 
   ///
-  // Closes the archive. This should be called directly to ensure that cleanup
-  // occurs on the correct thread.
+  /// Closes the archive. This should be called directly to ensure that cleanup
+  /// occurs on the correct thread.
   ///
   int(CEF_CALLBACK* close)(struct _cef_zip_reader_t* self);
 
-  // The below functions act on the file at the current cursor position.
-
   ///
-  // Returns the name of the file.
+  /// Returns the name of the file.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_file_name)(
       struct _cef_zip_reader_t* self);
 
   ///
-  // Returns the uncompressed size of the file.
+  /// Returns the uncompressed size of the file.
   ///
-  int64(CEF_CALLBACK* get_file_size)(struct _cef_zip_reader_t* self);
+  int64_t(CEF_CALLBACK* get_file_size)(struct _cef_zip_reader_t* self);
 
   ///
-  // Returns the last modified timestamp for the file.
+  /// Returns the last modified timestamp for the file.
   ///
-  cef_time_t(CEF_CALLBACK* get_file_last_modified)(
+  cef_basetime_t(CEF_CALLBACK* get_file_last_modified)(
       struct _cef_zip_reader_t* self);
 
   ///
-  // Opens the file for reading of uncompressed data. A read password may
-  // optionally be specified.
+  /// Opens the file for reading of uncompressed data. A read password may
+  /// optionally be specified.
   ///
   int(CEF_CALLBACK* open_file)(struct _cef_zip_reader_t* self,
                                const cef_string_t* password);
 
   ///
-  // Closes the file.
+  /// Closes the file.
   ///
   int(CEF_CALLBACK* close_file)(struct _cef_zip_reader_t* self);
 
   ///
-  // Read uncompressed file contents into the specified buffer. Returns < 0 if
-  // an error occurred, 0 if at the end of file, or the number of bytes read.
+  /// Read uncompressed file contents into the specified buffer. Returns < 0 if
+  /// an error occurred, 0 if at the end of file, or the number of bytes read.
   ///
   int(CEF_CALLBACK* read_file)(struct _cef_zip_reader_t* self,
                                void* buffer,
                                size_t bufferSize);
 
   ///
-  // Returns the current offset in the uncompressed file contents.
+  /// Returns the current offset in the uncompressed file contents.
   ///
-  int64(CEF_CALLBACK* tell)(struct _cef_zip_reader_t* self);
+  int64_t(CEF_CALLBACK* tell)(struct _cef_zip_reader_t* self);
 
   ///
-  // Returns true (1) if at end of the file contents.
+  /// Returns true (1) if at end of the file contents.
   ///
   int(CEF_CALLBACK* eof)(struct _cef_zip_reader_t* self);
 } cef_zip_reader_t;
 
 ///
-// Create a new cef_zip_reader_t object. The returned object's functions can
-// only be called from the thread that created the object.
+/// Create a new cef_zip_reader_t object. The returned object's functions can
+/// only be called from the thread that created the object.
 ///
 CEF_EXPORT cef_zip_reader_t* cef_zip_reader_create(
     struct _cef_stream_reader_t* stream);
diff --git a/src/include/capi/test/cef_test_helpers_capi.h b/src/include/capi/test/cef_test_helpers_capi.h
index 51d808c..c24bcf5 100644
--- a/src/include/capi/test/cef_test_helpers_capi.h
+++ b/src/include/capi/test/cef_test_helpers_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=44811580a3bddb5efed7d697ef8fa0b7e0925ef2$
+// $hash=4d10dad2278e6d61367b3deaf501a0e7b4fd60e9$
 //
 
 #ifndef CEF_INCLUDE_CAPI_TEST_CEF_TEST_HELPERS_CAPI_H_
@@ -52,13 +52,21 @@
 #endif
 
 ///
-// Execute JavaScript with a user gesture to trigger functionality like
-// onbeforeunload handlers that will otherwise be blocked.
+/// Execute JavaScript with a user gesture to trigger functionality like
+/// onbeforeunload handlers that will otherwise be blocked.
 ///
 CEF_EXPORT void cef_execute_java_script_with_user_gesture_for_tests(
     struct _cef_frame_t* frame,
     const cef_string_t* javascript);
 
+///
+/// Set the DIR_SRC_TEST_DATA_ROOT directory used to load test data. Must be
+/// configured when running from a CEF binary distribution. Defaults to the
+/// "chromium/src" directory when running from a local CEF/Chromium build. |dir|
+/// must be an absolute path.
+///
+CEF_EXPORT void cef_set_data_directory_for_tests(const cef_string_t* dir);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/include/capi/test/cef_test_server_capi.h b/src/include/capi/test/cef_test_server_capi.h
new file mode 100644
index 0000000..1741922
--- /dev/null
+++ b/src/include/capi/test/cef_test_server_capi.h
@@ -0,0 +1,197 @@
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool and should not edited
+// by hand. See the translator.README.txt file in the tools directory for
+// more information.
+//
+// $hash=f5731d0fffb953f1269b63b478a89bb6b842ac94$
+//
+
+#ifndef CEF_INCLUDE_CAPI_TEST_CEF_TEST_SERVER_CAPI_H_
+#define CEF_INCLUDE_CAPI_TEST_CEF_TEST_SERVER_CAPI_H_
+#pragma once
+
+#if !defined(BUILDING_CEF_SHARED) && !defined(WRAPPING_CEF_SHARED) && \
+    !defined(UNIT_TEST)
+#error This file can be included for unit tests only
+#endif
+
+#include "include/capi/cef_base_capi.h"
+#include "include/capi/cef_request_capi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _cef_test_server_connection_t;
+struct _cef_test_server_handler_t;
+
+///
+/// Structure representing an embedded test server that supports HTTP/HTTPS
+/// requests. This is a basic server providing only an essential subset of the
+/// HTTP/1.1 protocol. Especially, it assumes that the request syntax is
+/// correct. It *does not* support a Chunked Transfer Encoding. Server capacity
+/// is limited and is intended to handle only a small number of simultaneous
+/// connections (e.g. for communicating between applications on localhost). The
+/// functions of this structure are safe to call from any thread in the brower
+/// process unless otherwise indicated.
+///
+typedef struct _cef_test_server_t {
+  ///
+  /// Base structure.
+  ///
+  cef_base_ref_counted_t base;
+
+  ///
+  /// Stop the server and shut down the dedicated server thread. This function
+  /// must be called on the same thread as CreateAndStart. It will block until
+  /// the dedicated server thread has shut down.
+  ///
+  void(CEF_CALLBACK* stop)(struct _cef_test_server_t* self);
+
+  ///
+  /// Returns the server origin including the port number (e.g.
+  /// "[http|https]://127.0.0.1:<port>".
+  ///
+  // The resulting string must be freed by calling cef_string_userfree_free().
+  cef_string_userfree_t(CEF_CALLBACK* get_origin)(
+      struct _cef_test_server_t* self);
+} cef_test_server_t;
+
+///
+/// Create and start a new test server that binds to |port|. If |port| is 0 an
+/// available port number will be selected. If |https_server| is true (1) the
+/// server will be HTTPS, otherwise it will be HTTP. When |https_server| is true
+/// (1) the |https_cert_type| value is used to configure the certificate type.
+/// Returns the newly created server object on success, or nullptr if the server
+/// cannot be started.
+///
+/// A new thread will be created for each CreateAndStart call (the "dedicated
+/// server thread"). It is therefore recommended to use a different
+/// cef_test_server_handler_t instance for each CreateAndStart call to avoid
+/// thread safety issues in the cef_test_server_handler_t implementation.
+///
+/// On success, this function will block until the dedicated server thread has
+/// started. The server will continue running until Stop is called.
+///
+CEF_EXPORT cef_test_server_t* cef_test_server_create_and_start(
+    uint16_t port,
+    int https_server,
+    cef_test_cert_type_t https_cert_type,
+    struct _cef_test_server_handler_t* handler);
+
+///
+/// Implement this structure to handle test server requests. A new thread will
+/// be created for each cef_test_server_t::CreateAndStart call (the "dedicated
+/// server thread"), and the functions of this structure will be called on that
+/// thread. See related documentation on cef_test_server_t::CreateAndStart.
+///
+typedef struct _cef_test_server_handler_t {
+  ///
+  /// Base structure.
+  ///
+  cef_base_ref_counted_t base;
+
+  ///
+  /// Called when |server| receives a request. To handle the request return true
+  /// (1) and use |connection| to send the response either synchronously or
+  /// asynchronously. Otherwise, return false (0) if the request is unhandled.
+  /// When returning false (0) do not call any |connection| functions.
+  ///
+  int(CEF_CALLBACK* on_test_server_request)(
+      struct _cef_test_server_handler_t* self,
+      struct _cef_test_server_t* server,
+      struct _cef_request_t* request,
+      struct _cef_test_server_connection_t* connection);
+} cef_test_server_handler_t;
+
+///
+/// Structure representing a test server connection. The functions of this
+/// structure are safe to call from any thread in the brower process unless
+/// otherwise indicated.
+///
+typedef struct _cef_test_server_connection_t {
+  ///
+  /// Base structure.
+  ///
+  cef_base_ref_counted_t base;
+
+  ///
+  /// Send an HTTP 200 "OK" response. |content_type| is the response content
+  /// type (e.g. "text/html"). |data| is the response content and |data_size| is
+  /// the size of |data| in bytes. The contents of |data| will be copied. The
+  /// connection will be closed automatically after the response is sent.
+  ///
+  void(CEF_CALLBACK* send_http200response)(
+      struct _cef_test_server_connection_t* self,
+      const cef_string_t* content_type,
+      const void* data,
+      size_t data_size);
+
+  ///
+  /// Send an HTTP 404 "Not Found" response. The connection will be closed
+  /// automatically after the response is sent.
+  ///
+  void(CEF_CALLBACK* send_http404response)(
+      struct _cef_test_server_connection_t* self);
+
+  ///
+  /// Send an HTTP 500 "Internal Server Error" response. |error_message| is the
+  /// associated error message. The connection will be closed automatically
+  /// after the response is sent.
+  ///
+  void(CEF_CALLBACK* send_http500response)(
+      struct _cef_test_server_connection_t* self,
+      const cef_string_t* error_message);
+
+  ///
+  /// Send a custom HTTP response. |response_code| is the HTTP response code
+  /// sent in the status line (e.g. 200). |content_type| is the response content
+  /// type (e.g. "text/html"). |data| is the response content and |data_size| is
+  /// the size of |data| in bytes. The contents of |data| will be copied.
+  /// |extra_headers| is an optional map of additional header key/value pairs.
+  /// The connection will be closed automatically after the response is sent.
+  ///
+  void(CEF_CALLBACK* send_http_response)(
+      struct _cef_test_server_connection_t* self,
+      int response_code,
+      const cef_string_t* content_type,
+      const void* data,
+      size_t data_size,
+      cef_string_multimap_t extra_headers);
+} cef_test_server_connection_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // CEF_INCLUDE_CAPI_TEST_CEF_TEST_SERVER_CAPI_H_
diff --git a/src/include/capi/test/cef_translator_test_capi.h b/src/include/capi/test/cef_translator_test_capi.h
index 42a9b6e..b1e87b0 100644
--- a/src/include/capi/test/cef_translator_test_capi.h
+++ b/src/include/capi/test/cef_translator_test_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=a5d8033127cf2d21f1cb0c87f76d2d59ec3eace0$
+// $hash=58809bc0a16010773cf11b5165e65b32ec4b4793$
 //
 
 #ifndef CEF_INCLUDE_CAPI_TEST_CEF_TRANSLATOR_TEST_CAPI_H_
@@ -61,214 +61,206 @@
 struct _cef_translator_test_scoped_library_t;
 
 ///
-// Structure for testing all of the possible data transfer types.
+/// Structure for testing all of the possible data transfer types.
 ///
 typedef struct _cef_translator_test_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
-  // PRIMITIVE VALUES
-
   ///
-  // Return a void value.
+  /// Return a void value.
   ///
   void(CEF_CALLBACK* get_void)(struct _cef_translator_test_t* self);
 
   ///
-  // Return a bool value.
+  /// Return a bool value.
   ///
   int(CEF_CALLBACK* get_bool)(struct _cef_translator_test_t* self);
 
   ///
-  // Return an int value.
+  /// Return an int value.
   ///
   int(CEF_CALLBACK* get_int)(struct _cef_translator_test_t* self);
 
   ///
-  // Return a double value.
+  /// Return a double value.
   ///
   double(CEF_CALLBACK* get_double)(struct _cef_translator_test_t* self);
 
   ///
-  // Return a long value.
+  /// Return a long value.
   ///
   long(CEF_CALLBACK* get_long)(struct _cef_translator_test_t* self);
 
   ///
-  // Return a size_t value.
+  /// Return a size_t value.
   ///
   size_t(CEF_CALLBACK* get_sizet)(struct _cef_translator_test_t* self);
 
   ///
-  // Set a void value.
+  /// Set a void value.
   ///
   int(CEF_CALLBACK* set_void)(struct _cef_translator_test_t* self);
 
   ///
-  // Set a bool value.
+  /// Set a bool value.
   ///
   int(CEF_CALLBACK* set_bool)(struct _cef_translator_test_t* self, int val);
 
   ///
-  // Set an int value.
+  /// Set an int value.
   ///
   int(CEF_CALLBACK* set_int)(struct _cef_translator_test_t* self, int val);
 
   ///
-  // Set a double value.
+  /// Set a double value.
   ///
   int(CEF_CALLBACK* set_double)(struct _cef_translator_test_t* self,
                                 double val);
 
   ///
-  // Set a long value.
+  /// Set a long value.
   ///
   int(CEF_CALLBACK* set_long)(struct _cef_translator_test_t* self, long val);
 
   ///
-  // Set a size_t value.
+  /// Set a size_t value.
   ///
   int(CEF_CALLBACK* set_sizet)(struct _cef_translator_test_t* self, size_t val);
 
   ///
-  // Set a int list value.
+  /// Set a int list value.
   ///
   int(CEF_CALLBACK* set_int_list)(struct _cef_translator_test_t* self,
                                   size_t valCount,
                                   int const* val);
 
   ///
-  // Return an int list value by out-param.
+  /// Return an int list value by out-param.
   ///
   int(CEF_CALLBACK* get_int_list_by_ref)(struct _cef_translator_test_t* self,
                                          size_t* valCount,
                                          int* val);
 
   ///
-  // Return the number of points that will be output above.
+  /// Return the number of points that will be output above.
   ///
   size_t(CEF_CALLBACK* get_int_list_size)(struct _cef_translator_test_t* self);
 
-  // STRING VALUES
-
   ///
-  // Return a string value.
+  /// Return a string value.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_string)(
       struct _cef_translator_test_t* self);
 
   ///
-  // Set a string value.
+  /// Set a string value.
   ///
   int(CEF_CALLBACK* set_string)(struct _cef_translator_test_t* self,
                                 const cef_string_t* val);
 
   ///
-  // Return a string value by out-param.
+  /// Return a string value by out-param.
   ///
   void(CEF_CALLBACK* get_string_by_ref)(struct _cef_translator_test_t* self,
                                         cef_string_t* val);
 
   ///
-  // Set a string list value.
+  /// Set a string list value.
   ///
   int(CEF_CALLBACK* set_string_list)(struct _cef_translator_test_t* self,
                                      cef_string_list_t val);
 
   ///
-  // Return a string list value by out-param.
+  /// Return a string list value by out-param.
   ///
   int(CEF_CALLBACK* get_string_list_by_ref)(struct _cef_translator_test_t* self,
                                             cef_string_list_t val);
 
   ///
-  // Set a string map value.
+  /// Set a string map value.
   ///
   int(CEF_CALLBACK* set_string_map)(struct _cef_translator_test_t* self,
                                     cef_string_map_t val);
 
   ///
-  // Return a string map value by out-param.
+  /// Return a string map value by out-param.
   ///
   int(CEF_CALLBACK* get_string_map_by_ref)(struct _cef_translator_test_t* self,
                                            cef_string_map_t val);
 
   ///
-  // Set a string multimap value.
+  /// Set a string multimap value.
   ///
   int(CEF_CALLBACK* set_string_multimap)(struct _cef_translator_test_t* self,
                                          cef_string_multimap_t val);
 
   ///
-  // Return a string multimap value by out-param.
+  /// Return a string multimap value by out-param.
   ///
   int(CEF_CALLBACK* get_string_multimap_by_ref)(
       struct _cef_translator_test_t* self,
       cef_string_multimap_t val);
 
-  // STRUCT VALUES
-
   ///
-  // Return a point value.
+  /// Return a point value.
   ///
   cef_point_t(CEF_CALLBACK* get_point)(struct _cef_translator_test_t* self);
 
   ///
-  // Set a point value.
+  /// Set a point value.
   ///
   int(CEF_CALLBACK* set_point)(struct _cef_translator_test_t* self,
                                const cef_point_t* val);
 
   ///
-  // Return a point value by out-param.
+  /// Return a point value by out-param.
   ///
   void(CEF_CALLBACK* get_point_by_ref)(struct _cef_translator_test_t* self,
                                        cef_point_t* val);
 
   ///
-  // Set a point list vlaue.
+  /// Set a point list vlaue.
   ///
   int(CEF_CALLBACK* set_point_list)(struct _cef_translator_test_t* self,
                                     size_t valCount,
                                     cef_point_t const* val);
 
   ///
-  // Return a point list value by out-param.
+  /// Return a point list value by out-param.
   ///
   int(CEF_CALLBACK* get_point_list_by_ref)(struct _cef_translator_test_t* self,
                                            size_t* valCount,
                                            cef_point_t* val);
 
   ///
-  // Return the number of points that will be output above.
+  /// Return the number of points that will be output above.
   ///
   size_t(CEF_CALLBACK* get_point_list_size)(
       struct _cef_translator_test_t* self);
 
-  // LIBRARY-SIDE REFPTR VALUES
-
   ///
-  // Return an new library-side object.
+  /// Return an new library-side object.
   ///
   struct _cef_translator_test_ref_ptr_library_t*(
       CEF_CALLBACK* get_ref_ptr_library)(struct _cef_translator_test_t* self,
                                          int val);
 
   ///
-  // Set an object. Returns the value from
-  // cef_translator_test_ref_ptr_library_t::get_value(). This tests input and
-  // execution of a library-side object type.
+  /// Set an object. Returns the value from
+  /// cef_translator_test_ref_ptr_library_t::get_value(). This tests input and
+  /// execution of a library-side object type.
   ///
   int(CEF_CALLBACK* set_ref_ptr_library)(
       struct _cef_translator_test_t* self,
       struct _cef_translator_test_ref_ptr_library_t* val);
 
   ///
-  // Set an object. Returns the object passed in. This tests input and output of
-  // a library-side object type.
+  /// Set an object. Returns the object passed in. This tests input and output
+  /// of a library-side object type.
   ///
   struct _cef_translator_test_ref_ptr_library_t*(
       CEF_CALLBACK* set_ref_ptr_library_and_return)(
@@ -276,17 +268,17 @@
       struct _cef_translator_test_ref_ptr_library_t* val);
 
   ///
-  // Set a child object. Returns the value from
-  // cef_translator_test_ref_ptr_library_t::get_value(). This tests input of a
-  // library- side child object type and execution as the parent type.
+  /// Set a child object. Returns the value from
+  /// cef_translator_test_ref_ptr_library_t::get_value(). This tests input of a
+  /// library- side child object type and execution as the parent type.
   ///
   int(CEF_CALLBACK* set_child_ref_ptr_library)(
       struct _cef_translator_test_t* self,
       struct _cef_translator_test_ref_ptr_library_child_t* val);
 
   ///
-  // Set a child object. Returns the object as the parent type. This tests input
-  // of a library-side child object type and return as the parent type.
+  /// Set a child object. Returns the object as the parent type. This tests
+  /// input of a library-side child object type and return as the parent type.
   ///
   struct _cef_translator_test_ref_ptr_library_t*(
       CEF_CALLBACK* set_child_ref_ptr_library_and_return_parent)(
@@ -294,7 +286,7 @@
       struct _cef_translator_test_ref_ptr_library_child_t* val);
 
   ///
-  // Set an object list vlaue.
+  /// Set an object list vlaue.
   ///
   int(CEF_CALLBACK* set_ref_ptr_library_list)(
       struct _cef_translator_test_t* self,
@@ -304,7 +296,7 @@
       int val2);
 
   ///
-  // Return an object list value by out-param.
+  /// Return an object list value by out-param.
   ///
   int(CEF_CALLBACK* get_ref_ptr_library_list_by_ref)(
       struct _cef_translator_test_t* self,
@@ -314,25 +306,23 @@
       int val2);
 
   ///
-  // Return the number of object that will be output above.
+  /// Return the number of object that will be output above.
   ///
   size_t(CEF_CALLBACK* get_ref_ptr_library_list_size)(
       struct _cef_translator_test_t* self);
 
-  // CLIENT-SIDE REFPTR VALUES
-
   ///
-  // Set an object. Returns the value from
-  // cef_translator_test_ref_ptr_client_t::get_value(). This tests input and
-  // execution of a client-side object type.
+  /// Set an object. Returns the value from
+  /// cef_translator_test_ref_ptr_client_t::get_value(). This tests input and
+  /// execution of a client-side object type.
   ///
   int(CEF_CALLBACK* set_ref_ptr_client)(
       struct _cef_translator_test_t* self,
       struct _cef_translator_test_ref_ptr_client_t* val);
 
   ///
-  // Set an object. Returns the handler passed in. This tests input and output
-  // of a client-side object type.
+  /// Set an object. Returns the handler passed in. This tests input and output
+  /// of a client-side object type.
   ///
   struct _cef_translator_test_ref_ptr_client_t*(
       CEF_CALLBACK* set_ref_ptr_client_and_return)(
@@ -340,17 +330,17 @@
       struct _cef_translator_test_ref_ptr_client_t* val);
 
   ///
-  // Set a child object. Returns the value from
-  // cef_translator_test_ref_ptr_client_t::get_value(). This tests input of a
-  // client- side child object type and execution as the parent type.
+  /// Set a child object. Returns the value from
+  /// cef_translator_test_ref_ptr_client_t::get_value(). This tests input of a
+  /// client- side child object type and execution as the parent type.
   ///
   int(CEF_CALLBACK* set_child_ref_ptr_client)(
       struct _cef_translator_test_t* self,
       struct _cef_translator_test_ref_ptr_client_child_t* val);
 
   ///
-  // Set a child object. Returns the object as the parent type. This tests input
-  // of a client-side child object type and return as the parent type.
+  /// Set a child object. Returns the object as the parent type. This tests
+  /// input of a client-side child object type and return as the parent type.
   ///
   struct _cef_translator_test_ref_ptr_client_t*(
       CEF_CALLBACK* set_child_ref_ptr_client_and_return_parent)(
@@ -358,7 +348,7 @@
       struct _cef_translator_test_ref_ptr_client_child_t* val);
 
   ///
-  // Set an object list vlaue.
+  /// Set an object list vlaue.
   ///
   int(CEF_CALLBACK* set_ref_ptr_client_list)(
       struct _cef_translator_test_t* self,
@@ -368,7 +358,7 @@
       int val2);
 
   ///
-  // Return an object list value by out-param.
+  /// Return an object list value by out-param.
   ///
   int(CEF_CALLBACK* get_ref_ptr_client_list_by_ref)(
       struct _cef_translator_test_t* self,
@@ -378,32 +368,30 @@
       struct _cef_translator_test_ref_ptr_client_t* val2);
 
   ///
-  // Return the number of object that will be output above.
+  /// Return the number of object that will be output above.
   ///
   size_t(CEF_CALLBACK* get_ref_ptr_client_list_size)(
       struct _cef_translator_test_t* self);
 
-  // LIBRARY-SIDE OWNPTR VALUES
-
   ///
-  // Return an new library-side object.
+  /// Return an new library-side object.
   ///
   struct _cef_translator_test_scoped_library_t*(
       CEF_CALLBACK* get_own_ptr_library)(struct _cef_translator_test_t* self,
                                          int val);
 
   ///
-  // Set an object. Returns the value from
-  // cef_translator_test_scoped_library_t::get_value(). This tests input and
-  // execution of a library-side object type.
+  /// Set an object. Returns the value from
+  /// cef_translator_test_scoped_library_t::get_value(). This tests input and
+  /// execution of a library-side object type.
   ///
   int(CEF_CALLBACK* set_own_ptr_library)(
       struct _cef_translator_test_t* self,
       struct _cef_translator_test_scoped_library_t* val);
 
   ///
-  // Set an object. Returns the object passed in. This tests input and output of
-  // a library-side object type.
+  /// Set an object. Returns the object passed in. This tests input and output
+  /// of a library-side object type.
   ///
   struct _cef_translator_test_scoped_library_t*(
       CEF_CALLBACK* set_own_ptr_library_and_return)(
@@ -411,37 +399,35 @@
       struct _cef_translator_test_scoped_library_t* val);
 
   ///
-  // Set a child object. Returns the value from
-  // cef_translator_test_scoped_library_t::get_value(). This tests input of a
-  // library- side child object type and execution as the parent type.
+  /// Set a child object. Returns the value from
+  /// cef_translator_test_scoped_library_t::get_value(). This tests input of a
+  /// library- side child object type and execution as the parent type.
   ///
   int(CEF_CALLBACK* set_child_own_ptr_library)(
       struct _cef_translator_test_t* self,
       struct _cef_translator_test_scoped_library_child_t* val);
 
   ///
-  // Set a child object. Returns the object as the parent type. This tests input
-  // of a library-side child object type and return as the parent type.
+  /// Set a child object. Returns the object as the parent type. This tests
+  /// input of a library-side child object type and return as the parent type.
   ///
   struct _cef_translator_test_scoped_library_t*(
       CEF_CALLBACK* set_child_own_ptr_library_and_return_parent)(
       struct _cef_translator_test_t* self,
       struct _cef_translator_test_scoped_library_child_t* val);
 
-  // CLIENT-SIDE OWNPTR VALUES
-
   ///
-  // Set an object. Returns the value from
-  // cef_translator_test_scoped_client_t::get_value(). This tests input and
-  // execution of a client-side object type.
+  /// Set an object. Returns the value from
+  /// cef_translator_test_scoped_client_t::get_value(). This tests input and
+  /// execution of a client-side object type.
   ///
   int(CEF_CALLBACK* set_own_ptr_client)(
       struct _cef_translator_test_t* self,
       struct _cef_translator_test_scoped_client_t* val);
 
   ///
-  // Set an object. Returns the handler passed in. This tests input and output
-  // of a client-side object type.
+  /// Set an object. Returns the handler passed in. This tests input and output
+  /// of a client-side object type.
   ///
   struct _cef_translator_test_scoped_client_t*(
       CEF_CALLBACK* set_own_ptr_client_and_return)(
@@ -449,45 +435,43 @@
       struct _cef_translator_test_scoped_client_t* val);
 
   ///
-  // Set a child object. Returns the value from
-  // cef_translator_test_scoped_client_t::get_value(). This tests input of a
-  // client- side child object type and execution as the parent type.
+  /// Set a child object. Returns the value from
+  /// cef_translator_test_scoped_client_t::get_value(). This tests input of a
+  /// client- side child object type and execution as the parent type.
   ///
   int(CEF_CALLBACK* set_child_own_ptr_client)(
       struct _cef_translator_test_t* self,
       struct _cef_translator_test_scoped_client_child_t* val);
 
   ///
-  // Set a child object. Returns the object as the parent type. This tests input
-  // of a client-side child object type and return as the parent type.
+  /// Set a child object. Returns the object as the parent type. This tests
+  /// input of a client-side child object type and return as the parent type.
   ///
   struct _cef_translator_test_scoped_client_t*(
       CEF_CALLBACK* set_child_own_ptr_client_and_return_parent)(
       struct _cef_translator_test_t* self,
       struct _cef_translator_test_scoped_client_child_t* val);
 
-  // LIBRARY-SIDE RAWPTR VALUES
-
   ///
-  // Set an object. Returns the value from
-  // cef_translator_test_scoped_library_t::get_value(). This tests input and
-  // execution of a library-side object type.
+  /// Set an object. Returns the value from
+  /// cef_translator_test_scoped_library_t::get_value(). This tests input and
+  /// execution of a library-side object type.
   ///
   int(CEF_CALLBACK* set_raw_ptr_library)(
       struct _cef_translator_test_t* self,
       struct _cef_translator_test_scoped_library_t* val);
 
   ///
-  // Set a child object. Returns the value from
-  // cef_translator_test_scoped_library_t::get_value(). This tests input of a
-  // library- side child object type and execution as the parent type.
+  /// Set a child object. Returns the value from
+  /// cef_translator_test_scoped_library_t::get_value(). This tests input of a
+  /// library- side child object type and execution as the parent type.
   ///
   int(CEF_CALLBACK* set_child_raw_ptr_library)(
       struct _cef_translator_test_t* self,
       struct _cef_translator_test_scoped_library_child_t* val);
 
   ///
-  // Set an object list vlaue.
+  /// Set an object list vlaue.
   ///
   int(CEF_CALLBACK* set_raw_ptr_library_list)(
       struct _cef_translator_test_t* self,
@@ -496,28 +480,26 @@
       int val1,
       int val2);
 
-  // CLIENT-SIDE RAWPTR VALUES
-
   ///
-  // Set an object. Returns the value from
-  // cef_translator_test_scoped_client_t::get_value(). This tests input and
-  // execution of a client-side object type.
+  /// Set an object. Returns the value from
+  /// cef_translator_test_scoped_client_t::get_value(). This tests input and
+  /// execution of a client-side object type.
   ///
   int(CEF_CALLBACK* set_raw_ptr_client)(
       struct _cef_translator_test_t* self,
       struct _cef_translator_test_scoped_client_t* val);
 
   ///
-  // Set a child object. Returns the value from
-  // cef_translator_test_scoped_client_t::get_value(). This tests input of a
-  // client- side child object type and execution as the parent type.
+  /// Set a child object. Returns the value from
+  /// cef_translator_test_scoped_client_t::get_value(). This tests input of a
+  /// client- side child object type and execution as the parent type.
   ///
   int(CEF_CALLBACK* set_child_raw_ptr_client)(
       struct _cef_translator_test_t* self,
       struct _cef_translator_test_scoped_client_child_t* val);
 
   ///
-  // Set an object list vlaue.
+  /// Set an object list vlaue.
   ///
   int(CEF_CALLBACK* set_raw_ptr_client_list)(
       struct _cef_translator_test_t* self,
@@ -528,27 +510,27 @@
 } cef_translator_test_t;
 
 ///
-// Create the test object.
+/// Create the test object.
 ///
-CEF_EXPORT cef_translator_test_t* cef_translator_test_create();
+CEF_EXPORT cef_translator_test_t* cef_translator_test_create(void);
 
 ///
-// Library-side test object for RefPtr.
+/// Library-side test object for RefPtr.
 ///
 typedef struct _cef_translator_test_ref_ptr_library_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Return a value.
+  /// Return a value.
   ///
   int(CEF_CALLBACK* get_value)(
       struct _cef_translator_test_ref_ptr_library_t* self);
 
   ///
-  // Set a value.
+  /// Set a value.
   ///
   void(CEF_CALLBACK* set_value)(
       struct _cef_translator_test_ref_ptr_library_t* self,
@@ -556,28 +538,28 @@
 } cef_translator_test_ref_ptr_library_t;
 
 ///
-// Create the test object.
+/// Create the test object.
 ///
 CEF_EXPORT cef_translator_test_ref_ptr_library_t*
 cef_translator_test_ref_ptr_library_create(int value);
 
 ///
-// Library-side child test object for RefPtr.
+/// Library-side child test object for RefPtr.
 ///
 typedef struct _cef_translator_test_ref_ptr_library_child_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_translator_test_ref_ptr_library_t base;
 
   ///
-  // Return a value.
+  /// Return a value.
   ///
   int(CEF_CALLBACK* get_other_value)(
       struct _cef_translator_test_ref_ptr_library_child_t* self);
 
   ///
-  // Set a value.
+  /// Set a value.
   ///
   void(CEF_CALLBACK* set_other_value)(
       struct _cef_translator_test_ref_ptr_library_child_t* self,
@@ -585,28 +567,28 @@
 } cef_translator_test_ref_ptr_library_child_t;
 
 ///
-// Create the test object.
+/// Create the test object.
 ///
 CEF_EXPORT cef_translator_test_ref_ptr_library_child_t*
 cef_translator_test_ref_ptr_library_child_create(int value, int other_value);
 
 ///
-// Another library-side child test object for RefPtr.
+/// Another library-side child test object for RefPtr.
 ///
 typedef struct _cef_translator_test_ref_ptr_library_child_child_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_translator_test_ref_ptr_library_child_t base;
 
   ///
-  // Return a value.
+  /// Return a value.
   ///
   int(CEF_CALLBACK* get_other_other_value)(
       struct _cef_translator_test_ref_ptr_library_child_child_t* self);
 
   ///
-  // Set a value.
+  /// Set a value.
   ///
   void(CEF_CALLBACK* set_other_other_value)(
       struct _cef_translator_test_ref_ptr_library_child_child_t* self,
@@ -614,7 +596,7 @@
 } cef_translator_test_ref_ptr_library_child_child_t;
 
 ///
-// Create the test object.
+/// Create the test object.
 ///
 CEF_EXPORT cef_translator_test_ref_ptr_library_child_child_t*
 cef_translator_test_ref_ptr_library_child_child_create(int value,
@@ -622,54 +604,54 @@
                                                        int other_other_value);
 
 ///
-// Client-side test object for RefPtr.
+/// Client-side test object for RefPtr.
 ///
 typedef struct _cef_translator_test_ref_ptr_client_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Return a value.
+  /// Return a value.
   ///
   int(CEF_CALLBACK* get_value)(
       struct _cef_translator_test_ref_ptr_client_t* self);
 } cef_translator_test_ref_ptr_client_t;
 
 ///
-// Client-side child test object for RefPtr.
+/// Client-side child test object for RefPtr.
 ///
 typedef struct _cef_translator_test_ref_ptr_client_child_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_translator_test_ref_ptr_client_t base;
 
   ///
-  // Return a value.
+  /// Return a value.
   ///
   int(CEF_CALLBACK* get_other_value)(
       struct _cef_translator_test_ref_ptr_client_child_t* self);
 } cef_translator_test_ref_ptr_client_child_t;
 
 ///
-// Library-side test object for OwnPtr/RawPtr.
+/// Library-side test object for OwnPtr/RawPtr.
 ///
 typedef struct _cef_translator_test_scoped_library_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_scoped_t base;
 
   ///
-  // Return a value.
+  /// Return a value.
   ///
   int(CEF_CALLBACK* get_value)(
       struct _cef_translator_test_scoped_library_t* self);
 
   ///
-  // Set a value.
+  /// Set a value.
   ///
   void(CEF_CALLBACK* set_value)(
       struct _cef_translator_test_scoped_library_t* self,
@@ -677,28 +659,28 @@
 } cef_translator_test_scoped_library_t;
 
 ///
-// Create the test object.
+/// Create the test object.
 ///
 CEF_EXPORT cef_translator_test_scoped_library_t*
 cef_translator_test_scoped_library_create(int value);
 
 ///
-// Library-side child test object for OwnPtr/RawPtr.
+/// Library-side child test object for OwnPtr/RawPtr.
 ///
 typedef struct _cef_translator_test_scoped_library_child_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_translator_test_scoped_library_t base;
 
   ///
-  // Return a value.
+  /// Return a value.
   ///
   int(CEF_CALLBACK* get_other_value)(
       struct _cef_translator_test_scoped_library_child_t* self);
 
   ///
-  // Set a value.
+  /// Set a value.
   ///
   void(CEF_CALLBACK* set_other_value)(
       struct _cef_translator_test_scoped_library_child_t* self,
@@ -706,28 +688,28 @@
 } cef_translator_test_scoped_library_child_t;
 
 ///
-// Create the test object.
+/// Create the test object.
 ///
 CEF_EXPORT cef_translator_test_scoped_library_child_t*
 cef_translator_test_scoped_library_child_create(int value, int other_value);
 
 ///
-// Another library-side child test object for OwnPtr/RawPtr.
+/// Another library-side child test object for OwnPtr/RawPtr.
 ///
 typedef struct _cef_translator_test_scoped_library_child_child_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_translator_test_scoped_library_child_t base;
 
   ///
-  // Return a value.
+  /// Return a value.
   ///
   int(CEF_CALLBACK* get_other_other_value)(
       struct _cef_translator_test_scoped_library_child_child_t* self);
 
   ///
-  // Set a value.
+  /// Set a value.
   ///
   void(CEF_CALLBACK* set_other_other_value)(
       struct _cef_translator_test_scoped_library_child_child_t* self,
@@ -735,7 +717,7 @@
 } cef_translator_test_scoped_library_child_child_t;
 
 ///
-// Create the test object.
+/// Create the test object.
 ///
 CEF_EXPORT cef_translator_test_scoped_library_child_child_t*
 cef_translator_test_scoped_library_child_child_create(int value,
@@ -743,32 +725,32 @@
                                                       int other_other_value);
 
 ///
-// Client-side test object for OwnPtr/RawPtr.
+/// Client-side test object for OwnPtr/RawPtr.
 ///
 typedef struct _cef_translator_test_scoped_client_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_scoped_t base;
 
   ///
-  // Return a value.
+  /// Return a value.
   ///
   int(CEF_CALLBACK* get_value)(
       struct _cef_translator_test_scoped_client_t* self);
 } cef_translator_test_scoped_client_t;
 
 ///
-// Client-side child test object for OwnPtr/RawPtr.
+/// Client-side child test object for OwnPtr/RawPtr.
 ///
 typedef struct _cef_translator_test_scoped_client_child_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_translator_test_scoped_client_t base;
 
   ///
-  // Return a value.
+  /// Return a value.
   ///
   int(CEF_CALLBACK* get_other_value)(
       struct _cef_translator_test_scoped_client_child_t* self);
diff --git a/src/include/capi/views/cef_box_layout_capi.h b/src/include/capi/views/cef_box_layout_capi.h
index 8328d67..f053f01 100644
--- a/src/include/capi/views/cef_box_layout_capi.h
+++ b/src/include/capi/views/cef_box_layout_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=ddf96505520b7f8df0662d9f66221917a665b029$
+// $hash=31153d0702b646d310e74f04e256c0f5915b8caa$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_BOX_LAYOUT_CAPI_H_
@@ -49,33 +49,33 @@
 struct _cef_view_t;
 
 ///
-// A Layout manager that arranges child views vertically or horizontally in a
-// side-by-side fashion with spacing around and between the child views. The
-// child views are always sized according to their preferred size. If the host's
-// bounds provide insufficient space, child views will be clamped. Excess space
-// will not be distributed. Methods must be called on the browser process UI
-// thread unless otherwise indicated.
+/// A Layout manager that arranges child views vertically or horizontally in a
+/// side-by-side fashion with spacing around and between the child views. The
+/// child views are always sized according to their preferred size. If the
+/// host's bounds provide insufficient space, child views will be clamped.
+/// Excess space will not be distributed. Methods must be called on the browser
+/// process UI thread unless otherwise indicated.
 ///
 typedef struct _cef_box_layout_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_layout_t base;
 
   ///
-  // Set the flex weight for the given |view|. Using the preferred size as the
-  // basis, free space along the main axis is distributed to views in the ratio
-  // of their flex weights. Similarly, if the views will overflow the parent,
-  // space is subtracted in these ratios. A flex of 0 means this view is not
-  // resized. Flex values must not be negative.
+  /// Set the flex weight for the given |view|. Using the preferred size as the
+  /// basis, free space along the main axis is distributed to views in the ratio
+  /// of their flex weights. Similarly, if the views will overflow the parent,
+  /// space is subtracted in these ratios. A flex of 0 means this view is not
+  /// resized. Flex values must not be negative.
   ///
   void(CEF_CALLBACK* set_flex_for_view)(struct _cef_box_layout_t* self,
                                         struct _cef_view_t* view,
                                         int flex);
 
   ///
-  // Clears the flex for the given |view|, causing it to use the default flex
-  // specified via cef_box_layout_tSettings.default_flex.
+  /// Clears the flex for the given |view|, causing it to use the default flex
+  /// specified via cef_box_layout_tSettings.default_flex.
   ///
   void(CEF_CALLBACK* clear_flex_for_view)(struct _cef_box_layout_t* self,
                                           struct _cef_view_t* view);
diff --git a/src/include/capi/views/cef_browser_view_capi.h b/src/include/capi/views/cef_browser_view_capi.h
index f597c87..fbc8cbc 100644
--- a/src/include/capi/views/cef_browser_view_capi.h
+++ b/src/include/capi/views/cef_browser_view_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=3ac114f5bd9aa0e6d62e7540e9205adce485a09d$
+// $hash=bc80e7f1e467a4e0943dcbf7ea6d08366817d5ca$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_BROWSER_VIEW_CAPI_H_
@@ -49,41 +49,58 @@
 #endif
 
 ///
-// A View hosting a cef_browser_t instance. Methods must be called on the
-// browser process UI thread unless otherwise indicated.
+/// A View hosting a cef_browser_t instance. Methods must be called on the
+/// browser process UI thread unless otherwise indicated.
 ///
 typedef struct _cef_browser_view_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_view_t base;
 
   ///
-  // Returns the cef_browser_t hosted by this BrowserView. Will return NULL if
-  // the browser has not yet been created or has already been destroyed.
+  /// Returns the cef_browser_t hosted by this BrowserView. Will return NULL if
+  /// the browser has not yet been created or has already been destroyed.
   ///
   struct _cef_browser_t*(CEF_CALLBACK* get_browser)(
       struct _cef_browser_view_t* self);
 
   ///
-  // Sets whether accelerators registered with cef_window_t::SetAccelerator are
-  // triggered before or after the event is sent to the cef_browser_t. If
-  // |prefer_accelerators| is true (1) then the matching accelerator will be
-  // triggered immediately and the event will not be sent to the cef_browser_t.
-  // If |prefer_accelerators| is false (0) then the matching accelerator will
-  // only be triggered if the event is not handled by web content or by
-  // cef_keyboard_handler_t. The default value is false (0).
+  /// Returns the Chrome toolbar associated with this BrowserView. Only
+  /// supported when using the Chrome runtime. The cef_browser_view_delegate_t::
+  /// get_chrome_toolbar_type() function must return a value other than
+  /// CEF_CTT_NONE and the toolbar will not be available until after this
+  /// BrowserView is added to a cef_window_t and
+  /// cef_view_delegate_t::on_window_changed() has been called.
+  ///
+  struct _cef_view_t*(CEF_CALLBACK* get_chrome_toolbar)(
+      struct _cef_browser_view_t* self);
+
+  ///
+  /// Sets whether normal priority accelerators are first forwarded to the web
+  /// content (`keydown` event handler) or cef_keyboard_handler_t. Normal
+  /// priority accelerators can be registered via cef_window_t::SetAccelerator
+  /// (with |high_priority|=false (0)) or internally for standard accelerators
+  /// supported by the Chrome runtime. If |prefer_accelerators| is true (1) then
+  /// the matching accelerator will be triggered immediately (calling
+  /// cef_window_delegate_t::OnAccelerator or
+  /// cef_command_handler_t::OnChromeCommand respectively) and the event will
+  /// not be forwarded to the web content or cef_keyboard_handler_t first. If
+  /// |prefer_accelerators| is false (0) then the matching accelerator will only
+  /// be triggered if the event is not handled by web content (`keydown` event
+  /// handler that calls `event.preventDefault()`) or by cef_keyboard_handler_t.
+  /// The default value is false (0).
   ///
   void(CEF_CALLBACK* set_prefer_accelerators)(struct _cef_browser_view_t* self,
                                               int prefer_accelerators);
 } cef_browser_view_t;
 
 ///
-// Create a new BrowserView. The underlying cef_browser_t will not be created
-// until this view is added to the views hierarchy. The optional |extra_info|
-// parameter provides an opportunity to specify extra information specific to
-// the created browser that will be passed to
-// cef_render_process_handler_t::on_browser_created() in the render process.
+/// Create a new BrowserView. The underlying cef_browser_t will not be created
+/// until this view is added to the views hierarchy. The optional |extra_info|
+/// parameter provides an opportunity to specify extra information specific to
+/// the created browser that will be passed to
+/// cef_render_process_handler_t::on_browser_created() in the render process.
 ///
 CEF_EXPORT cef_browser_view_t* cef_browser_view_create(
     struct _cef_client_t* client,
@@ -94,7 +111,7 @@
     struct _cef_browser_view_delegate_t* delegate);
 
 ///
-// Returns the BrowserView associated with |browser|.
+/// Returns the BrowserView associated with |browser|.
 ///
 CEF_EXPORT cef_browser_view_t* cef_browser_view_get_for_browser(
     struct _cef_browser_t* browser);
diff --git a/src/include/capi/views/cef_browser_view_delegate_capi.h b/src/include/capi/views/cef_browser_view_delegate_capi.h
index d707169..5c24e3e 100644
--- a/src/include/capi/views/cef_browser_view_delegate_capi.h
+++ b/src/include/capi/views/cef_browser_view_delegate_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=f850005cb52b08b69b803fc020c77fc7f623839c$
+// $hash=9e8dd2187d592f7556cbee0db3ceab851f9aae13$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_BROWSER_VIEW_DELEGATE_CAPI_H_
@@ -51,21 +51,21 @@
 struct _cef_browser_view_t;
 
 ///
-// Implement this structure to handle BrowserView events. The functions of this
-// structure will be called on the browser process UI thread unless otherwise
-// indicated.
+/// Implement this structure to handle BrowserView events. The functions of this
+/// structure will be called on the browser process UI thread unless otherwise
+/// indicated.
 ///
 typedef struct _cef_browser_view_delegate_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_view_delegate_t base;
 
   ///
-  // Called when |browser| associated with |browser_view| is created. This
-  // function will be called after cef_life_span_handler_t::on_after_created()
-  // is called for |browser| and before on_popup_browser_view_created() is
-  // called for |browser|'s parent delegate if |browser| is a popup.
+  /// Called when |browser| associated with |browser_view| is created. This
+  /// function will be called after cef_life_span_handler_t::on_after_created()
+  /// is called for |browser| and before on_popup_browser_view_created() is
+  /// called for |browser|'s parent delegate if |browser| is a popup.
   ///
   void(CEF_CALLBACK* on_browser_created)(
       struct _cef_browser_view_delegate_t* self,
@@ -73,10 +73,10 @@
       struct _cef_browser_t* browser);
 
   ///
-  // Called when |browser| associated with |browser_view| is destroyed. Release
-  // all references to |browser| and do not attempt to execute any functions on
-  // |browser| after this callback returns. This function will be called before
-  // cef_life_span_handler_t::on_before_close() is called for |browser|.
+  /// Called when |browser| associated with |browser_view| is destroyed. Release
+  /// all references to |browser| and do not attempt to execute any functions on
+  /// |browser| after this callback returns. This function will be called before
+  /// cef_life_span_handler_t::on_before_close() is called for |browser|.
   ///
   void(CEF_CALLBACK* on_browser_destroyed)(
       struct _cef_browser_view_delegate_t* self,
@@ -84,11 +84,11 @@
       struct _cef_browser_t* browser);
 
   ///
-  // Called before a new popup BrowserView is created. The popup originated from
-  // |browser_view|. |settings| and |client| are the values returned from
-  // cef_life_span_handler_t::on_before_popup(). |is_devtools| will be true (1)
-  // if the popup will be a DevTools browser. Return the delegate that will be
-  // used for the new popup BrowserView.
+  /// Called before a new popup BrowserView is created. The popup originated
+  /// from |browser_view|. |settings| and |client| are the values returned from
+  /// cef_life_span_handler_t::on_before_popup(). |is_devtools| will be true (1)
+  /// if the popup will be a DevTools browser. Return the delegate that will be
+  /// used for the new popup BrowserView.
   ///
   struct _cef_browser_view_delegate_t*(
       CEF_CALLBACK* get_delegate_for_popup_browser_view)(
@@ -99,19 +99,48 @@
       int is_devtools);
 
   ///
-  // Called after |popup_browser_view| is created. This function will be called
-  // after cef_life_span_handler_t::on_after_created() and on_browser_created()
-  // are called for the new popup browser. The popup originated from
-  // |browser_view|. |is_devtools| will be true (1) if the popup is a DevTools
-  // browser. Optionally add |popup_browser_view| to the views hierarchy
-  // yourself and return true (1). Otherwise return false (0) and a default
-  // cef_window_t will be created for the popup.
+  /// Called after |popup_browser_view| is created. This function will be called
+  /// after cef_life_span_handler_t::on_after_created() and on_browser_created()
+  /// are called for the new popup browser. The popup originated from
+  /// |browser_view|. |is_devtools| will be true (1) if the popup is a DevTools
+  /// browser. Optionally add |popup_browser_view| to the views hierarchy
+  /// yourself and return true (1). Otherwise return false (0) and a default
+  /// cef_window_t will be created for the popup.
   ///
   int(CEF_CALLBACK* on_popup_browser_view_created)(
       struct _cef_browser_view_delegate_t* self,
       struct _cef_browser_view_t* browser_view,
       struct _cef_browser_view_t* popup_browser_view,
       int is_devtools);
+
+  ///
+  /// Returns the Chrome toolbar type that will be available via
+  /// cef_browser_view_t::get_chrome_toolbar(). See that function for related
+  /// documentation.
+  ///
+  cef_chrome_toolbar_type_t(CEF_CALLBACK* get_chrome_toolbar_type)(
+      struct _cef_browser_view_delegate_t* self,
+      struct _cef_browser_view_t* browser_view);
+
+  ///
+  /// Return true (1) to create frameless windows for Document picture-in-
+  /// picture popups. Content in frameless windows should specify draggable
+  /// regions using "-webkit-app-region: drag" CSS.
+  ///
+  int(CEF_CALLBACK* use_frameless_window_for_picture_in_picture)(
+      struct _cef_browser_view_delegate_t* self,
+      struct _cef_browser_view_t* browser_view);
+
+  ///
+  /// Called when |browser_view| receives a gesture command. Return true (1) to
+  /// handle (or disable) a |gesture_command| or false (0) to propagate the
+  /// gesture to the browser for default handling. With the Chrome runtime these
+  /// commands can also be handled via cef_command_handler_t::OnChromeCommand.
+  ///
+  int(CEF_CALLBACK* on_gesture_command)(
+      struct _cef_browser_view_delegate_t* self,
+      struct _cef_browser_view_t* browser_view,
+      cef_gesture_command_t gesture_command);
 } cef_browser_view_delegate_t;
 
 #ifdef __cplusplus
diff --git a/src/include/capi/views/cef_button_capi.h b/src/include/capi/views/cef_button_capi.h
index 2c3d992..e4fa681 100644
--- a/src/include/capi/views/cef_button_capi.h
+++ b/src/include/capi/views/cef_button_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=066842f6905c8eed7de1fc8cf831e06801029b97$
+// $hash=6580dc6ef6c20d5d78dc0160982b9ef57c939f86$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_BUTTON_CAPI_H_
@@ -49,48 +49,49 @@
 struct _cef_label_button_t;
 
 ///
-// A View representing a button. Depending on the specific type, the button
-// could be implemented by a native control or custom rendered. Methods must be
-// called on the browser process UI thread unless otherwise indicated.
+/// A View representing a button. Depending on the specific type, the button
+/// could be implemented by a native control or custom rendered. Methods must be
+/// called on the browser process UI thread unless otherwise indicated.
 ///
 typedef struct _cef_button_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_view_t base;
 
   ///
-  // Returns this Button as a LabelButton or NULL if this is not a LabelButton.
+  /// Returns this Button as a LabelButton or NULL if this is not a LabelButton.
   ///
   struct _cef_label_button_t*(CEF_CALLBACK* as_label_button)(
       struct _cef_button_t* self);
 
   ///
-  // Sets the current display state of the Button.
+  /// Sets the current display state of the Button.
   ///
   void(CEF_CALLBACK* set_state)(struct _cef_button_t* self,
                                 cef_button_state_t state);
 
   ///
-  // Returns the current display state of the Button.
+  /// Returns the current display state of the Button.
   ///
   cef_button_state_t(CEF_CALLBACK* get_state)(struct _cef_button_t* self);
 
   ///
-  // Sets the Button will use an ink drop effect for displaying state changes.
+  /// Sets the Button will use an ink drop effect for displaying state changes.
   ///
   void(CEF_CALLBACK* set_ink_drop_enabled)(struct _cef_button_t* self,
                                            int enabled);
 
   ///
-  // Sets the tooltip text that will be displayed when the user hovers the mouse
-  // cursor over the Button.
+  /// Sets the tooltip text that will be displayed when the user hovers the
+  /// mouse cursor over the Button.
   ///
   void(CEF_CALLBACK* set_tooltip_text)(struct _cef_button_t* self,
                                        const cef_string_t* tooltip_text);
 
   ///
-  // Sets the accessible name that will be exposed to assistive technology (AT).
+  /// Sets the accessible name that will be exposed to assistive technology
+  /// (AT).
   ///
   void(CEF_CALLBACK* set_accessible_name)(struct _cef_button_t* self,
                                           const cef_string_t* name);
diff --git a/src/include/capi/views/cef_button_delegate_capi.h b/src/include/capi/views/cef_button_delegate_capi.h
index da67a0b..caa27da 100644
--- a/src/include/capi/views/cef_button_delegate_capi.h
+++ b/src/include/capi/views/cef_button_delegate_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=71def746b63431f9aa779bbb67e85bc2e0176615$
+// $hash=9843593667569cf8755386ab2d884620087a36b8$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_BUTTON_DELEGATE_CAPI_H_
@@ -49,24 +49,24 @@
 struct _cef_button_t;
 
 ///
-// Implement this structure to handle Button events. The functions of this
-// structure will be called on the browser process UI thread unless otherwise
-// indicated.
+/// Implement this structure to handle Button events. The functions of this
+/// structure will be called on the browser process UI thread unless otherwise
+/// indicated.
 ///
 typedef struct _cef_button_delegate_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_view_delegate_t base;
 
   ///
-  // Called when |button| is pressed.
+  /// Called when |button| is pressed.
   ///
   void(CEF_CALLBACK* on_button_pressed)(struct _cef_button_delegate_t* self,
                                         struct _cef_button_t* button);
 
   ///
-  // Called when the state of |button| changes.
+  /// Called when the state of |button| changes.
   ///
   void(CEF_CALLBACK* on_button_state_changed)(
       struct _cef_button_delegate_t* self,
diff --git a/src/include/capi/views/cef_display_capi.h b/src/include/capi/views/cef_display_capi.h
index 89bb5ad..031cb51 100644
--- a/src/include/capi/views/cef_display_capi.h
+++ b/src/include/capi/views/cef_display_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=422243fda6e1404222aca7bdd4e7b84b961a9626$
+// $hash=2e9acfffaf1dbc70f0c76fcf58a5190326b131ba$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_DISPLAY_CAPI_H_
@@ -47,98 +47,127 @@
 #endif
 
 ///
-// This structure typically, but not always, corresponds to a physical display
-// connected to the system. A fake Display may exist on a headless system, or a
-// Display may correspond to a remote, virtual display. All size and position
-// values are in density independent pixels (DIP) unless otherwise indicated.
-// Methods must be called on the browser process UI thread unless otherwise
-// indicated.
+/// This structure typically, but not always, corresponds to a physical display
+/// connected to the system. A fake Display may exist on a headless system, or a
+/// Display may correspond to a remote, virtual display. All size and position
+/// values are in density independent pixel (DIP) coordinates unless otherwise
+/// indicated. Methods must be called on the browser process UI thread unless
+/// otherwise indicated.
 ///
 typedef struct _cef_display_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns the unique identifier for this Display.
+  /// Returns the unique identifier for this Display.
   ///
-  int64(CEF_CALLBACK* get_id)(struct _cef_display_t* self);
+  int64_t(CEF_CALLBACK* get_id)(struct _cef_display_t* self);
 
   ///
-  // Returns this Display's device pixel scale factor. This specifies how much
-  // the UI should be scaled when the actual output has more pixels than
-  // standard displays (which is around 100~120dpi). The potential return values
-  // differ by platform.
+  /// Returns this Display's device pixel scale factor. This specifies how much
+  /// the UI should be scaled when the actual output has more pixels than
+  /// standard displays (which is around 100~120dpi). The potential return
+  /// values differ by platform.
   ///
   float(CEF_CALLBACK* get_device_scale_factor)(struct _cef_display_t* self);
 
   ///
-  // Convert |point| from density independent pixels (DIP) to pixel coordinates
-  // using this Display's device scale factor.
+  /// Convert |point| from DIP coordinates to pixel coordinates using this
+  /// Display's device scale factor.
   ///
   void(CEF_CALLBACK* convert_point_to_pixels)(struct _cef_display_t* self,
                                               cef_point_t* point);
 
   ///
-  // Convert |point| from pixel coordinates to density independent pixels (DIP)
-  // using this Display's device scale factor.
+  /// Convert |point| from pixel coordinates to DIP coordinates using this
+  /// Display's device scale factor.
   ///
   void(CEF_CALLBACK* convert_point_from_pixels)(struct _cef_display_t* self,
                                                 cef_point_t* point);
 
   ///
-  // Returns this Display's bounds. This is the full size of the display.
+  /// Returns this Display's bounds in DIP screen coordinates. This is the full
+  /// size of the display.
   ///
   cef_rect_t(CEF_CALLBACK* get_bounds)(struct _cef_display_t* self);
 
   ///
-  // Returns this Display's work area. This excludes areas of the display that
-  // are occupied for window manager toolbars, etc.
+  /// Returns this Display's work area in DIP screen coordinates. This excludes
+  /// areas of the display that are occupied with window manager toolbars, etc.
   ///
   cef_rect_t(CEF_CALLBACK* get_work_area)(struct _cef_display_t* self);
 
   ///
-  // Returns this Display's rotation in degrees.
+  /// Returns this Display's rotation in degrees.
   ///
   int(CEF_CALLBACK* get_rotation)(struct _cef_display_t* self);
 } cef_display_t;
 
 ///
-// Returns the primary Display.
+/// Returns the primary Display.
 ///
-CEF_EXPORT cef_display_t* cef_display_get_primary();
+CEF_EXPORT cef_display_t* cef_display_get_primary(void);
 
 ///
-// Returns the Display nearest |point|. Set |input_pixel_coords| to true (1) if
-// |point| is in pixel coordinates instead of density independent pixels (DIP).
+/// Returns the Display nearest |point|. Set |input_pixel_coords| to true (1) if
+/// |point| is in pixel screen coordinates instead of DIP screen coordinates.
 ///
 CEF_EXPORT cef_display_t* cef_display_get_nearest_point(
     const cef_point_t* point,
     int input_pixel_coords);
 
 ///
-// Returns the Display that most closely intersects |bounds|.  Set
-// |input_pixel_coords| to true (1) if |bounds| is in pixel coordinates instead
-// of density independent pixels (DIP).
+/// Returns the Display that most closely intersects |bounds|.  Set
+/// |input_pixel_coords| to true (1) if |bounds| is in pixel screen coordinates
+/// instead of DIP screen coordinates.
 ///
 CEF_EXPORT cef_display_t* cef_display_get_matching_bounds(
     const cef_rect_t* bounds,
     int input_pixel_coords);
 
 ///
-// Returns the total number of Displays. Mirrored displays are excluded; this
-// function is intended to return the number of distinct, usable displays.
+/// Returns the total number of Displays. Mirrored displays are excluded; this
+/// function is intended to return the number of distinct, usable displays.
 ///
-CEF_EXPORT size_t cef_display_get_count();
+CEF_EXPORT size_t cef_display_get_count(void);
 
 ///
-// Returns all Displays. Mirrored displays are excluded; this function is
-// intended to return distinct, usable displays.
+/// Returns all Displays. Mirrored displays are excluded; this function is
+/// intended to return distinct, usable displays.
 ///
 CEF_EXPORT void cef_display_get_alls(size_t* displaysCount,
                                      cef_display_t** displays);
 
+///
+/// Convert |point| from DIP screen coordinates to pixel screen coordinates.
+/// This function is only used on Windows.
+///
+CEF_EXPORT cef_point_t
+cef_display_convert_screen_point_to_pixels(const cef_point_t* point);
+
+///
+/// Convert |point| from pixel screen coordinates to DIP screen coordinates.
+/// This function is only used on Windows.
+///
+CEF_EXPORT cef_point_t
+cef_display_convert_screen_point_from_pixels(const cef_point_t* point);
+
+///
+/// Convert |rect| from DIP screen coordinates to pixel screen coordinates. This
+/// function is only used on Windows.
+///
+CEF_EXPORT cef_rect_t
+cef_display_convert_screen_rect_to_pixels(const cef_rect_t* rect);
+
+///
+/// Convert |rect| from pixel screen coordinates to DIP screen coordinates. This
+/// function is only used on Windows.
+///
+CEF_EXPORT cef_rect_t
+cef_display_convert_screen_rect_from_pixels(const cef_rect_t* rect);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/include/capi/views/cef_fill_layout_capi.h b/src/include/capi/views/cef_fill_layout_capi.h
index edd56c6..c9ae6d9 100644
--- a/src/include/capi/views/cef_fill_layout_capi.h
+++ b/src/include/capi/views/cef_fill_layout_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=14016ebf5d63f625436aebd14396e403b673703f$
+// $hash=fdb3457ac8b18ad3cf0144af5886586dd675c8f8$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_FILL_LAYOUT_CAPI_H_
@@ -47,13 +47,13 @@
 #endif
 
 ///
-// A simple Layout that causes the associated Panel's one child to be sized to
-// match the bounds of its parent. Methods must be called on the browser process
-// UI thread unless otherwise indicated.
+/// A simple Layout that causes the associated Panel's one child to be sized to
+/// match the bounds of its parent. Methods must be called on the browser
+/// process UI thread unless otherwise indicated.
 ///
 typedef struct _cef_fill_layout_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_layout_t base;
 } cef_fill_layout_t;
diff --git a/src/include/capi/views/cef_label_button_capi.h b/src/include/capi/views/cef_label_button_capi.h
index 05a930f..07b3876 100644
--- a/src/include/capi/views/cef_label_button_capi.h
+++ b/src/include/capi/views/cef_label_button_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=d947a566036f44439f352aea45098dfb46043b9a$
+// $hash=eee5b9ebfa58617d5e6fa969e27cc9e378fddb22$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_LABEL_BUTTON_CAPI_H_
@@ -51,104 +51,105 @@
 struct _cef_menu_button_t;
 
 ///
-// LabelButton is a button with optional text and/or icon. Methods must be
-// called on the browser process UI thread unless otherwise indicated.
+/// LabelButton is a button with optional text and/or icon. Methods must be
+/// called on the browser process UI thread unless otherwise indicated.
 ///
 typedef struct _cef_label_button_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_button_t base;
 
   ///
-  // Returns this LabelButton as a MenuButton or NULL if this is not a
-  // MenuButton.
+  /// Returns this LabelButton as a MenuButton or NULL if this is not a
+  /// MenuButton.
   ///
   struct _cef_menu_button_t*(CEF_CALLBACK* as_menu_button)(
       struct _cef_label_button_t* self);
 
   ///
-  // Sets the text shown on the LabelButton. By default |text| will also be used
-  // as the accessible name.
+  /// Sets the text shown on the LabelButton. By default |text| will also be
+  /// used as the accessible name.
   ///
   void(CEF_CALLBACK* set_text)(struct _cef_label_button_t* self,
                                const cef_string_t* text);
 
   ///
-  // Returns the text shown on the LabelButton.
+  /// Returns the text shown on the LabelButton.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_text)(
       struct _cef_label_button_t* self);
 
   ///
-  // Sets the image shown for |button_state|. When this Button is drawn if no
-  // image exists for the current state then the image for
-  // CEF_BUTTON_STATE_NORMAL, if any, will be shown.
+  /// Sets the image shown for |button_state|. When this Button is drawn if no
+  /// image exists for the current state then the image for
+  /// CEF_BUTTON_STATE_NORMAL, if any, will be shown.
   ///
   void(CEF_CALLBACK* set_image)(struct _cef_label_button_t* self,
                                 cef_button_state_t button_state,
                                 struct _cef_image_t* image);
 
   ///
-  // Returns the image shown for |button_state|. If no image exists for that
-  // state then the image for CEF_BUTTON_STATE_NORMAL will be returned.
+  /// Returns the image shown for |button_state|. If no image exists for that
+  /// state then the image for CEF_BUTTON_STATE_NORMAL will be returned.
   ///
   struct _cef_image_t*(CEF_CALLBACK* get_image)(
       struct _cef_label_button_t* self,
       cef_button_state_t button_state);
 
   ///
-  // Sets the text color shown for the specified button |for_state| to |color|.
+  /// Sets the text color shown for the specified button |for_state| to |color|.
   ///
   void(CEF_CALLBACK* set_text_color)(struct _cef_label_button_t* self,
                                      cef_button_state_t for_state,
                                      cef_color_t color);
 
   ///
-  // Sets the text colors shown for the non-disabled states to |color|.
+  /// Sets the text colors shown for the non-disabled states to |color|.
   ///
   void(CEF_CALLBACK* set_enabled_text_colors)(struct _cef_label_button_t* self,
                                               cef_color_t color);
 
   ///
-  // Sets the font list. The format is "<FONT_FAMILY_LIST>,[STYLES] <SIZE>",
-  // where: - FONT_FAMILY_LIST is a comma-separated list of font family names, -
-  // STYLES is an optional space-separated list of style names (case-sensitive
-  //   "Bold" and "Italic" are supported), and
-  // - SIZE is an integer font size in pixels with the suffix "px".
-  //
-  // Here are examples of valid font description strings: - "Arial, Helvetica,
-  // Bold Italic 14px" - "Arial, 14px"
+  /// Sets the font list. The format is "<FONT_FAMILY_LIST>,[STYLES] <SIZE>",
+  /// where: - FONT_FAMILY_LIST is a comma-separated list of font family names,
+  /// - STYLES is an optional space-separated list of style names (case-
+  /// sensitive
+  ///   "Bold" and "Italic" are supported), and
+  /// - SIZE is an integer font size in pixels with the suffix "px".
+  ///
+  /// Here are examples of valid font description strings: - "Arial, Helvetica,
+  /// Bold Italic 14px" - "Arial, 14px"
   ///
   void(CEF_CALLBACK* set_font_list)(struct _cef_label_button_t* self,
                                     const cef_string_t* font_list);
 
   ///
-  // Sets the horizontal alignment; reversed in RTL. Default is
-  // CEF_HORIZONTAL_ALIGNMENT_CENTER.
+  /// Sets the horizontal alignment; reversed in RTL. Default is
+  /// CEF_HORIZONTAL_ALIGNMENT_CENTER.
   ///
   void(CEF_CALLBACK* set_horizontal_alignment)(
       struct _cef_label_button_t* self,
       cef_horizontal_alignment_t alignment);
 
   ///
-  // Reset the minimum size of this LabelButton to |size|.
+  /// Reset the minimum size of this LabelButton to |size|.
   ///
   void(CEF_CALLBACK* set_minimum_size)(struct _cef_label_button_t* self,
                                        const cef_size_t* size);
 
   ///
-  // Reset the maximum size of this LabelButton to |size|.
+  /// Reset the maximum size of this LabelButton to |size|.
   ///
   void(CEF_CALLBACK* set_maximum_size)(struct _cef_label_button_t* self,
                                        const cef_size_t* size);
 } cef_label_button_t;
 
 ///
-// Create a new LabelButton. A |delegate| must be provided to handle the button
-// click. |text| will be shown on the LabelButton and used as the default
-// accessible name.
+/// Create a new LabelButton. A |delegate| must be provided to handle the button
+/// click. |text| will be shown on the LabelButton and used as the default
+/// accessible name.
 ///
 CEF_EXPORT cef_label_button_t* cef_label_button_create(
     struct _cef_button_delegate_t* delegate,
diff --git a/src/include/capi/views/cef_layout_capi.h b/src/include/capi/views/cef_layout_capi.h
index 2ecfd7b..5430a45 100644
--- a/src/include/capi/views/cef_layout_capi.h
+++ b/src/include/capi/views/cef_layout_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=7db4a977d7fbbff0783d0334e53fa47f00fc9fac$
+// $hash=c4a17c07bb2a3518fc5b7350efdc13ffeb803747$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_LAYOUT_CAPI_H_
@@ -50,30 +50,30 @@
 struct _cef_fill_layout_t;
 
 ///
-// A Layout handles the sizing of the children of a Panel according to
-// implementation-specific heuristics. Methods must be called on the browser
-// process UI thread unless otherwise indicated.
+/// A Layout handles the sizing of the children of a Panel according to
+/// implementation-specific heuristics. Methods must be called on the browser
+/// process UI thread unless otherwise indicated.
 ///
 typedef struct _cef_layout_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns this Layout as a BoxLayout or NULL if this is not a BoxLayout.
+  /// Returns this Layout as a BoxLayout or NULL if this is not a BoxLayout.
   ///
   struct _cef_box_layout_t*(CEF_CALLBACK* as_box_layout)(
       struct _cef_layout_t* self);
 
   ///
-  // Returns this Layout as a FillLayout or NULL if this is not a FillLayout.
+  /// Returns this Layout as a FillLayout or NULL if this is not a FillLayout.
   ///
   struct _cef_fill_layout_t*(CEF_CALLBACK* as_fill_layout)(
       struct _cef_layout_t* self);
 
   ///
-  // Returns true (1) if this Layout is valid.
+  /// Returns true (1) if this Layout is valid.
   ///
   int(CEF_CALLBACK* is_valid)(struct _cef_layout_t* self);
 } cef_layout_t;
diff --git a/src/include/capi/views/cef_menu_button_capi.h b/src/include/capi/views/cef_menu_button_capi.h
index 37f1bb8..85cec0f 100644
--- a/src/include/capi/views/cef_menu_button_capi.h
+++ b/src/include/capi/views/cef_menu_button_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=8e1972f8c40d4c7a708f32016dbfeb5bf2a2ff0b$
+// $hash=dcfa5d39d1355b2c675637a13378f43376a8053e$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_MENU_BUTTON_CAPI_H_
@@ -49,22 +49,23 @@
 #endif
 
 ///
-// MenuButton is a button with optional text, icon and/or menu marker that shows
-// a menu when clicked with the left mouse button. All size and position values
-// are in density independent pixels (DIP) unless otherwise indicated. Methods
-// must be called on the browser process UI thread unless otherwise indicated.
+/// MenuButton is a button with optional text, icon and/or menu marker that
+/// shows a menu when clicked with the left mouse button. All size and position
+/// values are in density independent pixels (DIP) unless otherwise indicated.
+/// Methods must be called on the browser process UI thread unless otherwise
+/// indicated.
 ///
 typedef struct _cef_menu_button_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_label_button_t base;
 
   ///
-  // Show a menu with contents |menu_model|. |screen_point| specifies the menu
-  // position in screen coordinates. |anchor_position| specifies how the menu
-  // will be anchored relative to |screen_point|. This function should be called
-  // from cef_menu_button_delegate_t::on_menu_button_pressed().
+  /// Show a menu with contents |menu_model|. |screen_point| specifies the menu
+  /// position in screen coordinates. |anchor_position| specifies how the menu
+  /// will be anchored relative to |screen_point|. This function should be
+  /// called from cef_menu_button_delegate_t::on_menu_button_pressed().
   ///
   void(CEF_CALLBACK* show_menu)(struct _cef_menu_button_t* self,
                                 struct _cef_menu_model_t* menu_model,
@@ -72,20 +73,20 @@
                                 cef_menu_anchor_position_t anchor_position);
 
   ///
-  // Show the menu for this button. Results in a call to
-  // cef_menu_button_delegate_t::on_menu_button_pressed().
+  /// Show the menu for this button. Results in a call to
+  /// cef_menu_button_delegate_t::on_menu_button_pressed().
   ///
   void(CEF_CALLBACK* trigger_menu)(struct _cef_menu_button_t* self);
 } cef_menu_button_t;
 
 ///
-// Create a new MenuButton. A |delegate| must be provided to call show_menu()
-// when the button is clicked. |text| will be shown on the MenuButton and used
-// as the default accessible name. If |with_frame| is true (1) the button will
-// have a visible frame at all times, center alignment, additional padding and a
-// default minimum size of 70x33 DIP. If |with_frame| is false (0) the button
-// will only have a visible frame on hover/press, left alignment, less padding
-// and no default minimum size.
+/// Create a new MenuButton. A |delegate| must be provided to call show_menu()
+/// when the button is clicked. |text| will be shown on the MenuButton and used
+/// as the default accessible name. If |with_frame| is true (1) the button will
+/// have a visible frame at all times, center alignment, additional padding and
+/// a default minimum size of 70x33 DIP. If |with_frame| is false (0) the button
+/// will only have a visible frame on hover/press, left alignment, less padding
+/// and no default minimum size.
 ///
 CEF_EXPORT cef_menu_button_t* cef_menu_button_create(
     struct _cef_menu_button_delegate_t* delegate,
diff --git a/src/include/capi/views/cef_menu_button_delegate_capi.h b/src/include/capi/views/cef_menu_button_delegate_capi.h
index b2c4a5c..5d93864 100644
--- a/src/include/capi/views/cef_menu_button_delegate_capi.h
+++ b/src/include/capi/views/cef_menu_button_delegate_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=6668ddfd94bb501f0cb35b2c23043333c1cafe63$
+// $hash=38177cad78713d382b81f8b8aa4372402c62fac7$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_MENU_BUTTON_DELEGATE_CAPI_H_
@@ -49,31 +49,31 @@
 struct _cef_menu_button_t;
 
 ///
-// MenuButton pressed lock is released when this object is destroyed.
+/// MenuButton pressed lock is released when this object is destroyed.
 ///
 typedef struct _cef_menu_button_pressed_lock_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 } cef_menu_button_pressed_lock_t;
 
 ///
-// Implement this structure to handle MenuButton events. The functions of this
-// structure will be called on the browser process UI thread unless otherwise
-// indicated.
+/// Implement this structure to handle MenuButton events. The functions of this
+/// structure will be called on the browser process UI thread unless otherwise
+/// indicated.
 ///
 typedef struct _cef_menu_button_delegate_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_button_delegate_t base;
 
   ///
-  // Called when |button| is pressed. Call cef_menu_button_t::show_menu() to
-  // show a popup menu at |screen_point|. When showing a custom popup such as a
-  // window keep a reference to |button_pressed_lock| until the popup is hidden
-  // to maintain the pressed button state.
+  /// Called when |button| is pressed. Call cef_menu_button_t::show_menu() to
+  /// show a popup menu at |screen_point|. When showing a custom popup such as a
+  /// window keep a reference to |button_pressed_lock| until the popup is hidden
+  /// to maintain the pressed button state.
   ///
   void(CEF_CALLBACK* on_menu_button_pressed)(
       struct _cef_menu_button_delegate_t* self,
diff --git a/src/include/capi/views/cef_overlay_controller_capi.h b/src/include/capi/views/cef_overlay_controller_capi.h
new file mode 100644
index 0000000..8084bfd
--- /dev/null
+++ b/src/include/capi/views/cef_overlay_controller_capi.h
@@ -0,0 +1,217 @@
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool and should not edited
+// by hand. See the translator.README.txt file in the tools directory for
+// more information.
+//
+// $hash=a5a2c7fe2c285b45268eee1710a8549ab12727f3$
+//
+
+#ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_OVERLAY_CONTROLLER_CAPI_H_
+#define CEF_INCLUDE_CAPI_VIEWS_CEF_OVERLAY_CONTROLLER_CAPI_H_
+#pragma once
+
+#include "include/capi/cef_base_capi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _cef_view_t;
+struct _cef_window_t;
+
+///
+/// Controller for an overlay that contains a contents View added via
+/// cef_window_t::AddOverlayView. Methods exposed by this controller should be
+/// called in preference to functions of the same name exposed by the contents
+/// View unless otherwise indicated. Methods must be called on the browser
+/// process UI thread unless otherwise indicated.
+///
+typedef struct _cef_overlay_controller_t {
+  ///
+  /// Base structure.
+  ///
+  cef_base_ref_counted_t base;
+
+  ///
+  /// Returns true (1) if this object is valid.
+  ///
+  int(CEF_CALLBACK* is_valid)(struct _cef_overlay_controller_t* self);
+
+  ///
+  /// Returns true (1) if this object is the same as |that| object.
+  ///
+  int(CEF_CALLBACK* is_same)(struct _cef_overlay_controller_t* self,
+                             struct _cef_overlay_controller_t* that);
+
+  ///
+  /// Returns the contents View for this overlay.
+  ///
+  struct _cef_view_t*(CEF_CALLBACK* get_contents_view)(
+      struct _cef_overlay_controller_t* self);
+
+  ///
+  /// Returns the top-level Window hosting this overlay. Use this function
+  /// instead of calling get_window() on the contents View.
+  ///
+  struct _cef_window_t*(CEF_CALLBACK* get_window)(
+      struct _cef_overlay_controller_t* self);
+
+  ///
+  /// Returns the docking mode for this overlay.
+  ///
+  cef_docking_mode_t(CEF_CALLBACK* get_docking_mode)(
+      struct _cef_overlay_controller_t* self);
+
+  ///
+  /// Destroy this overlay.
+  ///
+  void(CEF_CALLBACK* destroy)(struct _cef_overlay_controller_t* self);
+
+  ///
+  /// Sets the bounds (size and position) of this overlay. This will set the
+  /// bounds of the contents View to match and trigger a re-layout if necessary.
+  /// |bounds| is in parent coordinates and any insets configured on this
+  /// overlay will be ignored. Use this function only for overlays created with
+  /// a docking mode value of CEF_DOCKING_MODE_CUSTOM. With other docking modes
+  /// modify the insets of this overlay and/or layout of the contents View and
+  /// call size_to_preferred_size() instead to calculate the new size and re-
+  /// position the overlay if necessary.
+  ///
+  void(CEF_CALLBACK* set_bounds)(struct _cef_overlay_controller_t* self,
+                                 const cef_rect_t* bounds);
+
+  ///
+  /// Returns the bounds (size and position) of this overlay in parent
+  /// coordinates.
+  ///
+  cef_rect_t(CEF_CALLBACK* get_bounds)(struct _cef_overlay_controller_t* self);
+
+  ///
+  /// Returns the bounds (size and position) of this overlay in DIP screen
+  /// coordinates.
+  ///
+  cef_rect_t(CEF_CALLBACK* get_bounds_in_screen)(
+      struct _cef_overlay_controller_t* self);
+
+  ///
+  /// Sets the size of this overlay without changing the position. This will set
+  /// the size of the contents View to match and trigger a re-layout if
+  /// necessary. |size| is in parent coordinates and any insets configured on
+  /// this overlay will be ignored. Use this function only for overlays created
+  /// with a docking mode value of CEF_DOCKING_MODE_CUSTOM. With other docking
+  /// modes modify the insets of this overlay and/or layout of the contents View
+  /// and call size_to_preferred_size() instead to calculate the new size and
+  /// re-position the overlay if necessary.
+  ///
+  void(CEF_CALLBACK* set_size)(struct _cef_overlay_controller_t* self,
+                               const cef_size_t* size);
+
+  ///
+  /// Returns the size of this overlay in parent coordinates.
+  ///
+  cef_size_t(CEF_CALLBACK* get_size)(struct _cef_overlay_controller_t* self);
+
+  ///
+  /// Sets the position of this overlay without changing the size. |position| is
+  /// in parent coordinates and any insets configured on this overlay will be
+  /// ignored. Use this function only for overlays created with a docking mode
+  /// value of CEF_DOCKING_MODE_CUSTOM. With other docking modes modify the
+  /// insets of this overlay and/or layout of the contents View and call
+  /// size_to_preferred_size() instead to calculate the new size and re-position
+  /// the overlay if necessary.
+  ///
+  void(CEF_CALLBACK* set_position)(struct _cef_overlay_controller_t* self,
+                                   const cef_point_t* position);
+
+  ///
+  /// Returns the position of this overlay in parent coordinates.
+  ///
+  cef_point_t(CEF_CALLBACK* get_position)(
+      struct _cef_overlay_controller_t* self);
+
+  ///
+  /// Sets the insets for this overlay. |insets| is in parent coordinates. Use
+  /// this function only for overlays created with a docking mode value other
+  /// than CEF_DOCKING_MODE_CUSTOM.
+  ///
+  void(CEF_CALLBACK* set_insets)(struct _cef_overlay_controller_t* self,
+                                 const cef_insets_t* insets);
+
+  ///
+  /// Returns the insets for this overlay in parent coordinates.
+  ///
+  cef_insets_t(CEF_CALLBACK* get_insets)(
+      struct _cef_overlay_controller_t* self);
+
+  ///
+  /// Size this overlay to its preferred size and trigger a re-layout if
+  /// necessary. The position of overlays created with a docking mode value of
+  /// CEF_DOCKING_MODE_CUSTOM will not be modified by calling this function.
+  /// With other docking modes this function may re-position the overlay if
+  /// necessary to accommodate the new size and any insets configured on the
+  /// contents View.
+  ///
+  void(CEF_CALLBACK* size_to_preferred_size)(
+      struct _cef_overlay_controller_t* self);
+
+  ///
+  /// Sets whether this overlay is visible. Overlays are hidden by default. If
+  /// this overlay is hidden then it and any child Views will not be drawn and,
+  /// if any of those Views currently have focus, then focus will also be
+  /// cleared. Painting is scheduled as needed.
+  ///
+  void(CEF_CALLBACK* set_visible)(struct _cef_overlay_controller_t* self,
+                                  int visible);
+
+  ///
+  /// Returns whether this overlay is visible. A View may be visible but still
+  /// not drawn in a Window if any parent Views are hidden. Call is_drawn() to
+  /// determine whether this overlay and all parent Views are visible and will
+  /// be drawn.
+  ///
+  int(CEF_CALLBACK* is_visible)(struct _cef_overlay_controller_t* self);
+
+  ///
+  /// Returns whether this overlay is visible and drawn in a Window. A View is
+  /// drawn if it and all parent Views are visible. To determine if the
+  /// containing Window is visible to the user on-screen call is_visible() on
+  /// the Window.
+  ///
+  int(CEF_CALLBACK* is_drawn)(struct _cef_overlay_controller_t* self);
+} cef_overlay_controller_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // CEF_INCLUDE_CAPI_VIEWS_CEF_OVERLAY_CONTROLLER_CAPI_H_
diff --git a/src/include/capi/views/cef_panel_capi.h b/src/include/capi/views/cef_panel_capi.h
index cf82398..658b005 100644
--- a/src/include/capi/views/cef_panel_capi.h
+++ b/src/include/capi/views/cef_panel_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=28db02fcdd51238b61d74195dae36fe23e0717da$
+// $hash=40d350f75893a1e4307b282317d55f0fceae3baf$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_PANEL_CAPI_H_
@@ -53,93 +53,93 @@
 struct _cef_window_t;
 
 ///
-// A Panel is a container in the views hierarchy that can contain other Views as
-// children. Methods must be called on the browser process UI thread unless
-// otherwise indicated.
+/// A Panel is a container in the views hierarchy that can contain other Views
+/// as children. Methods must be called on the browser process UI thread unless
+/// otherwise indicated.
 ///
 typedef struct _cef_panel_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_view_t base;
 
   ///
-  // Returns this Panel as a Window or NULL if this is not a Window.
+  /// Returns this Panel as a Window or NULL if this is not a Window.
   ///
   struct _cef_window_t*(CEF_CALLBACK* as_window)(struct _cef_panel_t* self);
 
   ///
-  // Set this Panel's Layout to FillLayout and return the FillLayout object.
+  /// Set this Panel's Layout to FillLayout and return the FillLayout object.
   ///
   struct _cef_fill_layout_t*(CEF_CALLBACK* set_to_fill_layout)(
       struct _cef_panel_t* self);
 
   ///
-  // Set this Panel's Layout to BoxLayout and return the BoxLayout object.
+  /// Set this Panel's Layout to BoxLayout and return the BoxLayout object.
   ///
   struct _cef_box_layout_t*(CEF_CALLBACK* set_to_box_layout)(
       struct _cef_panel_t* self,
-      const struct _cef_box_layout_settings_t* settings);
+      const cef_box_layout_settings_t* settings);
 
   ///
-  // Get the Layout.
+  /// Get the Layout.
   ///
   struct _cef_layout_t*(CEF_CALLBACK* get_layout)(struct _cef_panel_t* self);
 
   ///
-  // Lay out the child Views (set their bounds based on sizing heuristics
-  // specific to the current Layout).
+  /// Lay out the child Views (set their bounds based on sizing heuristics
+  /// specific to the current Layout).
   ///
   void(CEF_CALLBACK* layout)(struct _cef_panel_t* self);
 
   ///
-  // Add a child View.
+  /// Add a child View.
   ///
   void(CEF_CALLBACK* add_child_view)(struct _cef_panel_t* self,
                                      struct _cef_view_t* view);
 
   ///
-  // Add a child View at the specified |index|. If |index| matches the result of
-  // GetChildCount() then the View will be added at the end.
+  /// Add a child View at the specified |index|. If |index| matches the result
+  /// of GetChildCount() then the View will be added at the end.
   ///
   void(CEF_CALLBACK* add_child_view_at)(struct _cef_panel_t* self,
                                         struct _cef_view_t* view,
                                         int index);
 
   ///
-  // Move the child View to the specified |index|. A negative value for |index|
-  // will move the View to the end.
+  /// Move the child View to the specified |index|. A negative value for |index|
+  /// will move the View to the end.
   ///
   void(CEF_CALLBACK* reorder_child_view)(struct _cef_panel_t* self,
                                          struct _cef_view_t* view,
                                          int index);
 
   ///
-  // Remove a child View. The View can then be added to another Panel.
+  /// Remove a child View. The View can then be added to another Panel.
   ///
   void(CEF_CALLBACK* remove_child_view)(struct _cef_panel_t* self,
                                         struct _cef_view_t* view);
 
   ///
-  // Remove all child Views. The removed Views will be deleted if the client
-  // holds no references to them.
+  /// Remove all child Views. The removed Views will be deleted if the client
+  /// holds no references to them.
   ///
   void(CEF_CALLBACK* remove_all_child_views)(struct _cef_panel_t* self);
 
   ///
-  // Returns the number of child Views.
+  /// Returns the number of child Views.
   ///
   size_t(CEF_CALLBACK* get_child_view_count)(struct _cef_panel_t* self);
 
   ///
-  // Returns the child View at the specified |index|.
+  /// Returns the child View at the specified |index|.
   ///
   struct _cef_view_t*(
       CEF_CALLBACK* get_child_view_at)(struct _cef_panel_t* self, int index);
 } cef_panel_t;
 
 ///
-// Create a new Panel.
+/// Create a new Panel.
 ///
 CEF_EXPORT cef_panel_t* cef_panel_create(
     struct _cef_panel_delegate_t* delegate);
diff --git a/src/include/capi/views/cef_panel_delegate_capi.h b/src/include/capi/views/cef_panel_delegate_capi.h
index 9e178b7..227762d 100644
--- a/src/include/capi/views/cef_panel_delegate_capi.h
+++ b/src/include/capi/views/cef_panel_delegate_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=8a0ded4e62ff61b04fc1694228905daa995197b4$
+// $hash=e8bdae70e1f16fba3a5e01d9e215a02f13291ff5$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_PANEL_DELEGATE_CAPI_H_
@@ -47,13 +47,13 @@
 #endif
 
 ///
-// Implement this structure to handle Panel events. The functions of this
-// structure will be called on the browser process UI thread unless otherwise
-// indicated.
+/// Implement this structure to handle Panel events. The functions of this
+/// structure will be called on the browser process UI thread unless otherwise
+/// indicated.
 ///
 typedef struct _cef_panel_delegate_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_view_delegate_t base;
 } cef_panel_delegate_t;
diff --git a/src/include/capi/views/cef_scroll_view_capi.h b/src/include/capi/views/cef_scroll_view_capi.h
index 89de452..dd503c2 100644
--- a/src/include/capi/views/cef_scroll_view_capi.h
+++ b/src/include/capi/views/cef_scroll_view_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=3b9789f2149c3e6d6a2e671e5427c19654442ede$
+// $hash=e3aa3fbb265a600d498884b0fbb852fc5bbf8856$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_SCROLL_VIEW_CAPI_H_
@@ -47,60 +47,60 @@
 #endif
 
 ///
-// A ScrollView will show horizontal and/or vertical scrollbars when necessary
-// based on the size of the attached content view. Methods must be called on the
-// browser process UI thread unless otherwise indicated.
+/// A ScrollView will show horizontal and/or vertical scrollbars when necessary
+/// based on the size of the attached content view. Methods must be called on
+/// the browser process UI thread unless otherwise indicated.
 ///
 typedef struct _cef_scroll_view_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_view_t base;
 
   ///
-  // Set the content View. The content View must have a specified size (e.g. via
-  // cef_view_t::SetBounds or cef_view_delegate_t::GetPreferredSize).
+  /// Set the content View. The content View must have a specified size (e.g.
+  /// via cef_view_t::SetBounds or cef_view_delegate_t::GetPreferredSize).
   ///
   void(CEF_CALLBACK* set_content_view)(struct _cef_scroll_view_t* self,
                                        struct _cef_view_t* view);
 
   ///
-  // Returns the content View.
+  /// Returns the content View.
   ///
   struct _cef_view_t*(CEF_CALLBACK* get_content_view)(
       struct _cef_scroll_view_t* self);
 
   ///
-  // Returns the visible region of the content View.
+  /// Returns the visible region of the content View.
   ///
   cef_rect_t(CEF_CALLBACK* get_visible_content_rect)(
       struct _cef_scroll_view_t* self);
 
   ///
-  // Returns true (1) if the horizontal scrollbar is currently showing.
+  /// Returns true (1) if the horizontal scrollbar is currently showing.
   ///
   int(CEF_CALLBACK* has_horizontal_scrollbar)(struct _cef_scroll_view_t* self);
 
   ///
-  // Returns the height of the horizontal scrollbar.
+  /// Returns the height of the horizontal scrollbar.
   ///
   int(CEF_CALLBACK* get_horizontal_scrollbar_height)(
       struct _cef_scroll_view_t* self);
 
   ///
-  // Returns true (1) if the vertical scrollbar is currently showing.
+  /// Returns true (1) if the vertical scrollbar is currently showing.
   ///
   int(CEF_CALLBACK* has_vertical_scrollbar)(struct _cef_scroll_view_t* self);
 
   ///
-  // Returns the width of the vertical scrollbar.
+  /// Returns the width of the vertical scrollbar.
   ///
   int(CEF_CALLBACK* get_vertical_scrollbar_width)(
       struct _cef_scroll_view_t* self);
 } cef_scroll_view_t;
 
 ///
-// Create a new ScrollView.
+/// Create a new ScrollView.
 ///
 CEF_EXPORT cef_scroll_view_t* cef_scroll_view_create(
     struct _cef_view_delegate_t* delegate);
diff --git a/src/include/capi/views/cef_textfield_capi.h b/src/include/capi/views/cef_textfield_capi.h
index 1b49658..c525f21 100644
--- a/src/include/capi/views/cef_textfield_capi.h
+++ b/src/include/capi/views/cef_textfield_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=71ba0e5714400e2bea3ca564cab4527d95e4b52c$
+// $hash=7d5a43282c9847c5c842abd5de023f4c5c69a9f0$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_TEXTFIELD_CAPI_H_
@@ -48,166 +48,167 @@
 #endif
 
 ///
-// A Textfield supports editing of text. This control is custom rendered with no
-// platform-specific code. Methods must be called on the browser process UI
-// thread unless otherwise indicated.
+/// A Textfield supports editing of text. This control is custom rendered with
+/// no platform-specific code. Methods must be called on the browser process UI
+/// thread unless otherwise indicated.
 ///
 typedef struct _cef_textfield_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_view_t base;
 
   ///
-  // Sets whether the text will be displayed as asterisks.
+  /// Sets whether the text will be displayed as asterisks.
   ///
   void(CEF_CALLBACK* set_password_input)(struct _cef_textfield_t* self,
                                          int password_input);
 
   ///
-  // Returns true (1) if the text will be displayed as asterisks.
+  /// Returns true (1) if the text will be displayed as asterisks.
   ///
   int(CEF_CALLBACK* is_password_input)(struct _cef_textfield_t* self);
 
   ///
-  // Sets whether the text will read-only.
+  /// Sets whether the text will read-only.
   ///
   void(CEF_CALLBACK* set_read_only)(struct _cef_textfield_t* self,
                                     int read_only);
 
   ///
-  // Returns true (1) if the text is read-only.
+  /// Returns true (1) if the text is read-only.
   ///
   int(CEF_CALLBACK* is_read_only)(struct _cef_textfield_t* self);
 
   ///
-  // Returns the currently displayed text.
+  /// Returns the currently displayed text.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_text)(struct _cef_textfield_t* self);
 
   ///
-  // Sets the contents to |text|. The cursor will be moved to end of the text if
-  // the current position is outside of the text range.
+  /// Sets the contents to |text|. The cursor will be moved to end of the text
+  /// if the current position is outside of the text range.
   ///
   void(CEF_CALLBACK* set_text)(struct _cef_textfield_t* self,
                                const cef_string_t* text);
 
   ///
-  // Appends |text| to the previously-existing text.
+  /// Appends |text| to the previously-existing text.
   ///
   void(CEF_CALLBACK* append_text)(struct _cef_textfield_t* self,
                                   const cef_string_t* text);
 
   ///
-  // Inserts |text| at the current cursor position replacing any selected text.
+  /// Inserts |text| at the current cursor position replacing any selected text.
   ///
   void(CEF_CALLBACK* insert_or_replace_text)(struct _cef_textfield_t* self,
                                              const cef_string_t* text);
 
   ///
-  // Returns true (1) if there is any selected text.
+  /// Returns true (1) if there is any selected text.
   ///
   int(CEF_CALLBACK* has_selection)(struct _cef_textfield_t* self);
 
   ///
-  // Returns the currently selected text.
+  /// Returns the currently selected text.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_selected_text)(
       struct _cef_textfield_t* self);
 
   ///
-  // Selects all text. If |reversed| is true (1) the range will end at the
-  // logical beginning of the text; this generally shows the leading portion of
-  // text that overflows its display area.
+  /// Selects all text. If |reversed| is true (1) the range will end at the
+  /// logical beginning of the text; this generally shows the leading portion of
+  /// text that overflows its display area.
   ///
   void(CEF_CALLBACK* select_all)(struct _cef_textfield_t* self, int reversed);
 
   ///
-  // Clears the text selection and sets the caret to the end.
+  /// Clears the text selection and sets the caret to the end.
   ///
   void(CEF_CALLBACK* clear_selection)(struct _cef_textfield_t* self);
 
   ///
-  // Returns the selected logical text range.
+  /// Returns the selected logical text range.
   ///
   cef_range_t(CEF_CALLBACK* get_selected_range)(struct _cef_textfield_t* self);
 
   ///
-  // Selects the specified logical text range.
+  /// Selects the specified logical text range.
   ///
   void(CEF_CALLBACK* select_range)(struct _cef_textfield_t* self,
                                    const cef_range_t* range);
 
   ///
-  // Returns the current cursor position.
+  /// Returns the current cursor position.
   ///
   size_t(CEF_CALLBACK* get_cursor_position)(struct _cef_textfield_t* self);
 
   ///
-  // Sets the text color.
+  /// Sets the text color.
   ///
   void(CEF_CALLBACK* set_text_color)(struct _cef_textfield_t* self,
                                      cef_color_t color);
 
   ///
-  // Returns the text color.
+  /// Returns the text color.
   ///
   cef_color_t(CEF_CALLBACK* get_text_color)(struct _cef_textfield_t* self);
 
   ///
-  // Sets the selection text color.
+  /// Sets the selection text color.
   ///
   void(CEF_CALLBACK* set_selection_text_color)(struct _cef_textfield_t* self,
                                                cef_color_t color);
 
   ///
-  // Returns the selection text color.
+  /// Returns the selection text color.
   ///
   cef_color_t(CEF_CALLBACK* get_selection_text_color)(
       struct _cef_textfield_t* self);
 
   ///
-  // Sets the selection background color.
+  /// Sets the selection background color.
   ///
   void(CEF_CALLBACK* set_selection_background_color)(
       struct _cef_textfield_t* self,
       cef_color_t color);
 
   ///
-  // Returns the selection background color.
+  /// Returns the selection background color.
   ///
   cef_color_t(CEF_CALLBACK* get_selection_background_color)(
       struct _cef_textfield_t* self);
 
   ///
-  // Sets the font list. The format is "<FONT_FAMILY_LIST>,[STYLES] <SIZE>",
-  // where: - FONT_FAMILY_LIST is a comma-separated list of font family names, -
-  // STYLES is an optional space-separated list of style names (case-sensitive
-  //   "Bold" and "Italic" are supported), and
-  // - SIZE is an integer font size in pixels with the suffix "px".
-  //
-  // Here are examples of valid font description strings: - "Arial, Helvetica,
-  // Bold Italic 14px" - "Arial, 14px"
+  /// Sets the font list. The format is "<FONT_FAMILY_LIST>,[STYLES] <SIZE>",
+  /// where: - FONT_FAMILY_LIST is a comma-separated list of font family names,
+  /// - STYLES is an optional space-separated list of style names (case-
+  /// sensitive
+  ///   "Bold" and "Italic" are supported), and
+  /// - SIZE is an integer font size in pixels with the suffix "px".
+  ///
+  /// Here are examples of valid font description strings: - "Arial, Helvetica,
+  /// Bold Italic 14px" - "Arial, 14px"
   ///
   void(CEF_CALLBACK* set_font_list)(struct _cef_textfield_t* self,
                                     const cef_string_t* font_list);
 
   ///
-  // Applies |color| to the specified |range| without changing the default
-  // color. If |range| is NULL the color will be set on the complete text
-  // contents.
+  /// Applies |color| to the specified |range| without changing the default
+  /// color. If |range| is NULL the color will be set on the complete text
+  /// contents.
   ///
   void(CEF_CALLBACK* apply_text_color)(struct _cef_textfield_t* self,
                                        cef_color_t color,
                                        const cef_range_t* range);
 
   ///
-  // Applies |style| to the specified |range| without changing the default
-  // style. If |add| is true (1) the style will be added, otherwise the style
-  // will be removed. If |range| is NULL the style will be set on the complete
-  // text contents.
+  /// Applies |style| to the specified |range| without changing the default
+  /// style. If |add| is true (1) the style will be added, otherwise the style
+  /// will be removed. If |range| is NULL the style will be set on the complete
+  /// text contents.
   ///
   void(CEF_CALLBACK* apply_text_style)(struct _cef_textfield_t* self,
                                        cef_text_style_t style,
@@ -215,56 +216,53 @@
                                        const cef_range_t* range);
 
   ///
-  // Returns true (1) if the action associated with the specified command id is
-  // enabled. See additional comments on execute_command().
+  /// Returns true (1) if the action associated with the specified command id is
+  /// enabled. See additional comments on execute_command().
   ///
   int(CEF_CALLBACK* is_command_enabled)(struct _cef_textfield_t* self,
-                                        int command_id);
+                                        cef_text_field_commands_t command_id);
 
   ///
-  // Performs the action associated with the specified command id. Valid values
-  // include IDS_APP_UNDO, IDS_APP_REDO, IDS_APP_CUT, IDS_APP_COPY,
-  // IDS_APP_PASTE, IDS_APP_DELETE, IDS_APP_SELECT_ALL, IDS_DELETE_* and
-  // IDS_MOVE_*. See include/cef_pack_strings.h for definitions.
+  /// Performs the action associated with the specified command id.
   ///
   void(CEF_CALLBACK* execute_command)(struct _cef_textfield_t* self,
-                                      int command_id);
+                                      cef_text_field_commands_t command_id);
 
   ///
-  // Clears Edit history.
+  /// Clears Edit history.
   ///
   void(CEF_CALLBACK* clear_edit_history)(struct _cef_textfield_t* self);
 
   ///
-  // Sets the placeholder text that will be displayed when the Textfield is
-  // NULL.
+  /// Sets the placeholder text that will be displayed when the Textfield is
+  /// NULL.
   ///
   void(CEF_CALLBACK* set_placeholder_text)(struct _cef_textfield_t* self,
                                            const cef_string_t* text);
 
   ///
-  // Returns the placeholder text that will be displayed when the Textfield is
-  // NULL.
+  /// Returns the placeholder text that will be displayed when the Textfield is
+  /// NULL.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_placeholder_text)(
       struct _cef_textfield_t* self);
 
   ///
-  // Sets the placeholder text color.
+  /// Sets the placeholder text color.
   ///
   void(CEF_CALLBACK* set_placeholder_text_color)(struct _cef_textfield_t* self,
                                                  cef_color_t color);
 
   ///
-  // Set the accessible name that will be exposed to assistive technology (AT).
+  /// Set the accessible name that will be exposed to assistive technology (AT).
   ///
   void(CEF_CALLBACK* set_accessible_name)(struct _cef_textfield_t* self,
                                           const cef_string_t* name);
 } cef_textfield_t;
 
 ///
-// Create a new Textfield.
+/// Create a new Textfield.
 ///
 CEF_EXPORT cef_textfield_t* cef_textfield_create(
     struct _cef_textfield_delegate_t* delegate);
diff --git a/src/include/capi/views/cef_textfield_delegate_capi.h b/src/include/capi/views/cef_textfield_delegate_capi.h
index 6442fe5..a14c0bf 100644
--- a/src/include/capi/views/cef_textfield_delegate_capi.h
+++ b/src/include/capi/views/cef_textfield_delegate_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=ba43938d4c400bcdd25e48b4f84758b18609813b$
+// $hash=482b091326684014bd799fef864e3dfdfc8693a1$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_TEXTFIELD_DELEGATE_CAPI_H_
@@ -49,27 +49,27 @@
 struct _cef_textfield_t;
 
 ///
-// Implement this structure to handle Textfield events. The functions of this
-// structure will be called on the browser process UI thread unless otherwise
-// indicated.
+/// Implement this structure to handle Textfield events. The functions of this
+/// structure will be called on the browser process UI thread unless otherwise
+/// indicated.
 ///
 typedef struct _cef_textfield_delegate_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_view_delegate_t base;
 
   ///
-  // Called when |textfield| recieves a keyboard event. |event| contains
-  // information about the keyboard event. Return true (1) if the keyboard event
-  // was handled or false (0) otherwise for default handling.
+  /// Called when |textfield| recieves a keyboard event. |event| contains
+  /// information about the keyboard event. Return true (1) if the keyboard
+  /// event was handled or false (0) otherwise for default handling.
   ///
   int(CEF_CALLBACK* on_key_event)(struct _cef_textfield_delegate_t* self,
                                   struct _cef_textfield_t* textfield,
-                                  const struct _cef_key_event_t* event);
+                                  const cef_key_event_t* event);
 
   ///
-  // Called after performing a user action that may change |textfield|.
+  /// Called after performing a user action that may change |textfield|.
   ///
   void(CEF_CALLBACK* on_after_user_action)(
       struct _cef_textfield_delegate_t* self,
diff --git a/src/include/capi/views/cef_view_capi.h b/src/include/capi/views/cef_view_capi.h
index e50c73d..5372f61 100644
--- a/src/include/capi/views/cef_view_capi.h
+++ b/src/include/capi/views/cef_view_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=45b421dfcf8ee7cf61b1991a336bc65d33fbe10a$
+// $hash=cb5950b283944d06312903eb554cc4c980713e98$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_VIEW_CAPI_H_
@@ -54,328 +54,352 @@
 struct _cef_window_t;
 
 ///
-// A View is a rectangle within the views View hierarchy. It is the base
-// structure for all Views. All size and position values are in density
-// independent pixels (DIP) unless otherwise indicated. Methods must be called
-// on the browser process UI thread unless otherwise indicated.
+/// A View is a rectangle within the views View hierarchy. It is the base
+/// structure for all Views. All size and position values are in density
+/// independent pixels (DIP) unless otherwise indicated. Methods must be called
+/// on the browser process UI thread unless otherwise indicated.
 ///
 typedef struct _cef_view_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Returns this View as a BrowserView or NULL if this is not a BrowserView.
+  /// Returns this View as a BrowserView or NULL if this is not a BrowserView.
   ///
   struct _cef_browser_view_t*(CEF_CALLBACK* as_browser_view)(
       struct _cef_view_t* self);
 
   ///
-  // Returns this View as a Button or NULL if this is not a Button.
+  /// Returns this View as a Button or NULL if this is not a Button.
   ///
   struct _cef_button_t*(CEF_CALLBACK* as_button)(struct _cef_view_t* self);
 
   ///
-  // Returns this View as a Panel or NULL if this is not a Panel.
+  /// Returns this View as a Panel or NULL if this is not a Panel.
   ///
   struct _cef_panel_t*(CEF_CALLBACK* as_panel)(struct _cef_view_t* self);
 
   ///
-  // Returns this View as a ScrollView or NULL if this is not a ScrollView.
+  /// Returns this View as a ScrollView or NULL if this is not a ScrollView.
   ///
   struct _cef_scroll_view_t*(CEF_CALLBACK* as_scroll_view)(
       struct _cef_view_t* self);
 
   ///
-  // Returns this View as a Textfield or NULL if this is not a Textfield.
+  /// Returns this View as a Textfield or NULL if this is not a Textfield.
   ///
   struct _cef_textfield_t*(CEF_CALLBACK* as_textfield)(
       struct _cef_view_t* self);
 
   ///
-  // Returns the type of this View as a string. Used primarily for testing
-  // purposes.
+  /// Returns the type of this View as a string. Used primarily for testing
+  /// purposes.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_type_string)(
       struct _cef_view_t* self);
 
   ///
-  // Returns a string representation of this View which includes the type and
-  // various type-specific identifying attributes. If |include_children| is true
-  // (1) any child Views will also be included. Used primarily for testing
-  // purposes.
+  /// Returns a string representation of this View which includes the type and
+  /// various type-specific identifying attributes. If |include_children| is
+  /// true (1) any child Views will also be included. Used primarily for testing
+  /// purposes.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* to_string)(struct _cef_view_t* self,
                                                  int include_children);
 
   ///
-  // Returns true (1) if this View is valid.
+  /// Returns true (1) if this View is valid.
   ///
   int(CEF_CALLBACK* is_valid)(struct _cef_view_t* self);
 
   ///
-  // Returns true (1) if this View is currently attached to another View. A View
-  // can only be attached to one View at a time.
+  /// Returns true (1) if this View is currently attached to another View. A
+  /// View can only be attached to one View at a time.
   ///
   int(CEF_CALLBACK* is_attached)(struct _cef_view_t* self);
 
   ///
-  // Returns true (1) if this View is the same as |that| View.
+  /// Returns true (1) if this View is the same as |that| View.
   ///
   int(CEF_CALLBACK* is_same)(struct _cef_view_t* self,
                              struct _cef_view_t* that);
 
   ///
-  // Returns the delegate associated with this View, if any.
+  /// Returns the delegate associated with this View, if any.
   ///
   struct _cef_view_delegate_t*(CEF_CALLBACK* get_delegate)(
       struct _cef_view_t* self);
 
   ///
-  // Returns the top-level Window hosting this View, if any.
+  /// Returns the top-level Window hosting this View, if any.
   ///
   struct _cef_window_t*(CEF_CALLBACK* get_window)(struct _cef_view_t* self);
 
   ///
-  // Returns the ID for this View.
+  /// Returns the ID for this View.
   ///
   int(CEF_CALLBACK* get_id)(struct _cef_view_t* self);
 
   ///
-  // Sets the ID for this View. ID should be unique within the subtree that you
-  // intend to search for it. 0 is the default ID for views.
+  /// Sets the ID for this View. ID should be unique within the subtree that you
+  /// intend to search for it. 0 is the default ID for views.
   ///
   void(CEF_CALLBACK* set_id)(struct _cef_view_t* self, int id);
 
   ///
-  // Returns the group id of this View, or -1 if not set.
+  /// Returns the group id of this View, or -1 if not set.
   ///
   int(CEF_CALLBACK* get_group_id)(struct _cef_view_t* self);
 
   ///
-  // A group id is used to tag Views which are part of the same logical group.
-  // Focus can be moved between views with the same group using the arrow keys.
-  // The group id is immutable once it's set.
+  /// A group id is used to tag Views which are part of the same logical group.
+  /// Focus can be moved between views with the same group using the arrow keys.
+  /// The group id is immutable once it's set.
   ///
   void(CEF_CALLBACK* set_group_id)(struct _cef_view_t* self, int group_id);
 
   ///
-  // Returns the View that contains this View, if any.
+  /// Returns the View that contains this View, if any.
   ///
   struct _cef_view_t*(CEF_CALLBACK* get_parent_view)(struct _cef_view_t* self);
 
   ///
-  // Recursively descends the view tree starting at this View, and returns the
-  // first child that it encounters with the given ID. Returns NULL if no
-  // matching child view is found.
+  /// Recursively descends the view tree starting at this View, and returns the
+  /// first child that it encounters with the given ID. Returns NULL if no
+  /// matching child view is found.
   ///
   struct _cef_view_t*(CEF_CALLBACK* get_view_for_id)(struct _cef_view_t* self,
                                                      int id);
 
   ///
-  // Sets the bounds (size and position) of this View. Position is in parent
-  // coordinates.
+  /// Sets the bounds (size and position) of this View. |bounds| is in parent
+  /// coordinates, or DIP screen coordinates if there is no parent.
   ///
   void(CEF_CALLBACK* set_bounds)(struct _cef_view_t* self,
                                  const cef_rect_t* bounds);
 
   ///
-  // Returns the bounds (size and position) of this View. Position is in parent
-  // coordinates.
+  /// Returns the bounds (size and position) of this View in parent coordinates,
+  /// or DIP screen coordinates if there is no parent.
   ///
   cef_rect_t(CEF_CALLBACK* get_bounds)(struct _cef_view_t* self);
 
   ///
-  // Returns the bounds (size and position) of this View. Position is in screen
-  // coordinates.
+  /// Returns the bounds (size and position) of this View in DIP screen
+  /// coordinates.
   ///
   cef_rect_t(CEF_CALLBACK* get_bounds_in_screen)(struct _cef_view_t* self);
 
   ///
-  // Sets the size of this View without changing the position.
+  /// Sets the size of this View without changing the position. |size| in parent
+  /// coordinates, or DIP screen coordinates if there is no parent.
   ///
   void(CEF_CALLBACK* set_size)(struct _cef_view_t* self,
                                const cef_size_t* size);
 
   ///
-  // Returns the size of this View.
+  /// Returns the size of this View in parent coordinates, or DIP screen
+  /// coordinates if there is no parent.
   ///
   cef_size_t(CEF_CALLBACK* get_size)(struct _cef_view_t* self);
 
   ///
-  // Sets the position of this View without changing the size. |position| is in
-  // parent coordinates.
+  /// Sets the position of this View without changing the size. |position| is in
+  /// parent coordinates, or DIP screen coordinates if there is no parent.
   ///
   void(CEF_CALLBACK* set_position)(struct _cef_view_t* self,
                                    const cef_point_t* position);
 
   ///
-  // Returns the position of this View. Position is in parent coordinates.
+  /// Returns the position of this View. Position is in parent coordinates, or
+  /// DIP screen coordinates if there is no parent.
   ///
   cef_point_t(CEF_CALLBACK* get_position)(struct _cef_view_t* self);
 
   ///
-  // Returns the size this View would like to be if enough space is available.
+  /// Sets the insets for this View. |insets| is in parent coordinates, or DIP
+  /// screen coordinates if there is no parent.
+  ///
+  void(CEF_CALLBACK* set_insets)(struct _cef_view_t* self,
+                                 const cef_insets_t* insets);
+
+  ///
+  /// Returns the insets for this View in parent coordinates, or DIP screen
+  /// coordinates if there is no parent.
+  ///
+  cef_insets_t(CEF_CALLBACK* get_insets)(struct _cef_view_t* self);
+
+  ///
+  /// Returns the size this View would like to be if enough space is available.
+  /// Size is in parent coordinates, or DIP screen coordinates if there is no
+  /// parent.
   ///
   cef_size_t(CEF_CALLBACK* get_preferred_size)(struct _cef_view_t* self);
 
   ///
-  // Size this View to its preferred size.
+  /// Size this View to its preferred size. Size is in parent coordinates, or
+  /// DIP screen coordinates if there is no parent.
   ///
   void(CEF_CALLBACK* size_to_preferred_size)(struct _cef_view_t* self);
 
   ///
-  // Returns the minimum size for this View.
+  /// Returns the minimum size for this View. Size is in parent coordinates, or
+  /// DIP screen coordinates if there is no parent.
   ///
   cef_size_t(CEF_CALLBACK* get_minimum_size)(struct _cef_view_t* self);
 
   ///
-  // Returns the maximum size for this View.
+  /// Returns the maximum size for this View. Size is in parent coordinates, or
+  /// DIP screen coordinates if there is no parent.
   ///
   cef_size_t(CEF_CALLBACK* get_maximum_size)(struct _cef_view_t* self);
 
   ///
-  // Returns the height necessary to display this View with the provided width.
+  /// Returns the height necessary to display this View with the provided width.
   ///
   int(CEF_CALLBACK* get_height_for_width)(struct _cef_view_t* self, int width);
 
   ///
-  // Indicate that this View and all parent Views require a re-layout. This
-  // ensures the next call to layout() will propagate to this View even if the
-  // bounds of parent Views do not change.
+  /// Indicate that this View and all parent Views require a re-layout. This
+  /// ensures the next call to layout() will propagate to this View even if the
+  /// bounds of parent Views do not change.
   ///
   void(CEF_CALLBACK* invalidate_layout)(struct _cef_view_t* self);
 
   ///
-  // Sets whether this View is visible. Windows are hidden by default and other
-  // views are visible by default. This View and any parent views must be set as
-  // visible for this View to be drawn in a Window. If this View is set as
-  // hidden then it and any child views will not be drawn and, if any of those
-  // views currently have focus, then focus will also be cleared. Painting is
-  // scheduled as needed. If this View is a Window then calling this function is
-  // equivalent to calling the Window show() and hide() functions.
+  /// Sets whether this View is visible. Windows are hidden by default and other
+  /// views are visible by default. This View and any parent views must be set
+  /// as visible for this View to be drawn in a Window. If this View is set as
+  /// hidden then it and any child views will not be drawn and, if any of those
+  /// views currently have focus, then focus will also be cleared. Painting is
+  /// scheduled as needed. If this View is a Window then calling this function
+  /// is equivalent to calling the Window show() and hide() functions.
   ///
   void(CEF_CALLBACK* set_visible)(struct _cef_view_t* self, int visible);
 
   ///
-  // Returns whether this View is visible. A view may be visible but still not
-  // drawn in a Window if any parent views are hidden. If this View is a Window
-  // then a return value of true (1) indicates that this Window is currently
-  // visible to the user on-screen. If this View is not a Window then call
-  // is_drawn() to determine whether this View and all parent views are visible
-  // and will be drawn.
+  /// Returns whether this View is visible. A view may be visible but still not
+  /// drawn in a Window if any parent views are hidden. If this View is a Window
+  /// then a return value of true (1) indicates that this Window is currently
+  /// visible to the user on-screen. If this View is not a Window then call
+  /// is_drawn() to determine whether this View and all parent views are visible
+  /// and will be drawn.
   ///
   int(CEF_CALLBACK* is_visible)(struct _cef_view_t* self);
 
   ///
-  // Returns whether this View is visible and drawn in a Window. A view is drawn
-  // if it and all parent views are visible. If this View is a Window then
-  // calling this function is equivalent to calling is_visible(). Otherwise, to
-  // determine if the containing Window is visible to the user on-screen call
-  // is_visible() on the Window.
+  /// Returns whether this View is visible and drawn in a Window. A view is
+  /// drawn if it and all parent views are visible. If this View is a Window
+  /// then calling this function is equivalent to calling is_visible().
+  /// Otherwise, to determine if the containing Window is visible to the user
+  /// on-screen call is_visible() on the Window.
   ///
   int(CEF_CALLBACK* is_drawn)(struct _cef_view_t* self);
 
   ///
-  // Set whether this View is enabled. A disabled View does not receive keyboard
-  // or mouse inputs. If |enabled| differs from the current value the View will
-  // be repainted. Also, clears focus if the focused View is disabled.
+  /// Set whether this View is enabled. A disabled View does not receive
+  /// keyboard or mouse inputs. If |enabled| differs from the current value the
+  /// View will be repainted. Also, clears focus if the focused View is
+  /// disabled.
   ///
   void(CEF_CALLBACK* set_enabled)(struct _cef_view_t* self, int enabled);
 
   ///
-  // Returns whether this View is enabled.
+  /// Returns whether this View is enabled.
   ///
   int(CEF_CALLBACK* is_enabled)(struct _cef_view_t* self);
 
   ///
-  // Sets whether this View is capable of taking focus. It will clear focus if
-  // the focused View is set to be non-focusable. This is false (0) by default
-  // so that a View used as a container does not get the focus.
+  /// Sets whether this View is capable of taking focus. It will clear focus if
+  /// the focused View is set to be non-focusable. This is false (0) by default
+  /// so that a View used as a container does not get the focus.
   ///
   void(CEF_CALLBACK* set_focusable)(struct _cef_view_t* self, int focusable);
 
   ///
-  // Returns true (1) if this View is focusable, enabled and drawn.
+  /// Returns true (1) if this View is focusable, enabled and drawn.
   ///
   int(CEF_CALLBACK* is_focusable)(struct _cef_view_t* self);
 
   ///
-  // Return whether this View is focusable when the user requires full keyboard
-  // access, even though it may not be normally focusable.
+  /// Return whether this View is focusable when the user requires full keyboard
+  /// access, even though it may not be normally focusable.
   ///
   int(CEF_CALLBACK* is_accessibility_focusable)(struct _cef_view_t* self);
 
   ///
-  // Request keyboard focus. If this View is focusable it will become the
-  // focused View.
+  /// Request keyboard focus. If this View is focusable it will become the
+  /// focused View.
   ///
   void(CEF_CALLBACK* request_focus)(struct _cef_view_t* self);
 
   ///
-  // Sets the background color for this View.
+  /// Sets the background color for this View.
   ///
   void(CEF_CALLBACK* set_background_color)(struct _cef_view_t* self,
                                            cef_color_t color);
 
   ///
-  // Returns the background color for this View.
+  /// Returns the background color for this View.
   ///
   cef_color_t(CEF_CALLBACK* get_background_color)(struct _cef_view_t* self);
 
   ///
-  // Convert |point| from this View's coordinate system to that of the screen.
-  // This View must belong to a Window when calling this function. Returns true
-  // (1) if the conversion is successful or false (0) otherwise. Use
-  // cef_display_t::convert_point_to_pixels() after calling this function if
-  // further conversion to display-specific pixel coordinates is desired.
+  /// Convert |point| from this View's coordinate system to DIP screen
+  /// coordinates. This View must belong to a Window when calling this function.
+  /// Returns true (1) if the conversion is successful or false (0) otherwise.
+  /// Use cef_display_t::convert_point_to_pixels() after calling this function
+  /// if further conversion to display-specific pixel coordinates is desired.
   ///
   int(CEF_CALLBACK* convert_point_to_screen)(struct _cef_view_t* self,
                                              cef_point_t* point);
 
   ///
-  // Convert |point| to this View's coordinate system from that of the screen.
-  // This View must belong to a Window when calling this function. Returns true
-  // (1) if the conversion is successful or false (0) otherwise. Use
-  // cef_display_t::convert_point_from_pixels() before calling this function if
-  // conversion from display-specific pixel coordinates is necessary.
+  /// Convert |point| to this View's coordinate system from DIP screen
+  /// coordinates. This View must belong to a Window when calling this function.
+  /// Returns true (1) if the conversion is successful or false (0) otherwise.
+  /// Use cef_display_t::convert_point_from_pixels() before calling this
+  /// function if conversion from display-specific pixel coordinates is
+  /// necessary.
   ///
   int(CEF_CALLBACK* convert_point_from_screen)(struct _cef_view_t* self,
                                                cef_point_t* point);
 
   ///
-  // Convert |point| from this View's coordinate system to that of the Window.
-  // This View must belong to a Window when calling this function. Returns true
-  // (1) if the conversion is successful or false (0) otherwise.
+  /// Convert |point| from this View's coordinate system to that of the Window.
+  /// This View must belong to a Window when calling this function. Returns true
+  /// (1) if the conversion is successful or false (0) otherwise.
   ///
   int(CEF_CALLBACK* convert_point_to_window)(struct _cef_view_t* self,
                                              cef_point_t* point);
 
   ///
-  // Convert |point| to this View's coordinate system from that of the Window.
-  // This View must belong to a Window when calling this function. Returns true
-  // (1) if the conversion is successful or false (0) otherwise.
+  /// Convert |point| to this View's coordinate system from that of the Window.
+  /// This View must belong to a Window when calling this function. Returns true
+  /// (1) if the conversion is successful or false (0) otherwise.
   ///
   int(CEF_CALLBACK* convert_point_from_window)(struct _cef_view_t* self,
                                                cef_point_t* point);
 
   ///
-  // Convert |point| from this View's coordinate system to that of |view|.
-  // |view| needs to be in the same Window but not necessarily the same view
-  // hierarchy. Returns true (1) if the conversion is successful or false (0)
-  // otherwise.
+  /// Convert |point| from this View's coordinate system to that of |view|.
+  /// |view| needs to be in the same Window but not necessarily the same view
+  /// hierarchy. Returns true (1) if the conversion is successful or false (0)
+  /// otherwise.
   ///
   int(CEF_CALLBACK* convert_point_to_view)(struct _cef_view_t* self,
                                            struct _cef_view_t* view,
                                            cef_point_t* point);
 
   ///
-  // Convert |point| to this View's coordinate system from that |view|. |view|
-  // needs to be in the same Window but not necessarily the same view hierarchy.
-  // Returns true (1) if the conversion is successful or false (0) otherwise.
+  /// Convert |point| to this View's coordinate system from that |view|. |view|
+  /// needs to be in the same Window but not necessarily the same view
+  /// hierarchy. Returns true (1) if the conversion is successful or false (0)
+  /// otherwise.
   ///
   int(CEF_CALLBACK* convert_point_from_view)(struct _cef_view_t* self,
                                              struct _cef_view_t* view,
diff --git a/src/include/capi/views/cef_view_delegate_capi.h b/src/include/capi/views/cef_view_delegate_capi.h
index 585f166..4f4b8f0 100644
--- a/src/include/capi/views/cef_view_delegate_capi.h
+++ b/src/include/capi/views/cef_view_delegate_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=52cd273ebe5d458482a830c8ca777907c6c21cc2$
+// $hash=70646cb55b5bf98ccfa2a93b2cf57bd5ba367268$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_VIEW_DELEGATE_CAPI_H_
@@ -49,52 +49,53 @@
 struct _cef_view_t;
 
 ///
-// Implement this structure to handle view events. The functions of this
-// structure will be called on the browser process UI thread unless otherwise
-// indicated.
+/// Implement this structure to handle view events. All size and position values
+/// are in density independent pixels (DIP) unless otherwise indicated. The
+/// functions of this structure will be called on the browser process UI thread
+/// unless otherwise indicated.
 ///
 typedef struct _cef_view_delegate_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_base_ref_counted_t base;
 
   ///
-  // Return the preferred size for |view|. The Layout will use this information
-  // to determine the display size.
+  /// Return the preferred size for |view|. The Layout will use this information
+  /// to determine the display size.
   ///
   cef_size_t(CEF_CALLBACK* get_preferred_size)(
       struct _cef_view_delegate_t* self,
       struct _cef_view_t* view);
 
   ///
-  // Return the minimum size for |view|.
+  /// Return the minimum size for |view|.
   ///
   cef_size_t(CEF_CALLBACK* get_minimum_size)(struct _cef_view_delegate_t* self,
                                              struct _cef_view_t* view);
 
   ///
-  // Return the maximum size for |view|.
+  /// Return the maximum size for |view|.
   ///
   cef_size_t(CEF_CALLBACK* get_maximum_size)(struct _cef_view_delegate_t* self,
                                              struct _cef_view_t* view);
 
   ///
-  // Return the height necessary to display |view| with the provided |width|. If
-  // not specified the result of get_preferred_size().height will be used by
-  // default. Override if |view|'s preferred height depends upon the width (for
-  // example, with Labels).
+  /// Return the height necessary to display |view| with the provided |width|.
+  /// If not specified the result of get_preferred_size().height will be used by
+  /// default. Override if |view|'s preferred height depends upon the width (for
+  /// example, with Labels).
   ///
   int(CEF_CALLBACK* get_height_for_width)(struct _cef_view_delegate_t* self,
                                           struct _cef_view_t* view,
                                           int width);
 
   ///
-  // Called when the parent of |view| has changed. If |view| is being added to
-  // |parent| then |added| will be true (1). If |view| is being removed from
-  // |parent| then |added| will be false (0). If |view| is being reparented the
-  // remove notification will be sent before the add notification. Do not modify
-  // the view hierarchy in this callback.
+  /// Called when the parent of |view| has changed. If |view| is being added to
+  /// |parent| then |added| will be true (1). If |view| is being removed from
+  /// |parent| then |added| will be false (0). If |view| is being reparented the
+  /// remove notification will be sent before the add notification. Do not
+  /// modify the view hierarchy in this callback.
   ///
   void(CEF_CALLBACK* on_parent_view_changed)(struct _cef_view_delegate_t* self,
                                              struct _cef_view_t* view,
@@ -102,12 +103,12 @@
                                              struct _cef_view_t* parent);
 
   ///
-  // Called when a child of |view| has changed. If |child| is being added to
-  // |view| then |added| will be true (1). If |child| is being removed from
-  // |view| then |added| will be false (0). If |child| is being reparented the
-  // remove notification will be sent to the old parent before the add
-  // notification is sent to the new parent. Do not modify the view hierarchy in
-  // this callback.
+  /// Called when a child of |view| has changed. If |child| is being added to
+  /// |view| then |added| will be true (1). If |child| is being removed from
+  /// |view| then |added| will be false (0). If |child| is being reparented the
+  /// remove notification will be sent to the old parent before the add
+  /// notification is sent to the new parent. Do not modify the view hierarchy
+  /// in this callback.
   ///
   void(CEF_CALLBACK* on_child_view_changed)(struct _cef_view_delegate_t* self,
                                             struct _cef_view_t* view,
@@ -115,13 +116,27 @@
                                             struct _cef_view_t* child);
 
   ///
-  // Called when |view| gains focus.
+  /// Called when |view| is added or removed from the cef_window_t.
+  ///
+  void(CEF_CALLBACK* on_window_changed)(struct _cef_view_delegate_t* self,
+                                        struct _cef_view_t* view,
+                                        int added);
+
+  ///
+  /// Called when the layout of |view| has changed.
+  ///
+  void(CEF_CALLBACK* on_layout_changed)(struct _cef_view_delegate_t* self,
+                                        struct _cef_view_t* view,
+                                        const cef_rect_t* new_bounds);
+
+  ///
+  /// Called when |view| gains focus.
   ///
   void(CEF_CALLBACK* on_focus)(struct _cef_view_delegate_t* self,
                                struct _cef_view_t* view);
 
   ///
-  // Called when |view| loses focus.
+  /// Called when |view| loses focus.
   ///
   void(CEF_CALLBACK* on_blur)(struct _cef_view_delegate_t* self,
                               struct _cef_view_t* view);
diff --git a/src/include/capi/views/cef_window_capi.h b/src/include/capi/views/cef_window_capi.h
index a62fda5..72aba00 100644
--- a/src/include/capi/views/cef_window_capi.h
+++ b/src/include/capi/views/cef_window_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=adedd44a4276c3900bce9abc7dc434411407143c$
+// $hash=a48904fcd0f6be07e27839922d8feb07271ed2b5$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_WINDOW_CAPI_H_
@@ -43,6 +43,7 @@
 #include "include/capi/cef_image_capi.h"
 #include "include/capi/cef_menu_model_capi.h"
 #include "include/capi/views/cef_display_capi.h"
+#include "include/capi/views/cef_overlay_controller_capi.h"
 #include "include/capi/views/cef_panel_capi.h"
 #include "include/capi/views/cef_window_delegate_capi.h"
 
@@ -50,157 +51,210 @@
 extern "C" {
 #endif
 
+struct _cef_browser_view_t;
+
 ///
-// A Window is a top-level Window/widget in the Views hierarchy. By default it
-// will have a non-client area with title bar, icon and buttons that supports
-// moving and resizing. All size and position values are in density independent
-// pixels (DIP) unless otherwise indicated. Methods must be called on the
-// browser process UI thread unless otherwise indicated.
+/// A Window is a top-level Window/widget in the Views hierarchy. By default it
+/// will have a non-client area with title bar, icon and buttons that supports
+/// moving and resizing. All size and position values are in density independent
+/// pixels (DIP) unless otherwise indicated. Methods must be called on the
+/// browser process UI thread unless otherwise indicated.
 ///
 typedef struct _cef_window_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_panel_t base;
 
   ///
-  // Show the Window.
+  /// Show the Window.
   ///
   void(CEF_CALLBACK* show)(struct _cef_window_t* self);
 
   ///
-  // Hide the Window.
+  /// Show the Window as a browser modal dialog relative to |browser_view|. A
+  /// parent Window must be returned via
+  /// cef_window_delegate_t::get_parent_window() and |browser_view| must belong
+  /// to that parent Window. While this Window is visible, |browser_view| will
+  /// be disabled while other controls in the parent Window remain enabled.
+  /// Navigating or destroying the |browser_view| will close this Window
+  /// automatically. Alternately, use show() and return true (1) from
+  /// cef_window_delegate_t::is_window_modal_dialog() for a window modal dialog
+  /// where all controls in the parent Window are disabled.
+  ///
+  void(CEF_CALLBACK* show_as_browser_modal_dialog)(
+      struct _cef_window_t* self,
+      struct _cef_browser_view_t* browser_view);
+
+  ///
+  /// Hide the Window.
   ///
   void(CEF_CALLBACK* hide)(struct _cef_window_t* self);
 
   ///
-  // Sizes the Window to |size| and centers it in the current display.
+  /// Sizes the Window to |size| and centers it in the current display.
   ///
   void(CEF_CALLBACK* center_window)(struct _cef_window_t* self,
                                     const cef_size_t* size);
 
   ///
-  // Close the Window.
+  /// Close the Window.
   ///
   void(CEF_CALLBACK* close)(struct _cef_window_t* self);
 
   ///
-  // Returns true (1) if the Window has been closed.
+  /// Returns true (1) if the Window has been closed.
   ///
   int(CEF_CALLBACK* is_closed)(struct _cef_window_t* self);
 
   ///
-  // Activate the Window, assuming it already exists and is visible.
+  /// Activate the Window, assuming it already exists and is visible.
   ///
   void(CEF_CALLBACK* activate)(struct _cef_window_t* self);
 
   ///
-  // Deactivate the Window, making the next Window in the Z order the active
-  // Window.
+  /// Deactivate the Window, making the next Window in the Z order the active
+  /// Window.
   ///
   void(CEF_CALLBACK* deactivate)(struct _cef_window_t* self);
 
   ///
-  // Returns whether the Window is the currently active Window.
+  /// Returns whether the Window is the currently active Window.
   ///
   int(CEF_CALLBACK* is_active)(struct _cef_window_t* self);
 
   ///
-  // Bring this Window to the top of other Windows in the Windowing system.
+  /// Bring this Window to the top of other Windows in the Windowing system.
   ///
   void(CEF_CALLBACK* bring_to_top)(struct _cef_window_t* self);
 
   ///
-  // Set the Window to be on top of other Windows in the Windowing system.
+  /// Set the Window to be on top of other Windows in the Windowing system.
   ///
   void(CEF_CALLBACK* set_always_on_top)(struct _cef_window_t* self, int on_top);
 
   ///
-  // Returns whether the Window has been set to be on top of other Windows in
-  // the Windowing system.
+  /// Returns whether the Window has been set to be on top of other Windows in
+  /// the Windowing system.
   ///
   int(CEF_CALLBACK* is_always_on_top)(struct _cef_window_t* self);
 
   ///
-  // Maximize the Window.
+  /// Maximize the Window.
   ///
   void(CEF_CALLBACK* maximize)(struct _cef_window_t* self);
 
   ///
-  // Minimize the Window.
+  /// Minimize the Window.
   ///
   void(CEF_CALLBACK* minimize)(struct _cef_window_t* self);
 
   ///
-  // Restore the Window.
+  /// Restore the Window.
   ///
   void(CEF_CALLBACK* restore)(struct _cef_window_t* self);
 
   ///
-  // Set fullscreen Window state.
+  /// Set fullscreen Window state. The
+  /// cef_window_delegate_t::OnWindowFullscreenTransition function will be
+  /// called during the fullscreen transition for notification purposes.
   ///
   void(CEF_CALLBACK* set_fullscreen)(struct _cef_window_t* self,
                                      int fullscreen);
 
   ///
-  // Returns true (1) if the Window is maximized.
+  /// Returns true (1) if the Window is maximized.
   ///
   int(CEF_CALLBACK* is_maximized)(struct _cef_window_t* self);
 
   ///
-  // Returns true (1) if the Window is minimized.
+  /// Returns true (1) if the Window is minimized.
   ///
   int(CEF_CALLBACK* is_minimized)(struct _cef_window_t* self);
 
   ///
-  // Returns true (1) if the Window is fullscreen.
+  /// Returns true (1) if the Window is fullscreen.
   ///
   int(CEF_CALLBACK* is_fullscreen)(struct _cef_window_t* self);
 
   ///
-  // Set the Window title.
+  /// Set the Window title.
   ///
   void(CEF_CALLBACK* set_title)(struct _cef_window_t* self,
                                 const cef_string_t* title);
 
   ///
-  // Get the Window title.
+  /// Get the Window title.
   ///
   // The resulting string must be freed by calling cef_string_userfree_free().
   cef_string_userfree_t(CEF_CALLBACK* get_title)(struct _cef_window_t* self);
 
   ///
-  // Set the Window icon. This should be a 16x16 icon suitable for use in the
-  // Windows's title bar.
+  /// Set the Window icon. This should be a 16x16 icon suitable for use in the
+  /// Windows's title bar.
   ///
   void(CEF_CALLBACK* set_window_icon)(struct _cef_window_t* self,
                                       struct _cef_image_t* image);
 
   ///
-  // Get the Window icon.
+  /// Get the Window icon.
   ///
   struct _cef_image_t*(CEF_CALLBACK* get_window_icon)(
       struct _cef_window_t* self);
 
   ///
-  // Set the Window App icon. This should be a larger icon for use in the host
-  // environment app switching UI. On Windows, this is the ICON_BIG used in Alt-
-  // Tab list and Windows taskbar. The Window icon will be used by default if no
-  // Window App icon is specified.
+  /// Set the Window App icon. This should be a larger icon for use in the host
+  /// environment app switching UI. On Windows, this is the ICON_BIG used in
+  /// Alt-Tab list and Windows taskbar. The Window icon will be used by default
+  /// if no Window App icon is specified.
   ///
   void(CEF_CALLBACK* set_window_app_icon)(struct _cef_window_t* self,
                                           struct _cef_image_t* image);
 
   ///
-  // Get the Window App icon.
+  /// Get the Window App icon.
   ///
   struct _cef_image_t*(CEF_CALLBACK* get_window_app_icon)(
       struct _cef_window_t* self);
 
   ///
-  // Show a menu with contents |menu_model|. |screen_point| specifies the menu
-  // position in screen coordinates. |anchor_position| specifies how the menu
-  // will be anchored relative to |screen_point|.
+  /// Add a View that will be overlayed on the Window contents with absolute
+  /// positioning and high z-order. Positioning is controlled by |docking_mode|
+  /// as described below. The returned cef_overlay_controller_t object is used
+  /// to control the overlay. Overlays are hidden by default.
+  ///
+  /// With CEF_DOCKING_MODE_CUSTOM:
+  ///   1. The overlay is initially hidden, sized to |view|'s preferred size,
+  ///      and positioned in the top-left corner.
+  ///   2. Optionally change the overlay position and/or size by calling
+  ///      CefOverlayController methods.
+  ///   3. Call CefOverlayController::SetVisible(true) to show the overlay.
+  ///   4. The overlay will be automatically re-sized if |view|'s layout
+  ///      changes. Optionally change the overlay position and/or size when
+  ///      OnLayoutChanged is called on the Window's delegate to indicate a
+  ///      change in Window bounds.
+  ///
+  /// With other docking modes:
+  ///   1. The overlay is initially hidden, sized to |view|'s preferred size,
+  ///      and positioned based on |docking_mode|.
+  ///   2. Call CefOverlayController::SetVisible(true) to show the overlay.
+  ///   3. The overlay will be automatically re-sized if |view|'s layout changes
+  ///      and re-positioned as appropriate when the Window resizes.
+  ///
+  /// Overlays created by this function will receive a higher z-order then any
+  /// child Views added previously. It is therefore recommended to call this
+  /// function last after all other child Views have been added so that the
+  /// overlay displays as the top-most child of the Window.
+  ///
+  struct _cef_overlay_controller_t*(CEF_CALLBACK* add_overlay_view)(
+      struct _cef_window_t* self,
+      struct _cef_view_t* view,
+      cef_docking_mode_t docking_mode);
+
+  ///
+  /// Show a menu with contents |menu_model|. |screen_point| specifies the menu
+  /// position in screen coordinates. |anchor_position| specifies how the menu
+  /// will be anchored relative to |screen_point|.
   ///
   void(CEF_CALLBACK* show_menu)(struct _cef_window_t* self,
                                 struct _cef_menu_model_t* menu_model,
@@ -208,28 +262,28 @@
                                 cef_menu_anchor_position_t anchor_position);
 
   ///
-  // Cancel the menu that is currently showing, if any.
+  /// Cancel the menu that is currently showing, if any.
   ///
   void(CEF_CALLBACK* cancel_menu)(struct _cef_window_t* self);
 
   ///
-  // Returns the Display that most closely intersects the bounds of this Window.
-  // May return NULL if this Window is not currently displayed.
+  /// Returns the Display that most closely intersects the bounds of this
+  /// Window. May return NULL if this Window is not currently displayed.
   ///
   struct _cef_display_t*(CEF_CALLBACK* get_display)(struct _cef_window_t* self);
 
   ///
-  // Returns the bounds (size and position) of this Window's client area.
-  // Position is in screen coordinates.
+  /// Returns the bounds (size and position) of this Window's client area.
+  /// Position is in screen coordinates.
   ///
   cef_rect_t(CEF_CALLBACK* get_client_area_bounds_in_screen)(
       struct _cef_window_t* self);
 
   ///
-  // Set the regions where mouse events will be intercepted by this Window to
-  // support drag operations. Call this function with an NULL vector to clear
-  // the draggable regions. The draggable region bounds should be in window
-  // coordinates.
+  /// Set the regions where mouse events will be intercepted by this Window to
+  /// support drag operations. Call this function with an NULL vector to clear
+  /// the draggable regions. The draggable region bounds should be in window
+  /// coordinates.
   ///
   void(CEF_CALLBACK* set_draggable_regions)(
       struct _cef_window_t* self,
@@ -237,39 +291,39 @@
       cef_draggable_region_t const* regions);
 
   ///
-  // Retrieve the platform window handle for this Window.
+  /// Retrieve the platform window handle for this Window.
   ///
   cef_window_handle_t(CEF_CALLBACK* get_window_handle)(
       struct _cef_window_t* self);
 
   ///
-  // Simulate a key press. |key_code| is the VKEY_* value from Chromium's
-  // ui/events/keycodes/keyboard_codes.h header (VK_* values on Windows).
-  // |event_flags| is some combination of EVENTFLAG_SHIFT_DOWN,
-  // EVENTFLAG_CONTROL_DOWN and/or EVENTFLAG_ALT_DOWN. This function is exposed
-  // primarily for testing purposes.
+  /// Simulate a key press. |key_code| is the VKEY_* value from Chromium's
+  /// ui/events/keycodes/keyboard_codes.h header (VK_* values on Windows).
+  /// |event_flags| is some combination of EVENTFLAG_SHIFT_DOWN,
+  /// EVENTFLAG_CONTROL_DOWN and/or EVENTFLAG_ALT_DOWN. This function is exposed
+  /// primarily for testing purposes.
   ///
   void(CEF_CALLBACK* send_key_press)(struct _cef_window_t* self,
                                      int key_code,
-                                     uint32 event_flags);
+                                     uint32_t event_flags);
 
   ///
-  // Simulate a mouse move. The mouse cursor will be moved to the specified
-  // (screen_x, screen_y) position. This function is exposed primarily for
-  // testing purposes.
+  /// Simulate a mouse move. The mouse cursor will be moved to the specified
+  /// (screen_x, screen_y) position. This function is exposed primarily for
+  /// testing purposes.
   ///
   void(CEF_CALLBACK* send_mouse_move)(struct _cef_window_t* self,
                                       int screen_x,
                                       int screen_y);
 
   ///
-  // Simulate mouse down and/or mouse up events. |button| is the mouse button
-  // type. If |mouse_down| is true (1) a mouse down event will be sent. If
-  // |mouse_up| is true (1) a mouse up event will be sent. If both are true (1)
-  // a mouse down event will be sent followed by a mouse up event (equivalent to
-  // clicking the mouse button). The events will be sent using the current
-  // cursor position so make sure to call send_mouse_move() first to position
-  // the mouse. This function is exposed primarily for testing purposes.
+  /// Simulate mouse down and/or mouse up events. |button| is the mouse button
+  /// type. If |mouse_down| is true (1) a mouse down event will be sent. If
+  /// |mouse_up| is true (1) a mouse up event will be sent. If both are true (1)
+  /// a mouse down event will be sent followed by a mouse up event (equivalent
+  /// to clicking the mouse button). The events will be sent using the current
+  /// cursor position so make sure to call send_mouse_move() first to position
+  /// the mouse. This function is exposed primarily for testing purposes.
   ///
   void(CEF_CALLBACK* send_mouse_events)(struct _cef_window_t* self,
                                         cef_mouse_button_type_t button,
@@ -277,32 +331,41 @@
                                         int mouse_up);
 
   ///
-  // Set the keyboard accelerator for the specified |command_id|. |key_code| can
-  // be any virtual key or character value. cef_window_delegate_t::OnAccelerator
-  // will be called if the keyboard combination is triggered while this window
-  // has focus.
+  /// Set the keyboard accelerator for the specified |command_id|. |key_code|
+  /// can be any virtual key or character value. Required modifier keys are
+  /// specified by |shift_pressed|, |ctrl_pressed| and/or |alt_pressed|.
+  /// cef_window_delegate_t::OnAccelerator will be called if the keyboard
+  /// combination is triggered while this window has focus.
+  ///
+  /// The |high_priority| value will be considered if a child cef_browser_view_t
+  /// has focus when the keyboard combination is triggered. If |high_priority|
+  /// is true (1) then the key event will not be forwarded to the web content
+  /// (`keydown` event handler) or cef_keyboard_handler_t first. If
+  /// |high_priority| is false (0) then the behavior will depend on the
+  /// cef_browser_view_t::SetPreferAccelerators configuration.
   ///
   void(CEF_CALLBACK* set_accelerator)(struct _cef_window_t* self,
                                       int command_id,
                                       int key_code,
                                       int shift_pressed,
                                       int ctrl_pressed,
-                                      int alt_pressed);
+                                      int alt_pressed,
+                                      int high_priority);
 
   ///
-  // Remove the keyboard accelerator for the specified |command_id|.
+  /// Remove the keyboard accelerator for the specified |command_id|.
   ///
   void(CEF_CALLBACK* remove_accelerator)(struct _cef_window_t* self,
                                          int command_id);
 
   ///
-  // Remove all keyboard accelerators.
+  /// Remove all keyboard accelerators.
   ///
   void(CEF_CALLBACK* remove_all_accelerators)(struct _cef_window_t* self);
 } cef_window_t;
 
 ///
-// Create a new Window.
+/// Create a new Window.
 ///
 CEF_EXPORT cef_window_t* cef_window_create_top_level(
     struct _cef_window_delegate_t* delegate);
diff --git a/src/include/capi/views/cef_window_delegate_capi.h b/src/include/capi/views/cef_window_delegate_capi.h
index c26f096..2abeb45 100644
--- a/src/include/capi/views/cef_window_delegate_capi.h
+++ b/src/include/capi/views/cef_window_delegate_capi.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -33,7 +33,7 @@
 // by hand. See the translator.README.txt file in the tools directory for
 // more information.
 //
-// $hash=a0cec778fbaf0b1f5c9b3ef75dc7bbeeba777a44$
+// $hash=456f00f7afbac910cf36feecd38399a2fb16960d$
 //
 
 #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_WINDOW_DELEGATE_CAPI_H_
@@ -49,37 +49,74 @@
 struct _cef_window_t;
 
 ///
-// Implement this structure to handle window events. The functions of this
-// structure will be called on the browser process UI thread unless otherwise
-// indicated.
+/// Implement this structure to handle window events. The functions of this
+/// structure will be called on the browser process UI thread unless otherwise
+/// indicated.
 ///
 typedef struct _cef_window_delegate_t {
   ///
-  // Base structure.
+  /// Base structure.
   ///
   cef_panel_delegate_t base;
 
   ///
-  // Called when |window| is created.
+  /// Called when |window| is created.
   ///
   void(CEF_CALLBACK* on_window_created)(struct _cef_window_delegate_t* self,
                                         struct _cef_window_t* window);
 
   ///
-  // Called when |window| is destroyed. Release all references to |window| and
-  // do not attempt to execute any functions on |window| after this callback
-  // returns.
+  /// Called when |window| is closing.
+  ///
+  void(CEF_CALLBACK* on_window_closing)(struct _cef_window_delegate_t* self,
+                                        struct _cef_window_t* window);
+
+  ///
+  /// Called when |window| is destroyed. Release all references to |window| and
+  /// do not attempt to execute any functions on |window| after this callback
+  /// returns.
   ///
   void(CEF_CALLBACK* on_window_destroyed)(struct _cef_window_delegate_t* self,
                                           struct _cef_window_t* window);
 
   ///
-  // Return the parent for |window| or NULL if the |window| does not have a
-  // parent. Windows with parents will not get a taskbar button. Set |is_menu|
-  // to true (1) if |window| will be displayed as a menu, in which case it will
-  // not be clipped to the parent window bounds. Set |can_activate_menu| to
-  // false (0) if |is_menu| is true (1) and |window| should not be activated
-  // (given keyboard focus) when displayed.
+  /// Called when |window| is activated or deactivated.
+  ///
+  void(CEF_CALLBACK* on_window_activation_changed)(
+      struct _cef_window_delegate_t* self,
+      struct _cef_window_t* window,
+      int active);
+
+  ///
+  /// Called when |window| bounds have changed. |new_bounds| will be in DIP
+  /// screen coordinates.
+  ///
+  void(CEF_CALLBACK* on_window_bounds_changed)(
+      struct _cef_window_delegate_t* self,
+      struct _cef_window_t* window,
+      const cef_rect_t* new_bounds);
+
+  ///
+  /// Called when |window| is transitioning to or from fullscreen mode. On MacOS
+  /// the transition occurs asynchronously with |is_competed| set to false (0)
+  /// when the transition starts and true (1) after the transition completes. On
+  /// other platforms the transition occurs synchronously with |is_completed|
+  /// set to true (1) after the transition completes. With the Alloy runtime you
+  /// must also implement cef_display_handler_t::OnFullscreenModeChange to
+  /// handle fullscreen transitions initiated by browser content.
+  ///
+  void(CEF_CALLBACK* on_window_fullscreen_transition)(
+      struct _cef_window_delegate_t* self,
+      struct _cef_window_t* window,
+      int is_completed);
+
+  ///
+  /// Return the parent for |window| or NULL if the |window| does not have a
+  /// parent. Windows with parents will not get a taskbar button. Set |is_menu|
+  /// to true (1) if |window| will be displayed as a menu, in which case it will
+  /// not be clipped to the parent window bounds. Set |can_activate_menu| to
+  /// false (0) if |is_menu| is true (1) and |window| should not be activated
+  /// (given keyboard focus) when displayed.
   ///
   struct _cef_window_t*(CEF_CALLBACK* get_parent_window)(
       struct _cef_window_delegate_t* self,
@@ -88,55 +125,105 @@
       int* can_activate_menu);
 
   ///
-  // Return true (1) if |window| should be created without a frame or title bar.
-  // The window will be resizable if can_resize() returns true (1). Use
-  // cef_window_t::set_draggable_regions() to specify draggable regions.
+  /// Return true (1) if |window| should be created as a window modal dialog.
+  /// Only called when a Window is returned via get_parent_window() with
+  /// |is_menu| set to false (0). All controls in the parent Window will be
+  /// disabled while |window| is visible. This functionality is not supported by
+  /// all Linux window managers. Alternately, use
+  /// cef_window_t::show_as_browser_modal_dialog() for a browser modal dialog
+  /// that works on all platforms.
+  ///
+  int(CEF_CALLBACK* is_window_modal_dialog)(struct _cef_window_delegate_t* self,
+                                            struct _cef_window_t* window);
+
+  ///
+  /// Return the initial bounds for |window| in density independent pixel (DIP)
+  /// coordinates. If this function returns an NULL CefRect then
+  /// get_preferred_size() will be called to retrieve the size, and the window
+  /// will be placed on the screen with origin (0,0). This function can be used
+  /// in combination with cef_view_t::get_bounds_in_screen() to restore the
+  /// previous window bounds.
+  ///
+  cef_rect_t(CEF_CALLBACK* get_initial_bounds)(
+      struct _cef_window_delegate_t* self,
+      struct _cef_window_t* window);
+
+  ///
+  /// Return the initial show state for |window|.
+  ///
+  cef_show_state_t(CEF_CALLBACK* get_initial_show_state)(
+      struct _cef_window_delegate_t* self,
+      struct _cef_window_t* window);
+
+  ///
+  /// Return true (1) if |window| should be created without a frame or title
+  /// bar. The window will be resizable if can_resize() returns true (1). Use
+  /// cef_window_t::set_draggable_regions() to specify draggable regions.
   ///
   int(CEF_CALLBACK* is_frameless)(struct _cef_window_delegate_t* self,
                                   struct _cef_window_t* window);
 
   ///
-  // Return true (1) if |window| can be resized.
+  /// Return true (1) if |window| should be created with standard window buttons
+  /// like close, minimize and zoom. This function is only supported on macOS.
+  ///
+  int(CEF_CALLBACK* with_standard_window_buttons)(
+      struct _cef_window_delegate_t* self,
+      struct _cef_window_t* window);
+
+  ///
+  /// Return whether the titlebar height should be overridden, and sets the
+  /// height of the titlebar in |titlebar_height|. On macOS, it can also be used
+  /// to adjust the vertical position of the traffic light buttons in frameless
+  /// windows. The buttons will be positioned halfway down the titlebar at a
+  /// height of |titlebar_height| / 2.
+  ///
+  int(CEF_CALLBACK* get_titlebar_height)(struct _cef_window_delegate_t* self,
+                                         struct _cef_window_t* window,
+                                         float* titlebar_height);
+
+  ///
+  /// Return true (1) if |window| can be resized.
   ///
   int(CEF_CALLBACK* can_resize)(struct _cef_window_delegate_t* self,
                                 struct _cef_window_t* window);
 
   ///
-  // Return true (1) if |window| can be maximized.
+  /// Return true (1) if |window| can be maximized.
   ///
   int(CEF_CALLBACK* can_maximize)(struct _cef_window_delegate_t* self,
                                   struct _cef_window_t* window);
 
   ///
-  // Return true (1) if |window| can be minimized.
+  /// Return true (1) if |window| can be minimized.
   ///
   int(CEF_CALLBACK* can_minimize)(struct _cef_window_delegate_t* self,
                                   struct _cef_window_t* window);
 
   ///
-  // Return true (1) if |window| can be closed. This will be called for user-
-  // initiated window close actions and when cef_window_t::close() is called.
+  /// Return true (1) if |window| can be closed. This will be called for user-
+  /// initiated window close actions and when cef_window_t::close() is called.
   ///
   int(CEF_CALLBACK* can_close)(struct _cef_window_delegate_t* self,
                                struct _cef_window_t* window);
 
   ///
-  // Called when a keyboard accelerator registered with
-  // cef_window_t::SetAccelerator is triggered. Return true (1) if the
-  // accelerator was handled or false (0) otherwise.
+  /// Called when a keyboard accelerator registered with
+  /// cef_window_t::SetAccelerator is triggered. Return true (1) if the
+  /// accelerator was handled or false (0) otherwise.
   ///
   int(CEF_CALLBACK* on_accelerator)(struct _cef_window_delegate_t* self,
                                     struct _cef_window_t* window,
                                     int command_id);
 
   ///
-  // Called after all other controls in the window have had a chance to handle
-  // the event. |event| contains information about the keyboard event. Return
-  // true (1) if the keyboard event was handled or false (0) otherwise.
+  /// Called after all other controls in the window have had a chance to handle
+  /// the event. |event| contains information about the keyboard event. Return
+  /// true (1) if the keyboard event was handled or false (0) otherwise.
   ///
   int(CEF_CALLBACK* on_key_event)(struct _cef_window_delegate_t* self,
                                   struct _cef_window_t* window,
-                                  const struct _cef_key_event_t* event);
+                                  const cef_key_event_t* event);
 } cef_window_delegate_t;
 
 #ifdef __cplusplus
diff --git a/src/include/cef_accessibility_handler.h b/src/include/cef_accessibility_handler.h
index c34e0c5..2b1719a 100644
--- a/src/include/cef_accessibility_handler.h
+++ b/src/include/cef_accessibility_handler.h
@@ -41,23 +41,23 @@
 #include "include/cef_values.h"
 
 ///
-// Implement this interface to receive accessibility notification when
-// accessibility events have been registered. The methods of this class will
-// be called on the UI thread.
+/// Implement this interface to receive accessibility notification when
+/// accessibility events have been registered. The methods of this class will
+/// be called on the UI thread.
 ///
 /*--cef(source=client)--*/
 class CefAccessibilityHandler : public virtual CefBaseRefCounted {
  public:
   ///
-  // Called after renderer process sends accessibility tree changes to the
-  // browser process.
+  /// Called after renderer process sends accessibility tree changes to the
+  /// browser process.
   ///
   /*--cef()--*/
   virtual void OnAccessibilityTreeChange(CefRefPtr<CefValue> value) = 0;
 
   ///
-  // Called after renderer process sends accessibility location changes to the
-  // browser process.
+  /// Called after renderer process sends accessibility location changes to the
+  /// browser process.
   ///
   /*--cef()--*/
   virtual void OnAccessibilityLocationChange(CefRefPtr<CefValue> value) = 0;
diff --git a/src/include/cef_api_hash.h b/src/include/cef_api_hash.h
index 9595afd..a774bdc 100644
--- a/src/include/cef_api_hash.h
+++ b/src/include/cef_api_hash.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -42,13 +42,13 @@
 // way that may cause binary incompatibility with other builds. The universal
 // hash value will change if any platform is affected whereas the platform hash
 // values will change only if that particular platform is affected.
-#define CEF_API_HASH_UNIVERSAL "385d8af3c6da76f123f3aa292d3a3308ef456297"
+#define CEF_API_HASH_UNIVERSAL "ce9401699c6753553cba867b1f5c329f759d2c67"
 #if defined(OS_WIN)
-#define CEF_API_HASH_PLATFORM "4bb528b0bb076ed5177d6581cfca12dd7b2fee04"
-#elif defined(OS_MACOSX)
-#define CEF_API_HASH_PLATFORM "f6580fc0858f3580b7d25e1d094dd0a336132522"
+#define CEF_API_HASH_PLATFORM "e094f42b7a60d2c8c9bcb3db51907a3b42f51d04"
+#elif defined(OS_MAC)
+#define CEF_API_HASH_PLATFORM "6ce44bd7182aa7e9544f5ca33c310f2a096ab638"
 #elif defined(OS_LINUX)
-#define CEF_API_HASH_PLATFORM "83f3053840abba3b83e43ade58230f10b48591dd"
+#define CEF_API_HASH_PLATFORM "8e9886cd490aefc89283d65f5f7d104a51e2d289"
 #endif
 
 #ifdef __cplusplus
diff --git a/src/include/cef_app.h b/src/include/cef_app.h
index 56fb715..3591297 100644
--- a/src/include/cef_app.h
+++ b/src/include/cef_app.h
@@ -48,16 +48,16 @@
 class CefApp;
 
 ///
-// This function should be called from the application entry point function to
-// execute a secondary process. It can be used to run secondary processes from
-// the browser client executable (default behavior) or from a separate
-// executable specified by the CefSettings.browser_subprocess_path value. If
-// called for the browser process (identified by no "type" command-line value)
-// it will return immediately with a value of -1. If called for a recognized
-// secondary process it will block until the process should exit and then return
-// the process exit code. The |application| parameter may be empty. The
-// |windows_sandbox_info| parameter is only used on Windows and may be NULL (see
-// cef_sandbox_win.h for details).
+/// This function should be called from the application entry point function to
+/// execute a secondary process. It can be used to run secondary processes from
+/// the browser client executable (default behavior) or from a separate
+/// executable specified by the cef_settings_t.browser_subprocess_path value. If
+/// called for the browser process (identified by no "type" command-line value)
+/// it will return immediately with a value of -1. If called for a recognized
+/// secondary process it will block until the process should exit and then
+/// return the process exit code. The |application| parameter may be empty. The
+/// |windows_sandbox_info| parameter is only used on Windows and may be NULL
+/// (see cef_sandbox_win.h for details).
 ///
 /*--cef(api_hash_check,optional_param=application,
         optional_param=windows_sandbox_info)--*/
@@ -66,11 +66,11 @@
                       void* windows_sandbox_info);
 
 ///
-// This function should be called on the main application thread to initialize
-// the CEF browser process. The |application| parameter may be empty. A return
-// value of true indicates that it succeeded and false indicates that it failed.
-// The |windows_sandbox_info| parameter is only used on Windows and may be NULL
-// (see cef_sandbox_win.h for details).
+/// This function should be called on the main application thread to initialize
+/// the CEF browser process. The |application| parameter may be empty. A return
+/// value of true indicates that it succeeded and false indicates that it
+/// failed. The |windows_sandbox_info| parameter is only used on Windows and may
+/// be NULL (see cef_sandbox_win.h for details).
 ///
 /*--cef(api_hash_check,optional_param=application,
         optional_param=windows_sandbox_info)--*/
@@ -80,80 +80,67 @@
                    void* windows_sandbox_info);
 
 ///
-// This function should be called on the main application thread to shut down
-// the CEF browser process before the application exits.
+/// This function should be called on the main application thread to shut down
+/// the CEF browser process before the application exits.
 ///
 /*--cef()--*/
 void CefShutdown();
 
 ///
-// Perform a single iteration of CEF message loop processing. This function is
-// provided for cases where the CEF message loop must be integrated into an
-// existing application message loop. Use of this function is not recommended
-// for most users; use either the CefRunMessageLoop() function or
-// CefSettings.multi_threaded_message_loop if possible. When using this function
-// care must be taken to balance performance against excessive CPU usage. It is
-// recommended to enable the CefSettings.external_message_pump option when using
-// this function so that CefBrowserProcessHandler::OnScheduleMessagePumpWork()
-// callbacks can facilitate the scheduling process. This function should only be
-// called on the main application thread and only if CefInitialize() is called
-// with a CefSettings.multi_threaded_message_loop value of false. This function
-// will not block.
+/// Perform a single iteration of CEF message loop processing. This function is
+/// provided for cases where the CEF message loop must be integrated into an
+/// existing application message loop. Use of this function is not recommended
+/// for most users; use either the CefRunMessageLoop() function or
+/// cef_settings_t.multi_threaded_message_loop if possible. When using this
+/// function care must be taken to balance performance against excessive CPU
+/// usage. It is recommended to enable the cef_settings_t.external_message_pump
+/// option when using this function so that
+/// CefBrowserProcessHandler::OnScheduleMessagePumpWork() callbacks can
+/// facilitate the scheduling process. This function should only be called on
+/// the main application thread and only if CefInitialize() is called with a
+/// cef_settings_t.multi_threaded_message_loop value of false. This function
+/// will not block.
 ///
 /*--cef()--*/
 void CefDoMessageLoopWork();
 
 ///
-// Run the CEF message loop. Use this function instead of an application-
-// provided message loop to get the best balance between performance and CPU
-// usage. This function should only be called on the main application thread and
-// only if CefInitialize() is called with a
-// CefSettings.multi_threaded_message_loop value of false. This function will
-// block until a quit message is received by the system.
+/// Run the CEF message loop. Use this function instead of an application-
+/// provided message loop to get the best balance between performance and CPU
+/// usage. This function should only be called on the main application thread
+/// and only if CefInitialize() is called with a
+/// cef_settings_t.multi_threaded_message_loop value of false. This function
+/// will block until a quit message is received by the system.
 ///
 /*--cef()--*/
 void CefRunMessageLoop();
 
 ///
-// Quit the CEF message loop that was started by calling CefRunMessageLoop().
-// This function should only be called on the main application thread and only
-// if CefRunMessageLoop() was used.
+/// Quit the CEF message loop that was started by calling CefRunMessageLoop().
+/// This function should only be called on the main application thread and only
+/// if CefRunMessageLoop() was used.
 ///
 /*--cef()--*/
 void CefQuitMessageLoop();
 
 ///
-// Set to true before calling Windows APIs like TrackPopupMenu that enter a
-// modal message loop. Set to false after exiting the modal message loop.
-///
-/*--cef()--*/
-void CefSetOSModalLoop(bool osModalLoop);
-
-///
-// Call during process startup to enable High-DPI support on Windows 7 or newer.
-// Older versions of Windows should be left DPI-unaware because they do not
-// support DirectWrite and GDI fonts are kerned very badly.
-///
-/*--cef(capi_name=cef_enable_highdpi_support)--*/
-void CefEnableHighDPISupport();
-
-///
-// Implement this interface to provide handler implementations. Methods will be
-// called by the process and/or thread indicated.
+/// Implement this interface to provide handler implementations. Methods will be
+/// called by the process and/or thread indicated.
 ///
 /*--cef(source=client,no_debugct_check)--*/
 class CefApp : public virtual CefBaseRefCounted {
  public:
   ///
-  // Provides an opportunity to view and/or modify command-line arguments before
-  // processing by CEF and Chromium. The |process_type| value will be empty for
-  // the browser process. Do not keep a reference to the CefCommandLine object
-  // passed to this method. The CefSettings.command_line_args_disabled value
-  // can be used to start with an empty command-line object. Any values
-  // specified in CefSettings that equate to command-line arguments will be set
-  // before this method is called. Be cautious when using this method to modify
-  // command-line arguments for non-browser processes as this may result in
-  // undefined behavior including crashes.
+  /// Provides an opportunity to view and/or modify command-line arguments
+  /// before processing by CEF and Chromium. The |process_type| value will be
+  /// empty for the browser process. Do not keep a reference to the
+  /// CefCommandLine object passed to this method. The
+  /// cef_settings_t.command_line_args_disabled value can be used to start with
+  /// an empty command-line object. Any values specified in CefSettings that
+  /// equate to command-line arguments will be set before this method is called.
+  /// Be cautious when using this method to modify command-line arguments for
+  /// non-browser processes as this may result in undefined behavior including
+  /// crashes.
   ///
   /*--cef(optional_param=process_type)--*/
   virtual void OnBeforeCommandLineProcessing(
@@ -161,20 +148,20 @@
       CefRefPtr<CefCommandLine> command_line) {}
 
   ///
-  // Provides an opportunity to register custom schemes. Do not keep a reference
-  // to the |registrar| object. This method is called on the main thread for
-  // each process and the registered schemes should be the same across all
-  // processes.
+  /// Provides an opportunity to register custom schemes. Do not keep a
+  /// reference to the |registrar| object. This method is called on the main
+  /// thread for each process and the registered schemes should be the same
+  /// across all processes.
   ///
   /*--cef()--*/
   virtual void OnRegisterCustomSchemes(
       CefRawPtr<CefSchemeRegistrar> registrar) {}
 
   ///
-  // Return the handler for resource bundle events. If
-  // CefSettings.pack_loading_disabled is true a handler must be returned. If no
-  // handler is returned resources will be loaded from pack files. This method
-  // is called by the browser and render processes on multiple threads.
+  /// Return the handler for resource bundle events. If
+  /// cef_settings_t.pack_loading_disabled is true a handler must be returned.
+  /// If no handler is returned resources will be loaded from pack files. This
+  /// method is called by the browser and render processes on multiple threads.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefResourceBundleHandler> GetResourceBundleHandler() {
@@ -182,8 +169,8 @@
   }
 
   ///
-  // Return the handler for functionality specific to the browser process. This
-  // method is called on multiple threads in the browser process.
+  /// Return the handler for functionality specific to the browser process. This
+  /// method is called on multiple threads in the browser process.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() {
@@ -191,8 +178,8 @@
   }
 
   ///
-  // Return the handler for functionality specific to the render process. This
-  // method is called on the render process main thread.
+  /// Return the handler for functionality specific to the render process. This
+  /// method is called on the render process main thread.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() {
diff --git a/src/include/cef_application_mac.h b/src/include/cef_application_mac.h
index e2858c4..b607acc 100644
--- a/src/include/cef_application_mac.h
+++ b/src/include/cef_application_mac.h
@@ -35,7 +35,7 @@
 #include "include/cef_base.h"
 #endif  // __cplusplus
 
-#if defined(OS_MACOSX) && defined(__OBJC__)
+#if defined(OS_MAC) && defined(__OBJC__)
 
 #ifdef USING_CHROMIUM_INCLUDES
 
@@ -45,9 +45,6 @@
 // Use the existing CrAppProtocol definition.
 #import "base/message_loop/message_pump_mac.h"
 
-// Use the existing UnderlayableSurface definition.
-#import "ui/base/cocoa/underlay_opengl_hosting_window.h"
-
 // Use the existing empty protocol definitions.
 #import "base/mac/cocoa_protocols.h"
 
@@ -66,22 +63,15 @@
 @end
 
 // Copy of definition from base/mac/scoped_sending_event.h.
-@protocol CrAppControlProtocol<CrAppProtocol>
+@protocol CrAppControlProtocol <CrAppProtocol>
 - (void)setHandlingSendEvent:(BOOL)handlingSendEvent;
 @end
 
-// Copy of definition from ui/base/cocoa/underlay_opengl_hosting_window.h.
-// Common base class for windows that host a OpenGL surface that renders under
-// the window. Contains methods relating to hole punching so that the OpenGL
-// surface is visible through the window.
-@interface UnderlayOpenGLHostingWindow : NSWindow
-@end
-
 #endif  // USING_CHROMIUM_INCLUDES
 
 // All CEF client applications must subclass NSApplication and implement this
 // protocol.
-@protocol CefAppProtocol<CrAppControlProtocol>
+@protocol CefAppProtocol <CrAppControlProtocol>
 @end
 
 #ifdef __cplusplus
@@ -105,6 +95,6 @@
 
 #endif  // __cplusplus
 
-#endif  // defined(OS_MACOSX) && defined(__OBJC__)
+#endif  // defined(OS_MAC) && defined(__OBJC__)
 
 #endif  // CEF_INCLUDE_CEF_APPLICATION_MAC_H_
diff --git a/src/include/cef_audio_handler.h b/src/include/cef_audio_handler.h
index f581e6f..5211cba 100644
--- a/src/include/cef_audio_handler.h
+++ b/src/include/cef_audio_handler.h
@@ -42,7 +42,7 @@
 #include "include/cef_browser.h"
 
 ///
-// Implement this interface to handle audio events.
+/// Implement this interface to handle audio events.
 ///
 /*--cef(source=client)--*/
 class CefAudioHandler : public virtual CefBaseRefCounted {
@@ -50,10 +50,10 @@
   typedef cef_channel_layout_t ChannelLayout;
 
   ///
-  // Called on the UI thread to allow configuration of audio stream parameters.
-  // Return true to proceed with audio stream capture, or false to cancel it.
-  // All members of |params| can optionally be configured here, but they are
-  // also pre-filled with some sensible defaults.
+  /// Called on the UI thread to allow configuration of audio stream parameters.
+  /// Return true to proceed with audio stream capture, or false to cancel it.
+  /// All members of |params| can optionally be configured here, but they are
+  /// also pre-filled with some sensible defaults.
   ///
   /*--cef()--*/
   virtual bool GetAudioParameters(CefRefPtr<CefBrowser> browser,
@@ -62,11 +62,11 @@
   }
 
   ///
-  // Called on a browser audio capture thread when the browser starts
-  // streaming audio. OnAudioSteamStopped will always be called after
-  // OnAudioStreamStarted; both methods may be called multiple times
-  // for the same browser. |params| contains the audio parameters like
-  // sample rate and channel layout. |channels| is the number of channels.
+  /// Called on a browser audio capture thread when the browser starts
+  /// streaming audio. OnAudioStreamStopped will always be called after
+  /// OnAudioStreamStarted; both methods may be called multiple times
+  /// for the same browser. |params| contains the audio parameters like
+  /// sample rate and channel layout. |channels| is the number of channels.
   ///
   /*--cef()--*/
   virtual void OnAudioStreamStarted(CefRefPtr<CefBrowser> browser,
@@ -74,34 +74,34 @@
                                     int channels) = 0;
 
   ///
-  // Called on the audio stream thread when a PCM packet is received for the
-  // stream. |data| is an array representing the raw PCM data as a floating
-  // point type, i.e. 4-byte value(s). |frames| is the number of frames in the
-  // PCM packet. |pts| is the presentation timestamp (in milliseconds since the
-  // Unix Epoch) and represents the time at which the decompressed packet should
-  // be presented to the user. Based on |frames| and the |channel_layout| value
-  // passed to OnAudioStreamStarted you can calculate the size of the |data|
-  // array in bytes.
+  /// Called on the audio stream thread when a PCM packet is received for the
+  /// stream. |data| is an array representing the raw PCM data as a floating
+  /// point type, i.e. 4-byte value(s). |frames| is the number of frames in the
+  /// PCM packet. |pts| is the presentation timestamp (in milliseconds since the
+  /// Unix Epoch) and represents the time at which the decompressed packet
+  /// should be presented to the user. Based on |frames| and the
+  /// |channel_layout| value passed to OnAudioStreamStarted you can calculate
+  /// the size of the |data| array in bytes.
   ///
   /*--cef()--*/
   virtual void OnAudioStreamPacket(CefRefPtr<CefBrowser> browser,
                                    const float** data,
                                    int frames,
-                                   int64 pts) = 0;
+                                   int64_t pts) = 0;
 
   ///
-  // Called on the UI thread when the stream has stopped. OnAudioSteamStopped
-  // will always be called after OnAudioStreamStarted; both methods may be
-  // called multiple times for the same stream.
+  /// Called on the UI thread when the stream has stopped. OnAudioSteamStopped
+  /// will always be called after OnAudioStreamStarted; both methods may be
+  /// called multiple times for the same stream.
   ///
   /*--cef()--*/
   virtual void OnAudioStreamStopped(CefRefPtr<CefBrowser> browser) = 0;
 
   ///
-  // Called on the UI or audio stream thread when an error occurred. During the
-  // stream creation phase this callback will be called on the UI thread while
-  // in the capturing phase it will be called on the audio stream thread. The
-  // stream will be stopped immediately.
+  /// Called on the UI or audio stream thread when an error occurred. During the
+  /// stream creation phase this callback will be called on the UI thread while
+  /// in the capturing phase it will be called on the audio stream thread. The
+  /// stream will be stopped immediately.
   ///
   /*--cef()--*/
   virtual void OnAudioStreamError(CefRefPtr<CefBrowser> browser,
diff --git a/src/include/cef_auth_callback.h b/src/include/cef_auth_callback.h
index fc8a10a..3372a72 100644
--- a/src/include/cef_auth_callback.h
+++ b/src/include/cef_auth_callback.h
@@ -41,21 +41,21 @@
 #include "include/cef_base.h"
 
 ///
-// Callback interface used for asynchronous continuation of authentication
-// requests.
+/// Callback interface used for asynchronous continuation of authentication
+/// requests.
 ///
 /*--cef(source=library)--*/
 class CefAuthCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Continue the authentication request.
+  /// Continue the authentication request.
   ///
   /*--cef(capi_name=cont,optional_param=username,optional_param=password)--*/
   virtual void Continue(const CefString& username,
                         const CefString& password) = 0;
 
   ///
-  // Cancel the authentication request.
+  /// Cancel the authentication request.
   ///
   /*--cef()--*/
   virtual void Cancel() = 0;
diff --git a/src/include/cef_base.h b/src/include/cef_base.h
index 0db0f3a..bd8f11e 100644
--- a/src/include/cef_base.h
+++ b/src/include/cef_base.h
@@ -37,39 +37,40 @@
 
 // Bring in common C++ type definitions used by CEF consumers.
 #include "include/internal/cef_ptr.h"
+#include "include/internal/cef_time_wrappers.h"
 #include "include/internal/cef_types_wrappers.h"
 #if defined(OS_WIN)
 #include "include/internal/cef_win.h"
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
 #include "include/internal/cef_mac.h"
 #elif defined(OS_LINUX)
 #include "include/internal/cef_linux.h"
 #endif
 
 ///
-// All ref-counted framework classes must extend this class.
+/// All ref-counted framework classes must extend this class.
 ///
 class CefBaseRefCounted {
  public:
   ///
-  // Called to increment the reference count for the object. Should be called
-  // for every new copy of a pointer to a given object.
+  /// Called to increment the reference count for the object. Should be called
+  /// for every new copy of a pointer to a given object.
   ///
   virtual void AddRef() const = 0;
 
   ///
-  // Called to decrement the reference count for the object. Returns true if
-  // the reference count is 0, in which case the object should self-delete.
+  /// Called to decrement the reference count for the object. Returns true if
+  /// the reference count is 0, in which case the object should self-delete.
   ///
   virtual bool Release() const = 0;
 
   ///
-  // Returns true if the reference count is 1.
+  /// Returns true if the reference count is 1.
   ///
   virtual bool HasOneRef() const = 0;
 
   ///
-  // Returns true if the reference count is at least 1.
+  /// Returns true if the reference count is at least 1.
   ///
   virtual bool HasAtLeastOneRef() const = 0;
 
@@ -78,7 +79,7 @@
 };
 
 ///
-// All scoped framework classes must extend this class.
+/// All scoped framework classes must extend this class.
 ///
 class CefBaseScoped {
  public:
@@ -86,109 +87,63 @@
 };
 
 ///
-// Class that implements atomic reference counting.
+/// Class that implements atomic reference counting.
 ///
 class CefRefCount {
  public:
-  CefRefCount() : ref_count_(0) {}
+  CefRefCount() = default;
+
+  CefRefCount(const CefRefCount&) = delete;
+  CefRefCount& operator=(const CefRefCount&) = delete;
 
   ///
-  // Increment the reference count.
+  /// Increment the reference count.
   ///
-  void AddRef() const { base::AtomicRefCountInc(&ref_count_); }
+  void AddRef() const { ref_count_.Increment(); }
 
   ///
-  // Decrement the reference count. Returns true if the reference count is 0.
+  /// Decrement the reference count. Returns true if the reference count is 0.
   ///
-  bool Release() const { return !base::AtomicRefCountDec(&ref_count_); }
+  bool Release() const { return !ref_count_.Decrement(); }
 
   ///
-  // Returns true if the reference count is 1.
+  /// Returns true if the reference count is 1.
   ///
-  bool HasOneRef() const { return base::AtomicRefCountIsOne(&ref_count_); }
+  bool HasOneRef() const { return ref_count_.IsOne(); }
 
   ///
-  // Returns true if the reference count is at least 1.
+  /// Returns true if the reference count is at least 1.
   ///
-  bool HasAtLeastOneRef() const {
-    return !base::AtomicRefCountIsZero(&ref_count_);
-  }
+  bool HasAtLeastOneRef() const { return !ref_count_.IsZero(); }
 
  private:
-  mutable base::AtomicRefCount ref_count_;
-  DISALLOW_COPY_AND_ASSIGN(CefRefCount);
+  mutable base::AtomicRefCount ref_count_{0};
 };
 
 ///
-// Macro that provides a reference counting implementation for classes extending
-// CefBase.
+/// Macro that provides a reference counting implementation for classes
+/// extending CefBase.
 ///
-#define IMPLEMENT_REFCOUNTING(ClassName)                             \
- public:                                                             \
-  void AddRef() const OVERRIDE { ref_count_.AddRef(); }              \
-  bool Release() const OVERRIDE {                                    \
-    if (ref_count_.Release()) {                                      \
-      delete static_cast<const ClassName*>(this);                    \
-      return true;                                                   \
-    }                                                                \
-    return false;                                                    \
-  }                                                                  \
-  bool HasOneRef() const OVERRIDE { return ref_count_.HasOneRef(); } \
-  bool HasAtLeastOneRef() const OVERRIDE {                           \
-    return ref_count_.HasAtLeastOneRef();                            \
-  }                                                                  \
-                                                                     \
- private:                                                            \
+#define IMPLEMENT_REFCOUNTING(ClassName)          \
+ public:                                          \
+  void AddRef() const override {                  \
+    ref_count_.AddRef();                          \
+  }                                               \
+  bool Release() const override {                 \
+    if (ref_count_.Release()) {                   \
+      delete static_cast<const ClassName*>(this); \
+      return true;                                \
+    }                                             \
+    return false;                                 \
+  }                                               \
+  bool HasOneRef() const override {               \
+    return ref_count_.HasOneRef();                \
+  }                                               \
+  bool HasAtLeastOneRef() const override {        \
+    return ref_count_.HasAtLeastOneRef();         \
+  }                                               \
+                                                  \
+ private:                                         \
   CefRefCount ref_count_
 
-///
-// Macro that provides a locking implementation. Use the Lock() and Unlock()
-// methods to protect a section of code from simultaneous access by multiple
-// threads. The AutoLock class is a helper that will hold the lock while in
-// scope.
-//
-// THIS MACRO IS DEPRECATED. Use an explicit base::Lock member variable and
-// base::AutoLock instead. For example:
-//
-// #include "include/base/cef_lock.h"
-//
-// // Class declaration.
-// class MyClass : public CefBaseRefCounted {
-//  public:
-//   MyClass() : value_(0) {}
-//   // Method that may be called on multiple threads.
-//   void IncrementValue();
-//  private:
-//   // Value that may be accessed on multiple theads.
-//   int value_;
-//   // Lock used to protect access to |value_|.
-//   base::Lock lock_;
-//   IMPLEMENT_REFCOUNTING(MyClass);
-// };
-//
-// // Class implementation.
-// void MyClass::IncrementValue() {
-//   // Acquire the lock for the scope of this method.
-//   base::AutoLock lock_scope(lock_);
-//   // |value_| can now be modified safely.
-//   value_++;
-// }
-///
-#define IMPLEMENT_LOCKING(ClassName)                                    \
- public:                                                                \
-  class AutoLock {                                                      \
-   public:                                                              \
-    explicit AutoLock(ClassName* base) : base_(base) { base_->Lock(); } \
-    ~AutoLock() { base_->Unlock(); }                                    \
-                                                                        \
-   private:                                                             \
-    ClassName* base_;                                                   \
-    DISALLOW_COPY_AND_ASSIGN(AutoLock);                                 \
-  };                                                                    \
-  void Lock() { lock_.Acquire(); }                                      \
-  void Unlock() { lock_.Release(); }                                    \
-                                                                        \
- private:                                                               \
-  base::Lock lock_;
-
 #endif  // CEF_INCLUDE_CEF_BASE_H_
diff --git a/src/include/cef_browser.h b/src/include/cef_browser.h
index 172d0a1..7ba4985 100644
--- a/src/include/cef_browser.h
+++ b/src/include/cef_browser.h
@@ -52,171 +52,181 @@
 class CefClient;
 
 ///
-// Class used to represent a browser window. When used in the browser process
-// the methods of this class may be called on any thread unless otherwise
-// indicated in the comments. When used in the render process the methods of
-// this class may only be called on the main thread.
+/// Class used to represent a browser. When used in the browser process the
+/// methods of this class may be called on any thread unless otherwise indicated
+/// in the comments. When used in the render process the methods of this class
+/// may only be called on the main thread.
 ///
 /*--cef(source=library)--*/
 class CefBrowser : public virtual CefBaseRefCounted {
  public:
   ///
-  // Returns the browser host object. This method can only be called in the
-  // browser process.
+  /// True if this object is currently valid. This will return false after
+  /// CefLifeSpanHandler::OnBeforeClose is called.
+  ///
+  /*--cef()--*/
+  virtual bool IsValid() = 0;
+
+  ///
+  /// Returns the browser host object. This method can only be called in the
+  /// browser process.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBrowserHost> GetHost() = 0;
 
   ///
-  // Returns true if the browser can navigate backwards.
+  /// Returns true if the browser can navigate backwards.
   ///
   /*--cef()--*/
   virtual bool CanGoBack() = 0;
 
   ///
-  // Navigate backwards.
+  /// Navigate backwards.
   ///
   /*--cef()--*/
   virtual void GoBack() = 0;
 
   ///
-  // Returns true if the browser can navigate forwards.
+  /// Returns true if the browser can navigate forwards.
   ///
   /*--cef()--*/
   virtual bool CanGoForward() = 0;
 
   ///
-  // Navigate forwards.
+  /// Navigate forwards.
   ///
   /*--cef()--*/
   virtual void GoForward() = 0;
 
   ///
-  // Returns true if the browser is currently loading.
+  /// Returns true if the browser is currently loading.
   ///
   /*--cef()--*/
   virtual bool IsLoading() = 0;
 
   ///
-  // Reload the current page.
+  /// Reload the current page.
   ///
   /*--cef()--*/
   virtual void Reload() = 0;
 
   ///
-  // Reload the current page ignoring any cached data.
+  /// Reload the current page ignoring any cached data.
   ///
   /*--cef()--*/
   virtual void ReloadIgnoreCache() = 0;
 
   ///
-  // Stop loading the page.
+  /// Stop loading the page.
   ///
   /*--cef()--*/
   virtual void StopLoad() = 0;
 
   ///
-  // Returns the globally unique identifier for this browser. This value is also
-  // used as the tabId for extension APIs.
+  /// Returns the globally unique identifier for this browser. This value is
+  /// also used as the tabId for extension APIs.
   ///
   /*--cef()--*/
   virtual int GetIdentifier() = 0;
 
   ///
-  // Returns true if this object is pointing to the same handle as |that|
-  // object.
+  /// Returns true if this object is pointing to the same handle as |that|
+  /// object.
   ///
   /*--cef()--*/
   virtual bool IsSame(CefRefPtr<CefBrowser> that) = 0;
 
   ///
-  // Returns true if the window is a popup window.
+  /// Returns true if the browser is a popup.
   ///
   /*--cef()--*/
   virtual bool IsPopup() = 0;
 
   ///
-  // Returns true if a document has been loaded in the browser.
+  /// Returns true if a document has been loaded in the browser.
   ///
   /*--cef()--*/
   virtual bool HasDocument() = 0;
 
   ///
-  // Returns the main (top-level) frame for the browser window.
+  /// Returns the main (top-level) frame for the browser. In the browser process
+  /// this will return a valid object until after
+  /// CefLifeSpanHandler::OnBeforeClose is called. In the renderer process this
+  /// will return NULL if the main frame is hosted in a different renderer
+  /// process (e.g. for cross-origin sub-frames). The main frame object will
+  /// change during cross-origin navigation or re-navigation after renderer
+  /// process termination (due to crashes, etc).
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefFrame> GetMainFrame() = 0;
 
   ///
-  // Returns the focused frame for the browser window.
+  /// Returns the focused frame for the browser.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefFrame> GetFocusedFrame() = 0;
 
   ///
-  // Returns the frame with the specified identifier, or NULL if not found.
+  /// Returns the frame with the specified identifier, or NULL if not found.
   ///
   /*--cef(capi_name=get_frame_byident)--*/
-  virtual CefRefPtr<CefFrame> GetFrame(int64 identifier) = 0;
+  virtual CefRefPtr<CefFrame> GetFrame(int64_t identifier) = 0;
 
   ///
-  // Returns the frame with the specified name, or NULL if not found.
+  /// Returns the frame with the specified name, or NULL if not found.
   ///
   /*--cef(optional_param=name)--*/
   virtual CefRefPtr<CefFrame> GetFrame(const CefString& name) = 0;
 
   ///
-  // Returns the number of frames that currently exist.
+  /// Returns the number of frames that currently exist.
   ///
   /*--cef()--*/
   virtual size_t GetFrameCount() = 0;
 
   ///
-  // Returns the identifiers of all existing frames.
+  /// Returns the identifiers of all existing frames.
   ///
   /*--cef(count_func=identifiers:GetFrameCount)--*/
-  virtual void GetFrameIdentifiers(std::vector<int64>& identifiers) = 0;
+  virtual void GetFrameIdentifiers(std::vector<int64_t>& identifiers) = 0;
 
   ///
-  // Returns the names of all existing frames.
+  /// Returns the names of all existing frames.
   ///
   /*--cef()--*/
   virtual void GetFrameNames(std::vector<CefString>& names) = 0;
 };
 
 ///
-// Callback interface for CefBrowserHost::RunFileDialog. The methods of this
-// class will be called on the browser process UI thread.
+/// Callback interface for CefBrowserHost::RunFileDialog. The methods of this
+/// class will be called on the browser process UI thread.
 ///
 /*--cef(source=client)--*/
 class CefRunFileDialogCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Called asynchronously after the file dialog is dismissed.
-  // |selected_accept_filter| is the 0-based index of the value selected from
-  // the accept filters array passed to CefBrowserHost::RunFileDialog.
-  // |file_paths| will be a single value or a list of values depending on the
-  // dialog mode. If the selection was cancelled |file_paths| will be empty.
+  /// Called asynchronously after the file dialog is dismissed.
+  /// |file_paths| will be a single value or a list of values depending on the
+  /// dialog mode. If the selection was cancelled |file_paths| will be empty.
   ///
-  /*--cef(index_param=selected_accept_filter,optional_param=file_paths)--*/
+  /*--cef(optional_param=file_paths)--*/
   virtual void OnFileDialogDismissed(
-      int selected_accept_filter,
       const std::vector<CefString>& file_paths) = 0;
 };
 
 ///
-// Callback interface for CefBrowserHost::GetNavigationEntries. The methods of
-// this class will be called on the browser process UI thread.
+/// Callback interface for CefBrowserHost::GetNavigationEntries. The methods of
+/// this class will be called on the browser process UI thread.
 ///
 /*--cef(source=client)--*/
 class CefNavigationEntryVisitor : public virtual CefBaseRefCounted {
  public:
   ///
-  // Method that will be executed. Do not keep a reference to |entry| outside of
-  // this callback. Return true to continue visiting entries or false to stop.
-  // |current| is true if this entry is the currently loaded navigation entry.
-  // |index| is the 0-based index of this entry and |total| is the total number
-  // of entries.
+  /// Method that will be executed. Do not keep a reference to |entry| outside
+  /// of this callback. Return true to continue visiting entries or false to
+  /// stop. |current| is true if this entry is the currently loaded navigation
+  /// entry. |index| is the 0-based index of this entry and |total| is the total
+  /// number of entries.
   ///
   /*--cef()--*/
   virtual bool Visit(CefRefPtr<CefNavigationEntry> entry,
@@ -226,33 +236,33 @@
 };
 
 ///
-// Callback interface for CefBrowserHost::PrintToPDF. The methods of this class
-// will be called on the browser process UI thread.
+/// Callback interface for CefBrowserHost::PrintToPDF. The methods of this class
+/// will be called on the browser process UI thread.
 ///
 /*--cef(source=client)--*/
 class CefPdfPrintCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Method that will be executed when the PDF printing has completed. |path|
-  // is the output path. |ok| will be true if the printing completed
-  // successfully or false otherwise.
+  /// Method that will be executed when the PDF printing has completed. |path|
+  /// is the output path. |ok| will be true if the printing completed
+  /// successfully or false otherwise.
   ///
   /*--cef()--*/
   virtual void OnPdfPrintFinished(const CefString& path, bool ok) = 0;
 };
 
 ///
-// Callback interface for CefBrowserHost::DownloadImage. The methods of this
-// class will be called on the browser process UI thread.
+/// Callback interface for CefBrowserHost::DownloadImage. The methods of this
+/// class will be called on the browser process UI thread.
 ///
 /*--cef(source=client)--*/
 class CefDownloadImageCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Method that will be executed when the image download has completed.
-  // |image_url| is the URL that was downloaded and |http_status_code| is the
-  // resulting HTTP status code. |image| is the resulting image, possibly at
-  // multiple scale factors, or empty if the download failed.
+  /// Method that will be executed when the image download has completed.
+  /// |image_url| is the URL that was downloaded and |http_status_code| is the
+  /// resulting HTTP status code. |image| is the resulting image, possibly at
+  /// multiple scale factors, or empty if the download failed.
   ///
   /*--cef(optional_param=image)--*/
   virtual void OnDownloadImageFinished(const CefString& image_url,
@@ -261,10 +271,10 @@
 };
 
 ///
-// Class used to represent the browser process aspects of a browser window. The
-// methods of this class can only be called in the browser process. They may be
-// called on any thread in that process unless otherwise indicated in the
-// comments.
+/// Class used to represent the browser process aspects of a browser. The
+/// methods of this class can only be called in the browser process. They may be
+/// called on any thread in that process unless otherwise indicated in the
+/// comments.
 ///
 /*--cef(source=library)--*/
 class CefBrowserHost : public virtual CefBaseRefCounted {
@@ -275,14 +285,14 @@
   typedef cef_paint_element_type_t PaintElementType;
 
   ///
-  // Create a new browser window using the window parameters specified by
-  // |windowInfo|. All values will be copied internally and the actual window
-  // will be created on the UI thread. If |request_context| is empty the
-  // global request context will be used. This method can be called on any
-  // browser process thread and will not block. The optional |extra_info|
-  // parameter provides an opportunity to specify extra information specific
-  // to the created browser that will be passed to
-  // CefRenderProcessHandler::OnBrowserCreated() in the render process.
+  /// Create a new browser using the window parameters specified by
+  /// |windowInfo|. All values will be copied internally and the actual window
+  /// (if any) will be created on the UI thread. If |request_context| is empty
+  /// the global request context will be used. This method can be called on any
+  /// browser process thread and will not block. The optional |extra_info|
+  /// parameter provides an opportunity to specify extra information specific to
+  /// the created browser that will be passed to
+  /// CefRenderProcessHandler::OnBrowserCreated() in the render process.
   ///
   /*--cef(optional_param=client,optional_param=url,
           optional_param=request_context,optional_param=extra_info)--*/
@@ -294,13 +304,13 @@
                             CefRefPtr<CefRequestContext> request_context);
 
   ///
-  // Create a new browser window using the window parameters specified by
-  // |windowInfo|. If |request_context| is empty the global request context
-  // will be used. This method can only be called on the browser process UI
-  // thread. The optional |extra_info| parameter provides an opportunity to
-  // specify extra information specific to the created browser that will be
-  // passed to CefRenderProcessHandler::OnBrowserCreated() in the render
-  // process.
+  /// Create a new browser using the window parameters specified by
+  /// |windowInfo|. If |request_context| is empty the global request context
+  /// will be used. This method can only be called on the browser process UI
+  /// thread. The optional |extra_info| parameter provides an opportunity to
+  /// specify extra information specific to the created browser that will be
+  /// passed to CefRenderProcessHandler::OnBrowserCreated() in the render
+  /// process.
   ///
   /*--cef(optional_param=client,optional_param=url,
           optional_param=request_context,optional_param=extra_info)--*/
@@ -313,153 +323,177 @@
       CefRefPtr<CefRequestContext> request_context);
 
   ///
-  // Returns the hosted browser object.
+  /// Returns the hosted browser object.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBrowser> GetBrowser() = 0;
 
   ///
-  // Request that the browser close. The JavaScript 'onbeforeunload' event will
-  // be fired. If |force_close| is false the event handler, if any, will be
-  // allowed to prompt the user and the user can optionally cancel the close.
-  // If |force_close| is true the prompt will not be displayed and the close
-  // will proceed. Results in a call to CefLifeSpanHandler::DoClose() if the
-  // event handler allows the close or if |force_close| is true. See
-  // CefLifeSpanHandler::DoClose() documentation for additional usage
-  // information.
+  /// Request that the browser close. The JavaScript 'onbeforeunload' event will
+  /// be fired. If |force_close| is false the event handler, if any, will be
+  /// allowed to prompt the user and the user can optionally cancel the close.
+  /// If |force_close| is true the prompt will not be displayed and the close
+  /// will proceed. Results in a call to CefLifeSpanHandler::DoClose() if the
+  /// event handler allows the close or if |force_close| is true. See
+  /// CefLifeSpanHandler::DoClose() documentation for additional usage
+  /// information.
   ///
   /*--cef()--*/
   virtual void CloseBrowser(bool force_close) = 0;
 
   ///
-  // Helper for closing a browser. Call this method from the top-level window
-  // close handler. Internally this calls CloseBrowser(false) if the close has
-  // not yet been initiated. This method returns false while the close is
-  // pending and true after the close has completed. See CloseBrowser() and
-  // CefLifeSpanHandler::DoClose() documentation for additional usage
-  // information. This method must be called on the browser process UI thread.
+  /// Helper for closing a browser. Call this method from the top-level window
+  /// close handler (if any). Internally this calls CloseBrowser(false) if the
+  /// close has not yet been initiated. This method returns false while the
+  /// close is pending and true after the close has completed. See
+  /// CloseBrowser() and CefLifeSpanHandler::DoClose() documentation for
+  /// additional usage information. This method must be called on the browser
+  /// process UI thread.
   ///
   /*--cef()--*/
   virtual bool TryCloseBrowser() = 0;
 
   ///
-  // Set whether the browser is focused.
+  /// Set whether the browser is focused.
   ///
   /*--cef()--*/
   virtual void SetFocus(bool focus) = 0;
 
   ///
-  // Retrieve the window handle for this browser. If this browser is wrapped in
-  // a CefBrowserView this method should be called on the browser process UI
-  // thread and it will return the handle for the top-level native window.
+  /// Retrieve the window handle (if any) for this browser. If this browser is
+  /// wrapped in a CefBrowserView this method should be called on the browser
+  /// process UI thread and it will return the handle for the top-level native
+  /// window.
   ///
   /*--cef()--*/
   virtual CefWindowHandle GetWindowHandle() = 0;
 
   ///
-  // Retrieve the window handle of the browser that opened this browser. Will
-  // return NULL for non-popup windows or if this browser is wrapped in a
-  // CefBrowserView. This method can be used in combination with custom handling
-  // of modal windows.
+  /// Retrieve the window handle (if any) of the browser that opened this
+  /// browser. Will return NULL for non-popup browsers or if this browser is
+  /// wrapped in a CefBrowserView. This method can be used in combination with
+  /// custom handling of modal windows.
   ///
   /*--cef()--*/
   virtual CefWindowHandle GetOpenerWindowHandle() = 0;
 
   ///
-  // Returns true if this browser is wrapped in a CefBrowserView.
+  /// Returns true if this browser is wrapped in a CefBrowserView.
   ///
   /*--cef()--*/
   virtual bool HasView() = 0;
 
   ///
-  // Returns the client for this browser.
+  /// Returns the client for this browser.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefClient> GetClient() = 0;
 
   ///
-  // Returns the request context for this browser.
+  /// Returns the request context for this browser.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefRequestContext> GetRequestContext() = 0;
 
   ///
-  // Get the current zoom level. The default zoom level is 0.0. This method can
-  // only be called on the UI thread.
+  /// Returns true if this browser can execute the specified zoom command. This
+  /// method can only be called on the UI thread.
+  ///
+  /*--cef()--*/
+  virtual bool CanZoom(cef_zoom_command_t command) = 0;
+
+  ///
+  /// Execute a zoom command in this browser. If called on the UI thread the
+  /// change will be applied immediately. Otherwise, the change will be applied
+  /// asynchronously on the UI thread.
+  ///
+  /*--cef()--*/
+  virtual void Zoom(cef_zoom_command_t command) = 0;
+
+  ///
+  /// Get the default zoom level. This value will be 0.0 by default but can be
+  /// configured with the Chrome runtime. This method can only be called on the
+  /// UI thread.
+  ///
+  /*--cef()--*/
+  virtual double GetDefaultZoomLevel() = 0;
+
+  ///
+  /// Get the current zoom level. This method can only be called on the UI
+  /// thread.
   ///
   /*--cef()--*/
   virtual double GetZoomLevel() = 0;
 
   ///
-  // Change the zoom level to the specified value. Specify 0.0 to reset the
-  // zoom level. If called on the UI thread the change will be applied
-  // immediately. Otherwise, the change will be applied asynchronously on the
-  // UI thread.
+  /// Change the zoom level to the specified value. Specify 0.0 to reset the
+  /// zoom level to the default. If called on the UI thread the change will be
+  /// applied immediately. Otherwise, the change will be applied asynchronously
+  /// on the UI thread.
   ///
   /*--cef()--*/
   virtual void SetZoomLevel(double zoomLevel) = 0;
 
   ///
-  // Call to run a file chooser dialog. Only a single file chooser dialog may be
-  // pending at any given time. |mode| represents the type of dialog to display.
-  // |title| to the title to be used for the dialog and may be empty to show the
-  // default title ("Open" or "Save" depending on the mode). |default_file_path|
-  // is the path with optional directory and/or file name component that will be
-  // initially selected in the dialog. |accept_filters| are used to restrict the
-  // selectable file types and may any combination of (a) valid lower-cased MIME
-  // types (e.g. "text/*" or "image/*"), (b) individual file extensions (e.g.
-  // ".txt" or ".png"), or (c) combined description and file extension delimited
-  // using "|" and ";" (e.g. "Image Types|.png;.gif;.jpg").
-  // |selected_accept_filter| is the 0-based index of the filter that will be
-  // selected by default. |callback| will be executed after the dialog is
-  // dismissed or immediately if another dialog is already pending. The dialog
-  // will be initiated asynchronously on the UI thread.
+  /// Call to run a file chooser dialog. Only a single file chooser dialog may
+  /// be pending at any given time. |mode| represents the type of dialog to
+  /// display. |title| to the title to be used for the dialog and may be empty
+  /// to show the default title ("Open" or "Save" depending on the mode).
+  /// |default_file_path| is the path with optional directory and/or file name
+  /// component that will be initially selected in the dialog. |accept_filters|
+  /// are used to restrict the selectable file types and may any combination of
+  /// (a) valid lower-cased MIME types (e.g. "text/*" or "image/*"), (b)
+  /// individual file extensions (e.g.
+  /// ".txt" or ".png"), or (c) combined description and file extension
+  /// delimited using "|" and ";" (e.g. "Image Types|.png;.gif;.jpg").
+  /// |callback| will be executed after the dialog is dismissed or immediately
+  /// if another dialog is already pending. The dialog will be initiated
+  /// asynchronously on the UI thread.
   ///
   /*--cef(optional_param=title,optional_param=default_file_path,
-          optional_param=accept_filters,index_param=selected_accept_filter)--*/
+          optional_param=accept_filters)--*/
   virtual void RunFileDialog(FileDialogMode mode,
                              const CefString& title,
                              const CefString& default_file_path,
                              const std::vector<CefString>& accept_filters,
-                             int selected_accept_filter,
                              CefRefPtr<CefRunFileDialogCallback> callback) = 0;
 
   ///
-  // Download the file at |url| using CefDownloadHandler.
+  /// Download the file at |url| using CefDownloadHandler.
   ///
   /*--cef()--*/
   virtual void StartDownload(const CefString& url) = 0;
 
   ///
-  // Download |image_url| and execute |callback| on completion with the images
-  // received from the renderer. If |is_favicon| is true then cookies are not
-  // sent and not accepted during download. Images with density independent
-  // pixel (DIP) sizes larger than |max_image_size| are filtered out from the
-  // image results. Versions of the image at different scale factors may be
-  // downloaded up to the maximum scale factor supported by the system. If there
-  // are no image results <= |max_image_size| then the smallest image is resized
-  // to |max_image_size| and is the only result. A |max_image_size| of 0 means
-  // unlimited. If |bypass_cache| is true then |image_url| is requested from the
-  // server even if it is present in the browser cache.
+  /// Download |image_url| and execute |callback| on completion with the images
+  /// received from the renderer. If |is_favicon| is true then cookies are not
+  /// sent and not accepted during download. Images with density independent
+  /// pixel (DIP) sizes larger than |max_image_size| are filtered out from the
+  /// image results. Versions of the image at different scale factors may be
+  /// downloaded up to the maximum scale factor supported by the system. If
+  /// there are no image results <= |max_image_size| then the smallest image is
+  /// resized to |max_image_size| and is the only result. A |max_image_size| of
+  /// 0 means unlimited. If |bypass_cache| is true then |image_url| is requested
+  /// from the server even if it is present in the browser cache.
   ///
   /*--cef()--*/
   virtual void DownloadImage(const CefString& image_url,
                              bool is_favicon,
-                             uint32 max_image_size,
+                             uint32_t max_image_size,
                              bool bypass_cache,
                              CefRefPtr<CefDownloadImageCallback> callback) = 0;
 
   ///
-  // Print the current browser contents.
+  /// Print the current browser contents.
   ///
   /*--cef()--*/
   virtual void Print() = 0;
 
   ///
-  // Print the current browser contents to the PDF file specified by |path| and
-  // execute |callback| on completion. The caller is responsible for deleting
-  // |path| when done. For PDF printing to work on Linux you must implement the
-  // CefPrintHandler::GetPdfPaperSize method.
+  /// Print the current browser contents to the PDF file specified by |path| and
+  /// execute |callback| on completion. The caller is responsible for deleting
+  /// |path| when done. For PDF printing to work on Linux you must implement the
+  /// CefPrintHandler::GetPdfPaperSize method.
   ///
   /*--cef(optional_param=callback)--*/
   virtual void PrintToPDF(const CefString& path,
@@ -467,37 +501,34 @@
                           CefRefPtr<CefPdfPrintCallback> callback) = 0;
 
   ///
-  // Search for |searchText|. |identifier| must be a unique ID and these IDs
-  // must strictly increase so that newer requests always have greater IDs than
-  // older requests. If |identifier| is zero or less than the previous ID value
-  // then it will be automatically assigned a new valid ID. |forward| indicates
-  // whether to search forward or backward within the page. |matchCase|
-  // indicates whether the search should be case-sensitive. |findNext| indicates
-  // whether this is the first request or a follow-up. The CefFindHandler
-  // instance, if any, returned via CefClient::GetFindHandler will be called to
-  // report find results.
+  /// Search for |searchText|. |forward| indicates whether to search forward or
+  /// backward within the page. |matchCase| indicates whether the search should
+  /// be case-sensitive. |findNext| indicates whether this is the first request
+  /// or a follow-up. The search will be restarted if |searchText| or
+  /// |matchCase| change. The search will be stopped if |searchText| is empty.
+  /// The CefFindHandler instance, if any, returned via
+  /// CefClient::GetFindHandler will be called to report find results.
   ///
   /*--cef()--*/
-  virtual void Find(int identifier,
-                    const CefString& searchText,
+  virtual void Find(const CefString& searchText,
                     bool forward,
                     bool matchCase,
                     bool findNext) = 0;
 
   ///
-  // Cancel all searches that are currently going on.
+  /// Cancel all searches that are currently going on.
   ///
   /*--cef()--*/
   virtual void StopFinding(bool clearSelection) = 0;
 
   ///
-  // Open developer tools (DevTools) in its own browser. The DevTools browser
-  // will remain associated with this browser. If the DevTools browser is
-  // already open then it will be focused, in which case the |windowInfo|,
-  // |client| and |settings| parameters will be ignored. If |inspect_element_at|
-  // is non-empty then the element at the specified (x,y) location will be
-  // inspected. The |windowInfo| parameter will be ignored if this browser is
-  // wrapped in a CefBrowserView.
+  /// Open developer tools (DevTools) in its own browser. The DevTools browser
+  /// will remain associated with this browser. If the DevTools browser is
+  /// already open then it will be focused, in which case the |windowInfo|,
+  /// |client| and |settings| parameters will be ignored. If
+  /// |inspect_element_at| is non-empty then the element at the specified (x,y)
+  /// location will be inspected. The |windowInfo| parameter will be ignored if
+  /// this browser is wrapped in a CefBrowserView.
   ///
   /*--cef(optional_param=windowInfo,optional_param=client,
           optional_param=settings,optional_param=inspect_element_at)--*/
@@ -507,65 +538,65 @@
                             const CefPoint& inspect_element_at) = 0;
 
   ///
-  // Explicitly close the associated DevTools browser, if any.
+  /// Explicitly close the associated DevTools browser, if any.
   ///
   /*--cef()--*/
   virtual void CloseDevTools() = 0;
 
   ///
-  // Returns true if this browser currently has an associated DevTools browser.
-  // Must be called on the browser process UI thread.
+  /// Returns true if this browser currently has an associated DevTools browser.
+  /// Must be called on the browser process UI thread.
   ///
   /*--cef()--*/
   virtual bool HasDevTools() = 0;
 
   ///
-  // Send a method call message over the DevTools protocol. |message| must be a
-  // UTF8-encoded JSON dictionary that contains "id" (int), "method" (string)
-  // and "params" (dictionary, optional) values. See the DevTools protocol
-  // documentation at https://chromedevtools.github.io/devtools-protocol/ for
-  // details of supported methods and the expected "params" dictionary contents.
-  // |message| will be copied if necessary. This method will return true if
-  // called on the UI thread and the message was successfully submitted for
-  // validation, otherwise false. Validation will be applied asynchronously and
-  // any messages that fail due to formatting errors or missing parameters may
-  // be discarded without notification. Prefer ExecuteDevToolsMethod if a more
-  // structured approach to message formatting is desired.
-  //
-  // Every valid method call will result in an asynchronous method result or
-  // error message that references the sent message "id". Event messages are
-  // received while notifications are enabled (for example, between method calls
-  // for "Page.enable" and "Page.disable"). All received messages will be
-  // delivered to the observer(s) registered with AddDevToolsMessageObserver.
-  // See CefDevToolsMessageObserver::OnDevToolsMessage documentation for details
-  // of received message contents.
-  //
-  // Usage of the SendDevToolsMessage, ExecuteDevToolsMethod and
-  // AddDevToolsMessageObserver methods does not require an active DevTools
-  // front-end or remote-debugging session. Other active DevTools sessions will
-  // continue to function independently. However, any modification of global
-  // browser state by one session may not be reflected in the UI of other
-  // sessions.
-  //
-  // Communication with the DevTools front-end (when displayed) can be logged
-  // for development purposes by passing the
-  // `--devtools-protocol-log-file=<path>` command-line flag.
+  /// Send a method call message over the DevTools protocol. |message| must be a
+  /// UTF8-encoded JSON dictionary that contains "id" (int), "method" (string)
+  /// and "params" (dictionary, optional) values. See the DevTools protocol
+  /// documentation at https://chromedevtools.github.io/devtools-protocol/ for
+  /// details of supported methods and the expected "params" dictionary
+  /// contents. |message| will be copied if necessary. This method will return
+  /// true if called on the UI thread and the message was successfully submitted
+  /// for validation, otherwise false. Validation will be applied asynchronously
+  /// and any messages that fail due to formatting errors or missing parameters
+  /// may be discarded without notification. Prefer ExecuteDevToolsMethod if a
+  /// more structured approach to message formatting is desired.
+  ///
+  /// Every valid method call will result in an asynchronous method result or
+  /// error message that references the sent message "id". Event messages are
+  /// received while notifications are enabled (for example, between method
+  /// calls for "Page.enable" and "Page.disable"). All received messages will be
+  /// delivered to the observer(s) registered with AddDevToolsMessageObserver.
+  /// See CefDevToolsMessageObserver::OnDevToolsMessage documentation for
+  /// details of received message contents.
+  ///
+  /// Usage of the SendDevToolsMessage, ExecuteDevToolsMethod and
+  /// AddDevToolsMessageObserver methods does not require an active DevTools
+  /// front-end or remote-debugging session. Other active DevTools sessions will
+  /// continue to function independently. However, any modification of global
+  /// browser state by one session may not be reflected in the UI of other
+  /// sessions.
+  ///
+  /// Communication with the DevTools front-end (when displayed) can be logged
+  /// for development purposes by passing the
+  /// `--devtools-protocol-log-file=<path>` command-line flag.
   ///
   /*--cef()--*/
   virtual bool SendDevToolsMessage(const void* message,
                                    size_t message_size) = 0;
 
   ///
-  // Execute a method call over the DevTools protocol. This is a more structured
-  // version of SendDevToolsMessage. |message_id| is an incremental number that
-  // uniquely identifies the message (pass 0 to have the next number assigned
-  // automatically based on previous values). |method| is the method name.
-  // |params| are the method parameters, which may be empty. See the DevTools
-  // protocol documentation (linked above) for details of supported methods and
-  // the expected |params| dictionary contents. This method will return the
-  // assigned message ID if called on the UI thread and the message was
-  // successfully submitted for validation, otherwise 0. See the
-  // SendDevToolsMessage documentation for additional usage information.
+  /// Execute a method call over the DevTools protocol. This is a more
+  /// structured version of SendDevToolsMessage. |message_id| is an incremental
+  /// number that uniquely identifies the message (pass 0 to have the next
+  /// number assigned automatically based on previous values). |method| is the
+  /// method name. |params| are the method parameters, which may be empty. See
+  /// the DevTools protocol documentation (linked above) for details of
+  /// supported methods and the expected |params| dictionary contents. This
+  /// method will return the assigned message ID if called on the UI thread and
+  /// the message was successfully submitted for validation, otherwise 0. See
+  /// the SendDevToolsMessage documentation for additional usage information.
   ///
   /*--cef(optional_param=params)--*/
   virtual int ExecuteDevToolsMethod(int message_id,
@@ -573,19 +604,19 @@
                                     CefRefPtr<CefDictionaryValue> params) = 0;
 
   ///
-  // Add an observer for DevTools protocol messages (method results and events).
-  // The observer will remain registered until the returned Registration object
-  // is destroyed. See the SendDevToolsMessage documentation for additional
-  // usage information.
+  /// Add an observer for DevTools protocol messages (method results and
+  /// events). The observer will remain registered until the returned
+  /// Registration object is destroyed. See the SendDevToolsMessage
+  /// documentation for additional usage information.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefRegistration> AddDevToolsMessageObserver(
       CefRefPtr<CefDevToolsMessageObserver> observer) = 0;
 
   ///
-  // Retrieve a snapshot of current navigation entries as values sent to the
-  // specified visitor. If |current_only| is true only the current navigation
-  // entry will be sent, otherwise all navigation entries will be sent.
+  /// Retrieve a snapshot of current navigation entries as values sent to the
+  /// specified visitor. If |current_only| is true only the current navigation
+  /// entry will be sent, otherwise all navigation entries will be sent.
   ///
   /*--cef()--*/
   virtual void GetNavigationEntries(
@@ -593,88 +624,76 @@
       bool current_only) = 0;
 
   ///
-  // Set whether mouse cursor change is disabled.
-  ///
-  /*--cef()--*/
-  virtual void SetMouseCursorChangeDisabled(bool disabled) = 0;
-
-  ///
-  // Returns true if mouse cursor change is disabled.
-  ///
-  /*--cef()--*/
-  virtual bool IsMouseCursorChangeDisabled() = 0;
-
-  ///
-  // If a misspelled word is currently selected in an editable node calling
-  // this method will replace it with the specified |word|.
+  /// If a misspelled word is currently selected in an editable node calling
+  /// this method will replace it with the specified |word|.
   ///
   /*--cef()--*/
   virtual void ReplaceMisspelling(const CefString& word) = 0;
 
   ///
-  // Add the specified |word| to the spelling dictionary.
+  /// Add the specified |word| to the spelling dictionary.
   ///
   /*--cef()--*/
   virtual void AddWordToDictionary(const CefString& word) = 0;
 
   ///
-  // Returns true if window rendering is disabled.
+  /// Returns true if window rendering is disabled.
   ///
   /*--cef()--*/
   virtual bool IsWindowRenderingDisabled() = 0;
 
   ///
-  // Notify the browser that the widget has been resized. The browser will first
-  // call CefRenderHandler::GetViewRect to get the new size and then call
-  // CefRenderHandler::OnPaint asynchronously with the updated regions. This
-  // method is only used when window rendering is disabled.
+  /// Notify the browser that the widget has been resized. The browser will
+  /// first call CefRenderHandler::GetViewRect to get the new size and then call
+  /// CefRenderHandler::OnPaint asynchronously with the updated regions. This
+  /// method is only used when window rendering is disabled.
   ///
   /*--cef()--*/
   virtual void WasResized() = 0;
 
   ///
-  // Notify the browser that it has been hidden or shown. Layouting and
-  // CefRenderHandler::OnPaint notification will stop when the browser is
-  // hidden. This method is only used when window rendering is disabled.
+  /// Notify the browser that it has been hidden or shown. Layouting and
+  /// CefRenderHandler::OnPaint notification will stop when the browser is
+  /// hidden. This method is only used when window rendering is disabled.
   ///
   /*--cef()--*/
   virtual void WasHidden(bool hidden) = 0;
 
   ///
-  // Send a notification to the browser that the screen info has changed. The
-  // browser will then call CefRenderHandler::GetScreenInfo to update the
-  // screen information with the new values. This simulates moving the webview
-  // window from one display to another, or changing the properties of the
-  // current display. This method is only used when window rendering is
-  // disabled.
+  /// Send a notification to the browser that the screen info has changed. The
+  /// browser will then call CefRenderHandler::GetScreenInfo to update the
+  /// screen information with the new values. This simulates moving the webview
+  /// window from one display to another, or changing the properties of the
+  /// current display. This method is only used when window rendering is
+  /// disabled.
   ///
   /*--cef()--*/
   virtual void NotifyScreenInfoChanged() = 0;
 
   ///
-  // Invalidate the view. The browser will call CefRenderHandler::OnPaint
-  // asynchronously. This method is only used when window rendering is
-  // disabled.
+  /// Invalidate the view. The browser will call CefRenderHandler::OnPaint
+  /// asynchronously. This method is only used when window rendering is
+  /// disabled.
   ///
   /*--cef()--*/
   virtual void Invalidate(PaintElementType type) = 0;
 
   ///
-  // Issue a BeginFrame request to Chromium.  Only valid when
-  // CefWindowInfo::external_begin_frame_enabled is set to true.
+  /// Issue a BeginFrame request to Chromium.  Only valid when
+  /// CefWindowInfo::external_begin_frame_enabled is set to true.
   ///
   /*--cef()--*/
   virtual void SendExternalBeginFrame() = 0;
 
   ///
-  // Send a key event to the browser.
+  /// Send a key event to the browser.
   ///
   /*--cef()--*/
   virtual void SendKeyEvent(const CefKeyEvent& event) = 0;
 
   ///
-  // Send a mouse click event to the browser. The |x| and |y| coordinates are
-  // relative to the upper-left corner of the view.
+  /// Send a mouse click event to the browser. The |x| and |y| coordinates are
+  /// relative to the upper-left corner of the view.
   ///
   /*--cef()--*/
   virtual void SendMouseClickEvent(const CefMouseEvent& event,
@@ -683,19 +702,20 @@
                                    int clickCount) = 0;
 
   ///
-  // Send a mouse move event to the browser. The |x| and |y| coordinates are
-  // relative to the upper-left corner of the view.
+  /// Send a mouse move event to the browser. The |x| and |y| coordinates are
+  /// relative to the upper-left corner of the view.
   ///
   /*--cef()--*/
   virtual void SendMouseMoveEvent(const CefMouseEvent& event,
                                   bool mouseLeave) = 0;
 
   ///
-  // Send a mouse wheel event to the browser. The |x| and |y| coordinates are
-  // relative to the upper-left corner of the view. The |deltaX| and |deltaY|
-  // values represent the movement delta in the X and Y directions respectively.
-  // In order to scroll inside select popups with window rendering disabled
-  // CefRenderHandler::GetScreenPoint should be implemented properly.
+  /// Send a mouse wheel event to the browser. The |x| and |y| coordinates are
+  /// relative to the upper-left corner of the view. The |deltaX| and |deltaY|
+  /// values represent the movement delta in the X and Y directions
+  /// respectively. In order to scroll inside select popups with window
+  /// rendering disabled CefRenderHandler::GetScreenPoint should be implemented
+  /// properly.
   ///
   /*--cef()--*/
   virtual void SendMouseWheelEvent(const CefMouseEvent& event,
@@ -703,72 +723,68 @@
                                    int deltaY) = 0;
 
   ///
-  // Send a touch event to the browser for a windowless browser.
+  /// Send a touch event to the browser for a windowless browser.
   ///
   /*--cef()--*/
   virtual void SendTouchEvent(const CefTouchEvent& event) = 0;
 
   ///
-  // Send a focus event to the browser.
-  ///
-  /*--cef()--*/
-  virtual void SendFocusEvent(bool setFocus) = 0;
-
-  ///
-  // Send a capture lost event to the browser.
+  /// Send a capture lost event to the browser.
   ///
   /*--cef()--*/
   virtual void SendCaptureLostEvent() = 0;
 
   ///
-  // Notify the browser that the window hosting it is about to be moved or
-  // resized. This method is only used on Windows and Linux.
+  /// Notify the browser that the window hosting it is about to be moved or
+  /// resized. This method is only used on Windows and Linux.
   ///
   /*--cef()--*/
   virtual void NotifyMoveOrResizeStarted() = 0;
 
   ///
-  // Returns the maximum rate in frames per second (fps) that CefRenderHandler::
-  // OnPaint will be called for a windowless browser. The actual fps may be
-  // lower if the browser cannot generate frames at the requested rate. The
-  // minimum value is 1 and the maximum value is 60 (default 30). This method
-  // can only be called on the UI thread.
+  /// Returns the maximum rate in frames per second (fps) that
+  /// CefRenderHandler::OnPaint will be called for a windowless browser. The
+  /// actual fps may be lower if the browser cannot generate frames at the
+  /// requested rate. The minimum value is 1 and the maximum value is 60
+  /// (default 30). This method can only be called on the UI thread.
   ///
   /*--cef()--*/
   virtual int GetWindowlessFrameRate() = 0;
 
   ///
-  // Set the maximum rate in frames per second (fps) that CefRenderHandler::
-  // OnPaint will be called for a windowless browser. The actual fps may be
-  // lower if the browser cannot generate frames at the requested rate. The
-  // minimum value is 1 and the maximum value is 60 (default 30). Can also be
-  // set at browser creation via CefBrowserSettings.windowless_frame_rate.
+  /// Set the maximum rate in frames per second (fps) that CefRenderHandler::
+  /// OnPaint will be called for a windowless browser. The actual fps may be
+  /// lower if the browser cannot generate frames at the requested rate. The
+  /// minimum value is 1 and the maximum value is 60 (default 30). Can also be
+  /// set at browser creation via CefBrowserSettings.windowless_frame_rate.
   ///
   /*--cef()--*/
   virtual void SetWindowlessFrameRate(int frame_rate) = 0;
 
   ///
-  // Begins a new composition or updates the existing composition. Blink has a
-  // special node (a composition node) that allows the input method to change
-  // text without affecting other DOM nodes. |text| is the optional text that
-  // will be inserted into the composition node. |underlines| is an optional set
-  // of ranges that will be underlined in the resulting text.
-  // |replacement_range| is an optional range of the existing text that will be
-  // replaced. |selection_range| is an optional range of the resulting text that
-  // will be selected after insertion or replacement. The |replacement_range|
-  // value is only used on OS X.
-  //
-  // This method may be called multiple times as the composition changes. When
-  // the client is done making changes the composition should either be canceled
-  // or completed. To cancel the composition call ImeCancelComposition. To
-  // complete the composition call either ImeCommitText or
-  // ImeFinishComposingText. Completion is usually signaled when:
-  //   A. The client receives a WM_IME_COMPOSITION message with a GCS_RESULTSTR
-  //      flag (on Windows), or;
-  //   B. The client receives a "commit" signal of GtkIMContext (on Linux), or;
-  //   C. insertText of NSTextInput is called (on Mac).
-  //
-  // This method is only used when window rendering is disabled.
+  /// Begins a new composition or updates the existing composition. Blink has a
+  /// special node (a composition node) that allows the input method to change
+  /// text without affecting other DOM nodes. |text| is the optional text that
+  /// will be inserted into the composition node. |underlines| is an optional
+  /// set of ranges that will be underlined in the resulting text.
+  /// |replacement_range| is an optional range of the existing text that will be
+  /// replaced. |selection_range| is an optional range of the resulting text
+  /// that will be selected after insertion or replacement. The
+  /// |replacement_range| value is only used on OS X.
+  ///
+  /// This method may be called multiple times as the composition changes. When
+  /// the client is done making changes the composition should either be
+  /// canceled or completed. To cancel the composition call
+  /// ImeCancelComposition. To complete the composition call either
+  /// ImeCommitText or ImeFinishComposingText. Completion is usually signaled
+  /// when:
+  ///
+  /// 1. The client receives a WM_IME_COMPOSITION message with a GCS_RESULTSTR
+  ///    flag (on Windows), or;
+  /// 2. The client receives a "commit" signal of GtkIMContext (on Linux), or;
+  /// 3. insertText of NSTextInput is called (on Mac).
+  ///
+  /// This method is only used when window rendering is disabled.
   ///
   /*--cef(optional_param=text, optional_param=underlines)--*/
   virtual void ImeSetComposition(
@@ -778,13 +794,13 @@
       const CefRange& selection_range) = 0;
 
   ///
-  // Completes the existing composition by optionally inserting the specified
-  // |text| into the composition node. |replacement_range| is an optional range
-  // of the existing text that will be replaced. |relative_cursor_pos| is where
-  // the cursor will be positioned relative to the current cursor position. See
-  // comments on ImeSetComposition for usage. The |replacement_range| and
-  // |relative_cursor_pos| values are only used on OS X.
-  // This method is only used when window rendering is disabled.
+  /// Completes the existing composition by optionally inserting the specified
+  /// |text| into the composition node. |replacement_range| is an optional range
+  /// of the existing text that will be replaced. |relative_cursor_pos| is where
+  /// the cursor will be positioned relative to the current cursor position. See
+  /// comments on ImeSetComposition for usage. The |replacement_range| and
+  /// |relative_cursor_pos| values are only used on OS X.
+  /// This method is only used when window rendering is disabled.
   ///
   /*--cef(optional_param=text)--*/
   virtual void ImeCommitText(const CefString& text,
@@ -792,31 +808,31 @@
                              int relative_cursor_pos) = 0;
 
   ///
-  // Completes the existing composition by applying the current composition node
-  // contents. If |keep_selection| is false the current selection, if any, will
-  // be discarded. See comments on ImeSetComposition for usage.
-  // This method is only used when window rendering is disabled.
+  /// Completes the existing composition by applying the current composition
+  /// node contents. If |keep_selection| is false the current selection, if any,
+  /// will be discarded. See comments on ImeSetComposition for usage. This
+  /// method is only used when window rendering is disabled.
   ///
   /*--cef()--*/
   virtual void ImeFinishComposingText(bool keep_selection) = 0;
 
   ///
-  // Cancels the existing composition and discards the composition node
-  // contents without applying them. See comments on ImeSetComposition for
-  // usage.
-  // This method is only used when window rendering is disabled.
+  /// Cancels the existing composition and discards the composition node
+  /// contents without applying them. See comments on ImeSetComposition for
+  /// usage.
+  /// This method is only used when window rendering is disabled.
   ///
   /*--cef()--*/
   virtual void ImeCancelComposition() = 0;
 
   ///
-  // Call this method when the user drags the mouse into the web view (before
-  // calling DragTargetDragOver/DragTargetLeave/DragTargetDrop).
-  // |drag_data| should not contain file contents as this type of data is not
-  // allowed to be dragged into the web view. File contents can be removed using
-  // CefDragData::ResetFileContents (for example, if |drag_data| comes from
-  // CefRenderHandler::StartDragging).
-  // This method is only used when window rendering is disabled.
+  /// Call this method when the user drags the mouse into the web view (before
+  /// calling DragTargetDragOver/DragTargetLeave/DragTargetDrop).
+  /// |drag_data| should not contain file contents as this type of data is not
+  /// allowed to be dragged into the web view. File contents can be removed
+  /// using CefDragData::ResetFileContents (for example, if |drag_data| comes
+  /// from CefRenderHandler::StartDragging). This method is only used when
+  /// window rendering is disabled.
   ///
   /*--cef()--*/
   virtual void DragTargetDragEnter(CefRefPtr<CefDragData> drag_data,
@@ -824,97 +840,97 @@
                                    DragOperationsMask allowed_ops) = 0;
 
   ///
-  // Call this method each time the mouse is moved across the web view during
-  // a drag operation (after calling DragTargetDragEnter and before calling
-  // DragTargetDragLeave/DragTargetDrop).
-  // This method is only used when window rendering is disabled.
+  /// Call this method each time the mouse is moved across the web view during
+  /// a drag operation (after calling DragTargetDragEnter and before calling
+  /// DragTargetDragLeave/DragTargetDrop).
+  /// This method is only used when window rendering is disabled.
   ///
   /*--cef()--*/
   virtual void DragTargetDragOver(const CefMouseEvent& event,
                                   DragOperationsMask allowed_ops) = 0;
 
   ///
-  // Call this method when the user drags the mouse out of the web view (after
-  // calling DragTargetDragEnter).
-  // This method is only used when window rendering is disabled.
+  /// Call this method when the user drags the mouse out of the web view (after
+  /// calling DragTargetDragEnter).
+  /// This method is only used when window rendering is disabled.
   ///
   /*--cef()--*/
   virtual void DragTargetDragLeave() = 0;
 
   ///
-  // Call this method when the user completes the drag operation by dropping
-  // the object onto the web view (after calling DragTargetDragEnter).
-  // The object being dropped is |drag_data|, given as an argument to
-  // the previous DragTargetDragEnter call.
-  // This method is only used when window rendering is disabled.
+  /// Call this method when the user completes the drag operation by dropping
+  /// the object onto the web view (after calling DragTargetDragEnter).
+  /// The object being dropped is |drag_data|, given as an argument to
+  /// the previous DragTargetDragEnter call.
+  /// This method is only used when window rendering is disabled.
   ///
   /*--cef()--*/
   virtual void DragTargetDrop(const CefMouseEvent& event) = 0;
 
   ///
-  // Call this method when the drag operation started by a
-  // CefRenderHandler::StartDragging call has ended either in a drop or
-  // by being cancelled. |x| and |y| are mouse coordinates relative to the
-  // upper-left corner of the view. If the web view is both the drag source
-  // and the drag target then all DragTarget* methods should be called before
-  // DragSource* mthods.
-  // This method is only used when window rendering is disabled.
+  /// Call this method when the drag operation started by a
+  /// CefRenderHandler::StartDragging call has ended either in a drop or
+  /// by being cancelled. |x| and |y| are mouse coordinates relative to the
+  /// upper-left corner of the view. If the web view is both the drag source
+  /// and the drag target then all DragTarget* methods should be called before
+  /// DragSource* mthods.
+  /// This method is only used when window rendering is disabled.
   ///
   /*--cef()--*/
   virtual void DragSourceEndedAt(int x, int y, DragOperationsMask op) = 0;
 
   ///
-  // Call this method when the drag operation started by a
-  // CefRenderHandler::StartDragging call has completed. This method may be
-  // called immediately without first calling DragSourceEndedAt to cancel a
-  // drag operation. If the web view is both the drag source and the drag
-  // target then all DragTarget* methods should be called before DragSource*
-  // mthods.
-  // This method is only used when window rendering is disabled.
+  /// Call this method when the drag operation started by a
+  /// CefRenderHandler::StartDragging call has completed. This method may be
+  /// called immediately without first calling DragSourceEndedAt to cancel a
+  /// drag operation. If the web view is both the drag source and the drag
+  /// target then all DragTarget* methods should be called before DragSource*
+  /// mthods.
+  /// This method is only used when window rendering is disabled.
   ///
   /*--cef()--*/
   virtual void DragSourceSystemDragEnded() = 0;
 
   ///
-  // Returns the current visible navigation entry for this browser. This method
-  // can only be called on the UI thread.
+  /// Returns the current visible navigation entry for this browser. This method
+  /// can only be called on the UI thread.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefNavigationEntry> GetVisibleNavigationEntry() = 0;
 
   ///
-  // Set accessibility state for all frames. |accessibility_state| may be
-  // default, enabled or disabled. If |accessibility_state| is STATE_DEFAULT
-  // then accessibility will be disabled by default and the state may be further
-  // controlled with the "force-renderer-accessibility" and
-  // "disable-renderer-accessibility" command-line switches. If
-  // |accessibility_state| is STATE_ENABLED then accessibility will be enabled.
-  // If |accessibility_state| is STATE_DISABLED then accessibility will be
-  // completely disabled.
-  //
-  // For windowed browsers accessibility will be enabled in Complete mode (which
-  // corresponds to kAccessibilityModeComplete in Chromium). In this mode all
-  // platform accessibility objects will be created and managed by Chromium's
-  // internal implementation. The client needs only to detect the screen reader
-  // and call this method appropriately. For example, on macOS the client can
-  // handle the @"AXEnhancedUserInterface" accessibility attribute to detect
-  // VoiceOver state changes and on Windows the client can handle WM_GETOBJECT
-  // with OBJID_CLIENT to detect accessibility readers.
-  //
-  // For windowless browsers accessibility will be enabled in TreeOnly mode
-  // (which corresponds to kAccessibilityModeWebContentsOnly in Chromium). In
-  // this mode renderer accessibility is enabled, the full tree is computed, and
-  // events are passed to CefAccessibiltyHandler, but platform accessibility
-  // objects are not created. The client may implement platform accessibility
-  // objects using CefAccessibiltyHandler callbacks if desired.
+  /// Set accessibility state for all frames. |accessibility_state| may be
+  /// default, enabled or disabled. If |accessibility_state| is STATE_DEFAULT
+  /// then accessibility will be disabled by default and the state may be
+  /// further controlled with the "force-renderer-accessibility" and
+  /// "disable-renderer-accessibility" command-line switches. If
+  /// |accessibility_state| is STATE_ENABLED then accessibility will be enabled.
+  /// If |accessibility_state| is STATE_DISABLED then accessibility will be
+  /// completely disabled.
+  ///
+  /// For windowed browsers accessibility will be enabled in Complete mode
+  /// (which corresponds to kAccessibilityModeComplete in Chromium). In this
+  /// mode all platform accessibility objects will be created and managed by
+  /// Chromium's internal implementation. The client needs only to detect the
+  /// screen reader and call this method appropriately. For example, on macOS
+  /// the client can handle the @"AXEnhancedUserInterface" accessibility
+  /// attribute to detect VoiceOver state changes and on Windows the client can
+  /// handle WM_GETOBJECT with OBJID_CLIENT to detect accessibility readers.
+  ///
+  /// For windowless browsers accessibility will be enabled in TreeOnly mode
+  /// (which corresponds to kAccessibilityModeWebContentsOnly in Chromium). In
+  /// this mode renderer accessibility is enabled, the full tree is computed,
+  /// and events are passed to CefAccessibiltyHandler, but platform
+  /// accessibility objects are not created. The client may implement platform
+  /// accessibility objects using CefAccessibiltyHandler callbacks if desired.
   ///
   /*--cef()--*/
   virtual void SetAccessibilityState(cef_state_t accessibility_state) = 0;
 
   ///
-  // Enable notifications of auto resize via CefDisplayHandler::OnAutoResize.
-  // Notifications are disabled by default. |min_size| and |max_size| define the
-  // range of allowed sizes.
+  /// Enable notifications of auto resize via CefDisplayHandler::OnAutoResize.
+  /// Notifications are disabled by default. |min_size| and |max_size| define
+  /// the range of allowed sizes.
   ///
   /*--cef()--*/
   virtual void SetAutoResizeEnabled(bool enabled,
@@ -922,32 +938,74 @@
                                     const CefSize& max_size) = 0;
 
   ///
-  // Returns the extension hosted in this browser or NULL if no extension is
-  // hosted. See CefRequestContext::LoadExtension for details.
+  /// Returns the extension hosted in this browser or NULL if no extension is
+  /// hosted. See CefRequestContext::LoadExtension for details.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefExtension> GetExtension() = 0;
 
   ///
-  // Returns true if this browser is hosting an extension background script.
-  // Background hosts do not have a window and are not displayable. See
-  // CefRequestContext::LoadExtension for details.
+  /// Returns true if this browser is hosting an extension background script.
+  /// Background hosts do not have a window and are not displayable. See
+  /// CefRequestContext::LoadExtension for details.
   ///
   /*--cef()--*/
   virtual bool IsBackgroundHost() = 0;
 
   ///
-  //  Set whether the browser's audio is muted.
+  /// Set whether the browser's audio is muted.
   ///
   /*--cef()--*/
   virtual void SetAudioMuted(bool mute) = 0;
 
   ///
-  // Returns true if the browser's audio is muted.  This method can only be
-  // called on the UI thread.
+  /// Returns true if the browser's audio is muted.  This method can only be
+  /// called on the UI thread.
   ///
   /*--cef()--*/
   virtual bool IsAudioMuted() = 0;
+
+  ///
+  /// Returns true if the renderer is currently in browser fullscreen. This
+  /// differs from window fullscreen in that browser fullscreen is entered using
+  /// the JavaScript Fullscreen API and modifies CSS attributes such as the
+  /// ::backdrop pseudo-element and :fullscreen pseudo-class. This method can
+  /// only be called on the UI thread.
+  ///
+  /*--cef()--*/
+  virtual bool IsFullscreen() = 0;
+
+  ///
+  /// Requests the renderer to exit browser fullscreen. In most cases exiting
+  /// window fullscreen should also exit browser fullscreen. With the Alloy
+  /// runtime this method should be called in response to a user action such as
+  /// clicking the green traffic light button on MacOS
+  /// (CefWindowDelegate::OnWindowFullscreenTransition callback) or pressing the
+  /// "ESC" key (CefKeyboardHandler::OnPreKeyEvent callback). With the Chrome
+  /// runtime these standard exit actions are handled internally but
+  /// new/additional user actions can use this method. Set |will_cause_resize|
+  /// to true if exiting browser fullscreen will cause a view resize.
+  ///
+  /*--cef()--*/
+  virtual void ExitFullscreen(bool will_cause_resize) = 0;
+
+  ///
+  /// Returns true if a Chrome command is supported and enabled. Values for
+  /// |command_id| can be found in the cef_command_ids.h file. This method can
+  /// only be called on the UI thread. Only used with the Chrome runtime.
+  ///
+  /*--cef()--*/
+  virtual bool CanExecuteChromeCommand(int command_id) = 0;
+
+  ///
+  /// Execute a Chrome command. Values for |command_id| can be found in the
+  /// cef_command_ids.h file. |disposition| provides information about the
+  /// intended command target. Only used with the Chrome runtime.
+  ///
+  /*--cef()--*/
+  virtual void ExecuteChromeCommand(
+      int command_id,
+      cef_window_open_disposition_t disposition) = 0;
 };
 
 #endif  // CEF_INCLUDE_CEF_BROWSER_H_
diff --git a/src/include/cef_browser_process_handler.h b/src/include/cef_browser_process_handler.h
index 7120606..4ab8c9a 100644
--- a/src/include/cef_browser_process_handler.h
+++ b/src/include/cef_browser_process_handler.h
@@ -39,68 +39,89 @@
 #pragma once
 
 #include "include/cef_base.h"
+#include "include/cef_client.h"
 #include "include/cef_command_line.h"
-#include "include/cef_print_handler.h"
+#include "include/cef_preference.h"
 #include "include/cef_values.h"
 
 ///
-// Class used to implement browser process callbacks. The methods of this class
-// will be called on the browser process main thread unless otherwise indicated.
+/// Class used to implement browser process callbacks. The methods of this class
+/// will be called on the browser process main thread unless otherwise
+/// indicated.
 ///
 /*--cef(source=client,no_debugct_check)--*/
 class CefBrowserProcessHandler : public virtual CefBaseRefCounted {
  public:
   ///
-  // Called on the browser process UI thread immediately after the CEF context
-  // has been initialized.
+  /// Provides an opportunity to register custom preferences prior to
+  /// global and request context initialization.
+  ///
+  /// If |type| is CEF_PREFERENCES_TYPE_GLOBAL the registered preferences can be
+  /// accessed via CefPreferenceManager::GetGlobalPreferences after
+  /// OnContextInitialized is called. Global preferences are registered a single
+  /// time at application startup. See related cef_settings_t.cache_path and
+  /// cef_settings_t.persist_user_preferences configuration.
+  ///
+  /// If |type| is CEF_PREFERENCES_TYPE_REQUEST_CONTEXT the preferences can be
+  /// accessed via the CefRequestContext after
+  /// CefRequestContextHandler::OnRequestContextInitialized is called. Request
+  /// context preferences are registered each time a new CefRequestContext is
+  /// created. It is intended but not required that all request contexts have
+  /// the same registered preferences. See related
+  /// cef_request_context_settings_t.cache_path and
+  /// cef_request_context_settings_t.persist_user_preferences configuration.
+  ///
+  /// Do not keep a reference to the |registrar| object. This method is called
+  /// on the browser process UI thread.
+  ///
+  /*--cef()--*/
+  virtual void OnRegisterCustomPreferences(
+      cef_preferences_type_t type,
+      CefRawPtr<CefPreferenceRegistrar> registrar) {}
+
+  ///
+  /// Called on the browser process UI thread immediately after the CEF context
+  /// has been initialized.
   ///
   /*--cef()--*/
   virtual void OnContextInitialized() {}
 
   ///
-  // Called before a child process is launched. Will be called on the browser
-  // process UI thread when launching a render process and on the browser
-  // process IO thread when launching a GPU or plugin process. Provides an
-  // opportunity to modify the child process command line. Do not keep a
-  // reference to |command_line| outside of this method.
+  /// Called before a child process is launched. Will be called on the browser
+  /// process UI thread when launching a render process and on the browser
+  /// process IO thread when launching a GPU process. Provides an opportunity to
+  /// modify the child process command line. Do not keep a reference to
+  /// |command_line| outside of this method.
   ///
   /*--cef()--*/
   virtual void OnBeforeChildProcessLaunch(
       CefRefPtr<CefCommandLine> command_line) {}
 
   ///
-  // Called on the browser process IO thread after the main thread has been
-  // created for a new render process. Provides an opportunity to specify extra
-  // information that will be passed to
-  // CefRenderProcessHandler::OnRenderThreadCreated() in the render process. Do
-  // not keep a reference to |extra_info| outside of this method.
+  /// Called from any thread when work has been scheduled for the browser
+  /// process main (UI) thread. This callback is used in combination with
+  /// cef_settings_t.external_message_pump and CefDoMessageLoopWork() in cases
+  /// where the CEF message loop must be integrated into an existing application
+  /// message loop (see additional comments and warnings on
+  /// CefDoMessageLoopWork). This callback should schedule a
+  /// CefDoMessageLoopWork() call to happen on the main (UI) thread. |delay_ms|
+  /// is the requested delay in milliseconds. If |delay_ms| is <= 0 then the
+  /// call should happen reasonably soon. If |delay_ms| is > 0 then the call
+  /// should be scheduled to happen after the specified delay and any currently
+  /// pending scheduled call should be cancelled.
   ///
   /*--cef()--*/
-  virtual void OnRenderProcessThreadCreated(
-      CefRefPtr<CefListValue> extra_info) {}
+  virtual void OnScheduleMessagePumpWork(int64_t delay_ms) {}
 
   ///
-  // Return the handler for printing on Linux. If a print handler is not
-  // provided then printing will not be supported on the Linux platform.
+  /// Return the default client for use with a newly created browser window. If
+  /// null is returned the browser will be unmanaged (no callbacks will be
+  /// executed for that browser) and application shutdown will be blocked until
+  /// the browser window is closed manually. This method is currently only used
+  /// with the chrome runtime.
   ///
   /*--cef()--*/
-  virtual CefRefPtr<CefPrintHandler> GetPrintHandler() { return nullptr; }
-
-  ///
-  // Called from any thread when work has been scheduled for the browser process
-  // main (UI) thread. This callback is used in combination with CefSettings.
-  // external_message_pump and CefDoMessageLoopWork() in cases where the CEF
-  // message loop must be integrated into an existing application message loop
-  // (see additional comments and warnings on CefDoMessageLoopWork). This
-  // callback should schedule a CefDoMessageLoopWork() call to happen on the
-  // main (UI) thread. |delay_ms| is the requested delay in milliseconds. If
-  // |delay_ms| is <= 0 then the call should happen reasonably soon. If
-  // |delay_ms| is > 0 then the call should be scheduled to happen after the
-  // specified delay and any currently pending scheduled call should be
-  // cancelled.
-  ///
-  /*--cef()--*/
-  virtual void OnScheduleMessagePumpWork(int64 delay_ms) {}
+  virtual CefRefPtr<CefClient> GetDefaultClient() { return nullptr; }
 };
 
 #endif  // CEF_INCLUDE_CEF_BROWSER_PROCESS_HANDLER_H_
diff --git a/src/include/cef_callback.h b/src/include/cef_callback.h
index e206cb9..b9e1111 100644
--- a/src/include/cef_callback.h
+++ b/src/include/cef_callback.h
@@ -41,32 +41,32 @@
 #include "include/cef_base.h"
 
 ///
-// Generic callback interface used for asynchronous continuation.
+/// Generic callback interface used for asynchronous continuation.
 ///
 /*--cef(source=library)--*/
 class CefCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Continue processing.
+  /// Continue processing.
   ///
   /*--cef(capi_name=cont)--*/
   virtual void Continue() = 0;
 
   ///
-  // Cancel processing.
+  /// Cancel processing.
   ///
   /*--cef()--*/
   virtual void Cancel() = 0;
 };
 
 ///
-// Generic callback interface used for asynchronous completion.
+/// Generic callback interface used for asynchronous completion.
 ///
 /*--cef(source=client)--*/
 class CefCompletionCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Method that will be called once the task is complete.
+  /// Method that will be called once the task is complete.
   ///
   /*--cef()--*/
   virtual void OnComplete() = 0;
diff --git a/src/include/cef_client.h b/src/include/cef_client.h
index ada7a6a..758c75f 100644
--- a/src/include/cef_client.h
+++ b/src/include/cef_client.h
@@ -40,6 +40,7 @@
 
 #include "include/cef_audio_handler.h"
 #include "include/cef_base.h"
+#include "include/cef_command_handler.h"
 #include "include/cef_context_menu_handler.h"
 #include "include/cef_dialog_handler.h"
 #include "include/cef_display_handler.h"
@@ -47,29 +48,39 @@
 #include "include/cef_drag_handler.h"
 #include "include/cef_find_handler.h"
 #include "include/cef_focus_handler.h"
+#include "include/cef_frame_handler.h"
 #include "include/cef_jsdialog_handler.h"
 #include "include/cef_keyboard_handler.h"
 #include "include/cef_life_span_handler.h"
 #include "include/cef_load_handler.h"
+#include "include/cef_permission_handler.h"
+#include "include/cef_print_handler.h"
 #include "include/cef_process_message.h"
 #include "include/cef_render_handler.h"
 #include "include/cef_request_handler.h"
 
 ///
-// Implement this interface to provide handler implementations.
+/// Implement this interface to provide handler implementations.
 ///
 /*--cef(source=client,no_debugct_check)--*/
 class CefClient : public virtual CefBaseRefCounted {
  public:
   ///
-  // Return the handler for audio rendering events.
+  /// Return the handler for audio rendering events.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefAudioHandler> GetAudioHandler() { return nullptr; }
 
   ///
-  // Return the handler for context menus. If no handler is provided the default
-  // implementation will be used.
+  /// Return the handler for commands. If no handler is provided the default
+  /// implementation will be used.
+  ///
+  /*--cef()--*/
+  virtual CefRefPtr<CefCommandHandler> GetCommandHandler() { return nullptr; }
+
+  ///
+  /// Return the handler for context menus. If no handler is provided the
+  /// default implementation will be used.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() {
@@ -77,84 +88,107 @@
   }
 
   ///
-  // Return the handler for dialogs. If no handler is provided the default
-  // implementation will be used.
+  /// Return the handler for dialogs. If no handler is provided the default
+  /// implementation will be used.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDialogHandler> GetDialogHandler() { return nullptr; }
 
   ///
-  // Return the handler for browser display state events.
+  /// Return the handler for browser display state events.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() { return nullptr; }
 
   ///
-  // Return the handler for download events. If no handler is returned downloads
-  // will not be allowed.
+  /// Return the handler for download events. If no handler is returned
+  /// downloads will not be allowed.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDownloadHandler> GetDownloadHandler() { return nullptr; }
 
   ///
-  // Return the handler for drag events.
+  /// Return the handler for drag events.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDragHandler> GetDragHandler() { return nullptr; }
 
   ///
-  // Return the handler for find result events.
+  /// Return the handler for find result events.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefFindHandler> GetFindHandler() { return nullptr; }
 
   ///
-  // Return the handler for focus events.
+  /// Return the handler for focus events.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefFocusHandler> GetFocusHandler() { return nullptr; }
 
   ///
-  // Return the handler for JavaScript dialogs. If no handler is provided the
-  // default implementation will be used.
+  /// Return the handler for events related to CefFrame lifespan. This method
+  /// will be called once during CefBrowser creation and the result will be
+  /// cached for performance reasons.
+  ///
+  /*--cef()--*/
+  virtual CefRefPtr<CefFrameHandler> GetFrameHandler() { return nullptr; }
+
+  ///
+  /// Return the handler for permission requests.
+  ///
+  /*--cef()--*/
+  virtual CefRefPtr<CefPermissionHandler> GetPermissionHandler() {
+    return nullptr;
+  }
+
+  ///
+  /// Return the handler for JavaScript dialogs. If no handler is provided the
+  /// default implementation will be used.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefJSDialogHandler> GetJSDialogHandler() { return nullptr; }
 
   ///
-  // Return the handler for keyboard events.
+  /// Return the handler for keyboard events.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() { return nullptr; }
 
   ///
-  // Return the handler for browser life span events.
+  /// Return the handler for browser life span events.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() { return nullptr; }
 
   ///
-  // Return the handler for browser load status events.
+  /// Return the handler for browser load status events.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefLoadHandler> GetLoadHandler() { return nullptr; }
 
   ///
-  // Return the handler for off-screen rendering events.
+  /// Return the handler for printing on Linux. If a print handler is not
+  /// provided then printing will not be supported on the Linux platform.
+  ///
+  /*--cef()--*/
+  virtual CefRefPtr<CefPrintHandler> GetPrintHandler() { return nullptr; }
+
+  ///
+  /// Return the handler for off-screen rendering events.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefRenderHandler> GetRenderHandler() { return nullptr; }
 
   ///
-  // Return the handler for browser request events.
+  /// Return the handler for browser request events.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefRequestHandler> GetRequestHandler() { return nullptr; }
 
   ///
-  // Called when a new message is received from a different process. Return true
-  // if the message was handled or false otherwise. Do not keep a reference to
-  // or attempt to access the message outside of this callback.
+  /// Called when a new message is received from a different process. Return
+  /// true if the message was handled or false otherwise.  It is safe to keep a
+  /// reference to |message| outside of this callback.
   ///
   /*--cef()--*/
   virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
diff --git a/src/include/cef_command_handler.h b/src/include/cef_command_handler.h
new file mode 100644
index 0000000..eed05a0
--- /dev/null
+++ b/src/include/cef_command_handler.h
@@ -0,0 +1,114 @@
+// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---------------------------------------------------------------------------
+//
+// The contents of this file must follow a specific format in order to
+// support the CEF translator tool. See the translator.README.txt file in the
+// tools directory for more information.
+//
+
+#ifndef CEF_INCLUDE_CEF_COMMAND_HANDLER_H_
+#define CEF_INCLUDE_CEF_COMMAND_HANDLER_H_
+#pragma once
+
+#include "include/cef_base.h"
+#include "include/cef_browser.h"
+
+///
+/// Implement this interface to handle events related to commands. The methods
+/// of this class will be called on the UI thread.
+///
+/*--cef(source=client)--*/
+class CefCommandHandler : public virtual CefBaseRefCounted {
+ public:
+  ///
+  /// Called to execute a Chrome command triggered via menu selection or
+  /// keyboard shortcut. Values for |command_id| can be found in the
+  /// cef_command_ids.h file. |disposition| provides information about the
+  /// intended command target. Return true if the command was handled or false
+  /// for the default implementation. For context menu commands this will be
+  /// called after CefContextMenuHandler::OnContextMenuCommand. Only used with
+  /// the Chrome runtime.
+  ///
+  /*--cef()--*/
+  virtual bool OnChromeCommand(CefRefPtr<CefBrowser> browser,
+                               int command_id,
+                               cef_window_open_disposition_t disposition) {
+    return false;
+  }
+
+  ///
+  /// Called to check if a Chrome app menu item should be visible. Values for
+  /// |command_id| can be found in the cef_command_ids.h file. Only called for
+  /// menu items that would be visible by default. Only used with the Chrome
+  /// runtime.
+  ///
+  /*--cef()--*/
+  virtual bool IsChromeAppMenuItemVisible(CefRefPtr<CefBrowser> browser,
+                                          int command_id) {
+    return true;
+  }
+
+  ///
+  /// Called to check if a Chrome app menu item should be enabled. Values for
+  /// |command_id| can be found in the cef_command_ids.h file. Only called for
+  /// menu items that would be enabled by default. Only used with the Chrome
+  /// runtime.
+  ///
+  /*--cef()--*/
+  virtual bool IsChromeAppMenuItemEnabled(CefRefPtr<CefBrowser> browser,
+                                          int command_id) {
+    return true;
+  }
+
+  ///
+  /// Called during browser creation to check if a Chrome page action icon
+  /// should be visible. Only called for icons that would be visible by default.
+  /// Only used with the Chrome runtime.
+  ///
+  /*--cef(optional_param=browser)--*/
+  virtual bool IsChromePageActionIconVisible(
+      cef_chrome_page_action_icon_type_t icon_type) {
+    return true;
+  }
+
+  ///
+  /// Called during browser creation to check if a Chrome toolbar button
+  /// should be visible. Only called for buttons that would be visible by
+  /// default. Only used with the Chrome runtime.
+  ///
+  /*--cef(optional_param=browser)--*/
+  virtual bool IsChromeToolbarButtonVisible(
+      cef_chrome_toolbar_button_type_t button_type) {
+    return true;
+  }
+};
+
+#endif  // CEF_INCLUDE_CEF_COMMAND_HANDLER_H_
diff --git a/src/include/cef_command_line.h b/src/include/cef_command_line.h
index dd5491c..9ae6ee6 100644
--- a/src/include/cef_command_line.h
+++ b/src/include/cef_command_line.h
@@ -43,14 +43,15 @@
 #include "include/cef_base.h"
 
 ///
-// Class used to create and/or parse command line arguments. Arguments with
-// '--', '-' and, on Windows, '/' prefixes are considered switches. Switches
-// will always precede any arguments without switch prefixes. Switches can
-// optionally have a value specified using the '=' delimiter (e.g.
-// "-switch=value"). An argument of "--" will terminate switch parsing with all
-// subsequent tokens, regardless of prefix, being interpreted as non-switch
-// arguments. Switch names are considered case-insensitive. This class can be
-// used before CefInitialize() is called.
+/// Class used to create and/or parse command line arguments. Arguments with
+/// "--", "-" and, on Windows, "/" prefixes are considered switches. Switches
+/// will always precede any arguments without switch prefixes. Switches can
+/// optionally have a value specified using the "=" delimiter (e.g.
+/// "-switch=value"). An argument of "--" will terminate switch parsing with all
+/// subsequent tokens, regardless of prefix, being interpreted as non-switch
+/// arguments. Switch names should be lowercase ASCII and will be converted to
+/// such if necessary. Switch values will retain the original case and UTF8
+/// encoding. This class can be used before CefInitialize() is called.
 ///
 /*--cef(source=library,no_debugct_check)--*/
 class CefCommandLine : public virtual CefBaseRefCounted {
@@ -59,147 +60,148 @@
   typedef std::map<CefString, CefString> SwitchMap;
 
   ///
-  // Create a new CefCommandLine instance.
+  /// Create a new CefCommandLine instance.
   ///
   /*--cef(api_hash_check)--*/
   static CefRefPtr<CefCommandLine> CreateCommandLine();
 
   ///
-  // Returns the singleton global CefCommandLine object. The returned object
-  // will be read-only.
+  /// Returns the singleton global CefCommandLine object. The returned object
+  /// will be read-only.
   ///
   /*--cef(api_hash_check)--*/
   static CefRefPtr<CefCommandLine> GetGlobalCommandLine();
 
   ///
-  // Returns true if this object is valid. Do not call any other methods if this
-  // function returns false.
+  /// Returns true if this object is valid. Do not call any other methods if
+  /// this function returns false.
   ///
   /*--cef()--*/
   virtual bool IsValid() = 0;
 
   ///
-  // Returns true if the values of this object are read-only. Some APIs may
-  // expose read-only objects.
+  /// Returns true if the values of this object are read-only. Some APIs may
+  /// expose read-only objects.
   ///
   /*--cef()--*/
   virtual bool IsReadOnly() = 0;
 
   ///
-  // Returns a writable copy of this object.
+  /// Returns a writable copy of this object.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefCommandLine> Copy() = 0;
 
   ///
-  // Initialize the command line with the specified |argc| and |argv| values.
-  // The first argument must be the name of the program. This method is only
-  // supported on non-Windows platforms.
+  /// Initialize the command line with the specified |argc| and |argv| values.
+  /// The first argument must be the name of the program. This method is only
+  /// supported on non-Windows platforms.
   ///
   /*--cef()--*/
   virtual void InitFromArgv(int argc, const char* const* argv) = 0;
 
   ///
-  // Initialize the command line with the string returned by calling
-  // GetCommandLineW(). This method is only supported on Windows.
+  /// Initialize the command line with the string returned by calling
+  /// GetCommandLineW(). This method is only supported on Windows.
   ///
   /*--cef()--*/
   virtual void InitFromString(const CefString& command_line) = 0;
 
   ///
-  // Reset the command-line switches and arguments but leave the program
-  // component unchanged.
+  /// Reset the command-line switches and arguments but leave the program
+  /// component unchanged.
   ///
   /*--cef()--*/
   virtual void Reset() = 0;
 
   ///
-  // Retrieve the original command line string as a vector of strings.
-  // The argv array: { program, [(--|-|/)switch[=value]]*, [--], [argument]* }
+  /// Retrieve the original command line string as a vector of strings.
+  /// The argv array:
+  /// `{ program, [(--|-|/)switch[=value]]*, [--], [argument]* }`
   ///
   /*--cef()--*/
   virtual void GetArgv(std::vector<CefString>& argv) = 0;
 
   ///
-  // Constructs and returns the represented command line string. Use this method
-  // cautiously because quoting behavior is unclear.
+  /// Constructs and returns the represented command line string. Use this
+  /// method cautiously because quoting behavior is unclear.
   ///
   /*--cef()--*/
   virtual CefString GetCommandLineString() = 0;
 
   ///
-  // Get the program part of the command line string (the first item).
+  /// Get the program part of the command line string (the first item).
   ///
   /*--cef()--*/
   virtual CefString GetProgram() = 0;
 
   ///
-  // Set the program part of the command line string (the first item).
+  /// Set the program part of the command line string (the first item).
   ///
   /*--cef()--*/
   virtual void SetProgram(const CefString& program) = 0;
 
   ///
-  // Returns true if the command line has switches.
+  /// Returns true if the command line has switches.
   ///
   /*--cef()--*/
   virtual bool HasSwitches() = 0;
 
   ///
-  // Returns true if the command line contains the given switch.
+  /// Returns true if the command line contains the given switch.
   ///
   /*--cef()--*/
   virtual bool HasSwitch(const CefString& name) = 0;
 
   ///
-  // Returns the value associated with the given switch. If the switch has no
-  // value or isn't present this method returns the empty string.
+  /// Returns the value associated with the given switch. If the switch has no
+  /// value or isn't present this method returns the empty string.
   ///
   /*--cef()--*/
   virtual CefString GetSwitchValue(const CefString& name) = 0;
 
   ///
-  // Returns the map of switch names and values. If a switch has no value an
-  // empty string is returned.
+  /// Returns the map of switch names and values. If a switch has no value an
+  /// empty string is returned.
   ///
   /*--cef()--*/
   virtual void GetSwitches(SwitchMap& switches) = 0;
 
   ///
-  // Add a switch to the end of the command line. If the switch has no value
-  // pass an empty value string.
+  /// Add a switch to the end of the command line.
   ///
   /*--cef()--*/
   virtual void AppendSwitch(const CefString& name) = 0;
 
   ///
-  // Add a switch with the specified value to the end of the command line.
+  /// Add a switch with the specified value to the end of the command line. If
+  /// the switch has no value pass an empty value string.
   ///
   /*--cef()--*/
   virtual void AppendSwitchWithValue(const CefString& name,
                                      const CefString& value) = 0;
 
   ///
-  // True if there are remaining command line arguments.
+  /// True if there are remaining command line arguments.
   ///
   /*--cef()--*/
   virtual bool HasArguments() = 0;
 
   ///
-  // Get the remaining command line arguments.
+  /// Get the remaining command line arguments.
   ///
   /*--cef()--*/
   virtual void GetArguments(ArgumentList& arguments) = 0;
 
   ///
-  // Add an argument to the end of the command line.
+  /// Add an argument to the end of the command line.
   ///
   /*--cef()--*/
   virtual void AppendArgument(const CefString& argument) = 0;
 
   ///
-  // Insert a command before the current command.
-  // Common for debuggers, like "valgrind" or "gdb --args".
+  /// Insert a command before the current command.
+  /// Common for debuggers, like "valgrind" or "gdb --args".
   ///
   /*--cef()--*/
   virtual void PrependWrapper(const CefString& wrapper) = 0;
diff --git a/src/include/cef_context_menu_handler.h b/src/include/cef_context_menu_handler.h
index 2a2a73e..d499592 100644
--- a/src/include/cef_context_menu_handler.h
+++ b/src/include/cef_context_menu_handler.h
@@ -46,42 +46,61 @@
 class CefContextMenuParams;
 
 ///
-// Callback interface used for continuation of custom context menu display.
+/// Callback interface used for continuation of custom context menu display.
 ///
 /*--cef(source=library)--*/
 class CefRunContextMenuCallback : public virtual CefBaseRefCounted {
  public:
-  typedef cef_event_flags_t EventFlags;
-
   ///
-  // Complete context menu display by selecting the specified |command_id| and
-  // |event_flags|.
+  /// Complete context menu display by selecting the specified |command_id| and
+  /// |event_flags|.
   ///
   /*--cef(capi_name=cont)--*/
-  virtual void Continue(int command_id, EventFlags event_flags) = 0;
+  virtual void Continue(int command_id, cef_event_flags_t event_flags) = 0;
 
   ///
-  // Cancel context menu display.
+  /// Cancel context menu display.
   ///
   /*--cef()--*/
   virtual void Cancel() = 0;
 };
 
 ///
-// Implement this interface to handle context menu events. The methods of this
-// class will be called on the UI thread.
+/// Callback interface used for continuation of custom quick menu display.
+///
+/*--cef(source=library)--*/
+class CefRunQuickMenuCallback : public virtual CefBaseRefCounted {
+ public:
+  ///
+  /// Complete quick menu display by selecting the specified |command_id| and
+  /// |event_flags|.
+  ///
+  /*--cef(capi_name=cont)--*/
+  virtual void Continue(int command_id, cef_event_flags_t event_flags) = 0;
+
+  ///
+  /// Cancel quick menu display.
+  ///
+  /*--cef()--*/
+  virtual void Cancel() = 0;
+};
+
+///
+/// Implement this interface to handle context menu events. The methods of this
+/// class will be called on the UI thread.
 ///
 /*--cef(source=client)--*/
 class CefContextMenuHandler : public virtual CefBaseRefCounted {
  public:
   typedef cef_event_flags_t EventFlags;
+  typedef cef_quick_menu_edit_state_flags_t QuickMenuEditStateFlags;
 
   ///
-  // Called before a context menu is displayed. |params| provides information
-  // about the context menu state. |model| initially contains the default
-  // context menu. The |model| can be cleared to show no context menu or
-  // modified to show a custom menu. Do not keep references to |params| or
-  // |model| outside of this callback.
+  /// Called before a context menu is displayed. |params| provides information
+  /// about the context menu state. |model| initially contains the default
+  /// context menu. The |model| can be cleared to show no context menu or
+  /// modified to show a custom menu. Do not keep references to |params| or
+  /// |model| outside of this callback.
   ///
   /*--cef()--*/
   virtual void OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
@@ -90,12 +109,12 @@
                                    CefRefPtr<CefMenuModel> model) {}
 
   ///
-  // Called to allow custom display of the context menu. |params| provides
-  // information about the context menu state. |model| contains the context menu
-  // model resulting from OnBeforeContextMenu. For custom display return true
-  // and execute |callback| either synchronously or asynchronously with the
-  // selected command ID. For default display return false. Do not keep
-  // references to |params| or |model| outside of this callback.
+  /// Called to allow custom display of the context menu. |params| provides
+  /// information about the context menu state. |model| contains the context
+  /// menu model resulting from OnBeforeContextMenu. For custom display return
+  /// true and execute |callback| either synchronously or asynchronously with
+  /// the selected command ID. For default display return false. Do not keep
+  /// references to |params| or |model| outside of this callback.
   ///
   /*--cef()--*/
   virtual bool RunContextMenu(CefRefPtr<CefBrowser> browser,
@@ -107,13 +126,13 @@
   }
 
   ///
-  // Called to execute a command selected from the context menu. Return true if
-  // the command was handled or false for the default implementation. See
-  // cef_menu_id_t for the command ids that have default implementations. All
-  // user-defined command ids should be between MENU_ID_USER_FIRST and
-  // MENU_ID_USER_LAST. |params| will have the same values as what was passed to
-  // OnBeforeContextMenu(). Do not keep a reference to |params| outside of this
-  // callback.
+  /// Called to execute a command selected from the context menu. Return true if
+  /// the command was handled or false for the default implementation. See
+  /// cef_menu_id_t for the command ids that have default implementations. All
+  /// user-defined command ids should be between MENU_ID_USER_FIRST and
+  /// MENU_ID_USER_LAST. |params| will have the same values as what was passed
+  /// to OnBeforeContextMenu(). Do not keep a reference to |params| outside of
+  /// this callback.
   ///
   /*--cef()--*/
   virtual bool OnContextMenuCommand(CefRefPtr<CefBrowser> browser,
@@ -125,17 +144,57 @@
   }
 
   ///
-  // Called when the context menu is dismissed irregardless of whether the menu
-  // was empty or a command was selected.
+  /// Called when the context menu is dismissed irregardless of whether the menu
+  /// was canceled or a command was selected.
   ///
   /*--cef()--*/
   virtual void OnContextMenuDismissed(CefRefPtr<CefBrowser> browser,
                                       CefRefPtr<CefFrame> frame) {}
+
+  ///
+  /// Called to allow custom display of the quick menu for a windowless browser.
+  /// |location| is the top left corner of the selected region. |size| is the
+  /// size of the selected region. |edit_state_flags| is a combination of flags
+  /// that represent the state of the quick menu. Return true if the menu will
+  /// be handled and execute |callback| either synchronously or asynchronously
+  /// with the selected command ID. Return false to cancel the menu.
+  ///
+  /*--cef()--*/
+  virtual bool RunQuickMenu(CefRefPtr<CefBrowser> browser,
+                            CefRefPtr<CefFrame> frame,
+                            const CefPoint& location,
+                            const CefSize& size,
+                            QuickMenuEditStateFlags edit_state_flags,
+                            CefRefPtr<CefRunQuickMenuCallback> callback) {
+    return false;
+  }
+
+  ///
+  /// Called to execute a command selected from the quick menu for a windowless
+  /// browser. Return true if the command was handled or false for the default
+  /// implementation. See cef_menu_id_t for command IDs that have default
+  /// implementations.
+  ///
+  /*--cef()--*/
+  virtual bool OnQuickMenuCommand(CefRefPtr<CefBrowser> browser,
+                                  CefRefPtr<CefFrame> frame,
+                                  int command_id,
+                                  EventFlags event_flags) {
+    return false;
+  }
+
+  ///
+  /// Called when the quick menu for a windowless browser is dismissed
+  /// irregardless of whether the menu was canceled or a command was selected.
+  ///
+  /*--cef()--*/
+  virtual void OnQuickMenuDismissed(CefRefPtr<CefBrowser> browser,
+                                    CefRefPtr<CefFrame> frame) {}
 };
 
 ///
-// Provides information about the context menu state. The ethods of this class
-// can only be accessed on browser process the UI thread.
+/// Provides information about the context menu state. The methods of this class
+/// can only be accessed on browser process the UI thread.
 ///
 /*--cef(source=library)--*/
 class CefContextMenuParams : public virtual CefBaseRefCounted {
@@ -146,147 +205,143 @@
   typedef cef_context_menu_edit_state_flags_t EditStateFlags;
 
   ///
-  // Returns the X coordinate of the mouse where the context menu was invoked.
-  // Coords are relative to the associated RenderView's origin.
+  /// Returns the X coordinate of the mouse where the context menu was invoked.
+  /// Coords are relative to the associated RenderView's origin.
   ///
   /*--cef()--*/
   virtual int GetXCoord() = 0;
 
   ///
-  // Returns the Y coordinate of the mouse where the context menu was invoked.
-  // Coords are relative to the associated RenderView's origin.
+  /// Returns the Y coordinate of the mouse where the context menu was invoked.
+  /// Coords are relative to the associated RenderView's origin.
   ///
   /*--cef()--*/
   virtual int GetYCoord() = 0;
 
   ///
-  // Returns flags representing the type of node that the context menu was
-  // invoked on.
+  /// Returns flags representing the type of node that the context menu was
+  /// invoked on.
   ///
   /*--cef(default_retval=CM_TYPEFLAG_NONE)--*/
   virtual TypeFlags GetTypeFlags() = 0;
 
   ///
-  // Returns the URL of the link, if any, that encloses the node that the
-  // context menu was invoked on.
+  /// Returns the URL of the link, if any, that encloses the node that the
+  /// context menu was invoked on.
   ///
   /*--cef()--*/
   virtual CefString GetLinkUrl() = 0;
 
   ///
-  // Returns the link URL, if any, to be used ONLY for "copy link address". We
-  // don't validate this field in the frontend process.
+  /// Returns the link URL, if any, to be used ONLY for "copy link address". We
+  /// don't validate this field in the frontend process.
   ///
   /*--cef()--*/
   virtual CefString GetUnfilteredLinkUrl() = 0;
 
   ///
-  // Returns the source URL, if any, for the element that the context menu was
-  // invoked on. Example of elements with source URLs are img, audio, and video.
+  /// Returns the source URL, if any, for the element that the context menu was
+  /// invoked on. Example of elements with source URLs are img, audio, and
+  /// video.
   ///
   /*--cef()--*/
   virtual CefString GetSourceUrl() = 0;
 
   ///
-  // Returns true if the context menu was invoked on an image which has
-  // non-empty contents.
+  /// Returns true if the context menu was invoked on an image which has
+  /// non-empty contents.
   ///
   /*--cef()--*/
   virtual bool HasImageContents() = 0;
 
   ///
-  // Returns the title text or the alt text if the context menu was invoked on
-  // an image.
+  /// Returns the title text or the alt text if the context menu was invoked on
+  /// an image.
   ///
   /*--cef()--*/
   virtual CefString GetTitleText() = 0;
 
   ///
-  // Returns the URL of the top level page that the context menu was invoked on.
+  /// Returns the URL of the top level page that the context menu was invoked
+  /// on.
   ///
   /*--cef()--*/
   virtual CefString GetPageUrl() = 0;
 
   ///
-  // Returns the URL of the subframe that the context menu was invoked on.
+  /// Returns the URL of the subframe that the context menu was invoked on.
   ///
   /*--cef()--*/
   virtual CefString GetFrameUrl() = 0;
 
   ///
-  // Returns the character encoding of the subframe that the context menu was
-  // invoked on.
+  /// Returns the character encoding of the subframe that the context menu was
+  /// invoked on.
   ///
   /*--cef()--*/
   virtual CefString GetFrameCharset() = 0;
 
   ///
-  // Returns the type of context node that the context menu was invoked on.
+  /// Returns the type of context node that the context menu was invoked on.
   ///
   /*--cef(default_retval=CM_MEDIATYPE_NONE)--*/
   virtual MediaType GetMediaType() = 0;
 
   ///
-  // Returns flags representing the actions supported by the media element, if
-  // any, that the context menu was invoked on.
+  /// Returns flags representing the actions supported by the media element, if
+  /// any, that the context menu was invoked on.
   ///
   /*--cef(default_retval=CM_MEDIAFLAG_NONE)--*/
   virtual MediaStateFlags GetMediaStateFlags() = 0;
 
   ///
-  // Returns the text of the selection, if any, that the context menu was
-  // invoked on.
+  /// Returns the text of the selection, if any, that the context menu was
+  /// invoked on.
   ///
   /*--cef()--*/
   virtual CefString GetSelectionText() = 0;
 
   ///
-  // Returns the text of the misspelled word, if any, that the context menu was
-  // invoked on.
+  /// Returns the text of the misspelled word, if any, that the context menu was
+  /// invoked on.
   ///
   /*--cef()--*/
   virtual CefString GetMisspelledWord() = 0;
 
   ///
-  // Returns true if suggestions exist, false otherwise. Fills in |suggestions|
-  // from the spell check service for the misspelled word if there is one.
+  /// Returns true if suggestions exist, false otherwise. Fills in |suggestions|
+  /// from the spell check service for the misspelled word if there is one.
   ///
   /*--cef()--*/
   virtual bool GetDictionarySuggestions(
       std::vector<CefString>& suggestions) = 0;
 
   ///
-  // Returns true if the context menu was invoked on an editable node.
+  /// Returns true if the context menu was invoked on an editable node.
   ///
   /*--cef()--*/
   virtual bool IsEditable() = 0;
 
   ///
-  // Returns true if the context menu was invoked on an editable node where
-  // spell-check is enabled.
+  /// Returns true if the context menu was invoked on an editable node where
+  /// spell-check is enabled.
   ///
   /*--cef()--*/
   virtual bool IsSpellCheckEnabled() = 0;
 
   ///
-  // Returns flags representing the actions supported by the editable node, if
-  // any, that the context menu was invoked on.
+  /// Returns flags representing the actions supported by the editable node, if
+  /// any, that the context menu was invoked on.
   ///
   /*--cef(default_retval=CM_EDITFLAG_NONE)--*/
   virtual EditStateFlags GetEditStateFlags() = 0;
 
   ///
-  // Returns true if the context menu contains items specified by the renderer
-  // process (for example, plugin placeholder or pepper plugin menu items).
+  /// Returns true if the context menu contains items specified by the renderer
+  /// process.
   ///
   /*--cef()--*/
   virtual bool IsCustomMenu() = 0;
-
-  ///
-  // Returns true if the context menu was invoked from a pepper plugin.
-  ///
-  /*--cef()--*/
-  virtual bool IsPepperMenu() = 0;
 };
 
 #endif  // CEF_INCLUDE_CEF_CONTEXT_MENU_HANDLER_H_
diff --git a/src/include/cef_cookie.h b/src/include/cef_cookie.h
index f48c7df..e3a6820 100644
--- a/src/include/cef_cookie.h
+++ b/src/include/cef_cookie.h
@@ -47,52 +47,38 @@
 class CefDeleteCookiesCallback;
 
 ///
-// Class used for managing cookies. The methods of this class may be called on
-// any thread unless otherwise indicated.
+/// Class used for managing cookies. The methods of this class may be called on
+/// any thread unless otherwise indicated.
 ///
 /*--cef(source=library,no_debugct_check)--*/
 class CefCookieManager : public virtual CefBaseRefCounted {
  public:
   ///
-  // Returns the global cookie manager. By default data will be stored at
-  // CefSettings.cache_path if specified or in memory otherwise. If |callback|
-  // is non-NULL it will be executed asnychronously on the UI thread after the
-  // manager's storage has been initialized. Using this method is equivalent to
-  // calling CefRequestContext::GetGlobalContext()->GetDefaultCookieManager().
+  /// Returns the global cookie manager. By default data will be stored at
+  /// cef_settings_t.cache_path if specified or in memory otherwise. If
+  /// |callback| is non-NULL it will be executed asnychronously on the UI thread
+  /// after the manager's storage has been initialized. Using this method is
+  /// equivalent to calling
+  /// CefRequestContext::GetGlobalContext()->GetDefaultCookieManager().
   ///
   /*--cef(optional_param=callback)--*/
   static CefRefPtr<CefCookieManager> GetGlobalManager(
       CefRefPtr<CefCompletionCallback> callback);
 
   ///
-  // Set the schemes supported by this manager. If |include_defaults| is true
-  // the default schemes ("http", "https", "ws" and "wss") will also be
-  // supported. Calling this method with an empty |schemes| value and
-  // |include_defaults| set to false will disable all loading and saving of
-  // cookies for this manager. If |callback| is non-NULL it will be executed
-  // asnychronously on the UI thread after the change has been applied. Must be
-  // called before any cookies are accessed.
-  ///
-  /*--cef(optional_param=callback)--*/
-  virtual void SetSupportedSchemes(
-      const std::vector<CefString>& schemes,
-      bool include_defaults,
-      CefRefPtr<CefCompletionCallback> callback) = 0;
-
-  ///
-  // Visit all cookies on the UI thread. The returned cookies are ordered by
-  // longest path, then by earliest creation date. Returns false if cookies
-  // cannot be accessed.
+  /// Visit all cookies on the UI thread. The returned cookies are ordered by
+  /// longest path, then by earliest creation date. Returns false if cookies
+  /// cannot be accessed.
   ///
   /*--cef()--*/
   virtual bool VisitAllCookies(CefRefPtr<CefCookieVisitor> visitor) = 0;
 
   ///
-  // Visit a subset of cookies on the UI thread. The results are filtered by the
-  // given url scheme, host, domain and path. If |includeHttpOnly| is true
-  // HTTP-only cookies will also be included in the results. The returned
-  // cookies are ordered by longest path, then by earliest creation date.
-  // Returns false if cookies cannot be accessed.
+  /// Visit a subset of cookies on the UI thread. The results are filtered by
+  /// the given url scheme, host, domain and path. If |includeHttpOnly| is true
+  /// HTTP-only cookies will also be included in the results. The returned
+  /// cookies are ordered by longest path, then by earliest creation date.
+  /// Returns false if cookies cannot be accessed.
   ///
   /*--cef()--*/
   virtual bool VisitUrlCookies(const CefString& url,
@@ -100,13 +86,13 @@
                                CefRefPtr<CefCookieVisitor> visitor) = 0;
 
   ///
-  // Sets a cookie given a valid URL and explicit user-provided cookie
-  // attributes. This function expects each attribute to be well-formed. It will
-  // check for disallowed characters (e.g. the ';' character is disallowed
-  // within the cookie value attribute) and fail without setting the cookie if
-  // such characters are found. If |callback| is non-NULL it will be executed
-  // asnychronously on the UI thread after the cookie has been set. Returns
-  // false if an invalid URL is specified or if cookies cannot be accessed.
+  /// Sets a cookie given a valid URL and explicit user-provided cookie
+  /// attributes. This function expects each attribute to be well-formed. It
+  /// will check for disallowed characters (e.g. the ';' character is disallowed
+  /// within the cookie value attribute) and fail without setting the cookie if
+  /// such characters are found. If |callback| is non-NULL it will be executed
+  /// asnychronously on the UI thread after the cookie has been set. Returns
+  /// false if an invalid URL is specified or if cookies cannot be accessed.
   ///
   /*--cef(optional_param=callback)--*/
   virtual bool SetCookie(const CefString& url,
@@ -114,15 +100,15 @@
                          CefRefPtr<CefSetCookieCallback> callback) = 0;
 
   ///
-  // Delete all cookies that match the specified parameters. If both |url| and
-  // |cookie_name| values are specified all host and domain cookies matching
-  // both will be deleted. If only |url| is specified all host cookies (but not
-  // domain cookies) irrespective of path will be deleted. If |url| is empty all
-  // cookies for all hosts and domains will be deleted. If |callback| is
-  // non-NULL it will be executed asnychronously on the UI thread after the
-  // cookies have been deleted. Returns false if a non-empty invalid URL is
-  // specified or if cookies cannot be accessed. Cookies can alternately be
-  // deleted using the Visit*Cookies() methods.
+  /// Delete all cookies that match the specified parameters. If both |url| and
+  /// |cookie_name| values are specified all host and domain cookies matching
+  /// both will be deleted. If only |url| is specified all host cookies (but not
+  /// domain cookies) irrespective of path will be deleted. If |url| is empty
+  /// all cookies for all hosts and domains will be deleted. If |callback| is
+  /// non-NULL it will be executed asnychronously on the UI thread after the
+  /// cookies have been deleted. Returns false if a non-empty invalid URL is
+  /// specified or if cookies cannot be accessed. Cookies can alternately be
+  /// deleted using the Visit*Cookies() methods.
   ///
   /*--cef(optional_param=url,optional_param=cookie_name,
           optional_param=callback)--*/
@@ -131,27 +117,27 @@
                              CefRefPtr<CefDeleteCookiesCallback> callback) = 0;
 
   ///
-  // Flush the backing store (if any) to disk. If |callback| is non-NULL it will
-  // be executed asnychronously on the UI thread after the flush is complete.
-  // Returns false if cookies cannot be accessed.
+  /// Flush the backing store (if any) to disk. If |callback| is non-NULL it
+  /// will be executed asnychronously on the UI thread after the flush is
+  /// complete. Returns false if cookies cannot be accessed.
   ///
   /*--cef(optional_param=callback)--*/
   virtual bool FlushStore(CefRefPtr<CefCompletionCallback> callback) = 0;
 };
 
 ///
-// Interface to implement for visiting cookie values. The methods of this class
-// will always be called on the UI thread.
+/// Interface to implement for visiting cookie values. The methods of this class
+/// will always be called on the UI thread.
 ///
 /*--cef(source=client)--*/
 class CefCookieVisitor : public virtual CefBaseRefCounted {
  public:
   ///
-  // Method that will be called once for each cookie. |count| is the 0-based
-  // index for the current cookie. |total| is the total number of cookies.
-  // Set |deleteCookie| to true to delete the cookie currently being visited.
-  // Return false to stop visiting cookies. This method may never be called if
-  // no cookies are found.
+  /// Method that will be called once for each cookie. |count| is the 0-based
+  /// index for the current cookie. |total| is the total number of cookies.
+  /// Set |deleteCookie| to true to delete the cookie currently being visited.
+  /// Return false to stop visiting cookies. This method may never be called if
+  /// no cookies are found.
   ///
   /*--cef()--*/
   virtual bool Visit(const CefCookie& cookie,
@@ -161,30 +147,30 @@
 };
 
 ///
-// Interface to implement to be notified of asynchronous completion via
-// CefCookieManager::SetCookie().
+/// Interface to implement to be notified of asynchronous completion via
+/// CefCookieManager::SetCookie().
 ///
 /*--cef(source=client)--*/
 class CefSetCookieCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Method that will be called upon completion. |success| will be true if the
-  // cookie was set successfully.
+  /// Method that will be called upon completion. |success| will be true if the
+  /// cookie was set successfully.
   ///
   /*--cef()--*/
   virtual void OnComplete(bool success) = 0;
 };
 
 ///
-// Interface to implement to be notified of asynchronous completion via
-// CefCookieManager::DeleteCookies().
+/// Interface to implement to be notified of asynchronous completion via
+/// CefCookieManager::DeleteCookies().
 ///
 /*--cef(source=client)--*/
 class CefDeleteCookiesCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Method that will be called upon completion. |num_deleted| will be the
-  // number of cookies that were deleted.
+  /// Method that will be called upon completion. |num_deleted| will be the
+  /// number of cookies that were deleted.
   ///
   /*--cef()--*/
   virtual void OnComplete(int num_deleted) = 0;
diff --git a/src/include/cef_crash_util.h b/src/include/cef_crash_util.h
index e569df7..956b5ff 100644
--- a/src/include/cef_crash_util.h
+++ b/src/include/cef_crash_util.h
@@ -39,94 +39,97 @@
 #pragma once
 
 ///
-// Crash reporting is configured using an INI-style config file named
-// "crash_reporter.cfg". On Windows and Linux this file must be placed next to
-// the main application executable. On macOS this file must be placed in the
-// top-level app bundle Resources directory (e.g.
-// "<appname>.app/Contents/Resources"). File contents are as follows:
-//
-//  # Comments start with a hash character and must be on their own line.
-//
-//  [Config]
-//  ProductName=<Value of the "prod" crash key; defaults to "cef">
-//  ProductVersion=<Value of the "ver" crash key; defaults to the CEF version>
-//  AppName=<Windows only; App-specific folder name component for storing crash
-//           information; default to "CEF">
-//  ExternalHandler=<Windows only; Name of the external handler exe to use
-//                   instead of re-launching the main exe; default to empty>
-//  BrowserCrashForwardingEnabled=<macOS only; True if browser process crashes
-//                                 should be forwarded to the system crash
-//                                 reporter; default to false>
-//  ServerURL=<crash server URL; default to empty>
-//  RateLimitEnabled=<True if uploads should be rate limited; default to true>
-//  MaxUploadsPerDay=<Max uploads per 24 hours, used if rate limit is enabled;
-//                    default to 5>
-//  MaxDatabaseSizeInMb=<Total crash report disk usage greater than this value
-//                       will cause older reports to be deleted; default to 20>
-//  MaxDatabaseAgeInDays=<Crash reports older than this value will be deleted;
-//                        default to 5>
-//
-//  [CrashKeys]
-//  my_key1=<small|medium|large>
-//  my_key2=<small|medium|large>
-//
-// Config section:
-//
-// If "ProductName" and/or "ProductVersion" are set then the specified values
-// will be included in the crash dump metadata. On macOS if these values are set
-// to empty then they will be retrieved from the Info.plist file using the
-// "CFBundleName" and "CFBundleShortVersionString" keys respectively.
-//
-// If "AppName" is set on Windows then crash report information (metrics,
-// database and dumps) will be stored locally on disk under the
-// "C:\Users\[CurrentUser]\AppData\Local\[AppName]\User Data" folder. On other
-// platforms the CefSettings.user_data_path value will be used.
-//
-// If "ExternalHandler" is set on Windows then the specified exe will be
-// launched as the crashpad-handler instead of re-launching the main process
-// exe. The value can be an absolute path or a path relative to the main exe
-// directory. On Linux the CefSettings.browser_subprocess_path value will be
-// used. On macOS the existing subprocess app bundle will be used.
-//
-// If "BrowserCrashForwardingEnabled" is set to true on macOS then browser
-// process crashes will be forwarded to the system crash reporter. This results
-// in the crash UI dialog being displayed to the user and crash reports being
-// logged under "~/Library/Logs/DiagnosticReports". Forwarding of crash reports
-// from non-browser processes and Debug builds is always disabled.
-//
-// If "ServerURL" is set then crashes will be uploaded as a multi-part POST
-// request to the specified URL. Otherwise, reports will only be stored locally
-// on disk.
-//
-// If "RateLimitEnabled" is set to true then crash report uploads will be rate
-// limited as follows:
-//  1. If "MaxUploadsPerDay" is set to a positive value then at most the
-//     specified number of crashes will be uploaded in each 24 hour period.
-//  2. If crash upload fails due to a network or server error then an
-//     incremental backoff delay up to a maximum of 24 hours will be applied for
-//     retries.
-//  3. If a backoff delay is applied and "MaxUploadsPerDay" is > 1 then the
-//     "MaxUploadsPerDay" value will be reduced to 1 until the client is
-//     restarted. This helps to avoid an upload flood when the network or
-//     server error is resolved.
-// Rate limiting is not supported on Linux.
-//
-// If "MaxDatabaseSizeInMb" is set to a positive value then crash report storage
-// on disk will be limited to that size in megabytes. For example, on Windows
-// each dump is about 600KB so a "MaxDatabaseSizeInMb" value of 20 equates to
-// about 34 crash reports stored on disk. Not supported on Linux.
-//
-// If "MaxDatabaseAgeInDays" is set to a positive value then crash reports older
-// than the specified age in days will be deleted. Not supported on Linux.
-//
-// CrashKeys section:
-//
-// A maximum of 26 crash keys of each size can be specified for use by the
-// application. Crash key values will be truncated based on the specified size
-// (small = 64 bytes, medium = 256 bytes, large = 1024 bytes). The value of
-// crash keys can be set from any thread or process using the
-// CefSetCrashKeyValue function. These key/value pairs will be sent to the crash
-// server along with the crash dump file.
+/// Crash reporting is configured using an INI-style config file named
+/// "crash_reporter.cfg". On Windows and Linux this file must be placed next to
+/// the main application executable. On macOS this file must be placed in the
+/// top-level app bundle Resources directory (e.g.
+/// "<appname>.app/Contents/Resources"). File contents are as follows:
+///
+/// <pre>
+///  # Comments start with a hash character and must be on their own line.
+///
+///  [Config]
+///  ProductName=<Value of the "prod" crash key; defaults to "cef">
+///  ProductVersion=<Value of the "ver" crash key; defaults to the CEF version>
+///  AppName=<Windows only; App-specific folder name component for storing crash
+///           information; default to "CEF">
+///  ExternalHandler=<Windows only; Name of the external handler exe to use
+///                   instead of re-launching the main exe; default to empty>
+///  BrowserCrashForwardingEnabled=<macOS only; True if browser process crashes
+///                                 should be forwarded to the system crash
+///                                 reporter; default to false>
+///  ServerURL=<crash server URL; default to empty>
+///  RateLimitEnabled=<True if uploads should be rate limited; default to true>
+///  MaxUploadsPerDay=<Max uploads per 24 hours, used if rate limit is enabled;
+///                    default to 5>
+///  MaxDatabaseSizeInMb=<Total crash report disk usage greater than this value
+///                       will cause older reports to be deleted; default to 20>
+///  MaxDatabaseAgeInDays=<Crash reports older than this value will be deleted;
+///                        default to 5>
+///
+///  [CrashKeys]
+///  my_key1=<small|medium|large>
+///  my_key2=<small|medium|large>
+/// </pre>
+///
+/// <b>Config section:</b>
+///
+/// If "ProductName" and/or "ProductVersion" are set then the specified values
+/// will be included in the crash dump metadata. On macOS if these values are
+/// set to empty then they will be retrieved from the Info.plist file using the
+/// "CFBundleName" and "CFBundleShortVersionString" keys respectively.
+///
+/// If "AppName" is set on Windows then crash report information (metrics,
+/// database and dumps) will be stored locally on disk under the
+/// "C:\Users\[CurrentUser]\AppData\Local\[AppName]\User Data" folder. On other
+/// platforms the cef_settings_t.root_cache_path value will be used.
+///
+/// If "ExternalHandler" is set on Windows then the specified exe will be
+/// launched as the crashpad-handler instead of re-launching the main process
+/// exe. The value can be an absolute path or a path relative to the main exe
+/// directory. On Linux the cef_settings_t.browser_subprocess_path value will be
+/// used. On macOS the existing subprocess app bundle will be used.
+///
+/// If "BrowserCrashForwardingEnabled" is set to true on macOS then browser
+/// process crashes will be forwarded to the system crash reporter. This results
+/// in the crash UI dialog being displayed to the user and crash reports being
+/// logged under "~/Library/Logs/DiagnosticReports". Forwarding of crash reports
+/// from non-browser processes and Debug builds is always disabled.
+///
+/// If "ServerURL" is set then crashes will be uploaded as a multi-part POST
+/// request to the specified URL. Otherwise, reports will only be stored locally
+/// on disk.
+///
+/// If "RateLimitEnabled" is set to true then crash report uploads will be rate
+/// limited as follows:
+///  1. If "MaxUploadsPerDay" is set to a positive value then at most the
+///     specified number of crashes will be uploaded in each 24 hour period.
+///  2. If crash upload fails due to a network or server error then an
+///     incremental backoff delay up to a maximum of 24 hours will be applied
+///     for retries.
+///  3. If a backoff delay is applied and "MaxUploadsPerDay" is > 1 then the
+///     "MaxUploadsPerDay" value will be reduced to 1 until the client is
+///     restarted. This helps to avoid an upload flood when the network or
+///     server error is resolved.
+/// Rate limiting is not supported on Linux.
+///
+/// If "MaxDatabaseSizeInMb" is set to a positive value then crash report
+/// storage on disk will be limited to that size in megabytes. For example, on
+/// Windows each dump is about 600KB so a "MaxDatabaseSizeInMb" value of 20
+/// equates to about 34 crash reports stored on disk. Not supported on Linux.
+///
+/// If "MaxDatabaseAgeInDays" is set to a positive value then crash reports
+/// older than the specified age in days will be deleted. Not supported on
+/// Linux.
+///
+/// <b>CrashKeys section:</b>
+///
+/// A maximum of 26 crash keys of each size can be specified for use by the
+/// application. Crash key values will be truncated based on the specified size
+/// (small = 64 bytes, medium = 256 bytes, large = 1024 bytes). The value of
+/// crash keys can be set from any thread or process using the
+/// CefSetCrashKeyValue function. These key/value pairs will be sent to the
+/// crash server along with the crash dump file.
 ///
 /*--cef()--*/
 bool CefCrashReportingEnabled();
@@ -134,7 +137,7 @@
 #include "include/cef_base.h"
 
 ///
-// Sets or clears a specific key-value pair from the crash metadata.
+/// Sets or clears a specific key-value pair from the crash metadata.
 ///
 /*--cef(optional_param=value)--*/
 void CefSetCrashKeyValue(const CefString& key, const CefString& value);
diff --git a/src/include/cef_devtools_message_observer.h b/src/include/cef_devtools_message_observer.h
index c65aee9..757c607 100644
--- a/src/include/cef_devtools_message_observer.h
+++ b/src/include/cef_devtools_message_observer.h
@@ -43,32 +43,33 @@
 class CefBrowser;
 
 ///
-// Callback interface for CefBrowserHost::AddDevToolsMessageObserver. The
-// methods of this class will be called on the browser process UI thread.
+/// Callback interface for CefBrowserHost::AddDevToolsMessageObserver. The
+/// methods of this class will be called on the browser process UI thread.
 ///
 /*--cef(source=client)--*/
 class CefDevToolsMessageObserver : public virtual CefBaseRefCounted {
  public:
   ///
-  // Method that will be called on receipt of a DevTools protocol message.
-  // |browser| is the originating browser instance. |message| is a UTF8-encoded
-  // JSON dictionary representing either a method result or an event. |message|
-  // is only valid for the scope of this callback and should be copied if
-  // necessary. Return true if the message was handled or false if the message
-  // should be further processed and passed to the OnDevToolsMethodResult or
-  // OnDevToolsEvent methods as appropriate.
-  //
-  // Method result dictionaries include an "id" (int) value that identifies the
-  // orginating method call sent from CefBrowserHost::SendDevToolsMessage, and
-  // optionally either a "result" (dictionary) or "error" (dictionary) value.
-  // The "error" dictionary will contain "code" (int) and "message" (string)
-  // values. Event dictionaries include a "method" (string) value and optionally
-  // a "params" (dictionary) value. See the DevTools protocol documentation at
-  // https://chromedevtools.github.io/devtools-protocol/ for details of
-  // supported method calls and the expected "result" or "params" dictionary
-  // contents. JSON dictionaries can be parsed using the CefParseJSON function
-  // if desired, however be aware of performance considerations when parsing
-  // large messages (some of which may exceed 1MB in size).
+  /// Method that will be called on receipt of a DevTools protocol message.
+  /// |browser| is the originating browser instance. |message| is a UTF8-encoded
+  /// JSON dictionary representing either a method result or an event. |message|
+  /// is only valid for the scope of this callback and should be copied if
+  /// necessary. Return true if the message was handled or false if the message
+  /// should be further processed and passed to the OnDevToolsMethodResult or
+  /// OnDevToolsEvent methods as appropriate.
+  ///
+  /// Method result dictionaries include an "id" (int) value that identifies the
+  /// orginating method call sent from CefBrowserHost::SendDevToolsMessage, and
+  /// optionally either a "result" (dictionary) or "error" (dictionary) value.
+  /// The "error" dictionary will contain "code" (int) and "message" (string)
+  /// values. Event dictionaries include a "method" (string) value and
+  /// optionally a "params" (dictionary) value. See the DevTools protocol
+  /// documentation at https://chromedevtools.github.io/devtools-protocol/ for
+  /// details of supported method calls and the expected "result" or "params"
+  /// dictionary contents. JSON dictionaries can be parsed using the
+  /// CefParseJSON function if desired, however be aware of performance
+  /// considerations when parsing large messages (some of which may exceed 1MB
+  /// in size).
   ///
   /*--cef()--*/
   virtual bool OnDevToolsMessage(CefRefPtr<CefBrowser> browser,
@@ -78,15 +79,16 @@
   }
 
   ///
-  // Method that will be called after attempted execution of a DevTools protocol
-  // method. |browser| is the originating browser instance. |message_id| is the
-  // "id" value that identifies the originating method call message. If the
-  // method succeeded |success| will be true and |result| will be the
-  // UTF8-encoded JSON "result" dictionary value (which may be empty). If the
-  // method failed |success| will be false and |result| will be the UTF8-encoded
-  // JSON "error" dictionary value. |result| is only valid for the scope of this
-  // callback and should be copied if necessary. See the OnDevToolsMessage
-  // documentation for additional details on |result| contents.
+  /// Method that will be called after attempted execution of a DevTools
+  /// protocol method. |browser| is the originating browser instance.
+  /// |message_id| is the "id" value that identifies the originating method call
+  /// message. If the method succeeded |success| will be true and |result| will
+  /// be the UTF8-encoded JSON "result" dictionary value (which may be empty).
+  /// If the method failed |success| will be false and |result| will be the
+  /// UTF8-encoded JSON "error" dictionary value. |result| is only valid for the
+  /// scope of this callback and should be copied if necessary. See the
+  /// OnDevToolsMessage documentation for additional details on |result|
+  /// contents.
   ///
   /*--cef(optional_param=result)--*/
   virtual void OnDevToolsMethodResult(CefRefPtr<CefBrowser> browser,
@@ -96,12 +98,12 @@
                                       size_t result_size) {}
 
   ///
-  // Method that will be called on receipt of a DevTools protocol event.
-  // |browser| is the originating browser instance. |method| is the "method"
-  // value. |params| is the UTF8-encoded JSON "params" dictionary value (which
-  // may be empty). |params| is only valid for the scope of this callback and
-  // should be copied if necessary. See the OnDevToolsMessage documentation for
-  // additional details on |params| contents.
+  /// Method that will be called on receipt of a DevTools protocol event.
+  /// |browser| is the originating browser instance. |method| is the "method"
+  /// value. |params| is the UTF8-encoded JSON "params" dictionary value (which
+  /// may be empty). |params| is only valid for the scope of this callback and
+  /// should be copied if necessary. See the OnDevToolsMessage documentation for
+  /// additional details on |params| contents.
   ///
   /*--cef(optional_param=params)--*/
   virtual void OnDevToolsEvent(CefRefPtr<CefBrowser> browser,
@@ -110,18 +112,18 @@
                                size_t params_size) {}
 
   ///
-  // Method that will be called when the DevTools agent has attached. |browser|
-  // is the originating browser instance. This will generally occur in response
-  // to the first message sent while the agent is detached.
+  /// Method that will be called when the DevTools agent has attached. |browser|
+  /// is the originating browser instance. This will generally occur in response
+  /// to the first message sent while the agent is detached.
   ///
   /*--cef()--*/
   virtual void OnDevToolsAgentAttached(CefRefPtr<CefBrowser> browser) {}
 
   ///
-  // Method that will be called when the DevTools agent has detached. |browser|
-  // is the originating browser instance. Any method results that were pending
-  // before the agent became detached will not be delivered, and any active
-  // event subscriptions will be canceled.
+  /// Method that will be called when the DevTools agent has detached. |browser|
+  /// is the originating browser instance. Any method results that were pending
+  /// before the agent became detached will not be delivered, and any active
+  /// event subscriptions will be canceled.
   ///
   /*--cef()--*/
   virtual void OnDevToolsAgentDetached(CefRefPtr<CefBrowser> browser) {}
diff --git a/src/include/cef_dialog_handler.h b/src/include/cef_dialog_handler.h
index 3ce02e6..30fd3a1 100644
--- a/src/include/cef_dialog_handler.h
+++ b/src/include/cef_dialog_handler.h
@@ -42,33 +42,29 @@
 #include "include/cef_browser.h"
 
 ///
-// Callback interface for asynchronous continuation of file dialog requests.
+/// Callback interface for asynchronous continuation of file dialog requests.
 ///
 /*--cef(source=library)--*/
 class CefFileDialogCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Continue the file selection. |selected_accept_filter| should be the 0-based
-  // index of the value selected from the accept filters array passed to
-  // CefDialogHandler::OnFileDialog. |file_paths| should be a single value or a
-  // list of values depending on the dialog mode. An empty |file_paths| value is
-  // treated the same as calling Cancel().
+  /// Continue the file selection. |file_paths| should be a single value or a
+  /// list of values depending on the dialog mode. An empty |file_paths| value
+  /// is treated the same as calling Cancel().
   ///
-  /*--cef(capi_name=cont,index_param=selected_accept_filter,
-          optional_param=file_paths)--*/
-  virtual void Continue(int selected_accept_filter,
-                        const std::vector<CefString>& file_paths) = 0;
+  /*--cef(capi_name=cont,optional_param=file_paths)--*/
+  virtual void Continue(const std::vector<CefString>& file_paths) = 0;
 
   ///
-  // Cancel the file selection.
+  /// Cancel the file selection.
   ///
   /*--cef()--*/
   virtual void Cancel() = 0;
 };
 
 ///
-// Implement this interface to handle dialog events. The methods of this class
-// will be called on the browser process UI thread.
+/// Implement this interface to handle dialog events. The methods of this class
+/// will be called on the browser process UI thread.
 ///
 /*--cef(source=client)--*/
 class CefDialogHandler : public virtual CefBaseRefCounted {
@@ -76,28 +72,26 @@
   typedef cef_file_dialog_mode_t FileDialogMode;
 
   ///
-  // Called to run a file chooser dialog. |mode| represents the type of dialog
-  // to display. |title| to the title to be used for the dialog and may be empty
-  // to show the default title ("Open" or "Save" depending on the mode).
-  // |default_file_path| is the path with optional directory and/or file name
-  // component that should be initially selected in the dialog. |accept_filters|
-  // are used to restrict the selectable file types and may any combination of
-  // (a) valid lower-cased MIME types (e.g. "text/*" or "image/*"),
-  // (b) individual file extensions (e.g. ".txt" or ".png"), or (c) combined
-  // description and file extension delimited using "|" and ";" (e.g.
-  // "Image Types|.png;.gif;.jpg"). |selected_accept_filter| is the 0-based
-  // index of the filter that should be selected by default. To display a custom
-  // dialog return true and execute |callback| either inline or at a later time.
-  // To display the default dialog return false.
+  /// Called to run a file chooser dialog. |mode| represents the type of dialog
+  /// to display. |title| to the title to be used for the dialog and may be
+  /// empty to show the default title ("Open" or "Save" depending on the mode).
+  /// |default_file_path| is the path with optional directory and/or file name
+  /// component that should be initially selected in the dialog.
+  /// |accept_filters| are used to restrict the selectable file types and may
+  /// any combination of (a) valid lower-cased MIME types (e.g. "text/*" or
+  /// "image/*"), (b) individual file extensions (e.g. ".txt" or ".png"), or (c)
+  /// combined description and file extension delimited using "|" and ";" (e.g.
+  /// "Image Types|.png;.gif;.jpg"). To display a custom dialog return true and
+  /// execute |callback| either inline or at a later time. To display the
+  /// default dialog return false.
   ///
   /*--cef(optional_param=title,optional_param=default_file_path,
-          optional_param=accept_filters,index_param=selected_accept_filter)--*/
+          optional_param=accept_filters)--*/
   virtual bool OnFileDialog(CefRefPtr<CefBrowser> browser,
                             FileDialogMode mode,
                             const CefString& title,
                             const CefString& default_file_path,
                             const std::vector<CefString>& accept_filters,
-                            int selected_accept_filter,
                             CefRefPtr<CefFileDialogCallback> callback) {
     return false;
   }
diff --git a/src/include/cef_display_handler.h b/src/include/cef_display_handler.h
index 4fdc3c3..3b776b4 100644
--- a/src/include/cef_display_handler.h
+++ b/src/include/cef_display_handler.h
@@ -43,14 +43,14 @@
 #include "include/cef_frame.h"
 
 ///
-// Implement this interface to handle events related to browser display state.
-// The methods of this class will be called on the UI thread.
+/// Implement this interface to handle events related to browser display state.
+/// The methods of this class will be called on the UI thread.
 ///
 /*--cef(source=client)--*/
 class CefDisplayHandler : public virtual CefBaseRefCounted {
  public:
   ///
-  // Called when a frame's address has changed.
+  /// Called when a frame's address has changed.
   ///
   /*--cef()--*/
   virtual void OnAddressChange(CefRefPtr<CefBrowser> browser,
@@ -58,37 +58,41 @@
                                const CefString& url) {}
 
   ///
-  // Called when the page title changes.
+  /// Called when the page title changes.
   ///
   /*--cef(optional_param=title)--*/
   virtual void OnTitleChange(CefRefPtr<CefBrowser> browser,
                              const CefString& title) {}
 
   ///
-  // Called when the page icon changes.
+  /// Called when the page icon changes.
   ///
   /*--cef(optional_param=icon_urls)--*/
   virtual void OnFaviconURLChange(CefRefPtr<CefBrowser> browser,
                                   const std::vector<CefString>& icon_urls) {}
 
   ///
-  // Called when web content in the page has toggled fullscreen mode. If
-  // |fullscreen| is true the content will automatically be sized to fill the
-  // browser content area. If |fullscreen| is false the content will
-  // automatically return to its original size and position. The client is
-  // responsible for resizing the browser if desired.
+  /// Called when web content in the page has toggled fullscreen mode. If
+  /// |fullscreen| is true the content will automatically be sized to fill the
+  /// browser content area. If |fullscreen| is false the content will
+  /// automatically return to its original size and position. With the Alloy
+  /// runtime the client is responsible for triggering the fullscreen transition
+  /// (for example, by calling CefWindow::SetFullscreen when using Views). With
+  /// the Chrome runtime the fullscreen transition will be triggered
+  /// automatically. The CefWindowDelegate::OnWindowFullscreenTransition method
+  /// will be called during the fullscreen transition for notification purposes.
   ///
   /*--cef()--*/
   virtual void OnFullscreenModeChange(CefRefPtr<CefBrowser> browser,
                                       bool fullscreen) {}
 
   ///
-  // Called when the browser is about to display a tooltip. |text| contains the
-  // text that will be displayed in the tooltip. To handle the display of the
-  // tooltip yourself return true. Otherwise, you can optionally modify |text|
-  // and then return false to allow the browser to display the tooltip.
-  // When window rendering is disabled the application is responsible for
-  // drawing tooltips and the return value is ignored.
+  /// Called when the browser is about to display a tooltip. |text| contains the
+  /// text that will be displayed in the tooltip. To handle the display of the
+  /// tooltip yourself return true. Otherwise, you can optionally modify |text|
+  /// and then return false to allow the browser to display the tooltip.
+  /// When window rendering is disabled the application is responsible for
+  /// drawing tooltips and the return value is ignored.
   ///
   /*--cef(optional_param=text)--*/
   virtual bool OnTooltip(CefRefPtr<CefBrowser> browser, CefString& text) {
@@ -96,16 +100,16 @@
   }
 
   ///
-  // Called when the browser receives a status message. |value| contains the
-  // text that will be displayed in the status message.
+  /// Called when the browser receives a status message. |value| contains the
+  /// text that will be displayed in the status message.
   ///
   /*--cef(optional_param=value)--*/
   virtual void OnStatusMessage(CefRefPtr<CefBrowser> browser,
                                const CefString& value) {}
 
   ///
-  // Called to display a console message. Return true to stop the message from
-  // being output to the console.
+  /// Called to display a console message. Return true to stop the message from
+  /// being output to the console.
   ///
   /*--cef(optional_param=message,optional_param=source)--*/
   virtual bool OnConsoleMessage(CefRefPtr<CefBrowser> browser,
@@ -117,10 +121,10 @@
   }
 
   ///
-  // Called when auto-resize is enabled via CefBrowserHost::SetAutoResizeEnabled
-  // and the contents have auto-resized. |new_size| will be the desired size in
-  // view coordinates. Return true if the resize was handled or false for
-  // default handling.
+  /// Called when auto-resize is enabled via
+  /// CefBrowserHost::SetAutoResizeEnabled and the contents have auto-resized.
+  /// |new_size| will be the desired size in view coordinates. Return true if
+  /// the resize was handled or false for default handling.
   ///
   /*--cef()--*/
   virtual bool OnAutoResize(CefRefPtr<CefBrowser> browser,
@@ -129,12 +133,35 @@
   }
 
   ///
-  // Called when the overall page loading progress has changed. |progress|
-  // ranges from 0.0 to 1.0.
+  /// Called when the overall page loading progress has changed. |progress|
+  /// ranges from 0.0 to 1.0.
   ///
   /*--cef()--*/
   virtual void OnLoadingProgressChange(CefRefPtr<CefBrowser> browser,
                                        double progress) {}
+
+  ///
+  /// Called when the browser's cursor has changed. If |type| is CT_CUSTOM then
+  /// |custom_cursor_info| will be populated with the custom cursor information.
+  /// Return true if the cursor change was handled or false for default
+  /// handling.
+  ///
+  /*--cef()--*/
+  virtual bool OnCursorChange(CefRefPtr<CefBrowser> browser,
+                              CefCursorHandle cursor,
+                              cef_cursor_type_t type,
+                              const CefCursorInfo& custom_cursor_info) {
+    return false;
+  }
+
+  ///
+  /// Called when the browser's access to an audio and/or video source has
+  /// changed.
+  ///
+  /*--cef()--*/
+  virtual void OnMediaAccessChange(CefRefPtr<CefBrowser> browser,
+                                   bool has_video_access,
+                                   bool has_audio_access) {}
 };
 
 #endif  // CEF_INCLUDE_CEF_DISPLAY_HANDLER_H_
diff --git a/src/include/cef_dom.h b/src/include/cef_dom.h
index 382b193..8ddb8f6 100644
--- a/src/include/cef_dom.h
+++ b/src/include/cef_dom.h
@@ -45,26 +45,26 @@
 class CefDOMNode;
 
 ///
-// Interface to implement for visiting the DOM. The methods of this class will
-// be called on the render process main thread.
+/// Interface to implement for visiting the DOM. The methods of this class will
+/// be called on the render process main thread.
 ///
 /*--cef(source=client)--*/
 class CefDOMVisitor : public virtual CefBaseRefCounted {
  public:
   ///
-  // Method executed for visiting the DOM. The document object passed to this
-  // method represents a snapshot of the DOM at the time this method is
-  // executed. DOM objects are only valid for the scope of this method. Do not
-  // keep references to or attempt to access any DOM objects outside the scope
-  // of this method.
+  /// Method executed for visiting the DOM. The document object passed to this
+  /// method represents a snapshot of the DOM at the time this method is
+  /// executed. DOM objects are only valid for the scope of this method. Do not
+  /// keep references to or attempt to access any DOM objects outside the scope
+  /// of this method.
   ///
   /*--cef()--*/
   virtual void Visit(CefRefPtr<CefDOMDocument> document) = 0;
 };
 
 ///
-// Class used to represent a DOM document. The methods of this class should only
-// be called on the render process main thread thread.
+/// Class used to represent a DOM document. The methods of this class should
+/// only be called on the render process main thread thread.
 ///
 /*--cef(source=library)--*/
 class CefDOMDocument : public virtual CefBaseRefCounted {
@@ -72,206 +72,207 @@
   typedef cef_dom_document_type_t Type;
 
   ///
-  // Returns the document type.
+  /// Returns the document type.
   ///
   /*--cef(default_retval=DOM_DOCUMENT_TYPE_UNKNOWN)--*/
   virtual Type GetType() = 0;
 
   ///
-  // Returns the root document node.
+  /// Returns the root document node.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDOMNode> GetDocument() = 0;
 
   ///
-  // Returns the BODY node of an HTML document.
+  /// Returns the BODY node of an HTML document.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDOMNode> GetBody() = 0;
 
   ///
-  // Returns the HEAD node of an HTML document.
+  /// Returns the HEAD node of an HTML document.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDOMNode> GetHead() = 0;
 
   ///
-  // Returns the title of an HTML document.
+  /// Returns the title of an HTML document.
   ///
   /*--cef()--*/
   virtual CefString GetTitle() = 0;
 
   ///
-  // Returns the document element with the specified ID value.
+  /// Returns the document element with the specified ID value.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDOMNode> GetElementById(const CefString& id) = 0;
 
   ///
-  // Returns the node that currently has keyboard focus.
+  /// Returns the node that currently has keyboard focus.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDOMNode> GetFocusedNode() = 0;
 
   ///
-  // Returns true if a portion of the document is selected.
+  /// Returns true if a portion of the document is selected.
   ///
   /*--cef()--*/
   virtual bool HasSelection() = 0;
 
   ///
-  // Returns the selection offset within the start node.
+  /// Returns the selection offset within the start node.
   ///
   /*--cef()--*/
   virtual int GetSelectionStartOffset() = 0;
 
   ///
-  // Returns the selection offset within the end node.
+  /// Returns the selection offset within the end node.
   ///
   /*--cef()--*/
   virtual int GetSelectionEndOffset() = 0;
 
   ///
-  // Returns the contents of this selection as markup.
+  /// Returns the contents of this selection as markup.
   ///
   /*--cef()--*/
   virtual CefString GetSelectionAsMarkup() = 0;
 
   ///
-  // Returns the contents of this selection as text.
+  /// Returns the contents of this selection as text.
   ///
   /*--cef()--*/
   virtual CefString GetSelectionAsText() = 0;
 
   ///
-  // Returns the base URL for the document.
+  /// Returns the base URL for the document.
   ///
   /*--cef()--*/
   virtual CefString GetBaseURL() = 0;
 
   ///
-  // Returns a complete URL based on the document base URL and the specified
-  // partial URL.
+  /// Returns a complete URL based on the document base URL and the specified
+  /// partial URL.
   ///
   /*--cef()--*/
   virtual CefString GetCompleteURL(const CefString& partialURL) = 0;
 };
 
 ///
-// Class used to represent a DOM node. The methods of this class should only be
-// called on the render process main thread.
+/// Class used to represent a DOM node. The methods of this class should only be
+/// called on the render process main thread.
 ///
 /*--cef(source=library)--*/
 class CefDOMNode : public virtual CefBaseRefCounted {
  public:
   typedef std::map<CefString, CefString> AttributeMap;
   typedef cef_dom_node_type_t Type;
+  typedef cef_dom_form_control_type_t FormControlType;
 
   ///
-  // Returns the type for this node.
+  /// Returns the type for this node.
   ///
   /*--cef(default_retval=DOM_NODE_TYPE_UNSUPPORTED)--*/
   virtual Type GetType() = 0;
 
   ///
-  // Returns true if this is a text node.
+  /// Returns true if this is a text node.
   ///
   /*--cef()--*/
   virtual bool IsText() = 0;
 
   ///
-  // Returns true if this is an element node.
+  /// Returns true if this is an element node.
   ///
   /*--cef()--*/
   virtual bool IsElement() = 0;
 
   ///
-  // Returns true if this is an editable node.
+  /// Returns true if this is an editable node.
   ///
   /*--cef()--*/
   virtual bool IsEditable() = 0;
 
   ///
-  // Returns true if this is a form control element node.
+  /// Returns true if this is a form control element node.
   ///
-  /*--cef()--*/
+  /*--cef(default_retval=DOM_NODE_TYPE_UNSUPPORTED)--*/
   virtual bool IsFormControlElement() = 0;
 
   ///
-  // Returns the type of this form control element node.
+  /// Returns the type of this form control element node.
   ///
-  /*--cef()--*/
-  virtual CefString GetFormControlElementType() = 0;
+  /*--cef(default_retval=DOM_FORM_CONTROL_TYPE_UNSUPPORTED)--*/
+  virtual FormControlType GetFormControlElementType() = 0;
 
   ///
-  // Returns true if this object is pointing to the same handle as |that|
-  // object.
+  /// Returns true if this object is pointing to the same handle as |that|
+  /// object.
   ///
   /*--cef()--*/
   virtual bool IsSame(CefRefPtr<CefDOMNode> that) = 0;
 
   ///
-  // Returns the name of this node.
+  /// Returns the name of this node.
   ///
   /*--cef()--*/
   virtual CefString GetName() = 0;
 
   ///
-  // Returns the value of this node.
+  /// Returns the value of this node.
   ///
   /*--cef()--*/
   virtual CefString GetValue() = 0;
 
   ///
-  // Set the value of this node. Returns true on success.
+  /// Set the value of this node. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool SetValue(const CefString& value) = 0;
 
   ///
-  // Returns the contents of this node as markup.
+  /// Returns the contents of this node as markup.
   ///
   /*--cef()--*/
   virtual CefString GetAsMarkup() = 0;
 
   ///
-  // Returns the document associated with this node.
+  /// Returns the document associated with this node.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDOMDocument> GetDocument() = 0;
 
   ///
-  // Returns the parent node.
+  /// Returns the parent node.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDOMNode> GetParent() = 0;
 
   ///
-  // Returns the previous sibling node.
+  /// Returns the previous sibling node.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDOMNode> GetPreviousSibling() = 0;
 
   ///
-  // Returns the next sibling node.
+  /// Returns the next sibling node.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDOMNode> GetNextSibling() = 0;
 
   ///
-  // Returns true if this node has child nodes.
+  /// Returns true if this node has child nodes.
   ///
   /*--cef()--*/
   virtual bool HasChildren() = 0;
 
   ///
-  // Return the first child node.
+  /// Return the first child node.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDOMNode> GetFirstChild() = 0;
 
   ///
-  // Returns the last child node.
+  /// Returns the last child node.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDOMNode> GetLastChild() = 0;
@@ -279,51 +280,52 @@
   // The following methods are valid only for element nodes.
 
   ///
-  // Returns the tag name of this element.
+  /// Returns the tag name of this element.
   ///
   /*--cef()--*/
   virtual CefString GetElementTagName() = 0;
 
   ///
-  // Returns true if this element has attributes.
+  /// Returns true if this element has attributes.
   ///
   /*--cef()--*/
   virtual bool HasElementAttributes() = 0;
 
   ///
-  // Returns true if this element has an attribute named |attrName|.
+  /// Returns true if this element has an attribute named |attrName|.
   ///
   /*--cef()--*/
   virtual bool HasElementAttribute(const CefString& attrName) = 0;
 
   ///
-  // Returns the element attribute named |attrName|.
+  /// Returns the element attribute named |attrName|.
   ///
   /*--cef()--*/
   virtual CefString GetElementAttribute(const CefString& attrName) = 0;
 
   ///
-  // Returns a map of all element attributes.
+  /// Returns a map of all element attributes.
   ///
   /*--cef()--*/
   virtual void GetElementAttributes(AttributeMap& attrMap) = 0;
 
   ///
-  // Set the value for the element attribute named |attrName|. Returns true on
-  // success.
+  /// Set the value for the element attribute named |attrName|. Returns true on
+  /// success.
   ///
   /*--cef()--*/
   virtual bool SetElementAttribute(const CefString& attrName,
                                    const CefString& value) = 0;
 
   ///
-  // Returns the inner text of the element.
+  /// Returns the inner text of the element.
   ///
   /*--cef()--*/
   virtual CefString GetElementInnerText() = 0;
 
   ///
-  // Returns the bounds of the element.
+  /// Returns the bounds of the element in device pixels. Use
+  /// "window.devicePixelRatio" to convert to/from CSS pixels.
   ///
   /*--cef()--*/
   virtual CefRect GetElementBounds() = 0;
diff --git a/src/include/cef_download_handler.h b/src/include/cef_download_handler.h
index dfaeba5..de911b6 100644
--- a/src/include/cef_download_handler.h
+++ b/src/include/cef_download_handler.h
@@ -43,59 +43,73 @@
 #include "include/cef_download_item.h"
 
 ///
-// Callback interface used to asynchronously continue a download.
+/// Callback interface used to asynchronously continue a download.
 ///
 /*--cef(source=library)--*/
 class CefBeforeDownloadCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Call to continue the download. Set |download_path| to the full file path
-  // for the download including the file name or leave blank to use the
-  // suggested name and the default temp directory. Set |show_dialog| to true
-  // if you do wish to show the default "Save As" dialog.
+  /// Call to continue the download. Set |download_path| to the full file path
+  /// for the download including the file name or leave blank to use the
+  /// suggested name and the default temp directory. Set |show_dialog| to true
+  /// if you do wish to show the default "Save As" dialog.
   ///
   /*--cef(capi_name=cont,optional_param=download_path)--*/
   virtual void Continue(const CefString& download_path, bool show_dialog) = 0;
 };
 
 ///
-// Callback interface used to asynchronously cancel a download.
+/// Callback interface used to asynchronously cancel a download.
 ///
 /*--cef(source=library)--*/
 class CefDownloadItemCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Call to cancel the download.
+  /// Call to cancel the download.
   ///
   /*--cef()--*/
   virtual void Cancel() = 0;
 
   ///
-  // Call to pause the download.
+  /// Call to pause the download.
   ///
   /*--cef()--*/
   virtual void Pause() = 0;
 
   ///
-  // Call to resume the download.
+  /// Call to resume the download.
   ///
   /*--cef()--*/
   virtual void Resume() = 0;
 };
 
 ///
-// Class used to handle file downloads. The methods of this class will called
-// on the browser process UI thread.
+/// Class used to handle file downloads. The methods of this class will called
+/// on the browser process UI thread.
 ///
 /*--cef(source=client)--*/
 class CefDownloadHandler : public virtual CefBaseRefCounted {
  public:
   ///
-  // Called before a download begins. |suggested_name| is the suggested name for
-  // the download file. By default the download will be canceled. Execute
-  // |callback| either asynchronously or in this method to continue the download
-  // if desired. Do not keep a reference to |download_item| outside of this
-  // method.
+  /// Called before a download begins in response to a user-initiated action
+  /// (e.g. alt + link click or link click that returns a `Content-Disposition:
+  /// attachment` response from the server). |url| is the target download URL
+  /// and |request_method| is the target method (GET, POST, etc). Return true to
+  /// proceed with the download or false to cancel the download.
+  ///
+  /*--cef()--*/
+  virtual bool CanDownload(CefRefPtr<CefBrowser> browser,
+                           const CefString& url,
+                           const CefString& request_method) {
+    return true;
+  }
+
+  ///
+  /// Called before a download begins. |suggested_name| is the suggested name
+  /// for the download file. By default the download will be canceled. Execute
+  /// |callback| either asynchronously or in this method to continue the
+  /// download if desired. Do not keep a reference to |download_item| outside of
+  /// this method.
   ///
   /*--cef()--*/
   virtual void OnBeforeDownload(
@@ -105,11 +119,11 @@
       CefRefPtr<CefBeforeDownloadCallback> callback) = 0;
 
   ///
-  // Called when a download's status or progress information has been updated.
-  // This may be called multiple times before and after OnBeforeDownload().
-  // Execute |callback| either asynchronously or in this method to cancel the
-  // download if desired. Do not keep a reference to |download_item| outside of
-  // this method.
+  /// Called when a download's status or progress information has been updated.
+  /// This may be called multiple times before and after OnBeforeDownload().
+  /// Execute |callback| either asynchronously or in this method to cancel the
+  /// download if desired. Do not keep a reference to |download_item| outside of
+  /// this method.
   ///
   /*--cef()--*/
   virtual void OnDownloadUpdated(CefRefPtr<CefBrowser> browser,
diff --git a/src/include/cef_download_item.h b/src/include/cef_download_item.h
index 930f53b..bb4be2b 100644
--- a/src/include/cef_download_item.h
+++ b/src/include/cef_download_item.h
@@ -41,111 +41,123 @@
 #include "include/cef_base.h"
 
 ///
-// Class used to represent a download item.
+/// Class used to represent a download item.
 ///
 /*--cef(source=library)--*/
 class CefDownloadItem : public virtual CefBaseRefCounted {
  public:
   ///
-  // Returns true if this object is valid. Do not call any other methods if this
-  // function returns false.
+  /// Returns true if this object is valid. Do not call any other methods if
+  /// this function returns false.
   ///
   /*--cef()--*/
   virtual bool IsValid() = 0;
 
   ///
-  // Returns true if the download is in progress.
+  /// Returns true if the download is in progress.
   ///
   /*--cef()--*/
   virtual bool IsInProgress() = 0;
 
   ///
-  // Returns true if the download is complete.
+  /// Returns true if the download is complete.
   ///
   /*--cef()--*/
   virtual bool IsComplete() = 0;
 
   ///
-  // Returns true if the download has been canceled or interrupted.
+  /// Returns true if the download has been canceled.
   ///
   /*--cef()--*/
   virtual bool IsCanceled() = 0;
 
   ///
-  // Returns a simple speed estimate in bytes/s.
+  /// Returns true if the download has been interrupted.
   ///
   /*--cef()--*/
-  virtual int64 GetCurrentSpeed() = 0;
+  virtual bool IsInterrupted() = 0;
 
   ///
-  // Returns the rough percent complete or -1 if the receive total size is
-  // unknown.
+  /// Returns the most recent interrupt reason.
+  ///
+  /*--cef(default_retval=CEF_DOWNLOAD_INTERRUPT_REASON_NONE)--*/
+  virtual cef_download_interrupt_reason_t GetInterruptReason() = 0;
+
+  ///
+  /// Returns a simple speed estimate in bytes/s.
+  ///
+  /*--cef()--*/
+  virtual int64_t GetCurrentSpeed() = 0;
+
+  ///
+  /// Returns the rough percent complete or -1 if the receive total size is
+  /// unknown.
   ///
   /*--cef()--*/
   virtual int GetPercentComplete() = 0;
 
   ///
-  // Returns the total number of bytes.
+  /// Returns the total number of bytes.
   ///
   /*--cef()--*/
-  virtual int64 GetTotalBytes() = 0;
+  virtual int64_t GetTotalBytes() = 0;
 
   ///
-  // Returns the number of received bytes.
+  /// Returns the number of received bytes.
   ///
   /*--cef()--*/
-  virtual int64 GetReceivedBytes() = 0;
+  virtual int64_t GetReceivedBytes() = 0;
 
   ///
-  // Returns the time that the download started.
+  /// Returns the time that the download started.
   ///
   /*--cef()--*/
-  virtual CefTime GetStartTime() = 0;
+  virtual CefBaseTime GetStartTime() = 0;
 
   ///
-  // Returns the time that the download ended.
+  /// Returns the time that the download ended.
   ///
   /*--cef()--*/
-  virtual CefTime GetEndTime() = 0;
+  virtual CefBaseTime GetEndTime() = 0;
 
   ///
-  // Returns the full path to the downloaded or downloading file.
+  /// Returns the full path to the downloaded or downloading file.
   ///
   /*--cef()--*/
   virtual CefString GetFullPath() = 0;
 
   ///
-  // Returns the unique identifier for this download.
+  /// Returns the unique identifier for this download.
   ///
   /*--cef()--*/
-  virtual uint32 GetId() = 0;
+  virtual uint32_t GetId() = 0;
 
   ///
-  // Returns the URL.
+  /// Returns the URL.
   ///
   /*--cef()--*/
   virtual CefString GetURL() = 0;
 
   ///
-  // Returns the original URL before any redirections.
+  /// Returns the original URL before any redirections.
   ///
   /*--cef()--*/
   virtual CefString GetOriginalUrl() = 0;
 
   ///
-  // Returns the suggested file name.
+  /// Returns the suggested file name.
   ///
   /*--cef()--*/
   virtual CefString GetSuggestedFileName() = 0;
 
   ///
-  // Returns the content disposition.
+  /// Returns the content disposition.
   ///
   /*--cef()--*/
   virtual CefString GetContentDisposition() = 0;
 
   ///
-  // Returns the mime type.
+  /// Returns the mime type.
   ///
   /*--cef()--*/
   virtual CefString GetMimeType() = 0;
diff --git a/src/include/cef_drag_data.h b/src/include/cef_drag_data.h
index 35661f8..735a64c 100644
--- a/src/include/cef_drag_data.h
+++ b/src/include/cef_drag_data.h
@@ -44,173 +44,186 @@
 #include "include/cef_stream.h"
 
 ///
-// Class used to represent drag data. The methods of this class may be called
-// on any thread.
+/// Class used to represent drag data. The methods of this class may be called
+/// on any thread.
 ///
 /*--cef(source=library)--*/
 class CefDragData : public virtual CefBaseRefCounted {
  public:
   ///
-  // Create a new CefDragData object.
+  /// Create a new CefDragData object.
   ///
   /*--cef()--*/
   static CefRefPtr<CefDragData> Create();
 
   ///
-  // Returns a copy of the current object.
+  /// Returns a copy of the current object.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDragData> Clone() = 0;
 
   ///
-  // Returns true if this object is read-only.
+  /// Returns true if this object is read-only.
   ///
   /*--cef()--*/
   virtual bool IsReadOnly() = 0;
 
   ///
-  // Returns true if the drag data is a link.
+  /// Returns true if the drag data is a link.
   ///
   /*--cef()--*/
   virtual bool IsLink() = 0;
 
   ///
-  // Returns true if the drag data is a text or html fragment.
+  /// Returns true if the drag data is a text or html fragment.
   ///
   /*--cef()--*/
   virtual bool IsFragment() = 0;
 
   ///
-  // Returns true if the drag data is a file.
+  /// Returns true if the drag data is a file.
   ///
   /*--cef()--*/
   virtual bool IsFile() = 0;
 
   ///
-  // Return the link URL that is being dragged.
+  /// Return the link URL that is being dragged.
   ///
   /*--cef()--*/
   virtual CefString GetLinkURL() = 0;
 
   ///
-  // Return the title associated with the link being dragged.
+  /// Return the title associated with the link being dragged.
   ///
   /*--cef()--*/
   virtual CefString GetLinkTitle() = 0;
 
   ///
-  // Return the metadata, if any, associated with the link being dragged.
+  /// Return the metadata, if any, associated with the link being dragged.
   ///
   /*--cef()--*/
   virtual CefString GetLinkMetadata() = 0;
 
   ///
-  // Return the plain text fragment that is being dragged.
+  /// Return the plain text fragment that is being dragged.
   ///
   /*--cef()--*/
   virtual CefString GetFragmentText() = 0;
 
   ///
-  // Return the text/html fragment that is being dragged.
+  /// Return the text/html fragment that is being dragged.
   ///
   /*--cef()--*/
   virtual CefString GetFragmentHtml() = 0;
 
   ///
-  // Return the base URL that the fragment came from. This value is used for
-  // resolving relative URLs and may be empty.
+  /// Return the base URL that the fragment came from. This value is used for
+  /// resolving relative URLs and may be empty.
   ///
   /*--cef()--*/
   virtual CefString GetFragmentBaseURL() = 0;
 
   ///
-  // Return the name of the file being dragged out of the browser window.
+  /// Return the name of the file being dragged out of the browser window.
   ///
   /*--cef()--*/
   virtual CefString GetFileName() = 0;
 
   ///
-  // Write the contents of the file being dragged out of the web view into
-  // |writer|. Returns the number of bytes sent to |writer|. If |writer| is
-  // NULL this method will return the size of the file contents in bytes.
-  // Call GetFileName() to get a suggested name for the file.
+  /// Write the contents of the file being dragged out of the web view into
+  /// |writer|. Returns the number of bytes sent to |writer|. If |writer| is
+  /// NULL this method will return the size of the file contents in bytes.
+  /// Call GetFileName() to get a suggested name for the file.
   ///
   /*--cef(optional_param=writer)--*/
   virtual size_t GetFileContents(CefRefPtr<CefStreamWriter> writer) = 0;
 
   ///
-  // Retrieve the list of file names that are being dragged into the browser
-  // window.
+  /// Retrieve the list of file names that are being dragged into the browser
+  /// window.
   ///
   /*--cef()--*/
   virtual bool GetFileNames(std::vector<CefString>& names) = 0;
 
   ///
-  // Set the link URL that is being dragged.
+  /// Retrieve the list of file paths that are being dragged into the browser
+  /// window.
+  ///
+  /*--cef()--*/
+  virtual bool GetFilePaths(std::vector<CefString>& paths) = 0;
+
+  ///
+  /// Set the link URL that is being dragged.
   ///
   /*--cef(optional_param=url)--*/
   virtual void SetLinkURL(const CefString& url) = 0;
 
   ///
-  // Set the title associated with the link being dragged.
+  /// Set the title associated with the link being dragged.
   ///
   /*--cef(optional_param=title)--*/
   virtual void SetLinkTitle(const CefString& title) = 0;
 
   ///
-  // Set the metadata associated with the link being dragged.
+  /// Set the metadata associated with the link being dragged.
   ///
   /*--cef(optional_param=data)--*/
   virtual void SetLinkMetadata(const CefString& data) = 0;
 
   ///
-  // Set the plain text fragment that is being dragged.
+  /// Set the plain text fragment that is being dragged.
   ///
   /*--cef(optional_param=text)--*/
   virtual void SetFragmentText(const CefString& text) = 0;
 
   ///
-  // Set the text/html fragment that is being dragged.
+  /// Set the text/html fragment that is being dragged.
   ///
   /*--cef(optional_param=html)--*/
   virtual void SetFragmentHtml(const CefString& html) = 0;
 
   ///
-  // Set the base URL that the fragment came from.
+  /// Set the base URL that the fragment came from.
   ///
   /*--cef(optional_param=base_url)--*/
   virtual void SetFragmentBaseURL(const CefString& base_url) = 0;
 
   ///
-  // Reset the file contents. You should do this before calling
-  // CefBrowserHost::DragTargetDragEnter as the web view does not allow us to
-  // drag in this kind of data.
+  /// Reset the file contents. You should do this before calling
+  /// CefBrowserHost::DragTargetDragEnter as the web view does not allow us to
+  /// drag in this kind of data.
   ///
   /*--cef()--*/
   virtual void ResetFileContents() = 0;
 
   ///
-  // Add a file that is being dragged into the webview.
+  /// Add a file that is being dragged into the webview.
   ///
   /*--cef(optional_param=display_name)--*/
   virtual void AddFile(const CefString& path,
                        const CefString& display_name) = 0;
 
   ///
-  // Get the image representation of drag data. May return NULL if no image
-  // representation is available.
+  /// Clear list of filenames.
+  ///
+  /*--cef()--*/
+  virtual void ClearFilenames() = 0;
+
+  ///
+  /// Get the image representation of drag data. May return NULL if no image
+  /// representation is available.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefImage> GetImage() = 0;
 
   ///
-  // Get the image hotspot (drag start location relative to image dimensions).
+  /// Get the image hotspot (drag start location relative to image dimensions).
   ///
   /*--cef()--*/
   virtual CefPoint GetImageHotspot() = 0;
 
   ///
-  // Returns true if an image representation of drag data is available.
+  /// Returns true if an image representation of drag data is available.
   ///
   /*--cef()--*/
   virtual bool HasImage() = 0;
diff --git a/src/include/cef_drag_handler.h b/src/include/cef_drag_handler.h
index dfa226e..cd354d7 100644
--- a/src/include/cef_drag_handler.h
+++ b/src/include/cef_drag_handler.h
@@ -44,8 +44,8 @@
 #include "include/cef_frame.h"
 
 ///
-// Implement this interface to handle events related to dragging. The methods of
-// this class will be called on the UI thread.
+/// Implement this interface to handle events related to dragging. The methods
+/// of this class will be called on the UI thread.
 ///
 /*--cef(source=client)--*/
 class CefDragHandler : public virtual CefBaseRefCounted {
@@ -53,10 +53,10 @@
   typedef cef_drag_operations_mask_t DragOperationsMask;
 
   ///
-  // Called when an external drag event enters the browser window. |dragData|
-  // contains the drag event data and |mask| represents the type of drag
-  // operation. Return false for default drag handling behavior or true to
-  // cancel the drag event.
+  /// Called when an external drag event enters the browser window. |dragData|
+  /// contains the drag event data and |mask| represents the type of drag
+  /// operation. Return false for default drag handling behavior or true to
+  /// cancel the drag event.
   ///
   /*--cef()--*/
   virtual bool OnDragEnter(CefRefPtr<CefBrowser> browser,
@@ -66,11 +66,11 @@
   }
 
   ///
-  // Called whenever draggable regions for the browser window change. These can
-  // be specified using the '-webkit-app-region: drag/no-drag' CSS-property. If
-  // draggable regions are never defined in a document this method will also
-  // never be called. If the last draggable region is removed from a document
-  // this method will be called with an empty vector.
+  /// Called whenever draggable regions for the browser window change. These can
+  /// be specified using the '-webkit-app-region: drag/no-drag' CSS-property. If
+  /// draggable regions are never defined in a document this method will also
+  /// never be called. If the last draggable region is removed from a document
+  /// this method will be called with an empty vector.
   ///
   /*--cef()--*/
   virtual void OnDraggableRegionsChanged(
diff --git a/src/include/cef_extension.h b/src/include/cef_extension.h
index c34d013..5d94192 100644
--- a/src/include/cef_extension.h
+++ b/src/include/cef_extension.h
@@ -45,70 +45,71 @@
 class CefRequestContext;
 
 ///
-// Object representing an extension. Methods may be called on any thread unless
-// otherwise indicated.
+/// Object representing an extension. Methods may be called on any thread unless
+/// otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefExtension : public CefBaseRefCounted {
  public:
   ///
-  // Returns the unique extension identifier. This is calculated based on the
-  // extension public key, if available, or on the extension path. See
-  // https://developer.chrome.com/extensions/manifest/key for details.
+  /// Returns the unique extension identifier. This is calculated based on the
+  /// extension public key, if available, or on the extension path. See
+  /// https://developer.chrome.com/extensions/manifest/key for details.
   ///
   /*--cef()--*/
   virtual CefString GetIdentifier() = 0;
 
   ///
-  // Returns the absolute path to the extension directory on disk. This value
-  // will be prefixed with PK_DIR_RESOURCES if a relative path was passed to
-  // CefRequestContext::LoadExtension.
+  /// Returns the absolute path to the extension directory on disk. This value
+  /// will be prefixed with PK_DIR_RESOURCES if a relative path was passed to
+  /// CefRequestContext::LoadExtension.
   ///
   /*--cef()--*/
   virtual CefString GetPath() = 0;
 
   ///
-  // Returns the extension manifest contents as a CefDictionaryValue object. See
-  // https://developer.chrome.com/extensions/manifest for details.
+  /// Returns the extension manifest contents as a CefDictionaryValue object.
+  /// See https://developer.chrome.com/extensions/manifest for details.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDictionaryValue> GetManifest() = 0;
 
   ///
-  // Returns true if this object is the same extension as |that| object.
-  // Extensions are considered the same if identifier, path and loader context
-  // match.
+  /// Returns true if this object is the same extension as |that| object.
+  /// Extensions are considered the same if identifier, path and loader context
+  /// match.
   ///
   /*--cef()--*/
   virtual bool IsSame(CefRefPtr<CefExtension> that) = 0;
 
   ///
-  // Returns the handler for this extension. Will return NULL for internal
-  // extensions or if no handler was passed to CefRequestContext::LoadExtension.
+  /// Returns the handler for this extension. Will return NULL for internal
+  /// extensions or if no handler was passed to
+  /// CefRequestContext::LoadExtension.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefExtensionHandler> GetHandler() = 0;
 
   ///
-  // Returns the request context that loaded this extension. Will return NULL
-  // for internal extensions or if the extension has been unloaded. See the
-  // CefRequestContext::LoadExtension documentation for more information about
-  // loader contexts. Must be called on the browser process UI thread.
+  /// Returns the request context that loaded this extension. Will return NULL
+  /// for internal extensions or if the extension has been unloaded. See the
+  /// CefRequestContext::LoadExtension documentation for more information about
+  /// loader contexts. Must be called on the browser process UI thread.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefRequestContext> GetLoaderContext() = 0;
 
   ///
-  // Returns true if this extension is currently loaded. Must be called on the
-  // browser process UI thread.
+  /// Returns true if this extension is currently loaded. Must be called on the
+  /// browser process UI thread.
   ///
   /*--cef()--*/
   virtual bool IsLoaded() = 0;
 
   ///
-  // Unload this extension if it is not an internal extension and is currently
-  // loaded. Will result in a call to CefExtensionHandler::OnExtensionUnloaded
-  // on success.
+  /// Unload this extension if it is not an internal extension and is currently
+  /// loaded. Will result in a call to CefExtensionHandler::OnExtensionUnloaded
+  /// on success.
   ///
   /*--cef()--*/
   virtual void Unload() = 0;
diff --git a/src/include/cef_extension_handler.h b/src/include/cef_extension_handler.h
index 67dda33..4b34fbc 100644
--- a/src/include/cef_extension_handler.h
+++ b/src/include/cef_extension_handler.h
@@ -46,67 +46,67 @@
 class CefClient;
 
 ///
-// Callback interface used for asynchronous continuation of
-// CefExtensionHandler::GetExtensionResource.
+/// Callback interface used for asynchronous continuation of
+/// CefExtensionHandler::GetExtensionResource.
 ///
 /*--cef(source=library)--*/
 class CefGetExtensionResourceCallback : public CefBaseRefCounted {
  public:
   ///
-  // Continue the request. Read the resource contents from |stream|.
+  /// Continue the request. Read the resource contents from |stream|.
   ///
   /*--cef(capi_name=cont,optional_param=stream)--*/
   virtual void Continue(CefRefPtr<CefStreamReader> stream) = 0;
 
   ///
-  // Cancel the request.
+  /// Cancel the request.
   ///
   /*--cef()--*/
   virtual void Cancel() = 0;
 };
 
 ///
-// Implement this interface to handle events related to browser extensions.
-// The methods of this class will be called on the UI thread. See
-// CefRequestContext::LoadExtension for information about extension loading.
+/// Implement this interface to handle events related to browser extensions.
+/// The methods of this class will be called on the UI thread. See
+/// CefRequestContext::LoadExtension for information about extension loading.
 ///
 /*--cef(source=client)--*/
 class CefExtensionHandler : public virtual CefBaseRefCounted {
  public:
   ///
-  // Called if the CefRequestContext::LoadExtension request fails. |result| will
-  // be the error code.
+  /// Called if the CefRequestContext::LoadExtension request fails. |result|
+  /// will be the error code.
   ///
   /*--cef()--*/
   virtual void OnExtensionLoadFailed(cef_errorcode_t result) {}
 
   ///
-  // Called if the CefRequestContext::LoadExtension request succeeds.
-  // |extension| is the loaded extension.
+  /// Called if the CefRequestContext::LoadExtension request succeeds.
+  /// |extension| is the loaded extension.
   ///
   /*--cef()--*/
   virtual void OnExtensionLoaded(CefRefPtr<CefExtension> extension) {}
 
   ///
-  // Called after the CefExtension::Unload request has completed.
+  /// Called after the CefExtension::Unload request has completed.
   ///
   /*--cef()--*/
   virtual void OnExtensionUnloaded(CefRefPtr<CefExtension> extension) {}
 
   ///
-  // Called when an extension needs a browser to host a background script
-  // specified via the "background" manifest key. The browser will have no
-  // visible window and cannot be displayed. |extension| is the extension that
-  // is loading the background script. |url| is an internally generated
-  // reference to an HTML page that will be used to load the background script
-  // via a <script> src attribute. To allow creation of the browser optionally
-  // modify |client| and |settings| and return false. To cancel creation of the
-  // browser (and consequently cancel load of the background script) return
-  // true. Successful creation will be indicated by a call to
-  // CefLifeSpanHandler::OnAfterCreated, and CefBrowserHost::IsBackgroundHost
-  // will return true for the resulting browser. See
-  // https://developer.chrome.com/extensions/event_pages for more information
-  // about extension background script usage.
+  /// Called when an extension needs a browser to host a background script
+  /// specified via the "background" manifest key. The browser will have no
+  /// visible window and cannot be displayed. |extension| is the extension that
+  /// is loading the background script. |url| is an internally generated
+  /// reference to an HTML page that will be used to load the background script
+  /// via a "<script>" src attribute. To allow creation of the browser
+  /// optionally modify |client| and |settings| and return false. To cancel
+  /// creation of the browser (and consequently cancel load of the background
+  /// script) return true. Successful creation will be indicated by a call to
+  /// CefLifeSpanHandler::OnAfterCreated, and CefBrowserHost::IsBackgroundHost
+  /// will return true for the resulting browser. See
+  /// https://developer.chrome.com/extensions/event_pages for more information
+  /// about extension background script usage.
   ///
   /*--cef()--*/
   virtual bool OnBeforeBackgroundBrowser(CefRefPtr<CefExtension> extension,
@@ -117,18 +117,19 @@
   }
 
   ///
-  // Called when an extension API (e.g. chrome.tabs.create) requests creation of
-  // a new browser. |extension| and |browser| are the source of the API call.
-  // |active_browser| may optionally be specified via the windowId property or
-  // returned via the GetActiveBrowser() callback and provides the default
-  // |client| and |settings| values for the new browser. |index| is the position
-  // value optionally specified via the index property. |url| is the URL that
-  // will be loaded in the browser. |active| is true if the new browser should
-  // be active when opened.  To allow creation of the browser optionally modify
-  // |windowInfo|, |client| and |settings| and return false. To cancel creation
-  // of the browser return true. Successful creation will be indicated by a call
-  // to CefLifeSpanHandler::OnAfterCreated. Any modifications to |windowInfo|
-  // will be ignored if |active_browser| is wrapped in a CefBrowserView.
+  /// Called when an extension API (e.g. chrome.tabs.create) requests creation
+  /// of a new browser. |extension| and |browser| are the source of the API
+  /// call. |active_browser| may optionally be specified via the windowId
+  /// property or returned via the GetActiveBrowser() callback and provides the
+  /// default |client| and |settings| values for the new browser. |index| is the
+  /// position value optionally specified via the index property. |url| is the
+  /// URL that will be loaded in the browser. |active| is true if the new
+  /// browser should be active when opened.  To allow creation of the browser
+  /// optionally modify |windowInfo|, |client| and |settings| and return false.
+  /// To cancel creation of the browser return true. Successful creation will be
+  /// indicated by a call to CefLifeSpanHandler::OnAfterCreated. Any
+  /// modifications to |windowInfo| will be ignored if |active_browser| is
+  /// wrapped in a CefBrowserView.
   ///
   /*--cef()--*/
   virtual bool OnBeforeBrowser(CefRefPtr<CefExtension> extension,
@@ -144,13 +145,13 @@
   }
 
   ///
-  // Called when no tabId is specified to an extension API call that accepts a
-  // tabId parameter (e.g. chrome.tabs.*). |extension| and |browser| are the
-  // source of the API call. Return the browser that will be acted on by the API
-  // call or return NULL to act on |browser|. The returned browser must share
-  // the same CefRequestContext as |browser|. Incognito browsers should not be
-  // considered unless the source extension has incognito access enabled, in
-  // which case |include_incognito| will be true.
+  /// Called when no tabId is specified to an extension API call that accepts a
+  /// tabId parameter (e.g. chrome.tabs.*). |extension| and |browser| are the
+  /// source of the API call. Return the browser that will be acted on by the
+  /// API call or return NULL to act on |browser|. The returned browser must
+  /// share the same CefRequestContext as |browser|. Incognito browsers should
+  /// not be considered unless the source extension has incognito access
+  /// enabled, in which case |include_incognito| will be true.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBrowser> GetActiveBrowser(
@@ -161,12 +162,12 @@
   }
 
   ///
-  // Called when the tabId associated with |target_browser| is specified to an
-  // extension API call that accepts a tabId parameter (e.g. chrome.tabs.*).
-  // |extension| and |browser| are the source of the API call. Return true
-  // to allow access of false to deny access. Access to incognito browsers
-  // should not be allowed unless the source extension has incognito access
-  // enabled, in which case |include_incognito| will be true.
+  /// Called when the tabId associated with |target_browser| is specified to an
+  /// extension API call that accepts a tabId parameter (e.g. chrome.tabs.*).
+  /// |extension| and |browser| are the source of the API call. Return true
+  /// to allow access of false to deny access. Access to incognito browsers
+  /// should not be allowed unless the source extension has incognito access
+  /// enabled, in which case |include_incognito| will be true.
   ///
   /*--cef()--*/
   virtual bool CanAccessBrowser(CefRefPtr<CefExtension> extension,
@@ -177,14 +178,14 @@
   }
 
   ///
-  // Called to retrieve an extension resource that would normally be loaded from
-  // disk (e.g. if a file parameter is specified to chrome.tabs.executeScript).
-  // |extension| and |browser| are the source of the resource request. |file| is
-  // the requested relative file path. To handle the resource request return
-  // true and execute |callback| either synchronously or asynchronously. For the
-  // default behavior which reads the resource from the extension directory on
-  // disk return false. Localization substitutions will not be applied to
-  // resources handled via this method.
+  /// Called to retrieve an extension resource that would normally be loaded
+  /// from disk (e.g. if a file parameter is specified to
+  /// chrome.tabs.executeScript). |extension| and |browser| are the source of
+  /// the resource request. |file| is the requested relative file path. To
+  /// handle the resource request return true and execute |callback| either
+  /// synchronously or asynchronously. For the default behavior which reads the
+  /// resource from the extension directory on disk return false. Localization
+  /// substitutions will not be applied to resources handled via this method.
   ///
   /*--cef()--*/
   virtual bool GetExtensionResource(
diff --git a/src/include/cef_file_util.h b/src/include/cef_file_util.h
index 8dd1ff6..838bdc1 100644
--- a/src/include/cef_file_util.h
+++ b/src/include/cef_file_util.h
@@ -42,43 +42,43 @@
 #include "include/cef_base.h"
 
 ///
-// Creates a directory and all parent directories if they don't already exist.
-// Returns true on successful creation or if the directory already exists. The
-// directory is only readable by the current user. Calling this function on the
-// browser process UI or IO threads is not allowed.
+/// Creates a directory and all parent directories if they don't already exist.
+/// Returns true on successful creation or if the directory already exists. The
+/// directory is only readable by the current user. Calling this function on the
+/// browser process UI or IO threads is not allowed.
 ///
 /*--cef()--*/
 bool CefCreateDirectory(const CefString& full_path);
 
 ///
-// Get the temporary directory provided by the system.
-//
-// WARNING: In general, you should use the temp directory variants below instead
-// of this function. Those variants will ensure that the proper permissions are
-// set so that other users on the system can't edit them while they're open
-// (which could lead to security issues).
+/// Get the temporary directory provided by the system.
+///
+/// WARNING: In general, you should use the temp directory variants below
+/// instead of this function. Those variants will ensure that the proper
+/// permissions are set so that other users on the system can't edit them while
+/// they're open (which could lead to security issues).
 ///
 /*--cef()--*/
 bool CefGetTempDirectory(CefString& temp_dir);
 
 ///
-// Creates a new directory. On Windows if |prefix| is provided the new directory
-// name is in the format of "prefixyyyy". Returns true on success and sets
-// |new_temp_path| to the full path of the directory that was created. The
-// directory is only readable by the current user. Calling this function on the
-// browser process UI or IO threads is not allowed.
+/// Creates a new directory. On Windows if |prefix| is provided the new
+/// directory name is in the format of "prefixyyyy". Returns true on success and
+/// sets |new_temp_path| to the full path of the directory that was created. The
+/// directory is only readable by the current user. Calling this function on the
+/// browser process UI or IO threads is not allowed.
 ///
 /*--cef(optional_param=prefix)--*/
 bool CefCreateNewTempDirectory(const CefString& prefix,
                                CefString& new_temp_path);
 
 ///
-// Creates a directory within another directory. Extra characters will be
-// appended to |prefix| to ensure that the new directory does not have the same
-// name as an existing directory. Returns true on success and sets |new_dir| to
-// the full path of the directory that was created. The directory is only
-// readable by the current user. Calling this function on the browser process
-// UI or IO threads is not allowed.
+/// Creates a directory within another directory. Extra characters will be
+/// appended to |prefix| to ensure that the new directory does not have the same
+/// name as an existing directory. Returns true on success and sets |new_dir| to
+/// the full path of the directory that was created. The directory is only
+/// readable by the current user. Calling this function on the browser process
+/// UI or IO threads is not allowed.
 ///
 /*--cef(optional_param=prefix)--*/
 bool CefCreateTempDirectoryInDirectory(const CefString& base_dir,
@@ -86,29 +86,29 @@
                                        CefString& new_dir);
 
 ///
-// Returns true if the given path exists and is a directory. Calling this
-// function on the browser process UI or IO threads is not allowed.
+/// Returns true if the given path exists and is a directory. Calling this
+/// function on the browser process UI or IO threads is not allowed.
 ///
 /*--cef()--*/
 bool CefDirectoryExists(const CefString& path);
 
 ///
-// Deletes the given path whether it's a file or a directory. If |path| is a
-// directory all contents will be deleted.  If |recursive| is true any sub-
-// directories and their contents will also be deleted (equivalent to executing
-// "rm -rf", so use with caution). On POSIX environments if |path| is a symbolic
-// link then only the symlink will be deleted. Returns true on successful
-// deletion or if |path| does not exist. Calling this function on the browser
-// process UI or IO threads is not allowed.
+/// Deletes the given path whether it's a file or a directory. If |path| is a
+/// directory all contents will be deleted.  If |recursive| is true any sub-
+/// directories and their contents will also be deleted (equivalent to executing
+/// "rm -rf", so use with caution). On POSIX environments if |path| is a
+/// symbolic link then only the symlink will be deleted. Returns true on
+/// successful deletion or if |path| does not exist. Calling this function on
+/// the browser process UI or IO threads is not allowed.
 ///
 /*--cef()--*/
 bool CefDeleteFile(const CefString& path, bool recursive);
 
 ///
-// Writes the contents of |src_dir| into a zip archive at |dest_file|. If
-// |include_hidden_files| is true files starting with "." will be included.
-// Returns true on success.  Calling this function on the browser process UI or
-// IO threads is not allowed.
+/// Writes the contents of |src_dir| into a zip archive at |dest_file|. If
+/// |include_hidden_files| is true files starting with "." will be included.
+/// Returns true on success.  Calling this function on the browser process UI or
+/// IO threads is not allowed.
 ///
 /*--cef()--*/
 bool CefZipDirectory(const CefString& src_dir,
@@ -116,12 +116,13 @@
                      bool include_hidden_files);
 
 ///
-// Loads the existing "Certificate Revocation Lists" file that is managed by
-// Google Chrome. This file can generally be found in Chrome's User Data
-// directory (e.g. "C:\Users\[User]\AppData\Local\Google\Chrome\User Data\" on
-// Windows) and is updated periodically by Chrome's component updater service.
-// Must be called in the browser process after the context has been initialized.
-// See https://dev.chromium.org/Home/chromium-security/crlsets for background.
+/// Loads the existing "Certificate Revocation Lists" file that is managed by
+/// Google Chrome. This file can generally be found in Chrome's User Data
+/// directory (e.g. "C:\Users\[User]\AppData\Local\Google\Chrome\User Data\" on
+/// Windows) and is updated periodically by Chrome's component updater service.
+/// Must be called in the browser process after the context has been
+/// initialized. See https://dev.chromium.org/Home/chromium-security/crlsets for
+/// background.
 ///
 /*--cef()--*/
 void CefLoadCRLSetsFile(const CefString& path);
diff --git a/src/include/cef_find_handler.h b/src/include/cef_find_handler.h
index a9cac0a..bd3a700 100644
--- a/src/include/cef_find_handler.h
+++ b/src/include/cef_find_handler.h
@@ -42,19 +42,19 @@
 #include "include/cef_browser.h"
 
 ///
-// Implement this interface to handle events related to find results. The
-// methods of this class will be called on the UI thread.
+/// Implement this interface to handle events related to find results. The
+/// methods of this class will be called on the UI thread.
 ///
 /*--cef(source=client)--*/
 class CefFindHandler : public virtual CefBaseRefCounted {
  public:
   ///
-  // Called to report find results returned by CefBrowserHost::Find().
-  // |identifer| is the identifier passed to Find(), |count| is the number of
-  // matches currently identified, |selectionRect| is the location of where the
-  // match was found (in window coordinates), |activeMatchOrdinal| is the
-  // current position in the search results, and |finalUpdate| is true if this
-  // is the last find notification.
+  /// Called to report find results returned by CefBrowserHost::Find().
+  /// |identifer| is a unique incremental identifier for the currently active
+  /// search, |count| is the number of matches currently identified,
+  /// |selectionRect| is the location of where the match was found (in window
+  /// coordinates), |activeMatchOrdinal| is the current position in the search
+  /// results, and |finalUpdate| is true if this is the last find notification.
   ///
   /*--cef()--*/
   virtual void OnFindResult(CefRefPtr<CefBrowser> browser,
diff --git a/src/include/cef_focus_handler.h b/src/include/cef_focus_handler.h
index 6fd44f5..5f05e50 100644
--- a/src/include/cef_focus_handler.h
+++ b/src/include/cef_focus_handler.h
@@ -44,8 +44,8 @@
 #include "include/cef_frame.h"
 
 ///
-// Implement this interface to handle events related to focus. The methods of
-// this class will be called on the UI thread.
+/// Implement this interface to handle events related to focus. The methods of
+/// this class will be called on the UI thread.
 ///
 /*--cef(source=client)--*/
 class CefFocusHandler : public virtual CefBaseRefCounted {
@@ -53,18 +53,18 @@
   typedef cef_focus_source_t FocusSource;
 
   ///
-  // Called when the browser component is about to loose focus. For instance, if
-  // focus was on the last HTML element and the user pressed the TAB key. |next|
-  // will be true if the browser is giving focus to the next component and false
-  // if the browser is giving focus to the previous component.
+  /// Called when the browser component is about to loose focus. For instance,
+  /// if focus was on the last HTML element and the user pressed the TAB key.
+  /// |next| will be true if the browser is giving focus to the next component
+  /// and false if the browser is giving focus to the previous component.
   ///
   /*--cef()--*/
   virtual void OnTakeFocus(CefRefPtr<CefBrowser> browser, bool next) {}
 
   ///
-  // Called when the browser component is requesting focus. |source| indicates
-  // where the focus request is originating from. Return false to allow the
-  // focus to be set or true to cancel setting the focus.
+  /// Called when the browser component is requesting focus. |source| indicates
+  /// where the focus request is originating from. Return false to allow the
+  /// focus to be set or true to cancel setting the focus.
   ///
   /*--cef()--*/
   virtual bool OnSetFocus(CefRefPtr<CefBrowser> browser, FocusSource source) {
@@ -72,7 +72,7 @@
   }
 
   ///
-  // Called when the browser component has received focus.
+  /// Called when the browser component has received focus.
   ///
   /*--cef()--*/
   virtual void OnGotFocus(CefRefPtr<CefBrowser> browser) {}
diff --git a/src/include/cef_frame.h b/src/include/cef_frame.h
index a1d0bba..ab11dee 100644
--- a/src/include/cef_frame.h
+++ b/src/include/cef_frame.h
@@ -51,106 +51,106 @@
 class CefV8Context;
 
 ///
-// Class used to represent a frame in the browser window. When used in the
-// browser process the methods of this class may be called on any thread unless
-// otherwise indicated in the comments. When used in the render process the
-// methods of this class may only be called on the main thread.
+/// Class used to represent a frame in the browser window. When used in the
+/// browser process the methods of this class may be called on any thread unless
+/// otherwise indicated in the comments. When used in the render process the
+/// methods of this class may only be called on the main thread.
 ///
 /*--cef(source=library)--*/
 class CefFrame : public virtual CefBaseRefCounted {
  public:
   ///
-  // True if this object is currently attached to a valid frame.
+  /// True if this object is currently attached to a valid frame.
   ///
   /*--cef()--*/
   virtual bool IsValid() = 0;
 
   ///
-  // Execute undo in this frame.
+  /// Execute undo in this frame.
   ///
   /*--cef()--*/
   virtual void Undo() = 0;
 
   ///
-  // Execute redo in this frame.
+  /// Execute redo in this frame.
   ///
   /*--cef()--*/
   virtual void Redo() = 0;
 
   ///
-  // Execute cut in this frame.
+  /// Execute cut in this frame.
   ///
   /*--cef()--*/
   virtual void Cut() = 0;
 
   ///
-  // Execute copy in this frame.
+  /// Execute copy in this frame.
   ///
   /*--cef()--*/
   virtual void Copy() = 0;
 
   ///
-  // Execute paste in this frame.
+  /// Execute paste in this frame.
   ///
   /*--cef()--*/
   virtual void Paste() = 0;
 
   ///
-  // Execute delete in this frame.
+  /// Execute delete in this frame.
   ///
   /*--cef(capi_name=del)--*/
   virtual void Delete() = 0;
 
   ///
-  // Execute select all in this frame.
+  /// Execute select all in this frame.
   ///
   /*--cef()--*/
   virtual void SelectAll() = 0;
 
   ///
-  // Save this frame's HTML source to a temporary file and open it in the
-  // default text viewing application. This method can only be called from the
-  // browser process.
+  /// Save this frame's HTML source to a temporary file and open it in the
+  /// default text viewing application. This method can only be called from the
+  /// browser process.
   ///
   /*--cef()--*/
   virtual void ViewSource() = 0;
 
   ///
-  // Retrieve this frame's HTML source as a string sent to the specified
-  // visitor.
+  /// Retrieve this frame's HTML source as a string sent to the specified
+  /// visitor.
   ///
   /*--cef()--*/
   virtual void GetSource(CefRefPtr<CefStringVisitor> visitor) = 0;
 
   ///
-  // Retrieve this frame's display text as a string sent to the specified
-  // visitor.
+  /// Retrieve this frame's display text as a string sent to the specified
+  /// visitor.
   ///
   /*--cef()--*/
   virtual void GetText(CefRefPtr<CefStringVisitor> visitor) = 0;
 
   ///
-  // Load the request represented by the |request| object.
-  //
-  // WARNING: This method will fail with "bad IPC message" reason
-  // INVALID_INITIATOR_ORIGIN (213) unless you first navigate to the
-  // request origin using some other mechanism (LoadURL, link click, etc).
+  /// Load the request represented by the |request| object.
+  ///
+  /// WARNING: This method will fail with "bad IPC message" reason
+  /// INVALID_INITIATOR_ORIGIN (213) unless you first navigate to the
+  /// request origin using some other mechanism (LoadURL, link click, etc).
   ///
   /*--cef()--*/
   virtual void LoadRequest(CefRefPtr<CefRequest> request) = 0;
 
   ///
-  // Load the specified |url|.
+  /// Load the specified |url|.
   ///
   /*--cef()--*/
   virtual void LoadURL(const CefString& url) = 0;
 
   ///
-  // Execute a string of JavaScript code in this frame. The |script_url|
-  // parameter is the URL where the script in question can be found, if any.
-  // The renderer may request this URL to show the developer the source of the
-  // error.  The |start_line| parameter is the base line number to use for error
-  // reporting.
+  /// Execute a string of JavaScript code in this frame. The |script_url|
+  /// parameter is the URL where the script in question can be found, if any.
+  /// The renderer may request this URL to show the developer the source of the
+  /// error.  The |start_line| parameter is the base line number to use for
+  /// error reporting.
   ///
   /*--cef(optional_param=script_url)--*/
   virtual void ExecuteJavaScript(const CefString& code,
@@ -158,87 +158,81 @@
                                  int start_line) = 0;
 
   ///
-  // Returns true if this is the main (top-level) frame.
+  /// Returns true if this is the main (top-level) frame.
   ///
   /*--cef()--*/
   virtual bool IsMain() = 0;
 
   ///
-  // Returns true if this is the focused frame.
+  /// Returns true if this is the focused frame.
   ///
   /*--cef()--*/
   virtual bool IsFocused() = 0;
 
   ///
-  // Returns the name for this frame. If the frame has an assigned name (for
-  // example, set via the iframe "name" attribute) then that value will be
-  // returned. Otherwise a unique name will be constructed based on the frame
-  // parent hierarchy. The main (top-level) frame will always have an empty name
-  // value.
+  /// Returns the name for this frame. If the frame has an assigned name (for
+  /// example, set via the iframe "name" attribute) then that value will be
+  /// returned. Otherwise a unique name will be constructed based on the frame
+  /// parent hierarchy. The main (top-level) frame will always have an empty
+  /// name value.
   ///
   /*--cef()--*/
   virtual CefString GetName() = 0;
 
   ///
-  // Returns the globally unique identifier for this frame or < 0 if the
-  // underlying frame does not yet exist.
+  /// Returns the globally unique identifier for this frame or < 0 if the
+  /// underlying frame does not yet exist.
   ///
   /*--cef()--*/
-  virtual int64 GetIdentifier() = 0;
+  virtual int64_t GetIdentifier() = 0;
 
   ///
-  // Returns the parent of this frame or NULL if this is the main (top-level)
-  // frame.
+  /// Returns the parent of this frame or NULL if this is the main (top-level)
+  /// frame.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefFrame> GetParent() = 0;
 
   ///
-  // Returns the URL currently loaded in this frame.
+  /// Returns the URL currently loaded in this frame.
   ///
   /*--cef()--*/
   virtual CefString GetURL() = 0;
 
   ///
-  // Returns the browser that this frame belongs to.
+  /// Returns the browser that this frame belongs to.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBrowser> GetBrowser() = 0;
 
   ///
-  // Get the V8 context associated with the frame. This method can only be
-  // called from the render process.
+  /// Get the V8 context associated with the frame. This method can only be
+  /// called from the render process.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefV8Context> GetV8Context() = 0;
 
   ///
-  // Visit the DOM document. This method can only be called from the render
-  // process.
+  /// Visit the DOM document. This method can only be called from the render
+  /// process.
   ///
   /*--cef()--*/
   virtual void VisitDOM(CefRefPtr<CefDOMVisitor> visitor) = 0;
 
   ///
-  // Create a new URL request that will be treated as originating from this
-  // frame and the associated browser. This request may be intercepted by the
-  // client via CefResourceRequestHandler or CefSchemeHandlerFactory. Use
-  // CefURLRequest::Create instead if you do not want the request to have this
-  // association, in which case it may be handled differently (see documentation
-  // on that method). Requests may originate from both the browser process and
-  // the render process.
-  //
-  // For requests originating from the browser process:
-  //   - POST data may only contain a single element of type PDE_TYPE_FILE or
-  //     PDE_TYPE_BYTES.
-  // For requests originating from the render process:
-  //   - POST data may only contain a single element of type PDE_TYPE_BYTES.
-  //   - If the response contains Content-Disposition or Mime-Type header values
-  //     that would not normally be rendered then the response may receive
-  //     special handling inside the browser (for example, via the file download
-  //     code path instead of the URL request code path).
-  //
-  // The |request| object will be marked as read-only after calling this method.
+  /// Create a new URL request that will be treated as originating from this
+  /// frame and the associated browser. Use CefURLRequest::Create instead if you
+  /// do not want the request to have this association, in which case it may be
+  /// handled differently (see documentation on that method). A request created
+  /// with this method may only originate from the browser process, and will
+  /// behave as follows:
+  ///   - It may be intercepted by the client via CefResourceRequestHandler or
+  ///     CefSchemeHandlerFactory.
+  ///   - POST data may only contain a single element of type PDE_TYPE_FILE or
+  ///     PDE_TYPE_BYTES.
+  ///
+  /// The |request| object will be marked as read-only after calling this
+  /// method.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefURLRequest> CreateURLRequest(
@@ -246,10 +240,12 @@
       CefRefPtr<CefURLRequestClient> client) = 0;
 
   ///
-  // Send a message to the specified |target_process|. Message delivery is not
-  // guaranteed in all cases (for example, if the browser is closing,
-  // navigating, or if the target process crashes). Send an ACK message back
-  // from the target process if confirmation is required.
+  /// Send a message to the specified |target_process|. Ownership of the message
+  /// contents will be transferred and the |message| reference will be
+  /// invalidated. Message delivery is not guaranteed in all cases (for example,
+  /// if the browser is closing, navigating, or if the target process crashes).
+  /// Send an ACK message back from the target process if confirmation is
+  /// required.
   ///
   /*--cef()--*/
   virtual void SendProcessMessage(CefProcessId target_process,
diff --git a/src/include/cef_frame_handler.h b/src/include/cef_frame_handler.h
new file mode 100644
index 0000000..b742623
--- /dev/null
+++ b/src/include/cef_frame_handler.h
@@ -0,0 +1,177 @@
+// Copyright (c) 2021 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---------------------------------------------------------------------------
+//
+// The contents of this file must follow a specific format in order to
+// support the CEF translator tool. See the translator.README.txt file in the
+// tools directory for more information.
+//
+
+#ifndef CEF_INCLUDE_CEF_FRAME_HANDLER_H_
+#define CEF_INCLUDE_CEF_FRAME_HANDLER_H_
+#pragma once
+
+#include "include/cef_base.h"
+#include "include/cef_browser.h"
+#include "include/cef_frame.h"
+
+///
+/// Implement this interface to handle events related to CefFrame life span. The
+/// order of callbacks is:
+///
+/// (1) During initial CefBrowserHost creation and navigation of the main frame:
+/// - CefFrameHandler::OnFrameCreated => The initial main frame object has been
+///   created. Any commands will be queued until the frame is attached.
+/// - CefFrameHandler::OnMainFrameChanged => The initial main frame object has
+///   been assigned to the browser.
+/// - CefLifeSpanHandler::OnAfterCreated => The browser is now valid and can be
+///   used.
+/// - CefFrameHandler::OnFrameAttached => The initial main frame object is now
+///   connected to its peer in the renderer process. Commands can be routed.
+///
+/// (2) During further CefBrowserHost navigation/loading of the main frame
+///     and/or sub-frames:
+/// - CefFrameHandler::OnFrameCreated => A new main frame or sub-frame object
+///   has been created. Any commands will be queued until the frame is attached.
+/// - CefFrameHandler::OnFrameAttached => A new main frame or sub-frame object
+///   is now connected to its peer in the renderer process. Commands can be
+///   routed.
+/// - CefFrameHandler::OnFrameDetached => An existing main frame or sub-frame
+///   object has lost its connection to the renderer process. If multiple
+///   objects are detached at the same time then notifications will be sent for
+///   any sub-frame objects before the main frame object. Commands can no longer
+///   be routed and will be discarded.
+/// - CefFrameHandler::OnMainFrameChanged => A new main frame object has been
+///   assigned to the browser. This will only occur with cross-origin navigation
+///   or re-navigation after renderer process termination (due to crashes, etc).
+///
+/// (3) During final CefBrowserHost destruction of the main frame:
+/// - CefFrameHandler::OnFrameDetached => Any sub-frame objects have lost their
+///   connection to the renderer process. Commands can no longer be routed and
+///   will be discarded.
+/// - CefLifeSpanHandler::OnBeforeClose => The browser has been destroyed.
+/// - CefFrameHandler::OnFrameDetached => The main frame object have lost its
+///   connection to the renderer process. Notifications will be sent for any
+///   sub-frame objects before the main frame object. Commands can no longer be
+///   routed and will be discarded.
+/// - CefFrameHandler::OnMainFrameChanged => The final main frame object has
+///   been removed from the browser.
+///
+/// Cross-origin navigation and/or loading receives special handling.
+///
+/// When the main frame navigates to a different origin the OnMainFrameChanged
+/// callback (2) will be executed with the old and new main frame objects.
+///
+/// When a new sub-frame is loaded in, or an existing sub-frame is navigated to,
+/// a different origin from the parent frame, a temporary sub-frame object will
+/// first be created in the parent's renderer process. That temporary sub-frame
+/// will then be discarded after the real cross-origin sub-frame is created in
+/// the new/target renderer process. The client will receive cross-origin
+/// navigation callbacks (2) for the transition from the temporary sub-frame to
+/// the real sub-frame. The temporary sub-frame will not recieve or execute
+/// commands during this transitional period (any sent commands will be
+/// discarded).
+///
+/// When a new popup browser is created in a different origin from the parent
+/// browser, a temporary main frame object for the popup will first be created
+/// in the parent's renderer process. That temporary main frame will then be
+/// discarded after the real cross-origin main frame is created in the
+/// new/target renderer process. The client will recieve creation and initial
+/// navigation callbacks (1) for the temporary main frame, followed by
+/// cross-origin navigation callbacks (2) for the transition from the temporary
+/// main frame to the real main frame. The temporary main frame may receive and
+/// execute commands during this transitional period (any sent commands may be
+/// executed, but the behavior is potentially undesirable since they execute in
+/// the parent browser's renderer process and not the new/target renderer
+/// process).
+///
+/// Callbacks will not be executed for placeholders that may be created during
+/// pre-commit navigation for sub-frames that do not yet exist in the renderer
+/// process. Placeholders will have CefFrame::GetIdentifier() == -4.
+///
+/// The methods of this class will be called on the UI thread unless otherwise
+/// indicated.
+///
+/*--cef(source=client)--*/
+class CefFrameHandler : public virtual CefBaseRefCounted {
+ public:
+  ///
+  /// Called when a new frame is created. This will be the first notification
+  /// that references |frame|. Any commands that require transport to the
+  /// associated renderer process (LoadRequest, SendProcessMessage, GetSource,
+  /// etc.) will be queued until OnFrameAttached is called for |frame|.
+  ///
+  /*--cef()--*/
+  virtual void OnFrameCreated(CefRefPtr<CefBrowser> browser,
+                              CefRefPtr<CefFrame> frame) {}
+
+  ///
+  /// Called when a frame can begin routing commands to/from the associated
+  /// renderer process. |reattached| will be true if the frame was re-attached
+  /// after exiting the BackForwardCache. Any commands that were queued have now
+  /// been dispatched.
+  ///
+  /*--cef()--*/
+  virtual void OnFrameAttached(CefRefPtr<CefBrowser> browser,
+                               CefRefPtr<CefFrame> frame,
+                               bool reattached) {}
+
+  ///
+  /// Called when a frame loses its connection to the renderer process and will
+  /// be destroyed. Any pending or future commands will be discarded and
+  /// CefFrame::IsValid() will now return false for |frame|. If called after
+  /// CefLifeSpanHandler::OnBeforeClose() during browser destruction then
+  /// CefBrowser::IsValid() will return false for |browser|.
+  ///
+  /*--cef()--*/
+  virtual void OnFrameDetached(CefRefPtr<CefBrowser> browser,
+                               CefRefPtr<CefFrame> frame) {}
+
+  ///
+  /// Called when the main frame changes due to (a) initial browser creation,
+  /// (b) final browser destruction, (c) cross-origin navigation or (d)
+  /// re-navigation after renderer process termination (due to crashes, etc).
+  /// |old_frame| will be NULL and |new_frame| will be non-NULL when a main
+  /// frame is assigned to |browser| for the first time. |old_frame| will be
+  /// non-NULL and |new_frame| will be NULL and  when a main frame is removed
+  /// from |browser| for the last time. Both |old_frame| and |new_frame| will be
+  /// non-NULL for cross-origin navigations or re-navigation after renderer
+  /// process termination. This method will be called after OnFrameCreated() for
+  /// |new_frame| and/or after OnFrameDetached() for |old_frame|. If called
+  /// after CefLifeSpanHandler::OnBeforeClose() during browser destruction then
+  /// CefBrowser::IsValid() will return false for |browser|.
+  ///
+  /*--cef(optional_param=old_frame,optional_param=new_frame)--*/
+  virtual void OnMainFrameChanged(CefRefPtr<CefBrowser> browser,
+                                  CefRefPtr<CefFrame> old_frame,
+                                  CefRefPtr<CefFrame> new_frame) {}
+};
+
+#endif  // CEF_INCLUDE_CEF_FRAME_HANDLER_H_
diff --git a/src/include/cef_request_callback.h b/src/include/cef_i18n_util.h
similarity index 73%
rename from src/include/cef_request_callback.h
rename to src/include/cef_i18n_util.h
index 68094de..5f9e116 100644
--- a/src/include/cef_request_callback.h
+++ b/src/include/cef_i18n_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2021 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -34,30 +34,16 @@
 // tools directory for more information.
 //
 
-#ifndef CEF_INCLUDE_CEF_REQUEST_CALLBACK_H_
-#define CEF_INCLUDE_CEF_REQUEST_CALLBACK_H_
+#ifndef CEF_INCLUDE_CEF_I18N_UTIL_H_
+#define CEF_INCLUDE_CEF_I18N_UTIL_H_
 #pragma once
 
 #include "include/cef_base.h"
 
 ///
-// Callback interface used for asynchronous continuation of url requests.
+/// Returns true if the application text direction is right-to-left.
 ///
-/*--cef(source=library)--*/
-class CefRequestCallback : public virtual CefBaseRefCounted {
- public:
-  ///
-  // Continue the url request. If |allow| is true the request will be continued.
-  // Otherwise, the request will be canceled.
-  ///
-  /*--cef(capi_name=cont)--*/
-  virtual void Continue(bool allow) = 0;
+/*--cef()--*/
+bool CefIsRTL();
 
-  ///
-  // Cancel the url request.
-  ///
-  /*--cef()--*/
-  virtual void Cancel() = 0;
-};
-
-#endif  // CEF_INCLUDE_CEF_REQUEST_CALLBACK_H_
+#endif  // CEF_INCLUDE_CEF_I18N_UTIL_H_
diff --git a/src/include/cef_image.h b/src/include/cef_image.h
index 6346812..cbea565 100644
--- a/src/include/cef_image.h
+++ b/src/include/cef_image.h
@@ -42,42 +42,42 @@
 #include "include/cef_values.h"
 
 ///
-// Container for a single image represented at different scale factors. All
-// image representations should be the same size in density independent pixel
-// (DIP) units. For example, if the image at scale factor 1.0 is 100x100 pixels
-// then the image at scale factor 2.0 should be 200x200 pixels -- both images
-// will display with a DIP size of 100x100 units. The methods of this class can
-// be called on any browser process thread.
+/// Container for a single image represented at different scale factors. All
+/// image representations should be the same size in density independent pixel
+/// (DIP) units. For example, if the image at scale factor 1.0 is 100x100 pixels
+/// then the image at scale factor 2.0 should be 200x200 pixels -- both images
+/// will display with a DIP size of 100x100 units. The methods of this class can
+/// be called on any browser process thread.
 ///
 /*--cef(source=library)--*/
 class CefImage : public virtual CefBaseRefCounted {
  public:
   ///
-  // Create a new CefImage. It will initially be empty. Use the Add*() methods
-  // to add representations at different scale factors.
+  /// Create a new CefImage. It will initially be empty. Use the Add*() methods
+  /// to add representations at different scale factors.
   ///
   /*--cef()--*/
   static CefRefPtr<CefImage> CreateImage();
 
   ///
-  // Returns true if this Image is empty.
+  /// Returns true if this Image is empty.
   ///
   /*--cef()--*/
   virtual bool IsEmpty() = 0;
 
   ///
-  // Returns true if this Image and |that| Image share the same underlying
-  // storage. Will also return true if both images are empty.
+  /// Returns true if this Image and |that| Image share the same underlying
+  /// storage. Will also return true if both images are empty.
   ///
   /*--cef()--*/
   virtual bool IsSame(CefRefPtr<CefImage> that) = 0;
 
   ///
-  // Add a bitmap image representation for |scale_factor|. Only 32-bit RGBA/BGRA
-  // formats are supported. |pixel_width| and |pixel_height| are the bitmap
-  // representation size in pixel coordinates. |pixel_data| is the array of
-  // pixel data and should be |pixel_width| x |pixel_height| x 4 bytes in size.
-  // |color_type| and |alpha_type| values specify the pixel format.
+  /// Add a bitmap image representation for |scale_factor|. Only 32-bit
+  /// RGBA/BGRA formats are supported. |pixel_width| and |pixel_height| are the
+  /// bitmap representation size in pixel coordinates. |pixel_data| is the array
+  /// of pixel data and should be |pixel_width| x |pixel_height| x 4 bytes in
+  /// size. |color_type| and |alpha_type| values specify the pixel format.
   ///
   /*--cef()--*/
   virtual bool AddBitmap(float scale_factor,
@@ -89,9 +89,9 @@
                          size_t pixel_data_size) = 0;
 
   ///
-  // Add a PNG image representation for |scale_factor|. |png_data| is the image
-  // data of size |png_data_size|. Any alpha transparency in the PNG data will
-  // be maintained.
+  /// Add a PNG image representation for |scale_factor|. |png_data| is the image
+  /// data of size |png_data_size|. Any alpha transparency in the PNG data will
+  /// be maintained.
   ///
   /*--cef()--*/
   virtual bool AddPNG(float scale_factor,
@@ -99,9 +99,9 @@
                       size_t png_data_size) = 0;
 
   ///
-  // Create a JPEG image representation for |scale_factor|. |jpeg_data| is the
-  // image data of size |jpeg_data_size|. The JPEG format does not support
-  // transparency so the alpha byte will be set to 0xFF for all pixels.
+  /// Create a JPEG image representation for |scale_factor|. |jpeg_data| is the
+  /// image data of size |jpeg_data_size|. The JPEG format does not support
+  /// transparency so the alpha byte will be set to 0xFF for all pixels.
   ///
   /*--cef()--*/
   virtual bool AddJPEG(float scale_factor,
@@ -109,34 +109,34 @@
                        size_t jpeg_data_size) = 0;
 
   ///
-  // Returns the image width in density independent pixel (DIP) units.
+  /// Returns the image width in density independent pixel (DIP) units.
   ///
   /*--cef()--*/
   virtual size_t GetWidth() = 0;
 
   ///
-  // Returns the image height in density independent pixel (DIP) units.
+  /// Returns the image height in density independent pixel (DIP) units.
   ///
   /*--cef()--*/
   virtual size_t GetHeight() = 0;
 
   ///
-  // Returns true if this image contains a representation for |scale_factor|.
+  /// Returns true if this image contains a representation for |scale_factor|.
   ///
   /*--cef()--*/
   virtual bool HasRepresentation(float scale_factor) = 0;
 
   ///
-  // Removes the representation for |scale_factor|. Returns true on success.
+  /// Removes the representation for |scale_factor|. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool RemoveRepresentation(float scale_factor) = 0;
 
   ///
-  // Returns information for the representation that most closely matches
-  // |scale_factor|. |actual_scale_factor| is the actual scale factor for the
-  // representation. |pixel_width| and |pixel_height| are the representation
-  // size in pixel coordinates. Returns true on success.
+  /// Returns information for the representation that most closely matches
+  /// |scale_factor|. |actual_scale_factor| is the actual scale factor for the
+  /// representation. |pixel_width| and |pixel_height| are the representation
+  /// size in pixel coordinates. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool GetRepresentationInfo(float scale_factor,
@@ -145,12 +145,12 @@
                                      int& pixel_height) = 0;
 
   ///
-  // Returns the bitmap representation that most closely matches |scale_factor|.
-  // Only 32-bit RGBA/BGRA formats are supported. |color_type| and |alpha_type|
-  // values specify the desired output pixel format. |pixel_width| and
-  // |pixel_height| are the output representation size in pixel coordinates.
-  // Returns a CefBinaryValue containing the pixel data on success or NULL on
-  // failure.
+  /// Returns the bitmap representation that most closely matches
+  /// |scale_factor|. Only 32-bit RGBA/BGRA formats are supported. |color_type|
+  /// and |alpha_type| values specify the desired output pixel format.
+  /// |pixel_width| and |pixel_height| are the output representation size in
+  /// pixel coordinates. Returns a CefBinaryValue containing the pixel data on
+  /// success or NULL on failure.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBinaryValue> GetAsBitmap(float scale_factor,
@@ -160,11 +160,12 @@
                                                 int& pixel_height) = 0;
 
   ///
-  // Returns the PNG representation that most closely matches |scale_factor|. If
-  // |with_transparency| is true any alpha transparency in the image will be
-  // represented in the resulting PNG data. |pixel_width| and |pixel_height| are
-  // the output representation size in pixel coordinates. Returns a
-  // CefBinaryValue containing the PNG image data on success or NULL on failure.
+  /// Returns the PNG representation that most closely matches |scale_factor|.
+  /// If |with_transparency| is true any alpha transparency in the image will be
+  /// represented in the resulting PNG data. |pixel_width| and |pixel_height|
+  /// are the output representation size in pixel coordinates. Returns a
+  /// CefBinaryValue containing the PNG image data on success or NULL on
+  /// failure.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBinaryValue> GetAsPNG(float scale_factor,
@@ -173,13 +174,13 @@
                                              int& pixel_height) = 0;
 
   ///
-  // Returns the JPEG representation that most closely matches |scale_factor|.
-  // |quality| determines the compression level with 0 == lowest and 100 ==
-  // highest. The JPEG format does not support alpha transparency and the alpha
-  // channel, if any, will be discarded. |pixel_width| and |pixel_height| are
-  // the output representation size in pixel coordinates. Returns a
-  // CefBinaryValue containing the JPEG image data on success or NULL on
-  // failure.
+  /// Returns the JPEG representation that most closely matches |scale_factor|.
+  /// |quality| determines the compression level with 0 == lowest and 100 ==
+  /// highest. The JPEG format does not support alpha transparency and the alpha
+  /// channel, if any, will be discarded. |pixel_width| and |pixel_height| are
+  /// the output representation size in pixel coordinates. Returns a
+  /// CefBinaryValue containing the JPEG image data on success or NULL on
+  /// failure.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBinaryValue> GetAsJPEG(float scale_factor,
diff --git a/src/include/cef_jsdialog_handler.h b/src/include/cef_jsdialog_handler.h
index b7e0945..9ad6527 100644
--- a/src/include/cef_jsdialog_handler.h
+++ b/src/include/cef_jsdialog_handler.h
@@ -42,23 +42,23 @@
 #include "include/cef_browser.h"
 
 ///
-// Callback interface used for asynchronous continuation of JavaScript dialog
-// requests.
+/// Callback interface used for asynchronous continuation of JavaScript dialog
+/// requests.
 ///
 /*--cef(source=library)--*/
 class CefJSDialogCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Continue the JS dialog request. Set |success| to true if the OK button was
-  // pressed. The |user_input| value should be specified for prompt dialogs.
+  /// Continue the JS dialog request. Set |success| to true if the OK button was
+  /// pressed. The |user_input| value should be specified for prompt dialogs.
   ///
   /*--cef(capi_name=cont,optional_param=user_input)--*/
   virtual void Continue(bool success, const CefString& user_input) = 0;
 };
 
 ///
-// Implement this interface to handle events related to JavaScript dialogs. The
-// methods of this class will be called on the UI thread.
+/// Implement this interface to handle events related to JavaScript dialogs. The
+/// methods of this class will be called on the UI thread.
 ///
 /*--cef(source=client)--*/
 class CefJSDialogHandler : public virtual CefBaseRefCounted {
@@ -66,20 +66,20 @@
   typedef cef_jsdialog_type_t JSDialogType;
 
   ///
-  // Called to run a JavaScript dialog. If |origin_url| is non-empty it can be
-  // passed to the CefFormatUrlForSecurityDisplay function to retrieve a secure
-  // and user-friendly display string. The |default_prompt_text| value will be
-  // specified for prompt dialogs only. Set |suppress_message| to true and
-  // return false to suppress the message (suppressing messages is preferable to
-  // immediately executing the callback as this is used to detect presumably
-  // malicious behavior like spamming alert messages in onbeforeunload). Set
-  // |suppress_message| to false and return false to use the default
-  // implementation (the default implementation will show one modal dialog at a
-  // time and suppress any additional dialog requests until the displayed dialog
-  // is dismissed). Return true if the application will use a custom dialog or
-  // if the callback has been executed immediately. Custom dialogs may be either
-  // modal or modeless. If a custom dialog is used the application must execute
-  // |callback| once the custom dialog is dismissed.
+  /// Called to run a JavaScript dialog. If |origin_url| is non-empty it can be
+  /// passed to the CefFormatUrlForSecurityDisplay function to retrieve a secure
+  /// and user-friendly display string. The |default_prompt_text| value will be
+  /// specified for prompt dialogs only. Set |suppress_message| to true and
+  /// return false to suppress the message (suppressing messages is preferable
+  /// to immediately executing the callback as this is used to detect presumably
+  /// malicious behavior like spamming alert messages in onbeforeunload). Set
+  /// |suppress_message| to false and return false to use the default
+  /// implementation (the default implementation will show one modal dialog at a
+  /// time and suppress any additional dialog requests until the displayed
+  /// dialog is dismissed). Return true if the application will use a custom
+  /// dialog or if the callback has been executed immediately. Custom dialogs
+  /// may be either modal or modeless. If a custom dialog is used the
+  /// application must execute |callback| once the custom dialog is dismissed.
   ///
   /*--cef(optional_param=origin_url,optional_param=accept_lang,
           optional_param=message_text,optional_param=default_prompt_text)--*/
@@ -94,12 +94,12 @@
   }
 
   ///
-  // Called to run a dialog asking the user if they want to leave a page. Return
-  // false to use the default dialog implementation. Return true if the
-  // application will use a custom dialog or if the callback has been executed
-  // immediately. Custom dialogs may be either modal or modeless. If a custom
-  // dialog is used the application must execute |callback| once the custom
-  // dialog is dismissed.
+  /// Called to run a dialog asking the user if they want to leave a page.
+  /// Return false to use the default dialog implementation. Return true if the
+  /// application will use a custom dialog or if the callback has been executed
+  /// immediately. Custom dialogs may be either modal or modeless. If a custom
+  /// dialog is used the application must execute |callback| once the custom
+  /// dialog is dismissed.
   ///
   /*--cef(optional_param=message_text)--*/
   virtual bool OnBeforeUnloadDialog(CefRefPtr<CefBrowser> browser,
@@ -110,15 +110,15 @@
   }
 
   ///
-  // Called to cancel any pending dialogs and reset any saved dialog state. Will
-  // be called due to events like page navigation irregardless of whether any
-  // dialogs are currently pending.
+  /// Called to cancel any pending dialogs and reset any saved dialog state.
+  /// Will be called due to events like page navigation irregardless of whether
+  /// any dialogs are currently pending.
   ///
   /*--cef()--*/
   virtual void OnResetDialogState(CefRefPtr<CefBrowser> browser) {}
 
   ///
-  // Called when the default implementation dialog is closed.
+  /// Called when the dialog is closed.
   ///
   /*--cef()--*/
   virtual void OnDialogClosed(CefRefPtr<CefBrowser> browser) {}
diff --git a/src/include/cef_keyboard_handler.h b/src/include/cef_keyboard_handler.h
index 386491e..69838f9 100644
--- a/src/include/cef_keyboard_handler.h
+++ b/src/include/cef_keyboard_handler.h
@@ -42,18 +42,18 @@
 #include "include/cef_browser.h"
 
 ///
-// Implement this interface to handle events related to keyboard input. The
-// methods of this class will be called on the UI thread.
+/// Implement this interface to handle events related to keyboard input. The
+/// methods of this class will be called on the UI thread.
 ///
 /*--cef(source=client)--*/
 class CefKeyboardHandler : public virtual CefBaseRefCounted {
  public:
   ///
-  // Called before a keyboard event is sent to the renderer. |event| contains
-  // information about the keyboard event. |os_event| is the operating system
-  // event message, if any. Return true if the event was handled or false
-  // otherwise. If the event will be handled in OnKeyEvent() as a keyboard
-  // shortcut set |is_keyboard_shortcut| to true and return false.
+  /// Called before a keyboard event is sent to the renderer. |event| contains
+  /// information about the keyboard event. |os_event| is the operating system
+  /// event message, if any. Return true if the event was handled or false
+  /// otherwise. If the event will be handled in OnKeyEvent() as a keyboard
+  /// shortcut set |is_keyboard_shortcut| to true and return false.
   ///
   /*--cef()--*/
   virtual bool OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
@@ -64,10 +64,10 @@
   }
 
   ///
-  // Called after the renderer and JavaScript in the page has had a chance to
-  // handle the event. |event| contains information about the keyboard event.
-  // |os_event| is the operating system event message, if any. Return true if
-  // the keyboard event was handled or false otherwise.
+  /// Called after the renderer and JavaScript in the page has had a chance to
+  /// handle the event. |event| contains information about the keyboard event.
+  /// |os_event| is the operating system event message, if any. Return true if
+  /// the keyboard event was handled or false otherwise.
   ///
   /*--cef()--*/
   virtual bool OnKeyEvent(CefRefPtr<CefBrowser> browser,
diff --git a/src/include/cef_life_span_handler.h b/src/include/cef_life_span_handler.h
index c08cfcf..067a3f9 100644
--- a/src/include/cef_life_span_handler.h
+++ b/src/include/cef_life_span_handler.h
@@ -44,9 +44,9 @@
 class CefClient;
 
 ///
-// Implement this interface to handle events related to browser life span. The
-// methods of this class will be called on the UI thread unless otherwise
-// indicated.
+/// Implement this interface to handle events related to browser life span. The
+/// methods of this class will be called on the UI thread unless otherwise
+/// indicated.
 ///
 /*--cef(source=client)--*/
 class CefLifeSpanHandler : public virtual CefBaseRefCounted {
@@ -54,29 +54,29 @@
   typedef cef_window_open_disposition_t WindowOpenDisposition;
 
   ///
-  // Called on the UI thread before a new popup browser is created. The
-  // |browser| and |frame| values represent the source of the popup request. The
-  // |target_url| and |target_frame_name| values indicate where the popup
-  // browser should navigate and may be empty if not specified with the request.
-  // The |target_disposition| value indicates where the user intended to open
-  // the popup (e.g. current tab, new tab, etc). The |user_gesture| value will
-  // be true if the popup was opened via explicit user gesture (e.g. clicking a
-  // link) or false if the popup opened automatically (e.g. via the
-  // DomContentLoaded event). The |popupFeatures| structure contains additional
-  // information about the requested popup window. To allow creation of the
-  // popup browser optionally modify |windowInfo|, |client|, |settings| and
-  // |no_javascript_access| and return false. To cancel creation of the popup
-  // browser return true. The |client| and |settings| values will default to the
-  // source browser's values. If the |no_javascript_access| value is set to
-  // false the new browser will not be scriptable and may not be hosted in the
-  // same renderer process as the source browser. Any modifications to
-  // |windowInfo| will be ignored if the parent browser is wrapped in a
-  // CefBrowserView. Popup browser creation will be canceled if the parent
-  // browser is destroyed before the popup browser creation completes (indicated
-  // by a call to OnAfterCreated for the popup browser). The |extra_info|
-  // parameter provides an opportunity to specify extra information specific
-  // to the created popup browser that will be passed to
-  // CefRenderProcessHandler::OnBrowserCreated() in the render process.
+  /// Called on the UI thread before a new popup browser is created. The
+  /// |browser| and |frame| values represent the source of the popup request.
+  /// The |target_url| and |target_frame_name| values indicate where the popup
+  /// browser should navigate and may be empty if not specified with the
+  /// request. The |target_disposition| value indicates where the user intended
+  /// to open the popup (e.g. current tab, new tab, etc). The |user_gesture|
+  /// value will be true if the popup was opened via explicit user gesture (e.g.
+  /// clicking a link) or false if the popup opened automatically (e.g. via the
+  /// DomContentLoaded event). The |popupFeatures| structure contains additional
+  /// information about the requested popup window. To allow creation of the
+  /// popup browser optionally modify |windowInfo|, |client|, |settings| and
+  /// |no_javascript_access| and return false. To cancel creation of the popup
+  /// browser return true. The |client| and |settings| values will default to
+  /// the source browser's values. If the |no_javascript_access| value is set to
+  /// false the new browser will not be scriptable and may not be hosted in the
+  /// same renderer process as the source browser. Any modifications to
+  /// |windowInfo| will be ignored if the parent browser is wrapped in a
+  /// CefBrowserView. Popup browser creation will be canceled if the parent
+  /// browser is destroyed before the popup browser creation completes
+  /// (indicated by a call to OnAfterCreated for the popup browser). The
+  /// |extra_info| parameter provides an opportunity to specify extra
+  /// information specific to the created popup browser that will be passed to
+  /// CefRenderProcessHandler::OnBrowserCreated() in the render process.
   ///
   /*--cef(optional_param=target_url,optional_param=target_frame_name)--*/
   virtual bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
@@ -95,113 +95,144 @@
   }
 
   ///
-  // Called after a new browser is created. This callback will be the first
-  // notification that references |browser|.
+  /// Called on the UI thread before a new DevTools popup browser is created.
+  /// The |browser| value represents the source of the popup request. Optionally
+  /// modify |windowInfo|, |client|, |settings| and |extra_info| values. The
+  /// |client|, |settings| and |extra_info| values will default to the source
+  /// browser's values. Any modifications to |windowInfo| will be ignored if the
+  /// parent browser is Views-hosted (wrapped in a CefBrowserView).
+  ///
+  /// The |extra_info| parameter provides an opportunity to specify extra
+  /// information specific to the created popup browser that will be passed to
+  /// CefRenderProcessHandler::OnBrowserCreated() in the render process. The
+  /// existing |extra_info| object, if any, will be read-only but may be
+  /// replaced with a new object.
+  ///
+  /// Views-hosted source browsers will create Views-hosted DevTools popups
+  /// unless |use_default_window| is set to to true. DevTools popups can be
+  /// blocked by returning true from CefCommandHandler::OnChromeCommand for
+  /// IDC_DEV_TOOLS. Only used with the Chrome runtime.
+  ///
+  /*--cef()--*/
+  virtual void OnBeforeDevToolsPopup(CefRefPtr<CefBrowser> browser,
+                                     CefWindowInfo& windowInfo,
+                                     CefRefPtr<CefClient>& client,
+                                     CefBrowserSettings& settings,
+                                     CefRefPtr<CefDictionaryValue>& extra_info,
+                                     bool* use_default_window) {}
+
+  ///
+  /// Called after a new browser is created. It is now safe to begin performing
+  /// actions with |browser|. CefFrameHandler callbacks related to initial main
+  /// frame creation will arrive before this callback. See CefFrameHandler
+  /// documentation for additional usage information.
   ///
   /*--cef()--*/
   virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) {}
 
   ///
-  // Called when a browser has recieved a request to close. This may result
-  // directly from a call to CefBrowserHost::*CloseBrowser() or indirectly if
-  // the browser is parented to a top-level window created by CEF and the user
-  // attempts to close that window (by clicking the 'X', for example). The
-  // DoClose() method will be called after the JavaScript 'onunload' event has
-  // been fired.
-  //
-  // An application should handle top-level owner window close notifications by
-  // calling CefBrowserHost::TryCloseBrowser() or
-  // CefBrowserHost::CloseBrowser(false) instead of allowing the window to close
-  // immediately (see the examples below). This gives CEF an opportunity to
-  // process the 'onbeforeunload' event and optionally cancel the close before
-  // DoClose() is called.
-  //
-  // When windowed rendering is enabled CEF will internally create a window or
-  // view to host the browser. In that case returning false from DoClose() will
-  // send the standard close notification to the browser's top-level owner
-  // window (e.g. WM_CLOSE on Windows, performClose: on OS X, "delete_event" on
-  // Linux or CefWindowDelegate::CanClose() callback from Views). If the
-  // browser's host window/view has already been destroyed (via view hierarchy
-  // tear-down, for example) then DoClose() will not be called for that browser
-  // since is no longer possible to cancel the close.
-  //
-  // When windowed rendering is disabled returning false from DoClose() will
-  // cause the browser object to be destroyed immediately.
-  //
-  // If the browser's top-level owner window requires a non-standard close
-  // notification then send that notification from DoClose() and return true.
-  //
-  // The CefLifeSpanHandler::OnBeforeClose() method will be called after
-  // DoClose() (if DoClose() is called) and immediately before the browser
-  // object is destroyed. The application should only exit after OnBeforeClose()
-  // has been called for all existing browsers.
-  //
-  // The below examples describe what should happen during window close when the
-  // browser is parented to an application-provided top-level window.
-  //
-  // Example 1: Using CefBrowserHost::TryCloseBrowser(). This is recommended for
-  // clients using standard close handling and windows created on the browser
-  // process UI thread.
-  // 1.  User clicks the window close button which sends a close notification to
-  //     the application's top-level window.
-  // 2.  Application's top-level window receives the close notification and
-  //     calls TryCloseBrowser() (which internally calls CloseBrowser(false)).
-  //     TryCloseBrowser() returns false so the client cancels the window close.
-  // 3.  JavaScript 'onbeforeunload' handler executes and shows the close
-  //     confirmation dialog (which can be overridden via
-  //     CefJSDialogHandler::OnBeforeUnloadDialog()).
-  // 4.  User approves the close.
-  // 5.  JavaScript 'onunload' handler executes.
-  // 6.  CEF sends a close notification to the application's top-level window
-  //     (because DoClose() returned false by default).
-  // 7.  Application's top-level window receives the close notification and
-  //     calls TryCloseBrowser(). TryCloseBrowser() returns true so the client
-  //     allows the window close.
-  // 8.  Application's top-level window is destroyed.
-  // 9.  Application's OnBeforeClose() handler is called and the browser object
-  //     is destroyed.
-  // 10. Application exits by calling CefQuitMessageLoop() if no other browsers
-  //     exist.
-  //
-  // Example 2: Using CefBrowserHost::CloseBrowser(false) and implementing the
-  // DoClose() callback. This is recommended for clients using non-standard
-  // close handling or windows that were not created on the browser process UI
-  // thread.
-  // 1.  User clicks the window close button which sends a close notification to
-  //     the application's top-level window.
-  // 2.  Application's top-level window receives the close notification and:
-  //     A. Calls CefBrowserHost::CloseBrowser(false).
-  //     B. Cancels the window close.
-  // 3.  JavaScript 'onbeforeunload' handler executes and shows the close
-  //     confirmation dialog (which can be overridden via
-  //     CefJSDialogHandler::OnBeforeUnloadDialog()).
-  // 4.  User approves the close.
-  // 5.  JavaScript 'onunload' handler executes.
-  // 6.  Application's DoClose() handler is called. Application will:
-  //     A. Set a flag to indicate that the next close attempt will be allowed.
-  //     B. Return false.
-  // 7.  CEF sends an close notification to the application's top-level window.
-  // 8.  Application's top-level window receives the close notification and
-  //     allows the window to close based on the flag from #6B.
-  // 9.  Application's top-level window is destroyed.
-  // 10. Application's OnBeforeClose() handler is called and the browser object
-  //     is destroyed.
-  // 11. Application exits by calling CefQuitMessageLoop() if no other browsers
-  //     exist.
+  /// Called when a browser has recieved a request to close. This may result
+  /// directly from a call to CefBrowserHost::*CloseBrowser() or indirectly if
+  /// the browser is parented to a top-level window created by CEF and the user
+  /// attempts to close that window (by clicking the 'X', for example). The
+  /// DoClose() method will be called after the JavaScript 'onunload' event has
+  /// been fired.
+  ///
+  /// An application should handle top-level owner window close notifications by
+  /// calling CefBrowserHost::TryCloseBrowser() or
+  /// CefBrowserHost::CloseBrowser(false) instead of allowing the window to
+  /// close immediately (see the examples below). This gives CEF an opportunity
+  /// to process the 'onbeforeunload' event and optionally cancel the close
+  /// before DoClose() is called.
+  ///
+  /// When windowed rendering is enabled CEF will internally create a window or
+  /// view to host the browser. In that case returning false from DoClose() will
+  /// send the standard close notification to the browser's top-level owner
+  /// window (e.g. WM_CLOSE on Windows, performClose: on OS X, "delete_event" on
+  /// Linux or CefWindowDelegate::CanClose() callback from Views). If the
+  /// browser's host window/view has already been destroyed (via view hierarchy
+  /// tear-down, for example) then DoClose() will not be called for that browser
+  /// since is no longer possible to cancel the close.
+  ///
+  /// When windowed rendering is disabled returning false from DoClose() will
+  /// cause the browser object to be destroyed immediately.
+  ///
+  /// If the browser's top-level owner window requires a non-standard close
+  /// notification then send that notification from DoClose() and return true.
+  ///
+  /// The CefLifeSpanHandler::OnBeforeClose() method will be called after
+  /// DoClose() (if DoClose() is called) and immediately before the browser
+  /// object is destroyed. The application should only exit after
+  /// OnBeforeClose() has been called for all existing browsers.
+  ///
+  /// The below examples describe what should happen during window close when
+  /// the browser is parented to an application-provided top-level window.
+  ///
+  /// Example 1: Using CefBrowserHost::TryCloseBrowser(). This is recommended
+  /// for clients using standard close handling and windows created on the
+  /// browser process UI thread.
+  /// 1.  User clicks the window close button which sends a close notification
+  ///     to the application's top-level window.
+  /// 2.  Application's top-level window receives the close notification and
+  ///     calls TryCloseBrowser() (which internally calls CloseBrowser(false)).
+  ///     TryCloseBrowser() returns false so the client cancels the window
+  ///     close.
+  /// 3.  JavaScript 'onbeforeunload' handler executes and shows the close
+  ///     confirmation dialog (which can be overridden via
+  ///     CefJSDialogHandler::OnBeforeUnloadDialog()).
+  /// 4.  User approves the close.
+  /// 5.  JavaScript 'onunload' handler executes.
+  /// 6.  CEF sends a close notification to the application's top-level window
+  ///     (because DoClose() returned false by default).
+  /// 7.  Application's top-level window receives the close notification and
+  ///     calls TryCloseBrowser(). TryCloseBrowser() returns true so the client
+  ///     allows the window close.
+  /// 8.  Application's top-level window is destroyed.
+  /// 9.  Application's OnBeforeClose() handler is called and the browser object
+  ///     is destroyed.
+  /// 10. Application exits by calling CefQuitMessageLoop() if no other browsers
+  ///     exist.
+  ///
+  /// Example 2: Using CefBrowserHost::CloseBrowser(false) and implementing the
+  /// DoClose() callback. This is recommended for clients using non-standard
+  /// close handling or windows that were not created on the browser process UI
+  /// thread.
+  /// 1.  User clicks the window close button which sends a close notification
+  ///     to the application's top-level window.
+  /// 2.  Application's top-level window receives the close notification and:
+  ///     A. Calls CefBrowserHost::CloseBrowser(false).
+  ///     B. Cancels the window close.
+  /// 3.  JavaScript 'onbeforeunload' handler executes and shows the close
+  ///     confirmation dialog (which can be overridden via
+  ///     CefJSDialogHandler::OnBeforeUnloadDialog()).
+  /// 4.  User approves the close.
+  /// 5.  JavaScript 'onunload' handler executes.
+  /// 6.  Application's DoClose() handler is called. Application will:
+  ///     A. Set a flag to indicate that the next close attempt will be allowed.
+  ///     B. Return false.
+  /// 7.  CEF sends an close notification to the application's top-level window.
+  /// 8.  Application's top-level window receives the close notification and
+  ///     allows the window to close based on the flag from #6B.
+  /// 9.  Application's top-level window is destroyed.
+  /// 10. Application's OnBeforeClose() handler is called and the browser object
+  ///     is destroyed.
+  /// 11. Application exits by calling CefQuitMessageLoop() if no other browsers
+  ///     exist.
   ///
   /*--cef()--*/
   virtual bool DoClose(CefRefPtr<CefBrowser> browser) { return false; }
 
   ///
-  // Called just before a browser is destroyed. Release all references to the
-  // browser object and do not attempt to execute any methods on the browser
-  // object (other than GetIdentifier or IsSame) after this callback returns.
-  // This callback will be the last notification that references |browser| on
-  // the UI thread. Any in-progress network requests associated with |browser|
-  // will be aborted when the browser is destroyed, and
-  // CefResourceRequestHandler callbacks related to those requests may still
-  // arrive on the IO thread after this method is called. See DoClose()
-  // documentation for additional usage information.
+  /// Called just before a browser is destroyed. Release all references to the
+  /// browser object and do not attempt to execute any methods on the browser
+  /// object (other than IsValid, GetIdentifier or IsSame) after this callback
+  /// returns. CefFrameHandler callbacks related to final main frame destruction
+  /// will arrive after this callback and CefBrowser::IsValid will return false
+  /// at that time. Any in-progress network requests associated with |browser|
+  /// will be aborted when the browser is destroyed, and
+  /// CefResourceRequestHandler callbacks related to those requests may still
+  /// arrive on the IO thread after this callback. See CefFrameHandler and
+  /// DoClose() documentation for additional usage information.
   ///
   /*--cef()--*/
   virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) {}
diff --git a/src/include/cef_load_handler.h b/src/include/cef_load_handler.h
index 66b5567..a7381d8 100644
--- a/src/include/cef_load_handler.h
+++ b/src/include/cef_load_handler.h
@@ -43,9 +43,9 @@
 #include "include/cef_frame.h"
 
 ///
-// Implement this interface to handle events related to browser load status. The
-// methods of this class will be called on the browser process UI thread or
-// render process main thread (TID_RENDERER).
+/// Implement this interface to handle events related to browser load status.
+/// The methods of this class will be called on the browser process UI thread or
+/// render process main thread (TID_RENDERER).
 ///
 /*--cef(source=client)--*/
 class CefLoadHandler : public virtual CefBaseRefCounted {
@@ -54,11 +54,11 @@
   typedef cef_transition_type_t TransitionType;
 
   ///
-  // Called when the loading state has changed. This callback will be executed
-  // twice -- once when loading is initiated either programmatically or by user
-  // action, and once when loading is terminated due to completion, cancellation
-  // of failure. It will be called before any calls to OnLoadStart and after all
-  // calls to OnLoadError and/or OnLoadEnd.
+  /// Called when the loading state has changed. This callback will be executed
+  /// twice -- once when loading is initiated either programmatically or by user
+  /// action, and once when loading is terminated due to completion,
+  /// cancellation of failure. It will be called before any calls to OnLoadStart
+  /// and after all calls to OnLoadError and/or OnLoadEnd.
   ///
   /*--cef()--*/
   virtual void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
@@ -67,16 +67,16 @@
                                     bool canGoForward) {}
 
   ///
-  // Called after a navigation has been committed and before the browser begins
-  // loading contents in the frame. The |frame| value will never be empty --
-  // call the IsMain() method to check if this frame is the main frame.
-  // |transition_type| provides information about the source of the navigation
-  // and an accurate value is only available in the browser process. Multiple
-  // frames may be loading at the same time. Sub-frames may start or continue
-  // loading after the main frame load has ended. This method will not be called
-  // for same page navigations (fragments, history state, etc.) or for
-  // navigations that fail or are canceled before commit. For notification of
-  // overall browser load status use OnLoadingStateChange instead.
+  /// Called after a navigation has been committed and before the browser begins
+  /// loading contents in the frame. The |frame| value will never be empty --
+  /// call the IsMain() method to check if this frame is the main frame.
+  /// |transition_type| provides information about the source of the navigation
+  /// and an accurate value is only available in the browser process. Multiple
+  /// frames may be loading at the same time. Sub-frames may start or continue
+  /// loading after the main frame load has ended. This method will not be
+  /// called for same page navigations (fragments, history state, etc.) or for
+  /// navigations that fail or are canceled before commit. For notification of
+  /// overall browser load status use OnLoadingStateChange instead.
   ///
   /*--cef()--*/
   virtual void OnLoadStart(CefRefPtr<CefBrowser> browser,
@@ -84,14 +84,14 @@
                            TransitionType transition_type) {}
 
   ///
-  // Called when the browser is done loading a frame. The |frame| value will
-  // never be empty -- call the IsMain() method to check if this frame is the
-  // main frame. Multiple frames may be loading at the same time. Sub-frames may
-  // start or continue loading after the main frame load has ended. This method
-  // will not be called for same page navigations (fragments, history state,
-  // etc.) or for navigations that fail or are canceled before commit. For
-  // notification of overall browser load status use OnLoadingStateChange
-  // instead.
+  /// Called when the browser is done loading a frame. The |frame| value will
+  /// never be empty -- call the IsMain() method to check if this frame is the
+  /// main frame. Multiple frames may be loading at the same time. Sub-frames
+  /// may start or continue loading after the main frame load has ended. This
+  /// method will not be called for same page navigations (fragments, history
+  /// state, etc.) or for navigations that fail or are canceled before commit.
+  /// For notification of overall browser load status use OnLoadingStateChange
+  /// instead.
   ///
   /*--cef()--*/
   virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
@@ -99,11 +99,12 @@
                          int httpStatusCode) {}
 
   ///
-  // Called when a navigation fails or is canceled. This method may be called
-  // by itself if before commit or in combination with OnLoadStart/OnLoadEnd if
-  // after commit. |errorCode| is the error code number, |errorText| is the
-  // error text and |failedUrl| is the URL that failed to load.
-  // See net\base\net_error_list.h for complete descriptions of the error codes.
+  /// Called when a navigation fails or is canceled. This method may be called
+  /// by itself if before commit or in combination with OnLoadStart/OnLoadEnd if
+  /// after commit. |errorCode| is the error code number, |errorText| is the
+  /// error text and |failedUrl| is the URL that failed to load.
+  /// See net\base\net_error_list.h for complete descriptions of the error
+  /// codes.
   ///
   /*--cef(optional_param=errorText)--*/
   virtual void OnLoadError(CefRefPtr<CefBrowser> browser,
diff --git a/src/include/cef_media_router.h b/src/include/cef_media_router.h
index 2c7cb59..eb9ea3f 100644
--- a/src/include/cef_media_router.h
+++ b/src/include/cef_media_router.h
@@ -40,6 +40,7 @@
 
 #include <vector>
 #include "include/cef_base.h"
+#include "include/cef_callback.h"
 #include "include/cef_registration.h"
 
 class CefMediaObserver;
@@ -50,51 +51,53 @@
 class CefMediaSource;
 
 ///
-// Supports discovery of and communication with media devices on the local
-// network via the Cast and DIAL protocols. The methods of this class may be
-// called on any browser process thread unless otherwise indicated.
+/// Supports discovery of and communication with media devices on the local
+/// network via the Cast and DIAL protocols. The methods of this class may be
+/// called on any browser process thread unless otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefMediaRouter : public virtual CefBaseRefCounted {
  public:
   ///
-  // Returns the MediaRouter object associated with the global request context.
-  // Equivalent to calling
-  // CefRequestContext::GetGlobalContext()->GetMediaRouter().
+  /// Returns the MediaRouter object associated with the global request context.
+  /// If |callback| is non-NULL it will be executed asnychronously on the UI
+  /// thread after the manager's storage has been initialized. Equivalent to
+  /// calling CefRequestContext::GetGlobalContext()->GetMediaRouter().
   ///
-  /*--cef()--*/
-  static CefRefPtr<CefMediaRouter> GetGlobalMediaRouter();
+  /*--cef(optional_param=callback)--*/
+  static CefRefPtr<CefMediaRouter> GetGlobalMediaRouter(
+      CefRefPtr<CefCompletionCallback> callback);
 
   ///
-  // Add an observer for MediaRouter events. The observer will remain registered
-  // until the returned Registration object is destroyed.
+  /// Add an observer for MediaRouter events. The observer will remain
+  /// registered until the returned Registration object is destroyed.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefRegistration> AddObserver(
       CefRefPtr<CefMediaObserver> observer) = 0;
 
   ///
-  // Returns a MediaSource object for the specified media source URN. Supported
-  // URN schemes include "cast:" and "dial:", and will be already known by the
-  // client application (e.g. "cast:<appId>?clientId=<clientId>").
+  /// Returns a MediaSource object for the specified media source URN. Supported
+  /// URN schemes include "cast:" and "dial:", and will be already known by the
+  /// client application (e.g. "cast:<appId>?clientId=<clientId>").
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefMediaSource> GetSource(const CefString& urn) = 0;
 
   ///
-  // Trigger an asynchronous call to CefMediaObserver::OnSinks on all
-  // registered observers.
+  /// Trigger an asynchronous call to CefMediaObserver::OnSinks on all
+  /// registered observers.
   ///
   /*--cef()--*/
   virtual void NotifyCurrentSinks() = 0;
 
   ///
-  // Create a new route between |source| and |sink|. Source and sink must be
-  // valid, compatible (as reported by CefMediaSink::IsCompatibleWith), and a
-  // route between them must not already exist. |callback| will be executed
-  // on success or failure. If route creation succeeds it will also trigger an
-  // asynchronous call to CefMediaObserver::OnRoutes on all registered
-  // observers.
+  /// Create a new route between |source| and |sink|. Source and sink must be
+  /// valid, compatible (as reported by CefMediaSink::IsCompatibleWith), and a
+  /// route between them must not already exist. |callback| will be executed
+  /// on success or failure. If route creation succeeds it will also trigger an
+  /// asynchronous call to CefMediaObserver::OnRoutes on all registered
+  /// observers.
   ///
   /*--cef()--*/
   virtual void CreateRoute(CefRefPtr<CefMediaSource> source,
@@ -102,17 +105,17 @@
                            CefRefPtr<CefMediaRouteCreateCallback> callback) = 0;
 
   ///
-  // Trigger an asynchronous call to CefMediaObserver::OnRoutes on all
-  // registered observers.
+  /// Trigger an asynchronous call to CefMediaObserver::OnRoutes on all
+  /// registered observers.
   ///
   /*--cef()--*/
   virtual void NotifyCurrentRoutes() = 0;
 };
 
 ///
-// Implemented by the client to observe MediaRouter events and registered via
-// CefMediaRouter::AddObserver. The methods of this class will be called on the
-// browser process UI thread.
+/// Implemented by the client to observe MediaRouter events and registered via
+/// CefMediaRouter::AddObserver. The methods of this class will be called on the
+/// browser process UI thread.
 ///
 /*--cef(source=client)--*/
 class CefMediaObserver : public virtual CefBaseRefCounted {
@@ -120,30 +123,30 @@
   typedef cef_media_route_connection_state_t ConnectionState;
 
   ///
-  // The list of available media sinks has changed or
-  // CefMediaRouter::NotifyCurrentSinks was called.
+  /// The list of available media sinks has changed or
+  /// CefMediaRouter::NotifyCurrentSinks was called.
   ///
   /*--cef()--*/
   virtual void OnSinks(const std::vector<CefRefPtr<CefMediaSink>>& sinks) = 0;
 
   ///
-  // The list of available media routes has changed or
-  // CefMediaRouter::NotifyCurrentRoutes was called.
+  /// The list of available media routes has changed or
+  /// CefMediaRouter::NotifyCurrentRoutes was called.
   ///
   /*--cef()--*/
   virtual void OnRoutes(
       const std::vector<CefRefPtr<CefMediaRoute>>& routes) = 0;
 
   ///
-  // The connection state of |route| has changed.
+  /// The connection state of |route| has changed.
   ///
   /*--cef()--*/
   virtual void OnRouteStateChanged(CefRefPtr<CefMediaRoute> route,
                                    ConnectionState state) = 0;
 
   ///
-  // A message was recieved over |route|. |message| is only valid for
-  // the scope of this callback and should be copied if necessary.
+  /// A message was recieved over |route|. |message| is only valid for
+  /// the scope of this callback and should be copied if necessary.
   ///
   /*--cef()--*/
   virtual void OnRouteMessageReceived(CefRefPtr<CefMediaRoute> route,
@@ -152,50 +155,50 @@
 };
 
 ///
-// Represents the route between a media source and sink. Instances of this
-// object are created via CefMediaRouter::CreateRoute and retrieved via
-// CefMediaObserver::OnRoutes. Contains the status and metadata of a
-// routing operation. The methods of this class may be called on any browser
-// process thread unless otherwise indicated.
+/// Represents the route between a media source and sink. Instances of this
+/// object are created via CefMediaRouter::CreateRoute and retrieved via
+/// CefMediaObserver::OnRoutes. Contains the status and metadata of a
+/// routing operation. The methods of this class may be called on any browser
+/// process thread unless otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefMediaRoute : public virtual CefBaseRefCounted {
  public:
   ///
-  // Returns the ID for this route.
+  /// Returns the ID for this route.
   ///
   /*--cef()--*/
   virtual CefString GetId() = 0;
 
   ///
-  // Returns the source associated with this route.
+  /// Returns the source associated with this route.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefMediaSource> GetSource() = 0;
 
   ///
-  // Returns the sink associated with this route.
+  /// Returns the sink associated with this route.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefMediaSink> GetSink() = 0;
 
   ///
-  // Send a message over this route. |message| will be copied if necessary.
+  /// Send a message over this route. |message| will be copied if necessary.
   ///
   /*--cef()--*/
   virtual void SendRouteMessage(const void* message, size_t message_size) = 0;
 
   ///
-  // Terminate this route. Will result in an asynchronous call to
-  // CefMediaObserver::OnRoutes on all registered observers.
+  /// Terminate this route. Will result in an asynchronous call to
+  /// CefMediaObserver::OnRoutes on all registered observers.
   ///
   /*--cef()--*/
   virtual void Terminate() = 0;
 };
 
 ///
-// Callback interface for CefMediaRouter::CreateRoute. The methods of this
-// class will be called on the browser process UI thread.
+/// Callback interface for CefMediaRouter::CreateRoute. The methods of this
+/// class will be called on the browser process UI thread.
 ///
 /*--cef(source=client)--*/
 class CefMediaRouteCreateCallback : public virtual CefBaseRefCounted {
@@ -203,10 +206,10 @@
   typedef cef_media_route_create_result_t RouteCreateResult;
 
   ///
-  // Method that will be executed when the route creation has finished. |result|
-  // will be CEF_MRCR_OK if the route creation succeeded. |error| will be a
-  // description of the error if the route creation failed. |route| is the
-  // resulting route, or empty if the route creation failed.
+  /// Method that will be executed when the route creation has finished.
+  /// |result| will be CEF_MRCR_OK if the route creation succeeded. |error| will
+  /// be a description of the error if the route creation failed. |route| is the
+  /// resulting route, or empty if the route creation failed.
   ///
   /*--cef(optional_param=error,optional_param=route)--*/
   virtual void OnMediaRouteCreateFinished(RouteCreateResult result,
@@ -215,9 +218,9 @@
 };
 
 ///
-// Represents a sink to which media can be routed. Instances of this object are
-// retrieved via CefMediaObserver::OnSinks. The methods of this class may
-// be called on any browser process thread unless otherwise indicated.
+/// Represents a sink to which media can be routed. Instances of this object are
+/// retrieved via CefMediaObserver::OnSinks. The methods of this class may
+/// be called on any browser process thread unless otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefMediaSink : public virtual CefBaseRefCounted {
@@ -225,71 +228,59 @@
   typedef cef_media_sink_icon_type_t IconType;
 
   ///
-  // Returns the ID for this sink.
+  /// Returns the ID for this sink.
   ///
   /*--cef()--*/
   virtual CefString GetId() = 0;
 
   ///
-  // Returns true if this sink is valid.
-  ///
-  /*--cef()--*/
-  virtual bool IsValid() = 0;
-
-  ///
-  // Returns the name of this sink.
+  /// Returns the name of this sink.
   ///
   /*--cef()--*/
   virtual CefString GetName() = 0;
 
   ///
-  // Returns the description of this sink.
-  ///
-  /*--cef()--*/
-  virtual CefString GetDescription() = 0;
-
-  ///
-  // Returns the icon type for this sink.
+  /// Returns the icon type for this sink.
   ///
   /*--cef(default_retval=CEF_MSIT_GENERIC)--*/
   virtual IconType GetIconType() = 0;
 
   ///
-  // Asynchronously retrieves device info.
+  /// Asynchronously retrieves device info.
   ///
   /*--cef()--*/
   virtual void GetDeviceInfo(
       CefRefPtr<CefMediaSinkDeviceInfoCallback> callback) = 0;
 
   ///
-  // Returns true if this sink accepts content via Cast.
+  /// Returns true if this sink accepts content via Cast.
   ///
   /*--cef()--*/
   virtual bool IsCastSink() = 0;
 
   ///
-  // Returns true if this sink accepts content via DIAL.
+  /// Returns true if this sink accepts content via DIAL.
   ///
   /*--cef()--*/
   virtual bool IsDialSink() = 0;
 
   ///
-  // Returns true if this sink is compatible with |source|.
+  /// Returns true if this sink is compatible with |source|.
   ///
   /*--cef()--*/
   virtual bool IsCompatibleWith(CefRefPtr<CefMediaSource> source) = 0;
 };
 
 ///
-// Callback interface for CefMediaSink::GetDeviceInfo. The methods of this
-// class will be called on the browser process UI thread.
+/// Callback interface for CefMediaSink::GetDeviceInfo. The methods of this
+/// class will be called on the browser process UI thread.
 ///
 /*--cef(source=client)--*/
 class CefMediaSinkDeviceInfoCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Method that will be executed asyncronously once device information has been
-  // retrieved.
+  /// Method that will be executed asyncronously once device information has
+  /// been retrieved.
   ///
   /*--cef()--*/
   virtual void OnMediaSinkDeviceInfo(
@@ -297,33 +288,27 @@
 };
 
 ///
-// Represents a source from which media can be routed. Instances of this object
-// are retrieved via CefMediaRouter::GetSource. The methods of this class may be
-// called on any browser process thread unless otherwise indicated.
+/// Represents a source from which media can be routed. Instances of this object
+/// are retrieved via CefMediaRouter::GetSource. The methods of this class may
+/// be called on any browser process thread unless otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefMediaSource : public virtual CefBaseRefCounted {
  public:
   ///
-  // Returns the ID (media source URN or URL) for this source.
+  /// Returns the ID (media source URN or URL) for this source.
   ///
   /*--cef()--*/
   virtual CefString GetId() = 0;
 
   ///
-  // Returns true if this source is valid.
-  ///
-  /*--cef()--*/
-  virtual bool IsValid() = 0;
-
-  ///
-  // Returns true if this source outputs its content via Cast.
+  /// Returns true if this source outputs its content via Cast.
   ///
   /*--cef()--*/
   virtual bool IsCastSource() = 0;
 
   ///
-  // Returns true if this source outputs its content via DIAL.
+  /// Returns true if this source outputs its content via DIAL.
   ///
   /*--cef()--*/
   virtual bool IsDialSource() = 0;
diff --git a/src/include/cef_menu_model.h b/src/include/cef_menu_model.h
index 1c9a7c0..4ddc54a 100644
--- a/src/include/cef_menu_model.h
+++ b/src/include/cef_menu_model.h
@@ -42,10 +42,10 @@
 #include "include/cef_menu_model_delegate.h"
 
 ///
-// Supports creation and modification of menus. See cef_menu_id_t for the
-// command ids that have default implementations. All user-defined command ids
-// should be between MENU_ID_USER_FIRST and MENU_ID_USER_LAST. The methods of
-// this class can only be accessed on the browser process the UI thread.
+/// Supports creation and modification of menus. See cef_menu_id_t for the
+/// command ids that have default implementations. All user-defined command ids
+/// should be between MENU_ID_USER_FIRST and MENU_ID_USER_LAST. The methods of
+/// this class can only be accessed on the browser process the UI thread.
 ///
 /*--cef(source=library)--*/
 class CefMenuModel : public virtual CefBaseRefCounted {
@@ -53,50 +53,50 @@
   typedef cef_menu_item_type_t MenuItemType;
 
   ///
-  // Create a new MenuModel with the specified |delegate|.
+  /// Create a new MenuModel with the specified |delegate|.
   ///
   /*--cef()--*/
   static CefRefPtr<CefMenuModel> CreateMenuModel(
       CefRefPtr<CefMenuModelDelegate> delegate);
 
   ///
-  // Returns true if this menu is a submenu.
+  /// Returns true if this menu is a submenu.
   ///
   /*--cef()--*/
   virtual bool IsSubMenu() = 0;
 
   ///
-  // Clears the menu. Returns true on success.
+  /// Clears the menu. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool Clear() = 0;
 
   ///
-  // Returns the number of items in this menu.
+  /// Returns the number of items in this menu.
   ///
   /*--cef()--*/
-  virtual int GetCount() = 0;
+  virtual size_t GetCount() = 0;
 
   ///
-  // Add a separator to the menu. Returns true on success.
+  /// Add a separator to the menu. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool AddSeparator() = 0;
 
   ///
-  // Add an item to the menu. Returns true on success.
+  /// Add an item to the menu. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool AddItem(int command_id, const CefString& label) = 0;
 
   ///
-  // Add a check item to the menu. Returns true on success.
+  /// Add a check item to the menu. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool AddCheckItem(int command_id, const CefString& label) = 0;
   ///
-  // Add a radio item to the menu. Only a single item with the specified
-  // |group_id| can be checked at a time. Returns true on success.
+  /// Add a radio item to the menu. Only a single item with the specified
+  /// |group_id| can be checked at a time. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool AddRadioItem(int command_id,
@@ -104,257 +104,257 @@
                             int group_id) = 0;
 
   ///
-  // Add a sub-menu to the menu. The new sub-menu is returned.
+  /// Add a sub-menu to the menu. The new sub-menu is returned.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefMenuModel> AddSubMenu(int command_id,
                                              const CefString& label) = 0;
 
   ///
-  // Insert a separator in the menu at the specified |index|. Returns true on
-  // success.
+  /// Insert a separator in the menu at the specified |index|. Returns true on
+  /// success.
   ///
   /*--cef()--*/
-  virtual bool InsertSeparatorAt(int index) = 0;
+  virtual bool InsertSeparatorAt(size_t index) = 0;
 
   ///
-  // Insert an item in the menu at the specified |index|. Returns true on
-  // success.
+  /// Insert an item in the menu at the specified |index|. Returns true on
+  /// success.
   ///
   /*--cef()--*/
-  virtual bool InsertItemAt(int index,
+  virtual bool InsertItemAt(size_t index,
                             int command_id,
                             const CefString& label) = 0;
 
   ///
-  // Insert a check item in the menu at the specified |index|. Returns true on
-  // success.
+  /// Insert a check item in the menu at the specified |index|. Returns true on
+  /// success.
   ///
   /*--cef()--*/
-  virtual bool InsertCheckItemAt(int index,
+  virtual bool InsertCheckItemAt(size_t index,
                                  int command_id,
                                  const CefString& label) = 0;
 
   ///
-  // Insert a radio item in the menu at the specified |index|. Only a single
-  // item with the specified |group_id| can be checked at a time. Returns true
-  // on success.
+  /// Insert a radio item in the menu at the specified |index|. Only a single
+  /// item with the specified |group_id| can be checked at a time. Returns true
+  /// on success.
   ///
   /*--cef()--*/
-  virtual bool InsertRadioItemAt(int index,
+  virtual bool InsertRadioItemAt(size_t index,
                                  int command_id,
                                  const CefString& label,
                                  int group_id) = 0;
 
   ///
-  // Insert a sub-menu in the menu at the specified |index|. The new sub-menu
-  // is returned.
+  /// Insert a sub-menu in the menu at the specified |index|. The new sub-menu
+  /// is returned.
   ///
   /*--cef()--*/
-  virtual CefRefPtr<CefMenuModel> InsertSubMenuAt(int index,
+  virtual CefRefPtr<CefMenuModel> InsertSubMenuAt(size_t index,
                                                   int command_id,
                                                   const CefString& label) = 0;
 
   ///
-  // Removes the item with the specified |command_id|. Returns true on success.
+  /// Removes the item with the specified |command_id|. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool Remove(int command_id) = 0;
 
   ///
-  // Removes the item at the specified |index|. Returns true on success.
+  /// Removes the item at the specified |index|. Returns true on success.
   ///
   /*--cef()--*/
-  virtual bool RemoveAt(int index) = 0;
+  virtual bool RemoveAt(size_t index) = 0;
 
   ///
-  // Returns the index associated with the specified |command_id| or -1 if not
-  // found due to the command id not existing in the menu.
+  /// Returns the index associated with the specified |command_id| or -1 if not
+  /// found due to the command id not existing in the menu.
   ///
   /*--cef()--*/
   virtual int GetIndexOf(int command_id) = 0;
 
   ///
-  // Returns the command id at the specified |index| or -1 if not found due to
-  // invalid range or the index being a separator.
+  /// Returns the command id at the specified |index| or -1 if not found due to
+  /// invalid range or the index being a separator.
   ///
   /*--cef()--*/
-  virtual int GetCommandIdAt(int index) = 0;
+  virtual int GetCommandIdAt(size_t index) = 0;
 
   ///
-  // Sets the command id at the specified |index|. Returns true on success.
+  /// Sets the command id at the specified |index|. Returns true on success.
   ///
   /*--cef()--*/
-  virtual bool SetCommandIdAt(int index, int command_id) = 0;
+  virtual bool SetCommandIdAt(size_t index, int command_id) = 0;
 
   ///
-  // Returns the label for the specified |command_id| or empty if not found.
+  /// Returns the label for the specified |command_id| or empty if not found.
   ///
   /*--cef()--*/
   virtual CefString GetLabel(int command_id) = 0;
 
   ///
-  // Returns the label at the specified |index| or empty if not found due to
-  // invalid range or the index being a separator.
+  /// Returns the label at the specified |index| or empty if not found due to
+  /// invalid range or the index being a separator.
   ///
   /*--cef()--*/
-  virtual CefString GetLabelAt(int index) = 0;
+  virtual CefString GetLabelAt(size_t index) = 0;
 
   ///
-  // Sets the label for the specified |command_id|. Returns true on success.
+  /// Sets the label for the specified |command_id|. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool SetLabel(int command_id, const CefString& label) = 0;
 
   ///
-  // Set the label at the specified |index|. Returns true on success.
+  /// Set the label at the specified |index|. Returns true on success.
   ///
   /*--cef()--*/
-  virtual bool SetLabelAt(int index, const CefString& label) = 0;
+  virtual bool SetLabelAt(size_t index, const CefString& label) = 0;
 
   ///
-  // Returns the item type for the specified |command_id|.
+  /// Returns the item type for the specified |command_id|.
   ///
   /*--cef(default_retval=MENUITEMTYPE_NONE)--*/
   virtual MenuItemType GetType(int command_id) = 0;
 
   ///
-  // Returns the item type at the specified |index|.
+  /// Returns the item type at the specified |index|.
   ///
   /*--cef(default_retval=MENUITEMTYPE_NONE)--*/
-  virtual MenuItemType GetTypeAt(int index) = 0;
+  virtual MenuItemType GetTypeAt(size_t index) = 0;
 
   ///
-  // Returns the group id for the specified |command_id| or -1 if invalid.
+  /// Returns the group id for the specified |command_id| or -1 if invalid.
   ///
   /*--cef()--*/
   virtual int GetGroupId(int command_id) = 0;
 
   ///
-  // Returns the group id at the specified |index| or -1 if invalid.
+  /// Returns the group id at the specified |index| or -1 if invalid.
   ///
   /*--cef()--*/
-  virtual int GetGroupIdAt(int index) = 0;
+  virtual int GetGroupIdAt(size_t index) = 0;
 
   ///
-  // Sets the group id for the specified |command_id|. Returns true on success.
+  /// Sets the group id for the specified |command_id|. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool SetGroupId(int command_id, int group_id) = 0;
 
   ///
-  // Sets the group id at the specified |index|. Returns true on success.
+  /// Sets the group id at the specified |index|. Returns true on success.
   ///
   /*--cef()--*/
-  virtual bool SetGroupIdAt(int index, int group_id) = 0;
+  virtual bool SetGroupIdAt(size_t index, int group_id) = 0;
 
   ///
-  // Returns the submenu for the specified |command_id| or empty if invalid.
+  /// Returns the submenu for the specified |command_id| or empty if invalid.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefMenuModel> GetSubMenu(int command_id) = 0;
 
   ///
-  // Returns the submenu at the specified |index| or empty if invalid.
+  /// Returns the submenu at the specified |index| or empty if invalid.
   ///
   /*--cef()--*/
-  virtual CefRefPtr<CefMenuModel> GetSubMenuAt(int index) = 0;
+  virtual CefRefPtr<CefMenuModel> GetSubMenuAt(size_t index) = 0;
 
   ///
-  // Returns true if the specified |command_id| is visible.
+  /// Returns true if the specified |command_id| is visible.
   ///
   /*--cef()--*/
   virtual bool IsVisible(int command_id) = 0;
 
   ///
-  // Returns true if the specified |index| is visible.
+  /// Returns true if the specified |index| is visible.
   ///
   /*--cef()--*/
-  virtual bool IsVisibleAt(int index) = 0;
+  virtual bool IsVisibleAt(size_t index) = 0;
 
   ///
-  // Change the visibility of the specified |command_id|. Returns true on
-  // success.
+  /// Change the visibility of the specified |command_id|. Returns true on
+  /// success.
   ///
   /*--cef()--*/
   virtual bool SetVisible(int command_id, bool visible) = 0;
 
   ///
-  // Change the visibility at the specified |index|. Returns true on success.
+  /// Change the visibility at the specified |index|. Returns true on success.
   ///
   /*--cef()--*/
-  virtual bool SetVisibleAt(int index, bool visible) = 0;
+  virtual bool SetVisibleAt(size_t index, bool visible) = 0;
 
   ///
-  // Returns true if the specified |command_id| is enabled.
+  /// Returns true if the specified |command_id| is enabled.
   ///
   /*--cef()--*/
   virtual bool IsEnabled(int command_id) = 0;
 
   ///
-  // Returns true if the specified |index| is enabled.
+  /// Returns true if the specified |index| is enabled.
   ///
   /*--cef()--*/
-  virtual bool IsEnabledAt(int index) = 0;
+  virtual bool IsEnabledAt(size_t index) = 0;
 
   ///
-  // Change the enabled status of the specified |command_id|. Returns true on
-  // success.
+  /// Change the enabled status of the specified |command_id|. Returns true on
+  /// success.
   ///
   /*--cef()--*/
   virtual bool SetEnabled(int command_id, bool enabled) = 0;
 
   ///
-  // Change the enabled status at the specified |index|. Returns true on
-  // success.
+  /// Change the enabled status at the specified |index|. Returns true on
+  /// success.
   ///
   /*--cef()--*/
-  virtual bool SetEnabledAt(int index, bool enabled) = 0;
+  virtual bool SetEnabledAt(size_t index, bool enabled) = 0;
 
   ///
-  // Returns true if the specified |command_id| is checked. Only applies to
-  // check and radio items.
+  /// Returns true if the specified |command_id| is checked. Only applies to
+  /// check and radio items.
   ///
   /*--cef()--*/
   virtual bool IsChecked(int command_id) = 0;
 
   ///
-  // Returns true if the specified |index| is checked. Only applies to check
-  // and radio items.
+  /// Returns true if the specified |index| is checked. Only applies to check
+  /// and radio items.
   ///
   /*--cef()--*/
-  virtual bool IsCheckedAt(int index) = 0;
+  virtual bool IsCheckedAt(size_t index) = 0;
 
   ///
-  // Check the specified |command_id|. Only applies to check and radio items.
-  // Returns true on success.
+  /// Check the specified |command_id|. Only applies to check and radio items.
+  /// Returns true on success.
   ///
   /*--cef()--*/
   virtual bool SetChecked(int command_id, bool checked) = 0;
 
   ///
-  // Check the specified |index|. Only applies to check and radio items. Returns
-  // true on success.
+  /// Check the specified |index|. Only applies to check and radio items.
+  /// Returns true on success.
   ///
   /*--cef()--*/
-  virtual bool SetCheckedAt(int index, bool checked) = 0;
+  virtual bool SetCheckedAt(size_t index, bool checked) = 0;
 
   ///
-  // Returns true if the specified |command_id| has a keyboard accelerator
-  // assigned.
+  /// Returns true if the specified |command_id| has a keyboard accelerator
+  /// assigned.
   ///
   /*--cef()--*/
   virtual bool HasAccelerator(int command_id) = 0;
 
   ///
-  // Returns true if the specified |index| has a keyboard accelerator assigned.
+  /// Returns true if the specified |index| has a keyboard accelerator assigned.
   ///
   /*--cef()--*/
-  virtual bool HasAcceleratorAt(int index) = 0;
+  virtual bool HasAcceleratorAt(size_t index) = 0;
 
   ///
-  // Set the keyboard accelerator for the specified |command_id|. |key_code| can
-  // be any virtual key or character value. Returns true on success.
+  /// Set the keyboard accelerator for the specified |command_id|. |key_code|
+  /// can be any virtual key or character value. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool SetAccelerator(int command_id,
@@ -364,33 +364,33 @@
                               bool alt_pressed) = 0;
 
   ///
-  // Set the keyboard accelerator at the specified |index|. |key_code| can be
-  // any virtual key or character value. Returns true on success.
+  /// Set the keyboard accelerator at the specified |index|. |key_code| can be
+  /// any virtual key or character value. Returns true on success.
   ///
   /*--cef()--*/
-  virtual bool SetAcceleratorAt(int index,
+  virtual bool SetAcceleratorAt(size_t index,
                                 int key_code,
                                 bool shift_pressed,
                                 bool ctrl_pressed,
                                 bool alt_pressed) = 0;
 
   ///
-  // Remove the keyboard accelerator for the specified |command_id|. Returns
-  // true on success.
+  /// Remove the keyboard accelerator for the specified |command_id|. Returns
+  /// true on success.
   ///
   /*--cef()--*/
   virtual bool RemoveAccelerator(int command_id) = 0;
 
   ///
-  // Remove the keyboard accelerator at the specified |index|. Returns true on
-  // success.
+  /// Remove the keyboard accelerator at the specified |index|. Returns true on
+  /// success.
   ///
   /*--cef()--*/
-  virtual bool RemoveAcceleratorAt(int index) = 0;
+  virtual bool RemoveAcceleratorAt(size_t index) = 0;
 
   ///
-  // Retrieves the keyboard accelerator for the specified |command_id|. Returns
-  // true on success.
+  /// Retrieves the keyboard accelerator for the specified |command_id|. Returns
+  /// true on success.
   ///
   /*--cef()--*/
   virtual bool GetAccelerator(int command_id,
@@ -400,21 +400,21 @@
                               bool& alt_pressed) = 0;
 
   ///
-  // Retrieves the keyboard accelerator for the specified |index|. Returns true
-  // on success.
+  /// Retrieves the keyboard accelerator for the specified |index|. Returns true
+  /// on success.
   ///
   /*--cef()--*/
-  virtual bool GetAcceleratorAt(int index,
+  virtual bool GetAcceleratorAt(size_t index,
                                 int& key_code,
                                 bool& shift_pressed,
                                 bool& ctrl_pressed,
                                 bool& alt_pressed) = 0;
 
   ///
-  // Set the explicit color for |command_id| and |color_type| to |color|.
-  // Specify a |color| value of 0 to remove the explicit color. If no explicit
-  // color or default color is set for |color_type| then the system color will
-  // be used. Returns true on success.
+  /// Set the explicit color for |command_id| and |color_type| to |color|.
+  /// Specify a |color| value of 0 to remove the explicit color. If no explicit
+  /// color or default color is set for |color_type| then the system color will
+  /// be used. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool SetColor(int command_id,
@@ -422,11 +422,11 @@
                         cef_color_t color) = 0;
 
   ///
-  // Set the explicit color for |command_id| and |index| to |color|. Specify a
-  // |color| value of 0 to remove the explicit color. Specify an |index| value
-  // of -1 to set the default color for items that do not have an explicit
-  // color set. If no explicit color or default color is set for |color_type|
-  // then the system color will be used. Returns true on success.
+  /// Set the explicit color for |command_id| and |index| to |color|. Specify a
+  /// |color| value of 0 to remove the explicit color. Specify an |index| value
+  /// of -1 to set the default color for items that do not have an explicit
+  /// color set. If no explicit color or default color is set for |color_type|
+  /// then the system color will be used. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool SetColorAt(int index,
@@ -434,9 +434,9 @@
                           cef_color_t color) = 0;
 
   ///
-  // Returns in |color| the color that was explicitly set for |command_id| and
-  // |color_type|. If a color was not set then 0 will be returned in |color|.
-  // Returns true on success.
+  /// Returns in |color| the color that was explicitly set for |command_id| and
+  /// |color_type|. If a color was not set then 0 will be returned in |color|.
+  /// Returns true on success.
   ///
   /*--cef()--*/
   virtual bool GetColor(int command_id,
@@ -444,10 +444,10 @@
                         cef_color_t& color) = 0;
 
   ///
-  // Returns in |color| the color that was explicitly set for |command_id| and
-  // |color_type|. Specify an |index| value of -1 to return the default color
-  // in |color|. If a color was not set then 0 will be returned in |color|.
-  // Returns true on success.
+  /// Returns in |color| the color that was explicitly set for |command_id| and
+  /// |color_type|. Specify an |index| value of -1 to return the default color
+  /// in |color|. If a color was not set then 0 will be returned in |color|.
+  /// Returns true on success.
   ///
   /*--cef()--*/
   virtual bool GetColorAt(int index,
@@ -455,34 +455,34 @@
                           cef_color_t& color) = 0;
 
   ///
-  // Sets the font list for the specified |command_id|. If |font_list| is empty
-  // the system font will be used. Returns true on success. The format is
-  // "<FONT_FAMILY_LIST>,[STYLES] <SIZE>", where:
-  // - FONT_FAMILY_LIST is a comma-separated list of font family names,
-  // - STYLES is an optional space-separated list of style names (case-sensitive
-  //   "Bold" and "Italic" are supported), and
-  // - SIZE is an integer font size in pixels with the suffix "px".
-  //
-  // Here are examples of valid font description strings:
-  // - "Arial, Helvetica, Bold Italic 14px"
-  // - "Arial, 14px"
+  /// Sets the font list for the specified |command_id|. If |font_list| is empty
+  /// the system font will be used. Returns true on success. The format is
+  /// "<FONT_FAMILY_LIST>,[STYLES] <SIZE>", where:
+  /// - FONT_FAMILY_LIST is a comma-separated list of font family names,
+  /// - STYLES is an optional space-separated list of style names
+  ///   (case-sensitive "Bold" and "Italic" are supported), and
+  /// - SIZE is an integer font size in pixels with the suffix "px".
+  ///
+  /// Here are examples of valid font description strings:
+  /// - "Arial, Helvetica, Bold Italic 14px"
+  /// - "Arial, 14px"
   ///
   /*--cef(optional_param=font_list)--*/
   virtual bool SetFontList(int command_id, const CefString& font_list) = 0;
 
   ///
-  // Sets the font list for the specified |index|. Specify an |index| value of
-  // -1 to set the default font. If |font_list| is empty the system font will
-  // be used. Returns true on success. The format is
-  // "<FONT_FAMILY_LIST>,[STYLES] <SIZE>", where:
-  // - FONT_FAMILY_LIST is a comma-separated list of font family names,
-  // - STYLES is an optional space-separated list of style names (case-sensitive
-  //   "Bold" and "Italic" are supported), and
-  // - SIZE is an integer font size in pixels with the suffix "px".
-  //
-  // Here are examples of valid font description strings:
-  // - "Arial, Helvetica, Bold Italic 14px"
-  // - "Arial, 14px"
+  /// Sets the font list for the specified |index|. Specify an |index| value of
+  /// -1 to set the default font. If |font_list| is empty the system font will
+  /// be used. Returns true on success. The format is
+  /// "<FONT_FAMILY_LIST>,[STYLES] <SIZE>", where:
+  /// - FONT_FAMILY_LIST is a comma-separated list of font family names,
+  /// - STYLES is an optional space-separated list of style names
+  ///   (case-sensitive "Bold" and "Italic" are supported), and
+  /// - SIZE is an integer font size in pixels with the suffix "px".
+  ///
+  /// Here are examples of valid font description strings:
+  /// - "Arial, Helvetica, Bold Italic 14px"
+  /// - "Arial, 14px"
   ///
   /*--cef(optional_param=font_list)--*/
   virtual bool SetFontListAt(int index, const CefString& font_list) = 0;
diff --git a/src/include/cef_menu_model_delegate.h b/src/include/cef_menu_model_delegate.h
index e3ddfbd..c648230 100644
--- a/src/include/cef_menu_model_delegate.h
+++ b/src/include/cef_menu_model_delegate.h
@@ -43,16 +43,16 @@
 class CefMenuModel;
 
 ///
-// Implement this interface to handle menu model events. The methods of this
-// class will be called on the browser process UI thread unless otherwise
-// indicated.
+/// Implement this interface to handle menu model events. The methods of this
+/// class will be called on the browser process UI thread unless otherwise
+/// indicated.
 ///
 /*--cef(source=client)--*/
 class CefMenuModelDelegate : public virtual CefBaseRefCounted {
  public:
   ///
-  // Perform the action associated with the specified |command_id| and
-  // optional |event_flags|.
+  /// Perform the action associated with the specified |command_id| and
+  /// optional |event_flags|.
   ///
   /*--cef()--*/
   virtual void ExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
@@ -60,43 +60,43 @@
                               cef_event_flags_t event_flags) = 0;
 
   ///
-  // Called when the user moves the mouse outside the menu and over the owning
-  // window.
+  /// Called when the user moves the mouse outside the menu and over the owning
+  /// window.
   ///
   /*--cef()--*/
   virtual void MouseOutsideMenu(CefRefPtr<CefMenuModel> menu_model,
                                 const CefPoint& screen_point) {}
 
   ///
-  // Called on unhandled open submenu keyboard commands. |is_rtl| will be true
-  // if the menu is displaying a right-to-left language.
+  /// Called on unhandled open submenu keyboard commands. |is_rtl| will be true
+  /// if the menu is displaying a right-to-left language.
   ///
   /*--cef()--*/
   virtual void UnhandledOpenSubmenu(CefRefPtr<CefMenuModel> menu_model,
                                     bool is_rtl) {}
 
   ///
-  // Called on unhandled close submenu keyboard commands. |is_rtl| will be true
-  // if the menu is displaying a right-to-left language.
+  /// Called on unhandled close submenu keyboard commands. |is_rtl| will be true
+  /// if the menu is displaying a right-to-left language.
   ///
   /*--cef()--*/
   virtual void UnhandledCloseSubmenu(CefRefPtr<CefMenuModel> menu_model,
                                      bool is_rtl) {}
 
   ///
-  // The menu is about to show.
+  /// The menu is about to show.
   ///
   /*--cef()--*/
   virtual void MenuWillShow(CefRefPtr<CefMenuModel> menu_model) {}
 
   ///
-  // The menu has closed.
+  /// The menu has closed.
   ///
   /*--cef()--*/
   virtual void MenuClosed(CefRefPtr<CefMenuModel> menu_model) {}
 
   ///
-  // Optionally modify a menu item label. Return true if |label| was modified.
+  /// Optionally modify a menu item label. Return true if |label| was modified.
   ///
   /*--cef()--*/
   virtual bool FormatLabel(CefRefPtr<CefMenuModel> menu_model,
diff --git a/src/include/cef_navigation_entry.h b/src/include/cef_navigation_entry.h
index 292f5b6..a8e2f33 100644
--- a/src/include/cef_navigation_entry.h
+++ b/src/include/cef_navigation_entry.h
@@ -42,7 +42,7 @@
 #include "include/cef_ssl_status.h"
 
 ///
-// Class used to represent an entry in navigation history.
+/// Class used to represent an entry in navigation history.
 ///
 /*--cef(source=library)--*/
 class CefNavigationEntry : public virtual CefBaseRefCounted {
@@ -50,68 +50,69 @@
   typedef cef_transition_type_t TransitionType;
 
   ///
-  // Returns true if this object is valid. Do not call any other methods if this
-  // function returns false.
+  /// Returns true if this object is valid. Do not call any other methods if
+  /// this function returns false.
   ///
   /*--cef()--*/
   virtual bool IsValid() = 0;
 
   ///
-  // Returns the actual URL of the page. For some pages this may be data: URL or
-  // similar. Use GetDisplayURL() to return a display-friendly version.
+  /// Returns the actual URL of the page. For some pages this may be data: URL
+  /// or similar. Use GetDisplayURL() to return a display-friendly version.
   ///
   /*--cef()--*/
   virtual CefString GetURL() = 0;
 
   ///
-  // Returns a display-friendly version of the URL.
+  /// Returns a display-friendly version of the URL.
   ///
   /*--cef()--*/
   virtual CefString GetDisplayURL() = 0;
 
   ///
-  // Returns the original URL that was entered by the user before any redirects.
+  /// Returns the original URL that was entered by the user before any
+  /// redirects.
   ///
   /*--cef()--*/
   virtual CefString GetOriginalURL() = 0;
 
   ///
-  // Returns the title set by the page. This value may be empty.
+  /// Returns the title set by the page. This value may be empty.
   ///
   /*--cef()--*/
   virtual CefString GetTitle() = 0;
 
   ///
-  // Returns the transition type which indicates what the user did to move to
-  // this page from the previous page.
+  /// Returns the transition type which indicates what the user did to move to
+  /// this page from the previous page.
   ///
   /*--cef(default_retval=TT_EXPLICIT)--*/
   virtual TransitionType GetTransitionType() = 0;
 
   ///
-  // Returns true if this navigation includes post data.
+  /// Returns true if this navigation includes post data.
   ///
   /*--cef()--*/
   virtual bool HasPostData() = 0;
 
   ///
-  // Returns the time for the last known successful navigation completion. A
-  // navigation may be completed more than once if the page is reloaded. May be
-  // 0 if the navigation has not yet completed.
+  /// Returns the time for the last known successful navigation completion. A
+  /// navigation may be completed more than once if the page is reloaded. May be
+  /// 0 if the navigation has not yet completed.
   ///
   /*--cef()--*/
-  virtual CefTime GetCompletionTime() = 0;
+  virtual CefBaseTime GetCompletionTime() = 0;
 
   ///
-  // Returns the HTTP status code for the last known successful navigation
-  // response. May be 0 if the response has not yet been received or if the
-  // navigation has not yet completed.
+  /// Returns the HTTP status code for the last known successful navigation
+  /// response. May be 0 if the response has not yet been received or if the
+  /// navigation has not yet completed.
   ///
   /*--cef()--*/
   virtual int GetHttpStatusCode() = 0;
 
   ///
-  // Returns the SSL information for this navigation entry.
+  /// Returns the SSL information for this navigation entry.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefSSLStatus> GetSSLStatus() = 0;
diff --git a/src/include/cef_origin_whitelist.h b/src/include/cef_origin_whitelist.h
index ad17318..e684ef6 100644
--- a/src/include/cef_origin_whitelist.h
+++ b/src/include/cef_origin_whitelist.h
@@ -41,40 +41,41 @@
 #include "include/cef_base.h"
 
 ///
-// Add an entry to the cross-origin access whitelist.
-//
-// The same-origin policy restricts how scripts hosted from different origins
-// (scheme + domain + port) can communicate. By default, scripts can only access
-// resources with the same origin. Scripts hosted on the HTTP and HTTPS schemes
-// (but no other schemes) can use the "Access-Control-Allow-Origin" header to
-// allow cross-origin requests. For example, https://source.example.com can make
-// XMLHttpRequest requests on http://target.example.com if the
-// http://target.example.com request returns an "Access-Control-Allow-Origin:
-// https://source.example.com" response header.
-//
-// Scripts in separate frames or iframes and hosted from the same protocol and
-// domain suffix can execute cross-origin JavaScript if both pages set the
-// document.domain value to the same domain suffix. For example,
-// scheme://foo.example.com and scheme://bar.example.com can communicate using
-// JavaScript if both domains set document.domain="example.com".
-//
-// This method is used to allow access to origins that would otherwise violate
-// the same-origin policy. Scripts hosted underneath the fully qualified
-// |source_origin| URL (like http://www.example.com) will be allowed access to
-// all resources hosted on the specified |target_protocol| and |target_domain|.
-// If |target_domain| is non-empty and |allow_target_subdomains| if false only
-// exact domain matches will be allowed. If |target_domain| contains a top-
-// level domain component (like "example.com") and |allow_target_subdomains| is
-// true sub-domain matches will be allowed. If |target_domain| is empty and
-// |allow_target_subdomains| if true all domains and IP addresses will be
-// allowed.
-//
-// This method cannot be used to bypass the restrictions on local or display
-// isolated schemes. See the comments on CefRegisterCustomScheme for more
-// information.
-//
-// This function may be called on any thread. Returns false if |source_origin|
-// is invalid or the whitelist cannot be accessed.
+/// Add an entry to the cross-origin access whitelist.
+///
+/// The same-origin policy restricts how scripts hosted from different origins
+/// (scheme + domain + port) can communicate. By default, scripts can only
+/// access resources with the same origin. Scripts hosted on the HTTP and HTTPS
+/// schemes (but no other schemes) can use the "Access-Control-Allow-Origin"
+/// header to allow cross-origin requests. For example,
+/// https://source.example.com can make XMLHttpRequest requests on
+/// http://target.example.com if the http://target.example.com request returns
+/// an "Access-Control-Allow-Origin: https://source.example.com" response
+/// header.
+///
+/// Scripts in separate frames or iframes and hosted from the same protocol and
+/// domain suffix can execute cross-origin JavaScript if both pages set the
+/// document.domain value to the same domain suffix. For example,
+/// scheme://foo.example.com and scheme://bar.example.com can communicate using
+/// JavaScript if both domains set document.domain="example.com".
+///
+/// This method is used to allow access to origins that would otherwise violate
+/// the same-origin policy. Scripts hosted underneath the fully qualified
+/// |source_origin| URL (like http://www.example.com) will be allowed access to
+/// all resources hosted on the specified |target_protocol| and |target_domain|.
+/// If |target_domain| is non-empty and |allow_target_subdomains| is false only
+/// exact domain matches will be allowed. If |target_domain| contains a top-
+/// level domain component (like "example.com") and |allow_target_subdomains| is
+/// true sub-domain matches will be allowed. If |target_domain| is empty and
+/// |allow_target_subdomains| if true all domains and IP addresses will be
+/// allowed.
+///
+/// This method cannot be used to bypass the restrictions on local or display
+/// isolated schemes. See the comments on CefRegisterCustomScheme for more
+/// information.
+///
+/// This function may be called on any thread. Returns false if |source_origin|
+/// is invalid or the whitelist cannot be accessed.
 ///
 /*--cef(optional_param=target_domain)--*/
 bool CefAddCrossOriginWhitelistEntry(const CefString& source_origin,
@@ -83,8 +84,8 @@
                                      bool allow_target_subdomains);
 
 ///
-// Remove an entry from the cross-origin access whitelist. Returns false if
-// |source_origin| is invalid or the whitelist cannot be accessed.
+/// Remove an entry from the cross-origin access whitelist. Returns false if
+/// |source_origin| is invalid or the whitelist cannot be accessed.
 ///
 /*--cef(optional_param=target_domain)--*/
 bool CefRemoveCrossOriginWhitelistEntry(const CefString& source_origin,
@@ -93,8 +94,8 @@
                                         bool allow_target_subdomains);
 
 ///
-// Remove all entries from the cross-origin access whitelist. Returns false if
-// the whitelist cannot be accessed.
+/// Remove all entries from the cross-origin access whitelist. Returns false if
+/// the whitelist cannot be accessed.
 ///
 /*--cef()--*/
 bool CefClearCrossOriginWhitelist();
diff --git a/src/include/cef_parser.h b/src/include/cef_parser.h
index bae958b..7482c7f 100644
--- a/src/include/cef_parser.h
+++ b/src/include/cef_parser.h
@@ -44,81 +44,90 @@
 #include "include/cef_values.h"
 
 ///
-// Parse the specified |url| into its component parts.
-// Returns false if the URL is empty or invalid.
+/// Combines specified |base_url| and |relative_url| into |resolved_url|.
+/// Returns false if one of the URLs is empty or invalid.
+///
+/*--cef()--*/
+bool CefResolveURL(const CefString& base_url,
+                   const CefString& relative_url,
+                   CefString& resolved_url);
+
+///
+/// Parse the specified |url| into its component parts.
+/// Returns false if the URL is empty or invalid.
 ///
 /*--cef()--*/
 bool CefParseURL(const CefString& url, CefURLParts& parts);
 
 ///
-// Creates a URL from the specified |parts|, which must contain a non-empty
-// spec or a non-empty host and path (at a minimum), but not both.
-// Returns false if |parts| isn't initialized as described.
+/// Creates a URL from the specified |parts|, which must contain a non-empty
+/// spec or a non-empty host and path (at a minimum), but not both.
+/// Returns false if |parts| isn't initialized as described.
 ///
 /*--cef()--*/
 bool CefCreateURL(const CefURLParts& parts, CefString& url);
 
 ///
-// This is a convenience function for formatting a URL in a concise and human-
-// friendly way to help users make security-related decisions (or in other
-// circumstances when people need to distinguish sites, origins, or otherwise-
-// simplified URLs from each other). Internationalized domain names (IDN) may be
-// presented in Unicode if the conversion is considered safe. The returned value
-// will (a) omit the path for standard schemes, excepting file and filesystem,
-// and (b) omit the port if it is the default for the scheme. Do not use this
-// for URLs which will be parsed or sent to other applications.
+/// This is a convenience function for formatting a URL in a concise and human-
+/// friendly way to help users make security-related decisions (or in other
+/// circumstances when people need to distinguish sites, origins, or otherwise-
+/// simplified URLs from each other). Internationalized domain names (IDN) may
+/// be presented in Unicode if the conversion is considered safe. The returned
+/// value will (a) omit the path for standard schemes, excepting file and
+/// filesystem, and (b) omit the port if it is the default for the scheme. Do
+/// not use this for URLs which will be parsed or sent to other applications.
 ///
 /*--cef(optional_param=languages)--*/
 CefString CefFormatUrlForSecurityDisplay(const CefString& origin_url);
 
 ///
-// Returns the mime type for the specified file extension or an empty string if
-// unknown.
+/// Returns the mime type for the specified file extension or an empty string if
+/// unknown.
 ///
 /*--cef()--*/
 CefString CefGetMimeType(const CefString& extension);
 
 ///
-// Get the extensions associated with the given mime type. This should be passed
-// in lower case. There could be multiple extensions for a given mime type, like
-// "html,htm" for "text/html", or "txt,text,html,..." for "text/*". Any existing
-// elements in the provided vector will not be erased.
+/// Get the extensions associated with the given mime type. This should be
+/// passed in lower case. There could be multiple extensions for a given mime
+/// type, like "html,htm" for "text/html", or "txt,text,html,..." for "text/*".
+/// Any existing elements in the provided vector will not be erased.
 ///
 /*--cef()--*/
 void CefGetExtensionsForMimeType(const CefString& mime_type,
                                  std::vector<CefString>& extensions);
 
 ///
-// Encodes |data| as a base64 string.
+/// Encodes |data| as a base64 string.
 ///
 /*--cef()--*/
 CefString CefBase64Encode(const void* data, size_t data_size);
 
 ///
-// Decodes the base64 encoded string |data|. The returned value will be NULL if
-// the decoding fails.
+/// Decodes the base64 encoded string |data|. The returned value will be NULL if
+/// the decoding fails.
 ///
 /*--cef()--*/
 CefRefPtr<CefBinaryValue> CefBase64Decode(const CefString& data);
 
 ///
-// Escapes characters in |text| which are unsuitable for use as a query
-// parameter value. Everything except alphanumerics and -_.!~*'() will be
-// converted to "%XX". If |use_plus| is true spaces will change to "+". The
-// result is basically the same as encodeURIComponent in Javacript.
+/// Escapes characters in |text| which are unsuitable for use as a query
+/// parameter value. Everything except alphanumerics and -_.!~*'() will be
+/// converted to "%XX". If |use_plus| is true spaces will change to "+". The
+/// result is basically the same as encodeURIComponent in Javacript.
 ///
 /*--cef()--*/
 CefString CefURIEncode(const CefString& text, bool use_plus);
 
 ///
-// Unescapes |text| and returns the result. Unescaping consists of looking for
-// the exact pattern "%XX" where each X is a hex digit and converting to the
-// character with the numerical value of those digits (e.g. "i%20=%203%3b"
-// unescapes to "i = 3;"). If |convert_to_utf8| is true this function will
-// attempt to interpret the initial decoded result as UTF-8. If the result is
-// convertable into UTF-8 it will be returned as converted. Otherwise the
-// initial decoded result will be returned.  The |unescape_rule| parameter
-// supports further customization the decoding process.
+/// Unescapes |text| and returns the result. Unescaping consists of looking for
+/// the exact pattern "%XX" where each X is a hex digit and converting to the
+/// character with the numerical value of those digits (e.g. "i%20=%203%3b"
+/// unescapes to "i = 3;"). If |convert_to_utf8| is true this function will
+/// attempt to interpret the initial decoded result as UTF-8. If the result is
+/// convertable into UTF-8 it will be returned as converted. Otherwise the
+/// initial decoded result will be returned.  The |unescape_rule| parameter
+/// supports further customization the decoding process.
 ///
 /*--cef()--*/
 CefString CefURIDecode(const CefString& text,
@@ -126,17 +135,17 @@
                        cef_uri_unescape_rule_t unescape_rule);
 
 ///
-// Parses the specified |json_string| and returns a dictionary or list
-// representation. If JSON parsing fails this method returns NULL.
+/// Parses the specified |json_string| and returns a dictionary or list
+/// representation. If JSON parsing fails this method returns NULL.
 ///
 /*--cef()--*/
 CefRefPtr<CefValue> CefParseJSON(const CefString& json_string,
                                  cef_json_parser_options_t options);
 
 ///
-// Parses the specified UTF8-encoded |json| buffer of size |json_size| and
-// returns a dictionary or list representation. If JSON parsing fails this
-// method returns NULL.
+/// Parses the specified UTF8-encoded |json| buffer of size |json_size| and
+/// returns a dictionary or list representation. If JSON parsing fails this
+/// method returns NULL.
 ///
 /*--cef(capi_name=cef_parse_json_buffer)--*/
 CefRefPtr<CefValue> CefParseJSON(const void* json,
@@ -144,22 +153,20 @@
                                  cef_json_parser_options_t options);
 
 ///
-// Parses the specified |json_string| and returns a dictionary or list
-// representation. If JSON parsing fails this method returns NULL and populates
-// |error_code_out| and |error_msg_out| with an error code and a formatted error
-// message respectively.
+/// Parses the specified |json_string| and returns a dictionary or list
+/// representation. If JSON parsing fails this method returns NULL and populates
+/// |error_msg_out| with a formatted error message.
 ///
 /*--cef()--*/
 CefRefPtr<CefValue> CefParseJSONAndReturnError(
     const CefString& json_string,
     cef_json_parser_options_t options,
-    cef_json_parser_error_t& error_code_out,
     CefString& error_msg_out);
 
 ///
-// Generates a JSON string from the specified root |node| which should be a
-// dictionary or list value. Returns an empty string on failure. This method
-// requires exclusive access to |node| including any underlying data.
+/// Generates a JSON string from the specified root |node| which should be a
+/// dictionary or list value. Returns an empty string on failure. This method
+/// requires exclusive access to |node| including any underlying data.
 ///
 /*--cef()--*/
 CefString CefWriteJSON(CefRefPtr<CefValue> node,
diff --git a/src/include/cef_path_util.h b/src/include/cef_path_util.h
index 552f4ba..d30dc6c 100644
--- a/src/include/cef_path_util.h
+++ b/src/include/cef_path_util.h
@@ -43,8 +43,8 @@
 typedef cef_path_key_t PathKey;
 
 ///
-// Retrieve the path associated with the specified |key|. Returns true on
-// success. Can be called on any thread in the browser process.
+/// Retrieve the path associated with the specified |key|. Returns true on
+/// success. Can be called on any thread in the browser process.
 ///
 /*--cef()--*/
 bool CefGetPath(PathKey key, CefString& path);
diff --git a/src/include/cef_permission_handler.h b/src/include/cef_permission_handler.h
new file mode 100644
index 0000000..e28c6a6
--- /dev/null
+++ b/src/include/cef_permission_handler.h
@@ -0,0 +1,149 @@
+// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---------------------------------------------------------------------------
+//
+// The contents of this file must follow a specific format in order to
+// support the CEF translator tool. See the translator.README.txt file in the
+// tools directory for more information.
+//
+
+#ifndef CEF_INCLUDE_CEF_PERMISSION_HANDLER_H_
+#define CEF_INCLUDE_CEF_PERMISSION_HANDLER_H_
+#pragma once
+
+#include "include/cef_base.h"
+#include "include/cef_browser.h"
+
+///
+/// Callback interface used for asynchronous continuation of media access
+/// permission requests.
+///
+/*--cef(source=library)--*/
+class CefMediaAccessCallback : public virtual CefBaseRefCounted {
+ public:
+  ///
+  /// Call to allow or deny media access. If this callback was initiated in
+  /// response to a getUserMedia (indicated by
+  /// CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE and/or
+  /// CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE being set) then
+  /// |allowed_permissions| must match |required_permissions| passed to
+  /// OnRequestMediaAccessPermission.
+  ///
+  /*--cef(capi_name=cont)--*/
+  virtual void Continue(uint32_t allowed_permissions) = 0;
+
+  ///
+  /// Cancel the media access request.
+  ///
+  /*--cef()--*/
+  virtual void Cancel() = 0;
+};
+
+///
+/// Callback interface used for asynchronous continuation of permission prompts.
+///
+/*--cef(source=library)--*/
+class CefPermissionPromptCallback : public virtual CefBaseRefCounted {
+ public:
+  ///
+  /// Complete the permissions request with the specified |result|.
+  ///
+  /*--cef(capi_name=cont)--*/
+  virtual void Continue(cef_permission_request_result_t result) = 0;
+};
+
+///
+/// Implement this interface to handle events related to permission requests.
+/// The methods of this class will be called on the browser process UI thread.
+///
+/*--cef(source=client)--*/
+class CefPermissionHandler : public virtual CefBaseRefCounted {
+ public:
+  ///
+  /// Called when a page requests permission to access media.
+  /// |requesting_origin| is the URL origin requesting permission.
+  /// |requested_permissions| is a combination of values from
+  /// cef_media_access_permission_types_t that represent the requested
+  /// permissions. Return true and call CefMediaAccessCallback methods either in
+  /// this method or at a later time to continue or cancel the request. Return
+  /// false to proceed with default handling. With the Chrome runtime, default
+  /// handling will display the permission request UI. With the Alloy runtime,
+  /// default handling will deny the request. This method will not be called if
+  /// the "--enable-media-stream" command-line switch is used to grant all
+  /// permissions.
+  ///
+  /*--cef()--*/
+  virtual bool OnRequestMediaAccessPermission(
+      CefRefPtr<CefBrowser> browser,
+      CefRefPtr<CefFrame> frame,
+      const CefString& requesting_origin,
+      uint32_t requested_permissions,
+      CefRefPtr<CefMediaAccessCallback> callback) {
+    return false;
+  }
+
+  ///
+  /// Called when a page should show a permission prompt. |prompt_id| uniquely
+  /// identifies the prompt. |requesting_origin| is the URL origin requesting
+  /// permission. |requested_permissions| is a combination of values from
+  /// cef_permission_request_types_t that represent the requested permissions.
+  /// Return true and call CefPermissionPromptCallback::Continue either in this
+  /// method or at a later time to continue or cancel the request. Return false
+  /// to proceed with default handling. With the Chrome runtime, default
+  /// handling will display the permission prompt UI. With the Alloy runtime,
+  /// default handling is CEF_PERMISSION_RESULT_IGNORE.
+  ///
+  /*--cef()--*/
+  virtual bool OnShowPermissionPrompt(
+      CefRefPtr<CefBrowser> browser,
+      uint64_t prompt_id,
+      const CefString& requesting_origin,
+      uint32_t requested_permissions,
+      CefRefPtr<CefPermissionPromptCallback> callback) {
+    return false;
+  }
+
+  ///
+  /// Called when a permission prompt handled via OnShowPermissionPrompt is
+  /// dismissed. |prompt_id| will match the value that was passed to
+  /// OnShowPermissionPrompt. |result| will be the value passed to
+  /// CefPermissionPromptCallback::Continue or CEF_PERMISSION_RESULT_IGNORE if
+  /// the dialog was dismissed for other reasons such as navigation, browser
+  /// closure, etc. This method will not be called if OnShowPermissionPrompt
+  /// returned false for |prompt_id|.
+  ///
+  /*--cef()--*/
+  virtual void OnDismissPermissionPrompt(
+      CefRefPtr<CefBrowser> browser,
+      uint64_t prompt_id,
+      cef_permission_request_result_t result) {}
+};
+
+#endif  // CEF_INCLUDE_CEF_PERMISSION_HANDLER_H_
diff --git a/src/include/cef_preference.h b/src/include/cef_preference.h
new file mode 100644
index 0000000..8f3d61a
--- /dev/null
+++ b/src/include/cef_preference.h
@@ -0,0 +1,134 @@
+// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---------------------------------------------------------------------------
+//
+// The contents of this file must follow a specific format in order to
+// support the CEF translator tool. See the translator.README.txt file in the
+// tools directory for more information.
+//
+
+#ifndef CEF_INCLUDE_CEF_PREFERENCE_H_
+#define CEF_INCLUDE_CEF_PREFERENCE_H_
+#pragma once
+
+#include <vector>
+
+#include "include/cef_base.h"
+#include "include/cef_values.h"
+
+///
+/// Class that manages custom preference registrations.
+///
+/*--cef(source=library)--*/
+class CefPreferenceRegistrar : public CefBaseScoped {
+ public:
+  ///
+  /// Register a preference with the specified |name| and |default_value|. To
+  /// avoid conflicts with built-in preferences the |name| value should contain
+  /// an application-specific prefix followed by a period (e.g. "myapp.value").
+  /// The contents of |default_value| will be copied. The data type for the
+  /// preference will be inferred from |default_value|'s type and cannot be
+  /// changed after registration. Returns true on success. Returns false if
+  /// |name| is already registered or if |default_value| has an invalid type.
+  /// This method must be called from within the scope of the
+  /// CefBrowserProcessHandler::OnRegisterCustomPreferences callback.
+  ///
+  /*--cef()--*/
+  virtual bool AddPreference(const CefString& name,
+                             CefRefPtr<CefValue> default_value) = 0;
+};
+
+///
+/// Manage access to preferences. Many built-in preferences are registered by
+/// Chromium. Custom preferences can be registered in
+/// CefBrowserProcessHandler::OnRegisterCustomPreferences.
+///
+/*--cef(source=library,no_debugct_check)--*/
+class CefPreferenceManager : public virtual CefBaseRefCounted {
+ public:
+  ///
+  /// Returns the global preference manager object.
+  ///
+  /*--cef()--*/
+  static CefRefPtr<CefPreferenceManager> GetGlobalPreferenceManager();
+
+  ///
+  /// Returns true if a preference with the specified |name| exists. This method
+  /// must be called on the browser process UI thread.
+  ///
+  /*--cef()--*/
+  virtual bool HasPreference(const CefString& name) = 0;
+
+  ///
+  /// Returns the value for the preference with the specified |name|. Returns
+  /// NULL if the preference does not exist. The returned object contains a copy
+  /// of the underlying preference value and modifications to the returned
+  /// object will not modify the underlying preference value. This method must
+  /// be called on the browser process UI thread.
+  ///
+  /*--cef()--*/
+  virtual CefRefPtr<CefValue> GetPreference(const CefString& name) = 0;
+
+  ///
+  /// Returns all preferences as a dictionary. If |include_defaults| is true
+  /// then preferences currently at their default value will be included. The
+  /// returned object contains a copy of the underlying preference values and
+  /// modifications to the returned object will not modify the underlying
+  /// preference values. This method must be called on the browser process UI
+  /// thread.
+  ///
+  /*--cef()--*/
+  virtual CefRefPtr<CefDictionaryValue> GetAllPreferences(
+      bool include_defaults) = 0;
+
+  ///
+  /// Returns true if the preference with the specified |name| can be modified
+  /// using SetPreference. As one example preferences set via the command-line
+  /// usually cannot be modified. This method must be called on the browser
+  /// process UI thread.
+  ///
+  /*--cef()--*/
+  virtual bool CanSetPreference(const CefString& name) = 0;
+
+  ///
+  /// Set the |value| associated with preference |name|. Returns true if the
+  /// value is set successfully and false otherwise. If |value| is NULL the
+  /// preference will be restored to its default value. If setting the
+  /// preference fails then |error| will be populated with a detailed
+  /// description of the problem. This method must be called on the browser
+  /// process UI thread.
+  ///
+  /*--cef(optional_param=value)--*/
+  virtual bool SetPreference(const CefString& name,
+                             CefRefPtr<CefValue> value,
+                             CefString& error) = 0;
+};
+
+#endif  // CEF_INCLUDE_CEF_PREFERENCE_H_
diff --git a/src/include/cef_print_handler.h b/src/include/cef_print_handler.h
index c668bd4..8e4bcc6 100644
--- a/src/include/cef_print_handler.h
+++ b/src/include/cef_print_handler.h
@@ -43,58 +43,58 @@
 #include "include/cef_print_settings.h"
 
 ///
-// Callback interface for asynchronous continuation of print dialog requests.
+/// Callback interface for asynchronous continuation of print dialog requests.
 ///
 /*--cef(source=library)--*/
 class CefPrintDialogCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Continue printing with the specified |settings|.
+  /// Continue printing with the specified |settings|.
   ///
   /*--cef(capi_name=cont)--*/
   virtual void Continue(CefRefPtr<CefPrintSettings> settings) = 0;
 
   ///
-  // Cancel the printing.
+  /// Cancel the printing.
   ///
   /*--cef()--*/
   virtual void Cancel() = 0;
 };
 
 ///
-// Callback interface for asynchronous continuation of print job requests.
+/// Callback interface for asynchronous continuation of print job requests.
 ///
 /*--cef(source=library)--*/
 class CefPrintJobCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Indicate completion of the print job.
+  /// Indicate completion of the print job.
   ///
   /*--cef(capi_name=cont)--*/
   virtual void Continue() = 0;
 };
 
 ///
-// Implement this interface to handle printing on Linux. Each browser will have
-// only one print job in progress at a time. The methods of this class will be
-// called on the browser process UI thread.
+/// Implement this interface to handle printing on Linux. Each browser will have
+/// only one print job in progress at a time. The methods of this class will be
+/// called on the browser process UI thread.
 ///
 /*--cef(source=client)--*/
 class CefPrintHandler : public virtual CefBaseRefCounted {
  public:
   ///
-  // Called when printing has started for the specified |browser|. This method
-  // will be called before the other OnPrint*() methods and irrespective of how
-  // printing was initiated (e.g. CefBrowserHost::Print(), JavaScript
-  // window.print() or PDF extension print button).
+  /// Called when printing has started for the specified |browser|. This method
+  /// will be called before the other OnPrint*() methods and irrespective of how
+  /// printing was initiated (e.g. CefBrowserHost::Print(), JavaScript
+  /// window.print() or PDF extension print button).
   ///
   /*--cef()--*/
   virtual void OnPrintStart(CefRefPtr<CefBrowser> browser) = 0;
 
   ///
-  // Synchronize |settings| with client state. If |get_defaults| is true then
-  // populate |settings| with the default print settings. Do not keep a
-  // reference to |settings| outside of this callback.
+  /// Synchronize |settings| with client state. If |get_defaults| is true then
+  /// populate |settings| with the default print settings. Do not keep a
+  /// reference to |settings| outside of this callback.
   ///
   /*--cef()--*/
   virtual void OnPrintSettings(CefRefPtr<CefBrowser> browser,
@@ -102,9 +102,9 @@
                                bool get_defaults) = 0;
 
   ///
-  // Show the print dialog. Execute |callback| once the dialog is dismissed.
-  // Return true if the dialog will be displayed or false to cancel the
-  // printing immediately.
+  /// Show the print dialog. Execute |callback| once the dialog is dismissed.
+  /// Return true if the dialog will be displayed or false to cancel the
+  /// printing immediately.
   ///
   /*--cef()--*/
   virtual bool OnPrintDialog(CefRefPtr<CefBrowser> browser,
@@ -112,9 +112,9 @@
                              CefRefPtr<CefPrintDialogCallback> callback) = 0;
 
   ///
-  // Send the print job to the printer. Execute |callback| once the job is
-  // completed. Return true if the job will proceed or false to cancel the job
-  // immediately.
+  /// Send the print job to the printer. Execute |callback| once the job is
+  /// completed. Return true if the job will proceed or false to cancel the job
+  /// immediately.
   ///
   /*--cef()--*/
   virtual bool OnPrintJob(CefRefPtr<CefBrowser> browser,
@@ -123,17 +123,18 @@
                           CefRefPtr<CefPrintJobCallback> callback) = 0;
 
   ///
-  // Reset client state related to printing.
+  /// Reset client state related to printing.
   ///
   /*--cef()--*/
   virtual void OnPrintReset(CefRefPtr<CefBrowser> browser) = 0;
 
   ///
-  // Return the PDF paper size in device units. Used in combination with
-  // CefBrowserHost::PrintToPDF().
+  /// Return the PDF paper size in device units. Used in combination with
+  /// CefBrowserHost::PrintToPDF().
   ///
   /*--cef()--*/
-  virtual CefSize GetPdfPaperSize(int device_units_per_inch) {
+  virtual CefSize GetPdfPaperSize(CefRefPtr<CefBrowser> browser,
+                                  int device_units_per_inch) {
     return CefSize();
   }
 };
diff --git a/src/include/cef_print_settings.h b/src/include/cef_print_settings.h
index ba1c294..df61a29 100644
--- a/src/include/cef_print_settings.h
+++ b/src/include/cef_print_settings.h
@@ -43,7 +43,7 @@
 #include "include/cef_base.h"
 
 ///
-// Class representing print settings.
+/// Class representing print settings.
 ///
 /*--cef(source=library)--*/
 class CefPrintSettings : public virtual CefBaseRefCounted {
@@ -53,41 +53,41 @@
   typedef std::vector<CefRange> PageRangeList;
 
   ///
-  // Create a new CefPrintSettings object.
+  /// Create a new CefPrintSettings object.
   ///
   /*--cef()--*/
   static CefRefPtr<CefPrintSettings> Create();
 
   ///
-  // Returns true if this object is valid. Do not call any other methods if this
-  // function returns false.
+  /// Returns true if this object is valid. Do not call any other methods if
+  /// this function returns false.
   ///
   /*--cef()--*/
   virtual bool IsValid() = 0;
 
   ///
-  // Returns true if the values of this object are read-only. Some APIs may
-  // expose read-only objects.
+  /// Returns true if the values of this object are read-only. Some APIs may
+  /// expose read-only objects.
   ///
   /*--cef()--*/
   virtual bool IsReadOnly() = 0;
 
   ///
-  // Set the page orientation.
+  /// Set the page orientation.
   ///
   /*--cef()--*/
   virtual void SetOrientation(bool landscape) = 0;
 
   ///
-  // Returns true if the orientation is landscape.
+  /// Returns true if the orientation is landscape.
   ///
   /*--cef()--*/
   virtual bool IsLandscape() = 0;
 
   ///
-  // Set the printer printable area in device units.
-  // Some platforms already provide flipped area. Set |landscape_needs_flip|
-  // to false on those platforms to avoid double flipping.
+  /// Set the printer printable area in device units.
+  /// Some platforms already provide flipped area. Set |landscape_needs_flip|
+  /// to false on those platforms to avoid double flipping.
   ///
   /*--cef()--*/
   virtual void SetPrinterPrintableArea(
@@ -96,103 +96,103 @@
       bool landscape_needs_flip) = 0;
 
   ///
-  // Set the device name.
+  /// Set the device name.
   ///
   /*--cef(optional_param=name)--*/
   virtual void SetDeviceName(const CefString& name) = 0;
 
   ///
-  // Get the device name.
+  /// Get the device name.
   ///
   /*--cef()--*/
   virtual CefString GetDeviceName() = 0;
 
   ///
-  // Set the DPI (dots per inch).
+  /// Set the DPI (dots per inch).
   ///
   /*--cef()--*/
   virtual void SetDPI(int dpi) = 0;
 
   ///
-  // Get the DPI (dots per inch).
+  /// Get the DPI (dots per inch).
   ///
   /*--cef()--*/
   virtual int GetDPI() = 0;
 
   ///
-  // Set the page ranges.
+  /// Set the page ranges.
   ///
   /*--cef()--*/
   virtual void SetPageRanges(const PageRangeList& ranges) = 0;
 
   ///
-  // Returns the number of page ranges that currently exist.
+  /// Returns the number of page ranges that currently exist.
   ///
   /*--cef()--*/
   virtual size_t GetPageRangesCount() = 0;
 
   ///
-  // Retrieve the page ranges.
+  /// Retrieve the page ranges.
   ///
   /*--cef(count_func=ranges:GetPageRangesCount)--*/
   virtual void GetPageRanges(PageRangeList& ranges) = 0;
 
   ///
-  // Set whether only the selection will be printed.
+  /// Set whether only the selection will be printed.
   ///
   /*--cef()--*/
   virtual void SetSelectionOnly(bool selection_only) = 0;
 
   ///
-  // Returns true if only the selection will be printed.
+  /// Returns true if only the selection will be printed.
   ///
   /*--cef()--*/
   virtual bool IsSelectionOnly() = 0;
 
   ///
-  // Set whether pages will be collated.
+  /// Set whether pages will be collated.
   ///
   /*--cef()--*/
   virtual void SetCollate(bool collate) = 0;
 
   ///
-  // Returns true if pages will be collated.
+  /// Returns true if pages will be collated.
   ///
   /*--cef()--*/
   virtual bool WillCollate() = 0;
 
   ///
-  // Set the color model.
+  /// Set the color model.
   ///
   /*--cef()--*/
   virtual void SetColorModel(ColorModel model) = 0;
 
   ///
-  // Get the color model.
+  /// Get the color model.
   ///
   /*--cef(default_retval=COLOR_MODEL_UNKNOWN)--*/
   virtual ColorModel GetColorModel() = 0;
 
   ///
-  // Set the number of copies.
+  /// Set the number of copies.
   ///
   /*--cef()--*/
   virtual void SetCopies(int copies) = 0;
 
   ///
-  // Get the number of copies.
+  /// Get the number of copies.
   ///
   /*--cef()--*/
   virtual int GetCopies() = 0;
 
   ///
-  // Set the duplex mode.
+  /// Set the duplex mode.
   ///
   /*--cef()--*/
   virtual void SetDuplexMode(DuplexMode mode) = 0;
 
   ///
-  // Get the duplex mode.
+  /// Get the duplex mode.
   ///
   /*--cef(default_retval=DUPLEX_MODE_UNKNOWN)--*/
   virtual DuplexMode GetDuplexMode() = 0;
diff --git a/src/include/cef_process_message.h b/src/include/cef_process_message.h
index c4daeb8..74f6481 100644
--- a/src/include/cef_process_message.h
+++ b/src/include/cef_process_message.h
@@ -39,53 +39,63 @@
 #pragma once
 
 #include "include/cef_base.h"
+#include "include/cef_shared_memory_region.h"
 #include "include/cef_values.h"
 
 typedef cef_process_id_t CefProcessId;
 
 ///
-// Class representing a message. Can be used on any process and thread.
+/// Class representing a message. Can be used on any process and thread.
 ///
 /*--cef(source=library)--*/
 class CefProcessMessage : public virtual CefBaseRefCounted {
  public:
   ///
-  // Create a new CefProcessMessage object with the specified name.
+  /// Create a new CefProcessMessage object with the specified name.
   ///
   /*--cef()--*/
   static CefRefPtr<CefProcessMessage> Create(const CefString& name);
 
   ///
-  // Returns true if this object is valid. Do not call any other methods if this
-  // function returns false.
+  /// Returns true if this object is valid. Do not call any other methods if
+  /// this function returns false.
   ///
   /*--cef()--*/
   virtual bool IsValid() = 0;
 
   ///
-  // Returns true if the values of this object are read-only. Some APIs may
-  // expose read-only objects.
+  /// Returns true if the values of this object are read-only. Some APIs may
+  /// expose read-only objects.
   ///
   /*--cef()--*/
   virtual bool IsReadOnly() = 0;
 
   ///
-  // Returns a writable copy of this object.
+  /// Returns a writable copy of this object.
+  /// Returns nullptr when message contains a shared memory region.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefProcessMessage> Copy() = 0;
 
   ///
-  // Returns the message name.
+  /// Returns the message name.
   ///
   /*--cef()--*/
   virtual CefString GetName() = 0;
 
   ///
-  // Returns the list of arguments.
+  /// Returns the list of arguments.
+  /// Returns nullptr when message contains a shared memory region.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefListValue> GetArgumentList() = 0;
+
+  ///
+  /// Returns the shared memory region.
+  /// Returns nullptr when message contains an argument list.
+  ///
+  /*--cef()--*/
+  virtual CefRefPtr<CefSharedMemoryRegion> GetSharedMemoryRegion() = 0;
 };
 
 #endif  // CEF_INCLUDE_CEF_MESSAGE_H_
diff --git a/src/include/cef_process_util.h b/src/include/cef_process_util.h
index 4fce778..c3e6731 100644
--- a/src/include/cef_process_util.h
+++ b/src/include/cef_process_util.h
@@ -42,14 +42,14 @@
 #include "include/cef_command_line.h"
 
 ///
-// Launches the process specified via |command_line|. Returns true upon
-// success. Must be called on the browser process TID_PROCESS_LAUNCHER thread.
-//
-// Unix-specific notes:
-// - All file descriptors open in the parent process will be closed in the
-//   child process except for stdin, stdout, and stderr.
-// - If the first argument on the command line does not contain a slash,
-//   PATH will be searched. (See man execvp.)
+/// Launches the process specified via |command_line|. Returns true upon
+/// success. Must be called on the browser process TID_PROCESS_LAUNCHER thread.
+///
+/// Unix-specific notes:
+/// - All file descriptors open in the parent process will be closed in the
+///   child process except for stdin, stdout, and stderr.
+/// - If the first argument on the command line does not contain a slash,
+///   PATH will be searched. (See man execvp.)
 ///
 /*--cef()--*/
 bool CefLaunchProcess(CefRefPtr<CefCommandLine> command_line);
diff --git a/src/include/cef_registration.h b/src/include/cef_registration.h
index e8e6caa..87c9eee 100644
--- a/src/include/cef_registration.h
+++ b/src/include/cef_registration.h
@@ -41,7 +41,7 @@
 #include "include/cef_base.h"
 
 ///
-// Generic callback interface used for managing the lifespan of a registration.
+/// Generic callback interface used for managing the lifespan of a registration.
 ///
 /*--cef(source=library)--*/
 class CefRegistration : public virtual CefBaseRefCounted {};
diff --git a/src/include/cef_render_handler.h b/src/include/cef_render_handler.h
index c6c40f8..b27403f 100644
--- a/src/include/cef_render_handler.h
+++ b/src/include/cef_render_handler.h
@@ -46,13 +46,12 @@
 #include "include/cef_drag_data.h"
 
 ///
-// Implement this interface to handle events when window rendering is disabled.
-// The methods of this class will be called on the UI thread.
+/// Implement this interface to handle events when window rendering is disabled.
+/// The methods of this class will be called on the UI thread.
 ///
 /*--cef(source=client)--*/
 class CefRenderHandler : public virtual CefBaseRefCounted {
  public:
-  typedef cef_cursor_type_t CursorType;
   typedef cef_drag_operations_mask_t DragOperation;
   typedef cef_drag_operations_mask_t DragOperationsMask;
   typedef cef_paint_element_type_t PaintElementType;
@@ -60,8 +59,8 @@
   typedef cef_text_input_mode_t TextInputMode;
 
   ///
-  // Return the handler for accessibility notifications. If no handler is
-  // provided the default implementation will be used.
+  /// Return the handler for accessibility notifications. If no handler is
+  /// provided the default implementation will be used.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefAccessibilityHandler> GetAccessibilityHandler() {
@@ -69,9 +68,9 @@
   }
 
   ///
-  // Called to retrieve the root window rectangle in screen coordinates. Return
-  // true if the rectangle was provided. If this method returns false the
-  // rectangle from GetViewRect will be used.
+  /// Called to retrieve the root window rectangle in screen DIP coordinates.
+  /// Return true if the rectangle was provided. If this method returns false
+  /// the rectangle from GetViewRect will be used.
   ///
   /*--cef()--*/
   virtual bool GetRootScreenRect(CefRefPtr<CefBrowser> browser, CefRect& rect) {
@@ -79,15 +78,17 @@
   }
 
   ///
-  // Called to retrieve the view rectangle which is relative to screen
-  // coordinates. This method must always provide a non-empty rectangle.
+  /// Called to retrieve the view rectangle in screen DIP coordinates. This
+  /// method must always provide a non-empty rectangle.
   ///
   /*--cef()--*/
   virtual void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) = 0;
 
   ///
-  // Called to retrieve the translation from view coordinates to actual screen
-  // coordinates. Return true if the screen coordinates were provided.
+  /// Called to retrieve the translation from view DIP coordinates to screen
+  /// coordinates. Windows/Linux should provide screen device (pixel)
+  /// coordinates and MacOS should provide screen DIP coordinates. Return true
+  /// if the requested coordinates were provided.
   ///
   /*--cef()--*/
   virtual bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
@@ -99,13 +100,13 @@
   }
 
   ///
-  // Called to allow the client to fill in the CefScreenInfo object with
-  // appropriate values. Return true if the |screen_info| structure has been
-  // modified.
-  //
-  // If the screen info rectangle is left empty the rectangle from GetViewRect
-  // will be used. If the rectangle is still empty or invalid popups may not be
-  // drawn correctly.
+  /// Called to allow the client to fill in the CefScreenInfo object with
+  /// appropriate values. Return true if the |screen_info| structure has been
+  /// modified.
+  ///
+  /// If the screen info rectangle is left empty the rectangle from GetViewRect
+  /// will be used. If the rectangle is still empty or invalid popups may not be
+  /// drawn correctly.
   ///
   /*--cef()--*/
   virtual bool GetScreenInfo(CefRefPtr<CefBrowser> browser,
@@ -114,30 +115,30 @@
   }
 
   ///
-  // Called when the browser wants to show or hide the popup widget. The popup
-  // should be shown if |show| is true and hidden if |show| is false.
+  /// Called when the browser wants to show or hide the popup widget. The popup
+  /// should be shown if |show| is true and hidden if |show| is false.
   ///
   /*--cef()--*/
   virtual void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) {}
 
   ///
-  // Called when the browser wants to move or resize the popup widget. |rect|
-  // contains the new location and size in view coordinates.
+  /// Called when the browser wants to move or resize the popup widget. |rect|
+  /// contains the new location and size in view coordinates.
   ///
   /*--cef()--*/
   virtual void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect) {
   }
 
   ///
-  // Called when an element should be painted. Pixel values passed to this
-  // method are scaled relative to view coordinates based on the value of
-  // CefScreenInfo.device_scale_factor returned from GetScreenInfo. |type|
-  // indicates whether the element is the view or the popup widget. |buffer|
-  // contains the pixel data for the whole image. |dirtyRects| contains the set
-  // of rectangles in pixel coordinates that need to be repainted. |buffer| will
-  // be |width|*|height|*4 bytes in size and represents a BGRA image with an
-  // upper-left origin. This method is only called when
-  // CefWindowInfo::shared_texture_enabled is set to false.
+  /// Called when an element should be painted. Pixel values passed to this
+  /// method are scaled relative to view coordinates based on the value of
+  /// CefScreenInfo.device_scale_factor returned from GetScreenInfo. |type|
+  /// indicates whether the element is the view or the popup widget. |buffer|
+  /// contains the pixel data for the whole image. |dirtyRects| contains the set
+  /// of rectangles in pixel coordinates that need to be repainted. |buffer|
+  /// will be |width|*|height|*4 bytes in size and represents a BGRA image with
+  /// an upper-left origin. This method is only called when
+  /// CefWindowInfo::shared_texture_enabled is set to false.
   ///
   /*--cef()--*/
   virtual void OnPaint(CefRefPtr<CefBrowser> browser,
@@ -148,13 +149,13 @@
                        int height) = 0;
 
   ///
-  // Called when an element has been rendered to the shared texture handle.
-  // |type| indicates whether the element is the view or the popup widget.
-  // |dirtyRects| contains the set of rectangles in pixel coordinates that need
-  // to be repainted. |shared_handle| is the handle for a D3D11 Texture2D that
-  // can be accessed via ID3D11Device using the OpenSharedResource method. This
-  // method is only called when CefWindowInfo::shared_texture_enabled is set to
-  // true, and is currently only supported on Windows.
+  /// Called when an element has been rendered to the shared texture handle.
+  /// |type| indicates whether the element is the view or the popup widget.
+  /// |dirtyRects| contains the set of rectangles in pixel coordinates that need
+  /// to be repainted. |shared_handle| is the handle for a D3D11 Texture2D that
+  /// can be accessed via ID3D11Device using the OpenSharedResource method. This
+  /// method is only called when CefWindowInfo::shared_texture_enabled is set to
+  /// true, and is currently only supported on Windows.
   ///
   /*--cef()--*/
   virtual void OnAcceleratedPaint(CefRefPtr<CefBrowser> browser,
@@ -163,29 +164,36 @@
                                   void* shared_handle) {}
 
   ///
-  // Called when the browser's cursor has changed. If |type| is CT_CUSTOM then
-  // |custom_cursor_info| will be populated with the custom cursor information.
+  /// Called to retrieve the size of the touch handle for the specified
+  /// |orientation|.
   ///
   /*--cef()--*/
-  virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
-                              CefCursorHandle cursor,
-                              CursorType type,
-                              const CefCursorInfo& custom_cursor_info) {}
+  virtual void GetTouchHandleSize(CefRefPtr<CefBrowser> browser,
+                                  cef_horizontal_alignment_t orientation,
+                                  CefSize& size) {}
 
   ///
-  // Called when the user starts dragging content in the web view. Contextual
-  // information about the dragged content is supplied by |drag_data|.
-  // (|x|, |y|) is the drag start location in screen coordinates.
-  // OS APIs that run a system message loop may be used within the
-  // StartDragging call.
-  //
-  // Return false to abort the drag operation. Don't call any of
-  // CefBrowserHost::DragSource*Ended* methods after returning false.
-  //
-  // Return true to handle the drag operation. Call
-  // CefBrowserHost::DragSourceEndedAt and DragSourceSystemDragEnded either
-  // synchronously or asynchronously to inform the web view that the drag
-  // operation has ended.
+  /// Called when touch handle state is updated. The client is responsible for
+  /// rendering the touch handles.
+  ///
+  /*--cef()--*/
+  virtual void OnTouchHandleStateChanged(CefRefPtr<CefBrowser> browser,
+                                         const CefTouchHandleState& state) {}
+
+  ///
+  /// Called when the user starts dragging content in the web view. Contextual
+  /// information about the dragged content is supplied by |drag_data|.
+  /// (|x|, |y|) is the drag start location in screen coordinates.
+  /// OS APIs that run a system message loop may be used within the
+  /// StartDragging call.
+  ///
+  /// Return false to abort the drag operation. Don't call any of
+  /// CefBrowserHost::DragSource*Ended* methods after returning false.
+  ///
+  /// Return true to handle the drag operation. Call
+  /// CefBrowserHost::DragSourceEndedAt and DragSourceSystemDragEnded either
+  /// synchronously or asynchronously to inform the web view that the drag
+  /// operation has ended.
   ///
   /*--cef()--*/
   virtual bool StartDragging(CefRefPtr<CefBrowser> browser,
@@ -197,16 +205,16 @@
   }
 
   ///
-  // Called when the web view wants to update the mouse cursor during a
-  // drag & drop operation. |operation| describes the allowed operation
-  // (none, move, copy, link).
+  /// Called when the web view wants to update the mouse cursor during a
+  /// drag & drop operation. |operation| describes the allowed operation
+  /// (none, move, copy, link).
   ///
   /*--cef()--*/
   virtual void UpdateDragCursor(CefRefPtr<CefBrowser> browser,
                                 DragOperation operation) {}
 
   ///
-  // Called when the scroll offset has changed.
+  /// Called when the scroll offset has changed.
   ///
   /*--cef()--*/
   virtual void OnScrollOffsetChanged(CefRefPtr<CefBrowser> browser,
@@ -214,9 +222,9 @@
                                      double y) {}
 
   ///
-  // Called when the IME composition range has changed. |selected_range| is the
-  // range of characters that have been selected. |character_bounds| is the
-  // bounds of each character in view coordinates.
+  /// Called when the IME composition range has changed. |selected_range| is the
+  /// range of characters that have been selected. |character_bounds| is the
+  /// bounds of each character in view coordinates.
   ///
   /*--cef()--*/
   virtual void OnImeCompositionRangeChanged(CefRefPtr<CefBrowser> browser,
@@ -224,9 +232,9 @@
                                             const RectList& character_bounds) {}
 
   ///
-  // Called when text selection has changed for the specified |browser|.
-  // |selected_text| is the currently selected text and |selected_range| is
-  // the character range.
+  /// Called when text selection has changed for the specified |browser|.
+  /// |selected_text| is the currently selected text and |selected_range| is
+  /// the character range.
   ///
   /*--cef(optional_param=selected_text,optional_param=selected_range)--*/
   virtual void OnTextSelectionChanged(CefRefPtr<CefBrowser> browser,
@@ -234,10 +242,10 @@
                                       const CefRange& selected_range) {}
 
   ///
-  // Called when an on-screen keyboard should be shown or hidden for the
-  // specified |browser|. |input_mode| specifies what kind of keyboard
-  // should be opened. If |input_mode| is CEF_TEXT_INPUT_MODE_NONE, any
-  // existing keyboard for this browser should be hidden.
+  /// Called when an on-screen keyboard should be shown or hidden for the
+  /// specified |browser|. |input_mode| specifies what kind of keyboard
+  /// should be opened. If |input_mode| is CEF_TEXT_INPUT_MODE_NONE, any
+  /// existing keyboard for this browser should be hidden.
   ///
   /*--cef()--*/
   virtual void OnVirtualKeyboardRequested(CefRefPtr<CefBrowser> browser,
diff --git a/src/include/cef_render_process_handler.h b/src/include/cef_render_process_handler.h
index 8ba4ec4..a9049ba 100644
--- a/src/include/cef_render_process_handler.h
+++ b/src/include/cef_render_process_handler.h
@@ -48,9 +48,9 @@
 #include "include/cef_values.h"
 
 ///
-// Class used to implement render process callbacks. The methods of this class
-// will be called on the render process main thread (TID_RENDERER) unless
-// otherwise indicated.
+/// Class used to implement render process callbacks. The methods of this class
+/// will be called on the render process main thread (TID_RENDERER) unless
+/// otherwise indicated.
 ///
 /*--cef(source=client,no_debugct_check)--*/
 class CefRenderProcessHandler : public virtual CefBaseRefCounted {
@@ -58,49 +58,41 @@
   typedef cef_navigation_type_t NavigationType;
 
   ///
-  // Called after the render process main thread has been created. |extra_info|
-  // is a read-only value originating from
-  // CefBrowserProcessHandler::OnRenderProcessThreadCreated(). Do not keep a
-  // reference to |extra_info| outside of this method.
-  ///
-  /*--cef()--*/
-  virtual void OnRenderThreadCreated(CefRefPtr<CefListValue> extra_info) {}
-
-  ///
-  // Called after WebKit has been initialized.
+  /// Called after WebKit has been initialized.
   ///
   /*--cef()--*/
   virtual void OnWebKitInitialized() {}
 
   ///
-  // Called after a browser has been created. When browsing cross-origin a new
-  // browser will be created before the old browser with the same identifier is
-  // destroyed. |extra_info| is a read-only value originating from
-  // CefBrowserHost::CreateBrowser(), CefBrowserHost::CreateBrowserSync(),
-  // CefLifeSpanHandler::OnBeforePopup() or CefBrowserView::CreateBrowserView().
+  /// Called after a browser has been created. When browsing cross-origin a new
+  /// browser will be created before the old browser with the same identifier is
+  /// destroyed. |extra_info| is an optional read-only value originating from
+  /// CefBrowserHost::CreateBrowser(), CefBrowserHost::CreateBrowserSync(),
+  /// CefLifeSpanHandler::OnBeforePopup() or
+  /// CefBrowserView::CreateBrowserView().
   ///
-  /*--cef()--*/
+  /*--cef(optional_param=extra_info)--*/
   virtual void OnBrowserCreated(CefRefPtr<CefBrowser> browser,
                                 CefRefPtr<CefDictionaryValue> extra_info) {}
 
   ///
-  // Called before a browser is destroyed.
+  /// Called before a browser is destroyed.
   ///
   /*--cef()--*/
   virtual void OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) {}
 
   ///
-  // Return the handler for browser load status events.
+  /// Return the handler for browser load status events.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefLoadHandler> GetLoadHandler() { return nullptr; }
 
   ///
-  // Called immediately after the V8 context for a frame has been created. To
-  // retrieve the JavaScript 'window' object use the CefV8Context::GetGlobal()
-  // method. V8 handles can only be accessed from the thread on which they are
-  // created. A task runner for posting tasks on the associated thread can be
-  // retrieved via the CefV8Context::GetTaskRunner() method.
+  /// Called immediately after the V8 context for a frame has been created. To
+  /// retrieve the JavaScript 'window' object use the CefV8Context::GetGlobal()
+  /// method. V8 handles can only be accessed from the thread on which they are
+  /// created. A task runner for posting tasks on the associated thread can be
+  /// retrieved via the CefV8Context::GetTaskRunner() method.
   ///
   /*--cef()--*/
   virtual void OnContextCreated(CefRefPtr<CefBrowser> browser,
@@ -108,8 +100,8 @@
                                 CefRefPtr<CefV8Context> context) {}
 
   ///
-  // Called immediately before the V8 context for a frame is released. No
-  // references to the context should be kept after this method is called.
+  /// Called immediately before the V8 context for a frame is released. No
+  /// references to the context should be kept after this method is called.
   ///
   /*--cef()--*/
   virtual void OnContextReleased(CefRefPtr<CefBrowser> browser,
@@ -117,9 +109,9 @@
                                  CefRefPtr<CefV8Context> context) {}
 
   ///
-  // Called for global uncaught exceptions in a frame. Execution of this
-  // callback is disabled by default. To enable set
-  // CefSettings.uncaught_exception_stack_size > 0.
+  /// Called for global uncaught exceptions in a frame. Execution of this
+  /// callback is disabled by default. To enable set
+  /// cef_settings_t.uncaught_exception_stack_size > 0.
   ///
   /*--cef()--*/
   virtual void OnUncaughtException(CefRefPtr<CefBrowser> browser,
@@ -129,12 +121,12 @@
                                    CefRefPtr<CefV8StackTrace> stackTrace) {}
 
   ///
-  // Called when a new node in the the browser gets focus. The |node| value may
-  // be empty if no specific node has gained focus. The node object passed to
-  // this method represents a snapshot of the DOM at the time this method is
-  // executed. DOM objects are only valid for the scope of this method. Do not
-  // keep references to or attempt to access any DOM objects outside the scope
-  // of this method.
+  /// Called when a new node in the the browser gets focus. The |node| value may
+  /// be empty if no specific node has gained focus. The node object passed to
+  /// this method represents a snapshot of the DOM at the time this method is
+  /// executed. DOM objects are only valid for the scope of this method. Do not
+  /// keep references to or attempt to access any DOM objects outside the scope
+  /// of this method.
   ///
   /*--cef(optional_param=frame,optional_param=node)--*/
   virtual void OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
@@ -142,9 +134,9 @@
                                     CefRefPtr<CefDOMNode> node) {}
 
   ///
-  // Called when a new message is received from a different process. Return true
-  // if the message was handled or false otherwise. Do not keep a reference to
-  // or attempt to access the message outside of this callback.
+  /// Called when a new message is received from a different process. Return
+  /// true if the message was handled or false otherwise. It is safe to keep a
+  /// reference to |message| outside of this callback.
   ///
   /*--cef()--*/
   virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
diff --git a/src/include/cef_request.h b/src/include/cef_request.h
index cbe2d03..5f5a440 100644
--- a/src/include/cef_request.h
+++ b/src/include/cef_request.h
@@ -46,8 +46,8 @@
 class CefPostDataElement;
 
 ///
-// Class used to represent a web request. The methods of this class may be
-// called on any thread.
+/// Class used to represent a web request. The methods of this class may be
+/// called on any thread.
 ///
 /*--cef(source=library,no_debugct_check)--*/
 class CefRequest : public virtual CefBaseRefCounted {
@@ -58,101 +58,101 @@
   typedef cef_transition_type_t TransitionType;
 
   ///
-  // Create a new CefRequest object.
+  /// Create a new CefRequest object.
   ///
   /*--cef()--*/
   static CefRefPtr<CefRequest> Create();
 
   ///
-  // Returns true if this object is read-only.
+  /// Returns true if this object is read-only.
   ///
   /*--cef()--*/
   virtual bool IsReadOnly() = 0;
 
   ///
-  // Get the fully qualified URL.
+  /// Get the fully qualified URL.
   ///
   /*--cef()--*/
   virtual CefString GetURL() = 0;
 
   ///
-  // Set the fully qualified URL.
+  /// Set the fully qualified URL.
   ///
   /*--cef()--*/
   virtual void SetURL(const CefString& url) = 0;
 
   ///
-  // Get the request method type. The value will default to POST if post data
-  // is provided and GET otherwise.
+  /// Get the request method type. The value will default to POST if post data
+  /// is provided and GET otherwise.
   ///
   /*--cef()--*/
   virtual CefString GetMethod() = 0;
 
   ///
-  // Set the request method type.
+  /// Set the request method type.
   ///
   /*--cef()--*/
   virtual void SetMethod(const CefString& method) = 0;
 
   ///
-  // Set the referrer URL and policy. If non-empty the referrer URL must be
-  // fully qualified with an HTTP or HTTPS scheme component. Any username,
-  // password or ref component will be removed.
+  /// Set the referrer URL and policy. If non-empty the referrer URL must be
+  /// fully qualified with an HTTP or HTTPS scheme component. Any username,
+  /// password or ref component will be removed.
   ///
   /*--cef(optional_param=referrer_url)--*/
   virtual void SetReferrer(const CefString& referrer_url,
                            ReferrerPolicy policy) = 0;
 
   ///
-  // Get the referrer URL.
+  /// Get the referrer URL.
   ///
   /*--cef()--*/
   virtual CefString GetReferrerURL() = 0;
 
   ///
-  // Get the referrer policy.
+  /// Get the referrer policy.
   ///
   /*--cef(default_retval=REFERRER_POLICY_DEFAULT)--*/
   virtual ReferrerPolicy GetReferrerPolicy() = 0;
 
   ///
-  // Get the post data.
+  /// Get the post data.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefPostData> GetPostData() = 0;
 
   ///
-  // Set the post data.
+  /// Set the post data.
   ///
   /*--cef()--*/
   virtual void SetPostData(CefRefPtr<CefPostData> postData) = 0;
 
   ///
-  // Get the header values. Will not include the Referer value if any.
+  /// Get the header values. Will not include the Referer value if any.
   ///
   /*--cef()--*/
   virtual void GetHeaderMap(HeaderMap& headerMap) = 0;
 
   ///
-  // Set the header values. If a Referer value exists in the header map it will
-  // be removed and ignored.
+  /// Set the header values. If a Referer value exists in the header map it will
+  /// be removed and ignored.
   ///
   /*--cef()--*/
   virtual void SetHeaderMap(const HeaderMap& headerMap) = 0;
 
   ///
-  // Returns the first header value for |name| or an empty string if not found.
-  // Will not return the Referer value if any. Use GetHeaderMap instead if
-  // |name| might have multiple values.
+  /// Returns the first header value for |name| or an empty string if not found.
+  /// Will not return the Referer value if any. Use GetHeaderMap instead if
+  /// |name| might have multiple values.
   ///
   /*--cef()--*/
   virtual CefString GetHeaderByName(const CefString& name) = 0;
 
   ///
-  // Set the header |name| to |value|. If |overwrite| is true any existing
-  // values will be replaced with the new value. If |overwrite| is false any
-  // existing values will not be overwritten. The Referer value cannot be set
-  // using this method.
+  /// Set the header |name| to |value|. If |overwrite| is true any existing
+  /// values will be replaced with the new value. If |overwrite| is false any
+  /// existing values will not be overwritten. The Referer value cannot be set
+  /// using this method.
   ///
   /*--cef(optional_param=value)--*/
   virtual void SetHeaderByName(const CefString& name,
@@ -160,7 +160,7 @@
                                bool overwrite) = 0;
 
   ///
-  // Set all values at one time.
+  /// Set all values at one time.
   ///
   /*--cef(optional_param=postData)--*/
   virtual void Set(const CefString& url,
@@ -169,60 +169,60 @@
                    const HeaderMap& headerMap) = 0;
 
   ///
-  // Get the flags used in combination with CefURLRequest. See
-  // cef_urlrequest_flags_t for supported values.
+  /// Get the flags used in combination with CefURLRequest. See
+  /// cef_urlrequest_flags_t for supported values.
   ///
   /*--cef(default_retval=UR_FLAG_NONE)--*/
   virtual int GetFlags() = 0;
 
   ///
-  // Set the flags used in combination with CefURLRequest.  See
-  // cef_urlrequest_flags_t for supported values.
+  /// Set the flags used in combination with CefURLRequest.  See
+  /// cef_urlrequest_flags_t for supported values.
   ///
   /*--cef()--*/
   virtual void SetFlags(int flags) = 0;
 
   ///
-  // Get the URL to the first party for cookies used in combination with
-  // CefURLRequest.
+  /// Get the URL to the first party for cookies used in combination with
+  /// CefURLRequest.
   ///
   /*--cef()--*/
   virtual CefString GetFirstPartyForCookies() = 0;
 
   ///
-  // Set the URL to the first party for cookies used in combination with
-  // CefURLRequest.
+  /// Set the URL to the first party for cookies used in combination with
+  /// CefURLRequest.
   ///
   /*--cef(optional_param=url)--*/
   virtual void SetFirstPartyForCookies(const CefString& url) = 0;
 
   ///
-  // Get the resource type for this request. Only available in the browser
-  // process.
+  /// Get the resource type for this request. Only available in the browser
+  /// process.
   ///
   /*--cef(default_retval=RT_SUB_RESOURCE)--*/
   virtual ResourceType GetResourceType() = 0;
 
   ///
-  // Get the transition type for this request. Only available in the browser
-  // process and only applies to requests that represent a main frame or
-  // sub-frame navigation.
+  /// Get the transition type for this request. Only available in the browser
+  /// process and only applies to requests that represent a main frame or
+  /// sub-frame navigation.
   ///
   /*--cef(default_retval=TT_EXPLICIT)--*/
   virtual TransitionType GetTransitionType() = 0;
 
   ///
-  // Returns the globally unique identifier for this request or 0 if not
-  // specified. Can be used by CefResourceRequestHandler implementations in the
-  // browser process to track a single request across multiple callbacks.
+  /// Returns the globally unique identifier for this request or 0 if not
+  /// specified. Can be used by CefResourceRequestHandler implementations in the
+  /// browser process to track a single request across multiple callbacks.
   ///
   /*--cef()--*/
-  virtual uint64 GetIdentifier() = 0;
+  virtual uint64_t GetIdentifier() = 0;
 };
 
 ///
-// Class used to represent post data for a web request. The methods of this
-// class may be called on any thread.
+/// Class used to represent post data for a web request. The methods of this
+/// class may be called on any thread.
 ///
 /*--cef(source=library,no_debugct_check)--*/
 class CefPostData : public virtual CefBaseRefCounted {
@@ -230,122 +230,122 @@
   typedef std::vector<CefRefPtr<CefPostDataElement>> ElementVector;
 
   ///
-  // Create a new CefPostData object.
+  /// Create a new CefPostData object.
   ///
   /*--cef()--*/
   static CefRefPtr<CefPostData> Create();
 
   ///
-  // Returns true if this object is read-only.
+  /// Returns true if this object is read-only.
   ///
   /*--cef()--*/
   virtual bool IsReadOnly() = 0;
 
   ///
-  // Returns true if the underlying POST data includes elements that are not
-  // represented by this CefPostData object (for example, multi-part file upload
-  // data). Modifying CefPostData objects with excluded elements may result in
-  // the request failing.
+  /// Returns true if the underlying POST data includes elements that are not
+  /// represented by this CefPostData object (for example, multi-part file
+  /// upload data). Modifying CefPostData objects with excluded elements may
+  /// result in the request failing.
   ///
   /*--cef()--*/
   virtual bool HasExcludedElements() = 0;
 
   ///
-  // Returns the number of existing post data elements.
+  /// Returns the number of existing post data elements.
   ///
   /*--cef()--*/
   virtual size_t GetElementCount() = 0;
 
   ///
-  // Retrieve the post data elements.
+  /// Retrieve the post data elements.
   ///
   /*--cef(count_func=elements:GetElementCount)--*/
   virtual void GetElements(ElementVector& elements) = 0;
 
   ///
-  // Remove the specified post data element.  Returns true if the removal
-  // succeeds.
+  /// Remove the specified post data element.  Returns true if the removal
+  /// succeeds.
   ///
   /*--cef()--*/
   virtual bool RemoveElement(CefRefPtr<CefPostDataElement> element) = 0;
 
   ///
-  // Add the specified post data element.  Returns true if the add succeeds.
+  /// Add the specified post data element.  Returns true if the add succeeds.
   ///
   /*--cef()--*/
   virtual bool AddElement(CefRefPtr<CefPostDataElement> element) = 0;
 
   ///
-  // Remove all existing post data elements.
+  /// Remove all existing post data elements.
   ///
   /*--cef()--*/
   virtual void RemoveElements() = 0;
 };
 
 ///
-// Class used to represent a single element in the request post data. The
-// methods of this class may be called on any thread.
+/// Class used to represent a single element in the request post data. The
+/// methods of this class may be called on any thread.
 ///
 /*--cef(source=library,no_debugct_check)--*/
 class CefPostDataElement : public virtual CefBaseRefCounted {
  public:
   ///
-  // Post data elements may represent either bytes or files.
+  /// Post data elements may represent either bytes or files.
   ///
   typedef cef_postdataelement_type_t Type;
 
   ///
-  // Create a new CefPostDataElement object.
+  /// Create a new CefPostDataElement object.
   ///
   /*--cef()--*/
   static CefRefPtr<CefPostDataElement> Create();
 
   ///
-  // Returns true if this object is read-only.
+  /// Returns true if this object is read-only.
   ///
   /*--cef()--*/
   virtual bool IsReadOnly() = 0;
 
   ///
-  // Remove all contents from the post data element.
+  /// Remove all contents from the post data element.
   ///
   /*--cef()--*/
   virtual void SetToEmpty() = 0;
 
   ///
-  // The post data element will represent a file.
+  /// The post data element will represent a file.
   ///
   /*--cef()--*/
   virtual void SetToFile(const CefString& fileName) = 0;
 
   ///
-  // The post data element will represent bytes.  The bytes passed
-  // in will be copied.
+  /// The post data element will represent bytes.  The bytes passed
+  /// in will be copied.
   ///
   /*--cef()--*/
   virtual void SetToBytes(size_t size, const void* bytes) = 0;
 
   ///
-  // Return the type of this post data element.
+  /// Return the type of this post data element.
   ///
   /*--cef(default_retval=PDE_TYPE_EMPTY)--*/
   virtual Type GetType() = 0;
 
   ///
-  // Return the file name.
+  /// Return the file name.
   ///
   /*--cef()--*/
   virtual CefString GetFile() = 0;
 
   ///
-  // Return the number of bytes.
+  /// Return the number of bytes.
   ///
   /*--cef()--*/
   virtual size_t GetBytesCount() = 0;
 
   ///
-  // Read up to |size| bytes into |bytes| and return the number of bytes
-  // actually read.
+  /// Read up to |size| bytes into |bytes| and return the number of bytes
+  /// actually read.
   ///
   /*--cef()--*/
   virtual size_t GetBytes(size_t size, void* bytes) = 0;
diff --git a/src/include/cef_request_context.h b/src/include/cef_request_context.h
index edb65da..1ecaf44 100644
--- a/src/include/cef_request_context.h
+++ b/src/include/cef_request_context.h
@@ -45,21 +45,22 @@
 #include "include/cef_extension.h"
 #include "include/cef_extension_handler.h"
 #include "include/cef_media_router.h"
+#include "include/cef_preference.h"
 #include "include/cef_values.h"
 
 class CefRequestContextHandler;
 class CefSchemeHandlerFactory;
 
 ///
-// Callback interface for CefRequestContext::ResolveHost.
+/// Callback interface for CefRequestContext::ResolveHost.
 ///
 /*--cef(source=client)--*/
 class CefResolveCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Called on the UI thread after the ResolveHost request has completed.
-  // |result| will be the result code. |resolved_ips| will be the list of
-  // resolved IP addresses or empty if the resolution failed.
+  /// Called on the UI thread after the ResolveHost request has completed.
+  /// |result| will be the result code. |resolved_ips| will be the list of
+  /// resolved IP addresses or empty if the resolution failed.
   ///
   /*--cef(optional_param=resolved_ips)--*/
   virtual void OnResolveCompleted(
@@ -68,33 +69,33 @@
 };
 
 ///
-// A request context provides request handling for a set of related browser
-// or URL request objects. A request context can be specified when creating a
-// new browser via the CefBrowserHost static factory methods or when creating a
-// new URL request via the CefURLRequest static factory methods. Browser objects
-// with different request contexts will never be hosted in the same render
-// process. Browser objects with the same request context may or may not be
-// hosted in the same render process depending on the process model. Browser
-// objects created indirectly via the JavaScript window.open function or
-// targeted links will share the same render process and the same request
-// context as the source browser. When running in single-process mode there is
-// only a single render process (the main process) and so all browsers created
-// in single-process mode will share the same request context. This will be the
-// first request context passed into a CefBrowserHost static factory method and
-// all other request context objects will be ignored.
+/// A request context provides request handling for a set of related browser
+/// or URL request objects. A request context can be specified when creating a
+/// new browser via the CefBrowserHost static factory methods or when creating a
+/// new URL request via the CefURLRequest static factory methods. Browser
+/// objects with different request contexts will never be hosted in the same
+/// render process. Browser objects with the same request context may or may not
+/// be hosted in the same render process depending on the process model. Browser
+/// objects created indirectly via the JavaScript window.open function or
+/// targeted links will share the same render process and the same request
+/// context as the source browser. When running in single-process mode there is
+/// only a single render process (the main process) and so all browsers created
+/// in single-process mode will share the same request context. This will be the
+/// first request context passed into a CefBrowserHost static factory method and
+/// all other request context objects will be ignored.
 ///
 /*--cef(source=library,no_debugct_check)--*/
-class CefRequestContext : public virtual CefBaseRefCounted {
+class CefRequestContext : public CefPreferenceManager {
  public:
   ///
-  // Returns the global context object.
+  /// Returns the global context object.
   ///
   /*--cef()--*/
   static CefRefPtr<CefRequestContext> GetGlobalContext();
 
   ///
-  // Creates a new context object with the specified |settings| and optional
-  // |handler|.
+  /// Creates a new context object with the specified |settings| and optional
+  /// |handler|.
   ///
   /*--cef(optional_param=handler)--*/
   static CefRefPtr<CefRequestContext> CreateContext(
@@ -102,8 +103,8 @@
       CefRefPtr<CefRequestContextHandler> handler);
 
   ///
-  // Creates a new context object that shares storage with |other| and uses an
-  // optional |handler|.
+  /// Creates a new context object that shares storage with |other| and uses an
+  /// optional |handler|.
   ///
   /*--cef(capi_name=cef_create_context_shared,optional_param=handler)--*/
   static CefRefPtr<CefRequestContext> CreateContext(
@@ -111,60 +112,60 @@
       CefRefPtr<CefRequestContextHandler> handler);
 
   ///
-  // Returns true if this object is pointing to the same context as |that|
-  // object.
+  /// Returns true if this object is pointing to the same context as |that|
+  /// object.
   ///
   /*--cef()--*/
   virtual bool IsSame(CefRefPtr<CefRequestContext> other) = 0;
 
   ///
-  // Returns true if this object is sharing the same storage as |that| object.
+  /// Returns true if this object is sharing the same storage as |that| object.
   ///
   /*--cef()--*/
   virtual bool IsSharingWith(CefRefPtr<CefRequestContext> other) = 0;
 
   ///
-  // Returns true if this object is the global context. The global context is
-  // used by default when creating a browser or URL request with a NULL context
-  // argument.
+  /// Returns true if this object is the global context. The global context is
+  /// used by default when creating a browser or URL request with a NULL context
+  /// argument.
   ///
   /*--cef()--*/
   virtual bool IsGlobal() = 0;
 
   ///
-  // Returns the handler for this context if any.
+  /// Returns the handler for this context if any.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefRequestContextHandler> GetHandler() = 0;
 
   ///
-  // Returns the cache path for this object. If empty an "incognito mode"
-  // in-memory cache is being used.
+  /// Returns the cache path for this object. If empty an "incognito mode"
+  /// in-memory cache is being used.
   ///
   /*--cef()--*/
   virtual CefString GetCachePath() = 0;
 
   ///
-  // Returns the cookie manager for this object. If |callback| is non-NULL it
-  // will be executed asnychronously on the IO thread after the manager's
-  // storage has been initialized.
+  /// Returns the cookie manager for this object. If |callback| is non-NULL it
+  /// will be executed asnychronously on the UI thread after the manager's
+  /// storage has been initialized.
   ///
   /*--cef(optional_param=callback)--*/
   virtual CefRefPtr<CefCookieManager> GetCookieManager(
       CefRefPtr<CefCompletionCallback> callback) = 0;
 
   ///
-  // Register a scheme handler factory for the specified |scheme_name| and
-  // optional |domain_name|. An empty |domain_name| value for a standard scheme
-  // will cause the factory to match all domain names. The |domain_name| value
-  // will be ignored for non-standard schemes. If |scheme_name| is a built-in
-  // scheme and no handler is returned by |factory| then the built-in scheme
-  // handler factory will be called. If |scheme_name| is a custom scheme then
-  // you must also implement the CefApp::OnRegisterCustomSchemes() method in all
-  // processes. This function may be called multiple times to change or remove
-  // the factory that matches the specified |scheme_name| and optional
-  // |domain_name|. Returns false if an error occurs. This function may be
-  // called on any thread in the browser process.
+  /// Register a scheme handler factory for the specified |scheme_name| and
+  /// optional |domain_name|. An empty |domain_name| value for a standard scheme
+  /// will cause the factory to match all domain names. The |domain_name| value
+  /// will be ignored for non-standard schemes. If |scheme_name| is a built-in
+  /// scheme and no handler is returned by |factory| then the built-in scheme
+  /// handler factory will be called. If |scheme_name| is a custom scheme then
+  /// you must also implement the CefApp::OnRegisterCustomSchemes() method in
+  /// all processes. This function may be called multiple times to change or
+  /// remove the factory that matches the specified |scheme_name| and optional
+  /// |domain_name|. Returns false if an error occurs. This function may be
+  /// called on any thread in the browser process.
   ///
   /*--cef(optional_param=domain_name,optional_param=factory)--*/
   virtual bool RegisterSchemeHandlerFactory(
@@ -173,154 +174,97 @@
       CefRefPtr<CefSchemeHandlerFactory> factory) = 0;
 
   ///
-  // Clear all registered scheme handler factories. Returns false on error. This
-  // function may be called on any thread in the browser process.
+  /// Clear all registered scheme handler factories. Returns false on error.
+  /// This function may be called on any thread in the browser process.
   ///
   /*--cef()--*/
   virtual bool ClearSchemeHandlerFactories() = 0;
 
   ///
-  // Tells all renderer processes associated with this context to throw away
-  // their plugin list cache. If |reload_pages| is true they will also reload
-  // all pages with plugins. CefRequestContextHandler::OnBeforePluginLoad may
-  // be called to rebuild the plugin list cache.
-  ///
-  /*--cef()--*/
-  virtual void PurgePluginListCache(bool reload_pages) = 0;
-
-  ///
-  // Returns true if a preference with the specified |name| exists. This method
-  // must be called on the browser process UI thread.
-  ///
-  /*--cef()--*/
-  virtual bool HasPreference(const CefString& name) = 0;
-
-  ///
-  // Returns the value for the preference with the specified |name|. Returns
-  // NULL if the preference does not exist. The returned object contains a copy
-  // of the underlying preference value and modifications to the returned object
-  // will not modify the underlying preference value. This method must be called
-  // on the browser process UI thread.
-  ///
-  /*--cef()--*/
-  virtual CefRefPtr<CefValue> GetPreference(const CefString& name) = 0;
-
-  ///
-  // Returns all preferences as a dictionary. If |include_defaults| is true then
-  // preferences currently at their default value will be included. The returned
-  // object contains a copy of the underlying preference values and
-  // modifications to the returned object will not modify the underlying
-  // preference values. This method must be called on the browser process UI
-  // thread.
-  ///
-  /*--cef()--*/
-  virtual CefRefPtr<CefDictionaryValue> GetAllPreferences(
-      bool include_defaults) = 0;
-
-  ///
-  // Returns true if the preference with the specified |name| can be modified
-  // using SetPreference. As one example preferences set via the command-line
-  // usually cannot be modified. This method must be called on the browser
-  // process UI thread.
-  ///
-  /*--cef()--*/
-  virtual bool CanSetPreference(const CefString& name) = 0;
-
-  ///
-  // Set the |value| associated with preference |name|. Returns true if the
-  // value is set successfully and false otherwise. If |value| is NULL the
-  // preference will be restored to its default value. If setting the preference
-  // fails then |error| will be populated with a detailed description of the
-  // problem. This method must be called on the browser process UI thread.
-  ///
-  /*--cef(optional_param=value)--*/
-  virtual bool SetPreference(const CefString& name,
-                             CefRefPtr<CefValue> value,
-                             CefString& error) = 0;
-
-  ///
-  // Clears all certificate exceptions that were added as part of handling
-  // CefRequestHandler::OnCertificateError(). If you call this it is
-  // recommended that you also call CloseAllConnections() or you risk not
-  // being prompted again for server certificates if you reconnect quickly.
-  // If |callback| is non-NULL it will be executed on the UI thread after
-  // completion.
+  /// Clears all certificate exceptions that were added as part of handling
+  /// CefRequestHandler::OnCertificateError(). If you call this it is
+  /// recommended that you also call CloseAllConnections() or you risk not
+  /// being prompted again for server certificates if you reconnect quickly.
+  /// If |callback| is non-NULL it will be executed on the UI thread after
+  /// completion.
   ///
   /*--cef(optional_param=callback)--*/
   virtual void ClearCertificateExceptions(
       CefRefPtr<CefCompletionCallback> callback) = 0;
 
   ///
-  // Clears all HTTP authentication credentials that were added as part of
-  // handling GetAuthCredentials. If |callback| is non-NULL it will be executed
-  // on the UI thread after completion.
+  /// Clears all HTTP authentication credentials that were added as part of
+  /// handling GetAuthCredentials. If |callback| is non-NULL it will be executed
+  /// on the UI thread after completion.
   ///
   /*--cef(optional_param=callback)--*/
   virtual void ClearHttpAuthCredentials(
       CefRefPtr<CefCompletionCallback> callback) = 0;
 
   ///
-  // Clears all active and idle connections that Chromium currently has.
-  // This is only recommended if you have released all other CEF objects but
-  // don't yet want to call CefShutdown(). If |callback| is non-NULL it will be
-  // executed on the UI thread after completion.
+  /// Clears all active and idle connections that Chromium currently has.
+  /// This is only recommended if you have released all other CEF objects but
+  /// don't yet want to call CefShutdown(). If |callback| is non-NULL it will be
+  /// executed on the UI thread after completion.
   ///
   /*--cef(optional_param=callback)--*/
   virtual void CloseAllConnections(
       CefRefPtr<CefCompletionCallback> callback) = 0;
 
   ///
-  // Attempts to resolve |origin| to a list of associated IP addresses.
-  // |callback| will be executed on the UI thread after completion.
+  /// Attempts to resolve |origin| to a list of associated IP addresses.
+  /// |callback| will be executed on the UI thread after completion.
   ///
   /*--cef()--*/
   virtual void ResolveHost(const CefString& origin,
                            CefRefPtr<CefResolveCallback> callback) = 0;
 
   ///
-  // Load an extension.
-  //
-  // If extension resources will be read from disk using the default load
-  // implementation then |root_directory| should be the absolute path to the
-  // extension resources directory and |manifest| should be NULL. If extension
-  // resources will be provided by the client (e.g. via CefRequestHandler and/or
-  // CefExtensionHandler) then |root_directory| should be a path component
-  // unique to the extension (if not absolute this will be internally prefixed
-  // with the PK_DIR_RESOURCES path) and |manifest| should contain the contents
-  // that would otherwise be read from the "manifest.json" file on disk.
-  //
-  // The loaded extension will be accessible in all contexts sharing the same
-  // storage (HasExtension returns true). However, only the context on which
-  // this method was called is considered the loader (DidLoadExtension returns
-  // true) and only the loader will receive CefRequestContextHandler callbacks
-  // for the extension.
-  //
-  // CefExtensionHandler::OnExtensionLoaded will be called on load success or
-  // CefExtensionHandler::OnExtensionLoadFailed will be called on load failure.
-  //
-  // If the extension specifies a background script via the "background"
-  // manifest key then CefExtensionHandler::OnBeforeBackgroundBrowser will be
-  // called to create the background browser. See that method for additional
-  // information about background scripts.
-  //
-  // For visible extension views the client application should evaluate the
-  // manifest to determine the correct extension URL to load and then pass that
-  // URL to the CefBrowserHost::CreateBrowser* function after the extension has
-  // loaded. For example, the client can look for the "browser_action" manifest
-  // key as documented at https://developer.chrome.com/extensions/browserAction.
-  // Extension URLs take the form "chrome-extension://<extension_id>/<path>".
-  //
-  // Browsers that host extensions differ from normal browsers as follows:
-  //  - Can access chrome.* JavaScript APIs if allowed by the manifest. Visit
-  //    chrome://extensions-support for the list of extension APIs currently
-  //    supported by CEF.
-  //  - Main frame navigation to non-extension content is blocked.
-  //  - Pinch-zooming is disabled.
-  //  - CefBrowserHost::GetExtension returns the hosted extension.
-  //  - CefBrowserHost::IsBackgroundHost returns true for background hosts.
-  //
-  // See https://developer.chrome.com/extensions for extension implementation
-  // and usage documentation.
+  /// Load an extension.
+  ///
+  /// If extension resources will be read from disk using the default load
+  /// implementation then |root_directory| should be the absolute path to the
+  /// extension resources directory and |manifest| should be NULL. If extension
+  /// resources will be provided by the client (e.g. via CefRequestHandler
+  /// and/or CefExtensionHandler) then |root_directory| should be a path
+  /// component unique to the extension (if not absolute this will be internally
+  /// prefixed with the PK_DIR_RESOURCES path) and |manifest| should contain the
+  /// contents that would otherwise be read from the "manifest.json" file on
+  /// disk.
+  ///
+  /// The loaded extension will be accessible in all contexts sharing the same
+  /// storage (HasExtension returns true). However, only the context on which
+  /// this method was called is considered the loader (DidLoadExtension returns
+  /// true) and only the loader will receive CefRequestContextHandler callbacks
+  /// for the extension.
+  ///
+  /// CefExtensionHandler::OnExtensionLoaded will be called on load success or
+  /// CefExtensionHandler::OnExtensionLoadFailed will be called on load failure.
+  ///
+  /// If the extension specifies a background script via the "background"
+  /// manifest key then CefExtensionHandler::OnBeforeBackgroundBrowser will be
+  /// called to create the background browser. See that method for additional
+  /// information about background scripts.
+  ///
+  /// For visible extension views the client application should evaluate the
+  /// manifest to determine the correct extension URL to load and then pass that
+  /// URL to the CefBrowserHost::CreateBrowser* function after the extension has
+  /// loaded. For example, the client can look for the "browser_action" manifest
+  /// key as documented at
+  /// https://developer.chrome.com/extensions/browserAction. Extension URLs take
+  /// the form "chrome-extension://<extension_id>/<path>".
+  ///
+  /// Browsers that host extensions differ from normal browsers as follows:
+  ///  - Can access chrome.* JavaScript APIs if allowed by the manifest. Visit
+  ///    chrome://extensions-support for the list of extension APIs currently
+  ///    supported by CEF.
+  ///  - Main frame navigation to non-extension content is blocked.
+  ///  - Pinch-zooming is disabled.
+  ///  - CefBrowserHost::GetExtension returns the hosted extension.
+  ///  - CefBrowserHost::IsBackgroundHost returns true for background hosts.
+  ///
+  /// See https://developer.chrome.com/extensions for extension implementation
+  /// and usage documentation.
   ///
   /*--cef(optional_param=manifest,optional_param=handler)--*/
   virtual void LoadExtension(const CefString& root_directory,
@@ -328,46 +272,115 @@
                              CefRefPtr<CefExtensionHandler> handler) = 0;
 
   ///
-  // Returns true if this context was used to load the extension identified by
-  // |extension_id|. Other contexts sharing the same storage will also have
-  // access to the extension (see HasExtension). This method must be called on
-  // the browser process UI thread.
+  /// Returns true if this context was used to load the extension identified by
+  /// |extension_id|. Other contexts sharing the same storage will also have
+  /// access to the extension (see HasExtension). This method must be called on
+  /// the browser process UI thread.
   ///
   /*--cef()--*/
   virtual bool DidLoadExtension(const CefString& extension_id) = 0;
 
   ///
-  // Returns true if this context has access to the extension identified by
-  // |extension_id|. This may not be the context that was used to load the
-  // extension (see DidLoadExtension). This method must be called on the browser
-  // process UI thread.
+  /// Returns true if this context has access to the extension identified by
+  /// |extension_id|. This may not be the context that was used to load the
+  /// extension (see DidLoadExtension). This method must be called on the
+  /// browser process UI thread.
   ///
   /*--cef()--*/
   virtual bool HasExtension(const CefString& extension_id) = 0;
 
   ///
-  // Retrieve the list of all extensions that this context has access to (see
-  // HasExtension). |extension_ids| will be populated with the list of extension
-  // ID values. Returns true on success. This method must be called on the
-  // browser process UI thread.
+  /// Retrieve the list of all extensions that this context has access to (see
+  /// HasExtension). |extension_ids| will be populated with the list of
+  /// extension ID values. Returns true on success. This method must be called
+  /// on the browser process UI thread.
   ///
   /*--cef()--*/
   virtual bool GetExtensions(std::vector<CefString>& extension_ids) = 0;
 
   ///
-  // Returns the extension matching |extension_id| or NULL if no matching
-  // extension is accessible in this context (see HasExtension). This method
-  // must be called on the browser process UI thread.
+  /// Returns the extension matching |extension_id| or NULL if no matching
+  /// extension is accessible in this context (see HasExtension). This method
+  /// must be called on the browser process UI thread.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefExtension> GetExtension(
       const CefString& extension_id) = 0;
 
   ///
-  // Returns the MediaRouter object associated with this context.
+  /// Returns the MediaRouter object associated with this context.  If
+  /// |callback| is non-NULL it will be executed asnychronously on the UI thread
+  /// after the manager's context has been initialized.
   ///
-  /*--cef()--*/
-  virtual CefRefPtr<CefMediaRouter> GetMediaRouter() = 0;
+  /*--cef(optional_param=callback)--*/
+  virtual CefRefPtr<CefMediaRouter> GetMediaRouter(
+      CefRefPtr<CefCompletionCallback> callback) = 0;
+
+  ///
+  /// Returns the current value for |content_type| that applies for the
+  /// specified URLs. If both URLs are empty the default value will be returned.
+  /// Returns nullptr if no value is configured. Must be called on the browser
+  /// process UI thread.
+  ///
+  /*--cef(optional_param=requesting_url,optional_param=top_level_url)--*/
+  virtual CefRefPtr<CefValue> GetWebsiteSetting(
+      const CefString& requesting_url,
+      const CefString& top_level_url,
+      cef_content_setting_types_t content_type) = 0;
+
+  ///
+  /// Sets the current value for |content_type| for the specified URLs in the
+  /// default scope. If both URLs are empty, and the context is not incognito,
+  /// the default value will be set. Pass nullptr for |value| to remove the
+  /// default value for this content type.
+  ///
+  /// WARNING: Incorrect usage of this method may cause instability or security
+  /// issues in Chromium. Make sure that you first understand the potential
+  /// impact of any changes to |content_type| by reviewing the related source
+  /// code in Chromium. For example, if you plan to modify
+  /// CEF_CONTENT_SETTING_TYPE_POPUPS, first review and understand the usage of
+  /// ContentSettingsType::POPUPS in Chromium:
+  /// https://source.chromium.org/search?q=ContentSettingsType::POPUPS
+  ///
+  /*--cef(optional_param=requesting_url,optional_param=top_level_url,
+          optional_param=value)--*/
+  virtual void SetWebsiteSetting(const CefString& requesting_url,
+                                 const CefString& top_level_url,
+                                 cef_content_setting_types_t content_type,
+                                 CefRefPtr<CefValue> value) = 0;
+
+  ///
+  /// Returns the current value for |content_type| that applies for the
+  /// specified URLs. If both URLs are empty the default value will be returned.
+  /// Returns CEF_CONTENT_SETTING_VALUE_DEFAULT if no value is configured. Must
+  /// be called on the browser process UI thread.
+  ///
+  /*--cef(optional_param=requesting_url,optional_param=top_level_url,
+          default_retval=CEF_CONTENT_SETTING_VALUE_DEFAULT)--*/
+  virtual cef_content_setting_values_t GetContentSetting(
+      const CefString& requesting_url,
+      const CefString& top_level_url,
+      cef_content_setting_types_t content_type) = 0;
+
+  ///
+  /// Sets the current value for |content_type| for the specified URLs in the
+  /// default scope. If both URLs are empty, and the context is not incognito,
+  /// the default value will be set. Pass CEF_CONTENT_SETTING_VALUE_DEFAULT for
+  /// |value| to use the default value for this content type.
+  ///
+  /// WARNING: Incorrect usage of this method may cause instability or security
+  /// issues in Chromium. Make sure that you first understand the potential
+  /// impact of any changes to |content_type| by reviewing the related source
+  /// code in Chromium. For example, if you plan to modify
+  /// CEF_CONTENT_SETTING_TYPE_POPUPS, first review and understand the usage of
+  /// ContentSettingsType::POPUPS in Chromium:
+  /// https://source.chromium.org/search?q=ContentSettingsType::POPUPS
+  ///
+  /*--cef(optional_param=requesting_url,optional_param=top_level_url)--*/
+  virtual void SetContentSetting(const CefString& requesting_url,
+                                 const CefString& top_level_url,
+                                 cef_content_setting_types_t content_type,
+                                 cef_content_setting_values_t value) = 0;
 };
 
 #endif  // CEF_INCLUDE_CEF_REQUEST_CONTEXT_H_
diff --git a/src/include/cef_request_context_handler.h b/src/include/cef_request_context_handler.h
index 13cf164..ac8c771 100644
--- a/src/include/cef_request_context_handler.h
+++ b/src/include/cef_request_context_handler.h
@@ -41,73 +41,43 @@
 #include "include/cef_base.h"
 #include "include/cef_browser.h"
 #include "include/cef_frame.h"
+#include "include/cef_preference.h"
 #include "include/cef_request.h"
 #include "include/cef_resource_request_handler.h"
-#include "include/cef_web_plugin.h"
 
 ///
-// Implement this interface to provide handler implementations. The handler
-// instance will not be released until all objects related to the context have
-// been destroyed.
+/// Implement this interface to provide handler implementations. The handler
+/// instance will not be released until all objects related to the context have
+/// been destroyed.
 ///
 /*--cef(source=client,no_debugct_check)--*/
 class CefRequestContextHandler : public virtual CefBaseRefCounted {
  public:
-  typedef cef_plugin_policy_t PluginPolicy;
-
   ///
-  // Called on the browser process UI thread immediately after the request
-  // context has been initialized.
+  /// Called on the browser process UI thread immediately after the request
+  /// context has been initialized.
   ///
   /*--cef()--*/
   virtual void OnRequestContextInitialized(
       CefRefPtr<CefRequestContext> request_context) {}
 
   ///
-  // Called on multiple browser process threads before a plugin instance is
-  // loaded. |mime_type| is the mime type of the plugin that will be loaded.
-  // |plugin_url| is the content URL that the plugin will load and may be empty.
-  // |is_main_frame| will be true if the plugin is being loaded in the main
-  // (top-level) frame, |top_origin_url| is the URL for the top-level frame that
-  // contains the plugin when loading a specific plugin instance or empty when
-  // building the initial list of enabled plugins for 'navigator.plugins'
-  // JavaScript state. |plugin_info| includes additional information about the
-  // plugin that will be loaded. |plugin_policy| is the recommended policy.
-  // Modify |plugin_policy| and return true to change the policy. Return false
-  // to use the recommended policy. The default plugin policy can be set at
-  // runtime using the `--plugin-policy=[allow|detect|block]` command-line flag.
-  // Decisions to mark a plugin as disabled by setting |plugin_policy| to
-  // PLUGIN_POLICY_DISABLED may be cached when |top_origin_url| is empty. To
-  // purge the plugin list cache and potentially trigger new calls to this
-  // method call CefRequestContext::PurgePluginListCache.
-  ///
-  /*--cef(optional_param=plugin_url,optional_param=top_origin_url)--*/
-  virtual bool OnBeforePluginLoad(const CefString& mime_type,
-                                  const CefString& plugin_url,
-                                  bool is_main_frame,
-                                  const CefString& top_origin_url,
-                                  CefRefPtr<CefWebPluginInfo> plugin_info,
-                                  PluginPolicy* plugin_policy) {
-    return false;
-  }
-
-  ///
-  // Called on the browser process IO thread before a resource request is
-  // initiated. The |browser| and |frame| values represent the source of the
-  // request, and may be NULL for requests originating from service workers or
-  // CefURLRequest. |request| represents the request contents and cannot be
-  // modified in this callback. |is_navigation| will be true if the resource
-  // request is a navigation. |is_download| will be true if the resource request
-  // is a download. |request_initiator| is the origin (scheme + domain) of the
-  // page that initiated the request. Set |disable_default_handling| to true to
-  // disable default handling of the request, in which case it will need to be
-  // handled via CefResourceRequestHandler::GetResourceHandler or it will be
-  // canceled. To allow the resource load to proceed with default handling
-  // return NULL. To specify a handler for the resource return a
-  // CefResourceRequestHandler object. This method will not be called if the
-  // client associated with |browser| returns a non-NULL value from
-  // CefRequestHandler::GetResourceRequestHandler for the same request
-  // (identified by CefRequest::GetIdentifier).
+  /// Called on the browser process IO thread before a resource request is
+  /// initiated. The |browser| and |frame| values represent the source of the
+  /// request, and may be NULL for requests originating from service workers or
+  /// CefURLRequest. |request| represents the request contents and cannot be
+  /// modified in this callback. |is_navigation| will be true if the resource
+  /// request is a navigation. |is_download| will be true if the resource
+  /// request is a download. |request_initiator| is the origin (scheme + domain)
+  /// of the page that initiated the request. Set |disable_default_handling| to
+  /// true to disable default handling of the request, in which case it will
+  /// need to be handled via CefResourceRequestHandler::GetResourceHandler or it
+  /// will be canceled. To allow the resource load to proceed with default
+  /// handling return NULL. To specify a handler for the resource return a
+  /// CefResourceRequestHandler object. This method will not be called if the
+  /// client associated with |browser| returns a non-NULL value from
+  /// CefRequestHandler::GetResourceRequestHandler for the same request
+  /// (identified by CefRequest::GetIdentifier).
   ///
   /*--cef(optional_param=browser,optional_param=frame,
           optional_param=request_initiator)--*/
diff --git a/src/include/cef_request_handler.h b/src/include/cef_request_handler.h
index c255057..edeefbd 100644
--- a/src/include/cef_request_handler.h
+++ b/src/include/cef_request_handler.h
@@ -43,30 +43,30 @@
 #include "include/cef_auth_callback.h"
 #include "include/cef_base.h"
 #include "include/cef_browser.h"
+#include "include/cef_callback.h"
 #include "include/cef_frame.h"
 #include "include/cef_request.h"
-#include "include/cef_request_callback.h"
 #include "include/cef_resource_request_handler.h"
 #include "include/cef_ssl_info.h"
 #include "include/cef_x509_certificate.h"
 
 ///
-// Callback interface used to select a client certificate for authentication.
+/// Callback interface used to select a client certificate for authentication.
 ///
 /*--cef(source=library)--*/
 class CefSelectClientCertificateCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Chooses the specified certificate for client certificate authentication.
-  // NULL value means that no client certificate should be used.
+  /// Chooses the specified certificate for client certificate authentication.
+  /// NULL value means that no client certificate should be used.
   ///
   /*--cef(optional_param=cert)--*/
   virtual void Select(CefRefPtr<CefX509Certificate> cert) = 0;
 };
 
 ///
-// Implement this interface to handle events related to browser requests. The
-// methods of this class will be called on the thread indicated.
+/// Implement this interface to handle events related to browser requests. The
+/// methods of this class will be called on the thread indicated.
 ///
 /*--cef(source=client)--*/
 class CefRequestHandler : public virtual CefBaseRefCounted {
@@ -76,16 +76,16 @@
   typedef std::vector<CefRefPtr<CefX509Certificate>> X509CertificateList;
 
   ///
-  // Called on the UI thread before browser navigation. Return true to cancel
-  // the navigation or false to allow the navigation to proceed. The |request|
-  // object cannot be modified in this callback.
-  // CefLoadHandler::OnLoadingStateChange will be called twice in all cases.
-  // If the navigation is allowed CefLoadHandler::OnLoadStart and
-  // CefLoadHandler::OnLoadEnd will be called. If the navigation is canceled
-  // CefLoadHandler::OnLoadError will be called with an |errorCode| value of
-  // ERR_ABORTED. The |user_gesture| value will be true if the browser
-  // navigated via explicit user gesture (e.g. clicking a link) or false if it
-  // navigated automatically (e.g. via the DomContentLoaded event).
+  /// Called on the UI thread before browser navigation. Return true to cancel
+  /// the navigation or false to allow the navigation to proceed. The |request|
+  /// object cannot be modified in this callback.
+  /// CefLoadHandler::OnLoadingStateChange will be called twice in all cases.
+  /// If the navigation is allowed CefLoadHandler::OnLoadStart and
+  /// CefLoadHandler::OnLoadEnd will be called. If the navigation is canceled
+  /// CefLoadHandler::OnLoadError will be called with an |errorCode| value of
+  /// ERR_ABORTED. The |user_gesture| value will be true if the browser
+  /// navigated via explicit user gesture (e.g. clicking a link) or false if it
+  /// navigated automatically (e.g. via the DomContentLoaded event).
   ///
   /*--cef()--*/
   virtual bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
@@ -97,20 +97,20 @@
   }
 
   ///
-  // Called on the UI thread before OnBeforeBrowse in certain limited cases
-  // where navigating a new or different browser might be desirable. This
-  // includes user-initiated navigation that might open in a special way (e.g.
-  // links clicked via middle-click or ctrl + left-click) and certain types of
-  // cross-origin navigation initiated from the renderer process (e.g.
-  // navigating the top-level frame to/from a file URL). The |browser| and
-  // |frame| values represent the source of the navigation. The
-  // |target_disposition| value indicates where the user intended to navigate
-  // the browser based on standard Chromium behaviors (e.g. current tab,
-  // new tab, etc). The |user_gesture| value will be true if the browser
-  // navigated via explicit user gesture (e.g. clicking a link) or false if it
-  // navigated automatically (e.g. via the DomContentLoaded event). Return true
-  // to cancel the navigation or false to allow the navigation to proceed in the
-  // source browser's top-level frame.
+  /// Called on the UI thread before OnBeforeBrowse in certain limited cases
+  /// where navigating a new or different browser might be desirable. This
+  /// includes user-initiated navigation that might open in a special way (e.g.
+  /// links clicked via middle-click or ctrl + left-click) and certain types of
+  /// cross-origin navigation initiated from the renderer process (e.g.
+  /// navigating the top-level frame to/from a file URL). The |browser| and
+  /// |frame| values represent the source of the navigation. The
+  /// |target_disposition| value indicates where the user intended to navigate
+  /// the browser based on standard Chromium behaviors (e.g. current tab,
+  /// new tab, etc). The |user_gesture| value will be true if the browser
+  /// navigated via explicit user gesture (e.g. clicking a link) or false if it
+  /// navigated automatically (e.g. via the DomContentLoaded event). Return true
+  /// to cancel the navigation or false to allow the navigation to proceed in
+  /// the source browser's top-level frame.
   ///
   /*--cef()--*/
   virtual bool OnOpenURLFromTab(CefRefPtr<CefBrowser> browser,
@@ -122,19 +122,19 @@
   }
 
   ///
-  // Called on the browser process IO thread before a resource request is
-  // initiated. The |browser| and |frame| values represent the source of the
-  // request. |request| represents the request contents and cannot be modified
-  // in this callback. |is_navigation| will be true if the resource request is a
-  // navigation. |is_download| will be true if the resource request is a
-  // download. |request_initiator| is the origin (scheme + domain) of the page
-  // that initiated the request. Set |disable_default_handling| to true to
-  // disable default handling of the request, in which case it will need to be
-  // handled via CefResourceRequestHandler::GetResourceHandler or it will be
-  // canceled. To allow the resource load to proceed with default handling
-  // return NULL. To specify a handler for the resource return a
-  // CefResourceRequestHandler object. If this callback returns NULL the same
-  // method will be called on the associated CefRequestContextHandler, if any.
+  /// Called on the browser process IO thread before a resource request is
+  /// initiated. The |browser| and |frame| values represent the source of the
+  /// request. |request| represents the request contents and cannot be modified
+  /// in this callback. |is_navigation| will be true if the resource request is
+  /// a navigation. |is_download| will be true if the resource request is a
+  /// download. |request_initiator| is the origin (scheme + domain) of the page
+  /// that initiated the request. Set |disable_default_handling| to true to
+  /// disable default handling of the request, in which case it will need to be
+  /// handled via CefResourceRequestHandler::GetResourceHandler or it will be
+  /// canceled. To allow the resource load to proceed with default handling
+  /// return NULL. To specify a handler for the resource return a
+  /// CefResourceRequestHandler object. If this callback returns NULL the same
+  /// method will be called on the associated CefRequestContextHandler, if any.
   ///
   /*--cef(optional_param=request_initiator)--*/
   virtual CefRefPtr<CefResourceRequestHandler> GetResourceRequestHandler(
@@ -149,16 +149,16 @@
   }
 
   ///
-  // Called on the IO thread when the browser needs credentials from the user.
-  // |origin_url| is the origin making this authentication request. |isProxy|
-  // indicates whether the host is a proxy server. |host| contains the hostname
-  // and |port| contains the port number. |realm| is the realm of the challenge
-  // and may be empty. |scheme| is the authentication scheme used, such as
-  // "basic" or "digest", and will be empty if the source of the request is an
-  // FTP server. Return true to continue the request and call
-  // CefAuthCallback::Continue() either in this method or at a later time when
-  // the authentication information is available. Return false to cancel the
-  // request immediately.
+  /// Called on the IO thread when the browser needs credentials from the user.
+  /// |origin_url| is the origin making this authentication request. |isProxy|
+  /// indicates whether the host is a proxy server. |host| contains the hostname
+  /// and |port| contains the port number. |realm| is the realm of the challenge
+  /// and may be empty. |scheme| is the authentication scheme used, such as
+  /// "basic" or "digest", and will be empty if the source of the request is an
+  /// FTP server. Return true to continue the request and call
+  /// CefAuthCallback::Continue() either in this method or at a later time when
+  /// the authentication information is available. Return false to cancel the
+  /// request immediately.
   ///
   /*--cef(optional_param=realm,optional_param=scheme)--*/
   virtual bool GetAuthCredentials(CefRefPtr<CefBrowser> browser,
@@ -173,49 +173,34 @@
   }
 
   ///
-  // Called on the IO thread when JavaScript requests a specific storage quota
-  // size via the webkitStorageInfo.requestQuota function. |origin_url| is the
-  // origin of the page making the request. |new_size| is the requested quota
-  // size in bytes. Return true to continue the request and call
-  // CefRequestCallback::Continue() either in this method or at a later time to
-  // grant or deny the request. Return false to cancel the request immediately.
-  ///
-  /*--cef()--*/
-  virtual bool OnQuotaRequest(CefRefPtr<CefBrowser> browser,
-                              const CefString& origin_url,
-                              int64 new_size,
-                              CefRefPtr<CefRequestCallback> callback) {
-    return false;
-  }
-
-  ///
-  // Called on the UI thread to handle requests for URLs with an invalid
-  // SSL certificate. Return true and call CefRequestCallback::Continue() either
-  // in this method or at a later time to continue or cancel the request. Return
-  // false to cancel the request immediately. If
-  // CefSettings.ignore_certificate_errors is set all invalid certificates will
-  // be accepted without calling this method.
+  /// Called on the UI thread to handle requests for URLs with an invalid
+  /// SSL certificate. Return true and call CefCallback methods either in this
+  /// method or at a later time to continue or cancel the request. Return false
+  /// to cancel the request immediately. If
+  /// cef_settings_t.ignore_certificate_errors is set all invalid certificates
+  /// will be accepted without calling this method.
   ///
   /*--cef()--*/
   virtual bool OnCertificateError(CefRefPtr<CefBrowser> browser,
                                   cef_errorcode_t cert_error,
                                   const CefString& request_url,
                                   CefRefPtr<CefSSLInfo> ssl_info,
-                                  CefRefPtr<CefRequestCallback> callback) {
+                                  CefRefPtr<CefCallback> callback) {
     return false;
   }
 
   ///
-  // Called on the UI thread when a client certificate is being requested for
-  // authentication. Return false to use the default behavior and automatically
-  // select the first certificate available. Return true and call
-  // CefSelectClientCertificateCallback::Select either in this method or at a
-  // later time to select a certificate. Do not call Select or call it with NULL
-  // to continue without using any certificate. |isProxy| indicates whether the
-  // host is an HTTPS proxy or the origin server. |host| and |port| contains the
-  // hostname and port of the SSL server. |certificates| is the list of
-  // certificates to choose from; this list has already been pruned by Chromium
-  // so that it only contains certificates from issuers that the server trusts.
+  /// Called on the UI thread when a client certificate is being requested for
+  /// authentication. Return false to use the default behavior and automatically
+  /// select the first certificate available. Return true and call
+  /// CefSelectClientCertificateCallback::Select either in this method or at a
+  /// later time to select a certificate. Do not call Select or call it with
+  /// NULL to continue without using any certificate. |isProxy| indicates
+  /// whether the host is an HTTPS proxy or the origin server. |host| and |port|
+  /// contains the hostname and port of the SSL server. |certificates| is the
+  /// list of certificates to choose from; this list has already been pruned by
+  /// Chromium so that it only contains certificates from issuers that the
+  /// server trusts.
   ///
   /*--cef()--*/
   virtual bool OnSelectClientCertificate(
@@ -229,33 +214,25 @@
   }
 
   ///
-  // Called on the browser process UI thread when a plugin has crashed.
-  // |plugin_path| is the path of the plugin that crashed.
-  ///
-  /*--cef()--*/
-  virtual void OnPluginCrashed(CefRefPtr<CefBrowser> browser,
-                               const CefString& plugin_path) {}
-
-  ///
-  // Called on the browser process UI thread when the render view associated
-  // with |browser| is ready to receive/handle IPC messages in the render
-  // process.
+  /// Called on the browser process UI thread when the render view associated
+  /// with |browser| is ready to receive/handle IPC messages in the render
+  /// process.
   ///
   /*--cef()--*/
   virtual void OnRenderViewReady(CefRefPtr<CefBrowser> browser) {}
 
   ///
-  // Called on the browser process UI thread when the render process
-  // terminates unexpectedly. |status| indicates how the process
-  // terminated.
+  /// Called on the browser process UI thread when the render process
+  /// terminates unexpectedly. |status| indicates how the process
+  /// terminated.
   ///
   /*--cef()--*/
   virtual void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
                                          TerminationStatus status) {}
 
   ///
-  // Called on the browser process UI thread when the window.document object of
-  // the main frame has been created.
+  /// Called on the browser process UI thread when the window.document object of
+  /// the main frame has been created.
   ///
   /*--cef()--*/
   virtual void OnDocumentAvailableInMainFrame(CefRefPtr<CefBrowser> browser) {}
diff --git a/src/include/cef_resource_bundle.h b/src/include/cef_resource_bundle.h
index c08f5b0..d235e1c 100644
--- a/src/include/cef_resource_bundle.h
+++ b/src/include/cef_resource_bundle.h
@@ -39,13 +39,14 @@
 #pragma once
 
 #include "include/cef_base.h"
+#include "include/cef_values.h"
 
 ///
-// Class used for retrieving resources from the resource bundle (*.pak) files
-// loaded by CEF during startup or via the CefResourceBundleHandler returned
-// from CefApp::GetResourceBundleHandler. See CefSettings for additional options
-// related to resource bundle loading. The methods of this class may be called
-// on any thread unless otherwise indicated.
+/// Class used for retrieving resources from the resource bundle (*.pak) files
+/// loaded by CEF during startup or via the CefResourceBundleHandler returned
+/// from CefApp::GetResourceBundleHandler. See CefSettings for additional
+/// options related to resource bundle loading. The methods of this class may be
+/// called on any thread unless otherwise indicated.
 ///
 /*--cef(source=library,no_debugct_check)--*/
 class CefResourceBundle : public virtual CefBaseRefCounted {
@@ -53,47 +54,38 @@
   typedef cef_scale_factor_t ScaleFactor;
 
   ///
-  // Returns the global resource bundle instance.
+  /// Returns the global resource bundle instance.
   ///
   /*--cef()--*/
   static CefRefPtr<CefResourceBundle> GetGlobal();
 
   ///
-  // Returns the localized string for the specified |string_id| or an empty
-  // string if the value is not found. Include cef_pack_strings.h for a listing
-  // of valid string ID values.
+  /// Returns the localized string for the specified |string_id| or an empty
+  /// string if the value is not found. Include cef_pack_strings.h for a listing
+  /// of valid string ID values.
   ///
   /*--cef()--*/
   virtual CefString GetLocalizedString(int string_id) = 0;
 
   ///
-  // Retrieves the contents of the specified scale independent |resource_id|.
-  // If the value is found then |data| and |data_size| will be populated and
-  // this method will return true. If the value is not found then this method
-  // will return false. The returned |data| pointer will remain resident in
-  // memory and should not be freed. Include cef_pack_resources.h for a listing
-  // of valid resource ID values.
+  /// Returns a CefBinaryValue containing the decompressed contents of the
+  /// specified scale independent |resource_id| or NULL if not found. Include
+  /// cef_pack_resources.h for a listing of valid resource ID values.
   ///
   /*--cef()--*/
-  virtual bool GetDataResource(int resource_id,
-                               void*& data,
-                               size_t& data_size) = 0;
+  virtual CefRefPtr<CefBinaryValue> GetDataResource(int resource_id) = 0;
 
   ///
-  // Retrieves the contents of the specified |resource_id| nearest the scale
-  // factor |scale_factor|. Use a |scale_factor| value of SCALE_FACTOR_NONE for
-  // scale independent resources or call GetDataResource instead. If the value
-  // is found then |data| and |data_size| will be populated and this method will
-  // return true. If the value is not found then this method will return false.
-  // The returned |data| pointer will remain resident in memory and should not
-  // be freed. Include cef_pack_resources.h for a listing of valid resource ID
-  // values.
+  /// Returns a CefBinaryValue containing the decompressed contents of the
+  /// specified |resource_id| nearest the scale factor |scale_factor| or NULL if
+  /// not found. Use a |scale_factor| value of SCALE_FACTOR_NONE for scale
+  /// independent resources or call GetDataResource instead.Include
+  /// cef_pack_resources.h for a listing of valid resource ID values.
   ///
   /*--cef()--*/
-  virtual bool GetDataResourceForScale(int resource_id,
-                                       ScaleFactor scale_factor,
-                                       void*& data,
-                                       size_t& data_size) = 0;
+  virtual CefRefPtr<CefBinaryValue> GetDataResourceForScale(
+      int resource_id,
+      ScaleFactor scale_factor) = 0;
 };
 
 #endif  // CEF_INCLUDE_CEF_RESOURCE_BUNDLE_H_
diff --git a/src/include/cef_resource_bundle_handler.h b/src/include/cef_resource_bundle_handler.h
index 6cd6c9a..4743482 100644
--- a/src/include/cef_resource_bundle_handler.h
+++ b/src/include/cef_resource_bundle_handler.h
@@ -41,9 +41,9 @@
 #include "include/cef_base.h"
 
 ///
-// Class used to implement a custom resource bundle interface. See CefSettings
-// for additional options related to resource bundle loading. The methods of
-// this class may be called on multiple threads.
+/// Class used to implement a custom resource bundle interface. See CefSettings
+/// for additional options related to resource bundle loading. The methods of
+/// this class may be called on multiple threads.
 ///
 /*--cef(source=client)--*/
 class CefResourceBundleHandler : public virtual CefBaseRefCounted {
@@ -51,21 +51,21 @@
   typedef cef_scale_factor_t ScaleFactor;
 
   ///
-  // Called to retrieve a localized translation for the specified |string_id|.
-  // To provide the translation set |string| to the translation string and
-  // return true. To use the default translation return false. Include
-  // cef_pack_strings.h for a listing of valid string ID values.
+  /// Called to retrieve a localized translation for the specified |string_id|.
+  /// To provide the translation set |string| to the translation string and
+  /// return true. To use the default translation return false. Include
+  /// cef_pack_strings.h for a listing of valid string ID values.
   ///
   /*--cef()--*/
   virtual bool GetLocalizedString(int string_id, CefString& string) = 0;
 
   ///
-  // Called to retrieve data for the specified scale independent |resource_id|.
-  // To provide the resource data set |data| and |data_size| to the data pointer
-  // and size respectively and return true. To use the default resource data
-  // return false. The resource data will not be copied and must remain resident
-  // in memory. Include cef_pack_resources.h for a listing of valid resource ID
-  // values.
+  /// Called to retrieve data for the specified scale independent |resource_id|.
+  /// To provide the resource data set |data| and |data_size| to the data
+  /// pointer and size respectively and return true. To use the default resource
+  /// data return false. The resource data will not be copied and must remain
+  /// resident in memory. Include cef_pack_resources.h for a listing of valid
+  /// resource ID values.
   ///
   /*--cef()--*/
   virtual bool GetDataResource(int resource_id,
@@ -73,12 +73,12 @@
                                size_t& data_size) = 0;
 
   ///
-  // Called to retrieve data for the specified |resource_id| nearest the scale
-  // factor |scale_factor|. To provide the resource data set |data| and
-  // |data_size| to the data pointer and size respectively and return true. To
-  // use the default resource data return false. The resource data will not be
-  // copied and must remain resident in memory. Include cef_pack_resources.h for
-  // a listing of valid resource ID values.
+  /// Called to retrieve data for the specified |resource_id| nearest the scale
+  /// factor |scale_factor|. To provide the resource data set |data| and
+  /// |data_size| to the data pointer and size respectively and return true. To
+  /// use the default resource data return false. The resource data will not be
+  /// copied and must remain resident in memory. Include cef_pack_resources.h
+  /// for a listing of valid resource ID values.
   ///
   /*--cef()--*/
   virtual bool GetDataResourceForScale(int resource_id,
diff --git a/src/include/cef_resource_handler.h b/src/include/cef_resource_handler.h
index 4d9535e..9c43ee7 100644
--- a/src/include/cef_resource_handler.h
+++ b/src/include/cef_resource_handler.h
@@ -46,55 +46,55 @@
 #include "include/cef_response.h"
 
 ///
-// Callback for asynchronous continuation of CefResourceHandler::Skip().
+/// Callback for asynchronous continuation of CefResourceHandler::Skip().
 ///
 /*--cef(source=library)--*/
 class CefResourceSkipCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Callback for asynchronous continuation of Skip(). If |bytes_skipped| > 0
-  // then either Skip() will be called again until the requested number of
-  // bytes have been skipped or the request will proceed. If |bytes_skipped|
-  // <= 0 the request will fail with ERR_REQUEST_RANGE_NOT_SATISFIABLE.
+  /// Callback for asynchronous continuation of Skip(). If |bytes_skipped| > 0
+  /// then either Skip() will be called again until the requested number of
+  /// bytes have been skipped or the request will proceed. If |bytes_skipped|
+  /// <= 0 the request will fail with ERR_REQUEST_RANGE_NOT_SATISFIABLE.
   ///
   /*--cef(capi_name=cont)--*/
-  virtual void Continue(int64 bytes_skipped) = 0;
+  virtual void Continue(int64_t bytes_skipped) = 0;
 };
 
 ///
-// Callback for asynchronous continuation of CefResourceHandler::Read().
+/// Callback for asynchronous continuation of CefResourceHandler::Read().
 ///
 /*--cef(source=library)--*/
 class CefResourceReadCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Callback for asynchronous continuation of Read(). If |bytes_read| == 0
-  // the response will be considered complete. If |bytes_read| > 0 then Read()
-  // will be called again until the request is complete (based on either the
-  // result or the expected content length). If |bytes_read| < 0 then the
-  // request will fail and the |bytes_read| value will be treated as the error
-  // code.
+  /// Callback for asynchronous continuation of Read(). If |bytes_read| == 0
+  /// the response will be considered complete. If |bytes_read| > 0 then Read()
+  /// will be called again until the request is complete (based on either the
+  /// result or the expected content length). If |bytes_read| < 0 then the
+  /// request will fail and the |bytes_read| value will be treated as the error
+  /// code.
   ///
   /*--cef(capi_name=cont)--*/
   virtual void Continue(int bytes_read) = 0;
 };
 
 ///
-// Class used to implement a custom request handler interface. The methods of
-// this class will be called on the IO thread unless otherwise indicated.
+/// Class used to implement a custom request handler interface. The methods of
+/// this class will be called on the IO thread unless otherwise indicated.
 ///
 /*--cef(source=client)--*/
 class CefResourceHandler : public virtual CefBaseRefCounted {
  public:
   ///
-  // Open the response stream. To handle the request immediately set
-  // |handle_request| to true and return true. To decide at a later time set
-  // |handle_request| to false, return true, and execute |callback| to continue
-  // or cancel the request. To cancel the request immediately set
-  // |handle_request| to true and return false. This method will be called in
-  // sequence but not from a dedicated thread. For backwards compatibility set
-  // |handle_request| to false and return false and the ProcessRequest method
-  // will be called.
+  /// Open the response stream. To handle the request immediately set
+  /// |handle_request| to true and return true. To decide at a later time set
+  /// |handle_request| to false, return true, and execute |callback| to continue
+  /// or cancel the request. To cancel the request immediately set
+  /// |handle_request| to true and return false. This method will be called in
+  /// sequence but not from a dedicated thread. For backwards compatibility set
+  /// |handle_request| to false and return false and the ProcessRequest method
+  /// will be called.
   ///
   /*--cef()--*/
   virtual bool Open(CefRefPtr<CefRequest> request,
@@ -105,13 +105,13 @@
   }
 
   ///
-  // Begin processing the request. To handle the request return true and call
-  // CefCallback::Continue() once the response header information is available
-  // (CefCallback::Continue() can also be called from inside this method if
-  // header information is available immediately). To cancel the request return
-  // false.
-  //
-  // WARNING: This method is deprecated. Use Open instead.
+  /// Begin processing the request. To handle the request return true and call
+  /// CefCallback::Continue() once the response header information is available
+  /// (CefCallback::Continue() can also be called from inside this method if
+  /// header information is available immediately). To cancel the request return
+  /// false.
+  ///
+  /// WARNING: This method is deprecated. Use Open instead.
   ///
   /*--cef()--*/
   virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
@@ -120,54 +120,54 @@
   }
 
   ///
-  // Retrieve response header information. If the response length is not known
-  // set |response_length| to -1 and ReadResponse() will be called until it
-  // returns false. If the response length is known set |response_length|
-  // to a positive value and ReadResponse() will be called until it returns
-  // false or the specified number of bytes have been read. Use the |response|
-  // object to set the mime type, http status code and other optional header
-  // values. To redirect the request to a new URL set |redirectUrl| to the new
-  // URL. |redirectUrl| can be either a relative or fully qualified URL.
-  // It is also possible to set |response| to a redirect http status code
-  // and pass the new URL via a Location header. Likewise with |redirectUrl| it
-  // is valid to set a relative or fully qualified URL as the Location header
-  // value. If an error occured while setting up the request you can call
-  // SetError() on |response| to indicate the error condition.
+  /// Retrieve response header information. If the response length is not known
+  /// set |response_length| to -1 and ReadResponse() will be called until it
+  /// returns false. If the response length is known set |response_length|
+  /// to a positive value and ReadResponse() will be called until it returns
+  /// false or the specified number of bytes have been read. Use the |response|
+  /// object to set the mime type, http status code and other optional header
+  /// values. To redirect the request to a new URL set |redirectUrl| to the new
+  /// URL. |redirectUrl| can be either a relative or fully qualified URL.
+  /// It is also possible to set |response| to a redirect http status code
+  /// and pass the new URL via a Location header. Likewise with |redirectUrl| it
+  /// is valid to set a relative or fully qualified URL as the Location header
+  /// value. If an error occured while setting up the request you can call
+  /// SetError() on |response| to indicate the error condition.
   ///
   /*--cef()--*/
   virtual void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                                  int64& response_length,
+                                  int64_t& response_length,
                                   CefString& redirectUrl) = 0;
 
   ///
-  // Skip response data when requested by a Range header. Skip over and discard
-  // |bytes_to_skip| bytes of response data. If data is available immediately
-  // set |bytes_skipped| to the number of bytes skipped and return true. To
-  // read the data at a later time set |bytes_skipped| to 0, return true and
-  // execute |callback| when the data is available. To indicate failure set
-  // |bytes_skipped| to < 0 (e.g. -2 for ERR_FAILED) and return false. This
-  // method will be called in sequence but not from a dedicated thread.
+  /// Skip response data when requested by a Range header. Skip over and discard
+  /// |bytes_to_skip| bytes of response data. If data is available immediately
+  /// set |bytes_skipped| to the number of bytes skipped and return true. To
+  /// read the data at a later time set |bytes_skipped| to 0, return true and
+  /// execute |callback| when the data is available. To indicate failure set
+  /// |bytes_skipped| to < 0 (e.g. -2 for ERR_FAILED) and return false. This
+  /// method will be called in sequence but not from a dedicated thread.
   ///
   /*--cef()--*/
-  virtual bool Skip(int64 bytes_to_skip,
-                    int64& bytes_skipped,
+  virtual bool Skip(int64_t bytes_to_skip,
+                    int64_t& bytes_skipped,
                     CefRefPtr<CefResourceSkipCallback> callback) {
     bytes_skipped = -2;
     return false;
   }
 
   ///
-  // Read response data. If data is available immediately copy up to
-  // |bytes_to_read| bytes into |data_out|, set |bytes_read| to the number of
-  // bytes copied, and return true. To read the data at a later time keep a
-  // pointer to |data_out|, set |bytes_read| to 0, return true and execute
-  // |callback| when the data is available (|data_out| will remain valid until
-  // the callback is executed). To indicate response completion set |bytes_read|
-  // to 0 and return false. To indicate failure set |bytes_read| to < 0 (e.g. -2
-  // for ERR_FAILED) and return false. This method will be called in sequence
-  // but not from a dedicated thread. For backwards compatibility set
-  // |bytes_read| to -1 and return false and the ReadResponse method will be
-  // called.
+  /// Read response data. If data is available immediately copy up to
+  /// |bytes_to_read| bytes into |data_out|, set |bytes_read| to the number of
+  /// bytes copied, and return true. To read the data at a later time keep a
+  /// pointer to |data_out|, set |bytes_read| to 0, return true and execute
+  /// |callback| when the data is available (|data_out| will remain valid until
+  /// the callback is executed). To indicate response completion set
+  /// |bytes_read| to 0 and return false. To indicate failure set |bytes_read|
+  /// to < 0 (e.g. -2 for ERR_FAILED) and return false. This method will be
+  /// called in sequence but not from a dedicated thread. For backwards
+  /// compatibility set |bytes_read| to -1 and return false and the ReadResponse
+  /// method will be called.
   ///
   /*--cef()--*/
   virtual bool Read(void* data_out,
@@ -179,13 +179,13 @@
   }
 
   ///
-  // Read response data. If data is available immediately copy up to
-  // |bytes_to_read| bytes into |data_out|, set |bytes_read| to the number of
-  // bytes copied, and return true. To read the data at a later time set
-  // |bytes_read| to 0, return true and call CefCallback::Continue() when the
-  // data is available. To indicate response completion return false.
-  //
-  // WARNING: This method is deprecated. Use Skip and Read instead.
+  /// Read response data. If data is available immediately copy up to
+  /// |bytes_to_read| bytes into |data_out|, set |bytes_read| to the number of
+  /// bytes copied, and return true. To read the data at a later time set
+  /// |bytes_read| to 0, return true and call CefCallback::Continue() when the
+  /// data is available. To indicate response completion return false.
+  ///
+  /// WARNING: This method is deprecated. Use Skip and Read instead.
   ///
   /*--cef()--*/
   virtual bool ReadResponse(void* data_out,
@@ -197,7 +197,7 @@
   }
 
   ///
-  // Request processing has been canceled.
+  /// Request processing has been canceled.
   ///
   /*--cef()--*/
   virtual void Cancel() = 0;
diff --git a/src/include/cef_resource_request_handler.h b/src/include/cef_resource_request_handler.h
index d13afb3..572065b 100644
--- a/src/include/cef_resource_request_handler.h
+++ b/src/include/cef_resource_request_handler.h
@@ -40,9 +40,9 @@
 
 #include "include/cef_base.h"
 #include "include/cef_browser.h"
+#include "include/cef_callback.h"
 #include "include/cef_frame.h"
 #include "include/cef_request.h"
-#include "include/cef_request_callback.h"
 #include "include/cef_resource_handler.h"
 #include "include/cef_response.h"
 #include "include/cef_response_filter.h"
@@ -50,9 +50,9 @@
 class CefCookieAccessFilter;
 
 ///
-// Implement this interface to handle events related to browser requests. The
-// methods of this class will be called on the IO thread unless otherwise
-// indicated.
+/// Implement this interface to handle events related to browser requests. The
+/// methods of this class will be called on the IO thread unless otherwise
+/// indicated.
 ///
 /*--cef(source=client,no_debugct_check)--*/
 class CefResourceRequestHandler : public virtual CefBaseRefCounted {
@@ -61,11 +61,11 @@
   typedef cef_urlrequest_status_t URLRequestStatus;
 
   ///
-  // Called on the IO thread before a resource request is loaded. The |browser|
-  // and |frame| values represent the source of the request, and may be NULL for
-  // requests originating from service workers or CefURLRequest. To optionally
-  // filter cookies for the request return a CefCookieAccessFilter object. The
-  // |request| object cannot not be modified in this callback.
+  /// Called on the IO thread before a resource request is loaded. The |browser|
+  /// and |frame| values represent the source of the request, and may be NULL
+  /// for requests originating from service workers or CefURLRequest. To
+  /// optionally filter cookies for the request return a CefCookieAccessFilter
+  /// object. The |request| object cannot not be modified in this callback.
   ///
   /*--cef(optional_param=browser,optional_param=frame)--*/
   virtual CefRefPtr<CefCookieAccessFilter> GetCookieAccessFilter(
@@ -76,33 +76,32 @@
   }
 
   ///
-  // Called on the IO thread before a resource request is loaded. The |browser|
-  // and |frame| values represent the source of the request, and may be NULL for
-  // requests originating from service workers or CefURLRequest. To redirect or
-  // change the resource load optionally modify |request|. Modification of the
-  // request URL will be treated as a redirect. Return RV_CONTINUE to continue
-  // the request immediately. Return RV_CONTINUE_ASYNC and call
-  // CefRequestCallback:: Continue() at a later time to continue or cancel the
-  // request asynchronously. Return RV_CANCEL to cancel the request immediately.
-  //
+  /// Called on the IO thread before a resource request is loaded. The |browser|
+  /// and |frame| values represent the source of the request, and may be NULL
+  /// for requests originating from service workers or CefURLRequest. To
+  /// redirect or change the resource load optionally modify |request|.
+  /// Modification of the request URL will be treated as a redirect. Return
+  /// RV_CONTINUE to continue the request immediately. Return RV_CONTINUE_ASYNC
+  /// and call CefCallback methods at a later time to continue or cancel the
+  /// request asynchronously. Return RV_CANCEL to cancel the request
+  /// immediately.
   ///
   /*--cef(optional_param=browser,optional_param=frame,
           default_retval=RV_CONTINUE)--*/
-  virtual ReturnValue OnBeforeResourceLoad(
-      CefRefPtr<CefBrowser> browser,
-      CefRefPtr<CefFrame> frame,
-      CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) {
+  virtual ReturnValue OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser,
+                                           CefRefPtr<CefFrame> frame,
+                                           CefRefPtr<CefRequest> request,
+                                           CefRefPtr<CefCallback> callback) {
     return RV_CONTINUE;
   }
 
   ///
-  // Called on the IO thread before a resource is loaded. The |browser| and
-  // |frame| values represent the source of the request, and may be NULL for
-  // requests originating from service workers or CefURLRequest. To allow the
-  // resource to load using the default network loader return NULL. To specify a
-  // handler for the resource return a CefResourceHandler object. The |request|
-  // object cannot not be modified in this callback.
+  /// Called on the IO thread before a resource is loaded. The |browser| and
+  /// |frame| values represent the source of the request, and may be NULL for
+  /// requests originating from service workers or CefURLRequest. To allow the
+  /// resource to load using the default network loader return NULL. To specify
+  /// a handler for the resource return a CefResourceHandler object. The
+  /// |request| object cannot not be modified in this callback.
   ///
   /*--cef(optional_param=browser,optional_param=frame)--*/
   virtual CefRefPtr<CefResourceHandler> GetResourceHandler(
@@ -113,14 +112,14 @@
   }
 
   ///
-  // Called on the IO thread when a resource load is redirected. The |browser|
-  // and |frame| values represent the source of the request, and may be NULL for
-  // requests originating from service workers or CefURLRequest. The |request|
-  // parameter will contain the old URL and other request-related information.
-  // The |response| parameter will contain the response that resulted in the
-  // redirect. The |new_url| parameter will contain the new URL and can be
-  // changed if desired. The |request| and |response| objects cannot be modified
-  // in this callback.
+  /// Called on the IO thread when a resource load is redirected. The |browser|
+  /// and |frame| values represent the source of the request, and may be NULL
+  /// for requests originating from service workers or CefURLRequest. The
+  /// |request| parameter will contain the old URL and other request-related
+  /// information. The |response| parameter will contain the response that
+  /// resulted in the redirect. The |new_url| parameter will contain the new URL
+  /// and can be changed if desired. The |request| and |response| objects cannot
+  /// be modified in this callback.
   ///
   /*--cef(optional_param=browser,optional_param=frame)--*/
   virtual void OnResourceRedirect(CefRefPtr<CefBrowser> browser,
@@ -130,17 +129,17 @@
                                   CefString& new_url) {}
 
   ///
-  // Called on the IO thread when a resource response is received. The |browser|
-  // and |frame| values represent the source of the request, and may be NULL for
-  // requests originating from service workers or CefURLRequest. To allow the
-  // resource load to proceed without modification return false. To redirect or
-  // retry the resource load optionally modify |request| and return true.
-  // Modification of the request URL will be treated as a redirect. Requests
-  // handled using the default network loader cannot be redirected in this
-  // callback. The |response| object cannot be modified in this callback.
-  //
-  // WARNING: Redirecting using this method is deprecated. Use
-  // OnBeforeResourceLoad or GetResourceHandler to perform redirects.
+  /// Called on the IO thread when a resource response is received. The
+  /// |browser| and |frame| values represent the source of the request, and may
+  /// be NULL for requests originating from service workers or CefURLRequest. To
+  /// allow the resource load to proceed without modification return false. To
+  /// redirect or retry the resource load optionally modify |request| and return
+  /// true. Modification of the request URL will be treated as a redirect.
+  /// Requests handled using the default network loader cannot be redirected in
+  /// this callback. The |response| object cannot be modified in this callback.
+  ///
+  /// WARNING: Redirecting using this method is deprecated. Use
+  /// OnBeforeResourceLoad or GetResourceHandler to perform redirects.
   ///
   /*--cef(optional_param=browser,optional_param=frame)--*/
   virtual bool OnResourceResponse(CefRefPtr<CefBrowser> browser,
@@ -151,11 +150,11 @@
   }
 
   ///
-  // Called on the IO thread to optionally filter resource response content. The
-  // |browser| and |frame| values represent the source of the request, and may
-  // be NULL for requests originating from service workers or CefURLRequest.
-  // |request| and |response| represent the request and response respectively
-  // and cannot be modified in this callback.
+  /// Called on the IO thread to optionally filter resource response content.
+  /// The |browser| and |frame| values represent the source of the request, and
+  /// may be NULL for requests originating from service workers or
+  /// CefURLRequest. |request| and |response| represent the request and response
+  /// respectively and cannot be modified in this callback.
   ///
   /*--cef(optional_param=browser,optional_param=frame)--*/
   virtual CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
@@ -167,19 +166,20 @@
   }
 
   ///
-  // Called on the IO thread when a resource load has completed. The |browser|
-  // and |frame| values represent the source of the request, and may be NULL for
-  // requests originating from service workers or CefURLRequest. |request| and
-  // |response| represent the request and response respectively and cannot be
-  // modified in this callback. |status| indicates the load completion status.
-  // |received_content_length| is the number of response bytes actually read.
-  // This method will be called for all requests, including requests that are
-  // aborted due to CEF shutdown or destruction of the associated browser. In
-  // cases where the associated browser is destroyed this callback may arrive
-  // after the CefLifeSpanHandler::OnBeforeClose callback for that browser. The
-  // CefFrame::IsValid method can be used to test for this situation, and care
-  // should be taken not to call |browser| or |frame| methods that modify state
-  // (like LoadURL, SendProcessMessage, etc.) if the frame is invalid.
+  /// Called on the IO thread when a resource load has completed. The |browser|
+  /// and |frame| values represent the source of the request, and may be NULL
+  /// for requests originating from service workers or CefURLRequest. |request|
+  /// and |response| represent the request and response respectively and cannot
+  /// be modified in this callback. |status| indicates the load completion
+  /// status. |received_content_length| is the number of response bytes actually
+  /// read. This method will be called for all requests, including requests that
+  /// are aborted due to CEF shutdown or destruction of the associated browser.
+  /// In cases where the associated browser is destroyed this callback may
+  /// arrive after the CefLifeSpanHandler::OnBeforeClose callback for that
+  /// browser. The CefFrame::IsValid method can be used to test for this
+  /// situation, and care should be taken not to call |browser| or |frame|
+  /// methods that modify state (like LoadURL, SendProcessMessage, etc.) if the
+  /// frame is invalid.
   ///
   /*--cef(optional_param=browser,optional_param=frame)--*/
   virtual void OnResourceLoadComplete(CefRefPtr<CefBrowser> browser,
@@ -187,17 +187,17 @@
                                       CefRefPtr<CefRequest> request,
                                       CefRefPtr<CefResponse> response,
                                       URLRequestStatus status,
-                                      int64 received_content_length) {}
+                                      int64_t received_content_length) {}
 
   ///
-  // Called on the IO thread to handle requests for URLs with an unknown
-  // protocol component. The |browser| and |frame| values represent the source
-  // of the request, and may be NULL for requests originating from service
-  // workers or CefURLRequest. |request| cannot be modified in this callback.
-  // Set |allow_os_execution| to true to attempt execution via the registered OS
-  // protocol handler, if any.
-  // SECURITY WARNING: YOU SHOULD USE THIS METHOD TO ENFORCE RESTRICTIONS BASED
-  // ON SCHEME, HOST OR OTHER URL ANALYSIS BEFORE ALLOWING OS EXECUTION.
+  /// Called on the IO thread to handle requests for URLs with an unknown
+  /// protocol component. The |browser| and |frame| values represent the source
+  /// of the request, and may be NULL for requests originating from service
+  /// workers or CefURLRequest. |request| cannot be modified in this callback.
+  /// Set |allow_os_execution| to true to attempt execution via the registered
+  /// OS protocol handler, if any. SECURITY WARNING: YOU SHOULD USE THIS METHOD
+  /// TO ENFORCE RESTRICTIONS BASED ON SCHEME, HOST OR OTHER URL ANALYSIS BEFORE
+  /// ALLOWING OS EXECUTION.
   ///
   /*--cef(optional_param=browser,optional_param=frame)--*/
   virtual void OnProtocolExecution(CefRefPtr<CefBrowser> browser,
@@ -207,19 +207,19 @@
 };
 
 ///
-// Implement this interface to filter cookies that may be sent or received from
-// resource requests. The methods of this class will be called on the IO thread
-// unless otherwise indicated.
+/// Implement this interface to filter cookies that may be sent or received from
+/// resource requests. The methods of this class will be called on the IO thread
+/// unless otherwise indicated.
 ///
 /*--cef(source=client,no_debugct_check)--*/
 class CefCookieAccessFilter : public virtual CefBaseRefCounted {
  public:
   ///
-  // Called on the IO thread before a resource request is sent. The |browser|
-  // and |frame| values represent the source of the request, and may be NULL for
-  // requests originating from service workers or CefURLRequest. |request|
-  // cannot be modified in this callback. Return true if the specified cookie
-  // can be sent with the request or false otherwise.
+  /// Called on the IO thread before a resource request is sent. The |browser|
+  /// and |frame| values represent the source of the request, and may be NULL
+  /// for requests originating from service workers or CefURLRequest. |request|
+  /// cannot be modified in this callback. Return true if the specified cookie
+  /// can be sent with the request or false otherwise.
   ///
   /*--cef(optional_param=browser,optional_param=frame)--*/
   virtual bool CanSendCookie(CefRefPtr<CefBrowser> browser,
@@ -230,11 +230,12 @@
   }
 
   ///
-  // Called on the IO thread after a resource response is received. The
-  // |browser| and |frame| values represent the source of the request, and may
-  // be NULL for requests originating from service workers or CefURLRequest.
-  // |request| cannot be modified in this callback. Return true if the specified
-  // cookie returned with the response can be saved or false otherwise.
+  /// Called on the IO thread after a resource response is received. The
+  /// |browser| and |frame| values represent the source of the request, and may
+  /// be NULL for requests originating from service workers or CefURLRequest.
+  /// |request| cannot be modified in this callback. Return true if the
+  /// specified cookie returned with the response can be saved or false
+  /// otherwise.
   ///
   /*--cef(optional_param=browser,optional_param=frame)--*/
   virtual bool CanSaveCookie(CefRefPtr<CefBrowser> browser,
diff --git a/src/include/cef_response.h b/src/include/cef_response.h
index f871c11..571998a 100644
--- a/src/include/cef_response.h
+++ b/src/include/cef_response.h
@@ -42,8 +42,8 @@
 #include "include/cef_base.h"
 
 ///
-// Class used to represent a web response. The methods of this class may be
-// called on any thread.
+/// Class used to represent a web response. The methods of this class may be
+/// called on any thread.
 ///
 /*--cef(source=library,no_debugct_check)--*/
 class CefResponse : public virtual CefBaseRefCounted {
@@ -51,88 +51,88 @@
   typedef std::multimap<CefString, CefString> HeaderMap;
 
   ///
-  // Create a new CefResponse object.
+  /// Create a new CefResponse object.
   ///
   /*--cef()--*/
   static CefRefPtr<CefResponse> Create();
 
   ///
-  // Returns true if this object is read-only.
+  /// Returns true if this object is read-only.
   ///
   /*--cef()--*/
   virtual bool IsReadOnly() = 0;
 
   ///
-  // Get the response error code. Returns ERR_NONE if there was no error.
+  /// Get the response error code. Returns ERR_NONE if there was no error.
   ///
   /*--cef(default_retval=ERR_NONE)--*/
   virtual cef_errorcode_t GetError() = 0;
 
   ///
-  // Set the response error code. This can be used by custom scheme handlers
-  // to return errors during initial request processing.
+  /// Set the response error code. This can be used by custom scheme handlers
+  /// to return errors during initial request processing.
   ///
   /*--cef()--*/
   virtual void SetError(cef_errorcode_t error) = 0;
 
   ///
-  // Get the response status code.
+  /// Get the response status code.
   ///
   /*--cef()--*/
   virtual int GetStatus() = 0;
 
   ///
-  // Set the response status code.
+  /// Set the response status code.
   ///
   /*--cef()--*/
   virtual void SetStatus(int status) = 0;
 
   ///
-  // Get the response status text.
+  /// Get the response status text.
   ///
   /*--cef()--*/
   virtual CefString GetStatusText() = 0;
 
   ///
-  // Set the response status text.
+  /// Set the response status text.
   ///
   /*--cef(optional_param=statusText)--*/
   virtual void SetStatusText(const CefString& statusText) = 0;
 
   ///
-  // Get the response mime type.
+  /// Get the response mime type.
   ///
   /*--cef()--*/
   virtual CefString GetMimeType() = 0;
 
   ///
-  // Set the response mime type.
+  /// Set the response mime type.
   ///
   /*--cef(optional_param=mimeType)--*/
   virtual void SetMimeType(const CefString& mimeType) = 0;
 
   ///
-  // Get the response charset.
+  /// Get the response charset.
   ///
   /*--cef()--*/
   virtual CefString GetCharset() = 0;
 
   ///
-  // Set the response charset.
+  /// Set the response charset.
   ///
   /*--cef(optional_param=charset)--*/
   virtual void SetCharset(const CefString& charset) = 0;
 
   ///
-  // Get the value for the specified response header field.
+  /// Get the value for the specified response header field.
   ///
   /*--cef()--*/
   virtual CefString GetHeaderByName(const CefString& name) = 0;
 
   ///
-  // Set the header |name| to |value|. If |overwrite| is true any existing
-  // values will be replaced with the new value. If |overwrite| is false any
-  // existing values will not be overwritten.
+  /// Set the header |name| to |value|. If |overwrite| is true any existing
+  /// values will be replaced with the new value. If |overwrite| is false any
+  /// existing values will not be overwritten.
   ///
   /*--cef(optional_param=value)--*/
   virtual void SetHeaderByName(const CefString& name,
@@ -140,25 +140,25 @@
                                bool overwrite) = 0;
 
   ///
-  // Get all response header fields.
+  /// Get all response header fields.
   ///
   /*--cef()--*/
   virtual void GetHeaderMap(HeaderMap& headerMap) = 0;
 
   ///
-  // Set all response header fields.
+  /// Set all response header fields.
   ///
   /*--cef()--*/
   virtual void SetHeaderMap(const HeaderMap& headerMap) = 0;
 
   ///
-  // Get the resolved URL after redirects or changed as a result of HSTS.
+  /// Get the resolved URL after redirects or changed as a result of HSTS.
   ///
   /*--cef()--*/
   virtual CefString GetURL() = 0;
 
   ///
-  // Set the resolved URL after redirects or changed as a result of HSTS.
+  /// Set the resolved URL after redirects or changed as a result of HSTS.
   ///
   /*--cef(optional_param=url)--*/
   virtual void SetURL(const CefString& url) = 0;
diff --git a/src/include/cef_response_filter.h b/src/include/cef_response_filter.h
index 2eb446f..37d7064 100644
--- a/src/include/cef_response_filter.h
+++ b/src/include/cef_response_filter.h
@@ -41,8 +41,8 @@
 #include "include/cef_base.h"
 
 ///
-// Implement this interface to filter resource response content. The methods of
-// this class will be called on the browser process IO thread.
+/// Implement this interface to filter resource response content. The methods of
+/// this class will be called on the browser process IO thread.
 ///
 /*--cef(source=client)--*/
 class CefResponseFilter : public virtual CefBaseRefCounted {
@@ -50,41 +50,42 @@
   typedef cef_response_filter_status_t FilterStatus;
 
   ///
-  // Initialize the response filter. Will only be called a single time. The
-  // filter will not be installed if this method returns false.
+  /// Initialize the response filter. Will only be called a single time. The
+  /// filter will not be installed if this method returns false.
   ///
   /*--cef()--*/
   virtual bool InitFilter() = 0;
 
   ///
-  // Called to filter a chunk of data. Expected usage is as follows:
-  //
-  //  A. Read input data from |data_in| and set |data_in_read| to the number of
-  //     bytes that were read up to a maximum of |data_in_size|. |data_in| will
-  //     be NULL if |data_in_size| is zero.
-  //  B. Write filtered output data to |data_out| and set |data_out_written| to
-  //     the number of bytes that were written up to a maximum of
-  //     |data_out_size|. If no output data was written then all data must be
-  //     read from |data_in| (user must set |data_in_read| = |data_in_size|).
-  //  C. Return RESPONSE_FILTER_DONE if all output data was written or
-  //     RESPONSE_FILTER_NEED_MORE_DATA if output data is still pending.
-  //
-  // This method will be called repeatedly until the input buffer has been
-  // fully read (user sets |data_in_read| = |data_in_size|) and there is no
-  // more input data to filter (the resource response is complete). This method
-  // may then be called an additional time with an empty input buffer if the
-  // user filled the output buffer (set |data_out_written| = |data_out_size|)
-  // and returned RESPONSE_FILTER_NEED_MORE_DATA to indicate that output data is
-  // still pending.
-  //
-  // Calls to this method will stop when one of the following conditions is met:
-  //
-  //  A. There is no more input data to filter (the resource response is
-  //     complete) and the user sets |data_out_written| = 0 or returns
-  //     RESPONSE_FILTER_DONE to indicate that all data has been written, or;
-  //  B. The user returns RESPONSE_FILTER_ERROR to indicate an error.
-  //
-  // Do not keep a reference to the buffers passed to this method.
+  /// Called to filter a chunk of data. Expected usage is as follows:
+  ///
+  ///  1. Read input data from |data_in| and set |data_in_read| to the number of
+  ///     bytes that were read up to a maximum of |data_in_size|. |data_in| will
+  ///     be NULL if |data_in_size| is zero.
+  ///  2. Write filtered output data to |data_out| and set |data_out_written| to
+  ///     the number of bytes that were written up to a maximum of
+  ///     |data_out_size|. If no output data was written then all data must be
+  ///     read from |data_in| (user must set |data_in_read| = |data_in_size|).
+  ///  3. Return RESPONSE_FILTER_DONE if all output data was written or
+  ///     RESPONSE_FILTER_NEED_MORE_DATA if output data is still pending.
+  ///
+  /// This method will be called repeatedly until the input buffer has been
+  /// fully read (user sets |data_in_read| = |data_in_size|) and there is no
+  /// more input data to filter (the resource response is complete). This method
+  /// may then be called an additional time with an empty input buffer if the
+  /// user filled the output buffer (set |data_out_written| = |data_out_size|)
+  /// and returned RESPONSE_FILTER_NEED_MORE_DATA to indicate that output data
+  /// is still pending.
+  ///
+  /// Calls to this method will stop when one of the following conditions is
+  /// met:
+  ///
+  ///  1. There is no more input data to filter (the resource response is
+  ///     complete) and the user sets |data_out_written| = 0 or returns
+  ///     RESPONSE_FILTER_DONE to indicate that all data has been written, or;
+  ///  2. The user returns RESPONSE_FILTER_ERROR to indicate an error.
+  ///
+  /// Do not keep a reference to the buffers passed to this method.
   ///
   /*--cef(optional_param=data_in,default_retval=RESPONSE_FILTER_ERROR)--*/
   virtual FilterStatus Filter(void* data_in,
diff --git a/src/include/cef_sandbox_mac.h b/src/include/cef_sandbox_mac.h
index 48886ed..cec624e 100644
--- a/src/include/cef_sandbox_mac.h
+++ b/src/include/cef_sandbox_mac.h
@@ -34,33 +34,36 @@
 #include "include/base/cef_build.h"
 #include "include/internal/cef_export.h"
 
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-// The sandbox is used to restrict sub-processes (renderer, plugin, GPU, etc)
-// from directly accessing system resources. This helps to protect the user
-// from untrusted and potentially malicious Web content.
-// See http://www.chromium.org/developers/design-documents/sandbox for
-// complete details.
-//
-// To enable the sandbox on macOS the following requirements must be met:
-// 1. Link the helper process executable with the cef_sandbox static library.
-// 2. Call the cef_sandbox_initialize() function at the beginning of the
-//    helper executable main() function and before loading the CEF framework
-//    library. See include/wrapper/cef_library_loader.h for example usage.
+///
+/// \file
+/// The sandbox is used to restrict sub-processes (renderer, GPU, etc) from
+/// directly accessing system resources. This helps to protect the user from
+/// untrusted and potentially malicious Web content. See
+/// http://www.chromium.org/developers/design-documents/sandbox for complete
+/// details.
+///
+/// To enable the sandbox on macOS the following requirements must be met:
+/// 1. Link the helper process executable with the cef_sandbox static library.
+/// 2. Call the cef_sandbox_initialize() function at the beginning of the
+///    helper executable main() function and before loading the CEF framework
+///    library. See include/wrapper/cef_library_loader.h for example usage.
+///
 
 ///
-// Initialize the sandbox for this process. Returns the sandbox context
-// handle on success or NULL on failure. The returned handle should be
-// passed to cef_sandbox_destroy() immediately before process termination.
+/// Initialize the sandbox for this process. Returns the sandbox context
+/// handle on success or NULL on failure. The returned handle should be
+/// passed to cef_sandbox_destroy() immediately before process termination.
 ///
 CEF_EXPORT void* cef_sandbox_initialize(int argc, char** argv);
 
 ///
-// Destroy the specified sandbox context handle.
+/// Destroy the specified sandbox context handle.
 ///
 CEF_EXPORT void cef_sandbox_destroy(void* sandbox_context);
 
@@ -68,14 +71,16 @@
 }
 
 ///
-// Scoped helper for managing the life span of a sandbox context handle.
+/// Scoped helper for managing the life span of a sandbox context handle.
 ///
 class CEF_EXPORT CefScopedSandboxContext {
  public:
   CefScopedSandboxContext();
   ~CefScopedSandboxContext();
 
-  // Load the sandbox for this process. Returns true on success.
+  ///
+  /// Load the sandbox for this process. Returns true on success.
+  ///
   bool Initialize(int argc, char** argv);
 
  private:
@@ -83,6 +88,6 @@
 };
 #endif  // __cplusplus
 
-#endif  // defined(OS_MACOSX)
+#endif  // defined(OS_MAC)
 
 #endif  // CEF_INCLUDE_CEF_SANDBOX_MAC_H_
diff --git a/src/include/cef_sandbox_win.h b/src/include/cef_sandbox_win.h
index 3b7c4e0..a98d64c 100644
--- a/src/include/cef_sandbox_win.h
+++ b/src/include/cef_sandbox_win.h
@@ -39,29 +39,32 @@
 extern "C" {
 #endif
 
-// The sandbox is used to restrict sub-processes (renderer, plugin, GPU, etc)
-// from directly accessing system resources. This helps to protect the user
-// from untrusted and potentially malicious Web content.
-// See http://www.chromium.org/developers/design-documents/sandbox for
-// complete details.
-//
-// To enable the sandbox on Windows the following requirements must be met:
-// 1. Use the same executable for the browser process and all sub-processes.
-// 2. Link the executable with the cef_sandbox static library.
-// 3. Call the cef_sandbox_info_create() function from within the executable
-//    (not from a separate DLL) and pass the resulting pointer into both the
-//    CefExecutProcess() and CefInitialize() functions via the
-//    |windows_sandbox_info| parameter.
+///
+/// \file
+/// The sandbox is used to restrict sub-processes (renderer, GPU, etc) from
+/// directly accessing system resources. This helps to protect the user from
+/// untrusted and potentially malicious Web content. See
+/// http://www.chromium.org/developers/design-documents/sandbox for complete
+/// details.
+///
+/// To enable the sandbox on Windows the following requirements must be met:
+/// 1. Use the same executable for the browser process and all sub-processes.
+/// 2. Link the executable with the cef_sandbox static library.
+/// 3. Call the cef_sandbox_info_create() function from within the executable
+///    (not from a separate DLL) and pass the resulting pointer into both the
+///    CefExecuteProcess() and CefInitialize() functions via the
+///    |windows_sandbox_info| parameter.
+///
 
 ///
-// Create the sandbox information object for this process. It is safe to create
-// multiple of this object and to destroy the object immediately after passing
-// into the CefExecutProcess() and/or CefInitialize() functions.
+/// Create the sandbox information object for this process. It is safe to create
+/// multiple of this object and to destroy the object immediately after passing
+/// into the CefExecuteProcess() and/or CefInitialize() functions.
 ///
-void* cef_sandbox_info_create();
+void* cef_sandbox_info_create(void);
 
 ///
-// Destroy the specified sandbox information object.
+/// Destroy the specified sandbox information object.
 ///
 void cef_sandbox_info_destroy(void* sandbox_info);
 
@@ -69,7 +72,7 @@
 }
 
 ///
-// Manages the life span of a sandbox information object.
+/// Manages the life span of a sandbox information object.
 ///
 class CefScopedSandboxInfo {
  public:
diff --git a/src/include/cef_scheme.h b/src/include/cef_scheme.h
index 082f9ec..97f4c15 100644
--- a/src/include/cef_scheme.h
+++ b/src/include/cef_scheme.h
@@ -48,18 +48,18 @@
 class CefSchemeHandlerFactory;
 
 ///
-// Register a scheme handler factory with the global request context. An empty
-// |domain_name| value for a standard scheme will cause the factory to match all
-// domain names. The |domain_name| value will be ignored for non-standard
-// schemes. If |scheme_name| is a built-in scheme and no handler is returned by
-// |factory| then the built-in scheme handler factory will be called. If
-// |scheme_name| is a custom scheme then you must also implement the
-// CefApp::OnRegisterCustomSchemes() method in all processes. This function may
-// be called multiple times to change or remove the factory that matches the
-// specified |scheme_name| and optional |domain_name|. Returns false if an error
-// occurs. This function may be called on any thread in the browser process.
-// Using this function is equivalent to calling
-// CefRequestContext::GetGlobalContext()->RegisterSchemeHandlerFactory().
+/// Register a scheme handler factory with the global request context. An empty
+/// |domain_name| value for a standard scheme will cause the factory to match
+/// all domain names. The |domain_name| value will be ignored for non-standard
+/// schemes. If |scheme_name| is a built-in scheme and no handler is returned by
+/// |factory| then the built-in scheme handler factory will be called. If
+/// |scheme_name| is a custom scheme then you must also implement the
+/// CefApp::OnRegisterCustomSchemes() method in all processes. This function may
+/// be called multiple times to change or remove the factory that matches the
+/// specified |scheme_name| and optional |domain_name|. Returns false if an
+/// error occurs. This function may be called on any thread in the browser
+/// process. Using this function is equivalent to calling
+/// CefRequestContext::GetGlobalContext()->RegisterSchemeHandlerFactory().
 ///
 /*--cef(optional_param=domain_name,optional_param=factory)--*/
 bool CefRegisterSchemeHandlerFactory(
@@ -68,48 +68,48 @@
     CefRefPtr<CefSchemeHandlerFactory> factory);
 
 ///
-// Clear all scheme handler factories registered with the global request
-// context. Returns false on error. This function may be called on any thread in
-// the browser process. Using this function is equivalent to calling
-// CefRequestContext::GetGlobalContext()->ClearSchemeHandlerFactories().
+/// Clear all scheme handler factories registered with the global request
+/// context. Returns false on error. This function may be called on any thread
+/// in the browser process. Using this function is equivalent to calling
+/// CefRequestContext::GetGlobalContext()->ClearSchemeHandlerFactories().
 ///
 /*--cef()--*/
 bool CefClearSchemeHandlerFactories();
 
 ///
-// Class that manages custom scheme registrations.
+/// Class that manages custom scheme registrations.
 ///
 /*--cef(source=library)--*/
 class CefSchemeRegistrar : public CefBaseScoped {
  public:
   ///
-  // Register a custom scheme. This method should not be called for the built-in
-  // HTTP, HTTPS, FILE, FTP, ABOUT and DATA schemes.
-  //
-  // See cef_scheme_options_t for possible values for |options|.
-  //
-  // This function may be called on any thread. It should only be called once
-  // per unique |scheme_name| value. If |scheme_name| is already registered or
-  // if an error occurs this method will return false.
+  /// Register a custom scheme. This method should not be called for the
+  /// built-in HTTP, HTTPS, FILE, FTP, ABOUT and DATA schemes.
+  ///
+  /// See cef_scheme_options_t for possible values for |options|.
+  ///
+  /// This function may be called on any thread. It should only be called once
+  /// per unique |scheme_name| value. If |scheme_name| is already registered or
+  /// if an error occurs this method will return false.
   ///
   /*--cef()--*/
   virtual bool AddCustomScheme(const CefString& scheme_name, int options) = 0;
 };
 
 ///
-// Class that creates CefResourceHandler instances for handling scheme requests.
-// The methods of this class will always be called on the IO thread.
+/// Class that creates CefResourceHandler instances for handling scheme
+/// requests. The methods of this class will always be called on the IO thread.
 ///
 /*--cef(source=client,no_debugct_check)--*/
 class CefSchemeHandlerFactory : public virtual CefBaseRefCounted {
  public:
   ///
-  // Return a new resource handler instance to handle the request or an empty
-  // reference to allow default handling of the request. |browser| and |frame|
-  // will be the browser window and frame respectively that originated the
-  // request or NULL if the request did not originate from a browser window
-  // (for example, if the request came from CefURLRequest). The |request| object
-  // passed to this method cannot be modified.
+  /// Return a new resource handler instance to handle the request or an empty
+  /// reference to allow default handling of the request. |browser| and |frame|
+  /// will be the browser window and frame respectively that originated the
+  /// request or NULL if the request did not originate from a browser window
+  /// (for example, if the request came from CefURLRequest). The |request|
+  /// object passed to this method cannot be modified.
   ///
   /*--cef(optional_param=browser,optional_param=frame)--*/
   virtual CefRefPtr<CefResourceHandler> Create(
diff --git a/src/include/cef_server.h b/src/include/cef_server.h
index e22b8a6..b868581 100644
--- a/src/include/cef_server.h
+++ b/src/include/cef_server.h
@@ -47,11 +47,11 @@
 class CefServerHandler;
 
 ///
-// Class representing a server that supports HTTP and WebSocket requests. Server
-// capacity is limited and is intended to handle only a small number of
-// simultaneous connections (e.g. for communicating between applications on
-// localhost). The methods of this class are safe to call from any thread in the
-// brower process unless otherwise indicated.
+/// Class representing a server that supports HTTP and WebSocket requests.
+/// Server capacity is limited and is intended to handle only a small number of
+/// simultaneous connections (e.g. for communicating between applications on
+/// localhost). The methods of this class are safe to call from any thread in
+/// the brower process unless otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefServer : public CefBaseRefCounted {
@@ -59,74 +59,74 @@
   typedef std::multimap<CefString, CefString> HeaderMap;
 
   ///
-  // Create a new server that binds to |address| and |port|. |address| must be a
-  // valid IPv4 or IPv6 address (e.g. 127.0.0.1 or ::1) and |port| must be a
-  // port number outside of the reserved range (e.g. between 1025 and 65535 on
-  // most platforms). |backlog| is the maximum number of pending connections.
-  // A new thread will be created for each CreateServer call (the "dedicated
-  // server thread"). It is therefore recommended to use a different
-  // CefServerHandler instance for each CreateServer call to avoid thread safety
-  // issues in the CefServerHandler implementation. The
-  // CefServerHandler::OnServerCreated method will be called on the dedicated
-  // server thread to report success or failure. See
-  // CefServerHandler::OnServerCreated documentation for a description of server
-  // lifespan.
+  /// Create a new server that binds to |address| and |port|. |address| must be
+  /// a valid IPv4 or IPv6 address (e.g. 127.0.0.1 or ::1) and |port| must be a
+  /// port number outside of the reserved range (e.g. between 1025 and 65535 on
+  /// most platforms). |backlog| is the maximum number of pending connections.
+  /// A new thread will be created for each CreateServer call (the "dedicated
+  /// server thread"). It is therefore recommended to use a different
+  /// CefServerHandler instance for each CreateServer call to avoid thread
+  /// safety issues in the CefServerHandler implementation. The
+  /// CefServerHandler::OnServerCreated method will be called on the dedicated
+  /// server thread to report success or failure. See
+  /// CefServerHandler::OnServerCreated documentation for a description of
+  /// server lifespan.
   ///
   /*--cef()--*/
   static void CreateServer(const CefString& address,
-                           uint16 port,
+                           uint16_t port,
                            int backlog,
                            CefRefPtr<CefServerHandler> handler);
 
   ///
-  // Returns the task runner for the dedicated server thread.
+  /// Returns the task runner for the dedicated server thread.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefTaskRunner> GetTaskRunner() = 0;
 
   ///
-  // Stop the server and shut down the dedicated server thread. See
-  // CefServerHandler::OnServerCreated documentation for a description of
-  // server lifespan.
+  /// Stop the server and shut down the dedicated server thread. See
+  /// CefServerHandler::OnServerCreated documentation for a description of
+  /// server lifespan.
   ///
   /*--cef()--*/
   virtual void Shutdown() = 0;
 
   ///
-  // Returns true if the server is currently running and accepting incoming
-  // connections. See CefServerHandler::OnServerCreated documentation for a
-  // description of server lifespan. This method must be called on the dedicated
-  // server thread.
+  /// Returns true if the server is currently running and accepting incoming
+  /// connections. See CefServerHandler::OnServerCreated documentation for a
+  /// description of server lifespan. This method must be called on the
+  /// dedicated server thread.
   ///
   /*--cef()--*/
   virtual bool IsRunning() = 0;
 
   ///
-  // Returns the server address including the port number.
+  /// Returns the server address including the port number.
   ///
   /*--cef()--*/
   virtual CefString GetAddress() = 0;
 
   ///
-  // Returns true if the server currently has a connection. This method must be
-  // called on the dedicated server thread.
+  /// Returns true if the server currently has a connection. This method must be
+  /// called on the dedicated server thread.
   ///
   /*--cef()--*/
   virtual bool HasConnection() = 0;
 
   ///
-  // Returns true if |connection_id| represents a valid connection. This method
-  // must be called on the dedicated server thread.
+  /// Returns true if |connection_id| represents a valid connection. This method
+  /// must be called on the dedicated server thread.
   ///
   /*--cef()--*/
   virtual bool IsValidConnection(int connection_id) = 0;
 
   ///
-  // Send an HTTP 200 "OK" response to the connection identified by
-  // |connection_id|. |content_type| is the response content type (e.g.
-  // "text/html"), |data| is the response content, and |data_size| is the size
-  // of |data| in bytes. The contents of |data| will be copied. The connection
-  // will be closed automatically after the response is sent.
+  /// Send an HTTP 200 "OK" response to the connection identified by
+  /// |connection_id|. |content_type| is the response content type (e.g.
+  /// "text/html"), |data| is the response content, and |data_size| is the size
+  /// of |data| in bytes. The contents of |data| will be copied. The connection
+  /// will be closed automatically after the response is sent.
   ///
   /*--cef()--*/
   virtual void SendHttp200Response(int connection_id,
@@ -135,51 +135,51 @@
                                    size_t data_size) = 0;
 
   ///
-  // Send an HTTP 404 "Not Found" response to the connection identified by
-  // |connection_id|. The connection will be closed automatically after the
-  // response is sent.
+  /// Send an HTTP 404 "Not Found" response to the connection identified by
+  /// |connection_id|. The connection will be closed automatically after the
+  /// response is sent.
   ///
   /*--cef()--*/
   virtual void SendHttp404Response(int connection_id) = 0;
 
   ///
-  // Send an HTTP 500 "Internal Server Error" response to the connection
-  // identified by |connection_id|. |error_message| is the associated error
-  // message. The connection will be closed automatically after the response is
-  // sent.
+  /// Send an HTTP 500 "Internal Server Error" response to the connection
+  /// identified by |connection_id|. |error_message| is the associated error
+  /// message. The connection will be closed automatically after the response is
+  /// sent.
   ///
   /*--cef()--*/
   virtual void SendHttp500Response(int connection_id,
                                    const CefString& error_message) = 0;
 
   ///
-  // Send a custom HTTP response to the connection identified by
-  // |connection_id|. |response_code| is the HTTP response code sent in the
-  // status line (e.g. 200), |content_type| is the response content type sent
-  // as the "Content-Type" header (e.g. "text/html"), |content_length| is the
-  // expected content length, and |extra_headers| is the map of extra response
-  // headers. If |content_length| is >= 0 then the "Content-Length" header will
-  // be sent. If |content_length| is 0 then no content is expected and the
-  // connection will be closed automatically after the response is sent. If
-  // |content_length| is < 0 then no "Content-Length" header will be sent and
-  // the client will continue reading until the connection is closed. Use the
-  // SendRawData method to send the content, if applicable, and call
-  // CloseConnection after all content has been sent.
+  /// Send a custom HTTP response to the connection identified by
+  /// |connection_id|. |response_code| is the HTTP response code sent in the
+  /// status line (e.g. 200), |content_type| is the response content type sent
+  /// as the "Content-Type" header (e.g. "text/html"), |content_length| is the
+  /// expected content length, and |extra_headers| is the map of extra response
+  /// headers. If |content_length| is >= 0 then the "Content-Length" header will
+  /// be sent. If |content_length| is 0 then no content is expected and the
+  /// connection will be closed automatically after the response is sent. If
+  /// |content_length| is < 0 then no "Content-Length" header will be sent and
+  /// the client will continue reading until the connection is closed. Use the
+  /// SendRawData method to send the content, if applicable, and call
+  /// CloseConnection after all content has been sent.
   ///
   /*--cef(optional_param=extra_headers)--*/
   virtual void SendHttpResponse(int connection_id,
                                 int response_code,
                                 const CefString& content_type,
-                                int64 content_length,
+                                int64_t content_length,
                                 const HeaderMap& extra_headers) = 0;
 
   ///
-  // Send raw data directly to the connection identified by |connection_id|.
-  // |data| is the raw data and |data_size| is the size of |data| in bytes.
-  // The contents of |data| will be copied. No validation of |data| is
-  // performed internally so the client should be careful to send the amount
-  // indicated by the "Content-Length" header, if specified. See
-  // SendHttpResponse documentation for intended usage.
+  /// Send raw data directly to the connection identified by |connection_id|.
+  /// |data| is the raw data and |data_size| is the size of |data| in bytes.
+  /// The contents of |data| will be copied. No validation of |data| is
+  /// performed internally so the client should be careful to send the amount
+  /// indicated by the "Content-Length" header, if specified. See
+  /// SendHttpResponse documentation for intended usage.
   ///
   /*--cef()--*/
   virtual void SendRawData(int connection_id,
@@ -187,17 +187,17 @@
                            size_t data_size) = 0;
 
   ///
-  // Close the connection identified by |connection_id|. See SendHttpResponse
-  // documentation for intended usage.
+  /// Close the connection identified by |connection_id|. See SendHttpResponse
+  /// documentation for intended usage.
   ///
   /*--cef()--*/
   virtual void CloseConnection(int connection_id) = 0;
 
   ///
-  // Send a WebSocket message to the connection identified by |connection_id|.
-  // |data| is the response content and |data_size| is the size of |data| in
-  // bytes. The contents of |data| will be copied. See
-  // CefServerHandler::OnWebSocketRequest documentation for intended usage.
+  /// Send a WebSocket message to the connection identified by |connection_id|.
+  /// |data| is the response content and |data_size| is the size of |data| in
+  /// bytes. The contents of |data| will be copied. See
+  /// CefServerHandler::OnWebSocketRequest documentation for intended usage.
   ///
   /*--cef()--*/
   virtual void SendWebSocketMessage(int connection_id,
@@ -206,62 +206,62 @@
 };
 
 ///
-// Implement this interface to handle HTTP server requests. A new thread will be
-// created for each CefServer::CreateServer call (the "dedicated server
-// thread"), and the methods of this class will be called on that thread. It is
-// therefore recommended to use a different CefServerHandler instance for each
-// CefServer::CreateServer call to avoid thread safety issues in the
-// CefServerHandler implementation.
+/// Implement this interface to handle HTTP server requests. A new thread will
+/// be created for each CefServer::CreateServer call (the "dedicated server
+/// thread"), and the methods of this class will be called on that thread. It is
+/// therefore recommended to use a different CefServerHandler instance for each
+/// CefServer::CreateServer call to avoid thread safety issues in the
+/// CefServerHandler implementation.
 ///
 /*--cef(source=client)--*/
 class CefServerHandler : public virtual CefBaseRefCounted {
  public:
   ///
-  // Called when |server| is created. If the server was started successfully
-  // then CefServer::IsRunning will return true. The server will continue
-  // running until CefServer::Shutdown is called, after which time
-  // OnServerDestroyed will be called. If the server failed to start then
-  // OnServerDestroyed will be called immediately after this method returns.
+  /// Called when |server| is created. If the server was started successfully
+  /// then CefServer::IsRunning will return true. The server will continue
+  /// running until CefServer::Shutdown is called, after which time
+  /// OnServerDestroyed will be called. If the server failed to start then
+  /// OnServerDestroyed will be called immediately after this method returns.
   ///
   /*--cef()--*/
   virtual void OnServerCreated(CefRefPtr<CefServer> server) = 0;
 
   ///
-  // Called when |server| is destroyed. The server thread will be stopped after
-  // this method returns. The client should release any references to |server|
-  // when this method is called. See OnServerCreated documentation for a
-  // description of server lifespan.
+  /// Called when |server| is destroyed. The server thread will be stopped after
+  /// this method returns. The client should release any references to |server|
+  /// when this method is called. See OnServerCreated documentation for a
+  /// description of server lifespan.
   ///
   /*--cef()--*/
   virtual void OnServerDestroyed(CefRefPtr<CefServer> server) = 0;
 
   ///
-  // Called when a client connects to |server|. |connection_id| uniquely
-  // identifies the connection. Each call to this method will have a matching
-  // call to OnClientDisconnected.
+  /// Called when a client connects to |server|. |connection_id| uniquely
+  /// identifies the connection. Each call to this method will have a matching
+  /// call to OnClientDisconnected.
   ///
   /*--cef()--*/
   virtual void OnClientConnected(CefRefPtr<CefServer> server,
                                  int connection_id) = 0;
 
   ///
-  // Called when a client disconnects from |server|. |connection_id| uniquely
-  // identifies the connection. The client should release any data associated
-  // with |connection_id| when this method is called and |connection_id| should
-  // no longer be passed to CefServer methods. Disconnects can originate from
-  // either the client or the server. For example, the server will disconnect
-  // automatically after a CefServer::SendHttpXXXResponse method is called.
+  /// Called when a client disconnects from |server|. |connection_id| uniquely
+  /// identifies the connection. The client should release any data associated
+  /// with |connection_id| when this method is called and |connection_id| should
+  /// no longer be passed to CefServer methods. Disconnects can originate from
+  /// either the client or the server. For example, the server will disconnect
+  /// automatically after a CefServer::SendHttpXXXResponse method is called.
   ///
   /*--cef()--*/
   virtual void OnClientDisconnected(CefRefPtr<CefServer> server,
                                     int connection_id) = 0;
 
   ///
-  // Called when |server| receives an HTTP request. |connection_id| uniquely
-  // identifies the connection, |client_address| is the requesting IPv4 or IPv6
-  // client address including port number, and |request| contains the request
-  // contents (URL, method, headers and optional POST data). Call CefServer
-  // methods either synchronously or asynchronusly to send a response.
+  /// Called when |server| receives an HTTP request. |connection_id| uniquely
+  /// identifies the connection, |client_address| is the requesting IPv4 or IPv6
+  /// client address including port number, and |request| contains the request
+  /// contents (URL, method, headers and optional POST data). Call CefServer
+  /// methods either synchronously or asynchronusly to send a response.
   ///
   /*--cef()--*/
   virtual void OnHttpRequest(CefRefPtr<CefServer> server,
@@ -270,17 +270,18 @@
                              CefRefPtr<CefRequest> request) = 0;
 
   ///
-  // Called when |server| receives a WebSocket request. |connection_id| uniquely
-  // identifies the connection, |client_address| is the requesting IPv4 or
-  // IPv6 client address including port number, and |request| contains the
-  // request contents (URL, method, headers and optional POST data). Execute
-  // |callback| either synchronously or asynchronously to accept or decline the
-  // WebSocket connection. If the request is accepted then OnWebSocketConnected
-  // will be called after the WebSocket has connected and incoming messages will
-  // be delivered to the OnWebSocketMessage callback. If the request is declined
-  // then the client will be disconnected and OnClientDisconnected will be
-  // called. Call the CefServer::SendWebSocketMessage method after receiving the
-  // OnWebSocketConnected callback to respond with WebSocket messages.
+  /// Called when |server| receives a WebSocket request. |connection_id|
+  /// uniquely identifies the connection, |client_address| is the requesting
+  /// IPv4 or IPv6 client address including port number, and |request| contains
+  /// the request contents (URL, method, headers and optional POST data).
+  /// Execute |callback| either synchronously or asynchronously to accept or
+  /// decline the WebSocket connection. If the request is accepted then
+  /// OnWebSocketConnected will be called after the WebSocket has connected and
+  /// incoming messages will be delivered to the OnWebSocketMessage callback. If
+  /// the request is declined then the client will be disconnected and
+  /// OnClientDisconnected will be called. Call the
+  /// CefServer::SendWebSocketMessage method after receiving the
+  /// OnWebSocketConnected callback to respond with WebSocket messages.
   ///
   /*--cef()--*/
   virtual void OnWebSocketRequest(CefRefPtr<CefServer> server,
@@ -290,20 +291,20 @@
                                   CefRefPtr<CefCallback> callback) = 0;
 
   ///
-  // Called after the client has accepted the WebSocket connection for |server|
-  // and |connection_id| via the OnWebSocketRequest callback. See
-  // OnWebSocketRequest documentation for intended usage.
+  /// Called after the client has accepted the WebSocket connection for |server|
+  /// and |connection_id| via the OnWebSocketRequest callback. See
+  /// OnWebSocketRequest documentation for intended usage.
   ///
   /*--cef()--*/
   virtual void OnWebSocketConnected(CefRefPtr<CefServer> server,
                                     int connection_id) = 0;
 
   ///
-  // Called when |server| receives an WebSocket message. |connection_id|
-  // uniquely identifies the connection, |data| is the message content and
-  // |data_size| is the size of |data| in bytes. Do not keep a reference to
-  // |data| outside of this method. See OnWebSocketRequest documentation for
-  // intended usage.
+  /// Called when |server| receives an WebSocket message. |connection_id|
+  /// uniquely identifies the connection, |data| is the message content and
+  /// |data_size| is the size of |data| in bytes. Do not keep a reference to
+  /// |data| outside of this method. See OnWebSocketRequest documentation for
+  /// intended usage.
   ///
   /*--cef()--*/
   virtual void OnWebSocketMessage(CefRefPtr<CefServer> server,
diff --git a/src/include/cef_request_callback.h b/src/include/cef_shared_memory_region.h
similarity index 71%
copy from src/include/cef_request_callback.h
copy to src/include/cef_shared_memory_region.h
index 68094de..126a979 100644
--- a/src/include/cef_request_callback.h
+++ b/src/include/cef_shared_memory_region.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -34,30 +34,36 @@
 // tools directory for more information.
 //
 
-#ifndef CEF_INCLUDE_CEF_REQUEST_CALLBACK_H_
-#define CEF_INCLUDE_CEF_REQUEST_CALLBACK_H_
+#ifndef CEF_INCLUDE_CEF_SHARED_MEMORY_REGION_H_
+#define CEF_INCLUDE_CEF_SHARED_MEMORY_REGION_H_
 #pragma once
 
 #include "include/cef_base.h"
 
 ///
-// Callback interface used for asynchronous continuation of url requests.
+/// Class that wraps platform-dependent share memory region mapping.
 ///
 /*--cef(source=library)--*/
-class CefRequestCallback : public virtual CefBaseRefCounted {
+class CefSharedMemoryRegion : public virtual CefBaseRefCounted {
  public:
   ///
-  // Continue the url request. If |allow| is true the request will be continued.
-  // Otherwise, the request will be canceled.
-  ///
-  /*--cef(capi_name=cont)--*/
-  virtual void Continue(bool allow) = 0;
-
-  ///
-  // Cancel the url request.
+  /// Returns true if the mapping is valid.
   ///
   /*--cef()--*/
-  virtual void Cancel() = 0;
+  virtual bool IsValid() = 0;
+
+  ///
+  /// Returns the size of the mapping in bytes. Returns 0 for invalid instances.
+  ///
+  /*--cef()--*/
+  virtual size_t Size() = 0;
+
+  ///
+  /// Returns the pointer to the memory. Returns nullptr for invalid instances.
+  /// The returned pointer is only valid for the life span of this object.
+  ///
+  /*--cef()--*/
+  virtual void* Memory() = 0;
 };
 
-#endif  // CEF_INCLUDE_CEF_REQUEST_CALLBACK_H_
+#endif  // CEF_INCLUDE_CEF_SHARED_MEMORY_REGION_H_
diff --git a/src/include/cef_shared_process_message_builder.h b/src/include/cef_shared_process_message_builder.h
new file mode 100644
index 0000000..f67e58f
--- /dev/null
+++ b/src/include/cef_shared_process_message_builder.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---------------------------------------------------------------------------
+//
+// The contents of this file must follow a specific format in order to
+// support the CEF translator tool. See the translator.README.txt file in the
+// tools directory for more information.
+//
+
+#ifndef CEF_INCLUDE_CEF_SHARED_PROCESS_MESSAGE_BUILDER_H_
+#define CEF_INCLUDE_CEF_SHARED_PROCESS_MESSAGE_BUILDER_H_
+#pragma once
+
+#include "include/cef_process_message.h"
+
+///
+/// Class that builds a CefProcessMessage containing a shared memory region.
+/// This class is not thread-safe but may be used exclusively on a different
+/// thread from the one which constructed it.
+///
+/*--cef(source=library)--*/
+class CefSharedProcessMessageBuilder : public virtual CefBaseRefCounted {
+ public:
+  ///
+  /// Creates a new CefSharedProcessMessageBuilder with the specified |name| and
+  /// shared memory region of specified |byte_size|.
+  ///
+  /*--cef()--*/
+  static CefRefPtr<CefSharedProcessMessageBuilder> Create(const CefString& name,
+                                                          size_t byte_size);
+  ///
+  /// Returns true if the builder is valid.
+  ///
+  /*--cef()--*/
+  virtual bool IsValid() = 0;
+
+  ///
+  /// Returns the size of the shared memory region in bytes. Returns 0 for
+  /// invalid instances.
+  ///
+  /*--cef()--*/
+  virtual size_t Size() = 0;
+
+  ///
+  /// Returns the pointer to the writable memory. Returns nullptr for invalid
+  /// instances. The returned pointer is only valid for the life span of this
+  /// object.
+  ///
+  /*--cef()--*/
+  virtual void* Memory() = 0;
+
+  ///
+  /// Creates a new CefProcessMessage from the data provided to the builder.
+  /// Returns nullptr for invalid instances. Invalidates the builder instance.
+  ///
+  /*--cef()--*/
+  virtual CefRefPtr<CefProcessMessage> Build() = 0;
+};
+
+#endif  // CEF_INCLUDE_CEF_SHARED_PROCESS_MESSAGE_BUILDER_H_
diff --git a/src/include/cef_ssl_info.h b/src/include/cef_ssl_info.h
index 40dc5c0..67b9cdf 100644
--- a/src/include/cef_ssl_info.h
+++ b/src/include/cef_ssl_info.h
@@ -44,27 +44,27 @@
 #include "include/cef_x509_certificate.h"
 
 ///
-// Class representing SSL information.
+/// Class representing SSL information.
 ///
 /*--cef(source=library)--*/
 class CefSSLInfo : public virtual CefBaseRefCounted {
  public:
   ///
-  // Returns a bitmask containing any and all problems verifying the server
-  // certificate.
+  /// Returns a bitmask containing any and all problems verifying the server
+  /// certificate.
   ///
   /*--cef(default_retval=CERT_STATUS_NONE)--*/
   virtual cef_cert_status_t GetCertStatus() = 0;
 
   ///
-  // Returns the X.509 certificate.
+  /// Returns the X.509 certificate.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefX509Certificate> GetX509Certificate() = 0;
 };
 
 ///
-// Returns true if the certificate status represents an error.
+/// Returns true if the certificate status represents an error.
 ///
 /*--cef()--*/
 bool CefIsCertStatusError(cef_cert_status_t status);
diff --git a/src/include/cef_ssl_status.h b/src/include/cef_ssl_status.h
index 002ac49..fe108df 100644
--- a/src/include/cef_ssl_status.h
+++ b/src/include/cef_ssl_status.h
@@ -43,38 +43,38 @@
 #include "include/cef_x509_certificate.h"
 
 ///
-// Class representing the SSL information for a navigation entry.
+/// Class representing the SSL information for a navigation entry.
 ///
 /*--cef(source=library)--*/
 class CefSSLStatus : public virtual CefBaseRefCounted {
  public:
   ///
-  // Returns true if the status is related to a secure SSL/TLS connection.
+  /// Returns true if the status is related to a secure SSL/TLS connection.
   ///
   /*--cef()--*/
   virtual bool IsSecureConnection() = 0;
 
   ///
-  // Returns a bitmask containing any and all problems verifying the server
-  // certificate.
+  /// Returns a bitmask containing any and all problems verifying the server
+  /// certificate.
   ///
   /*--cef(default_retval=CERT_STATUS_NONE)--*/
   virtual cef_cert_status_t GetCertStatus() = 0;
 
   ///
-  // Returns the SSL version used for the SSL connection.
+  /// Returns the SSL version used for the SSL connection.
   ///
   /*--cef(default_retval=SSL_CONNECTION_VERSION_UNKNOWN)--*/
   virtual cef_ssl_version_t GetSSLVersion() = 0;
 
   ///
-  // Returns a bitmask containing the page security content status.
+  /// Returns a bitmask containing the page security content status.
   ///
   /*--cef(default_retval=SSL_CONTENT_NORMAL_CONTENT)--*/
   virtual cef_ssl_content_status_t GetContentStatus() = 0;
 
   ///
-  // Returns the X.509 certificate.
+  /// Returns the X.509 certificate.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefX509Certificate> GetX509Certificate() = 0;
diff --git a/src/include/cef_stream.h b/src/include/cef_stream.h
index c40392e..22d4ef0 100644
--- a/src/include/cef_stream.h
+++ b/src/include/cef_stream.h
@@ -40,197 +40,199 @@
 #include "include/cef_base.h"
 
 ///
-// Interface the client can implement to provide a custom stream reader. The
-// methods of this class may be called on any thread.
+/// Interface the client can implement to provide a custom stream reader. The
+/// methods of this class may be called on any thread.
 ///
 /*--cef(source=client)--*/
 class CefReadHandler : public virtual CefBaseRefCounted {
  public:
   ///
-  // Read raw binary data.
+  /// Read raw binary data.
   ///
   /*--cef()--*/
   virtual size_t Read(void* ptr, size_t size, size_t n) = 0;
 
   ///
-  // Seek to the specified offset position. |whence| may be any one of
-  // SEEK_CUR, SEEK_END or SEEK_SET. Return zero on success and non-zero on
-  // failure.
+  /// Seek to the specified offset position. |whence| may be any one of
+  /// SEEK_CUR, SEEK_END or SEEK_SET. Return zero on success and non-zero on
+  /// failure.
   ///
   /*--cef()--*/
-  virtual int Seek(int64 offset, int whence) = 0;
+  virtual int Seek(int64_t offset, int whence) = 0;
 
   ///
-  // Return the current offset position.
+  /// Return the current offset position.
   ///
   /*--cef()--*/
-  virtual int64 Tell() = 0;
+  virtual int64_t Tell() = 0;
 
   ///
-  // Return non-zero if at end of file.
+  /// Return non-zero if at end of file.
   ///
   /*--cef()--*/
   virtual int Eof() = 0;
 
   ///
-  // Return true if this handler performs work like accessing the file system
-  // which may block. Used as a hint for determining the thread to access the
-  // handler from.
+  /// Return true if this handler performs work like accessing the file system
+  /// which may block. Used as a hint for determining the thread to access the
+  /// handler from.
   ///
   /*--cef()--*/
   virtual bool MayBlock() = 0;
 };
 
 ///
-// Class used to read data from a stream. The methods of this class may be
-// called on any thread.
+/// Class used to read data from a stream. The methods of this class may be
+/// called on any thread.
 ///
 /*--cef(source=library)--*/
 class CefStreamReader : public virtual CefBaseRefCounted {
  public:
   ///
-  // Create a new CefStreamReader object from a file.
+  /// Create a new CefStreamReader object from a file.
   ///
   /*--cef()--*/
   static CefRefPtr<CefStreamReader> CreateForFile(const CefString& fileName);
+
   ///
-  // Create a new CefStreamReader object from data.
+  /// Create a new CefStreamReader object from data.
   ///
   /*--cef()--*/
   static CefRefPtr<CefStreamReader> CreateForData(void* data, size_t size);
+
   ///
-  // Create a new CefStreamReader object from a custom handler.
+  /// Create a new CefStreamReader object from a custom handler.
   ///
   /*--cef()--*/
   static CefRefPtr<CefStreamReader> CreateForHandler(
       CefRefPtr<CefReadHandler> handler);
 
   ///
-  // Read raw binary data.
+  /// Read raw binary data.
   ///
   /*--cef()--*/
   virtual size_t Read(void* ptr, size_t size, size_t n) = 0;
 
   ///
-  // Seek to the specified offset position. |whence| may be any one of
-  // SEEK_CUR, SEEK_END or SEEK_SET. Returns zero on success and non-zero on
-  // failure.
+  /// Seek to the specified offset position. |whence| may be any one of
+  /// SEEK_CUR, SEEK_END or SEEK_SET. Returns zero on success and non-zero on
+  /// failure.
   ///
   /*--cef()--*/
-  virtual int Seek(int64 offset, int whence) = 0;
+  virtual int Seek(int64_t offset, int whence) = 0;
 
   ///
-  // Return the current offset position.
+  /// Return the current offset position.
   ///
   /*--cef()--*/
-  virtual int64 Tell() = 0;
+  virtual int64_t Tell() = 0;
 
   ///
-  // Return non-zero if at end of file.
+  /// Return non-zero if at end of file.
   ///
   /*--cef()--*/
   virtual int Eof() = 0;
 
   ///
-  // Returns true if this reader performs work like accessing the file system
-  // which may block. Used as a hint for determining the thread to access the
-  // reader from.
+  /// Returns true if this reader performs work like accessing the file system
+  /// which may block. Used as a hint for determining the thread to access the
+  /// reader from.
   ///
   /*--cef()--*/
   virtual bool MayBlock() = 0;
 };
 
 ///
-// Interface the client can implement to provide a custom stream writer. The
-// methods of this class may be called on any thread.
+/// Interface the client can implement to provide a custom stream writer. The
+/// methods of this class may be called on any thread.
 ///
 /*--cef(source=client)--*/
 class CefWriteHandler : public virtual CefBaseRefCounted {
  public:
   ///
-  // Write raw binary data.
+  /// Write raw binary data.
   ///
   /*--cef()--*/
   virtual size_t Write(const void* ptr, size_t size, size_t n) = 0;
 
   ///
-  // Seek to the specified offset position. |whence| may be any one of
-  // SEEK_CUR, SEEK_END or SEEK_SET. Return zero on success and non-zero on
-  // failure.
+  /// Seek to the specified offset position. |whence| may be any one of
+  /// SEEK_CUR, SEEK_END or SEEK_SET. Return zero on success and non-zero on
+  /// failure.
   ///
   /*--cef()--*/
-  virtual int Seek(int64 offset, int whence) = 0;
+  virtual int Seek(int64_t offset, int whence) = 0;
 
   ///
-  // Return the current offset position.
+  /// Return the current offset position.
   ///
   /*--cef()--*/
-  virtual int64 Tell() = 0;
+  virtual int64_t Tell() = 0;
 
   ///
-  // Flush the stream.
+  /// Flush the stream.
   ///
   /*--cef()--*/
   virtual int Flush() = 0;
 
   ///
-  // Return true if this handler performs work like accessing the file system
-  // which may block. Used as a hint for determining the thread to access the
-  // handler from.
+  /// Return true if this handler performs work like accessing the file system
+  /// which may block. Used as a hint for determining the thread to access the
+  /// handler from.
   ///
   /*--cef()--*/
   virtual bool MayBlock() = 0;
 };
 
 ///
-// Class used to write data to a stream. The methods of this class may be called
-// on any thread.
+/// Class used to write data to a stream. The methods of this class may be
+/// called on any thread.
 ///
 /*--cef(source=library)--*/
 class CefStreamWriter : public virtual CefBaseRefCounted {
  public:
   ///
-  // Create a new CefStreamWriter object for a file.
+  /// Create a new CefStreamWriter object for a file.
   ///
   /*--cef()--*/
   static CefRefPtr<CefStreamWriter> CreateForFile(const CefString& fileName);
   ///
-  // Create a new CefStreamWriter object for a custom handler.
+  /// Create a new CefStreamWriter object for a custom handler.
   ///
   /*--cef()--*/
   static CefRefPtr<CefStreamWriter> CreateForHandler(
       CefRefPtr<CefWriteHandler> handler);
 
   ///
-  // Write raw binary data.
+  /// Write raw binary data.
   ///
   /*--cef()--*/
   virtual size_t Write(const void* ptr, size_t size, size_t n) = 0;
 
   ///
-  // Seek to the specified offset position. |whence| may be any one of
-  // SEEK_CUR, SEEK_END or SEEK_SET. Returns zero on success and non-zero on
-  // failure.
+  /// Seek to the specified offset position. |whence| may be any one of
+  /// SEEK_CUR, SEEK_END or SEEK_SET. Returns zero on success and non-zero on
+  /// failure.
   ///
   /*--cef()--*/
-  virtual int Seek(int64 offset, int whence) = 0;
+  virtual int Seek(int64_t offset, int whence) = 0;
 
   ///
-  // Return the current offset position.
+  /// Return the current offset position.
   ///
   /*--cef()--*/
-  virtual int64 Tell() = 0;
+  virtual int64_t Tell() = 0;
 
   ///
-  // Flush the stream.
+  /// Flush the stream.
   ///
   /*--cef()--*/
   virtual int Flush() = 0;
 
   ///
-  // Returns true if this writer performs work like accessing the file system
-  // which may block. Used as a hint for determining the thread to access the
-  // writer from.
+  /// Returns true if this writer performs work like accessing the file system
+  /// which may block. Used as a hint for determining the thread to access the
+  /// writer from.
   ///
   /*--cef()--*/
   virtual bool MayBlock() = 0;
diff --git a/src/include/cef_string_visitor.h b/src/include/cef_string_visitor.h
index f23dfb6..c77e59c 100644
--- a/src/include/cef_string_visitor.h
+++ b/src/include/cef_string_visitor.h
@@ -40,13 +40,13 @@
 #include "include/cef_base.h"
 
 ///
-// Implement this interface to receive string values asynchronously.
+/// Implement this interface to receive string values asynchronously.
 ///
 /*--cef(source=client)--*/
 class CefStringVisitor : public virtual CefBaseRefCounted {
  public:
   ///
-  // Method that will be executed.
+  /// Method that will be executed.
   ///
   /*--cef(optional_param=string)--*/
   virtual void Visit(const CefString& string) = 0;
diff --git a/src/include/cef_task.h b/src/include/cef_task.h
index 642c69e..2e5085e 100644
--- a/src/include/cef_task.h
+++ b/src/include/cef_task.h
@@ -42,106 +42,107 @@
 typedef cef_thread_id_t CefThreadId;
 
 ///
-// Implement this interface for asynchronous task execution. If the task is
-// posted successfully and if the associated message loop is still running then
-// the Execute() method will be called on the target thread. If the task fails
-// to post then the task object may be destroyed on the source thread instead of
-// the target thread. For this reason be cautious when performing work in the
-// task object destructor.
+/// Implement this interface for asynchronous task execution. If the task is
+/// posted successfully and if the associated message loop is still running then
+/// the Execute() method will be called on the target thread. If the task fails
+/// to post then the task object may be destroyed on the source thread instead
+/// of the target thread. For this reason be cautious when performing work in
+/// the task object destructor.
 ///
 /*--cef(source=client,no_debugct_check)--*/
 class CefTask : public virtual CefBaseRefCounted {
  public:
   ///
-  // Method that will be executed on the target thread.
+  /// Method that will be executed on the target thread.
   ///
   /*--cef()--*/
   virtual void Execute() = 0;
 };
 
 ///
-// Class that asynchronously executes tasks on the associated thread. It is safe
-// to call the methods of this class on any thread.
-//
-// CEF maintains multiple internal threads that are used for handling different
-// types of tasks in different processes. The cef_thread_id_t definitions in
-// cef_types.h list the common CEF threads. Task runners are also available for
-// other CEF threads as appropriate (for example, V8 WebWorker threads).
+/// Class that asynchronously executes tasks on the associated thread. It is
+/// safe to call the methods of this class on any thread.
+///
+/// CEF maintains multiple internal threads that are used for handling different
+/// types of tasks in different processes. The cef_thread_id_t definitions in
+/// cef_types.h list the common CEF threads. Task runners are also available for
+/// other CEF threads as appropriate (for example, V8 WebWorker threads).
 ///
 /*--cef(source=library)--*/
 class CefTaskRunner : public virtual CefBaseRefCounted {
  public:
   ///
-  // Returns the task runner for the current thread. Only CEF threads will have
-  // task runners. An empty reference will be returned if this method is called
-  // on an invalid thread.
+  /// Returns the task runner for the current thread. Only CEF threads will have
+  /// task runners. An empty reference will be returned if this method is called
+  /// on an invalid thread.
   ///
   /*--cef()--*/
   static CefRefPtr<CefTaskRunner> GetForCurrentThread();
 
   ///
-  // Returns the task runner for the specified CEF thread.
+  /// Returns the task runner for the specified CEF thread.
   ///
   /*--cef()--*/
   static CefRefPtr<CefTaskRunner> GetForThread(CefThreadId threadId);
 
   ///
-  // Returns true if this object is pointing to the same task runner as |that|
-  // object.
+  /// Returns true if this object is pointing to the same task runner as |that|
+  /// object.
   ///
   /*--cef()--*/
   virtual bool IsSame(CefRefPtr<CefTaskRunner> that) = 0;
 
   ///
-  // Returns true if this task runner belongs to the current thread.
+  /// Returns true if this task runner belongs to the current thread.
   ///
   /*--cef()--*/
   virtual bool BelongsToCurrentThread() = 0;
 
   ///
-  // Returns true if this task runner is for the specified CEF thread.
+  /// Returns true if this task runner is for the specified CEF thread.
   ///
   /*--cef()--*/
   virtual bool BelongsToThread(CefThreadId threadId) = 0;
 
   ///
-  // Post a task for execution on the thread associated with this task runner.
-  // Execution will occur asynchronously.
+  /// Post a task for execution on the thread associated with this task runner.
+  /// Execution will occur asynchronously.
   ///
   /*--cef()--*/
   virtual bool PostTask(CefRefPtr<CefTask> task) = 0;
 
   ///
-  // Post a task for delayed execution on the thread associated with this task
-  // runner. Execution will occur asynchronously. Delayed tasks are not
-  // supported on V8 WebWorker threads and will be executed without the
-  // specified delay.
+  /// Post a task for delayed execution on the thread associated with this task
+  /// runner. Execution will occur asynchronously. Delayed tasks are not
+  /// supported on V8 WebWorker threads and will be executed without the
+  /// specified delay.
   ///
   /*--cef()--*/
-  virtual bool PostDelayedTask(CefRefPtr<CefTask> task, int64 delay_ms) = 0;
+  virtual bool PostDelayedTask(CefRefPtr<CefTask> task, int64_t delay_ms) = 0;
 };
 
 ///
-// Returns true if called on the specified thread. Equivalent to using
-// CefTaskRunner::GetForThread(threadId)->BelongsToCurrentThread().
+/// Returns true if called on the specified thread. Equivalent to using
+/// CefTaskRunner::GetForThread(threadId)->BelongsToCurrentThread().
 ///
 /*--cef()--*/
 bool CefCurrentlyOn(CefThreadId threadId);
 
 ///
-// Post a task for execution on the specified thread. Equivalent to
-// using CefTaskRunner::GetForThread(threadId)->PostTask(task).
+/// Post a task for execution on the specified thread. Equivalent to
+/// using CefTaskRunner::GetForThread(threadId)->PostTask(task).
 ///
 /*--cef()--*/
 bool CefPostTask(CefThreadId threadId, CefRefPtr<CefTask> task);
 
 ///
-// Post a task for delayed execution on the specified thread. Equivalent to
-// using CefTaskRunner::GetForThread(threadId)->PostDelayedTask(task, delay_ms).
+/// Post a task for delayed execution on the specified thread. Equivalent to
+/// using CefTaskRunner::GetForThread(threadId)->PostDelayedTask(task,
+/// delay_ms).
 ///
 /*--cef()--*/
 bool CefPostDelayedTask(CefThreadId threadId,
                         CefRefPtr<CefTask> task,
-                        int64 delay_ms);
+                        int64_t delay_ms);
 
 #endif  // CEF_INCLUDE_CEF_TASK_H_
diff --git a/src/include/cef_thread.h b/src/include/cef_thread.h
index 1d0bd4c..da00c1e 100644
--- a/src/include/cef_thread.h
+++ b/src/include/cef_thread.h
@@ -42,30 +42,30 @@
 #include "include/internal/cef_thread_internal.h"
 
 ///
-// A simple thread abstraction that establishes a message loop on a new thread.
-// The consumer uses CefTaskRunner to execute code on the thread's message loop.
-// The thread is terminated when the CefThread object is destroyed or Stop() is
-// called. All pending tasks queued on the thread's message loop will run to
-// completion before the thread is terminated. CreateThread() can be called on
-// any valid CEF thread in either the browser or render process. This class
-// should only be used for tasks that require a dedicated thread. In most cases
-// you can post tasks to an existing CEF thread instead of creating a new one;
-// see cef_task.h for details.
+/// A simple thread abstraction that establishes a message loop on a new thread.
+/// The consumer uses CefTaskRunner to execute code on the thread's message
+/// loop. The thread is terminated when the CefThread object is destroyed or
+/// Stop() is called. All pending tasks queued on the thread's message loop will
+/// run to completion before the thread is terminated. CreateThread() can be
+/// called on any valid CEF thread in either the browser or render process. This
+/// class should only be used for tasks that require a dedicated thread. In most
+/// cases you can post tasks to an existing CEF thread instead of creating a new
+/// one; see cef_task.h for details.
 ///
 /*--cef(source=library)--*/
 class CefThread : public CefBaseRefCounted {
  public:
   ///
-  // Create and start a new thread. This method does not block waiting for the
-  // thread to run initialization. |display_name| is the name that will be used
-  // to identify the thread. |priority| is the thread execution priority.
-  // |message_loop_type| indicates the set of asynchronous events that the
-  // thread can process. If |stoppable| is true the thread will stopped and
-  // joined on destruction or when Stop() is called; otherwise, the the thread
-  // cannot be stopped and will be leaked on shutdown. On Windows the
-  // |com_init_mode| value specifies how COM will be initialized for the thread.
-  // If |com_init_mode| is set to COM_INIT_MODE_STA then |message_loop_type|
-  // must be set to ML_TYPE_UI.
+  /// Create and start a new thread. This method does not block waiting for the
+  /// thread to run initialization. |display_name| is the name that will be used
+  /// to identify the thread. |priority| is the thread execution priority.
+  /// |message_loop_type| indicates the set of asynchronous events that the
+  /// thread can process. If |stoppable| is true the thread will stopped and
+  /// joined on destruction or when Stop() is called; otherwise, the thread
+  /// cannot be stopped and will be leaked on shutdown. On Windows the
+  /// |com_init_mode| value specifies how COM will be initialized for the
+  /// thread. If |com_init_mode| is set to COM_INIT_MODE_STA then
+  /// |message_loop_type| must be set to ML_TYPE_UI.
   ///
   /*--cef(optional_param=display_name)--*/
   static CefRefPtr<CefThread> CreateThread(
@@ -76,8 +76,8 @@
       cef_com_init_mode_t com_init_mode);
 
   ///
-  // Create and start a new thread with default/recommended values.
-  // |display_name| is the name that will be used to identify the thread.
+  /// Create and start a new thread with default/recommended values.
+  /// |display_name| is the name that will be used to identify the thread.
   ///
   static CefRefPtr<CefThread> CreateThread(const CefString& display_name) {
     return CreateThread(display_name, TP_NORMAL, ML_TYPE_DEFAULT, true,
@@ -85,30 +85,30 @@
   }
 
   ///
-  // Returns the CefTaskRunner that will execute code on this thread's message
-  // loop. This method is safe to call from any thread.
+  /// Returns the CefTaskRunner that will execute code on this thread's message
+  /// loop. This method is safe to call from any thread.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefTaskRunner> GetTaskRunner() = 0;
 
   ///
-  // Returns the platform thread ID. It will return the same value after Stop()
-  // is called. This method is safe to call from any thread.
+  /// Returns the platform thread ID. It will return the same value after Stop()
+  /// is called. This method is safe to call from any thread.
   ///
   /*--cef(default_retval=kInvalidPlatformThreadId)--*/
   virtual cef_platform_thread_id_t GetPlatformThreadId() = 0;
 
   ///
-  // Stop and join the thread. This method must be called from the same thread
-  // that called CreateThread(). Do not call this method if CreateThread() was
-  // called with a |stoppable| value of false.
+  /// Stop and join the thread. This method must be called from the same thread
+  /// that called CreateThread(). Do not call this method if CreateThread() was
+  /// called with a |stoppable| value of false.
   ///
   /*--cef()--*/
   virtual void Stop() = 0;
 
   ///
-  // Returns true if the thread is currently running. This method must be called
-  // from the same thread that called CreateThread().
+  /// Returns true if the thread is currently running. This method must be
+  /// called from the same thread that called CreateThread().
   ///
   /*--cef()--*/
   virtual bool IsRunning() = 0;
diff --git a/src/include/cef_trace.h b/src/include/cef_trace.h
index bc92d38..2fa71ee 100644
--- a/src/include/cef_trace.h
+++ b/src/include/cef_trace.h
@@ -45,66 +45,67 @@
 #include "include/cef_callback.h"
 
 ///
-// Implement this interface to receive notification when tracing has completed.
-// The methods of this class will be called on the browser process UI thread.
+/// Implement this interface to receive notification when tracing has completed.
+/// The methods of this class will be called on the browser process UI thread.
 ///
 /*--cef(source=client)--*/
 class CefEndTracingCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Called after all processes have sent their trace data. |tracing_file| is
-  // the path at which tracing data was written. The client is responsible for
-  // deleting |tracing_file|.
+  /// Called after all processes have sent their trace data. |tracing_file| is
+  /// the path at which tracing data was written. The client is responsible for
+  /// deleting |tracing_file|.
   ///
   /*--cef()--*/
   virtual void OnEndTracingComplete(const CefString& tracing_file) = 0;
 };
 
 ///
-// Start tracing events on all processes. Tracing is initialized asynchronously
-// and |callback| will be executed on the UI thread after initialization is
-// complete.
-//
-// If CefBeginTracing was called previously, or if a CefEndTracingAsync call is
-// pending, CefBeginTracing will fail and return false.
-//
-// |categories| is a comma-delimited list of category wildcards. A category can
-// have an optional '-' prefix to make it an excluded category. Having both
-// included and excluded categories in the same list is not supported.
-//
-// Example: "test_MyTest*"
-// Example: "test_MyTest*,test_OtherStuff"
-// Example: "-excluded_category1,-excluded_category2"
-//
-// This function must be called on the browser process UI thread.
+/// Start tracing events on all processes. Tracing is initialized asynchronously
+/// and |callback| will be executed on the UI thread after initialization is
+/// complete.
+///
+/// If CefBeginTracing was called previously, or if a CefEndTracingAsync call is
+/// pending, CefBeginTracing will fail and return false.
+///
+/// |categories| is a comma-delimited list of category wildcards. A category can
+/// have an optional '-' prefix to make it an excluded category. Having both
+/// included and excluded categories in the same list is not supported.
+///
+/// Examples:
+/// - "test_MyTest*"
+/// - "test_MyTest*,test_OtherStuff"
+/// - "-excluded_category1,-excluded_category2"
+///
+/// This function must be called on the browser process UI thread.
 ///
 /*--cef(optional_param=categories,optional_param=callback)--*/
 bool CefBeginTracing(const CefString& categories,
                      CefRefPtr<CefCompletionCallback> callback);
 
 ///
-// Stop tracing events on all processes.
-//
-// This function will fail and return false if a previous call to
-// CefEndTracingAsync is already pending or if CefBeginTracing was not called.
-//
-// |tracing_file| is the path at which tracing data will be written and
-// |callback| is the callback that will be executed once all processes have
-// sent their trace data. If |tracing_file| is empty a new temporary file path
-// will be used. If |callback| is empty no trace data will be written.
-//
-// This function must be called on the browser process UI thread.
+/// Stop tracing events on all processes.
+///
+/// This function will fail and return false if a previous call to
+/// CefEndTracingAsync is already pending or if CefBeginTracing was not called.
+///
+/// |tracing_file| is the path at which tracing data will be written and
+/// |callback| is the callback that will be executed once all processes have
+/// sent their trace data. If |tracing_file| is empty a new temporary file path
+/// will be used. If |callback| is empty no trace data will be written.
+///
+/// This function must be called on the browser process UI thread.
 ///
 /*--cef(optional_param=tracing_file,optional_param=callback)--*/
 bool CefEndTracing(const CefString& tracing_file,
                    CefRefPtr<CefEndTracingCallback> callback);
 
 ///
-// Returns the current system trace time or, if none is defined, the current
-// high-res time. Can be used by clients to synchronize with the time
-// information in trace events.
+/// Returns the current system trace time or, if none is defined, the current
+/// high-res time. Can be used by clients to synchronize with the time
+/// information in trace events.
 ///
 /*--cef()--*/
-int64 CefNowFromSystemTraceTime();
+int64_t CefNowFromSystemTraceTime();
 
 #endif  // CEF_INCLUDE_CEF_TRACE_H_
diff --git a/src/include/cef_urlrequest.h b/src/include/cef_urlrequest.h
index 8966eb8..77a82a6 100644
--- a/src/include/cef_urlrequest.h
+++ b/src/include/cef_urlrequest.h
@@ -47,11 +47,11 @@
 class CefURLRequestClient;
 
 ///
-// Class used to make a URL request. URL requests are not associated with a
-// browser instance so no CefClient callbacks will be executed. URL requests
-// can be created on any valid CEF thread in either the browser or render
-// process. Once created the methods of the URL request object must be accessed
-// on the same thread that created it.
+/// Class used to make a URL request. URL requests are not associated with a
+/// browser instance so no CefClient callbacks will be executed. URL requests
+/// can be created on any valid CEF thread in either the browser or render
+/// process. Once created the methods of the URL request object must be accessed
+/// on the same thread that created it.
 ///
 /*--cef(source=library)--*/
 class CefURLRequest : public virtual CefBaseRefCounted {
@@ -60,25 +60,19 @@
   typedef cef_errorcode_t ErrorCode;
 
   ///
-  // Create a new URL request that is not associated with a specific browser or
-  // frame. Use CefFrame::CreateURLRequest instead if you want the request to
-  // have this association, in which case it may be handled differently (see
-  // documentation on that method). Requests may originate from the both browser
-  // process and the render process.
-  //
-  // For requests originating from the browser process:
-  //   - It may be intercepted by the client via CefResourceRequestHandler or
-  //     CefSchemeHandlerFactory.
-  //   - POST data may only contain only a single element of type PDE_TYPE_FILE
-  //     or PDE_TYPE_BYTES.
-  //   - If |request_context| is empty the global request context will be used.
-  // For requests originating from the render process:
-  //   - It cannot be intercepted by the client so only http(s) and blob schemes
-  //     are supported.
-  //   - POST data may only contain a single element of type PDE_TYPE_BYTES.
-  //   - The |request_context| parameter must be NULL.
-  //
-  // The |request| object will be marked as read-only after calling this method.
+  /// Create a new URL request that is not associated with a specific browser or
+  /// frame. Use CefFrame::CreateURLRequest instead if you want the request to
+  /// have this association, in which case it may be handled differently (see
+  /// documentation on that method). A request created with this method may only
+  /// originate from the browser process, and will behave as follows:
+  ///   - It may be intercepted by the client via CefResourceRequestHandler or
+  ///     CefSchemeHandlerFactory.
+  ///   - POST data may only contain only a single element of type PDE_TYPE_FILE
+  ///     or PDE_TYPE_BYTES.
+  ///   - If |request_context| is empty the global request context will be used.
+  ///
+  /// The |request| object will be marked as read-only after calling this
+  /// method.
   ///
   /*--cef(optional_param=request_context)--*/
   static CefRefPtr<CefURLRequest> Create(
@@ -87,94 +81,94 @@
       CefRefPtr<CefRequestContext> request_context);
 
   ///
-  // Returns the request object used to create this URL request. The returned
-  // object is read-only and should not be modified.
+  /// Returns the request object used to create this URL request. The returned
+  /// object is read-only and should not be modified.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefRequest> GetRequest() = 0;
 
   ///
-  // Returns the client.
+  /// Returns the client.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefURLRequestClient> GetClient() = 0;
 
   ///
-  // Returns the request status.
+  /// Returns the request status.
   ///
   /*--cef(default_retval=UR_UNKNOWN)--*/
   virtual Status GetRequestStatus() = 0;
 
   ///
-  // Returns the request error if status is UR_CANCELED or UR_FAILED, or 0
-  // otherwise.
+  /// Returns the request error if status is UR_CANCELED or UR_FAILED, or 0
+  /// otherwise.
   ///
   /*--cef(default_retval=ERR_NONE)--*/
   virtual ErrorCode GetRequestError() = 0;
 
   ///
-  // Returns the response, or NULL if no response information is available.
-  // Response information will only be available after the upload has completed.
-  // The returned object is read-only and should not be modified.
+  /// Returns the response, or NULL if no response information is available.
+  /// Response information will only be available after the upload has
+  /// completed. The returned object is read-only and should not be modified.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefResponse> GetResponse() = 0;
 
   ///
-  // Returns true if the response body was served from the cache. This includes
-  // responses for which revalidation was required.
+  /// Returns true if the response body was served from the cache. This includes
+  /// responses for which revalidation was required.
   ///
   /*--cef()--*/
   virtual bool ResponseWasCached() = 0;
 
   ///
-  // Cancel the request.
+  /// Cancel the request.
   ///
   /*--cef()--*/
   virtual void Cancel() = 0;
 };
 
 ///
-// Interface that should be implemented by the CefURLRequest client. The
-// methods of this class will be called on the same thread that created the
-// request unless otherwise documented.
+/// Interface that should be implemented by the CefURLRequest client. The
+/// methods of this class will be called on the same thread that created the
+/// request unless otherwise documented.
 ///
 /*--cef(source=client)--*/
 class CefURLRequestClient : public virtual CefBaseRefCounted {
  public:
   ///
-  // Notifies the client that the request has completed. Use the
-  // CefURLRequest::GetRequestStatus method to determine if the request was
-  // successful or not.
+  /// Notifies the client that the request has completed. Use the
+  /// CefURLRequest::GetRequestStatus method to determine if the request was
+  /// successful or not.
   ///
   /*--cef()--*/
   virtual void OnRequestComplete(CefRefPtr<CefURLRequest> request) = 0;
 
   ///
-  // Notifies the client of upload progress. |current| denotes the number of
-  // bytes sent so far and |total| is the total size of uploading data (or -1 if
-  // chunked upload is enabled). This method will only be called if the
-  // UR_FLAG_REPORT_UPLOAD_PROGRESS flag is set on the request.
+  /// Notifies the client of upload progress. |current| denotes the number of
+  /// bytes sent so far and |total| is the total size of uploading data (or -1
+  /// if chunked upload is enabled). This method will only be called if the
+  /// UR_FLAG_REPORT_UPLOAD_PROGRESS flag is set on the request.
   ///
   /*--cef()--*/
   virtual void OnUploadProgress(CefRefPtr<CefURLRequest> request,
-                                int64 current,
-                                int64 total) = 0;
+                                int64_t current,
+                                int64_t total) = 0;
 
   ///
-  // Notifies the client of download progress. |current| denotes the number of
-  // bytes received up to the call and |total| is the expected total size of the
-  // response (or -1 if not determined).
+  /// Notifies the client of download progress. |current| denotes the number of
+  /// bytes received up to the call and |total| is the expected total size of
+  /// the response (or -1 if not determined).
   ///
   /*--cef()--*/
   virtual void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
-                                  int64 current,
-                                  int64 total) = 0;
+                                  int64_t current,
+                                  int64_t total) = 0;
 
   ///
-  // Called when some part of the response is read. |data| contains the current
-  // bytes received since the last call. This method will not be called if the
-  // UR_FLAG_NO_DOWNLOAD_DATA flag is set on the request.
+  /// Called when some part of the response is read. |data| contains the current
+  /// bytes received since the last call. This method will not be called if the
+  /// UR_FLAG_NO_DOWNLOAD_DATA flag is set on the request.
   ///
   /*--cef()--*/
   virtual void OnDownloadData(CefRefPtr<CefURLRequest> request,
@@ -182,15 +176,15 @@
                               size_t data_length) = 0;
 
   ///
-  // Called on the IO thread when the browser needs credentials from the user.
-  // |isProxy| indicates whether the host is a proxy server. |host| contains the
-  // hostname and |port| contains the port number. Return true to continue the
-  // request and call CefAuthCallback::Continue() when the authentication
-  // information is available. If the request has an associated browser/frame
-  // then returning false will result in a call to GetAuthCredentials on the
-  // CefRequestHandler associated with that browser, if any. Otherwise,
-  // returning false will cancel the request immediately. This method will only
-  // be called for requests initiated from the browser process.
+  /// Called on the IO thread when the browser needs credentials from the user.
+  /// |isProxy| indicates whether the host is a proxy server. |host| contains
+  /// the hostname and |port| contains the port number. Return true to continue
+  /// the request and call CefAuthCallback::Continue() when the authentication
+  /// information is available. If the request has an associated browser/frame
+  /// then returning false will result in a call to GetAuthCredentials on the
+  /// CefRequestHandler associated with that browser, if any. Otherwise,
+  /// returning false will cancel the request immediately. This method will only
+  /// be called for requests initiated from the browser process.
   ///
   /*--cef(optional_param=realm)--*/
   virtual bool GetAuthCredentials(bool isProxy,
diff --git a/src/include/cef_v8.h b/src/include/cef_v8.h
index 8bbc028..f6a01c1 100644
--- a/src/include/cef_v8.h
+++ b/src/include/cef_v8.h
@@ -50,63 +50,64 @@
 class CefV8Value;
 
 ///
-// Register a new V8 extension with the specified JavaScript extension code and
-// handler. Functions implemented by the handler are prototyped using the
-// keyword 'native'. The calling of a native function is restricted to the scope
-// in which the prototype of the native function is defined. This function may
-// only be called on the render process main thread.
-//
-// Example JavaScript extension code:
-// <pre>
-//   // create the 'example' global object if it doesn't already exist.
-//   if (!example)
-//     example = {};
-//   // create the 'example.test' global object if it doesn't already exist.
-//   if (!example.test)
-//     example.test = {};
-//   (function() {
-//     // Define the function 'example.test.myfunction'.
-//     example.test.myfunction = function() {
-//       // Call CefV8Handler::Execute() with the function name 'MyFunction'
-//       // and no arguments.
-//       native function MyFunction();
-//       return MyFunction();
-//     };
-//     // Define the getter function for parameter 'example.test.myparam'.
-//     example.test.__defineGetter__('myparam', function() {
-//       // Call CefV8Handler::Execute() with the function name 'GetMyParam'
-//       // and no arguments.
-//       native function GetMyParam();
-//       return GetMyParam();
-//     });
-//     // Define the setter function for parameter 'example.test.myparam'.
-//     example.test.__defineSetter__('myparam', function(b) {
-//       // Call CefV8Handler::Execute() with the function name 'SetMyParam'
-//       // and a single argument.
-//       native function SetMyParam();
-//       if(b) SetMyParam(b);
-//     });
-//
-//     // Extension definitions can also contain normal JavaScript variables
-//     // and functions.
-//     var myint = 0;
-//     example.test.increment = function() {
-//       myint += 1;
-//       return myint;
-//     };
-//   })();
-// </pre>
-// Example usage in the page:
-// <pre>
-//   // Call the function.
-//   example.test.myfunction();
-//   // Set the parameter.
-//   example.test.myparam = value;
-//   // Get the parameter.
-//   value = example.test.myparam;
-//   // Call another function.
-//   example.test.increment();
-// </pre>
+/// Register a new V8 extension with the specified JavaScript extension code and
+/// handler. Functions implemented by the handler are prototyped using the
+/// keyword 'native'. The calling of a native function is restricted to the
+/// scope in which the prototype of the native function is defined. This
+/// function may only be called on the render process main thread.
+///
+/// Example JavaScript extension code:
+/// <pre>
+///   // create the 'example' global object if it doesn't already exist.
+///   if (!example)
+///     example = {};
+///   // create the 'example.test' global object if it doesn't already exist.
+///   if (!example.test)
+///     example.test = {};
+///   (function() {
+///     // Define the function 'example.test.myfunction'.
+///     example.test.myfunction = function() {
+///       // Call CefV8Handler::Execute() with the function name 'MyFunction'
+///       // and no arguments.
+///       native function MyFunction();
+///       return MyFunction();
+///     };
+///     // Define the getter function for parameter 'example.test.myparam'.
+///     example.test.__defineGetter__('myparam', function() {
+///       // Call CefV8Handler::Execute() with the function name 'GetMyParam'
+///       // and no arguments.
+///       native function GetMyParam();
+///       return GetMyParam();
+///     });
+///     // Define the setter function for parameter 'example.test.myparam'.
+///     example.test.__defineSetter__('myparam', function(b) {
+///       // Call CefV8Handler::Execute() with the function name 'SetMyParam'
+///       // and a single argument.
+///       native function SetMyParam();
+///       if(b) SetMyParam(b);
+///     });
+///
+///     // Extension definitions can also contain normal JavaScript variables
+///     // and functions.
+///     var myint = 0;
+///     example.test.increment = function() {
+///       myint += 1;
+///       return myint;
+///     };
+///   })();
+/// </pre>
+///
+/// Example usage in the page:
+/// <pre>
+///   // Call the function.
+///   example.test.myfunction();
+///   // Set the parameter.
+///   example.test.myparam = value;
+///   // Get the parameter.
+///   value = example.test.myparam;
+///   // Call another function.
+///   example.test.increment();
+/// </pre>
 ///
 /*--cef(optional_param=handler)--*/
 bool CefRegisterExtension(const CefString& extension_name,
@@ -114,101 +115,101 @@
                           CefRefPtr<CefV8Handler> handler);
 
 ///
-// Class representing a V8 context handle. V8 handles can only be accessed from
-// the thread on which they are created. Valid threads for creating a V8 handle
-// include the render process main thread (TID_RENDERER) and WebWorker threads.
-// A task runner for posting tasks on the associated thread can be retrieved via
-// the CefV8Context::GetTaskRunner() method.
+/// Class representing a V8 context handle. V8 handles can only be accessed from
+/// the thread on which they are created. Valid threads for creating a V8 handle
+/// include the render process main thread (TID_RENDERER) and WebWorker threads.
+/// A task runner for posting tasks on the associated thread can be retrieved
+/// via the CefV8Context::GetTaskRunner() method.
 ///
 /*--cef(source=library,no_debugct_check)--*/
 class CefV8Context : public virtual CefBaseRefCounted {
  public:
   ///
-  // Returns the current (top) context object in the V8 context stack.
+  /// Returns the current (top) context object in the V8 context stack.
   ///
   /*--cef()--*/
   static CefRefPtr<CefV8Context> GetCurrentContext();
 
   ///
-  // Returns the entered (bottom) context object in the V8 context stack.
+  /// Returns the entered (bottom) context object in the V8 context stack.
   ///
   /*--cef()--*/
   static CefRefPtr<CefV8Context> GetEnteredContext();
 
   ///
-  // Returns true if V8 is currently inside a context.
+  /// Returns true if V8 is currently inside a context.
   ///
   /*--cef()--*/
   static bool InContext();
 
   ///
-  // Returns the task runner associated with this context. V8 handles can only
-  // be accessed from the thread on which they are created. This method can be
-  // called on any render process thread.
+  /// Returns the task runner associated with this context. V8 handles can only
+  /// be accessed from the thread on which they are created. This method can be
+  /// called on any render process thread.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefTaskRunner> GetTaskRunner() = 0;
 
   ///
-  // Returns true if the underlying handle is valid and it can be accessed on
-  // the current thread. Do not call any other methods if this method returns
-  // false.
+  /// Returns true if the underlying handle is valid and it can be accessed on
+  /// the current thread. Do not call any other methods if this method returns
+  /// false.
   ///
   /*--cef()--*/
   virtual bool IsValid() = 0;
 
   ///
-  // Returns the browser for this context. This method will return an empty
-  // reference for WebWorker contexts.
+  /// Returns the browser for this context. This method will return an empty
+  /// reference for WebWorker contexts.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBrowser> GetBrowser() = 0;
 
   ///
-  // Returns the frame for this context. This method will return an empty
-  // reference for WebWorker contexts.
+  /// Returns the frame for this context. This method will return an empty
+  /// reference for WebWorker contexts.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefFrame> GetFrame() = 0;
 
   ///
-  // Returns the global object for this context. The context must be entered
-  // before calling this method.
+  /// Returns the global object for this context. The context must be entered
+  /// before calling this method.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefV8Value> GetGlobal() = 0;
 
   ///
-  // Enter this context. A context must be explicitly entered before creating a
-  // V8 Object, Array, Function or Date asynchronously. Exit() must be called
-  // the same number of times as Enter() before releasing this context. V8
-  // objects belong to the context in which they are created. Returns true if
-  // the scope was entered successfully.
+  /// Enter this context. A context must be explicitly entered before creating a
+  /// V8 Object, Array, Function or Date asynchronously. Exit() must be called
+  /// the same number of times as Enter() before releasing this context. V8
+  /// objects belong to the context in which they are created. Returns true if
+  /// the scope was entered successfully.
   ///
   /*--cef()--*/
   virtual bool Enter() = 0;
 
   ///
-  // Exit this context. Call this method only after calling Enter(). Returns
-  // true if the scope was exited successfully.
+  /// Exit this context. Call this method only after calling Enter(). Returns
+  /// true if the scope was exited successfully.
   ///
   /*--cef()--*/
   virtual bool Exit() = 0;
 
   ///
-  // Returns true if this object is pointing to the same handle as |that|
-  // object.
+  /// Returns true if this object is pointing to the same handle as |that|
+  /// object.
   ///
   /*--cef()--*/
   virtual bool IsSame(CefRefPtr<CefV8Context> that) = 0;
 
   ///
-  // Execute a string of JavaScript code in this V8 context. The |script_url|
-  // parameter is the URL where the script in question can be found, if any.
-  // The |start_line| parameter is the base line number to use for error
-  // reporting. On success |retval| will be set to the return value, if any, and
-  // the function will return true. On failure |exception| will be set to the
-  // exception, if any, and the function will return false.
+  /// Execute a string of JavaScript code in this V8 context. The |script_url|
+  /// parameter is the URL where the script in question can be found, if any.
+  /// The |start_line| parameter is the base line number to use for error
+  /// reporting. On success |retval| will be set to the return value, if any,
+  /// and the function will return true. On failure |exception| will be set to
+  /// the exception, if any, and the function will return false.
   ///
   /*--cef(optional_param=script_url)--*/
   virtual bool Eval(const CefString& code,
@@ -221,18 +222,19 @@
 typedef std::vector<CefRefPtr<CefV8Value>> CefV8ValueList;
 
 ///
-// Interface that should be implemented to handle V8 function calls. The methods
-// of this class will be called on the thread associated with the V8 function.
+/// Interface that should be implemented to handle V8 function calls. The
+/// methods of this class will be called on the thread associated with the V8
+/// function.
 ///
 /*--cef(source=client,no_debugct_check)--*/
 class CefV8Handler : public virtual CefBaseRefCounted {
  public:
   ///
-  // Handle execution of the function identified by |name|. |object| is the
-  // receiver ('this' object) of the function. |arguments| is the list of
-  // arguments passed to the function. If execution succeeds set |retval| to the
-  // function return value. If execution fails set |exception| to the exception
-  // that will be thrown. Return true if execution was handled.
+  /// Handle execution of the function identified by |name|. |object| is the
+  /// receiver ('this' object) of the function. |arguments| is the list of
+  /// arguments passed to the function. If execution succeeds set |retval| to
+  /// the function return value. If execution fails set |exception| to the
+  /// exception that will be thrown. Return true if execution was handled.
   ///
   /*--cef()--*/
   virtual bool Execute(const CefString& name,
@@ -243,19 +245,19 @@
 };
 
 ///
-// Interface that should be implemented to handle V8 accessor calls. Accessor
-// identifiers are registered by calling CefV8Value::SetValue(). The methods
-// of this class will be called on the thread associated with the V8 accessor.
+/// Interface that should be implemented to handle V8 accessor calls. Accessor
+/// identifiers are registered by calling CefV8Value::SetValue(). The methods
+/// of this class will be called on the thread associated with the V8 accessor.
 ///
 /*--cef(source=client,no_debugct_check)--*/
 class CefV8Accessor : public virtual CefBaseRefCounted {
  public:
   ///
-  // Handle retrieval the accessor value identified by |name|. |object| is the
-  // receiver ('this' object) of the accessor. If retrieval succeeds set
-  // |retval| to the return value. If retrieval fails set |exception| to the
-  // exception that will be thrown. Return true if accessor retrieval was
-  // handled.
+  /// Handle retrieval the accessor value identified by |name|. |object| is the
+  /// receiver ('this' object) of the accessor. If retrieval succeeds set
+  /// |retval| to the return value. If retrieval fails set |exception| to the
+  /// exception that will be thrown. Return true if accessor retrieval was
+  /// handled.
   ///
   /*--cef()--*/
   virtual bool Get(const CefString& name,
@@ -264,11 +266,11 @@
                    CefString& exception) = 0;
 
   ///
-  // Handle assignment of the accessor value identified by |name|. |object| is
-  // the receiver ('this' object) of the accessor. |value| is the new value
-  // being assigned to the accessor. If assignment fails set |exception| to the
-  // exception that will be thrown. Return true if accessor assignment was
-  // handled.
+  /// Handle assignment of the accessor value identified by |name|. |object| is
+  /// the receiver ('this' object) of the accessor. |value| is the new value
+  /// being assigned to the accessor. If assignment fails set |exception| to the
+  /// exception that will be thrown. Return true if accessor assignment was
+  /// handled.
   ///
   /*--cef()--*/
   virtual bool Set(const CefString& name,
@@ -278,24 +280,24 @@
 };
 
 ///
-// Interface that should be implemented to handle V8 interceptor calls. The
-// methods of this class will be called on the thread associated with the V8
-// interceptor. Interceptor's named property handlers (with first argument of
-// type CefString) are called when object is indexed by string. Indexed property
-// handlers (with first argument of type int) are called when object is indexed
-// by integer.
+/// Interface that should be implemented to handle V8 interceptor calls. The
+/// methods of this class will be called on the thread associated with the V8
+/// interceptor. Interceptor's named property handlers (with first argument of
+/// type CefString) are called when object is indexed by string. Indexed
+/// property handlers (with first argument of type int) are called when object
+/// is indexed by integer.
 ///
 /*--cef(source=client,no_debugct_check)--*/
 class CefV8Interceptor : public virtual CefBaseRefCounted {
  public:
   ///
-  // Handle retrieval of the interceptor value identified by |name|. |object| is
-  // the receiver ('this' object) of the interceptor. If retrieval succeeds, set
-  // |retval| to the return value. If the requested value does not exist, don't
-  // set either |retval| or |exception|. If retrieval fails, set |exception| to
-  // the exception that will be thrown. If the property has an associated
-  // accessor, it will be called only if you don't set |retval|.
-  // Return true if interceptor retrieval was handled, false otherwise.
+  /// Handle retrieval of the interceptor value identified by |name|. |object|
+  /// is the receiver ('this' object) of the interceptor. If retrieval succeeds,
+  /// set |retval| to the return value. If the requested value does not exist,
+  /// don't set either |retval| or |exception|. If retrieval fails, set
+  /// |exception| to the exception that will be thrown. If the property has an
+  /// associated accessor, it will be called only if you don't set |retval|.
+  /// Return true if interceptor retrieval was handled, false otherwise.
   ///
   /*--cef(capi_name=get_byname)--*/
   virtual bool Get(const CefString& name,
@@ -304,12 +306,12 @@
                    CefString& exception) = 0;
 
   ///
-  // Handle retrieval of the interceptor value identified by |index|. |object|
-  // is the receiver ('this' object) of the interceptor. If retrieval succeeds,
-  // set |retval| to the return value. If the requested value does not exist,
-  // don't set either |retval| or |exception|. If retrieval fails, set
-  // |exception| to the exception that will be thrown.
-  // Return true if interceptor retrieval was handled, false otherwise.
+  /// Handle retrieval of the interceptor value identified by |index|. |object|
+  /// is the receiver ('this' object) of the interceptor. If retrieval succeeds,
+  /// set |retval| to the return value. If the requested value does not exist,
+  /// don't set either |retval| or |exception|. If retrieval fails, set
+  /// |exception| to the exception that will be thrown.
+  /// Return true if interceptor retrieval was handled, false otherwise.
   ///
   /*--cef(capi_name=get_byindex,index_param=index)--*/
   virtual bool Get(int index,
@@ -318,12 +320,12 @@
                    CefString& exception) = 0;
 
   ///
-  // Handle assignment of the interceptor value identified by |name|. |object|
-  // is the receiver ('this' object) of the interceptor. |value| is the new
-  // value being assigned to the interceptor. If assignment fails, set
-  // |exception| to the exception that will be thrown. This setter will always
-  // be called, even when the property has an associated accessor.
-  // Return true if interceptor assignment was handled, false otherwise.
+  /// Handle assignment of the interceptor value identified by |name|. |object|
+  /// is the receiver ('this' object) of the interceptor. |value| is the new
+  /// value being assigned to the interceptor. If assignment fails, set
+  /// |exception| to the exception that will be thrown. This setter will always
+  /// be called, even when the property has an associated accessor.
+  /// Return true if interceptor assignment was handled, false otherwise.
   ///
   /*--cef(capi_name=set_byname)--*/
   virtual bool Set(const CefString& name,
@@ -332,11 +334,11 @@
                    CefString& exception) = 0;
 
   ///
-  // Handle assignment of the interceptor value identified by |index|. |object|
-  // is the receiver ('this' object) of the interceptor. |value| is the new
-  // value being assigned to the interceptor. If assignment fails, set
-  // |exception| to the exception that will be thrown.
-  // Return true if interceptor assignment was handled, false otherwise.
+  /// Handle assignment of the interceptor value identified by |index|. |object|
+  /// is the receiver ('this' object) of the interceptor. |value| is the new
+  /// value being assigned to the interceptor. If assignment fails, set
+  /// |exception| to the exception that will be thrown.
+  /// Return true if interceptor assignment was handled, false otherwise.
   ///
   /*--cef(capi_name=set_byindex,index_param=index)--*/
   virtual bool Set(int index,
@@ -346,88 +348,88 @@
 };
 
 ///
-// Class representing a V8 exception. The methods of this class may be called on
-// any render process thread.
+/// Class representing a V8 exception. The methods of this class may be called
+/// on any render process thread.
 ///
 /*--cef(source=library,no_debugct_check)--*/
 class CefV8Exception : public virtual CefBaseRefCounted {
  public:
   ///
-  // Returns the exception message.
+  /// Returns the exception message.
   ///
   /*--cef()--*/
   virtual CefString GetMessage() = 0;
 
   ///
-  // Returns the line of source code that the exception occurred within.
+  /// Returns the line of source code that the exception occurred within.
   ///
   /*--cef()--*/
   virtual CefString GetSourceLine() = 0;
 
   ///
-  // Returns the resource name for the script from where the function causing
-  // the error originates.
+  /// Returns the resource name for the script from where the function causing
+  /// the error originates.
   ///
   /*--cef()--*/
   virtual CefString GetScriptResourceName() = 0;
 
   ///
-  // Returns the 1-based number of the line where the error occurred or 0 if the
-  // line number is unknown.
+  /// Returns the 1-based number of the line where the error occurred or 0 if
+  /// the line number is unknown.
   ///
   /*--cef()--*/
   virtual int GetLineNumber() = 0;
 
   ///
-  // Returns the index within the script of the first character where the error
-  // occurred.
+  /// Returns the index within the script of the first character where the error
+  /// occurred.
   ///
   /*--cef()--*/
   virtual int GetStartPosition() = 0;
 
   ///
-  // Returns the index within the script of the last character where the error
-  // occurred.
+  /// Returns the index within the script of the last character where the error
+  /// occurred.
   ///
   /*--cef()--*/
   virtual int GetEndPosition() = 0;
 
   ///
-  // Returns the index within the line of the first character where the error
-  // occurred.
+  /// Returns the index within the line of the first character where the error
+  /// occurred.
   ///
   /*--cef()--*/
   virtual int GetStartColumn() = 0;
 
   ///
-  // Returns the index within the line of the last character where the error
-  // occurred.
+  /// Returns the index within the line of the last character where the error
+  /// occurred.
   ///
   /*--cef()--*/
   virtual int GetEndColumn() = 0;
 };
 
 ///
-// Callback interface that is passed to CefV8Value::CreateArrayBuffer.
+/// Callback interface that is passed to CefV8Value::CreateArrayBuffer.
 ///
 /*--cef(source=client,no_debugct_check)--*/
 class CefV8ArrayBufferReleaseCallback : public virtual CefBaseRefCounted {
  public:
   ///
-  // Called to release |buffer| when the ArrayBuffer JS object is garbage
-  // collected. |buffer| is the value that was passed to CreateArrayBuffer along
-  // with this object.
+  /// Called to release |buffer| when the ArrayBuffer JS object is garbage
+  /// collected. |buffer| is the value that was passed to CreateArrayBuffer
+  /// along with this object.
   ///
   /*--cef()--*/
   virtual void ReleaseBuffer(void* buffer) = 0;
 };
 
 ///
-// Class representing a V8 value handle. V8 handles can only be accessed from
-// the thread on which they are created. Valid threads for creating a V8 handle
-// include the render process main thread (TID_RENDERER) and WebWorker threads.
-// A task runner for posting tasks on the associated thread can be retrieved via
-// the CefV8Context::GetTaskRunner() method.
+/// Class representing a V8 value handle. V8 handles can only be accessed from
+/// the thread on which they are created. Valid threads for creating a V8 handle
+/// include the render process main thread (TID_RENDERER) and WebWorker threads.
+/// A task runner for posting tasks on the associated thread can be retrieved
+/// via the CefV8Context::GetTaskRunner() method.
 ///
 /*--cef(source=library,no_debugct_check)--*/
 class CefV8Value : public virtual CefBaseRefCounted {
@@ -436,62 +438,62 @@
   typedef cef_v8_propertyattribute_t PropertyAttribute;
 
   ///
-  // Create a new CefV8Value object of type undefined.
+  /// Create a new CefV8Value object of type undefined.
   ///
   /*--cef()--*/
   static CefRefPtr<CefV8Value> CreateUndefined();
 
   ///
-  // Create a new CefV8Value object of type null.
+  /// Create a new CefV8Value object of type null.
   ///
   /*--cef()--*/
   static CefRefPtr<CefV8Value> CreateNull();
 
   ///
-  // Create a new CefV8Value object of type bool.
+  /// Create a new CefV8Value object of type bool.
   ///
   /*--cef()--*/
   static CefRefPtr<CefV8Value> CreateBool(bool value);
 
   ///
-  // Create a new CefV8Value object of type int.
+  /// Create a new CefV8Value object of type int.
   ///
   /*--cef()--*/
-  static CefRefPtr<CefV8Value> CreateInt(int32 value);
+  static CefRefPtr<CefV8Value> CreateInt(int32_t value);
 
   ///
-  // Create a new CefV8Value object of type unsigned int.
+  /// Create a new CefV8Value object of type unsigned int.
   ///
   /*--cef()--*/
-  static CefRefPtr<CefV8Value> CreateUInt(uint32 value);
+  static CefRefPtr<CefV8Value> CreateUInt(uint32_t value);
 
   ///
-  // Create a new CefV8Value object of type double.
+  /// Create a new CefV8Value object of type double.
   ///
   /*--cef()--*/
   static CefRefPtr<CefV8Value> CreateDouble(double value);
 
   ///
-  // Create a new CefV8Value object of type Date. This method should only be
-  // called from within the scope of a CefRenderProcessHandler, CefV8Handler or
-  // CefV8Accessor callback, or in combination with calling Enter() and Exit()
-  // on a stored CefV8Context reference.
+  /// Create a new CefV8Value object of type Date. This method should only be
+  /// called from within the scope of a CefRenderProcessHandler, CefV8Handler or
+  /// CefV8Accessor callback, or in combination with calling Enter() and Exit()
+  /// on a stored CefV8Context reference.
   ///
   /*--cef()--*/
-  static CefRefPtr<CefV8Value> CreateDate(const CefTime& date);
+  static CefRefPtr<CefV8Value> CreateDate(CefBaseTime date);
 
   ///
-  // Create a new CefV8Value object of type string.
+  /// Create a new CefV8Value object of type string.
   ///
   /*--cef(optional_param=value)--*/
   static CefRefPtr<CefV8Value> CreateString(const CefString& value);
 
   ///
-  // Create a new CefV8Value object of type object with optional accessor and/or
-  // interceptor. This method should only be called from within the scope of a
-  // CefRenderProcessHandler, CefV8Handler or CefV8Accessor callback, or in
-  // combination with calling Enter() and Exit() on a stored CefV8Context
-  // reference.
+  /// Create a new CefV8Value object of type object with optional accessor
+  /// and/or interceptor. This method should only be called from within the
+  /// scope of a CefRenderProcessHandler, CefV8Handler or CefV8Accessor
+  /// callback, or in combination with calling Enter() and Exit() on a stored
+  /// CefV8Context reference.
   ///
   /*--cef(optional_param=accessor, optional_param=interceptor)--*/
   static CefRefPtr<CefV8Value> CreateObject(
@@ -499,260 +501,275 @@
       CefRefPtr<CefV8Interceptor> interceptor);
 
   ///
-  // Create a new CefV8Value object of type array with the specified |length|.
-  // If |length| is negative the returned array will have length 0. This method
-  // should only be called from within the scope of a CefRenderProcessHandler,
-  // CefV8Handler or CefV8Accessor callback, or in combination with calling
-  // Enter() and Exit() on a stored CefV8Context reference.
+  /// Create a new CefV8Value object of type array with the specified |length|.
+  /// If |length| is negative the returned array will have length 0. This method
+  /// should only be called from within the scope of a CefRenderProcessHandler,
+  /// CefV8Handler or CefV8Accessor callback, or in combination with calling
+  /// Enter() and Exit() on a stored CefV8Context reference.
   ///
   /*--cef()--*/
   static CefRefPtr<CefV8Value> CreateArray(int length);
 
   ///
-  // Create a new CefV8Value object of type ArrayBuffer which wraps the provided
-  // |buffer| of size |length| bytes. The ArrayBuffer is externalized, meaning
-  // that it does not own |buffer|. The caller is responsible for freeing
-  // |buffer| when requested via a call to CefV8ArrayBufferReleaseCallback::
-  // ReleaseBuffer. This method should only be called from within the scope of a
-  // CefRenderProcessHandler, CefV8Handler or CefV8Accessor callback, or in
-  // combination with calling Enter() and Exit() on a stored CefV8Context
-  // reference.
+  /// Create a new CefV8Value object of type ArrayBuffer which wraps the
+  /// provided |buffer| of size |length| bytes. The ArrayBuffer is externalized,
+  /// meaning that it does not own |buffer|. The caller is responsible for
+  /// freeing |buffer| when requested via a call to
+  /// CefV8ArrayBufferReleaseCallback::ReleaseBuffer. This method should only
+  /// be called from within the scope of a CefRenderProcessHandler, CefV8Handler
+  /// or CefV8Accessor callback, or in combination with calling Enter() and
+  /// Exit() on a stored CefV8Context reference.
   ///
-  /*--cef()--*/
+  /*--cef(optional_param=buffer)--*/
   static CefRefPtr<CefV8Value> CreateArrayBuffer(
       void* buffer,
       size_t length,
       CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback);
 
   ///
-  // Create a new CefV8Value object of type function. This method should only be
-  // called from within the scope of a CefRenderProcessHandler, CefV8Handler or
-  // CefV8Accessor callback, or in combination with calling Enter() and Exit()
-  // on a stored CefV8Context reference.
+  /// Create a new CefV8Value object of type function. This method should only
+  /// be called from within the scope of a CefRenderProcessHandler, CefV8Handler
+  /// or CefV8Accessor callback, or in combination with calling Enter() and
+  /// Exit() on a stored CefV8Context reference.
   ///
   /*--cef()--*/
   static CefRefPtr<CefV8Value> CreateFunction(const CefString& name,
                                               CefRefPtr<CefV8Handler> handler);
 
   ///
-  // Returns true if the underlying handle is valid and it can be accessed on
-  // the current thread. Do not call any other methods if this method returns
-  // false.
+  /// Create a new CefV8Value object of type Promise. This method should only be
+  /// called from within the scope of a CefRenderProcessHandler, CefV8Handler or
+  /// CefV8Accessor callback, or in combination with calling Enter() and Exit()
+  /// on a stored CefV8Context reference.
+  ///
+  /*--cef()--*/
+  static CefRefPtr<CefV8Value> CreatePromise();
+
+  ///
+  /// Returns true if the underlying handle is valid and it can be accessed on
+  /// the current thread. Do not call any other methods if this method returns
+  /// false.
   ///
   /*--cef()--*/
   virtual bool IsValid() = 0;
 
   ///
-  // True if the value type is undefined.
+  /// True if the value type is undefined.
   ///
   /*--cef()--*/
   virtual bool IsUndefined() = 0;
 
   ///
-  // True if the value type is null.
+  /// True if the value type is null.
   ///
   /*--cef()--*/
   virtual bool IsNull() = 0;
 
   ///
-  // True if the value type is bool.
+  /// True if the value type is bool.
   ///
   /*--cef()--*/
   virtual bool IsBool() = 0;
 
   ///
-  // True if the value type is int.
+  /// True if the value type is int.
   ///
   /*--cef()--*/
   virtual bool IsInt() = 0;
 
   ///
-  // True if the value type is unsigned int.
+  /// True if the value type is unsigned int.
   ///
   /*--cef()--*/
   virtual bool IsUInt() = 0;
 
   ///
-  // True if the value type is double.
+  /// True if the value type is double.
   ///
   /*--cef()--*/
   virtual bool IsDouble() = 0;
 
   ///
-  // True if the value type is Date.
+  /// True if the value type is Date.
   ///
   /*--cef()--*/
   virtual bool IsDate() = 0;
 
   ///
-  // True if the value type is string.
+  /// True if the value type is string.
   ///
   /*--cef()--*/
   virtual bool IsString() = 0;
 
   ///
-  // True if the value type is object.
+  /// True if the value type is object.
   ///
   /*--cef()--*/
   virtual bool IsObject() = 0;
 
   ///
-  // True if the value type is array.
+  /// True if the value type is array.
   ///
   /*--cef()--*/
   virtual bool IsArray() = 0;
 
   ///
-  // True if the value type is an ArrayBuffer.
+  /// True if the value type is an ArrayBuffer.
   ///
   /*--cef()--*/
   virtual bool IsArrayBuffer() = 0;
 
   ///
-  // True if the value type is function.
+  /// True if the value type is function.
   ///
   /*--cef()--*/
   virtual bool IsFunction() = 0;
 
   ///
-  // Returns true if this object is pointing to the same handle as |that|
-  // object.
+  /// True if the value type is a Promise.
+  ///
+  /*--cef()--*/
+  virtual bool IsPromise() = 0;
+
+  ///
+  /// Returns true if this object is pointing to the same handle as |that|
+  /// object.
   ///
   /*--cef()--*/
   virtual bool IsSame(CefRefPtr<CefV8Value> that) = 0;
 
   ///
-  // Return a bool value.
+  /// Return a bool value.
   ///
   /*--cef()--*/
   virtual bool GetBoolValue() = 0;
 
   ///
-  // Return an int value.
+  /// Return an int value.
   ///
   /*--cef()--*/
-  virtual int32 GetIntValue() = 0;
+  virtual int32_t GetIntValue() = 0;
 
   ///
-  // Return an unsigned int value.
+  /// Return an unsigned int value.
   ///
   /*--cef()--*/
-  virtual uint32 GetUIntValue() = 0;
+  virtual uint32_t GetUIntValue() = 0;
 
   ///
-  // Return a double value.
+  /// Return a double value.
   ///
   /*--cef()--*/
   virtual double GetDoubleValue() = 0;
 
   ///
-  // Return a Date value.
+  /// Return a Date value.
   ///
   /*--cef()--*/
-  virtual CefTime GetDateValue() = 0;
+  virtual CefBaseTime GetDateValue() = 0;
 
   ///
-  // Return a string value.
+  /// Return a string value.
   ///
   /*--cef()--*/
   virtual CefString GetStringValue() = 0;
 
-  // OBJECT METHODS - These methods are only available on objects. Arrays and
-  // functions are also objects. String- and integer-based keys can be used
-  // interchangably with the framework converting between them as necessary.
+  /// OBJECT METHODS - These methods are only available on objects. Arrays and
+  /// functions are also objects. String- and integer-based keys can be used
+  /// interchangably with the framework converting between them as necessary.
 
   ///
-  // Returns true if this is a user created object.
+  /// Returns true if this is a user created object.
   ///
   /*--cef()--*/
   virtual bool IsUserCreated() = 0;
 
   ///
-  // Returns true if the last method call resulted in an exception. This
-  // attribute exists only in the scope of the current CEF value object.
+  /// Returns true if the last method call resulted in an exception. This
+  /// attribute exists only in the scope of the current CEF value object.
   ///
   /*--cef()--*/
   virtual bool HasException() = 0;
 
   ///
-  // Returns the exception resulting from the last method call. This attribute
-  // exists only in the scope of the current CEF value object.
+  /// Returns the exception resulting from the last method call. This attribute
+  /// exists only in the scope of the current CEF value object.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefV8Exception> GetException() = 0;
 
   ///
-  // Clears the last exception and returns true on success.
+  /// Clears the last exception and returns true on success.
   ///
   /*--cef()--*/
   virtual bool ClearException() = 0;
 
   ///
-  // Returns true if this object will re-throw future exceptions. This attribute
-  // exists only in the scope of the current CEF value object.
+  /// Returns true if this object will re-throw future exceptions. This
+  /// attribute exists only in the scope of the current CEF value object.
   ///
   /*--cef()--*/
   virtual bool WillRethrowExceptions() = 0;
 
   ///
-  // Set whether this object will re-throw future exceptions. By default
-  // exceptions are not re-thrown. If a exception is re-thrown the current
-  // context should not be accessed again until after the exception has been
-  // caught and not re-thrown. Returns true on success. This attribute exists
-  // only in the scope of the current CEF value object.
+  /// Set whether this object will re-throw future exceptions. By default
+  /// exceptions are not re-thrown. If a exception is re-thrown the current
+  /// context should not be accessed again until after the exception has been
+  /// caught and not re-thrown. Returns true on success. This attribute exists
+  /// only in the scope of the current CEF value object.
   ///
   /*--cef()--*/
   virtual bool SetRethrowExceptions(bool rethrow) = 0;
 
   ///
-  // Returns true if the object has a value with the specified identifier.
+  /// Returns true if the object has a value with the specified identifier.
   ///
   /*--cef(capi_name=has_value_bykey,optional_param=key)--*/
   virtual bool HasValue(const CefString& key) = 0;
 
   ///
-  // Returns true if the object has a value with the specified identifier.
+  /// Returns true if the object has a value with the specified identifier.
   ///
   /*--cef(capi_name=has_value_byindex,index_param=index)--*/
   virtual bool HasValue(int index) = 0;
 
   ///
-  // Deletes the value with the specified identifier and returns true on
-  // success. Returns false if this method is called incorrectly or an exception
-  // is thrown. For read-only and don't-delete values this method will return
-  // true even though deletion failed.
+  /// Deletes the value with the specified identifier and returns true on
+  /// success. Returns false if this method is called incorrectly or an
+  /// exception is thrown. For read-only and don't-delete values this method
+  /// will return true even though deletion failed.
   ///
   /*--cef(capi_name=delete_value_bykey,optional_param=key)--*/
   virtual bool DeleteValue(const CefString& key) = 0;
 
   ///
-  // Deletes the value with the specified identifier and returns true on
-  // success. Returns false if this method is called incorrectly, deletion fails
-  // or an exception is thrown. For read-only and don't-delete values this
-  // method will return true even though deletion failed.
+  /// Deletes the value with the specified identifier and returns true on
+  /// success. Returns false if this method is called incorrectly, deletion
+  /// fails or an exception is thrown. For read-only and don't-delete values
+  /// this method will return true even though deletion failed.
   ///
   /*--cef(capi_name=delete_value_byindex,index_param=index)--*/
   virtual bool DeleteValue(int index) = 0;
 
   ///
-  // Returns the value with the specified identifier on success. Returns NULL
-  // if this method is called incorrectly or an exception is thrown.
+  /// Returns the value with the specified identifier on success. Returns NULL
+  /// if this method is called incorrectly or an exception is thrown.
   ///
   /*--cef(capi_name=get_value_bykey,optional_param=key)--*/
   virtual CefRefPtr<CefV8Value> GetValue(const CefString& key) = 0;
 
   ///
-  // Returns the value with the specified identifier on success. Returns NULL
-  // if this method is called incorrectly or an exception is thrown.
+  /// Returns the value with the specified identifier on success. Returns NULL
+  /// if this method is called incorrectly or an exception is thrown.
   ///
   /*--cef(capi_name=get_value_byindex,index_param=index)--*/
   virtual CefRefPtr<CefV8Value> GetValue(int index) = 0;
 
   ///
-  // Associates a value with the specified identifier and returns true on
-  // success. Returns false if this method is called incorrectly or an exception
-  // is thrown. For read-only values this method will return true even though
-  // assignment failed.
+  /// Associates a value with the specified identifier and returns true on
+  /// success. Returns false if this method is called incorrectly or an
+  /// exception is thrown. For read-only values this method will return true
+  /// even though assignment failed.
   ///
   /*--cef(capi_name=set_value_bykey,optional_param=key)--*/
   virtual bool SetValue(const CefString& key,
@@ -760,20 +777,20 @@
                         PropertyAttribute attribute) = 0;
 
   ///
-  // Associates a value with the specified identifier and returns true on
-  // success. Returns false if this method is called incorrectly or an exception
-  // is thrown. For read-only values this method will return true even though
-  // assignment failed.
+  /// Associates a value with the specified identifier and returns true on
+  /// success. Returns false if this method is called incorrectly or an
+  /// exception is thrown. For read-only values this method will return true
+  /// even though assignment failed.
   ///
   /*--cef(capi_name=set_value_byindex,index_param=index)--*/
   virtual bool SetValue(int index, CefRefPtr<CefV8Value> value) = 0;
 
   ///
-  // Registers an identifier and returns true on success. Access to the
-  // identifier will be forwarded to the CefV8Accessor instance passed to
-  // CefV8Value::CreateObject(). Returns false if this method is called
-  // incorrectly or an exception is thrown. For read-only values this method
-  // will return true even though assignment failed.
+  /// Registers an identifier and returns true on success. Access to the
+  /// identifier will be forwarded to the CefV8Accessor instance passed to
+  /// CefV8Value::CreateObject(). Returns false if this method is called
+  /// incorrectly or an exception is thrown. For read-only values this method
+  /// will return true even though assignment failed.
   ///
   /*--cef(capi_name=set_value_byaccessor,optional_param=key)--*/
   virtual bool SetValue(const CefString& key,
@@ -781,43 +798,43 @@
                         PropertyAttribute attribute) = 0;
 
   ///
-  // Read the keys for the object's values into the specified vector. Integer-
-  // based keys will also be returned as strings.
+  /// Read the keys for the object's values into the specified vector. Integer-
+  /// based keys will also be returned as strings.
   ///
   /*--cef()--*/
   virtual bool GetKeys(std::vector<CefString>& keys) = 0;
 
   ///
-  // Sets the user data for this object and returns true on success. Returns
-  // false if this method is called incorrectly. This method can only be called
-  // on user created objects.
+  /// Sets the user data for this object and returns true on success. Returns
+  /// false if this method is called incorrectly. This method can only be called
+  /// on user created objects.
   ///
   /*--cef(optional_param=user_data)--*/
   virtual bool SetUserData(CefRefPtr<CefBaseRefCounted> user_data) = 0;
 
   ///
-  // Returns the user data, if any, assigned to this object.
+  /// Returns the user data, if any, assigned to this object.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBaseRefCounted> GetUserData() = 0;
 
   ///
-  // Returns the amount of externally allocated memory registered for the
-  // object.
+  /// Returns the amount of externally allocated memory registered for the
+  /// object.
   ///
   /*--cef()--*/
   virtual int GetExternallyAllocatedMemory() = 0;
 
   ///
-  // Adjusts the amount of registered external memory for the object. Used to
-  // give V8 an indication of the amount of externally allocated memory that is
-  // kept alive by JavaScript objects. V8 uses this information to decide when
-  // to perform global garbage collection. Each CefV8Value tracks the amount of
-  // external memory associated with it and automatically decreases the global
-  // total by the appropriate amount on its destruction. |change_in_bytes|
-  // specifies the number of bytes to adjust by. This method returns the number
-  // of bytes associated with the object after the adjustment. This method can
-  // only be called on user created objects.
+  /// Adjusts the amount of registered external memory for the object. Used to
+  /// give V8 an indication of the amount of externally allocated memory that is
+  /// kept alive by JavaScript objects. V8 uses this information to decide when
+  /// to perform global garbage collection. Each CefV8Value tracks the amount of
+  /// external memory associated with it and automatically decreases the global
+  /// total by the appropriate amount on its destruction. |change_in_bytes|
+  /// specifies the number of bytes to adjust by. This method returns the number
+  /// of bytes associated with the object after the adjustment. This method can
+  /// only be called on user created objects.
   ///
   /*--cef()--*/
   virtual int AdjustExternallyAllocatedMemory(int change_in_bytes) = 0;
@@ -825,7 +842,7 @@
   // ARRAY METHODS - These methods are only available on arrays.
 
   ///
-  // Returns the number of elements in the array.
+  /// Returns the number of elements in the array.
   ///
   /*--cef()--*/
   virtual int GetArrayLength() = 0;
@@ -833,45 +850,59 @@
   // ARRAY BUFFER METHODS - These methods are only available on ArrayBuffers.
 
   ///
-  // Returns the ReleaseCallback object associated with the ArrayBuffer or NULL
-  // if the ArrayBuffer was not created with CreateArrayBuffer.
+  /// Returns the ReleaseCallback object associated with the ArrayBuffer or NULL
+  /// if the ArrayBuffer was not created with CreateArrayBuffer.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefV8ArrayBufferReleaseCallback>
   GetArrayBufferReleaseCallback() = 0;
 
   ///
-  // Prevent the ArrayBuffer from using it's memory block by setting the length
-  // to zero. This operation cannot be undone. If the ArrayBuffer was created
-  // with CreateArrayBuffer then CefV8ArrayBufferReleaseCallback::ReleaseBuffer
-  // will be called to release the underlying buffer.
+  /// Prevent the ArrayBuffer from using it's memory block by setting the length
+  /// to zero. This operation cannot be undone. If the ArrayBuffer was created
+  /// with CreateArrayBuffer then CefV8ArrayBufferReleaseCallback::ReleaseBuffer
+  /// will be called to release the underlying buffer.
   ///
   /*--cef()--*/
   virtual bool NeuterArrayBuffer() = 0;
 
+  ///
+  /// Returns the length (in bytes) of the ArrayBuffer.
+  ///
+  /*--cef()--*/
+  virtual size_t GetArrayBufferByteLength() = 0;
+
+  ///
+  /// Returns a pointer to the beginning of the memory block for this
+  /// ArrayBuffer backing store. The returned pointer is valid as long as the
+  /// CefV8Value is alive.
+  ///
+  /*--cef()--*/
+  virtual void* GetArrayBufferData() = 0;
+
   // FUNCTION METHODS - These methods are only available on functions.
 
   ///
-  // Returns the function name.
+  /// Returns the function name.
   ///
   /*--cef()--*/
   virtual CefString GetFunctionName() = 0;
 
   ///
-  // Returns the function handler or NULL if not a CEF-created function.
+  /// Returns the function handler or NULL if not a CEF-created function.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefV8Handler> GetFunctionHandler() = 0;
 
   ///
-  // Execute the function using the current V8 context. This method should only
-  // be called from within the scope of a CefV8Handler or CefV8Accessor
-  // callback, or in combination with calling Enter() and Exit() on a stored
-  // CefV8Context reference. |object| is the receiver ('this' object) of the
-  // function. If |object| is empty the current context's global object will be
-  // used. |arguments| is the list of arguments that will be passed to the
-  // function. Returns the function return value on success. Returns NULL if
-  // this method is called incorrectly or an exception is thrown.
+  /// Execute the function using the current V8 context. This method should only
+  /// be called from within the scope of a CefV8Handler or CefV8Accessor
+  /// callback, or in combination with calling Enter() and Exit() on a stored
+  /// CefV8Context reference. |object| is the receiver ('this' object) of the
+  /// function. If |object| is empty the current context's global object will be
+  /// used. |arguments| is the list of arguments that will be passed to the
+  /// function. Returns the function return value on success. Returns NULL if
+  /// this method is called incorrectly or an exception is thrown.
   ///
   /*--cef(optional_param=object)--*/
   virtual CefRefPtr<CefV8Value> ExecuteFunction(
@@ -879,117 +910,140 @@
       const CefV8ValueList& arguments) = 0;
 
   ///
-  // Execute the function using the specified V8 context. |object| is the
-  // receiver ('this' object) of the function. If |object| is empty the
-  // specified context's global object will be used. |arguments| is the list of
-  // arguments that will be passed to the function. Returns the function return
-  // value on success. Returns NULL if this method is called incorrectly or an
-  // exception is thrown.
+  /// Execute the function using the specified V8 context. |object| is the
+  /// receiver ('this' object) of the function. If |object| is empty the
+  /// specified context's global object will be used. |arguments| is the list of
+  /// arguments that will be passed to the function. Returns the function return
+  /// value on success. Returns NULL if this method is called incorrectly or an
+  /// exception is thrown.
   ///
   /*--cef(optional_param=object)--*/
   virtual CefRefPtr<CefV8Value> ExecuteFunctionWithContext(
       CefRefPtr<CefV8Context> context,
       CefRefPtr<CefV8Value> object,
       const CefV8ValueList& arguments) = 0;
+
+  // PROMISE METHODS - These methods are only available on Promises.
+
+  ///
+  /// Resolve the Promise using the current V8 context. This method should only
+  /// be called from within the scope of a CefV8Handler or CefV8Accessor
+  /// callback, or in combination with calling Enter() and Exit() on a stored
+  /// CefV8Context reference. |arg| is the argument passed to the resolved
+  /// promise. Returns true on success. Returns false if this method is called
+  /// incorrectly or an exception is thrown.
+  ///
+  /*--cef(optional_param=arg)--*/
+  virtual bool ResolvePromise(CefRefPtr<CefV8Value> arg) = 0;
+
+  ///
+  /// Reject the Promise using the current V8 context. This method should only
+  /// be called from within the scope of a CefV8Handler or CefV8Accessor
+  /// callback, or in combination with calling Enter() and Exit() on a stored
+  /// CefV8Context reference. Returns true on success. Returns false if this
+  /// method is called incorrectly or an exception is thrown.
+  ///
+  /*--cef()--*/
+  virtual bool RejectPromise(const CefString& errorMsg) = 0;
 };
 
 ///
-// Class representing a V8 stack trace handle. V8 handles can only be accessed
-// from the thread on which they are created. Valid threads for creating a V8
-// handle include the render process main thread (TID_RENDERER) and WebWorker
-// threads. A task runner for posting tasks on the associated thread can be
-// retrieved via the CefV8Context::GetTaskRunner() method.
+/// Class representing a V8 stack trace handle. V8 handles can only be accessed
+/// from the thread on which they are created. Valid threads for creating a V8
+/// handle include the render process main thread (TID_RENDERER) and WebWorker
+/// threads. A task runner for posting tasks on the associated thread can be
+/// retrieved via the CefV8Context::GetTaskRunner() method.
 ///
 /*--cef(source=library)--*/
 class CefV8StackTrace : public virtual CefBaseRefCounted {
  public:
   ///
-  // Returns the stack trace for the currently active context. |frame_limit| is
-  // the maximum number of frames that will be captured.
+  /// Returns the stack trace for the currently active context. |frame_limit| is
+  /// the maximum number of frames that will be captured.
   ///
   /*--cef()--*/
   static CefRefPtr<CefV8StackTrace> GetCurrent(int frame_limit);
 
   ///
-  // Returns true if the underlying handle is valid and it can be accessed on
-  // the current thread. Do not call any other methods if this method returns
-  // false.
+  /// Returns true if the underlying handle is valid and it can be accessed on
+  /// the current thread. Do not call any other methods if this method returns
+  /// false.
   ///
   /*--cef()--*/
   virtual bool IsValid() = 0;
 
   ///
-  // Returns the number of stack frames.
+  /// Returns the number of stack frames.
   ///
   /*--cef()--*/
   virtual int GetFrameCount() = 0;
 
   ///
-  // Returns the stack frame at the specified 0-based index.
+  /// Returns the stack frame at the specified 0-based index.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefV8StackFrame> GetFrame(int index) = 0;
 };
 
 ///
-// Class representing a V8 stack frame handle. V8 handles can only be accessed
-// from the thread on which they are created. Valid threads for creating a V8
-// handle include the render process main thread (TID_RENDERER) and WebWorker
-// threads. A task runner for posting tasks on the associated thread can be
-// retrieved via the CefV8Context::GetTaskRunner() method.
+/// Class representing a V8 stack frame handle. V8 handles can only be accessed
+/// from the thread on which they are created. Valid threads for creating a V8
+/// handle include the render process main thread (TID_RENDERER) and WebWorker
+/// threads. A task runner for posting tasks on the associated thread can be
+/// retrieved via the CefV8Context::GetTaskRunner() method.
 ///
 /*--cef(source=library,no_debugct_check)--*/
 class CefV8StackFrame : public virtual CefBaseRefCounted {
  public:
   ///
-  // Returns true if the underlying handle is valid and it can be accessed on
-  // the current thread. Do not call any other methods if this method returns
-  // false.
+  /// Returns true if the underlying handle is valid and it can be accessed on
+  /// the current thread. Do not call any other methods if this method returns
+  /// false.
   ///
   /*--cef()--*/
   virtual bool IsValid() = 0;
 
   ///
-  // Returns the name of the resource script that contains the function.
+  /// Returns the name of the resource script that contains the function.
   ///
   /*--cef()--*/
   virtual CefString GetScriptName() = 0;
 
   ///
-  // Returns the name of the resource script that contains the function or the
-  // sourceURL value if the script name is undefined and its source ends with
-  // a "//@ sourceURL=..." string.
+  /// Returns the name of the resource script that contains the function or the
+  /// sourceURL value if the script name is undefined and its source ends with
+  /// a "//@ sourceURL=..." string.
   ///
   /*--cef()--*/
   virtual CefString GetScriptNameOrSourceURL() = 0;
 
   ///
-  // Returns the name of the function.
+  /// Returns the name of the function.
   ///
   /*--cef()--*/
   virtual CefString GetFunctionName() = 0;
 
   ///
-  // Returns the 1-based line number for the function call or 0 if unknown.
+  /// Returns the 1-based line number for the function call or 0 if unknown.
   ///
   /*--cef()--*/
   virtual int GetLineNumber() = 0;
 
   ///
-  // Returns the 1-based column offset on the line for the function call or 0 if
-  // unknown.
+  /// Returns the 1-based column offset on the line for the function call or 0
+  /// if unknown.
   ///
   /*--cef()--*/
   virtual int GetColumn() = 0;
 
   ///
-  // Returns true if the function was compiled using eval().
+  /// Returns true if the function was compiled using eval().
   ///
   /*--cef()--*/
   virtual bool IsEval() = 0;
 
   ///
-  // Returns true if the function was called as a constructor via "new".
+  /// Returns true if the function was called as a constructor via "new".
   ///
   /*--cef()--*/
   virtual bool IsConstructor() = 0;
diff --git a/src/include/cef_values.h b/src/include/cef_values.h
index be88794..f7bcb79 100644
--- a/src/include/cef_values.h
+++ b/src/include/cef_values.h
@@ -48,244 +48,252 @@
 typedef cef_value_type_t CefValueType;
 
 ///
-// Class that wraps other data value types. Complex types (binary, dictionary
-// and list) will be referenced but not owned by this object. Can be used on any
-// process and thread.
+/// Class that wraps other data value types. Complex types (binary, dictionary
+/// and list) will be referenced but not owned by this object. Can be used on
+/// any process and thread.
 ///
 /*--cef(source=library)--*/
 class CefValue : public virtual CefBaseRefCounted {
  public:
   ///
-  // Creates a new object.
+  /// Creates a new object.
   ///
   /*--cef()--*/
   static CefRefPtr<CefValue> Create();
 
   ///
-  // Returns true if the underlying data is valid. This will always be true for
-  // simple types. For complex types (binary, dictionary and list) the
-  // underlying data may become invalid if owned by another object (e.g. list or
-  // dictionary) and that other object is then modified or destroyed. This value
-  // object can be re-used by calling Set*() even if the underlying data is
-  // invalid.
+  /// Returns true if the underlying data is valid. This will always be true for
+  /// simple types. For complex types (binary, dictionary and list) the
+  /// underlying data may become invalid if owned by another object (e.g. list
+  /// or dictionary) and that other object is then modified or destroyed. This
+  /// value object can be re-used by calling Set*() even if the underlying data
+  /// is invalid.
   ///
   /*--cef()--*/
   virtual bool IsValid() = 0;
 
   ///
-  // Returns true if the underlying data is owned by another object.
+  /// Returns true if the underlying data is owned by another object.
   ///
   /*--cef()--*/
   virtual bool IsOwned() = 0;
 
   ///
-  // Returns true if the underlying data is read-only. Some APIs may expose
-  // read-only objects.
+  /// Returns true if the underlying data is read-only. Some APIs may expose
+  /// read-only objects.
   ///
   /*--cef()--*/
   virtual bool IsReadOnly() = 0;
 
   ///
-  // Returns true if this object and |that| object have the same underlying
-  // data. If true modifications to this object will also affect |that| object
-  // and vice-versa.
+  /// Returns true if this object and |that| object have the same underlying
+  /// data. If true modifications to this object will also affect |that| object
+  /// and vice-versa.
   ///
   /*--cef()--*/
   virtual bool IsSame(CefRefPtr<CefValue> that) = 0;
 
   ///
-  // Returns true if this object and |that| object have an equivalent underlying
-  // value but are not necessarily the same object.
+  /// Returns true if this object and |that| object have an equivalent
+  /// underlying value but are not necessarily the same object.
   ///
   /*--cef()--*/
   virtual bool IsEqual(CefRefPtr<CefValue> that) = 0;
 
   ///
-  // Returns a copy of this object. The underlying data will also be copied.
+  /// Returns a copy of this object. The underlying data will also be copied.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefValue> Copy() = 0;
 
   ///
-  // Returns the underlying value type.
+  /// Returns the underlying value type.
   ///
   /*--cef(default_retval=VTYPE_INVALID)--*/
   virtual CefValueType GetType() = 0;
 
   ///
-  // Returns the underlying value as type bool.
+  /// Returns the underlying value as type bool.
   ///
   /*--cef()--*/
   virtual bool GetBool() = 0;
 
   ///
-  // Returns the underlying value as type int.
+  /// Returns the underlying value as type int.
   ///
   /*--cef()--*/
   virtual int GetInt() = 0;
 
   ///
-  // Returns the underlying value as type double.
+  /// Returns the underlying value as type double.
   ///
   /*--cef()--*/
   virtual double GetDouble() = 0;
 
   ///
-  // Returns the underlying value as type string.
+  /// Returns the underlying value as type string.
   ///
   /*--cef()--*/
   virtual CefString GetString() = 0;
 
   ///
-  // Returns the underlying value as type binary. The returned reference may
-  // become invalid if the value is owned by another object or if ownership is
-  // transferred to another object in the future. To maintain a reference to
-  // the value after assigning ownership to a dictionary or list pass this
-  // object to the SetValue() method instead of passing the returned reference
-  // to SetBinary().
+  /// Returns the underlying value as type binary. The returned reference may
+  /// become invalid if the value is owned by another object or if ownership is
+  /// transferred to another object in the future. To maintain a reference to
+  /// the value after assigning ownership to a dictionary or list pass this
+  /// object to the SetValue() method instead of passing the returned reference
+  /// to SetBinary().
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBinaryValue> GetBinary() = 0;
 
   ///
-  // Returns the underlying value as type dictionary. The returned reference may
-  // become invalid if the value is owned by another object or if ownership is
-  // transferred to another object in the future. To maintain a reference to
-  // the value after assigning ownership to a dictionary or list pass this
-  // object to the SetValue() method instead of passing the returned reference
-  // to SetDictionary().
+  /// Returns the underlying value as type dictionary. The returned reference
+  /// may become invalid if the value is owned by another object or if ownership
+  /// is transferred to another object in the future. To maintain a reference to
+  /// the value after assigning ownership to a dictionary or list pass this
+  /// object to the SetValue() method instead of passing the returned reference
+  /// to SetDictionary().
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDictionaryValue> GetDictionary() = 0;
 
   ///
-  // Returns the underlying value as type list. The returned reference may
-  // become invalid if the value is owned by another object or if ownership is
-  // transferred to another object in the future. To maintain a reference to
-  // the value after assigning ownership to a dictionary or list pass this
-  // object to the SetValue() method instead of passing the returned reference
-  // to SetList().
+  /// Returns the underlying value as type list. The returned reference may
+  /// become invalid if the value is owned by another object or if ownership is
+  /// transferred to another object in the future. To maintain a reference to
+  /// the value after assigning ownership to a dictionary or list pass this
+  /// object to the SetValue() method instead of passing the returned reference
+  /// to SetList().
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefListValue> GetList() = 0;
 
   ///
-  // Sets the underlying value as type null. Returns true if the value was set
-  // successfully.
+  /// Sets the underlying value as type null. Returns true if the value was set
+  /// successfully.
   ///
   /*--cef()--*/
   virtual bool SetNull() = 0;
 
   ///
-  // Sets the underlying value as type bool. Returns true if the value was set
-  // successfully.
+  /// Sets the underlying value as type bool. Returns true if the value was set
+  /// successfully.
   ///
   /*--cef()--*/
   virtual bool SetBool(bool value) = 0;
 
   ///
-  // Sets the underlying value as type int. Returns true if the value was set
-  // successfully.
+  /// Sets the underlying value as type int. Returns true if the value was set
+  /// successfully.
   ///
   /*--cef()--*/
   virtual bool SetInt(int value) = 0;
 
   ///
-  // Sets the underlying value as type double. Returns true if the value was set
-  // successfully.
+  /// Sets the underlying value as type double. Returns true if the value was
+  /// set successfully.
   ///
   /*--cef()--*/
   virtual bool SetDouble(double value) = 0;
 
   ///
-  // Sets the underlying value as type string. Returns true if the value was set
-  // successfully.
+  /// Sets the underlying value as type string. Returns true if the value was
+  /// set successfully.
   ///
   /*--cef(optional_param=value)--*/
   virtual bool SetString(const CefString& value) = 0;
 
   ///
-  // Sets the underlying value as type binary. Returns true if the value was set
-  // successfully. This object keeps a reference to |value| and ownership of the
-  // underlying data remains unchanged.
+  /// Sets the underlying value as type binary. Returns true if the value was
+  /// set successfully. This object keeps a reference to |value| and ownership
+  /// of the underlying data remains unchanged.
   ///
   /*--cef()--*/
   virtual bool SetBinary(CefRefPtr<CefBinaryValue> value) = 0;
 
   ///
-  // Sets the underlying value as type dict. Returns true if the value was set
-  // successfully. This object keeps a reference to |value| and ownership of the
-  // underlying data remains unchanged.
+  /// Sets the underlying value as type dict. Returns true if the value was set
+  /// successfully. This object keeps a reference to |value| and ownership of
+  /// the underlying data remains unchanged.
   ///
   /*--cef()--*/
   virtual bool SetDictionary(CefRefPtr<CefDictionaryValue> value) = 0;
 
   ///
-  // Sets the underlying value as type list. Returns true if the value was set
-  // successfully. This object keeps a reference to |value| and ownership of the
-  // underlying data remains unchanged.
+  /// Sets the underlying value as type list. Returns true if the value was set
+  /// successfully. This object keeps a reference to |value| and ownership of
+  /// the underlying data remains unchanged.
   ///
   /*--cef()--*/
   virtual bool SetList(CefRefPtr<CefListValue> value) = 0;
 };
 
 ///
-// Class representing a binary value. Can be used on any process and thread.
+/// Class representing a binary value. Can be used on any process and thread.
 ///
 /*--cef(source=library)--*/
 class CefBinaryValue : public virtual CefBaseRefCounted {
  public:
   ///
-  // Creates a new object that is not owned by any other object. The specified
-  // |data| will be copied.
+  /// Creates a new object that is not owned by any other object. The specified
+  /// |data| will be copied.
   ///
   /*--cef()--*/
   static CefRefPtr<CefBinaryValue> Create(const void* data, size_t data_size);
 
   ///
-  // Returns true if this object is valid. This object may become invalid if
-  // the underlying data is owned by another object (e.g. list or dictionary)
-  // and that other object is then modified or destroyed. Do not call any other
-  // methods if this method returns false.
+  /// Returns true if this object is valid. This object may become invalid if
+  /// the underlying data is owned by another object (e.g. list or dictionary)
+  /// and that other object is then modified or destroyed. Do not call any other
+  /// methods if this method returns false.
   ///
   /*--cef()--*/
   virtual bool IsValid() = 0;
 
   ///
-  // Returns true if this object is currently owned by another object.
+  /// Returns true if this object is currently owned by another object.
   ///
   /*--cef()--*/
   virtual bool IsOwned() = 0;
 
   ///
-  // Returns true if this object and |that| object have the same underlying
-  // data.
+  /// Returns true if this object and |that| object have the same underlying
+  /// data.
   ///
   /*--cef()--*/
   virtual bool IsSame(CefRefPtr<CefBinaryValue> that) = 0;
 
   ///
-  // Returns true if this object and |that| object have an equivalent underlying
-  // value but are not necessarily the same object.
+  /// Returns true if this object and |that| object have an equivalent
+  /// underlying value but are not necessarily the same object.
   ///
   /*--cef()--*/
   virtual bool IsEqual(CefRefPtr<CefBinaryValue> that) = 0;
 
   ///
-  // Returns a copy of this object. The data in this object will also be copied.
+  /// Returns a copy of this object. The data in this object will also be
+  /// copied.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBinaryValue> Copy() = 0;
 
   ///
-  // Returns the data size.
+  /// Returns a pointer to the beginning of the memory block.
+  /// The returned pointer is valid as long as the CefBinaryValue is alive.
+  ///
+  /*--cef()--*/
+  virtual const void* GetRawData() = 0;
+
+  ///
+  /// Returns the data size.
   ///
   /*--cef()--*/
   virtual size_t GetSize() = 0;
 
   ///
-  // Read up to |buffer_size| number of bytes into |buffer|. Reading begins at
-  // the specified byte |data_offset|. Returns the number of bytes read.
+  /// Read up to |buffer_size| number of bytes into |buffer|. Reading begins at
+  /// the specified byte |data_offset|. Returns the number of bytes read.
   ///
   /*--cef()--*/
   virtual size_t GetData(void* buffer,
@@ -294,7 +302,8 @@
 };
 
 ///
-// Class representing a dictionary value. Can be used on any process and thread.
+/// Class representing a dictionary value. Can be used on any process and
+/// thread.
 ///
 /*--cef(source=library)--*/
 class CefDictionaryValue : public virtual CefBaseRefCounted {
@@ -302,444 +311,444 @@
   typedef std::vector<CefString> KeyList;
 
   ///
-  // Creates a new object that is not owned by any other object.
+  /// Creates a new object that is not owned by any other object.
   ///
   /*--cef()--*/
   static CefRefPtr<CefDictionaryValue> Create();
 
   ///
-  // Returns true if this object is valid. This object may become invalid if
-  // the underlying data is owned by another object (e.g. list or dictionary)
-  // and that other object is then modified or destroyed. Do not call any other
-  // methods if this method returns false.
+  /// Returns true if this object is valid. This object may become invalid if
+  /// the underlying data is owned by another object (e.g. list or dictionary)
+  /// and that other object is then modified or destroyed. Do not call any other
+  /// methods if this method returns false.
   ///
   /*--cef()--*/
   virtual bool IsValid() = 0;
 
   ///
-  // Returns true if this object is currently owned by another object.
+  /// Returns true if this object is currently owned by another object.
   ///
   /*--cef()--*/
   virtual bool IsOwned() = 0;
 
   ///
-  // Returns true if the values of this object are read-only. Some APIs may
-  // expose read-only objects.
+  /// Returns true if the values of this object are read-only. Some APIs may
+  /// expose read-only objects.
   ///
   /*--cef()--*/
   virtual bool IsReadOnly() = 0;
 
   ///
-  // Returns true if this object and |that| object have the same underlying
-  // data. If true modifications to this object will also affect |that| object
-  // and vice-versa.
+  /// Returns true if this object and |that| object have the same underlying
+  /// data. If true modifications to this object will also affect |that| object
+  /// and vice-versa.
   ///
   /*--cef()--*/
   virtual bool IsSame(CefRefPtr<CefDictionaryValue> that) = 0;
 
   ///
-  // Returns true if this object and |that| object have an equivalent underlying
-  // value but are not necessarily the same object.
+  /// Returns true if this object and |that| object have an equivalent
+  /// underlying value but are not necessarily the same object.
   ///
   /*--cef()--*/
   virtual bool IsEqual(CefRefPtr<CefDictionaryValue> that) = 0;
 
   ///
-  // Returns a writable copy of this object. If |exclude_empty_children| is true
-  // any empty dictionaries or lists will be excluded from the copy.
+  /// Returns a writable copy of this object. If |exclude_empty_children| is
+  /// true any empty dictionaries or lists will be excluded from the copy.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDictionaryValue> Copy(bool exclude_empty_children) = 0;
 
   ///
-  // Returns the number of values.
+  /// Returns the number of values.
   ///
   /*--cef()--*/
   virtual size_t GetSize() = 0;
 
   ///
-  // Removes all values. Returns true on success.
+  /// Removes all values. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool Clear() = 0;
 
   ///
-  // Returns true if the current dictionary has a value for the given key.
+  /// Returns true if the current dictionary has a value for the given key.
   ///
   /*--cef()--*/
   virtual bool HasKey(const CefString& key) = 0;
 
   ///
-  // Reads all keys for this dictionary into the specified vector.
+  /// Reads all keys for this dictionary into the specified vector.
   ///
   /*--cef()--*/
   virtual bool GetKeys(KeyList& keys) = 0;
 
   ///
-  // Removes the value at the specified key. Returns true is the value was
-  // removed successfully.
+  /// Removes the value at the specified key. Returns true is the value was
+  /// removed successfully.
   ///
   /*--cef()--*/
   virtual bool Remove(const CefString& key) = 0;
 
   ///
-  // Returns the value type for the specified key.
+  /// Returns the value type for the specified key.
   ///
   /*--cef(default_retval=VTYPE_INVALID)--*/
   virtual CefValueType GetType(const CefString& key) = 0;
 
   ///
-  // Returns the value at the specified key. For simple types the returned
-  // value will copy existing data and modifications to the value will not
-  // modify this object. For complex types (binary, dictionary and list) the
-  // returned value will reference existing data and modifications to the value
-  // will modify this object.
+  /// Returns the value at the specified key. For simple types the returned
+  /// value will copy existing data and modifications to the value will not
+  /// modify this object. For complex types (binary, dictionary and list) the
+  /// returned value will reference existing data and modifications to the value
+  /// will modify this object.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefValue> GetValue(const CefString& key) = 0;
 
   ///
-  // Returns the value at the specified key as type bool.
+  /// Returns the value at the specified key as type bool.
   ///
   /*--cef()--*/
   virtual bool GetBool(const CefString& key) = 0;
 
   ///
-  // Returns the value at the specified key as type int.
+  /// Returns the value at the specified key as type int.
   ///
   /*--cef()--*/
   virtual int GetInt(const CefString& key) = 0;
 
   ///
-  // Returns the value at the specified key as type double.
+  /// Returns the value at the specified key as type double.
   ///
   /*--cef()--*/
   virtual double GetDouble(const CefString& key) = 0;
 
   ///
-  // Returns the value at the specified key as type string.
+  /// Returns the value at the specified key as type string.
   ///
   /*--cef()--*/
   virtual CefString GetString(const CefString& key) = 0;
 
   ///
-  // Returns the value at the specified key as type binary. The returned
-  // value will reference existing data.
+  /// Returns the value at the specified key as type binary. The returned
+  /// value will reference existing data.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBinaryValue> GetBinary(const CefString& key) = 0;
 
   ///
-  // Returns the value at the specified key as type dictionary. The returned
-  // value will reference existing data and modifications to the value will
-  // modify this object.
+  /// Returns the value at the specified key as type dictionary. The returned
+  /// value will reference existing data and modifications to the value will
+  /// modify this object.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDictionaryValue> GetDictionary(const CefString& key) = 0;
 
   ///
-  // Returns the value at the specified key as type list. The returned value
-  // will reference existing data and modifications to the value will modify
-  // this object.
+  /// Returns the value at the specified key as type list. The returned value
+  /// will reference existing data and modifications to the value will modify
+  /// this object.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefListValue> GetList(const CefString& key) = 0;
 
   ///
-  // Sets the value at the specified key. Returns true if the value was set
-  // successfully. If |value| represents simple data then the underlying data
-  // will be copied and modifications to |value| will not modify this object. If
-  // |value| represents complex data (binary, dictionary or list) then the
-  // underlying data will be referenced and modifications to |value| will modify
-  // this object.
+  /// Sets the value at the specified key. Returns true if the value was set
+  /// successfully. If |value| represents simple data then the underlying data
+  /// will be copied and modifications to |value| will not modify this object.
+  /// If |value| represents complex data (binary, dictionary or list) then the
+  /// underlying data will be referenced and modifications to |value| will
+  /// modify this object.
   ///
   /*--cef()--*/
   virtual bool SetValue(const CefString& key, CefRefPtr<CefValue> value) = 0;
 
   ///
-  // Sets the value at the specified key as type null. Returns true if the
-  // value was set successfully.
+  /// Sets the value at the specified key as type null. Returns true if the
+  /// value was set successfully.
   ///
   /*--cef()--*/
   virtual bool SetNull(const CefString& key) = 0;
 
   ///
-  // Sets the value at the specified key as type bool. Returns true if the
-  // value was set successfully.
+  /// Sets the value at the specified key as type bool. Returns true if the
+  /// value was set successfully.
   ///
   /*--cef()--*/
   virtual bool SetBool(const CefString& key, bool value) = 0;
 
   ///
-  // Sets the value at the specified key as type int. Returns true if the
-  // value was set successfully.
+  /// Sets the value at the specified key as type int. Returns true if the
+  /// value was set successfully.
   ///
   /*--cef()--*/
   virtual bool SetInt(const CefString& key, int value) = 0;
 
   ///
-  // Sets the value at the specified key as type double. Returns true if the
-  // value was set successfully.
+  /// Sets the value at the specified key as type double. Returns true if the
+  /// value was set successfully.
   ///
   /*--cef()--*/
   virtual bool SetDouble(const CefString& key, double value) = 0;
 
   ///
-  // Sets the value at the specified key as type string. Returns true if the
-  // value was set successfully.
+  /// Sets the value at the specified key as type string. Returns true if the
+  /// value was set successfully.
   ///
   /*--cef(optional_param=value)--*/
   virtual bool SetString(const CefString& key, const CefString& value) = 0;
 
   ///
-  // Sets the value at the specified key as type binary. Returns true if the
-  // value was set successfully. If |value| is currently owned by another object
-  // then the value will be copied and the |value| reference will not change.
-  // Otherwise, ownership will be transferred to this object and the |value|
-  // reference will be invalidated.
+  /// Sets the value at the specified key as type binary. Returns true if the
+  /// value was set successfully. If |value| is currently owned by another
+  /// object then the value will be copied and the |value| reference will not
+  /// change. Otherwise, ownership will be transferred to this object and the
+  /// |value| reference will be invalidated.
   ///
   /*--cef()--*/
   virtual bool SetBinary(const CefString& key,
                          CefRefPtr<CefBinaryValue> value) = 0;
 
   ///
-  // Sets the value at the specified key as type dict. Returns true if the
-  // value was set successfully. If |value| is currently owned by another object
-  // then the value will be copied and the |value| reference will not change.
-  // Otherwise, ownership will be transferred to this object and the |value|
-  // reference will be invalidated.
+  /// Sets the value at the specified key as type dict. Returns true if the
+  /// value was set successfully. If |value| is currently owned by another
+  /// object then the value will be copied and the |value| reference will not
+  /// change. Otherwise, ownership will be transferred to this object and the
+  /// |value| reference will be invalidated.
   ///
   /*--cef()--*/
   virtual bool SetDictionary(const CefString& key,
                              CefRefPtr<CefDictionaryValue> value) = 0;
 
   ///
-  // Sets the value at the specified key as type list. Returns true if the
-  // value was set successfully. If |value| is currently owned by another object
-  // then the value will be copied and the |value| reference will not change.
-  // Otherwise, ownership will be transferred to this object and the |value|
-  // reference will be invalidated.
+  /// Sets the value at the specified key as type list. Returns true if the
+  /// value was set successfully. If |value| is currently owned by another
+  /// object then the value will be copied and the |value| reference will not
+  /// change. Otherwise, ownership will be transferred to this object and the
+  /// |value| reference will be invalidated.
   ///
   /*--cef()--*/
   virtual bool SetList(const CefString& key, CefRefPtr<CefListValue> value) = 0;
 };
 
 ///
-// Class representing a list value. Can be used on any process and thread.
+/// Class representing a list value. Can be used on any process and thread.
 ///
 /*--cef(source=library)--*/
 class CefListValue : public virtual CefBaseRefCounted {
  public:
   ///
-  // Creates a new object that is not owned by any other object.
+  /// Creates a new object that is not owned by any other object.
   ///
   /*--cef()--*/
   static CefRefPtr<CefListValue> Create();
 
   ///
-  // Returns true if this object is valid. This object may become invalid if
-  // the underlying data is owned by another object (e.g. list or dictionary)
-  // and that other object is then modified or destroyed. Do not call any other
-  // methods if this method returns false.
+  /// Returns true if this object is valid. This object may become invalid if
+  /// the underlying data is owned by another object (e.g. list or dictionary)
+  /// and that other object is then modified or destroyed. Do not call any other
+  /// methods if this method returns false.
   ///
   /*--cef()--*/
   virtual bool IsValid() = 0;
 
   ///
-  // Returns true if this object is currently owned by another object.
+  /// Returns true if this object is currently owned by another object.
   ///
   /*--cef()--*/
   virtual bool IsOwned() = 0;
 
   ///
-  // Returns true if the values of this object are read-only. Some APIs may
-  // expose read-only objects.
+  /// Returns true if the values of this object are read-only. Some APIs may
+  /// expose read-only objects.
   ///
   /*--cef()--*/
   virtual bool IsReadOnly() = 0;
 
   ///
-  // Returns true if this object and |that| object have the same underlying
-  // data. If true modifications to this object will also affect |that| object
-  // and vice-versa.
+  /// Returns true if this object and |that| object have the same underlying
+  /// data. If true modifications to this object will also affect |that| object
+  /// and vice-versa.
   ///
   /*--cef()--*/
   virtual bool IsSame(CefRefPtr<CefListValue> that) = 0;
 
   ///
-  // Returns true if this object and |that| object have an equivalent underlying
-  // value but are not necessarily the same object.
+  /// Returns true if this object and |that| object have an equivalent
+  /// underlying value but are not necessarily the same object.
   ///
   /*--cef()--*/
   virtual bool IsEqual(CefRefPtr<CefListValue> that) = 0;
 
   ///
-  // Returns a writable copy of this object.
+  /// Returns a writable copy of this object.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefListValue> Copy() = 0;
 
   ///
-  // Sets the number of values. If the number of values is expanded all
-  // new value slots will default to type null. Returns true on success.
+  /// Sets the number of values. If the number of values is expanded all
+  /// new value slots will default to type null. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool SetSize(size_t size) = 0;
 
   ///
-  // Returns the number of values.
+  /// Returns the number of values.
   ///
   /*--cef()--*/
   virtual size_t GetSize() = 0;
 
   ///
-  // Removes all values. Returns true on success.
+  /// Removes all values. Returns true on success.
   ///
   /*--cef()--*/
   virtual bool Clear() = 0;
 
   ///
-  // Removes the value at the specified index.
+  /// Removes the value at the specified index.
   ///
   /*--cef()--*/
   virtual bool Remove(size_t index) = 0;
 
   ///
-  // Returns the value type at the specified index.
+  /// Returns the value type at the specified index.
   ///
   /*--cef(default_retval=VTYPE_INVALID)--*/
   virtual CefValueType GetType(size_t index) = 0;
 
   ///
-  // Returns the value at the specified index. For simple types the returned
-  // value will copy existing data and modifications to the value will not
-  // modify this object. For complex types (binary, dictionary and list) the
-  // returned value will reference existing data and modifications to the value
-  // will modify this object.
+  /// Returns the value at the specified index. For simple types the returned
+  /// value will copy existing data and modifications to the value will not
+  /// modify this object. For complex types (binary, dictionary and list) the
+  /// returned value will reference existing data and modifications to the value
+  /// will modify this object.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefValue> GetValue(size_t index) = 0;
 
   ///
-  // Returns the value at the specified index as type bool.
+  /// Returns the value at the specified index as type bool.
   ///
   /*--cef()--*/
   virtual bool GetBool(size_t index) = 0;
 
   ///
-  // Returns the value at the specified index as type int.
+  /// Returns the value at the specified index as type int.
   ///
   /*--cef()--*/
   virtual int GetInt(size_t index) = 0;
 
   ///
-  // Returns the value at the specified index as type double.
+  /// Returns the value at the specified index as type double.
   ///
   /*--cef()--*/
   virtual double GetDouble(size_t index) = 0;
 
   ///
-  // Returns the value at the specified index as type string.
+  /// Returns the value at the specified index as type string.
   ///
   /*--cef()--*/
   virtual CefString GetString(size_t index) = 0;
 
   ///
-  // Returns the value at the specified index as type binary. The returned
-  // value will reference existing data.
+  /// Returns the value at the specified index as type binary. The returned
+  /// value will reference existing data.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBinaryValue> GetBinary(size_t index) = 0;
 
   ///
-  // Returns the value at the specified index as type dictionary. The returned
-  // value will reference existing data and modifications to the value will
-  // modify this object.
+  /// Returns the value at the specified index as type dictionary. The returned
+  /// value will reference existing data and modifications to the value will
+  /// modify this object.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDictionaryValue> GetDictionary(size_t index) = 0;
 
   ///
-  // Returns the value at the specified index as type list. The returned
-  // value will reference existing data and modifications to the value will
-  // modify this object.
+  /// Returns the value at the specified index as type list. The returned
+  /// value will reference existing data and modifications to the value will
+  /// modify this object.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefListValue> GetList(size_t index) = 0;
 
   ///
-  // Sets the value at the specified index. Returns true if the value was set
-  // successfully. If |value| represents simple data then the underlying data
-  // will be copied and modifications to |value| will not modify this object. If
-  // |value| represents complex data (binary, dictionary or list) then the
-  // underlying data will be referenced and modifications to |value| will modify
-  // this object.
+  /// Sets the value at the specified index. Returns true if the value was set
+  /// successfully. If |value| represents simple data then the underlying data
+  /// will be copied and modifications to |value| will not modify this object.
+  /// If |value| represents complex data (binary, dictionary or list) then the
+  /// underlying data will be referenced and modifications to |value| will
+  /// modify this object.
   ///
   /*--cef()--*/
   virtual bool SetValue(size_t index, CefRefPtr<CefValue> value) = 0;
 
   ///
-  // Sets the value at the specified index as type null. Returns true if the
-  // value was set successfully.
+  /// Sets the value at the specified index as type null. Returns true if the
+  /// value was set successfully.
   ///
   /*--cef()--*/
   virtual bool SetNull(size_t index) = 0;
 
   ///
-  // Sets the value at the specified index as type bool. Returns true if the
-  // value was set successfully.
+  /// Sets the value at the specified index as type bool. Returns true if the
+  /// value was set successfully.
   ///
   /*--cef()--*/
   virtual bool SetBool(size_t index, bool value) = 0;
 
   ///
-  // Sets the value at the specified index as type int. Returns true if the
-  // value was set successfully.
+  /// Sets the value at the specified index as type int. Returns true if the
+  /// value was set successfully.
   ///
   /*--cef()--*/
   virtual bool SetInt(size_t index, int value) = 0;
 
   ///
-  // Sets the value at the specified index as type double. Returns true if the
-  // value was set successfully.
+  /// Sets the value at the specified index as type double. Returns true if the
+  /// value was set successfully.
   ///
   /*--cef()--*/
   virtual bool SetDouble(size_t index, double value) = 0;
 
   ///
-  // Sets the value at the specified index as type string. Returns true if the
-  // value was set successfully.
+  /// Sets the value at the specified index as type string. Returns true if the
+  /// value was set successfully.
   ///
   /*--cef(optional_param=value)--*/
   virtual bool SetString(size_t index, const CefString& value) = 0;
 
   ///
-  // Sets the value at the specified index as type binary. Returns true if the
-  // value was set successfully. If |value| is currently owned by another object
-  // then the value will be copied and the |value| reference will not change.
-  // Otherwise, ownership will be transferred to this object and the |value|
-  // reference will be invalidated.
+  /// Sets the value at the specified index as type binary. Returns true if the
+  /// value was set successfully. If |value| is currently owned by another
+  /// object then the value will be copied and the |value| reference will not
+  /// change. Otherwise, ownership will be transferred to this object and the
+  /// |value| reference will be invalidated.
   ///
   /*--cef()--*/
   virtual bool SetBinary(size_t index, CefRefPtr<CefBinaryValue> value) = 0;
 
   ///
-  // Sets the value at the specified index as type dict. Returns true if the
-  // value was set successfully. If |value| is currently owned by another object
-  // then the value will be copied and the |value| reference will not change.
-  // Otherwise, ownership will be transferred to this object and the |value|
-  // reference will be invalidated.
+  /// Sets the value at the specified index as type dict. Returns true if the
+  /// value was set successfully. If |value| is currently owned by another
+  /// object then the value will be copied and the |value| reference will not
+  /// change. Otherwise, ownership will be transferred to this object and the
+  /// |value| reference will be invalidated.
   ///
   /*--cef()--*/
   virtual bool SetDictionary(size_t index,
                              CefRefPtr<CefDictionaryValue> value) = 0;
 
   ///
-  // Sets the value at the specified index as type list. Returns true if the
-  // value was set successfully. If |value| is currently owned by another object
-  // then the value will be copied and the |value| reference will not change.
-  // Otherwise, ownership will be transferred to this object and the |value|
-  // reference will be invalidated.
+  /// Sets the value at the specified index as type list. Returns true if the
+  /// value was set successfully. If |value| is currently owned by another
+  /// object then the value will be copied and the |value| reference will not
+  /// change. Otherwise, ownership will be transferred to this object and the
+  /// |value| reference will be invalidated.
   ///
   /*--cef()--*/
   virtual bool SetList(size_t index, CefRefPtr<CefListValue> value) = 0;
diff --git a/src/include/cef_waitable_event.h b/src/include/cef_waitable_event.h
index d89371e..fa9a938 100644
--- a/src/include/cef_waitable_event.h
+++ b/src/include/cef_waitable_event.h
@@ -41,25 +41,25 @@
 #include "include/cef_base.h"
 
 ///
-// WaitableEvent is a thread synchronization tool that allows one thread to wait
-// for another thread to finish some work. This is equivalent to using a
-// Lock+ConditionVariable to protect a simple boolean value. However, using
-// WaitableEvent in conjunction with a Lock to wait for a more complex state
-// change (e.g., for an item to be added to a queue) is not recommended. In that
-// case consider using a ConditionVariable instead of a WaitableEvent. It is
-// safe to create and/or signal a WaitableEvent from any thread. Blocking on a
-// WaitableEvent by calling the *Wait() methods is not allowed on the browser
-// process UI or IO threads.
+/// WaitableEvent is a thread synchronization tool that allows one thread to
+/// wait for another thread to finish some work. This is equivalent to using a
+/// Lock+ConditionVariable to protect a simple boolean value. However, using
+/// WaitableEvent in conjunction with a Lock to wait for a more complex state
+/// change (e.g., for an item to be added to a queue) is not recommended. In
+/// that case consider using a ConditionVariable instead of a WaitableEvent. It
+/// is safe to create and/or signal a WaitableEvent from any thread. Blocking on
+/// a WaitableEvent by calling the *Wait() methods is not allowed on the browser
+/// process UI or IO threads.
 ///
 /*--cef(source=library)--*/
 class CefWaitableEvent : public CefBaseRefCounted {
  public:
   ///
-  // Create a new waitable event. If |automatic_reset| is true then the event
-  // state is automatically reset to un-signaled after a single waiting thread
-  // has been released; otherwise, the state remains signaled until Reset() is
-  // called manually. If |initially_signaled| is true then the event will start
-  // in the signaled state.
+  /// Create a new waitable event. If |automatic_reset| is true then the event
+  /// state is automatically reset to un-signaled after a single waiting thread
+  /// has been released; otherwise, the state remains signaled until Reset() is
+  /// called manually. If |initially_signaled| is true then the event will start
+  /// in the signaled state.
   ///
   /*--cef()--*/
   static CefRefPtr<CefWaitableEvent> CreateWaitableEvent(
@@ -67,43 +67,43 @@
       bool initially_signaled);
 
   ///
-  // Put the event in the un-signaled state.
+  /// Put the event in the un-signaled state.
   ///
   /*--cef()--*/
   virtual void Reset() = 0;
 
   ///
-  // Put the event in the signaled state. This causes any thread blocked on Wait
-  // to be woken up.
+  /// Put the event in the signaled state. This causes any thread blocked on
+  /// Wait to be woken up.
   ///
   /*--cef()--*/
   virtual void Signal() = 0;
 
   ///
-  // Returns true if the event is in the signaled state, else false. If the
-  // event was created with |automatic_reset| set to true then calling this
-  // method will also cause a reset.
+  /// Returns true if the event is in the signaled state, else false. If the
+  /// event was created with |automatic_reset| set to true then calling this
+  /// method will also cause a reset.
   ///
   /*--cef()--*/
   virtual bool IsSignaled() = 0;
 
   ///
-  // Wait indefinitely for the event to be signaled. This method will not return
-  // until after the call to Signal() has completed. This method cannot be
-  // called on the browser process UI or IO threads.
+  /// Wait indefinitely for the event to be signaled. This method will not
+  /// return until after the call to Signal() has completed. This method cannot
+  /// be called on the browser process UI or IO threads.
   ///
   /*--cef()--*/
   virtual void Wait() = 0;
 
   ///
-  // Wait up to |max_ms| milliseconds for the event to be signaled. Returns true
-  // if the event was signaled. A return value of false does not necessarily
-  // mean that |max_ms| was exceeded. This method will not return until after
-  // the call to Signal() has completed. This method cannot be called on the
-  // browser process UI or IO threads.
+  /// Wait up to |max_ms| milliseconds for the event to be signaled. Returns
+  /// true if the event was signaled. A return value of false does not
+  /// necessarily mean that |max_ms| was exceeded. This method will not return
+  /// until after the call to Signal() has completed. This method cannot be
+  /// called on the browser process UI or IO threads.
   ///
   /*--cef()--*/
-  virtual bool TimedWait(int64 max_ms) = 0;
+  virtual bool TimedWait(int64_t max_ms) = 0;
 };
 
 #endif  // CEF_INCLUDE_CEF_WAITABLE_EVENT_H_
diff --git a/src/include/cef_web_plugin.h b/src/include/cef_web_plugin.h
deleted file mode 100644
index 118788b..0000000
--- a/src/include/cef_web_plugin.h
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the name Chromium Embedded
-// Framework nor the names of its contributors may be used to endorse
-// or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// ---------------------------------------------------------------------------
-//
-// The contents of this file must follow a specific format in order to
-// support the CEF translator tool. See the translator.README.txt file in the
-// tools directory for more information.
-//
-
-#ifndef CEF_INCLUDE_CEF_WEB_PLUGIN_H_
-#define CEF_INCLUDE_CEF_WEB_PLUGIN_H_
-
-#include "include/cef_base.h"
-
-class CefBrowser;
-
-///
-// Information about a specific web plugin.
-///
-/*--cef(source=library)--*/
-class CefWebPluginInfo : public virtual CefBaseRefCounted {
- public:
-  ///
-  // Returns the plugin name (i.e. Flash).
-  ///
-  /*--cef()--*/
-  virtual CefString GetName() = 0;
-
-  ///
-  // Returns the plugin file path (DLL/bundle/library).
-  ///
-  /*--cef()--*/
-  virtual CefString GetPath() = 0;
-
-  ///
-  // Returns the version of the plugin (may be OS-specific).
-  ///
-  /*--cef()--*/
-  virtual CefString GetVersion() = 0;
-
-  ///
-  // Returns a description of the plugin from the version information.
-  ///
-  /*--cef()--*/
-  virtual CefString GetDescription() = 0;
-};
-
-///
-// Interface to implement for visiting web plugin information. The methods of
-// this class will be called on the browser process UI thread.
-///
-/*--cef(source=client)--*/
-class CefWebPluginInfoVisitor : public virtual CefBaseRefCounted {
- public:
-  ///
-  // Method that will be called once for each plugin. |count| is the 0-based
-  // index for the current plugin. |total| is the total number of plugins.
-  // Return false to stop visiting plugins. This method may never be called if
-  // no plugins are found.
-  ///
-  /*--cef()--*/
-  virtual bool Visit(CefRefPtr<CefWebPluginInfo> info,
-                     int count,
-                     int total) = 0;
-};
-
-///
-// Visit web plugin information. Can be called on any thread in the browser
-// process.
-///
-/*--cef()--*/
-void CefVisitWebPluginInfo(CefRefPtr<CefWebPluginInfoVisitor> visitor);
-
-///
-// Cause the plugin list to refresh the next time it is accessed regardless
-// of whether it has already been loaded. Can be called on any thread in the
-// browser process.
-///
-/*--cef()--*/
-void CefRefreshWebPlugins();
-
-///
-// Unregister an internal plugin. This may be undone the next time
-// CefRefreshWebPlugins() is called. Can be called on any thread in the browser
-// process.
-///
-/*--cef()--*/
-void CefUnregisterInternalWebPlugin(const CefString& path);
-
-///
-// Register a plugin crash. Can be called on any thread in the browser process
-// but will be executed on the IO thread.
-///
-/*--cef()--*/
-void CefRegisterWebPluginCrash(const CefString& path);
-
-///
-// Interface to implement for receiving unstable plugin information. The methods
-// of this class will be called on the browser process IO thread.
-///
-/*--cef(source=client)--*/
-class CefWebPluginUnstableCallback : public virtual CefBaseRefCounted {
- public:
-  ///
-  // Method that will be called for the requested plugin. |unstable| will be
-  // true if the plugin has reached the crash count threshold of 3 times in 120
-  // seconds.
-  ///
-  /*--cef()--*/
-  virtual void IsUnstable(const CefString& path, bool unstable) = 0;
-};
-
-///
-// Query if a plugin is unstable. Can be called on any thread in the browser
-// process.
-///
-/*--cef()--*/
-void CefIsWebPluginUnstable(const CefString& path,
-                            CefRefPtr<CefWebPluginUnstableCallback> callback);
-
-///
-// Implement this interface to receive notification when CDM registration is
-// complete. The methods of this class will be called on the browser process
-// UI thread.
-///
-/*--cef(source=client)--*/
-class CefRegisterCdmCallback : public virtual CefBaseRefCounted {
- public:
-  ///
-  // Method that will be called when CDM registration is complete. |result|
-  // will be CEF_CDM_REGISTRATION_ERROR_NONE if registration completed
-  // successfully. Otherwise, |result| and |error_message| will contain
-  // additional information about why registration failed.
-  ///
-  /*--cef(optional_param=error_message)--*/
-  virtual void OnCdmRegistrationComplete(cef_cdm_registration_error_t result,
-                                         const CefString& error_message) = 0;
-};
-
-///
-// Register the Widevine CDM plugin.
-//
-// The client application is responsible for downloading an appropriate
-// platform-specific CDM binary distribution from Google, extracting the
-// contents, and building the required directory structure on the local machine.
-// The CefBrowserHost::StartDownload method and CefZipArchive class can be used
-// to implement this functionality in CEF. Contact Google via
-// https://www.widevine.com/contact.html for details on CDM download.
-//
-// |path| is a directory that must contain the following files:
-//   1. manifest.json file from the CDM binary distribution (see below).
-//   2. widevinecdm file from the CDM binary distribution (e.g.
-//      widevinecdm.dll on on Windows, libwidevinecdm.dylib on OS X,
-//      libwidevinecdm.so on Linux).
-//
-// If any of these files are missing or if the manifest file has incorrect
-// contents the registration will fail and |callback| will receive a |result|
-// value of CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS.
-//
-// The manifest.json file must contain the following keys:
-//   A. "os": Supported OS (e.g. "mac", "win" or "linux").
-//   B. "arch": Supported architecture (e.g. "ia32" or "x64").
-//   C. "x-cdm-module-versions": Module API version (e.g. "4").
-//   D. "x-cdm-interface-versions": Interface API version (e.g. "8").
-//   E. "x-cdm-host-versions": Host API version (e.g. "8").
-//   F. "version": CDM version (e.g. "1.4.8.903").
-//   G. "x-cdm-codecs": List of supported codecs (e.g. "vp8,vp9.0,avc1").
-//
-// A through E are used to verify compatibility with the current Chromium
-// version. If the CDM is not compatible the registration will fail and
-// |callback| will receive a |result| value of
-// CEF_CDM_REGISTRATION_ERROR_INCOMPATIBLE.
-//
-// |callback| will be executed asynchronously once registration is complete.
-//
-// On Linux this function must be called before CefInitialize() and the
-// registration cannot be changed during runtime. If registration is not
-// supported at the time that CefRegisterWidevineCdm() is called then |callback|
-// will receive a |result| value of CEF_CDM_REGISTRATION_ERROR_NOT_SUPPORTED.
-///
-/*--cef(optional_param=callback)--*/
-void CefRegisterWidevineCdm(const CefString& path,
-                            CefRefPtr<CefRegisterCdmCallback> callback);
-
-#endif  // CEF_INCLUDE_CEF_WEB_PLUGIN_H_
diff --git a/src/include/cef_x509_certificate.h b/src/include/cef_x509_certificate.h
index b466a6a..68ae752 100644
--- a/src/include/cef_x509_certificate.h
+++ b/src/include/cef_x509_certificate.h
@@ -44,70 +44,58 @@
 #include "include/cef_values.h"
 
 ///
-// Class representing the issuer or subject field of an X.509 certificate.
+/// Class representing the issuer or subject field of an X.509 certificate.
 ///
 /*--cef(source=library)--*/
 class CefX509CertPrincipal : public virtual CefBaseRefCounted {
  public:
   ///
-  // Returns a name that can be used to represent the issuer. It tries in this
-  // order: Common Name (CN), Organization Name (O) and Organizational Unit
-  // Name (OU) and returns the first non-empty one found.
+  /// Returns a name that can be used to represent the issuer. It tries in this
+  /// order: Common Name (CN), Organization Name (O) and Organizational Unit
+  /// Name (OU) and returns the first non-empty one found.
   ///
   /*--cef()--*/
   virtual CefString GetDisplayName() = 0;
 
   ///
-  // Returns the common name.
+  /// Returns the common name.
   ///
   /*--cef()--*/
   virtual CefString GetCommonName() = 0;
 
   ///
-  // Returns the locality name.
+  /// Returns the locality name.
   ///
   /*--cef()--*/
   virtual CefString GetLocalityName() = 0;
 
   ///
-  // Returns the state or province name.
+  /// Returns the state or province name.
   ///
   /*--cef()--*/
   virtual CefString GetStateOrProvinceName() = 0;
 
   ///
-  // Returns the country name.
+  /// Returns the country name.
   ///
   /*--cef()--*/
   virtual CefString GetCountryName() = 0;
 
   ///
-  // Retrieve the list of street addresses.
-  ///
-  /*--cef()--*/
-  virtual void GetStreetAddresses(std::vector<CefString>& addresses) = 0;
-
-  ///
-  // Retrieve the list of organization names.
+  /// Retrieve the list of organization names.
   ///
   /*--cef()--*/
   virtual void GetOrganizationNames(std::vector<CefString>& names) = 0;
 
   ///
-  // Retrieve the list of organization unit names.
+  /// Retrieve the list of organization unit names.
   ///
   /*--cef()--*/
   virtual void GetOrganizationUnitNames(std::vector<CefString>& names) = 0;
-
-  ///
-  // Retrieve the list of domain components.
-  ///
-  /*--cef()--*/
-  virtual void GetDomainComponents(std::vector<CefString>& components) = 0;
 };
 
 ///
-// Class representing a X.509 certificate.
+/// Class representing a X.509 certificate.
 ///
 /*--cef(source=library)--*/
 class CefX509Certificate : public virtual CefBaseRefCounted {
@@ -115,71 +103,71 @@
   typedef std::vector<CefRefPtr<CefBinaryValue>> IssuerChainBinaryList;
 
   ///
-  // Returns the subject of the X.509 certificate. For HTTPS server
-  // certificates this represents the web server.  The common name of the
-  // subject should match the host name of the web server.
+  /// Returns the subject of the X.509 certificate. For HTTPS server
+  /// certificates this represents the web server.  The common name of the
+  /// subject should match the host name of the web server.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefX509CertPrincipal> GetSubject() = 0;
 
   ///
-  // Returns the issuer of the X.509 certificate.
+  /// Returns the issuer of the X.509 certificate.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefX509CertPrincipal> GetIssuer() = 0;
 
   ///
-  // Returns the DER encoded serial number for the X.509 certificate. The value
-  // possibly includes a leading 00 byte.
+  /// Returns the DER encoded serial number for the X.509 certificate. The value
+  /// possibly includes a leading 00 byte.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBinaryValue> GetSerialNumber() = 0;
 
   ///
-  // Returns the date before which the X.509 certificate is invalid.
-  // CefTime.GetTimeT() will return 0 if no date was specified.
+  /// Returns the date before which the X.509 certificate is invalid.
+  /// CefBaseTime.GetTimeT() will return 0 if no date was specified.
   ///
   /*--cef()--*/
-  virtual CefTime GetValidStart() = 0;
+  virtual CefBaseTime GetValidStart() = 0;
 
   ///
-  // Returns the date after which the X.509 certificate is invalid.
-  // CefTime.GetTimeT() will return 0 if no date was specified.
+  /// Returns the date after which the X.509 certificate is invalid.
+  /// CefBaseTime.GetTimeT() will return 0 if no date was specified.
   ///
   /*--cef()--*/
-  virtual CefTime GetValidExpiry() = 0;
+  virtual CefBaseTime GetValidExpiry() = 0;
 
   ///
-  // Returns the DER encoded data for the X.509 certificate.
+  /// Returns the DER encoded data for the X.509 certificate.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBinaryValue> GetDEREncoded() = 0;
 
   ///
-  // Returns the PEM encoded data for the X.509 certificate.
+  /// Returns the PEM encoded data for the X.509 certificate.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBinaryValue> GetPEMEncoded() = 0;
 
   ///
-  // Returns the number of certificates in the issuer chain.
-  // If 0, the certificate is self-signed.
+  /// Returns the number of certificates in the issuer chain.
+  /// If 0, the certificate is self-signed.
   ///
   /*--cef()--*/
   virtual size_t GetIssuerChainSize() = 0;
 
   ///
-  // Returns the DER encoded data for the certificate issuer chain.
-  // If we failed to encode a certificate in the chain it is still
-  // present in the array but is an empty string.
+  /// Returns the DER encoded data for the certificate issuer chain.
+  /// If we failed to encode a certificate in the chain it is still
+  /// present in the array but is an empty string.
   ///
   /*--cef(count_func=chain:GetIssuerChainSize)--*/
   virtual void GetDEREncodedIssuerChain(IssuerChainBinaryList& chain) = 0;
 
   ///
-  // Returns the PEM encoded data for the certificate issuer chain.
-  // If we failed to encode a certificate in the chain it is still
-  // present in the array but is an empty string.
+  /// Returns the PEM encoded data for the certificate issuer chain.
+  /// If we failed to encode a certificate in the chain it is still
+  /// present in the array but is an empty string.
   ///
   /*--cef(count_func=chain:GetIssuerChainSize)--*/
   virtual void GetPEMEncodedIssuerChain(IssuerChainBinaryList& chain) = 0;
diff --git a/src/include/cef_xml_reader.h b/src/include/cef_xml_reader.h
index 5269ef5..055d522 100644
--- a/src/include/cef_xml_reader.h
+++ b/src/include/cef_xml_reader.h
@@ -42,9 +42,9 @@
 #include "include/cef_stream.h"
 
 ///
-// Class that supports the reading of XML data via the libxml streaming API.
-// The methods of this class should only be called on the thread that creates
-// the object.
+/// Class that supports the reading of XML data via the libxml streaming API.
+/// The methods of this class should only be called on the thread that creates
+/// the object.
 ///
 /*--cef(source=library)--*/
 class CefXmlReader : public virtual CefBaseRefCounted {
@@ -53,8 +53,8 @@
   typedef cef_xml_node_type_t NodeType;
 
   ///
-  // Create a new CefXmlReader object. The returned object's methods can only
-  // be called from the thread that created the object.
+  /// Create a new CefXmlReader object. The returned object's methods can only
+  /// be called from the thread that created the object.
   ///
   /*--cef()--*/
   static CefRefPtr<CefXmlReader> Create(CefRefPtr<CefStreamReader> stream,
@@ -62,202 +62,202 @@
                                         const CefString& URI);
 
   ///
-  // Moves the cursor to the next node in the document. This method must be
-  // called at least once to set the current cursor position. Returns true if
-  // the cursor position was set successfully.
+  /// Moves the cursor to the next node in the document. This method must be
+  /// called at least once to set the current cursor position. Returns true if
+  /// the cursor position was set successfully.
   ///
   /*--cef()--*/
   virtual bool MoveToNextNode() = 0;
 
   ///
-  // Close the document. This should be called directly to ensure that cleanup
-  // occurs on the correct thread.
+  /// Close the document. This should be called directly to ensure that cleanup
+  /// occurs on the correct thread.
   ///
   /*--cef()--*/
   virtual bool Close() = 0;
 
   ///
-  // Returns true if an error has been reported by the XML parser.
+  /// Returns true if an error has been reported by the XML parser.
   ///
   /*--cef()--*/
   virtual bool HasError() = 0;
 
   ///
-  // Returns the error string.
+  /// Returns the error string.
   ///
   /*--cef()--*/
   virtual CefString GetError() = 0;
 
-  // The below methods retrieve data for the node at the current cursor
-  // position.
+  /// The below methods retrieve data for the node at the current cursor
+  /// position.
 
   ///
-  // Returns the node type.
+  /// Returns the node type.
   ///
   /*--cef(default_retval=XML_NODE_UNSUPPORTED)--*/
   virtual NodeType GetType() = 0;
 
   ///
-  // Returns the node depth. Depth starts at 0 for the root node.
+  /// Returns the node depth. Depth starts at 0 for the root node.
   ///
   /*--cef()--*/
   virtual int GetDepth() = 0;
 
   ///
-  // Returns the local name. See
-  // http://www.w3.org/TR/REC-xml-names/#NT-LocalPart for additional details.
+  /// Returns the local name. See
+  /// http://www.w3.org/TR/REC-xml-names/#NT-LocalPart for additional details.
   ///
   /*--cef()--*/
   virtual CefString GetLocalName() = 0;
 
   ///
-  // Returns the namespace prefix. See http://www.w3.org/TR/REC-xml-names/ for
-  // additional details.
+  /// Returns the namespace prefix. See http://www.w3.org/TR/REC-xml-names/ for
+  /// additional details.
   ///
   /*--cef()--*/
   virtual CefString GetPrefix() = 0;
 
   ///
-  // Returns the qualified name, equal to (Prefix:)LocalName. See
-  // http://www.w3.org/TR/REC-xml-names/#ns-qualnames for additional details.
+  /// Returns the qualified name, equal to (Prefix:)LocalName. See
+  /// http://www.w3.org/TR/REC-xml-names/#ns-qualnames for additional details.
   ///
   /*--cef()--*/
   virtual CefString GetQualifiedName() = 0;
 
   ///
-  // Returns the URI defining the namespace associated with the node. See
-  // http://www.w3.org/TR/REC-xml-names/ for additional details.
+  /// Returns the URI defining the namespace associated with the node. See
+  /// http://www.w3.org/TR/REC-xml-names/ for additional details.
   ///
   /*--cef()--*/
   virtual CefString GetNamespaceURI() = 0;
 
   ///
-  // Returns the base URI of the node. See http://www.w3.org/TR/xmlbase/ for
-  // additional details.
+  /// Returns the base URI of the node. See http://www.w3.org/TR/xmlbase/ for
+  /// additional details.
   ///
   /*--cef()--*/
   virtual CefString GetBaseURI() = 0;
 
   ///
-  // Returns the xml:lang scope within which the node resides. See
-  // http://www.w3.org/TR/REC-xml/#sec-lang-tag for additional details.
+  /// Returns the xml:lang scope within which the node resides. See
+  /// http://www.w3.org/TR/REC-xml/#sec-lang-tag for additional details.
   ///
   /*--cef()--*/
   virtual CefString GetXmlLang() = 0;
 
   ///
-  // Returns true if the node represents an empty element. <a/> is considered
-  // empty but <a></a> is not.
+  /// Returns true if the node represents an empty element. "<a/>" is considered
+  /// empty but "<a></a>" is not.
   ///
   /*--cef()--*/
   virtual bool IsEmptyElement() = 0;
 
   ///
-  // Returns true if the node has a text value.
+  /// Returns true if the node has a text value.
   ///
   /*--cef()--*/
   virtual bool HasValue() = 0;
 
   ///
-  // Returns the text value.
+  /// Returns the text value.
   ///
   /*--cef()--*/
   virtual CefString GetValue() = 0;
 
   ///
-  // Returns true if the node has attributes.
+  /// Returns true if the node has attributes.
   ///
   /*--cef()--*/
   virtual bool HasAttributes() = 0;
 
   ///
-  // Returns the number of attributes.
+  /// Returns the number of attributes.
   ///
   /*--cef()--*/
   virtual size_t GetAttributeCount() = 0;
 
   ///
-  // Returns the value of the attribute at the specified 0-based index.
+  /// Returns the value of the attribute at the specified 0-based index.
   ///
   /*--cef(capi_name=get_attribute_byindex,index_param=index)--*/
   virtual CefString GetAttribute(int index) = 0;
 
   ///
-  // Returns the value of the attribute with the specified qualified name.
+  /// Returns the value of the attribute with the specified qualified name.
   ///
   /*--cef(capi_name=get_attribute_byqname)--*/
   virtual CefString GetAttribute(const CefString& qualifiedName) = 0;
 
   ///
-  // Returns the value of the attribute with the specified local name and
-  // namespace URI.
+  /// Returns the value of the attribute with the specified local name and
+  /// namespace URI.
   ///
   /*--cef(capi_name=get_attribute_bylname)--*/
   virtual CefString GetAttribute(const CefString& localName,
                                  const CefString& namespaceURI) = 0;
 
   ///
-  // Returns an XML representation of the current node's children.
+  /// Returns an XML representation of the current node's children.
   ///
   /*--cef()--*/
   virtual CefString GetInnerXml() = 0;
 
   ///
-  // Returns an XML representation of the current node including its children.
+  /// Returns an XML representation of the current node including its children.
   ///
   /*--cef()--*/
   virtual CefString GetOuterXml() = 0;
 
   ///
-  // Returns the line number for the current node.
+  /// Returns the line number for the current node.
   ///
   /*--cef()--*/
   virtual int GetLineNumber() = 0;
 
-  // Attribute nodes are not traversed by default. The below methods can be
-  // used to move the cursor to an attribute node. MoveToCarryingElement() can
-  // be called afterwards to return the cursor to the carrying element. The
-  // depth of an attribute node will be 1 + the depth of the carrying element.
+  /// Attribute nodes are not traversed by default. The below methods can be
+  /// used to move the cursor to an attribute node. MoveToCarryingElement() can
+  /// be called afterwards to return the cursor to the carrying element. The
+  /// depth of an attribute node will be 1 + the depth of the carrying element.
 
   ///
-  // Moves the cursor to the attribute at the specified 0-based index. Returns
-  // true if the cursor position was set successfully.
+  /// Moves the cursor to the attribute at the specified 0-based index. Returns
+  /// true if the cursor position was set successfully.
   ///
   /*--cef(capi_name=move_to_attribute_byindex,index_param=index)--*/
   virtual bool MoveToAttribute(int index) = 0;
 
   ///
-  // Moves the cursor to the attribute with the specified qualified name.
-  // Returns true if the cursor position was set successfully.
+  /// Moves the cursor to the attribute with the specified qualified name.
+  /// Returns true if the cursor position was set successfully.
   ///
   /*--cef(capi_name=move_to_attribute_byqname)--*/
   virtual bool MoveToAttribute(const CefString& qualifiedName) = 0;
 
   ///
-  // Moves the cursor to the attribute with the specified local name and
-  // namespace URI. Returns true if the cursor position was set successfully.
+  /// Moves the cursor to the attribute with the specified local name and
+  /// namespace URI. Returns true if the cursor position was set successfully.
   ///
   /*--cef(capi_name=move_to_attribute_bylname)--*/
   virtual bool MoveToAttribute(const CefString& localName,
                                const CefString& namespaceURI) = 0;
 
   ///
-  // Moves the cursor to the first attribute in the current element. Returns
-  // true if the cursor position was set successfully.
+  /// Moves the cursor to the first attribute in the current element. Returns
+  /// true if the cursor position was set successfully.
   ///
   /*--cef()--*/
   virtual bool MoveToFirstAttribute() = 0;
 
   ///
-  // Moves the cursor to the next attribute in the current element. Returns
-  // true if the cursor position was set successfully.
+  /// Moves the cursor to the next attribute in the current element. Returns
+  /// true if the cursor position was set successfully.
   ///
   /*--cef()--*/
   virtual bool MoveToNextAttribute() = 0;
 
   ///
-  // Moves the cursor back to the carrying element. Returns true if the cursor
-  // position was set successfully.
+  /// Moves the cursor back to the carrying element. Returns true if the cursor
+  /// position was set successfully.
   ///
   /*--cef()--*/
   virtual bool MoveToCarryingElement() = 0;
diff --git a/src/include/cef_zip_reader.h b/src/include/cef_zip_reader.h
index 5dc2efd..9aa5e9b 100644
--- a/src/include/cef_zip_reader.h
+++ b/src/include/cef_zip_reader.h
@@ -41,97 +41,97 @@
 #include "include/cef_stream.h"
 
 ///
-// Class that supports the reading of zip archives via the zlib unzip API.
-// The methods of this class should only be called on the thread that creates
-// the object.
+/// Class that supports the reading of zip archives via the zlib unzip API.
+/// The methods of this class should only be called on the thread that creates
+/// the object.
 ///
 /*--cef(source=library)--*/
 class CefZipReader : public virtual CefBaseRefCounted {
  public:
   ///
-  // Create a new CefZipReader object. The returned object's methods can only
-  // be called from the thread that created the object.
+  /// Create a new CefZipReader object. The returned object's methods can only
+  /// be called from the thread that created the object.
   ///
   /*--cef()--*/
   static CefRefPtr<CefZipReader> Create(CefRefPtr<CefStreamReader> stream);
 
   ///
-  // Moves the cursor to the first file in the archive. Returns true if the
-  // cursor position was set successfully.
+  /// Moves the cursor to the first file in the archive. Returns true if the
+  /// cursor position was set successfully.
   ///
   /*--cef()--*/
   virtual bool MoveToFirstFile() = 0;
 
   ///
-  // Moves the cursor to the next file in the archive. Returns true if the
-  // cursor position was set successfully.
+  /// Moves the cursor to the next file in the archive. Returns true if the
+  /// cursor position was set successfully.
   ///
   /*--cef()--*/
   virtual bool MoveToNextFile() = 0;
 
   ///
-  // Moves the cursor to the specified file in the archive. If |caseSensitive|
-  // is true then the search will be case sensitive. Returns true if the cursor
-  // position was set successfully.
+  /// Moves the cursor to the specified file in the archive. If |caseSensitive|
+  /// is true then the search will be case sensitive. Returns true if the cursor
+  /// position was set successfully.
   ///
   /*--cef()--*/
   virtual bool MoveToFile(const CefString& fileName, bool caseSensitive) = 0;
 
   ///
-  // Closes the archive. This should be called directly to ensure that cleanup
-  // occurs on the correct thread.
+  /// Closes the archive. This should be called directly to ensure that cleanup
+  /// occurs on the correct thread.
   ///
   /*--cef()--*/
   virtual bool Close() = 0;
 
-  // The below methods act on the file at the current cursor position.
+  /// The below methods act on the file at the current cursor position.
 
   ///
-  // Returns the name of the file.
+  /// Returns the name of the file.
   ///
   /*--cef()--*/
   virtual CefString GetFileName() = 0;
 
   ///
-  // Returns the uncompressed size of the file.
+  /// Returns the uncompressed size of the file.
   ///
   /*--cef()--*/
-  virtual int64 GetFileSize() = 0;
+  virtual int64_t GetFileSize() = 0;
 
   ///
-  // Returns the last modified timestamp for the file.
+  /// Returns the last modified timestamp for the file.
   ///
   /*--cef()--*/
-  virtual CefTime GetFileLastModified() = 0;
+  virtual CefBaseTime GetFileLastModified() = 0;
 
   ///
-  // Opens the file for reading of uncompressed data. A read password may
-  // optionally be specified.
+  /// Opens the file for reading of uncompressed data. A read password may
+  /// optionally be specified.
   ///
   /*--cef(optional_param=password)--*/
   virtual bool OpenFile(const CefString& password) = 0;
 
   ///
-  // Closes the file.
+  /// Closes the file.
   ///
   /*--cef()--*/
   virtual bool CloseFile() = 0;
 
   ///
-  // Read uncompressed file contents into the specified buffer. Returns < 0 if
-  // an error occurred, 0 if at the end of file, or the number of bytes read.
+  /// Read uncompressed file contents into the specified buffer. Returns < 0 if
+  /// an error occurred, 0 if at the end of file, or the number of bytes read.
   ///
   /*--cef()--*/
   virtual int ReadFile(void* buffer, size_t bufferSize) = 0;
 
   ///
-  // Returns the current offset in the uncompressed file contents.
+  /// Returns the current offset in the uncompressed file contents.
   ///
   /*--cef()--*/
-  virtual int64 Tell() = 0;
+  virtual int64_t Tell() = 0;
 
   ///
-  // Returns true if at end of the file contents.
+  /// Returns true if at end of the file contents.
   ///
   /*--cef()--*/
   virtual bool Eof() = 0;
diff --git a/src/include/internal/cef_app_win.h b/src/include/internal/cef_app_win.h
new file mode 100644
index 0000000..a28d905
--- /dev/null
+++ b/src/include/internal/cef_app_win.h
@@ -0,0 +1,100 @@
+// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CEF_INCLUDE_INTERNAL_CEF_APP_WIN_H_
+#define CEF_INCLUDE_INTERNAL_CEF_APP_WIN_H_
+#pragma once
+
+#include "include/base/cef_build.h"
+
+#if defined(OS_WIN)
+
+#if defined(ARCH_CPU_32_BITS)
+#include <windows.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(ARCH_CPU_32_BITS)
+typedef int(APIENTRY* wWinMainPtr)(HINSTANCE hInstance,
+                                   HINSTANCE hPrevInstance,
+                                   LPWSTR lpCmdLine,
+                                   int nCmdShow);
+typedef int (*mainPtr)(int argc, char* argv[]);
+
+///
+/// Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
+/// stack size. This function must be called at the top of the executable entry
+/// point function (`main()` or `wWinMain()`). It is used in combination with
+/// the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
+/// flag on executable targets. This saves significant memory on threads (like
+/// those in the Windows thread pool, and others) whose stack size can only be
+/// controlled via the linker flag.
+///
+/// CEF's main thread needs at least a 1.5 MiB stack size in order to avoid
+/// stack overflow crashes. However, if this is set in the PE file then other
+/// threads get this size as well, leading to address-space exhaustion in 32-bit
+/// CEF. This function uses fibers to switch the main thread to a 4 MiB stack
+/// (roughly the same effective size as the 64-bit build's 8 MiB stack) before
+/// running any other code.
+///
+/// Choose the function variant that matches the entry point function type used
+/// by the executable. Reusing the entry point minimizes confusion when
+/// examining call stacks in crash reports.
+///
+/// If this function is already running on the fiber it will return -1
+/// immediately, meaning that execution should proceed with the remainder of the
+/// entry point function. Otherwise, this function will block until the entry
+/// point function has completed execution on the fiber and then return a result
+/// >= 0, meaning that the entry point function should return the result
+/// immediately without proceeding with execution.
+///
+CEF_EXPORT int cef_run_winmain_with_preferred_stack_size(wWinMainPtr wWinMain,
+                                                         HINSTANCE hInstance,
+                                                         LPWSTR lpCmdLine,
+                                                         int nCmdShow);
+CEF_EXPORT int cef_run_main_with_preferred_stack_size(mainPtr main,
+                                                      int argc,
+                                                      char* argv[]);
+#endif  // defined(ARCH_CPU_32_BITS)
+
+///
+/// Set to true (1) before calling Windows APIs like TrackPopupMenu that enter a
+/// modal message loop. Set to false (0) after exiting the modal message loop.
+///
+CEF_EXPORT void cef_set_osmodal_loop(int osModalLoop);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // defined(OS_WIN)
+#endif  // CEF_INCLUDE_INTERNAL_CEF_APP_WIN_H_
diff --git a/src/include/internal/cef_linux.h b/src/include/internal/cef_linux.h
index a247d44..cebd7f6 100644
--- a/src/include/internal/cef_linux.h
+++ b/src/include/internal/cef_linux.h
@@ -39,32 +39,15 @@
 #define CefEventHandle cef_event_handle_t
 #define CefWindowHandle cef_window_handle_t
 
-struct CefMainArgsTraits {
-  typedef cef_main_args_t struct_type;
-
-  static inline void init(struct_type* s) {}
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    target->argc = src->argc;
-    target->argv = src->argv;
-  }
-};
-
-// Class representing CefExecuteProcess arguments.
-class CefMainArgs : public CefStructBase<CefMainArgsTraits> {
+///
+/// Class representing CefExecuteProcess arguments.
+///
+class CefMainArgs : public cef_main_args_t {
  public:
-  typedef CefStructBase<CefMainArgsTraits> parent;
-
-  CefMainArgs() : parent() {}
-  explicit CefMainArgs(const cef_main_args_t& r) : parent(r) {}
-  explicit CefMainArgs(const CefMainArgs& r) : parent(r) {}
-  CefMainArgs(int argc_arg, char** argv_arg) : parent() {
-    argc = argc_arg;
-    argv = argv_arg;
-  }
+  CefMainArgs() : cef_main_args_t{} {}
+  CefMainArgs(const cef_main_args_t& r) : cef_main_args_t(r) {}
+  CefMainArgs(int argc_arg, char** argv_arg)
+      : cef_main_args_t{argc_arg, argv_arg} {}
 };
 
 struct CefWindowInfoTraits {
@@ -81,10 +64,7 @@
                          bool copy) {
     cef_string_set(src->window_name.str, src->window_name.length,
                    &target->window_name, copy);
-    target->x = src->x;
-    target->y = src->y;
-    target->width = src->width;
-    target->height = src->height;
+    target->bounds = src->bounds;
     target->parent_window = src->parent_window;
     target->windowless_rendering_enabled = src->windowless_rendering_enabled;
     target->shared_texture_enabled = src->shared_texture_enabled;
@@ -93,7 +73,9 @@
   }
 };
 
-// Class representing window information.
+///
+/// Class representing window information.
+///
 class CefWindowInfo : public CefStructBase<CefWindowInfoTraits> {
  public:
   typedef CefStructBase<CefWindowInfoTraits> parent;
@@ -102,28 +84,28 @@
   explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {}
   explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {}
 
+  CefWindowInfo& operator=(const CefWindowInfo&) = default;
+  CefWindowInfo& operator=(CefWindowInfo&&) = default;
+
   ///
-  // Create the browser as a child window.
+  /// Create the browser as a child window.
   ///
-  void SetAsChild(CefWindowHandle parent, const CefRect& windowRect) {
+  void SetAsChild(CefWindowHandle parent, const CefRect& bounds) {
     parent_window = parent;
-    x = windowRect.x;
-    y = windowRect.y;
-    width = windowRect.width;
-    height = windowRect.height;
+    this->bounds = bounds;
   }
 
   ///
-  // Create the browser using windowless (off-screen) rendering. No window
-  // will be created for the browser and all rendering will occur via the
-  // CefRenderHandler interface. The |parent| value will be used to identify
-  // monitor info and to act as the parent window for dialogs, context menus,
-  // etc. If |parent| is not provided then the main screen monitor will be used
-  // and some functionality that requires a parent window may not function
-  // correctly. In order to create windowless browsers the
-  // CefSettings.windowless_rendering_enabled value must be set to true.
-  // Transparent painting is enabled by default but can be disabled by setting
-  // CefBrowserSettings.background_color to an opaque value.
+  /// Create the browser using windowless (off-screen) rendering. No window
+  /// will be created for the browser and all rendering will occur via the
+  /// CefRenderHandler interface. The |parent| value will be used to identify
+  /// monitor info and to act as the parent window for dialogs, context menus,
+  /// etc. If |parent| is not provided then the main screen monitor will be used
+  /// and some functionality that requires a parent window may not function
+  /// correctly. In order to create windowless browsers the
+  /// CefSettings.windowless_rendering_enabled value must be set to true.
+  /// Transparent painting is enabled by default but can be disabled by setting
+  /// CefBrowserSettings.background_color to an opaque value.
   ///
   void SetAsWindowless(CefWindowHandle parent) {
     windowless_rendering_enabled = true;
diff --git a/src/include/internal/cef_logging_internal.h b/src/include/internal/cef_logging_internal.h
index 598263d..d29cfc8 100644
--- a/src/include/internal/cef_logging_internal.h
+++ b/src/include/internal/cef_logging_internal.h
@@ -42,19 +42,19 @@
 // See include/base/cef_logging.h for macros and intended usage.
 
 ///
-// Gets the current log level.
+/// Gets the current log level.
 ///
-CEF_EXPORT int cef_get_min_log_level();
+CEF_EXPORT int cef_get_min_log_level(void);
 
 ///
-// Gets the current vlog level for the given file (usually taken from
-// __FILE__). Note that |N| is the size *with* the null terminator.
+/// Gets the current vlog level for the given file (usually taken from
+/// __FILE__). Note that |N| is the size *with* the null terminator.
 ///
 CEF_EXPORT int cef_get_vlog_level(const char* file_start, size_t N);
 
 ///
-// Add a log message. See the LogSeverity defines for supported |severity|
-// values.
+/// Add a log message. See the LogSeverity defines for supported |severity|
+/// values.
 ///
 CEF_EXPORT void cef_log(const char* file,
                         int line,
diff --git a/src/include/internal/cef_mac.h b/src/include/internal/cef_mac.h
index 3123fb5..983eda8 100644
--- a/src/include/internal/cef_mac.h
+++ b/src/include/internal/cef_mac.h
@@ -39,32 +39,15 @@
 #define CefEventHandle cef_event_handle_t
 #define CefWindowHandle cef_window_handle_t
 
-struct CefMainArgsTraits {
-  typedef cef_main_args_t struct_type;
-
-  static inline void init(struct_type* s) {}
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    target->argc = src->argc;
-    target->argv = src->argv;
-  }
-};
-
-// Class representing CefExecuteProcess arguments.
-class CefMainArgs : public CefStructBase<CefMainArgsTraits> {
+///
+/// Class representing CefExecuteProcess arguments.
+///
+class CefMainArgs : public cef_main_args_t {
  public:
-  typedef CefStructBase<CefMainArgsTraits> parent;
-
-  CefMainArgs() : parent() {}
-  explicit CefMainArgs(const cef_main_args_t& r) : parent(r) {}
-  explicit CefMainArgs(const CefMainArgs& r) : parent(r) {}
-  CefMainArgs(int argc, char** argv) : parent() {
-    this->argc = argc;
-    this->argv = argv;
-  }
+  CefMainArgs() : cef_main_args_t{} {}
+  CefMainArgs(const cef_main_args_t& r) : cef_main_args_t(r) {}
+  CefMainArgs(int argc_arg, char** argv_arg)
+      : cef_main_args_t{argc_arg, argv_arg} {}
 };
 
 struct CefWindowInfoTraits {
@@ -81,10 +64,7 @@
                          bool copy) {
     cef_string_set(src->window_name.str, src->window_name.length,
                    &target->window_name, copy);
-    target->x = src->x;
-    target->y = src->y;
-    target->width = src->width;
-    target->height = src->height;
+    target->bounds = src->bounds;
     target->hidden = src->hidden;
     target->parent_view = src->parent_view;
     target->windowless_rendering_enabled = src->windowless_rendering_enabled;
@@ -94,7 +74,9 @@
   }
 };
 
-// Class representing window information.
+///
+/// Class representing window information.
+///
 class CefWindowInfo : public CefStructBase<CefWindowInfoTraits> {
  public:
   typedef CefStructBase<CefWindowInfoTraits> parent;
@@ -103,29 +85,29 @@
   explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {}
   explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {}
 
+  CefWindowInfo& operator=(const CefWindowInfo&) = default;
+  CefWindowInfo& operator=(CefWindowInfo&&) = default;
+
   ///
-  // Create the browser as a child view.
+  /// Create the browser as a child view.
   ///
-  void SetAsChild(CefWindowHandle parent, int x, int y, int width, int height) {
+  void SetAsChild(CefWindowHandle parent, const CefRect& bounds) {
     parent_view = parent;
-    this->x = x;
-    this->y = y;
-    this->width = width;
-    this->height = height;
+    this->bounds = bounds;
     hidden = false;
   }
 
   ///
-  // Create the browser using windowless (off-screen) rendering. No view
-  // will be created for the browser and all rendering will occur via the
-  // CefRenderHandler interface. The |parent| value will be used to identify
-  // monitor info and to act as the parent view for dialogs, context menus,
-  // etc. If |parent| is not provided then the main screen monitor will be used
-  // and some functionality that requires a parent view may not function
-  // correctly. In order to create windowless browsers the
-  // CefSettings.windowless_rendering_enabled value must be set to true.
-  // Transparent painting is enabled by default but can be disabled by setting
-  // CefBrowserSettings.background_color to an opaque value.
+  /// Create the browser using windowless (off-screen) rendering. No view
+  /// will be created for the browser and all rendering will occur via the
+  /// CefRenderHandler interface. The |parent| value will be used to identify
+  /// monitor info and to act as the parent view for dialogs, context menus,
+  /// etc. If |parent| is not provided then the main screen monitor will be used
+  /// and some functionality that requires a parent view may not function
+  /// correctly. In order to create windowless browsers the
+  /// CefSettings.windowless_rendering_enabled value must be set to true.
+  /// Transparent painting is enabled by default but can be disabled by setting
+  /// CefBrowserSettings.background_color to an opaque value.
   ///
   void SetAsWindowless(CefWindowHandle parent) {
     windowless_rendering_enabled = true;
diff --git a/src/include/internal/cef_ptr.h b/src/include/internal/cef_ptr.h
index 044c733..855ade5 100644
--- a/src/include/internal/cef_ptr.h
+++ b/src/include/internal/cef_ptr.h
@@ -31,200 +31,146 @@
 #define CEF_INCLUDE_INTERNAL_CEF_PTR_H_
 #pragma once
 
+#include <memory>
+
 #include "include/base/cef_build.h"
 #include "include/base/cef_ref_counted.h"
 
-#if defined(USING_CHROMIUM_INCLUDES)
-#include <memory>  // For std::unique_ptr.
-#else
-#include "include/base/cef_scoped_ptr.h"
-#endif
-
 ///
-// Smart pointer implementation that is an alias of scoped_refptr from
-// include/base/cef_ref_counted.h.
-// <p>
-// A smart pointer class for reference counted objects.  Use this class instead
-// of calling AddRef and Release manually on a reference counted object to
-// avoid common memory leaks caused by forgetting to Release an object
-// reference.  Sample usage:
-// <pre>
-//   class MyFoo : public CefBaseRefCounted {
-//    ...
-//   };
-//
-//   void some_function() {
-//     // The MyFoo object that |foo| represents starts with a single
-//     // reference.
-//     CefRefPtr&lt;MyFoo&gt; foo = new MyFoo();
-//     foo-&gt;Method(param);
-//     // |foo| is released when this function returns
-//   }
-//
-//   void some_other_function() {
-//     CefRefPtr&lt;MyFoo&gt; foo = new MyFoo();
-//     ...
-//     foo = NULL;  // explicitly releases |foo|
-//     ...
-//     if (foo)
-//       foo-&gt;Method(param);
-//   }
-// </pre>
-// The above examples show how CefRefPtr&lt;T&gt; acts like a pointer to T.
-// Given two CefRefPtr&lt;T&gt; classes, it is also possible to exchange
-// references between the two objects, like so:
-// <pre>
-//   {
-//     CefRefPtr&lt;MyFoo&gt; a = new MyFoo();
-//     CefRefPtr&lt;MyFoo&gt; b;
-//
-//     b.swap(a);
-//     // now, |b| references the MyFoo object, and |a| references NULL.
-//   }
-// </pre>
-// To make both |a| and |b| in the above example reference the same MyFoo
-// object, simply use the assignment operator:
-// <pre>
-//   {
-//     CefRefPtr&lt;MyFoo&gt; a = new MyFoo();
-//     CefRefPtr&lt;MyFoo&gt; b;
-//
-//     b = a;
-//     // now, |a| and |b| each own a reference to the same MyFoo object.
-//     // the reference count of the underlying MyFoo object will be 2.
-//   }
-// </pre>
-// Reference counted objects can also be passed as function parameters and
-// used as function return values:
-// <pre>
-//   void some_func_with_param(CefRefPtr&lt;MyFoo&gt; param) {
-//     // A reference is added to the MyFoo object that |param| represents
-//     // during the scope of some_func_with_param() and released when
-//     // some_func_with_param() goes out of scope.
-//   }
-//
-//   CefRefPtr&lt;MyFoo&gt; some_func_with_retval() {
-//     // The MyFoo object that |foox| represents starts with a single
-//     // reference.
-//     CefRefPtr&lt;MyFoo&gt; foox = new MyFoo();
-//
-//     // Creating the return value adds an additional reference.
-//     return foox;
-//
-//     // When some_func_with_retval() goes out of scope the original |foox|
-//     // reference is released.
-//   }
-//
-//   void and_another_function() {
-//     CefRefPtr&lt;MyFoo&gt; foo = new MyFoo();
-//
-//     // pass |foo| as a parameter.
-//     some_function(foo);
-//
-//     CefRefPtr&lt;MyFoo&gt; foo2 = some_func_with_retval();
-//     // Now, since we kept a reference to the some_func_with_retval() return
-//     // value, |foo2| is the only class pointing to the MyFoo object created
-//     in some_func_with_retval(), and it has a reference count of 1.
-//
-//     some_func_with_retval();
-//     // Now, since we didn't keep a reference to the some_func_with_retval()
-//     // return value, the MyFoo object created in some_func_with_retval()
-//     // will automatically be released.
-//   }
-// </pre>
-// And in standard containers:
-// <pre>
-//   {
-//      // Create a vector that holds MyFoo objects.
-//      std::vector&lt;CefRefPtr&lt;MyFoo&gt; &gt; MyFooVec;
-//
-//     // The MyFoo object that |foo| represents starts with a single
-//     // reference.
-//     CefRefPtr&lt;MyFoo&gt; foo = new MyFoo();
-//
-//     // When the MyFoo object is added to |MyFooVec| the reference count
-//     // is increased to 2.
-//     MyFooVec.push_back(foo);
-//   }
-// </pre>
-// </p>
+/// Smart pointer implementation that is an alias of scoped_refptr from
+/// include/base/cef_ref_counted.h.
 ///
-#if defined(HAS_CPP11_TEMPLATE_ALIAS_SUPPORT)
+/// A smart pointer class for reference counted objects.  Use this class instead
+/// of calling AddRef and Release manually on a reference counted object to
+/// avoid common memory leaks caused by forgetting to Release an object
+/// reference.  Sample usage:
+///
+/// <pre>
+///   class MyFoo : public CefBaseRefCounted {
+///     ...
+///   };
+///
+///   void some_function() {
+///     // The MyFoo object that |foo| represents starts with a single
+///     // reference.
+///     CefRefPtr&lt;MyFoo&gt; foo = new MyFoo();
+///     foo-&gt;Method(param);
+///     // |foo| is released when this function returns
+///   }
+///
+///   void some_other_function() {
+///     CefRefPtr&lt;MyFoo&gt; foo = new MyFoo();
+///     ...
+///     foo = NULL;  /// explicitly releases |foo|
+///     ...
+///     if (foo)
+///       foo-&gt;Method(param);
+///   }
+/// </pre>
+///
+/// The above examples show how CefRefPtr&lt;T&gt; acts like a pointer to T.
+/// Given two CefRefPtr&lt;T&gt; classes, it is also possible to exchange
+/// references between the two objects, like so:
+///
+/// <pre>
+///   {
+///     CefRefPtr&lt;MyFoo&gt; a = new MyFoo();
+///     CefRefPtr&lt;MyFoo&gt; b;
+///
+///     b.swap(a);
+///     // now, |b| references the MyFoo object, and |a| references NULL.
+///   }
+/// </pre>
+///
+/// To make both |a| and |b| in the above example reference the same MyFoo
+/// object, simply use the assignment operator:
+///
+/// <pre>
+///   {
+///     CefRefPtr&lt;MyFoo&gt; a = new MyFoo();
+///     CefRefPtr&lt;MyFoo&gt; b;
+///
+///     b = a;
+///     // now, |a| and |b| each own a reference to the same MyFoo object.
+///     // the reference count of the underlying MyFoo object will be 2.
+///   }
+/// </pre>
+///
+/// Reference counted objects can also be passed as function parameters and
+/// used as function return values:
+///
+/// <pre>
+///   void some_func_with_param(CefRefPtr&lt;MyFoo&gt; param) {
+///     // A reference is added to the MyFoo object that |param| represents
+///     // during the scope of some_func_with_param() and released when
+///     // some_func_with_param() goes out of scope.
+///   }
+///
+///   CefRefPtr&lt;MyFoo&gt; some_func_with_retval() {
+///     // The MyFoo object that |foox| represents starts with a single
+///     // reference.
+///     CefRefPtr&lt;MyFoo&gt; foox = new MyFoo();
+///
+///     // Creating the return value adds an additional reference.
+///     return foox;
+///
+///     // When some_func_with_retval() goes out of scope the original |foox|
+///     // reference is released.
+///   }
+///
+///   void and_another_function() {
+///     CefRefPtr&lt;MyFoo&gt; foo = new MyFoo();
+///
+///     // pass |foo| as a parameter.
+///     some_function(foo);
+///
+///     CefRefPtr&lt;MyFoo&gt; foo2 = some_func_with_retval();
+///     // Now, since we kept a reference to the some_func_with_retval() return
+///     // value, |foo2| is the only class pointing to the MyFoo object created
+///     in some_func_with_retval(), and it has a reference count of 1.
+///
+///     some_func_with_retval();
+///     // Now, since we didn't keep a reference to the some_func_with_retval()
+///     // return value, the MyFoo object created in some_func_with_retval()
+///     // will automatically be released.
+///   }
+/// </pre>
+///
+/// And in standard containers:
+///
+/// <pre>
+///   {
+///     // Create a vector that holds MyFoo objects.
+///     std::vector&lt;CefRefPtr&lt;MyFoo&gt; &gt; MyFooVec;
+///
+///     // The MyFoo object that |foo| represents starts with a single
+///     // reference.
+///     CefRefPtr&lt;MyFoo&gt; foo = new MyFoo();
+///
+///     // When the MyFoo object is added to |MyFooVec| the reference count
+///     // is increased to 2.
+///     MyFooVec.push_back(foo);
+///   }
+/// </pre>
+///
 template <class T>
 using CefRefPtr = scoped_refptr<T>;
-#else
-// When template aliases are not supported use a define instead of subclassing
-// because it's otherwise hard to get the constructors to behave correctly.
-#define CefRefPtr scoped_refptr
-#endif
 
 ///
-// A CefOwnPtr<T> is like a T*, except that the destructor of CefOwnPtr<T>
-// automatically deletes the pointer it holds (if any). That is, CefOwnPtr<T>
-// owns the T object that it points to. Like a T*, a CefOwnPtr<T> may hold
-// either NULL or a pointer to a T object. Also like T*, CefOwnPtr<T> is
-// thread-compatible, and once you dereference it, you get the thread safety
-// guarantees of T.
+/// A CefOwnPtr<T> is like a T*, except that the destructor of CefOwnPtr<T>
+/// automatically deletes the pointer it holds (if any). That is, CefOwnPtr<T>
+/// owns the T object that it points to. Like a T*, a CefOwnPtr<T> may hold
+/// either NULL or a pointer to a T object. Also like T*, CefOwnPtr<T> is
+/// thread-compatible, and once you dereference it, you get the thread safety
+/// guarantees of T.
 ///
-#if defined(USING_CHROMIUM_INCLUDES)
-// Implementation-side code uses std::unique_ptr instead of scoped_ptr.
 template <class T, class D = std::default_delete<T>>
 using CefOwnPtr = std::unique_ptr<T, D>;
-#elif defined(HAS_CPP11_TEMPLATE_ALIAS_SUPPORT)
-template <class T, class D = base::DefaultDeleter<T>>
-using CefOwnPtr = scoped_ptr<T, D>;
-#else
-// When template aliases are not supported use a define instead of subclassing
-// because it's otherwise hard to get the constructors to behave correctly.
-#define CefOwnPtr scoped_ptr
-#endif
 
 ///
-// A CefRawPtr<T> is the same as T*
+/// A CefRawPtr<T> is the same as T*
 ///
-#if defined(HAS_CPP11_TEMPLATE_ALIAS_SUPPORT)
-#define CEF_RAW_PTR_GET(r) r
 template <class T>
 using CefRawPtr = T*;
-#else
-// Simple wrapper implementation that behaves as much like T* as possible.
-// CEF_RAW_PTR_GET is required for VS2008 compatibility (Issue #2155).
-#define CEF_RAW_PTR_GET(r) r.get()
-template <class T>
-class CefRawPtr {
- public:
-  CefRawPtr() : ptr_(nullptr) {}
-  CefRawPtr(T* p) : ptr_(p) {}
-  CefRawPtr(const CefRawPtr& r) : ptr_(r.ptr_) {}
-
-  template <typename U>
-  CefRawPtr(const CefRawPtr<U>& r) : ptr_(r.get()) {}
-
-  T* get() const { return ptr_; }
-
-  // Allow CefRawPtr to be used in boolean expression and comparison operations.
-  operator T*() const { return ptr_; }
-
-  T* operator->() const {
-    assert(ptr_ != NULL);
-    return ptr_;
-  }
-
-  CefRawPtr<T>& operator=(T* p) {
-    ptr_ = p;
-    return *this;
-  }
-
-  CefRawPtr<T>& operator=(const CefRawPtr<T>& r) { return *this = r.ptr_; }
-
-  template <typename U>
-  CefRawPtr<T>& operator=(const CefRawPtr<U>& r) {
-    return *this = r.get();
-  }
-
- private:
-  T* ptr_;
-};
-#endif
 
 #endif  // CEF_INCLUDE_INTERNAL_CEF_PTR_H_
diff --git a/src/include/internal/cef_string.h b/src/include/internal/cef_string.h
index 77c8ca3..20df91a 100644
--- a/src/include/internal/cef_string.h
+++ b/src/include/internal/cef_string.h
@@ -74,7 +74,7 @@
 #define cef_string_to_wide cef_string_utf8_to_wide
 #define cef_string_from_wide cef_string_wide_to_utf8
 #elif defined(CEF_STRING_TYPE_UTF16)
-typedef char16 cef_char_t;
+typedef char16_t cef_char_t;
 typedef cef_string_userfree_utf16_t cef_string_userfree_t;
 typedef cef_string_utf16_t cef_string_t;
 #define cef_string_set cef_string_utf16_set
diff --git a/src/include/internal/cef_string_list.h b/src/include/internal/cef_string_list.h
index b44bac7..e8339bd 100644
--- a/src/include/internal/cef_string_list.h
+++ b/src/include/internal/cef_string_list.h
@@ -39,46 +39,46 @@
 #endif
 
 ///
-// CEF string maps are a set of key/value string pairs.
+/// CEF string maps are a set of key/value string pairs.
 ///
-typedef void* cef_string_list_t;
+typedef struct _cef_string_list_t* cef_string_list_t;
 
 ///
-// Allocate a new string map.
+/// Allocate a new string map.
 ///
-CEF_EXPORT cef_string_list_t cef_string_list_alloc();
+CEF_EXPORT cef_string_list_t cef_string_list_alloc(void);
 
 ///
-// Return the number of elements in the string list.
+/// Return the number of elements in the string list.
 ///
 CEF_EXPORT size_t cef_string_list_size(cef_string_list_t list);
 
 ///
-// Retrieve the value at the specified zero-based string list index. Returns
-// true (1) if the value was successfully retrieved.
+/// Retrieve the value at the specified zero-based string list index. Returns
+/// true (1) if the value was successfully retrieved.
 ///
 CEF_EXPORT int cef_string_list_value(cef_string_list_t list,
                                      size_t index,
                                      cef_string_t* value);
 
 ///
-// Append a new value at the end of the string list.
+/// Append a new value at the end of the string list.
 ///
 CEF_EXPORT void cef_string_list_append(cef_string_list_t list,
                                        const cef_string_t* value);
 
 ///
-// Clear the string list.
+/// Clear the string list.
 ///
 CEF_EXPORT void cef_string_list_clear(cef_string_list_t list);
 
 ///
-// Free the string list.
+/// Free the string list.
 ///
 CEF_EXPORT void cef_string_list_free(cef_string_list_t list);
 
 ///
-// Creates a copy of an existing string list.
+/// Creates a copy of an existing string list.
 ///
 CEF_EXPORT cef_string_list_t cef_string_list_copy(cef_string_list_t list);
 
diff --git a/src/include/internal/cef_string_map.h b/src/include/internal/cef_string_map.h
index 0f33425..031a6bf 100644
--- a/src/include/internal/cef_string_map.h
+++ b/src/include/internal/cef_string_map.h
@@ -39,55 +39,56 @@
 #endif
 
 ///
-// CEF string maps are a set of key/value string pairs.
+/// CEF string maps are a set of key/value string pairs.
 ///
-typedef void* cef_string_map_t;
+typedef struct _cef_string_map_t* cef_string_map_t;
 
 ///
-// Allocate a new string map.
+/// Allocate a new string map.
 ///
-CEF_EXPORT cef_string_map_t cef_string_map_alloc();
+CEF_EXPORT cef_string_map_t cef_string_map_alloc(void);
 
 ///
-// Return the number of elements in the string map.
+/// Return the number of elements in the string map.
 ///
 CEF_EXPORT size_t cef_string_map_size(cef_string_map_t map);
 
 ///
-// Return the value assigned to the specified key.
+/// Return the value assigned to the specified key.
 ///
 CEF_EXPORT int cef_string_map_find(cef_string_map_t map,
                                    const cef_string_t* key,
                                    cef_string_t* value);
 
 ///
-// Return the key at the specified zero-based string map index.
+/// Return the key at the specified zero-based string map index.
 ///
 CEF_EXPORT int cef_string_map_key(cef_string_map_t map,
                                   size_t index,
                                   cef_string_t* key);
 
 ///
-// Return the value at the specified zero-based string map index.
+/// Return the value at the specified zero-based string map index.
 ///
 CEF_EXPORT int cef_string_map_value(cef_string_map_t map,
                                     size_t index,
                                     cef_string_t* value);
 
 ///
-// Append a new key/value pair at the end of the string map.
+/// Append a new key/value pair at the end of the string map. If the key exists,
+/// overwrite the existing value with a new value w/o changing the pair order.
 ///
 CEF_EXPORT int cef_string_map_append(cef_string_map_t map,
                                      const cef_string_t* key,
                                      const cef_string_t* value);
 
 ///
-// Clear the string map.
+/// Clear the string map.
 ///
 CEF_EXPORT void cef_string_map_clear(cef_string_map_t map);
 
 ///
-// Free the string map.
+/// Free the string map.
 ///
 CEF_EXPORT void cef_string_map_free(cef_string_map_t map);
 
diff --git a/src/include/internal/cef_string_multimap.h b/src/include/internal/cef_string_multimap.h
index cd07746..9dde805 100644
--- a/src/include/internal/cef_string_multimap.h
+++ b/src/include/internal/cef_string_multimap.h
@@ -39,29 +39,29 @@
 #endif
 
 ///
-// CEF string multimaps are a set of key/value string pairs.
-// More than one value can be assigned to a single key.
+/// CEF string multimaps are a set of key/value string pairs.
+/// More than one value can be assigned to a single key.
 ///
-typedef void* cef_string_multimap_t;
+typedef struct _cef_string_multimap_t* cef_string_multimap_t;
 
 ///
-// Allocate a new string multimap.
+/// Allocate a new string multimap.
 ///
-CEF_EXPORT cef_string_multimap_t cef_string_multimap_alloc();
+CEF_EXPORT cef_string_multimap_t cef_string_multimap_alloc(void);
 
 ///
-// Return the number of elements in the string multimap.
+/// Return the number of elements in the string multimap.
 ///
 CEF_EXPORT size_t cef_string_multimap_size(cef_string_multimap_t map);
 
 ///
-// Return the number of values with the specified key.
+/// Return the number of values with the specified key.
 ///
 CEF_EXPORT size_t cef_string_multimap_find_count(cef_string_multimap_t map,
                                                  const cef_string_t* key);
 
 ///
-// Return the value_index-th value with the specified key.
+/// Return the value_index-th value with the specified key.
 ///
 CEF_EXPORT int cef_string_multimap_enumerate(cef_string_multimap_t map,
                                              const cef_string_t* key,
@@ -69,33 +69,33 @@
                                              cef_string_t* value);
 
 ///
-// Return the key at the specified zero-based string multimap index.
+/// Return the key at the specified zero-based string multimap index.
 ///
 CEF_EXPORT int cef_string_multimap_key(cef_string_multimap_t map,
                                        size_t index,
                                        cef_string_t* key);
 
 ///
-// Return the value at the specified zero-based string multimap index.
+/// Return the value at the specified zero-based string multimap index.
 ///
 CEF_EXPORT int cef_string_multimap_value(cef_string_multimap_t map,
                                          size_t index,
                                          cef_string_t* value);
 
 ///
-// Append a new key/value pair at the end of the string multimap.
+/// Append a new key/value pair at the end of the string multimap.
 ///
 CEF_EXPORT int cef_string_multimap_append(cef_string_multimap_t map,
                                           const cef_string_t* key,
                                           const cef_string_t* value);
 
 ///
-// Clear the string multimap.
+/// Clear the string multimap.
 ///
 CEF_EXPORT void cef_string_multimap_clear(cef_string_multimap_t map);
 
 ///
-// Free the string multimap.
+/// Free the string multimap.
 ///
 CEF_EXPORT void cef_string_multimap_free(cef_string_multimap_t map);
 
diff --git a/src/include/internal/cef_string_types.h b/src/include/internal/cef_string_types.h
index ea91960..ee3308b 100644
--- a/src/include/internal/cef_string_types.h
+++ b/src/include/internal/cef_string_types.h
@@ -31,26 +31,42 @@
 #define CEF_INCLUDE_INTERNAL_CEF_STRING_TYPES_H_
 #pragma once
 
-// CEF provides functions for converting between UTF-8, -16 and -32 strings.
-// CEF string types are safe for reading from multiple threads but not for
-// modification. It is the user's responsibility to provide synchronization if
-// modifying CEF strings from multiple threads.
-
 #include <stddef.h>
 
-#include "include/base/cef_basictypes.h"
+#ifdef __clang__
+// On macOS, <uchar.h> is only available with Xcode 14.3+.
+#if __has_include(<uchar.h>)
+#include <uchar.h>
+#elif !defined(__cplusplus)
+#include <stdint.h>
+typedef uint_least16_t char16_t;
+#endif
+#else
+#include <uchar.h>
+#endif
+
 #include "include/internal/cef_export.h"
 
+///
+/// \file
+/// CEF provides functions for converting between UTF-8, -16 and -32 strings.
+/// CEF string types are safe for reading from multiple threads but not for
+/// modification. It is the user's responsibility to provide synchronization if
+/// modifying CEF strings from multiple threads.
+///
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-// CEF string type definitions. Whomever allocates |str| is responsible for
-// providing an appropriate |dtor| implementation that will free the string in
-// the same memory space. When reusing an existing string structure make sure
-// to call |dtor| for the old value before assigning new |str| and |dtor|
-// values. Static strings will have a NULL |dtor| value. Using the below
-// functions if you want this managed for you.
+///
+/// CEF string type definitions. Whomever allocates |str| is responsible for
+/// providing an appropriate |dtor| implementation that will free the string in
+/// the same memory space. When reusing an existing string structure make sure
+/// to call |dtor| for the old value before assigning new |str| and |dtor|
+/// values. Static strings will have a NULL |dtor| value. Using the below
+/// functions if you want this managed for you.
+///
 
 typedef struct _cef_string_wide_t {
   wchar_t* str;
@@ -65,15 +81,15 @@
 } cef_string_utf8_t;
 
 typedef struct _cef_string_utf16_t {
-  char16* str;
+  char16_t* str;
   size_t length;
-  void (*dtor)(char16* str);
+  void (*dtor)(char16_t* str);
 } cef_string_utf16_t;
 
 ///
-// These functions set string values. If |copy| is true (1) the value will be
-// copied instead of referenced. It is up to the user to properly manage
-// the lifespan of references.
+/// These functions set string values. If |copy| is true (1) the value will be
+/// copied instead of referenced. It is up to the user to properly manage
+/// the lifespan of references.
 ///
 
 CEF_EXPORT int cef_string_wide_set(const wchar_t* src,
@@ -84,13 +100,13 @@
                                    size_t src_len,
                                    cef_string_utf8_t* output,
                                    int copy);
-CEF_EXPORT int cef_string_utf16_set(const char16* src,
+CEF_EXPORT int cef_string_utf16_set(const char16_t* src,
                                     size_t src_len,
                                     cef_string_utf16_t* output,
                                     int copy);
 
 ///
-// Convenience macros for copying values.
+/// Convenience macros for copying values.
 ///
 
 #define cef_string_wide_copy(src, src_len, output) \
@@ -101,7 +117,7 @@
   cef_string_utf16_set(src, src_len, output, true)
 
 ///
-// These functions clear string values. The structure itself is not freed.
+/// These functions clear string values. The structure itself is not freed.
 ///
 
 CEF_EXPORT void cef_string_wide_clear(cef_string_wide_t* str);
@@ -109,7 +125,7 @@
 CEF_EXPORT void cef_string_utf16_clear(cef_string_utf16_t* str);
 
 ///
-// These functions compare two string values with the same results as strcmp().
+/// These functions compare two string values with the same results as strcmp().
 ///
 
 CEF_EXPORT int cef_string_wide_cmp(const cef_string_wide_t* str1,
@@ -120,10 +136,10 @@
                                     const cef_string_utf16_t* str2);
 
 ///
-// These functions convert between UTF-8, -16, and -32 strings. They are
-// potentially slow so unnecessary conversions should be avoided. The best
-// possible result will always be written to |output| with the boolean return
-// value indicating whether the conversion is 100% valid.
+/// These functions convert between UTF-8, -16, and -32 strings. They are
+/// potentially slow so unnecessary conversions should be avoided. The best
+/// possible result will always be written to |output| with the boolean return
+/// value indicating whether the conversion is 100% valid.
 ///
 
 CEF_EXPORT int cef_string_wide_to_utf8(const wchar_t* src,
@@ -136,21 +152,21 @@
 CEF_EXPORT int cef_string_wide_to_utf16(const wchar_t* src,
                                         size_t src_len,
                                         cef_string_utf16_t* output);
-CEF_EXPORT int cef_string_utf16_to_wide(const char16* src,
+CEF_EXPORT int cef_string_utf16_to_wide(const char16_t* src,
                                         size_t src_len,
                                         cef_string_wide_t* output);
 
 CEF_EXPORT int cef_string_utf8_to_utf16(const char* src,
                                         size_t src_len,
                                         cef_string_utf16_t* output);
-CEF_EXPORT int cef_string_utf16_to_utf8(const char16* src,
+CEF_EXPORT int cef_string_utf16_to_utf8(const char16_t* src,
                                         size_t src_len,
                                         cef_string_utf8_t* output);
 
 ///
-// These functions convert an ASCII string, typically a hardcoded constant, to a
-// Wide/UTF16 string. Use instead of the UTF8 conversion routines if you know
-// the string is ASCII.
+/// These functions convert an ASCII string, typically a hardcoded constant, to
+/// a Wide/UTF16 string. Use instead of the UTF8 conversion routines if you know
+/// the string is ASCII.
 ///
 
 CEF_EXPORT int cef_string_ascii_to_wide(const char* src,
@@ -161,9 +177,9 @@
                                          cef_string_utf16_t* output);
 
 ///
-// It is sometimes necessary for the system to allocate string structures with
-// the expectation that the user will free them. The userfree types act as a
-// hint that the user is responsible for freeing the structure.
+/// It is sometimes necessary for the system to allocate string structures with
+/// the expectation that the user will free them. The userfree types act as a
+/// hint that the user is responsible for freeing the structure.
 ///
 
 typedef cef_string_wide_t* cef_string_userfree_wide_t;
@@ -171,17 +187,17 @@
 typedef cef_string_utf16_t* cef_string_userfree_utf16_t;
 
 ///
-// These functions allocate a new string structure. They must be freed by
-// calling the associated free function.
+/// These functions allocate a new string structure. They must be freed by
+/// calling the associated free function.
 ///
 
-CEF_EXPORT cef_string_userfree_wide_t cef_string_userfree_wide_alloc();
-CEF_EXPORT cef_string_userfree_utf8_t cef_string_userfree_utf8_alloc();
-CEF_EXPORT cef_string_userfree_utf16_t cef_string_userfree_utf16_alloc();
+CEF_EXPORT cef_string_userfree_wide_t cef_string_userfree_wide_alloc(void);
+CEF_EXPORT cef_string_userfree_utf8_t cef_string_userfree_utf8_alloc(void);
+CEF_EXPORT cef_string_userfree_utf16_t cef_string_userfree_utf16_alloc(void);
 
 ///
-// These functions free the string structure allocated by the associated
-// alloc function. Any string contents will first be cleared.
+/// These functions free the string structure allocated by the associated
+/// alloc function. Any string contents will first be cleared.
 ///
 
 CEF_EXPORT void cef_string_userfree_wide_free(cef_string_userfree_wide_t str);
@@ -189,14 +205,14 @@
 CEF_EXPORT void cef_string_userfree_utf16_free(cef_string_userfree_utf16_t str);
 
 ///
-// These functions convert utf16 string case using the current ICU locale. This
-// may change the length of the string in some cases.
+/// These functions convert utf16 string case using the current ICU locale. This
+/// may change the length of the string in some cases.
 ///
 
-CEF_EXPORT int cef_string_utf16_to_lower(const char16* src,
+CEF_EXPORT int cef_string_utf16_to_lower(const char16_t* src,
                                          size_t src_len,
                                          cef_string_utf16_t* output);
-CEF_EXPORT int cef_string_utf16_to_upper(const char16* src,
+CEF_EXPORT int cef_string_utf16_to_upper(const char16_t* src,
                                          size_t src_len,
                                          cef_string_utf16_t* output);
 
diff --git a/src/include/internal/cef_string_wrappers.h b/src/include/internal/cef_string_wrappers.h
index f965e9c..44efeff 100644
--- a/src/include/internal/cef_string_wrappers.h
+++ b/src/include/internal/cef_string_wrappers.h
@@ -34,7 +34,6 @@
 #include <memory.h>
 #include <string>
 
-#include "include/base/cef_string16.h"
 #include "include/internal/cef_string_types.h"
 
 #if defined(USING_CHROMIUM_INCLUDES)
@@ -42,7 +41,7 @@
 #endif
 
 ///
-// Traits implementation for wide character strings.
+/// Traits implementation for wide character strings.
 ///
 struct CefStringTraitsWide {
   typedef wchar_t char_type;
@@ -75,49 +74,73 @@
     memset(&cstr, 0, sizeof(cstr));
     cef_string_wide_to_utf8(s->str, s->length, &cstr);
     std::string str;
-    if (cstr.length > 0)
+    if (cstr.length > 0) {
       str = std::string(cstr.str, cstr.length);
+    }
     cef_string_utf8_clear(&cstr);
     return str;
   }
+  static inline bool from_string(const std::string::value_type* data,
+                                 size_t length,
+                                 struct_type* s) {
+    return cef_string_utf8_to_wide(data, length, s) ? true : false;
+  }
   static inline bool from_string(const std::string& str, struct_type* s) {
-    return cef_string_utf8_to_wide(str.c_str(), str.length(), s) ? true : false;
+    return from_string(str.data(), str.length(), s);
   }
   static inline std::wstring to_wstring(const struct_type* s) {
     return std::wstring(s->str, s->length);
   }
+  static inline bool from_wstring(const std::wstring::value_type* data,
+                                  size_t length,
+                                  struct_type* s) {
+    return cef_string_wide_set(data, length, s, true) ? true : false;
+  }
   static inline bool from_wstring(const std::wstring& str, struct_type* s) {
-    return cef_string_wide_set(str.c_str(), str.length(), s, true) ? true
-                                                                   : false;
+    return from_wstring(str.data(), str.length(), s);
   }
 #if defined(WCHAR_T_IS_UTF32)
-  static inline base::string16 to_string16(const struct_type* s) {
+  static inline std::u16string to_string16(const struct_type* s) {
     cef_string_utf16_t cstr;
     memset(&cstr, 0, sizeof(cstr));
     cef_string_wide_to_utf16(s->str, s->length, &cstr);
-    base::string16 str;
-    if (cstr.length > 0)
-      str = base::string16(cstr.str, cstr.length);
+    std::u16string str;
+    if (cstr.length > 0) {
+      str = std::u16string(
+          reinterpret_cast<std::u16string::value_type*>(cstr.str), cstr.length);
+    }
     cef_string_utf16_clear(&cstr);
     return str;
   }
-  static inline bool from_string16(const base::string16& str, struct_type* s) {
-    return cef_string_utf16_to_wide(str.c_str(), str.length(), s) ? true
-                                                                  : false;
+  static inline bool from_string16(const std::u16string::value_type* data,
+                                   size_t length,
+                                   struct_type* s) {
+    return cef_string_utf16_to_wide(reinterpret_cast<const char16_t*>(data),
+                                    length, s)
+               ? true
+               : false;
   }
 #else   // WCHAR_T_IS_UTF32
-  static inline base::string16 to_string16(const struct_type* s) {
-    return base::string16(s->str, s->length);
+  static inline std::u16string to_string16(const struct_type* s) {
+    return std::u16string(
+        reinterpret_cast<const std::u16string::value_type*>(s->str), s->length);
   }
-  static inline bool from_string16(const base::string16& str, struct_type* s) {
-    return cef_string_wide_set(str.c_str(), str.length(), s, true) ? true
-                                                                   : false;
+  static inline bool from_string16(const std::u16string::value_type* data,
+                                   size_t length,
+                                   struct_type* s) {
+    return cef_string_wide_set(reinterpret_cast<const wchar_t*>(data), length,
+                               s, true)
+               ? true
+               : false;
   }
 #endif  // WCHAR_T_IS_UTF32
+  static inline bool from_string16(const std::u16string& str, struct_type* s) {
+    return from_string16(str.data(), str.length(), s);
+  }
 };
 
 ///
-// Traits implementation for utf8 character strings.
+/// Traits implementation for utf8 character strings.
 ///
 struct CefStringTraitsUTF8 {
   typedef char char_type;
@@ -148,43 +171,63 @@
   static inline std::string to_string(const struct_type* s) {
     return std::string(s->str, s->length);
   }
+  static inline bool from_string(const std::string::value_type* data,
+                                 size_t length,
+                                 struct_type* s) {
+    return cef_string_utf8_copy(data, length, s) ? true : false;
+  }
   static inline bool from_string(const std::string& str, struct_type* s) {
-    return cef_string_utf8_copy(str.c_str(), str.length(), s) ? true : false;
+    return from_string(str.c_str(), str.length(), s);
   }
   static inline std::wstring to_wstring(const struct_type* s) {
     cef_string_wide_t cstr;
     memset(&cstr, 0, sizeof(cstr));
     cef_string_utf8_to_wide(s->str, s->length, &cstr);
     std::wstring str;
-    if (cstr.length > 0)
+    if (cstr.length > 0) {
       str = std::wstring(cstr.str, cstr.length);
+    }
     cef_string_wide_clear(&cstr);
     return str;
   }
-  static inline bool from_wstring(const std::wstring& str, struct_type* s) {
-    return cef_string_wide_to_utf8(str.c_str(), str.length(), s) ? true : false;
+  static inline bool from_wstring(const std::wstring::value_type* data,
+                                  size_t length,
+                                  struct_type* s) {
+    return cef_string_wide_to_utf8(data, length, s) ? true : false;
   }
-  static inline base::string16 to_string16(const struct_type* s) {
+  static inline bool from_wstring(const std::wstring& str, struct_type* s) {
+    return from_wstring(str.data(), str.length(), s);
+  }
+  static inline std::u16string to_string16(const struct_type* s) {
     cef_string_utf16_t cstr;
     memset(&cstr, 0, sizeof(cstr));
     cef_string_utf8_to_utf16(s->str, s->length, &cstr);
-    base::string16 str;
-    if (cstr.length > 0)
-      str = base::string16(cstr.str, cstr.length);
+    std::u16string str;
+    if (cstr.length > 0) {
+      str = std::u16string(
+          reinterpret_cast<std::u16string::value_type*>(cstr.str), cstr.length);
+    }
     cef_string_utf16_clear(&cstr);
     return str;
   }
-  static inline bool from_string16(const base::string16& str, struct_type* s) {
-    return cef_string_utf16_to_utf8(str.c_str(), str.length(), s) ? true
-                                                                  : false;
+  static inline bool from_string16(const std::u16string::value_type* data,
+                                   size_t length,
+                                   struct_type* s) {
+    return cef_string_utf16_to_utf8(reinterpret_cast<const char16_t*>(data),
+                                    length, s)
+               ? true
+               : false;
+  }
+  static inline bool from_string16(const std::u16string& str, struct_type* s) {
+    return from_string16(str.data(), str.length(), s);
   }
 };
 
 ///
-// Traits implementation for utf16 character strings.
+/// Traits implementation for utf16 character strings.
 ///
 struct CefStringTraitsUTF16 {
-  typedef char16 char_type;
+  typedef char16_t char_type;
   typedef cef_string_utf16_t struct_type;
   typedef cef_string_userfree_utf16_t userfree_struct_type;
 
@@ -214,14 +257,19 @@
     memset(&cstr, 0, sizeof(cstr));
     cef_string_utf16_to_utf8(s->str, s->length, &cstr);
     std::string str;
-    if (cstr.length > 0)
+    if (cstr.length > 0) {
       str = std::string(cstr.str, cstr.length);
+    }
     cef_string_utf8_clear(&cstr);
     return str;
   }
+  static inline bool from_string(const std::string::value_type* data,
+                                 size_t length,
+                                 struct_type* s) {
+    return cef_string_utf8_to_utf16(data, length, s) ? true : false;
+  }
   static inline bool from_string(const std::string& str, struct_type* s) {
-    return cef_string_utf8_to_utf16(str.c_str(), str.length(), s) ? true
-                                                                  : false;
+    return from_string(str.data(), str.length(), s);
   }
 #if defined(WCHAR_T_IS_UTF32)
   static inline std::wstring to_wstring(const struct_type* s) {
@@ -229,193 +277,223 @@
     memset(&cstr, 0, sizeof(cstr));
     cef_string_utf16_to_wide(s->str, s->length, &cstr);
     std::wstring str;
-    if (cstr.length > 0)
+    if (cstr.length > 0) {
       str = std::wstring(cstr.str, cstr.length);
+    }
     cef_string_wide_clear(&cstr);
     return str;
   }
-  static inline bool from_wstring(const std::wstring& str, struct_type* s) {
-    return cef_string_wide_to_utf16(str.c_str(), str.length(), s) ? true
-                                                                  : false;
+  static inline bool from_wstring(const std::wstring::value_type* data,
+                                  size_t length,
+                                  struct_type* s) {
+    return cef_string_wide_to_utf16(data, length, s) ? true : false;
   }
 #else   // WCHAR_T_IS_UTF32
   static inline std::wstring to_wstring(const struct_type* s) {
-    return std::wstring(s->str, s->length);
+    return std::wstring(reinterpret_cast<wchar_t*>(s->str), s->length);
   }
-  static inline bool from_wstring(const std::wstring& str, struct_type* s) {
-    return cef_string_utf16_set(str.c_str(), str.length(), s, true) ? true
-                                                                    : false;
+  static inline bool from_wstring(const std::wstring::value_type* data,
+                                  size_t length,
+                                  struct_type* s) {
+    return cef_string_utf16_set(reinterpret_cast<const char16_t*>(data), length,
+                                s, true)
+               ? true
+               : false;
   }
 #endif  // WCHAR_T_IS_UTF32
-  static inline base::string16 to_string16(const struct_type* s) {
-    return base::string16(s->str, s->length);
+  static inline bool from_wstring(const std::wstring& str, struct_type* s) {
+    return from_wstring(str.data(), str.length(), s);
   }
-  static inline bool from_string16(const base::string16& str, struct_type* s) {
-    return cef_string_utf16_set(str.c_str(), str.length(), s, true) ? true
-                                                                    : false;
+  static inline std::u16string to_string16(const struct_type* s) {
+    return std::u16string(
+        reinterpret_cast<const std::u16string::value_type*>(s->str), s->length);
+  }
+  static inline bool from_string16(const std::u16string::value_type* data,
+                                   size_t length,
+                                   struct_type* s) {
+    return cef_string_utf16_set(reinterpret_cast<const char16_t*>(data), length,
+                                s, true)
+               ? true
+               : false;
+  }
+  static inline bool from_string16(const std::u16string& str, struct_type* s) {
+    return from_string16(str.data(), str.length(), s);
   }
 };
 
 ///
-// CEF string classes can convert between all supported string types. For
-// example, the CefStringWide class uses wchar_t as the underlying character
-// type and provides two approaches for converting data to/from a UTF8 string
-// (std::string).
-// <p>
-// 1. Implicit conversion using the assignment operator overload.
-// <pre>
-//   CefStringWide aCefString;
-//   std::string aUTF8String;
-//   aCefString = aUTF8String; // Assign std::string to CefStringWide
-//   aUTF8String = aCefString; // Assign CefStringWide to std::string
-// </pre>
-// 2. Explicit conversion using the FromString/ToString methods.
-// <pre>
-//   CefStringWide aCefString;
-//   std::string aUTF8String;
-//   aCefString.FromString(aUTF8String); // Assign std::string to CefStringWide
-//   aUTF8String = aCefString.ToString(); // Assign CefStringWide to std::string
-// </pre>
-// Conversion will only occur if the assigned value is a different string type.
-// Assigning a std::string to a CefStringUTF8, for example, will copy the data
-// without performing a conversion.
-// </p>
-// CEF string classes are safe for reading from multiple threads but not for
-// modification. It is the user's responsibility to provide synchronization if
-// modifying CEF strings from multiple threads.
+/// CEF string classes can convert between all supported string types. For
+/// example, the CefStringWide class uses wchar_t as the underlying character
+/// type and provides two approaches for converting data to/from a UTF8 string
+/// (std::string).
+///
+/// 1. Implicit conversion using the assignment operator overload.
+/// <pre>
+///   CefStringWide aCefString;
+///   std::string aUTF8String;
+///   aCefString = aUTF8String; // Assign std::string to CefStringWide
+///   aUTF8String = aCefString; // Assign CefStringWide to std::string
+/// </pre>
+///
+/// 2. Explicit conversion using the FromString/ToString methods.
+/// <pre>
+///   CefStringWide aCefString;
+///   std::string aUTF8String;
+///   aCefString.FromString(aUTF8String); // Assign std::string to CefStringWide
+///   aUTF8String = aCefString.ToString(); // Assign CefStringWide to
+///   std::string
+/// </pre>
+///
+/// Conversion will only occur if the assigned value is a different string type.
+/// Assigning a std::string to a CefStringUTF8, for example, will copy the data
+/// without performing a conversion.
+///
+/// CEF string classes are safe for reading from multiple threads but not for
+/// modification. It is the user's responsibility to provide synchronization if
+/// modifying CEF strings from multiple threads.
 ///
 template <class traits>
-class CefStringBase {
+class CefStringBase final {
  public:
   typedef typename traits::char_type char_type;
   typedef typename traits::struct_type struct_type;
   typedef typename traits::userfree_struct_type userfree_struct_type;
 
   ///
-  // Default constructor.
+  /// Default constructor.
   ///
   CefStringBase() : string_(NULL), owner_(false) {}
 
   ///
-  // Create a new string from an existing string. Data will always be copied.
+  /// Create a new string from an existing string. Data will always be copied.
   ///
   CefStringBase(const CefStringBase& str) : string_(NULL), owner_(false) {
     FromString(str.c_str(), str.length(), true);
   }
 
   ///
-  // Create a new string from an existing std::string. Data will be always
-  // copied. Translation will occur if necessary based on the underlying string
-  // type.
+  /// Create a new string from an existing std::string. Data will be always
+  /// copied. Translation will occur if necessary based on the underlying string
+  /// type.
   ///
   CefStringBase(const std::string& src) : string_(NULL), owner_(false) {
     FromString(src);
   }
-  CefStringBase(const char* src) : string_(NULL), owner_(false) {
-    if (src)
-      FromString(std::string(src));
+  CefStringBase(const char* src, size_t length = 0)
+      : string_(NULL), owner_(false) {
+    if (src) {
+      FromString(src, length);
+    }
   }
 
   ///
-  // Create a new string from an existing std::wstring. Data will be always
-  // copied. Translation will occur if necessary based on the underlying string
-  // type.
+  /// Create a new string from an existing std::wstring. Data will be always
+  /// copied. Translation will occur if necessary based on the underlying string
+  /// type.
   ///
   CefStringBase(const std::wstring& src) : string_(NULL), owner_(false) {
     FromWString(src);
   }
-  CefStringBase(const wchar_t* src) : string_(NULL), owner_(false) {
-    if (src)
-      FromWString(std::wstring(src));
+  CefStringBase(const wchar_t* src, size_t length = 0)
+      : string_(NULL), owner_(false) {
+    if (src) {
+      FromWString(src, length);
+    }
   }
 
-#if defined(WCHAR_T_IS_UTF32)
   ///
-  // Create a new string from an existing string16. Data will be always
-  // copied. Translation will occur if necessary based on the underlying string
-  // type.
+  /// Create a new string from an existing string16. Data will be always
+  /// copied. Translation will occur if necessary based on the underlying string
+  /// type.
   ///
-  CefStringBase(const base::string16& src) : string_(NULL), owner_(false) {
+  CefStringBase(const std::u16string& src) : string_(NULL), owner_(false) {
     FromString16(src);
   }
-  CefStringBase(const char16* src) : string_(NULL), owner_(false) {
-    if (src)
-      FromString16(base::string16(src));
+  CefStringBase(const std::u16string::value_type* src, size_t length = 0)
+      : string_(NULL), owner_(false) {
+    if (src) {
+      FromString16(src, length);
+    }
   }
-#endif  // WCHAR_T_IS_UTF32
 
   ///
-  // Create a new string from an existing character array. If |copy| is true
-  // this class will copy the data. Otherwise, this class will reference the
-  // existing data. Referenced data must exist for the lifetime of this class
-  // and will not be freed by this class.
+  /// Create a new string from an existing character array. If |copy| is true
+  /// this class will copy the data. Otherwise, this class will reference the
+  /// existing data. Referenced data must exist for the lifetime of this class
+  /// and will not be freed by this class.
   ///
   CefStringBase(const char_type* src, size_t src_len, bool copy)
       : string_(NULL), owner_(false) {
-    if (src && src_len > 0)
+    if (src && src_len > 0) {
       FromString(src, src_len, copy);
+    }
   }
 
   ///
-  // Create a new string referencing an existing string structure without taking
-  // ownership. Referenced structures must exist for the lifetime of this class
-  // and will not be freed by this class.
+  /// Create a new string referencing an existing string structure without
+  /// taking ownership. Referenced structures must exist for the lifetime of
+  /// this class and will not be freed by this class.
   ///
   CefStringBase(const struct_type* src) : string_(NULL), owner_(false) {
-    if (!src)
+    if (!src) {
       return;
+    }
     // Reference the existing structure without taking ownership.
     Attach(const_cast<struct_type*>(src), false);
   }
 
-  virtual ~CefStringBase() { ClearAndFree(); }
+  ~CefStringBase() { ClearAndFree(); }
 
-  // The following methods are named for compatibility with the standard library
-  // string template types.
+  /// The following methods are named for compatibility with the standard
+  /// library string template types.
 
   ///
-  // Return a read-only pointer to the string data.
+  /// Return a read-only pointer to the string data.
   ///
   const char_type* c_str() const { return (string_ ? string_->str : NULL); }
 
   ///
-  // Return the length of the string data.
+  /// Return the length of the string data.
   ///
   size_t length() const { return (string_ ? string_->length : 0); }
 
   ///
-  // Return the length of the string data.
+  /// Return the length of the string data.
   ///
   inline size_t size() const { return length(); }
 
   ///
-  // Returns true if the string is empty.
+  /// Returns true if the string is empty.
   ///
   bool empty() const { return (string_ == NULL || string_->length == 0); }
 
   ///
-  // Compare this string to the specified string.
+  /// Compare this string to the specified string.
   ///
   int compare(const CefStringBase& str) const {
-    if (empty() && str.empty())
+    if (empty() && str.empty()) {
       return 0;
-    if (empty())
+    }
+    if (empty()) {
       return -1;
-    if (str.empty())
+    }
+    if (str.empty()) {
       return 1;
+    }
     return traits::compare(string_, str.GetStruct());
   }
 
   ///
-  // Clear the string data.
+  /// Clear the string data.
   ///
   void clear() {
-    if (string_)
+    if (string_) {
       traits::clear(string_);
+    }
   }
 
   ///
-  // Swap this string's contents with the specified string.
+  /// Swap this string's contents with the specified string.
   ///
   void swap(CefStringBase& str) {
     struct_type* tmp_string = string_;
@@ -429,19 +507,19 @@
   // The following methods are unique to CEF string template types.
 
   ///
-  // Returns true if this class owns the underlying string structure.
+  /// Returns true if this class owns the underlying string structure.
   ///
   bool IsOwner() const { return owner_; }
 
   ///
-  // Returns a read-only pointer to the underlying string structure. May return
-  // NULL if no structure is currently allocated.
+  /// Returns a read-only pointer to the underlying string structure. May return
+  /// NULL if no structure is currently allocated.
   ///
   const struct_type* GetStruct() const { return string_; }
 
   ///
-  // Returns a writable pointer to the underlying string structure. Will never
-  // return NULL.
+  /// Returns a writable pointer to the underlying string structure. Will never
+  /// return NULL.
   ///
   struct_type* GetWritableStruct() {
     AllocIfNeeded();
@@ -449,12 +527,13 @@
   }
 
   ///
-  // Clear the state of this class. The underlying string structure and data
-  // will be freed if this class owns the structure.
+  /// Clear the state of this class. The underlying string structure and data
+  /// will be freed if this class owns the structure.
   ///
   void ClearAndFree() {
-    if (!string_)
+    if (!string_) {
       return;
+    }
     if (owner_) {
       clear();
       delete string_;
@@ -464,8 +543,8 @@
   }
 
   ///
-  // Attach to the specified string structure. If |owner| is true this class
-  // will take ownership of the structure.
+  /// Attach to the specified string structure. If |owner| is true this class
+  /// will take ownership of the structure.
   ///
   void Attach(struct_type* str, bool owner) {
     // Free the previous structure and data, if any.
@@ -476,30 +555,31 @@
   }
 
   ///
-  // Take ownership of the specified userfree structure's string data. The
-  // userfree structure itself will be freed. Only use this method with userfree
-  // structures.
+  /// Take ownership of the specified userfree structure's string data. The
+  /// userfree structure itself will be freed. Only use this method with
+  /// userfree structures.
   ///
   void AttachToUserFree(userfree_struct_type str) {
     // Free the previous structure and data, if any.
     ClearAndFree();
 
-    if (!str)
+    if (!str) {
       return;
+    }
 
     AllocIfNeeded();
     owner_ = true;
     memcpy(string_, str, sizeof(struct_type));
 
-    // Free the |str| structure but not the data.
+    /// Free the |str| structure but not the data.
     memset(str, 0, sizeof(struct_type));
     traits::userfree_free(str);
   }
 
   ///
-  // Detach from the underlying string structure. To avoid memory leaks only use
-  // this method if you already hold a pointer to the underlying string
-  // structure.
+  /// Detach from the underlying string structure. To avoid memory leaks only
+  /// use this method if you already hold a pointer to the underlying string
+  /// structure.
   ///
   void Detach() {
     string_ = NULL;
@@ -507,29 +587,36 @@
   }
 
   ///
-  // Create a userfree structure and give it ownership of this class' string
-  // data. This class will be disassociated from the data. May return NULL if
-  // this string class currently contains no data.
+  /// Create a userfree structure and give it ownership of this class' string
+  /// data. This class will be disassociated from the data. May return NULL if
+  /// this string class currently contains no data.
   ///
   userfree_struct_type DetachToUserFree() {
-    if (empty())
+    if (empty()) {
       return NULL;
+    }
 
     userfree_struct_type str = traits::userfree_alloc();
-    memcpy(str, string_, sizeof(struct_type));
+    if (owner_) {
+      // Transfer ownership of the data to |str|.
+      memcpy(str, string_, sizeof(struct_type));
+      // Free this class' structure but not the data.
+      memset(string_, 0, sizeof(struct_type));
+    } else {
+      // Copy the data to |str|.
+      traits::set(string_->str, string_->length, str, /*copy=*/true);
+    }
 
-    // Free this class' structure but not the data.
-    memset(string_, 0, sizeof(struct_type));
     ClearAndFree();
 
     return str;
   }
 
   ///
-  // Set this string's data to the specified character array. If |copy| is true
-  // this class will copy the data. Otherwise, this class will reference the
-  // existing data. Referenced data must exist for the lifetime of this class
-  // and will not be freed by this class.
+  /// Set this string's data to the specified character array. If |copy| is true
+  /// this class will copy the data. Otherwise, this class will reference the
+  /// existing data. Referenced data must exist for the lifetime of this class
+  /// and will not be freed by this class.
   ///
   bool FromString(const char_type* src, size_t src_len, bool copy) {
     if (src == NULL || src_len == 0) {
@@ -541,9 +628,9 @@
   }
 
   ///
-  // Set this string's data from an existing ASCII string. Data will be always
-  // copied. Translation will occur if necessary based on the underlying string
-  // type.
+  /// Set this string's data from an existing ASCII string. Data will be always
+  /// copied. Translation will occur if necessary based on the underlying string
+  /// type.
   ///
   bool FromASCII(const char* str) {
     size_t len = str ? strlen(str) : 0;
@@ -556,19 +643,20 @@
   }
 
   ///
-  // Return this string's data as a std::string. Translation will occur if
-  // necessary based on the underlying string type.
+  /// Return this string's data as a std::string. Translation will occur if
+  /// necessary based on the underlying string type.
   ///
   std::string ToString() const {
-    if (empty())
+    if (empty()) {
       return std::string();
+    }
     return traits::to_string(string_);
   }
 
   ///
-  // Set this string's data from an existing std::string. Data will be always
-  // copied. Translation will occur if necessary based on the underlying string
-  // type.
+  /// Set this string's data from an existing std::string. Data will be always
+  /// copied. Translation will occur if necessary based on the underlying string
+  /// type.
   ///
   bool FromString(const std::string& str) {
     if (str.empty()) {
@@ -580,19 +668,37 @@
   }
 
   ///
-  // Return this string's data as a std::wstring. Translation will occur if
-  // necessary based on the underlying string type.
+  /// Set this string's data from existing |data| and optional |length|. Data
+  /// will be always copied. Translation will occur if necessary based on the
+  /// underlying string type.
+  ///
+  bool FromString(const std::string::value_type* data, size_t length = 0) {
+    if (data && length == 0) {
+      length = std::char_traits<std::string::value_type>::length(data);
+    }
+    if (!data || length == 0) {
+      clear();
+      return true;
+    }
+    AllocIfNeeded();
+    return traits::from_string(data, length, string_);
+  }
+
+  ///
+  /// Return this string's data as a std::wstring. Translation will occur if
+  /// necessary based on the underlying string type.
   ///
   std::wstring ToWString() const {
-    if (empty())
+    if (empty()) {
       return std::wstring();
+    }
     return traits::to_wstring(string_);
   }
 
   ///
-  // Set this string's data from an existing std::wstring. Data will be always
-  // copied. Translation will occur if necessary based on the underlying string
-  // type.
+  /// Set this string's data from an existing std::wstring. Data will be always
+  /// copied. Translation will occur if necessary based on the underlying string
+  /// type.
   ///
   bool FromWString(const std::wstring& str) {
     if (str.empty()) {
@@ -604,21 +710,39 @@
   }
 
   ///
-  // Return this string's data as a string16. Translation will occur if
-  // necessary based on the underlying string type.
+  /// Set this string's data from existing |data| and optional |length|. Data
+  /// will be always copied. Translation will occur if necessary based on the
+  /// underlying string type.
   ///
-  base::string16 ToString16() const {
-    if (empty())
-      return base::string16();
+  bool FromWString(const std::wstring::value_type* data, size_t length = 0) {
+    if (data && length == 0) {
+      length = std::char_traits<std::wstring::value_type>::length(data);
+    }
+    if (!data || length == 0) {
+      clear();
+      return true;
+    }
+    AllocIfNeeded();
+    return traits::from_wstring(data, length, string_);
+  }
+
+  ///
+  /// Return this string's data as a string16. Translation will occur if
+  /// necessary based on the underlying string type.
+  ///
+  std::u16string ToString16() const {
+    if (empty()) {
+      return std::u16string();
+    }
     return traits::to_string16(string_);
   }
 
   ///
-  // Set this string's data from an existing string16. Data will be always
-  // copied. Translation will occur if necessary based on the underlying string
-  // type.
+  /// Set this string's data from an existing string16. Data will be always
+  /// copied. Translation will occur if necessary based on the underlying string
+  /// type.
   ///
-  bool FromString16(const base::string16& str) {
+  bool FromString16(const std::u16string& str) {
     if (str.empty()) {
       clear();
       return true;
@@ -628,7 +752,24 @@
   }
 
   ///
-  // Comparison operator overloads.
+  /// Set this string's data from existing |data| and optional |length|. Data
+  /// will be always copied. Translation will occur if necessary based on the
+  /// underlying string type.
+  ///
+  bool FromString16(const std::u16string::value_type* data, size_t length = 0) {
+    if (data && length == 0) {
+      length = std::char_traits<std::u16string::value_type>::length(data);
+    }
+    if (!data || length == 0) {
+      clear();
+      return true;
+    }
+    AllocIfNeeded();
+    return traits::from_string16(data, length, string_);
+  }
+
+  ///
+  /// Comparison operator overloads.
   ///
   bool operator<(const CefStringBase& str) const { return (compare(str) < 0); }
   bool operator<=(const CefStringBase& str) const {
@@ -646,7 +787,7 @@
   }
 
   ///
-  // Assignment operator overloads.
+  /// Assignment operator overloads.
   ///
   CefStringBase& operator=(const CefStringBase& str) {
     FromString(str.c_str(), str.length(), true);
@@ -657,8 +798,8 @@
     FromString(str);
     return *this;
   }
-  CefStringBase& operator=(const char* str) {
-    FromString(std::string(str));
+  CefStringBase& operator=(const std::string::value_type* str) {
+    FromString(str);
     return *this;
   }
   operator std::wstring() const { return ToWString(); }
@@ -666,21 +807,19 @@
     FromWString(str);
     return *this;
   }
-  CefStringBase& operator=(const wchar_t* str) {
-    FromWString(std::wstring(str));
+  CefStringBase& operator=(const std::wstring::value_type* str) {
+    FromWString(str);
     return *this;
   }
-#if defined(WCHAR_T_IS_UTF32)
-  operator base::string16() const { return ToString16(); }
-  CefStringBase& operator=(const base::string16& str) {
+  operator std::u16string() const { return ToString16(); }
+  CefStringBase& operator=(const std::u16string& str) {
     FromString16(str);
     return *this;
   }
-  CefStringBase& operator=(const char16* str) {
-    FromString16(base::string16(str));
+  CefStringBase& operator=(const std::u16string::value_type* str) {
+    FromString16(str);
     return *this;
   }
-#endif  // WCHAR_T_IS_UTF32
 #if defined(USING_CHROMIUM_INCLUDES)
   // The base::FilePath constructor is marked as explicit so provide the
   // conversion here for convenience.
@@ -694,7 +833,7 @@
 #endif  // USING_CHROMIUM_INCLUDES
 
  private:
-  // Allocate the string structure if it doesn't already exist.
+  /// Allocate the string structure if it doesn't already exist.
   void AllocIfNeeded() {
     if (string_ == NULL) {
       string_ = new struct_type;
diff --git a/src/include/internal/cef_thread_internal.h b/src/include/internal/cef_thread_internal.h
index f326bcd..7df3be8 100644
--- a/src/include/internal/cef_thread_internal.h
+++ b/src/include/internal/cef_thread_internal.h
@@ -53,9 +53,9 @@
 #endif
 
 ///
-// Returns the current platform thread ID.
+/// Returns the current platform thread ID.
 ///
-CEF_EXPORT cef_platform_thread_id_t cef_get_current_platform_thread_id();
+CEF_EXPORT cef_platform_thread_id_t cef_get_current_platform_thread_id(void);
 
 #if defined(OS_WIN)
 typedef DWORD cef_platform_thread_handle_t;
@@ -66,10 +66,10 @@
 #endif
 
 ///
-// Returns the current platform thread handle.
+/// Returns the current platform thread handle.
 ///
 CEF_EXPORT cef_platform_thread_handle_t
-cef_get_current_platform_thread_handle();
+cef_get_current_platform_thread_handle(void);
 
 #ifdef __cplusplus
 }
diff --git a/src/include/internal/cef_time.h b/src/include/internal/cef_time.h
index 5435e59..1a3d6c3 100644
--- a/src/include/internal/cef_time.h
+++ b/src/include/internal/cef_time.h
@@ -35,53 +35,117 @@
 extern "C" {
 #endif
 
+#include <stdint.h>
 #include <time.h>
+
 #include "include/internal/cef_export.h"
 
 ///
-// Time information. Values should always be in UTC.
+/// Represents a wall clock time in UTC. Values are not guaranteed to be
+/// monotonically non-decreasing and are subject to large amounts of skew.
+/// Time is stored internally as microseconds since the Windows epoch (1601).
+///
+/// This is equivalent of Chromium `base::Time` (see base/time/time.h).
+///
+typedef struct _cef_basetime_t {
+  int64_t val;
+} cef_basetime_t;
+
+///
+/// Time information. Values should always be in UTC.
 ///
 typedef struct _cef_time_t {
-  int year;          // Four or five digit year "2007" (1601 to 30827 on
-                     //   Windows, 1970 to 2038 on 32-bit POSIX)
-  int month;         // 1-based month (values 1 = January, etc.)
-  int day_of_week;   // 0-based day of week (0 = Sunday, etc.)
-  int day_of_month;  // 1-based day of month (1-31)
-  int hour;          // Hour within the current day (0-23)
-  int minute;        // Minute within the current hour (0-59)
-  int second;        // Second within the current minute (0-59 plus leap
-                     //   seconds which may take it up to 60).
-  int millisecond;   // Milliseconds within the current second (0-999)
+  ///
+  /// Four or five digit year "2007" (1601 to 30827 on Windows, 1970 to 2038 on
+  /// 32-bit POSIX)
+  ///
+  int year;
+
+  ///
+  /// 1-based month (values 1 = January, etc.)
+  ///
+  int month;
+
+  ///
+  /// 0-based day of week (0 = Sunday, etc.)
+  ///
+  int day_of_week;
+
+  ///
+  /// 1-based day of month (1-31)
+  ///
+  int day_of_month;
+
+  ///
+  /// Hour within the current day (0-23)
+  ///
+  int hour;
+
+  ///
+  /// Minute within the current hour (0-59)
+  ///
+  int minute;
+
+  ///
+  /// Second within the current minute (0-59 plus leap seconds which may take
+  /// it up to 60).
+  ///
+  int second;
+
+  ///
+  /// Milliseconds within the current second (0-999)
+  ///
+  int millisecond;
 } cef_time_t;
 
 ///
-// Converts cef_time_t to/from time_t. Returns true (1) on success and false (0)
-// on failure.
+/// Converts cef_time_t to/from time_t. Returns true (1) on success and false
+/// (0) on failure.
 ///
 CEF_EXPORT int cef_time_to_timet(const cef_time_t* cef_time, time_t* time);
 CEF_EXPORT int cef_time_from_timet(time_t time, cef_time_t* cef_time);
 
 ///
-// Converts cef_time_t to/from a double which is the number of seconds since
-// epoch (Jan 1, 1970). Webkit uses this format to represent time. A value of 0
-// means "not initialized". Returns true (1) on success and false (0) on
-// failure.
+/// Converts cef_time_t to/from a double which is the number of seconds since
+/// epoch (Jan 1, 1970). Webkit uses this format to represent time. A value of 0
+/// means "not initialized". Returns true (1) on success and false (0) on
+/// failure.
 ///
 CEF_EXPORT int cef_time_to_doublet(const cef_time_t* cef_time, double* time);
 CEF_EXPORT int cef_time_from_doublet(double time, cef_time_t* cef_time);
 
 ///
-// Retrieve the current system time.
-//
+/// Retrieve the current system time. Returns true (1) on success and false (0)
+/// on failure.
+///
 CEF_EXPORT int cef_time_now(cef_time_t* cef_time);
 
 ///
-// Retrieve the delta in milliseconds between two time values.
+/// Retrieve the current system time.
+///
+CEF_EXPORT cef_basetime_t cef_basetime_now(void);
+
+///
+/// Retrieve the delta in milliseconds between two time values. Returns true (1)
+/// on success and false (0) on failure.
 //
 CEF_EXPORT int cef_time_delta(const cef_time_t* cef_time1,
                               const cef_time_t* cef_time2,
                               long long* delta);
 
+///
+/// Converts cef_time_t to cef_basetime_t. Returns true (1) on success and
+/// false (0) on failure.
+///
+CEF_EXPORT int cef_time_to_basetime(const cef_time_t* from, cef_basetime_t* to);
+
+///
+/// Converts cef_basetime_t to cef_time_t. Returns true (1) on success and
+/// false (0) on failure.
+///
+CEF_EXPORT int cef_time_from_basetime(const cef_basetime_t from,
+                                      cef_time_t* to);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/include/internal/cef_time_wrappers.h b/src/include/internal/cef_time_wrappers.h
new file mode 100644
index 0000000..7b5cbfb
--- /dev/null
+++ b/src/include/internal/cef_time_wrappers.h
@@ -0,0 +1,111 @@
+// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CEF_INCLUDE_INTERNAL_CEF_TIME_WRAPPERS_H_
+#define CEF_INCLUDE_INTERNAL_CEF_TIME_WRAPPERS_H_
+#pragma once
+
+#include "include/internal/cef_time.h"
+
+#if defined(USING_CHROMIUM_INCLUDES)
+#include "base/time/time.h"
+#endif
+
+///
+/// Represents a wall clock time in UTC. Values are not guaranteed to be
+/// monotonically non-decreasing and are subject to large amounts of skew.
+/// Time is stored internally as microseconds since the Windows epoch (1601).
+///
+/// This is equivalent of Chromium `base::Time` (see base/time/time.h).
+///
+class CefBaseTime : public cef_basetime_t {
+ public:
+  CefBaseTime() : cef_basetime_t{} {}
+  CefBaseTime(const cef_basetime_t& value) : cef_basetime_t(value) {}
+
+#if defined(USING_CHROMIUM_INCLUDES)
+  CefBaseTime(const base::Time& value)
+      : cef_basetime_t{value.ToDeltaSinceWindowsEpoch().InMicroseconds()} {}
+
+  operator base::Time() const {
+    return base::Time::FromDeltaSinceWindowsEpoch(base::Microseconds(val));
+  }
+#endif
+
+  static CefBaseTime Now() { return cef_basetime_now(); }
+};
+
+///
+/// Class representing a time.
+///
+class CefTime : public cef_time_t {
+ public:
+  CefTime() : cef_time_t{} {}
+  CefTime(const cef_time_t& r) : cef_time_t(r) {}
+  explicit CefTime(time_t r) { SetTimeT(r); }
+  explicit CefTime(double r) { SetDoubleT(r); }
+
+  ///
+  /// Converts to/from time_t.
+  ///
+  void SetTimeT(time_t r) { cef_time_from_timet(r, this); }
+  time_t GetTimeT() const {
+    time_t time = 0;
+    cef_time_to_timet(this, &time);
+    return time;
+  }
+
+  ///
+  /// Converts to/from a double which is the number of seconds since epoch
+  /// (Jan 1, 1970). Webkit uses this format to represent time. A value of 0
+  /// means "not initialized".
+  ///
+  void SetDoubleT(double r) { cef_time_from_doublet(r, this); }
+  double GetDoubleT() const {
+    double time = 0;
+    cef_time_to_doublet(this, &time);
+    return time;
+  }
+
+  ///
+  /// Set this object to now.
+  ///
+  void Now() { cef_time_now(this); }
+
+  ///
+  /// Return the delta between this object and |other| in milliseconds.
+  ///
+  long long Delta(const CefTime& other) {
+    long long delta = 0;
+    cef_time_delta(this, &other, &delta);
+    return delta;
+  }
+};
+
+#endif  // CEF_INCLUDE_INTERNAL_CEF_TIME_WRAPPERS_H_
diff --git a/src/include/internal/cef_trace_event_internal.h b/src/include/internal/cef_trace_event_internal.h
index 6df8707..3c726a8 100644
--- a/src/include/internal/cef_trace_event_internal.h
+++ b/src/include/internal/cef_trace_event_internal.h
@@ -45,77 +45,66 @@
 //   may not include "(quotes) chars.
 // - |argX_name|, |argX_val|, |valueX_name|, |valeX_val| are optional parameters
 //   and represent pairs of name and values of arguments
-// - |copy| is used to avoid memory scoping issues with the |name| and
-//   |arg_name| parameters by copying them
 // - |id| is used to disambiguate counters with the same name, or match async
 //   trace events
 
 CEF_EXPORT void cef_trace_event_instant(const char* category,
                                         const char* name,
                                         const char* arg1_name,
-                                        uint64 arg1_val,
+                                        uint64_t arg1_val,
                                         const char* arg2_name,
-                                        uint64 arg2_val,
-                                        int copy);
+                                        uint64_t arg2_val);
 CEF_EXPORT void cef_trace_event_begin(const char* category,
                                       const char* name,
                                       const char* arg1_name,
-                                      uint64 arg1_val,
+                                      uint64_t arg1_val,
                                       const char* arg2_name,
-                                      uint64 arg2_val,
-                                      int copy);
+                                      uint64_t arg2_val);
 CEF_EXPORT void cef_trace_event_end(const char* category,
                                     const char* name,
                                     const char* arg1_name,
-                                    uint64 arg1_val,
+                                    uint64_t arg1_val,
                                     const char* arg2_name,
-                                    uint64 arg2_val,
-                                    int copy);
+                                    uint64_t arg2_val);
 CEF_EXPORT void cef_trace_counter(const char* category,
                                   const char* name,
                                   const char* value1_name,
-                                  uint64 value1_val,
+                                  uint64_t value1_val,
                                   const char* value2_name,
-                                  uint64 value2_val,
-                                  int copy);
+                                  uint64_t value2_val);
 CEF_EXPORT void cef_trace_counter_id(const char* category,
                                      const char* name,
-                                     uint64 id,
+                                     uint64_t id,
                                      const char* value1_name,
-                                     uint64 value1_val,
+                                     uint64_t value1_val,
                                      const char* value2_name,
-                                     uint64 value2_val,
-                                     int copy);
+                                     uint64_t value2_val);
 CEF_EXPORT void cef_trace_event_async_begin(const char* category,
                                             const char* name,
-                                            uint64 id,
+                                            uint64_t id,
                                             const char* arg1_name,
-                                            uint64 arg1_val,
+                                            uint64_t arg1_val,
                                             const char* arg2_name,
-                                            uint64 arg2_val,
-                                            int copy);
+                                            uint64_t arg2_val);
 CEF_EXPORT void cef_trace_event_async_step_into(const char* category,
                                                 const char* name,
-                                                uint64 id,
-                                                uint64 step,
+                                                uint64_t id,
+                                                uint64_t step,
                                                 const char* arg1_name,
-                                                uint64 arg1_val,
-                                                int copy);
+                                                uint64_t arg1_val);
 CEF_EXPORT void cef_trace_event_async_step_past(const char* category,
                                                 const char* name,
-                                                uint64 id,
-                                                uint64 step,
+                                                uint64_t id,
+                                                uint64_t step,
                                                 const char* arg1_name,
-                                                uint64 arg1_val,
-                                                int copy);
+                                                uint64_t arg1_val);
 CEF_EXPORT void cef_trace_event_async_end(const char* category,
                                           const char* name,
-                                          uint64 id,
+                                          uint64_t id,
                                           const char* arg1_name,
-                                          uint64 arg1_val,
+                                          uint64_t arg1_val,
                                           const char* arg2_name,
-                                          uint64 arg2_val,
-                                          int copy);
+                                          uint64_t arg2_val);
 
 #ifdef __cplusplus
 }
diff --git a/src/include/internal/cef_types.h b/src/include/internal/cef_types.h
index ab4c495..ea3fe8f 100644
--- a/src/include/internal/cef_types.h
+++ b/src/include/internal/cef_types.h
@@ -31,15 +31,20 @@
 #define CEF_INCLUDE_INTERNAL_CEF_TYPES_H_
 #pragma once
 
-#include "include/base/cef_basictypes.h"
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+
 #include "include/internal/cef_string.h"
 #include "include/internal/cef_string_list.h"
 #include "include/internal/cef_time.h"
+#include "include/internal/cef_types_content_settings.h"
+#include "include/internal/cef_types_geometry.h"
 
 // Bring in platform-specific definitions.
 #if defined(OS_WIN)
 #include "include/internal/cef_types_win.h"
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
 #include "include/internal/cef_types_mac.h"
 #elif defined(OS_LINUX)
 #include "include/internal/cef_types_linux.h"
@@ -47,7 +52,7 @@
 
 // 32-bit ARGB color value, not premultiplied. The color components are always
 // in a known order. Equivalent to the SkColor type.
-typedef uint32 cef_color_t;
+typedef uint32_t cef_color_t;
 
 // Return the alpha byte from a cef_color_t value.
 #define CefColorGetA(color) (((color) >> 24) & 0xFF)
@@ -64,449 +69,512 @@
       (static_cast<unsigned>(a) << 24) | (static_cast<unsigned>(r) << 16) | \
       (static_cast<unsigned>(g) << 8) | (static_cast<unsigned>(b) << 0))
 
-// Return an int64 value with the specified low and high int32 component values.
-#define CefInt64Set(int32_low, int32_high)                                \
-  static_cast<int64>((static_cast<uint32>(int32_low)) |                   \
-                     (static_cast<int64>(static_cast<int32>(int32_high))) \
-                         << 32)
+// Return an int64_t value with the specified low and high int32_t component
+// values.
+#define CefInt64Set(int32_low, int32_high) \
+  static_cast<int64_t>(                    \
+      (static_cast<uint32_t>(int32_low)) | \
+      (static_cast<int64_t>(static_cast<int32_t>(int32_high))) << 32)
 
-// Return the low int32 value from an int64 value.
-#define CefInt64GetLow(int64_val) static_cast<int32>(int64_val)
-// Return the high int32 value from an int64 value.
+// Return the low int32_t value from an int64_t value.
+#define CefInt64GetLow(int64_val) static_cast<int32_t>(int64_val)
+// Return the high int32_t value from an int64_t value.
 #define CefInt64GetHigh(int64_val) \
-  static_cast<int32>((static_cast<int64>(int64_val) >> 32) & 0xFFFFFFFFL)
+  static_cast<int32_t>((static_cast<int64_t>(int64_val) >> 32) & 0xFFFFFFFFL)
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 ///
-// Log severity levels.
+/// Log severity levels.
 ///
 typedef enum {
   ///
-  // Default logging (currently INFO logging).
+  /// Default logging (currently INFO logging).
   ///
   LOGSEVERITY_DEFAULT,
 
   ///
-  // Verbose logging.
+  /// Verbose logging.
   ///
   LOGSEVERITY_VERBOSE,
 
   ///
-  // DEBUG logging.
+  /// DEBUG logging.
   ///
   LOGSEVERITY_DEBUG = LOGSEVERITY_VERBOSE,
 
   ///
-  // INFO logging.
+  /// INFO logging.
   ///
   LOGSEVERITY_INFO,
 
   ///
-  // WARNING logging.
+  /// WARNING logging.
   ///
   LOGSEVERITY_WARNING,
 
   ///
-  // ERROR logging.
+  /// ERROR logging.
   ///
   LOGSEVERITY_ERROR,
 
   ///
-  // FATAL logging.
+  /// FATAL logging.
   ///
   LOGSEVERITY_FATAL,
 
   ///
-  // Disable logging to file for all messages, and to stderr for messages with
-  // severity less than FATAL.
+  /// Disable logging to file for all messages, and to stderr for messages with
+  /// severity less than FATAL.
   ///
   LOGSEVERITY_DISABLE = 99
 } cef_log_severity_t;
 
 ///
-// Represents the state of a setting.
+/// Log items prepended to each log line.
 ///
 typedef enum {
   ///
-  // Use the default state for the setting.
+  /// Prepend the default list of items.
+  ///
+  LOG_ITEMS_DEFAULT = 0,
+
+  ///
+  /// Prepend no items.
+  ///
+  LOG_ITEMS_NONE = 1,
+
+  ///
+  /// Prepend the process ID.
+  ///
+  LOG_ITEMS_FLAG_PROCESS_ID = 1 << 1,
+
+  ///
+  /// Prepend the thread ID.
+  ///
+  LOG_ITEMS_FLAG_THREAD_ID = 1 << 2,
+
+  ///
+  /// Prepend the timestamp.
+  ///
+  LOG_ITEMS_FLAG_TIME_STAMP = 1 << 3,
+
+  ///
+  /// Prepend the tickcount.
+  ///
+  LOG_ITEMS_FLAG_TICK_COUNT = 1 << 4,
+
+} cef_log_items_t;
+
+///
+/// Represents the state of a setting.
+///
+typedef enum {
+  ///
+  /// Use the default state for the setting.
   ///
   STATE_DEFAULT = 0,
 
   ///
-  // Enable or allow the setting.
+  /// Enable or allow the setting.
   ///
   STATE_ENABLED,
 
   ///
-  // Disable or disallow the setting.
+  /// Disable or disallow the setting.
   ///
   STATE_DISABLED,
 } cef_state_t;
 
 ///
-// Initialization settings. Specify NULL or 0 to get the recommended default
-// values. Many of these and other settings can also configured using command-
-// line switches.
+/// Initialization settings. Specify NULL or 0 to get the recommended default
+/// values. Many of these and other settings can also configured using command-
+/// line switches.
 ///
 typedef struct _cef_settings_t {
   ///
-  // Size of this structure.
+  /// Size of this structure.
   ///
   size_t size;
 
   ///
-  // Set to true (1) to disable the sandbox for sub-processes. See
-  // cef_sandbox_win.h for requirements to enable the sandbox on Windows. Also
-  // configurable using the "no-sandbox" command-line switch.
+  /// Set to true (1) to disable the sandbox for sub-processes. See
+  /// cef_sandbox_win.h for requirements to enable the sandbox on Windows. Also
+  /// configurable using the "no-sandbox" command-line switch.
   ///
   int no_sandbox;
 
   ///
-  // The path to a separate executable that will be launched for sub-processes.
-  // If this value is empty on Windows or Linux then the main process executable
-  // will be used. If this value is empty on macOS then a helper executable must
-  // exist at "Contents/Frameworks/<app> Helper.app/Contents/MacOS/<app> Helper"
-  // in the top-level app bundle. See the comments on CefExecuteProcess() for
-  // details. If this value is non-empty then it must be an absolute path. Also
-  // configurable using the "browser-subprocess-path" command-line switch.
+  /// The path to a separate executable that will be launched for sub-processes.
+  /// If this value is empty on Windows or Linux then the main process
+  /// executable will be used. If this value is empty on macOS then a helper
+  /// executable must exist at "Contents/Frameworks/<app>
+  /// Helper.app/Contents/MacOS/<app> Helper" in the top-level app bundle. See
+  /// the comments on CefExecuteProcess() for details. If this value is
+  /// non-empty then it must be an absolute path. Also configurable using the
+  /// "browser-subprocess-path" command-line switch.
   ///
   cef_string_t browser_subprocess_path;
 
   ///
-  // The path to the CEF framework directory on macOS. If this value is empty
-  // then the framework must exist at "Contents/Frameworks/Chromium Embedded
-  // Framework.framework" in the top-level app bundle. If this value is
-  // non-empty then it must be an absolute path. Also configurable using the
-  // "framework-dir-path" command-line switch.
+  /// The path to the CEF framework directory on macOS. If this value is empty
+  /// then the framework must exist at "Contents/Frameworks/Chromium Embedded
+  /// Framework.framework" in the top-level app bundle. If this value is
+  /// non-empty then it must be an absolute path. Also configurable using the
+  /// "framework-dir-path" command-line switch.
   ///
   cef_string_t framework_dir_path;
 
   ///
-  // The path to the main bundle on macOS. If this value is empty then it
-  // defaults to the top-level app bundle. If this value is non-empty then it
-  // must be an absolute path. Also configurable using the "main-bundle-path"
-  // command-line switch.
+  /// The path to the main bundle on macOS. If this value is empty then it
+  /// defaults to the top-level app bundle. If this value is non-empty then it
+  /// must be an absolute path. Also configurable using the "main-bundle-path"
+  /// command-line switch.
   ///
   cef_string_t main_bundle_path;
 
   ///
-  // Set to true (1) to have the browser process message loop run in a separate
-  // thread. If false (0) than the CefDoMessageLoopWork() function must be
-  // called from your application message loop. This option is only supported on
-  // Windows and Linux.
+  /// Set to true (1) to enable use of the Chrome runtime in CEF. This feature
+  /// is considered experimental and is not recommended for most users at this
+  /// time. See issue #2969 for details.
+  ///
+  int chrome_runtime;
+
+  ///
+  /// Set to true (1) to have the browser process message loop run in a separate
+  /// thread. If false (0) then the CefDoMessageLoopWork() function must be
+  /// called from your application message loop. This option is only supported
+  /// on Windows and Linux.
   ///
   int multi_threaded_message_loop;
 
   ///
-  // Set to true (1) to control browser process main (UI) thread message pump
-  // scheduling via the CefBrowserProcessHandler::OnScheduleMessagePumpWork()
-  // callback. This option is recommended for use in combination with the
-  // CefDoMessageLoopWork() function in cases where the CEF message loop must be
-  // integrated into an existing application message loop (see additional
-  // comments and warnings on CefDoMessageLoopWork). Enabling this option is not
-  // recommended for most users; leave this option disabled and use either the
-  // CefRunMessageLoop() function or multi_threaded_message_loop if possible.
+  /// Set to true (1) to control browser process main (UI) thread message pump
+  /// scheduling via the CefBrowserProcessHandler::OnScheduleMessagePumpWork()
+  /// callback. This option is recommended for use in combination with the
+  /// CefDoMessageLoopWork() function in cases where the CEF message loop must
+  /// be integrated into an existing application message loop (see additional
+  /// comments and warnings on CefDoMessageLoopWork). Enabling this option is
+  /// not recommended for most users; leave this option disabled and use either
+  /// the CefRunMessageLoop() function or multi_threaded_message_loop if
+  /// possible.
   ///
   int external_message_pump;
 
   ///
-  // Set to true (1) to enable windowless (off-screen) rendering support. Do not
-  // enable this value if the application does not use windowless rendering as
-  // it may reduce rendering performance on some systems.
+  /// Set to true (1) to enable windowless (off-screen) rendering support. Do
+  /// not enable this value if the application does not use windowless rendering
+  /// as it may reduce rendering performance on some systems.
   ///
   int windowless_rendering_enabled;
 
   ///
-  // Set to true (1) to disable configuration of browser process features using
-  // standard CEF and Chromium command-line arguments. Configuration can still
-  // be specified using CEF data structures or via the
-  // CefApp::OnBeforeCommandLineProcessing() method.
+  /// Set to true (1) to disable configuration of browser process features using
+  /// standard CEF and Chromium command-line arguments. Configuration can still
+  /// be specified using CEF data structures or via the
+  /// CefApp::OnBeforeCommandLineProcessing() method.
   ///
   int command_line_args_disabled;
 
   ///
-  // The location where data for the global browser cache will be stored on
-  // disk. If this value is non-empty then it must be an absolute path that is
-  // either equal to or a child directory of CefSettings.root_cache_path. If
-  // this value is empty then browsers will be created in "incognito mode" where
-  // in-memory caches are used for storage and no data is persisted to disk.
-  // HTML5 databases such as localStorage will only persist across sessions if a
-  // cache path is specified. Can be overridden for individual CefRequestContext
-  // instances via the CefRequestContextSettings.cache_path value.
+  /// The location where data for the global browser cache will be stored on
+  /// disk. If this value is non-empty then it must be an absolute path that is
+  /// either equal to or a child directory of CefSettings.root_cache_path. If
+  /// this value is empty then browsers will be created in "incognito mode"
+  /// where in-memory caches are used for storage and no data is persisted to
+  /// disk. HTML5 databases such as localStorage will only persist across
+  /// sessions if a cache path is specified. Can be overridden for individual
+  /// CefRequestContext instances via the CefRequestContextSettings.cache_path
+  /// value. When using the Chrome runtime the "default" profile will be used if
+  /// |cache_path| and |root_cache_path| have the same value.
   ///
   cef_string_t cache_path;
 
   ///
-  // The root directory that all CefSettings.cache_path and
-  // CefRequestContextSettings.cache_path values must have in common. If this
-  // value is empty and CefSettings.cache_path is non-empty then it will
-  // default to the CefSettings.cache_path value. If this value is non-empty
-  // then it must be an absolute path. Failure to set this value correctly may
-  // result in the sandbox blocking read/write access to the cache_path
-  // directory.
+  /// The root directory that all CefSettings.cache_path and
+  /// CefRequestContextSettings.cache_path values must have in common. If this
+  /// value is empty and CefSettings.cache_path is non-empty then it will
+  /// default to the CefSettings.cache_path value. If both values are empty
+  /// then the default platform-specific directory will be used
+  /// ("~/.config/cef_user_data" directory on Linux, "~/Library/Application
+  /// Support/CEF/User Data" directory on MacOS, "AppData\Local\CEF\User Data"
+  /// directory under the user profile directory on Windows). If this value is
+  /// non-empty then it must be an absolute path. Failure to set this value
+  /// correctly may result in the sandbox blocking read/write access to certain
+  /// files.
   ///
   cef_string_t root_cache_path;
 
   ///
-  // The location where user data such as spell checking dictionary files will
-  // be stored on disk. If this value is empty then the default
-  // platform-specific user data directory will be used ("~/.cef_user_data"
-  // directory on Linux, "~/Library/Application Support/CEF/User Data" directory
-  // on Mac OS X, "Local Settings\Application Data\CEF\User Data" directory
-  // under the user profile directory on Windows). If this value is non-empty
-  // then it must be an absolute path.
-  ///
-  cef_string_t user_data_path;
-
-  ///
-  // To persist session cookies (cookies without an expiry date or validity
-  // interval) by default when using the global cookie manager set this value to
-  // true (1). Session cookies are generally intended to be transient and most
-  // Web browsers do not persist them. A |cache_path| value must also be
-  // specified to enable this feature. Also configurable using the
-  // "persist-session-cookies" command-line switch. Can be overridden for
-  // individual CefRequestContext instances via the
-  // CefRequestContextSettings.persist_session_cookies value.
+  /// To persist session cookies (cookies without an expiry date or validity
+  /// interval) by default when using the global cookie manager set this value
+  /// to true (1). Session cookies are generally intended to be transient and
+  /// most Web browsers do not persist them. A |cache_path| value must also be
+  /// specified to enable this feature. Also configurable using the
+  /// "persist-session-cookies" command-line switch. Can be overridden for
+  /// individual CefRequestContext instances via the
+  /// CefRequestContextSettings.persist_session_cookies value.
   ///
   int persist_session_cookies;
 
   ///
-  // To persist user preferences as a JSON file in the cache path directory set
-  // this value to true (1). A |cache_path| value must also be specified
-  // to enable this feature. Also configurable using the
-  // "persist-user-preferences" command-line switch. Can be overridden for
-  // individual CefRequestContext instances via the
-  // CefRequestContextSettings.persist_user_preferences value.
+  /// To persist user preferences as a JSON file in the cache path directory set
+  /// this value to true (1). A |cache_path| value must also be specified
+  /// to enable this feature. Also configurable using the
+  /// "persist-user-preferences" command-line switch. Can be overridden for
+  /// individual CefRequestContext instances via the
+  /// CefRequestContextSettings.persist_user_preferences value.
   ///
   int persist_user_preferences;
 
   ///
-  // Value that will be returned as the User-Agent HTTP header. If empty the
-  // default User-Agent string will be used. Also configurable using the
-  // "user-agent" command-line switch.
+  /// Value that will be returned as the User-Agent HTTP header. If empty the
+  /// default User-Agent string will be used. Also configurable using the
+  /// "user-agent" command-line switch.
   ///
   cef_string_t user_agent;
 
   ///
-  // Value that will be inserted as the product portion of the default
-  // User-Agent string. If empty the Chromium product version will be used. If
-  // |userAgent| is specified this value will be ignored. Also configurable
-  // using the "product-version" command-line switch.
+  /// Value that will be inserted as the product portion of the default
+  /// User-Agent string. If empty the Chromium product version will be used. If
+  /// |userAgent| is specified this value will be ignored. Also configurable
+  /// using the "user-agent-product" command-line switch.
   ///
-  cef_string_t product_version;
+  cef_string_t user_agent_product;
 
   ///
-  // The locale string that will be passed to WebKit. If empty the default
-  // locale of "en-US" will be used. This value is ignored on Linux where locale
-  // is determined using environment variable parsing with the precedence order:
-  // LANGUAGE, LC_ALL, LC_MESSAGES and LANG. Also configurable using the "lang"
-  // command-line switch.
+  /// The locale string that will be passed to WebKit. If empty the default
+  /// locale of "en-US" will be used. This value is ignored on Linux where
+  /// locale is determined using environment variable parsing with the
+  /// precedence order: LANGUAGE, LC_ALL, LC_MESSAGES and LANG. Also
+  /// configurable using the "lang" command-line switch.
   ///
   cef_string_t locale;
 
   ///
-  // The directory and file name to use for the debug log. If empty a default
-  // log file name and location will be used. On Windows and Linux a "debug.log"
-  // file will be written in the main executable directory. On Mac OS X a
-  // "~/Library/Logs/<app name>_debug.log" file will be written where <app name>
-  // is the name of the main app executable. Also configurable using the
-  // "log-file" command-line switch.
+  /// The directory and file name to use for the debug log. If empty a default
+  /// log file name and location will be used. On Windows and Linux a
+  /// "debug.log" file will be written in the main executable directory. On
+  /// MacOS a "~/Library/Logs/[app name]_debug.log" file will be written where
+  /// [app name] is the name of the main app executable. Also configurable using
+  /// the "log-file" command-line switch.
   ///
   cef_string_t log_file;
 
   ///
-  // The log severity. Only messages of this severity level or higher will be
-  // logged. When set to DISABLE no messages will be written to the log file,
-  // but FATAL messages will still be output to stderr. Also configurable using
-  // the "log-severity" command-line switch with a value of "verbose", "info",
-  // "warning", "error", "fatal" or "disable".
+  /// The log severity. Only messages of this severity level or higher will be
+  /// logged. When set to DISABLE no messages will be written to the log file,
+  /// but FATAL messages will still be output to stderr. Also configurable using
+  /// the "log-severity" command-line switch with a value of "verbose", "info",
+  /// "warning", "error", "fatal" or "disable".
   ///
   cef_log_severity_t log_severity;
 
   ///
-  // Custom flags that will be used when initializing the V8 JavaScript engine.
-  // The consequences of using custom flags may not be well tested. Also
-  // configurable using the "js-flags" command-line switch.
+  /// The log items prepended to each log line. If not set the default log items
+  /// will be used. Also configurable using the "log-items" command-line switch
+  /// with a value of "none" for no log items, or a comma-delimited list of
+  /// values "pid", "tid", "timestamp" or "tickcount" for custom log items.
+  ///
+  cef_log_items_t log_items;
+
+  ///
+  /// Custom flags that will be used when initializing the V8 JavaScript engine.
+  /// The consequences of using custom flags may not be well tested. Also
+  /// configurable using the "js-flags" command-line switch.
   ///
   cef_string_t javascript_flags;
 
   ///
-  // The fully qualified path for the resources directory. If this value is
-  // empty the cef.pak and/or devtools_resources.pak files must be located in
-  // the module directory on Windows/Linux or the app bundle Resources directory
-  // on Mac OS X. If this value is non-empty then it must be an absolute path.
-  // Also configurable using the "resources-dir-path" command-line switch.
+  /// The fully qualified path for the resources directory. If this value is
+  /// empty the *.pak files must be located in the module directory on
+  /// Windows/Linux or the app bundle Resources directory on MacOS. If this
+  /// value is non-empty then it must be an absolute path. Also configurable
+  /// using the "resources-dir-path" command-line switch.
   ///
   cef_string_t resources_dir_path;
 
   ///
-  // The fully qualified path for the locales directory. If this value is empty
-  // the locales directory must be located in the module directory. If this
-  // value is non-empty then it must be an absolute path. This value is ignored
-  // on Mac OS X where pack files are always loaded from the app bundle
-  // Resources directory. Also configurable using the "locales-dir-path"
-  // command-line switch.
+  /// The fully qualified path for the locales directory. If this value is empty
+  /// the locales directory must be located in the module directory. If this
+  /// value is non-empty then it must be an absolute path. This value is ignored
+  /// on MacOS where pack files are always loaded from the app bundle Resources
+  /// directory. Also configurable using the "locales-dir-path" command-line
+  /// switch.
   ///
   cef_string_t locales_dir_path;
 
   ///
-  // Set to true (1) to disable loading of pack files for resources and locales.
-  // A resource bundle handler must be provided for the browser and render
-  // processes via CefApp::GetResourceBundleHandler() if loading of pack files
-  // is disabled. Also configurable using the "disable-pack-loading" command-
-  // line switch.
+  /// Set to true (1) to disable loading of pack files for resources and
+  /// locales. A resource bundle handler must be provided for the browser and
+  /// render processes via CefApp::GetResourceBundleHandler() if loading of pack
+  /// files is disabled. Also configurable using the "disable-pack-loading"
+  /// command- line switch.
   ///
   int pack_loading_disabled;
 
   ///
-  // Set to a value between 1024 and 65535 to enable remote debugging on the
-  // specified port. For example, if 8080 is specified the remote debugging URL
-  // will be http://localhost:8080. CEF can be remotely debugged from any CEF or
-  // Chrome browser window. Also configurable using the "remote-debugging-port"
-  // command-line switch.
+  /// Set to a value between 1024 and 65535 to enable remote debugging on the
+  /// specified port. Also configurable using the "remote-debugging-port"
+  /// command-line switch. Remote debugging can be accessed by loading the
+  /// chrome://inspect page in Google Chrome. Port numbers 9222 and 9229 are
+  /// discoverable by default. Other port numbers may need to be configured via
+  /// "Discover network targets" on the Devices tab.
   ///
   int remote_debugging_port;
 
   ///
-  // The number of stack trace frames to capture for uncaught exceptions.
-  // Specify a positive value to enable the CefRenderProcessHandler::
-  // OnUncaughtException() callback. Specify 0 (default value) and
-  // OnUncaughtException() will not be called. Also configurable using the
-  // "uncaught-exception-stack-size" command-line switch.
+  /// The number of stack trace frames to capture for uncaught exceptions.
+  /// Specify a positive value to enable the
+  /// CefRenderProcessHandler::OnUncaughtException() callback. Specify 0
+  /// (default value) and OnUncaughtException() will not be called. Also
+  /// configurable using the "uncaught-exception-stack-size" command-line
+  /// switch.
   ///
   int uncaught_exception_stack_size;
 
   ///
-  // Set to true (1) to ignore errors related to invalid SSL certificates.
-  // Enabling this setting can lead to potential security vulnerabilities like
-  // "man in the middle" attacks. Applications that load content from the
-  // internet should not enable this setting. Also configurable using the
-  // "ignore-certificate-errors" command-line switch. Can be overridden for
-  // individual CefRequestContext instances via the
-  // CefRequestContextSettings.ignore_certificate_errors value.
-  ///
-  int ignore_certificate_errors;
-
-  ///
-  // Background color used for the browser before a document is loaded and when
-  // no document color is specified. The alpha component must be either fully
-  // opaque (0xFF) or fully transparent (0x00). If the alpha component is fully
-  // opaque then the RGB components will be used as the background color. If the
-  // alpha component is fully transparent for a windowed browser then the
-  // default value of opaque white be used. If the alpha component is fully
-  // transparent for a windowless (off-screen) browser then transparent painting
-  // will be enabled.
+  /// Background color used for the browser before a document is loaded and when
+  /// no document color is specified. The alpha component must be either fully
+  /// opaque (0xFF) or fully transparent (0x00). If the alpha component is fully
+  /// opaque then the RGB components will be used as the background color. If
+  /// the alpha component is fully transparent for a windowed browser then the
+  /// default value of opaque white be used. If the alpha component is fully
+  /// transparent for a windowless (off-screen) browser then transparent
+  /// painting will be enabled.
   ///
   cef_color_t background_color;
 
   ///
-  // Comma delimited ordered list of language codes without any whitespace that
-  // will be used in the "Accept-Language" HTTP header. May be overridden on a
-  // per-browser basis using the CefBrowserSettings.accept_language_list value.
-  // If both values are empty then "en-US,en" will be used. Can be overridden
-  // for individual CefRequestContext instances via the
-  // CefRequestContextSettings.accept_language_list value.
+  /// Comma delimited ordered list of language codes without any whitespace that
+  /// will be used in the "Accept-Language" HTTP request header and
+  /// "navigator.language" JS attribute. Can be overridden for individual
+  /// CefRequestContext instances via the
+  /// CefRequestContextSettings.accept_language_list value.
   ///
   cef_string_t accept_language_list;
 
   ///
-  // GUID string used for identifying the application. This is passed to the
-  // system AV function for scanning downloaded files. By default, the GUID
-  // will be an empty string and the file will be treated as an untrusted
-  // file when the GUID is empty.
+  /// Comma delimited list of schemes supported by the associated
+  /// CefCookieManager. If |cookieable_schemes_exclude_defaults| is false (0)
+  /// the default schemes ("http", "https", "ws" and "wss") will also be
+  /// supported. Not specifying a |cookieable_schemes_list| value and setting
+  /// |cookieable_schemes_exclude_defaults| to true (1) will disable all loading
+  /// and saving of cookies. These settings will only impact the global
+  /// CefRequestContext. Individual CefRequestContext instances can be
+  /// configured via the CefRequestContextSettings.cookieable_schemes_list and
+  /// CefRequestContextSettings.cookieable_schemes_exclude_defaults values.
   ///
-  cef_string_t application_client_id_for_file_scanning;
+  cef_string_t cookieable_schemes_list;
+  int cookieable_schemes_exclude_defaults;
+
+  ///
+  /// Specify an ID to enable Chrome policy management via Platform and OS-user
+  /// policies. On Windows, this is a registry key like
+  /// "SOFTWARE\\Policies\\Google\\Chrome". On MacOS, this is a bundle ID like
+  /// "com.google.Chrome". On Linux, this is an absolute directory path like
+  /// "/etc/opt/chrome/policies". Only supported with the Chrome runtime. See
+  /// https://support.google.com/chrome/a/answer/9037717 for details.
+  ///
+  /// Chrome Browser Cloud Management integration, when enabled via the
+  /// "enable-chrome-browser-cloud-management" command-line flag, will also use
+  /// the specified ID. See https://support.google.com/chrome/a/answer/9116814
+  /// for details.
+  ///
+  cef_string_t chrome_policy_id;
 } cef_settings_t;
 
 ///
-// Request context initialization settings. Specify NULL or 0 to get the
-// recommended default values.
+/// Request context initialization settings. Specify NULL or 0 to get the
+/// recommended default values.
 ///
 typedef struct _cef_request_context_settings_t {
   ///
-  // Size of this structure.
+  /// Size of this structure.
   ///
   size_t size;
 
   ///
-  // The location where cache data for this request context will be stored on
-  // disk. If this value is non-empty then it must be an absolute path that is
-  // either equal to or a child directory of CefSettings.root_cache_path. If
-  // this value is empty then browsers will be created in "incognito mode" where
-  // in-memory caches are used for storage and no data is persisted to disk.
-  // HTML5 databases such as localStorage will only persist across sessions if a
-  // cache path is specified. To share the global browser cache and related
-  // configuration set this value to match the CefSettings.cache_path value.
+  /// The location where cache data for this request context will be stored on
+  /// disk. If this value is non-empty then it must be an absolute path that is
+  /// either equal to or a child directory of CefSettings.root_cache_path. If
+  /// this value is empty then browsers will be created in "incognito mode"
+  /// where in-memory caches are used for storage and no data is persisted to
+  /// disk. HTML5 databases such as localStorage will only persist across
+  /// sessions if a cache path is specified. To share the global browser cache
+  /// and related configuration set this value to match the
+  /// CefSettings.cache_path value.
   ///
   cef_string_t cache_path;
 
   ///
-  // To persist session cookies (cookies without an expiry date or validity
-  // interval) by default when using the global cookie manager set this value to
-  // true (1). Session cookies are generally intended to be transient and most
-  // Web browsers do not persist them. Can be set globally using the
-  // CefSettings.persist_session_cookies value. This value will be ignored if
-  // |cache_path| is empty or if it matches the CefSettings.cache_path value.
+  /// To persist session cookies (cookies without an expiry date or validity
+  /// interval) by default when using the global cookie manager set this value
+  /// to true (1). Session cookies are generally intended to be transient and
+  /// most Web browsers do not persist them. Can be set globally using the
+  /// CefSettings.persist_session_cookies value. This value will be ignored if
+  /// |cache_path| is empty or if it matches the CefSettings.cache_path value.
   ///
   int persist_session_cookies;
 
   ///
-  // To persist user preferences as a JSON file in the cache path directory set
-  // this value to true (1). Can be set globally using the
-  // CefSettings.persist_user_preferences value. This value will be ignored if
-  // |cache_path| is empty or if it matches the CefSettings.cache_path value.
+  /// To persist user preferences as a JSON file in the cache path directory set
+  /// this value to true (1). Can be set globally using the
+  /// CefSettings.persist_user_preferences value. This value will be ignored if
+  /// |cache_path| is empty or if it matches the CefSettings.cache_path value.
   ///
   int persist_user_preferences;
 
   ///
-  // Set to true (1) to ignore errors related to invalid SSL certificates.
-  // Enabling this setting can lead to potential security vulnerabilities like
-  // "man in the middle" attacks. Applications that load content from the
-  // internet should not enable this setting. Can be set globally using the
-  // CefSettings.ignore_certificate_errors value. This value will be ignored if
-  // |cache_path| matches the CefSettings.cache_path value.
-  ///
-  int ignore_certificate_errors;
-
-  ///
-  // Comma delimited ordered list of language codes without any whitespace that
-  // will be used in the "Accept-Language" HTTP header. Can be set globally
-  // using the CefSettings.accept_language_list value or overridden on a per-
-  // browser basis using the CefBrowserSettings.accept_language_list value. If
-  // all values are empty then "en-US,en" will be used. This value will be
-  // ignored if |cache_path| matches the CefSettings.cache_path value.
+  /// Comma delimited ordered list of language codes without any whitespace that
+  /// will be used in the "Accept-Language" HTTP request header and
+  /// "navigator.language" JS attribute. Can be set globally using the
+  /// CefSettings.accept_language_list value. If all values are empty then
+  /// "en-US,en" will be used. This value will be ignored if |cache_path|
+  /// matches the CefSettings.cache_path value.
   ///
   cef_string_t accept_language_list;
+
+  ///
+  /// Comma delimited list of schemes supported by the associated
+  /// CefCookieManager. If |cookieable_schemes_exclude_defaults| is false (0)
+  /// the default schemes ("http", "https", "ws" and "wss") will also be
+  /// supported. Not specifying a |cookieable_schemes_list| value and setting
+  /// |cookieable_schemes_exclude_defaults| to true (1) will disable all loading
+  /// and saving of cookies. These values will be ignored if |cache_path|
+  /// matches the CefSettings.cache_path value.
+  ///
+  cef_string_t cookieable_schemes_list;
+  int cookieable_schemes_exclude_defaults;
 } cef_request_context_settings_t;
 
 ///
-// Browser initialization settings. Specify NULL or 0 to get the recommended
-// default values. The consequences of using custom values may not be well
-// tested. Many of these and other settings can also configured using command-
-// line switches.
+/// Browser initialization settings. Specify NULL or 0 to get the recommended
+/// default values. The consequences of using custom values may not be well
+/// tested. Many of these and other settings can also configured using command-
+/// line switches.
 ///
 typedef struct _cef_browser_settings_t {
   ///
-  // Size of this structure.
+  /// Size of this structure.
   ///
   size_t size;
 
   ///
-  // The maximum rate in frames per second (fps) that CefRenderHandler::OnPaint
-  // will be called for a windowless browser. The actual fps may be lower if
-  // the browser cannot generate frames at the requested rate. The minimum
-  // value is 1 and the maximum value is 60 (default 30). This value can also be
-  // changed dynamically via CefBrowserHost::SetWindowlessFrameRate.
+  /// The maximum rate in frames per second (fps) that CefRenderHandler::OnPaint
+  /// will be called for a windowless browser. The actual fps may be lower if
+  /// the browser cannot generate frames at the requested rate. The minimum
+  /// value is 1 and the maximum value is 60 (default 30). This value can also
+  /// be changed dynamically via CefBrowserHost::SetWindowlessFrameRate.
   ///
   int windowless_frame_rate;
 
-  // The below values map to WebPreferences settings.
+  /// BEGIN values that map to WebPreferences settings.
 
   ///
-  // Font settings.
+  /// Font settings.
   ///
   cef_string_t standard_font_family;
   cef_string_t fixed_font_family;
@@ -520,225 +588,200 @@
   int minimum_logical_font_size;
 
   ///
-  // Default encoding for Web content. If empty "ISO-8859-1" will be used. Also
-  // configurable using the "default-encoding" command-line switch.
+  /// Default encoding for Web content. If empty "ISO-8859-1" will be used. Also
+  /// configurable using the "default-encoding" command-line switch.
   ///
   cef_string_t default_encoding;
 
   ///
-  // Controls the loading of fonts from remote sources. Also configurable using
-  // the "disable-remote-fonts" command-line switch.
+  /// Controls the loading of fonts from remote sources. Also configurable using
+  /// the "disable-remote-fonts" command-line switch.
   ///
   cef_state_t remote_fonts;
 
   ///
-  // Controls whether JavaScript can be executed. Also configurable using the
-  // "disable-javascript" command-line switch.
+  /// Controls whether JavaScript can be executed. Also configurable using the
+  /// "disable-javascript" command-line switch.
   ///
   cef_state_t javascript;
 
   ///
-  // Controls whether JavaScript can be used to close windows that were not
-  // opened via JavaScript. JavaScript can still be used to close windows that
-  // were opened via JavaScript or that have no back/forward history. Also
-  // configurable using the "disable-javascript-close-windows" command-line
-  // switch.
+  /// Controls whether JavaScript can be used to close windows that were not
+  /// opened via JavaScript. JavaScript can still be used to close windows that
+  /// were opened via JavaScript or that have no back/forward history. Also
+  /// configurable using the "disable-javascript-close-windows" command-line
+  /// switch.
   ///
   cef_state_t javascript_close_windows;
 
   ///
-  // Controls whether JavaScript can access the clipboard. Also configurable
-  // using the "disable-javascript-access-clipboard" command-line switch.
+  /// Controls whether JavaScript can access the clipboard. Also configurable
+  /// using the "disable-javascript-access-clipboard" command-line switch.
   ///
   cef_state_t javascript_access_clipboard;
 
   ///
-  // Controls whether DOM pasting is supported in the editor via
-  // execCommand("paste"). The |javascript_access_clipboard| setting must also
-  // be enabled. Also configurable using the "disable-javascript-dom-paste"
-  // command-line switch.
+  /// Controls whether DOM pasting is supported in the editor via
+  /// execCommand("paste"). The |javascript_access_clipboard| setting must also
+  /// be enabled. Also configurable using the "disable-javascript-dom-paste"
+  /// command-line switch.
   ///
   cef_state_t javascript_dom_paste;
 
   ///
-  // Controls whether any plugins will be loaded. Also configurable using the
-  // "disable-plugins" command-line switch.
-  ///
-  cef_state_t plugins;
-
-  ///
-  // Controls whether file URLs will have access to all URLs. Also configurable
-  // using the "allow-universal-access-from-files" command-line switch.
-  ///
-  cef_state_t universal_access_from_file_urls;
-
-  ///
-  // Controls whether file URLs will have access to other file URLs. Also
-  // configurable using the "allow-access-from-files" command-line switch.
-  ///
-  cef_state_t file_access_from_file_urls;
-
-  ///
-  // Controls whether web security restrictions (same-origin policy) will be
-  // enforced. Disabling this setting is not recommend as it will allow risky
-  // security behavior such as cross-site scripting (XSS). Also configurable
-  // using the "disable-web-security" command-line switch.
-  ///
-  cef_state_t web_security;
-
-  ///
-  // Controls whether image URLs will be loaded from the network. A cached image
-  // will still be rendered if requested. Also configurable using the
-  // "disable-image-loading" command-line switch.
+  /// Controls whether image URLs will be loaded from the network. A cached
+  /// image will still be rendered if requested. Also configurable using the
+  /// "disable-image-loading" command-line switch.
   ///
   cef_state_t image_loading;
 
   ///
-  // Controls whether standalone images will be shrunk to fit the page. Also
-  // configurable using the "image-shrink-standalone-to-fit" command-line
-  // switch.
+  /// Controls whether standalone images will be shrunk to fit the page. Also
+  /// configurable using the "image-shrink-standalone-to-fit" command-line
+  /// switch.
   ///
   cef_state_t image_shrink_standalone_to_fit;
 
   ///
-  // Controls whether text areas can be resized. Also configurable using the
-  // "disable-text-area-resize" command-line switch.
+  /// Controls whether text areas can be resized. Also configurable using the
+  /// "disable-text-area-resize" command-line switch.
   ///
   cef_state_t text_area_resize;
 
   ///
-  // Controls whether the tab key can advance focus to links. Also configurable
-  // using the "disable-tab-to-links" command-line switch.
+  /// Controls whether the tab key can advance focus to links. Also configurable
+  /// using the "disable-tab-to-links" command-line switch.
   ///
   cef_state_t tab_to_links;
 
   ///
-  // Controls whether local storage can be used. Also configurable using the
-  // "disable-local-storage" command-line switch.
+  /// Controls whether local storage can be used. Also configurable using the
+  /// "disable-local-storage" command-line switch.
   ///
   cef_state_t local_storage;
 
   ///
-  // Controls whether databases can be used. Also configurable using the
-  // "disable-databases" command-line switch.
+  /// Controls whether databases can be used. Also configurable using the
+  /// "disable-databases" command-line switch.
   ///
   cef_state_t databases;
 
   ///
-  // Controls whether the application cache can be used. Also configurable using
-  // the "disable-application-cache" command-line switch.
-  ///
-  cef_state_t application_cache;
-
-  ///
-  // Controls whether WebGL can be used. Note that WebGL requires hardware
-  // support and may not work on all systems even when enabled. Also
-  // configurable using the "disable-webgl" command-line switch.
+  /// Controls whether WebGL can be used. Note that WebGL requires hardware
+  /// support and may not work on all systems even when enabled. Also
+  /// configurable using the "disable-webgl" command-line switch.
   ///
   cef_state_t webgl;
 
+  /// END values that map to WebPreferences settings.
+
   ///
-  // Background color used for the browser before a document is loaded and when
-  // no document color is specified. The alpha component must be either fully
-  // opaque (0xFF) or fully transparent (0x00). If the alpha component is fully
-  // opaque then the RGB components will be used as the background color. If the
-  // alpha component is fully transparent for a windowed browser then the
-  // CefSettings.background_color value will be used. If the alpha component is
-  // fully transparent for a windowless (off-screen) browser then transparent
-  // painting will be enabled.
+  /// Background color used for the browser before a document is loaded and when
+  /// no document color is specified. The alpha component must be either fully
+  /// opaque (0xFF) or fully transparent (0x00). If the alpha component is fully
+  /// opaque then the RGB components will be used as the background color. If
+  /// the alpha component is fully transparent for a windowed browser then the
+  /// CefSettings.background_color value will be used. If the alpha component is
+  /// fully transparent for a windowless (off-screen) browser then transparent
+  /// painting will be enabled.
   ///
   cef_color_t background_color;
 
   ///
-  // Comma delimited ordered list of language codes without any whitespace that
-  // will be used in the "Accept-Language" HTTP header. May be set globally
-  // using the CefBrowserSettings.accept_language_list value. If both values are
-  // empty then "en-US,en" will be used.
+  /// Controls whether the Chrome status bubble will be used. Only supported
+  /// with the Chrome runtime. For details about the status bubble see
+  /// https://www.chromium.org/user-experience/status-bubble/
   ///
-  cef_string_t accept_language_list;
+  cef_state_t chrome_status_bubble;
+
+  ///
+  /// Controls whether the Chrome zoom bubble will be shown when zooming. Only
+  /// supported with the Chrome runtime.
+  ///
+  cef_state_t chrome_zoom_bubble;
 } cef_browser_settings_t;
 
 ///
-// Return value types.
+/// Return value types.
 ///
 typedef enum {
   ///
-  // Cancel immediately.
+  /// Cancel immediately.
   ///
   RV_CANCEL = 0,
 
   ///
-  // Continue immediately.
+  /// Continue immediately.
   ///
   RV_CONTINUE,
 
   ///
-  // Continue asynchronously (usually via a callback).
+  /// Continue asynchronously (usually via a callback).
   ///
   RV_CONTINUE_ASYNC,
 } cef_return_value_t;
 
 ///
-// URL component parts.
+/// URL component parts.
 ///
 typedef struct _cef_urlparts_t {
   ///
-  // The complete URL specification.
+  /// The complete URL specification.
   ///
   cef_string_t spec;
 
   ///
-  // Scheme component not including the colon (e.g., "http").
+  /// Scheme component not including the colon (e.g., "http").
   ///
   cef_string_t scheme;
 
   ///
-  // User name component.
+  /// User name component.
   ///
   cef_string_t username;
 
   ///
-  // Password component.
+  /// Password component.
   ///
   cef_string_t password;
 
   ///
-  // Host component. This may be a hostname, an IPv4 address or an IPv6 literal
-  // surrounded by square brackets (e.g., "[2001:db8::1]").
+  /// Host component. This may be a hostname, an IPv4 address or an IPv6 literal
+  /// surrounded by square brackets (e.g., "[2001:db8::1]").
   ///
   cef_string_t host;
 
   ///
-  // Port number component.
+  /// Port number component.
   ///
   cef_string_t port;
 
   ///
-  // Origin contains just the scheme, host, and port from a URL. Equivalent to
-  // clearing any username and password, replacing the path with a slash, and
-  // clearing everything after that. This value will be empty for non-standard
-  // URLs.
+  /// Origin contains just the scheme, host, and port from a URL. Equivalent to
+  /// clearing any username and password, replacing the path with a slash, and
+  /// clearing everything after that. This value will be empty for non-standard
+  /// URLs.
   ///
   cef_string_t origin;
 
   ///
-  // Path component including the first slash following the host.
+  /// Path component including the first slash following the host.
   ///
   cef_string_t path;
 
   ///
-  // Query string component (i.e., everything following the '?').
+  /// Query string component (i.e., everything following the '?').
   ///
   cef_string_t query;
 
   ///
-  // Fragment (hash) identifier component (i.e., the string following the '#').
+  /// Fragment (hash) identifier component (i.e., the string following the '#').
   ///
   cef_string_t fragment;
 } cef_urlparts_t;
 
 ///
-// Cookie priority values.
+/// Cookie priority values.
 ///
 typedef enum {
   CEF_COOKIE_PRIORITY_LOW = -1,
@@ -747,7 +790,7 @@
 } cef_cookie_priority_t;
 
 ///
-// Cookie same site values.
+/// Cookie same site values.
 ///
 typedef enum {
   CEF_COOKIE_SAME_SITE_UNSPECIFIED,
@@ -757,152 +800,152 @@
 } cef_cookie_same_site_t;
 
 ///
-// Cookie information.
+/// Cookie information.
 ///
 typedef struct _cef_cookie_t {
   ///
-  // The cookie name.
+  /// The cookie name.
   ///
   cef_string_t name;
 
   ///
-  // The cookie value.
+  /// The cookie value.
   ///
   cef_string_t value;
 
   ///
-  // If |domain| is empty a host cookie will be created instead of a domain
-  // cookie. Domain cookies are stored with a leading "." and are visible to
-  // sub-domains whereas host cookies are not.
+  /// If |domain| is empty a host cookie will be created instead of a domain
+  /// cookie. Domain cookies are stored with a leading "." and are visible to
+  /// sub-domains whereas host cookies are not.
   ///
   cef_string_t domain;
 
   ///
-  // If |path| is non-empty only URLs at or below the path will get the cookie
-  // value.
+  /// If |path| is non-empty only URLs at or below the path will get the cookie
+  /// value.
   ///
   cef_string_t path;
 
   ///
-  // If |secure| is true the cookie will only be sent for HTTPS requests.
+  /// If |secure| is true the cookie will only be sent for HTTPS requests.
   ///
   int secure;
 
   ///
-  // If |httponly| is true the cookie will only be sent for HTTP requests.
+  /// If |httponly| is true the cookie will only be sent for HTTP requests.
   ///
   int httponly;
 
   ///
-  // The cookie creation date. This is automatically populated by the system on
-  // cookie creation.
+  /// The cookie creation date. This is automatically populated by the system on
+  /// cookie creation.
   ///
-  cef_time_t creation;
+  cef_basetime_t creation;
 
   ///
-  // The cookie last access date. This is automatically populated by the system
-  // on access.
+  /// The cookie last access date. This is automatically populated by the system
+  /// on access.
   ///
-  cef_time_t last_access;
+  cef_basetime_t last_access;
 
   ///
-  // The cookie expiration date is only valid if |has_expires| is true.
+  /// The cookie expiration date is only valid if |has_expires| is true.
   ///
   int has_expires;
-  cef_time_t expires;
+  cef_basetime_t expires;
 
   ///
-  // Same site.
+  /// Same site.
   ///
   cef_cookie_same_site_t same_site;
 
   ///
-  // Priority.
+  /// Priority.
   ///
   cef_cookie_priority_t priority;
 } cef_cookie_t;
 
 ///
-// Process termination status values.
+/// Process termination status values.
 ///
 typedef enum {
   ///
-  // Non-zero exit status.
+  /// Non-zero exit status.
   ///
   TS_ABNORMAL_TERMINATION,
 
   ///
-  // SIGKILL or task manager kill.
+  /// SIGKILL or task manager kill.
   ///
   TS_PROCESS_WAS_KILLED,
 
   ///
-  // Segmentation fault.
+  /// Segmentation fault.
   ///
   TS_PROCESS_CRASHED,
 
   ///
-  // Out of memory. Some platforms may use TS_PROCESS_CRASHED instead.
+  /// Out of memory. Some platforms may use TS_PROCESS_CRASHED instead.
   ///
   TS_PROCESS_OOM,
 } cef_termination_status_t;
 
 ///
-// Path key values.
+/// Path key values.
 ///
 typedef enum {
   ///
-  // Current directory.
+  /// Current directory.
   ///
   PK_DIR_CURRENT,
 
   ///
-  // Directory containing PK_FILE_EXE.
+  /// Directory containing PK_FILE_EXE.
   ///
   PK_DIR_EXE,
 
   ///
-  // Directory containing PK_FILE_MODULE.
+  /// Directory containing PK_FILE_MODULE.
   ///
   PK_DIR_MODULE,
 
   ///
-  // Temporary directory.
+  /// Temporary directory.
   ///
   PK_DIR_TEMP,
 
   ///
-  // Path and filename of the current executable.
+  /// Path and filename of the current executable.
   ///
   PK_FILE_EXE,
 
   ///
-  // Path and filename of the module containing the CEF code (usually the libcef
-  // module).
+  /// Path and filename of the module containing the CEF code (usually the
+  /// libcef module).
   ///
   PK_FILE_MODULE,
 
   ///
-  // "Local Settings\Application Data" directory under the user profile
-  // directory on Windows.
+  /// "Local Settings\Application Data" directory under the user profile
+  /// directory on Windows.
   ///
   PK_LOCAL_APP_DATA,
 
   ///
-  // "Application Data" directory under the user profile directory on Windows
-  // and "~/Library/Application Support" directory on Mac OS X.
+  /// "Application Data" directory under the user profile directory on Windows
+  /// and "~/Library/Application Support" directory on MacOS.
   ///
   PK_USER_DATA,
 
   ///
-  // Directory containing application resources. Can be configured via
-  // CefSettings.resources_dir_path.
+  /// Directory containing application resources. Can be configured via
+  /// CefSettings.resources_dir_path.
   ///
   PK_DIR_RESOURCES,
 } cef_path_key_t;
 
 ///
-// Storage types.
+/// Storage types.
 ///
 typedef enum {
   ST_LOCALSTORAGE = 0,
@@ -910,7 +953,8 @@
 } cef_storage_type_t;
 
 ///
-// Supported error code values.
+/// Supported error code values. For the complete list of error values see
+/// "include/base/internal/cef_net_error_list.h".
 ///
 typedef enum {
   // No error.
@@ -923,9 +967,9 @@
 } cef_errorcode_t;
 
 ///
-// Supported certificate status code values. See net\cert\cert_status_flags.h
-// for more information. CERT_STATUS_NONE is new in CEF because we use an
-// enum while cert_status_flags.h uses a typedef and static const variables.
+/// Supported certificate status code values. See net\cert\cert_status_flags.h
+/// for more information. CERT_STATUS_NONE is new in CEF because we use an
+/// enum while cert_status_flags.h uses a typedef and static const variables.
 ///
 typedef enum {
   CERT_STATUS_NONE = 0,
@@ -955,27 +999,80 @@
 } cef_cert_status_t;
 
 ///
-// The manner in which a link click should be opened. These constants match
-// their equivalents in Chromium's window_open_disposition.h and should not be
-// renumbered.
+/// The manner in which a link click should be opened. These constants match
+/// their equivalents in Chromium's window_open_disposition.h and should not be
+/// renumbered.
 ///
 typedef enum {
-  WOD_UNKNOWN,
-  WOD_CURRENT_TAB,
-  WOD_SINGLETON_TAB,
-  WOD_NEW_FOREGROUND_TAB,
-  WOD_NEW_BACKGROUND_TAB,
-  WOD_NEW_POPUP,
-  WOD_NEW_WINDOW,
-  WOD_SAVE_TO_DISK,
-  WOD_OFF_THE_RECORD,
-  WOD_IGNORE_ACTION
+  CEF_WOD_UNKNOWN,
+
+  ///
+  /// Current tab. This is the default in most cases.
+  ///
+  CEF_WOD_CURRENT_TAB,
+
+  ///
+  /// Indicates that only one tab with the url should exist in the same window.
+  ///
+  CEF_WOD_SINGLETON_TAB,
+
+  ///
+  /// Shift key + Middle mouse button or meta/ctrl key while clicking.
+  ///
+  CEF_WOD_NEW_FOREGROUND_TAB,
+
+  ///
+  /// Middle mouse button or meta/ctrl key while clicking.
+  ///
+  CEF_WOD_NEW_BACKGROUND_TAB,
+
+  ///
+  /// New popup window.
+  ///
+  CEF_WOD_NEW_POPUP,
+
+  ///
+  /// Shift key while clicking.
+  ///
+  CEF_WOD_NEW_WINDOW,
+
+  ///
+  /// Alt key while clicking.
+  ///
+  CEF_WOD_SAVE_TO_DISK,
+
+  ///
+  /// New off-the-record (incognito) window.
+  ///
+  CEF_WOD_OFF_THE_RECORD,
+
+  ///
+  /// Special case error condition from the renderer.
+  ///
+  CEF_WOD_IGNORE_ACTION,
+
+  ///
+  /// Activates an existing tab containing the url, rather than navigating.
+  /// This is similar to SINGLETON_TAB, but searches across all windows from
+  /// the current profile and anonymity (instead of just the current one);
+  /// closes the current tab on switching if the current tab was the NTP with
+  /// no session history; and behaves like CURRENT_TAB instead of
+  /// NEW_FOREGROUND_TAB when no existing tab is found.
+  ///
+  CEF_WOD_SWITCH_TO_TAB,
+
+  ///
+  /// Creates a new document picture-in-picture window showing a child WebView.
+  ///
+  CEF_WOD_NEW_PICTURE_IN_PICTURE,
+
+  CEF_WOD_MAX_VALUE = CEF_WOD_NEW_PICTURE_IN_PICTURE,
 } cef_window_open_disposition_t;
 
 ///
-// "Verb" of a drag-and-drop operation as negotiated between the source and
-// destination. These constants match their equivalents in WebCore's
-// DragActions.h and should not be renumbered.
+/// "Verb" of a drag-and-drop operation as negotiated between the source and
+/// destination. These constants match their equivalents in WebCore's
+/// DragActions.h and should not be renumbered.
 ///
 typedef enum {
   DRAG_OPERATION_NONE = 0,
@@ -989,9 +1086,9 @@
 } cef_drag_operations_mask_t;
 
 ///
-// Input mode of a virtual keyboard. These constants match their equivalents
-// in Chromium's text_input_mode.h and should not be renumbered.
-// See https://html.spec.whatwg.org/#input-modalities:-the-inputmode-attribute
+/// Input mode of a virtual keyboard. These constants match their equivalents
+/// in Chromium's text_input_mode.h and should not be renumbered.
+/// See https://html.spec.whatwg.org/#input-modalities:-the-inputmode-attribute
 ///
 typedef enum {
   CEF_TEXT_INPUT_MODE_DEFAULT,
@@ -1008,7 +1105,7 @@
 } cef_text_input_mode_t;
 
 ///
-// V8 access control values.
+/// V8 access control values.
 ///
 typedef enum {
   V8_ACCESS_CONTROL_DEFAULT = 0,
@@ -1018,18 +1115,32 @@
 } cef_v8_accesscontrol_t;
 
 ///
-// V8 property attribute values.
+/// V8 property attribute values.
 ///
 typedef enum {
-  V8_PROPERTY_ATTRIBUTE_NONE = 0,            // Writeable, Enumerable,
-                                             //   Configurable
-  V8_PROPERTY_ATTRIBUTE_READONLY = 1 << 0,   // Not writeable
-  V8_PROPERTY_ATTRIBUTE_DONTENUM = 1 << 1,   // Not enumerable
-  V8_PROPERTY_ATTRIBUTE_DONTDELETE = 1 << 2  // Not configurable
+  ///
+  /// Writeable, Enumerable, Configurable
+  ///
+  V8_PROPERTY_ATTRIBUTE_NONE = 0,
+
+  ///
+  /// Not writeable
+  ///
+  V8_PROPERTY_ATTRIBUTE_READONLY = 1 << 0,
+
+  ///
+  /// Not enumerable
+  ///
+  V8_PROPERTY_ATTRIBUTE_DONTENUM = 1 << 1,
+
+  ///
+  /// Not configurable
+  ///
+  V8_PROPERTY_ATTRIBUTE_DONTDELETE = 1 << 2
 } cef_v8_propertyattribute_t;
 
 ///
-// Post data elements may represent either bytes or files.
+/// Post data elements may represent either bytes or files.
 ///
 typedef enum {
   PDE_TYPE_EMPTY = 0,
@@ -1038,516 +1149,538 @@
 } cef_postdataelement_type_t;
 
 ///
-// Resource type for a request.
+/// Resource type for a request. These constants match their equivalents in
+/// Chromium's ResourceType and should not be renumbered.
 ///
 typedef enum {
   ///
-  // Top level page.
+  /// Top level page.
   ///
   RT_MAIN_FRAME = 0,
 
   ///
-  // Frame or iframe.
+  /// Frame or iframe.
   ///
   RT_SUB_FRAME,
 
   ///
-  // CSS stylesheet.
+  /// CSS stylesheet.
   ///
   RT_STYLESHEET,
 
   ///
-  // External script.
+  /// External script.
   ///
   RT_SCRIPT,
 
   ///
-  // Image (jpg/gif/png/etc).
+  /// Image (jpg/gif/png/etc).
   ///
   RT_IMAGE,
 
   ///
-  // Font.
+  /// Font.
   ///
   RT_FONT_RESOURCE,
 
   ///
-  // Some other subresource. This is the default type if the actual type is
-  // unknown.
+  /// Some other subresource. This is the default type if the actual type is
+  /// unknown.
   ///
   RT_SUB_RESOURCE,
 
   ///
-  // Object (or embed) tag for a plugin, or a resource that a plugin requested.
+  /// Object (or embed) tag for a plugin, or a resource that a plugin requested.
   ///
   RT_OBJECT,
 
   ///
-  // Media resource.
+  /// Media resource.
   ///
   RT_MEDIA,
 
   ///
-  // Main resource of a dedicated worker.
+  /// Main resource of a dedicated worker.
   ///
   RT_WORKER,
 
   ///
-  // Main resource of a shared worker.
+  /// Main resource of a shared worker.
   ///
   RT_SHARED_WORKER,
 
   ///
-  // Explicitly requested prefetch.
+  /// Explicitly requested prefetch.
   ///
   RT_PREFETCH,
 
   ///
-  // Favicon.
+  /// Favicon.
   ///
   RT_FAVICON,
 
   ///
-  // XMLHttpRequest.
+  /// XMLHttpRequest.
   ///
   RT_XHR,
 
   ///
-  // A request for a <ping>
+  /// A request for a "<ping>".
   ///
   RT_PING,
 
   ///
-  // Main resource of a service worker.
+  /// Main resource of a service worker.
   ///
   RT_SERVICE_WORKER,
 
   ///
-  // A report of Content Security Policy violations.
+  /// A report of Content Security Policy violations.
   ///
   RT_CSP_REPORT,
 
   ///
-  // A resource that a plugin requested.
+  /// A resource that a plugin requested.
   ///
   RT_PLUGIN_RESOURCE,
+
+  ///
+  /// A main-frame service worker navigation preload request.
+  ///
+  RT_NAVIGATION_PRELOAD_MAIN_FRAME = 19,
+
+  ///
+  /// A sub-frame service worker navigation preload request.
+  ///
+  RT_NAVIGATION_PRELOAD_SUB_FRAME,
 } cef_resource_type_t;
 
 ///
-// Transition type for a request. Made up of one source value and 0 or more
-// qualifiers.
+/// Transition type for a request. Made up of one source value and 0 or more
+/// qualifiers.
 ///
 typedef enum {
   ///
-  // Source is a link click or the JavaScript window.open function. This is
-  // also the default value for requests like sub-resource loads that are not
-  // navigations.
+  /// Source is a link click or the JavaScript window.open function. This is
+  /// also the default value for requests like sub-resource loads that are not
+  /// navigations.
   ///
   TT_LINK = 0,
 
   ///
-  // Source is some other "explicit" navigation. This is the default value for
-  // navigations where the actual type is unknown. See also TT_DIRECT_LOAD_FLAG.
+  /// Source is some other "explicit" navigation. This is the default value for
+  /// navigations where the actual type is unknown. See also
+  /// TT_DIRECT_LOAD_FLAG.
   ///
   TT_EXPLICIT = 1,
 
   ///
-  // Source is a subframe navigation. This is any content that is automatically
-  // loaded in a non-toplevel frame. For example, if a page consists of several
-  // frames containing ads, those ad URLs will have this transition type.
-  // The user may not even realize the content in these pages is a separate
-  // frame, so may not care about the URL.
+  /// User got to this page through a suggestion in the UI (for example, via the
+  /// destinations page). Chrome runtime only.
+  ///
+  TT_AUTO_BOOKMARK = 2,
+
+  ///
+  /// Source is a subframe navigation. This is any content that is automatically
+  /// loaded in a non-toplevel frame. For example, if a page consists of several
+  /// frames containing ads, those ad URLs will have this transition type.
+  /// The user may not even realize the content in these pages is a separate
+  /// frame, so may not care about the URL.
   ///
   TT_AUTO_SUBFRAME = 3,
 
   ///
-  // Source is a subframe navigation explicitly requested by the user that will
-  // generate new navigation entries in the back/forward list. These are
-  // probably more important than frames that were automatically loaded in
-  // the background because the user probably cares about the fact that this
-  // link was loaded.
+  /// Source is a subframe navigation explicitly requested by the user that will
+  /// generate new navigation entries in the back/forward list. These are
+  /// probably more important than frames that were automatically loaded in
+  /// the background because the user probably cares about the fact that this
+  /// link was loaded.
   ///
   TT_MANUAL_SUBFRAME = 4,
 
   ///
-  // Source is a form submission by the user. NOTE: In some situations
-  // submitting a form does not result in this transition type. This can happen
-  // if the form uses a script to submit the contents.
+  /// User got to this page by typing in the URL bar and selecting an entry
+  /// that did not look like a URL.  For example, a match might have the URL
+  /// of a Google search result page, but appear like "Search Google for ...".
+  /// These are not quite the same as EXPLICIT navigations because the user
+  /// didn't type or see the destination URL. Chrome runtime only.
+  /// See also TT_KEYWORD.
+  ///
+  TT_GENERATED = 5,
+
+  ///
+  /// This is a toplevel navigation. This is any content that is automatically
+  /// loaded in a toplevel frame.  For example, opening a tab to show the ASH
+  /// screen saver, opening the devtools window, opening the NTP after the safe
+  /// browsing warning, opening web-based dialog boxes are examples of
+  /// AUTO_TOPLEVEL navigations. Chrome runtime only.
+  ///
+  TT_AUTO_TOPLEVEL = 6,
+
+  ///
+  /// Source is a form submission by the user. NOTE: In some situations
+  /// submitting a form does not result in this transition type. This can happen
+  /// if the form uses a script to submit the contents.
   ///
   TT_FORM_SUBMIT = 7,
 
   ///
-  // Source is a "reload" of the page via the Reload function or by re-visiting
-  // the same URL. NOTE: This is distinct from the concept of whether a
-  // particular load uses "reload semantics" (i.e. bypasses cached data).
+  /// Source is a "reload" of the page via the Reload function or by re-visiting
+  /// the same URL. NOTE: This is distinct from the concept of whether a
+  /// particular load uses "reload semantics" (i.e. bypasses cached data).
   ///
   TT_RELOAD = 8,
 
   ///
-  // General mask defining the bits used for the source values.
+  /// The url was generated from a replaceable keyword other than the default
+  /// search provider. If the user types a keyword (which also applies to
+  /// tab-to-search) in the omnibox this qualifier is applied to the transition
+  /// type of the generated url. TemplateURLModel then may generate an
+  /// additional visit with a transition type of TT_KEYWORD_GENERATED against
+  /// the url 'http://' + keyword. For example, if you do a tab-to-search
+  /// against wikipedia the generated url has a transition qualifer of
+  /// TT_KEYWORD, and TemplateURLModel generates a visit for 'wikipedia.org'
+  /// with a transition type of TT_KEYWORD_GENERATED. Chrome runtime only.
+  ///
+  TT_KEYWORD = 9,
+
+  ///
+  /// Corresponds to a visit generated for a keyword. See description of
+  /// TT_KEYWORD for more details. Chrome runtime only.
+  ///
+  TT_KEYWORD_GENERATED = 10,
+
+  ///
+  /// General mask defining the bits used for the source values.
   ///
   TT_SOURCE_MASK = 0xFF,
 
-  // Qualifiers.
-  // Any of the core values above can be augmented by one or more qualifiers.
-  // These qualifiers further define the transition.
+  /// Qualifiers.
+  /// Any of the core values above can be augmented by one or more qualifiers.
+  /// These qualifiers further define the transition.
 
   ///
-  // Attempted to visit a URL but was blocked.
+  /// Attempted to visit a URL but was blocked.
   ///
   TT_BLOCKED_FLAG = 0x00800000,
 
   ///
-  // Used the Forward or Back function to navigate among browsing history.
-  // Will be ORed to the transition type for the original load.
+  /// Used the Forward or Back function to navigate among browsing history.
+  /// Will be ORed to the transition type for the original load.
   ///
   TT_FORWARD_BACK_FLAG = 0x01000000,
 
   ///
-  // Loaded a URL directly via CreateBrowser, LoadURL or LoadRequest.
+  /// Loaded a URL directly via CreateBrowser, LoadURL or LoadRequest.
   ///
   TT_DIRECT_LOAD_FLAG = 0x02000000,
 
   ///
-  // The beginning of a navigation chain.
+  /// User is navigating to the home page. Chrome runtime only.
+  ///
+  TT_HOME_PAGE_FLAG = 0x04000000,
+
+  ///
+  /// The transition originated from an external application; the exact
+  /// definition of this is embedder dependent. Chrome runtime and
+  /// extension system only.
+  ///
+  TT_FROM_API_FLAG = 0x08000000,
+
+  ///
+  /// The beginning of a navigation chain.
   ///
   TT_CHAIN_START_FLAG = 0x10000000,
 
   ///
-  // The last transition in a redirect chain.
+  /// The last transition in a redirect chain.
   ///
   TT_CHAIN_END_FLAG = 0x20000000,
 
   ///
-  // Redirects caused by JavaScript or a meta refresh tag on the page.
+  /// Redirects caused by JavaScript or a meta refresh tag on the page.
   ///
   TT_CLIENT_REDIRECT_FLAG = 0x40000000,
 
   ///
-  // Redirects sent from the server by HTTP headers.
+  /// Redirects sent from the server by HTTP headers.
   ///
   TT_SERVER_REDIRECT_FLAG = 0x80000000,
 
   ///
-  // Used to test whether a transition involves a redirect.
+  /// Used to test whether a transition involves a redirect.
   ///
   TT_IS_REDIRECT_MASK = 0xC0000000,
 
   ///
-  // General mask defining the bits used for the qualifiers.
+  /// General mask defining the bits used for the qualifiers.
   ///
   TT_QUALIFIER_MASK = 0xFFFFFF00,
 } cef_transition_type_t;
 
 ///
-// Flags used to customize the behavior of CefURLRequest.
+/// Flags used to customize the behavior of CefURLRequest.
 ///
 typedef enum {
   ///
-  // Default behavior.
+  /// Default behavior.
   ///
   UR_FLAG_NONE = 0,
 
   ///
-  // If set the cache will be skipped when handling the request. Setting this
-  // value is equivalent to specifying the "Cache-Control: no-cache" request
-  // header. Setting this value in combination with UR_FLAG_ONLY_FROM_CACHE will
-  // cause the request to fail.
+  /// If set the cache will be skipped when handling the request. Setting this
+  /// value is equivalent to specifying the "Cache-Control: no-cache" request
+  /// header. Setting this value in combination with UR_FLAG_ONLY_FROM_CACHE
+  /// will cause the request to fail.
   ///
   UR_FLAG_SKIP_CACHE = 1 << 0,
 
   ///
-  // If set the request will fail if it cannot be served from the cache (or some
-  // equivalent local store). Setting this value is equivalent to specifying the
-  // "Cache-Control: only-if-cached" request header. Setting this value in
-  // combination with UR_FLAG_SKIP_CACHE or UR_FLAG_DISABLE_CACHE will cause the
-  // request to fail.
+  /// If set the request will fail if it cannot be served from the cache (or
+  /// some equivalent local store). Setting this value is equivalent to
+  /// specifying the "Cache-Control: only-if-cached" request header. Setting
+  /// this value in combination with UR_FLAG_SKIP_CACHE or UR_FLAG_DISABLE_CACHE
+  /// will cause the request to fail.
   ///
   UR_FLAG_ONLY_FROM_CACHE = 1 << 1,
 
   ///
-  // If set the cache will not be used at all. Setting this value is equivalent
-  // to specifying the "Cache-Control: no-store" request header. Setting this
-  // value in combination with UR_FLAG_ONLY_FROM_CACHE will cause the request to
-  // fail.
+  /// If set the cache will not be used at all. Setting this value is equivalent
+  /// to specifying the "Cache-Control: no-store" request header. Setting this
+  /// value in combination with UR_FLAG_ONLY_FROM_CACHE will cause the request
+  /// to fail.
   ///
   UR_FLAG_DISABLE_CACHE = 1 << 2,
 
   ///
-  // If set user name, password, and cookies may be sent with the request, and
-  // cookies may be saved from the response.
+  /// If set user name, password, and cookies may be sent with the request, and
+  /// cookies may be saved from the response.
   ///
   UR_FLAG_ALLOW_STORED_CREDENTIALS = 1 << 3,
 
   ///
-  // If set upload progress events will be generated when a request has a body.
+  /// If set upload progress events will be generated when a request has a body.
   ///
   UR_FLAG_REPORT_UPLOAD_PROGRESS = 1 << 4,
 
   ///
-  // If set the CefURLRequestClient::OnDownloadData method will not be called.
+  /// If set the CefURLRequestClient::OnDownloadData method will not be called.
   ///
   UR_FLAG_NO_DOWNLOAD_DATA = 1 << 5,
 
   ///
-  // If set 5XX redirect errors will be propagated to the observer instead of
-  // automatically re-tried. This currently only applies for requests
-  // originated in the browser process.
+  /// If set 5XX redirect errors will be propagated to the observer instead of
+  /// automatically re-tried. This currently only applies for requests
+  /// originated in the browser process.
   ///
   UR_FLAG_NO_RETRY_ON_5XX = 1 << 6,
 
   ///
-  // If set 3XX responses will cause the fetch to halt immediately rather than
-  // continue through the redirect.
+  /// If set 3XX responses will cause the fetch to halt immediately rather than
+  /// continue through the redirect.
   ///
   UR_FLAG_STOP_ON_REDIRECT = 1 << 7,
 } cef_urlrequest_flags_t;
 
 ///
-// Flags that represent CefURLRequest status.
+/// Flags that represent CefURLRequest status.
 ///
 typedef enum {
   ///
-  // Unknown status.
+  /// Unknown status.
   ///
   UR_UNKNOWN = 0,
 
   ///
-  // Request succeeded.
+  /// Request succeeded.
   ///
   UR_SUCCESS,
 
   ///
-  // An IO request is pending, and the caller will be informed when it is
-  // completed.
+  /// An IO request is pending, and the caller will be informed when it is
+  /// completed.
   ///
   UR_IO_PENDING,
 
   ///
-  // Request was canceled programatically.
+  /// Request was canceled programatically.
   ///
   UR_CANCELED,
 
   ///
-  // Request failed for some reason.
+  /// Request failed for some reason.
   ///
   UR_FAILED,
 } cef_urlrequest_status_t;
 
-///
-// Structure representing a point.
-///
-typedef struct _cef_point_t {
-  int x;
-  int y;
-} cef_point_t;
-
-///
-// Structure representing a rectangle.
-///
-typedef struct _cef_rect_t {
-  int x;
-  int y;
-  int width;
-  int height;
-} cef_rect_t;
-
-///
-// Structure representing a size.
-///
-typedef struct _cef_size_t {
-  int width;
-  int height;
-} cef_size_t;
-
-///
-// Structure representing a range.
-///
-typedef struct _cef_range_t {
-  int from;
-  int to;
-} cef_range_t;
-
-///
-// Structure representing insets.
-///
-typedef struct _cef_insets_t {
-  int top;
-  int left;
-  int bottom;
-  int right;
-} cef_insets_t;
-
-///
-// Structure representing a draggable region.
+/// Structure representing a draggable region.
 ///
 typedef struct _cef_draggable_region_t {
   ///
-  // Bounds of the region.
+  /// Bounds of the region.
   ///
   cef_rect_t bounds;
 
   ///
-  // True (1) this this region is draggable and false (0) otherwise.
+  /// True (1) this this region is draggable and false (0) otherwise.
   ///
   int draggable;
 } cef_draggable_region_t;
 
 ///
-// Existing process IDs.
+/// Existing process IDs.
 ///
 typedef enum {
   ///
-  // Browser process.
+  /// Browser process.
   ///
   PID_BROWSER,
   ///
-  // Renderer process.
+  /// Renderer process.
   ///
   PID_RENDERER,
 } cef_process_id_t;
 
 ///
-// Existing thread IDs.
+/// Existing thread IDs.
 ///
 typedef enum {
   // BROWSER PROCESS THREADS -- Only available in the browser process.
 
   ///
-  // The main thread in the browser. This will be the same as the main
-  // application thread if CefInitialize() is called with a
-  // CefSettings.multi_threaded_message_loop value of false. Do not perform
-  // blocking tasks on this thread. All tasks posted after
-  // CefBrowserProcessHandler::OnContextInitialized() and before CefShutdown()
-  // are guaranteed to run. This thread will outlive all other CEF threads.
+  /// The main thread in the browser. This will be the same as the main
+  /// application thread if CefInitialize() is called with a
+  /// CefSettings.multi_threaded_message_loop value of false. Do not perform
+  /// blocking tasks on this thread. All tasks posted after
+  /// CefBrowserProcessHandler::OnContextInitialized() and before CefShutdown()
+  /// are guaranteed to run. This thread will outlive all other CEF threads.
   ///
   TID_UI,
 
   ///
-  // Used for blocking tasks (e.g. file system access) where the user won't
-  // notice if the task takes an arbitrarily long time to complete. All tasks
-  // posted after CefBrowserProcessHandler::OnContextInitialized() and before
-  // CefShutdown() are guaranteed to run.
+  /// Used for blocking tasks like file system access where the user won't
+  /// notice if the task takes an arbitrarily long time to complete. All tasks
+  /// posted after CefBrowserProcessHandler::OnContextInitialized() and before
+  /// CefShutdown() are guaranteed to run.
   ///
   TID_FILE_BACKGROUND,
-  TID_FILE = TID_FILE_BACKGROUND,
 
   ///
-  // Used for blocking tasks (e.g. file system access) that affect UI or
-  // responsiveness of future user interactions. Do not use if an immediate
-  // response to a user interaction is expected. All tasks posted after
-  // CefBrowserProcessHandler::OnContextInitialized() and before CefShutdown()
-  // are guaranteed to run.
-  // Examples:
-  // - Updating the UI to reflect progress on a long task.
-  // - Loading data that might be shown in the UI after a future user
-  //   interaction.
+  /// Used for blocking tasks like file system access that affect UI or
+  /// responsiveness of future user interactions. Do not use if an immediate
+  /// response to a user interaction is expected. All tasks posted after
+  /// CefBrowserProcessHandler::OnContextInitialized() and before CefShutdown()
+  /// are guaranteed to run.
+  /// Examples:
+  /// - Updating the UI to reflect progress on a long task.
+  /// - Loading data that might be shown in the UI after a future user
+  ///   interaction.
   ///
   TID_FILE_USER_VISIBLE,
 
   ///
-  // Used for blocking tasks (e.g. file system access) that affect UI
-  // immediately after a user interaction. All tasks posted after
-  // CefBrowserProcessHandler::OnContextInitialized() and before CefShutdown()
-  // are guaranteed to run.
-  // Example: Generating data shown in the UI immediately after a click.
+  /// Used for blocking tasks like file system access that affect UI
+  /// immediately after a user interaction. All tasks posted after
+  /// CefBrowserProcessHandler::OnContextInitialized() and before CefShutdown()
+  /// are guaranteed to run.
+  /// Example: Generating data shown in the UI immediately after a click.
   ///
   TID_FILE_USER_BLOCKING,
 
   ///
-  // Used to launch and terminate browser processes.
+  /// Used to launch and terminate browser processes.
   ///
   TID_PROCESS_LAUNCHER,
 
   ///
-  // Used to process IPC and network messages. Do not perform blocking tasks on
-  // this thread. All tasks posted after
-  // CefBrowserProcessHandler::OnContextInitialized() and before CefShutdown()
-  // are guaranteed to run.
+  /// Used to process IPC and network messages. Do not perform blocking tasks on
+  /// this thread. All tasks posted after
+  /// CefBrowserProcessHandler::OnContextInitialized() and before CefShutdown()
+  /// are guaranteed to run.
   ///
   TID_IO,
 
   // RENDER PROCESS THREADS -- Only available in the render process.
 
   ///
-  // The main thread in the renderer. Used for all WebKit and V8 interaction.
-  // Tasks may be posted to this thread after
-  // CefRenderProcessHandler::OnRenderThreadCreated but are not guaranteed to
-  // run before sub-process termination (sub-processes may be killed at any time
-  // without warning).
+  /// The main thread in the renderer. Used for all WebKit and V8 interaction.
+  /// Tasks may be posted to this thread after
+  /// CefRenderProcessHandler::OnWebKitInitialized but are not guaranteed to
+  /// run before sub-process termination (sub-processes may be killed at any
+  /// time without warning).
   ///
   TID_RENDERER,
 } cef_thread_id_t;
 
 ///
-// Thread priority values listed in increasing order of importance.
+/// Thread priority values listed in increasing order of importance.
 ///
 typedef enum {
   ///
-  // Suitable for threads that shouldn't disrupt high priority work.
+  /// Suitable for threads that shouldn't disrupt high priority work.
   ///
   TP_BACKGROUND,
 
   ///
-  // Default priority level.
+  /// Default priority level.
   ///
   TP_NORMAL,
 
   ///
-  // Suitable for threads which generate data for the display (at ~60Hz).
+  /// Suitable for threads which generate data for the display (at ~60Hz).
   ///
   TP_DISPLAY,
 
   ///
-  // Suitable for low-latency, glitch-resistant audio.
+  /// Suitable for low-latency, glitch-resistant audio.
   ///
   TP_REALTIME_AUDIO,
 } cef_thread_priority_t;
 
 ///
-// Message loop types. Indicates the set of asynchronous events that a message
-// loop can process.
+/// Message loop types. Indicates the set of asynchronous events that a message
+/// loop can process.
 ///
 typedef enum {
   ///
-  // Supports tasks and timers.
+  /// Supports tasks and timers.
   ///
   ML_TYPE_DEFAULT,
 
   ///
-  // Supports tasks, timers and native UI events (e.g. Windows messages).
+  /// Supports tasks, timers and native UI events (e.g. Windows messages).
   ///
   ML_TYPE_UI,
 
   ///
-  // Supports tasks, timers and asynchronous IO events.
+  /// Supports tasks, timers and asynchronous IO events.
   ///
   ML_TYPE_IO,
 } cef_message_loop_type_t;
 
 ///
-// Windows COM initialization mode. Specifies how COM will be initialized for a
-// new thread.
+/// Windows COM initialization mode. Specifies how COM will be initialized for a
+/// new thread.
 ///
 typedef enum {
   ///
-  // No COM initialization.
+  /// No COM initialization.
   ///
   COM_INIT_MODE_NONE,
 
   ///
-  // Initialize COM using single-threaded apartments.
+  /// Initialize COM using single-threaded apartments.
   ///
   COM_INIT_MODE_STA,
 
   ///
-  // Initialize COM using multi-threaded apartments.
+  /// Initialize COM using multi-threaded apartments.
   ///
   COM_INIT_MODE_MTA,
 } cef_com_init_mode_t;
 
 ///
-// Supported value types.
+/// Supported value types.
 ///
 typedef enum {
   VTYPE_INVALID = 0,
@@ -1562,7 +1695,7 @@
 } cef_value_type_t;
 
 ///
-// Supported JavaScript dialog types.
+/// Supported JavaScript dialog types.
 ///
 typedef enum {
   JSDIALOGTYPE_ALERT = 0,
@@ -1571,64 +1704,64 @@
 } cef_jsdialog_type_t;
 
 ///
-// Screen information used when window rendering is disabled. This structure is
-// passed as a parameter to CefRenderHandler::GetScreenInfo and should be filled
-// in by the client.
+/// Screen information used when window rendering is disabled. This structure is
+/// passed as a parameter to CefRenderHandler::GetScreenInfo and should be
+/// filled in by the client.
 ///
 typedef struct _cef_screen_info_t {
   ///
-  // Device scale factor. Specifies the ratio between physical and logical
-  // pixels.
+  /// Device scale factor. Specifies the ratio between physical and logical
+  /// pixels.
   ///
   float device_scale_factor;
 
   ///
-  // The screen depth in bits per pixel.
+  /// The screen depth in bits per pixel.
   ///
   int depth;
 
   ///
-  // The bits per color component. This assumes that the colors are balanced
-  // equally.
+  /// The bits per color component. This assumes that the colors are balanced
+  /// equally.
   ///
   int depth_per_component;
 
   ///
-  // This can be true for black and white printers.
+  /// This can be true for black and white printers.
   ///
   int is_monochrome;
 
   ///
-  // This is set from the rcMonitor member of MONITORINFOEX, to whit:
-  //   "A RECT structure that specifies the display monitor rectangle,
-  //   expressed in virtual-screen coordinates. Note that if the monitor
-  //   is not the primary display monitor, some of the rectangle's
-  //   coordinates may be negative values."
+  /// This is set from the rcMonitor member of MONITORINFOEX, to whit:
+  ///   "A RECT structure that specifies the display monitor rectangle,
+  ///   expressed in virtual-screen coordinates. Note that if the monitor
+  ///   is not the primary display monitor, some of the rectangle's
+  ///   coordinates may be negative values."
   //
-  // The |rect| and |available_rect| properties are used to determine the
-  // available surface for rendering popup views.
+  /// The |rect| and |available_rect| properties are used to determine the
+  /// available surface for rendering popup views.
   ///
   cef_rect_t rect;
 
   ///
-  // This is set from the rcWork member of MONITORINFOEX, to whit:
-  //   "A RECT structure that specifies the work area rectangle of the
-  //   display monitor that can be used by applications, expressed in
-  //   virtual-screen coordinates. Windows uses this rectangle to
-  //   maximize an application on the monitor. The rest of the area in
-  //   rcMonitor contains system windows such as the task bar and side
-  //   bars. Note that if the monitor is not the primary display monitor,
-  //   some of the rectangle's coordinates may be negative values".
+  /// This is set from the rcWork member of MONITORINFOEX, to whit:
+  ///   "A RECT structure that specifies the work area rectangle of the
+  ///   display monitor that can be used by applications, expressed in
+  ///   virtual-screen coordinates. Windows uses this rectangle to
+  ///   maximize an application on the monitor. The rest of the area in
+  ///   rcMonitor contains system windows such as the task bar and side
+  ///   bars. Note that if the monitor is not the primary display monitor,
+  ///   some of the rectangle's coordinates may be negative values".
   //
-  // The |rect| and |available_rect| properties are used to determine the
-  // available surface for rendering popup views.
+  /// The |rect| and |available_rect| properties are used to determine the
+  /// available surface for rendering popup views.
   ///
   cef_rect_t available_rect;
 } cef_screen_info_t;
 
 ///
-// Supported menu IDs. Non-English translations can be provided for the
-// IDS_MENU_* strings in CefResourceBundleHandler::GetLocalizedString().
+/// Supported menu IDs. Non-English translations can be provided for the
+/// IDS_MENU_* strings in CefResourceBundleHandler::GetLocalizedString().
 ///
 typedef enum {
   // Navigation.
@@ -1662,8 +1795,7 @@
   MENU_ID_NO_SPELLING_SUGGESTIONS = 205,
   MENU_ID_ADD_TO_DICTIONARY = 206,
 
-  // Custom menu items originating from the renderer process. For example,
-  // plugin placeholder menu items or Flash menu items.
+  // Custom menu items originating from the renderer process.
   MENU_ID_CUSTOM_FIRST = 220,
   MENU_ID_CUSTOM_LAST = 250,
 
@@ -1675,7 +1807,7 @@
 } cef_menu_id_t;
 
 ///
-// Mouse button types.
+/// Mouse button types.
 ///
 typedef enum {
   MBT_LEFT = 0,
@@ -1684,28 +1816,28 @@
 } cef_mouse_button_type_t;
 
 ///
-// Structure representing mouse event information.
+/// Structure representing mouse event information.
 ///
 typedef struct _cef_mouse_event_t {
   ///
-  // X coordinate relative to the left side of the view.
+  /// X coordinate relative to the left side of the view.
   ///
   int x;
 
   ///
-  // Y coordinate relative to the top side of the view.
+  /// Y coordinate relative to the top side of the view.
   ///
   int y;
 
   ///
-  // Bit flags describing any pressed modifier keys. See
-  // cef_event_flags_t for values.
+  /// Bit flags describing any pressed modifier keys. See
+  /// cef_event_flags_t for values.
   ///
-  uint32 modifiers;
+  uint32_t modifiers;
 } cef_mouse_event_t;
 
 ///
-// Touch points states types.
+/// Touch points states types.
 ///
 typedef enum {
   CEF_TET_RELEASED = 0,
@@ -1715,7 +1847,7 @@
 } cef_touch_event_type_t;
 
 ///
-// The device type that caused the event.
+/// The device type that caused the event.
 ///
 typedef enum {
   CEF_POINTER_TYPE_TOUCH = 0,
@@ -1726,70 +1858,70 @@
 } cef_pointer_type_t;
 
 ///
-// Structure representing touch event information.
+/// Structure representing touch event information.
 ///
 typedef struct _cef_touch_event_t {
   ///
-  // Id of a touch point. Must be unique per touch, can be any number except -1.
-  // Note that a maximum of 16 concurrent touches will be tracked; touches
-  // beyond that will be ignored.
+  /// Id of a touch point. Must be unique per touch, can be any number except
+  /// -1. Note that a maximum of 16 concurrent touches will be tracked; touches
+  /// beyond that will be ignored.
   ///
   int id;
 
   ///
-  // X coordinate relative to the left side of the view.
+  /// X coordinate relative to the left side of the view.
   ///
   float x;
 
   ///
-  // Y coordinate relative to the top side of the view.
+  /// Y coordinate relative to the top side of the view.
   ///
   float y;
 
   ///
-  // X radius in pixels. Set to 0 if not applicable.
+  /// X radius in pixels. Set to 0 if not applicable.
   ///
   float radius_x;
 
   ///
-  // Y radius in pixels. Set to 0 if not applicable.
+  /// Y radius in pixels. Set to 0 if not applicable.
   ///
   float radius_y;
 
   ///
-  // Rotation angle in radians. Set to 0 if not applicable.
+  /// Rotation angle in radians. Set to 0 if not applicable.
   ///
   float rotation_angle;
 
   ///
-  // The normalized pressure of the pointer input in the range of [0,1].
-  // Set to 0 if not applicable.
+  /// The normalized pressure of the pointer input in the range of [0,1].
+  /// Set to 0 if not applicable.
   ///
   float pressure;
 
   ///
-  // The state of the touch point. Touches begin with one CEF_TET_PRESSED event
-  // followed by zero or more CEF_TET_MOVED events and finally one
-  // CEF_TET_RELEASED or CEF_TET_CANCELLED event. Events not respecting this
-  // order will be ignored.
+  /// The state of the touch point. Touches begin with one CEF_TET_PRESSED event
+  /// followed by zero or more CEF_TET_MOVED events and finally one
+  /// CEF_TET_RELEASED or CEF_TET_CANCELLED event. Events not respecting this
+  /// order will be ignored.
   ///
   cef_touch_event_type_t type;
 
   ///
-  // Bit flags describing any pressed modifier keys. See
-  // cef_event_flags_t for values.
+  /// Bit flags describing any pressed modifier keys. See
+  /// cef_event_flags_t for values.
   ///
-  uint32 modifiers;
+  uint32_t modifiers;
 
   ///
-  // The device type that caused the event.
+  /// The device type that caused the event.
   ///
   cef_pointer_type_t pointer_type;
 
 } cef_touch_event_t;
 
 ///
-// Paint element types.
+/// Paint element types.
 ///
 typedef enum {
   PET_VIEW = 0,
@@ -1797,7 +1929,7 @@
 } cef_paint_element_type_t;
 
 ///
-// Supported event bit flags.
+/// Supported event bit flags.
 ///
 typedef enum {
   EVENTFLAG_NONE = 0,
@@ -1808,17 +1940,18 @@
   EVENTFLAG_LEFT_MOUSE_BUTTON = 1 << 4,
   EVENTFLAG_MIDDLE_MOUSE_BUTTON = 1 << 5,
   EVENTFLAG_RIGHT_MOUSE_BUTTON = 1 << 6,
-  // Mac OS-X command key.
+  /// Mac OS-X command key.
   EVENTFLAG_COMMAND_DOWN = 1 << 7,
   EVENTFLAG_NUM_LOCK_ON = 1 << 8,
   EVENTFLAG_IS_KEY_PAD = 1 << 9,
   EVENTFLAG_IS_LEFT = 1 << 10,
   EVENTFLAG_IS_RIGHT = 1 << 11,
   EVENTFLAG_ALTGR_DOWN = 1 << 12,
+  EVENTFLAG_IS_REPEAT = 1 << 13,
 } cef_event_flags_t;
 
 ///
-// Supported menu item types.
+/// Supported menu item types.
 ///
 typedef enum {
   MENUITEMTYPE_NONE,
@@ -1830,88 +1963,100 @@
 } cef_menu_item_type_t;
 
 ///
-// Supported context menu type flags.
+/// Supported context menu type flags.
 ///
 typedef enum {
   ///
-  // No node is selected.
+  /// No node is selected.
   ///
   CM_TYPEFLAG_NONE = 0,
   ///
-  // The top page is selected.
+  /// The top page is selected.
   ///
   CM_TYPEFLAG_PAGE = 1 << 0,
   ///
-  // A subframe page is selected.
+  /// A subframe page is selected.
   ///
   CM_TYPEFLAG_FRAME = 1 << 1,
   ///
-  // A link is selected.
+  /// A link is selected.
   ///
   CM_TYPEFLAG_LINK = 1 << 2,
   ///
-  // A media node is selected.
+  /// A media node is selected.
   ///
   CM_TYPEFLAG_MEDIA = 1 << 3,
   ///
-  // There is a textual or mixed selection that is selected.
+  /// There is a textual or mixed selection that is selected.
   ///
   CM_TYPEFLAG_SELECTION = 1 << 4,
   ///
-  // An editable element is selected.
+  /// An editable element is selected.
   ///
   CM_TYPEFLAG_EDITABLE = 1 << 5,
 } cef_context_menu_type_flags_t;
 
 ///
-// Supported context menu media types.
+/// Supported context menu media types. These constants match their equivalents
+/// in Chromium's ContextMenuDataMediaType and should not be renumbered.
 ///
 typedef enum {
   ///
-  // No special node is in context.
+  /// No special node is in context.
   ///
   CM_MEDIATYPE_NONE,
   ///
-  // An image node is selected.
+  /// An image node is selected.
   ///
   CM_MEDIATYPE_IMAGE,
   ///
-  // A video node is selected.
+  /// A video node is selected.
   ///
   CM_MEDIATYPE_VIDEO,
   ///
-  // An audio node is selected.
+  /// An audio node is selected.
   ///
   CM_MEDIATYPE_AUDIO,
   ///
-  // A file node is selected.
+  /// An canvas node is selected.
+  ///
+  CM_MEDIATYPE_CANVAS,
+  ///
+  /// A file node is selected.
   ///
   CM_MEDIATYPE_FILE,
   ///
-  // A plugin node is selected.
+  /// A plugin node is selected.
   ///
   CM_MEDIATYPE_PLUGIN,
 } cef_context_menu_media_type_t;
 
 ///
-// Supported context menu media state bit flags.
+/// Supported context menu media state bit flags. These constants match their
+/// equivalents in Chromium's ContextMenuData::MediaFlags and should not be
+/// renumbered.
 ///
 typedef enum {
   CM_MEDIAFLAG_NONE = 0,
-  CM_MEDIAFLAG_ERROR = 1 << 0,
+  CM_MEDIAFLAG_IN_ERROR = 1 << 0,
   CM_MEDIAFLAG_PAUSED = 1 << 1,
   CM_MEDIAFLAG_MUTED = 1 << 2,
   CM_MEDIAFLAG_LOOP = 1 << 3,
   CM_MEDIAFLAG_CAN_SAVE = 1 << 4,
   CM_MEDIAFLAG_HAS_AUDIO = 1 << 5,
-  CM_MEDIAFLAG_HAS_VIDEO = 1 << 6,
-  CM_MEDIAFLAG_CONTROL_ROOT_ELEMENT = 1 << 7,
+  CM_MEDIAFLAG_CAN_TOGGLE_CONTROLS = 1 << 6,
+  CM_MEDIAFLAG_CONTROLS = 1 << 7,
   CM_MEDIAFLAG_CAN_PRINT = 1 << 8,
   CM_MEDIAFLAG_CAN_ROTATE = 1 << 9,
+  CM_MEDIAFLAG_CAN_PICTURE_IN_PICTURE = 1 << 10,
+  CM_MEDIAFLAG_PICTURE_IN_PICTURE = 1 << 11,
+  CM_MEDIAFLAG_CAN_LOOP = 1 << 12,
 } cef_context_menu_media_state_flags_t;
 
 ///
-// Supported context menu edit state bit flags.
+/// Supported context menu edit state bit flags. These constants match their
+/// equivalents in Chromium's ContextMenuDataEditFlags and should not be
+/// renumbered.
 ///
 typedef enum {
   CM_EDITFLAG_NONE = 0,
@@ -1923,106 +2068,118 @@
   CM_EDITFLAG_CAN_DELETE = 1 << 5,
   CM_EDITFLAG_CAN_SELECT_ALL = 1 << 6,
   CM_EDITFLAG_CAN_TRANSLATE = 1 << 7,
+  CM_EDITFLAG_CAN_EDIT_RICHLY = 1 << 8,
 } cef_context_menu_edit_state_flags_t;
 
 ///
-// Key event types.
+/// Supported quick menu state bit flags.
+///
+typedef enum {
+  QM_EDITFLAG_NONE = 0,
+  QM_EDITFLAG_CAN_ELLIPSIS = 1 << 0,
+  QM_EDITFLAG_CAN_CUT = 1 << 1,
+  QM_EDITFLAG_CAN_COPY = 1 << 2,
+  QM_EDITFLAG_CAN_PASTE = 1 << 3,
+} cef_quick_menu_edit_state_flags_t;
+
+///
+/// Key event types.
 ///
 typedef enum {
   ///
-  // Notification that a key transitioned from "up" to "down".
+  /// Notification that a key transitioned from "up" to "down".
   ///
   KEYEVENT_RAWKEYDOWN = 0,
 
   ///
-  // Notification that a key was pressed. This does not necessarily correspond
-  // to a character depending on the key and language. Use KEYEVENT_CHAR for
-  // character input.
+  /// Notification that a key was pressed. This does not necessarily correspond
+  /// to a character depending on the key and language. Use KEYEVENT_CHAR for
+  /// character input.
   ///
   KEYEVENT_KEYDOWN,
 
   ///
-  // Notification that a key was released.
+  /// Notification that a key was released.
   ///
   KEYEVENT_KEYUP,
 
   ///
-  // Notification that a character was typed. Use this for text input. Key
-  // down events may generate 0, 1, or more than one character event depending
-  // on the key, locale, and operating system.
+  /// Notification that a character was typed. Use this for text input. Key
+  /// down events may generate 0, 1, or more than one character event depending
+  /// on the key, locale, and operating system.
   ///
   KEYEVENT_CHAR
 } cef_key_event_type_t;
 
 ///
-// Structure representing keyboard event information.
+/// Structure representing keyboard event information.
 ///
 typedef struct _cef_key_event_t {
   ///
-  // The type of keyboard event.
+  /// The type of keyboard event.
   ///
   cef_key_event_type_t type;
 
   ///
-  // Bit flags describing any pressed modifier keys. See
-  // cef_event_flags_t for values.
+  /// Bit flags describing any pressed modifier keys. See
+  /// cef_event_flags_t for values.
   ///
-  uint32 modifiers;
+  uint32_t modifiers;
 
   ///
-  // The Windows key code for the key event. This value is used by the DOM
-  // specification. Sometimes it comes directly from the event (i.e. on
-  // Windows) and sometimes it's determined using a mapping function. See
-  // WebCore/platform/chromium/KeyboardCodes.h for the list of values.
+  /// The Windows key code for the key event. This value is used by the DOM
+  /// specification. Sometimes it comes directly from the event (i.e. on
+  /// Windows) and sometimes it's determined using a mapping function. See
+  /// WebCore/platform/chromium/KeyboardCodes.h for the list of values.
   ///
   int windows_key_code;
 
   ///
-  // The actual key code genenerated by the platform.
+  /// The actual key code genenerated by the platform.
   ///
   int native_key_code;
 
   ///
-  // Indicates whether the event is considered a "system key" event (see
-  // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx for details).
-  // This value will always be false on non-Windows platforms.
+  /// Indicates whether the event is considered a "system key" event (see
+  /// http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx for details).
+  /// This value will always be false on non-Windows platforms.
   ///
   int is_system_key;
 
   ///
-  // The character generated by the keystroke.
+  /// The character generated by the keystroke.
   ///
-  char16 character;
+  char16_t character;
 
   ///
-  // Same as |character| but unmodified by any concurrently-held modifiers
-  // (except shift). This is useful for working out shortcut keys.
+  /// Same as |character| but unmodified by any concurrently-held modifiers
+  /// (except shift). This is useful for working out shortcut keys.
   ///
-  char16 unmodified_character;
+  char16_t unmodified_character;
 
   ///
-  // True if the focus is currently on an editable field on the page. This is
-  // useful for determining if standard key events should be intercepted.
+  /// True if the focus is currently on an editable field on the page. This is
+  /// useful for determining if standard key events should be intercepted.
   ///
   int focus_on_editable_field;
 } cef_key_event_t;
 
 ///
-// Focus sources.
+/// Focus sources.
 ///
 typedef enum {
   ///
-  // The source is explicit navigation via the API (LoadURL(), etc).
+  /// The source is explicit navigation via the API (LoadURL(), etc).
   ///
   FOCUS_SOURCE_NAVIGATION = 0,
   ///
-  // The source is a system-generated focus event.
+  /// The source is a system-generated focus event.
   ///
   FOCUS_SOURCE_SYSTEM,
 } cef_focus_source_t;
 
 ///
-// Navigation types.
+/// Navigation types.
 ///
 typedef enum {
   NAVIGATION_LINK_CLICKED = 0,
@@ -2034,10 +2191,10 @@
 } cef_navigation_type_t;
 
 ///
-// Supported XML encoding types. The parser supports ASCII, ISO-8859-1, and
-// UTF16 (LE and BE) by default. All other types must be translated to UTF8
-// before being passed to the parser. If a BOM is detected and the correct
-// decoder is available then that decoder will be used automatically.
+/// Supported XML encoding types. The parser supports ASCII, ISO-8859-1, and
+/// UTF16 (LE and BE) by default. All other types must be translated to UTF8
+/// before being passed to the parser. If a BOM is detected and the correct
+/// decoder is available then that decoder will be used automatically.
 ///
 typedef enum {
   XML_ENCODING_NONE = 0,
@@ -2048,7 +2205,7 @@
 } cef_xml_encoding_type_t;
 
 ///
-// XML node types.
+/// XML node types.
 ///
 typedef enum {
   XML_NODE_UNSUPPORTED = 0,
@@ -2065,7 +2222,7 @@
 } cef_xml_node_type_t;
 
 ///
-// Popup window features.
+/// Popup window features.
 ///
 typedef struct _cef_popup_features_t {
   int x;
@@ -2077,14 +2234,12 @@
   int height;
   int heightSet;
 
-  int menuBarVisible;
-  int statusBarVisible;
-  int toolBarVisible;
-  int scrollbarsVisible;
+  /// True (1) if browser interface elements should be hidden.
+  int isPopup;
 } cef_popup_features_t;
 
 ///
-// DOM document types.
+/// DOM document types.
 ///
 typedef enum {
   DOM_DOCUMENT_TYPE_UNKNOWN = 0,
@@ -2094,7 +2249,7 @@
 } cef_dom_document_type_t;
 
 ///
-// DOM event category flags.
+/// DOM event category flags.
 ///
 typedef enum {
   DOM_EVENT_CATEGORY_UNKNOWN = 0x0,
@@ -2117,7 +2272,7 @@
 } cef_dom_event_category_t;
 
 ///
-// DOM event processing phases.
+/// DOM event processing phases.
 ///
 typedef enum {
   DOM_EVENT_PHASE_UNKNOWN = 0,
@@ -2127,7 +2282,7 @@
 } cef_dom_event_phase_t;
 
 ///
-// DOM node types.
+/// DOM node types.
 ///
 typedef enum {
   DOM_NODE_TYPE_UNSUPPORTED = 0,
@@ -2143,53 +2298,73 @@
 } cef_dom_node_type_t;
 
 ///
-// Supported file dialog modes.
+/// DOM form control types. Should be kept in sync with Chromium's
+/// blink::mojom::FormControlType type.
+///
+typedef enum {
+  DOM_FORM_CONTROL_TYPE_UNSUPPORTED = 0,
+  DOM_FORM_CONTROL_TYPE_BUTTON_BUTTON,
+  DOM_FORM_CONTROL_TYPE_BUTTON_SUBMIT,
+  DOM_FORM_CONTROL_TYPE_BUTTON_RESET,
+  DOM_FORM_CONTROL_TYPE_BUTTON_SELECT_LIST,
+  DOM_FORM_CONTROL_TYPE_FIELDSET,
+  DOM_FORM_CONTROL_TYPE_INPUT_BUTTON,
+  DOM_FORM_CONTROL_TYPE_INPUT_CHECKBOX,
+  DOM_FORM_CONTROL_TYPE_INPUT_COLOR,
+  DOM_FORM_CONTROL_TYPE_INPUT_DATE,
+  DOM_FORM_CONTROL_TYPE_INPUT_DATETIME_LOCAL,
+  DOM_FORM_CONTROL_TYPE_INPUT_EMAIL,
+  DOM_FORM_CONTROL_TYPE_INPUT_FILE,
+  DOM_FORM_CONTROL_TYPE_INPUT_HIDDEN,
+  DOM_FORM_CONTROL_TYPE_INPUT_IMAGE,
+  DOM_FORM_CONTROL_TYPE_INPUT_MONTH,
+  DOM_FORM_CONTROL_TYPE_INPUT_NUMBER,
+  DOM_FORM_CONTROL_TYPE_INPUT_PASSWORD,
+  DOM_FORM_CONTROL_TYPE_INPUT_RADIO,
+  DOM_FORM_CONTROL_TYPE_INPUT_RANGE,
+  DOM_FORM_CONTROL_TYPE_INPUT_RESET,
+  DOM_FORM_CONTROL_TYPE_INPUT_SEARCH,
+  DOM_FORM_CONTROL_TYPE_INPUT_SUBMIT,
+  DOM_FORM_CONTROL_TYPE_INPUT_TELEPHONE,
+  DOM_FORM_CONTROL_TYPE_INPUT_TEXT,
+  DOM_FORM_CONTROL_TYPE_INPUT_TIME,
+  DOM_FORM_CONTROL_TYPE_INPUT_URL,
+  DOM_FORM_CONTROL_TYPE_INPUT_WEEK,
+  DOM_FORM_CONTROL_TYPE_OUTPUT,
+  DOM_FORM_CONTROL_TYPE_SELECT_ONE,
+  DOM_FORM_CONTROL_TYPE_SELECT_MULTIPLE,
+  DOM_FORM_CONTROL_TYPE_SELECT_LIST,
+  DOM_FORM_CONTROL_TYPE_TEXT_AREA,
+} cef_dom_form_control_type_t;
+
+///
+/// Supported file dialog modes.
 ///
 typedef enum {
   ///
-  // Requires that the file exists before allowing the user to pick it.
+  /// Requires that the file exists before allowing the user to pick it.
   ///
   FILE_DIALOG_OPEN = 0,
 
   ///
-  // Like Open, but allows picking multiple files to open.
+  /// Like Open, but allows picking multiple files to open.
   ///
   FILE_DIALOG_OPEN_MULTIPLE,
 
   ///
-  // Like Open, but selects a folder to open.
+  /// Like Open, but selects a folder to open.
   ///
   FILE_DIALOG_OPEN_FOLDER,
 
   ///
-  // Allows picking a nonexistent file, and prompts to overwrite if the file
-  // already exists.
+  /// Allows picking a nonexistent file, and prompts to overwrite if the file
+  /// already exists.
   ///
   FILE_DIALOG_SAVE,
-
-  ///
-  // General mask defining the bits used for the type values.
-  ///
-  FILE_DIALOG_TYPE_MASK = 0xFF,
-
-  // Qualifiers.
-  // Any of the type values above can be augmented by one or more qualifiers.
-  // These qualifiers further define the dialog behavior.
-
-  ///
-  // Prompt to overwrite if the user selects an existing file with the Save
-  // dialog.
-  ///
-  FILE_DIALOG_OVERWRITEPROMPT_FLAG = 0x01000000,
-
-  ///
-  // Do not display read-only files.
-  ///
-  FILE_DIALOG_HIDEREADONLY_FLAG = 0x02000000,
 } cef_file_dialog_mode_t;
 
 ///
-// Print job color mode values.
+/// Print job color mode values.
 ///
 typedef enum {
   COLOR_MODEL_UNKNOWN,
@@ -2216,7 +2391,7 @@
 } cef_color_model_t;
 
 ///
-// Print job duplex mode values.
+/// Print job duplex mode values.
 ///
 typedef enum {
   DUPLEX_MODE_UNKNOWN = -1,
@@ -2226,7 +2401,7 @@
 } cef_duplex_mode_t;
 
 ///
-// Cursor type values.
+/// Cursor type values.
 ///
 typedef enum {
   CT_POINTER = 0,
@@ -2282,9 +2457,9 @@
 } cef_cursor_type_t;
 
 ///
-// Structure representing cursor information. |buffer| will be
-// |size.width|*|size.height|*4 bytes in size and represents a BGRA image with
-// an upper-left origin.
+/// Structure representing cursor information. |buffer| will be
+/// |size.width|*|size.height|*4 bytes in size and represents a BGRA image with
+/// an upper-left origin.
 ///
 typedef struct _cef_cursor_info_t {
   cef_point_t hotspot;
@@ -2294,217 +2469,226 @@
 } cef_cursor_info_t;
 
 ///
-// URI unescape rules passed to CefURIDecode().
+/// URI unescape rules passed to CefURIDecode().
 ///
 typedef enum {
   ///
-  // Don't unescape anything at all.
+  /// Don't unescape anything at all.
   ///
   UU_NONE = 0,
 
   ///
-  // Don't unescape anything special, but all normal unescaping will happen.
-  // This is a placeholder and can't be combined with other flags (since it's
-  // just the absence of them). All other unescape rules imply "normal" in
-  // addition to their special meaning. Things like escaped letters, digits,
-  // and most symbols will get unescaped with this mode.
+  /// Don't unescape anything special, but all normal unescaping will happen.
+  /// This is a placeholder and can't be combined with other flags (since it's
+  /// just the absence of them). All other unescape rules imply "normal" in
+  /// addition to their special meaning. Things like escaped letters, digits,
+  /// and most symbols will get unescaped with this mode.
   ///
   UU_NORMAL = 1 << 0,
 
   ///
-  // Convert %20 to spaces. In some places where we're showing URLs, we may
-  // want this. In places where the URL may be copied and pasted out, then
-  // you wouldn't want this since it might not be interpreted in one piece
-  // by other applications.
+  /// Convert %20 to spaces. In some places where we're showing URLs, we may
+  /// want this. In places where the URL may be copied and pasted out, then
+  /// you wouldn't want this since it might not be interpreted in one piece
+  /// by other applications.
   ///
   UU_SPACES = 1 << 1,
 
   ///
-  // Unescapes '/' and '\\'. If these characters were unescaped, the resulting
-  // URL won't be the same as the source one. Moreover, they are dangerous to
-  // unescape in strings that will be used as file paths or names. This value
-  // should only be used when slashes don't have special meaning, like data
-  // URLs.
+  /// Unescapes '/' and '\\'. If these characters were unescaped, the resulting
+  /// URL won't be the same as the source one. Moreover, they are dangerous to
+  /// unescape in strings that will be used as file paths or names. This value
+  /// should only be used when slashes don't have special meaning, like data
+  /// URLs.
   ///
   UU_PATH_SEPARATORS = 1 << 2,
 
   ///
-  // Unescapes various characters that will change the meaning of URLs,
-  // including '%', '+', '&', '#'. Does not unescape path separators.
-  // If these characters were unescaped, the resulting URL won't be the same
-  // as the source one. This flag is used when generating final output like
-  // filenames for URLs where we won't be interpreting as a URL and want to do
-  // as much unescaping as possible.
+  /// Unescapes various characters that will change the meaning of URLs,
+  /// including '%', '+', '&', '#'. Does not unescape path separators.
+  /// If these characters were unescaped, the resulting URL won't be the same
+  /// as the source one. This flag is used when generating final output like
+  /// filenames for URLs where we won't be interpreting as a URL and want to do
+  /// as much unescaping as possible.
   ///
   UU_URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS = 1 << 3,
 
   ///
-  // URL queries use "+" for space. This flag controls that replacement.
+  /// URL queries use "+" for space. This flag controls that replacement.
   ///
   UU_REPLACE_PLUS_WITH_SPACE = 1 << 4,
 } cef_uri_unescape_rule_t;
 
 ///
-// Options that can be passed to CefParseJSON.
+/// Options that can be passed to CefParseJSON.
 ///
 typedef enum {
   ///
-  // Parses the input strictly according to RFC 4627. See comments in Chromium's
-  // base/json/json_reader.h file for known limitations/deviations from the RFC.
+  /// Parses the input strictly according to RFC 4627. See comments in
+  /// Chromium's base/json/json_reader.h file for known limitations/
+  /// deviations from the RFC.
   ///
   JSON_PARSER_RFC = 0,
 
   ///
-  // Allows commas to exist after the last element in structures.
+  /// Allows commas to exist after the last element in structures.
   ///
   JSON_PARSER_ALLOW_TRAILING_COMMAS = 1 << 0,
 } cef_json_parser_options_t;
 
 ///
-// Error codes that can be returned from CefParseJSONAndReturnError.
-///
-typedef enum {
-  JSON_NO_ERROR = 0,
-  JSON_INVALID_ESCAPE,
-  JSON_SYNTAX_ERROR,
-  JSON_UNEXPECTED_TOKEN,
-  JSON_TRAILING_COMMA,
-  JSON_TOO_MUCH_NESTING,
-  JSON_UNEXPECTED_DATA_AFTER_ROOT,
-  JSON_UNSUPPORTED_ENCODING,
-  JSON_UNQUOTED_DICTIONARY_KEY,
-  JSON_PARSE_ERROR_COUNT
-} cef_json_parser_error_t;
-
-///
-// Options that can be passed to CefWriteJSON.
+/// Options that can be passed to CefWriteJSON.
 ///
 typedef enum {
   ///
-  // Default behavior.
+  /// Default behavior.
   ///
   JSON_WRITER_DEFAULT = 0,
 
   ///
-  // This option instructs the writer that if a Binary value is encountered,
-  // the value (and key if within a dictionary) will be omitted from the
-  // output, and success will be returned. Otherwise, if a binary value is
-  // encountered, failure will be returned.
+  /// This option instructs the writer that if a Binary value is encountered,
+  /// the value (and key if within a dictionary) will be omitted from the
+  /// output, and success will be returned. Otherwise, if a binary value is
+  /// encountered, failure will be returned.
   ///
   JSON_WRITER_OMIT_BINARY_VALUES = 1 << 0,
 
   ///
-  // This option instructs the writer to write doubles that have no fractional
-  // part as a normal integer (i.e., without using exponential notation
-  // or appending a '.0') as long as the value is within the range of a
-  // 64-bit int.
+  /// This option instructs the writer to write doubles that have no fractional
+  /// part as a normal integer (i.e., without using exponential notation
+  /// or appending a '.0') as long as the value is within the range of a
+  /// 64-bit int.
   ///
   JSON_WRITER_OMIT_DOUBLE_TYPE_PRESERVATION = 1 << 1,
 
   ///
-  // Return a slightly nicer formatted json string (pads with whitespace to
-  // help with readability).
+  /// Return a slightly nicer formatted json string (pads with whitespace to
+  /// help with readability).
   ///
   JSON_WRITER_PRETTY_PRINT = 1 << 2,
 } cef_json_writer_options_t;
 
 ///
-// Margin type for PDF printing.
+/// Margin type for PDF printing.
 ///
 typedef enum {
   ///
-  // Default margins.
+  /// Default margins of 1cm (~0.4 inches).
   ///
   PDF_PRINT_MARGIN_DEFAULT,
 
   ///
-  // No margins.
+  /// No margins.
   ///
   PDF_PRINT_MARGIN_NONE,
 
   ///
-  // Minimum margins.
-  ///
-  PDF_PRINT_MARGIN_MINIMUM,
-
-  ///
-  // Custom margins using the |margin_*| values from cef_pdf_print_settings_t.
+  /// Custom margins using the |margin_*| values from cef_pdf_print_settings_t.
   ///
   PDF_PRINT_MARGIN_CUSTOM,
 } cef_pdf_print_margin_type_t;
 
 ///
-// Structure representing PDF print settings.
+/// Structure representing PDF print settings. These values match the parameters
+/// supported by the DevTools Page.printToPDF function. See
+/// https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF
 ///
 typedef struct _cef_pdf_print_settings_t {
   ///
-  // Page title to display in the header. Only used if |header_footer_enabled|
-  // is set to true (1).
-  ///
-  cef_string_t header_footer_title;
-
-  ///
-  // URL to display in the footer. Only used if |header_footer_enabled| is set
-  // to true (1).
-  ///
-  cef_string_t header_footer_url;
-
-  ///
-  // Output page size in microns. If either of these values is less than or
-  // equal to zero then the default paper size (A4) will be used.
-  ///
-  int page_width;
-  int page_height;
-
-  ///
-  // The percentage to scale the PDF by before printing (e.g. 50 is 50%).
-  // If this value is less than or equal to zero the default value of 100
-  // will be used.
-  ///
-  int scale_factor;
-
-  ///
-  // Margins in points. Only used if |margin_type| is set to
-  // PDF_PRINT_MARGIN_CUSTOM.
-  ///
-  int margin_top;
-  int margin_right;
-  int margin_bottom;
-  int margin_left;
-
-  ///
-  // Margin type.
-  ///
-  cef_pdf_print_margin_type_t margin_type;
-
-  ///
-  // Set to true (1) to print headers and footers or false (0) to not print
-  // headers and footers.
-  ///
-  int header_footer_enabled;
-
-  ///
-  // Set to true (1) to print the selection only or false (0) to print all.
-  ///
-  int selection_only;
-
-  ///
-  // Set to true (1) for landscape mode or false (0) for portrait mode.
+  /// Set to true (1) for landscape mode or false (0) for portrait mode.
   ///
   int landscape;
 
   ///
-  // Set to true (1) to print background graphics or false (0) to not print
-  // background graphics.
+  /// Set to true (1) to print background graphics.
   ///
-  int backgrounds_enabled;
+  int print_background;
 
+  ///
+  /// The percentage to scale the PDF by before printing (e.g. .5 is 50%).
+  /// If this value is less than or equal to zero the default value of 1.0
+  /// will be used.
+  ///
+  double scale;
+
+  ///
+  /// Output paper size in inches. If either of these values is less than or
+  /// equal to zero then the default paper size (letter, 8.5 x 11 inches) will
+  /// be used.
+  ///
+  double paper_width;
+  double paper_height;
+
+  ///
+  /// Set to true (1) to prefer page size as defined by css. Defaults to false
+  /// (0), in which case the content will be scaled to fit the paper size.
+  ///
+  int prefer_css_page_size;
+
+  ///
+  /// Margin type.
+  ///
+  cef_pdf_print_margin_type_t margin_type;
+
+  ///
+  /// Margins in inches. Only used if |margin_type| is set to
+  /// PDF_PRINT_MARGIN_CUSTOM.
+  ///
+  double margin_top;
+  double margin_right;
+  double margin_bottom;
+  double margin_left;
+
+  ///
+  /// Paper ranges to print, one based, e.g., '1-5, 8, 11-13'. Pages are printed
+  /// in the document order, not in the order specified, and no more than once.
+  /// Defaults to empty string, which implies the entire document is printed.
+  /// The page numbers are quietly capped to actual page count of the document,
+  /// and ranges beyond the end of the document are ignored. If this results in
+  /// no pages to print, an error is reported. It is an error to specify a range
+  /// with start greater than end.
+  ///
+  cef_string_t page_ranges;
+
+  ///
+  /// Set to true (1) to display the header and/or footer. Modify
+  /// |header_template| and/or |footer_template| to customize the display.
+  ///
+  int display_header_footer;
+
+  ///
+  /// HTML template for the print header. Only displayed if
+  /// |display_header_footer| is true (1). Should be valid HTML markup with
+  /// the following classes used to inject printing values into them:
+  ///
+  /// - date: formatted print date
+  /// - title: document title
+  /// - url: document location
+  /// - pageNumber: current page number
+  /// - totalPages: total pages in the document
+  ///
+  /// For example, "<span class=title></span>" would generate a span containing
+  /// the title.
+  ///
+  cef_string_t header_template;
+
+  ///
+  /// HTML template for the print footer. Only displayed if
+  /// |display_header_footer| is true (1). Uses the same format as
+  /// |header_template|.
+  ///
+  cef_string_t footer_template;
+
+  ///
+  /// Set to true (1) to generate tagged (accessible) PDF.
+  ///
+  int generate_tagged_pdf;
 } cef_pdf_print_settings_t;
 
 ///
-// Supported UI scale factors for the platform. SCALE_FACTOR_NONE is used for
-// density independent resources such as string, html/js files or an image that
-// can be used for any scale factors (such as wallpapers).
+/// Supported UI scale factors for the platform. SCALE_FACTOR_NONE is used for
+/// density independent resources such as string, html/js files or an image that
+/// can be used for any scale factors (such as wallpapers).
 ///
 typedef enum {
   SCALE_FACTOR_NONE = 0,
@@ -2520,151 +2704,125 @@
 } cef_scale_factor_t;
 
 ///
-// Plugin policies supported by CefRequestContextHandler::OnBeforePluginLoad.
+/// Policy for how the Referrer HTTP header value will be sent during
+/// navigation. If the `--no-referrers` command-line flag is specified then the
+/// policy value will be ignored and the Referrer value will never be sent. Must
+/// be kept synchronized with net::URLRequest::ReferrerPolicy from Chromium.
 ///
 typedef enum {
   ///
-  // Allow the content.
-  ///
-  PLUGIN_POLICY_ALLOW,
-
-  ///
-  // Allow important content and block unimportant content based on heuristics.
-  // The user can manually load blocked content.
-  ///
-  PLUGIN_POLICY_DETECT_IMPORTANT,
-
-  ///
-  // Block the content. The user can manually load blocked content.
-  ///
-  PLUGIN_POLICY_BLOCK,
-
-  ///
-  // Disable the content. The user cannot load disabled content.
-  ///
-  PLUGIN_POLICY_DISABLE,
-} cef_plugin_policy_t;
-
-///
-// Policy for how the Referrer HTTP header value will be sent during navigation.
-// If the `--no-referrers` command-line flag is specified then the policy value
-// will be ignored and the Referrer value will never be sent.
-// Must be kept synchronized with net::URLRequest::ReferrerPolicy from Chromium.
-///
-typedef enum {
-  ///
-  // Clear the referrer header if the header value is HTTPS but the request
-  // destination is HTTP. This is the default behavior.
+  /// Clear the referrer header if the header value is HTTPS but the request
+  /// destination is HTTP. This is the default behavior.
   ///
   REFERRER_POLICY_CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
   REFERRER_POLICY_DEFAULT =
       REFERRER_POLICY_CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
 
   ///
-  // A slight variant on CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE:
-  // If the request destination is HTTP, an HTTPS referrer will be cleared. If
-  // the request's destination is cross-origin with the referrer (but does not
-  // downgrade), the referrer's granularity will be stripped down to an origin
-  // rather than a full URL. Same-origin requests will send the full referrer.
+  /// A slight variant on CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE:
+  /// If the request destination is HTTP, an HTTPS referrer will be cleared. If
+  /// the request's destination is cross-origin with the referrer (but does not
+  /// downgrade), the referrer's granularity will be stripped down to an origin
+  /// rather than a full URL. Same-origin requests will send the full referrer.
   ///
   REFERRER_POLICY_REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
 
   ///
-  // Strip the referrer down to an origin when the origin of the referrer is
-  // different from the destination's origin.
+  /// Strip the referrer down to an origin when the origin of the referrer is
+  /// different from the destination's origin.
   ///
   REFERRER_POLICY_ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN,
 
   ///
-  // Never change the referrer.
+  /// Never change the referrer.
   ///
   REFERRER_POLICY_NEVER_CLEAR_REFERRER,
 
   ///
-  // Strip the referrer down to the origin regardless of the redirect location.
+  /// Strip the referrer down to the origin regardless of the redirect location.
   ///
   REFERRER_POLICY_ORIGIN,
 
   ///
-  // Clear the referrer when the request's referrer is cross-origin with the
-  // request's destination.
+  /// Clear the referrer when the request's referrer is cross-origin with the
+  /// request's destination.
   ///
   REFERRER_POLICY_CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN,
 
   ///
-  // Strip the referrer down to the origin, but clear it entirely if the
-  // referrer value is HTTPS and the destination is HTTP.
+  /// Strip the referrer down to the origin, but clear it entirely if the
+  /// referrer value is HTTPS and the destination is HTTP.
   ///
   REFERRER_POLICY_ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
 
   ///
-  // Always clear the referrer regardless of the request destination.
+  /// Always clear the referrer regardless of the request destination.
   ///
   REFERRER_POLICY_NO_REFERRER,
 
-  // Always the last value in this enumeration.
+  /// Always the last value in this enumeration.
   REFERRER_POLICY_LAST_VALUE = REFERRER_POLICY_NO_REFERRER,
 } cef_referrer_policy_t;
 
 ///
-// Return values for CefResponseFilter::Filter().
+/// Return values for CefResponseFilter::Filter().
 ///
 typedef enum {
   ///
-  // Some or all of the pre-filter data was read successfully but more data is
-  // needed in order to continue filtering (filtered output is pending).
+  /// Some or all of the pre-filter data was read successfully but more data is
+  /// needed in order to continue filtering (filtered output is pending).
   ///
   RESPONSE_FILTER_NEED_MORE_DATA,
 
   ///
-  // Some or all of the pre-filter data was read successfully and all available
-  // filtered output has been written.
+  /// Some or all of the pre-filter data was read successfully and all available
+  /// filtered output has been written.
   ///
   RESPONSE_FILTER_DONE,
 
   ///
-  // An error occurred during filtering.
+  /// An error occurred during filtering.
   ///
   RESPONSE_FILTER_ERROR
 } cef_response_filter_status_t;
 
 ///
-// Describes how to interpret the components of a pixel.
+/// Describes how to interpret the components of a pixel.
 ///
 typedef enum {
   ///
-  // RGBA with 8 bits per pixel (32bits total).
+  /// RGBA with 8 bits per pixel (32bits total).
   ///
   CEF_COLOR_TYPE_RGBA_8888,
 
   ///
-  // BGRA with 8 bits per pixel (32bits total).
+  /// BGRA with 8 bits per pixel (32bits total).
   ///
   CEF_COLOR_TYPE_BGRA_8888,
 } cef_color_type_t;
 
 ///
-// Describes how to interpret the alpha component of a pixel.
+/// Describes how to interpret the alpha component of a pixel.
 ///
 typedef enum {
   ///
-  // No transparency. The alpha component is ignored.
+  /// No transparency. The alpha component is ignored.
   ///
   CEF_ALPHA_TYPE_OPAQUE,
 
   ///
-  // Transparency with pre-multiplied alpha component.
+  /// Transparency with pre-multiplied alpha component.
   ///
   CEF_ALPHA_TYPE_PREMULTIPLIED,
 
   ///
-  // Transparency with post-multiplied alpha component.
+  /// Transparency with post-multiplied alpha component.
   ///
   CEF_ALPHA_TYPE_POSTMULTIPLIED,
 } cef_alpha_type_t;
 
 ///
-// Text style types. Should be kepy in sync with gfx::TextStyle.
+/// Text style types. Should be kepy in sync with gfx::TextStyle.
 ///
 typedef enum {
   CEF_TEXT_STYLE_BOLD,
@@ -2675,111 +2833,112 @@
 } cef_text_style_t;
 
 ///
-// Specifies where along the main axis the CefBoxLayout child views should be
-// laid out.
+/// Specifies where along the main axis the CefBoxLayout child views should be
+/// laid out.
 ///
 typedef enum {
   ///
-  // Child views will be left-aligned.
+  /// Child views will be left-aligned.
   ///
   CEF_MAIN_AXIS_ALIGNMENT_START,
 
   ///
-  // Child views will be center-aligned.
+  /// Child views will be center-aligned.
   ///
   CEF_MAIN_AXIS_ALIGNMENT_CENTER,
 
   ///
-  // Child views will be right-aligned.
+  /// Child views will be right-aligned.
   ///
   CEF_MAIN_AXIS_ALIGNMENT_END,
 } cef_main_axis_alignment_t;
 
 ///
-// Specifies where along the cross axis the CefBoxLayout child views should be
-// laid out.
+/// Specifies where along the cross axis the CefBoxLayout child views should be
+/// laid out.
 ///
 typedef enum {
   ///
-  // Child views will be stretched to fit.
+  /// Child views will be stretched to fit.
   ///
   CEF_CROSS_AXIS_ALIGNMENT_STRETCH,
 
   ///
-  // Child views will be left-aligned.
+  /// Child views will be left-aligned.
   ///
   CEF_CROSS_AXIS_ALIGNMENT_START,
 
   ///
-  // Child views will be center-aligned.
+  /// Child views will be center-aligned.
   ///
   CEF_CROSS_AXIS_ALIGNMENT_CENTER,
 
   ///
-  // Child views will be right-aligned.
+  /// Child views will be right-aligned.
   ///
   CEF_CROSS_AXIS_ALIGNMENT_END,
 } cef_cross_axis_alignment_t;
 
 ///
-// Settings used when initializing a CefBoxLayout.
+/// Settings used when initializing a CefBoxLayout.
 ///
 typedef struct _cef_box_layout_settings_t {
   ///
-  // If true (1) the layout will be horizontal, otherwise the layout will be
-  // vertical.
+  /// If true (1) the layout will be horizontal, otherwise the layout will be
+  /// vertical.
   ///
   int horizontal;
 
   ///
-  // Adds additional horizontal space between the child view area and the host
-  // view border.
+  /// Adds additional horizontal space between the child view area and the host
+  /// view border.
   ///
   int inside_border_horizontal_spacing;
 
   ///
-  // Adds additional vertical space between the child view area and the host
-  // view border.
+  /// Adds additional vertical space between the child view area and the host
+  /// view border.
   ///
   int inside_border_vertical_spacing;
 
   ///
-  // Adds additional space around the child view area.
+  /// Adds additional space around the child view area.
   ///
   cef_insets_t inside_border_insets;
 
   ///
-  // Adds additional space between child views.
+  /// Adds additional space between child views.
   ///
   int between_child_spacing;
 
   ///
-  // Specifies where along the main axis the child views should be laid out.
+  /// Specifies where along the main axis the child views should be laid out.
   ///
   cef_main_axis_alignment_t main_axis_alignment;
 
   ///
-  // Specifies where along the cross axis the child views should be laid out.
+  /// Specifies where along the cross axis the child views should be laid out.
   ///
   cef_cross_axis_alignment_t cross_axis_alignment;
 
   ///
-  // Minimum cross axis size.
+  /// Minimum cross axis size.
   ///
   int minimum_cross_axis_size;
 
   ///
-  // Default flex for views when none is specified via CefBoxLayout methods.
-  // Using the preferred size as the basis, free space along the main axis is
-  // distributed to views in the ratio of their flex weights. Similarly, if the
-  // views will overflow the parent, space is subtracted in these ratios. A flex
-  // of 0 means this view is not resized. Flex values must not be negative.
+  /// Default flex for views when none is specified via CefBoxLayout methods.
+  /// Using the preferred size as the basis, free space along the main axis is
+  /// distributed to views in the ratio of their flex weights. Similarly, if the
+  /// views will overflow the parent, space is subtracted in these ratios. A
+  /// flex of 0 means this view is not resized. Flex values must not be
+  /// negative.
   ///
   int default_flex;
 } cef_box_layout_settings_t;
 
 ///
-// Specifies the button display state.
+/// Specifies the button display state.
 ///
 typedef enum {
   CEF_BUTTON_STATE_NORMAL,
@@ -2789,28 +2948,28 @@
 } cef_button_state_t;
 
 ///
-// Specifies the horizontal text alignment mode.
+/// Specifies the horizontal text alignment mode.
 ///
 typedef enum {
   ///
-  // Align the text's left edge with that of its display area.
+  /// Align the text's left edge with that of its display area.
   ///
   CEF_HORIZONTAL_ALIGNMENT_LEFT,
 
   ///
-  // Align the text's center with that of its display area.
+  /// Align the text's center with that of its display area.
   ///
   CEF_HORIZONTAL_ALIGNMENT_CENTER,
 
   ///
-  // Align the text's right edge with that of its display area.
+  /// Align the text's right edge with that of its display area.
   ///
   CEF_HORIZONTAL_ALIGNMENT_RIGHT,
 } cef_horizontal_alignment_t;
 
 ///
-// Specifies how a menu will be anchored for non-RTL languages. The opposite
-// position will be used for RTL languages.
+/// Specifies how a menu will be anchored for non-RTL languages. The opposite
+/// position will be used for RTL languages.
 ///
 typedef enum {
   CEF_MENU_ANCHOR_TOPLEFT,
@@ -2819,7 +2978,7 @@
 } cef_menu_anchor_position_t;
 
 ///
-// Supported color types for menu items.
+/// Supported color types for menu items.
 ///
 typedef enum {
   CEF_MENU_COLOR_TEXT,
@@ -2831,8 +2990,8 @@
   CEF_MENU_COLOR_COUNT,
 } cef_menu_color_type_t;
 
-// Supported SSL version values. See net/ssl/ssl_connection_status_flags.h
-// for more information.
+/// Supported SSL version values. See net/ssl/ssl_connection_status_flags.h
+/// for more information.
 typedef enum {
   SSL_CONNECTION_VERSION_UNKNOWN = 0,  // Unknown SSL version.
   SSL_CONNECTION_VERSION_SSL2 = 1,
@@ -2844,8 +3003,8 @@
   SSL_CONNECTION_VERSION_QUIC = 7,
 } cef_ssl_version_t;
 
-// Supported SSL content status flags. See content/public/common/ssl_status.h
-// for more information.
+/// Supported SSL content status flags. See content/public/common/ssl_status.h
+/// for more information.
 typedef enum {
   SSL_CONTENT_NORMAL_CONTENT = 0,
   SSL_CONTENT_DISPLAYED_INSECURE_CONTENT = 1 << 0,
@@ -2853,116 +3012,100 @@
 } cef_ssl_content_status_t;
 
 //
-// Configuration options for registering a custom scheme.
-// These values are used when calling AddCustomScheme.
+/// Configuration options for registering a custom scheme.
+/// These values are used when calling AddCustomScheme.
 //
 typedef enum {
   CEF_SCHEME_OPTION_NONE = 0,
 
   ///
-  // If CEF_SCHEME_OPTION_STANDARD is set the scheme will be treated as a
-  // standard scheme. Standard schemes are subject to URL canonicalization and
-  // parsing rules as defined in the Common Internet Scheme Syntax RFC 1738
-  // Section 3.1 available at http://www.ietf.org/rfc/rfc1738.txt
+  /// If CEF_SCHEME_OPTION_STANDARD is set the scheme will be treated as a
+  /// standard scheme. Standard schemes are subject to URL canonicalization and
+  /// parsing rules as defined in the Common Internet Scheme Syntax RFC 1738
+  /// Section 3.1 available at http://www.ietf.org/rfc/rfc1738.txt
   //
-  // In particular, the syntax for standard scheme URLs must be of the form:
-  // <pre>
-  //  [scheme]://[username]:[password]@[host]:[port]/[url-path]
-  // </pre> Standard scheme URLs must have a host component that is a fully
-  // qualified domain name as defined in Section 3.5 of RFC 1034 [13] and
-  // Section 2.1 of RFC 1123. These URLs will be canonicalized to
-  // "scheme://host/path" in the simplest case and
-  // "scheme://username:password@host:port/path" in the most explicit case. For
-  // example, "scheme:host/path" and "scheme:///host/path" will both be
-  // canonicalized to "scheme://host/path". The origin of a standard scheme URL
-  // is the combination of scheme, host and port (i.e., "scheme://host:port" in
-  // the most explicit case).
+  /// In particular, the syntax for standard scheme URLs must be of the form:
+  /// <pre>
+  ///  [scheme]://[username]:[password]@[host]:[port]/[url-path]
+  /// </pre> Standard scheme URLs must have a host component that is a fully
+  /// qualified domain name as defined in Section 3.5 of RFC 1034 [13] and
+  /// Section 2.1 of RFC 1123. These URLs will be canonicalized to
+  /// "scheme://host/path" in the simplest case and
+  /// "scheme://username:password@host:port/path" in the most explicit case. For
+  /// example, "scheme:host/path" and "scheme:///host/path" will both be
+  /// canonicalized to "scheme://host/path". The origin of a standard scheme URL
+  /// is the combination of scheme, host and port (i.e., "scheme://host:port" in
+  /// the most explicit case).
   //
-  // For non-standard scheme URLs only the "scheme:" component is parsed and
-  // canonicalized. The remainder of the URL will be passed to the handler as-
-  // is. For example, "scheme:///some%20text" will remain the same. Non-standard
-  // scheme URLs cannot be used as a target for form submission.
+  /// For non-standard scheme URLs only the "scheme:" component is parsed and
+  /// canonicalized. The remainder of the URL will be passed to the handler as-
+  /// is. For example, "scheme:///some%20text" will remain the same.
+  /// Non-standard scheme URLs cannot be used as a target for form submission.
   ///
   CEF_SCHEME_OPTION_STANDARD = 1 << 0,
 
   ///
-  // If CEF_SCHEME_OPTION_LOCAL is set the scheme will be treated with the same
-  // security rules as those applied to "file" URLs. Normal pages cannot link to
-  // or access local URLs. Also, by default, local URLs can only perform
-  // XMLHttpRequest calls to the same URL (origin + path) that originated the
-  // request. To allow XMLHttpRequest calls from a local URL to other URLs with
-  // the same origin set the CefSettings.file_access_from_file_urls_allowed
-  // value to true (1). To allow XMLHttpRequest calls from a local URL to all
-  // origins set the CefSettings.universal_access_from_file_urls_allowed value
-  // to true (1).
+  /// If CEF_SCHEME_OPTION_LOCAL is set the scheme will be treated with the same
+  /// security rules as those applied to "file" URLs. Normal pages cannot link
+  /// to or access local URLs. Also, by default, local URLs can only perform
+  /// XMLHttpRequest calls to the same URL (origin + path) that originated the
+  /// request. To allow XMLHttpRequest calls from a local URL to other URLs with
+  /// the same origin set the CefSettings.file_access_from_file_urls_allowed
+  /// value to true (1). To allow XMLHttpRequest calls from a local URL to all
+  /// origins set the CefSettings.universal_access_from_file_urls_allowed value
+  /// to true (1).
   ///
   CEF_SCHEME_OPTION_LOCAL = 1 << 1,
 
   ///
-  // If CEF_SCHEME_OPTION_DISPLAY_ISOLATED is set the scheme can only be
-  // displayed from other content hosted with the same scheme. For example,
-  // pages in other origins cannot create iframes or hyperlinks to URLs with the
-  // scheme. For schemes that must be accessible from other schemes don't set
-  // this, set CEF_SCHEME_OPTION_CORS_ENABLED, and use CORS
-  // "Access-Control-Allow-Origin" headers to further restrict access.
+  /// If CEF_SCHEME_OPTION_DISPLAY_ISOLATED is set the scheme can only be
+  /// displayed from other content hosted with the same scheme. For example,
+  /// pages in other origins cannot create iframes or hyperlinks to URLs with
+  /// the scheme. For schemes that must be accessible from other schemes don't
+  /// set this, set CEF_SCHEME_OPTION_CORS_ENABLED, and use CORS
+  /// "Access-Control-Allow-Origin" headers to further restrict access.
   ///
   CEF_SCHEME_OPTION_DISPLAY_ISOLATED = 1 << 2,
 
   ///
-  // If CEF_SCHEME_OPTION_SECURE is set the scheme will be treated with the same
-  // security rules as those applied to "https" URLs. For example, loading this
-  // scheme from other secure schemes will not trigger mixed content warnings.
+  /// If CEF_SCHEME_OPTION_SECURE is set the scheme will be treated with the
+  /// same security rules as those applied to "https" URLs. For example, loading
+  /// this scheme from other secure schemes will not trigger mixed content
+  /// warnings.
   ///
   CEF_SCHEME_OPTION_SECURE = 1 << 3,
 
   ///
-  // If CEF_SCHEME_OPTION_CORS_ENABLED is set the scheme can be sent CORS
-  // requests. This value should be set in most cases where
-  // CEF_SCHEME_OPTION_STANDARD is set.
+  /// If CEF_SCHEME_OPTION_CORS_ENABLED is set the scheme can be sent CORS
+  /// requests. This value should be set in most cases where
+  /// CEF_SCHEME_OPTION_STANDARD is set.
   ///
   CEF_SCHEME_OPTION_CORS_ENABLED = 1 << 4,
 
   ///
-  // If CEF_SCHEME_OPTION_CSP_BYPASSING is set the scheme can bypass Content-
-  // Security-Policy (CSP) checks. This value should not be set in most cases
-  // where CEF_SCHEME_OPTION_STANDARD is set.
+  /// If CEF_SCHEME_OPTION_CSP_BYPASSING is set the scheme can bypass Content-
+  /// Security-Policy (CSP) checks. This value should not be set in most cases
+  /// where CEF_SCHEME_OPTION_STANDARD is set.
   ///
   CEF_SCHEME_OPTION_CSP_BYPASSING = 1 << 5,
 
   ///
-  // If CEF_SCHEME_OPTION_FETCH_ENABLED is set the scheme can perform Fetch API
-  // requests.
+  /// If CEF_SCHEME_OPTION_FETCH_ENABLED is set the scheme can perform Fetch API
+  /// requests.
   ///
   CEF_SCHEME_OPTION_FETCH_ENABLED = 1 << 6,
 } cef_scheme_options_t;
 
 ///
-// Error codes for CDM registration. See cef_web_plugin.h for details.
+/// Structure representing a range.
 ///
-typedef enum {
-  ///
-  // No error. Registration completed successfully.
-  ///
-  CEF_CDM_REGISTRATION_ERROR_NONE,
-
-  ///
-  // Required files or manifest contents are missing.
-  ///
-  CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS,
-
-  ///
-  // The CDM is incompatible with the current Chromium version.
-  ///
-  CEF_CDM_REGISTRATION_ERROR_INCOMPATIBLE,
-
-  ///
-  // CDM registration is not supported at this time.
-  ///
-  CEF_CDM_REGISTRATION_ERROR_NOT_SUPPORTED,
-} cef_cdm_registration_error_t;
+typedef struct _cef_range_t {
+  uint32_t from;
+  uint32_t to;
+} cef_range_t;
 
 ///
-// Composition underline style.
+/// Composition underline style.
 ///
 typedef enum {
   CEF_CUS_SOLID,
@@ -2972,171 +3115,178 @@
 } cef_composition_underline_style_t;
 
 ///
-// Structure representing IME composition underline information. This is a thin
-// wrapper around Blink's WebCompositionUnderline class and should be kept in
-// sync with that.
+/// Structure representing IME composition underline information. This is a thin
+/// wrapper around Blink's WebCompositionUnderline class and should be kept in
+/// sync with that.
 ///
 typedef struct _cef_composition_underline_t {
   ///
-  // Underline character range.
+  /// Underline character range.
   ///
   cef_range_t range;
 
   ///
-  // Text color.
+  /// Text color.
   ///
   cef_color_t color;
 
   ///
-  // Background color.
+  /// Background color.
   ///
   cef_color_t background_color;
 
   ///
-  // Set to true (1) for thick underline.
+  /// Set to true (1) for thick underline.
   ///
   int thick;
 
   ///
-  // Style.
+  /// Style.
   ///
   cef_composition_underline_style_t style;
 } cef_composition_underline_t;
 
 ///
-// Enumerates the various representations of the ordering of audio channels.
-// Must be kept synchronized with media::ChannelLayout from Chromium.
-// See media\base\channel_layout.h
+/// Enumerates the various representations of the ordering of audio channels.
+/// Must be kept synchronized with media::ChannelLayout from Chromium.
+/// See media\base\channel_layout.h
 ///
 typedef enum {
   CEF_CHANNEL_LAYOUT_NONE = 0,
   CEF_CHANNEL_LAYOUT_UNSUPPORTED = 1,
 
-  // Front C
+  /// Front C
   CEF_CHANNEL_LAYOUT_MONO = 2,
 
-  // Front L, Front R
+  /// Front L, Front R
   CEF_CHANNEL_LAYOUT_STEREO = 3,
 
-  // Front L, Front R, Back C
+  /// Front L, Front R, Back C
   CEF_CHANNEL_LAYOUT_2_1 = 4,
 
-  // Front L, Front R, Front C
+  /// Front L, Front R, Front C
   CEF_CHANNEL_LAYOUT_SURROUND = 5,
 
-  // Front L, Front R, Front C, Back C
+  /// Front L, Front R, Front C, Back C
   CEF_CHANNEL_LAYOUT_4_0 = 6,
 
-  // Front L, Front R, Side L, Side R
+  /// Front L, Front R, Side L, Side R
   CEF_CHANNEL_LAYOUT_2_2 = 7,
 
-  // Front L, Front R, Back L, Back R
+  /// Front L, Front R, Back L, Back R
   CEF_CHANNEL_LAYOUT_QUAD = 8,
 
-  // Front L, Front R, Front C, Side L, Side R
+  /// Front L, Front R, Front C, Side L, Side R
   CEF_CHANNEL_LAYOUT_5_0 = 9,
 
-  // Front L, Front R, Front C, LFE, Side L, Side R
+  /// Front L, Front R, Front C, LFE, Side L, Side R
   CEF_CHANNEL_LAYOUT_5_1 = 10,
 
-  // Front L, Front R, Front C, Back L, Back R
+  /// Front L, Front R, Front C, Back L, Back R
   CEF_CHANNEL_LAYOUT_5_0_BACK = 11,
 
-  // Front L, Front R, Front C, LFE, Back L, Back R
+  /// Front L, Front R, Front C, LFE, Back L, Back R
   CEF_CHANNEL_LAYOUT_5_1_BACK = 12,
 
-  // Front L, Front R, Front C, Side L, Side R, Back L, Back R
+  /// Front L, Front R, Front C, Side L, Side R, Back L, Back R
   CEF_CHANNEL_LAYOUT_7_0 = 13,
 
-  // Front L, Front R, Front C, LFE, Side L, Side R, Back L, Back R
+  /// Front L, Front R, Front C, LFE, Side L, Side R, Back L, Back R
   CEF_CHANNEL_LAYOUT_7_1 = 14,
 
-  // Front L, Front R, Front C, LFE, Side L, Side R, Front LofC, Front RofC
+  /// Front L, Front R, Front C, LFE, Side L, Side R, Front LofC, Front RofC
   CEF_CHANNEL_LAYOUT_7_1_WIDE = 15,
 
-  // Stereo L, Stereo R
+  /// Stereo L, Stereo R
   CEF_CHANNEL_LAYOUT_STEREO_DOWNMIX = 16,
 
-  // Stereo L, Stereo R, LFE
+  /// Stereo L, Stereo R, LFE
   CEF_CHANNEL_LAYOUT_2POINT1 = 17,
 
-  // Stereo L, Stereo R, Front C, LFE
+  /// Stereo L, Stereo R, Front C, LFE
   CEF_CHANNEL_LAYOUT_3_1 = 18,
 
-  // Stereo L, Stereo R, Front C, Rear C, LFE
+  /// Stereo L, Stereo R, Front C, Rear C, LFE
   CEF_CHANNEL_LAYOUT_4_1 = 19,
 
-  // Stereo L, Stereo R, Front C, Side L, Side R, Back C
+  /// Stereo L, Stereo R, Front C, Side L, Side R, Back C
   CEF_CHANNEL_LAYOUT_6_0 = 20,
 
-  // Stereo L, Stereo R, Side L, Side R, Front LofC, Front RofC
+  /// Stereo L, Stereo R, Side L, Side R, Front LofC, Front RofC
   CEF_CHANNEL_LAYOUT_6_0_FRONT = 21,
 
-  // Stereo L, Stereo R, Front C, Rear L, Rear R, Rear C
+  /// Stereo L, Stereo R, Front C, Rear L, Rear R, Rear C
   CEF_CHANNEL_LAYOUT_HEXAGONAL = 22,
 
-  // Stereo L, Stereo R, Front C, LFE, Side L, Side R, Rear Center
+  /// Stereo L, Stereo R, Front C, LFE, Side L, Side R, Rear Center
   CEF_CHANNEL_LAYOUT_6_1 = 23,
 
-  // Stereo L, Stereo R, Front C, LFE, Back L, Back R, Rear Center
+  /// Stereo L, Stereo R, Front C, LFE, Back L, Back R, Rear Center
   CEF_CHANNEL_LAYOUT_6_1_BACK = 24,
 
-  // Stereo L, Stereo R, Side L, Side R, Front LofC, Front RofC, LFE
+  /// Stereo L, Stereo R, Side L, Side R, Front LofC, Front RofC, LFE
   CEF_CHANNEL_LAYOUT_6_1_FRONT = 25,
 
-  // Front L, Front R, Front C, Side L, Side R, Front LofC, Front RofC
+  /// Front L, Front R, Front C, Side L, Side R, Front LofC, Front RofC
   CEF_CHANNEL_LAYOUT_7_0_FRONT = 26,
 
-  // Front L, Front R, Front C, LFE, Back L, Back R, Front LofC, Front RofC
+  /// Front L, Front R, Front C, LFE, Back L, Back R, Front LofC, Front RofC
   CEF_CHANNEL_LAYOUT_7_1_WIDE_BACK = 27,
 
-  // Front L, Front R, Front C, Side L, Side R, Rear L, Back R, Back C.
+  /// Front L, Front R, Front C, Side L, Side R, Rear L, Back R, Back C.
   CEF_CHANNEL_LAYOUT_OCTAGONAL = 28,
 
-  // Channels are not explicitly mapped to speakers.
+  /// Channels are not explicitly mapped to speakers.
   CEF_CHANNEL_LAYOUT_DISCRETE = 29,
 
-  // Front L, Front R, Front C. Front C contains the keyboard mic audio. This
-  // layout is only intended for input for WebRTC. The Front C channel
-  // is stripped away in the WebRTC audio input pipeline and never seen outside
-  // of that.
+  /// Front L, Front R, Front C. Front C contains the keyboard mic audio. This
+  /// layout is only intended for input for WebRTC. The Front C channel
+  /// is stripped away in the WebRTC audio input pipeline and never seen outside
+  /// of that.
   CEF_CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC = 30,
 
-  // Front L, Front R, Side L, Side R, LFE
+  /// Front L, Front R, Side L, Side R, LFE
   CEF_CHANNEL_LAYOUT_4_1_QUAD_SIDE = 31,
 
-  // Actual channel layout is specified in the bitstream and the actual channel
-  // count is unknown at Chromium media pipeline level (useful for audio
-  // pass-through mode).
+  /// Actual channel layout is specified in the bitstream and the actual channel
+  /// count is unknown at Chromium media pipeline level (useful for audio
+  /// pass-through mode).
   CEF_CHANNEL_LAYOUT_BITSTREAM = 32,
 
-  // Max value, must always equal the largest entry ever logged.
-  CEF_CHANNEL_LAYOUT_MAX = CEF_CHANNEL_LAYOUT_BITSTREAM
+  /// Front L, Front R, Front C, LFE, Side L, Side R,
+  /// Front Height L, Front Height R, Rear Height L, Rear Height R
+  /// Will be represented as six channels (5.1) due to eight channel limit
+  /// kMaxConcurrentChannels
+  CEF_CHANNEL_LAYOUT_5_1_4_DOWNMIX = 33,
+
+  /// Max value, must always equal the largest entry ever logged.
+  CEF_CHANNEL_LAYOUT_MAX = CEF_CHANNEL_LAYOUT_5_1_4_DOWNMIX
 } cef_channel_layout_t;
 
 ///
-// Structure representing the audio parameters for setting up the audio handler.
+/// Structure representing the audio parameters for setting up the audio
+/// handler.
 ///
 typedef struct _cef_audio_parameters_t {
   ///
-  // Layout of the audio channels
+  /// Layout of the audio channels
   ///
   cef_channel_layout_t channel_layout;
 
   ///
-  // Sample rate
+  /// Sample rate
   //
   int sample_rate;
 
   ///
-  // Number of frames per buffer
+  /// Number of frames per buffer
   ///
   int frames_per_buffer;
 } cef_audio_parameters_t;
 
 ///
-// Result codes for CefMediaRouter::CreateRoute. Should be kept in sync with
-// Chromium's media_router::RouteRequestResult::ResultCode type.
+/// Result codes for CefMediaRouter::CreateRoute. Should be kept in sync with
+/// Chromium's media_router::mojom::RouteRequestResultCode type.
 ///
 typedef enum {
   CEF_MRCR_UNKNOWN_ERROR = 0,
@@ -3148,12 +3298,11 @@
   CEF_MRCR_NO_SUPPORTED_PROVIDER = 7,
   CEF_MRCR_CANCELLED = 8,
   CEF_MRCR_ROUTE_ALREADY_EXISTS = 9,
-
-  CEF_MRCR_TOTAL_COUNT = 11  // The total number of values.
+  CEF_MRCR_ROUTE_ALREADY_TERMINATED = 11,
 } cef_media_route_create_result_t;
 
 ///
-// Connection state for a MediaRoute object.
+/// Connection state for a MediaRoute object.
 ///
 typedef enum {
   CEF_MRCS_UNKNOWN,
@@ -3164,8 +3313,8 @@
 } cef_media_route_connection_state_t;
 
 ///
-// Icon types for a MediaSink object. Should be kept in sync with Chromium's
-// media_router::SinkIconType type.
+/// Icon types for a MediaSink object. Should be kept in sync with Chromium's
+/// media_router::SinkIconType type.
 ///
 typedef enum {
   CEF_MSIT_CAST,
@@ -3181,7 +3330,7 @@
 } cef_media_sink_icon_type_t;
 
 ///
-// Device information for a MediaSink object.
+/// Device information for a MediaSink object.
 ///
 typedef struct _cef_media_sink_device_info_t {
   cef_string_t ip_address;
@@ -3189,6 +3338,391 @@
   cef_string_t model_name;
 } cef_media_sink_device_info_t;
 
+///
+/// Represents commands available to TextField.
+///
+typedef enum {
+  CEF_TFC_CUT = 1,
+  CEF_TFC_COPY,
+  CEF_TFC_PASTE,
+  CEF_TFC_UNDO,
+  CEF_TFC_DELETE,
+  CEF_TFC_SELECT_ALL,
+} cef_text_field_commands_t;
+
+///
+/// Chrome toolbar types.
+///
+typedef enum {
+  CEF_CTT_NONE = 1,
+  CEF_CTT_NORMAL,
+  CEF_CTT_LOCATION,
+} cef_chrome_toolbar_type_t;
+
+///
+/// Chrome page action icon types. Should be kept in sync with Chromium's
+/// PageActionIconType type.
+///
+typedef enum {
+  CEF_CPAIT_BOOKMARK_STAR = 0,
+  CEF_CPAIT_CLICK_TO_CALL,
+  CEF_CPAIT_COOKIE_CONTROLS,
+  CEF_CPAIT_FILE_SYSTEM_ACCESS,
+  CEF_CPAIT_FIND,
+  CEF_CPAIT_HIGH_EFFICIENCY,
+  CEF_CPAIT_INTENT_PICKER,
+  CEF_CPAIT_LOCAL_CARD_MIGRATION,
+  CEF_CPAIT_MANAGE_PASSWORDS,
+  CEF_CPAIT_PAYMENTS_OFFER_NOTIFICATION,
+  CEF_CPAIT_PRICE_TRACKING,
+  CEF_CPAIT_PWA_INSTALL,
+  CEF_CPAIT_QR_CODE_GENERATOR,
+  CEF_CPAIT_READER_MODE,
+  CEF_CPAIT_SAVE_AUTOFILL_ADDRESS,
+  CEF_CPAIT_SAVE_CARD,
+  CEF_CPAIT_SEND_TAB_TO_SELF,
+  CEF_CPAIT_SHARING_HUB,
+  CEF_CPAIT_SIDE_SEARCH,
+  CEF_CPAIT_SMS_REMOTE_FETCHER,
+  CEF_CPAIT_TRANSLATE,
+  CEF_CPAIT_VIRTUAL_CARD_ENROLL,
+  CEF_CPAIT_VIRTUAL_CARD_MANUAL_FALLBACK,
+  CEF_CPAIT_ZOOM,
+  CEF_CPAIT_SAVE_IBAN,
+  CEF_CPAIT_MANDATORY_REAUTH,
+  CEF_CPAIT_PRICE_INSIGHTS,
+  CEF_CPAIT_MAX_VALUE = CEF_CPAIT_PRICE_INSIGHTS,
+} cef_chrome_page_action_icon_type_t;
+
+///
+/// Chrome toolbar button types. Should be kept in sync with CEF's internal
+/// ToolbarButtonType type.
+///
+typedef enum {
+  CEF_CTBT_CAST = 0,
+  CEF_CTBT_DOWNLOAD,
+  CEF_CTBT_SEND_TAB_TO_SELF,
+  CEF_CTBT_SIDE_PANEL,
+  CEF_CTBT_MAX_VALUE = CEF_CTBT_SIDE_PANEL,
+} cef_chrome_toolbar_button_type_t;
+
+///
+/// Docking modes supported by CefWindow::AddOverlay.
+///
+typedef enum {
+  CEF_DOCKING_MODE_TOP_LEFT = 1,
+  CEF_DOCKING_MODE_TOP_RIGHT,
+  CEF_DOCKING_MODE_BOTTOM_LEFT,
+  CEF_DOCKING_MODE_BOTTOM_RIGHT,
+  CEF_DOCKING_MODE_CUSTOM,
+} cef_docking_mode_t;
+
+///
+/// Show states supported by CefWindowDelegate::GetInitialShowState.
+///
+typedef enum {
+  CEF_SHOW_STATE_NORMAL = 1,
+  CEF_SHOW_STATE_MINIMIZED,
+  CEF_SHOW_STATE_MAXIMIZED,
+  CEF_SHOW_STATE_FULLSCREEN,
+} cef_show_state_t;
+
+///
+/// Values indicating what state of the touch handle is set.
+///
+typedef enum {
+  CEF_THS_FLAG_NONE = 0,
+  CEF_THS_FLAG_ENABLED = 1 << 0,
+  CEF_THS_FLAG_ORIENTATION = 1 << 1,
+  CEF_THS_FLAG_ORIGIN = 1 << 2,
+  CEF_THS_FLAG_ALPHA = 1 << 3,
+} cef_touch_handle_state_flags_t;
+
+typedef struct _cef_touch_handle_state_t {
+  ///
+  /// Touch handle id. Increments for each new touch handle.
+  ///
+  int touch_handle_id;
+
+  ///
+  /// Combination of cef_touch_handle_state_flags_t values indicating what state
+  /// is set.
+  ///
+  uint32_t flags;
+
+  ///
+  /// Enabled state. Only set if |flags| contains CEF_THS_FLAG_ENABLED.
+  ///
+  int enabled;
+
+  ///
+  /// Orientation state. Only set if |flags| contains CEF_THS_FLAG_ORIENTATION.
+  ///
+  cef_horizontal_alignment_t orientation;
+  int mirror_vertical;
+  int mirror_horizontal;
+
+  ///
+  /// Origin state. Only set if |flags| contains CEF_THS_FLAG_ORIGIN.
+  ///
+  cef_point_t origin;
+
+  ///
+  /// Alpha state. Only set if |flags| contains CEF_THS_FLAG_ALPHA.
+  ///
+  float alpha;
+} cef_touch_handle_state_t;
+
+///
+/// Media access permissions used by OnRequestMediaAccessPermission.
+///
+typedef enum {
+  ///
+  /// No permission.
+  ///
+  CEF_MEDIA_PERMISSION_NONE = 0,
+
+  ///
+  /// Device audio capture permission.
+  ///
+  CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE = 1 << 0,
+
+  ///
+  /// Device video capture permission.
+  ///
+  CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE = 1 << 1,
+
+  ///
+  /// Desktop audio capture permission.
+  ///
+  CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE = 1 << 2,
+
+  ///
+  /// Desktop video capture permission.
+  ///
+  CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE = 1 << 3,
+} cef_media_access_permission_types_t;
+
+///
+/// Permission types used with OnShowPermissionPrompt. Some types are
+/// platform-specific or only supported with the Chrome runtime. Should be kept
+/// in sync with Chromium's permissions::RequestType type.
+///
+typedef enum {
+  CEF_PERMISSION_TYPE_NONE = 0,
+  CEF_PERMISSION_TYPE_ACCESSIBILITY_EVENTS = 1 << 0,
+  CEF_PERMISSION_TYPE_AR_SESSION = 1 << 1,
+  CEF_PERMISSION_TYPE_CAMERA_PAN_TILT_ZOOM = 1 << 2,
+  CEF_PERMISSION_TYPE_CAMERA_STREAM = 1 << 3,
+  CEF_PERMISSION_TYPE_CLIPBOARD = 1 << 4,
+  CEF_PERMISSION_TYPE_TOP_LEVEL_STORAGE_ACCESS = 1 << 5,
+  CEF_PERMISSION_TYPE_DISK_QUOTA = 1 << 6,
+  CEF_PERMISSION_TYPE_LOCAL_FONTS = 1 << 7,
+  CEF_PERMISSION_TYPE_GEOLOCATION = 1 << 8,
+  CEF_PERMISSION_TYPE_IDLE_DETECTION = 1 << 9,
+  CEF_PERMISSION_TYPE_MIC_STREAM = 1 << 10,
+  CEF_PERMISSION_TYPE_MIDI = 1 << 11,
+  CEF_PERMISSION_TYPE_MIDI_SYSEX = 1 << 12,
+  CEF_PERMISSION_TYPE_MULTIPLE_DOWNLOADS = 1 << 13,
+  CEF_PERMISSION_TYPE_NOTIFICATIONS = 1 << 14,
+  CEF_PERMISSION_TYPE_PROTECTED_MEDIA_IDENTIFIER = 1 << 15,
+  CEF_PERMISSION_TYPE_REGISTER_PROTOCOL_HANDLER = 1 << 16,
+  CEF_PERMISSION_TYPE_STORAGE_ACCESS = 1 << 17,
+  CEF_PERMISSION_TYPE_VR_SESSION = 1 << 18,
+  CEF_PERMISSION_TYPE_WINDOW_MANAGEMENT = 1 << 19,
+} cef_permission_request_types_t;
+
+///
+/// Permission request results.
+///
+typedef enum {
+  ///
+  /// Accept the permission request as an explicit user action.
+  ///
+  CEF_PERMISSION_RESULT_ACCEPT,
+
+  ///
+  /// Deny the permission request as an explicit user action.
+  ///
+  CEF_PERMISSION_RESULT_DENY,
+
+  ///
+  /// Dismiss the permission request as an explicit user action.
+  ///
+  CEF_PERMISSION_RESULT_DISMISS,
+
+  ///
+  /// Ignore the permission request. If the prompt remains unhandled (e.g.
+  /// OnShowPermissionPrompt returns false and there is no default permissions
+  /// UI) then any related promises may remain unresolved.
+  ///
+  CEF_PERMISSION_RESULT_IGNORE,
+} cef_permission_request_result_t;
+
+///
+/// Certificate types supported by CefTestServer::CreateAndStart. The matching
+/// certificate file must exist in the "net/data/ssl/certificates" directory.
+/// See CefSetDataDirectoryForTests() for related configuration.
+///
+typedef enum {
+  /// Valid certificate using the IP (127.0.0.1). Loads the "ok_cert.pem" file.
+  CEF_TEST_CERT_OK_IP,
+
+  /// Valid certificate using the domain ("localhost"). Loads the
+  /// "localhost_cert.pem" file.
+  CEF_TEST_CERT_OK_DOMAIN,
+
+  /// Expired certificate. Loads the "expired_cert.pem" file.
+  CEF_TEST_CERT_EXPIRED,
+} cef_test_cert_type_t;
+
+///
+/// Preferences type passed to
+/// CefBrowserProcessHandler::OnRegisterCustomPreferences.
+///
+typedef enum {
+  /// Global preferences registered a single time at application startup.
+  CEF_PREFERENCES_TYPE_GLOBAL,
+
+  /// Request context preferences registered each time a new CefRequestContext
+  /// is created.
+  CEF_PREFERENCES_TYPE_REQUEST_CONTEXT,
+} cef_preferences_type_t;
+
+///
+/// Download interrupt reasons. Should be kept in sync with
+/// Chromium's download::DownloadInterruptReason type.
+///
+typedef enum {
+  CEF_DOWNLOAD_INTERRUPT_REASON_NONE = 0,
+
+  /// Generic file operation failure.
+  CEF_DOWNLOAD_INTERRUPT_REASON_FILE_FAILED = 1,
+
+  /// The file cannot be accessed due to security restrictions.
+  CEF_DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED = 2,
+
+  /// There is not enough room on the drive.
+  CEF_DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE = 3,
+
+  /// The directory or file name is too long.
+  CEF_DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG = 5,
+
+  /// The file is too large for the file system to handle.
+  CEF_DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE = 6,
+
+  /// The file contains a virus.
+  CEF_DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED = 7,
+
+  /// The file was in use. Too many files are opened at once. We have run out of
+  /// memory.
+  CEF_DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR = 10,
+
+  /// The file was blocked due to local policy.
+  CEF_DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED = 11,
+
+  /// An attempt to check the safety of the download failed due to unexpected
+  /// reasons. See http://crbug.com/153212.
+  CEF_DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED = 12,
+
+  /// An attempt was made to seek past the end of a file in opening
+  /// a file (as part of resuming a previously interrupted download).
+  CEF_DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT = 13,
+
+  /// The partial file didn't match the expected hash.
+  CEF_DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH = 14,
+
+  /// The source and the target of the download were the same.
+  CEF_DOWNLOAD_INTERRUPT_REASON_FILE_SAME_AS_SOURCE = 15,
+
+  // Network errors.
+
+  /// Generic network failure.
+  CEF_DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED = 20,
+
+  /// The network operation timed out.
+  CEF_DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT = 21,
+
+  /// The network connection has been lost.
+  CEF_DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED = 22,
+
+  /// The server has gone down.
+  CEF_DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN = 23,
+
+  /// The network request was invalid. This may be due to the original URL or a
+  /// redirected URL:
+  /// - Having an unsupported scheme.
+  /// - Being an invalid URL.
+  /// - Being disallowed by policy.
+  CEF_DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST = 24,
+
+  // Server responses.
+
+  /// The server indicates that the operation has failed (generic).
+  CEF_DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED = 30,
+
+  /// The server does not support range requests.
+  /// Internal use only:  must restart from the beginning.
+  CEF_DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE = 31,
+
+  /// The server does not have the requested data.
+  CEF_DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT = 33,
+
+  /// Server didn't authorize access to resource.
+  CEF_DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED = 34,
+
+  /// Server certificate problem.
+  CEF_DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM = 35,
+
+  /// Server access forbidden.
+  CEF_DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN = 36,
+
+  /// Unexpected server response. This might indicate that the responding server
+  /// may not be the intended server.
+  CEF_DOWNLOAD_INTERRUPT_REASON_SERVER_UNREACHABLE = 37,
+
+  /// The server sent fewer bytes than the content-length header. It may
+  /// indicate that the connection was closed prematurely, or the Content-Length
+  /// header was invalid. The download is only interrupted if strong validators
+  /// are present. Otherwise, it is treated as finished.
+  CEF_DOWNLOAD_INTERRUPT_REASON_SERVER_CONTENT_LENGTH_MISMATCH = 38,
+
+  /// An unexpected cross-origin redirect happened.
+  CEF_DOWNLOAD_INTERRUPT_REASON_SERVER_CROSS_ORIGIN_REDIRECT = 39,
+
+  // User input.
+
+  /// The user canceled the download.
+  CEF_DOWNLOAD_INTERRUPT_REASON_USER_CANCELED = 40,
+
+  /// The user shut down the browser.
+  /// Internal use only:  resume pending downloads if possible.
+  CEF_DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN = 41,
+
+  // Crash.
+
+  /// The browser crashed.
+  /// Internal use only:  resume pending downloads if possible.
+  CEF_DOWNLOAD_INTERRUPT_REASON_CRASH = 50,
+} cef_download_interrupt_reason_t;
+
+///
+/// Specifies the gesture commands.
+///
+typedef enum {
+  CEF_GESTURE_COMMAND_BACK,
+  CEF_GESTURE_COMMAND_FORWARD,
+} cef_gesture_command_t;
+
+///
+/// Specifies the zoom commands supported by CefBrowserHost::Zoom.
+///
+typedef enum {
+  CEF_ZOOM_COMMAND_OUT,
+  CEF_ZOOM_COMMAND_RESET,
+  CEF_ZOOM_COMMAND_IN,
+} cef_zoom_command_t;
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/include/internal/cef_types_content_settings.h b/src/include/internal/cef_types_content_settings.h
new file mode 100644
index 0000000..bb34a6c
--- /dev/null
+++ b/src/include/internal/cef_types_content_settings.h
@@ -0,0 +1,405 @@
+// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CEF_INCLUDE_INTERNAL_CEF_TYPES_CONTENT_SETTINGS_H_
+#define CEF_INCLUDE_INTERNAL_CEF_TYPES_CONTENT_SETTINGS_H_
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///
+/// Supported content setting types. Some types are platform-specific or only
+/// supported with the Chrome runtime. Should be kept in sync with Chromium's
+/// ContentSettingsType type.
+///
+typedef enum {
+  // This setting governs whether cookies are enabled by the user in the
+  /// provided context. However, it may be overridden by other settings. This
+  /// enum should NOT be read directly to determine whether cookies are enabled;
+  /// the client should instead rely on the CookieSettings API.
+  CEF_CONTENT_SETTING_TYPE_COOKIES = 0,
+  CEF_CONTENT_SETTING_TYPE_IMAGES,
+  CEF_CONTENT_SETTING_TYPE_JAVASCRIPT,
+
+  /// This setting governs both popups and unwanted redirects like tab-unders
+  /// and framebusting.
+  CEF_CONTENT_SETTING_TYPE_POPUPS,
+
+  CEF_CONTENT_SETTING_TYPE_GEOLOCATION,
+  CEF_CONTENT_SETTING_TYPE_NOTIFICATIONS,
+  CEF_CONTENT_SETTING_TYPE_AUTO_SELECT_CERTIFICATE,
+  CEF_CONTENT_SETTING_TYPE_MIXEDSCRIPT,
+  CEF_CONTENT_SETTING_TYPE_MEDIASTREAM_MIC,
+  CEF_CONTENT_SETTING_TYPE_MEDIASTREAM_CAMERA,
+  CEF_CONTENT_SETTING_TYPE_PROTOCOL_HANDLERS,
+  CEF_CONTENT_SETTING_TYPE_DEPRECATED_PPAPI_BROKER,
+  CEF_CONTENT_SETTING_TYPE_AUTOMATIC_DOWNLOADS,
+
+  /// Advanced device-specific functions on MIDI devices. MIDI-SysEx
+  /// communications can be used for changing the MIDI device's persistent state
+  /// such as firmware.
+  CEF_CONTENT_SETTING_TYPE_MIDI_SYSEX,
+
+  CEF_CONTENT_SETTING_TYPE_SSL_CERT_DECISIONS,
+  CEF_CONTENT_SETTING_TYPE_PROTECTED_MEDIA_IDENTIFIER,
+  CEF_CONTENT_SETTING_TYPE_APP_BANNER,
+  CEF_CONTENT_SETTING_TYPE_SITE_ENGAGEMENT,
+  CEF_CONTENT_SETTING_TYPE_DURABLE_STORAGE,
+  CEF_CONTENT_SETTING_TYPE_USB_CHOOSER_DATA,
+  CEF_CONTENT_SETTING_TYPE_BLUETOOTH_GUARD,
+  CEF_CONTENT_SETTING_TYPE_BACKGROUND_SYNC,
+  CEF_CONTENT_SETTING_TYPE_AUTOPLAY,
+  CEF_CONTENT_SETTING_TYPE_IMPORTANT_SITE_INFO,
+  CEF_CONTENT_SETTING_TYPE_PERMISSION_AUTOBLOCKER_DATA,
+  CEF_CONTENT_SETTING_TYPE_ADS,
+
+  /// Website setting which stores metadata for the subresource filter to aid in
+  /// decisions for whether or not to show the UI.
+  CEF_CONTENT_SETTING_TYPE_ADS_DATA,
+
+  /// MIDI stands for Musical Instrument Digital Interface. It is a standard
+  /// that allows electronic musical instruments, computers, and other devices
+  /// to communicate with each other.
+  CEF_CONTENT_SETTING_TYPE_MIDI,
+
+  /// This content setting type is for caching password protection service's
+  /// verdicts of each origin.
+  CEF_CONTENT_SETTING_TYPE_PASSWORD_PROTECTION,
+
+  /// Website setting which stores engagement data for media related to a
+  /// specific origin.
+  CEF_CONTENT_SETTING_TYPE_MEDIA_ENGAGEMENT,
+
+  /// Content setting which stores whether or not the site can play audible
+  /// sound. This will not block playback but instead the user will not hear it.
+  CEF_CONTENT_SETTING_TYPE_SOUND,
+
+  /// Website setting which stores the list of client hints that the origin
+  /// requested the browser to remember. The browser is expected to send all
+  /// client hints in the HTTP request headers for every resource requested
+  /// from that origin.
+  CEF_CONTENT_SETTING_TYPE_CLIENT_HINTS,
+
+  /// Generic Sensor API covering ambient-light-sensor, accelerometer, gyroscope
+  /// and magnetometer are all mapped to a single content_settings_type.
+  /// Setting for the Generic Sensor API covering ambient-light-sensor,
+  /// accelerometer, gyroscope and magnetometer. These are all mapped to a
+  /// single ContentSettingsType.
+  CEF_CONTENT_SETTING_TYPE_SENSORS,
+
+  /// Content setting which stores whether or not the user has granted the site
+  /// permission to respond to accessibility events, which can be used to
+  /// provide a custom accessibility experience. Requires explicit user consent
+  /// because some users may not want sites to know they're using assistive
+  /// technology.
+  CEF_CONTENT_SETTING_TYPE_ACCESSIBILITY_EVENTS,
+
+  /// Used to store whether to allow a website to install a payment handler.
+  CEF_CONTENT_SETTING_TYPE_PAYMENT_HANDLER,
+
+  /// Content setting which stores whether to allow sites to ask for permission
+  /// to access USB devices. If this is allowed specific device permissions are
+  /// stored under USB_CHOOSER_DATA.
+  CEF_CONTENT_SETTING_TYPE_USB_GUARD,
+
+  /// Nothing is stored in this setting at present. Please refer to
+  /// BackgroundFetchPermissionContext for details on how this permission
+  /// is ascertained.
+  CEF_CONTENT_SETTING_TYPE_BACKGROUND_FETCH,
+
+  /// Website setting which stores the amount of times the user has dismissed
+  /// intent picker UI without explicitly choosing an option.
+  CEF_CONTENT_SETTING_TYPE_INTENT_PICKER_DISPLAY,
+
+  /// Used to store whether to allow a website to detect user active/idle state.
+  CEF_CONTENT_SETTING_TYPE_IDLE_DETECTION,
+
+  /// Content settings for access to serial ports. The "guard" content setting
+  /// stores whether to allow sites to ask for permission to access a port. The
+  /// permissions granted to access particular ports are stored in the "chooser
+  /// data" website setting.
+  CEF_CONTENT_SETTING_TYPE_SERIAL_GUARD,
+  CEF_CONTENT_SETTING_TYPE_SERIAL_CHOOSER_DATA,
+
+  /// Nothing is stored in this setting at present. Please refer to
+  /// PeriodicBackgroundSyncPermissionContext for details on how this permission
+  /// is ascertained.
+  /// This content setting is not registered because it does not require access
+  /// to any existing providers.
+  CEF_CONTENT_SETTING_TYPE_PERIODIC_BACKGROUND_SYNC,
+
+  /// Content setting which stores whether to allow sites to ask for permission
+  /// to do Bluetooth scanning.
+  CEF_CONTENT_SETTING_TYPE_BLUETOOTH_SCANNING,
+
+  /// Content settings for access to HID devices. The "guard" content setting
+  /// stores whether to allow sites to ask for permission to access a device.
+  /// The permissions granted to access particular devices are stored in the
+  /// "chooser data" website setting.
+  CEF_CONTENT_SETTING_TYPE_HID_GUARD,
+  CEF_CONTENT_SETTING_TYPE_HID_CHOOSER_DATA,
+
+  /// Wake Lock API, which has two lock types: screen and system locks.
+  /// Currently, screen locks do not need any additional permission, and system
+  /// locks are always denied while the right UI is worked out.
+  CEF_CONTENT_SETTING_TYPE_WAKE_LOCK_SCREEN,
+  CEF_CONTENT_SETTING_TYPE_WAKE_LOCK_SYSTEM,
+
+  /// Legacy SameSite cookie behavior. This disables SameSite=Lax-by-default,
+  /// SameSite=None requires Secure, and Schemeful Same-Site, forcing the
+  /// legacy behavior wherein 1) cookies that don't specify SameSite are treated
+  /// as SameSite=None, 2) SameSite=None cookies are not required to be Secure,
+  /// and 3) schemeful same-site is not active.
+  ///
+  /// This will also be used to revert to legacy behavior when future changes
+  /// in cookie handling are introduced.
+  CEF_CONTENT_SETTING_TYPE_LEGACY_COOKIE_ACCESS,
+
+  /// Content settings which stores whether to allow sites to ask for permission
+  /// to save changes to an original file selected by the user through the
+  /// File System Access API.
+  CEF_CONTENT_SETTING_TYPE_FILE_SYSTEM_WRITE_GUARD,
+
+  /// Used to store whether to allow a website to exchange data with NFC
+  /// devices.
+  CEF_CONTENT_SETTING_TYPE_NFC,
+
+  /// Website setting to store permissions granted to access particular
+  /// Bluetooth devices.
+  CEF_CONTENT_SETTING_TYPE_BLUETOOTH_CHOOSER_DATA,
+
+  /// Full access to the system clipboard (sanitized read without user gesture,
+  /// and unsanitized read and write with user gesture).
+  CEF_CONTENT_SETTING_TYPE_CLIPBOARD_READ_WRITE,
+
+  /// This is special-cased in the permissions layer to always allow, and as
+  /// such doesn't have associated prefs data.
+  CEF_CONTENT_SETTING_TYPE_CLIPBOARD_SANITIZED_WRITE,
+
+  /// This content setting type is for caching safe browsing real time url
+  /// check's verdicts of each origin.
+  CEF_CONTENT_SETTING_TYPE_SAFE_BROWSING_URL_CHECK_DATA,
+
+  /// Used to store whether a site is allowed to request AR or VR sessions with
+  /// the WebXr Device API.
+  CEF_CONTENT_SETTING_TYPE_VR,
+  CEF_CONTENT_SETTING_TYPE_AR,
+
+  /// Content setting which stores whether to allow site to open and read files
+  /// and directories selected through the File System Access API.
+  CEF_CONTENT_SETTING_TYPE_FILE_SYSTEM_READ_GUARD,
+
+  /// Access to first party storage in a third-party context. Exceptions are
+  /// scoped to the combination of requesting/top-level origin, and are managed
+  /// through the Storage Access API. For the time being, this content setting
+  /// exists in parallel to third-party cookie rules stored in COOKIES.
+  CEF_CONTENT_SETTING_TYPE_STORAGE_ACCESS,
+
+  /// Content setting which stores whether to allow a site to control camera
+  /// movements. It does not give access to camera.
+  CEF_CONTENT_SETTING_TYPE_CAMERA_PAN_TILT_ZOOM,
+
+  /// Content setting for Screen Enumeration and Screen Detail functionality.
+  /// Permits access to detailed multi-screen information, like size and
+  /// position. Permits placing fullscreen and windowed content on specific
+  /// screens. See also: https://w3c.github.io/window-placement
+  CEF_CONTENT_SETTING_TYPE_WINDOW_MANAGEMENT,
+
+  /// Stores whether to allow insecure websites to make private network
+  /// requests.
+  /// See also: https://wicg.github.io/cors-rfc1918
+  /// Set through enterprise policies only.
+  CEF_CONTENT_SETTING_TYPE_INSECURE_PRIVATE_NETWORK,
+
+  /// Content setting which stores whether or not a site can access low-level
+  /// locally installed font data using the Local Fonts Access API.
+  CEF_CONTENT_SETTING_TYPE_LOCAL_FONTS,
+
+  /// Stores per-origin state for permission auto-revocation (for all permission
+  /// types).
+  CEF_CONTENT_SETTING_TYPE_PERMISSION_AUTOREVOCATION_DATA,
+
+  /// Stores per-origin state of the most recently selected directory for the
+  /// use by the File System Access API.
+  CEF_CONTENT_SETTING_TYPE_FILE_SYSTEM_LAST_PICKED_DIRECTORY,
+
+  /// Controls access to the getDisplayMedia API when {preferCurrentTab: true}
+  /// is specified.
+  CEF_CONTENT_SETTING_TYPE_DISPLAY_CAPTURE,
+
+  /// Website setting to store permissions metadata granted to paths on the
+  /// local file system via the File System Access API.
+  /// |FILE_SYSTEM_WRITE_GUARD| is the corresponding "guard" setting. The stored
+  /// data represents valid permission only if
+  /// |FILE_SYSTEM_ACCESS_EXTENDED_PERMISSION| is enabled via user opt-in.
+  /// Otherwise, they represent "recently granted but revoked permission", which
+  /// are used to restore the permission.
+  CEF_CONTENT_SETTING_TYPE_FILE_SYSTEM_ACCESS_CHOOSER_DATA,
+
+  /// Stores a grant that allows a relying party to send a request for identity
+  /// information to specified identity providers, potentially through any
+  /// anti-tracking measures that would otherwise prevent it. This setting is
+  /// associated with the relying party's origin.
+  CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_SHARING,
+
+  /// Whether to use the v8 optimized JIT for running JavaScript on the page.
+  CEF_CONTENT_SETTING_TYPE_JAVASCRIPT_JIT,
+
+  /// Content setting which stores user decisions to allow loading a site over
+  /// HTTP. Entries are added by hostname when a user bypasses the HTTPS-First
+  /// Mode interstitial warning when a site does not support HTTPS. Allowed
+  /// hosts are exact hostname matches -- subdomains of a host on the allowlist
+  /// must be separately allowlisted.
+  CEF_CONTENT_SETTING_TYPE_HTTP_ALLOWED,
+
+  /// Stores metadata related to form fill, such as e.g. whether user data was
+  /// autofilled on a specific website.
+  CEF_CONTENT_SETTING_TYPE_FORMFILL_METADATA,
+
+  /// Setting to indicate that there is an active federated sign-in session
+  /// between a specified relying party and a specified identity provider for
+  /// a specified account. When this is present it allows access to session
+  /// management capabilities between the sites. This setting is associated
+  /// with the relying party's origin.
+  CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_ACTIVE_SESSION,
+
+  /// Setting to indicate whether Chrome should automatically apply darkening to
+  /// web content.
+  CEF_CONTENT_SETTING_TYPE_AUTO_DARK_WEB_CONTENT,
+
+  /// Setting to indicate whether Chrome should request the desktop view of a
+  /// site instead of the mobile one.
+  CEF_CONTENT_SETTING_TYPE_REQUEST_DESKTOP_SITE,
+
+  /// Setting to indicate whether browser should allow signing into a website
+  /// via the browser FedCM API.
+  CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_API,
+
+  /// Stores notification interactions per origin for the past 90 days.
+  /// Interactions per origin are pre-aggregated over seven-day windows: A
+  /// notification interaction or display is assigned to the last Monday
+  /// midnight in local time.
+  CEF_CONTENT_SETTING_TYPE_NOTIFICATION_INTERACTIONS,
+
+  /// Website setting which stores the last reduced accept language negotiated
+  /// for a given origin, to be used on future visits to the origin.
+  CEF_CONTENT_SETTING_TYPE_REDUCED_ACCEPT_LANGUAGE,
+
+  /// Website setting which is used for NotificationPermissionReviewService to
+  /// store origin blocklist from review notification permissions feature.
+  CEF_CONTENT_SETTING_TYPE_NOTIFICATION_PERMISSION_REVIEW,
+
+  /// Website setting to store permissions granted to access particular devices
+  /// in private network.
+  CEF_CONTENT_SETTING_TYPE_PRIVATE_NETWORK_GUARD,
+  CEF_CONTENT_SETTING_TYPE_PRIVATE_NETWORK_CHOOSER_DATA,
+
+  /// Website setting which stores whether the browser has observed the user
+  /// signing into an identity-provider based on observing the IdP-SignIn-Status
+  /// HTTP header.
+  CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_IDENTITY_PROVIDER_SIGNIN_STATUS,
+
+  /// Website setting which is used for UnusedSitePermissionsService to
+  /// store revoked permissions of unused sites from unused site permissions
+  /// feature.
+  CEF_CONTENT_SETTING_TYPE_REVOKED_UNUSED_SITE_PERMISSIONS,
+
+  /// Similar to STORAGE_ACCESS, but applicable at the page-level rather than
+  /// being specific to a frame.
+  CEF_CONTENT_SETTING_TYPE_TOP_LEVEL_STORAGE_ACCESS,
+
+  /// Setting to indicate whether user has opted in to allowing auto re-authn
+  /// via the FedCM API.
+  CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_AUTO_REAUTHN_PERMISSION,
+
+  /// Website setting which stores whether the user has explicitly registered
+  /// a website as an identity-provider.
+  CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_IDENTITY_PROVIDER_REGISTRATION,
+
+  /// Content setting which is used to indicate whether anti-abuse functionality
+  /// should be enabled.
+  CEF_CONTENT_SETTING_TYPE_ANTI_ABUSE,
+
+  /// Content setting used to indicate whether third-party storage partitioning
+  /// should be enabled.
+  CEF_CONTENT_SETTING_TYPE_THIRD_PARTY_STORAGE_PARTITIONING,
+
+  /// Used to indicate whether HTTPS-First Mode is enabled on the hostname.
+  CEF_CONTENT_SETTING_TYPE_HTTPS_ENFORCED,
+
+  /// Setting for enabling the `getAllScreensMedia` API. Spec link:
+  /// https://github.com/screen-share/capture-all-screens
+  CEF_CONTENT_SETTING_TYPE_ALL_SCREEN_CAPTURE,
+
+  /// Stores per origin metadata for cookie controls.
+  CEF_CONTENT_SETTING_TYPE_COOKIE_CONTROLS_METADATA,
+
+  /// Content Setting for 3PC accesses granted via 3PC deprecation trial.
+  CEF_CONTENT_SETTING_TYPE_TPCD_SUPPORT,
+
+  /// Content setting used to indicate whether entering picture-in-picture
+  /// automatically should be enabled.
+  CEF_CONTENT_SETTING_TYPE_AUTO_PICTURE_IN_PICTURE,
+
+  /// Content Setting for 3PC accesses granted by metadata delivered via the
+  /// component updater service. This type will only be used when
+  /// `net::features::kTpcdMetadataGrants` is enabled.
+  CEF_CONTENT_SETTING_TYPE_TPCD_METADATA_GRANTS,
+
+  /// Whether user has opted into keeping file/directory permissions persistent
+  /// between visits for a given origin. When enabled, permission metadata
+  /// stored under |FILE_SYSTEM_ACCESS_CHOOSER_DATA| can auto-grant incoming
+  /// permission request.
+  CEF_CONTENT_SETTING_TYPE_FILE_SYSTEM_ACCESS_EXTENDED_PERMISSION,
+
+  CEF_CONTENT_SETTING_TYPE_NUM_TYPES,
+} cef_content_setting_types_t;
+
+///
+/// Supported content setting values. Should be kept in sync with Chromium's
+/// ContentSetting type.
+///
+typedef enum {
+  CEF_CONTENT_SETTING_VALUE_DEFAULT = 0,
+  CEF_CONTENT_SETTING_VALUE_ALLOW,
+  CEF_CONTENT_SETTING_VALUE_BLOCK,
+  CEF_CONTENT_SETTING_VALUE_ASK,
+  CEF_CONTENT_SETTING_VALUE_SESSION_ONLY,
+  CEF_CONTENT_SETTING_VALUE_DETECT_IMPORTANT_CONTENT,
+
+  CEF_CONTENT_SETTING_VALUE_NUM_VALUES
+} cef_content_setting_values_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // CEF_INCLUDE_INTERNAL_CEF_TYPES_CONTENT_SETTINGS_H_
diff --git a/src/include/cef_request_callback.h b/src/include/internal/cef_types_geometry.h
similarity index 61%
copy from src/include/cef_request_callback.h
copy to src/include/internal/cef_types_geometry.h
index 68094de..7410f15 100644
--- a/src/include/cef_request_callback.h
+++ b/src/include/internal/cef_types_geometry.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved.
+// Copyright (c) 2014 Marshall A. Greenblatt. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
@@ -26,38 +26,53 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// ---------------------------------------------------------------------------
-//
-// The contents of this file must follow a specific format in order to
-// support the CEF translator tool. See the translator.README.txt file in the
-// tools directory for more information.
-//
 
-#ifndef CEF_INCLUDE_CEF_REQUEST_CALLBACK_H_
-#define CEF_INCLUDE_CEF_REQUEST_CALLBACK_H_
+#ifndef CEF_INCLUDE_INTERNAL_CEF_TYPES_GEOMETRY_H_
+#define CEF_INCLUDE_INTERNAL_CEF_TYPES_GEOMETRY_H_
 #pragma once
 
-#include "include/cef_base.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 ///
-// Callback interface used for asynchronous continuation of url requests.
+/// Structure representing a point.
 ///
-/*--cef(source=library)--*/
-class CefRequestCallback : public virtual CefBaseRefCounted {
- public:
-  ///
-  // Continue the url request. If |allow| is true the request will be continued.
-  // Otherwise, the request will be canceled.
-  ///
-  /*--cef(capi_name=cont)--*/
-  virtual void Continue(bool allow) = 0;
+typedef struct _cef_point_t {
+  int x;
+  int y;
+} cef_point_t;
 
-  ///
-  // Cancel the url request.
-  ///
-  /*--cef()--*/
-  virtual void Cancel() = 0;
-};
+///
+/// Structure representing a rectangle.
+///
+typedef struct _cef_rect_t {
+  int x;
+  int y;
+  int width;
+  int height;
+} cef_rect_t;
 
-#endif  // CEF_INCLUDE_CEF_REQUEST_CALLBACK_H_
+///
+/// Structure representing a size.
+///
+typedef struct _cef_size_t {
+  int width;
+  int height;
+} cef_size_t;
+
+///
+/// Structure representing insets.
+///
+typedef struct _cef_insets_t {
+  int top;
+  int left;
+  int bottom;
+  int right;
+} cef_insets_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // CEF_INCLUDE_INTERNAL_CEF_TYPES_GEOMETRY_H_
diff --git a/src/include/internal/cef_types_linux.h b/src/include/internal/cef_types_linux.h
index b21d655..171cda3 100644
--- a/src/include/internal/cef_types_linux.h
+++ b/src/include/internal/cef_types_linux.h
@@ -43,6 +43,7 @@
 
 #include "include/internal/cef_export.h"
 #include "include/internal/cef_string.h"
+#include "include/internal/cef_types_geometry.h"
 
 // Handle types.
 #if defined(CEF_X11)
@@ -64,15 +65,15 @@
 #endif
 
 ///
-// Return the singleton X11 display shared with Chromium. The display is not
-// thread-safe and must only be accessed on the browser process UI thread.
+/// Return the singleton X11 display shared with Chromium. The display is not
+/// thread-safe and must only be accessed on the browser process UI thread.
 ///
 #if defined(CEF_X11)
-CEF_EXPORT XDisplay* cef_get_xdisplay();
+CEF_EXPORT XDisplay* cef_get_xdisplay(void);
 #endif
 
 ///
-// Structure representing CefExecuteProcess arguments.
+/// Structure representing CefExecuteProcess arguments.
 ///
 typedef struct _cef_main_args_t {
   int argc;
@@ -80,58 +81,58 @@
 } cef_main_args_t;
 
 ///
-// Class representing window information.
+/// Class representing window information.
 ///
 typedef struct _cef_window_info_t {
   ///
-  // The initial title of the window, to be set when the window is created.
-  // Some layout managers (e.g., Compiz) can look at the window title
-  // in order to decide where to place the window when it is
-  // created. When this attribute is not empty, the window title will
-  // be set before the window is mapped to the dispay. Otherwise the
-  // title will be initially empty.
+  /// The initial title of the window, to be set when the window is created.
+  /// Some layout managers (e.g., Compiz) can look at the window title
+  /// in order to decide where to place the window when it is
+  /// created. When this attribute is not empty, the window title will
+  /// be set before the window is mapped to the dispay. Otherwise the
+  /// title will be initially empty.
   ///
   cef_string_t window_name;
 
-  unsigned int x;
-  unsigned int y;
-  unsigned int width;
-  unsigned int height;
+  ///
+  /// Initial window bounds.
+  ///
+  cef_rect_t bounds;
 
   ///
-  // Pointer for the parent window.
+  /// Pointer for the parent window.
   ///
   cef_window_handle_t parent_window;
 
   ///
-  // Set to true (1) to create the browser using windowless (off-screen)
-  // rendering. No window will be created for the browser and all rendering will
-  // occur via the CefRenderHandler interface. The |parent_window| value will be
-  // used to identify monitor info and to act as the parent window for dialogs,
-  // context menus, etc. If |parent_window| is not provided then the main screen
-  // monitor will be used and some functionality that requires a parent window
-  // may not function correctly. In order to create windowless browsers the
-  // CefSettings.windowless_rendering_enabled value must be set to true.
-  // Transparent painting is enabled by default but can be disabled by setting
-  // CefBrowserSettings.background_color to an opaque value.
+  /// Set to true (1) to create the browser using windowless (off-screen)
+  /// rendering. No window will be created for the browser and all rendering
+  /// will occur via the CefRenderHandler interface. The |parent_window| value
+  /// will be used to identify monitor info and to act as the parent window for
+  /// dialogs, context menus, etc. If |parent_window| is not provided then the
+  /// main screen monitor will be used and some functionality that requires a
+  /// parent window may not function correctly. In order to create windowless
+  /// browsers the CefSettings.windowless_rendering_enabled value must be set to
+  /// true. Transparent painting is enabled by default but can be disabled by
+  /// setting CefBrowserSettings.background_color to an opaque value.
   ///
   int windowless_rendering_enabled;
 
   ///
-  // Set to true (1) to enable shared textures for windowless rendering. Only
-  // valid if windowless_rendering_enabled above is also set to true. Currently
-  // only supported on Windows (D3D11).
+  /// Set to true (1) to enable shared textures for windowless rendering. Only
+  /// valid if windowless_rendering_enabled above is also set to true. Currently
+  /// only supported on Windows (D3D11).
   ///
   int shared_texture_enabled;
 
   ///
-  // Set to true (1) to enable the ability to issue BeginFrame requests from the
-  // client application by calling CefBrowserHost::SendExternalBeginFrame.
+  /// Set to true (1) to enable the ability to issue BeginFrame requests from
+  /// the client application by calling CefBrowserHost::SendExternalBeginFrame.
   ///
   int external_begin_frame_enabled;
 
   ///
-  // Pointer for the new browser window. Only used with windowed rendering.
+  /// Pointer for the new browser window. Only used with windowed rendering.
   ///
   cef_window_handle_t window;
 } cef_window_info_t;
diff --git a/src/include/internal/cef_types_mac.h b/src/include/internal/cef_types_mac.h
index 14e61da..8ee619e 100644
--- a/src/include/internal/cef_types_mac.h
+++ b/src/include/internal/cef_types_mac.h
@@ -33,8 +33,9 @@
 
 #include "include/base/cef_build.h"
 
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
 #include "include/internal/cef_string.h"
+#include "include/internal/cef_types_geometry.h"
 
 // Handle types.
 // Actually NSCursor*
@@ -73,7 +74,7 @@
 #endif
 
 ///
-// Structure representing CefExecuteProcess arguments.
+/// Structure representing CefExecuteProcess arguments.
 ///
 typedef struct _cef_main_args_t {
   int argc;
@@ -81,54 +82,56 @@
 } cef_main_args_t;
 
 ///
-// Class representing window information.
+/// Class representing window information.
 ///
 typedef struct _cef_window_info_t {
   cef_string_t window_name;
-  int x;
-  int y;
-  int width;
-  int height;
 
   ///
-  // Set to true (1) to create the view initially hidden.
+  /// Initial window bounds.
+  ///
+  cef_rect_t bounds;
+
+  ///
+  /// Set to true (1) to create the view initially hidden.
   ///
   int hidden;
 
   ///
-  // NSView pointer for the parent view.
+  /// NSView pointer for the parent view.
   ///
   cef_window_handle_t parent_view;
 
   ///
-  // Set to true (1) to create the browser using windowless (off-screen)
-  // rendering. No view will be created for the browser and all rendering will
-  // occur via the CefRenderHandler interface. The |parent_view| value will be
-  // used to identify monitor info and to act as the parent view for dialogs,
-  // context menus, etc. If |parent_view| is not provided then the main screen
-  // monitor will be used and some functionality that requires a parent view
-  // may not function correctly. In order to create windowless browsers the
-  // CefSettings.windowless_rendering_enabled value must be set to true.
-  // Transparent painting is enabled by default but can be disabled by setting
-  // CefBrowserSettings.background_color to an opaque value.
+  /// Set to true (1) to create the browser using windowless (off-screen)
+  /// rendering. No view will be created for the browser and all rendering will
+  /// occur via the CefRenderHandler interface. The |parent_view| value will be
+  /// used to identify monitor info and to act as the parent view for dialogs,
+  /// context menus, etc. If |parent_view| is not provided then the main screen
+  /// monitor will be used and some functionality that requires a parent view
+  /// may not function correctly. In order to create windowless browsers the
+  /// CefSettings.windowless_rendering_enabled value must be set to true.
+  /// Transparent painting is enabled by default but can be disabled by setting
+  /// CefBrowserSettings.background_color to an opaque value.
   ///
   int windowless_rendering_enabled;
 
   ///
-  // Set to true (1) to enable shared textures for windowless rendering. Only
-  // valid if windowless_rendering_enabled above is also set to true. Currently
-  // only supported on Windows (D3D11).
+  /// Set to true (1) to enable shared textures for windowless rendering. Only
+  /// valid if windowless_rendering_enabled above is also set to true. Currently
+  /// only supported on Windows (D3D11).
   ///
   int shared_texture_enabled;
 
   ///
-  // Set to true (1) to enable the ability to issue BeginFrame from the client
-  // application.
+  /// Set to true (1) to enable the ability to issue BeginFrame from the client
+  /// application.
   ///
   int external_begin_frame_enabled;
 
   ///
-  // NSView pointer for the new browser view. Only used with windowed rendering.
+  /// NSView pointer for the new browser view. Only used with windowed
+  /// rendering.
   ///
   cef_window_handle_t view;
 } cef_window_info_t;
@@ -137,6 +140,6 @@
 }
 #endif
 
-#endif  // OS_MACOSX
+#endif  // OS_MAC
 
 #endif  // CEF_INCLUDE_INTERNAL_CEF_TYPES_MAC_H_
diff --git a/src/include/internal/cef_types_win.h b/src/include/internal/cef_types_win.h
index dce8967..abf80c7 100644
--- a/src/include/internal/cef_types_win.h
+++ b/src/include/internal/cef_types_win.h
@@ -35,7 +35,9 @@
 
 #if defined(OS_WIN)
 #include <windows.h>
+
 #include "include/internal/cef_string.h"
+#include "include/internal/cef_types_geometry.h"
 
 // Handle types.
 #define cef_cursor_handle_t HCURSOR
@@ -51,54 +53,53 @@
 #endif
 
 ///
-// Structure representing CefExecuteProcess arguments.
+/// Structure representing CefExecuteProcess arguments.
 ///
-typedef struct _cef_main_args_t { HINSTANCE instance; } cef_main_args_t;
+typedef struct _cef_main_args_t {
+  HINSTANCE instance;
+} cef_main_args_t;
 
 ///
-// Structure representing window information.
+/// Structure representing window information.
 ///
 typedef struct _cef_window_info_t {
   // Standard parameters required by CreateWindowEx()
   DWORD ex_style;
   cef_string_t window_name;
   DWORD style;
-  int x;
-  int y;
-  int width;
-  int height;
+  cef_rect_t bounds;
   cef_window_handle_t parent_window;
   HMENU menu;
 
   ///
-  // Set to true (1) to create the browser using windowless (off-screen)
-  // rendering. No window will be created for the browser and all rendering will
-  // occur via the CefRenderHandler interface. The |parent_window| value will be
-  // used to identify monitor info and to act as the parent window for dialogs,
-  // context menus, etc. If |parent_window| is not provided then the main screen
-  // monitor will be used and some functionality that requires a parent window
-  // may not function correctly. In order to create windowless browsers the
-  // CefSettings.windowless_rendering_enabled value must be set to true.
-  // Transparent painting is enabled by default but can be disabled by setting
-  // CefBrowserSettings.background_color to an opaque value.
+  /// Set to true (1) to create the browser using windowless (off-screen)
+  /// rendering. No window will be created for the browser and all rendering
+  /// will occur via the CefRenderHandler interface. The |parent_window| value
+  /// will be used to identify monitor info and to act as the parent window for
+  /// dialogs, context menus, etc. If |parent_window| is not provided then the
+  /// main screen monitor will be used and some functionality that requires a
+  /// parent window may not function correctly. In order to create windowless
+  /// browsers the CefSettings.windowless_rendering_enabled value must be set to
+  /// true. Transparent painting is enabled by default but can be disabled by
+  /// setting CefBrowserSettings.background_color to an opaque value.
   ///
   int windowless_rendering_enabled;
 
   ///
-  // Set to true (1) to enable shared textures for windowless rendering. Only
-  // valid if windowless_rendering_enabled above is also set to true. Currently
-  // only supported on Windows (D3D11).
+  /// Set to true (1) to enable shared textures for windowless rendering. Only
+  /// valid if windowless_rendering_enabled above is also set to true. Currently
+  /// only supported on Windows (D3D11).
   ///
   int shared_texture_enabled;
 
   ///
-  // Set to true (1) to enable the ability to issue BeginFrame requests from the
-  // client application by calling CefBrowserHost::SendExternalBeginFrame.
+  /// Set to true (1) to enable the ability to issue BeginFrame requests from
+  /// the client application by calling CefBrowserHost::SendExternalBeginFrame.
   ///
   int external_begin_frame_enabled;
 
   ///
-  // Handle for the new browser window. Only used with windowed rendering.
+  /// Handle for the new browser window. Only used with windowed rendering.
   ///
   cef_window_handle_t window;
 } cef_window_info_t;
diff --git a/src/include/internal/cef_types_wrappers.h b/src/include/internal/cef_types_wrappers.h
index 0e8caec..a6e99e3 100644
--- a/src/include/internal/cef_types_wrappers.h
+++ b/src/include/internal/cef_types_wrappers.h
@@ -31,24 +31,29 @@
 #define CEF_INCLUDE_INTERNAL_CEF_TYPES_WRAPPERS_H_
 #pragma once
 
+#include <limits>
+
 #include "include/internal/cef_string.h"
 #include "include/internal/cef_string_list.h"
 #include "include/internal/cef_types.h"
 
 ///
-// Template class that provides common functionality for CEF structure wrapping.
+/// Template class that provides common functionality for CEF structure
+/// wrapping. Use only with non-POD types that benefit from referencing unowned
+/// members.
 ///
 template <class traits>
 class CefStructBase : public traits::struct_type {
  public:
-  typedef typename traits::struct_type struct_type;
+  using struct_type = typename traits::struct_type;
 
   CefStructBase() : attached_to_(NULL) { Init(); }
   virtual ~CefStructBase() {
     // Only clear this object's data if it isn't currently attached to a
     // structure.
-    if (!attached_to_)
+    if (!attached_to_) {
       Clear(this);
+    }
   }
 
   CefStructBase(const CefStructBase& r) {
@@ -61,22 +66,15 @@
   }
 
   ///
-  // Clear this object's values.
-  ///
-  void Reset() {
-    Clear(this);
-    Init();
-  }
-
-  ///
-  // Attach to the source structure's existing values. DetachTo() can be called
-  // to insert the values back into the existing structure.
+  /// Attach to the source structure's existing values. DetachTo() can be called
+  /// to insert the values back into the existing structure.
   ///
   void AttachTo(struct_type& source) {
     // Only clear this object's data if it isn't currently attached to a
     // structure.
-    if (!attached_to_)
+    if (!attached_to_) {
       Clear(this);
+    }
 
     // This object is now attached to the new structure.
     attached_to_ = &source;
@@ -86,7 +84,7 @@
   }
 
   ///
-  // Relinquish ownership of values to the target structure.
+  /// Relinquish ownership of values to the target structure.
   ///
   void DetachTo(struct_type& target) {
     if (attached_to_ != &target) {
@@ -103,8 +101,8 @@
   }
 
   ///
-  // Set this object's values. If |copy| is true the source structure's values
-  // will be copied instead of referenced.
+  /// Set this object's values. If |copy| is true the source structure's values
+  /// will be copied instead of referenced.
   ///
   void Set(const struct_type& source, bool copy) {
     traits::set(&source, this, copy);
@@ -131,30 +129,14 @@
   struct_type* attached_to_;
 };
 
-struct CefPointTraits {
-  typedef cef_point_t struct_type;
-
-  static inline void init(struct_type* s) {}
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    *target = *src;
-  }
-};
-
 ///
-// Class representing a point.
+/// Class representing a point.
 ///
-class CefPoint : public CefStructBase<CefPointTraits> {
+class CefPoint : public cef_point_t {
  public:
-  typedef CefStructBase<CefPointTraits> parent;
-
-  CefPoint() : parent() {}
-  CefPoint(const cef_point_t& r) : parent(r) {}
-  CefPoint(const CefPoint& r) : parent(r) {}
-  CefPoint(int x, int y) : parent() { Set(x, y); }
+  CefPoint() : cef_point_t{} {}
+  CefPoint(const cef_point_t& r) : cef_point_t(r) {}
+  CefPoint(int x, int y) : cef_point_t{x, y} {}
 
   bool IsEmpty() const { return x <= 0 && y <= 0; }
   void Set(int x_val, int y_val) { x = x_val, y = y_val; }
@@ -168,41 +150,26 @@
   return !(a == b);
 }
 
-struct CefRectTraits {
-  typedef cef_rect_t struct_type;
-
-  static inline void init(struct_type* s) {}
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    *target = *src;
-  }
-};
-
 ///
-// Class representing a rectangle.
+/// Class representing a rectangle.
 ///
-class CefRect : public CefStructBase<CefRectTraits> {
+class CefRect : public cef_rect_t {
  public:
-  typedef CefStructBase<CefRectTraits> parent;
-
-  CefRect() : parent() {}
-  CefRect(const cef_rect_t& r) : parent(r) {}
-  CefRect(const CefRect& r) : parent(r) {}
-  CefRect(int x, int y, int width, int height) : parent() {
-    Set(x, y, width, height);
-  }
+  CefRect() : cef_rect_t{} {}
+  CefRect(const cef_rect_t& r) : cef_rect_t(r) {}
+  CefRect(int x, int y, int width, int height)
+      : cef_rect_t{x, y, width, height} {}
 
   bool IsEmpty() const { return width <= 0 || height <= 0; }
   void Set(int x_val, int y_val, int width_val, int height_val) {
     x = x_val, y = y_val, width = width_val, height = height_val;
   }
 
-  // Returns true if the point identified by point_x and point_y falls inside
-  // this rectangle.  The point (x, y) is inside the rectangle, but the
-  // point (x + width, y + height) is not.
+  ///
+  /// Returns true if the point identified by point_x and point_y falls inside
+  /// this rectangle.  The point (x, y) is inside the rectangle, but the
+  /// point (x + width, y + height) is not.
+  ///
   bool Contains(int point_x, int point_y) const {
     return (point_x >= x) && (point_x < x + width) && (point_y >= y) &&
            (point_y < y + height);
@@ -220,30 +187,14 @@
   return !(a == b);
 }
 
-struct CefSizeTraits {
-  typedef cef_size_t struct_type;
-
-  static inline void init(struct_type* s) {}
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    *target = *src;
-  }
-};
-
 ///
-// Class representing a size.
+/// Class representing a size.
 ///
-class CefSize : public CefStructBase<CefSizeTraits> {
+class CefSize : public cef_size_t {
  public:
-  typedef CefStructBase<CefSizeTraits> parent;
-
-  CefSize() : parent() {}
-  CefSize(const cef_size_t& r) : parent(r) {}
-  CefSize(const CefSize& r) : parent(r) {}
-  CefSize(int width, int height) : parent() { Set(width, height); }
+  CefSize() : cef_size_t{} {}
+  CefSize(const cef_size_t& r) : cef_size_t(r) {}
+  CefSize(int width, int height) : cef_size_t{width, height} {}
 
   bool IsEmpty() const { return width <= 0 || height <= 0; }
   void Set(int width_val, int height_val) {
@@ -259,30 +210,19 @@
   return !(a == b);
 }
 
-struct CefRangeTraits {
-  typedef cef_range_t struct_type;
-
-  static inline void init(struct_type* s) {}
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    *target = *src;
-  }
-};
-
 ///
-// Class representing a range.
+/// Class representing a range.
 ///
-class CefRange : public CefStructBase<CefRangeTraits> {
+class CefRange : public cef_range_t {
  public:
-  typedef CefStructBase<CefRangeTraits> parent;
+  CefRange() : cef_range_t{} {}
+  CefRange(const cef_range_t& r) : cef_range_t(r) {}
+  CefRange(uint32_t from, uint32_t to) : cef_range_t{from, to} {}
 
-  CefRange() : parent() {}
-  CefRange(const cef_range_t& r) : parent(r) {}
-  CefRange(const CefRange& r) : parent(r) {}
-  CefRange(int from, int to) : parent() { Set(from, to); }
+  static CefRange InvalidRange() {
+    return CefRange((std::numeric_limits<uint32_t>::max)(),
+                    (std::numeric_limits<uint32_t>::max)());
+  }
 
   void Set(int from_val, int to_val) { from = from_val, to = to_val; }
 };
@@ -295,32 +235,15 @@
   return !(a == b);
 }
 
-struct CefInsetsTraits {
-  typedef cef_insets_t struct_type;
-
-  static inline void init(struct_type* s) {}
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    *target = *src;
-  }
-};
-
 ///
-// Class representing insets.
+/// Class representing insets.
 ///
-class CefInsets : public CefStructBase<CefInsetsTraits> {
+class CefInsets : public cef_insets_t {
  public:
-  typedef CefStructBase<CefInsetsTraits> parent;
-
-  CefInsets() : parent() {}
-  CefInsets(const cef_insets_t& r) : parent(r) {}
-  CefInsets(const CefInsets& r) : parent(r) {}
-  CefInsets(int top, int left, int bottom, int right) : parent() {
-    Set(top, left, bottom, right);
-  }
+  CefInsets() : cef_insets_t{} {}
+  CefInsets(const cef_insets_t& r) : cef_insets_t(r) {}
+  CefInsets(int top, int left, int bottom, int right)
+      : cef_insets_t{top, left, bottom, right} {}
 
   void Set(int top_val, int left_val, int bottom_val, int right_val) {
     top = top_val, left = left_val, bottom = bottom_val, right = right_val;
@@ -336,32 +259,16 @@
   return !(a == b);
 }
 
-struct CefDraggableRegionTraits {
-  typedef cef_draggable_region_t struct_type;
-
-  static inline void init(struct_type* s) {}
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    *target = *src;
-  }
-};
-
 ///
-// Class representing a draggable region.
+/// Class representing a draggable region.
 ///
-class CefDraggableRegion : public CefStructBase<CefDraggableRegionTraits> {
+class CefDraggableRegion : public cef_draggable_region_t {
  public:
-  typedef CefStructBase<CefDraggableRegionTraits> parent;
-
-  CefDraggableRegion() : parent() {}
-  CefDraggableRegion(const cef_draggable_region_t& r) : parent(r) {}
-  CefDraggableRegion(const CefDraggableRegion& r) : parent(r) {}
-  CefDraggableRegion(const CefRect& bounds, bool draggable) : parent() {
-    Set(bounds, draggable);
-  }
+  CefDraggableRegion() : cef_draggable_region_t{} {}
+  CefDraggableRegion(const cef_draggable_region_t& r)
+      : cef_draggable_region_t(r) {}
+  CefDraggableRegion(const cef_rect_t& bounds, bool draggable)
+      : cef_draggable_region_t{bounds, draggable} {}
 
   void Set(const CefRect& bounds_val, bool draggable_val) {
     bounds = bounds_val, draggable = draggable_val;
@@ -378,46 +285,22 @@
   return !(a == b);
 }
 
-struct CefScreenInfoTraits {
-  typedef cef_screen_info_t struct_type;
-
-  static inline void init(struct_type* s) {}
-
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    target->device_scale_factor = src->device_scale_factor;
-    target->depth = src->depth;
-    target->depth_per_component = src->depth_per_component;
-    target->is_monochrome = src->is_monochrome;
-    target->rect = src->rect;
-    target->available_rect = src->available_rect;
-  }
-};
-
 ///
-// Class representing the virtual screen information for use when window
-// rendering is disabled.
+/// Class representing the virtual screen information for use when window
+/// rendering is disabled.
 ///
-class CefScreenInfo : public CefStructBase<CefScreenInfoTraits> {
+class CefScreenInfo : public cef_screen_info_t {
  public:
-  typedef CefStructBase<CefScreenInfoTraits> parent;
-
-  CefScreenInfo() : parent() {}
-  CefScreenInfo(const cef_screen_info_t& r) : parent(r) {}
-  CefScreenInfo(const CefScreenInfo& r) : parent(r) {}
+  CefScreenInfo() : cef_screen_info_t{} {}
+  CefScreenInfo(const cef_screen_info_t& r) : cef_screen_info_t(r) {}
   CefScreenInfo(float device_scale_factor,
                 int depth,
                 int depth_per_component,
                 bool is_monochrome,
-                const CefRect& rect,
-                const CefRect& available_rect)
-      : parent() {
-    Set(device_scale_factor, depth, depth_per_component, is_monochrome, rect,
-        available_rect);
-  }
+                const cef_rect_t& rect,
+                const cef_rect_t& available_rect)
+      : cef_screen_info_t{device_scale_factor, depth, depth_per_component,
+                          is_monochrome,       rect,  available_rect} {}
 
   void Set(float device_scale_factor_val,
            int depth_val,
@@ -434,109 +317,44 @@
   }
 };
 
-struct CefKeyEventTraits {
-  typedef cef_key_event_t struct_type;
-
-  static inline void init(struct_type* s) {}
-
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    target->type = src->type;
-    target->modifiers = src->modifiers;
-    target->windows_key_code = src->windows_key_code;
-    target->native_key_code = src->native_key_code;
-    target->is_system_key = src->is_system_key;
-    target->character = src->character;
-    target->unmodified_character = src->unmodified_character;
-    target->focus_on_editable_field = src->focus_on_editable_field;
-  }
+///
+/// Class representing a a keyboard event.
+///
+class CefKeyEvent : public cef_key_event_t {
+ public:
+  CefKeyEvent() : cef_key_event_t{} {}
+  CefKeyEvent(const cef_key_event_t& r) : cef_key_event_t(r) {}
 };
 
 ///
-// Class representing a a keyboard event.
+/// Class representing a mouse event.
 ///
-typedef CefStructBase<CefKeyEventTraits> CefKeyEvent;
-
-struct CefMouseEventTraits {
-  typedef cef_mouse_event_t struct_type;
-
-  static inline void init(struct_type* s) {}
-
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    target->x = src->x;
-    target->y = src->y;
-    target->modifiers = src->modifiers;
-  }
+class CefMouseEvent : public cef_mouse_event_t {
+ public:
+  CefMouseEvent() : cef_mouse_event_t{} {}
+  CefMouseEvent(const cef_mouse_event_t& r) : cef_mouse_event_t(r) {}
 };
 
 ///
-// Class representing a mouse event.
+/// Class representing a touch event.
 ///
-typedef CefStructBase<CefMouseEventTraits> CefMouseEvent;
-
-struct CefTouchEventTraits {
-  typedef cef_touch_event_t struct_type;
-
-  static inline void init(struct_type* s) {}
-
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    *target = *src;
-  }
+class CefTouchEvent : public cef_touch_event_t {
+ public:
+  CefTouchEvent() : cef_touch_event_t{} {}
+  CefTouchEvent(const cef_touch_event_t& r) : cef_touch_event_t(r) {}
 };
 
 ///
-// Class representing a touch event.
+/// Class representing popup window features.
 ///
-typedef CefStructBase<CefTouchEventTraits> CefTouchEvent;
-
-struct CefPopupFeaturesTraits {
-  typedef cef_popup_features_t struct_type;
-
-  static inline void init(struct_type* s) {
-    s->menuBarVisible = true;
-    s->statusBarVisible = true;
-    s->toolBarVisible = true;
-    s->scrollbarsVisible = true;
-  }
-
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    target->x = src->x;
-    target->xSet = src->xSet;
-    target->y = src->y;
-    target->ySet = src->ySet;
-    target->width = src->width;
-    target->widthSet = src->widthSet;
-    target->height = src->height;
-    target->heightSet = src->heightSet;
-    target->menuBarVisible = src->menuBarVisible;
-    target->statusBarVisible = src->statusBarVisible;
-    target->toolBarVisible = src->toolBarVisible;
-    target->scrollbarsVisible = src->scrollbarsVisible;
-  }
+class CefPopupFeatures : public cef_popup_features_t {
+ public:
+  CefPopupFeatures() : cef_popup_features_t{} {}
+  CefPopupFeatures(const cef_popup_features_t& r) : cef_popup_features_t(r) {}
 };
 
-///
-// Class representing popup window features.
-///
-typedef CefStructBase<CefPopupFeaturesTraits> CefPopupFeatures;
-
 struct CefSettingsTraits {
-  typedef cef_settings_t struct_type;
+  using struct_type = cef_settings_t;
 
   static inline void init(struct_type* s) { s->size = sizeof(struct_type); }
 
@@ -546,16 +364,16 @@
     cef_string_clear(&s->main_bundle_path);
     cef_string_clear(&s->cache_path);
     cef_string_clear(&s->root_cache_path);
-    cef_string_clear(&s->user_data_path);
     cef_string_clear(&s->user_agent);
-    cef_string_clear(&s->product_version);
+    cef_string_clear(&s->user_agent_product);
     cef_string_clear(&s->locale);
     cef_string_clear(&s->log_file);
     cef_string_clear(&s->javascript_flags);
     cef_string_clear(&s->resources_dir_path);
     cef_string_clear(&s->locales_dir_path);
     cef_string_clear(&s->accept_language_list);
-    cef_string_clear(&s->application_client_id_for_file_scanning);
+    cef_string_clear(&s->cookieable_schemes_list);
+    cef_string_clear(&s->chrome_policy_id);
   }
 
   static inline void set(const struct_type* src,
@@ -569,6 +387,7 @@
                    &target->framework_dir_path, copy);
     cef_string_set(src->main_bundle_path.str, src->main_bundle_path.length,
                    &target->main_bundle_path, copy);
+    target->chrome_runtime = src->chrome_runtime;
     target->multi_threaded_message_loop = src->multi_threaded_message_loop;
     target->external_message_pump = src->external_message_pump;
     target->windowless_rendering_enabled = src->windowless_rendering_enabled;
@@ -578,20 +397,19 @@
                    &target->cache_path, copy);
     cef_string_set(src->root_cache_path.str, src->root_cache_path.length,
                    &target->root_cache_path, copy);
-    cef_string_set(src->user_data_path.str, src->user_data_path.length,
-                   &target->user_data_path, copy);
     target->persist_session_cookies = src->persist_session_cookies;
     target->persist_user_preferences = src->persist_user_preferences;
 
     cef_string_set(src->user_agent.str, src->user_agent.length,
                    &target->user_agent, copy);
-    cef_string_set(src->product_version.str, src->product_version.length,
-                   &target->product_version, copy);
+    cef_string_set(src->user_agent_product.str, src->user_agent_product.length,
+                   &target->user_agent_product, copy);
     cef_string_set(src->locale.str, src->locale.length, &target->locale, copy);
 
     cef_string_set(src->log_file.str, src->log_file.length, &target->log_file,
                    copy);
     target->log_severity = src->log_severity;
+    target->log_items = src->log_items;
     cef_string_set(src->javascript_flags.str, src->javascript_flags.length,
                    &target->javascript_flags, copy);
 
@@ -602,31 +420,37 @@
     target->pack_loading_disabled = src->pack_loading_disabled;
     target->remote_debugging_port = src->remote_debugging_port;
     target->uncaught_exception_stack_size = src->uncaught_exception_stack_size;
-    target->ignore_certificate_errors = src->ignore_certificate_errors;
     target->background_color = src->background_color;
 
     cef_string_set(src->accept_language_list.str,
                    src->accept_language_list.length,
                    &target->accept_language_list, copy);
-    cef_string_set(src->application_client_id_for_file_scanning.str,
-                   src->application_client_id_for_file_scanning.length,
-                   &target->application_client_id_for_file_scanning, copy);
+
+    cef_string_set(src->cookieable_schemes_list.str,
+                   src->cookieable_schemes_list.length,
+                   &target->cookieable_schemes_list, copy);
+    target->cookieable_schemes_exclude_defaults =
+        src->cookieable_schemes_exclude_defaults;
+
+    cef_string_set(src->chrome_policy_id.str, src->chrome_policy_id.length,
+                   &target->chrome_policy_id, copy);
   }
 };
 
 ///
-// Class representing initialization settings.
+/// Class representing initialization settings.
 ///
-typedef CefStructBase<CefSettingsTraits> CefSettings;
+using CefSettings = CefStructBase<CefSettingsTraits>;
 
 struct CefRequestContextSettingsTraits {
-  typedef cef_request_context_settings_t struct_type;
+  using struct_type = cef_request_context_settings_t;
 
   static inline void init(struct_type* s) { s->size = sizeof(struct_type); }
 
   static inline void clear(struct_type* s) {
     cef_string_clear(&s->cache_path);
     cef_string_clear(&s->accept_language_list);
+    cef_string_clear(&s->cookieable_schemes_list);
   }
 
   static inline void set(const struct_type* src,
@@ -636,21 +460,26 @@
                    &target->cache_path, copy);
     target->persist_session_cookies = src->persist_session_cookies;
     target->persist_user_preferences = src->persist_user_preferences;
-    target->ignore_certificate_errors = src->ignore_certificate_errors;
     cef_string_set(src->accept_language_list.str,
                    src->accept_language_list.length,
                    &target->accept_language_list, copy);
+
+    cef_string_set(src->cookieable_schemes_list.str,
+                   src->cookieable_schemes_list.length,
+                   &target->cookieable_schemes_list, copy);
+    target->cookieable_schemes_exclude_defaults =
+        src->cookieable_schemes_exclude_defaults;
   }
 };
 
 ///
-// Class representing request context initialization settings.
+/// Class representing request context initialization settings.
 ///
-typedef CefStructBase<CefRequestContextSettingsTraits>
-    CefRequestContextSettings;
+using CefRequestContextSettings =
+    CefStructBase<CefRequestContextSettingsTraits>;
 
 struct CefBrowserSettingsTraits {
-  typedef cef_browser_settings_t struct_type;
+  using struct_type = cef_browser_settings_t;
 
   static inline void init(struct_type* s) { s->size = sizeof(struct_type); }
 
@@ -662,7 +491,6 @@
     cef_string_clear(&s->cursive_font_family);
     cef_string_clear(&s->fantasy_font_family);
     cef_string_clear(&s->default_encoding);
-    cef_string_clear(&s->accept_language_list);
   }
 
   static inline void set(const struct_type* src,
@@ -700,11 +528,6 @@
     target->javascript_close_windows = src->javascript_close_windows;
     target->javascript_access_clipboard = src->javascript_access_clipboard;
     target->javascript_dom_paste = src->javascript_dom_paste;
-    target->plugins = src->plugins;
-    target->universal_access_from_file_urls =
-        src->universal_access_from_file_urls;
-    target->file_access_from_file_urls = src->file_access_from_file_urls;
-    target->web_security = src->web_security;
     target->image_loading = src->image_loading;
     target->image_shrink_standalone_to_fit =
         src->image_shrink_standalone_to_fit;
@@ -712,24 +535,22 @@
     target->tab_to_links = src->tab_to_links;
     target->local_storage = src->local_storage;
     target->databases = src->databases;
-    target->application_cache = src->application_cache;
     target->webgl = src->webgl;
 
     target->background_color = src->background_color;
 
-    cef_string_set(src->accept_language_list.str,
-                   src->accept_language_list.length,
-                   &target->accept_language_list, copy);
+    target->chrome_status_bubble = src->chrome_status_bubble;
+    target->chrome_zoom_bubble = src->chrome_zoom_bubble;
   }
 };
 
 ///
-// Class representing browser initialization settings.
+/// Class representing browser initialization settings.
 ///
-typedef CefStructBase<CefBrowserSettingsTraits> CefBrowserSettings;
+using CefBrowserSettings = CefStructBase<CefBrowserSettingsTraits>;
 
 struct CefURLPartsTraits {
-  typedef cef_urlparts_t struct_type;
+  using struct_type = cef_urlparts_t;
 
   static inline void init(struct_type* s) {}
 
@@ -766,68 +587,22 @@
 };
 
 ///
-// Class representing a URL's component parts.
+/// Class representing a URL's component parts.
 ///
-typedef CefStructBase<CefURLPartsTraits> CefURLParts;
-
-struct CefTimeTraits {
-  typedef cef_time_t struct_type;
-
-  static inline void init(struct_type* s) {}
-
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    *target = *src;
-  }
-};
+using CefURLParts = CefStructBase<CefURLPartsTraits>;
 
 ///
-// Class representing a time.
+/// Class representing the state of a touch handle.
 ///
-class CefTime : public CefStructBase<CefTimeTraits> {
+class CefTouchHandleState : public cef_touch_handle_state_t {
  public:
-  typedef CefStructBase<CefTimeTraits> parent;
-
-  CefTime() : parent() {}
-  CefTime(const cef_time_t& r) : parent(r) {}
-  CefTime(const CefTime& r) : parent(r) {}
-  explicit CefTime(time_t r) : parent() { SetTimeT(r); }
-  explicit CefTime(double r) : parent() { SetDoubleT(r); }
-
-  // Converts to/from time_t.
-  void SetTimeT(time_t r) { cef_time_from_timet(r, this); }
-  time_t GetTimeT() const {
-    time_t time = 0;
-    cef_time_to_timet(this, &time);
-    return time;
-  }
-
-  // Converts to/from a double which is the number of seconds since epoch
-  // (Jan 1, 1970). Webkit uses this format to represent time. A value of 0
-  // means "not initialized".
-  void SetDoubleT(double r) { cef_time_from_doublet(r, this); }
-  double GetDoubleT() const {
-    double time = 0;
-    cef_time_to_doublet(this, &time);
-    return time;
-  }
-
-  // Set this object to now.
-  void Now() { cef_time_now(this); }
-
-  // Return the delta between this object and |other| in milliseconds.
-  long long Delta(const CefTime& other) {
-    long long delta = 0;
-    cef_time_delta(this, &other, &delta);
-    return delta;
-  }
+  CefTouchHandleState() : cef_touch_handle_state_t{} {}
+  CefTouchHandleState(const cef_touch_handle_state_t& r)
+      : cef_touch_handle_state_t(r) {}
 };
 
 struct CefCookieTraits {
-  typedef cef_cookie_t struct_type;
+  using struct_type = cef_cookie_t;
 
   static inline void init(struct_type* s) {}
 
@@ -857,130 +632,96 @@
 };
 
 ///
-// Class representing a cookie.
+/// Class representing a cookie.
 ///
-typedef CefStructBase<CefCookieTraits> CefCookie;
+using CefCookie = CefStructBase<CefCookieTraits>;
 
-struct CefCursorInfoTraits {
-  typedef cef_cursor_info_t struct_type;
-
-  static inline void init(struct_type* s) {}
-
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    *target = *src;
-  }
+///
+/// Class representing cursor information.
+///
+class CefCursorInfo : public cef_cursor_info_t {
+ public:
+  CefCursorInfo() : cef_cursor_info_t{} {}
+  CefCursorInfo(const cef_cursor_info_t& r) : cef_cursor_info_t(r) {}
 };
 
-///
-// Class representing cursor information.
-///
-typedef CefStructBase<CefCursorInfoTraits> CefCursorInfo;
-
 struct CefPdfPrintSettingsTraits {
-  typedef cef_pdf_print_settings_t struct_type;
+  using struct_type = cef_pdf_print_settings_t;
 
   static inline void init(struct_type* s) {}
 
   static inline void clear(struct_type* s) {
-    cef_string_clear(&s->header_footer_title);
-    cef_string_clear(&s->header_footer_url);
+    cef_string_clear(&s->page_ranges);
+    cef_string_clear(&s->header_template);
+    cef_string_clear(&s->footer_template);
   }
 
   static inline void set(const struct_type* src,
                          struct_type* target,
                          bool copy) {
-    cef_string_set(src->header_footer_title.str,
-                   src->header_footer_title.length,
-                   &target->header_footer_title, copy);
-    cef_string_set(src->header_footer_url.str, src->header_footer_url.length,
-                   &target->header_footer_url, copy);
+    target->landscape = src->landscape;
+    target->print_background = src->print_background;
+    target->scale = src->scale;
+    target->paper_width = src->paper_width;
+    target->paper_height = src->paper_height;
+    target->prefer_css_page_size = src->prefer_css_page_size;
 
-    target->page_width = src->page_width;
-    target->page_height = src->page_height;
-
-    target->scale_factor = src->scale_factor;
-
+    target->margin_type = src->margin_type;
     target->margin_top = src->margin_top;
     target->margin_right = src->margin_right;
     target->margin_bottom = src->margin_bottom;
     target->margin_left = src->margin_left;
-    target->margin_type = src->margin_type;
 
-    target->header_footer_enabled = src->header_footer_enabled;
-    target->selection_only = src->selection_only;
-    target->landscape = src->landscape;
-    target->backgrounds_enabled = src->backgrounds_enabled;
+    cef_string_set(src->page_ranges.str, src->page_ranges.length,
+                   &target->page_ranges, copy);
+
+    target->display_header_footer = src->display_header_footer;
+    cef_string_set(src->header_template.str, src->header_template.length,
+                   &target->header_template, copy);
+    cef_string_set(src->footer_template.str, src->footer_template.length,
+                   &target->footer_template, copy);
+
+    target->generate_tagged_pdf = src->generate_tagged_pdf;
   }
 };
 
 ///
-// Class representing PDF print settings
+/// Class representing PDF print settings
 ///
-typedef CefStructBase<CefPdfPrintSettingsTraits> CefPdfPrintSettings;
+using CefPdfPrintSettings = CefStructBase<CefPdfPrintSettingsTraits>;
 
-struct CefBoxLayoutSettingsTraits {
-  typedef cef_box_layout_settings_t struct_type;
-
-  static inline void init(struct_type* s) {}
-
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    *target = *src;
-  }
+///
+/// Class representing CefBoxLayout settings.
+///
+class CefBoxLayoutSettings : public cef_box_layout_settings_t {
+ public:
+  CefBoxLayoutSettings() : cef_box_layout_settings_t{} {}
+  CefBoxLayoutSettings(const cef_box_layout_settings_t& r)
+      : cef_box_layout_settings_t(r) {}
 };
 
 ///
-// Class representing CefBoxLayout settings.
+/// Class representing IME composition underline.
 ///
-typedef CefStructBase<CefBoxLayoutSettingsTraits> CefBoxLayoutSettings;
-
-struct CefCompositionUnderlineTraits {
-  typedef cef_composition_underline_t struct_type;
-
-  static inline void init(struct_type* s) {}
-
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    *target = *src;
-  }
+class CefCompositionUnderline : public cef_composition_underline_t {
+ public:
+  CefCompositionUnderline() : cef_composition_underline_t{} {}
+  CefCompositionUnderline(const cef_composition_underline_t& r)
+      : cef_composition_underline_t(r) {}
 };
 
 ///
-// Class representing IME composition underline.
+/// Class representing CefAudioParameters settings
 ///
-typedef CefStructBase<CefCompositionUnderlineTraits> CefCompositionUnderline;
-
-struct CefAudioParametersTraits {
-  typedef cef_audio_parameters_t struct_type;
-
-  static inline void init(struct_type* s) {}
-
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    *target = *src;
-  }
+class CefAudioParameters : public cef_audio_parameters_t {
+ public:
+  CefAudioParameters() : cef_audio_parameters_t{} {}
+  CefAudioParameters(const cef_audio_parameters_t& r)
+      : cef_audio_parameters_t(r) {}
 };
 
-///
-// Class representing CefAudioParameters settings
-///
-typedef CefStructBase<CefAudioParametersTraits> CefAudioParameters;
-
 struct CefMediaSinkDeviceInfoTraits {
-  typedef cef_media_sink_device_info_t struct_type;
+  using struct_type = cef_media_sink_device_info_t;
 
   static inline void init(struct_type* s) {}
 
@@ -1001,8 +742,8 @@
 };
 
 ///
-// Class representing MediaSink device info.
+/// Class representing MediaSink device info.
 ///
-typedef CefStructBase<CefMediaSinkDeviceInfoTraits> CefMediaSinkDeviceInfo;
+using CefMediaSinkDeviceInfo = CefStructBase<CefMediaSinkDeviceInfoTraits>;
 
 #endif  // CEF_INCLUDE_INTERNAL_CEF_TYPES_WRAPPERS_H_
diff --git a/src/include/internal/cef_win.h b/src/include/internal/cef_win.h
index 292864e..a37d21c 100644
--- a/src/include/internal/cef_win.h
+++ b/src/include/internal/cef_win.h
@@ -31,38 +31,23 @@
 #define CEF_INCLUDE_INTERNAL_CEF_WIN_H_
 #pragma once
 
+#include "include/internal/cef_app_win.h"
 #include "include/internal/cef_types_win.h"
 #include "include/internal/cef_types_wrappers.h"
 
-///
 // Handle types.
-///
 #define CefCursorHandle cef_cursor_handle_t
 #define CefEventHandle cef_event_handle_t
 #define CefWindowHandle cef_window_handle_t
 
-struct CefMainArgsTraits {
-  typedef cef_main_args_t struct_type;
-
-  static inline void init(struct_type* s) {}
-  static inline void clear(struct_type* s) {}
-
-  static inline void set(const struct_type* src,
-                         struct_type* target,
-                         bool copy) {
-    target->instance = src->instance;
-  }
-};
-
-// Class representing CefExecuteProcess arguments.
-class CefMainArgs : public CefStructBase<CefMainArgsTraits> {
+///
+/// Class representing CefExecuteProcess arguments.
+///
+class CefMainArgs : public cef_main_args_t {
  public:
-  typedef CefStructBase<CefMainArgsTraits> parent;
-
-  CefMainArgs() : parent() {}
-  explicit CefMainArgs(const cef_main_args_t& r) : parent(r) {}
-  explicit CefMainArgs(const CefMainArgs& r) : parent(r) {}
-  explicit CefMainArgs(HINSTANCE hInstance) : parent() { instance = hInstance; }
+  CefMainArgs() : cef_main_args_t{} {}
+  CefMainArgs(const cef_main_args_t& r) : cef_main_args_t(r) {}
+  explicit CefMainArgs(HINSTANCE hInstance) : cef_main_args_t{hInstance} {}
 };
 
 struct CefWindowInfoTraits {
@@ -81,10 +66,7 @@
     cef_string_set(src->window_name.str, src->window_name.length,
                    &target->window_name, copy);
     target->style = src->style;
-    target->x = src->x;
-    target->y = src->y;
-    target->width = src->width;
-    target->height = src->height;
+    target->bounds = src->bounds;
     target->parent_window = src->parent_window;
     target->menu = src->menu;
     target->windowless_rendering_enabled = src->windowless_rendering_enabled;
@@ -95,7 +77,7 @@
 };
 
 ///
-// Class representing window information.
+/// Class representing window information.
 ///
 class CefWindowInfo : public CefStructBase<CefWindowInfoTraits> {
  public:
@@ -105,45 +87,45 @@
   explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {}
   explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {}
 
+  CefWindowInfo& operator=(const CefWindowInfo&) = default;
+  CefWindowInfo& operator=(CefWindowInfo&&) = default;
+
   ///
-  // Create the browser as a child window.
+  /// Create the browser as a child window.
   ///
-  void SetAsChild(CefWindowHandle parent, RECT windowRect) {
+  void SetAsChild(CefWindowHandle parent, const CefRect& windowBounds) {
     style =
         WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_TABSTOP | WS_VISIBLE;
     parent_window = parent;
-    x = windowRect.left;
-    y = windowRect.top;
-    width = windowRect.right - windowRect.left;
-    height = windowRect.bottom - windowRect.top;
+    bounds = windowBounds;
   }
 
   ///
-  // Create the browser as a popup window.
+  /// Create the browser as a popup window.
   ///
   void SetAsPopup(CefWindowHandle parent, const CefString& windowName) {
     style =
         WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE;
     parent_window = parent;
-    x = CW_USEDEFAULT;
-    y = CW_USEDEFAULT;
-    width = CW_USEDEFAULT;
-    height = CW_USEDEFAULT;
+    bounds.x = CW_USEDEFAULT;
+    bounds.y = CW_USEDEFAULT;
+    bounds.width = CW_USEDEFAULT;
+    bounds.height = CW_USEDEFAULT;
 
     cef_string_copy(windowName.c_str(), windowName.length(), &window_name);
   }
 
   ///
-  // Create the browser using windowless (off-screen) rendering. No window
-  // will be created for the browser and all rendering will occur via the
-  // CefRenderHandler interface. The |parent| value will be used to identify
-  // monitor info and to act as the parent window for dialogs, context menus,
-  // etc. If |parent| is not provided then the main screen monitor will be used
-  // and some functionality that requires a parent window may not function
-  // correctly. In order to create windowless browsers the
-  // CefSettings.windowless_rendering_enabled value must be set to true.
-  // Transparent painting is enabled by default but can be disabled by setting
-  // CefBrowserSettings.background_color to an opaque value.
+  /// Create the browser using windowless (off-screen) rendering. No window
+  /// will be created for the browser and all rendering will occur via the
+  /// CefRenderHandler interface. The |parent| value will be used to identify
+  /// monitor info and to act as the parent window for dialogs, context menus,
+  /// etc. If |parent| is not provided then the main screen monitor will be used
+  /// and some functionality that requires a parent window may not function
+  /// correctly. In order to create windowless browsers the
+  /// CefSettings.windowless_rendering_enabled value must be set to true.
+  /// Transparent painting is enabled by default but can be disabled by setting
+  /// CefBrowserSettings.background_color to an opaque value.
   ///
   void SetAsWindowless(CefWindowHandle parent) {
     windowless_rendering_enabled = TRUE;
@@ -151,4 +133,45 @@
   }
 };
 
+#if defined(ARCH_CPU_32_BITS)
+///
+/// Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
+/// stack size. This function must be called at the top of the executable entry
+/// point function (`main()` or `wWinMain()`). It is used in combination with
+/// the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
+/// flag on executable targets. This saves significant memory on threads (like
+/// those in the Windows thread pool, and others) whose stack size can only be
+/// controlled via the linker flag.
+///
+/// CEF's main thread needs at least a 1.5 MiB stack size in order to avoid
+/// stack overflow crashes. However, if this is set in the PE file then other
+/// threads get this size as well, leading to address-space exhaustion in 32-bit
+/// CEF. This function uses fibers to switch the main thread to a 4 MiB stack
+/// (roughly the same effective size as the 64-bit build's 8 MiB stack) before
+/// running any other code.
+///
+/// Choose the function variant that matches the entry point function type used
+/// by the executable. Reusing the entry point minimizes confusion when
+/// examining call stacks in crash reports.
+///
+/// If this function is already running on the fiber it will return -1
+/// immediately, meaning that execution should proceed with the remainder of the
+/// entry point function. Otherwise, this function will block until the entry
+/// point function has completed execution on the fiber and then return a result
+/// >= 0, meaning that the entry point function should return the result
+/// immediately without proceeding with execution.
+///
+int CefRunWinMainWithPreferredStackSize(wWinMainPtr wWinMain,
+                                        HINSTANCE hInstance,
+                                        LPWSTR lpCmdLine,
+                                        int nCmdShow);
+int CefRunMainWithPreferredStackSize(mainPtr main, int argc, char* argv[]);
+#endif  // defined(ARCH_CPU_32_BITS)
+
+///
+/// Set to true before calling Windows APIs like TrackPopupMenu that enter a
+/// modal message loop. Set to false after exiting the modal message loop.
+///
+void CefSetOSModalLoop(bool osModalLoop);
+
 #endif  // CEF_INCLUDE_INTERNAL_CEF_WIN_H_
diff --git a/src/include/test/cef_test_helpers.h b/src/include/test/cef_test_helpers.h
index a4e45b8..7f7c374 100644
--- a/src/include/test/cef_test_helpers.h
+++ b/src/include/test/cef_test_helpers.h
@@ -51,11 +51,20 @@
 #include "include/cef_frame.h"
 
 ///
-// Execute JavaScript with a user gesture to trigger functionality like
-// onbeforeunload handlers that will otherwise be blocked.
+/// Execute JavaScript with a user gesture to trigger functionality like
+/// onbeforeunload handlers that will otherwise be blocked.
 ///
 /*--cef(optional_param=javascript)--*/
 void CefExecuteJavaScriptWithUserGestureForTests(CefRefPtr<CefFrame> frame,
                                                  const CefString& javascript);
 
+///
+/// Set the DIR_SRC_TEST_DATA_ROOT directory used to load test data. Must be
+/// configured when running from a CEF binary distribution. Defaults to the
+/// "chromium/src" directory when running from a local CEF/Chromium build. |dir|
+/// must be an absolute path.
+///
+/*--cef()--*/
+void CefSetDataDirectoryForTests(const CefString& dir);
+
 #endif  // CEF_INCLUDE_TEST_CEF_TEST_HELPERS_H_
diff --git a/src/include/test/cef_test_server.h b/src/include/test/cef_test_server.h
new file mode 100644
index 0000000..80a59e1
--- /dev/null
+++ b/src/include/test/cef_test_server.h
@@ -0,0 +1,184 @@
+// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---------------------------------------------------------------------------
+//
+// The contents of this file must follow a specific format in order to
+// support the CEF translator tool. See the translator.README.txt file in the
+// tools directory for more information.
+//
+// THIS FILE IS FOR TESTING PURPOSES ONLY.
+//
+// The APIs defined in this file are for testing purposes only. They should only
+// be included from unit test targets.
+//
+
+#ifndef CEF_INCLUDE_TEST_CEF_TEST_SERVER_H_
+#define CEF_INCLUDE_TEST_CEF_TEST_SERVER_H_
+#pragma once
+
+#if !defined(BUILDING_CEF_SHARED) && !defined(WRAPPING_CEF_SHARED) && \
+    !defined(UNIT_TEST)
+#error This file can be included for unit tests only
+#endif
+
+#include <map>
+#include "include/cef_base.h"
+#include "include/cef_request.h"
+
+class CefTestServerConnection;
+class CefTestServerHandler;
+
+///
+/// Class representing an embedded test server that supports HTTP/HTTPS
+/// requests. This is a basic server providing only an essential subset of the
+/// HTTP/1.1 protocol. Especially, it assumes that the request syntax is
+/// correct. It *does not* support a Chunked Transfer Encoding. Server capacity
+/// is limited and is intended to handle only a small number of simultaneous
+/// connections (e.g. for communicating between applications on localhost). The
+/// methods of this class are safe to call from any thread in the brower process
+/// unless otherwise indicated.
+///
+/*--cef(source=library)--*/
+class CefTestServer : public CefBaseRefCounted {
+ public:
+  ///
+  /// Create and start a new test server that binds to |port|. If |port| is 0 an
+  /// available port number will be selected. If |https_server| is true the
+  /// server will be HTTPS, otherwise it will be HTTP. When |https_server| is
+  /// true the |https_cert_type| value is used to configure the certificate
+  /// type. Returns the newly created server object on success, or nullptr if
+  /// the server cannot be started.
+  ///
+  /// A new thread will be created for each CreateAndStart call (the "dedicated
+  /// server thread"). It is therefore recommended to use a different
+  /// CefTestServerHandler instance for each CreateAndStart call to avoid thread
+  /// safety issues in the CefTestServerHandler implementation.
+  ///
+  /// On success, this method will block until the dedicated server thread has
+  /// started. The server will continue running until Stop is called.
+  ///
+  /*--cef()--*/
+  static CefRefPtr<CefTestServer> CreateAndStart(
+      uint16_t port,
+      bool https_server,
+      cef_test_cert_type_t https_cert_type,
+      CefRefPtr<CefTestServerHandler> handler);
+
+  ///
+  /// Stop the server and shut down the dedicated server thread. This method
+  /// must be called on the same thread as CreateAndStart. It will block until
+  /// the dedicated server thread has shut down.
+  ///
+  /*--cef()--*/
+  virtual void Stop() = 0;
+
+  ///
+  /// Returns the server origin including the port number (e.g.
+  /// "[http|https]://127.0.0.1:<port>".
+  ///
+  /*--cef()--*/
+  virtual CefString GetOrigin() = 0;
+};
+
+///
+/// Implement this interface to handle test server requests. A new thread will
+/// be created for each CefTestServer::CreateAndStart call (the "dedicated
+/// server thread"), and the methods of this class will be called on that
+/// thread. See related documentation on CefTestServer::CreateAndStart.
+///
+/*--cef(source=client)--*/
+class CefTestServerHandler : public virtual CefBaseRefCounted {
+ public:
+  ///
+  /// Called when |server| receives a request. To handle the request return true
+  /// and use |connection| to send the response either synchronously or
+  /// asynchronously. Otherwise, return false if the request is unhandled. When
+  /// returning false do not call any |connection| methods.
+  ///
+  /*--cef()--*/
+  virtual bool OnTestServerRequest(
+      CefRefPtr<CefTestServer> server,
+      CefRefPtr<CefRequest> request,
+      CefRefPtr<CefTestServerConnection> connection) = 0;
+};
+
+///
+/// Class representing a test server connection. The methods of this class are
+/// safe to call from any thread in the brower process unless otherwise
+/// indicated.
+///
+/*--cef(source=library)--*/
+class CefTestServerConnection : public CefBaseRefCounted {
+ public:
+  typedef std::multimap<CefString, CefString> HeaderMap;
+
+  ///
+  /// Send an HTTP 200 "OK" response. |content_type| is the response content
+  /// type (e.g. "text/html"). |data| is the response content and |data_size| is
+  /// the size of |data| in bytes. The contents of |data| will be copied. The
+  /// connection will be closed automatically after the response is sent.
+  ///
+  /*--cef()--*/
+  virtual void SendHttp200Response(const CefString& content_type,
+                                   const void* data,
+                                   size_t data_size) = 0;
+
+  ///
+  /// Send an HTTP 404 "Not Found" response. The connection will be closed
+  /// automatically after the response is sent.
+  ///
+  /*--cef()--*/
+  virtual void SendHttp404Response() = 0;
+
+  ///
+  /// Send an HTTP 500 "Internal Server Error" response. |error_message| is the
+  /// associated error message. The connection will be closed automatically
+  /// after the response is sent.
+  ///
+  /*--cef()--*/
+  virtual void SendHttp500Response(const CefString& error_message) = 0;
+
+  ///
+  /// Send a custom HTTP response. |response_code| is the HTTP response code
+  /// sent in the status line (e.g. 200). |content_type| is the response content
+  /// type (e.g. "text/html"). |data| is the response content and |data_size| is
+  /// the size of |data| in bytes. The contents of |data| will be copied.
+  /// |extra_headers| is an optional map of additional header key/value pairs.
+  /// The connection will be closed automatically after the response is sent.
+  ///
+  /*--cef(optional_param=extra_headers)--*/
+  virtual void SendHttpResponse(int response_code,
+                                const CefString& content_type,
+                                const void* data,
+                                size_t data_size,
+                                const HeaderMap& extra_headers) = 0;
+};
+
+#endif  // CEF_INCLUDE_TEST_CEF_TEST_SERVER_H_
diff --git a/src/include/test/cef_translator_test.h b/src/include/test/cef_translator_test.h
index 590b5a2..8ac4934 100644
--- a/src/include/test/cef_translator_test.h
+++ b/src/include/test/cef_translator_test.h
@@ -81,13 +81,13 @@
 #define TEST_Y_VAL2 300
 
 ///
-// Class for testing all of the possible data transfer types.
+/// Class for testing all of the possible data transfer types.
 ///
 /*--cef(source=library)--*/
 class CefTranslatorTest : public CefBaseRefCounted {
  public:
   ///
-  // Create the test object.
+  /// Create the test object.
   ///
   /*--cef()--*/
   static CefRefPtr<CefTranslatorTest> Create();
@@ -95,73 +95,73 @@
   // PRIMITIVE VALUES
 
   ///
-  // Return a void value.
+  /// Return a void value.
   ///
   /*--cef()--*/
   virtual void GetVoid() = 0;
 
   ///
-  // Return a bool value.
+  /// Return a bool value.
   ///
   /*--cef()--*/
   virtual bool GetBool() = 0;
 
   ///
-  // Return an int value.
+  /// Return an int value.
   ///
   /*--cef()--*/
   virtual int GetInt() = 0;
 
   ///
-  // Return a double value.
+  /// Return a double value.
   ///
   /*--cef()--*/
   virtual double GetDouble() = 0;
 
   ///
-  // Return a long value.
+  /// Return a long value.
   ///
   /*--cef()--*/
   virtual long GetLong() = 0;
 
   ///
-  // Return a size_t value.
+  /// Return a size_t value.
   ///
   /*--cef()--*/
   virtual size_t GetSizet() = 0;
 
   ///
-  // Set a void value.
+  /// Set a void value.
   ///
   /*--cef()--*/
   virtual bool SetVoid() = 0;
 
   ///
-  // Set a bool value.
+  /// Set a bool value.
   ///
   /*--cef()--*/
   virtual bool SetBool(bool val) = 0;
 
   ///
-  // Set an int value.
+  /// Set an int value.
   ///
   /*--cef()--*/
   virtual bool SetInt(int val) = 0;
 
   ///
-  // Set a double value.
+  /// Set a double value.
   ///
   /*--cef()--*/
   virtual bool SetDouble(double val) = 0;
 
   ///
-  // Set a long value.
+  /// Set a long value.
   ///
   /*--cef()--*/
   virtual bool SetLong(long val) = 0;
 
   ///
-  // Set a size_t value.
+  /// Set a size_t value.
   ///
   /*--cef()--*/
   virtual bool SetSizet(size_t val) = 0;
@@ -172,19 +172,19 @@
   typedef std::vector<int> IntList;
 
   ///
-  // Set a int list value.
+  /// Set a int list value.
   ///
   /*--cef()--*/
   virtual bool SetIntList(const std::vector<int>& val) = 0;
 
   ///
-  // Return an int list value by out-param.
+  /// Return an int list value by out-param.
   ///
   /*--cef(count_func=val:GetIntListSize)--*/
   virtual bool GetIntListByRef(IntList& val) = 0;
 
   ///
-  // Return the number of points that will be output above.
+  /// Return the number of points that will be output above.
   ///
   /*--cef()--*/
   virtual size_t GetIntListSize() = 0;
@@ -192,19 +192,19 @@
   // STRING VALUES
 
   ///
-  // Return a string value.
+  /// Return a string value.
   ///
   /*--cef()--*/
   virtual CefString GetString() = 0;
 
   ///
-  // Set a string value.
+  /// Set a string value.
   ///
   /*--cef()--*/
   virtual bool SetString(const CefString& val) = 0;
 
   ///
-  // Return a string value by out-param.
+  /// Return a string value by out-param.
   ///
   /*--cef()--*/
   virtual void GetStringByRef(CefString& val) = 0;
@@ -215,13 +215,13 @@
   typedef std::vector<CefString> StringList;
 
   ///
-  // Set a string list value.
+  /// Set a string list value.
   ///
   /*--cef()--*/
   virtual bool SetStringList(const std::vector<CefString>& val) = 0;
 
   ///
-  // Return a string list value by out-param.
+  /// Return a string list value by out-param.
   ///
   /*--cef()--*/
   virtual bool GetStringListByRef(StringList& val) = 0;
@@ -232,13 +232,13 @@
   typedef std::map<CefString, CefString> StringMap;
 
   ///
-  // Set a string map value.
+  /// Set a string map value.
   ///
   /*--cef()--*/
   virtual bool SetStringMap(const StringMap& val) = 0;
 
   ///
-  // Return a string map value by out-param.
+  /// Return a string map value by out-param.
   ///
   /*--cef()--*/
   virtual bool GetStringMapByRef(std::map<CefString, CefString>& val) = 0;
@@ -249,14 +249,14 @@
   typedef std::multimap<CefString, CefString> StringMultimap;
 
   ///
-  // Set a string multimap value.
+  /// Set a string multimap value.
   ///
   /*--cef()--*/
   virtual bool SetStringMultimap(
       const std::multimap<CefString, CefString>& val) = 0;
 
   ///
-  // Return a string multimap value by out-param.
+  /// Return a string multimap value by out-param.
   ///
   /*--cef()--*/
   virtual bool GetStringMultimapByRef(StringMultimap& val) = 0;
@@ -264,19 +264,19 @@
   // STRUCT VALUES
 
   ///
-  // Return a point value.
+  /// Return a point value.
   ///
   /*--cef()--*/
   virtual CefPoint GetPoint() = 0;
 
   ///
-  // Set a point value.
+  /// Set a point value.
   ///
   /*--cef()--*/
   virtual bool SetPoint(const CefPoint& val) = 0;
 
   ///
-  // Return a point value by out-param.
+  /// Return a point value by out-param.
   ///
   /*--cef()--*/
   virtual void GetPointByRef(CefPoint& val) = 0;
@@ -287,19 +287,19 @@
   typedef std::vector<CefPoint> PointList;
 
   ///
-  // Set a point list vlaue.
+  /// Set a point list vlaue.
   ///
   /*--cef()--*/
   virtual bool SetPointList(const std::vector<CefPoint>& val) = 0;
 
   ///
-  // Return a point list value by out-param.
+  /// Return a point list value by out-param.
   ///
   /*--cef(count_func=val:GetPointListSize)--*/
   virtual bool GetPointListByRef(PointList& val) = 0;
 
   ///
-  // Return the number of points that will be output above.
+  /// Return the number of points that will be output above.
   ///
   /*--cef()--*/
   virtual size_t GetPointListSize() = 0;
@@ -307,41 +307,41 @@
   // LIBRARY-SIDE REFPTR VALUES
 
   ///
-  // Return an new library-side object.
+  /// Return an new library-side object.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefTranslatorTestRefPtrLibrary> GetRefPtrLibrary(
       int val) = 0;
 
   ///
-  // Set an object. Returns the value from
-  // CefTranslatorTestRefPtrLibrary::GetValue().
-  // This tests input and execution of a library-side object type.
+  /// Set an object. Returns the value from
+  /// CefTranslatorTestRefPtrLibrary::GetValue().
+  /// This tests input and execution of a library-side object type.
   ///
   /*--cef()--*/
   virtual int SetRefPtrLibrary(
       CefRefPtr<CefTranslatorTestRefPtrLibrary> val) = 0;
 
   ///
-  // Set an object. Returns the object passed in. This tests input and output
-  // of a library-side object type.
+  /// Set an object. Returns the object passed in. This tests input and output
+  /// of a library-side object type.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefTranslatorTestRefPtrLibrary> SetRefPtrLibraryAndReturn(
       CefRefPtr<CefTranslatorTestRefPtrLibrary> val) = 0;
 
   ///
-  // Set a child object. Returns the value from
-  // CefTranslatorTestRefPtrLibrary::GetValue(). This tests input of a library-
-  // side child object type and execution as the parent type.
+  /// Set a child object. Returns the value from
+  /// CefTranslatorTestRefPtrLibrary::GetValue(). This tests input of a library-
+  /// side child object type and execution as the parent type.
   ///
   /*--cef()--*/
   virtual int SetChildRefPtrLibrary(
       CefRefPtr<CefTranslatorTestRefPtrLibraryChild> val) = 0;
 
   ///
-  // Set a child object. Returns the object as the parent type. This tests input
-  // of a library-side child object type and return as the parent type.
+  /// Set a child object. Returns the object as the parent type. This tests
+  /// input of a library-side child object type and return as the parent type.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefTranslatorTestRefPtrLibrary>
@@ -355,7 +355,7 @@
       RefPtrLibraryList;
 
   ///
-  // Set an object list vlaue.
+  /// Set an object list vlaue.
   ///
   /*--cef()--*/
   virtual bool SetRefPtrLibraryList(
@@ -364,7 +364,7 @@
       int val2) = 0;
 
   ///
-  // Return an object list value by out-param.
+  /// Return an object list value by out-param.
   ///
   /*--cef(count_func=val:GetRefPtrLibraryListSize)--*/
   virtual bool GetRefPtrLibraryListByRef(RefPtrLibraryList& val,
@@ -372,7 +372,7 @@
                                          int val2) = 0;
 
   ///
-  // Return the number of object that will be output above.
+  /// Return the number of object that will be output above.
   ///
   /*--cef()--*/
   virtual size_t GetRefPtrLibraryListSize() = 0;
@@ -380,33 +380,33 @@
   // CLIENT-SIDE REFPTR VALUES
 
   ///
-  // Set an object. Returns the value from
-  // CefTranslatorTestRefPtrClient::GetValue().
-  // This tests input and execution of a client-side object type.
+  /// Set an object. Returns the value from
+  /// CefTranslatorTestRefPtrClient::GetValue().
+  /// This tests input and execution of a client-side object type.
   ///
   /*--cef()--*/
   virtual int SetRefPtrClient(CefRefPtr<CefTranslatorTestRefPtrClient> val) = 0;
 
   ///
-  // Set an object. Returns the handler passed in. This tests input and output
-  // of a client-side object type.
+  /// Set an object. Returns the handler passed in. This tests input and output
+  /// of a client-side object type.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefTranslatorTestRefPtrClient> SetRefPtrClientAndReturn(
       CefRefPtr<CefTranslatorTestRefPtrClient> val) = 0;
 
   ///
-  // Set a child object. Returns the value from
-  // CefTranslatorTestRefPtrClient::GetValue(). This tests input of a client-
-  // side child object type and execution as the parent type.
+  /// Set a child object. Returns the value from
+  /// CefTranslatorTestRefPtrClient::GetValue(). This tests input of a client-
+  /// side child object type and execution as the parent type.
   ///
   /*--cef()--*/
   virtual int SetChildRefPtrClient(
       CefRefPtr<CefTranslatorTestRefPtrClientChild> val) = 0;
 
   ///
-  // Set a child object. Returns the object as the parent type. This tests
-  // input of a client-side child object type and return as the parent type.
+  /// Set a child object. Returns the object as the parent type. This tests
+  /// input of a client-side child object type and return as the parent type.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefTranslatorTestRefPtrClient>
@@ -420,7 +420,7 @@
       RefPtrClientList;
 
   ///
-  // Set an object list vlaue.
+  /// Set an object list vlaue.
   ///
   /*--cef()--*/
   virtual bool SetRefPtrClientList(
@@ -429,7 +429,7 @@
       int val2) = 0;
 
   ///
-  // Return an object list value by out-param.
+  /// Return an object list value by out-param.
   ///
   /*--cef(count_func=val:GetRefPtrLibraryListSize)--*/
   virtual bool GetRefPtrClientListByRef(
@@ -438,7 +438,7 @@
       CefRefPtr<CefTranslatorTestRefPtrClient> val2) = 0;
 
   ///
-  // Return the number of object that will be output above.
+  /// Return the number of object that will be output above.
   ///
   /*--cef()--*/
   virtual size_t GetRefPtrClientListSize() = 0;
@@ -446,41 +446,41 @@
   // LIBRARY-SIDE OWNPTR VALUES
 
   ///
-  // Return an new library-side object.
+  /// Return an new library-side object.
   ///
   /*--cef()--*/
   virtual CefOwnPtr<CefTranslatorTestScopedLibrary> GetOwnPtrLibrary(
       int val) = 0;
 
   ///
-  // Set an object. Returns the value from
-  // CefTranslatorTestScopedLibrary::GetValue().
-  // This tests input and execution of a library-side object type.
+  /// Set an object. Returns the value from
+  /// CefTranslatorTestScopedLibrary::GetValue().
+  /// This tests input and execution of a library-side object type.
   ///
   /*--cef()--*/
   virtual int SetOwnPtrLibrary(
       CefOwnPtr<CefTranslatorTestScopedLibrary> val) = 0;
 
   ///
-  // Set an object. Returns the object passed in. This tests input and output
-  // of a library-side object type.
+  /// Set an object. Returns the object passed in. This tests input and output
+  /// of a library-side object type.
   ///
   /*--cef()--*/
   virtual CefOwnPtr<CefTranslatorTestScopedLibrary> SetOwnPtrLibraryAndReturn(
       CefOwnPtr<CefTranslatorTestScopedLibrary> val) = 0;
 
   ///
-  // Set a child object. Returns the value from
-  // CefTranslatorTestScopedLibrary::GetValue(). This tests input of a library-
-  // side child object type and execution as the parent type.
+  /// Set a child object. Returns the value from
+  /// CefTranslatorTestScopedLibrary::GetValue(). This tests input of a library-
+  /// side child object type and execution as the parent type.
   ///
   /*--cef()--*/
   virtual int SetChildOwnPtrLibrary(
       CefOwnPtr<CefTranslatorTestScopedLibraryChild> val) = 0;
 
   ///
-  // Set a child object. Returns the object as the parent type. This tests input
-  // of a library-side child object type and return as the parent type.
+  /// Set a child object. Returns the object as the parent type. This tests
+  /// input of a library-side child object type and return as the parent type.
   ///
   /*--cef()--*/
   virtual CefOwnPtr<CefTranslatorTestScopedLibrary>
@@ -490,33 +490,33 @@
   // CLIENT-SIDE OWNPTR VALUES
 
   ///
-  // Set an object. Returns the value from
-  // CefTranslatorTestScopedClient::GetValue().
-  // This tests input and execution of a client-side object type.
+  /// Set an object. Returns the value from
+  /// CefTranslatorTestScopedClient::GetValue().
+  /// This tests input and execution of a client-side object type.
   ///
   /*--cef()--*/
   virtual int SetOwnPtrClient(CefOwnPtr<CefTranslatorTestScopedClient> val) = 0;
 
   ///
-  // Set an object. Returns the handler passed in. This tests input and output
-  // of a client-side object type.
+  /// Set an object. Returns the handler passed in. This tests input and output
+  /// of a client-side object type.
   ///
   /*--cef()--*/
   virtual CefOwnPtr<CefTranslatorTestScopedClient> SetOwnPtrClientAndReturn(
       CefOwnPtr<CefTranslatorTestScopedClient> val) = 0;
 
   ///
-  // Set a child object. Returns the value from
-  // CefTranslatorTestScopedClient::GetValue(). This tests input of a client-
-  // side child object type and execution as the parent type.
+  /// Set a child object. Returns the value from
+  /// CefTranslatorTestScopedClient::GetValue(). This tests input of a client-
+  /// side child object type and execution as the parent type.
   ///
   /*--cef()--*/
   virtual int SetChildOwnPtrClient(
       CefOwnPtr<CefTranslatorTestScopedClientChild> val) = 0;
 
   ///
-  // Set a child object. Returns the object as the parent type. This tests
-  // input of a client-side child object type and return as the parent type.
+  /// Set a child object. Returns the object as the parent type. This tests
+  /// input of a client-side child object type and return as the parent type.
   ///
   /*--cef()--*/
   virtual CefOwnPtr<CefTranslatorTestScopedClient>
@@ -526,18 +526,18 @@
   // LIBRARY-SIDE RAWPTR VALUES
 
   ///
-  // Set an object. Returns the value from
-  // CefTranslatorTestScopedLibrary::GetValue().
-  // This tests input and execution of a library-side object type.
+  /// Set an object. Returns the value from
+  /// CefTranslatorTestScopedLibrary::GetValue().
+  /// This tests input and execution of a library-side object type.
   ///
   /*--cef()--*/
   virtual int SetRawPtrLibrary(
       CefRawPtr<CefTranslatorTestScopedLibrary> val) = 0;
 
   ///
-  // Set a child object. Returns the value from
-  // CefTranslatorTestScopedLibrary::GetValue(). This tests input of a library-
-  // side child object type and execution as the parent type.
+  /// Set a child object. Returns the value from
+  /// CefTranslatorTestScopedLibrary::GetValue(). This tests input of a library-
+  /// side child object type and execution as the parent type.
   ///
   /*--cef()--*/
   virtual int SetChildRawPtrLibrary(
@@ -550,7 +550,7 @@
       RawPtrLibraryList;
 
   ///
-  // Set an object list vlaue.
+  /// Set an object list vlaue.
   ///
   /*--cef()--*/
   virtual bool SetRawPtrLibraryList(
@@ -561,17 +561,17 @@
   // CLIENT-SIDE RAWPTR VALUES
 
   ///
-  // Set an object. Returns the value from
-  // CefTranslatorTestScopedClient::GetValue().
-  // This tests input and execution of a client-side object type.
+  /// Set an object. Returns the value from
+  /// CefTranslatorTestScopedClient::GetValue().
+  /// This tests input and execution of a client-side object type.
   ///
   /*--cef()--*/
   virtual int SetRawPtrClient(CefRawPtr<CefTranslatorTestScopedClient> val) = 0;
 
   ///
-  // Set a child object. Returns the value from
-  // CefTranslatorTestScopedClient::GetValue(). This tests input of a client-
-  // side child object type and execution as the parent type.
+  /// Set a child object. Returns the value from
+  /// CefTranslatorTestScopedClient::GetValue(). This tests input of a client-
+  /// side child object type and execution as the parent type.
   ///
   /*--cef()--*/
   virtual int SetChildRawPtrClient(
@@ -584,7 +584,7 @@
       RawPtrClientList;
 
   ///
-  // Set an object list vlaue.
+  /// Set an object list vlaue.
   ///
   /*--cef()--*/
   virtual bool SetRawPtrClientList(
@@ -594,212 +594,212 @@
 };
 
 ///
-// Library-side test object for RefPtr.
+/// Library-side test object for RefPtr.
 ///
 /*--cef(source=library)--*/
 class CefTranslatorTestRefPtrLibrary : public CefBaseRefCounted {
  public:
   ///
-  // Create the test object.
+  /// Create the test object.
   ///
   /*--cef()--*/
   static CefRefPtr<CefTranslatorTestRefPtrLibrary> Create(int value);
 
   ///
-  // Return a value.
+  /// Return a value.
   ///
   /*--cef()--*/
   virtual int GetValue() = 0;
 
   ///
-  // Set a value.
+  /// Set a value.
   ///
   /*--cef()--*/
   virtual void SetValue(int value) = 0;
 };
 
 ///
-// Library-side child test object for RefPtr.
+/// Library-side child test object for RefPtr.
 ///
 /*--cef(source=library)--*/
 class CefTranslatorTestRefPtrLibraryChild
     : public CefTranslatorTestRefPtrLibrary {
  public:
   ///
-  // Create the test object.
+  /// Create the test object.
   ///
   /*--cef()--*/
   static CefRefPtr<CefTranslatorTestRefPtrLibraryChild> Create(int value,
                                                                int other_value);
 
   ///
-  // Return a value.
+  /// Return a value.
   ///
   /*--cef()--*/
   virtual int GetOtherValue() = 0;
 
   ///
-  // Set a value.
+  /// Set a value.
   ///
   /*--cef()--*/
   virtual void SetOtherValue(int value) = 0;
 };
 
 ///
-// Another library-side child test object for RefPtr.
+/// Another library-side child test object for RefPtr.
 ///
 /*--cef(source=library)--*/
 class CefTranslatorTestRefPtrLibraryChildChild
     : public CefTranslatorTestRefPtrLibraryChild {
  public:
   ///
-  // Create the test object.
+  /// Create the test object.
   ///
   /*--cef()--*/
   static CefRefPtr<CefTranslatorTestRefPtrLibraryChildChild>
   Create(int value, int other_value, int other_other_value);
 
   ///
-  // Return a value.
+  /// Return a value.
   ///
   /*--cef()--*/
   virtual int GetOtherOtherValue() = 0;
 
   ///
-  // Set a value.
+  /// Set a value.
   ///
   /*--cef()--*/
   virtual void SetOtherOtherValue(int value) = 0;
 };
 
 ///
-// Client-side test object for RefPtr.
+/// Client-side test object for RefPtr.
 ///
 /*--cef(source=client)--*/
 class CefTranslatorTestRefPtrClient : public virtual CefBaseRefCounted {
  public:
   ///
-  // Return a value.
+  /// Return a value.
   ///
   /*--cef()--*/
   virtual int GetValue() = 0;
 };
 
 ///
-// Client-side child test object for RefPtr.
+/// Client-side child test object for RefPtr.
 ///
 /*--cef(source=client)--*/
 class CefTranslatorTestRefPtrClientChild
     : public CefTranslatorTestRefPtrClient {
  public:
   ///
-  // Return a value.
+  /// Return a value.
   ///
   /*--cef()--*/
   virtual int GetOtherValue() = 0;
 };
 
 ///
-// Library-side test object for OwnPtr/RawPtr.
+/// Library-side test object for OwnPtr/RawPtr.
 ///
 /*--cef(source=library)--*/
 class CefTranslatorTestScopedLibrary : public CefBaseScoped {
  public:
   ///
-  // Create the test object.
+  /// Create the test object.
   ///
   /*--cef()--*/
   static CefOwnPtr<CefTranslatorTestScopedLibrary> Create(int value);
 
   ///
-  // Return a value.
+  /// Return a value.
   ///
   /*--cef()--*/
   virtual int GetValue() = 0;
 
   ///
-  // Set a value.
+  /// Set a value.
   ///
   /*--cef()--*/
   virtual void SetValue(int value) = 0;
 };
 
 ///
-// Library-side child test object for OwnPtr/RawPtr.
+/// Library-side child test object for OwnPtr/RawPtr.
 ///
 /*--cef(source=library)--*/
 class CefTranslatorTestScopedLibraryChild
     : public CefTranslatorTestScopedLibrary {
  public:
   ///
-  // Create the test object.
+  /// Create the test object.
   ///
   /*--cef()--*/
   static CefOwnPtr<CefTranslatorTestScopedLibraryChild> Create(int value,
                                                                int other_value);
 
   ///
-  // Return a value.
+  /// Return a value.
   ///
   /*--cef()--*/
   virtual int GetOtherValue() = 0;
 
   ///
-  // Set a value.
+  /// Set a value.
   ///
   /*--cef()--*/
   virtual void SetOtherValue(int value) = 0;
 };
 
 ///
-// Another library-side child test object for OwnPtr/RawPtr.
+/// Another library-side child test object for OwnPtr/RawPtr.
 ///
 /*--cef(source=library)--*/
 class CefTranslatorTestScopedLibraryChildChild
     : public CefTranslatorTestScopedLibraryChild {
  public:
   ///
-  // Create the test object.
+  /// Create the test object.
   ///
   /*--cef()--*/
   static CefOwnPtr<CefTranslatorTestScopedLibraryChildChild>
   Create(int value, int other_value, int other_other_value);
 
   ///
-  // Return a value.
+  /// Return a value.
   ///
   /*--cef()--*/
   virtual int GetOtherOtherValue() = 0;
 
   ///
-  // Set a value.
+  /// Set a value.
   ///
   /*--cef()--*/
   virtual void SetOtherOtherValue(int value) = 0;
 };
 
 ///
-// Client-side test object for OwnPtr/RawPtr.
+/// Client-side test object for OwnPtr/RawPtr.
 ///
 /*--cef(source=client)--*/
 class CefTranslatorTestScopedClient : public virtual CefBaseScoped {
  public:
   ///
-  // Return a value.
+  /// Return a value.
   ///
   /*--cef()--*/
   virtual int GetValue() = 0;
 };
 
 ///
-// Client-side child test object for OwnPtr/RawPtr.
+/// Client-side child test object for OwnPtr/RawPtr.
 ///
 /*--cef(source=client)--*/
 class CefTranslatorTestScopedClientChild
     : public CefTranslatorTestScopedClient {
  public:
   ///
-  // Return a value.
+  /// Return a value.
   ///
   /*--cef()--*/
   virtual int GetOtherValue() = 0;
diff --git a/src/include/views/cef_box_layout.h b/src/include/views/cef_box_layout.h
index 7498919..14bb8d2 100644
--- a/src/include/views/cef_box_layout.h
+++ b/src/include/views/cef_box_layout.h
@@ -43,29 +43,29 @@
 class CefView;
 
 ///
-// A Layout manager that arranges child views vertically or horizontally in a
-// side-by-side fashion with spacing around and between the child views. The
-// child views are always sized according to their preferred size. If the
-// host's bounds provide insufficient space, child views will be clamped.
-// Excess space will not be distributed. Methods must be called on the browser
-// process UI thread unless otherwise indicated.
+/// A Layout manager that arranges child views vertically or horizontally in a
+/// side-by-side fashion with spacing around and between the child views. The
+/// child views are always sized according to their preferred size. If the
+/// host's bounds provide insufficient space, child views will be clamped.
+/// Excess space will not be distributed. Methods must be called on the browser
+/// process UI thread unless otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefBoxLayout : public CefLayout {
  public:
   ///
-  // Set the flex weight for the given |view|. Using the preferred size as
-  // the basis, free space along the main axis is distributed to views in the
-  // ratio of their flex weights. Similarly, if the views will overflow the
-  // parent, space is subtracted in these ratios. A flex of 0 means this view is
-  // not resized. Flex values must not be negative.
+  /// Set the flex weight for the given |view|. Using the preferred size as
+  /// the basis, free space along the main axis is distributed to views in the
+  /// ratio of their flex weights. Similarly, if the views will overflow the
+  /// parent, space is subtracted in these ratios. A flex of 0 means this view
+  /// is not resized. Flex values must not be negative.
   ///
   /*--cef()--*/
   virtual void SetFlexForView(CefRefPtr<CefView> view, int flex) = 0;
 
   ///
-  // Clears the flex for the given |view|, causing it to use the default flex
-  // specified via CefBoxLayoutSettings.default_flex.
+  /// Clears the flex for the given |view|, causing it to use the default flex
+  /// specified via CefBoxLayoutSettings.default_flex.
   ///
   /*--cef()--*/
   virtual void ClearFlexForView(CefRefPtr<CefView> view) = 0;
diff --git a/src/include/views/cef_browser_view.h b/src/include/views/cef_browser_view.h
index a310eb0..dc7efc2 100644
--- a/src/include/views/cef_browser_view.h
+++ b/src/include/views/cef_browser_view.h
@@ -43,18 +43,18 @@
 #include "include/views/cef_view.h"
 
 ///
-// A View hosting a CefBrowser instance. Methods must be called on the browser
-// process UI thread unless otherwise indicated.
+/// A View hosting a CefBrowser instance. Methods must be called on the browser
+/// process UI thread unless otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefBrowserView : public CefView {
  public:
   ///
-  // Create a new BrowserView. The underlying CefBrowser will not be created
-  // until this view is added to the views hierarchy. The optional |extra_info|
-  // parameter provides an opportunity to specify extra information specific
-  // to the created browser that will be passed to
-  // CefRenderProcessHandler::OnBrowserCreated() in the render process.
+  /// Create a new BrowserView. The underlying CefBrowser will not be created
+  /// until this view is added to the views hierarchy. The optional |extra_info|
+  /// parameter provides an opportunity to specify extra information specific
+  /// to the created browser that will be passed to
+  /// CefRenderProcessHandler::OnBrowserCreated() in the render process.
   ///
   /*--cef(optional_param=client,optional_param=url,
           optional_param=request_context,optional_param=delegate,
@@ -68,26 +68,42 @@
       CefRefPtr<CefBrowserViewDelegate> delegate);
 
   ///
-  // Returns the BrowserView associated with |browser|.
+  /// Returns the BrowserView associated with |browser|.
   ///
   /*--cef()--*/
   static CefRefPtr<CefBrowserView> GetForBrowser(CefRefPtr<CefBrowser> browser);
 
   ///
-  // Returns the CefBrowser hosted by this BrowserView. Will return NULL if the
-  // browser has not yet been created or has already been destroyed.
+  /// Returns the CefBrowser hosted by this BrowserView. Will return NULL if the
+  /// browser has not yet been created or has already been destroyed.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBrowser> GetBrowser() = 0;
 
   ///
-  // Sets whether accelerators registered with CefWindow::SetAccelerator are
-  // triggered before or after the event is sent to the CefBrowser. If
-  // |prefer_accelerators| is true then the matching accelerator will be
-  // triggered immediately and the event will not be sent to the CefBrowser. If
-  // |prefer_accelerators| is false then the matching accelerator will only be
-  // triggered if the event is not handled by web content or by
-  // CefKeyboardHandler. The default value is false.
+  /// Returns the Chrome toolbar associated with this BrowserView. Only
+  /// supported when using the Chrome runtime. The CefBrowserViewDelegate::
+  /// GetChromeToolbarType() method must return a value other than
+  /// CEF_CTT_NONE and the toolbar will not be available until after this
+  /// BrowserView is added to a CefWindow and CefViewDelegate::OnWindowChanged()
+  /// has been called.
+  ///
+  /*--cef()--*/
+  virtual CefRefPtr<CefView> GetChromeToolbar() = 0;
+
+  ///
+  /// Sets whether normal priority accelerators are first forwarded to the web
+  /// content (`keydown` event handler) or CefKeyboardHandler. Normal priority
+  /// accelerators can be registered via CefWindow::SetAccelerator (with
+  /// |high_priority|=false) or internally for standard accelerators supported
+  /// by the Chrome runtime. If |prefer_accelerators| is true then the matching
+  /// accelerator will be triggered immediately (calling
+  /// CefWindowDelegate::OnAccelerator or CefCommandHandler::OnChromeCommand
+  /// respectively) and the event will not be forwarded to the web content or
+  /// CefKeyboardHandler first. If |prefer_accelerators| is false then the
+  /// matching accelerator will only be triggered if the event is not handled by
+  /// web content (`keydown` event handler that calls `event.preventDefault()`)
+  /// or by CefKeyboardHandler. The default value is false.
   ///
   /*--cef()--*/
   virtual void SetPreferAccelerators(bool prefer_accelerators) = 0;
diff --git a/src/include/views/cef_browser_view_delegate.h b/src/include/views/cef_browser_view_delegate.h
index 93eea91..e87a1f0 100644
--- a/src/include/views/cef_browser_view_delegate.h
+++ b/src/include/views/cef_browser_view_delegate.h
@@ -45,41 +45,43 @@
 class CefBrowserView;
 
 ///
-// Implement this interface to handle BrowserView events. The methods of this
-// class will be called on the browser process UI thread unless otherwise
-// indicated.
+/// Implement this interface to handle BrowserView events. The methods of this
+/// class will be called on the browser process UI thread unless otherwise
+/// indicated.
 ///
 /*--cef(source=client)--*/
 class CefBrowserViewDelegate : public CefViewDelegate {
  public:
+  typedef cef_chrome_toolbar_type_t ChromeToolbarType;
+
   ///
-  // Called when |browser| associated with |browser_view| is created. This
-  // method will be called after CefLifeSpanHandler::OnAfterCreated() is called
-  // for |browser| and before OnPopupBrowserViewCreated() is called for
-  // |browser|'s parent delegate if |browser| is a popup.
+  /// Called when |browser| associated with |browser_view| is created. This
+  /// method will be called after CefLifeSpanHandler::OnAfterCreated() is called
+  /// for |browser| and before OnPopupBrowserViewCreated() is called for
+  /// |browser|'s parent delegate if |browser| is a popup.
   ///
   /*--cef()--*/
   virtual void OnBrowserCreated(CefRefPtr<CefBrowserView> browser_view,
                                 CefRefPtr<CefBrowser> browser) {}
 
   ///
-  // Called when |browser| associated with |browser_view| is destroyed. Release
-  // all references to |browser| and do not attempt to execute any methods on
-  // |browser| after this callback returns. This method will be called before
-  // CefLifeSpanHandler::OnBeforeClose() is called for |browser|.
+  /// Called when |browser| associated with |browser_view| is destroyed. Release
+  /// all references to |browser| and do not attempt to execute any methods on
+  /// |browser| after this callback returns. This method will be called before
+  /// CefLifeSpanHandler::OnBeforeClose() is called for |browser|.
   ///
   /*--cef()--*/
   virtual void OnBrowserDestroyed(CefRefPtr<CefBrowserView> browser_view,
                                   CefRefPtr<CefBrowser> browser) {}
 
   ///
-  // Called before a new popup BrowserView is created. The popup originated
-  // from |browser_view|. |settings| and |client| are the values returned from
-  // CefLifeSpanHandler::OnBeforePopup(). |is_devtools| will be true if the
-  // popup will be a DevTools browser. Return the delegate that will be used for
-  // the new popup BrowserView.
+  /// Called before a new popup BrowserView is created. The popup originated
+  /// from |browser_view|. |settings| and |client| are the values returned from
+  /// CefLifeSpanHandler::OnBeforePopup(). |is_devtools| will be true if the
+  /// popup will be a DevTools browser. Return the delegate that will be used
+  /// for the new popup BrowserView.
   ///
-  /*--cef()--*/
+  /*--cef(optional_param=client)--*/
   virtual CefRefPtr<CefBrowserViewDelegate> GetDelegateForPopupBrowserView(
       CefRefPtr<CefBrowserView> browser_view,
       const CefBrowserSettings& settings,
@@ -89,13 +91,13 @@
   }
 
   ///
-  // Called after |popup_browser_view| is created. This method will be called
-  // after CefLifeSpanHandler::OnAfterCreated() and OnBrowserCreated() are
-  // called for the new popup browser. The popup originated from |browser_view|.
-  // |is_devtools| will be true if the popup is a DevTools browser. Optionally
-  // add |popup_browser_view| to the views hierarchy yourself and return true.
-  // Otherwise return false and a default CefWindow will be created for the
-  // popup.
+  /// Called after |popup_browser_view| is created. This method will be called
+  /// after CefLifeSpanHandler::OnAfterCreated() and OnBrowserCreated() are
+  /// called for the new popup browser. The popup originated from
+  /// |browser_view|. |is_devtools| will be true if the popup is a DevTools
+  /// browser. Optionally add |popup_browser_view| to the views hierarchy
+  /// yourself and return true. Otherwise return false and a default CefWindow
+  /// will be created for the popup.
   ///
   /*--cef()--*/
   virtual bool OnPopupBrowserViewCreated(
@@ -104,6 +106,40 @@
       bool is_devtools) {
     return false;
   }
+
+  ///
+  /// Returns the Chrome toolbar type that will be available via
+  /// CefBrowserView::GetChromeToolbar(). See that method for related
+  /// documentation.
+  ///
+  /*--cef(default_retval=CEF_CTT_NONE)--*/
+  virtual ChromeToolbarType GetChromeToolbarType(
+      CefRefPtr<CefBrowserView> browser_view) {
+    return CEF_CTT_NONE;
+  }
+
+  ///
+  /// Return true to create frameless windows for Document picture-in-picture
+  /// popups. Content in frameless windows should specify draggable regions
+  /// using "-webkit-app-region: drag" CSS.
+  ///
+  /*--cef()--*/
+  virtual bool UseFramelessWindowForPictureInPicture(
+      CefRefPtr<CefBrowserView> browser_view) {
+    return false;
+  }
+
+  ///
+  /// Called when |browser_view| receives a gesture command. Return true to
+  /// handle (or disable) a |gesture_command| or false to propagate the gesture
+  /// to the browser for default handling. With the Chrome runtime these
+  /// commands can also be handled via CefCommandHandler::OnChromeCommand.
+  ///
+  /*--cef()--*/
+  virtual bool OnGestureCommand(CefRefPtr<CefBrowserView> browser_view,
+                                cef_gesture_command_t gesture_command) {
+    return false;
+  }
 };
 
 #endif  // CEF_INCLUDE_VIEWS_CEF_BROWSER_VIEW_DELEGATE_H_
diff --git a/src/include/views/cef_button.h b/src/include/views/cef_button.h
index 039446b..944a7bb 100644
--- a/src/include/views/cef_button.h
+++ b/src/include/views/cef_button.h
@@ -43,46 +43,47 @@
 class CefLabelButton;
 
 ///
-// A View representing a button. Depending on the specific type, the button
-// could be implemented by a native control or custom rendered. Methods must be
-// called on the browser process UI thread unless otherwise indicated.
+/// A View representing a button. Depending on the specific type, the button
+/// could be implemented by a native control or custom rendered. Methods must be
+/// called on the browser process UI thread unless otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefButton : public CefView {
  public:
   ///
-  // Returns this Button as a LabelButton or NULL if this is not a LabelButton.
+  /// Returns this Button as a LabelButton or NULL if this is not a LabelButton.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefLabelButton> AsLabelButton() = 0;
 
   ///
-  // Sets the current display state of the Button.
+  /// Sets the current display state of the Button.
   ///
   /*--cef()--*/
   virtual void SetState(cef_button_state_t state) = 0;
 
   ///
-  // Returns the current display state of the Button.
+  /// Returns the current display state of the Button.
   ///
   /*--cef(default_retval=CEF_BUTTON_STATE_NORMAL)--*/
   virtual cef_button_state_t GetState() = 0;
 
   ///
-  // Sets the Button will use an ink drop effect for displaying state changes.
+  /// Sets the Button will use an ink drop effect for displaying state changes.
   ///
   /*--cef()--*/
   virtual void SetInkDropEnabled(bool enabled) = 0;
 
   ///
-  // Sets the tooltip text that will be displayed when the user hovers the mouse
-  // cursor over the Button.
+  /// Sets the tooltip text that will be displayed when the user hovers the
+  /// mouse cursor over the Button.
   ///
   /*--cef()--*/
   virtual void SetTooltipText(const CefString& tooltip_text) = 0;
 
   ///
-  // Sets the accessible name that will be exposed to assistive technology (AT).
+  /// Sets the accessible name that will be exposed to assistive technology
+  /// (AT).
   ///
   /*--cef()--*/
   virtual void SetAccessibleName(const CefString& name) = 0;
diff --git a/src/include/views/cef_button_delegate.h b/src/include/views/cef_button_delegate.h
index 60d8a2f..3d6ee22 100644
--- a/src/include/views/cef_button_delegate.h
+++ b/src/include/views/cef_button_delegate.h
@@ -43,20 +43,20 @@
 class CefButton;
 
 ///
-// Implement this interface to handle Button events. The methods of this class
-// will be called on the browser process UI thread unless otherwise indicated.
+/// Implement this interface to handle Button events. The methods of this class
+/// will be called on the browser process UI thread unless otherwise indicated.
 ///
 /*--cef(source=client)--*/
 class CefButtonDelegate : public CefViewDelegate {
  public:
   ///
-  // Called when |button| is pressed.
+  /// Called when |button| is pressed.
   ///
   /*--cef()--*/
   virtual void OnButtonPressed(CefRefPtr<CefButton> button) = 0;
 
   ///
-  // Called when the state of |button| changes.
+  /// Called when the state of |button| changes.
   ///
   /*--cef()--*/
   virtual void OnButtonStateChanged(CefRefPtr<CefButton> button) {}
diff --git a/src/include/views/cef_display.h b/src/include/views/cef_display.h
index de3e7ab..4010cae 100644
--- a/src/include/views/cef_display.h
+++ b/src/include/views/cef_display.h
@@ -43,35 +43,34 @@
 #include "include/cef_base.h"
 
 ///
-// This class typically, but not always, corresponds to a physical display
-// connected to the system. A fake Display may exist on a headless system, or a
-// Display may correspond to a remote, virtual display. All size and position
-// values are in density independent pixels (DIP) unless otherwise indicated.
-// Methods must be called on the browser process UI thread unless otherwise
-// indicated.
+/// This class typically, but not always, corresponds to a physical display
+/// connected to the system. A fake Display may exist on a headless system, or a
+/// Display may correspond to a remote, virtual display. All size and position
+/// values are in density independent pixel (DIP) coordinates unless otherwise
+/// indicated. Methods must be called on the browser process UI thread unless
+/// otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefDisplay : public CefBaseRefCounted {
  public:
   ///
-  // Returns the primary Display.
+  /// Returns the primary Display.
   ///
   /*--cef()--*/
   static CefRefPtr<CefDisplay> GetPrimaryDisplay();
 
   ///
-  // Returns the Display nearest |point|. Set |input_pixel_coords| to true if
-  // |point| is in pixel coordinates instead of density independent pixels
-  // (DIP).
+  /// Returns the Display nearest |point|. Set |input_pixel_coords| to true if
+  /// |point| is in pixel screen coordinates instead of DIP screen coordinates.
   ///
   /*--cef()--*/
   static CefRefPtr<CefDisplay> GetDisplayNearestPoint(const CefPoint& point,
                                                       bool input_pixel_coords);
 
   ///
-  // Returns the Display that most closely intersects |bounds|.  Set
-  // |input_pixel_coords| to true if |bounds| is in pixel coordinates instead of
-  // density independent pixels (DIP).
+  /// Returns the Display that most closely intersects |bounds|.  Set
+  /// |input_pixel_coords| to true if |bounds| is in pixel screen coordinates
+  /// instead of DIP screen coordinates.
   ///
   /*--cef()--*/
   static CefRefPtr<CefDisplay> GetDisplayMatchingBounds(
@@ -79,63 +78,92 @@
       bool input_pixel_coords);
 
   ///
-  // Returns the total number of Displays. Mirrored displays are excluded; this
-  // method is intended to return the number of distinct, usable displays.
+  /// Returns the total number of Displays. Mirrored displays are excluded; this
+  /// method is intended to return the number of distinct, usable displays.
   ///
   /*--cef()--*/
   static size_t GetDisplayCount();
 
   ///
-  // Returns all Displays. Mirrored displays are excluded; this method is
-  // intended to return distinct, usable displays.
+  /// Returns all Displays. Mirrored displays are excluded; this method is
+  /// intended to return distinct, usable displays.
   ///
   /*--cef(count_func=displays:GetDisplayCount)--*/
   static void GetAllDisplays(std::vector<CefRefPtr<CefDisplay>>& displays);
 
   ///
-  // Returns the unique identifier for this Display.
+  /// Convert |point| from DIP screen coordinates to pixel screen coordinates.
+  /// This method is only used on Windows.
   ///
   /*--cef()--*/
-  virtual int64 GetID() = 0;
+  static CefPoint ConvertScreenPointToPixels(const CefPoint& point);
 
   ///
-  // Returns this Display's device pixel scale factor. This specifies how much
-  // the UI should be scaled when the actual output has more pixels than
-  // standard displays (which is around 100~120dpi). The potential return values
-  // differ by platform.
+  /// Convert |point| from pixel screen coordinates to DIP screen coordinates.
+  /// This method is only used on Windows.
+  ///
+  /*--cef()--*/
+  static CefPoint ConvertScreenPointFromPixels(const CefPoint& point);
+
+  ///
+  /// Convert |rect| from DIP screen coordinates to pixel screen coordinates.
+  /// This method is only used on Windows.
+  ///
+  /*--cef()--*/
+  static CefRect ConvertScreenRectToPixels(const CefRect& rect);
+
+  ///
+  /// Convert |rect| from pixel screen coordinates to DIP screen coordinates.
+  /// This method is only used on Windows.
+  ///
+  /*--cef()--*/
+  static CefRect ConvertScreenRectFromPixels(const CefRect& rect);
+
+  ///
+  /// Returns the unique identifier for this Display.
+  ///
+  /*--cef()--*/
+  virtual int64_t GetID() = 0;
+
+  ///
+  /// Returns this Display's device pixel scale factor. This specifies how much
+  /// the UI should be scaled when the actual output has more pixels than
+  /// standard displays (which is around 100~120dpi). The potential return
+  /// values differ by platform.
   ///
   /*--cef()--*/
   virtual float GetDeviceScaleFactor() = 0;
 
   ///
-  // Convert |point| from density independent pixels (DIP) to pixel coordinates
-  // using this Display's device scale factor.
+  /// Convert |point| from DIP coordinates to pixel coordinates using this
+  /// Display's device scale factor.
   ///
   /*--cef()--*/
   virtual void ConvertPointToPixels(CefPoint& point) = 0;
 
   ///
-  // Convert |point| from pixel coordinates to density independent pixels (DIP)
-  // using this Display's device scale factor.
+  /// Convert |point| from pixel coordinates to DIP coordinates using this
+  /// Display's device scale factor.
   ///
   /*--cef()--*/
   virtual void ConvertPointFromPixels(CefPoint& point) = 0;
 
   ///
-  // Returns this Display's bounds. This is the full size of the display.
+  /// Returns this Display's bounds in DIP screen coordinates. This is the full
+  /// size of the display.
   ///
   /*--cef()--*/
   virtual CefRect GetBounds() = 0;
 
   ///
-  // Returns this Display's work area. This excludes areas of the display that
-  // are occupied for window manager toolbars, etc.
+  /// Returns this Display's work area in DIP screen coordinates. This excludes
+  /// areas of the display that are occupied with window manager toolbars, etc.
   ///
   /*--cef()--*/
   virtual CefRect GetWorkArea() = 0;
 
   ///
-  // Returns this Display's rotation in degrees.
+  /// Returns this Display's rotation in degrees.
   ///
   /*--cef()--*/
   virtual int GetRotation() = 0;
diff --git a/src/include/views/cef_fill_layout.h b/src/include/views/cef_fill_layout.h
index a412f63..eedbc94 100644
--- a/src/include/views/cef_fill_layout.h
+++ b/src/include/views/cef_fill_layout.h
@@ -41,9 +41,9 @@
 #include "include/views/cef_layout.h"
 
 ///
-// A simple Layout that causes the associated Panel's one child to be sized to
-// match the bounds of its parent. Methods must be called on the browser process
-// UI thread unless otherwise indicated.
+/// A simple Layout that causes the associated Panel's one child to be sized to
+/// match the bounds of its parent. Methods must be called on the browser
+/// process UI thread unless otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefFillLayout : public CefLayout {};
diff --git a/src/include/views/cef_label_button.h b/src/include/views/cef_label_button.h
index c2c7fe9..c099d43 100644
--- a/src/include/views/cef_label_button.h
+++ b/src/include/views/cef_label_button.h
@@ -45,16 +45,16 @@
 class CefMenuButton;
 
 ///
-// LabelButton is a button with optional text and/or icon. Methods must be
-// called on the browser process UI thread unless otherwise indicated.
+/// LabelButton is a button with optional text and/or icon. Methods must be
+/// called on the browser process UI thread unless otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefLabelButton : public CefButton {
  public:
   ///
-  // Create a new LabelButton. A |delegate| must be provided to handle the
-  // button click. |text| will be shown on the LabelButton and used as the
-  // default accessible name.
+  /// Create a new LabelButton. A |delegate| must be provided to handle the
+  /// button click. |text| will be shown on the LabelButton and used as the
+  /// default accessible name.
   ///
   /*--cef(optional_param=text)--*/
   static CefRefPtr<CefLabelButton> CreateLabelButton(
@@ -62,84 +62,85 @@
       const CefString& text);
 
   ///
-  // Returns this LabelButton as a MenuButton or NULL if this is not a
-  // MenuButton.
+  /// Returns this LabelButton as a MenuButton or NULL if this is not a
+  /// MenuButton.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefMenuButton> AsMenuButton() = 0;
 
   ///
-  // Sets the text shown on the LabelButton. By default |text| will also be used
-  // as the accessible name.
+  /// Sets the text shown on the LabelButton. By default |text| will also be
+  /// used as the accessible name.
   ///
   /*--cef()--*/
   virtual void SetText(const CefString& text) = 0;
 
   ///
-  // Returns the text shown on the LabelButton.
+  /// Returns the text shown on the LabelButton.
   ///
   /*--cef()--*/
   virtual CefString GetText() = 0;
 
   ///
-  // Sets the image shown for |button_state|. When this Button is drawn if no
-  // image exists for the current state then the image for
-  // CEF_BUTTON_STATE_NORMAL, if any, will be shown.
+  /// Sets the image shown for |button_state|. When this Button is drawn if no
+  /// image exists for the current state then the image for
+  /// CEF_BUTTON_STATE_NORMAL, if any, will be shown.
   ///
   /*--cef(optional_param=image)--*/
   virtual void SetImage(cef_button_state_t button_state,
                         CefRefPtr<CefImage> image) = 0;
 
   ///
-  // Returns the image shown for |button_state|. If no image exists for that
-  // state then the image for CEF_BUTTON_STATE_NORMAL will be returned.
+  /// Returns the image shown for |button_state|. If no image exists for that
+  /// state then the image for CEF_BUTTON_STATE_NORMAL will be returned.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefImage> GetImage(cef_button_state_t button_state) = 0;
 
   ///
-  // Sets the text color shown for the specified button |for_state| to |color|.
+  /// Sets the text color shown for the specified button |for_state| to |color|.
   ///
   /*--cef()--*/
   virtual void SetTextColor(cef_button_state_t for_state,
                             cef_color_t color) = 0;
 
   ///
-  // Sets the text colors shown for the non-disabled states to |color|.
+  /// Sets the text colors shown for the non-disabled states to |color|.
   ///
   /*--cef()--*/
   virtual void SetEnabledTextColors(cef_color_t color) = 0;
 
   ///
-  // Sets the font list. The format is "<FONT_FAMILY_LIST>,[STYLES] <SIZE>",
-  // where:
-  // - FONT_FAMILY_LIST is a comma-separated list of font family names,
-  // - STYLES is an optional space-separated list of style names (case-sensitive
-  //   "Bold" and "Italic" are supported), and
-  // - SIZE is an integer font size in pixels with the suffix "px".
-  //
-  // Here are examples of valid font description strings:
-  // - "Arial, Helvetica, Bold Italic 14px"
-  // - "Arial, 14px"
+  /// Sets the font list. The format is "<FONT_FAMILY_LIST>,[STYLES] <SIZE>",
+  /// where:
+  /// - FONT_FAMILY_LIST is a comma-separated list of font family names,
+  /// - STYLES is an optional space-separated list of style names
+  /// (case-sensitive
+  ///   "Bold" and "Italic" are supported), and
+  /// - SIZE is an integer font size in pixels with the suffix "px".
+  ///
+  /// Here are examples of valid font description strings:
+  /// - "Arial, Helvetica, Bold Italic 14px"
+  /// - "Arial, 14px"
   ///
   /*--cef()--*/
   virtual void SetFontList(const CefString& font_list) = 0;
 
   ///
-  // Sets the horizontal alignment; reversed in RTL. Default is
-  // CEF_HORIZONTAL_ALIGNMENT_CENTER.
+  /// Sets the horizontal alignment; reversed in RTL. Default is
+  /// CEF_HORIZONTAL_ALIGNMENT_CENTER.
   ///
   /*--cef()--*/
   virtual void SetHorizontalAlignment(cef_horizontal_alignment_t alignment) = 0;
 
   ///
-  // Reset the minimum size of this LabelButton to |size|.
+  /// Reset the minimum size of this LabelButton to |size|.
   ///
   /*--cef()--*/
   virtual void SetMinimumSize(const CefSize& size) = 0;
 
   ///
-  // Reset the maximum size of this LabelButton to |size|.
+  /// Reset the maximum size of this LabelButton to |size|.
   ///
   /*--cef()--*/
   virtual void SetMaximumSize(const CefSize& size) = 0;
diff --git a/src/include/views/cef_layout.h b/src/include/views/cef_layout.h
index 454ff01..61687da 100644
--- a/src/include/views/cef_layout.h
+++ b/src/include/views/cef_layout.h
@@ -44,27 +44,27 @@
 class CefFillLayout;
 
 ///
-// A Layout handles the sizing of the children of a Panel according to
-// implementation-specific heuristics. Methods must be called on the browser
-// process UI thread unless otherwise indicated.
+/// A Layout handles the sizing of the children of a Panel according to
+/// implementation-specific heuristics. Methods must be called on the browser
+/// process UI thread unless otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefLayout : public CefBaseRefCounted {
  public:
   ///
-  // Returns this Layout as a BoxLayout or NULL if this is not a BoxLayout.
+  /// Returns this Layout as a BoxLayout or NULL if this is not a BoxLayout.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBoxLayout> AsBoxLayout() = 0;
 
   ///
-  // Returns this Layout as a FillLayout or NULL if this is not a FillLayout.
+  /// Returns this Layout as a FillLayout or NULL if this is not a FillLayout.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefFillLayout> AsFillLayout() = 0;
 
   ///
-  // Returns true if this Layout is valid.
+  /// Returns true if this Layout is valid.
   ///
   /*--cef()--*/
   virtual bool IsValid() = 0;
diff --git a/src/include/views/cef_menu_button.h b/src/include/views/cef_menu_button.h
index 429444d..11f1bf4 100644
--- a/src/include/views/cef_menu_button.h
+++ b/src/include/views/cef_menu_button.h
@@ -43,22 +43,23 @@
 #include "include/views/cef_menu_button_delegate.h"
 
 ///
-// MenuButton is a button with optional text, icon and/or menu marker that shows
-// a menu when clicked with the left mouse button. All size and position values
-// are in density independent pixels (DIP) unless otherwise indicated. Methods
-// must be called on the browser process UI thread unless otherwise indicated.
+/// MenuButton is a button with optional text, icon and/or menu marker that
+/// shows a menu when clicked with the left mouse button. All size and position
+/// values are in density independent pixels (DIP) unless otherwise indicated.
+/// Methods must be called on the browser process UI thread unless otherwise
+/// indicated.
 ///
 /*--cef(source=library)--*/
 class CefMenuButton : public CefLabelButton {
  public:
   ///
-  // Create a new MenuButton. A |delegate| must be provided to call ShowMenu()
-  // when the button is clicked. |text| will be shown on the MenuButton and used
-  // as the default accessible name. If |with_frame| is true the button will
-  // have a visible frame at all times, center alignment, additional padding and
-  // a default minimum size of 70x33 DIP. If |with_frame| is false the button
-  // will only have a visible frame on hover/press, left alignment, less padding
-  // and no default minimum size.
+  /// Create a new MenuButton. A |delegate| must be provided to call ShowMenu()
+  /// when the button is clicked. |text| will be shown on the MenuButton and
+  /// used as the default accessible name. If |with_frame| is true the button
+  /// will have a visible frame at all times, center alignment, additional
+  /// padding and a default minimum size of 70x33 DIP. If |with_frame| is false
+  /// the button will only have a visible frame on hover/press, left alignment,
+  /// less padding and no default minimum size.
   ///
   /*--cef(optional_param=text)--*/
   static CefRefPtr<CefMenuButton> CreateMenuButton(
@@ -66,10 +67,10 @@
       const CefString& text);
 
   ///
-  // Show a menu with contents |menu_model|. |screen_point| specifies the menu
-  // position in screen coordinates. |anchor_position| specifies how the menu
-  // will be anchored relative to |screen_point|. This method should be called
-  // from CefMenuButtonDelegate::OnMenuButtonPressed().
+  /// Show a menu with contents |menu_model|. |screen_point| specifies the menu
+  /// position in screen coordinates. |anchor_position| specifies how the menu
+  /// will be anchored relative to |screen_point|. This method should be called
+  /// from CefMenuButtonDelegate::OnMenuButtonPressed().
   ///
   /*--cef()--*/
   virtual void ShowMenu(CefRefPtr<CefMenuModel> menu_model,
@@ -77,8 +78,8 @@
                         cef_menu_anchor_position_t anchor_position) = 0;
 
   ///
-  // Show the menu for this button. Results in a call to
-  // CefMenuButtonDelegate::OnMenuButtonPressed().
+  /// Show the menu for this button. Results in a call to
+  /// CefMenuButtonDelegate::OnMenuButtonPressed().
   ///
   /*--cef()--*/
   virtual void TriggerMenu() = 0;
diff --git a/src/include/views/cef_menu_button_delegate.h b/src/include/views/cef_menu_button_delegate.h
index 787b179..333e80e 100644
--- a/src/include/views/cef_menu_button_delegate.h
+++ b/src/include/views/cef_menu_button_delegate.h
@@ -43,24 +43,24 @@
 class CefMenuButton;
 
 ///
-// MenuButton pressed lock is released when this object is destroyed.
+/// MenuButton pressed lock is released when this object is destroyed.
 ///
 /*--cef(source=library)--*/
 class CefMenuButtonPressedLock : public CefBaseRefCounted {};
 
 ///
-// Implement this interface to handle MenuButton events. The methods of this
-// class will be called on the browser process UI thread unless otherwise
-// indicated.
+/// Implement this interface to handle MenuButton events. The methods of this
+/// class will be called on the browser process UI thread unless otherwise
+/// indicated.
 ///
 /*--cef(source=client)--*/
 class CefMenuButtonDelegate : public CefButtonDelegate {
  public:
   ///
-  // Called when |button| is pressed. Call CefMenuButton::ShowMenu() to show a
-  // popup menu at |screen_point|. When showing a custom popup such as a window
-  // keep a reference to |button_pressed_lock| until the popup is hidden to
-  // maintain the pressed button state.
+  /// Called when |button| is pressed. Call CefMenuButton::ShowMenu() to show a
+  /// popup menu at |screen_point|. When showing a custom popup such as a window
+  /// keep a reference to |button_pressed_lock| until the popup is hidden to
+  /// maintain the pressed button state.
   ///
   /*--cef()--*/
   virtual void OnMenuButtonPressed(
diff --git a/src/include/views/cef_overlay_controller.h b/src/include/views/cef_overlay_controller.h
new file mode 100644
index 0000000..038c26d
--- /dev/null
+++ b/src/include/views/cef_overlay_controller.h
@@ -0,0 +1,210 @@
+// Copyright (c) 2021 Marshall A. Greenblatt. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the names of its contributors may be used to endorse
+// or promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ---------------------------------------------------------------------------
+//
+// The contents of this file must follow a specific format in order to
+// support the CEF translator tool. See the translator.README.txt file in the
+// tools directory for more information.
+//
+
+#ifndef CEF_INCLUDE_VIEWS_CEF_OVERLAY_CONTROLLER_H_
+#define CEF_INCLUDE_VIEWS_CEF_OVERLAY_CONTROLLER_H_
+#pragma once
+
+#include "include/cef_base.h"
+
+class CefView;
+class CefWindow;
+
+///
+/// Controller for an overlay that contains a contents View added via
+/// CefWindow::AddOverlayView. Methods exposed by this controller should be
+/// called in preference to methods of the same name exposed by the contents
+/// View unless otherwise indicated. Methods must be called on the browser
+/// process UI thread unless otherwise indicated.
+///
+/*--cef(source=library)--*/
+class CefOverlayController : public CefBaseRefCounted {
+ public:
+  ///
+  /// Returns true if this object is valid.
+  ///
+  /*--cef()--*/
+  virtual bool IsValid() = 0;
+
+  ///
+  /// Returns true if this object is the same as |that| object.
+  ///
+  /*--cef()--*/
+  virtual bool IsSame(CefRefPtr<CefOverlayController> that) = 0;
+
+  ///
+  /// Returns the contents View for this overlay.
+  ///
+  /*--cef()--*/
+  virtual CefRefPtr<CefView> GetContentsView() = 0;
+
+  ///
+  /// Returns the top-level Window hosting this overlay. Use this method instead
+  /// of calling GetWindow() on the contents View.
+  ///
+  /*--cef()--*/
+  virtual CefRefPtr<CefWindow> GetWindow() = 0;
+
+  ///
+  /// Returns the docking mode for this overlay.
+  ///
+  /*--cef(default_retval=CEF_DOCKING_MODE_TOP_LEFT)--*/
+  virtual cef_docking_mode_t GetDockingMode() = 0;
+
+  ///
+  /// Destroy this overlay.
+  ///
+  /*--cef()--*/
+  virtual void Destroy() = 0;
+
+  ///
+  /// Sets the bounds (size and position) of this overlay. This will set the
+  /// bounds of the contents View to match and trigger a re-layout if necessary.
+  /// |bounds| is in parent coordinates and any insets configured on this
+  /// overlay will be ignored. Use this method only for overlays created with a
+  /// docking mode value of CEF_DOCKING_MODE_CUSTOM. With other docking modes
+  /// modify the insets of this overlay and/or layout of the contents View and
+  /// call SizeToPreferredSize() instead to calculate the new size and
+  /// re-position the overlay if necessary.
+  ///
+  /*--cef()--*/
+  virtual void SetBounds(const CefRect& bounds) = 0;
+
+  ///
+  /// Returns the bounds (size and position) of this overlay in parent
+  /// coordinates.
+  ///
+  /*--cef()--*/
+  virtual CefRect GetBounds() = 0;
+
+  ///
+  /// Returns the bounds (size and position) of this overlay in DIP screen
+  /// coordinates.
+  ///
+  /*--cef()--*/
+  virtual CefRect GetBoundsInScreen() = 0;
+
+  ///
+  /// Sets the size of this overlay without changing the position. This will set
+  /// the size of the contents View to match and trigger a re-layout if
+  /// necessary. |size| is in parent coordinates and any insets configured on
+  /// this overlay will be ignored. Use this method only for overlays created
+  /// with a docking mode value of CEF_DOCKING_MODE_CUSTOM. With other docking
+  /// modes modify the insets of this overlay and/or layout of the contents View
+  /// and call SizeToPreferredSize() instead to calculate the new size and
+  /// re-position the overlay if necessary.
+  ///
+  /*--cef()--*/
+  virtual void SetSize(const CefSize& size) = 0;
+
+  ///
+  /// Returns the size of this overlay in parent coordinates.
+  ///
+  /*--cef()--*/
+  virtual CefSize GetSize() = 0;
+
+  ///
+  /// Sets the position of this overlay without changing the size. |position| is
+  /// in parent coordinates and any insets configured on this overlay will
+  /// be ignored. Use this method only for overlays created with a docking mode
+  /// value of CEF_DOCKING_MODE_CUSTOM. With other docking modes modify the
+  /// insets of this overlay and/or layout of the contents View and call
+  /// SizeToPreferredSize() instead to calculate the new size and re-position
+  /// the overlay if necessary.
+  ///
+  /*--cef()--*/
+  virtual void SetPosition(const CefPoint& position) = 0;
+
+  ///
+  /// Returns the position of this overlay in parent coordinates.
+  ///
+  /*--cef()--*/
+  virtual CefPoint GetPosition() = 0;
+
+  ///
+  /// Sets the insets for this overlay. |insets| is in parent coordinates. Use
+  /// this method only for overlays created with a docking mode value other than
+  /// CEF_DOCKING_MODE_CUSTOM.
+  ///
+  /*--cef()--*/
+  virtual void SetInsets(const CefInsets& insets) = 0;
+
+  ///
+  /// Returns the insets for this overlay in parent coordinates.
+  ///
+  /*--cef()--*/
+  virtual CefInsets GetInsets() = 0;
+
+  ///
+  /// Size this overlay to its preferred size and trigger a re-layout if
+  /// necessary. The position of overlays created with a docking mode value of
+  /// CEF_DOCKING_MODE_CUSTOM will not be modified by calling this method. With
+  /// other docking modes this method may re-position the overlay if necessary
+  /// to accommodate the new size and any insets configured on the contents
+  /// View.
+  ///
+  /*--cef()--*/
+  virtual void SizeToPreferredSize() = 0;
+
+  ///
+  /// Sets whether this overlay is visible. Overlays are hidden by default. If
+  /// this overlay is hidden then it and any child Views will not be drawn and,
+  /// if any of those Views currently have focus, then focus will also be
+  /// cleared. Painting is scheduled as needed.
+  ///
+  /*--cef()--*/
+  virtual void SetVisible(bool visible) = 0;
+
+  ///
+  /// Returns whether this overlay is visible. A View may be visible but still
+  /// not drawn in a Window if any parent Views are hidden. Call IsDrawn() to
+  /// determine whether this overlay and all parent Views are visible and will
+  /// be drawn.
+  ///
+  /*--cef()--*/
+  virtual bool IsVisible() = 0;
+
+  ///
+  /// Returns whether this overlay is visible and drawn in a Window. A View is
+  /// drawn if it and all parent Views are visible. To determine if the
+  /// containing Window is visible to the user on-screen call IsVisible() on the
+  /// Window.
+  ///
+  /*--cef()--*/
+  virtual bool IsDrawn() = 0;
+};
+
+#endif  // CEF_INCLUDE_VIEWS_CEF_OVERLAY_CONTROLLER_H_
diff --git a/src/include/views/cef_panel.h b/src/include/views/cef_panel.h
index 4a4fb90..f74c228 100644
--- a/src/include/views/cef_panel.h
+++ b/src/include/views/cef_panel.h
@@ -47,92 +47,92 @@
 class CefWindow;
 
 ///
-// A Panel is a container in the views hierarchy that can contain other Views
-// as children. Methods must be called on the browser process UI thread unless
-// otherwise indicated.
+/// A Panel is a container in the views hierarchy that can contain other Views
+/// as children. Methods must be called on the browser process UI thread unless
+/// otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefPanel : public CefView {
  public:
   ///
-  // Create a new Panel.
+  /// Create a new Panel.
   ///
   /*--cef(optional_param=delegate)--*/
   static CefRefPtr<CefPanel> CreatePanel(CefRefPtr<CefPanelDelegate> delegate);
 
   ///
-  // Returns this Panel as a Window or NULL if this is not a Window.
+  /// Returns this Panel as a Window or NULL if this is not a Window.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefWindow> AsWindow() = 0;
 
   ///
-  // Set this Panel's Layout to FillLayout and return the FillLayout object.
+  /// Set this Panel's Layout to FillLayout and return the FillLayout object.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefFillLayout> SetToFillLayout() = 0;
 
   ///
-  // Set this Panel's Layout to BoxLayout and return the BoxLayout object.
+  /// Set this Panel's Layout to BoxLayout and return the BoxLayout object.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBoxLayout> SetToBoxLayout(
       const CefBoxLayoutSettings& settings) = 0;
 
   ///
-  // Get the Layout.
+  /// Get the Layout.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefLayout> GetLayout() = 0;
 
   ///
-  // Lay out the child Views (set their bounds based on sizing heuristics
-  // specific to the current Layout).
+  /// Lay out the child Views (set their bounds based on sizing heuristics
+  /// specific to the current Layout).
   ///
   /*--cef()--*/
   virtual void Layout() = 0;
 
   ///
-  // Add a child View.
+  /// Add a child View.
   ///
   /*--cef()--*/
   virtual void AddChildView(CefRefPtr<CefView> view) = 0;
 
   ///
-  // Add a child View at the specified |index|. If |index| matches the result of
-  // GetChildCount() then the View will be added at the end.
+  /// Add a child View at the specified |index|. If |index| matches the result
+  /// of GetChildCount() then the View will be added at the end.
   ///
   /*--cef(index_param=index)--*/
   virtual void AddChildViewAt(CefRefPtr<CefView> view, int index) = 0;
 
   ///
-  // Move the child View to the specified |index|. A negative value for |index|
-  // will move the View to the end.
+  /// Move the child View to the specified |index|. A negative value for |index|
+  /// will move the View to the end.
   ///
   /*--cef()--*/
   virtual void ReorderChildView(CefRefPtr<CefView> view, int index) = 0;
 
   ///
-  // Remove a child View. The View can then be added to another Panel.
+  /// Remove a child View. The View can then be added to another Panel.
   ///
   /*--cef()--*/
   virtual void RemoveChildView(CefRefPtr<CefView> view) = 0;
 
   ///
-  // Remove all child Views. The removed Views will be deleted if the client
-  // holds no references to them.
+  /// Remove all child Views. The removed Views will be deleted if the client
+  /// holds no references to them.
   ///
   /*--cef()--*/
   virtual void RemoveAllChildViews() = 0;
 
   ///
-  // Returns the number of child Views.
+  /// Returns the number of child Views.
   ///
   /*--cef()--*/
   virtual size_t GetChildViewCount() = 0;
 
   ///
-  // Returns the child View at the specified |index|.
+  /// Returns the child View at the specified |index|.
   ///
   /*--cef(index_param=index)--*/
   virtual CefRefPtr<CefView> GetChildViewAt(int index) = 0;
diff --git a/src/include/views/cef_panel_delegate.h b/src/include/views/cef_panel_delegate.h
index cd49611..1076838 100644
--- a/src/include/views/cef_panel_delegate.h
+++ b/src/include/views/cef_panel_delegate.h
@@ -41,8 +41,8 @@
 #include "include/views/cef_view_delegate.h"
 
 ///
-// Implement this interface to handle Panel events. The methods of this class
-// will be called on the browser process UI thread unless otherwise indicated.
+/// Implement this interface to handle Panel events. The methods of this class
+/// will be called on the browser process UI thread unless otherwise indicated.
 ///
 /*--cef(source=client)--*/
 class CefPanelDelegate : public CefViewDelegate {};
diff --git a/src/include/views/cef_scroll_view.h b/src/include/views/cef_scroll_view.h
index da472bd..fb62459 100644
--- a/src/include/views/cef_scroll_view.h
+++ b/src/include/views/cef_scroll_view.h
@@ -41,59 +41,59 @@
 #include "include/views/cef_view.h"
 
 ///
-// A ScrollView will show horizontal and/or vertical scrollbars when necessary
-// based on the size of the attached content view. Methods must be called on the
-// browser process UI thread unless otherwise indicated.
+/// A ScrollView will show horizontal and/or vertical scrollbars when necessary
+/// based on the size of the attached content view. Methods must be called on
+/// the browser process UI thread unless otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefScrollView : public CefView {
  public:
   ///
-  // Create a new ScrollView.
+  /// Create a new ScrollView.
   ///
   /*--cef(optional_param=delegate)--*/
   static CefRefPtr<CefScrollView> CreateScrollView(
       CefRefPtr<CefViewDelegate> delegate);
 
   ///
-  // Set the content View. The content View must have a specified size (e.g.
-  // via CefView::SetBounds or CefViewDelegate::GetPreferredSize).
+  /// Set the content View. The content View must have a specified size (e.g.
+  /// via CefView::SetBounds or CefViewDelegate::GetPreferredSize).
   ///
   /*--cef()--*/
   virtual void SetContentView(CefRefPtr<CefView> view) = 0;
 
   ///
-  // Returns the content View.
+  /// Returns the content View.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefView> GetContentView() = 0;
 
   ///
-  // Returns the visible region of the content View.
+  /// Returns the visible region of the content View.
   ///
   /*--cef()--*/
   virtual CefRect GetVisibleContentRect() = 0;
 
   ///
-  // Returns true if the horizontal scrollbar is currently showing.
+  /// Returns true if the horizontal scrollbar is currently showing.
   ///
   /*--cef()--*/
   virtual bool HasHorizontalScrollbar() = 0;
 
   ///
-  // Returns the height of the horizontal scrollbar.
+  /// Returns the height of the horizontal scrollbar.
   ///
   /*--cef()--*/
   virtual int GetHorizontalScrollbarHeight() = 0;
 
   ///
-  // Returns true if the vertical scrollbar is currently showing.
+  /// Returns true if the vertical scrollbar is currently showing.
   ///
   /*--cef()--*/
   virtual bool HasVerticalScrollbar() = 0;
 
   ///
-  // Returns the width of the vertical scrollbar.
+  /// Returns the width of the vertical scrollbar.
   ///
   /*--cef()--*/
   virtual int GetVerticalScrollbarWidth() = 0;
diff --git a/src/include/views/cef_textfield.h b/src/include/views/cef_textfield.h
index 9b53f72..e6f8edb 100644
--- a/src/include/views/cef_textfield.h
+++ b/src/include/views/cef_textfield.h
@@ -42,177 +42,178 @@
 #include "include/views/cef_view.h"
 
 ///
-// A Textfield supports editing of text. This control is custom rendered with no
-// platform-specific code. Methods must be called on the browser process UI
-// thread unless otherwise indicated.
+/// A Textfield supports editing of text. This control is custom rendered with
+/// no platform-specific code. Methods must be called on the browser process UI
+/// thread unless otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefTextfield : public CefView {
  public:
   ///
-  // Create a new Textfield.
+  /// Create a new Textfield.
   ///
   /*--cef(optional_param=delegate)--*/
   static CefRefPtr<CefTextfield> CreateTextfield(
       CefRefPtr<CefTextfieldDelegate> delegate);
 
   ///
-  // Sets whether the text will be displayed as asterisks.
+  /// Sets whether the text will be displayed as asterisks.
   ///
   /*--cef()--*/
   virtual void SetPasswordInput(bool password_input) = 0;
 
   ///
-  // Returns true if the text will be displayed as asterisks.
+  /// Returns true if the text will be displayed as asterisks.
   ///
   /*--cef()--*/
   virtual bool IsPasswordInput() = 0;
 
   ///
-  // Sets whether the text will read-only.
+  /// Sets whether the text will read-only.
   ///
   /*--cef()--*/
   virtual void SetReadOnly(bool read_only) = 0;
 
   ///
-  // Returns true if the text is read-only.
+  /// Returns true if the text is read-only.
   ///
   /*--cef()--*/
   virtual bool IsReadOnly() = 0;
 
   ///
-  // Returns the currently displayed text.
+  /// Returns the currently displayed text.
   ///
   /*--cef()--*/
   virtual CefString GetText() = 0;
 
   ///
-  // Sets the contents to |text|. The cursor will be moved to end of the text if
-  // the current position is outside of the text range.
+  /// Sets the contents to |text|. The cursor will be moved to end of the text
+  /// if the current position is outside of the text range.
   ///
   /*--cef()--*/
   virtual void SetText(const CefString& text) = 0;
 
   ///
-  // Appends |text| to the previously-existing text.
+  /// Appends |text| to the previously-existing text.
   ///
   /*--cef()--*/
   virtual void AppendText(const CefString& text) = 0;
 
   ///
-  // Inserts |text| at the current cursor position replacing any selected text.
+  /// Inserts |text| at the current cursor position replacing any selected text.
   ///
   /*--cef()--*/
   virtual void InsertOrReplaceText(const CefString& text) = 0;
 
   ///
-  // Returns true if there is any selected text.
+  /// Returns true if there is any selected text.
   ///
   /*--cef()--*/
   virtual bool HasSelection() = 0;
 
   ///
-  // Returns the currently selected text.
+  /// Returns the currently selected text.
   ///
   /*--cef()--*/
   virtual CefString GetSelectedText() = 0;
 
   ///
-  // Selects all text. If |reversed| is true the range will end at the logical
-  // beginning of the text; this generally shows the leading portion of text
-  // that overflows its display area.
+  /// Selects all text. If |reversed| is true the range will end at the logical
+  /// beginning of the text; this generally shows the leading portion of text
+  /// that overflows its display area.
   ///
   /*--cef()--*/
   virtual void SelectAll(bool reversed) = 0;
 
   ///
-  // Clears the text selection and sets the caret to the end.
+  /// Clears the text selection and sets the caret to the end.
   ///
   /*--cef()--*/
   virtual void ClearSelection() = 0;
 
   ///
-  // Returns the selected logical text range.
+  /// Returns the selected logical text range.
   ///
   /*--cef()--*/
   virtual CefRange GetSelectedRange() = 0;
 
   ///
-  // Selects the specified logical text range.
+  /// Selects the specified logical text range.
   ///
   /*--cef()--*/
   virtual void SelectRange(const CefRange& range) = 0;
 
   ///
-  // Returns the current cursor position.
+  /// Returns the current cursor position.
   ///
   /*--cef()--*/
   virtual size_t GetCursorPosition() = 0;
 
   ///
-  // Sets the text color.
+  /// Sets the text color.
   ///
   /*--cef()--*/
   virtual void SetTextColor(cef_color_t color) = 0;
 
   ///
-  // Returns the text color.
+  /// Returns the text color.
   ///
   /*--cef()--*/
   virtual cef_color_t GetTextColor() = 0;
 
   ///
-  // Sets the selection text color.
+  /// Sets the selection text color.
   ///
   /*--cef()--*/
   virtual void SetSelectionTextColor(cef_color_t color) = 0;
 
   ///
-  // Returns the selection text color.
+  /// Returns the selection text color.
   ///
   /*--cef()--*/
   virtual cef_color_t GetSelectionTextColor() = 0;
 
   ///
-  // Sets the selection background color.
+  /// Sets the selection background color.
   ///
   /*--cef()--*/
   virtual void SetSelectionBackgroundColor(cef_color_t color) = 0;
 
   ///
-  // Returns the selection background color.
+  /// Returns the selection background color.
   ///
   /*--cef()--*/
   virtual cef_color_t GetSelectionBackgroundColor() = 0;
 
   ///
-  // Sets the font list. The format is "<FONT_FAMILY_LIST>,[STYLES] <SIZE>",
-  // where:
-  // - FONT_FAMILY_LIST is a comma-separated list of font family names,
-  // - STYLES is an optional space-separated list of style names (case-sensitive
-  //   "Bold" and "Italic" are supported), and
-  // - SIZE is an integer font size in pixels with the suffix "px".
-  //
-  // Here are examples of valid font description strings:
-  // - "Arial, Helvetica, Bold Italic 14px"
-  // - "Arial, 14px"
+  /// Sets the font list. The format is "<FONT_FAMILY_LIST>,[STYLES] <SIZE>",
+  /// where:
+  /// - FONT_FAMILY_LIST is a comma-separated list of font family names,
+  /// - STYLES is an optional space-separated list of style names
+  /// (case-sensitive
+  ///   "Bold" and "Italic" are supported), and
+  /// - SIZE is an integer font size in pixels with the suffix "px".
+  ///
+  /// Here are examples of valid font description strings:
+  /// - "Arial, Helvetica, Bold Italic 14px"
+  /// - "Arial, 14px"
   ///
   /*--cef()--*/
   virtual void SetFontList(const CefString& font_list) = 0;
 
   ///
-  // Applies |color| to the specified |range| without changing the default
-  // color. If |range| is empty the color will be set on the complete text
-  // contents.
+  /// Applies |color| to the specified |range| without changing the default
+  /// color. If |range| is empty the color will be set on the complete text
+  /// contents.
   ///
   /*--cef()--*/
   virtual void ApplyTextColor(cef_color_t color, const CefRange& range) = 0;
 
   ///
-  // Applies |style| to the specified |range| without changing the default
-  // style. If |add| is true the style will be added, otherwise the style will
-  // be removed. If |range| is empty the style will be set on the complete text
-  // contents.
+  /// Applies |style| to the specified |range| without changing the default
+  /// style. If |add| is true the style will be added, otherwise the style will
+  /// be removed. If |range| is empty the style will be set on the complete text
+  /// contents.
   ///
   /*--cef()--*/
   virtual void ApplyTextStyle(cef_text_style_t style,
@@ -220,49 +221,46 @@
                               const CefRange& range) = 0;
 
   ///
-  // Returns true if the action associated with the specified command id is
-  // enabled. See additional comments on ExecuteCommand().
+  /// Returns true if the action associated with the specified command id is
+  /// enabled. See additional comments on ExecuteCommand().
   ///
   /*--cef()--*/
-  virtual bool IsCommandEnabled(int command_id) = 0;
+  virtual bool IsCommandEnabled(cef_text_field_commands_t command_id) = 0;
 
   ///
-  // Performs the action associated with the specified command id. Valid values
-  // include IDS_APP_UNDO, IDS_APP_REDO, IDS_APP_CUT, IDS_APP_COPY,
-  // IDS_APP_PASTE, IDS_APP_DELETE, IDS_APP_SELECT_ALL, IDS_DELETE_* and
-  // IDS_MOVE_*. See include/cef_pack_strings.h for definitions.
+  /// Performs the action associated with the specified command id.
   ///
   /*--cef()--*/
-  virtual void ExecuteCommand(int command_id) = 0;
+  virtual void ExecuteCommand(cef_text_field_commands_t command_id) = 0;
 
   ///
-  // Clears Edit history.
+  /// Clears Edit history.
   ///
   /*--cef()--*/
   virtual void ClearEditHistory() = 0;
 
   ///
-  // Sets the placeholder text that will be displayed when the Textfield is
-  // empty.
+  /// Sets the placeholder text that will be displayed when the Textfield is
+  /// empty.
   ///
   /*--cef()--*/
   virtual void SetPlaceholderText(const CefString& text) = 0;
 
   ///
-  // Returns the placeholder text that will be displayed when the Textfield is
-  // empty.
+  /// Returns the placeholder text that will be displayed when the Textfield is
+  /// empty.
   ///
   /*--cef()--*/
   virtual CefString GetPlaceholderText() = 0;
 
   ///
-  // Sets the placeholder text color.
+  /// Sets the placeholder text color.
   ///
   /*--cef()--*/
   virtual void SetPlaceholderTextColor(cef_color_t color) = 0;
 
   ///
-  // Set the accessible name that will be exposed to assistive technology (AT).
+  /// Set the accessible name that will be exposed to assistive technology (AT).
   ///
   /*--cef()--*/
   virtual void SetAccessibleName(const CefString& name) = 0;
diff --git a/src/include/views/cef_textfield_delegate.h b/src/include/views/cef_textfield_delegate.h
index c3fddaf..aa3660e 100644
--- a/src/include/views/cef_textfield_delegate.h
+++ b/src/include/views/cef_textfield_delegate.h
@@ -43,17 +43,17 @@
 class CefTextfield;
 
 ///
-// Implement this interface to handle Textfield events. The methods of this
-// class will be called on the browser process UI thread unless otherwise
-// indicated.
+/// Implement this interface to handle Textfield events. The methods of this
+/// class will be called on the browser process UI thread unless otherwise
+/// indicated.
 ///
 /*--cef(source=client)--*/
 class CefTextfieldDelegate : public CefViewDelegate {
  public:
   ///
-  // Called when |textfield| recieves a keyboard event. |event| contains
-  // information about the keyboard event. Return true if the keyboard event was
-  // handled or false otherwise for default handling.
+  /// Called when |textfield| recieves a keyboard event. |event| contains
+  /// information about the keyboard event. Return true if the keyboard event
+  /// was handled or false otherwise for default handling.
   ///
   /*--cef()--*/
   virtual bool OnKeyEvent(CefRefPtr<CefTextfield> textfield,
@@ -62,7 +62,7 @@
   }
 
   ///
-  // Called after performing a user action that may change |textfield|.
+  /// Called after performing a user action that may change |textfield|.
   ///
   /*--cef()--*/
   virtual void OnAfterUserAction(CefRefPtr<CefTextfield> textfield) {}
diff --git a/src/include/views/cef_view.h b/src/include/views/cef_view.h
index eed14f3..9bfd1f4 100644
--- a/src/include/views/cef_view.h
+++ b/src/include/views/cef_view.h
@@ -48,350 +48,376 @@
 class CefWindow;
 
 ///
-// A View is a rectangle within the views View hierarchy. It is the base class
-// for all Views. All size and position values are in density independent pixels
-// (DIP) unless otherwise indicated. Methods must be called on the browser
-// process UI thread unless otherwise indicated.
+/// A View is a rectangle within the views View hierarchy. It is the base class
+/// for all Views. All size and position values are in density independent
+/// pixels (DIP) unless otherwise indicated. Methods must be called on the
+/// browser process UI thread unless otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefView : public CefBaseRefCounted {
  public:
   ///
-  // Returns this View as a BrowserView or NULL if this is not a BrowserView.
+  /// Returns this View as a BrowserView or NULL if this is not a BrowserView.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefBrowserView> AsBrowserView() = 0;
 
   ///
-  // Returns this View as a Button or NULL if this is not a Button.
+  /// Returns this View as a Button or NULL if this is not a Button.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefButton> AsButton() = 0;
 
   ///
-  // Returns this View as a Panel or NULL if this is not a Panel.
+  /// Returns this View as a Panel or NULL if this is not a Panel.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefPanel> AsPanel() = 0;
 
   ///
-  // Returns this View as a ScrollView or NULL if this is not a ScrollView.
+  /// Returns this View as a ScrollView or NULL if this is not a ScrollView.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefScrollView> AsScrollView() = 0;
 
   ///
-  // Returns this View as a Textfield or NULL if this is not a Textfield.
+  /// Returns this View as a Textfield or NULL if this is not a Textfield.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefTextfield> AsTextfield() = 0;
 
   ///
-  // Returns the type of this View as a string. Used primarily for testing
-  // purposes.
+  /// Returns the type of this View as a string. Used primarily for testing
+  /// purposes.
   ///
   /*--cef()--*/
   virtual CefString GetTypeString() = 0;
 
   ///
-  // Returns a string representation of this View which includes the type and
-  // various type-specific identifying attributes. If |include_children| is true
-  // any child Views will also be included. Used primarily for testing purposes.
+  /// Returns a string representation of this View which includes the type and
+  /// various type-specific identifying attributes. If |include_children| is
+  /// true any child Views will also be included. Used primarily for testing
+  /// purposes.
   ///
   /*--cef()--*/
   virtual CefString ToString(bool include_children) = 0;
 
   ///
-  // Returns true if this View is valid.
+  /// Returns true if this View is valid.
   ///
   /*--cef()--*/
   virtual bool IsValid() = 0;
 
   ///
-  // Returns true if this View is currently attached to another View. A View can
-  // only be attached to one View at a time.
+  /// Returns true if this View is currently attached to another View. A View
+  /// can only be attached to one View at a time.
   ///
   /*--cef()--*/
   virtual bool IsAttached() = 0;
 
   ///
-  // Returns true if this View is the same as |that| View.
+  /// Returns true if this View is the same as |that| View.
   ///
   /*--cef()--*/
   virtual bool IsSame(CefRefPtr<CefView> that) = 0;
 
   ///
-  // Returns the delegate associated with this View, if any.
+  /// Returns the delegate associated with this View, if any.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefViewDelegate> GetDelegate() = 0;
 
   ///
-  // Returns the top-level Window hosting this View, if any.
+  /// Returns the top-level Window hosting this View, if any.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefWindow> GetWindow() = 0;
 
   ///
-  // Returns the ID for this View.
+  /// Returns the ID for this View.
   ///
   /*--cef()--*/
   virtual int GetID() = 0;
 
   ///
-  // Sets the ID for this View. ID should be unique within the subtree that you
-  // intend to search for it. 0 is the default ID for views.
+  /// Sets the ID for this View. ID should be unique within the subtree that you
+  /// intend to search for it. 0 is the default ID for views.
   ///
   /*--cef()--*/
   virtual void SetID(int id) = 0;
 
   ///
-  // Returns the group id of this View, or -1 if not set.
+  /// Returns the group id of this View, or -1 if not set.
   ///
   /*--cef()--*/
   virtual int GetGroupID() = 0;
 
   ///
-  // A group id is used to tag Views which are part of the same logical group.
-  // Focus can be moved between views with the same group using the arrow keys.
-  // The group id is immutable once it's set.
+  /// A group id is used to tag Views which are part of the same logical group.
+  /// Focus can be moved between views with the same group using the arrow keys.
+  /// The group id is immutable once it's set.
   ///
   /*--cef()--*/
   virtual void SetGroupID(int group_id) = 0;
 
   ///
-  // Returns the View that contains this View, if any.
+  /// Returns the View that contains this View, if any.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefView> GetParentView() = 0;
 
   ///
-  // Recursively descends the view tree starting at this View, and returns the
-  // first child that it encounters with the given ID. Returns NULL if no
-  // matching child view is found.
+  /// Recursively descends the view tree starting at this View, and returns the
+  /// first child that it encounters with the given ID. Returns NULL if no
+  /// matching child view is found.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefView> GetViewForID(int id) = 0;
 
   ///
-  // Sets the bounds (size and position) of this View. Position is in parent
-  // coordinates.
+  /// Sets the bounds (size and position) of this View. |bounds| is in parent
+  /// coordinates, or DIP screen coordinates if there is no parent.
   ///
   /*--cef()--*/
   virtual void SetBounds(const CefRect& bounds) = 0;
 
   ///
-  // Returns the bounds (size and position) of this View. Position is in parent
-  // coordinates.
+  /// Returns the bounds (size and position) of this View in parent coordinates,
+  /// or DIP screen coordinates if there is no parent.
   ///
   /*--cef()--*/
   virtual CefRect GetBounds() = 0;
 
   ///
-  // Returns the bounds (size and position) of this View. Position is in screen
-  // coordinates.
+  /// Returns the bounds (size and position) of this View in DIP screen
+  /// coordinates.
   ///
   /*--cef()--*/
   virtual CefRect GetBoundsInScreen() = 0;
 
   ///
-  // Sets the size of this View without changing the position.
+  /// Sets the size of this View without changing the position. |size| in
+  /// parent coordinates, or DIP screen coordinates if there is no parent.
   ///
   /*--cef()--*/
   virtual void SetSize(const CefSize& size) = 0;
 
   ///
-  // Returns the size of this View.
+  /// Returns the size of this View in parent coordinates, or DIP screen
+  /// coordinates if there is no parent.
   ///
   /*--cef()--*/
   virtual CefSize GetSize() = 0;
 
   ///
-  // Sets the position of this View without changing the size. |position| is in
-  // parent coordinates.
+  /// Sets the position of this View without changing the size. |position| is in
+  /// parent coordinates, or DIP screen coordinates if there is no parent.
   ///
   /*--cef()--*/
   virtual void SetPosition(const CefPoint& position) = 0;
 
   ///
-  // Returns the position of this View. Position is in parent coordinates.
+  /// Returns the position of this View. Position is in parent coordinates, or
+  /// DIP screen coordinates if there is no parent.
   ///
   /*--cef()--*/
   virtual CefPoint GetPosition() = 0;
 
   ///
-  // Returns the size this View would like to be if enough space is available.
+  /// Sets the insets for this View. |insets| is in parent coordinates, or DIP
+  /// screen coordinates if there is no parent.
+  ///
+  /*--cef()--*/
+  virtual void SetInsets(const CefInsets& insets) = 0;
+
+  ///
+  /// Returns the insets for this View in parent coordinates, or DIP screen
+  /// coordinates if there is no parent.
+  ///
+  /*--cef()--*/
+  virtual CefInsets GetInsets() = 0;
+
+  ///
+  /// Returns the size this View would like to be if enough space is available.
+  /// Size is in parent coordinates, or DIP screen coordinates if there is no
+  /// parent.
   ///
   /*--cef()--*/
   virtual CefSize GetPreferredSize() = 0;
 
   ///
-  // Size this View to its preferred size.
+  /// Size this View to its preferred size. Size is in parent coordinates, or
+  /// DIP screen coordinates if there is no parent.
   ///
   /*--cef()--*/
   virtual void SizeToPreferredSize() = 0;
 
   ///
-  // Returns the minimum size for this View.
+  /// Returns the minimum size for this View. Size is in parent coordinates, or
+  /// DIP screen coordinates if there is no parent.
   ///
   /*--cef()--*/
   virtual CefSize GetMinimumSize() = 0;
 
   ///
-  // Returns the maximum size for this View.
+  /// Returns the maximum size for this View. Size is in parent coordinates, or
+  /// DIP screen coordinates if there is no parent.
   ///
   /*--cef()--*/
   virtual CefSize GetMaximumSize() = 0;
 
   ///
-  // Returns the height necessary to display this View with the provided width.
+  /// Returns the height necessary to display this View with the provided width.
   ///
   /*--cef()--*/
   virtual int GetHeightForWidth(int width) = 0;
 
   ///
-  // Indicate that this View and all parent Views require a re-layout. This
-  // ensures the next call to Layout() will propagate to this View even if the
-  // bounds of parent Views do not change.
+  /// Indicate that this View and all parent Views require a re-layout. This
+  /// ensures the next call to Layout() will propagate to this View even if the
+  /// bounds of parent Views do not change.
   ///
   /*--cef()--*/
   virtual void InvalidateLayout() = 0;
 
   ///
-  // Sets whether this View is visible. Windows are hidden by default and other
-  // views are visible by default. This View and any parent views must be set as
-  // visible for this View to be drawn in a Window. If this View is set as
-  // hidden then it and any child views will not be drawn and, if any of those
-  // views currently have focus, then focus will also be cleared. Painting is
-  // scheduled as needed. If this View is a Window then calling this method is
-  // equivalent to calling the Window Show() and Hide() methods.
+  /// Sets whether this View is visible. Windows are hidden by default and other
+  /// views are visible by default. This View and any parent views must be set
+  /// as visible for this View to be drawn in a Window. If this View is set as
+  /// hidden then it and any child views will not be drawn and, if any of those
+  /// views currently have focus, then focus will also be cleared. Painting is
+  /// scheduled as needed. If this View is a Window then calling this method is
+  /// equivalent to calling the Window Show() and Hide() methods.
   ///
   /*--cef()--*/
   virtual void SetVisible(bool visible) = 0;
 
   ///
-  // Returns whether this View is visible. A view may be visible but still not
-  // drawn in a Window if any parent views are hidden. If this View is a Window
-  // then a return value of true indicates that this Window is currently visible
-  // to the user on-screen. If this View is not a Window then call IsDrawn() to
-  // determine whether this View and all parent views are visible and will be
-  // drawn.
+  /// Returns whether this View is visible. A view may be visible but still not
+  /// drawn in a Window if any parent views are hidden. If this View is a Window
+  /// then a return value of true indicates that this Window is currently
+  /// visible to the user on-screen. If this View is not a Window then call
+  /// IsDrawn() to determine whether this View and all parent views are visible
+  /// and will be drawn.
   ///
   /*--cef()--*/
   virtual bool IsVisible() = 0;
 
   ///
-  // Returns whether this View is visible and drawn in a Window. A view is drawn
-  // if it and all parent views are visible. If this View is a Window then
-  // calling this method is equivalent to calling IsVisible(). Otherwise, to
-  // determine if the containing Window is visible to the user on-screen call
-  // IsVisible() on the Window.
+  /// Returns whether this View is visible and drawn in a Window. A view is
+  /// drawn if it and all parent views are visible. If this View is a Window
+  /// then calling this method is equivalent to calling IsVisible(). Otherwise,
+  /// to determine if the containing Window is visible to the user on-screen
+  /// call IsVisible() on the Window.
   ///
   /*--cef()--*/
   virtual bool IsDrawn() = 0;
 
   ///
-  // Set whether this View is enabled. A disabled View does not receive keyboard
-  // or mouse inputs. If |enabled| differs from the current value the View will
-  // be repainted. Also, clears focus if the focused View is disabled.
+  /// Set whether this View is enabled. A disabled View does not receive
+  /// keyboard or mouse inputs. If |enabled| differs from the current value the
+  /// View will be repainted. Also, clears focus if the focused View is
+  /// disabled.
   ///
   /*--cef()--*/
   virtual void SetEnabled(bool enabled) = 0;
 
   ///
-  // Returns whether this View is enabled.
+  /// Returns whether this View is enabled.
   ///
   /*--cef()--*/
   virtual bool IsEnabled() = 0;
 
   ///
-  // Sets whether this View is capable of taking focus. It will clear focus if
-  // the focused View is set to be non-focusable. This is false by default so
-  // that a View used as a container does not get the focus.
+  /// Sets whether this View is capable of taking focus. It will clear focus if
+  /// the focused View is set to be non-focusable. This is false by default so
+  /// that a View used as a container does not get the focus.
   ///
   /*--cef()--*/
   virtual void SetFocusable(bool focusable) = 0;
 
   ///
-  // Returns true if this View is focusable, enabled and drawn.
+  /// Returns true if this View is focusable, enabled and drawn.
   ///
   /*--cef()--*/
   virtual bool IsFocusable() = 0;
 
   ///
-  // Return whether this View is focusable when the user requires full keyboard
-  // access, even though it may not be normally focusable.
+  /// Return whether this View is focusable when the user requires full keyboard
+  /// access, even though it may not be normally focusable.
   ///
   /*--cef()--*/
   virtual bool IsAccessibilityFocusable() = 0;
 
   ///
-  // Request keyboard focus. If this View is focusable it will become the
-  // focused View.
+  /// Request keyboard focus. If this View is focusable it will become the
+  /// focused View.
   ///
   /*--cef()--*/
   virtual void RequestFocus() = 0;
 
   ///
-  // Sets the background color for this View.
+  /// Sets the background color for this View.
   ///
   /*--cef()--*/
   virtual void SetBackgroundColor(cef_color_t color) = 0;
 
   ///
-  // Returns the background color for this View.
+  /// Returns the background color for this View.
   ///
   /*--cef()--*/
   virtual cef_color_t GetBackgroundColor() = 0;
 
   ///
-  // Convert |point| from this View's coordinate system to that of the screen.
-  // This View must belong to a Window when calling this method. Returns true
-  // if the conversion is successful or false otherwise. Use
-  // CefDisplay::ConvertPointToPixels() after calling this method if further
-  // conversion to display-specific pixel coordinates is desired.
+  /// Convert |point| from this View's coordinate system to DIP screen
+  /// coordinates. This View must belong to a Window when calling this method.
+  /// Returns true if the conversion is successful or false otherwise. Use
+  /// CefDisplay::ConvertPointToPixels() after calling this method if further
+  /// conversion to display-specific pixel coordinates is desired.
   ///
   /*--cef()--*/
   virtual bool ConvertPointToScreen(CefPoint& point) = 0;
 
   ///
-  // Convert |point| to this View's coordinate system from that of the screen.
-  // This View must belong to a Window when calling this method. Returns true if
-  // the conversion is successful or false otherwise. Use
-  // CefDisplay::ConvertPointFromPixels() before calling this method if
-  // conversion from display-specific pixel coordinates is necessary.
+  /// Convert |point| to this View's coordinate system from DIP screen
+  /// coordinates. This View must belong to a Window when calling this method.
+  /// Returns true if the conversion is successful or false otherwise. Use
+  /// CefDisplay::ConvertPointFromPixels() before calling this method if
+  /// conversion from display-specific pixel coordinates is necessary.
   ///
   /*--cef()--*/
   virtual bool ConvertPointFromScreen(CefPoint& point) = 0;
 
   ///
-  // Convert |point| from this View's coordinate system to that of the Window.
-  // This View must belong to a Window when calling this method. Returns true if
-  // the conversion is successful or false otherwise.
+  /// Convert |point| from this View's coordinate system to that of the Window.
+  /// This View must belong to a Window when calling this method. Returns true
+  /// if the conversion is successful or false otherwise.
   ///
   /*--cef()--*/
   virtual bool ConvertPointToWindow(CefPoint& point) = 0;
 
   ///
-  // Convert |point| to this View's coordinate system from that of the Window.
-  // This View must belong to a Window when calling this method. Returns true if
-  // the conversion is successful or false otherwise.
+  /// Convert |point| to this View's coordinate system from that of the Window.
+  /// This View must belong to a Window when calling this method. Returns true
+  /// if the conversion is successful or false otherwise.
   ///
   /*--cef()--*/
   virtual bool ConvertPointFromWindow(CefPoint& point) = 0;
 
   ///
-  // Convert |point| from this View's coordinate system to that of |view|.
-  // |view| needs to be in the same Window but not necessarily the same view
-  // hierarchy. Returns true if the conversion is successful or false otherwise.
+  /// Convert |point| from this View's coordinate system to that of |view|.
+  /// |view| needs to be in the same Window but not necessarily the same view
+  /// hierarchy. Returns true if the conversion is successful or false
+  /// otherwise.
   ///
   /*--cef()--*/
   virtual bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) = 0;
 
   ///
-  // Convert |point| to this View's coordinate system from that |view|. |view|
-  // needs to be in the same Window but not necessarily the same view hierarchy.
-  // Returns true if the conversion is successful or false otherwise.
+  /// Convert |point| to this View's coordinate system from that |view|. |view|
+  /// needs to be in the same Window but not necessarily the same view
+  /// hierarchy. Returns true if the conversion is successful or false
+  /// otherwise.
   ///
   /*--cef()--*/
   virtual bool ConvertPointFromView(CefRefPtr<CefView> view,
diff --git a/src/include/views/cef_view_delegate.h b/src/include/views/cef_view_delegate.h
index 438896c..2387832 100644
--- a/src/include/views/cef_view_delegate.h
+++ b/src/include/views/cef_view_delegate.h
@@ -43,15 +43,17 @@
 class CefView;
 
 ///
-// Implement this interface to handle view events. The methods of this class
-// will be called on the browser process UI thread unless otherwise indicated.
+/// Implement this interface to handle view events. All size and position values
+/// are in density independent pixels (DIP) unless otherwise indicated. The
+/// methods of this class will be called on the browser process UI thread unless
+/// otherwise indicated.
 ///
 /*--cef(source=client)--*/
 class CefViewDelegate : public virtual CefBaseRefCounted {
  public:
   ///
-  // Return the preferred size for |view|. The Layout will use this information
-  // to determine the display size.
+  /// Return the preferred size for |view|. The Layout will use this information
+  /// to determine the display size.
   ///
   /*--cef()--*/
   virtual CefSize GetPreferredSize(CefRefPtr<CefView> view) {
@@ -59,22 +61,22 @@
   }
 
   ///
-  // Return the minimum size for |view|.
+  /// Return the minimum size for |view|.
   ///
   /*--cef()--*/
   virtual CefSize GetMinimumSize(CefRefPtr<CefView> view) { return CefSize(); }
 
   ///
-  // Return the maximum size for |view|.
+  /// Return the maximum size for |view|.
   ///
   /*--cef()--*/
   virtual CefSize GetMaximumSize(CefRefPtr<CefView> view) { return CefSize(); }
 
   ///
-  // Return the height necessary to display |view| with the provided |width|.
-  // If not specified the result of GetPreferredSize().height will be used by
-  // default. Override if |view|'s preferred height depends upon the width
-  // (for example, with Labels).
+  /// Return the height necessary to display |view| with the provided |width|.
+  /// If not specified the result of GetPreferredSize().height will be used by
+  /// default. Override if |view|'s preferred height depends upon the width
+  /// (for example, with Labels).
   ///
   /*--cef()--*/
   virtual int GetHeightForWidth(CefRefPtr<CefView> view, int width) {
@@ -82,11 +84,11 @@
   }
 
   ///
-  // Called when the parent of |view| has changed. If |view| is being added to
-  // |parent| then |added| will be true. If |view| is being removed from
-  // |parent| then |added| will be false. If |view| is being reparented the
-  // remove notification will be sent before the add notification. Do not modify
-  // the view hierarchy in this callback.
+  /// Called when the parent of |view| has changed. If |view| is being added to
+  /// |parent| then |added| will be true. If |view| is being removed from
+  /// |parent| then |added| will be false. If |view| is being reparented the
+  /// remove notification will be sent before the add notification. Do not
+  /// modify the view hierarchy in this callback.
   ///
   /*--cef()--*/
   virtual void OnParentViewChanged(CefRefPtr<CefView> view,
@@ -94,11 +96,11 @@
                                    CefRefPtr<CefView> parent) {}
 
   ///
-  // Called when a child of |view| has changed. If |child| is being added to
-  // |view| then |added| will be true. If |child| is being removed from |view|
-  // then |added| will be false. If |child| is being reparented the remove
-  // notification will be sent to the old parent before the add notification is
-  // sent to the new parent. Do not modify the view hierarchy in this callback.
+  /// Called when a child of |view| has changed. If |child| is being added to
+  /// |view| then |added| will be true. If |child| is being removed from |view|
+  /// then |added| will be false. If |child| is being reparented the remove
+  /// notification will be sent to the old parent before the add notification is
+  /// sent to the new parent. Do not modify the view hierarchy in this callback.
   ///
   /*--cef()--*/
   virtual void OnChildViewChanged(CefRefPtr<CefView> view,
@@ -106,13 +108,26 @@
                                   CefRefPtr<CefView> child) {}
 
   ///
-  // Called when |view| gains focus.
+  /// Called when |view| is added or removed from the CefWindow.
+  ///
+  /*--cef()--*/
+  virtual void OnWindowChanged(CefRefPtr<CefView> view, bool added) {}
+
+  ///
+  /// Called when the layout of |view| has changed.
+  ///
+  /*--cef()--*/
+  virtual void OnLayoutChanged(CefRefPtr<CefView> view,
+                               const CefRect& new_bounds) {}
+
+  ///
+  /// Called when |view| gains focus.
   ///
   /*--cef()--*/
   virtual void OnFocus(CefRefPtr<CefView> view) {}
 
   ///
-  // Called when |view| loses focus.
+  /// Called when |view| loses focus.
   ///
   /*--cef()--*/
   virtual void OnBlur(CefRefPtr<CefView> view) {}
diff --git a/src/include/views/cef_window.h b/src/include/views/cef_window.h
index 2dce068..80a522e 100644
--- a/src/include/views/cef_window.h
+++ b/src/include/views/cef_window.h
@@ -41,180 +41,233 @@
 #include "include/cef_image.h"
 #include "include/cef_menu_model.h"
 #include "include/views/cef_display.h"
+#include "include/views/cef_overlay_controller.h"
 #include "include/views/cef_panel.h"
 #include "include/views/cef_window_delegate.h"
 
+class CefBrowserView;
+
 ///
-// A Window is a top-level Window/widget in the Views hierarchy. By default it
-// will have a non-client area with title bar, icon and buttons that supports
-// moving and resizing. All size and position values are in density independent
-// pixels (DIP) unless otherwise indicated. Methods must be called on the
-// browser process UI thread unless otherwise indicated.
+/// A Window is a top-level Window/widget in the Views hierarchy. By default it
+/// will have a non-client area with title bar, icon and buttons that supports
+/// moving and resizing. All size and position values are in density independent
+/// pixels (DIP) unless otherwise indicated. Methods must be called on the
+/// browser process UI thread unless otherwise indicated.
 ///
 /*--cef(source=library)--*/
 class CefWindow : public CefPanel {
  public:
   ///
-  // Create a new Window.
+  /// Create a new Window.
   ///
   /*--cef(optional_param=delegate)--*/
   static CefRefPtr<CefWindow> CreateTopLevelWindow(
       CefRefPtr<CefWindowDelegate> delegate);
 
   ///
-  // Show the Window.
+  /// Show the Window.
   ///
   /*--cef()--*/
   virtual void Show() = 0;
 
   ///
-  // Hide the Window.
+  /// Show the Window as a browser modal dialog relative to |browser_view|. A
+  /// parent Window must be returned via CefWindowDelegate::GetParentWindow()
+  /// and |browser_view| must belong to that parent Window. While this Window is
+  /// visible, |browser_view| will be disabled while other controls in the
+  /// parent Window remain enabled. Navigating or destroying the |browser_view|
+  /// will close this Window automatically. Alternately, use Show() and return
+  /// true from CefWindowDelegate::IsWindowModalDialog() for a window modal
+  /// dialog where all controls in the parent Window are disabled.
+  ///
+  /*--cef()--*/
+  virtual void ShowAsBrowserModalDialog(
+      CefRefPtr<CefBrowserView> browser_view) = 0;
+
+  ///
+  /// Hide the Window.
   ///
   /*--cef()--*/
   virtual void Hide() = 0;
 
   ///
-  // Sizes the Window to |size| and centers it in the current display.
+  /// Sizes the Window to |size| and centers it in the current display.
   ///
   /*--cef()--*/
   virtual void CenterWindow(const CefSize& size) = 0;
 
   ///
-  // Close the Window.
+  /// Close the Window.
   ///
   /*--cef()--*/
   virtual void Close() = 0;
 
   ///
-  // Returns true if the Window has been closed.
+  /// Returns true if the Window has been closed.
   ///
   /*--cef()--*/
   virtual bool IsClosed() = 0;
 
   ///
-  // Activate the Window, assuming it already exists and is visible.
+  /// Activate the Window, assuming it already exists and is visible.
   ///
   /*--cef()--*/
   virtual void Activate() = 0;
 
   ///
-  // Deactivate the Window, making the next Window in the Z order the active
-  // Window.
+  /// Deactivate the Window, making the next Window in the Z order the active
+  /// Window.
   ///
   /*--cef()--*/
   virtual void Deactivate() = 0;
 
   ///
-  // Returns whether the Window is the currently active Window.
+  /// Returns whether the Window is the currently active Window.
   ///
   /*--cef()--*/
   virtual bool IsActive() = 0;
 
   ///
-  // Bring this Window to the top of other Windows in the Windowing system.
+  /// Bring this Window to the top of other Windows in the Windowing system.
   ///
   /*--cef()--*/
   virtual void BringToTop() = 0;
 
   ///
-  // Set the Window to be on top of other Windows in the Windowing system.
+  /// Set the Window to be on top of other Windows in the Windowing system.
   ///
   /*--cef()--*/
   virtual void SetAlwaysOnTop(bool on_top) = 0;
 
   ///
-  // Returns whether the Window has been set to be on top of other Windows in
-  // the Windowing system.
+  /// Returns whether the Window has been set to be on top of other Windows in
+  /// the Windowing system.
   ///
   /*--cef()--*/
   virtual bool IsAlwaysOnTop() = 0;
 
   ///
-  // Maximize the Window.
+  /// Maximize the Window.
   ///
   /*--cef()--*/
   virtual void Maximize() = 0;
 
   ///
-  // Minimize the Window.
+  /// Minimize the Window.
   ///
   /*--cef()--*/
   virtual void Minimize() = 0;
 
   ///
-  // Restore the Window.
+  /// Restore the Window.
   ///
   /*--cef()--*/
   virtual void Restore() = 0;
 
   ///
-  // Set fullscreen Window state.
+  /// Set fullscreen Window state. The
+  /// CefWindowDelegate::OnWindowFullscreenTransition method will be called
+  /// during the fullscreen transition for notification purposes.
   ///
   /*--cef()--*/
   virtual void SetFullscreen(bool fullscreen) = 0;
 
   ///
-  // Returns true if the Window is maximized.
+  /// Returns true if the Window is maximized.
   ///
   /*--cef()--*/
   virtual bool IsMaximized() = 0;
 
   ///
-  // Returns true if the Window is minimized.
+  /// Returns true if the Window is minimized.
   ///
   /*--cef()--*/
   virtual bool IsMinimized() = 0;
 
   ///
-  // Returns true if the Window is fullscreen.
+  /// Returns true if the Window is fullscreen.
   ///
   /*--cef()--*/
   virtual bool IsFullscreen() = 0;
 
   ///
-  // Set the Window title.
+  /// Set the Window title.
   ///
   /*--cef(optional_param=title)--*/
   virtual void SetTitle(const CefString& title) = 0;
 
   ///
-  // Get the Window title.
+  /// Get the Window title.
   ///
   /*--cef()--*/
   virtual CefString GetTitle() = 0;
 
   ///
-  // Set the Window icon. This should be a 16x16 icon suitable for use in the
-  // Windows's title bar.
+  /// Set the Window icon. This should be a 16x16 icon suitable for use in the
+  /// Windows's title bar.
   ///
   /*--cef()--*/
   virtual void SetWindowIcon(CefRefPtr<CefImage> image) = 0;
 
   ///
-  // Get the Window icon.
+  /// Get the Window icon.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefImage> GetWindowIcon() = 0;
 
   ///
-  // Set the Window App icon. This should be a larger icon for use in the host
-  // environment app switching UI. On Windows, this is the ICON_BIG used in
-  // Alt-Tab list and Windows taskbar. The Window icon will be used by default
-  // if no Window App icon is specified.
+  /// Set the Window App icon. This should be a larger icon for use in the host
+  /// environment app switching UI. On Windows, this is the ICON_BIG used in
+  /// Alt-Tab list and Windows taskbar. The Window icon will be used by default
+  /// if no Window App icon is specified.
   ///
   /*--cef()--*/
   virtual void SetWindowAppIcon(CefRefPtr<CefImage> image) = 0;
 
   ///
-  // Get the Window App icon.
+  /// Get the Window App icon.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefImage> GetWindowAppIcon() = 0;
 
   ///
-  // Show a menu with contents |menu_model|. |screen_point| specifies the menu
-  // position in screen coordinates. |anchor_position| specifies how the menu
-  // will be anchored relative to |screen_point|.
+  /// Add a View that will be overlayed on the Window contents with absolute
+  /// positioning and high z-order. Positioning is controlled by |docking_mode|
+  /// as described below. The returned CefOverlayController object is used to
+  /// control the overlay. Overlays are hidden by default.
+  ///
+  /// With CEF_DOCKING_MODE_CUSTOM:
+  ///   1. The overlay is initially hidden, sized to |view|'s preferred size,
+  ///      and positioned in the top-left corner.
+  ///   2. Optionally change the overlay position and/or size by calling
+  ///      CefOverlayController methods.
+  ///   3. Call CefOverlayController::SetVisible(true) to show the overlay.
+  ///   4. The overlay will be automatically re-sized if |view|'s layout
+  ///      changes. Optionally change the overlay position and/or size when
+  ///      OnLayoutChanged is called on the Window's delegate to indicate a
+  ///      change in Window bounds.
+  ///
+  /// With other docking modes:
+  ///   1. The overlay is initially hidden, sized to |view|'s preferred size,
+  ///      and positioned based on |docking_mode|.
+  ///   2. Call CefOverlayController::SetVisible(true) to show the overlay.
+  ///   3. The overlay will be automatically re-sized if |view|'s layout changes
+  ///      and re-positioned as appropriate when the Window resizes.
+  ///
+  /// Overlays created by this method will receive a higher z-order then any
+  /// child Views added previously. It is therefore recommended to call this
+  /// method last after all other child Views have been added so that the
+  /// overlay displays as the top-most child of the Window.
+  ///
+  /*--cef()--*/
+  virtual CefRefPtr<CefOverlayController> AddOverlayView(
+      CefRefPtr<CefView> view,
+      cef_docking_mode_t docking_mode) = 0;
+
+  ///
+  /// Show a menu with contents |menu_model|. |screen_point| specifies the menu
+  /// position in screen coordinates. |anchor_position| specifies how the menu
+  /// will be anchored relative to |screen_point|.
   ///
   /*--cef()--*/
   virtual void ShowMenu(CefRefPtr<CefMenuModel> menu_model,
@@ -222,93 +275,103 @@
                         cef_menu_anchor_position_t anchor_position) = 0;
 
   ///
-  // Cancel the menu that is currently showing, if any.
+  /// Cancel the menu that is currently showing, if any.
   ///
   /*--cef()--*/
   virtual void CancelMenu() = 0;
 
   ///
-  // Returns the Display that most closely intersects the bounds of this Window.
-  // May return NULL if this Window is not currently displayed.
+  /// Returns the Display that most closely intersects the bounds of this
+  /// Window. May return NULL if this Window is not currently displayed.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefDisplay> GetDisplay() = 0;
 
   ///
-  // Returns the bounds (size and position) of this Window's client area.
-  // Position is in screen coordinates.
+  /// Returns the bounds (size and position) of this Window's client area.
+  /// Position is in screen coordinates.
   ///
   /*--cef()--*/
   virtual CefRect GetClientAreaBoundsInScreen() = 0;
 
   ///
-  // Set the regions where mouse events will be intercepted by this Window to
-  // support drag operations. Call this method with an empty vector to clear the
-  // draggable regions. The draggable region bounds should be in window
-  // coordinates.
+  /// Set the regions where mouse events will be intercepted by this Window to
+  /// support drag operations. Call this method with an empty vector to clear
+  /// the draggable regions. The draggable region bounds should be in window
+  /// coordinates.
   ///
   /*--cef(optional_param=regions)--*/
   virtual void SetDraggableRegions(
       const std::vector<CefDraggableRegion>& regions) = 0;
 
   ///
-  // Retrieve the platform window handle for this Window.
+  /// Retrieve the platform window handle for this Window.
   ///
   /*--cef()--*/
   virtual CefWindowHandle GetWindowHandle() = 0;
 
   ///
-  // Simulate a key press. |key_code| is the VKEY_* value from Chromium's
-  // ui/events/keycodes/keyboard_codes.h header (VK_* values on Windows).
-  // |event_flags| is some combination of EVENTFLAG_SHIFT_DOWN,
-  // EVENTFLAG_CONTROL_DOWN and/or EVENTFLAG_ALT_DOWN. This method is exposed
-  // primarily for testing purposes.
+  /// Simulate a key press. |key_code| is the VKEY_* value from Chromium's
+  /// ui/events/keycodes/keyboard_codes.h header (VK_* values on Windows).
+  /// |event_flags| is some combination of EVENTFLAG_SHIFT_DOWN,
+  /// EVENTFLAG_CONTROL_DOWN and/or EVENTFLAG_ALT_DOWN. This method is exposed
+  /// primarily for testing purposes.
   ///
   /*--cef()--*/
-  virtual void SendKeyPress(int key_code, uint32 event_flags) = 0;
+  virtual void SendKeyPress(int key_code, uint32_t event_flags) = 0;
 
   ///
-  // Simulate a mouse move. The mouse cursor will be moved to the specified
-  // (screen_x, screen_y) position. This method is exposed primarily for testing
-  // purposes.
+  /// Simulate a mouse move. The mouse cursor will be moved to the specified
+  /// (screen_x, screen_y) position. This method is exposed primarily for
+  /// testing purposes.
   ///
   /*--cef()--*/
   virtual void SendMouseMove(int screen_x, int screen_y) = 0;
 
   ///
-  // Simulate mouse down and/or mouse up events. |button| is the mouse button
-  // type. If |mouse_down| is true a mouse down event will be sent. If
-  // |mouse_up| is true a mouse up event will be sent. If both are true a mouse
-  // down event will be sent followed by a mouse up event (equivalent to
-  // clicking the mouse button). The events will be sent using the current
-  // cursor position so make sure to call SendMouseMove() first to position the
-  // mouse. This method is exposed primarily for testing purposes.
+  /// Simulate mouse down and/or mouse up events. |button| is the mouse button
+  /// type. If |mouse_down| is true a mouse down event will be sent. If
+  /// |mouse_up| is true a mouse up event will be sent. If both are true a mouse
+  /// down event will be sent followed by a mouse up event (equivalent to
+  /// clicking the mouse button). The events will be sent using the current
+  /// cursor position so make sure to call SendMouseMove() first to position the
+  /// mouse. This method is exposed primarily for testing purposes.
   ///
   /*--cef()--*/
   virtual void SendMouseEvents(cef_mouse_button_type_t button,
                                bool mouse_down,
                                bool mouse_up) = 0;
+
   ///
-  // Set the keyboard accelerator for the specified |command_id|. |key_code| can
-  // be any virtual key or character value. CefWindowDelegate::OnAccelerator
-  // will be called if the keyboard combination is triggered while this window
-  // has focus.
+  /// Set the keyboard accelerator for the specified |command_id|. |key_code|
+  /// can be any virtual key or character value. Required modifier keys are
+  /// specified by |shift_pressed|, |ctrl_pressed| and/or |alt_pressed|.
+  /// CefWindowDelegate::OnAccelerator will be called if the keyboard
+  /// combination is triggered while this window has focus.
+  ///
+  /// The |high_priority| value will be considered if a child CefBrowserView has
+  /// focus when the keyboard combination is triggered. If |high_priority| is
+  /// true then the key event will not be forwarded to the web content
+  /// (`keydown` event handler) or CefKeyboardHandler first. If |high_priority|
+  /// is false then the behavior will depend on the
+  /// CefBrowserView::SetPreferAccelerators configuration.
   ///
   /*--cef()--*/
   virtual void SetAccelerator(int command_id,
                               int key_code,
                               bool shift_pressed,
                               bool ctrl_pressed,
-                              bool alt_pressed) = 0;
+                              bool alt_pressed,
+                              bool high_priority) = 0;
 
   ///
-  // Remove the keyboard accelerator for the specified |command_id|.
+  /// Remove the keyboard accelerator for the specified |command_id|.
   ///
   /*--cef()--*/
   virtual void RemoveAccelerator(int command_id) = 0;
 
   ///
-  // Remove all keyboard accelerators.
+  /// Remove all keyboard accelerators.
   ///
   /*--cef()--*/
   virtual void RemoveAllAccelerators() = 0;
diff --git a/src/include/views/cef_window_delegate.h b/src/include/views/cef_window_delegate.h
index a145782..6c0f239 100644
--- a/src/include/views/cef_window_delegate.h
+++ b/src/include/views/cef_window_delegate.h
@@ -43,33 +43,67 @@
 class CefWindow;
 
 ///
-// Implement this interface to handle window events. The methods of this class
-// will be called on the browser process UI thread unless otherwise indicated.
+/// Implement this interface to handle window events. The methods of this class
+/// will be called on the browser process UI thread unless otherwise indicated.
 ///
 /*--cef(source=client)--*/
 class CefWindowDelegate : public CefPanelDelegate {
  public:
   ///
-  // Called when |window| is created.
+  /// Called when |window| is created.
   ///
   /*--cef()--*/
   virtual void OnWindowCreated(CefRefPtr<CefWindow> window) {}
 
   ///
-  // Called when |window| is destroyed. Release all references to |window| and
-  // do not attempt to execute any methods on |window| after this callback
-  // returns.
+  /// Called when |window| is closing.
+  ///
+  /*--cef()--*/
+  virtual void OnWindowClosing(CefRefPtr<CefWindow> window) {}
+
+  ///
+  /// Called when |window| is destroyed. Release all references to |window| and
+  /// do not attempt to execute any methods on |window| after this callback
+  /// returns.
   ///
   /*--cef()--*/
   virtual void OnWindowDestroyed(CefRefPtr<CefWindow> window) {}
 
   ///
-  // Return the parent for |window| or NULL if the |window| does not have a
-  // parent. Windows with parents will not get a taskbar button. Set |is_menu|
-  // to true if |window| will be displayed as a menu, in which case it will not
-  // be clipped to the parent window bounds. Set |can_activate_menu| to false
-  // if |is_menu| is true and |window| should not be activated (given keyboard
-  // focus) when displayed.
+  /// Called when |window| is activated or deactivated.
+  ///
+  /*--cef()--*/
+  virtual void OnWindowActivationChanged(CefRefPtr<CefWindow> window,
+                                         bool active) {}
+
+  ///
+  /// Called when |window| bounds have changed. |new_bounds| will be in DIP
+  /// screen coordinates.
+  ///
+  /*--cef()--*/
+  virtual void OnWindowBoundsChanged(CefRefPtr<CefWindow> window,
+                                     const CefRect& new_bounds) {}
+
+  ///
+  /// Called when |window| is transitioning to or from fullscreen mode. On MacOS
+  /// the transition occurs asynchronously with |is_competed| set to false when
+  /// the transition starts and true after the transition completes. On other
+  /// platforms the transition occurs synchronously with |is_completed| set to
+  /// true after the transition completes. With the Alloy runtime you must also
+  /// implement CefDisplayHandler::OnFullscreenModeChange to handle fullscreen
+  /// transitions initiated by browser content.
+  ///
+  /*--cef()--*/
+  virtual void OnWindowFullscreenTransition(CefRefPtr<CefWindow> window,
+                                            bool is_completed) {}
+
+  ///
+  /// Return the parent for |window| or NULL if the |window| does not have a
+  /// parent. Windows with parents will not get a taskbar button. Set |is_menu|
+  /// to true if |window| will be displayed as a menu, in which case it will not
+  /// be clipped to the parent window bounds. Set |can_activate_menu| to false
+  /// if |is_menu| is true and |window| should not be activated (given keyboard
+  /// focus) when displayed.
   ///
   /*--cef()--*/
   virtual CefRefPtr<CefWindow> GetParentWindow(CefRefPtr<CefWindow> window,
@@ -79,42 +113,99 @@
   }
 
   ///
-  // Return true if |window| should be created without a frame or title bar. The
-  // window will be resizable if CanResize() returns true. Use
-  // CefWindow::SetDraggableRegions() to specify draggable regions.
+  /// Return true if |window| should be created as a window modal dialog. Only
+  /// called when a Window is returned via GetParentWindow() with |is_menu| set
+  /// to false. All controls in the parent Window will be disabled while
+  /// |window| is visible. This functionality is not supported by all Linux
+  /// window managers. Alternately, use CefWindow::ShowAsBrowserModalDialog()
+  /// for a browser modal dialog that works on all platforms.
+  ///
+  /*--cef()--*/
+  virtual bool IsWindowModalDialog(CefRefPtr<CefWindow> window) {
+    return false;
+  }
+
+  ///
+  /// Return the initial bounds for |window| in density independent pixel (DIP)
+  /// coordinates. If this method returns an empty CefRect then
+  /// GetPreferredSize() will be called to retrieve the size, and the window
+  /// will be placed on the screen with origin (0,0). This method can be used in
+  /// combination with CefView::GetBoundsInScreen() to restore the previous
+  /// window bounds.
+  ///
+  /*--cef()--*/
+  virtual CefRect GetInitialBounds(CefRefPtr<CefWindow> window) {
+    return CefRect();
+  }
+
+  ///
+  /// Return the initial show state for |window|.
+  ///
+  /*--cef(default_retval=CEF_SHOW_STATE_NORMAL)--*/
+  virtual cef_show_state_t GetInitialShowState(CefRefPtr<CefWindow> window) {
+    return CEF_SHOW_STATE_NORMAL;
+  }
+
+  ///
+  /// Return true if |window| should be created without a frame or title bar.
+  /// The window will be resizable if CanResize() returns true. Use
+  /// CefWindow::SetDraggableRegions() to specify draggable regions.
   ///
   /*--cef()--*/
   virtual bool IsFrameless(CefRefPtr<CefWindow> window) { return false; }
 
   ///
-  // Return true if |window| can be resized.
+  /// Return true if |window| should be created with standard window buttons
+  /// like close, minimize and zoom. This method is only supported on macOS.
+  ///
+  /*--cef()--*/
+  virtual bool WithStandardWindowButtons(CefRefPtr<CefWindow> window) {
+    return !IsFrameless(window);
+  }
+
+  ///
+  /// Return whether the titlebar height should be overridden,
+  /// and sets the height of the titlebar in |titlebar_height|.
+  /// On macOS, it can also be used to adjust the vertical position
+  /// of the traffic light buttons in frameless windows.
+  /// The buttons will be positioned halfway down the titlebar
+  /// at a height of |titlebar_height| / 2.
+  ///
+  /*--cef()--*/
+  virtual bool GetTitlebarHeight(CefRefPtr<CefWindow> window,
+                                 float* titlebar_height) {
+    return false;
+  }
+
+  ///
+  /// Return true if |window| can be resized.
   ///
   /*--cef()--*/
   virtual bool CanResize(CefRefPtr<CefWindow> window) { return true; }
 
   ///
-  // Return true if |window| can be maximized.
+  /// Return true if |window| can be maximized.
   ///
   /*--cef()--*/
   virtual bool CanMaximize(CefRefPtr<CefWindow> window) { return true; }
 
   ///
-  // Return true if |window| can be minimized.
+  /// Return true if |window| can be minimized.
   ///
   /*--cef()--*/
   virtual bool CanMinimize(CefRefPtr<CefWindow> window) { return true; }
 
   ///
-  // Return true if |window| can be closed. This will be called for user-
-  // initiated window close actions and when CefWindow::Close() is called.
+  /// Return true if |window| can be closed. This will be called for user-
+  /// initiated window close actions and when CefWindow::Close() is called.
   ///
   /*--cef()--*/
   virtual bool CanClose(CefRefPtr<CefWindow> window) { return true; }
 
   ///
-  // Called when a keyboard accelerator registered with
-  // CefWindow::SetAccelerator is triggered. Return true if the accelerator was
-  // handled or false otherwise.
+  /// Called when a keyboard accelerator registered with
+  /// CefWindow::SetAccelerator is triggered. Return true if the accelerator was
+  /// handled or false otherwise.
   ///
   /*--cef()--*/
   virtual bool OnAccelerator(CefRefPtr<CefWindow> window, int command_id) {
@@ -122,9 +213,9 @@
   }
 
   ///
-  // Called after all other controls in the window have had a chance to
-  // handle the event. |event| contains information about the keyboard event.
-  // Return true if the keyboard event was handled or false otherwise.
+  /// Called after all other controls in the window have had a chance to
+  /// handle the event. |event| contains information about the keyboard event.
+  /// Return true if the keyboard event was handled or false otherwise.
   ///
   /*--cef()--*/
   virtual bool OnKeyEvent(CefRefPtr<CefWindow> window,
diff --git a/src/include/wrapper/cef_byte_read_handler.h b/src/include/wrapper/cef_byte_read_handler.h
index bf593d0..5dd0416 100644
--- a/src/include/wrapper/cef_byte_read_handler.h
+++ b/src/include/wrapper/cef_byte_read_handler.h
@@ -38,42 +38,43 @@
 #pragma once
 
 #include "include/base/cef_lock.h"
-#include "include/base/cef_macros.h"
 #include "include/cef_base.h"
 #include "include/cef_stream.h"
 
 ///
-// Thread safe implementation of the CefReadHandler class for reading an
-// in-memory array of bytes.
+/// Thread safe implementation of the CefReadHandler class for reading an
+/// in-memory array of bytes.
 ///
 class CefByteReadHandler : public CefReadHandler {
  public:
   ///
-  // Create a new object for reading an array of bytes. An optional |source|
-  // reference can be kept to keep the underlying data source from being
-  // released while the reader exists.
+  /// Create a new object for reading an array of bytes. An optional |source|
+  /// reference can be kept to keep the underlying data source from being
+  /// released while the reader exists.
   ///
   CefByteReadHandler(const unsigned char* bytes,
                      size_t size,
                      CefRefPtr<CefBaseRefCounted> source);
 
+  CefByteReadHandler(const CefByteReadHandler&) = delete;
+  CefByteReadHandler& operator=(const CefByteReadHandler&) = delete;
+
   // CefReadHandler methods.
-  virtual size_t Read(void* ptr, size_t size, size_t n) OVERRIDE;
-  virtual int Seek(int64 offset, int whence) OVERRIDE;
-  virtual int64 Tell() OVERRIDE;
-  virtual int Eof() OVERRIDE;
-  virtual bool MayBlock() OVERRIDE { return false; }
+  virtual size_t Read(void* ptr, size_t size, size_t n) override;
+  virtual int Seek(int64_t offset, int whence) override;
+  virtual int64_t Tell() override;
+  virtual int Eof() override;
+  virtual bool MayBlock() override { return false; }
 
  private:
   const unsigned char* bytes_;
-  int64 size_;
-  int64 offset_;
+  int64_t size_;
+  int64_t offset_;
   CefRefPtr<CefBaseRefCounted> source_;
 
   base::Lock lock_;
 
   IMPLEMENT_REFCOUNTING(CefByteReadHandler);
-  DISALLOW_COPY_AND_ASSIGN(CefByteReadHandler);
 };
 
 #endif  // CEF_INCLUDE_WRAPPER_CEF_BYTE_READ_HANDLER_H_
diff --git a/src/include/wrapper/cef_closure_task.h b/src/include/wrapper/cef_closure_task.h
index 71f54b5..95dde6a 100644
--- a/src/include/wrapper/cef_closure_task.h
+++ b/src/include/wrapper/cef_closure_task.h
@@ -38,65 +38,80 @@
 #pragma once
 
 #include "include/base/cef_callback_forward.h"
-#include "include/base/cef_macros.h"
 #include "include/cef_task.h"
 
 ///
-// Helpers for asynchronously executing a base::Closure (bound function or
-// method) on a CEF thread. Creation of base::Closures can be facilitated using
-// base::Bind. See include/base/cef_callback.h for complete usage instructions.
-//
-// TO use these helpers you should include this header and the header that
-// defines base::Bind.
-//
-// #include "include/base/cef_bind.h"
-// #include "include/wrapper/cef_closure_task.h"
-//
-// Example of executing a bound function:
-//
-// // Define a function.
-// void MyFunc(int arg) { /* do something with |arg| on the UI thread */ }
-//
-// // Post a task that will execute MyFunc on the UI thread and pass an |arg|
-// // value of 5.
-// CefPostTask(TID_UI, base::Bind(&MyFunc, 5));
-//
-// Example of executing a bound method:
-//
-// // Define a class.
-// class MyClass : public CefBaseRefCounted {
-//  public:
-//   MyClass() {}
-//   void MyMethod(int arg) { /* do something with |arg| on the UI thread */ }
-//  private:
-//   IMPLEMENT_REFCOUNTING(MyClass);
-// };
-//
-// // Create an instance of MyClass.
-// CefRefPtr<MyClass> instance = new MyClass();
-//
-// // Post a task that will execute MyClass::MyMethod on the UI thread and pass
-// // an |arg| value of 5. |instance| will be kept alive until after the task
-// // completes.
-// CefPostTask(TID_UI, base::Bind(&MyClass::MyMethod, instance, 5));
+/// \file
+/// Helpers for asynchronously executing a base::[Once|Repeating]Closure (bound
+/// function or method) on a CEF thread. Creation of a
+/// base::[Once|Repeating]Closure can be facilitated using
+/// base::Bind[Once|Repeating]. See include/base/cef_callback.h for complete
+/// usage instructions.
+///
+/// To use these helpers you should include this header and the header that
+/// defines base::Bind[Once|Repeating].
+///
+/// <pre>
+///   #include "include/base/cef_callback.h"
+///   #include "include/wrapper/cef_closure_task.h"
+/// </pre>
+///
+/// Example of executing a bound function:
+///
+/// <pre>
+///   // Define a function.
+///   void MyFunc(int arg) { /* do something with |arg| on the UI thread */ }
+///
+///   // Post a task that will execute MyFunc on the UI thread and pass an |arg|
+///   // value of 5.
+///   CefPostTask(TID_UI, base::BindOnce(&MyFunc, 5));
+/// </pre>
+///
+/// Example of executing a bound method:
+///
+/// <pre>
+///   // Define a class.
+///   class MyClass : public CefBaseRefCounted {
+///    public:
+///     MyClass() {}
+///     void MyMethod(int arg) { /* do something with |arg| on the UI thread */
+///     }
+///    private:
+///     IMPLEMENT_REFCOUNTING(MyClass);
+///   };
+///
+///   // Create an instance of MyClass.
+///   CefRefPtr<MyClass> instance = new MyClass();
+///
+///   // Post a task that will execute MyClass::MyMethod on the UI thread and
+///   // pass an |arg| value of 5. |instance| will be kept alive until after the
+///   // task completes.
+///   CefPostTask(TID_UI, base::BindOnce(&MyClass::MyMethod, instance, 5));
+/// </pre>
 ///
 
 ///
-// Create a CefTask that wraps a base::Closure. Can be used in combination with
-// CefTaskRunner.
+/// Create a CefTask that wraps a base::[Once|Repeating]Closure. Can be used in
+/// combination with CefTaskRunner.
 ///
-CefRefPtr<CefTask> CefCreateClosureTask(const base::Closure& closure);
+CefRefPtr<CefTask> CefCreateClosureTask(base::OnceClosure closure);
+CefRefPtr<CefTask> CefCreateClosureTask(const base::RepeatingClosure& closure);
 
 ///
-// Post a Closure for execution on the specified thread.
+/// Post a base::[Once|Repeating]Closure for execution on the specified thread.
 ///
-bool CefPostTask(CefThreadId threadId, const base::Closure& closure);
+bool CefPostTask(CefThreadId threadId, base::OnceClosure closure);
+bool CefPostTask(CefThreadId threadId, const base::RepeatingClosure& closure);
 
 ///
-// Post a Closure for delayed execution on the specified thread.
+/// Post a base::[Once|Repeating]Closure for delayed execution on the specified
+/// thread.
 ///
 bool CefPostDelayedTask(CefThreadId threadId,
-                        const base::Closure& closure,
-                        int64 delay_ms);
+                        base::OnceClosure closure,
+                        int64_t delay_ms);
+bool CefPostDelayedTask(CefThreadId threadId,
+                        const base::RepeatingClosure& closure,
+                        int64_t delay_ms);
 
 #endif  // CEF_INCLUDE_WRAPPER_CEF_CLOSURE_TASK_H_
diff --git a/src/include/wrapper/cef_helpers.h b/src/include/wrapper/cef_helpers.h
index 93c4a51..4917c88 100644
--- a/src/include/wrapper/cef_helpers.h
+++ b/src/include/wrapper/cef_helpers.h
@@ -43,34 +43,41 @@
 
 #include "include/base/cef_bind.h"
 #include "include/base/cef_logging.h"
-#include "include/base/cef_macros.h"
 #include "include/cef_task.h"
 
 #define CEF_REQUIRE_UI_THREAD() DCHECK(CefCurrentlyOn(TID_UI));
 #define CEF_REQUIRE_IO_THREAD() DCHECK(CefCurrentlyOn(TID_IO));
-#define CEF_REQUIRE_FILE_THREAD() DCHECK(CefCurrentlyOn(TID_FILE));
+#define CEF_REQUIRE_FILE_BACKGROUND_THREAD() \
+  DCHECK(CefCurrentlyOn(TID_FILE_BACKGROUND));
+#define CEF_REQUIRE_FILE_USER_VISIBLE_THREAD() \
+  DCHECK(CefCurrentlyOn(TID_FILE_USER_VISIBLE));
+#define CEF_REQUIRE_FILE_USER_BLOCKING_THREAD() \
+  DCHECK(CefCurrentlyOn(TID_FILE_USER_BLOCKING));
 #define CEF_REQUIRE_RENDERER_THREAD() DCHECK(CefCurrentlyOn(TID_RENDERER));
 
-// Use this struct in conjuction with refcounted types to ensure that an
-// object is deleted on the specified thread. For example:
-//
-// class Foo : public base::RefCountedThreadSafe<Foo, CefDeleteOnUIThread> {
-//  public:
-//   Foo();
-//   void DoSomething();
-//
-//  private:
-//   // Allow deletion via scoped_refptr only.
-//   friend struct CefDeleteOnThread<TID_UI>;
-//   friend class base::RefCountedThreadSafe<Foo, CefDeleteOnUIThread>;
-//
-//   virtual ~Foo() {}
-// };
-//
-// base::scoped_refptr<Foo> foo = new Foo();
-// foo->DoSomething();
-// foo = NULL;  // Deletion of |foo| will occur on the UI thread.
-//
+///
+/// Use this struct in conjuction with refcounted types to ensure that an
+/// object is deleted on the specified thread. For example:
+///
+/// <pre>
+///   class Foo : public base::RefCountedThreadSafe<Foo, CefDeleteOnUIThread> {
+///    public:
+///     Foo();
+///     void DoSomething();
+///
+///    private:
+///     // Allow deletion via scoped_refptr only.
+///     friend struct CefDeleteOnThread<TID_UI>;
+///     friend class base::RefCountedThreadSafe<Foo, CefDeleteOnUIThread>;
+///
+///     virtual ~Foo() {}
+///   };
+///
+///   base::scoped_refptr<Foo> foo = new Foo();
+///   foo->DoSomething();
+///   foo = NULL;  /// Deletion of |foo| will occur on the UI thread.
+/// </pre>
+///
 template <CefThreadId thread>
 struct CefDeleteOnThread {
   template <typename T>
@@ -79,18 +86,53 @@
       delete x;
     } else {
       CefPostTask(thread,
-                  base::Bind(&CefDeleteOnThread<thread>::Destruct<T>, x));
+                  base::BindOnce(&CefDeleteOnThread<thread>::Destruct<T>,
+                                 base::Unretained(x)));
     }
   }
 };
 
 struct CefDeleteOnUIThread : public CefDeleteOnThread<TID_UI> {};
 struct CefDeleteOnIOThread : public CefDeleteOnThread<TID_IO> {};
-struct CefDeleteOnFileThread : public CefDeleteOnThread<TID_FILE> {};
+struct CefDeleteOnFileBackgroundThread
+    : public CefDeleteOnThread<TID_FILE_BACKGROUND> {};
+struct CefDeleteOnFileUserVisibleThread
+    : public CefDeleteOnThread<TID_FILE_USER_VISIBLE> {};
+struct CefDeleteOnFileUserBlockingThread
+    : public CefDeleteOnThread<TID_FILE_USER_BLOCKING> {};
 struct CefDeleteOnRendererThread : public CefDeleteOnThread<TID_RENDERER> {};
 
+// Same as IMPLEMENT_REFCOUNTING() but using the specified Destructor.
+#define IMPLEMENT_REFCOUNTING_EX(ClassName, Destructor) \
+ public:                                                \
+  void AddRef() const override {                        \
+    ref_count_.AddRef();                                \
+  }                                                     \
+  bool Release() const override {                       \
+    if (ref_count_.Release()) {                         \
+      Destructor::Destruct(this);                       \
+      return true;                                      \
+    }                                                   \
+    return false;                                       \
+  }                                                     \
+  bool HasOneRef() const override {                     \
+    return ref_count_.HasOneRef();                      \
+  }                                                     \
+  bool HasAtLeastOneRef() const override {              \
+    return ref_count_.HasAtLeastOneRef();               \
+  }                                                     \
+                                                        \
+ private:                                               \
+  CefRefCount ref_count_
+
+#define IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(ClassName) \
+  IMPLEMENT_REFCOUNTING_EX(ClassName, CefDeleteOnUIThread)
+
+#define IMPLEMENT_REFCOUNTING_DELETE_ON_IOT(ClassName) \
+  IMPLEMENT_REFCOUNTING_EX(ClassName, CefDeleteOnIOThread)
+
 ///
-// Helper class to manage a scoped copy of |argv|.
+/// Helper class to manage a scoped copy of |argv|.
 ///
 class CefScopedArgArray {
  public:
@@ -104,6 +146,10 @@
     }
     array_[argc] = NULL;
   }
+
+  CefScopedArgArray(const CefScopedArgArray&) = delete;
+  CefScopedArgArray& operator=(const CefScopedArgArray&) = delete;
+
   ~CefScopedArgArray() { delete[] array_; }
 
   char** array() const { return array_; }
@@ -114,8 +160,6 @@
   // Keep values in a vector separate from |array_| because various users may
   // modify |array_| and we still want to clean up memory properly.
   std::vector<std::string> values_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefScopedArgArray);
 };
 
 #endif  // CEF_INCLUDE_WRAPPER_CEF_HELPERS_H_
diff --git a/src/include/wrapper/cef_library_loader.h b/src/include/wrapper/cef_library_loader.h
index c15b855..4fa8343 100644
--- a/src/include/wrapper/cef_library_loader.h
+++ b/src/include/wrapper/cef_library_loader.h
@@ -36,82 +36,88 @@
 #ifdef __cplusplus
 #include <string>
 
-#include "include/base/cef_macros.h"
-
 extern "C" {
 #endif  // __cplusplus
 
 ///
-// Load the CEF library at the specified |path|. Returns true (1) on
-// success and false (0) on failure.
+/// Load the CEF library at the specified |path|. Returns true (1) on
+/// success and false (0) on failure.
 ///
 int cef_load_library(const char* path);
 
 ///
-// Unload the CEF library that was previously loaded. Returns true (1)
-// on success and false (0) on failure.
+/// Unload the CEF library that was previously loaded. Returns true (1)
+/// on success and false (0) on failure.
 ///
-int cef_unload_library();
+int cef_unload_library(void);
 
 #ifdef __cplusplus
 }
 
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
 
 ///
-// Scoped helper for loading and unloading the CEF framework library at
-// runtime from the expected location in the app bundle. Loading at runtime
-// instead of linking directly is a requirement of the macOS sandbox
-// implementation.
-//
-// Example usage in the main process:
-//
-//   #include "include/wrapper/cef_library_loader.h"
-//
-//   int main(int argc, char* argv[]) {
-//     // Dynamically load the CEF framework library.
-//     CefScopedLibraryLoader library_loader;
-//     if (!library_loader.LoadInMain())
-//       return 1;
-//
-//     // Continue with CEF initialization...
-//   }
-//
-// Example usage in the helper process:
-//
-//   #include "include/cef_sandbox_mac.h"
-//   #include "include/wrapper/cef_library_loader.h"
-//
-//   int main(int argc, char* argv[]) {
-//     // Initialize the macOS sandbox for this helper process.
-//     CefScopedSandboxContext sandbox_context;
-//     if (!sandbox_context.Initialize(argc, argv))
-//       return 1;
-//
-//     // Dynamically load the CEF framework library.
-//     CefScopedLibraryLoader library_loader;
-//     if (!library_loader.LoadInHelper())
-//       return 1;
-//
-//     // Continue with CEF initialization...
-//   }
+/// Scoped helper for loading and unloading the CEF framework library at
+/// runtime from the expected location in the app bundle. Loading at runtime
+/// instead of linking directly is a requirement of the macOS sandbox
+/// implementation.
+///
+/// Example usage in the main process:
+///
+/// <pre>
+///   #include "include/wrapper/cef_library_loader.h"
+///
+///   int main(int argc, char* argv[]) {
+///     // Dynamically load the CEF framework library.
+///     CefScopedLibraryLoader library_loader;
+///     if (!library_loader.LoadInMain())
+///       return 1;
+///
+///     // Continue with CEF initialization...
+///   }
+/// </pre>
+///
+/// Example usage in the helper process:
+///
+/// <pre>
+///   #include "include/cef_sandbox_mac.h"
+///   #include "include/wrapper/cef_library_loader.h"
+///
+///   int main(int argc, char* argv[]) {
+///     // Initialize the macOS sandbox for this helper process.
+///     CefScopedSandboxContext sandbox_context;
+///     if (!sandbox_context.Initialize(argc, argv))
+///       return 1;
+///
+///     // Dynamically load the CEF framework library.
+///     CefScopedLibraryLoader library_loader;
+///     if (!library_loader.LoadInHelper())
+///       return 1;
+///
+///     // Continue with CEF initialization...
+///   }
+/// </pre>
 ///
 class CefScopedLibraryLoader {
  public:
   CefScopedLibraryLoader();
+
+  CefScopedLibraryLoader(const CefScopedLibraryLoader&) = delete;
+  CefScopedLibraryLoader& operator=(const CefScopedLibraryLoader&) = delete;
+
   ~CefScopedLibraryLoader();
 
   ///
-  // Load the CEF framework in the main process from the expected app
-  // bundle location relative to the executable. Returns true if the
-  // load succeeds.
+  /// Load the CEF framework in the main process from the expected app
+  /// bundle location relative to the executable. Returns true if the
+  /// load succeeds.
   ///
   bool LoadInMain() { return Load(false); }
 
   ///
-  // Load the CEF framework in the helper process from the expected app
-  // bundle location relative to the executable. Returns true if the
-  // load succeeds.
+  /// Load the CEF framework in the helper process from the expected app
+  /// bundle location relative to the executable. Returns true if the
+  /// load succeeds.
   ///
   bool LoadInHelper() { return Load(true); }
 
@@ -119,10 +125,9 @@
   bool Load(bool helper);
 
   bool loaded_;
-  DISALLOW_COPY_AND_ASSIGN(CefScopedLibraryLoader);
 };
 
-#endif  // defined(OS_MACOSX)
+#endif  // defined(OS_MAC)
 #endif  // __cplusplus
 
 #endif  // CEF_INCLUDE_WRAPPER_CEF_LIBRARY_LOADER_H_
diff --git a/src/include/wrapper/cef_message_router.h b/src/include/wrapper/cef_message_router.h
index 9344222..6897603 100644
--- a/src/include/wrapper/cef_message_router.h
+++ b/src/include/wrapper/cef_message_router.h
@@ -46,7 +46,7 @@
 // The below classes implement support for routing aynchronous messages between
 // JavaScript running in the renderer process and C++ running in the browser
 // process. An application interacts with the router by passing it data from
-// standard CEF C++ callbacks (OnBeforeBrowse, OnProcessMessageRecieved,
+// standard CEF C++ callbacks (OnBeforeBrowse, OnProcessMessageReceived,
 // OnContextCreated, etc). The renderer-side router supports generic JavaScript
 // callback registration and execution while the browser-side router supports
 // application-specific logic via one or more application-provided Handler
@@ -78,7 +78,7 @@
 // with an error code of -1.
 //
 // Queries can be either persistent or non-persistent. If the query is
-// persistent than the callbacks will remain registered until one of the
+// persistent then the callbacks will remain registered until one of the
 // following conditions are met:
 //
 // A. The query is canceled in JavaScript using the |window.cefQueryCancel|
@@ -177,7 +177,7 @@
 // 8. Handle the query in your Handler::OnQuery implementation and execute the
 //    appropriate callback either immediately or asynchronously.
 //
-//    void MyHandler::OnQuery(int64 query_id,
+//    void MyHandler::OnQuery(int64_t query_id,
 //                            CefRefPtr<CefBrowser> browser,
 //                            CefRefPtr<CefFrame> frame,
 //                            const CefString& request,
@@ -193,73 +193,122 @@
 // 9. Notice that the onSuccess callback is executed in JavaScript.
 
 ///
-// Used to configure the query router. The same values must be passed to both
-// CefMessageRouterBrowserSide and CefMessageRouterRendererSide. If using
-// multiple router pairs make sure to choose values that do not conflict.
+/// Used to configure the query router. The same values must be passed to both
+/// CefMessageRouterBrowserSide and CefMessageRouterRendererSide. If using
+/// multiple router pairs make sure to choose values that do not conflict.
 ///
 struct CefMessageRouterConfig {
   CefMessageRouterConfig();
 
-  // Name of the JavaScript function that will be added to the 'window' object
-  // for sending a query. The default value is "cefQuery".
+  ///
+  /// Name of the JavaScript function that will be added to the 'window' object
+  /// for sending a query. The default value is "cefQuery".
+  ///
   CefString js_query_function;
 
-  // Name of the JavaScript function that will be added to the 'window' object
-  // for canceling a pending query. The default value is "cefQueryCancel".
+  ///
+  /// Name of the JavaScript function that will be added to the 'window' object
+  /// for canceling a pending query. The default value is "cefQueryCancel".
+  ///
   CefString js_cancel_function;
+
+  ///
+  /// Messages of size (in bytes) larger than this threshold will be sent via
+  /// shared memory region.
+  ///
+  size_t message_size_threshold;
 };
 
 ///
-// Implements the browser side of query routing. The methods of this class may
-// be called on any browser process thread unless otherwise indicated.
+/// This class acts as a container for managing binary data. It retains
+/// references to the underlying backing store, ensuring it is valid as long as
+/// the CefBinaryBuffer exists. This allows efficient, zero-copy access to data
+/// received from another process.
+///
+/// This class is not designed to be thread-safe, and it is the user's
+/// responsibility to synchronize access from multiple threads to ensure data
+/// integrity.
+///
+class CefBinaryBuffer : public CefBaseRefCounted {
+ public:
+  ///
+  /// Returns the read-only pointer to the memory. Returns nullptr if
+  /// |GetSize()| returns zero. The returned pointer is only valid for the life
+  /// span of this object.
+  ///
+  virtual const void* GetData() const = 0;
+
+  ///
+  /// Returns the writable pointer to the memory. Returns nullptr if
+  /// |GetSize()| returns zero. The returned pointer is only valid for the life
+  /// span of this object.
+  ///
+  virtual void* GetData() = 0;
+
+  ///
+  /// Returns the size of the data.
+  ///
+  virtual size_t GetSize() const = 0;
+};
+
+///
+/// Implements the browser side of query routing. The methods of this class may
+/// be called on any browser process thread unless otherwise indicated.
 ///
 class CefMessageRouterBrowserSide
     : public base::RefCountedThreadSafe<CefMessageRouterBrowserSide> {
  public:
   ///
-  // Callback associated with a single pending asynchronous query. Execute the
-  // Success or Failure method to send an asynchronous response to the
-  // associated JavaScript handler. It is a runtime error to destroy a Callback
-  // object associated with an uncanceled query without first executing one of
-  // the callback methods. The methods of this class may be called on any
-  // browser process thread.
+  /// Callback associated with a single pending asynchronous query. Execute the
+  /// Success or Failure method to send an asynchronous response to the
+  /// associated JavaScript handler. It is a runtime error to destroy a Callback
+  /// object associated with an uncanceled query without first executing one of
+  /// the callback methods. The methods of this class may be called on any
+  /// browser process thread.
   ///
   class Callback : public CefBaseRefCounted {
    public:
     ///
-    // Notify the associated JavaScript onSuccess callback that the query has
-    // completed successfully with the specified |response|.
+    /// Notify the associated JavaScript onSuccess callback that the query has
+    /// completed successfully with the specified string |response|.
     ///
     virtual void Success(const CefString& response) = 0;
 
     ///
-    // Notify the associated JavaScript onFailure callback that the query has
-    // failed with the specified |error_code| and |error_message|.
+    /// Notify the associated JavaScript onSuccess callback that the query has
+    /// completed successfully with binary data. A |data| pointer to the binary
+    /// data can be nullptr only if the |size| is 0.
+    ///
+    virtual void Success(const void* data, size_t size) = 0;
+
+    ///
+    /// Notify the associated JavaScript onFailure callback that the query has
+    /// failed with the specified |error_code| and |error_message|.
     ///
     virtual void Failure(int error_code, const CefString& error_message) = 0;
   };
 
   ///
-  // Implement this interface to handle queries. All methods will be executed on
-  // the browser process UI thread.
+  /// Implement this interface to handle queries. All methods will be executed
+  /// on the browser process UI thread.
   ///
   class Handler {
    public:
-    typedef CefMessageRouterBrowserSide::Callback Callback;
+    using Callback = CefMessageRouterBrowserSide::Callback;
 
     ///
-    // Executed when a new query is received. |query_id| uniquely identifies the
-    // query for the life span of the router. Return true to handle the query
-    // or false to propagate the query to other registered handlers, if any. If
-    // no handlers return true from this method then the query will be
-    // automatically canceled with an error code of -1 delivered to the
-    // JavaScript onFailure callback. If this method returns true then a
-    // Callback method must be executed either in this method or asynchronously
-    // to complete the query.
+    /// Executed when a new query is received. |query_id| uniquely identifies
+    /// the query for the life span of the router. Return true to handle the
+    /// query or false to propagate the query to other registered handlers, if
+    /// any. If no handlers return true from this method then the query will be
+    /// automatically canceled with an error code of -1 delivered to the
+    /// JavaScript onFailure callback. If this method returns true then a
+    /// Callback method must be executed either in this method or asynchronously
+    /// to complete the query.
     ///
     virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
                          CefRefPtr<CefFrame> frame,
-                         int64 query_id,
+                         int64_t query_id,
                          const CefString& request,
                          bool persistent,
                          CefRefPtr<Callback> callback) {
@@ -267,96 +316,115 @@
     }
 
     ///
-    // Executed when a query has been canceled either explicitly using the
-    // JavaScript cancel function or implicitly due to browser destruction,
-    // navigation or renderer process termination. It will only be called for
-    // the single handler that returned true from OnQuery for the same
-    // |query_id|. No references to the associated Callback object should be
-    // kept after this method is called, nor should any Callback methods be
-    // executed.
+    /// Executed when a new query is received. |query_id| uniquely identifies
+    /// the query for the life span of the router. Return true to handle the
+    /// query or false to propagate the query to other registered handlers, if
+    /// any. If no handlers return true from this method then the query will be
+    /// automatically canceled with an error code of -1 delivered to the
+    /// JavaScript onFailure callback. If this method returns true then a
+    /// Callback method must be executed either in this method or asynchronously
+    /// to complete the query.
+    ///
+    virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
+                         CefRefPtr<CefFrame> frame,
+                         int64_t query_id,
+                         CefRefPtr<const CefBinaryBuffer> request,
+                         bool persistent,
+                         CefRefPtr<Callback> callback) {
+      return false;
+    }
+
+    ///
+    /// Executed when a query has been canceled either explicitly using the
+    /// JavaScript cancel function or implicitly due to browser destruction,
+    /// navigation or renderer process termination. It will only be called for
+    /// the single handler that returned true from OnQuery for the same
+    /// |query_id|. No references to the associated Callback object should be
+    /// kept after this method is called, nor should any Callback methods be
+    /// executed.
     ///
     virtual void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
                                  CefRefPtr<CefFrame> frame,
-                                 int64 query_id) {}
+                                 int64_t query_id) {}
 
     virtual ~Handler() {}
   };
 
   ///
-  // Create a new router with the specified configuration.
+  /// Create a new router with the specified configuration.
   ///
   static CefRefPtr<CefMessageRouterBrowserSide> Create(
       const CefMessageRouterConfig& config);
 
   ///
-  // Add a new query handler. If |first| is true it will be added as the first
-  // handler, otherwise it will be added as the last handler. Returns true if
-  // the handler is added successfully or false if the handler has already been
-  // added. Must be called on the browser process UI thread. The Handler object
-  // must either outlive the router or be removed before deletion.
+  /// Add a new query handler. If |first| is true it will be added as the first
+  /// handler, otherwise it will be added as the last handler. Returns true if
+  /// the handler is added successfully or false if the handler has already been
+  /// added. Must be called on the browser process UI thread. The Handler object
+  /// must either outlive the router or be removed before deletion.
   ///
   virtual bool AddHandler(Handler* handler, bool first) = 0;
 
   ///
-  // Remove an existing query handler. Any pending queries associated with the
-  // handler will be canceled. Handler::OnQueryCanceled will be called and the
-  // associated JavaScript onFailure callback will be executed with an error
-  // code of -1. Returns true if the handler is removed successfully or false
-  // if the handler is not found. Must be called on the browser process UI
-  // thread.
+  /// Remove an existing query handler. Any pending queries associated with the
+  /// handler will be canceled. Handler::OnQueryCanceled will be called and the
+  /// associated JavaScript onFailure callback will be executed with an error
+  /// code of -1. Returns true if the handler is removed successfully or false
+  /// if the handler is not found. Must be called on the browser process UI
+  /// thread.
   ///
   virtual bool RemoveHandler(Handler* handler) = 0;
 
   ///
-  // Cancel all pending queries associated with either |browser| or |handler|.
-  // If both |browser| and |handler| are NULL all pending queries will be
-  // canceled. Handler::OnQueryCanceled will be called and the associated
-  // JavaScript onFailure callback will be executed in all cases with an error
-  // code of -1.
+  /// Cancel all pending queries associated with either |browser| or |handler|.
+  /// If both |browser| and |handler| are NULL all pending queries will be
+  /// canceled. Handler::OnQueryCanceled will be called and the associated
+  /// JavaScript onFailure callback will be executed in all cases with an error
+  /// code of -1.
   ///
   virtual void CancelPending(CefRefPtr<CefBrowser> browser,
                              Handler* handler) = 0;
 
   ///
-  // Returns the number of queries currently pending for the specified |browser|
-  // and/or |handler|. Either or both values may be empty. Must be called on the
-  // browser process UI thread.
+  /// Returns the number of queries currently pending for the specified
+  /// |browser| and/or |handler|. Either or both values may be empty. Must be
+  /// called on the browser process UI thread.
   ///
   virtual int GetPendingCount(CefRefPtr<CefBrowser> browser,
                               Handler* handler) = 0;
 
-  // The below methods should be called from other CEF handlers. They must be
-  // called exactly as documented for the router to function correctly.
+  /// The below methods should be called from other CEF handlers. They must be
+  /// called exactly as documented for the router to function correctly.
 
   ///
-  // Call from CefLifeSpanHandler::OnBeforeClose. Any pending queries associated
-  // with |browser| will be canceled and Handler::OnQueryCanceled will be
-  // called. No JavaScript callbacks will be executed since this indicates
-  // destruction of the browser.
+  /// Call from CefLifeSpanHandler::OnBeforeClose. Any pending queries
+  /// associated with |browser| will be canceled and Handler::OnQueryCanceled
+  /// will be called. No JavaScript callbacks will be executed since this
+  /// indicates destruction of the browser.
   ///
   virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) = 0;
 
   ///
-  // Call from CefRequestHandler::OnRenderProcessTerminated. Any pending queries
-  // associated with |browser| will be canceled and Handler::OnQueryCanceled
-  // will be called. No JavaScript callbacks will be executed since this
-  // indicates destruction of the context.
+  /// Call from CefRequestHandler::OnRenderProcessTerminated. Any pending
+  /// queries associated with |browser| will be canceled and
+  /// Handler::OnQueryCanceled will be called. No JavaScript callbacks will be
+  /// executed since this indicates destruction of the context.
   ///
   virtual void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser) = 0;
 
   ///
-  // Call from CefRequestHandler::OnBeforeBrowse only if the navigation is
-  // allowed to proceed. If |frame| is the main frame then any pending queries
-  // associated with |browser| will be canceled and Handler::OnQueryCanceled
-  // will be called. No JavaScript callbacks will be executed since this
-  // indicates destruction of the context.
+  /// Call from CefRequestHandler::OnBeforeBrowse only if the navigation is
+  /// allowed to proceed. If |frame| is the main frame then any pending queries
+  /// associated with |browser| will be canceled and Handler::OnQueryCanceled
+  /// will be called. No JavaScript callbacks will be executed since this
+  /// indicates destruction of the context.
   ///
   virtual void OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
                               CefRefPtr<CefFrame> frame) = 0;
 
   ///
-  // Call from CefClient::OnProcessMessageReceived. Returns true if the message
-  // is handled by this router or false otherwise.
+  /// Call from CefClient::OnProcessMessageReceived. Returns true if the message
+  /// is handled by this router or false otherwise.
   ///
   virtual bool OnProcessMessageReceived(
       CefRefPtr<CefBrowser> browser,
@@ -371,21 +439,21 @@
 };
 
 ///
-// Implements the renderer side of query routing. The methods of this class must
-// be called on the render process main thread.
+/// Implements the renderer side of query routing. The methods of this class
+/// must be called on the render process main thread.
 ///
 class CefMessageRouterRendererSide
     : public base::RefCountedThreadSafe<CefMessageRouterRendererSide> {
  public:
   ///
-  // Create a new router with the specified configuration.
+  /// Create a new router with the specified configuration.
   ///
   static CefRefPtr<CefMessageRouterRendererSide> Create(
       const CefMessageRouterConfig& config);
 
   ///
-  // Returns the number of queries currently pending for the specified |browser|
-  // and/or |context|. Either or both values may be empty.
+  /// Returns the number of queries currently pending for the specified
+  /// |browser| and/or |context|. Either or both values may be empty.
   ///
   virtual int GetPendingCount(CefRefPtr<CefBrowser> browser,
                               CefRefPtr<CefV8Context> context) = 0;
@@ -394,25 +462,25 @@
   // called exactly as documented for the router to function correctly.
 
   ///
-  // Call from CefRenderProcessHandler::OnContextCreated. Registers the
-  // JavaScripts functions with the new context.
+  /// Call from CefRenderProcessHandler::OnContextCreated. Registers the
+  /// JavaScripts functions with the new context.
   ///
   virtual void OnContextCreated(CefRefPtr<CefBrowser> browser,
                                 CefRefPtr<CefFrame> frame,
                                 CefRefPtr<CefV8Context> context) = 0;
 
   ///
-  // Call from CefRenderProcessHandler::OnContextReleased. Any pending queries
-  // associated with the released context will be canceled and
-  // Handler::OnQueryCanceled will be called in the browser process.
+  /// Call from CefRenderProcessHandler::OnContextReleased. Any pending queries
+  /// associated with the released context will be canceled and
+  /// Handler::OnQueryCanceled will be called in the browser process.
   ///
   virtual void OnContextReleased(CefRefPtr<CefBrowser> browser,
                                  CefRefPtr<CefFrame> frame,
                                  CefRefPtr<CefV8Context> context) = 0;
 
   ///
-  // Call from CefRenderProcessHandler::OnProcessMessageReceived. Returns true
-  // if the message is handled by this router or false otherwise.
+  /// Call from CefRenderProcessHandler::OnProcessMessageReceived. Returns true
+  /// if the message is handled by this router or false otherwise.
   ///
   virtual bool OnProcessMessageReceived(
       CefRefPtr<CefBrowser> browser,
diff --git a/src/include/wrapper/cef_resource_manager.h b/src/include/wrapper/cef_resource_manager.h
index 91190b7..f524b71 100644
--- a/src/include/wrapper/cef_resource_manager.h
+++ b/src/include/wrapper/cef_resource_manager.h
@@ -38,41 +38,43 @@
 #pragma once
 
 #include <list>
+#include <memory>
 
-#include "include/base/cef_macros.h"
+#include "include/base/cef_callback.h"
 #include "include/base/cef_ref_counted.h"
-#include "include/base/cef_scoped_ptr.h"
 #include "include/base/cef_weak_ptr.h"
 #include "include/cef_request_handler.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "include/wrapper/cef_helpers.h"
 
 ///
-// Class for managing multiple resource providers. For each resource request
-// providers will be called in order and have the option to (a) handle the
-// request by returning a CefResourceHandler, (b) pass the request to the next
-// provider in order, or (c) stop handling the request. See comments on the
-// Request object for additional usage information. The methods of this class
-// may be called on any browser process thread unless otherwise indicated.
+/// Class for managing multiple resource providers. For each resource request
+/// providers will be called in order and have the option to (a) handle the
+/// request by returning a CefResourceHandler, (b) pass the request to the next
+/// provider in order, or (c) stop handling the request. See comments on the
+/// Request object for additional usage information. The methods of this class
+/// may be called on any browser process thread unless otherwise indicated.
 ///
 class CefResourceManager
     : public base::RefCountedThreadSafe<CefResourceManager,
                                         CefDeleteOnIOThread> {
  public:
   ///
-  // Provides an opportunity to modify |url| before it is passed to a provider.
-  // For example, the implementation could rewrite |url| to include a default
-  // file extension. |url| will be fully qualified and may contain query or
-  // fragment components.
+  /// Provides an opportunity to modify |url| before it is passed to a provider.
+  /// For example, the implementation could rewrite |url| to include a default
+  /// file extension. |url| will be fully qualified and may contain query or
+  /// fragment components.
   ///
-  typedef base::Callback<std::string(const std::string& /*url*/)> UrlFilter;
+  using UrlFilter =
+      base::RepeatingCallback<std::string(const std::string& /*url*/)>;
 
   ///
-  // Used to resolve mime types for URLs, usually based on the file extension.
-  // |url| will be fully qualified and may contain query or fragment components.
+  /// Used to resolve mime types for URLs, usually based on the file extension.
+  /// |url| will be fully qualified and may contain query or fragment
+  /// components.
   ///
-  typedef base::Callback<std::string(const std::string& /*url*/)>
-      MimeTypeResolver;
+  using MimeTypeResolver =
+      base::RepeatingCallback<std::string(const std::string& /*url*/)>;
 
  private:
   // Values that stay with a request as it moves between providers.
@@ -90,64 +92,67 @@
 
  public:
   ///
-  // Object representing a request. Each request object is used for a single
-  // call to Provider::OnRequest and will become detached (meaning the callbacks
-  // will no longer trigger) after Request::Continue or Request::Stop is called.
-  // A request passed to Provider::OnRequestCanceled will already have been
-  // detached. The methods of this class may be called on any browser process
-  // thread.
+  /// Object representing a request. Each request object is used for a single
+  /// call to Provider::OnRequest and will become detached (meaning the
+  /// callbacks will no longer trigger) after Request::Continue or Request::Stop
+  /// is called. A request passed to Provider::OnRequestCanceled will already
+  /// have been detached. The methods of this class may be called on any browser
+  /// process thread.
   ///
   class Request : public base::RefCountedThreadSafe<Request> {
    public:
+    Request(const Request&) = delete;
+    Request& operator=(const Request&) = delete;
+
     ///
-    // Returns the URL associated with this request. The returned value will be
-    // fully qualified but will not contain query or fragment components. It
-    // will already have been passed through the URL filter.
+    /// Returns the URL associated with this request. The returned value will be
+    /// fully qualified but will not contain query or fragment components. It
+    /// will already have been passed through the URL filter.
     ///
     std::string url() const { return params_.url_; }
 
     ///
-    // Returns the CefBrowser associated with this request.
+    /// Returns the CefBrowser associated with this request.
     ///
     CefRefPtr<CefBrowser> browser() const { return params_.browser_; }
 
     ///
-    // Returns the CefFrame associated with this request.
+    /// Returns the CefFrame associated with this request.
     ///
     CefRefPtr<CefFrame> frame() const { return params_.frame_; }
 
     ///
-    // Returns the CefRequest associated with this request.
+    /// Returns the CefRequest associated with this request.
     ///
     CefRefPtr<CefRequest> request() const { return params_.request_; }
 
     ///
-    // Returns the current URL filter.
+    /// Returns the current URL filter.
     ///
     const CefResourceManager::UrlFilter& url_filter() const {
       return params_.url_filter_;
     }
 
     ///
-    // Returns the current mime type resolver.
+    /// Returns the current mime type resolver.
     ///
     const CefResourceManager::MimeTypeResolver& mime_type_resolver() const {
       return params_.mime_type_resolver_;
     }
 
     ///
-    // Continue handling the request. If |handler| is non-NULL then no
-    // additional providers will be called and the |handler| value will be
-    // returned via CefResourceManager::GetResourceHandler. If |handler| is NULL
-    // then the next provider in order, if any, will be called. If there are no
-    // additional providers then NULL will be returned via CefResourceManager::
-    // GetResourceHandler.
+    /// Continue handling the request. If |handler| is non-NULL then no
+    /// additional providers will be called and the |handler| value will be
+    /// returned via CefResourceManager::GetResourceHandler. If |handler| is
+    /// NULL then the next provider in order, if any, will be called. If there
+    /// are no additional providers then NULL will be returned via
+    /// CefResourceManager:: GetResourceHandler.
     ///
     void Continue(CefRefPtr<CefResourceHandler> handler);
 
     ///
-    // Stop handling the request. No additional providers will be called and
-    // NULL will be returned via CefResourceManager::GetResourceHandler.
+    /// Stop handling the request. No additional providers will be called and
+    /// NULL will be returned via CefResourceManager::GetResourceHandler.
     ///
     void Stop();
 
@@ -159,47 +164,45 @@
 
     // The below methods are called on the browser process IO thread.
 
-    explicit Request(scoped_ptr<RequestState> state);
+    explicit Request(std::unique_ptr<RequestState> state);
 
-    scoped_ptr<RequestState> SendRequest();
+    std::unique_ptr<RequestState> SendRequest();
     bool HasState();
 
-    static void ContinueOnIOThread(scoped_ptr<RequestState> state,
+    static void ContinueOnIOThread(std::unique_ptr<RequestState> state,
                                    CefRefPtr<CefResourceHandler> handler);
-    static void StopOnIOThread(scoped_ptr<RequestState> state);
+    static void StopOnIOThread(std::unique_ptr<RequestState> state);
 
     // Will be non-NULL while the request is pending. Only accessed on the
     // browser process IO thread.
-    scoped_ptr<RequestState> state_;
+    std::unique_ptr<RequestState> state_;
 
     // Params that stay with this request object. Safe to access on any thread.
     RequestParams params_;
-
-    DISALLOW_COPY_AND_ASSIGN(Request);
   };
 
-  typedef std::list<scoped_refptr<Request>> RequestList;
+  using RequestList = std::list<scoped_refptr<Request>>;
 
   ///
-  // Interface implemented by resource providers. A provider may be created on
-  // any thread but the methods will be called on, and the object will be
-  // destroyed on, the browser process IO thread.
+  /// Interface implemented by resource providers. A provider may be created on
+  /// any thread but the methods will be called on, and the object will be
+  /// destroyed on, the browser process IO thread.
   ///
   class Provider {
    public:
     ///
-    // Called to handle a request. If the provider knows immediately that it
-    // will not handle the request return false. Otherwise, return true and call
-    // Request::Continue or Request::Stop either in this method or
-    // asynchronously to indicate completion. See comments on Request for
-    // additional usage information.
+    /// Called to handle a request. If the provider knows immediately that it
+    /// will not handle the request return false. Otherwise, return true and
+    /// call Request::Continue or Request::Stop either in this method or
+    /// asynchronously to indicate completion. See comments on Request for
+    /// additional usage information.
     ///
     virtual bool OnRequest(scoped_refptr<Request> request) = 0;
 
     ///
-    // Called when a request has been canceled. It is still safe to dereference
-    // |request| but any calls to Request::Continue or Request::Stop will be
-    // ignored.
+    /// Called when a request has been canceled. It is still safe to dereference
+    /// |request| but any calls to Request::Continue or Request::Stop will be
+    /// ignored.
     ///
     virtual void OnRequestCanceled(scoped_refptr<Request> request) {}
 
@@ -208,11 +211,14 @@
 
   CefResourceManager();
 
+  CefResourceManager(const CefResourceManager&) = delete;
+  CefResourceManager& operator=(const CefResourceManager&) = delete;
+
   ///
-  // Add a provider that maps requests for |url| to |content|. |url| should be
-  // fully qualified but not include a query or fragment component. If
-  // |mime_type| is empty the MimeTypeResolver will be used. See comments on
-  // AddProvider for usage of the |order| and |identifier| parameters.
+  /// Add a provider that maps requests for |url| to |content|. |url| should be
+  /// fully qualified but not include a query or fragment component. If
+  /// |mime_type| is empty the MimeTypeResolver will be used. See comments on
+  /// AddProvider for usage of the |order| and |identifier| parameters.
   ///
   void AddContentProvider(const std::string& url,
                           const std::string& content,
@@ -221,11 +227,11 @@
                           const std::string& identifier);
 
   ///
-  // Add a provider that maps requests that start with |url_path| to files under
-  // |directory_path|. |url_path| should include an origin and optional path
-  // component only. Files will be loaded when a matching URL is requested.
-  // See comments on AddProvider for usage of the |order| and |identifier|
-  // parameters.
+  /// Add a provider that maps requests that start with |url_path| to files
+  /// under |directory_path|. |url_path| should include an origin and optional
+  /// path component only. Files will be loaded when a matching URL is
+  /// requested. See comments on AddProvider for usage of the |order| and
+  /// |identifier| parameters.
   ///
   void AddDirectoryProvider(const std::string& url_path,
                             const std::string& directory_path,
@@ -233,11 +239,11 @@
                             const std::string& identifier);
 
   ///
-  // Add a provider that maps requests that start with |url_path| to files
-  // stored in the archive file at |archive_path|. |url_path| should include an
-  // origin and optional path component only. The archive file will be loaded
-  // when a matching URL is requested for the first time. See comments on
-  // AddProvider for usage of the |order| and |identifier| parameters.
+  /// Add a provider that maps requests that start with |url_path| to files
+  /// stored in the archive file at |archive_path|. |url_path| should include an
+  /// origin and optional path component only. The archive file will be loaded
+  /// when a matching URL is requested for the first time. See comments on
+  /// AddProvider for usage of the |order| and |identifier| parameters.
   ///
   void AddArchiveProvider(const std::string& url_path,
                           const std::string& archive_path,
@@ -246,59 +252,58 @@
                           const std::string& identifier);
 
   ///
-  // Add a provider. This object takes ownership of |provider|. Providers will
-  // be called in ascending order based on the |order| value. Multiple providers
-  // sharing the same |order| value will be called in the order that they were
-  // added. The |identifier| value, which does not need to be unique, can be
-  // used to remove the provider at a later time.
+  /// Add a provider. This object takes ownership of |provider|. Providers will
+  /// be called in ascending order based on the |order| value. Multiple
+  /// providers sharing the same |order| value will be called in the order that
+  /// they were added. The |identifier| value, which does not need to be unique,
+  /// can be used to remove the provider at a later time.
   ///
   void AddProvider(Provider* provider,
                    int order,
                    const std::string& identifier);
 
   ///
-  // Remove all providers with the specified |identifier| value. If any removed
-  // providers have pending requests the Provider::OnRequestCancel method will
-  // be called. The removed providers may be deleted immediately or at a later
-  // time.
+  /// Remove all providers with the specified |identifier| value. If any removed
+  /// providers have pending requests the Provider::OnRequestCancel method will
+  /// be called. The removed providers may be deleted immediately or at a later
+  /// time.
   ///
   void RemoveProviders(const std::string& identifier);
 
   ///
-  // Remove all providers. If any removed providers have pending requests the
-  // Provider::OnRequestCancel method will be called. The removed providers may
-  // be deleted immediately or at a later time.
+  /// Remove all providers. If any removed providers have pending requests the
+  /// Provider::OnRequestCancel method will be called. The removed providers may
+  /// be deleted immediately or at a later time.
   ///
   void RemoveAllProviders();
 
   ///
-  // Set the url filter. If not set the default no-op filter will be used.
-  // Changes to this value will not affect currently pending requests.
+  /// Set the url filter. If not set the default no-op filter will be used.
+  /// Changes to this value will not affect currently pending requests.
   ///
   void SetUrlFilter(const UrlFilter& filter);
 
   ///
-  // Set the mime type resolver. If not set the default resolver will be used.
-  // Changes to this value will not affect currently pending requests.
+  /// Set the mime type resolver. If not set the default resolver will be used.
+  /// Changes to this value will not affect currently pending requests.
   ///
   void SetMimeTypeResolver(const MimeTypeResolver& resolver);
 
-  // The below methods should be called from other CEF handlers. They must be
-  // called exactly as documented for the manager to function correctly.
+  /// The below methods should be called from other CEF handlers. They must be
+  /// called exactly as documented for the manager to function correctly.
 
   ///
-  // Called from CefRequestHandler::OnBeforeResourceLoad on the browser process
-  // IO thread.
+  /// Called from CefRequestHandler::OnBeforeResourceLoad on the browser process
+  /// IO thread.
   ///
-  cef_return_value_t OnBeforeResourceLoad(
-      CefRefPtr<CefBrowser> browser,
-      CefRefPtr<CefFrame> frame,
-      CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback);
+  cef_return_value_t OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser,
+                                          CefRefPtr<CefFrame> frame,
+                                          CefRefPtr<CefRequest> request,
+                                          CefRefPtr<CefCallback> callback);
 
   ///
-  // Called from CefRequestHandler::GetResourceHandler on the browser process
-  // IO thread.
+  /// Called from CefRequestHandler::GetResourceHandler on the browser process
+  /// IO thread.
   ///
   CefRefPtr<CefResourceHandler> GetResourceHandler(
       CefRefPtr<CefBrowser> browser,
@@ -315,7 +320,7 @@
 
   // Provider and associated information.
   struct ProviderEntry;
-  typedef std::list<ProviderEntry*> ProviderEntryList;
+  using ProviderEntryList = std::list<ProviderEntry*>;
 
   // Values associated with the pending request only. Ownership will be passed
   // between requests and the resource manager as request handling proceeds.
@@ -325,7 +330,7 @@
     base::WeakPtr<CefResourceManager> manager_;
 
     // Callback to execute once request handling is complete.
-    CefRefPtr<CefRequestCallback> callback_;
+    CefRefPtr<CefCallback> callback_;
 
     // Position of the currently associated ProviderEntry in the |providers_|
     // list.
@@ -341,10 +346,10 @@
 
   // Methods that manage request state between requests. Called on the browser
   // process IO thread.
-  bool SendRequest(scoped_ptr<RequestState> state);
-  void ContinueRequest(scoped_ptr<RequestState> state,
+  bool SendRequest(std::unique_ptr<RequestState> state);
+  void ContinueRequest(std::unique_ptr<RequestState> state,
                        CefRefPtr<CefResourceHandler> handler);
-  void StopRequest(scoped_ptr<RequestState> state);
+  void StopRequest(std::unique_ptr<RequestState> state);
   bool IncrementProvider(RequestState* state);
   void DetachRequestFromProvider(RequestState* state);
   void GetNextValidProvider(ProviderEntryList::iterator& iterator);
@@ -356,16 +361,14 @@
   ProviderEntryList providers_;
 
   // Map of response ID to pending CefResourceHandler object.
-  typedef std::map<uint64, CefRefPtr<CefResourceHandler>> PendingHandlersMap;
+  using PendingHandlersMap = std::map<uint64_t, CefRefPtr<CefResourceHandler>>;
   PendingHandlersMap pending_handlers_;
 
   UrlFilter url_filter_;
   MimeTypeResolver mime_type_resolver_;
 
   // Must be the last member. Created and accessed on the IO thread.
-  scoped_ptr<base::WeakPtrFactory<CefResourceManager>> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefResourceManager);
+  std::unique_ptr<base::WeakPtrFactory<CefResourceManager>> weak_ptr_factory_;
 };
 
 #endif  // CEF_INCLUDE_WRAPPER_CEF_RESOURCE_MANAGER_H_
diff --git a/src/include/wrapper/cef_scoped_temp_dir.h b/src/include/wrapper/cef_scoped_temp_dir.h
index f40fa7d..6bd8cea 100644
--- a/src/include/wrapper/cef_scoped_temp_dir.h
+++ b/src/include/wrapper/cef_scoped_temp_dir.h
@@ -39,80 +39,80 @@
 #pragma once
 
 #include "include/base/cef_build.h"
-#include "include/base/cef_macros.h"
 #include "include/cef_base.h"
 
 ///
-// An object representing a temporary / scratch directory that should be cleaned
-// up (recursively) when this object goes out of scope.  Note that since
-// deletion occurs during the destructor, no further error handling is possible
-// if the directory fails to be deleted.  As a result, deletion is not
-// guaranteed by this class.
-//
-// Multiple calls to the methods which establish a temporary directory
-// (CreateUniqueTempDir, CreateUniqueTempDirUnderPath, and Set) must have
-// intervening calls to Delete or Take, or the calls will fail.
+/// An object representing a temporary / scratch directory that should be
+/// cleaned up (recursively) when this object goes out of scope.  Note that
+/// since deletion occurs during the destructor, no further error handling is
+/// possible if the directory fails to be deleted.  As a result, deletion is not
+/// guaranteed by this class.
+///
+/// Multiple calls to the methods which establish a temporary directory
+/// (CreateUniqueTempDir, CreateUniqueTempDirUnderPath, and Set) must have
+/// intervening calls to Delete or Take, or the calls will fail.
 ///
 class CefScopedTempDir {
  public:
   ///
-  // No directory is owned/created initially.
+  /// No directory is owned/created initially.
   ///
   CefScopedTempDir();
 
+  CefScopedTempDir(const CefScopedTempDir&) = delete;
+  CefScopedTempDir& operator=(const CefScopedTempDir&) = delete;
+
   ///
-  // Recursively delete path.
+  /// Recursively delete path.
   ///
   ~CefScopedTempDir();
 
   ///
-  // Creates a unique directory in TempPath, and takes ownership of it.
-  // See file_util::CreateNewTemporaryDirectory.
+  /// Creates a unique directory in TempPath, and takes ownership of it.
+  /// See file_util::CreateNewTemporaryDirectory.
   ///
-  bool CreateUniqueTempDir() WARN_UNUSED_RESULT;
+  [[nodiscard]] bool CreateUniqueTempDir();
 
   ///
-  // Creates a unique directory under a given path, and takes ownership of it.
+  /// Creates a unique directory under a given path, and takes ownership of it.
   ///
-  bool CreateUniqueTempDirUnderPath(const CefString& path) WARN_UNUSED_RESULT;
+  [[nodiscard]] bool CreateUniqueTempDirUnderPath(const CefString& path);
 
   ///
-  // Takes ownership of directory at |path|, creating it if necessary.
-  // Don't call multiple times unless Take() has been called first.
+  /// Takes ownership of directory at |path|, creating it if necessary.
+  /// Don't call multiple times unless Take() has been called first.
   ///
-  bool Set(const CefString& path) WARN_UNUSED_RESULT;
+  [[nodiscard]] bool Set(const CefString& path);
 
   ///
-  // Deletes the temporary directory wrapped by this object.
+  /// Deletes the temporary directory wrapped by this object.
   ///
-  bool Delete() WARN_UNUSED_RESULT;
+  [[nodiscard]] bool Delete();
 
   ///
-  // Caller takes ownership of the temporary directory so it won't be destroyed
-  // when this object goes out of scope.
+  /// Caller takes ownership of the temporary directory so it won't be destroyed
+  /// when this object goes out of scope.
   ///
   CefString Take();
 
   ///
-  // Returns the path to the created directory. Call one of the
-  // CreateUniqueTempDir* methods before getting the path.
+  /// Returns the path to the created directory. Call one of the
+  /// CreateUniqueTempDir* methods before getting the path.
   ///
   const CefString& GetPath() const;
 
   ///
-  // Returns true if path_ is empty.
+  /// Returns true if path_ is empty.
   ///
   bool IsEmpty() const;
 
   ///
-  // Returns true if path_ is non-empty and exists.
+  /// Returns true if path_ is non-empty and exists.
   ///
   bool IsValid() const;
 
  private:
   CefString path_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefScopedTempDir);
 };
 
 #endif  // CEF_INCLUDE_SCOPED_TEMP_DIR_H_
diff --git a/src/include/wrapper/cef_stream_resource_handler.h b/src/include/wrapper/cef_stream_resource_handler.h
index 130e20b..06690fc 100644
--- a/src/include/wrapper/cef_stream_resource_handler.h
+++ b/src/include/wrapper/cef_stream_resource_handler.h
@@ -37,23 +37,22 @@
 #define CEF_INCLUDE_WRAPPER_CEF_STREAM_RESOURCE_HANDLER_H_
 #pragma once
 
-#include "include/base/cef_macros.h"
 #include "include/cef_resource_handler.h"
 #include "include/cef_response.h"
 #include "include/cef_stream.h"
 
 ///
-// Implementation of the CefResourceHandler class for reading from a CefStream.
+/// Implementation of the CefResourceHandler class for reading from a CefStream.
 ///
 class CefStreamResourceHandler : public CefResourceHandler {
  public:
   ///
-  // Create a new object with default response values.
+  /// Create a new object with default response values.
   ///
   CefStreamResourceHandler(const CefString& mime_type,
                            CefRefPtr<CefStreamReader> stream);
   ///
-  // Create a new object with explicit response values.
+  /// Create a new object with explicit response values.
   ///
   CefStreamResourceHandler(int status_code,
                            const CefString& status_text,
@@ -61,18 +60,21 @@
                            CefResponse::HeaderMap header_map,
                            CefRefPtr<CefStreamReader> stream);
 
+  CefStreamResourceHandler(const CefStreamResourceHandler&) = delete;
+  CefStreamResourceHandler& operator=(const CefStreamResourceHandler&) = delete;
+
   // CefResourceHandler methods.
   bool Open(CefRefPtr<CefRequest> request,
             bool& handle_request,
-            CefRefPtr<CefCallback> callback) OVERRIDE;
+            CefRefPtr<CefCallback> callback) override;
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
-                          CefString& redirectUrl) OVERRIDE;
+                          int64_t& response_length,
+                          CefString& redirectUrl) override;
   bool Read(void* data_out,
             int bytes_to_read,
             int& bytes_read,
-            CefRefPtr<CefResourceReadCallback> callback) OVERRIDE;
-  void Cancel() OVERRIDE;
+            CefRefPtr<CefResourceReadCallback> callback) override;
+  void Cancel() override;
 
  private:
   const int status_code_;
@@ -82,7 +84,6 @@
   const CefRefPtr<CefStreamReader> stream_;
 
   IMPLEMENT_REFCOUNTING(CefStreamResourceHandler);
-  DISALLOW_COPY_AND_ASSIGN(CefStreamResourceHandler);
 };
 
 #endif  // CEF_INCLUDE_WRAPPER_CEF_STREAM_RESOURCE_HANDLER_H_
diff --git a/src/include/wrapper/cef_xml_object.h b/src/include/wrapper/cef_xml_object.h
index 9315adc..3613098 100644
--- a/src/include/wrapper/cef_xml_object.h
+++ b/src/include/wrapper/cef_xml_object.h
@@ -41,7 +41,6 @@
 #include <vector>
 
 #include "include/base/cef_lock.h"
-#include "include/base/cef_macros.h"
 #include "include/base/cef_ref_counted.h"
 #include "include/cef_base.h"
 #include "include/cef_xml_reader.h"
@@ -49,42 +48,43 @@
 class CefStreamReader;
 
 ///
-// Thread safe class for representing XML data as a structured object. This
-// class should not be used with large XML documents because all data will be
-// resident in memory at the same time. This implementation supports a
-// restricted set of XML features:
-// <pre>
-// (1) Processing instructions, whitespace and comments are ignored.
-// (2) Elements and attributes must always be referenced using the fully
-//     qualified name (ie, namespace:localname).
-// (3) Empty elements (<a/>) and elements with zero-length values (<a></a>)
-//     are considered the same.
-// (4) Element nodes are considered part of a value if:
-//     (a) The element node follows a non-element node at the same depth
-//         (see 5), or
-//     (b) The element node does not have a namespace and the parent node does.
-// (5) Mixed node types at the same depth are combined into a single element
-//     value as follows:
-//     (a) All node values are concatenated to form a single string value.
-//     (b) Entity reference nodes are resolved to the corresponding entity
-//         value.
-//     (c) Element nodes are represented by their outer XML string.
-// </pre>
+/// Thread safe class for representing XML data as a structured object. This
+/// class should not be used with large XML documents because all data will be
+/// resident in memory at the same time. This implementation supports a
+/// restricted set of XML features:
+///
+/// 1. Processing instructions, whitespace and comments are ignored.
+/// 2. Elements and attributes must always be referenced using the fully
+///    qualified name (ie, namespace:localname).
+/// 3. Empty elements ("<a/>") and elements with zero-length values ("<a></a>")
+///    are considered the same.
+/// 4. Element nodes are considered part of a value if:
+///    1. The element node follows a non-element node at the same depth
+///       (see 5), or
+///    2. The element node does not have a namespace and the parent node does.
+/// 5. Mixed node types at the same depth are combined into a single element
+///    value as follows:
+///    1. All node values are concatenated to form a single string value.
+///    2. Entity reference nodes are resolved to the corresponding entity value.
+///    3. Element nodes are represented by their outer XML string.
 ///
 class CefXmlObject : public base::RefCountedThreadSafe<CefXmlObject> {
  public:
-  typedef std::vector<CefRefPtr<CefXmlObject>> ObjectVector;
-  typedef std::map<CefString, CefString> AttributeMap;
+  using ObjectVector = std::vector<CefRefPtr<CefXmlObject>>;
+  using AttributeMap = std::map<CefString, CefString>;
 
   ///
-  // Create a new object with the specified name. An object name must always be
-  // at least one character long.
+  /// Create a new object with the specified name. An object name must always be
+  /// at least one character long.
   ///
   explicit CefXmlObject(const CefString& name);
 
+  CefXmlObject(const CefXmlObject&) = delete;
+  CefXmlObject& operator=(const CefXmlObject&) = delete;
+
   ///
-  // Load the contents of the specified XML stream into this object.  The
-  // existing children and attributes, if any, will first be cleared.
+  /// Load the contents of the specified XML stream into this object.  The
+  /// existing children and attributes, if any, will first be cleared.
   ///
   bool Load(CefRefPtr<CefStreamReader> stream,
             CefXmlReader::EncodingType encodingType,
@@ -92,56 +92,56 @@
             CefString* loadError);
 
   ///
-  // Set the name, children and attributes of this object to a duplicate of the
-  // specified object's contents. The existing children and attributes, if any,
-  // will first be cleared.
+  /// Set the name, children and attributes of this object to a duplicate of the
+  /// specified object's contents. The existing children and attributes, if any,
+  /// will first be cleared.
   ///
   void Set(CefRefPtr<CefXmlObject> object);
 
   ///
-  // Append a duplicate of the children and attributes of the specified object
-  // to this object. If |overwriteAttributes| is true then any attributes in
-  // this object that also exist in the specified object will be overwritten
-  // with the new values. The name of this object is not changed.
+  /// Append a duplicate of the children and attributes of the specified object
+  /// to this object. If |overwriteAttributes| is true then any attributes in
+  /// this object that also exist in the specified object will be overwritten
+  /// with the new values. The name of this object is not changed.
   ///
   void Append(CefRefPtr<CefXmlObject> object, bool overwriteAttributes);
 
   ///
-  // Return a new object with the same name, children and attributes as this
-  // object. The parent of the new object will be NULL.
+  /// Return a new object with the same name, children and attributes as this
+  /// object. The parent of the new object will be NULL.
   ///
   CefRefPtr<CefXmlObject> Duplicate();
 
   ///
-  // Clears this object's children and attributes. The name and parenting of
-  // this object are not changed.
+  /// Clears this object's children and attributes. The name and parenting of
+  /// this object are not changed.
   ///
   void Clear();
 
   ///
-  // Access the object's name. An object name must always be at least one
-  // character long.
+  /// Access the object's name. An object name must always be at least one
+  /// character long.
   ///
   CefString GetName();
   bool SetName(const CefString& name);
 
   ///
-  // Access the object's parent. The parent can be NULL if this object has not
-  // been added as the child on another object.
+  /// Access the object's parent. The parent can be NULL if this object has not
+  /// been added as the child on another object.
   ///
   bool HasParent();
   CefRefPtr<CefXmlObject> GetParent();
 
   ///
-  // Access the object's value. An object cannot have a value if it also has
-  // children. Attempting to set the value while children exist will fail.
+  /// Access the object's value. An object cannot have a value if it also has
+  /// children. Attempting to set the value while children exist will fail.
   ///
   bool HasValue();
   CefString GetValue();
   bool SetValue(const CefString& value);
 
   ///
-  // Access the object's attributes. Attributes must have unique names.
+  /// Access the object's attributes. Attributes must have unique names.
   ///
   bool HasAttributes();
   size_t GetAttributeCount();
@@ -152,11 +152,11 @@
   void ClearAttributes();
 
   ///
-  // Access the object's children. Each object can only have one parent so
-  // attempting to add an object that already has a parent will fail. Removing a
-  // child will set the child's parent to NULL. Adding a child will set the
-  // child's parent to this object. This object's value, if any, will be cleared
-  // if a child is added.
+  /// Access the object's children. Each object can only have one parent so
+  /// attempting to add an object that already has a parent will fail. Removing
+  /// a child will set the child's parent to NULL. Adding a child will set the
+  /// child's parent to this object. This object's value, if any, will be
+  /// cleared if a child is added.
   ///
   bool HasChildren();
   size_t GetChildCount();
@@ -167,12 +167,12 @@
   void ClearChildren();
 
   ///
-  // Find the first child with the specified name.
+  /// Find the first child with the specified name.
   ///
   CefRefPtr<CefXmlObject> FindChild(const CefString& name);
 
   ///
-  // Find all children with the specified name.
+  /// Find all children with the specified name.
   ///
   size_t FindChildren(const CefString& name, ObjectVector& children);
 
@@ -190,8 +190,6 @@
   ObjectVector children_;
 
   base::Lock lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefXmlObject);
 };
 
 #endif  // CEF_INCLUDE_WRAPPER_CEF_XML_OBJECT_H_
diff --git a/src/include/wrapper/cef_zip_archive.h b/src/include/wrapper/cef_zip_archive.h
index 9eb2812..4f8d351 100644
--- a/src/include/wrapper/cef_zip_archive.h
+++ b/src/include/wrapper/cef_zip_archive.h
@@ -40,91 +40,93 @@
 #include <map>
 
 #include "include/base/cef_lock.h"
-#include "include/base/cef_macros.h"
 #include "include/base/cef_ref_counted.h"
 #include "include/cef_base.h"
 
 class CefStreamReader;
 
 ///
-// Thread-safe class for accessing zip archive file contents. This class should
-// not be used with large archive files because all data will be resident in
-// memory at the same time. This implementation supports a restricted set of zip
-// archive features:
-// (1) All file names are stored and compared in lower case.
-// (2) File ordering from the original zip archive is not maintained. This
-//     means that files from the same folder may not be located together in the
-//     file content map.
+/// Thread-safe class for accessing zip archive file contents. This class should
+/// not be used with large archive files because all data will be resident in
+/// memory at the same time. This implementation supports a restricted set of
+/// zip archive features:
+/// 1. All file names are stored and compared in lower case.
+/// 2. File ordering from the original zip archive is not maintained. This means
+///    that files from the same folder may not be located together in the file
+///    content map.
 ///
 class CefZipArchive : public base::RefCountedThreadSafe<CefZipArchive> {
  public:
   ///
-  // Class representing a file in the archive. Accessing the file data from
-  // multiple threads is safe provided a reference to the File object is kept.
+  /// Class representing a file in the archive. Accessing the file data from
+  /// multiple threads is safe provided a reference to the File object is kept.
   ///
   class File : public CefBaseRefCounted {
    public:
     ///
-    // Returns the read-only data contained in the file.
+    /// Returns the read-only data contained in the file.
     ///
     virtual const unsigned char* GetData() const = 0;
 
     ///
-    // Returns the size of the data in the file.
+    /// Returns the size of the data in the file.
     ///
     virtual size_t GetDataSize() const = 0;
 
     ///
-    // Returns a CefStreamReader object for streaming the contents of the file.
+    /// Returns a CefStreamReader object for streaming the contents of the file.
     ///
     virtual CefRefPtr<CefStreamReader> GetStreamReader() const = 0;
   };
 
-  typedef std::map<CefString, CefRefPtr<File>> FileMap;
+  using FileMap = std::map<CefString, CefRefPtr<File>>;
 
   ///
-  // Create a new object.
+  /// Create a new object.
   ///
   CefZipArchive();
 
+  CefZipArchive(const CefZipArchive&) = delete;
+  CefZipArchive& operator=(const CefZipArchive&) = delete;
+
   ///
-  // Load the contents of the specified zip archive stream into this object.
-  // If the zip archive requires a password then provide it via |password|.
-  // If |overwriteExisting| is true then any files in this object that also
-  // exist in the specified archive will be replaced with the new files.
-  // Returns the number of files successfully loaded.
+  /// Load the contents of the specified zip archive stream into this object.
+  /// If the zip archive requires a password then provide it via |password|.
+  /// If |overwriteExisting| is true then any files in this object that also
+  /// exist in the specified archive will be replaced with the new files.
+  /// Returns the number of files successfully loaded.
   ///
   size_t Load(CefRefPtr<CefStreamReader> stream,
               const CefString& password,
               bool overwriteExisting);
 
   ///
-  // Clears the contents of this object.
+  /// Clears the contents of this object.
   ///
   void Clear();
 
   ///
-  // Returns the number of files in the archive.
+  /// Returns the number of files in the archive.
   ///
   size_t GetFileCount() const;
 
   ///
-  // Returns true if the specified file exists and has contents.
+  /// Returns true if the specified file exists and has contents.
   ///
   bool HasFile(const CefString& fileName) const;
 
   ///
-  // Returns the specified file.
+  /// Returns the specified file.
   ///
   CefRefPtr<File> GetFile(const CefString& fileName) const;
 
   ///
-  // Removes the specified file.
+  /// Removes the specified file.
   ///
   bool RemoveFile(const CefString& fileName);
 
   ///
-  // Returns the map of all files.
+  /// Returns the map of all files.
   ///
   size_t GetFiles(FileMap& map) const;
 
@@ -136,8 +138,6 @@
   FileMap contents_;
 
   mutable base::Lock lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefZipArchive);
 };
 
 #endif  // CEF_INCLUDE_WRAPPER_CEF_ZIP_ARCHIVE_H_
diff --git a/src/libcef/browser/alloy/alloy_browser_context.cc b/src/libcef/browser/alloy/alloy_browser_context.cc
new file mode 100644
index 0000000..9eb99ef
--- /dev/null
+++ b/src/libcef/browser/alloy/alloy_browser_context.cc
@@ -0,0 +1,485 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/browser/alloy/alloy_browser_context.h"
+
+#include <map>
+#include <utility>
+
+#include "libcef/browser/download_manager_delegate.h"
+#include "libcef/browser/extensions/extension_system.h"
+#include "libcef/browser/prefs/browser_prefs.h"
+#include "libcef/browser/ssl_host_state_delegate.h"
+#include "libcef/browser/thread_util.h"
+#include "libcef/common/cef_switches.h"
+#include "libcef/common/extensions/extensions_util.h"
+
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "chrome/browser/font_family_cache.h"
+#include "chrome/browser/permissions/permission_manager_factory.h"
+#include "chrome/browser/plugins/chrome_plugin_service_filter.h"
+#include "chrome/browser/profiles/profile_key.h"
+#include "chrome/browser/reduce_accept_language/reduce_accept_language_factory.h"
+#include "chrome/browser/ui/zoom/chrome_zoom_level_prefs.h"
+#include "chrome/common/pref_names.h"
+#include "components/guest_view/browser/guest_view_manager.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/keyed_service/core/simple_dependency_manager.h"
+#include "components/keyed_service/core/simple_key_map.h"
+#include "components/permissions/permission_manager.h"
+#include "components/prefs/pref_service.h"
+#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
+#include "components/user_prefs/user_prefs.h"
+#include "components/visitedlink/browser/visitedlink_event_listener.h"
+#include "components/visitedlink/browser/visitedlink_writer.h"
+#include "components/zoom/zoom_event_manager.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/download_manager.h"
+#include "content/public/browser/resource_context.h"
+#include "content/public/browser/storage_partition.h"
+#include "extensions/browser/extension_protocols.h"
+#include "extensions/browser/process_manager.h"
+#include "extensions/common/constants.h"
+#include "net/proxy_resolution/proxy_config_service.h"
+#include "services/network/public/mojom/cors_origin_pattern.mojom.h"
+
+using content::BrowserThread;
+
+// Creates and manages VisitedLinkEventListener objects for each
+// AlloyBrowserContext sharing the same VisitedLinkWriter.
+class CefVisitedLinkListener : public visitedlink::VisitedLinkWriter::Listener {
+ public:
+  CefVisitedLinkListener() { DCHECK(listener_map_.empty()); }
+
+  CefVisitedLinkListener(const CefVisitedLinkListener&) = delete;
+  CefVisitedLinkListener& operator=(const CefVisitedLinkListener&) = delete;
+
+  void CreateListenerForContext(content::BrowserContext* context) {
+    CEF_REQUIRE_UIT();
+    auto listener =
+        std::make_unique<visitedlink::VisitedLinkEventListener>(context);
+    listener_map_.insert(std::make_pair(context, std::move(listener)));
+  }
+
+  void RemoveListenerForContext(content::BrowserContext* context) {
+    CEF_REQUIRE_UIT();
+    ListenerMap::iterator it = listener_map_.find(context);
+    DCHECK(it != listener_map_.end());
+    listener_map_.erase(it);
+  }
+
+  // visitedlink::VisitedLinkWriter::Listener methods.
+
+  void NewTable(base::ReadOnlySharedMemoryRegion* table_region) override {
+    CEF_REQUIRE_UIT();
+    ListenerMap::iterator it = listener_map_.begin();
+    for (; it != listener_map_.end(); ++it) {
+      it->second->NewTable(table_region);
+    }
+  }
+
+  void Add(visitedlink::VisitedLinkCommon::Fingerprint fingerprint) override {
+    CEF_REQUIRE_UIT();
+    ListenerMap::iterator it = listener_map_.begin();
+    for (; it != listener_map_.end(); ++it) {
+      it->second->Add(fingerprint);
+    }
+  }
+
+  void Reset(bool invalidate_hashes) override {
+    CEF_REQUIRE_UIT();
+    ListenerMap::iterator it = listener_map_.begin();
+    for (; it != listener_map_.end(); ++it) {
+      it->second->Reset(invalidate_hashes);
+    }
+  }
+
+ private:
+  // Map of AlloyBrowserContext to the associated VisitedLinkEventListener.
+  using ListenerMap =
+      std::map<const content::BrowserContext*,
+               std::unique_ptr<visitedlink::VisitedLinkEventListener>>;
+  ListenerMap listener_map_;
+};
+
+AlloyBrowserContext::AlloyBrowserContext(
+    const CefRequestContextSettings& settings)
+    : CefBrowserContext(settings) {}
+
+AlloyBrowserContext::~AlloyBrowserContext() {
+  if (resource_context_) {
+    content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE,
+                                       resource_context_.release());
+  }
+}
+
+bool AlloyBrowserContext::IsInitialized() const {
+  CEF_REQUIRE_UIT();
+  return !!key_;
+}
+
+void AlloyBrowserContext::StoreOrTriggerInitCallback(
+    base::OnceClosure callback) {
+  CEF_REQUIRE_UIT();
+  // Initialization is always synchronous.
+  std::move(callback).Run();
+}
+
+void AlloyBrowserContext::Initialize() {
+  CefBrowserContext::Initialize();
+
+  key_ = std::make_unique<ProfileKey>(cache_path_);
+  SimpleKeyMap::GetInstance()->Associate(this, key_.get());
+
+  // Initialize the PrefService object.
+  pref_service_ = browser_prefs::CreatePrefService(
+      this, cache_path_, !!settings_.persist_user_preferences);
+
+  // This must be called before creating any services to avoid hitting
+  // DependencyManager::AssertContextWasntDestroyed when creating/destroying
+  // multiple browser contexts (due to pointer address reuse).
+  BrowserContextDependencyManager::GetInstance()->CreateBrowserContextServices(
+      this);
+
+  const bool extensions_enabled = extensions::ExtensionsEnabled();
+  if (extensions_enabled) {
+    // Create the custom ExtensionSystem first because other KeyedServices
+    // depend on it.
+    extension_system_ = static_cast<extensions::CefExtensionSystem*>(
+        extensions::ExtensionSystem::Get(this));
+    extension_system_->InitForRegularProfile(true);
+
+    // Make sure the ProcessManager is created so that it receives extension
+    // load notifications. This is necessary for the proper initialization of
+    // background/event pages.
+    extensions::ProcessManager::Get(this);
+  }
+
+  // Initialize visited links management.
+  base::FilePath visited_link_path;
+  if (!cache_path_.empty()) {
+    visited_link_path = cache_path_.Append(FILE_PATH_LITERAL("Visited Links"));
+  }
+  visitedlink_listener_ = new CefVisitedLinkListener;
+  visitedlink_master_.reset(new visitedlink::VisitedLinkWriter(
+      visitedlink_listener_, this, !visited_link_path.empty(), false,
+      visited_link_path, 0));
+  visitedlink_listener_->CreateListenerForContext(this);
+  visitedlink_master_->Init();
+
+  // Initialize proxy configuration tracker.
+  pref_proxy_config_tracker_.reset(new PrefProxyConfigTrackerImpl(
+      GetPrefs(), content::GetIOThreadTaskRunner({})));
+
+  // Spell checking support and possibly other subsystems retrieve the
+  // PrefService associated with a BrowserContext via UserPrefs::Get().
+  PrefService* pref_service = GetPrefs();
+  DCHECK(pref_service);
+  user_prefs::UserPrefs::Set(this, pref_service);
+  key_->SetPrefs(pref_service);
+
+  if (extensions_enabled) {
+    extension_system_->Init();
+  }
+
+  ChromePluginServiceFilter::GetInstance()->RegisterProfile(this);
+}
+
+void AlloyBrowserContext::Shutdown() {
+  CefBrowserContext::Shutdown();
+
+  // Send notifications to clean up objects associated with this Profile.
+  MaybeSendDestroyedNotification();
+
+  ChromePluginServiceFilter::GetInstance()->UnregisterProfile(this);
+
+  // Remove any BrowserContextKeyedServiceFactory associations. This must be
+  // called before the ProxyService owned by AlloyBrowserContext is destroyed.
+  // The SimpleDependencyManager should always be passed after the
+  // BrowserContextDependencyManager. This is because the KeyedService instances
+  // in the BrowserContextDependencyManager's dependency graph can depend on the
+  // ones in the SimpleDependencyManager's graph.
+  DependencyManager::PerformInterlockedTwoPhaseShutdown(
+      BrowserContextDependencyManager::GetInstance(), this,
+      SimpleDependencyManager::GetInstance(), key_.get());
+
+  key_.reset();
+  SimpleKeyMap::GetInstance()->Dissociate(this);
+
+  // Shuts down the storage partitions associated with this browser context.
+  // This must be called before the browser context is actually destroyed
+  // and before a clean-up task for its corresponding IO thread residents
+  // (e.g. ResourceContext) is posted, so that the classes that hung on
+  // StoragePartition can have time to do necessary cleanups on IO thread.
+  ShutdownStoragePartitions();
+
+  visitedlink_listener_->RemoveListenerForContext(this);
+
+  // The FontFamilyCache references the ProxyService so delete it before the
+  // ProxyService is deleted.
+  SetUserData(&kFontFamilyCacheKey, nullptr);
+
+  pref_proxy_config_tracker_->DetachFromPrefService();
+
+  // Delete the download manager delegate here because otherwise we'll crash
+  // when it's accessed from the content::BrowserContext destructor.
+  if (download_manager_delegate_) {
+    download_manager_delegate_.reset(nullptr);
+  }
+}
+
+void AlloyBrowserContext::RemoveCefRequestContext(
+    CefRequestContextImpl* context) {
+  CEF_REQUIRE_UIT();
+
+  if (extensions::ExtensionsEnabled()) {
+    extension_system()->OnRequestContextDeleted(context);
+  }
+
+  // May result in |this| being deleted.
+  CefBrowserContext::RemoveCefRequestContext(context);
+}
+
+void AlloyBrowserContext::LoadExtension(
+    const CefString& root_directory,
+    CefRefPtr<CefDictionaryValue> manifest,
+    CefRefPtr<CefExtensionHandler> handler,
+    CefRefPtr<CefRequestContext> loader_context) {
+  if (!extensions::ExtensionsEnabled()) {
+    if (handler) {
+      handler->OnExtensionLoadFailed(ERR_ABORTED);
+    }
+    return;
+  }
+
+  if (manifest && manifest->GetSize() > 0) {
+    CefDictionaryValueImpl* value_impl =
+        static_cast<CefDictionaryValueImpl*>(manifest.get());
+    auto value = value_impl->CopyValue();
+    extension_system()->LoadExtension(std::move(value.GetDict()),
+                                      root_directory, false /* builtin */,
+                                      loader_context, handler);
+  } else {
+    extension_system()->LoadExtension(root_directory, false /* builtin */,
+                                      loader_context, handler);
+  }
+}
+
+bool AlloyBrowserContext::GetExtensions(std::vector<CefString>& extension_ids) {
+  if (!extensions::ExtensionsEnabled()) {
+    return false;
+  }
+
+  extensions::CefExtensionSystem::ExtensionMap extension_map =
+      extension_system()->GetExtensions();
+  extensions::CefExtensionSystem::ExtensionMap::const_iterator it =
+      extension_map.begin();
+  for (; it != extension_map.end(); ++it) {
+    extension_ids.push_back(it->second->GetIdentifier());
+  }
+
+  return true;
+}
+
+CefRefPtr<CefExtension> AlloyBrowserContext::GetExtension(
+    const CefString& extension_id) {
+  if (!extensions::ExtensionsEnabled()) {
+    return nullptr;
+  }
+
+  return extension_system()->GetExtension(extension_id);
+}
+
+bool AlloyBrowserContext::UnloadExtension(const CefString& extension_id) {
+  DCHECK(extensions::ExtensionsEnabled());
+  return extension_system()->UnloadExtension(extension_id);
+}
+
+bool AlloyBrowserContext::IsPrintPreviewSupported() const {
+  CEF_REQUIRE_UIT();
+  if (!extensions::PrintPreviewEnabled()) {
+    return false;
+  }
+
+  return !GetPrefs()->GetBoolean(prefs::kPrintPreviewDisabled);
+}
+
+content::ResourceContext* AlloyBrowserContext::GetResourceContext() {
+  if (!resource_context_) {
+    resource_context_ = std::make_unique<content::ResourceContext>();
+  }
+  return resource_context_.get();
+}
+
+content::ClientHintsControllerDelegate*
+AlloyBrowserContext::GetClientHintsControllerDelegate() {
+  return nullptr;
+}
+
+ChromeZoomLevelPrefs* AlloyBrowserContext::GetZoomLevelPrefs() {
+  return static_cast<ChromeZoomLevelPrefs*>(
+      GetStoragePartition(nullptr)->GetZoomLevelDelegate());
+}
+
+scoped_refptr<network::SharedURLLoaderFactory>
+AlloyBrowserContext::GetURLLoaderFactory() {
+  return GetDefaultStoragePartition()->GetURLLoaderFactoryForBrowserProcess();
+}
+
+base::FilePath AlloyBrowserContext::GetPath() {
+  return cache_path_;
+}
+
+base::FilePath AlloyBrowserContext::GetPath() const {
+  return cache_path_;
+}
+
+std::unique_ptr<content::ZoomLevelDelegate>
+AlloyBrowserContext::CreateZoomLevelDelegate(
+    const base::FilePath& partition_path) {
+  if (cache_path_.empty()) {
+    return std::unique_ptr<content::ZoomLevelDelegate>();
+  }
+
+  return base::WrapUnique(new ChromeZoomLevelPrefs(
+      GetPrefs(), cache_path_, partition_path,
+      zoom::ZoomEventManager::GetForBrowserContext(this)->GetWeakPtr()));
+}
+
+content::DownloadManagerDelegate*
+AlloyBrowserContext::GetDownloadManagerDelegate() {
+  if (!download_manager_delegate_) {
+    download_manager_delegate_.reset(
+        new CefDownloadManagerDelegate(GetDownloadManager()));
+  }
+  return download_manager_delegate_.get();
+}
+
+content::BrowserPluginGuestManager* AlloyBrowserContext::GetGuestManager() {
+  if (!extensions::ExtensionsEnabled()) {
+    return nullptr;
+  }
+  return guest_view::GuestViewManager::FromBrowserContext(this);
+}
+
+storage::SpecialStoragePolicy* AlloyBrowserContext::GetSpecialStoragePolicy() {
+  return nullptr;
+}
+
+content::PlatformNotificationService*
+AlloyBrowserContext::GetPlatformNotificationService() {
+  return nullptr;
+}
+
+content::PushMessagingService* AlloyBrowserContext::GetPushMessagingService() {
+  return nullptr;
+}
+
+content::StorageNotificationService*
+AlloyBrowserContext::GetStorageNotificationService() {
+  return nullptr;
+}
+
+content::SSLHostStateDelegate* AlloyBrowserContext::GetSSLHostStateDelegate() {
+  if (!ssl_host_state_delegate_) {
+    ssl_host_state_delegate_.reset(new CefSSLHostStateDelegate());
+  }
+  return ssl_host_state_delegate_.get();
+}
+
+content::PermissionControllerDelegate*
+AlloyBrowserContext::GetPermissionControllerDelegate() {
+  return PermissionManagerFactory::GetForProfile(this);
+}
+
+content::BackgroundFetchDelegate*
+AlloyBrowserContext::GetBackgroundFetchDelegate() {
+  return nullptr;
+}
+
+content::BackgroundSyncController*
+AlloyBrowserContext::GetBackgroundSyncController() {
+  return nullptr;
+}
+
+content::BrowsingDataRemoverDelegate*
+AlloyBrowserContext::GetBrowsingDataRemoverDelegate() {
+  return nullptr;
+}
+
+content::ReduceAcceptLanguageControllerDelegate*
+AlloyBrowserContext::GetReduceAcceptLanguageControllerDelegate() {
+  return ReduceAcceptLanguageFactory::GetForProfile(this);
+}
+
+PrefService* AlloyBrowserContext::GetPrefs() {
+  return pref_service_.get();
+}
+
+const PrefService* AlloyBrowserContext::GetPrefs() const {
+  return pref_service_.get();
+}
+
+ProfileKey* AlloyBrowserContext::GetProfileKey() const {
+  DCHECK(key_);
+  return key_.get();
+}
+
+policy::SchemaRegistryService*
+AlloyBrowserContext::GetPolicySchemaRegistryService() {
+  DCHECK(false);
+  return nullptr;
+}
+
+policy::UserCloudPolicyManager*
+AlloyBrowserContext::GetUserCloudPolicyManager() {
+  DCHECK(false);
+  return nullptr;
+}
+
+policy::ProfileCloudPolicyManager*
+AlloyBrowserContext::GetProfileCloudPolicyManager() {
+  DCHECK(false);
+  return nullptr;
+}
+
+policy::ProfilePolicyConnector*
+AlloyBrowserContext::GetProfilePolicyConnector() {
+  DCHECK(false);
+  return nullptr;
+}
+
+const policy::ProfilePolicyConnector*
+AlloyBrowserContext::GetProfilePolicyConnector() const {
+  DCHECK(false);
+  return nullptr;
+}
+
+bool AlloyBrowserContext::IsNewProfile() const {
+  DCHECK(false);
+  return false;
+}
+
+void AlloyBrowserContext::RebuildTable(
+    const scoped_refptr<URLEnumerator>& enumerator) {
+  // Called when visited links will not or cannot be loaded from disk.
+  enumerator->OnComplete(true);
+}
+
+DownloadPrefs* AlloyBrowserContext::GetDownloadPrefs() {
+  CEF_REQUIRE_UIT();
+  if (!download_prefs_) {
+    download_prefs_.reset(new DownloadPrefs(this));
+  }
+  return download_prefs_.get();
+}
+
+void AlloyBrowserContext::AddVisitedURLs(const std::vector<GURL>& urls) {
+  visitedlink_master_->AddURLs(urls);
+}
diff --git a/src/libcef/browser/alloy/alloy_browser_context.h b/src/libcef/browser/alloy/alloy_browser_context.h
new file mode 100644
index 0000000..2a9c835
--- /dev/null
+++ b/src/libcef/browser/alloy/alloy_browser_context.h
@@ -0,0 +1,149 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_BROWSER_ALLOY_ALLOY_BROWSER_CONTEXT_H_
+#define CEF_LIBCEF_BROWSER_ALLOY_ALLOY_BROWSER_CONTEXT_H_
+#pragma once
+
+#include "include/cef_request_context_handler.h"
+#include "libcef/browser/alloy/chrome_profile_alloy.h"
+#include "libcef/browser/browser_context.h"
+#include "libcef/browser/request_context_handler_map.h"
+
+#include "chrome/browser/download/download_prefs.h"
+#include "components/proxy_config/pref_proxy_config_tracker.h"
+#include "components/visitedlink/browser/visitedlink_delegate.h"
+
+class CefDownloadManagerDelegate;
+class CefSSLHostStateDelegate;
+class CefVisitedLinkListener;
+class PrefService;
+
+namespace extensions {
+class CefExtensionSystem;
+}
+
+namespace visitedlink {
+class VisitedLinkWriter;
+}
+
+// See CefBrowserContext documentation for usage. Only accessed on the UI thread
+// unless otherwise indicated. ChromeProfileAlloy must be the first listed base
+// class to avoid issues when casting between void* and content::BrowserContext*
+// in Chromium code.
+class AlloyBrowserContext : public ChromeProfileAlloy,
+                            public CefBrowserContext,
+                            public visitedlink::VisitedLinkDelegate {
+ public:
+  explicit AlloyBrowserContext(const CefRequestContextSettings& settings);
+
+  AlloyBrowserContext(const AlloyBrowserContext&) = delete;
+  AlloyBrowserContext& operator=(const AlloyBrowserContext&) = delete;
+
+  // CefBrowserContext overrides.
+  content::BrowserContext* AsBrowserContext() override { return this; }
+  Profile* AsProfile() override { return this; }
+  bool IsInitialized() const override;
+  void StoreOrTriggerInitCallback(base::OnceClosure callback) override;
+  void Initialize() override;
+  void Shutdown() override;
+  void RemoveCefRequestContext(CefRequestContextImpl* context) override;
+  void LoadExtension(const CefString& root_directory,
+                     CefRefPtr<CefDictionaryValue> manifest,
+                     CefRefPtr<CefExtensionHandler> handler,
+                     CefRefPtr<CefRequestContext> loader_context) override;
+  bool GetExtensions(std::vector<CefString>& extension_ids) override;
+  CefRefPtr<CefExtension> GetExtension(const CefString& extension_id) override;
+  bool UnloadExtension(const CefString& extension_id) override;
+  bool IsPrintPreviewSupported() const override;
+
+  // content::BrowserContext overrides.
+  content::ResourceContext* GetResourceContext() override;
+  content::ClientHintsControllerDelegate* GetClientHintsControllerDelegate()
+      override;
+  base::FilePath GetPath() override;
+  base::FilePath GetPath() const override;
+  std::unique_ptr<content::ZoomLevelDelegate> CreateZoomLevelDelegate(
+      const base::FilePath& partition_path) override;
+  content::DownloadManagerDelegate* GetDownloadManagerDelegate() override;
+  content::BrowserPluginGuestManager* GetGuestManager() override;
+  storage::SpecialStoragePolicy* GetSpecialStoragePolicy() override;
+  content::PlatformNotificationService* GetPlatformNotificationService()
+      override;
+  content::PushMessagingService* GetPushMessagingService() override;
+  content::StorageNotificationService* GetStorageNotificationService() override;
+  content::SSLHostStateDelegate* GetSSLHostStateDelegate() override;
+  content::PermissionControllerDelegate* GetPermissionControllerDelegate()
+      override;
+  content::BackgroundFetchDelegate* GetBackgroundFetchDelegate() override;
+  content::BackgroundSyncController* GetBackgroundSyncController() override;
+  content::BrowsingDataRemoverDelegate* GetBrowsingDataRemoverDelegate()
+      override;
+  content::ReduceAcceptLanguageControllerDelegate*
+  GetReduceAcceptLanguageControllerDelegate() override;
+
+  // Profile overrides.
+  ChromeZoomLevelPrefs* GetZoomLevelPrefs() override;
+  scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
+  PrefService* GetPrefs() override;
+  bool AllowsBrowserWindows() const override { return false; }
+  const PrefService* GetPrefs() const override;
+  ProfileKey* GetProfileKey() const override;
+  policy::SchemaRegistryService* GetPolicySchemaRegistryService() override;
+  policy::UserCloudPolicyManager* GetUserCloudPolicyManager() override;
+  policy::ProfileCloudPolicyManager* GetProfileCloudPolicyManager() override;
+  policy::ProfilePolicyConnector* GetProfilePolicyConnector() override;
+  const policy::ProfilePolicyConnector* GetProfilePolicyConnector()
+      const override;
+  bool IsNewProfile() const override;
+
+  // Values checked in ProfileNetworkContextService::CreateNetworkContextParams
+  // when creating the NetworkContext.
+  bool ShouldRestoreOldSessionCookies() override {
+    return ShouldPersistSessionCookies();
+  }
+  bool ShouldPersistSessionCookies() const override {
+    return !!settings_.persist_session_cookies;
+  }
+
+  // visitedlink::VisitedLinkDelegate methods.
+  void RebuildTable(const scoped_refptr<URLEnumerator>& enumerator) override;
+
+  // Manages extensions.
+  extensions::CefExtensionSystem* extension_system() const {
+    return extension_system_;
+  }
+
+  // Called from AlloyBrowserHostImpl::DidFinishNavigation to update the table
+  // of visited links.
+  void AddVisitedURLs(const std::vector<GURL>& urls);
+
+  // Called from DownloadPrefs::FromBrowserContext.
+  DownloadPrefs* GetDownloadPrefs();
+
+ private:
+  ~AlloyBrowserContext() override;
+
+  std::unique_ptr<PrefService> pref_service_;
+  std::unique_ptr<PrefProxyConfigTracker> pref_proxy_config_tracker_;
+
+  std::unique_ptr<CefDownloadManagerDelegate> download_manager_delegate_;
+  std::unique_ptr<CefSSLHostStateDelegate> ssl_host_state_delegate_;
+  std::unique_ptr<visitedlink::VisitedLinkWriter> visitedlink_master_;
+  // |visitedlink_listener_| is owned by visitedlink_master_.
+  CefVisitedLinkListener* visitedlink_listener_ = nullptr;
+
+  // Owned by the KeyedService system.
+  extensions::CefExtensionSystem* extension_system_ = nullptr;
+
+  // The key to index KeyedService instances created by
+  // SimpleKeyedServiceFactory.
+  std::unique_ptr<ProfileKey> key_;
+
+  std::unique_ptr<DownloadPrefs> download_prefs_;
+
+  std::unique_ptr<content::ResourceContext> resource_context_;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_ALLOY_ALLOY_BROWSER_CONTEXT_H_
diff --git a/src/libcef/browser/alloy/alloy_browser_host_impl.cc b/src/libcef/browser/alloy/alloy_browser_host_impl.cc
new file mode 100644
index 0000000..703b040
--- /dev/null
+++ b/src/libcef/browser/alloy/alloy_browser_host_impl.cc
@@ -0,0 +1,1486 @@
+// Copyright (c) 2012 The Chromium Embedded Framework Authors.
+// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
+
+#include <string>
+#include <utility>
+
+#include "libcef/browser/alloy/alloy_browser_context.h"
+#include "libcef/browser/alloy/browser_platform_delegate_alloy.h"
+#include "libcef/browser/audio_capturer.h"
+#include "libcef/browser/browser_context.h"
+#include "libcef/browser/browser_info.h"
+#include "libcef/browser/browser_info_manager.h"
+#include "libcef/browser/browser_platform_delegate.h"
+#include "libcef/browser/context.h"
+#include "libcef/browser/devtools/devtools_manager.h"
+#include "libcef/browser/media_access_query.h"
+#include "libcef/browser/osr/osr_util.h"
+#include "libcef/browser/request_context_impl.h"
+#include "libcef/browser/thread_util.h"
+#include "libcef/common/cef_switches.h"
+#include "libcef/common/drag_data_impl.h"
+#include "libcef/common/frame_util.h"
+#include "libcef/common/net/url_util.h"
+#include "libcef/common/request_impl.h"
+#include "libcef/common/values_impl.h"
+#include "libcef/features/runtime_checks.h"
+
+#include "base/command_line.h"
+#include "base/functional/bind.h"
+#include "base/functional/callback_helpers.h"
+#include "chrome/browser/file_select_helper.h"
+#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
+#include "components/zoom/page_zoom.h"
+#include "content/browser/gpu/compositor_util.h"
+#include "content/public/browser/desktop_media_id.h"
+#include "content/public/browser/file_select_listener.h"
+#include "content/public/browser/keyboard_event_processing_result.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/input/native_web_keyboard_event.h"
+#include "content/public/common/url_constants.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/extension.h"
+#include "net/base/net_errors.h"
+#include "ui/events/base_event_utils.h"
+
+using content::KeyboardEventProcessingResult;
+
+namespace {
+
+static constexpr base::TimeDelta kRecentlyAudibleTimeout = base::Seconds(2);
+
+}  // namespace
+
+// AlloyBrowserHostImpl static methods.
+// -----------------------------------------------------------------------------
+
+// static
+CefRefPtr<AlloyBrowserHostImpl> AlloyBrowserHostImpl::Create(
+    CefBrowserCreateParams& create_params) {
+  std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate =
+      CefBrowserPlatformDelegate::Create(create_params);
+  CHECK(platform_delegate);
+
+  const bool is_devtools_popup = !!create_params.devtools_opener;
+
+  scoped_refptr<CefBrowserInfo> info =
+      CefBrowserInfoManager::GetInstance()->CreateBrowserInfo(
+          is_devtools_popup, platform_delegate->IsWindowless(),
+          create_params.extra_info);
+
+  bool own_web_contents = false;
+
+  // This call may modify |create_params|.
+  auto web_contents =
+      platform_delegate->CreateWebContents(create_params, own_web_contents);
+
+  auto request_context_impl =
+      static_cast<CefRequestContextImpl*>(create_params.request_context.get());
+
+  CefRefPtr<CefExtension> cef_extension;
+  if (create_params.extension) {
+    auto cef_browser_context = request_context_impl->GetBrowserContext();
+    cef_extension =
+        cef_browser_context->GetExtension(create_params.extension->id());
+    CHECK(cef_extension);
+  }
+
+  auto platform_delegate_ptr = platform_delegate.get();
+
+  CefRefPtr<AlloyBrowserHostImpl> browser = CreateInternal(
+      create_params.settings, create_params.client, web_contents,
+      own_web_contents, info,
+      static_cast<AlloyBrowserHostImpl*>(create_params.devtools_opener.get()),
+      is_devtools_popup, request_context_impl, std::move(platform_delegate),
+      cef_extension);
+  if (!browser) {
+    return nullptr;
+  }
+
+  GURL url = url_util::MakeGURL(create_params.url, /*fixup=*/true);
+
+  if (create_params.extension) {
+    platform_delegate_ptr->CreateExtensionHost(
+        create_params.extension, url, create_params.extension_host_type);
+  } else if (!url.is_empty()) {
+    content::OpenURLParams params(url, content::Referrer(),
+                                  WindowOpenDisposition::CURRENT_TAB,
+                                  CefFrameHostImpl::kPageTransitionExplicit,
+                                  /*is_renderer_initiated=*/false);
+    browser->LoadMainFrameURL(params);
+  }
+
+  return browser.get();
+}
+
+// static
+CefRefPtr<AlloyBrowserHostImpl> AlloyBrowserHostImpl::CreateInternal(
+    const CefBrowserSettings& settings,
+    CefRefPtr<CefClient> client,
+    content::WebContents* web_contents,
+    bool own_web_contents,
+    scoped_refptr<CefBrowserInfo> browser_info,
+    CefRefPtr<AlloyBrowserHostImpl> opener,
+    bool is_devtools_popup,
+    CefRefPtr<CefRequestContextImpl> request_context,
+    std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
+    CefRefPtr<CefExtension> extension) {
+  CEF_REQUIRE_UIT();
+  DCHECK(web_contents);
+  DCHECK(browser_info);
+  DCHECK(request_context);
+  DCHECK(platform_delegate);
+
+  // If |opener| is non-NULL it must be a popup window.
+  DCHECK(!opener.get() || browser_info->is_popup());
+
+  if (opener) {
+    if (!opener->platform_delegate_) {
+      // The opener window is being destroyed. Cancel the popup.
+      if (own_web_contents) {
+        delete web_contents;
+      }
+      return nullptr;
+    }
+
+    // Give the opener browser's platform delegate an opportunity to modify the
+    // new browser's platform delegate.
+    opener->platform_delegate_->PopupWebContentsCreated(
+        settings, client, web_contents, platform_delegate.get(),
+        is_devtools_popup);
+  }
+
+  // Take ownership of |web_contents| if |own_web_contents| is true.
+  platform_delegate->WebContentsCreated(web_contents, own_web_contents);
+
+  CefRefPtr<AlloyBrowserHostImpl> browser = new AlloyBrowserHostImpl(
+      settings, client, web_contents, browser_info, opener, request_context,
+      std::move(platform_delegate), extension);
+  browser->InitializeBrowser();
+
+  if (!browser->CreateHostWindow()) {
+    return nullptr;
+  }
+
+  // Notify that the browser has been created. These must be delivered in the
+  // expected order.
+
+  if (opener && opener->platform_delegate_) {
+    // 1. Notify the opener browser's platform delegate. With Views this will
+    // result in a call to CefBrowserViewDelegate::OnPopupBrowserViewCreated().
+    // Do this first for consistency with the Chrome runtime.
+    opener->platform_delegate_->PopupBrowserCreated(browser.get(),
+                                                    is_devtools_popup);
+  }
+
+  // 2. Notify the browser's LifeSpanHandler. This must always be the first
+  // notification for the browser. Block navigation to avoid issues with focus
+  // changes being sent to an unbound interface.
+  {
+    auto navigation_lock = browser_info->CreateNavigationLock();
+    browser->OnAfterCreated();
+  }
+
+  // 3. Notify the platform delegate. With Views this will result in a call to
+  // CefBrowserViewDelegate::OnBrowserCreated().
+  browser->platform_delegate_->NotifyBrowserCreated();
+
+  return browser;
+}
+
+// static
+CefRefPtr<AlloyBrowserHostImpl> AlloyBrowserHostImpl::GetBrowserForHost(
+    const content::RenderViewHost* host) {
+  REQUIRE_ALLOY_RUNTIME();
+  auto browser = CefBrowserHostBase::GetBrowserForHost(host);
+  return static_cast<AlloyBrowserHostImpl*>(browser.get());
+}
+
+// static
+CefRefPtr<AlloyBrowserHostImpl> AlloyBrowserHostImpl::GetBrowserForHost(
+    const content::RenderFrameHost* host) {
+  REQUIRE_ALLOY_RUNTIME();
+  auto browser = CefBrowserHostBase::GetBrowserForHost(host);
+  return static_cast<AlloyBrowserHostImpl*>(browser.get());
+}
+
+// static
+CefRefPtr<AlloyBrowserHostImpl> AlloyBrowserHostImpl::GetBrowserForContents(
+    const content::WebContents* contents) {
+  REQUIRE_ALLOY_RUNTIME();
+  auto browser = CefBrowserHostBase::GetBrowserForContents(contents);
+  return static_cast<AlloyBrowserHostImpl*>(browser.get());
+}
+
+// static
+CefRefPtr<AlloyBrowserHostImpl> AlloyBrowserHostImpl::GetBrowserForGlobalId(
+    const content::GlobalRenderFrameHostId& global_id) {
+  REQUIRE_ALLOY_RUNTIME();
+  auto browser = CefBrowserHostBase::GetBrowserForGlobalId(global_id);
+  return static_cast<AlloyBrowserHostImpl*>(browser.get());
+}
+
+// AlloyBrowserHostImpl methods.
+// -----------------------------------------------------------------------------
+
+AlloyBrowserHostImpl::~AlloyBrowserHostImpl() {}
+
+void AlloyBrowserHostImpl::CloseBrowser(bool force_close) {
+  if (CEF_CURRENTLY_ON_UIT()) {
+    // Exit early if a close attempt is already pending and this method is
+    // called again from somewhere other than WindowDestroyed().
+    if (destruction_state_ >= DESTRUCTION_STATE_PENDING &&
+        (IsWindowless() || !window_destroyed_)) {
+      if (force_close && destruction_state_ == DESTRUCTION_STATE_PENDING) {
+        // Upgrade the destruction state.
+        destruction_state_ = DESTRUCTION_STATE_ACCEPTED;
+      }
+      return;
+    }
+
+    if (destruction_state_ < DESTRUCTION_STATE_ACCEPTED) {
+      destruction_state_ = (force_close ? DESTRUCTION_STATE_ACCEPTED
+                                        : DESTRUCTION_STATE_PENDING);
+    }
+
+    content::WebContents* contents = web_contents();
+    if (contents && contents->NeedToFireBeforeUnloadOrUnloadEvents()) {
+      // Will result in a call to BeforeUnloadFired() and, if the close isn't
+      // canceled, CloseContents().
+      contents->DispatchBeforeUnload(false /* auto_cancel */);
+    } else {
+      CloseContents(contents);
+    }
+  } else {
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(&AlloyBrowserHostImpl::CloseBrowser,
+                                          this, force_close));
+  }
+}
+
+bool AlloyBrowserHostImpl::TryCloseBrowser() {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    DCHECK(false) << "called on invalid thread";
+    return false;
+  }
+
+  // Protect against multiple requests to close while the close is pending.
+  if (destruction_state_ <= DESTRUCTION_STATE_PENDING) {
+    if (destruction_state_ == DESTRUCTION_STATE_NONE) {
+      // Request that the browser close.
+      CloseBrowser(false);
+    }
+
+    // Cancel the close.
+    return false;
+  }
+
+  // Allow the close.
+  return true;
+}
+
+CefWindowHandle AlloyBrowserHostImpl::GetWindowHandle() {
+  if (is_views_hosted_ && CEF_CURRENTLY_ON_UIT()) {
+    // Always return the most up-to-date window handle for a views-hosted
+    // browser since it may change if the view is re-parented.
+    if (platform_delegate_) {
+      return platform_delegate_->GetHostWindowHandle();
+    }
+  }
+  return host_window_handle_;
+}
+
+CefWindowHandle AlloyBrowserHostImpl::GetOpenerWindowHandle() {
+  return opener_;
+}
+
+void AlloyBrowserHostImpl::Find(const CefString& searchText,
+                                bool forward,
+                                bool matchCase,
+                                bool findNext) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&AlloyBrowserHostImpl::Find, this, searchText,
+                                 forward, matchCase, findNext));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->Find(searchText, forward, matchCase, findNext);
+  }
+}
+
+void AlloyBrowserHostImpl::StopFinding(bool clearSelection) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(&AlloyBrowserHostImpl::StopFinding,
+                                          this, clearSelection));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->StopFinding(clearSelection);
+  }
+}
+
+void AlloyBrowserHostImpl::ShowDevToolsOnUIThread(
+    std::unique_ptr<CefShowDevToolsParams> params) {
+  CEF_REQUIRE_UIT();
+  if (!EnsureDevToolsManager()) {
+    return;
+  }
+  devtools_manager_->ShowDevTools(params->window_info_, params->client_,
+                                  params->settings_,
+                                  params->inspect_element_at_);
+}
+
+void AlloyBrowserHostImpl::CloseDevTools() {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&AlloyBrowserHostImpl::CloseDevTools, this));
+    return;
+  }
+
+  if (!devtools_manager_) {
+    return;
+  }
+  devtools_manager_->CloseDevTools();
+}
+
+bool AlloyBrowserHostImpl::HasDevTools() {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    DCHECK(false) << "called on invalid thread";
+    return false;
+  }
+
+  if (!devtools_manager_) {
+    return false;
+  }
+  return devtools_manager_->HasDevTools();
+}
+
+void AlloyBrowserHostImpl::SetAccessibilityState(
+    cef_state_t accessibility_state) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&AlloyBrowserHostImpl::SetAccessibilityState,
+                                 this, accessibility_state));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->SetAccessibilityState(accessibility_state);
+  }
+}
+
+void AlloyBrowserHostImpl::SetAutoResizeEnabled(bool enabled,
+                                                const CefSize& min_size,
+                                                const CefSize& max_size) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&AlloyBrowserHostImpl::SetAutoResizeEnabled,
+                                 this, enabled, min_size, max_size));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->SetAutoResizeEnabled(enabled, min_size, max_size);
+  }
+}
+
+CefRefPtr<CefExtension> AlloyBrowserHostImpl::GetExtension() {
+  return extension_;
+}
+
+bool AlloyBrowserHostImpl::IsBackgroundHost() {
+  return is_background_host_;
+}
+
+bool AlloyBrowserHostImpl::CanExecuteChromeCommand(int command_id) {
+  return false;
+}
+
+void AlloyBrowserHostImpl::ExecuteChromeCommand(
+    int command_id,
+    cef_window_open_disposition_t disposition) {
+  NOTIMPLEMENTED();
+}
+
+bool AlloyBrowserHostImpl::IsWindowRenderingDisabled() {
+  return IsWindowless();
+}
+
+void AlloyBrowserHostImpl::WasResized() {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&AlloyBrowserHostImpl::WasResized, this));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->WasResized();
+  }
+}
+
+void AlloyBrowserHostImpl::WasHidden(bool hidden) {
+  if (!IsWindowless()) {
+    DCHECK(false) << "Window rendering is not disabled";
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&CefBrowserHost::WasHidden, this, hidden));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->WasHidden(hidden);
+  }
+}
+
+void AlloyBrowserHostImpl::NotifyScreenInfoChanged() {
+  if (!IsWindowless()) {
+    DCHECK(false) << "Window rendering is not disabled";
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(&AlloyBrowserHostImpl::NotifyScreenInfoChanged, this));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->NotifyScreenInfoChanged();
+  }
+}
+
+void AlloyBrowserHostImpl::Invalidate(PaintElementType type) {
+  if (!IsWindowless()) {
+    DCHECK(false) << "Window rendering is not disabled";
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT, base::BindOnce(&AlloyBrowserHostImpl::Invalidate, this, type));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->Invalidate(type);
+  }
+}
+
+void AlloyBrowserHostImpl::SendExternalBeginFrame() {
+  if (!IsWindowless()) {
+    DCHECK(false) << "Window rendering is not disabled";
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(&AlloyBrowserHostImpl::SendExternalBeginFrame, this));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->SendExternalBeginFrame();
+  }
+}
+
+void AlloyBrowserHostImpl::SendTouchEvent(const CefTouchEvent& event) {
+  if (!IsWindowless()) {
+    DCHECK(false) << "Window rendering is not disabled";
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(&AlloyBrowserHostImpl::SendTouchEvent,
+                                          this, event));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->SendTouchEvent(event);
+  }
+}
+
+void AlloyBrowserHostImpl::SendCaptureLostEvent() {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(&AlloyBrowserHostImpl::SendCaptureLostEvent, this));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->SendCaptureLostEvent();
+  }
+}
+
+int AlloyBrowserHostImpl::GetWindowlessFrameRate() {
+  // Verify that this method is being called on the UI thread.
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    DCHECK(false) << "called on invalid thread";
+    return 0;
+  }
+
+  return osr_util::ClampFrameRate(settings_.windowless_frame_rate);
+}
+
+void AlloyBrowserHostImpl::SetWindowlessFrameRate(int frame_rate) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&AlloyBrowserHostImpl::SetWindowlessFrameRate,
+                                 this, frame_rate));
+    return;
+  }
+
+  settings_.windowless_frame_rate = frame_rate;
+
+  if (platform_delegate_) {
+    platform_delegate_->SetWindowlessFrameRate(frame_rate);
+  }
+}
+
+// AlloyBrowserHostImpl public methods.
+// -----------------------------------------------------------------------------
+
+bool AlloyBrowserHostImpl::IsWindowless() const {
+  return is_windowless_;
+}
+
+bool AlloyBrowserHostImpl::IsVisible() const {
+  CEF_REQUIRE_UIT();
+  if (IsWindowless() && platform_delegate_) {
+    return !platform_delegate_->IsHidden();
+  }
+  return CefBrowserHostBase::IsVisible();
+}
+
+bool AlloyBrowserHostImpl::IsPictureInPictureSupported() const {
+  // Not currently supported with OSR.
+  return !IsWindowless();
+}
+
+void AlloyBrowserHostImpl::WindowDestroyed() {
+  CEF_REQUIRE_UIT();
+  DCHECK(!window_destroyed_);
+  window_destroyed_ = true;
+  CloseBrowser(true);
+}
+
+bool AlloyBrowserHostImpl::WillBeDestroyed() const {
+  CEF_REQUIRE_UIT();
+  return destruction_state_ >= DESTRUCTION_STATE_ACCEPTED;
+}
+
+void AlloyBrowserHostImpl::DestroyBrowser() {
+  CEF_REQUIRE_UIT();
+
+  destruction_state_ = DESTRUCTION_STATE_COMPLETED;
+
+  // Notify that this browser has been destroyed. These must be delivered in
+  // the expected order.
+
+  // 1. Notify the platform delegate. With Views this will result in a call to
+  // CefBrowserViewDelegate::OnBrowserDestroyed().
+  platform_delegate_->NotifyBrowserDestroyed();
+
+  // 2. Notify the browser's LifeSpanHandler. This must always be the last
+  // notification for this browser.
+  OnBeforeClose();
+
+  // Destroy any platform constructs first.
+  if (javascript_dialog_manager_.get()) {
+    javascript_dialog_manager_->Destroy();
+  }
+  if (menu_manager_.get()) {
+    menu_manager_->Destroy();
+  }
+
+  // Notify any observers that may have state associated with this browser.
+  OnBrowserDestroyed();
+
+  // If the WebContents still exists at this point, signal destruction before
+  // browser destruction.
+  if (web_contents()) {
+    WebContentsDestroyed();
+  }
+
+  // Disassociate the platform delegate from this browser.
+  platform_delegate_->BrowserDestroyed(this);
+
+  // Delete objects created by the platform delegate that may be referenced by
+  // the WebContents.
+  file_dialog_manager_.reset(nullptr);
+  javascript_dialog_manager_.reset(nullptr);
+  menu_manager_.reset(nullptr);
+
+  // Delete the audio capturer
+  if (recently_audible_timer_) {
+    recently_audible_timer_->Stop();
+    recently_audible_timer_.reset();
+  }
+  audio_capturer_.reset(nullptr);
+
+  CefBrowserHostBase::DestroyBrowser();
+}
+
+void AlloyBrowserHostImpl::CancelContextMenu() {
+  CEF_REQUIRE_UIT();
+  if (menu_manager_) {
+    menu_manager_->CancelContextMenu();
+  }
+}
+
+bool AlloyBrowserHostImpl::MaybeAllowNavigation(
+    content::RenderFrameHost* opener,
+    bool is_guest_view,
+    const content::OpenURLParams& params) {
+  if (is_guest_view && !params.is_pdf &&
+      !params.url.SchemeIs(extensions::kExtensionScheme) &&
+      !params.url.SchemeIs(content::kChromeUIScheme)) {
+    // The PDF viewer will load the PDF extension in the guest view, and print
+    // preview will load chrome://print in the guest view. The PDF renderer
+    // used with PdfUnseasoned will set |params.is_pdf| when loading the PDF
+    // stream (see PdfNavigationThrottle::WillStartRequest). All other
+    // navigations are passed to the owner browser.
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(
+                      base::IgnoreResult(&AlloyBrowserHostImpl::OpenURLFromTab),
+                      this, nullptr, params));
+
+    return false;
+  }
+
+  return true;
+}
+
+extensions::ExtensionHost* AlloyBrowserHostImpl::GetExtensionHost() const {
+  CEF_REQUIRE_UIT();
+  DCHECK(platform_delegate_);
+  return platform_delegate_->GetExtensionHost();
+}
+
+void AlloyBrowserHostImpl::OnSetFocus(cef_focus_source_t source) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(&AlloyBrowserHostImpl::OnSetFocus,
+                                          this, source));
+    return;
+  }
+
+  if (contents_delegate_->OnSetFocus(source)) {
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->SetFocus(true);
+  }
+}
+
+void AlloyBrowserHostImpl::EnterFullscreenModeForTab(
+    content::RenderFrameHost* requesting_frame,
+    const blink::mojom::FullscreenOptions& options) {
+  contents_delegate_->EnterFullscreenModeForTab(requesting_frame, options);
+  WasResized();
+}
+
+void AlloyBrowserHostImpl::ExitFullscreenModeForTab(
+    content::WebContents* web_contents) {
+  contents_delegate_->ExitFullscreenModeForTab(web_contents);
+  WasResized();
+}
+
+bool AlloyBrowserHostImpl::IsFullscreenForTabOrPending(
+    const content::WebContents* web_contents) {
+  return is_fullscreen_;
+}
+
+blink::mojom::DisplayMode AlloyBrowserHostImpl::GetDisplayMode(
+    const content::WebContents* web_contents) {
+  return is_fullscreen_ ? blink::mojom::DisplayMode::kFullscreen
+                        : blink::mojom::DisplayMode::kBrowser;
+}
+
+void AlloyBrowserHostImpl::FindReply(content::WebContents* web_contents,
+                                     int request_id,
+                                     int number_of_matches,
+                                     const gfx::Rect& selection_rect,
+                                     int active_match_ordinal,
+                                     bool final_update) {
+  auto alloy_delegate =
+      static_cast<CefBrowserPlatformDelegateAlloy*>(platform_delegate());
+  if (alloy_delegate->HandleFindReply(request_id, number_of_matches,
+                                      selection_rect, active_match_ordinal,
+                                      final_update)) {
+    if (client_) {
+      if (auto handler = client_->GetFindHandler()) {
+        const auto& details = alloy_delegate->last_search_result();
+        CefRect rect(details.selection_rect().x(), details.selection_rect().y(),
+                     details.selection_rect().width(),
+                     details.selection_rect().height());
+        handler->OnFindResult(
+            this, details.request_id(), details.number_of_matches(), rect,
+            details.active_match_ordinal(), details.final_update());
+      }
+    }
+  }
+}
+
+void AlloyBrowserHostImpl::ImeSetComposition(
+    const CefString& text,
+    const std::vector<CefCompositionUnderline>& underlines,
+    const CefRange& replacement_range,
+    const CefRange& selection_range) {
+  if (!IsWindowless()) {
+    DCHECK(false) << "Window rendering is not disabled";
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(&AlloyBrowserHostImpl::ImeSetComposition, this, text,
+                       underlines, replacement_range, selection_range));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->ImeSetComposition(text, underlines, replacement_range,
+                                          selection_range);
+  }
+}
+
+void AlloyBrowserHostImpl::ImeCommitText(const CefString& text,
+                                         const CefRange& replacement_range,
+                                         int relative_cursor_pos) {
+  if (!IsWindowless()) {
+    DCHECK(false) << "Window rendering is not disabled";
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&AlloyBrowserHostImpl::ImeCommitText, this,
+                                 text, replacement_range, relative_cursor_pos));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->ImeCommitText(text, replacement_range,
+                                      relative_cursor_pos);
+  }
+}
+
+void AlloyBrowserHostImpl::ImeFinishComposingText(bool keep_selection) {
+  if (!IsWindowless()) {
+    DCHECK(false) << "Window rendering is not disabled";
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&AlloyBrowserHostImpl::ImeFinishComposingText,
+                                 this, keep_selection));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->ImeFinishComposingText(keep_selection);
+  }
+}
+
+void AlloyBrowserHostImpl::ImeCancelComposition() {
+  if (!IsWindowless()) {
+    DCHECK(false) << "Window rendering is not disabled";
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(&AlloyBrowserHostImpl::ImeCancelComposition, this));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->ImeCancelComposition();
+  }
+}
+
+void AlloyBrowserHostImpl::DragTargetDragEnter(
+    CefRefPtr<CefDragData> drag_data,
+    const CefMouseEvent& event,
+    CefBrowserHost::DragOperationsMask allowed_ops) {
+  if (!IsWindowless()) {
+    DCHECK(false) << "Window rendering is not disabled";
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&AlloyBrowserHostImpl::DragTargetDragEnter,
+                                 this, drag_data, event, allowed_ops));
+    return;
+  }
+
+  if (!drag_data.get()) {
+    DCHECK(false);
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->DragTargetDragEnter(drag_data, event, allowed_ops);
+  }
+}
+
+void AlloyBrowserHostImpl::DragTargetDragOver(
+    const CefMouseEvent& event,
+    CefBrowserHost::DragOperationsMask allowed_ops) {
+  if (!IsWindowless()) {
+    DCHECK(false) << "Window rendering is not disabled";
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT, base::BindOnce(&AlloyBrowserHostImpl::DragTargetDragOver, this,
+                                event, allowed_ops));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->DragTargetDragOver(event, allowed_ops);
+  }
+}
+
+void AlloyBrowserHostImpl::DragTargetDragLeave() {
+  if (!IsWindowless()) {
+    DCHECK(false) << "Window rendering is not disabled";
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(&AlloyBrowserHostImpl::DragTargetDragLeave, this));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->DragTargetDragLeave();
+  }
+}
+
+void AlloyBrowserHostImpl::DragTargetDrop(const CefMouseEvent& event) {
+  if (!IsWindowless()) {
+    DCHECK(false) << "Window rendering is not disabled";
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(&AlloyBrowserHostImpl::DragTargetDrop,
+                                          this, event));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->DragTargetDrop(event);
+  }
+}
+
+void AlloyBrowserHostImpl::DragSourceSystemDragEnded() {
+  if (!IsWindowless()) {
+    DCHECK(false) << "Window rendering is not disabled";
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(&AlloyBrowserHostImpl::DragSourceSystemDragEnded, this));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->DragSourceSystemDragEnded();
+  }
+}
+
+void AlloyBrowserHostImpl::DragSourceEndedAt(
+    int x,
+    int y,
+    CefBrowserHost::DragOperationsMask op) {
+  if (!IsWindowless()) {
+    DCHECK(false) << "Window rendering is not disabled";
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&AlloyBrowserHostImpl::DragSourceEndedAt, this,
+                                 x, y, op));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->DragSourceEndedAt(x, y, op);
+  }
+}
+
+void AlloyBrowserHostImpl::SetAudioMuted(bool mute) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(&AlloyBrowserHostImpl::SetAudioMuted,
+                                          this, mute));
+    return;
+  }
+  if (!web_contents()) {
+    return;
+  }
+  web_contents()->SetAudioMuted(mute);
+}
+
+bool AlloyBrowserHostImpl::IsAudioMuted() {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    DCHECK(false) << "called on invalid thread";
+    return false;
+  }
+  if (!web_contents()) {
+    return false;
+  }
+  return web_contents()->IsAudioMuted();
+}
+
+// content::WebContentsDelegate methods.
+// -----------------------------------------------------------------------------
+
+content::WebContents* AlloyBrowserHostImpl::OpenURLFromTab(
+    content::WebContents* source,
+    const content::OpenURLParams& params) {
+  auto target_contents = contents_delegate_->OpenURLFromTab(source, params);
+  if (target_contents) {
+    // Start a navigation in the current browser that will result in the
+    // creation of a new render process.
+    LoadMainFrameURL(params);
+    return target_contents;
+  }
+
+  // Cancel the navigation.
+  return nullptr;
+}
+
+bool AlloyBrowserHostImpl::ShouldAllowRendererInitiatedCrossProcessNavigation(
+    bool is_main_frame_navigation) {
+  return platform_delegate_->ShouldAllowRendererInitiatedCrossProcessNavigation(
+      is_main_frame_navigation);
+}
+
+void AlloyBrowserHostImpl::AddNewContents(
+    content::WebContents* source,
+    std::unique_ptr<content::WebContents> new_contents,
+    const GURL& target_url,
+    WindowOpenDisposition disposition,
+    const blink::mojom::WindowFeatures& window_features,
+    bool user_gesture,
+    bool* was_blocked) {
+  platform_delegate_->AddNewContents(source, std::move(new_contents),
+                                     target_url, disposition, window_features,
+                                     user_gesture, was_blocked);
+}
+
+void AlloyBrowserHostImpl::LoadingStateChanged(content::WebContents* source,
+                                               bool should_show_loading_ui) {
+  contents_delegate_->LoadingStateChanged(source, should_show_loading_ui);
+}
+
+void AlloyBrowserHostImpl::CloseContents(content::WebContents* source) {
+  CEF_REQUIRE_UIT();
+
+  if (destruction_state_ == DESTRUCTION_STATE_COMPLETED) {
+    return;
+  }
+
+  bool close_browser = true;
+
+  // If this method is called in response to something other than
+  // WindowDestroyed() ask the user if the browser should close.
+  if (client_.get() && (IsWindowless() || !window_destroyed_)) {
+    CefRefPtr<CefLifeSpanHandler> handler = client_->GetLifeSpanHandler();
+    if (handler.get()) {
+      close_browser = !handler->DoClose(this);
+    }
+  }
+
+  if (close_browser) {
+    if (destruction_state_ != DESTRUCTION_STATE_ACCEPTED) {
+      destruction_state_ = DESTRUCTION_STATE_ACCEPTED;
+    }
+
+    if (!IsWindowless() && !window_destroyed_) {
+      // A window exists so try to close it using the platform method. Will
+      // result in a call to WindowDestroyed() if/when the window is destroyed
+      // via the platform window destruction mechanism.
+      platform_delegate_->CloseHostWindow();
+    } else {
+      // Keep a reference to the browser while it's in the process of being
+      // destroyed.
+      CefRefPtr<AlloyBrowserHostImpl> browser(this);
+
+      if (source) {
+        // Try to fast shutdown the associated process.
+        source->GetPrimaryMainFrame()->GetProcess()->FastShutdownIfPossible(
+            1, false);
+      }
+
+      // No window exists. Destroy the browser immediately. Don't call other
+      // browser methods after calling DestroyBrowser().
+      DestroyBrowser();
+    }
+  } else if (destruction_state_ != DESTRUCTION_STATE_NONE) {
+    destruction_state_ = DESTRUCTION_STATE_NONE;
+  }
+}
+
+void AlloyBrowserHostImpl::UpdateTargetURL(content::WebContents* source,
+                                           const GURL& url) {
+  contents_delegate_->UpdateTargetURL(source, url);
+}
+
+bool AlloyBrowserHostImpl::DidAddMessageToConsole(
+    content::WebContents* source,
+    blink::mojom::ConsoleMessageLevel level,
+    const std::u16string& message,
+    int32_t line_no,
+    const std::u16string& source_id) {
+  return contents_delegate_->DidAddMessageToConsole(source, level, message,
+                                                    line_no, source_id);
+}
+
+void AlloyBrowserHostImpl::ContentsZoomChange(bool zoom_in) {
+  zoom::PageZoom::Zoom(
+      web_contents(), zoom_in ? content::PAGE_ZOOM_IN : content::PAGE_ZOOM_OUT);
+}
+
+void AlloyBrowserHostImpl::BeforeUnloadFired(content::WebContents* source,
+                                             bool proceed,
+                                             bool* proceed_to_fire_unload) {
+  if (destruction_state_ == DESTRUCTION_STATE_ACCEPTED || proceed) {
+    *proceed_to_fire_unload = true;
+  } else if (!proceed) {
+    *proceed_to_fire_unload = false;
+    destruction_state_ = DESTRUCTION_STATE_NONE;
+  }
+}
+
+bool AlloyBrowserHostImpl::TakeFocus(content::WebContents* source,
+                                     bool reverse) {
+  if (client_.get()) {
+    CefRefPtr<CefFocusHandler> handler = client_->GetFocusHandler();
+    if (handler.get()) {
+      handler->OnTakeFocus(this, !reverse);
+    }
+  }
+
+  return false;
+}
+
+void AlloyBrowserHostImpl::CanDownload(
+    const GURL& url,
+    const std::string& request_method,
+    base::OnceCallback<void(bool)> callback) {
+  contents_delegate_->CanDownload(url, request_method, std::move(callback));
+}
+
+KeyboardEventProcessingResult AlloyBrowserHostImpl::PreHandleKeyboardEvent(
+    content::WebContents* source,
+    const content::NativeWebKeyboardEvent& event) {
+  return contents_delegate_->PreHandleKeyboardEvent(source, event);
+}
+
+bool AlloyBrowserHostImpl::HandleKeyboardEvent(
+    content::WebContents* source,
+    const content::NativeWebKeyboardEvent& event) {
+  // Check to see if event should be ignored.
+  if (event.skip_if_unhandled) {
+    return false;
+  }
+
+  if (contents_delegate_->HandleKeyboardEvent(source, event)) {
+    return true;
+  }
+
+  if (platform_delegate_) {
+    return platform_delegate_->HandleKeyboardEvent(event);
+  }
+  return false;
+}
+
+bool AlloyBrowserHostImpl::PreHandleGestureEvent(
+    content::WebContents* source,
+    const blink::WebGestureEvent& event) {
+  return platform_delegate_->PreHandleGestureEvent(source, event);
+}
+
+bool AlloyBrowserHostImpl::CanDragEnter(content::WebContents* source,
+                                        const content::DropData& data,
+                                        blink::DragOperationsMask mask) {
+  CefRefPtr<CefDragHandler> handler;
+  if (client_) {
+    handler = client_->GetDragHandler();
+  }
+  if (handler) {
+    CefRefPtr<CefDragDataImpl> drag_data(new CefDragDataImpl(data));
+    drag_data->SetReadOnly(true);
+    if (handler->OnDragEnter(
+            this, drag_data.get(),
+            static_cast<CefDragHandler::DragOperationsMask>(mask))) {
+      return false;
+    }
+  }
+  return true;
+}
+
+void AlloyBrowserHostImpl::GetCustomWebContentsView(
+    content::WebContents* web_contents,
+    const GURL& target_url,
+    int opener_render_process_id,
+    int opener_render_frame_id,
+    content::WebContentsView** view,
+    content::RenderViewHostDelegateView** delegate_view) {
+  CefBrowserInfoManager::GetInstance()->GetCustomWebContentsView(
+      target_url,
+      frame_util::MakeGlobalId(opener_render_process_id,
+                               opener_render_frame_id),
+      view, delegate_view);
+}
+
+void AlloyBrowserHostImpl::WebContentsCreated(
+    content::WebContents* source_contents,
+    int opener_render_process_id,
+    int opener_render_frame_id,
+    const std::string& frame_name,
+    const GURL& target_url,
+    content::WebContents* new_contents) {
+  CefBrowserSettings settings;
+  CefRefPtr<CefClient> client;
+  std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate;
+  CefRefPtr<CefDictionaryValue> extra_info;
+
+  CefBrowserInfoManager::GetInstance()->WebContentsCreated(
+      target_url,
+      frame_util::MakeGlobalId(opener_render_process_id,
+                               opener_render_frame_id),
+      settings, client, platform_delegate, extra_info, new_contents);
+
+  scoped_refptr<CefBrowserInfo> info =
+      CefBrowserInfoManager::GetInstance()->CreatePopupBrowserInfo(
+          new_contents, platform_delegate->IsWindowless(), extra_info);
+  CHECK(info.get());
+  CHECK(info->is_popup());
+
+  CefRefPtr<AlloyBrowserHostImpl> opener =
+      GetBrowserForContents(source_contents);
+  if (!opener) {
+    return;
+  }
+
+  // Popups must share the same RequestContext as the parent.
+  CefRefPtr<CefRequestContextImpl> request_context = opener->request_context();
+  CHECK(request_context);
+
+  // We don't officially own |new_contents| until AddNewContents() is called.
+  // However, we need to install observers/delegates here.
+  CefRefPtr<AlloyBrowserHostImpl> browser =
+      CreateInternal(settings, client, new_contents, /*own_web_contents=*/false,
+                     info, opener, /*is_devtools_popup=*/false, request_context,
+                     std::move(platform_delegate), /*cef_extension=*/nullptr);
+}
+
+content::JavaScriptDialogManager*
+AlloyBrowserHostImpl::GetJavaScriptDialogManager(content::WebContents* source) {
+  if (!javascript_dialog_manager_) {
+    javascript_dialog_manager_.reset(new CefJavaScriptDialogManager(this));
+  }
+  return javascript_dialog_manager_.get();
+}
+
+void AlloyBrowserHostImpl::RunFileChooser(
+    content::RenderFrameHost* render_frame_host,
+    scoped_refptr<content::FileSelectListener> listener,
+    const blink::mojom::FileChooserParams& params) {
+  // This will eventually call into CefFileDialogManager.
+  FileSelectHelper::RunFileChooser(render_frame_host, std::move(listener),
+                                   params);
+}
+
+bool AlloyBrowserHostImpl::ShowContextMenu(
+    const content::ContextMenuParams& params) {
+  CEF_REQUIRE_UIT();
+  if (!menu_manager_.get() && platform_delegate_) {
+    menu_manager_.reset(
+        new CefMenuManager(this, platform_delegate_->CreateMenuRunner()));
+  }
+  return menu_manager_->CreateContextMenu(params);
+}
+
+void AlloyBrowserHostImpl::UpdatePreferredSize(content::WebContents* source,
+                                               const gfx::Size& pref_size) {
+#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC))
+  CEF_REQUIRE_UIT();
+  if (platform_delegate_) {
+    platform_delegate_->SizeTo(pref_size.width(), pref_size.height());
+  }
+#endif
+}
+
+void AlloyBrowserHostImpl::ResizeDueToAutoResize(content::WebContents* source,
+                                                 const gfx::Size& new_size) {
+  CEF_REQUIRE_UIT();
+
+  if (client_) {
+    CefRefPtr<CefDisplayHandler> handler = client_->GetDisplayHandler();
+    if (handler && handler->OnAutoResize(
+                       this, CefSize(new_size.width(), new_size.height()))) {
+      return;
+    }
+  }
+
+  UpdatePreferredSize(source, new_size);
+}
+
+void AlloyBrowserHostImpl::RequestMediaAccessPermission(
+    content::WebContents* web_contents,
+    const content::MediaStreamRequest& request,
+    content::MediaResponseCallback callback) {
+  auto returned_callback = media_access_query::RequestMediaAccessPermission(
+      this, request, std::move(callback), /*default_disallow=*/true);
+  // Callback should not be returned.
+  DCHECK(returned_callback.is_null());
+}
+
+bool AlloyBrowserHostImpl::CheckMediaAccessPermission(
+    content::RenderFrameHost* render_frame_host,
+    const GURL& security_origin,
+    blink::mojom::MediaStreamType type) {
+  return media_access_query::CheckMediaAccessPermission(this, render_frame_host,
+                                                        security_origin, type);
+}
+
+bool AlloyBrowserHostImpl::IsNeverComposited(
+    content::WebContents* web_contents) {
+  return platform_delegate_->IsNeverComposited(web_contents);
+}
+
+content::PictureInPictureResult AlloyBrowserHostImpl::EnterPictureInPicture(
+    content::WebContents* web_contents) {
+  if (!IsPictureInPictureSupported()) {
+    return content::PictureInPictureResult::kNotSupported;
+  }
+
+  return PictureInPictureWindowManager::GetInstance()
+      ->EnterVideoPictureInPicture(web_contents);
+}
+
+void AlloyBrowserHostImpl::ExitPictureInPicture() {
+  DCHECK(IsPictureInPictureSupported());
+  PictureInPictureWindowManager::GetInstance()->ExitPictureInPicture();
+}
+
+bool AlloyBrowserHostImpl::IsBackForwardCacheSupported() {
+  // Disabled due to issue #3237.
+  return false;
+}
+
+content::PreloadingEligibility AlloyBrowserHostImpl::IsPrerender2Supported(
+    content::WebContents& web_contents) {
+  return content::PreloadingEligibility::kEligible;
+}
+
+// content::WebContentsObserver methods.
+// -----------------------------------------------------------------------------
+
+void AlloyBrowserHostImpl::DidFinishNavigation(
+    content::NavigationHandle* navigation_handle) {
+  if (web_contents()) {
+    auto cef_browser_context =
+        static_cast<AlloyBrowserContext*>(web_contents()->GetBrowserContext());
+    if (cef_browser_context) {
+      cef_browser_context->AddVisitedURLs(
+          navigation_handle->GetRedirectChain());
+    }
+  }
+}
+
+void AlloyBrowserHostImpl::OnAudioStateChanged(bool audible) {
+  if (audible) {
+    if (recently_audible_timer_) {
+      recently_audible_timer_->Stop();
+    }
+
+    StartAudioCapturer();
+  } else if (audio_capturer_) {
+    if (!recently_audible_timer_) {
+      recently_audible_timer_ = std::make_unique<base::OneShotTimer>();
+    }
+
+    // If you have a media playing that has a short quiet moment, web_contents
+    // will immediately switch to non-audible state. We don't want to stop
+    // audio stream so quickly, let's give the stream some time to resume
+    // playing.
+    recently_audible_timer_->Start(
+        FROM_HERE, kRecentlyAudibleTimeout,
+        base::BindOnce(&AlloyBrowserHostImpl::OnRecentlyAudibleTimerFired,
+                       this));
+  }
+}
+
+void AlloyBrowserHostImpl::OnRecentlyAudibleTimerFired() {
+  audio_capturer_.reset();
+}
+
+void AlloyBrowserHostImpl::AccessibilityEventReceived(
+    const content::AXEventNotificationDetails& content_event_bundle) {
+  // Only needed in windowless mode.
+  if (IsWindowless()) {
+    if (!web_contents() || !platform_delegate_) {
+      return;
+    }
+
+    platform_delegate_->AccessibilityEventReceived(content_event_bundle);
+  }
+}
+
+void AlloyBrowserHostImpl::AccessibilityLocationChangesReceived(
+    const std::vector<content::AXLocationChangeNotificationDetails>& locData) {
+  // Only needed in windowless mode.
+  if (IsWindowless()) {
+    if (!web_contents() || !platform_delegate_) {
+      return;
+    }
+
+    platform_delegate_->AccessibilityLocationChangesReceived(locData);
+  }
+}
+
+void AlloyBrowserHostImpl::WebContentsDestroyed() {
+  auto wc = web_contents();
+  content::WebContentsObserver::Observe(nullptr);
+  if (platform_delegate_) {
+    platform_delegate_->WebContentsDestroyed(wc);
+  }
+}
+
+void AlloyBrowserHostImpl::StartAudioCapturer() {
+  if (!client_.get() || audio_capturer_) {
+    return;
+  }
+
+  CefRefPtr<CefAudioHandler> audio_handler = client_->GetAudioHandler();
+  if (!audio_handler.get()) {
+    return;
+  }
+
+  CefAudioParameters params;
+  params.channel_layout = CEF_CHANNEL_LAYOUT_STEREO;
+  params.sample_rate = media::AudioParameters::kAudioCDSampleRate;
+  params.frames_per_buffer = 1024;
+
+  if (!audio_handler->GetAudioParameters(this, params)) {
+    return;
+  }
+
+  audio_capturer_.reset(new CefAudioCapturer(params, this, audio_handler));
+}
+
+// AlloyBrowserHostImpl private methods.
+// -----------------------------------------------------------------------------
+
+AlloyBrowserHostImpl::AlloyBrowserHostImpl(
+    const CefBrowserSettings& settings,
+    CefRefPtr<CefClient> client,
+    content::WebContents* web_contents,
+    scoped_refptr<CefBrowserInfo> browser_info,
+    CefRefPtr<AlloyBrowserHostImpl> opener,
+    CefRefPtr<CefRequestContextImpl> request_context,
+    std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
+    CefRefPtr<CefExtension> extension)
+    : CefBrowserHostBase(settings,
+                         client,
+                         std::move(platform_delegate),
+                         browser_info,
+                         request_context),
+      content::WebContentsObserver(web_contents),
+      opener_(kNullWindowHandle),
+      is_windowless_(platform_delegate_->IsWindowless()),
+      extension_(extension) {
+  contents_delegate_->ObserveWebContents(web_contents);
+
+  if (opener.get() && !is_views_hosted_) {
+    // GetOpenerWindowHandle() only returns a value for non-views-hosted
+    // popup browsers.
+    opener_ = opener->GetWindowHandle();
+  }
+
+  // Associate the platform delegate with this browser.
+  platform_delegate_->BrowserCreated(this);
+
+  // Make sure RenderFrameCreated is called at least one time.
+  RenderFrameCreated(web_contents->GetPrimaryMainFrame());
+}
+
+bool AlloyBrowserHostImpl::CreateHostWindow() {
+  // |host_window_handle_| will not change after initial host creation for
+  // non-views-hosted browsers.
+  bool success = true;
+  if (!IsWindowless()) {
+    success = platform_delegate_->CreateHostWindow();
+  }
+  if (success && !is_views_hosted_) {
+    host_window_handle_ = platform_delegate_->GetHostWindowHandle();
+  }
+  return success;
+}
+
+gfx::Point AlloyBrowserHostImpl::GetScreenPoint(const gfx::Point& view,
+                                                bool want_dip_coords) const {
+  CEF_REQUIRE_UIT();
+  if (platform_delegate_) {
+    return platform_delegate_->GetScreenPoint(view, want_dip_coords);
+  }
+  return gfx::Point();
+}
+
+void AlloyBrowserHostImpl::StartDragging(
+    const content::DropData& drop_data,
+    blink::DragOperationsMask allowed_ops,
+    const gfx::ImageSkia& image,
+    const gfx::Vector2d& image_offset,
+    const blink::mojom::DragEventSourceInfo& event_info,
+    content::RenderWidgetHostImpl* source_rwh) {
+  if (platform_delegate_) {
+    platform_delegate_->StartDragging(drop_data, allowed_ops, image,
+                                      image_offset, event_info, source_rwh);
+  }
+}
+
+void AlloyBrowserHostImpl::UpdateDragOperation(
+    ui::mojom::DragOperation operation,
+    bool document_is_handling_drag) {
+  if (platform_delegate_) {
+    platform_delegate_->UpdateDragOperation(operation,
+                                            document_is_handling_drag);
+  }
+}
diff --git a/src/libcef/browser/alloy/alloy_browser_host_impl.h b/src/libcef/browser/alloy/alloy_browser_host_impl.h
new file mode 100644
index 0000000..e2298ba
--- /dev/null
+++ b/src/libcef/browser/alloy/alloy_browser_host_impl.h
@@ -0,0 +1,351 @@
+// Copyright (c) 2012 The Chromium Embedded Framework Authors.
+// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_BROWSER_ALLOY_ALLOY_BROWSER_HOST_IMPL_H_
+#define CEF_LIBCEF_BROWSER_ALLOY_ALLOY_BROWSER_HOST_IMPL_H_
+#pragma once
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "include/cef_browser.h"
+#include "include/cef_client.h"
+#include "include/cef_frame.h"
+#include "libcef/browser/browser_host_base.h"
+#include "libcef/browser/browser_info.h"
+#include "libcef/browser/frame_host_impl.h"
+#include "libcef/browser/javascript_dialog_manager.h"
+#include "libcef/browser/menu_manager.h"
+#include "libcef/browser/request_context_impl.h"
+
+#include "base/synchronization/lock.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "extensions/common/mojom/view_type.mojom-forward.h"
+
+class CefAudioCapturer;
+class CefBrowserInfo;
+class SiteInstance;
+
+// CefBrowser implementation for the alloy runtime. Method calls are delegated
+// to the CefPlatformDelegate or the WebContents as appropriate. All methods are
+// thread-safe unless otherwise indicated.
+//
+// WebContentsDelegate: Interface for handling WebContents delegations. There is
+// a one-to-one relationship between AlloyBrowserHostImpl and WebContents
+// instances.
+//
+// WebContentsObserver: Interface for observing WebContents notifications and
+// IPC messages. There is a one-to-one relationship between WebContents and
+// RenderViewHost instances. IPC messages received by the RenderViewHost will be
+// forwarded to this WebContentsObserver implementation via WebContents. IPC
+// messages sent using AlloyBrowserHostImpl::Send() will be forwarded to the
+// RenderViewHost (after posting to the UI thread if necessary). Use
+// WebContentsObserver::routing_id() when sending IPC messages.
+class AlloyBrowserHostImpl : public CefBrowserHostBase,
+                             public content::WebContentsDelegate,
+                             public content::WebContentsObserver {
+ public:
+  // Used for handling the response to command messages.
+  class CommandResponseHandler : public virtual CefBaseRefCounted {
+   public:
+    virtual void OnResponse(const std::string& response) = 0;
+  };
+
+  ~AlloyBrowserHostImpl() override;
+
+  // Create a new AlloyBrowserHostImpl instance with owned WebContents.
+  static CefRefPtr<AlloyBrowserHostImpl> Create(
+      CefBrowserCreateParams& create_params);
+
+  // Returns the browser associated with the specified RenderViewHost.
+  static CefRefPtr<AlloyBrowserHostImpl> GetBrowserForHost(
+      const content::RenderViewHost* host);
+  // Returns the browser associated with the specified RenderFrameHost.
+  static CefRefPtr<AlloyBrowserHostImpl> GetBrowserForHost(
+      const content::RenderFrameHost* host);
+  // Returns the browser associated with the specified WebContents.
+  static CefRefPtr<AlloyBrowserHostImpl> GetBrowserForContents(
+      const content::WebContents* contents);
+  // Returns the browser associated with the specified global ID.
+  static CefRefPtr<AlloyBrowserHostImpl> GetBrowserForGlobalId(
+      const content::GlobalRenderFrameHostId& global_id);
+
+  // CefBrowserHost methods.
+  void CloseBrowser(bool force_close) override;
+  bool TryCloseBrowser() override;
+  CefWindowHandle GetWindowHandle() override;
+  CefWindowHandle GetOpenerWindowHandle() override;
+  void Find(const CefString& searchText,
+            bool forward,
+            bool matchCase,
+            bool findNext) override;
+  void StopFinding(bool clearSelection) override;
+  void CloseDevTools() override;
+  bool HasDevTools() override;
+  bool IsWindowRenderingDisabled() override;
+  void WasResized() override;
+  void WasHidden(bool hidden) override;
+  void NotifyScreenInfoChanged() override;
+  void Invalidate(PaintElementType type) override;
+  void SendExternalBeginFrame() override;
+  void SendTouchEvent(const CefTouchEvent& event) override;
+  void SendCaptureLostEvent() override;
+  int GetWindowlessFrameRate() override;
+  void SetWindowlessFrameRate(int frame_rate) override;
+  void ImeSetComposition(const CefString& text,
+                         const std::vector<CefCompositionUnderline>& underlines,
+                         const CefRange& replacement_range,
+                         const CefRange& selection_range) override;
+  void ImeCommitText(const CefString& text,
+                     const CefRange& replacement_range,
+                     int relative_cursor_pos) override;
+  void ImeFinishComposingText(bool keep_selection) override;
+  void ImeCancelComposition() override;
+  void DragTargetDragEnter(CefRefPtr<CefDragData> drag_data,
+                           const CefMouseEvent& event,
+                           DragOperationsMask allowed_ops) override;
+  void DragTargetDragOver(const CefMouseEvent& event,
+                          DragOperationsMask allowed_ops) override;
+  void DragTargetDragLeave() override;
+  void DragTargetDrop(const CefMouseEvent& event) override;
+  void DragSourceSystemDragEnded() override;
+  void DragSourceEndedAt(int x, int y, DragOperationsMask op) override;
+  void SetAudioMuted(bool mute) override;
+  bool IsAudioMuted() override;
+  void SetAccessibilityState(cef_state_t accessibility_state) override;
+  void SetAutoResizeEnabled(bool enabled,
+                            const CefSize& min_size,
+                            const CefSize& max_size) override;
+  CefRefPtr<CefExtension> GetExtension() override;
+  bool IsBackgroundHost() override;
+  bool CanExecuteChromeCommand(int command_id) override;
+  void ExecuteChromeCommand(int command_id,
+                            cef_window_open_disposition_t disposition) override;
+
+  // Returns true if windowless rendering is enabled.
+  bool IsWindowless() const override;
+
+  bool IsVisible() const override;
+
+  // Returns true if this browser supports picture-in-picture.
+  bool IsPictureInPictureSupported() const;
+
+  // Called when the OS window hosting the browser is destroyed.
+  void WindowDestroyed() override;
+
+  bool WillBeDestroyed() const override;
+
+  // Destroy the browser members. This method should only be called after the
+  // native browser window is not longer processing messages.
+  void DestroyBrowser() override;
+
+  // Cancel display of the context menu, if any.
+  void CancelContextMenu();
+
+  bool MaybeAllowNavigation(content::RenderFrameHost* opener,
+                            bool is_guest_view,
+                            const content::OpenURLParams& params) override;
+
+  // Convert from view DIP coordinates to screen coordinates. If
+  // |want_dip_coords| is true return DIP instead of device (pixel) coordinates
+  // on Windows/Linux.
+  gfx::Point GetScreenPoint(const gfx::Point& view, bool want_dip_coords) const;
+
+  void StartDragging(const content::DropData& drop_data,
+                     blink::DragOperationsMask allowed_ops,
+                     const gfx::ImageSkia& image,
+                     const gfx::Vector2d& image_offset,
+                     const blink::mojom::DragEventSourceInfo& event_info,
+                     content::RenderWidgetHostImpl* source_rwh);
+  void UpdateDragOperation(ui::mojom::DragOperation operation,
+                           bool document_is_handling_drag);
+
+  // Accessors that must be called on the UI thread.
+  extensions::ExtensionHost* GetExtensionHost() const;
+
+  void OnSetFocus(cef_focus_source_t source) override;
+
+  bool ShowContextMenu(const content::ContextMenuParams& params);
+
+  enum DestructionState {
+    DESTRUCTION_STATE_NONE = 0,
+    DESTRUCTION_STATE_PENDING,
+    DESTRUCTION_STATE_ACCEPTED,
+    DESTRUCTION_STATE_COMPLETED
+  };
+  DestructionState destruction_state() const { return destruction_state_; }
+
+  // content::WebContentsDelegate methods.
+  content::WebContents* OpenURLFromTab(
+      content::WebContents* source,
+      const content::OpenURLParams& params) override;
+  bool ShouldAllowRendererInitiatedCrossProcessNavigation(
+      bool is_main_frame_navigation) override;
+  void AddNewContents(content::WebContents* source,
+                      std::unique_ptr<content::WebContents> new_contents,
+                      const GURL& target_url,
+                      WindowOpenDisposition disposition,
+                      const blink::mojom::WindowFeatures& window_features,
+                      bool user_gesture,
+                      bool* was_blocked) override;
+  void LoadingStateChanged(content::WebContents* source,
+                           bool should_show_loading_ui) override;
+  void CloseContents(content::WebContents* source) override;
+  void UpdateTargetURL(content::WebContents* source, const GURL& url) override;
+  bool DidAddMessageToConsole(content::WebContents* source,
+                              blink::mojom::ConsoleMessageLevel log_level,
+                              const std::u16string& message,
+                              int32_t line_no,
+                              const std::u16string& source_id) override;
+  void ContentsZoomChange(bool zoom_in) override;
+  void BeforeUnloadFired(content::WebContents* source,
+                         bool proceed,
+                         bool* proceed_to_fire_unload) override;
+  bool TakeFocus(content::WebContents* source, bool reverse) override;
+  void CanDownload(const GURL& url,
+                   const std::string& request_method,
+                   base::OnceCallback<void(bool)> callback) override;
+  content::KeyboardEventProcessingResult PreHandleKeyboardEvent(
+      content::WebContents* source,
+      const content::NativeWebKeyboardEvent& event) override;
+  bool HandleKeyboardEvent(
+      content::WebContents* source,
+      const content::NativeWebKeyboardEvent& event) override;
+  bool PreHandleGestureEvent(content::WebContents* source,
+                             const blink::WebGestureEvent& event) override;
+  bool CanDragEnter(content::WebContents* source,
+                    const content::DropData& data,
+                    blink::DragOperationsMask operations_allowed) override;
+  void GetCustomWebContentsView(
+      content::WebContents* web_contents,
+      const GURL& target_url,
+      int opener_render_process_id,
+      int opener_render_frame_id,
+      content::WebContentsView** view,
+      content::RenderViewHostDelegateView** delegate_view) override;
+  void WebContentsCreated(content::WebContents* source_contents,
+                          int opener_render_process_id,
+                          int opener_render_frame_id,
+                          const std::string& frame_name,
+                          const GURL& target_url,
+                          content::WebContents* new_contents) override;
+  content::JavaScriptDialogManager* GetJavaScriptDialogManager(
+      content::WebContents* source) override;
+  void RunFileChooser(content::RenderFrameHost* render_frame_host,
+                      scoped_refptr<content::FileSelectListener> listener,
+                      const blink::mojom::FileChooserParams& params) override;
+  void EnterFullscreenModeForTab(
+      content::RenderFrameHost* requesting_frame,
+      const blink::mojom::FullscreenOptions& options) override;
+  void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
+  bool IsFullscreenForTabOrPending(
+      const content::WebContents* web_contents) override;
+  blink::mojom::DisplayMode GetDisplayMode(
+      const content::WebContents* web_contents) override;
+  void FindReply(content::WebContents* web_contents,
+                 int request_id,
+                 int number_of_matches,
+                 const gfx::Rect& selection_rect,
+                 int active_match_ordinal,
+                 bool final_update) override;
+  void UpdatePreferredSize(content::WebContents* source,
+                           const gfx::Size& pref_size) override;
+  void ResizeDueToAutoResize(content::WebContents* source,
+                             const gfx::Size& new_size) override;
+  void RequestMediaAccessPermission(
+      content::WebContents* web_contents,
+      const content::MediaStreamRequest& request,
+      content::MediaResponseCallback callback) override;
+  bool CheckMediaAccessPermission(content::RenderFrameHost* render_frame_host,
+                                  const GURL& security_origin,
+                                  blink::mojom::MediaStreamType type) override;
+  bool IsNeverComposited(content::WebContents* web_contents) override;
+  content::PictureInPictureResult EnterPictureInPicture(
+      content::WebContents* web_contents) override;
+  void ExitPictureInPicture() override;
+  bool IsBackForwardCacheSupported() override;
+  content::PreloadingEligibility IsPrerender2Supported(
+      content::WebContents& web_contents) override;
+
+  // content::WebContentsObserver methods.
+  using content::WebContentsObserver::BeforeUnloadFired;
+  void DidFinishNavigation(
+      content::NavigationHandle* navigation_handle) override;
+  void OnAudioStateChanged(bool audible) override;
+  void AccessibilityEventReceived(
+      const content::AXEventNotificationDetails& content_event_bundle) override;
+  void AccessibilityLocationChangesReceived(
+      const std::vector<content::AXLocationChangeNotificationDetails>& locData)
+      override;
+  void WebContentsDestroyed() override;
+
+ protected:
+  void ShowDevToolsOnUIThread(
+      std::unique_ptr<CefShowDevToolsParams> params) override;
+
+ private:
+  friend class CefBrowserPlatformDelegateAlloy;
+
+  static CefRefPtr<AlloyBrowserHostImpl> CreateInternal(
+      const CefBrowserSettings& settings,
+      CefRefPtr<CefClient> client,
+      content::WebContents* web_contents,
+      bool own_web_contents,
+      scoped_refptr<CefBrowserInfo> browser_info,
+      CefRefPtr<AlloyBrowserHostImpl> opener,
+      bool is_devtools_popup,
+      CefRefPtr<CefRequestContextImpl> request_context,
+      std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
+      CefRefPtr<CefExtension> extension);
+
+  AlloyBrowserHostImpl(
+      const CefBrowserSettings& settings,
+      CefRefPtr<CefClient> client,
+      content::WebContents* web_contents,
+      scoped_refptr<CefBrowserInfo> browser_info,
+      CefRefPtr<AlloyBrowserHostImpl> opener,
+      CefRefPtr<CefRequestContextImpl> request_context,
+      std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
+      CefRefPtr<CefExtension> extension);
+
+  // Give the platform delegate an opportunity to create the host window.
+  bool CreateHostWindow();
+
+  void StartAudioCapturer();
+  void OnRecentlyAudibleTimerFired();
+
+  CefWindowHandle opener_;
+  const bool is_windowless_;
+  CefWindowHandle host_window_handle_ = kNullWindowHandle;
+  CefRefPtr<CefExtension> extension_;
+  bool is_background_host_ = false;
+
+  // Represents the current browser destruction state. Only accessed on the UI
+  // thread.
+  DestructionState destruction_state_ = DESTRUCTION_STATE_NONE;
+
+  // True if the OS window hosting the browser has been destroyed. Only accessed
+  // on the UI thread.
+  bool window_destroyed_ = false;
+
+  // Used for creating and managing JavaScript dialogs.
+  std::unique_ptr<CefJavaScriptDialogManager> javascript_dialog_manager_;
+
+  // Used for creating and managing context menus.
+  std::unique_ptr<CefMenuManager> menu_manager_;
+
+  // Used for capturing audio for CefAudioHandler.
+  std::unique_ptr<CefAudioCapturer> audio_capturer_;
+
+  // Timer for determining when "recently audible" transitions to false. This
+  // starts running when a tab stops being audible, and is canceled if it starts
+  // being audible again before it fires.
+  std::unique_ptr<base::OneShotTimer> recently_audible_timer_;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_ALLOY_ALLOY_BROWSER_HOST_IMPL_H_
diff --git a/src/libcef/browser/alloy/alloy_browser_main.cc b/src/libcef/browser/alloy/alloy_browser_main.cc
new file mode 100644
index 0000000..310b14a
--- /dev/null
+++ b/src/libcef/browser/alloy/alloy_browser_main.cc
@@ -0,0 +1,360 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/browser/alloy/alloy_browser_main.h"
+
+#include <stdint.h>
+
+#include <string>
+
+#include "libcef/browser/alloy/dialogs/alloy_constrained_window_views_client.h"
+#include "libcef/browser/browser_context.h"
+#include "libcef/browser/browser_context_keyed_service_factories.h"
+#include "libcef/browser/context.h"
+#include "libcef/browser/devtools/devtools_manager_delegate.h"
+#include "libcef/browser/extensions/extension_system_factory.h"
+#include "libcef/browser/file_dialog_runner.h"
+#include "libcef/browser/net/chrome_scheme_handler.h"
+#include "libcef/browser/permission_prompt.h"
+#include "libcef/browser/thread_util.h"
+#include "libcef/common/app_manager.h"
+#include "libcef/common/extensions/extensions_util.h"
+#include "libcef/common/net/net_resource_provider.h"
+
+#include "base/feature_list.h"
+#include "base/functional/bind.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/task/thread_pool.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/media/router/chrome_media_router_factory.h"
+#include "chrome/browser/net/system_network_context_manager.h"
+#include "chrome/browser/ui/color/chrome_color_mixers.h"
+#include "chrome/browser/ui/javascript_dialogs/chrome_javascript_app_modal_dialog_view_factory.h"
+#include "chrome/browser/ui/ui_features.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "components/constrained_window/constrained_window_views.h"
+#include "content/public/browser/gpu_data_manager.h"
+#include "content/public/browser/network_service_instance.h"
+#include "content/public/common/result_codes.h"
+#include "extensions/browser/extensions_browser_client.h"
+#include "extensions/common/constants.h"
+#include "net/base/net_module.h"
+#include "third_party/widevine/cdm/buildflags.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/color/color_provider_manager.h"
+#include "ui/native_theme/native_theme.h"
+
+#if BUILDFLAG(IS_LINUX)
+#include "ui/ozone/buildflags.h"
+#if defined(USE_AURA) && BUILDFLAG(OZONE_PLATFORM_X11)
+#include "ui/events/devices/x11/touch_factory_x11.h"
+#endif
+#endif
+
+#if defined(USE_AURA)
+#include "ui/aura/env.h"
+#include "ui/views/widget/desktop_aura/desktop_screen.h"
+#include "ui/wm/core/wm_state.h"
+
+#if BUILDFLAG(IS_WIN)
+#include "base/enterprise_util.h"
+#include "base/files/file_util.h"
+#include "chrome/browser/chrome_browser_main_win.h"
+#include "chrome/browser/win/parental_controls.h"
+#endif
+#endif  // defined(USE_AURA)
+
+#if BUILDFLAG(IS_MAC)
+#include "chrome/browser/ui/views/chrome_layout_provider.h"
+#include "chrome/browser/ui/views/chrome_views_delegate.h"
+#else
+#include "ui/views/test/desktop_test_views_delegate.h"
+#endif
+
+#if defined(USE_AURA) && BUILDFLAG(IS_LINUX)
+#include "ui/base/ime/init/input_method_initializer.h"
+#endif
+
+#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
+#include "components/os_crypt/sync/os_crypt.h"
+#endif
+
+#if BUILDFLAG(IS_LINUX)
+#include "base/path_service.h"
+#include "chrome/browser/themes/theme_service_aura_linux.h"
+#include "chrome/browser/ui/views/theme_profile_key.h"
+#include "chrome/grit/branded_strings.h"
+#include "components/os_crypt/sync/key_storage_config_linux.h"
+#include "libcef/browser/printing/print_dialog_linux.h"
+#include "ui/base/cursor/cursor_factory.h"
+#include "ui/base/ime/input_method.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/linux/linux_ui.h"
+#include "ui/linux/linux_ui_delegate.h"
+#include "ui/linux/linux_ui_factory.h"
+#include "ui/linux/linux_ui_getter.h"
+#include "ui/ozone/public/ozone_platform.h"
+#endif  // BUILDFLAG(IS_LINUX)
+
+#if BUILDFLAG(ENABLE_MEDIA_FOUNDATION_WIDEVINE_CDM)
+#include "chrome/browser/component_updater/media_foundation_widevine_cdm_component_installer.h"
+#endif
+
+#if BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT)
+#include "chrome/browser/component_updater/widevine_cdm_component_installer.h"
+#endif
+
+namespace {
+
+#if BUILDFLAG(IS_LINUX)
+
+class LinuxUiGetterImpl : public ui::LinuxUiGetter {
+ public:
+  LinuxUiGetterImpl() = default;
+  ~LinuxUiGetterImpl() override = default;
+  ui::LinuxUiTheme* GetForWindow(aura::Window* window) override {
+    return window ? GetForProfile(GetThemeProfileForWindow(window)) : nullptr;
+  }
+  ui::LinuxUiTheme* GetForProfile(Profile* profile) override {
+    return ui::GetLinuxUiTheme(
+        ThemeServiceAuraLinux::GetSystemThemeForProfile(profile));
+  }
+};
+
+ui::LinuxUi* GetLinuxUI() {
+  // We can't use GtkUi in combination with multi-threaded-message-loop because
+  // Chromium's GTK implementation doesn't use GDK threads.
+  if (!!CefContext::Get()->settings().multi_threaded_message_loop) {
+    return nullptr;
+  }
+
+  // If the ozone backend hasn't provided a LinuxUiDelegate, don't try to create
+  // a LinuxUi instance as this may result in a crash in toolkit initialization.
+  if (!ui::LinuxUiDelegate::GetInstance()) {
+    return nullptr;
+  }
+
+  return ui::GetDefaultLinuxUi();
+}
+
+#endif  // BUILDFLAG(IS_LINUX)
+
+}  // namespace
+
+AlloyBrowserMainParts::AlloyBrowserMainParts() = default;
+
+AlloyBrowserMainParts::~AlloyBrowserMainParts() {
+  constrained_window::SetConstrainedWindowViewsClient(nullptr);
+}
+
+void AlloyBrowserMainParts::ToolkitInitialized() {
+  SetConstrainedWindowViewsClient(CreateAlloyConstrainedWindowViewsClient());
+#if defined(USE_AURA)
+  CHECK(aura::Env::GetInstance());
+
+  wm_state_.reset(new wm::WMState);
+#endif  // defined(USE_AURA)
+
+#if BUILDFLAG(IS_MAC)
+  views_delegate_ = std::make_unique<ChromeViewsDelegate>();
+  layout_provider_ = ChromeLayoutProvider::CreateLayoutProvider();
+#else
+  views_delegate_ = std::make_unique<views::DesktopTestViewsDelegate>();
+#endif
+
+#if BUILDFLAG(IS_LINUX)
+  // Based on chrome_browser_main_extra_parts_views_linux.cc
+  if (auto linux_ui = GetLinuxUI()) {
+    linux_ui_getter_ = std::make_unique<LinuxUiGetterImpl>();
+    ui::LinuxUi::SetInstance(linux_ui);
+
+    // Cursor theme changes are tracked by LinuxUI (via a CursorThemeManager
+    // implementation). Start observing them once it's initialized.
+    ui::CursorFactory::GetInstance()->ObserveThemeChanges();
+  }
+
+  auto printing_delegate = new CefPrintingContextLinuxDelegate();
+  auto default_delegate =
+      ui::PrintingContextLinuxDelegate::SetInstance(printing_delegate);
+  printing_delegate->SetDefaultDelegate(default_delegate);
+#endif  // BUILDFLAG(IS_LINUX)
+
+#if BUILDFLAG(IS_MAC)
+  if (base::FeatureList::IsEnabled(features::kViewsJSAppModalDialog)) {
+    InstallChromeJavaScriptAppModalDialogViewFactory();
+  } else {
+    InstallChromeJavaScriptAppModalDialogViewCocoaFactory();
+  }
+#else
+  InstallChromeJavaScriptAppModalDialogViewFactory();
+#endif
+
+  // On GTK that builds the native theme that, in turn, adds the GTK core color
+  // mixer; core mixers should all be added before we add chrome mixers.
+  ui::ColorProviderManager::Get().AppendColorProviderInitializer(
+      base::BindRepeating(AddChromeColorMixers));
+}
+
+void AlloyBrowserMainParts::PreCreateMainMessageLoop() {
+#if BUILDFLAG(IS_LINUX)
+#if defined(USE_AURA) && BUILDFLAG(OZONE_PLATFORM_X11)
+  ui::TouchFactory::SetTouchDeviceListFromCommandLine();
+#endif
+#endif
+
+#if BUILDFLAG(IS_WIN)
+  // Initialize the OSCrypt.
+  PrefService* local_state = g_browser_process->local_state();
+  DCHECK(local_state);
+  bool os_crypt_init = OSCrypt::Init(local_state);
+  DCHECK(os_crypt_init);
+
+  // installer_util references strings that are normally compiled into
+  // setup.exe.  In Chrome, these strings are in the locale files.
+  ChromeBrowserMainPartsWin::SetupInstallerUtilStrings();
+#endif  // BUILDFLAG(IS_WIN)
+
+  media_router::ChromeMediaRouterFactory::DoPlatformInit();
+}
+
+void AlloyBrowserMainParts::PostCreateMainMessageLoop() {
+#if BUILDFLAG(IS_LINUX)
+  const base::CommandLine* command_line =
+      base::CommandLine::ForCurrentProcess();
+
+  // Set up crypt config. This needs to be done before anything starts the
+  // network service, as the raw encryption key needs to be shared with the
+  // network service for encrypted cookie storage.
+  // Based on ChromeBrowserMainPartsLinux::PostCreateMainMessageLoop.
+  std::unique_ptr<os_crypt::Config> config =
+      std::make_unique<os_crypt::Config>();
+  // Forward to os_crypt the flag to use a specific password store.
+  config->store = command_line->GetSwitchValueASCII(switches::kPasswordStore);
+  // Forward the product name (defaults to "Chromium").
+  config->product_name = l10n_util::GetStringUTF8(IDS_PRODUCT_NAME);
+  // OSCrypt can be disabled in a special settings file.
+  config->should_use_preference =
+      command_line->HasSwitch(switches::kEnableEncryptionSelection);
+  base::PathService::Get(chrome::DIR_USER_DATA, &config->user_data_path);
+  DCHECK(!config->user_data_path.empty());
+  OSCrypt::SetConfig(std::move(config));
+#endif  // BUILDFLAG(IS_LINUX)
+
+#if BUILDFLAG(IS_WIN)
+  base::SetExtraNoExecuteAllowedPath(chrome::DIR_USER_DATA);
+#endif
+}
+
+int AlloyBrowserMainParts::PreCreateThreads() {
+#if BUILDFLAG(IS_WIN)
+  PlatformInitialize();
+#endif
+
+  net::NetModule::SetResourceProvider(&NetResourceProvider);
+
+  // Initialize these objects before IO access restrictions are applied and
+  // before the IO thread is started.
+  content::GpuDataManager::GetInstance();
+  SystemNetworkContextManager::CreateInstance(g_browser_process->local_state());
+
+  return 0;
+}
+
+int AlloyBrowserMainParts::PreMainMessageLoopRun() {
+#if defined(USE_AURA)
+  screen_ = views::CreateDesktopScreen();
+#endif
+#if BUILDFLAG(IS_MAC)
+  screen_ = std::make_unique<display::ScopedNativeScreen>();
+#endif
+
+  if (extensions::ExtensionsEnabled()) {
+    // This should be set in ChromeBrowserProcessAlloy::Initialize.
+    DCHECK(extensions::ExtensionsBrowserClient::Get());
+    // Initialize extension global objects before creating the global
+    // BrowserContext.
+    extensions::CefExtensionSystemFactory::GetInstance();
+  }
+
+  // Register additional KeyedService factories here. See
+  // ChromeBrowserMainExtraPartsProfiles for details.
+  cef::EnsureBrowserContextKeyedServiceFactoriesBuilt();
+
+  background_task_runner_ = base::ThreadPool::CreateSingleThreadTaskRunner(
+      {base::TaskPriority::BEST_EFFORT,
+       base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()});
+  user_visible_task_runner_ = base::ThreadPool::CreateSingleThreadTaskRunner(
+      {base::TaskPriority::USER_VISIBLE,
+       base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()});
+  user_blocking_task_runner_ = base::ThreadPool::CreateSingleThreadTaskRunner(
+      {base::TaskPriority::USER_BLOCKING,
+       base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()});
+
+  CefRequestContextSettings settings;
+  CefContext::Get()->PopulateGlobalRequestContextSettings(&settings);
+
+  // Create the global RequestContext.
+  global_request_context_ =
+      CefRequestContextImpl::CreateGlobalRequestContext(settings);
+  auto browser_context =
+      global_request_context_->GetBrowserContext()->AsBrowserContext();
+
+  CefDevToolsManagerDelegate::StartHttpHandler(browser_context);
+
+#if BUILDFLAG(IS_WIN)
+  // Windows parental controls calls can be slow, so we do an early init here
+  // that calculates this value off of the UI thread.
+  InitializeWinParentalControls();
+
+  // These methods may call LoadLibrary and could trigger
+  // AssertBlockingAllowed() failures if executed at a later time on the UI
+  // thread.
+  base::IsManagedDevice();
+  base::IsEnterpriseDevice();
+#endif  // BUILDFLAG(IS_WIN)
+
+  scheme::RegisterWebUIControllerFactory();
+  file_dialog_runner::RegisterFactory();
+  permission_prompt::RegisterCreateCallback();
+
+  // Initialize theme configuration (high contrast, dark mode, etc).
+  ui::NativeTheme::GetInstanceForNativeUi();
+
+#if BUILDFLAG(ENABLE_MEDIA_FOUNDATION_WIDEVINE_CDM) || \
+    BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT)
+  const base::CommandLine* command_line =
+      base::CommandLine::ForCurrentProcess();
+  if (!command_line->HasSwitch(switches::kDisableComponentUpdate)) {
+    auto* const cus = g_browser_process->component_updater();
+
+#if BUILDFLAG(ENABLE_MEDIA_FOUNDATION_WIDEVINE_CDM)
+    RegisterMediaFoundationWidevineCdmComponent(cus);
+#endif
+
+#if BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT)
+    RegisterWidevineCdmComponent(cus);
+#endif
+  }
+#endif
+
+  return content::RESULT_CODE_NORMAL_EXIT;
+}
+
+void AlloyBrowserMainParts::PostMainMessageLoopRun() {
+  // NOTE: Destroy objects in reverse order of creation.
+  CefDevToolsManagerDelegate::StopHttpHandler();
+
+  // There should be no additional references to the global CefRequestContext
+  // during shutdown. Did you forget to release a CefBrowser reference?
+  DCHECK(global_request_context_->HasOneRef());
+  global_request_context_ = nullptr;
+}
+
+void AlloyBrowserMainParts::PostDestroyThreads() {
+  views_delegate_.reset();
+#if BUILDFLAG(IS_MAC)
+  layout_provider_.reset();
+#endif
+}
diff --git a/src/libcef/browser/browser_main.h b/src/libcef/browser/alloy/alloy_browser_main.h
similarity index 64%
rename from src/libcef/browser/browser_main.h
rename to src/libcef/browser/alloy/alloy_browser_main.h
index 5827697..856d19f 100644
--- a/src/libcef/browser/browser_main.h
+++ b/src/libcef/browser/alloy/alloy_browser_main.h
@@ -2,26 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CEF_LIBCEF_BROWSER_BROWSER_MAIN_H_
-#define CEF_LIBCEF_BROWSER_BROWSER_MAIN_H_
+#ifndef CEF_LIBCEF_BROWSER_ALLOY_ALLOY_BROWSER_MAIN_H_
+#define CEF_LIBCEF_BROWSER_ALLOY_ALLOY_BROWSER_MAIN_H_
 #pragma once
 
 #include "libcef/browser/request_context_impl.h"
 
-#include "base/macros.h"
+#include "base/command_line.h"
 #include "base/strings/string_piece.h"
 #include "build/build_config.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_main_parts.h"
-
-namespace content {
-struct MainFunctionParams;
-}
-
-namespace extensions {
-class ExtensionsBrowserClient;
-class ExtensionsClient;
-}  // namespace extensions
+#include "ui/display/screen.h"
 
 #if defined(USE_AURA)
 namespace wm {
@@ -29,28 +21,35 @@
 }
 #endif
 
-#if defined(TOOLKIT_VIEWS)
 namespace views {
 class ViewsDelegate;
-#if defined(OS_MACOSX)
+#if BUILDFLAG(IS_MAC)
 class LayoutProvider;
 #endif
+}  // namespace views
+
+#if BUILDFLAG(IS_LINUX)
+namespace ui {
+class LinuxUiGetter;
 }
-#endif  // defined(TOOLKIT_VIEWS)
+#endif
 
 class CefDevToolsDelegate;
 
-class CefBrowserMainParts : public content::BrowserMainParts {
+class AlloyBrowserMainParts : public content::BrowserMainParts {
  public:
-  explicit CefBrowserMainParts(const content::MainFunctionParams& parameters);
-  ~CefBrowserMainParts() override;
+  AlloyBrowserMainParts();
 
-  int PreEarlyInitialization() override;
+  AlloyBrowserMainParts(const AlloyBrowserMainParts&) = delete;
+  AlloyBrowserMainParts& operator=(const AlloyBrowserMainParts&) = delete;
+
+  ~AlloyBrowserMainParts() override;
+
   void ToolkitInitialized() override;
-  void PreMainMessageLoopStart() override;
-  void PostMainMessageLoopStart() override;
+  void PreCreateMainMessageLoop() override;
+  void PostCreateMainMessageLoop() override;
   int PreCreateThreads() override;
-  void PreMainMessageLoopRun() override;
+  int PreMainMessageLoopRun() override;
   void PostMainMessageLoopRun() override;
   void PostDestroyThreads() override;
 
@@ -71,16 +70,12 @@
   }
 
  private:
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   void PlatformInitialize();
-#endif  // defined(OS_WIN)
+#endif  // BUILDFLAG(IS_WIN)
 
   CefRefPtr<CefRequestContextImpl> global_request_context_;
-  CefDevToolsDelegate* devtools_delegate_;  // Deletes itself.
-
-  std::unique_ptr<extensions::ExtensionsClient> extensions_client_;
-  std::unique_ptr<extensions::ExtensionsBrowserClient>
-      extensions_browser_client_;
+  CefDevToolsDelegate* devtools_delegate_ = nullptr;  // Deletes itself.
 
   // Blocking task runners exposed via CefTaskRunner. For consistency with
   // previous named thread behavior always execute all pending tasks before
@@ -91,17 +86,19 @@
   scoped_refptr<base::SingleThreadTaskRunner> user_blocking_task_runner_;
 
 #if defined(USE_AURA)
+  std::unique_ptr<display::Screen> screen_;
   std::unique_ptr<wm::WMState> wm_state_;
 #endif
 
-#if defined(TOOLKIT_VIEWS)
   std::unique_ptr<views::ViewsDelegate> views_delegate_;
-#if defined(OS_MACOSX)
+#if BUILDFLAG(IS_MAC)
+  std::unique_ptr<display::ScopedNativeScreen> screen_;
   std::unique_ptr<views::LayoutProvider> layout_provider_;
 #endif
-#endif  // defined(TOOLKIT_VIEWS)
 
-  DISALLOW_COPY_AND_ASSIGN(CefBrowserMainParts);
+#if BUILDFLAG(IS_LINUX)
+  std::unique_ptr<ui::LinuxUiGetter> linux_ui_getter_;
+#endif
 };
 
-#endif  // CEF_LIBCEF_BROWSER_BROWSER_MAIN_H_
+#endif  // CEF_LIBCEF_BROWSER_ALLOY_ALLOY_BROWSER_MAIN_H_
diff --git a/src/libcef/browser/browser_main_win.cc b/src/libcef/browser/alloy/alloy_browser_main_win.cc
similarity index 85%
rename from src/libcef/browser/browser_main_win.cc
rename to src/libcef/browser/alloy/alloy_browser_main_win.cc
index 272fcbd..ac3cbc1 100644
--- a/src/libcef/browser/browser_main_win.cc
+++ b/src/libcef/browser/alloy/alloy_browser_main_win.cc
@@ -6,11 +6,11 @@
 #include <commctrl.h>
 #include <windows.h>
 
-#include "libcef/browser/browser_main.h"
+#include "libcef/browser/alloy/alloy_browser_main.h"
 
 #include "base/logging.h"
 
-void CefBrowserMainParts::PlatformInitialize() {
+void AlloyBrowserMainParts::PlatformInitialize() {
   HRESULT res;
 
   // Initialize common controls.
diff --git a/src/libcef/browser/alloy/alloy_content_browser_client.cc b/src/libcef/browser/alloy/alloy_content_browser_client.cc
new file mode 100644
index 0000000..1fab90b
--- /dev/null
+++ b/src/libcef/browser/alloy/alloy_content_browser_client.cc
@@ -0,0 +1,1447 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/browser/alloy/alloy_content_browser_client.h"
+
+#include <algorithm>
+#include <tuple>
+#include <utility>
+
+#include "include/cef_version.h"
+#include "libcef/browser/alloy/alloy_browser_context.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_browser_main.h"
+#include "libcef/browser/alloy/alloy_web_contents_view_delegate.h"
+#include "libcef/browser/browser_context.h"
+#include "libcef/browser/browser_frame.h"
+#include "libcef/browser/browser_info.h"
+#include "libcef/browser/browser_info_manager.h"
+#include "libcef/browser/browser_manager.h"
+#include "libcef/browser/browser_platform_delegate.h"
+#include "libcef/browser/certificate_query.h"
+#include "libcef/browser/context.h"
+#include "libcef/browser/devtools/devtools_manager_delegate.h"
+#include "libcef/browser/extensions/extension_system.h"
+#include "libcef/browser/extensions/extension_web_contents_observer.h"
+#include "libcef/browser/media_capture_devices_dispatcher.h"
+#include "libcef/browser/net/chrome_scheme_handler.h"
+#include "libcef/browser/net/throttle_handler.h"
+#include "libcef/browser/net_service/cookie_manager_impl.h"
+#include "libcef/browser/net_service/login_delegate.h"
+#include "libcef/browser/net_service/proxy_url_loader_factory.h"
+#include "libcef/browser/net_service/resource_request_handler_wrapper.h"
+#include "libcef/browser/prefs/renderer_prefs.h"
+#include "libcef/browser/speech_recognition_manager_delegate.h"
+#include "libcef/browser/thread_util.h"
+#include "libcef/browser/x509_certificate_impl.h"
+#include "libcef/common/alloy/alloy_content_client.h"
+#include "libcef/common/app_manager.h"
+#include "libcef/common/cef_switches.h"
+#include "libcef/common/command_line_impl.h"
+#include "libcef/common/extensions/extensions_util.h"
+#include "libcef/common/frame_util.h"
+#include "libcef/common/net/scheme_registration.h"
+#include "libcef/common/request_impl.h"
+
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/json/json_reader.h"
+#include "base/path_service.h"
+#include "base/stl_util.h"
+#include "base/threading/thread_restrictions.h"
+#include "cef/grit/cef_resources.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/content_settings/cookie_settings_factory.h"
+#include "chrome/browser/extensions/chrome_content_browser_client_extensions_part.h"
+#include "chrome/browser/media/webrtc/media_device_salt_service_factory.h"
+#include "chrome/browser/net/profile_network_context_service.h"
+#include "chrome/browser/net/profile_network_context_service_factory.h"
+#include "chrome/browser/net/system_network_context_manager.h"
+#include "chrome/browser/pdf/chrome_pdf_stream_delegate.h"
+#include "chrome/browser/plugins/pdf_iframe_navigation_throttle.h"
+#include "chrome/browser/plugins/plugin_info_host_impl.h"
+#include "chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.h"
+#include "chrome/browser/plugins/plugin_utils.h"
+#include "chrome/browser/predictors/network_hints_handler_impl.h"
+#include "chrome/browser/printing/print_view_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/renderer_updater.h"
+#include "chrome/browser/profiles/renderer_updater_factory.h"
+#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
+#include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h"
+#include "chrome/browser/ui/chrome_select_file_policy.h"
+#include "chrome/browser/ui/pdf/chrome_pdf_document_helper_client.h"
+#include "chrome/common/chrome_content_client.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/google_url_loader_throttle.h"
+#include "chrome/common/pdf_util.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/generated_resources.h"
+#include "chrome/services/printing/printing_service.h"
+#include "chrome/services/speech/buildflags/buildflags.h"
+#include "components/content_settings/core/browser/cookie_settings.h"
+#include "components/embedder_support/switches.h"
+#include "components/embedder_support/user_agent_utils.h"
+#include "components/media_device_salt/media_device_salt_service.h"
+#include "components/pdf/browser/pdf_document_helper.h"
+#include "components/pdf/browser/pdf_navigation_throttle.h"
+#include "components/pdf/browser/pdf_url_loader_request_interceptor.h"
+#include "components/pdf/common/internal_plugin_helpers.h"
+#include "components/policy/core/common/policy_pref_names.h"
+#include "components/spellcheck/common/spellcheck.mojom.h"
+#include "components/version_info/version_info.h"
+#include "content/browser/plugin_service_impl.h"
+#include "content/browser/renderer_host/render_frame_host_impl.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_ppapi_host.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/client_certificate_delegate.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/overlay_window.h"
+#include "content/public/browser/page_navigator.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/browser/web_ui_url_loader_factory.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/common/user_agent.h"
+#include "crypto/crypto_buildflags.h"
+#include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_message_filter.h"
+#include "extensions/browser/extension_protocols.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_web_contents_observer.h"
+#include "extensions/browser/extensions_browser_client.h"
+#include "extensions/browser/guest_view/extensions_guest_view.h"
+#include "extensions/browser/guest_view/web_view/web_view_guest.h"
+#include "extensions/browser/process_map.h"
+#include "extensions/browser/renderer_startup_helper.h"
+#include "extensions/browser/url_loader_factory_manager.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/switches.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
+#include "net/base/auth.h"
+#include "net/ssl/ssl_cert_request_info.h"
+#include "net/ssl/ssl_private_key.h"
+#include "pdf/pdf_features.h"
+#include "ppapi/host/ppapi_host.h"
+#include "sandbox/policy/switches.h"
+#include "services/network/public/cpp/network_switches.h"
+#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
+#include "services/service_manager/public/mojom/connector.mojom.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
+#include "third_party/blink/public/common/web_preferences/web_preferences.h"
+#include "third_party/blink/public/mojom/badging/badging.mojom.h"
+#include "third_party/blink/public/mojom/prerender/prerender.mojom.h"
+#include "third_party/blink/public/web/web_window_features.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/ui_base_switches.h"
+#include "url/gurl.h"
+
+#if BUILDFLAG(IS_MAC)
+#include "net/ssl/client_cert_store_mac.h"
+#include "services/video_capture/public/mojom/constants.mojom.h"
+#elif BUILDFLAG(IS_POSIX)
+#include "components/crash/core/app/crash_switches.h"
+#include "components/crash/core/app/crashpad.h"
+#include "content/public/common/content_descriptors.h"
+#include "libcef/common/crash_reporting.h"
+#endif
+
+#if BUILDFLAG(IS_WIN)
+#if BUILDFLAG(ENABLE_SPEECH_SERVICE)
+#include "media/mojo/mojom/renderer_extensions.mojom.h"
+#endif
+#include "net/ssl/client_cert_store_win.h"
+#include "sandbox/win/src/sandbox_policy.h"
+#endif  // BUILDFLAG(IS_WIN)
+
+#if BUILDFLAG(USE_NSS_CERTS)
+#include "net/ssl/client_cert_store_nss.h"
+#endif
+
+#if BUILDFLAG(HAS_SPELLCHECK_PANEL)
+#include "chrome/browser/spellchecker/spell_check_panel_host_impl.h"
+#endif
+
+namespace {
+
+class CefSelectClientCertificateCallbackImpl
+    : public CefSelectClientCertificateCallback {
+ public:
+  explicit CefSelectClientCertificateCallbackImpl(
+      std::unique_ptr<content::ClientCertificateDelegate> delegate)
+      : delegate_(std::move(delegate)) {}
+
+  CefSelectClientCertificateCallbackImpl(
+      const CefSelectClientCertificateCallbackImpl&) = delete;
+  CefSelectClientCertificateCallbackImpl& operator=(
+      const CefSelectClientCertificateCallbackImpl&) = delete;
+
+  ~CefSelectClientCertificateCallbackImpl() {
+    // If Select has not been called, call it with NULL to continue without any
+    // client certificate.
+    if (delegate_) {
+      DoSelect(nullptr);
+    }
+  }
+
+  void Select(CefRefPtr<CefX509Certificate> cert) override {
+    if (delegate_) {
+      DoSelect(cert);
+    }
+  }
+
+ private:
+  void DoSelect(CefRefPtr<CefX509Certificate> cert) {
+    if (CEF_CURRENTLY_ON_UIT()) {
+      RunNow(std::move(delegate_), cert);
+    } else {
+      CEF_POST_TASK(
+          CEF_UIT,
+          base::BindOnce(&CefSelectClientCertificateCallbackImpl::RunNow,
+                         std::move(delegate_), cert));
+    }
+  }
+
+  static void RunNow(
+      std::unique_ptr<content::ClientCertificateDelegate> delegate,
+      CefRefPtr<CefX509Certificate> cert) {
+    CEF_REQUIRE_UIT();
+
+    if (cert) {
+      CefX509CertificateImpl* certImpl =
+          static_cast<CefX509CertificateImpl*>(cert.get());
+      certImpl->AcquirePrivateKey(base::BindOnce(
+          &CefSelectClientCertificateCallbackImpl::RunWithPrivateKey,
+          std::move(delegate), cert));
+      return;
+    }
+
+    delegate->ContinueWithCertificate(nullptr, nullptr);
+  }
+
+  static void RunWithPrivateKey(
+      std::unique_ptr<content::ClientCertificateDelegate> delegate,
+      CefRefPtr<CefX509Certificate> cert,
+      scoped_refptr<net::SSLPrivateKey> key) {
+    CEF_REQUIRE_UIT();
+    DCHECK(cert);
+
+    if (key) {
+      CefX509CertificateImpl* certImpl =
+          static_cast<CefX509CertificateImpl*>(cert.get());
+      delegate->ContinueWithCertificate(certImpl->GetInternalCertObject(), key);
+    } else {
+      delegate->ContinueWithCertificate(nullptr, nullptr);
+    }
+  }
+
+  std::unique_ptr<content::ClientCertificateDelegate> delegate_;
+
+  IMPLEMENT_REFCOUNTING(CefSelectClientCertificateCallbackImpl);
+};
+
+#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+int GetCrashSignalFD() {
+  if (!crash_reporting::Enabled()) {
+    return -1;
+  }
+
+  int fd;
+  pid_t pid;
+  return crash_reporter::GetHandlerSocket(&fd, &pid) ? fd : -1;
+}
+#endif  // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+
+// From chrome/browser/plugins/chrome_content_browser_client_plugins_part.cc.
+void BindPluginInfoHost(
+    int render_process_id,
+    mojo::PendingAssociatedReceiver<chrome::mojom::PluginInfoHost> receiver) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  content::RenderProcessHost* host =
+      content::RenderProcessHost::FromID(render_process_id);
+  if (!host) {
+    return;
+  }
+
+  Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
+  mojo::MakeSelfOwnedAssociatedReceiver(
+      std::make_unique<PluginInfoHostImpl>(render_process_id, profile),
+      std::move(receiver));
+}
+
+void BindBadgeService(
+    content::RenderFrameHost* frame_host,
+    mojo::PendingReceiver<blink::mojom::BadgeService> receiver) {}
+
+void BindBadgeServiceForServiceWorker(
+    const content::ServiceWorkerVersionBaseInfo& info,
+    mojo::PendingReceiver<blink::mojom::BadgeService> receiver) {}
+
+#if BUILDFLAG(IS_WIN) && BUILDFLAG(ENABLE_SPEECH_SERVICE)
+void BindMediaFoundationRendererNotifierHandler(
+    content::RenderFrameHost* frame_host,
+    mojo::PendingReceiver<media::mojom::MediaFoundationRendererNotifier>
+        receiver) {}
+#endif
+
+void BindNetworkHintsHandler(
+    content::RenderFrameHost* frame_host,
+    mojo::PendingReceiver<network_hints::mojom::NetworkHintsHandler> receiver) {
+  predictors::NetworkHintsHandlerImpl::Create(frame_host, std::move(receiver));
+}
+
+base::FilePath GetUserDataPath() {
+  base::FilePath user_data_path;
+  base::PathService::Get(chrome::DIR_USER_DATA, &user_data_path);
+  DCHECK(!user_data_path.empty());
+  return user_data_path;
+}
+
+const extensions::Extension* GetEnabledExtensionFromSiteURL(
+    content::BrowserContext* context,
+    const GURL& site_url) {
+  if (!site_url.SchemeIs(extensions::kExtensionScheme)) {
+    return nullptr;
+  }
+
+  auto registry = extensions::ExtensionRegistry::Get(context);
+  if (!registry) {
+    return nullptr;
+  }
+
+  return registry->enabled_extensions().GetByID(site_url.host());
+}
+
+std::unique_ptr<blink::URLLoaderThrottle> CreateGoogleURLLoaderThrottle(
+    Profile* profile) {
+  chrome::mojom::DynamicParamsPtr dynamic_params =
+      chrome::mojom::DynamicParams::New(
+#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS)
+          /*bound_session_params=*/nullptr,
+#endif
+          profile->GetPrefs()->GetBoolean(
+              policy::policy_prefs::kForceGoogleSafeSearch),
+          profile->GetPrefs()->GetInteger(
+              policy::policy_prefs::kForceYouTubeRestrict),
+          profile->GetPrefs()->GetString(prefs::kAllowedDomainsForApps));
+  return std::make_unique<GoogleURLLoaderThrottle>(
+#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS)
+      /*bound_session_request_throttled_listener=*/nullptr,
+#endif
+      std::move(dynamic_params));
+}
+
+}  // namespace
+
+AlloyContentBrowserClient::AlloyContentBrowserClient() = default;
+
+AlloyContentBrowserClient::~AlloyContentBrowserClient() = default;
+
+std::unique_ptr<content::BrowserMainParts>
+AlloyContentBrowserClient::CreateBrowserMainParts(
+    bool /* is_integration_test */) {
+  auto browser_main_parts = std::make_unique<AlloyBrowserMainParts>();
+  browser_main_parts_ = browser_main_parts.get();
+  return browser_main_parts;
+}
+
+void AlloyContentBrowserClient::RenderProcessWillLaunch(
+    content::RenderProcessHost* host) {
+  const int id = host->GetID();
+  Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
+
+  if (extensions::ExtensionsEnabled()) {
+    host->AddFilter(new extensions::ExtensionMessageFilter(id, profile));
+  }
+
+  // If the renderer process crashes then the host may already have
+  // CefBrowserInfoManager as an observer. Try to remove it first before adding
+  // to avoid DCHECKs.
+  host->RemoveObserver(CefBrowserInfoManager::GetInstance());
+  host->AddObserver(CefBrowserInfoManager::GetInstance());
+
+  // Forwards dynamic parameters to CefRenderThreadObserver.
+  Profile* original_profile = profile->GetOriginalProfile();
+  RendererUpdaterFactory::GetForProfile(original_profile)
+      ->InitializeRenderer(host);
+}
+
+bool AlloyContentBrowserClient::ShouldUseProcessPerSite(
+    content::BrowserContext* browser_context,
+    const GURL& site_url) {
+  if (extensions::ExtensionsEnabled()) {
+    if (auto profile = Profile::FromBrowserContext(browser_context)) {
+      return extensions::ChromeContentBrowserClientExtensionsPart::
+          ShouldUseProcessPerSite(profile, site_url);
+    }
+  }
+
+  return content::ContentBrowserClient::ShouldUseProcessPerSite(browser_context,
+                                                                site_url);
+}
+
+bool AlloyContentBrowserClient::ShouldUseSpareRenderProcessHost(
+    content::BrowserContext* browser_context,
+    const GURL& site_url) {
+  if (extensions::ExtensionsEnabled()) {
+    if (auto profile = Profile::FromBrowserContext(browser_context)) {
+      return extensions::ChromeContentBrowserClientExtensionsPart::
+          ShouldUseSpareRenderProcessHost(profile, site_url);
+    }
+  }
+
+  return content::ContentBrowserClient::ShouldUseSpareRenderProcessHost(
+      browser_context, site_url);
+}
+
+bool AlloyContentBrowserClient::DoesSiteRequireDedicatedProcess(
+    content::BrowserContext* browser_context,
+    const GURL& effective_site_url) {
+  if (extensions::ExtensionsEnabled()) {
+    return extensions::ChromeContentBrowserClientExtensionsPart::
+        DoesSiteRequireDedicatedProcess(browser_context, effective_site_url);
+  }
+
+  return content::ContentBrowserClient::DoesSiteRequireDedicatedProcess(
+      browser_context, effective_site_url);
+}
+
+bool AlloyContentBrowserClient::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
+    base::StringPiece scheme,
+    bool is_embedded_origin_secure) {
+  // This is needed to bypass the normal SameSite rules for any chrome:// page
+  // embedding a secure origin, regardless of the registrable domains of any
+  // intervening frames. For example, this is needed for browser UI to interact
+  // with SameSite cookies on accounts.google.com, which are used for logging
+  // into Cloud Print from chrome://print, for displaying a list of available
+  // accounts on the NTP (chrome://new-tab-page), etc.
+  if (is_embedded_origin_secure && scheme == content::kChromeUIScheme) {
+    return true;
+  }
+
+  if (extensions::ExtensionsEnabled()) {
+    return scheme == extensions::kExtensionScheme;
+  }
+
+  return false;
+}
+
+bool AlloyContentBrowserClient::
+    ShouldIgnoreSameSiteCookieRestrictionsWhenTopLevel(
+        base::StringPiece scheme,
+        bool is_embedded_origin_secure) {
+  return is_embedded_origin_secure && scheme == content::kChromeUIScheme;
+}
+
+void AlloyContentBrowserClient::OverrideURLLoaderFactoryParams(
+    content::BrowserContext* browser_context,
+    const url::Origin& origin,
+    bool is_for_isolated_world,
+    network::mojom::URLLoaderFactoryParams* factory_params) {
+  if (extensions::ExtensionsEnabled()) {
+    extensions::URLLoaderFactoryManager::OverrideURLLoaderFactoryParams(
+        browser_context, origin, is_for_isolated_world, factory_params);
+  }
+}
+
+void AlloyContentBrowserClient::GetAdditionalWebUISchemes(
+    std::vector<std::string>* additional_schemes) {
+  // Any schemes listed here are treated as WebUI schemes but do not get WebUI
+  // bindings. Also, view-source is allowed for these schemes. WebUI schemes
+  // will not be passed to HandleExternalProtocol.
+}
+
+void AlloyContentBrowserClient::GetAdditionalViewSourceSchemes(
+    std::vector<std::string>* additional_schemes) {
+  GetAdditionalWebUISchemes(additional_schemes);
+
+  additional_schemes->push_back(extensions::kExtensionScheme);
+}
+
+std::unique_ptr<ui::SelectFilePolicy>
+AlloyContentBrowserClient::CreateSelectFilePolicy(
+    content::WebContents* web_contents) {
+  return std::make_unique<ChromeSelectFilePolicy>(web_contents);
+}
+
+void AlloyContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
+    std::vector<std::string>* additional_allowed_schemes) {
+  ContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
+      additional_allowed_schemes);
+  additional_allowed_schemes->push_back(content::kChromeDevToolsScheme);
+  additional_allowed_schemes->push_back(content::kChromeUIScheme);
+  additional_allowed_schemes->push_back(content::kChromeUIUntrustedScheme);
+}
+
+bool AlloyContentBrowserClient::IsWebUIAllowedToMakeNetworkRequests(
+    const url::Origin& origin) {
+  return scheme::IsWebUIAllowedToMakeNetworkRequests(origin);
+}
+
+bool AlloyContentBrowserClient::IsHandledURL(const GURL& url) {
+  if (!url.is_valid()) {
+    return false;
+  }
+  const std::string& scheme = url.scheme();
+  DCHECK_EQ(scheme, base::ToLowerASCII(scheme));
+
+  if (scheme::IsInternalHandledScheme(scheme)) {
+    return true;
+  }
+
+  return CefAppManager::Get()->HasCustomScheme(scheme);
+}
+
+void AlloyContentBrowserClient::SiteInstanceGotProcess(
+    content::SiteInstance* site_instance) {
+  if (!extensions::ExtensionsEnabled()) {
+    return;
+  }
+
+  CHECK(site_instance->HasProcess());
+
+  auto context = site_instance->GetBrowserContext();
+
+  // Only add the process to the map if the SiteInstance's site URL is already
+  // a chrome-extension:// URL. This includes hosted apps, except in rare cases
+  // that a URL in the hosted app's extent is not treated as a hosted app (e.g.,
+  // for isolated origins or cross-site iframes). For that case, don't look up
+  // the hosted app's Extension from the site URL using GetExtensionOrAppByURL,
+  // since it isn't treated as a hosted app.
+  const auto extension =
+      GetEnabledExtensionFromSiteURL(context, site_instance->GetSiteURL());
+  if (!extension) {
+    return;
+  }
+
+  extensions::ProcessMap::Get(context)->Insert(
+      extension->id(), site_instance->GetProcess()->GetID());
+}
+
+void AlloyContentBrowserClient::BindHostReceiverForRenderer(
+    content::RenderProcessHost* render_process_host,
+    mojo::GenericPendingReceiver receiver) {
+  if (auto host_receiver = receiver.As<spellcheck::mojom::SpellCheckHost>()) {
+    SpellCheckHostChromeImpl::Create(render_process_host->GetID(),
+                                     std::move(host_receiver));
+    return;
+  }
+
+#if BUILDFLAG(HAS_SPELLCHECK_PANEL)
+  if (auto panel_host_receiver =
+          receiver.As<spellcheck::mojom::SpellCheckPanelHost>()) {
+    SpellCheckPanelHostImpl::Create(render_process_host->GetID(),
+                                    std::move(panel_host_receiver));
+    return;
+  }
+#endif  // BUILDFLAG(HAS_SPELLCHECK_PANEL)
+}
+
+void AlloyContentBrowserClient::AppendExtraCommandLineSwitches(
+    base::CommandLine* command_line,
+    int child_process_id) {
+  const base::CommandLine* browser_cmd = base::CommandLine::ForCurrentProcess();
+
+  {
+    // Propagate the following switches to all command lines (along with any
+    // associated values) if present in the browser command line.
+    static const char* const kSwitchNames[] = {
+      switches::kDisablePackLoading,
+#if BUILDFLAG(IS_MAC)
+      switches::kFrameworkDirPath,
+      switches::kMainBundlePath,
+#endif
+      switches::kLocalesDirPath,
+      switches::kLogItems,
+      switches::kLogSeverity,
+      switches::kResourcesDirPath,
+      embedder_support::kUserAgent,
+      switches::kUserAgentProductAndVersion,
+    };
+    command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames);
+  }
+
+  const std::string& process_type =
+      command_line->GetSwitchValueASCII(switches::kProcessType);
+  if (process_type == switches::kRendererProcess) {
+    // Propagate the following switches to the renderer command line (along with
+    // any associated values) if present in the browser command line.
+    static const char* const kSwitchNames[] = {
+        switches::kDisableExtensions,
+        switches::kDisablePdfExtension,
+        switches::kDisablePrintPreview,
+        switches::kDisableScrollBounce,
+        switches::kDisableSpellChecking,
+        switches::kEnableSpeechInput,
+        switches::kUncaughtExceptionStackSize,
+        network::switches::kUnsafelyTreatInsecureOriginAsSecure,
+    };
+    command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames);
+
+    if (extensions::ExtensionsEnabled()) {
+      content::RenderProcessHost* process =
+          content::RenderProcessHost::FromID(child_process_id);
+      auto browser_context = process->GetBrowserContext();
+      CefBrowserContext* cef_browser_context =
+          process ? CefBrowserContext::FromBrowserContext(browser_context)
+                  : nullptr;
+      if (cef_browser_context) {
+        if (cef_browser_context->IsPrintPreviewSupported()) {
+          command_line->AppendSwitch(switches::kEnablePrintPreview);
+        }
+
+        // Based on ChromeContentBrowserClientExtensionsPart::
+        // AppendExtraRendererCommandLineSwitches
+        if (extensions::ProcessMap::Get(browser_context)
+                ->Contains(process->GetID())) {
+          command_line->AppendSwitch(extensions::switches::kExtensionProcess);
+        }
+      }
+    }
+  } else {
+    // Propagate the following switches to non-renderer command line (along with
+    // any associated values) if present in the browser command line.
+    static const char* const kSwitchNames[] = {
+        switches::kLang,
+    };
+    command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames);
+  }
+
+  // Necessary to populate DIR_USER_DATA in sub-processes.
+  // See resource_util.cc GetUserDataPath.
+  base::FilePath user_data_dir;
+  if (base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
+    command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
+  }
+
+#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+  if (process_type == switches::kZygoteProcess) {
+    if (browser_cmd->HasSwitch(switches::kBrowserSubprocessPath)) {
+      // Force use of the sub-process executable path for the zygote process.
+      const base::FilePath& subprocess_path =
+          browser_cmd->GetSwitchValuePath(switches::kBrowserSubprocessPath);
+      if (!subprocess_path.empty()) {
+        command_line->SetProgram(subprocess_path);
+      }
+    }
+
+    // Propagate the following switches to the zygote command line (along with
+    // any associated values) if present in the browser command line.
+    static const char* const kSwitchNames[] = {
+        switches::kLogFile,
+    };
+    command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames);
+  }
+
+  if (crash_reporting::Enabled()) {
+    int fd;
+    pid_t pid;
+    if (crash_reporter::GetHandlerSocket(&fd, &pid)) {
+      command_line->AppendSwitchASCII(
+          crash_reporter::switches::kCrashpadHandlerPid,
+          base::NumberToString(pid));
+    }
+  }
+#endif  // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+
+  CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
+  if (app.get()) {
+    CefRefPtr<CefBrowserProcessHandler> handler =
+        app->GetBrowserProcessHandler();
+    if (handler.get()) {
+      CefRefPtr<CefCommandLineImpl> commandLinePtr(
+          new CefCommandLineImpl(command_line, false, false));
+      handler->OnBeforeChildProcessLaunch(commandLinePtr.get());
+      std::ignore = commandLinePtr->Detach(nullptr);
+    }
+  }
+}
+
+std::string AlloyContentBrowserClient::GetApplicationLocale() {
+  return g_browser_process->GetApplicationLocale();
+}
+
+scoped_refptr<network::SharedURLLoaderFactory>
+AlloyContentBrowserClient::GetSystemSharedURLLoaderFactory() {
+  DCHECK(
+      content::BrowserThread::CurrentlyOn(content::BrowserThread::UI) ||
+      !content::BrowserThread::IsThreadInitialized(content::BrowserThread::UI));
+
+  if (!SystemNetworkContextManager::GetInstance()) {
+    return nullptr;
+  }
+
+  return SystemNetworkContextManager::GetInstance()
+      ->GetSharedURLLoaderFactory();
+}
+
+network::mojom::NetworkContext*
+AlloyContentBrowserClient::GetSystemNetworkContext() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  DCHECK(SystemNetworkContextManager::GetInstance());
+  return SystemNetworkContextManager::GetInstance()->GetContext();
+}
+
+content::MediaObserver* AlloyContentBrowserClient::GetMediaObserver() {
+  return CefMediaCaptureDevicesDispatcher::GetInstance();
+}
+
+content::SpeechRecognitionManagerDelegate*
+AlloyContentBrowserClient::CreateSpeechRecognitionManagerDelegate() {
+  const base::CommandLine* command_line =
+      base::CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(switches::kEnableSpeechInput)) {
+    return new CefSpeechRecognitionManagerDelegate();
+  }
+
+  return nullptr;
+}
+
+content::GeneratedCodeCacheSettings
+AlloyContentBrowserClient::GetGeneratedCodeCacheSettings(
+    content::BrowserContext* context) {
+  // If we pass 0 for size, disk_cache will pick a default size using the
+  // heuristics based on available disk size. These are implemented in
+  // disk_cache::PreferredCacheSize in net/disk_cache/cache_util.cc.
+  const base::FilePath& cache_path = context->GetPath();
+  return content::GeneratedCodeCacheSettings(!cache_path.empty() /* enabled */,
+                                             0 /* size */, cache_path);
+}
+
+void AlloyContentBrowserClient::AllowCertificateError(
+    content::WebContents* web_contents,
+    int cert_error,
+    const net::SSLInfo& ssl_info,
+    const GURL& request_url,
+    bool is_main_frame_request,
+    bool strict_enforcement,
+    base::OnceCallback<void(content::CertificateRequestResultType)> callback) {
+  auto returned_callback = certificate_query::AllowCertificateError(
+      web_contents, cert_error, ssl_info, request_url, is_main_frame_request,
+      strict_enforcement, std::move(callback), /*default_disallow=*/true);
+  // Callback should not be returned.
+  DCHECK(returned_callback.is_null());
+}
+
+base::OnceClosure AlloyContentBrowserClient::SelectClientCertificate(
+    content::BrowserContext* browser_context,
+    content::WebContents* web_contents,
+    net::SSLCertRequestInfo* cert_request_info,
+    net::ClientCertIdentityList client_certs,
+    std::unique_ptr<content::ClientCertificateDelegate> delegate) {
+  CEF_REQUIRE_UIT();
+
+  CefRefPtr<CefRequestHandler> handler;
+  CefRefPtr<AlloyBrowserHostImpl> browser =
+      AlloyBrowserHostImpl::GetBrowserForContents(web_contents);
+  if (browser.get()) {
+    CefRefPtr<CefClient> client = browser->GetClient();
+    if (client.get()) {
+      handler = client->GetRequestHandler();
+    }
+  }
+
+  if (!handler.get()) {
+    delegate->ContinueWithCertificate(nullptr, nullptr);
+    return base::OnceClosure();
+  }
+
+  CefRequestHandler::X509CertificateList certs;
+  for (net::ClientCertIdentityList::iterator iter = client_certs.begin();
+       iter != client_certs.end(); iter++) {
+    certs.push_back(new CefX509CertificateImpl(std::move(*iter)));
+  }
+
+  CefRefPtr<CefSelectClientCertificateCallbackImpl> callbackImpl(
+      new CefSelectClientCertificateCallbackImpl(std::move(delegate)));
+
+  bool proceed = handler->OnSelectClientCertificate(
+      browser.get(), cert_request_info->is_proxy,
+      cert_request_info->host_and_port.host(),
+      cert_request_info->host_and_port.port(), certs, callbackImpl.get());
+
+  if (!proceed && !certs.empty()) {
+    callbackImpl->Select(certs[0]);
+  }
+  return base::OnceClosure();
+}
+
+bool AlloyContentBrowserClient::CanCreateWindow(
+    content::RenderFrameHost* opener,
+    const GURL& opener_url,
+    const GURL& opener_top_level_frame_url,
+    const url::Origin& source_origin,
+    content::mojom::WindowContainerType container_type,
+    const GURL& target_url,
+    const content::Referrer& referrer,
+    const std::string& frame_name,
+    WindowOpenDisposition disposition,
+    const blink::mojom::WindowFeatures& features,
+    bool user_gesture,
+    bool opener_suppressed,
+    bool* no_javascript_access) {
+  CEF_REQUIRE_UIT();
+  *no_javascript_access = false;
+
+  return CefBrowserInfoManager::GetInstance()->CanCreateWindow(
+      opener, target_url, referrer, frame_name, disposition, features,
+      user_gesture, opener_suppressed, no_javascript_access);
+}
+
+void AlloyContentBrowserClient::OverrideWebkitPrefs(
+    content::WebContents* web_contents,
+    blink::web_pref::WebPreferences* prefs) {
+  auto rvh = web_contents->GetRenderViewHost();
+
+  // Using RVH instead of RFH here because rvh->GetMainFrame() may be nullptr
+  // when this method is called.
+  SkColor base_background_color;
+  renderer_prefs::PopulateWebPreferences(rvh, *prefs, base_background_color);
+
+  web_contents->SetPageBaseBackgroundColor(base_background_color);
+}
+
+bool AlloyContentBrowserClient::OverrideWebPreferencesAfterNavigation(
+    content::WebContents* web_contents,
+    blink::web_pref::WebPreferences* prefs) {
+  return renderer_prefs::PopulateWebPreferencesAfterNavigation(web_contents,
+                                                               *prefs);
+}
+
+void AlloyContentBrowserClient::BrowserURLHandlerCreated(
+    content::BrowserURLHandler* handler) {
+  scheme::BrowserURLHandlerCreated(handler);
+}
+
+std::string AlloyContentBrowserClient::GetDefaultDownloadName() {
+  return "download";
+}
+
+void AlloyContentBrowserClient::DidCreatePpapiPlugin(
+    content::BrowserPpapiHost* browser_host) {
+  browser_host->GetPpapiHost()->AddHostFactoryFilter(
+      std::unique_ptr<ppapi::host::HostFactory>(
+          new ChromeBrowserPepperHostFactory(browser_host)));
+}
+
+std::unique_ptr<content::DevToolsManagerDelegate>
+AlloyContentBrowserClient::CreateDevToolsManagerDelegate() {
+  return std::make_unique<CefDevToolsManagerDelegate>();
+}
+
+void AlloyContentBrowserClient::
+    RegisterAssociatedInterfaceBindersForRenderFrameHost(
+        content::RenderFrameHost& render_frame_host,
+        blink::AssociatedInterfaceRegistry& associated_registry) {
+  associated_registry.AddInterface<extensions::mojom::LocalFrameHost>(
+      base::BindRepeating(
+          [](content::RenderFrameHost* render_frame_host,
+             mojo::PendingAssociatedReceiver<extensions::mojom::LocalFrameHost>
+                 receiver) {
+            extensions::ExtensionWebContentsObserver::BindLocalFrameHost(
+                std::move(receiver), render_frame_host);
+          },
+          &render_frame_host));
+
+  associated_registry.AddInterface<printing::mojom::PrintManagerHost>(
+      base::BindRepeating(
+          [](content::RenderFrameHost* render_frame_host,
+             mojo::PendingAssociatedReceiver<printing::mojom::PrintManagerHost>
+                 receiver) {
+            printing::PrintViewManager::BindPrintManagerHost(
+                std::move(receiver), render_frame_host);
+          },
+          &render_frame_host));
+
+  associated_registry.AddInterface<pdf::mojom::PdfService>(base::BindRepeating(
+      [](content::RenderFrameHost* render_frame_host,
+         mojo::PendingAssociatedReceiver<pdf::mojom::PdfService> receiver) {
+        pdf::PDFDocumentHelper::BindPdfService(
+            std::move(receiver), render_frame_host,
+            std::make_unique<ChromePDFDocumentHelperClient>());
+      },
+      &render_frame_host));
+}
+
+std::vector<std::unique_ptr<content::NavigationThrottle>>
+AlloyContentBrowserClient::CreateThrottlesForNavigation(
+    content::NavigationHandle* navigation_handle) {
+  throttle::NavigationThrottleList throttles;
+
+  if (extensions::ExtensionsEnabled()) {
+    auto pdf_iframe_throttle =
+        PDFIFrameNavigationThrottle::MaybeCreateThrottleFor(navigation_handle);
+    if (pdf_iframe_throttle) {
+      throttles.push_back(std::move(pdf_iframe_throttle));
+    }
+
+    auto pdf_throttle = pdf::PdfNavigationThrottle::MaybeCreateThrottleFor(
+        navigation_handle, std::make_unique<ChromePdfStreamDelegate>());
+    if (pdf_throttle) {
+      throttles.push_back(std::move(pdf_throttle));
+    }
+  }
+
+  throttle::CreateThrottlesForNavigation(navigation_handle, throttles);
+
+  return throttles;
+}
+
+std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
+AlloyContentBrowserClient::CreateURLLoaderThrottles(
+    const network::ResourceRequest& request,
+    content::BrowserContext* browser_context,
+    const base::RepeatingCallback<content::WebContents*()>& wc_getter,
+    content::NavigationUIData* navigation_ui_data,
+    int frame_tree_node_id) {
+  std::vector<std::unique_ptr<blink::URLLoaderThrottle>> result;
+
+  // Used to substitute View ID for PDF contents when using the PDF plugin.
+  result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>(
+      request.destination, frame_tree_node_id));
+
+  Profile* profile = Profile::FromBrowserContext(browser_context);
+
+  if (auto google_throttle = CreateGoogleURLLoaderThrottle(profile)) {
+    result.push_back(std::move(google_throttle));
+  }
+
+  return result;
+}
+
+std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
+AlloyContentBrowserClient::CreateURLLoaderThrottlesForKeepAlive(
+    const network::ResourceRequest& request,
+    content::BrowserContext* browser_context,
+    const base::RepeatingCallback<content::WebContents*()>& wc_getter,
+    int frame_tree_node_id) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  std::vector<std::unique_ptr<blink::URLLoaderThrottle>> result;
+
+  Profile* profile = Profile::FromBrowserContext(browser_context);
+
+  if (auto google_throttle = CreateGoogleURLLoaderThrottle(profile)) {
+    result.push_back(std::move(google_throttle));
+  }
+
+  return result;
+}
+
+std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
+AlloyContentBrowserClient::WillCreateURLLoaderRequestInterceptors(
+    content::NavigationUIData* navigation_ui_data,
+    int frame_tree_node_id,
+    int64_t navigation_id,
+    scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner) {
+  std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
+      interceptors;
+
+  if (extensions::ExtensionsEnabled()) {
+    auto pdf_interceptor =
+        pdf::PdfURLLoaderRequestInterceptor::MaybeCreateInterceptor(
+            frame_tree_node_id, std::make_unique<ChromePdfStreamDelegate>());
+    if (pdf_interceptor) {
+      interceptors.push_back(std::move(pdf_interceptor));
+    }
+  }
+
+  return interceptors;
+}
+
+#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+void AlloyContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
+    const base::CommandLine& command_line,
+    int child_process_id,
+    content::PosixFileDescriptorInfo* mappings) {
+  int crash_signal_fd = GetCrashSignalFD();
+  if (crash_signal_fd >= 0) {
+    mappings->Share(kCrashDumpSignal, crash_signal_fd);
+  }
+}
+#endif  //  BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+
+void AlloyContentBrowserClient::ExposeInterfacesToRenderer(
+    service_manager::BinderRegistry* registry,
+    blink::AssociatedInterfaceRegistry* associated_registry,
+    content::RenderProcessHost* host) {
+  associated_registry->AddInterface<chrome::mojom::PluginInfoHost>(
+      base::BindRepeating(&BindPluginInfoHost, host->GetID()));
+
+  if (extensions::ExtensionsEnabled()) {
+    associated_registry->AddInterface<extensions::mojom::EventRouter>(
+        base::BindRepeating(&extensions::EventRouter::BindForRenderer,
+                            host->GetID()));
+    associated_registry->AddInterface<guest_view::mojom::GuestViewHost>(
+        base::BindRepeating(
+            &extensions::ExtensionsGuestView::CreateForComponents,
+            host->GetID()));
+    associated_registry->AddInterface<extensions::mojom::GuestView>(
+        base::BindRepeating(
+            &extensions::ExtensionsGuestView::CreateForExtensions,
+            host->GetID()));
+    associated_registry->AddInterface<extensions::mojom::RendererHost>(
+        base::BindRepeating(&extensions::RendererStartupHelper::BindForRenderer,
+                            host->GetID()));
+  }
+
+  CefBrowserManager::ExposeInterfacesToRenderer(registry, associated_registry,
+                                                host);
+}
+
+std::unique_ptr<net::ClientCertStore>
+AlloyContentBrowserClient::CreateClientCertStore(
+    content::BrowserContext* browser_context) {
+  // Match the logic in ProfileNetworkContextService::CreateClientCertStore.
+#if BUILDFLAG(USE_NSS_CERTS)
+  // TODO: Add support for client implementation of crypto password dialog.
+  return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreNSS(
+      net::ClientCertStoreNSS::PasswordDelegateFactory()));
+#elif BUILDFLAG(IS_WIN)
+  return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreWin());
+#elif BUILDFLAG(IS_MAC)
+  return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreMac());
+#else
+#error Unknown platform.
+#endif
+}
+
+std::unique_ptr<content::LoginDelegate>
+AlloyContentBrowserClient::CreateLoginDelegate(
+    const net::AuthChallengeInfo& auth_info,
+    content::WebContents* web_contents,
+    const content::GlobalRequestID& request_id,
+    bool is_request_for_main_frame,
+    const GURL& url,
+    scoped_refptr<net::HttpResponseHeaders> response_headers,
+    bool first_auth_attempt,
+    LoginAuthRequiredCallback auth_required_callback) {
+  return std::make_unique<net_service::LoginDelegate>(
+      auth_info, web_contents, request_id, url,
+      std::move(auth_required_callback));
+}
+
+void AlloyContentBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories(
+    int frame_tree_node_id,
+    ukm::SourceIdObj ukm_source_id,
+    NonNetworkURLLoaderFactoryMap* factories) {
+  if (!extensions::ExtensionsEnabled()) {
+    return;
+  }
+
+  content::WebContents* web_contents =
+      content::WebContents::FromFrameTreeNodeId(frame_tree_node_id);
+  factories->emplace(
+      extensions::kExtensionScheme,
+      extensions::CreateExtensionNavigationURLLoaderFactory(
+          web_contents->GetBrowserContext(), ukm_source_id,
+          !!extensions::WebViewGuest::FromWebContents(web_contents)));
+}
+
+void AlloyContentBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
+    int render_process_id,
+    int render_frame_id,
+    const absl::optional<url::Origin>& request_initiator_origin,
+    NonNetworkURLLoaderFactoryMap* factories) {
+  if (!extensions::ExtensionsEnabled()) {
+    return;
+  }
+
+  auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id,
+                                                             render_frame_id);
+  if (factory) {
+    factories->emplace(extensions::kExtensionScheme, std::move(factory));
+  }
+
+  content::RenderFrameHost* frame_host =
+      content::RenderFrameHost::FromID(render_process_id, render_frame_id);
+  content::WebContents* web_contents =
+      content::WebContents::FromRenderFrameHost(frame_host);
+  if (!web_contents) {
+    return;
+  }
+
+  extensions::CefExtensionWebContentsObserver* web_observer =
+      extensions::CefExtensionWebContentsObserver::FromWebContents(
+          web_contents);
+
+  // There is nothing to do if no CefExtensionWebContentsObserver is attached
+  // to the |web_contents|.
+  if (!web_observer) {
+    return;
+  }
+
+  const extensions::Extension* extension =
+      web_observer->GetExtensionFromFrame(frame_host, false);
+  if (!extension) {
+    return;
+  }
+
+  std::vector<std::string> allowed_webui_hosts;
+  // Support for chrome:// scheme if appropriate.
+  if ((extension->is_extension() || extension->is_platform_app()) &&
+      extensions::Manifest::IsComponentLocation(extension->location())) {
+    // Components of chrome that are implemented as extensions or platform apps
+    // are allowed to use chrome://resources/ and chrome://theme/ URLs.
+    // See also HasCrossOriginWhitelistEntry.
+    allowed_webui_hosts.emplace_back(content::kChromeUIResourcesHost);
+    allowed_webui_hosts.emplace_back(chrome::kChromeUIThemeHost);
+  }
+  if (!allowed_webui_hosts.empty()) {
+    factories->emplace(content::kChromeUIScheme,
+                       content::CreateWebUIURLLoaderFactory(
+                           frame_host, content::kChromeUIScheme,
+                           std::move(allowed_webui_hosts)));
+  }
+}
+
+bool AlloyContentBrowserClient::WillCreateURLLoaderFactory(
+    content::BrowserContext* browser_context,
+    content::RenderFrameHost* frame,
+    int render_process_id,
+    URLLoaderFactoryType type,
+    const url::Origin& request_initiator,
+    absl::optional<int64_t> navigation_id,
+    ukm::SourceIdObj ukm_source_id,
+    mojo::PendingReceiver<network::mojom::URLLoaderFactory>* factory_receiver,
+    mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
+        header_client,
+    bool* bypass_redirect_checks,
+    bool* disable_secure_dns,
+    network::mojom::URLLoaderFactoryOverridePtr* factory_override,
+    scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner) {
+  auto request_handler = net_service::CreateInterceptedRequestHandler(
+      browser_context, frame, render_process_id,
+      type == URLLoaderFactoryType::kNavigation,
+      type == URLLoaderFactoryType::kDownload, request_initiator);
+
+  net_service::ProxyURLLoaderFactory::CreateProxy(
+      browser_context, factory_receiver, header_client,
+      std::move(request_handler));
+  return true;
+}
+
+void AlloyContentBrowserClient::OnNetworkServiceCreated(
+    network::mojom::NetworkService* network_service) {
+  DCHECK(g_browser_process);
+  PrefService* local_state = g_browser_process->local_state();
+  DCHECK(local_state);
+
+  // Need to set up global NetworkService state before anything else uses it.
+  DCHECK(SystemNetworkContextManager::GetInstance());
+  SystemNetworkContextManager::GetInstance()->OnNetworkServiceCreated(
+      network_service);
+}
+
+bool AlloyContentBrowserClient::ConfigureNetworkContextParams(
+    content::BrowserContext* context,
+    bool in_memory,
+    const base::FilePath& relative_partition_path,
+    network::mojom::NetworkContextParams* network_context_params,
+    cert_verifier::mojom::CertVerifierCreationParams*
+        cert_verifier_creation_params) {
+  // This method may be called during shutdown when using multi-threaded
+  // message loop mode. In that case exit early to avoid crashes.
+  if (!SystemNetworkContextManager::GetInstance()) {
+    // Cancel NetworkContext creation in
+    // StoragePartitionImpl::InitNetworkContext.
+    return false;
+  }
+
+  auto cef_context = CefBrowserContext::FromBrowserContext(context);
+
+  Profile* profile = cef_context->AsProfile();
+  ProfileNetworkContextService* service =
+      ProfileNetworkContextServiceFactory::GetForContext(profile);
+  if (service) {
+    service->ConfigureNetworkContextParams(in_memory, relative_partition_path,
+                                           network_context_params,
+                                           cert_verifier_creation_params);
+  } else {
+    // Set default params.
+    network_context_params->user_agent = GetUserAgent();
+    network_context_params->accept_language = GetApplicationLocale();
+  }
+
+  network_context_params->cookieable_schemes =
+      cef_context->GetCookieableSchemes();
+
+  // TODO(cef): Remove this and add required NetworkAnonymizationKey,
+  // this is currently not the case and this was not required pre M84.
+  network_context_params->require_network_anonymization_key = false;
+
+  return true;
+}
+
+// The sandbox may block read/write access from the NetworkService to
+// directories that are not returned by this method.
+std::vector<base::FilePath>
+AlloyContentBrowserClient::GetNetworkContextsParentDirectory() {
+  return {GetUserDataPath()};
+}
+
+bool AlloyContentBrowserClient::HandleExternalProtocol(
+    const GURL& url,
+    content::WebContents::Getter web_contents_getter,
+    int frame_tree_node_id,
+    content::NavigationUIData* navigation_data,
+    bool is_primary_main_frame,
+    bool is_in_fenced_frame_tree,
+    network::mojom::WebSandboxFlags sandbox_flags,
+    ui::PageTransition page_transition,
+    bool has_user_gesture,
+    const absl::optional<url::Origin>& initiating_origin,
+    content::RenderFrameHost* initiator_document,
+    mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
+  // Call the other HandleExternalProtocol variant.
+  return false;
+}
+
+bool AlloyContentBrowserClient::HandleExternalProtocol(
+    content::WebContents::Getter web_contents_getter,
+    int frame_tree_node_id,
+    content::NavigationUIData* navigation_data,
+    bool is_primary_main_frame,
+    bool is_in_fenced_frame_tree,
+    network::mojom::WebSandboxFlags sandbox_flags,
+    const network::ResourceRequest& resource_request,
+    const absl::optional<url::Origin>& initiating_origin,
+    content::RenderFrameHost* initiator_document,
+    mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
+  mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver =
+      out_factory->InitWithNewPipeAndPassReceiver();
+
+  // CefBrowserPlatformDelegate::HandleExternalProtocol may be called if
+  // nothing handles the request.
+  auto request_handler = net_service::CreateInterceptedRequestHandler(
+      web_contents_getter, frame_tree_node_id, resource_request,
+      base::BindRepeating(CefBrowserPlatformDelegate::HandleExternalProtocol,
+                          resource_request.url));
+
+  net_service::ProxyURLLoaderFactory::CreateProxy(
+      web_contents_getter, std::move(receiver), std::move(request_handler));
+  return true;
+}
+
+std::unique_ptr<content::VideoOverlayWindow>
+AlloyContentBrowserClient::CreateWindowForVideoPictureInPicture(
+    content::VideoPictureInPictureWindowController* controller) {
+  // Note: content::VideoOverlayWindow::Create() is defined by platform-specific
+  // implementation in chrome/browser/ui/views. This layering hack, which goes
+  // through //content and ContentBrowserClient, allows us to work around the
+  // dependency constraints that disallow directly calling
+  // chrome/browser/ui/views code either from here or from other code in
+  // chrome/browser.
+  return content::VideoOverlayWindow::Create(controller);
+}
+
+void AlloyContentBrowserClient::RegisterBrowserInterfaceBindersForFrame(
+    content::RenderFrameHost* render_frame_host,
+    mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
+  CefBrowserFrame::RegisterBrowserInterfaceBindersForFrame(render_frame_host,
+                                                           map);
+
+  map->Add<blink::mojom::BadgeService>(base::BindRepeating(&BindBadgeService));
+#if BUILDFLAG(IS_WIN) && BUILDFLAG(ENABLE_SPEECH_SERVICE)
+  map->Add<media::mojom::MediaFoundationRendererNotifier>(
+      base::BindRepeating(&BindMediaFoundationRendererNotifierHandler));
+#endif
+  map->Add<network_hints::mojom::NetworkHintsHandler>(
+      base::BindRepeating(&BindNetworkHintsHandler));
+
+  if (!extensions::ExtensionsEnabled()) {
+    return;
+  }
+
+  content::WebContents* web_contents =
+      content::WebContents::FromRenderFrameHost(render_frame_host);
+  if (!web_contents) {
+    return;
+  }
+
+  const GURL& site = render_frame_host->GetSiteInstance()->GetSiteURL();
+  if (!site.SchemeIs(extensions::kExtensionScheme)) {
+    return;
+  }
+
+  content::BrowserContext* browser_context =
+      render_frame_host->GetProcess()->GetBrowserContext();
+  auto* extension = extensions::ExtensionRegistry::Get(browser_context)
+                        ->enabled_extensions()
+                        .GetByID(site.host());
+  if (!extension) {
+    return;
+  }
+  extensions::ExtensionsBrowserClient::Get()
+      ->RegisterBrowserInterfaceBindersForFrame(map, render_frame_host,
+                                                extension);
+}
+
+void AlloyContentBrowserClient::RegisterBrowserInterfaceBindersForServiceWorker(
+    content::BrowserContext* browser_context,
+    const content::ServiceWorkerVersionBaseInfo& service_worker_version_info,
+    mojo::BinderMapWithContext<const content::ServiceWorkerVersionBaseInfo&>*
+        map) {
+  map->Add<blink::mojom::BadgeService>(
+      base::BindRepeating(&BindBadgeServiceForServiceWorker));
+}
+
+base::FilePath
+AlloyContentBrowserClient::GetSandboxedStorageServiceDataDirectory() {
+  return GetUserDataPath();
+}
+
+base::FilePath AlloyContentBrowserClient::GetShaderDiskCacheDirectory() {
+  return GetUserDataPath().Append(FILE_PATH_LITERAL("ShaderCache"));
+}
+
+base::FilePath AlloyContentBrowserClient::GetGrShaderDiskCacheDirectory() {
+  return GetUserDataPath().Append(FILE_PATH_LITERAL("GrShaderCache"));
+}
+
+base::FilePath AlloyContentBrowserClient::GetGraphiteDawnDiskCacheDirectory() {
+  return GetUserDataPath().Append(FILE_PATH_LITERAL("GraphiteDawnCache"));
+}
+
+base::FilePath AlloyContentBrowserClient::GetNetLogDefaultDirectory() {
+  return GetUserDataPath();
+}
+
+base::FilePath AlloyContentBrowserClient::GetFirstPartySetsDirectory() {
+  return GetUserDataPath();
+}
+
+absl::optional<base::FilePath>
+AlloyContentBrowserClient::GetLocalTracesDirectory() {
+  return GetUserDataPath();
+}
+
+std::string AlloyContentBrowserClient::GetProduct() {
+  return GetChromeProduct();
+}
+
+std::string AlloyContentBrowserClient::GetChromeProduct() {
+  return std::string(version_info::GetProductNameAndVersionForUserAgent());
+}
+
+std::string AlloyContentBrowserClient::GetUserAgent() {
+  return embedder_support::GetUserAgent();
+}
+
+std::unique_ptr<content::WebContentsViewDelegate>
+AlloyContentBrowserClient::GetWebContentsViewDelegate(
+    content::WebContents* web_contents) {
+  return std::make_unique<AlloyWebContentsViewDelegate>(web_contents);
+}
+
+blink::UserAgentMetadata AlloyContentBrowserClient::GetUserAgentMetadata() {
+  return embedder_support::GetUserAgentMetadata(
+      g_browser_process->local_state());
+}
+
+base::flat_set<std::string>
+AlloyContentBrowserClient::GetPluginMimeTypesWithExternalHandlers(
+    content::BrowserContext* browser_context) {
+  base::flat_set<std::string> mime_types;
+  auto map = PluginUtils::GetMimeTypeToExtensionIdMap(browser_context);
+  for (const auto& pair : map) {
+    mime_types.insert(pair.first);
+  }
+  mime_types.insert(pdf::kInternalPluginMimeType);
+  return mime_types;
+}
+
+void AlloyContentBrowserClient::GetMediaDeviceIDSalt(
+    content::RenderFrameHost* rfh,
+    const net::SiteForCookies& site_for_cookies,
+    const blink::StorageKey& storage_key,
+    base::OnceCallback<void(bool, const std::string&)> callback) {
+  GURL url = rfh->GetLastCommittedURL();
+  url::Origin top_frame_origin = rfh->GetMainFrame()->GetLastCommittedOrigin();
+  content::BrowserContext* browser_context = rfh->GetBrowserContext();
+
+  // Persistent MediaDevice IDs are allowed if cookies are allowed.
+  scoped_refptr<content_settings::CookieSettings> cookie_settings =
+      CookieSettingsFactory::GetForProfile(
+          Profile::FromBrowserContext(browser_context));
+  bool allowed = cookie_settings->IsFullCookieAccessAllowed(
+      url, site_for_cookies, top_frame_origin,
+      cookie_settings->SettingOverridesForStorage());
+  media_device_salt::MediaDeviceSaltService* salt_service =
+      MediaDeviceSaltServiceFactory::GetInstance()->GetForBrowserContext(
+          browser_context);
+  if (!salt_service) {
+    std::move(callback).Run(allowed, browser_context->UniqueId());
+    return;
+  }
+
+  salt_service->GetSalt(rfh->GetStorageKey(),
+                        base::BindOnce(std::move(callback), allowed));
+}
+
+void AlloyContentBrowserClient::OnWebContentsCreated(
+    content::WebContents* web_contents) {
+  // Attach universal WebContentsObservers. These are quite rare, and in most
+  // cases CefBrowserPlatformDelegateAlloy::BrowserCreated and/or
+  // CefExtensionsAPIClient::AttachWebContentsHelpers should be used instead.
+
+  if (extensions::ExtensionsEnabled()) {
+    extensions::CefExtensionWebContentsObserver::CreateForWebContents(
+        web_contents);
+  }
+}
+
+bool AlloyContentBrowserClient::IsFindInPageDisabledForOrigin(
+    const url::Origin& origin) {
+  // For PDF viewing with the PPAPI-free PDF Viewer, find-in-page should only
+  // display results from the PDF content, and not from the UI.
+  return IsPdfExtensionOrigin(origin);
+}
+
+CefRefPtr<CefRequestContextImpl> AlloyContentBrowserClient::request_context()
+    const {
+  return browser_main_parts_->request_context();
+}
+
+CefDevToolsDelegate* AlloyContentBrowserClient::devtools_delegate() const {
+  return browser_main_parts_->devtools_delegate();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+AlloyContentBrowserClient::background_task_runner() const {
+  return browser_main_parts_->background_task_runner();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+AlloyContentBrowserClient::user_visible_task_runner() const {
+  return browser_main_parts_->user_visible_task_runner();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+AlloyContentBrowserClient::user_blocking_task_runner() const {
+  return browser_main_parts_->user_blocking_task_runner();
+}
+
+const extensions::Extension* AlloyContentBrowserClient::GetExtension(
+    content::SiteInstance* site_instance) {
+  extensions::ExtensionRegistry* registry =
+      extensions::ExtensionRegistry::Get(site_instance->GetBrowserContext());
+  if (!registry) {
+    return nullptr;
+  }
+  return registry->enabled_extensions().GetExtensionOrAppByURL(
+      site_instance->GetSiteURL());
+}
diff --git a/src/libcef/browser/content_browser_client.h b/src/libcef/browser/alloy/alloy_content_browser_client.h
similarity index 63%
rename from src/libcef/browser/content_browser_client.h
rename to src/libcef/browser/alloy/alloy_content_browser_client.h
index a673791..dcb3a96 100644
--- a/src/libcef/browser/content_browser_client.h
+++ b/src/libcef/browser/alloy/alloy_content_browser_client.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CEF_LIBCEF_BROWSER_CONTENT_BROWSER_CLIENT_H_
-#define CEF_LIBCEF_BROWSER_CONTENT_BROWSER_CLIENT_H_
+#ifndef CEF_LIBCEF_BROWSER_ALLOY_ALLOY_CONTENT_BROWSER_CLIENT_H_
+#define CEF_LIBCEF_BROWSER_ALLOY_ALLOY_CONTENT_BROWSER_CLIENT_H_
 #pragma once
 
 #include <string>
@@ -12,17 +12,15 @@
 #include "include/cef_request_context_handler.h"
 #include "libcef/browser/request_context_impl.h"
 
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "build/build_config.h"
 #include "content/public/browser/content_browser_client.h"
 #include "third_party/skia/include/core/SkColor.h"
 
-class CefBrowserMainParts;
+class AlloyBrowserMainParts;
 class CefDevToolsDelegate;
 
 namespace content {
-class PluginServiceFilter;
 class SiteInstance;
 }  // namespace content
 
@@ -30,22 +28,27 @@
 class Extension;
 }
 
-class CefContentBrowserClient : public content::ContentBrowserClient {
+class AlloyContentBrowserClient : public content::ContentBrowserClient {
  public:
-  CefContentBrowserClient();
-  ~CefContentBrowserClient() override;
-
-  // Returns the singleton CefContentBrowserClient instance.
-  static CefContentBrowserClient* Get();
+  AlloyContentBrowserClient();
+  ~AlloyContentBrowserClient() override;
 
   // ContentBrowserClient implementation.
   std::unique_ptr<content::BrowserMainParts> CreateBrowserMainParts(
-      const content::MainFunctionParams& parameters) override;
+      bool is_integration_test) override;
   void RenderProcessWillLaunch(content::RenderProcessHost* host) override;
   bool ShouldUseProcessPerSite(content::BrowserContext* browser_context,
-                               const GURL& effective_url) override;
+                               const GURL& site_url) override;
+  bool ShouldUseSpareRenderProcessHost(content::BrowserContext* browser_context,
+                                       const GURL& site_url) override;
   bool DoesSiteRequireDedicatedProcess(content::BrowserContext* browser_context,
                                        const GURL& effective_site_url) override;
+  bool ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
+      base::StringPiece scheme,
+      bool is_embedded_origin_secure) override;
+  bool ShouldIgnoreSameSiteCookieRestrictionsWhenTopLevel(
+      base::StringPiece scheme,
+      bool is_embedded_origin_secure) override;
   void OverrideURLLoaderFactoryParams(
       content::BrowserContext* browser_context,
       const url::Origin& origin,
@@ -55,25 +58,22 @@
       std::vector<std::string>* additional_schemes) override;
   void GetAdditionalViewSourceSchemes(
       std::vector<std::string>* additional_schemes) override;
+  std::unique_ptr<ui::SelectFilePolicy> CreateSelectFilePolicy(
+      content::WebContents* web_contents) override;
   void GetAdditionalAllowedSchemesForFileSystem(
       std::vector<std::string>* additional_allowed_schemes) override;
   bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin) override;
   bool IsHandledURL(const GURL& url) override;
   void SiteInstanceGotProcess(content::SiteInstance* site_instance) override;
-  void SiteInstanceDeleting(content::SiteInstance* site_instance) override;
   void BindHostReceiverForRenderer(
       content::RenderProcessHost* render_process_host,
       mojo::GenericPendingReceiver receiver) override;
-  base::Optional<service_manager::Manifest> GetServiceManifestOverlay(
-      base::StringPiece name) override;
   void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
                                       int child_process_id) override;
   std::string GetApplicationLocale() override;
   scoped_refptr<network::SharedURLLoaderFactory>
   GetSystemSharedURLLoaderFactory() override;
   network::mojom::NetworkContext* GetSystemNetworkContext() override;
-  scoped_refptr<content::QuotaPermissionContext> CreateQuotaPermissionContext()
-      override;
   content::MediaObserver* GetMediaObserver() override;
   content::SpeechRecognitionManagerDelegate*
   CreateSpeechRecognitionManagerDelegate() override;
@@ -89,6 +89,7 @@
       base::OnceCallback<void(content::CertificateRequestResultType)> callback)
       override;
   base::OnceClosure SelectClientCertificate(
+      content::BrowserContext* browser_context,
       content::WebContents* web_contents,
       net::SSLCertRequestInfo* cert_request_info,
       net::ClientCertIdentityList client_certs,
@@ -106,12 +107,19 @@
                        bool user_gesture,
                        bool opener_suppressed,
                        bool* no_javascript_access) override;
-  void OverrideWebkitPrefs(content::RenderViewHost* rvh,
-                           content::WebPreferences* prefs) override;
+  void OverrideWebkitPrefs(content::WebContents* web_contents,
+                           blink::web_pref::WebPreferences* prefs) override;
+  bool OverrideWebPreferencesAfterNavigation(
+      content::WebContents* web_contents,
+      blink::web_pref::WebPreferences* prefs) override;
   void BrowserURLHandlerCreated(content::BrowserURLHandler* handler) override;
   std::string GetDefaultDownloadName() override;
   void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override;
-  content::DevToolsManagerDelegate* GetDevToolsManagerDelegate() override;
+  std::unique_ptr<content::DevToolsManagerDelegate>
+  CreateDevToolsManagerDelegate() override;
+  void RegisterAssociatedInterfaceBindersForRenderFrameHost(
+      content::RenderFrameHost& render_frame_host,
+      blink::AssociatedInterfaceRegistry& associated_registry) override;
   std::vector<std::unique_ptr<content::NavigationThrottle>>
   CreateThrottlesForNavigation(
       content::NavigationHandle* navigation_handle) override;
@@ -122,20 +130,27 @@
       const base::RepeatingCallback<content::WebContents*()>& wc_getter,
       content::NavigationUIData* navigation_ui_data,
       int frame_tree_node_id) override;
+  std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
+  CreateURLLoaderThrottlesForKeepAlive(
+      const network::ResourceRequest& request,
+      content::BrowserContext* browser_context,
+      const base::RepeatingCallback<content::WebContents*()>& wc_getter,
+      int frame_tree_node_id) override;
+  std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
+  WillCreateURLLoaderRequestInterceptors(
+      content::NavigationUIData* navigation_ui_data,
+      int frame_tree_node_id,
+      int64_t navigation_id,
+      scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner)
+      override;
 
-#if defined(OS_LINUX)
+#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
   void GetAdditionalMappedFilesForChildProcess(
       const base::CommandLine& command_line,
       int child_process_id,
       content::PosixFileDescriptorInfo* mappings) override;
 #endif
 
-#if defined(OS_WIN)
-  const wchar_t* GetResourceDllName();
-  bool PreSpawnRenderer(sandbox::TargetPolicy* policy,
-                        RendererSpawnFlags flags) override;
-#endif
-
   void ExposeInterfacesToRenderer(
       service_manager::BinderRegistry* registry,
       blink::AssociatedInterfaceRegistry* associated_registry,
@@ -153,10 +168,12 @@
       LoginAuthRequiredCallback auth_required_callback) override;
   void RegisterNonNetworkNavigationURLLoaderFactories(
       int frame_tree_node_id,
+      ukm::SourceIdObj ukm_source_id,
       NonNetworkURLLoaderFactoryMap* factories) override;
   void RegisterNonNetworkSubresourceURLLoaderFactories(
       int render_process_id,
       int render_frame_id,
+      const absl::optional<url::Origin>& request_initiator_origin,
       NonNetworkURLLoaderFactoryMap* factories) override;
   bool WillCreateURLLoaderFactory(
       content::BrowserContext* browser_context,
@@ -164,51 +181,85 @@
       int render_process_id,
       URLLoaderFactoryType type,
       const url::Origin& request_initiator,
-      base::Optional<int64_t> navigation_id,
+      absl::optional<int64_t> navigation_id,
+      ukm::SourceIdObj ukm_source_id,
       mojo::PendingReceiver<network::mojom::URLLoaderFactory>* factory_receiver,
       mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
           header_client,
       bool* bypass_redirect_checks,
       bool* disable_secure_dns,
-      network::mojom::URLLoaderFactoryOverridePtr* factory_override) override;
+      network::mojom::URLLoaderFactoryOverridePtr* factory_override,
+      scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner)
+      override;
   void OnNetworkServiceCreated(
       network::mojom::NetworkService* network_service) override;
-  mojo::Remote<network::mojom::NetworkContext> CreateNetworkContext(
+  bool ConfigureNetworkContextParams(
       content::BrowserContext* context,
       bool in_memory,
-      const base::FilePath& relative_partition_path) override;
+      const base::FilePath& relative_partition_path,
+      network::mojom::NetworkContextParams* network_context_params,
+      cert_verifier::mojom::CertVerifierCreationParams*
+          cert_verifier_creation_params) override;
   std::vector<base::FilePath> GetNetworkContextsParentDirectory() override;
   bool HandleExternalProtocol(
       const GURL& url,
-      base::OnceCallback<content::WebContents*()> web_contents_getter,
-      int child_id,
+      content::WebContents::Getter web_contents_getter,
+      int frame_tree_node_id,
       content::NavigationUIData* navigation_data,
-      bool is_main_frame,
+      bool is_primary_main_frame,
+      bool is_in_fenced_frame_tree,
+      network::mojom::WebSandboxFlags sandbox_flags,
       ui::PageTransition page_transition,
       bool has_user_gesture,
-      const base::Optional<url::Origin>& initiating_origin,
+      const absl::optional<url::Origin>& initiating_origin,
+      content::RenderFrameHost* initiator_document,
       mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory)
       override;
   bool HandleExternalProtocol(
       content::WebContents::Getter web_contents_getter,
       int frame_tree_node_id,
       content::NavigationUIData* navigation_data,
+      bool is_primary_main_frame,
+      bool is_in_fenced_frame_tree,
+      network::mojom::WebSandboxFlags sandbox_flags,
       const network::ResourceRequest& request,
+      const absl::optional<url::Origin>& initiating_origin,
+      content::RenderFrameHost* initiator_document,
       mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory)
       override;
-  std::unique_ptr<content::OverlayWindow> CreateWindowForPictureInPicture(
-      content::PictureInPictureWindowController* controller) override;
+  std::unique_ptr<content::VideoOverlayWindow>
+  CreateWindowForVideoPictureInPicture(
+      content::VideoPictureInPictureWindowController* controller) override;
   void RegisterBrowserInterfaceBindersForFrame(
       content::RenderFrameHost* render_frame_host,
-      service_manager::BinderMapWithContext<content::RenderFrameHost*>* map)
-      override;
+      mojo::BinderMapWithContext<content::RenderFrameHost*>* map) override;
+  void RegisterBrowserInterfaceBindersForServiceWorker(
+      content::BrowserContext* browser_context,
+      const content::ServiceWorkerVersionBaseInfo& service_worker_version_info,
+      mojo::BinderMapWithContext<const content::ServiceWorkerVersionBaseInfo&>*
+          map) override;
   base::FilePath GetSandboxedStorageServiceDataDirectory() override;
+  base::FilePath GetShaderDiskCacheDirectory() override;
+  base::FilePath GetGrShaderDiskCacheDirectory() override;
+  base::FilePath GetGraphiteDawnDiskCacheDirectory() override;
+  base::FilePath GetNetLogDefaultDirectory() override;
+  base::FilePath GetFirstPartySetsDirectory() override;
+  absl::optional<base::FilePath> GetLocalTracesDirectory() override;
   std::string GetProduct() override;
   std::string GetChromeProduct() override;
   std::string GetUserAgent() override;
+  std::unique_ptr<content::WebContentsViewDelegate> GetWebContentsViewDelegate(
+      content::WebContents* web_contents) override;
   blink::UserAgentMetadata GetUserAgentMetadata() override;
   base::flat_set<std::string> GetPluginMimeTypesWithExternalHandlers(
       content::BrowserContext* browser_context) override;
+  void GetMediaDeviceIDSalt(
+      content::RenderFrameHost* rfh,
+      const net::SiteForCookies& site_for_cookies,
+      const blink::StorageKey& storage_key,
+      base::OnceCallback<void(bool, const std::string&)> callback) override;
+  void OnWebContentsCreated(content::WebContents* web_contents) override;
+  bool IsFindInPageDisabledForOrigin(const url::Origin& origin) override;
 
   CefRefPtr<CefRequestContextImpl> request_context() const;
   CefDevToolsDelegate* devtools_delegate() const;
@@ -222,9 +273,7 @@
   const extensions::Extension* GetExtension(
       content::SiteInstance* site_instance);
 
-  CefBrowserMainParts* browser_main_parts_;
-
-  std::unique_ptr<content::PluginServiceFilter> plugin_service_filter_;
+  AlloyBrowserMainParts* browser_main_parts_ = nullptr;
 };
 
-#endif  // CEF_LIBCEF_BROWSER_CONTENT_BROWSER_CLIENT_H_
+#endif  // CEF_LIBCEF_BROWSER_ALLOY_ALLOY_CONTENT_BROWSER_CLIENT_H_
diff --git a/src/libcef/browser/alloy/alloy_download_util.cc b/src/libcef/browser/alloy/alloy_download_util.cc
new file mode 100644
index 0000000..92e52b6
--- /dev/null
+++ b/src/libcef/browser/alloy/alloy_download_util.cc
@@ -0,0 +1,16 @@
+// Copyright 2021 The Chromium Embedded Framework 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 "libcef/browser/alloy/alloy_download_util.h"
+
+#include "libcef/browser/alloy/alloy_browser_context.h"
+
+namespace alloy {
+
+DownloadPrefs* GetDownloadPrefsFromBrowserContext(
+    content::BrowserContext* context) {
+  return static_cast<AlloyBrowserContext*>(context)->GetDownloadPrefs();
+}
+
+}  // namespace alloy
diff --git a/src/libcef/browser/alloy/alloy_download_util.h b/src/libcef/browser/alloy/alloy_download_util.h
new file mode 100644
index 0000000..51c2e28
--- /dev/null
+++ b/src/libcef/browser/alloy/alloy_download_util.h
@@ -0,0 +1,23 @@
+// Copyright 2021 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_ALLOY_ALLOY_DOWNLOAD_UTIL_H_
+#define CEF_LIBCEF_BROWSER_ALLOY_ALLOY_DOWNLOAD_UTIL_H_
+#pragma once
+
+class DownloadPrefs;
+
+namespace content {
+class BrowserContext;
+}  // namespace content
+
+namespace alloy {
+
+// Called from DownloadPrefs::FromBrowserContext.
+DownloadPrefs* GetDownloadPrefsFromBrowserContext(
+    content::BrowserContext* context);
+
+}  // namespace alloy
+
+#endif  // CEF_LIBCEF_BROWSER_ALLOY_ALLOY_DOWNLOAD_UTIL_H_
diff --git a/src/libcef/browser/alloy/alloy_web_contents_view_delegate.cc b/src/libcef/browser/alloy/alloy_web_contents_view_delegate.cc
new file mode 100644
index 0000000..39a65dc
--- /dev/null
+++ b/src/libcef/browser/alloy/alloy_web_contents_view_delegate.cc
@@ -0,0 +1,22 @@
+// Copyright 2022 The Chromium Embedded Framework 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 "libcef/browser/alloy/alloy_web_contents_view_delegate.h"
+
+#include "content/public/browser/web_contents.h"
+
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
+
+AlloyWebContentsViewDelegate::AlloyWebContentsViewDelegate(
+    content::WebContents* web_contents)
+    : web_contents_(web_contents) {}
+
+void AlloyWebContentsViewDelegate::ShowContextMenu(
+    content::RenderFrameHost& render_frame_host,
+    const content::ContextMenuParams& params) {
+  if (auto browser =
+          AlloyBrowserHostImpl::GetBrowserForContents(web_contents_)) {
+    browser->ShowContextMenu(params);
+  }
+}
diff --git a/src/libcef/browser/alloy/alloy_web_contents_view_delegate.h b/src/libcef/browser/alloy/alloy_web_contents_view_delegate.h
new file mode 100644
index 0000000..17992df
--- /dev/null
+++ b/src/libcef/browser/alloy/alloy_web_contents_view_delegate.h
@@ -0,0 +1,33 @@
+// Copyright 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_ALLOY_ALLOY_WEB_CONTENTS_VIEW_DELEGATE_H_
+#define CEF_LIBCEF_BROWSER_ALLOY_ALLOY_WEB_CONTENTS_VIEW_DELEGATE_H_
+#pragma once
+
+#include "include/internal/cef_ptr.h"
+
+#include "content/public/browser/web_contents_view_delegate.h"
+
+namespace content {
+class WebContents;
+}
+
+class AlloyWebContentsViewDelegate : public content::WebContentsViewDelegate {
+ public:
+  explicit AlloyWebContentsViewDelegate(content::WebContents* web_contents);
+
+  AlloyWebContentsViewDelegate(const AlloyWebContentsViewDelegate&) = delete;
+  AlloyWebContentsViewDelegate& operator=(const AlloyWebContentsViewDelegate&) =
+      delete;
+
+  // WebContentsViewDelegate methods:
+  void ShowContextMenu(content::RenderFrameHost& render_frame_host,
+                       const content::ContextMenuParams& params) override;
+
+ private:
+  content::WebContents* const web_contents_;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_ALLOY_ALLOY_WEB_CONTENTS_VIEW_DELEGATE_H_
diff --git a/src/libcef/browser/alloy/browser_platform_delegate_alloy.cc b/src/libcef/browser/alloy/browser_platform_delegate_alloy.cc
new file mode 100644
index 0000000..49849bd
--- /dev/null
+++ b/src/libcef/browser/alloy/browser_platform_delegate_alloy.cc
@@ -0,0 +1,441 @@
+// Copyright 2015 The Chromium Embedded Framework 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 "libcef/browser/alloy/browser_platform_delegate_alloy.h"
+
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
+#include "libcef/browser/alloy/dialogs/alloy_javascript_dialog_manager_delegate.h"
+#include "libcef/browser/extensions/browser_extensions_util.h"
+#include "libcef/browser/extensions/extension_background_host.h"
+#include "libcef/browser/extensions/extension_system.h"
+#include "libcef/browser/extensions/extension_view_host.h"
+#include "libcef/browser/extensions/extension_web_contents_observer.h"
+#include "libcef/common/extensions/extensions_util.h"
+#include "libcef/common/net/url_util.h"
+#include "libcef/features/runtime_checks.h"
+
+#include "base/logging.h"
+#include "chrome/browser/printing/print_view_manager.h"
+#include "chrome/browser/ui/prefs/prefs_tab_helper.h"
+#include "components/find_in_page/find_tab_helper.h"
+#include "components/find_in_page/find_types.h"
+#include "components/javascript_dialogs/tab_modal_dialog_manager.h"
+#include "components/permissions/permission_request_manager.h"
+#include "components/zoom/zoom_controller.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/render_view_host.h"
+#include "extensions/browser/process_manager.h"
+#include "pdf/pdf_features.h"
+#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
+
+CefBrowserPlatformDelegateAlloy::CefBrowserPlatformDelegateAlloy()
+    : weak_ptr_factory_(this) {}
+
+content::WebContents* CefBrowserPlatformDelegateAlloy::CreateWebContents(
+    CefBrowserCreateParams& create_params,
+    bool& own_web_contents) {
+  REQUIRE_ALLOY_RUNTIME();
+  DCHECK(primary_);
+
+  if (!create_params.request_context) {
+    // Using the global request context.
+    create_params.request_context = CefRequestContext::GetGlobalContext();
+  }
+
+  auto* browser_context =
+      CefRequestContextImpl::GetBrowserContext(create_params.request_context);
+  CHECK(browser_context);
+
+  scoped_refptr<content::SiteInstance> site_instance;
+  if (extensions::ExtensionsEnabled() && !create_params.url.empty()) {
+    GURL gurl = url_util::MakeGURL(create_params.url, /*fixup=*/true);
+    if (!create_params.extension) {
+      // We might be loading an extension app view where the extension URL is
+      // provided by the client.
+      create_params.extension =
+          extensions::GetExtensionForUrl(browser_context, gurl);
+    }
+    if (create_params.extension) {
+      if (create_params.extension_host_type ==
+          extensions::mojom::ViewType::kInvalid) {
+        // Default to dialog behavior.
+        create_params.extension_host_type =
+            extensions::mojom::ViewType::kExtensionDialog;
+      }
+
+      // Extension resources will fail to load if we don't use a SiteInstance
+      // associated with the extension.
+      // (AlloyContentBrowserClient::SiteInstanceGotProcess won't find the
+      // extension to register with InfoMap, and AllowExtensionResourceLoad in
+      // ExtensionProtocolHandler::MaybeCreateJob will return false resulting in
+      // ERR_BLOCKED_BY_CLIENT).
+      site_instance = extensions::ProcessManager::Get(browser_context)
+                          ->GetSiteInstanceForURL(gurl);
+      DCHECK(site_instance);
+    }
+  }
+
+  content::WebContents::CreateParams wc_create_params(browser_context,
+                                                      site_instance);
+
+  if (IsWindowless()) {
+    // Create the OSR view for the WebContents.
+    CreateViewForWebContents(&wc_create_params.view,
+                             &wc_create_params.delegate_view);
+  }
+
+  auto web_contents = content::WebContents::Create(wc_create_params);
+  CHECK(web_contents);
+
+  own_web_contents = true;
+  return web_contents.release();
+}
+
+void CefBrowserPlatformDelegateAlloy::WebContentsCreated(
+    content::WebContents* web_contents,
+    bool owned) {
+  CefBrowserPlatformDelegate::WebContentsCreated(web_contents, owned);
+
+  if (primary_) {
+    find_in_page::FindTabHelper::CreateForWebContents(web_contents);
+
+    if (owned) {
+      SetOwnedWebContents(web_contents);
+    }
+  } else {
+    DCHECK(!owned);
+  }
+}
+
+void CefBrowserPlatformDelegateAlloy::AddNewContents(
+    content::WebContents* source,
+    std::unique_ptr<content::WebContents> new_contents,
+    const GURL& target_url,
+    WindowOpenDisposition disposition,
+    const blink::mojom::WindowFeatures& window_features,
+    bool user_gesture,
+    bool* was_blocked) {
+  REQUIRE_ALLOY_RUNTIME();
+  DCHECK(primary_);
+
+  CefRefPtr<AlloyBrowserHostImpl> owner =
+      AlloyBrowserHostImpl::GetBrowserForContents(new_contents.get());
+  if (owner) {
+    // Taking ownership of |new_contents|.
+    static_cast<CefBrowserPlatformDelegateAlloy*>(
+        owner->platform_delegate_.get())
+        ->SetOwnedWebContents(new_contents.release());
+    return;
+  }
+
+  if (extension_host_) {
+    extension_host_->AddNewContents(source, std::move(new_contents), target_url,
+                                    disposition, window_features, user_gesture,
+                                    was_blocked);
+  }
+}
+
+bool CefBrowserPlatformDelegateAlloy::
+    ShouldAllowRendererInitiatedCrossProcessNavigation(
+        bool is_main_frame_navigation) {
+  if (extension_host_) {
+    return extension_host_->ShouldAllowRendererInitiatedCrossProcessNavigation(
+        is_main_frame_navigation);
+  }
+  return true;
+}
+
+void CefBrowserPlatformDelegateAlloy::RenderViewReady() {
+  ConfigureAutoResize();
+}
+
+void CefBrowserPlatformDelegateAlloy::BrowserCreated(
+    CefBrowserHostBase* browser) {
+  CefBrowserPlatformDelegate::BrowserCreated(browser);
+
+  // Only register WebContents delegate/observers if we're the primary delegate.
+  if (!primary_) {
+    return;
+  }
+
+  DCHECK(!web_contents_->GetDelegate());
+  web_contents_->SetDelegate(static_cast<AlloyBrowserHostImpl*>(browser));
+
+  permissions::PermissionRequestManager::CreateForWebContents(web_contents_);
+  PrefsTabHelper::CreateForWebContents(web_contents_);
+  printing::PrintViewManager::CreateForWebContents(web_contents_);
+  zoom::ZoomController::CreateForWebContents(web_contents_);
+
+  javascript_dialogs::TabModalDialogManager::CreateForWebContents(
+      web_contents_,
+      CreateAlloyJavaScriptTabModalDialogManagerDelegateDesktop(web_contents_));
+
+  // Used for print preview and JavaScript dialogs.
+  web_contents_dialog_helper_.reset(
+      new AlloyWebContentsDialogHelper(web_contents_, this));
+}
+
+void CefBrowserPlatformDelegateAlloy::CreateExtensionHost(
+    const extensions::Extension* extension,
+    const GURL& url,
+    extensions::mojom::ViewType host_type) {
+  REQUIRE_ALLOY_RUNTIME();
+  DCHECK(primary_);
+
+  // Should get WebContentsCreated and BrowserCreated calls first.
+  DCHECK(web_contents_);
+  DCHECK(browser_);
+  DCHECK(!extension_host_);
+
+  auto alloy_browser = static_cast<AlloyBrowserHostImpl*>(browser_);
+
+  if (host_type == extensions::mojom::ViewType::kExtensionDialog ||
+      host_type == extensions::mojom::ViewType::kExtensionPopup) {
+    // Create an extension host that we own.
+    extension_host_ = new extensions::CefExtensionViewHost(
+        alloy_browser, extension, web_contents_, url, host_type);
+    // Trigger load of the extension URL.
+    extension_host_->CreateRendererSoon();
+  } else if (host_type ==
+             extensions::mojom::ViewType::kExtensionBackgroundPage) {
+    is_background_host_ = true;
+    alloy_browser->is_background_host_ = true;
+    // Create an extension host that will be owned by ProcessManager.
+    extension_host_ = new extensions::CefExtensionBackgroundHost(
+        alloy_browser,
+        base::BindOnce(&CefBrowserPlatformDelegateAlloy::OnExtensionHostDeleted,
+                       weak_ptr_factory_.GetWeakPtr()),
+        extension, web_contents_, url, host_type);
+    // Load will be triggered by ProcessManager::CreateBackgroundHost.
+  } else {
+    DCHECK(false) << " Unsupported extension host type: " << host_type;
+  }
+}
+
+extensions::ExtensionHost* CefBrowserPlatformDelegateAlloy::GetExtensionHost()
+    const {
+  return extension_host_;
+}
+
+void CefBrowserPlatformDelegateAlloy::BrowserDestroyed(
+    CefBrowserHostBase* browser) {
+  if (primary_) {
+    DestroyExtensionHost();
+    owned_web_contents_.reset();
+  }
+
+  CefBrowserPlatformDelegate::BrowserDestroyed(browser);
+}
+
+web_modal::WebContentsModalDialogHost*
+CefBrowserPlatformDelegateAlloy::GetWebContentsModalDialogHost() const {
+  return web_contents_dialog_helper_.get();
+}
+
+void CefBrowserPlatformDelegateAlloy::SendCaptureLostEvent() {
+  if (!web_contents_) {
+    return;
+  }
+  content::RenderViewHost* host = web_contents_->GetRenderViewHost();
+  if (!host) {
+    return;
+  }
+
+  content::RenderWidgetHostImpl* widget =
+      content::RenderWidgetHostImpl::From(host->GetWidget());
+  if (widget) {
+    widget->LostCapture();
+  }
+}
+
+#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC))
+void CefBrowserPlatformDelegateAlloy::NotifyMoveOrResizeStarted() {
+  if (!browser_) {
+    return;
+  }
+
+  // Dismiss any existing popups.
+  auto frame = browser_->GetMainFrame();
+  if (frame && frame->IsValid()) {
+    static_cast<CefFrameHostImpl*>(frame.get())->NotifyMoveOrResizeStarted();
+  }
+}
+#endif
+
+bool CefBrowserPlatformDelegateAlloy::PreHandleGestureEvent(
+    content::WebContents* source,
+    const blink::WebGestureEvent& event) {
+  if (extension_host_) {
+    return extension_host_->PreHandleGestureEvent(source, event);
+  }
+  return false;
+}
+
+bool CefBrowserPlatformDelegateAlloy::IsNeverComposited(
+    content::WebContents* web_contents) {
+  if (extension_host_) {
+    return extension_host_->IsNeverComposited(web_contents);
+  }
+  return false;
+}
+
+void CefBrowserPlatformDelegateAlloy::SetAutoResizeEnabled(
+    bool enabled,
+    const CefSize& min_size,
+    const CefSize& max_size) {
+  if (enabled == auto_resize_enabled_) {
+    return;
+  }
+
+  auto_resize_enabled_ = enabled;
+  if (enabled) {
+    auto_resize_min_ = gfx::Size(min_size.width, min_size.height);
+    auto_resize_max_ = gfx::Size(max_size.width, max_size.height);
+  } else {
+    auto_resize_min_ = auto_resize_max_ = gfx::Size();
+  }
+  ConfigureAutoResize();
+}
+
+void CefBrowserPlatformDelegateAlloy::ConfigureAutoResize() {
+  if (!web_contents_ || !web_contents_->GetRenderWidgetHostView()) {
+    return;
+  }
+
+  if (auto_resize_enabled_) {
+    web_contents_->GetRenderWidgetHostView()->EnableAutoResize(
+        auto_resize_min_, auto_resize_max_);
+  } else {
+    web_contents_->GetRenderWidgetHostView()->DisableAutoResize(gfx::Size());
+  }
+}
+
+void CefBrowserPlatformDelegateAlloy::SetAccessibilityState(
+    cef_state_t accessibility_state) {
+  // Do nothing if state is set to default. It'll be disabled by default and
+  // controlled by the commmand-line flags "force-renderer-accessibility" and
+  // "disable-renderer-accessibility".
+  if (accessibility_state == STATE_DEFAULT) {
+    return;
+  }
+
+  content::WebContentsImpl* web_contents_impl =
+      static_cast<content::WebContentsImpl*>(web_contents_);
+
+  if (!web_contents_impl) {
+    return;
+  }
+
+  ui::AXMode accMode;
+  // In windowless mode set accessibility to TreeOnly mode. Else native
+  // accessibility APIs, specific to each platform, are also created.
+  if (accessibility_state == STATE_ENABLED) {
+    accMode = IsWindowless() ? ui::kAXModeWebContentsOnly : ui::kAXModeComplete;
+  }
+  web_contents_impl->SetAccessibilityMode(accMode);
+}
+
+bool CefBrowserPlatformDelegateAlloy::IsPrintPreviewSupported() const {
+  REQUIRE_ALLOY_RUNTIME();
+
+  // Print preview is not currently supported with OSR.
+  if (IsWindowless()) {
+    return false;
+  }
+
+  auto cef_browser_context =
+      CefBrowserContext::FromBrowserContext(web_contents_->GetBrowserContext());
+  return cef_browser_context->IsPrintPreviewSupported();
+}
+
+void CefBrowserPlatformDelegateAlloy::Find(const CefString& searchText,
+                                           bool forward,
+                                           bool matchCase,
+                                           bool findNext) {
+  if (!web_contents_) {
+    return;
+  }
+
+  find_in_page::FindTabHelper::FromWebContents(web_contents_)
+      ->StartFinding(searchText.ToString16(), forward, matchCase, findNext,
+                     /*run_synchronously_for_testing=*/false);
+}
+
+void CefBrowserPlatformDelegateAlloy::StopFinding(bool clearSelection) {
+  if (!web_contents_) {
+    return;
+  }
+
+  last_search_result_ = find_in_page::FindNotificationDetails();
+  find_in_page::FindTabHelper::FromWebContents(web_contents_)
+      ->StopFinding(clearSelection ? find_in_page::SelectionAction::kClear
+                                   : find_in_page::SelectionAction::kKeep);
+}
+
+bool CefBrowserPlatformDelegateAlloy::HandleFindReply(
+    int request_id,
+    int number_of_matches,
+    const gfx::Rect& selection_rect,
+    int active_match_ordinal,
+    bool final_update) {
+  if (!web_contents_) {
+    return false;
+  }
+
+  auto find_in_page =
+      find_in_page::FindTabHelper::FromWebContents(web_contents_);
+
+  find_in_page->HandleFindReply(request_id, number_of_matches, selection_rect,
+                                active_match_ordinal, final_update);
+  if (!(find_in_page->find_result() == last_search_result_)) {
+    last_search_result_ = find_in_page->find_result();
+    return true;
+  }
+  return false;
+}
+
+base::RepeatingClosure
+CefBrowserPlatformDelegateAlloy::GetBoundsChangedCallback() {
+  if (web_contents_dialog_helper_) {
+    return web_contents_dialog_helper_->GetBoundsChangedCallback();
+  }
+
+  return base::RepeatingClosure();
+}
+
+void CefBrowserPlatformDelegateAlloy::SetOwnedWebContents(
+    content::WebContents* owned_contents) {
+  DCHECK(primary_);
+
+  // Should not currently own a WebContents.
+  CHECK(!owned_web_contents_);
+  owned_web_contents_.reset(owned_contents);
+}
+
+void CefBrowserPlatformDelegateAlloy::DestroyExtensionHost() {
+  if (!extension_host_) {
+    return;
+  }
+  if (extension_host_->extension_host_type() ==
+      extensions::mojom::ViewType::kExtensionBackgroundPage) {
+    DCHECK(is_background_host_);
+    // Close notification for background pages arrives via CloseContents.
+    // The extension host will be deleted by
+    // ProcessManager::CloseBackgroundHost and OnExtensionHostDeleted will be
+    // called to notify us.
+    extension_host_->Close();
+  } else {
+    DCHECK(!is_background_host_);
+    // We own the extension host and must delete it.
+    delete extension_host_;
+    extension_host_ = nullptr;
+  }
+}
+
+void CefBrowserPlatformDelegateAlloy::OnExtensionHostDeleted() {
+  DCHECK(is_background_host_);
+  DCHECK(extension_host_);
+  extension_host_ = nullptr;
+}
diff --git a/src/libcef/browser/alloy/browser_platform_delegate_alloy.h b/src/libcef/browser/alloy/browser_platform_delegate_alloy.h
new file mode 100644
index 0000000..dbd9e5c
--- /dev/null
+++ b/src/libcef/browser/alloy/browser_platform_delegate_alloy.h
@@ -0,0 +1,121 @@
+// Copyright (c) 2015 The Chromium Embedded Framework Authors.
+// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_BROWSER_ALLOY_BROWSER_PLATFORM_DELEGATE_ALLOY_H_
+#define CEF_LIBCEF_BROWSER_ALLOY_BROWSER_PLATFORM_DELEGATE_ALLOY_H_
+
+#include "libcef/browser/alloy/dialogs/alloy_web_contents_dialog_helper.h"
+#include "libcef/browser/browser_platform_delegate.h"
+
+#include "base/memory/weak_ptr.h"
+#include "components/find_in_page/find_notification_details.h"
+#include "content/public/browser/web_contents.h"
+#include "ui/gfx/geometry/size.h"
+
+// Implementation of Alloy-based browser functionality.
+class CefBrowserPlatformDelegateAlloy : public CefBrowserPlatformDelegate {
+ public:
+  CefBrowserPlatformDelegateAlloy(const CefBrowserPlatformDelegateAlloy&) =
+      delete;
+  CefBrowserPlatformDelegateAlloy& operator=(
+      const CefBrowserPlatformDelegateAlloy&) = delete;
+
+  content::WebContents* CreateWebContents(CefBrowserCreateParams& create_params,
+                                          bool& own_web_contents) override;
+  void WebContentsCreated(content::WebContents* web_contents,
+                          bool owned) override;
+  void AddNewContents(content::WebContents* source,
+                      std::unique_ptr<content::WebContents> new_contents,
+                      const GURL& target_url,
+                      WindowOpenDisposition disposition,
+                      const blink::mojom::WindowFeatures& window_features,
+                      bool user_gesture,
+                      bool* was_blocked) override;
+  bool ShouldAllowRendererInitiatedCrossProcessNavigation(
+      bool is_main_frame_navigation) override;
+  void RenderViewReady() override;
+  void BrowserCreated(CefBrowserHostBase* browser) override;
+  void CreateExtensionHost(const extensions::Extension* extension,
+                           const GURL& url,
+                           extensions::mojom::ViewType host_type) override;
+  extensions::ExtensionHost* GetExtensionHost() const override;
+  void BrowserDestroyed(CefBrowserHostBase* browser) override;
+  web_modal::WebContentsModalDialogHost* GetWebContentsModalDialogHost()
+      const override;
+  void SendCaptureLostEvent() override;
+#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC))
+  void NotifyMoveOrResizeStarted() override;
+#endif
+  bool PreHandleGestureEvent(content::WebContents* source,
+                             const blink::WebGestureEvent& event) override;
+  bool IsNeverComposited(content::WebContents* web_contents) override;
+  void SetAutoResizeEnabled(bool enabled,
+                            const CefSize& min_size,
+                            const CefSize& max_size) override;
+  void SetAccessibilityState(cef_state_t accessibility_state) override;
+  bool IsPrintPreviewSupported() const override;
+  void Find(const CefString& searchText,
+            bool forward,
+            bool matchCase,
+            bool findNext) override;
+  void StopFinding(bool clearSelection) override;
+
+  // Called from AlloyBrowserHostImpl::FindReply().
+  bool HandleFindReply(int request_id,
+                       int number_of_matches,
+                       const gfx::Rect& selection_rect,
+                       int active_match_ordinal,
+                       bool final_update);
+
+  const find_in_page::FindNotificationDetails& last_search_result() const {
+    return last_search_result_;
+  }
+
+ protected:
+  CefBrowserPlatformDelegateAlloy();
+
+  base::RepeatingClosure GetBoundsChangedCallback();
+
+  // Called from BrowserPlatformDelegateNative::set_windowless_handler().
+  void set_as_secondary() { primary_ = false; }
+
+ private:
+  void SetOwnedWebContents(content::WebContents* owned_contents);
+
+  void DestroyExtensionHost();
+  void OnExtensionHostDeleted();
+
+  void ConfigureAutoResize();
+
+  // Non-nullptr if this object owns the WebContents. Will be nullptr for popup
+  // browsers between the calls to WebContentsCreated() and AddNewContents(),
+  // and may never be set if the parent browser is destroyed during popup
+  // creation.
+  std::unique_ptr<content::WebContents> owned_web_contents_;
+
+  // Used for the print preview dialog.
+  std::unique_ptr<AlloyWebContentsDialogHelper> web_contents_dialog_helper_;
+
+  // The last find result. This object contains details about the number of
+  // matches, the find selection rectangle, etc.
+  find_in_page::FindNotificationDetails last_search_result_;
+
+  // Used when the browser is hosting an extension.
+  extensions::ExtensionHost* extension_host_ = nullptr;
+  bool is_background_host_ = false;
+
+  // Used with auto-resize.
+  bool auto_resize_enabled_ = false;
+  gfx::Size auto_resize_min_;
+  gfx::Size auto_resize_max_;
+
+  // True if this is the primary platform delegate, in which case it will
+  // register WebContents delegate/observers.
+  bool primary_ = true;
+
+  base::WeakPtrFactory<CefBrowserPlatformDelegateAlloy> weak_ptr_factory_;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_ALLOY_BROWSER_PLATFORM_DELEGATE_ALLOY_H_
diff --git a/src/libcef/browser/alloy/chrome_browser_process_alloy.cc b/src/libcef/browser/alloy/chrome_browser_process_alloy.cc
new file mode 100644
index 0000000..0d2288e
--- /dev/null
+++ b/src/libcef/browser/alloy/chrome_browser_process_alloy.cc
@@ -0,0 +1,428 @@
+// Copyright (c) 2013 The Chromium Embedded Framework Authors.
+// Portions (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/browser/alloy/chrome_browser_process_alloy.h"
+
+#include "libcef/browser/alloy/chrome_profile_manager_alloy.h"
+#include "libcef/browser/browser_context.h"
+#include "libcef/browser/context.h"
+#include "libcef/browser/extensions/extensions_browser_client.h"
+#include "libcef/browser/prefs/browser_prefs.h"
+#include "libcef/browser/thread_util.h"
+#include "libcef/common/cef_switches.h"
+#include "libcef/common/extensions/extensions_client.h"
+#include "libcef/common/extensions/extensions_util.h"
+
+#include "base/command_line.h"
+#include "base/path_service.h"
+#include "chrome/browser/component_updater/chrome_component_updater_configurator.h"
+#include "chrome/browser/net/system_network_context_manager.h"
+#include "chrome/browser/permissions/chrome_permissions_client.h"
+#include "chrome/browser/policy/chrome_browser_policy_connector.h"
+#include "chrome/browser/printing/background_printing_manager.h"
+#include "chrome/browser/printing/print_job_manager.h"
+#include "chrome/browser/printing/print_preview_dialog_controller.h"
+#include "chrome/browser/ui/prefs/pref_watcher.h"
+#include "chrome/common/chrome_paths.h"
+#include "components/component_updater/component_updater_service.h"
+#include "components/component_updater/timer_update_scheduler.h"
+#include "components/net_log/chrome_net_log.h"
+#include "components/prefs/pref_service.h"
+#include "content/browser/startup_helper.h"
+#include "content/public/browser/network_service_instance.h"
+#include "content/public/common/content_switches.h"
+#include "net/log/net_log_capture_mode.h"
+#include "services/network/public/cpp/network_switches.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+ChromeBrowserProcessAlloy::ChromeBrowserProcessAlloy()
+    : initialized_(false),
+      context_initialized_(false),
+      shutdown_(false),
+      locale_("en-US") {}
+
+ChromeBrowserProcessAlloy::~ChromeBrowserProcessAlloy() {
+  DCHECK((!initialized_ && !context_initialized_) || shutdown_);
+
+  if (extensions::ExtensionsEnabled()) {
+    extensions::ExtensionsBrowserClient::Set(nullptr);
+    extensions_browser_client_.reset();
+  }
+}
+
+void ChromeBrowserProcessAlloy::Initialize() {
+  DCHECK(!initialized_);
+  DCHECK(!context_initialized_);
+  DCHECK(!shutdown_);
+  DCHECK(!field_trial_list_);
+
+  // Initialize this early before any code tries to check feature flags.
+  field_trial_list_ = content::SetUpFieldTrialsAndFeatureList();
+
+  if (extensions::ExtensionsEnabled()) {
+    // Initialize extension global objects before creating the global
+    // BrowserContext.
+    extensions_client_.reset(new extensions::CefExtensionsClient());
+    extensions::ExtensionsClient::Set(extensions_client_.get());
+    extensions_browser_client_.reset(
+        new extensions::CefExtensionsBrowserClient);
+    extensions::ExtensionsBrowserClient::Set(extensions_browser_client_.get());
+  }
+
+  // Make sure permissions client has been set.
+  ChromePermissionsClient::GetInstance();
+
+  initialized_ = true;
+}
+
+void ChromeBrowserProcessAlloy::OnContextInitialized() {
+  CEF_REQUIRE_UIT();
+  DCHECK(initialized_);
+  DCHECK(!context_initialized_);
+  DCHECK(!shutdown_);
+
+  // Must be created after the NotificationService.
+  print_job_manager_.reset(new printing::PrintJobManager());
+  profile_manager_.reset(new ChromeProfileManagerAlloy());
+  event_router_forwarder_ = new extensions::EventRouterForwarder();
+  context_initialized_ = true;
+}
+
+void ChromeBrowserProcessAlloy::CleanupOnUIThread() {
+  CEF_REQUIRE_UIT();
+  DCHECK(initialized_);
+  DCHECK(context_initialized_);
+  DCHECK(!shutdown_);
+
+  // Wait for the pending print jobs to finish. Don't do this later, since
+  // this might cause a nested message loop to run, and we don't want pending
+  // tasks to run once teardown has started.
+  print_job_manager_->Shutdown();
+  print_job_manager_.reset(nullptr);
+  print_preview_dialog_controller_ = nullptr;
+
+  profile_manager_.reset();
+  event_router_forwarder_ = nullptr;
+
+  if (SystemNetworkContextManager::GetInstance()) {
+    SystemNetworkContextManager::DeleteInstance();
+  }
+
+  // Release any references held by objects associated with a Profile. The
+  // Profile will be deleted later.
+  for (const auto& browser_context : CefBrowserContext::GetAll()) {
+    // Release any references to |local_state_|.
+    auto profile = browser_context->AsProfile();
+    PrefWatcher* pref_watcher = PrefWatcher::Get(profile);
+    if (pref_watcher) {
+      pref_watcher->Shutdown();
+    }
+
+    // Unregister observers for |background_printing_manager_|.
+    if (background_printing_manager_) {
+      background_printing_manager_->DeletePreviewContentsForBrowserContext(
+          profile);
+    }
+  }
+
+  local_state_.reset();
+  browser_policy_connector_.reset();
+  background_printing_manager_.reset();
+  field_trial_list_.reset();
+  component_updater_.reset();
+
+  shutdown_ = true;
+}
+
+void ChromeBrowserProcessAlloy::EndSession() {
+  DCHECK(false);
+}
+
+void ChromeBrowserProcessAlloy::FlushLocalStateAndReply(
+    base::OnceClosure reply) {
+  DCHECK(false);
+}
+
+metrics_services_manager::MetricsServicesManager*
+ChromeBrowserProcessAlloy::GetMetricsServicesManager() {
+  DCHECK(false);
+  return nullptr;
+}
+
+metrics::MetricsService* ChromeBrowserProcessAlloy::metrics_service() {
+  DCHECK(false);
+  return nullptr;
+}
+
+SystemNetworkContextManager*
+ChromeBrowserProcessAlloy::system_network_context_manager() {
+  DCHECK(SystemNetworkContextManager::GetInstance());
+  return SystemNetworkContextManager::GetInstance();
+}
+
+network::NetworkQualityTracker*
+ChromeBrowserProcessAlloy::network_quality_tracker() {
+  DCHECK(false);
+  return nullptr;
+}
+
+embedder_support::OriginTrialsSettingsStorage*
+ChromeBrowserProcessAlloy::GetOriginTrialsSettingsStorage() {
+  DCHECK(false);
+  return nullptr;
+}
+
+ProfileManager* ChromeBrowserProcessAlloy::profile_manager() {
+  DCHECK(context_initialized_);
+  return profile_manager_.get();
+}
+
+PrefService* ChromeBrowserProcessAlloy::local_state() {
+  DCHECK(initialized_);
+  if (!local_state_) {
+    base::FilePath user_data_path;
+    base::PathService::Get(chrome::DIR_USER_DATA, &user_data_path);
+    DCHECK(!user_data_path.empty());
+
+    // Used for very early NetworkService initialization.
+    // Always persist preferences for this PrefService if possible because it
+    // contains the cookie encryption key on Windows.
+    local_state_ =
+        browser_prefs::CreatePrefService(nullptr /* profile */, user_data_path,
+                                         true /* persist_user_preferences */);
+  }
+  return local_state_.get();
+}
+
+scoped_refptr<network::SharedURLLoaderFactory>
+ChromeBrowserProcessAlloy::shared_url_loader_factory() {
+  DCHECK(false);
+  return nullptr;
+}
+
+variations::VariationsService* ChromeBrowserProcessAlloy::variations_service() {
+  DCHECK(false);
+  return nullptr;
+}
+
+BrowserProcessPlatformPart* ChromeBrowserProcessAlloy::platform_part() {
+  DCHECK(false);
+  return nullptr;
+}
+
+extensions::EventRouterForwarder*
+ChromeBrowserProcessAlloy::extension_event_router_forwarder() {
+  DCHECK(context_initialized_);
+  return event_router_forwarder_.get();
+}
+
+NotificationUIManager* ChromeBrowserProcessAlloy::notification_ui_manager() {
+  DCHECK(false);
+  return nullptr;
+}
+
+NotificationPlatformBridge*
+ChromeBrowserProcessAlloy::notification_platform_bridge() {
+  DCHECK(false);
+  return nullptr;
+}
+
+policy::ChromeBrowserPolicyConnector*
+ChromeBrowserProcessAlloy::browser_policy_connector() {
+  if (!browser_policy_connector_) {
+    browser_policy_connector_ =
+        std::make_unique<policy::ChromeBrowserPolicyConnector>();
+  }
+  return browser_policy_connector_.get();
+}
+
+policy::PolicyService* ChromeBrowserProcessAlloy::policy_service() {
+  return browser_policy_connector()->GetPolicyService();
+}
+
+IconManager* ChromeBrowserProcessAlloy::icon_manager() {
+  DCHECK(false);
+  return nullptr;
+}
+
+GpuModeManager* ChromeBrowserProcessAlloy::gpu_mode_manager() {
+  DCHECK(false);
+  return nullptr;
+}
+
+void ChromeBrowserProcessAlloy::CreateDevToolsProtocolHandler() {
+  DCHECK(false);
+}
+
+void ChromeBrowserProcessAlloy::CreateDevToolsAutoOpener() {
+  DCHECK(false);
+}
+
+bool ChromeBrowserProcessAlloy::IsShuttingDown() {
+  DCHECK(false);
+  return false;
+}
+
+printing::PrintJobManager* ChromeBrowserProcessAlloy::print_job_manager() {
+  DCHECK(context_initialized_);
+  return print_job_manager_.get();
+}
+
+printing::PrintPreviewDialogController*
+ChromeBrowserProcessAlloy::print_preview_dialog_controller() {
+  if (!print_preview_dialog_controller_.get()) {
+    print_preview_dialog_controller_ =
+        new printing::PrintPreviewDialogController();
+  }
+  return print_preview_dialog_controller_.get();
+}
+
+printing::BackgroundPrintingManager*
+ChromeBrowserProcessAlloy::background_printing_manager() {
+  if (!background_printing_manager_.get()) {
+    background_printing_manager_.reset(
+        new printing::BackgroundPrintingManager());
+  }
+  return background_printing_manager_.get();
+}
+
+IntranetRedirectDetector*
+ChromeBrowserProcessAlloy::intranet_redirect_detector() {
+  DCHECK(false);
+  return nullptr;
+}
+
+const std::string& ChromeBrowserProcessAlloy::GetApplicationLocale() {
+  DCHECK(!locale_.empty());
+  return locale_;
+}
+
+void ChromeBrowserProcessAlloy::SetApplicationLocale(
+    const std::string& locale) {
+  locale_ = locale;
+}
+
+DownloadStatusUpdater* ChromeBrowserProcessAlloy::download_status_updater() {
+  DCHECK(false);
+  return nullptr;
+}
+
+DownloadRequestLimiter* ChromeBrowserProcessAlloy::download_request_limiter() {
+  DCHECK(false);
+  return nullptr;
+}
+
+#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
+BackgroundModeManager* ChromeBrowserProcessAlloy::background_mode_manager() {
+  DCHECK(false);
+  return nullptr;
+}
+
+void ChromeBrowserProcessAlloy::set_background_mode_manager_for_test(
+    std::unique_ptr<BackgroundModeManager> manager) {
+  DCHECK(false);
+}
+#endif
+
+StatusTray* ChromeBrowserProcessAlloy::status_tray() {
+  DCHECK(false);
+  return nullptr;
+}
+
+safe_browsing::SafeBrowsingService*
+ChromeBrowserProcessAlloy::safe_browsing_service() {
+  return nullptr;
+}
+
+subresource_filter::RulesetService*
+ChromeBrowserProcessAlloy::subresource_filter_ruleset_service() {
+  DCHECK(false);
+  return nullptr;
+}
+
+StartupData* ChromeBrowserProcessAlloy::startup_data() {
+  DCHECK(false);
+  return nullptr;
+}
+
+#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
+void ChromeBrowserProcessAlloy::StartAutoupdateTimer() {}
+#endif
+
+component_updater::ComponentUpdateService*
+ChromeBrowserProcessAlloy::component_updater() {
+  if (component_updater_) {
+    return component_updater_.get();
+  }
+
+  if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
+    return nullptr;
+  }
+
+  std::unique_ptr<component_updater::UpdateScheduler> scheduler =
+      std::make_unique<component_updater::TimerUpdateScheduler>();
+
+  component_updater_ = component_updater::ComponentUpdateServiceFactory(
+      component_updater::MakeChromeComponentUpdaterConfigurator(
+          base::CommandLine::ForCurrentProcess(),
+          g_browser_process->local_state()),
+      std::move(scheduler), /*brand=*/std::string());
+
+  return component_updater_.get();
+}
+
+MediaFileSystemRegistry*
+ChromeBrowserProcessAlloy::media_file_system_registry() {
+  DCHECK(false);
+  return nullptr;
+}
+
+WebRtcLogUploader* ChromeBrowserProcessAlloy::webrtc_log_uploader() {
+  DCHECK(false);
+  return nullptr;
+}
+
+network_time::NetworkTimeTracker*
+ChromeBrowserProcessAlloy::network_time_tracker() {
+  DCHECK(false);
+  return nullptr;
+}
+
+gcm::GCMDriver* ChromeBrowserProcessAlloy::gcm_driver() {
+  DCHECK(false);
+  return nullptr;
+}
+
+resource_coordinator::TabManager* ChromeBrowserProcessAlloy::GetTabManager() {
+  DCHECK(false);
+  return nullptr;
+}
+
+resource_coordinator::ResourceCoordinatorParts*
+ChromeBrowserProcessAlloy::resource_coordinator_parts() {
+  DCHECK(false);
+  return nullptr;
+}
+
+BuildState* ChromeBrowserProcessAlloy::GetBuildState() {
+  DCHECK(false);
+  return nullptr;
+}
+
+SerialPolicyAllowedPorts*
+ChromeBrowserProcessAlloy::serial_policy_allowed_ports() {
+  DCHECK(false);
+  return nullptr;
+}
+
+HidSystemTrayIcon* ChromeBrowserProcessAlloy::hid_system_tray_icon() {
+  DCHECK(false);
+  return nullptr;
+}
+
+UsbSystemTrayIcon* ChromeBrowserProcessAlloy::usb_system_tray_icon() {
+  DCHECK(false);
+  return nullptr;
+}
diff --git a/src/libcef/browser/chrome_browser_process_stub.h b/src/libcef/browser/alloy/chrome_browser_process_alloy.h
similarity index 73%
rename from src/libcef/browser/chrome_browser_process_stub.h
rename to src/libcef/browser/alloy/chrome_browser_process_alloy.h
index 4a322ac..2ae131d 100644
--- a/src/libcef/browser/chrome_browser_process_stub.h
+++ b/src/libcef/browser/alloy/chrome_browser_process_alloy.h
@@ -6,37 +6,47 @@
 // This file provides a stub implementation of Chrome's BrowserProcess object
 // for use as an interop layer between CEF and files that live in chrome/.
 
-#ifndef CEF_LIBCEF_BROWSER_CHROME_BROWSER_PROCESS_STUB_H_
-#define CEF_LIBCEF_BROWSER_CHROME_BROWSER_PROCESS_STUB_H_
+#ifndef CEF_LIBCEF_BROWSER_ALLOY_CHROME_BROWSER_PROCESS_ALLOY_H_
+#define CEF_LIBCEF_BROWSER_ALLOY_CHROME_BROWSER_PROCESS_ALLOY_H_
 
 #include <memory>
 #include <string>
 
-#include "base/compiler_specific.h"
 #include "base/metrics/field_trial.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/event_router_forwarder.h"
 #include "media/media_buildflags.h"
 
-class ChromeProfileManagerStub;
+namespace extensions {
+class ExtensionsBrowserClient;
+class ExtensionsClient;
+}  // namespace extensions
+
+class ChromeProfileManagerAlloy;
 
 class BackgroundModeManager {
  public:
   BackgroundModeManager();
-  virtual ~BackgroundModeManager();
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(BackgroundModeManager);
+  BackgroundModeManager(const BackgroundModeManager&) = delete;
+  BackgroundModeManager& operator=(const BackgroundModeManager&) = delete;
+
+  virtual ~BackgroundModeManager();
 };
 
-class ChromeBrowserProcessStub : public BrowserProcess {
+class ChromeBrowserProcessAlloy : public BrowserProcess {
  public:
-  ChromeBrowserProcessStub();
-  ~ChromeBrowserProcessStub() override;
+  ChromeBrowserProcessAlloy();
+
+  ChromeBrowserProcessAlloy(const ChromeBrowserProcessAlloy&) = delete;
+  ChromeBrowserProcessAlloy& operator=(const ChromeBrowserProcessAlloy&) =
+      delete;
+
+  ~ChromeBrowserProcessAlloy() override;
 
   void Initialize();
   void OnContextInitialized();
-  void Shutdown();
+  void CleanupOnUIThread();
 
   // BrowserProcess implementation.
   void EndSession() override;
@@ -44,10 +54,10 @@
   metrics_services_manager::MetricsServicesManager* GetMetricsServicesManager()
       override;
   metrics::MetricsService* metrics_service() override;
-  rappor::RapporServiceImpl* rappor_service() override;
   SystemNetworkContextManager* system_network_context_manager() override;
   network::NetworkQualityTracker* network_quality_tracker() override;
-  WatchDogThread* watchdog_thread() override;
+  embedder_support::OriginTrialsSettingsStorage*
+  GetOriginTrialsSettingsStorage() override;
   ProfileManager* profile_manager() override;
   PrefService* local_state() override;
   scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory()
@@ -73,20 +83,18 @@
   void SetApplicationLocale(const std::string& locale) override;
   DownloadStatusUpdater* download_status_updater() override;
   DownloadRequestLimiter* download_request_limiter() override;
+#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
   BackgroundModeManager* background_mode_manager() override;
   void set_background_mode_manager_for_test(
       std::unique_ptr<BackgroundModeManager> manager) override;
+#endif
   StatusTray* status_tray() override;
   safe_browsing::SafeBrowsingService* safe_browsing_service() override;
-  safe_browsing::ClientSideDetectionService* safe_browsing_detection_service()
-      override;
   subresource_filter::RulesetService* subresource_filter_ruleset_service()
       override;
-  optimization_guide::OptimizationGuideService* optimization_guide_service()
-      override;
   StartupData* startup_data() override;
 
-#if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
   void StartAutoupdateTimer() override;
 #endif
 
@@ -99,27 +107,35 @@
   resource_coordinator::ResourceCoordinatorParts* resource_coordinator_parts()
       override;
   BuildState* GetBuildState() override;
+  SerialPolicyAllowedPorts* serial_policy_allowed_ports() override;
+  HidSystemTrayIcon* hid_system_tray_icon() override;
+  UsbSystemTrayIcon* usb_system_tray_icon() override;
 
  private:
   bool initialized_;
   bool context_initialized_;
   bool shutdown_;
 
+  std::unique_ptr<extensions::ExtensionsClient> extensions_client_;
+  std::unique_ptr<extensions::ExtensionsBrowserClient>
+      extensions_browser_client_;
+
   std::string locale_;
   std::unique_ptr<printing::PrintJobManager> print_job_manager_;
-  std::unique_ptr<ChromeProfileManagerStub> profile_manager_;
+  std::unique_ptr<ChromeProfileManagerAlloy> profile_manager_;
   scoped_refptr<extensions::EventRouterForwarder> event_router_forwarder_;
   scoped_refptr<printing::PrintPreviewDialogController>
       print_preview_dialog_controller_;
   std::unique_ptr<printing::BackgroundPrintingManager>
       background_printing_manager_;
   std::unique_ptr<PrefService> local_state_;
+
   // Must be destroyed after |local_state_|.
   std::unique_ptr<policy::ChromeBrowserPolicyConnector>
       browser_policy_connector_;
   std::unique_ptr<base::FieldTrialList> field_trial_list_;
 
-  DISALLOW_COPY_AND_ASSIGN(ChromeBrowserProcessStub);
+  std::unique_ptr<component_updater::ComponentUpdateService> component_updater_;
 };
 
-#endif  // CEF_LIBCEF_BROWSER_CHROME_BROWSER_PROCESS_STUB_H_
+#endif  // CEF_LIBCEF_BROWSER_ALLOY_CHROME_BROWSER_PROCESS_ALLOY_H_
diff --git a/src/libcef/browser/alloy/chrome_profile_alloy.cc b/src/libcef/browser/alloy/chrome_profile_alloy.cc
new file mode 100644
index 0000000..5615c56
--- /dev/null
+++ b/src/libcef/browser/alloy/chrome_profile_alloy.cc
@@ -0,0 +1,168 @@
+// Copyright (c) 2015 The Chromium Embedded Framework Authors.
+// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/browser/alloy/chrome_profile_alloy.h"
+
+#include "base/no_destructor.h"
+#include "components/profile_metrics/browser_profile_type.h"
+#include "components/variations/variations_client.h"
+#include "components/variations/variations_ids_provider.h"
+#include "net/url_request/url_request_context.h"
+
+namespace {
+
+class CefVariationsClient : public variations::VariationsClient {
+ public:
+  explicit CefVariationsClient(content::BrowserContext* browser_context)
+      : browser_context_(browser_context) {}
+
+  ~CefVariationsClient() override = default;
+
+  bool IsOffTheRecord() const override {
+    return browser_context_->IsOffTheRecord();
+  }
+
+  variations::mojom::VariationsHeadersPtr GetVariationsHeaders()
+      const override {
+    return variations::VariationsIdsProvider::GetInstance()
+        ->GetClientDataHeaders(false /* is_signed_in */);
+  }
+
+ private:
+  content::BrowserContext* browser_context_;
+};
+
+}  // namespace
+
+ChromeProfileAlloy::ChromeProfileAlloy() {
+  profile_metrics::SetBrowserProfileType(
+      this, profile_metrics::BrowserProfileType::kRegular);
+}
+
+ChromeProfileAlloy::~ChromeProfileAlloy() {}
+
+bool ChromeProfileAlloy::IsOffTheRecord() {
+  return false;
+}
+
+bool ChromeProfileAlloy::IsOffTheRecord() const {
+  // Alloy contexts are never flagged as off-the-record. It causes problems
+  // for the extension system.
+  return false;
+}
+
+const Profile::OTRProfileID& ChromeProfileAlloy::GetOTRProfileID() const {
+  DCHECK(false);
+  static base::NoDestructor<Profile::OTRProfileID> otr_profile_id(
+      Profile::OTRProfileID::PrimaryID());
+  return *otr_profile_id;
+}
+
+variations::VariationsClient* ChromeProfileAlloy::GetVariationsClient() {
+  if (!variations_client_) {
+    variations_client_ = std::make_unique<CefVariationsClient>(this);
+  }
+  return variations_client_.get();
+}
+
+scoped_refptr<base::SequencedTaskRunner> ChromeProfileAlloy::GetIOTaskRunner() {
+  DCHECK(false);
+  return scoped_refptr<base::SequencedTaskRunner>();
+}
+
+std::string ChromeProfileAlloy::GetProfileUserName() const {
+  DCHECK(false);
+  return std::string();
+}
+
+Profile* ChromeProfileAlloy::GetOffTheRecordProfile(
+    const Profile::OTRProfileID& otr_profile_id,
+    bool create_if_needed) {
+  DCHECK(false);
+  return nullptr;
+}
+
+std::vector<Profile*> ChromeProfileAlloy::GetAllOffTheRecordProfiles() {
+  return {};
+}
+
+void ChromeProfileAlloy::DestroyOffTheRecordProfile(Profile* otr_profile) {
+  DCHECK(false);
+}
+
+bool ChromeProfileAlloy::HasOffTheRecordProfile(
+    const Profile::OTRProfileID& otr_profile_id) {
+  return false;
+}
+
+bool ChromeProfileAlloy::HasAnyOffTheRecordProfile() {
+  return false;
+}
+
+Profile* ChromeProfileAlloy::GetOriginalProfile() {
+  return this;
+}
+
+const Profile* ChromeProfileAlloy::GetOriginalProfile() const {
+  return this;
+}
+
+bool ChromeProfileAlloy::IsChild() const {
+  return false;
+}
+
+ExtensionSpecialStoragePolicy*
+ChromeProfileAlloy::GetExtensionSpecialStoragePolicy() {
+  DCHECK(false);
+  return nullptr;
+}
+
+bool ChromeProfileAlloy::IsSameOrParent(Profile* profile) {
+  DCHECK(false);
+  return false;
+}
+
+base::Time ChromeProfileAlloy::GetStartTime() const {
+  DCHECK(false);
+  return base::Time();
+}
+
+base::FilePath ChromeProfileAlloy::last_selected_directory() {
+  return last_selected_directory_;
+}
+
+void ChromeProfileAlloy::set_last_selected_directory(
+    const base::FilePath& path) {
+  last_selected_directory_ = path;
+}
+
+GURL ChromeProfileAlloy::GetHomePage() {
+  DCHECK(false);
+  return GURL();
+}
+
+bool ChromeProfileAlloy::WasCreatedByVersionOrLater(
+    const std::string& version) {
+  DCHECK(false);
+  return false;
+}
+
+base::Time ChromeProfileAlloy::GetCreationTime() const {
+  DCHECK(false);
+  return base::Time();
+}
+
+void ChromeProfileAlloy::SetCreationTimeForTesting(base::Time creation_time) {
+  DCHECK(false);
+}
+
+void ChromeProfileAlloy::RecordPrimaryMainFrameNavigation() {
+  DCHECK(false);
+}
+
+bool ChromeProfileAlloy::IsSignedIn() {
+  DCHECK(false);
+  return false;
+}
diff --git a/src/libcef/browser/alloy/chrome_profile_alloy.h b/src/libcef/browser/alloy/chrome_profile_alloy.h
new file mode 100644
index 0000000..95c6ca9
--- /dev/null
+++ b/src/libcef/browser/alloy/chrome_profile_alloy.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2015 The Chromium Embedded Framework Authors.
+// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This class gathers state related to a single user profile.
+
+#ifndef CEF_LIBCEF_BROWSER_ALLOY_CHROME_PROFILE_ALLOY_H_
+#define CEF_LIBCEF_BROWSER_ALLOY_CHROME_PROFILE_ALLOY_H_
+
+#include "base/files/file_path.h"
+#include "chrome/browser/profiles/profile.h"
+
+// This file provides a stub implementation of Chrome's Profile object for use
+// as an interop layer between CEF and files that live in chrome/.
+
+class ChromeProfileAlloy : public Profile {
+ public:
+  ChromeProfileAlloy();
+
+  ChromeProfileAlloy(const ChromeProfileAlloy&) = delete;
+  ChromeProfileAlloy& operator=(const ChromeProfileAlloy&) = delete;
+
+  ~ChromeProfileAlloy() override;
+
+ protected:
+  // Profile methods.
+  bool IsOffTheRecord() override;
+  bool IsOffTheRecord() const override;
+  const OTRProfileID& GetOTRProfileID() const override;
+  variations::VariationsClient* GetVariationsClient() override;
+  scoped_refptr<base::SequencedTaskRunner> GetIOTaskRunner() override;
+  std::string GetProfileUserName() const override;
+  Profile* GetOffTheRecordProfile(const Profile::OTRProfileID& otr_profile_id,
+                                  bool create_if_needed) override;
+  std::vector<Profile*> GetAllOffTheRecordProfiles() override;
+  void DestroyOffTheRecordProfile(Profile* otr_profile) override;
+  bool HasOffTheRecordProfile(
+      const Profile::OTRProfileID& otr_profile_id) override;
+  bool HasAnyOffTheRecordProfile() override;
+  Profile* GetOriginalProfile() override;
+  const Profile* GetOriginalProfile() const override;
+  bool IsChild() const override;
+  ExtensionSpecialStoragePolicy* GetExtensionSpecialStoragePolicy() override;
+  bool IsSameOrParent(Profile* profile) override;
+  base::Time GetStartTime() const override;
+  base::FilePath last_selected_directory() override;
+  void set_last_selected_directory(const base::FilePath& path) override;
+  GURL GetHomePage() override;
+  bool WasCreatedByVersionOrLater(const std::string& version) override;
+  base::Time GetCreationTime() const override;
+  void SetCreationTimeForTesting(base::Time creation_time) override;
+  void RecordPrimaryMainFrameNavigation() override;
+  bool IsSignedIn() override;
+
+ private:
+  std::unique_ptr<variations::VariationsClient> variations_client_;
+  base::FilePath last_selected_directory_;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_ALLOY_CHROME_PROFILE_ALLOY_H_
diff --git a/src/libcef/browser/chrome_profile_manager_stub.cc b/src/libcef/browser/alloy/chrome_profile_manager_alloy.cc
similarity index 62%
rename from src/libcef/browser/chrome_profile_manager_stub.cc
rename to src/libcef/browser/alloy/chrome_profile_manager_alloy.cc
index ba3e8ca..8a577f5 100644
--- a/src/libcef/browser/chrome_profile_manager_stub.cc
+++ b/src/libcef/browser/alloy/chrome_profile_manager_alloy.cc
@@ -3,10 +3,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "libcef/browser/chrome_profile_manager_stub.h"
+#include "libcef/browser/alloy/chrome_profile_manager_alloy.h"
 
 #include "libcef/browser/browser_context.h"
-#include "libcef/browser/content_browser_client.h"
+#include "libcef/browser/request_context_impl.h"
+#include "libcef/common/app_manager.h"
 
 namespace {
 
@@ -21,21 +22,22 @@
 // Return the main context for now since we don't currently have a good way to
 // determine that.
 CefBrowserContext* GetActiveBrowserContext() {
-  return static_cast<CefBrowserContext*>(
-      CefContentBrowserClient::Get()->request_context()->GetBrowserContext());
+  auto request_context = static_cast<CefRequestContextImpl*>(
+      CefAppManager::Get()->GetGlobalRequestContext().get());
+  return request_context->GetBrowserContext();
 }
 
 }  // namespace
 
-ChromeProfileManagerStub::ChromeProfileManagerStub()
+ChromeProfileManagerAlloy::ChromeProfileManagerAlloy()
     : ProfileManager(base::FilePath()) {}
 
-ChromeProfileManagerStub::~ChromeProfileManagerStub() {}
+ChromeProfileManagerAlloy::~ChromeProfileManagerAlloy() {}
 
-Profile* ChromeProfileManagerStub::GetProfile(
+Profile* ChromeProfileManagerAlloy::GetProfile(
     const base::FilePath& profile_dir) {
   CefBrowserContext* browser_context =
-      CefBrowserContext::GetForCachePath(profile_dir);
+      CefBrowserContext::FromCachePath(profile_dir);
   if (!browser_context) {
     // ProfileManager makes assumptions about profile directory paths that do
     // not match CEF usage. For example, the default Chrome profile name is
@@ -45,19 +47,13 @@
     // asking for.
     browser_context = GetActiveBrowserContext();
   }
-  return browser_context;
+  return browser_context->AsProfile();
 }
 
-bool ChromeProfileManagerStub::IsValidProfile(const void* profile) {
-  if (!profile)
+bool ChromeProfileManagerAlloy::IsValidProfile(const void* profile) {
+  if (!profile) {
     return false;
-  return !!CefBrowserContext::GetForContext(
-      reinterpret_cast<content::BrowserContext*>(const_cast<void*>(profile)));
-}
-
-Profile* ChromeProfileManagerStub::GetLastUsedProfile(
-    const base::FilePath& user_data_dir) {
-  // Override this method to avoid having to register prefs::kProfileLastUsed,
-  // usage of which doesn't make sense for CEF.
-  return GetActiveBrowserContext();
+  }
+  return !!CefBrowserContext::FromBrowserContext(
+      static_cast<const content::BrowserContext*>(profile));
 }
diff --git a/src/libcef/browser/alloy/chrome_profile_manager_alloy.h b/src/libcef/browser/alloy/chrome_profile_manager_alloy.h
new file mode 100644
index 0000000..5473d2e
--- /dev/null
+++ b/src/libcef/browser/alloy/chrome_profile_manager_alloy.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2016 The Chromium Embedded Framework Authors.
+// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file provides a stub implementation of Chrome's ProfileManager object
+// for use as an interop layer between CEF and files that live in chrome/.
+
+#ifndef CEF_LIBCEF_BROWSER_ALLOY_CHROME_PROFILE_MANAGER_ALLOY_H_
+#define CEF_LIBCEF_BROWSER_ALLOY_CHROME_PROFILE_MANAGER_ALLOY_H_
+
+#include "chrome/browser/profiles/profile_manager.h"
+
+class ChromeProfileManagerAlloy : public ProfileManager {
+ public:
+  ChromeProfileManagerAlloy();
+
+  ChromeProfileManagerAlloy(const ChromeProfileManagerAlloy&) = delete;
+  ChromeProfileManagerAlloy& operator=(const ChromeProfileManagerAlloy&) =
+      delete;
+
+  ~ChromeProfileManagerAlloy() override;
+
+  Profile* GetProfile(const base::FilePath& profile_dir) override;
+  bool IsValidProfile(const void* profile) override;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_ALLOY_CHROME_PROFILE_MANAGER_ALLOY_H_
diff --git a/src/libcef/browser/alloy/dialogs/alloy_constrained_window_views_client.cc b/src/libcef/browser/alloy/dialogs/alloy_constrained_window_views_client.cc
new file mode 100644
index 0000000..a45782c
--- /dev/null
+++ b/src/libcef/browser/alloy/dialogs/alloy_constrained_window_views_client.cc
@@ -0,0 +1,76 @@
+// Copyright 2022 The Chromium Embedded Framework Authors.
+// Portions copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/browser/alloy/dialogs/alloy_constrained_window_views_client.h"
+
+#include "libcef/browser/browser_host_base.h"
+
+#include "base/notreached.h"
+#include "components/web_modal/web_contents_modal_dialog_host.h"
+
+namespace {
+
+class AlloyConstrainedWindowViewsClient
+    : public constrained_window::ConstrainedWindowViewsClient {
+ public:
+  AlloyConstrainedWindowViewsClient() = default;
+
+  AlloyConstrainedWindowViewsClient(const AlloyConstrainedWindowViewsClient&) =
+      delete;
+  AlloyConstrainedWindowViewsClient& operator=(
+      const AlloyConstrainedWindowViewsClient&) = delete;
+
+ private:
+  // ConstrainedWindowViewsClient methods:
+  web_modal::ModalDialogHost* GetModalDialogHost(
+      gfx::NativeWindow parent) override {
+    if (auto browser = GetPreferredBrowser(parent)) {
+      return browser->platform_delegate()->GetWebContentsModalDialogHost();
+    }
+    DCHECK(false);
+    return nullptr;
+  }
+
+  gfx::NativeView GetDialogHostView(gfx::NativeWindow parent) override {
+    if (auto dialog_host = GetModalDialogHost(parent)) {
+      return dialog_host->GetHostView();
+    }
+    return gfx::NativeView();
+  }
+
+  static CefRefPtr<CefBrowserHostBase> GetPreferredBrowser(
+      gfx::NativeWindow parent) {
+    CefRefPtr<CefBrowserHostBase> browser;
+
+    // 1. Browser associated with the top-level native window (owning_window).
+    // This should be reliable with windowed browsers. However, |parent| will
+    // always be nullptr with windowless browsers.
+    if (parent) {
+      browser = CefBrowserHostBase::GetBrowserForTopLevelNativeWindow(parent);
+      if (!browser) {
+        LOG(WARNING) << "No browser associated with top-level native window";
+      }
+    }
+
+    // 2. Browser most likely to be focused. This may be somewhat iffy with
+    // windowless browsers as there is no guarantee that the client has only
+    // one browser focused at a time.
+    if (!browser) {
+      browser = CefBrowserHostBase::GetLikelyFocusedBrowser();
+      if (!browser) {
+        LOG(WARNING) << "No likely focused browser";
+      }
+    }
+
+    return browser;
+  }
+};
+
+}  // namespace
+
+std::unique_ptr<constrained_window::ConstrainedWindowViewsClient>
+CreateAlloyConstrainedWindowViewsClient() {
+  return std::make_unique<AlloyConstrainedWindowViewsClient>();
+}
diff --git a/src/libcef/browser/alloy/dialogs/alloy_constrained_window_views_client.h b/src/libcef/browser/alloy/dialogs/alloy_constrained_window_views_client.h
new file mode 100644
index 0000000..c33a38c
--- /dev/null
+++ b/src/libcef/browser/alloy/dialogs/alloy_constrained_window_views_client.h
@@ -0,0 +1,17 @@
+// Copyright 2022 The Chromium Embedded Framework Authors.
+// Portions copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_BROWSER_ALLOY_DIALOGS_ALLOY_CONSTRAINED_WINDOW_VIEWS_CLIENT_H_
+#define CEF_LIBCEF_BROWSER_ALLOY_DIALOGS_ALLOY_CONSTRAINED_WINDOW_VIEWS_CLIENT_H_
+
+#include <memory>
+
+#include "components/constrained_window/constrained_window_views_client.h"
+
+// Creates a ConstrainedWindowViewsClient for the Chrome environment.
+std::unique_ptr<constrained_window::ConstrainedWindowViewsClient>
+CreateAlloyConstrainedWindowViewsClient();
+
+#endif  // CEF_LIBCEF_BROWSER_ALLOY_DIALOGS_ALLOY_CONSTRAINED_WINDOW_VIEWS_CLIENT_H_
\ No newline at end of file
diff --git a/src/libcef/browser/alloy/dialogs/alloy_javascript_dialog_manager_delegate.cc b/src/libcef/browser/alloy/dialogs/alloy_javascript_dialog_manager_delegate.cc
new file mode 100644
index 0000000..bb7647b
--- /dev/null
+++ b/src/libcef/browser/alloy/dialogs/alloy_javascript_dialog_manager_delegate.cc
@@ -0,0 +1,58 @@
+// Copyright 2022 The Chromium Embedded Framework Authors.
+// Portions copyright 2020 The Chromium 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 "libcef/browser/alloy/dialogs/alloy_javascript_dialog_manager_delegate.h"
+
+#include "libcef/browser/browser_host_base.h"
+
+#include "base/logging.h"
+
+namespace {
+
+class AlloyJavaScriptTabModalDialogManagerDelegateDesktop
+    : public JavaScriptTabModalDialogManagerDelegateDesktop {
+ public:
+  explicit AlloyJavaScriptTabModalDialogManagerDelegateDesktop(
+      content::WebContents* web_contents)
+      : JavaScriptTabModalDialogManagerDelegateDesktop(web_contents),
+        web_contents_(web_contents) {}
+
+  AlloyJavaScriptTabModalDialogManagerDelegateDesktop(
+      const AlloyJavaScriptTabModalDialogManagerDelegateDesktop&) = delete;
+  AlloyJavaScriptTabModalDialogManagerDelegateDesktop& operator=(
+      const AlloyJavaScriptTabModalDialogManagerDelegateDesktop&) = delete;
+
+  // javascript_dialogs::TabModalDialogManagerDelegate methods:
+  void WillRunDialog() override {}
+
+  void DidCloseDialog() override {}
+
+  void SetTabNeedsAttention(bool attention) override {}
+
+  bool IsWebContentsForemost() override {
+    if (auto browser =
+            CefBrowserHostBase::GetBrowserForContents(web_contents_)) {
+      return browser->IsVisible();
+    }
+    return false;
+  }
+
+  bool IsApp() override { return false; }
+
+ private:
+  // The WebContents for the tab over which the dialog will be modal. This may
+  // be different from the WebContents that requested the dialog, such as with
+  // Chrome app <webview>s.
+  raw_ptr<content::WebContents> web_contents_;
+};
+
+}  // namespace
+
+std::unique_ptr<JavaScriptTabModalDialogManagerDelegateDesktop>
+CreateAlloyJavaScriptTabModalDialogManagerDelegateDesktop(
+    content::WebContents* web_contents) {
+  return std::make_unique<AlloyJavaScriptTabModalDialogManagerDelegateDesktop>(
+      web_contents);
+}
diff --git a/src/libcef/browser/alloy/dialogs/alloy_javascript_dialog_manager_delegate.h b/src/libcef/browser/alloy/dialogs/alloy_javascript_dialog_manager_delegate.h
new file mode 100644
index 0000000..4d3df0d
--- /dev/null
+++ b/src/libcef/browser/alloy/dialogs/alloy_javascript_dialog_manager_delegate.h
@@ -0,0 +1,18 @@
+// Copyright 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_ALLOY_DIALOGS_ALLOY_JAVASCRIPT_DIALOG_MANAGER_DELEGATE_H_
+#define CEF_LIBCEF_BROWSER_ALLOY_DIALOGS_ALLOY_JAVASCRIPT_DIALOG_MANAGER_DELEGATE_H_
+
+#include <memory>
+
+#include "chrome/browser/ui/javascript_dialogs/javascript_tab_modal_dialog_manager_delegate_desktop.h"
+
+// Creates a JavaScriptTabModalDialogManagerDelegateDesktop for the Chrome
+// environment.
+std::unique_ptr<JavaScriptTabModalDialogManagerDelegateDesktop>
+CreateAlloyJavaScriptTabModalDialogManagerDelegateDesktop(
+    content::WebContents* web_contents);
+
+#endif  // CEF_LIBCEF_BROWSER_ALLOY_DIALOGS_ALLOY_JAVASCRIPT_DIALOG_MANAGER_DELEGATE_H_
\ No newline at end of file
diff --git a/src/libcef/browser/alloy/dialogs/alloy_web_contents_dialog_helper.cc b/src/libcef/browser/alloy/dialogs/alloy_web_contents_dialog_helper.cc
new file mode 100644
index 0000000..8cf8b81
--- /dev/null
+++ b/src/libcef/browser/alloy/dialogs/alloy_web_contents_dialog_helper.cc
@@ -0,0 +1,99 @@
+// Copyright (c) 2019 The Chromium Embedded Framework 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 "libcef/browser/alloy/dialogs/alloy_web_contents_dialog_helper.h"
+
+#include "libcef/browser/browser_platform_delegate.h"
+
+#include "base/notreached.h"
+#include "chrome/browser/platform_util.h"
+#include "components/web_modal/web_contents_modal_dialog_manager.h"
+#include "ui/views/widget/widget.h"
+
+AlloyWebContentsDialogHelper::AlloyWebContentsDialogHelper(
+    content::WebContents* web_contents,
+    CefBrowserPlatformDelegate* browser_delegate)
+    : browser_delegate_(browser_delegate), weak_factory_(this) {
+  web_modal::WebContentsModalDialogManager::CreateForWebContents(web_contents);
+  web_modal::WebContentsModalDialogManager::FromWebContents(web_contents)
+      ->SetDelegate(this);
+}
+
+base::RepeatingClosure
+AlloyWebContentsDialogHelper::GetBoundsChangedCallback() {
+  return base::BindRepeating(&AlloyWebContentsDialogHelper::OnBoundsChanged,
+                             weak_factory_.GetWeakPtr());
+}
+
+bool AlloyWebContentsDialogHelper::IsWebContentsVisible(
+    content::WebContents* web_contents) {
+  if (browser_delegate_->IsWindowless()) {
+    return !browser_delegate_->IsHidden();
+  } else if (auto native_view = web_contents->GetNativeView()) {
+    return platform_util::IsVisible(native_view);
+  }
+  DCHECK(false);
+  return false;
+}
+
+web_modal::WebContentsModalDialogHost*
+AlloyWebContentsDialogHelper::GetWebContentsModalDialogHost() {
+  return this;
+}
+
+gfx::NativeView AlloyWebContentsDialogHelper::GetHostView() const {
+  // Windowless rendering uses GetAcceleratedWidget() instead.
+  if (browser_delegate_->IsWindowless()) {
+    return gfx::NativeView();
+  }
+
+  if (auto widget = browser_delegate_->GetWindowWidget()) {
+    return widget->GetNativeView();
+  }
+  DCHECK(false);
+  return gfx::NativeView();
+}
+
+gfx::AcceleratedWidget AlloyWebContentsDialogHelper::GetAcceleratedWidget()
+    const {
+#if defined(USE_AURA)
+  // Windowed rendering uses GetHostView() instead.
+  if (!browser_delegate_->IsWindowless()) {
+    return gfx::kNullAcceleratedWidget;
+  }
+
+  if (auto parent_widget = browser_delegate_->GetHostWindowHandle()) {
+    return parent_widget;
+  }
+#endif  // defined(USE_AURA)
+  DCHECK(false);
+  return gfx::kNullAcceleratedWidget;
+}
+
+gfx::Point AlloyWebContentsDialogHelper::GetDialogPosition(
+    const gfx::Size& size) {
+  return browser_delegate_->GetDialogPosition(size);
+}
+
+gfx::Size AlloyWebContentsDialogHelper::GetMaximumDialogSize() {
+  return browser_delegate_->GetMaximumDialogSize();
+}
+
+void AlloyWebContentsDialogHelper::AddObserver(
+    web_modal::ModalDialogHostObserver* observer) {
+  if (observer && !observer_list_.HasObserver(observer)) {
+    observer_list_.AddObserver(observer);
+  }
+}
+
+void AlloyWebContentsDialogHelper::RemoveObserver(
+    web_modal::ModalDialogHostObserver* observer) {
+  observer_list_.RemoveObserver(observer);
+}
+
+void AlloyWebContentsDialogHelper::OnBoundsChanged() {
+  for (auto& observer : observer_list_) {
+    observer.OnPositionRequiresUpdate();
+  }
+}
diff --git a/src/libcef/browser/web_contents_dialog_helper.h b/src/libcef/browser/alloy/dialogs/alloy_web_contents_dialog_helper.h
similarity index 71%
rename from src/libcef/browser/web_contents_dialog_helper.h
rename to src/libcef/browser/alloy/dialogs/alloy_web_contents_dialog_helper.h
index 39be126..0f3ec92 100644
--- a/src/libcef/browser/web_contents_dialog_helper.h
+++ b/src/libcef/browser/alloy/dialogs/alloy_web_contents_dialog_helper.h
@@ -2,11 +2,11 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#ifndef CEF_LIBCEF_BROWSER_WEB_CONTENTS_DIALOG_HELPER_H_
-#define CEF_LIBCEF_BROWSER_WEB_CONTENTS_DIALOG_HELPER_H_
+#ifndef CEF_LIBCEF_BROWSER_ALLOY_DIALOGS_ALLOY_WEB_CONTENTS_DIALOG_HELPER_H_
+#define CEF_LIBCEF_BROWSER_ALLOY_DIALOGS_ALLOY_WEB_CONTENTS_DIALOG_HELPER_H_
 #pragma once
 
-#include "base/callback_forward.h"
+#include "base/functional/callback_forward.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "components/web_modal/modal_dialog_host.h"
@@ -15,12 +15,12 @@
 
 class CefBrowserPlatformDelegate;
 
-class CefWebContentsDialogHelper
+class AlloyWebContentsDialogHelper
     : public web_modal::WebContentsModalDialogManagerDelegate,
       public web_modal::WebContentsModalDialogHost {
  public:
-  CefWebContentsDialogHelper(content::WebContents* web_contents,
-                             CefBrowserPlatformDelegate* browser_delegate);
+  AlloyWebContentsDialogHelper(content::WebContents* web_contents,
+                               CefBrowserPlatformDelegate* browser_delegate);
 
   base::RepeatingClosure GetBoundsChangedCallback();
 
@@ -31,6 +31,7 @@
 
   // web_modal::WebContentsModalDialogHost methods:
   gfx::NativeView GetHostView() const override;
+  gfx::AcceleratedWidget GetAcceleratedWidget() const override;
   gfx::Point GetDialogPosition(const gfx::Size& size) override;
   gfx::Size GetMaximumDialogSize() override;
   void AddObserver(web_modal::ModalDialogHostObserver* observer) override;
@@ -45,7 +46,7 @@
   base::ObserverList<web_modal::ModalDialogHostObserver>::Unchecked
       observer_list_;
 
-  base::WeakPtrFactory<CefWebContentsDialogHelper> weak_factory_;
+  base::WeakPtrFactory<AlloyWebContentsDialogHelper> weak_factory_;
 };
 
-#endif  // CEF_LIBCEF_BROWSER_WEB_CONTENTS_DIALOG_HELPER_H_
+#endif  // CEF_LIBCEF_BROWSER_ALLOY_DIALOGS_ALLOY_WEB_CONTENTS_DIALOG_HELPER_H_
diff --git a/src/libcef/browser/audio_capturer.cc b/src/libcef/browser/audio_capturer.cc
index 3eed7a7..ce76250 100644
--- a/src/libcef/browser/audio_capturer.cc
+++ b/src/libcef/browser/audio_capturer.cc
@@ -4,15 +4,16 @@
 // found in the LICENSE file.
 
 #include "libcef/browser/audio_capturer.h"
-#include "libcef/browser/browser_host_impl.h"
+
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
+#include "libcef/browser/audio_loopback_stream_creator.h"
 
 #include "components/mirroring/service/captured_audio_input.h"
-#include "content/public/browser/audio_loopback_stream_creator.h"
 #include "media/audio/audio_input_device.h"
 
 namespace {
 
-media::ChannelLayout TranslateChannelLayout(
+media::ChannelLayoutConfig TranslateChannelLayout(
     cef_channel_layout_t channel_layout) {
   // Verify that our enum matches Chromium's values. The enum values match
   // between those enums and existing values don't ever change, so it's enough
@@ -21,12 +22,14 @@
       static_cast<int>(CEF_CHANNEL_LAYOUT_MAX) ==
           static_cast<int>(media::CHANNEL_LAYOUT_MAX),
       "cef_channel_layout_t must match the ChannelLayout enum in Chromium");
-  return static_cast<media::ChannelLayout>(channel_layout);
+
+  const auto layout = static_cast<media::ChannelLayout>(channel_layout);
+  return {layout, media::ChannelLayoutToChannelCount(layout)};
 }
 
 void StreamCreatorHelper(
     content::WebContents* source_web_contents,
-    content::AudioLoopbackStreamCreator* audio_stream_creator,
+    CefAudioLoopbackStreamCreator* audio_stream_creator,
     mojo::PendingRemote<mirroring::mojom::AudioStreamCreatorClient> client,
     const media::AudioParameters& params,
     uint32_t total_segments) {
@@ -41,9 +44,9 @@
              media::mojom::ReadOnlyAudioDataPipePtr data_pipe) {
             mojo::Remote<mirroring::mojom::AudioStreamCreatorClient>
                 audio_client(std::move(client));
-            audio_client->StreamCreated(
-                std::move(stream), std::move(client_receiver),
-                std::move(data_pipe), false /* initially_muted */);
+            audio_client->StreamCreated(std::move(stream),
+                                        std::move(client_receiver),
+                                        std::move(data_pipe));
           },
           base::Passed(&client)));
 }
@@ -51,13 +54,12 @@
 }  // namespace
 
 CefAudioCapturer::CefAudioCapturer(const CefAudioParameters& params,
-                                   CefRefPtr<CefBrowserHostImpl> browser,
+                                   CefRefPtr<AlloyBrowserHostImpl> browser,
                                    CefRefPtr<CefAudioHandler> audio_handler)
     : params_(params),
       browser_(browser),
       audio_handler_(audio_handler),
-      audio_stream_creator_(content::AudioLoopbackStreamCreator::
-                                CreateInProcessAudioLoopbackStreamCreator()) {
+      audio_stream_creator_(std::make_unique<CefAudioLoopbackStreamCreator>()) {
   media::AudioParameters audio_params(
       media::AudioParameters::AUDIO_PCM_LINEAR,
       TranslateChannelLayout(params.channel_layout), params.sample_rate,
@@ -77,7 +79,8 @@
       std::make_unique<mirroring::CapturedAudioInput>(base::BindRepeating(
           &StreamCreatorHelper, base::Unretained(browser_->web_contents()),
           base::Unretained(audio_stream_creator_.get()))),
-      media::AudioInputDevice::kLoopback);
+      media::AudioInputDevice::kLoopback,
+      media::AudioInputDevice::DeadStreamDetection::kEnabled);
 
   audio_input_device_->Initialize(audio_params, this);
   audio_input_device_->Start();
@@ -109,16 +112,20 @@
                                       pts.InMilliseconds());
 }
 
-void CefAudioCapturer::OnCaptureError(const std::string& message) {
+void CefAudioCapturer::OnCaptureError(
+    media::AudioCapturerSource::ErrorCode code,
+    const std::string& message) {
   audio_handler_->OnAudioStreamError(browser_, message);
   StopStream();
 }
 
 void CefAudioCapturer::StopStream() {
-  if (audio_input_device_)
+  if (audio_input_device_) {
     audio_input_device_->Stop();
-  if (capturing_)
+  }
+  if (capturing_) {
     audio_handler_->OnAudioStreamStopped(browser_);
+  }
 
   audio_input_device_ = nullptr;
   capturing_ = false;
diff --git a/src/libcef/browser/audio_capturer.h b/src/libcef/browser/audio_capturer.h
index 9801481..c38e01d 100644
--- a/src/libcef/browser/audio_capturer.h
+++ b/src/libcef/browser/audio_capturer.h
@@ -12,21 +12,18 @@
 
 #include "media/base/audio_capturer_source.h"
 
-namespace content {
-class AudioLoopbackStreamCreator;
-}  // namespace content
-
 namespace media {
 class AudioInputDevice;
 }  // namespace media
 
 class CefAudioHandler;
-class CefBrowserHostImpl;
+class CefAudioLoopbackStreamCreator;
+class AlloyBrowserHostImpl;
 
 class CefAudioCapturer : public media::AudioCapturerSource::CaptureCallback {
  public:
   CefAudioCapturer(const CefAudioParameters& params,
-                   CefRefPtr<CefBrowserHostImpl> browser,
+                   CefRefPtr<AlloyBrowserHostImpl> browser,
                    CefRefPtr<CefAudioHandler> audio_handler);
   ~CefAudioCapturer() override;
 
@@ -36,15 +33,16 @@
                base::TimeTicks audio_capture_time,
                double volume,
                bool key_pressed) override;
-  void OnCaptureError(const std::string& message) override;
+  void OnCaptureError(media::AudioCapturerSource::ErrorCode code,
+                      const std::string& message) override;
   void OnCaptureMuted(bool is_muted) override {}
 
   void StopStream();
 
   CefAudioParameters params_;
-  CefRefPtr<CefBrowserHostImpl> browser_;
+  CefRefPtr<AlloyBrowserHostImpl> browser_;
   CefRefPtr<CefAudioHandler> audio_handler_;
-  std::unique_ptr<content::AudioLoopbackStreamCreator> audio_stream_creator_;
+  std::unique_ptr<CefAudioLoopbackStreamCreator> audio_stream_creator_;
   scoped_refptr<media::AudioInputDevice> audio_input_device_;
   bool capturing_ = false;
   int channels_ = 0;
diff --git a/src/libcef/browser/audio_loopback_stream_creator.cc b/src/libcef/browser/audio_loopback_stream_creator.cc
new file mode 100644
index 0000000..48aea22
--- /dev/null
+++ b/src/libcef/browser/audio_loopback_stream_creator.cc
@@ -0,0 +1,135 @@
+// 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 "libcef/browser/audio_loopback_stream_creator.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/check_op.h"
+#include "base/functional/bind.h"
+#include "base/location.h"
+#include "content/browser/browser_main_loop.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+#include "media/audio/audio_device_description.h"
+#include "media/base/user_input_monitor.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "third_party/blink/public/mojom/media/renderer_audio_input_stream_factory.mojom.h"
+
+namespace {
+
+// A blink::mojom::RendererAudioInputStreamFactoryClient that holds a
+// CefAudioLoopbackStreamCreator::StreamCreatedCallback. The callback runs when
+// the requested audio stream is created.
+class StreamCreatedCallbackAdapter final
+    : public blink::mojom::RendererAudioInputStreamFactoryClient {
+ public:
+  explicit StreamCreatedCallbackAdapter(
+      const CefAudioLoopbackStreamCreator::StreamCreatedCallback& callback)
+      : callback_(callback) {
+    DCHECK(callback_);
+  }
+
+  StreamCreatedCallbackAdapter(const StreamCreatedCallbackAdapter&) = delete;
+  StreamCreatedCallbackAdapter& operator=(const StreamCreatedCallbackAdapter&) =
+      delete;
+
+  ~StreamCreatedCallbackAdapter() override {}
+
+  // blink::mojom::RendererAudioInputStreamFactoryClient implementation.
+  void StreamCreated(
+      mojo::PendingRemote<media::mojom::AudioInputStream> stream,
+      mojo::PendingReceiver<media::mojom::AudioInputStreamClient>
+          client_receiver,
+      media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
+      bool initially_muted,
+      const absl::optional<base::UnguessableToken>& stream_id) override {
+    DCHECK(!initially_muted);  // Loopback streams shouldn't be started muted.
+    callback_.Run(std::move(stream), std::move(client_receiver),
+                  std::move(data_pipe));
+  }
+
+ private:
+  const CefAudioLoopbackStreamCreator::StreamCreatedCallback callback_;
+};
+
+void CreateLoopbackStreamHelper(
+    content::ForwardingAudioStreamFactory::Core* factory,
+    content::AudioStreamBroker::LoopbackSource* loopback_source,
+    const media::AudioParameters& params,
+    uint32_t total_segments,
+    mojo::PendingRemote<blink::mojom::RendererAudioInputStreamFactoryClient>
+        client_remote) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+  const bool mute_source = true;
+  factory->CreateLoopbackStream(-1, -1, loopback_source, params, total_segments,
+                                mute_source, std::move(client_remote));
+}
+
+void CreateSystemWideLoopbackStreamHelper(
+    content::ForwardingAudioStreamFactory::Core* factory,
+    const media::AudioParameters& params,
+    uint32_t total_segments,
+    mojo::PendingRemote<blink::mojom::RendererAudioInputStreamFactoryClient>
+        client_remote) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+  const bool enable_agc = false;
+  factory->CreateInputStream(
+      -1, -1, media::AudioDeviceDescription::kLoopbackWithMuteDeviceId, params,
+      total_segments, enable_agc, media::mojom::AudioProcessingConfigPtr(),
+      std::move(client_remote));
+}
+
+}  // namespace
+
+CefAudioLoopbackStreamCreator::CefAudioLoopbackStreamCreator()
+    : factory_(nullptr,
+               content::BrowserMainLoop::GetInstance()
+                   ? static_cast<media::UserInputMonitorBase*>(
+                         content::BrowserMainLoop::GetInstance()
+                             ->user_input_monitor())
+                   : nullptr,
+               content::AudioStreamBrokerFactory::CreateImpl()) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+}
+
+CefAudioLoopbackStreamCreator::~CefAudioLoopbackStreamCreator() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+}
+
+void CefAudioLoopbackStreamCreator::CreateLoopbackStream(
+    content::WebContents* loopback_source,
+    const media::AudioParameters& params,
+    uint32_t total_segments,
+    const StreamCreatedCallback& callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  mojo::PendingRemote<blink::mojom::RendererAudioInputStreamFactoryClient>
+      client;
+  mojo::MakeSelfOwnedReceiver(
+      std::make_unique<StreamCreatedCallbackAdapter>(callback),
+      client.InitWithNewPipeAndPassReceiver());
+  // Deletion of factory_.core() is posted to the IO thread when |factory_| is
+  // destroyed, so Unretained is safe below.
+  if (loopback_source) {
+    content::GetIOThreadTaskRunner({})->PostTask(
+        FROM_HERE,
+        base::BindOnce(&CreateLoopbackStreamHelper, factory_.core(),
+                       static_cast<content::WebContentsImpl*>(loopback_source)
+                           ->GetAudioStreamFactory()
+                           ->core(),
+                       params, total_segments, std::move(client)));
+    return;
+  }
+  // A null |frame_of_source_web_contents| requests system-wide loopback.
+  content::GetIOThreadTaskRunner({})->PostTask(
+      FROM_HERE,
+      base::BindOnce(&CreateSystemWideLoopbackStreamHelper, factory_.core(),
+                     params, total_segments, std::move(client)));
+}
diff --git a/src/libcef/browser/audio_loopback_stream_creator.h b/src/libcef/browser/audio_loopback_stream_creator.h
new file mode 100644
index 0000000..1887832
--- /dev/null
+++ b/src/libcef/browser/audio_loopback_stream_creator.h
@@ -0,0 +1,53 @@
+// 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 CEF_LIBCEF_BROWSER_AUDIO_LOOPBACK_STREAM_CREATOR_H_
+#define CEF_LIBCEF_BROWSER_AUDIO_LOOPBACK_STREAM_CREATOR_H_
+
+#include "base/functional/callback.h"
+#include "content/browser/media/forwarding_audio_stream_factory.h"
+#include "content/common/content_export.h"
+#include "media/mojo/mojom/audio_data_pipe.mojom.h"
+#include "media/mojo/mojom/audio_input_stream.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+
+namespace media {
+class AudioParameters;
+}
+
+// This class handles creating a loopback stream that either captures audio from
+// a WebContents or the system-wide loopback through the Audio Service.
+// This class is operated on the UI thread.
+// Based on InProcessAudioLoopbackStreamCreator which was deleted in
+// https://crrev.com/a5af2468cf.
+class CefAudioLoopbackStreamCreator final {
+ public:
+  CefAudioLoopbackStreamCreator();
+
+  CefAudioLoopbackStreamCreator(const CefAudioLoopbackStreamCreator&) = delete;
+  CefAudioLoopbackStreamCreator& operator=(
+      const CefAudioLoopbackStreamCreator&) = delete;
+
+  ~CefAudioLoopbackStreamCreator();
+
+  // The callback that is called when the requested stream is created.
+  using StreamCreatedCallback = base::RepeatingCallback<void(
+      mojo::PendingRemote<media::mojom::AudioInputStream> stream,
+      mojo::PendingReceiver<media::mojom::AudioInputStreamClient>
+          client_receiver,
+      media::mojom::ReadOnlyAudioDataPipePtr data_pipe)>;
+
+  // Creates a loopback stream that captures the audio from |loopback_source|,
+  // or the default system playback if |loopback_source| is null. Local output
+  // of the source/system audio is muted during capturing.
+  void CreateLoopbackStream(content::WebContents* loopback_source,
+                            const media::AudioParameters& params,
+                            uint32_t total_segments,
+                            const StreamCreatedCallback& callback);
+
+ private:
+  content::ForwardingAudioStreamFactory factory_;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_AUDIO_LOOPBACK_STREAM_CREATOR_H_
diff --git a/src/libcef/browser/browser_contents_delegate.cc b/src/libcef/browser/browser_contents_delegate.cc
new file mode 100644
index 0000000..ac191ed
--- /dev/null
+++ b/src/libcef/browser/browser_contents_delegate.cc
@@ -0,0 +1,720 @@
+// Copyright 2020 The Chromium Embedded Framework 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 "libcef/browser/browser_contents_delegate.h"
+
+#include "libcef/browser/browser_host_base.h"
+#include "libcef/browser/browser_platform_delegate.h"
+#include "libcef/browser/browser_util.h"
+#include "libcef/browser/native/cursor_util.h"
+#include "libcef/common/frame_util.h"
+
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/public/browser/focused_node_details.h"
+#include "content/public/browser/keyboard_event_processing_result.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_source.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_observer.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/common/input/native_web_keyboard_event.h"
+#include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h"
+#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/widget/platform_widget.mojom-test-utils.h"
+
+using content::KeyboardEventProcessingResult;
+
+namespace {
+
+class CefWidgetHostInterceptor
+    : public blink::mojom::WidgetHostInterceptorForTesting,
+      public content::RenderWidgetHostObserver {
+ public:
+  CefWidgetHostInterceptor(CefRefPtr<CefBrowser> browser,
+                           content::RenderWidgetHost* render_widget_host)
+      : browser_(browser),
+        render_widget_host_(render_widget_host),
+        impl_(static_cast<content::RenderWidgetHostImpl*>(render_widget_host)
+                  ->widget_host_receiver_for_testing()
+                  .SwapImplForTesting(this)) {
+    render_widget_host_->AddObserver(this);
+  }
+
+  CefWidgetHostInterceptor(const CefWidgetHostInterceptor&) = delete;
+  CefWidgetHostInterceptor& operator=(const CefWidgetHostInterceptor&) = delete;
+
+  blink::mojom::WidgetHost* GetForwardingInterface() override { return impl_; }
+
+  // WidgetHostInterceptorForTesting method:
+  void SetCursor(const ui::Cursor& cursor) override {
+    if (cursor_util::OnCursorChange(browser_, cursor)) {
+      // Don't change the cursor.
+      return;
+    }
+
+    GetForwardingInterface()->SetCursor(cursor);
+  }
+
+  // RenderWidgetHostObserver method:
+  void RenderWidgetHostDestroyed(
+      content::RenderWidgetHost* widget_host) override {
+    widget_host->RemoveObserver(this);
+    delete this;
+  }
+
+ private:
+  CefRefPtr<CefBrowser> const browser_;
+  content::RenderWidgetHost* const render_widget_host_;
+  blink::mojom::WidgetHost* const impl_;
+};
+
+}  // namespace
+
+CefBrowserContentsDelegate::CefBrowserContentsDelegate(
+    scoped_refptr<CefBrowserInfo> browser_info)
+    : browser_info_(browser_info) {
+  DCHECK(browser_info_->browser());
+}
+
+void CefBrowserContentsDelegate::ObserveWebContents(
+    content::WebContents* new_contents) {
+  WebContentsObserver::Observe(new_contents);
+
+  if (new_contents) {
+    registrar_.reset(new content::NotificationRegistrar);
+
+    // When navigating through the history, the restored NavigationEntry's title
+    // will be used. If the entry ends up having the same title after we return
+    // to it, as will usually be the case, the
+    // NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED will then be suppressed, since
+    // the NavigationEntry's title hasn't changed.
+    registrar_->Add(this, content::NOTIFICATION_LOAD_STOP,
+                    content::Source<content::NavigationController>(
+                        &new_contents->GetController()));
+
+    // Make sure MaybeCreateFrame is called at least one time.
+    // Create the frame representation before OnAfterCreated is called for a new
+    // browser.
+    browser_info_->MaybeCreateFrame(new_contents->GetPrimaryMainFrame(),
+                                    false /* is_guest_view */);
+
+    // Make sure RenderWidgetCreated is called at least one time. This Observer
+    // is registered too late to catch the initial creation.
+    RenderWidgetCreated(new_contents->GetRenderViewHost()->GetWidget());
+  } else {
+    registrar_.reset();
+  }
+}
+
+void CefBrowserContentsDelegate::AddObserver(Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void CefBrowserContentsDelegate::RemoveObserver(Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+// |source| may be NULL for navigations in the current tab, or if the
+// navigation originates from a guest view via MaybeAllowNavigation.
+content::WebContents* CefBrowserContentsDelegate::OpenURLFromTab(
+    content::WebContents* source,
+    const content::OpenURLParams& params) {
+  bool cancel = false;
+
+  if (auto c = client()) {
+    if (auto handler = c->GetRequestHandler()) {
+      // May return nullptr for omnibox navigations.
+      auto frame = browser()->GetFrame(params.frame_tree_node_id);
+      if (!frame) {
+        frame = browser()->GetMainFrame();
+      }
+      cancel = handler->OnOpenURLFromTab(
+          browser(), frame, params.url.spec(),
+          static_cast<cef_window_open_disposition_t>(params.disposition),
+          params.user_gesture);
+    }
+  }
+
+  // Returning nullptr will cancel the navigation.
+  return cancel ? nullptr : web_contents();
+}
+
+void CefBrowserContentsDelegate::LoadingStateChanged(
+    content::WebContents* source,
+    bool should_show_loading_ui) {
+  const int current_index =
+      source->GetController().GetLastCommittedEntryIndex();
+  const int max_index = source->GetController().GetEntryCount() - 1;
+
+  const bool is_loading = source->IsLoading();
+  const bool can_go_back = (current_index > 0);
+  const bool can_go_forward = (current_index < max_index);
+
+  // This method may be called multiple times in a row with |is_loading|
+  // true as a result of https://crrev.com/5e750ad0. Ignore the 2nd+ times.
+  if (is_loading_ == is_loading && can_go_back_ == can_go_back &&
+      can_go_forward_ == can_go_forward) {
+    return;
+  }
+
+  is_loading_ = is_loading;
+  can_go_back_ = can_go_back;
+  can_go_forward_ = can_go_forward;
+  OnStateChanged(State::kNavigation);
+
+  if (auto c = client()) {
+    if (auto handler = c->GetLoadHandler()) {
+      auto navigation_lock = browser_info_->CreateNavigationLock();
+      handler->OnLoadingStateChange(browser(), is_loading, can_go_back,
+                                    can_go_forward);
+    }
+  }
+}
+
+void CefBrowserContentsDelegate::UpdateTargetURL(content::WebContents* source,
+                                                 const GURL& url) {
+  if (auto c = client()) {
+    if (auto handler = c->GetDisplayHandler()) {
+      handler->OnStatusMessage(browser(), url.spec());
+    }
+  }
+}
+
+bool CefBrowserContentsDelegate::DidAddMessageToConsole(
+    content::WebContents* source,
+    blink::mojom::ConsoleMessageLevel log_level,
+    const std::u16string& message,
+    int32_t line_no,
+    const std::u16string& source_id) {
+  if (auto c = client()) {
+    if (auto handler = c->GetDisplayHandler()) {
+      // Use LOGSEVERITY_DEBUG for unrecognized |level| values.
+      cef_log_severity_t cef_level = LOGSEVERITY_DEBUG;
+      switch (log_level) {
+        case blink::mojom::ConsoleMessageLevel::kVerbose:
+          cef_level = LOGSEVERITY_DEBUG;
+          break;
+        case blink::mojom::ConsoleMessageLevel::kInfo:
+          cef_level = LOGSEVERITY_INFO;
+          break;
+        case blink::mojom::ConsoleMessageLevel::kWarning:
+          cef_level = LOGSEVERITY_WARNING;
+          break;
+        case blink::mojom::ConsoleMessageLevel::kError:
+          cef_level = LOGSEVERITY_ERROR;
+          break;
+      }
+
+      return handler->OnConsoleMessage(browser(), cef_level, message, source_id,
+                                       line_no);
+    }
+  }
+
+  return false;
+}
+
+void CefBrowserContentsDelegate::EnterFullscreenModeForTab(
+    content::RenderFrameHost* requesting_frame,
+    const blink::mojom::FullscreenOptions& options) {
+  OnFullscreenModeChange(/*fullscreen=*/true);
+}
+
+void CefBrowserContentsDelegate::ExitFullscreenModeForTab(
+    content::WebContents* web_contents) {
+  OnFullscreenModeChange(/*fullscreen=*/false);
+}
+
+void CefBrowserContentsDelegate::CanDownload(
+    const GURL& url,
+    const std::string& request_method,
+    base::OnceCallback<void(bool)> callback) {
+  bool allow = true;
+
+  if (auto delegate = platform_delegate()) {
+    if (auto c = client()) {
+      if (auto handler = c->GetDownloadHandler()) {
+        allow = handler->CanDownload(browser(), url.spec(), request_method);
+      }
+    }
+  }
+
+  std::move(callback).Run(allow);
+}
+
+KeyboardEventProcessingResult
+CefBrowserContentsDelegate::PreHandleKeyboardEvent(
+    content::WebContents* source,
+    const content::NativeWebKeyboardEvent& event) {
+  if (auto delegate = platform_delegate()) {
+    if (auto c = client()) {
+      if (auto handler = c->GetKeyboardHandler()) {
+        CefKeyEvent cef_event;
+        if (browser_util::GetCefKeyEvent(event, cef_event)) {
+          cef_event.focus_on_editable_field = focus_on_editable_field_;
+
+          auto event_handle = delegate->GetEventHandle(event);
+          bool is_keyboard_shortcut = false;
+          bool result = handler->OnPreKeyEvent(
+              browser(), cef_event, event_handle, &is_keyboard_shortcut);
+          if (result) {
+            return KeyboardEventProcessingResult::HANDLED;
+          } else if (is_keyboard_shortcut) {
+            return KeyboardEventProcessingResult::NOT_HANDLED_IS_SHORTCUT;
+          }
+        }
+      }
+    }
+  }
+
+  return KeyboardEventProcessingResult::NOT_HANDLED;
+}
+
+bool CefBrowserContentsDelegate::HandleKeyboardEvent(
+    content::WebContents* source,
+    const content::NativeWebKeyboardEvent& event) {
+  // Check to see if event should be ignored.
+  if (event.skip_if_unhandled) {
+    return false;
+  }
+
+  if (auto delegate = platform_delegate()) {
+    if (auto c = client()) {
+      if (auto handler = c->GetKeyboardHandler()) {
+        CefKeyEvent cef_event;
+        if (browser_util::GetCefKeyEvent(event, cef_event)) {
+          cef_event.focus_on_editable_field = focus_on_editable_field_;
+
+          auto event_handle = delegate->GetEventHandle(event);
+          if (handler->OnKeyEvent(browser(), cef_event, event_handle)) {
+            return true;
+          }
+        }
+      }
+    }
+  }
+
+  return false;
+}
+
+void CefBrowserContentsDelegate::RenderFrameCreated(
+    content::RenderFrameHost* render_frame_host) {
+  browser_info_->MaybeCreateFrame(render_frame_host, false /* is_guest_view */);
+  if (render_frame_host->GetParent() == nullptr) {
+    auto render_view_host = render_frame_host->GetRenderViewHost();
+    auto base_background_color = platform_delegate()->GetBackgroundColor();
+    if (browser_info_ && browser_info_->is_popup()) {
+      // force reset page base background color because popup window won't get
+      // the page base background from web_contents at the creation time
+      web_contents()->SetPageBaseBackgroundColor(SkColor());
+      web_contents()->SetPageBaseBackgroundColor(base_background_color);
+    }
+    if (render_view_host->GetWidget() &&
+        render_view_host->GetWidget()->GetView()) {
+      render_view_host->GetWidget()->GetView()->SetBackgroundColor(
+          base_background_color);
+    }
+
+    platform_delegate()->RenderViewCreated(render_view_host);
+  }
+}
+
+void CefBrowserContentsDelegate::RenderFrameHostChanged(
+    content::RenderFrameHost* old_host,
+    content::RenderFrameHost* new_host) {
+  // Just in case RenderFrameCreated wasn't called for some reason.
+  RenderFrameCreated(new_host);
+}
+
+void CefBrowserContentsDelegate::RenderFrameHostStateChanged(
+    content::RenderFrameHost* host,
+    content::RenderFrameHost::LifecycleState old_state,
+    content::RenderFrameHost::LifecycleState new_state) {
+  browser_info_->FrameHostStateChanged(host, old_state, new_state);
+}
+
+void CefBrowserContentsDelegate::RenderFrameDeleted(
+    content::RenderFrameHost* render_frame_host) {
+  const auto frame_id =
+      frame_util::MakeFrameId(render_frame_host->GetGlobalId());
+  browser_info_->RemoveFrame(render_frame_host);
+
+  if (focused_frame_ && focused_frame_->GetIdentifier() == frame_id) {
+    focused_frame_ = nullptr;
+    OnStateChanged(State::kFocusedFrame);
+  }
+}
+
+void CefBrowserContentsDelegate::RenderWidgetCreated(
+    content::RenderWidgetHost* render_widget_host) {
+  new CefWidgetHostInterceptor(browser(), render_widget_host);
+}
+
+void CefBrowserContentsDelegate::RenderViewReady() {
+  platform_delegate()->RenderViewReady();
+
+  if (auto c = client()) {
+    if (auto handler = c->GetRequestHandler()) {
+      handler->OnRenderViewReady(browser());
+    }
+  }
+}
+
+void CefBrowserContentsDelegate::PrimaryMainFrameRenderProcessGone(
+    base::TerminationStatus status) {
+  cef_termination_status_t ts = TS_ABNORMAL_TERMINATION;
+  if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
+    ts = TS_PROCESS_WAS_KILLED;
+  } else if (status == base::TERMINATION_STATUS_PROCESS_CRASHED) {
+    ts = TS_PROCESS_CRASHED;
+  } else if (status == base::TERMINATION_STATUS_OOM) {
+    ts = TS_PROCESS_OOM;
+  } else if (status != base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
+    return;
+  }
+
+  if (auto c = client()) {
+    if (auto handler = c->GetRequestHandler()) {
+      auto navigation_lock = browser_info_->CreateNavigationLock();
+      handler->OnRenderProcessTerminated(browser(), ts);
+    }
+  }
+}
+
+void CefBrowserContentsDelegate::OnFrameFocused(
+    content::RenderFrameHost* render_frame_host) {
+  CefRefPtr<CefFrameHostImpl> frame = static_cast<CefFrameHostImpl*>(
+      browser_info_->GetFrameForHost(render_frame_host).get());
+  if (!frame || frame->IsFocused()) {
+    return;
+  }
+
+  CefRefPtr<CefFrameHostImpl> previous_frame = focused_frame_;
+  if (frame->IsMain()) {
+    focused_frame_ = nullptr;
+  } else {
+    focused_frame_ = frame;
+  }
+
+  if (!previous_frame) {
+    // The main frame is focused by default.
+    previous_frame = browser_info_->GetMainFrame();
+  }
+
+  if (previous_frame->GetIdentifier() != frame->GetIdentifier()) {
+    previous_frame->SetFocused(false);
+    frame->SetFocused(true);
+  }
+
+  OnStateChanged(State::kFocusedFrame);
+}
+
+void CefBrowserContentsDelegate::PrimaryMainDocumentElementAvailable() {
+  has_document_ = true;
+  OnStateChanged(State::kDocument);
+
+  if (auto c = client()) {
+    if (auto handler = c->GetRequestHandler()) {
+      handler->OnDocumentAvailableInMainFrame(browser());
+    }
+  }
+}
+
+void CefBrowserContentsDelegate::LoadProgressChanged(double progress) {
+  if (auto c = client()) {
+    if (auto handler = c->GetDisplayHandler()) {
+      handler->OnLoadingProgressChange(browser(), progress);
+    }
+  }
+}
+
+void CefBrowserContentsDelegate::DidStopLoading() {
+  // Notify all renderers that loading has stopped. We used to use
+  // RenderFrameObserver::DidStopLoading in the renderer process but that was
+  // removed in https://crrev.com/3e37dd0ead. However, that callback wasn't
+  // necessarily accurate because it wasn't called in all of the cases where
+  // RenderFrameImpl sends the FrameHostMsg_DidStopLoading message. This adds
+  // an additional round trip but should provide the same or improved
+  // functionality.
+  for (const auto& frame : browser_info_->GetAllFrames()) {
+    frame->MaybeSendDidStopLoading();
+  }
+}
+
+void CefBrowserContentsDelegate::DidFinishNavigation(
+    content::NavigationHandle* navigation_handle) {
+  const net::Error error_code = navigation_handle->GetNetErrorCode();
+
+  // Skip calls where the navigation has not yet committed and there is no
+  // error code. For example, when creating a browser without loading a URL.
+  if (!navigation_handle->HasCommitted() && error_code == net::OK) {
+    return;
+  }
+
+  if (navigation_handle->IsInPrimaryMainFrame() &&
+      navigation_handle->HasCommitted()) {
+    // A primary main frame navigation has occured.
+    has_document_ = false;
+    OnStateChanged(State::kDocument);
+  }
+
+  const bool is_main_frame = navigation_handle->IsInMainFrame();
+  const auto global_id = frame_util::GetGlobalId(navigation_handle);
+  const GURL& url =
+      (error_code == net::OK ? navigation_handle->GetURL() : GURL());
+
+  auto browser_info = browser_info_;
+  if (!browser_info->browser()) {
+    // Ignore notifications when the browser is closing.
+    return;
+  }
+
+  // May return NULL when starting a new navigation if the previous navigation
+  // caused the renderer process to crash during load.
+  CefRefPtr<CefFrameHostImpl> frame =
+      browser_info->GetFrameForGlobalId(global_id);
+  if (!frame) {
+    if (is_main_frame) {
+      frame = browser_info->GetMainFrame();
+    } else {
+      frame = browser_info->CreateTempSubFrame(frame_util::InvalidGlobalId());
+    }
+  }
+  frame->RefreshAttributes();
+
+  if (error_code == net::OK) {
+    // The navigation has been committed and there is no error.
+    DCHECK(navigation_handle->HasCommitted());
+
+    // Don't call OnLoadStart for same page navigations (fragments,
+    // history state).
+    if (!navigation_handle->IsSameDocument()) {
+      OnLoadStart(frame.get(), navigation_handle->GetPageTransition());
+      if (navigation_handle->IsServedFromBackForwardCache()) {
+        // We won't get an OnLoadEnd notification from anywhere else.
+        OnLoadEnd(frame.get(), navigation_handle->GetURL(), 0);
+      }
+    }
+
+    if (is_main_frame) {
+      OnAddressChange(url);
+    }
+  } else {
+    // The navigation failed with an error. This may happen before commit
+    // (e.g. network error) or after commit (e.g. response filter error).
+    // If the error happened before commit then this call will originate from
+    // RenderFrameHostImpl::OnDidFailProvisionalLoadWithError.
+    // OnLoadStart/OnLoadEnd will not be called.
+    OnLoadError(frame.get(), navigation_handle->GetURL(), error_code);
+  }
+}
+
+void CefBrowserContentsDelegate::DidFailLoad(
+    content::RenderFrameHost* render_frame_host,
+    const GURL& validated_url,
+    int error_code) {
+  // The navigation failed after commit. OnLoadStart was called so we also
+  // call OnLoadEnd.
+  auto frame = browser_info_->GetFrameForHost(render_frame_host);
+  frame->RefreshAttributes();
+  OnLoadError(frame, validated_url, error_code);
+  OnLoadEnd(frame, validated_url, error_code);
+}
+
+void CefBrowserContentsDelegate::DidFinishLoad(
+    content::RenderFrameHost* render_frame_host,
+    const GURL& validated_url) {
+  auto frame = browser_info_->GetFrameForHost(render_frame_host);
+  frame->RefreshAttributes();
+
+  int http_status_code = 0;
+  if (auto response_headers = render_frame_host->GetLastResponseHeaders()) {
+    http_status_code = response_headers->response_code();
+  }
+
+  OnLoadEnd(frame, validated_url, http_status_code);
+}
+
+void CefBrowserContentsDelegate::TitleWasSet(content::NavigationEntry* entry) {
+  // |entry| may be NULL if a popup is created via window.open and never
+  // navigated.
+  if (entry) {
+    OnTitleChange(entry->GetTitle());
+  } else if (web_contents()) {
+    OnTitleChange(web_contents()->GetTitle());
+  }
+}
+
+void CefBrowserContentsDelegate::DidUpdateFaviconURL(
+    content::RenderFrameHost* render_frame_host,
+    const std::vector<blink::mojom::FaviconURLPtr>& candidates) {
+  if (auto c = client()) {
+    if (auto handler = c->GetDisplayHandler()) {
+      std::vector<CefString> icon_urls;
+      for (const auto& icon : candidates) {
+        if (icon->icon_type == blink::mojom::FaviconIconType::kFavicon) {
+          icon_urls.push_back(icon->icon_url.spec());
+        }
+      }
+      if (!icon_urls.empty()) {
+        handler->OnFaviconURLChange(browser(), icon_urls);
+      }
+    }
+  }
+}
+
+void CefBrowserContentsDelegate::OnWebContentsFocused(
+    content::RenderWidgetHost* render_widget_host) {
+  if (auto c = client()) {
+    if (auto handler = c->GetFocusHandler()) {
+      handler->OnGotFocus(browser());
+    }
+  }
+}
+
+void CefBrowserContentsDelegate::OnFocusChangedInPage(
+    content::FocusedNodeDetails* details) {
+  focus_on_editable_field_ =
+      details->focus_type != blink::mojom::blink::FocusType::kNone &&
+      details->is_editable_node;
+}
+
+void CefBrowserContentsDelegate::WebContentsDestroyed() {
+  auto wc = web_contents();
+  ObserveWebContents(nullptr);
+  for (auto& observer : observers_) {
+    observer.OnWebContentsDestroyed(wc);
+  }
+}
+
+void CefBrowserContentsDelegate::Observe(
+    int type,
+    const content::NotificationSource& source,
+    const content::NotificationDetails& details) {
+  DCHECK_EQ(type, content::NOTIFICATION_LOAD_STOP);
+
+  if (type == content::NOTIFICATION_LOAD_STOP) {
+    OnTitleChange(web_contents()->GetTitle());
+  }
+}
+
+bool CefBrowserContentsDelegate::OnSetFocus(cef_focus_source_t source) {
+  // SetFocus() might be called while inside the OnSetFocus() callback. If
+  // so, don't re-enter the callback.
+  if (is_in_onsetfocus_) {
+    return true;
+  }
+
+  if (auto c = client()) {
+    if (auto handler = c->GetFocusHandler()) {
+      is_in_onsetfocus_ = true;
+      bool handled = handler->OnSetFocus(browser(), source);
+      is_in_onsetfocus_ = false;
+
+      return handled;
+    }
+  }
+
+  return false;
+}
+
+CefRefPtr<CefClient> CefBrowserContentsDelegate::client() const {
+  if (auto b = browser()) {
+    return b->GetHost()->GetClient();
+  }
+  return nullptr;
+}
+
+CefRefPtr<CefBrowser> CefBrowserContentsDelegate::browser() const {
+  return browser_info_->browser();
+}
+
+CefBrowserPlatformDelegate* CefBrowserContentsDelegate::platform_delegate()
+    const {
+  auto browser = browser_info_->browser();
+  if (browser) {
+    return browser->platform_delegate();
+  }
+  return nullptr;
+}
+
+void CefBrowserContentsDelegate::OnAddressChange(const GURL& url) {
+  if (auto c = client()) {
+    if (auto handler = c->GetDisplayHandler()) {
+      // On the handler of an address change.
+      handler->OnAddressChange(browser(), browser_info_->GetMainFrame(),
+                               url.spec());
+    }
+  }
+}
+
+void CefBrowserContentsDelegate::OnLoadStart(
+    CefRefPtr<CefFrame> frame,
+    ui::PageTransition transition_type) {
+  if (auto c = client()) {
+    if (auto handler = c->GetLoadHandler()) {
+      auto navigation_lock = browser_info_->CreateNavigationLock();
+      // On the handler that loading has started.
+      handler->OnLoadStart(browser(), frame,
+                           static_cast<cef_transition_type_t>(transition_type));
+    }
+  }
+}
+
+void CefBrowserContentsDelegate::OnLoadEnd(CefRefPtr<CefFrame> frame,
+                                           const GURL& url,
+                                           int http_status_code) {
+  if (auto c = client()) {
+    if (auto handler = c->GetLoadHandler()) {
+      auto navigation_lock = browser_info_->CreateNavigationLock();
+      handler->OnLoadEnd(browser(), frame, http_status_code);
+    }
+  }
+}
+
+void CefBrowserContentsDelegate::OnLoadError(CefRefPtr<CefFrame> frame,
+                                             const GURL& url,
+                                             int error_code) {
+  if (auto c = client()) {
+    if (auto handler = c->GetLoadHandler()) {
+      auto navigation_lock = browser_info_->CreateNavigationLock();
+      // On the handler that loading has failed.
+      handler->OnLoadError(browser(), frame,
+                           static_cast<cef_errorcode_t>(error_code),
+                           net::ErrorToShortString(error_code), url.spec());
+    }
+  }
+}
+
+void CefBrowserContentsDelegate::OnTitleChange(const std::u16string& title) {
+  if (auto c = client()) {
+    if (auto handler = c->GetDisplayHandler()) {
+      handler->OnTitleChange(browser(), title);
+    }
+  }
+}
+
+void CefBrowserContentsDelegate::OnFullscreenModeChange(bool fullscreen) {
+  if (fullscreen == is_fullscreen_) {
+    return;
+  }
+
+  is_fullscreen_ = fullscreen;
+  OnStateChanged(State::kFullscreen);
+
+  if (auto c = client()) {
+    if (auto handler = c->GetDisplayHandler()) {
+      handler->OnFullscreenModeChange(browser(), fullscreen);
+    }
+  }
+}
+
+void CefBrowserContentsDelegate::OnStateChanged(State state_changed) {
+  for (auto& observer : observers_) {
+    observer.OnStateChanged(state_changed);
+  }
+}
diff --git a/src/libcef/browser/browser_contents_delegate.h b/src/libcef/browser/browser_contents_delegate.h
new file mode 100644
index 0000000..87c931e
--- /dev/null
+++ b/src/libcef/browser/browser_contents_delegate.h
@@ -0,0 +1,206 @@
+// Copyright 2020 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_BROWSER_CONTENTS_DELEGATE_H_
+#define CEF_LIBCEF_BROWSER_BROWSER_CONTENTS_DELEGATE_H_
+#pragma once
+
+#include <memory>
+
+#include "libcef/browser/frame_host_impl.h"
+
+#include "base/callback_list.h"
+#include "base/observer_list.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/browser/web_contents_observer.h"
+
+class CefBrowser;
+class CefBrowserInfo;
+class CefBrowserPlatformDelegate;
+class CefClient;
+
+// Flags that represent which states have changed.
+enum class CefBrowserContentsState : uint8_t {
+  kNone = 0,
+  kNavigation = (1 << 0),
+  kDocument = (1 << 1),
+  kFullscreen = (1 << 2),
+  kFocusedFrame = (1 << 3),
+};
+
+constexpr inline CefBrowserContentsState operator&(
+    CefBrowserContentsState lhs,
+    CefBrowserContentsState rhs) {
+  return static_cast<CefBrowserContentsState>(static_cast<int>(lhs) &
+                                              static_cast<int>(rhs));
+}
+
+constexpr inline CefBrowserContentsState operator|(
+    CefBrowserContentsState lhs,
+    CefBrowserContentsState rhs) {
+  return static_cast<CefBrowserContentsState>(static_cast<int>(lhs) |
+                                              static_cast<int>(rhs));
+}
+
+// Tracks state and executes client callbacks based on WebContents callbacks.
+// Includes functionality that is shared by the alloy and chrome runtimes.
+// Only accessed on the UI thread.
+class CefBrowserContentsDelegate : public content::WebContentsDelegate,
+                                   public content::WebContentsObserver,
+                                   public content::NotificationObserver {
+ public:
+  using State = CefBrowserContentsState;
+
+  // Interface to implement for observers that wish to be informed of changes
+  // to the delegate. All methods will be called on the UI thread.
+  class Observer : public base::CheckedObserver {
+   public:
+    // Called after state has changed and before the associated CefClient
+    // callback is executed.
+    virtual void OnStateChanged(State state_changed) = 0;
+
+    // Called when the associated WebContents is destroyed.
+    virtual void OnWebContentsDestroyed(content::WebContents* web_contents) = 0;
+
+   protected:
+    ~Observer() override {}
+  };
+
+  explicit CefBrowserContentsDelegate(
+      scoped_refptr<CefBrowserInfo> browser_info);
+
+  CefBrowserContentsDelegate(const CefBrowserContentsDelegate&) = delete;
+  CefBrowserContentsDelegate& operator=(const CefBrowserContentsDelegate&) =
+      delete;
+
+  void ObserveWebContents(content::WebContents* new_contents);
+
+  // Manage observer objects. The observer must either outlive this object or
+  // be removed before destruction.
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
+  // WebContentsDelegate methods:
+  content::WebContents* OpenURLFromTab(
+      content::WebContents* source,
+      const content::OpenURLParams& params) override;
+  void LoadingStateChanged(content::WebContents* source,
+                           bool should_show_loading_ui) override;
+  void UpdateTargetURL(content::WebContents* source, const GURL& url) override;
+  bool DidAddMessageToConsole(content::WebContents* source,
+                              blink::mojom::ConsoleMessageLevel log_level,
+                              const std::u16string& message,
+                              int32_t line_no,
+                              const std::u16string& source_id) override;
+  void EnterFullscreenModeForTab(
+      content::RenderFrameHost* requesting_frame,
+      const blink::mojom::FullscreenOptions& options) override;
+  void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
+  void CanDownload(const GURL& url,
+                   const std::string& request_method,
+                   base::OnceCallback<void(bool)> callback) override;
+  content::KeyboardEventProcessingResult PreHandleKeyboardEvent(
+      content::WebContents* source,
+      const content::NativeWebKeyboardEvent& event) override;
+  bool HandleKeyboardEvent(
+      content::WebContents* source,
+      const content::NativeWebKeyboardEvent& event) override;
+
+  // WebContentsObserver methods:
+  void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
+  void RenderFrameHostChanged(content::RenderFrameHost* old_host,
+                              content::RenderFrameHost* new_host) override;
+  void RenderFrameHostStateChanged(
+      content::RenderFrameHost* host,
+      content::RenderFrameHost::LifecycleState old_state,
+      content::RenderFrameHost::LifecycleState new_state) override;
+  void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
+  void RenderWidgetCreated(
+      content::RenderWidgetHost* render_widget_host) override;
+  void RenderViewReady() override;
+  void PrimaryMainFrameRenderProcessGone(
+      base::TerminationStatus status) override;
+  void OnFrameFocused(content::RenderFrameHost* render_frame_host) override;
+  void PrimaryMainDocumentElementAvailable() override;
+  void LoadProgressChanged(double progress) override;
+  void DidStopLoading() override;
+  void DidFinishNavigation(
+      content::NavigationHandle* navigation_handle) override;
+  void DidFailLoad(content::RenderFrameHost* render_frame_host,
+                   const GURL& validated_url,
+                   int error_code) override;
+  void DidFinishLoad(content::RenderFrameHost* render_frame_host,
+                     const GURL& validated_url) override;
+  void TitleWasSet(content::NavigationEntry* entry) override;
+  void DidUpdateFaviconURL(
+      content::RenderFrameHost* render_frame_host,
+      const std::vector<blink::mojom::FaviconURLPtr>& candidates) override;
+  void OnWebContentsFocused(
+      content::RenderWidgetHost* render_widget_host) override;
+  void OnFocusChangedInPage(content::FocusedNodeDetails* details) override;
+  void WebContentsDestroyed() override;
+
+  // NotificationObserver methods.
+  void Observe(int type,
+               const content::NotificationSource& source,
+               const content::NotificationDetails& details) override;
+
+  // Accessors for state information. Changes will be signaled to
+  // Observer::OnStateChanged.
+  bool is_loading() const { return is_loading_; }
+  bool can_go_back() const { return can_go_back_; }
+  bool can_go_forward() const { return can_go_forward_; }
+  bool has_document() const { return has_document_; }
+  bool is_fullscreen() const { return is_fullscreen_; }
+  CefRefPtr<CefFrameHostImpl> focused_frame() const { return focused_frame_; }
+
+  // Helpers for executing client callbacks.
+  // TODO(cef): Make this private if/when possible.
+  bool OnSetFocus(cef_focus_source_t source);
+
+ private:
+  CefRefPtr<CefClient> client() const;
+  CefRefPtr<CefBrowser> browser() const;
+  CefBrowserPlatformDelegate* platform_delegate() const;
+
+  // Helpers for executing client callbacks.
+  void OnAddressChange(const GURL& url);
+  void OnLoadStart(CefRefPtr<CefFrame> frame,
+                   ui::PageTransition transition_type);
+  void OnLoadEnd(CefRefPtr<CefFrame> frame,
+                 const GURL& url,
+                 int http_status_code);
+  void OnLoadError(CefRefPtr<CefFrame> frame, const GURL& url, int error_code);
+  void OnTitleChange(const std::u16string& title);
+  void OnFullscreenModeChange(bool fullscreen);
+
+  void OnStateChanged(State state_changed);
+
+  scoped_refptr<CefBrowserInfo> browser_info_;
+
+  bool is_loading_ = false;
+  bool can_go_back_ = false;
+  bool can_go_forward_ = false;
+  bool has_document_ = false;
+  bool is_fullscreen_ = false;
+
+  // The currently focused frame, or nullptr if the main frame is focused.
+  CefRefPtr<CefFrameHostImpl> focused_frame_;
+
+  // True if currently in the OnSetFocus callback.
+  bool is_in_onsetfocus_ = false;
+
+  // Observers that want to be notified of changes to this object.
+  base::ObserverList<Observer> observers_;
+
+  // Used for managing notification subscriptions.
+  std::unique_ptr<content::NotificationRegistrar> registrar_;
+
+  // True if the focus is currently on an editable field on the page.
+  bool focus_on_editable_field_ = false;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_BROWSER_CONTENTS_DELEGATE_H_
diff --git a/src/libcef/browser/browser_context.cc b/src/libcef/browser/browser_context.cc
index 2a81bca..eddb623 100644
--- a/src/libcef/browser/browser_context.cc
+++ b/src/libcef/browser/browser_context.cc
@@ -7,47 +7,25 @@
 #include <map>
 #include <utility>
 
-#include "libcef/browser/content_browser_client.h"
-#include "libcef/browser/download_manager_delegate.h"
-#include "libcef/browser/extensions/extension_system.h"
+#include "libcef/browser/context.h"
 #include "libcef/browser/media_router/media_router_manager.h"
-#include "libcef/browser/prefs/browser_prefs.h"
 #include "libcef/browser/request_context_impl.h"
-#include "libcef/browser/ssl_host_state_delegate.h"
 #include "libcef/browser/thread_util.h"
 #include "libcef/common/cef_switches.h"
-#include "libcef/common/extensions/extensions_util.h"
+#include "libcef/common/frame_util.h"
+#include "libcef/features/runtime.h"
 
-#include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
+#include "base/no_destructor.h"
+#include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
-#include "chrome/browser/font_family_cache.h"
-#include "chrome/browser/plugins/chrome_plugin_service_filter.h"
-#include "chrome/browser/profiles/profile_key.h"
-#include "chrome/browser/ui/zoom/chrome_zoom_level_prefs.h"
-#include "chrome/common/pref_names.h"
-#include "components/content_settings/core/browser/host_content_settings_map.h"
-#include "components/guest_view/browser/guest_view_manager.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/keyed_service/core/simple_dependency_manager.h"
-#include "components/keyed_service/core/simple_key_map.h"
-#include "components/prefs/pref_service.h"
-#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
-#include "components/user_prefs/user_prefs.h"
-#include "components/visitedlink/browser/visitedlink_event_listener.h"
-#include "components/visitedlink/browser/visitedlink_writer.h"
-#include "components/zoom/zoom_event_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/download_manager.h"
 #include "content/public/browser/storage_partition.h"
-#include "extensions/browser/extension_protocols.h"
-#include "extensions/browser/process_manager.h"
-#include "extensions/common/constants.h"
-#include "net/proxy_resolution/proxy_config_service.h"
-#include "services/network/public/mojom/cors_origin_pattern.mojom.h"
 
 using content::BrowserThread;
 
@@ -56,9 +34,13 @@
 // Manages the global list of Impl instances.
 class ImplManager {
  public:
-  typedef std::vector<CefBrowserContext*> Vector;
+  using Vector = std::vector<CefBrowserContext*>;
 
   ImplManager() {}
+
+  ImplManager(const ImplManager&) = delete;
+  ImplManager& operator=(const ImplManager&) = delete;
+
   ~ImplManager() {
     DCHECK(all_.empty());
     DCHECK(map_.empty());
@@ -73,15 +55,18 @@
   void RemoveImpl(CefBrowserContext* impl, const base::FilePath& path) {
     CEF_REQUIRE_UIT();
 
-    Vector::iterator it = GetImplPos(impl);
-    DCHECK(it != all_.end());
-    all_.erase(it);
+    {
+      Vector::iterator it = GetImplPos(impl);
+      DCHECK(it != all_.end());
+      all_.erase(it);
+    }
 
     if (!path.empty()) {
       PathMap::iterator it = map_.find(path);
       DCHECK(it != map_.end());
-      if (it != map_.end())
+      if (it != map_.end()) {
         map_.erase(it);
+      }
     }
   }
 
@@ -90,30 +75,29 @@
     return GetImplPos(impl) != all_.end();
   }
 
-  CefBrowserContext* GetImplForIDs(int render_process_id,
-                                   int render_frame_id,
-                                   int frame_tree_node_id,
-                                   bool require_frame_match) {
+  CefBrowserContext* GetImplFromGlobalId(
+      const content::GlobalRenderFrameHostId& global_id,
+      bool require_frame_match) {
     CEF_REQUIRE_UIT();
     for (const auto& context : all_) {
-      if (context->IsAssociatedContext(render_process_id, render_frame_id,
-                                       frame_tree_node_id,
-                                       require_frame_match)) {
+      if (context->IsAssociatedContext(global_id, require_frame_match)) {
         return context;
       }
     }
     return nullptr;
   }
 
-  CefBrowserContext* GetImplForContext(const content::BrowserContext* context) {
+  CefBrowserContext* GetImplFromBrowserContext(
+      const content::BrowserContext* context) {
     CEF_REQUIRE_UIT();
-    if (!context)
+    if (!context) {
       return nullptr;
+    }
 
-    Vector::iterator it = all_.begin();
-    for (; it != all_.end(); ++it) {
-      if (*it == context)
-        return *it;
+    for (const auto& bc : all_) {
+      if (bc->AsBrowserContext() == context) {
+        return bc;
+      }
     }
     return nullptr;
   }
@@ -122,16 +106,17 @@
     CEF_REQUIRE_UIT();
     DCHECK(!path.empty());
     DCHECK(IsValidImpl(impl));
-    DCHECK(GetImplForPath(path) == nullptr);
+    DCHECK(GetImplFromPath(path) == nullptr);
     map_.insert(std::make_pair(path, impl));
   }
 
-  CefBrowserContext* GetImplForPath(const base::FilePath& path) {
+  CefBrowserContext* GetImplFromPath(const base::FilePath& path) {
     CEF_REQUIRE_UIT();
     DCHECK(!path.empty());
     PathMap::const_iterator it = map_.find(path);
-    if (it != map_.end())
+    if (it != map_.end()) {
       return it->second;
+    }
     return nullptr;
   }
 
@@ -141,18 +126,17 @@
   Vector::iterator GetImplPos(const CefBrowserContext* impl) {
     Vector::iterator it = all_.begin();
     for (; it != all_.end(); ++it) {
-      if (*it == impl)
+      if (*it == impl) {
         return it;
+      }
     }
     return all_.end();
   }
 
-  typedef std::map<base::FilePath, CefBrowserContext*> PathMap;
+  using PathMap = std::map<base::FilePath, CefBrowserContext*>;
   PathMap map_;
 
   Vector all_;
-
-  DISALLOW_COPY_AND_ASSIGN(ImplManager);
 };
 
 #if DCHECK_IS_ON()
@@ -168,61 +152,41 @@
   return self.get();
 }
 
+CefBrowserContext::CookieableSchemes MakeSupportedSchemes(
+    const CefString& schemes_list,
+    bool include_defaults) {
+  if (schemes_list.empty() && include_defaults) {
+    // No explicit registration of schemes.
+    return absl::nullopt;
+  }
+
+  std::vector<std::string> all_schemes;
+  if (!schemes_list.empty()) {
+    all_schemes =
+        base::SplitString(schemes_list.ToString(), std::string(","),
+                          base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+  }
+
+  if (include_defaults) {
+    // Add default schemes that should always support cookies.
+    // This list should match CookieMonster::kDefaultCookieableSchemes.
+    all_schemes.push_back("http");
+    all_schemes.push_back("https");
+    all_schemes.push_back("ws");
+    all_schemes.push_back("wss");
+  }
+
+  return absl::make_optional(all_schemes);
+}
+
+template <typename T>
+CefBrowserContext::CookieableSchemes MakeSupportedSchemes(const T& settings) {
+  return MakeSupportedSchemes(CefString(&settings.cookieable_schemes_list),
+                              !settings.cookieable_schemes_exclude_defaults);
+}
+
 }  // namespace
 
-// Creates and manages VisitedLinkEventListener objects for each
-// CefBrowserContext sharing the same VisitedLinkWriter.
-class CefVisitedLinkListener : public visitedlink::VisitedLinkWriter::Listener {
- public:
-  CefVisitedLinkListener() { DCHECK(listener_map_.empty()); }
-
-  void CreateListenerForContext(const CefBrowserContext* context) {
-    CEF_REQUIRE_UIT();
-    auto listener = std::make_unique<visitedlink::VisitedLinkEventListener>(
-        const_cast<CefBrowserContext*>(context));
-    listener_map_.insert(std::make_pair(context, std::move(listener)));
-  }
-
-  void RemoveListenerForContext(const CefBrowserContext* context) {
-    CEF_REQUIRE_UIT();
-    ListenerMap::iterator it = listener_map_.find(context);
-    DCHECK(it != listener_map_.end());
-    listener_map_.erase(it);
-  }
-
-  // visitedlink::VisitedLinkWriter::Listener methods.
-
-  void NewTable(base::ReadOnlySharedMemoryRegion* table_region) override {
-    CEF_REQUIRE_UIT();
-    ListenerMap::iterator it = listener_map_.begin();
-    for (; it != listener_map_.end(); ++it)
-      it->second->NewTable(table_region);
-  }
-
-  void Add(visitedlink::VisitedLinkCommon::Fingerprint fingerprint) override {
-    CEF_REQUIRE_UIT();
-    ListenerMap::iterator it = listener_map_.begin();
-    for (; it != listener_map_.end(); ++it)
-      it->second->Add(fingerprint);
-  }
-
-  void Reset(bool invalidate_hashes) override {
-    CEF_REQUIRE_UIT();
-    ListenerMap::iterator it = listener_map_.begin();
-    for (; it != listener_map_.end(); ++it)
-      it->second->Reset(invalidate_hashes);
-  }
-
- private:
-  // Map of CefBrowserContext to the associated VisitedLinkEventListener.
-  typedef std::map<const CefBrowserContext*,
-                   std::unique_ptr<visitedlink::VisitedLinkEventListener>>
-      ListenerMap;
-  ListenerMap listener_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefVisitedLinkListener);
-};
-
 CefBrowserContext::CefBrowserContext(const CefRequestContextSettings& settings)
     : settings_(settings), weak_ptr_factory_(this) {
   g_manager.Get().AddImpl(this);
@@ -231,6 +195,28 @@
 
 CefBrowserContext::~CefBrowserContext() {
   CEF_REQUIRE_UIT();
+#if DCHECK_IS_ON()
+  DCHECK(is_shutdown_);
+#endif
+}
+
+void CefBrowserContext::Initialize() {
+  cache_path_ = base::FilePath(CefString(&settings_.cache_path));
+
+  if (!cache_path_.empty()) {
+    g_manager.Get().SetImplPath(this, cache_path_);
+  }
+
+  iothread_state_ = base::MakeRefCounted<CefIOThreadState>();
+  cookieable_schemes_ = MakeSupportedSchemes(settings_);
+}
+
+void CefBrowserContext::Shutdown() {
+  CEF_REQUIRE_UIT();
+
+#if DCHECK_IS_ON()
+  is_shutdown_ = true;
+#endif
 
   // No CefRequestContext should be referencing this object any longer.
   DCHECK(request_context_set_.empty());
@@ -241,122 +227,8 @@
   // Destroy objects that may hold references to the MediaRouter.
   media_router_manager_.reset();
 
-  // Send notifications to clean up objects associated with this Profile.
-  MaybeSendDestroyedNotification();
-
-  ChromePluginServiceFilter::GetInstance()->UnregisterProfile(this);
-
-  // Remove any BrowserContextKeyedServiceFactory associations. This must be
-  // called before the ProxyService owned by CefBrowserContext is destroyed.
-  // The SimpleDependencyManager should always be passed after the
-  // BrowserContextDependencyManager. This is because the KeyedService instances
-  // in the BrowserContextDependencyManager's dependency graph can depend on the
-  // ones in the SimpleDependencyManager's graph.
-  DependencyManager::PerformInterlockedTwoPhaseShutdown(
-      BrowserContextDependencyManager::GetInstance(), this,
-      SimpleDependencyManager::GetInstance(), key_.get());
-
-  key_.reset();
-  SimpleKeyMap::GetInstance()->Dissociate(this);
-
-  // Shuts down the storage partitions associated with this browser context.
-  // This must be called before the browser context is actually destroyed
-  // and before a clean-up task for its corresponding IO thread residents
-  // (e.g. ResourceContext) is posted, so that the classes that hung on
-  // StoragePartition can have time to do necessary cleanups on IO thread.
-  ShutdownStoragePartitions();
-
-  if (resource_context_.get()) {
-    // Destruction of the ResourceContext will trigger destruction of all
-    // associated network requests.
-    content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE,
-                                       resource_context_.release());
-  }
-
-  visitedlink_listener_->RemoveListenerForContext(this);
-
-  // The FontFamilyCache references the ProxyService so delete it before the
-  // ProxyService is deleted.
-  SetUserData(&kFontFamilyCacheKey, nullptr);
-
-  pref_proxy_config_tracker_->DetachFromPrefService();
-
-  if (host_content_settings_map_)
-    host_content_settings_map_->ShutdownOnUIThread();
-
-  // Delete the download manager delegate here because otherwise we'll crash
-  // when it's accessed from the content::BrowserContext destructor.
-  if (download_manager_delegate_)
-    download_manager_delegate_.reset(nullptr);
-}
-
-void CefBrowserContext::Initialize() {
-  cache_path_ = base::FilePath(CefString(&settings_.cache_path));
-
-  if (!cache_path_.empty())
-    g_manager.Get().SetImplPath(this, cache_path_);
-
-  if (!!settings_.persist_session_cookies) {
-    set_should_persist_session_cookies(true);
-  }
-
-  key_ = std::make_unique<ProfileKey>(cache_path_);
-  SimpleKeyMap::GetInstance()->Associate(this, key_.get());
-
-  // Initialize the PrefService object.
-  pref_service_ = browser_prefs::CreatePrefService(
-      this, cache_path_, !!settings_.persist_user_preferences);
-
-  content::BrowserContext::Initialize(this, cache_path_);
-
-  resource_context_.reset(new CefResourceContext(IsOffTheRecord()));
-
-  // This must be called before creating any services to avoid hitting
-  // DependencyManager::AssertContextWasntDestroyed when creating/destroying
-  // multiple browser contexts (due to pointer address reuse).
-  BrowserContextDependencyManager::GetInstance()->CreateBrowserContextServices(
-      this);
-
-  const bool extensions_enabled = extensions::ExtensionsEnabled();
-  if (extensions_enabled) {
-    // Create the custom ExtensionSystem first because other KeyedServices
-    // depend on it.
-    extension_system_ = static_cast<extensions::CefExtensionSystem*>(
-        extensions::ExtensionSystem::Get(this));
-    extension_system_->InitForRegularProfile(true);
-
-    // Make sure the ProcessManager is created so that it receives extension
-    // load notifications. This is necessary for the proper initialization of
-    // background/event pages.
-    extensions::ProcessManager::Get(this);
-  }
-
-  // Initialize visited links management.
-  base::FilePath visited_link_path;
-  if (!cache_path_.empty())
-    visited_link_path = cache_path_.Append(FILE_PATH_LITERAL("Visited Links"));
-  visitedlink_listener_ = new CefVisitedLinkListener;
-  visitedlink_master_.reset(new visitedlink::VisitedLinkWriter(
-      visitedlink_listener_, this, !visited_link_path.empty(), false,
-      visited_link_path, 0));
-  visitedlink_listener_->CreateListenerForContext(this);
-  visitedlink_master_->Init();
-
-  // Initialize proxy configuration tracker.
-  pref_proxy_config_tracker_.reset(new PrefProxyConfigTrackerImpl(
-      GetPrefs(), base::CreateSingleThreadTaskRunner({BrowserThread::IO})));
-
-  // Spell checking support and possibly other subsystems retrieve the
-  // PrefService associated with a BrowserContext via UserPrefs::Get().
-  PrefService* pref_service = GetPrefs();
-  DCHECK(pref_service);
-  user_prefs::UserPrefs::Set(this, pref_service);
-  key_->SetPrefs(pref_service);
-
-  if (extensions_enabled)
-    extension_system_->Init();
-
-  ChromePluginServiceFilter::GetInstance()->RegisterProfile(this);
+  // Invalidate any Getter references to this object.
+  weak_ptr_factory_.InvalidateWeakPtrs();
 }
 
 void CefBrowserContext::AddCefRequestContext(CefRequestContextImpl* context) {
@@ -368,36 +240,54 @@
     CefRequestContextImpl* context) {
   CEF_REQUIRE_UIT();
 
-  if (extensions::ExtensionsEnabled()) {
-    extension_system()->OnRequestContextDeleted(context);
-  }
-
   request_context_set_.erase(context);
 
   // Delete ourselves when the reference count reaches zero.
-  if (request_context_set_.empty())
-    delete this;
+  if (request_context_set_.empty()) {
+    Shutdown();
+
+    // Allow the current call stack to unwind before deleting |this|.
+    content::BrowserThread::DeleteSoon(CEF_UIT, FROM_HERE, this);
+  }
 }
 
 // static
-CefBrowserContext* CefBrowserContext::GetForCachePath(
+CefBrowserContext* CefBrowserContext::FromCachePath(
     const base::FilePath& cache_path) {
-  return g_manager.Get().GetImplForPath(cache_path);
+  return g_manager.Get().GetImplFromPath(cache_path);
 }
 
 // static
-CefBrowserContext* CefBrowserContext::GetForIDs(int render_process_id,
-                                                int render_frame_id,
-                                                int frame_tree_node_id,
-                                                bool require_frame_match) {
-  return g_manager.Get().GetImplForIDs(render_process_id, render_frame_id,
-                                       frame_tree_node_id, require_frame_match);
+CefBrowserContext* CefBrowserContext::FromGlobalId(
+    const content::GlobalRenderFrameHostId& global_id,
+    bool require_frame_match) {
+  return g_manager.Get().GetImplFromGlobalId(global_id, require_frame_match);
 }
 
 // static
-CefBrowserContext* CefBrowserContext::GetForContext(
-    content::BrowserContext* context) {
-  return g_manager.Get().GetImplForContext(context);
+CefBrowserContext* CefBrowserContext::FromBrowserContext(
+    const content::BrowserContext* context) {
+  return g_manager.Get().GetImplFromBrowserContext(context);
+}
+
+// static
+CefBrowserContext* CefBrowserContext::FromProfile(const Profile* profile) {
+  auto* cef_context = FromBrowserContext(profile);
+  if (cef_context) {
+    return cef_context;
+  }
+
+  if (cef::IsChromeRuntimeEnabled()) {
+    auto* original_profile = profile->GetOriginalProfile();
+    if (original_profile != profile) {
+      // With the Chrome runtime if the user launches an incognito window via
+      // the UI we might be associated with the original Profile instead of the
+      // (current) incognito profile.
+      return FromBrowserContext(original_profile);
+    }
+  }
+
+  return nullptr;
 }
 
 // static
@@ -405,413 +295,151 @@
   return g_manager.Get().GetAllImpl();
 }
 
-content::ResourceContext* CefBrowserContext::GetResourceContext() {
-  return resource_context_.get();
-}
-
-content::ClientHintsControllerDelegate*
-CefBrowserContext::GetClientHintsControllerDelegate() {
-  return nullptr;
-}
-
-void CefBrowserContext::SetCorsOriginAccessListForOrigin(
-    const url::Origin& source_origin,
-    std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
-    std::vector<network::mojom::CorsOriginPatternPtr> block_patterns,
-    base::OnceClosure closure) {
-  // This method is called for Extension support.
-  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(closure));
-}
-
-ChromeZoomLevelPrefs* CefBrowserContext::GetZoomLevelPrefs() {
-  return static_cast<ChromeZoomLevelPrefs*>(
-      GetStoragePartition(this, nullptr)->GetZoomLevelDelegate());
-}
-
-scoped_refptr<network::SharedURLLoaderFactory>
-CefBrowserContext::GetURLLoaderFactory() {
-  return GetDefaultStoragePartition(this)
-      ->GetURLLoaderFactoryForBrowserProcess();
-}
-
-base::FilePath CefBrowserContext::GetPath() {
-  return cache_path_;
-}
-
-base::FilePath CefBrowserContext::GetPath() const {
-  return cache_path_;
-}
-
-std::unique_ptr<content::ZoomLevelDelegate>
-CefBrowserContext::CreateZoomLevelDelegate(
-    const base::FilePath& partition_path) {
-  if (cache_path_.empty())
-    return std::unique_ptr<content::ZoomLevelDelegate>();
-
-  return base::WrapUnique(new ChromeZoomLevelPrefs(
-      GetPrefs(), cache_path_, partition_path,
-      zoom::ZoomEventManager::GetForBrowserContext(this)->GetWeakPtr()));
-}
-
-bool CefBrowserContext::IsOffTheRecord() const {
-  // CEF contexts are never flagged as off-the-record. It causes problems
-  // for the extension system.
-  return false;
-}
-
-content::DownloadManagerDelegate*
-CefBrowserContext::GetDownloadManagerDelegate() {
-  if (!download_manager_delegate_) {
-    content::DownloadManager* manager =
-        BrowserContext::GetDownloadManager(this);
-    download_manager_delegate_.reset(new CefDownloadManagerDelegate(manager));
-  }
-  return download_manager_delegate_.get();
-}
-
-content::BrowserPluginGuestManager* CefBrowserContext::GetGuestManager() {
-  DCHECK(extensions::ExtensionsEnabled());
-  return guest_view::GuestViewManager::FromBrowserContext(this);
-}
-
-storage::SpecialStoragePolicy* CefBrowserContext::GetSpecialStoragePolicy() {
-  return nullptr;
-}
-
-content::PushMessagingService* CefBrowserContext::GetPushMessagingService() {
-  return nullptr;
-}
-
-content::StorageNotificationService*
-CefBrowserContext::GetStorageNotificationService() {
-  return nullptr;
-}
-
-content::SSLHostStateDelegate* CefBrowserContext::GetSSLHostStateDelegate() {
-  if (!ssl_host_state_delegate_.get())
-    ssl_host_state_delegate_.reset(new CefSSLHostStateDelegate());
-  return ssl_host_state_delegate_.get();
-}
-
-content::PermissionControllerDelegate*
-CefBrowserContext::GetPermissionControllerDelegate() {
-  return nullptr;
-}
-
-content::BackgroundFetchDelegate*
-CefBrowserContext::GetBackgroundFetchDelegate() {
-  return nullptr;
-}
-
-content::BackgroundSyncController*
-CefBrowserContext::GetBackgroundSyncController() {
-  return nullptr;
-}
-
-content::BrowsingDataRemoverDelegate*
-CefBrowserContext::GetBrowsingDataRemoverDelegate() {
-  return nullptr;
-}
-
-PrefService* CefBrowserContext::GetPrefs() {
-  return pref_service_.get();
-}
-
-const PrefService* CefBrowserContext::GetPrefs() const {
-  return pref_service_.get();
-}
-
-ProfileKey* CefBrowserContext::GetProfileKey() const {
-  DCHECK(key_);
-  return key_.get();
-}
-
-policy::SchemaRegistryService*
-CefBrowserContext::GetPolicySchemaRegistryService() {
-  NOTREACHED();
-  return nullptr;
-}
-
-policy::UserCloudPolicyManager* CefBrowserContext::GetUserCloudPolicyManager() {
-  NOTREACHED();
-  return nullptr;
-}
-
-policy::ProfilePolicyConnector* CefBrowserContext::GetProfilePolicyConnector() {
-  NOTREACHED();
-  return nullptr;
-}
-
-const policy::ProfilePolicyConnector*
-CefBrowserContext::GetProfilePolicyConnector() const {
-  NOTREACHED();
-  return nullptr;
-}
-
-const CefRequestContextSettings& CefBrowserContext::GetSettings() const {
-  return settings_;
-}
-
-HostContentSettingsMap* CefBrowserContext::GetHostContentSettingsMap() {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (!host_content_settings_map_.get()) {
-    // The |is_incognito_profile| and |is_guest_profile| arguments are
-    // intentionally set to false as they otherwise limit the types of values
-    // that can be stored in the settings map (for example, default values set
-    // via DefaultProvider::SetWebsiteSetting).
-    host_content_settings_map_ =
-        new HostContentSettingsMap(GetPrefs(), false, false, false);
-
-    // Change the default plugin policy.
-    const base::CommandLine* command_line =
-        base::CommandLine::ForCurrentProcess();
-    const std::string& plugin_policy_str =
-        command_line->GetSwitchValueASCII(switches::kPluginPolicy);
-    if (!plugin_policy_str.empty()) {
-      ContentSetting plugin_policy = CONTENT_SETTING_ALLOW;
-      if (base::LowerCaseEqualsASCII(plugin_policy_str,
-                                     switches::kPluginPolicy_Detect)) {
-        plugin_policy = CONTENT_SETTING_DETECT_IMPORTANT_CONTENT;
-      } else if (base::LowerCaseEqualsASCII(plugin_policy_str,
-                                            switches::kPluginPolicy_Block)) {
-        plugin_policy = CONTENT_SETTING_BLOCK;
-      }
-      host_content_settings_map_->SetDefaultContentSetting(
-          ContentSettingsType::PLUGINS, plugin_policy);
-    }
-  }
-  return host_content_settings_map_.get();
-}
-
-void CefBrowserContext::AddVisitedURLs(const std::vector<GURL>& urls) {
-  visitedlink_master_->AddURLs(urls);
-}
-
-void CefBrowserContext::RebuildTable(
-    const scoped_refptr<URLEnumerator>& enumerator) {
-  // Called when visited links will not or cannot be loaded from disk.
-  enumerator->OnComplete(true);
-}
-
 void CefBrowserContext::OnRenderFrameCreated(
     CefRequestContextImpl* request_context,
-    int render_process_id,
-    int render_frame_id,
-    int frame_tree_node_id,
+    const content::GlobalRenderFrameHostId& global_id,
     bool is_main_frame,
     bool is_guest_view) {
   CEF_REQUIRE_UIT();
-  DCHECK_GE(render_process_id, 0);
-  DCHECK_GE(render_frame_id, 0);
-  DCHECK_GE(frame_tree_node_id, 0);
+  DCHECK(frame_util::IsValidGlobalId(global_id));
 
-  render_id_set_.insert(std::make_pair(render_process_id, render_frame_id));
-  node_id_set_.insert(frame_tree_node_id);
+  render_id_set_.insert(global_id);
 
   CefRefPtr<CefRequestContextHandler> handler = request_context->GetHandler();
   if (handler) {
-    handler_map_.AddHandler(render_process_id, render_frame_id,
-                            frame_tree_node_id, handler);
+    handler_map_.AddHandler(global_id, handler);
 
-    if (resource_context_) {
-      // Using base::Unretained() is safe because both this callback and
-      // possible deletion of |resource_context_| will execute on the IO thread,
-      // and this callback will be executed first.
-      CEF_POST_TASK(CEF_IOT,
-                    base::Bind(&CefResourceContext::AddHandler,
-                               base::Unretained(resource_context_.get()),
-                               render_process_id, render_frame_id,
-                               frame_tree_node_id, handler));
-    }
+    CEF_POST_TASK(CEF_IOT, base::BindOnce(&CefIOThreadState::AddHandler,
+                                          iothread_state_, global_id, handler));
   }
 }
 
 void CefBrowserContext::OnRenderFrameDeleted(
     CefRequestContextImpl* request_context,
-    int render_process_id,
-    int render_frame_id,
-    int frame_tree_node_id,
+    const content::GlobalRenderFrameHostId& global_id,
     bool is_main_frame,
     bool is_guest_view) {
   CEF_REQUIRE_UIT();
-  DCHECK_GE(render_process_id, 0);
-  DCHECK_GE(render_frame_id, 0);
-  DCHECK_GE(frame_tree_node_id, 0);
+  DCHECK(frame_util::IsValidGlobalId(global_id));
 
-  auto it1 =
-      render_id_set_.find(std::make_pair(render_process_id, render_frame_id));
-  if (it1 != render_id_set_.end())
+  auto it1 = render_id_set_.find(global_id);
+  if (it1 != render_id_set_.end()) {
     render_id_set_.erase(it1);
-
-  auto it2 = node_id_set_.find(frame_tree_node_id);
-  if (it2 != node_id_set_.end())
-    node_id_set_.erase(it2);
+  }
 
   CefRefPtr<CefRequestContextHandler> handler = request_context->GetHandler();
   if (handler) {
-    handler_map_.RemoveHandler(render_process_id, render_frame_id,
-                               frame_tree_node_id);
+    handler_map_.RemoveHandler(global_id);
 
-    if (resource_context_) {
-      // Using base::Unretained() is safe because both this callback and
-      // possible deletion of |resource_context_| will execute on the IO thread,
-      // and this callback will be executed first.
-      CEF_POST_TASK(
-          CEF_IOT,
-          base::Bind(&CefResourceContext::RemoveHandler,
-                     base::Unretained(resource_context_.get()),
-                     render_process_id, render_frame_id, frame_tree_node_id));
-    }
-  }
-
-  if (is_main_frame) {
-    ClearPluginLoadDecision(render_process_id);
+    CEF_POST_TASK(CEF_IOT, base::BindOnce(&CefIOThreadState::RemoveHandler,
+                                          iothread_state_, global_id));
   }
 }
 
 CefRefPtr<CefRequestContextHandler> CefBrowserContext::GetHandler(
-    int render_process_id,
-    int render_frame_id,
-    int frame_tree_node_id,
+    const content::GlobalRenderFrameHostId& global_id,
     bool require_frame_match) const {
   CEF_REQUIRE_UIT();
-  return handler_map_.GetHandler(render_process_id, render_frame_id,
-                                 frame_tree_node_id, require_frame_match);
+  return handler_map_.GetHandler(global_id, require_frame_match);
 }
 
-bool CefBrowserContext::IsAssociatedContext(int render_process_id,
-                                            int render_frame_id,
-                                            int frame_tree_node_id,
-                                            bool require_frame_match) const {
+bool CefBrowserContext::IsAssociatedContext(
+    const content::GlobalRenderFrameHostId& global_id,
+    bool require_frame_match) const {
   CEF_REQUIRE_UIT();
 
-  if (render_process_id >= 0 && render_frame_id >= 0) {
-    const auto it1 =
-        render_id_set_.find(std::make_pair(render_process_id, render_frame_id));
-    if (it1 != render_id_set_.end())
+  if (frame_util::IsValidGlobalId(global_id)) {
+    const auto it1 = render_id_set_.find(global_id);
+    if (it1 != render_id_set_.end()) {
       return true;
+    }
   }
 
-  if (frame_tree_node_id >= 0) {
-    const auto it2 = node_id_set_.find(frame_tree_node_id);
-    if (it2 != node_id_set_.end())
-      return true;
-  }
-
-  if (render_process_id >= 0 && !require_frame_match) {
+  if (frame_util::IsValidChildId(global_id.child_id) && !require_frame_match) {
     // Choose an arbitrary handler for the same process.
     for (const auto& render_ids : render_id_set_) {
-      if (render_ids.first == render_process_id)
+      if (render_ids.child_id == global_id.child_id) {
         return true;
+      }
     }
   }
 
   return false;
 }
 
-void CefBrowserContext::AddPluginLoadDecision(
-    int render_process_id,
-    const base::FilePath& plugin_path,
-    bool is_main_frame,
-    const url::Origin& main_frame_origin,
-    chrome::mojom::PluginStatus status) {
-  CEF_REQUIRE_UIT();
-  DCHECK_GE(render_process_id, 0);
-  DCHECK(!plugin_path.empty());
-
-  plugin_load_decision_map_.insert(std::make_pair(
-      std::make_pair(std::make_pair(render_process_id, plugin_path),
-                     std::make_pair(is_main_frame, main_frame_origin)),
-      status));
-}
-
-bool CefBrowserContext::HasPluginLoadDecision(
-    int render_process_id,
-    const base::FilePath& plugin_path,
-    bool is_main_frame,
-    const url::Origin& main_frame_origin,
-    chrome::mojom::PluginStatus* status) const {
-  CEF_REQUIRE_UIT();
-  DCHECK_GE(render_process_id, 0);
-  DCHECK(!plugin_path.empty());
-
-  PluginLoadDecisionMap::const_iterator it = plugin_load_decision_map_.find(
-      std::make_pair(std::make_pair(render_process_id, plugin_path),
-                     std::make_pair(is_main_frame, main_frame_origin)));
-  if (it == plugin_load_decision_map_.end())
-    return false;
-
-  *status = it->second;
-  return true;
-}
-
-void CefBrowserContext::ClearPluginLoadDecision(int render_process_id) {
-  CEF_REQUIRE_UIT();
-
-  if (render_process_id == -1) {
-    plugin_load_decision_map_.clear();
-  } else {
-    PluginLoadDecisionMap::iterator it = plugin_load_decision_map_.begin();
-    while (it != plugin_load_decision_map_.end()) {
-      if (it->first.first.first == render_process_id)
-        it = plugin_load_decision_map_.erase(it);
-      else
-        ++it;
-    }
-  }
-}
-
 void CefBrowserContext::RegisterSchemeHandlerFactory(
-    const std::string& scheme_name,
-    const std::string& domain_name,
+    const CefString& scheme_name,
+    const CefString& domain_name,
     CefRefPtr<CefSchemeHandlerFactory> factory) {
-  if (resource_context_) {
-    // Using base::Unretained() is safe because both this callback and possible
-    // deletion of |resource_context_| will execute on the IO thread, and this
-    // callback will be executed first.
-    CEF_POST_TASK(CEF_IOT,
-                  base::Bind(&CefResourceContext::RegisterSchemeHandlerFactory,
-                             base::Unretained(resource_context_.get()),
-                             scheme_name, domain_name, factory));
-  }
+  CEF_POST_TASK(
+      CEF_IOT,
+      base::BindOnce(&CefIOThreadState::RegisterSchemeHandlerFactory,
+                     iothread_state_, scheme_name, domain_name, factory));
 }
 
 void CefBrowserContext::ClearSchemeHandlerFactories() {
-  if (resource_context_) {
-    // Using base::Unretained() is safe because both this callback and possible
-    // deletion of |resource_context_| will execute on the IO thread, and this
-    // callback will be executed first.
-    CEF_POST_TASK(CEF_IOT,
-                  base::Bind(&CefResourceContext::ClearSchemeHandlerFactories,
-                             base::Unretained(resource_context_.get())));
+  CEF_POST_TASK(CEF_IOT,
+                base::BindOnce(&CefIOThreadState::ClearSchemeHandlerFactories,
+                               iothread_state_));
+}
+
+void CefBrowserContext::LoadExtension(
+    const CefString& root_directory,
+    CefRefPtr<CefDictionaryValue> manifest,
+    CefRefPtr<CefExtensionHandler> handler,
+    CefRefPtr<CefRequestContext> loader_context) {
+  NOTIMPLEMENTED();
+  if (handler) {
+    handler->OnExtensionLoadFailed(ERR_ABORTED);
   }
 }
 
+bool CefBrowserContext::GetExtensions(std::vector<CefString>& extension_ids) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+CefRefPtr<CefExtension> CefBrowserContext::GetExtension(
+    const CefString& extension_id) {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
+bool CefBrowserContext::UnloadExtension(const CefString& extension_id) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool CefBrowserContext::IsPrintPreviewSupported() const {
+  return true;
+}
+
 network::mojom::NetworkContext* CefBrowserContext::GetNetworkContext() {
   CEF_REQUIRE_UIT();
-  return GetDefaultStoragePartition(this)->GetNetworkContext();
-}
-
-DownloadPrefs* CefBrowserContext::GetDownloadPrefs() {
-  CEF_REQUIRE_UIT();
-  if (!download_prefs_) {
-    download_prefs_.reset(new DownloadPrefs(this));
-  }
-  return download_prefs_.get();
-}
-
-bool CefBrowserContext::IsPrintPreviewSupported() const {
-  CEF_REQUIRE_UIT();
-  if (!extensions::PrintPreviewEnabled())
-    return false;
-
-  return !GetPrefs()->GetBoolean(prefs::kPrintPreviewDisabled);
+  auto browser_context = AsBrowserContext();
+  return browser_context->GetDefaultStoragePartition()->GetNetworkContext();
 }
 
 CefMediaRouterManager* CefBrowserContext::GetMediaRouterManager() {
   CEF_REQUIRE_UIT();
   if (!media_router_manager_) {
-    media_router_manager_.reset(new CefMediaRouterManager(this));
+    media_router_manager_.reset(new CefMediaRouterManager(AsBrowserContext()));
   }
   return media_router_manager_.get();
 }
+
+CefBrowserContext::CookieableSchemes CefBrowserContext::GetCookieableSchemes()
+    const {
+  CEF_REQUIRE_UIT();
+  return cookieable_schemes_;
+}
+
+// static
+CefBrowserContext::CookieableSchemes
+CefBrowserContext::GetGlobalCookieableSchemes() {
+  CEF_REQUIRE_UIT();
+
+  static base::NoDestructor<CookieableSchemes> schemes(
+      []() { return MakeSupportedSchemes(CefContext::Get()->settings()); }());
+  return *schemes;
+}
diff --git a/src/libcef/browser/browser_context.h b/src/libcef/browser/browser_context.h
index 232de11..8da7995 100644
--- a/src/libcef/browser/browser_context.h
+++ b/src/libcef/browser/browser_context.h
@@ -7,23 +7,19 @@
 #pragma once
 
 #include <set>
+#include <vector>
 
 #include "include/cef_request_context_handler.h"
-#include "libcef/browser/chrome_profile_stub.h"
+#include "libcef/browser/iothread_state.h"
 #include "libcef/browser/request_context_handler_map.h"
-#include "libcef/browser/resource_context.h"
 
-#include "base/callback.h"
 #include "base/files/file_path.h"
-#include "base/memory/ref_counted.h"
+#include "base/functional/callback.h"
 #include "base/memory/weak_ptr.h"
-#include "chrome/browser/download/download_prefs.h"
+#include "base/task/sequenced_task_runner_helpers.h"
 #include "chrome/common/plugin.mojom.h"
-#include "components/proxy_config/pref_proxy_config_tracker.h"
-#include "components/visitedlink/browser/visitedlink_delegate.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
+#include "services/network/public/mojom/network_context.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/origin.h"
 
 /*
@@ -31,31 +27,30 @@
 //
 // WC = WebContents
 //  Content API representation of a browser. Created by BHI or the system (for
-//  popups) and owned by BHI. Keeps a pointer to BC.
+//  popups) and owned by BHI. Keeps a pointer to the content::BrowserContext.
 //
-// BHI = CefBrowserHostImpl
+// BHI = AlloyBrowserHostImpl
 //  Implements the CefBrowser and CefBrowserHost interfaces which are exposed
-//  to clients. References an RCI instance. Owns a WC. Life span is controlled
-//  by client references and CefContentBrowserClient.
+//  to clients. References an RCI instance. Owns a WC. Lifespan is controlled
+//  by client references and CefBrowserInfoManager (until the browser has
+//  closed).
 //
 // RCI = CefRequestContextImpl
 //  Implements the CefRequestContext interface which is exposed to clients.
-//  References the isolated BC.
+//  Creates or references a BC. Lifespan is controlled by client references and
+//  BrowserMainParts (for the global RCI).
 //
 // BC = CefBrowserContext
-//   Entry point from WC when using an isolated RCI. Owns the RC and creates the
-//   SPI indirectly. Owned by CefBrowserMainParts for the global context or RCI
-//   for non-global contexts.
+//   Is/owns the content::BrowserContext which is the entry point from WC.
+//   Owns the IOTS and creates the SPI indirectly. Potentially shared by
+//   multiple RCI. Deletes itself when no longer needed by RCI.
 //
 // SPI = content::StoragePartitionImpl
 //   Owns storage-related objects like Quota, IndexedDB, Cache, etc. Created by
-//   StoragePartitionImplMap::Get(). Provides access to the URCG. Life span is
-//   controlled indirectly by BC.
+//   StoragePartitionImplMap::Get(). Life span is controlled indirectly by BC.
 //
-// RC = CefResourceContext
-//   Acts as a bridge for resource loading. Network request life span is tied to
-//   this object. Must be destroyed before the associated URCG. Life span is
-//   controlled by BC.
+// IOTS = CefIOThreadState
+//   Stores state for access on the IO thread. Life span is controlled by BC.
 //
 //
 // Relationship diagram:
@@ -63,156 +58,85 @@
 //   own = ownership (std::unique_ptr)
 //   ptr = raw pointer
 //
-//               CefBrowserMainParts
-//                       |
-//                      own
-//                       v
-// BHI -own-> WC -ptr-> BC -own-> SPI
-//
-// BHI -ref-> RCI -own-> BC -own-> RC
+// BHI -ref-> RCI -ptr-> BC -own-> SPI, IOTS
+//                      ^
+// BHI -own-> WC -ptr--/
 //
 //
 // How shutdown works:
-// 1. CefBrowserHostImpl is destroyed on any thread due to browser close,
-//    ref release, etc.
+// 1. AlloyBrowserHostImpl::DestroyBrowser is called on the UI thread after the
+//    browser is closed and deletes the WebContents.
+// 1. AlloyBrowserHostImpl is destroyed on any thread when the last reference
+//    is released.
 // 2. CefRequestContextImpl is destroyed (possibly asynchronously) on the UI
-//    thread due to CefBrowserHostImpl destruction, ref release, etc.
-// 3. CefBrowserContext is destroyed on the UI thread due to
-//    CefRequestContextImpl destruction or deletion in
-//    CefBrowserMainParts::PostMainMessageLoopRun().
-// 4. CefResourceContext is destroyed asynchronously on the IO thread due to
-//    CefBrowserContext destruction. This cancels/destroys any pending
-//    network requests.
+//    thread when the last reference is released.
+// 3. CefBrowserContext is destroyed on the UI thread when no longer needed
+//    by any CefRequestContextImpl (via RemoveCefRequestContext).
+// 4. CefIOThreadState is destroyed asynchronously on the IO thread after
+//    the owning CefBrowserContext is destroyed.
 */
 
-class CefDownloadManagerDelegate;
+namespace content {
+class BrowserContext;
+struct GlobalRenderFrameHostId;
+}  // namespace content
+
 class CefMediaRouterManager;
 class CefRequestContextImpl;
-class CefSSLHostStateDelegate;
-class CefVisitedLinkListener;
-class HostContentSettingsMap;
-class PrefService;
+class Profile;
 
-namespace extensions {
-class CefExtensionSystem;
-}
-
-namespace visitedlink {
-class VisitedLinkWriter;
-}
-
-// Main entry point for configuring behavior on a per-browser basis. An instance
-// of this class is passed to WebContents::Create in CefBrowserHostImpl::
-// CreateInternal. Only accessed on the UI thread unless otherwise indicated.
-class CefBrowserContext : public ChromeProfileStub,
-                          public visitedlink::VisitedLinkDelegate {
+// Main entry point for configuring behavior on a per-RequestContext basis. The
+// content::BrowserContext represented by this class is passed to
+// WebContents::Create in AlloyBrowserHostImpl::CreateInternal. Only accessed on
+// the UI thread unless otherwise indicated.
+class CefBrowserContext {
  public:
-  explicit CefBrowserContext(const CefRequestContextSettings& settings);
+  CefBrowserContext(const CefBrowserContext&) = delete;
+  CefBrowserContext& operator=(const CefBrowserContext&) = delete;
 
   // Returns the existing instance, if any, associated with the specified
   // |cache_path|.
-  static CefBrowserContext* GetForCachePath(const base::FilePath& cache_path);
+  static CefBrowserContext* FromCachePath(const base::FilePath& cache_path);
 
   // Returns the existing instance, if any, associated with the specified IDs.
   // See comments on IsAssociatedContext() for usage.
-  static CefBrowserContext* GetForIDs(int render_process_id,
-                                      int render_frame_id,
-                                      int frame_tree_node_id,
-                                      bool require_frame_match);
+  static CefBrowserContext* FromGlobalId(
+      const content::GlobalRenderFrameHostId& global_id,
+      bool require_frame_match);
 
   // Returns the underlying CefBrowserContext if any.
-  static CefBrowserContext* GetForContext(content::BrowserContext* context);
+  static CefBrowserContext* FromBrowserContext(
+      const content::BrowserContext* context);
+  static CefBrowserContext* FromProfile(const Profile* profile);
 
   // Returns all existing CefBrowserContext.
   static std::vector<CefBrowserContext*> GetAll();
 
-  // Must be called immediately after this object is created.
-  void Initialize();
+  // Returns the content and chrome layer representations of the context.
+  virtual content::BrowserContext* AsBrowserContext() = 0;
+  virtual Profile* AsProfile() = 0;
 
-  // Track associated CefRequestContextImpl objects. This object will delete
-  // itself when the count reaches zero.
+  // Returns true if the context is fully initialized.
+  virtual bool IsInitialized() const = 0;
+
+  // If the context is fully initialized execute |callback|, otherwise
+  // store it until the context is fully initialized.
+  virtual void StoreOrTriggerInitCallback(base::OnceClosure callback) = 0;
+
+  // Called from CefRequestContextImpl to track associated objects. This
+  // object will delete itself when the count reaches zero.
   void AddCefRequestContext(CefRequestContextImpl* context);
-  void RemoveCefRequestContext(CefRequestContextImpl* context);
-
-  // BrowserContext methods.
-  content::ResourceContext* GetResourceContext() override;
-  content::ClientHintsControllerDelegate* GetClientHintsControllerDelegate()
-      override;
-  void SetCorsOriginAccessListForOrigin(
-      const url::Origin& source_origin,
-      std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns,
-      std::vector<network::mojom::CorsOriginPatternPtr> block_patterns,
-      base::OnceClosure closure) override;
-  base::FilePath GetPath() override;
-  base::FilePath GetPath() const override;
-  std::unique_ptr<content::ZoomLevelDelegate> CreateZoomLevelDelegate(
-      const base::FilePath& partition_path) override;
-  bool IsOffTheRecord() const override;
-  content::DownloadManagerDelegate* GetDownloadManagerDelegate() override;
-  content::BrowserPluginGuestManager* GetGuestManager() override;
-  storage::SpecialStoragePolicy* GetSpecialStoragePolicy() override;
-  content::PushMessagingService* GetPushMessagingService() override;
-  content::StorageNotificationService* GetStorageNotificationService() override;
-  content::SSLHostStateDelegate* GetSSLHostStateDelegate() override;
-  content::PermissionControllerDelegate* GetPermissionControllerDelegate()
-      override;
-  content::BackgroundFetchDelegate* GetBackgroundFetchDelegate() override;
-  content::BackgroundSyncController* GetBackgroundSyncController() override;
-  content::BrowsingDataRemoverDelegate* GetBrowsingDataRemoverDelegate()
-      override;
-
-  // Profile methods.
-  ChromeZoomLevelPrefs* GetZoomLevelPrefs() override;
-  scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
-  PrefService* GetPrefs() override;
-  bool AllowsBrowserWindows() const override { return false; }
-  const PrefService* GetPrefs() const override;
-  ProfileKey* GetProfileKey() const override;
-  policy::SchemaRegistryService* GetPolicySchemaRegistryService() override;
-  policy::UserCloudPolicyManager* GetUserCloudPolicyManager() override;
-  policy::ProfilePolicyConnector* GetProfilePolicyConnector() override;
-  const policy::ProfilePolicyConnector* GetProfilePolicyConnector()
-      const override;
-
-  // Values checked in ProfileNetworkContextService::CreateNetworkContextParams
-  // when creating the NetworkContext.
-  bool ShouldRestoreOldSessionCookies() override {
-    return should_persist_session_cookies_;
-  }
-  bool ShouldPersistSessionCookies() override {
-    return should_persist_session_cookies_;
-  }
-  base::Optional<std::vector<std::string>> GetCookieableSchemes() override {
-    return cookieable_schemes_;
-  }
-
-  // visitedlink::VisitedLinkDelegate methods.
-  void RebuildTable(const scoped_refptr<URLEnumerator>& enumerator) override;
-
-  // Returns the settings associated with this object. Safe to call from any
-  // thread.
-  const CefRequestContextSettings& GetSettings() const;
-
-  // Settings for plugins and extensions.
-  HostContentSettingsMap* GetHostContentSettingsMap();
-
-  // Called from CefBrowserHostImpl::DidNavigateAnyFrame to update the table of
-  // visited links.
-  void AddVisitedURLs(const std::vector<GURL>& urls);
+  virtual void RemoveCefRequestContext(CefRequestContextImpl* context);
 
   // Called from CefRequestContextImpl::OnRenderFrameCreated.
   void OnRenderFrameCreated(CefRequestContextImpl* request_context,
-                            int render_process_id,
-                            int render_frame_id,
-                            int frame_tree_node_id,
+                            const content::GlobalRenderFrameHostId& global_id,
                             bool is_main_frame,
                             bool is_guest_view);
 
   // Called from CefRequestContextImpl::OnRenderFrameDeleted.
   void OnRenderFrameDeleted(CefRequestContextImpl* request_context,
-                            int render_process_id,
-                            int render_frame_id,
-                            int frame_tree_node_id,
+                            const content::GlobalRenderFrameHostId& global_id,
                             bool is_main_frame,
                             bool is_guest_view);
 
@@ -222,138 +146,98 @@
   // match, then the first handler for the same |render_process_id| will be
   // returned.
   CefRefPtr<CefRequestContextHandler> GetHandler(
-      int render_process_id,
-      int render_frame_id,
-      int frame_tree_node_id,
+      const content::GlobalRenderFrameHostId& global_id,
       bool require_frame_match) const;
 
   // Returns true if this context is associated with the specified IDs. Pass -1
   // for unknown values. If |require_frame_match| is true only exact matches
   // will qualify. If |require_frame_match| is false, and there is not an exact
   // match, then any match for |render_process_id| will qualify.
-  bool IsAssociatedContext(int render_process_id,
-                           int render_frame_id,
-                           int frame_tree_node_id,
+  bool IsAssociatedContext(const content::GlobalRenderFrameHostId& global_id,
                            bool require_frame_match) const;
 
-  // Remember the plugin load decision for plugin status requests that arrive
-  // via CefPluginServiceFilter::IsPluginAvailable.
-  void AddPluginLoadDecision(int render_process_id,
-                             const base::FilePath& plugin_path,
-                             bool is_main_frame,
-                             const url::Origin& main_frame_origin,
-                             chrome::mojom::PluginStatus status);
-  bool HasPluginLoadDecision(int render_process_id,
-                             const base::FilePath& plugin_path,
-                             bool is_main_frame,
-                             const url::Origin& main_frame_origin,
-                             chrome::mojom::PluginStatus* status) const;
-
-  // Clear the plugin load decisions associated with |render_process_id|, or all
-  // plugin load decisions if |render_process_id| is -1.
-  void ClearPluginLoadDecision(int render_process_id);
-
   // Called from CefRequestContextImpl methods of the same name.
-  void RegisterSchemeHandlerFactory(const std::string& scheme_name,
-                                    const std::string& domain_name,
+  void RegisterSchemeHandlerFactory(const CefString& scheme_name,
+                                    const CefString& domain_name,
                                     CefRefPtr<CefSchemeHandlerFactory> factory);
   void ClearSchemeHandlerFactories();
+  // TODO(chrome-runtime): Make these extension methods pure virtual.
+  virtual void LoadExtension(const CefString& root_directory,
+                             CefRefPtr<CefDictionaryValue> manifest,
+                             CefRefPtr<CefExtensionHandler> handler,
+                             CefRefPtr<CefRequestContext> loader_context);
+  virtual bool GetExtensions(std::vector<CefString>& extension_ids);
+  virtual CefRefPtr<CefExtension> GetExtension(const CefString& extension_id);
+
+  // Called from CefExtensionImpl::Unload().
+  virtual bool UnloadExtension(const CefString& extension_id);
+
+  // Returns true if this context supports print preview.
+  virtual bool IsPrintPreviewSupported() const;
 
   network::mojom::NetworkContext* GetNetworkContext();
 
-  void set_should_persist_session_cookies(bool value) {
-    should_persist_session_cookies_ = value;
-  }
-  void set_cookieable_schemes(
-      base::Optional<std::vector<std::string>> schemes) {
-    cookieable_schemes_ = schemes;
-  }
-
-  CefResourceContext* resource_context() const {
-    return resource_context_.get();
-  }
-  extensions::CefExtensionSystem* extension_system() const {
-    return extension_system_;
-  }
-
-  // Called from DownloadPrefs::FromBrowserContext.
-  DownloadPrefs* GetDownloadPrefs();
-
-  // Returns true if this context supports print preview.
-  bool IsPrintPreviewSupported() const;
-
   CefMediaRouterManager* GetMediaRouterManager();
 
-  // Returns the BrowserContext, or nullptr if the BrowserContext has already
-  // been destroyed.
+  using CookieableSchemes = absl::optional<std::vector<std::string>>;
+
+  // Returns the schemes associated with this context specifically, or the
+  // global configuration if unset.
+  CookieableSchemes GetCookieableSchemes() const;
+  static CookieableSchemes GetGlobalCookieableSchemes();
+
+  // These accessors are safe to call from any thread because the values don't
+  // change during this object's lifespan.
+  const CefRequestContextSettings& settings() const { return settings_; }
+  base::FilePath cache_path() const { return cache_path_; }
+  scoped_refptr<CefIOThreadState> iothread_state() const {
+    return iothread_state_;
+  }
+
+  // Used to hold a WeakPtr reference to this this object. The Getter returns
+  // nullptr if this object has already been destroyed.
   using Getter = base::RepeatingCallback<CefBrowserContext*()>;
   Getter getter() const { return getter_; }
 
- private:
-  // Allow deletion via std::unique_ptr().
-  friend std::default_delete<CefBrowserContext>;
+ protected:
+  explicit CefBrowserContext(const CefRequestContextSettings& settings);
+  virtual ~CefBrowserContext();
 
-  ~CefBrowserContext() override;
+  // Will be called immediately after this object is created.
+  virtual void Initialize();
 
-  // Members initialized during construction are safe to access from any thread.
+  // Will be called immediately before this object is deleted.
+  virtual void Shutdown();
+
+  // Members initialized during construction or Initialize() are safe to access
+  // from any thread.
   const CefRequestContextSettings settings_;
   base::FilePath cache_path_;
 
+ private:
+  // For DeleteSoon().
+  friend class base::DeleteHelper<CefBrowserContext>;
+
+  scoped_refptr<CefIOThreadState> iothread_state_;
+  CookieableSchemes cookieable_schemes_;
+  std::unique_ptr<CefMediaRouterManager> media_router_manager_;
+
   // CefRequestContextImpl objects referencing this object.
   std::set<CefRequestContextImpl*> request_context_set_;
 
-  std::unique_ptr<PrefService> pref_service_;
-  std::unique_ptr<PrefProxyConfigTracker> pref_proxy_config_tracker_;
-
-  std::unique_ptr<CefDownloadManagerDelegate> download_manager_delegate_;
-  std::unique_ptr<CefSSLHostStateDelegate> ssl_host_state_delegate_;
-  scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
-  std::unique_ptr<visitedlink::VisitedLinkWriter> visitedlink_master_;
-  // |visitedlink_listener_| is owned by visitedlink_master_.
-  CefVisitedLinkListener* visitedlink_listener_;
-  bool should_persist_session_cookies_ = false;
-  base::Optional<std::vector<std::string>> cookieable_schemes_;
-
-  std::unique_ptr<CefResourceContext> resource_context_;
-
-  // Owned by the KeyedService system.
-  extensions::CefExtensionSystem* extension_system_ = nullptr;
-
-  // The key to index KeyedService instances created by
-  // SimpleKeyedServiceFactory.
-  std::unique_ptr<ProfileKey> key_;
-
-  std::unique_ptr<DownloadPrefs> download_prefs_;
-
-  std::unique_ptr<CefMediaRouterManager> media_router_manager_;
-
   // Map IDs to CefRequestContextHandler objects.
   CefRequestContextHandlerMap handler_map_;
 
-  // Map (render_process_id, plugin_path, is_main_frame, main_frame_origin) to
-  // plugin load decision.
-  typedef std::map<
-      std::pair<std::pair<int, base::FilePath>, std::pair<bool, url::Origin>>,
-      chrome::mojom::PluginStatus>
-      PluginLoadDecisionMap;
-  PluginLoadDecisionMap plugin_load_decision_map_;
-
-  // Set of (render_process_id, render_frame_id) associated with this context.
-  typedef std::set<std::pair<int, int>> RenderIdSet;
+  // Set of global IDs associated with this context.
+  using RenderIdSet = std::set<content::GlobalRenderFrameHostId>;
   RenderIdSet render_id_set_;
 
-  // Set of frame_tree_node_id associated with this context. Keeping this list
-  // is necessary because, when navigating the main frame, a new (pre-commit)
-  // network request will be created before the RenderFrameHost. Consequently we
-  // can't rely on valid render IDs. See https://crbug.com/776884 for
-  // background.
-  typedef std::set<int> NodeIdSet;
-  NodeIdSet node_id_set_;
+#if DCHECK_IS_ON()
+  bool is_shutdown_ = false;
+#endif
 
   Getter getter_;
   base::WeakPtrFactory<CefBrowserContext> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefBrowserContext);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_BROWSER_CONTEXT_IMPL_H_
diff --git a/src/libcef/browser/browser_context_keyed_service_factories.cc b/src/libcef/browser/browser_context_keyed_service_factories.cc
index f89c3e8..8730bfb 100644
--- a/src/libcef/browser/browser_context_keyed_service_factories.cc
+++ b/src/libcef/browser/browser_context_keyed_service_factories.cc
@@ -5,20 +5,28 @@
 #include "libcef/browser/browser_context_keyed_service_factories.h"
 #include "libcef/common/extensions/extensions_util.h"
 
+#include "base/feature_list.h"
 #include "chrome/browser/content_settings/cookie_settings_factory.h"
+#include "chrome/browser/media/router/chrome_media_router_factory.h"
+#include "chrome/browser/media/webrtc/media_device_salt_service_factory.h"
 #include "chrome/browser/plugins/plugin_prefs_factory.h"
 #include "chrome/browser/profiles/renderer_updater_factory.h"
+#include "chrome/browser/reduce_accept_language/reduce_accept_language_factory.h"
 #include "chrome/browser/spellchecker/spellcheck_factory.h"
 #include "chrome/browser/themes/theme_service_factory.h"
 #include "chrome/browser/ui/prefs/prefs_tab_helper.h"
+#include "components/permissions/features.h"
 #include "extensions/browser/api/alarms/alarm_manager.h"
 #include "extensions/browser/api/storage/storage_frontend.h"
 #include "extensions/browser/renderer_startup_helper.h"
+#include "services/network/public/cpp/features.h"
 
 namespace cef {
 
 void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
   CookieSettingsFactory::GetInstance();
+  MediaDeviceSaltServiceFactory::GetInstance();
+  media_router::ChromeMediaRouterFactory::GetInstance();
   PluginPrefsFactory::GetInstance();
   PrefsTabHelper::GetServiceInstance();
   RendererUpdaterFactory::GetInstance();
@@ -30,6 +38,10 @@
     extensions::RendererStartupHelperFactory::GetInstance();
     extensions::StorageFrontend::GetFactoryInstance();
   }
+
+  if (base::FeatureList::IsEnabled(network::features::kReduceAcceptLanguage)) {
+    ReduceAcceptLanguageFactory::GetInstance();
+  }
 }
 
 }  // namespace cef
diff --git a/src/libcef/browser/browser_frame.cc b/src/libcef/browser/browser_frame.cc
new file mode 100644
index 0000000..9b354d6
--- /dev/null
+++ b/src/libcef/browser/browser_frame.cc
@@ -0,0 +1,82 @@
+// Copyright 2021 The Chromium Embedded Framework 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 "libcef/browser/browser_frame.h"
+
+#include "libcef/browser/browser_host_base.h"
+#include "libcef/browser/thread_util.h"
+
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+
+CefBrowserFrame::CefBrowserFrame(
+    content::RenderFrameHost* render_frame_host,
+    mojo::PendingReceiver<cef::mojom::BrowserFrame> receiver)
+    : FrameServiceBase(render_frame_host, std::move(receiver)) {}
+
+CefBrowserFrame::~CefBrowserFrame() = default;
+
+// static
+void CefBrowserFrame::RegisterBrowserInterfaceBindersForFrame(
+    content::RenderFrameHost* render_frame_host,
+    mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
+  map->Add<cef::mojom::BrowserFrame>(base::BindRepeating(
+      [](content::RenderFrameHost* frame_host,
+         mojo::PendingReceiver<cef::mojom::BrowserFrame> receiver) {
+        // This object is bound to the lifetime of |frame_host| and the mojo
+        // connection. See DocumentServiceBase for details.
+        new CefBrowserFrame(frame_host, std::move(receiver));
+      }));
+}
+
+void CefBrowserFrame::SendMessage(const std::string& name,
+                                  base::Value::List arguments) {
+  // Always send to the newly created RFH, which may be speculative when
+  // navigating cross-origin.
+  if (auto host = GetFrameHost(/*prefer_speculative=*/true)) {
+    host->SendMessage(name, std::move(arguments));
+  }
+}
+
+void CefBrowserFrame::SendSharedMemoryRegion(
+    const std::string& name,
+    base::WritableSharedMemoryRegion region) {
+  // Always send to the newly created RFH, which may be speculative when
+  // navigating cross-origin.
+  if (auto host = GetFrameHost(/*prefer_speculative=*/true)) {
+    host->SendSharedMemoryRegion(name, std::move(region));
+  }
+}
+
+void CefBrowserFrame::FrameAttached(
+    mojo::PendingRemote<cef::mojom::RenderFrame> render_frame,
+    bool reattached) {
+  // Always send to the newly created RFH, which may be speculative when
+  // navigating cross-origin.
+  if (auto host = GetFrameHost(/*prefer_speculative=*/true)) {
+    host->FrameAttached(std::move(render_frame), reattached);
+  }
+}
+
+void CefBrowserFrame::UpdateDraggableRegions(
+    absl::optional<std::vector<cef::mojom::DraggableRegionEntryPtr>> regions) {
+  if (auto host = GetFrameHost()) {
+    host->UpdateDraggableRegions(std::move(regions));
+  }
+}
+
+CefRefPtr<CefFrameHostImpl> CefBrowserFrame::GetFrameHost(
+    bool prefer_speculative) const {
+  CEF_REQUIRE_UIT();
+  auto rfh = render_frame_host();
+  if (auto browser = CefBrowserHostBase::GetBrowserForHost(rfh)) {
+    return browser->browser_info()->GetFrameForHost(rfh, nullptr,
+                                                    prefer_speculative);
+  }
+  DCHECK(false);
+  return nullptr;
+}
diff --git a/src/libcef/browser/browser_frame.h b/src/libcef/browser/browser_frame.h
new file mode 100644
index 0000000..a9bf83c
--- /dev/null
+++ b/src/libcef/browser/browser_frame.h
@@ -0,0 +1,55 @@
+// Copyright 2021 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_BROWSER_FRAME_H_
+#define CEF_LIBCEF_BROWSER_BROWSER_FRAME_H_
+#pragma once
+
+#include "libcef/browser/frame_host_impl.h"
+#include "libcef/browser/frame_service_base.h"
+
+#include "cef/libcef/common/mojom/cef.mojom.h"
+#include "mojo/public/cpp/bindings/binder_map.h"
+
+// Implementation of the BrowserFrame mojo interface.
+// This is implemented separately from CefFrameHostImpl to better manage the
+// association with the RenderFrameHost (which may be speculative, etc.), and so
+// that messages are always routed to the most appropriate CefFrameHostImpl
+// instance. Lifespan is tied to the RFH via FrameServiceBase.
+class CefBrowserFrame
+    : public content::FrameServiceBase<cef::mojom::BrowserFrame> {
+ public:
+  CefBrowserFrame(content::RenderFrameHost* render_frame_host,
+                  mojo::PendingReceiver<cef::mojom::BrowserFrame> receiver);
+
+  CefBrowserFrame(const CefBrowserFrame&) = delete;
+  CefBrowserFrame& operator=(const CefBrowserFrame&) = delete;
+
+  ~CefBrowserFrame() override;
+
+  // Called from the ContentBrowserClient method of the same name.
+  static void RegisterBrowserInterfaceBindersForFrame(
+      content::RenderFrameHost* render_frame_host,
+      mojo::BinderMapWithContext<content::RenderFrameHost*>* map);
+
+ private:
+  // cef::mojom::BrowserFrame methods:
+  void SendMessage(const std::string& name,
+                   base::Value::List arguments) override;
+  void SendSharedMemoryRegion(const std::string& name,
+                              base::WritableSharedMemoryRegion region) override;
+  void FrameAttached(mojo::PendingRemote<cef::mojom::RenderFrame> render_frame,
+                     bool reattached) override;
+  void UpdateDraggableRegions(
+      absl::optional<std::vector<cef::mojom::DraggableRegionEntryPtr>> regions)
+      override;
+
+  // FrameServiceBase methods:
+  bool ShouldCloseOnFinishNavigation() const override { return false; }
+
+  CefRefPtr<CefFrameHostImpl> GetFrameHost(
+      bool prefer_speculative = false) const;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_BROWSER_FRAME_H_
diff --git a/src/libcef/browser/browser_host_base.cc b/src/libcef/browser/browser_host_base.cc
new file mode 100644
index 0000000..3f310c4
--- /dev/null
+++ b/src/libcef/browser/browser_host_base.cc
@@ -0,0 +1,1287 @@
+// Copyright 2020 The Chromium Embedded Framework 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 "libcef/browser/browser_host_base.h"
+
+#include <tuple>
+
+#include "libcef/browser/browser_info_manager.h"
+#include "libcef/browser/browser_platform_delegate.h"
+#include "libcef/browser/context.h"
+#include "libcef/browser/image_impl.h"
+#include "libcef/browser/navigation_entry_impl.h"
+#include "libcef/browser/printing/print_util.h"
+#include "libcef/browser/thread_util.h"
+#include "libcef/common/frame_util.h"
+#include "libcef/common/net/url_util.h"
+
+#include "base/logging.h"
+#include "chrome/browser/platform_util.h"
+#include "chrome/browser/spellchecker/spellcheck_factory.h"
+#include "chrome/browser/spellchecker/spellcheck_service.h"
+#include "chrome/browser/ui/browser_commands.h"
+#include "components/favicon/core/favicon_url.h"
+#include "components/spellcheck/common/spellcheck_features.h"
+#include "components/zoom/page_zoom.h"
+#include "components/zoom/zoom_controller.h"
+#include "content/browser/renderer_host/render_frame_host_impl.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/download_manager.h"
+#include "content/public/browser/download_request_utils.h"
+#include "content/public/browser/file_select_listener.h"
+#include "content/public/browser/navigation_entry.h"
+#include "ui/base/resource/resource_scale_factor.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/shell_dialogs/select_file_policy.h"
+
+#if BUILDFLAG(IS_MAC)
+#include "components/spellcheck/browser/spellcheck_platform.h"
+#endif
+
+namespace {
+
+// Associates a CefBrowserHostBase instance with a WebContents. This object will
+// be deleted automatically when the WebContents is destroyed.
+class WebContentsUserDataAdapter : public base::SupportsUserData::Data {
+ public:
+  static void Register(CefRefPtr<CefBrowserHostBase> browser) {
+    new WebContentsUserDataAdapter(browser);
+  }
+
+  static CefRefPtr<CefBrowserHostBase> Get(
+      const content::WebContents* web_contents) {
+    WebContentsUserDataAdapter* adapter =
+        static_cast<WebContentsUserDataAdapter*>(
+            web_contents->GetUserData(UserDataKey()));
+    if (adapter) {
+      return adapter->browser_;
+    }
+    return nullptr;
+  }
+
+ private:
+  WebContentsUserDataAdapter(CefRefPtr<CefBrowserHostBase> browser)
+      : browser_(browser) {
+    auto web_contents = browser->GetWebContents();
+    DCHECK(web_contents);
+    web_contents->SetUserData(UserDataKey(), base::WrapUnique(this));
+  }
+
+  static void* UserDataKey() {
+    // We just need a unique constant. Use the address of a static that
+    // COMDAT folding won't touch in an optimizing linker.
+    static int data_key = 0;
+    return reinterpret_cast<void*>(&data_key);
+  }
+
+  CefRefPtr<CefBrowserHostBase> browser_;
+};
+
+}  // namespace
+
+// static
+CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForHost(
+    const content::RenderViewHost* host) {
+  DCHECK(host);
+  CEF_REQUIRE_UIT();
+  content::WebContents* web_contents = content::WebContents::FromRenderViewHost(
+      const_cast<content::RenderViewHost*>(host));
+  if (web_contents) {
+    return GetBrowserForContents(web_contents);
+  }
+  return nullptr;
+}
+
+// static
+CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForHost(
+    const content::RenderFrameHost* host) {
+  DCHECK(host);
+  CEF_REQUIRE_UIT();
+  content::WebContents* web_contents =
+      content::WebContents::FromRenderFrameHost(
+          const_cast<content::RenderFrameHost*>(host));
+  if (web_contents) {
+    return GetBrowserForContents(web_contents);
+  }
+  return nullptr;
+}
+
+// static
+CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForContents(
+    const content::WebContents* contents) {
+  DCHECK(contents);
+  CEF_REQUIRE_UIT();
+  return WebContentsUserDataAdapter::Get(contents);
+}
+
+// static
+CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetBrowserForGlobalId(
+    const content::GlobalRenderFrameHostId& global_id) {
+  if (!frame_util::IsValidGlobalId(global_id)) {
+    return nullptr;
+  }
+
+  if (CEF_CURRENTLY_ON_UIT()) {
+    // Use the non-thread-safe but potentially faster approach.
+    content::RenderFrameHost* render_frame_host =
+        content::RenderFrameHost::FromID(global_id);
+    if (!render_frame_host) {
+      return nullptr;
+    }
+    return GetBrowserForHost(render_frame_host);
+  } else {
+    // Use the thread-safe approach.
+    bool is_guest_view = false;
+    auto info = CefBrowserInfoManager::GetInstance()->GetBrowserInfo(
+        global_id, &is_guest_view);
+    if (info && !is_guest_view) {
+      auto browser = info->browser();
+      if (!browser) {
+        LOG(WARNING) << "Found browser id " << info->browser_id()
+                     << " but no browser object matching frame "
+                     << frame_util::GetFrameDebugString(global_id);
+      }
+      return browser;
+    }
+    return nullptr;
+  }
+}
+
+// static
+CefRefPtr<CefBrowserHostBase>
+CefBrowserHostBase::GetBrowserForTopLevelNativeWindow(
+    gfx::NativeWindow owning_window) {
+  DCHECK(owning_window);
+  CEF_REQUIRE_UIT();
+
+  for (const auto& browser_info :
+       CefBrowserInfoManager::GetInstance()->GetBrowserInfoList()) {
+    if (auto browser = browser_info->browser()) {
+      if (browser->GetTopLevelNativeWindow() == owning_window) {
+        return browser;
+      }
+    }
+  }
+
+  return nullptr;
+}
+
+// static
+CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::GetLikelyFocusedBrowser() {
+  CEF_REQUIRE_UIT();
+
+  for (const auto& browser_info :
+       CefBrowserInfoManager::GetInstance()->GetBrowserInfoList()) {
+    if (auto browser = browser_info->browser()) {
+      if (browser->IsFocused()) {
+        return browser;
+      }
+    }
+  }
+
+  return nullptr;
+}
+
+CefBrowserHostBase::CefBrowserHostBase(
+    const CefBrowserSettings& settings,
+    CefRefPtr<CefClient> client,
+    std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
+    scoped_refptr<CefBrowserInfo> browser_info,
+    CefRefPtr<CefRequestContextImpl> request_context)
+    : settings_(settings),
+      client_(client),
+      platform_delegate_(std::move(platform_delegate)),
+      browser_info_(browser_info),
+      request_context_(request_context),
+      is_views_hosted_(platform_delegate_->IsViewsHosted()) {
+  CEF_REQUIRE_UIT();
+  DCHECK(!browser_info_->browser().get());
+  browser_info_->SetBrowser(this);
+
+  contents_delegate_ =
+      std::make_unique<CefBrowserContentsDelegate>(browser_info_);
+  contents_delegate_->AddObserver(this);
+}
+
+void CefBrowserHostBase::InitializeBrowser() {
+  CEF_REQUIRE_UIT();
+
+  // Associate the WebContents with this browser object.
+  DCHECK(GetWebContents());
+  WebContentsUserDataAdapter::Register(this);
+}
+
+void CefBrowserHostBase::DestroyBrowser() {
+  CEF_REQUIRE_UIT();
+
+  devtools_manager_.reset();
+  media_stream_registrar_.reset();
+
+  platform_delegate_.reset();
+
+  contents_delegate_->RemoveObserver(this);
+  contents_delegate_->ObserveWebContents(nullptr);
+
+  CefBrowserInfoManager::GetInstance()->RemoveBrowserInfo(browser_info_);
+  browser_info_->SetBrowser(nullptr);
+}
+
+CefRefPtr<CefBrowser> CefBrowserHostBase::GetBrowser() {
+  return this;
+}
+
+CefRefPtr<CefClient> CefBrowserHostBase::GetClient() {
+  return client_;
+}
+
+CefRefPtr<CefRequestContext> CefBrowserHostBase::GetRequestContext() {
+  return request_context_;
+}
+
+bool CefBrowserHostBase::CanZoom(cef_zoom_command_t command) {
+  // Verify that this method is being called on the UI thread.
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    DCHECK(false) << "called on invalid thread";
+    return false;
+  }
+
+  if (auto web_contents = GetWebContents()) {
+    switch (command) {
+      case CEF_ZOOM_COMMAND_OUT:
+        return chrome::CanZoomOut(web_contents);
+      case CEF_ZOOM_COMMAND_RESET:
+        return chrome::CanResetZoom(web_contents);
+      case CEF_ZOOM_COMMAND_IN:
+        return chrome::CanZoomIn(web_contents);
+    }
+  }
+
+  return false;
+}
+
+void CefBrowserHostBase::Zoom(cef_zoom_command_t command) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&CefBrowserHostBase::Zoom, this, command));
+    return;
+  }
+
+  if (auto web_contents = GetWebContents()) {
+    const content::PageZoom page_zoom = [command]() {
+      switch (command) {
+        case CEF_ZOOM_COMMAND_OUT:
+          return content::PAGE_ZOOM_OUT;
+        case CEF_ZOOM_COMMAND_RESET:
+          return content::PAGE_ZOOM_RESET;
+        case CEF_ZOOM_COMMAND_IN:
+          return content::PAGE_ZOOM_IN;
+      }
+    }();
+
+    // Same implementation as chrome::Zoom(), but explicitly specifying the
+    // WebContents.
+    zoom::PageZoom::Zoom(web_contents, page_zoom);
+  }
+}
+
+double CefBrowserHostBase::GetDefaultZoomLevel() {
+  // Verify that this method is being called on the UI thread.
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    DCHECK(false) << "called on invalid thread";
+    return 0.0;
+  }
+
+  if (auto web_contents = GetWebContents()) {
+    zoom::ZoomController* zoom_controller =
+        zoom::ZoomController::FromWebContents(web_contents);
+    if (zoom_controller) {
+      return zoom_controller->GetDefaultZoomLevel();
+    }
+  }
+
+  return 0.0;
+}
+
+double CefBrowserHostBase::GetZoomLevel() {
+  // Verify that this method is being called on the UI thread.
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    DCHECK(false) << "called on invalid thread";
+    return 0.0;
+  }
+
+  if (auto web_contents = GetWebContents()) {
+    zoom::ZoomController* zoom_controller =
+        zoom::ZoomController::FromWebContents(web_contents);
+    if (zoom_controller) {
+      return zoom_controller->GetZoomLevel();
+    }
+  }
+
+  return 0.0;
+}
+
+void CefBrowserHostBase::SetZoomLevel(double zoomLevel) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::SetZoomLevel,
+                                          this, zoomLevel));
+    return;
+  }
+
+  if (auto web_contents = GetWebContents()) {
+    zoom::ZoomController* zoom_controller =
+        zoom::ZoomController::FromWebContents(web_contents);
+    if (zoom_controller) {
+      if (zoomLevel == 0.0) {
+        // Same logic as PageZoom::Zoom(PAGE_ZOOM_RESET).
+        zoomLevel = zoom_controller->GetDefaultZoomLevel();
+        web_contents->SetPageScale(1.f);
+      }
+      zoom_controller->SetZoomLevel(zoomLevel);
+    }
+  }
+}
+
+bool CefBrowserHostBase::HasView() {
+  return is_views_hosted_;
+}
+
+void CefBrowserHostBase::SetFocus(bool focus) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&CefBrowserHostBase::SetFocus, this, focus));
+    return;
+  }
+
+  if (focus) {
+    OnSetFocus(FOCUS_SOURCE_SYSTEM);
+  } else if (platform_delegate_) {
+    platform_delegate_->SetFocus(false);
+  }
+}
+
+void CefBrowserHostBase::RunFileDialog(
+    FileDialogMode mode,
+    const CefString& title,
+    const CefString& default_file_path,
+    const std::vector<CefString>& accept_filters,
+    CefRefPtr<CefRunFileDialogCallback> callback) {
+  DCHECK(callback);
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::RunFileDialog,
+                                          this, mode, title, default_file_path,
+                                          accept_filters, callback));
+    return;
+  }
+
+  if (!callback || !EnsureFileDialogManager()) {
+    LOG(ERROR) << "File dialog canceled due to invalid state.";
+    if (callback) {
+      callback->OnFileDialogDismissed({});
+    }
+    return;
+  }
+
+  file_dialog_manager_->RunFileDialog(mode, title, default_file_path,
+                                      accept_filters, callback);
+}
+
+void CefBrowserHostBase::StartDownload(const CefString& url) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT, base::BindOnce(&CefBrowserHostBase::StartDownload, this, url));
+    return;
+  }
+
+  GURL gurl = GURL(url.ToString());
+  if (gurl.is_empty() || !gurl.is_valid()) {
+    return;
+  }
+
+  auto web_contents = GetWebContents();
+  if (!web_contents) {
+    return;
+  }
+
+  auto browser_context = web_contents->GetBrowserContext();
+  if (!browser_context) {
+    return;
+  }
+
+  content::DownloadManager* manager = browser_context->GetDownloadManager();
+  if (!manager) {
+    return;
+  }
+
+  std::unique_ptr<download::DownloadUrlParameters> params(
+      content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(
+          web_contents, gurl, MISSING_TRAFFIC_ANNOTATION));
+  manager->DownloadUrl(std::move(params));
+}
+
+void CefBrowserHostBase::DownloadImage(
+    const CefString& image_url,
+    bool is_favicon,
+    uint32_t max_image_size,
+    bool bypass_cache,
+    CefRefPtr<CefDownloadImageCallback> callback) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(&CefBrowserHostBase::DownloadImage, this, image_url,
+                       is_favicon, max_image_size, bypass_cache, callback));
+    return;
+  }
+
+  if (!callback) {
+    return;
+  }
+
+  GURL gurl = GURL(image_url.ToString());
+  if (gurl.is_empty() || !gurl.is_valid()) {
+    return;
+  }
+
+  auto web_contents = GetWebContents();
+  if (!web_contents) {
+    return;
+  }
+
+  const float scale = ui::GetScaleForMaxSupportedResourceScaleFactor();
+  web_contents->DownloadImage(
+      gurl, is_favicon, gfx::Size(max_image_size, max_image_size),
+      max_image_size * scale, bypass_cache,
+      base::BindOnce(
+          [](uint32_t max_image_size,
+             CefRefPtr<CefDownloadImageCallback> callback, int id,
+             int http_status_code, const GURL& image_url,
+             const std::vector<SkBitmap>& bitmaps,
+             const std::vector<gfx::Size>& sizes) {
+            CEF_REQUIRE_UIT();
+
+            CefRefPtr<CefImageImpl> image_impl;
+
+            if (!bitmaps.empty()) {
+              image_impl = new CefImageImpl();
+              image_impl->AddBitmaps(max_image_size, bitmaps);
+            }
+
+            callback->OnDownloadImageFinished(
+                image_url.spec(), http_status_code, image_impl.get());
+          },
+          max_image_size, callback));
+}
+
+void CefBrowserHostBase::Print() {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::Print, this));
+    return;
+  }
+
+  auto web_contents = GetWebContents();
+  if (!web_contents) {
+    return;
+  }
+
+  const bool print_preview_disabled =
+      !platform_delegate_ || !platform_delegate_->IsPrintPreviewSupported();
+  print_util::Print(web_contents, print_preview_disabled);
+}
+
+void CefBrowserHostBase::PrintToPDF(const CefString& path,
+                                    const CefPdfPrintSettings& settings,
+                                    CefRefPtr<CefPdfPrintCallback> callback) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::PrintToPDF, this,
+                                          path, settings, callback));
+    return;
+  }
+
+  auto web_contents = GetWebContents();
+  if (!web_contents) {
+    return;
+  }
+
+  print_util::PrintToPDF(web_contents, path, settings, callback);
+}
+
+void CefBrowserHostBase::ShowDevTools(const CefWindowInfo& windowInfo,
+                                      CefRefPtr<CefClient> client,
+                                      const CefBrowserSettings& settings,
+                                      const CefPoint& inspect_element_at) {
+  auto params = std::make_unique<CefShowDevToolsParams>(
+      windowInfo, client, settings, inspect_element_at);
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&CefBrowserHostBase::ShowDevToolsOnUIThread,
+                                 this, std::move(params)));
+  } else {
+    ShowDevToolsOnUIThread(std::move(params));
+  }
+}
+
+bool CefBrowserHostBase::SendDevToolsMessage(const void* message,
+                                             size_t message_size) {
+  if (!message || message_size == 0) {
+    return false;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    std::string message_str(static_cast<const char*>(message), message_size);
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(
+            [](CefRefPtr<CefBrowserHostBase> self, std::string message_str) {
+              self->SendDevToolsMessage(message_str.data(), message_str.size());
+            },
+            CefRefPtr<CefBrowserHostBase>(this), std::move(message_str)));
+    return false;
+  }
+
+  if (!EnsureDevToolsManager()) {
+    return false;
+  }
+  return devtools_manager_->SendDevToolsMessage(message, message_size);
+}
+
+int CefBrowserHostBase::ExecuteDevToolsMethod(
+    int message_id,
+    const CefString& method,
+    CefRefPtr<CefDictionaryValue> params) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT, base::BindOnce(base::IgnoreResult(
+                                    &CefBrowserHostBase::ExecuteDevToolsMethod),
+                                this, message_id, method, params));
+    return 0;
+  }
+
+  if (!EnsureDevToolsManager()) {
+    return 0;
+  }
+  return devtools_manager_->ExecuteDevToolsMethod(message_id, method, params);
+}
+
+CefRefPtr<CefRegistration> CefBrowserHostBase::AddDevToolsMessageObserver(
+    CefRefPtr<CefDevToolsMessageObserver> observer) {
+  if (!observer) {
+    return nullptr;
+  }
+  auto registration = CefDevToolsManager::CreateRegistration(observer);
+  InitializeDevToolsRegistrationOnUIThread(registration);
+  return registration.get();
+}
+
+void CefBrowserHostBase::GetNavigationEntries(
+    CefRefPtr<CefNavigationEntryVisitor> visitor,
+    bool current_only) {
+  DCHECK(visitor.get());
+  if (!visitor.get()) {
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT, base::BindOnce(&CefBrowserHostBase::GetNavigationEntries, this,
+                                visitor, current_only));
+    return;
+  }
+
+  auto web_contents = GetWebContents();
+  if (!web_contents) {
+    return;
+  }
+
+  content::NavigationController& controller = web_contents->GetController();
+  const int total = controller.GetEntryCount();
+  const int current = controller.GetCurrentEntryIndex();
+
+  if (current_only) {
+    // Visit only the current entry.
+    CefRefPtr<CefNavigationEntryImpl> entry =
+        new CefNavigationEntryImpl(controller.GetEntryAtIndex(current));
+    visitor->Visit(entry.get(), true, current, total);
+    std::ignore = entry->Detach(nullptr);
+  } else {
+    // Visit all entries.
+    bool cont = true;
+    for (int i = 0; i < total && cont; ++i) {
+      CefRefPtr<CefNavigationEntryImpl> entry =
+          new CefNavigationEntryImpl(controller.GetEntryAtIndex(i));
+      cont = visitor->Visit(entry.get(), (i == current), i, total);
+      std::ignore = entry->Detach(nullptr);
+    }
+  }
+}
+
+CefRefPtr<CefNavigationEntry> CefBrowserHostBase::GetVisibleNavigationEntry() {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    DCHECK(false) << "called on invalid thread";
+    return nullptr;
+  }
+
+  content::NavigationEntry* entry = nullptr;
+  auto web_contents = GetWebContents();
+  if (web_contents) {
+    entry = web_contents->GetController().GetVisibleEntry();
+  }
+
+  if (!entry) {
+    return nullptr;
+  }
+
+  return new CefNavigationEntryImpl(entry);
+}
+
+void CefBrowserHostBase::NotifyMoveOrResizeStarted() {
+#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC))
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(&CefBrowserHostBase::NotifyMoveOrResizeStarted, this));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->NotifyMoveOrResizeStarted();
+  }
+#endif
+}
+
+bool CefBrowserHostBase::IsFullscreen() {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    DCHECK(false) << "called on invalid thread";
+    return false;
+  }
+
+  if (auto web_contents = GetWebContents()) {
+    return web_contents->IsFullscreen();
+  }
+  return false;
+}
+
+void CefBrowserHostBase::ExitFullscreen(bool will_cause_resize) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::ExitFullscreen,
+                                          this, will_cause_resize));
+    return;
+  }
+
+  auto web_contents = GetWebContents();
+  if (web_contents && web_contents->IsFullscreen()) {
+    web_contents->ExitFullscreen(will_cause_resize);
+  }
+}
+
+void CefBrowserHostBase::ReplaceMisspelling(const CefString& word) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(&CefBrowserHostBase::ReplaceMisspelling, this, word));
+    return;
+  }
+
+  auto web_contents = GetWebContents();
+  if (web_contents) {
+    web_contents->ReplaceMisspelling(word);
+  }
+}
+
+void CefBrowserHostBase::AddWordToDictionary(const CefString& word) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(&CefBrowserHostBase::AddWordToDictionary, this, word));
+    return;
+  }
+
+  auto web_contents = GetWebContents();
+  if (!web_contents) {
+    return;
+  }
+
+  SpellcheckService* spellcheck = nullptr;
+  content::BrowserContext* browser_context = web_contents->GetBrowserContext();
+  if (browser_context) {
+    spellcheck = SpellcheckServiceFactory::GetForContext(browser_context);
+    if (spellcheck) {
+      spellcheck->GetCustomDictionary()->AddWord(word);
+    }
+  }
+#if BUILDFLAG(IS_MAC)
+  if (spellcheck && spellcheck::UseBrowserSpellChecker()) {
+    spellcheck_platform::AddWord(spellcheck->platform_spell_checker(), word);
+  }
+#endif
+}
+
+void CefBrowserHostBase::SendKeyEvent(const CefKeyEvent& event) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::SendKeyEvent,
+                                          this, event));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->SendKeyEvent(event);
+  }
+}
+
+void CefBrowserHostBase::SendMouseClickEvent(const CefMouseEvent& event,
+                                             MouseButtonType type,
+                                             bool mouseUp,
+                                             int clickCount) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&CefBrowserHostBase::SendMouseClickEvent, this,
+                                 event, type, mouseUp, clickCount));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->SendMouseClickEvent(event, type, mouseUp, clickCount);
+  }
+}
+
+void CefBrowserHostBase::SendMouseMoveEvent(const CefMouseEvent& event,
+                                            bool mouseLeave) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&CefBrowserHostBase::SendMouseMoveEvent, this,
+                                 event, mouseLeave));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->SendMouseMoveEvent(event, mouseLeave);
+  }
+}
+
+void CefBrowserHostBase::SendMouseWheelEvent(const CefMouseEvent& event,
+                                             int deltaX,
+                                             int deltaY) {
+  if (deltaX == 0 && deltaY == 0) {
+    // Nothing to do.
+    return;
+  }
+
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&CefBrowserHostBase::SendMouseWheelEvent, this,
+                                 event, deltaX, deltaY));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->SendMouseWheelEvent(event, deltaX, deltaY);
+  }
+}
+
+bool CefBrowserHostBase::IsValid() {
+  return browser_info_->browser() == this;
+}
+
+CefRefPtr<CefBrowserHost> CefBrowserHostBase::GetHost() {
+  return this;
+}
+
+bool CefBrowserHostBase::CanGoBack() {
+  base::AutoLock lock_scope(state_lock_);
+  return can_go_back_;
+}
+
+void CefBrowserHostBase::GoBack() {
+  auto callback = base::BindOnce(&CefBrowserHostBase::GoBack, this);
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, std::move(callback));
+    return;
+  }
+
+  if (browser_info_->IsNavigationLocked(std::move(callback))) {
+    return;
+  }
+
+  auto wc = GetWebContents();
+  if (wc && wc->GetController().CanGoBack()) {
+    wc->GetController().GoBack();
+  }
+}
+
+bool CefBrowserHostBase::CanGoForward() {
+  base::AutoLock lock_scope(state_lock_);
+  return can_go_forward_;
+}
+
+void CefBrowserHostBase::GoForward() {
+  auto callback = base::BindOnce(&CefBrowserHostBase::GoForward, this);
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, std::move(callback));
+    return;
+  }
+
+  if (browser_info_->IsNavigationLocked(std::move(callback))) {
+    return;
+  }
+
+  auto wc = GetWebContents();
+  if (wc && wc->GetController().CanGoForward()) {
+    wc->GetController().GoForward();
+  }
+}
+
+bool CefBrowserHostBase::IsLoading() {
+  base::AutoLock lock_scope(state_lock_);
+  return is_loading_;
+}
+
+void CefBrowserHostBase::Reload() {
+  auto callback = base::BindOnce(&CefBrowserHostBase::Reload, this);
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, std::move(callback));
+    return;
+  }
+
+  if (browser_info_->IsNavigationLocked(std::move(callback))) {
+    return;
+  }
+
+  auto wc = GetWebContents();
+  if (wc) {
+    wc->GetController().Reload(content::ReloadType::NORMAL, true);
+  }
+}
+
+void CefBrowserHostBase::ReloadIgnoreCache() {
+  auto callback = base::BindOnce(&CefBrowserHostBase::ReloadIgnoreCache, this);
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, std::move(callback));
+    return;
+  }
+
+  if (browser_info_->IsNavigationLocked(std::move(callback))) {
+    return;
+  }
+
+  auto wc = GetWebContents();
+  if (wc) {
+    wc->GetController().Reload(content::ReloadType::BYPASSING_CACHE, true);
+  }
+}
+
+void CefBrowserHostBase::StopLoad() {
+  auto callback = base::BindOnce(&CefBrowserHostBase::StopLoad, this);
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, std::move(callback));
+    return;
+  }
+
+  if (browser_info_->IsNavigationLocked(std::move(callback))) {
+    return;
+  }
+
+  auto wc = GetWebContents();
+  if (wc) {
+    wc->Stop();
+  }
+}
+
+int CefBrowserHostBase::GetIdentifier() {
+  return browser_id();
+}
+
+bool CefBrowserHostBase::IsSame(CefRefPtr<CefBrowser> that) {
+  auto impl = static_cast<CefBrowserHostBase*>(that.get());
+  return (impl == this);
+}
+
+bool CefBrowserHostBase::HasDocument() {
+  base::AutoLock lock_scope(state_lock_);
+  return has_document_;
+}
+
+bool CefBrowserHostBase::IsPopup() {
+  return browser_info_->is_popup();
+}
+
+CefRefPtr<CefFrame> CefBrowserHostBase::GetMainFrame() {
+  return GetFrame(CefFrameHostImpl::kMainFrameId);
+}
+
+CefRefPtr<CefFrame> CefBrowserHostBase::GetFocusedFrame() {
+  return GetFrame(CefFrameHostImpl::kFocusedFrameId);
+}
+
+CefRefPtr<CefFrame> CefBrowserHostBase::GetFrame(int64_t identifier) {
+  if (identifier == CefFrameHostImpl::kInvalidFrameId) {
+    return nullptr;
+  } else if (identifier == CefFrameHostImpl::kMainFrameId) {
+    return browser_info_->GetMainFrame();
+  } else if (identifier == CefFrameHostImpl::kFocusedFrameId) {
+    base::AutoLock lock_scope(state_lock_);
+    if (!focused_frame_) {
+      // The main frame is focused by default.
+      return browser_info_->GetMainFrame();
+    }
+    return focused_frame_;
+  }
+
+  return browser_info_->GetFrameForGlobalId(
+      frame_util::MakeGlobalId(identifier));
+}
+
+CefRefPtr<CefFrame> CefBrowserHostBase::GetFrame(const CefString& name) {
+  for (const auto& frame : browser_info_->GetAllFrames()) {
+    if (frame->GetName() == name) {
+      return frame;
+    }
+  }
+  return nullptr;
+}
+
+size_t CefBrowserHostBase::GetFrameCount() {
+  return browser_info_->GetAllFrames().size();
+}
+
+void CefBrowserHostBase::GetFrameIdentifiers(
+    std::vector<int64_t>& identifiers) {
+  if (identifiers.size() > 0) {
+    identifiers.clear();
+  }
+
+  const auto frames = browser_info_->GetAllFrames();
+  if (frames.empty()) {
+    return;
+  }
+
+  identifiers.reserve(frames.size());
+  for (const auto& frame : frames) {
+    identifiers.push_back(frame->GetIdentifier());
+  }
+}
+
+void CefBrowserHostBase::GetFrameNames(std::vector<CefString>& names) {
+  if (names.size() > 0) {
+    names.clear();
+  }
+
+  const auto frames = browser_info_->GetAllFrames();
+  if (frames.empty()) {
+    return;
+  }
+
+  names.reserve(frames.size());
+  for (const auto& frame : frames) {
+    names.push_back(frame->GetName());
+  }
+}
+
+void CefBrowserHostBase::OnStateChanged(CefBrowserContentsState state_changed) {
+  // Make sure that CefBrowser state is consistent before the associated
+  // CefClient callback is executed.
+  base::AutoLock lock_scope(state_lock_);
+  if ((state_changed & CefBrowserContentsState::kNavigation) ==
+      CefBrowserContentsState::kNavigation) {
+    is_loading_ = contents_delegate_->is_loading();
+    can_go_back_ = contents_delegate_->can_go_back();
+    can_go_forward_ = contents_delegate_->can_go_forward();
+  }
+  if ((state_changed & CefBrowserContentsState::kDocument) ==
+      CefBrowserContentsState::kDocument) {
+    has_document_ = contents_delegate_->has_document();
+  }
+  if ((state_changed & CefBrowserContentsState::kFullscreen) ==
+      CefBrowserContentsState::kFullscreen) {
+    is_fullscreen_ = contents_delegate_->is_fullscreen();
+  }
+  if ((state_changed & CefBrowserContentsState::kFocusedFrame) ==
+      CefBrowserContentsState::kFocusedFrame) {
+    focused_frame_ = contents_delegate_->focused_frame();
+  }
+}
+
+void CefBrowserHostBase::OnWebContentsDestroyed(
+    content::WebContents* web_contents) {}
+
+CefRefPtr<CefFrame> CefBrowserHostBase::GetFrameForHost(
+    const content::RenderFrameHost* host) {
+  CEF_REQUIRE_UIT();
+  if (!host) {
+    return nullptr;
+  }
+
+  return browser_info_->GetFrameForHost(host);
+}
+
+CefRefPtr<CefFrame> CefBrowserHostBase::GetFrameForGlobalId(
+    const content::GlobalRenderFrameHostId& global_id) {
+  return browser_info_->GetFrameForGlobalId(global_id, nullptr);
+}
+
+void CefBrowserHostBase::AddObserver(Observer* observer) {
+  CEF_REQUIRE_UIT();
+  observers_.AddObserver(observer);
+}
+
+void CefBrowserHostBase::RemoveObserver(Observer* observer) {
+  CEF_REQUIRE_UIT();
+  observers_.RemoveObserver(observer);
+}
+
+bool CefBrowserHostBase::HasObserver(Observer* observer) const {
+  CEF_REQUIRE_UIT();
+  return observers_.HasObserver(observer);
+}
+
+void CefBrowserHostBase::LoadMainFrameURL(
+    const content::OpenURLParams& params) {
+  auto callback =
+      base::BindOnce(&CefBrowserHostBase::LoadMainFrameURL, this, params);
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, std::move(callback));
+    return;
+  }
+
+  if (browser_info_->IsNavigationLocked(std::move(callback))) {
+    return;
+  }
+
+  if (Navigate(params)) {
+    OnSetFocus(FOCUS_SOURCE_NAVIGATION);
+  }
+}
+
+bool CefBrowserHostBase::Navigate(const content::OpenURLParams& params) {
+  CEF_REQUIRE_UIT();
+  auto web_contents = GetWebContents();
+  if (web_contents) {
+    GURL gurl = params.url;
+    if (!url_util::FixupGURL(gurl)) {
+      return false;
+    }
+
+    web_contents->GetController().LoadURL(
+        gurl, params.referrer, params.transition, params.extra_headers);
+    return true;
+  }
+  return false;
+}
+
+void CefBrowserHostBase::ViewText(const std::string& text) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&CefBrowserHostBase::ViewText, this, text));
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->ViewText(text);
+  }
+}
+
+void CefBrowserHostBase::RunFileChooserForBrowser(
+    const blink::mojom::FileChooserParams& params,
+    CefFileDialogManager::RunFileChooserCallback callback) {
+  if (!EnsureFileDialogManager()) {
+    LOG(ERROR) << "File dialog canceled due to invalid state.";
+    std::move(callback).Run({});
+    return;
+  }
+  file_dialog_manager_->RunFileChooser(params, std::move(callback));
+}
+
+void CefBrowserHostBase::RunSelectFile(
+    ui::SelectFileDialog::Listener* listener,
+    std::unique_ptr<ui::SelectFilePolicy> policy,
+    ui::SelectFileDialog::Type type,
+    const std::u16string& title,
+    const base::FilePath& default_path,
+    const ui::SelectFileDialog::FileTypeInfo* file_types,
+    int file_type_index,
+    const base::FilePath::StringType& default_extension,
+    gfx::NativeWindow owning_window,
+    void* params) {
+  if (!EnsureFileDialogManager()) {
+    LOG(ERROR) << "File dialog canceled due to invalid state.";
+    listener->FileSelectionCanceled(params);
+    return;
+  }
+  file_dialog_manager_->RunSelectFile(listener, std::move(policy), type, title,
+                                      default_path, file_types, file_type_index,
+                                      default_extension, owning_window, params);
+}
+
+void CefBrowserHostBase::SelectFileListenerDestroyed(
+    ui::SelectFileDialog::Listener* listener) {
+  if (file_dialog_manager_) {
+    file_dialog_manager_->SelectFileListenerDestroyed(listener);
+  }
+}
+
+bool CefBrowserHostBase::MaybeAllowNavigation(
+    content::RenderFrameHost* opener,
+    bool is_guest_view,
+    const content::OpenURLParams& params) {
+  return true;
+}
+
+void CefBrowserHostBase::OnAfterCreated() {
+  CEF_REQUIRE_UIT();
+  if (client_) {
+    if (auto handler = client_->GetLifeSpanHandler()) {
+      handler->OnAfterCreated(this);
+    }
+  }
+}
+
+void CefBrowserHostBase::OnBeforeClose() {
+  CEF_REQUIRE_UIT();
+  if (client_) {
+    if (auto handler = client_->GetLifeSpanHandler()) {
+      handler->OnBeforeClose(this);
+    }
+  }
+  browser_info_->SetClosing();
+}
+
+void CefBrowserHostBase::OnBrowserDestroyed() {
+  CEF_REQUIRE_UIT();
+
+  // Destroy any platform constructs.
+  if (file_dialog_manager_) {
+    file_dialog_manager_->Destroy();
+    file_dialog_manager_.reset();
+  }
+
+  for (auto& observer : observers_) {
+    observer.OnBrowserDestroyed(this);
+  }
+}
+
+int CefBrowserHostBase::browser_id() const {
+  return browser_info_->browser_id();
+}
+
+SkColor CefBrowserHostBase::GetBackgroundColor() const {
+  // Don't use |platform_delegate_| because it's not thread-safe.
+  return CefContext::Get()->GetBackgroundColor(
+      &settings_, IsWindowless() ? STATE_ENABLED : STATE_DISABLED);
+}
+
+bool CefBrowserHostBase::IsWindowless() const {
+  return false;
+}
+
+content::WebContents* CefBrowserHostBase::GetWebContents() const {
+  CEF_REQUIRE_UIT();
+  return contents_delegate_->web_contents();
+}
+
+content::BrowserContext* CefBrowserHostBase::GetBrowserContext() const {
+  CEF_REQUIRE_UIT();
+  auto web_contents = GetWebContents();
+  if (web_contents) {
+    return web_contents->GetBrowserContext();
+  }
+  return nullptr;
+}
+
+CefMediaStreamRegistrar* CefBrowserHostBase::GetMediaStreamRegistrar() {
+  CEF_REQUIRE_UIT();
+  if (!media_stream_registrar_) {
+    media_stream_registrar_ = std::make_unique<CefMediaStreamRegistrar>(this);
+  }
+  return media_stream_registrar_.get();
+}
+
+views::Widget* CefBrowserHostBase::GetWindowWidget() const {
+  CEF_REQUIRE_UIT();
+  if (!platform_delegate_) {
+    return nullptr;
+  }
+  return platform_delegate_->GetWindowWidget();
+}
+
+CefRefPtr<CefBrowserView> CefBrowserHostBase::GetBrowserView() const {
+  CEF_REQUIRE_UIT();
+  if (is_views_hosted_ && platform_delegate_) {
+    return platform_delegate_->GetBrowserView();
+  }
+  return nullptr;
+}
+
+gfx::NativeWindow CefBrowserHostBase::GetTopLevelNativeWindow() const {
+  CEF_REQUIRE_UIT();
+  // Windowless browsers always return nullptr from GetTopLevelNativeWindow().
+  if (!IsWindowless()) {
+    auto web_contents = GetWebContents();
+    if (web_contents) {
+      return web_contents->GetTopLevelNativeWindow();
+    }
+  }
+  return gfx::NativeWindow();
+}
+
+bool CefBrowserHostBase::IsFocused() const {
+  CEF_REQUIRE_UIT();
+  auto web_contents = GetWebContents();
+  if (web_contents) {
+    return static_cast<content::RenderFrameHostImpl*>(
+               web_contents->GetPrimaryMainFrame())
+        ->IsFocused();
+  }
+  return false;
+}
+
+bool CefBrowserHostBase::IsVisible() const {
+  CEF_REQUIRE_UIT();
+  // Windowless browsers always return nullptr from GetNativeView().
+  if (!IsWindowless()) {
+    auto web_contents = GetWebContents();
+    if (web_contents) {
+      return platform_util::IsVisible(web_contents->GetNativeView());
+    }
+  }
+  return false;
+}
+
+bool CefBrowserHostBase::EnsureDevToolsManager() {
+  CEF_REQUIRE_UIT();
+  if (!contents_delegate_->web_contents()) {
+    return false;
+  }
+
+  if (!devtools_manager_) {
+    devtools_manager_ = std::make_unique<CefDevToolsManager>(this);
+  }
+  return true;
+}
+
+void CefBrowserHostBase::InitializeDevToolsRegistrationOnUIThread(
+    CefRefPtr<CefRegistration> registration) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(
+            &CefBrowserHostBase::InitializeDevToolsRegistrationOnUIThread, this,
+            registration));
+    return;
+  }
+
+  if (!EnsureDevToolsManager()) {
+    return;
+  }
+  devtools_manager_->InitializeRegistrationOnUIThread(registration);
+}
+
+bool CefBrowserHostBase::EnsureFileDialogManager() {
+  CEF_REQUIRE_UIT();
+  if (!contents_delegate_->web_contents()) {
+    return false;
+  }
+
+  if (!file_dialog_manager_) {
+    file_dialog_manager_ = std::make_unique<CefFileDialogManager>(this);
+  }
+  return true;
+}
diff --git a/src/libcef/browser/browser_host_base.h b/src/libcef/browser/browser_host_base.h
new file mode 100644
index 0000000..f1724c5
--- /dev/null
+++ b/src/libcef/browser/browser_host_base.h
@@ -0,0 +1,414 @@
+// Copyright 2020 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_BROWSER_HOST_BASE_H_
+#define CEF_LIBCEF_BROWSER_BROWSER_HOST_BASE_H_
+#pragma once
+
+#include "include/cef_browser.h"
+#include "include/cef_client.h"
+#include "include/views/cef_browser_view.h"
+#include "libcef/browser/browser_contents_delegate.h"
+#include "libcef/browser/browser_info.h"
+#include "libcef/browser/browser_platform_delegate.h"
+#include "libcef/browser/devtools/devtools_manager.h"
+#include "libcef/browser/file_dialog_manager.h"
+#include "libcef/browser/frame_host_impl.h"
+#include "libcef/browser/media_stream_registrar.h"
+#include "libcef/browser/request_context_impl.h"
+
+#include "base/observer_list.h"
+#include "base/synchronization/lock.h"
+#include "extensions/common/mojom/view_type.mojom.h"
+
+namespace extensions {
+class Extension;
+}
+
+// Parameters that are passed to the runtime-specific Create methods.
+struct CefBrowserCreateParams {
+  CefBrowserCreateParams() {}
+
+  // Copy constructor used with the chrome runtime only.
+  CefBrowserCreateParams(const CefBrowserCreateParams& that) {
+    operator=(that);
+  }
+  CefBrowserCreateParams& operator=(const CefBrowserCreateParams& that) {
+    // Not all parameters can be copied.
+    client = that.client;
+    url = that.url;
+    settings = that.settings;
+    request_context = that.request_context;
+    extra_info = that.extra_info;
+    if (that.window_info) {
+      MaybeSetWindowInfo(*that.window_info);
+    }
+    browser_view = that.browser_view;
+    return *this;
+  }
+
+  // Set |window_info| if appropriate (see below).
+  void MaybeSetWindowInfo(const CefWindowInfo& window_info);
+
+  // Platform-specific window creation info. Will be nullptr for Views-hosted
+  // browsers except when using the Chrome runtime with a native parent handle.
+  std::unique_ptr<CefWindowInfo> window_info;
+
+  // The BrowserView that will own a Views-hosted browser. Will be nullptr for
+  // popup browsers.
+  CefRefPtr<CefBrowserView> browser_view;
+
+  // True if this browser is a popup and has a Views-hosted opener, in which
+  // case the BrowserView for this browser will be created later (from
+  // PopupWebContentsCreated).
+  bool popup_with_views_hosted_opener = false;
+
+  // Client implementation. May be nullptr.
+  CefRefPtr<CefClient> client;
+
+  // Initial URL to load. May be empty. If this is a valid extension URL then
+  // the browser will be created as an app view extension host.
+  CefString url;
+
+  // Browser settings.
+  CefBrowserSettings settings;
+
+  // Other browser that opened this DevTools browser. Will be nullptr for non-
+  // DevTools browsers. Currently used with the alloy runtime only.
+  CefRefPtr<CefBrowserHostBase> devtools_opener;
+
+  // Request context to use when creating the browser. If nullptr the global
+  // request context will be used.
+  CefRefPtr<CefRequestContext> request_context;
+
+  // Extra information that will be passed to
+  // CefRenderProcessHandler::OnBrowserCreated.
+  CefRefPtr<CefDictionaryValue> extra_info;
+
+  // Used when explicitly creating the browser as an extension host via
+  // ProcessManager::CreateBackgroundHost. Currently used with the alloy
+  // runtime only.
+  const extensions::Extension* extension = nullptr;
+  extensions::mojom::ViewType extension_host_type =
+      extensions::mojom::ViewType::kInvalid;
+};
+
+// Parameters passed to ShowDevToolsOnUIThread().
+struct CefShowDevToolsParams {
+  CefShowDevToolsParams(const CefWindowInfo& windowInfo,
+                        CefRefPtr<CefClient> client,
+                        const CefBrowserSettings& settings,
+                        const CefPoint& inspect_element_at)
+      : window_info_(windowInfo),
+        client_(client),
+        settings_(settings),
+        inspect_element_at_(inspect_element_at) {}
+
+  CefWindowInfo window_info_;
+  CefRefPtr<CefClient> client_;
+  CefBrowserSettings settings_;
+  CefPoint inspect_element_at_;
+};
+
+// Base class for CefBrowserHost implementations. Includes functionality that is
+// shared by the alloy and chrome runtimes. All methods are thread-safe unless
+// otherwise indicated.
+class CefBrowserHostBase : public CefBrowserHost,
+                           public CefBrowser,
+                           public CefBrowserContentsDelegate::Observer {
+ public:
+  // Interface to implement for observers that wish to be informed of changes
+  // to the CefBrowserHostBase. All methods will be called on the UI thread.
+  class Observer : public base::CheckedObserver {
+   public:
+    // Called before |browser| is destroyed. Any references to |browser| should
+    // be cleared when this method is called.
+    virtual void OnBrowserDestroyed(CefBrowserHostBase* browser) = 0;
+
+   protected:
+    virtual ~Observer() {}
+  };
+
+  // Create a new CefBrowserHost instance of the current runtime type with
+  // owned WebContents.
+  static CefRefPtr<CefBrowserHostBase> Create(
+      CefBrowserCreateParams& create_params);
+
+  // Returns the browser associated with the specified RenderViewHost.
+  static CefRefPtr<CefBrowserHostBase> GetBrowserForHost(
+      const content::RenderViewHost* host);
+  // Returns the browser associated with the specified RenderFrameHost.
+  static CefRefPtr<CefBrowserHostBase> GetBrowserForHost(
+      const content::RenderFrameHost* host);
+  // Returns the browser associated with the specified WebContents.
+  static CefRefPtr<CefBrowserHostBase> GetBrowserForContents(
+      const content::WebContents* contents);
+  // Returns the browser associated with the specified global ID.
+  static CefRefPtr<CefBrowserHostBase> GetBrowserForGlobalId(
+      const content::GlobalRenderFrameHostId& global_id);
+  // Returns the browser associated with the specified top-level window.
+  static CefRefPtr<CefBrowserHostBase> GetBrowserForTopLevelNativeWindow(
+      gfx::NativeWindow owning_window);
+
+  // Returns the browser most likely to be focused. This may be somewhat iffy
+  // with windowless browsers as there is no guarantee that the client has only
+  // one browser focused at a time.
+  static CefRefPtr<CefBrowserHostBase> GetLikelyFocusedBrowser();
+
+  CefBrowserHostBase(
+      const CefBrowserSettings& settings,
+      CefRefPtr<CefClient> client,
+      std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
+      scoped_refptr<CefBrowserInfo> browser_info,
+      CefRefPtr<CefRequestContextImpl> request_context);
+
+  CefBrowserHostBase(const CefBrowserHostBase&) = delete;
+  CefBrowserHostBase& operator=(const CefBrowserHostBase&) = delete;
+
+  // Called on the UI thread after the associated WebContents is created.
+  virtual void InitializeBrowser();
+
+  // Called on the UI thread when the OS window hosting the browser is
+  // destroyed.
+  virtual void WindowDestroyed() = 0;
+
+  // Returns true if the browser is in the process of being destroyed. Called on
+  // the UI thread only.
+  virtual bool WillBeDestroyed() const = 0;
+
+  // Called on the UI thread after the associated WebContents is destroyed.
+  // Also called from CefBrowserInfoManager::DestroyAllBrowsers if the browser
+  // was not properly shut down.
+  virtual void DestroyBrowser();
+
+  // CefBrowserHost methods:
+  CefRefPtr<CefBrowser> GetBrowser() override;
+  CefRefPtr<CefClient> GetClient() override;
+  CefRefPtr<CefRequestContext> GetRequestContext() override;
+  bool CanZoom(cef_zoom_command_t command) override;
+  void Zoom(cef_zoom_command_t command) override;
+  double GetDefaultZoomLevel() override;
+  double GetZoomLevel() override;
+  void SetZoomLevel(double zoomLevel) override;
+  bool HasView() override;
+  void SetFocus(bool focus) override;
+  void RunFileDialog(FileDialogMode mode,
+                     const CefString& title,
+                     const CefString& default_file_path,
+                     const std::vector<CefString>& accept_filters,
+                     CefRefPtr<CefRunFileDialogCallback> callback) override;
+  void StartDownload(const CefString& url) override;
+  void DownloadImage(const CefString& image_url,
+                     bool is_favicon,
+                     uint32_t max_image_size,
+                     bool bypass_cache,
+                     CefRefPtr<CefDownloadImageCallback> callback) override;
+  void Print() override;
+  void PrintToPDF(const CefString& path,
+                  const CefPdfPrintSettings& settings,
+                  CefRefPtr<CefPdfPrintCallback> callback) override;
+  void ShowDevTools(const CefWindowInfo& windowInfo,
+                    CefRefPtr<CefClient> client,
+                    const CefBrowserSettings& settings,
+                    const CefPoint& inspect_element_at) override;
+  void ReplaceMisspelling(const CefString& word) override;
+  void AddWordToDictionary(const CefString& word) override;
+  void SendKeyEvent(const CefKeyEvent& event) override;
+  void SendMouseClickEvent(const CefMouseEvent& event,
+                           MouseButtonType type,
+                           bool mouseUp,
+                           int clickCount) override;
+  void SendMouseMoveEvent(const CefMouseEvent& event, bool mouseLeave) override;
+  void SendMouseWheelEvent(const CefMouseEvent& event,
+                           int deltaX,
+                           int deltaY) override;
+  bool SendDevToolsMessage(const void* message, size_t message_size) override;
+  int ExecuteDevToolsMethod(int message_id,
+                            const CefString& method,
+                            CefRefPtr<CefDictionaryValue> params) override;
+  CefRefPtr<CefRegistration> AddDevToolsMessageObserver(
+      CefRefPtr<CefDevToolsMessageObserver> observer) override;
+  void GetNavigationEntries(CefRefPtr<CefNavigationEntryVisitor> visitor,
+                            bool current_only) override;
+  CefRefPtr<CefNavigationEntry> GetVisibleNavigationEntry() override;
+  void NotifyMoveOrResizeStarted() override;
+  bool IsFullscreen() override;
+  void ExitFullscreen(bool will_cause_resize) override;
+
+  // CefBrowser methods:
+  bool IsValid() override;
+  CefRefPtr<CefBrowserHost> GetHost() override;
+  bool CanGoBack() override;
+  void GoBack() override;
+  bool CanGoForward() override;
+  void GoForward() override;
+  bool IsLoading() override;
+  void Reload() override;
+  void ReloadIgnoreCache() override;
+  void StopLoad() override;
+  int GetIdentifier() override;
+  bool IsSame(CefRefPtr<CefBrowser> that) override;
+  bool HasDocument() override;
+  bool IsPopup() override;
+  CefRefPtr<CefFrame> GetMainFrame() override;
+  CefRefPtr<CefFrame> GetFocusedFrame() override;
+  CefRefPtr<CefFrame> GetFrame(int64_t identifier) override;
+  CefRefPtr<CefFrame> GetFrame(const CefString& name) override;
+  size_t GetFrameCount() override;
+  void GetFrameIdentifiers(std::vector<int64_t>& identifiers) override;
+  void GetFrameNames(std::vector<CefString>& names) override;
+
+  // CefBrowserContentsDelegate::Observer methods:
+  void OnStateChanged(CefBrowserContentsState state_changed) override;
+  void OnWebContentsDestroyed(content::WebContents* web_contents) override;
+
+  // Returns the frame associated with the specified RenderFrameHost.
+  CefRefPtr<CefFrame> GetFrameForHost(const content::RenderFrameHost* host);
+
+  // Returns the frame associated with the specified global ID. See
+  // documentation on RenderFrameHost::GetFrameTreeNodeId() for why the global
+  // ID is preferred.
+  CefRefPtr<CefFrame> GetFrameForGlobalId(
+      const content::GlobalRenderFrameHostId& global_id);
+
+  // Manage observer objects. The observer must either outlive this object or
+  // be removed before destruction. Must be called on the UI thread.
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+  bool HasObserver(Observer* observer) const;
+
+  // Methods called from CefFrameHostImpl.
+  void LoadMainFrameURL(const content::OpenURLParams& params);
+  virtual void OnSetFocus(cef_focus_source_t source) = 0;
+  void ViewText(const std::string& text);
+
+  // Calls CefFileDialogManager methods.
+  void RunFileChooserForBrowser(
+      const blink::mojom::FileChooserParams& params,
+      CefFileDialogManager::RunFileChooserCallback callback);
+  void RunSelectFile(ui::SelectFileDialog::Listener* listener,
+                     std::unique_ptr<ui::SelectFilePolicy> policy,
+                     ui::SelectFileDialog::Type type,
+                     const std::u16string& title,
+                     const base::FilePath& default_path,
+                     const ui::SelectFileDialog::FileTypeInfo* file_types,
+                     int file_type_index,
+                     const base::FilePath::StringType& default_extension,
+                     gfx::NativeWindow owning_window,
+                     void* params);
+  void SelectFileListenerDestroyed(ui::SelectFileDialog::Listener* listener);
+
+  // Called from CefBrowserInfoManager::MaybeAllowNavigation.
+  virtual bool MaybeAllowNavigation(content::RenderFrameHost* opener,
+                                    bool is_guest_view,
+                                    const content::OpenURLParams& params);
+
+  // Helpers for executing client callbacks. Must be called on the UI thread.
+  void OnAfterCreated();
+  void OnBeforeClose();
+  void OnBrowserDestroyed();
+
+  // Thread-safe accessors.
+  const CefBrowserSettings& settings() const { return settings_; }
+  CefRefPtr<CefClient> client() const { return client_; }
+  scoped_refptr<CefBrowserInfo> browser_info() const { return browser_info_; }
+  int browser_id() const;
+  CefRefPtr<CefRequestContextImpl> request_context() const {
+    return request_context_;
+  }
+  bool is_views_hosted() const { return is_views_hosted_; }
+  SkColor GetBackgroundColor() const;
+
+  // Returns true if windowless rendering is enabled.
+  virtual bool IsWindowless() const;
+
+  // Accessors that must be called on the UI thread.
+  content::WebContents* GetWebContents() const;
+  content::BrowserContext* GetBrowserContext() const;
+  CefBrowserPlatformDelegate* platform_delegate() const {
+    return platform_delegate_.get();
+  }
+  CefBrowserContentsDelegate* contents_delegate() const {
+    return contents_delegate_.get();
+  }
+  CefMediaStreamRegistrar* GetMediaStreamRegistrar();
+
+  // Returns the Widget owner for the browser window. Only used with windowed
+  // browsers.
+  views::Widget* GetWindowWidget() const;
+
+  // Returns the BrowserView associated with this browser. Only used with Views-
+  // based browsers.
+  CefRefPtr<CefBrowserView> GetBrowserView() const;
+
+  // Returns the top-level native window for this browser. With windowed
+  // browsers this will be an aura::Window* on Aura platforms (Windows/Linux)
+  // and an NSWindow wrapper object from native_widget_types.h on MacOS. With
+  // windowless browsers this method will always return an empty value.
+  gfx::NativeWindow GetTopLevelNativeWindow() const;
+
+  // Returns true if this browser is currently focused. A browser is considered
+  // focused when the top-level RenderFrameHost is in the parent chain of the
+  // currently focused RFH within the frame tree. In addition, its associated
+  // RenderWidgetHost must also be focused. With windowed browsers only one
+  // browser should be focused at a time. With windowless browsers this relies
+  // on the client to properly configure focus state.
+  bool IsFocused() const;
+
+  // Returns true if this browser is currently visible.
+  virtual bool IsVisible() const;
+
+ protected:
+  bool EnsureDevToolsManager();
+  void InitializeDevToolsRegistrationOnUIThread(
+      CefRefPtr<CefRegistration> registration);
+
+  // Called from LoadMainFrameURL to perform the actual navigation.
+  virtual bool Navigate(const content::OpenURLParams& params);
+
+  // Called from ShowDevTools to perform the actual show.
+  virtual void ShowDevToolsOnUIThread(
+      std::unique_ptr<CefShowDevToolsParams> params) = 0;
+
+  // Create the CefFileDialogManager if it doesn't already exist.
+  bool EnsureFileDialogManager();
+
+  // Thread-safe members.
+  CefBrowserSettings settings_;
+  CefRefPtr<CefClient> client_;
+  std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate_;
+  scoped_refptr<CefBrowserInfo> browser_info_;
+  CefRefPtr<CefRequestContextImpl> request_context_;
+  const bool is_views_hosted_;
+
+  // Only accessed on the UI thread.
+  std::unique_ptr<CefBrowserContentsDelegate> contents_delegate_;
+
+  // Observers that want to be notified of changes to this object.
+  // Only accessed on the UI thread.
+  base::ObserverList<Observer> observers_;
+
+  // Used for creating and managing file dialogs.
+  std::unique_ptr<CefFileDialogManager> file_dialog_manager_;
+
+  // Volatile state accessed from multiple threads. All access must be protected
+  // by |state_lock_|.
+  base::Lock state_lock_;
+  bool is_loading_ = false;
+  bool can_go_back_ = false;
+  bool can_go_forward_ = false;
+  bool has_document_ = false;
+  bool is_fullscreen_ = false;
+  CefRefPtr<CefFrameHostImpl> focused_frame_;
+
+  // Used for creating and managing DevTools instances.
+  std::unique_ptr<CefDevToolsManager> devtools_manager_;
+
+  std::unique_ptr<CefMediaStreamRegistrar> media_stream_registrar_;
+
+ private:
+  IMPLEMENT_REFCOUNTING(CefBrowserHostBase);
+};
+
+#endif  // CEF_LIBCEF_BROWSER_BROWSER_HOST_BASE_H_
diff --git a/src/libcef/browser/browser_host_create.cc b/src/libcef/browser/browser_host_create.cc
new file mode 100644
index 0000000..1ea8288
--- /dev/null
+++ b/src/libcef/browser/browser_host_create.cc
@@ -0,0 +1,174 @@
+// Copyright (c) 2012 The Chromium Embedded Framework Authors.
+// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "include/cef_browser.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
+#include "libcef/browser/chrome/chrome_browser_host_impl.h"
+#include "libcef/browser/chrome/views/chrome_child_window.h"
+#include "libcef/browser/context.h"
+#include "libcef/browser/thread_util.h"
+#include "libcef/features/runtime.h"
+
+namespace {
+
+class CreateBrowserHelper {
+ public:
+  CreateBrowserHelper(const CefWindowInfo& windowInfo,
+                      CefRefPtr<CefClient> client,
+                      const CefString& url,
+                      const CefBrowserSettings& settings,
+                      CefRefPtr<CefDictionaryValue> extra_info,
+                      CefRefPtr<CefRequestContext> request_context)
+      : window_info_(windowInfo),
+        client_(client),
+        url_(url),
+        settings_(settings),
+        extra_info_(extra_info),
+        request_context_(request_context) {}
+
+  void Run() {
+    CefBrowserHost::CreateBrowserSync(window_info_, client_, url_, settings_,
+                                      extra_info_, request_context_);
+  }
+
+  CefWindowInfo window_info_;
+  CefRefPtr<CefClient> client_;
+  CefString url_;
+  CefBrowserSettings settings_;
+  CefRefPtr<CefDictionaryValue> extra_info_;
+  CefRefPtr<CefRequestContext> request_context_;
+};
+
+}  // namespace
+
+// static
+bool CefBrowserHost::CreateBrowser(
+    const CefWindowInfo& windowInfo,
+    CefRefPtr<CefClient> client,
+    const CefString& url,
+    const CefBrowserSettings& settings,
+    CefRefPtr<CefDictionaryValue> extra_info,
+    CefRefPtr<CefRequestContext> request_context) {
+  // Verify that the context is in a valid state.
+  if (!CONTEXT_STATE_VALID()) {
+    DCHECK(false) << "context not valid";
+    return false;
+  }
+
+  // Verify that the settings structure is a valid size.
+  if (settings.size != sizeof(cef_browser_settings_t)) {
+    DCHECK(false) << "invalid CefBrowserSettings structure size";
+    return false;
+  }
+
+  // Verify windowless rendering requirements.
+  if (windowInfo.windowless_rendering_enabled &&
+      !client->GetRenderHandler().get()) {
+    DCHECK(false) << "CefRenderHandler implementation is required";
+    return false;
+  }
+
+  if (windowInfo.windowless_rendering_enabled &&
+      !CefContext::Get()->settings().windowless_rendering_enabled) {
+    LOG(ERROR) << "Creating a windowless browser without setting "
+                  "CefSettings.windowless_rendering_enabled may result in "
+                  "reduced performance or runtime errors.";
+  }
+
+  if (!request_context) {
+    request_context = CefRequestContext::GetGlobalContext();
+  }
+
+  auto helper = std::make_unique<CreateBrowserHelper>(
+      windowInfo, client, url, settings, extra_info, request_context);
+
+  auto request_context_impl =
+      static_cast<CefRequestContextImpl*>(request_context.get());
+
+  // Wait for the browser context to be initialized before creating the browser.
+  request_context_impl->ExecuteWhenBrowserContextInitialized(base::BindOnce(
+      [](std::unique_ptr<CreateBrowserHelper> helper) {
+        // Always execute asynchronously to avoid potential issues if we're
+        // being called synchronously during app initialization.
+        CEF_POST_TASK(CEF_UIT, base::BindOnce(&CreateBrowserHelper::Run,
+                                              std::move(helper)));
+      },
+      std::move(helper)));
+
+  return true;
+}
+
+// static
+CefRefPtr<CefBrowser> CefBrowserHost::CreateBrowserSync(
+    const CefWindowInfo& windowInfo,
+    CefRefPtr<CefClient> client,
+    const CefString& url,
+    const CefBrowserSettings& settings,
+    CefRefPtr<CefDictionaryValue> extra_info,
+    CefRefPtr<CefRequestContext> request_context) {
+  // Verify that the context is in a valid state.
+  if (!CONTEXT_STATE_VALID()) {
+    DCHECK(false) << "context not valid";
+    return nullptr;
+  }
+
+  // Verify that the settings structure is a valid size.
+  if (settings.size != sizeof(cef_browser_settings_t)) {
+    DCHECK(false) << "invalid CefBrowserSettings structure size";
+    return nullptr;
+  }
+
+  if (!request_context) {
+    request_context = CefRequestContext::GetGlobalContext();
+  }
+
+  // Verify that the browser context is valid.
+  auto request_context_impl =
+      static_cast<CefRequestContextImpl*>(request_context.get());
+  if (!request_context_impl->VerifyBrowserContext()) {
+    return nullptr;
+  }
+
+  // Verify windowless rendering requirements.
+  if (windowInfo.windowless_rendering_enabled &&
+      !client->GetRenderHandler().get()) {
+    DCHECK(false) << "CefRenderHandler implementation is required";
+    return nullptr;
+  }
+
+  CefBrowserCreateParams create_params;
+  create_params.MaybeSetWindowInfo(windowInfo);
+  create_params.client = client;
+  create_params.url = url;
+  create_params.settings = settings;
+  create_params.extra_info = extra_info;
+  create_params.request_context = request_context;
+
+  return CefBrowserHostBase::Create(create_params);
+}
+
+void CefBrowserCreateParams::MaybeSetWindowInfo(
+    const CefWindowInfo& new_window_info) {
+  if (!cef::IsChromeRuntimeEnabled() ||
+      chrome_child_window::HasParentHandle(new_window_info)) {
+    window_info = std::make_unique<CefWindowInfo>(new_window_info);
+  }
+}
+
+// static
+CefRefPtr<CefBrowserHostBase> CefBrowserHostBase::Create(
+    CefBrowserCreateParams& create_params) {
+  if (cef::IsChromeRuntimeEnabled()) {
+    if (auto browser =
+            chrome_child_window::MaybeCreateChildBrowser(create_params)) {
+      return browser.get();
+    }
+    auto browser = ChromeBrowserHostImpl::Create(create_params);
+    return browser.get();
+  }
+
+  auto browser = AlloyBrowserHostImpl::Create(create_params);
+  return browser.get();
+}
diff --git a/src/libcef/browser/browser_host_impl.cc b/src/libcef/browser/browser_host_impl.cc
deleted file mode 100644
index 865786b..0000000
--- a/src/libcef/browser/browser_host_impl.cc
+++ /dev/null
@@ -1,3216 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/browser_host_impl.h"
-
-#include <string>
-#include <utility>
-
-#include "libcef/browser/audio_capturer.h"
-#include "libcef/browser/browser_context.h"
-#include "libcef/browser/browser_info.h"
-#include "libcef/browser/browser_info_manager.h"
-#include "libcef/browser/browser_platform_delegate.h"
-#include "libcef/browser/browser_util.h"
-#include "libcef/browser/content_browser_client.h"
-#include "libcef/browser/context.h"
-#include "libcef/browser/devtools/devtools_manager.h"
-#include "libcef/browser/extensions/browser_extensions_util.h"
-#include "libcef/browser/extensions/extension_background_host.h"
-#include "libcef/browser/extensions/extension_system.h"
-#include "libcef/browser/extensions/extension_view_host.h"
-#include "libcef/browser/extensions/extension_web_contents_observer.h"
-#include "libcef/browser/image_impl.h"
-#include "libcef/browser/media_capture_devices_dispatcher.h"
-#include "libcef/browser/navigation_entry_impl.h"
-#include "libcef/browser/net/chrome_scheme_handler.h"
-#include "libcef/browser/net/scheme_handler.h"
-#include "libcef/browser/osr/osr_util.h"
-#include "libcef/browser/printing/print_view_manager.h"
-#include "libcef/browser/request_context_impl.h"
-#include "libcef/browser/thread_util.h"
-#include "libcef/common/cef_messages.h"
-#include "libcef/common/cef_switches.h"
-#include "libcef/common/drag_data_impl.h"
-#include "libcef/common/extensions/extensions_util.h"
-#include "libcef/common/main_delegate.h"
-#include "libcef/common/request_impl.h"
-#include "libcef/common/values_impl.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/command_line.h"
-#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
-#include "chrome/browser/printing/print_view_manager.h"
-#include "chrome/browser/spellchecker/spellcheck_factory.h"
-#include "chrome/browser/spellchecker/spellcheck_service.h"
-#include "chrome/browser/ui/prefs/prefs_tab_helper.h"
-#include "components/favicon/core/favicon_url.h"
-#include "components/spellcheck/common/spellcheck_features.h"
-#include "components/zoom/zoom_controller.h"
-#include "content/browser/gpu/compositor_util.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/common/widget_messages.h"
-#include "content/public/browser/desktop_media_id.h"
-#include "content/public/browser/download_manager.h"
-#include "content/public/browser/download_request_utils.h"
-#include "content/public/browser/file_select_listener.h"
-#include "content/public/browser/host_zoom_map.h"
-#include "content/public/browser/keyboard_event_processing_result.h"
-#include "content/public/browser/native_web_keyboard_event.h"
-#include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_widget_host.h"
-#include "content/public/browser/web_contents.h"
-#include "extensions/browser/process_manager.h"
-#include "net/base/net_errors.h"
-#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
-#include "ui/events/base_event_utils.h"
-
-#if defined(OS_MACOSX)
-#include "components/spellcheck/browser/spellcheck_platform.h"
-#endif
-
-using content::KeyboardEventProcessingResult;
-
-namespace {
-
-// Associates a CefBrowserHostImpl instance with a WebContents. This object will
-// be deleted automatically when the WebContents is destroyed.
-class WebContentsUserDataAdapter : public base::SupportsUserData::Data {
- public:
-  static void Register(CefBrowserHostImpl* browser) {
-    new WebContentsUserDataAdapter(browser);
-  }
-
-  static CefBrowserHostImpl* Get(const content::WebContents* web_contents) {
-    WebContentsUserDataAdapter* adapter =
-        static_cast<WebContentsUserDataAdapter*>(
-            web_contents->GetUserData(UserDataKey()));
-    if (adapter)
-      return adapter->browser_;
-    return nullptr;
-  }
-
- private:
-  WebContentsUserDataAdapter(CefBrowserHostImpl* browser) : browser_(browser) {
-    browser->web_contents()->SetUserData(UserDataKey(), base::WrapUnique(this));
-  }
-
-  static void* UserDataKey() {
-    // We just need a unique constant. Use the address of a static that
-    // COMDAT folding won't touch in an optimizing linker.
-    static int data_key = 0;
-    return reinterpret_cast<void*>(&data_key);
-  }
-
-  CefBrowserHostImpl* browser_;  // Not owned.
-};
-
-class CreateBrowserHelper {
- public:
-  CreateBrowserHelper(const CefWindowInfo& windowInfo,
-                      CefRefPtr<CefClient> client,
-                      const CefString& url,
-                      const CefBrowserSettings& settings,
-                      CefRefPtr<CefDictionaryValue> extra_info,
-                      CefRefPtr<CefRequestContext> request_context)
-      : window_info_(windowInfo),
-        client_(client),
-        url_(url),
-        settings_(settings),
-        extra_info_(extra_info),
-        request_context_(request_context) {}
-
-  CefWindowInfo window_info_;
-  CefRefPtr<CefClient> client_;
-  CefString url_;
-  CefBrowserSettings settings_;
-  CefRefPtr<CefDictionaryValue> extra_info_;
-  CefRefPtr<CefRequestContext> request_context_;
-};
-
-void CreateBrowserWithHelper(CreateBrowserHelper* helper) {
-  CefBrowserHost::CreateBrowserSync(
-      helper->window_info_, helper->client_, helper->url_, helper->settings_,
-      helper->extra_info_, helper->request_context_);
-  delete helper;
-}
-
-class ShowDevToolsHelper {
- public:
-  ShowDevToolsHelper(CefRefPtr<CefBrowserHostImpl> browser,
-                     const CefWindowInfo& windowInfo,
-                     CefRefPtr<CefClient> client,
-                     const CefBrowserSettings& settings,
-                     const CefPoint& inspect_element_at)
-      : browser_(browser),
-        window_info_(windowInfo),
-        client_(client),
-        settings_(settings),
-        inspect_element_at_(inspect_element_at) {}
-
-  CefRefPtr<CefBrowserHostImpl> browser_;
-  CefWindowInfo window_info_;
-  CefRefPtr<CefClient> client_;
-  CefBrowserSettings settings_;
-  CefPoint inspect_element_at_;
-};
-
-void ShowDevToolsWithHelper(ShowDevToolsHelper* helper) {
-  helper->browser_->ShowDevTools(helper->window_info_, helper->client_,
-                                 helper->settings_,
-                                 helper->inspect_element_at_);
-  delete helper;
-}
-
-// Callback from CefBrowserHostImpl::DownloadImage.
-void OnDownloadImage(uint32 max_image_size,
-                     CefRefPtr<CefDownloadImageCallback> callback,
-                     int id,
-                     int http_status_code,
-                     const GURL& image_url,
-                     const std::vector<SkBitmap>& bitmaps,
-                     const std::vector<gfx::Size>& sizes) {
-  CEF_REQUIRE_UIT();
-
-  CefRefPtr<CefImageImpl> image_impl;
-
-  if (!bitmaps.empty()) {
-    image_impl = new CefImageImpl();
-    image_impl->AddBitmaps(max_image_size, bitmaps);
-  }
-
-  callback->OnDownloadImageFinished(image_url.spec(), http_status_code,
-                                    image_impl.get());
-}
-
-static constexpr base::TimeDelta kRecentlyAudibleTimeout =
-    base::TimeDelta::FromSeconds(2);
-
-}  // namespace
-
-// CefBrowserHost static methods.
-// -----------------------------------------------------------------------------
-
-// static
-bool CefBrowserHost::CreateBrowser(
-    const CefWindowInfo& windowInfo,
-    CefRefPtr<CefClient> client,
-    const CefString& url,
-    const CefBrowserSettings& settings,
-    CefRefPtr<CefDictionaryValue> extra_info,
-    CefRefPtr<CefRequestContext> request_context) {
-  // Verify that the context is in a valid state.
-  if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
-    return false;
-  }
-
-  // Verify that the settings structure is a valid size.
-  if (settings.size != sizeof(cef_browser_settings_t)) {
-    NOTREACHED() << "invalid CefBrowserSettings structure size";
-    return false;
-  }
-
-  // Verify windowless rendering requirements.
-  if (windowInfo.windowless_rendering_enabled &&
-      !client->GetRenderHandler().get()) {
-    NOTREACHED() << "CefRenderHandler implementation is required";
-    return false;
-  }
-
-  if (windowInfo.windowless_rendering_enabled &&
-      !CefContext::Get()->settings().windowless_rendering_enabled) {
-    LOG(ERROR) << "Creating a windowless browser without setting "
-                  "CefSettings.windowless_rendering_enabled may result in "
-                  "reduced performance or runtime errors.";
-  }
-
-  // Create the browser on the UI thread.
-  CreateBrowserHelper* helper = new CreateBrowserHelper(
-      windowInfo, client, url, settings, extra_info, request_context);
-  CEF_POST_TASK(CEF_UIT, base::BindOnce(CreateBrowserWithHelper, helper));
-
-  return true;
-}
-
-// static
-CefRefPtr<CefBrowser> CefBrowserHost::CreateBrowserSync(
-    const CefWindowInfo& windowInfo,
-    CefRefPtr<CefClient> client,
-    const CefString& url,
-    const CefBrowserSettings& settings,
-    CefRefPtr<CefDictionaryValue> extra_info,
-    CefRefPtr<CefRequestContext> request_context) {
-  // Verify that the context is in a valid state.
-  if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
-    return nullptr;
-  }
-
-  // Verify that the settings structure is a valid size.
-  if (settings.size != sizeof(cef_browser_settings_t)) {
-    NOTREACHED() << "invalid CefBrowserSettings structure size";
-    return nullptr;
-  }
-
-  // Verify that this method is being called on the UI thread.
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
-    return nullptr;
-  }
-
-  // Verify windowless rendering requirements.
-  if (windowInfo.windowless_rendering_enabled &&
-      !client->GetRenderHandler().get()) {
-    NOTREACHED() << "CefRenderHandler implementation is required";
-    return nullptr;
-  }
-
-  CefBrowserHostImpl::CreateParams create_params;
-  create_params.window_info.reset(new CefWindowInfo(windowInfo));
-  create_params.client = client;
-  create_params.url = GURL(url.ToString());
-  if (!url.empty() && !create_params.url.is_valid() &&
-      !create_params.url.has_scheme()) {
-    std::string new_url = std::string("http://") + url.ToString();
-    create_params.url = GURL(new_url);
-  }
-  create_params.settings = settings;
-  create_params.extra_info = extra_info;
-  create_params.request_context = request_context;
-
-  CefRefPtr<CefBrowserHostImpl> browser =
-      CefBrowserHostImpl::Create(create_params);
-  return browser.get();
-}
-
-// CefBrowserHostImpl static methods.
-// -----------------------------------------------------------------------------
-
-// static
-CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::Create(
-    CreateParams& create_params) {
-  std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate =
-      CefBrowserPlatformDelegate::Create(create_params);
-  CHECK(platform_delegate);
-
-  const bool is_devtools_popup = !!create_params.devtools_opener;
-
-  scoped_refptr<CefBrowserInfo> info =
-      CefBrowserInfoManager::GetInstance()->CreateBrowserInfo(
-          is_devtools_popup, platform_delegate->IsWindowless(),
-          create_params.extra_info);
-
-  // Get or create the request context and browser context.
-  CefRefPtr<CefRequestContextImpl> request_context_impl =
-      CefRequestContextImpl::GetOrCreateForRequestContext(
-          create_params.request_context);
-  DCHECK(request_context_impl);
-  CefBrowserContext* browser_context =
-      request_context_impl->GetBrowserContext();
-  DCHECK(browser_context);
-
-  if (!create_params.request_context) {
-    // Using the global request context.
-    create_params.request_context = request_context_impl.get();
-  }
-
-  CefRefPtr<CefExtension> cef_extension;
-  scoped_refptr<content::SiteInstance> site_instance;
-  if (extensions::ExtensionsEnabled() && !create_params.url.is_empty()) {
-    if (!create_params.extension) {
-      // We might be loading an extension app view where the extension URL is
-      // provided by the client.
-      create_params.extension =
-          extensions::GetExtensionForUrl(browser_context, create_params.url);
-    }
-    if (create_params.extension) {
-      cef_extension = browser_context->extension_system()->GetExtension(
-          create_params.extension->id());
-      DCHECK(cef_extension);
-
-      if (create_params.extension_host_type == extensions::VIEW_TYPE_INVALID) {
-        // Default to dialog behavior.
-        create_params.extension_host_type =
-            extensions::VIEW_TYPE_EXTENSION_DIALOG;
-      }
-
-      // Extension resources will fail to load if we don't use a SiteInstance
-      // associated with the extension.
-      // (CefContentBrowserClient::SiteInstanceGotProcess won't find the
-      // extension to register with InfoMap, and AllowExtensionResourceLoad in
-      // ExtensionProtocolHandler::MaybeCreateJob will return false resulting in
-      // ERR_BLOCKED_BY_CLIENT).
-      site_instance = extensions::ProcessManager::Get(browser_context)
-                          ->GetSiteInstanceForURL(create_params.url);
-      DCHECK(site_instance);
-    }
-  }
-
-  content::WebContents::CreateParams wc_create_params(browser_context,
-                                                      site_instance);
-
-  if (platform_delegate->IsWindowless()) {
-    // Create the OSR view for the WebContents.
-    platform_delegate->CreateViewForWebContents(
-        &wc_create_params.view, &wc_create_params.delegate_view);
-  }
-
-  std::unique_ptr<content::WebContents> web_contents =
-      content::WebContents::Create(wc_create_params);
-  DCHECK(web_contents);
-
-  CefRefPtr<CefBrowserHostImpl> browser = CreateInternal(
-      create_params.settings, create_params.client, web_contents.release(),
-      true, info, create_params.devtools_opener, is_devtools_popup,
-      static_cast<CefRequestContextImpl*>(create_params.request_context.get()),
-      std::move(platform_delegate), cef_extension);
-  if (!browser)
-    return nullptr;
-
-  if (create_params.extension) {
-    browser->CreateExtensionHost(create_params.extension, browser_context,
-                                 browser->web_contents(), create_params.url,
-                                 create_params.extension_host_type);
-  } else if (!create_params.url.is_empty()) {
-    browser->LoadMainFrameURL(create_params.url.spec(), content::Referrer(),
-                              CefFrameHostImpl::kPageTransitionExplicit,
-                              std::string());
-  }
-
-  return browser.get();
-}
-
-// static
-CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::CreateInternal(
-    const CefBrowserSettings& settings,
-    CefRefPtr<CefClient> client,
-    content::WebContents* web_contents,
-    bool own_web_contents,
-    scoped_refptr<CefBrowserInfo> browser_info,
-    CefRefPtr<CefBrowserHostImpl> opener,
-    bool is_devtools_popup,
-    CefRefPtr<CefRequestContextImpl> request_context,
-    std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
-    CefRefPtr<CefExtension> extension) {
-  CEF_REQUIRE_UIT();
-  DCHECK(web_contents);
-  DCHECK(browser_info);
-  DCHECK(request_context);
-  DCHECK(platform_delegate);
-
-  // If |opener| is non-NULL it must be a popup window.
-  DCHECK(!opener.get() || browser_info->is_popup());
-
-  if (opener) {
-    if (!opener->platform_delegate_) {
-      // The opener window is being destroyed. Cancel the popup.
-      return nullptr;
-    }
-
-    // Give the opener browser's platform delegate an opportunity to modify the
-    // new browser's platform delegate.
-    opener->platform_delegate_->PopupWebContentsCreated(
-        settings, client, web_contents, platform_delegate.get(),
-        is_devtools_popup);
-  }
-
-  platform_delegate->WebContentsCreated(web_contents);
-
-  CefRefPtr<CefBrowserHostImpl> browser = new CefBrowserHostImpl(
-      settings, client, web_contents, browser_info, opener, request_context,
-      std::move(platform_delegate), extension);
-  if (own_web_contents)
-    browser->set_owned_web_contents(web_contents);
-  if (!browser->CreateHostWindow())
-    return nullptr;
-
-  // Notify that the browser has been created. These must be delivered in the
-  // expected order.
-
-  // 1. Notify the browser's LifeSpanHandler. This must always be the first
-  // notification for the browser.
-  if (client.get()) {
-    CefRefPtr<CefLifeSpanHandler> handler = client->GetLifeSpanHandler();
-    if (handler.get())
-      handler->OnAfterCreated(browser.get());
-  }
-
-  // 2. Notify the platform delegate. With Views this will result in a call to
-  // CefBrowserViewDelegate::OnBrowserCreated().
-  browser->platform_delegate_->NotifyBrowserCreated();
-
-  if (opener && opener->platform_delegate_) {
-    // 3. Notify the opener browser's platform delegate. With Views this will
-    // result in a call to CefBrowserViewDelegate::OnPopupBrowserViewCreated().
-    opener->platform_delegate_->PopupBrowserCreated(browser.get(),
-                                                    is_devtools_popup);
-  }
-
-  return browser;
-}
-
-// static
-CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::GetBrowserForHost(
-    const content::RenderViewHost* host) {
-  DCHECK(host);
-  CEF_REQUIRE_UIT();
-  content::WebContents* web_contents = content::WebContents::FromRenderViewHost(
-      const_cast<content::RenderViewHost*>(host));
-  if (web_contents)
-    return GetBrowserForContents(web_contents);
-  return nullptr;
-}
-
-// static
-CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::GetBrowserForHost(
-    const content::RenderFrameHost* host) {
-  DCHECK(host);
-  CEF_REQUIRE_UIT();
-  content::WebContents* web_contents =
-      content::WebContents::FromRenderFrameHost(
-          const_cast<content::RenderFrameHost*>(host));
-  if (web_contents)
-    return GetBrowserForContents(web_contents);
-  return nullptr;
-}
-
-// static
-CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::GetBrowserForContents(
-    const content::WebContents* contents) {
-  DCHECK(contents);
-  CEF_REQUIRE_UIT();
-  return WebContentsUserDataAdapter::Get(contents);
-}
-
-// static
-CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::GetBrowserForFrameTreeNode(
-    int frame_tree_node_id) {
-  // Use the thread-safe approach.
-  scoped_refptr<CefBrowserInfo> info =
-      CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameTreeNode(
-          frame_tree_node_id);
-  if (info.get()) {
-    CefRefPtr<CefBrowserHostImpl> browser = info->browser();
-    if (!browser.get()) {
-      LOG(WARNING) << "Found browser id " << info->browser_id()
-                   << " but no browser object matching frame tree node id "
-                   << frame_tree_node_id;
-    }
-    return browser;
-  }
-
-  return nullptr;
-}
-
-// static
-CefRefPtr<CefBrowserHostImpl> CefBrowserHostImpl::GetBrowserForFrameRoute(
-    int render_process_id,
-    int render_routing_id) {
-  if (render_process_id == -1 || render_routing_id == MSG_ROUTING_NONE)
-    return nullptr;
-
-  if (CEF_CURRENTLY_ON_UIT()) {
-    // Use the non-thread-safe but potentially faster approach.
-    content::RenderFrameHost* render_frame_host =
-        content::RenderFrameHost::FromID(render_process_id, render_routing_id);
-    if (!render_frame_host)
-      return nullptr;
-    return GetBrowserForHost(render_frame_host);
-  } else {
-    // Use the thread-safe approach.
-    bool is_guest_view = false;
-    scoped_refptr<CefBrowserInfo> info =
-        CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameRoute(
-            render_process_id, render_routing_id, &is_guest_view);
-    if (info.get() && !is_guest_view) {
-      CefRefPtr<CefBrowserHostImpl> browser = info->browser();
-      if (!browser.get()) {
-        LOG(WARNING) << "Found browser id " << info->browser_id()
-                     << " but no browser object matching frame process id "
-                     << render_process_id << " and routing id "
-                     << render_routing_id;
-      }
-      return browser;
-    }
-    return nullptr;
-  }
-}
-
-// CefBrowserHostImpl methods.
-// -----------------------------------------------------------------------------
-
-CefBrowserHostImpl::~CefBrowserHostImpl() {}
-
-CefRefPtr<CefBrowser> CefBrowserHostImpl::GetBrowser() {
-  return this;
-}
-
-void CefBrowserHostImpl::CloseBrowser(bool force_close) {
-  if (CEF_CURRENTLY_ON_UIT()) {
-    // Exit early if a close attempt is already pending and this method is
-    // called again from somewhere other than WindowDestroyed().
-    if (destruction_state_ >= DESTRUCTION_STATE_PENDING &&
-        (IsWindowless() || !window_destroyed_)) {
-      if (force_close && destruction_state_ == DESTRUCTION_STATE_PENDING) {
-        // Upgrade the destruction state.
-        destruction_state_ = DESTRUCTION_STATE_ACCEPTED;
-      }
-      return;
-    }
-
-    if (destruction_state_ < DESTRUCTION_STATE_ACCEPTED) {
-      destruction_state_ = (force_close ? DESTRUCTION_STATE_ACCEPTED
-                                        : DESTRUCTION_STATE_PENDING);
-    }
-
-    content::WebContents* contents = web_contents();
-    if (contents && contents->NeedToFireBeforeUnloadOrUnload()) {
-      // Will result in a call to BeforeUnloadFired() and, if the close isn't
-      // canceled, CloseContents().
-      contents->DispatchBeforeUnload(false /* auto_cancel */);
-    } else {
-      CloseContents(contents);
-    }
-  } else {
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostImpl::CloseBrowser,
-                                          this, force_close));
-  }
-}
-
-bool CefBrowserHostImpl::TryCloseBrowser() {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
-    return false;
-  }
-
-  // Protect against multiple requests to close while the close is pending.
-  if (destruction_state_ <= DESTRUCTION_STATE_PENDING) {
-    if (destruction_state_ == DESTRUCTION_STATE_NONE) {
-      // Request that the browser close.
-      CloseBrowser(false);
-    }
-
-    // Cancel the close.
-    return false;
-  }
-
-  // Allow the close.
-  return true;
-}
-
-void CefBrowserHostImpl::SetFocus(bool focus) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::SetFocus, this, focus));
-    return;
-  }
-
-  if (focus)
-    OnSetFocus(FOCUS_SOURCE_SYSTEM);
-  else if (platform_delegate_)
-    platform_delegate_->SendFocusEvent(false);
-}
-
-CefWindowHandle CefBrowserHostImpl::GetWindowHandle() {
-  if (IsViewsHosted() && CEF_CURRENTLY_ON_UIT()) {
-    // Always return the most up-to-date window handle for a views-hosted
-    // browser since it may change if the view is re-parented.
-    if (platform_delegate_)
-      return platform_delegate_->GetHostWindowHandle();
-  }
-  return host_window_handle_;
-}
-
-CefWindowHandle CefBrowserHostImpl::GetOpenerWindowHandle() {
-  return opener_;
-}
-
-bool CefBrowserHostImpl::HasView() {
-  return IsViewsHosted();
-}
-
-CefRefPtr<CefClient> CefBrowserHostImpl::GetClient() {
-  return client_;
-}
-
-CefRefPtr<CefRequestContext> CefBrowserHostImpl::GetRequestContext() {
-  return request_context_;
-}
-
-double CefBrowserHostImpl::GetZoomLevel() {
-  // Verify that this method is being called on the UI thread.
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
-    return 0;
-  }
-
-  if (web_contents())
-    return content::HostZoomMap::GetZoomLevel(web_contents());
-
-  return 0;
-}
-
-void CefBrowserHostImpl::SetZoomLevel(double zoomLevel) {
-  if (CEF_CURRENTLY_ON_UIT()) {
-    if (web_contents())
-      content::HostZoomMap::SetZoomLevel(web_contents(), zoomLevel);
-  } else {
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostImpl::SetZoomLevel,
-                                          this, zoomLevel));
-  }
-}
-
-void CefBrowserHostImpl::RunFileDialog(
-    FileDialogMode mode,
-    const CefString& title,
-    const CefString& default_file_path,
-    const std::vector<CefString>& accept_filters,
-    int selected_accept_filter,
-    CefRefPtr<CefRunFileDialogCallback> callback) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::RunFileDialog, this, mode,
-                                 title, default_file_path, accept_filters,
-                                 selected_accept_filter, callback));
-    return;
-  }
-
-  EnsureFileDialogManager();
-  file_dialog_manager_->RunFileDialog(mode, title, default_file_path,
-                                      accept_filters, selected_accept_filter,
-                                      callback);
-}
-
-void CefBrowserHostImpl::StartDownload(const CefString& url) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT, base::BindOnce(&CefBrowserHostImpl::StartDownload, this, url));
-    return;
-  }
-
-  GURL gurl = GURL(url.ToString());
-  if (gurl.is_empty() || !gurl.is_valid())
-    return;
-
-  if (!web_contents())
-    return;
-
-  CefBrowserContext* context =
-      static_cast<CefBrowserContext*>(web_contents()->GetBrowserContext());
-  if (!context)
-    return;
-
-  content::DownloadManager* manager =
-      content::BrowserContext::GetDownloadManager(context);
-  if (!manager)
-    return;
-
-  std::unique_ptr<download::DownloadUrlParameters> params(
-      content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(
-          web_contents(), gurl, MISSING_TRAFFIC_ANNOTATION));
-  manager->DownloadUrl(std::move(params));
-}
-
-void CefBrowserHostImpl::DownloadImage(
-    const CefString& image_url,
-    bool is_favicon,
-    uint32 max_image_size,
-    bool bypass_cache,
-    CefRefPtr<CefDownloadImageCallback> callback) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::BindOnce(&CefBrowserHostImpl::DownloadImage, this, image_url,
-                       is_favicon, max_image_size, bypass_cache, callback));
-    return;
-  }
-
-  if (!callback)
-    return;
-
-  GURL gurl = GURL(image_url.ToString());
-  if (gurl.is_empty() || !gurl.is_valid())
-    return;
-
-  if (!web_contents())
-    return;
-
-  web_contents()->DownloadImage(
-      gurl, is_favicon, max_image_size,
-      max_image_size * gfx::ImageSkia::GetMaxSupportedScale(), bypass_cache,
-      base::BindOnce(OnDownloadImage, max_image_size, callback));
-}
-
-void CefBrowserHostImpl::Print() {
-  if (CEF_CURRENTLY_ON_UIT()) {
-    auto actionable_contents = GetActionableWebContents();
-    if (!actionable_contents)
-      return;
-
-    auto rfh = actionable_contents->GetMainFrame();
-
-    if (IsPrintPreviewSupported()) {
-      printing::CefPrintViewManager::FromWebContents(actionable_contents)
-          ->PrintPreviewNow(rfh, false);
-    } else {
-      printing::PrintViewManager::FromWebContents(actionable_contents)
-          ->PrintNow(rfh);
-    }
-  } else {
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostImpl::Print, this));
-  }
-}
-
-void CefBrowserHostImpl::PrintToPDF(const CefString& path,
-                                    const CefPdfPrintSettings& settings,
-                                    CefRefPtr<CefPdfPrintCallback> callback) {
-  if (CEF_CURRENTLY_ON_UIT()) {
-    content::WebContents* actionable_contents = GetActionableWebContents();
-    if (!actionable_contents)
-      return;
-
-    printing::CefPrintViewManager::PdfPrintCallback pdf_callback;
-    if (callback.get()) {
-      pdf_callback = base::Bind(&CefPdfPrintCallback::OnPdfPrintFinished,
-                                callback.get(), path);
-    }
-    printing::CefPrintViewManager::FromWebContents(actionable_contents)
-        ->PrintToPDF(actionable_contents->GetMainFrame(), base::FilePath(path),
-                     settings, pdf_callback);
-  } else {
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostImpl::PrintToPDF, this,
-                                          path, settings, callback));
-  }
-}
-
-void CefBrowserHostImpl::Find(int identifier,
-                              const CefString& searchText,
-                              bool forward,
-                              bool matchCase,
-                              bool findNext) {
-  if (CEF_CURRENTLY_ON_UIT()) {
-    if (!web_contents())
-      return;
-
-    // Every find request must have a unique ID and these IDs must strictly
-    // increase so that newer requests always have greater IDs than older
-    // requests.
-    if (identifier <= find_request_id_counter_)
-      identifier = ++find_request_id_counter_;
-    else
-      find_request_id_counter_ = identifier;
-
-    auto options = blink::mojom::FindOptions::New();
-    options->forward = forward;
-    options->match_case = matchCase;
-    options->find_next = findNext;
-    web_contents()->Find(identifier, searchText, std::move(options));
-  } else {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::Find, this, identifier,
-                                 searchText, forward, matchCase, findNext));
-  }
-}
-
-void CefBrowserHostImpl::StopFinding(bool clearSelection) {
-  if (CEF_CURRENTLY_ON_UIT()) {
-    if (!web_contents())
-      return;
-
-    content::StopFindAction action =
-        clearSelection ? content::STOP_FIND_ACTION_CLEAR_SELECTION
-                       : content::STOP_FIND_ACTION_KEEP_SELECTION;
-    web_contents()->StopFinding(action);
-  } else {
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostImpl::StopFinding,
-                                          this, clearSelection));
-  }
-}
-
-void CefBrowserHostImpl::ShowDevTools(const CefWindowInfo& windowInfo,
-                                      CefRefPtr<CefClient> client,
-                                      const CefBrowserSettings& settings,
-                                      const CefPoint& inspect_element_at) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    ShowDevToolsHelper* helper = new ShowDevToolsHelper(
-        this, windowInfo, client, settings, inspect_element_at);
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(ShowDevToolsWithHelper, helper));
-    return;
-  }
-
-  if (!EnsureDevToolsManager())
-    return;
-  devtools_manager_->ShowDevTools(windowInfo, client, settings,
-                                  inspect_element_at);
-}
-
-void CefBrowserHostImpl::CloseDevTools() {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::CloseDevTools, this));
-    return;
-  }
-
-  if (!devtools_manager_)
-    return;
-  devtools_manager_->CloseDevTools();
-}
-
-bool CefBrowserHostImpl::HasDevTools() {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
-    return false;
-  }
-
-  if (!devtools_manager_)
-    return false;
-  return devtools_manager_->HasDevTools();
-}
-
-bool CefBrowserHostImpl::SendDevToolsMessage(const void* message,
-                                             size_t message_size) {
-  if (!message || message_size == 0)
-    return false;
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    std::string message_str(static_cast<const char*>(message), message_size);
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::BindOnce(
-            [](CefRefPtr<CefBrowserHostImpl> self, std::string message_str) {
-              self->SendDevToolsMessage(message_str.data(), message_str.size());
-            },
-            CefRefPtr<CefBrowserHostImpl>(this), std::move(message_str)));
-    return false;
-  }
-
-  if (!EnsureDevToolsManager())
-    return false;
-  return devtools_manager_->SendDevToolsMessage(message, message_size);
-}
-
-int CefBrowserHostImpl::ExecuteDevToolsMethod(
-    int message_id,
-    const CefString& method,
-    CefRefPtr<CefDictionaryValue> params) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT, base::BindOnce(base::IgnoreResult(
-                                    &CefBrowserHostImpl::ExecuteDevToolsMethod),
-                                this, message_id, method, params));
-    return 0;
-  }
-
-  if (!EnsureDevToolsManager())
-    return 0;
-  return devtools_manager_->ExecuteDevToolsMethod(message_id, method, params);
-}
-
-CefRefPtr<CefRegistration> CefBrowserHostImpl::AddDevToolsMessageObserver(
-    CefRefPtr<CefDevToolsMessageObserver> observer) {
-  if (!observer)
-    return nullptr;
-  auto registration = CefDevToolsManager::CreateRegistration(observer);
-  InitializeDevToolsRegistrationOnUIThread(registration);
-  return registration.get();
-}
-
-bool CefBrowserHostImpl::EnsureDevToolsManager() {
-  CEF_REQUIRE_UIT();
-  if (!web_contents())
-    return false;
-
-  if (!devtools_manager_) {
-    devtools_manager_.reset(new CefDevToolsManager(this));
-  }
-  return true;
-}
-
-void CefBrowserHostImpl::InitializeDevToolsRegistrationOnUIThread(
-    CefRefPtr<CefRegistration> registration) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::BindOnce(
-            &CefBrowserHostImpl::InitializeDevToolsRegistrationOnUIThread, this,
-            registration));
-    return;
-  }
-
-  if (!EnsureDevToolsManager())
-    return;
-  devtools_manager_->InitializeRegistrationOnUIThread(registration);
-}
-
-void CefBrowserHostImpl::GetNavigationEntries(
-    CefRefPtr<CefNavigationEntryVisitor> visitor,
-    bool current_only) {
-  DCHECK(visitor.get());
-  if (!visitor.get())
-    return;
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT, base::BindOnce(&CefBrowserHostImpl::GetNavigationEntries, this,
-                                visitor, current_only));
-    return;
-  }
-
-  if (!web_contents())
-    return;
-
-  content::NavigationController& controller = web_contents()->GetController();
-  const int total = controller.GetEntryCount();
-  const int current = controller.GetCurrentEntryIndex();
-
-  if (current_only) {
-    // Visit only the current entry.
-    CefRefPtr<CefNavigationEntryImpl> entry =
-        new CefNavigationEntryImpl(controller.GetEntryAtIndex(current));
-    visitor->Visit(entry.get(), true, current, total);
-    entry->Detach(nullptr);
-  } else {
-    // Visit all entries.
-    bool cont = true;
-    for (int i = 0; i < total && cont; ++i) {
-      CefRefPtr<CefNavigationEntryImpl> entry =
-          new CefNavigationEntryImpl(controller.GetEntryAtIndex(i));
-      cont = visitor->Visit(entry.get(), (i == current), i, total);
-      entry->Detach(nullptr);
-    }
-  }
-}
-
-CefRefPtr<CefNavigationEntry> CefBrowserHostImpl::GetVisibleNavigationEntry() {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
-    return nullptr;
-  }
-
-  content::NavigationEntry* entry = nullptr;
-  if (web_contents())
-    entry = web_contents()->GetController().GetVisibleEntry();
-
-  if (!entry)
-    return nullptr;
-
-  return new CefNavigationEntryImpl(entry);
-}
-
-void CefBrowserHostImpl::SetAccessibilityState(
-    cef_state_t accessibility_state) {
-  // Do nothing if state is set to default. It'll be disabled by default and
-  // controlled by the commmand-line flags "force-renderer-accessibility" and
-  // "disable-renderer-accessibility".
-  if (accessibility_state == STATE_DEFAULT)
-    return;
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::SetAccessibilityState,
-                                 this, accessibility_state));
-    return;
-  }
-
-  content::WebContentsImpl* web_contents_impl =
-      static_cast<content::WebContentsImpl*>(web_contents());
-
-  if (!web_contents_impl)
-    return;
-
-  ui::AXMode accMode;
-  // In windowless mode set accessibility to TreeOnly mode. Else native
-  // accessibility APIs, specific to each platform, are also created.
-  if (accessibility_state == STATE_ENABLED) {
-    accMode = IsWindowless() ? ui::kAXModeWebContentsOnly : ui::kAXModeComplete;
-  }
-  web_contents_impl->SetAccessibilityMode(accMode);
-}
-
-void CefBrowserHostImpl::SetAutoResizeEnabled(bool enabled,
-                                              const CefSize& min_size,
-                                              const CefSize& max_size) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT, base::BindOnce(&CefBrowserHostImpl::SetAutoResizeEnabled, this,
-                                enabled, min_size, max_size));
-    return;
-  }
-
-  if (enabled == auto_resize_enabled_)
-    return;
-
-  auto_resize_enabled_ = enabled;
-  if (enabled) {
-    auto_resize_min_ = gfx::Size(min_size.width, min_size.height);
-    auto_resize_max_ = gfx::Size(max_size.width, max_size.height);
-  } else {
-    auto_resize_min_ = auto_resize_max_ = gfx::Size();
-  }
-  ConfigureAutoResize();
-}
-
-CefRefPtr<CefExtension> CefBrowserHostImpl::GetExtension() {
-  return extension_;
-}
-
-bool CefBrowserHostImpl::IsBackgroundHost() {
-  return is_background_host_;
-}
-
-void CefBrowserHostImpl::SetMouseCursorChangeDisabled(bool disabled) {
-  base::AutoLock lock_scope(state_lock_);
-  mouse_cursor_change_disabled_ = disabled;
-}
-
-bool CefBrowserHostImpl::IsMouseCursorChangeDisabled() {
-  base::AutoLock lock_scope(state_lock_);
-  return mouse_cursor_change_disabled_;
-}
-
-bool CefBrowserHostImpl::IsWindowRenderingDisabled() {
-  return IsWindowless();
-}
-
-void CefBrowserHostImpl::ReplaceMisspelling(const CefString& word) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::BindOnce(&CefBrowserHostImpl::ReplaceMisspelling, this, word));
-    return;
-  }
-
-  if (web_contents())
-    web_contents()->ReplaceMisspelling(word);
-}
-
-void CefBrowserHostImpl::AddWordToDictionary(const CefString& word) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::BindOnce(&CefBrowserHostImpl::AddWordToDictionary, this, word));
-    return;
-  }
-
-  if (!web_contents())
-    return;
-
-  SpellcheckService* spellcheck = nullptr;
-  content::BrowserContext* browser_context =
-      web_contents()->GetBrowserContext();
-  if (browser_context) {
-    spellcheck = SpellcheckServiceFactory::GetForContext(browser_context);
-    if (spellcheck)
-      spellcheck->GetCustomDictionary()->AddWord(word);
-  }
-#if defined(OS_MACOSX)
-  if (spellcheck && spellcheck::UseBrowserSpellChecker()) {
-    spellcheck_platform::AddWord(spellcheck->platform_spell_checker(), word);
-  }
-#endif
-}
-
-void CefBrowserHostImpl::WasResized() {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::WasResized, this));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->WasResized();
-}
-
-void CefBrowserHostImpl::WasHidden(bool hidden) {
-  if (!IsWindowless()) {
-    NOTREACHED() << "Window rendering is not disabled";
-    return;
-  }
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHost::WasHidden, this, hidden));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->WasHidden(hidden);
-}
-
-void CefBrowserHostImpl::NotifyScreenInfoChanged() {
-  if (!IsWindowless()) {
-    NOTREACHED() << "Window rendering is not disabled";
-    return;
-  }
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::BindOnce(&CefBrowserHostImpl::NotifyScreenInfoChanged, this));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->NotifyScreenInfoChanged();
-}
-
-void CefBrowserHostImpl::Invalidate(PaintElementType type) {
-  if (!IsWindowless()) {
-    NOTREACHED() << "Window rendering is not disabled";
-    return;
-  }
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::Invalidate, this, type));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->Invalidate(type);
-}
-
-void CefBrowserHostImpl::SendExternalBeginFrame() {
-  if (!IsWindowless()) {
-    NOTREACHED() << "Window rendering is not disabled";
-    return;
-  }
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT, base::Bind(&CefBrowserHostImpl::SendExternalBeginFrame, this));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->SendExternalBeginFrame();
-}
-
-void CefBrowserHostImpl::SendKeyEvent(const CefKeyEvent& event) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostImpl::SendKeyEvent,
-                                          this, event));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->SendKeyEvent(event);
-}
-
-void CefBrowserHostImpl::SendMouseClickEvent(const CefMouseEvent& event,
-                                             MouseButtonType type,
-                                             bool mouseUp,
-                                             int clickCount) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::SendMouseClickEvent, this,
-                                 event, type, mouseUp, clickCount));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->SendMouseClickEvent(event, type, mouseUp, clickCount);
-}
-
-void CefBrowserHostImpl::SendMouseMoveEvent(const CefMouseEvent& event,
-                                            bool mouseLeave) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::SendMouseMoveEvent, this,
-                                 event, mouseLeave));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->SendMouseMoveEvent(event, mouseLeave);
-}
-
-void CefBrowserHostImpl::SendMouseWheelEvent(const CefMouseEvent& event,
-                                             int deltaX,
-                                             int deltaY) {
-  if (deltaX == 0 && deltaY == 0) {
-    // Nothing to do.
-    return;
-  }
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::SendMouseWheelEvent, this,
-                                 event, deltaX, deltaY));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->SendMouseWheelEvent(event, deltaX, deltaY);
-}
-
-void CefBrowserHostImpl::SendFocusEvent(bool setFocus) {
-  SetFocus(setFocus);
-}
-
-void CefBrowserHostImpl::SendCaptureLostEvent() {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::BindOnce(&CefBrowserHostImpl::SendCaptureLostEvent, this));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->SendCaptureLostEvent();
-}
-
-void CefBrowserHostImpl::NotifyMoveOrResizeStarted() {
-#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX))
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::BindOnce(&CefBrowserHostImpl::NotifyMoveOrResizeStarted, this));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->NotifyMoveOrResizeStarted();
-#endif
-}
-
-int CefBrowserHostImpl::GetWindowlessFrameRate() {
-  // Verify that this method is being called on the UI thread.
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
-    return 0;
-  }
-
-  return osr_util::ClampFrameRate(settings_.windowless_frame_rate);
-}
-
-void CefBrowserHostImpl::SetWindowlessFrameRate(int frame_rate) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::SetWindowlessFrameRate,
-                                 this, frame_rate));
-    return;
-  }
-
-  settings_.windowless_frame_rate = frame_rate;
-
-  if (platform_delegate_)
-    platform_delegate_->SetWindowlessFrameRate(frame_rate);
-}
-
-// CefBrowser methods.
-// -----------------------------------------------------------------------------
-
-CefRefPtr<CefBrowserHost> CefBrowserHostImpl::GetHost() {
-  return this;
-}
-
-bool CefBrowserHostImpl::CanGoBack() {
-  base::AutoLock lock_scope(state_lock_);
-  return can_go_back_;
-}
-
-void CefBrowserHostImpl::GoBack() {
-  if (CEF_CURRENTLY_ON_UIT()) {
-    if (navigation_locked()) {
-      // Try again after the lock has been released.
-      set_pending_navigation_action(
-          base::BindOnce(&CefBrowserHostImpl::GoBack, this));
-      return;
-    }
-
-    if (web_contents() && web_contents()->GetController().CanGoBack())
-      web_contents()->GetController().GoBack();
-  } else {
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostImpl::GoBack, this));
-  }
-}
-
-bool CefBrowserHostImpl::CanGoForward() {
-  base::AutoLock lock_scope(state_lock_);
-  return can_go_forward_;
-}
-
-void CefBrowserHostImpl::GoForward() {
-  if (CEF_CURRENTLY_ON_UIT()) {
-    if (navigation_locked()) {
-      // Try again after the lock has been released.
-      set_pending_navigation_action(
-          base::BindOnce(&CefBrowserHostImpl::GoForward, this));
-      return;
-    }
-
-    if (web_contents() && web_contents()->GetController().CanGoForward())
-      web_contents()->GetController().GoForward();
-  } else {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::GoForward, this));
-  }
-}
-
-bool CefBrowserHostImpl::IsLoading() {
-  base::AutoLock lock_scope(state_lock_);
-  return is_loading_;
-}
-
-void CefBrowserHostImpl::Reload() {
-  if (CEF_CURRENTLY_ON_UIT()) {
-    if (navigation_locked()) {
-      // Try again after the lock has been released.
-      set_pending_navigation_action(
-          base::BindOnce(&CefBrowserHostImpl::Reload, this));
-      return;
-    }
-
-    if (web_contents())
-      web_contents()->GetController().Reload(content::ReloadType::NORMAL, true);
-  } else {
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostImpl::Reload, this));
-  }
-}
-
-void CefBrowserHostImpl::ReloadIgnoreCache() {
-  if (CEF_CURRENTLY_ON_UIT()) {
-    if (navigation_locked()) {
-      // Try again after the lock has been released.
-      set_pending_navigation_action(
-          base::BindOnce(&CefBrowserHostImpl::ReloadIgnoreCache, this));
-      return;
-    }
-
-    if (web_contents()) {
-      web_contents()->GetController().Reload(
-          content::ReloadType::BYPASSING_CACHE, true);
-    }
-  } else {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::ReloadIgnoreCache, this));
-  }
-}
-
-void CefBrowserHostImpl::StopLoad() {
-  if (CEF_CURRENTLY_ON_UIT()) {
-    if (navigation_locked()) {
-      // Try again after the lock has been released.
-      set_pending_navigation_action(
-          base::BindOnce(&CefBrowserHostImpl::StopLoad, this));
-      return;
-    }
-
-    if (web_contents())
-      web_contents()->Stop();
-  } else {
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostImpl::StopLoad, this));
-  }
-}
-
-int CefBrowserHostImpl::GetIdentifier() {
-  return browser_id();
-}
-
-bool CefBrowserHostImpl::IsSame(CefRefPtr<CefBrowser> that) {
-  CefBrowserHostImpl* impl = static_cast<CefBrowserHostImpl*>(that.get());
-  return (impl == this);
-}
-
-bool CefBrowserHostImpl::IsPopup() {
-  return browser_info_->is_popup();
-}
-
-bool CefBrowserHostImpl::HasDocument() {
-  base::AutoLock lock_scope(state_lock_);
-  return has_document_;
-}
-
-CefRefPtr<CefFrame> CefBrowserHostImpl::GetMainFrame() {
-  return GetFrame(CefFrameHostImpl::kMainFrameId);
-}
-
-CefRefPtr<CefFrame> CefBrowserHostImpl::GetFocusedFrame() {
-  return GetFrame(CefFrameHostImpl::kFocusedFrameId);
-}
-
-CefRefPtr<CefFrame> CefBrowserHostImpl::GetFrame(int64 identifier) {
-  if (identifier == CefFrameHostImpl::kInvalidFrameId) {
-    return nullptr;
-  } else if (identifier == CefFrameHostImpl::kMainFrameId) {
-    return browser_info_->GetMainFrame();
-  } else if (identifier == CefFrameHostImpl::kFocusedFrameId) {
-    base::AutoLock lock_scope(state_lock_);
-    if (!focused_frame_) {
-      // The main frame is focused by default.
-      return browser_info_->GetMainFrame();
-    }
-    return focused_frame_;
-  }
-
-  return browser_info_->GetFrameForId(identifier);
-}
-
-CefRefPtr<CefFrame> CefBrowserHostImpl::GetFrame(const CefString& name) {
-  for (const auto& frame : browser_info_->GetAllFrames()) {
-    if (frame->GetName() == name)
-      return frame;
-  }
-  return nullptr;
-}
-
-size_t CefBrowserHostImpl::GetFrameCount() {
-  return browser_info_->GetAllFrames().size();
-}
-
-void CefBrowserHostImpl::GetFrameIdentifiers(std::vector<int64>& identifiers) {
-  if (identifiers.size() > 0)
-    identifiers.clear();
-
-  const auto frames = browser_info_->GetAllFrames();
-  if (frames.empty())
-    return;
-
-  identifiers.reserve(frames.size());
-  for (const auto& frame : frames) {
-    identifiers.push_back(frame->GetIdentifier());
-  }
-}
-
-void CefBrowserHostImpl::GetFrameNames(std::vector<CefString>& names) {
-  if (names.size() > 0)
-    names.clear();
-
-  const auto frames = browser_info_->GetAllFrames();
-  if (frames.empty())
-    return;
-
-  names.reserve(frames.size());
-  for (const auto& frame : frames) {
-    names.push_back(frame->GetName());
-  }
-}
-
-// CefBrowserHostImpl public methods.
-// -----------------------------------------------------------------------------
-
-bool CefBrowserHostImpl::IsWindowless() const {
-  return is_windowless_;
-}
-
-bool CefBrowserHostImpl::IsViewsHosted() const {
-  return is_views_hosted_;
-}
-
-bool CefBrowserHostImpl::IsPrintPreviewSupported() const {
-  CEF_REQUIRE_UIT();
-  auto actionable_contents = GetActionableWebContents();
-  if (!actionable_contents)
-    return false;
-
-  if (!CefBrowserContext::GetForContext(
-           actionable_contents->GetBrowserContext())
-           ->IsPrintPreviewSupported()) {
-    return false;
-  }
-
-  // Print preview is not currently supported with OSR.
-  return !IsWindowless();
-}
-
-bool CefBrowserHostImpl::IsPictureInPictureSupported() const {
-  // Not currently supported with OSR.
-  return !IsWindowless();
-}
-
-void CefBrowserHostImpl::WindowDestroyed() {
-  CEF_REQUIRE_UIT();
-  DCHECK(!window_destroyed_);
-  window_destroyed_ = true;
-  CloseBrowser(true);
-}
-
-void CefBrowserHostImpl::DestroyBrowser() {
-  CEF_REQUIRE_UIT();
-
-  destruction_state_ = DESTRUCTION_STATE_COMPLETED;
-
-  // Notify that this browser has been destroyed. These must be delivered in
-  // the expected order.
-
-  // 1. Notify the platform delegate. With Views this will result in a call to
-  // CefBrowserViewDelegate::OnBrowserDestroyed().
-  platform_delegate_->NotifyBrowserDestroyed();
-
-  // 2. Notify the browser's LifeSpanHandler. This must always be the last
-  // notification for this browser.
-  if (client_.get()) {
-    CefRefPtr<CefLifeSpanHandler> handler = client_->GetLifeSpanHandler();
-    if (handler.get()) {
-      // Notify the handler that the window is about to be closed.
-      handler->OnBeforeClose(this);
-    }
-  }
-
-  // Destroy any platform constructs first.
-  if (file_dialog_manager_.get())
-    file_dialog_manager_->Destroy();
-  if (javascript_dialog_manager_.get())
-    javascript_dialog_manager_->Destroy();
-  if (menu_manager_.get())
-    menu_manager_->Destroy();
-  DestroyExtensionHost();
-
-  // Notify any observers that may have state associated with this browser.
-  for (auto& observer : observers_)
-    observer.OnBrowserDestroyed(this);
-
-  // Disassociate the platform delegate from this browser.
-  platform_delegate_->BrowserDestroyed(this);
-
-  registrar_.reset(nullptr);
-  content::WebContentsObserver::Observe(nullptr);
-  if (owned_web_contents_)
-    owned_web_contents_.reset(nullptr);
-
-  // Delete objects created by the platform delegate that may be referenced by
-  // the WebContents.
-  file_dialog_manager_.reset(nullptr);
-  javascript_dialog_manager_.reset(nullptr);
-  menu_manager_.reset(nullptr);
-
-  // Delete the audio capturer
-  recently_audible_timer_.Stop();
-  audio_capturer_.reset(nullptr);
-
-  devtools_manager_.reset(nullptr);
-
-  // Delete the platform delegate.
-  platform_delegate_.reset(nullptr);
-
-  CefBrowserInfoManager::GetInstance()->RemoveBrowserInfo(browser_info_);
-  browser_info_->SetBrowser(nullptr);
-}
-
-#if defined(USE_AURA)
-views::Widget* CefBrowserHostImpl::GetWindowWidget() const {
-  CEF_REQUIRE_UIT();
-  if (!platform_delegate_)
-    return nullptr;
-  return platform_delegate_->GetWindowWidget();
-}
-
-CefRefPtr<CefBrowserView> CefBrowserHostImpl::GetBrowserView() const {
-  CEF_REQUIRE_UIT();
-  if (IsViewsHosted() && platform_delegate_)
-    return platform_delegate_->GetBrowserView();
-  return nullptr;
-}
-#endif
-
-void CefBrowserHostImpl::CancelContextMenu() {
-  CEF_REQUIRE_UIT();
-  if (menu_manager_)
-    menu_manager_->CancelContextMenu();
-}
-
-CefRefPtr<CefFrame> CefBrowserHostImpl::GetFrameForHost(
-    const content::RenderFrameHost* host) {
-  CEF_REQUIRE_UIT();
-  if (!host)
-    return nullptr;
-
-  return browser_info_->GetFrameForHost(host);
-}
-
-CefRefPtr<CefFrame> CefBrowserHostImpl::GetFrameForFrameTreeNode(
-    int frame_tree_node_id) {
-  return browser_info_->GetFrameForFrameTreeNode(frame_tree_node_id, nullptr);
-}
-
-void CefBrowserHostImpl::LoadMainFrameURL(const std::string& url,
-                                          const content::Referrer& referrer,
-                                          ui::PageTransition transition,
-                                          const std::string& extra_headers) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::LoadMainFrameURL, this,
-                                 url, referrer, transition, extra_headers));
-    return;
-  }
-
-  // Go through the navigation controller.
-  if (navigation_locked()) {
-    // Try again after the lock has been released.
-    set_pending_navigation_action(
-        base::BindOnce(&CefBrowserHostImpl::LoadMainFrameURL, this, url,
-                       referrer, transition, extra_headers));
-    return;
-  }
-
-  if (web_contents()) {
-    GURL gurl = GURL(url);
-
-    if (!gurl.is_valid() && !gurl.has_scheme()) {
-      // Try to add "http://" at the beginning
-      std::string new_url = std::string("http://") + url;
-      gurl = GURL(new_url);
-    }
-
-    if (!gurl.is_valid()) {
-      LOG(ERROR)
-          << "Invalid URL passed to CefBrowserHostImpl::LoadMainFrameURL: "
-          << url;
-      return;
-    }
-
-    web_contents()->GetController().LoadURL(gurl, referrer, transition,
-                                            extra_headers);
-    OnSetFocus(FOCUS_SOURCE_NAVIGATION);
-  }
-}
-
-void CefBrowserHostImpl::OnDidFinishLoad(CefRefPtr<CefFrameHostImpl> frame,
-                                         const GURL& validated_url,
-                                         int http_status_code) {
-  frame->RefreshAttributes();
-
-  // Give internal scheme handlers an opportunity to update content.
-  scheme::DidFinishLoad(frame, validated_url);
-
-  OnLoadEnd(frame, validated_url, http_status_code);
-}
-
-void CefBrowserHostImpl::ViewText(const std::string& text) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::ViewText, this, text));
-    return;
-  }
-
-  if (platform_delegate_)
-    platform_delegate_->ViewText(text);
-}
-
-SkColor CefBrowserHostImpl::GetBackgroundColor() const {
-  // Don't use |platform_delegate_| because it's not thread-safe.
-  return CefContext::Get()->GetBackgroundColor(
-      &settings_, is_windowless_ ? STATE_ENABLED : STATE_DISABLED);
-}
-
-int CefBrowserHostImpl::browser_id() const {
-  return browser_info_->browser_id();
-}
-
-content::BrowserContext* CefBrowserHostImpl::GetBrowserContext() {
-  CEF_REQUIRE_UIT();
-  if (web_contents())
-    return web_contents()->GetBrowserContext();
-  return nullptr;
-}
-
-void CefBrowserHostImpl::OnSetFocus(cef_focus_source_t source) {
-  if (CEF_CURRENTLY_ON_UIT()) {
-    // SetFocus() might be called while inside the OnSetFocus() callback. If
-    // so, don't re-enter the callback.
-    if (!is_in_onsetfocus_) {
-      if (client_.get()) {
-        CefRefPtr<CefFocusHandler> handler = client_->GetFocusHandler();
-        if (handler.get()) {
-          is_in_onsetfocus_ = true;
-          bool handled = handler->OnSetFocus(this, source);
-          is_in_onsetfocus_ = false;
-
-          if (handled)
-            return;
-        }
-      }
-    }
-
-    if (platform_delegate_)
-      platform_delegate_->SendFocusEvent(true);
-  } else {
-    CEF_POST_TASK(
-        CEF_UIT, base::BindOnce(&CefBrowserHostImpl::OnSetFocus, this, source));
-  }
-}
-
-void CefBrowserHostImpl::RunFileChooser(
-    const CefFileDialogRunner::FileChooserParams& params,
-    CefFileDialogRunner::RunFileChooserCallback callback) {
-  EnsureFileDialogManager();
-  file_dialog_manager_->RunFileChooser(params, std::move(callback));
-}
-
-bool CefBrowserHostImpl::EmbedsFullscreenWidget() {
-  // When using windowless rendering do not allow Flash to create its own
-  // full- screen widget.
-  return IsWindowless();
-}
-
-void CefBrowserHostImpl::EnterFullscreenModeForTab(
-    content::WebContents* web_contents,
-    const GURL& origin,
-    const blink::mojom::FullscreenOptions& options) {
-  OnFullscreenModeChange(true);
-}
-
-void CefBrowserHostImpl::ExitFullscreenModeForTab(
-    content::WebContents* web_contents) {
-  OnFullscreenModeChange(false);
-}
-
-bool CefBrowserHostImpl::IsFullscreenForTabOrPending(
-    const content::WebContents* web_contents) {
-  return is_fullscreen_;
-}
-
-blink::mojom::DisplayMode CefBrowserHostImpl::GetDisplayMode(
-    const content::WebContents* web_contents) {
-  return is_fullscreen_ ? blink::mojom::DisplayMode::kFullscreen
-                        : blink::mojom::DisplayMode::kBrowser;
-}
-
-void CefBrowserHostImpl::FindReply(content::WebContents* web_contents,
-                                   int request_id,
-                                   int number_of_matches,
-                                   const gfx::Rect& selection_rect,
-                                   int active_match_ordinal,
-                                   bool final_update) {
-  if (client_.get()) {
-    CefRefPtr<CefFindHandler> handler = client_->GetFindHandler();
-    if (handler.get()) {
-      CefRect rect(selection_rect.x(), selection_rect.y(),
-                   selection_rect.width(), selection_rect.height());
-      handler->OnFindResult(this, request_id, number_of_matches, rect,
-                            active_match_ordinal, final_update);
-    }
-  }
-}
-
-void CefBrowserHostImpl::ImeSetComposition(
-    const CefString& text,
-    const std::vector<CefCompositionUnderline>& underlines,
-    const CefRange& replacement_range,
-    const CefRange& selection_range) {
-  if (!IsWindowless()) {
-    NOTREACHED() << "Window rendering is not disabled";
-    return;
-  }
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::BindOnce(&CefBrowserHostImpl::ImeSetComposition, this, text,
-                       underlines, replacement_range, selection_range));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->ImeSetComposition(text, underlines, replacement_range,
-                                        selection_range);
-}
-
-void CefBrowserHostImpl::ImeCommitText(const CefString& text,
-                                       const CefRange& replacement_range,
-                                       int relative_cursor_pos) {
-  if (!IsWindowless()) {
-    NOTREACHED() << "Window rendering is not disabled";
-    return;
-  }
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::ImeCommitText, this, text,
-                                 replacement_range, relative_cursor_pos));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->ImeCommitText(text, replacement_range,
-                                    relative_cursor_pos);
-}
-
-void CefBrowserHostImpl::ImeFinishComposingText(bool keep_selection) {
-  if (!IsWindowless()) {
-    NOTREACHED() << "Window rendering is not disabled";
-    return;
-  }
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::ImeFinishComposingText,
-                                 this, keep_selection));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->ImeFinishComposingText(keep_selection);
-}
-
-void CefBrowserHostImpl::ImeCancelComposition() {
-  if (!IsWindowless()) {
-    NOTREACHED() << "Window rendering is not disabled";
-    return;
-  }
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::BindOnce(&CefBrowserHostImpl::ImeCancelComposition, this));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->ImeCancelComposition();
-}
-
-void CefBrowserHostImpl::DragTargetDragEnter(
-    CefRefPtr<CefDragData> drag_data,
-    const CefMouseEvent& event,
-    CefBrowserHost::DragOperationsMask allowed_ops) {
-  if (!IsWindowless()) {
-    NOTREACHED() << "Window rendering is not disabled";
-    return;
-  }
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::DragTargetDragEnter, this,
-                                 drag_data, event, allowed_ops));
-    return;
-  }
-
-  if (!drag_data.get()) {
-    NOTREACHED();
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->DragTargetDragEnter(drag_data, event, allowed_ops);
-}
-
-void CefBrowserHostImpl::DragTargetDragOver(
-    const CefMouseEvent& event,
-    CefBrowserHost::DragOperationsMask allowed_ops) {
-  if (!IsWindowless()) {
-    NOTREACHED() << "Window rendering is not disabled";
-    return;
-  }
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefBrowserHostImpl::DragTargetDragOver, this,
-                                 event, allowed_ops));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->DragTargetDragOver(event, allowed_ops);
-}
-
-void CefBrowserHostImpl::DragTargetDragLeave() {
-  if (!IsWindowless()) {
-    NOTREACHED() << "Window rendering is not disabled";
-    return;
-  }
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(
-                               &CefBrowserHostImpl::DragTargetDragLeave, this));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->DragTargetDragLeave();
-}
-
-void CefBrowserHostImpl::DragTargetDrop(const CefMouseEvent& event) {
-  if (!IsWindowless()) {
-    NOTREACHED() << "Window rendering is not disabled";
-    return;
-  }
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostImpl::DragTargetDrop,
-                                          this, event));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->DragTargetDrop(event);
-}
-
-void CefBrowserHostImpl::DragSourceSystemDragEnded() {
-  if (!IsWindowless()) {
-    NOTREACHED() << "Window rendering is not disabled";
-    return;
-  }
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::BindOnce(&CefBrowserHostImpl::DragSourceSystemDragEnded, this));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->DragSourceSystemDragEnded();
-}
-
-void CefBrowserHostImpl::DragSourceEndedAt(
-    int x,
-    int y,
-    CefBrowserHost::DragOperationsMask op) {
-  if (!IsWindowless()) {
-    NOTREACHED() << "Window rendering is not disabled";
-    return;
-  }
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::BindOnce(&CefBrowserHostImpl::DragSourceEndedAt, this, x, y, op));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->DragSourceEndedAt(x, y, op);
-}
-
-void CefBrowserHostImpl::SetAudioMuted(bool mute) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::Bind(&CefBrowserHostImpl::SetAudioMuted, this, mute));
-    return;
-  }
-  if (!web_contents())
-    return;
-  web_contents()->SetAudioMuted(mute);
-}
-
-bool CefBrowserHostImpl::IsAudioMuted() {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
-    return false;
-  }
-  if (!web_contents())
-    return false;
-  return web_contents()->IsAudioMuted();
-}
-
-// content::WebContentsDelegate methods.
-// -----------------------------------------------------------------------------
-
-// |source| may be NULL if the navigation originates from a guest view via
-// CefContentBrowserClient::CanCreateWindow.
-content::WebContents* CefBrowserHostImpl::OpenURLFromTab(
-    content::WebContents* source,
-    const content::OpenURLParams& params) {
-  bool cancel = false;
-
-  if (client_.get()) {
-    CefRefPtr<CefRequestHandler> handler = client_->GetRequestHandler();
-    if (handler.get()) {
-      cancel = handler->OnOpenURLFromTab(
-          this, GetFrame(params.frame_tree_node_id), params.url.spec(),
-          static_cast<cef_window_open_disposition_t>(params.disposition),
-          params.user_gesture);
-    }
-  }
-
-  if (!cancel) {
-    // Start a navigation in the current browser that will result in the
-    // creation of a new render process.
-    LoadMainFrameURL(params.url.spec(), params.referrer, params.transition,
-                     params.extra_headers);
-    return source;
-  }
-
-  // We don't know where the navigation, if any, will occur.
-  return nullptr;
-}
-
-bool CefBrowserHostImpl::ShouldTransferNavigation(
-    bool is_main_frame_navigation) {
-  if (extension_host_) {
-    return extension_host_->ShouldTransferNavigation(is_main_frame_navigation);
-  }
-  return true;
-}
-
-void CefBrowserHostImpl::AddNewContents(
-    content::WebContents* source,
-    std::unique_ptr<content::WebContents> new_contents,
-    WindowOpenDisposition disposition,
-    const gfx::Rect& initial_rect,
-    bool user_gesture,
-    bool* was_blocked) {
-  CefRefPtr<CefBrowserHostImpl> owner =
-      GetBrowserForContents(new_contents.get());
-  if (owner) {
-    // Taking ownership of |new_contents|.
-    owner->set_owned_web_contents(new_contents.release());
-    return;
-  }
-
-  if (extension_host_) {
-    extension_host_->AddNewContents(source, std::move(new_contents),
-                                    disposition, initial_rect, user_gesture,
-                                    was_blocked);
-  }
-}
-
-void CefBrowserHostImpl::LoadingStateChanged(content::WebContents* source,
-                                             bool to_different_document) {
-  const int current_index =
-      source->GetController().GetLastCommittedEntryIndex();
-  const int max_index = source->GetController().GetEntryCount() - 1;
-
-  const bool is_loading = source->IsLoading();
-  const bool can_go_back = (current_index > 0);
-  const bool can_go_forward = (current_index < max_index);
-
-  {
-    base::AutoLock lock_scope(state_lock_);
-
-    // This method may be called multiple times in a row with |is_loading|
-    // true as a result of https://crrev.com/5e750ad0. Ignore the 2nd+ times.
-    if (is_loading_ == is_loading && can_go_back_ == can_go_back &&
-        can_go_forward_ == can_go_forward) {
-      return;
-    }
-
-    is_loading_ = is_loading;
-    can_go_back_ = can_go_back;
-    can_go_forward_ = can_go_forward;
-  }
-
-  if (client_.get()) {
-    CefRefPtr<CefLoadHandler> handler = client_->GetLoadHandler();
-    if (handler.get()) {
-      handler->OnLoadingStateChange(this, is_loading, can_go_back,
-                                    can_go_forward);
-    }
-  }
-}
-
-void CefBrowserHostImpl::LoadProgressChanged(double progress) {
-  if (client_.get()) {
-    CefRefPtr<CefDisplayHandler> handler = client_->GetDisplayHandler();
-    if (handler.get()) {
-      handler->OnLoadingProgressChange(this, progress);
-    }
-  }
-}
-
-void CefBrowserHostImpl::CloseContents(content::WebContents* source) {
-  CEF_REQUIRE_UIT();
-
-  if (destruction_state_ == DESTRUCTION_STATE_COMPLETED)
-    return;
-
-  bool close_browser = true;
-
-  // If this method is called in response to something other than
-  // WindowDestroyed() ask the user if the browser should close.
-  if (client_.get() && (IsWindowless() || !window_destroyed_)) {
-    CefRefPtr<CefLifeSpanHandler> handler = client_->GetLifeSpanHandler();
-    if (handler.get()) {
-      close_browser = !handler->DoClose(this);
-    }
-  }
-
-  if (close_browser) {
-    if (destruction_state_ != DESTRUCTION_STATE_ACCEPTED)
-      destruction_state_ = DESTRUCTION_STATE_ACCEPTED;
-
-    if (!IsWindowless() && !window_destroyed_) {
-      // A window exists so try to close it using the platform method. Will
-      // result in a call to WindowDestroyed() if/when the window is destroyed
-      // via the platform window destruction mechanism.
-      platform_delegate_->CloseHostWindow();
-    } else {
-      // Keep a reference to the browser while it's in the process of being
-      // destroyed.
-      CefRefPtr<CefBrowserHostImpl> browser(this);
-
-      // No window exists. Destroy the browser immediately. Don't call other
-      // browser methods after calling DestroyBrowser().
-      DestroyBrowser();
-    }
-  } else if (destruction_state_ != DESTRUCTION_STATE_NONE) {
-    destruction_state_ = DESTRUCTION_STATE_NONE;
-  }
-}
-
-void CefBrowserHostImpl::UpdateTargetURL(content::WebContents* source,
-                                         const GURL& url) {
-  if (client_.get()) {
-    CefRefPtr<CefDisplayHandler> handler = client_->GetDisplayHandler();
-    if (handler.get())
-      handler->OnStatusMessage(this, url.spec());
-  }
-}
-
-bool CefBrowserHostImpl::DidAddMessageToConsole(
-    content::WebContents* source,
-    blink::mojom::ConsoleMessageLevel level,
-    const base::string16& message,
-    int32_t line_no,
-    const base::string16& source_id) {
-  if (client_.get()) {
-    CefRefPtr<CefDisplayHandler> handler = client_->GetDisplayHandler();
-    if (handler.get()) {
-      // Use LOGSEVERITY_DEBUG for unrecognized |level| values.
-      cef_log_severity_t log_level = LOGSEVERITY_DEBUG;
-      switch (level) {
-        case blink::mojom::ConsoleMessageLevel::kVerbose:
-          log_level = LOGSEVERITY_DEBUG;
-          break;
-        case blink::mojom::ConsoleMessageLevel::kInfo:
-          log_level = LOGSEVERITY_INFO;
-          break;
-        case blink::mojom::ConsoleMessageLevel::kWarning:
-          log_level = LOGSEVERITY_WARNING;
-          break;
-        case blink::mojom::ConsoleMessageLevel::kError:
-          log_level = LOGSEVERITY_ERROR;
-          break;
-      }
-
-      return handler->OnConsoleMessage(this, log_level, message, source_id,
-                                       line_no);
-    }
-  }
-
-  return false;
-}
-
-void CefBrowserHostImpl::BeforeUnloadFired(content::WebContents* source,
-                                           bool proceed,
-                                           bool* proceed_to_fire_unload) {
-  if (destruction_state_ == DESTRUCTION_STATE_ACCEPTED || proceed) {
-    *proceed_to_fire_unload = true;
-  } else if (!proceed) {
-    *proceed_to_fire_unload = false;
-    destruction_state_ = DESTRUCTION_STATE_NONE;
-  }
-}
-
-bool CefBrowserHostImpl::TakeFocus(content::WebContents* source, bool reverse) {
-  if (client_.get()) {
-    CefRefPtr<CefFocusHandler> handler = client_->GetFocusHandler();
-    if (handler.get())
-      handler->OnTakeFocus(this, !reverse);
-  }
-
-  return false;
-}
-
-bool CefBrowserHostImpl::HandleContextMenu(
-    content::RenderFrameHost* render_frame_host,
-    const content::ContextMenuParams& params) {
-  return HandleContextMenu(web_contents(), params);
-}
-
-content::WebContents* CefBrowserHostImpl::GetActionableWebContents() const {
-  if (web_contents() && extensions::ExtensionsEnabled()) {
-    content::WebContents* guest_contents =
-        extensions::GetFullPageGuestForOwnerContents(web_contents());
-    if (guest_contents)
-      return guest_contents;
-  }
-  return web_contents();
-}
-
-KeyboardEventProcessingResult CefBrowserHostImpl::PreHandleKeyboardEvent(
-    content::WebContents* source,
-    const content::NativeWebKeyboardEvent& event) {
-  if (platform_delegate_ && client_.get()) {
-    CefRefPtr<CefKeyboardHandler> handler = client_->GetKeyboardHandler();
-    if (handler.get()) {
-      CefKeyEvent cef_event;
-      if (browser_util::GetCefKeyEvent(event, cef_event)) {
-        cef_event.focus_on_editable_field = focus_on_editable_field_;
-
-        CefEventHandle event_handle = platform_delegate_->GetEventHandle(event);
-        bool is_keyboard_shortcut = false;
-        bool result = handler->OnPreKeyEvent(this, cef_event, event_handle,
-                                             &is_keyboard_shortcut);
-        if (result)
-          return KeyboardEventProcessingResult::HANDLED;
-        else if (is_keyboard_shortcut)
-          return KeyboardEventProcessingResult::NOT_HANDLED_IS_SHORTCUT;
-      }
-    }
-  }
-
-  return KeyboardEventProcessingResult::NOT_HANDLED;
-}
-
-bool CefBrowserHostImpl::HandleKeyboardEvent(
-    content::WebContents* source,
-    const content::NativeWebKeyboardEvent& event) {
-  // Check to see if event should be ignored.
-  if (event.skip_in_browser)
-    return false;
-
-  if (!platform_delegate_)
-    return false;
-
-  if (client_.get()) {
-    CefRefPtr<CefKeyboardHandler> handler = client_->GetKeyboardHandler();
-    if (handler.get()) {
-      CefKeyEvent cef_event;
-      if (browser_util::GetCefKeyEvent(event, cef_event)) {
-        cef_event.focus_on_editable_field = focus_on_editable_field_;
-
-        CefEventHandle event_handle = platform_delegate_->GetEventHandle(event);
-        if (handler->OnKeyEvent(this, cef_event, event_handle))
-          return true;
-      }
-    }
-  }
-
-  return platform_delegate_->HandleKeyboardEvent(event);
-}
-
-bool CefBrowserHostImpl::PreHandleGestureEvent(
-    content::WebContents* source,
-    const blink::WebGestureEvent& event) {
-  if (extension_host_)
-    return extension_host_->PreHandleGestureEvent(source, event);
-  return false;
-}
-
-bool CefBrowserHostImpl::CanDragEnter(content::WebContents* source,
-                                      const content::DropData& data,
-                                      blink::WebDragOperationsMask mask) {
-  CefRefPtr<CefDragHandler> handler = client_->GetDragHandler();
-  if (handler.get()) {
-    CefRefPtr<CefDragDataImpl> drag_data(new CefDragDataImpl(data));
-    drag_data->SetReadOnly(true);
-    if (handler->OnDragEnter(
-            this, drag_data.get(),
-            static_cast<CefDragHandler::DragOperationsMask>(mask))) {
-      return false;
-    }
-  }
-  return true;
-}
-
-void CefBrowserHostImpl::GetCustomWebContentsView(
-    content::WebContents* web_contents,
-    const GURL& target_url,
-    int opener_render_process_id,
-    int opener_render_frame_id,
-    content::WebContentsView** view,
-    content::RenderViewHostDelegateView** delegate_view) {
-  CefBrowserInfoManager::GetInstance()->GetCustomWebContentsView(
-      target_url, opener_render_process_id, opener_render_frame_id, view,
-      delegate_view);
-}
-
-void CefBrowserHostImpl::WebContentsCreated(
-    content::WebContents* source_contents,
-    int opener_render_process_id,
-    int opener_render_frame_id,
-    const std::string& frame_name,
-    const GURL& target_url,
-    content::WebContents* new_contents) {
-  CefBrowserSettings settings;
-  CefRefPtr<CefClient> client;
-  std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate;
-  CefRefPtr<CefDictionaryValue> extra_info;
-
-  CefBrowserInfoManager::GetInstance()->WebContentsCreated(
-      target_url, opener_render_process_id, opener_render_frame_id, settings,
-      client, platform_delegate, extra_info);
-
-  scoped_refptr<CefBrowserInfo> info =
-      CefBrowserInfoManager::GetInstance()->CreatePopupBrowserInfo(
-          new_contents, platform_delegate->IsWindowless(), extra_info);
-  DCHECK(info.get());
-  DCHECK(info->is_popup());
-
-  CefRefPtr<CefBrowserHostImpl> opener = GetBrowserForContents(source_contents);
-  if (!opener.get())
-    return;
-
-  // Popups must share the same RequestContext as the parent.
-  CefRefPtr<CefRequestContextImpl> request_context = opener->request_context();
-  DCHECK(request_context);
-
-  // We don't officially own |new_contents| until AddNewContents() is called.
-  // However, we need to install observers/delegates here.
-  CefRefPtr<CefBrowserHostImpl> browser =
-      CreateInternal(settings, client, new_contents, false, info, opener, false,
-                     request_context, std::move(platform_delegate), nullptr);
-}
-
-void CefBrowserHostImpl::DidNavigateMainFramePostCommit(
-    content::WebContents* web_contents) {
-  base::AutoLock lock_scope(state_lock_);
-  has_document_ = false;
-}
-
-content::JavaScriptDialogManager*
-CefBrowserHostImpl::GetJavaScriptDialogManager(content::WebContents* source) {
-  if (!javascript_dialog_manager_.get() && platform_delegate_) {
-    javascript_dialog_manager_.reset(new CefJavaScriptDialogManager(
-        this, platform_delegate_->CreateJavaScriptDialogRunner()));
-  }
-  return javascript_dialog_manager_.get();
-}
-
-void CefBrowserHostImpl::RunFileChooser(
-    content::RenderFrameHost* render_frame_host,
-    std::unique_ptr<content::FileSelectListener> listener,
-    const blink::mojom::FileChooserParams& params) {
-  EnsureFileDialogManager();
-  file_dialog_manager_->RunFileChooser(std::move(listener), params);
-}
-
-bool CefBrowserHostImpl::HandleContextMenu(
-    content::WebContents* web_contents,
-    const content::ContextMenuParams& params) {
-  CEF_REQUIRE_UIT();
-  if (!menu_manager_.get() && platform_delegate_) {
-    menu_manager_.reset(
-        new CefMenuManager(this, platform_delegate_->CreateMenuRunner()));
-  }
-  return menu_manager_->CreateContextMenu(params);
-}
-
-void CefBrowserHostImpl::UpdatePreferredSize(content::WebContents* source,
-                                             const gfx::Size& pref_size) {
-#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX))
-  CEF_REQUIRE_UIT();
-  if (platform_delegate_)
-    platform_delegate_->SizeTo(pref_size.width(), pref_size.height());
-#endif
-}
-
-void CefBrowserHostImpl::ResizeDueToAutoResize(content::WebContents* source,
-                                               const gfx::Size& new_size) {
-  CEF_REQUIRE_UIT();
-
-  if (client_) {
-    CefRefPtr<CefDisplayHandler> handler = client_->GetDisplayHandler();
-    if (handler && handler->OnAutoResize(
-                       this, CefSize(new_size.width(), new_size.height()))) {
-      return;
-    }
-  }
-
-  UpdatePreferredSize(source, new_size);
-}
-
-void CefBrowserHostImpl::RequestMediaAccessPermission(
-    content::WebContents* web_contents,
-    const content::MediaStreamRequest& request,
-    content::MediaResponseCallback callback) {
-  CEF_REQUIRE_UIT();
-
-  blink::MediaStreamDevices devices;
-
-  const base::CommandLine* command_line =
-      base::CommandLine::ForCurrentProcess();
-  if (!command_line->HasSwitch(switches::kEnableMediaStream)) {
-    // Cancel the request.
-    std::move(callback).Run(
-        devices, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
-        std::unique_ptr<content::MediaStreamUI>());
-    return;
-  }
-
-  // Based on chrome/browser/media/media_stream_devices_controller.cc
-  bool microphone_requested =
-      (request.audio_type ==
-       blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE);
-  bool webcam_requested = (request.video_type ==
-                           blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE);
-  bool screen_requested =
-      (request.video_type ==
-       blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE);
-  if (microphone_requested || webcam_requested || screen_requested) {
-    // Pick the desired device or fall back to the first available of the
-    // given type.
-    if (microphone_requested) {
-      CefMediaCaptureDevicesDispatcher::GetInstance()->GetRequestedDevice(
-          request.requested_audio_device_id, true, false, &devices);
-    }
-    if (webcam_requested) {
-      CefMediaCaptureDevicesDispatcher::GetInstance()->GetRequestedDevice(
-          request.requested_video_device_id, false, true, &devices);
-    }
-    if (screen_requested) {
-      content::DesktopMediaID media_id;
-      if (request.requested_video_device_id.empty()) {
-        media_id =
-            content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
-                                    -1 /* webrtc::kFullDesktopScreenId */);
-      } else {
-        media_id =
-            content::DesktopMediaID::Parse(request.requested_video_device_id);
-      }
-      devices.push_back(blink::MediaStreamDevice(
-          blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE,
-          media_id.ToString(), "Screen"));
-    }
-  }
-
-  std::move(callback).Run(devices, blink::mojom::MediaStreamRequestResult::OK,
-                          std::unique_ptr<content::MediaStreamUI>());
-}
-
-bool CefBrowserHostImpl::CheckMediaAccessPermission(
-    content::RenderFrameHost* render_frame_host,
-    const GURL& security_origin,
-    blink::mojom::MediaStreamType type) {
-  // Check media access permission without prompting the user. This is called
-  // when loading the Pepper Flash plugin.
-  const base::CommandLine* command_line =
-      base::CommandLine::ForCurrentProcess();
-  return command_line->HasSwitch(switches::kEnableMediaStream);
-}
-
-bool CefBrowserHostImpl::IsNeverComposited(content::WebContents* web_contents) {
-  if (extension_host_)
-    return extension_host_->IsNeverComposited(web_contents);
-  return false;
-}
-
-content::PictureInPictureResult CefBrowserHostImpl::EnterPictureInPicture(
-    content::WebContents* web_contents,
-    const viz::SurfaceId& surface_id,
-    const gfx::Size& natural_size) {
-  if (!IsPictureInPictureSupported()) {
-    return content::PictureInPictureResult::kNotSupported;
-  }
-
-  return PictureInPictureWindowManager::GetInstance()->EnterPictureInPicture(
-      web_contents, surface_id, natural_size);
-}
-
-void CefBrowserHostImpl::ExitPictureInPicture() {
-  DCHECK(IsPictureInPictureSupported());
-  PictureInPictureWindowManager::GetInstance()->ExitPictureInPicture();
-}
-
-// content::WebContentsObserver methods.
-// -----------------------------------------------------------------------------
-
-void CefBrowserHostImpl::RenderFrameCreated(
-    content::RenderFrameHost* render_frame_host) {
-  browser_info_->MaybeCreateFrame(render_frame_host, false /* is_guest_view */);
-}
-
-void CefBrowserHostImpl::RenderFrameHostChanged(
-    content::RenderFrameHost* old_host,
-    content::RenderFrameHost* new_host) {
-  // Just in case RenderFrameCreated wasn't called for some reason.
-  RenderFrameCreated(new_host);
-}
-
-void CefBrowserHostImpl::RenderFrameDeleted(
-    content::RenderFrameHost* render_frame_host) {
-  const auto frame_id = CefFrameHostImpl::MakeFrameId(render_frame_host);
-  browser_info_->RemoveFrame(render_frame_host);
-
-  base::AutoLock lock_scope(state_lock_);
-
-  if (focused_frame_ && focused_frame_->GetIdentifier() == frame_id) {
-    focused_frame_ = nullptr;
-  }
-}
-
-void CefBrowserHostImpl::RenderViewCreated(
-    content::RenderViewHost* render_view_host) {
-  // May be already registered if the renderer crashed previously.
-  if (!registrar_->IsRegistered(
-          this, content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
-          content::Source<content::RenderViewHost>(render_view_host))) {
-    registrar_->Add(this, content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
-                    content::Source<content::RenderViewHost>(render_view_host));
-  }
-
-  // RenderFrameCreated is otherwise not called for new popup browsers.
-  RenderFrameCreated(render_view_host->GetMainFrame());
-
-  platform_delegate_->RenderViewCreated(render_view_host);
-}
-
-void CefBrowserHostImpl::RenderViewDeleted(
-    content::RenderViewHost* render_view_host) {
-  if (registrar_->IsRegistered(
-          this, content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
-          content::Source<content::RenderViewHost>(render_view_host))) {
-    registrar_->Remove(
-        this, content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
-        content::Source<content::RenderViewHost>(render_view_host));
-  }
-}
-
-void CefBrowserHostImpl::RenderViewReady() {
-  ConfigureAutoResize();
-
-  if (client_.get()) {
-    CefRefPtr<CefRequestHandler> handler = client_->GetRequestHandler();
-    if (handler.get())
-      handler->OnRenderViewReady(this);
-  }
-}
-
-void CefBrowserHostImpl::RenderProcessGone(base::TerminationStatus status) {
-  cef_termination_status_t ts = TS_ABNORMAL_TERMINATION;
-  if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED)
-    ts = TS_PROCESS_WAS_KILLED;
-  else if (status == base::TERMINATION_STATUS_PROCESS_CRASHED)
-    ts = TS_PROCESS_CRASHED;
-  else if (status == base::TERMINATION_STATUS_OOM)
-    ts = TS_PROCESS_OOM;
-  else if (status != base::TERMINATION_STATUS_ABNORMAL_TERMINATION)
-    return;
-
-  if (client_.get()) {
-    CefRefPtr<CefRequestHandler> handler = client_->GetRequestHandler();
-    if (handler.get()) {
-      std::unique_ptr<NavigationLock> navigation_lock = CreateNavigationLock();
-      handler->OnRenderProcessTerminated(this, ts);
-    }
-  }
-}
-
-void CefBrowserHostImpl::DidFinishNavigation(
-    content::NavigationHandle* navigation_handle) {
-  const net::Error error_code = navigation_handle->GetNetErrorCode();
-
-  // Skip calls where the navigation has not yet committed and there is no
-  // error code. For example, when creating a browser without loading a URL.
-  if (!navigation_handle->HasCommitted() && error_code == net::OK)
-    return;
-
-  const bool is_main_frame = navigation_handle->IsInMainFrame();
-  const GURL& url =
-      (error_code == net::OK ? navigation_handle->GetURL() : GURL());
-
-  // May return NULL when starting a new navigation if the previous navigation
-  // caused the renderer process to crash during load.
-  CefRefPtr<CefFrameHostImpl> frame = browser_info_->GetFrameForFrameTreeNode(
-      navigation_handle->GetFrameTreeNodeId());
-  if (!frame) {
-    if (is_main_frame) {
-      frame = browser_info_->GetMainFrame();
-    } else {
-      frame =
-          browser_info_->CreateTempSubFrame(CefFrameHostImpl::kInvalidFrameId);
-    }
-  }
-  frame->RefreshAttributes();
-
-  if (error_code == net::OK) {
-    // The navigation has been committed and there is no error.
-    DCHECK(navigation_handle->HasCommitted());
-
-    // Don't call OnLoadStart for same page navigations (fragments,
-    // history state).
-    if (!navigation_handle->IsSameDocument())
-      OnLoadStart(frame.get(), navigation_handle->GetPageTransition());
-
-    if (is_main_frame)
-      OnAddressChange(url);
-  } else {
-    // The navigation failed with an error. This may happen before commit
-    // (e.g. network error) or after commit (e.g. response filter error).
-    // If the error happened before commit then this call will originate from
-    // RenderFrameHostImpl::OnDidFailProvisionalLoadWithError.
-    // OnLoadStart/OnLoadEnd will not be called.
-    OnLoadError(frame.get(), navigation_handle->GetURL(), error_code);
-  }
-
-  if (web_contents()) {
-    CefBrowserContext* context =
-        static_cast<CefBrowserContext*>(web_contents()->GetBrowserContext());
-    if (context) {
-      context->AddVisitedURLs(navigation_handle->GetRedirectChain());
-    }
-  }
-}
-
-void CefBrowserHostImpl::DidStopLoading() {
-  // Notify all renderers that loading has stopped. We used to use
-  // RenderFrameObserver::DidStopLoading which was removed in
-  // https://crrev.com/3e37dd0ead. However, that callback wasn't necessarily
-  // accurate because it wasn't called in all of the cases where
-  // RenderFrameImpl sends the FrameHostMsg_DidStopLoading message. This adds
-  // an additional round trip but should provide the same or improved
-  // functionality.
-  for (const auto& frame : browser_info_->GetAllFrames()) {
-    frame->MaybeSendDidStopLoading();
-  }
-}
-
-void CefBrowserHostImpl::DocumentAvailableInMainFrame() {
-  {
-    base::AutoLock lock_scope(state_lock_);
-    has_document_ = true;
-  }
-
-  if (client_) {
-    CefRefPtr<CefRequestHandler> handler = client_->GetRequestHandler();
-    if (handler)
-      handler->OnDocumentAvailableInMainFrame(this);
-  }
-}
-
-void CefBrowserHostImpl::DidFailLoad(
-    content::RenderFrameHost* render_frame_host,
-    const GURL& validated_url,
-    int error_code) {
-  // The navigation failed after commit. OnLoadStart was called so we also
-  // call OnLoadEnd.
-  auto frame = browser_info_->GetFrameForHost(render_frame_host);
-  frame->RefreshAttributes();
-  OnLoadError(frame, validated_url, error_code);
-  OnLoadEnd(frame, validated_url, error_code);
-}
-
-void CefBrowserHostImpl::TitleWasSet(content::NavigationEntry* entry) {
-  // |entry| may be NULL if a popup is created via window.open and never
-  // navigated.
-  if (entry)
-    OnTitleChange(entry->GetTitle());
-  else if (web_contents())
-    OnTitleChange(web_contents()->GetTitle());
-}
-
-void CefBrowserHostImpl::PluginCrashed(const base::FilePath& plugin_path,
-                                       base::ProcessId plugin_pid) {
-  if (client_.get()) {
-    CefRefPtr<CefRequestHandler> handler = client_->GetRequestHandler();
-    if (handler.get())
-      handler->OnPluginCrashed(this, plugin_path.value());
-  }
-}
-
-void CefBrowserHostImpl::DidUpdateFaviconURL(
-    const std::vector<blink::mojom::FaviconURLPtr>& candidates) {
-  if (client_.get()) {
-    CefRefPtr<CefDisplayHandler> handler = client_->GetDisplayHandler();
-    if (handler.get()) {
-      std::vector<CefString> icon_urls;
-      for (const auto& icon : candidates) {
-        if (icon->icon_type == blink::mojom::FaviconIconType::kFavicon)
-          icon_urls.push_back(icon->icon_url.spec());
-      }
-      if (!icon_urls.empty())
-        handler->OnFaviconURLChange(this, icon_urls);
-    }
-  }
-}
-
-void CefBrowserHostImpl::OnAudioStateChanged(bool audible) {
-  if (audible) {
-    recently_audible_timer_.Stop();
-    StartAudioCapturer();
-  } else if (audio_capturer_) {
-    // If you have a media playing that has a short quiet moment, web_contents
-    // will immediately switch to non-audible state. We don't want to stop
-    // audio stream so quickly, let's give the stream some time to resume
-    // playing.
-    recently_audible_timer_.Start(
-        FROM_HERE, kRecentlyAudibleTimeout,
-        base::BindOnce(&CefBrowserHostImpl::OnRecentlyAudibleTimerFired, this));
-  }
-}
-
-void CefBrowserHostImpl::OnRecentlyAudibleTimerFired() {
-  audio_capturer_.reset();
-}
-
-bool CefBrowserHostImpl::OnMessageReceived(const IPC::Message& message) {
-  // Handle the cursor message here if mouse cursor change is disabled instead
-  // of propegating the message to the normal handler.
-  if (message.type() == WidgetHostMsg_SetCursor::ID)
-    return IsMouseCursorChangeDisabled();
-
-  return false;
-}
-
-bool CefBrowserHostImpl::OnMessageReceived(
-    const IPC::Message& message,
-    content::RenderFrameHost* render_frame_host) {
-  // Messages may arrive after a frame is detached. Ignore those messages.
-  auto frame = GetFrameForHost(render_frame_host);
-  if (frame) {
-    return static_cast<CefFrameHostImpl*>(frame.get())
-        ->OnMessageReceived(message);
-  }
-  return false;
-}
-
-void CefBrowserHostImpl::OnFrameFocused(
-    content::RenderFrameHost* render_frame_host) {
-  CefRefPtr<CefFrameHostImpl> frame =
-      static_cast<CefFrameHostImpl*>(GetFrameForHost(render_frame_host).get());
-  if (!frame || frame->IsFocused())
-    return;
-
-  CefRefPtr<CefFrameHostImpl> previous_frame;
-  {
-    base::AutoLock lock_scope(state_lock_);
-    previous_frame = focused_frame_;
-    if (frame->IsMain())
-      focused_frame_ = nullptr;
-    else
-      focused_frame_ = frame;
-  }
-
-  if (!previous_frame) {
-    // The main frame is focused by default.
-    previous_frame = browser_info_->GetMainFrame();
-  }
-
-  if (previous_frame->GetIdentifier() != frame->GetIdentifier()) {
-    previous_frame->SetFocused(false);
-    frame->SetFocused(true);
-  }
-}
-
-void CefBrowserHostImpl::AccessibilityEventReceived(
-    const content::AXEventNotificationDetails& content_event_bundle) {
-  // Only needed in windowless mode.
-  if (IsWindowless()) {
-    if (!web_contents() || !platform_delegate_)
-      return;
-
-    platform_delegate_->AccessibilityEventReceived(content_event_bundle);
-  }
-}
-
-void CefBrowserHostImpl::AccessibilityLocationChangesReceived(
-    const std::vector<content::AXLocationChangeNotificationDetails>& locData) {
-  // Only needed in windowless mode.
-  if (IsWindowless()) {
-    if (!web_contents() || !platform_delegate_)
-      return;
-
-    platform_delegate_->AccessibilityLocationChangesReceived(locData);
-  }
-}
-
-void CefBrowserHostImpl::OnWebContentsFocused(
-    content::RenderWidgetHost* render_widget_host) {
-  if (client_.get()) {
-    CefRefPtr<CefFocusHandler> handler = client_->GetFocusHandler();
-    if (handler.get())
-      handler->OnGotFocus(this);
-  }
-}
-
-void CefBrowserHostImpl::AddObserver(Observer* observer) {
-  CEF_REQUIRE_UIT();
-  observers_.AddObserver(observer);
-}
-
-void CefBrowserHostImpl::RemoveObserver(Observer* observer) {
-  CEF_REQUIRE_UIT();
-  observers_.RemoveObserver(observer);
-}
-
-bool CefBrowserHostImpl::HasObserver(Observer* observer) const {
-  CEF_REQUIRE_UIT();
-  return observers_.HasObserver(observer);
-}
-
-void CefBrowserHostImpl::StartAudioCapturer() {
-  if (!client_.get() || audio_capturer_)
-    return;
-
-  CefRefPtr<CefAudioHandler> audio_handler = client_->GetAudioHandler();
-  if (!audio_handler.get())
-    return;
-
-  CefAudioParameters params;
-  params.channel_layout = CEF_CHANNEL_LAYOUT_STEREO;
-  params.sample_rate = media::AudioParameters::kAudioCDSampleRate;
-  params.frames_per_buffer = 1024;
-
-  if (!audio_handler->GetAudioParameters(this, params))
-    return;
-
-  audio_capturer_.reset(new CefAudioCapturer(params, this, audio_handler));
-}
-
-CefBrowserHostImpl::NavigationLock::NavigationLock(
-    CefRefPtr<CefBrowserHostImpl> browser)
-    : browser_(browser) {
-  CEF_REQUIRE_UIT();
-  browser_->navigation_lock_count_++;
-}
-
-CefBrowserHostImpl::NavigationLock::~NavigationLock() {
-  CEF_REQUIRE_UIT();
-  if (--browser_->navigation_lock_count_ == 0) {
-    if (!browser_->pending_navigation_action_.is_null()) {
-      CEF_POST_TASK(CEF_UIT, std::move(browser_->pending_navigation_action_));
-    }
-  }
-}
-
-std::unique_ptr<CefBrowserHostImpl::NavigationLock>
-CefBrowserHostImpl::CreateNavigationLock() {
-  return base::WrapUnique(new NavigationLock(this));
-}
-
-bool CefBrowserHostImpl::navigation_locked() const {
-  CEF_REQUIRE_UIT();
-  return navigation_lock_count_ > 0;
-}
-
-void CefBrowserHostImpl::set_pending_navigation_action(
-    base::OnceClosure action) {
-  CEF_REQUIRE_UIT();
-  pending_navigation_action_ = std::move(action);
-}
-
-// content::NotificationObserver methods.
-// -----------------------------------------------------------------------------
-
-void CefBrowserHostImpl::Observe(int type,
-                                 const content::NotificationSource& source,
-                                 const content::NotificationDetails& details) {
-  DCHECK(type == content::NOTIFICATION_LOAD_STOP ||
-         type == content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE);
-
-  if (type == content::NOTIFICATION_LOAD_STOP) {
-    content::NavigationController* controller =
-        content::Source<content::NavigationController>(source).ptr();
-    OnTitleChange(controller->GetWebContents()->GetTitle());
-  } else if (type == content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE) {
-    focus_on_editable_field_ = *content::Details<bool>(details).ptr();
-  }
-}
-
-// CefBrowserHostImpl private methods.
-// -----------------------------------------------------------------------------
-
-CefBrowserHostImpl::CefBrowserHostImpl(
-    const CefBrowserSettings& settings,
-    CefRefPtr<CefClient> client,
-    content::WebContents* web_contents,
-    scoped_refptr<CefBrowserInfo> browser_info,
-    CefRefPtr<CefBrowserHostImpl> opener,
-    CefRefPtr<CefRequestContextImpl> request_context,
-    std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
-    CefRefPtr<CefExtension> extension)
-    : content::WebContentsObserver(web_contents),
-      settings_(settings),
-      client_(client),
-      browser_info_(browser_info),
-      opener_(kNullWindowHandle),
-      request_context_(request_context),
-      platform_delegate_(std::move(platform_delegate)),
-      is_windowless_(platform_delegate_->IsWindowless()),
-      is_views_hosted_(platform_delegate_->IsViewsHosted()),
-      extension_(extension) {
-  if (opener.get() && !platform_delegate_->IsViewsHosted()) {
-    // GetOpenerWindowHandle() only returns a value for non-views-hosted
-    // popup browsers.
-    opener_ = opener->GetWindowHandle();
-  }
-
-  DCHECK(!browser_info_->browser().get());
-  browser_info_->SetBrowser(this);
-
-  web_contents->SetDelegate(this);
-
-  // Associate the WebContents with this browser object.
-  WebContentsUserDataAdapter::Register(this);
-
-  registrar_.reset(new content::NotificationRegistrar);
-
-  // When navigating through the history, the restored NavigationEntry's title
-  // will be used. If the entry ends up having the same title after we return
-  // to it, as will usually be the case, the
-  // NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED will then be suppressed, since
-  // the NavigationEntry's title hasn't changed.
-  registrar_->Add(this, content::NOTIFICATION_LOAD_STOP,
-                  content::Source<content::NavigationController>(
-                      &web_contents->GetController()));
-
-  PrefsTabHelper::CreateForWebContents(web_contents);
-  printing::CefPrintViewManager::CreateForWebContents(web_contents);
-
-  if (extensions::ExtensionsEnabled()) {
-    extensions::CefExtensionWebContentsObserver::CreateForWebContents(
-        web_contents);
-
-    // Used by the tabs extension API.
-    zoom::ZoomController::CreateForWebContents(web_contents);
-  }
-
-  // Make sure RenderViewCreated is called at least one time.
-  RenderViewCreated(web_contents->GetRenderViewHost());
-
-  // Associate the platform delegate with this browser.
-  platform_delegate_->BrowserCreated(this);
-}
-
-void CefBrowserHostImpl::set_owned_web_contents(
-    content::WebContents* owned_contents) {
-  // Should not currently own a WebContents.
-  CHECK(!owned_web_contents_);
-  // Should already be associated with |owned_contents|.
-  CHECK(web_contents() == owned_contents);
-  owned_web_contents_.reset(owned_contents);
-}
-
-bool CefBrowserHostImpl::CreateHostWindow() {
-  // |host_window_handle_| will not change after initial host creation for
-  // non-views-hosted browsers.
-  bool success = true;
-  if (!IsWindowless())
-    success = platform_delegate_->CreateHostWindow();
-  if (success && !IsViewsHosted())
-    host_window_handle_ = platform_delegate_->GetHostWindowHandle();
-  return success;
-}
-
-void CefBrowserHostImpl::CreateExtensionHost(
-    const extensions::Extension* extension,
-    content::BrowserContext* browser_context,
-    content::WebContents* host_contents,
-    const GURL& url,
-    extensions::ViewType host_type) {
-  DCHECK(!extension_host_);
-
-  if (host_type == extensions::VIEW_TYPE_EXTENSION_DIALOG ||
-      host_type == extensions::VIEW_TYPE_EXTENSION_POPUP) {
-    // Create an extension host that we own.
-    extension_host_ = new extensions::CefExtensionViewHost(
-        this, extension, browser_context, host_contents, url, host_type);
-    // Trigger load of the extension URL.
-    extension_host_->CreateRenderViewSoon();
-  } else if (host_type == extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
-    is_background_host_ = true;
-    // Create an extension host that will be owned by ProcessManager.
-    extension_host_ = new extensions::CefExtensionBackgroundHost(
-        this, base::BindOnce(&CefBrowserHostImpl::OnExtensionHostDeleted, this),
-        extension, browser_context, host_contents, url, host_type);
-    // Load will be triggered by ProcessManager::CreateBackgroundHost.
-  } else {
-    NOTREACHED() << " Unsupported extension host type: " << host_type;
-  }
-}
-
-void CefBrowserHostImpl::DestroyExtensionHost() {
-  if (!extension_host_)
-    return;
-  if (extension_host_->extension_host_type() ==
-      extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
-    DCHECK(is_background_host_);
-    // Close notification for background pages arrives via CloseContents.
-    // The extension host will be deleted by
-    // ProcessManager::CloseBackgroundHost and OnExtensionHostDeleted will be
-    // called to notify us.
-    extension_host_->Close();
-  } else {
-    DCHECK(!is_background_host_);
-    // We own the extension host and must delete it.
-    delete extension_host_;
-    extension_host_ = nullptr;
-  }
-}
-
-void CefBrowserHostImpl::OnExtensionHostDeleted() {
-  DCHECK(is_background_host_);
-  DCHECK(extension_host_);
-  extension_host_ = nullptr;
-}
-
-gfx::Point CefBrowserHostImpl::GetScreenPoint(const gfx::Point& view) const {
-  CEF_REQUIRE_UIT();
-  if (platform_delegate_)
-    return platform_delegate_->GetScreenPoint(view);
-  return gfx::Point();
-}
-
-void CefBrowserHostImpl::StartDragging(
-    const content::DropData& drop_data,
-    blink::WebDragOperationsMask allowed_ops,
-    const gfx::ImageSkia& image,
-    const gfx::Vector2d& image_offset,
-    const content::DragEventSourceInfo& event_info,
-    content::RenderWidgetHostImpl* source_rwh) {
-  if (platform_delegate_) {
-    platform_delegate_->StartDragging(drop_data, allowed_ops, image,
-                                      image_offset, event_info, source_rwh);
-  }
-}
-
-void CefBrowserHostImpl::UpdateDragCursor(blink::WebDragOperation operation) {
-  if (platform_delegate_)
-    platform_delegate_->UpdateDragCursor(operation);
-}
-
-void CefBrowserHostImpl::OnAddressChange(const GURL& url) {
-  if (client_.get()) {
-    CefRefPtr<CefDisplayHandler> handler = client_->GetDisplayHandler();
-    if (handler.get()) {
-      // Notify the handler of an address change.
-      handler->OnAddressChange(this, GetMainFrame(), url.spec());
-    }
-  }
-}
-
-void CefBrowserHostImpl::OnLoadStart(CefRefPtr<CefFrame> frame,
-                                     ui::PageTransition transition_type) {
-  if (client_.get()) {
-    CefRefPtr<CefLoadHandler> handler = client_->GetLoadHandler();
-    if (handler.get()) {
-      // Notify the handler that loading has started.
-      handler->OnLoadStart(this, frame,
-                           static_cast<cef_transition_type_t>(transition_type));
-    }
-  }
-}
-
-void CefBrowserHostImpl::OnLoadError(CefRefPtr<CefFrame> frame,
-                                     const GURL& url,
-                                     int error_code) {
-  if (client_.get()) {
-    CefRefPtr<CefLoadHandler> handler = client_->GetLoadHandler();
-    if (handler.get()) {
-      std::unique_ptr<NavigationLock> navigation_lock = CreateNavigationLock();
-      // Notify the handler that loading has failed.
-      handler->OnLoadError(this, frame,
-                           static_cast<cef_errorcode_t>(error_code),
-                           net::ErrorToShortString(error_code), url.spec());
-    }
-  }
-}
-
-void CefBrowserHostImpl::OnLoadEnd(CefRefPtr<CefFrame> frame,
-                                   const GURL& url,
-                                   int http_status_code) {
-  if (client_.get()) {
-    CefRefPtr<CefLoadHandler> handler = client_->GetLoadHandler();
-    if (handler.get())
-      handler->OnLoadEnd(this, frame, http_status_code);
-  }
-}
-
-void CefBrowserHostImpl::OnFullscreenModeChange(bool fullscreen) {
-  if (is_fullscreen_ == fullscreen)
-    return;
-
-  is_fullscreen_ = fullscreen;
-  WasResized();
-
-  if (client_.get()) {
-    CefRefPtr<CefDisplayHandler> handler = client_->GetDisplayHandler();
-    if (handler.get())
-      handler->OnFullscreenModeChange(this, fullscreen);
-  }
-}
-
-void CefBrowserHostImpl::OnTitleChange(const base::string16& title) {
-  if (client_.get()) {
-    CefRefPtr<CefDisplayHandler> handler = client_->GetDisplayHandler();
-    if (handler.get())
-      handler->OnTitleChange(this, title);
-  }
-}
-
-void CefBrowserHostImpl::EnsureFileDialogManager() {
-  CEF_REQUIRE_UIT();
-  if (!file_dialog_manager_.get() && platform_delegate_) {
-    file_dialog_manager_.reset(new CefFileDialogManager(
-        this, platform_delegate_->CreateFileDialogRunner()));
-  }
-}
-
-void CefBrowserHostImpl::ConfigureAutoResize() {
-  CEF_REQUIRE_UIT();
-  if (!web_contents() || !web_contents()->GetRenderWidgetHostView()) {
-    return;
-  }
-
-  if (auto_resize_enabled_) {
-    web_contents()->GetRenderWidgetHostView()->EnableAutoResize(
-        auto_resize_min_, auto_resize_max_);
-  } else {
-    web_contents()->GetRenderWidgetHostView()->DisableAutoResize(gfx::Size());
-  }
-}
-
-void CefBrowserHostImpl::SendTouchEvent(const CefTouchEvent& event) {
-  if (!IsWindowless()) {
-    NOTREACHED() << "Window rendering is not disabled";
-    return;
-  }
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::Bind(&CefBrowserHostImpl::SendTouchEvent, this, event));
-    return;
-  }
-
-  if (!web_contents() || !platform_delegate_)
-    return;
-
-  platform_delegate_->SendTouchEvent(event);
-}
diff --git a/src/libcef/browser/browser_host_impl.h b/src/libcef/browser/browser_host_impl.h
deleted file mode 100644
index 0fb19b4..0000000
--- a/src/libcef/browser/browser_host_impl.h
+++ /dev/null
@@ -1,696 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_BROWSER_BROWSER_HOST_IMPL_H_
-#define CEF_LIBCEF_BROWSER_BROWSER_HOST_IMPL_H_
-#pragma once
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "include/cef_browser.h"
-#include "include/cef_client.h"
-#include "include/cef_frame.h"
-#include "include/views/cef_browser_view.h"
-#include "libcef/browser/browser_info.h"
-#include "libcef/browser/file_dialog_manager.h"
-#include "libcef/browser/frame_host_impl.h"
-#include "libcef/browser/javascript_dialog_manager.h"
-#include "libcef/browser/menu_manager.h"
-#include "libcef/browser/request_context_impl.h"
-
-#include "base/observer_list.h"
-#include "base/strings/string16.h"
-#include "base/synchronization/lock.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_delegate.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "extensions/common/view_type.h"
-
-namespace content {
-struct DragEventSourceInfo;
-class RenderWidgetHostImpl;
-}  // namespace content
-
-namespace extensions {
-class Extension;
-class ExtensionHost;
-}  // namespace extensions
-
-#if defined(USE_AURA)
-namespace views {
-class Widget;
-}
-#endif  // defined(USE_AURA)
-
-class CefAudioCapturer;
-class CefBrowserInfo;
-class CefBrowserPlatformDelegate;
-class CefDevToolsManager;
-class SiteInstance;
-
-// Implementation of CefBrowser.
-//
-// WebContentsDelegate: Interface for handling WebContents delegations. There is
-// a one-to-one relationship between CefBrowserHostImpl and WebContents
-// instances.
-//
-// WebContentsObserver: Interface for observing WebContents notifications and
-// IPC messages. There is a one-to-one relationship between WebContents and
-// RenderViewHost instances. IPC messages received by the RenderViewHost will be
-// forwarded to this WebContentsObserver implementation via WebContents. IPC
-// messages sent using CefBrowserHostImpl::Send() will be forwarded to the
-// RenderViewHost (after posting to the UI thread if necessary). Use
-// WebContentsObserver::routing_id() when sending IPC messages.
-//
-// NotificationObserver: Interface for observing post-processed notifications.
-class CefBrowserHostImpl : public CefBrowserHost,
-                           public CefBrowser,
-                           public content::WebContentsDelegate,
-                           public content::WebContentsObserver,
-                           public content::NotificationObserver {
- public:
-  // Used for handling the response to command messages.
-  class CommandResponseHandler : public virtual CefBaseRefCounted {
-   public:
-    virtual void OnResponse(const std::string& response) = 0;
-  };
-
-  // Interface to implement for observers that wish to be informed of changes
-  // to the CefBrowserHostImpl. All methods will be called on the UI thread.
-  class Observer {
-   public:
-    // Called before |browser| is destroyed. Any references to |browser| should
-    // be cleared when this method is called.
-    virtual void OnBrowserDestroyed(CefBrowserHostImpl* browser) = 0;
-
-   protected:
-    virtual ~Observer() {}
-  };
-
-  ~CefBrowserHostImpl() override;
-
-  struct CreateParams {
-    // Platform-specific window creation info. Will be nullptr when creating a
-    // views-hosted browser.
-    std::unique_ptr<CefWindowInfo> window_info;
-
-#if defined(USE_AURA)
-    // The BrowserView that will own a views-hosted browser. Will be nullptr for
-    // popup browsers (the BrowserView will be created later in that case).
-    CefRefPtr<CefBrowserView> browser_view;
-#endif
-
-    // Client implementation. May be nullptr.
-    CefRefPtr<CefClient> client;
-
-    // Initial URL to load. May be empty. If this is a valid extension URL then
-    // the browser will be created as an app view extension host.
-    GURL url;
-
-    // Browser settings.
-    CefBrowserSettings settings;
-
-    // Other browser that opened this DevTools browser. Will be nullptr for non-
-    // DevTools browsers.
-    CefRefPtr<CefBrowserHostImpl> devtools_opener;
-
-    // Request context to use when creating the browser. If nullptr the global
-    // request context will be used.
-    CefRefPtr<CefRequestContext> request_context;
-
-    CefRefPtr<CefDictionaryValue> extra_info;
-
-    // Used when explicitly creating the browser as an extension host via
-    // ProcessManager::CreateBackgroundHost.
-    const extensions::Extension* extension = nullptr;
-    extensions::ViewType extension_host_type = extensions::VIEW_TYPE_INVALID;
-  };
-
-  // Create a new CefBrowserHostImpl instance.
-  static CefRefPtr<CefBrowserHostImpl> Create(CreateParams& create_params);
-
-  // Returns the browser associated with the specified RenderViewHost.
-  static CefRefPtr<CefBrowserHostImpl> GetBrowserForHost(
-      const content::RenderViewHost* host);
-  // Returns the browser associated with the specified RenderFrameHost.
-  static CefRefPtr<CefBrowserHostImpl> GetBrowserForHost(
-      const content::RenderFrameHost* host);
-  // Returns the browser associated with the specified WebContents.
-  static CefRefPtr<CefBrowserHostImpl> GetBrowserForContents(
-      const content::WebContents* contents);
-  // Returns the browser associated with the specified FrameTreeNode ID.
-  static CefRefPtr<CefBrowserHostImpl> GetBrowserForFrameTreeNode(
-      int frame_tree_node_id);
-  // Returns the browser associated with the specified frame routing IDs.
-  static CefRefPtr<CefBrowserHostImpl> GetBrowserForFrameRoute(
-      int render_process_id,
-      int render_routing_id);
-
-  // CefBrowserHost methods.
-  CefRefPtr<CefBrowser> GetBrowser() override;
-  void CloseBrowser(bool force_close) override;
-  bool TryCloseBrowser() override;
-  void SetFocus(bool focus) override;
-  CefWindowHandle GetWindowHandle() override;
-  CefWindowHandle GetOpenerWindowHandle() override;
-  bool HasView() override;
-  CefRefPtr<CefClient> GetClient() override;
-  CefRefPtr<CefRequestContext> GetRequestContext() override;
-  double GetZoomLevel() override;
-  void SetZoomLevel(double zoomLevel) override;
-  void RunFileDialog(FileDialogMode mode,
-                     const CefString& title,
-                     const CefString& default_file_path,
-                     const std::vector<CefString>& accept_filters,
-                     int selected_accept_filter,
-                     CefRefPtr<CefRunFileDialogCallback> callback) override;
-  void StartDownload(const CefString& url) override;
-  void DownloadImage(const CefString& image_url,
-                     bool is_favicon,
-                     uint32 max_image_size,
-                     bool bypass_cache,
-                     CefRefPtr<CefDownloadImageCallback> callback) override;
-  void Print() override;
-  void PrintToPDF(const CefString& path,
-                  const CefPdfPrintSettings& settings,
-                  CefRefPtr<CefPdfPrintCallback> callback) override;
-  void Find(int identifier,
-            const CefString& searchText,
-            bool forward,
-            bool matchCase,
-            bool findNext) override;
-  void StopFinding(bool clearSelection) override;
-  void ShowDevTools(const CefWindowInfo& windowInfo,
-                    CefRefPtr<CefClient> client,
-                    const CefBrowserSettings& settings,
-                    const CefPoint& inspect_element_at) override;
-  void CloseDevTools() override;
-  bool HasDevTools() override;
-  bool SendDevToolsMessage(const void* message, size_t message_size) override;
-  int ExecuteDevToolsMethod(int message_id,
-                            const CefString& method,
-                            CefRefPtr<CefDictionaryValue> params) override;
-  CefRefPtr<CefRegistration> AddDevToolsMessageObserver(
-      CefRefPtr<CefDevToolsMessageObserver> observer) override;
-  void GetNavigationEntries(CefRefPtr<CefNavigationEntryVisitor> visitor,
-                            bool current_only) override;
-  void SetMouseCursorChangeDisabled(bool disabled) override;
-  bool IsMouseCursorChangeDisabled() override;
-  bool IsWindowRenderingDisabled() override;
-  void ReplaceMisspelling(const CefString& word) override;
-  void AddWordToDictionary(const CefString& word) override;
-  void WasResized() override;
-  void WasHidden(bool hidden) override;
-  void NotifyScreenInfoChanged() override;
-  void Invalidate(PaintElementType type) override;
-  void SendExternalBeginFrame() override;
-  void SendKeyEvent(const CefKeyEvent& event) override;
-  void SendMouseClickEvent(const CefMouseEvent& event,
-                           MouseButtonType type,
-                           bool mouseUp,
-                           int clickCount) override;
-  void SendMouseMoveEvent(const CefMouseEvent& event, bool mouseLeave) override;
-  void SendMouseWheelEvent(const CefMouseEvent& event,
-                           int deltaX,
-                           int deltaY) override;
-  void SendTouchEvent(const CefTouchEvent& event) override;
-  void SendFocusEvent(bool setFocus) override;
-  void SendCaptureLostEvent() override;
-  void NotifyMoveOrResizeStarted() override;
-  int GetWindowlessFrameRate() override;
-  void SetWindowlessFrameRate(int frame_rate) override;
-  void ImeSetComposition(const CefString& text,
-                         const std::vector<CefCompositionUnderline>& underlines,
-                         const CefRange& replacement_range,
-                         const CefRange& selection_range) override;
-  void ImeCommitText(const CefString& text,
-                     const CefRange& replacement_range,
-                     int relative_cursor_pos) override;
-  void ImeFinishComposingText(bool keep_selection) override;
-  void ImeCancelComposition() override;
-  void DragTargetDragEnter(CefRefPtr<CefDragData> drag_data,
-                           const CefMouseEvent& event,
-                           DragOperationsMask allowed_ops) override;
-  void DragTargetDragOver(const CefMouseEvent& event,
-                          DragOperationsMask allowed_ops) override;
-  void DragTargetDragLeave() override;
-  void DragTargetDrop(const CefMouseEvent& event) override;
-  void DragSourceSystemDragEnded() override;
-  void DragSourceEndedAt(int x, int y, DragOperationsMask op) override;
-  void SetAudioMuted(bool mute) override;
-  bool IsAudioMuted() override;
-  CefRefPtr<CefNavigationEntry> GetVisibleNavigationEntry() override;
-  void SetAccessibilityState(cef_state_t accessibility_state) override;
-  void SetAutoResizeEnabled(bool enabled,
-                            const CefSize& min_size,
-                            const CefSize& max_size) override;
-  CefRefPtr<CefExtension> GetExtension() override;
-  bool IsBackgroundHost() override;
-
-  // CefBrowser methods.
-  CefRefPtr<CefBrowserHost> GetHost() override;
-  bool CanGoBack() override;
-  void GoBack() override;
-  bool CanGoForward() override;
-  void GoForward() override;
-  bool IsLoading() override;
-  void Reload() override;
-  void ReloadIgnoreCache() override;
-  void StopLoad() override;
-  int GetIdentifier() override;
-  bool IsSame(CefRefPtr<CefBrowser> that) override;
-  bool IsPopup() override;
-  bool HasDocument() override;
-  CefRefPtr<CefFrame> GetMainFrame() override;
-  CefRefPtr<CefFrame> GetFocusedFrame() override;
-  CefRefPtr<CefFrame> GetFrame(int64 identifier) override;
-  CefRefPtr<CefFrame> GetFrame(const CefString& name) override;
-  size_t GetFrameCount() override;
-  void GetFrameIdentifiers(std::vector<int64>& identifiers) override;
-  void GetFrameNames(std::vector<CefString>& names) override;
-
-  // Returns true if windowless rendering is enabled.
-  bool IsWindowless() const;
-
-  // Returns true if this browser is views-hosted.
-  bool IsViewsHosted() const;
-
-  // Returns true if this browser supports print preview.
-  bool IsPrintPreviewSupported() const;
-
-  // Returns true if this browser supports picture-in-picture.
-  bool IsPictureInPictureSupported() const;
-
-  // Called when the OS window hosting the browser is destroyed.
-  void WindowDestroyed();
-
-  // Destroy the browser members. This method should only be called after the
-  // native browser window is not longer processing messages.
-  void DestroyBrowser();
-
-  // Cancel display of the context menu, if any.
-  void CancelContextMenu();
-
-#if defined(USE_AURA)
-  // Returns the Widget owner for the browser window. Only used with windowed
-  // rendering.
-  views::Widget* GetWindowWidget() const;
-
-  // Returns the BrowserView associated with this browser. Only used with views-
-  // based browsers.
-  CefRefPtr<CefBrowserView> GetBrowserView() const;
-#endif
-
-  // Returns the frame associated with the specified RenderFrameHost.
-  CefRefPtr<CefFrame> GetFrameForHost(const content::RenderFrameHost* host);
-
-  // Returns the frame associated with the specified FrameTreeNode ID.
-  CefRefPtr<CefFrame> GetFrameForFrameTreeNode(int frame_tree_node_id);
-
-  // Load the specified URL in the main frame.
-  void LoadMainFrameURL(const std::string& url,
-                        const content::Referrer& referrer,
-                        ui::PageTransition transition,
-                        const std::string& extra_headers);
-
-  // Called from CefFrameHostImpl.
-  void OnDidFinishLoad(CefRefPtr<CefFrameHostImpl> frame,
-                       const GURL& validated_url,
-                       int http_status_code);
-
-  // Open the specified text in the default text editor.
-  void ViewText(const std::string& text);
-
-  // Convert from view coordinates to screen coordinates. Potential display
-  // scaling will be applied to the result.
-  gfx::Point GetScreenPoint(const gfx::Point& view) const;
-
-  void StartDragging(const content::DropData& drop_data,
-                     blink::WebDragOperationsMask allowed_ops,
-                     const gfx::ImageSkia& image,
-                     const gfx::Vector2d& image_offset,
-                     const content::DragEventSourceInfo& event_info,
-                     content::RenderWidgetHostImpl* source_rwh);
-  void UpdateDragCursor(blink::WebDragOperation operation);
-
-  // Thread safe accessors.
-  const CefBrowserSettings& settings() const { return settings_; }
-  SkColor GetBackgroundColor() const;
-  CefRefPtr<CefClient> client() const { return client_; }
-  scoped_refptr<CefBrowserInfo> browser_info() const { return browser_info_; }
-  int browser_id() const;
-  CefRefPtr<CefRequestContextImpl> request_context() const {
-    return request_context_;
-  }
-
-  // Accessors that must be called on the UI thread.
-  content::BrowserContext* GetBrowserContext();
-  extensions::ExtensionHost* extension_host() const { return extension_host_; }
-
-  void OnSetFocus(cef_focus_source_t source);
-
-  // Run the file chooser dialog specified by |params|. Only a single dialog may
-  // be pending at any given time. |callback| will be executed asynchronously
-  // after the dialog is dismissed or if another dialog is already pending.
-  void RunFileChooser(const CefFileDialogRunner::FileChooserParams& params,
-                      CefFileDialogRunner::RunFileChooserCallback callback);
-
-  bool HandleContextMenu(content::WebContents* web_contents,
-                         const content::ContextMenuParams& params);
-
-  // Returns the WebContents most likely to handle an action. If extensions are
-  // enabled and this browser has a full-page guest (for example, a full-page
-  // PDF viewer extension) then the guest's WebContents will be returned.
-  // Otherwise, the browser's WebContents will be returned.
-  content::WebContents* GetActionableWebContents() const;
-
-  enum DestructionState {
-    DESTRUCTION_STATE_NONE = 0,
-    DESTRUCTION_STATE_PENDING,
-    DESTRUCTION_STATE_ACCEPTED,
-    DESTRUCTION_STATE_COMPLETED
-  };
-  DestructionState destruction_state() const { return destruction_state_; }
-
-  // content::WebContentsDelegate methods.
-  content::WebContents* OpenURLFromTab(
-      content::WebContents* source,
-      const content::OpenURLParams& params) override;
-  bool ShouldTransferNavigation(bool is_main_frame_navigation) override;
-  void AddNewContents(content::WebContents* source,
-                      std::unique_ptr<content::WebContents> new_contents,
-                      WindowOpenDisposition disposition,
-                      const gfx::Rect& initial_rect,
-                      bool user_gesture,
-                      bool* was_blocked) override;
-  void LoadingStateChanged(content::WebContents* source,
-                           bool to_different_document) override;
-  void LoadProgressChanged(double progress) override;
-  void CloseContents(content::WebContents* source) override;
-  void UpdateTargetURL(content::WebContents* source, const GURL& url) override;
-  bool DidAddMessageToConsole(content::WebContents* source,
-                              blink::mojom::ConsoleMessageLevel log_level,
-                              const base::string16& message,
-                              int32_t line_no,
-                              const base::string16& source_id) override;
-  void BeforeUnloadFired(content::WebContents* source,
-                         bool proceed,
-                         bool* proceed_to_fire_unload) override;
-  bool TakeFocus(content::WebContents* source, bool reverse) override;
-
-  bool HandleContextMenu(content::RenderFrameHost* render_frame_host,
-                         const content::ContextMenuParams& params) override;
-  content::KeyboardEventProcessingResult PreHandleKeyboardEvent(
-      content::WebContents* source,
-      const content::NativeWebKeyboardEvent& event) override;
-  bool HandleKeyboardEvent(
-      content::WebContents* source,
-      const content::NativeWebKeyboardEvent& event) override;
-  bool PreHandleGestureEvent(content::WebContents* source,
-                             const blink::WebGestureEvent& event) override;
-  bool CanDragEnter(content::WebContents* source,
-                    const content::DropData& data,
-                    blink::WebDragOperationsMask operations_allowed) override;
-  void GetCustomWebContentsView(
-      content::WebContents* web_contents,
-      const GURL& target_url,
-      int opener_render_process_id,
-      int opener_render_frame_id,
-      content::WebContentsView** view,
-      content::RenderViewHostDelegateView** delegate_view) override;
-  void WebContentsCreated(content::WebContents* source_contents,
-                          int opener_render_process_id,
-                          int opener_render_frame_id,
-                          const std::string& frame_name,
-                          const GURL& target_url,
-                          content::WebContents* new_contents) override;
-  void DidNavigateMainFramePostCommit(
-      content::WebContents* web_contents) override;
-  content::JavaScriptDialogManager* GetJavaScriptDialogManager(
-      content::WebContents* source) override;
-  void RunFileChooser(content::RenderFrameHost* render_frame_host,
-                      std::unique_ptr<content::FileSelectListener> listener,
-                      const blink::mojom::FileChooserParams& params) override;
-  bool EmbedsFullscreenWidget() override;
-  void EnterFullscreenModeForTab(
-      content::WebContents* web_contents,
-      const GURL& origin,
-      const blink::mojom::FullscreenOptions& options) override;
-  void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
-  bool IsFullscreenForTabOrPending(
-      const content::WebContents* web_contents) override;
-  blink::mojom::DisplayMode GetDisplayMode(
-      const content::WebContents* web_contents) override;
-  void FindReply(content::WebContents* web_contents,
-                 int request_id,
-                 int number_of_matches,
-                 const gfx::Rect& selection_rect,
-                 int active_match_ordinal,
-                 bool final_update) override;
-  void UpdatePreferredSize(content::WebContents* source,
-                           const gfx::Size& pref_size) override;
-  void ResizeDueToAutoResize(content::WebContents* source,
-                             const gfx::Size& new_size) override;
-  void RequestMediaAccessPermission(
-      content::WebContents* web_contents,
-      const content::MediaStreamRequest& request,
-      content::MediaResponseCallback callback) override;
-  bool CheckMediaAccessPermission(content::RenderFrameHost* render_frame_host,
-                                  const GURL& security_origin,
-                                  blink::mojom::MediaStreamType type) override;
-  bool IsNeverComposited(content::WebContents* web_contents) override;
-  content::PictureInPictureResult EnterPictureInPicture(
-      content::WebContents* web_contents,
-      const viz::SurfaceId& surface_id,
-      const gfx::Size& natural_size) override;
-  void ExitPictureInPicture() override;
-
-  // content::WebContentsObserver methods.
-  using content::WebContentsObserver::BeforeUnloadFired;
-  void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
-  void RenderFrameHostChanged(content::RenderFrameHost* old_host,
-                              content::RenderFrameHost* new_host) override;
-  void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
-  void RenderViewCreated(content::RenderViewHost* render_view_host) override;
-  void RenderViewDeleted(content::RenderViewHost* render_view_host) override;
-  void RenderViewReady() override;
-  void RenderProcessGone(base::TerminationStatus status) override;
-  void DidFinishNavigation(
-      content::NavigationHandle* navigation_handle) override;
-  void DidStopLoading() override;
-  void DocumentAvailableInMainFrame() override;
-  void DidFailLoad(content::RenderFrameHost* render_frame_host,
-                   const GURL& validated_url,
-                   int error_code) override;
-  void TitleWasSet(content::NavigationEntry* entry) override;
-  void PluginCrashed(const base::FilePath& plugin_path,
-                     base::ProcessId plugin_pid) override;
-  void DidUpdateFaviconURL(
-      const std::vector<blink::mojom::FaviconURLPtr>& candidates) override;
-  void OnAudioStateChanged(bool audible) override;
-  bool OnMessageReceived(const IPC::Message& message) override;
-  bool OnMessageReceived(const IPC::Message& message,
-                         content::RenderFrameHost* render_frame_host) override;
-  void OnFrameFocused(content::RenderFrameHost* render_frame_host) override;
-  void AccessibilityEventReceived(
-      const content::AXEventNotificationDetails& content_event_bundle) override;
-  void AccessibilityLocationChangesReceived(
-      const std::vector<content::AXLocationChangeNotificationDetails>& locData)
-      override;
-
-  void OnWebContentsFocused(
-      content::RenderWidgetHost* render_widget_host) override;
-
-  // Manage observer objects. The observer must either outlive this object or
-  // remove itself before destruction. These methods can only be called on the
-  // UI thread.
-  void AddObserver(Observer* observer);
-  void RemoveObserver(Observer* observer);
-  bool HasObserver(Observer* observer) const;
-
-  class NavigationLock final {
-   private:
-    friend class CefBrowserHostImpl;
-    friend std::unique_ptr<NavigationLock>::deleter_type;
-
-    explicit NavigationLock(CefRefPtr<CefBrowserHostImpl> browser);
-    ~NavigationLock();
-
-    CefRefPtr<CefBrowserHostImpl> browser_;
-  };
-
-  // Block navigation-related events on NavigationLock life span.
-  std::unique_ptr<NavigationLock> CreateNavigationLock();
-
- private:
-  static CefRefPtr<CefBrowserHostImpl> CreateInternal(
-      const CefBrowserSettings& settings,
-      CefRefPtr<CefClient> client,
-      content::WebContents* web_contents,
-      bool own_web_contents,
-      scoped_refptr<CefBrowserInfo> browser_info,
-      CefRefPtr<CefBrowserHostImpl> opener,
-      bool is_devtools_popup,
-      CefRefPtr<CefRequestContextImpl> request_context,
-      std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
-      CefRefPtr<CefExtension> extension);
-
-  // content::NotificationObserver methods.
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override;
-
-  CefBrowserHostImpl(
-      const CefBrowserSettings& settings,
-      CefRefPtr<CefClient> client,
-      content::WebContents* web_contents,
-      scoped_refptr<CefBrowserInfo> browser_info,
-      CefRefPtr<CefBrowserHostImpl> opener,
-      CefRefPtr<CefRequestContextImpl> request_context,
-      std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
-      CefRefPtr<CefExtension> extension);
-
-  void set_owned_web_contents(content::WebContents* owned_contents);
-
-  // Give the platform delegate an opportunity to create the host window.
-  bool CreateHostWindow();
-
-  // Create/delete the host for extensions.
-  void CreateExtensionHost(const extensions::Extension* extension,
-                           content::BrowserContext* browser_context,
-                           content::WebContents* host_contents,
-                           const GURL& url,
-                           extensions::ViewType host_type);
-  void DestroyExtensionHost();
-  void OnExtensionHostDeleted();
-
-  // Returns true if navigation actions are currently locked.
-  bool navigation_locked() const;
-  // Action to be executed once the navigation lock is released.
-  void set_pending_navigation_action(base::OnceClosure action);
-
-  void OnAddressChange(const GURL& url);
-  void OnLoadStart(CefRefPtr<CefFrame> frame,
-                   ui::PageTransition transition_type);
-  void OnLoadError(CefRefPtr<CefFrame> frame, const GURL& url, int error_code);
-  void OnLoadEnd(CefRefPtr<CefFrame> frame,
-                 const GURL& url,
-                 int http_status_code);
-  void OnFullscreenModeChange(bool fullscreen);
-  void OnTitleChange(const base::string16& title);
-
-  // Create the CefFileDialogManager if it doesn't already exist.
-  void EnsureFileDialogManager();
-
-  void ConfigureAutoResize();
-
-  void StartAudioCapturer();
-
-  void OnRecentlyAudibleTimerFired();
-
-  bool EnsureDevToolsManager();
-  void InitializeDevToolsRegistrationOnUIThread(
-      CefRefPtr<CefRegistration> registration);
-
-  CefBrowserSettings settings_;
-  CefRefPtr<CefClient> client_;
-  scoped_refptr<CefBrowserInfo> browser_info_;
-  CefWindowHandle opener_;
-  CefRefPtr<CefRequestContextImpl> request_context_;
-  std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate_;
-  const bool is_windowless_;
-  const bool is_views_hosted_;
-  CefWindowHandle host_window_handle_ = kNullWindowHandle;
-
-  // Non-nullptr if this object owns the WebContents. Will be nullptr for popup
-  // browsers between the calls to WebContentsCreated() and AddNewContents(),
-  // and may never be set if the parent browser is destroyed during popup
-  // creation.
-  std::unique_ptr<content::WebContents> owned_web_contents_;
-
-  // Volatile state information. All access must be protected by the state lock.
-  base::Lock state_lock_;
-  bool is_loading_ = false;
-  bool can_go_back_ = false;
-  bool can_go_forward_ = false;
-  bool has_document_ = false;
-  bool is_fullscreen_ = false;
-
-  // The currently focused frame, or nullptr if the main frame is focused.
-  CefRefPtr<CefFrameHostImpl> focused_frame_;
-
-  // Represents the current browser destruction state. Only accessed on the UI
-  // thread.
-  DestructionState destruction_state_ = DESTRUCTION_STATE_NONE;
-
-  // Navigation will not occur while |navigation_lock_count_| > 0.
-  // |pending_navigation_action_| will be executed when the lock is released.
-  // Only accessed on the UI thread.
-  int navigation_lock_count_ = 0;
-  base::OnceClosure pending_navigation_action_;
-
-  // True if the OS window hosting the browser has been destroyed. Only accessed
-  // on the UI thread.
-  bool window_destroyed_ = false;
-
-  // True if currently in the OnSetFocus callback. Only accessed on the UI
-  // thread.
-  bool is_in_onsetfocus_ = false;
-
-  // True if the focus is currently on an editable field on the page. Only
-  // accessed on the UI thread.
-  bool focus_on_editable_field_ = false;
-
-  // True if mouse cursor change is disabled.
-  bool mouse_cursor_change_disabled_ = false;
-
-  // Used for managing notification subscriptions.
-  std::unique_ptr<content::NotificationRegistrar> registrar_;
-
-  // Used for creating and managing file dialogs.
-  std::unique_ptr<CefFileDialogManager> file_dialog_manager_;
-
-  // Used for creating and managing JavaScript dialogs.
-  std::unique_ptr<CefJavaScriptDialogManager> javascript_dialog_manager_;
-
-  // Used for creating and managing context menus.
-  std::unique_ptr<CefMenuManager> menu_manager_;
-
-  // Used for creating and managing DevTools instances.
-  std::unique_ptr<CefDevToolsManager> devtools_manager_;
-
-  // Observers that want to be notified of changes to this object.
-  base::ObserverList<Observer>::Unchecked observers_;
-
-  // Used to provide unique incremental IDs for each find request.
-  int find_request_id_counter_ = 0;
-
-  // Used when the browser is hosting an extension.
-  extensions::ExtensionHost* extension_host_ = nullptr;
-  CefRefPtr<CefExtension> extension_;
-  bool is_background_host_ = false;
-
-  // Used for capturing audio for CefAudioHandler.
-  std::unique_ptr<CefAudioCapturer> audio_capturer_;
-
-  // Timer for determining when "recently audible" transitions to false. This
-  // starts running when a tab stops being audible, and is canceled if it starts
-  // being audible again before it fires.
-  base::OneShotTimer recently_audible_timer_;
-
-  // Used with auto-resize.
-  bool auto_resize_enabled_ = false;
-  gfx::Size auto_resize_min_;
-  gfx::Size auto_resize_max_;
-
-  IMPLEMENT_REFCOUNTING(CefBrowserHostImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefBrowserHostImpl);
-};
-
-#endif  // CEF_LIBCEF_BROWSER_BROWSER_HOST_IMPL_H_
diff --git a/src/libcef/browser/browser_info.cc b/src/libcef/browser/browser_info.cc
index 851e7d5..d77d3f2 100644
--- a/src/libcef/browser/browser_info.cc
+++ b/src/libcef/browser/browser_info.cc
@@ -4,21 +4,24 @@
 
 #include "libcef/browser/browser_info.h"
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/browser_host_base.h"
 #include "libcef/browser/thread_util.h"
+#include "libcef/common/frame_util.h"
 #include "libcef/common/values_impl.h"
 
 #include "base/logging.h"
-#include "content/browser/frame_host/frame_tree_node.h"
-#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/renderer_host/frame_tree_node.h"
+#include "content/browser/renderer_host/render_frame_host_impl.h"
 #include "content/public/browser/render_process_host.h"
 #include "ipc/ipc_message.h"
 
 CefBrowserInfo::FrameInfo::~FrameInfo() {
-  if (frame_ && !is_main_frame_) {
-    // Disassociate sub-frames from the browser.
-    frame_->Detach();
+#if DCHECK_IS_ON()
+  if (frame_ && !IsCurrentMainFrame()) {
+    // Should already be Detached.
+    DCHECK(!frame_->GetRenderFrameHost());
   }
+#endif
 }
 
 CefBrowserInfo::CefBrowserInfo(int browser_id,
@@ -30,30 +33,68 @@
       is_windowless_(is_windowless),
       extra_info_(extra_info) {
   DCHECK_GT(browser_id, 0);
+
+  if (extra_info_ && !extra_info_->IsReadOnly()) {
+    // |extra_info_| should always be read-only to avoid accidental future
+    // modification. Take a copy instead of modifying the passed-in object for
+    // backwards compatibility.
+    extra_info_ = extra_info_->Copy(/*exclude_empty_children=*/false);
+    auto extra_info_impl =
+        static_cast<CefDictionaryValueImpl*>(extra_info_.get());
+    extra_info_impl->MarkReadOnly();
+  }
 }
 
-CefBrowserInfo::~CefBrowserInfo() {}
-
-CefRefPtr<CefBrowserHostImpl> CefBrowserInfo::browser() const {
-  base::AutoLock lock_scope(lock_);
-  return browser_;
+CefBrowserInfo::~CefBrowserInfo() {
+  DCHECK(frame_info_set_.empty());
 }
 
-void CefBrowserInfo::SetBrowser(CefRefPtr<CefBrowserHostImpl> browser) {
+CefRefPtr<CefBrowserHostBase> CefBrowserInfo::browser() const {
   base::AutoLock lock_scope(lock_);
+  if (!is_closing_) {
+    return browser_;
+  }
+  return nullptr;
+}
+
+void CefBrowserInfo::SetBrowser(CefRefPtr<CefBrowserHostBase> browser) {
+  NotificationStateLock lock_scope(this);
+
+  if (browser) {
+    DCHECK(!browser_);
+
+    // Cache the associated frame handler.
+    if (auto client = browser->GetClient()) {
+      frame_handler_ = client->GetFrameHandler();
+    }
+  } else {
+    DCHECK(browser_);
+  }
+
+  auto old_browser = browser_;
   browser_ = browser;
 
-  if (!browser) {
-    RemoveAllFrames();
+  if (!browser_) {
+    RemoveAllFrames(old_browser);
+
+    // Any future calls to MaybeExecuteFrameNotification will now fail.
+    // NotificationStateLock already took a reference for the delivery of any
+    // notifications that are currently queued due to RemoveAllFrames.
+    frame_handler_ = nullptr;
   }
 }
 
+void CefBrowserInfo::SetClosing() {
+  base::AutoLock lock_scope(lock_);
+  DCHECK(!is_closing_);
+  is_closing_ = true;
+}
+
 void CefBrowserInfo::MaybeCreateFrame(content::RenderFrameHost* host,
                                       bool is_guest_view) {
   CEF_REQUIRE_UIT();
 
-  const auto frame_id = CefFrameHostImpl::MakeFrameId(host);
-  const int frame_tree_node_id = host->GetFrameTreeNodeId();
+  const auto global_id = host->GetGlobalId();
   const bool is_main_frame = (host->GetParent() == nullptr);
 
   // A speculative RFH will be created in response to a browser-initiated
@@ -68,17 +109,16 @@
                                    ->render_manager()
                                    ->current_frame_host() != host);
 
-  base::AutoLock lock_scope(lock_);
+  NotificationStateLock lock_scope(this);
   DCHECK(browser_);
 
-  const auto it = frame_id_map_.find(frame_id);
+  const auto it = frame_id_map_.find(global_id);
   if (it != frame_id_map_.end()) {
     auto info = it->second;
 
 #if DCHECK_IS_ON()
     // Check that the frame info hasn't changed unexpectedly.
-    DCHECK_EQ(info->frame_id_, frame_id);
-    DCHECK_EQ(info->frame_tree_node_id_, frame_tree_node_id);
+    DCHECK_EQ(info->global_id_, global_id);
     DCHECK_EQ(info->is_guest_view_, is_guest_view);
     DCHECK_EQ(info->is_main_frame_, is_main_frame);
 #endif
@@ -86,185 +126,198 @@
     if (!info->is_guest_view_ && info->is_speculative_ && !is_speculative) {
       // Upgrade the frame info from speculative to non-speculative.
       if (info->is_main_frame_) {
-        if (main_frame_) {
-          // Update the existing main frame object.
-          main_frame_->SetRenderFrameHost(host);
-          info->frame_ = main_frame_;
-        } else {
-          // Set the main frame object.
-          main_frame_ = info->frame_;
-        }
+        // Set the main frame object.
+        SetMainFrame(browser_, info->frame_);
       }
       info->is_speculative_ = false;
-      MaybeUpdateFrameTreeNodeIdMap(info);
     }
     return;
   }
 
   auto frame_info = new FrameInfo;
   frame_info->host_ = host;
-  frame_info->frame_id_ = frame_id;
-  frame_info->frame_tree_node_id_ = frame_tree_node_id;
+  frame_info->global_id_ = global_id;
   frame_info->is_guest_view_ = is_guest_view;
   frame_info->is_main_frame_ = is_main_frame;
   frame_info->is_speculative_ = is_speculative;
 
   // Guest views don't get their own CefBrowser or CefFrame objects.
   if (!is_guest_view) {
-    if (is_main_frame && main_frame_ && !is_speculative) {
-      // Update the existing main frame object.
-      main_frame_->SetRenderFrameHost(host);
-      frame_info->frame_ = main_frame_;
-    } else {
-      // Create a new frame object.
-      frame_info->frame_ = new CefFrameHostImpl(this, host);
-      if (is_main_frame && !is_speculative) {
-        main_frame_ = frame_info->frame_;
-      }
+    // Create a new frame object.
+    frame_info->frame_ = new CefFrameHostImpl(this, host);
+    MaybeNotifyFrameCreated(frame_info->frame_);
+    if (is_main_frame && !is_speculative) {
+      SetMainFrame(browser_, frame_info->frame_);
     }
+
 #if DCHECK_IS_ON()
     // Check that the frame info hasn't changed unexpectedly.
-    DCHECK_EQ(frame_id, frame_info->frame_->GetIdentifier());
+    DCHECK_EQ(frame_util::MakeFrameId(global_id),
+              frame_info->frame_->GetIdentifier());
     DCHECK_EQ(frame_info->is_main_frame_, frame_info->frame_->IsMain());
 #endif
   }
 
-  browser_->request_context()->OnRenderFrameCreated(
-      host->GetProcess()->GetID(), host->GetRoutingID(), frame_tree_node_id,
-      is_main_frame, is_guest_view);
+  browser_->request_context()->OnRenderFrameCreated(global_id, is_main_frame,
+                                                    is_guest_view);
 
   // Populate the lookup maps.
-  frame_id_map_.insert(std::make_pair(frame_id, frame_info));
-  MaybeUpdateFrameTreeNodeIdMap(frame_info);
+  frame_id_map_.insert(std::make_pair(global_id, frame_info));
 
   // And finally set the ownership.
   frame_info_set_.insert(base::WrapUnique(frame_info));
 }
 
-void CefBrowserInfo::RemoveFrame(content::RenderFrameHost* host) {
+void CefBrowserInfo::FrameHostStateChanged(
+    content::RenderFrameHost* host,
+    content::RenderFrameHost::LifecycleState old_state,
+    content::RenderFrameHost::LifecycleState new_state) {
   CEF_REQUIRE_UIT();
 
+  if ((old_state == content::RenderFrameHost::LifecycleState::kPrerendering ||
+       old_state ==
+           content::RenderFrameHost::LifecycleState::kInBackForwardCache) &&
+      new_state == content::RenderFrameHost::LifecycleState::kActive) {
+    if (auto frame = GetFrameForHost(host)) {
+      // Update the associated RFH, which may have changed.
+      frame->MaybeReAttach(this, host);
+
+      if (frame->IsMain()) {
+        // Update the main frame object.
+        NotificationStateLock lock_scope(this);
+        SetMainFrame(browser_, frame);
+      }
+
+      // Update draggable regions.
+      frame->MaybeSendDidStopLoading();
+    }
+  }
+
+  // Update BackForwardCache state.
+  bool added_to_bfcache =
+      new_state ==
+      content::RenderFrameHost::LifecycleState::kInBackForwardCache;
+  bool removed_from_bfcache =
+      old_state ==
+      content::RenderFrameHost::LifecycleState::kInBackForwardCache;
+  if (!added_to_bfcache && !removed_from_bfcache) {
+    return;
+  }
+
   base::AutoLock lock_scope(lock_);
 
-  const auto frame_id = CefFrameHostImpl::MakeFrameId(host);
+  auto it = frame_id_map_.find(host->GetGlobalId());
+  DCHECK(it != frame_id_map_.end());
+  DCHECK((!it->second->is_in_bfcache_ && added_to_bfcache) ||
+         (it->second->is_in_bfcache_ && removed_from_bfcache));
+  it->second->is_in_bfcache_ = added_to_bfcache;
+}
 
-  auto it = frame_id_map_.find(frame_id);
+void CefBrowserInfo::RemoveFrame(content::RenderFrameHost* host) {
+  CEF_REQUIRE_UIT();
+
+  NotificationStateLock lock_scope(this);
+
+  const auto global_id = host->GetGlobalId();
+  auto it = frame_id_map_.find(global_id);
   DCHECK(it != frame_id_map_.end());
 
   auto frame_info = it->second;
 
   browser_->request_context()->OnRenderFrameDeleted(
-      host->GetProcess()->GetID(), host->GetRoutingID(),
-      frame_info->frame_tree_node_id_, frame_info->is_main_frame_,
-      frame_info->is_guest_view_);
+      global_id, frame_info->is_main_frame_, frame_info->is_guest_view_);
 
   // Remove from the lookup maps.
   frame_id_map_.erase(it);
 
-  // A new RFH with the same node ID may be added before the old RFH is deleted,
-  // or this might be a speculative RFH. Therefore only delete the map entry if
-  // it's currently pointing to the to-be-deleted frame info object.
-  {
-    auto it2 = frame_tree_node_id_map_.find(frame_info->frame_tree_node_id_);
-    if (it2 != frame_tree_node_id_map_.end() && it2->second == frame_info) {
-      frame_tree_node_id_map_.erase(frame_info->frame_tree_node_id_);
-    }
-  }
-
   // And finally delete the frame info.
   {
     auto it2 = frame_info_set_.find(frame_info);
+
+    // Explicitly Detach everything but the current main frame.
+    const auto& other_frame_info = *it2;
+    if (other_frame_info->frame_ && !other_frame_info->IsCurrentMainFrame()) {
+      if (other_frame_info->frame_->Detach(
+              CefFrameHostImpl::DetachReason::RENDER_FRAME_DELETED)) {
+        MaybeNotifyFrameDetached(browser_, other_frame_info->frame_);
+      }
+    }
+
     frame_info_set_.erase(it2);
   }
 }
 
 CefRefPtr<CefFrameHostImpl> CefBrowserInfo::GetMainFrame() {
   base::AutoLock lock_scope(lock_);
-  DCHECK(browser_);
-  if (!main_frame_) {
-    // Create a temporary object that will eventually be updated with real
-    // routing information.
-    main_frame_ =
-        new CefFrameHostImpl(this, true, CefFrameHostImpl::kInvalidFrameId);
+  // Early exit if called post-destruction.
+  if (!browser_ || is_closing_) {
+    return nullptr;
   }
+
+  CHECK(main_frame_);
   return main_frame_;
 }
 
 CefRefPtr<CefFrameHostImpl> CefBrowserInfo::CreateTempSubFrame(
-    int64_t parent_frame_id) {
-  CefRefPtr<CefFrameHostImpl> parent = GetFrameForId(parent_frame_id);
-  if (!parent)
+    const content::GlobalRenderFrameHostId& parent_global_id) {
+  CefRefPtr<CefFrameHostImpl> parent = GetFrameForGlobalId(parent_global_id);
+  if (!parent) {
     parent = GetMainFrame();
-  return new CefFrameHostImpl(this, false, parent->GetIdentifier());
+  }
+  // Intentionally not notifying for temporary frames.
+  return new CefFrameHostImpl(this, parent->GetIdentifier());
 }
 
 CefRefPtr<CefFrameHostImpl> CefBrowserInfo::GetFrameForHost(
     const content::RenderFrameHost* host,
-    bool* is_guest_view) const {
-  if (is_guest_view)
+    bool* is_guest_view,
+    bool prefer_speculative) const {
+  if (is_guest_view) {
     *is_guest_view = false;
+  }
 
-  if (!host)
+  if (!host) {
     return nullptr;
+  }
 
-  return GetFrameForId(CefFrameHostImpl::MakeFrameId(host), is_guest_view);
+  return GetFrameForGlobalId(
+      const_cast<content::RenderFrameHost*>(host)->GetGlobalId(), is_guest_view,
+      prefer_speculative);
 }
 
-CefRefPtr<CefFrameHostImpl> CefBrowserInfo::GetFrameForRoute(
-    int32_t render_process_id,
-    int32_t render_routing_id,
-    bool* is_guest_view) const {
-  if (is_guest_view)
+CefRefPtr<CefFrameHostImpl> CefBrowserInfo::GetFrameForGlobalId(
+    const content::GlobalRenderFrameHostId& global_id,
+    bool* is_guest_view,
+    bool prefer_speculative) const {
+  if (is_guest_view) {
     *is_guest_view = false;
+  }
 
-  if (render_process_id < 0 || render_routing_id < 0)
+  if (!frame_util::IsValidGlobalId(global_id)) {
     return nullptr;
-
-  return GetFrameForId(
-      CefFrameHostImpl::MakeFrameId(render_process_id, render_routing_id),
-      is_guest_view);
-}
-
-CefRefPtr<CefFrameHostImpl> CefBrowserInfo::GetFrameForId(
-    int64_t frame_id,
-    bool* is_guest_view) const {
-  if (is_guest_view)
-    *is_guest_view = false;
-
-  if (frame_id < 0)
-    return nullptr;
+  }
 
   base::AutoLock lock_scope(lock_);
 
-  const auto it = frame_id_map_.find(frame_id);
+  const auto it = frame_id_map_.find(global_id);
   if (it != frame_id_map_.end()) {
     const auto info = it->second;
 
     if (info->is_guest_view_) {
-      if (is_guest_view)
+      if (is_guest_view) {
         *is_guest_view = true;
+      }
       return nullptr;
     }
 
-    if (info->is_speculative_) {
+    if (info->is_speculative_ && !prefer_speculative) {
       if (info->is_main_frame_ && main_frame_) {
         // Always prefer the non-speculative main frame.
         return main_frame_;
-      } else {
-        // Always prefer an existing non-speculative frame for the same node ID.
-        bool is_guest_view_tmp;
-        auto frame = GetFrameForFrameTreeNodeInternal(info->frame_tree_node_id_,
-                                                      &is_guest_view_tmp);
-        if (is_guest_view_tmp) {
-          if (is_guest_view)
-            *is_guest_view = true;
-          return nullptr;
-        }
-        if (frame)
-          return frame;
       }
 
-      LOG(WARNING) << "Returning a speculative frame for frame id " << frame_id;
+      LOG(WARNING) << "Returning a speculative frame for "
+                   << frame_util::GetFrameDebugString(global_id);
     }
 
     DCHECK(info->frame_);
@@ -274,100 +327,247 @@
   return nullptr;
 }
 
-CefRefPtr<CefFrameHostImpl> CefBrowserInfo::GetFrameForFrameTreeNode(
-    int frame_tree_node_id,
-    bool* is_guest_view) const {
-  if (is_guest_view)
-    *is_guest_view = false;
-
-  if (frame_tree_node_id < 0)
-    return nullptr;
-
-  base::AutoLock lock_scope(lock_);
-  return GetFrameForFrameTreeNodeInternal(frame_tree_node_id, is_guest_view);
-}
-
 CefBrowserInfo::FrameHostList CefBrowserInfo::GetAllFrames() const {
   base::AutoLock lock_scope(lock_);
   FrameHostList frames;
   for (const auto& info : frame_info_set_) {
-    if (info->frame_ && !info->is_speculative_)
+    if (info->frame_ && !info->is_speculative_ && !info->is_in_bfcache_) {
       frames.insert(info->frame_);
+    }
   }
   return frames;
 }
 
-void CefBrowserInfo::MaybeUpdateFrameTreeNodeIdMap(FrameInfo* info) {
-  lock_.AssertAcquired();
+CefBrowserInfo::NavigationLock::NavigationLock() : weak_ptr_factory_(this) {}
 
-  auto it = frame_tree_node_id_map_.find(info->frame_tree_node_id_);
-  const bool has_entry = (it != frame_tree_node_id_map_.end());
+CefBrowserInfo::NavigationLock::~NavigationLock() {
+  CEF_REQUIRE_UIT();
+  if (pending_action_) {
+    CEF_POST_TASK(CEF_UIT, std::move(pending_action_));
+  }
+}
 
-  if (has_entry && it->second == info) {
-    // Already mapping to |info|.
+scoped_refptr<CefBrowserInfo::NavigationLock>
+CefBrowserInfo::CreateNavigationLock() {
+  CEF_REQUIRE_UIT();
+  scoped_refptr<NavigationLock> lock;
+  if (!navigation_lock_) {
+    lock = new NavigationLock();
+    navigation_lock_ = lock->weak_ptr_factory_.GetWeakPtr();
+  } else {
+    lock = navigation_lock_.get();
+  }
+  return lock;
+}
+
+bool CefBrowserInfo::IsNavigationLocked(base::OnceClosure pending_action) {
+  CEF_REQUIRE_UIT();
+  if (navigation_lock_) {
+    navigation_lock_->pending_action_ = std::move(pending_action);
+    return true;
+  }
+  return false;
+}
+
+void CefBrowserInfo::MaybeExecuteFrameNotification(
+    FrameNotifyOnceAction pending_action) {
+  CefRefPtr<CefFrameHandler> frame_handler;
+
+  {
+    base::AutoLock lock_scope_(notification_lock_);
+    if (!frame_handler_) {
+      // No notifications will be executed.
+      return;
+    }
+
+    if (notification_state_lock_) {
+      // Queue the notification until the lock is released.
+      notification_state_lock_->queue_.push(std::move(pending_action));
+      return;
+    }
+
+    frame_handler = frame_handler_;
+  }
+
+  // Execute immediately if not locked.
+  std::move(pending_action).Run(frame_handler);
+}
+
+void CefBrowserInfo::MaybeNotifyDraggableRegionsChanged(
+    CefRefPtr<CefBrowserHostBase> browser,
+    CefRefPtr<CefFrameHostImpl> frame,
+    std::vector<CefDraggableRegion> draggable_regions) {
+  CEF_REQUIRE_UIT();
+  DCHECK(frame->IsMain());
+
+  if (draggable_regions == draggable_regions_) {
     return;
   }
 
-  // Don't replace an existing node ID entry with a speculative RFH, but do
-  // add an entry if one doesn't already exist.
-  if (!info->is_speculative_ || !has_entry) {
-    // A new RFH with the same node ID may be added before the old RFH is
-    // deleted. To avoid duplicate entries in the map remove the old entry, if
-    // any, before adding the new entry.
-    if (has_entry)
-      frame_tree_node_id_map_.erase(it);
+  draggable_regions_ = std::move(draggable_regions);
 
-    frame_tree_node_id_map_.insert(
-        std::make_pair(info->frame_tree_node_id_, info));
-  }
-}
-
-CefRefPtr<CefFrameHostImpl> CefBrowserInfo::GetFrameForFrameTreeNodeInternal(
-    int frame_tree_node_id,
-    bool* is_guest_view) const {
-  if (is_guest_view)
-    *is_guest_view = false;
-
-  lock_.AssertAcquired();
-
-  const auto it = frame_tree_node_id_map_.find(frame_tree_node_id);
-  if (it != frame_tree_node_id_map_.end()) {
-    const auto info = it->second;
-
-    LOG_IF(WARNING, info->is_speculative_)
-        << "Returning a speculative frame for node id " << frame_tree_node_id;
-
-    if (info->is_guest_view_) {
-      if (is_guest_view)
-        *is_guest_view = true;
-      return nullptr;
+  if (auto client = browser->GetClient()) {
+    if (auto handler = client->GetDragHandler()) {
+      handler->OnDraggableRegionsChanged(browser.get(), frame,
+                                         draggable_regions_);
     }
-
-    DCHECK(info->frame_);
-    return info->frame_;
   }
-
-  return nullptr;
 }
 
-void CefBrowserInfo::RemoveAllFrames() {
+// Passing in |browser| here because |browser_| may already be cleared.
+void CefBrowserInfo::SetMainFrame(CefRefPtr<CefBrowserHostBase> browser,
+                                  CefRefPtr<CefFrameHostImpl> frame) {
   lock_.AssertAcquired();
+  DCHECK(browser);
+  DCHECK(!frame || frame->IsMain());
+
+  if (frame && main_frame_ &&
+      frame->GetIdentifier() == main_frame_->GetIdentifier()) {
+    // Nothing to do.
+    return;
+  }
+
+  CefRefPtr<CefFrameHostImpl> old_frame;
+  if (main_frame_) {
+    old_frame = main_frame_;
+    if (old_frame->Detach(CefFrameHostImpl::DetachReason::NEW_MAIN_FRAME)) {
+      MaybeNotifyFrameDetached(browser, old_frame);
+    }
+  }
+
+  main_frame_ = frame;
+
+  MaybeNotifyMainFrameChanged(browser, old_frame, main_frame_);
+}
+
+void CefBrowserInfo::MaybeNotifyFrameCreated(
+    CefRefPtr<CefFrameHostImpl> frame) {
+  CEF_REQUIRE_UIT();
+
+  // Never notify for temporary objects.
+  DCHECK(!frame->is_temporary());
+
+  MaybeExecuteFrameNotification(base::BindOnce(
+      [](scoped_refptr<CefBrowserInfo> self, CefRefPtr<CefFrameHostImpl> frame,
+         CefRefPtr<CefFrameHandler> handler) {
+        if (auto browser = self->browser()) {
+          handler->OnFrameCreated(browser, frame);
+        }
+      },
+      scoped_refptr<CefBrowserInfo>(this), frame));
+}
+
+// Passing in |browser| here because |browser_| may already be cleared.
+void CefBrowserInfo::MaybeNotifyFrameDetached(
+    CefRefPtr<CefBrowserHostBase> browser,
+    CefRefPtr<CefFrameHostImpl> frame) {
+  CEF_REQUIRE_UIT();
+
+  // Never notify for temporary objects.
+  DCHECK(!frame->is_temporary());
+
+  MaybeExecuteFrameNotification(base::BindOnce(
+      [](CefRefPtr<CefBrowserHostBase> browser,
+         CefRefPtr<CefFrameHostImpl> frame,
+         CefRefPtr<CefFrameHandler> handler) {
+        handler->OnFrameDetached(browser, frame);
+      },
+      browser, frame));
+}
+
+// Passing in |browser| here because |browser_| may already be cleared.
+void CefBrowserInfo::MaybeNotifyMainFrameChanged(
+    CefRefPtr<CefBrowserHostBase> browser,
+    CefRefPtr<CefFrameHostImpl> old_frame,
+    CefRefPtr<CefFrameHostImpl> new_frame) {
+  CEF_REQUIRE_UIT();
+
+  // Never notify for temporary objects.
+  DCHECK(!old_frame || !old_frame->is_temporary());
+  DCHECK(!new_frame || !new_frame->is_temporary());
+
+  MaybeExecuteFrameNotification(base::BindOnce(
+      [](CefRefPtr<CefBrowserHostBase> browser,
+         CefRefPtr<CefFrameHostImpl> old_frame,
+         CefRefPtr<CefFrameHostImpl> new_frame,
+         CefRefPtr<CefFrameHandler> handler) {
+        handler->OnMainFrameChanged(browser, old_frame, new_frame);
+      },
+      browser, old_frame, new_frame));
+}
+
+void CefBrowserInfo::RemoveAllFrames(
+    CefRefPtr<CefBrowserHostBase> old_browser) {
+  lock_.AssertAcquired();
+
+  // Make sure any callbacks will see the correct state (e.g. like
+  // CefBrowser::GetMainFrame returning nullptr and CefBrowser::IsValid
+  // returning false).
+  DCHECK(!browser_);
+  DCHECK(old_browser);
 
   // Clear the lookup maps.
   frame_id_map_.clear();
-  frame_tree_node_id_map_.clear();
 
-  // Explicitly Detach main frames.
+  // Explicitly Detach everything but the current main frame.
   for (auto& info : frame_info_set_) {
-    if (info->frame_ && info->is_main_frame_)
-      info->frame_->Detach();
+    if (info->frame_ && !info->IsCurrentMainFrame()) {
+      if (info->frame_->Detach(
+              CefFrameHostImpl::DetachReason::BROWSER_DESTROYED)) {
+        MaybeNotifyFrameDetached(old_browser, info->frame_);
+      }
+    }
   }
 
   if (main_frame_) {
-    main_frame_->Detach();
-    main_frame_ = nullptr;
+    SetMainFrame(old_browser, nullptr);
   }
 
   // And finally delete the frame info.
   frame_info_set_.clear();
 }
+
+CefBrowserInfo::NotificationStateLock::NotificationStateLock(
+    CefBrowserInfo* browser_info)
+    : browser_info_(browser_info) {
+  CEF_REQUIRE_UIT();
+
+  // Take the navigation state lock.
+  {
+    base::AutoLock lock_scope_(browser_info_->notification_lock_);
+    CHECK(!browser_info_->notification_state_lock_);
+    browser_info_->notification_state_lock_ = this;
+    // We may need this on destruction, and the original might be cleared.
+    frame_handler_ = browser_info_->frame_handler_;
+  }
+
+  // Take the browser info state lock.
+  browser_info_lock_scope_.reset(new base::AutoLock(browser_info_->lock_));
+}
+
+CefBrowserInfo::NotificationStateLock::~NotificationStateLock() {
+  CEF_REQUIRE_UIT();
+
+  // Unlock in reverse order.
+  browser_info_lock_scope_.reset();
+
+  {
+    base::AutoLock lock_scope_(browser_info_->notification_lock_);
+    CHECK_EQ(this, browser_info_->notification_state_lock_);
+    browser_info_->notification_state_lock_ = nullptr;
+  }
+
+  if (!queue_.empty()) {
+    DCHECK(frame_handler_);
+
+    // Don't navigate while inside callbacks.
+    auto nav_lock = browser_info_->CreateNavigationLock();
+
+    // Empty the queue of pending actions. Any of these actions might result in
+    // the acquisition of a new NotificationStateLock.
+    while (!queue_.empty()) {
+      std::move(queue_.front()).Run(frame_handler_);
+      queue_.pop();
+    }
+  }
+}
diff --git a/src/libcef/browser/browser_info.h b/src/libcef/browser/browser_info.h
index c48328f..d53d77a 100644
--- a/src/libcef/browser/browser_info.h
+++ b/src/libcef/browser/browser_info.h
@@ -6,6 +6,7 @@
 #define CEF_LIBCEF_BROWSER_BROWSER_INFO_H_
 #pragma once
 
+#include <queue>
 #include <set>
 #include <unordered_map>
 
@@ -13,20 +14,21 @@
 #include "libcef/common/values_impl.h"
 
 #include "base/containers/unique_ptr_adapters.h"
+#include "base/functional/callback.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
 #include "base/synchronization/lock.h"
 #include "base/values.h"
+#include "content/public/browser/global_routing_id.h"
+#include "content/public/browser/render_frame_host.h"
 
-namespace content {
-class RenderFrameHost;
-}
-
-class CefBrowserHostImpl;
+class CefBrowserHostBase;
+class CefFrameHandler;
 class CefFrameHostImpl;
 
 // CefBrowserInfo is used to associate a browser ID and render view/process
-// IDs with a particular CefBrowserHostImpl. Render view/process IDs may change
-// during the lifetime of a single CefBrowserHostImpl.
+// IDs with a particular CefBrowserHostBase. Render view/process IDs may change
+// during the lifetime of a single CefBrowserHostBase.
 //
 // CefBrowserInfo objects are managed by CefBrowserInfoManager and should not be
 // created directly.
@@ -37,6 +39,9 @@
                  bool is_windowless,
                  CefRefPtr<CefDictionaryValue> extra_info);
 
+  CefBrowserInfo(const CefBrowserInfo&) = delete;
+  CefBrowserInfo& operator=(const CefBrowserInfo&) = delete;
+
   int browser_id() const { return browser_id_; }
   bool is_popup() const { return is_popup_; }
   bool is_windowless() const { return is_windowless_; }
@@ -44,23 +49,38 @@
 
   // May return NULL if the browser has not yet been created or if the browser
   // has been destroyed.
-  CefRefPtr<CefBrowserHostImpl> browser() const;
+  CefRefPtr<CefBrowserHostBase> browser() const;
 
-  // Set or clear the browser. Called from the CefBrowserHostImpl constructor
+  // Set or clear the browser. Called from CefBrowserHostBase InitializeBrowser
   // (to set) and DestroyBrowser (to clear).
-  void SetBrowser(CefRefPtr<CefBrowserHostImpl> browser);
+  void SetBrowser(CefRefPtr<CefBrowserHostBase> browser);
+
+  // Called after OnBeforeClose and before SetBrowser(nullptr). This will cause
+  // browser() and GetMainFrame() to return nullptr as expected by
+  // CefFrameHandler callbacks. Note that this differs from calling
+  // SetBrowser(nullptr) because the WebContents has not yet been destroyed and
+  // further frame-related callbacks are expected.
+  void SetClosing();
 
   // Ensure that a frame record exists for |host|. Called for the main frame
   // when the RenderView is created, or for a sub-frame when the associated
   // RenderFrame is created in the renderer process.
-  // Called from CefBrowserHostImpl::RenderFrameCreated (is_guest_view = false)
-  // or CefMimeHandlerViewGuestDelegate::OnGuestAttached (is_guest_view = true).
+  // Called from CefBrowserContentsDelegate::RenderFrameCreated (is_guest_view =
+  // false) or CefMimeHandlerViewGuestDelegate::OnGuestAttached (is_guest_view =
+  // true).
   void MaybeCreateFrame(content::RenderFrameHost* host, bool is_guest_view);
 
+  // Used to track state changes such as entering/exiting the BackForwardCache.
+  // Called from CefBrowserContentsDelegate::RenderFrameHostStateChanged.
+  void FrameHostStateChanged(
+      content::RenderFrameHost* host,
+      content::RenderFrameHost::LifecycleState old_state,
+      content::RenderFrameHost::LifecycleState new_state);
+
   // Remove the frame record for |host|. Called for the main frame when the
   // RenderView is destroyed, or for a sub-frame when the associated RenderFrame
   // is destroyed in the renderer process.
-  // Called from CefBrowserHostImpl::FrameDeleted or
+  // Called from CefBrowserContentsDelegate::RenderFrameDeleted or
   // CefMimeHandlerViewGuestDelegate::OnGuestDetached.
   void RemoveFrame(content::RenderFrameHost* host);
 
@@ -76,7 +96,8 @@
   // is invalid the current main frame will be specified as the parent.
   // Temporary frame objects are not tracked but will be implicitly detached
   // on browser destruction.
-  CefRefPtr<CefFrameHostImpl> CreateTempSubFrame(int64_t parent_frame_id);
+  CefRefPtr<CefFrameHostImpl> CreateTempSubFrame(
+      const content::GlobalRenderFrameHostId& parent_global_id);
 
   // Returns the frame object matching the specified host or nullptr if no match
   // is found. Nullptr will also be returned if a guest view match is found
@@ -85,42 +106,62 @@
   // UI thread.
   CefRefPtr<CefFrameHostImpl> GetFrameForHost(
       const content::RenderFrameHost* host,
-      bool* is_guest_view = nullptr) const;
-
-  // Returns the frame object matching the specified IDs or nullptr if no match
-  // is found. Nullptr will also be returned if a guest view match is found
-  // because we don't create frame objects for guest views. If |is_guest_view|
-  // is non-nullptr it will be set to true in this case. Safe to call from any
-  // thread.
-  CefRefPtr<CefFrameHostImpl> GetFrameForRoute(
-      int32_t render_process_id,
-      int32_t render_routing_id,
-      bool* is_guest_view = nullptr) const;
+      bool* is_guest_view = nullptr,
+      bool prefer_speculative = false) const;
 
   // Returns the frame object matching the specified ID or nullptr if no match
   // is found. Nullptr will also be returned if a guest view match is found
   // because we don't create frame objects for guest views. If |is_guest_view|
   // is non-nullptr it will be set to true in this case. Safe to call from any
   // thread.
-  CefRefPtr<CefFrameHostImpl> GetFrameForId(
-      int64_t frame_id,
-      bool* is_guest_view = nullptr) const;
-
-  // Returns the frame object matching the specified ID or nullptr if no match
-  // is found. Nullptr will also be returned if a guest view match is found
-  // because we don't create frame objects for guest views. If |is_guest_view|
-  // is non-nullptr it will be set to true in this case. Safe to call from any
-  // thread.
-  CefRefPtr<CefFrameHostImpl> GetFrameForFrameTreeNode(
-      int frame_tree_node_id,
-      bool* is_guest_view = nullptr) const;
+  CefRefPtr<CefFrameHostImpl> GetFrameForGlobalId(
+      const content::GlobalRenderFrameHostId& global_id,
+      bool* is_guest_view = nullptr,
+      bool prefer_speculative = false) const;
 
   // Returns all non-speculative frame objects that currently exist. Guest views
   // will be excluded because they don't have a frame object. Safe to call from
   // any thread.
-  typedef std::set<CefRefPtr<CefFrameHostImpl>> FrameHostList;
+  using FrameHostList = std::set<CefRefPtr<CefFrameHostImpl>>;
   FrameHostList GetAllFrames() const;
 
+  class NavigationLock final : public base::RefCounted<NavigationLock> {
+   private:
+    friend class CefBrowserInfo;
+    friend class base::RefCounted<NavigationLock>;
+
+    NavigationLock();
+    ~NavigationLock();
+
+    base::OnceClosure pending_action_;
+    base::WeakPtrFactory<NavigationLock> weak_ptr_factory_;
+  };
+
+  // Block navigation actions on NavigationLock life span. Must be called on the
+  // UI thread.
+  scoped_refptr<NavigationLock> CreateNavigationLock();
+
+  // Returns true if navigation actions are currently blocked. If this method
+  // returns true the most recent |pending_action| will be executed on the UI
+  // thread once the navigation lock is released. Must be called on the UI
+  // thread.
+  bool IsNavigationLocked(base::OnceClosure pending_action);
+
+  using FrameNotifyOnceAction =
+      base::OnceCallback<void(CefRefPtr<CefFrameHandler>)>;
+
+  // Specifies a CefFrameHandler notification action whose execution may need
+  // to be blocked on release of a potentially held NotificationStateLock. If no
+  // CefFrameHandler exists then the action will be discarded without executing.
+  // If the NotificationStateLock is not currently held then the action will be
+  // executed immediately.
+  void MaybeExecuteFrameNotification(FrameNotifyOnceAction pending_action);
+
+  void MaybeNotifyDraggableRegionsChanged(
+      CefRefPtr<CefBrowserHostBase> browser,
+      CefRefPtr<CefFrameHostImpl> frame,
+      std::vector<CefDraggableRegion> draggable_regions);
+
  private:
   friend class base::RefCountedThreadSafe<CefBrowserInfo>;
 
@@ -129,51 +170,90 @@
   struct FrameInfo {
     ~FrameInfo();
 
+    inline bool IsCurrentMainFrame() const {
+      return frame_ && is_main_frame_ && !is_speculative_ && !is_in_bfcache_;
+    }
+
     content::RenderFrameHost* host_;
-    int64_t frame_id_;  // Combination of render_process_id + render_routing_id.
-    int frame_tree_node_id_;
+    content::GlobalRenderFrameHostId global_id_;
     bool is_guest_view_;
     bool is_main_frame_;
     bool is_speculative_;
+    bool is_in_bfcache_ = false;
     CefRefPtr<CefFrameHostImpl> frame_;
   };
 
-  void MaybeUpdateFrameTreeNodeIdMap(FrameInfo* info);
+  void SetMainFrame(CefRefPtr<CefBrowserHostBase> browser,
+                    CefRefPtr<CefFrameHostImpl> frame);
 
-  CefRefPtr<CefFrameHostImpl> GetFrameForFrameTreeNodeInternal(
-      int frame_tree_node_id,
-      bool* is_guest_view = nullptr) const;
+  void MaybeNotifyFrameCreated(CefRefPtr<CefFrameHostImpl> frame);
+  void MaybeNotifyFrameDetached(CefRefPtr<CefBrowserHostBase> browser,
+                                CefRefPtr<CefFrameHostImpl> frame);
+  void MaybeNotifyMainFrameChanged(CefRefPtr<CefBrowserHostBase> browser,
+                                   CefRefPtr<CefFrameHostImpl> old_frame,
+                                   CefRefPtr<CefFrameHostImpl> new_frame);
 
-  void RemoveAllFrames();
+  void RemoveAllFrames(CefRefPtr<CefBrowserHostBase> old_browser);
 
   int browser_id_;
   bool is_popup_;
   bool is_windowless_;
   CefRefPtr<CefDictionaryValue> extra_info_;
 
+  // Navigation will be blocked while |navigation_lock_| exists.
+  // Only accessed on the UI thread.
+  base::WeakPtr<NavigationLock> navigation_lock_;
+
+  // Used instead of |base::AutoLock(lock_)| in situations that might generate
+  // CefFrameHandler notifications. Any notifications passed to
+  // MaybeExecuteFrameNotification() will be queued until the lock is released,
+  // and then executed in order. Only accessed on the UI thread.
+  class NotificationStateLock final {
+   public:
+    explicit NotificationStateLock(CefBrowserInfo* browser_info);
+    ~NotificationStateLock();
+
+   protected:
+    friend class CefBrowserInfo;
+    CefBrowserInfo* const browser_info_;
+    CefRefPtr<CefFrameHandler> frame_handler_;
+    std::unique_ptr<base::AutoLock> browser_info_lock_scope_;
+    std::queue<FrameNotifyOnceAction> queue_;
+  };
+
+  mutable base::Lock notification_lock_;
+
+  // These members must be protected by |notification_lock_|.
+  NotificationStateLock* notification_state_lock_ = nullptr;
+  CefRefPtr<CefFrameHandler> frame_handler_;
+
   mutable base::Lock lock_;
 
   // The below members must be protected by |lock_|.
 
-  CefRefPtr<CefBrowserHostImpl> browser_;
+  CefRefPtr<CefBrowserHostBase> browser_;
 
   // Owner of FrameInfo structs.
-  typedef std::set<std::unique_ptr<FrameInfo>, base::UniquePtrComparator>
-      FrameInfoSet;
+  using FrameInfoSet =
+      std::set<std::unique_ptr<FrameInfo>, base::UniquePtrComparator>;
   FrameInfoSet frame_info_set_;
 
-  // Map a frame ID (e.g. MakeFrameId(process_id, routing_id)) to one frame.
-  typedef std::unordered_map<int64_t, FrameInfo*> FrameIDMap;
+  // Map a global ID to one frame. These IDs are guaranteed to uniquely
+  // identify a RFH for its complete lifespan. See documentation on
+  // RenderFrameHost::GetFrameTreeNodeId() for background.
+  using FrameIDMap = std::unordered_map<content::GlobalRenderFrameHostId,
+                                        FrameInfo*,
+                                        content::GlobalRenderFrameHostIdHasher>;
   FrameIDMap frame_id_map_;
 
-  // Map a frame_tree_node_id to one frame.
-  typedef std::unordered_map<int, FrameInfo*> FrameTreeNodeIDMap;
-  FrameTreeNodeIDMap frame_tree_node_id_map_;
-
   // The current main frame.
   CefRefPtr<CefFrameHostImpl> main_frame_;
 
-  DISALLOW_COPY_AND_ASSIGN(CefBrowserInfo);
+  // True if the browser is currently closing.
+  bool is_closing_ = false;
+
+  // Only accessed on the UI thread.
+  std::vector<CefDraggableRegion> draggable_regions_;
 };
 
 #endif  // CEF_LIBCEF_BROWSER_BROWSER_INFO_H_
diff --git a/src/libcef/browser/browser_info_manager.cc b/src/libcef/browser/browser_info_manager.cc
index 23622dc..39feaaf 100644
--- a/src/libcef/browser/browser_info_manager.cc
+++ b/src/libcef/browser/browser_info_manager.cc
@@ -6,22 +6,24 @@
 
 #include <utility>
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/browser_host_base.h"
 #include "libcef/browser/browser_platform_delegate.h"
 #include "libcef/browser/extensions/browser_extensions_util.h"
 #include "libcef/browser/thread_util.h"
-#include "libcef/common/cef_messages.h"
 #include "libcef/common/cef_switches.h"
 #include "libcef/common/extensions/extensions_util.h"
+#include "libcef/common/frame_util.h"
 #include "libcef/common/values_impl.h"
+#include "libcef/features/runtime_checks.h"
 
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "content/common/view_messages.h"
+#include "base/task/sequenced_task_runner.h"
+#include "content/public/browser/child_process_host.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/child_process_host.h"
+#include "content/public/common/url_constants.h"
 
 namespace {
 
@@ -30,19 +32,16 @@
 
 void TranslatePopupFeatures(const blink::mojom::WindowFeatures& webKitFeatures,
                             CefPopupFeatures& features) {
-  features.x = static_cast<int>(webKitFeatures.x);
+  features.x = static_cast<int>(webKitFeatures.bounds.x());
   features.xSet = webKitFeatures.has_x;
-  features.y = static_cast<int>(webKitFeatures.y);
+  features.y = static_cast<int>(webKitFeatures.bounds.y());
   features.ySet = webKitFeatures.has_y;
-  features.width = static_cast<int>(webKitFeatures.width);
+  features.width = static_cast<int>(webKitFeatures.bounds.width());
   features.widthSet = webKitFeatures.has_width;
-  features.height = static_cast<int>(webKitFeatures.height);
+  features.height = static_cast<int>(webKitFeatures.bounds.height());
   features.heightSet = webKitFeatures.has_height;
 
-  features.menuBarVisible = webKitFeatures.menu_bar_visible;
-  features.statusBarVisible = webKitFeatures.status_bar_visible;
-  features.toolBarVisible = webKitFeatures.tool_bar_visible;
-  features.scrollbarsVisible = webKitFeatures.scrollbars_visible;
+  features.isPopup = webKitFeatures.is_popup;
 }
 
 CefBrowserInfoManager* g_info_manager = nullptr;
@@ -83,20 +82,18 @@
     CefRefPtr<CefDictionaryValue> extra_info) {
   base::AutoLock lock_scope(browser_info_lock_);
 
-  auto frame_host = new_contents->GetMainFrame();
-  const int render_process_id = frame_host->GetProcess()->GetID();
-  const auto frame_id = CefFrameHostImpl::MakeFrameId(frame_host);
+  auto frame_host = new_contents->GetPrimaryMainFrame();
 
   scoped_refptr<CefBrowserInfo> browser_info =
       new CefBrowserInfo(++next_browser_id_, true, is_windowless, extra_info);
   browser_info_list_.push_back(browser_info);
 
   // Continue any pending NewBrowserInfo request.
-  auto it = pending_new_browser_info_map_.find(frame_id);
+  auto it = pending_new_browser_info_map_.find(frame_host->GetGlobalId());
   if (it != pending_new_browser_info_map_.end()) {
-    SendNewBrowserInfoResponse(render_process_id, browser_info,
-                               false /* is_guest_view */,
-                               it->second->reply_msg);
+    SendNewBrowserInfoResponse(browser_info, /*is_guest_view=*/false,
+                               std::move(it->second->callback),
+                               it->second->callback_runner);
     pending_new_browser_info_map_.erase(it);
   }
 
@@ -115,43 +112,30 @@
     bool* no_javascript_access) {
   CEF_REQUIRE_UIT();
 
-  bool is_guest_view = false;
-  CefRefPtr<CefBrowserHostImpl> browser =
-      extensions::GetOwnerBrowserForHost(opener, &is_guest_view);
-  DCHECK(browser.get());
-  if (!browser.get()) {
-    // Cancel the popup.
-    return false;
-  }
+  content::OpenURLParams params(target_url, referrer, disposition,
+                                ui::PAGE_TRANSITION_LINK,
+                                /*is_renderer_initiated=*/true);
+  params.user_gesture = user_gesture;
 
-  if (is_guest_view) {
-    content::OpenURLParams params(target_url, referrer, disposition,
-                                  ui::PAGE_TRANSITION_LINK, true);
-    params.user_gesture = user_gesture;
-
-    // Pass navigation to the owner browser.
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::Bind(base::IgnoreResult(&CefBrowserHostImpl::OpenURLFromTab),
-                   browser.get(), nullptr, params));
-
+  CefRefPtr<CefBrowserHostBase> browser;
+  if (!MaybeAllowNavigation(opener, params, browser) || !browser) {
     // Cancel the popup.
     return false;
   }
 
   CefRefPtr<CefClient> client = browser->GetClient();
   bool allow = true;
+  bool handled = false;
 
-  std::unique_ptr<CefWindowInfo> window_info(new CefWindowInfo);
+  CefWindowInfo window_info;
 
-#if defined(OS_WIN)
-  window_info->SetAsPopup(nullptr, CefString());
+#if BUILDFLAG(IS_WIN)
+  window_info.SetAsPopup(nullptr, CefString());
 #endif
 
   auto pending_popup = std::make_unique<CefBrowserInfoManager::PendingPopup>();
-  pending_popup->step = CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW;
-  pending_popup->opener_render_process_id = opener->GetProcess()->GetID();
-  pending_popup->opener_render_routing_id = opener->GetRoutingID();
+  pending_popup->step = PendingPopup::CAN_CREATE_WINDOW;
+  pending_popup->opener_global_id = opener->GetGlobalId();
   pending_popup->target_url = target_url;
   pending_popup->target_frame_name = frame_name;
 
@@ -159,6 +143,11 @@
   pending_popup->client = client;
   pending_popup->settings = browser->settings();
 
+  // With the Chrome runtime, we want to use default popup Browser creation
+  // for document picture-in-picture.
+  pending_popup->use_default_browser_creation =
+      disposition == WindowOpenDisposition::NEW_PICTURE_IN_PICTURE;
+
   if (client.get()) {
     CefRefPtr<CefLifeSpanHandler> handler = client->GetLifeSpanHandler();
     if (handler.get()) {
@@ -168,34 +157,44 @@
       CefPopupFeatures cef_features;
       TranslatePopupFeatures(features, cef_features);
 
-#if (defined(OS_WIN) || defined(OS_MACOSX))
       // Default to the size from the popup features.
-      if (cef_features.xSet)
-        window_info->x = cef_features.x;
-      if (cef_features.ySet)
-        window_info->y = cef_features.y;
-      if (cef_features.widthSet)
-        window_info->width = cef_features.width;
-      if (cef_features.heightSet)
-        window_info->height = cef_features.height;
-#endif
+      if (cef_features.xSet) {
+        window_info.bounds.x = cef_features.x;
+      }
+      if (cef_features.ySet) {
+        window_info.bounds.y = cef_features.y;
+      }
+      if (cef_features.widthSet) {
+        window_info.bounds.width = cef_features.width;
+      }
+      if (cef_features.heightSet) {
+        window_info.bounds.height = cef_features.height;
+      }
 
       allow = !handler->OnBeforePopup(
           browser.get(), opener_frame, pending_popup->target_url.spec(),
           pending_popup->target_frame_name,
           static_cast<cef_window_open_disposition_t>(disposition), user_gesture,
-          cef_features, *window_info, pending_popup->client,
+          cef_features, window_info, pending_popup->client,
           pending_popup->settings, pending_popup->extra_info,
           no_javascript_access);
+      handled = true;
     }
   }
 
   if (allow) {
-    CefBrowserHostImpl::CreateParams create_params;
+    CefBrowserCreateParams create_params;
+    create_params.MaybeSetWindowInfo(window_info);
 
-    if (!browser->IsViewsHosted())
-      create_params.window_info = std::move(window_info);
+    if (!handled) {
+      // Use default Browser creation if OnBeforePopup was unhandled.
+      // TODO(chrome): Expose a mechanism for the client to choose default
+      // creation.
+      pending_popup->use_default_browser_creation = true;
+    }
 
+    create_params.popup_with_views_hosted_opener = ShouldCreateViewsHostedPopup(
+        browser, pending_popup->use_default_browser_creation);
     create_params.settings = pending_popup->settings;
     create_params.client = pending_popup->client;
     create_params.extra_info = pending_popup->extra_info;
@@ -219,16 +218,14 @@
 
 void CefBrowserInfoManager::GetCustomWebContentsView(
     const GURL& target_url,
-    int opener_render_process_id,
-    int opener_render_routing_id,
+    const content::GlobalRenderFrameHostId& opener_global_id,
     content::WebContentsView** view,
     content::RenderViewHostDelegateView** delegate_view) {
   CEF_REQUIRE_UIT();
+  REQUIRE_ALLOY_RUNTIME();
 
-  std::unique_ptr<CefBrowserInfoManager::PendingPopup> pending_popup =
-      PopPendingPopup(CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW,
-                      opener_render_process_id, opener_render_routing_id,
-                      target_url);
+  auto pending_popup = PopPendingPopup(PendingPopup::CAN_CREATE_WINDOW,
+                                       opener_global_id, target_url);
   DCHECK(pending_popup.get());
   DCHECK(pending_popup->platform_delegate.get());
 
@@ -237,25 +234,27 @@
                                                                delegate_view);
   }
 
-  pending_popup->step =
-      CefBrowserInfoManager::PendingPopup::GET_CUSTOM_WEB_CONTENTS_VIEW;
+  pending_popup->step = PendingPopup::GET_CUSTOM_WEB_CONTENTS_VIEW;
   PushPendingPopup(std::move(pending_popup));
 }
 
 void CefBrowserInfoManager::WebContentsCreated(
     const GURL& target_url,
-    int opener_render_process_id,
-    int opener_render_routing_id,
+    const content::GlobalRenderFrameHostId& opener_global_id,
     CefBrowserSettings& settings,
     CefRefPtr<CefClient>& client,
     std::unique_ptr<CefBrowserPlatformDelegate>& platform_delegate,
-    CefRefPtr<CefDictionaryValue>& extra_info) {
+    CefRefPtr<CefDictionaryValue>& extra_info,
+    content::WebContents* new_contents) {
   CEF_REQUIRE_UIT();
 
-  std::unique_ptr<CefBrowserInfoManager::PendingPopup> pending_popup =
-      PopPendingPopup(
-          CefBrowserInfoManager::PendingPopup::GET_CUSTOM_WEB_CONTENTS_VIEW,
-          opener_render_process_id, opener_render_routing_id, target_url);
+  // GET_CUSTOM_WEB_CONTENTS_VIEW is only used with the alloy runtime.
+  const auto previous_step = cef::IsAlloyRuntimeEnabled()
+                                 ? PendingPopup::GET_CUSTOM_WEB_CONTENTS_VIEW
+                                 : PendingPopup::CAN_CREATE_WINDOW;
+
+  auto pending_popup =
+      PopPendingPopup(previous_step, opener_global_id, target_url);
   DCHECK(pending_popup.get());
   DCHECK(pending_popup->platform_delegate.get());
 
@@ -263,55 +262,79 @@
   client = pending_popup->client;
   platform_delegate = std::move(pending_popup->platform_delegate);
   extra_info = pending_popup->extra_info;
+
+  // AddWebContents (the next step) is only used with the Chrome runtime.
+  if (cef::IsChromeRuntimeEnabled()) {
+    pending_popup->step = PendingPopup::WEB_CONTENTS_CREATED;
+    pending_popup->new_contents = new_contents;
+    PushPendingPopup(std::move(pending_popup));
+  }
 }
 
-void CefBrowserInfoManager::OnGetNewBrowserInfo(int render_process_id,
-                                                int render_routing_id,
-                                                IPC::Message* reply_msg) {
-  DCHECK_NE(render_process_id, content::ChildProcessHost::kInvalidUniqueID);
-  DCHECK_GT(render_routing_id, 0);
-  DCHECK(reply_msg);
+bool CefBrowserInfoManager::AddWebContents(content::WebContents* new_contents) {
+  CEF_REQUIRE_UIT();
+  DCHECK(cef::IsChromeRuntimeEnabled());
+
+  // Pending popup information may be missing in cases where
+  // chrome::AddWebContents is called directly from the Chrome UI (profile
+  // settings, etc).
+  auto pending_popup =
+      PopPendingPopup(PendingPopup::WEB_CONTENTS_CREATED, new_contents);
+  if (pending_popup) {
+    return !pending_popup->use_default_browser_creation;
+  }
+
+  // Proceed with default handling.
+  return false;
+}
+
+void CefBrowserInfoManager::OnGetNewBrowserInfo(
+    const content::GlobalRenderFrameHostId& global_id,
+    cef::mojom::BrowserManager::GetNewBrowserInfoCallback callback) {
+  DCHECK(frame_util::IsValidGlobalId(global_id));
+  DCHECK(callback);
+
+  auto callback_runner = base::SequencedTaskRunner::GetCurrentDefault();
 
   base::AutoLock lock_scope(browser_info_lock_);
 
   bool is_guest_view = false;
 
   scoped_refptr<CefBrowserInfo> browser_info =
-      GetBrowserInfo(render_process_id, render_routing_id, &is_guest_view);
+      GetBrowserInfoInternal(global_id, &is_guest_view);
 
-  if (browser_info.get()) {
+  if (browser_info) {
     // Send the response immediately.
-    SendNewBrowserInfoResponse(render_process_id, browser_info, is_guest_view,
-                               reply_msg);
+    SendNewBrowserInfoResponse(browser_info, is_guest_view, std::move(callback),
+                               callback_runner);
     return;
   }
 
-  const auto frame_id =
-      CefFrameHostImpl::MakeFrameId(render_process_id, render_routing_id);
-
   // Verify that no request for the same route is currently queued.
-  DCHECK(pending_new_browser_info_map_.find(frame_id) ==
+  DCHECK(pending_new_browser_info_map_.find(global_id) ==
          pending_new_browser_info_map_.end());
 
   const int timeout_id = ++next_timeout_id_;
 
   // Queue the request.
   std::unique_ptr<PendingNewBrowserInfo> pending(new PendingNewBrowserInfo());
-  pending->render_process_id = render_process_id;
-  pending->render_routing_id = render_routing_id;
+  pending->global_id = global_id;
   pending->timeout_id = timeout_id;
-  pending->reply_msg = reply_msg;
+  pending->callback = std::move(callback);
+  pending->callback_runner = callback_runner;
   pending_new_browser_info_map_.insert(
-      std::make_pair(frame_id, std::move(pending)));
+      std::make_pair(global_id, std::move(pending)));
 
   // Register a timeout for the pending response so that the renderer process
-  // doesn't hang forever.
+  // doesn't hang forever. With the Chrome runtime, timeouts may occur in cases
+  // where chrome::AddWebContents or WebContents::Create are called directly
+  // from the Chrome UI (profile settings, etc).
   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kDisableNewBrowserInfoTimeout)) {
     CEF_POST_DELAYED_TASK(
         CEF_UIT,
         base::BindOnce(&CefBrowserInfoManager::TimeoutNewBrowserInfoResponse,
-                       frame_id, timeout_id),
+                       global_id, timeout_id),
         kNewBrowserInfoResponseTimeoutMs);
   }
 }
@@ -328,7 +351,7 @@
     }
   }
 
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserInfoManager::DestroyAllBrowsers() {
@@ -343,7 +366,7 @@
   if (!list.empty()) {
     BrowserInfoList::iterator it = list.begin();
     for (; it != list.end(); ++it) {
-      CefRefPtr<CefBrowserHostImpl> browser = (*it)->browser();
+      CefRefPtr<CefBrowserHostBase> browser = (*it)->browser();
       DCHECK(browser.get());
       if (browser.get()) {
         // DestroyBrowser will call RemoveBrowserInfo.
@@ -361,37 +384,46 @@
 #endif
 }
 
-scoped_refptr<CefBrowserInfo>
-CefBrowserInfoManager::GetBrowserInfoForFrameRoute(int render_process_id,
-                                                   int render_routing_id,
-                                                   bool* is_guest_view) {
+scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::GetBrowserInfo(
+    const content::GlobalRenderFrameHostId& global_id,
+    bool* is_guest_view) {
   base::AutoLock lock_scope(browser_info_lock_);
-  return GetBrowserInfo(render_process_id, render_routing_id, is_guest_view);
+  return GetBrowserInfoInternal(global_id, is_guest_view);
 }
 
-scoped_refptr<CefBrowserInfo>
-CefBrowserInfoManager::GetBrowserInfoForFrameTreeNode(int frame_tree_node_id,
-                                                      bool* is_guest_view) {
-  if (is_guest_view)
-    *is_guest_view = false;
+bool CefBrowserInfoManager::MaybeAllowNavigation(
+    content::RenderFrameHost* opener,
+    const content::OpenURLParams& params,
+    CefRefPtr<CefBrowserHostBase>& browser_out) const {
+  CEF_REQUIRE_UIT();
 
-  if (frame_tree_node_id < 0)
-    return nullptr;
-
-  base::AutoLock lock_scope(browser_info_lock_);
-
-  for (const auto& browser_info : browser_info_list_) {
-    bool is_guest_view_tmp;
-    auto frame = browser_info->GetFrameForFrameTreeNode(frame_tree_node_id,
-                                                        &is_guest_view_tmp);
-    if (frame || is_guest_view_tmp) {
-      if (is_guest_view)
-        *is_guest_view = is_guest_view_tmp;
-      return browser_info;
-    }
+  bool is_guest_view = false;
+  auto browser = extensions::GetOwnerBrowserForHost(opener, &is_guest_view);
+  if (!browser) {
+    // Print preview uses a modal dialog where we don't own the WebContents.
+    // Allow that navigation to proceed.
+    return true;
   }
 
-  return nullptr;
+  if (!browser->MaybeAllowNavigation(opener, is_guest_view, params)) {
+    return false;
+  }
+
+  browser_out = browser;
+  return true;
+}
+
+// static
+bool CefBrowserInfoManager::ShouldCreateViewsHostedPopup(
+    CefRefPtr<CefBrowserHostBase> opener,
+    bool use_default_browser_creation) {
+  // In most cases, Views-hosted browsers should create Views-hosted popups
+  // and native browsers should use default popup handling. With the Chrome
+  // runtime, we should additionally use default handling (a) when using an
+  // external parent and (b) when using default Browser creation.
+  return opener->HasView() &&
+         !opener->platform_delegate()->HasExternalParent() &&
+         !use_default_browser_creation;
 }
 
 CefBrowserInfoManager::BrowserInfoList
@@ -406,6 +438,8 @@
     content::RenderProcessHost* host) {
   CEF_REQUIRE_UIT();
 
+  host->RemoveObserver(this);
+
   const int render_process_id = host->GetID();
   DCHECK_GT(render_process_id, 0);
 
@@ -416,11 +450,13 @@
     PendingNewBrowserInfoMap::iterator it =
         pending_new_browser_info_map_.begin();
     while (it != pending_new_browser_info_map_.end()) {
-      auto info = it->second.get();
-      if (info->render_process_id == render_process_id)
+      const auto& info = it->second;
+      if (info->global_id.child_id == render_process_id) {
+        CancelNewBrowserInfoResponse(info.get());
         it = pending_new_browser_info_map_.erase(it);
-      else
+      } else {
         ++it;
+      }
     }
   }
 
@@ -429,7 +465,7 @@
     PendingPopupList::iterator it = pending_popup_list_.begin();
     while (it != pending_popup_list_.end()) {
       PendingPopup* popup = it->get();
-      if (popup->opener_render_process_id == render_process_id) {
+      if (popup->opener_global_id.child_id == render_process_id) {
         it = pending_popup_list_.erase(it);
       } else {
         ++it;
@@ -445,20 +481,19 @@
 }
 
 std::unique_ptr<CefBrowserInfoManager::PendingPopup>
-CefBrowserInfoManager::PopPendingPopup(PendingPopup::Step step,
-                                       int opener_render_process_id,
-                                       int opener_render_routing_id,
-                                       const GURL& target_url) {
+CefBrowserInfoManager::PopPendingPopup(
+    PendingPopup::Step previous_step,
+    const content::GlobalRenderFrameHostId& opener_global_id,
+    const GURL& target_url) {
   CEF_REQUIRE_UIT();
-  DCHECK_GT(opener_render_process_id, 0);
-  DCHECK_GT(opener_render_routing_id, 0);
+  DCHECK(frame_util::IsValidGlobalId(opener_global_id));
+  DCHECK_LE(previous_step, PendingPopup::GET_CUSTOM_WEB_CONTENTS_VIEW);
 
   PendingPopupList::iterator it = pending_popup_list_.begin();
   for (; it != pending_popup_list_.end(); ++it) {
     PendingPopup* popup = it->get();
-    if (popup->step == step &&
-        popup->opener_render_process_id == opener_render_process_id &&
-        popup->opener_render_routing_id == opener_render_routing_id &&
+    if (popup->step == previous_step &&
+        popup->opener_global_id == opener_global_id &&
         popup->target_url == target_url) {
       // Transfer ownership of the pointer.
       it->release();
@@ -470,25 +505,47 @@
   return nullptr;
 }
 
-scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::GetBrowserInfo(
-    int render_process_id,
-    int render_routing_id,
+std::unique_ptr<CefBrowserInfoManager::PendingPopup>
+CefBrowserInfoManager::PopPendingPopup(PendingPopup::Step previous_step,
+                                       content::WebContents* new_contents) {
+  CEF_REQUIRE_UIT();
+  DCHECK_GE(previous_step, PendingPopup::WEB_CONTENTS_CREATED);
+
+  PendingPopupList::iterator it = pending_popup_list_.begin();
+  for (; it != pending_popup_list_.end(); ++it) {
+    PendingPopup* popup = it->get();
+    if (popup->step == previous_step && popup->new_contents == new_contents) {
+      // Transfer ownership of the pointer.
+      it->release();
+      pending_popup_list_.erase(it);
+      return base::WrapUnique(popup);
+    }
+  }
+
+  return nullptr;
+}
+
+scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::GetBrowserInfoInternal(
+    const content::GlobalRenderFrameHostId& global_id,
     bool* is_guest_view) {
   browser_info_lock_.AssertAcquired();
 
-  if (is_guest_view)
+  if (is_guest_view) {
     *is_guest_view = false;
+  }
 
-  if (render_process_id < 0 || render_routing_id < 0)
+  if (!frame_util::IsValidGlobalId(global_id)) {
     return nullptr;
+  }
 
   for (const auto& browser_info : browser_info_list_) {
     bool is_guest_view_tmp;
-    auto frame = browser_info->GetFrameForRoute(
-        render_process_id, render_routing_id, &is_guest_view_tmp);
+    auto frame =
+        browser_info->GetFrameForGlobalId(global_id, &is_guest_view_tmp);
     if (frame || is_guest_view_tmp) {
-      if (is_guest_view)
+      if (is_guest_view) {
         *is_guest_view = is_guest_view_tmp;
+      }
       return browser_info;
     }
   }
@@ -498,72 +555,81 @@
 
 // static
 void CefBrowserInfoManager::SendNewBrowserInfoResponse(
-    int render_process_id,
     scoped_refptr<CefBrowserInfo> browser_info,
     bool is_guest_view,
-    IPC::Message* reply_msg) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::Bind(&CefBrowserInfoManager::SendNewBrowserInfoResponse,
-                   render_process_id, browser_info, is_guest_view, reply_msg));
+    cef::mojom::BrowserManager::GetNewBrowserInfoCallback callback,
+    scoped_refptr<base::SequencedTaskRunner> callback_runner) {
+  if (!callback_runner->RunsTasksInCurrentSequence()) {
+    callback_runner->PostTask(
+        FROM_HERE,
+        base::BindOnce(&CefBrowserInfoManager::SendNewBrowserInfoResponse,
+                       browser_info, is_guest_view, std::move(callback),
+                       callback_runner));
     return;
   }
 
-  content::RenderProcessHost* host =
-      content::RenderProcessHost::FromID(render_process_id);
-  if (!host) {
-    delete reply_msg;
-    return;
-  }
-
-  CefProcessHostMsg_GetNewBrowserInfo_Params params;
-  params.is_guest_view = is_guest_view;
+  auto params = cef::mojom::NewBrowserInfo::New();
+  params->is_guest_view = is_guest_view;
 
   if (browser_info) {
-    params.browser_id = browser_info->browser_id();
-    params.is_windowless = browser_info->is_windowless();
-    params.is_popup = browser_info->is_popup();
+    params->browser_id = browser_info->browser_id();
+    params->is_windowless = browser_info->is_windowless();
+    params->is_popup = browser_info->is_popup();
 
     auto extra_info = browser_info->extra_info();
     if (extra_info) {
       auto extra_info_impl =
           static_cast<CefDictionaryValueImpl*>(extra_info.get());
       auto extra_info_value = extra_info_impl->CopyValue();
-      extra_info_value->Swap(&params.extra_info);
+      params->extra_info = std::move(extra_info_value.GetDict());
     }
   } else {
     // The new browser info response has timed out.
-    params.browser_id = -1;
+    params->browser_id = -1;
   }
 
-  CefProcessHostMsg_GetNewBrowserInfo::WriteReplyParams(reply_msg, params);
-  host->Send(reply_msg);
+  std::move(callback).Run(std::move(params));
 }
 
 // static
-void CefBrowserInfoManager::TimeoutNewBrowserInfoResponse(int64_t frame_id,
-                                                          int timeout_id) {
-  if (!g_info_manager)
+void CefBrowserInfoManager::CancelNewBrowserInfoResponse(
+    PendingNewBrowserInfo* pending_info) {
+  SendNewBrowserInfoResponse(/*browser_info=*/nullptr, /*is_guest_view=*/false,
+                             std::move(pending_info->callback),
+                             pending_info->callback_runner);
+}
+
+// static
+void CefBrowserInfoManager::TimeoutNewBrowserInfoResponse(
+    const content::GlobalRenderFrameHostId& global_id,
+    int timeout_id) {
+  CEF_REQUIRE_UIT();
+  if (!g_info_manager) {
     return;
+  }
 
   base::AutoLock lock_scope(g_info_manager->browser_info_lock_);
 
   // Continue the NewBrowserInfo request if it's still pending.
-  auto it = g_info_manager->pending_new_browser_info_map_.find(frame_id);
+  auto it = g_info_manager->pending_new_browser_info_map_.find(global_id);
   if (it != g_info_manager->pending_new_browser_info_map_.end()) {
     const auto& pending_info = it->second;
     // Don't accidentally timeout a new request for the same frame.
-    if (pending_info->timeout_id != timeout_id)
+    if (pending_info->timeout_id != timeout_id) {
       return;
+    }
 
-    LOG(ERROR) << "Timeout of new browser info response for frame process id "
-               << pending_info->render_process_id << " and routing id "
-               << pending_info->render_routing_id;
+#if DCHECK_IS_ON()
+    // This method should never be called for a PDF renderer.
+    content::RenderProcessHost* process =
+        content::RenderProcessHost::FromID(global_id.child_id);
+    DCHECK(!process || !process->IsPdf());
+#endif
 
-    SendNewBrowserInfoResponse(pending_info->render_process_id, nullptr,
-                               false /* is_guest_view */,
-                               pending_info->reply_msg);
+    LOG(ERROR) << "Timeout of new browser info response for frame "
+               << frame_util::GetFrameDebugString(global_id);
+
+    CancelNewBrowserInfoResponse(pending_info.get());
     g_info_manager->pending_new_browser_info_map_.erase(it);
   }
 }
diff --git a/src/libcef/browser/browser_info_manager.h b/src/libcef/browser/browser_info_manager.h
index 3bdc1c7..1ccc4de 100644
--- a/src/libcef/browser/browser_info_manager.h
+++ b/src/libcef/browser/browser_info_manager.h
@@ -8,6 +8,7 @@
 
 #include "include/cef_client.h"
 
+#include <list>
 #include <map>
 #include <memory>
 #include <vector>
@@ -15,6 +16,9 @@
 #include "libcef/browser/browser_info.h"
 
 #include "base/synchronization/lock.h"
+#include "base/task/sequenced_task_runner.h"
+#include "cef/libcef/common/mojom/cef.mojom.h"
+#include "content/public/browser/global_routing_id.h"
 #include "content/public/browser/render_process_host_observer.h"
 #include "third_party/blink/public/mojom/window_features/window_features.mojom.h"
 #include "ui/base/window_open_disposition.h"
@@ -25,6 +29,7 @@
 }
 
 namespace content {
+struct OpenURLParams;
 struct Referrer;
 class RenderFrameHost;
 class RenderViewHostDelegateView;
@@ -32,29 +37,30 @@
 class WebContentsView;
 }  // namespace content
 
-namespace IPC {
-class Message;
-}
-
+class CefBrowserHostBase;
 class CefBrowserPlatformDelegate;
 
 // Singleton object for managing BrowserInfo instances.
 class CefBrowserInfoManager : public content::RenderProcessHostObserver {
  public:
   CefBrowserInfoManager();
+
+  CefBrowserInfoManager(const CefBrowserInfoManager&) = delete;
+  CefBrowserInfoManager& operator=(const CefBrowserInfoManager&) = delete;
+
   ~CefBrowserInfoManager() override;
 
   // Returns this singleton instance of this class.
   static CefBrowserInfoManager* GetInstance();
 
-  // Called from CefBrowserHostImpl::Create when a new browser is being created
+  // Called immediately before a new CefBrowserHost implementation is created
   // directly. In this case |is_popup| will be true only for DevTools browsers.
   scoped_refptr<CefBrowserInfo> CreateBrowserInfo(
       bool is_popup,
       bool is_windowless,
       CefRefPtr<CefDictionaryValue> extra_info);
 
-  // Called from CefBrowserHostImpl::WebContentsCreated when a new browser is
+  // Called from WebContentsDelegate::WebContentsCreated when a new browser is
   // being created for a traditional popup (e.g. window.open() or targeted
   // link). If any OnGetNewBrowserInfo requests are pending for the popup the
   // response will be sent when this method is called.
@@ -63,7 +69,7 @@
       bool is_windowless,
       CefRefPtr<CefDictionaryValue> extra_info);
 
-  // Called from CefContentBrowserClient::CanCreateWindow. See comments on
+  // Called from ContentBrowserClient::CanCreateWindow. See comments on
   // PendingPopup for more information.
   bool CanCreateWindow(content::RenderFrameHost* opener,
                        const GURL& target_url,
@@ -75,85 +81,90 @@
                        bool opener_suppressed,
                        bool* no_javascript_access);
 
-  // Called from CefBrowserHostImpl::GetCustomWebContentsView. See comments on
-  // PendingPopup for more information.
+  // Called from WebContentsDelegate::GetCustomWebContentsView (alloy runtime
+  // only). See comments on PendingPopup for more information.
   void GetCustomWebContentsView(
       const GURL& target_url,
-      int opener_render_process_id,
-      int opener_render_routing_id,
+      const content::GlobalRenderFrameHostId& opener_global_id,
       content::WebContentsView** view,
       content::RenderViewHostDelegateView** delegate_view);
 
-  // Called from CefBrowserHostImpl::WebContentsCreated. See comments on
+  // Called from WebContentsDelegate::WebContentsCreated. See comments on
   // PendingPopup for more information.
   void WebContentsCreated(
       const GURL& target_url,
-      int opener_render_process_id,
-      int opener_render_routing_id,
+      const content::GlobalRenderFrameHostId& opener_global_id,
       CefBrowserSettings& settings,
       CefRefPtr<CefClient>& client,
       std::unique_ptr<CefBrowserPlatformDelegate>& platform_delegate,
-      CefRefPtr<CefDictionaryValue>& extra_info);
+      CefRefPtr<CefDictionaryValue>& extra_info,
+      content::WebContents* new_contents);
 
-  // Called from CefBrowserMessageFilter::OnGetNewBrowserInfo for delivering
+  // Called from ChromeBrowserDelegate::AddWebContents. See comments on
+  // PendingPopup for more information. Returns true for custom handling.
+  bool AddWebContents(content::WebContents* source_contents);
+
+  // Called from CefBrowserManager::GetNewBrowserInfo for delivering
   // browser info to the renderer process. If the browser info already exists
   // the response will be sent immediately. Otherwise, the response will be sent
   // when CreatePopupBrowserInfo creates the browser info. The info will already
   // exist for explicitly created browsers and guest views. It may sometimes
   // already exist for traditional popup browsers depending on timing. See
   // comments on PendingPopup for more information.
-  void OnGetNewBrowserInfo(int render_process_id,
-                           int render_routing_id,
-                           IPC::Message* reply_msg);
+  void OnGetNewBrowserInfo(
+      const content::GlobalRenderFrameHostId& global_id,
+      cef::mojom::BrowserManager::GetNewBrowserInfoCallback callback);
 
-  // Called from CefBrowserHostImpl::DestroyBrowser() when a browser is
+  // Called from CefBrowserHostBase::DestroyBrowser() when a browser is
   // destroyed.
   void RemoveBrowserInfo(scoped_refptr<CefBrowserInfo> browser_info);
 
   // Called from CefContext::FinishShutdownOnUIThread() to destroy all browsers.
   void DestroyAllBrowsers();
 
-  // Returns the CefBrowserInfo matching the specified IDs or nullptr if no
+  // Returns the CefBrowserInfo matching the specified ID or nullptr if no
   // match is found. It is allowed to add new callers of this method but
-  // consider using CefBrowserHostImpl::GetBrowserForFrameRoute() or
-  // extensions::GetOwnerBrowserForFrameRoute() instead. If |is_guest_view| is
-  // non-nullptr it will be set to true if the IDs match a guest view associated
-  // with the returned browser info instead of the browser itself.
-  scoped_refptr<CefBrowserInfo> GetBrowserInfoForFrameRoute(
-      int render_process_id,
-      int render_routing_id,
-      bool* is_guest_view = nullptr);
-
-  // Returns the CefBrowserInfo matching the specified ID or nullptr if no match
-  // is found. It is allowed to add new callers of this method but consider
-  // using CefBrowserHostImpl::GetBrowserForFrameTreeNode() instead. If
-  // |is_guest_view| is non-nullptr it will be set to true if the IDs match a
-  // guest view associated with the returned browser info instead of the browser
-  // itself.
-  scoped_refptr<CefBrowserInfo> GetBrowserInfoForFrameTreeNode(
-      int frame_tree_node_id,
+  // consider using CefBrowserHostBase::GetBrowserForGlobalId() or
+  // extensions::GetOwnerBrowserForGlobalId() instead. If |is_guest_view| is
+  // non-nullptr it will be set to true if the ID matches a guest view
+  // associated with the returned browser info instead of the browser itself.
+  scoped_refptr<CefBrowserInfo> GetBrowserInfo(
+      const content::GlobalRenderFrameHostId& global_id,
       bool* is_guest_view = nullptr);
 
   // Returns all existing CefBrowserInfo objects.
-  typedef std::list<scoped_refptr<CefBrowserInfo>> BrowserInfoList;
+  using BrowserInfoList = std::list<scoped_refptr<CefBrowserInfo>>;
   BrowserInfoList GetBrowserInfoList();
 
+  // Returns true if the navigation should be allowed to proceed, or false if
+  // the navigation will instead be sent via OpenURLFromTab. If allowed,
+  // |browser| will be set to the target browser if any.
+  bool MaybeAllowNavigation(content::RenderFrameHost* opener,
+                            const content::OpenURLParams& params,
+                            CefRefPtr<CefBrowserHostBase>& browser) const;
+
+  static bool ShouldCreateViewsHostedPopup(CefRefPtr<CefBrowserHostBase> opener,
+                                           bool use_default_browser_creation);
+
  private:
   // RenderProcessHostObserver methods:
   void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;
 
   // Store state information about pending popups. Call order is:
-  // - CefContentBrowserClient::CanCreateWindow (UIT)
+  // - CanCreateWindow (UIT):
   //   Provides an opportunity to cancel the popup (calls OnBeforePopup) and
   //   creates the new platform delegate for the popup. If the popup owner is
   //   an extension guest view then the popup is canceled and
-  //   CefBrowserHostImpl::OpenURLFromTab is called.
+  //   WebContentsDelegate::OpenURLFromTab is called via the
+  //   CefBrowserHostBase::MaybeAllowNavigation implementation.
   // And then the following calls may occur at the same time:
-  // - CefBrowserHostImpl::GetCustomWebContentsView (UIT)
+  // - GetCustomWebContentsView (UIT) (alloy runtime only):
   //   Creates the OSR views for windowless popups.
-  // - CefBrowserHostImpl::WebContentsCreated (UIT)
-  //   Creates the CefBrowserHostImpl representation for the popup.
-  // - CefBrowserMessageFilter::OnGetNewBrowserInfo (IOT)
+  // - WebContentsCreated (UIT):
+  //   Creates the CefBrowserHost representation for the popup.
+  // - AddWebContents (UIT) (chrome runtime only):
+  //   Creates the Browser or tab representation for the popup.
+  // - CefBrowserManager::GetNewBrowserInfo (IOT)
   //   Passes information about the popup to the renderer process.
   struct PendingPopup {
     // Track the last method that modified this PendingPopup instance. There may
@@ -162,13 +173,13 @@
     enum Step {
       CAN_CREATE_WINDOW,
       GET_CUSTOM_WEB_CONTENTS_VIEW,
+      WEB_CONTENTS_CREATED,
     } step;
 
     // Initial state from ViewHostMsg_CreateWindow.
     // |target_url| will be empty if a popup is created via window.open() and
     // never navigated. For example: javascript:window.open();
-    int opener_render_process_id;
-    int opener_render_routing_id;
+    content::GlobalRenderFrameHostId opener_global_id;
     GURL target_url;
     std::string target_frame_name;
 
@@ -179,39 +190,57 @@
 
     // Platform delegate specific to the new popup.
     std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate;
+
+    // True if default Browser or tab creation should proceed from
+    // AddWebContents (chrome runtime only).
+    bool use_default_browser_creation = false;
+
+    // The newly created WebContents (set in WebContentsCreated).
+    content::WebContents* new_contents = nullptr;
   };
 
   // Manage pending popups. Only called on the UI thread.
   void PushPendingPopup(std::unique_ptr<PendingPopup> popup);
-  std::unique_ptr<PendingPopup> PopPendingPopup(PendingPopup::Step step,
-                                                int opener_process_id,
-                                                int opener_routing_id,
-                                                const GURL& target_url);
 
-  // Retrieves the BrowserInfo matching the specified IDs. If both sets are
-  // valid then this method makes sure both sets have been registered.
-  scoped_refptr<CefBrowserInfo> GetBrowserInfo(int render_process_id,
-                                               int render_routing_id,
-                                               bool* is_guest_view);
+  // Used after CanCreateWindow is called.
+  std::unique_ptr<PendingPopup> PopPendingPopup(
+      PendingPopup::Step previous_step,
+      const content::GlobalRenderFrameHostId& opener_global_id,
+      const GURL& target_url);
+
+  // Used after WebContentsCreated is called.
+  std::unique_ptr<PendingPopup> PopPendingPopup(
+      PendingPopup::Step previous_step,
+      content::WebContents* new_contents);
+
+  // Retrieves the BrowserInfo matching the specified ID.
+  scoped_refptr<CefBrowserInfo> GetBrowserInfoInternal(
+      const content::GlobalRenderFrameHostId& global_id,
+      bool* is_guest_view);
 
   // Send the response for a pending OnGetNewBrowserInfo request.
   static void SendNewBrowserInfoResponse(
-      int render_process_id,
       scoped_refptr<CefBrowserInfo> browser_info,
       bool is_guest_view,
-      IPC::Message* reply_msg);
-
-  // Time out a response if it's still pending.
-  static void TimeoutNewBrowserInfoResponse(int64_t frame_id, int timeout_id);
+      cef::mojom::BrowserManager::GetNewBrowserInfoCallback callback,
+      scoped_refptr<base::SequencedTaskRunner> callback_runner);
 
   // Pending request for OnGetNewBrowserInfo.
   struct PendingNewBrowserInfo {
-    int render_process_id;
-    int render_routing_id;
+    content::GlobalRenderFrameHostId global_id;
     int timeout_id;
-    IPC::Message* reply_msg;
+    cef::mojom::BrowserManager::GetNewBrowserInfoCallback callback;
+    scoped_refptr<base::SequencedTaskRunner> callback_runner;
   };
 
+  // Cancel a response that is still pending.
+  static void CancelNewBrowserInfoResponse(PendingNewBrowserInfo* pending_info);
+
+  // Time out a response if it's still pending.
+  static void TimeoutNewBrowserInfoResponse(
+      const content::GlobalRenderFrameHostId& global_id,
+      int timeout_id);
+
   mutable base::Lock browser_info_lock_;
 
   // Access to the below members must be protected by |browser_info_lock_|.
@@ -219,9 +248,12 @@
   BrowserInfoList browser_info_list_;
   int next_browser_id_ = 0;
 
-  // Map of frame ID to info.
+  // Map of global ID to info. These IDs are guaranteed to uniquely
+  // identify a RFH for its complete lifespan. See documentation on
+  // RenderFrameHost::GetFrameTreeNodeId() for background.
   using PendingNewBrowserInfoMap =
-      std::map<int64_t, std::unique_ptr<PendingNewBrowserInfo>>;
+      std::map<content::GlobalRenderFrameHostId,
+               std::unique_ptr<PendingNewBrowserInfo>>;
   PendingNewBrowserInfoMap pending_new_browser_info_map_;
 
   // Only accessed on the UI thread.
@@ -229,8 +261,6 @@
   PendingPopupList pending_popup_list_;
 
   int next_timeout_id_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(CefBrowserInfoManager);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_BROWSER_INFO_H_
diff --git a/src/libcef/browser/browser_main.cc b/src/libcef/browser/browser_main.cc
deleted file mode 100644
index b7567c3..0000000
--- a/src/libcef/browser/browser_main.cc
+++ /dev/null
@@ -1,238 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/browser_main.h"
-
-#include <stdint.h>
-
-#include <string>
-
-#include "libcef/browser/browser_context.h"
-#include "libcef/browser/browser_context_keyed_service_factories.h"
-#include "libcef/browser/content_browser_client.h"
-#include "libcef/browser/context.h"
-#include "libcef/browser/devtools/devtools_manager_delegate.h"
-#include "libcef/browser/extensions/extension_system_factory.h"
-#include "libcef/browser/extensions/extensions_browser_client.h"
-#include "libcef/browser/net/chrome_scheme_handler.h"
-#include "libcef/browser/printing/constrained_window_views_client.h"
-#include "libcef/browser/printing/printing_message_filter.h"
-#include "libcef/browser/thread_util.h"
-#include "libcef/common/extensions/extensions_client.h"
-#include "libcef/common/extensions/extensions_util.h"
-#include "libcef/common/net/net_resource_provider.h"
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/task/post_task.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/net/system_network_context_manager.h"
-#include "chrome/browser/plugins/plugin_finder.h"
-#include "components/constrained_window/constrained_window_views.h"
-#include "content/public/browser/gpu_data_manager.h"
-#include "content/public/browser/network_service_instance.h"
-#include "extensions/browser/extension_system.h"
-#include "extensions/common/constants.h"
-#include "net/base/net_module.h"
-#include "services/service_manager/embedder/result_codes.h"
-#include "ui/base/resource/resource_bundle.h"
-
-#if defined(USE_AURA) && defined(USE_X11)
-#include "ui/events/devices/x11/touch_factory_x11.h"
-#endif
-
-#if defined(USE_AURA)
-#include "ui/aura/env.h"
-#include "ui/display/screen.h"
-#include "ui/views/widget/desktop_aura/desktop_screen.h"
-#include "ui/wm/core/wm_state.h"
-
-#if defined(OS_WIN)
-#include "chrome/browser/chrome_browser_main_win.h"
-#include "chrome/browser/win/parental_controls.h"
-#include "components/os_crypt/os_crypt.h"
-#include "ui/base/cursor/cursor_loader_win.h"
-#endif
-#endif  // defined(USE_AURA)
-
-#if defined(TOOLKIT_VIEWS)
-#if defined(OS_MACOSX)
-#include "chrome/browser/ui/views/chrome_layout_provider.h"
-#include "chrome/browser/ui/views/chrome_views_delegate.h"
-#else
-#include "ui/views/test/desktop_test_views_delegate.h"
-#endif
-#endif  // defined(TOOLKIT_VIEWS)
-
-#if defined(USE_AURA) && defined(OS_LINUX)
-#include "ui/base/ime/init/input_method_initializer.h"
-#endif
-
-#if defined(OS_LINUX)
-#include "libcef/browser/printing/print_dialog_linux.h"
-#endif
-
-CefBrowserMainParts::CefBrowserMainParts(
-    const content::MainFunctionParams& parameters)
-    : BrowserMainParts(), devtools_delegate_(nullptr) {}
-
-CefBrowserMainParts::~CefBrowserMainParts() {
-  constrained_window::SetConstrainedWindowViewsClient(nullptr);
-}
-
-int CefBrowserMainParts::PreEarlyInitialization() {
-#if defined(USE_AURA) && defined(OS_LINUX)
-  // TODO(linux): Consider using a real input method or
-  // views::LinuxUI::SetInstance.
-  ui::InitializeInputMethodForTesting();
-#endif
-
-  return service_manager::RESULT_CODE_NORMAL_EXIT;
-}
-
-void CefBrowserMainParts::ToolkitInitialized() {
-  SetConstrainedWindowViewsClient(CreateCefConstrainedWindowViewsClient());
-#if defined(USE_AURA)
-  CHECK(aura::Env::GetInstance());
-
-  wm_state_.reset(new wm::WMState);
-
-#if defined(OS_WIN)
-  ui::CursorLoaderWin::SetCursorResourceModule(
-      CefContentBrowserClient::Get()->GetResourceDllName());
-#endif
-#endif  // defined(USE_AURA)
-
-#if defined(TOOLKIT_VIEWS)
-#if defined(OS_MACOSX)
-  views_delegate_ = std::make_unique<ChromeViewsDelegate>();
-  layout_provider_ = ChromeLayoutProvider::CreateLayoutProvider();
-#else
-  views_delegate_ = std::make_unique<views::DesktopTestViewsDelegate>();
-#endif
-#endif  // defined(TOOLKIT_VIEWS)
-}
-
-void CefBrowserMainParts::PreMainMessageLoopStart() {
-#if defined(USE_AURA) && defined(USE_X11)
-  ui::TouchFactory::SetTouchDeviceListFromCommandLine();
-#endif
-
-#if defined(OS_WIN)
-  // Initialize the OSCrypt.
-  PrefService* local_state = g_browser_process->local_state();
-  DCHECK(local_state);
-  bool os_crypt_init = OSCrypt::Init(local_state);
-  DCHECK(os_crypt_init);
-
-  // installer_util references strings that are normally compiled into
-  // setup.exe.  In Chrome, these strings are in the locale files.
-  ChromeBrowserMainPartsWin::SetupInstallerUtilStrings();
-#endif  // defined(OS_WIN)
-}
-
-void CefBrowserMainParts::PostMainMessageLoopStart() {
-#if defined(OS_LINUX)
-  printing::PrintingContextLinux::SetCreatePrintDialogFunction(
-      &CefPrintDialogLinux::CreatePrintDialog);
-  printing::PrintingContextLinux::SetPdfPaperSizeFunction(
-      &CefPrintDialogLinux::GetPdfPaperSize);
-#endif
-}
-
-int CefBrowserMainParts::PreCreateThreads() {
-#if defined(OS_WIN)
-  PlatformInitialize();
-#endif
-
-  net::NetModule::SetResourceProvider(&NetResourceProvider);
-
-  // Initialize these objects before IO access restrictions are applied and
-  // before the IO thread is started.
-  content::GpuDataManager::GetInstance();
-  SystemNetworkContextManager::CreateInstance(g_browser_process->local_state());
-
-  return 0;
-}
-
-void CefBrowserMainParts::PreMainMessageLoopRun() {
-#if defined(USE_AURA)
-  display::Screen::SetScreenInstance(views::CreateDesktopScreen());
-#endif
-
-  if (extensions::ExtensionsEnabled()) {
-    // Initialize extension global objects before creating the global
-    // BrowserContext.
-    extensions_client_.reset(new extensions::CefExtensionsClient());
-    extensions::ExtensionsClient::Set(extensions_client_.get());
-    extensions_browser_client_.reset(
-        new extensions::CefExtensionsBrowserClient);
-    extensions::ExtensionsBrowserClient::Set(extensions_browser_client_.get());
-
-    extensions::CefExtensionSystemFactory::GetInstance();
-  }
-
-  // Register additional KeyedService factories here. See
-  // ChromeBrowserMainExtraPartsProfiles for details.
-  cef::EnsureBrowserContextKeyedServiceFactoriesBuilt();
-
-  printing::CefPrintingMessageFilter::EnsureShutdownNotifierFactoryBuilt();
-
-  background_task_runner_ = base::CreateSingleThreadTaskRunner(
-      {base::ThreadPool(), base::TaskPriority::BEST_EFFORT,
-       base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()});
-  user_visible_task_runner_ = base::CreateSingleThreadTaskRunner(
-      {base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
-       base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()});
-  user_blocking_task_runner_ = base::CreateSingleThreadTaskRunner(
-      {base::ThreadPool(), base::TaskPriority::USER_BLOCKING,
-       base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()});
-
-  CefRequestContextSettings settings;
-  CefContext::Get()->PopulateGlobalRequestContextSettings(&settings);
-
-  // Create the global RequestContext.
-  global_request_context_ =
-      CefRequestContextImpl::CreateGlobalRequestContext(settings);
-  CefBrowserContext* browser_context = static_cast<CefBrowserContext*>(
-      global_request_context_->GetBrowserContext());
-
-  CefDevToolsManagerDelegate::StartHttpHandler(browser_context);
-
-#if defined(OS_WIN)
-  // Windows parental controls calls can be slow, so we do an early init here
-  // that calculates this value off of the UI thread.
-  InitializeWinParentalControls();
-#endif
-
-  // Triggers initialization of the singleton instance on UI thread.
-  PluginFinder::GetInstance()->Init();
-
-  scheme::RegisterWebUIControllerFactory();
-}
-
-void CefBrowserMainParts::PostMainMessageLoopRun() {
-  // NOTE: Destroy objects in reverse order of creation.
-  CefDevToolsManagerDelegate::StopHttpHandler();
-
-  // There should be no additional references to the global CefRequestContext
-  // during shutdown. Did you forget to release a CefBrowser reference?
-  DCHECK(global_request_context_->HasOneRef());
-  global_request_context_ = nullptr;
-}
-
-void CefBrowserMainParts::PostDestroyThreads() {
-  if (extensions::ExtensionsEnabled()) {
-    extensions::ExtensionsBrowserClient::Set(nullptr);
-    extensions_browser_client_.reset();
-  }
-
-#if defined(TOOLKIT_VIEWS)
-  views_delegate_.reset();
-#if defined(OS_MACOSX)
-  layout_provider_.reset();
-#endif
-#endif  // defined(TOOLKIT_VIEWS)
-}
diff --git a/src/libcef/browser/browser_manager.cc b/src/libcef/browser/browser_manager.cc
new file mode 100644
index 0000000..8022e26
--- /dev/null
+++ b/src/libcef/browser/browser_manager.cc
@@ -0,0 +1,58 @@
+// Copyright 2021 The Chromium Embedded Framework 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 "libcef/browser/browser_manager.h"
+
+#include "libcef/browser/browser_info_manager.h"
+#include "libcef/browser/origin_whitelist_impl.h"
+#include "libcef/common/frame_util.h"
+
+#include "content/public/browser/render_process_host.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+
+CefBrowserManager::CefBrowserManager(int render_process_id)
+    : render_process_id_(render_process_id) {}
+
+CefBrowserManager::~CefBrowserManager() = default;
+
+// static
+void CefBrowserManager::ExposeInterfacesToRenderer(
+    service_manager::BinderRegistry* registry,
+    blink::AssociatedInterfaceRegistry* associated_registry,
+    content::RenderProcessHost* host) {
+  registry->AddInterface<cef::mojom::BrowserManager>(base::BindRepeating(
+      [](int render_process_id,
+         mojo::PendingReceiver<cef::mojom::BrowserManager> receiver) {
+        mojo::MakeSelfOwnedReceiver(
+            std::make_unique<CefBrowserManager>(render_process_id),
+            std::move(receiver));
+      },
+      host->GetID()));
+}
+
+// static
+mojo::Remote<cef::mojom::RenderManager>
+CefBrowserManager::GetRenderManagerForProcess(
+    content::RenderProcessHost* host) {
+  mojo::Remote<cef::mojom::RenderManager> client;
+  host->BindReceiver(client.BindNewPipeAndPassReceiver());
+  return client;
+}
+
+void CefBrowserManager::GetNewRenderThreadInfo(
+    cef::mojom::BrowserManager::GetNewRenderThreadInfoCallback callback) {
+  auto info = cef::mojom::NewRenderThreadInfo::New();
+  GetCrossOriginWhitelistEntries(&info->cross_origin_whitelist_entries);
+  std::move(callback).Run(std::move(info));
+}
+
+void CefBrowserManager::GetNewBrowserInfo(
+    int32_t render_frame_routing_id,
+    cef::mojom::BrowserManager::GetNewBrowserInfoCallback callback) {
+  CefBrowserInfoManager::GetInstance()->OnGetNewBrowserInfo(
+      frame_util::MakeGlobalId(render_process_id_, render_frame_routing_id),
+      std::move(callback));
+}
diff --git a/src/libcef/browser/browser_manager.h b/src/libcef/browser/browser_manager.h
new file mode 100644
index 0000000..3087050
--- /dev/null
+++ b/src/libcef/browser/browser_manager.h
@@ -0,0 +1,56 @@
+// Copyright 2021 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_BROWSER_MANAGER_H_
+#define CEF_LIBCEF_BROWSER_BROWSER_MANAGER_H_
+
+#include "cef/libcef/common/mojom/cef.mojom.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+
+namespace blink {
+class AssociatedInterfaceRegistry;
+}
+
+namespace content {
+class RenderProcessHost;
+}
+
+class CefBrowserManager : public cef::mojom::BrowserManager {
+ public:
+  explicit CefBrowserManager(int render_process_id);
+
+  CefBrowserManager(const CefBrowserManager&) = delete;
+  CefBrowserManager& operator=(const CefBrowserManager&) = delete;
+
+  ~CefBrowserManager() override;
+
+  // Called from the ContentBrowserClient method of the same name.
+  // |associated_registry| is used for interfaces which must be associated with
+  // some IPC::ChannelProxy, meaning that messages on the interface retain FIFO
+  // with respect to legacy Chrome IPC messages sent or dispatched on the
+  // channel.
+  static void ExposeInterfacesToRenderer(
+      service_manager::BinderRegistry* registry,
+      blink::AssociatedInterfaceRegistry* associated_registry,
+      content::RenderProcessHost* host);
+
+  // Connects to CefRenderManager in the render process.
+  static mojo::Remote<cef::mojom::RenderManager> GetRenderManagerForProcess(
+      content::RenderProcessHost* host);
+
+ private:
+  // cef::mojom::BrowserManager methods:
+  void GetNewRenderThreadInfo(
+      cef::mojom::BrowserManager::GetNewRenderThreadInfoCallback callback)
+      override;
+  void GetNewBrowserInfo(
+      int32_t render_frame_routing_id,
+      cef::mojom::BrowserManager::GetNewBrowserInfoCallback callback) override;
+
+  // The process ID of the renderer.
+  const int render_process_id_;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_BROWSER_MANAGER_H_
diff --git a/src/libcef/browser/browser_message_filter.cc b/src/libcef/browser/browser_message_filter.cc
deleted file mode 100644
index b673a9f..0000000
--- a/src/libcef/browser/browser_message_filter.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework Authors.
-// Portions (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/browser_message_filter.h"
-
-#include "libcef/browser/browser_info_manager.h"
-#include "libcef/browser/origin_whitelist_impl.h"
-#include "libcef/common/cef_messages.h"
-#include "libcef/common/content_client.h"
-#include "libcef/common/values_impl.h"
-
-#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "content/public/common/child_process_host.h"
-
-CefBrowserMessageFilter::CefBrowserMessageFilter(int render_process_id)
-    : content::BrowserMessageFilter(ExtensionMsgStart),
-      render_process_id_(render_process_id) {}
-
-CefBrowserMessageFilter::~CefBrowserMessageFilter() {}
-
-void CefBrowserMessageFilter::OnFilterRemoved() {
-  render_process_id_ = content::ChildProcessHost::kInvalidUniqueID;
-  content::BrowserMessageFilter::OnFilterRemoved();
-}
-
-bool CefBrowserMessageFilter::OnMessageReceived(const IPC::Message& message) {
-  bool handled = true;
-
-  IPC_BEGIN_MESSAGE_MAP(CefBrowserMessageFilter, message)
-    IPC_MESSAGE_HANDLER(CefProcessHostMsg_GetNewRenderThreadInfo,
-                        OnGetNewRenderThreadInfo)
-    IPC_MESSAGE_HANDLER_DELAY_REPLY(CefProcessHostMsg_GetNewBrowserInfo,
-                                    OnGetNewBrowserInfo)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  return handled;
-}
-
-void CefBrowserMessageFilter::OnGetNewRenderThreadInfo(
-    CefProcessHostMsg_GetNewRenderThreadInfo_Params* params) {
-  GetCrossOriginWhitelistEntries(&params->cross_origin_whitelist_entries);
-
-  CefRefPtr<CefApp> app = CefContentClient::Get()->application();
-  if (app.get()) {
-    CefRefPtr<CefBrowserProcessHandler> handler =
-        app->GetBrowserProcessHandler();
-    if (handler.get()) {
-      CefRefPtr<CefListValueImpl> listValuePtr(
-          new CefListValueImpl(&params->extra_info, false, false));
-      handler->OnRenderProcessThreadCreated(listValuePtr.get());
-      listValuePtr->Detach(nullptr);
-    }
-  }
-}
-
-void CefBrowserMessageFilter::OnGetNewBrowserInfo(int render_frame_routing_id,
-                                                  IPC::Message* reply_msg) {
-  if (render_process_id_ != content::ChildProcessHost::kInvalidUniqueID) {
-    CefBrowserInfoManager::GetInstance()->OnGetNewBrowserInfo(
-        render_process_id_, render_frame_routing_id, reply_msg);
-  } else {
-    delete reply_msg;
-  }
-}
diff --git a/src/libcef/browser/browser_message_filter.h b/src/libcef/browser/browser_message_filter.h
deleted file mode 100644
index c4a28e4..0000000
--- a/src/libcef/browser/browser_message_filter.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_BROWSER_BROWSER_MESSAGE_FILTER_H_
-#define CEF_LIBCEF_BROWSER_BROWSER_MESSAGE_FILTER_H_
-
-#include <stdint.h>
-
-#include <string>
-
-#include "content/public/browser/browser_message_filter.h"
-
-struct CefProcessHostMsg_GetNewBrowserInfo_Params;
-struct CefProcessHostMsg_GetNewRenderThreadInfo_Params;
-
-// This class sends and receives control messages on the browser process.
-class CefBrowserMessageFilter : public content::BrowserMessageFilter {
- public:
-  explicit CefBrowserMessageFilter(int render_process_id);
-  ~CefBrowserMessageFilter() override;
-
-  // IPC::ChannelProxy::MessageFilter implementation.
-  void OnFilterRemoved() override;
-  bool OnMessageReceived(const IPC::Message& message) override;
-
- private:
-  // Message handlers.
-  void OnGetNewRenderThreadInfo(
-      CefProcessHostMsg_GetNewRenderThreadInfo_Params* params);
-  void OnGetNewBrowserInfo(int render_frame_routing_id,
-                           IPC::Message* reply_msg);
-
-  int render_process_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefBrowserMessageFilter);
-};
-
-#endif  // CEF_LIBCEF_BROWSER_BROWSER_MESSAGE_FILTER_H_
diff --git a/src/libcef/browser/browser_message_loop.cc b/src/libcef/browser/browser_message_loop.cc
index d810884..31d4b4a 100644
--- a/src/libcef/browser/browser_message_loop.cc
+++ b/src/libcef/browser/browser_message_loop.cc
@@ -3,16 +3,15 @@
 // be found in the LICENSE file.
 
 #include "libcef/browser/browser_message_loop.h"
-#include "libcef/browser/context.h"
-#include "libcef/common/content_client.h"
+#include "libcef/common/app_manager.h"
 
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_pump.h"
 #include "base/message_loop/message_pump_for_ui.h"
 
-#if defined(OS_MACOSX)
-#include "base/mac/scoped_nsautorelease_pool.h"
-#include "base/message_loop/message_pump_mac.h"
+#if BUILDFLAG(IS_MAC)
+#include "base/apple/scoped_nsautorelease_pool.h"
+#include "base/message_loop/message_pump_apple.h"
 #endif
 
 #include "content/public/browser/browser_thread.h"
@@ -30,14 +29,15 @@
   void Run(Delegate* delegate) override {
     base::TimeTicks start = base::TimeTicks::Now();
     while (true) {
-#if defined(OS_MACOSX)
-      base::mac::ScopedNSAutoreleasePool autorelease_pool;
+#if BUILDFLAG(IS_MAC)
+      base::apple::ScopedNSAutoreleasePool autorelease_pool;
 #endif
 
       base::TimeTicks next_run_time;  // is_null()
       const bool has_more_work = DirectRunWork(delegate, &next_run_time);
-      if (!has_more_work)
+      if (!has_more_work) {
         break;
+      }
 
       if (next_run_time.is_null()) {
         // We have more work that should run immediately.
@@ -45,8 +45,9 @@
       }
 
       const base::TimeDelta& delta = next_run_time - start;
-      if (delta.InSecondsF() > max_time_slice_)
+      if (delta.InSecondsF() > max_time_slice_) {
         break;
+      }
     }
   }
 
@@ -54,8 +55,10 @@
 
   void ScheduleWork() override { handler_->OnScheduleMessagePumpWork(0); }
 
-  void ScheduleDelayedWork(const base::TimeTicks& delayed_work_time) override {
-    const base::TimeDelta& delta = delayed_work_time - base::TimeTicks::Now();
+  void ScheduleDelayedWork(
+      const Delegate::NextWorkInfo& next_work_info) override {
+    const base::TimeDelta& delta =
+        next_work_info.delayed_run_time - next_work_info.recent_now;
     handler_->OnScheduleMessagePumpWork(delta.InMilliseconds());
   }
 
@@ -71,19 +74,21 @@
     // is_immediate() returns true if the next task is ready right away.
     more_immediate_work = next_work_info.is_immediate();
     if (!more_immediate_work) {
-      // DoIdleWork() returns true if idle work was all done.
-      more_idle_work = !delegate->DoIdleWork();
-
       // Check the next PendingTask's |delayed_run_time|.
       // is_max() returns true if there are no more immediate nor delayed tasks.
       more_delayed_work = !next_work_info.delayed_run_time.is_max();
-      if (more_delayed_work && !more_idle_work) {
+      if (more_delayed_work) {
         // The only remaining work that we know about is the PendingTask.
         // Consider the run time for that task in the time slice calculation.
         *next_run_time = next_work_info.delayed_run_time;
       }
     }
 
+    if (!more_immediate_work && !more_delayed_work) {
+      // DoIdleWork() returns true if idle work was all done.
+      more_idle_work = !delegate->DoIdleWork();
+    }
+
     return more_immediate_work || more_idle_work || more_delayed_work;
   }
 
@@ -92,9 +97,10 @@
 };
 
 CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() {
-  CefRefPtr<CefApp> app = CefContentClient::Get()->application();
-  if (app)
+  CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
+  if (app) {
     return app->GetBrowserProcessHandler();
+  }
   return nullptr;
 }
 
@@ -103,12 +109,13 @@
           content::BrowserThread::UI) ||
       content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
     CefRefPtr<CefBrowserProcessHandler> handler = GetBrowserProcessHandler();
-    if (handler)
+    if (handler) {
       return std::make_unique<MessagePumpExternal>(0.01f, handler);
+    }
   }
 
-#if defined(OS_MACOSX)
-  return base::MessagePumpMac::Create();
+#if BUILDFLAG(IS_MAC)
+  return base::message_pump_apple::Create();
 #else
   return std::make_unique<base::MessagePumpForUI>();
 #endif
@@ -116,9 +123,6 @@
 
 }  // namespace
 
-void InitMessagePumpFactoryForUI() {
-  const CefSettings& settings = CefContext::Get()->settings();
-  if (settings.external_message_pump) {
-    base::MessagePump::OverrideMessagePumpForUIFactory(MessagePumpFactoryForUI);
-  }
+void InitExternalMessagePumpFactoryForUI() {
+  base::MessagePump::OverrideMessagePumpForUIFactory(MessagePumpFactoryForUI);
 }
diff --git a/src/libcef/browser/browser_message_loop.h b/src/libcef/browser/browser_message_loop.h
index 8510c1c..38f2b02 100644
--- a/src/libcef/browser/browser_message_loop.h
+++ b/src/libcef/browser/browser_message_loop.h
@@ -5,6 +5,6 @@
 #ifndef CEF_LIBCEF_BROWSER_BROWSER_MESSAGE_LOOP_H_
 #define CEF_LIBCEF_BROWSER_BROWSER_MESSAGE_LOOP_H_
 
-void InitMessagePumpFactoryForUI();
+void InitExternalMessagePumpFactoryForUI();
 
 #endif  // CEF_LIBCEF_BROWSER_BROWSER_MESSAGE_LOOP_H_
diff --git a/src/libcef/browser/browser_platform_delegate.cc b/src/libcef/browser/browser_platform_delegate.cc
index 5a77906..a06db2b 100644
--- a/src/libcef/browser/browser_platform_delegate.cc
+++ b/src/libcef/browser/browser_platform_delegate.cc
@@ -4,79 +4,157 @@
 
 #include "libcef/browser/browser_platform_delegate.h"
 
-#include "libcef/browser/browser_host_impl.h"
-#include "libcef/browser/osr/browser_platform_delegate_osr.h"
-#include "libcef/browser/web_contents_dialog_helper.h"
-#include "libcef/common/extensions/extensions_util.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
+#include "libcef/browser/thread_util.h"
 
 #include "base/logging.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "chrome/browser/platform_util.h"
+#include "chrome/browser/shell_integration.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_view.h"
 
-CefBrowserPlatformDelegate::CefBrowserPlatformDelegate() {}
+namespace {
+
+void ExecuteExternalProtocol(const GURL& url) {
+  CEF_REQUIRE_BLOCKING();
+
+  // Check that an application is associated with the scheme.
+  if (shell_integration::GetApplicationNameForScheme(url).empty()) {
+    return;
+  }
+
+  CEF_POST_TASK(TID_UI, base::BindOnce(&platform_util::OpenExternal, url));
+}
+
+}  // namespace
+
+CefBrowserPlatformDelegate::CefBrowserPlatformDelegate() = default;
 
 CefBrowserPlatformDelegate::~CefBrowserPlatformDelegate() {
   DCHECK(!browser_);
 }
 
+content::WebContents* CefBrowserPlatformDelegate::CreateWebContents(
+    CefBrowserCreateParams& create_params,
+    bool& own_web_contents) {
+  DCHECK(false);
+  return nullptr;
+}
+
 void CefBrowserPlatformDelegate::CreateViewForWebContents(
     content::WebContentsView** view,
     content::RenderViewHostDelegateView** delegate_view) {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::WebContentsCreated(
-    content::WebContents* web_contents) {}
+    content::WebContents* web_contents,
+    bool owned) {
+  // We should not have a browser at this point.
+  DCHECK(!browser_);
+
+  DCHECK(!web_contents_);
+  web_contents_ = web_contents;
+}
+
+void CefBrowserPlatformDelegate::AddNewContents(
+    content::WebContents* source,
+    std::unique_ptr<content::WebContents> new_contents,
+    const GURL& target_url,
+    WindowOpenDisposition disposition,
+    const blink::mojom::WindowFeatures& window_features,
+    bool user_gesture,
+    bool* was_blocked) {
+  DCHECK(false);
+}
+
+void CefBrowserPlatformDelegate::WebContentsDestroyed(
+    content::WebContents* web_contents) {
+  DCHECK(web_contents_ && web_contents_ == web_contents);
+  web_contents_ = nullptr;
+}
+
+bool CefBrowserPlatformDelegate::
+    ShouldAllowRendererInitiatedCrossProcessNavigation(
+        bool is_main_frame_navigation) {
+  return true;
+}
 
 void CefBrowserPlatformDelegate::RenderViewCreated(
     content::RenderViewHost* render_view_host) {
-  // Indicate that the view has an external parent (namely us). This changes the
-  // default view behavior in some cases (e.g. focus handling on Linux).
-  if (!IsViewsHosted() && render_view_host->GetWidget()->GetView())
+  // Indicate that the view has an external parent (namely us). This setting is
+  // required for proper focus handling on Windows and Linux.
+  if (HasExternalParent() && render_view_host->GetWidget()->GetView()) {
     render_view_host->GetWidget()->GetView()->SetHasExternalParent(true);
+  }
 }
 
-void CefBrowserPlatformDelegate::BrowserCreated(CefBrowserHostImpl* browser) {
+void CefBrowserPlatformDelegate::RenderViewReady() {}
+
+void CefBrowserPlatformDelegate::BrowserCreated(CefBrowserHostBase* browser) {
+  // We should have an associated WebContents at this point.
+  DCHECK(web_contents_);
+
   DCHECK(!browser_);
   DCHECK(browser);
   browser_ = browser;
+}
 
-  if (browser_->IsPrintPreviewSupported()) {
-    web_contents_dialog_helper_.reset(
-        new CefWebContentsDialogHelper(browser_->web_contents(), this));
-  }
+void CefBrowserPlatformDelegate::CreateExtensionHost(
+    const extensions::Extension* extension,
+    const GURL& url,
+    extensions::mojom::ViewType host_type) {
+  DCHECK(false);
+}
+
+extensions::ExtensionHost* CefBrowserPlatformDelegate::GetExtensionHost()
+    const {
+  DCHECK(false);
+  return nullptr;
 }
 
 void CefBrowserPlatformDelegate::NotifyBrowserCreated() {}
 
 void CefBrowserPlatformDelegate::NotifyBrowserDestroyed() {}
 
-void CefBrowserPlatformDelegate::BrowserDestroyed(CefBrowserHostImpl* browser) {
+void CefBrowserPlatformDelegate::BrowserDestroyed(CefBrowserHostBase* browser) {
+  // WebContentsDestroyed should already be called.
+  DCHECK(!web_contents_);
+
   DCHECK(browser_ && browser_ == browser);
   browser_ = nullptr;
 }
 
 bool CefBrowserPlatformDelegate::CreateHostWindow() {
-  NOTREACHED();
+  DCHECK(false);
   return true;
 }
 
 void CefBrowserPlatformDelegate::CloseHostWindow() {
-  NOTREACHED();
+  DCHECK(false);
 }
 
-#if defined(USE_AURA)
+CefWindowHandle CefBrowserPlatformDelegate::GetHostWindowHandle() const {
+  DCHECK(false);
+  return kNullWindowHandle;
+}
+
 views::Widget* CefBrowserPlatformDelegate::GetWindowWidget() const {
-  NOTREACHED();
+  DCHECK(false);
   return nullptr;
 }
 
 CefRefPtr<CefBrowserView> CefBrowserPlatformDelegate::GetBrowserView() const {
-  NOTREACHED();
+  DCHECK(false);
   return nullptr;
 }
-#endif
+
+web_modal::WebContentsModalDialogHost*
+CefBrowserPlatformDelegate::GetWebContentsModalDialogHost() const {
+  DCHECK(false);
+  return nullptr;
+}
 
 void CefBrowserPlatformDelegate::PopupWebContentsCreated(
     const CefBrowserSettings& settings,
@@ -86,30 +164,94 @@
     bool is_devtools) {}
 
 void CefBrowserPlatformDelegate::PopupBrowserCreated(
-    CefBrowserHostImpl* new_browser,
+    CefBrowserHostBase* new_browser,
     bool is_devtools) {}
 
-void CefBrowserPlatformDelegate::SendCaptureLostEvent() {
-  content::RenderWidgetHostImpl* widget = content::RenderWidgetHostImpl::From(
-      browser_->web_contents()->GetRenderViewHost()->GetWidget());
-  if (widget)
-    widget->LostCapture();
+SkColor CefBrowserPlatformDelegate::GetBackgroundColor() const {
+  DCHECK(false);
+  return SkColor();
 }
 
-#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX))
-void CefBrowserPlatformDelegate::NotifyMoveOrResizeStarted() {
-  // Dismiss any existing popups.
-  content::RenderViewHost* host = browser_->web_contents()->GetRenderViewHost();
-  if (host)
-    host->NotifyMoveOrResizeStarted();
+void CefBrowserPlatformDelegate::WasResized() {
+  DCHECK(false);
 }
 
+void CefBrowserPlatformDelegate::SendKeyEvent(const CefKeyEvent& event) {
+  NOTIMPLEMENTED();
+}
+
+void CefBrowserPlatformDelegate::SendMouseClickEvent(
+    const CefMouseEvent& event,
+    CefBrowserHost::MouseButtonType type,
+    bool mouseUp,
+    int clickCount) {
+  NOTIMPLEMENTED();
+}
+
+void CefBrowserPlatformDelegate::SendMouseMoveEvent(const CefMouseEvent& event,
+                                                    bool mouseLeave) {
+  NOTIMPLEMENTED();
+}
+
+void CefBrowserPlatformDelegate::SendMouseWheelEvent(const CefMouseEvent& event,
+                                                     int deltaX,
+                                                     int deltaY) {
+  NOTIMPLEMENTED();
+}
+
+void CefBrowserPlatformDelegate::SendTouchEvent(const CefTouchEvent& event) {
+  NOTIMPLEMENTED();
+}
+
+void CefBrowserPlatformDelegate::SetFocus(bool setFocus) {}
+
+void CefBrowserPlatformDelegate::SendCaptureLostEvent() {
+  NOTIMPLEMENTED();
+}
+
+#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC))
+void CefBrowserPlatformDelegate::NotifyMoveOrResizeStarted() {}
+
 void CefBrowserPlatformDelegate::SizeTo(int width, int height) {}
 #endif
 
-std::unique_ptr<CefFileDialogRunner>
-CefBrowserPlatformDelegate::CreateFileDialogRunner() {
-  return nullptr;
+gfx::Point CefBrowserPlatformDelegate::GetScreenPoint(
+    const gfx::Point& view,
+    bool want_dip_coords) const {
+  DCHECK(false);
+  return gfx::Point();
+}
+
+void CefBrowserPlatformDelegate::ViewText(const std::string& text) {
+  NOTIMPLEMENTED();
+}
+
+bool CefBrowserPlatformDelegate::HandleKeyboardEvent(
+    const content::NativeWebKeyboardEvent& event) {
+  DCHECK(false);
+  return false;
+}
+
+bool CefBrowserPlatformDelegate::PreHandleGestureEvent(
+    content::WebContents* source,
+    const blink::WebGestureEvent& event) {
+  return false;
+}
+
+bool CefBrowserPlatformDelegate::IsNeverComposited(
+    content::WebContents* web_contents) {
+  return false;
+}
+
+// static
+void CefBrowserPlatformDelegate::HandleExternalProtocol(const GURL& url) {
+  CEF_POST_USER_VISIBLE_TASK(base::BindOnce(ExecuteExternalProtocol, url));
+}
+
+CefEventHandle CefBrowserPlatformDelegate::GetEventHandle(
+    const content::NativeWebKeyboardEvent& event) const {
+  DCHECK(false);
+  return kNullEventHandle;
 }
 
 std::unique_ptr<CefJavaScriptDialogRunner>
@@ -117,24 +259,51 @@
   return nullptr;
 }
 
+std::unique_ptr<CefMenuRunner> CefBrowserPlatformDelegate::CreateMenuRunner() {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
+void CefBrowserPlatformDelegate::UpdateFindBarBoundingBox(
+    gfx::Rect* bounds) const {}
+
+bool CefBrowserPlatformDelegate::IsWindowless() const {
+  return false;
+}
+
+bool CefBrowserPlatformDelegate::IsViewsHosted() const {
+  return false;
+}
+
+bool CefBrowserPlatformDelegate::HasExternalParent() const {
+  // In the majority of cases a Views-hosted browser will not have an external
+  // parent, and visa-versa.
+  return !IsViewsHosted();
+}
+
 void CefBrowserPlatformDelegate::WasHidden(bool hidden) {
-  NOTREACHED();
+  DCHECK(false);
+}
+
+bool CefBrowserPlatformDelegate::IsHidden() const {
+  DCHECK(false);
+  return false;
 }
 
 void CefBrowserPlatformDelegate::NotifyScreenInfoChanged() {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::Invalidate(cef_paint_element_type_t type) {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::SendExternalBeginFrame() {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::SetWindowlessFrameRate(int frame_rate) {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::ImeSetComposition(
@@ -142,128 +311,171 @@
     const std::vector<CefCompositionUnderline>& underlines,
     const CefRange& replacement_range,
     const CefRange& selection_range) {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::ImeCommitText(
     const CefString& text,
     const CefRange& replacement_range,
     int relative_cursor_pos) {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::ImeFinishComposingText(bool keep_selection) {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::ImeCancelComposition() {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::DragTargetDragEnter(
     CefRefPtr<CefDragData> drag_data,
     const CefMouseEvent& event,
     cef_drag_operations_mask_t allowed_ops) {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::DragTargetDragOver(
     const CefMouseEvent& event,
     cef_drag_operations_mask_t allowed_ops) {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::DragTargetDragLeave() {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::DragTargetDrop(const CefMouseEvent& event) {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::StartDragging(
     const content::DropData& drop_data,
-    blink::WebDragOperationsMask allowed_ops,
+    blink::DragOperationsMask allowed_ops,
     const gfx::ImageSkia& image,
     const gfx::Vector2d& image_offset,
-    const content::DragEventSourceInfo& event_info,
+    const blink::mojom::DragEventSourceInfo& event_info,
     content::RenderWidgetHostImpl* source_rwh) {
-  NOTREACHED();
+  DCHECK(false);
 }
 
-void CefBrowserPlatformDelegate::UpdateDragCursor(
-    blink::WebDragOperation operation) {
-  NOTREACHED();
+void CefBrowserPlatformDelegate::UpdateDragOperation(
+    ui::mojom::DragOperation operation,
+    bool document_is_handling_drag) {
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::DragSourceEndedAt(
     int x,
     int y,
     cef_drag_operations_mask_t op) {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::DragSourceSystemDragEnded() {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::AccessibilityEventReceived(
     const content::AXEventNotificationDetails& eventData) {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 void CefBrowserPlatformDelegate::AccessibilityLocationChangesReceived(
     const std::vector<content::AXLocationChangeNotificationDetails>& locData) {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 gfx::Point CefBrowserPlatformDelegate::GetDialogPosition(
     const gfx::Size& size) {
-  NOTREACHED();
-  return gfx::Point();
+  const gfx::Size& max_size = GetMaximumDialogSize();
+  return gfx::Point((max_size.width() - size.width()) / 2,
+                    (max_size.height() - size.height()) / 2);
 }
 
 gfx::Size CefBrowserPlatformDelegate::GetMaximumDialogSize() {
-  NOTREACHED();
-  return gfx::Size();
-}
-
-base::RepeatingClosure CefBrowserPlatformDelegate::GetBoundsChangedCallback() {
-  if (web_contents_dialog_helper_) {
-    return web_contents_dialog_helper_->GetBoundsChangedCallback();
+  if (!web_contents_) {
+    return gfx::Size();
   }
 
-  return base::RepeatingClosure();
+  // The dialog should try to fit within the overlay for the web contents.
+  // Note that, for things like print preview, this is just a suggested maximum.
+  return web_contents_->GetContainerBounds().size();
+}
+
+void CefBrowserPlatformDelegate::SetAutoResizeEnabled(bool enabled,
+                                                      const CefSize& min_size,
+                                                      const CefSize& max_size) {
+  NOTIMPLEMENTED();
+}
+
+void CefBrowserPlatformDelegate::SetAccessibilityState(
+    cef_state_t accessibility_state) {
+  NOTIMPLEMENTED();
+}
+
+bool CefBrowserPlatformDelegate::IsPrintPreviewSupported() const {
+  return true;
+}
+
+void CefBrowserPlatformDelegate::Find(const CefString& searchText,
+                                      bool forward,
+                                      bool matchCase,
+                                      bool findNext) {
+  NOTIMPLEMENTED();
+}
+
+void CefBrowserPlatformDelegate::StopFinding(bool clearSelection) {
+  NOTIMPLEMENTED();
 }
 
 // static
 int CefBrowserPlatformDelegate::TranslateWebEventModifiers(
-    uint32 cef_modifiers) {
+    uint32_t cef_modifiers) {
   int result = 0;
   // Set modifiers based on key state.
-  if (cef_modifiers & EVENTFLAG_SHIFT_DOWN)
-    result |= blink::WebInputEvent::kShiftKey;
-  if (cef_modifiers & EVENTFLAG_CONTROL_DOWN)
-    result |= blink::WebInputEvent::kControlKey;
-  if (cef_modifiers & EVENTFLAG_ALT_DOWN)
-    result |= blink::WebInputEvent::kAltKey;
-  if (cef_modifiers & EVENTFLAG_COMMAND_DOWN)
-    result |= blink::WebInputEvent::kMetaKey;
-  if (cef_modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON)
-    result |= blink::WebInputEvent::kLeftButtonDown;
-  if (cef_modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON)
-    result |= blink::WebInputEvent::kMiddleButtonDown;
-  if (cef_modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON)
-    result |= blink::WebInputEvent::kRightButtonDown;
-  if (cef_modifiers & EVENTFLAG_CAPS_LOCK_ON)
+  if (cef_modifiers & EVENTFLAG_CAPS_LOCK_ON) {
     result |= blink::WebInputEvent::kCapsLockOn;
-  if (cef_modifiers & EVENTFLAG_NUM_LOCK_ON)
+  }
+  if (cef_modifiers & EVENTFLAG_SHIFT_DOWN) {
+    result |= blink::WebInputEvent::kShiftKey;
+  }
+  if (cef_modifiers & EVENTFLAG_CONTROL_DOWN) {
+    result |= blink::WebInputEvent::kControlKey;
+  }
+  if (cef_modifiers & EVENTFLAG_ALT_DOWN) {
+    result |= blink::WebInputEvent::kAltKey;
+  }
+  if (cef_modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) {
+    result |= blink::WebInputEvent::kLeftButtonDown;
+  }
+  if (cef_modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) {
+    result |= blink::WebInputEvent::kMiddleButtonDown;
+  }
+  if (cef_modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) {
+    result |= blink::WebInputEvent::kRightButtonDown;
+  }
+  if (cef_modifiers & EVENTFLAG_COMMAND_DOWN) {
+    result |= blink::WebInputEvent::kMetaKey;
+  }
+  if (cef_modifiers & EVENTFLAG_NUM_LOCK_ON) {
     result |= blink::WebInputEvent::kNumLockOn;
-  if (cef_modifiers & EVENTFLAG_IS_LEFT)
-    result |= blink::WebInputEvent::kIsLeft;
-  if (cef_modifiers & EVENTFLAG_IS_RIGHT)
-    result |= blink::WebInputEvent::kIsRight;
-  if (cef_modifiers & EVENTFLAG_IS_KEY_PAD)
+  }
+  if (cef_modifiers & EVENTFLAG_IS_KEY_PAD) {
     result |= blink::WebInputEvent::kIsKeyPad;
+  }
+  if (cef_modifiers & EVENTFLAG_IS_LEFT) {
+    result |= blink::WebInputEvent::kIsLeft;
+  }
+  if (cef_modifiers & EVENTFLAG_IS_RIGHT) {
+    result |= blink::WebInputEvent::kIsRight;
+  }
+  if (cef_modifiers & EVENTFLAG_ALTGR_DOWN) {
+    result |= blink::WebInputEvent::kAltGrKey;
+  }
+  if (cef_modifiers & EVENTFLAG_IS_REPEAT) {
+    result |= blink::WebInputEvent::kIsAutoRepeat;
+  }
   return result;
 }
diff --git a/src/libcef/browser/browser_platform_delegate.h b/src/libcef/browser/browser_platform_delegate.h
index a14c7ff..7c0e366 100644
--- a/src/libcef/browser/browser_platform_delegate.h
+++ b/src/libcef/browser/browser_platform_delegate.h
@@ -13,46 +13,87 @@
 #include "include/cef_drag_data.h"
 #include "include/internal/cef_types.h"
 #include "include/views/cef_browser_view.h"
-#include "libcef/browser/browser_host_impl.h"
 
-#include "base/callback_forward.h"
-#include "content/public/browser/web_contents.h"
+#include "base/functional/callback_forward.h"
+#include "extensions/common/mojom/view_type.mojom-forward.h"
+#include "third_party/blink/public/common/page/drag_operation.h"
+#include "third_party/blink/public/mojom/drag/drag.mojom-forward.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h"
+#include "ui/base/window_open_disposition.h"
+
+class GURL;
 
 namespace blink {
+class WebGestureEvent;
 class WebMouseEvent;
 class WebMouseWheelEvent;
 class WebInputEvent;
 class WebTouchEvent;
+
+namespace mojom {
+class WindowFeatures;
+}
 }  // namespace blink
 
 namespace content {
+struct AXEventNotificationDetails;
+struct AXLocationChangeNotificationDetails;
+struct DropData;
 struct NativeWebKeyboardEvent;
 class RenderViewHost;
 class RenderViewHostDelegateView;
+class RenderWidgetHostImpl;
+class WebContents;
 class WebContentsView;
 }  // namespace content
 
-#if defined(USE_AURA)
+namespace extensions {
+class Extension;
+class ExtensionHost;
+}  // namespace extensions
+
+namespace gfx {
+class ImageSkia;
+class Point;
+class Rect;
+class Size;
+class Vector2d;
+}  // namespace gfx
+
 namespace views {
 class Widget;
 }
-#endif
 
-class CefBrowserInfo;
-class CefFileDialogRunner;
+namespace web_modal {
+class WebContentsModalDialogHost;
+}
+
+struct CefBrowserCreateParams;
+class CefBrowserHostBase;
 class CefJavaScriptDialogRunner;
 class CefMenuRunner;
-class CefWebContentsDialogHelper;
 
 // Provides platform-specific implementations of browser functionality. All
 // methods are called on the browser process UI thread unless otherwise
 // indicated.
 class CefBrowserPlatformDelegate {
  public:
+  CefBrowserPlatformDelegate(const CefBrowserPlatformDelegate&) = delete;
+  CefBrowserPlatformDelegate& operator=(const CefBrowserPlatformDelegate&) =
+      delete;
+
   // Create a new CefBrowserPlatformDelegate instance. May be called on multiple
   // threads.
   static std::unique_ptr<CefBrowserPlatformDelegate> Create(
-      CefBrowserHostImpl::CreateParams& create_params);
+      const CefBrowserCreateParams& create_params);
+
+  // Called from AlloyBrowserHostImpl::Create.
+  // Wait for the call to WebContentsCreated(owned=true) before taking ownership
+  // of the resulting WebContents object.
+  virtual content::WebContents* CreateWebContents(
+      CefBrowserCreateParams& create_params,
+      bool& own_web_contents);
 
   // Called to create the view objects for a new WebContents. Will only be
   // called a single time per instance. May be called on multiple threads. Only
@@ -61,17 +102,52 @@
       content::WebContentsView** view,
       content::RenderViewHostDelegateView** delegate_view);
 
-  // Called after the WebContents for the browser is created. Will only be
-  // called a single time per instance.
-  virtual void WebContentsCreated(content::WebContents* web_contents);
+  // Called after the WebContents for a browser has been created. |owned| will
+  // be true if |web_contents| was created via CreateWebContents() and we should
+  // take ownership. This will also be called for popup WebContents created
+  // indirectly by Chromium. Will only be called a single time per instance.
+  virtual void WebContentsCreated(content::WebContents* web_contents,
+                                  bool owned);
+
+  // Called when Chromium is ready to hand over ownership of a popup
+  // WebContents. WebContentsCreated(owned=false) will be called first for
+  // |new_contents|. Will only be called a single time per instance. See also
+  // the WebContentsDelegate documentation.
+  virtual void AddNewContents(
+      content::WebContents* source,
+      std::unique_ptr<content::WebContents> new_contents,
+      const GURL& target_url,
+      WindowOpenDisposition disposition,
+      const blink::mojom::WindowFeatures& window_features,
+      bool user_gesture,
+      bool* was_blocked);
+
+  // Called when the WebContents is destroyed. This will be called before
+  // BrowserDestroyed(). Will only be called a single time per instance.
+  virtual void WebContentsDestroyed(content::WebContents* web_contents);
+
+  // See WebContentsDelegate documentation.
+  virtual bool ShouldAllowRendererInitiatedCrossProcessNavigation(
+      bool is_main_frame_navigation);
 
   // Called after the RenderViewHost is created.
   virtual void RenderViewCreated(content::RenderViewHost* render_view_host);
 
-  // Called after the owning CefBrowserHostImpl is created. Will only be called
-  // a single time per instance. Do not send any client notifications from this
-  // method.
-  virtual void BrowserCreated(CefBrowserHostImpl* browser);
+  // See WebContentsObserver documentation.
+  virtual void RenderViewReady();
+
+  // Called after the owning AlloyBrowserHostImpl is created. Will only be
+  // called a single time per instance. Do not send any client notifications
+  // from this method.
+  virtual void BrowserCreated(CefBrowserHostBase* browser);
+
+  // Called from AlloyBrowserHostImpl::Create.
+  virtual void CreateExtensionHost(const extensions::Extension* extension,
+                                   const GURL& url,
+                                   extensions::mojom::ViewType host_type);
+
+  // Returns the current extension host.
+  virtual extensions::ExtensionHost* GetExtensionHost() const;
 
   // Send any notifications related to browser creation. Called after
   // BrowserCreated().
@@ -81,11 +157,11 @@
   // BrowserDestroyed().
   virtual void NotifyBrowserDestroyed();
 
-  // Called before the owning CefBrowserHostImpl is destroyed. Will only be
-  // called a single time per instance. All references to the CefBrowserHostImpl
-  // and WebContents should be cleared when this method is called. Do not send
-  // any client notifications from this method.
-  virtual void BrowserDestroyed(CefBrowserHostImpl* browser);
+  // Called before the owning AlloyBrowserHostImpl is destroyed. Will only be
+  // called a single time per instance. All references to the
+  // AlloyBrowserHostImpl and WebContents should be cleared when this method is
+  // called. Do not send any client notifications from this method.
+  virtual void BrowserDestroyed(CefBrowserHostBase* browser);
 
   // Create the window that hosts the browser. Will only be called a single time
   // per instance. Only used with windowed rendering.
@@ -100,9 +176,8 @@
   // rendering this will return the most immediate parent window handle. For
   // windowless rendering this will return the parent window handle specified by
   // the client, which may be NULL. May be called on multiple threads.
-  virtual CefWindowHandle GetHostWindowHandle() const = 0;
+  virtual CefWindowHandle GetHostWindowHandle() const;
 
-#if defined(USE_AURA)
   // Returns the Widget owner for the browser window. Only used with windowed
   // rendering.
   virtual views::Widget* GetWindowWidget() const;
@@ -110,10 +185,13 @@
   // Returns the BrowserView associated with this browser. Only used with views-
   // based browsers.
   virtual CefRefPtr<CefBrowserView> GetBrowserView() const;
-#endif
+
+  // Returns the WebContentsModalDialogHost associated with this browser.
+  virtual web_modal::WebContentsModalDialogHost* GetWebContentsModalDialogHost()
+      const;
 
   // Called after the WebContents have been created for a new popup browser
-  // parented to this browser but before the CefBrowserHostImpl is created for
+  // parented to this browser but before the AlloyBrowserHostImpl is created for
   // the popup. |is_devtools| will be true if the popup will host DevTools. This
   // method will be called before WebContentsCreated() is called on
   // |new_platform_delegate|. Do not make the new browser visible in this
@@ -125,13 +203,13 @@
       CefBrowserPlatformDelegate* new_platform_delegate,
       bool is_devtools);
 
-  // Called after the CefBrowserHostImpl is created for a new popup browser
+  // Called after the AlloyBrowserHostImpl is created for a new popup browser
   // parented to this browser. |is_devtools| will be true if the popup will host
   // DevTools. This method will be called immediately after
   // CefLifeSpanHandler::OnAfterCreated() for the popup browser. It is safe to
   // make the new browser visible in this callback (for example, add the browser
   // to a window and show it).
-  virtual void PopupBrowserCreated(CefBrowserHostImpl* new_browser,
+  virtual void PopupBrowserCreated(CefBrowserHostBase* new_browser,
                                    bool is_devtools);
 
   // Returns the background color for the browser. The alpha component will be
@@ -139,35 +217,31 @@
   // fully opaque). SK_AlphaOPAQUE will always be returned for windowed
   // browsers. SK_ColorTRANSPARENT may be returned for windowless browsers to
   // enable transparency.
-  virtual SkColor GetBackgroundColor() const = 0;
-
-  virtual bool CanUseSharedTexture() const = 0;
-  virtual bool CanUseExternalBeginFrame() const = 0;
+  virtual SkColor GetBackgroundColor() const;
 
   // Notify the window that it was resized.
-  virtual void WasResized() = 0;
+  virtual void WasResized();
 
   // Send input events.
-  virtual void SendKeyEvent(const CefKeyEvent& event) = 0;
+  virtual void SendKeyEvent(const CefKeyEvent& event);
   virtual void SendMouseClickEvent(const CefMouseEvent& event,
                                    CefBrowserHost::MouseButtonType type,
                                    bool mouseUp,
-                                   int clickCount) = 0;
-  virtual void SendMouseMoveEvent(const CefMouseEvent& event,
-                                  bool mouseLeave) = 0;
+                                   int clickCount);
+  virtual void SendMouseMoveEvent(const CefMouseEvent& event, bool mouseLeave);
   virtual void SendMouseWheelEvent(const CefMouseEvent& event,
                                    int deltaX,
-                                   int deltaY) = 0;
-  virtual void SendTouchEvent(const CefTouchEvent& event) = 0;
+                                   int deltaY);
+  virtual void SendTouchEvent(const CefTouchEvent& event);
 
   // Send focus event. The browser's WebContents may be NULL when this method is
   // called.
-  virtual void SendFocusEvent(bool setFocus) = 0;
+  virtual void SetFocus(bool setFocus);
 
   // Send capture lost event.
   virtual void SendCaptureLostEvent();
 
-#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX))
+#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC))
   // The window hosting the browser is about to be moved or resized. Only used
   // on Windows and Linux.
   virtual void NotifyMoveOrResizeStarted();
@@ -177,46 +251,63 @@
   virtual void SizeTo(int width, int height);
 #endif
 
-  // Convert from view coordinates to screen coordinates. Potential display
-  // scaling will be applied to the result.
-  virtual gfx::Point GetScreenPoint(const gfx::Point& view) const = 0;
+  // Convert from view DIP coordinates to screen coordinates. If
+  // |want_dip_coords| is true return DIP instead of device (pixel) coordinates
+  // on Windows/Linux.
+  virtual gfx::Point GetScreenPoint(const gfx::Point& view,
+                                    bool want_dip_coords) const;
 
   // Open the specified text in the default text editor.
-  virtual void ViewText(const std::string& text) = 0;
+  virtual void ViewText(const std::string& text);
 
   // Forward the keyboard event to the application or frame window to allow
   // processing of shortcut keys.
   virtual bool HandleKeyboardEvent(
-      const content::NativeWebKeyboardEvent& event) = 0;
+      const content::NativeWebKeyboardEvent& event);
+
+  // See WebContentsDelegate documentation.
+  virtual bool PreHandleGestureEvent(content::WebContents* source,
+                                     const blink::WebGestureEvent& event);
+
+  // See WebContentsDelegate documentation.
+  virtual bool IsNeverComposited(content::WebContents* web_contents);
 
   // Invoke platform specific handling for the external protocol.
   static void HandleExternalProtocol(const GURL& url);
 
   // Returns the OS event handle, if any, associated with |event|.
   virtual CefEventHandle GetEventHandle(
-      const content::NativeWebKeyboardEvent& event) const = 0;
-
-  // Create the platform-specific file dialog runner.
-  virtual std::unique_ptr<CefFileDialogRunner> CreateFileDialogRunner();
+      const content::NativeWebKeyboardEvent& event) const;
 
   // Create the platform-specific JavaScript dialog runner.
   virtual std::unique_ptr<CefJavaScriptDialogRunner>
   CreateJavaScriptDialogRunner();
 
   // Create the platform-specific menu runner.
-  virtual std::unique_ptr<CefMenuRunner> CreateMenuRunner() = 0;
+  virtual std::unique_ptr<CefMenuRunner> CreateMenuRunner();
+
+  // Optionally modify the bounding box for the Chrome Find bar.
+  virtual void UpdateFindBarBoundingBox(gfx::Rect* bounds) const;
 
   // Returns true if this delegate implements windowless rendering. May be
   // called on multiple threads.
-  virtual bool IsWindowless() const = 0;
+  virtual bool IsWindowless() const;
 
   // Returns true if this delegate implements views-hosted browser handling. May
   // be called on multiple threads.
-  virtual bool IsViewsHosted() const = 0;
+  virtual bool IsViewsHosted() const;
+
+  // Returns true if this delegate implements a browser with external
+  // (client-provided) parent window. May be called on multiple threads.
+  virtual bool HasExternalParent() const;
 
   // Notify the browser that it was hidden. Only used with windowless rendering.
   virtual void WasHidden(bool hidden);
 
+  // Returns true if the browser is currently hidden. Only used with windowless
+  // rendering.
+  virtual bool IsHidden() const;
+
   // Notify the browser that screen information has changed. Only used with
   // windowless rendering.
   virtual void NotifyScreenInfoChanged();
@@ -224,6 +315,7 @@
   // Invalidate the view. Only used with windowless rendering.
   virtual void Invalidate(cef_paint_element_type_t type);
 
+  // Send the external begin frame message. Only used with windowless rendering.
   virtual void SendExternalBeginFrame();
 
   // Set the windowless frame rate. Only used with windowless rendering.
@@ -251,13 +343,15 @@
                                   cef_drag_operations_mask_t allowed_ops);
   virtual void DragTargetDragLeave();
   virtual void DragTargetDrop(const CefMouseEvent& event);
-  virtual void StartDragging(const content::DropData& drop_data,
-                             blink::WebDragOperationsMask allowed_ops,
-                             const gfx::ImageSkia& image,
-                             const gfx::Vector2d& image_offset,
-                             const content::DragEventSourceInfo& event_info,
-                             content::RenderWidgetHostImpl* source_rwh);
-  virtual void UpdateDragCursor(blink::WebDragOperation operation);
+  virtual void StartDragging(
+      const content::DropData& drop_data,
+      blink::DragOperationsMask allowed_ops,
+      const gfx::ImageSkia& image,
+      const gfx::Vector2d& image_offset,
+      const blink::mojom::DragEventSourceInfo& event_info,
+      content::RenderWidgetHostImpl* source_rwh);
+  virtual void UpdateDragOperation(ui::mojom::DragOperation operation,
+                                   bool document_is_handling_drag);
   virtual void DragSourceEndedAt(int x, int y, cef_drag_operations_mask_t op);
   virtual void DragSourceSystemDragEnded();
   virtual void AccessibilityEventReceived(
@@ -267,24 +361,30 @@
   virtual gfx::Point GetDialogPosition(const gfx::Size& size);
   virtual gfx::Size GetMaximumDialogSize();
 
+  // See CefBrowserHost documentation.
+  virtual void SetAutoResizeEnabled(bool enabled,
+                                    const CefSize& min_size,
+                                    const CefSize& max_size);
+  virtual void SetAccessibilityState(cef_state_t accessibility_state);
+  virtual bool IsPrintPreviewSupported() const;
+  virtual void Find(const CefString& searchText,
+                    bool forward,
+                    bool matchCase,
+                    bool findNext);
+  virtual void StopFinding(bool clearSelection);
+
  protected:
-  // Allow deletion via scoped_ptr only.
+  // Allow deletion via std::unique_ptr only.
   friend std::default_delete<CefBrowserPlatformDelegate>;
 
   CefBrowserPlatformDelegate();
   virtual ~CefBrowserPlatformDelegate();
 
-  base::RepeatingClosure GetBoundsChangedCallback();
+  static int TranslateWebEventModifiers(uint32_t cef_modifiers);
 
-  static int TranslateWebEventModifiers(uint32 cef_modifiers);
-
-  CefBrowserHostImpl* browser_ = nullptr;  // Not owned by this object.
-
- private:
-  // Used for the print preview dialog.
-  std::unique_ptr<CefWebContentsDialogHelper> web_contents_dialog_helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefBrowserPlatformDelegate);
+  // Not owned by this object.
+  content::WebContents* web_contents_ = nullptr;
+  CefBrowserHostBase* browser_ = nullptr;
 };
 
 #endif  // CEF_LIBCEF_BROWSER_BROWSER_PLATFORM_DELEGATE_H_
diff --git a/src/libcef/browser/browser_platform_delegate_create.cc b/src/libcef/browser/browser_platform_delegate_create.cc
index 75c05f4..5e09068 100644
--- a/src/libcef/browser/browser_platform_delegate_create.cc
+++ b/src/libcef/browser/browser_platform_delegate_create.cc
@@ -11,56 +11,58 @@
 #include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 
+#include "libcef/browser/browser_host_base.h"
+#include "libcef/browser/chrome/browser_platform_delegate_chrome.h"
+#include "libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.h"
+#include "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h"
+#include "libcef/browser/chrome/views/chrome_child_window.h"
 #include "libcef/browser/extensions/browser_platform_delegate_background.h"
+#include "libcef/browser/views/browser_platform_delegate_views.h"
+#include "libcef/features/runtime_checks.h"
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 #include "libcef/browser/native/browser_platform_delegate_native_win.h"
 #include "libcef/browser/osr/browser_platform_delegate_osr_win.h"
-#elif defined(OS_MACOSX)
+#elif BUILDFLAG(IS_MAC)
 #include "libcef/browser/native/browser_platform_delegate_native_mac.h"
 #include "libcef/browser/osr/browser_platform_delegate_osr_mac.h"
-#elif defined(OS_LINUX)
+#elif BUILDFLAG(IS_LINUX)
 #include "libcef/browser/native/browser_platform_delegate_native_linux.h"
 #include "libcef/browser/osr/browser_platform_delegate_osr_linux.h"
 #else
 #error A delegate implementation is not available for your platform.
 #endif
 
-#if defined(USE_AURA)
-#include "libcef/browser/views/browser_platform_delegate_views.h"
-#endif
-
 namespace {
 
 std::unique_ptr<CefBrowserPlatformDelegateNative> CreateNativeDelegate(
     const CefWindowInfo& window_info,
-    SkColor background_color,
-    bool use_shared_texture,
-    bool use_external_begin_frame) {
-#if defined(OS_WIN)
+    SkColor background_color) {
+#if BUILDFLAG(IS_WIN)
   return std::make_unique<CefBrowserPlatformDelegateNativeWin>(
-      window_info, background_color, use_shared_texture,
-      use_external_begin_frame);
-#elif defined(OS_MACOSX)
+      window_info, background_color);
+#elif BUILDFLAG(IS_MAC)
   return std::make_unique<CefBrowserPlatformDelegateNativeMac>(
       window_info, background_color);
-#elif defined(OS_LINUX)
+#elif BUILDFLAG(IS_LINUX)
   return std::make_unique<CefBrowserPlatformDelegateNativeLinux>(
-      window_info, background_color, use_external_begin_frame);
+      window_info, background_color);
 #endif
 }
 
 std::unique_ptr<CefBrowserPlatformDelegateOsr> CreateOSRDelegate(
-    std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate) {
-#if defined(OS_WIN)
+    std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
+    bool use_shared_texture,
+    bool use_external_begin_frame) {
+#if BUILDFLAG(IS_WIN)
   return std::make_unique<CefBrowserPlatformDelegateOsrWin>(
-      std::move(native_delegate));
-#elif defined(OS_MACOSX)
+      std::move(native_delegate), use_shared_texture, use_external_begin_frame);
+#elif BUILDFLAG(IS_MAC)
   return std::make_unique<CefBrowserPlatformDelegateOsrMac>(
       std::move(native_delegate));
-#elif defined(OS_LINUX)
+#elif BUILDFLAG(IS_LINUX)
   return std::make_unique<CefBrowserPlatformDelegateOsrLinux>(
-      std::move(native_delegate));
+      std::move(native_delegate), use_external_begin_frame);
 #endif
 }
 
@@ -68,7 +70,7 @@
 
 // static
 std::unique_ptr<CefBrowserPlatformDelegate> CefBrowserPlatformDelegate::Create(
-    CefBrowserHostImpl::CreateParams& create_params) {
+    const CefBrowserCreateParams& create_params) {
   const bool is_windowless =
       create_params.window_info &&
       create_params.window_info->windowless_rendering_enabled &&
@@ -76,46 +78,66 @@
   const SkColor background_color = CefContext::Get()->GetBackgroundColor(
       &create_params.settings, is_windowless ? STATE_ENABLED : STATE_DISABLED);
 
-  bool use_shared_texture = false;
-  bool use_external_begin_frame = false;
+  if (cef::IsChromeRuntimeEnabled()) {
+    CefWindowInfo window_info;
+    if (create_params.window_info) {
+      window_info = *create_params.window_info;
+    }
 
-  if (is_windowless) {
-    use_shared_texture = create_params.window_info &&
-                         create_params.window_info->shared_texture_enabled;
-
-    use_external_begin_frame =
-        create_params.window_info &&
-        create_params.window_info->external_begin_frame_enabled;
-  }
-
-  if (create_params.window_info) {
     std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate =
-        CreateNativeDelegate(*create_params.window_info.get(), background_color,
-                             use_shared_texture, use_external_begin_frame);
-    if (is_windowless)
-      return CreateOSRDelegate(std::move(native_delegate));
-    return std::move(native_delegate);
-  } else if (create_params.extension_host_type ==
-             extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
-    // Creating a background extension host without a window.
-    std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate =
-        CreateNativeDelegate(CefWindowInfo(), background_color,
-                             use_shared_texture, use_external_begin_frame);
-    return std::make_unique<CefBrowserPlatformDelegateBackground>(
+        CreateNativeDelegate(window_info, background_color);
+
+    if (create_params.window_info) {
+      // CefWindowInfo should only be set if a parent handle was specified.
+      DCHECK(chrome_child_window::HasParentHandle(window_info));
+      return std::make_unique<CefBrowserPlatformDelegateChromeChildWindow>(
+          std::move(native_delegate),
+          static_cast<CefBrowserViewImpl*>(create_params.browser_view.get()));
+    } else if (create_params.browser_view ||
+               create_params.popup_with_views_hosted_opener) {
+      // CefWindowInfo is not used in this case.
+      return std::make_unique<CefBrowserPlatformDelegateChromeViews>(
+          std::move(native_delegate),
+          static_cast<CefBrowserViewImpl*>(create_params.browser_view.get()));
+    }
+
+    return std::make_unique<CefBrowserPlatformDelegateChrome>(
         std::move(native_delegate));
   }
-#if defined(USE_AURA)
-  else {
+
+  if (create_params.browser_view ||
+      create_params.popup_with_views_hosted_opener) {
     // CefWindowInfo is not used in this case.
     std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate =
-        CreateNativeDelegate(CefWindowInfo(), background_color,
-                             use_shared_texture, use_external_begin_frame);
+        CreateNativeDelegate(CefWindowInfo(), background_color);
     return std::make_unique<CefBrowserPlatformDelegateViews>(
         std::move(native_delegate),
         static_cast<CefBrowserViewImpl*>(create_params.browser_view.get()));
-  }
-#endif  // defined(USE_AURA)
+  } else if (create_params.extension_host_type ==
+             extensions::mojom::ViewType::kExtensionBackgroundPage) {
+    // Creating a background extension host without a window.
+    std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate =
+        CreateNativeDelegate(CefWindowInfo(), background_color);
+    return std::make_unique<CefBrowserPlatformDelegateBackground>(
+        std::move(native_delegate));
+  } else if (create_params.window_info) {
+    std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate =
+        CreateNativeDelegate(*create_params.window_info, background_color);
+    if (is_windowless) {
+      REQUIRE_ALLOY_RUNTIME();
 
-  NOTREACHED();
+      const bool use_shared_texture =
+          create_params.window_info->shared_texture_enabled;
+
+      const bool use_external_begin_frame =
+          create_params.window_info->external_begin_frame_enabled;
+
+      return CreateOSRDelegate(std::move(native_delegate), use_shared_texture,
+                               use_external_begin_frame);
+    }
+    return std::move(native_delegate);
+  }
+
+  DCHECK(false);
   return nullptr;
 }
diff --git a/src/libcef/browser/browser_util.cc b/src/libcef/browser/browser_util.cc
index fbe292e..adad370 100644
--- a/src/libcef/browser/browser_util.cc
+++ b/src/libcef/browser/browser_util.cc
@@ -4,23 +4,23 @@
 
 #include "libcef/browser/browser_util.h"
 
-#include "content/public/browser/native_web_keyboard_event.h"
+#include "content/public/common/input/native_web_keyboard_event.h"
 
 namespace browser_util {
 
 bool GetCefKeyEvent(const content::NativeWebKeyboardEvent& event,
                     CefKeyEvent& cef_event) {
   switch (event.GetType()) {
-    case blink::WebKeyboardEvent::kRawKeyDown:
+    case blink::WebKeyboardEvent::Type::kRawKeyDown:
       cef_event.type = KEYEVENT_RAWKEYDOWN;
       break;
-    case blink::WebKeyboardEvent::kKeyDown:
+    case blink::WebKeyboardEvent::Type::kKeyDown:
       cef_event.type = KEYEVENT_KEYDOWN;
       break;
-    case blink::WebKeyboardEvent::kKeyUp:
+    case blink::WebKeyboardEvent::Type::kKeyUp:
       cef_event.type = KEYEVENT_KEYUP;
       break;
-    case blink::WebKeyboardEvent::kChar:
+    case blink::WebKeyboardEvent::Type::kChar:
       cef_event.type = KEYEVENT_CHAR;
       break;
     default:
@@ -28,16 +28,33 @@
   }
 
   cef_event.modifiers = 0;
-  if (event.GetModifiers() & blink::WebKeyboardEvent::kShiftKey)
+  if (event.GetModifiers() & blink::WebKeyboardEvent::kShiftKey) {
     cef_event.modifiers |= EVENTFLAG_SHIFT_DOWN;
-  if (event.GetModifiers() & blink::WebKeyboardEvent::kControlKey)
+  }
+  if (event.GetModifiers() & blink::WebKeyboardEvent::kControlKey) {
     cef_event.modifiers |= EVENTFLAG_CONTROL_DOWN;
-  if (event.GetModifiers() & blink::WebKeyboardEvent::kAltKey)
+  }
+  if (event.GetModifiers() & blink::WebKeyboardEvent::kAltKey) {
     cef_event.modifiers |= EVENTFLAG_ALT_DOWN;
-  if (event.GetModifiers() & blink::WebKeyboardEvent::kMetaKey)
+  }
+  if (event.GetModifiers() & blink::WebKeyboardEvent::kMetaKey) {
     cef_event.modifiers |= EVENTFLAG_COMMAND_DOWN;
-  if (event.GetModifiers() & blink::WebKeyboardEvent::kIsKeyPad)
+  }
+  if (event.GetModifiers() & blink::WebKeyboardEvent::kIsKeyPad) {
     cef_event.modifiers |= EVENTFLAG_IS_KEY_PAD;
+  }
+  if (event.GetModifiers() & blink::WebKeyboardEvent::kIsLeft) {
+    cef_event.modifiers |= EVENTFLAG_IS_LEFT;
+  }
+  if (event.GetModifiers() & blink::WebKeyboardEvent::kIsRight) {
+    cef_event.modifiers |= EVENTFLAG_IS_RIGHT;
+  }
+  if (event.GetModifiers() & blink::WebKeyboardEvent::kAltGrKey) {
+    cef_event.modifiers |= EVENTFLAG_ALTGR_DOWN;
+  }
+  if (event.GetModifiers() & blink::WebKeyboardEvent::kIsAutoRepeat) {
+    cef_event.modifiers |= EVENTFLAG_IS_REPEAT;
+  }
 
   cef_event.windows_key_code = event.windows_key_code;
   cef_event.native_key_code = event.native_key_code;
diff --git a/src/libcef/browser/certificate_query.cc b/src/libcef/browser/certificate_query.cc
new file mode 100644
index 0000000..ca78798
--- /dev/null
+++ b/src/libcef/browser/certificate_query.cc
@@ -0,0 +1,130 @@
+// Copyright 2022 The Chromium Embedded Framework 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 "libcef/browser/certificate_query.h"
+
+#include "include/cef_request_handler.h"
+#include "libcef/browser/browser_host_base.h"
+#include "libcef/browser/ssl_info_impl.h"
+#include "libcef/browser/thread_util.h"
+
+#include "base/functional/callback.h"
+#include "base/functional/callback_helpers.h"
+#include "base/logging.h"
+#include "content/public/browser/web_contents.h"
+#include "net/ssl/ssl_info.h"
+#include "url/gurl.h"
+
+namespace certificate_query {
+
+namespace {
+
+class CefAllowCertificateErrorCallbackImpl : public CefCallback {
+ public:
+  using CallbackType = CertificateErrorCallback;
+
+  explicit CefAllowCertificateErrorCallbackImpl(CallbackType callback)
+      : callback_(std::move(callback)) {}
+
+  CefAllowCertificateErrorCallbackImpl(
+      const CefAllowCertificateErrorCallbackImpl&) = delete;
+  CefAllowCertificateErrorCallbackImpl& operator=(
+      const CefAllowCertificateErrorCallbackImpl&) = delete;
+
+  ~CefAllowCertificateErrorCallbackImpl() {
+    if (!callback_.is_null()) {
+      // The callback is still pending. Cancel it now.
+      if (CEF_CURRENTLY_ON_UIT()) {
+        RunNow(std::move(callback_), false);
+      } else {
+        CEF_POST_TASK(
+            CEF_UIT,
+            base::BindOnce(&CefAllowCertificateErrorCallbackImpl::RunNow,
+                           std::move(callback_), false));
+      }
+    }
+  }
+
+  void Continue() override { ContinueNow(true); }
+
+  void Cancel() override { ContinueNow(false); }
+
+  [[nodiscard]] CallbackType Disconnect() { return std::move(callback_); }
+
+ private:
+  void ContinueNow(bool allow) {
+    if (CEF_CURRENTLY_ON_UIT()) {
+      if (!callback_.is_null()) {
+        RunNow(std::move(callback_), allow);
+      }
+    } else {
+      CEF_POST_TASK(
+          CEF_UIT,
+          base::BindOnce(&CefAllowCertificateErrorCallbackImpl::ContinueNow,
+                         this, allow));
+    }
+  }
+
+  static void RunNow(CallbackType callback, bool allow) {
+    CEF_REQUIRE_UIT();
+    std::move(callback).Run(
+        allow ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE
+              : content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
+  }
+
+  CallbackType callback_;
+
+  IMPLEMENT_REFCOUNTING(CefAllowCertificateErrorCallbackImpl);
+};
+
+}  // namespace
+
+CertificateErrorCallback AllowCertificateError(
+    content::WebContents* web_contents,
+    int cert_error,
+    const net::SSLInfo& ssl_info,
+    const GURL& request_url,
+    bool is_main_frame_request,
+    bool strict_enforcement,
+    CertificateErrorCallback callback,
+    bool default_disallow) {
+  CEF_REQUIRE_UIT();
+
+  if (!is_main_frame_request) {
+    // A sub-resource has a certificate error. The user doesn't really
+    // have a context for making the right decision, so block the request
+    // hard.
+    std::move(callback).Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
+    return base::NullCallback();
+  }
+
+  if (auto browser = CefBrowserHostBase::GetBrowserForContents(web_contents)) {
+    if (auto client = browser->GetClient()) {
+      if (auto handler = client->GetRequestHandler()) {
+        CefRefPtr<CefSSLInfo> sslInfo(new CefSSLInfoImpl(ssl_info));
+        CefRefPtr<CefAllowCertificateErrorCallbackImpl> callbackImpl(
+            new CefAllowCertificateErrorCallbackImpl(std::move(callback)));
+
+        bool proceed = handler->OnCertificateError(
+            browser.get(), static_cast<cef_errorcode_t>(cert_error),
+            request_url.spec(), sslInfo, callbackImpl.get());
+        if (!proceed) {
+          callback = callbackImpl->Disconnect();
+          LOG_IF(ERROR, callback.is_null())
+              << "Should return true from OnCertificateError when executing "
+                 "the callback";
+        }
+      }
+    }
+  }
+
+  if (!callback.is_null() && default_disallow) {
+    std::move(callback).Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
+    return base::NullCallback();
+  }
+
+  return callback;
+}
+
+}  // namespace certificate_query
diff --git a/src/libcef/browser/certificate_query.h b/src/libcef/browser/certificate_query.h
new file mode 100644
index 0000000..f2e6b53
--- /dev/null
+++ b/src/libcef/browser/certificate_query.h
@@ -0,0 +1,42 @@
+// Copyright 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_CERTIFICATE_QUERY_H_
+#define CEF_LIBCEF_BROWSER_CERTIFICATE_QUERY_H_
+#pragma once
+
+#include "base/functional/callback_forward.h"
+#include "content/public/browser/certificate_request_result_type.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace net {
+class SSLInfo;
+}
+
+class GURL;
+
+namespace certificate_query {
+
+using CertificateErrorCallback =
+    base::OnceCallback<void(content::CertificateRequestResultType)>;
+
+// Called from ContentBrowserClient::AllowCertificateError.
+// |callback| will be returned if the request is unhandled and
+// |default_disallow| is false.
+[[nodiscard]] CertificateErrorCallback AllowCertificateError(
+    content::WebContents* web_contents,
+    int cert_error,
+    const net::SSLInfo& ssl_info,
+    const GURL& request_url,
+    bool is_main_frame_request,
+    bool strict_enforcement,
+    CertificateErrorCallback callback,
+    bool default_disallow);
+
+}  // namespace certificate_query
+
+#endif  // CEF_LIBCEF_BROWSER_CERTIFICATE_QUERY_H_
diff --git a/src/libcef/browser/chrome/browser_delegate.h b/src/libcef/browser/chrome/browser_delegate.h
new file mode 100644
index 0000000..5e9b53d
--- /dev/null
+++ b/src/libcef/browser/chrome/browser_delegate.h
@@ -0,0 +1,145 @@
+// Copyright 2020 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_CHROME_BROWSER_DELEGATE_H_
+#define CEF_LIBCEF_BROWSER_CHROME_BROWSER_DELEGATE_H_
+#pragma once
+
+#include <memory>
+
+#include "base/memory/scoped_refptr.h"
+#include "chrome/browser/ui/page_action/page_action_icon_type.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/skia/include/core/SkRegion.h"
+#include "ui/base/window_open_disposition.h"
+
+class Browser;
+class Profile;
+
+namespace cef {
+
+// Delegate for the chrome Browser object. Lifespan is controlled by the Browser
+// object. See the ChromeBrowserDelegate documentation for additional details.
+// Only accessed on the UI thread.
+class BrowserDelegate : public content::WebContentsDelegate {
+ public:
+  // Opaque ref-counted base class for CEF-specific parameters passed via
+  // Browser::CreateParams::cef_params and possibly shared by multiple Browser
+  // instances.
+  class CreateParams : public base::RefCounted<CreateParams> {
+   public:
+    virtual ~CreateParams() {}
+  };
+
+  // Called from the Browser constructor to create a new delegate.
+  static std::unique_ptr<BrowserDelegate> Create(
+      Browser* browser,
+      scoped_refptr<CreateParams> cef_params,
+      const Browser* opener);
+
+  ~BrowserDelegate() override {}
+
+  // Optionally override Browser creation in
+  // DevToolsWindow::CreateDevToolsBrowser. The returned Browser, if any, will
+  // take ownership of |devtools_contents|.
+  virtual Browser* CreateDevToolsBrowser(
+      Profile* profile,
+      Browser* opener,
+      std::unique_ptr<content::WebContents>& devtools_contents) = 0;
+
+  // Optionally override chrome::AddWebContents behavior. This is most often
+  // called via Browser::AddNewContents for new popup browsers and provides an
+  // opportunity for CEF to create a new Browser instead of proceeding with
+  // default Browser or tab creation.
+  virtual std::unique_ptr<content::WebContents> AddWebContents(
+      std::unique_ptr<content::WebContents> new_contents) = 0;
+
+  // Called immediately after |new_contents| is created via chrome::Navigate.
+  // This is most often called for navigations targeting a new tab without a
+  // pre-existing WebContents.
+  virtual void OnWebContentsCreated(content::WebContents* new_contents) = 0;
+
+  // Add or remove ownership of the WebContents.
+  virtual void SetAsDelegate(content::WebContents* web_contents,
+                             bool set_delegate) = 0;
+
+  // Return true to show the status bubble. This should consistently return the
+  // same value for the lifespan of a Browser.
+  virtual bool ShowStatusBubble(bool show_by_default) {
+    return show_by_default;
+  }
+
+  // Return true to handle (or disable) a command. ID values come from
+  // chrome/app/chrome_command_ids.h.
+  virtual bool HandleCommand(int command_id,
+                             WindowOpenDisposition disposition) {
+    return false;
+  }
+
+  // Return true if the app menu item should be visible. ID values come from
+  // chrome/app/chrome_command_ids.h.
+  virtual bool IsAppMenuItemVisible(int command_id) { return true; }
+
+  // Return true if the app menu item should be enabled. ID values come from
+  // chrome/app/chrome_command_ids.h.
+  virtual bool IsAppMenuItemEnabled(int command_id) { return true; }
+
+  // Return true if the page action icon should be visible.
+  virtual bool IsPageActionIconVisible(PageActionIconType icon_type) {
+    return true;
+  }
+
+  enum class ToolbarButtonType {
+    kCast = 0,
+    kDownload,
+    kSendTabToSelf,
+    kSidePanel,
+    kMaxValue = kSidePanel,
+  };
+
+  // Return true if the toolbar button should be visible.
+  virtual bool IsToolbarButtonVisible(ToolbarButtonType button_type) {
+    return true;
+  }
+
+  // Optionally modify the bounding box for the Find bar.
+  virtual void UpdateFindBarBoundingBox(gfx::Rect* bounds) {}
+
+  // Same as RequestMediaAccessPermission but returning |callback| if the
+  // request is unhandled.
+  [[nodiscard]] virtual content::MediaResponseCallback
+  RequestMediaAccessPermissionEx(content::WebContents* web_contents,
+                                 const content::MediaStreamRequest& request,
+                                 content::MediaResponseCallback callback) {
+    return callback;
+  }
+
+  // Optionally override support for the specified window feature of type
+  // Browser::WindowFeature.
+  virtual absl::optional<bool> SupportsWindowFeature(int feature) const {
+    return absl::nullopt;
+  }
+
+  // Returns true if draggable regions are supported.
+  virtual bool SupportsDraggableRegion() const { return false; }
+
+  // Returns the draggable region, if any, relative to the web contents.
+  // Called from PictureInPictureBrowserFrameView::NonClientHitTest and
+  // BrowserView::ShouldDescendIntoChildForEventHandling.
+  virtual const absl::optional<SkRegion> GetDraggableRegion() const {
+    return absl::nullopt;
+  }
+
+  // Set the draggable region relative to web contents.
+  // Called from DraggableRegionsHostImpl::UpdateDraggableRegions.
+  virtual void UpdateDraggableRegion(const SkRegion& region) {}
+
+  // Called at the end of a fullscreen transition.
+  virtual void WindowFullscreenStateChanged() {}
+};
+
+}  // namespace cef
+
+#endif  // CEF_LIBCEF_BROWSER_CHROME_BROWSER_DELEGATE_H_
diff --git a/src/libcef/browser/chrome/browser_platform_delegate_chrome.cc b/src/libcef/browser/chrome/browser_platform_delegate_chrome.cc
new file mode 100644
index 0000000..83b8de0
--- /dev/null
+++ b/src/libcef/browser/chrome/browser_platform_delegate_chrome.cc
@@ -0,0 +1,148 @@
+// Copyright 2020 The Chromium Embedded Framework 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 "libcef/browser/chrome/browser_platform_delegate_chrome.h"
+
+#include "libcef/browser/views/view_util.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h"
+#include "chrome/common/pref_names.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
+#include "ui/gfx/geometry/point.h"
+
+CefBrowserPlatformDelegateChrome::CefBrowserPlatformDelegateChrome(
+    std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate)
+    : native_delegate_(std::move(native_delegate)) {
+  native_delegate_->set_windowless_handler(this);
+}
+
+void CefBrowserPlatformDelegateChrome::WebContentsCreated(
+    content::WebContents* web_contents,
+    bool owned) {
+  CefBrowserPlatformDelegate::WebContentsCreated(web_contents, owned);
+  native_delegate_->WebContentsCreated(web_contents, /*owned=*/false);
+}
+
+void CefBrowserPlatformDelegateChrome::WebContentsDestroyed(
+    content::WebContents* web_contents) {
+  CefBrowserPlatformDelegate::WebContentsDestroyed(web_contents);
+  native_delegate_->WebContentsDestroyed(web_contents);
+}
+
+void CefBrowserPlatformDelegateChrome::BrowserCreated(
+    CefBrowserHostBase* browser) {
+  CefBrowserPlatformDelegate::BrowserCreated(browser);
+  native_delegate_->BrowserCreated(browser);
+}
+
+void CefBrowserPlatformDelegateChrome::BrowserDestroyed(
+    CefBrowserHostBase* browser) {
+  CefBrowserPlatformDelegate::BrowserDestroyed(browser);
+  native_delegate_->BrowserDestroyed(browser);
+}
+
+CefWindowHandle CefBrowserPlatformDelegateChrome::GetHostWindowHandle() const {
+  return view_util::GetWindowHandle(GetNativeWindow());
+}
+
+web_modal::WebContentsModalDialogHost*
+CefBrowserPlatformDelegateChrome::GetWebContentsModalDialogHost() const {
+  if (chrome_browser_) {
+    ChromeWebModalDialogManagerDelegate* manager = chrome_browser_;
+    return manager->GetWebContentsModalDialogHost();
+  }
+  DCHECK(false);
+  return nullptr;
+}
+
+SkColor CefBrowserPlatformDelegateChrome::GetBackgroundColor() const {
+  return native_delegate_->GetBackgroundColor();
+}
+
+void CefBrowserPlatformDelegateChrome::SendKeyEvent(const CefKeyEvent& event) {
+  native_delegate_->SendKeyEvent(event);
+}
+
+void CefBrowserPlatformDelegateChrome::SendMouseClickEvent(
+    const CefMouseEvent& event,
+    CefBrowserHost::MouseButtonType type,
+    bool mouseUp,
+    int clickCount) {
+  native_delegate_->SendMouseClickEvent(event, type, mouseUp, clickCount);
+}
+
+void CefBrowserPlatformDelegateChrome::SendMouseMoveEvent(
+    const CefMouseEvent& event,
+    bool mouseLeave) {
+  native_delegate_->SendMouseMoveEvent(event, mouseLeave);
+}
+
+void CefBrowserPlatformDelegateChrome::SendMouseWheelEvent(
+    const CefMouseEvent& event,
+    int deltaX,
+    int deltaY) {
+  native_delegate_->SendMouseWheelEvent(event, deltaX, deltaY);
+}
+
+gfx::Point CefBrowserPlatformDelegateChrome::GetScreenPoint(
+    const gfx::Point& view,
+    bool want_dip_coords) const {
+  auto screen = display::Screen::GetScreen();
+
+  // Get device (pixel) coordinates.
+  auto screen_rect = screen->DIPToScreenRectInWindow(
+      GetNativeWindow(), gfx::Rect(view, gfx::Size(0, 0)));
+  auto screen_point = screen_rect.origin();
+
+  if (want_dip_coords) {
+    // Convert to DIP coordinates.
+    const auto& display = view_util::GetDisplayNearestPoint(
+        screen_point, /*input_pixel_coords=*/true);
+    view_util::ConvertPointFromPixels(&screen_point,
+                                      display.device_scale_factor());
+  }
+
+  return screen_point;
+}
+
+void CefBrowserPlatformDelegateChrome::ViewText(const std::string& text) {
+  native_delegate_->ViewText(text);
+}
+
+CefEventHandle CefBrowserPlatformDelegateChrome::GetEventHandle(
+    const content::NativeWebKeyboardEvent& event) const {
+  return native_delegate_->GetEventHandle(event);
+}
+
+bool CefBrowserPlatformDelegateChrome::IsPrintPreviewSupported() const {
+  return chrome_browser_ && !chrome_browser_->profile()->GetPrefs()->GetBoolean(
+                                prefs::kPrintPreviewDisabled);
+}
+
+CefWindowHandle CefBrowserPlatformDelegateChrome::GetParentWindowHandle()
+    const {
+  return GetHostWindowHandle();
+}
+
+gfx::Point CefBrowserPlatformDelegateChrome::GetParentScreenPoint(
+    const gfx::Point& view,
+    bool want_dip_coords) const {
+  return GetScreenPoint(view, want_dip_coords);
+}
+
+void CefBrowserPlatformDelegateChrome::set_chrome_browser(Browser* browser) {
+  chrome_browser_ = browser;
+}
+
+gfx::NativeWindow CefBrowserPlatformDelegateChrome::GetNativeWindow() const {
+  if (chrome_browser_ && chrome_browser_->window()) {
+    return chrome_browser_->window()->GetNativeWindow();
+  }
+  DCHECK(false);
+  return gfx::NativeWindow();
+}
diff --git a/src/libcef/browser/chrome/browser_platform_delegate_chrome.h b/src/libcef/browser/chrome/browser_platform_delegate_chrome.h
new file mode 100644
index 0000000..4f13ace
--- /dev/null
+++ b/src/libcef/browser/chrome/browser_platform_delegate_chrome.h
@@ -0,0 +1,66 @@
+// Copyright 2020 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_CHROME_BROWSER_PLATFORM_DELEGATE_CHROME_H_
+#define CEF_LIBCEF_BROWSER_CHROME_BROWSER_PLATFORM_DELEGATE_CHROME_H_
+
+#include "libcef/browser/browser_platform_delegate.h"
+#include "libcef/browser/native/browser_platform_delegate_native.h"
+
+class Browser;
+
+// Implementation of Chrome-based browser functionality.
+class CefBrowserPlatformDelegateChrome
+    : public CefBrowserPlatformDelegate,
+      public CefBrowserPlatformDelegateNative::WindowlessHandler {
+ public:
+  explicit CefBrowserPlatformDelegateChrome(
+      std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate);
+
+  // CefBrowserPlatformDelegate overrides.
+  void WebContentsCreated(content::WebContents* web_contents,
+                          bool owned) override;
+  void WebContentsDestroyed(content::WebContents* web_contents) override;
+  void BrowserCreated(CefBrowserHostBase* browser) override;
+  void BrowserDestroyed(CefBrowserHostBase* browser) override;
+  CefWindowHandle GetHostWindowHandle() const override;
+  web_modal::WebContentsModalDialogHost* GetWebContentsModalDialogHost()
+      const override;
+  SkColor GetBackgroundColor() const override;
+  void SendKeyEvent(const CefKeyEvent& event) override;
+  void SendMouseClickEvent(const CefMouseEvent& event,
+                           CefBrowserHost::MouseButtonType type,
+                           bool mouseUp,
+                           int clickCount) override;
+  void SendMouseMoveEvent(const CefMouseEvent& event, bool mouseLeave) override;
+  void SendMouseWheelEvent(const CefMouseEvent& event,
+                           int deltaX,
+                           int deltaY) override;
+  gfx::Point GetScreenPoint(const gfx::Point& view,
+                            bool want_dip_coords) const override;
+  void ViewText(const std::string& text) override;
+  CefEventHandle GetEventHandle(
+      const content::NativeWebKeyboardEvent& event) const override;
+  bool IsPrintPreviewSupported() const override;
+
+  // CefBrowserPlatformDelegateNative::WindowlessHandler methods:
+  CefWindowHandle GetParentWindowHandle() const override;
+  gfx::Point GetParentScreenPoint(const gfx::Point& view,
+                                  bool want_dip_coords) const override;
+
+  void set_chrome_browser(Browser* browser);
+
+  CefBrowserPlatformDelegateNative* native_delegate() const {
+    return native_delegate_.get();
+  }
+
+ protected:
+  gfx::NativeWindow GetNativeWindow() const;
+
+  std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate_;
+
+  Browser* chrome_browser_ = nullptr;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_CHROME_BROWSER_PLATFORM_DELEGATE_CHROME_H_
diff --git a/src/libcef/browser/chrome/chrome_browser_context.cc b/src/libcef/browser/chrome/chrome_browser_context.cc
new file mode 100644
index 0000000..c35b733
--- /dev/null
+++ b/src/libcef/browser/chrome/chrome_browser_context.cc
@@ -0,0 +1,187 @@
+// Copyright 2020 The Chromium Embedded Framework 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 "libcef/browser/chrome/chrome_browser_context.h"
+
+#include "libcef/browser/prefs/browser_prefs.h"
+#include "libcef/browser/thread_util.h"
+
+#include "base/threading/thread_restrictions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h"
+#include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h"
+#include "chrome/browser/profiles/off_the_record_profile_impl.h"
+#include "chrome/common/pref_names.h"
+
+namespace {
+
+// Match the default logic from ProfileManager::GetPrimaryUserProfile which was
+// restricted in https://crbug.com/1264436.
+Profile* GetPrimaryUserProfile() {
+  ProfileManager* profile_manager = g_browser_process->profile_manager();
+
+  // From ProfileManager::GetActiveUserOrOffTheRecordProfile.
+  base::FilePath default_profile_dir = profile_manager->user_data_dir().Append(
+      profile_manager->GetInitialProfileDir());
+  return profile_manager->GetProfile(default_profile_dir);
+}
+
+}  // namespace
+
+ChromeBrowserContext::ChromeBrowserContext(
+    const CefRequestContextSettings& settings)
+    : CefBrowserContext(settings), weak_ptr_factory_(this) {}
+
+ChromeBrowserContext::~ChromeBrowserContext() = default;
+
+content::BrowserContext* ChromeBrowserContext::AsBrowserContext() {
+  CHECK(!destroyed_);
+  return profile_;
+}
+
+Profile* ChromeBrowserContext::AsProfile() {
+  CHECK(!destroyed_);
+  return profile_;
+}
+
+bool ChromeBrowserContext::IsInitialized() const {
+  CEF_REQUIRE_UIT();
+  CHECK(!destroyed_);
+  return !!profile_;
+}
+
+void ChromeBrowserContext::StoreOrTriggerInitCallback(
+    base::OnceClosure callback) {
+  CEF_REQUIRE_UIT();
+  if (IsInitialized()) {
+    std::move(callback).Run();
+  } else {
+    init_callbacks_.emplace_back(std::move(callback));
+  }
+}
+
+void ChromeBrowserContext::InitializeAsync(base::OnceClosure initialized_cb) {
+  init_callbacks_.emplace_back(std::move(initialized_cb));
+
+  CefBrowserContext::Initialize();
+
+  if (!cache_path_.empty()) {
+    auto* profile_manager = g_browser_process->profile_manager();
+    const auto& user_data_dir = profile_manager->user_data_dir();
+
+    if (cache_path_ == user_data_dir) {
+      // Use the default disk-based profile.
+      auto profile = GetPrimaryUserProfile();
+      ProfileCreated(Profile::CreateStatus::CREATE_STATUS_INITIALIZED, profile);
+      return;
+    } else if (cache_path_.DirName() == user_data_dir) {
+      // Create or load a specific disk-based profile. May continue
+      // synchronously or asynchronously.
+      profile_manager->CreateProfileAsync(
+          cache_path_,
+          base::BindOnce(&ChromeBrowserContext::ProfileCreated,
+                         weak_ptr_factory_.GetWeakPtr(),
+                         Profile::CreateStatus::CREATE_STATUS_INITIALIZED),
+          base::BindOnce(&ChromeBrowserContext::ProfileCreated,
+                         weak_ptr_factory_.GetWeakPtr(),
+                         Profile::CreateStatus::CREATE_STATUS_CREATED));
+      return;
+    } else {
+      // All profile directories must be relative to |user_data_dir|.
+      LOG(ERROR) << "Cannot create profile at path "
+                 << cache_path_.AsUTF8Unsafe();
+    }
+  }
+
+  // Default to creating a new/unique OffTheRecord profile.
+  ProfileCreated(Profile::CreateStatus::CREATE_STATUS_LOCAL_FAIL, nullptr);
+}
+
+void ChromeBrowserContext::Shutdown() {
+  CefBrowserContext::Shutdown();
+
+  // Allow potential deletion of the Profile at some future point (controlled
+  // by ProfileManager).
+  profile_keep_alive_.reset();
+
+  // |g_browser_process| may be nullptr during shutdown.
+  if (g_browser_process) {
+    if (should_destroy_) {
+      GetPrimaryUserProfile()->DestroyOffTheRecordProfile(profile_);
+    } else if (profile_) {
+      OnProfileWillBeDestroyed(profile_);
+    }
+  }
+}
+
+void ChromeBrowserContext::ProfileCreated(Profile::CreateStatus status,
+                                          Profile* profile) {
+  Profile* parent_profile = nullptr;
+  OffTheRecordProfileImpl* otr_profile = nullptr;
+
+  if (status != Profile::CreateStatus::CREATE_STATUS_CREATED &&
+      status != Profile::CreateStatus::CREATE_STATUS_INITIALIZED) {
+    CHECK(!profile);
+    CHECK(!profile_);
+
+    // Profile creation may access the filesystem.
+    base::ScopedAllowBlockingForTesting allow_blocking;
+
+    // Creation of a disk-based profile failed for some reason. Create a
+    // new/unique OffTheRecord profile instead.
+    const auto& profile_id = Profile::OTRProfileID::CreateUniqueForCEF();
+    parent_profile = GetPrimaryUserProfile();
+    profile_ = parent_profile->GetOffTheRecordProfile(
+        profile_id, /*create_if_needed=*/true);
+    otr_profile = static_cast<OffTheRecordProfileImpl*>(profile_);
+    status = Profile::CreateStatus::CREATE_STATUS_INITIALIZED;
+    should_destroy_ = true;
+  } else if (profile && !profile_) {
+    // May be CREATE_STATUS_CREATED or CREATE_STATUS_INITIALIZED since
+    // *CREATED isn't always sent for a disk-based profile that already
+    // exists.
+    profile_ = profile;
+    profile_->AddObserver(this);
+    profile_keep_alive_.reset(new ScopedProfileKeepAlive(
+        profile_, ProfileKeepAliveOrigin::kAppWindow));
+  }
+
+  if (status == Profile::CreateStatus::CREATE_STATUS_INITIALIZED) {
+    CHECK(profile_);
+
+    // Must set |profile_| before Init() calls
+    // ChromeContentBrowserClientCef::ConfigureNetworkContextParams so that
+    // CefBrowserContext::FromBrowserContext can find us.
+    if (otr_profile) {
+      otr_profile->Init();
+      parent_profile->NotifyOffTheRecordProfileCreated(otr_profile);
+    }
+
+    if (!profile_->IsOffTheRecord()) {
+      // Configure the desired profile restore behavior for the next application
+      // restart (checked via ProfileImpl::ShouldRestoreOldSessionCookies).
+      profile_->GetPrefs()->SetInteger(
+          prefs::kRestoreOnStartup, !!settings_.persist_session_cookies
+                                        ? SessionStartupPref::kPrefValueLast
+                                        : SessionStartupPref::kPrefValueNewTab);
+    }
+
+    browser_prefs::SetInitialProfilePrefs(profile_);
+
+    if (!init_callbacks_.empty()) {
+      for (auto& callback : init_callbacks_) {
+        std::move(callback).Run();
+      }
+      init_callbacks_.clear();
+    }
+  }
+}
+
+void ChromeBrowserContext::OnProfileWillBeDestroyed(Profile* profile) {
+  CHECK_EQ(profile_, profile);
+  profile_->RemoveObserver(this);
+  profile_ = nullptr;
+  destroyed_ = true;
+}
diff --git a/src/libcef/browser/chrome/chrome_browser_context.h b/src/libcef/browser/chrome/chrome_browser_context.h
new file mode 100644
index 0000000..0bac7fd
--- /dev/null
+++ b/src/libcef/browser/chrome/chrome_browser_context.h
@@ -0,0 +1,55 @@
+// Copyright 2020 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_CONTEXT_H_
+#define CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_CONTEXT_H_
+#pragma once
+
+#include "libcef/browser/browser_context.h"
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/profiles/profile_observer.h"
+
+class ScopedProfileKeepAlive;
+
+// See CefBrowserContext documentation for usage. Only accessed on the UI thread
+// unless otherwise indicated.
+class ChromeBrowserContext : public CefBrowserContext, public ProfileObserver {
+ public:
+  explicit ChromeBrowserContext(const CefRequestContextSettings& settings);
+
+  ChromeBrowserContext(const ChromeBrowserContext&) = delete;
+  ChromeBrowserContext& operator=(const ChromeBrowserContext&) = delete;
+
+  void InitializeAsync(base::OnceClosure initialized_cb);
+
+  // CefBrowserContext overrides.
+  content::BrowserContext* AsBrowserContext() override;
+  Profile* AsProfile() override;
+  bool IsInitialized() const override;
+  void StoreOrTriggerInitCallback(base::OnceClosure callback) override;
+  void Shutdown() override;
+
+  // ProfileObserver overrides.
+  void OnProfileWillBeDestroyed(Profile* profile) override;
+
+ private:
+  ~ChromeBrowserContext() override;
+
+  void ProfileCreated(Profile::CreateStatus status, Profile* profile);
+
+  base::OnceClosure initialized_cb_;
+  Profile* profile_ = nullptr;
+  bool should_destroy_ = false;
+
+  bool destroyed_ = false;
+  std::unique_ptr<ScopedProfileKeepAlive> profile_keep_alive_;
+
+  std::vector<base::OnceClosure> init_callbacks_;
+
+  base::WeakPtrFactory<ChromeBrowserContext> weak_ptr_factory_;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_CONTEXT_H_
diff --git a/src/libcef/browser/chrome/chrome_browser_delegate.cc b/src/libcef/browser/chrome/chrome_browser_delegate.cc
new file mode 100644
index 0000000..083073f
--- /dev/null
+++ b/src/libcef/browser/chrome/chrome_browser_delegate.cc
@@ -0,0 +1,687 @@
+// Copyright 2020 The Chromium Embedded Framework Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+
+#include "libcef/browser/chrome/chrome_browser_delegate.h"
+
+#include "libcef/browser/browser_contents_delegate.h"
+#include "libcef/browser/browser_host_base.h"
+#include "libcef/browser/browser_info_manager.h"
+#include "libcef/browser/browser_platform_delegate.h"
+#include "libcef/browser/chrome/chrome_browser_host_impl.h"
+#include "libcef/browser/chrome/views/chrome_browser_view.h"
+#include "libcef/browser/chrome/views/chrome_child_window.h"
+#include "libcef/browser/media_access_query.h"
+#include "libcef/browser/request_context_impl.h"
+#include "libcef/browser/views/browser_view_impl.h"
+#include "libcef/browser/views/window_impl.h"
+#include "libcef/common/app_manager.h"
+#include "libcef/common/frame_util.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "content/public/browser/global_routing_id.h"
+#include "content/public/browser/keyboard_event_processing_result.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/common/input/native_web_keyboard_event.h"
+
+using content::KeyboardEventProcessingResult;
+
+ChromeBrowserDelegate::ChromeBrowserDelegate(
+    Browser* browser,
+    const CefBrowserCreateParams& create_params,
+    const Browser* opener)
+    : browser_(browser), create_params_(create_params) {
+  DCHECK(browser_);
+
+  if (opener) {
+    DCHECK(browser->is_type_picture_in_picture() ||
+           browser->is_type_devtools());
+    auto opener_host = ChromeBrowserHostImpl::GetBrowserForBrowser(opener);
+    DCHECK(opener_host);
+    if (opener_host) {
+      opener_host_ = opener_host->GetWeakPtr();
+    }
+  }
+}
+
+ChromeBrowserDelegate::~ChromeBrowserDelegate() = default;
+
+Browser* ChromeBrowserDelegate::CreateDevToolsBrowser(
+    Profile* profile,
+    Browser* opener,
+    std::unique_ptr<content::WebContents>& devtools_contents) {
+  // |opener| is the same value that will be passed to the ChromeBrowserDelegate
+  // constructor for the new popup Browser. It may be nullptr in certain rare
+  // situations (e.g. if DevTools is launched for a WebContents that is not a
+  // Browser Tab). In that case, the popup browser host will instead be created
+  // via SetAsDelegate.
+  auto opener_browser_host =
+      opener ? ChromeBrowserHostImpl::GetBrowserForBrowser(opener) : nullptr;
+  if (!opener_browser_host) {
+    return nullptr;
+  }
+
+  // We expect openers and popups to have the same Profile.
+  CHECK_EQ(
+      CefRequestContextImpl::GetProfile(opener_browser_host->request_context()),
+      profile);
+
+  //
+  // 1. Get configuration settings from the user and create the new platform
+  // delegate. Logical equivalent of CefBrowserInfoManager::CanCreateWindow()
+  // for normal popups.
+  //
+
+  auto opener_client = opener_browser_host->GetClient();
+  auto life_span_handler =
+      opener_client ? opener_client->GetLifeSpanHandler() : nullptr;
+
+  CefBrowserCreateParams create_params;
+  CefWindowInfo window_info;
+
+  // If |client| is empty, or if the user clears |client| in
+  // OnBeforeDevToolsPopup, we'll use the result of GetDefaultClient() later on
+  // in CreateBrowserHost().
+  if (pending_show_devtools_params_) {
+    // Start with the params passed to CefBrowserHost::ShowDevTools().
+    create_params.client = pending_show_devtools_params_->client_;
+    create_params.settings = pending_show_devtools_params_->settings_;
+    window_info = pending_show_devtools_params_->window_info_;
+
+    // Pending params are only used a single time.
+    pending_show_devtools_params_.reset();
+  } else {
+    // Start with the same client and settings as the opener.
+    create_params.client = opener_client;
+    create_params.settings = opener_browser_host->settings();
+
+#if BUILDFLAG(IS_WIN)
+    window_info.SetAsPopup(nullptr, CefString());
+#endif
+  }
+
+  // Start with the same extra info as the opener, for consistency with
+  // current Alloy runtime behavior (see CefDevToolsFrontend::Show). This
+  // value, if non-empty, will be read-only.
+  create_params.extra_info = opener_browser_host->browser_info()->extra_info();
+  DCHECK(!create_params.extra_info || create_params.extra_info->IsReadOnly());
+
+  // Use default (non-Views-hosted) window if OnBeforeDevToolsPopup is
+  // unhandled.
+  bool use_default_window = !life_span_handler;
+
+  if (life_span_handler) {
+    life_span_handler->OnBeforeDevToolsPopup(
+        opener_browser_host.get(), window_info, create_params.client,
+        create_params.settings, create_params.extra_info, &use_default_window);
+  }
+
+  if (opener_browser_host->platform_delegate()->HasExternalParent()) {
+    // A parent window handle for DevTools creation is only supported if the
+    // opener also has an external parent.
+    create_params.MaybeSetWindowInfo(window_info);
+  } else if (chrome_child_window::HasParentHandle(window_info)) {
+    LOG(ERROR) << "Parent window handle not supported for this DevTools window";
+  }
+
+  create_params.popup_with_views_hosted_opener =
+      CefBrowserInfoManager::ShouldCreateViewsHostedPopup(opener_browser_host,
+                                                          use_default_window);
+
+  auto platform_delegate = CefBrowserPlatformDelegate::Create(create_params);
+  CHECK(platform_delegate);
+
+  //
+  // 2. Create the new browser host. Logical equivalent of WebContentsCreated()
+  // for normal popups.
+  //
+
+  // Create a new browser host that remains alive until the associated
+  // WebContents is destroyed. Associate that browser host with the WebContents
+  // and execute initial client callbacks. Deliver required information to the
+  // renderer process.
+  auto browser_host = CreateBrowserHostForPopup(
+      devtools_contents.get(), create_params.settings, create_params.client,
+      create_params.extra_info, std::move(platform_delegate),
+      /*is_devtools_popup=*/true, opener_browser_host);
+
+  //
+  // 3. Create the new Browser. Logical equivalent of AddWebContents() for
+  // normal popups.
+  //
+
+  // Use Browser creation params specific to DevTools popups.
+  auto chrome_params = Browser::CreateParams::CreateForDevTools(profile);
+
+  // Pass |opener| to the ChromeBrowserDelegate constructor for the new popup
+  // Browser.
+  chrome_params.opener = opener;
+
+  // Create a new Browser and give it ownership of the new WebContents.
+  // Results in a call to SetAsDelegate to associate the Browser with the
+  // browser host.
+  browser_host->AddNewContents(std::move(devtools_contents),
+                               std::move(chrome_params));
+
+  // Give the opener browser a reference to the new DevTools browser. Do this
+  // last because don't want the client to attempt access to the DevTools
+  // browser via opener browser methods (e.g. ShowDevTools, CloseDevTools, etc)
+  // while creation is still in progress.
+  opener_browser_host->SetDevToolsBrowserHost(browser_host->GetWeakPtr());
+
+  auto browser = browser_host->browser();
+  CHECK(browser);
+  return browser;
+}
+
+std::unique_ptr<content::WebContents> ChromeBrowserDelegate::AddWebContents(
+    std::unique_ptr<content::WebContents> new_contents) {
+  if (CefBrowserInfoManager::GetInstance()->AddWebContents(
+          new_contents.get())) {
+    // The browser host should have been created in WebContentsCreated().
+    auto new_browser =
+        ChromeBrowserHostImpl::GetBrowserForContents(new_contents.get());
+    if (new_browser) {
+      // Create a new Browser and give it ownership of the new WebContents.
+      // Results in a call to SetAsDelegate to associate the Browser with the
+      // browser host.
+      new_browser->AddNewContents(std::move(new_contents), std::nullopt);
+    } else {
+      LOG(ERROR) << "No host found for chrome popup browser";
+    }
+  }
+
+  // Proceed with default chrome::AddWebContents behavior.
+  return new_contents;
+}
+
+void ChromeBrowserDelegate::OnWebContentsCreated(
+    content::WebContents* new_contents) {
+  // Necessary to receive LoadingStateChanged calls during initial navigation.
+  // This will be called again in Browser::SetAsDelegate, which should be fine.
+  new_contents->SetDelegate(browser_);
+
+  SetAsDelegate(new_contents, /*set_delegate=*/true);
+}
+
+void ChromeBrowserDelegate::SetAsDelegate(content::WebContents* web_contents,
+                                          bool set_delegate) {
+  DCHECK(web_contents);
+  auto browser_host =
+      ChromeBrowserHostImpl::GetBrowserForContents(web_contents);
+
+  // |set_delegate=false| only makes sense if we already have a browser host.
+  DCHECK(browser_host || set_delegate);
+
+  if (browser_host) {
+    // We already have a browser host, so just change the associated Browser.
+    browser_host->SetBrowser(set_delegate ? browser_ : nullptr);
+    return;
+  }
+
+  const bool is_devtools_popup = browser_->is_type_devtools();
+
+  // We should never reach here for DevTools popups that have an opener, as
+  // CreateDevToolsBrowser should have already created the browser host.
+  DCHECK(!is_devtools_popup || !opener_host_);
+
+  auto platform_delegate = CefBrowserPlatformDelegate::Create(create_params_);
+  CHECK(platform_delegate);
+
+  auto browser_info = CefBrowserInfoManager::GetInstance()->CreateBrowserInfo(
+      is_devtools_popup, /*is_windowless=*/false, create_params_.extra_info);
+
+  auto request_context_impl =
+      CefRequestContextImpl::GetOrCreateForRequestContext(
+          create_params_.request_context);
+
+  CreateBrowserHost(web_contents, create_params_.settings,
+                    create_params_.client, std::move(platform_delegate),
+                    browser_info, is_devtools_popup, /*opener=*/nullptr,
+                    request_context_impl);
+}
+
+bool ChromeBrowserDelegate::ShowStatusBubble(bool show_by_default) {
+  if (!show_status_bubble_.has_value()) {
+    show_status_bubble_ = show_by_default;
+    if (auto browser = ChromeBrowserHostImpl::GetBrowserForBrowser(browser_)) {
+      const auto& state = browser->settings().chrome_status_bubble;
+      if (show_by_default && state == STATE_DISABLED) {
+        show_status_bubble_ = false;
+      } else if (!show_by_default && state == STATE_ENABLED) {
+        show_status_bubble_ = true;
+      }
+    }
+  }
+
+  return *show_status_bubble_;
+}
+
+bool ChromeBrowserDelegate::HandleCommand(int command_id,
+                                          WindowOpenDisposition disposition) {
+  // Verify that our enum matches Chromium's values.
+  static_assert(static_cast<int>(CEF_WOD_MAX_VALUE) ==
+                    static_cast<int>(WindowOpenDisposition::MAX_VALUE),
+                "enum mismatch");
+
+  if (auto browser = ChromeBrowserHostImpl::GetBrowserForBrowser(browser_)) {
+    if (auto client = browser->GetClient()) {
+      if (auto handler = client->GetCommandHandler()) {
+        return handler->OnChromeCommand(
+            browser.get(), command_id,
+            static_cast<cef_window_open_disposition_t>(disposition));
+      }
+    }
+  }
+  return false;
+}
+
+bool ChromeBrowserDelegate::IsAppMenuItemVisible(int command_id) {
+  if (auto browser = ChromeBrowserHostImpl::GetBrowserForBrowser(browser_)) {
+    if (auto client = browser->GetClient()) {
+      if (auto handler = client->GetCommandHandler()) {
+        return handler->IsChromeAppMenuItemVisible(browser.get(), command_id);
+      }
+    }
+  }
+  return true;
+}
+
+bool ChromeBrowserDelegate::IsAppMenuItemEnabled(int command_id) {
+  if (auto browser = ChromeBrowserHostImpl::GetBrowserForBrowser(browser_)) {
+    if (auto client = browser->GetClient()) {
+      if (auto handler = client->GetCommandHandler()) {
+        return handler->IsChromeAppMenuItemEnabled(browser.get(), command_id);
+      }
+    }
+  }
+  return true;
+}
+
+bool ChromeBrowserDelegate::IsPageActionIconVisible(
+    PageActionIconType icon_type) {
+  // Verify that our enum matches Chromium's values.
+  static_assert(static_cast<int>(CEF_CPAIT_MAX_VALUE) ==
+                    static_cast<int>(PageActionIconType::kMaxValue),
+                "enum mismatch");
+
+  if (auto client = create_params_.client) {
+    if (auto handler = client->GetCommandHandler()) {
+      return handler->IsChromePageActionIconVisible(
+          static_cast<cef_chrome_page_action_icon_type_t>(icon_type));
+    }
+  }
+  return true;
+}
+
+bool ChromeBrowserDelegate::IsToolbarButtonVisible(
+    ToolbarButtonType button_type) {
+  // Verify that our enum matches BrowserDelegate's values.
+  static_assert(static_cast<int>(CEF_CTBT_MAX_VALUE) ==
+                    static_cast<int>(ToolbarButtonType::kMaxValue),
+                "enum mismatch");
+
+  if (auto client = create_params_.client) {
+    if (auto handler = client->GetCommandHandler()) {
+      return handler->IsChromeToolbarButtonVisible(
+          static_cast<cef_chrome_toolbar_button_type_t>(button_type));
+    }
+  }
+  return true;
+}
+
+void ChromeBrowserDelegate::UpdateFindBarBoundingBox(gfx::Rect* bounds) {
+  if (auto browser = ChromeBrowserHostImpl::GetBrowserForBrowser(browser_)) {
+    browser->platform_delegate()->UpdateFindBarBoundingBox(bounds);
+  }
+}
+
+content::MediaResponseCallback
+ChromeBrowserDelegate::RequestMediaAccessPermissionEx(
+    content::WebContents* web_contents,
+    const content::MediaStreamRequest& request,
+    content::MediaResponseCallback callback) {
+  if (auto browser = ChromeBrowserHostImpl::GetBrowserForBrowser(browser_)) {
+    return media_access_query::RequestMediaAccessPermission(
+        browser.get(), request, std::move(callback),
+        /*default_disallow=*/false);
+  }
+  return callback;
+}
+
+bool ChromeBrowserDelegate::SupportsFramelessPictureInPicture() const {
+  if (!browser_->is_type_picture_in_picture()) {
+    return false;
+  }
+
+  if (frameless_pip_.has_value()) {
+    return *frameless_pip_;
+  }
+
+  frameless_pip_ = false;
+
+  if (opener_host_) {
+    if (auto chrome_browser_view = opener_host_->chrome_browser_view()) {
+      if (auto cef_delegate = chrome_browser_view->cef_delegate()) {
+        frameless_pip_ = cef_delegate->UseFramelessWindowForPictureInPicture(
+            chrome_browser_view->cef_browser_view());
+      }
+    }
+  }
+
+  return *frameless_pip_;
+}
+
+absl::optional<bool> ChromeBrowserDelegate::SupportsWindowFeature(
+    int feature) const {
+  // Override the default value from
+  // Browser::PictureInPictureBrowserSupportsWindowFeature.
+  if (feature == Browser::FEATURE_TITLEBAR &&
+      browser_->is_type_picture_in_picture()) {
+    // Return false to hide titlebar and enable draggable regions.
+    return !SupportsFramelessPictureInPicture();
+  }
+  return absl::nullopt;
+}
+
+bool ChromeBrowserDelegate::SupportsDraggableRegion() const {
+  return SupportsFramelessPictureInPicture();
+}
+
+const absl::optional<SkRegion> ChromeBrowserDelegate::GetDraggableRegion()
+    const {
+  DCHECK(SupportsDraggableRegion());
+  return draggable_region_;
+}
+
+void ChromeBrowserDelegate::UpdateDraggableRegion(const SkRegion& region) {
+  DCHECK(SupportsDraggableRegion());
+  draggable_region_ = region;
+}
+
+void ChromeBrowserDelegate::WindowFullscreenStateChanged() {
+  // Use a synchronous callback for notification on Windows/Linux. MacOS gets
+  // notified asynchronously via CefNativeWidgetMac callbacks.
+#if !BUILDFLAG(IS_MAC)
+  if (auto browser = ChromeBrowserHostImpl::GetBrowserForBrowser(browser_)) {
+    if (auto chrome_browser_view = browser->chrome_browser_view()) {
+      auto* cef_window = chrome_browser_view->cef_browser_view()->cef_window();
+      if (auto* delegate = cef_window->delegate()) {
+        // Give the CefWindowDelegate a chance to handle the event.
+        delegate->OnWindowFullscreenTransition(cef_window,
+                                               /*is_completed=*/true);
+      }
+    }
+  }
+#endif
+}
+
+void ChromeBrowserDelegate::WebContentsCreated(
+    content::WebContents* source_contents,
+    int opener_render_process_id,
+    int opener_render_frame_id,
+    const std::string& frame_name,
+    const GURL& target_url,
+    content::WebContents* new_contents) {
+  CefBrowserSettings settings;
+  CefRefPtr<CefClient> client;
+  std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate;
+  CefRefPtr<CefDictionaryValue> extra_info;
+
+  CefBrowserInfoManager::GetInstance()->WebContentsCreated(
+      target_url,
+      frame_util::MakeGlobalId(opener_render_process_id,
+                               opener_render_frame_id),
+      settings, client, platform_delegate, extra_info, new_contents);
+
+  auto opener = ChromeBrowserHostImpl::GetBrowserForContents(source_contents);
+  if (!opener) {
+    LOG(ERROR) << "No opener found for chrome popup browser";
+    return;
+  }
+
+  // Create a new browser host that remains alive until the associated
+  // WebContents is destroyed. Associate that browser host with the WebContents
+  // and execute initial client callbacks. Deliver required information to the
+  // renderer process.
+  CreateBrowserHostForPopup(new_contents, settings, client, extra_info,
+                            std::move(platform_delegate),
+                            /*is_devtools_popup=*/false, opener);
+}
+
+content::WebContents* ChromeBrowserDelegate::OpenURLFromTab(
+    content::WebContents* source,
+    const content::OpenURLParams& params) {
+  // |source| may be nullptr when opening a link from chrome UI such as the
+  // Reading List sidebar. In that case we default to using the Browser's
+  // currently active WebContents.
+  if (!source) {
+    source = browser_->tab_strip_model()->GetActiveWebContents();
+    DCHECK(source);
+  }
+
+  // Return nullptr to cancel the navigation. Otherwise, proceed with default
+  // chrome handling.
+  if (auto delegate = GetDelegateForWebContents(source)) {
+    return delegate->OpenURLFromTab(source, params);
+  }
+  return nullptr;
+}
+
+void ChromeBrowserDelegate::LoadingStateChanged(content::WebContents* source,
+                                                bool should_show_loading_ui) {
+  if (auto delegate = GetDelegateForWebContents(source)) {
+    delegate->LoadingStateChanged(source, should_show_loading_ui);
+  }
+}
+
+void ChromeBrowserDelegate::UpdateTargetURL(content::WebContents* source,
+                                            const GURL& url) {
+  if (auto delegate = GetDelegateForWebContents(source)) {
+    delegate->UpdateTargetURL(source, url);
+  }
+}
+
+bool ChromeBrowserDelegate::DidAddMessageToConsole(
+    content::WebContents* source,
+    blink::mojom::ConsoleMessageLevel log_level,
+    const std::u16string& message,
+    int32_t line_no,
+    const std::u16string& source_id) {
+  if (auto delegate = GetDelegateForWebContents(source)) {
+    return delegate->DidAddMessageToConsole(source, log_level, message, line_no,
+                                            source_id);
+  }
+  return false;
+}
+
+void ChromeBrowserDelegate::EnterFullscreenModeForTab(
+    content::RenderFrameHost* requesting_frame,
+    const blink::mojom::FullscreenOptions& options) {
+  auto web_contents =
+      content::WebContents::FromRenderFrameHost(requesting_frame);
+  if (!web_contents) {
+    return;
+  }
+
+  if (auto delegate = GetDelegateForWebContents(web_contents)) {
+    delegate->EnterFullscreenModeForTab(requesting_frame, options);
+  }
+}
+
+void ChromeBrowserDelegate::ExitFullscreenModeForTab(
+    content::WebContents* web_contents) {
+  if (auto delegate = GetDelegateForWebContents(web_contents)) {
+    delegate->ExitFullscreenModeForTab(web_contents);
+  }
+
+  // Workaround for https://crbug.com/1500371. Ensure WebContents exits
+  // fullscreen state by explicitly sending a resize message.
+  if (auto* rwhv = web_contents->GetRenderWidgetHostView()) {
+    if (auto* render_widget_host = rwhv->GetRenderWidgetHost()) {
+      render_widget_host->SynchronizeVisualProperties();
+    }
+  }
+}
+
+void ChromeBrowserDelegate::CanDownload(
+    const GURL& url,
+    const std::string& request_method,
+    base::OnceCallback<void(bool)> callback) {
+  auto source = browser_->tab_strip_model()->GetActiveWebContents();
+  DCHECK(source);
+
+  if (auto delegate = GetDelegateForWebContents(source)) {
+    delegate->CanDownload(url, request_method, std::move(callback));
+    return;
+  }
+  std::move(callback).Run(true);
+}
+
+KeyboardEventProcessingResult ChromeBrowserDelegate::PreHandleKeyboardEvent(
+    content::WebContents* source,
+    const content::NativeWebKeyboardEvent& event) {
+  if (auto delegate = GetDelegateForWebContents(source)) {
+    return delegate->PreHandleKeyboardEvent(source, event);
+  }
+  return KeyboardEventProcessingResult::NOT_HANDLED;
+}
+
+bool ChromeBrowserDelegate::HandleKeyboardEvent(
+    content::WebContents* source,
+    const content::NativeWebKeyboardEvent& event) {
+  if (auto delegate = GetDelegateForWebContents(source)) {
+    return delegate->HandleKeyboardEvent(source, event);
+  }
+  return false;
+}
+
+void ChromeBrowserDelegate::SetPendingShowDevToolsParams(
+    std::unique_ptr<CefShowDevToolsParams> params) {
+  DCHECK(!pending_show_devtools_params_);
+  pending_show_devtools_params_ = std::move(params);
+}
+
+CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserDelegate::CreateBrowserHost(
+    content::WebContents* web_contents,
+    const CefBrowserSettings& settings,
+    CefRefPtr<CefClient> client,
+    std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
+    scoped_refptr<CefBrowserInfo> browser_info,
+    bool is_devtools_popup,
+    CefRefPtr<ChromeBrowserHostImpl> opener,
+    CefRefPtr<CefRequestContextImpl> request_context_impl) {
+  CEF_REQUIRE_UIT();
+  DCHECK(web_contents);
+  DCHECK(platform_delegate);
+  DCHECK(browser_info);
+  DCHECK(request_context_impl);
+
+  // If |opener| is non-nullptr it must be a popup window.
+  DCHECK(!opener.get() || browser_info->is_popup());
+
+  if (!client) {
+    if (auto app = CefAppManager::Get()->GetApplication()) {
+      if (auto bph = app->GetBrowserProcessHandler()) {
+        client = bph->GetDefaultClient();
+      }
+    }
+  }
+
+  if (!client) {
+    LOG(WARNING) << "Creating a chrome browser without a client";
+  }
+
+  // Check if chrome and CEF are using the same browser context.
+  // TODO(chrome-runtime): Verify if/when this might occur.
+  auto chrome_browser_context =
+      CefBrowserContext::FromBrowserContext(browser_->create_params().profile);
+  if (chrome_browser_context != request_context_impl->GetBrowserContext()) {
+    LOG(WARNING) << "Creating a chrome browser with mismatched context";
+  }
+
+  // Remains alive until the associated WebContents is destroyed.
+  CefRefPtr<ChromeBrowserHostImpl> browser_host =
+      new ChromeBrowserHostImpl(settings, client, std::move(platform_delegate),
+                                browser_info, request_context_impl);
+  browser_host->Attach(web_contents, is_devtools_popup, opener);
+
+  // The Chrome browser for a normal popup won't be created until
+  // AddNewContents().
+  if (!opener) {
+    browser_host->SetBrowser(browser_);
+  }
+
+  return browser_host;
+}
+
+CefRefPtr<ChromeBrowserHostImpl>
+ChromeBrowserDelegate::CreateBrowserHostForPopup(
+    content::WebContents* web_contents,
+    const CefBrowserSettings& settings,
+    CefRefPtr<CefClient> client,
+    CefRefPtr<CefDictionaryValue> extra_info,
+    std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
+    bool is_devtools_popup,
+    CefRefPtr<ChromeBrowserHostImpl> opener) {
+  auto browser_info =
+      CefBrowserInfoManager::GetInstance()->CreatePopupBrowserInfo(
+          web_contents, /*is_windowless=*/false, extra_info);
+  CHECK(browser_info->is_popup());
+
+  // Popups must share the same RequestContext as the parent.
+  auto request_context_impl = opener->request_context();
+  CHECK(request_context_impl);
+
+  // We don't officially own |web_contents| until AddNewContents() is called.
+  // However, we need to install observers/delegates here.
+  return CreateBrowserHost(web_contents, settings, client,
+                           std::move(platform_delegate), browser_info,
+                           is_devtools_popup, opener, request_context_impl);
+}
+
+CefBrowserContentsDelegate* ChromeBrowserDelegate::GetDelegateForWebContents(
+    content::WebContents* web_contents) {
+  auto browser_host =
+      ChromeBrowserHostImpl::GetBrowserForContents(web_contents);
+  if (browser_host) {
+    return browser_host->contents_delegate();
+  }
+  return nullptr;
+}
+
+namespace cef {
+
+// static
+std::unique_ptr<BrowserDelegate> BrowserDelegate::Create(
+    Browser* browser,
+    scoped_refptr<CreateParams> cef_params,
+    const Browser* opener) {
+  if (!cef::IsChromeRuntimeEnabled()) {
+    return nullptr;
+  }
+
+  CefBrowserCreateParams create_params;
+
+  // Parameters from ChromeBrowserHostImpl::Create, or nullptr if the Browser
+  // was created from somewhere else.
+  auto params = static_cast<ChromeBrowserHostImpl::DelegateCreateParams*>(
+      cef_params.get());
+  if (params) {
+    create_params = params->create_params_;
+
+    // Clear these values so they're not persisted to additional Browsers.
+    params->create_params_.window_info.reset();
+    params->create_params_.browser_view = nullptr;
+  }
+
+  return std::make_unique<ChromeBrowserDelegate>(browser, create_params,
+                                                 opener);
+}
+
+}  // namespace cef
diff --git a/src/libcef/browser/chrome/chrome_browser_delegate.h b/src/libcef/browser/chrome/chrome_browser_delegate.h
new file mode 100644
index 0000000..c25a95c
--- /dev/null
+++ b/src/libcef/browser/chrome/chrome_browser_delegate.h
@@ -0,0 +1,157 @@
+// Copyright 2020 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_DELEGATE_H_
+#define CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_DELEGATE_H_
+#pragma once
+
+#include <memory>
+
+#include "libcef/browser/browser_host_base.h"
+#include "libcef/browser/browser_info.h"
+#include "libcef/browser/chrome/browser_delegate.h"
+
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+class CefBrowserContentsDelegate;
+class CefRequestContextImpl;
+class ChromeBrowserHostImpl;
+
+// Implementation of the cef::BrowserDelegate interface. Lifespan is controlled
+// by the Browser object. Only accessed on the UI thread.
+//
+// The Browser object represents the top-level Chrome browser window. One or
+// more tabs (WebContents) are then owned by the Browser object via
+// TabStripModel. A new Browser object can be created programmatically using
+// "new Browser" or Browser::Create, or as a result of user action such as
+// dragging a tab out of an existing window. New or existing tabs can also be
+// added to an already existing Browser object.
+//
+// The Browser object acts as the WebContentsDelegate for all attached tabs. CEF
+// integration requires WebContentsDelegate callbacks and notification of tab
+// attach/detach. To support this integration a cef::BrowserDelegate
+// (ChromeBrowserDelegate) member is created in the Browser constructor and
+// receives delegation for the Browser callbacks. ChromeBrowserDelegate creates
+// a new ChromeBrowserHostImpl when a tab is added to a Browser for the first
+// time, and that ChromeBrowserHostImpl continues to exist until the tab's
+// WebContents is destroyed. The associated WebContents object does not change,
+// but the Browser object will change when the tab is dragged between windows.
+class ChromeBrowserDelegate : public cef::BrowserDelegate {
+ public:
+  // The |create_params| and |opener| values are specified via the
+  // Browser::CreateParams passed to Browser::Create. |opener| will only be
+  // specified for certain special Browser types.
+  ChromeBrowserDelegate(Browser* browser,
+                        const CefBrowserCreateParams& create_params,
+                        const Browser* opener);
+
+  ChromeBrowserDelegate(const ChromeBrowserDelegate&) = delete;
+  ChromeBrowserDelegate& operator=(const ChromeBrowserDelegate&) = delete;
+
+  ~ChromeBrowserDelegate() override;
+
+  // cef::BrowserDelegate methods:
+  Browser* CreateDevToolsBrowser(
+      Profile* profile,
+      Browser* opener,
+      std::unique_ptr<content::WebContents>& devtools_contents) override;
+  std::unique_ptr<content::WebContents> AddWebContents(
+      std::unique_ptr<content::WebContents> new_contents) override;
+  void OnWebContentsCreated(content::WebContents* new_contents) override;
+  void SetAsDelegate(content::WebContents* web_contents,
+                     bool set_delegate) override;
+  bool ShowStatusBubble(bool show_by_default) override;
+  bool HandleCommand(int command_id,
+                     WindowOpenDisposition disposition) override;
+  bool IsAppMenuItemVisible(int command_id) override;
+  bool IsAppMenuItemEnabled(int command_id) override;
+  bool IsPageActionIconVisible(PageActionIconType icon_type) override;
+  bool IsToolbarButtonVisible(ToolbarButtonType button_type) override;
+  void UpdateFindBarBoundingBox(gfx::Rect* bounds) override;
+  [[nodiscard]] content::MediaResponseCallback RequestMediaAccessPermissionEx(
+      content::WebContents* web_contents,
+      const content::MediaStreamRequest& request,
+      content::MediaResponseCallback callback) override;
+  absl::optional<bool> SupportsWindowFeature(int feature) const override;
+  bool SupportsDraggableRegion() const override;
+  const absl::optional<SkRegion> GetDraggableRegion() const override;
+  void UpdateDraggableRegion(const SkRegion& region) override;
+  void WindowFullscreenStateChanged() override;
+
+  // WebContentsDelegate methods:
+  void WebContentsCreated(content::WebContents* source_contents,
+                          int opener_render_process_id,
+                          int opener_render_frame_id,
+                          const std::string& frame_name,
+                          const GURL& target_url,
+                          content::WebContents* new_contents) override;
+  content::WebContents* OpenURLFromTab(
+      content::WebContents* source,
+      const content::OpenURLParams& params) override;
+  void LoadingStateChanged(content::WebContents* source,
+                           bool should_show_loading_ui) override;
+  void UpdateTargetURL(content::WebContents* source, const GURL& url) override;
+  bool DidAddMessageToConsole(content::WebContents* source,
+                              blink::mojom::ConsoleMessageLevel log_level,
+                              const std::u16string& message,
+                              int32_t line_no,
+                              const std::u16string& source_id) override;
+  void EnterFullscreenModeForTab(
+      content::RenderFrameHost* requesting_frame,
+      const blink::mojom::FullscreenOptions& options) override;
+  void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
+  void CanDownload(const GURL& url,
+                   const std::string& request_method,
+                   base::OnceCallback<void(bool)> callback) override;
+  content::KeyboardEventProcessingResult PreHandleKeyboardEvent(
+      content::WebContents* source,
+      const content::NativeWebKeyboardEvent& event) override;
+  bool HandleKeyboardEvent(
+      content::WebContents* source,
+      const content::NativeWebKeyboardEvent& event) override;
+
+  void SetPendingShowDevToolsParams(
+      std::unique_ptr<CefShowDevToolsParams> params);
+
+  Browser* browser() const { return browser_; }
+
+ private:
+  CefRefPtr<ChromeBrowserHostImpl> CreateBrowserHost(
+      content::WebContents* web_contents,
+      const CefBrowserSettings& settings,
+      CefRefPtr<CefClient> client,
+      std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
+      scoped_refptr<CefBrowserInfo> browser_info,
+      bool is_devtools_popup,
+      CefRefPtr<ChromeBrowserHostImpl> opener,
+      CefRefPtr<CefRequestContextImpl> request_context_impl);
+
+  CefRefPtr<ChromeBrowserHostImpl> CreateBrowserHostForPopup(
+      content::WebContents* web_contents,
+      const CefBrowserSettings& settings,
+      CefRefPtr<CefClient> client,
+      CefRefPtr<CefDictionaryValue> extra_info,
+      std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
+      bool is_devtools_popup,
+      CefRefPtr<ChromeBrowserHostImpl> opener);
+
+  CefBrowserContentsDelegate* GetDelegateForWebContents(
+      content::WebContents* web_contents);
+
+  bool SupportsFramelessPictureInPicture() const;
+
+  Browser* const browser_;
+  base::WeakPtr<ChromeBrowserHostImpl> opener_host_;
+
+  // Used when creating a new browser host.
+  const CefBrowserCreateParams create_params_;
+
+  absl::optional<bool> show_status_bubble_;
+  absl::optional<SkRegion> draggable_region_;
+  mutable absl::optional<bool> frameless_pip_;
+
+  std::unique_ptr<CefShowDevToolsParams> pending_show_devtools_params_;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_DELEGATE_H_
diff --git a/src/libcef/browser/chrome/chrome_browser_host_impl.cc b/src/libcef/browser/chrome/chrome_browser_host_impl.cc
new file mode 100644
index 0000000..93dc988
--- /dev/null
+++ b/src/libcef/browser/chrome/chrome_browser_host_impl.cc
@@ -0,0 +1,678 @@
+// Copyright 2020 The Chromium Embedded Framework 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 "libcef/browser/chrome/chrome_browser_host_impl.h"
+
+#include "libcef/browser/browser_platform_delegate.h"
+#include "libcef/browser/chrome/browser_platform_delegate_chrome.h"
+#include "libcef/browser/chrome/chrome_browser_delegate.h"
+#include "libcef/browser/thread_util.h"
+#include "libcef/browser/views/browser_view_impl.h"
+#include "libcef/common/net/url_util.h"
+#include "libcef/features/runtime_checks.h"
+
+#include "base/logging.h"
+#include "base/notreached.h"
+#include "chrome/browser/devtools/devtools_window.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/views/frame/contents_web_view.h"
+#include "chrome/common/pref_names.h"
+#include "libcef/browser/chrome/views/chrome_browser_frame.h"
+#include "libcef/browser/chrome/views/chrome_browser_view.h"
+
+// static
+CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserHostImpl::Create(
+    const CefBrowserCreateParams& params) {
+  auto browser = CreateBrowser(params, std::nullopt);
+
+  GURL url = url_util::MakeGURL(params.url, /*fixup=*/true);
+  if (url.is_empty()) {
+    // Chrome will navigate to kChromeUINewTabURL by default. We want to keep
+    // the current CEF behavior of not navigating at all. Use a special URL that
+    // will be recognized in HandleNonNavigationAboutURL.
+    url = GURL("chrome://ignore/");
+  }
+
+  // Add a new tab. This will indirectly create a new tab WebContents and
+  // call ChromeBrowserDelegate::OnWebContentsCreated to create the associated
+  // ChromeBrowserHostImpl.
+  chrome::AddTabAt(browser, url, /*index=*/TabStripModel::kNoTab,
+                   /*foreground=*/true);
+
+  // The new tab WebContents.
+  auto web_contents = browser->tab_strip_model()->GetActiveWebContents();
+  CHECK(web_contents);
+
+  // The associated ChromeBrowserHostImpl.
+  auto browser_host =
+      ChromeBrowserHostImpl::GetBrowserForContents(web_contents);
+  CHECK(browser_host);
+
+  return browser_host;
+}
+
+// static
+CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserHostImpl::GetBrowserForHost(
+    const content::RenderViewHost* host) {
+  REQUIRE_CHROME_RUNTIME();
+  auto browser = CefBrowserHostBase::GetBrowserForHost(host);
+  return static_cast<ChromeBrowserHostImpl*>(browser.get());
+}
+
+// static
+CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserHostImpl::GetBrowserForHost(
+    const content::RenderFrameHost* host) {
+  REQUIRE_CHROME_RUNTIME();
+  auto browser = CefBrowserHostBase::GetBrowserForHost(host);
+  return static_cast<ChromeBrowserHostImpl*>(browser.get());
+}
+
+// static
+CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserHostImpl::GetBrowserForContents(
+    const content::WebContents* contents) {
+  REQUIRE_CHROME_RUNTIME();
+  auto browser = CefBrowserHostBase::GetBrowserForContents(contents);
+  return static_cast<ChromeBrowserHostImpl*>(browser.get());
+}
+
+// static
+CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserHostImpl::GetBrowserForGlobalId(
+    const content::GlobalRenderFrameHostId& global_id) {
+  REQUIRE_CHROME_RUNTIME();
+  auto browser = CefBrowserHostBase::GetBrowserForGlobalId(global_id);
+  return static_cast<ChromeBrowserHostImpl*>(browser.get());
+}
+
+// static
+CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserHostImpl::GetBrowserForBrowser(
+    const Browser* browser) {
+  REQUIRE_CHROME_RUNTIME();
+  return GetBrowserForContents(
+      browser->tab_strip_model()->GetActiveWebContents());
+}
+
+ChromeBrowserHostImpl::~ChromeBrowserHostImpl() = default;
+
+void ChromeBrowserHostImpl::AddNewContents(
+    std::unique_ptr<content::WebContents> contents,
+    std::optional<Browser::CreateParams> browser_create_params) {
+  DCHECK(contents);
+  DCHECK(!browser_);
+
+  // We should already be associated with the WebContents.
+  DCHECK_EQ(GetWebContents(), contents.get());
+
+  CefBrowserCreateParams params;
+  params.request_context = request_context();
+  params.browser_view = GetBrowserView();
+
+  // Create the new Browser representation.
+  auto browser = CreateBrowser(params, std::move(browser_create_params));
+
+  // Add the WebContents to the Browser.
+  browser->tab_strip_model()->AddWebContents(
+      std::move(contents), /*index=*/TabStripModel::kNoTab,
+      ui::PageTransition::PAGE_TRANSITION_AUTO_TOPLEVEL,
+      AddTabTypes::ADD_ACTIVE);
+
+  SetBrowser(browser);
+}
+
+void ChromeBrowserHostImpl::OnWebContentsDestroyed(
+    content::WebContents* web_contents) {
+  // GetWebContents() should return nullptr at this point.
+  DCHECK(!GetWebContents());
+
+  // In most cases WebContents destruction will trigger browser destruction.
+  // The exception is if the browser still exists at CefShutdown, in which
+  // case DestroyBrowser() will be called first via
+  // CefBrowserInfoManager::DestroyAllBrowsers().
+  if (platform_delegate_) {
+    platform_delegate_->WebContentsDestroyed(web_contents);
+    DestroyBrowser();
+  }
+}
+
+void ChromeBrowserHostImpl::OnSetFocus(cef_focus_source_t source) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(&ChromeBrowserHostImpl::OnSetFocus,
+                                          this, source));
+    return;
+  }
+
+  if (contents_delegate_->OnSetFocus(source)) {
+    return;
+  }
+
+  if (platform_delegate_) {
+    platform_delegate_->SetFocus(true);
+  }
+
+  if (browser_) {
+    const int tab_index = GetCurrentTabIndex();
+    if (tab_index != TabStripModel::kNoTab) {
+      chrome::SelectNumberedTab(browser_, tab_index);
+    }
+  }
+}
+
+void ChromeBrowserHostImpl::CloseBrowser(bool force_close) {
+  // Always do this asynchronously because TabStripModel is not re-entrant.
+  CEF_POST_TASK(CEF_UIT, base::BindOnce(&ChromeBrowserHostImpl::DoCloseBrowser,
+                                        this, force_close));
+}
+
+bool ChromeBrowserHostImpl::TryCloseBrowser() {
+  // TODO(chrome): Handle the case where the browser may not close immediately.
+  CloseBrowser(true);
+  return true;
+}
+
+CefWindowHandle ChromeBrowserHostImpl::GetWindowHandle() {
+  if (CEF_CURRENTLY_ON_UIT()) {
+    // Always return the most up-to-date window handle for a views-hosted
+    // browser since it may change if the view is re-parented.
+    if (platform_delegate_) {
+      return platform_delegate_->GetHostWindowHandle();
+    }
+  }
+  return host_window_handle_;
+}
+
+CefWindowHandle ChromeBrowserHostImpl::GetOpenerWindowHandle() {
+  NOTIMPLEMENTED();
+  return kNullWindowHandle;
+}
+
+void ChromeBrowserHostImpl::Find(const CefString& searchText,
+                                 bool forward,
+                                 bool matchCase,
+                                 bool findNext) {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::StopFinding(bool clearSelection) {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::ShowDevToolsOnUIThread(
+    std::unique_ptr<CefShowDevToolsParams> params) {
+  CEF_REQUIRE_UIT();
+
+  if (!browser_) {
+    return;
+  }
+
+  auto* web_contents = GetWebContents();
+  if (!web_contents) {
+    return;
+  }
+
+  auto* profile = CefRequestContextImpl::GetProfile(request_context());
+  if (!DevToolsWindow::AllowDevToolsFor(profile, web_contents)) {
+    LOG(WARNING) << "DevTools is not allowed for this browser";
+    return;
+  }
+
+  auto inspect_element_at = params->inspect_element_at_;
+
+  if (!devtools_browser_host_) {
+    // Configure parameters for ChromeBrowserDelegate::CreateDevToolsBrowser
+    // which will be called indirectly to create the DevTools window.
+    auto chrome_browser_delegate =
+        static_cast<ChromeBrowserDelegate*>(browser_->cef_delegate());
+    chrome_browser_delegate->SetPendingShowDevToolsParams(std::move(params));
+  }
+
+  // Focus the existing DevTools window or create a new one.
+  if (!inspect_element_at.IsEmpty()) {
+    DevToolsWindow::InspectElement(web_contents->GetPrimaryMainFrame(),
+                                   inspect_element_at.x, inspect_element_at.y);
+  } else {
+    DevToolsWindow::OpenDevToolsWindow(web_contents, profile);
+  }
+
+  // The DevTools browser host should now exist.
+  DCHECK(devtools_browser_host_);
+}
+
+void ChromeBrowserHostImpl::CloseDevTools() {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&ChromeBrowserHostImpl::CloseDevTools, this));
+    return;
+  }
+
+  if (devtools_browser_host_) {
+    devtools_browser_host_->TryCloseBrowser();
+  }
+}
+
+bool ChromeBrowserHostImpl::HasDevTools() {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    DCHECK(false) << "called on invalid thread";
+    return false;
+  }
+
+  return !!devtools_browser_host_;
+}
+
+bool ChromeBrowserHostImpl::IsWindowRenderingDisabled() {
+  return false;
+}
+
+void ChromeBrowserHostImpl::WasResized() {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::WasHidden(bool hidden) {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::NotifyScreenInfoChanged() {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::Invalidate(PaintElementType type) {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::SendExternalBeginFrame() {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::SendTouchEvent(const CefTouchEvent& event) {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::SendCaptureLostEvent() {
+  NOTIMPLEMENTED();
+}
+
+int ChromeBrowserHostImpl::GetWindowlessFrameRate() {
+  return 0;
+}
+
+void ChromeBrowserHostImpl::SetWindowlessFrameRate(int frame_rate) {}
+
+void ChromeBrowserHostImpl::ImeSetComposition(
+    const CefString& text,
+    const std::vector<CefCompositionUnderline>& underlines,
+    const CefRange& replacement_range,
+    const CefRange& selection_range) {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::ImeCommitText(const CefString& text,
+                                          const CefRange& replacement_range,
+                                          int relative_cursor_pos) {
+  NOTIMPLEMENTED();
+}
+void ChromeBrowserHostImpl::ImeFinishComposingText(bool keep_selection) {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::ImeCancelComposition() {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::DragTargetDragEnter(
+    CefRefPtr<CefDragData> drag_data,
+    const CefMouseEvent& event,
+    DragOperationsMask allowed_ops) {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::DragTargetDragOver(const CefMouseEvent& event,
+                                               DragOperationsMask allowed_ops) {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::DragTargetDragLeave() {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::DragTargetDrop(const CefMouseEvent& event) {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::DragSourceSystemDragEnded() {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::DragSourceEndedAt(int x,
+                                              int y,
+                                              DragOperationsMask op) {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::SetAudioMuted(bool mute) {
+  NOTIMPLEMENTED();
+}
+
+bool ChromeBrowserHostImpl::IsAudioMuted() {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+void ChromeBrowserHostImpl::SetAccessibilityState(
+    cef_state_t accessibility_state) {
+  NOTIMPLEMENTED();
+}
+
+void ChromeBrowserHostImpl::SetAutoResizeEnabled(bool enabled,
+                                                 const CefSize& min_size,
+                                                 const CefSize& max_size) {
+  NOTIMPLEMENTED();
+}
+
+CefRefPtr<CefExtension> ChromeBrowserHostImpl::GetExtension() {
+  return nullptr;
+}
+
+bool ChromeBrowserHostImpl::IsBackgroundHost() {
+  return false;
+}
+
+bool ChromeBrowserHostImpl::CanExecuteChromeCommand(int command_id) {
+  // Verify that this method is being called on the UI thread.
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    DCHECK(false) << "called on invalid thread";
+    return false;
+  }
+
+  if (browser_) {
+    return chrome::SupportsCommand(browser_, command_id) &&
+           chrome::IsCommandEnabled(browser_, command_id);
+  }
+  return false;
+}
+
+void ChromeBrowserHostImpl::ExecuteChromeCommand(
+    int command_id,
+    cef_window_open_disposition_t disposition) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&ChromeBrowserHostImpl::ExecuteChromeCommand,
+                                 this, command_id, disposition));
+    return;
+  }
+
+  if (browser_) {
+    chrome::ExecuteCommandWithDisposition(
+        browser_, command_id, static_cast<WindowOpenDisposition>(disposition));
+  }
+}
+
+ChromeBrowserView* ChromeBrowserHostImpl::chrome_browser_view() const {
+  if (browser_ && is_views_hosted_) {
+    return static_cast<ChromeBrowserView*>(browser_->window());
+  }
+  return nullptr;
+}
+
+bool ChromeBrowserHostImpl::Navigate(const content::OpenURLParams& params) {
+  CEF_REQUIRE_UIT();
+  if (GetCurrentTabIndex() == TabStripModel::kNoTab) {
+    // We can't navigate via the Browser because we don't have a current tab.
+    return CefBrowserHostBase::Navigate(params);
+  }
+
+  if (browser_) {
+    GURL gurl = params.url;
+    if (!url_util::FixupGURL(gurl)) {
+      return false;
+    }
+
+    // This is generally equivalent to calling Browser::OpenURL, except:
+    // 1. It doesn't trigger a call to CefRequestHandler::OnOpenURLFromTab, and
+    // 2. It navigates in this CefBrowserHost's WebContents instead of
+    //    (a) creating a new WebContents, or (b) using the Browser's active
+    //    WebContents (which may not be the same), and
+    // 3. There is no risk of triggering chrome's popup blocker.
+    NavigateParams nav_params(browser_, gurl, params.transition);
+    nav_params.FillNavigateParamsFromOpenURLParams(params);
+
+    // Always navigate in the current tab.
+    nav_params.disposition = WindowOpenDisposition::CURRENT_TAB;
+    nav_params.source_contents = GetWebContents();
+
+    nav_params.tabstrip_add_types = AddTabTypes::ADD_NONE;
+    if (params.user_gesture) {
+      nav_params.window_action = NavigateParams::SHOW_WINDOW;
+    }
+    ::Navigate(&nav_params);
+    return true;
+  }
+  return false;
+}
+
+ChromeBrowserHostImpl::ChromeBrowserHostImpl(
+    const CefBrowserSettings& settings,
+    CefRefPtr<CefClient> client,
+    std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
+    scoped_refptr<CefBrowserInfo> browser_info,
+    CefRefPtr<CefRequestContextImpl> request_context)
+    : CefBrowserHostBase(settings,
+                         client,
+                         std::move(platform_delegate),
+                         browser_info,
+                         request_context) {}
+
+// static
+Browser* ChromeBrowserHostImpl::CreateBrowser(
+    const CefBrowserCreateParams& params,
+    std::optional<Browser::CreateParams> browser_create_params) {
+  Browser::CreateParams chrome_params = [&params, &browser_create_params]() {
+    if (!browser_create_params.has_value()) {
+      auto* profile = CefRequestContextImpl::GetProfile(params.request_context);
+      return Browser::CreateParams(profile, /*user_gesture=*/false);
+    } else {
+      return std::move(*browser_create_params);
+    }
+  }();
+
+  // Pass |params| to cef::BrowserDelegate::Create from the Browser constructor.
+  chrome_params.cef_params = base::MakeRefCounted<DelegateCreateParams>(params);
+
+  // Configure Browser creation to use the existing Views-based
+  // Widget/BrowserFrame (ChromeBrowserFrame) and BrowserView/BrowserWindow
+  // (ChromeBrowserView). See views/chrome_browser_frame.h for related
+  // documentation.
+  ChromeBrowserView* chrome_browser_view = nullptr;
+  if (params.browser_view) {
+    if (chrome_params.type == Browser::TYPE_NORMAL) {
+      // Don't show most controls.
+      chrome_params.type = Browser::TYPE_POPUP;
+      // Don't show title bar or address.
+      chrome_params.trusted_source = true;
+    }
+
+    auto view_impl =
+        static_cast<CefBrowserViewImpl*>(params.browser_view.get());
+
+    chrome_browser_view = view_impl->chrome_browser_view();
+    chrome_params.window = chrome_browser_view;
+
+    auto chrome_widget =
+        static_cast<ChromeBrowserFrame*>(chrome_browser_view->GetWidget());
+    chrome_browser_view->set_frame(chrome_widget);
+  }
+
+  // Create the Browser. This will indirectly create the ChomeBrowserDelegate.
+  // The same params will be used to create a new Browser if the tab is dragged
+  // out of the existing Browser. The returned Browser is owned by the
+  // associated BrowserView.
+  auto browser = Browser::Create(chrome_params);
+
+  bool show_browser = true;
+
+  if (chrome_browser_view) {
+    // Initialize the BrowserFrame and BrowserView and create the controls that
+    // require access to the Browser.
+    chrome_browser_view->InitBrowser(base::WrapUnique(browser));
+
+    // Don't set theme colors in ContentsWebView::UpdateBackgroundColor.
+    chrome_browser_view->contents_web_view()->SetBackgroundVisible(false);
+
+    // Don't show the browser by default.
+    show_browser = false;
+  }
+
+  if (show_browser) {
+    browser->window()->Show();
+  }
+
+  return browser;
+}
+
+void ChromeBrowserHostImpl::Attach(content::WebContents* web_contents,
+                                   bool is_devtools_popup,
+                                   CefRefPtr<ChromeBrowserHostImpl> opener) {
+  DCHECK(web_contents);
+
+  if (opener) {
+    // Give the opener browser's platform delegate an opportunity to modify the
+    // new browser's platform delegate.
+    opener->platform_delegate_->PopupWebContentsCreated(
+        settings_, client_, web_contents, platform_delegate_.get(),
+        is_devtools_popup);
+  }
+
+  platform_delegate_->WebContentsCreated(web_contents,
+                                         /*own_web_contents=*/false);
+  contents_delegate_->ObserveWebContents(web_contents);
+
+  // Associate the platform delegate with this browser.
+  platform_delegate_->BrowserCreated(this);
+
+  // Associate the base class with the WebContents.
+  InitializeBrowser();
+
+  // Notify that the browser has been created. These must be delivered in the
+  // expected order.
+
+  if (opener) {
+    // 1. Notify the opener browser's platform delegate. With Views this will
+    // result in a call to CefBrowserViewDelegate::OnPopupBrowserViewCreated().
+    // We want to call this method first because the implementation will often
+    // create the Widget for the new popup browser. Without that Widget
+    // CefBrowserHost::GetWindowHandle() will return kNullWindowHandle in
+    // OnAfterCreated(), which breaks client expectations (e.g. clients expect
+    // everything about the browser to be valid at that time).
+    opener->platform_delegate_->PopupBrowserCreated(this, is_devtools_popup);
+  }
+
+  // 2. Notify the browser's LifeSpanHandler. This must always be the first
+  // notification for the browser.
+  {
+    // The WebContents won't be added to the Browser's TabStripModel until later
+    // in the current call stack. Block navigation until that time.
+    auto navigation_lock = browser_info_->CreateNavigationLock();
+    OnAfterCreated();
+  }
+
+  // 3. Notify the platform delegate. With Views this will result in a call to
+  // CefBrowserViewDelegate::OnBrowserCreated().
+  platform_delegate_->NotifyBrowserCreated();
+}
+
+void ChromeBrowserHostImpl::SetBrowser(Browser* browser) {
+  CEF_REQUIRE_UIT();
+  if (browser == browser_) {
+    return;
+  }
+
+  browser_ = browser;
+  static_cast<CefBrowserPlatformDelegateChrome*>(platform_delegate_.get())
+      ->set_chrome_browser(browser);
+  if (browser_) {
+    host_window_handle_ = platform_delegate_->GetHostWindowHandle();
+  } else {
+    host_window_handle_ = kNullWindowHandle;
+  }
+}
+
+void ChromeBrowserHostImpl::SetDevToolsBrowserHost(
+    base::WeakPtr<ChromeBrowserHostImpl> devtools_browser_host) {
+  CEF_REQUIRE_UIT();
+  DCHECK(!devtools_browser_host_);
+  devtools_browser_host_ = devtools_browser_host;
+}
+
+void ChromeBrowserHostImpl::WindowDestroyed() {
+  CEF_REQUIRE_UIT();
+  if (auto view = chrome_browser_view()) {
+    view->Destroyed();
+  }
+
+  platform_delegate_->CloseHostWindow();
+}
+
+bool ChromeBrowserHostImpl::WillBeDestroyed() const {
+  CEF_REQUIRE_UIT();
+  // TODO(chrome): Modify this to support DoClose(), see issue #3294.
+  return !!browser_;
+}
+
+void ChromeBrowserHostImpl::DestroyBrowser() {
+  CEF_REQUIRE_UIT();
+
+  // Notify that this browser has been destroyed. These must be delivered in
+  // the expected order.
+
+  // 1. Notify the platform delegate. With Views this will result in a call to
+  // CefBrowserViewDelegate::OnBrowserDestroyed().
+  platform_delegate_->NotifyBrowserDestroyed();
+
+  // 2. Notify the browser's LifeSpanHandler. This must always be the last
+  // notification for this browser.
+  OnBeforeClose();
+
+  // Notify any observers that may have state associated with this browser.
+  OnBrowserDestroyed();
+
+  // If the WebContents still exists at this point, signal destruction before
+  // browser destruction.
+  if (auto web_contents = GetWebContents()) {
+    platform_delegate_->WebContentsDestroyed(web_contents);
+  }
+
+  // Disassociate the platform delegate from this browser.
+  platform_delegate_->BrowserDestroyed(this);
+
+  // Clean up UI thread state.
+  browser_ = nullptr;
+  weak_ptr_factory_.InvalidateWeakPtrs();
+
+  CefBrowserHostBase::DestroyBrowser();
+}
+
+void ChromeBrowserHostImpl::DoCloseBrowser(bool force_close) {
+  CEF_REQUIRE_UIT();
+  if (browser_) {
+    // Like chrome::CloseTab() but specifying the WebContents.
+    const int tab_index = GetCurrentTabIndex();
+    if (tab_index != TabStripModel::kNoTab) {
+      // TODO(chrome): Handle the case where this method returns false,
+      // indicating that the contents were not closed immediately.
+      browser_->tab_strip_model()->CloseWebContentsAt(
+          tab_index, TabCloseTypes::CLOSE_CREATE_HISTORICAL_TAB |
+                         TabCloseTypes::CLOSE_USER_GESTURE);
+    }
+  }
+}
+
+int ChromeBrowserHostImpl::GetCurrentTabIndex() const {
+  CEF_REQUIRE_UIT();
+  if (browser_) {
+    return browser_->tab_strip_model()->GetIndexOfWebContents(GetWebContents());
+  }
+  return TabStripModel::kNoTab;
+}
diff --git a/src/libcef/browser/chrome/chrome_browser_host_impl.h b/src/libcef/browser/chrome/chrome_browser_host_impl.h
new file mode 100644
index 0000000..fb162fa
--- /dev/null
+++ b/src/libcef/browser/chrome/chrome_browser_host_impl.h
@@ -0,0 +1,187 @@
+// Copyright 2020 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_HOST_IMPL_H_
+#define CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_HOST_IMPL_H_
+#pragma once
+
+#include <memory>
+
+#include "libcef/browser/browser_host_base.h"
+#include "libcef/browser/chrome/browser_delegate.h"
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/browser.h"
+
+class ChromeBrowserDelegate;
+class ChromeBrowserView;
+
+// CefBrowser implementation for the chrome runtime. Method calls are delegated
+// to the chrome Browser object or the WebContents as appropriate. See the
+// ChromeBrowserDelegate documentation for additional details. All methods are
+// thread-safe unless otherwise indicated.
+class ChromeBrowserHostImpl : public CefBrowserHostBase {
+ public:
+  // CEF-specific parameters passed via Browser::CreateParams::cef_params and
+  // possibly shared by multiple Browser instances.
+  class DelegateCreateParams : public cef::BrowserDelegate::CreateParams {
+   public:
+    DelegateCreateParams(const CefBrowserCreateParams& create_params)
+        : create_params_(create_params) {}
+
+    CefBrowserCreateParams create_params_;
+  };
+
+  // Create a new Browser with a single tab (WebContents) and associated
+  // ChromeBrowserHostImpl instance.
+  static CefRefPtr<ChromeBrowserHostImpl> Create(
+      const CefBrowserCreateParams& params);
+
+  // Returns the browser associated with the specified RenderViewHost.
+  static CefRefPtr<ChromeBrowserHostImpl> GetBrowserForHost(
+      const content::RenderViewHost* host);
+  // Returns the browser associated with the specified RenderFrameHost.
+  static CefRefPtr<ChromeBrowserHostImpl> GetBrowserForHost(
+      const content::RenderFrameHost* host);
+  // Returns the browser associated with the specified WebContents.
+  static CefRefPtr<ChromeBrowserHostImpl> GetBrowserForContents(
+      const content::WebContents* contents);
+  // Returns the browser associated with the specified global ID.
+  static CefRefPtr<ChromeBrowserHostImpl> GetBrowserForGlobalId(
+      const content::GlobalRenderFrameHostId& global_id);
+  // Returns the browser associated with the specified Browser.
+  static CefRefPtr<ChromeBrowserHostImpl> GetBrowserForBrowser(
+      const Browser* browser);
+
+  ~ChromeBrowserHostImpl() override;
+
+  // CefBrowserContentsDelegate::Observer methods:
+  void OnWebContentsDestroyed(content::WebContents* web_contents) override;
+
+  // CefBrowserHostBase methods called from CefFrameHostImpl:
+  void OnSetFocus(cef_focus_source_t source) override;
+
+  // CefBrowserHost methods:
+  void CloseBrowser(bool force_close) override;
+  bool TryCloseBrowser() override;
+  CefWindowHandle GetWindowHandle() override;
+  CefWindowHandle GetOpenerWindowHandle() override;
+  void Find(const CefString& searchText,
+            bool forward,
+            bool matchCase,
+            bool findNext) override;
+  void StopFinding(bool clearSelection) override;
+  void CloseDevTools() override;
+  bool HasDevTools() override;
+  bool IsWindowRenderingDisabled() override;
+  void WasResized() override;
+  void WasHidden(bool hidden) override;
+  void NotifyScreenInfoChanged() override;
+  void Invalidate(PaintElementType type) override;
+  void SendExternalBeginFrame() override;
+  void SendTouchEvent(const CefTouchEvent& event) override;
+  void SendCaptureLostEvent() override;
+  int GetWindowlessFrameRate() override;
+  void SetWindowlessFrameRate(int frame_rate) override;
+  void ImeSetComposition(const CefString& text,
+                         const std::vector<CefCompositionUnderline>& underlines,
+                         const CefRange& replacement_range,
+                         const CefRange& selection_range) override;
+  void ImeCommitText(const CefString& text,
+                     const CefRange& replacement_range,
+                     int relative_cursor_pos) override;
+  void ImeFinishComposingText(bool keep_selection) override;
+  void ImeCancelComposition() override;
+  void DragTargetDragEnter(CefRefPtr<CefDragData> drag_data,
+                           const CefMouseEvent& event,
+                           DragOperationsMask allowed_ops) override;
+  void DragTargetDragOver(const CefMouseEvent& event,
+                          DragOperationsMask allowed_ops) override;
+  void DragTargetDragLeave() override;
+  void DragTargetDrop(const CefMouseEvent& event) override;
+  void DragSourceSystemDragEnded() override;
+  void DragSourceEndedAt(int x, int y, DragOperationsMask op) override;
+  void SetAudioMuted(bool mute) override;
+  bool IsAudioMuted() override;
+  void SetAccessibilityState(cef_state_t accessibility_state) override;
+  void SetAutoResizeEnabled(bool enabled,
+                            const CefSize& min_size,
+                            const CefSize& max_size) override;
+  CefRefPtr<CefExtension> GetExtension() override;
+  bool IsBackgroundHost() override;
+  bool CanExecuteChromeCommand(int command_id) override;
+  void ExecuteChromeCommand(int command_id,
+                            cef_window_open_disposition_t disposition) override;
+
+  Browser* browser() const { return browser_; }
+
+  // Return the CEF specialization of BrowserView.
+  ChromeBrowserView* chrome_browser_view() const;
+
+  base::WeakPtr<ChromeBrowserHostImpl> GetWeakPtr() {
+    return weak_ptr_factory_.GetWeakPtr();
+  }
+
+ protected:
+  bool Navigate(const content::OpenURLParams& params) override;
+  void ShowDevToolsOnUIThread(
+      std::unique_ptr<CefShowDevToolsParams> params) override;
+
+ private:
+  friend class ChromeBrowserDelegate;
+
+  ChromeBrowserHostImpl(
+      const CefBrowserSettings& settings,
+      CefRefPtr<CefClient> client,
+      std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
+      scoped_refptr<CefBrowserInfo> browser_info,
+      CefRefPtr<CefRequestContextImpl> request_context);
+
+  // Create a new Browser without initializing the WebContents.
+  // |browser_create_params| may be empty for default Browser creation behavior.
+  static Browser* CreateBrowser(
+      const CefBrowserCreateParams& params,
+      std::optional<Browser::CreateParams> browser_create_params);
+
+  // Called from ChromeBrowserDelegate::CreateBrowser when this object is first
+  // created. Must be called on the UI thread.
+  void Attach(content::WebContents* web_contents,
+              bool is_devtools_popup,
+              CefRefPtr<ChromeBrowserHostImpl> opener);
+
+  // Called from ChromeBrowserDelegate::AddNewContents to take ownership of a
+  // popup WebContents. |browser_create_params| may be empty for default Browser
+  // creation behavior.
+  void AddNewContents(
+      std::unique_ptr<content::WebContents> contents,
+      std::optional<Browser::CreateParams> browser_create_params);
+
+  // Called when this object changes Browser ownership (e.g. initially created,
+  // dragging between windows, etc). The old Browser, if any, will be cleared
+  // before the new Browser is added. Must be called on the UI thread.
+  void SetBrowser(Browser* browser);
+
+  void SetDevToolsBrowserHost(
+      base::WeakPtr<ChromeBrowserHostImpl> devtools_browser_host);
+
+  // CefBrowserHostBase methods:
+  void WindowDestroyed() override;
+  bool WillBeDestroyed() const override;
+  void DestroyBrowser() override;
+
+  void DoCloseBrowser(bool force_close);
+
+  // Returns the current tab index for the associated WebContents, or
+  // TabStripModel::kNoTab if not found.
+  int GetCurrentTabIndex() const;
+
+  Browser* browser_ = nullptr;
+  CefWindowHandle host_window_handle_ = kNullWindowHandle;
+
+  base::WeakPtr<ChromeBrowserHostImpl> devtools_browser_host_;
+
+  base::WeakPtrFactory<ChromeBrowserHostImpl> weak_ptr_factory_{this};
+};
+
+#endif  // CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_HOST_IMPL_H_
diff --git a/src/libcef/browser/chrome/chrome_browser_main_extra_parts_cef.cc b/src/libcef/browser/chrome/chrome_browser_main_extra_parts_cef.cc
new file mode 100644
index 0000000..87aa49f
--- /dev/null
+++ b/src/libcef/browser/chrome/chrome_browser_main_extra_parts_cef.cc
@@ -0,0 +1,52 @@
+// 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.
+
+#include "libcef/browser/chrome/chrome_browser_main_extra_parts_cef.h"
+
+#include "libcef/browser/chrome/chrome_context_menu_handler.h"
+#include "libcef/browser/context.h"
+#include "libcef/browser/file_dialog_runner.h"
+#include "libcef/browser/net/chrome_scheme_handler.h"
+#include "libcef/browser/permission_prompt.h"
+
+#include "base/task/thread_pool.h"
+#include "chrome/browser/profiles/profile.h"
+
+ChromeBrowserMainExtraPartsCef::ChromeBrowserMainExtraPartsCef() = default;
+
+ChromeBrowserMainExtraPartsCef::~ChromeBrowserMainExtraPartsCef() = default;
+
+void ChromeBrowserMainExtraPartsCef::PostProfileInit(Profile* profile,
+                                                     bool is_initial_profile) {
+  if (!is_initial_profile) {
+    return;
+  }
+
+  CefRequestContextSettings settings;
+  CefContext::Get()->PopulateGlobalRequestContextSettings(&settings);
+
+  // Use the existing path for the initial profile.
+  CefString(&settings.cache_path) = profile->GetPath().value();
+
+  // Create the global RequestContext.
+  global_request_context_ =
+      CefRequestContextImpl::CreateGlobalRequestContext(settings);
+}
+
+void ChromeBrowserMainExtraPartsCef::PreMainMessageLoopRun() {
+  background_task_runner_ = base::ThreadPool::CreateSingleThreadTaskRunner(
+      {base::TaskPriority::BEST_EFFORT,
+       base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()});
+  user_visible_task_runner_ = base::ThreadPool::CreateSingleThreadTaskRunner(
+      {base::TaskPriority::USER_VISIBLE,
+       base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()});
+  user_blocking_task_runner_ = base::ThreadPool::CreateSingleThreadTaskRunner(
+      {base::TaskPriority::USER_BLOCKING,
+       base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()});
+
+  scheme::RegisterWebUIControllerFactory();
+  context_menu::RegisterMenuCreatedCallback();
+  file_dialog_runner::RegisterFactory();
+  permission_prompt::RegisterCreateCallback();
+}
diff --git a/src/libcef/browser/chrome/chrome_browser_main_extra_parts_cef.h b/src/libcef/browser/chrome/chrome_browser_main_extra_parts_cef.h
new file mode 100644
index 0000000..74a6c32
--- /dev/null
+++ b/src/libcef/browser/chrome/chrome_browser_main_extra_parts_cef.h
@@ -0,0 +1,57 @@
+// 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.
+
+#ifndef CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_MAIN_EXTRA_PARTS_CEF_H_
+#define CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_MAIN_EXTRA_PARTS_CEF_H_
+
+#include <memory>
+
+#include "libcef/browser/request_context_impl.h"
+
+#include "base/task/single_thread_task_runner.h"
+#include "chrome/browser/chrome_browser_main_extra_parts.h"
+
+// Wrapper that owns and initialize the browser memory-related extra parts.
+class ChromeBrowserMainExtraPartsCef : public ChromeBrowserMainExtraParts {
+ public:
+  ChromeBrowserMainExtraPartsCef();
+
+  ChromeBrowserMainExtraPartsCef(const ChromeBrowserMainExtraPartsCef&) =
+      delete;
+  ChromeBrowserMainExtraPartsCef& operator=(
+      const ChromeBrowserMainExtraPartsCef&) = delete;
+
+  ~ChromeBrowserMainExtraPartsCef() override;
+
+  CefRefPtr<CefRequestContextImpl> request_context() const {
+    return global_request_context_;
+  }
+
+  scoped_refptr<base::SingleThreadTaskRunner> background_task_runner() const {
+    return background_task_runner_;
+  }
+  scoped_refptr<base::SingleThreadTaskRunner> user_visible_task_runner() const {
+    return user_visible_task_runner_;
+  }
+  scoped_refptr<base::SingleThreadTaskRunner> user_blocking_task_runner()
+      const {
+    return user_blocking_task_runner_;
+  }
+
+ private:
+  // ChromeBrowserMainExtraParts overrides.
+  void PostProfileInit(Profile* profile, bool is_initial_profile) override;
+  void PreMainMessageLoopRun() override;
+
+  CefRefPtr<CefRequestContextImpl> global_request_context_;
+
+  // Blocking task runners exposed via CefTaskRunner. For consistency with
+  // previous named thread behavior always execute all pending tasks before
+  // shutdown (e.g. to make sure critical data is saved to disk).
+  scoped_refptr<base::SingleThreadTaskRunner> background_task_runner_;
+  scoped_refptr<base::SingleThreadTaskRunner> user_visible_task_runner_;
+  scoped_refptr<base::SingleThreadTaskRunner> user_blocking_task_runner_;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_MAIN_EXTRA_PARTS_CEF_H_
diff --git a/src/libcef/browser/chrome/chrome_content_browser_client_cef.cc b/src/libcef/browser/chrome/chrome_content_browser_client_cef.cc
new file mode 100644
index 0000000..a6572c5
--- /dev/null
+++ b/src/libcef/browser/chrome/chrome_content_browser_client_cef.cc
@@ -0,0 +1,492 @@
+// Copyright 2020 The Chromium Embedded Framework Authors.
+// Portions copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/browser/chrome/chrome_content_browser_client_cef.h"
+
+#include <tuple>
+
+#include "libcef/browser/browser_frame.h"
+#include "libcef/browser/browser_info_manager.h"
+#include "libcef/browser/browser_manager.h"
+#include "libcef/browser/certificate_query.h"
+#include "libcef/browser/chrome/chrome_browser_host_impl.h"
+#include "libcef/browser/chrome/chrome_browser_main_extra_parts_cef.h"
+#include "libcef/browser/context.h"
+#include "libcef/browser/net/chrome_scheme_handler.h"
+#include "libcef/browser/net/throttle_handler.h"
+#include "libcef/browser/net_service/cookie_manager_impl.h"
+#include "libcef/browser/net_service/login_delegate.h"
+#include "libcef/browser/net_service/proxy_url_loader_factory.h"
+#include "libcef/browser/net_service/resource_request_handler_wrapper.h"
+#include "libcef/browser/prefs/browser_prefs.h"
+#include "libcef/browser/prefs/renderer_prefs.h"
+#include "libcef/common/app_manager.h"
+#include "libcef/common/cef_switches.h"
+#include "libcef/common/command_line_impl.h"
+
+#include "base/command_line.h"
+#include "base/path_service.h"
+#include "chrome/browser/chrome_browser_main.h"
+#include "chrome/browser/net/system_network_context_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "content/public/browser/navigation_throttle.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/weak_document_ptr.h"
+#include "content/public/common/content_switches.h"
+#include "third_party/blink/public/common/web_preferences/web_preferences.h"
+#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
+
+namespace {
+
+void HandleExternalProtocolHelper(
+    ChromeContentBrowserClientCef* self,
+    content::WebContents::Getter web_contents_getter,
+    int frame_tree_node_id,
+    content::NavigationUIData* navigation_data,
+    bool is_primary_main_frame,
+    bool is_in_fenced_frame_tree,
+    network::mojom::WebSandboxFlags sandbox_flags,
+    const network::ResourceRequest& resource_request,
+    const absl::optional<url::Origin>& initiating_origin,
+    content::WeakDocumentPtr initiator_document) {
+  // May return nullptr if frame has been deleted or a cross-document navigation
+  // has committed in the same RenderFrameHost.
+  auto initiator_rfh = initiator_document.AsRenderFrameHostIfValid();
+  if (!initiator_rfh) {
+    return;
+  }
+
+  // Match the logic of the original call in
+  // NavigationURLLoaderImpl::PrepareForNonInterceptedRequest.
+  self->HandleExternalProtocol(
+      resource_request.url, web_contents_getter, frame_tree_node_id,
+      navigation_data, is_primary_main_frame, is_in_fenced_frame_tree,
+      sandbox_flags,
+      static_cast<ui::PageTransition>(resource_request.transition_type),
+      resource_request.has_user_gesture, initiating_origin, initiator_rfh,
+      nullptr);
+}
+
+}  // namespace
+
+ChromeContentBrowserClientCef::ChromeContentBrowserClientCef() = default;
+ChromeContentBrowserClientCef::~ChromeContentBrowserClientCef() = default;
+
+std::unique_ptr<content::BrowserMainParts>
+ChromeContentBrowserClientCef::CreateBrowserMainParts(
+    bool is_integration_test) {
+  auto main_parts =
+      ChromeContentBrowserClient::CreateBrowserMainParts(is_integration_test);
+  auto browser_main_parts = std::make_unique<ChromeBrowserMainExtraPartsCef>();
+  browser_main_parts_ = browser_main_parts.get();
+  static_cast<ChromeBrowserMainParts*>(main_parts.get())
+      ->AddParts(std::move(browser_main_parts));
+  return main_parts;
+}
+
+void ChromeContentBrowserClientCef::AppendExtraCommandLineSwitches(
+    base::CommandLine* command_line,
+    int child_process_id) {
+  ChromeContentBrowserClient::AppendExtraCommandLineSwitches(command_line,
+                                                             child_process_id);
+
+  // Necessary to launch sub-processes in the correct mode.
+  command_line->AppendSwitch(switches::kEnableChromeRuntime);
+
+  // Necessary to populate DIR_USER_DATA in sub-processes.
+  // See resource_util.cc GetUserDataPath.
+  base::FilePath user_data_dir;
+  if (base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
+    command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
+  }
+
+  const base::CommandLine* browser_cmd = base::CommandLine::ForCurrentProcess();
+
+  {
+    // Propagate the following switches to all command lines (along with any
+    // associated values) if present in the browser command line.
+    static const char* const kSwitchNames[] = {
+        switches::kUserAgentProductAndVersion,
+    };
+    command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames);
+  }
+
+  const std::string& process_type =
+      command_line->GetSwitchValueASCII(switches::kProcessType);
+  if (process_type == switches::kRendererProcess) {
+    // Propagate the following switches to the renderer command line (along with
+    // any associated values) if present in the browser command line.
+    static const char* const kSwitchNames[] = {
+        switches::kUncaughtExceptionStackSize,
+    };
+    command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames);
+  }
+
+  CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
+  if (app.get()) {
+    CefRefPtr<CefBrowserProcessHandler> handler =
+        app->GetBrowserProcessHandler();
+    if (handler.get()) {
+      CefRefPtr<CefCommandLineImpl> commandLinePtr(
+          new CefCommandLineImpl(command_line, false, false));
+      handler->OnBeforeChildProcessLaunch(commandLinePtr.get());
+      std::ignore = commandLinePtr->Detach(nullptr);
+    }
+  }
+}
+
+void ChromeContentBrowserClientCef::RenderProcessWillLaunch(
+    content::RenderProcessHost* host) {
+  ChromeContentBrowserClient::RenderProcessWillLaunch(host);
+
+  // If the renderer process crashes then the host may already have
+  // CefBrowserInfoManager as an observer. Try to remove it first before adding
+  // to avoid DCHECKs.
+  host->RemoveObserver(CefBrowserInfoManager::GetInstance());
+  host->AddObserver(CefBrowserInfoManager::GetInstance());
+}
+
+void ChromeContentBrowserClientCef::AllowCertificateError(
+    content::WebContents* web_contents,
+    int cert_error,
+    const net::SSLInfo& ssl_info,
+    const GURL& request_url,
+    bool is_main_frame_request,
+    bool strict_enforcement,
+    base::OnceCallback<void(content::CertificateRequestResultType)> callback) {
+  auto returned_callback = certificate_query::AllowCertificateError(
+      web_contents, cert_error, ssl_info, request_url, is_main_frame_request,
+      strict_enforcement, std::move(callback), /*default_disallow=*/false);
+  if (returned_callback.is_null()) {
+    // The error was handled.
+    return;
+  }
+
+  // Proceed with default handling.
+  ChromeContentBrowserClient::AllowCertificateError(
+      web_contents, cert_error, ssl_info, request_url, is_main_frame_request,
+      strict_enforcement, std::move(returned_callback));
+}
+
+bool ChromeContentBrowserClientCef::CanCreateWindow(
+    content::RenderFrameHost* opener,
+    const GURL& opener_url,
+    const GURL& opener_top_level_frame_url,
+    const url::Origin& source_origin,
+    content::mojom::WindowContainerType container_type,
+    const GURL& target_url,
+    const content::Referrer& referrer,
+    const std::string& frame_name,
+    WindowOpenDisposition disposition,
+    const blink::mojom::WindowFeatures& features,
+    bool user_gesture,
+    bool opener_suppressed,
+    bool* no_javascript_access) {
+  // The chrome layer has popup blocker, extensions, etc.
+  if (!ChromeContentBrowserClient::CanCreateWindow(
+          opener, opener_url, opener_top_level_frame_url, source_origin,
+          container_type, target_url, referrer, frame_name, disposition,
+          features, user_gesture, opener_suppressed, no_javascript_access)) {
+    return false;
+  }
+
+  return CefBrowserInfoManager::GetInstance()->CanCreateWindow(
+      opener, target_url, referrer, frame_name, disposition, features,
+      user_gesture, opener_suppressed, no_javascript_access);
+}
+
+void ChromeContentBrowserClientCef::OverrideWebkitPrefs(
+    content::WebContents* web_contents,
+    blink::web_pref::WebPreferences* prefs) {
+  renderer_prefs::SetDefaultPrefs(*prefs);
+
+  ChromeContentBrowserClient::OverrideWebkitPrefs(web_contents, prefs);
+
+  SkColor base_background_color;
+  auto browser = ChromeBrowserHostImpl::GetBrowserForContents(web_contents);
+  if (browser) {
+    renderer_prefs::SetCefPrefs(browser->settings(), *prefs);
+
+    // Set the background color for the WebView.
+    base_background_color = browser->GetBackgroundColor();
+  } else {
+    // We don't know for sure that the browser will be windowless but assume
+    // that the global windowless state is likely to be accurate.
+    base_background_color =
+        CefContext::Get()->GetBackgroundColor(nullptr, STATE_DEFAULT);
+  }
+
+  web_contents->SetPageBaseBackgroundColor(base_background_color);
+}
+
+bool ChromeContentBrowserClientCef::WillCreateURLLoaderFactory(
+    content::BrowserContext* browser_context,
+    content::RenderFrameHost* frame,
+    int render_process_id,
+    URLLoaderFactoryType type,
+    const url::Origin& request_initiator,
+    absl::optional<int64_t> navigation_id,
+    ukm::SourceIdObj ukm_source_id,
+    mojo::PendingReceiver<network::mojom::URLLoaderFactory>* factory_receiver,
+    mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
+        header_client,
+    bool* bypass_redirect_checks,
+    bool* disable_secure_dns,
+    network::mojom::URLLoaderFactoryOverridePtr* factory_override,
+    scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner) {
+  // Don't intercept requests for Profiles that were not created by CEF.
+  // For example, the User Manager profile created via
+  // profiles::CreateSystemProfileForUserManager.
+  auto profile = Profile::FromBrowserContext(browser_context);
+  if (!CefBrowserContext::FromProfile(profile)) {
+    return ChromeContentBrowserClient::WillCreateURLLoaderFactory(
+        browser_context, frame, render_process_id, type, request_initiator,
+        navigation_id, ukm_source_id, factory_receiver, header_client,
+        bypass_redirect_checks, disable_secure_dns, factory_override,
+        navigation_response_task_runner);
+  }
+
+  // Based on content/browser/devtools/devtools_instrumentation.cc
+  // WillCreateURLLoaderFactoryInternal.
+  network::mojom::URLLoaderFactoryOverridePtr cef_override(
+      network::mojom::URLLoaderFactoryOverride::New());
+  // If caller passed some existing overrides, use those.
+  // Otherwise, use our local var, then if handlers actually
+  // decide to intercept, move it to |factory_override|.
+  network::mojom::URLLoaderFactoryOverridePtr* handler_override =
+      factory_override && *factory_override ? factory_override : &cef_override;
+  network::mojom::URLLoaderFactoryOverride* intercepting_factory =
+      handler_override->get();
+
+  // If we're the first interceptor to install an override, make a
+  // remote/receiver pair, then handle this similarly to appending
+  // a proxy to existing override.
+  if (!intercepting_factory->overriding_factory) {
+    DCHECK(!intercepting_factory->overridden_factory_receiver);
+    intercepting_factory->overridden_factory_receiver =
+        intercepting_factory->overriding_factory
+            .InitWithNewPipeAndPassReceiver();
+  }
+
+  // TODO(chrome): Is it necessary to proxy |header_client| callbacks?
+  bool use_proxy = ChromeContentBrowserClient::WillCreateURLLoaderFactory(
+      browser_context, frame, render_process_id, type, request_initiator,
+      navigation_id, ukm_source_id,
+      &(intercepting_factory->overridden_factory_receiver),
+      /*header_client=*/nullptr, bypass_redirect_checks, disable_secure_dns,
+      handler_override, navigation_response_task_runner);
+
+  if (use_proxy) {
+    DCHECK(intercepting_factory->overriding_factory);
+    DCHECK(intercepting_factory->overridden_factory_receiver);
+    if (!factory_override) {
+      // Not a subresource navigation, so just override the target receiver.
+      mojo::FusePipes(std::move(*factory_receiver),
+                      std::move(cef_override->overriding_factory));
+      *factory_receiver = std::move(cef_override->overridden_factory_receiver);
+    } else if (!*factory_override) {
+      // No other overrides, so just returns ours as is.
+      *factory_override = network::mojom::URLLoaderFactoryOverride::New(
+          std::move(cef_override->overriding_factory),
+          std::move(cef_override->overridden_factory_receiver), false);
+    }
+    // ... else things are already taken care of, as handler_override was
+    // pointing to factory override and we've done all magic in-place.
+    DCHECK(!cef_override->overriding_factory);
+    DCHECK(!cef_override->overridden_factory_receiver);
+  }
+
+  auto request_handler = net_service::CreateInterceptedRequestHandler(
+      browser_context, frame, render_process_id,
+      type == URLLoaderFactoryType::kNavigation,
+      type == URLLoaderFactoryType::kDownload, request_initiator);
+
+  net_service::ProxyURLLoaderFactory::CreateProxy(
+      browser_context, factory_receiver, header_client,
+      std::move(request_handler));
+
+  return true;
+}
+
+bool ChromeContentBrowserClientCef::HandleExternalProtocol(
+    const GURL& url,
+    content::WebContents::Getter web_contents_getter,
+    int frame_tree_node_id,
+    content::NavigationUIData* navigation_data,
+    bool is_primary_main_frame,
+    bool is_in_fenced_frame_tree,
+    network::mojom::WebSandboxFlags sandbox_flags,
+    ui::PageTransition page_transition,
+    bool has_user_gesture,
+    const absl::optional<url::Origin>& initiating_origin,
+    content::RenderFrameHost* initiator_document,
+    mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
+  // |out_factory| will be non-nullptr when this method is initially called
+  // from NavigationURLLoaderImpl::PrepareForNonInterceptedRequest.
+  if (out_factory) {
+    // Let the other HandleExternalProtocol variant handle the request.
+    return false;
+  }
+
+  // The request was unhandled and we've recieved a callback from
+  // HandleExternalProtocolHelper. Forward to the chrome layer for default
+  // handling.
+  return ChromeContentBrowserClient::HandleExternalProtocol(
+      url, web_contents_getter, frame_tree_node_id, navigation_data,
+      is_primary_main_frame, is_in_fenced_frame_tree, sandbox_flags,
+      page_transition, has_user_gesture, initiating_origin, initiator_document,
+      nullptr);
+}
+
+bool ChromeContentBrowserClientCef::HandleExternalProtocol(
+    content::WebContents::Getter web_contents_getter,
+    int frame_tree_node_id,
+    content::NavigationUIData* navigation_data,
+    bool is_primary_main_frame,
+    bool is_in_fenced_frame_tree,
+    network::mojom::WebSandboxFlags sandbox_flags,
+    const network::ResourceRequest& resource_request,
+    const absl::optional<url::Origin>& initiating_origin,
+    content::RenderFrameHost* initiator_document,
+    mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
+  mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver =
+      out_factory->InitWithNewPipeAndPassReceiver();
+
+  auto weak_initiator_document = initiator_document
+                                     ? initiator_document->GetWeakDocumentPtr()
+                                     : content::WeakDocumentPtr();
+
+  // HandleExternalProtocolHelper may be called if nothing handles the request.
+  auto request_handler = net_service::CreateInterceptedRequestHandler(
+      web_contents_getter, frame_tree_node_id, resource_request,
+      base::BindRepeating(HandleExternalProtocolHelper, base::Unretained(this),
+                          web_contents_getter, frame_tree_node_id,
+                          navigation_data, is_primary_main_frame,
+                          is_in_fenced_frame_tree, sandbox_flags,
+                          resource_request, initiating_origin,
+                          std::move(weak_initiator_document)));
+
+  net_service::ProxyURLLoaderFactory::CreateProxy(
+      web_contents_getter, std::move(receiver), std::move(request_handler));
+  return true;
+}
+
+std::vector<std::unique_ptr<content::NavigationThrottle>>
+ChromeContentBrowserClientCef::CreateThrottlesForNavigation(
+    content::NavigationHandle* navigation_handle) {
+  auto throttles = ChromeContentBrowserClient::CreateThrottlesForNavigation(
+      navigation_handle);
+  throttle::CreateThrottlesForNavigation(navigation_handle, throttles);
+  return throttles;
+}
+
+bool ChromeContentBrowserClientCef::ConfigureNetworkContextParams(
+    content::BrowserContext* context,
+    bool in_memory,
+    const base::FilePath& relative_partition_path,
+    network::mojom::NetworkContextParams* network_context_params,
+    cert_verifier::mojom::CertVerifierCreationParams*
+        cert_verifier_creation_params) {
+  // This method may be called during shutdown when using multi-threaded
+  // message loop mode. In that case exit early to avoid crashes.
+  if (!SystemNetworkContextManager::GetInstance()) {
+    // Cancel NetworkContext creation in
+    // StoragePartitionImpl::InitNetworkContext.
+    return false;
+  }
+
+  ChromeContentBrowserClient::ConfigureNetworkContextParams(
+      context, in_memory, relative_partition_path, network_context_params,
+      cert_verifier_creation_params);
+
+  auto cef_context = CefBrowserContext::FromBrowserContext(context);
+  network_context_params->cookieable_schemes =
+      cef_context ? cef_context->GetCookieableSchemes()
+                  : CefBrowserContext::GetGlobalCookieableSchemes();
+
+  return true;
+}
+
+std::unique_ptr<content::LoginDelegate>
+ChromeContentBrowserClientCef::CreateLoginDelegate(
+    const net::AuthChallengeInfo& auth_info,
+    content::WebContents* web_contents,
+    const content::GlobalRequestID& request_id,
+    bool is_request_for_main_frame,
+    const GURL& url,
+    scoped_refptr<net::HttpResponseHeaders> response_headers,
+    bool first_auth_attempt,
+    LoginAuthRequiredCallback auth_required_callback) {
+  // |web_contents| is nullptr for CefURLRequests without an associated frame.
+  if (!web_contents || base::CommandLine::ForCurrentProcess()->HasSwitch(
+                           switches::kDisableChromeLoginPrompt)) {
+    // Delegate auth callbacks to GetAuthCredentials.
+    return std::make_unique<net_service::LoginDelegate>(
+        auth_info, web_contents, request_id, url,
+        std::move(auth_required_callback));
+  }
+
+  return ChromeContentBrowserClient::CreateLoginDelegate(
+      auth_info, web_contents, request_id, is_request_for_main_frame, url,
+      response_headers, first_auth_attempt, std::move(auth_required_callback));
+}
+
+void ChromeContentBrowserClientCef::BrowserURLHandlerCreated(
+    content::BrowserURLHandler* handler) {
+  // Register the Chrome handlers first for proper URL rewriting.
+  ChromeContentBrowserClient::BrowserURLHandlerCreated(handler);
+  scheme::BrowserURLHandlerCreated(handler);
+}
+
+bool ChromeContentBrowserClientCef::IsWebUIAllowedToMakeNetworkRequests(
+    const url::Origin& origin) {
+  return scheme::IsWebUIAllowedToMakeNetworkRequests(origin);
+}
+
+void ChromeContentBrowserClientCef::ExposeInterfacesToRenderer(
+    service_manager::BinderRegistry* registry,
+    blink::AssociatedInterfaceRegistry* associated_registry,
+    content::RenderProcessHost* host) {
+  ChromeContentBrowserClient::ExposeInterfacesToRenderer(
+      registry, associated_registry, host);
+
+  CefBrowserManager::ExposeInterfacesToRenderer(registry, associated_registry,
+                                                host);
+}
+
+void ChromeContentBrowserClientCef::RegisterBrowserInterfaceBindersForFrame(
+    content::RenderFrameHost* render_frame_host,
+    mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
+  ChromeContentBrowserClient::RegisterBrowserInterfaceBindersForFrame(
+      render_frame_host, map);
+
+  CefBrowserFrame::RegisterBrowserInterfaceBindersForFrame(render_frame_host,
+                                                           map);
+}
+
+CefRefPtr<CefRequestContextImpl>
+ChromeContentBrowserClientCef::request_context() const {
+  return browser_main_parts_->request_context();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+ChromeContentBrowserClientCef::background_task_runner() const {
+  return browser_main_parts_->background_task_runner();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+ChromeContentBrowserClientCef::user_visible_task_runner() const {
+  return browser_main_parts_->user_visible_task_runner();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+ChromeContentBrowserClientCef::user_blocking_task_runner() const {
+  return browser_main_parts_->user_blocking_task_runner();
+}
diff --git a/src/libcef/browser/chrome/chrome_content_browser_client_cef.h b/src/libcef/browser/chrome/chrome_content_browser_client_cef.h
new file mode 100644
index 0000000..4b3bdd1
--- /dev/null
+++ b/src/libcef/browser/chrome/chrome_content_browser_client_cef.h
@@ -0,0 +1,139 @@
+// Copyright 2020 The Chromium Embedded Framework Authors.
+// Portions copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_BROWSER_CHROME_CHROME_CONTENT_BROWSER_CLIENT_CEF_
+#define CEF_LIBCEF_BROWSER_CHROME_CHROME_CONTENT_BROWSER_CLIENT_CEF_
+
+#include <memory>
+
+#include "libcef/browser/request_context_impl.h"
+
+#include "chrome/browser/chrome_content_browser_client.h"
+
+class ChromeBrowserMainExtraPartsCef;
+
+// CEF override of ChromeContentBrowserClient.
+class ChromeContentBrowserClientCef : public ChromeContentBrowserClient {
+ public:
+  ChromeContentBrowserClientCef();
+
+  ChromeContentBrowserClientCef(const ChromeContentBrowserClientCef&) = delete;
+  ChromeContentBrowserClientCef& operator=(
+      const ChromeContentBrowserClientCef&) = delete;
+
+  ~ChromeContentBrowserClientCef() override;
+
+  // ChromeContentBrowserClient overrides.
+  std::unique_ptr<content::BrowserMainParts> CreateBrowserMainParts(
+      bool is_integration_test) override;
+  void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
+                                      int child_process_id) override;
+  void RenderProcessWillLaunch(content::RenderProcessHost* host) override;
+  void AllowCertificateError(
+      content::WebContents* web_contents,
+      int cert_error,
+      const net::SSLInfo& ssl_info,
+      const GURL& request_url,
+      bool is_main_frame_request,
+      bool strict_enforcement,
+      base::OnceCallback<void(content::CertificateRequestResultType)> callback)
+      override;
+  bool CanCreateWindow(content::RenderFrameHost* opener,
+                       const GURL& opener_url,
+                       const GURL& opener_top_level_frame_url,
+                       const url::Origin& source_origin,
+                       content::mojom::WindowContainerType container_type,
+                       const GURL& target_url,
+                       const content::Referrer& referrer,
+                       const std::string& frame_name,
+                       WindowOpenDisposition disposition,
+                       const blink::mojom::WindowFeatures& features,
+                       bool user_gesture,
+                       bool opener_suppressed,
+                       bool* no_javascript_access) override;
+  void OverrideWebkitPrefs(content::WebContents* web_contents,
+                           blink::web_pref::WebPreferences* prefs) override;
+  bool WillCreateURLLoaderFactory(
+      content::BrowserContext* browser_context,
+      content::RenderFrameHost* frame,
+      int render_process_id,
+      URLLoaderFactoryType type,
+      const url::Origin& request_initiator,
+      absl::optional<int64_t> navigation_id,
+      ukm::SourceIdObj ukm_source_id,
+      mojo::PendingReceiver<network::mojom::URLLoaderFactory>* factory_receiver,
+      mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
+          header_client,
+      bool* bypass_redirect_checks,
+      bool* disable_secure_dns,
+      network::mojom::URLLoaderFactoryOverridePtr* factory_override,
+      scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner)
+      override;
+  bool HandleExternalProtocol(
+      const GURL& url,
+      content::WebContents::Getter web_contents_getter,
+      int frame_tree_node_id,
+      content::NavigationUIData* navigation_data,
+      bool is_primary_main_frame,
+      bool is_in_fenced_frame_tree,
+      network::mojom::WebSandboxFlags sandbox_flags,
+      ui::PageTransition page_transition,
+      bool has_user_gesture,
+      const absl::optional<url::Origin>& initiating_origin,
+      content::RenderFrameHost* initiator_document,
+      mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory)
+      override;
+  bool HandleExternalProtocol(
+      content::WebContents::Getter web_contents_getter,
+      int frame_tree_node_id,
+      content::NavigationUIData* navigation_data,
+      bool is_primary_main_frame,
+      bool is_in_fenced_frame_tree,
+      network::mojom::WebSandboxFlags sandbox_flags,
+      const network::ResourceRequest& request,
+      const absl::optional<url::Origin>& initiating_origin,
+      content::RenderFrameHost* initiator_document,
+      mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory)
+      override;
+  std::vector<std::unique_ptr<content::NavigationThrottle>>
+  CreateThrottlesForNavigation(
+      content::NavigationHandle* navigation_handle) override;
+  bool ConfigureNetworkContextParams(
+      content::BrowserContext* context,
+      bool in_memory,
+      const base::FilePath& relative_partition_path,
+      network::mojom::NetworkContextParams* network_context_params,
+      cert_verifier::mojom::CertVerifierCreationParams*
+          cert_verifier_creation_params) override;
+  std::unique_ptr<content::LoginDelegate> CreateLoginDelegate(
+      const net::AuthChallengeInfo& auth_info,
+      content::WebContents* web_contents,
+      const content::GlobalRequestID& request_id,
+      bool is_request_for_main_frame,
+      const GURL& url,
+      scoped_refptr<net::HttpResponseHeaders> response_headers,
+      bool first_auth_attempt,
+      LoginAuthRequiredCallback auth_required_callback) override;
+  void BrowserURLHandlerCreated(content::BrowserURLHandler* handler) override;
+  bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin) override;
+  void ExposeInterfacesToRenderer(
+      service_manager::BinderRegistry* registry,
+      blink::AssociatedInterfaceRegistry* associated_registry,
+      content::RenderProcessHost* render_process_host) override;
+  void RegisterBrowserInterfaceBindersForFrame(
+      content::RenderFrameHost* render_frame_host,
+      mojo::BinderMapWithContext<content::RenderFrameHost*>* map) override;
+
+  CefRefPtr<CefRequestContextImpl> request_context() const;
+
+  scoped_refptr<base::SingleThreadTaskRunner> background_task_runner() const;
+  scoped_refptr<base::SingleThreadTaskRunner> user_visible_task_runner() const;
+  scoped_refptr<base::SingleThreadTaskRunner> user_blocking_task_runner() const;
+
+ private:
+  ChromeBrowserMainExtraPartsCef* browser_main_parts_ = nullptr;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_CHROME_CHROME_CONTENT_BROWSER_CLIENT_CEF_
diff --git a/src/libcef/browser/chrome/chrome_context_menu_handler.cc b/src/libcef/browser/chrome/chrome_context_menu_handler.cc
new file mode 100644
index 0000000..95fa540
--- /dev/null
+++ b/src/libcef/browser/chrome/chrome_context_menu_handler.cc
@@ -0,0 +1,214 @@
+// Copyright (c) 2021 The Chromium Embedded Framework 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 "libcef/browser/chrome/chrome_context_menu_handler.h"
+
+#include "libcef/browser/browser_host_base.h"
+#include "libcef/browser/context_menu_params_impl.h"
+#include "libcef/browser/simple_menu_model_impl.h"
+
+#include "chrome/browser/renderer_context_menu/render_view_context_menu.h"
+
+namespace context_menu {
+
+namespace {
+
+// Lifespan is controlled by RenderViewContextMenu.
+class CefContextMenuObserver : public RenderViewContextMenuObserver,
+                               public CefSimpleMenuModelImpl::StateDelegate {
+ public:
+  CefContextMenuObserver(RenderViewContextMenu* context_menu,
+                         CefRefPtr<CefBrowserHostBase> browser,
+                         CefRefPtr<CefContextMenuHandler> handler)
+      : context_menu_(context_menu), browser_(browser), handler_(handler) {}
+
+  CefContextMenuObserver(const CefContextMenuObserver&) = delete;
+  CefContextMenuObserver& operator=(const CefContextMenuObserver&) = delete;
+
+  // RenderViewContextMenuObserver methods:
+
+  void InitMenu(const content::ContextMenuParams& params) override {
+    params_ = new CefContextMenuParamsImpl(
+        const_cast<content::ContextMenuParams*>(&context_menu_->params()));
+    model_ = new CefSimpleMenuModelImpl(
+        const_cast<ui::SimpleMenuModel*>(&context_menu_->menu_model()),
+        context_menu_, this, /*is_owned=*/false, /*is_popup=*/false);
+
+    handler_->OnBeforeContextMenu(browser_, GetFrame(), params_, model_);
+  }
+
+  bool IsCommandIdSupported(int command_id) override {
+    // Always claim support for the reserved user ID range.
+    if (command_id >= MENU_ID_USER_FIRST && command_id <= MENU_ID_USER_LAST) {
+      return true;
+    }
+
+    // Also claim support in specific cases where an ItemInfo exists.
+    return GetItemInfo(command_id) != nullptr;
+  }
+
+  // Only called if IsCommandIdSupported() returns true.
+  bool IsCommandIdEnabled(int command_id) override {
+    // Always return true to use the SimpleMenuModel state.
+    return true;
+  }
+
+  // Only called if IsCommandIdSupported() returns true.
+  bool IsCommandIdChecked(int command_id) override {
+    auto* info = GetItemInfo(command_id);
+    return info ? info->checked : false;
+  }
+
+  // Only called if IsCommandIdSupported() returns true.
+  bool GetAccelerator(int command_id, ui::Accelerator* accel) override {
+    auto* info = GetItemInfo(command_id);
+    if (info && info->accel) {
+      *accel = *info->accel;
+      return true;
+    }
+    return false;
+  }
+
+  void CommandWillBeExecuted(int command_id) override {
+    if (handler_->OnContextMenuCommand(browser_, GetFrame(), params_,
+                                       command_id, EVENTFLAG_NONE)) {
+      // Create an ItemInfo so that we get the ExecuteCommand() callback
+      // instead of the default handler.
+      GetOrCreateItemInfo(command_id);
+    }
+  }
+
+  // Only called if IsCommandIdSupported() returns true.
+  void ExecuteCommand(int command_id) override {
+    auto* info = GetItemInfo(command_id);
+    if (info) {
+      // In case it was added in CommandWillBeExecuted().
+      MaybeDeleteItemInfo(command_id, info);
+    }
+  }
+
+  void OnMenuClosed() override {
+    handler_->OnContextMenuDismissed(browser_, GetFrame());
+    model_->Detach();
+
+    // Clear stored state because this object won't be deleted until a new
+    // context menu is created or the associated browser is destroyed.
+    browser_ = nullptr;
+    handler_ = nullptr;
+    params_ = nullptr;
+    model_ = nullptr;
+    iteminfomap_.clear();
+  }
+
+  // CefSimpleMenuModelImpl::StateDelegate methods:
+
+  void SetChecked(int command_id, bool checked) override {
+    // No-op if already at the default state.
+    if (!checked && !GetItemInfo(command_id)) {
+      return;
+    }
+
+    auto* info = GetOrCreateItemInfo(command_id);
+    info->checked = checked;
+    if (!checked) {
+      MaybeDeleteItemInfo(command_id, info);
+    }
+  }
+
+  void SetAccelerator(int command_id,
+                      absl::optional<ui::Accelerator> accel) override {
+    // No-op if already at the default state.
+    if (!accel && !GetItemInfo(command_id)) {
+      return;
+    }
+
+    auto* info = GetOrCreateItemInfo(command_id);
+    info->accel = accel;
+    if (!accel) {
+      MaybeDeleteItemInfo(command_id, info);
+    }
+  }
+
+ private:
+  struct ItemInfo {
+    ItemInfo() {}
+
+    bool checked = false;
+    absl::optional<ui::Accelerator> accel;
+  };
+
+  ItemInfo* GetItemInfo(int command_id) {
+    auto it = iteminfomap_.find(command_id);
+    if (it != iteminfomap_.end()) {
+      return &it->second;
+    }
+    return nullptr;
+  }
+
+  ItemInfo* GetOrCreateItemInfo(int command_id) {
+    if (auto info = GetItemInfo(command_id)) {
+      return info;
+    }
+
+    auto result = iteminfomap_.insert(std::make_pair(command_id, ItemInfo()));
+    return &result.first->second;
+  }
+
+  void MaybeDeleteItemInfo(int command_id, ItemInfo* info) {
+    // Remove if all info has reverted to the default state.
+    if (!info->checked && !info->accel) {
+      auto it = iteminfomap_.find(command_id);
+      iteminfomap_.erase(it);
+    }
+  }
+
+  CefRefPtr<CefFrame> GetFrame() const {
+    CefRefPtr<CefFrame> frame;
+
+    // May return nullptr if the frame is destroyed while the menu is pending.
+    auto* rfh = context_menu_->GetRenderFrameHost();
+    if (rfh) {
+      frame = browser_->GetFrameForHost(rfh);
+    }
+    if (!frame) {
+      frame = browser_->GetMainFrame();
+    }
+    return frame;
+  }
+
+  RenderViewContextMenu* const context_menu_;
+  CefRefPtr<CefBrowserHostBase> browser_;
+  CefRefPtr<CefContextMenuHandler> handler_;
+  CefRefPtr<CefContextMenuParams> params_;
+  CefRefPtr<CefSimpleMenuModelImpl> model_;
+
+  // Map of command_id to ItemInfo.
+  using ItemInfoMap = std::map<int, ItemInfo>;
+  ItemInfoMap iteminfomap_;
+};
+
+std::unique_ptr<RenderViewContextMenuObserver> MenuCreatedCallback(
+    RenderViewContextMenu* context_menu) {
+  auto browser = CefBrowserHostBase::GetBrowserForContents(
+      context_menu->source_web_contents());
+  if (browser) {
+    if (auto client = browser->GetClient()) {
+      if (auto handler = client->GetContextMenuHandler()) {
+        return std::make_unique<CefContextMenuObserver>(context_menu, browser,
+                                                        handler);
+      }
+    }
+  }
+
+  return nullptr;
+}
+
+}  // namespace
+
+void RegisterMenuCreatedCallback() {
+  RenderViewContextMenu::RegisterMenuCreatedCallback(
+      base::BindRepeating(&MenuCreatedCallback));
+}
+
+}  // namespace context_menu
diff --git a/src/libcef/browser/chrome/chrome_context_menu_handler.h b/src/libcef/browser/chrome/chrome_context_menu_handler.h
new file mode 100644
index 0000000..12c31f1
--- /dev/null
+++ b/src/libcef/browser/chrome/chrome_context_menu_handler.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2021 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_CHROME_CHROME_CONTEXT_MENU_HANDLER_H_
+#define CEF_LIBCEF_BROWSER_CHROME_CHROME_CONTEXT_MENU_HANDLER_H_
+#pragma once
+
+namespace context_menu {
+
+// Register the context menu created callback.
+void RegisterMenuCreatedCallback();
+
+}  // namespace context_menu
+
+#endif  // CEF_LIBCEF_BROWSER_CHROME_CHROME_CONTEXT_MENU_HANDLER_H_
diff --git a/src/libcef/browser/chrome/extensions/chrome_mime_handler_view_guest_delegate_cef.cc b/src/libcef/browser/chrome/extensions/chrome_mime_handler_view_guest_delegate_cef.cc
new file mode 100644
index 0000000..1dea160
--- /dev/null
+++ b/src/libcef/browser/chrome/extensions/chrome_mime_handler_view_guest_delegate_cef.cc
@@ -0,0 +1,48 @@
+// Copyright 2015 The Chromium Embedded Framework Authors.
+// Portions copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/browser/chrome/extensions/chrome_mime_handler_view_guest_delegate_cef.h"
+
+#include "libcef/browser/browser_host_base.h"
+#include "libcef/browser/browser_info.h"
+
+#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
+
+namespace extensions {
+
+ChromeMimeHandlerViewGuestDelegateCef::ChromeMimeHandlerViewGuestDelegateCef(
+    MimeHandlerViewGuest* guest)
+    : guest_(guest), owner_web_contents_(guest_->owner_web_contents()) {}
+
+ChromeMimeHandlerViewGuestDelegateCef::
+    ~ChromeMimeHandlerViewGuestDelegateCef() = default;
+
+void ChromeMimeHandlerViewGuestDelegateCef::OnGuestAttached() {
+  content::WebContents* web_contents = guest_->web_contents();
+  DCHECK(web_contents);
+
+  auto owner_browser =
+      CefBrowserHostBase::GetBrowserForContents(owner_web_contents_);
+  DCHECK(owner_browser);
+
+  // Associate guest state information with the owner browser.
+  owner_browser->browser_info()->MaybeCreateFrame(
+      web_contents->GetPrimaryMainFrame(), true /* is_guest_view */);
+}
+
+void ChromeMimeHandlerViewGuestDelegateCef::OnGuestDetached() {
+  content::WebContents* web_contents = guest_->web_contents();
+  DCHECK(web_contents);
+
+  auto owner_browser =
+      CefBrowserHostBase::GetBrowserForContents(owner_web_contents_);
+  DCHECK(owner_browser);
+
+  // Disassociate guest state information with the owner browser.
+  owner_browser->browser_info()->RemoveFrame(
+      web_contents->GetPrimaryMainFrame());
+}
+
+}  // namespace extensions
diff --git a/src/libcef/browser/chrome/extensions/chrome_mime_handler_view_guest_delegate_cef.h b/src/libcef/browser/chrome/extensions/chrome_mime_handler_view_guest_delegate_cef.h
new file mode 100644
index 0000000..8d9216b
--- /dev/null
+++ b/src/libcef/browser/chrome/extensions/chrome_mime_handler_view_guest_delegate_cef.h
@@ -0,0 +1,37 @@
+// Copyright 2015 The Chromium Embedded Framework Authors.
+// Portions copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_BROWSER_CHROME_EXTENSIONS_CHROME_MIME_HANDLER_VIEW_GUEST_DELEGATE_CEF_H_
+#define CEF_LIBCEF_BROWSER_CHROME_EXTENSIONS_CHROME_MIME_HANDLER_VIEW_GUEST_DELEGATE_CEF_H_
+
+#include "chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_guest_delegate.h"
+#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
+
+namespace extensions {
+
+class ChromeMimeHandlerViewGuestDelegateCef
+    : public ChromeMimeHandlerViewGuestDelegate {
+ public:
+  explicit ChromeMimeHandlerViewGuestDelegateCef(MimeHandlerViewGuest* guest);
+
+  ChromeMimeHandlerViewGuestDelegateCef(
+      const ChromeMimeHandlerViewGuestDelegateCef&) = delete;
+  ChromeMimeHandlerViewGuestDelegateCef& operator=(
+      const ChromeMimeHandlerViewGuestDelegateCef&) = delete;
+
+  ~ChromeMimeHandlerViewGuestDelegateCef() override;
+
+  // MimeHandlerViewGuestDelegate methods.
+  void OnGuestAttached() override;
+  void OnGuestDetached() override;
+
+ private:
+  MimeHandlerViewGuest* guest_;  // Owns us.
+  content::WebContents* owner_web_contents_;
+};
+
+}  // namespace extensions
+
+#endif  // CEF_LIBCEF_BROWSER_CHROME_EXTENSIONS_CHROME_MIME_HANDLER_VIEW_GUEST_DELEGATE_CEF_H_
diff --git a/src/libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.cc b/src/libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.cc
new file mode 100644
index 0000000..c650090
--- /dev/null
+++ b/src/libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.cc
@@ -0,0 +1,29 @@
+// Copyright 2022 The Chromium Embedded Framework 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 "libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.h"
+
+#include "include/views/cef_browser_view.h"
+#include "libcef/browser/chrome/views/chrome_child_window.h"
+
+CefBrowserPlatformDelegateChromeChildWindow::
+    CefBrowserPlatformDelegateChromeChildWindow(
+        std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
+        CefRefPtr<CefBrowserViewImpl> browser_view)
+    : CefBrowserPlatformDelegateChromeViews(std::move(native_delegate),
+                                            browser_view) {}
+
+void CefBrowserPlatformDelegateChromeChildWindow::CloseHostWindow() {
+  native_delegate_->CloseHostWindow();
+}
+
+void CefBrowserPlatformDelegateChromeChildWindow::SetFocus(bool focus) {
+  native_delegate_->SetFocus(focus);
+}
+
+#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC))
+void CefBrowserPlatformDelegateChromeChildWindow::NotifyMoveOrResizeStarted() {
+  native_delegate_->NotifyMoveOrResizeStarted();
+}
+#endif
diff --git a/src/libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.h b/src/libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.h
new file mode 100644
index 0000000..b709510
--- /dev/null
+++ b/src/libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.h
@@ -0,0 +1,29 @@
+// Copyright 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_CHROME_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_CHILD_WINDOW_H_
+#define CEF_LIBCEF_BROWSER_CHROME_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_CHILD_WINDOW_H_
+
+#include "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h"
+
+// Implementation of Chrome-based browser functionality.
+class CefBrowserPlatformDelegateChromeChildWindow
+    : public CefBrowserPlatformDelegateChromeViews {
+ public:
+  CefBrowserPlatformDelegateChromeChildWindow(
+      std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
+      CefRefPtr<CefBrowserViewImpl> browser_view);
+
+  // CefBrowserPlatformDelegate overrides.
+  void CloseHostWindow() override;
+  void SetFocus(bool focus) override;
+
+#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC))
+  void NotifyMoveOrResizeStarted() override;
+#endif
+
+  bool HasExternalParent() const override { return true; }
+};
+
+#endif  // CEF_LIBCEF_BROWSER_CHROME_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_CHILD_WINDOW_H_
diff --git a/src/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.cc b/src/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.cc
new file mode 100644
index 0000000..78f1d84
--- /dev/null
+++ b/src/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.cc
@@ -0,0 +1,217 @@
+// Copyright 2021 The Chromium Embedded Framework 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 "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h"
+
+#include "include/views/cef_window.h"
+#include "libcef/browser/views/window_impl.h"
+
+#include "chrome/browser/devtools/devtools_window.h"
+#include "chrome/browser/ui/browser.h"
+#include "components/zoom/zoom_controller.h"
+#include "ui/views/widget/widget.h"
+
+namespace {
+
+// Default popup window delegate implementation.
+class PopupWindowDelegate : public CefWindowDelegate {
+ public:
+  explicit PopupWindowDelegate(CefRefPtr<CefBrowserView> browser_view)
+      : browser_view_(browser_view) {}
+
+  PopupWindowDelegate(const PopupWindowDelegate&) = delete;
+  PopupWindowDelegate& operator=(const PopupWindowDelegate&) = delete;
+
+  void OnWindowCreated(CefRefPtr<CefWindow> window) override {
+    window->AddChildView(browser_view_);
+    window->Show();
+    browser_view_->RequestFocus();
+  }
+
+  void OnWindowDestroyed(CefRefPtr<CefWindow> window) override {
+    browser_view_ = nullptr;
+  }
+
+  bool CanClose(CefRefPtr<CefWindow> window) override {
+    CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
+    if (browser) {
+      return browser->GetHost()->TryCloseBrowser();
+    }
+    return true;
+  }
+
+ private:
+  CefRefPtr<CefBrowserView> browser_view_;
+
+  IMPLEMENT_REFCOUNTING(PopupWindowDelegate);
+};
+
+}  // namespace
+
+CefBrowserPlatformDelegateChromeViews::CefBrowserPlatformDelegateChromeViews(
+    std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
+    CefRefPtr<CefBrowserViewImpl> browser_view)
+    : CefBrowserPlatformDelegateChrome(std::move(native_delegate)) {
+  if (browser_view) {
+    SetBrowserView(browser_view);
+  }
+}
+
+void CefBrowserPlatformDelegateChromeViews::SetBrowserView(
+    CefRefPtr<CefBrowserViewImpl> browser_view) {
+  DCHECK(!browser_view_);
+  DCHECK(browser_view);
+  browser_view_ = browser_view;
+}
+
+void CefBrowserPlatformDelegateChromeViews::WebContentsCreated(
+    content::WebContents* web_contents,
+    bool owned) {
+  CefBrowserPlatformDelegateChrome::WebContentsCreated(web_contents, owned);
+  browser_view_->WebContentsCreated(web_contents);
+}
+
+void CefBrowserPlatformDelegateChromeViews::BrowserCreated(
+    CefBrowserHostBase* browser) {
+  CefBrowserPlatformDelegateChrome::BrowserCreated(browser);
+  browser_view_->BrowserCreated(browser, base::RepeatingClosure());
+}
+
+void CefBrowserPlatformDelegateChromeViews::NotifyBrowserCreated() {
+  if (auto delegate = browser_view_->delegate()) {
+    delegate->OnBrowserCreated(browser_view_, browser_);
+
+    // DevTools windows hide the notification bubble by default. However, we
+    // don't currently have the ability to intercept WebContents creation via
+    // DevToolsWindow::Create(), so |show_by_default| will always be true here.
+    const bool show_by_default =
+        !DevToolsWindow::IsDevToolsWindow(web_contents_);
+
+    bool show_zoom_bubble = show_by_default;
+    const auto& state = browser_->settings().chrome_zoom_bubble;
+    if (show_by_default && state == STATE_DISABLED) {
+      show_zoom_bubble = false;
+    } else if (!show_by_default && state == STATE_ENABLED) {
+      show_zoom_bubble = true;
+    }
+
+    if (show_zoom_bubble != show_by_default) {
+      // We may be called before TabHelpers::AttachTabHelpers(), so create
+      // the ZoomController if necessary.
+      zoom::ZoomController::CreateForWebContents(web_contents_);
+      zoom::ZoomController::FromWebContents(web_contents_)
+          ->SetShowsNotificationBubble(show_zoom_bubble);
+    }
+  }
+}
+
+void CefBrowserPlatformDelegateChromeViews::NotifyBrowserDestroyed() {
+  if (browser_view_->delegate()) {
+    browser_view_->delegate()->OnBrowserDestroyed(browser_view_, browser_);
+  }
+}
+
+void CefBrowserPlatformDelegateChromeViews::BrowserDestroyed(
+    CefBrowserHostBase* browser) {
+  CefBrowserPlatformDelegateChrome::BrowserDestroyed(browser);
+  browser_view_->BrowserDestroyed(browser);
+}
+
+void CefBrowserPlatformDelegateChromeViews::CloseHostWindow() {
+  views::Widget* widget = GetWindowWidget();
+  if (widget && !widget->IsClosed()) {
+    widget->Close();
+  }
+}
+
+CefWindowHandle CefBrowserPlatformDelegateChromeViews::GetHostWindowHandle()
+    const {
+  return view_util::GetWindowHandle(GetWindowWidget());
+}
+
+views::Widget* CefBrowserPlatformDelegateChromeViews::GetWindowWidget() const {
+  if (browser_view_->root_view()) {
+    return browser_view_->root_view()->GetWidget();
+  }
+  return nullptr;
+}
+
+CefRefPtr<CefBrowserView>
+CefBrowserPlatformDelegateChromeViews::GetBrowserView() const {
+  return browser_view_.get();
+}
+
+void CefBrowserPlatformDelegateChromeViews::PopupWebContentsCreated(
+    const CefBrowserSettings& settings,
+    CefRefPtr<CefClient> client,
+    content::WebContents* new_web_contents,
+    CefBrowserPlatformDelegate* new_platform_delegate,
+    bool is_devtools) {
+  // Default popup handling may not be Views-hosted.
+  if (!new_platform_delegate->IsViewsHosted()) {
+    return;
+  }
+
+  auto* new_platform_delegate_impl =
+      static_cast<CefBrowserPlatformDelegateChromeViews*>(
+          new_platform_delegate);
+
+  CefRefPtr<CefBrowserViewDelegate> new_delegate;
+  if (browser_view_->delegate()) {
+    new_delegate = browser_view_->delegate()->GetDelegateForPopupBrowserView(
+        browser_view_.get(), settings, client, is_devtools);
+  }
+
+  // Create a new BrowserView for the popup.
+  CefRefPtr<CefBrowserViewImpl> new_browser_view =
+      CefBrowserViewImpl::CreateForPopup(settings, new_delegate);
+
+  // Associate the PlatformDelegate with the new BrowserView.
+  new_platform_delegate_impl->SetBrowserView(new_browser_view);
+}
+
+void CefBrowserPlatformDelegateChromeViews::PopupBrowserCreated(
+    CefBrowserHostBase* new_browser,
+    bool is_devtools) {
+  // Default popup handling may not be Views-hosted.
+  if (!new_browser->HasView()) {
+    return;
+  }
+
+  CefRefPtr<CefBrowserView> new_browser_view =
+      CefBrowserView::GetForBrowser(new_browser);
+  DCHECK(new_browser_view);
+
+  bool popup_handled = false;
+  if (browser_view_->delegate()) {
+    popup_handled = browser_view_->delegate()->OnPopupBrowserViewCreated(
+        browser_view_.get(), new_browser_view.get(), is_devtools);
+  }
+
+  if (!popup_handled) {
+    CefWindow::CreateTopLevelWindow(
+        new PopupWindowDelegate(new_browser_view.get()));
+  }
+}
+
+void CefBrowserPlatformDelegateChromeViews::UpdateFindBarBoundingBox(
+    gfx::Rect* bounds) const {
+  if (auto* window_impl = GetWindowImpl()) {
+    if (window_impl->root_view()) {
+      window_impl->root_view()->UpdateFindBarBoundingBox(bounds);
+    }
+  }
+}
+
+bool CefBrowserPlatformDelegateChromeViews::IsViewsHosted() const {
+  return true;
+}
+
+CefWindowImpl* CefBrowserPlatformDelegateChromeViews::GetWindowImpl() const {
+  if (auto* widget = GetWindowWidget()) {
+    CefRefPtr<CefWindow> window = view_util::GetWindowFor(widget);
+    return static_cast<CefWindowImpl*>(window.get());
+  }
+  return nullptr;
+}
diff --git a/src/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h b/src/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h
new file mode 100644
index 0000000..f27ba88
--- /dev/null
+++ b/src/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h
@@ -0,0 +1,53 @@
+// Copyright 2021 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_CHROME_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_VIEWS_H_
+#define CEF_LIBCEF_BROWSER_CHROME_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_VIEWS_H_
+
+#include "libcef/browser/chrome/browser_platform_delegate_chrome.h"
+#include "libcef/browser/views/browser_view_impl.h"
+
+class CefWindowImpl;
+
+// Implementation of Chrome-based browser functionality.
+class CefBrowserPlatformDelegateChromeViews
+    : public CefBrowserPlatformDelegateChrome {
+ public:
+  explicit CefBrowserPlatformDelegateChromeViews(
+      std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
+      CefRefPtr<CefBrowserViewImpl> browser_view);
+
+  // CefBrowserPlatformDelegate overrides.
+  void WebContentsCreated(content::WebContents* web_contents,
+                          bool owned) override;
+  void BrowserCreated(CefBrowserHostBase* browser) override;
+  void NotifyBrowserCreated() override;
+  void NotifyBrowserDestroyed() override;
+  void BrowserDestroyed(CefBrowserHostBase* browser) override;
+  void CloseHostWindow() override;
+  CefWindowHandle GetHostWindowHandle() const override;
+  views::Widget* GetWindowWidget() const override;
+  CefRefPtr<CefBrowserView> GetBrowserView() const override;
+  void PopupWebContentsCreated(
+      const CefBrowserSettings& settings,
+      CefRefPtr<CefClient> client,
+      content::WebContents* new_web_contents,
+      CefBrowserPlatformDelegate* new_platform_delegate,
+      bool is_devtools) override;
+  void PopupBrowserCreated(CefBrowserHostBase* new_browser,
+                           bool is_devtools) override;
+  void UpdateFindBarBoundingBox(gfx::Rect* bounds) const override;
+  bool IsViewsHosted() const override;
+
+  CefRefPtr<CefBrowserViewImpl> browser_view() const { return browser_view_; }
+
+ private:
+  void SetBrowserView(CefRefPtr<CefBrowserViewImpl> browser_view);
+
+  CefWindowImpl* GetWindowImpl() const;
+
+  CefRefPtr<CefBrowserViewImpl> browser_view_;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_CHROME_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_VIEWS_H_
diff --git a/src/libcef/browser/chrome/views/chrome_browser_frame.cc b/src/libcef/browser/chrome/views/chrome_browser_frame.cc
new file mode 100644
index 0000000..9960854
--- /dev/null
+++ b/src/libcef/browser/chrome/views/chrome_browser_frame.cc
@@ -0,0 +1,82 @@
+// Copyright 2021 The Chromium Embedded Framework 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 "libcef/browser/chrome/views/chrome_browser_frame.h"
+
+#include "libcef/browser/chrome/chrome_browser_host_impl.h"
+
+#include "chrome/browser/themes/theme_service.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+
+#if BUILDFLAG(IS_MAC)
+#include "libcef/browser/views/native_widget_mac.h"
+#include "libcef/browser/views/view_util.h"
+#include "ui/views/widget/native_widget_private.h"
+#endif
+
+void ChromeBrowserFrame::Init(BrowserView* browser_view,
+                              std::unique_ptr<Browser> browser) {
+  DCHECK(browser_view);
+  DCHECK(browser);
+
+  DCHECK(!browser_view_);
+  browser_view_ = browser_view;
+
+  // Initialize BrowserFrame state.
+  InitBrowserView(browser_view);
+
+  // Initialize BrowserView state.
+  browser_view->InitBrowser(std::move(browser));
+
+#if BUILDFLAG(IS_MAC)
+  // Initialize native window state.
+  if (auto native_window = view_util::GetNativeWindow(this)) {
+    if (auto* native_widget_private = views::internal::NativeWidgetPrivate::
+            GetNativeWidgetForNativeWindow(native_window)) {
+      auto* native_widget_mac =
+          static_cast<CefNativeWidgetMac*>(native_widget_private);
+      native_widget_mac->SetBrowserView(browser_view);
+      native_widget_mac->OnWindowInitialized();
+    }
+  }
+#endif  // BUILDFLAG(IS_MAC)
+}
+
+void ChromeBrowserFrame::ToggleFullscreenMode() {
+  chrome::ToggleFullscreenMode(browser_view_->browser());
+}
+
+views::internal::RootView* ChromeBrowserFrame::CreateRootView() {
+  // Bypass the BrowserFrame implementation.
+  return views::Widget::CreateRootView();
+}
+
+std::unique_ptr<views::NonClientFrameView>
+ChromeBrowserFrame::CreateNonClientFrameView() {
+  // Bypass the BrowserFrame implementation.
+  return views::Widget::CreateNonClientFrameView();
+}
+
+void ChromeBrowserFrame::Activate() {
+  if (browser_view_ && browser_view_->browser() &&
+      browser_view_->browser()->is_type_devtools()) {
+    if (auto browser_host = ChromeBrowserHostImpl::GetBrowserForBrowser(
+            browser_view_->browser())) {
+      if (browser_host->platform_delegate()->HasExternalParent()) {
+        // Handle activation of DevTools with external parent via the platform
+        // delegate. On Windows the default platform implementation
+        // (HWNDMessageHandler::Activate) will call SetForegroundWindow but that
+        // doesn't seem to work for DevTools windows when activated via the
+        // right-click context menu.
+        browser_host->SetFocus(true);
+        return;
+      }
+    }
+  }
+
+  // Proceed with default handling.
+  BrowserFrame::Activate();
+}
diff --git a/src/libcef/browser/chrome/views/chrome_browser_frame.h b/src/libcef/browser/chrome/views/chrome_browser_frame.h
new file mode 100644
index 0000000..ffd823e
--- /dev/null
+++ b/src/libcef/browser/chrome/views/chrome_browser_frame.h
@@ -0,0 +1,114 @@
+// Copyright 2021 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_BROWSER_FRAME_H_
+#define CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_BROWSER_FRAME_H_
+#pragma once
+
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/views/frame/browser_frame.h"
+
+// An overview of the Chrome Browser object model is provided below. Object
+// creation normally begins with a call to Browser::Create(CreateParams) which
+// then creates the necessary Browser view, window and frame objects. CEF has
+// modified the default object creation model are described below to better
+// integrate with the existing CEF Views APIs.
+//
+// OVERVIEW
+//
+// Browser and BrowserWindow are the primary Chrome objects. Browser provides
+// the concrete state and mutation methods while BrowserWindow is an interface
+// implemented by the platform-specific "view" of the Browser window.
+//
+// Browser:
+// - Creates a BrowserView (aka BrowserWindow) and BrowserFrame (aka Widget) via
+//   a call to BrowserWindow::CreateBrowserWindow() in the Browser constructor.
+//   - An existing BrowserWindow can alternately be specified via the
+//     Browser::CreateParams::window parameter.
+// - Owned by the BrowserView after creation.
+//
+// The Chrome Views implementation uses BrowserView to represent the browser
+// client area and BrowserFrame (plus helpers) to represent the non-client
+// window frame.
+//
+// BrowserView:
+// - Extends BrowserWindow, views::ClientView, views::WidgetDelegate.
+// - Owns the Browser.
+// - References the BrowserFrame.
+// - Passed to Widget::Init() via Widget::InitParams::delegate to receive
+//   WidgetDelegate callbacks.
+// - Extended by CEF as ChromeBrowserView.
+// BrowserFrame:
+// - Extends Widget (aka views::internal::NativeWidgetDelegate).
+// - References the BrowserView.
+// - Creates/owns a DesktopBrowserFrameAura (aka NativeBrowserFrame) via
+//   BrowserFrame::InitBrowserFrame().
+// - Extended by CEF as ChromeBrowserFrame.
+//
+// Chrome custom window/frame handling is implemented using platform-specific
+// objects.
+//
+// DesktopBrowserFrameAura:
+// - Extends NativeBrowserFrame, DesktopNativeWidgetAura.
+// - Acts as a helper for BrowserFrame.
+// - Creates/references a BrowserDesktopWindowTreeHostWin via
+//   DesktopBrowserFrameAura::InitNativeWidget().
+// BrowserDesktopWindowTreeHostWin (for Windows):
+// - Extends DesktopWindowTreeHost.
+// - References DesktopBrowserFrameAura, BrowserView, BrowserFrame.
+// - Passed to Widget::Init() via Widget::InitParams::desktop_window_tree_host.
+//
+// CEF MODIFICATIONS
+//
+// The CEF Views integration uses an alternative approach of creating the
+// ChromeBrowserFrame in CefWindowView::CreateWidget() and the
+// ChromeBrowserView in CefBrowserViewImpl::CreateRootView().
+// The object associations described above are then configured via
+// ChromeBrowserView::AddedToWidget() and ChromeBrowserHostImpl::Create()
+// after the BrowserView is added to the Widget. The Chromium code has been
+// patched to allow later initialization of the Browser, BrowserFrame and
+// BrowserView members to support this model.
+//
+// CEF does not use Chrome's NativeBrowserFrame (aka DesktopBrowserFrameAura),
+// BrowserNonClientFrameView or BrowserRootView objects (all normally created by
+// BrowserFrame during Widget initialization). Consequently
+// |BrowserFrame::native_browser_frame_| and |BrowserFrame::browser_frame_view_|
+// (sometimes retrieved via BrowserFrame::GetFrameView) will be nullptr and the
+// Chromium code has been patched to add the necessary null checks.
+//
+// CEF does not pass ChromeBrowserView as the WidgetDelegate when the Widget is
+// initialized in CefWindowView::CreateWidget(). Some of the WidgetDelegate
+// callbacks may need to be routed from CefWindowView to ChromeBrowserView in
+// the future.
+//
+// See the chrome_runtime_views.patch file for the complete set of related
+// modifications.
+
+class BrowserView;
+
+// Widget for a Views-hosted Chrome browser. Created in
+// CefWindowView::CreateWidget() when the Chrome runtime is enabled.
+class ChromeBrowserFrame : public BrowserFrame {
+ public:
+  ChromeBrowserFrame() {}
+  ChromeBrowserFrame(const ChromeBrowserFrame&) = delete;
+  ChromeBrowserFrame& operator=(const ChromeBrowserFrame&) = delete;
+
+  void Init(BrowserView* browser_view, std::unique_ptr<Browser> browser);
+
+  void ToggleFullscreenMode();
+
+  // views::Widget methods:
+  views::internal::RootView* CreateRootView() override;
+  std::unique_ptr<views::NonClientFrameView> CreateNonClientFrameView()
+      override;
+  void Activate() override;
+
+  BrowserView* browser_view() const { return browser_view_; }
+
+ private:
+  BrowserView* browser_view_ = nullptr;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_BROWSER_FRAME_H_
diff --git a/src/libcef/browser/chrome/views/chrome_browser_view.cc b/src/libcef/browser/chrome/views/chrome_browser_view.cc
new file mode 100644
index 0000000..59f7c0f
--- /dev/null
+++ b/src/libcef/browser/chrome/views/chrome_browser_view.cc
@@ -0,0 +1,95 @@
+// Copyright 2021 The Chromium Embedded Framework 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 "libcef/browser/chrome/views/chrome_browser_view.h"
+
+#include "libcef/browser/chrome/views/chrome_browser_frame.h"
+#include "libcef/browser/views/browser_view_impl.h"
+
+ChromeBrowserView::ChromeBrowserView(CefBrowserViewImpl* cef_browser_view)
+    : ParentClass(cef_browser_view->delegate()),
+      cef_browser_view_(cef_browser_view) {}
+
+void ChromeBrowserView::InitBrowser(std::unique_ptr<Browser> browser) {
+  DCHECK(!web_view_);
+
+  // Initialize the BrowserFrame and BrowserView.
+  auto chrome_widget = static_cast<ChromeBrowserFrame*>(GetWidget());
+  chrome_widget->Init(this, std::move(browser));
+
+  // Retrieve the views::WebView that was created by the above initializations.
+  web_view_ = cef_browser_view_->web_view();
+  DCHECK(web_view_);
+
+  ParentClass::AddedToWidget();
+}
+
+void ChromeBrowserView::Destroyed() {
+  DCHECK(!destroyed_);
+  destroyed_ = true;
+  web_view_ = nullptr;
+}
+
+void ChromeBrowserView::ViewHierarchyChanged(
+    const views::ViewHierarchyChangedDetails& details) {
+  ParentClass::ViewHierarchyChanged(details);
+  if (details.is_add && details.child == this) {
+    gfx::Size size = GetPreferredSize();
+    if (size.IsEmpty()) {
+      // No size was provided for this View. Size it to the parent by default
+      // or, depending on the Layout, the browser may be initially 0x0 size and
+      // will not display until the parent is next resized (resulting in a call
+      // to WebView::OnBoundsChanged). For example, this can happen when adding
+      // this View to a CefWindow with FillLayout and then calling
+      // CefWindow::Show() without first resizing the CefWindow.
+      size = details.parent->GetPreferredSize();
+      if (!size.IsEmpty()) {
+        SetSize(size);
+      }
+    }
+  }
+}
+
+void ChromeBrowserView::AddedToWidget() {
+  // Results in a call to InitBrowser which calls ParentClass::AddedToWidget.
+  cef_browser_view_->OnBrowserViewAdded();
+}
+
+void ChromeBrowserView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
+  ParentClass::OnBoundsChanged(previous_bounds);
+  cef_browser_view_->OnBoundsChanged();
+}
+
+void ChromeBrowserView::OnGestureEvent(ui::GestureEvent* event) {
+  if (cef_browser_view_->OnGestureEvent(event)) {
+    return;
+  }
+  ParentClass::OnGestureEvent(event);
+}
+
+ToolbarView* ChromeBrowserView::OverrideCreateToolbar() {
+  if (cef_delegate()) {
+    auto toolbar_type = cef_delegate()->GetChromeToolbarType(cef_browser_view_);
+    absl::optional<ToolbarView::DisplayMode> display_mode;
+    switch (toolbar_type) {
+      case CEF_CTT_NORMAL:
+        display_mode = ToolbarView::DisplayMode::NORMAL;
+        break;
+      case CEF_CTT_LOCATION:
+        display_mode = ToolbarView::DisplayMode::LOCATION;
+        break;
+      default:
+        break;
+    }
+    if (display_mode) {
+      cef_toolbar_ =
+          CefToolbarViewImpl::Create(nullptr, browser(), this, display_mode);
+      // Ownership will be taken by BrowserView.
+      view_util::PassOwnership(cef_toolbar_).release();
+      return cef_toolbar_->root_view();
+    }
+  }
+
+  return nullptr;
+}
diff --git a/src/libcef/browser/chrome/views/chrome_browser_view.h b/src/libcef/browser/chrome/views/chrome_browser_view.h
new file mode 100644
index 0000000..c7ae94a
--- /dev/null
+++ b/src/libcef/browser/chrome/views/chrome_browser_view.h
@@ -0,0 +1,64 @@
+// Copyright 2021 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_BROWSER_VIEW_H_
+#define CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_BROWSER_VIEW_H_
+#pragma once
+
+#include "include/views/cef_browser_view.h"
+#include "include/views/cef_browser_view_delegate.h"
+#include "libcef/browser/chrome/views/toolbar_view_impl.h"
+#include "libcef/browser/views/browser_view_view.h"
+#include "libcef/browser/views/view_view.h"
+
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+
+namespace views {
+class WebView;
+}  // namespace views
+
+class CefBrowserViewImpl;
+
+// A variant of CefBrowserViewView that extends BrowserView instead of
+// views::WebView. See chrome_browser_frame.h for related documentation.
+class ChromeBrowserView
+    : public CefViewView<BrowserView, CefBrowserViewDelegate> {
+ public:
+  using ParentClass = CefViewView<BrowserView, CefBrowserViewDelegate>;
+
+  // |cef_browser_view| is non-nullptr and will outlive this object.
+  explicit ChromeBrowserView(CefBrowserViewImpl* cef_browser_view);
+
+  ChromeBrowserView(const ChromeBrowserView&) = delete;
+  ChromeBrowserView& operator=(const ChromeBrowserView&) = delete;
+
+  // Called by ChromeBrowserHostImpl.
+  void InitBrowser(std::unique_ptr<Browser> browser);
+  void Destroyed();
+
+  // View methods:
+  void ViewHierarchyChanged(
+      const views::ViewHierarchyChangedDetails& details) override;
+  void AddedToWidget() override;
+  void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
+  void OnGestureEvent(ui::GestureEvent* event) override;
+
+  // BrowserView methods:
+  ToolbarView* OverrideCreateToolbar() override;
+
+  CefRefPtr<CefToolbarViewImpl> cef_toolbar() const { return cef_toolbar_; }
+  CefBrowserViewImpl* cef_browser_view() const { return cef_browser_view_; }
+
+ private:
+  CefBrowserViewImpl* const cef_browser_view_;
+
+  views::WebView* web_view_ = nullptr;
+
+  bool destroyed_ = false;
+
+  CefRefPtr<CefToolbarViewImpl> cef_toolbar_;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_BROWSER_VIEW_H_
diff --git a/src/libcef/browser/chrome/views/chrome_child_window.cc b/src/libcef/browser/chrome/views/chrome_child_window.cc
new file mode 100644
index 0000000..e37561c
--- /dev/null
+++ b/src/libcef/browser/chrome/views/chrome_child_window.cc
@@ -0,0 +1,201 @@
+// Copyright 2022 The Chromium Embedded Framework 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 "libcef/browser/chrome/views/chrome_child_window.h"
+
+#include "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h"
+#include "libcef/browser/views/browser_view_impl.h"
+#include "libcef/browser/views/window_impl.h"
+
+#if BUILDFLAG(IS_WIN)
+#include "libcef/browser/native/browser_platform_delegate_native_win.h"
+#include "ui/views/win/hwnd_util.h"
+#endif
+
+namespace {
+
+class ChildWindowDelegate : public CefWindowDelegate {
+ public:
+  ChildWindowDelegate(const ChildWindowDelegate&) = delete;
+  ChildWindowDelegate& operator=(const ChildWindowDelegate&) = delete;
+
+  static void Create(CefRefPtr<CefBrowserView> browser_view,
+                     const CefWindowInfo& window_info,
+                     gfx::AcceleratedWidget parent_handle) {
+    DCHECK(parent_handle != gfx::kNullAcceleratedWidget);
+
+    // Create the Window. It will show itself after creation.
+    CefWindowImpl::Create(new ChildWindowDelegate(browser_view, window_info),
+                          parent_handle);
+  }
+
+  void OnWindowCreated(CefRefPtr<CefWindow> window) override {
+    DCHECK(!window_);
+    window_ = window;
+
+    // Add the browser view. It will now have an associated Widget.
+    window_->AddChildView(browser_view_);
+
+    ShowWindow();
+  }
+
+  void OnWindowDestroyed(CefRefPtr<CefWindow> window) override {
+    browser_view_ = nullptr;
+    window_ = nullptr;
+  }
+
+  CefRect GetInitialBounds(CefRefPtr<CefWindow> window) override {
+    CefRect initial_bounds(window_info_.bounds);
+    if (initial_bounds.IsEmpty()) {
+      return CefRect(0, 0, 800, 600);
+    }
+    return initial_bounds;
+  }
+
+  void ShowWindow() {
+#if BUILDFLAG(IS_WIN)
+    auto widget = static_cast<CefWindowImpl*>(window_.get())->widget();
+    DCHECK(widget);
+    const HWND widget_hwnd = HWNDForWidget(widget);
+    DCHECK(widget_hwnd);
+
+    // The native delegate needs state to perform some actions.
+    auto browser =
+        static_cast<CefBrowserHostBase*>(browser_view_->GetBrowser().get());
+    auto platform_delegate = browser->platform_delegate();
+    DCHECK(platform_delegate->IsViewsHosted());
+    auto chrome_delegate =
+        static_cast<CefBrowserPlatformDelegateChromeViews*>(platform_delegate);
+    auto native_delegate = static_cast<CefBrowserPlatformDelegateNativeWin*>(
+        chrome_delegate->native_delegate());
+    native_delegate->set_widget(widget, widget_hwnd);
+
+    if (window_info_.ex_style & WS_EX_NOACTIVATE) {
+      const DWORD widget_ex_styles = GetWindowLongPtr(widget_hwnd, GWL_EXSTYLE);
+
+      // Add the WS_EX_NOACTIVATE style on the DesktopWindowTreeHostWin HWND
+      // so that HWNDMessageHandler::Show() called via Widget::Show() does not
+      // activate the window.
+      SetWindowLongPtr(widget_hwnd, GWL_EXSTYLE,
+                       widget_ex_styles | WS_EX_NOACTIVATE);
+
+      window_->Show();
+
+      // Remove the WS_EX_NOACTIVATE style so that future mouse clicks inside
+      // the browser correctly activate and focus the window.
+      SetWindowLongPtr(widget_hwnd, GWL_EXSTYLE, widget_ex_styles);
+      return;
+    }
+#endif  // BUILDFLAG(IS_WIN)
+
+    window_->Show();
+
+    // Give keyboard focus to the browser view.
+    browser_view_->RequestFocus();
+  }
+
+ private:
+  ChildWindowDelegate(CefRefPtr<CefBrowserView> browser_view,
+                      const CefWindowInfo& window_info)
+      : browser_view_(browser_view), window_info_(window_info) {}
+
+  CefRefPtr<CefBrowserView> browser_view_;
+  const CefWindowInfo window_info_;
+
+  CefRefPtr<CefWindow> window_;
+
+  IMPLEMENT_REFCOUNTING(ChildWindowDelegate);
+};
+
+class ChildBrowserViewDelegate : public CefBrowserViewDelegate {
+ public:
+  ChildBrowserViewDelegate() = default;
+
+  ChildBrowserViewDelegate(const ChildBrowserViewDelegate&) = delete;
+  ChildBrowserViewDelegate& operator=(const ChildBrowserViewDelegate&) = delete;
+
+  CefRefPtr<CefBrowserViewDelegate> GetDelegateForPopupBrowserView(
+      CefRefPtr<CefBrowserView> browser_view,
+      const CefBrowserSettings& settings,
+      CefRefPtr<CefClient> client,
+      bool is_devtools) override {
+    return new ChildBrowserViewDelegate();
+  }
+
+  bool OnPopupBrowserViewCreated(CefRefPtr<CefBrowserView> browser_view,
+                                 CefRefPtr<CefBrowserView> popup_browser_view,
+                                 bool is_devtools) override {
+    auto new_browser = static_cast<CefBrowserHostBase*>(
+        popup_browser_view->GetBrowser().get());
+    auto new_platform_delegate = new_browser->platform_delegate();
+    DCHECK(new_platform_delegate->IsViewsHosted());
+    auto new_platform_delegate_impl =
+        static_cast<CefBrowserPlatformDelegateChromeViews*>(
+            new_platform_delegate);
+
+    const auto& window_info =
+        new_platform_delegate_impl->native_delegate()->window_info();
+    const auto parent_handle =
+        chrome_child_window::GetParentHandle(window_info);
+    if (parent_handle != gfx::kNullAcceleratedWidget) {
+      ChildWindowDelegate::Create(popup_browser_view, window_info,
+                                  parent_handle);
+      return true;
+    }
+
+    // Use the default implementation that creates a new Views-hosted top-level
+    // window.
+    return false;
+  }
+
+ private:
+  IMPLEMENT_REFCOUNTING(ChildBrowserViewDelegate);
+};
+
+}  // namespace
+
+namespace chrome_child_window {
+
+bool HasParentHandle(const CefWindowInfo& window_info) {
+  return GetParentHandle(window_info) != gfx::kNullAcceleratedWidget;
+}
+
+gfx::AcceleratedWidget GetParentHandle(const CefWindowInfo& window_info) {
+#if !BUILDFLAG(IS_MAC)
+  return window_info.parent_window;
+#else
+  return gfx::kNullAcceleratedWidget;
+#endif
+}
+
+CefRefPtr<CefBrowserHostBase> MaybeCreateChildBrowser(
+    const CefBrowserCreateParams& create_params) {
+  // If the BrowserView already exists it means that we're dealing with a popup
+  // and we'll instead create the Window in OnPopupBrowserViewCreated.
+  if (create_params.browser_view) {
+    return nullptr;
+  }
+
+  if (!create_params.window_info) {
+    return nullptr;
+  }
+
+  const auto parent_handle = GetParentHandle(*create_params.window_info);
+  if (parent_handle == gfx::kNullAcceleratedWidget) {
+    return nullptr;
+  }
+
+  // Create the BrowserView.
+  auto browser_view = CefBrowserViewImpl::Create(
+      *create_params.window_info, create_params.client, create_params.url,
+      create_params.settings, create_params.extra_info,
+      create_params.request_context, new ChildBrowserViewDelegate());
+
+  ChildWindowDelegate::Create(browser_view, *create_params.window_info,
+                              parent_handle);
+
+  return static_cast<CefBrowserHostBase*>(browser_view->GetBrowser().get());
+}
+
+}  // namespace chrome_child_window
diff --git a/src/libcef/browser/chrome/views/chrome_child_window.h b/src/libcef/browser/chrome/views/chrome_child_window.h
new file mode 100644
index 0000000..ac77481
--- /dev/null
+++ b/src/libcef/browser/chrome/views/chrome_child_window.h
@@ -0,0 +1,24 @@
+// Copyright 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_CHILD_WINDOW_H_
+#define CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_CHILD_WINDOW_H_
+#pragma once
+
+#include "libcef/browser/browser_host_base.h"
+
+#include "ui/gfx/native_widget_types.h"
+
+namespace chrome_child_window {
+
+bool HasParentHandle(const CefWindowInfo& window_info);
+gfx::AcceleratedWidget GetParentHandle(const CefWindowInfo& window_info);
+
+// Called from CefBrowserHostBase::Create.
+CefRefPtr<CefBrowserHostBase> MaybeCreateChildBrowser(
+    const CefBrowserCreateParams& create_params);
+
+}  // namespace chrome_child_window
+
+#endif  // CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_CHILD_WINDOW_H_
diff --git a/src/libcef/browser/chrome/views/chrome_views_util.cc b/src/libcef/browser/chrome/views/chrome_views_util.cc
new file mode 100644
index 0000000..83254ab
--- /dev/null
+++ b/src/libcef/browser/chrome/views/chrome_views_util.cc
@@ -0,0 +1,15 @@
+// Copyright 2021 The Chromium Embedded Framework 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 "libcef/browser/chrome/views/chrome_views_util.h"
+
+#include "libcef/browser/views/view_util.h"
+
+namespace cef {
+
+bool IsCefView(views::View* view) {
+  return view_util::GetFor(view, /*find_known_parent=*/false) != nullptr;
+}
+
+}  // namespace cef
diff --git a/src/libcef/browser/chrome/views/chrome_views_util.h b/src/libcef/browser/chrome/views/chrome_views_util.h
new file mode 100644
index 0000000..20f528a
--- /dev/null
+++ b/src/libcef/browser/chrome/views/chrome_views_util.h
@@ -0,0 +1,20 @@
+// Copyright 2021 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_VIEWS_H_
+#define CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_VIEWS_H_
+#pragma once
+
+namespace views {
+class View;
+}
+
+namespace cef {
+
+// Returns true if |view| is a CefView.
+bool IsCefView(views::View* view);
+
+}  // namespace cef
+
+#endif  // CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_VIEWS_H_
diff --git a/src/libcef/browser/chrome/views/toolbar_view_impl.cc b/src/libcef/browser/chrome/views/toolbar_view_impl.cc
new file mode 100644
index 0000000..fcc1755
--- /dev/null
+++ b/src/libcef/browser/chrome/views/toolbar_view_impl.cc
@@ -0,0 +1,40 @@
+// Copyright 2021 The Chromium Embedded Framework 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 "libcef/browser/chrome/views/toolbar_view_impl.h"
+
+// static
+CefRefPtr<CefToolbarViewImpl> CefToolbarViewImpl::Create(
+    CefRefPtr<CefViewDelegate> delegate,
+    Browser* browser,
+    BrowserView* browser_view,
+    absl::optional<ToolbarView::DisplayMode> display_mode) {
+  CEF_REQUIRE_UIT_RETURN(nullptr);
+  CefRefPtr<CefToolbarViewImpl> view =
+      new CefToolbarViewImpl(delegate, browser, browser_view, display_mode);
+  view->Initialize();
+  return view;
+}
+
+// static
+const char* const CefToolbarViewImpl::kTypeString = "ToolbarView";
+
+CefToolbarViewImpl::CefToolbarViewImpl(
+    CefRefPtr<CefViewDelegate> delegate,
+    Browser* browser,
+    BrowserView* browser_view,
+    absl::optional<ToolbarView::DisplayMode> display_mode)
+    : ParentClass(delegate),
+      browser_(browser),
+      browser_view_(browser_view),
+      display_mode_(display_mode) {}
+
+CefToolbarViewView* CefToolbarViewImpl::CreateRootView() {
+  return new CefToolbarViewView(delegate(), browser_, browser_view_,
+                                display_mode_);
+}
+
+void CefToolbarViewImpl::InitializeRootView() {
+  static_cast<CefToolbarViewView*>(root_view())->Initialize();
+}
diff --git a/src/libcef/browser/chrome/views/toolbar_view_impl.h b/src/libcef/browser/chrome/views/toolbar_view_impl.h
new file mode 100644
index 0000000..9248614
--- /dev/null
+++ b/src/libcef/browser/chrome/views/toolbar_view_impl.h
@@ -0,0 +1,57 @@
+// Copyright 2021 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_CHROME_VIEWS_TOOLBAR_VIEW_IMPL_H_
+#define CEF_LIBCEF_BROWSER_CHROME_VIEWS_TOOLBAR_VIEW_IMPL_H_
+#pragma once
+
+#include "include/views/cef_view_delegate.h"
+
+#include "libcef/browser/chrome/views/toolbar_view_view.h"
+#include "libcef/browser/views/view_impl.h"
+
+class Browser;
+class BrowserView;
+
+class CefToolbarViewImpl
+    : public CefViewImpl<CefToolbarViewView, CefView, CefViewDelegate> {
+ public:
+  using ParentClass = CefViewImpl<CefToolbarViewView, CefView, CefViewDelegate>;
+
+  CefToolbarViewImpl(const CefToolbarViewImpl&) = delete;
+  CefToolbarViewImpl& operator=(const CefToolbarViewImpl&) = delete;
+
+  // Create a new CefToolbarViewImpl instance. |delegate| may be nullptr.
+  static CefRefPtr<CefToolbarViewImpl> Create(
+      CefRefPtr<CefViewDelegate> delegate,
+      Browser* browser,
+      BrowserView* browser_view,
+      absl::optional<ToolbarView::DisplayMode> display_mode);
+
+  static const char* const kTypeString;
+
+  // CefViewAdapter methods:
+  std::string GetDebugType() override { return kTypeString; }
+
+ private:
+  // Create a new implementation object.
+  // Always call Initialize() after creation.
+  // |delegate| may be nullptr.
+  CefToolbarViewImpl(CefRefPtr<CefViewDelegate> delegate,
+                     Browser* browser,
+                     BrowserView* browser_view,
+                     absl::optional<ToolbarView::DisplayMode> display_mode);
+
+  // CefViewImpl methods:
+  CefToolbarViewView* CreateRootView() override;
+  void InitializeRootView() override;
+
+  Browser* const browser_;
+  BrowserView* const browser_view_;
+  absl::optional<ToolbarView::DisplayMode> const display_mode_;
+
+  IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefToolbarViewImpl);
+};
+
+#endif  // CEF_LIBCEF_BROWSER_VIEWS_SCROLL_VIEW_IMPL_H_
diff --git a/src/libcef/browser/chrome/views/toolbar_view_view.cc b/src/libcef/browser/chrome/views/toolbar_view_view.cc
new file mode 100644
index 0000000..ad986bd
--- /dev/null
+++ b/src/libcef/browser/chrome/views/toolbar_view_view.cc
@@ -0,0 +1,11 @@
+// Copyright 2021 The Chromium Embedded Framework 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 "libcef/browser/chrome/views/toolbar_view_view.h"
+
+CefToolbarViewView::CefToolbarViewView(CefViewDelegate* cef_delegate,
+                                       Browser* browser,
+                                       BrowserView* browser_view,
+                                       absl::optional<DisplayMode> display_mode)
+    : ParentClass(cef_delegate, browser, browser_view, display_mode) {}
diff --git a/src/libcef/browser/chrome/views/toolbar_view_view.h b/src/libcef/browser/chrome/views/toolbar_view_view.h
new file mode 100644
index 0000000..4892000
--- /dev/null
+++ b/src/libcef/browser/chrome/views/toolbar_view_view.h
@@ -0,0 +1,27 @@
+// Copyright 2021 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_CHROME_VIEWS_TOOLBAR_VIEW_VIEW_H_
+#define CEF_LIBCEF_BROWSER_CHROME_VIEWS_TOOLBAR_VIEW_VIEW_H_
+#pragma once
+
+#include "libcef/browser/views/view_view.h"
+
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+
+class CefToolbarViewView : public CefViewView<ToolbarView, CefViewDelegate> {
+ public:
+  using ParentClass = CefViewView<ToolbarView, CefViewDelegate>;
+
+  // |cef_delegate| may be nullptr.
+  explicit CefToolbarViewView(CefViewDelegate* cef_delegate,
+                              Browser* browser,
+                              BrowserView* browser_view,
+                              absl::optional<DisplayMode> display_mode);
+
+  CefToolbarViewView(const CefToolbarViewView&) = delete;
+  CefToolbarViewView& operator=(const CefToolbarViewView&) = delete;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_CHROME_VIEWS_TOOLBAR_VIEW_VIEW_H_
diff --git a/src/libcef/browser/chrome_browser_process_stub.cc b/src/libcef/browser/chrome_browser_process_stub.cc
deleted file mode 100644
index 47b72a7..0000000
--- a/src/libcef/browser/chrome_browser_process_stub.cc
+++ /dev/null
@@ -1,381 +0,0 @@
-// Copyright (c) 2013 The Chromium Embedded Framework Authors.
-// Portions (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/chrome_browser_process_stub.h"
-
-#include "libcef/browser/browser_context.h"
-#include "libcef/browser/chrome_profile_manager_stub.h"
-#include "libcef/browser/context.h"
-#include "libcef/browser/prefs/browser_prefs.h"
-#include "libcef/browser/thread_util.h"
-#include "libcef/common/cef_switches.h"
-
-#include "base/command_line.h"
-#include "chrome/browser/net/system_network_context_manager.h"
-#include "chrome/browser/policy/chrome_browser_policy_connector.h"
-#include "chrome/browser/printing/background_printing_manager.h"
-#include "chrome/browser/printing/print_job_manager.h"
-#include "chrome/browser/printing/print_preview_dialog_controller.h"
-#include "chrome/browser/ui/prefs/pref_watcher.h"
-#include "components/net_log/chrome_net_log.h"
-#include "components/prefs/pref_service.h"
-#include "content/browser/startup_helper.h"
-#include "content/public/common/content_switches.h"
-#include "net/log/net_log_capture_mode.h"
-#include "services/network/public/cpp/network_switches.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-
-ChromeBrowserProcessStub::ChromeBrowserProcessStub()
-    : initialized_(false),
-      context_initialized_(false),
-      shutdown_(false),
-      locale_("en-US") {}
-
-ChromeBrowserProcessStub::~ChromeBrowserProcessStub() {
-  DCHECK((!initialized_ && !context_initialized_) || shutdown_);
-}
-
-void ChromeBrowserProcessStub::Initialize() {
-  DCHECK(!initialized_);
-  DCHECK(!context_initialized_);
-  DCHECK(!shutdown_);
-  DCHECK(!field_trial_list_);
-
-  // Initialize this early before any code tries to check feature flags.
-  field_trial_list_ = content::SetUpFieldTrialsAndFeatureList();
-
-  initialized_ = true;
-}
-
-void ChromeBrowserProcessStub::OnContextInitialized() {
-  CEF_REQUIRE_UIT();
-  DCHECK(initialized_);
-  DCHECK(!context_initialized_);
-  DCHECK(!shutdown_);
-
-  // Must be created after the NotificationService.
-  print_job_manager_.reset(new printing::PrintJobManager());
-  profile_manager_.reset(new ChromeProfileManagerStub());
-  event_router_forwarder_ = new extensions::EventRouterForwarder();
-  context_initialized_ = true;
-}
-
-void ChromeBrowserProcessStub::Shutdown() {
-  CEF_REQUIRE_UIT();
-  DCHECK(initialized_);
-  DCHECK(context_initialized_);
-  DCHECK(!shutdown_);
-
-  // Wait for the pending print jobs to finish. Don't do this later, since
-  // this might cause a nested message loop to run, and we don't want pending
-  // tasks to run once teardown has started.
-  print_job_manager_->Shutdown();
-  print_job_manager_.reset(nullptr);
-  print_preview_dialog_controller_ = nullptr;
-
-  profile_manager_.reset();
-  event_router_forwarder_ = nullptr;
-
-  if (SystemNetworkContextManager::GetInstance()) {
-    SystemNetworkContextManager::DeleteInstance();
-  }
-
-  // Release any references held by objects associated with a Profile. The
-  // Profile will be deleted later.
-  for (const auto& profile : CefBrowserContext::GetAll()) {
-    // Release any references to |local_state_|.
-    PrefWatcher* pref_watcher = PrefWatcher::Get(profile);
-    if (pref_watcher)
-      pref_watcher->Shutdown();
-
-    // Unregister observers for |background_printing_manager_|.
-    if (background_printing_manager_) {
-      background_printing_manager_->DeletePreviewContentsForBrowserContext(
-          profile);
-    }
-  }
-
-  local_state_.reset();
-  browser_policy_connector_.reset();
-
-  background_printing_manager_.reset();
-
-  field_trial_list_.reset();
-
-  shutdown_ = true;
-}
-
-void ChromeBrowserProcessStub::EndSession() {
-  NOTREACHED();
-}
-
-void ChromeBrowserProcessStub::FlushLocalStateAndReply(
-    base::OnceClosure reply) {
-  NOTREACHED();
-}
-
-metrics_services_manager::MetricsServicesManager*
-ChromeBrowserProcessStub::GetMetricsServicesManager() {
-  NOTREACHED();
-  return nullptr;
-}
-
-metrics::MetricsService* ChromeBrowserProcessStub::metrics_service() {
-  NOTREACHED();
-  return nullptr;
-}
-
-rappor::RapporServiceImpl* ChromeBrowserProcessStub::rappor_service() {
-  // Called from PluginInfoHostImpl::ReportMetrics.
-  return nullptr;
-}
-
-SystemNetworkContextManager*
-ChromeBrowserProcessStub::system_network_context_manager() {
-  DCHECK(SystemNetworkContextManager::GetInstance());
-  return SystemNetworkContextManager::GetInstance();
-}
-
-network::NetworkQualityTracker*
-ChromeBrowserProcessStub::network_quality_tracker() {
-  NOTREACHED();
-  return nullptr;
-}
-
-WatchDogThread* ChromeBrowserProcessStub::watchdog_thread() {
-  NOTREACHED();
-  return nullptr;
-}
-
-ProfileManager* ChromeBrowserProcessStub::profile_manager() {
-  DCHECK(context_initialized_);
-  return profile_manager_.get();
-}
-
-PrefService* ChromeBrowserProcessStub::local_state() {
-  DCHECK(initialized_);
-  if (!local_state_) {
-    // Use a location that is shared by all request contexts.
-    const CefSettings& settings = CefContext::Get()->settings();
-    const base::FilePath& root_cache_path =
-        base::FilePath(CefString(&settings.root_cache_path));
-
-    // Used for very early NetworkService initialization.
-    // Always persist preferences for this PrefService if possible because it
-    // contains the cookie encryption key on Windows.
-    local_state_ =
-        browser_prefs::CreatePrefService(nullptr /* profile */, root_cache_path,
-                                         true /* persist_user_preferences */);
-  }
-  return local_state_.get();
-}
-
-scoped_refptr<network::SharedURLLoaderFactory>
-ChromeBrowserProcessStub::shared_url_loader_factory() {
-  NOTREACHED();
-  return nullptr;
-}
-
-variations::VariationsService* ChromeBrowserProcessStub::variations_service() {
-  NOTREACHED();
-  return nullptr;
-}
-
-BrowserProcessPlatformPart* ChromeBrowserProcessStub::platform_part() {
-  NOTREACHED();
-  return nullptr;
-}
-
-extensions::EventRouterForwarder*
-ChromeBrowserProcessStub::extension_event_router_forwarder() {
-  DCHECK(context_initialized_);
-  return event_router_forwarder_.get();
-}
-
-NotificationUIManager* ChromeBrowserProcessStub::notification_ui_manager() {
-  NOTREACHED();
-  return nullptr;
-}
-
-NotificationPlatformBridge*
-ChromeBrowserProcessStub::notification_platform_bridge() {
-  NOTREACHED();
-  return nullptr;
-}
-
-policy::ChromeBrowserPolicyConnector*
-ChromeBrowserProcessStub::browser_policy_connector() {
-  if (!browser_policy_connector_) {
-    browser_policy_connector_ =
-        std::make_unique<policy::ChromeBrowserPolicyConnector>();
-  }
-  return browser_policy_connector_.get();
-}
-
-policy::PolicyService* ChromeBrowserProcessStub::policy_service() {
-  return browser_policy_connector()->GetPolicyService();
-}
-
-IconManager* ChromeBrowserProcessStub::icon_manager() {
-  NOTREACHED();
-  return nullptr;
-}
-
-GpuModeManager* ChromeBrowserProcessStub::gpu_mode_manager() {
-  NOTREACHED();
-  return nullptr;
-}
-
-void ChromeBrowserProcessStub::CreateDevToolsProtocolHandler() {
-  NOTREACHED();
-}
-
-void ChromeBrowserProcessStub::CreateDevToolsAutoOpener() {
-  NOTREACHED();
-}
-
-bool ChromeBrowserProcessStub::IsShuttingDown() {
-  NOTREACHED();
-  return false;
-}
-
-printing::PrintJobManager* ChromeBrowserProcessStub::print_job_manager() {
-  DCHECK(context_initialized_);
-  return print_job_manager_.get();
-}
-
-printing::PrintPreviewDialogController*
-ChromeBrowserProcessStub::print_preview_dialog_controller() {
-  if (!print_preview_dialog_controller_.get()) {
-    print_preview_dialog_controller_ =
-        new printing::PrintPreviewDialogController();
-  }
-  return print_preview_dialog_controller_.get();
-}
-
-printing::BackgroundPrintingManager*
-ChromeBrowserProcessStub::background_printing_manager() {
-  if (!background_printing_manager_.get()) {
-    background_printing_manager_.reset(
-        new printing::BackgroundPrintingManager());
-  }
-  return background_printing_manager_.get();
-}
-
-IntranetRedirectDetector*
-ChromeBrowserProcessStub::intranet_redirect_detector() {
-  NOTREACHED();
-  return nullptr;
-}
-
-const std::string& ChromeBrowserProcessStub::GetApplicationLocale() {
-  DCHECK(!locale_.empty());
-  return locale_;
-}
-
-void ChromeBrowserProcessStub::SetApplicationLocale(const std::string& locale) {
-  locale_ = locale;
-}
-
-DownloadStatusUpdater* ChromeBrowserProcessStub::download_status_updater() {
-  NOTREACHED();
-  return nullptr;
-}
-
-DownloadRequestLimiter* ChromeBrowserProcessStub::download_request_limiter() {
-  NOTREACHED();
-  return nullptr;
-}
-
-BackgroundModeManager* ChromeBrowserProcessStub::background_mode_manager() {
-  NOTREACHED();
-  return nullptr;
-}
-
-void ChromeBrowserProcessStub::set_background_mode_manager_for_test(
-    std::unique_ptr<BackgroundModeManager> manager) {
-  NOTREACHED();
-}
-
-StatusTray* ChromeBrowserProcessStub::status_tray() {
-  NOTREACHED();
-  return nullptr;
-}
-
-safe_browsing::SafeBrowsingService*
-ChromeBrowserProcessStub::safe_browsing_service() {
-  return nullptr;
-}
-
-safe_browsing::ClientSideDetectionService*
-ChromeBrowserProcessStub::safe_browsing_detection_service() {
-  NOTREACHED();
-  return nullptr;
-}
-
-subresource_filter::RulesetService*
-ChromeBrowserProcessStub::subresource_filter_ruleset_service() {
-  NOTREACHED();
-  return nullptr;
-}
-
-optimization_guide::OptimizationGuideService*
-ChromeBrowserProcessStub::optimization_guide_service() {
-  NOTREACHED();
-  return nullptr;
-}
-
-StartupData* ChromeBrowserProcessStub::startup_data() {
-  NOTREACHED();
-  return nullptr;
-}
-
-#if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
-void ChromeBrowserProcessStub::StartAutoupdateTimer() {}
-#endif
-
-component_updater::ComponentUpdateService*
-ChromeBrowserProcessStub::component_updater() {
-  NOTREACHED();
-  return nullptr;
-}
-
-MediaFileSystemRegistry*
-ChromeBrowserProcessStub::media_file_system_registry() {
-  NOTREACHED();
-  return nullptr;
-}
-
-WebRtcLogUploader* ChromeBrowserProcessStub::webrtc_log_uploader() {
-  NOTREACHED();
-  return nullptr;
-}
-
-network_time::NetworkTimeTracker*
-ChromeBrowserProcessStub::network_time_tracker() {
-  NOTREACHED();
-  return nullptr;
-}
-
-gcm::GCMDriver* ChromeBrowserProcessStub::gcm_driver() {
-  NOTREACHED();
-  return nullptr;
-}
-
-resource_coordinator::TabManager* ChromeBrowserProcessStub::GetTabManager() {
-  NOTREACHED();
-  return nullptr;
-}
-
-resource_coordinator::ResourceCoordinatorParts*
-ChromeBrowserProcessStub::resource_coordinator_parts() {
-  NOTREACHED();
-  return nullptr;
-}
-
-BuildState* ChromeBrowserProcessStub::GetBuildState() {
-  NOTREACHED();
-  return nullptr;
-}
diff --git a/src/libcef/browser/chrome_crash_reporter_client_stub.cc b/src/libcef/browser/chrome_crash_reporter_client_stub.cc
index 837db31..247f323 100644
--- a/src/libcef/browser/chrome_crash_reporter_client_stub.cc
+++ b/src/libcef/browser/chrome_crash_reporter_client_stub.cc
@@ -5,11 +5,11 @@
 
 #include "build/build_config.h"
 
-#if defined(OS_MACOSX)
+#if BUILDFLAG(IS_MAC)
 
 #include "chrome/app/chrome_crash_reporter_client.h"
 
 // Required due to https://crrev.com/1c9f89a06f
 void ChromeCrashReporterClient::Create() {}
 
-#endif  // defined(OS_MACOSX)
+#endif  // BUILDFLAG(IS_MAC)
diff --git a/src/libcef/browser/chrome_profile_manager_stub.h b/src/libcef/browser/chrome_profile_manager_stub.h
deleted file mode 100644
index 549ff75..0000000
--- a/src/libcef/browser/chrome_profile_manager_stub.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2016 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file provides a stub implementation of Chrome's ProfileManager object
-// for use as an interop layer between CEF and files that live in chrome/.
-
-#ifndef CEF_LIBCEF_BROWSER_CHROME_PROFILE_MANAGER_STUB_H_
-#define CEF_LIBCEF_BROWSER_CHROME_PROFILE_MANAGER_STUB_H_
-
-#include "chrome/browser/profiles/profile_manager.h"
-
-class ChromeProfileManagerStub : public ProfileManager {
- public:
-  ChromeProfileManagerStub();
-  ~ChromeProfileManagerStub() override;
-
-  Profile* GetProfile(const base::FilePath& profile_dir) override;
-  bool IsValidProfile(const void* profile) override;
-  Profile* GetLastUsedProfile(const base::FilePath& user_data_dir) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ChromeProfileManagerStub);
-};
-
-#endif  // CEF_LIBCEF_BROWSER_CHROME_PROFILE_MANAGER_STUB_H_
diff --git a/src/libcef/browser/chrome_profile_stub.cc b/src/libcef/browser/chrome_profile_stub.cc
deleted file mode 100644
index b52f826..0000000
--- a/src/libcef/browser/chrome_profile_stub.cc
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright (c) 2015 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/chrome_profile_stub.h"
-
-#include "components/variations/variations_client.h"
-#include "components/variations/variations_http_header_provider.h"
-#include "content/public/browser/resource_context.h"
-#include "net/url_request/url_request_context.h"
-
-namespace {
-
-class CefVariationsClient : public variations::VariationsClient {
- public:
-  explicit CefVariationsClient(content::BrowserContext* browser_context)
-      : browser_context_(browser_context) {}
-
-  ~CefVariationsClient() override = default;
-
-  bool IsIncognito() const override {
-    return browser_context_->IsOffTheRecord();
-  }
-
-  std::string GetVariationsHeader() const override {
-    return variations::VariationsHttpHeaderProvider::GetInstance()
-        ->GetClientDataHeader(false /* is_signed_in */);
-  }
-
- private:
-  content::BrowserContext* browser_context_;
-};
-
-}  // namespace
-
-ChromeProfileStub::ChromeProfileStub() {}
-
-ChromeProfileStub::~ChromeProfileStub() {}
-
-bool ChromeProfileStub::IsOffTheRecord() {
-  return false;
-}
-
-bool ChromeProfileStub::IsOffTheRecord() const {
-  return false;
-}
-
-variations::VariationsClient* ChromeProfileStub::GetVariationsClient() {
-  if (!variations_client_)
-    variations_client_ = std::make_unique<CefVariationsClient>(this);
-  return variations_client_.get();
-}
-
-scoped_refptr<base::SequencedTaskRunner> ChromeProfileStub::GetIOTaskRunner() {
-  NOTREACHED();
-  return scoped_refptr<base::SequencedTaskRunner>();
-}
-
-std::string ChromeProfileStub::GetProfileUserName() const {
-  NOTREACHED();
-  return std::string();
-}
-
-Profile::ProfileType ChromeProfileStub::GetProfileType() const {
-  return REGULAR_PROFILE;
-}
-
-Profile* ChromeProfileStub::GetOffTheRecordProfile() {
-  NOTREACHED();
-  return nullptr;
-}
-
-void ChromeProfileStub::DestroyOffTheRecordProfile() {
-  NOTREACHED();
-}
-
-bool ChromeProfileStub::HasOffTheRecordProfile() {
-  return false;
-}
-
-Profile* ChromeProfileStub::GetOriginalProfile() {
-  return this;
-}
-
-const Profile* ChromeProfileStub::GetOriginalProfile() const {
-  return this;
-}
-
-bool ChromeProfileStub::IsSupervised() const {
-  return false;
-}
-
-bool ChromeProfileStub::IsChild() const {
-  return false;
-}
-
-bool ChromeProfileStub::IsLegacySupervised() const {
-  return false;
-}
-
-ExtensionSpecialStoragePolicy*
-ChromeProfileStub::GetExtensionSpecialStoragePolicy() {
-  NOTREACHED();
-  return nullptr;
-}
-
-PrefService* ChromeProfileStub::GetOffTheRecordPrefs() {
-  NOTREACHED();
-  return nullptr;
-}
-
-bool ChromeProfileStub::IsSameProfile(Profile* profile) {
-  NOTREACHED();
-  return false;
-}
-
-base::Time ChromeProfileStub::GetStartTime() const {
-  NOTREACHED();
-  return base::Time();
-}
-
-base::FilePath ChromeProfileStub::last_selected_directory() {
-  NOTREACHED();
-  return base::FilePath();
-}
-
-void ChromeProfileStub::set_last_selected_directory(
-    const base::FilePath& path) {
-  NOTREACHED();
-}
-
-GURL ChromeProfileStub::GetHomePage() {
-  NOTREACHED();
-  return GURL();
-}
-
-bool ChromeProfileStub::WasCreatedByVersionOrLater(const std::string& version) {
-  NOTREACHED();
-  return false;
-}
-
-bool ChromeProfileStub::IsIndependentOffTheRecordProfile() {
-  return false;
-}
-
-void ChromeProfileStub::SetExitType(ExitType exit_type) {
-  NOTREACHED();
-}
-
-Profile::ExitType ChromeProfileStub::GetLastSessionExitType() {
-  NOTREACHED();
-  return EXIT_NORMAL;
-}
-
-base::Time ChromeProfileStub::GetCreationTime() const {
-  NOTREACHED();
-  return base::Time();
-}
-
-void ChromeProfileStub::SetCreationTimeForTesting(base::Time creation_time) {
-  NOTREACHED();
-}
diff --git a/src/libcef/browser/chrome_profile_stub.h b/src/libcef/browser/chrome_profile_stub.h
deleted file mode 100644
index c9859da..0000000
--- a/src/libcef/browser/chrome_profile_stub.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2015 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This class gathers state related to a single user profile.
-
-#ifndef CEF_LIBCEF_BROWSER_CHROME_PROFILE_STUB_H_
-#define CEF_LIBCEF_BROWSER_CHROME_PROFILE_STUB_H_
-
-#include "chrome/browser/profiles/profile.h"
-
-// This file provides a stub implementation of Chrome's Profile object for use
-// as an interop layer between CEF and files that live in chrome/.
-
-class ChromeProfileStub : public Profile {
- public:
-  ChromeProfileStub();
-  ~ChromeProfileStub() override;
-
- protected:
-  // Profile methods.
-  bool IsOffTheRecord() override;
-  bool IsOffTheRecord() const override;
-  variations::VariationsClient* GetVariationsClient() override;
-  scoped_refptr<base::SequencedTaskRunner> GetIOTaskRunner() override;
-  std::string GetProfileUserName() const override;
-  ProfileType GetProfileType() const override;
-  Profile* GetOffTheRecordProfile() override;
-  void DestroyOffTheRecordProfile() override;
-  bool HasOffTheRecordProfile() override;
-  Profile* GetOriginalProfile() override;
-  const Profile* GetOriginalProfile() const override;
-  bool IsSupervised() const override;
-  bool IsChild() const override;
-  bool IsLegacySupervised() const override;
-  ExtensionSpecialStoragePolicy* GetExtensionSpecialStoragePolicy() override;
-  PrefService* GetOffTheRecordPrefs() override;
-  bool IsSameProfile(Profile* profile) override;
-  base::Time GetStartTime() const override;
-  base::FilePath last_selected_directory() override;
-  void set_last_selected_directory(const base::FilePath& path) override;
-  GURL GetHomePage() override;
-  bool WasCreatedByVersionOrLater(const std::string& version) override;
-  bool IsIndependentOffTheRecordProfile() override;
-  void SetExitType(ExitType exit_type) override;
-  ExitType GetLastSessionExitType() override;
-  base::Time GetCreationTime() const override;
-  void SetCreationTimeForTesting(base::Time creation_time) override;
-
- private:
-  std::unique_ptr<variations::VariationsClient> variations_client_;
-
-  DISALLOW_COPY_AND_ASSIGN(ChromeProfileStub);
-};
-
-#endif  // CEF_LIBCEF_BROWSER_CHROME_PROFILE_STUB_H_
diff --git a/src/libcef/browser/content_browser_client.cc b/src/libcef/browser/content_browser_client.cc
deleted file mode 100644
index 64f3b3c..0000000
--- a/src/libcef/browser/content_browser_client.cc
+++ /dev/null
@@ -1,1515 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/content_browser_client.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "include/cef_version.h"
-#include "libcef/browser/browser_context.h"
-#include "libcef/browser/browser_host_impl.h"
-#include "libcef/browser/browser_info.h"
-#include "libcef/browser/browser_info_manager.h"
-#include "libcef/browser/browser_main.h"
-#include "libcef/browser/browser_message_filter.h"
-#include "libcef/browser/browser_platform_delegate.h"
-#include "libcef/browser/context.h"
-#include "libcef/browser/devtools/devtools_manager_delegate.h"
-#include "libcef/browser/extensions/extension_system.h"
-#include "libcef/browser/extensions/extension_web_contents_observer.h"
-#include "libcef/browser/media_capture_devices_dispatcher.h"
-#include "libcef/browser/net/chrome_scheme_handler.h"
-#include "libcef/browser/net_service/login_delegate.h"
-#include "libcef/browser/net_service/proxy_url_loader_factory.h"
-#include "libcef/browser/net_service/resource_request_handler_wrapper.h"
-#include "libcef/browser/plugins/plugin_service_filter.h"
-#include "libcef/browser/prefs/renderer_prefs.h"
-#include "libcef/browser/printing/printing_message_filter.h"
-#include "libcef/browser/speech_recognition_manager_delegate.h"
-#include "libcef/browser/ssl_info_impl.h"
-#include "libcef/browser/thread_util.h"
-#include "libcef/browser/x509_certificate_impl.h"
-#include "libcef/common/cef_messages.h"
-#include "libcef/common/cef_switches.h"
-#include "libcef/common/command_line_impl.h"
-#include "libcef/common/content_client.h"
-#include "libcef/common/extensions/extensions_util.h"
-#include "libcef/common/net/scheme_registration.h"
-#include "libcef/common/request_impl.h"
-#include "libcef/common/service_manifests/cef_content_browser_overlay_manifest.h"
-
-#include "base/base_switches.h"
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/json/json_reader.h"
-#include "base/path_service.h"
-#include "base/stl_util.h"
-#include "base/threading/thread_restrictions.h"
-#include "cef/grit/cef_resources.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_content_browser_client.h"
-#include "chrome/browser/net/system_network_context_manager.h"
-#include "chrome/browser/plugins/plugin_info_host_impl.h"
-#include "chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.h"
-#include "chrome/browser/plugins/plugin_utils.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/renderer_updater.h"
-#include "chrome/browser/profiles/renderer_updater_factory.h"
-#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
-#include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/google_url_loader_throttle.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/webui_url_constants.h"
-#include "chrome/grit/browser_resources.h"
-#include "chrome/grit/generated_resources.h"
-#include "chrome/services/printing/printing_service.h"
-#include "components/navigation_interception/intercept_navigation_throttle.h"
-#include "components/navigation_interception/navigation_params.h"
-#include "components/spellcheck/common/spellcheck.mojom.h"
-#include "components/variations/variations_http_header_provider.h"
-#include "components/version_info/version_info.h"
-#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/browser/plugin_service_impl.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_ppapi_host.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/client_certificate_delegate.h"
-#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/overlay_window.h"
-#include "content/public/browser/page_navigator.h"
-#include "content/public/browser/quota_permission_context.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_widget_host.h"
-#include "content/public/browser/render_widget_host_view.h"
-#include "content/public/browser/storage_partition.h"
-#include "content/public/browser/web_ui_url_loader_factory.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/service_names.mojom.h"
-#include "content/public/common/storage_quota_params.h"
-#include "content/public/common/url_constants.h"
-#include "content/public/common/user_agent.h"
-#include "content/public/common/web_preferences.h"
-#include "extensions/browser/extension_message_filter.h"
-#include "extensions/browser/extension_protocols.h"
-#include "extensions/browser/extension_registry.h"
-#include "extensions/browser/extensions_browser_client.h"
-#include "extensions/browser/guest_view/extensions_guest_view_message_filter.h"
-#include "extensions/browser/guest_view/web_view/web_view_guest.h"
-#include "extensions/browser/url_loader_factory_manager.h"
-#include "extensions/common/constants.h"
-#include "extensions/common/switches.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
-#include "net/base/auth.h"
-#include "net/ssl/ssl_cert_request_info.h"
-#include "ppapi/host/ppapi_host.h"
-#include "services/network/public/cpp/network_switches.h"
-#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
-#include "services/service_manager/embedder/switches.h"
-#include "services/service_manager/public/mojom/connector.mojom.h"
-#include "services/service_manager/sandbox/switches.h"
-#include "storage/browser/quota/quota_settings.h"
-#include "third_party/blink/public/mojom/insecure_input/insecure_input_service.mojom.h"
-#include "third_party/blink/public/mojom/prerender/prerender.mojom.h"
-#include "third_party/blink/public/web/web_window_features.h"
-#include "third_party/widevine/cdm/buildflags.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/base/ui_base_switches.h"
-#include "url/gurl.h"
-
-#if defined(OS_LINUX)
-#include "libcef/common/widevine_loader.h"
-#endif
-
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-#include "base/debug/leak_annotations.h"
-#include "chrome/common/chrome_paths.h"
-#include "components/crash/content/browser/crash_handler_host_linux.h"
-#include "components/crash/core/app/breakpad_linux.h"
-#include "content/public/common/content_descriptors.h"
-#endif
-
-#if defined(OS_MACOSX)
-#include "net/ssl/client_cert_store_mac.h"
-#include "services/video_capture/public/mojom/constants.mojom.h"
-#endif
-
-#if defined(OS_WIN)
-#include "net/ssl/client_cert_store_win.h"
-#include "sandbox/win/src/sandbox_policy.h"
-#endif
-
-#if defined(USE_NSS_CERTS)
-#include "net/ssl/client_cert_store_nss.h"
-#endif
-
-#if BUILDFLAG(HAS_SPELLCHECK_PANEL)
-#include "chrome/browser/spellchecker/spell_check_panel_host_impl.h"
-#endif
-
-namespace {
-
-class CefQuotaCallbackImpl : public CefRequestCallback {
- public:
-  using CallbackType = content::QuotaPermissionContext::PermissionCallback;
-
-  explicit CefQuotaCallbackImpl(CallbackType callback)
-      : callback_(std::move(callback)) {}
-
-  ~CefQuotaCallbackImpl() {
-    if (!callback_.is_null()) {
-      // The callback is still pending. Cancel it now.
-      if (CEF_CURRENTLY_ON_IOT()) {
-        RunNow(std::move(callback_), false);
-      } else {
-        CEF_POST_TASK(CEF_IOT, base::BindOnce(&CefQuotaCallbackImpl::RunNow,
-                                              std::move(callback_), false));
-      }
-    }
-  }
-
-  void Continue(bool allow) override {
-    if (CEF_CURRENTLY_ON_IOT()) {
-      if (!callback_.is_null()) {
-        RunNow(std::move(callback_), allow);
-      }
-    } else {
-      CEF_POST_TASK(CEF_IOT, base::BindOnce(&CefQuotaCallbackImpl::Continue,
-                                            this, allow));
-    }
-  }
-
-  void Cancel() override { Continue(false); }
-
-  CallbackType Disconnect() WARN_UNUSED_RESULT { return std::move(callback_); }
-
- private:
-  static void RunNow(CallbackType callback, bool allow) {
-    CEF_REQUIRE_IOT();
-    std::move(callback).Run(
-        allow ? content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW
-              : content::QuotaPermissionContext::
-                    QUOTA_PERMISSION_RESPONSE_DISALLOW);
-  }
-
-  CallbackType callback_;
-
-  IMPLEMENT_REFCOUNTING(CefQuotaCallbackImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefQuotaCallbackImpl);
-};
-
-class CefAllowCertificateErrorCallbackImpl : public CefRequestCallback {
- public:
-  typedef base::OnceCallback<void(content::CertificateRequestResultType)>
-      CallbackType;
-
-  explicit CefAllowCertificateErrorCallbackImpl(CallbackType callback)
-      : callback_(std::move(callback)) {}
-
-  ~CefAllowCertificateErrorCallbackImpl() {
-    if (!callback_.is_null()) {
-      // The callback is still pending. Cancel it now.
-      if (CEF_CURRENTLY_ON_UIT()) {
-        RunNow(std::move(callback_), false);
-      } else {
-        CEF_POST_TASK(
-            CEF_UIT,
-            base::BindOnce(&CefAllowCertificateErrorCallbackImpl::RunNow,
-                           std::move(callback_), false));
-      }
-    }
-  }
-
-  void Continue(bool allow) override {
-    if (CEF_CURRENTLY_ON_UIT()) {
-      if (!callback_.is_null()) {
-        RunNow(std::move(callback_), allow);
-      }
-    } else {
-      CEF_POST_TASK(CEF_UIT,
-                    base::Bind(&CefAllowCertificateErrorCallbackImpl::Continue,
-                               this, allow));
-    }
-  }
-
-  void Cancel() override { Continue(false); }
-
-  CallbackType Disconnect() WARN_UNUSED_RESULT { return std::move(callback_); }
-
- private:
-  static void RunNow(CallbackType callback, bool allow) {
-    CEF_REQUIRE_UIT();
-    std::move(callback).Run(
-        allow ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE
-              : content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL);
-  }
-
-  CallbackType callback_;
-
-  IMPLEMENT_REFCOUNTING(CefAllowCertificateErrorCallbackImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefAllowCertificateErrorCallbackImpl);
-};
-
-class CefSelectClientCertificateCallbackImpl
-    : public CefSelectClientCertificateCallback {
- public:
-  explicit CefSelectClientCertificateCallbackImpl(
-      std::unique_ptr<content::ClientCertificateDelegate> delegate)
-      : delegate_(std::move(delegate)) {}
-
-  ~CefSelectClientCertificateCallbackImpl() {
-    // If Select has not been called, call it with NULL to continue without any
-    // client certificate.
-    if (delegate_)
-      DoSelect(nullptr);
-  }
-
-  void Select(CefRefPtr<CefX509Certificate> cert) override {
-    if (delegate_)
-      DoSelect(cert);
-  }
-
- private:
-  void DoSelect(CefRefPtr<CefX509Certificate> cert) {
-    if (CEF_CURRENTLY_ON_UIT()) {
-      RunNow(std::move(delegate_), cert);
-    } else {
-      CEF_POST_TASK(
-          CEF_UIT,
-          base::BindOnce(&CefSelectClientCertificateCallbackImpl::RunNow,
-                         std::move(delegate_), cert));
-    }
-  }
-
-  static void RunNow(
-      std::unique_ptr<content::ClientCertificateDelegate> delegate,
-      CefRefPtr<CefX509Certificate> cert) {
-    CEF_REQUIRE_UIT();
-
-    if (cert) {
-      CefX509CertificateImpl* certImpl =
-          static_cast<CefX509CertificateImpl*>(cert.get());
-      certImpl->AcquirePrivateKey(base::BindOnce(
-          &CefSelectClientCertificateCallbackImpl::RunWithPrivateKey,
-          std::move(delegate), cert));
-      return;
-    }
-
-    delegate->ContinueWithCertificate(nullptr, nullptr);
-  }
-
-  static void RunWithPrivateKey(
-      std::unique_ptr<content::ClientCertificateDelegate> delegate,
-      CefRefPtr<CefX509Certificate> cert,
-      scoped_refptr<net::SSLPrivateKey> key) {
-    CEF_REQUIRE_UIT();
-    DCHECK(cert);
-
-    if (key) {
-      CefX509CertificateImpl* certImpl =
-          static_cast<CefX509CertificateImpl*>(cert.get());
-      delegate->ContinueWithCertificate(certImpl->GetInternalCertObject(), key);
-    } else {
-      delegate->ContinueWithCertificate(nullptr, nullptr);
-    }
-  }
-
-  std::unique_ptr<content::ClientCertificateDelegate> delegate_;
-
-  IMPLEMENT_REFCOUNTING(CefSelectClientCertificateCallbackImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefSelectClientCertificateCallbackImpl);
-};
-
-class CefQuotaPermissionContext : public content::QuotaPermissionContext {
- public:
-  CefQuotaPermissionContext() {}
-
-  // The callback will be dispatched on the IO thread.
-  void RequestQuotaPermission(const content::StorageQuotaParams& params,
-                              int render_process_id,
-                              PermissionCallback callback) override {
-    if (params.storage_type != blink::mojom::StorageType::kPersistent) {
-      // To match Chrome behavior we only support requesting quota with this
-      // interface for Persistent storage type.
-      std::move(callback).Run(QUOTA_PERMISSION_RESPONSE_DISALLOW);
-      return;
-    }
-
-    bool handled = false;
-
-    CefRefPtr<CefBrowserHostImpl> browser =
-        CefBrowserHostImpl::GetBrowserForFrameRoute(render_process_id,
-                                                    params.render_frame_id);
-    if (browser.get()) {
-      CefRefPtr<CefClient> client = browser->GetClient();
-      if (client.get()) {
-        CefRefPtr<CefRequestHandler> handler = client->GetRequestHandler();
-        if (handler.get()) {
-          CefRefPtr<CefQuotaCallbackImpl> callbackImpl(
-              new CefQuotaCallbackImpl(std::move(callback)));
-          handled = handler->OnQuotaRequest(
-              browser.get(), params.origin_url.spec(), params.requested_size,
-              callbackImpl.get());
-          if (!handled) {
-            // May return nullptr if the client has already executed the
-            // callback.
-            callback = callbackImpl->Disconnect();
-          }
-        }
-      }
-    }
-
-    if (!handled && !callback.is_null()) {
-      // Disallow the request by default.
-      std::move(callback).Run(QUOTA_PERMISSION_RESPONSE_DISALLOW);
-    }
-  }
-
- private:
-  ~CefQuotaPermissionContext() override {}
-
-  DISALLOW_COPY_AND_ASSIGN(CefQuotaPermissionContext);
-};
-
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-breakpad::CrashHandlerHostLinux* CreateCrashHandlerHost(
-    const std::string& process_type) {
-  base::FilePath dumps_path;
-  base::PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path);
-  {
-    ANNOTATE_SCOPED_MEMORY_LEAK;
-    // Uploads will only occur if a non-empty crash URL is specified in
-    // CefMainDelegate::InitCrashReporter.
-    breakpad::CrashHandlerHostLinux* crash_handler =
-        new breakpad::CrashHandlerHostLinux(process_type, dumps_path,
-                                            true /* upload */);
-    crash_handler->StartUploaderThread();
-    return crash_handler;
-  }
-}
-
-int GetCrashSignalFD(const base::CommandLine& command_line) {
-  if (!breakpad::IsCrashReporterEnabled())
-    return -1;
-
-  // Extensions have the same process type as renderers.
-  if (command_line.HasSwitch(extensions::switches::kExtensionProcess)) {
-    static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
-    if (!crash_handler)
-      crash_handler = CreateCrashHandlerHost("extension");
-    return crash_handler->GetDeathSignalSocket();
-  }
-
-  std::string process_type =
-      command_line.GetSwitchValueASCII(switches::kProcessType);
-
-  if (process_type == switches::kRendererProcess) {
-    static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
-    if (!crash_handler)
-      crash_handler = CreateCrashHandlerHost(process_type);
-    return crash_handler->GetDeathSignalSocket();
-  }
-
-  if (process_type == switches::kPpapiPluginProcess) {
-    static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
-    if (!crash_handler)
-      crash_handler = CreateCrashHandlerHost(process_type);
-    return crash_handler->GetDeathSignalSocket();
-  }
-
-  if (process_type == switches::kGpuProcess) {
-    static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
-    if (!crash_handler)
-      crash_handler = CreateCrashHandlerHost(process_type);
-    return crash_handler->GetDeathSignalSocket();
-  }
-
-  return -1;
-}
-#endif  // defined(OS_POSIX) && !defined(OS_MACOSX)
-
-// TODO(cef): We can't currently trust NavigationParams::is_main_frame() because
-// it's always set to true in
-// InterceptNavigationThrottle::CheckIfShouldIgnoreNavigation. Remove the
-// |is_main_frame| argument once this problem is fixed.
-bool NavigationOnUIThread(
-    bool is_main_frame,
-    int64_t frame_id,
-    int64_t parent_frame_id,
-    int frame_tree_node_id,
-    content::WebContents* source,
-    const navigation_interception::NavigationParams& params) {
-  CEF_REQUIRE_UIT();
-
-  bool ignore_navigation = false;
-
-  CefRefPtr<CefBrowserHostImpl> browser =
-      CefBrowserHostImpl::GetBrowserForContents(source);
-  if (browser.get()) {
-    CefRefPtr<CefClient> client = browser->GetClient();
-    if (client.get()) {
-      CefRefPtr<CefRequestHandler> handler = client->GetRequestHandler();
-      if (handler.get()) {
-        CefRefPtr<CefFrame> frame;
-        if (is_main_frame) {
-          frame = browser->GetMainFrame();
-        } else if (frame_id >= 0) {
-          frame = browser->GetFrame(frame_id);
-        }
-        if (!frame && frame_tree_node_id >= 0) {
-          frame = browser->GetFrameForFrameTreeNode(frame_tree_node_id);
-        }
-        if (!frame) {
-          // Create a temporary frame object for navigation of sub-frames that
-          // don't yet exist.
-          frame = browser->browser_info()->CreateTempSubFrame(parent_frame_id);
-        }
-
-        CefRefPtr<CefRequestImpl> request = new CefRequestImpl();
-        request->Set(params, is_main_frame);
-        request->SetReadOnly(true);
-
-        // Initiating a new navigation in OnBeforeBrowse will delete the
-        // InterceptNavigationThrottle that currently owns this callback,
-        // resulting in a crash. Use the lock to prevent that.
-        std::unique_ptr<CefBrowserHostImpl::NavigationLock> navigation_lock =
-            browser->CreateNavigationLock();
-        ignore_navigation = handler->OnBeforeBrowse(
-            browser.get(), frame, request.get(), params.has_user_gesture(),
-            params.is_redirect());
-      }
-    }
-  }
-
-  return ignore_navigation;
-}
-
-// From chrome/browser/plugins/chrome_content_browser_client_plugins_part.cc.
-void BindPluginInfoHost(
-    int render_process_id,
-    mojo::PendingAssociatedReceiver<chrome::mojom::PluginInfoHost> receiver) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  content::RenderProcessHost* host =
-      content::RenderProcessHost::FromID(render_process_id);
-  if (!host)
-    return;
-
-  Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
-  mojo::MakeSelfOwnedAssociatedReceiver(
-      std::make_unique<PluginInfoHostImpl>(render_process_id, profile),
-      std::move(receiver));
-}
-
-base::FilePath GetRootCachePath() {
-  // The CefContext::ValidateCachePath method enforces the requirement that all
-  // cache_path values be either equal to or a child of root_cache_path.
-  return base::FilePath(
-      CefString(&CefContext::Get()->settings().root_cache_path));
-}
-
-// Register BrowserInterfaceBroker's GetInterface() handler callbacks for
-// chrome-specific document-scoped interfaces.
-// Stub implementations to silence "Empty binder for interface
-// blink.mojom.[Name] for the frame/document scope" errors.
-// Based on chrome/browser/chrome_browser_interface_binders.cc.
-void PopulateChromeFrameBinders(
-    service_manager::BinderMapWithContext<content::RenderFrameHost*>* map) {
-  map->Add<blink::mojom::InsecureInputService>(base::BindRepeating(
-      [](content::RenderFrameHost* frame_host,
-         mojo::PendingReceiver<blink::mojom::InsecureInputService> receiver) {
-      }));
-
-  map->Add<blink::mojom::PrerenderProcessor>(base::BindRepeating(
-      [](content::RenderFrameHost* frame_host,
-         mojo::PendingReceiver<blink::mojom::PrerenderProcessor> receiver) {}));
-}
-
-}  // namespace
-
-CefContentBrowserClient::CefContentBrowserClient()
-    : browser_main_parts_(nullptr) {
-  plugin_service_filter_.reset(new CefPluginServiceFilter);
-  content::PluginServiceImpl::GetInstance()->SetFilter(
-      plugin_service_filter_.get());
-}
-
-CefContentBrowserClient::~CefContentBrowserClient() {}
-
-// static
-CefContentBrowserClient* CefContentBrowserClient::Get() {
-  if (!CefContentClient::Get())
-    return nullptr;
-  return static_cast<CefContentBrowserClient*>(
-      CefContentClient::Get()->browser());
-}
-
-std::unique_ptr<content::BrowserMainParts>
-CefContentBrowserClient::CreateBrowserMainParts(
-    const content::MainFunctionParams& parameters) {
-  browser_main_parts_ = new CefBrowserMainParts(parameters);
-  return base::WrapUnique(browser_main_parts_);
-}
-
-void CefContentBrowserClient::RenderProcessWillLaunch(
-    content::RenderProcessHost* host) {
-  const int id = host->GetID();
-  Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
-
-  host->AddFilter(new CefBrowserMessageFilter(id));
-  host->AddFilter(new printing::CefPrintingMessageFilter(id, profile));
-
-  if (extensions::ExtensionsEnabled()) {
-    host->AddFilter(new extensions::ExtensionMessageFilter(id, profile));
-    host->AddFilter(
-        new extensions::ExtensionsGuestViewMessageFilter(id, profile));
-  }
-
-  // If the renderer process crashes then the host may already have
-  // CefBrowserInfoManager as an observer. Try to remove it first before adding
-  // to avoid DCHECKs.
-  host->RemoveObserver(CefBrowserInfoManager::GetInstance());
-  host->AddObserver(CefBrowserInfoManager::GetInstance());
-
-  // Forwards dynamic parameters to CefRenderThreadObserver.
-  Profile* original_profile = profile->GetOriginalProfile();
-  RendererUpdaterFactory::GetForProfile(original_profile)
-      ->InitializeRenderer(host);
-}
-
-bool CefContentBrowserClient::ShouldUseProcessPerSite(
-    content::BrowserContext* browser_context,
-    const GURL& effective_url) {
-  if (!extensions::ExtensionsEnabled())
-    return false;
-
-  if (!effective_url.SchemeIs(extensions::kExtensionScheme))
-    return false;
-
-  extensions::ExtensionRegistry* registry =
-      extensions::ExtensionRegistry::Get(browser_context);
-  if (!registry)
-    return false;
-
-  const extensions::Extension* extension =
-      registry->enabled_extensions().GetByID(effective_url.host());
-  if (!extension)
-    return false;
-
-  // TODO(extensions): Extra checks required if type is TYPE_HOSTED_APP.
-
-  // Hosted apps that have script access to their background page must use
-  // process per site, since all instances can make synchronous calls to the
-  // background window.  Other extensions should use process per site as well.
-  return true;
-}
-
-// Based on
-// ChromeContentBrowserClientExtensionsPart::DoesSiteRequireDedicatedProcess.
-bool CefContentBrowserClient::DoesSiteRequireDedicatedProcess(
-    content::BrowserContext* browser_context,
-    const GURL& effective_site_url) {
-  if (!extensions::ExtensionsEnabled())
-    return false;
-
-  const extensions::Extension* extension =
-      extensions::ExtensionRegistry::Get(browser_context)
-          ->enabled_extensions()
-          .GetExtensionOrAppByURL(effective_site_url);
-  // Isolate all extensions.
-  return extension != nullptr;
-}
-
-void CefContentBrowserClient::OverrideURLLoaderFactoryParams(
-    content::BrowserContext* browser_context,
-    const url::Origin& origin,
-    bool is_for_isolated_world,
-    network::mojom::URLLoaderFactoryParams* factory_params) {
-  if (extensions::ExtensionsEnabled()) {
-    extensions::URLLoaderFactoryManager::OverrideURLLoaderFactoryParams(
-        browser_context, origin, is_for_isolated_world, factory_params);
-  }
-}
-
-void CefContentBrowserClient::GetAdditionalWebUISchemes(
-    std::vector<std::string>* additional_schemes) {
-  // Any schemes listed here are treated as WebUI schemes but do not get WebUI
-  // bindings. Also, view-source is allowed for these schemes. WebUI schemes
-  // will not be passed to HandleExternalProtocol.
-}
-
-void CefContentBrowserClient::GetAdditionalViewSourceSchemes(
-    std::vector<std::string>* additional_schemes) {
-  GetAdditionalWebUISchemes(additional_schemes);
-
-  additional_schemes->push_back(extensions::kExtensionScheme);
-}
-
-void CefContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
-    std::vector<std::string>* additional_allowed_schemes) {
-  ContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
-      additional_allowed_schemes);
-  additional_allowed_schemes->push_back(content::kChromeDevToolsScheme);
-  additional_allowed_schemes->push_back(content::kChromeUIScheme);
-}
-
-bool CefContentBrowserClient::IsWebUIAllowedToMakeNetworkRequests(
-    const url::Origin& origin) {
-  return scheme::IsWebUIAllowedToMakeNetworkRequests(origin);
-}
-
-bool CefContentBrowserClient::IsHandledURL(const GURL& url) {
-  if (!url.is_valid())
-    return false;
-  const std::string& scheme = url.scheme();
-  DCHECK_EQ(scheme, base::ToLowerASCII(scheme));
-
-  if (scheme::IsInternalHandledScheme(scheme))
-    return true;
-
-  return CefContentClient::Get()->HasCustomScheme(scheme);
-}
-
-void CefContentBrowserClient::SiteInstanceGotProcess(
-    content::SiteInstance* site_instance) {
-  if (!extensions::ExtensionsEnabled())
-    return;
-
-  // If this isn't an extension renderer there's nothing to do.
-  const extensions::Extension* extension = GetExtension(site_instance);
-  if (!extension)
-    return;
-
-  CefBrowserContext* browser_context =
-      static_cast<CefBrowserContext*>(site_instance->GetBrowserContext());
-
-  extensions::ProcessMap::Get(browser_context)
-      ->Insert(extension->id(), site_instance->GetProcess()->GetID(),
-               site_instance->GetId());
-
-  CEF_POST_TASK(
-      CEF_IOT, base::Bind(&extensions::InfoMap::RegisterExtensionProcess,
-                          browser_context->extension_system()->info_map(),
-                          extension->id(), site_instance->GetProcess()->GetID(),
-                          site_instance->GetId()));
-}
-
-void CefContentBrowserClient::SiteInstanceDeleting(
-    content::SiteInstance* site_instance) {
-  if (!extensions::ExtensionsEnabled())
-    return;
-
-  // May be NULL during shutdown.
-  if (!extensions::ExtensionsBrowserClient::Get())
-    return;
-
-  // May be NULL during shutdown.
-  if (!site_instance->HasProcess())
-    return;
-
-  // If this isn't an extension renderer there's nothing to do.
-  const extensions::Extension* extension = GetExtension(site_instance);
-  if (!extension)
-    return;
-
-  CefBrowserContext* browser_context =
-      static_cast<CefBrowserContext*>(site_instance->GetBrowserContext());
-
-  extensions::ProcessMap::Get(browser_context)
-      ->Remove(extension->id(), site_instance->GetProcess()->GetID(),
-               site_instance->GetId());
-
-  CEF_POST_TASK(
-      CEF_IOT, base::Bind(&extensions::InfoMap::UnregisterExtensionProcess,
-                          browser_context->extension_system()->info_map(),
-                          extension->id(), site_instance->GetProcess()->GetID(),
-                          site_instance->GetId()));
-}
-
-void CefContentBrowserClient::BindHostReceiverForRenderer(
-    content::RenderProcessHost* render_process_host,
-    mojo::GenericPendingReceiver receiver) {
-  if (auto host_receiver = receiver.As<spellcheck::mojom::SpellCheckHost>()) {
-    SpellCheckHostChromeImpl::Create(render_process_host->GetID(),
-                                     std::move(host_receiver));
-    return;
-  }
-
-#if BUILDFLAG(HAS_SPELLCHECK_PANEL)
-  if (auto panel_host_receiver =
-          receiver.As<spellcheck::mojom::SpellCheckPanelHost>()) {
-    SpellCheckPanelHostImpl::Create(render_process_host->GetID(),
-                                    std::move(panel_host_receiver));
-    return;
-  }
-#endif  // BUILDFLAG(HAS_SPELLCHECK_PANEL)
-}
-
-base::Optional<service_manager::Manifest>
-CefContentBrowserClient::GetServiceManifestOverlay(base::StringPiece name) {
-  if (name == content::mojom::kBrowserServiceName) {
-    return GetCefContentBrowserOverlayManifest();
-  }
-
-  return base::nullopt;
-}
-
-void CefContentBrowserClient::AppendExtraCommandLineSwitches(
-    base::CommandLine* command_line,
-    int child_process_id) {
-  const base::CommandLine* browser_cmd = base::CommandLine::ForCurrentProcess();
-
-  {
-    // Propagate the following switches to all command lines (along with any
-    // associated values) if present in the browser command line.
-    static const char* const kSwitchNames[] = {
-      switches::kDisablePackLoading,
-#if defined(OS_MACOSX)
-      switches::kFrameworkDirPath,
-      switches::kMainBundlePath,
-#endif
-      switches::kLocalesDirPath,
-      switches::kLogFile,
-      switches::kLogSeverity,
-      switches::kProductVersion,
-      switches::kResourcesDirPath,
-      switches::kUserAgent,
-    };
-    command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames,
-                                   base::size(kSwitchNames));
-  }
-
-  const std::string& process_type =
-      command_line->GetSwitchValueASCII(switches::kProcessType);
-  if (process_type == switches::kRendererProcess) {
-    // Propagate the following switches to the renderer command line (along with
-    // any associated values) if present in the browser command line.
-    static const char* const kSwitchNames[] = {
-        switches::kDisableExtensions,
-        switches::kDisablePdfExtension,
-        switches::kDisablePlugins,
-        switches::kDisablePrintPreview,
-        switches::kDisableScrollBounce,
-        switches::kDisableSpellChecking,
-        switches::kEnableSpeechInput,
-        switches::kEnableSystemFlash,
-        switches::kPpapiFlashArgs,
-        switches::kPpapiFlashPath,
-        switches::kPpapiFlashVersion,
-        switches::kUncaughtExceptionStackSize,
-        network::switches::kUnsafelyTreatInsecureOriginAsSecure,
-    };
-    command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames,
-                                   base::size(kSwitchNames));
-
-    if (extensions::ExtensionsEnabled()) {
-      content::RenderProcessHost* process =
-          content::RenderProcessHost::FromID(child_process_id);
-      CefBrowserContext* context =
-          process
-              ? CefBrowserContext::GetForContext(process->GetBrowserContext())
-              : nullptr;
-      if (context) {
-        if (context->IsPrintPreviewSupported()) {
-          command_line->AppendSwitch(switches::kEnablePrintPreview);
-        }
-
-        // Based on ChromeContentBrowserClientExtensionsPart::
-        // AppendExtraRendererCommandLineSwitches
-        if (extensions::ProcessMap::Get(context)->Contains(process->GetID())) {
-          command_line->AppendSwitch(extensions::switches::kExtensionProcess);
-        }
-      }
-    }
-  } else {
-    // Propagate the following switches to non-renderer command line (along with
-    // any associated values) if present in the browser command line.
-    static const char* const kSwitchNames[] = {
-        switches::kLang,
-    };
-    command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames,
-                                   base::size(kSwitchNames));
-  }
-
-#if defined(OS_LINUX)
-  if (process_type == service_manager::switches::kZygoteProcess) {
-    // Propagate the following switches to the zygote command line (along with
-    // any associated values) if present in the browser command line.
-    static const char* const kSwitchNames[] = {
-        switches::kPpapiFlashPath,
-        switches::kPpapiFlashVersion,
-    };
-    command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames,
-                                   base::size(kSwitchNames));
-
-#if BUILDFLAG(ENABLE_WIDEVINE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
-    if (!browser_cmd->HasSwitch(service_manager::switches::kNoSandbox)) {
-      // Pass the Widevine CDM path to the Zygote process. See comments in
-      // CefWidevineLoader::AddContentDecryptionModules.
-      const base::FilePath& cdm_path = CefWidevineLoader::GetInstance()->path();
-      if (!cdm_path.empty())
-        command_line->AppendSwitchPath(switches::kWidevineCdmPath, cdm_path);
-    }
-#endif
-
-    if (browser_cmd->HasSwitch(switches::kBrowserSubprocessPath)) {
-      // Force use of the sub-process executable path for the zygote process.
-      const base::FilePath& subprocess_path =
-          browser_cmd->GetSwitchValuePath(switches::kBrowserSubprocessPath);
-      if (!subprocess_path.empty())
-        command_line->SetProgram(subprocess_path);
-    }
-  }
-#endif  // defined(OS_LINUX)
-
-  CefRefPtr<CefApp> app = CefContentClient::Get()->application();
-  if (app.get()) {
-    CefRefPtr<CefBrowserProcessHandler> handler =
-        app->GetBrowserProcessHandler();
-    if (handler.get()) {
-      CefRefPtr<CefCommandLineImpl> commandLinePtr(
-          new CefCommandLineImpl(command_line, false, false));
-      handler->OnBeforeChildProcessLaunch(commandLinePtr.get());
-      commandLinePtr->Detach(nullptr);
-    }
-  }
-}
-
-std::string CefContentBrowserClient::GetApplicationLocale() {
-  return g_browser_process->GetApplicationLocale();
-}
-
-scoped_refptr<network::SharedURLLoaderFactory>
-CefContentBrowserClient::GetSystemSharedURLLoaderFactory() {
-  DCHECK(
-      content::BrowserThread::CurrentlyOn(content::BrowserThread::UI) ||
-      !content::BrowserThread::IsThreadInitialized(content::BrowserThread::UI));
-
-  if (!SystemNetworkContextManager::GetInstance())
-    return nullptr;
-
-  return SystemNetworkContextManager::GetInstance()
-      ->GetSharedURLLoaderFactory();
-}
-
-network::mojom::NetworkContext*
-CefContentBrowserClient::GetSystemNetworkContext() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK(SystemNetworkContextManager::GetInstance());
-  return SystemNetworkContextManager::GetInstance()->GetContext();
-}
-
-scoped_refptr<content::QuotaPermissionContext>
-CefContentBrowserClient::CreateQuotaPermissionContext() {
-  return new CefQuotaPermissionContext();
-}
-
-content::MediaObserver* CefContentBrowserClient::GetMediaObserver() {
-  return CefMediaCaptureDevicesDispatcher::GetInstance();
-}
-
-content::SpeechRecognitionManagerDelegate*
-CefContentBrowserClient::CreateSpeechRecognitionManagerDelegate() {
-  const base::CommandLine* command_line =
-      base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kEnableSpeechInput))
-    return new CefSpeechRecognitionManagerDelegate();
-
-  return nullptr;
-}
-
-content::GeneratedCodeCacheSettings
-CefContentBrowserClient::GetGeneratedCodeCacheSettings(
-    content::BrowserContext* context) {
-  // If we pass 0 for size, disk_cache will pick a default size using the
-  // heuristics based on available disk size. These are implemented in
-  // disk_cache::PreferredCacheSize in net/disk_cache/cache_util.cc.
-  const base::FilePath& cache_path = context->GetPath();
-  return content::GeneratedCodeCacheSettings(!cache_path.empty() /* enabled */,
-                                             0 /* size */, cache_path);
-}
-
-void CefContentBrowserClient::AllowCertificateError(
-    content::WebContents* web_contents,
-    int cert_error,
-    const net::SSLInfo& ssl_info,
-    const GURL& request_url,
-    bool is_main_frame_request,
-    bool strict_enforcement,
-    base::OnceCallback<void(content::CertificateRequestResultType)> callback) {
-  CEF_REQUIRE_UIT();
-
-  if (!is_main_frame_request) {
-    // A sub-resource has a certificate error. The user doesn't really
-    // have a context for making the right decision, so block the request
-    // hard.
-    std::move(callback).Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL);
-    return;
-  }
-
-  CefRefPtr<CefBrowserHostImpl> browser =
-      CefBrowserHostImpl::GetBrowserForContents(web_contents);
-  if (!browser.get())
-    return;
-  CefRefPtr<CefClient> client = browser->GetClient();
-  if (!client.get())
-    return;
-  CefRefPtr<CefRequestHandler> handler = client->GetRequestHandler();
-  if (!handler.get())
-    return;
-
-  CefRefPtr<CefSSLInfo> cef_ssl_info = new CefSSLInfoImpl(ssl_info);
-
-  CefRefPtr<CefAllowCertificateErrorCallbackImpl> callbackImpl(
-      new CefAllowCertificateErrorCallbackImpl(std::move(callback)));
-
-  bool proceed = handler->OnCertificateError(
-      browser.get(), static_cast<cef_errorcode_t>(cert_error),
-      request_url.spec(), cef_ssl_info, callbackImpl.get());
-  if (!proceed) {
-    // |callback| may be null if the user executed it despite returning false.
-    callback = callbackImpl->Disconnect();
-    if (!callback.is_null()) {
-      std::move(callback).Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL);
-    }
-  }
-}
-
-base::OnceClosure CefContentBrowserClient::SelectClientCertificate(
-    content::WebContents* web_contents,
-    net::SSLCertRequestInfo* cert_request_info,
-    net::ClientCertIdentityList client_certs,
-    std::unique_ptr<content::ClientCertificateDelegate> delegate) {
-  CEF_REQUIRE_UIT();
-
-  CefRefPtr<CefRequestHandler> handler;
-  CefRefPtr<CefBrowserHostImpl> browser =
-      CefBrowserHostImpl::GetBrowserForContents(web_contents);
-  if (browser.get()) {
-    CefRefPtr<CefClient> client = browser->GetClient();
-    if (client.get())
-      handler = client->GetRequestHandler();
-  }
-
-  if (!handler.get()) {
-    delegate->ContinueWithCertificate(nullptr, nullptr);
-    return base::OnceClosure();
-  }
-
-  CefRequestHandler::X509CertificateList certs;
-  for (net::ClientCertIdentityList::iterator iter = client_certs.begin();
-       iter != client_certs.end(); iter++) {
-    certs.push_back(new CefX509CertificateImpl(std::move(*iter)));
-  }
-
-  CefRefPtr<CefSelectClientCertificateCallbackImpl> callbackImpl(
-      new CefSelectClientCertificateCallbackImpl(std::move(delegate)));
-
-  bool proceed = handler->OnSelectClientCertificate(
-      browser.get(), cert_request_info->is_proxy,
-      cert_request_info->host_and_port.host(),
-      cert_request_info->host_and_port.port(), certs, callbackImpl.get());
-
-  if (!proceed && !certs.empty()) {
-    callbackImpl->Select(certs[0]);
-  }
-  return base::OnceClosure();
-}
-
-bool CefContentBrowserClient::CanCreateWindow(
-    content::RenderFrameHost* opener,
-    const GURL& opener_url,
-    const GURL& opener_top_level_frame_url,
-    const url::Origin& source_origin,
-    content::mojom::WindowContainerType container_type,
-    const GURL& target_url,
-    const content::Referrer& referrer,
-    const std::string& frame_name,
-    WindowOpenDisposition disposition,
-    const blink::mojom::WindowFeatures& features,
-    bool user_gesture,
-    bool opener_suppressed,
-    bool* no_javascript_access) {
-  CEF_REQUIRE_UIT();
-  *no_javascript_access = false;
-
-  return CefBrowserInfoManager::GetInstance()->CanCreateWindow(
-      opener, target_url, referrer, frame_name, disposition, features,
-      user_gesture, opener_suppressed, no_javascript_access);
-}
-
-void CefContentBrowserClient::OverrideWebkitPrefs(
-    content::RenderViewHost* rvh,
-    content::WebPreferences* prefs) {
-  // Using RVH instead of RFH here because rvh->GetMainFrame() may be nullptr
-  // when this method is called.
-  renderer_prefs::PopulateWebPreferences(rvh, *prefs);
-
-  if (rvh->GetWidget()->GetView()) {
-    rvh->GetWidget()->GetView()->SetBackgroundColor(
-        prefs->base_background_color);
-  }
-}
-
-void CefContentBrowserClient::BrowserURLHandlerCreated(
-    content::BrowserURLHandler* handler) {
-  scheme::BrowserURLHandlerCreated(handler);
-}
-
-std::string CefContentBrowserClient::GetDefaultDownloadName() {
-  return "download";
-}
-
-void CefContentBrowserClient::DidCreatePpapiPlugin(
-    content::BrowserPpapiHost* browser_host) {
-  browser_host->GetPpapiHost()->AddHostFactoryFilter(
-      std::unique_ptr<ppapi::host::HostFactory>(
-          new ChromeBrowserPepperHostFactory(browser_host)));
-}
-
-content::DevToolsManagerDelegate*
-CefContentBrowserClient::GetDevToolsManagerDelegate() {
-  return new CefDevToolsManagerDelegate();
-}
-
-std::vector<std::unique_ptr<content::NavigationThrottle>>
-CefContentBrowserClient::CreateThrottlesForNavigation(
-    content::NavigationHandle* navigation_handle) {
-  CEF_REQUIRE_UIT();
-
-  std::vector<std::unique_ptr<content::NavigationThrottle>> throttles;
-
-  const bool is_main_frame = navigation_handle->IsInMainFrame();
-
-  // Identify the RenderFrameHost that originated the navigation.
-  const int64_t parent_frame_id =
-      !is_main_frame
-          ? CefFrameHostImpl::MakeFrameId(navigation_handle->GetParentFrame())
-          : CefFrameHostImpl::kInvalidFrameId;
-
-  const int64_t frame_id = !is_main_frame && navigation_handle->HasCommitted()
-                               ? CefFrameHostImpl::MakeFrameId(
-                                     navigation_handle->GetRenderFrameHost())
-                               : CefFrameHostImpl::kInvalidFrameId;
-
-  // Must use SynchronyMode::kSync to ensure that OnBeforeBrowse is always
-  // called before OnBeforeResourceLoad.
-  std::unique_ptr<content::NavigationThrottle> throttle =
-      std::make_unique<navigation_interception::InterceptNavigationThrottle>(
-          navigation_handle,
-          base::Bind(&NavigationOnUIThread, is_main_frame, frame_id,
-                     parent_frame_id, navigation_handle->GetFrameTreeNodeId()),
-          navigation_interception::SynchronyMode::kSync);
-  throttles.push_back(std::move(throttle));
-
-  return throttles;
-}
-
-std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
-CefContentBrowserClient::CreateURLLoaderThrottles(
-    const network::ResourceRequest& request,
-    content::BrowserContext* browser_context,
-    const base::RepeatingCallback<content::WebContents*()>& wc_getter,
-    content::NavigationUIData* navigation_ui_data,
-    int frame_tree_node_id) {
-  std::vector<std::unique_ptr<blink::URLLoaderThrottle>> result;
-
-  // Used to substitute View ID for PDF contents when using the PDF plugin.
-  result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>(
-      request.resource_type, frame_tree_node_id));
-
-  Profile* profile = Profile::FromBrowserContext(browser_context);
-
-  chrome::mojom::DynamicParams dynamic_params = {
-      profile->GetPrefs()->GetBoolean(prefs::kForceGoogleSafeSearch),
-      profile->GetPrefs()->GetInteger(prefs::kForceYouTubeRestrict),
-      profile->GetPrefs()->GetString(prefs::kAllowedDomainsForApps)};
-  result.push_back(
-      std::make_unique<GoogleURLLoaderThrottle>(std::move(dynamic_params)));
-
-  return result;
-}
-
-#if defined(OS_LINUX)
-void CefContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
-    const base::CommandLine& command_line,
-    int child_process_id,
-    content::PosixFileDescriptorInfo* mappings) {
-  int crash_signal_fd = GetCrashSignalFD(command_line);
-  if (crash_signal_fd >= 0) {
-    mappings->Share(service_manager::kCrashDumpSignal, crash_signal_fd);
-  }
-}
-#endif  // defined(OS_LINUX)
-
-#if defined(OS_WIN)
-const wchar_t* CefContentBrowserClient::GetResourceDllName() {
-  static wchar_t file_path[MAX_PATH + 1] = {0};
-
-  if (file_path[0] == 0) {
-    // Retrieve the module path (usually libcef.dll).
-    base::FilePath module;
-    base::PathService::Get(base::FILE_MODULE, &module);
-    const std::wstring wstr = module.value();
-    size_t count = std::min(static_cast<size_t>(MAX_PATH), wstr.size());
-    wcsncpy(file_path, wstr.c_str(), count);
-    file_path[count] = 0;
-  }
-
-  return file_path;
-}
-
-bool CefContentBrowserClient::PreSpawnRenderer(sandbox::TargetPolicy* policy,
-                                               RendererSpawnFlags flags) {
-  return true;
-}
-#endif  // defined(OS_WIN)
-
-void CefContentBrowserClient::ExposeInterfacesToRenderer(
-    service_manager::BinderRegistry* registry,
-    blink::AssociatedInterfaceRegistry* associated_registry,
-    content::RenderProcessHost* host) {
-  associated_registry->AddInterface(
-      base::BindRepeating(&BindPluginInfoHost, host->GetID()));
-}
-
-std::unique_ptr<net::ClientCertStore>
-CefContentBrowserClient::CreateClientCertStore(
-    content::BrowserContext* browser_context) {
-  // Match the logic in ProfileNetworkContextService::CreateClientCertStore.
-#if defined(USE_NSS_CERTS)
-  // TODO: Add support for client implementation of crypto password dialog.
-  return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreNSS(
-      net::ClientCertStoreNSS::PasswordDelegateFactory()));
-#elif defined(OS_WIN)
-  return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreWin());
-#elif defined(OS_MACOSX)
-  return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreMac());
-#else
-#error Unknown platform.
-#endif
-}
-
-std::unique_ptr<content::LoginDelegate>
-CefContentBrowserClient::CreateLoginDelegate(
-    const net::AuthChallengeInfo& auth_info,
-    content::WebContents* web_contents,
-    const content::GlobalRequestID& request_id,
-    bool is_request_for_main_frame,
-    const GURL& url,
-    scoped_refptr<net::HttpResponseHeaders> response_headers,
-    bool first_auth_attempt,
-    LoginAuthRequiredCallback auth_required_callback) {
-  return std::make_unique<net_service::LoginDelegate>(
-      auth_info, web_contents, request_id, url,
-      std::move(auth_required_callback));
-}
-
-void CefContentBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories(
-    int frame_tree_node_id,
-    NonNetworkURLLoaderFactoryMap* factories) {
-  if (!extensions::ExtensionsEnabled())
-    return;
-
-  content::WebContents* web_contents =
-      content::WebContents::FromFrameTreeNodeId(frame_tree_node_id);
-  factories->emplace(
-      extensions::kExtensionScheme,
-      extensions::CreateExtensionNavigationURLLoaderFactory(
-          web_contents->GetBrowserContext(),
-          !!extensions::WebViewGuest::FromWebContents(web_contents)));
-}
-
-void CefContentBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
-    int render_process_id,
-    int render_frame_id,
-    NonNetworkURLLoaderFactoryMap* factories) {
-  if (!extensions::ExtensionsEnabled())
-    return;
-
-  auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id,
-                                                             render_frame_id);
-  if (factory)
-    factories->emplace(extensions::kExtensionScheme, std::move(factory));
-
-  content::RenderFrameHost* frame_host =
-      content::RenderFrameHost::FromID(render_process_id, render_frame_id);
-  content::WebContents* web_contents =
-      content::WebContents::FromRenderFrameHost(frame_host);
-  if (!web_contents)
-    return;
-
-  extensions::CefExtensionWebContentsObserver* web_observer =
-      extensions::CefExtensionWebContentsObserver::FromWebContents(
-          web_contents);
-
-  // There is nothing to do if no CefExtensionWebContentsObserver is attached
-  // to the |web_contents|.
-  if (!web_observer)
-    return;
-
-  const extensions::Extension* extension =
-      web_observer->GetExtensionFromFrame(frame_host, false);
-  if (!extension)
-    return;
-
-  std::vector<std::string> allowed_webui_hosts;
-  // Support for chrome:// scheme if appropriate.
-  if ((extension->is_extension() || extension->is_platform_app()) &&
-      extensions::Manifest::IsComponentLocation(extension->location())) {
-    // Components of chrome that are implemented as extensions or platform apps
-    // are allowed to use chrome://resources/ and chrome://theme/ URLs.
-    allowed_webui_hosts.emplace_back(content::kChromeUIResourcesHost);
-    allowed_webui_hosts.emplace_back(chrome::kChromeUIThemeHost);
-  }
-  if (!allowed_webui_hosts.empty()) {
-    factories->emplace(
-        content::kChromeUIScheme,
-        content::CreateWebUIURLLoader(frame_host, content::kChromeUIScheme,
-                                      std::move(allowed_webui_hosts)));
-  }
-}
-
-bool CefContentBrowserClient::WillCreateURLLoaderFactory(
-    content::BrowserContext* browser_context,
-    content::RenderFrameHost* frame,
-    int render_process_id,
-    URLLoaderFactoryType type,
-    const url::Origin& request_initiator,
-    base::Optional<int64_t> navigation_id,
-    mojo::PendingReceiver<network::mojom::URLLoaderFactory>* factory_receiver,
-    mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
-        header_client,
-    bool* bypass_redirect_checks,
-    bool* disable_secure_dns,
-    network::mojom::URLLoaderFactoryOverridePtr* factory_override) {
-  auto request_handler = net_service::CreateInterceptedRequestHandler(
-      browser_context, frame, render_process_id,
-      type == URLLoaderFactoryType::kNavigation,
-      type == URLLoaderFactoryType::kDownload, request_initiator);
-
-  net_service::ProxyURLLoaderFactory::CreateProxy(
-      browser_context, factory_receiver, header_client,
-      std::move(request_handler));
-  return true;
-}
-
-void CefContentBrowserClient::OnNetworkServiceCreated(
-    network::mojom::NetworkService* network_service) {
-  DCHECK(g_browser_process);
-  PrefService* local_state = g_browser_process->local_state();
-  DCHECK(local_state);
-
-  // Need to set up global NetworkService state before anything else uses it.
-  DCHECK(SystemNetworkContextManager::GetInstance());
-  SystemNetworkContextManager::GetInstance()->OnNetworkServiceCreated(
-      network_service);
-}
-
-mojo::Remote<network::mojom::NetworkContext>
-CefContentBrowserClient::CreateNetworkContext(
-    content::BrowserContext* context,
-    bool in_memory,
-    const base::FilePath& relative_partition_path) {
-  // This method may be called during shutdown when using multi-threaded
-  // message loop mode. In that case exit early to avoid crashes.
-  if (!SystemNetworkContextManager::GetInstance())
-    return mojo::Remote<network::mojom::NetworkContext>();
-
-  Profile* profile = Profile::FromBrowserContext(context);
-  return profile->CreateNetworkContext(in_memory, relative_partition_path);
-}
-
-// The sandbox may block read/write access from the NetworkService to
-// directories that are not returned by this method.
-std::vector<base::FilePath>
-CefContentBrowserClient::GetNetworkContextsParentDirectory() {
-  base::FilePath user_data_path;
-  base::PathService::Get(chrome::DIR_USER_DATA, &user_data_path);
-  DCHECK(!user_data_path.empty());
-
-  const auto& root_cache_path = GetRootCachePath();
-
-  // root_cache_path may sometimes be empty or a child of user_data_path, so
-  // only return the one path in that case.
-  if (root_cache_path.empty() || user_data_path.IsParent(root_cache_path)) {
-    return {user_data_path};
-  }
-
-  return {user_data_path, root_cache_path};
-}
-
-bool CefContentBrowserClient::HandleExternalProtocol(
-    const GURL& url,
-    base::OnceCallback<content::WebContents*()> web_contents_getter,
-    int child_id,
-    content::NavigationUIData* navigation_data,
-    bool is_main_frame,
-    ui::PageTransition page_transition,
-    bool has_user_gesture,
-    const base::Optional<url::Origin>& initiating_origin,
-    mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
-  // Call the other HandleExternalProtocol variant.
-  return false;
-}
-
-bool CefContentBrowserClient::HandleExternalProtocol(
-    content::WebContents::Getter web_contents_getter,
-    int frame_tree_node_id,
-    content::NavigationUIData* navigation_data,
-    const network::ResourceRequest& resource_request,
-    mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
-  mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver =
-      out_factory->InitWithNewPipeAndPassReceiver();
-  // CefBrowserPlatformDelegate::HandleExternalProtocol may be called if
-  // nothing handles the request.
-  if (CEF_CURRENTLY_ON_IOT()) {
-    auto request_handler = net_service::CreateInterceptedRequestHandler(
-        web_contents_getter, frame_tree_node_id, resource_request);
-    net_service::ProxyURLLoaderFactory::CreateProxy(
-        web_contents_getter, std::move(receiver), std::move(request_handler));
-  } else {
-    auto request_handler = net_service::CreateInterceptedRequestHandler(
-        web_contents_getter, frame_tree_node_id, resource_request);
-    CEF_POST_TASK(
-        CEF_IOT,
-        base::BindOnce(
-            [](mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,
-               std::unique_ptr<net_service::InterceptedRequestHandler>
-                   request_handler,
-               content::WebContents::Getter web_contents_getter) {
-              // Manages its own lifetime.
-
-              net_service::ProxyURLLoaderFactory::CreateProxy(
-                  web_contents_getter, std::move(receiver),
-                  std::move(request_handler));
-            },
-            std::move(receiver), std::move(request_handler),
-            std::move(web_contents_getter)));
-  }
-  return true;
-}
-
-std::unique_ptr<content::OverlayWindow>
-CefContentBrowserClient::CreateWindowForPictureInPicture(
-    content::PictureInPictureWindowController* controller) {
-  // Note: content::OverlayWindow::Create() is defined by platform-specific
-  // implementation in chrome/browser/ui/views. This layering hack, which goes
-  // through //content and ContentBrowserClient, allows us to work around the
-  // dependency constraints that disallow directly calling
-  // chrome/browser/ui/views code either from here or from other code in
-  // chrome/browser.
-  return content::OverlayWindow::Create(controller);
-}
-
-void CefContentBrowserClient::RegisterBrowserInterfaceBindersForFrame(
-    content::RenderFrameHost* render_frame_host,
-    service_manager::BinderMapWithContext<content::RenderFrameHost*>* map) {
-  PopulateChromeFrameBinders(map);
-
-  if (!extensions::ExtensionsEnabled())
-    return;
-
-  content::WebContents* web_contents =
-      content::WebContents::FromRenderFrameHost(render_frame_host);
-  if (!web_contents)
-    return;
-
-  const GURL& site = render_frame_host->GetSiteInstance()->GetSiteURL();
-  if (!site.SchemeIs(extensions::kExtensionScheme))
-    return;
-
-  content::BrowserContext* browser_context =
-      render_frame_host->GetProcess()->GetBrowserContext();
-  auto* extension = extensions::ExtensionRegistry::Get(browser_context)
-                        ->enabled_extensions()
-                        .GetByID(site.host());
-  if (!extension)
-    return;
-  extensions::ExtensionsBrowserClient::Get()
-      ->RegisterBrowserInterfaceBindersForFrame(map, render_frame_host,
-                                                extension);
-}
-
-base::FilePath
-CefContentBrowserClient::GetSandboxedStorageServiceDataDirectory() {
-  return GetRootCachePath();
-}
-
-std::string CefContentBrowserClient::GetProduct() {
-  // Match the logic in chrome_content_browser_client.cc GetProduct().
-  return ::GetProduct();
-}
-
-std::string CefContentBrowserClient::GetChromeProduct() {
-  return version_info::GetProductNameAndVersionForUserAgent();
-}
-
-std::string CefContentBrowserClient::GetUserAgent() {
-  // Match the logic in chrome_content_browser_client.cc GetUserAgent().
-  return ::GetUserAgent();
-}
-
-blink::UserAgentMetadata CefContentBrowserClient::GetUserAgentMetadata() {
-  blink::UserAgentMetadata metadata;
-
-  metadata.brand = version_info::GetProductName();
-  metadata.full_version = version_info::GetVersionNumber();
-  metadata.platform = version_info::GetOSType();
-
-  // TODO(mkwst): Poke at BuildUserAgentFromProduct to split out these pieces.
-  metadata.architecture = "";
-  metadata.model = "";
-
-  return metadata;
-}
-
-base::flat_set<std::string>
-CefContentBrowserClient::GetPluginMimeTypesWithExternalHandlers(
-    content::BrowserContext* browser_context) {
-  base::flat_set<std::string> mime_types;
-  auto map = PluginUtils::GetMimeTypeToExtensionIdMap(browser_context);
-  for (const auto& pair : map)
-    mime_types.insert(pair.first);
-  return mime_types;
-}
-
-CefRefPtr<CefRequestContextImpl> CefContentBrowserClient::request_context()
-    const {
-  return browser_main_parts_->request_context();
-}
-
-CefDevToolsDelegate* CefContentBrowserClient::devtools_delegate() const {
-  return browser_main_parts_->devtools_delegate();
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-CefContentBrowserClient::background_task_runner() const {
-  return browser_main_parts_->background_task_runner();
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-CefContentBrowserClient::user_visible_task_runner() const {
-  return browser_main_parts_->user_visible_task_runner();
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-CefContentBrowserClient::user_blocking_task_runner() const {
-  return browser_main_parts_->user_blocking_task_runner();
-}
-
-const extensions::Extension* CefContentBrowserClient::GetExtension(
-    content::SiteInstance* site_instance) {
-  extensions::ExtensionRegistry* registry =
-      extensions::ExtensionRegistry::Get(site_instance->GetBrowserContext());
-  if (!registry)
-    return nullptr;
-  return registry->enabled_extensions().GetExtensionOrAppByURL(
-      site_instance->GetSiteURL());
-}
diff --git a/src/libcef/browser/context.cc b/src/libcef/browser/context.cc
index 5fd2138..5e0d6f7 100644
--- a/src/libcef/browser/context.cc
+++ b/src/libcef/browser/context.cc
@@ -3,48 +3,29 @@
 // be found in the LICENSE file.
 
 #include "libcef/browser/context.h"
-#include "libcef/browser/browser_host_impl.h"
-#include "libcef/browser/browser_info.h"
+
 #include "libcef/browser/browser_info_manager.h"
-#include "libcef/browser/browser_main.h"
-#include "libcef/browser/chrome_browser_process_stub.h"
+#include "libcef/browser/request_context_impl.h"
 #include "libcef/browser/thread_util.h"
 #include "libcef/browser/trace_subscriber.h"
 #include "libcef/common/cef_switches.h"
-#include "libcef/common/main_delegate.h"
-#include "libcef/common/widevine_loader.h"
-#include "libcef/renderer/content_renderer_client.h"
 
-#include "base/base_switches.h"
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/debug/debugger.h"
 #include "base/files/file_util.h"
+#include "base/functional/bind.h"
 #include "base/run_loop.h"
-#include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "components/network_session_configurator/common/network_switches.h"
-#include "content/app/content_service_manager_main_delegate.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/common/content_switches.h"
-#include "services/service_manager/embedder/main.h"
-#include "ui/base/resource/resource_bundle.h"
 #include "ui/base/ui_base_switches.h"
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
+#include "base/debug/alias.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/chrome_elf/chrome_elf_main.h"
 #include "chrome/install_static/initialize_from_primary_module.h"
-#include "components/crash/core/app/crashpad.h"
-#include "content/public/app/sandbox_helper_win.h"
-#include "sandbox/win/src/sandbox_types.h"
-#endif
-
-#if defined(OS_MACOSX) || defined(OS_WIN)
-#include "components/crash/core/app/crash_switches.h"
-#include "third_party/crashpad/crashpad/handler/handler_main.h"
+#include "include/internal/cef_win.h"
 #endif
 
 namespace {
@@ -59,27 +40,15 @@
 } g_shutdown_checker;
 #endif  // DCHECK_IS_ON()
 
-#if defined(OS_WIN)
-#if defined(ARCH_CPU_X86_64)
-// VS2013 only checks the existence of FMA3 instructions, not the enabled-ness
-// of them at the OS level (this is fixed in VS2015). We force off usage of
-// FMA3 instructions in the CRT to avoid using that path and hitting illegal
-// instructions when running on CPUs that support FMA3, but OSs that don't.
-void DisableFMA3() {
-  static bool disabled = false;
-  if (disabled)
-    return;
-  disabled = true;
-  _set_FMA3_enable(0);
-}
-#endif  // defined(ARCH_CPU_X86_64)
+#if BUILDFLAG(IS_WIN)
 
 // Transfer state from chrome_elf.dll to the libcef.dll. Accessed when
 // loading chrome://system.
 void InitInstallDetails() {
   static bool initialized = false;
-  if (initialized)
+  if (initialized) {
     return;
+  }
   initialized = true;
   install_static::InitializeFromPrimaryModule();
 }
@@ -88,65 +57,20 @@
 // DllMain. See https://crbug.com/656800 for details.
 void InitCrashReporter() {
   static bool initialized = false;
-  if (initialized)
+  if (initialized) {
     return;
+  }
   initialized = true;
   SignalInitializeCrashReporting();
 }
-#endif  // defined(OS_WIN)
 
-#if defined(OS_MACOSX) || defined(OS_WIN)
-
-// Based on components/crash/core/app/run_as_crashpad_handler_win.cc
-// Remove the "--type=crashpad-handler" command-line flag that will otherwise
-// confuse the crashpad handler.
-// Chrome uses an embedded crashpad handler on Windows only and imports this
-// function via the existing "run_as_crashpad_handler" target defined in
-// components/crash/core/app/BUILD.gn. CEF uses an embedded handler on both
-// Windows and macOS so we define the function here instead of using the
-// existing target (because we can't use that target on macOS).
-int RunAsCrashpadHandler(const base::CommandLine& command_line) {
-  base::CommandLine::StringVector argv = command_line.argv();
-  const base::CommandLine::StringType process_type =
-      FILE_PATH_LITERAL("--type=");
-  argv.erase(
-      std::remove_if(argv.begin(), argv.end(),
-                     [&process_type](const base::CommandLine::StringType& str) {
-                       return base::StartsWith(str, process_type,
-                                               base::CompareCase::SENSITIVE) ||
-                              (!str.empty() && str[0] == L'/');
-                     }),
-      argv.end());
-
-#if defined(OS_MACOSX)
-  // HandlerMain on macOS uses the system version of getopt_long which expects
-  // the first argument to be the program name.
-  argv.insert(argv.begin(), command_line.GetProgram().value());
-#endif
-
-  std::unique_ptr<char*[]> argv_as_utf8(new char*[argv.size() + 1]);
-  std::vector<std::string> storage;
-  storage.reserve(argv.size());
-  for (size_t i = 0; i < argv.size(); ++i) {
-#if defined(OS_WIN)
-    storage.push_back(base::UTF16ToUTF8(argv[i]));
-#else
-    storage.push_back(argv[i]);
-#endif
-    argv_as_utf8[i] = &storage[i][0];
-  }
-  argv_as_utf8[argv.size()] = nullptr;
-  argv.clear();
-  return crashpad::HandlerMain(static_cast<int>(storage.size()),
-                               argv_as_utf8.get(), nullptr);
-}
-
-#endif  // defined(OS_MACOSX) || defined(OS_WIN)
+#endif  // BUILDFLAG(IS_WIN)
 
 bool GetColor(const cef_color_t cef_in, bool is_windowless, SkColor* sk_out) {
   // Windowed browser colors must be fully opaque.
-  if (!is_windowless && CefColorGetA(cef_in) != SK_AlphaOPAQUE)
+  if (!is_windowless && CefColorGetA(cef_in) != SK_AlphaOPAQUE) {
     return false;
+  }
 
   // Windowless browser colors may be fully transparent.
   if (is_windowless && CefColorGetA(cef_in) == SK_AlphaTRANSPARENT) {
@@ -164,8 +88,9 @@
 base::FilePath NormalizePath(const cef_string_t& path_str,
                              const char* name,
                              bool* has_error = nullptr) {
-  if (has_error)
+  if (has_error) {
     *has_error = false;
+  }
 
   base::FilePath path = base::FilePath(CefString(&path_str));
   if (path.EndsWithSeparator()) {
@@ -177,8 +102,9 @@
   if (!path.empty() && !path.IsAbsolute()) {
     LOG(ERROR) << "The " << name << " directory (" << path.value()
                << ") is not an absolute path. Defaulting to empty.";
-    if (has_error)
+    if (has_error) {
       *has_error = true;
+    }
     path = base::FilePath();
   }
 
@@ -186,7 +112,7 @@
 }
 
 void SetPath(cef_string_t& path_str, const base::FilePath& path) {
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   CefString(&path_str).FromWString(path.value());
 #else
   CefString(&path_str).FromString(path.value());
@@ -203,8 +129,9 @@
 // Verify that |cache_path| is valid and create it if necessary.
 bool ValidateCachePath(const base::FilePath& cache_path,
                        const base::FilePath& root_cache_path) {
-  if (cache_path.empty())
+  if (cache_path.empty()) {
     return true;
+  }
 
   if (!root_cache_path.empty() && root_cache_path != cache_path &&
       !root_cache_path.IsParent(cache_path)) {
@@ -214,7 +141,7 @@
     return false;
   }
 
-  base::ThreadRestrictions::ScopedAllowIO allow_io;
+  base::ScopedAllowBlockingForTesting allow_blocking;
   if (!base::DirectoryExists(cache_path) &&
       !base::CreateDirectory(cache_path)) {
     LOG(ERROR) << "The cache_path directory (" << cache_path.value()
@@ -239,89 +166,142 @@
   return path;
 }
 
+// Based on chrome/app/chrome_exe_main_win.cc.
+// In 32-bit builds, the main thread starts with the default (small) stack size.
+// The ARCH_CPU_32_BITS blocks here and below are in support of moving the main
+// thread to a fiber with a larger stack size.
+#if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_32_BITS)
+// The information needed to transfer control to the large-stack fiber and later
+// pass the main routine's exit code back to the small-stack fiber prior to
+// termination.
+struct FiberState {
+  FiberState(wWinMainPtr wWinMain,
+             HINSTANCE hInstance,
+             LPWSTR lpCmdLine,
+             int nCmdShow) {
+    this->wWinMain = wWinMain;
+    this->hInstance = hInstance;
+    this->lpCmdLine = lpCmdLine;
+    this->nCmdShow = nCmdShow;
+  }
+
+  FiberState(mainPtr main, int argc, char** argv) {
+    this->main = main;
+    this->argc = argc;
+    this->argv = argv;
+  }
+
+  wWinMainPtr wWinMain = nullptr;
+  HINSTANCE hInstance;
+  LPWSTR lpCmdLine;
+  int nCmdShow;
+
+  mainPtr main = nullptr;
+  int argc;
+  char** argv;
+
+  LPVOID original_fiber;
+  int fiber_result;
+};
+
+// A PFIBER_START_ROUTINE function run on a large-stack fiber that calls the
+// main routine, stores its return value, and returns control to the small-stack
+// fiber. |params| must be a pointer to a FiberState struct.
+void WINAPI FiberBinder(void* params) {
+  auto* fiber_state = static_cast<FiberState*>(params);
+  // Call the main routine from the fiber. Reusing the entry point minimizes
+  // confusion when examining call stacks in crash reports - seeing wWinMain on
+  // the stack is a handy hint that this is the main thread of the process.
+  if (fiber_state->main) {
+    fiber_state->fiber_result =
+        fiber_state->main(fiber_state->argc, fiber_state->argv);
+  } else {
+    fiber_state->fiber_result =
+        fiber_state->wWinMain(fiber_state->hInstance, nullptr,
+                              fiber_state->lpCmdLine, fiber_state->nCmdShow);
+  }
+
+  // Switch back to the main thread to exit.
+  ::SwitchToFiber(fiber_state->original_fiber);
+}
+
+int RunMainWithPreferredStackSize(FiberState& fiber_state) {
+  enum class FiberStatus { kConvertFailed, kCreateFiberFailed, kSuccess };
+  FiberStatus fiber_status = FiberStatus::kSuccess;
+  // GetLastError result if fiber conversion failed.
+  DWORD fiber_error = ERROR_SUCCESS;
+  if (!::IsThreadAFiber()) {
+    // Make the main thread's stack size 4 MiB so that it has roughly the same
+    // effective size as the 64-bit build's 8 MiB stack.
+    constexpr size_t kStackSize = 4 * 1024 * 1024;  // 4 MiB
+    // Leak the fiber on exit.
+    LPVOID original_fiber =
+        ::ConvertThreadToFiberEx(nullptr, FIBER_FLAG_FLOAT_SWITCH);
+    if (original_fiber) {
+      fiber_state.original_fiber = original_fiber;
+      // Create a fiber with a bigger stack and switch to it. Leak the fiber on
+      // exit.
+      LPVOID big_stack_fiber = ::CreateFiberEx(
+          0, kStackSize, FIBER_FLAG_FLOAT_SWITCH, FiberBinder, &fiber_state);
+      if (big_stack_fiber) {
+        ::SwitchToFiber(big_stack_fiber);
+        // The fibers must be cleaned up to avoid obscure TLS-related shutdown
+        // crashes.
+        ::DeleteFiber(big_stack_fiber);
+        ::ConvertFiberToThread();
+        // Control returns here after CEF has finished running on FiberMain.
+        return fiber_state.fiber_result;
+      }
+      fiber_status = FiberStatus::kCreateFiberFailed;
+    } else {
+      fiber_status = FiberStatus::kConvertFailed;
+    }
+    // If we reach here then creating and switching to a fiber has failed. This
+    // probably means we are low on memory and will soon crash. Try to report
+    // this error once crash reporting is initialized.
+    fiber_error = ::GetLastError();
+    base::debug::Alias(&fiber_error);
+  }
+
+  // If we are already a fiber then continue normal execution.
+  // Intentionally crash if converting to a fiber failed.
+  CHECK_EQ(fiber_status, FiberStatus::kSuccess);
+  return -1;
+}
+#endif  // BUILDFLAG(IS_WIN) && defined(ARCH_CPU_32_BITS)
+
 }  // namespace
 
 int CefExecuteProcess(const CefMainArgs& args,
                       CefRefPtr<CefApp> application,
                       void* windows_sandbox_info) {
-#if defined(OS_WIN)
-#if defined(ARCH_CPU_X86_64)
-  DisableFMA3();
-#endif
+#if BUILDFLAG(IS_WIN)
   InitInstallDetails();
   InitCrashReporter();
 #endif
 
-  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-#if defined(OS_WIN)
-  command_line.ParseFromString(::GetCommandLineW());
-#else
-  command_line.InitFromArgv(args.argc, args.argv);
-#endif
-
-  // Wait for the debugger as early in process initialization as possible.
-  if (command_line.HasSwitch(switches::kWaitForDebugger))
-    base::debug::WaitForDebugger(60, true);
-
-  // If no process type is specified then it represents the browser process and
-  // we do nothing.
-  std::string process_type =
-      command_line.GetSwitchValueASCII(switches::kProcessType);
-  if (process_type.empty())
-    return -1;
-
-#if defined(OS_MACOSX) || defined(OS_WIN)
-  if (process_type == crash_reporter::switches::kCrashpadHandler)
-    return RunAsCrashpadHandler(command_line);
-#endif
-
-  CefMainDelegate main_delegate(application);
-
-// Execute the secondary process.
-#if defined(OS_WIN)
-  sandbox::SandboxInterfaceInfo sandbox_info = {0};
-  if (windows_sandbox_info == nullptr) {
-    content::InitializeSandboxInfo(&sandbox_info);
-    windows_sandbox_info = &sandbox_info;
-  }
-
-  content::ContentMainParams params(&main_delegate);
-  params.instance = args.instance;
-  params.sandbox_info =
-      static_cast<sandbox::SandboxInterfaceInfo*>(windows_sandbox_info);
-
-  return content::ContentMain(params);
-#else
-  content::ContentMainParams params(&main_delegate);
-  params.argc = args.argc;
-  params.argv = const_cast<const char**>(args.argv);
-
-  return content::ContentMain(params);
-#endif
+  return CefMainRunner::RunAsHelperProcess(args, application,
+                                           windows_sandbox_info);
 }
 
 bool CefInitialize(const CefMainArgs& args,
                    const CefSettings& settings,
                    CefRefPtr<CefApp> application,
                    void* windows_sandbox_info) {
-#if defined(OS_WIN)
-#if defined(ARCH_CPU_X86_64)
-  DisableFMA3();
-#endif
+#if BUILDFLAG(IS_WIN)
   InitInstallDetails();
   InitCrashReporter();
 #endif
 
   // Return true if the global context already exists.
-  if (g_context)
+  if (g_context) {
     return true;
-
-  if (settings.size != sizeof(cef_settings_t)) {
-    NOTREACHED() << "invalid CefSettings structure size";
-    return false;
   }
 
-  g_browser_process = new ChromeBrowserProcessStub();
+  if (settings.size != sizeof(cef_settings_t)) {
+    DCHECK(false) << "invalid CefSettings structure size";
+    return false;
+  }
 
   // Create the new global context object.
   g_context = new CefContext();
@@ -334,13 +314,13 @@
 void CefShutdown() {
   // Verify that the context is in a valid state.
   if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
+    DCHECK(false) << "context not valid";
     return;
   }
 
   // Must always be called on the same thread as Initialize.
   if (!g_context->OnInitThread()) {
-    NOTREACHED() << "called on invalid thread";
+    DCHECK(false) << "called on invalid thread";
     return;
   }
 
@@ -355,13 +335,13 @@
 void CefDoMessageLoopWork() {
   // Verify that the context is in a valid state.
   if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
+    DCHECK(false) << "context not valid";
     return;
   }
 
   // Must always be called on the same thread as Initialize.
   if (!g_context->OnInitThread()) {
-    NOTREACHED() << "called on invalid thread";
+    DCHECK(false) << "called on invalid thread";
     return;
   }
 
@@ -372,52 +352,71 @@
 void CefRunMessageLoop() {
   // Verify that the context is in a valid state.
   if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
+    DCHECK(false) << "context not valid";
     return;
   }
 
   // Must always be called on the same thread as Initialize.
   if (!g_context->OnInitThread()) {
-    NOTREACHED() << "called on invalid thread";
+    DCHECK(false) << "called on invalid thread";
     return;
   }
 
-  base::RunLoop run_loop;
-  run_loop.Run();
+  g_context->RunMessageLoop();
 }
 
 void CefQuitMessageLoop() {
   // Verify that the context is in a valid state.
   if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
+    DCHECK(false) << "context not valid";
     return;
   }
 
   // Must always be called on the same thread as Initialize.
   if (!g_context->OnInitThread()) {
-    NOTREACHED() << "called on invalid thread";
+    DCHECK(false) << "called on invalid thread";
     return;
   }
 
-  // Quit the CefBrowserMessageLoop.
-  base::RunLoop::QuitCurrentWhenIdleDeprecated();
+  g_context->QuitMessageLoop();
 }
 
+#if BUILDFLAG(IS_WIN)
+
+#if defined(ARCH_CPU_32_BITS)
+int CefRunWinMainWithPreferredStackSize(wWinMainPtr wWinMain,
+                                        HINSTANCE hInstance,
+                                        LPWSTR lpCmdLine,
+                                        int nCmdShow) {
+  CHECK(wWinMain && hInstance);
+  FiberState fiber_state(wWinMain, hInstance, lpCmdLine, nCmdShow);
+  return RunMainWithPreferredStackSize(fiber_state);
+}
+
+int CefRunMainWithPreferredStackSize(mainPtr main, int argc, char* argv[]) {
+  CHECK(main);
+  FiberState fiber_state(main, argc, argv);
+  return RunMainWithPreferredStackSize(fiber_state);
+}
+#endif  // defined(ARCH_CPU_32_BITS)
+
 void CefSetOSModalLoop(bool osModalLoop) {
-#if defined(OS_WIN)
   // Verify that the context is in a valid state.
   if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
+    DCHECK(false) << "context not valid";
     return;
   }
 
-  if (CEF_CURRENTLY_ON_UIT())
-    base::MessageLoopCurrent::Get()->set_os_modal_loop(osModalLoop);
-  else
-    CEF_POST_TASK(CEF_UIT, base::Bind(CefSetOSModalLoop, osModalLoop));
-#endif  // defined(OS_WIN)
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(CefSetOSModalLoop, osModalLoop));
+    return;
+  }
+
+  base::CurrentThread::Get()->set_os_modal_loop(osModalLoop);
 }
 
+#endif  // BUILDFLAG(IS_WIN)
+
 // CefContext
 
 CefContext::CefContext()
@@ -436,15 +435,16 @@
                             void* windows_sandbox_info) {
   init_thread_id_ = base::PlatformThread::CurrentId();
   settings_ = settings;
+  application_ = application;
 
-#if !(defined(OS_WIN) || defined(OS_LINUX))
+#if !(BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX))
   if (settings.multi_threaded_message_loop) {
     NOTIMPLEMENTED() << "multi_threaded_message_loop is not supported.";
     return false;
   }
 #endif
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   // Signal Chrome Elf that Chrome has begun to start.
   SignalChromeElf();
 #endif
@@ -462,82 +462,32 @@
                       "browser_subprocess_path");
   NormalizePathAndSet(settings_.framework_dir_path, "framework_dir_path");
   NormalizePathAndSet(settings_.main_bundle_path, "main_bundle_path");
-  NormalizePathAndSet(settings_.user_data_path, "user_data_path");
   NormalizePathAndSet(settings_.resources_dir_path, "resources_dir_path");
   NormalizePathAndSet(settings_.locales_dir_path, "locales_dir_path");
 
-  main_delegate_.reset(new CefMainDelegate(application));
   browser_info_manager_.reset(new CefBrowserInfoManager);
 
-  int exit_code;
+  main_runner_.reset(new CefMainRunner(settings_.multi_threaded_message_loop,
+                                       settings_.external_message_pump));
+  return main_runner_->Initialize(
+      &settings_, application, args, windows_sandbox_info, &initialized_,
+      base::BindOnce(&CefContext::OnContextInitialized,
+                     base::Unretained(this)));
+}
 
-  // Initialize the content runner.
-  content::ContentMainParams params(main_delegate_.get());
-#if defined(OS_WIN)
-  sandbox::SandboxInterfaceInfo sandbox_info = {0};
-  if (windows_sandbox_info == nullptr) {
-    windows_sandbox_info = &sandbox_info;
-    settings_.no_sandbox = true;
-  }
+void CefContext::RunMessageLoop() {
+  // Must always be called on the same thread as Initialize.
+  DCHECK(OnInitThread());
 
-  params.instance = args.instance;
-  params.sandbox_info =
-      static_cast<sandbox::SandboxInterfaceInfo*>(windows_sandbox_info);
-#else
-  params.argc = args.argc;
-  params.argv = const_cast<const char**>(args.argv);
-#endif
+  // Blocks until QuitMessageLoop() is called.
+  main_runner_->RunMessageLoop();
+}
 
-  sm_main_delegate_.reset(
-      new content::ContentServiceManagerMainDelegate(params));
-  sm_main_params_.reset(
-      new service_manager::MainParams(sm_main_delegate_.get()));
+void CefContext::QuitMessageLoop() {
+  // Must always be called on the same thread as Initialize.
+  DCHECK(OnInitThread());
 
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
-  sm_main_params_->argc = params.argc;
-  sm_main_params_->argv = params.argv;
-#endif
-
-  exit_code = service_manager::MainInitialize(*sm_main_params_);
-  DCHECK_LT(exit_code, 0);
-  if (exit_code >= 0)
-    return false;
-
-  static_cast<ChromeBrowserProcessStub*>(g_browser_process)->Initialize();
-
-  if (settings.multi_threaded_message_loop) {
-    base::WaitableEvent uithread_startup_event(
-        base::WaitableEvent::ResetPolicy::AUTOMATIC,
-        base::WaitableEvent::InitialState::NOT_SIGNALED);
-
-    if (!main_delegate_->CreateUIThread(base::BindOnce(
-            [](CefContext* context, base::WaitableEvent* event) {
-              service_manager::MainRun(*context->sm_main_params_);
-              event->Signal();
-            },
-            base::Unretained(this),
-            base::Unretained(&uithread_startup_event)))) {
-      return false;
-    }
-
-    initialized_ = true;
-
-    // We need to wait until service_manager::MainRun has finished.
-    uithread_startup_event.Wait();
-  } else {
-    initialized_ = true;
-    service_manager::MainRun(*sm_main_params_);
-  }
-
-  if (CEF_CURRENTLY_ON_UIT()) {
-    OnContextInitialized();
-  } else {
-    // Continue initialization on the UI thread.
-    CEF_POST_TASK(CEF_UIT, base::Bind(&CefContext::OnContextInitialized,
-                                      base::Unretained(this)));
-  }
-
-  return true;
+  main_runner_->QuitMessageLoop();
 }
 
 void CefContext::Shutdown() {
@@ -546,28 +496,9 @@
 
   shutting_down_ = true;
 
-  if (settings_.multi_threaded_message_loop) {
-    // Events that will be used to signal when shutdown is complete. Start in
-    // non-signaled mode so that the event will block.
-    base::WaitableEvent uithread_shutdown_event(
-        base::WaitableEvent::ResetPolicy::AUTOMATIC,
-        base::WaitableEvent::InitialState::NOT_SIGNALED);
-
-    // Finish shutdown on the UI thread.
-    CEF_POST_TASK(CEF_UIT,
-                  base::Bind(&CefContext::FinishShutdownOnUIThread,
-                             base::Unretained(this), &uithread_shutdown_event));
-
-    /// Block until UI thread shutdown is complete.
-    uithread_shutdown_event.Wait();
-
-    FinalizeShutdown();
-  } else {
-    // Finish shutdown on the current thread, which should be the UI thread.
-    FinishShutdownOnUIThread(nullptr);
-
-    FinalizeShutdown();
-  }
+  main_runner_->Shutdown(
+      base::BindOnce(&CefContext::ShutdownOnUIThread, base::Unretained(this)),
+      base::BindOnce(&CefContext::FinalizeShutdown, base::Unretained(this)));
 }
 
 bool CefContext::OnInitThread() {
@@ -595,10 +526,12 @@
 
 CefTraceSubscriber* CefContext::GetTraceSubscriber() {
   CEF_REQUIRE_UIT();
-  if (shutting_down_)
+  if (shutting_down_) {
     return nullptr;
-  if (!trace_subscriber_.get())
+  }
+  if (!trace_subscriber_.get()) {
     trace_subscriber_.reset(new CefTraceSubscriber());
+  }
   return trace_subscriber_.get();
 }
 
@@ -616,11 +549,11 @@
   settings->persist_user_preferences =
       settings_.persist_user_preferences ||
       command_line->HasSwitch(switches::kPersistUserPreferences);
-  settings->ignore_certificate_errors =
-      settings_.ignore_certificate_errors ||
-      command_line->HasSwitch(switches::kIgnoreCertificateErrors);
-  CefString(&settings->accept_language_list) =
-      CefString(&settings_.accept_language_list);
+
+  CefString(&settings->cookieable_schemes_list) =
+      CefString(&settings_.cookieable_schemes_list);
+  settings->cookieable_schemes_exclude_defaults =
+      settings_.cookieable_schemes_exclude_defaults;
 }
 
 void CefContext::NormalizeRequestContextSettings(
@@ -628,12 +561,6 @@
   // The |root_cache_path| value was already normalized in Initialize.
   const base::FilePath& root_cache_path = CefString(&settings_.root_cache_path);
   NormalizeCachePathAndSet(settings->cache_path, root_cache_path);
-
-  if (settings->accept_language_list.length == 0) {
-    // Use the global language list setting.
-    CefString(&settings->accept_language_list) =
-        CefString(&settings_.accept_language_list);
-  }
 }
 
 void CefContext::AddObserver(Observer* observer) {
@@ -654,62 +581,38 @@
 void CefContext::OnContextInitialized() {
   CEF_REQUIRE_UIT();
 
-  static_cast<ChromeBrowserProcessStub*>(g_browser_process)
-      ->OnContextInitialized();
-
-#if BUILDFLAG(ENABLE_WIDEVINE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
-  CefWidevineLoader::GetInstance()->OnContextInitialized();
-#endif
-
-  // Notify the handler.
-  CefRefPtr<CefApp> app = CefContentClient::Get()->application();
-  if (app.get()) {
-    CefRefPtr<CefBrowserProcessHandler> handler =
-        app->GetBrowserProcessHandler();
-    if (handler.get())
-      handler->OnContextInitialized();
+  if (application_) {
+    // Notify the handler after the global browser context has initialized.
+    CefRefPtr<CefRequestContext> request_context =
+        CefRequestContext::GetGlobalContext();
+    auto impl = static_cast<CefRequestContextImpl*>(request_context.get());
+    impl->ExecuteWhenBrowserContextInitialized(base::BindOnce(
+        [](CefRefPtr<CefApp> app) {
+          CefRefPtr<CefBrowserProcessHandler> handler =
+              app->GetBrowserProcessHandler();
+          if (handler) {
+            handler->OnContextInitialized();
+          }
+        },
+        application_));
   }
 }
 
-void CefContext::FinishShutdownOnUIThread(
-    base::WaitableEvent* uithread_shutdown_event) {
+void CefContext::ShutdownOnUIThread() {
   CEF_REQUIRE_UIT();
 
   browser_info_manager_->DestroyAllBrowsers();
 
-  for (auto& observer : observers_)
+  for (auto& observer : observers_) {
     observer.OnContextDestroyed();
+  }
 
-  if (trace_subscriber_.get())
+  if (trace_subscriber_.get()) {
     trace_subscriber_.reset(nullptr);
-
-  static_cast<ChromeBrowserProcessStub*>(g_browser_process)->Shutdown();
-
-  ui::ResourceBundle::GetSharedInstance().CleanupOnUIThread();
-
-  sm_main_delegate_->ShutdownOnUIThread();
-
-  if (uithread_shutdown_event)
-    uithread_shutdown_event->Signal();
+  }
 }
 
 void CefContext::FinalizeShutdown() {
-  if (content::RenderProcessHost::run_renderer_in_process()) {
-    // Blocks until RenderProcess cleanup is complete.
-    CefContentRendererClient::Get()->RunSingleProcessCleanup();
-  }
-
-  // Shut down the browser runner or UI thread.
-  main_delegate_->ShutdownBrowser();
-
-  // Shut down the content runner.
-  service_manager::MainShutdown(*sm_main_params_);
-
   browser_info_manager_.reset(nullptr);
-  sm_main_params_.reset(nullptr);
-  sm_main_delegate_.reset(nullptr);
-  main_delegate_.reset(nullptr);
-
-  delete g_browser_process;
-  g_browser_process = nullptr;
+  application_ = nullptr;
 }
diff --git a/src/libcef/browser/context.h b/src/libcef/browser/context.h
index eacc02a..40530c0 100644
--- a/src/libcef/browser/context.h
+++ b/src/libcef/browser/context.h
@@ -11,32 +11,17 @@
 #include <string>
 
 #include "include/cef_app.h"
+#include "libcef/browser/main_runner.h"
 
 #include "base/observer_list.h"
 #include "base/threading/platform_thread.h"
 #include "third_party/skia/include/core/SkColor.h"
 
-namespace base {
-class WaitableEvent;
-}
-
-namespace content {
-class ContentServiceManagerMainDelegate;
-}
-
-namespace service_manager {
-struct MainParams;
-}
-
-class CefBrowserHostImpl;
 class CefBrowserInfoManager;
-class CefMainDelegate;
 class CefTraceSubscriber;
 
 class CefContext {
  public:
-  typedef std::list<CefRefPtr<CefBrowserHostImpl>> BrowserList;
-
   // Interface to implement for observers that wish to be informed of changes
   // to the context. All methods will be called on the UI thread.
   class Observer {
@@ -59,6 +44,8 @@
                   const CefSettings& settings,
                   CefRefPtr<CefApp> application,
                   void* windows_sandbox_info);
+  void RunMessageLoop();
+  void QuitMessageLoop();
   void Shutdown();
 
   // Returns true if the current thread is the initialization thread.
@@ -105,7 +92,7 @@
 
   // Performs shutdown actions that need to occur on the UI thread before any
   // threads are destroyed.
-  void FinishShutdownOnUIThread(base::WaitableEvent* uithread_shutdown_event);
+  void ShutdownOnUIThread();
 
   // Destroys the main runner and related objects.
   void FinalizeShutdown();
@@ -118,10 +105,9 @@
   base::PlatformThreadId init_thread_id_;
 
   CefSettings settings_;
+  CefRefPtr<CefApp> application_;
 
-  std::unique_ptr<CefMainDelegate> main_delegate_;
-  std::unique_ptr<content::ContentServiceManagerMainDelegate> sm_main_delegate_;
-  std::unique_ptr<service_manager::MainParams> sm_main_params_;
+  std::unique_ptr<CefMainRunner> main_runner_;
   std::unique_ptr<CefTraceSubscriber> trace_subscriber_;
   std::unique_ptr<CefBrowserInfoManager> browser_info_manager_;
 
diff --git a/src/libcef/browser/context_menu_params_impl.cc b/src/libcef/browser/context_menu_params_impl.cc
index 6047d1a..fe3be41 100644
--- a/src/libcef/browser/context_menu_params_impl.cc
+++ b/src/libcef/browser/context_menu_params_impl.cc
@@ -5,6 +5,7 @@
 #include "libcef/browser/context_menu_params_impl.h"
 
 #include "base/logging.h"
+#include "third_party/blink/public/mojom/context_menu/context_menu.mojom.h"
 
 CefContextMenuParamsImpl::CefContextMenuParamsImpl(
     content::ContextMenuParams* value)
@@ -32,18 +33,24 @@
   CEF_VALUE_VERIFY_RETURN(false, CM_TYPEFLAG_NONE);
   const content::ContextMenuParams& params = const_value();
   int type_flags = CM_TYPEFLAG_NONE;
-  if (!params.page_url.is_empty())
+  if (!params.page_url.is_empty()) {
     type_flags |= CM_TYPEFLAG_PAGE;
-  if (!params.frame_url.is_empty())
+  }
+  if (!params.frame_url.is_empty()) {
     type_flags |= CM_TYPEFLAG_FRAME;
-  if (!params.link_url.is_empty())
+  }
+  if (!params.link_url.is_empty()) {
     type_flags |= CM_TYPEFLAG_LINK;
-  if (params.media_type != blink::ContextMenuDataMediaType::kNone)
+  }
+  if (params.media_type != blink::mojom::ContextMenuDataMediaType::kNone) {
     type_flags |= CM_TYPEFLAG_MEDIA;
-  if (!params.selection_text.empty())
+  }
+  if (!params.selection_text.empty()) {
     type_flags |= CM_TYPEFLAG_SELECTION;
-  if (params.is_editable)
+  }
+  if (params.is_editable) {
     type_flags |= CM_TYPEFLAG_EDITABLE;
+  }
   return static_cast<TypeFlags>(type_flags);
 }
 
@@ -112,16 +119,19 @@
     std::vector<CefString>& suggestions) {
   CEF_VALUE_VERIFY_RETURN(false, false);
 
-  if (!suggestions.empty())
+  if (!suggestions.empty()) {
     suggestions.clear();
+  }
 
-  if (const_value().dictionary_suggestions.empty())
+  if (const_value().dictionary_suggestions.empty()) {
     return false;
+  }
 
-  std::vector<base::string16>::const_iterator it =
+  std::vector<std::u16string>::const_iterator it =
       const_value().dictionary_suggestions.begin();
-  for (; it != const_value().dictionary_suggestions.end(); ++it)
+  for (; it != const_value().dictionary_suggestions.end(); ++it) {
     suggestions.push_back(*it);
+  }
 
   return true;
 }
@@ -146,8 +156,3 @@
   CEF_VALUE_VERIFY_RETURN(false, false);
   return !const_value().custom_items.empty();
 }
-
-bool CefContextMenuParamsImpl::IsPepperMenu() {
-  CEF_VALUE_VERIFY_RETURN(false, false);
-  return const_value().custom_context.is_pepper_menu;
-}
diff --git a/src/libcef/browser/context_menu_params_impl.h b/src/libcef/browser/context_menu_params_impl.h
index 5d28efb..782848a 100644
--- a/src/libcef/browser/context_menu_params_impl.h
+++ b/src/libcef/browser/context_menu_params_impl.h
@@ -17,6 +17,9 @@
  public:
   explicit CefContextMenuParamsImpl(content::ContextMenuParams* value);
 
+  CefContextMenuParamsImpl(const CefContextMenuParamsImpl&) = delete;
+  CefContextMenuParamsImpl& operator=(const CefContextMenuParamsImpl&) = delete;
+
   // CefContextMenuParams methods.
   int GetXCoord() override;
   int GetYCoord() override;
@@ -38,9 +41,6 @@
   bool IsSpellCheckEnabled() override;
   EditStateFlags GetEditStateFlags() override;
   bool IsCustomMenu() override;
-  bool IsPepperMenu() override;
-
-  DISALLOW_COPY_AND_ASSIGN(CefContextMenuParamsImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_CONTEXT_MENU_PARAMS_IMPL_H_
diff --git a/src/libcef/browser/devtools/devtools_controller.cc b/src/libcef/browser/devtools/devtools_controller.cc
index 9b3496e..30f5776 100644
--- a/src/libcef/browser/devtools/devtools_controller.cc
+++ b/src/libcef/browser/devtools/devtools_controller.cc
@@ -31,8 +31,9 @@
 bool CefDevToolsController::SendDevToolsMessage(
     const base::StringPiece& message) {
   CEF_REQUIRE_UIT();
-  if (!EnsureAgentHost())
+  if (!EnsureAgentHost()) {
     return false;
+  }
 
   agent_host_->DispatchProtocolMessage(
       this, base::as_bytes(base::make_span(message)));
@@ -42,27 +43,31 @@
 int CefDevToolsController::ExecuteDevToolsMethod(
     int suggested_message_id,
     const std::string& method,
-    const base::DictionaryValue* params) {
+    const base::Value::Dict* params) {
   CEF_REQUIRE_UIT();
-  if (!EnsureAgentHost())
+  if (!EnsureAgentHost()) {
     return 0;
+  }
 
   // Message IDs must always be increasing and unique.
   int message_id = suggested_message_id;
-  if (message_id < next_message_id_)
+  if (message_id < next_message_id_) {
     message_id = next_message_id_++;
-  else
+  } else {
     next_message_id_ = message_id + 1;
+  }
 
-  base::DictionaryValue message;
-  message.SetIntKey("id", message_id);
-  message.SetStringKey("method", method);
-  if (params)
-    message.SetKey("params", params->Clone());
+  base::Value::Dict message;
+  message.Set("id", message_id);
+  message.Set("method", method);
+  if (params) {
+    message.Set("params", params->Clone());
+  }
 
   std::string protocol_message;
-  if (!base::JSONWriter::Write(message, &protocol_message))
+  if (!base::JSONWriter::Write(message, &protocol_message)) {
     return 0;
+  }
 
   agent_host_->DispatchProtocolMessage(
       this, base::as_bytes(base::make_span(protocol_message)));
@@ -91,8 +96,9 @@
 void CefDevToolsController::DispatchProtocolMessage(
     content::DevToolsAgentHost* agent_host,
     base::span<const uint8_t> message) {
-  if (!observers_.might_have_observers())
+  if (observers_.empty()) {
     return;
+  }
 
   base::StringPiece str_message(reinterpret_cast<const char*>(message.data()),
                                 message.size());
diff --git a/src/libcef/browser/devtools/devtools_controller.h b/src/libcef/browser/devtools/devtools_controller.h
index a1730b7..3bed09f 100644
--- a/src/libcef/browser/devtools/devtools_controller.h
+++ b/src/libcef/browser/devtools/devtools_controller.h
@@ -41,13 +41,17 @@
 
   // |inspected_contents| will outlive this object.
   explicit CefDevToolsController(content::WebContents* inspected_contents);
+
+  CefDevToolsController(const CefDevToolsController&) = delete;
+  CefDevToolsController& operator=(const CefDevToolsController&) = delete;
+
   ~CefDevToolsController() override;
 
   // See CefBrowserHost methods of the same name for documentation.
   bool SendDevToolsMessage(const base::StringPiece& message);
   int ExecuteDevToolsMethod(int message_id,
                             const std::string& method,
-                            const base::DictionaryValue* params);
+                            const base::Value::Dict* params);
 
   // |observer| must outlive this object or be removed.
   void AddObserver(Observer* observer);
@@ -72,8 +76,6 @@
   base::ObserverList<Observer> observers_;
 
   base::WeakPtrFactory<CefDevToolsController> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefDevToolsController);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_DEVTOOLS_DEVTOOLS_CONTROLLER_H_
diff --git a/src/libcef/browser/devtools/devtools_file_manager.cc b/src/libcef/browser/devtools/devtools_file_manager.cc
index 9307824..2d8220b 100644
--- a/src/libcef/browser/devtools/devtools_file_manager.cc
+++ b/src/libcef/browser/devtools/devtools_file_manager.cc
@@ -4,19 +4,19 @@
 
 #include "libcef/browser/devtools/devtools_file_manager.h"
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 
-#include "base/bind.h"
-#include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
+#include "base/functional/bind.h"
+#include "base/functional/callback.h"
 #include "base/json/json_writer.h"
+#include "base/json/values_util.h"
 #include "base/lazy_instance.h"
 #include "base/path_service.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "base/value_conversions.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/task/thread_pool.h"
 #include "base/values.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/scoped_user_pref_update.h"
@@ -34,56 +34,57 @@
 
 void AppendToFile(const base::FilePath& path, const std::string& content) {
   DCHECK(!path.empty());
-  base::AppendToFile(path, content.c_str(), content.size());
+  base::AppendToFile(path, base::StringPiece(content));
 }
 
 }  // namespace
 
-CefDevToolsFileManager::CefDevToolsFileManager(CefBrowserHostImpl* browser_impl,
-                                               PrefService* prefs)
+CefDevToolsFileManager::CefDevToolsFileManager(
+    AlloyBrowserHostImpl* browser_impl,
+    PrefService* prefs)
     : browser_impl_(browser_impl),
       prefs_(prefs),
-      file_task_runner_(base::CreateSequencedTaskRunner(
-          {base::ThreadPool(), base::MayBlock()})),
+      file_task_runner_(
+          base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})),
       weak_factory_(this) {}
 
 void CefDevToolsFileManager::SaveToFile(const std::string& url,
                                         const std::string& content,
                                         bool save_as) {
   Save(url, content, save_as,
-       base::Bind(&CefDevToolsFileManager::FileSavedAs,
-                  weak_factory_.GetWeakPtr(), url),
-       base::Bind(&CefDevToolsFileManager::CanceledFileSaveAs,
-                  weak_factory_.GetWeakPtr(), url));
+       base::BindOnce(&CefDevToolsFileManager::FileSavedAs,
+                      weak_factory_.GetWeakPtr(), url),
+       base::BindOnce(&CefDevToolsFileManager::CanceledFileSaveAs,
+                      weak_factory_.GetWeakPtr(), url));
 }
 
 void CefDevToolsFileManager::AppendToFile(const std::string& url,
                                           const std::string& content) {
   Append(url, content,
-         base::Bind(&CefDevToolsFileManager::AppendedTo,
-                    weak_factory_.GetWeakPtr(), url));
+         base::BindOnce(&CefDevToolsFileManager::AppendedTo,
+                        weak_factory_.GetWeakPtr(), url));
 }
 
 void CefDevToolsFileManager::Save(const std::string& url,
                                   const std::string& content,
                                   bool save_as,
-                                  const SaveCallback& saveCallback,
-                                  const CancelCallback& cancelCallback) {
+                                  SaveCallback saveCallback,
+                                  CancelCallback cancelCallback) {
   auto it = saved_files_.find(url);
   if (it != saved_files_.end() && !save_as) {
-    SaveAsFileSelected(url, content, saveCallback, it->second);
+    SaveAsFileSelected(url, content, std::move(saveCallback), it->second);
     return;
   }
 
-  const base::DictionaryValue* file_map =
-      prefs_->GetDictionary(prefs::kDevToolsEditedFiles);
+  const base::Value::Dict& file_map =
+      prefs_->GetDict(prefs::kDevToolsEditedFiles);
   base::FilePath initial_path;
 
-  const base::Value* path_value;
-  if (file_map->Get(base::MD5String(url), &path_value)) {
-    // Ignore base::GetValueAsFilePath() failure since we handle empty
-    // |initial_path| below.
-    ignore_result(base::GetValueAsFilePath(*path_value, &initial_path));
+  if (const base::Value* path_value = file_map.Find(base::MD5String(url))) {
+    absl::optional<base::FilePath> path = base::ValueToFilePath(*path_value);
+    if (path) {
+      initial_path = std::move(*path);
+    }
   }
 
   if (initial_path.empty()) {
@@ -91,8 +92,9 @@
     std::string suggested_file_name =
         gurl.is_valid() ? gurl.ExtractFileName() : url;
 
-    if (suggested_file_name.length() > 64)
+    if (suggested_file_name.length() > 64) {
       suggested_file_name = suggested_file_name.substr(0, 64);
+    }
 
     if (!g_last_save_path.Pointer()->empty()) {
       initial_path = g_last_save_path.Pointer()->DirName().AppendASCII(
@@ -104,7 +106,7 @@
     }
   }
 
-  CefFileDialogRunner::FileChooserParams params;
+  blink::mojom::FileChooserParams params;
   params.mode = blink::mojom::FileChooserParams::Mode::kSave;
   if (!initial_path.empty()) {
     params.default_file_name = initial_path;
@@ -113,38 +115,37 @@
     }
   }
 
-  browser_impl_->RunFileChooser(
-      params, base::Bind(&CefDevToolsFileManager::SaveAsDialogDismissed,
-                         weak_factory_.GetWeakPtr(), url, content, saveCallback,
-                         cancelCallback));
+  browser_impl_->RunFileChooserForBrowser(
+      params,
+      base::BindOnce(&CefDevToolsFileManager::SaveAsDialogDismissed,
+                     weak_factory_.GetWeakPtr(), url, content,
+                     std::move(saveCallback), std::move(cancelCallback)));
 }
 
 void CefDevToolsFileManager::SaveAsDialogDismissed(
     const std::string& url,
     const std::string& content,
-    const SaveCallback& saveCallback,
-    const CancelCallback& cancelCallback,
-    int selected_accept_filter,
+    SaveCallback saveCallback,
+    CancelCallback cancelCallback,
     const std::vector<base::FilePath>& file_paths) {
   if (file_paths.size() == 1) {
-    SaveAsFileSelected(url, content, saveCallback, file_paths[0]);
+    SaveAsFileSelected(url, content, std::move(saveCallback), file_paths[0]);
   } else {
-    cancelCallback.Run();
+    std::move(cancelCallback).Run();
   }
 }
 
 void CefDevToolsFileManager::SaveAsFileSelected(const std::string& url,
                                                 const std::string& content,
-                                                const SaveCallback& callback,
+                                                SaveCallback callback,
                                                 const base::FilePath& path) {
   *g_last_save_path.Pointer() = path;
   saved_files_[url] = path;
 
-  DictionaryPrefUpdate update(prefs_, prefs::kDevToolsEditedFiles);
-  base::DictionaryValue* files_map = update.Get();
-  files_map->SetKey(base::MD5String(url), base::CreateFilePathValue(path));
+  ScopedDictPrefUpdate update(prefs_, prefs::kDevToolsEditedFiles);
+  update->Set(base::MD5String(url), base::FilePathToValue(path));
   std::string file_system_path = path.AsUTF8Unsafe();
-  callback.Run(file_system_path);
+  std::move(callback).Run(file_system_path);
   file_task_runner_->PostTask(FROM_HERE,
                               base::BindOnce(&::WriteToFile, path, content));
 }
@@ -165,11 +166,12 @@
 
 void CefDevToolsFileManager::Append(const std::string& url,
                                     const std::string& content,
-                                    const AppendCallback& callback) {
+                                    AppendCallback callback) {
   auto it = saved_files_.find(url);
-  if (it == saved_files_.end())
+  if (it == saved_files_.end()) {
     return;
-  callback.Run();
+  }
+  std::move(callback).Run();
   file_task_runner_->PostTask(
       FROM_HERE, base::BindOnce(&::AppendToFile, it->second, content));
 }
@@ -199,6 +201,6 @@
     }
   }
   javascript.append(");");
-  browser_impl_->web_contents()->GetMainFrame()->ExecuteJavaScript(
+  browser_impl_->web_contents()->GetPrimaryMainFrame()->ExecuteJavaScript(
       base::UTF8ToUTF16(javascript), base::NullCallback());
 }
diff --git a/src/libcef/browser/devtools/devtools_file_manager.h b/src/libcef/browser/devtools/devtools_file_manager.h
index 364f26d..08b2b83 100644
--- a/src/libcef/browser/devtools/devtools_file_manager.h
+++ b/src/libcef/browser/devtools/devtools_file_manager.h
@@ -5,8 +5,7 @@
 #ifndef CEF_LIBCEF_BROWSER_DEVTOOLS_DEVTOOLS_FILE_MANAGER_H_
 #define CEF_LIBCEF_BROWSER_DEVTOOLS_DEVTOOLS_FILE_MANAGER_H_
 
-#include "base/callback_forward.h"
-#include "base/macros.h"
+#include "base/functional/callback_forward.h"
 #include "base/memory/weak_ptr.h"
 
 #include <map>
@@ -18,7 +17,7 @@
 class Value;
 }  // namespace base
 
-class CefBrowserHostImpl;
+class AlloyBrowserHostImpl;
 class PrefService;
 
 // File management helper for DevTools.
@@ -26,7 +25,11 @@
 // chrome/browser/devtools/devtools_file_helper.cc.
 class CefDevToolsFileManager {
  public:
-  CefDevToolsFileManager(CefBrowserHostImpl* browser_impl, PrefService* prefs);
+  CefDevToolsFileManager(AlloyBrowserHostImpl* browser_impl,
+                         PrefService* prefs);
+
+  CefDevToolsFileManager(const CefDevToolsFileManager&) = delete;
+  CefDevToolsFileManager& operator=(const CefDevToolsFileManager&) = delete;
 
   void SaveToFile(const std::string& url,
                   const std::string& content,
@@ -35,31 +38,30 @@
 
  private:
   // SaveToFile implementation:
-  typedef base::Callback<void(const std::string&)> SaveCallback;
-  typedef base::Callback<void()> CancelCallback;
+  using SaveCallback = base::OnceCallback<void(const std::string&)>;
+  using CancelCallback = base::OnceCallback<void()>;
   void Save(const std::string& url,
             const std::string& content,
             bool save_as,
-            const SaveCallback& saveCallback,
-            const CancelCallback& cancelCallback);
+            SaveCallback saveCallback,
+            CancelCallback cancelCallback);
   void SaveAsDialogDismissed(const std::string& url,
                              const std::string& content,
-                             const SaveCallback& saveCallback,
-                             const CancelCallback& cancelCallback,
-                             int selected_accept_filter,
+                             SaveCallback saveCallback,
+                             CancelCallback cancelCallback,
                              const std::vector<base::FilePath>& file_paths);
   void SaveAsFileSelected(const std::string& url,
                           const std::string& content,
-                          const SaveCallback& callback,
+                          SaveCallback callback,
                           const base::FilePath& path);
   void FileSavedAs(const std::string& url, const std::string& file_system_path);
   void CanceledFileSaveAs(const std::string& url);
 
   // AppendToFile implementation:
-  typedef base::Callback<void(void)> AppendCallback;
+  using AppendCallback = base::OnceCallback<void(void)>;
   void Append(const std::string& url,
               const std::string& content,
-              const AppendCallback& callback);
+              AppendCallback callback);
   void AppendedTo(const std::string& url);
 
   void CallClientFunction(const std::string& function_name,
@@ -68,15 +70,13 @@
                           const base::Value* arg3);
 
   // Guaranteed to outlive this object.
-  CefBrowserHostImpl* browser_impl_;
+  AlloyBrowserHostImpl* browser_impl_;
   PrefService* prefs_;
 
-  typedef std::map<std::string, base::FilePath> PathsMap;
+  using PathsMap = std::map<std::string, base::FilePath>;
   PathsMap saved_files_;
   scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
   base::WeakPtrFactory<CefDevToolsFileManager> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefDevToolsFileManager);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_DEVTOOLS_DEVTOOLS_FILE_MANAGER_H_
diff --git a/src/libcef/browser/devtools/devtools_frontend.cc b/src/libcef/browser/devtools/devtools_frontend.cc
index 5c3b3ef..008cc59 100644
--- a/src/libcef/browser/devtools/devtools_frontend.cc
+++ b/src/libcef/browser/devtools/devtools_frontend.cc
@@ -10,25 +10,26 @@
 #include <utility>
 
 #include "libcef/browser/browser_context.h"
-#include "libcef/browser/content_browser_client.h"
 #include "libcef/browser/devtools/devtools_manager_delegate.h"
 #include "libcef/browser/net/devtools_scheme_handler.h"
+#include "libcef/browser/thread_util.h"
 #include "libcef/common/cef_switches.h"
+#include "libcef/common/task_runner_manager.h"
 
 #include "base/base64.h"
 #include "base/command_line.h"
 #include "base/files/file_util.h"
-#include "base/guid.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/json/string_escape.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
+#include "base/uuid.h"
 #include "base/values.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "content/public/browser/browser_context.h"
@@ -52,28 +53,34 @@
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
 #include "storage/browser/file_system/native_file_util.h"
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 #include <windows.h>
-#elif defined(OS_POSIX)
+#elif BUILDFLAG(IS_POSIX)
 #include <time.h>
 #endif
 
 namespace {
 
+// This constant should be in sync with the constant in
+// chrome/browser/devtools/devtools_ui_bindings.cc.
+constexpr size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4;
+
+constexpr int kMaxLogLineLength = 1024;
+
 static std::string GetFrontendURL() {
   return base::StringPrintf("%s://%s/devtools_app.html",
                             content::kChromeDevToolsScheme,
                             scheme::kChromeDevToolsHost);
 }
 
-std::unique_ptr<base::DictionaryValue> BuildObjectForResponse(
-    const net::HttpResponseHeaders* rh,
-    bool success,
-    int net_error) {
-  auto response = std::make_unique<base::DictionaryValue>();
+base::Value::Dict BuildObjectForResponse(const net::HttpResponseHeaders* rh,
+                                         bool success,
+                                         int net_error) {
+  base::Value::Dict response;
   int responseCode = 200;
   if (rh) {
     responseCode = rh->response_code();
@@ -81,27 +88,26 @@
     // In case of no headers, assume file:// URL and failed to load
     responseCode = 404;
   }
-  response->SetInteger("statusCode", responseCode);
-  response->SetInteger("netError", net_error);
-  response->SetString("netErrorName", net::ErrorToString(net_error));
+  response.Set("statusCode", responseCode);
+  response.Set("netError", net_error);
+  response.Set("netErrorName", net::ErrorToString(net_error));
 
-  auto headers = std::make_unique<base::DictionaryValue>();
+  base::Value::Dict headers;
   size_t iterator = 0;
   std::string name;
   std::string value;
   // TODO(caseq): this probably needs to handle duplicate header names
   // correctly by folding them.
-  while (rh && rh->EnumerateHeaderLines(&iterator, &name, &value))
-    headers->SetString(name, value);
+  while (rh && rh->EnumerateHeaderLines(&iterator, &name, &value)) {
+    headers.Set(name, value);
+  }
 
-  response->Set("headers", std::move(headers));
+  response.Set("headers", std::move(headers));
   return response;
 }
 
-const int kMaxLogLineLength = 1024;
-
 void WriteTimestamp(std::stringstream& stream) {
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   SYSTEMTIME local_time;
   GetLocalTime(&local_time);
   stream << std::setfill('0') << std::setw(2) << local_time.wMonth
@@ -109,7 +115,7 @@
          << local_time.wHour << std::setw(2) << local_time.wMinute
          << std::setw(2) << local_time.wSecond << '.' << std::setw(3)
          << local_time.wMilliseconds;
-#elif defined(OS_POSIX)
+#elif BUILDFLAG(IS_POSIX)
   timeval tv;
   gettimeofday(&tv, nullptr);
   time_t t = tv.tv_sec;
@@ -130,8 +136,9 @@
                         std::string to_log) {
   // Track if logging has failed, in which case we don't keep trying.
   static bool log_error = false;
-  if (log_error)
+  if (log_error) {
     return;
+  }
 
   if (storage::NativeFileUtil::EnsureFileExists(log_file, nullptr) !=
       base::File::FILE_OK) {
@@ -157,7 +164,7 @@
   WriteTimestamp(stream);
   stream << ": " << type_label << ": " << to_log << "\n";
   const std::string& str = stream.str();
-  if (!base::AppendToFile(log_file, str.c_str(), str.size())) {
+  if (!base::AppendToFile(log_file, base::StringPiece(str))) {
     LOG(ERROR) << "Failed to write file " << log_file.value();
     log_error = true;
   }
@@ -182,6 +189,9 @@
     loader_->DownloadAsStream(url_loader_factory, this);
   }
 
+  NetworkResourceLoader(const NetworkResourceLoader&) = delete;
+  NetworkResourceLoader& operator=(const NetworkResourceLoader&) = delete;
+
  private:
   void OnResponseStarted(const GURL& final_url,
                          const network::mojom::URLResponseHead& response_head) {
@@ -203,37 +213,32 @@
     base::Value id(stream_id_);
     base::Value encodedValue(encoded);
 
-    bindings_->CallClientFunction("DevToolsAPI.streamWrite", &id, &chunkValue,
-                                  &encodedValue);
+    bindings_->CallClientFunction("DevToolsAPI", "streamWrite", std::move(id),
+                                  std::move(chunkValue),
+                                  std::move(encodedValue));
     std::move(resume).Run();
   }
 
   void OnComplete(bool success) override {
     auto response = BuildObjectForResponse(response_headers_.get(), success,
                                            loader_->NetError());
-    bindings_->SendMessageAck(request_id_, response.get());
+    bindings_->SendMessageAck(request_id_, std::move(response));
 
     bindings_->loaders_.erase(bindings_->loaders_.find(this));
   }
 
-  void OnRetry(base::OnceClosure start_retry) override { NOTREACHED(); }
+  void OnRetry(base::OnceClosure start_retry) override { DCHECK(false); }
 
   const int stream_id_;
   CefDevToolsFrontend* const bindings_;
   std::unique_ptr<network::SimpleURLLoader> loader_;
   int request_id_;
   scoped_refptr<net::HttpResponseHeaders> response_headers_;
-
-  DISALLOW_COPY_AND_ASSIGN(NetworkResourceLoader);
 };
 
-// This constant should be in sync with
-// the constant at devtools_ui_bindings.cc.
-const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4;
-
 // static
 CefDevToolsFrontend* CefDevToolsFrontend::Show(
-    CefBrowserHostImpl* inspected_browser,
+    AlloyBrowserHostImpl* inspected_browser,
     const CefWindowInfo& windowInfo,
     CefRefPtr<CefClient> client,
     const CefBrowserSettings& settings,
@@ -247,24 +252,27 @@
     new_settings.background_color = SK_ColorWHITE;
   }
 
-  CefBrowserHostImpl::CreateParams create_params;
-  if (!inspected_browser->IsViewsHosted())
+  CefBrowserCreateParams create_params;
+  if (inspected_browser->is_views_hosted()) {
+    create_params.popup_with_views_hosted_opener = true;
+  } else {
     create_params.window_info.reset(new CefWindowInfo(windowInfo));
+  }
   create_params.client = client;
   create_params.settings = new_settings;
   create_params.devtools_opener = inspected_browser;
   create_params.request_context = inspected_browser->GetRequestContext();
   create_params.extra_info = inspected_browser->browser_info()->extra_info();
 
-  CefRefPtr<CefBrowserHostImpl> frontend_browser =
-      CefBrowserHostImpl::Create(create_params);
+  CefRefPtr<AlloyBrowserHostImpl> frontend_browser =
+      AlloyBrowserHostImpl::Create(create_params);
 
   content::WebContents* inspected_contents = inspected_browser->web_contents();
 
   // CefDevToolsFrontend will delete itself when the frontend WebContents is
   // destroyed.
   CefDevToolsFrontend* devtools_frontend = new CefDevToolsFrontend(
-      static_cast<CefBrowserHostImpl*>(frontend_browser.get()),
+      static_cast<AlloyBrowserHostImpl*>(frontend_browser.get()),
       inspected_contents, inspect_element_at,
       std::move(frontend_destroyed_callback));
 
@@ -283,20 +291,21 @@
 }
 
 void CefDevToolsFrontend::InspectElementAt(int x, int y) {
-  if (inspect_element_at_.x != x || inspect_element_at_.y != y)
+  if (inspect_element_at_.x != x || inspect_element_at_.y != y) {
     inspect_element_at_.Set(x, y);
-  if (agent_host_)
+  }
+  if (agent_host_) {
     agent_host_->InspectElement(inspected_contents_->GetFocusedFrame(), x, y);
+  }
 }
 
 void CefDevToolsFrontend::Close() {
-  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
-                 base::Bind(&CefBrowserHostImpl::CloseBrowser,
-                            frontend_browser_.get(), true));
+  CEF_POST_TASK(CEF_UIT, base::BindOnce(&AlloyBrowserHostImpl::CloseBrowser,
+                                        frontend_browser_.get(), true));
 }
 
 CefDevToolsFrontend::CefDevToolsFrontend(
-    CefBrowserHostImpl* frontend_browser,
+    AlloyBrowserHostImpl* frontend_browser,
     content::WebContents* inspected_contents,
     const CefPoint& inspect_element_at,
     base::OnceClosure frontend_destroyed_callback)
@@ -320,30 +329,34 @@
   content::RenderFrameHost* frame = navigation_handle->GetRenderFrameHost();
   if (navigation_handle->IsInMainFrame()) {
     frontend_host_ = content::DevToolsFrontendHost::Create(
-        frame,
-        base::Bind(&CefDevToolsFrontend::HandleMessageFromDevToolsFrontend,
+        frame, base::BindRepeating(
+                   &CefDevToolsFrontend::HandleMessageFromDevToolsFrontend,
                    base::Unretained(this)));
     return;
   }
 
-  std::string origin = navigation_handle->GetURL().GetOrigin().spec();
+  std::string origin =
+      navigation_handle->GetURL().DeprecatedGetOriginAsURL().spec();
   auto it = extensions_api_.find(origin);
-  if (it == extensions_api_.end())
+  if (it == extensions_api_.end()) {
     return;
-  std::string script = base::StringPrintf("%s(\"%s\")", it->second.c_str(),
-                                          base::GenerateGUID().c_str());
+  }
+  std::string script = base::StringPrintf(
+      "%s(\"%s\")", it->second.c_str(),
+      base::Uuid::GenerateRandomV4().AsLowercaseString().c_str());
   content::DevToolsFrontendHost::SetupExtensionsAPI(frame, script);
 }
 
-void CefDevToolsFrontend::DocumentAvailableInMainFrame() {
+void CefDevToolsFrontend::PrimaryMainDocumentElementAvailable() {
   // Don't call AttachClient multiple times for the same DevToolsAgentHost.
   // Otherwise it will call AgentHostClosed which closes the DevTools window.
   // This may happen in cases where the DevTools content fails to load.
   scoped_refptr<content::DevToolsAgentHost> agent_host =
       content::DevToolsAgentHost::GetOrCreateFor(inspected_contents_);
   if (agent_host != agent_host_) {
-    if (agent_host_)
+    if (agent_host_) {
       agent_host_->DetachClient(this);
+    }
     agent_host_ = agent_host;
     agent_host_->AttachClient(this);
     if (!inspect_element_at_.IsEmpty()) {
@@ -363,48 +376,56 @@
 }
 
 void CefDevToolsFrontend::HandleMessageFromDevToolsFrontend(
-    const std::string& message) {
-  std::string method;
-  base::ListValue* params = nullptr;
-  base::DictionaryValue* dict = nullptr;
-  base::Optional<base::Value> parsed_message = base::JSONReader::Read(message);
-  if (!parsed_message || !parsed_message->GetAsDictionary(&dict) ||
-      !dict->GetString("method", &method)) {
+    base::Value::Dict message) {
+  const std::string* method = message.FindString("method");
+  if (!method) {
     return;
   }
-  int request_id = 0;
-  dict->GetInteger("id", &request_id);
-  dict->GetList("params", &params);
 
-  if (method == "dispatchProtocolMessage" && params && params->GetSize() == 1) {
-    std::string protocol_message;
-    if (!agent_host_ || !params->GetString(0, &protocol_message))
+  int request_id = message.FindInt("id").value_or(0);
+  base::Value::List* params_value = message.FindList("params");
+
+  // Since we've received message by value, we can take the list.
+  base::Value::List params;
+  if (params_value) {
+    params = std::move(*params_value);
+  }
+
+  if (*method == "dispatchProtocolMessage") {
+    if (params.size() < 1) {
       return;
+    }
+    const std::string* protocol_message = params[0].GetIfString();
+    if (!agent_host_ || !protocol_message) {
+      return;
+    }
     if (ProtocolLoggingEnabled()) {
-      LogProtocolMessage(ProtocolMessageType::METHOD, protocol_message);
+      LogProtocolMessage(ProtocolMessageType::METHOD, *protocol_message);
     }
     agent_host_->DispatchProtocolMessage(
-        this, base::as_bytes(base::make_span(protocol_message)));
-  } else if (method == "loadCompleted") {
-    web_contents()->GetMainFrame()->ExecuteJavaScriptForTests(
-        base::ASCIIToUTF16("DevToolsAPI.setUseSoftMenu(true);"),
-        base::NullCallback());
-  } else if (method == "loadNetworkResource" && params->GetSize() == 3) {
-    // TODO(pfeldman): handle some of the embedder messages in content.
-    std::string url;
-    std::string headers;
-    int stream_id;
-    if (!params->GetString(0, &url) || !params->GetString(1, &headers) ||
-        !params->GetInteger(2, &stream_id)) {
+        this, base::as_bytes(base::make_span(*protocol_message)));
+  } else if (*method == "loadCompleted") {
+    web_contents()->GetPrimaryMainFrame()->ExecuteJavaScriptForTests(
+        u"DevToolsAPI.setUseSoftMenu(true);", base::NullCallback());
+  } else if (*method == "loadNetworkResource") {
+    if (params.size() < 3) {
       return;
     }
 
-    GURL gurl(url);
+    // TODO(pfeldman): handle some of the embedder messages in content.
+    const std::string* url = params[0].GetIfString();
+    const std::string* headers = params[1].GetIfString();
+    absl::optional<const int> stream_id = params[2].GetIfInt();
+    if (!url || !headers || !stream_id.has_value()) {
+      return;
+    }
+
+    GURL gurl(*url);
     if (!gurl.is_valid()) {
-      base::DictionaryValue response;
-      response.SetInteger("statusCode", 404);
-      response.SetBoolean("urlValid", false);
-      SendMessageAck(request_id, &response);
+      base::Value::Dict response;
+      response.Set("statusCode", 404);
+      response.Set("urlValid", false);
+      SendMessageAck(request_id, std::move(response));
       return;
     }
 
@@ -441,158 +462,176 @@
     // implementation. We really need to pass proper first party origin from
     // the front-end.
     resource_request->site_for_cookies = net::SiteForCookies::FromUrl(gurl);
-    resource_request->headers.AddHeadersFromString(headers);
+    resource_request->headers.AddHeadersFromString(*headers);
 
-    std::unique_ptr<network::mojom::URLLoaderFactory> file_url_loader_factory;
-    scoped_refptr<network::SharedURLLoaderFactory> network_url_loader_factory;
-    std::unique_ptr<network::mojom::URLLoaderFactory> webui_url_loader_factory;
-    network::mojom::URLLoaderFactory* url_loader_factory;
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory;
     if (gurl.SchemeIsFile()) {
-      file_url_loader_factory = content::CreateFileURLLoaderFactory(
-          base::FilePath() /* profile_path */,
-          nullptr /* shared_cors_origin_access_list */);
-      url_loader_factory = file_url_loader_factory.get();
+      mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_remote =
+          content::CreateFileURLLoaderFactory(
+              base::FilePath() /* profile_path */,
+              nullptr /* shared_cors_origin_access_list */);
+      url_loader_factory = network::SharedURLLoaderFactory::Create(
+          std::make_unique<network::WrapperPendingSharedURLLoaderFactory>(
+              std::move(pending_remote)));
     } else if (content::HasWebUIScheme(gurl)) {
-      base::DictionaryValue response;
-      response.SetInteger("statusCode", 403);
-      SendMessageAck(request_id, &response);
+      base::Value::Dict response;
+      response.Set("statusCode", 403);
+      SendMessageAck(request_id, std::move(response));
       return;
     } else {
-      auto* partition = content::BrowserContext::GetStoragePartitionForSite(
-          web_contents()->GetBrowserContext(), gurl);
-      network_url_loader_factory =
-          partition->GetURLLoaderFactoryForBrowserProcess();
-      url_loader_factory = network_url_loader_factory.get();
+      auto* partition =
+          inspected_contents_->GetPrimaryMainFrame()->GetStoragePartition();
+      url_loader_factory = partition->GetURLLoaderFactoryForBrowserProcess();
     }
 
     auto simple_url_loader = network::SimpleURLLoader::Create(
         std::move(resource_request), traffic_annotation);
     auto resource_loader = std::make_unique<NetworkResourceLoader>(
-        stream_id, this, std::move(simple_url_loader), url_loader_factory,
-        request_id);
+        *stream_id, this, std::move(simple_url_loader),
+        url_loader_factory.get(), request_id);
     loaders_.insert(std::move(resource_loader));
     return;
-  } else if (method == "getPreferences") {
+  } else if (*method == "getPreferences") {
     SendMessageAck(request_id,
-                   GetPrefs()->GetDictionary(prefs::kDevToolsPreferences));
+                   GetPrefs()->GetDict(prefs::kDevToolsPreferences).Clone());
     return;
-  } else if (method == "setPreference") {
-    std::string name;
-    std::string value;
-    if (!params->GetString(0, &name) || !params->GetString(1, &value)) {
+  } else if (*method == "setPreference") {
+    if (params.size() < 2) {
       return;
     }
-    DictionaryPrefUpdate update(GetPrefs(), prefs::kDevToolsPreferences);
-    update.Get()->SetKey(name, base::Value(value));
-  } else if (method == "removePreference") {
-    std::string name;
-    if (!params->GetString(0, &name))
+    const std::string* name = params[0].GetIfString();
+
+    // We're just setting params[1] as a value anyways, so just make sure it's
+    // the type we want, but don't worry about getting it.
+    if (!name || !params[1].is_string()) {
       return;
-    DictionaryPrefUpdate update(GetPrefs(), prefs::kDevToolsPreferences);
-    update.Get()->RemoveWithoutPathExpansion(name, nullptr);
-  } else if (method == "requestFileSystems") {
-    web_contents()->GetMainFrame()->ExecuteJavaScriptForTests(
-        base::ASCIIToUTF16("DevToolsAPI.fileSystemsLoaded([]);"),
-        base::NullCallback());
-  } else if (method == "reattach") {
-    if (!agent_host_)
+    }
+
+    ScopedDictPrefUpdate update(GetPrefs(), prefs::kDevToolsPreferences);
+    update->Set(*name, std::move(params[1]));
+  } else if (*method == "removePreference") {
+    const std::string* name = params[0].GetIfString();
+    if (!name) {
       return;
+    }
+    ScopedDictPrefUpdate update(GetPrefs(), prefs::kDevToolsPreferences);
+    update->Remove(*name);
+  } else if (*method == "requestFileSystems") {
+    web_contents()->GetPrimaryMainFrame()->ExecuteJavaScriptForTests(
+        u"DevToolsAPI.fileSystemsLoaded([]);", base::NullCallback());
+  } else if (*method == "reattach") {
+    if (!agent_host_) {
+      return;
+    }
     agent_host_->DetachClient(this);
     agent_host_->AttachClient(this);
-  } else if (method == "registerExtensionsAPI") {
-    std::string origin;
-    std::string script;
-    if (!params->GetString(0, &origin) || !params->GetString(1, &script))
-      return;
-    extensions_api_[origin + "/"] = script;
-  } else if (method == "save" && params->GetSize() == 3) {
-    std::string url;
-    std::string content;
-    bool save_as;
-    if (!params->GetString(0, &url) || !params->GetString(1, &content) ||
-        !params->GetBoolean(2, &save_as)) {
+  } else if (*method == "registerExtensionsAPI") {
+    if (params.size() < 2) {
       return;
     }
-    file_manager_.SaveToFile(url, content, save_as);
-  } else if (method == "append" && params->GetSize() == 2) {
-    std::string url;
-    std::string content;
-    if (!params->GetString(0, &url) || !params->GetString(1, &content)) {
+    const std::string* origin = params[0].GetIfString();
+    const std::string* script = params[1].GetIfString();
+    if (!origin || !script) {
       return;
     }
-    file_manager_.AppendToFile(url, content);
+    extensions_api_[*origin + "/"] = *script;
+  } else if (*method == "save") {
+    if (params.size() < 3) {
+      return;
+    }
+    const std::string* url = params[0].GetIfString();
+    const std::string* content = params[1].GetIfString();
+    absl::optional<bool> save_as = params[2].GetIfBool();
+    if (!url || !content || !save_as.has_value()) {
+      return;
+    }
+    file_manager_.SaveToFile(*url, *content, *save_as);
+  } else if (*method == "append") {
+    if (params.size() < 2) {
+      return;
+    }
+    const std::string* url = params[0].GetIfString();
+    const std::string* content = params[1].GetIfString();
+    if (!url || !content) {
+      return;
+    }
+    file_manager_.AppendToFile(*url, *content);
   } else {
     return;
   }
 
-  if (request_id)
-    SendMessageAck(request_id, nullptr);
+  if (request_id) {
+    SendMessageAck(request_id, base::Value::Dict());
+  }
 }
 
 void CefDevToolsFrontend::DispatchProtocolMessage(
     content::DevToolsAgentHost* agent_host,
     base::span<const uint8_t> message) {
+  if (!frontend_browser_->GetWebContents() ||
+      frontend_browser_->GetWebContents()->IsBeingDestroyed()) {
+    return;
+  }
+
   base::StringPiece str_message(reinterpret_cast<const char*>(message.data()),
                                 message.size());
   if (ProtocolLoggingEnabled()) {
     // Quick check to avoid parsing the JSON object. Events begin with a
     // "method" value whereas method results begin with an "id" value.
-    LogProtocolMessage(str_message.starts_with("{\"method\":")
+    LogProtocolMessage(base::StartsWith(str_message, "{\"method\":")
                            ? ProtocolMessageType::EVENT
                            : ProtocolMessageType::RESULT,
                        str_message);
   }
-  if (str_message.length() < kMaxMessageChunkSize) {
-    std::string param;
-    base::EscapeJSONString(str_message, true, &param);
-    std::string code = "DevToolsAPI.dispatchMessage(" + param + ");";
-    base::string16 javascript = base::UTF8ToUTF16(code);
-    web_contents()->GetMainFrame()->ExecuteJavaScriptForTests(
-        javascript, base::NullCallback());
-    return;
-  }
 
-  size_t total_size = str_message.length();
-  for (size_t pos = 0; pos < str_message.length();
-       pos += kMaxMessageChunkSize) {
-    std::string param;
-    base::EscapeJSONString(str_message.substr(pos, kMaxMessageChunkSize), true,
-                           &param);
-    std::string code = "DevToolsAPI.dispatchMessageChunk(" + param + "," +
-                       std::to_string(pos ? 0 : total_size) + ");";
-    base::string16 javascript = base::UTF8ToUTF16(code);
-    web_contents()->GetMainFrame()->ExecuteJavaScriptForTests(
-        javascript, base::NullCallback());
+  if (str_message.length() < kMaxMessageChunkSize) {
+    CallClientFunction("DevToolsAPI", "dispatchMessage",
+                       base::Value(std::string(str_message)));
+  } else {
+    size_t total_size = str_message.length();
+    for (size_t pos = 0; pos < str_message.length();
+         pos += kMaxMessageChunkSize) {
+      base::StringPiece str_message_chunk =
+          str_message.substr(pos, kMaxMessageChunkSize);
+
+      CallClientFunction(
+          "DevToolsAPI", "dispatchMessageChunk",
+          base::Value(std::string(str_message_chunk)),
+          base::Value(base::NumberToString(pos ? 0 : total_size)));
+    }
   }
 }
 
-void CefDevToolsFrontend::CallClientFunction(const std::string& function_name,
-                                             const base::Value* arg1,
-                                             const base::Value* arg2,
-                                             const base::Value* arg3) {
-  std::string javascript = function_name + "(";
-  if (arg1) {
-    std::string json;
-    base::JSONWriter::Write(*arg1, &json);
-    javascript.append(json);
-    if (arg2) {
-      base::JSONWriter::Write(*arg2, &json);
-      javascript.append(", ").append(json);
-      if (arg3) {
-        base::JSONWriter::Write(*arg3, &json);
-        javascript.append(", ").append(json);
+void CefDevToolsFrontend::CallClientFunction(
+    const std::string& object_name,
+    const std::string& method_name,
+    base::Value arg1,
+    base::Value arg2,
+    base::Value arg3,
+    base::OnceCallback<void(base::Value)> cb) {
+  std::string javascript;
+
+  web_contents()->GetPrimaryMainFrame()->AllowInjectingJavaScript();
+
+  base::Value::List arguments;
+  if (!arg1.is_none()) {
+    arguments.Append(std::move(arg1));
+    if (!arg2.is_none()) {
+      arguments.Append(std::move(arg2));
+      if (!arg3.is_none()) {
+        arguments.Append(std::move(arg3));
       }
     }
   }
-  javascript.append(");");
-  web_contents()->GetMainFrame()->ExecuteJavaScriptForTests(
-      base::UTF8ToUTF16(javascript), base::NullCallback());
+  web_contents()->GetPrimaryMainFrame()->ExecuteJavaScriptMethod(
+      base::ASCIIToUTF16(object_name), base::ASCIIToUTF16(method_name),
+      std::move(arguments), std::move(cb));
 }
 
 void CefDevToolsFrontend::SendMessageAck(int request_id,
-                                         const base::Value* arg) {
-  base::Value id_value(request_id);
-  CallClientFunction("DevToolsAPI.embedderMessageAck", &id_value, arg, nullptr);
+                                         base::Value::Dict arg) {
+  CallClientFunction("DevToolsAPI", "embedderMessageAck",
+                     base::Value(request_id), base::Value(std::move(arg)));
 }
 
 bool CefDevToolsFrontend::ProtocolLoggingEnabled() const {
@@ -603,10 +642,10 @@
                                              const base::StringPiece& message) {
   DCHECK(ProtocolLoggingEnabled());
 
-  std::string to_log = message.substr(0, kMaxLogLineLength).as_string();
+  std::string to_log(message.substr(0, kMaxLogLineLength));
 
   // Execute in an ordered context that allows blocking.
-  auto task_runner = CefContentBrowserClient::Get()->background_task_runner();
+  auto task_runner = CefTaskRunnerManager::Get()->GetBackgroundTaskRunner();
   task_runner->PostTask(
       FROM_HERE, base::BindOnce(::LogProtocolMessage, protocol_log_file_, type,
                                 std::move(to_log)));
@@ -620,7 +659,8 @@
 }
 
 PrefService* CefDevToolsFrontend::GetPrefs() const {
-  return static_cast<CefBrowserContext*>(
+  return CefBrowserContext::FromBrowserContext(
              frontend_browser_->web_contents()->GetBrowserContext())
+      ->AsProfile()
       ->GetPrefs();
 }
diff --git a/src/libcef/browser/devtools/devtools_frontend.h b/src/libcef/browser/devtools/devtools_frontend.h
index 90e2def..36af6f1 100644
--- a/src/libcef/browser/devtools/devtools_frontend.h
+++ b/src/libcef/browser/devtools/devtools_frontend.h
@@ -7,12 +7,10 @@
 
 #include <memory>
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 #include "libcef/browser/devtools/devtools_file_manager.h"
 
-#include "base/compiler_specific.h"
 #include "base/files/file_path.h"
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/values.h"
@@ -41,8 +39,11 @@
 class CefDevToolsFrontend : public content::WebContentsObserver,
                             public content::DevToolsAgentHostClient {
  public:
+  CefDevToolsFrontend(const CefDevToolsFrontend&) = delete;
+  CefDevToolsFrontend& operator=(const CefDevToolsFrontend&) = delete;
+
   static CefDevToolsFrontend* Show(
-      CefBrowserHostImpl* inspected_browser,
+      AlloyBrowserHostImpl* inspected_browser,
       const CefWindowInfo& windowInfo,
       CefRefPtr<CefClient> client,
       const CefBrowserSettings& settings,
@@ -54,13 +55,16 @@
   void InspectElementAt(int x, int y);
   void Close();
 
-  void CallClientFunction(const std::string& function_name,
-                          const base::Value* arg1,
-                          const base::Value* arg2,
-                          const base::Value* arg3);
+  void CallClientFunction(
+      const std::string& object_name,
+      const std::string& method_name,
+      const base::Value arg1 = {},
+      const base::Value arg2 = {},
+      const base::Value arg3 = {},
+      base::OnceCallback<void(base::Value)> cb = base::NullCallback());
 
  private:
-  CefDevToolsFrontend(CefBrowserHostImpl* frontend_browser,
+  CefDevToolsFrontend(AlloyBrowserHostImpl* frontend_browser,
                       content::WebContents* inspected_contents,
                       const CefPoint& inspect_element_at,
                       base::OnceClosure destroyed_callback);
@@ -70,16 +74,16 @@
   void AgentHostClosed(content::DevToolsAgentHost* agent_host) override;
   void DispatchProtocolMessage(content::DevToolsAgentHost* agent_host,
                                base::span<const uint8_t> message) override;
-  void HandleMessageFromDevToolsFrontend(const std::string& message);
+  void HandleMessageFromDevToolsFrontend(base::Value::Dict message);
 
  private:
   // WebContentsObserver overrides
   void ReadyToCommitNavigation(
       content::NavigationHandle* navigation_handle) override;
-  void DocumentAvailableInMainFrame() override;
+  void PrimaryMainDocumentElementAvailable() override;
   void WebContentsDestroyed() override;
 
-  void SendMessageAck(int request_id, const base::Value* arg1);
+  void SendMessageAck(int request_id, base::Value::Dict arg);
 
   bool ProtocolLoggingEnabled() const;
   void LogProtocolMessage(ProtocolMessageType type,
@@ -87,7 +91,7 @@
 
   PrefService* GetPrefs() const;
 
-  CefRefPtr<CefBrowserHostImpl> frontend_browser_;
+  CefRefPtr<AlloyBrowserHostImpl> frontend_browser_;
   content::WebContents* inspected_contents_;
   scoped_refptr<content::DevToolsAgentHost> agent_host_;
   CefPoint inspect_element_at_;
@@ -105,8 +109,6 @@
   const base::FilePath protocol_log_file_;
 
   base::WeakPtrFactory<CefDevToolsFrontend> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefDevToolsFrontend);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_DEVTOOLS_DEVTOOLS_FRONTEND_H_
diff --git a/src/libcef/browser/devtools/devtools_manager.cc b/src/libcef/browser/devtools/devtools_manager.cc
index c93b274..170f609 100644
--- a/src/libcef/browser/devtools/devtools_manager.cc
+++ b/src/libcef/browser/devtools/devtools_manager.cc
@@ -6,6 +6,7 @@
 
 #include "libcef/browser/devtools/devtools_controller.h"
 #include "libcef/browser/devtools/devtools_frontend.h"
+#include "libcef/features/runtime.h"
 
 #include "content/public/browser/web_contents.h"
 
@@ -21,17 +22,22 @@
     DCHECK(observer_);
   }
 
+  CefDevToolsRegistrationImpl(const CefDevToolsRegistrationImpl&) = delete;
+  CefDevToolsRegistrationImpl& operator=(const CefDevToolsRegistrationImpl&) =
+      delete;
+
   ~CefDevToolsRegistrationImpl() override {
     CEF_REQUIRE_UIT();
 
     // May be null if OnDevToolsControllerDestroyed was called.
-    if (!controller_)
+    if (!controller_) {
       return;
+    }
 
     controller_->RemoveObserver(this);
   }
 
-  void Initialize(CefBrowserHostImpl* browser,
+  void Initialize(CefBrowserHostBase* browser,
                   base::WeakPtr<CefDevToolsController> controller) {
     CEF_REQUIRE_UIT();
     DCHECK(browser && controller);
@@ -61,7 +67,7 @@
   void OnDevToolsEvent(const base::StringPiece& method,
                        const base::StringPiece& params) override {
     CEF_REQUIRE_UIT();
-    observer_->OnDevToolsEvent(browser_, method.as_string(), params.data(),
+    observer_->OnDevToolsEvent(browser_, std::string(method), params.data(),
                                params.size());
   }
 
@@ -83,16 +89,15 @@
 
   CefRefPtr<CefDevToolsMessageObserver> observer_;
 
-  CefBrowserHostImpl* browser_ = nullptr;
+  CefBrowserHostBase* browser_ = nullptr;
   base::WeakPtr<CefDevToolsController> controller_;
 
   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefDevToolsRegistrationImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefDevToolsRegistrationImpl);
 };
 
 }  // namespace
 
-CefDevToolsManager::CefDevToolsManager(CefBrowserHostImpl* inspected_browser)
+CefDevToolsManager::CefDevToolsManager(CefBrowserHostBase* inspected_browser)
     : inspected_browser_(inspected_browser), weak_ptr_factory_(this) {
   CEF_REQUIRE_UIT();
 }
@@ -115,16 +120,22 @@
     return;
   }
 
-  devtools_frontend_ = CefDevToolsFrontend::Show(
-      inspected_browser_, windowInfo, client, settings, inspect_element_at,
-      base::BindOnce(&CefDevToolsManager::OnFrontEndDestroyed,
-                     weak_ptr_factory_.GetWeakPtr()));
+  if (cef::IsChromeRuntimeEnabled()) {
+    NOTIMPLEMENTED();
+  } else {
+    auto alloy_browser = static_cast<AlloyBrowserHostImpl*>(inspected_browser_);
+    devtools_frontend_ = CefDevToolsFrontend::Show(
+        alloy_browser, windowInfo, client, settings, inspect_element_at,
+        base::BindOnce(&CefDevToolsManager::OnFrontEndDestroyed,
+                       weak_ptr_factory_.GetWeakPtr()));
+  }
 }
 
 void CefDevToolsManager::CloseDevTools() {
   CEF_REQUIRE_UIT();
-  if (!devtools_frontend_)
+  if (!devtools_frontend_) {
     return;
+  }
   devtools_frontend_->Close();
 }
 
@@ -136,11 +147,13 @@
 bool CefDevToolsManager::SendDevToolsMessage(const void* message,
                                              size_t message_size) {
   CEF_REQUIRE_UIT();
-  if (!message || message_size == 0)
+  if (!message || message_size == 0) {
     return false;
+  }
 
-  if (!EnsureController())
+  if (!EnsureController()) {
     return false;
+  }
 
   return devtools_controller_->SendDevToolsMessage(
       base::StringPiece(static_cast<const char*>(message), message_size));
@@ -151,18 +164,20 @@
     const CefString& method,
     CefRefPtr<CefDictionaryValue> params) {
   CEF_REQUIRE_UIT();
-  if (method.empty())
+  if (method.empty()) {
     return 0;
+  }
 
-  if (!EnsureController())
+  if (!EnsureController()) {
     return 0;
+  }
 
   if (params && params->IsValid()) {
     CefDictionaryValueImpl* impl =
         static_cast<CefDictionaryValueImpl*>(params.get());
     CefValueController::AutoLock lock_scope(impl->controller());
-    return devtools_controller_->ExecuteDevToolsMethod(message_id, method,
-                                                       impl->GetValueUnsafe());
+    return devtools_controller_->ExecuteDevToolsMethod(
+        message_id, method, impl->GetValueUnsafe()->GetIfDict());
   } else {
     return devtools_controller_->ExecuteDevToolsMethod(message_id, method,
                                                        nullptr);
@@ -180,8 +195,9 @@
     CefRefPtr<CefRegistration> registration) {
   CEF_REQUIRE_UIT();
 
-  if (!EnsureController())
+  if (!EnsureController()) {
     return;
+  }
 
   static_cast<CefDevToolsRegistrationImpl*>(registration.get())
       ->Initialize(inspected_browser_, devtools_controller_->GetWeakPtr());
@@ -193,8 +209,8 @@
 
 bool CefDevToolsManager::EnsureController() {
   if (!devtools_controller_) {
-    devtools_controller_.reset(
-        new CefDevToolsController(inspected_browser_->web_contents()));
+    devtools_controller_.reset(new CefDevToolsController(
+        inspected_browser_->contents_delegate()->web_contents()));
   }
   return true;
 }
diff --git a/src/libcef/browser/devtools/devtools_manager.h b/src/libcef/browser/devtools/devtools_manager.h
index ae1d5fe..d390e49 100644
--- a/src/libcef/browser/devtools/devtools_manager.h
+++ b/src/libcef/browser/devtools/devtools_manager.h
@@ -10,7 +10,7 @@
 
 #include "base/memory/weak_ptr.h"
 
-class CefBrowserHostImpl;
+class CefBrowserHostBase;
 class CefDevToolsController;
 class CefDevToolsFrontend;
 
@@ -23,7 +23,11 @@
 class CefDevToolsManager {
  public:
   // |inspected_browser| will outlive this object.
-  explicit CefDevToolsManager(CefBrowserHostImpl* inspected_browser);
+  explicit CefDevToolsManager(CefBrowserHostBase* inspected_browser);
+
+  CefDevToolsManager(const CefDevToolsManager&) = delete;
+  CefDevToolsManager& operator=(const CefDevToolsManager&) = delete;
+
   ~CefDevToolsManager();
 
   // See CefBrowserHost methods of the same name for documentation.
@@ -52,7 +56,7 @@
 
   bool EnsureController();
 
-  CefBrowserHostImpl* const inspected_browser_;
+  CefBrowserHostBase* const inspected_browser_;
 
   // CefDevToolsFrontend will delete itself when the frontend WebContents is
   // destroyed.
@@ -62,8 +66,6 @@
   std::unique_ptr<CefDevToolsController> devtools_controller_;
 
   base::WeakPtrFactory<CefDevToolsManager> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefDevToolsManager);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_DEVTOOLS_DEVTOOLS_MANAGER_H_
diff --git a/src/libcef/browser/devtools/devtools_manager_delegate.cc b/src/libcef/browser/devtools/devtools_manager_delegate.cc
index 41fa033..8623079 100644
--- a/src/libcef/browser/devtools/devtools_manager_delegate.cc
+++ b/src/libcef/browser/devtools/devtools_manager_delegate.cc
@@ -8,13 +8,10 @@
 
 #include <vector>
 
-#include "libcef/browser/browser_host_impl.h"
-
 #include "base/atomicops.h"
-#include "base/bind.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
-#include "base/macros.h"
+#include "base/functional/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
@@ -46,13 +43,18 @@
   TCPServerSocketFactory(const std::string& address, uint16_t port)
       : address_(address), port_(port) {}
 
+  TCPServerSocketFactory(const TCPServerSocketFactory&) = delete;
+  TCPServerSocketFactory& operator=(const TCPServerSocketFactory&) = delete;
+
  private:
   // content::DevToolsSocketFactory.
   std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
     std::unique_ptr<net::ServerSocket> socket(
         new net::TCPServerSocket(nullptr, net::NetLogSource()));
-    if (socket->ListenWithAddressAndPort(address_, port_, kBackLog) != net::OK)
+    if (socket->ListenWithAddressAndPort(address_, port_, kBackLog) !=
+        net::OK) {
       return std::unique_ptr<net::ServerSocket>();
+    }
     return socket;
   }
 
@@ -63,8 +65,6 @@
 
   std::string address_;
   uint16_t port_;
-
-  DISALLOW_COPY_AND_ASSIGN(TCPServerSocketFactory);
 };
 
 std::unique_ptr<content::DevToolsSocketFactory> CreateSocketFactory() {
@@ -87,8 +87,9 @@
       DLOG(WARNING) << "Invalid http debugger port number " << temp_port;
     }
   }
-  if (port == 0)
+  if (port == 0) {
     return nullptr;
+  }
   return std::unique_ptr<content::DevToolsSocketFactory>(
       new TCPServerSocketFactory("127.0.0.1", port));
 }
@@ -102,15 +103,18 @@
     content::BrowserContext* browser_context) {
   std::unique_ptr<content::DevToolsSocketFactory> socket_factory =
       CreateSocketFactory();
-  if (!socket_factory)
+  if (!socket_factory) {
     return;
+  }
   content::DevToolsAgentHost::StartRemoteDebuggingServer(
       std::move(socket_factory), browser_context->GetPath(), base::FilePath());
 
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
-  if (command_line.HasSwitch(switches::kRemoteDebuggingPipe))
-    content::DevToolsAgentHost::StartRemoteDebuggingPipeHandler();
+  if (command_line.HasSwitch(switches::kRemoteDebuggingPipe)) {
+    content::DevToolsAgentHost::StartRemoteDebuggingPipeHandler(
+        base::OnceClosure());
+  }
 }
 
 // static
@@ -124,7 +128,9 @@
 CefDevToolsManagerDelegate::~CefDevToolsManagerDelegate() {}
 
 scoped_refptr<content::DevToolsAgentHost>
-CefDevToolsManagerDelegate::CreateNewTarget(const GURL& url) {
+CefDevToolsManagerDelegate::CreateNewTarget(
+    const GURL& url,
+    content::DevToolsManagerDelegate::TargetType target_type) {
   // This is reached when the user selects "Open link in new tab" from the
   // DevTools interface.
   // TODO(cef): Consider exposing new API to support this.
@@ -132,9 +138,8 @@
 }
 
 std::string CefDevToolsManagerDelegate::GetDiscoveryPageHTML() {
-  return ui::ResourceBundle::GetSharedInstance()
-      .GetRawDataResource(IDR_CEF_DEVTOOLS_DISCOVERY_PAGE)
-      .as_string();
+  return ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
+      IDR_CEF_DEVTOOLS_DISCOVERY_PAGE);
 }
 
 bool CefDevToolsManagerDelegate::HasBundledFrontendResources() {
diff --git a/src/libcef/browser/devtools/devtools_manager_delegate.h b/src/libcef/browser/devtools/devtools_manager_delegate.h
index 7e65fb2..bc408d9 100644
--- a/src/libcef/browser/devtools/devtools_manager_delegate.h
+++ b/src/libcef/browser/devtools/devtools_manager_delegate.h
@@ -5,8 +5,6 @@
 #ifndef CEF_LIBCEF_BROWSER_DEVTOOLS_DEVTOOLS_MANAGER_DELEGATE_H_
 #define CEF_LIBCEF_BROWSER_DEVTOOLS_DEVTOOLS_MANAGER_DELEGATE_H_
 
-#include "base/compiler_specific.h"
-#include "base/macros.h"
 #include "content/public/browser/devtools_manager_delegate.h"
 
 namespace content {
@@ -19,16 +17,19 @@
   static void StopHttpHandler();
 
   CefDevToolsManagerDelegate();
+
+  CefDevToolsManagerDelegate(const CefDevToolsManagerDelegate&) = delete;
+  CefDevToolsManagerDelegate& operator=(const CefDevToolsManagerDelegate&) =
+      delete;
+
   ~CefDevToolsManagerDelegate() override;
 
   // DevToolsManagerDelegate implementation.
   scoped_refptr<content::DevToolsAgentHost> CreateNewTarget(
-      const GURL& url) override;
+      const GURL& url,
+      content::DevToolsManagerDelegate::TargetType target_type) override;
   std::string GetDiscoveryPageHTML() override;
   bool HasBundledFrontendResources() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefDevToolsManagerDelegate);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_DEVTOOLS_DEVTOOLS_MANAGER_DELEGATE_H_
diff --git a/src/libcef/browser/devtools/devtools_util.cc b/src/libcef/browser/devtools/devtools_util.cc
index c0200cf..1ba53b1 100644
--- a/src/libcef/browser/devtools/devtools_util.cc
+++ b/src/libcef/browser/devtools/devtools_util.cc
@@ -5,6 +5,7 @@
 #include "libcef/browser/devtools/devtools_util.h"
 
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
 
 namespace devtools_util {
 
@@ -24,16 +25,19 @@
   static const char kMethodEnd[] = "\"";
   static const char kParamsStart[] = ",\"params\":";
 
-  if (!message.starts_with(kMethodStart))
+  if (!base::StartsWith(message, kMethodStart)) {
     return false;
+  }
 
   const size_t method_start = sizeof(kMethodStart) - 1;
   const size_t method_end = message.find(kMethodEnd, method_start);
-  if (method_end < 0U)
+  if (method_end == base::StringPiece::npos) {
     return false;
+  }
   method = message.substr(method_start, method_end - method_start);
-  if (method.empty())
+  if (method.empty()) {
     return false;
+  }
 
   size_t remainder_start = method_end + sizeof(kMethodEnd) - 1;
   if (remainder_start == message.size() - 1) {
@@ -41,7 +45,7 @@
     params = base::StringPiece();
   } else {
     const base::StringPiece& remainder = message.substr(remainder_start);
-    if (remainder.starts_with(kParamsStart)) {
+    if (base::StartsWith(remainder, kParamsStart)) {
       // Stop immediately before the message closing bracket.
       remainder_start += sizeof(kParamsStart) - 1;
       params =
@@ -51,8 +55,9 @@
       return false;
     }
 
-    if (!IsValidDictionary(params, /*allow_empty=*/true))
+    if (!IsValidDictionary(params, /*allow_empty=*/true)) {
       return false;
+    }
   }
 
   return true;
@@ -71,26 +76,29 @@
   static const char kResultStart[] = "\"result\":";
   static const char kErrorStart[] = "\"error\":";
 
-  if (!message.starts_with(kIdStart))
+  if (!base::StartsWith(message, kIdStart)) {
     return false;
+  }
 
   const size_t id_start = sizeof(kIdStart) - 1;
   const size_t id_end = message.find(kIdEnd, id_start);
-  if (id_end < 0U)
+  if (id_end == base::StringPiece::npos) {
     return false;
+  }
   const base::StringPiece& id_str = message.substr(id_start, id_end - id_start);
-  if (id_str.empty() || !base::StringToInt(id_str, &message_id))
+  if (id_str.empty() || !base::StringToInt(id_str, &message_id)) {
     return false;
+  }
 
   size_t remainder_start = id_end + sizeof(kIdEnd) - 1;
   const base::StringPiece& remainder = message.substr(remainder_start);
-  if (remainder.starts_with(kResultStart)) {
+  if (base::StartsWith(remainder, kResultStart)) {
     // Stop immediately before the message closing bracket.
     remainder_start += sizeof(kResultStart) - 1;
     result =
         message.substr(remainder_start, message.size() - 1 - remainder_start);
     success = true;
-  } else if (remainder.starts_with(kErrorStart)) {
+  } else if (base::StartsWith(remainder, kErrorStart)) {
     // Stop immediately before the message closing bracket.
     remainder_start += sizeof(kErrorStart) - 1;
     result =
@@ -101,8 +109,9 @@
     return false;
   }
 
-  if (!IsValidDictionary(result, /*allow_empty=*/true))
+  if (!IsValidDictionary(result, /*allow_empty=*/true)) {
     return false;
+  }
 
   return true;
 }
@@ -115,8 +124,9 @@
 }
 
 bool ProtocolParser::Initialize(const base::StringPiece& message) {
-  if (status_ != UNINITIALIZED)
+  if (status_ != UNINITIALIZED) {
     return false;
+  }
 
   if (ParseEvent(message, method_, params_)) {
     status_ = EVENT;
diff --git a/src/libcef/browser/devtools/devtools_util_unittest.cc b/src/libcef/browser/devtools/devtools_util_unittest.cc
index 0175aa0..ec41ede 100644
--- a/src/libcef/browser/devtools/devtools_util_unittest.cc
+++ b/src/libcef/browser/devtools/devtools_util_unittest.cc
@@ -83,7 +83,7 @@
   EXPECT_TRUE(parser.Initialize(message));
   EXPECT_TRUE(parser.IsInitialized());
   EXPECT_TRUE(parser.IsEvent());
-  EXPECT_STREQ("Test.myMethod", parser.method_.as_string().data());
+  EXPECT_EQ("Test.myMethod", parser.method_);
   EXPECT_TRUE(parser.params_.empty());
 
   parser.Reset();
@@ -94,8 +94,8 @@
   EXPECT_TRUE(parser.Initialize(message));
   EXPECT_TRUE(parser.IsInitialized());
   EXPECT_TRUE(parser.IsEvent());
-  EXPECT_STREQ("Test.myMethod2", parser.method_.as_string().data());
-  EXPECT_STREQ("{}", parser.params_.as_string().data());
+  EXPECT_EQ("Test.myMethod2", parser.method_);
+  EXPECT_EQ("{}", parser.params_);
 
   parser.Reset();
   EXPECT_FALSE(parser.IsInitialized());
@@ -105,8 +105,8 @@
   EXPECT_TRUE(parser.Initialize(message));
   EXPECT_TRUE(parser.IsInitialized());
   EXPECT_TRUE(parser.IsEvent());
-  EXPECT_STREQ("Test.myMethod3", parser.method_.as_string().data());
-  EXPECT_STREQ("{\"foo\":\"bar\"}", parser.params_.as_string().data());
+  EXPECT_EQ("Test.myMethod3", parser.method_);
+  EXPECT_EQ("{\"foo\":\"bar\"}", parser.params_);
 }
 
 TEST(DevToolsUtil, ProtocolParser_Initialize_IsFailure_ResultMalformed) {
@@ -162,7 +162,7 @@
   EXPECT_TRUE(parser.IsResult());
   EXPECT_EQ(1, parser.message_id_);
   EXPECT_TRUE(parser.success_);
-  EXPECT_STREQ("{}", parser.params_.as_string().data());
+  EXPECT_EQ("{}", parser.params_);
 
   parser.Reset();
   EXPECT_FALSE(parser.IsInitialized());
@@ -174,7 +174,7 @@
   EXPECT_TRUE(parser.IsResult());
   EXPECT_EQ(2, parser.message_id_);
   EXPECT_TRUE(parser.success_);
-  EXPECT_STREQ("{\"foo\":\"bar\"}", parser.params_.as_string().data());
+  EXPECT_EQ("{\"foo\":\"bar\"}", parser.params_);
 }
 
 TEST(DevToolsUtil, ProtocolParser_Initialize_IsResult_Error) {
@@ -188,7 +188,7 @@
   EXPECT_TRUE(parser.IsResult());
   EXPECT_EQ(1, parser.message_id_);
   EXPECT_FALSE(parser.success_);
-  EXPECT_STREQ("{}", parser.params_.as_string().data());
+  EXPECT_EQ("{}", parser.params_);
 
   parser.Reset();
   EXPECT_FALSE(parser.IsInitialized());
@@ -200,5 +200,21 @@
   EXPECT_TRUE(parser.IsResult());
   EXPECT_EQ(2, parser.message_id_);
   EXPECT_FALSE(parser.success_);
-  EXPECT_STREQ("{\"foo\":\"bar\"}", parser.params_.as_string().data());
+  EXPECT_EQ("{\"foo\":\"bar\"}", parser.params_);
+}
+
+TEST(DevToolsUtil, ProtocolParser_Can_Handle_MissingQuote) {
+  ProtocolParser parser;
+
+  const auto message = "{\"method\":\"Test.myMethod}";
+  EXPECT_TRUE(parser.Initialize(message));
+  EXPECT_TRUE(parser.IsFailure());
+}
+
+TEST(DevToolsUtil, ProtocolParser_Can_Handle_MissingComma) {
+  ProtocolParser parser;
+
+  const auto message = "{\"id\":1\"error\":{}}";
+  EXPECT_TRUE(parser.Initialize(message));
+  EXPECT_TRUE(parser.IsFailure());
 }
diff --git a/src/libcef/browser/download_item_impl.cc b/src/libcef/browser/download_item_impl.cc
index bffb74e..08e74af 100644
--- a/src/libcef/browser/download_item_impl.cc
+++ b/src/libcef/browser/download_item_impl.cc
@@ -39,7 +39,18 @@
   return const_value().GetState() == download::DownloadItem::CANCELLED;
 }
 
-int64 CefDownloadItemImpl::GetCurrentSpeed() {
+bool CefDownloadItemImpl::IsInterrupted() {
+  CEF_VALUE_VERIFY_RETURN(false, false);
+  return const_value().GetState() == download::DownloadItem::INTERRUPTED;
+}
+
+cef_download_interrupt_reason_t CefDownloadItemImpl::GetInterruptReason() {
+  CEF_VALUE_VERIFY_RETURN(false, CEF_DOWNLOAD_INTERRUPT_REASON_NONE);
+  return static_cast<cef_download_interrupt_reason_t>(
+      const_value().GetLastReason());
+}
+
+int64_t CefDownloadItemImpl::GetCurrentSpeed() {
   CEF_VALUE_VERIFY_RETURN(false, 0);
   return const_value().CurrentSpeed();
 }
@@ -49,28 +60,24 @@
   return const_value().PercentComplete();
 }
 
-int64 CefDownloadItemImpl::GetTotalBytes() {
+int64_t CefDownloadItemImpl::GetTotalBytes() {
   CEF_VALUE_VERIFY_RETURN(false, 0);
   return const_value().GetTotalBytes();
 }
 
-int64 CefDownloadItemImpl::GetReceivedBytes() {
+int64_t CefDownloadItemImpl::GetReceivedBytes() {
   CEF_VALUE_VERIFY_RETURN(false, 0);
   return const_value().GetReceivedBytes();
 }
 
-CefTime CefDownloadItemImpl::GetStartTime() {
-  CefTime time;
-  CEF_VALUE_VERIFY_RETURN(false, time);
-  cef_time_from_basetime(const_value().GetStartTime(), time);
-  return time;
+CefBaseTime CefDownloadItemImpl::GetStartTime() {
+  CEF_VALUE_VERIFY_RETURN(false, CefBaseTime());
+  return const_value().GetStartTime();
 }
 
-CefTime CefDownloadItemImpl::GetEndTime() {
-  CefTime time;
-  CEF_VALUE_VERIFY_RETURN(false, time);
-  cef_time_from_basetime(const_value().GetEndTime(), time);
-  return time;
+CefBaseTime CefDownloadItemImpl::GetEndTime() {
+  CEF_VALUE_VERIFY_RETURN(false, CefBaseTime());
+  return const_value().GetEndTime();
 }
 
 CefString CefDownloadItemImpl::GetFullPath() {
@@ -78,7 +85,7 @@
   return const_value().GetFullPath().value();
 }
 
-uint32 CefDownloadItemImpl::GetId() {
+uint32_t CefDownloadItemImpl::GetId() {
   CEF_VALUE_VERIFY_RETURN(false, 0);
   return const_value().GetId();
 }
diff --git a/src/libcef/browser/download_item_impl.h b/src/libcef/browser/download_item_impl.h
index ab7f4de..2311401 100644
--- a/src/libcef/browser/download_item_impl.h
+++ b/src/libcef/browser/download_item_impl.h
@@ -19,27 +19,29 @@
  public:
   explicit CefDownloadItemImpl(download::DownloadItem* value);
 
+  CefDownloadItemImpl(const CefDownloadItemImpl&) = delete;
+  CefDownloadItemImpl& operator=(const CefDownloadItemImpl&) = delete;
+
   // CefDownloadItem methods.
   bool IsValid() override;
   bool IsInProgress() override;
   bool IsComplete() override;
   bool IsCanceled() override;
-  int64 GetCurrentSpeed() override;
+  bool IsInterrupted() override;
+  cef_download_interrupt_reason_t GetInterruptReason() override;
+  int64_t GetCurrentSpeed() override;
   int GetPercentComplete() override;
-  int64 GetTotalBytes() override;
-  int64 GetReceivedBytes() override;
-  CefTime GetStartTime() override;
-  CefTime GetEndTime() override;
+  int64_t GetTotalBytes() override;
+  int64_t GetReceivedBytes() override;
+  CefBaseTime GetStartTime() override;
+  CefBaseTime GetEndTime() override;
   CefString GetFullPath() override;
-  uint32 GetId() override;
+  uint32_t GetId() override;
   CefString GetURL() override;
   CefString GetOriginalUrl() override;
   CefString GetSuggestedFileName() override;
   CefString GetContentDisposition() override;
   CefString GetMimeType() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefDownloadItemImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_DOWNLOAD_ITEM_IMPL_H_
diff --git a/src/libcef/browser/download_manager_delegate.cc b/src/libcef/browser/download_manager_delegate.cc
index e15c9a5..236067b 100644
--- a/src/libcef/browser/download_manager_delegate.cc
+++ b/src/libcef/browser/download_manager_delegate.cc
@@ -4,13 +4,16 @@
 
 #include "libcef/browser/download_manager_delegate.h"
 
+#include <tuple>
+
 #include "include/cef_download_handler.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 #include "libcef/browser/context.h"
 #include "libcef/browser/download_item_impl.h"
 #include "libcef/browser/thread_util.h"
 
-#include "base/bind.h"
 #include "base/files/file_util.h"
+#include "base/functional/bind.h"
 #include "base/logging.h"
 #include "base/path_service.h"
 #include "base/strings/string_util.h"
@@ -30,10 +33,11 @@
 
 // Helper function to retrieve the CefDownloadHandler.
 CefRefPtr<CefDownloadHandler> GetDownloadHandler(
-    CefRefPtr<CefBrowserHostImpl> browser) {
+    CefRefPtr<AlloyBrowserHostImpl> browser) {
   CefRefPtr<CefClient> client = browser->GetClient();
-  if (client.get())
+  if (client.get()) {
     return client->GetDownloadHandler();
+  }
   return nullptr;
 }
 
@@ -41,7 +45,7 @@
 class CefBeforeDownloadCallbackImpl : public CefBeforeDownloadCallback {
  public:
   CefBeforeDownloadCallbackImpl(const base::WeakPtr<DownloadManager>& manager,
-                                uint32 download_id,
+                                uint32_t download_id,
                                 const base::FilePath& suggested_name,
                                 content::DownloadTargetCallback callback)
       : manager_(manager),
@@ -49,10 +53,15 @@
         suggested_name_(suggested_name),
         callback_(std::move(callback)) {}
 
+  CefBeforeDownloadCallbackImpl(const CefBeforeDownloadCallbackImpl&) = delete;
+  CefBeforeDownloadCallbackImpl& operator=(
+      const CefBeforeDownloadCallbackImpl&) = delete;
+
   void Continue(const CefString& download_path, bool show_dialog) override {
     if (CEF_CURRENTLY_ON_UIT()) {
-      if (download_id_ <= 0)
+      if (download_id_ <= 0) {
         return;
+      }
 
       if (manager_) {
         base::FilePath path = base::FilePath(download_path);
@@ -72,7 +81,7 @@
 
  private:
   static void GenerateFilename(base::WeakPtr<DownloadManager> manager,
-                               uint32 download_id,
+                               uint32_t download_id,
                                const base::FilePath& suggested_name,
                                const base::FilePath& download_path,
                                bool show_dialog,
@@ -85,7 +94,7 @@
       base::FilePath dir_path = suggested_path.DirName();
       if (!base::DirectoryExists(dir_path) &&
           !base::CreateDirectory(dir_path)) {
-        NOTREACHED() << "failed to create the download directory";
+        DCHECK(false) << "failed to create the download directory";
         suggested_path.clear();
       }
     }
@@ -108,28 +117,30 @@
   }
 
   static void ChooseDownloadPath(base::WeakPtr<DownloadManager> manager,
-                                 uint32 download_id,
+                                 uint32_t download_id,
                                  const base::FilePath& suggested_path,
                                  bool show_dialog,
                                  content::DownloadTargetCallback callback) {
-    if (!manager)
+    if (!manager) {
       return;
+    }
 
     DownloadItem* item = manager->GetDownload(download_id);
-    if (!item || item->GetState() != DownloadItem::IN_PROGRESS)
+    if (!item || item->GetState() != DownloadItem::IN_PROGRESS) {
       return;
+    }
 
     bool handled = false;
 
     if (show_dialog) {
       WebContents* web_contents =
           content::DownloadItemUtils::GetWebContents(item);
-      CefRefPtr<CefBrowserHostImpl> browser =
-          CefBrowserHostImpl::GetBrowserForContents(web_contents);
+      CefRefPtr<AlloyBrowserHostImpl> browser =
+          AlloyBrowserHostImpl::GetBrowserForContents(web_contents);
       if (browser.get()) {
         handled = true;
 
-        CefFileDialogRunner::FileChooserParams params;
+        blink::mojom::FileChooserParams params;
         params.mode = blink::mojom::FileChooserParams::Mode::kSave;
         if (!suggested_path.empty()) {
           params.default_file_name = suggested_path;
@@ -139,7 +150,7 @@
           }
         }
 
-        browser->RunFileChooser(
+        browser->RunFileChooserForBrowser(
             params,
             base::BindOnce(
                 &CefBeforeDownloadCallbackImpl::ChooseDownloadPathCallback,
@@ -151,35 +162,37 @@
       std::move(callback).Run(
           suggested_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
           download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
-          download::DownloadItem::MixedContentStatus::UNKNOWN, suggested_path,
+          download::DownloadItem::InsecureDownloadStatus::UNKNOWN,
+          suggested_path, base::FilePath(), std::string() /*mime_type*/,
           download::DOWNLOAD_INTERRUPT_REASON_NONE);
     }
   }
 
   static void ChooseDownloadPathCallback(
       content::DownloadTargetCallback callback,
-      int selected_accept_filter,
       const std::vector<base::FilePath>& file_paths) {
     DCHECK_LE(file_paths.size(), (size_t)1);
 
     base::FilePath path;
-    if (file_paths.size() > 0)
+    if (file_paths.size() > 0) {
       path = file_paths.front();
+    }
 
     // The download will be cancelled if |path| is empty.
-    std::move(callback).Run(path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
-                            download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
-                            download::DownloadItem::MixedContentStatus::UNKNOWN,
-                            path, download::DOWNLOAD_INTERRUPT_REASON_NONE);
+    std::move(callback).Run(
+        path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+        download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+        download::DownloadItem::InsecureDownloadStatus::UNKNOWN, path,
+        base::FilePath(), std::string() /*mime_type*/,
+        download::DOWNLOAD_INTERRUPT_REASON_NONE);
   }
 
   base::WeakPtr<DownloadManager> manager_;
-  uint32 download_id_;
+  uint32_t download_id_;
   base::FilePath suggested_name_;
   content::DownloadTargetCallback callback_;
 
   IMPLEMENT_REFCOUNTING(CefBeforeDownloadCallbackImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefBeforeDownloadCallbackImpl);
 };
 
 // CefDownloadItemCallback implementation.
@@ -187,65 +200,74 @@
  public:
   explicit CefDownloadItemCallbackImpl(
       const base::WeakPtr<DownloadManager>& manager,
-      uint32 download_id)
+      uint32_t download_id)
       : manager_(manager), download_id_(download_id) {}
 
+  CefDownloadItemCallbackImpl(const CefDownloadItemCallbackImpl&) = delete;
+  CefDownloadItemCallbackImpl& operator=(const CefDownloadItemCallbackImpl&) =
+      delete;
+
   void Cancel() override {
     CEF_POST_TASK(CEF_UIT,
-                  base::Bind(&CefDownloadItemCallbackImpl::DoCancel, this));
+                  base::BindOnce(&CefDownloadItemCallbackImpl::DoCancel, this));
   }
 
   void Pause() override {
     CEF_POST_TASK(CEF_UIT,
-                  base::Bind(&CefDownloadItemCallbackImpl::DoPause, this));
+                  base::BindOnce(&CefDownloadItemCallbackImpl::DoPause, this));
   }
 
   void Resume() override {
     CEF_POST_TASK(CEF_UIT,
-                  base::Bind(&CefDownloadItemCallbackImpl::DoResume, this));
+                  base::BindOnce(&CefDownloadItemCallbackImpl::DoResume, this));
   }
 
  private:
   void DoCancel() {
-    if (download_id_ <= 0)
+    if (download_id_ <= 0) {
       return;
+    }
 
     if (manager_) {
       DownloadItem* item = manager_->GetDownload(download_id_);
-      if (item && item->GetState() == DownloadItem::IN_PROGRESS)
+      if (item && item->GetState() == DownloadItem::IN_PROGRESS) {
         item->Cancel(true);
+      }
     }
 
     download_id_ = 0;
   }
 
   void DoPause() {
-    if (download_id_ <= 0)
+    if (download_id_ <= 0) {
       return;
+    }
 
     if (manager_) {
       DownloadItem* item = manager_->GetDownload(download_id_);
-      if (item && item->GetState() == DownloadItem::IN_PROGRESS)
+      if (item && item->GetState() == DownloadItem::IN_PROGRESS) {
         item->Pause();
+      }
     }
   }
 
   void DoResume() {
-    if (download_id_ <= 0)
+    if (download_id_ <= 0) {
       return;
+    }
 
     if (manager_) {
       DownloadItem* item = manager_->GetDownload(download_id_);
-      if (item && item->CanResume())
+      if (item && item->CanResume()) {
         item->Resume(true);
+      }
     }
   }
 
   base::WeakPtr<DownloadManager> manager_;
-  uint32 download_id_;
+  uint32_t download_id_;
 
   IMPLEMENT_REFCOUNTING(CefDownloadItemCallbackImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefDownloadItemCallbackImpl);
 };
 
 }  // namespace
@@ -258,8 +280,9 @@
   DownloadManager::DownloadVector items;
   manager->GetAllDownloads(&items);
   DownloadManager::DownloadVector::const_iterator it = items.begin();
-  for (; it != items.end(); ++it)
+  for (; it != items.end(); ++it) {
     OnDownloadCreated(manager, *it);
+  }
 }
 
 CefDownloadManagerDelegate::~CefDownloadManagerDelegate() {
@@ -268,15 +291,17 @@
     manager_->RemoveObserver(this);
   }
 
-  while (!item_browser_map_.empty())
+  while (!item_browser_map_.empty()) {
     OnDownloadDestroyed(item_browser_map_.begin()->first);
+  }
 }
 
 void CefDownloadManagerDelegate::OnDownloadUpdated(DownloadItem* download) {
-  CefRefPtr<CefBrowserHostImpl> browser = GetBrowser(download);
+  CefRefPtr<AlloyBrowserHostImpl> browser = GetBrowser(download);
   CefRefPtr<CefDownloadHandler> handler;
-  if (browser.get())
+  if (browser.get()) {
     handler = GetDownloadHandler(browser);
+  }
 
   if (handler.get()) {
     CefRefPtr<CefDownloadItemImpl> download_item(
@@ -286,14 +311,14 @@
 
     handler->OnDownloadUpdated(browser.get(), download_item.get(), callback);
 
-    download_item->Detach(nullptr);
+    std::ignore = download_item->Detach(nullptr);
   }
 }
 
 void CefDownloadManagerDelegate::OnDownloadDestroyed(DownloadItem* item) {
   item->RemoveObserver(this);
 
-  CefBrowserHostImpl* browser = nullptr;
+  AlloyBrowserHostImpl* browser = nullptr;
 
   ItemBrowserMap::iterator it = item_browser_map_.find(item);
   DCHECK(it != item_browser_map_.end());
@@ -314,8 +339,9 @@
       }
     }
 
-    if (!has_remaining)
+    if (!has_remaining) {
       browser->RemoveObserver(this);
+    }
   }
 }
 
@@ -323,7 +349,7 @@
                                                    DownloadItem* item) {
   // This callback may arrive after DetermineDownloadTarget, so we allow
   // association from either method.
-  CefRefPtr<CefBrowserHostImpl> browser = GetOrAssociateBrowser(item);
+  CefRefPtr<AlloyBrowserHostImpl> browser = GetOrAssociateBrowser(item);
   if (!browser) {
     // If the download is rejected (e.g. ALT+click on an invalid protocol link)
     // then an "interrupted" download will be started via DownloadManagerImpl::
@@ -354,17 +380,19 @@
     std::move(*callback).Run(
         item->GetForcedFilePath(), DownloadItem::TARGET_DISPOSITION_OVERWRITE,
         download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
-        download::DownloadItem::MixedContentStatus::UNKNOWN,
-        item->GetForcedFilePath(), download::DOWNLOAD_INTERRUPT_REASON_NONE);
+        download::DownloadItem::InsecureDownloadStatus::UNKNOWN,
+        item->GetForcedFilePath(), base::FilePath(),
+        std::string() /*mime_type*/, download::DOWNLOAD_INTERRUPT_REASON_NONE);
     return true;
   }
 
   // This callback may arrive before OnDownloadCreated, so we allow association
   // from either method.
-  CefRefPtr<CefBrowserHostImpl> browser = GetOrAssociateBrowser(item);
+  CefRefPtr<AlloyBrowserHostImpl> browser = GetOrAssociateBrowser(item);
   CefRefPtr<CefDownloadHandler> handler;
-  if (browser.get())
+  if (browser.get()) {
     handler = GetDownloadHandler(browser);
+  }
 
   if (handler.get()) {
     base::FilePath suggested_name = net::GenerateFileName(
@@ -380,7 +408,7 @@
     handler->OnBeforeDownload(browser.get(), download_item.get(),
                               suggested_name.value(), callbackObj);
 
-    download_item->Detach(nullptr);
+    std::ignore = download_item->Detach(nullptr);
   }
 
   return true;
@@ -388,21 +416,16 @@
 
 void CefDownloadManagerDelegate::GetNextId(
     content::DownloadIdCallback callback) {
-  static uint32 next_id = DownloadItem::kInvalidId + 1;
+  static uint32_t next_id = DownloadItem::kInvalidId + 1;
   std::move(callback).Run(next_id++);
 }
 
 std::string CefDownloadManagerDelegate::ApplicationClientIdForFileScanning() {
-  const CefSettings& settings = CefContext::Get()->settings();
-  if (settings.application_client_id_for_file_scanning.length > 0) {
-    return CefString(&settings.application_client_id_for_file_scanning)
-        .ToString();
-  }
-  return std::string();
+  return std::string(chrome::kApplicationClientIDStringForAVScanning);
 }
 
 void CefDownloadManagerDelegate::OnBrowserDestroyed(
-    CefBrowserHostImpl* browser) {
+    CefBrowserHostBase* browser) {
   ItemBrowserMap::iterator it = item_browser_map_.begin();
   for (; it != item_browser_map_.end(); ++it) {
     if (it->second == browser) {
@@ -414,21 +437,23 @@
   }
 }
 
-CefBrowserHostImpl* CefDownloadManagerDelegate::GetOrAssociateBrowser(
+AlloyBrowserHostImpl* CefDownloadManagerDelegate::GetOrAssociateBrowser(
     download::DownloadItem* item) {
   ItemBrowserMap::const_iterator it = item_browser_map_.find(item);
-  if (it != item_browser_map_.end())
+  if (it != item_browser_map_.end()) {
     return it->second;
+  }
 
-  CefBrowserHostImpl* browser = nullptr;
+  AlloyBrowserHostImpl* browser = nullptr;
   content::WebContents* contents =
       content::DownloadItemUtils::GetWebContents(item);
   if (contents) {
-    browser = CefBrowserHostImpl::GetBrowserForContents(contents).get();
+    browser = AlloyBrowserHostImpl::GetBrowserForContents(contents).get();
     DCHECK(browser);
   }
-  if (!browser)
+  if (!browser) {
     return nullptr;
+  }
 
   item->AddObserver(this);
 
@@ -436,16 +461,19 @@
 
   // Register as an observer so that we can cancel associated DownloadItems when
   // the browser is destroyed.
-  if (!browser->HasObserver(this))
+  if (!browser->HasObserver(this)) {
     browser->AddObserver(this);
+  }
 
   return browser;
 }
 
-CefBrowserHostImpl* CefDownloadManagerDelegate::GetBrowser(DownloadItem* item) {
+AlloyBrowserHostImpl* CefDownloadManagerDelegate::GetBrowser(
+    DownloadItem* item) {
   ItemBrowserMap::const_iterator it = item_browser_map_.find(item);
-  if (it != item_browser_map_.end())
+  if (it != item_browser_map_.end()) {
     return it->second;
+  }
 
   // If the download is rejected (e.g. ALT+click on an invalid protocol link)
   // then an "interrupted" download will be started via DownloadManagerImpl::
diff --git a/src/libcef/browser/download_manager_delegate.h b/src/libcef/browser/download_manager_delegate.h
index 86a54ba..46c13bf 100644
--- a/src/libcef/browser/download_manager_delegate.h
+++ b/src/libcef/browser/download_manager_delegate.h
@@ -8,20 +8,26 @@
 
 #include <set>
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/browser_host_base.h"
 
-#include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
 #include "components/download/public/common/download_item.h"
 #include "content/public/browser/download_manager.h"
 #include "content/public/browser/download_manager_delegate.h"
 
+class AlloyBrowserHostImpl;
+
 class CefDownloadManagerDelegate : public download::DownloadItem::Observer,
                                    public content::DownloadManager::Observer,
                                    public content::DownloadManagerDelegate,
-                                   public CefBrowserHostImpl::Observer {
+                                   public CefBrowserHostBase::Observer {
  public:
   explicit CefDownloadManagerDelegate(content::DownloadManager* manager);
+
+  CefDownloadManagerDelegate(const CefDownloadManagerDelegate&) = delete;
+  CefDownloadManagerDelegate& operator=(const CefDownloadManagerDelegate&) =
+      delete;
+
   ~CefDownloadManagerDelegate() override;
 
  private:
@@ -41,22 +47,21 @@
   void GetNextId(content::DownloadIdCallback callback) override;
   std::string ApplicationClientIdForFileScanning() override;
 
-  // CefBrowserHostImpl::Observer methods.
-  void OnBrowserDestroyed(CefBrowserHostImpl* browser) override;
+  // CefBrowserHostBase::Observer methods.
+  void OnBrowserDestroyed(CefBrowserHostBase* browser) override;
 
-  CefBrowserHostImpl* GetOrAssociateBrowser(download::DownloadItem* item);
-  CefBrowserHostImpl* GetBrowser(download::DownloadItem* item);
+  AlloyBrowserHostImpl* GetOrAssociateBrowser(download::DownloadItem* item);
+  AlloyBrowserHostImpl* GetBrowser(download::DownloadItem* item);
 
   content::DownloadManager* manager_;
   base::WeakPtrFactory<content::DownloadManager> manager_ptr_factory_;
 
-  // Map of DownloadItem to originating CefBrowserHostImpl. Maintaining this
+  // Map of DownloadItem to originating AlloyBrowserHostImpl. Maintaining this
   // map is necessary because DownloadItem::GetWebContents() may return NULL if
   // the browser navigates while the download is in progress.
-  typedef std::map<download::DownloadItem*, CefBrowserHostImpl*> ItemBrowserMap;
+  using ItemBrowserMap =
+      std::map<download::DownloadItem*, AlloyBrowserHostImpl*>;
   ItemBrowserMap item_browser_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefDownloadManagerDelegate);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_DOWNLOAD_MANAGER_DELEGATE_H_
diff --git a/src/libcef/browser/extension_impl.cc b/src/libcef/browser/extension_impl.cc
index 5b7f677..756f29a 100644
--- a/src/libcef/browser/extension_impl.cc
+++ b/src/libcef/browser/extension_impl.cc
@@ -4,7 +4,6 @@
 
 #include "libcef/browser/extension_impl.h"
 
-#include "libcef/browser/extensions/extension_system.h"
 #include "libcef/browser/request_context_impl.h"
 #include "libcef/browser/thread_util.h"
 #include "libcef/common/values_impl.h"
@@ -17,9 +16,8 @@
     : id_(extension->id()),
       path_(extension->path().value()),
       manifest_(
-          new CefDictionaryValueImpl(extension->manifest()->value()->DeepCopy(),
-                                     true,
-                                     true)),
+          new CefDictionaryValueImpl(extension->manifest()->value()->Clone(),
+                                     /*read_only=*/true)),
       loader_context_(loader_context),
       handler_(handler) {}
 
@@ -37,12 +35,14 @@
 
 bool CefExtensionImpl::IsSame(CefRefPtr<CefExtension> that) {
   CefExtensionImpl* that_impl = static_cast<CefExtensionImpl*>(that.get());
-  if (!that_impl)
+  if (!that_impl) {
     return false;
+  }
 
   // Maybe the same object.
-  if (this == that_impl)
+  if (this == that_impl) {
     return true;
+  }
 
   return id_ == that_impl->id_ && path_ == that_impl->path_ &&
          loader_context_ == that_impl->loader_context_;
@@ -54,7 +54,7 @@
 
 CefRefPtr<CefRequestContext> CefExtensionImpl::GetLoaderContext() {
   if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
+    DCHECK(false) << "called on invalid thread";
     return nullptr;
   }
 
@@ -63,7 +63,7 @@
 
 bool CefExtensionImpl::IsLoaded() {
   if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
+    DCHECK(false) << "called on invalid thread";
     return false;
   }
 
@@ -77,28 +77,30 @@
   }
 
   // Will be NULL for internal extensions. They can't be unloaded.
-  if (!loader_context_)
+  if (!loader_context_) {
     return;
+  }
 
-  if (unloaded_)
+  if (unloaded_) {
     return;
+  }
 
   // CefExtensionHandler callbacks triggered by UnloadExtension may check this
   // flag, so set it here.
   unloaded_ = true;
 
-  const bool result = static_cast<CefRequestContextImpl*>(loader_context_)
-                          ->GetBrowserContext()
-                          ->extension_system()
-                          ->UnloadExtension(id_);
-  ALLOW_UNUSED_LOCAL(result);
+  [[maybe_unused]] const bool result =
+      static_cast<CefRequestContextImpl*>(loader_context_)
+          ->GetBrowserContext()
+          ->UnloadExtension(id_);
   DCHECK(result);
 }
 
 void CefExtensionImpl::OnExtensionLoaded() {
   CEF_REQUIRE_UIT();
-  if (handler_)
+  if (handler_) {
     handler_->OnExtensionLoaded(this);
+  }
 }
 
 void CefExtensionImpl::OnExtensionUnloaded() {
@@ -109,6 +111,7 @@
   unloaded_ = true;
   loader_context_ = nullptr;
 
-  if (handler_)
+  if (handler_) {
     handler_->OnExtensionUnloaded(this);
+  }
 }
diff --git a/src/libcef/browser/extension_impl.h b/src/libcef/browser/extension_impl.h
index bcb6294..482e98c 100644
--- a/src/libcef/browser/extension_impl.h
+++ b/src/libcef/browser/extension_impl.h
@@ -23,6 +23,9 @@
                    CefRequestContext* loader_context,
                    CefRefPtr<CefExtensionHandler> handler);
 
+  CefExtensionImpl(const CefExtensionImpl&) = delete;
+  CefExtensionImpl& operator=(const CefExtensionImpl&) = delete;
+
   // CefExtension methods.
   CefString GetIdentifier() override;
   CefString GetPath() override;
@@ -52,7 +55,6 @@
   bool unloaded_ = false;
 
   IMPLEMENT_REFCOUNTING(CefExtensionImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefExtensionImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_EXTENSION_IMPL_H_
diff --git a/src/libcef/browser/extensions/alloy_extensions_util.cc b/src/libcef/browser/extensions/alloy_extensions_util.cc
new file mode 100644
index 0000000..a802ab1
--- /dev/null
+++ b/src/libcef/browser/extensions/alloy_extensions_util.cc
@@ -0,0 +1,21 @@
+// Copyright 2021 The Chromium Embedded Framework 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 "libcef/browser/extensions/alloy_extensions_util.h"
+
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
+
+namespace extensions {
+namespace alloy {
+
+int GetTabIdForWebContents(content::WebContents* web_contents) {
+  auto browser = AlloyBrowserHostImpl::GetBrowserForContents(web_contents);
+  if (!browser) {
+    return -1;
+  }
+  return browser->GetIdentifier();
+}
+
+}  // namespace alloy
+}  // namespace extensions
diff --git a/src/libcef/browser/extensions/alloy_extensions_util.h b/src/libcef/browser/extensions/alloy_extensions_util.h
new file mode 100644
index 0000000..e68c0c2
--- /dev/null
+++ b/src/libcef/browser/extensions/alloy_extensions_util.h
@@ -0,0 +1,21 @@
+// Copyright 2021 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_EXTENSIONS_ALLOY_EXTENSIONS_UTIL_H_
+#define CEF_LIBCEF_BROWSER_EXTENSIONS_ALLOY_EXTENSIONS_UTIL_H_
+
+namespace content {
+class WebContents;
+}
+
+namespace extensions {
+namespace alloy {
+
+// Returns the tabId for |web_contents|, or -1 if not found.
+int GetTabIdForWebContents(content::WebContents* web_contents);
+
+}  // namespace alloy
+}  // namespace extensions
+
+#endif  // CEF_LIBCEF_BROWSER_EXTENSIONS_ALLOY_EXTENSIONS_UTIL_H_
diff --git a/src/libcef/browser/extensions/api/file_system/cef_file_system_delegate.cc b/src/libcef/browser/extensions/api/file_system/cef_file_system_delegate.cc
new file mode 100644
index 0000000..abe577b
--- /dev/null
+++ b/src/libcef/browser/extensions/api/file_system/cef_file_system_delegate.cc
@@ -0,0 +1,89 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+

+#include "libcef/browser/extensions/api/file_system/cef_file_system_delegate.h"

+

+#include "apps/saved_files_service.h"

+#include "base/files/file_path.h"

+#include "base/functional/callback.h"

+#include "chrome/browser/extensions/api/file_system/file_entry_picker.h"

+#include "chrome/grit/generated_resources.h"

+#include "content/public/browser/web_contents.h"

+#include "extensions/common/api/file_system.h"

+#include "extensions/common/extension.h"

+

+namespace extensions {

+namespace cef {

+

+CefFileSystemDelegate::CefFileSystemDelegate() = default;

+

+CefFileSystemDelegate::~CefFileSystemDelegate() = default;

+

+base::FilePath CefFileSystemDelegate::GetDefaultDirectory() {

+  return base::FilePath();

+}

+

+base::FilePath CefFileSystemDelegate::GetManagedSaveAsDirectory(

+    content::BrowserContext* browser_context,

+    const Extension& extension) {

+  return base::FilePath();

+}

+

+bool CefFileSystemDelegate::ShowSelectFileDialog(

+    scoped_refptr<ExtensionFunction> extension_function,

+    ui::SelectFileDialog::Type type,

+    const base::FilePath& default_path,

+    const ui::SelectFileDialog::FileTypeInfo* file_types,

+    FileSystemDelegate::FilesSelectedCallback files_selected_callback,

+    base::OnceClosure file_selection_canceled_callback) {

+  auto web_contents = extension_function->GetSenderWebContents();

+  if (!web_contents) {

+    return false;

+  }

+

+  // The file picker will hold a reference to the ExtensionFunction

+  // instance, preventing its destruction (and subsequent sending of the

+  // function response) until the user has selected a file or cancelled the

+  // picker. At that point, the picker will delete itself, which will also free

+  // the function instance.

+  new FileEntryPicker(web_contents, default_path, *file_types, type,

+                      std::move(files_selected_callback),

+                      std::move(file_selection_canceled_callback));

+  return true;

+}

+

+void CefFileSystemDelegate::ConfirmSensitiveDirectoryAccess(

+    bool has_write_permission,

+    const std::u16string& app_name,

+    content::WebContents* web_contents,

+    base::OnceClosure on_accept,

+    base::OnceClosure on_cancel) {

+  NOTIMPLEMENTED();

+

+  // Run the cancel callback by default.

+  std::move(on_cancel).Run();

+}

+

+// Based on ChromeFileSystemDelegate::GetDescriptionIdForAcceptType.

+int CefFileSystemDelegate::GetDescriptionIdForAcceptType(

+    const std::string& accept_type) {

+  if (accept_type == "image/*") {

+    return IDS_IMAGE_FILES;

+  }

+  if (accept_type == "audio/*") {

+    return IDS_AUDIO_FILES;

+  }

+  if (accept_type == "video/*") {

+    return IDS_VIDEO_FILES;

+  }

+  return 0;

+}

+

+SavedFilesServiceInterface* CefFileSystemDelegate::GetSavedFilesService(

+    content::BrowserContext* browser_context) {

+  return apps::SavedFilesService::Get(browser_context);

+}

+

+}  // namespace cef

+}  // namespace extensions

diff --git a/src/libcef/browser/extensions/api/file_system/cef_file_system_delegate.h b/src/libcef/browser/extensions/api/file_system/cef_file_system_delegate.h
new file mode 100644
index 0000000..bfcb020
--- /dev/null
+++ b/src/libcef/browser/extensions/api/file_system/cef_file_system_delegate.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+

+#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_API_FILE_SYSTEM_FILE_SYSTEM_DELEGATE_H_

+#define CEF_LIBCEF_BROWSER_EXTENSIONS_API_FILE_SYSTEM_FILE_SYSTEM_DELEGATE_H_

+

+#include <memory>

+

+#include "base/compiler_specific.h"

+#include "base/functional/callback.h"

+#include "base/memory/ref_counted.h"

+#include "extensions/browser/api/execute_code_function.h"

+#include "extensions/browser/api/file_system/file_system_delegate.h"

+#include "extensions/browser/extension_function.h"

+

+namespace content {

+class WebContents;

+}

+

+namespace extensions {

+namespace cef {

+

+class CefFileSystemDelegate : public FileSystemDelegate {

+ public:

+  CefFileSystemDelegate();

+

+  CefFileSystemDelegate(const CefFileSystemDelegate&) = delete;

+  CefFileSystemDelegate& operator=(const CefFileSystemDelegate&) = delete;

+

+  ~CefFileSystemDelegate() override;

+

+  // FileSystemDelegate

+  base::FilePath GetDefaultDirectory() override;

+  base::FilePath GetManagedSaveAsDirectory(

+      content::BrowserContext* browser_context,

+      const Extension& extension) override;

+  bool ShowSelectFileDialog(

+      scoped_refptr<ExtensionFunction> extension_function,

+      ui::SelectFileDialog::Type type,

+      const base::FilePath& default_path,

+      const ui::SelectFileDialog::FileTypeInfo* file_types,

+      FileSystemDelegate::FilesSelectedCallback files_selected_callback,

+      base::OnceClosure file_selection_canceled_callback) override;

+  void ConfirmSensitiveDirectoryAccess(bool has_write_permission,

+                                       const std::u16string& app_name,

+                                       content::WebContents* web_contents,

+                                       base::OnceClosure on_accept,

+                                       base::OnceClosure on_cancel) override;

+  int GetDescriptionIdForAcceptType(const std::string& accept_type) override;

+  SavedFilesServiceInterface* GetSavedFilesService(

+      content::BrowserContext* browser_context) override;

+};

+

+}  // namespace cef

+}  // namespace extensions

+

+#endif  // CEF_LIBCEF_BROWSER_EXTENSIONS_API_FILE_SYSTEM_FILE_SYSTEM_DELEGATE_H_

diff --git a/src/libcef/browser/extensions/api/storage/sync_value_store_cache.cc b/src/libcef/browser/extensions/api/storage/sync_value_store_cache.cc
index 8a6ab7b..5dff6f6 100644
--- a/src/libcef/browser/extensions/api/storage/sync_value_store_cache.cc
+++ b/src/libcef/browser/extensions/api/storage/sync_value_store_cache.cc
@@ -8,11 +8,13 @@
 #include <stddef.h>
 
 #include <limits>
+#include <utility>
 
+#include "components/value_store/value_store_factory.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/api/storage/backend_task_runner.h"
+#include "extensions/browser/api/storage/value_store_util.h"
 #include "extensions/browser/api/storage/weak_unlimited_settings_storage.h"
-#include "extensions/browser/value_store/value_store_factory.h"
 #include "extensions/common/api/storage.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/permissions/permissions_data.h"
@@ -37,8 +39,8 @@
 }  // namespace
 
 SyncValueStoreCache::SyncValueStoreCache(
-    const scoped_refptr<ValueStoreFactory>& factory)
-    : storage_factory_(factory), quota_(GetLocalQuotaLimits()) {
+    scoped_refptr<value_store::ValueStoreFactory> factory)
+    : storage_factory_(std::move(factory)), quota_(GetLocalQuotaLimits()) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
 
@@ -47,49 +49,55 @@
 }
 
 void SyncValueStoreCache::RunWithValueStoreForExtension(
-    const StorageCallback& callback,
+    StorageCallback callback,
     scoped_refptr<const Extension> extension) {
   DCHECK(IsOnBackendSequence());
 
-  ValueStore* storage = GetStorage(extension.get());
+  value_store::ValueStore* storage = GetStorage(extension.get());
 
   // A neat way to implement unlimited storage; if the extension has the
   // unlimited storage permission, force through all calls to Set().
   if (extension->permissions_data()->HasAPIPermission(
-          APIPermission::kUnlimitedStorage)) {
+          mojom::APIPermissionID::kUnlimitedStorage)) {
     WeakUnlimitedSettingsStorage unlimited_storage(storage);
-    callback.Run(&unlimited_storage);
+    std::move(callback).Run(&unlimited_storage);
   } else {
-    callback.Run(storage);
+    std::move(callback).Run(storage);
   }
 }
 
 void SyncValueStoreCache::DeleteStorageSoon(const std::string& extension_id) {
   DCHECK(IsOnBackendSequence());
   storage_map_.erase(extension_id);
-  storage_factory_->DeleteSettings(settings_namespace::SYNC,
-                                   ValueStoreFactory::ModelType::APP,
-                                   extension_id);
-  storage_factory_->DeleteSettings(settings_namespace::SYNC,
-                                   ValueStoreFactory::ModelType::EXTENSION,
-                                   extension_id);
+
+  value_store_util::DeleteValueStore(settings_namespace::SYNC,
+                                     value_store_util::ModelType::APP,
+                                     extension_id, storage_factory_);
+
+  value_store_util::DeleteValueStore(settings_namespace::SYNC,
+                                     value_store_util::ModelType::EXTENSION,
+                                     extension_id, storage_factory_);
 }
 
-ValueStore* SyncValueStoreCache::GetStorage(const Extension* extension) {
-  StorageMap::iterator iter = storage_map_.find(extension->id());
-  if (iter != storage_map_.end())
+value_store::ValueStore* SyncValueStoreCache::GetStorage(
+    const Extension* extension) {
+  auto iter = storage_map_.find(extension->id());
+  if (iter != storage_map_.end()) {
     return iter->second.get();
+  }
 
-  ValueStoreFactory::ModelType model_type =
-      extension->is_app() ? ValueStoreFactory::ModelType::APP
-                          : ValueStoreFactory::ModelType::EXTENSION;
-  std::unique_ptr<ValueStore> store = storage_factory_->CreateSettingsStore(
-      settings_namespace::SYNC, model_type, extension->id());
+  value_store_util::ModelType model_type =
+      extension->is_app() ? value_store_util::ModelType::APP
+                          : value_store_util::ModelType::EXTENSION;
+  std::unique_ptr<value_store::ValueStore> store =
+      value_store_util::CreateSettingsStore(settings_namespace::LOCAL,
+                                            model_type, extension->id(),
+                                            storage_factory_);
   std::unique_ptr<SettingsStorageQuotaEnforcer> storage(
       new SettingsStorageQuotaEnforcer(quota_, std::move(store)));
   DCHECK(storage.get());
 
-  ValueStore* storage_ptr = storage.get();
+  value_store::ValueStore* storage_ptr = storage.get();
   storage_map_[extension->id()] = std::move(storage);
   return storage_ptr;
 }
diff --git a/src/libcef/browser/extensions/api/storage/sync_value_store_cache.h b/src/libcef/browser/extensions/api/storage/sync_value_store_cache.h
index 269fc7c..626c182 100644
--- a/src/libcef/browser/extensions/api/storage/sync_value_store_cache.h
+++ b/src/libcef/browser/extensions/api/storage/sync_value_store_cache.h
@@ -8,16 +8,15 @@
 
 #include <memory>
 
-#include "base/compiler_specific.h"
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "extensions/browser/api/storage/settings_storage_quota_enforcer.h"
 #include "extensions/browser/api/storage/value_store_cache.h"
 
-namespace extensions {
-
+namespace value_store {
 class ValueStoreFactory;
+}
 
+namespace extensions {
 namespace cef {
 
 // Based on LocalValueStoreCache
@@ -25,31 +24,36 @@
 // another for extensions. Each backend takes care of persistence.
 class SyncValueStoreCache : public ValueStoreCache {
  public:
-  explicit SyncValueStoreCache(const scoped_refptr<ValueStoreFactory>& factory);
+  explicit SyncValueStoreCache(
+      scoped_refptr<value_store::ValueStoreFactory> factory);
+
+  SyncValueStoreCache(const SyncValueStoreCache&) = delete;
+  SyncValueStoreCache& operator=(const SyncValueStoreCache&) = delete;
+
   ~SyncValueStoreCache() override;
 
   // ValueStoreCache implementation:
   void RunWithValueStoreForExtension(
-      const StorageCallback& callback,
+      StorageCallback callback,
       scoped_refptr<const Extension> extension) override;
   void DeleteStorageSoon(const std::string& extension_id) override;
 
  private:
-  using StorageMap = std::map<std::string, std::unique_ptr<ValueStore>>;
+  using StorageMap =
+      std::map<std::string, std::unique_ptr<value_store::ValueStore>>;
 
-  ValueStore* GetStorage(const Extension* extension);
+  value_store::ValueStore* GetStorage(const Extension* extension);
 
   // The Factory to use for creating new ValueStores.
-  const scoped_refptr<ValueStoreFactory> storage_factory_;
+  const scoped_refptr<value_store::ValueStoreFactory> storage_factory_;
 
   // Quota limits (see SettingsStorageQuotaEnforcer).
   const SettingsStorageQuotaEnforcer::Limits quota_;
 
   // The collection of ValueStores for local storage.
   StorageMap storage_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(SyncValueStoreCache);
 };
+
 }  // namespace cef
 }  // namespace extensions
 
diff --git a/src/libcef/browser/extensions/api/tabs/tabs_api.cc b/src/libcef/browser/extensions/api/tabs/tabs_api.cc
index d732ae2..deb937a 100644
--- a/src/libcef/browser/extensions/api/tabs/tabs_api.cc
+++ b/src/libcef/browser/extensions/api/tabs/tabs_api.cc
@@ -6,10 +6,16 @@
 
 #include "libcef/browser/extensions/extension_web_contents_observer.h"
 
+#include "base/notreached.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
+#include "chrome/browser/extensions/extension_tab_util.h"
 #include "components/zoom/zoom_controller.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/site_instance.h"
 #include "extensions/browser/extension_api_frame_id_map.h"
 #include "extensions/browser/extension_zoom_request_client.h"
 #include "extensions/common/error_utils.h"
@@ -17,6 +23,8 @@
 #include "extensions/common/permissions/permissions_data.h"
 #include "third_party/blink/public/common/page/page_zoom.h"
 
+using zoom::ZoomController;
+
 namespace extensions {
 namespace cef {
 
@@ -52,14 +60,6 @@
   }
 }
 
-template <typename T>
-void AssignOptionalValue(const std::unique_ptr<T>& source,
-                         std::unique_ptr<T>& destination) {
-  if (source.get()) {
-    destination.reset(new T(*source));
-  }
-}
-
 }  // namespace
 
 ExtensionFunction::ResponseAction TabsGetFunction::Run() {
@@ -69,30 +69,176 @@
 TabsCreateFunction::TabsCreateFunction() : cef_details_(this) {}
 
 ExtensionFunction::ResponseAction TabsCreateFunction::Run() {
-  std::unique_ptr<tabs::Create::Params> params(
-      tabs::Create::Params::Create(*args_));
-  EXTENSION_FUNCTION_VALIDATE(params.get());
+  absl::optional<tabs::Create::Params> params =
+      tabs::Create::Params::Create(args());
+  EXTENSION_FUNCTION_VALIDATE(params);
 
   CefExtensionFunctionDetails::OpenTabParams options;
-  AssignOptionalValue(params->create_properties.window_id, options.window_id);
-  AssignOptionalValue(params->create_properties.opener_tab_id,
-                      options.opener_tab_id);
-  AssignOptionalValue(params->create_properties.selected, options.active);
+  options.window_id = params->create_properties.window_id;
+  options.opener_tab_id = params->create_properties.opener_tab_id;
+  options.active = params->create_properties.selected;
   // The 'active' property has replaced the 'selected' property.
-  AssignOptionalValue(params->create_properties.active, options.active);
-  AssignOptionalValue(params->create_properties.pinned, options.pinned);
-  AssignOptionalValue(params->create_properties.index, options.index);
-  AssignOptionalValue(params->create_properties.url, options.url);
+  options.active = params->create_properties.active;
+  options.pinned = params->create_properties.pinned;
+  options.index = params->create_properties.index;
+  options.url = params->create_properties.url;
 
   std::string error;
-  std::unique_ptr<base::DictionaryValue> result(
-      cef_details_.OpenTab(options, user_gesture(), &error));
-  if (!result)
+  auto result = cef_details_.OpenTab(options, user_gesture(), &error);
+  if (!result) {
     return RespondNow(Error(error));
+  }
 
   // Return data about the newly created tab.
-  return RespondNow(has_callback() ? OneArgument(std::move(result))
-                                   : NoArguments());
+  return RespondNow(has_callback()
+                        ? WithArguments(base::Value(result->ToValue()))
+                        : NoArguments());
+}
+
+BaseAPIFunction::BaseAPIFunction() : cef_details_(this) {}
+
+content::WebContents* BaseAPIFunction::GetWebContents(int tab_id) {
+  // Find a browser that we can access, or set |error_| and return nullptr.
+  CefRefPtr<AlloyBrowserHostImpl> browser =
+      cef_details_.GetBrowserForTabIdFirstTime(tab_id, &error_);
+  if (!browser) {
+    return nullptr;
+  }
+
+  return browser->web_contents();
+}
+
+ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
+  absl::optional<tabs::Update::Params> params =
+      tabs::Update::Params::Create(args());
+  EXTENSION_FUNCTION_VALIDATE(params);
+
+  tab_id_ = params->tab_id ? *params->tab_id : -1;
+  content::WebContents* web_contents = GetWebContents(tab_id_);
+  if (!web_contents) {
+    return RespondNow(Error(std::move(error_)));
+  }
+
+  web_contents_ = web_contents;
+
+  // TODO(rafaelw): handle setting remaining tab properties:
+  // -title
+  // -favIconUrl
+
+  // Navigate the tab to a new location if the url is different.
+  if (params->update_properties.url.has_value()) {
+    std::string updated_url = *params->update_properties.url;
+    if (!UpdateURL(updated_url, tab_id_, &error_)) {
+      return RespondNow(Error(std::move(error_)));
+    }
+  }
+
+  bool active = false;
+  // TODO(rafaelw): Setting |active| from js doesn't make much sense.
+  // Move tab selection management up to window.
+  if (params->update_properties.selected.has_value()) {
+    active = *params->update_properties.selected;
+  }
+
+  // The 'active' property has replaced 'selected'.
+  if (params->update_properties.active.has_value()) {
+    active = *params->update_properties.active;
+  }
+
+  if (active) {
+    // TODO: Activate the tab at |tab_id_|.
+    NOTIMPLEMENTED();
+    return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
+  }
+
+  if (params->update_properties.highlighted.has_value() &&
+      *params->update_properties.highlighted) {
+    // TODO: Highlight the tab at |tab_id_|.
+    NOTIMPLEMENTED();
+    return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
+  }
+
+  if (params->update_properties.pinned.has_value() &&
+      *params->update_properties.pinned) {
+    // TODO: Pin the tab at |tab_id_|.
+    NOTIMPLEMENTED();
+    return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
+  }
+
+  if (params->update_properties.muted.has_value()) {
+    // TODO: Mute/unmute the tab at |tab_id_|.
+    NOTIMPLEMENTED();
+    return RespondNow(Error(ErrorUtils::FormatErrorMessage(
+        tabs_constants::kCannotUpdateMuteCaptured,
+        base::NumberToString(tab_id_))));
+  }
+
+  if (params->update_properties.opener_tab_id.has_value()) {
+    int opener_id = *params->update_properties.opener_tab_id;
+    if (opener_id == tab_id_) {
+      return RespondNow(Error("Cannot set a tab's opener to itself."));
+    }
+
+    // TODO: Set the opener for the tab at |tab_id_|.
+    NOTIMPLEMENTED();
+    return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
+  }
+
+  if (params->update_properties.auto_discardable.has_value()) {
+    // TODO: Set auto-discardable state for the tab at |tab_id_|.
+    NOTIMPLEMENTED();
+  }
+
+  return RespondNow(GetResult());
+}
+
+bool TabsUpdateFunction::UpdateURL(const std::string& url_string,
+                                   int tab_id,
+                                   std::string* error) {
+  GURL url;
+  auto url_expected = ExtensionTabUtil::PrepareURLForNavigation(
+      url_string, extension(), browser_context());
+  if (url_expected.has_value()) {
+    url = *url_expected;
+  } else {
+    *error = std::move(url_expected.error());
+    return false;
+  }
+
+  content::NavigationController::LoadURLParams load_params(url);
+
+  // Treat extension-initiated navigations as renderer-initiated so that the URL
+  // does not show in the omnibox until it commits.  This avoids URL spoofs
+  // since URLs can be opened on behalf of untrusted content.
+  load_params.is_renderer_initiated = true;
+  // All renderer-initiated navigations need to have an initiator origin.
+  load_params.initiator_origin = extension()->origin();
+  // |source_site_instance| needs to be set so that a renderer process
+  // compatible with |initiator_origin| is picked by Site Isolation.
+  load_params.source_site_instance = content::SiteInstance::CreateForURL(
+      web_contents_->GetBrowserContext(),
+      load_params.initiator_origin->GetURL());
+
+  // Marking the navigation as initiated via an API means that the focus
+  // will stay in the omnibox - see https://crbug.com/1085779.
+  load_params.transition_type = ui::PAGE_TRANSITION_FROM_API;
+
+  web_contents_->GetController().LoadURLWithParams(load_params);
+
+  DCHECK_EQ(url,
+            web_contents_->GetController().GetPendingEntry()->GetVirtualURL());
+
+  return true;
+}
+
+ExtensionFunction::ResponseValue TabsUpdateFunction::GetResult() {
+  if (!has_callback()) {
+    return NoArguments();
+  }
+
+  return ArgumentList(tabs::Get::Results::Create(cef_details_.CreateTabObject(
+      AlloyBrowserHostImpl::GetBrowserForContents(web_contents_),
+      /*opener_browser_id=*/-1, /*active=*/true, tab_id_)));
 }
 
 ExecuteCodeInTabFunction::ExecuteCodeInTabFunction()
@@ -101,42 +247,66 @@
 ExecuteCodeInTabFunction::~ExecuteCodeInTabFunction() {}
 
 ExecuteCodeFunction::InitResult ExecuteCodeInTabFunction::Init() {
-  if (init_result_)
+  if (init_result_) {
     return init_result_.value();
+  }
 
+  if (args().size() < 2) {
+    return set_init_result(VALIDATION_FAILURE);
+  }
+
+  const auto& tab_id_value = args()[0];
   // |tab_id| is optional so it's ok if it's not there.
   int tab_id = -1;
-  if (args_->GetInteger(0, &tab_id) && tab_id < 0)
-    return set_init_result(VALIDATION_FAILURE);
+  if (tab_id_value.is_int()) {
+    // But if it is present, it needs to be non-negative.
+    tab_id = tab_id_value.GetInt();
+    if (tab_id < 0) {
+      return set_init_result(VALIDATION_FAILURE);
+    }
+  }
 
   // |details| are not optional.
-  base::DictionaryValue* details_value = nullptr;
-  if (!args_->GetDictionary(1, &details_value))
+  const base::Value& details_value = args()[1];
+  if (!details_value.is_dict()) {
     return set_init_result(VALIDATION_FAILURE);
+  }
   std::unique_ptr<InjectDetails> details(new InjectDetails());
-  if (!InjectDetails::Populate(*details_value, details.get()))
+  if (!InjectDetails::Populate(details_value.GetDict(), *details)) {
     return set_init_result(VALIDATION_FAILURE);
+  }
 
   // Find a browser that we can access, or fail with error.
   std::string error;
-  CefRefPtr<CefBrowserHostImpl> browser =
+  CefRefPtr<AlloyBrowserHostImpl> browser =
       cef_details_.GetBrowserForTabIdFirstTime(tab_id, &error);
-  if (!browser)
+  if (!browser) {
     return set_init_result_error(error);
+  }
 
   execute_tab_id_ = browser->GetIdentifier();
   details_ = std::move(details);
-  set_host_id(HostID(HostID::EXTENSIONS, extension()->id()));
+  set_host_id(
+      mojom::HostID(mojom::HostID::HostType::kExtensions, extension()->id()));
   return set_init_result(SUCCESS);
 }
 
+bool ExecuteCodeInTabFunction::ShouldInsertCSS() const {
+  return false;
+}
+
+bool ExecuteCodeInTabFunction::ShouldRemoveCSS() const {
+  return false;
+}
+
 bool ExecuteCodeInTabFunction::CanExecuteScriptOnPage(std::string* error) {
   CHECK_GE(execute_tab_id_, 0);
 
-  CefRefPtr<CefBrowserHostImpl> browser =
+  CefRefPtr<AlloyBrowserHostImpl> browser =
       cef_details_.GetBrowserForTabIdAgain(execute_tab_id_, error);
-  if (!browser)
+  if (!browser) {
     return false;
+  }
 
   int frame_id = details_->frame_id ? *details_->frame_id
                                     : ExtensionApiFrameIdMap::kTopFrameId;
@@ -172,7 +342,7 @@
                                                       execute_tab_id_, error)) {
     if (is_about_url &&
         extension()->permissions_data()->active_permissions().HasAPIPermission(
-            APIPermission::kTab)) {
+            mojom::APIPermissionID::kTab)) {
       *error = ErrorUtils::FormatErrorMessage(
           manifest_errors::kCannotAccessAboutUrl,
           rfh->GetLastCommittedURL().spec(),
@@ -188,10 +358,11 @@
     std::string* error) {
   CHECK_GE(execute_tab_id_, 0);
 
-  CefRefPtr<CefBrowserHostImpl> browser =
+  CefRefPtr<AlloyBrowserHostImpl> browser =
       cef_details_.GetBrowserForTabIdAgain(execute_tab_id_, error);
-  if (!browser)
+  if (!browser) {
     return nullptr;
+  }
 
   return CefExtensionWebContentsObserver::FromWebContents(
              browser->web_contents())
@@ -221,177 +392,150 @@
 void ExecuteCodeInTabFunction::LoadFileComplete(
     const std::string& file,
     std::unique_ptr<std::string> data) {
+  std::vector<std::unique_ptr<std::string>> data_list;
+  absl::optional<std::string> error;
   const bool success = !!data.get();
-  DidLoadAndLocalizeFile(file, success, std::move(data));
-}
-
-bool TabsExecuteScriptFunction::ShouldInsertCSS() const {
-  return false;
+  if (success) {
+    DCHECK(data);
+    data_list.push_back(std::move(data));
+  } else {
+    error = base::StringPrintf("Failed to load file '%s'.", file.c_str());
+  }
+  DidLoadAndLocalizeFile(file, std::move(data_list), std::move(error));
 }
 
 bool TabsInsertCSSFunction::ShouldInsertCSS() const {
   return true;
 }
 
-ZoomAPIFunction::ZoomAPIFunction() : cef_details_(this) {}
-
-content::WebContents* ZoomAPIFunction::GetWebContents(int tab_id) {
-  // Find a browser that we can access, or set |error_| and return nullptr.
-  CefRefPtr<CefBrowserHostImpl> browser =
-      cef_details_.GetBrowserForTabIdFirstTime(tab_id, &error_);
-  if (!browser)
-    return nullptr;
-
-  return browser->web_contents();
+bool TabsRemoveCSSFunction::ShouldRemoveCSS() const {
+  return true;
 }
 
-void ZoomAPIFunction::SendResponse(bool success) {
-  ResponseValue response;
-  if (success) {
-    response = ArgumentList(std::move(results_));
-  } else {
-    response = results_ ? ErrorWithArguments(std::move(results_), error_)
-                        : Error(error_);
-  }
-  Respond(std::move(response));
-}
-
-ExtensionFunction::ResponseAction ZoomAPIFunction::Run() {
-  if (RunAsync())
-    return RespondLater();
-  // TODO(devlin): Track these down and eliminate them if possible. We
-  // shouldn't return results and an error.
-  if (results_)
-    return RespondNow(ErrorWithArguments(std::move(results_), error_));
-  return RespondNow(Error(error_));
-}
-
-bool TabsSetZoomFunction::RunAsync() {
-  std::unique_ptr<tabs::SetZoom::Params> params(
-      tabs::SetZoom::Params::Create(*args_));
-  EXTENSION_FUNCTION_PRERUN_VALIDATE(params);
+ExtensionFunction::ResponseAction TabsSetZoomFunction::Run() {
+  absl::optional<tabs::SetZoom::Params> params =
+      tabs::SetZoom::Params::Create(args());
+  EXTENSION_FUNCTION_VALIDATE(params);
 
   int tab_id = params->tab_id ? *params->tab_id : -1;
   content::WebContents* web_contents = GetWebContents(tab_id);
-  if (!web_contents)
-    return false;
+  if (!web_contents) {
+    return RespondNow(Error(std::move(error_)));
+  }
 
   GURL url(web_contents->GetVisibleURL());
-  if (extension()->permissions_data()->IsRestrictedUrl(url, &error_))
-    return false;
+  if (extension()->permissions_data()->IsRestrictedUrl(url, &error_)) {
+    return RespondNow(Error(std::move(error_)));
+  }
 
-  zoom::ZoomController* zoom_controller =
-      zoom::ZoomController::FromWebContents(web_contents);
+  ZoomController* zoom_controller =
+      ZoomController::FromWebContents(web_contents);
   double zoom_level =
       params->zoom_factor > 0
           ? blink::PageZoomFactorToZoomLevel(params->zoom_factor)
           : zoom_controller->GetDefaultZoomLevel();
 
-  scoped_refptr<extensions::ExtensionZoomRequestClient> client(
-      new extensions::ExtensionZoomRequestClient(extension()));
+  auto client = base::MakeRefCounted<ExtensionZoomRequestClient>(extension());
   if (!zoom_controller->SetZoomLevelByClient(zoom_level, client)) {
     // Tried to zoom a tab in disabled mode.
-    error_ = keys::kCannotZoomDisabledTabError;
-    return false;
+    return RespondNow(Error(tabs_constants::kCannotZoomDisabledTabError));
   }
 
-  SendResponse(true);
-  return true;
+  return RespondNow(NoArguments());
 }
 
-bool TabsGetZoomFunction::RunAsync() {
-  std::unique_ptr<tabs::GetZoom::Params> params(
-      tabs::GetZoom::Params::Create(*args_));
-  EXTENSION_FUNCTION_PRERUN_VALIDATE(params);
+ExtensionFunction::ResponseAction TabsGetZoomFunction::Run() {
+  absl::optional<tabs::GetZoom::Params> params =
+      tabs::GetZoom::Params::Create(args());
+  EXTENSION_FUNCTION_VALIDATE(params);
 
   int tab_id = params->tab_id ? *params->tab_id : -1;
   content::WebContents* web_contents = GetWebContents(tab_id);
-  if (!web_contents)
-    return false;
+  if (!web_contents) {
+    return RespondNow(Error(std::move(error_)));
+  }
 
   double zoom_level =
       zoom::ZoomController::FromWebContents(web_contents)->GetZoomLevel();
   double zoom_factor = blink::PageZoomLevelToZoomFactor(zoom_level);
-  results_ = tabs::GetZoom::Results::Create(zoom_factor);
-  SendResponse(true);
-  return true;
+
+  return RespondNow(ArgumentList(tabs::GetZoom::Results::Create(zoom_factor)));
 }
 
-bool TabsSetZoomSettingsFunction::RunAsync() {
+ExtensionFunction::ResponseAction TabsSetZoomSettingsFunction::Run() {
   using api::tabs::ZoomSettings;
 
-  std::unique_ptr<tabs::SetZoomSettings::Params> params(
-      tabs::SetZoomSettings::Params::Create(*args_));
-  EXTENSION_FUNCTION_PRERUN_VALIDATE(params);
+  absl::optional<tabs::SetZoomSettings::Params> params =
+      tabs::SetZoomSettings::Params::Create(args());
+  EXTENSION_FUNCTION_VALIDATE(params);
 
   int tab_id = params->tab_id ? *params->tab_id : -1;
   content::WebContents* web_contents = GetWebContents(tab_id);
-  if (!web_contents)
-    return false;
+  if (!web_contents) {
+    return RespondNow(Error(std::move(error_)));
+  }
 
   GURL url(web_contents->GetVisibleURL());
-  if (extension()->permissions_data()->IsRestrictedUrl(url, &error_))
-    return false;
+  std::string error;
+  if (extension()->permissions_data()->IsRestrictedUrl(url, &error_)) {
+    return RespondNow(Error(std::move(error_)));
+  }
 
   // "per-origin" scope is only available in "automatic" mode.
   if (params->zoom_settings.scope == tabs::ZOOM_SETTINGS_SCOPE_PER_ORIGIN &&
       params->zoom_settings.mode != tabs::ZOOM_SETTINGS_MODE_AUTOMATIC &&
       params->zoom_settings.mode != tabs::ZOOM_SETTINGS_MODE_NONE) {
-    error_ = keys::kPerOriginOnlyInAutomaticError;
-    return false;
+    return RespondNow(Error(tabs_constants::kPerOriginOnlyInAutomaticError));
   }
 
   // Determine the correct internal zoom mode to set |web_contents| to from the
   // user-specified |zoom_settings|.
-  zoom::ZoomController::ZoomMode zoom_mode =
-      zoom::ZoomController::ZOOM_MODE_DEFAULT;
+  ZoomController::ZoomMode zoom_mode = ZoomController::ZOOM_MODE_DEFAULT;
   switch (params->zoom_settings.mode) {
     case tabs::ZOOM_SETTINGS_MODE_NONE:
     case tabs::ZOOM_SETTINGS_MODE_AUTOMATIC:
       switch (params->zoom_settings.scope) {
         case tabs::ZOOM_SETTINGS_SCOPE_NONE:
         case tabs::ZOOM_SETTINGS_SCOPE_PER_ORIGIN:
-          zoom_mode = zoom::ZoomController::ZOOM_MODE_DEFAULT;
+          zoom_mode = ZoomController::ZOOM_MODE_DEFAULT;
           break;
         case tabs::ZOOM_SETTINGS_SCOPE_PER_TAB:
-          zoom_mode = zoom::ZoomController::ZOOM_MODE_ISOLATED;
+          zoom_mode = ZoomController::ZOOM_MODE_ISOLATED;
       }
       break;
     case tabs::ZOOM_SETTINGS_MODE_MANUAL:
-      zoom_mode = zoom::ZoomController::ZOOM_MODE_MANUAL;
+      zoom_mode = ZoomController::ZOOM_MODE_MANUAL;
       break;
     case tabs::ZOOM_SETTINGS_MODE_DISABLED:
-      zoom_mode = zoom::ZoomController::ZOOM_MODE_DISABLED;
+      zoom_mode = ZoomController::ZOOM_MODE_DISABLED;
   }
 
-  zoom::ZoomController::FromWebContents(web_contents)->SetZoomMode(zoom_mode);
+  ZoomController::FromWebContents(web_contents)->SetZoomMode(zoom_mode);
 
-  SendResponse(true);
-  return true;
+  return RespondNow(NoArguments());
 }
 
-bool TabsGetZoomSettingsFunction::RunAsync() {
-  std::unique_ptr<tabs::GetZoomSettings::Params> params(
-      tabs::GetZoomSettings::Params::Create(*args_));
-  EXTENSION_FUNCTION_PRERUN_VALIDATE(params);
+ExtensionFunction::ResponseAction TabsGetZoomSettingsFunction::Run() {
+  absl::optional<tabs::GetZoomSettings::Params> params =
+      tabs::GetZoomSettings::Params::Create(args());
+  EXTENSION_FUNCTION_VALIDATE(params);
 
   int tab_id = params->tab_id ? *params->tab_id : -1;
   content::WebContents* web_contents = GetWebContents(tab_id);
-  if (!web_contents)
-    return false;
-  zoom::ZoomController* zoom_controller =
-      zoom::ZoomController::FromWebContents(web_contents);
+  if (!web_contents) {
+    return RespondNow(Error(std::move(error_)));
+  }
+  ZoomController* zoom_controller =
+      ZoomController::FromWebContents(web_contents);
 
-  zoom::ZoomController::ZoomMode zoom_mode = zoom_controller->zoom_mode();
+  ZoomController::ZoomMode zoom_mode = zoom_controller->zoom_mode();
   api::tabs::ZoomSettings zoom_settings;
   ZoomModeToZoomSettings(zoom_mode, &zoom_settings);
-  zoom_settings.default_zoom_factor.reset(
-      new double(blink::PageZoomLevelToZoomFactor(
-          zoom_controller->GetDefaultZoomLevel())));
+  zoom_settings.default_zoom_factor =
+      blink::PageZoomLevelToZoomFactor(zoom_controller->GetDefaultZoomLevel());
 
-  results_ = api::tabs::GetZoomSettings::Results::Create(zoom_settings);
-  SendResponse(true);
-  return true;
+  return RespondNow(
+      ArgumentList(api::tabs::GetZoomSettings::Results::Create(zoom_settings)));
 }
 
 }  // namespace cef
diff --git a/src/libcef/browser/extensions/api/tabs/tabs_api.h b/src/libcef/browser/extensions/api/tabs/tabs_api.h
index a195109..409d758 100644
--- a/src/libcef/browser/extensions/api/tabs/tabs_api.h
+++ b/src/libcef/browser/extensions/api/tabs/tabs_api.h
@@ -42,7 +42,38 @@
   const CefExtensionFunctionDetails cef_details_;
 };
 
-// Implement API call tabs.executeScript and tabs.insertCSS.
+class BaseAPIFunction : public ExtensionFunction {
+ public:
+  BaseAPIFunction();
+
+ protected:
+  ~BaseAPIFunction() override {}
+
+  // Gets the WebContents for |tab_id| if it is specified. Otherwise get the
+  // WebContents for the active tab in the current window. Calling this function
+  // may set |error_|.
+  content::WebContents* GetWebContents(int tab_id);
+
+  std::string error_;
+  const CefExtensionFunctionDetails cef_details_;
+};
+
+class TabsUpdateFunction : public BaseAPIFunction {
+ private:
+  ~TabsUpdateFunction() override {}
+
+  ResponseAction Run() override;
+
+  bool UpdateURL(const std::string& url, int tab_id, std::string* error);
+  ResponseValue GetResult();
+
+  DECLARE_EXTENSION_FUNCTION("tabs.update", TABS_UPDATE)
+
+  int tab_id_ = -1;
+  content::WebContents* web_contents_ = nullptr;
+};
+
+// Implement API calls tabs.executeScript, tabs.insertCSS, and tabs.removeCSS.
 class ExecuteCodeInTabFunction : public ExecuteCodeFunction {
  public:
   ExecuteCodeInTabFunction();
@@ -52,6 +83,8 @@
 
   // Initializes |execute_tab_id_| and |details_|.
   InitResult Init() override;
+  bool ShouldInsertCSS() const override;
+  bool ShouldRemoveCSS() const override;
   bool CanExecuteScriptOnPage(std::string* error) override;
   ScriptExecutor* GetScriptExecutor(std::string* error) override;
   bool IsWebView() const override;
@@ -69,9 +102,6 @@
 };
 
 class TabsExecuteScriptFunction : public ExecuteCodeInTabFunction {
- protected:
-  bool ShouldInsertCSS() const override;
-
  private:
   ~TabsExecuteScriptFunction() override {}
 
@@ -87,6 +117,15 @@
   DECLARE_EXTENSION_FUNCTION("tabs.insertCSS", TABS_INSERTCSS)
 };
 
+class TabsRemoveCSSFunction : public ExecuteCodeInTabFunction {
+ private:
+  ~TabsRemoveCSSFunction() override {}
+
+  bool ShouldRemoveCSS() const override;
+
+  DECLARE_EXTENSION_FUNCTION("tabs.removeCSS", TABS_INSERTCSS)
+};
+
 // Based on ChromeAsyncExtensionFunction.
 class ZoomAPIFunction : public ExtensionFunction {
  public:
@@ -100,58 +139,44 @@
   // may set |error_|.
   content::WebContents* GetWebContents(int tab_id);
 
-  virtual bool RunAsync() = 0;
-
-  // Responds with success/failure. |results_| or |error_| should be set
-  // accordingly.
-  void SendResponse(bool success);
-
-  // Exposed versions of ExtensionFunction::results_ and
-  // ExtensionFunction::error_ that are curried into the response.
-  // These need to keep the same name to avoid breaking existing
-  // implementations, but this should be temporary with crbug.com/648275
-  // and crbug.com/634140.
-  std::unique_ptr<base::ListValue> results_;
   std::string error_;
 
  private:
-  ResponseAction Run() final;
-
   const CefExtensionFunctionDetails cef_details_;
 };
 
-class TabsSetZoomFunction : public ZoomAPIFunction {
+class TabsSetZoomFunction : public BaseAPIFunction {
  private:
   ~TabsSetZoomFunction() override {}
 
-  bool RunAsync() override;
+  ResponseAction Run() override;
 
   DECLARE_EXTENSION_FUNCTION("tabs.setZoom", TABS_SETZOOM)
 };
 
-class TabsGetZoomFunction : public ZoomAPIFunction {
+class TabsGetZoomFunction : public BaseAPIFunction {
  private:
   ~TabsGetZoomFunction() override {}
 
-  bool RunAsync() override;
+  ResponseAction Run() override;
 
   DECLARE_EXTENSION_FUNCTION("tabs.getZoom", TABS_GETZOOM)
 };
 
-class TabsSetZoomSettingsFunction : public ZoomAPIFunction {
+class TabsSetZoomSettingsFunction : public BaseAPIFunction {
  private:
   ~TabsSetZoomSettingsFunction() override {}
 
-  bool RunAsync() override;
+  ResponseAction Run() override;
 
   DECLARE_EXTENSION_FUNCTION("tabs.setZoomSettings", TABS_SETZOOMSETTINGS)
 };
 
-class TabsGetZoomSettingsFunction : public ZoomAPIFunction {
+class TabsGetZoomSettingsFunction : public BaseAPIFunction {
  private:
   ~TabsGetZoomSettingsFunction() override {}
 
-  bool RunAsync() override;
+  ResponseAction Run() override;
 
   DECLARE_EXTENSION_FUNCTION("tabs.getZoomSettings", TABS_GETZOOMSETTINGS)
 };
diff --git a/src/libcef/browser/extensions/browser_extensions_util.cc b/src/libcef/browser/extensions/browser_extensions_util.cc
index c7ea3e1..9a780e2 100644
--- a/src/libcef/browser/extensions/browser_extensions_util.cc
+++ b/src/libcef/browser/extensions/browser_extensions_util.cc
@@ -4,18 +4,23 @@
 
 #include "libcef/browser/extensions/browser_extensions_util.h"
 
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 #include "libcef/browser/browser_context.h"
+#include "libcef/browser/browser_host_base.h"
 #include "libcef/browser/browser_info_manager.h"
 #include "libcef/browser/thread_util.h"
 #include "libcef/common/extensions/extensions_util.h"
+#include "libcef/common/frame_util.h"
+#include "libcef/features/runtime_checks.h"
 
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/printing/print_preview_dialog_controller.h"
-#include "content/browser/browser_plugin/browser_plugin_embedder.h"
 #include "content/browser/browser_plugin/browser_plugin_guest.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_plugin_guest_manager.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_view_host.h"
 #include "extensions/browser/extension_registry.h"
 
 namespace extensions {
@@ -30,27 +35,12 @@
 
 }  // namespace
 
-content::WebContents* GetFullPageGuestForOwnerContents(
-    content::WebContents* owner) {
-  content::WebContentsImpl* owner_impl =
-      static_cast<content::WebContentsImpl*>(owner);
-  content::BrowserPluginEmbedder* plugin_embedder =
-      owner_impl->GetBrowserPluginEmbedder();
-  if (plugin_embedder) {
-    content::BrowserPluginGuest* plugin_guest =
-        plugin_embedder->GetFullPageGuest();
-    if (plugin_guest)
-      return plugin_guest->web_contents();
-  }
-  return nullptr;
-}
-
 void GetAllGuestsForOwnerContents(content::WebContents* owner,
                                   std::vector<content::WebContents*>* guests) {
   content::BrowserPluginGuestManager* plugin_guest_manager =
       owner->GetBrowserContext()->GetGuestManager();
-  plugin_guest_manager->ForEachGuest(owner,
-                                     base::Bind(InsertWebContents, guests));
+  plugin_guest_manager->ForEachGuest(
+      owner, base::BindRepeating(InsertWebContents, guests));
 }
 
 content::WebContents* GetOwnerForGuestContents(content::WebContents* guest) {
@@ -59,8 +49,7 @@
   content::BrowserPluginGuest* plugin_guest =
       guest_impl->GetBrowserPluginGuest();
   if (plugin_guest) {
-    return content::WebContents::FromRenderFrameHost(
-        plugin_guest->GetEmbedderFrame());
+    return plugin_guest->owner_web_contents();
   }
 
   // Maybe it's a print preview dialog.
@@ -69,29 +58,28 @@
   return print_preview_controller->GetInitiator(guest);
 }
 
-CefRefPtr<CefBrowserHostImpl> GetOwnerBrowserForFrameRoute(
-    int render_process_id,
-    int render_routing_id,
+CefRefPtr<CefBrowserHostBase> GetOwnerBrowserForGlobalId(
+    const content::GlobalRenderFrameHostId& global_id,
     bool* is_guest_view) {
   if (CEF_CURRENTLY_ON_UIT()) {
     // Use the non-thread-safe but potentially faster approach.
     content::RenderFrameHost* host =
-        content::RenderFrameHost::FromID(render_process_id, render_routing_id);
-    if (host)
+        content::RenderFrameHost::FromID(global_id);
+    if (host) {
       return GetOwnerBrowserForHost(host, is_guest_view);
+    }
     return nullptr;
   } else {
     // Use the thread-safe approach.
     scoped_refptr<CefBrowserInfo> info =
-        CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameRoute(
-            render_process_id, render_routing_id, is_guest_view);
+        CefBrowserInfoManager::GetInstance()->GetBrowserInfo(global_id,
+                                                             is_guest_view);
     if (info.get()) {
-      CefRefPtr<CefBrowserHostImpl> browser = info->browser();
+      CefRefPtr<CefBrowserHostBase> browser = info->browser();
       if (!browser.get()) {
         LOG(WARNING) << "Found browser id " << info->browser_id()
-                     << " but no browser object matching view process id "
-                     << render_process_id << " and frame routing id "
-                     << render_routing_id;
+                     << " but no browser object matching frame "
+                     << frame_util::GetFrameDebugString(global_id);
       }
       return browser;
     }
@@ -99,66 +87,73 @@
   }
 }
 
-CefRefPtr<CefBrowserHostImpl> GetOwnerBrowserForHost(
+CefRefPtr<CefBrowserHostBase> GetOwnerBrowserForHost(
     content::RenderViewHost* host,
     bool* is_guest_view) {
-  if (is_guest_view)
+  if (is_guest_view) {
     *is_guest_view = false;
+  }
 
-  CefRefPtr<CefBrowserHostImpl> browser =
-      CefBrowserHostImpl::GetBrowserForHost(host);
+  CefRefPtr<CefBrowserHostBase> browser =
+      CefBrowserHostBase::GetBrowserForHost(host);
   if (!browser.get() && ExtensionsEnabled()) {
     // Retrieve the owner browser, if any.
     content::WebContents* owner = GetOwnerForGuestContents(
         content::WebContents::FromRenderViewHost(host));
     if (owner) {
-      browser = CefBrowserHostImpl::GetBrowserForContents(owner);
-      if (browser.get() && is_guest_view)
+      browser = CefBrowserHostBase::GetBrowserForContents(owner);
+      if (browser.get() && is_guest_view) {
         *is_guest_view = true;
+      }
     }
   }
   return browser;
 }
 
-CefRefPtr<CefBrowserHostImpl> GetOwnerBrowserForHost(
+CefRefPtr<CefBrowserHostBase> GetOwnerBrowserForHost(
     content::RenderFrameHost* host,
     bool* is_guest_view) {
-  if (is_guest_view)
+  if (is_guest_view) {
     *is_guest_view = false;
+  }
 
-  CefRefPtr<CefBrowserHostImpl> browser =
-      CefBrowserHostImpl::GetBrowserForHost(host);
+  CefRefPtr<CefBrowserHostBase> browser =
+      CefBrowserHostBase::GetBrowserForHost(host);
   if (!browser.get() && ExtensionsEnabled()) {
     // Retrieve the owner browser, if any.
     content::WebContents* owner = GetOwnerForGuestContents(
         content::WebContents::FromRenderFrameHost(host));
     if (owner) {
-      browser = CefBrowserHostImpl::GetBrowserForContents(owner);
-      if (browser.get() && is_guest_view)
+      browser = CefBrowserHostBase::GetBrowserForContents(owner);
+      if (browser.get() && is_guest_view) {
         *is_guest_view = true;
+      }
     }
   }
   return browser;
 }
 
-CefRefPtr<CefBrowserHostImpl> GetBrowserForTabId(
+CefRefPtr<AlloyBrowserHostImpl> GetBrowserForTabId(
     int tab_id,
     content::BrowserContext* browser_context) {
+  REQUIRE_ALLOY_RUNTIME();
   CEF_REQUIRE_UIT();
   DCHECK(browser_context);
-  if (tab_id < 0 || !browser_context)
+  if (tab_id < 0 || !browser_context) {
     return nullptr;
+  }
 
-  CefBrowserContext* browser_context_impl =
-      CefBrowserContext::GetForContext(browser_context);
+  auto cef_browser_context =
+      CefBrowserContext::FromBrowserContext(browser_context);
 
   for (const auto& browser_info :
        CefBrowserInfoManager::GetInstance()->GetBrowserInfoList()) {
-    CefRefPtr<CefBrowserHostImpl> current_browser = browser_info->browser();
+    CefRefPtr<AlloyBrowserHostImpl> current_browser =
+        static_cast<AlloyBrowserHostImpl*>(browser_info->browser().get());
     if (current_browser && current_browser->GetIdentifier() == tab_id) {
-      // Make sure we're operating in the same BrowserContextImpl.
-      if (CefBrowserContext::GetForContext(
-              current_browser->GetBrowserContext()) == browser_context_impl) {
+      // Make sure we're operating in the same CefBrowserContext.
+      if (CefBrowserContext::FromBrowserContext(
+              current_browser->GetBrowserContext()) == cef_browser_context) {
         return current_browser;
       } else {
         LOG(WARNING) << "Browser with tabId " << tab_id
@@ -175,8 +170,9 @@
 const Extension* GetExtensionForUrl(content::BrowserContext* browser_context,
                                     const GURL& url) {
   ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context);
-  if (!registry)
+  if (!registry) {
     return nullptr;
+  }
   std::string extension_id = url.host();
   return registry->enabled_extensions().GetByID(extension_id);
 }
diff --git a/src/libcef/browser/extensions/browser_extensions_util.h b/src/libcef/browser/extensions/browser_extensions_util.h
index a4de94b..b4adb7b 100644
--- a/src/libcef/browser/extensions/browser_extensions_util.h
+++ b/src/libcef/browser/extensions/browser_extensions_util.h
@@ -7,24 +7,25 @@
 
 #include <vector>
 
-#include "libcef/browser/browser_host_impl.h"
+#include "include/internal/cef_ptr.h"
 
 #include "url/gurl.h"
 
 namespace content {
 class BrowserContext;
+struct GlobalRenderFrameHostId;
+class RenderFrameHost;
 class RenderViewHost;
 class WebContents;
 }  // namespace content
 
+class CefBrowserHostBase;
+class AlloyBrowserHostImpl;
+
 namespace extensions {
 
 class Extension;
 
-// Returns the full-page guest WebContents for the specified |owner|, if any.
-content::WebContents* GetFullPageGuestForOwnerContents(
-    content::WebContents* owner);
-
 // Populates |guests| with all guest WebContents with the specified |owner|.
 void GetAllGuestsForOwnerContents(content::WebContents* owner,
                                   std::vector<content::WebContents*>* guests);
@@ -32,31 +33,30 @@
 // Returns the WebContents that owns the specified |guest|, if any.
 content::WebContents* GetOwnerForGuestContents(content::WebContents* guest);
 
-// Returns the CefBrowserHostImpl that owns the host identified by the specified
-// routing IDs, if any. |is_guest_view| will be set to true if the IDs
-// match a guest view associated with the returned browser instead of the
+// Returns the CefBrowserHostBase that owns the host identified by the specified
+// global ID, if any. |is_guest_view| will be set to true if the ID
+// matches a guest view associated with the returned browser instead of the
 // browser itself.
-CefRefPtr<CefBrowserHostImpl> GetOwnerBrowserForFrameRoute(
-    int render_process_id,
-    int render_routing_id,
+CefRefPtr<CefBrowserHostBase> GetOwnerBrowserForGlobalId(
+    const content::GlobalRenderFrameHostId& global_id,
     bool* is_guest_view);
 
-// Returns the CefBrowserHostImpl that owns the specified |host|, if any.
+// Returns the CefBrowserHostBase that owns the specified |host|, if any.
 // |is_guest_view| will be set to true if the host matches a guest view
 // associated with the returned browser instead of the browser itself.
 // TODO(cef): Delete the RVH variant once the remaining use case
-// (via CefContentBrowserClient::OverrideWebkitPrefs) has been removed.
-CefRefPtr<CefBrowserHostImpl> GetOwnerBrowserForHost(
+// (via AlloyContentBrowserClient::OverrideWebkitPrefs) has been removed.
+CefRefPtr<CefBrowserHostBase> GetOwnerBrowserForHost(
     content::RenderViewHost* host,
     bool* is_guest_view);
-CefRefPtr<CefBrowserHostImpl> GetOwnerBrowserForHost(
+CefRefPtr<CefBrowserHostBase> GetOwnerBrowserForHost(
     content::RenderFrameHost* host,
     bool* is_guest_view);
 
 // Returns the browser matching |tab_id| and |browser_context|. Returns false if
 // |tab_id| is < 0 or a matching browser cannot be found within
 // |browser_context|. Similar in concept to ExtensionTabUtil::GetTabById.
-CefRefPtr<CefBrowserHostImpl> GetBrowserForTabId(
+CefRefPtr<AlloyBrowserHostImpl> GetBrowserForTabId(
     int tab_id,
     content::BrowserContext* browser_context);
 
diff --git a/src/libcef/browser/extensions/browser_platform_delegate_background.cc b/src/libcef/browser/extensions/browser_platform_delegate_background.cc
index ac542b9..949f347 100644
--- a/src/libcef/browser/extensions/browser_platform_delegate_background.cc
+++ b/src/libcef/browser/extensions/browser_platform_delegate_background.cc
@@ -6,8 +6,9 @@
 
 #include <utility>
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 #include "libcef/browser/thread_util.h"
+#include "libcef/features/runtime_checks.h"
 
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
@@ -15,6 +16,7 @@
 CefBrowserPlatformDelegateBackground::CefBrowserPlatformDelegateBackground(
     std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate)
     : native_delegate_(std::move(native_delegate)) {
+  REQUIRE_ALLOY_RUNTIME();
   native_delegate_->set_windowless_handler(this);
 }
 
@@ -27,7 +29,8 @@
   // No host window, so continue browser destruction now. Do it asynchronously
   // so the call stack has a chance to unwind.
   CEF_POST_TASK(CEF_UIT,
-                base::Bind(&CefBrowserHostImpl::WindowDestroyed, browser_));
+                base::BindOnce(&AlloyBrowserHostImpl::WindowDestroyed,
+                               static_cast<AlloyBrowserHostImpl*>(browser_)));
 }
 
 CefWindowHandle CefBrowserPlatformDelegateBackground::GetHostWindowHandle()
@@ -35,14 +38,6 @@
   return kNullWindowHandle;
 }
 
-bool CefBrowserPlatformDelegateBackground::CanUseSharedTexture() const {
-  return native_delegate_->CanUseSharedTexture();
-}
-
-bool CefBrowserPlatformDelegateBackground::CanUseExternalBeginFrame() const {
-  return native_delegate_->CanUseExternalBeginFrame();
-}
-
 SkColor CefBrowserPlatformDelegateBackground::GetBackgroundColor() const {
   return native_delegate_->GetBackgroundColor();
 }
@@ -82,12 +77,13 @@
   // Nothing to do here.
 }
 
-void CefBrowserPlatformDelegateBackground::SendFocusEvent(bool setFocus) {
+void CefBrowserPlatformDelegateBackground::SetFocus(bool setFocus) {
   // Nothing to do here.
 }
 
 gfx::Point CefBrowserPlatformDelegateBackground::GetScreenPoint(
-    const gfx::Point& view_pt) const {
+    const gfx::Point& view_pt,
+    bool want_dip_coords) const {
   // Nothing to do here.
   return view_pt;
 }
@@ -107,36 +103,19 @@
   return native_delegate_->GetEventHandle(event);
 }
 
-std::unique_ptr<CefFileDialogRunner>
-CefBrowserPlatformDelegateBackground::CreateFileDialogRunner() {
-  return native_delegate_->CreateFileDialogRunner();
-}
-
-std::unique_ptr<CefJavaScriptDialogRunner>
-CefBrowserPlatformDelegateBackground::CreateJavaScriptDialogRunner() {
-  return native_delegate_->CreateJavaScriptDialogRunner();
-}
-
 std::unique_ptr<CefMenuRunner>
 CefBrowserPlatformDelegateBackground::CreateMenuRunner() {
   // No default menu implementation for background browsers.
   return nullptr;
 }
 
-bool CefBrowserPlatformDelegateBackground::IsWindowless() const {
-  return false;
-}
-
-bool CefBrowserPlatformDelegateBackground::IsViewsHosted() const {
-  return false;
-}
-
 CefWindowHandle CefBrowserPlatformDelegateBackground::GetParentWindowHandle()
     const {
   return GetHostWindowHandle();
 }
 
 gfx::Point CefBrowserPlatformDelegateBackground::GetParentScreenPoint(
-    const gfx::Point& view) const {
-  return GetScreenPoint(view);
+    const gfx::Point& view,
+    bool want_dip_coords) const {
+  return GetScreenPoint(view, want_dip_coords);
 }
diff --git a/src/libcef/browser/extensions/browser_platform_delegate_background.h b/src/libcef/browser/extensions/browser_platform_delegate_background.h
index 2ded373..39ae59f 100644
--- a/src/libcef/browser/extensions/browser_platform_delegate_background.h
+++ b/src/libcef/browser/extensions/browser_platform_delegate_background.h
@@ -5,12 +5,12 @@
 #ifndef CEF_LIBCEF_BROWSER_VIEWS_BROWSER_PLATFORM_DELEGATE_BACKGROUND_H_
 #define CEF_LIBCEF_BROWSER_VIEWS_BROWSER_PLATFORM_DELEGATE_BACKGROUND_H_
 
-#include "libcef/browser/browser_platform_delegate.h"
+#include "libcef/browser/alloy/browser_platform_delegate_alloy.h"
 #include "libcef/browser/native/browser_platform_delegate_native.h"
 
 // Implementation of browser functionality for background script hosts.
 class CefBrowserPlatformDelegateBackground
-    : public CefBrowserPlatformDelegate,
+    : public CefBrowserPlatformDelegateAlloy,
       public CefBrowserPlatformDelegateNative::WindowlessHandler {
  public:
   // Platform-specific behaviors will be delegated to |native_delegate|.
@@ -22,8 +22,6 @@
   void CloseHostWindow() override;
   CefWindowHandle GetHostWindowHandle() const override;
   SkColor GetBackgroundColor() const override;
-  bool CanUseSharedTexture() const override;
-  bool CanUseExternalBeginFrame() const override;
   void WasResized() override;
   void SendKeyEvent(const CefKeyEvent& event) override;
   void SendMouseClickEvent(const CefMouseEvent& event,
@@ -35,23 +33,20 @@
                            int deltaX,
                            int deltaY) override;
   void SendTouchEvent(const CefTouchEvent& event) override;
-  void SendFocusEvent(bool setFocus) override;
-  gfx::Point GetScreenPoint(const gfx::Point& view) const override;
+  void SetFocus(bool setFocus) override;
+  gfx::Point GetScreenPoint(const gfx::Point& view,
+                            bool want_dip_coords) const override;
   void ViewText(const std::string& text) override;
   bool HandleKeyboardEvent(
       const content::NativeWebKeyboardEvent& event) override;
   CefEventHandle GetEventHandle(
       const content::NativeWebKeyboardEvent& event) const override;
-  std::unique_ptr<CefFileDialogRunner> CreateFileDialogRunner() override;
-  std::unique_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner()
-      override;
   std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
-  bool IsWindowless() const override;
-  bool IsViewsHosted() const override;
 
   // CefBrowserPlatformDelegateNative::WindowlessHandler methods:
   CefWindowHandle GetParentWindowHandle() const override;
-  gfx::Point GetParentScreenPoint(const gfx::Point& view) const override;
+  gfx::Point GetParentScreenPoint(const gfx::Point& view,
+                                  bool want_dip_coords) const override;
 
  private:
   std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate_;
diff --git a/src/libcef/browser/extensions/chrome_api_registration.cc b/src/libcef/browser/extensions/chrome_api_registration.cc
index c082818..60c6153 100644
--- a/src/libcef/browser/extensions/chrome_api_registration.cc
+++ b/src/libcef/browser/extensions/chrome_api_registration.cc
@@ -12,6 +12,7 @@
 #include "libcef/browser/extensions/api/tabs/tabs_api.h"
 
 #include "chrome/browser/extensions/api/content_settings/content_settings_api.h"
+#include "chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api.h"
 #include "chrome/browser/extensions/api/resources_private/resources_private_api.h"
 #include "extensions/browser/api/alarms/alarms_api.h"
 #include "extensions/browser/api/storage/storage_api.h"
@@ -23,13 +24,11 @@
 
 namespace cefimpl = extensions::cef;
 
-#define EXTENSION_FUNCTION_NAME(classname) classname::function_name()
+#define EXTENSION_FUNCTION_NAME(classname) classname::static_function_name()
 
 // Maintain the same order as https://developer.chrome.com/extensions/api_index
 // so chrome://extensions-support looks nice.
 const char* const kSupportedAPIs[] = {
-    "resourcesPrivate",
-    EXTENSION_FUNCTION_NAME(ResourcesPrivateGetStringsFunction),
     "alarms",
     EXTENSION_FUNCTION_NAME(AlarmsCreateFunction),
     EXTENSION_FUNCTION_NAME(AlarmsGetFunction),
@@ -42,6 +41,11 @@
     EXTENSION_FUNCTION_NAME(ContentSettingsContentSettingSetFunction),
     EXTENSION_FUNCTION_NAME(
         ContentSettingsContentSettingGetResourceIdentifiersFunction),
+    "pdfViewerPrivate",
+    EXTENSION_FUNCTION_NAME(PdfViewerPrivateIsAllowedLocalFileAccessFunction),
+    EXTENSION_FUNCTION_NAME(PdfViewerPrivateIsPdfOcrAlwaysActiveFunction),
+    "resourcesPrivate",
+    EXTENSION_FUNCTION_NAME(ResourcesPrivateGetStringsFunction),
     "storage",
     EXTENSION_FUNCTION_NAME(StorageStorageAreaGetFunction),
     EXTENSION_FUNCTION_NAME(StorageStorageAreaSetFunction),
@@ -51,8 +55,10 @@
     "tabs",
     EXTENSION_FUNCTION_NAME(cefimpl::TabsGetFunction),
     EXTENSION_FUNCTION_NAME(cefimpl::TabsCreateFunction),
+    EXTENSION_FUNCTION_NAME(cefimpl::TabsUpdateFunction),
     EXTENSION_FUNCTION_NAME(cefimpl::TabsExecuteScriptFunction),
     EXTENSION_FUNCTION_NAME(cefimpl::TabsInsertCSSFunction),
+    EXTENSION_FUNCTION_NAME(cefimpl::TabsRemoveCSSFunction),
     EXTENSION_FUNCTION_NAME(cefimpl::TabsSetZoomFunction),
     EXTENSION_FUNCTION_NAME(cefimpl::TabsGetZoomFunction),
     EXTENSION_FUNCTION_NAME(cefimpl::TabsSetZoomSettingsFunction),
@@ -64,8 +70,9 @@
 // static
 bool ChromeFunctionRegistry::IsSupported(const std::string& name) {
   for (size_t i = 0; kSupportedAPIs[i] != nullptr; ++i) {
-    if (name == kSupportedAPIs[i])
+    if (name == kSupportedAPIs[i]) {
       return true;
+    }
   }
   return false;
 }
@@ -73,7 +80,6 @@
 // Only add APIs to this list that have been tested in CEF.
 // static
 void ChromeFunctionRegistry::RegisterAll(ExtensionFunctionRegistry* registry) {
-  registry->RegisterFunction<ResourcesPrivateGetStringsFunction>();
   registry->RegisterFunction<AlarmsCreateFunction>();
   registry->RegisterFunction<AlarmsGetFunction>();
   registry->RegisterFunction<AlarmsGetAllFunction>();
@@ -84,6 +90,10 @@
   registry->RegisterFunction<ContentSettingsContentSettingSetFunction>();
   registry->RegisterFunction<
       ContentSettingsContentSettingGetResourceIdentifiersFunction>();
+  registry
+      ->RegisterFunction<PdfViewerPrivateIsAllowedLocalFileAccessFunction>();
+  registry->RegisterFunction<PdfViewerPrivateIsPdfOcrAlwaysActiveFunction>();
+  registry->RegisterFunction<ResourcesPrivateGetStringsFunction>();
   registry->RegisterFunction<StorageStorageAreaGetFunction>();
   registry->RegisterFunction<StorageStorageAreaSetFunction>();
   registry->RegisterFunction<StorageStorageAreaRemoveFunction>();
@@ -91,8 +101,10 @@
   registry->RegisterFunction<StorageStorageAreaGetBytesInUseFunction>();
   registry->RegisterFunction<cefimpl::TabsExecuteScriptFunction>();
   registry->RegisterFunction<cefimpl::TabsInsertCSSFunction>();
+  registry->RegisterFunction<cefimpl::TabsRemoveCSSFunction>();
   registry->RegisterFunction<cefimpl::TabsGetFunction>();
   registry->RegisterFunction<cefimpl::TabsCreateFunction>();
+  registry->RegisterFunction<cefimpl::TabsUpdateFunction>();
   registry->RegisterFunction<cefimpl::TabsSetZoomFunction>();
   registry->RegisterFunction<cefimpl::TabsGetZoomFunction>();
   registry->RegisterFunction<cefimpl::TabsSetZoomSettingsFunction>();
diff --git a/src/libcef/browser/extensions/component_extension_resource_manager.cc b/src/libcef/browser/extensions/component_extension_resource_manager.cc
index c76e867..c7a3af0 100644
--- a/src/libcef/browser/extensions/component_extension_resource_manager.cc
+++ b/src/libcef/browser/extensions/component_extension_resource_manager.cc
@@ -4,16 +4,33 @@
 
 #include "libcef/browser/extensions/component_extension_resource_manager.h"
 
+#include "base/containers/contains.h"
 #include "base/logging.h"
 #include "base/path_service.h"
+#include "base/values.h"
+#include "chrome/browser/pdf/pdf_extension_util.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/grit/component_extension_resources_map.h"
+#include "chrome/grit/pdf_resources_map.h"
+#include "extensions/common/constants.h"
 
 namespace extensions {
 
 CefComponentExtensionResourceManager::CefComponentExtensionResourceManager() {
   AddComponentResourceEntries(kComponentExtensionResources,
                               kComponentExtensionResourcesSize);
+  AddComponentResourceEntries(kPdfResources, kPdfResourcesSize);
+
+  base::Value::Dict dict;
+  pdf_extension_util::AddStrings(
+      pdf_extension_util::PdfViewerContext::kPdfViewer, &dict);
+  pdf_extension_util::AddAdditionalData(/*enable_printing=*/true,
+                                        /*enable_annotations=*/true, &dict);
+
+  ui::TemplateReplacements pdf_viewer_replacements;
+  ui::TemplateReplacementsFromDictionaryValue(dict, &pdf_viewer_replacements);
+  template_replacements_[extension_misc::kPdfExtensionId] =
+      std::move(pdf_viewer_replacements);
 }
 
 CefComponentExtensionResourceManager::~CefComponentExtensionResourceManager() {}
@@ -44,34 +61,20 @@
 const ui::TemplateReplacements*
 CefComponentExtensionResourceManager::GetTemplateReplacementsForExtension(
     const std::string& extension_id) const {
-  return nullptr;
+  auto it = template_replacements_.find(extension_id);
+  return it != template_replacements_.end() ? &it->second : nullptr;
 }
 
 void CefComponentExtensionResourceManager::AddComponentResourceEntries(
-    const GritResourceMap* entries,
+    const webui::ResourcePath* entries,
     size_t size) {
-  base::FilePath gen_folder_path = base::FilePath().AppendASCII(
-      "@out_folder@/gen/chrome/browser/resources/");
-  gen_folder_path = gen_folder_path.NormalizePathSeparators();
-
   for (size_t i = 0; i < size; ++i) {
     base::FilePath resource_path =
-        base::FilePath().AppendASCII(entries[i].name);
+        base::FilePath().AppendASCII(entries[i].path);
     resource_path = resource_path.NormalizePathSeparators();
 
-    if (!gen_folder_path.IsParent(resource_path)) {
-      DCHECK(!base::Contains(path_to_resource_info_, resource_path));
-      path_to_resource_info_[resource_path] = entries[i].value;
-    } else {
-      // If the resource is a generated file, strip the generated folder's path,
-      // so that it can be served from a normal URL (as if it were not
-      // generated).
-      base::FilePath effective_path =
-          base::FilePath().AppendASCII(resource_path.AsUTF8Unsafe().substr(
-              gen_folder_path.value().length()));
-      DCHECK(!base::Contains(path_to_resource_info_, effective_path));
-      path_to_resource_info_[effective_path] = entries[i].value;
-    }
+    DCHECK(!base::Contains(path_to_resource_info_, resource_path));
+    path_to_resource_info_[resource_path] = entries[i].id;
   }
 }
 
diff --git a/src/libcef/browser/extensions/component_extension_resource_manager.h b/src/libcef/browser/extensions/component_extension_resource_manager.h
index 9f29af9..d541d9c 100644
--- a/src/libcef/browser/extensions/component_extension_resource_manager.h
+++ b/src/libcef/browser/extensions/component_extension_resource_manager.h
@@ -10,7 +10,9 @@
 #include "base/files/file_path.h"
 #include "extensions/browser/component_extension_resource_manager.h"
 
-struct GritResourceMap;
+namespace webui {
+struct ResourcePath;
+}
 
 namespace extensions {
 
@@ -18,6 +20,12 @@
     : public ComponentExtensionResourceManager {
  public:
   CefComponentExtensionResourceManager();
+
+  CefComponentExtensionResourceManager(
+      const CefComponentExtensionResourceManager&) = delete;
+  CefComponentExtensionResourceManager& operator=(
+      const CefComponentExtensionResourceManager&) = delete;
+
   ~CefComponentExtensionResourceManager() override;
 
   // Overridden from ComponentExtensionResourceManager:
@@ -28,13 +36,17 @@
       const std::string& extension_id) const override;
 
  private:
-  void AddComponentResourceEntries(const GritResourceMap* entries, size_t size);
+  void AddComponentResourceEntries(const webui::ResourcePath* entries,
+                                   size_t size);
 
   // A map from a resource path to the resource ID.  Used by
   // IsComponentExtensionResource.
   std::map<base::FilePath, int> path_to_resource_info_;
 
-  DISALLOW_COPY_AND_ASSIGN(CefComponentExtensionResourceManager);
+  // A map from an extension ID to its i18n template replacements.
+  using TemplateReplacementMap =
+      std::map<std::string, ui::TemplateReplacements>;
+  TemplateReplacementMap template_replacements_;
 };
 
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/extension_background_host.cc b/src/libcef/browser/extensions/extension_background_host.cc
index 2f5cbc8..37fe38b 100644
--- a/src/libcef/browser/extensions/extension_background_host.cc
+++ b/src/libcef/browser/extensions/extension_background_host.cc
@@ -4,24 +4,23 @@
 
 #include "libcef/browser/extensions/extension_background_host.h"
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 #include "libcef/browser/extensions/extension_host_delegate.h"
 
-#include "base/callback.h"
+#include "base/functional/callback.h"
 
 namespace extensions {
 
 CefExtensionBackgroundHost::CefExtensionBackgroundHost(
-    CefBrowserHostImpl* browser,
+    AlloyBrowserHostImpl* browser,
     base::OnceClosure deleted_callback,
     const Extension* extension,
-    content::BrowserContext* browser_context,
     content::WebContents* host_contents,
     const GURL& url,
-    ViewType host_type)
+    mojom::ViewType host_type)
     : ExtensionHost(new CefExtensionHostDelegate(browser),
                     extension,
-                    browser_context,
+                    host_contents->GetBrowserContext(),
                     host_contents,
                     url,
                     host_type),
@@ -29,15 +28,16 @@
   DCHECK(!deleted_callback_.is_null());
 
   // Only used for background pages.
-  DCHECK(host_type == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
+  DCHECK(host_type == mojom::ViewType::kExtensionBackgroundPage);
 }
 
 CefExtensionBackgroundHost::~CefExtensionBackgroundHost() {
   std::move(deleted_callback_).Run();
 }
 
-bool CefExtensionBackgroundHost::ShouldTransferNavigation(
-    bool is_main_frame_navigation) {
+bool CefExtensionBackgroundHost::
+    ShouldAllowRendererInitiatedCrossProcessNavigation(
+        bool is_main_frame_navigation) {
   // Block navigations that cause the main frame to navigate to non-extension
   // content (i.e. to web content).
   return !is_main_frame_navigation;
diff --git a/src/libcef/browser/extensions/extension_background_host.h b/src/libcef/browser/extensions/extension_background_host.h
index bdefe81..ed7f6c8 100644
--- a/src/libcef/browser/extensions/extension_background_host.h
+++ b/src/libcef/browser/extensions/extension_background_host.h
@@ -7,11 +7,10 @@
 
 #include <memory>
 
-#include "base/callback_forward.h"
-#include "base/macros.h"
+#include "base/functional/callback_forward.h"
 #include "extensions/browser/extension_host.h"
 
-class CefBrowserHostImpl;
+class AlloyBrowserHostImpl;
 
 namespace content {
 class WebContents;
@@ -24,23 +23,26 @@
 // is managed by ProcessManager.
 class CefExtensionBackgroundHost : public ExtensionHost {
  public:
-  CefExtensionBackgroundHost(CefBrowserHostImpl* browser,
+  CefExtensionBackgroundHost(AlloyBrowserHostImpl* browser,
                              base::OnceClosure deleted_callback,
                              const Extension* extension,
-                             content::BrowserContext* browser_context,
                              content::WebContents* host_contents,
                              const GURL& url,
-                             ViewType host_type);
+                             mojom::ViewType host_type);
+
+  CefExtensionBackgroundHost(const CefExtensionBackgroundHost&) = delete;
+  CefExtensionBackgroundHost& operator=(const CefExtensionBackgroundHost&) =
+      delete;
+
   ~CefExtensionBackgroundHost() override;
 
   // content::WebContentsDelegate methods:
-  bool ShouldTransferNavigation(bool is_main_frame_navigation) override;
+  bool ShouldAllowRendererInitiatedCrossProcessNavigation(
+      bool is_main_frame_navigation) override;
 
  private:
   // Callback that will be executed on host deletion.
   base::OnceClosure deleted_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefExtensionBackgroundHost);
 };
 
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/extension_function_details.cc b/src/libcef/browser/extensions/extension_function_details.cc
index 9ae9fe4..28351ca 100644
--- a/src/libcef/browser/extensions/extension_function_details.cc
+++ b/src/libcef/browser/extensions/extension_function_details.cc
@@ -7,11 +7,10 @@
 #include "libcef/browser/browser_context.h"
 #include "libcef/browser/extensions/browser_extensions_util.h"
 #include "libcef/browser/extensions/extension_system.h"
-#include "libcef/browser/navigate_params.h"
 #include "libcef/browser/thread_util.h"
 
 #include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
 #include "chrome/browser/extensions/extension_tab_util.h"
 #include "chrome/browser/profiles/profile.h"
@@ -38,6 +37,11 @@
       CefExtensionFunctionDetails::LoadFileCallback callback)
       : file_(file), callback_(std::move(callback)) {}
 
+  CefGetExtensionLoadFileCallbackImpl(
+      const CefGetExtensionLoadFileCallbackImpl&) = delete;
+  CefGetExtensionLoadFileCallbackImpl& operator=(
+      const CefGetExtensionLoadFileCallbackImpl&) = delete;
+
   ~CefGetExtensionLoadFileCallbackImpl() {
     if (!callback_.is_null()) {
       // The callback is still pending. Cancel it now.
@@ -81,10 +85,9 @@
       return;
     }
 
-    base::PostTaskAndReplyWithResult(
+    base::ThreadPool::PostTaskAndReplyWithResult(
         FROM_HERE,
-        {base::ThreadPool(), base::MayBlock(),
-         base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+        {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
         base::BindOnce(LoadFileFromStream, file, stream), std::move(callback));
   }
 
@@ -95,7 +98,7 @@
 
     // Move to the end of the stream.
     stream->Seek(0, SEEK_END);
-    const int64 size = stream->Tell();
+    const int64_t size = stream->Tell();
     if (size == 0) {
       LOG(WARNING) << "Extension resource " << file << " is empty.";
       return nullptr;
@@ -108,7 +111,7 @@
     stream->Seek(0, SEEK_SET);
 
     // Read all stream contents into the string.
-    int64 read, offset = 0;
+    int64_t read, offset = 0;
     do {
       read =
           static_cast<int>(stream->Read(&(*result)[offset], 1, size - offset));
@@ -128,7 +131,6 @@
   CefExtensionFunctionDetails::LoadFileCallback callback_;
 
   IMPLEMENT_REFCOUNTING(CefGetExtensionLoadFileCallbackImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefGetExtensionLoadFileCallbackImpl);
 };
 
 }  // namespace
@@ -143,18 +145,19 @@
   return Profile::FromBrowserContext(function_->browser_context());
 }
 
-CefRefPtr<CefBrowserHostImpl> CefExtensionFunctionDetails::GetSenderBrowser()
+CefRefPtr<AlloyBrowserHostImpl> CefExtensionFunctionDetails::GetSenderBrowser()
     const {
   content::WebContents* web_contents = function_->GetSenderWebContents();
-  if (web_contents)
-    return CefBrowserHostImpl::GetBrowserForContents(web_contents);
+  if (web_contents) {
+    return AlloyBrowserHostImpl::GetBrowserForContents(web_contents);
+  }
   return nullptr;
 }
 
-CefRefPtr<CefBrowserHostImpl> CefExtensionFunctionDetails::GetCurrentBrowser()
+CefRefPtr<AlloyBrowserHostImpl> CefExtensionFunctionDetails::GetCurrentBrowser()
     const {
   // Start with the browser hosting the extension.
-  CefRefPtr<CefBrowserHostImpl> browser = GetSenderBrowser();
+  CefRefPtr<AlloyBrowserHostImpl> browser = GetSenderBrowser();
   if (browser && browser->client()) {
     CefRefPtr<CefExtensionHandler> handler = GetCefExtension()->GetHandler();
     if (handler) {
@@ -163,12 +166,13 @@
           handler->GetActiveBrowser(GetCefExtension(), browser.get(),
                                     function_->include_incognito_information());
       if (active_browser && active_browser != browser) {
-        CefRefPtr<CefBrowserHostImpl> active_browser_impl =
-            static_cast<CefBrowserHostImpl*>(active_browser.get());
+        CefRefPtr<AlloyBrowserHostImpl> active_browser_impl =
+            static_cast<AlloyBrowserHostImpl*>(active_browser.get());
 
-        // Make sure we're operating in the same BrowserContextImpl.
-        if (CefBrowserContext::GetForContext(browser->GetBrowserContext()) ==
-            CefBrowserContext::GetForContext(
+        // Make sure we're operating in the same CefBrowserContext.
+        if (CefBrowserContext::FromBrowserContext(
+                browser->GetBrowserContext()) ==
+            CefBrowserContext::FromBrowserContext(
                 active_browser_impl->GetBrowserContext())) {
           browser = active_browser_impl;
         } else {
@@ -186,11 +190,11 @@
 }
 
 bool CefExtensionFunctionDetails::CanAccessBrowser(
-    CefRefPtr<CefBrowserHostImpl> target) const {
+    CefRefPtr<AlloyBrowserHostImpl> target) const {
   DCHECK(target);
 
   // Start with the browser hosting the extension.
-  CefRefPtr<CefBrowserHostImpl> browser = GetSenderBrowser();
+  CefRefPtr<AlloyBrowserHostImpl> browser = GetSenderBrowser();
   if (browser == target) {
     // A sender can always access itself.
     return true;
@@ -209,14 +213,14 @@
   return true;
 }
 
-CefRefPtr<CefBrowserHostImpl>
+CefRefPtr<AlloyBrowserHostImpl>
 CefExtensionFunctionDetails::GetBrowserForTabIdFirstTime(
     int tab_id,
     std::string* error_message) const {
   DCHECK(!get_browser_called_first_time_);
   get_browser_called_first_time_ = true;
 
-  CefRefPtr<CefBrowserHostImpl> browser;
+  CefRefPtr<AlloyBrowserHostImpl> browser;
 
   if (tab_id >= 0) {
     // May be an invalid tabId or in the wrong BrowserContext.
@@ -242,7 +246,7 @@
   return browser;
 }
 
-CefRefPtr<CefBrowserHostImpl>
+CefRefPtr<AlloyBrowserHostImpl>
 CefExtensionFunctionDetails::GetBrowserForTabIdAgain(
     int tab_id,
     std::string* error_message) const {
@@ -250,7 +254,7 @@
   DCHECK(get_browser_called_first_time_);
 
   // May return NULL during shutdown.
-  CefRefPtr<CefBrowserHostImpl> browser =
+  CefRefPtr<AlloyBrowserHostImpl> browser =
       GetBrowserForTabId(tab_id, function_->browser_context());
   if (!browser || !browser->web_contents()) {
     if (error_message) {
@@ -264,7 +268,7 @@
 bool CefExtensionFunctionDetails::LoadFile(const std::string& file,
                                            LoadFileCallback callback) const {
   // Start with the browser hosting the extension.
-  CefRefPtr<CefBrowserHostImpl> browser = GetSenderBrowser();
+  CefRefPtr<AlloyBrowserHostImpl> browser = GetSenderBrowser();
   if (browser && browser->client()) {
     CefRefPtr<CefExtensionHandler> handler = GetCefExtension()->GetHandler();
     if (handler) {
@@ -285,29 +289,32 @@
 
 CefExtensionFunctionDetails::OpenTabParams::~OpenTabParams() {}
 
-base::DictionaryValue* CefExtensionFunctionDetails::OpenTab(
+std::unique_ptr<api::tabs::Tab> CefExtensionFunctionDetails::OpenTab(
     const OpenTabParams& params,
     bool user_gesture,
     std::string* error_message) const {
-  CefRefPtr<CefBrowserHostImpl> sender_browser = GetSenderBrowser();
-  if (!sender_browser)
+  CefRefPtr<AlloyBrowserHostImpl> sender_browser = GetSenderBrowser();
+  if (!sender_browser) {
     return nullptr;
+  }
 
   // windowId defaults to "current" window.
   int window_id = extension_misc::kCurrentWindowId;
-  if (params.window_id.get())
+  if (params.window_id.has_value()) {
     window_id = *params.window_id;
+  }
 
   // CEF doesn't have the concept of windows containing tab strips so we'll
   // select an "active browser" for BrowserContext sharing instead.
-  CefRefPtr<CefBrowserHostImpl> active_browser =
+  CefRefPtr<AlloyBrowserHostImpl> active_browser =
       GetBrowserForTabIdFirstTime(window_id, error_message);
-  if (!active_browser)
+  if (!active_browser) {
     return nullptr;
+  }
 
   // If an opener browser was specified then we expect it to exist.
   int opener_browser_id = -1;
-  if (params.opener_tab_id.get() && *params.opener_tab_id >= 0) {
+  if (params.opener_tab_id.has_value() && *params.opener_tab_id >= 0) {
     if (GetBrowserForTabIdAgain(*params.opener_tab_id, error_message)) {
       opener_browser_id = *params.opener_tab_id;
     } else {
@@ -316,61 +323,55 @@
   }
 
   GURL url;
-  if (params.url.get()) {
-    std::string url_string = *params.url;
-    url = ExtensionTabUtil::ResolvePossiblyRelativeURL(url_string,
-                                                       function()->extension());
-    if (!url.is_valid()) {
-      if (error_message) {
-        *error_message =
-            ErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, url_string);
-      }
+  if (params.url.has_value()) {
+    auto url_expected = ExtensionTabUtil::PrepareURLForNavigation(
+        *params.url, function()->extension(), function()->browser_context());
+    if (url_expected.has_value()) {
+      url = *url_expected;
+    } else {
+      *error_message = std::move(url_expected.error());
       return nullptr;
     }
   }
 
-  // Don't let extensions crash the browser or renderers.
-  if (ExtensionTabUtil::IsKillURL(url)) {
-    if (error_message)
-      *error_message = keys::kNoCrashBrowserError;
-    return nullptr;
-  }
-
   // Default to foreground for the new tab. The presence of 'active' property
   // will override this default.
   bool active = true;
-  if (params.active.get())
+  if (params.active.has_value()) {
     active = *params.active;
+  }
 
   // CEF doesn't use the index value but we let the client see/modify it.
   int index = 0;
-  if (params.index.get())
+  if (params.index.has_value()) {
     index = *params.index;
+  }
 
-  CefBrowserContext* browser_context_impl =
-      CefBrowserContext::GetForContext(active_browser->GetBrowserContext());
+  auto cef_browser_context = CefBrowserContext::FromBrowserContext(
+      active_browser->GetBrowserContext());
 
   // A CEF representation should always exist.
   CefRefPtr<CefExtension> cef_extension =
-      browser_context_impl->extension_system()->GetExtension(
-          function()->extension()->id());
+      cef_browser_context->GetExtension(function()->extension()->id());
   DCHECK(cef_extension);
-  if (!cef_extension)
+  if (!cef_extension) {
     return nullptr;
+  }
 
   // Always use the same request context that the extension was registered with.
   // GetLoaderContext() will return NULL for internal extensions.
   CefRefPtr<CefRequestContext> request_context =
       cef_extension->GetLoaderContext();
-  if (!request_context)
+  if (!request_context) {
     return nullptr;
+  }
 
-  CefBrowserHostImpl::CreateParams create_params;
-  create_params.url = url;
+  CefBrowserCreateParams create_params;
+  create_params.url = url.spec();
   create_params.request_context = request_context;
   create_params.window_info.reset(new CefWindowInfo);
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   create_params.window_info->SetAsPopup(nullptr, CefString());
 #endif
 
@@ -379,25 +380,27 @@
   create_params.settings = active_browser->settings();
 
   CefRefPtr<CefExtensionHandler> handler = cef_extension->GetHandler();
-  if (handler.get() &&
+  if (handler &&
       handler->OnBeforeBrowser(cef_extension, sender_browser.get(),
-                               active_browser.get(), index, url.spec(), active,
-                               *create_params.window_info, create_params.client,
-                               create_params.settings)) {
+                               active_browser.get(), index, create_params.url,
+                               active, *create_params.window_info,
+                               create_params.client, create_params.settings)) {
     // Cancel the browser creation.
     return nullptr;
   }
 
-  if (active_browser->IsViewsHosted()) {
+  if (active_browser->is_views_hosted()) {
     // The new browser will also be Views hosted.
+    create_params.popup_with_views_hosted_opener = true;
     create_params.window_info.reset();
   }
 
   // Browser creation may fail under certain rare circumstances.
-  CefRefPtr<CefBrowserHostImpl> new_browser =
-      CefBrowserHostImpl::Create(create_params);
-  if (!new_browser)
+  CefRefPtr<AlloyBrowserHostImpl> new_browser =
+      AlloyBrowserHostImpl::Create(create_params);
+  if (!new_browser) {
     return nullptr;
+  }
 
   // Return data about the newly created tab.
   auto extension = function()->extension();
@@ -406,68 +409,66 @@
   auto scrub_tab_behavior = ExtensionTabUtil::GetScrubTabBehavior(
       extension, extensions::Feature::Context::UNSPECIFIED_CONTEXT,
       web_contents);
-  ExtensionTabUtil::ScrubTabForExtension(extension, web_contents, result.get(),
+  ExtensionTabUtil::ScrubTabForExtension(extension, web_contents, &result,
                                          scrub_tab_behavior);
-  return result->ToValue().release();
+  return base::WrapUnique(new api::tabs::Tab(std::move(result)));
 }
 
-std::unique_ptr<api::tabs::Tab> CefExtensionFunctionDetails::CreateTabObject(
-    CefRefPtr<CefBrowserHostImpl> new_browser,
+api::tabs::Tab CefExtensionFunctionDetails::CreateTabObject(
+    CefRefPtr<AlloyBrowserHostImpl> new_browser,
     int opener_browser_id,
     bool active,
     int index) const {
   content::WebContents* contents = new_browser->web_contents();
 
   bool is_loading = contents->IsLoading();
-  auto tab_object = std::make_unique<api::tabs::Tab>();
-  tab_object->id = std::make_unique<int>(new_browser->GetIdentifier());
-  tab_object->index = index;
-  tab_object->window_id = *tab_object->id;
-  tab_object->status = is_loading ? api::tabs::TAB_STATUS_LOADING
-                                  : api::tabs::TAB_STATUS_COMPLETE;
-  tab_object->active = active;
-  tab_object->selected = true;
-  tab_object->highlighted = true;
-  tab_object->pinned = false;
+  api::tabs::Tab tab_object;
+  tab_object.id = new_browser->GetIdentifier();
+  tab_object.index = index;
+  tab_object.window_id = *tab_object.id;
+  tab_object.status = is_loading ? api::tabs::TAB_STATUS_LOADING
+                                 : api::tabs::TAB_STATUS_COMPLETE;
+  tab_object.active = active;
+  tab_object.selected = true;
+  tab_object.highlighted = true;
+  tab_object.pinned = false;
   // TODO(extensions): Use RecentlyAudibleHelper to populate |audible|.
-  tab_object->discarded = false;
-  tab_object->auto_discardable = false;
-  tab_object->muted_info = CreateMutedInfo(contents);
-  tab_object->incognito = false;
+  tab_object.discarded = false;
+  tab_object.auto_discardable = false;
+  tab_object.muted_info = CreateMutedInfo(contents);
+  tab_object.incognito = false;
   gfx::Size contents_size = contents->GetContainerBounds().size();
-  tab_object->width = std::make_unique<int>(contents_size.width());
-  tab_object->height = std::make_unique<int>(contents_size.height());
-  tab_object->url = std::make_unique<std::string>(contents->GetURL().spec());
-  tab_object->title =
-      std::make_unique<std::string>(base::UTF16ToUTF8(contents->GetTitle()));
+  tab_object.width = contents_size.width();
+  tab_object.height = contents_size.height();
+  tab_object.url = contents->GetURL().spec();
+  tab_object.title = base::UTF16ToUTF8(contents->GetTitle());
 
   content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
   if (entry && entry->GetFavicon().valid) {
-    tab_object->fav_icon_url =
-        std::make_unique<std::string>(entry->GetFavicon().url.spec());
+    tab_object.fav_icon_url = entry->GetFavicon().url.spec();
   }
 
-  if (opener_browser_id >= 0)
-    tab_object->opener_tab_id = std::make_unique<int>(opener_browser_id);
+  if (opener_browser_id >= 0) {
+    tab_object.opener_tab_id = opener_browser_id;
+  }
 
   return tab_object;
 }
 
 // static
-std::unique_ptr<api::tabs::MutedInfo>
-CefExtensionFunctionDetails::CreateMutedInfo(content::WebContents* contents) {
+api::tabs::MutedInfo CefExtensionFunctionDetails::CreateMutedInfo(
+    content::WebContents* contents) {
   DCHECK(contents);
-  std::unique_ptr<api::tabs::MutedInfo> info(new api::tabs::MutedInfo);
-  info->muted = contents->IsAudioMuted();
-  // TODO(cef): Maybe populate |info->reason|.
+  api::tabs::MutedInfo info;
+  info.muted = contents->IsAudioMuted();
+  // TODO(cef): Maybe populate |info.reason|.
   return info;
 }
 
 CefRefPtr<CefExtension> CefExtensionFunctionDetails::GetCefExtension() const {
   if (!cef_extension_) {
     cef_extension_ =
-        static_cast<CefBrowserContext*>(function_->browser_context())
-            ->extension_system()
+        CefBrowserContext::FromBrowserContext(function_->browser_context())
             ->GetExtension(function_->extension_id());
     DCHECK(cef_extension_);
   }
diff --git a/src/libcef/browser/extensions/extension_function_details.h b/src/libcef/browser/extensions/extension_function_details.h
index 1ba7102..e47b3b4 100644
--- a/src/libcef/browser/extensions/extension_function_details.h
+++ b/src/libcef/browser/extensions/extension_function_details.h
@@ -5,12 +5,11 @@
 #ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_DETAILS_H_
 #define CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_DETAILS_H_
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 
 #include "include/cef_extension.h"
 
-#include "base/callback_forward.h"
-#include "base/macros.h"
+#include "base/functional/callback_forward.h"
 #include "chrome/common/extensions/api/tabs.h"
 #include "ui/gfx/native_widget_types.h"
 
@@ -30,13 +29,18 @@
   // Constructs a new ChromeExtensionFunctionDetails instance for |function|.
   // This instance does not own |function| and must outlive it.
   explicit CefExtensionFunctionDetails(ExtensionFunction* function);
+
+  CefExtensionFunctionDetails(const CefExtensionFunctionDetails&) = delete;
+  CefExtensionFunctionDetails& operator=(const CefExtensionFunctionDetails&) =
+      delete;
+
   ~CefExtensionFunctionDetails();
 
   Profile* GetProfile() const;
 
   // Get the "sender" browser that is hosting the extension. May return NULL
   // during startup/shutdown.
-  CefRefPtr<CefBrowserHostImpl> GetSenderBrowser() const;
+  CefRefPtr<AlloyBrowserHostImpl> GetSenderBrowser() const;
 
   // Get the "current" browser that will be acted on by this extension function,
   // if any. When mapping from a tabId use the GetBrowserForTabId* methods
@@ -57,12 +61,12 @@
   // This method can return NULL if there is no matching browser, which can
   // happen if only incognito windows are open, or early in startup or shutdown
   // shutdown when there are no active windows.
-  CefRefPtr<CefBrowserHostImpl> GetCurrentBrowser() const;
+  CefRefPtr<AlloyBrowserHostImpl> GetCurrentBrowser() const;
 
   // Returns true if the sender browser can access |target|. When mapping from a
   // tabId use the GetBrowserForTabId* methods instead of calling this method
   // directly.
-  bool CanAccessBrowser(CefRefPtr<CefBrowserHostImpl> target) const;
+  bool CanAccessBrowser(CefRefPtr<AlloyBrowserHostImpl> target) const;
 
   // Returns the browser matching |tab_id| or NULL if the browser cannot be
   // found or does not have a WebContents. If |tab_id| is < 0 the "current"
@@ -70,7 +74,7 @@
   // will be set with an appropriate message on error. This method should only
   // be called one time per extension function and will check all necessary
   // client permissions.
-  CefRefPtr<CefBrowserHostImpl> GetBrowserForTabIdFirstTime(
+  CefRefPtr<AlloyBrowserHostImpl> GetBrowserForTabIdFirstTime(
       int tab_id,
       std::string* error_message) const;
 
@@ -79,7 +83,7 @@
   // |error_message| can optionally be passed in and will be set with an
   // appropriate message on error. This method should be called only after
   // GetBrowserForTabIdFirstTime() has succeeded for the same |tab_id|.
-  CefRefPtr<CefBrowserHostImpl> GetBrowserForTabIdAgain(
+  CefRefPtr<AlloyBrowserHostImpl> GetBrowserForTabIdAgain(
       int tab_id,
       std::string* error_message) const;
 
@@ -94,35 +98,35 @@
     OpenTabParams();
     ~OpenTabParams();
 
-    std::unique_ptr<int> window_id;
-    std::unique_ptr<int> opener_tab_id;
-    std::unique_ptr<std::string> url;
-    std::unique_ptr<bool> active;
-    std::unique_ptr<bool> pinned;
-    std::unique_ptr<int> index;
+    bool create_browser_if_needed = false;
+    absl::optional<int> window_id;
+    absl::optional<int> opener_tab_id;
+    absl::optional<std::string> url;
+    absl::optional<bool> active;
+    absl::optional<bool> pinned;
+    absl::optional<int> index;
+    absl::optional<int> bookmark_id;
   };
 
   // Opens a new tab given creation parameters |params|. Returns a Tab object
   // if successful, or NULL and optionally sets |error_message| if an error
   // occurs.
-  base::DictionaryValue* OpenTab(const OpenTabParams& params,
-                                 bool user_gesture,
-                                 std::string* error_message) const;
+  std::unique_ptr<api::tabs::Tab> OpenTab(const OpenTabParams& params,
+                                          bool user_gesture,
+                                          std::string* error_message) const;
 
   // Creates a Tab object (see chrome/common/extensions/api/tabs.json) with
   // information about the state of a browser tab. Depending on the
   // permissions of the extension, the object may or may not include sensitive
   // data such as the tab's URL.
-  std::unique_ptr<api::tabs::Tab> CreateTabObject(
-      CefRefPtr<CefBrowserHostImpl> new_browser,
-      int opener_browser_id,
-      bool active,
-      int index) const;
+  api::tabs::Tab CreateTabObject(CefRefPtr<AlloyBrowserHostImpl> new_browser,
+                                 int opener_browser_id,
+                                 bool active,
+                                 int index) const;
 
   // Creates a tab MutedInfo object (see chrome/common/extensions/api/tabs.json)
   // with information about the mute state of a browser tab.
-  static std::unique_ptr<api::tabs::MutedInfo> CreateMutedInfo(
-      content::WebContents* contents);
+  static api::tabs::MutedInfo CreateMutedInfo(content::WebContents* contents);
 
   // Returns a pointer to the associated ExtensionFunction
   ExtensionFunction* function() { return function_; }
@@ -140,8 +144,6 @@
 
   // Verifies correct usage of GetBrowserForTabId* methods.
   mutable bool get_browser_called_first_time_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(CefExtensionFunctionDetails);
 };
 
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/extension_host_delegate.cc b/src/libcef/browser/extensions/extension_host_delegate.cc
index bd63230..6720ea2 100644
--- a/src/libcef/browser/extensions/extension_host_delegate.cc
+++ b/src/libcef/browser/extensions/extension_host_delegate.cc
@@ -13,20 +13,20 @@
 namespace extensions {
 
 CefExtensionHostDelegate::CefExtensionHostDelegate(
-    CefBrowserHostImpl* browser) {}
+    AlloyBrowserHostImpl* browser) {}
 
 CefExtensionHostDelegate::~CefExtensionHostDelegate() {}
 
 void CefExtensionHostDelegate::OnExtensionHostCreated(
     content::WebContents* web_contents) {}
 
-void CefExtensionHostDelegate::OnRenderViewCreatedForBackgroundPage(
+void CefExtensionHostDelegate::OnMainFrameCreatedForBackgroundPage(
     ExtensionHost* host) {}
 
 content::JavaScriptDialogManager*
 CefExtensionHostDelegate::GetJavaScriptDialogManager() {
-  // Never routed here from CefBrowserHostImpl.
-  NOTREACHED();
+  // Never routed here from AlloyBrowserHostImpl.
+  DCHECK(false);
   return nullptr;
 }
 
@@ -34,7 +34,7 @@
     std::unique_ptr<content::WebContents> web_contents,
     const std::string& extension_id,
     WindowOpenDisposition disposition,
-    const gfx::Rect& initial_rect,
+    const blink::mojom::WindowFeatures& window_features,
     bool user_gesture) {
   // TODO(cef): Add support for extensions opening popup windows.
   NOTIMPLEMENTED();
@@ -45,8 +45,8 @@
     const content::MediaStreamRequest& request,
     content::MediaResponseCallback callback,
     const Extension* extension) {
-  // Never routed here from CefBrowserHostImpl.
-  NOTREACHED();
+  // Never routed here from AlloyBrowserHostImpl.
+  DCHECK(false);
 }
 
 bool CefExtensionHostDelegate::CheckMediaAccessPermission(
@@ -54,21 +54,19 @@
     const GURL& security_origin,
     blink::mojom::MediaStreamType type,
     const Extension* extension) {
-  // Never routed here from CefBrowserHostImpl.
-  NOTREACHED();
+  // Never routed here from AlloyBrowserHostImpl.
+  DCHECK(false);
   return false;
 }
 
 content::PictureInPictureResult CefExtensionHostDelegate::EnterPictureInPicture(
-    content::WebContents* web_contents,
-    const viz::SurfaceId& surface_id,
-    const gfx::Size& natural_size) {
-  NOTREACHED();
+    content::WebContents* web_contents) {
+  DCHECK(false);
   return content::PictureInPictureResult::kNotSupported;
 }
 
 void CefExtensionHostDelegate::ExitPictureInPicture() {
-  NOTREACHED();
+  DCHECK(false);
 }
 
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/extension_host_delegate.h b/src/libcef/browser/extensions/extension_host_delegate.h
index 31e76fa..d3b2f19 100644
--- a/src/libcef/browser/extensions/extension_host_delegate.h
+++ b/src/libcef/browser/extensions/extension_host_delegate.h
@@ -5,26 +5,29 @@
 #ifndef LIBCEF_BROWSER_EXTENSIONS_EXTENSION_HOST_DELEGATE_H_
 #define LIBCEF_BROWSER_EXTENSIONS_EXTENSION_HOST_DELEGATE_H_
 
-#include "base/macros.h"
 #include "extensions/browser/extension_host_delegate.h"
 
-class CefBrowserHostImpl;
+class AlloyBrowserHostImpl;
 
 namespace extensions {
 
 class CefExtensionHostDelegate : public ExtensionHostDelegate {
  public:
-  explicit CefExtensionHostDelegate(CefBrowserHostImpl* browser);
+  explicit CefExtensionHostDelegate(AlloyBrowserHostImpl* browser);
+
+  CefExtensionHostDelegate(const CefExtensionHostDelegate&) = delete;
+  CefExtensionHostDelegate& operator=(const CefExtensionHostDelegate&) = delete;
+
   ~CefExtensionHostDelegate() override;
 
   // ExtensionHostDelegate implementation.
   void OnExtensionHostCreated(content::WebContents* web_contents) override;
-  void OnRenderViewCreatedForBackgroundPage(ExtensionHost* host) override;
+  void OnMainFrameCreatedForBackgroundPage(ExtensionHost* host) override;
   content::JavaScriptDialogManager* GetJavaScriptDialogManager() override;
   void CreateTab(std::unique_ptr<content::WebContents> web_contents,
                  const std::string& extension_id,
                  WindowOpenDisposition disposition,
-                 const gfx::Rect& initial_rect,
+                 const blink::mojom::WindowFeatures& window_features,
                  bool user_gesture) override;
   void ProcessMediaAccessRequest(content::WebContents* web_contents,
                                  const content::MediaStreamRequest& request,
@@ -35,13 +38,8 @@
                                   blink::mojom::MediaStreamType type,
                                   const Extension* extension) override;
   content::PictureInPictureResult EnterPictureInPicture(
-      content::WebContents* web_contents,
-      const viz::SurfaceId& surface_id,
-      const gfx::Size& natural_size) override;
+      content::WebContents* web_contents) override;
   void ExitPictureInPicture() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefExtensionHostDelegate);
 };
 
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/extension_system.cc b/src/libcef/browser/extensions/extension_system.cc
index 341142e..5c15973 100644
--- a/src/libcef/browser/extensions/extension_system.cc
+++ b/src/libcef/browser/extensions/extension_system.cc
@@ -8,7 +8,6 @@
 #include <string>
 
 #include "libcef/browser/extension_impl.h"
-#include "libcef/browser/extensions/pdf_extension_util.h"
 #include "libcef/browser/extensions/value_store/cef_value_store_factory.h"
 #include "libcef/browser/thread_util.h"
 #include "libcef/common/extensions/extensions_util.h"
@@ -16,12 +15,13 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
+#include "base/functional/bind.h"
 #include "base/json/json_string_value_serializer.h"
 #include "base/path_service.h"
 #include "base/strings/string_tokenizer.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
 #include "base/threading/thread_restrictions.h"
+#include "chrome/browser/pdf/pdf_extension_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_paths.h"
 #include "components/crx_file/id_util.h"
@@ -36,12 +36,9 @@
 #include "extensions/browser/api/app_runtime/app_runtime_api.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
-#include "extensions/browser/info_map.h"
-#include "extensions/browser/notification_types.h"
 #include "extensions/browser/null_app_sorting.h"
 #include "extensions/browser/quota_service.h"
 #include "extensions/browser/renderer_startup_helper.h"
-#include "extensions/browser/runtime_data.h"
 #include "extensions/browser/service_worker_manager.h"
 #include "extensions/browser/state_store.h"
 #include "extensions/browser/unloaded_extension_reason.h"
@@ -54,32 +51,31 @@
 #include "net/base/mime_util.h"
 
 using content::BrowserContext;
-using content::BrowserThread;
 
 namespace extensions {
 
 namespace {
 
 // Implementation based on ComponentLoader::ParseManifest.
-std::unique_ptr<base::DictionaryValue> ParseManifest(
-    const std::string& manifest_contents) {
+absl::optional<base::Value::Dict> ParseManifest(
+    base::StringPiece manifest_contents) {
   JSONStringValueDeserializer deserializer(manifest_contents);
-  std::unique_ptr<base::Value> manifest(
-      deserializer.Deserialize(nullptr, nullptr));
+  std::unique_ptr<base::Value> manifest =
+      deserializer.Deserialize(nullptr, nullptr);
 
   if (!manifest.get() || !manifest->is_dict()) {
     LOG(ERROR) << "Failed to parse extension manifest.";
-    return nullptr;
+    return absl::nullopt;
   }
-  // Transfer ownership to the caller.
-  return base::WrapUnique(
-      static_cast<base::DictionaryValue*>(manifest.release()));
+
+  return std::move(*manifest).TakeDict();
 }
 
 void ExecuteLoadFailure(CefRefPtr<CefExtensionHandler> handler,
                         cef_errorcode_t result) {
-  if (!handler)
+  if (!handler) {
     return;
+  }
 
   if (!CEF_CURRENTLY_ON_UIT()) {
     CEF_POST_TASK(CEF_UIT, base::BindOnce(ExecuteLoadFailure, handler, result));
@@ -90,7 +86,7 @@
 }
 
 void LoadExtensionOnUIThread(base::WeakPtr<CefExtensionSystem> context,
-                             std::unique_ptr<base::DictionaryValue> manifest,
+                             base::Value::Dict manifest,
                              const base::FilePath& root_directory,
                              bool internal,
                              CefRefPtr<CefRequestContext> loader_context,
@@ -116,15 +112,14 @@
                                CefRefPtr<CefExtensionHandler> handler) {
   CEF_REQUIRE_BLOCKING();
 
-  std::unique_ptr<base::DictionaryValue> manifest =
-      ParseManifest(manifest_contents);
+  auto manifest = ParseManifest(manifest_contents);
   if (!manifest) {
     LOG(WARNING) << "Failed to parse extension manifest";
     ExecuteLoadFailure(handler, ERR_INVALID_ARGUMENT);
     return;
   }
 
-  LoadExtensionOnUIThread(context, std::move(manifest), root_directory,
+  LoadExtensionOnUIThread(context, std::move(*manifest), root_directory,
                           internal, loader_context, handler);
 }
 
@@ -179,14 +174,10 @@
 
   // Inform the rest of the extensions system to start.
   ready_.Signal();
-  content::NotificationService::current()->Notify(
-      NOTIFICATION_EXTENSIONS_READY_DEPRECATED,
-      content::Source<BrowserContext>(browser_context_),
-      content::NotificationService::NoDetails());
 
   // Add the internal PDF extension. PDF loading works as follows:
-  // 1. The PDF PPAPI plugin is registered in libcef/common/content_client.cc
-  //    ComputeBuiltInPlugins to handle the kPDFPluginOutOfProcessMimeType.
+  // 1. The PDF plugin is registered in libcef/common/content_client.cc
+  //    ComputeBuiltInPlugins to handle the pdf::kInternalPluginMimeType.
   // 2. The PDF extension is registered by the below call to AddExtension and
   //    associated with the "application/pdf" mime type.
   // 3. Web content running in the owner CefBrowser requests to load a PDF file
@@ -224,7 +215,7 @@
   //    WebContents routing IDs with the owner CefBrowser. MimeHandlerViewGuest
   //    then loads the extension URL (index.html) in the guest WebContents.
   // 13.Creation of the RenderFrame in the guest renderer process triggers a
-  //    sync IPC call from CefContentRendererClient::MaybeCreateBrowser to
+  //    sync IPC call from AlloyContentRendererClient::MaybeCreateBrowser to
   //    CefBrowserInfoManager::GetBrowserInfo in the browser process to retrieve
   //    the CefBrowser information, which will be immediately available due to
   //    step 12.
@@ -236,31 +227,43 @@
   //    CefExtensionsBrowserClient::LoadResourceFromResourceBundle
   //    and CefComponentExtensionResourceManager. Access to chrome://resources
   //    is granted via CefExtensionWebContentsObserver::RenderViewCreated.
-  // 15.The PDF extension calls chrome.mimeHandlerPrivate.getStreamInfo
-  //    (chrome/browser/resources/pdf/browser_api.js) to retrieve the PDF
-  //    resource stream. This API is implemented using Mojo as described in
-  //    libcef/common/extensions/api/README.txt.
-  // 16.The PDF extension requests the PDF PPAPI plugin to handle
-  //    kPDFPluginOutOfProcessMimeType. Approval arrives in the guest renderer
+  // 15.The PDF extension requests the PDF plugin to handle
+  //    pdf::kInternalPluginMimeType. Approval arrives in the guest renderer
   //    process via ExtensionFrameHelper::OnExtensionResponse which calls
   //    NativeExtensionBindingsSystem::HandleResponse. This triggers creation of
   //    an HTMLPlugInElement via native V8 bindings to host the PDF plugin.
+  // 16.- With the old PPAPI plugin:
+  //      The PDF extension calls chrome.mimeHandlerPrivate.getStreamInfo
+  //      (chrome/browser/resources/pdf/browser_api.js) to retrieve the PDF
+  //      resource stream. This API is implemented using Mojo as described in
+  //      libcef/common/extensions/api/README.txt.
+  //    - With the new PdfUnseasoned plugin:
+  //      The PDF resource navigation is redirected by PdfNavigationThrottle and
+  //      the stream contents are replaced by PdfURLLoaderRequestInterceptor.
   // 17.HTMLPlugInElement::RequestObject is called in the guest renderer process
-  //    and determines that the PDF PPAPI plugin should be handled internally
+  //    and determines that the PDF plugin should be handled internally
   //    (handled_externally=false). A PluginDocument is created and
-  //    CefContentRendererClient::OverrideCreatePlugin is called to create a
+  //    AlloyContentRendererClient::OverrideCreatePlugin is called to create a
   //    WebPlugin.
-  // 18.The PDF extension and PDF plugin are now loaded. Print commands, if
+  // 18.- With the old PPAPI plugin:
+  //      The PDF plugin is loaded by ChromeContentRendererClient::CreatePlugin
+  //      calling RenderFrameImpl::CreatePlugin.
+  //    - With the new PdfUnseasoned plugin:
+  //      The PDF plugin is loaded by ChromeContentRendererClient::CreatePlugin
+  //      calling pdf::CreateInternalPlugin.
+  // 19.The PDF extension and PDF plugin are now loaded. Print commands, if
   //    any, are handled in the guest renderer process by ChromePDFPrintClient
   //    and CefPrintRenderFrameHelperDelegate.
-  // 19.When navigating away from the PDF file or closing the owner CefBrowser
+  // 20.When navigating away from the PDF file or closing the owner CefBrowser
   //    the guest WebContents will be destroyed. This triggers a call to
   //    CefMimeHandlerViewGuestDelegate::OnGuestDetached which removes the
   //    routing ID association with the owner CefBrowser.
   if (PdfExtensionEnabled()) {
-    LoadExtension(ParseManifest(pdf_extension_util::GetManifest()),
-                  base::FilePath(FILE_PATH_LITERAL("pdf")), true /* internal */,
-                  nullptr, nullptr);
+    if (auto manifest = ParseManifest(pdf_extension_util::GetManifest())) {
+      LoadExtension(std::move(*manifest),
+                    base::FilePath(FILE_PATH_LITERAL("pdf")),
+                    true /* internal */, nullptr, nullptr);
+    }
   }
 
   initialized_ = true;
@@ -291,7 +294,7 @@
 
 // Implementation based on ComponentLoader::Add.
 void CefExtensionSystem::LoadExtension(
-    std::unique_ptr<base::DictionaryValue> manifest,
+    base::Value::Dict manifest,
     const base::FilePath& root_directory,
     bool internal,
     CefRefPtr<CefRequestContext> loader_context,
@@ -307,10 +310,11 @@
   }
 #endif
 
-  ComponentExtensionInfo info(manifest.get(), root_directory, internal);
+  ComponentExtensionInfo info(std::move(manifest), root_directory, internal);
   const Extension* extension = LoadExtension(info, loader_context, handler);
-  if (!extension)
+  if (!extension) {
     ExecuteLoadFailure(handler, ERR_FAILED);
+  }
 }
 
 // Implementation based on ExtensionService::RemoveComponentExtension.
@@ -349,8 +353,9 @@
     const std::string& extension_id) const {
   CEF_REQUIRE_UIT();
   ExtensionMap::const_iterator it = extension_map_.find(extension_id);
-  if (it != extension_map_.end())
+  if (it != extension_map_.end()) {
     return it->second;
+  }
   return nullptr;
 }
 
@@ -370,8 +375,9 @@
   for (; it != map.end(); ++it) {
     CefRefPtr<CefExtensionImpl> cef_extension =
         static_cast<CefExtensionImpl*>(it->second.get());
-    if (cef_extension->loader_context() == context)
+    if (cef_extension->loader_context() == context) {
       UnloadExtension(it->first);
+    }
   }
 }
 
@@ -392,7 +398,6 @@
 void CefExtensionSystem::InitForRegularProfile(bool extensions_enabled) {
   DCHECK(!initialized_);
   service_worker_manager_.reset(new ServiceWorkerManager(browser_context_));
-  runtime_data_.reset(new RuntimeData(registry_));
   quota_service_.reset(new QuotaService);
   app_sorting_.reset(new NullAppSorting);
 }
@@ -401,10 +406,6 @@
   return nullptr;
 }
 
-RuntimeData* CefExtensionSystem::runtime_data() {
-  return runtime_data_.get();
-}
-
 ManagementPolicy* CefExtensionSystem::management_policy() {
   return nullptr;
 }
@@ -413,7 +414,7 @@
   return service_worker_manager_.get();
 }
 
-SharedUserScriptMaster* CefExtensionSystem::shared_user_script_master() {
+UserScriptManager* CefExtensionSystem::user_script_manager() {
   return nullptr;
 }
 
@@ -425,14 +426,13 @@
   return rules_store_.get();
 }
 
-scoped_refptr<ValueStoreFactory> CefExtensionSystem::store_factory() {
-  return store_factory_;
+StateStore* CefExtensionSystem::dynamic_user_scripts_store() {
+  return nullptr;
 }
 
-InfoMap* CefExtensionSystem::info_map() {
-  if (!info_map_.get())
-    info_map_ = new InfoMap;
-  return info_map_.get();
+scoped_refptr<value_store::ValueStoreFactory>
+CefExtensionSystem::store_factory() {
+  return store_factory_;
 }
 
 QuotaService* CefExtensionSystem::quota_service() {
@@ -443,36 +443,14 @@
   return app_sorting_.get();
 }
 
-// Implementation based on
-// ExtensionSystemImpl::RegisterExtensionWithRequestContexts.
-void CefExtensionSystem::RegisterExtensionWithRequestContexts(
-    const Extension* extension,
-    base::OnceClosure callback) {
-  // TODO(extensions): The |incognito_enabled| value should be set based on
-  // manifest settings.
-  base::PostTaskAndReply(
-      FROM_HERE, {BrowserThread::IO},
-      base::Bind(&InfoMap::AddExtension, info_map(),
-                 base::RetainedRef(extension), base::Time::Now(),
-                 true,    // incognito_enabled
-                 false),  // notifications_disabled
-      std::move(callback));
-}
-
-// Implementation based on
-// ExtensionSystemImpl::UnregisterExtensionWithRequestContexts.
-void CefExtensionSystem::UnregisterExtensionWithRequestContexts(
-    const std::string& extension_id,
-    const UnloadedExtensionReason reason) {
-  base::PostTask(
-      FROM_HERE, {BrowserThread::IO},
-      base::Bind(&InfoMap::RemoveExtension, info_map(), extension_id, reason));
-}
-
 const base::OneShotEvent& CefExtensionSystem::ready() const {
   return ready_;
 }
 
+bool CefExtensionSystem::is_ready() const {
+  return ready_.is_signaled();
+}
+
 ContentVerifier* CefExtensionSystem::content_verifier() {
   return nullptr;
 }
@@ -488,22 +466,30 @@
     const base::FilePath& temp_dir,
     bool install_immediately,
     InstallUpdateCallback install_update_callback) {
-  NOTREACHED();
-  base::DeleteFile(temp_dir, true /* recursive */);
+  DCHECK(false);
+  base::DeletePathRecursively(temp_dir);
+}
+
+void CefExtensionSystem::PerformActionBasedOnOmahaAttributes(
+    const std::string& extension_id,
+    const base::Value::Dict& attributes) {
+  DCHECK(false);
 }
 
 bool CefExtensionSystem::FinishDelayedInstallationIfReady(
     const std::string& extension_id,
     bool install_immediately) {
-  NOTREACHED();
+  DCHECK(false);
   return false;
 }
 
 CefExtensionSystem::ComponentExtensionInfo::ComponentExtensionInfo(
-    const base::DictionaryValue* manifest,
+    base::Value::Dict manifest,
     const base::FilePath& directory,
     bool internal)
-    : manifest(manifest), root_directory(directory), internal(internal) {
+    : manifest(std::move(manifest)),
+      root_directory(directory),
+      internal(internal) {
   if (!root_directory.IsAbsolute()) {
     // This path structure is required by
     // url_request_util::MaybeCreateURLRequestResourceBundleJob.
@@ -513,18 +499,19 @@
 }
 
 void CefExtensionSystem::InitPrefs() {
-  store_factory_ = new CefValueStoreFactory(browser_context_->GetPath());
+  store_factory_ =
+      new value_store::CefValueStoreFactory(browser_context_->GetPath());
 
   Profile* profile = Profile::FromBrowserContext(browser_context_);
 
   // Two state stores. The latter, which contains declarative rules, must be
   // loaded immediately so that the rules are ready before we issue network
   // requests.
-  state_store_.reset(new StateStore(
-      profile, store_factory_, ValueStoreFrontend::BackendType::STATE, true));
+  state_store_ = std::make_unique<StateStore>(
+      profile, store_factory_, StateStore::BackendType::STATE, true);
 
-  rules_store_.reset(new StateStore(
-      profile, store_factory_, ValueStoreFrontend::BackendType::RULES, false));
+  rules_store_ = std::make_unique<StateStore>(
+      profile, store_factory_, StateStore::BackendType::RULES, false);
 }
 
 // Implementation based on ComponentLoader::CreateExtension.
@@ -543,8 +530,9 @@
       // Tests should continue to use the Manifest::COMMAND_LINE value here
       // Some Chrome APIs will cause undesired effects if this is incorrect
       // e.g.: alarms API has 1 minute minimum applied to Packed Extensions
-      info.internal ? Manifest::COMPONENT : Manifest::COMMAND_LINE,
-      *info.manifest, flags, utf8_error);
+      info.internal ? mojom::ManifestLocation::kComponent
+                    : mojom::ManifestLocation::kCommandLine,
+      info.manifest, flags, utf8_error);
 }
 
 // Implementation based on ComponentLoader::Load and
@@ -572,12 +560,12 @@
   // Insert first so that callbacks can retrieve the loaded extension.
   extension_map_.insert(std::make_pair(extension->id(), cef_extension));
 
-  cef_extension->OnExtensionLoaded();
-
   // This may trigger additional callbacks.
   registry_->AddEnabled(extension.get());
   NotifyExtensionLoaded(extension.get());
 
+  cef_extension->OnExtensionLoaded();
+
   return extension.get();
 }
 
@@ -593,18 +581,11 @@
   // This method can be called via PostTask, so the extension may have been
   // unloaded by the time this runs.
   if (!extension.get()) {
-    // In case the extension may have crashed/uninstalled. Allow the profile to
-    // clean up its RequestContexts.
-    UnregisterExtensionWithRequestContexts(extension_id, reason);
     return;
   }
 
   if (registry_->disabled_extensions().Contains(extension->id())) {
     registry_->RemoveDisabled(extension->id());
-    // Make sure the profile cleans up its RequestContexts when an already
-    // disabled extension is unloaded (since they are also tracking the disabled
-    // extensions).
-    UnregisterExtensionWithRequestContexts(extension_id, reason);
     // Don't send the unloaded notification. It was sent when the extension
     // was disabled.
   } else {
@@ -612,27 +593,10 @@
     registry_->RemoveEnabled(extension->id());
     NotifyExtensionUnloaded(extension.get(), reason);
   }
-
-  content::NotificationService::current()->Notify(
-      extensions::NOTIFICATION_EXTENSION_REMOVED,
-      content::Source<content::BrowserContext>(browser_context_),
-      content::Details<const Extension>(extension.get()));
 }
 
 // Implementation based on ExtensionService::NotifyExtensionLoaded.
 void CefExtensionSystem::NotifyExtensionLoaded(const Extension* extension) {
-  // The URLRequestContexts need to be first to know that the extension
-  // was loaded, otherwise a race can arise where a renderer that is created
-  // for the extension may try to load an extension URL with an extension id
-  // that the request context doesn't yet know about. The profile is responsible
-  // for ensuring its URLRequestContexts appropriately discover the loaded
-  // extension.
-  RegisterExtensionWithRequestContexts(
-      extension,
-      base::Bind(&CefExtensionSystem::OnExtensionRegisteredWithRequestContexts,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 base::WrapRefCounted(extension)));
-
   // Tell renderers about the loaded extension.
   renderer_helper_->OnExtensionLoaded(*extension);
 
@@ -673,13 +637,6 @@
   }
 }
 
-void CefExtensionSystem::OnExtensionRegisteredWithRequestContexts(
-    scoped_refptr<const extensions::Extension> extension) {
-  registry_->AddReady(extension);
-  if (registry_->enabled_extensions().Contains(extension->id()))
-    registry_->TriggerOnReady(extension.get());
-}
-
 // Implementation based on ExtensionService::NotifyExtensionUnloaded.
 void CefExtensionSystem::NotifyExtensionUnloaded(
     const Extension* extension,
@@ -700,8 +657,6 @@
 
   // Tell renderers about the unloaded extension.
   renderer_helper_->OnExtensionUnloaded(*extension);
-
-  UnregisterExtensionWithRequestContexts(extension->id(), reason);
 }
 
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/extension_system.h b/src/libcef/browser/extensions/extension_system.h
index cdb7480..61fa3e3 100644
--- a/src/libcef/browser/extensions/extension_system.h
+++ b/src/libcef/browser/extensions/extension_system.h
@@ -12,17 +12,13 @@
 #include "include/cef_extension_handler.h"
 #include "include/cef_request_context.h"
 
-#include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
 #include "base/one_shot_event.h"
 #include "extensions/browser/extension_system.h"
 
-class BrowserContextKeyedServiceFactory;
-
 namespace base {
 class DictionaryValue;
-class FilePath;
-}  // namespace base
+}
 
 namespace content {
 class BrowserContext;
@@ -31,16 +27,17 @@
 namespace extensions {
 
 class ExtensionRegistry;
-class InfoMap;
 class ProcessManager;
 class RendererStartupHelper;
-class SharedUserScriptMaster;
-class ValueStoreFactory;
 
 // Used to manage extensions.
 class CefExtensionSystem : public ExtensionSystem {
  public:
   explicit CefExtensionSystem(content::BrowserContext* browser_context);
+
+  CefExtensionSystem(const CefExtensionSystem&) = delete;
+  CefExtensionSystem& operator=(const CefExtensionSystem&) = delete;
+
   ~CefExtensionSystem() override;
 
   // Initializes the extension system.
@@ -60,7 +57,7 @@
                      bool internal,
                      CefRefPtr<CefRequestContext> loader_context,
                      CefRefPtr<CefExtensionHandler> handler);
-  void LoadExtension(std::unique_ptr<base::DictionaryValue> manifest,
+  void LoadExtension(base::Value::Dict manifest,
                      const base::FilePath& root_directory,
                      bool internal,
                      CefRefPtr<CefRequestContext> loader_context,
@@ -90,23 +87,17 @@
   // ExtensionSystem implementation:
   void InitForRegularProfile(bool extensions_enabled) override;
   ExtensionService* extension_service() override;
-  RuntimeData* runtime_data() override;
   ManagementPolicy* management_policy() override;
   ServiceWorkerManager* service_worker_manager() override;
-  SharedUserScriptMaster* shared_user_script_master() override;
+  UserScriptManager* user_script_manager() override;
   StateStore* state_store() override;
   StateStore* rules_store() override;
-  scoped_refptr<ValueStoreFactory> store_factory() override;
-  InfoMap* info_map() override;
+  StateStore* dynamic_user_scripts_store() override;
+  scoped_refptr<value_store::ValueStoreFactory> store_factory() override;
   QuotaService* quota_service() override;
   AppSorting* app_sorting() override;
-  void RegisterExtensionWithRequestContexts(
-      const Extension* extension,
-      base::OnceClosure callback) override;
-  void UnregisterExtensionWithRequestContexts(
-      const std::string& extension_id,
-      const UnloadedExtensionReason reason) override;
   const base::OneShotEvent& ready() const override;
+  bool is_ready() const override;
   ContentVerifier* content_verifier() override;
   std::unique_ptr<ExtensionSet> GetDependentExtensions(
       const Extension* extension) override;
@@ -115,6 +106,9 @@
                      const base::FilePath& temp_dir,
                      bool install_immediately,
                      InstallUpdateCallback install_update_callback) override;
+  void PerformActionBasedOnOmahaAttributes(
+      const std::string& extension_id,
+      const base::Value::Dict& attributes) override;
   bool FinishDelayedInstallationIfReady(const std::string& extension_id,
                                         bool install_immediately) override;
 
@@ -125,12 +119,12 @@
 
   // Information about a registered component extension.
   struct ComponentExtensionInfo {
-    ComponentExtensionInfo(const base::DictionaryValue* manifest,
+    ComponentExtensionInfo(base::Value::Dict manifest,
                            const base::FilePath& root_directory,
                            bool internal);
 
     // The parsed contents of the extensions's manifest file.
-    const base::DictionaryValue* manifest;
+    base::Value::Dict manifest;
 
     // Directory where the extension is stored.
     base::FilePath root_directory;
@@ -159,26 +153,17 @@
   void NotifyExtensionUnloaded(const Extension* extension,
                                UnloadedExtensionReason reason);
 
-  // Completes extension loading after URLRequestContexts have been updated
-  // on the IO thread.
-  void OnExtensionRegisteredWithRequestContexts(
-      scoped_refptr<const extensions::Extension> extension);
-
   content::BrowserContext* browser_context_;  // Not owned.
 
   bool initialized_;
 
-  // Data to be accessed on the IO thread. Must outlive process_manager_.
-  scoped_refptr<InfoMap> info_map_;
-
   std::unique_ptr<ServiceWorkerManager> service_worker_manager_;
-  std::unique_ptr<RuntimeData> runtime_data_;
   std::unique_ptr<QuotaService> quota_service_;
   std::unique_ptr<AppSorting> app_sorting_;
 
   std::unique_ptr<StateStore> state_store_;
   std::unique_ptr<StateStore> rules_store_;
-  scoped_refptr<ValueStoreFactory> store_factory_;
+  scoped_refptr<value_store::ValueStoreFactory> store_factory_;
 
   // Signaled when the extension system has completed its startup tasks.
   base::OneShotEvent ready_;
@@ -195,8 +180,6 @@
 
   // Must be the last member.
   base::WeakPtrFactory<CefExtensionSystem> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefExtensionSystem);
 };
 
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/extension_system_factory.cc b/src/libcef/browser/extensions/extension_system_factory.cc
index ed8d9f1..2b82a4c 100644
--- a/src/libcef/browser/extensions/extension_system_factory.cc
+++ b/src/libcef/browser/extensions/extension_system_factory.cc
@@ -37,9 +37,10 @@
 
 CefExtensionSystemFactory::~CefExtensionSystemFactory() {}
 
-KeyedService* CefExtensionSystemFactory::BuildServiceInstanceFor(
+std::unique_ptr<KeyedService>
+CefExtensionSystemFactory::BuildServiceInstanceForBrowserContext(
     BrowserContext* context) const {
-  return new CefExtensionSystem(context);
+  return std::make_unique<CefExtensionSystem>(context);
 }
 
 BrowserContext* CefExtensionSystemFactory::GetBrowserContextToUse(
diff --git a/src/libcef/browser/extensions/extension_system_factory.h b/src/libcef/browser/extensions/extension_system_factory.h
index fd7b99f..605a17b 100644
--- a/src/libcef/browser/extensions/extension_system_factory.h
+++ b/src/libcef/browser/extensions/extension_system_factory.h
@@ -13,6 +13,10 @@
 // Factory that provides CefExtensionSystem.
 class CefExtensionSystemFactory : public ExtensionSystemProvider {
  public:
+  CefExtensionSystemFactory(const CefExtensionSystemFactory&) = delete;
+  CefExtensionSystemFactory& operator=(const CefExtensionSystemFactory&) =
+      delete;
+
   // ExtensionSystemProvider implementation:
   ExtensionSystem* GetForBrowserContext(
       content::BrowserContext* context) override;
@@ -26,13 +30,11 @@
   ~CefExtensionSystemFactory() override;
 
   // BrowserContextKeyedServiceFactory implementation:
-  KeyedService* BuildServiceInstanceFor(
+  std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext(
       content::BrowserContext* context) const override;
   content::BrowserContext* GetBrowserContextToUse(
       content::BrowserContext* context) const override;
   bool ServiceIsCreatedWithBrowserContext() const override;
-
-  DISALLOW_COPY_AND_ASSIGN(CefExtensionSystemFactory);
 };
 
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/extension_view_host.cc b/src/libcef/browser/extensions/extension_view_host.cc
index d7af716..8f2b19f 100644
--- a/src/libcef/browser/extensions/extension_view_host.cc
+++ b/src/libcef/browser/extensions/extension_view_host.cc
@@ -7,11 +7,8 @@
 #include "libcef/browser/browser_platform_delegate.h"
 #include "libcef/browser/extensions/extension_host_delegate.h"
 
-#include "content/public/browser/notification_source.h"
 #include "content/public/browser/web_contents.h"
-#include "extensions/browser/extension_system.h"
-#include "extensions/browser/notification_types.h"
-#include "extensions/browser/runtime_data.h"
+#include "extensions/browser/process_util.h"
 #include "third_party/blink/public/common/input/web_gesture_event.h"
 
 using content::NativeWebKeyboardEvent;
@@ -21,22 +18,20 @@
 
 namespace extensions {
 
-CefExtensionViewHost::CefExtensionViewHost(
-    CefBrowserHostImpl* browser,
-    const Extension* extension,
-    content::BrowserContext* browser_context,
-    content::WebContents* host_contents,
-    const GURL& url,
-    ViewType host_type)
+CefExtensionViewHost::CefExtensionViewHost(AlloyBrowserHostImpl* browser,
+                                           const Extension* extension,
+                                           content::WebContents* host_contents,
+                                           const GURL& url,
+                                           mojom::ViewType host_type)
     : ExtensionHost(new CefExtensionHostDelegate(browser),
                     extension,
-                    browser_context,
+                    host_contents->GetBrowserContext(),
                     host_contents,
                     url,
                     host_type) {
   // Only used for dialogs and popups.
-  DCHECK(host_type == VIEW_TYPE_EXTENSION_DIALOG ||
-         host_type == VIEW_TYPE_EXTENSION_POPUP);
+  DCHECK(host_type == mojom::ViewType::kExtensionDialog ||
+         host_type == mojom::ViewType::kExtensionPopup);
 }
 
 CefExtensionViewHost::~CefExtensionViewHost() {}
@@ -46,13 +41,12 @@
 }
 
 void CefExtensionViewHost::LoadInitialURL() {
-  if (!ExtensionSystem::Get(browser_context())
-           ->runtime_data()
-           ->IsBackgroundPageReady(extension())) {
+  if (process_util::GetPersistentBackgroundPageState(*extension(),
+                                                     browser_context()) ==
+      process_util::PersistentBackgroundPageState::kNotReady) {
     // Make sure the background page loads before any others.
-    registrar_.Add(this,
-                   extensions::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY,
-                   content::Source<Extension>(extension()));
+    host_registry_observation_.Observe(
+        ExtensionHostRegistry::Get(browser_context()));
     return;
   }
 
@@ -63,7 +57,7 @@
   return false;
 }
 
-bool CefExtensionViewHost::ShouldTransferNavigation(
+bool CefExtensionViewHost::ShouldAllowRendererInitiatedCrossProcessNavigation(
     bool is_main_frame_navigation) {
   // Block navigations that cause the main frame to navigate to non-extension
   // content (i.e. to web content).
@@ -78,19 +72,28 @@
 }
 
 WebContents* CefExtensionViewHost::GetVisibleWebContents() const {
-  if (extension_host_type() == VIEW_TYPE_EXTENSION_POPUP)
+  if (extension_host_type() == mojom::ViewType::kExtensionPopup) {
     return host_contents();
+  }
   return nullptr;
 }
 
-void CefExtensionViewHost::Observe(
-    int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-  DCHECK_EQ(type, extensions::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY);
-  DCHECK(ExtensionSystem::Get(browser_context())
-             ->runtime_data()
-             ->IsBackgroundPageReady(extension()));
+void CefExtensionViewHost::OnExtensionHostDocumentElementAvailable(
+    content::BrowserContext* host_browser_context,
+    ExtensionHost* extension_host) {
+  DCHECK(extension_host->extension());
+  if (host_browser_context != browser_context() ||
+      extension_host->extension() != extension() ||
+      extension_host->extension_host_type() !=
+          mojom::ViewType::kExtensionBackgroundPage) {
+    return;
+  }
+
+  DCHECK_EQ(process_util::PersistentBackgroundPageState::kReady,
+            process_util::GetPersistentBackgroundPageState(*extension(),
+                                                           browser_context()));
+  // We only needed to wait for the background page to load, so stop observing.
+  host_registry_observation_.Reset();
   LoadInitialURL();
 }
 
diff --git a/src/libcef/browser/extensions/extension_view_host.h b/src/libcef/browser/extensions/extension_view_host.h
index 438f7e0..2557e9e 100644
--- a/src/libcef/browser/extensions/extension_view_host.h
+++ b/src/libcef/browser/extensions/extension_view_host.h
@@ -7,12 +7,11 @@
 
 #include <memory>
 
-#include "base/macros.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
+#include "base/scoped_observation.h"
 #include "extensions/browser/extension_host.h"
+#include "extensions/browser/extension_host_registry.h"
 
-class CefBrowserHostImpl;
+class AlloyBrowserHostImpl;
 
 namespace content {
 class WebContents;
@@ -22,17 +21,20 @@
 
 // The ExtensionHost for an extension that backs a view in the browser UI. For
 // example, this could be an extension popup or dialog, but not a background
-// page. Object lifespan is managed by CefBrowserHostImpl. Based on
+// page. Object lifespan is managed by AlloyBrowserHostImpl. Based on
 // chrome/browser/extensions/extension_view_host.h.
 class CefExtensionViewHost : public ExtensionHost,
-                             public content::NotificationObserver {
+                             public ExtensionHostRegistry::Observer {
  public:
-  CefExtensionViewHost(CefBrowserHostImpl* browser,
+  CefExtensionViewHost(AlloyBrowserHostImpl* browser,
                        const Extension* extension,
-                       content::BrowserContext* browser_context,
                        content::WebContents* host_contents,
                        const GURL& url,
-                       ViewType host_type);
+                       mojom::ViewType host_type);
+
+  CefExtensionViewHost(const CefExtensionViewHost&) = delete;
+  CefExtensionViewHost& operator=(const CefExtensionViewHost&) = delete;
+
   ~CefExtensionViewHost() override;
 
   // ExtensionHost methods:
@@ -41,22 +43,23 @@
   bool IsBackgroundPage() const override;
 
   // content::WebContentsDelegate methods:
-  bool ShouldTransferNavigation(bool is_main_frame_navigation) override;
+  bool ShouldAllowRendererInitiatedCrossProcessNavigation(
+      bool is_main_frame_navigation) override;
   bool PreHandleGestureEvent(content::WebContents* source,
                              const blink::WebGestureEvent& event) override;
 
   // extensions::ExtensionFunctionDispatcher::Delegate methods:
   content::WebContents* GetVisibleWebContents() const override;
 
-  // content::NotificationObserver methods:
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override;
+  // ExtensionHostRegistry::Observer methods:
+  void OnExtensionHostDocumentElementAvailable(
+      content::BrowserContext* browser_context,
+      ExtensionHost* extension_host) override;
 
  private:
-  content::NotificationRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefExtensionViewHost);
+  base::ScopedObservation<ExtensionHostRegistry,
+                          ExtensionHostRegistry::Observer>
+      host_registry_observation_{this};
 };
 
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/extension_web_contents_observer.cc b/src/libcef/browser/extensions/extension_web_contents_observer.cc
index 1f825d0..6e50ebe 100644
--- a/src/libcef/browser/extensions/extension_web_contents_observer.cc
+++ b/src/libcef/browser/extensions/extension_web_contents_observer.cc
@@ -9,12 +9,15 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/common/url_constants.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 
 namespace extensions {
 
 CefExtensionWebContentsObserver::CefExtensionWebContentsObserver(
     content::WebContents* web_contents)
     : ExtensionWebContentsObserver(web_contents),
+      content::WebContentsUserData<CefExtensionWebContentsObserver>(
+          *web_contents),
       script_executor_(new ScriptExecutor(web_contents)) {}
 
 CefExtensionWebContentsObserver::~CefExtensionWebContentsObserver() {}
@@ -34,8 +37,9 @@
   ExtensionWebContentsObserver::RenderFrameCreated(render_frame_host);
 
   const Extension* extension = GetExtensionFromFrame(render_frame_host, false);
-  if (!extension)
+  if (!extension) {
     return;
+  }
 
   int process_id = render_frame_host->GetProcess()->GetID();
   auto policy = content::ChildProcessSecurityPolicy::GetInstance();
@@ -45,12 +49,12 @@
   if ((extension->is_extension() || extension->is_platform_app()) &&
       Manifest::IsComponentLocation(extension->location())) {
     policy->GrantRequestOrigin(
-        process_id, url::Origin::Create(GURL(content::kChromeUIResourcesURL)));
+        process_id, url::Origin::Create(GURL(blink::kChromeUIResourcesURL)));
     policy->GrantRequestOrigin(
         process_id, url::Origin::Create(GURL(chrome::kChromeUIThemeURL)));
   }
 }
 
-WEB_CONTENTS_USER_DATA_KEY_IMPL(CefExtensionWebContentsObserver)
+WEB_CONTENTS_USER_DATA_KEY_IMPL(CefExtensionWebContentsObserver);
 
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/extension_web_contents_observer.h b/src/libcef/browser/extensions/extension_web_contents_observer.h
index 742e535..f40b975 100644
--- a/src/libcef/browser/extensions/extension_web_contents_observer.h
+++ b/src/libcef/browser/extensions/extension_web_contents_observer.h
@@ -19,6 +19,11 @@
     : public ExtensionWebContentsObserver,
       public content::WebContentsUserData<CefExtensionWebContentsObserver> {
  public:
+  CefExtensionWebContentsObserver(const CefExtensionWebContentsObserver&) =
+      delete;
+  CefExtensionWebContentsObserver& operator=(
+      const CefExtensionWebContentsObserver&) = delete;
+
   ~CefExtensionWebContentsObserver() override;
 
   // Creates and initializes an instance of this class for the given
@@ -38,7 +43,6 @@
   std::unique_ptr<ScriptExecutor> script_executor_;
 
   WEB_CONTENTS_USER_DATA_KEY_DECL();
-  DISALLOW_COPY_AND_ASSIGN(CefExtensionWebContentsObserver);
 };
 
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/extensions_api_client.cc b/src/libcef/browser/extensions/extensions_api_client.cc
index a41bfc3..5d39a21 100644
--- a/src/libcef/browser/extensions/extensions_api_client.cc
+++ b/src/libcef/browser/extensions/extensions_api_client.cc
@@ -7,17 +7,17 @@
 
 #include "include/internal/cef_types_wrappers.h"
 #include "libcef/browser/browser_context.h"
+#include "libcef/browser/extensions/api/file_system/cef_file_system_delegate.h"
 #include "libcef/browser/extensions/api/storage/sync_value_store_cache.h"
 #include "libcef/browser/extensions/extension_web_contents_observer.h"
 #include "libcef/browser/extensions/mime_handler_view_guest_delegate.h"
-#include "libcef/browser/extensions/pdf_web_contents_helper_client.h"
-#include "libcef/browser/printing/print_view_manager.h"
 
 #include "base/memory/ptr_util.h"
+#include "chrome/browser/printing/print_view_manager.h"
 #include "chrome/browser/ui/prefs/prefs_tab_helper.h"
-#include "components/pdf/browser/pdf_web_contents_helper.h"
 #include "components/zoom/zoom_controller.h"
 #include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h"
+#include "printing/mojom/print.mojom.h"
 
 namespace extensions {
 
@@ -26,18 +26,16 @@
 AppViewGuestDelegate* CefExtensionsAPIClient::CreateAppViewGuestDelegate()
     const {
   // TODO(extensions): Implement to support Apps.
-  NOTREACHED();
+  DCHECK(false);
   return nullptr;
 }
 
 std::unique_ptr<guest_view::GuestViewManagerDelegate>
-CefExtensionsAPIClient::CreateGuestViewManagerDelegate(
-    content::BrowserContext* context) const {
+CefExtensionsAPIClient::CreateGuestViewManagerDelegate() const {
   // The GuestViewManager instance associated with the returned Delegate, which
   // will be retrieved in the future via GuestViewManager::FromBrowserContext,
   // will be associated with the CefBrowserContext.
-  return base::WrapUnique(new extensions::ExtensionsGuestViewManagerDelegate(
-      CefBrowserContext::GetForContext(context)));
+  return base::WrapUnique(new extensions::ExtensionsGuestViewManagerDelegate());
 }
 
 std::unique_ptr<MimeHandlerViewGuestDelegate>
@@ -49,14 +47,7 @@
 void CefExtensionsAPIClient::AttachWebContentsHelpers(
     content::WebContents* web_contents) const {
   PrefsTabHelper::CreateForWebContents(web_contents);
-  printing::CefPrintViewManager::CreateForWebContents(web_contents);
-
-  CefExtensionWebContentsObserver::CreateForWebContents(web_contents);
-
-  // Used by the PDF extension.
-  pdf::PDFWebContentsHelper::CreateForWebContentsWithClient(
-      web_contents, std::unique_ptr<pdf::PDFWebContentsHelperClient>(
-                        new CefPDFWebContentsHelperClient()));
+  printing::PrintViewManager::CreateForWebContents(web_contents);
 
   // Used by the tabs extension API.
   zoom::ZoomController::CreateForWebContents(web_contents);
@@ -64,9 +55,8 @@
 
 void CefExtensionsAPIClient::AddAdditionalValueStoreCaches(
     content::BrowserContext* context,
-    const scoped_refptr<ValueStoreFactory>& factory,
-    const scoped_refptr<base::ObserverListThreadSafe<SettingsObserver>>&
-        observers,
+    const scoped_refptr<value_store::ValueStoreFactory>& factory,
+    SettingsChangedCallback observer,
     std::map<settings_namespace::Namespace, ValueStoreCache*>* caches) {
   // Add support for chrome.storage.sync.
   // Because we don't support syncing with Google, we follow the behavior of
@@ -75,4 +65,11 @@
   (*caches)[settings_namespace::SYNC] = new cef::SyncValueStoreCache(factory);
 }
 
+FileSystemDelegate* CefExtensionsAPIClient::GetFileSystemDelegate() {
+  if (!file_system_delegate_) {
+    file_system_delegate_ = std::make_unique<cef::CefFileSystemDelegate>();
+  }
+  return file_system_delegate_.get();
+}
+
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/extensions_api_client.h b/src/libcef/browser/extensions/extensions_api_client.h
index 821f0b6..f3ec933 100644
--- a/src/libcef/browser/extensions/extensions_api_client.h
+++ b/src/libcef/browser/extensions/extensions_api_client.h
@@ -6,6 +6,7 @@
 #ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSIONS_API_CLIENT_H_
 #define CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSIONS_API_CLIENT_H_
 
+#include "components/value_store/value_store_factory.h"
 #include "extensions/browser/api/extensions_api_client.h"
 
 namespace extensions {
@@ -17,13 +18,13 @@
   // ExtensionsAPIClient implementation.
   AppViewGuestDelegate* CreateAppViewGuestDelegate() const override;
   std::unique_ptr<guest_view::GuestViewManagerDelegate>
-  CreateGuestViewManagerDelegate(
-      content::BrowserContext* context) const override;
+  CreateGuestViewManagerDelegate() const override;
   std::unique_ptr<MimeHandlerViewGuestDelegate>
   CreateMimeHandlerViewGuestDelegate(
       MimeHandlerViewGuest* guest) const override;
   void AttachWebContentsHelpers(
       content::WebContents* web_contents) const override;
+  FileSystemDelegate* GetFileSystemDelegate() override;
 
   // Storage API support.
 
@@ -31,11 +32,13 @@
   // to |caches|. By default adds nothing.
   void AddAdditionalValueStoreCaches(
       content::BrowserContext* context,
-      const scoped_refptr<ValueStoreFactory>& factory,
-      const scoped_refptr<base::ObserverListThreadSafe<SettingsObserver>>&
-          observers,
+      const scoped_refptr<value_store::ValueStoreFactory>& factory,
+      SettingsChangedCallback observer,
       std::map<settings_namespace::Namespace, ValueStoreCache*>* caches)
       override;
+
+ private:
+  std::unique_ptr<FileSystemDelegate> file_system_delegate_;
 };
 
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/extensions_browser_api_provider.cc b/src/libcef/browser/extensions/extensions_browser_api_provider.cc
index a2e28e0..5abc340 100644
--- a/src/libcef/browser/extensions/extensions_browser_api_provider.cc
+++ b/src/libcef/browser/extensions/extensions_browser_api_provider.cc
@@ -2,18 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "libcef/browser/extensions/chrome_api_registration.h"
 #include "libcef/browser/extensions/extensions_browser_api_provider.h"
+#include "libcef/browser/extensions/chrome_api_registration.h"
 
-//#include "cef/libcef/browser/extensions/api/generated_api_registration.h"
+// #include "cef/libcef/browser/extensions/api/generated_api_registration.h"
 #include "extensions/browser/api/generated_api_registration.h"
 
 namespace extensions {
 
-CefExtensionsBrowserAPIProvider::CefExtensionsBrowserAPIProvider() =
-    default;
-CefExtensionsBrowserAPIProvider::~CefExtensionsBrowserAPIProvider() =
-    default;
+CefExtensionsBrowserAPIProvider::CefExtensionsBrowserAPIProvider() = default;
+CefExtensionsBrowserAPIProvider::~CefExtensionsBrowserAPIProvider() = default;
 
 void CefExtensionsBrowserAPIProvider::RegisterExtensionFunctions(
     ExtensionFunctionRegistry* registry) {
diff --git a/src/libcef/browser/extensions/extensions_browser_api_provider.h b/src/libcef/browser/extensions/extensions_browser_api_provider.h
index f6fce14..d2131b7 100644
--- a/src/libcef/browser/extensions/extensions_browser_api_provider.h
+++ b/src/libcef/browser/extensions/extensions_browser_api_provider.h
@@ -5,7 +5,6 @@
 #ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSIONS_BROWSER_API_PROVIDER_H_
 #define CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSIONS_BROWSER_API_PROVIDER_H_
 
-#include "base/macros.h"
 #include "extensions/browser/extensions_browser_api_provider.h"
 
 namespace extensions {
@@ -13,12 +12,15 @@
 class CefExtensionsBrowserAPIProvider : public ExtensionsBrowserAPIProvider {
  public:
   CefExtensionsBrowserAPIProvider();
+
+  CefExtensionsBrowserAPIProvider(const CefExtensionsBrowserAPIProvider&) =
+      delete;
+  CefExtensionsBrowserAPIProvider& operator=(
+      const CefExtensionsBrowserAPIProvider&) = delete;
+
   ~CefExtensionsBrowserAPIProvider() override;
 
   void RegisterExtensionFunctions(ExtensionFunctionRegistry* registry) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefExtensionsBrowserAPIProvider);
 };
 
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/extensions_browser_client.cc b/src/libcef/browser/extensions/extensions_browser_client.cc
index 755f506..f99d711 100644
--- a/src/libcef/browser/extensions/extensions_browser_client.cc
+++ b/src/libcef/browser/extensions/extensions_browser_client.cc
@@ -7,8 +7,8 @@
 
 #include <utility>
 
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 #include "libcef/browser/browser_context.h"
-#include "libcef/browser/browser_host_impl.h"
 #include "libcef/browser/extensions/component_extension_resource_manager.h"
 #include "libcef/browser/extensions/extension_system.h"
 #include "libcef/browser/extensions/extension_system_factory.h"
@@ -20,18 +20,20 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/chrome_url_request_util.h"
 #include "chrome/browser/extensions/event_router_forwarder.h"
+#include "chrome/browser/media/webrtc/media_device_salt_service_factory.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
+#include "extensions/browser/api/core_extensions_browser_api_provider.h"
 #include "extensions/browser/api/extensions_api_client.h"
 #include "extensions/browser/api/mime_handler_private/mime_handler_private.h"
 #include "extensions/browser/api/runtime/runtime_api_delegate.h"
 #include "extensions/browser/app_sorting.h"
-#include "extensions/browser/core_extensions_browser_api_provider.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_host_delegate.h"
 #include "extensions/browser/extensions_browser_interface_binders.h"
 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
+#include "extensions/browser/kiosk/kiosk_delegate.h"
 #include "extensions/browser/url_request_util.h"
 #include "extensions/common/api/mime_handler.mojom.h"
 #include "extensions/common/constants.h"
@@ -48,13 +50,15 @@
     mojo::PendingReceiver<extensions::mime_handler::MimeHandlerService>
         receiver) {
   auto* web_contents = content::WebContents::FromRenderFrameHost(frame_host);
-  if (!web_contents)
+  if (!web_contents) {
     return;
+  }
 
   auto* guest_view =
       extensions::MimeHandlerViewGuest::FromWebContents(web_contents);
-  if (!guest_view)
+  if (!guest_view) {
     return;
+  }
   extensions::MimeHandlerServiceImpl::Create(guest_view->GetStreamWeakPtr(),
                                              std::move(receiver));
 }
@@ -64,21 +68,34 @@
     mojo::PendingReceiver<extensions::mime_handler::BeforeUnloadControl>
         receiver) {
   auto* web_contents = content::WebContents::FromRenderFrameHost(frame_host);
-  if (!web_contents)
+  if (!web_contents) {
     return;
+  }
 
   auto* guest_view =
       extensions::MimeHandlerViewGuest::FromWebContents(web_contents);
-  if (!guest_view)
+  if (!guest_view) {
     return;
+  }
   guest_view->FuseBeforeUnloadControl(std::move(receiver));
 }
 
+// Dummy KiosDelegate that always returns false
+class CefKioskDelegate : public extensions::KioskDelegate {
+ public:
+  CefKioskDelegate() = default;
+  ~CefKioskDelegate() override = default;
+
+  // KioskDelegate overrides:
+  bool IsAutoLaunchedKioskApp(const ExtensionId& id) const override {
+    return false;
+  }
+};
+
 }  // namespace
 
 CefExtensionsBrowserClient::CefExtensionsBrowserClient()
-    : api_client_(new CefExtensionsAPIClient),
-      resource_manager_(new CefComponentExtensionResourceManager) {
+    : api_client_(new CefExtensionsAPIClient) {
   AddAPIProvider(std::make_unique<CoreExtensionsBrowserAPIProvider>());
   AddAPIProvider(std::make_unique<CefExtensionsBrowserAPIProvider>());
 }
@@ -101,8 +118,8 @@
   return false;
 }
 
-bool CefExtensionsBrowserClient::IsValidContext(BrowserContext* context) {
-  return GetOriginalContext(context) != nullptr;
+bool CefExtensionsBrowserClient::IsValidContext(void* context) {
+  return GetOriginalContext(static_cast<BrowserContext*>(context)) != nullptr;
 }
 
 bool CefExtensionsBrowserClient::IsSameContext(BrowserContext* first,
@@ -125,7 +142,35 @@
 
 BrowserContext* CefExtensionsBrowserClient::GetOriginalContext(
     BrowserContext* context) {
-  return CefBrowserContext::GetForContext(context);
+  auto cef_browser_context = CefBrowserContext::FromBrowserContext(context);
+  if (cef_browser_context) {
+    return cef_browser_context->AsBrowserContext();
+  }
+  return nullptr;
+}
+
+content::BrowserContext*
+CefExtensionsBrowserClient::GetContextRedirectedToOriginal(
+    content::BrowserContext* context,
+    bool force_guest_profile) {
+  return context;
+}
+
+content::BrowserContext* CefExtensionsBrowserClient::GetContextOwnInstance(
+    content::BrowserContext* context,
+    bool force_guest_profile) {
+  return context;
+}
+
+content::BrowserContext* CefExtensionsBrowserClient::GetContextForOriginalOnly(
+    content::BrowserContext* context,
+    bool force_guest_profile) {
+  return context;
+}
+
+bool CefExtensionsBrowserClient::AreExtensionsDisabledForContext(
+    content::BrowserContext* context) {
+  return false;
 }
 
 bool CefExtensionsBrowserClient::IsGuestSession(BrowserContext* context) const {
@@ -157,17 +202,16 @@
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
     const base::FilePath& resource_relative_path,
     const int resource_id,
-    const std::string& content_security_policy,
-    mojo::PendingRemote<network::mojom::URLLoaderClient> client,
-    bool send_cors_header) {
+    scoped_refptr<net::HttpResponseHeaders> headers,
+    mojo::PendingRemote<network::mojom::URLLoaderClient> client) {
   chrome_url_request_util::LoadResourceFromResourceBundle(
       request, std::move(loader), resource_relative_path, resource_id,
-      content_security_policy, std::move(client), send_cors_header);
+      std::move(headers), std::move(client));
 }
 
 bool CefExtensionsBrowserClient::AllowCrossRendererResourceLoad(
-    const GURL& url,
-    blink::mojom::ResourceType resource_type,
+    const network::ResourceRequest& request,
+    network::mojom::RequestDestination destination,
     ui::PageTransition page_transition,
     int child_id,
     bool is_incognito,
@@ -176,7 +220,7 @@
     const ProcessMap& process_map) {
   bool allowed = false;
   if (url_request_util::AllowCrossRendererResourceLoad(
-          url, resource_type, page_transition, child_id, is_incognito,
+          request, destination, page_transition, child_id, is_incognito,
           extension, extensions, process_map, &allowed)) {
     return allowed;
   }
@@ -187,7 +231,9 @@
 
 PrefService* CefExtensionsBrowserClient::GetPrefServiceForContext(
     BrowserContext* context) {
-  return static_cast<CefBrowserContext*>(context)->GetPrefs();
+  return CefBrowserContext::FromBrowserContext(context)
+      ->AsProfile()
+      ->GetPrefs();
 }
 
 void CefExtensionsBrowserClient::GetEarlyExtensionPrefsObservers(
@@ -202,7 +248,7 @@
 std::unique_ptr<ExtensionHostDelegate>
 CefExtensionsBrowserClient::CreateExtensionHostDelegate() {
   // CEF does not use the ExtensionHost constructor that calls this method.
-  NOTREACHED();
+  DCHECK(false);
   return std::unique_ptr<ExtensionHostDelegate>();
 }
 
@@ -211,12 +257,12 @@
     content::BrowserContext* browser_context,
     const GURL& url,
     ExtensionHost** host) {
-  CefBrowserContext* browser_context_impl =
-      CefBrowserContext::GetForContext(browser_context);
+  auto cef_browser_context =
+      CefBrowserContext::FromBrowserContext(browser_context);
 
   // A CEF representation should always exist.
   CefRefPtr<CefExtension> cef_extension =
-      browser_context_impl->extension_system()->GetExtension(extension->id());
+      cef_browser_context->GetExtension(extension->id());
   DCHECK(cef_extension);
   if (!cef_extension) {
     // Cancel the background host creation.
@@ -232,29 +278,28 @@
     return true;
   }
 
-  CefBrowserHostImpl::CreateParams create_params;
-  create_params.url = url;
+  CefBrowserCreateParams create_params;
+  create_params.url = url.spec();
   create_params.request_context = request_context;
 
   CefRefPtr<CefExtensionHandler> handler = cef_extension->GetHandler();
   if (handler.get() && handler->OnBeforeBackgroundBrowser(
-                           cef_extension, url.spec(), create_params.client,
-                           create_params.settings)) {
+                           cef_extension, create_params.url,
+                           create_params.client, create_params.settings)) {
     // Cancel the background host creation.
     return true;
   }
 
   // This triggers creation of the background host.
   create_params.extension = extension;
-  create_params.extension_host_type =
-      extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE;
+  create_params.extension_host_type = mojom::ViewType::kExtensionBackgroundPage;
 
   // Browser creation may fail under certain rare circumstances. Fail the
   // background host creation in that case.
-  CefRefPtr<CefBrowserHostImpl> browser =
-      CefBrowserHostImpl::Create(create_params);
+  CefRefPtr<AlloyBrowserHostImpl> browser =
+      AlloyBrowserHostImpl::Create(create_params);
   if (browser) {
-    *host = browser->extension_host();
+    *host = browser->GetExtensionHost();
     DCHECK(*host);
   }
   return true;
@@ -295,7 +340,7 @@
 }
 
 void CefExtensionsBrowserClient::RegisterBrowserInterfaceBindersForFrame(
-    service_manager::BinderMapWithContext<content::RenderFrameHost*>* map,
+    mojo::BinderMapWithContext<content::RenderFrameHost*>* map,
     content::RenderFrameHost* render_frame_host,
     const Extension* extension) const {
   PopulateExtensionFrameBinders(map, render_frame_host, extension);
@@ -310,19 +355,23 @@
 CefExtensionsBrowserClient::CreateRuntimeAPIDelegate(
     content::BrowserContext* context) const {
   // TODO(extensions): Implement to support Apps.
-  NOTREACHED();
+  DCHECK(false);
   return nullptr;
 }
 
 const ComponentExtensionResourceManager*
 CefExtensionsBrowserClient::GetComponentExtensionResourceManager() {
+  if (!resource_manager_) {
+    resource_manager_ =
+        std::make_unique<CefComponentExtensionResourceManager>();
+  }
   return resource_manager_.get();
 }
 
 void CefExtensionsBrowserClient::BroadcastEventToRenderers(
     events::HistogramValue histogram_value,
     const std::string& event_name,
-    std::unique_ptr<base::ListValue> args,
+    base::Value::List args,
     bool dispatch_to_off_the_record_profiles) {
   g_browser_process->extension_event_router_forwarder()
       ->BroadcastEventToRenderers(histogram_value, event_name, std::move(args),
@@ -331,7 +380,7 @@
 
 ExtensionCache* CefExtensionsBrowserClient::GetExtensionCache() {
   // Only used by Chrome via ExtensionService.
-  NOTREACHED();
+  DCHECK(false);
   return nullptr;
 }
 
@@ -351,8 +400,10 @@
 }
 
 KioskDelegate* CefExtensionsBrowserClient::GetKioskDelegate() {
-  NOTREACHED();
-  return nullptr;
+  if (!kiosk_delegate_) {
+    kiosk_delegate_.reset(new CefKioskDelegate());
+  }
+  return kiosk_delegate_.get();
 }
 
 bool CefExtensionsBrowserClient::IsLockScreenContext(
@@ -364,4 +415,11 @@
   return g_browser_process->GetApplicationLocale();
 }
 
+media_device_salt::MediaDeviceSaltService*
+CefExtensionsBrowserClient::GetMediaDeviceSaltService(
+    content::BrowserContext* context) {
+  return MediaDeviceSaltServiceFactory::GetInstance()->GetForBrowserContext(
+      context);
+}
+
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/extensions_browser_client.h b/src/libcef/browser/extensions/extensions_browser_client.h
index cd82bbb..0168c60 100644
--- a/src/libcef/browser/extensions/extensions_browser_client.h
+++ b/src/libcef/browser/extensions/extensions_browser_client.h
@@ -6,7 +6,6 @@
 #ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSIONS_BROWSER_CLIENT_H_
 #define CEF_LIBCEF_BROWSER_EXTENSIONS_EXTENSIONS_BROWSER_CLIENT_H_
 
-#include "base/compiler_specific.h"
 #include "extensions/browser/extensions_browser_client.h"
 
 namespace extensions {
@@ -18,6 +17,11 @@
 class CefExtensionsBrowserClient : public ExtensionsBrowserClient {
  public:
   CefExtensionsBrowserClient();
+
+  CefExtensionsBrowserClient(const CefExtensionsBrowserClient&) = delete;
+  CefExtensionsBrowserClient& operator=(const CefExtensionsBrowserClient&) =
+      delete;
+
   ~CefExtensionsBrowserClient() override;
 
   // Returns the singleton CefExtensionsBrowserClient instance.
@@ -27,7 +31,7 @@
   bool IsShuttingDown() override;
   bool AreExtensionsDisabled(const base::CommandLine& command_line,
                              content::BrowserContext* context) override;
-  bool IsValidContext(content::BrowserContext* context) override;
+  bool IsValidContext(void* context) override;
   bool IsSameContext(content::BrowserContext* first,
                      content::BrowserContext* second) override;
   bool HasOffTheRecordContext(content::BrowserContext* context) override;
@@ -35,6 +39,17 @@
       content::BrowserContext* context) override;
   content::BrowserContext* GetOriginalContext(
       content::BrowserContext* context) override;
+  content::BrowserContext* GetContextRedirectedToOriginal(
+      content::BrowserContext* context,
+      bool force_guest_profile) override;
+  content::BrowserContext* GetContextOwnInstance(
+      content::BrowserContext* context,
+      bool force_guest_profile) override;
+  content::BrowserContext* GetContextForOriginalOnly(
+      content::BrowserContext* context,
+      bool force_guest_profile) override;
+  bool AreExtensionsDisabledForContext(
+      content::BrowserContext* context) override;
   bool IsGuestSession(content::BrowserContext* context) const override;
   bool IsExtensionIncognitoEnabled(
       const std::string& extension_id,
@@ -51,17 +66,17 @@
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
       const base::FilePath& resource_relative_path,
       const int resource_id,
-      const std::string& content_security_policy,
-      mojo::PendingRemote<network::mojom::URLLoaderClient> client,
-      bool send_cors_header) override;
-  bool AllowCrossRendererResourceLoad(const GURL& url,
-                                      blink::mojom::ResourceType resource_type,
-                                      ui::PageTransition page_transition,
-                                      int child_id,
-                                      bool is_incognito,
-                                      const Extension* extension,
-                                      const ExtensionSet& extensions,
-                                      const ProcessMap& process_map) override;
+      scoped_refptr<net::HttpResponseHeaders> headers,
+      mojo::PendingRemote<network::mojom::URLLoaderClient> client) override;
+  bool AllowCrossRendererResourceLoad(
+      const network::ResourceRequest& request,
+      network::mojom::RequestDestination destination,
+      ui::PageTransition page_transition,
+      int child_id,
+      bool is_incognito,
+      const Extension* extension,
+      const ExtensionSet& extensions,
+      const ProcessMap& process_map) override;
   PrefService* GetPrefServiceForContext(
       content::BrowserContext* context) override;
   void GetEarlyExtensionPrefsObservers(
@@ -82,8 +97,7 @@
   bool IsLoggedInAsPublicAccount() override;
   ExtensionSystemProvider* GetExtensionSystemFactory() override;
   void RegisterBrowserInterfaceBindersForFrame(
-      service_manager::BinderMapWithContext<content::RenderFrameHost*>*
-          binder_map,
+      mojo::BinderMapWithContext<content::RenderFrameHost*>* binder_map,
       content::RenderFrameHost* render_frame_host,
       const Extension* extension) const override;
   std::unique_ptr<RuntimeAPIDelegate> CreateRuntimeAPIDelegate(
@@ -93,7 +107,7 @@
   void BroadcastEventToRenderers(
       events::HistogramValue histogram_value,
       const std::string& event_name,
-      std::unique_ptr<base::ListValue> args,
+      base::Value::List args,
       bool dispatch_to_off_the_record_profiles) override;
   ExtensionCache* GetExtensionCache() override;
   bool IsBackgroundUpdateAllowed() override;
@@ -103,6 +117,8 @@
   KioskDelegate* GetKioskDelegate() override;
   bool IsLockScreenContext(content::BrowserContext* context) override;
   std::string GetApplicationLocale() override;
+  media_device_salt::MediaDeviceSaltService* GetMediaDeviceSaltService(
+      content::BrowserContext* context) override;
 
  private:
   // Support for extension APIs.
@@ -111,7 +127,7 @@
   // Resource manager used to supply resources from pak files.
   std::unique_ptr<ComponentExtensionResourceManager> resource_manager_;
 
-  DISALLOW_COPY_AND_ASSIGN(CefExtensionsBrowserClient);
+  std::unique_ptr<KioskDelegate> kiosk_delegate_;
 };
 
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/mime_handler_view_guest_delegate.cc b/src/libcef/browser/extensions/mime_handler_view_guest_delegate.cc
index 32af32c..ae5b67b 100644
--- a/src/libcef/browser/extensions/mime_handler_view_guest_delegate.cc
+++ b/src/libcef/browser/extensions/mime_handler_view_guest_delegate.cc
@@ -5,14 +5,12 @@
 
 #include "libcef/browser/extensions/mime_handler_view_guest_delegate.h"
 
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_content_browser_client.h"
 #include "libcef/browser/browser_context.h"
-#include "libcef/browser/browser_host_impl.h"
 #include "libcef/browser/browser_info.h"
-#include "libcef/browser/content_browser_client.h"
 #include "libcef/browser/osr/web_contents_view_osr.h"
 
-#include "content/browser/browser_plugin/browser_plugin_guest.h"
-#include "content/browser/web_contents/web_contents_impl.h"
 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
 
 namespace extensions {
@@ -27,8 +25,8 @@
     content::WebContents::CreateParams* params) {
   DCHECK(params->guest_delegate);
 
-  CefRefPtr<CefBrowserHostImpl> owner_browser =
-      CefBrowserHostImpl::GetBrowserForContents(owner_web_contents_);
+  CefRefPtr<AlloyBrowserHostImpl> owner_browser =
+      AlloyBrowserHostImpl::GetBrowserForContents(owner_web_contents_);
   DCHECK(owner_browser);
 
   if (owner_browser->IsWindowless()) {
@@ -43,46 +41,36 @@
   content::WebContents* web_contents = guest_->web_contents();
   DCHECK(web_contents);
 
-  CefRefPtr<CefBrowserHostImpl> owner_browser =
-      CefBrowserHostImpl::GetBrowserForContents(owner_web_contents_);
+  CefRefPtr<AlloyBrowserHostImpl> owner_browser =
+      AlloyBrowserHostImpl::GetBrowserForContents(owner_web_contents_);
   DCHECK(owner_browser);
 
   // Associate guest state information with the owner browser.
-  owner_browser->browser_info()->MaybeCreateFrame(web_contents->GetMainFrame(),
-                                                  true /* is_guest_view */);
+  owner_browser->browser_info()->MaybeCreateFrame(
+      web_contents->GetPrimaryMainFrame(), true /* is_guest_view */);
 }
 
 void CefMimeHandlerViewGuestDelegate::OnGuestDetached() {
   content::WebContents* web_contents = guest_->web_contents();
   DCHECK(web_contents);
 
-  CefRefPtr<CefBrowserHostImpl> owner_browser =
-      CefBrowserHostImpl::GetBrowserForContents(owner_web_contents_);
+  CefRefPtr<AlloyBrowserHostImpl> owner_browser =
+      AlloyBrowserHostImpl::GetBrowserForContents(owner_web_contents_);
   DCHECK(owner_browser);
 
   // Disassociate guest state information with the owner browser.
-  owner_browser->browser_info()->RemoveFrame(web_contents->GetMainFrame());
+  owner_browser->browser_info()->RemoveFrame(
+      web_contents->GetPrimaryMainFrame());
 }
 
 bool CefMimeHandlerViewGuestDelegate::HandleContextMenu(
-    content::WebContents* web_contents,
+    content::RenderFrameHost& render_frame_host,
     const content::ContextMenuParams& params) {
-  content::ContextMenuParams new_params = params;
-
-  gfx::Point guest_coordinates =
-      static_cast<content::WebContentsImpl*>(web_contents)
-          ->GetBrowserPluginGuest()
-          ->GetScreenCoordinates(gfx::Point());
-
-  // Adjust (x,y) position for offset from guest to embedder.
-  new_params.x += guest_coordinates.x();
-  new_params.y += guest_coordinates.y();
-
-  CefRefPtr<CefBrowserHostImpl> owner_browser =
-      CefBrowserHostImpl::GetBrowserForContents(owner_web_contents_);
+  CefRefPtr<AlloyBrowserHostImpl> owner_browser =
+      AlloyBrowserHostImpl::GetBrowserForContents(owner_web_contents_);
   DCHECK(owner_browser);
 
-  return owner_browser->HandleContextMenu(web_contents, new_params);
+  return owner_browser->ShowContextMenu(params);
 }
 
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/mime_handler_view_guest_delegate.h b/src/libcef/browser/extensions/mime_handler_view_guest_delegate.h
index 46e34cf..96b413b 100644
--- a/src/libcef/browser/extensions/mime_handler_view_guest_delegate.h
+++ b/src/libcef/browser/extensions/mime_handler_view_guest_delegate.h
@@ -18,6 +18,12 @@
 class CefMimeHandlerViewGuestDelegate : public MimeHandlerViewGuestDelegate {
  public:
   explicit CefMimeHandlerViewGuestDelegate(MimeHandlerViewGuest* guest);
+
+  CefMimeHandlerViewGuestDelegate(const CefMimeHandlerViewGuestDelegate&) =
+      delete;
+  CefMimeHandlerViewGuestDelegate& operator=(
+      const CefMimeHandlerViewGuestDelegate&) = delete;
+
   ~CefMimeHandlerViewGuestDelegate() override;
 
   // MimeHandlerViewGuestDelegate methods.
@@ -25,14 +31,12 @@
       content::WebContents::CreateParams* params) override;
   void OnGuestAttached() override;
   void OnGuestDetached() override;
-  bool HandleContextMenu(content::WebContents* web_contents,
+  bool HandleContextMenu(content::RenderFrameHost& render_frame_host,
                          const content::ContextMenuParams& params) override;
 
  private:
   MimeHandlerViewGuest* guest_;  // Owns us.
   content::WebContents* owner_web_contents_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefMimeHandlerViewGuestDelegate);
 };
 
 }  // namespace extensions
diff --git a/src/libcef/browser/extensions/pdf_extension_util.cc b/src/libcef/browser/extensions/pdf_extension_util.cc
deleted file mode 100644
index 9e3de9e..0000000
--- a/src/libcef/browser/extensions/pdf_extension_util.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/extensions/pdf_extension_util.h"
-
-#include "base/strings/string_util.h"
-#include "chrome/grit/browser_resources.h"
-#include "ui/base/resource/resource_bundle.h"
-
-namespace extensions {
-namespace pdf_extension_util {
-
-namespace {
-
-// Tags in the manifest to be replaced.
-const char kNameTag[] = "<NAME>";
-
-}  // namespace
-
-// These should match the keys for the Chrome and Chromium PDF Viewer entries in
-// chrome/browser/resources/plugin_metadata/plugins_*.json.
-#if defined(GOOGLE_CHROME_BUILD)
-const char kPdfResourceIdentifier[] = "google-chrome-pdf";
-#else
-const char kPdfResourceIdentifier[] = "chromium-pdf";
-#endif
-
-// Match the GOOGLE_CHROME_BUILD value from ChromeContentClient::kPDFPluginName
-// to avoid breaking Websites that specifically look for this string in the
-// plugin list.
-const char kPdfPluginName[] = "Chrome PDF Viewer";
-
-std::string GetManifest() {
-  std::string manifest_contents =
-      ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
-          IDR_PDF_MANIFEST);
-  DCHECK(manifest_contents.find(kNameTag) != std::string::npos);
-  base::ReplaceFirstSubstringAfterOffset(&manifest_contents, 0, kNameTag,
-                                         kPdfPluginName);
-
-  return manifest_contents;
-}
-
-}  // namespace pdf_extension_util
-}  // namespace extensions
diff --git a/src/libcef/browser/extensions/pdf_extension_util.h b/src/libcef/browser/extensions/pdf_extension_util.h
deleted file mode 100644
index 7293af2..0000000
--- a/src/libcef/browser/extensions/pdf_extension_util.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_PDF_EXTENSION_UTIL_H_
-#define CEF_LIBCEF_BROWSER_EXTENSIONS_PDF_EXTENSION_UTIL_H_
-
-#include <string>
-
-namespace extensions {
-namespace pdf_extension_util {
-
-// The ResourceIdentifier for the PDF Viewer plugin.
-extern const char kPdfResourceIdentifier[];
-
-// The name of the PDF Viewer plugin.
-extern const char kPdfPluginName[];
-
-// Return the extensions manifest for PDF. The manifest is loaded from
-// browser_resources.grd and certain fields are replaced based on what chrome
-// flags are enabled.
-std::string GetManifest();
-
-}  // namespace pdf_extension_util
-}  // namespace extensions
-
-#endif  // CEF_LIBCEF_BROWSER_EXTENSIONS_PDF_EXTENSION_UTIL_H_
diff --git a/src/libcef/browser/extensions/pdf_web_contents_helper_client.cc b/src/libcef/browser/extensions/pdf_web_contents_helper_client.cc
deleted file mode 100644
index 910aa0e..0000000
--- a/src/libcef/browser/extensions/pdf_web_contents_helper_client.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/extensions/pdf_web_contents_helper_client.h"
-
-#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
-
-namespace extensions {
-
-CefPDFWebContentsHelperClient::CefPDFWebContentsHelperClient() {}
-
-CefPDFWebContentsHelperClient::~CefPDFWebContentsHelperClient() {}
-
-void CefPDFWebContentsHelperClient::UpdateContentRestrictions(
-    content::WebContents* contents,
-    int content_restrictions) {}
-
-void CefPDFWebContentsHelperClient::OnPDFHasUnsupportedFeature(
-    content::WebContents* contents) {}
-
-void CefPDFWebContentsHelperClient::OnSaveURL(content::WebContents* contents) {}
-
-void CefPDFWebContentsHelperClient::SetPluginCanSave(
-    content::WebContents* contents,
-    bool can_save) {
-  auto* guest_view =
-      extensions::MimeHandlerViewGuest::FromWebContents(contents);
-  if (guest_view)
-    guest_view->SetPluginCanSave(can_save);
-}
-
-}  // namespace extensions
diff --git a/src/libcef/browser/extensions/pdf_web_contents_helper_client.h b/src/libcef/browser/extensions/pdf_web_contents_helper_client.h
deleted file mode 100644
index 13ed29e..0000000
--- a/src/libcef/browser/extensions/pdf_web_contents_helper_client.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_BROWSER_EXTENSIONS_PDF_WEB_CONTENTS_HELPER_CLIENT_H_
-#define CEF_LIBCEF_BROWSER_EXTENSIONS_PDF_WEB_CONTENTS_HELPER_CLIENT_H_
-
-#include "base/macros.h"
-#include "components/pdf/browser/pdf_web_contents_helper_client.h"
-
-namespace extensions {
-
-class CefPDFWebContentsHelperClient : public pdf::PDFWebContentsHelperClient {
- public:
-  CefPDFWebContentsHelperClient();
-  ~CefPDFWebContentsHelperClient() override;
-
- private:
-  // pdf::PDFWebContentsHelperClient:
-  void UpdateContentRestrictions(content::WebContents* contents,
-                                 int content_restrictions) override;
-  void OnPDFHasUnsupportedFeature(content::WebContents* contents) override;
-  void OnSaveURL(content::WebContents* contents) override;
-  void SetPluginCanSave(content::WebContents* contents, bool can_save) override;
-
-  DISALLOW_COPY_AND_ASSIGN(CefPDFWebContentsHelperClient);
-};
-
-}  // namespace extensions
-
-#endif  // CEF_LIBCEF_BROWSER_EXTENSIONS_PDF_WEB_CONTENTS_HELPER_CLIENT_H_
diff --git a/src/libcef/browser/extensions/value_store/cef_value_store.cc b/src/libcef/browser/extensions/value_store/cef_value_store.cc
index 569c336..0609d61 100644
--- a/src/libcef/browser/extensions/value_store/cef_value_store.cc
+++ b/src/libcef/browser/extensions/value_store/cef_value_store.cc
@@ -5,10 +5,13 @@
 
 #include "libcef/browser/extensions/value_store/cef_value_store.h"
 
+#include <memory>
+#include <ostream>
 #include <utility>
 
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
+#include "base/notreached.h"
+
+namespace value_store {
 
 namespace {
 
@@ -22,9 +25,8 @@
 
 }  // namespace
 
-CefValueStore::CefValueStore() : read_count_(0), write_count_(0) {}
-
-CefValueStore::~CefValueStore() {}
+CefValueStore::CefValueStore() = default;
+CefValueStore::~CefValueStore() = default;
 
 void CefValueStore::set_status_code(StatusCode status_code) {
   status_ = ValueStore::Status(status_code, kGenericErrorMessage);
@@ -32,19 +34,19 @@
 
 size_t CefValueStore::GetBytesInUse(const std::string& key) {
   // Let SettingsStorageQuotaEnforcer implement this.
-  NOTREACHED();
+  DCHECK(false) << "Not implemented";
   return 0;
 }
 
 size_t CefValueStore::GetBytesInUse(const std::vector<std::string>& keys) {
   // Let SettingsStorageQuotaEnforcer implement this.
-  NOTREACHED();
+  DCHECK(false) << "Not implemented";
   return 0;
 }
 
 size_t CefValueStore::GetBytesInUse() {
   // Let SettingsStorageQuotaEnforcer implement this.
-  NOTREACHED();
+  DCHECK(false) << "Not implemented";
   return 0;
 }
 
@@ -55,15 +57,15 @@
 ValueStore::ReadResult CefValueStore::Get(
     const std::vector<std::string>& keys) {
   read_count_++;
-  if (!status_.ok())
+  if (!status_.ok()) {
     return ReadResult(CreateStatusCopy(status_));
+  }
 
-  auto settings = std::make_unique<base::DictionaryValue>();
-  for (std::vector<std::string>::const_iterator it = keys.begin();
-       it != keys.end(); ++it) {
-    base::Value* value = nullptr;
-    if (storage_.GetWithoutPathExpansion(*it, &value)) {
-      settings->SetWithoutPathExpansion(*it, value->CreateDeepCopy());
+  base::Value::Dict settings;
+  for (const auto& key : keys) {
+    base::Value* value = storage_.Find(key);
+    if (value) {
+      settings.Set(key, value->Clone());
     }
   }
   return ReadResult(std::move(settings), CreateStatusCopy(status_));
@@ -71,38 +73,37 @@
 
 ValueStore::ReadResult CefValueStore::Get() {
   read_count_++;
-  if (!status_.ok())
+  if (!status_.ok()) {
     return ReadResult(CreateStatusCopy(status_));
-  return ReadResult(storage_.CreateDeepCopy(), CreateStatusCopy(status_));
+  }
+  return ReadResult(storage_.Clone(), CreateStatusCopy(status_));
 }
 
 ValueStore::WriteResult CefValueStore::Set(WriteOptions options,
                                            const std::string& key,
                                            const base::Value& value) {
-  base::DictionaryValue settings;
-  settings.SetWithoutPathExpansion(key, value.CreateDeepCopy());
+  base::Value::Dict settings;
+  settings.Set(key, value.Clone());
   return Set(options, settings);
 }
 
-ValueStore::WriteResult CefValueStore::Set(
-    WriteOptions options,
-    const base::DictionaryValue& settings) {
+ValueStore::WriteResult CefValueStore::Set(WriteOptions options,
+                                           const base::Value::Dict& settings) {
   write_count_++;
-  if (!status_.ok())
+  if (!status_.ok()) {
     return WriteResult(CreateStatusCopy(status_));
+  }
 
-  std::unique_ptr<ValueStoreChangeList> changes(new ValueStoreChangeList());
-  for (base::DictionaryValue::Iterator it(settings); !it.IsAtEnd();
-       it.Advance()) {
-    base::Value* old_value = nullptr;
-    if (!storage_.GetWithoutPathExpansion(it.key(), &old_value) ||
-        !old_value->Equals(&it.value())) {
-      changes->push_back(ValueStoreChange(
-          it.key(),
-          old_value ? base::Optional<base::Value>(old_value->Clone())
-                    : base::nullopt,
-          it.value().Clone()));
-      storage_.SetWithoutPathExpansion(it.key(), it.value().CreateDeepCopy());
+  ValueStoreChangeList changes;
+  for (const auto [key, value] : settings) {
+    base::Value* old_value = storage_.Find(key);
+    if (!old_value || *old_value != value) {
+      changes.emplace_back(key,
+                           old_value
+                               ? absl::optional<base::Value>(old_value->Clone())
+                               : absl::nullopt,
+                           value.Clone());
+      storage_.Set(key, value.Clone());
     }
   }
   return WriteResult(std::move(changes), CreateStatusCopy(status_));
@@ -115,16 +116,15 @@
 ValueStore::WriteResult CefValueStore::Remove(
     const std::vector<std::string>& keys) {
   write_count_++;
-  if (!status_.ok())
+  if (!status_.ok()) {
     return WriteResult(CreateStatusCopy(status_));
+  }
 
-  std::unique_ptr<ValueStoreChangeList> changes(new ValueStoreChangeList());
-  for (std::vector<std::string>::const_iterator it = keys.begin();
-       it != keys.end(); ++it) {
-    std::unique_ptr<base::Value> old_value;
-    if (storage_.RemoveWithoutPathExpansion(*it, &old_value)) {
-      changes->push_back(
-          ValueStoreChange(*it, std::move(*old_value), base::nullopt));
+  ValueStoreChangeList changes;
+  for (auto const& key : keys) {
+    absl::optional<base::Value> old_value = storage_.Extract(key);
+    if (old_value.has_value()) {
+      changes.emplace_back(key, std::move(*old_value), absl::nullopt);
     }
   }
   return WriteResult(std::move(changes), CreateStatusCopy(status_));
@@ -132,9 +132,10 @@
 
 ValueStore::WriteResult CefValueStore::Clear() {
   std::vector<std::string> keys;
-  for (base::DictionaryValue::Iterator it(storage_); !it.IsAtEnd();
-       it.Advance()) {
-    keys.push_back(it.key());
+  for (const auto [key, value] : storage_) {
+    keys.push_back(key);
   }
   return Remove(keys);
-}
\ No newline at end of file
+}
+
+}  // namespace value_store
diff --git a/src/libcef/browser/extensions/value_store/cef_value_store.h b/src/libcef/browser/extensions/value_store/cef_value_store.h
index c76b46f..fe41c34 100644
--- a/src/libcef/browser/extensions/value_store/cef_value_store.h
+++ b/src/libcef/browser/extensions/value_store/cef_value_store.h
@@ -11,29 +11,31 @@
 #include <string>
 #include <vector>
 
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "extensions/browser/value_store/value_store.h"
+#include "components/value_store/value_store.h"
 
-// Implementation Based on TestingValueStore
-// ValueStore with an in-memory storage but the ability to
-// optionally fail all operations.
+namespace value_store {
+
+// Implementation Based on TestingValueStore.
+// ValueStore with an in-memory storage but the ability to optionally fail all
+// operations.
 class CefValueStore : public ValueStore {
  public:
   CefValueStore();
   ~CefValueStore() override;
+  CefValueStore(const CefValueStore&) = delete;
+  CefValueStore& operator=(const CefValueStore&) = delete;
+
+  // Sets the error code for requests. If OK, errors won't be thrown.
+  // Defaults to OK.
+  void set_status_code(StatusCode status_code);
 
   // Accessors for the number of reads/writes done by this value store. Each
   // Get* operation (except for the BytesInUse ones) counts as one read, and
   // each Set*/Remove/Clear operation counts as one write. This is useful in
   // tests seeking to assert that some number of reads/writes to their
   // underlying value store have (or have not) happened.
-  int read_count() const { return read_count_; }
-  int write_count() const { return write_count_; }
-
-  // Sets the error code for requests. If OK, errors won't be thrown.
-  // Defaults to OK.
-  void set_status_code(StatusCode status_code);
+  int read_count() { return read_count_; }
+  int write_count() { return write_count_; }
 
   // ValueStore implementation.
   size_t GetBytesInUse(const std::string& key) override;
@@ -46,18 +48,18 @@
                   const std::string& key,
                   const base::Value& value) override;
   WriteResult Set(WriteOptions options,
-                  const base::DictionaryValue& values) override;
+                  const base::Value::Dict& values) override;
   WriteResult Remove(const std::string& key) override;
   WriteResult Remove(const std::vector<std::string>& keys) override;
   WriteResult Clear() override;
 
  private:
-  base::DictionaryValue storage_;
-  int read_count_;
-  int write_count_;
+  base::Value::Dict storage_;
+  int read_count_ = 0;
+  int write_count_ = 0;
   ValueStore::Status status_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefValueStore);
 };
 
+}  // namespace value_store
+
 #endif  // CEF_LIBCEF_BROWSER_EXTENSIONS_VALUE_STORE_CEF_VALUE_STORE_H_
diff --git a/src/libcef/browser/extensions/value_store/cef_value_store_factory.cc b/src/libcef/browser/extensions/value_store/cef_value_store_factory.cc
index cd52d61..b655210 100644
--- a/src/libcef/browser/extensions/value_store/cef_value_store_factory.cc
+++ b/src/libcef/browser/extensions/value_store/cef_value_store_factory.cc
@@ -5,187 +5,71 @@
 
 #include "libcef/browser/extensions/value_store/cef_value_store_factory.h"
 
-#include "base/memory/ptr_util.h"
-#include "extensions/browser/value_store/leveldb_value_store.h"
 #include "libcef/browser/extensions/value_store/cef_value_store.h"
 
+#include "base/containers/contains.h"
+#include "base/memory/ptr_util.h"
+#include "components/value_store/leveldb_value_store.h"
+
 namespace {
 
 const char kUMAClientName[] = "Cef";
 
 }  // namespace
 
-namespace extensions {
-
-using SettingsNamespace = settings_namespace::Namespace;
-
-CefValueStoreFactory::StorageHelper::StorageHelper() = default;
-
-CefValueStoreFactory::StorageHelper::~StorageHelper() = default;
-
-std::set<ExtensionId> CefValueStoreFactory::StorageHelper::GetKnownExtensionIDs(
-    ModelType model_type) const {
-  std::set<ExtensionId> ids;
-  switch (model_type) {
-    case ValueStoreFactory::ModelType::APP:
-      for (const auto& key : app_stores_)
-        ids.insert(key.first);
-      break;
-    case ValueStoreFactory::ModelType::EXTENSION:
-      for (const auto& key : extension_stores_)
-        ids.insert(key.first);
-      break;
-  }
-  return ids;
-}
-
-void CefValueStoreFactory::StorageHelper::Reset() {
-  app_stores_.clear();
-  extension_stores_.clear();
-}
-
-ValueStore* CefValueStoreFactory::StorageHelper::AddValueStore(
-    const ExtensionId& extension_id,
-    ValueStore* value_store,
-    ModelType model_type) {
-  if (model_type == ValueStoreFactory::ModelType::APP) {
-    DCHECK(app_stores_.find(extension_id) == app_stores_.end());
-    app_stores_[extension_id] = value_store;
-  } else {
-    DCHECK(extension_stores_.find(extension_id) == extension_stores_.end());
-    extension_stores_[extension_id] = value_store;
-  }
-  return value_store;
-}
-
-void CefValueStoreFactory::StorageHelper::DeleteSettings(
-    const ExtensionId& extension_id,
-    ModelType model_type) {
-  switch (model_type) {
-    case ValueStoreFactory::ModelType::APP:
-      app_stores_.erase(extension_id);
-      break;
-    case ValueStoreFactory::ModelType::EXTENSION:
-      extension_stores_.erase(extension_id);
-      break;
-  }
-}
-
-bool CefValueStoreFactory::StorageHelper::HasSettings(
-    const ExtensionId& extension_id,
-    ModelType model_type) const {
-  switch (model_type) {
-    case ValueStoreFactory::ModelType::APP:
-      return app_stores_.find(extension_id) != app_stores_.end();
-    case ValueStoreFactory::ModelType::EXTENSION:
-      return extension_stores_.find(extension_id) != extension_stores_.end();
-  }
-  NOTREACHED();
-  return false;
-}
-
-ValueStore* CefValueStoreFactory::StorageHelper::GetExisting(
-    const ExtensionId& extension_id) const {
-  auto it = app_stores_.find(extension_id);
-  if (it != app_stores_.end())
-    return it->second;
-  it = extension_stores_.find(extension_id);
-  if (it != extension_stores_.end())
-    return it->second;
-  return nullptr;
-}
+namespace value_store {
 
 CefValueStoreFactory::CefValueStoreFactory() = default;
 
 CefValueStoreFactory::CefValueStoreFactory(const base::FilePath& db_path)
     : db_path_(db_path) {}
 
-CefValueStoreFactory::~CefValueStoreFactory() {}
+CefValueStoreFactory::~CefValueStoreFactory() = default;
 
-std::unique_ptr<ValueStore> CefValueStoreFactory::CreateRulesStore() {
-  if (db_path_.empty())
-    last_created_store_ = new CefValueStore();
-  else
-    last_created_store_ = new LeveldbValueStore(kUMAClientName, db_path_);
-  return base::WrapUnique(last_created_store_);
-}
-
-std::unique_ptr<ValueStore> CefValueStoreFactory::CreateStateStore() {
-  return CreateRulesStore();
-}
-
-CefValueStoreFactory::StorageHelper& CefValueStoreFactory::GetStorageHelper(
-    SettingsNamespace settings_namespace) {
-  switch (settings_namespace) {
-    case settings_namespace::LOCAL:
-      return local_helper_;
-    case settings_namespace::SYNC:
-      return sync_helper_;
-    case settings_namespace::MANAGED:
-      return managed_helper_;
-    case settings_namespace::INVALID:
-      break;
-  }
-  NOTREACHED();
-  return local_helper_;
-}
-
-std::unique_ptr<ValueStore> CefValueStoreFactory::CreateSettingsStore(
-    SettingsNamespace settings_namespace,
-    ModelType model_type,
-    const ExtensionId& extension_id) {
-  std::unique_ptr<ValueStore> settings_store(CreateRulesStore());
-  // Note: This factory is purposely keeping the raw pointers to each ValueStore
-  //       created. Tests using CefValueStoreFactory must be careful to keep
-  //       those ValueStore's alive for the duration of their test.
-  GetStorageHelper(settings_namespace)
-      .AddValueStore(extension_id, settings_store.get(), model_type);
-  return settings_store;
+std::unique_ptr<ValueStore> CefValueStoreFactory::CreateValueStore(
+    const base::FilePath& directory,
+    const std::string& uma_client_name) {
+  std::unique_ptr<ValueStore> value_store(CreateStore());
+  // This factory is purposely keeping the raw pointers to each ValueStore
+  // created. Cefs using CefValueStoreFactory must be careful to keep
+  // those ValueStore's alive for the duration of their test.
+  value_store_map_[directory] = value_store.get();
+  return value_store;
 }
 
 ValueStore* CefValueStoreFactory::LastCreatedStore() const {
   return last_created_store_;
 }
 
-void CefValueStoreFactory::DeleteSettings(SettingsNamespace settings_namespace,
-                                          ModelType model_type,
-                                          const ExtensionId& extension_id) {
-  GetStorageHelper(settings_namespace).DeleteSettings(extension_id, model_type);
+void CefValueStoreFactory::DeleteValueStore(const base::FilePath& directory) {
+  value_store_map_.erase(directory);
 }
 
-bool CefValueStoreFactory::HasSettings(SettingsNamespace settings_namespace,
-                                       ModelType model_type,
-                                       const ExtensionId& extension_id) {
-  return GetStorageHelper(settings_namespace)
-      .HasSettings(extension_id, model_type);
-}
-
-std::set<ExtensionId> CefValueStoreFactory::GetKnownExtensionIDs(
-    SettingsNamespace settings_namespace,
-    ModelType model_type) const {
-  return const_cast<CefValueStoreFactory*>(this)
-      ->GetStorageHelper(settings_namespace)
-      .GetKnownExtensionIDs(model_type);
+bool CefValueStoreFactory::HasValueStore(const base::FilePath& directory) {
+  return base::Contains(value_store_map_, directory);
 }
 
 ValueStore* CefValueStoreFactory::GetExisting(
-    const ExtensionId& extension_id) const {
-  ValueStore* existing_store = local_helper_.GetExisting(extension_id);
-  if (existing_store)
-    return existing_store;
-  existing_store = sync_helper_.GetExisting(extension_id);
-  if (existing_store)
-    return existing_store;
-  existing_store = managed_helper_.GetExisting(extension_id);
-  DCHECK(existing_store != nullptr);
-  return existing_store;
+    const base::FilePath& directory) const {
+  auto it = value_store_map_.find(directory);
+  DCHECK(it != value_store_map_.end());
+  return it->second;
 }
 
 void CefValueStoreFactory::Reset() {
   last_created_store_ = nullptr;
-  local_helper_.Reset();
-  sync_helper_.Reset();
-  managed_helper_.Reset();
+  value_store_map_.clear();
 }
 
-}  // namespace extensions
+std::unique_ptr<ValueStore> CefValueStoreFactory::CreateStore() {
+  std::unique_ptr<ValueStore> store;
+  if (db_path_.empty()) {
+    store = std::make_unique<CefValueStore>();
+  } else {
+    store = std::make_unique<LeveldbValueStore>(kUMAClientName, db_path_);
+  }
+  last_created_store_ = store.get();
+  return store;
+}
+
+}  // namespace value_store
diff --git a/src/libcef/browser/extensions/value_store/cef_value_store_factory.h b/src/libcef/browser/extensions/value_store/cef_value_store_factory.h
index 073b5f7..3a60e65 100644
--- a/src/libcef/browser/extensions/value_store/cef_value_store_factory.h
+++ b/src/libcef/browser/extensions/value_store/cef_value_store_factory.h
@@ -8,90 +8,54 @@
 
 #include <map>
 #include <memory>
-#include <set>
 
 #include "base/files/file_path.h"
-#include "extensions/browser/value_store/value_store_factory.h"
-#include "extensions/common/extension_id.h"
+#include "components/value_store/value_store_factory.h"
+
+namespace value_store {
 
 class ValueStore;
 
-namespace extensions {
-
-// Will either open a database on disk (if path provided) returning a
-// |LeveldbValueStore|. Otherwise a new |CefValueStore| instance will be
-// returned.
+// Based on TestValueStoreFactory. Will either open a database on disk (if path
+// provided) returning a |LeveldbValueStore|. Otherwise a new |CefingValueStore|
+// instance will be returned.
 class CefValueStoreFactory : public ValueStoreFactory {
  public:
   CefValueStoreFactory();
   explicit CefValueStoreFactory(const base::FilePath& db_path);
+  CefValueStoreFactory(const CefValueStoreFactory&) = delete;
+  CefValueStoreFactory& operator=(const CefValueStoreFactory&) = delete;
 
   // ValueStoreFactory
-  std::unique_ptr<ValueStore> CreateRulesStore() override;
-  std::unique_ptr<ValueStore> CreateStateStore() override;
-  std::unique_ptr<ValueStore> CreateSettingsStore(
-      settings_namespace::Namespace settings_namespace,
-      ModelType model_type,
-      const ExtensionId& extension_id) override;
-  void DeleteSettings(settings_namespace::Namespace settings_namespace,
-                      ModelType model_type,
-                      const ExtensionId& extension_id) override;
-  bool HasSettings(settings_namespace::Namespace settings_namespace,
-                   ModelType model_type,
-                   const ExtensionId& extension_id) override;
-  std::set<ExtensionId> GetKnownExtensionIDs(
-      settings_namespace::Namespace settings_namespace,
-      ModelType model_type) const override;
+  std::unique_ptr<ValueStore> CreateValueStore(
+      const base::FilePath& directory,
+      const std::string& uma_client_name) override;
+  void DeleteValueStore(const base::FilePath& directory) override;
+  bool HasValueStore(const base::FilePath& directory) override;
 
   // Return the last created |ValueStore|. Use with caution as this may return
   // a dangling pointer since the creator now owns the ValueStore which can be
   // deleted at any time.
   ValueStore* LastCreatedStore() const;
-  // Return a previously created |ValueStore| for an extension.
-  ValueStore* GetExisting(const ExtensionId& extension_id) const;
+  // Return the previously created |ValueStore| in the given directory.
+  ValueStore* GetExisting(const base::FilePath& directory) const;
   // Reset this class (as if just created).
   void Reset();
 
  private:
-  // Manages a collection of |ValueStore|'s created for an app/extension.
-  // One of these exists for each setting type.
-  class StorageHelper {
-   public:
-    StorageHelper();
-    ~StorageHelper();
-    std::set<ExtensionId> GetKnownExtensionIDs(ModelType model_type) const;
-    ValueStore* AddValueStore(const ExtensionId& extension_id,
-                              ValueStore* value_store,
-                              ModelType model_type);
-    void DeleteSettings(const ExtensionId& extension_id, ModelType model_type);
-    bool HasSettings(const ExtensionId& extension_id,
-                     ModelType model_type) const;
-    void Reset();
-    ValueStore* GetExisting(const ExtensionId& extension_id) const;
-
-   private:
-    std::map<ExtensionId, ValueStore*> app_stores_;
-    std::map<ExtensionId, ValueStore*> extension_stores_;
-
-    DISALLOW_COPY_AND_ASSIGN(StorageHelper);
-  };
-
-  StorageHelper& GetStorageHelper(
-      settings_namespace::Namespace settings_namespace);
-
   ~CefValueStoreFactory() override;
+
+  std::unique_ptr<ValueStore> CreateStore();
+
   base::FilePath db_path_;
   ValueStore* last_created_store_ = nullptr;
 
-  // None of these value stores are owned by this factory, so care must be
-  // taken when calling GetExisting.
-  StorageHelper local_helper_;
-  StorageHelper sync_helper_;
-  StorageHelper managed_helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefValueStoreFactory);
+  // A mapping from directories to their ValueStore. None of these value
+  // stores are owned by this factory, so care must be taken when calling
+  // GetExisting.
+  std::map<base::FilePath, ValueStore*> value_store_map_;
 };
 
-}  // namespace extensions
+}  // namespace value_store
 
 #endif  // CEF_LIBCEF_BROWSER_EXTENSIONS_VALUE_STORE_CEF_VALUE_STORE_FACTORY_H_
diff --git a/src/libcef/browser/file_dialog_manager.cc b/src/libcef/browser/file_dialog_manager.cc
index eb25c9f..13b2b30 100644
--- a/src/libcef/browser/file_dialog_manager.cc
+++ b/src/libcef/browser/file_dialog_manager.cc
@@ -8,19 +8,23 @@
 #include <utility>
 
 #include "include/cef_dialog_handler.h"
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/browser_host_base.h"
+#include "libcef/browser/context.h"
 #include "libcef/browser/thread_util.h"
 
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/file_select_helper.h"
 #include "content/public/browser/file_select_listener.h"
 #include "content/public/browser/render_frame_host.h"
-#include "content/public/common/file_chooser_file_info.h"
-#include "net/base/directory_lister.h"
+#include "ui/shell_dialogs/select_file_policy.h"
+
+using blink::mojom::FileChooserParams;
 
 namespace {
 
 class CefFileDialogCallbackImpl : public CefFileDialogCallback {
  public:
-  using CallbackType = CefFileDialogRunner::RunFileChooserCallback;
+  using CallbackType = CefFileDialogManager::RunFileChooserCallback;
 
   explicit CefFileDialogCallbackImpl(CallbackType callback)
       : callback_(std::move(callback)) {}
@@ -38,22 +42,22 @@
     }
   }
 
-  void Continue(int selected_accept_filter,
-                const std::vector<CefString>& file_paths) override {
+  void Continue(const std::vector<CefString>& file_paths) override {
     if (CEF_CURRENTLY_ON_UIT()) {
       if (!callback_.is_null()) {
         std::vector<base::FilePath> vec;
         if (!file_paths.empty()) {
           std::vector<CefString>::const_iterator it = file_paths.begin();
-          for (; it != file_paths.end(); ++it)
+          for (; it != file_paths.end(); ++it) {
             vec.push_back(base::FilePath(*it));
+          }
         }
-        std::move(callback_).Run(selected_accept_filter, vec);
+        std::move(callback_).Run(vec);
       }
     } else {
       CEF_POST_TASK(CEF_UIT,
                     base::BindOnce(&CefFileDialogCallbackImpl::Continue, this,
-                                   selected_accept_filter, file_paths));
+                                   file_paths));
     }
   }
 
@@ -68,13 +72,13 @@
     }
   }
 
-  CallbackType Disconnect() WARN_UNUSED_RESULT { return std::move(callback_); }
+  [[nodiscard]] CallbackType Disconnect() { return std::move(callback_); }
 
  private:
   static void CancelNow(CallbackType callback) {
     CEF_REQUIRE_UIT();
     std::vector<base::FilePath> file_paths;
-    std::move(callback).Run(0, file_paths);
+    std::move(callback).Run(file_paths);
   }
 
   CallbackType callback_;
@@ -83,76 +87,211 @@
 };
 
 void RunFileDialogDismissed(CefRefPtr<CefRunFileDialogCallback> callback,
-                            int selected_accept_filter,
                             const std::vector<base::FilePath>& file_paths) {
   std::vector<CefString> paths;
   if (file_paths.size() > 0) {
-    for (size_t i = 0; i < file_paths.size(); ++i)
+    for (size_t i = 0; i < file_paths.size(); ++i) {
       paths.push_back(file_paths[i].value());
+    }
   }
-  callback->OnFileDialogDismissed(selected_accept_filter, paths);
+  callback->OnFileDialogDismissed(paths);
 }
 
-class UploadFolderHelper
-    : public net::DirectoryLister::DirectoryListerDelegate {
- public:
-  explicit UploadFolderHelper(
-      CefFileDialogRunner::RunFileChooserCallback callback)
-      : callback_(std::move(callback)) {}
+// Based on net/base/filename_util_internal.cc FilePathToString16().
+std::u16string FilePathTypeToString16(const base::FilePath::StringType& str) {
+  std::u16string result;
+#if BUILDFLAG(IS_WIN)
+  result.assign(str.begin(), str.end());
+#elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
+  if (!str.empty()) {
+    base::UTF8ToUTF16(str.c_str(), str.size(), &result);
+  }
+#endif
+  return result;
+}
 
-  ~UploadFolderHelper() override {
-    if (!callback_.is_null()) {
-      if (CEF_CURRENTLY_ON_UIT()) {
-        CancelNow(std::move(callback_));
-      } else {
-        CEF_POST_TASK(CEF_UIT, base::BindOnce(&UploadFolderHelper::CancelNow,
-                                              std::move(callback_)));
+FileChooserParams SelectFileToFileChooserParams(
+    ui::SelectFileDialog::Type type,
+    const std::u16string& title,
+    const base::FilePath& default_path,
+    const ui::SelectFileDialog::FileTypeInfo* file_types) {
+  FileChooserParams params;
+
+  absl::optional<FileChooserParams::Mode> mode;
+  switch (type) {
+    case ui::SelectFileDialog::Type::SELECT_UPLOAD_FOLDER:
+      mode = FileChooserParams::Mode::kUploadFolder;
+      break;
+    case ui::SelectFileDialog::Type::SELECT_SAVEAS_FILE:
+      mode = FileChooserParams::Mode::kSave;
+      break;
+    case ui::SelectFileDialog::Type::SELECT_OPEN_FILE:
+      mode = FileChooserParams::Mode::kOpen;
+      break;
+    case ui::SelectFileDialog::Type::SELECT_OPEN_MULTI_FILE:
+      mode = FileChooserParams::Mode::kOpenMultiple;
+      break;
+    default:
+      NOTIMPLEMENTED();
+      return params;
+  }
+
+  params.mode = *mode;
+  params.title = title;
+  params.default_file_name = default_path;
+
+  // Note that this translation will lose any mime-type based filters that
+  // may have existed in the original FileChooserParams::accept_types if this
+  // dialog was created via FileSelectHelper::RunFileChooser.
+  if (file_types) {
+    // A list of allowed extensions. For example, it might be
+    //   { { "htm", "html" }, { "txt" } }
+    for (auto& vec : file_types->extensions) {
+      for (auto& ext : vec) {
+        params.accept_types.push_back(
+            FilePathTypeToString16(FILE_PATH_LITERAL(".") + ext));
       }
     }
   }
 
-  void OnListFile(
-      const net::DirectoryLister::DirectoryListerData& data) override {
-    CEF_REQUIRE_UIT();
-    if (!data.info.IsDirectory())
-      select_files_.push_back(data.path);
-  }
+  return params;
+}
 
-  void OnListDone(int error) override {
-    CEF_REQUIRE_UIT();
-    if (!callback_.is_null()) {
-      std::move(callback_).Run(0, select_files_);
-    }
-  }
+class CefFileSelectListener : public content::FileSelectListener {
+ public:
+  using CallbackType = CefFileDialogManager::RunFileChooserCallback;
+
+  explicit CefFileSelectListener(CallbackType callback)
+      : callback_(std::move(callback)) {}
 
  private:
-  static void CancelNow(CefFileDialogRunner::RunFileChooserCallback callback) {
-    CEF_REQUIRE_UIT();
-    std::vector<base::FilePath> file_paths;
-    std::move(callback).Run(0, file_paths);
+  ~CefFileSelectListener() override = default;
+
+  void FileSelected(std::vector<blink::mojom::FileChooserFileInfoPtr> files,
+                    const base::FilePath& base_dir,
+                    FileChooserParams::Mode mode) override {
+    std::vector<base::FilePath> paths;
+    if (mode == FileChooserParams::Mode::kUploadFolder) {
+      if (!base_dir.empty()) {
+        paths.push_back(base_dir);
+      }
+    } else if (!files.empty()) {
+      for (auto& file : files) {
+        if (file->is_native_file()) {
+          paths.push_back(file->get_native_file()->file_path);
+        } else {
+          NOTIMPLEMENTED();
+        }
+      }
+    }
+
+    std::move(callback_).Run(paths);
   }
 
-  CefFileDialogRunner::RunFileChooserCallback callback_;
-  std::vector<base::FilePath> select_files_;
+  void FileSelectionCanceled() override { std::move(callback_).Run({}); }
 
-  DISALLOW_COPY_AND_ASSIGN(UploadFolderHelper);
+  CallbackType callback_;
 };
 
 }  // namespace
 
-CefFileDialogManager::CefFileDialogManager(
-    CefBrowserHostImpl* browser,
-    std::unique_ptr<CefFileDialogRunner> runner)
-    : browser_(browser),
-      runner_(std::move(runner)),
-      file_chooser_pending_(false),
-      weak_ptr_factory_(this) {}
+class CefSelectFileDialogListener : public ui::SelectFileDialog::Listener {
+ public:
+  CefSelectFileDialogListener(ui::SelectFileDialog::Listener* listener,
+                              void* params,
+                              base::OnceClosure callback)
+      : listener_(listener), params_(params), callback_(std::move(callback)) {}
 
-CefFileDialogManager::~CefFileDialogManager() {}
+  CefSelectFileDialogListener(const CefSelectFileDialogListener&) = delete;
+  CefSelectFileDialogListener& operator=(const CefSelectFileDialogListener&) =
+      delete;
+
+  void Cancel(bool listener_destroyed) {
+    if (executing_) {
+      // We're likely still on the stack. Do nothing and wait for Destroy().
+      return;
+    }
+    if (listener_destroyed) {
+      // Don't execute the listener.
+      Destroy();
+    } else {
+      FileSelectionCanceled(params_);
+    }
+  }
+
+  ui::SelectFileDialog::Listener* listener() const { return listener_; }
+
+ private:
+  ~CefSelectFileDialogListener() override = default;
+
+  void FileSelected(const base::FilePath& path,
+                    int index,
+                    void* params) override {
+    DCHECK_EQ(params, params_);
+    executing_ = true;
+    listener_->FileSelected(path, index, params);
+    Destroy();
+  }
+
+  void FileSelectedWithExtraInfo(const ui::SelectedFileInfo& file,
+                                 int index,
+                                 void* params) override {
+    DCHECK_EQ(params, params_);
+    executing_ = true;
+    listener_->FileSelectedWithExtraInfo(file, index, params);
+    Destroy();
+  }
+
+  void MultiFilesSelected(const std::vector<base::FilePath>& files,
+                          void* params) override {
+    DCHECK_EQ(params, params_);
+    executing_ = true;
+    listener_->MultiFilesSelected(files, params);
+    Destroy();
+  }
+
+  void MultiFilesSelectedWithExtraInfo(
+      const std::vector<ui::SelectedFileInfo>& files,
+      void* params) override {
+    DCHECK_EQ(params, params_);
+    executing_ = true;
+    listener_->MultiFilesSelectedWithExtraInfo(files, params);
+    Destroy();
+  }
+
+  void FileSelectionCanceled(void* params) override {
+    DCHECK_EQ(params, params_);
+    executing_ = true;
+    listener_->FileSelectionCanceled(params);
+    Destroy();
+  }
+
+  void Destroy() {
+    std::move(callback_).Run();
+    delete this;
+  }
+
+  ui::SelectFileDialog::Listener* const listener_;
+  void* const params_;
+  base::OnceClosure callback_;
+
+  // Used to avoid re-entrancy from Cancel().
+  bool executing_ = false;
+};
+
+CefFileDialogManager::CefFileDialogManager(CefBrowserHostBase* browser)
+    : browser_(browser) {}
+
+CefFileDialogManager::~CefFileDialogManager() = default;
 
 void CefFileDialogManager::Destroy() {
-  DCHECK(!file_chooser_pending_);
-  runner_.reset(nullptr);
+  if (dialog_listener_) {
+    // Cancel the listener and delete related objects.
+    SelectFileDoneByListenerCallback(/*listener_destroyed=*/false);
+  }
+  DCHECK(!dialog_);
+  DCHECK(!dialog_listener_);
+  DCHECK(active_listeners_.empty());
 }
 
 void CefFileDialogManager::RunFileDialog(
@@ -160,14 +299,14 @@
     const CefString& title,
     const CefString& default_file_path,
     const std::vector<CefString>& accept_filters,
-    int selected_accept_filter,
     CefRefPtr<CefRunFileDialogCallback> callback) {
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return;
+  }
 
-  CefFileDialogRunner::FileChooserParams params;
-  switch (mode & FILE_DIALOG_TYPE_MASK) {
+  blink::mojom::FileChooserParams params;
+  switch (mode) {
     case FILE_DIALOG_OPEN:
       params.mode = blink::mojom::FileChooserParams::Mode::kOpen;
       break;
@@ -182,75 +321,161 @@
       break;
   }
 
-  DCHECK_GE(selected_accept_filter, 0);
-  params.selected_accept_filter = selected_accept_filter;
-
-  params.overwriteprompt = !!(mode & FILE_DIALOG_OVERWRITEPROMPT_FLAG);
-  params.hidereadonly = !!(mode & FILE_DIALOG_HIDEREADONLY_FLAG);
-
   params.title = title;
-  if (!default_file_path.empty())
+  if (!default_file_path.empty()) {
     params.default_file_name = base::FilePath(default_file_path);
+  }
 
   if (!accept_filters.empty()) {
     std::vector<CefString>::const_iterator it = accept_filters.begin();
-    for (; it != accept_filters.end(); ++it)
+    for (; it != accept_filters.end(); ++it) {
       params.accept_types.push_back(*it);
+    }
   }
 
-  RunFileChooser(params, base::Bind(RunFileDialogDismissed, callback));
+  RunFileChooser(params, base::BindOnce(RunFileDialogDismissed, callback));
 }
 
 void CefFileDialogManager::RunFileChooser(
-    std::unique_ptr<content::FileSelectListener> listener,
-    const blink::mojom::FileChooserParams& params) {
+    const blink::mojom::FileChooserParams& params,
+    RunFileChooserCallback callback) {
   CEF_REQUIRE_UIT();
 
-  CefFileDialogRunner::FileChooserParams cef_params;
-  static_cast<blink::mojom::FileChooserParams&>(cef_params) = params;
-
-  CefFileDialogRunner::RunFileChooserCallback callback;
-  if (params.mode == blink::mojom::FileChooserParams::Mode::kUploadFolder) {
-    callback = base::BindOnce(
-        &CefFileDialogManager::OnRunFileChooserUploadFolderDelegateCallback,
-        weak_ptr_factory_.GetWeakPtr(), params.mode, std::move(listener));
-  } else {
-    callback = base::BindOnce(
-        &CefFileDialogManager::OnRunFileChooserDelegateCallback,
-        weak_ptr_factory_.GetWeakPtr(), params.mode, std::move(listener));
-  }
-
-  RunFileChooserInternal(cef_params, std::move(callback));
-}
-
-void CefFileDialogManager::RunFileChooser(
-    const CefFileDialogRunner::FileChooserParams& params,
-    CefFileDialogRunner::RunFileChooserCallback callback) {
-  CefFileDialogRunner::RunFileChooserCallback host_callback =
-      base::BindOnce(&CefFileDialogManager::OnRunFileChooserCallback,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(callback));
-  RunFileChooserInternal(params, std::move(host_callback));
-}
-
-void CefFileDialogManager::RunFileChooserInternal(
-    const CefFileDialogRunner::FileChooserParams& params,
-    CefFileDialogRunner::RunFileChooserCallback callback) {
-  CEF_REQUIRE_UIT();
-
-  if (file_chooser_pending_) {
-    // Dismiss the new dialog immediately.
-    std::move(callback).Run(0, std::vector<base::FilePath>());
+  // Execute the delegate with the most exact version of |params|. If not
+  // handled here there will be another call to the delegate from RunSelectFile.
+  // It might be better to execute the delegate only the single time here, but
+  // we don't currently have sufficient state in RunSelectFile to know that the
+  // delegate has already been executed.
+  callback = MaybeRunDelegate(params, std::move(callback));
+  if (callback.is_null()) {
+    // The delegate kept the callback.
     return;
   }
 
-  file_chooser_pending_ = true;
+  FileChooserParams new_params = params;
 
-  bool handled = false;
+  // Make sure we get native files in CefFileSelectListener.
+  new_params.need_local_path = true;
 
-  if (browser_->client().get()) {
-    CefRefPtr<CefDialogHandler> handler =
-        browser_->client()->GetDialogHandler();
-    if (handler.get()) {
+  // Requirements of FileSelectHelper.
+  if (params.mode != FileChooserParams::Mode::kSave) {
+    new_params.default_file_name = base::FilePath();
+  } else {
+    new_params.default_file_name = new_params.default_file_name.BaseName();
+  }
+
+  // FileSelectHelper is usually only used for renderer-initiated dialogs via
+  // WebContentsDelegate::RunFileChooser. We choose to use it here instead of
+  // calling ui::SelectFileDialog::Create directly because it provides some nice
+  // functionality related to default dialog settings and filter list
+  // generation. We customize the behavior slightly for non-renderer-initiated
+  // dialogs by passing the |run_from_cef=true| flag. FileSelectHelper uses
+  // ui::SelectFileDialog::Create internally and that call will be intercepted
+  // by CefSelectFileDialogFactory, resulting in call to RunSelectFile below.
+  // See related comments on CefSelectFileDialogFactory.
+  FileSelectHelper::RunFileChooser(
+      browser_->GetWebContents()->GetPrimaryMainFrame(),
+      base::MakeRefCounted<CefFileSelectListener>(std::move(callback)),
+      new_params, /*run_from_cef=*/true);
+}
+
+void CefFileDialogManager::RunSelectFile(
+    ui::SelectFileDialog::Listener* listener,
+    std::unique_ptr<ui::SelectFilePolicy> policy,
+    ui::SelectFileDialog::Type type,
+    const std::u16string& title,
+    const base::FilePath& default_path,
+    const ui::SelectFileDialog::FileTypeInfo* file_types,
+    int file_type_index,
+    const base::FilePath::StringType& default_extension,
+    gfx::NativeWindow owning_window,
+    void* params) {
+  CEF_REQUIRE_UIT();
+
+  active_listeners_.insert(listener);
+
+  // This will not be an exact representation of the original params.
+  auto chooser_params =
+      SelectFileToFileChooserParams(type, title, default_path, file_types);
+  auto callback =
+      base::BindOnce(&CefFileDialogManager::SelectFileDoneByDelegateCallback,
+                     weak_ptr_factory_.GetWeakPtr(), base::Unretained(listener),
+                     base::Unretained(params));
+  callback = MaybeRunDelegate(chooser_params, std::move(callback));
+  if (callback.is_null()) {
+    // The delegate kept the callback.
+    return;
+  }
+
+  if (dialog_) {
+    LOG(ERROR) << "Multiple simultaneous dialogs are not supported; "
+                  "canceling the file dialog";
+    std::move(callback).Run({});
+    return;
+  }
+
+#if BUILDFLAG(IS_LINUX)
+  // We can't use GtkUi in combination with multi-threaded-message-loop because
+  // Chromium's GTK implementation doesn't use GDK threads.
+  if (!!CefContext::Get()->settings().multi_threaded_message_loop) {
+    LOG(ERROR) << "Default dialog implementation is not available; "
+                  "canceling the file dialog";
+    std::move(callback).Run({});
+    return;
+  }
+#endif
+
+  // |callback| is no longer used at this point.
+  callback.Reset();
+
+  DCHECK(!dialog_listener_);
+
+  // This object will delete itself.
+  dialog_listener_ = new CefSelectFileDialogListener(
+      listener, params,
+      base::BindOnce(&CefFileDialogManager::SelectFileDoneByListenerCallback,
+                     weak_ptr_factory_.GetWeakPtr(),
+                     /*listener_destroyed=*/false));
+
+  // This call will not be intercepted by CefSelectFileDialogFactory due to the
+  // |run_from_cef=true| flag.
+  // See related comments on CefSelectFileDialogFactory.
+  dialog_ = ui::SelectFileDialog::Create(dialog_listener_, std::move(policy),
+                                         /*run_from_cef=*/true);
+
+  // With windowless rendering use the parent handle specified by the client.
+  if (browser_->IsWindowless()) {
+    DCHECK(!owning_window);
+    dialog_->set_owning_widget(browser_->GetWindowHandle());
+  }
+
+  dialog_->SelectFile(type, title, default_path, file_types, file_type_index,
+                      default_extension, owning_window, params);
+}
+
+void CefFileDialogManager::SelectFileListenerDestroyed(
+    ui::SelectFileDialog::Listener* listener) {
+  CEF_REQUIRE_UIT();
+  DCHECK(listener);
+
+  // This notification will arrive from whomever owns |listener|, so we don't
+  // want to execute any |listener| methods after this point.
+  if (dialog_listener_ && listener == dialog_listener_->listener()) {
+    // Cancel the currently active dialog.
+    SelectFileDoneByListenerCallback(/*listener_destroyed=*/true);
+  } else {
+    // Any future SelectFileDoneByDelegateCallback call for |listener| becomes a
+    // no-op.
+    active_listeners_.erase(listener);
+  }
+}
+
+CefFileDialogManager::RunFileChooserCallback
+CefFileDialogManager::MaybeRunDelegate(
+    const blink::mojom::FileChooserParams& params,
+    RunFileChooserCallback callback) {
+  if (auto client = browser_->client()) {
+    if (auto handler = browser_->client()->GetDialogHandler()) {
       int mode = FILE_DIALOG_OPEN;
       switch (params.mode) {
         case blink::mojom::FileChooserParams::Mode::kOpen:
@@ -266,28 +491,23 @@
           mode = FILE_DIALOG_SAVE;
           break;
         default:
-          NOTREACHED();
+          DCHECK(false);
           break;
       }
 
-      if (params.overwriteprompt)
-        mode |= FILE_DIALOG_OVERWRITEPROMPT_FLAG;
-      if (params.hidereadonly)
-        mode |= FILE_DIALOG_HIDEREADONLY_FLAG;
-
-      std::vector<base::string16>::const_iterator it;
+      std::vector<std::u16string>::const_iterator it;
 
       std::vector<CefString> accept_filters;
       it = params.accept_types.begin();
-      for (; it != params.accept_types.end(); ++it)
+      for (; it != params.accept_types.end(); ++it) {
         accept_filters.push_back(*it);
+      }
 
       CefRefPtr<CefFileDialogCallbackImpl> callbackImpl(
           new CefFileDialogCallbackImpl(std::move(callback)));
-      handled = handler->OnFileDialog(
+      const bool handled = handler->OnFileDialog(
           browser_, static_cast<cef_file_dialog_mode_t>(mode), params.title,
-          params.default_file_name.value(), accept_filters,
-          params.selected_accept_filter, callbackImpl.get());
+          params.default_file_name.value(), accept_filters, callbackImpl.get());
       if (!handled) {
         // May return nullptr if the client has already executed the callback.
         callback = callbackImpl->Disconnect();
@@ -295,82 +515,59 @@
     }
   }
 
-  if (!handled && !callback.is_null()) {
-    if (runner_.get()) {
-      runner_->Run(browser_, params, std::move(callback));
-    } else {
-      LOG(WARNING) << "No file dialog runner available for this platform";
-      std::move(callback).Run(0, std::vector<base::FilePath>());
-    }
+  return callback;
+}
+
+void CefFileDialogManager::SelectFileDoneByDelegateCallback(
+    ui::SelectFileDialog::Listener* listener,
+    void* params,
+    const std::vector<base::FilePath>& paths) {
+  CEF_REQUIRE_UIT();
+
+  // The listener may already be gone. This can occur if the client holds a
+  // RunFileChooserCallback past the call to SelectFileListenerDestroyed().
+  if (active_listeners_.find(listener) == active_listeners_.end()) {
+    return;
   }
-}
 
-void CefFileDialogManager::OnRunFileChooserCallback(
-    CefFileDialogRunner::RunFileChooserCallback callback,
-    int selected_accept_filter,
-    const std::vector<base::FilePath>& file_paths) {
-  CEF_REQUIRE_UIT();
+  active_listeners_.erase(listener);
 
-  Cleanup();
-
-  // Execute the callback asynchronously.
-  CEF_POST_TASK(CEF_UIT, base::BindOnce(std::move(callback),
-                                        selected_accept_filter, file_paths));
-}
-
-void CefFileDialogManager::OnRunFileChooserUploadFolderDelegateCallback(
-    const blink::mojom::FileChooserParams::Mode mode,
-    std::unique_ptr<content::FileSelectListener> listener,
-    int selected_accept_filter,
-    const std::vector<base::FilePath>& file_paths) {
-  CEF_REQUIRE_UIT();
-  DCHECK_EQ(mode, blink::mojom::FileChooserParams::Mode::kUploadFolder);
-
-  if (file_paths.size() == 0) {
-    // Client canceled the file chooser.
-    OnRunFileChooserDelegateCallback(mode, std::move(listener),
-                                     selected_accept_filter, file_paths);
+  if (paths.empty()) {
+    listener->FileSelectionCanceled(params);
+  } else if (paths.size() == 1) {
+    listener->FileSelected(paths[0], /*index=*/0, params);
   } else {
-    lister_.reset(new net::DirectoryLister(
-        file_paths[0], net::DirectoryLister::NO_SORT_RECURSIVE,
-        new UploadFolderHelper(base::BindOnce(
-            &CefFileDialogManager::OnRunFileChooserDelegateCallback,
-            weak_ptr_factory_.GetWeakPtr(), mode, std::move(listener)))));
-    lister_->Start();
+    listener->MultiFilesSelected(paths, params);
   }
+  // |listener| is likely deleted at this point.
 }
 
-void CefFileDialogManager::OnRunFileChooserDelegateCallback(
-    blink::mojom::FileChooserParams::Mode mode,
-    std::unique_ptr<content::FileSelectListener> listener,
-    int selected_accept_filter,
-    const std::vector<base::FilePath>& file_paths) {
+void CefFileDialogManager::SelectFileDoneByListenerCallback(
+    bool listener_destroyed) {
   CEF_REQUIRE_UIT();
 
-  base::FilePath base_dir;
-  std::vector<blink::mojom::FileChooserFileInfoPtr> selected_files;
-
-  if (!file_paths.empty()) {
-    if (mode == blink::mojom::FileChooserParams::Mode::kUploadFolder) {
-      base_dir = file_paths[0].DirName();
-    }
-
-    // Convert FilePath list to SelectedFileInfo list.
-    for (size_t i = 0; i < file_paths.size(); ++i) {
-      auto info = blink::mojom::FileChooserFileInfo::NewNativeFile(
-          blink::mojom::NativeFileInfo::New(file_paths[i], base::string16()));
-      selected_files.push_back(std::move(info));
-    }
+  // Avoid re-entrancy of this method. CefSelectFileDialogListener callbacks to
+  // the delegated listener may result in an immediate call to
+  // SelectFileListenerDestroyed() while |dialog_listener_| is still on the
+  // stack, followed by another execution from
+  // CefSelectFileDialogListener::Destroy(). Similarly, the below call to
+  // Cancel() may trigger another execution from
+  // CefSelectFileDialogListener::Destroy().
+  if (!dialog_listener_) {
+    return;
   }
 
-  listener->FileSelected(std::move(selected_files), base_dir, mode);
+  DCHECK(dialog_);
+  DCHECK(dialog_listener_);
 
-  Cleanup();
-}
+  active_listeners_.erase(dialog_listener_->listener());
 
-void CefFileDialogManager::Cleanup() {
-  if (lister_)
-    lister_.reset();
+  // Clear |dialog_listener_| before calling Cancel() to avoid re-entrancy.
+  auto dialog_listener = dialog_listener_;
+  dialog_listener_ = nullptr;
+  dialog_listener->Cancel(listener_destroyed);
 
-  file_chooser_pending_ = false;
+  // There should be no further listener callbacks after this call.
+  dialog_->ListenerDestroyed();
+  dialog_ = nullptr;
 }
diff --git a/src/libcef/browser/file_dialog_manager.h b/src/libcef/browser/file_dialog_manager.h
index a739c51..dba19fc 100644
--- a/src/libcef/browser/file_dialog_manager.h
+++ b/src/libcef/browser/file_dialog_manager.h
@@ -7,100 +7,93 @@
 #define CEF_LIBCEF_BROWSER_FILE_DIALOG_MANAGER_H_
 #pragma once
 
-#include "include/cef_browser.h"
-#include "libcef/browser/file_dialog_runner.h"
+#include <memory>
+#include <set>
 
-#include "base/compiler_specific.h"
-#include "base/memory/weak_ptr.h"
-#include "content/public/browser/web_contents_observer.h"
+#include "include/cef_browser.h"
+
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
+#include "ui/shell_dialogs/select_file_dialog.h"
 
 namespace content {
 class FileSelectListener;
-class WebContents;
 }  // namespace content
 
-namespace net {
-class DirectoryLister;
-}
-
-class CefBrowserHostImpl;
+class CefBrowserHostBase;
+class CefSelectFileDialogListener;
 
 class CefFileDialogManager {
  public:
-  // |runner| may be NULL if the platform doesn't implement dialogs.
-  CefFileDialogManager(CefBrowserHostImpl* browser,
-                       std::unique_ptr<CefFileDialogRunner> runner);
+  explicit CefFileDialogManager(CefBrowserHostBase* browser);
+
+  CefFileDialogManager(const CefFileDialogManager&) = delete;
+  CefFileDialogManager& operator=(const CefFileDialogManager&) = delete;
+
   ~CefFileDialogManager();
 
   // Delete the runner to free any platform constructs.
   void Destroy();
 
-  // Called from CefBrowserHostImpl::RunFileChooser.
-  // See CefBrowserHost::RunFileDialog documentation.
+  // Run a file dialog with the specified parameters. See
+  // CefBrowserHost::RunFileDialog for usage documentation. This method should
+  // be called via CefBrowserHostBase::RunFileDialog.
   void RunFileDialog(cef_file_dialog_mode_t mode,
                      const CefString& title,
                      const CefString& default_file_path,
                      const std::vector<CefString>& accept_filters,
-                     int selected_accept_filter,
                      CefRefPtr<CefRunFileDialogCallback> callback);
 
-  // Called from CefBrowserHostImpl::RunFileChooser.
-  // See WebContentsDelegate::RunFileChooser documentation.
-  void RunFileChooser(std::unique_ptr<content::FileSelectListener> listener,
-                      const blink::mojom::FileChooserParams& params);
+  // The argument vector will be empty if the dialog was canceled.
+  using RunFileChooserCallback =
+      base::OnceCallback<void(const std::vector<base::FilePath>&)>;
 
-  // Run the file chooser dialog specified by |params|. Only a single dialog may
-  // be pending at any given time. |callback| will be executed asynchronously
-  // after the dialog is dismissed or if another dialog is already pending.
-  void RunFileChooser(const CefFileDialogRunner::FileChooserParams& params,
-                      CefFileDialogRunner::RunFileChooserCallback callback);
+  // Run the file dialog specified by |params|. |callback| will be executed
+  // synchronously or asynchronously after the dialog is dismissed. This method
+  // should be called via CefBrowserHostBase::RunFileChooser.
+  void RunFileChooser(const blink::mojom::FileChooserParams& params,
+                      RunFileChooserCallback callback);
+
+  // Run a ui::SelectFileDialog with the specified parameters. See
+  // ui::SelectFileDialog for usage documentation. This method should be called
+  // via CefBrowserHostBase::RunSelectFile. It will be called for all file
+  // dialogs after interception via CefSelectFileDialog::SelectFileImpl.
+  void RunSelectFile(ui::SelectFileDialog::Listener* listener,
+                     std::unique_ptr<ui::SelectFilePolicy> policy,
+                     ui::SelectFileDialog::Type type,
+                     const std::u16string& title,
+                     const base::FilePath& default_path,
+                     const ui::SelectFileDialog::FileTypeInfo* file_types,
+                     int file_type_index,
+                     const base::FilePath::StringType& default_extension,
+                     gfx::NativeWindow owning_window,
+                     void* params);
+
+  // Must be called when the |listener| passed to RunSelectFile is destroyed.
+  void SelectFileListenerDestroyed(ui::SelectFileDialog::Listener* listener);
 
  private:
-  void RunFileChooserInternal(
-      const CefFileDialogRunner::FileChooserParams& params,
-      CefFileDialogRunner::RunFileChooserCallback callback);
+  [[nodiscard]] RunFileChooserCallback MaybeRunDelegate(
+      const blink::mojom::FileChooserParams& params,
+      RunFileChooserCallback callback);
 
-  // Used with the RunFileChooser variant where the caller specifies a callback
-  // (no associated RenderFrameHost).
-  void OnRunFileChooserCallback(
-      CefFileDialogRunner::RunFileChooserCallback callback,
-      int selected_accept_filter,
-      const std::vector<base::FilePath>& file_paths);
+  void SelectFileDoneByDelegateCallback(
+      ui::SelectFileDialog::Listener* listener,
+      void* params,
+      const std::vector<base::FilePath>& paths);
+  void SelectFileDoneByListenerCallback(bool listener_destroyed);
 
-  // Used with WebContentsDelegate::RunFileChooser when mode is
-  // blink::mojom::FileChooserParams::Mode::kUploadFolder.
-  void OnRunFileChooserUploadFolderDelegateCallback(
-      const blink::mojom::FileChooserParams::Mode mode,
-      std::unique_ptr<content::FileSelectListener> listener,
-      int selected_accept_filter,
-      const std::vector<base::FilePath>& file_paths);
+  // CefBrowserHostBase pointer is guaranteed to outlive this object.
+  CefBrowserHostBase* const browser_;
 
-  // Used with WebContentsDelegate::RunFileChooser to notify the
-  // RenderFrameHost.
-  void OnRunFileChooserDelegateCallback(
-      blink::mojom::FileChooserParams::Mode mode,
-      std::unique_ptr<content::FileSelectListener> listener,
-      int selected_accept_filter,
-      const std::vector<base::FilePath>& file_paths);
+  // Used when running a platform dialog via RunSelectFile.
+  scoped_refptr<ui::SelectFileDialog> dialog_;
+  CefSelectFileDialogListener* dialog_listener_ = nullptr;
 
-  // Clean up state associated with the last run.
-  void Cleanup();
+  // List of all currently active listeners.
+  std::set<ui::SelectFileDialog::Listener*> active_listeners_;
 
-  // CefBrowserHostImpl pointer is guaranteed to outlive this object.
-  CefBrowserHostImpl* browser_;
-
-  std::unique_ptr<CefFileDialogRunner> runner_;
-
-  // True if a file chooser is currently pending.
-  bool file_chooser_pending_;
-
-  // Used for asynchronously listing directory contents.
-  std::unique_ptr<net::DirectoryLister> lister_;
-
-  // Must be the last member.
-  base::WeakPtrFactory<CefFileDialogManager> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefFileDialogManager);
+  base::WeakPtrFactory<CefFileDialogManager> weak_ptr_factory_{this};
 };
 
 #endif  // CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_MANAGER_H_
diff --git a/src/libcef/browser/file_dialog_runner.cc b/src/libcef/browser/file_dialog_runner.cc
new file mode 100644
index 0000000..291cb56
--- /dev/null
+++ b/src/libcef/browser/file_dialog_runner.cc
@@ -0,0 +1,154 @@
+// Copyright (c) 2022 The Chromium Embedded Framework Authors.
+// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/browser/file_dialog_runner.h"
+
+#include "libcef/browser/browser_host_base.h"
+#include "libcef/browser/extensions/browser_extensions_util.h"
+
+#include "chrome/browser/file_select_helper.h"
+#include "chrome/browser/ui/chrome_select_file_policy.h"
+#include "ui/shell_dialogs/select_file_dialog_factory.h"
+#include "ui/shell_dialogs/select_file_policy.h"
+
+using blink::mojom::FileChooserParams;
+
+namespace {
+
+// Creation of a file dialog can be triggered via various code paths, but they
+// all eventually result in a call to ui::SelectFileDialog::Create. We intercept
+// that call with CefSelectFileDialogFactory and redirect it to
+// CefFileDialogManager::RunSelectFile. After triggering the CefDialogHandler
+// callbacks that method calls ui::SelectFileDialog::Create again with
+// |run_from_cef=false| to trigger creation of the default platform dialog.
+class CefSelectFileDialogFactory final : public ui::SelectFileDialogFactory {
+ public:
+  CefSelectFileDialogFactory() = default;
+
+  CefSelectFileDialogFactory(const CefSelectFileDialogFactory&) = delete;
+  CefSelectFileDialogFactory& operator=(const CefSelectFileDialogFactory&) =
+      delete;
+
+  ui::SelectFileDialog* Create(
+      ui::SelectFileDialog::Listener* listener,
+      std::unique_ptr<ui::SelectFilePolicy> policy) override;
+
+  bool IsCefFactory() const override { return true; }
+};
+
+// Delegates the running of the dialog to CefFileDialogManager.
+class CefSelectFileDialog final : public ui::SelectFileDialog {
+ public:
+  CefSelectFileDialog(ui::SelectFileDialog::Listener* listener,
+                      std::unique_ptr<ui::SelectFilePolicy> policy)
+      : ui::SelectFileDialog(listener, std::move(policy)) {
+    DCHECK(listener_);
+  }
+
+  CefSelectFileDialog(const CefSelectFileDialog&) = delete;
+  CefSelectFileDialog& operator=(const CefSelectFileDialog&) = delete;
+
+  void SelectFileImpl(Type type,
+                      const std::u16string& title,
+                      const base::FilePath& default_path,
+                      const FileTypeInfo* file_types,
+                      int file_type_index,
+                      const base::FilePath::StringType& default_extension,
+                      gfx::NativeWindow owning_window,
+                      void* params,
+                      const GURL* caller) override {
+    // Try to determine the associated browser (with decreasing levels of
+    // confidence).
+    // 1. Browser associated with the SelectFilePolicy. This is the most
+    // reliable mechanism if specified at the SelectFileDialog::Create call
+    // site.
+    if (select_file_policy_) {
+      auto chrome_policy =
+          static_cast<ChromeSelectFilePolicy*>(select_file_policy_.get());
+      auto web_contents = chrome_policy->source_contents();
+      if (web_contents) {
+        browser_ = extensions::GetOwnerBrowserForHost(
+            web_contents->GetRenderViewHost(), nullptr);
+      }
+      if (!browser_) {
+        LOG(WARNING) << "No browser associated with SelectFilePolicy";
+      }
+    }
+
+    // 2. Browser associated with the top-level native window (owning_window).
+    // This should be reliable with windowed browsers. However, |owning_window|
+    // will always be nullptr with windowless browsers.
+    if (!browser_ && owning_window) {
+      browser_ =
+          CefBrowserHostBase::GetBrowserForTopLevelNativeWindow(owning_window);
+      if (!browser_) {
+        LOG(WARNING) << "No browser associated with top-level native window";
+      }
+    }
+
+    // 3. Browser most likely to be focused. This may be somewhat iffy with
+    // windowless browsers as there is no guarantee that the client has only
+    // one browser focused at a time.
+    if (!browser_) {
+      browser_ = CefBrowserHostBase::GetLikelyFocusedBrowser();
+      if (!browser_) {
+        LOG(WARNING) << "No likely focused browser";
+      }
+    }
+
+    if (!browser_) {
+      LOG(ERROR)
+          << "Failed to identify associated browser; canceling the file dialog";
+      listener_->FileSelectionCanceled(params);
+      return;
+    }
+
+    owning_window_ = owning_window;
+    has_multiple_file_choices_ =
+        file_types ? file_types->extensions.size() > 1 : true;
+
+    browser_->RunSelectFile(listener_, std::move(select_file_policy_), type,
+                            title, default_path, file_types, file_type_index,
+                            default_extension, owning_window, params);
+  }
+
+  bool IsRunning(gfx::NativeWindow owning_window) const override {
+    return owning_window == owning_window_;
+  }
+
+  void ListenerDestroyed() override {
+    if (browser_) {
+      browser_->SelectFileListenerDestroyed(listener_);
+    }
+    listener_ = nullptr;
+  }
+
+  bool HasMultipleFileTypeChoicesImpl() override {
+    return has_multiple_file_choices_;
+  }
+
+ private:
+  gfx::NativeWindow owning_window_ = nullptr;
+  bool has_multiple_file_choices_ = false;
+
+  CefRefPtr<CefBrowserHostBase> browser_;
+};
+
+ui::SelectFileDialog* CefSelectFileDialogFactory::Create(
+    ui::SelectFileDialog::Listener* listener,
+    std::unique_ptr<ui::SelectFilePolicy> policy) {
+  return new CefSelectFileDialog(listener, std::move(policy));
+}
+
+}  // namespace
+
+namespace file_dialog_runner {
+
+void RegisterFactory() {
+  ui::SelectFileDialog::SetFactory(
+      std::make_unique<CefSelectFileDialogFactory>());
+}
+
+}  // namespace file_dialog_runner
diff --git a/src/libcef/browser/file_dialog_runner.h b/src/libcef/browser/file_dialog_runner.h
index 1ad1143..679a2c6 100644
--- a/src/libcef/browser/file_dialog_runner.h
+++ b/src/libcef/browser/file_dialog_runner.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Embedded Framework Authors.
+// Copyright (c) 2022 The Chromium Embedded Framework Authors.
 // Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
@@ -7,46 +7,11 @@
 #define CEF_LIBCEF_BROWSER_FILE_DIALOG_RUNNER_H_
 #pragma once
 
-#include <vector>
+namespace file_dialog_runner {
 
-#include "base/callback.h"
-#include "base/files/file_path.h"
-#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
+// One-time registration on startup.
+void RegisterFactory();
 
-class CefBrowserHostImpl;
-
-class CefFileDialogRunner {
- public:
-  // Extend blink::mojom::FileChooserParams with some options unique to CEF.
-  struct FileChooserParams : public blink::mojom::FileChooserParams {
-    // 0-based index of the selected value in |accept_types|.
-    int selected_accept_filter = 0;
-
-    // True if the Save dialog should prompt before overwriting files.
-    bool overwriteprompt = true;
-
-    // True if read-only files should be hidden.
-    bool hidereadonly = true;
-  };
-
-  // The argument vector will be empty if the dialog was canceled.
-  typedef base::OnceCallback<void(int, const std::vector<base::FilePath>&)>
-      RunFileChooserCallback;
-
-  // Display the file chooser dialog. Execute |callback| on completion.
-  virtual void Run(CefBrowserHostImpl* browser,
-                   const FileChooserParams& params,
-                   RunFileChooserCallback callback) = 0;
-
- protected:
-  // Allow deletion via scoped_ptr only.
-  friend std::default_delete<CefFileDialogRunner>;
-
-  CefFileDialogRunner() {}
-  virtual ~CefFileDialogRunner() {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefFileDialogRunner);
-};
+}  // namespace file_dialog_runner
 
 #endif  // CEF_LIBCEF_BROWSER_FILE_DIALOG_RUNNER_H_
diff --git a/src/libcef/browser/frame_host_impl.cc b/src/libcef/browser/frame_host_impl.cc
index 7b2f605..bb9767f 100644
--- a/src/libcef/browser/frame_host_impl.cc
+++ b/src/libcef/browser/frame_host_impl.cc
@@ -8,60 +8,76 @@
 #include "include/cef_stream.h"
 #include "include/cef_v8.h"
 #include "include/test/cef_test_helpers.h"
-#include "libcef/browser/browser_host_impl.h"
-#include "libcef/browser/navigate_params.h"
+#include "libcef/browser/browser_host_base.h"
 #include "libcef/browser/net_service/browser_urlrequest_impl.h"
-#include "libcef/common/cef_messages.h"
 #include "libcef/common/frame_util.h"
+#include "libcef/common/net/url_util.h"
 #include "libcef/common/process_message_impl.h"
+#include "libcef/common/process_message_smr_impl.h"
 #include "libcef/common/request_impl.h"
+#include "libcef/common/string_util.h"
 #include "libcef/common/task_runner_impl.h"
 
-#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/renderer_host/frame_tree_node.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
 
 namespace {
 
-// Implementation of CommandResponseHandler for calling a CefStringVisitor.
-class StringVisitHandler : public CefResponseManager::Handler {
- public:
-  explicit StringVisitHandler(CefRefPtr<CefStringVisitor> visitor)
-      : visitor_(visitor) {}
-  void OnResponse(const Cef_Response_Params& params) override {
-    visitor_->Visit(params.response);
+void StringVisitCallback(CefRefPtr<CefStringVisitor> visitor,
+                         base::ReadOnlySharedMemoryRegion response) {
+  string_util::ExecuteWithScopedCefString(
+      std::move(response),
+      base::BindOnce([](CefRefPtr<CefStringVisitor> visitor,
+                        const CefString& str) { visitor->Visit(str); },
+                     visitor));
+}
+
+void ViewTextCallback(CefRefPtr<CefFrameHostImpl> frame,
+                      base::ReadOnlySharedMemoryRegion response) {
+  if (auto browser = frame->GetBrowser()) {
+    string_util::ExecuteWithScopedCefString(
+        std::move(response),
+        base::BindOnce(
+            [](CefRefPtr<CefBrowser> browser, const CefString& str) {
+              static_cast<CefBrowserHostBase*>(browser.get())->ViewText(str);
+            },
+            browser));
   }
+}
 
- private:
-  CefRefPtr<CefStringVisitor> visitor_;
+using CefFrameHostImplCommand = void (CefFrameHostImpl::*)();
+using WebContentsCommand = void (content::WebContents::*)();
 
-  IMPLEMENT_REFCOUNTING(StringVisitHandler);
-};
-
-// Implementation of CommandResponseHandler for calling ViewText().
-class ViewTextHandler : public CefResponseManager::Handler {
- public:
-  explicit ViewTextHandler(CefRefPtr<CefFrameHostImpl> frame) : frame_(frame) {}
-  void OnResponse(const Cef_Response_Params& params) override {
-    CefRefPtr<CefBrowser> browser = frame_->GetBrowser();
-    if (browser.get()) {
-      static_cast<CefBrowserHostImpl*>(browser.get())
-          ->ViewText(params.response);
+void ExecWebContentsCommand(CefFrameHostImpl* fh,
+                            CefFrameHostImplCommand fh_func,
+                            WebContentsCommand wc_func,
+                            const std::string& command) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(fh_func, fh));
+    return;
+  }
+  auto rfh = fh->GetRenderFrameHost();
+  if (rfh) {
+    auto web_contents = content::WebContents::FromRenderFrameHost(rfh);
+    if (web_contents) {
+      std::invoke(wc_func, web_contents);
+      return;
     }
   }
+  fh->SendCommand(command);
+}
 
- private:
-  CefRefPtr<CefFrameHostImpl> frame_;
-
-  IMPLEMENT_REFCOUNTING(ViewTextHandler);
-};
+#define EXEC_WEBCONTENTS_COMMAND(name)                  \
+  ExecWebContentsCommand(this, &CefFrameHostImpl::name, \
+                         &content::WebContents::name, #name);
 
 }  // namespace
 
 CefFrameHostImpl::CefFrameHostImpl(scoped_refptr<CefBrowserInfo> browser_info,
-                                   bool is_main_frame,
                                    int64_t parent_frame_id)
-    : is_main_frame_(is_main_frame),
+    : is_main_frame_(false),
       frame_id_(kInvalidFrameId),
       browser_info_(browser_info),
       is_focused_(is_main_frame_),  // The main frame always starts focused.
@@ -79,88 +95,77 @@
 CefFrameHostImpl::CefFrameHostImpl(scoped_refptr<CefBrowserInfo> browser_info,
                                    content::RenderFrameHost* render_frame_host)
     : is_main_frame_(render_frame_host->GetParent() == nullptr),
-      frame_id_(MakeFrameId(render_frame_host)),
+      frame_id_(frame_util::MakeFrameId(render_frame_host->GetGlobalId())),
       browser_info_(browser_info),
       is_focused_(is_main_frame_),  // The main frame always starts focused.
       url_(render_frame_host->GetLastCommittedURL().spec()),
       name_(render_frame_host->GetFrameName()),
-      parent_frame_id_(is_main_frame_
-                           ? kInvalidFrameId
-                           : MakeFrameId(render_frame_host->GetParent())),
-      render_frame_host_(render_frame_host),
-      response_manager_(new CefResponseManager) {
+      parent_frame_id_(
+          is_main_frame_ ? kInvalidFrameId
+                         : frame_util::MakeFrameId(
+                               render_frame_host->GetParent()->GetGlobalId())),
+      render_frame_host_(render_frame_host) {
   DCHECK(browser_info_);
 }
 
-CefFrameHostImpl::~CefFrameHostImpl() {}
-
-void CefFrameHostImpl::SetRenderFrameHost(content::RenderFrameHost* host) {
-  CEF_REQUIRE_UIT();
-
-  base::AutoLock lock_scope(state_lock_);
-
-  // We should not be detached.
-  CHECK(browser_info_);
-  // We should be the main frame.
-  CHECK(is_main_frame_);
-
-  render_frame_host_ = host;
-  frame_id_ = MakeFrameId(host);
-  url_ = host->GetLastCommittedURL().spec();
-  name_ = host->GetFrameName();
-
-  // Cancel any existing messages.
-  response_manager_.reset(new CefResponseManager);
+CefFrameHostImpl::~CefFrameHostImpl() {
+  // Should have been Detached if not temporary.
+  DCHECK(is_temporary() || !browser_info_);
+  DCHECK(!render_frame_host_);
 }
 
 bool CefFrameHostImpl::IsValid() {
-  return !!GetBrowserHostImpl();
+  return !!GetBrowserHostBase();
 }
 
 void CefFrameHostImpl::Undo() {
-  SendCommand("Undo", nullptr);
+  EXEC_WEBCONTENTS_COMMAND(Undo);
 }
 
 void CefFrameHostImpl::Redo() {
-  SendCommand("Redo", nullptr);
+  EXEC_WEBCONTENTS_COMMAND(Redo);
 }
 
 void CefFrameHostImpl::Cut() {
-  SendCommand("Cut", nullptr);
+  EXEC_WEBCONTENTS_COMMAND(Cut);
 }
 
 void CefFrameHostImpl::Copy() {
-  SendCommand("Copy", nullptr);
+  EXEC_WEBCONTENTS_COMMAND(Copy);
 }
 
 void CefFrameHostImpl::Paste() {
-  SendCommand("Paste", nullptr);
+  EXEC_WEBCONTENTS_COMMAND(Paste);
 }
 
 void CefFrameHostImpl::Delete() {
-  SendCommand("Delete", nullptr);
+  EXEC_WEBCONTENTS_COMMAND(Delete);
 }
 
 void CefFrameHostImpl::SelectAll() {
-  SendCommand("SelectAll", nullptr);
+  EXEC_WEBCONTENTS_COMMAND(SelectAll);
 }
 
 void CefFrameHostImpl::ViewSource() {
-  SendCommand("GetSource", new ViewTextHandler(this));
+  SendCommandWithResponse(
+      "GetSource",
+      base::BindOnce(&ViewTextCallback, CefRefPtr<CefFrameHostImpl>(this)));
 }
 
 void CefFrameHostImpl::GetSource(CefRefPtr<CefStringVisitor> visitor) {
-  SendCommand("GetSource", new StringVisitHandler(visitor));
+  SendCommandWithResponse("GetSource",
+                          base::BindOnce(&StringVisitCallback, visitor));
 }
 
 void CefFrameHostImpl::GetText(CefRefPtr<CefStringVisitor> visitor) {
-  SendCommand("GetText", new StringVisitHandler(visitor));
+  SendCommandWithResponse("GetText",
+                          base::BindOnce(&StringVisitCallback, visitor));
 }
 
 void CefFrameHostImpl::LoadRequest(CefRefPtr<CefRequest> request) {
-  CefNavigateParams params(GURL(), kPageTransitionExplicit);
+  auto params = cef::mojom::RequestParams::New();
   static_cast<CefRequestImpl*>(request.get())->Get(params);
-  Navigate(params);
+  LoadRequest(std::move(params));
 }
 
 void CefFrameHostImpl::LoadURL(const CefString& url) {
@@ -188,24 +193,26 @@
   return name_;
 }
 
-int64 CefFrameHostImpl::GetIdentifier() {
+int64_t CefFrameHostImpl::GetIdentifier() {
   base::AutoLock lock_scope(state_lock_);
   return frame_id_;
 }
 
 CefRefPtr<CefFrame> CefFrameHostImpl::GetParent() {
-  int64 parent_frame_id;
+  int64_t parent_frame_id;
 
   {
     base::AutoLock lock_scope(state_lock_);
-    if (is_main_frame_ || parent_frame_id_ == kInvalidFrameId)
+    if (is_main_frame_ || parent_frame_id_ == kInvalidFrameId) {
       return nullptr;
+    }
     parent_frame_id = parent_frame_id_;
   }
 
-  auto browser = GetBrowserHostImpl();
-  if (browser)
+  auto browser = GetBrowserHostBase();
+  if (browser) {
     return browser->GetFrame(parent_frame_id);
+  }
 
   return nullptr;
 }
@@ -216,39 +223,42 @@
 }
 
 CefRefPtr<CefBrowser> CefFrameHostImpl::GetBrowser() {
-  return GetBrowserHostImpl().get();
+  return GetBrowserHostBase().get();
 }
 
 CefRefPtr<CefV8Context> CefFrameHostImpl::GetV8Context() {
-  NOTREACHED() << "GetV8Context cannot be called from the browser process";
+  DCHECK(false) << "GetV8Context cannot be called from the browser process";
   return nullptr;
 }
 
 void CefFrameHostImpl::VisitDOM(CefRefPtr<CefDOMVisitor> visitor) {
-  NOTREACHED() << "VisitDOM cannot be called from the browser process";
+  DCHECK(false) << "VisitDOM cannot be called from the browser process";
 }
 
 CefRefPtr<CefURLRequest> CefFrameHostImpl::CreateURLRequest(
     CefRefPtr<CefRequest> request,
     CefRefPtr<CefURLRequestClient> client) {
-  if (!request || !client)
-    return nullptr;
-
-  if (!CefTaskRunnerImpl::GetCurrentTaskRunner()) {
-    NOTREACHED() << "called on invalid thread";
+  if (!request || !client) {
     return nullptr;
   }
 
-  auto browser = GetBrowserHostImpl();
-  if (!browser)
+  if (!CefTaskRunnerImpl::GetCurrentTaskRunner()) {
+    DCHECK(false) << "called on invalid thread";
     return nullptr;
+  }
+
+  auto browser = GetBrowserHostBase();
+  if (!browser) {
+    return nullptr;
+  }
 
   auto request_context = browser->request_context();
 
   CefRefPtr<CefBrowserURLRequest> impl =
       new CefBrowserURLRequest(this, request, client, request_context);
-  if (impl->Start())
+  if (impl->Start()) {
     return impl.get();
+  }
   return nullptr;
 }
 
@@ -256,21 +266,35 @@
     CefProcessId target_process,
     CefRefPtr<CefProcessMessage> message) {
   DCHECK_EQ(PID_RENDERER, target_process);
-  DCHECK(message.get());
-
-  Cef_Request_Params params;
-  CefProcessMessageImpl* impl =
-      static_cast<CefProcessMessageImpl*>(message.get());
-  if (!impl->CopyTo(params))
+  DCHECK(message && message->IsValid());
+  if (!message || !message->IsValid()) {
     return;
+  }
 
-  DCHECK(!params.name.empty());
-
-  params.user_initiated = true;
-  params.request_id = -1;
-  params.expect_response = false;
-
-  Send(new CefMsg_Request(MSG_ROUTING_NONE, params));
+  if (message->GetArgumentList() != nullptr) {
+    // Invalidate the message object immediately by taking the argument list.
+    auto argument_list =
+        static_cast<CefProcessMessageImpl*>(message.get())->TakeArgumentList();
+    SendToRenderFrame(
+        __FUNCTION__,
+        base::BindOnce(
+            [](const CefString& name, base::Value::List argument_list,
+               const RenderFrameType& render_frame) {
+              render_frame->SendMessage(name, std::move(argument_list));
+            },
+            message->GetName(), std::move(argument_list)));
+  } else {
+    auto region =
+        static_cast<CefProcessMessageSMRImpl*>(message.get())->TakeRegion();
+    SendToRenderFrame(
+        __FUNCTION__,
+        base::BindOnce(
+            [](const CefString& name, base::WritableSharedMemoryRegion region,
+               const RenderFrameType& render_frame) {
+              render_frame->SendSharedMemoryRegion(name, std::move(region));
+            },
+            message->GetName(), std::move(region)));
+  }
 }
 
 void CefFrameHostImpl::SetFocused(bool focused) {
@@ -282,8 +306,9 @@
   CEF_REQUIRE_UIT();
 
   base::AutoLock lock_scope(state_lock_);
-  if (!render_frame_host_)
+  if (!render_frame_host_) {
     return;
+  }
   url_ = render_frame_host_->GetLastCommittedURL().spec();
 
   // Use the assigned name if it is non-empty. This represents the name property
@@ -298,34 +323,36 @@
     }
   }
 
-  if (!is_main_frame_)
-    parent_frame_id_ = MakeFrameId(render_frame_host_->GetParent());
+  if (!is_main_frame_) {
+    parent_frame_id_ =
+        frame_util::MakeFrameId(render_frame_host_->GetParent()->GetGlobalId());
+  }
 }
 
-void CefFrameHostImpl::Navigate(const CefNavigateParams& params) {
-  CefMsg_LoadRequest_Params request;
-  request.url = params.url;
-  if (!request.url.is_valid()) {
-    LOG(ERROR) << "Invalid URL passed to CefFrameHostImpl::Navigate: "
-               << params.url;
+void CefFrameHostImpl::NotifyMoveOrResizeStarted() {
+  SendToRenderFrame(__FUNCTION__,
+                    base::BindOnce([](const RenderFrameType& render_frame) {
+                      render_frame->MoveOrResizeStarted();
+                    }));
+}
+
+void CefFrameHostImpl::LoadRequest(cef::mojom::RequestParamsPtr params) {
+  if (!url_util::FixupGURL(params->url)) {
     return;
   }
 
-  request.method = params.method;
-  request.referrer = params.referrer.url;
-  request.referrer_policy =
-      CefRequestImpl::BlinkReferrerPolicyToNetReferrerPolicy(
-          params.referrer.policy);
-  request.site_for_cookies = params.site_for_cookies;
-  request.headers = params.headers;
-  request.load_flags = params.load_flags;
-  request.upload_data = params.upload_data;
+  SendToRenderFrame(__FUNCTION__,
+                    base::BindOnce(
+                        [](cef::mojom::RequestParamsPtr params,
+                           const RenderFrameType& render_frame) {
+                          render_frame->LoadRequest(std::move(params));
+                        },
+                        std::move(params)));
 
-  Send(new CefMsg_LoadRequest(MSG_ROUTING_NONE, request));
-
-  auto browser = GetBrowserHostImpl();
-  if (browser)
+  auto browser = GetBrowserHostBase();
+  if (browser) {
     browser->OnSetFocus(FOCUS_SOURCE_NAVIGATION);
+  }
 }
 
 void CefFrameHostImpl::LoadURLWithExtras(const std::string& url,
@@ -334,116 +361,68 @@
                                          const std::string& extra_headers) {
   // Only known frame ids or kMainFrameId are supported.
   const auto frame_id = GetFrameId();
-  if (frame_id < CefFrameHostImpl::kMainFrameId)
+  if (frame_id < CefFrameHostImpl::kMainFrameId) {
     return;
+  }
+
+  // Any necessary fixup will occur in LoadRequest.
+  GURL gurl = url_util::MakeGURL(url, /*fixup=*/false);
 
   if (frame_id == CefFrameHostImpl::kMainFrameId) {
     // Load via the browser using NavigationController.
-    auto browser = GetBrowserHostImpl();
+    auto browser = GetBrowserHostBase();
     if (browser) {
-      browser->LoadMainFrameURL(url, referrer, transition, extra_headers);
+      content::OpenURLParams params(
+          gurl, referrer, WindowOpenDisposition::CURRENT_TAB, transition,
+          /*is_renderer_initiated=*/false);
+      params.extra_headers = extra_headers;
+
+      browser->LoadMainFrameURL(params);
     }
   } else {
-    CefNavigateParams params(GURL(url), transition);
-    params.referrer = referrer;
-    params.headers = extra_headers;
-    Navigate(params);
+    auto params = cef::mojom::RequestParams::New();
+    params->url = gurl;
+    params->referrer =
+        blink::mojom::Referrer::New(referrer.url, referrer.policy);
+    params->headers = extra_headers;
+    LoadRequest(std::move(params));
   }
 }
 
-void CefFrameHostImpl::SendCommand(
-    const std::string& command,
-    CefRefPtr<CefResponseManager::Handler> responseHandler) {
+void CefFrameHostImpl::SendCommand(const std::string& command) {
   DCHECK(!command.empty());
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefFrameHostImpl::SendCommand, this,
-                                          command, responseHandler));
-    return;
-  }
-
-  // Only known frame ids or kMainFrameId are supported.
-  const auto frame_id = GetFrameId();
-  if (frame_id < CefFrameHostImpl::kMainFrameId)
-    return;
-
-  if (!render_frame_host_ || !response_manager_) {
-    // detached frame has no response_manager_
-    return;
-  }
-
-  TRACE_EVENT2("cef", "CefFrameHostImpl::SendCommand", "frame_id", frame_id,
-               "needsResponse", responseHandler.get() ? 1 : 0);
-  Cef_Request_Params params;
-  params.name = "execute-command";
-  params.user_initiated = false;
-
-  if (responseHandler.get()) {
-    params.request_id = response_manager_->RegisterHandler(responseHandler);
-    params.expect_response = true;
-  } else {
-    params.request_id = -1;
-    params.expect_response = false;
-  }
-
-  params.arguments.AppendString(command);
-
-  Send(new CefMsg_Request(MSG_ROUTING_NONE, params));
+  SendToRenderFrame(__FUNCTION__, base::BindOnce(
+                                      [](const std::string& command,
+                                         const RenderFrameType& render_frame) {
+                                        render_frame->SendCommand(command);
+                                      },
+                                      command));
 }
 
-void CefFrameHostImpl::SendCode(
-    bool is_javascript,
-    const std::string& code,
-    const std::string& script_url,
-    int script_start_line,
-    CefRefPtr<CefResponseManager::Handler> responseHandler) {
-  DCHECK(!code.empty());
-  DCHECK_GE(script_start_line, 0);
-
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefFrameHostImpl::SendCode, this,
-                                          is_javascript, code, script_url,
-                                          script_start_line, responseHandler));
-    return;
-  }
-
-  // Only known frame ids or kMainFrameId are supported.
-  auto frame_id = GetFrameId();
-  if (frame_id < CefFrameHostImpl::kMainFrameId)
-    return;
-
-  if (!render_frame_host_ || !response_manager_) {
-    // detached frame has no response_manager_
-    return;
-  }
-
-  TRACE_EVENT2("cef", "CefFrameHostImpl::SendCommand", "frame_id", frame_id,
-               "needsResponse", responseHandler.get() ? 1 : 0);
-  Cef_Request_Params params;
-  params.name = "execute-code";
-  params.user_initiated = false;
-
-  if (responseHandler.get()) {
-    params.request_id = response_manager_->RegisterHandler(responseHandler);
-    params.expect_response = true;
-  } else {
-    params.request_id = -1;
-    params.expect_response = false;
-  }
-
-  params.arguments.AppendBoolean(is_javascript);
-  params.arguments.AppendString(code);
-  params.arguments.AppendString(script_url);
-  params.arguments.AppendInteger(script_start_line);
-
-  Send(new CefMsg_Request(MSG_ROUTING_NONE, params));
+void CefFrameHostImpl::SendCommandWithResponse(
+    const std::string& command,
+    cef::mojom::RenderFrame::SendCommandWithResponseCallback
+        response_callback) {
+  DCHECK(!command.empty());
+  SendToRenderFrame(
+      __FUNCTION__,
+      base::BindOnce(
+          [](const std::string& command,
+             cef::mojom::RenderFrame::SendCommandWithResponseCallback
+                 response_callback,
+             const RenderFrameType& render_frame) {
+            render_frame->SendCommandWithResponse(command,
+                                                  std::move(response_callback));
+          },
+          command, std::move(response_callback)));
 }
 
-void CefFrameHostImpl::SendJavaScript(const std::string& jsCode,
+void CefFrameHostImpl::SendJavaScript(const std::u16string& jsCode,
                                       const std::string& scriptUrl,
                                       int startLine) {
-  if (jsCode.empty())
+  if (jsCode.empty()) {
     return;
+  }
   if (startLine <= 0) {
     // A value of 0 is v8::Message::kNoLineNumberInfo in V8. There is code in
     // V8 that will assert on that value (e.g. V8StackTraceImpl::Frame::Frame
@@ -451,13 +430,21 @@
     startLine = 1;
   }
 
-  SendCode(true, jsCode, scriptUrl, startLine, nullptr);
+  SendToRenderFrame(
+      __FUNCTION__,
+      base::BindOnce(
+          [](const std::u16string& jsCode, const std::string& scriptUrl,
+             int startLine, const RenderFrameType& render_frame) {
+            render_frame->SendJavaScript(jsCode, scriptUrl, startLine);
+          },
+          jsCode, scriptUrl, startLine));
 }
 
 void CefFrameHostImpl::MaybeSendDidStopLoading() {
   auto rfh = GetRenderFrameHost();
-  if (!rfh)
+  if (!rfh) {
     return;
+  }
 
   // We only want to notify for the highest-level LocalFrame in this frame's
   // renderer process subtree. If this frame has a parent in the same process
@@ -467,22 +454,10 @@
     return;
   }
 
-  Send(new CefMsg_DidStopLoading(MSG_ROUTING_NONE));
-}
-
-bool CefFrameHostImpl::OnMessageReceived(const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(CefFrameHostImpl, message)
-    IPC_MESSAGE_HANDLER(CefHostMsg_FrameAttached, OnAttached)
-    IPC_MESSAGE_HANDLER(CefHostMsg_DidFinishLoad, OnDidFinishLoad)
-    IPC_MESSAGE_HANDLER(CefHostMsg_UpdateDraggableRegions,
-                        OnUpdateDraggableRegions)
-    IPC_MESSAGE_HANDLER(CefHostMsg_Request, OnRequest)
-    IPC_MESSAGE_HANDLER(CefHostMsg_Response, OnResponse)
-    IPC_MESSAGE_HANDLER(CefHostMsg_ResponseAck, OnResponseAck)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  return handled;
+  SendToRenderFrame(__FUNCTION__,
+                    base::BindOnce([](const RenderFrameType& render_frame) {
+                      render_frame->DidStopLoading();
+                    }));
 }
 
 void CefFrameHostImpl::ExecuteJavaScriptWithUserGestureForTests(
@@ -497,8 +472,10 @@
   }
 
   content::RenderFrameHost* rfh = GetRenderFrameHost();
-  if (rfh)
-    rfh->ExecuteJavaScriptWithUserGestureForTests(javascript);
+  if (rfh) {
+    rfh->ExecuteJavaScriptWithUserGestureForTests(javascript,
+                                                  base::NullCallback());
+  }
 }
 
 content::RenderFrameHost* CefFrameHostImpl::GetRenderFrameHost() const {
@@ -506,35 +483,84 @@
   return render_frame_host_;
 }
 
-void CefFrameHostImpl::Detach() {
+bool CefFrameHostImpl::Detach(DetachReason reason) {
   CEF_REQUIRE_UIT();
 
+  if (VLOG_IS_ON(1)) {
+    std::string reason_str;
+    switch (reason) {
+      case DetachReason::RENDER_FRAME_DELETED:
+        reason_str = "RENDER_FRAME_DELETED";
+        break;
+      case DetachReason::NEW_MAIN_FRAME:
+        reason_str = "NEW_MAIN_FRAME";
+        break;
+      case DetachReason::BROWSER_DESTROYED:
+        reason_str = "BROWSER_DESTROYED";
+        break;
+    };
+
+    VLOG(1) << GetDebugString() << " detached (reason=" << reason_str
+            << ", is_connected=" << render_frame_.is_bound() << ")";
+  }
+
+  // May be called multiple times (e.g. from CefBrowserInfo SetMainFrame and
+  // RemoveFrame).
+  bool first_detach = false;
+
+  // Should not be called for temporary frames.
+  DCHECK(!is_temporary());
+
   {
     base::AutoLock lock_scope(state_lock_);
-    browser_info_ = nullptr;
+    if (browser_info_) {
+      first_detach = true;
+      browser_info_ = nullptr;
+    }
   }
 
   // In case we never attached, clean up.
-  while (!queued_messages_.empty()) {
-    queued_messages_.pop();
+  while (!queued_renderer_actions_.empty()) {
+    queued_renderer_actions_.pop();
   }
 
-  response_manager_.reset();
+  if (render_frame_.is_bound()) {
+    render_frame_->FrameDetached();
+  }
+
+  render_frame_.reset();
   render_frame_host_ = nullptr;
+
+  return first_detach;
 }
 
-// static
-int64_t CefFrameHostImpl::MakeFrameId(const content::RenderFrameHost* host) {
+void CefFrameHostImpl::MaybeReAttach(
+    scoped_refptr<CefBrowserInfo> browser_info,
+    content::RenderFrameHost* render_frame_host) {
   CEF_REQUIRE_UIT();
-  auto host_nonconst = const_cast<content::RenderFrameHost*>(host);
-  return MakeFrameId(host_nonconst->GetProcess()->GetID(),
-                     host_nonconst->GetRoutingID());
-}
+  if (render_frame_.is_bound() && render_frame_host_ == render_frame_host) {
+    // Nothing to do here.
+    return;
+  }
 
-// static
-int64_t CefFrameHostImpl::MakeFrameId(int32_t render_process_id,
-                                      int32_t render_routing_id) {
-  return frame_util::MakeFrameId(render_process_id, render_routing_id);
+  // We expect that Detach() was called previously.
+  CHECK(!is_temporary());
+  CHECK(!render_frame_.is_bound());
+  CHECK(!render_frame_host_);
+
+  // The RFH may change but the GlobalId should remain the same.
+  CHECK_EQ(frame_id_,
+           frame_util::MakeFrameId(render_frame_host->GetGlobalId()));
+
+  {
+    base::AutoLock lock_scope(state_lock_);
+    browser_info_ = browser_info;
+  }
+
+  render_frame_host_ = render_frame_host;
+  RefreshAttributes();
+
+  // We expect a reconnect to be triggered via FrameAttached().
 }
 
 // kMainFrameId must be -1 to align with renderer expectations.
@@ -548,137 +574,157 @@
     static_cast<ui::PageTransition>(ui::PAGE_TRANSITION_TYPED |
                                     ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
 
-int64 CefFrameHostImpl::GetFrameId() const {
+int64_t CefFrameHostImpl::GetFrameId() const {
   base::AutoLock lock_scope(state_lock_);
   return is_main_frame_ ? kMainFrameId : frame_id_;
 }
 
-CefRefPtr<CefBrowserHostImpl> CefFrameHostImpl::GetBrowserHostImpl() const {
+scoped_refptr<CefBrowserInfo> CefFrameHostImpl::GetBrowserInfo() const {
   base::AutoLock lock_scope(state_lock_);
-  if (browser_info_)
-    return browser_info_->browser();
+  return browser_info_;
+}
+
+CefRefPtr<CefBrowserHostBase> CefFrameHostImpl::GetBrowserHostBase() const {
+  if (auto browser_info = GetBrowserInfo()) {
+    return browser_info->browser();
+  }
   return nullptr;
 }
 
-void CefFrameHostImpl::OnAttached() {
-  if (!is_attached_) {
-    is_attached_ = true;
-    while (!queued_messages_.empty()) {
-      Send(queued_messages_.front().release());
-      queued_messages_.pop();
-    }
-  }
-}
-
-void CefFrameHostImpl::OnDidFinishLoad(const GURL& validated_url,
-                                       int http_status_code) {
-  auto browser = GetBrowserHostImpl();
-  if (browser)
-    browser->OnDidFinishLoad(this, validated_url, http_status_code);
-}
-
-void CefFrameHostImpl::OnUpdateDraggableRegions(
-    const std::vector<Cef_DraggableRegion_Params>& regions) {
-  auto browser = GetBrowserHostImpl();
-  if (!browser)
-    return;
-
-  CefRefPtr<CefDragHandler> handler;
-  auto client = browser->GetClient();
-  if (client)
-    handler = client->GetDragHandler();
-  if (!handler)
-    return;
-
-  std::vector<CefDraggableRegion> draggable_regions;
-  draggable_regions.reserve(regions.size());
-
-  std::vector<Cef_DraggableRegion_Params>::const_iterator it = regions.begin();
-  for (; it != regions.end(); ++it) {
-    const gfx::Rect& rect(it->bounds);
-    const CefRect bounds(rect.x(), rect.y(), rect.width(), rect.height());
-    draggable_regions.push_back(CefDraggableRegion(bounds, it->draggable));
-  }
-
-  handler->OnDraggableRegionsChanged(browser.get(), this, draggable_regions);
-}
-
-void CefFrameHostImpl::OnRequest(const Cef_Request_Params& params) {
-  CEF_REQUIRE_UIT();
-
-  bool success = false;
-  std::string response;
-  bool expect_response_ack = false;
-
-  if (params.user_initiated) {
-    auto browser = GetBrowserHostImpl();
-    if (browser && browser->client()) {
-      // Give the user a chance to handle the request.
-      CefRefPtr<CefProcessMessageImpl> message(new CefProcessMessageImpl(
-          const_cast<Cef_Request_Params*>(&params), false, true));
-      success = browser->client()->OnProcessMessageReceived(
-          browser.get(), this, PID_RENDERER, message.get());
-      message->Detach(nullptr);
-    }
-  } else {
-    // Invalid request.
-    NOTREACHED();
-  }
-
-  if (params.expect_response) {
-    DCHECK_GE(params.request_id, 0);
-
-    // Send a response to the renderer.
-    Cef_Response_Params response_params;
-    response_params.request_id = params.request_id;
-    response_params.success = success;
-    response_params.response = response;
-    response_params.expect_response_ack = expect_response_ack;
-    Send(new CefMsg_Response(MSG_ROUTING_NONE, response_params));
-  }
-}
-
-void CefFrameHostImpl::OnResponse(const Cef_Response_Params& params) {
-  CEF_REQUIRE_UIT();
-
-  response_manager_->RunHandler(params);
-  if (params.expect_response_ack)
-    Send(new CefMsg_ResponseAck(MSG_ROUTING_NONE, params.request_id));
-}
-
-void CefFrameHostImpl::OnResponseAck(int request_id) {
-  response_manager_->RunAckHandler(request_id);
-}
-
-void CefFrameHostImpl::Send(IPC::Message* message) {
+void CefFrameHostImpl::SendToRenderFrame(const std::string& function_name,
+                                         RenderFrameAction action) {
   if (!CEF_CURRENTLY_ON_UIT()) {
     CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(base::IgnoreResult(&CefFrameHostImpl::Send),
-                                 this, message));
+                  base::BindOnce(&CefFrameHostImpl::SendToRenderFrame, this,
+                                 function_name, std::move(action)));
     return;
   }
 
-  if (!render_frame_host_) {
-    // Either we're a placeholder frame without a renderer representation, or
-    // we've been detached.
-    delete message;
+  if (is_temporary()) {
+    LOG(WARNING) << function_name
+                 << " sent to temporary subframe will be ignored.";
+    return;
+  } else if (!render_frame_host_) {
+    // We've been detached.
+    LOG(WARNING) << function_name << " sent to detached " << GetDebugString()
+                 << " will be ignored";
     return;
   }
 
-  if (!is_attached_) {
-    // Queue messages until we're notified by the renderer that it's ready to
+  if (!render_frame_.is_bound()) {
+    // Queue actions until we're notified by the renderer that it's ready to
     // handle them.
-    queued_messages_.push(base::WrapUnique(message));
+    queued_renderer_actions_.push(
+        std::make_pair(function_name, std::move(action)));
     return;
   }
 
-  message->set_routing_id(render_frame_host_->GetRoutingID());
-  render_frame_host_->Send(message);
+  std::move(action).Run(render_frame_);
+}
+
+void CefFrameHostImpl::OnRenderFrameDisconnect() {
+  CEF_REQUIRE_UIT();
+
+  // Reconnect, if any, will be triggered via FrameAttached().
+  render_frame_.reset();
+}
+
+void CefFrameHostImpl::SendMessage(const std::string& name,
+                                   base::Value::List arguments) {
+  if (auto browser = GetBrowserHostBase()) {
+    if (auto client = browser->GetClient()) {
+      CefRefPtr<CefProcessMessageImpl> message(
+          new CefProcessMessageImpl(name, std::move(arguments),
+                                    /*read_only=*/true));
+      browser->GetClient()->OnProcessMessageReceived(
+          browser.get(), this, PID_RENDERER, message.get());
+    }
+  }
+}
+
+void CefFrameHostImpl::SendSharedMemoryRegion(
+    const std::string& name,
+    base::WritableSharedMemoryRegion region) {
+  if (auto browser = GetBrowserHostBase()) {
+    if (auto client = browser->GetClient()) {
+      CefRefPtr<CefProcessMessage> message(
+          new CefProcessMessageSMRImpl(name, std::move(region)));
+      browser->GetClient()->OnProcessMessageReceived(browser.get(), this,
+                                                     PID_RENDERER, message);
+    }
+  }
+}
+
+void CefFrameHostImpl::FrameAttached(
+    mojo::PendingRemote<cef::mojom::RenderFrame> render_frame_remote,
+    bool reattached) {
+  CEF_REQUIRE_UIT();
+  CHECK(render_frame_remote);
+
+  auto browser_info = GetBrowserInfo();
+  if (!browser_info) {
+    // Already Detached.
+    return;
+  }
+
+  VLOG(1) << GetDebugString() << " " << (reattached ? "re" : "") << "connected";
+
+  render_frame_.Bind(std::move(render_frame_remote));
+  render_frame_.set_disconnect_handler(
+      base::BindOnce(&CefFrameHostImpl::OnRenderFrameDisconnect, this));
+
+  // Notify the renderer process that it can start sending messages.
+  render_frame_->FrameAttachedAck();
+
+  while (!queued_renderer_actions_.empty()) {
+    std::move(queued_renderer_actions_.front().second).Run(render_frame_);
+    queued_renderer_actions_.pop();
+  }
+
+  browser_info->MaybeExecuteFrameNotification(base::BindOnce(
+      [](CefRefPtr<CefFrameHostImpl> self, bool reattached,
+         CefRefPtr<CefFrameHandler> handler) {
+        if (auto browser = self->GetBrowserHostBase()) {
+          handler->OnFrameAttached(browser, self, reattached);
+        }
+      },
+      CefRefPtr<CefFrameHostImpl>(this), reattached));
+}
+
+void CefFrameHostImpl::UpdateDraggableRegions(
+    absl::optional<std::vector<cef::mojom::DraggableRegionEntryPtr>> regions) {
+  auto browser = GetBrowserHostBase();
+  if (!browser) {
+    return;
+  }
+
+  std::vector<CefDraggableRegion> draggable_regions;
+  if (regions) {
+    draggable_regions.reserve(regions->size());
+
+    for (const auto& region : *regions) {
+      const auto& rect = region->bounds;
+      const CefRect bounds(rect.x(), rect.y(), rect.width(), rect.height());
+      draggable_regions.push_back(
+          CefDraggableRegion(bounds, region->draggable));
+    }
+  }
+
+  // Delegate to BrowserInfo so that current state is maintained with
+  // cross-origin navigation.
+  browser_info_->MaybeNotifyDraggableRegionsChanged(
+      browser, this, std::move(draggable_regions));
+}
+
+std::string CefFrameHostImpl::GetDebugString() const {
+  return "frame " + frame_util::GetFrameDebugString(frame_id_) +
+         (is_main_frame_ ? " (main)" : " (sub)");
 }
 
 void CefExecuteJavaScriptWithUserGestureForTests(CefRefPtr<CefFrame> frame,
                                                  const CefString& javascript) {
   CefFrameHostImpl* impl = static_cast<CefFrameHostImpl*>(frame.get());
-  if (impl)
+  if (impl) {
     impl->ExecuteJavaScriptWithUserGestureForTests(javascript);
+  }
 }
diff --git a/src/libcef/browser/frame_host_impl.h b/src/libcef/browser/frame_host_impl.h
index 4342502..c61df87 100644
--- a/src/libcef/browser/frame_host_impl.h
+++ b/src/libcef/browser/frame_host_impl.h
@@ -11,9 +11,11 @@
 #include <string>
 
 #include "include/cef_frame.h"
-#include "libcef/common/response_manager.h"
 
 #include "base/synchronization/lock.h"
+#include "cef/libcef/common/mojom/cef.mojom.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "ui/base/page_transition_types.h"
 
 namespace content {
@@ -21,34 +23,25 @@
 struct Referrer;
 }  // namespace content
 
-namespace IPC {
-class Message;
-}
-
 class GURL;
 
-struct Cef_DraggableRegion_Params;
-struct Cef_Request_Params;
-struct Cef_Response_Params;
 class CefBrowserInfo;
-class CefBrowserHostImpl;
-struct CefNavigateParams;
+class CefBrowserHostBase;
 
 // Implementation of CefFrame. CefFrameHostImpl objects should always be created
 // or retrieved via CefBrowerInfo.
-class CefFrameHostImpl : public CefFrame {
+class CefFrameHostImpl : public CefFrame, public cef::mojom::BrowserFrame {
  public:
-  // Create a temporary frame.
+  // Create a temporary sub-frame.
   CefFrameHostImpl(scoped_refptr<CefBrowserInfo> browser_info,
-                   bool is_main_frame,
                    int64_t parent_frame_id);
 
   // Create a frame backed by a RFH and owned by CefBrowserInfo.
   CefFrameHostImpl(scoped_refptr<CefBrowserInfo> browser_info,
                    content::RenderFrameHost* render_frame_host);
 
-  // Update an existing main frame object.
-  void SetRenderFrameHost(content::RenderFrameHost* host);
+  CefFrameHostImpl(const CefFrameHostImpl&) = delete;
+  CefFrameHostImpl& operator=(const CefFrameHostImpl&) = delete;
 
   ~CefFrameHostImpl() override;
 
@@ -72,7 +65,7 @@
   bool IsMain() override;
   bool IsFocused() override;
   CefString GetName() override;
-  int64 GetIdentifier() override;
+  int64_t GetIdentifier() override;
   CefRefPtr<CefFrame> GetParent() override;
   CefString GetURL() override;
   CefRefPtr<CefBrowser> GetBrowser() override;
@@ -84,11 +77,17 @@
   void SendProcessMessage(CefProcessId target_process,
                           CefRefPtr<CefProcessMessage> message) override;
 
+  bool is_temporary() const { return frame_id_ == kInvalidFrameId; }
+
   void SetFocused(bool focused);
   void RefreshAttributes();
 
-  // Navigate as specified by the |params| argument.
-  void Navigate(const CefNavigateParams& params);
+  // Notification that a move or resize of the renderer's containing window has
+  // started. Used on Windows and Linux with the Alloy runtime.
+  void NotifyMoveOrResizeStarted();
+
+  // Load the specified request.
+  void LoadRequest(cef::mojom::RequestParamsPtr params);
 
   // Load the specified URL.
   void LoadURLWithExtras(const std::string& url,
@@ -97,41 +96,54 @@
                          const std::string& extra_headers);
 
   // Send a command to the renderer for execution.
-  void SendCommand(const std::string& command,
-                   CefRefPtr<CefResponseManager::Handler> responseHandler);
-
-  // Send code to the renderer for execution.
-  void SendCode(bool is_javascript,
-                const std::string& code,
-                const std::string& script_url,
-                int script_start_line,
-                CefRefPtr<CefResponseManager::Handler> responseHandler);
+  void SendCommand(const std::string& command);
+  void SendCommandWithResponse(
+      const std::string& command,
+      cef::mojom::RenderFrame::SendCommandWithResponseCallback
+          response_callback);
 
   // Send JavaScript to the renderer for execution.
-  void SendJavaScript(const std::string& jsCode,
+  void SendJavaScript(const std::u16string& jsCode,
                       const std::string& scriptUrl,
                       int startLine);
 
-  // Called from CefBrowserHostImpl::DidStopLoading.
+  // Called from CefBrowserHostBase::DidStopLoading.
   void MaybeSendDidStopLoading();
 
-  // Called from CefBrowserHostImpl::OnMessageReceived.
-  bool OnMessageReceived(const IPC::Message& message);
-
   void ExecuteJavaScriptWithUserGestureForTests(const CefString& javascript);
 
   // Returns the RFH associated with this frame. Must be called on the UI
   // thread.
   content::RenderFrameHost* GetRenderFrameHost() const;
 
+  enum class DetachReason {
+    RENDER_FRAME_DELETED,
+    NEW_MAIN_FRAME,
+    BROWSER_DESTROYED,
+  };
+
   // Owned frame objects will be detached explicitly when the associated
   // RenderFrame is deleted. Temporary frame objects will be detached
-  // implicitly via CefBrowserInfo::browser() returning nullptr.
-  void Detach();
+  // implicitly via CefBrowserInfo::browser() returning nullptr. Returns true
+  // if this was the first call to Detach() for the frame.
+  bool Detach(DetachReason reason);
 
-  static int64_t MakeFrameId(const content::RenderFrameHost* host);
-  static int64_t MakeFrameId(int32_t render_process_id,
-                             int32_t render_routing_id);
+  // A frame has swapped to active status from prerendering or the back-forward
+  // cache. We may need to re-attach if the RFH has changed. See
+  // https://crbug.com/1179502#c8 for additional background.
+  void MaybeReAttach(scoped_refptr<CefBrowserInfo> browser_info,
+                     content::RenderFrameHost* render_frame_host);
+
+  // cef::mojom::BrowserFrame methods forwarded from CefBrowserFrame.
+  void SendMessage(const std::string& name,
+                   base::Value::List arguments) override;
+  void SendSharedMemoryRegion(const std::string& name,
+                              base::WritableSharedMemoryRegion region) override;
+  void FrameAttached(mojo::PendingRemote<cef::mojom::RenderFrame> render_frame,
+                     bool reattached) override;
+  void UpdateDraggableRegions(
+      absl::optional<std::vector<cef::mojom::DraggableRegionEntryPtr>> regions)
+      override;
 
   static const int64_t kMainFrameId;
   static const int64_t kFocusedFrameId;
@@ -144,46 +156,42 @@
   static const ui::PageTransition kPageTransitionExplicit;
 
  private:
-  int64 GetFrameId() const;
-  CefRefPtr<CefBrowserHostImpl> GetBrowserHostImpl() const;
+  int64_t GetFrameId() const;
+  scoped_refptr<CefBrowserInfo> GetBrowserInfo() const;
+  CefRefPtr<CefBrowserHostBase> GetBrowserHostBase() const;
 
-  // OnMessageReceived message handlers.
-  void OnAttached();
-  void OnDidFinishLoad(const GURL& validated_url, int http_status_code);
-  void OnUpdateDraggableRegions(
-      const std::vector<Cef_DraggableRegion_Params>& regions);
-  void OnRequest(const Cef_Request_Params& params);
-  void OnResponse(const Cef_Response_Params& params);
-  void OnResponseAck(int request_id);
+  // Send an action to the remote RenderFrame. This will queue the action if the
+  // remote frame is not yet attached.
+  using RenderFrameType = mojo::Remote<cef::mojom::RenderFrame>;
+  using RenderFrameAction = base::OnceCallback<void(const RenderFrameType&)>;
+  void SendToRenderFrame(const std::string& function_name,
+                         RenderFrameAction action);
 
-  // Send a message to the RenderFrameHost associated with this frame.
-  void Send(IPC::Message* message);
+  void OnRenderFrameDisconnect();
+
+  std::string GetDebugString() const;
 
   const bool is_main_frame_;
 
   // The following members may be read/modified from any thread. All access must
   // be protected by |state_lock_|.
   mutable base::Lock state_lock_;
-  int64 frame_id_;
+  int64_t frame_id_;
   scoped_refptr<CefBrowserInfo> browser_info_;
   bool is_focused_;
   CefString url_;
   CefString name_;
-  int64 parent_frame_id_;
+  int64_t parent_frame_id_;
 
   // The following members are only accessed on the UI thread.
   content::RenderFrameHost* render_frame_host_ = nullptr;
 
-  bool is_attached_ = false;
+  std::queue<std::pair<std::string, RenderFrameAction>>
+      queued_renderer_actions_;
 
-  // Qeueud messages to send when the renderer process attaches.
-  std::queue<std::unique_ptr<IPC::Message>> queued_messages_;
-
-  // Manages response registrations.
-  std::unique_ptr<CefResponseManager> response_manager_;
+  mojo::Remote<cef::mojom::RenderFrame> render_frame_;
 
   IMPLEMENT_REFCOUNTING(CefFrameHostImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefFrameHostImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_FRAME_HOST_IMPL_H_
diff --git a/src/libcef/browser/frame_service_base.h b/src/libcef/browser/frame_service_base.h
new file mode 100644
index 0000000..795ac29
--- /dev/null
+++ b/src/libcef/browser/frame_service_base.h
@@ -0,0 +1,126 @@
+// Copyright 2017 The Chromium 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 CEF_LIBCEF_BROWSER_FRAME_SERVICE_BASE_H_
+#define CEF_LIBCEF_BROWSER_FRAME_SERVICE_BASE_H_
+
+#include <utility>
+
+#include "base/functional/bind.h"
+#include "base/logging.h"
+#include "base/threading/thread_checker.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "url/origin.h"
+
+namespace content {
+
+// Base class for mojo interface implementations tied to a document's lifetime.
+// The service will be destroyed when any of the following happens:
+// 1. mojo interface connection error happened,
+// 2. the RenderFrameHost was deleted, or
+// 3. navigation was committed on the RenderFrameHost (not same document) and
+//    ShouldCloseOnFinishNavigation() returns true.
+//
+// WARNING: To avoid race conditions, subclasses MUST only get the origin via
+// origin() instead of from |render_frame_host| passed in the constructor.
+// See https://crbug.com/769189 for an example of such a race.
+//
+// Based on the old implementation of DocumentServiceBase that existed prior to
+// https://crrev.com/2809effa24. CEF requires the old implementation to support
+// bindings that outlive navigation.
+template <typename Interface>
+class FrameServiceBase : public Interface, public WebContentsObserver {
+ public:
+  FrameServiceBase(RenderFrameHost* render_frame_host,
+                   mojo::PendingReceiver<Interface> pending_receiver)
+      : WebContentsObserver(
+            WebContents::FromRenderFrameHost(render_frame_host)),
+        render_frame_host_(render_frame_host),
+        origin_(render_frame_host_->GetLastCommittedOrigin()),
+        receiver_(this, std::move(pending_receiver)) {
+    // |this| owns |receiver_|, so unretained is safe.
+    receiver_.set_disconnect_handler(
+        base::BindOnce(&FrameServiceBase::Close, base::Unretained(this)));
+  }
+
+ protected:
+  // Make the destructor private since |this| can only be deleted by Close().
+  virtual ~FrameServiceBase() = default;
+
+  // All subclasses should use this function to obtain the origin instead of
+  // trying to get it from the RenderFrameHost pointer directly.
+  const url::Origin& origin() const { return origin_; }
+
+  // Returns the RenderFrameHost held by this object.
+  RenderFrameHost* render_frame_host() const { return render_frame_host_; }
+
+  // Subclasses can use this to check thread safety.
+  // For example: DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  THREAD_CHECKER(thread_checker_);
+
+ private:
+  // Disallow calling web_contents() directly from the subclasses to ensure that
+  // tab-level state doesn't get queried or updated when the RenderFrameHost is
+  // not active.
+  // Use WebContents::From(render_frame_host()) instead, but please keep in mind
+  // that the render_frame_host() might not be active. See
+  // RenderFrameHost::IsActive() for details.
+  using WebContentsObserver::web_contents;
+
+  // WebContentsObserver implementation.
+  void RenderFrameDeleted(RenderFrameHost* render_frame_host) final {
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+    if (render_frame_host == render_frame_host_) {
+      DVLOG(1) << __func__ << ": RenderFrame destroyed.";
+      Close();
+    }
+  }
+
+  void DidFinishNavigation(NavigationHandle* navigation_handle) final {
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+    if (!ShouldCloseOnFinishNavigation()) {
+      return;
+    }
+
+    if (!navigation_handle->HasCommitted() ||
+        navigation_handle->IsSameDocument() ||
+        navigation_handle->IsPageActivation()) {
+      return;
+    }
+
+    if (navigation_handle->GetRenderFrameHost() == render_frame_host_) {
+      // FrameServiceBase is destroyed either when RenderFrameHost is
+      // destroyed (covered by RenderFrameDeleted) or when a new document
+      // commits in the same RenderFrameHost (covered by DidFinishNavigation).
+      // Only committed non-same-document non-bfcache non-prerendering
+      // activation navigations replace a document in existing RenderFrameHost.
+      DVLOG(1) << __func__ << ": Close connection on navigation.";
+      Close();
+    }
+  }
+
+  // Used for CEF bindings that outlive navigation.
+  virtual bool ShouldCloseOnFinishNavigation() const { return true; }
+
+  // Stops observing WebContents and delete |this|.
+  void Close() {
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+    DVLOG(1) << __func__;
+    delete this;
+  }
+
+  RenderFrameHost* const render_frame_host_ = nullptr;
+  const url::Origin origin_;
+  mojo::Receiver<Interface> receiver_;
+};
+
+}  // namespace content
+
+#endif  // CEF_LIBCEF_BROWSER_FRAME_SERVICE_BASE_H_
diff --git a/src/libcef/browser/geometry_util.cc b/src/libcef/browser/geometry_util.cc
new file mode 100644
index 0000000..65e2c6c
--- /dev/null
+++ b/src/libcef/browser/geometry_util.cc
@@ -0,0 +1,102 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "libcef/browser/geometry_util.h"
+
+#include <algorithm>
+
+#include "ui/gfx/geometry/rect.h"
+
+namespace {
+
+constexpr int kMinWidth = 0;
+constexpr int kMinHeight = 0;
+
+// Makes sure that line segment lies entirely between min and max.
+int clamp_segment_start(int start, int len, int min, int max) {
+  start = std::clamp(start, min, max);
+  const int end = start + len;
+  const int excess = end - max;
+
+  if (excess > 0) {
+    start = start - excess;
+  }
+
+  return start;
+}
+
+}  // namespace
+
+gfx::Rect MakeVisibleOnScreenRect(const gfx::Rect& rect,
+                                  const gfx::Rect& screen) {
+  const int width = std::clamp(rect.width(), kMinWidth, screen.width());
+  const int height = std::clamp(rect.height(), kMinHeight, screen.height());
+
+  const int right_border = screen.x() + screen.width();
+  const int x = clamp_segment_start(rect.x(), width, screen.x(), right_border);
+
+  const int bottom_border = screen.y() + screen.height();
+  const int y =
+      clamp_segment_start(rect.y(), height, screen.y(), bottom_border);
+
+  return gfx::Rect(x, y, width, height);
+}
+
+gfx::Rect SubtractOverlayFromBoundingBox(const gfx::Rect& bounds,
+                                         const gfx::Rect& overlay,
+                                         int max_distance) {
+  if (overlay.Contains(bounds)) {
+    // Early exit; |bounds| is completely inside |overlay|.
+    return bounds;
+  }
+
+  // Portion of |overlay| that is inside |bounds|.
+  auto overlap = overlay;
+  overlap.Intersect(bounds);
+  if (overlap.IsEmpty()) {
+    // Early exit; |bounds| and |overlay| don't intersect.
+    return bounds;
+  }
+
+  gfx::Insets insets;
+
+  if (overlap.width() >= overlap.height()) {
+    // Wide overlay; maybe inset |bounds| in the Y direction.
+    const int delta_top = overlap.y() - bounds.y();
+    const int delta_bottom =
+        bounds.y() + bounds.height() - overlap.y() - overlap.height();
+
+    // Inset from the closest side that meets |max_distance| requirements.
+    if (delta_top <= delta_bottom && delta_top <= max_distance) {
+      // Inset from the top.
+      insets.set_top(delta_top + overlap.height());
+    } else if (delta_bottom <= max_distance) {
+      // Inset from the bottom.
+      insets.set_bottom(delta_bottom + overlap.height());
+    }
+  } else {
+    // Tall overlay; maybe inset |bounds| in the X direction.
+    const int delta_left = overlap.x() - bounds.x();
+    const int delta_right =
+        bounds.x() + bounds.width() - overlap.x() - overlap.width();
+
+    // Inset from the closest side that meets |max_distance| requirements.
+    if (delta_left <= delta_right && delta_left <= max_distance) {
+      // Inset from the left.
+      insets.set_left(delta_left + overlap.width());
+    } else if (delta_right <= max_distance) {
+      // Inset from the right.
+      insets.set_right(delta_right + overlap.width());
+    }
+  }
+
+  if (insets.IsEmpty()) {
+    // |overlay| is too far inside |bounds| to trigger insets.
+    return bounds;
+  }
+
+  auto result = bounds;
+  result.Inset(insets);
+  return result;
+}
\ No newline at end of file
diff --git a/src/libcef/browser/geometry_util.h b/src/libcef/browser/geometry_util.h
new file mode 100644
index 0000000..25ec374
--- /dev/null
+++ b/src/libcef/browser/geometry_util.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_GEOMETRY_UTIL_H_
+#define CEF_LIBCEF_BROWSER_GEOMETRY_UTIL_H_
+#pragma once
+
+namespace gfx {
+class Rect;
+}
+
+// Create a new rectangle from the input |rect| rectangle that is fully visible
+// on provided |screen_rect| screen. The width and height of the resulting
+// rectangle are clamped to the screen width and height respectively if they
+// would overflow.
+gfx::Rect MakeVisibleOnScreenRect(const gfx::Rect& rect,
+                                  const gfx::Rect& screen);
+
+// Possibly subtract |overlay| from |bounds|. We only want to subtract overlays
+// that are inside |bounds| and close to the edges, so |max_distance| is the
+// maximum allowed distance between |overlay| and |bounds| extents in order to
+// trigger the subtraction. Subtraction will occur from the closest edge. If
+// distances are otherwise equal then top will be preferred followed by left.
+gfx::Rect SubtractOverlayFromBoundingBox(const gfx::Rect& bounds,
+                                         const gfx::Rect& overlay,
+                                         int max_distance);
+
+#endif  // CEF_LIBCEF_BROWSER_GEOMETRY_UTIL_H_
diff --git a/src/libcef/browser/geometry_util_unittest.cc b/src/libcef/browser/geometry_util_unittest.cc
new file mode 100644
index 0000000..ef8b947
--- /dev/null
+++ b/src/libcef/browser/geometry_util_unittest.cc
@@ -0,0 +1,352 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "cef/libcef/browser/geometry_util.h"
+#include "tests/gtest/include/gtest/gtest.h"
+
+#include "ui/gfx/geometry/rect.h"
+
+namespace {
+
+constexpr int kScreenWidth = 1024;
+constexpr int kScreenHeight = 768;
+const gfx::Rect kMainScreen(0, 0, kScreenWidth, kScreenHeight);
+const gfx::Rect kLeftScreen(-1024, 0, kScreenWidth, kScreenHeight);
+
+#define EXPECT_RECT_EQ(rect1, rect2)       \
+  EXPECT_EQ(rect1.x(), rect2.x());         \
+  EXPECT_EQ(rect1.y(), rect2.y());         \
+  EXPECT_EQ(rect1.width(), rect2.width()); \
+  EXPECT_EQ(rect1.height(), rect2.height())
+
+}  // namespace
+
+TEST(GeometryUtil, MakeVisibleOnScreenRect_RectSizeIsBiggerThanScreen) {
+  const gfx::Rect rect{400, 500, 1500, 800};
+
+  auto result = MakeVisibleOnScreenRect(rect, kMainScreen);
+
+  EXPECT_EQ(result.x(), 0);
+  EXPECT_EQ(result.width(), kMainScreen.width());
+  EXPECT_EQ(result.y(), 0);
+  EXPECT_EQ(result.height(), kMainScreen.height());
+}
+
+TEST(GeometryUtil, MakeVisibleOnScreenRect_RightBorderIsOutsideTheScreen) {
+  const gfx::Rect rect{600, 400, 500, 300};
+
+  auto result = MakeVisibleOnScreenRect(rect, kMainScreen);
+
+  EXPECT_EQ(result.x(), 524);
+  EXPECT_EQ(result.width(), rect.width());
+  EXPECT_EQ(result.y(), rect.y());
+  EXPECT_EQ(result.height(), rect.height());
+}
+
+TEST(GeometryUtil, MakeVisibleOnScreenRect_LeftBorderIsOutsideTheScreen) {
+  const gfx::Rect rect{-400, 400, 500, 300};
+
+  auto result = MakeVisibleOnScreenRect(rect, kMainScreen);
+
+  EXPECT_EQ(result.x(), 0);
+  EXPECT_EQ(result.width(), rect.width());
+  EXPECT_EQ(result.y(), rect.y());
+  EXPECT_EQ(result.height(), rect.height());
+}
+
+TEST(GeometryUtil, MakeVisibleOnScreenRect_BottomBorderIsOutsideTheScreen) {
+  const gfx::Rect rect{600, 500, 300, 300};
+
+  auto result = MakeVisibleOnScreenRect(rect, kMainScreen);
+
+  EXPECT_EQ(result.x(), 600);
+  EXPECT_EQ(result.width(), rect.width());
+  EXPECT_EQ(result.y(), 468);
+  EXPECT_EQ(result.height(), rect.height());
+}
+
+TEST(GeometryUtil, MakeVisibleOnScreenRect_RectIsVisibleOnTheLeftScreen) {
+  const gfx::Rect rect{-500, 300, 300, 300};
+
+  auto result = MakeVisibleOnScreenRect(rect, kLeftScreen);
+
+  EXPECT_RECT_EQ(result, rect);
+}
+
+TEST(GeometryUtil, MakeVisibleOnScreenRect_RectSizeIsBiggerThanLeftScreen) {
+  const gfx::Rect rect{-500, 300, 3000, 3000};
+
+  auto result = MakeVisibleOnScreenRect(rect, kLeftScreen);
+
+  EXPECT_RECT_EQ(result, kLeftScreen);
+}
+
+TEST(GeometryUtil, SubtractOverlayFromBoundingBox_Square_NoIntersect_NoInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{0, 0, 10, 10};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 10);
+
+  EXPECT_RECT_EQ(bounds, result);
+}
+
+TEST(GeometryUtil, SubtractOverlayFromBoundingBox_Square_Contains_NoInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{5, 5, 85, 85};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 10);
+
+  EXPECT_RECT_EQ(bounds, result);
+}
+
+TEST(GeometryUtil, SubtractOverlayFromBoundingBox_Square_AllClose_TopInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{12, 12, 76, 76};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  // When all sides are close, inset from the top.
+  const gfx::Rect expected_bounds{10, 88, 80, 2};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_Square_TopAndLeftClose_TopInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{12, 12, 30, 30};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  // When top and left sides are close, inset from the top.
+  const gfx::Rect expected_bounds{10, 42, 80, 48};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_Square_TopAndRightClose_TopInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{58, 12, 30, 30};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  // When top and right sides are close, inset from the top.
+  const gfx::Rect expected_bounds{10, 42, 80, 48};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_Square_BottomAndLeftClose_BottomInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{12, 58, 30, 30};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  // When bottom and left sides are close, inset from the botom.
+  const gfx::Rect expected_bounds{10, 10, 80, 48};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_Square_BottomAndRightClose_BottomInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{58, 58, 30, 30};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  // When bottom and right sides are close, inset from the botom.
+  const gfx::Rect expected_bounds{10, 10, 80, 48};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_WideRect_TopAndLeftExact_TopInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{10, 10, 10, 5};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 0);
+
+  const gfx::Rect expected_bounds{10, 15, 80, 75};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_WideRect_TopIntersectLeftExact_TopInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{10, 7, 10, 5};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  const gfx::Rect expected_bounds{10, 12, 80, 78};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_WideRect_TopInsideLeftExact_TopInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{10, 12, 10, 5};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  const gfx::Rect expected_bounds{10, 17, 80, 73};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_WideRect_TopTooFarInsideLeftExact_NoInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{10, 16, 10, 5};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  EXPECT_RECT_EQ(bounds, result);
+}
+
+TEST(GeometryUtil, SubtractOverlayFromBoundingBox_WideRect_Oversized_TopInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{5, 5, 85, 10};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 10);
+
+  const gfx::Rect expected_bounds{10, 15, 80, 75};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_WideRect_BottomAndLeftExact_BottomInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{10, 85, 10, 5};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 0);
+
+  const gfx::Rect expected_bounds{10, 10, 80, 75};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(
+    GeometryUtil,
+    SubtractOverlayFromBoundingBox_WideRect_BottomInsideLeftExact_BottomInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{10, 83, 10, 5};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  const gfx::Rect expected_bounds{10, 10, 80, 73};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(
+    GeometryUtil,
+    SubtractOverlayFromBoundingBox_WideRect_BottomIntersectLeftExact_BottomInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{10, 87, 10, 5};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  const gfx::Rect expected_bounds{10, 10, 80, 77};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(
+    GeometryUtil,
+    SubtractOverlayFromBoundingBox_WideRect_BottomTooFarInsideLeftExact_NoInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{10, 77, 10, 5};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  EXPECT_RECT_EQ(bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_WideRect_Oversized_BottomInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{5, 85, 85, 10};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 10);
+
+  const gfx::Rect expected_bounds{10, 10, 80, 75};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_TallRect_TopAndLeftExact_LeftInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{10, 10, 5, 10};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 0);
+
+  const gfx::Rect expected_bounds{15, 10, 75, 80};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_TallRect_TopExactLeftIntersect_LeftInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{7, 10, 5, 10};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  const gfx::Rect expected_bounds{12, 10, 78, 80};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_TallRect_TopExactLeftInside_LeftInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{12, 10, 5, 10};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  const gfx::Rect expected_bounds{17, 10, 73, 80};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_TallRect_TopExactLeftTooFarInside_NoInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{16, 10, 5, 10};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  EXPECT_RECT_EQ(bounds, result);
+}
+
+TEST(GeometryUtil, SubtractOverlayFromBoundingBox_TallRect_Oversize_LeftInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{5, 5, 10, 85};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 10);
+
+  const gfx::Rect expected_bounds{15, 10, 75, 80};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_TallRect_TopAndRightExact_RightInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{85, 10, 5, 10};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 0);
+
+  const gfx::Rect expected_bounds{10, 10, 75, 80};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_TallRect_TopExactRightInside_RightInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{83, 10, 5, 10};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  const gfx::Rect expected_bounds{10, 10, 73, 80};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(
+    GeometryUtil,
+    SubtractOverlayFromBoundingBox_TallRect_TopExactRightIntersect_RightInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{87, 10, 5, 10};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  const gfx::Rect expected_bounds{10, 10, 77, 80};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
+
+TEST(
+    GeometryUtil,
+    SubtractOverlayFromBoundingBox_TallRect_TopExactRightTooFarInside_NoInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{77, 10, 5, 10};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 5);
+
+  EXPECT_RECT_EQ(bounds, result);
+}
+
+TEST(GeometryUtil,
+     SubtractOverlayFromBoundingBox_TallRect_Oversize_RightInset) {
+  const gfx::Rect bounds{10, 10, 80, 80};
+  const gfx::Rect overlay{85, 5, 10, 85};
+  auto result = SubtractOverlayFromBoundingBox(bounds, overlay, 10);
+
+  const gfx::Rect expected_bounds{10, 10, 75, 80};
+  EXPECT_RECT_EQ(expected_bounds, result);
+}
diff --git a/src/libcef/browser/global_preference_manager_impl.cc b/src/libcef/browser/global_preference_manager_impl.cc
new file mode 100644
index 0000000..4259b16
--- /dev/null
+++ b/src/libcef/browser/global_preference_manager_impl.cc
@@ -0,0 +1,54 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "libcef/browser/global_preference_manager_impl.h"
+
+#include "libcef/browser/context.h"
+#include "libcef/browser/prefs/pref_helper.h"
+#include "libcef/browser/thread_util.h"
+
+#include "chrome/browser/browser_process.h"
+
+bool CefGlobalPreferenceManagerImpl::HasPreference(const CefString& name) {
+  CEF_REQUIRE_UIT_RETURN(false);
+  return pref_helper::HasPreference(g_browser_process->local_state(), name);
+}
+
+CefRefPtr<CefValue> CefGlobalPreferenceManagerImpl::GetPreference(
+    const CefString& name) {
+  CEF_REQUIRE_UIT_RETURN(nullptr);
+  return pref_helper::GetPreference(g_browser_process->local_state(), name);
+}
+
+CefRefPtr<CefDictionaryValue> CefGlobalPreferenceManagerImpl::GetAllPreferences(
+    bool include_defaults) {
+  CEF_REQUIRE_UIT_RETURN(nullptr);
+  return pref_helper::GetAllPreferences(g_browser_process->local_state(),
+                                        include_defaults);
+}
+
+bool CefGlobalPreferenceManagerImpl::CanSetPreference(const CefString& name) {
+  CEF_REQUIRE_UIT_RETURN(false);
+  return pref_helper::CanSetPreference(g_browser_process->local_state(), name);
+}
+
+bool CefGlobalPreferenceManagerImpl::SetPreference(const CefString& name,
+                                                   CefRefPtr<CefValue> value,
+                                                   CefString& error) {
+  CEF_REQUIRE_UIT_RETURN(false);
+  return pref_helper::SetPreference(g_browser_process->local_state(), name,
+                                    value, error);
+}
+
+// static
+CefRefPtr<CefPreferenceManager>
+CefPreferenceManager::GetGlobalPreferenceManager() {
+  // Verify that the context is in a valid state.
+  if (!CONTEXT_STATE_VALID()) {
+    DCHECK(false) << "context not valid";
+    return nullptr;
+  }
+
+  return new CefGlobalPreferenceManagerImpl();
+}
diff --git a/src/libcef/browser/global_preference_manager_impl.h b/src/libcef/browser/global_preference_manager_impl.h
new file mode 100644
index 0000000..d10a7f5
--- /dev/null
+++ b/src/libcef/browser/global_preference_manager_impl.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_GLOBAL_PREFERENCE_MANAGER_IMPL_H_
+#define CEF_LIBCEF_BROWSER_GLOBAL_PREFERENCE_MANAGER_IMPL_H_
+#pragma once
+
+#include "include/cef_preference.h"
+
+// Implementation of the CefPreferenceManager interface for global preferences.
+class CefGlobalPreferenceManagerImpl : public CefPreferenceManager {
+ public:
+  CefGlobalPreferenceManagerImpl() = default;
+
+  CefGlobalPreferenceManagerImpl(const CefGlobalPreferenceManagerImpl&) =
+      delete;
+  CefGlobalPreferenceManagerImpl& operator=(
+      const CefGlobalPreferenceManagerImpl&) = delete;
+
+  // CefPreferenceManager methods.
+  bool HasPreference(const CefString& name) override;
+  CefRefPtr<CefValue> GetPreference(const CefString& name) override;
+  CefRefPtr<CefDictionaryValue> GetAllPreferences(
+      bool include_defaults) override;
+  bool CanSetPreference(const CefString& name) override;
+  bool SetPreference(const CefString& name,
+                     CefRefPtr<CefValue> value,
+                     CefString& error) override;
+
+ private:
+  IMPLEMENT_REFCOUNTING(CefGlobalPreferenceManagerImpl);
+};
+
+#endif  // CEF_LIBCEF_BROWSER_GLOBAL_PREFERENCE_MANAGER_IMPL_H_
diff --git a/src/libcef/browser/gpu/external_texture_manager.cc b/src/libcef/browser/gpu/external_texture_manager.cc
index 08cd7da..cf06c10 100644
--- a/src/libcef/browser/gpu/external_texture_manager.cc
+++ b/src/libcef/browser/gpu/external_texture_manager.cc
@@ -13,7 +13,7 @@
 #include "ui/gl/gl_surface_egl.h"
 #include "ui/gl/init/gl_factory.h"
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 #include <d3d11_1.h>
 #include "ui/gl/gl_angle_util_win.h"
 #include "ui/gl/gl_image_dxgi.h"
@@ -29,7 +29,7 @@
 
 namespace {
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 
 class GLImageDXGISharedHandle : public gl::GLImageDXGI {
  public:
@@ -134,7 +134,7 @@
   GLuint texture_id_;
 };
 
-#endif  // defined(OS_WIN)
+#endif  // BUILDFLAG(IS_WIN)
 
 }  // namespace
 
@@ -148,7 +148,7 @@
                                             TextureManager* tex_man) {
   void* share_handle = nullptr;
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();
   if (egl_display == EGL_NO_DISPLAY) {
     return nullptr;
@@ -259,36 +259,36 @@
 
   eglMakeCurrent(egl_display, drawSurface, readSurface, curContext);
 
-#endif  // defined(OS_WIN)
+#endif  // BUILDFLAG(IS_WIN)
 
   return share_handle;
 }
 
 void ExternalTextureManager::LockTexture(void* handle) {
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   auto const img = surfaceMap_.find(handle);
   if (img != surfaceMap_.end()) {
     GLImageDXGISharedHandle* dxgi_image =
         reinterpret_cast<GLImageDXGISharedHandle*>(img->second.get());
     dxgi_image->Lock();
   }
-#endif  // defined(OS_WIN)
+#endif  // BUILDFLAG(IS_WIN)
 }
 
 void ExternalTextureManager::UnlockTexture(void* handle) {
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   auto const img = surfaceMap_.find(handle);
   if (img != surfaceMap_.end()) {
     GLImageDXGISharedHandle* dxgi_image =
         reinterpret_cast<GLImageDXGISharedHandle*>(img->second.get());
     dxgi_image->Unlock();
   }
-#endif  // defined(OS_WIN)
+#endif  // BUILDFLAG(IS_WIN)
 }
 
 void ExternalTextureManager::DeleteTexture(void* handle,
                                            TextureManager* tex_man) {
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();
   if (egl_display == EGL_NO_DISPLAY) {
     return;
@@ -334,7 +334,7 @@
     }
   }
   surfaceMap_.erase(img);
-#endif  // defined(OS_WIN)
+#endif  // BUILDFLAG(IS_WIN)
 }
 
 }  // namespace gles2
diff --git a/src/libcef/browser/gpu/external_texture_manager.h b/src/libcef/browser/gpu/external_texture_manager.h
index b090d7c..02a1cfd 100644
--- a/src/libcef/browser/gpu/external_texture_manager.h
+++ b/src/libcef/browser/gpu/external_texture_manager.h
@@ -36,7 +36,7 @@
   void DeleteTexture(void* handle, TextureManager* tex_man);
 
  private:
-  typedef std::map<void*, scoped_refptr<gl::GLImage>> ExternalSurfaceMap;
+  using ExternalSurfaceMap = std::map<void*, scoped_refptr<gl::GLImage>>;
   ExternalSurfaceMap surfaceMap_;
 };
 
diff --git a/src/libcef/browser/image_impl.cc b/src/libcef/browser/image_impl.cc
index a4a77c9..2a91c8f 100644
--- a/src/libcef/browser/image_impl.cc
+++ b/src/libcef/browser/image_impl.cc
@@ -6,10 +6,13 @@
 
 #include <algorithm>
 
+#include "skia/ext/skia_utils_base.h"
 #include "ui/gfx/codec/jpeg_codec.h"
 #include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/geometry/size.h"
 #include "ui/gfx/image/image_png_rep.h"
 #include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/image/image_skia_rep.h"
 
 namespace {
 
@@ -23,7 +26,7 @@
       break;
   }
 
-  NOTREACHED();
+  DCHECK(false);
   return kUnknown_SkColorType;
 }
 
@@ -39,7 +42,7 @@
       break;
   }
 
-  NOTREACHED();
+  DCHECK(false);
   return kUnknown_SkAlphaType;
 }
 
@@ -82,12 +85,14 @@
 
 bool CefImageImpl::IsSame(CefRefPtr<CefImage> that) {
   CefImageImpl* that_impl = static_cast<CefImageImpl*>(that.get());
-  if (!that_impl)
+  if (!that_impl) {
     return false;
+  }
 
   // Quick check for the same object.
-  if (this == that_impl)
+  if (this == that_impl) {
     return true;
+  }
 
   base::AutoLock lock_scope(lock_);
   return image_.AsImageSkia().BackedBySameObjectAs(
@@ -105,10 +110,12 @@
   const SkAlphaType at = GetSkAlphaType(alpha_type);
 
   // Make sure the client passed in the expected values.
-  if (ct != kBGRA_8888_SkColorType && ct != kRGBA_8888_SkColorType)
+  if (ct != kBGRA_8888_SkColorType && ct != kRGBA_8888_SkColorType) {
     return false;
-  if (pixel_data_size != pixel_width * pixel_height * 4U)
+  }
+  if (pixel_data_size != pixel_width * pixel_height * 4U) {
     return false;
+  }
 
   SkBitmap bitmap;
   if (!bitmap.tryAllocPixels(
@@ -139,8 +146,9 @@
                            size_t jpeg_data_size) {
   std::unique_ptr<SkBitmap> bitmap(gfx::JPEGCodec::Decode(
       static_cast<const unsigned char*>(jpeg_data), jpeg_data_size));
-  if (!bitmap.get())
+  if (!bitmap.get()) {
     return false;
+  }
 
   return AddBitmap(scale_factor, *bitmap);
 }
@@ -176,12 +184,14 @@
                                          int& pixel_height) {
   base::AutoLock lock_scope(lock_);
   gfx::ImageSkia image_skia = image_.AsImageSkia();
-  if (image_skia.isNull())
+  if (image_skia.isNull()) {
     return false;
+  }
 
   const gfx::ImageSkiaRep& rep = image_skia.GetRepresentation(scale_factor);
-  if (rep.is_null())
+  if (rep.is_null()) {
     return false;
+  }
 
   actual_scale_factor = rep.scale();
   pixel_width = rep.GetBitmap().width();
@@ -199,8 +209,9 @@
 
   base::AutoLock lock_scope(lock_);
   const SkBitmap* bitmap = GetBitmap(scale_factor);
-  if (!bitmap)
+  if (!bitmap) {
     return nullptr;
+  }
 
   DCHECK(bitmap->readyToDraw());
 
@@ -213,8 +224,9 @@
                                   bitmap->computeByteSize());
   } else {
     SkBitmap desired_bitmap;
-    if (!ConvertBitmap(*bitmap, &desired_bitmap, desired_ct, desired_at))
+    if (!ConvertBitmap(*bitmap, &desired_bitmap, desired_ct, desired_at)) {
       return nullptr;
+    }
     DCHECK(desired_bitmap.readyToDraw());
     return CefBinaryValue::Create(desired_bitmap.getPixels(),
                                   desired_bitmap.computeByteSize());
@@ -227,12 +239,14 @@
                                                  int& pixel_height) {
   base::AutoLock lock_scope(lock_);
   const SkBitmap* bitmap = GetBitmap(scale_factor);
-  if (!bitmap)
+  if (!bitmap) {
     return nullptr;
+  }
 
   std::vector<unsigned char> compressed;
-  if (!WritePNG(*bitmap, &compressed, with_transparency))
+  if (!WritePNG(*bitmap, &compressed, with_transparency)) {
     return nullptr;
+  }
 
   pixel_width = bitmap->width();
   pixel_height = bitmap->height();
@@ -246,12 +260,14 @@
                                                   int& pixel_height) {
   base::AutoLock lock_scope(lock_);
   const SkBitmap* bitmap = GetBitmap(scale_factor);
-  if (!bitmap)
+  if (!bitmap) {
     return nullptr;
+  }
 
   std::vector<unsigned char> compressed;
-  if (!WriteJPEG(*bitmap, &compressed, quality))
+  if (!WriteJPEG(*bitmap, &compressed, quality)) {
     return nullptr;
+  }
 
   pixel_width = bitmap->width();
   pixel_height = bitmap->height();
@@ -266,8 +282,9 @@
     int32_t min_size = std::numeric_limits<int32_t>::max();
     for (const SkBitmap& bitmap : bitmaps) {
       const int32_t size = std::max(bitmap.width(), bitmap.height());
-      if (size < min_size)
+      if (size < min_size) {
         min_size = size;
+      }
     }
     scale_1x_size = min_size;
   }
@@ -290,8 +307,9 @@
 
   const SkBitmap* bitmap = GetBitmap(scale_factor);
   gfx::ImageSkia image_skia;
-  if (bitmap)
+  if (bitmap) {
     image_skia.AddRepresentation(gfx::ImageSkiaRep(*bitmap, 1.0f));
+  }
   return image_skia;
 }
 
@@ -307,7 +325,16 @@
   DCHECK(bitmap.colorType() == kBGRA_8888_SkColorType ||
          bitmap.colorType() == kRGBA_8888_SkColorType);
 
-  gfx::ImageSkiaRep skia_rep(bitmap, scale_factor);
+  // Convert to N32 (e.g. native encoding) format if not already in that format.
+  // N32 is expected by the Views framework and this early conversion avoids
+  // CHECKs in ImageSkiaRep and eventual conversion to N32 at some later point
+  // in the compositing pipeline.
+  SkBitmap n32_bitmap;
+  if (!skia::SkBitmapToN32OpaqueOrPremul(bitmap, &n32_bitmap)) {
+    return false;
+  }
+
+  gfx::ImageSkiaRep skia_rep(n32_bitmap, scale_factor);
   base::AutoLock lock_scope(lock_);
   if (image_.IsEmpty()) {
     image_ = gfx::Image(gfx::ImageSkia(skia_rep));
@@ -320,12 +347,14 @@
 const SkBitmap* CefImageImpl::GetBitmap(float scale_factor) const {
   lock_.AssertAcquired();
   gfx::ImageSkia image_skia = image_.AsImageSkia();
-  if (image_skia.isNull())
+  if (image_skia.isNull()) {
     return nullptr;
+  }
 
   const gfx::ImageSkiaRep& rep = image_skia.GetRepresentation(scale_factor);
-  if (rep.is_null())
+  if (rep.is_null()) {
     return nullptr;
+  }
 
   return &rep.GetBitmap();
 }
@@ -342,8 +371,9 @@
 
   SkImageInfo target_info = SkImageInfo::Make(
       src_bitmap.width(), src_bitmap.height(), target_ct, target_at);
-  if (!target_bitmap->tryAllocPixels(target_info))
+  if (!target_bitmap->tryAllocPixels(target_info)) {
     return false;
+  }
 
   if (!src_bitmap.readPixels(target_info, target_bitmap->getPixels(),
                              target_bitmap->rowBytes(), 0, 0)) {
@@ -357,7 +387,7 @@
 // static
 bool CefImageImpl::WriteCompressedFormat(const SkBitmap& bitmap,
                                          std::vector<unsigned char>* compressed,
-                                         const CompressionMethod& method) {
+                                         CompressionMethod method) {
   const SkBitmap* bitmap_ptr = nullptr;
   SkBitmap bitmap_postalpha;
   if (bitmap.alphaType() == kPremul_SkAlphaType) {
@@ -377,7 +407,7 @@
   DCHECK(bitmap_ptr->alphaType() == kOpaque_SkAlphaType ||
          bitmap_ptr->alphaType() == kUnpremul_SkAlphaType);
 
-  return method.Run(*bitmap_ptr, compressed);
+  return std::move(method).Run(*bitmap_ptr, compressed);
 }
 
 // static
@@ -385,7 +415,7 @@
                             std::vector<unsigned char>* compressed,
                             bool with_transparency) {
   return WriteCompressedFormat(bitmap, compressed,
-                               base::Bind(PNGMethod, with_transparency));
+                               base::BindOnce(PNGMethod, with_transparency));
 }
 
 // static
@@ -393,5 +423,5 @@
                              std::vector<unsigned char>* compressed,
                              int quality) {
   return WriteCompressedFormat(bitmap, compressed,
-                               base::Bind(JPEGMethod, quality));
+                               base::BindOnce(JPEGMethod, quality));
 }
diff --git a/src/libcef/browser/image_impl.h b/src/libcef/browser/image_impl.h
index 9859f37..36d75f4 100644
--- a/src/libcef/browser/image_impl.h
+++ b/src/libcef/browser/image_impl.h
@@ -21,6 +21,9 @@
   // representation.
   explicit CefImageImpl(const gfx::ImageSkia& image_skia);
 
+  CefImageImpl(const CefImageImpl&) = delete;
+  CefImageImpl& operator=(const CefImageImpl&) = delete;
+
   // Deletes the image and, if the only owner of the storage, all of its cached
   // representations.
   ~CefImageImpl() override = default;
@@ -95,14 +98,14 @@
 
   // The |bitmap| argument will be RGBA or BGRA and either opaque or transparent
   // with post-multiplied alpha. Writes the compressed output into |compressed|.
-  typedef base::Callback<bool(const SkBitmap& /*bitmap*/,
-                              std::vector<unsigned char>* /*compressed*/)>
-      CompressionMethod;
+  using CompressionMethod =
+      base::OnceCallback<bool(const SkBitmap& /*bitmap*/,
+                              std::vector<unsigned char>* /*compressed*/)>;
 
   // Write |bitmap| into |compressed| using |method|.
   static bool WriteCompressedFormat(const SkBitmap& bitmap,
                                     std::vector<unsigned char>* compressed,
-                                    const CompressionMethod& method);
+                                    CompressionMethod method);
 
   // Write |bitmap| into |compressed| using PNG encoding.
   static bool WritePNG(const SkBitmap& bitmap,
@@ -121,7 +124,6 @@
   gfx::Image image_;
 
   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefImageImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefImageImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_IMAGE_IMPL_H_
diff --git a/src/libcef/browser/resource_context.cc b/src/libcef/browser/iothread_state.cc
similarity index 62%
rename from src/libcef/browser/resource_context.cc
rename to src/libcef/browser/iothread_state.cc
index 8d1b7c6..4b4d3b1 100644
--- a/src/libcef/browser/resource_context.cc
+++ b/src/libcef/browser/iothread_state.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "libcef/browser/resource_context.h"
+#include "libcef/browser/iothread_state.h"
 
 #include "libcef/browser/net/scheme_handler.h"
 #include "libcef/browser/thread_util.h"
@@ -14,47 +14,41 @@
 #include "base/strings/utf_string_conversions.h"
 #include "content/browser/resource_context_impl.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/global_routing_id.h"
 
-CefResourceContext::CefResourceContext(bool is_off_the_record)
-    : is_off_the_record_(is_off_the_record) {
+CefIOThreadState::CefIOThreadState() {
   // Using base::Unretained() is safe because both this callback and possible
   // deletion of |this| will execute on the IO thread, and this callback will
   // be executed first.
-  CEF_POST_TASK(CEF_IOT, base::Bind(&CefResourceContext::InitOnIOThread,
-                                    base::Unretained(this)));
+  CEF_POST_TASK(CEF_IOT, base::BindOnce(&CefIOThreadState::InitOnIOThread,
+                                        base::Unretained(this)));
 }
 
-CefResourceContext::~CefResourceContext() {}
+CefIOThreadState::~CefIOThreadState() {
+  CEF_REQUIRE_IOT();
+}
 
-void CefResourceContext::AddHandler(
-    int render_process_id,
-    int render_frame_id,
-    int frame_tree_node_id,
+void CefIOThreadState::AddHandler(
+    const content::GlobalRenderFrameHostId& global_id,
     CefRefPtr<CefRequestContextHandler> handler) {
   CEF_REQUIRE_IOT();
-  handler_map_.AddHandler(render_process_id, render_frame_id,
-                          frame_tree_node_id, handler);
+  handler_map_.AddHandler(global_id, handler);
 }
 
-void CefResourceContext::RemoveHandler(int render_process_id,
-                                       int render_frame_id,
-                                       int frame_tree_node_id) {
+void CefIOThreadState::RemoveHandler(
+    const content::GlobalRenderFrameHostId& global_id) {
   CEF_REQUIRE_IOT();
-  handler_map_.RemoveHandler(render_process_id, render_frame_id,
-                             frame_tree_node_id);
+  handler_map_.RemoveHandler(global_id);
 }
 
-CefRefPtr<CefRequestContextHandler> CefResourceContext::GetHandler(
-    int render_process_id,
-    int render_frame_id,
-    int frame_tree_node_id,
+CefRefPtr<CefRequestContextHandler> CefIOThreadState::GetHandler(
+    const content::GlobalRenderFrameHostId& global_id,
     bool require_frame_match) const {
   CEF_REQUIRE_IOT();
-  return handler_map_.GetHandler(render_process_id, render_frame_id,
-                                 frame_tree_node_id, require_frame_match);
+  return handler_map_.GetHandler(global_id, require_frame_match);
 }
 
-void CefResourceContext::RegisterSchemeHandlerFactory(
+void CefIOThreadState::RegisterSchemeHandlerFactory(
     const std::string& scheme_name,
     const std::string& domain_name,
     CefRefPtr<CefSchemeHandlerFactory> factory) {
@@ -78,12 +72,13 @@
   } else {
     // Remove the existing factory, if any.
     auto it = scheme_handler_factory_map_.find(key);
-    if (it != scheme_handler_factory_map_.end())
+    if (it != scheme_handler_factory_map_.end()) {
       scheme_handler_factory_map_.erase(it);
+    }
   }
 }
 
-void CefResourceContext::ClearSchemeHandlerFactories() {
+void CefIOThreadState::ClearSchemeHandlerFactories() {
   CEF_REQUIRE_IOT();
 
   scheme_handler_factory_map_.clear();
@@ -92,12 +87,13 @@
   scheme::RegisterInternalHandlers(this);
 }
 
-CefRefPtr<CefSchemeHandlerFactory> CefResourceContext::GetSchemeHandlerFactory(
+CefRefPtr<CefSchemeHandlerFactory> CefIOThreadState::GetSchemeHandlerFactory(
     const GURL& url) {
   CEF_REQUIRE_IOT();
 
-  if (scheme_handler_factory_map_.empty())
+  if (scheme_handler_factory_map_.empty()) {
     return nullptr;
+  }
 
   const std::string& scheme_lower = url.scheme();
   const std::string& domain_lower =
@@ -110,20 +106,22 @@
     // Try for a match with hostname first.
     const auto it = scheme_handler_factory_map_.find(
         std::make_pair(scheme_lower, domain_lower));
-    if (it != scheme_handler_factory_map_.end())
+    if (it != scheme_handler_factory_map_.end()) {
       return it->second;
+    }
   }
 
   // Try for a match with no specified hostname.
   const auto it = scheme_handler_factory_map_.find(
       std::make_pair(scheme_lower, std::string()));
-  if (it != scheme_handler_factory_map_.end())
+  if (it != scheme_handler_factory_map_.end()) {
     return it->second;
+  }
 
   return nullptr;
 }
 
-void CefResourceContext::InitOnIOThread() {
+void CefIOThreadState::InitOnIOThread() {
   CEF_REQUIRE_IOT();
 
   // Add the default internal handlers.
diff --git a/src/libcef/browser/iothread_state.h b/src/libcef/browser/iothread_state.h
new file mode 100644
index 0000000..71457fd
--- /dev/null
+++ b/src/libcef/browser/iothread_state.h
@@ -0,0 +1,68 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_BROWSER_IOTHREAD_STATE_H_
+#define CEF_LIBCEF_BROWSER_IOTHREAD_STATE_H_
+#pragma once
+
+#include "include/cef_request_context.h"
+#include "include/cef_request_context_handler.h"
+#include "include/cef_scheme.h"
+
+#include "libcef/browser/request_context_handler_map.h"
+
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+struct GlobalRenderFrameHostId;
+}
+
+class GURL;
+
+// Stores state that will be accessed on the IO thread. Life span is controlled
+// by CefBrowserContext. Created on the UI thread but accessed and destroyed on
+// the IO thread. See browser_context.h for an object relationship diagram.
+class CefIOThreadState : public base::RefCountedThreadSafe<
+                             CefIOThreadState,
+                             content::BrowserThread::DeleteOnIOThread> {
+ public:
+  CefIOThreadState();
+
+  CefIOThreadState(const CefIOThreadState&) = delete;
+  CefIOThreadState& operator=(const CefIOThreadState&) = delete;
+
+  // See comments in CefRequestContextHandlerMap.
+  void AddHandler(const content::GlobalRenderFrameHostId& global_id,
+                  CefRefPtr<CefRequestContextHandler> handler);
+  void RemoveHandler(const content::GlobalRenderFrameHostId& global_id);
+  CefRefPtr<CefRequestContextHandler> GetHandler(
+      const content::GlobalRenderFrameHostId& global_id,
+      bool require_frame_match) const;
+
+  // Manage scheme handler factories associated with this context.
+  void RegisterSchemeHandlerFactory(const std::string& scheme_name,
+                                    const std::string& domain_name,
+                                    CefRefPtr<CefSchemeHandlerFactory> factory);
+  void ClearSchemeHandlerFactories();
+  CefRefPtr<CefSchemeHandlerFactory> GetSchemeHandlerFactory(const GURL& url);
+
+ private:
+  friend struct content::BrowserThread::DeleteOnThread<
+      content::BrowserThread::IO>;
+  friend class base::DeleteHelper<CefIOThreadState>;
+
+  ~CefIOThreadState();
+
+  void InitOnIOThread();
+
+  // Map IDs to CefRequestContextHandler objects.
+  CefRequestContextHandlerMap handler_map_;
+
+  // Map (scheme, domain) to factories.
+  using SchemeHandlerFactoryMap = std::map<std::pair<std::string, std::string>,
+                                           CefRefPtr<CefSchemeHandlerFactory>>;
+  SchemeHandlerFactoryMap scheme_handler_factory_map_;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_IOTHREAD_STATE_H_
diff --git a/src/libcef/browser/javascript_dialog_manager.cc b/src/libcef/browser/javascript_dialog_manager.cc
index 4e4c791..1debbf1 100644
--- a/src/libcef/browser/javascript_dialog_manager.cc
+++ b/src/libcef/browser/javascript_dialog_manager.cc
@@ -7,13 +7,13 @@
 
 #include <utility>
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/browser_host_base.h"
 #include "libcef/browser/thread_util.h"
 
-#include "base/bind.h"
+#include "base/functional/bind.h"
+#include "base/functional/callback_helpers.h"
 #include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
-#include "components/url_formatter/elide_url.h"
+#include "components/javascript_dialogs/tab_modal_dialog_manager.h"
 
 namespace {
 
@@ -47,12 +47,12 @@
     }
   }
 
-  CallbackType Disconnect() WARN_UNUSED_RESULT { return std::move(callback_); }
+  [[nodiscard]] CallbackType Disconnect() { return std::move(callback_); }
 
  private:
   static void CancelNow(CallbackType callback) {
     CEF_REQUIRE_UIT();
-    std::move(callback).Run(false, base::string16());
+    std::move(callback).Run(false, std::u16string());
   }
 
   CallbackType callback_;
@@ -60,21 +60,26 @@
   IMPLEMENT_REFCOUNTING(CefJSDialogCallbackImpl);
 };
 
+javascript_dialogs::TabModalDialogManager* GetTabModalDialogManager(
+    content::WebContents* web_contents) {
+  return javascript_dialogs::TabModalDialogManager::FromWebContents(
+      web_contents);
+}
+
 }  // namespace
 
 CefJavaScriptDialogManager::CefJavaScriptDialogManager(
-    CefBrowserHostImpl* browser,
-    std::unique_ptr<CefJavaScriptDialogRunner> runner)
-    : browser_(browser),
-      runner_(std::move(runner)),
-      dialog_running_(false),
-      weak_ptr_factory_(this) {}
+    CefBrowserHostBase* browser)
+    : browser_(browser), weak_ptr_factory_(this) {}
 
 CefJavaScriptDialogManager::~CefJavaScriptDialogManager() {}
 
 void CefJavaScriptDialogManager::Destroy() {
-  if (runner_.get()) {
-    runner_.reset(nullptr);
+  if (handler_) {
+    CancelDialogs(nullptr, false);
+  }
+  if (runner_) {
+    runner_.reset();
   }
 }
 
@@ -82,17 +87,23 @@
     content::WebContents* web_contents,
     content::RenderFrameHost* render_frame_host,
     content::JavaScriptDialogType message_type,
-    const base::string16& message_text,
-    const base::string16& default_prompt_text,
+    const std::u16string& message_text,
+    const std::u16string& default_prompt_text,
     DialogClosedCallback callback,
     bool* did_suppress_message) {
+  *did_suppress_message = false;
+
   const GURL& origin_url = render_frame_host->GetLastCommittedURL();
 
-  CefRefPtr<CefClient> client = browser_->GetClient();
-  if (client.get()) {
-    CefRefPtr<CefJSDialogHandler> handler = client->GetJSDialogHandler();
-    if (handler.get()) {
-      *did_suppress_message = false;
+  // Always call DialogClosed().
+  callback =
+      base::BindOnce(&CefJavaScriptDialogManager::DialogClosed,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback));
+
+  if (auto client = browser_->GetClient()) {
+    if (auto handler = client->GetJSDialogHandler()) {
+      // If the dialog is handled this will be cleared in DialogClosed().
+      handler_ = handler;
 
       CefRefPtr<CefJSDialogCallbackImpl> callbackPtr(
           new CefJSDialogCallbackImpl(std::move(callback)));
@@ -110,32 +121,40 @@
 
       // |callback| may be null if the user executed it despite returning false.
       callback = callbackPtr->Disconnect();
-      if (callback.is_null() || *did_suppress_message)
+      if (callback.is_null()) {
+        LOG(WARNING)
+            << "OnJSDialog should return true when executing the callback";
         return;
+      }
+
+      if (*did_suppress_message) {
+        // Call OnResetDialogState but don't execute |callback|.
+        CancelDialogs(web_contents, /*reset_state=*/true);
+        return;
+      }
+
+      handler_ = nullptr;
     }
   }
 
-  *did_suppress_message = false;
+  DCHECK(!handler_);
 
-  if (!runner_.get() || dialog_running_) {
-    // Suppress the dialog if there is no platform runner or if the dialog is
-    // currently running.
-    if (!runner_.get())
-      LOG(WARNING) << "No javascript dialog runner available for this platform";
-    *did_suppress_message = true;
+  if (InitializeRunner()) {
+    runner_->Run(browser_, message_type, origin_url, message_text,
+                 default_prompt_text, std::move(callback));
     return;
   }
 
-  dialog_running_ = true;
+  if (!CanUseChromeDialogs()) {
+    // Dismiss the dialog.
+    std::move(callback).Run(false, std::u16string());
+    return;
+  }
 
-  const base::string16& display_url =
-      url_formatter::FormatUrlForSecurityDisplay(origin_url);
-
-  DCHECK(!callback.is_null());
-  runner_->Run(
-      browser_, message_type, display_url, message_text, default_prompt_text,
-      base::BindOnce(&CefJavaScriptDialogManager::DialogClosed,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  auto manager = GetTabModalDialogManager(web_contents);
+  manager->RunJavaScriptDialog(web_contents, render_frame_host, message_type,
+                               message_text, default_prompt_text,
+                               std::move(callback), did_suppress_message);
 }
 
 void CefJavaScriptDialogManager::RunBeforeUnloadDialog(
@@ -143,91 +162,150 @@
     content::RenderFrameHost* render_frame_host,
     bool is_reload,
     DialogClosedCallback callback) {
-  if (browser_->destruction_state() >=
-      CefBrowserHostImpl::DESTRUCTION_STATE_ACCEPTED) {
+  if (browser_->WillBeDestroyed()) {
     // Currently destroying the browser. Accept the unload without showing
     // the prompt.
-    std::move(callback).Run(true, base::string16());
+    std::move(callback).Run(true, std::u16string());
     return;
   }
 
-  const base::string16& message_text =
-      base::ASCIIToUTF16("Is it OK to leave/reload this page?");
+  const std::u16string& message_text = u"Is it OK to leave/reload this page?";
 
-  CefRefPtr<CefClient> client = browser_->GetClient();
-  if (client.get()) {
-    CefRefPtr<CefJSDialogHandler> handler = client->GetJSDialogHandler();
-    if (handler.get()) {
+  // Always call DialogClosed().
+  callback =
+      base::BindOnce(&CefJavaScriptDialogManager::DialogClosed,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback));
+
+  if (auto client = browser_->GetClient()) {
+    if (auto handler = client->GetJSDialogHandler()) {
+      // If the dialog is handled this will be cleared in DialogClosed().
+      handler_ = handler;
+
       CefRefPtr<CefJSDialogCallbackImpl> callbackPtr(
           new CefJSDialogCallbackImpl(std::move(callback)));
 
       // Execute the user callback.
       bool handled = handler->OnBeforeUnloadDialog(
           browser_, message_text, is_reload, callbackPtr.get());
-      if (handled)
+      if (handled) {
         return;
+      }
 
       // |callback| may be null if the user executed it despite returning false.
       callback = callbackPtr->Disconnect();
-      if (callback.is_null())
+      if (callback.is_null()) {
+        LOG(WARNING) << "OnBeforeUnloadDialog should return true when "
+                        "executing the callback";
         return;
+      }
+
+      handler_ = nullptr;
     }
   }
 
-  if (!runner_.get() || dialog_running_) {
-    if (!runner_.get())
-      LOG(WARNING) << "No javascript dialog runner available for this platform";
-    // Suppress the dialog if there is no platform runner or if the dialog is
-    // currently running.
-    std::move(callback).Run(true, base::string16());
+  DCHECK(!handler_);
+
+  if (InitializeRunner()) {
+    runner_->Run(browser_, content::JAVASCRIPT_DIALOG_TYPE_CONFIRM,
+                 /*origin_url=*/GURL(), message_text,
+                 /*default_prompt_text=*/std::u16string(), std::move(callback));
     return;
   }
 
-  dialog_running_ = true;
+  if (!CanUseChromeDialogs()) {
+    // Accept the unload without showing the prompt.
+    std::move(callback).Run(true, std::u16string());
+    return;
+  }
 
-  DCHECK(!callback.is_null());
-  runner_->Run(
-      browser_, content::JAVASCRIPT_DIALOG_TYPE_CONFIRM,
-      base::string16(),  // display_url
-      message_text,
-      base::string16(),  // default_prompt_text
-      base::BindOnce(&CefJavaScriptDialogManager::DialogClosed,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  auto manager = GetTabModalDialogManager(web_contents);
+  manager->RunBeforeUnloadDialog(web_contents, render_frame_host, is_reload,
+                                 std::move(callback));
+}
+
+bool CefJavaScriptDialogManager::HandleJavaScriptDialog(
+    content::WebContents* web_contents,
+    bool accept,
+    const std::u16string* prompt_override) {
+  if (handler_) {
+    DialogClosed(base::NullCallback(), accept,
+                 prompt_override ? *prompt_override : std::u16string());
+    return true;
+  }
+
+  if (runner_) {
+    runner_->Handle(accept, prompt_override);
+    return true;
+  }
+
+  if (!CanUseChromeDialogs()) {
+    return true;
+  }
+
+  auto manager = GetTabModalDialogManager(web_contents);
+  return manager->HandleJavaScriptDialog(web_contents, accept, prompt_override);
 }
 
 void CefJavaScriptDialogManager::CancelDialogs(
     content::WebContents* web_contents,
     bool reset_state) {
-  CefRefPtr<CefClient> client = browser_->GetClient();
-  if (client.get()) {
-    CefRefPtr<CefJSDialogHandler> handler = client->GetJSDialogHandler();
-    if (handler.get()) {
-      // Execute the user callback.
-      handler->OnResetDialogState(browser_);
+  if (handler_) {
+    if (reset_state) {
+      handler_->OnResetDialogState(browser_);
     }
+    handler_ = nullptr;
+    return;
   }
 
-  if (runner_.get() && dialog_running_) {
+  if (runner_) {
     runner_->Cancel();
-    dialog_running_ = false;
+    return;
   }
+
+  // Null when called from DialogClosed() or Destroy().
+  if (!web_contents) {
+    return;
+  }
+
+  if (!CanUseChromeDialogs()) {
+    return;
+  }
+
+  auto manager = GetTabModalDialogManager(web_contents);
+  manager->CancelDialogs(web_contents, reset_state);
 }
 
 void CefJavaScriptDialogManager::DialogClosed(
     DialogClosedCallback callback,
     bool success,
-    const base::string16& user_input) {
-  CefRefPtr<CefClient> client = browser_->GetClient();
-  if (client.get()) {
-    CefRefPtr<CefJSDialogHandler> handler = client->GetJSDialogHandler();
-    if (handler.get())
-      handler->OnDialogClosed(browser_);
+    const std::u16string& user_input) {
+  if (handler_) {
+    handler_->OnDialogClosed(browser_);
+    // Call OnResetDialogState.
+    CancelDialogs(/*web_contents=*/nullptr, /*reset_state=*/true);
   }
 
-  DCHECK(runner_.get());
-  DCHECK(dialog_running_);
-
-  dialog_running_ = false;
-
-  std::move(callback).Run(success, user_input);
+  // Null when called from HandleJavaScriptDialog().
+  if (!callback.is_null()) {
+    std::move(callback).Run(success, user_input);
+  }
 }
+
+bool CefJavaScriptDialogManager::InitializeRunner() {
+  if (!runner_initialized_) {
+    runner_ = browser_->platform_delegate()->CreateJavaScriptDialogRunner();
+    runner_initialized_ = true;
+  }
+  return !!runner_.get();
+}
+
+bool CefJavaScriptDialogManager::CanUseChromeDialogs() const {
+  if (browser_->IsWindowless() &&
+      browser_->GetWindowHandle() == kNullWindowHandle) {
+    LOG(ERROR) << "Default dialog implementation requires a parent window "
+                  "handle; canceling the JS dialog";
+    return false;
+  }
+
+  return true;
+}
\ No newline at end of file
diff --git a/src/libcef/browser/javascript_dialog_manager.h b/src/libcef/browser/javascript_dialog_manager.h
index 227cb52..241b4c1 100644
--- a/src/libcef/browser/javascript_dialog_manager.h
+++ b/src/libcef/browser/javascript_dialog_manager.h
@@ -7,21 +7,26 @@
 #define CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_MANAGER_H_
 #pragma once
 
+#include <memory>
 #include <string>
 
+#include "include/cef_jsdialog_handler.h"
 #include "libcef/browser/javascript_dialog_runner.h"
 
-#include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
 #include "content/public/browser/javascript_dialog_manager.h"
 
-class CefBrowserHostImpl;
+class CefBrowserHostBase;
 
 class CefJavaScriptDialogManager : public content::JavaScriptDialogManager {
  public:
   // |runner| may be NULL if the platform doesn't implement dialogs.
-  CefJavaScriptDialogManager(CefBrowserHostImpl* browser,
-                             std::unique_ptr<CefJavaScriptDialogRunner> runner);
+  explicit CefJavaScriptDialogManager(CefBrowserHostBase* browser);
+
+  CefJavaScriptDialogManager(const CefJavaScriptDialogManager&) = delete;
+  CefJavaScriptDialogManager& operator=(const CefJavaScriptDialogManager&) =
+      delete;
+
   ~CefJavaScriptDialogManager() override;
 
   // Delete the runner to free any platform constructs.
@@ -31,14 +36,17 @@
   void RunJavaScriptDialog(content::WebContents* web_contents,
                            content::RenderFrameHost* render_frame_host,
                            content::JavaScriptDialogType message_type,
-                           const base::string16& message_text,
-                           const base::string16& default_prompt_text,
+                           const std::u16string& message_text,
+                           const std::u16string& default_prompt_text,
                            DialogClosedCallback callback,
                            bool* did_suppress_message) override;
   void RunBeforeUnloadDialog(content::WebContents* web_contents,
                              content::RenderFrameHost* render_frame_host,
                              bool is_reload,
                              DialogClosedCallback callback) override;
+  bool HandleJavaScriptDialog(content::WebContents* web_contents,
+                              bool accept,
+                              const std::u16string* prompt_override) override;
   void CancelDialogs(content::WebContents* web_contents,
                      bool reset_state) override;
 
@@ -46,20 +54,22 @@
   // Method executed by the callback passed to CefJavaScriptDialogRunner::Run.
   void DialogClosed(DialogClosedCallback callback,
                     bool success,
-                    const base::string16& user_input);
+                    const std::u16string& user_input);
 
-  // CefBrowserHostImpl pointer is guaranteed to outlive this object.
-  CefBrowserHostImpl* browser_;
+  bool InitializeRunner();
+
+  bool CanUseChromeDialogs() const;
+
+  // CefBrowserHostBase pointer is guaranteed to outlive this object.
+  CefBrowserHostBase* const browser_;
+
+  CefRefPtr<CefJSDialogHandler> handler_;
 
   std::unique_ptr<CefJavaScriptDialogRunner> runner_;
-
-  // True if a dialog is currently running.
-  bool dialog_running_;
+  bool runner_initialized_ = false;
 
   // Must be the last member.
   base::WeakPtrFactory<CefJavaScriptDialogManager> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefJavaScriptDialogManager);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_MANAGER_H_
diff --git a/src/libcef/browser/javascript_dialog_runner.h b/src/libcef/browser/javascript_dialog_runner.h
index 8d79320..bbceece 100644
--- a/src/libcef/browser/javascript_dialog_runner.h
+++ b/src/libcef/browser/javascript_dialog_runner.h
@@ -7,38 +7,40 @@
 #define CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_RUNNER_H_
 #pragma once
 
-#include "base/callback.h"
-#include "base/strings/string16.h"
+#include "content/public/browser/javascript_dialog_manager.h"
 #include "content/public/common/javascript_dialog_type.h"
 
-class CefBrowserHostImpl;
+class CefBrowserHostBase;
 
 class CefJavaScriptDialogRunner {
  public:
-  typedef base::OnceCallback<void(bool /* success */,
-                                  const base::string16& /* user_input */)>
-      DialogClosedCallback;
+  CefJavaScriptDialogRunner(const CefJavaScriptDialogRunner&) = delete;
+  CefJavaScriptDialogRunner& operator=(const CefJavaScriptDialogRunner&) =
+      delete;
+
+  using DialogClosedCallback =
+      content::JavaScriptDialogManager::DialogClosedCallback;
 
   // Run the dialog. Execute |callback| on completion.
-  virtual void Run(CefBrowserHostImpl* browser,
+  virtual void Run(CefBrowserHostBase* browser,
                    content::JavaScriptDialogType message_type,
-                   const base::string16& display_url,
-                   const base::string16& message_text,
-                   const base::string16& default_prompt_text,
+                   const GURL& origin_url,
+                   const std::u16string& message_text,
+                   const std::u16string& default_prompt_text,
                    DialogClosedCallback callback) = 0;
 
+  // Dismiss the dialog with the specified results.
+  virtual void Handle(bool accept, const std::u16string* prompt_override) = 0;
+
   // Cancel a dialog mid-flight.
   virtual void Cancel() = 0;
 
  protected:
-  // Allow deletion via scoped_ptr only.
+  // Allow deletion via std::unique_ptr only.
   friend std::default_delete<CefJavaScriptDialogRunner>;
 
-  CefJavaScriptDialogRunner() {}
-  virtual ~CefJavaScriptDialogRunner() {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefJavaScriptDialogRunner);
+  CefJavaScriptDialogRunner() = default;
+  virtual ~CefJavaScriptDialogRunner() = default;
 };
 
 #endif  // CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_RUNNER_H_
diff --git a/src/libcef/browser/main_runner.cc b/src/libcef/browser/main_runner.cc
new file mode 100644
index 0000000..80c9626
--- /dev/null
+++ b/src/libcef/browser/main_runner.cc
@@ -0,0 +1,545 @@
+// Copyright 2020 The Chromium Embedded Framework Authors.
+// Portions copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/browser/main_runner.h"
+
+#include "libcef/browser/browser_message_loop.h"
+#include "libcef/browser/thread_util.h"
+#include "libcef/common/alloy/alloy_main_runner_delegate.h"
+#include "libcef/common/cef_switches.h"
+#include "libcef/common/chrome/chrome_main_runner_delegate.h"
+#include "libcef/features/runtime.h"
+
+#include "base/at_exit.h"
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/debug/debugger.h"
+#include "base/run_loop.h"
+#include "base/sequence_checker.h"
+#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "components/crash/core/app/crash_switches.h"
+#include "content/app/content_main_runner_impl.h"
+#include "content/browser/scheduler/browser_task_executor.h"
+#include "content/public/app/content_main.h"
+#include "content/public/app/content_main_runner.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/common/content_switches.h"
+#include "third_party/crashpad/crashpad/handler/handler_main.h"
+
+#if BUILDFLAG(IS_WIN)
+#include <Objbase.h>
+#include <windows.h>
+#include "content/public/app/sandbox_helper_win.h"
+#include "sandbox/win/src/sandbox_types.h"
+#endif
+
+namespace {
+
+enum class RuntimeType {
+  UNINITIALIZED,
+  ALLOY,
+  CHROME,
+};
+RuntimeType g_runtime_type = RuntimeType::UNINITIALIZED;
+
+std::unique_ptr<CefMainRunnerDelegate> MakeDelegate(
+    RuntimeType type,
+    CefMainRunnerHandler* runner,
+    CefSettings* settings,
+    CefRefPtr<CefApp> application) {
+  if (type == RuntimeType::ALLOY) {
+    g_runtime_type = RuntimeType::ALLOY;
+    return std::make_unique<AlloyMainRunnerDelegate>(runner, settings,
+                                                     application);
+  } else {
+    g_runtime_type = RuntimeType::CHROME;
+    return std::make_unique<ChromeMainRunnerDelegate>(runner, settings,
+                                                      application);
+  }
+}
+
+// Based on components/crash/core/app/run_as_crashpad_handler_win.cc
+// Remove the "--type=crashpad-handler" command-line flag that will otherwise
+// confuse the crashpad handler.
+// Chrome uses an embedded crashpad handler on Windows only and imports this
+// function via the existing "run_as_crashpad_handler" target defined in
+// components/crash/core/app/BUILD.gn. CEF uses an embedded handler on all
+// platforms so we define the function here instead of using the existing
+// target (because we can't use that target on macOS).
+int RunAsCrashpadHandler(const base::CommandLine& command_line) {
+  base::CommandLine::StringVector argv = command_line.argv();
+  const base::CommandLine::StringType process_type =
+      FILE_PATH_LITERAL("--type=");
+  argv.erase(
+      std::remove_if(argv.begin(), argv.end(),
+                     [&process_type](const base::CommandLine::StringType& str) {
+                       return base::StartsWith(str, process_type,
+                                               base::CompareCase::SENSITIVE) ||
+                              (!str.empty() && str[0] == L'/');
+                     }),
+      argv.end());
+
+#if BUILDFLAG(IS_POSIX)
+  // HandlerMain on POSIX uses the system version of getopt_long which expects
+  // the first argument to be the program name.
+  argv.insert(argv.begin(), command_line.GetProgram().value());
+#endif
+
+  std::unique_ptr<char*[]> argv_as_utf8(new char*[argv.size() + 1]);
+  std::vector<std::string> storage;
+  storage.reserve(argv.size());
+  for (size_t i = 0; i < argv.size(); ++i) {
+#if BUILDFLAG(IS_WIN)
+    storage.push_back(base::WideToUTF8(argv[i]));
+#else
+    storage.push_back(argv[i]);
+#endif
+    argv_as_utf8[i] = &storage[i][0];
+  }
+  argv_as_utf8[argv.size()] = nullptr;
+  argv.clear();
+  return crashpad::HandlerMain(static_cast<int>(storage.size()),
+                               argv_as_utf8.get(), nullptr);
+}
+
+}  // namespace
+
+// Used to run the UI on a separate thread.
+class CefUIThread : public base::PlatformThread::Delegate {
+ public:
+  CefUIThread(CefMainRunner* runner, base::OnceClosure setup_callback)
+      : runner_(runner), setup_callback_(std::move(setup_callback)) {}
+  ~CefUIThread() override { Stop(); }
+
+  void Start() {
+    base::AutoLock lock(thread_lock_);
+    bool success = base::PlatformThread::CreateWithType(
+        0, this, &thread_, base::ThreadType::kDefault);
+    if (!success) {
+      LOG(FATAL) << "failed to UI create thread";
+    }
+  }
+
+  void Stop() {
+    base::AutoLock lock(thread_lock_);
+
+    if (!stopping_) {
+      stopping_ = true;
+      CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefMainRunner::QuitMessageLoop,
+                                            base::Unretained(runner_)));
+    }
+
+    // Can't join if the |thread_| is either already gone or is non-joinable.
+    if (thread_.is_null()) {
+      return;
+    }
+
+    base::PlatformThread::Join(thread_);
+    thread_ = base::PlatformThreadHandle();
+
+    stopping_ = false;
+  }
+
+  bool WaitUntilThreadStarted() const {
+    DCHECK(owning_sequence_checker_.CalledOnValidSequence());
+    start_event_.Wait();
+    return true;
+  }
+
+  void InitializeBrowserRunner(
+      content::MainFunctionParams main_function_params) {
+    // Use our own browser process runner.
+    browser_runner_ = content::BrowserMainRunner::Create();
+
+    // Initialize browser process state. Uses the current thread's message loop.
+    int exit_code =
+        browser_runner_->Initialize(std::move(main_function_params));
+    CHECK_EQ(exit_code, -1);
+  }
+
+ protected:
+  void ThreadMain() override {
+    base::PlatformThread::SetName("CefUIThread");
+
+#if BUILDFLAG(IS_WIN)
+    // Initializes the COM library on the current thread.
+    CoInitialize(nullptr);
+#endif
+
+    start_event_.Signal();
+
+    std::move(setup_callback_).Run();
+
+    runner_->RunMessageLoop();
+
+    browser_runner_->Shutdown();
+    browser_runner_.reset();
+
+    content::BrowserTaskExecutor::Shutdown();
+
+    // Run exit callbacks on the UI thread to avoid sequence check failures.
+    base::AtExitManager::ProcessCallbacksNow();
+
+#if BUILDFLAG(IS_WIN)
+    // Closes the COM library on the current thread. CoInitialize must
+    // be balanced by a corresponding call to CoUninitialize.
+    CoUninitialize();
+#endif
+  }
+
+  CefMainRunner* const runner_;
+  base::OnceClosure setup_callback_;
+
+  std::unique_ptr<content::BrowserMainRunner> browser_runner_;
+
+  bool stopping_ = false;
+
+  // The thread's handle.
+  base::PlatformThreadHandle thread_;
+  mutable base::Lock thread_lock_;  // Protects |thread_|.
+
+  mutable base::WaitableEvent start_event_;
+
+  // This class is not thread-safe, use this to verify access from the owning
+  // sequence of the Thread.
+  base::SequenceChecker owning_sequence_checker_;
+};
+
+CefMainRunner::CefMainRunner(bool multi_threaded_message_loop,
+                             bool external_message_pump)
+    : multi_threaded_message_loop_(multi_threaded_message_loop),
+      external_message_pump_(external_message_pump) {}
+
+CefMainRunner::~CefMainRunner() = default;
+
+bool CefMainRunner::Initialize(CefSettings* settings,
+                               CefRefPtr<CefApp> application,
+                               const CefMainArgs& args,
+                               void* windows_sandbox_info,
+                               bool* initialized,
+                               base::OnceClosure context_initialized) {
+  DCHECK(!main_delegate_);
+  main_delegate_ = MakeDelegate(
+      settings->chrome_runtime ? RuntimeType::CHROME : RuntimeType::ALLOY, this,
+      settings, application);
+
+  const int exit_code =
+      ContentMainInitialize(args, windows_sandbox_info, &settings->no_sandbox);
+  if (exit_code >= 0) {
+    DCHECK(false) << "ContentMainInitialize failed";
+    return false;
+  }
+
+  if (!ContentMainRun(initialized, std::move(context_initialized))) {
+    DCHECK(false) << "ContentMainRun failed";
+    return false;
+  }
+
+  return true;
+}
+
+void CefMainRunner::Shutdown(base::OnceClosure shutdown_on_ui_thread,
+                             base::OnceClosure finalize_shutdown) {
+  if (multi_threaded_message_loop_) {
+    // Events that will be used to signal when shutdown is complete. Start in
+    // non-signaled mode so that the event will block.
+    base::WaitableEvent uithread_shutdown_event(
+        base::WaitableEvent::ResetPolicy::AUTOMATIC,
+        base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+    // Finish shutdown on the UI thread.
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(&CefMainRunner::FinishShutdownOnUIThread,
+                       base::Unretained(this), std::move(shutdown_on_ui_thread),
+                       &uithread_shutdown_event));
+
+    /// Block until UI thread shutdown is complete.
+    uithread_shutdown_event.Wait();
+
+    FinalizeShutdown(std::move(finalize_shutdown));
+  } else {
+    // Finish shutdown on the current thread, which should be the UI thread.
+    FinishShutdownOnUIThread(std::move(shutdown_on_ui_thread), nullptr);
+
+    FinalizeShutdown(std::move(finalize_shutdown));
+  }
+}
+
+void CefMainRunner::RunMessageLoop() {
+  base::RunLoop run_loop;
+
+  DCHECK(quit_callback_.is_null());
+  quit_callback_ = run_loop.QuitClosure();
+
+  main_delegate_->BeforeMainMessageLoopRun(&run_loop);
+
+  // Blocks until QuitMessageLoop() is called.
+  run_loop.Run();
+}
+
+void CefMainRunner::QuitMessageLoop() {
+  if (!quit_callback_.is_null()) {
+    if (main_delegate_->HandleMainMessageLoopQuit()) {
+      return;
+    }
+    std::move(quit_callback_).Run();
+  }
+}
+
+// static
+int CefMainRunner::RunAsHelperProcess(const CefMainArgs& args,
+                                      CefRefPtr<CefApp> application,
+                                      void* windows_sandbox_info) {
+  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
+#if BUILDFLAG(IS_WIN)
+  command_line.ParseFromString(::GetCommandLineW());
+#else
+  command_line.InitFromArgv(args.argc, args.argv);
+#endif
+
+  // Wait for the debugger as early in process initialization as possible.
+  if (command_line.HasSwitch(switches::kWaitForDebugger)) {
+    base::debug::WaitForDebugger(60, true);
+  }
+
+  // If no process type is specified then it represents the browser process and
+  // we do nothing.
+  const std::string& process_type =
+      command_line.GetSwitchValueASCII(switches::kProcessType);
+  if (process_type.empty()) {
+    return -1;
+  }
+
+  auto runtime_type = command_line.HasSwitch(switches::kEnableChromeRuntime)
+                          ? RuntimeType::CHROME
+                          : RuntimeType::ALLOY;
+  auto main_delegate = MakeDelegate(runtime_type, /*runner=*/nullptr,
+                                    /*settings=*/nullptr, application);
+  main_delegate->BeforeExecuteProcess(args);
+
+  int result;
+
+  if (process_type == crash_reporter::switches::kCrashpadHandler) {
+    result = RunAsCrashpadHandler(command_line);
+    main_delegate->AfterExecuteProcess();
+    return result;
+  }
+
+  // Execute the secondary process.
+  content::ContentMainParams main_params(
+      main_delegate->GetContentMainDelegate());
+#if BUILDFLAG(IS_WIN)
+  sandbox::SandboxInterfaceInfo sandbox_info = {nullptr};
+  if (windows_sandbox_info == nullptr) {
+    content::InitializeSandboxInfo(&sandbox_info);
+    windows_sandbox_info = &sandbox_info;
+  }
+
+  main_params.instance = args.instance;
+  main_params.sandbox_info =
+      static_cast<sandbox::SandboxInterfaceInfo*>(windows_sandbox_info);
+#else
+  main_params.argc = args.argc;
+  main_params.argv = const_cast<const char**>(args.argv);
+#endif
+  result = content::ContentMain(std::move(main_params));
+
+  main_delegate->AfterExecuteProcess();
+
+  return result;
+}
+
+int CefMainRunner::ContentMainInitialize(const CefMainArgs& args,
+                                         void* windows_sandbox_info,
+                                         int* no_sandbox) {
+  main_delegate_->BeforeMainThreadInitialize(args);
+
+  // Initialize the content runner.
+  main_runner_ = content::ContentMainRunner::Create();
+  content::ContentMainParams main_params(
+      main_delegate_->GetContentMainDelegate());
+
+#if BUILDFLAG(IS_WIN)
+  sandbox::SandboxInterfaceInfo sandbox_info = {nullptr};
+  if (windows_sandbox_info == nullptr) {
+    windows_sandbox_info = &sandbox_info;
+    *no_sandbox = true;
+  }
+
+  main_params.instance = args.instance;
+  main_params.sandbox_info =
+      static_cast<sandbox::SandboxInterfaceInfo*>(windows_sandbox_info);
+#else
+  main_params.argc = args.argc;
+  main_params.argv = const_cast<const char**>(args.argv);
+#endif
+
+  return content::ContentMainInitialize(std::move(main_params),
+                                        main_runner_.get());
+}
+
+bool CefMainRunner::ContentMainRun(bool* initialized,
+                                   base::OnceClosure context_initialized) {
+  main_delegate_->BeforeMainThreadRun(multi_threaded_message_loop_);
+
+  if (multi_threaded_message_loop_) {
+    // Detach the CommandLine from the main thread so that it can be
+    // attached and modified from the UI thread going forward.
+    base::CommandLine::ForCurrentProcess()->DetachFromCurrentSequence();
+
+    base::WaitableEvent uithread_startup_event(
+        base::WaitableEvent::ResetPolicy::AUTOMATIC,
+        base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+    if (!CreateUIThread(base::BindOnce(
+            [](CefMainRunner* runner, base::WaitableEvent* event) {
+              runner->main_delegate_->BeforeUIThreadInitialize();
+              content::ContentMainRun(runner->main_runner_.get());
+              event->Signal();
+            },
+            base::Unretained(this),
+            base::Unretained(&uithread_startup_event)))) {
+      return false;
+    }
+
+    *initialized = true;
+
+    // We need to wait until content::ContentMainRun has finished.
+    uithread_startup_event.Wait();
+  } else {
+    *initialized = true;
+    main_delegate_->BeforeUIThreadInitialize();
+    content::ContentMainRun(main_runner_.get());
+  }
+
+  if (CEF_CURRENTLY_ON_UIT()) {
+    OnContextInitialized(std::move(context_initialized));
+  } else {
+    // Continue initialization on the UI thread.
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefMainRunner::OnContextInitialized,
+                                          base::Unretained(this),
+                                          std::move(context_initialized)));
+  }
+
+  return true;
+}
+
+void CefMainRunner::PreBrowserMain() {
+  if (external_message_pump_) {
+    InitExternalMessagePumpFactoryForUI();
+  }
+}
+
+int CefMainRunner::RunMainProcess(
+    content::MainFunctionParams main_function_params) {
+  if (!multi_threaded_message_loop_) {
+    // Use our own browser process runner.
+    browser_runner_ = content::BrowserMainRunner::Create();
+
+    // Initialize browser process state. Results in a call to
+    // AlloyBrowserMain::PreBrowserMain() which creates the UI message
+    // loop.
+    int exit_code =
+        browser_runner_->Initialize(std::move(main_function_params));
+    if (exit_code >= 0) {
+      return exit_code;
+    }
+  } else {
+    // Running on the separate UI thread.
+    DCHECK(ui_thread_);
+    ui_thread_->InitializeBrowserRunner(std::move(main_function_params));
+  }
+
+  return 0;
+}
+
+bool CefMainRunner::CreateUIThread(base::OnceClosure setup_callback) {
+  DCHECK(!ui_thread_);
+
+  ui_thread_.reset(new CefUIThread(this, std::move(setup_callback)));
+  ui_thread_->Start();
+  ui_thread_->WaitUntilThreadStarted();
+
+  if (external_message_pump_) {
+    InitExternalMessagePumpFactoryForUI();
+  }
+  return true;
+}
+
+void CefMainRunner::OnContextInitialized(
+    base::OnceClosure context_initialized) {
+  CEF_REQUIRE_UIT();
+
+  main_delegate_->AfterUIThreadInitialize();
+  std::move(context_initialized).Run();
+}
+
+void CefMainRunner::FinishShutdownOnUIThread(
+    base::OnceClosure shutdown_on_ui_thread,
+    base::WaitableEvent* uithread_shutdown_event) {
+  CEF_REQUIRE_UIT();
+
+  // Execute all pending tasks now before proceeding with shutdown. Otherwise,
+  // objects bound to tasks and released at the end of shutdown via
+  // BrowserTaskExecutor::Shutdown may attempt to access other objects that have
+  // already been destroyed (for example, if teardown results in a call to
+  // RenderProcessHostImpl::Cleanup).
+  content::BrowserTaskExecutor::RunAllPendingTasksOnThreadForTesting(
+      content::BrowserThread::UI);
+  content::BrowserTaskExecutor::RunAllPendingTasksOnThreadForTesting(
+      content::BrowserThread::IO);
+
+  static_cast<content::ContentMainRunnerImpl*>(main_runner_.get())
+      ->ShutdownOnUIThread();
+
+  std::move(shutdown_on_ui_thread).Run();
+  main_delegate_->AfterUIThreadShutdown();
+
+  if (uithread_shutdown_event) {
+    uithread_shutdown_event->Signal();
+  }
+}
+
+void CefMainRunner::FinalizeShutdown(base::OnceClosure finalize_shutdown) {
+  main_delegate_->BeforeMainThreadShutdown();
+
+  if (browser_runner_.get()) {
+    browser_runner_->Shutdown();
+    browser_runner_.reset();
+  }
+
+  if (ui_thread_.get()) {
+    // Blocks until the thread has stopped.
+    ui_thread_->Stop();
+    ui_thread_.reset();
+  }
+
+  // Shut down the content runner.
+  content::ContentMainShutdown(main_runner_.get());
+
+  main_runner_.reset();
+
+  std::move(finalize_shutdown).Run();
+  main_delegate_->AfterMainThreadShutdown();
+
+  main_delegate_.reset();
+  g_runtime_type = RuntimeType::UNINITIALIZED;
+}
+
+// From libcef/features/runtime.h:
+namespace cef {
+
+bool IsAlloyRuntimeEnabled() {
+  return g_runtime_type == RuntimeType::ALLOY;
+}
+
+bool IsChromeRuntimeEnabled() {
+  return g_runtime_type == RuntimeType::CHROME;
+}
+
+}  // namespace cef
diff --git a/src/libcef/browser/main_runner.h b/src/libcef/browser/main_runner.h
new file mode 100644
index 0000000..2ad0e6f
--- /dev/null
+++ b/src/libcef/browser/main_runner.h
@@ -0,0 +1,95 @@
+// Copyright 2020 The Chromium Embedded Framework Authors.
+// Portions copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_BROWSER_MAIN_RUNNER_H_
+#define CEF_LIBCEF_BROWSER_MAIN_RUNNER_H_
+#pragma once
+
+#include "include/cef_app.h"
+#include "libcef/common/main_runner_delegate.h"
+#include "libcef/common/main_runner_handler.h"
+
+#include "base/functional/callback.h"
+#include "content/public/browser/browser_main_runner.h"
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace content {
+class ContentMainRunner;
+}  // namespace content
+
+class CefUIThread;
+
+// Manages the main process lifespan and related objects.
+class CefMainRunner : public CefMainRunnerHandler {
+ public:
+  CefMainRunner(bool multi_threaded_message_loop, bool external_message_pump);
+
+  CefMainRunner(const CefMainRunner&) = delete;
+  CefMainRunner& operator=(const CefMainRunner&) = delete;
+
+  ~CefMainRunner();
+
+  // Called from CefContext::Initialize.
+  bool Initialize(CefSettings* settings,
+                  CefRefPtr<CefApp> application,
+                  const CefMainArgs& args,
+                  void* windows_sandbox_info,
+                  bool* initialized,
+                  base::OnceClosure context_initialized);
+
+  // Called from CefContext::Shutdown.
+  void Shutdown(base::OnceClosure shutdown_on_ui_thread,
+                base::OnceClosure finalize_shutdown);
+
+  void RunMessageLoop();
+  void QuitMessageLoop();
+
+  // Called from CefExecuteProcess.
+  static int RunAsHelperProcess(const CefMainArgs& args,
+                                CefRefPtr<CefApp> application,
+                                void* windows_sandbox_info);
+
+ private:
+  // Called from Initialize().
+  int ContentMainInitialize(const CefMainArgs& args,
+                            void* windows_sandbox_info,
+                            int* no_sandbox);
+  bool ContentMainRun(bool* initialized, base::OnceClosure context_initialized);
+
+  // CefMainRunnerHandler methods:
+  void PreBrowserMain() override;
+  int RunMainProcess(content::MainFunctionParams main_function_params) override;
+
+  // Create the UI thread when running with multi-threaded message loop mode.
+  bool CreateUIThread(base::OnceClosure setup_callback);
+
+  // Called on the UI thread after the context is initialized.
+  void OnContextInitialized(base::OnceClosure context_initialized);
+
+  // Performs shutdown actions that need to occur on the UI thread before any
+  // threads are destroyed.
+  void FinishShutdownOnUIThread(base::OnceClosure shutdown_on_ui_thread,
+                                base::WaitableEvent* uithread_shutdown_event);
+
+  // Destroys the runtime and related objects.
+  void FinalizeShutdown(base::OnceClosure finalize_shutdown);
+
+  const bool multi_threaded_message_loop_;
+  const bool external_message_pump_;
+
+  std::unique_ptr<CefMainRunnerDelegate> main_delegate_;
+  std::unique_ptr<content::ContentMainRunner> main_runner_;
+
+  std::unique_ptr<content::BrowserMainRunner> browser_runner_;
+  std::unique_ptr<CefUIThread> ui_thread_;
+
+  // Used to quit the current base::RunLoop.
+  base::OnceClosure quit_callback_;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_MAIN_RUNNER_H_
diff --git a/src/libcef/browser/media_access_query.cc b/src/libcef/browser/media_access_query.cc
new file mode 100644
index 0000000..44f5434
--- /dev/null
+++ b/src/libcef/browser/media_access_query.cc
@@ -0,0 +1,359 @@
+// Copyright 2022 The Chromium Embedded Framework 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 "libcef/browser/media_access_query.h"
+
+#include "include/cef_permission_handler.h"
+#include "libcef/browser/browser_host_base.h"
+#include "libcef/browser/media_capture_devices_dispatcher.h"
+#include "libcef/browser/media_stream_registrar.h"
+#include "libcef/common/cef_switches.h"
+
+#include "base/command_line.h"
+#include "base/functional/callback_helpers.h"
+#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
+
+namespace media_access_query {
+
+namespace {
+
+class CefMediaAccessQuery {
+ public:
+  using CallbackType = content::MediaResponseCallback;
+
+  CefMediaAccessQuery(CefBrowserHostBase* const browser,
+                      const content::MediaStreamRequest& request,
+                      CallbackType&& callback)
+      : browser_(browser), request_(request), callback_(std::move(callback)) {}
+
+  CefMediaAccessQuery(CefMediaAccessQuery&& query)
+      : browser_(query.browser_),
+        request_(query.request_),
+        callback_(std::move(query.callback_)) {}
+  CefMediaAccessQuery& operator=(CefMediaAccessQuery&& query) {
+    browser_ = query.browser_;
+    request_ = query.request_;
+    callback_ = std::move(query.callback_);
+    return *this;
+  }
+
+  CefMediaAccessQuery(const CefMediaAccessQuery&) = delete;
+  CefMediaAccessQuery& operator=(const CefMediaAccessQuery&) = delete;
+
+  bool is_null() const { return callback_.is_null(); }
+
+  uint32_t requested_permissions() const {
+    int requested_permissions = CEF_MEDIA_PERMISSION_NONE;
+    if (device_audio_requested()) {
+      requested_permissions |= CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE;
+    }
+    if (device_video_requested()) {
+      requested_permissions |= CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE;
+    }
+    if (desktop_audio_requested()) {
+      requested_permissions |= CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE;
+    }
+    if (desktop_video_requested()) {
+      requested_permissions |= CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE;
+    }
+    return requested_permissions;
+  }
+
+  [[nodiscard]] CallbackType DisconnectCallback() {
+    return std::move(callback_);
+  }
+
+  void ExecuteCallback(uint32_t allowed_permissions) {
+    CEF_REQUIRE_UIT();
+
+    blink::mojom::MediaStreamRequestResult result;
+    blink::mojom::StreamDevicesSetPtr stream_devices_set;
+
+    if (allowed_permissions == CEF_MEDIA_PERMISSION_NONE) {
+      result = blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED;
+      stream_devices_set = blink::mojom::StreamDevicesSet::New();
+    } else {
+      bool error = false;
+      if (allowed_permissions == requested_permissions()) {
+        stream_devices_set = GetRequestedMediaDevices();
+      } else {
+        stream_devices_set = GetAllowedMediaDevices(allowed_permissions, error);
+      }
+      result = error ? blink::mojom::MediaStreamRequestResult::INVALID_STATE
+                     : blink::mojom::MediaStreamRequestResult::OK;
+    }
+
+    bool has_video = false;
+    bool has_audio = false;
+    if (!stream_devices_set->stream_devices.empty()) {
+      blink::mojom::StreamDevices& devices =
+          *stream_devices_set->stream_devices[0];
+      has_video = devices.video_device.has_value();
+      has_audio = devices.audio_device.has_value();
+    }
+    auto media_stream_ui =
+        browser_->GetMediaStreamRegistrar()->MaybeCreateMediaStreamUI(
+            has_video, has_audio);
+
+    std::move(callback_).Run(*stream_devices_set, result,
+                             std::move(media_stream_ui));
+  }
+
+ private:
+  bool device_audio_requested() const {
+    return request_.audio_type ==
+           blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE;
+  }
+
+  bool device_video_requested() const {
+    return request_.video_type ==
+           blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE;
+  }
+
+  bool desktop_audio_requested() const {
+    return (request_.audio_type ==
+            blink::mojom::MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE) ||
+           (request_.audio_type ==
+            blink::mojom::MediaStreamType::DISPLAY_AUDIO_CAPTURE);
+  }
+
+  bool desktop_video_requested() const {
+    return (request_.video_type ==
+            blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE) ||
+           (request_.video_type ==
+            blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE);
+  }
+
+  blink::mojom::StreamDevicesSetPtr GetRequestedMediaDevices() const {
+    CEF_REQUIRE_UIT();
+
+    blink::MediaStreamDevices audio_devices;
+    blink::MediaStreamDevices video_devices;
+
+    if (device_audio_requested()) {
+      // Pick the desired device or fall back to the first available of the
+      // given type.
+      CefMediaCaptureDevicesDispatcher::GetInstance()->GetRequestedDevice(
+          request_.requested_audio_device_id, true, false, &audio_devices);
+    }
+
+    if (device_video_requested()) {
+      // Pick the desired device or fall back to the first available of the
+      // given type.
+      CefMediaCaptureDevicesDispatcher::GetInstance()->GetRequestedDevice(
+          request_.requested_video_device_id, false, true, &video_devices);
+    }
+
+    if (desktop_audio_requested()) {
+      audio_devices.push_back(blink::MediaStreamDevice(
+          request_.audio_type, "loopback", "System Audio"));
+    }
+
+    if (desktop_video_requested()) {
+      content::DesktopMediaID media_id;
+      if (request_.requested_video_device_id.empty()) {
+        media_id =
+            content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
+                                    -1 /* webrtc::kFullDesktopScreenId */);
+      } else {
+        media_id =
+            content::DesktopMediaID::Parse(request_.requested_video_device_id);
+      }
+      video_devices.push_back(blink::MediaStreamDevice(
+          request_.video_type, media_id.ToString(), "Screen"));
+    }
+
+    blink::mojom::StreamDevicesSetPtr stream_devices_set =
+        blink::mojom::StreamDevicesSet::New();
+    stream_devices_set->stream_devices.emplace_back(
+        blink::mojom::StreamDevices::New());
+    blink::mojom::StreamDevices& devices =
+        *stream_devices_set->stream_devices[0];
+
+    // At most one audio device and one video device can be used in a stream.
+    if (!audio_devices.empty()) {
+      devices.audio_device = audio_devices.front();
+    }
+    if (!video_devices.empty()) {
+      devices.video_device = video_devices.front();
+    }
+
+    return stream_devices_set;
+  }
+
+  blink::mojom::StreamDevicesSetPtr GetAllowedMediaDevices(
+      uint32_t allowed_permissions,
+      bool& error) {
+    error = false;
+
+    const auto req_permissions = requested_permissions();
+
+    const bool device_audio_allowed =
+        allowed_permissions & CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE;
+    const bool device_video_allowed =
+        allowed_permissions & CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE;
+    const bool desktop_audio_allowed =
+        allowed_permissions & CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE;
+    const bool desktop_video_allowed =
+        allowed_permissions & CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE;
+
+    blink::mojom::StreamDevicesSetPtr stream_devices_set;
+
+    // getDisplayMedia must always request video
+    if (desktop_video_requested() &&
+        (!desktop_video_allowed && desktop_audio_allowed)) {
+      LOG(WARNING) << "Response to getDisplayMedia is not allowed to only "
+                      "return Audio";
+      error = true;
+    } else if (!desktop_video_requested() &&
+               req_permissions != allowed_permissions) {
+      LOG(WARNING)
+          << "Response to getUserMedia must match requested permissions ("
+          << req_permissions << " vs " << allowed_permissions << ")";
+      error = true;
+    }
+
+    if (error) {
+      stream_devices_set = blink::mojom::StreamDevicesSet::New();
+    } else {
+      if (!device_audio_allowed && !desktop_audio_allowed) {
+        request_.audio_type = blink::mojom::MediaStreamType::NO_SERVICE;
+      }
+      if (!device_video_allowed && !desktop_video_allowed) {
+        request_.video_type = blink::mojom::MediaStreamType::NO_SERVICE;
+      }
+      stream_devices_set = GetRequestedMediaDevices();
+    }
+
+    return stream_devices_set;
+  }
+
+  CefRefPtr<CefBrowserHostBase> browser_;
+  content::MediaStreamRequest request_;
+  CallbackType callback_;
+};
+
+class CefMediaAccessCallbackImpl : public CefMediaAccessCallback {
+ public:
+  using CallbackType = CefMediaAccessQuery;
+
+  explicit CefMediaAccessCallbackImpl(CallbackType&& callback)
+      : callback_(std::move(callback)) {}
+
+  CefMediaAccessCallbackImpl(const CefMediaAccessCallbackImpl&) = delete;
+  CefMediaAccessCallbackImpl& operator=(const CefMediaAccessCallbackImpl&) =
+      delete;
+
+  ~CefMediaAccessCallbackImpl() override {
+    if (!callback_.is_null()) {
+      // The callback is still pending. Cancel it now.
+      if (CEF_CURRENTLY_ON_UIT()) {
+        RunNow(std::move(callback_), CEF_MEDIA_PERMISSION_NONE);
+      } else {
+        CEF_POST_TASK(
+            CEF_UIT,
+            base::BindOnce(&CefMediaAccessCallbackImpl::RunNow,
+                           std::move(callback_), CEF_MEDIA_PERMISSION_NONE));
+      }
+    }
+  }
+
+  void Continue(uint32_t allowed_permissions) override {
+    if (CEF_CURRENTLY_ON_UIT()) {
+      if (!callback_.is_null()) {
+        RunNow(std::move(callback_), allowed_permissions);
+      }
+    } else {
+      CEF_POST_TASK(CEF_UIT,
+                    base::BindOnce(&CefMediaAccessCallbackImpl::Continue, this,
+                                   allowed_permissions));
+    }
+  }
+
+  void Cancel() override { Continue(CEF_MEDIA_PERMISSION_NONE); }
+
+  [[nodiscard]] CallbackType Disconnect() { return std::move(callback_); }
+  bool IsDisconnected() const { return callback_.is_null(); }
+
+ private:
+  static void RunNow(CallbackType callback, uint32_t allowed_permissions) {
+    callback.ExecuteCallback(allowed_permissions);
+  }
+
+  CallbackType callback_;
+
+  IMPLEMENT_REFCOUNTING(CefMediaAccessCallbackImpl);
+};
+
+bool CheckCommandLinePermission() {
+  const base::CommandLine* command_line =
+      base::CommandLine::ForCurrentProcess();
+  return command_line->HasSwitch(switches::kEnableMediaStream);
+}
+
+}  // namespace
+
+bool CheckMediaAccessPermission(CefBrowserHostBase* browser,
+                                content::RenderFrameHost* render_frame_host,
+                                const GURL& security_origin,
+                                blink::mojom::MediaStreamType type) {
+  // Always allowed here. RequestMediaAccessPermission will be called.
+  return true;
+}
+
+content::MediaResponseCallback RequestMediaAccessPermission(
+    CefBrowserHostBase* browser,
+    const content::MediaStreamRequest& request,
+    content::MediaResponseCallback callback,
+    bool default_disallow) {
+  CEF_REQUIRE_UIT();
+
+  CefMediaAccessQuery query(browser, request, std::move(callback));
+
+  if (CheckCommandLinePermission()) {
+    // Allow all requested permissions.
+    query.ExecuteCallback(query.requested_permissions());
+    return base::NullCallback();
+  }
+
+  bool handled = false;
+
+  if (auto client = browser->GetClient()) {
+    if (auto handler = client->GetPermissionHandler()) {
+      const auto requested_permissions = query.requested_permissions();
+      CefRefPtr<CefMediaAccessCallbackImpl> callbackImpl(
+          new CefMediaAccessCallbackImpl(std::move(query)));
+
+      auto frame =
+          browser->GetFrameForGlobalId(content::GlobalRenderFrameHostId(
+              request.render_process_id, request.render_frame_id));
+      if (!frame) {
+        frame = browser->GetMainFrame();
+      }
+      handled = handler->OnRequestMediaAccessPermission(
+          browser, frame, request.security_origin.spec(), requested_permissions,
+          callbackImpl.get());
+      if (!handled) {
+        LOG_IF(ERROR, callbackImpl->IsDisconnected())
+            << "Should return true from OnRequestMediaAccessPermission when "
+               "executing the callback";
+        query = callbackImpl->Disconnect();
+      }
+    }
+  }
+
+  if (!query.is_null()) {
+    if (default_disallow && !handled) {
+      // Disallow access by default.
+      query.ExecuteCallback(CEF_MEDIA_PERMISSION_NONE);
+    } else {
+      // Proceed with default handling.
+      return query.DisconnectCallback();
+    }
+  }
+
+  return base::NullCallback();
+}
+
+}  // namespace media_access_query
diff --git a/src/libcef/browser/media_access_query.h b/src/libcef/browser/media_access_query.h
new file mode 100644
index 0000000..1af6c26
--- /dev/null
+++ b/src/libcef/browser/media_access_query.h
@@ -0,0 +1,37 @@
+// Copyright 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_MEDIA_ACCESS_QUERY_H_
+#define CEF_LIBCEF_BROWSER_MEDIA_ACCESS_QUERY_H_
+#pragma once
+
+#include "content/public/browser/media_stream_request.h"
+
+namespace content {
+class RenderFrameHost;
+}
+
+class CefBrowserHostBase;
+class GURL;
+
+namespace media_access_query {
+
+// Called from WebContentsDelegate::CheckMediaAccessPermission.
+bool CheckMediaAccessPermission(CefBrowserHostBase* browser,
+                                content::RenderFrameHost* render_frame_host,
+                                const GURL& security_origin,
+                                blink::mojom::MediaStreamType type);
+
+// Called from WebContentsDelegate::RequestMediaAccessPermission.
+// |callback| will be returned if the request is unhandled and
+// |default_disallow| is false.
+[[nodiscard]] content::MediaResponseCallback RequestMediaAccessPermission(
+    CefBrowserHostBase* browser,
+    const content::MediaStreamRequest& request,
+    content::MediaResponseCallback callback,
+    bool default_disallow);
+
+}  // namespace media_access_query
+
+#endif  // CEF_LIBCEF_BROWSER_MEDIA_ACCESS_QUERY_H_
diff --git a/src/libcef/browser/media_capture_devices_dispatcher.cc b/src/libcef/browser/media_capture_devices_dispatcher.cc
index cc2c75e..25d5301 100644
--- a/src/libcef/browser/media_capture_devices_dispatcher.cc
+++ b/src/libcef/browser/media_capture_devices_dispatcher.cc
@@ -18,8 +18,9 @@
 const blink::MediaStreamDevice* FindDefaultDeviceWithId(
     const blink::MediaStreamDevices& devices,
     const std::string& device_id) {
-  if (devices.empty())
+  if (devices.empty()) {
     return nullptr;
+  }
 
   blink::MediaStreamDevices::const_iterator iter = devices.begin();
   for (; iter != devices.end(); ++iter) {
@@ -82,15 +83,17 @@
     const blink::MediaStreamDevices& audio_devices = GetAudioCaptureDevices();
     const blink::MediaStreamDevice* const device =
         FindDefaultDeviceWithId(audio_devices, requested_device_id);
-    if (device)
+    if (device) {
       devices->push_back(*device);
+    }
   }
   if (video) {
     const blink::MediaStreamDevices& video_devices = GetVideoCaptureDevices();
     const blink::MediaStreamDevice* const device =
         FindDefaultDeviceWithId(video_devices, requested_device_id);
-    if (device)
+    if (device) {
       devices->push_back(*device);
+    }
   }
 }
 
diff --git a/src/libcef/browser/media_capture_devices_dispatcher.h b/src/libcef/browser/media_capture_devices_dispatcher.h
index 1104206..3082bf1 100644
--- a/src/libcef/browser/media_capture_devices_dispatcher.h
+++ b/src/libcef/browser/media_capture_devices_dispatcher.h
@@ -5,7 +5,7 @@
 #ifndef CEF_LIBCEF_BROWSER_MEDIA_CAPTURE_DEVICES_DISPATCHER_H_
 #define CEF_LIBCEF_BROWSER_MEDIA_CAPTURE_DEVICES_DISPATCHER_H_
 
-#include "base/callback.h"
+#include "base/functional/callback.h"
 #include "base/memory/singleton.h"
 #include "base/observer_list.h"
 #include "content/public/browser/media_observer.h"
diff --git a/src/libcef/browser/media_router/media_route_impl.cc b/src/libcef/browser/media_router/media_route_impl.cc
index 928381d..243f585 100644
--- a/src/libcef/browser/media_router/media_route_impl.cc
+++ b/src/libcef/browser/media_router/media_route_impl.cc
@@ -16,7 +16,7 @@
   CEF_REQUIRE_UIT();
   DCHECK(!getter.is_null());
 
-  // Will return nullptr if the BrowserContext has been destroyed.
+  // Will return nullptr if the BrowserContext has been shut down.
   return getter.Run();
 }
 
@@ -38,7 +38,11 @@
 }
 
 CefRefPtr<CefMediaSink> CefMediaRouteImpl::GetSink() {
-  return new CefMediaSinkImpl(route_.media_sink_id(), route_.media_sink_name());
+  return new CefMediaSinkImpl(
+      route_.media_sink_id(), route_.media_sink_name(),
+      route_.media_source().IsDialSource()
+          ? media_router::mojom::MediaRouteProviderId::DIAL
+          : media_router::mojom::MediaRouteProviderId::CAST);
 }
 
 void CefMediaRouteImpl::SendRouteMessage(const void* message,
@@ -66,8 +70,9 @@
   }
 
   auto browser_context = GetBrowserContext(browser_context_getter_);
-  if (!browser_context)
+  if (!browser_context) {
     return;
+  }
 
   browser_context->GetMediaRouterManager()->TerminateRoute(
       route_.media_route_id());
@@ -75,8 +80,9 @@
 
 void CefMediaRouteImpl::SendRouteMessageInternal(std::string message) {
   auto browser_context = GetBrowserContext(browser_context_getter_);
-  if (!browser_context)
+  if (!browser_context) {
     return;
+  }
 
   browser_context->GetMediaRouterManager()->SendRouteMessage(
       route_.media_route_id(), message);
diff --git a/src/libcef/browser/media_router/media_route_impl.h b/src/libcef/browser/media_router/media_route_impl.h
index 9e707c6..8ca65c7 100644
--- a/src/libcef/browser/media_router/media_route_impl.h
+++ b/src/libcef/browser/media_router/media_route_impl.h
@@ -9,7 +9,7 @@
 #include "include/cef_media_router.h"
 #include "libcef/browser/browser_context.h"
 
-#include "chrome/common/media_router/media_route.h"
+#include "components/media_router/common/media_route.h"
 
 // Implementation of the CefMediaRoute interface. Only created on the UI thread.
 class CefMediaRouteImpl : public CefMediaRoute {
@@ -17,6 +17,9 @@
   CefMediaRouteImpl(const media_router::MediaRoute& route,
                     const CefBrowserContext::Getter& browser_context_getter);
 
+  CefMediaRouteImpl(const CefMediaRouteImpl&) = delete;
+  CefMediaRouteImpl& operator=(const CefMediaRouteImpl&) = delete;
+
   // CefMediaRoute methods.
   CefString GetId() override;
   CefRefPtr<CefMediaSource> GetSource() override;
@@ -34,7 +37,6 @@
   const CefBrowserContext::Getter browser_context_getter_;
 
   IMPLEMENT_REFCOUNTING(CefMediaRouteImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefMediaRouteImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_MEDIA_ROUTER_MEDIA_ROUTE_IMPL_H_
diff --git a/src/libcef/browser/media_router/media_router_impl.cc b/src/libcef/browser/media_router/media_router_impl.cc
index 52c4f5e..af32870 100644
--- a/src/libcef/browser/media_router/media_router_impl.cc
+++ b/src/libcef/browser/media_router/media_router_impl.cc
@@ -17,7 +17,7 @@
   CEF_REQUIRE_UIT();
   DCHECK(!getter.is_null());
 
-  // Will return nullptr if the BrowserContext has been destroyed.
+  // Will return nullptr if the BrowserContext has been shut down.
   return getter.Run();
 }
 
@@ -31,16 +31,21 @@
     DCHECK(observer_);
   }
 
+  CefRegistrationImpl(const CefRegistrationImpl&) = delete;
+  CefRegistrationImpl& operator=(const CefRegistrationImpl&) = delete;
+
   ~CefRegistrationImpl() override {
     CEF_REQUIRE_UIT();
 
     // May be null if OnMediaRouterDestroyed was called.
-    if (browser_context_getter_.is_null())
+    if (browser_context_getter_.is_null()) {
       return;
+    }
 
     auto browser_context = GetBrowserContext(browser_context_getter_);
-    if (!browser_context)
+    if (!browser_context) {
       return;
+    }
 
     browser_context->GetMediaRouterManager()->RemoveObserver(this);
   }
@@ -52,8 +57,9 @@
     browser_context_getter_ = browser_context_getter;
 
     auto browser_context = GetBrowserContext(browser_context_getter_);
-    if (!browser_context)
+    if (!browser_context) {
       return;
+    }
 
     browser_context->GetMediaRouterManager()->AddObserver(this);
   }
@@ -124,7 +130,7 @@
       case blink::mojom::PresentationConnectionState::TERMINATED:
         return CEF_MRCS_TERMINATED;
     }
-    NOTREACHED();
+    DCHECK(false);
     return CEF_MRCS_UNKNOWN;
   }
 
@@ -132,38 +138,50 @@
   CefBrowserContext::Getter browser_context_getter_;
 
   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefRegistrationImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefRegistrationImpl);
 };
 
-CefMediaRouterImpl::CefMediaRouterImpl() {
-  // Verify that our enum matches Chromium's values.
-  static_assert(
-      static_cast<int>(CEF_MRCR_TOTAL_COUNT) ==
-          static_cast<int>(media_router::RouteRequestResult::TOTAL_COUNT),
-      "enum mismatch");
-}
+CefMediaRouterImpl::CefMediaRouterImpl() = default;
 
 void CefMediaRouterImpl::Initialize(
-    const CefBrowserContext::Getter& browser_context_getter) {
+    const CefBrowserContext::Getter& browser_context_getter,
+    CefRefPtr<CefCompletionCallback> callback) {
   CEF_REQUIRE_UIT();
+  DCHECK(!initialized_);
   DCHECK(!browser_context_getter.is_null());
   DCHECK(browser_context_getter_.is_null());
   browser_context_getter_ = browser_context_getter;
+
+  initialized_ = true;
+  if (!init_callbacks_.empty()) {
+    for (auto& init_callback : init_callbacks_) {
+      std::move(init_callback).Run();
+    }
+    init_callbacks_.clear();
+  }
+
+  if (callback) {
+    // Execute client callback asynchronously for consistency.
+    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefCompletionCallback::OnComplete,
+                                          callback.get()));
+  }
 }
 
 CefRefPtr<CefRegistration> CefMediaRouterImpl::AddObserver(
     CefRefPtr<CefMediaObserver> observer) {
-  if (!observer)
+  if (!observer) {
     return nullptr;
+  }
   CefRefPtr<CefRegistrationImpl> registration =
       new CefRegistrationImpl(observer);
-  InitializeRegistrationOnUIThread(registration);
+  StoreOrTriggerInitCallback(base::BindOnce(
+      &CefMediaRouterImpl::InitializeRegistrationInternal, this, registration));
   return registration.get();
 }
 
 CefRefPtr<CefMediaSource> CefMediaRouterImpl::GetSource(const CefString& urn) {
-  if (urn.empty())
+  if (urn.empty()) {
     return nullptr;
+  }
 
   // Check for a valid URL and supported Cast/DIAL schemes.
   GURL presentation_url(urn.ToString());
@@ -181,37 +199,55 @@
 }
 
 void CefMediaRouterImpl::NotifyCurrentSinks() {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT, base::BindOnce(&CefMediaRouterImpl::NotifyCurrentSinks, this));
-    return;
-  }
-
-  auto browser_context = GetBrowserContext(browser_context_getter_);
-  if (!browser_context)
-    return;
-
-  browser_context->GetMediaRouterManager()->NotifyCurrentSinks();
+  StoreOrTriggerInitCallback(
+      base::BindOnce(&CefMediaRouterImpl::NotifyCurrentSinksInternal, this));
 }
 
 void CefMediaRouterImpl::CreateRoute(
     CefRefPtr<CefMediaSource> source,
     CefRefPtr<CefMediaSink> sink,
     CefRefPtr<CefMediaRouteCreateCallback> callback) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefMediaRouterImpl::CreateRoute,
-                                          this, source, sink, callback));
+  StoreOrTriggerInitCallback(base::BindOnce(
+      &CefMediaRouterImpl::CreateRouteInternal, this, source, sink, callback));
+}
+
+void CefMediaRouterImpl::NotifyCurrentRoutes() {
+  StoreOrTriggerInitCallback(
+      base::BindOnce(&CefMediaRouterImpl::NotifyCurrentRoutesInternal, this));
+}
+
+void CefMediaRouterImpl::InitializeRegistrationInternal(
+    CefRefPtr<CefRegistrationImpl> registration) {
+  DCHECK(ValidContext());
+
+  registration->Initialize(browser_context_getter_);
+}
+
+void CefMediaRouterImpl::NotifyCurrentSinksInternal() {
+  DCHECK(ValidContext());
+
+  auto browser_context = GetBrowserContext(browser_context_getter_);
+  if (!browser_context) {
     return;
   }
 
+  browser_context->GetMediaRouterManager()->NotifyCurrentSinks();
+}
+
+void CefMediaRouterImpl::CreateRouteInternal(
+    CefRefPtr<CefMediaSource> source,
+    CefRefPtr<CefMediaSink> sink,
+    CefRefPtr<CefMediaRouteCreateCallback> callback) {
+  DCHECK(ValidContext());
+
   std::string error;
 
   auto browser_context = GetBrowserContext(browser_context_getter_);
   if (!browser_context) {
-    error = "Context has already been destroyed";
-  } else if (!source || !source->IsValid()) {
+    error = "Context is not valid";
+  } else if (!source) {
     error = "Source is empty or invalid";
-  } else if (!sink || !sink->IsValid()) {
+  } else if (!sink) {
     error = "Sink is empty or invalid";
   } else if (!sink->IsCompatibleWith(source)) {
     error = "Sink is not compatible with source";
@@ -234,47 +270,33 @@
       base::BindOnce(&CefMediaRouterImpl::CreateRouteCallback, this, callback));
 }
 
-void CefMediaRouterImpl::NotifyCurrentRoutes() {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(
-                               &CefMediaRouterImpl::NotifyCurrentRoutes, this));
-    return;
-  }
+void CefMediaRouterImpl::NotifyCurrentRoutesInternal() {
+  DCHECK(ValidContext());
 
   auto browser_context = GetBrowserContext(browser_context_getter_);
-  if (!browser_context)
-    return;
-
-  browser_context->GetMediaRouterManager()->NotifyCurrentRoutes();
-}
-
-void CefMediaRouterImpl::InitializeRegistrationOnUIThread(
-    CefRefPtr<CefRegistrationImpl> registration) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::BindOnce(&CefMediaRouterImpl::InitializeRegistrationOnUIThread,
-                       this, registration));
+  if (!browser_context) {
     return;
   }
-  registration->Initialize(browser_context_getter_);
+
+  browser_context->GetMediaRouterManager()->NotifyCurrentRoutes();
 }
 
 void CefMediaRouterImpl::CreateRouteCallback(
     CefRefPtr<CefMediaRouteCreateCallback> callback,
     const media_router::RouteRequestResult& result) {
-  CEF_REQUIRE_UIT();
+  DCHECK(ValidContext());
 
-  if (result.result_code() != media_router::RouteRequestResult::OK) {
+  if (result.result_code() != media_router::mojom::RouteRequestResultCode::OK) {
     LOG(WARNING) << "Media route creation failed: " << result.error() << " ("
                  << result.result_code() << ")";
   }
 
-  if (!callback)
+  if (!callback) {
     return;
+  }
 
   CefRefPtr<CefMediaRoute> route;
-  if (result.result_code() == media_router::RouteRequestResult::OK &&
+  if (result.result_code() == media_router::mojom::RouteRequestResultCode::OK &&
       result.route()) {
     route = new CefMediaRouteImpl(*result.route(), browser_context_getter_);
   }
@@ -284,7 +306,30 @@
       result.error(), route);
 }
 
+void CefMediaRouterImpl::StoreOrTriggerInitCallback(
+    base::OnceClosure callback) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT, base::BindOnce(&CefMediaRouterImpl::StoreOrTriggerInitCallback,
+                                this, std::move(callback)));
+    return;
+  }
+
+  if (initialized_) {
+    std::move(callback).Run();
+  } else {
+    init_callbacks_.emplace_back(std::move(callback));
+  }
+}
+
+bool CefMediaRouterImpl::ValidContext() const {
+  return CEF_CURRENTLY_ON_UIT() && initialized_;
+}
+
+// CefMediaRouter methods ------------------------------------------------------
+
 // static
-CefRefPtr<CefMediaRouter> CefMediaRouter::GetGlobalMediaRouter() {
-  return CefRequestContext::GetGlobalContext()->GetMediaRouter();
+CefRefPtr<CefMediaRouter> CefMediaRouter::GetGlobalMediaRouter(
+    CefRefPtr<CefCompletionCallback> callback) {
+  return CefRequestContext::GetGlobalContext()->GetMediaRouter(callback);
 }
diff --git a/src/libcef/browser/media_router/media_router_impl.h b/src/libcef/browser/media_router/media_router_impl.h
index 6512f35..f0aba10 100644
--- a/src/libcef/browser/media_router/media_router_impl.h
+++ b/src/libcef/browser/media_router/media_router_impl.h
@@ -9,7 +9,7 @@
 #include "include/cef_media_router.h"
 #include "libcef/browser/browser_context.h"
 
-#include "chrome/common/media_router/mojom/media_router.mojom.h"
+#include "components/media_router/common/mojom/media_router.mojom.h"
 
 class CefRegistrationImpl;
 
@@ -18,9 +18,13 @@
  public:
   CefMediaRouterImpl();
 
+  CefMediaRouterImpl(const CefMediaRouterImpl&) = delete;
+  CefMediaRouterImpl& operator=(const CefMediaRouterImpl&) = delete;
+
   // Called on the UI thread after object creation and before any other object
   // methods are executed on the UI thread.
-  void Initialize(const CefBrowserContext::Getter& browser_context_getter);
+  void Initialize(const CefBrowserContext::Getter& browser_context_getter,
+                  CefRefPtr<CefCompletionCallback> callback);
 
   // CefMediaRouter methods.
   CefRefPtr<CefRegistration> AddObserver(
@@ -33,17 +37,30 @@
   void NotifyCurrentRoutes() override;
 
  private:
-  void InitializeRegistrationOnUIThread(
+  void InitializeRegistrationInternal(
       CefRefPtr<CefRegistrationImpl> registration);
+  void NotifyCurrentSinksInternal();
+  void CreateRouteInternal(CefRefPtr<CefMediaSource> source,
+                           CefRefPtr<CefMediaSink> sink,
+                           CefRefPtr<CefMediaRouteCreateCallback> callback);
+  void NotifyCurrentRoutesInternal();
 
   void CreateRouteCallback(CefRefPtr<CefMediaRouteCreateCallback> callback,
                            const media_router::RouteRequestResult& result);
 
+  // If the context is fully initialized execute |callback|, otherwise
+  // store it until the context is fully initialized.
+  void StoreOrTriggerInitCallback(base::OnceClosure callback);
+
+  bool ValidContext() const;
+
   // Only accessed on the UI thread. Will be non-null after Initialize().
   CefBrowserContext::Getter browser_context_getter_;
 
+  bool initialized_ = false;
+  std::vector<base::OnceClosure> init_callbacks_;
+
   IMPLEMENT_REFCOUNTING(CefMediaRouterImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefMediaRouterImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_MEDIA_ROUTER_MEDIA_ROUTER_IMPL_H_
diff --git a/src/libcef/browser/media_router/media_router_manager.cc b/src/libcef/browser/media_router/media_router_manager.cc
index d364751..562e979 100644
--- a/src/libcef/browser/media_router/media_router_manager.cc
+++ b/src/libcef/browser/media_router/media_router_manager.cc
@@ -7,10 +7,10 @@
 #include "libcef/browser/browser_context.h"
 #include "libcef/browser/thread_util.h"
 
-#include "chrome/browser/media/router/media_router_factory.h"
-#include "chrome/browser/media/router/media_routes_observer.h"
-#include "chrome/browser/media/router/route_message_observer.h"
-#include "chrome/browser/media/router/route_message_util.h"
+#include "components/media_router/browser/media_router_factory.h"
+#include "components/media_router/browser/media_routes_observer.h"
+#include "components/media_router/browser/presentation_connection_message_observer.h"
+#include "components/media_router/browser/route_message_util.h"
 
 namespace {
 
@@ -25,29 +25,37 @@
       : media_router::MediaRoutesObserver(manager->GetMediaRouter()),
         manager_(manager) {}
 
-  void OnRoutesUpdated(const std::vector<media_router::MediaRoute>& routes,
-                       const std::vector<media_router::MediaRoute::Id>&
-                           joinable_route_ids) override {
+  CefMediaRoutesObserver(const CefMediaRoutesObserver&) = delete;
+  CefMediaRoutesObserver& operator=(const CefMediaRoutesObserver&) = delete;
+
+  void OnRoutesUpdated(
+      const std::vector<media_router::MediaRoute>& routes) override {
     manager_->routes_ = routes;
     manager_->NotifyCurrentRoutes();
   }
 
  private:
   CefMediaRouterManager* const manager_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefMediaRoutesObserver);
 };
 
 // Used to receive messages if PresentationConnection is not supported.
-class CefRouteMessageObserver : public media_router::RouteMessageObserver {
+class CefPresentationConnectionMessageObserver
+    : public media_router::PresentationConnectionMessageObserver {
  public:
-  CefRouteMessageObserver(CefMediaRouterManager* manager,
-                          const media_router::MediaRoute& route)
-      : media_router::RouteMessageObserver(manager->GetMediaRouter(),
-                                           route.media_route_id()),
+  CefPresentationConnectionMessageObserver(
+      CefMediaRouterManager* manager,
+      const media_router::MediaRoute& route)
+      : media_router::PresentationConnectionMessageObserver(
+            manager->GetMediaRouter(),
+            route.media_route_id()),
         manager_(manager),
         route_(route) {}
 
+  CefPresentationConnectionMessageObserver(
+      const CefPresentationConnectionMessageObserver&) = delete;
+  CefPresentationConnectionMessageObserver& operator=(
+      const CefPresentationConnectionMessageObserver&) = delete;
+
   void OnMessagesReceived(
       CefMediaRouterManager::MediaMessageVector messages) override {
     manager_->OnMessagesReceived(route_, messages);
@@ -56,8 +64,6 @@
  private:
   CefMediaRouterManager* const manager_;
   const media_router::MediaRoute route_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefRouteMessageObserver);
 };
 
 // Used for messaging and route status notifications with Cast.
@@ -72,6 +78,10 @@
         connection_receiver_(this, std::move(connections->connection_receiver)),
         connection_remote_(std::move(connections->connection_remote)) {}
 
+  CefPresentationConnection(const CefPresentationConnection&) = delete;
+  CefPresentationConnection& operator=(const CefPresentationConnection&) =
+      delete;
+
   void OnMessage(
       blink::mojom::PresentationConnectionMessagePtr message) override {
     CefMediaRouterManager::MediaMessageVector messages;
@@ -117,11 +127,10 @@
 
   // Used to send messages to the MRP.
   mojo::Remote<blink::mojom::PresentationConnection> connection_remote_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefPresentationConnection);
 };
 
-CefMediaRouterManager::CefMediaRouterManager(CefBrowserContext* browser_context)
+CefMediaRouterManager::CefMediaRouterManager(
+    content::BrowserContext* browser_context)
     : browser_context_(browser_context),
       query_result_manager_(GetMediaRouter()),
       weak_ptr_factory_(this) {
@@ -180,10 +189,10 @@
     const url::Origin& origin,
     CreateRouteResultCallback callback) {
   GetMediaRouter()->CreateRoute(
-      source_id, sink_id, origin, nullptr /* web_contents */,
+      source_id, sink_id, origin, /*web_contents=*/nullptr,
       base::BindOnce(&CefMediaRouterManager::OnCreateRoute,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
-      base::TimeDelta::FromMilliseconds(kTimeoutMs), false /* incognito */);
+      base::Milliseconds(kTimeoutMs));
 }
 
 void CefMediaRouterManager::SendRouteMessage(
@@ -204,7 +213,7 @@
   GetMediaRouter()->TerminateRoute(route_id);
 }
 
-void CefMediaRouterManager::OnResultsUpdated(const MediaSinkVector& sinks) {
+void CefMediaRouterManager::OnSinksUpdated(const MediaSinkVector& sinks) {
   sinks_ = sinks;
   NotifyCurrentSinks();
 }
@@ -265,7 +274,7 @@
   } else {
     // Fallback if PresentationConnection is not supported.
     state->message_observer_ =
-        std::make_unique<CefRouteMessageObserver>(this, route);
+        std::make_unique<CefPresentationConnectionMessageObserver>(this, route);
     state->state_subscription_ =
         GetMediaRouter()->AddPresentationConnectionStateChangedCallback(
             route_id,
@@ -279,14 +288,16 @@
 CefMediaRouterManager::RouteState* CefMediaRouterManager::GetRouteState(
     const media_router::MediaRoute::Id& route_id) {
   const auto it = route_state_map_.find(route_id);
-  if (it != route_state_map_.end())
+  if (it != route_state_map_.end()) {
     return it->second.get();
+  }
   return nullptr;
 }
 
 void CefMediaRouterManager::RemoveRouteState(
     const media_router::MediaRoute::Id& route_id) {
   auto it = route_state_map_.find(route_id);
-  if (it != route_state_map_.end())
+  if (it != route_state_map_.end()) {
     route_state_map_.erase(it);
+  }
 }
diff --git a/src/libcef/browser/media_router/media_router_manager.h b/src/libcef/browser/media_router/media_router_manager.h
index 28b8f86..10f831d 100644
--- a/src/libcef/browser/media_router/media_router_manager.h
+++ b/src/libcef/browser/media_router/media_router_manager.h
@@ -7,23 +7,25 @@
 #pragma once
 
 #include "include/cef_media_router.h"
-#include "libcef/browser/browser_context.h"
 
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "chrome/browser/media/router/media_router.h"
 #include "chrome/browser/ui/media_router/query_result_manager.h"
-#include "chrome/common/media_router/mojom/media_router.mojom.h"
+#include "components/media_router/browser/media_router.h"
+#include "components/media_router/common/mojom/media_router.mojom.h"
 
-class CefBrowserContext;
+namespace content {
+class BrowserContext;
+}
+
 class CefMediaRoutesObserver;
 class CefPresentationConnection;
-class CefRouteMessageObserver;
+class CefPresentationConnectionMessageObserver;
 
 // Manages CEF usage of MediaRouter. Owned by CefBrowserContext and only
 // accessed on the UI thread.
 class CefMediaRouterManager
-    : public media_router::QueryResultManager::Observer {
+    : public media_router::MediaSinkWithCastModesObserver {
  public:
   using MediaRouteVector = std::vector<media_router::MediaRoute>;
   using MediaSinkVector = std::vector<media_router::MediaSinkWithCastModes>;
@@ -46,7 +48,11 @@
     ~Observer() override {}
   };
 
-  explicit CefMediaRouterManager(CefBrowserContext* browser_context);
+  explicit CefMediaRouterManager(content::BrowserContext* browser_context);
+
+  CefMediaRouterManager(const CefMediaRouterManager&) = delete;
+  CefMediaRouterManager& operator=(const CefMediaRouterManager&) = delete;
+
   ~CefMediaRouterManager() override;
 
   // |observer| must outlive this object or be removed.
@@ -68,13 +74,13 @@
                         const std::string& message);
   void TerminateRoute(const media_router::MediaRoute::Id& route_id);
 
-  // QueryResultManager::Observer methods.
-  void OnResultsUpdated(const MediaSinkVector& sinks) override;
+  // MediaSinkWithCastModesObserver methods.
+  void OnSinksUpdated(const MediaSinkVector& sinks) override;
 
  private:
   friend class CefMediaRoutesObserver;
   friend class CefPresentationConnection;
-  friend class CefRouteMessageObserver;
+  friend class CefPresentationConnectionMessageObserver;
 
   // Do not keep a reference to the object returned by this method.
   media_router::MediaRouter* GetMediaRouter() const;
@@ -93,9 +99,8 @@
     std::unique_ptr<CefPresentationConnection> presentation_connection_;
 
     // Used if there is no RoutePresentationConnectionPtr.
-    std::unique_ptr<CefRouteMessageObserver> message_observer_;
-    std::unique_ptr<media_router::PresentationConnectionStateSubscription>
-        state_subscription_;
+    std::unique_ptr<CefPresentationConnectionMessageObserver> message_observer_;
+    base::CallbackListSubscription state_subscription_;
   };
   void CreateRouteState(
       const media_router::MediaRoute& route,
@@ -103,7 +108,7 @@
   RouteState* GetRouteState(const media_router::MediaRoute::Id& route_id);
   void RemoveRouteState(const media_router::MediaRoute::Id& route_id);
 
-  CefBrowserContext* const browser_context_;
+  content::BrowserContext* const browser_context_;
 
   base::ObserverList<Observer> observers_;
 
@@ -118,8 +123,6 @@
   RouteStateMap route_state_map_;
 
   base::WeakPtrFactory<CefMediaRouterManager> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefMediaRouterManager);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_MEDIA_ROUTER_MEDIA_ROUTER_MANAGER_H_
diff --git a/src/libcef/browser/media_router/media_sink_impl.cc b/src/libcef/browser/media_router/media_sink_impl.cc
index ea62d6c..b66ad20 100644
--- a/src/libcef/browser/media_router/media_sink_impl.cc
+++ b/src/libcef/browser/media_router/media_sink_impl.cc
@@ -8,9 +8,10 @@
 
 #include "base/strings/string_number_conversions.h"
 #include "chrome/browser/media/router/discovery/dial/dial_media_sink_service_impl.h"
+#include "chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl.h"
 #include "chrome/browser/media/router/providers/cast/dual_media_sink_service.h"
-#include "chrome/common/media_router/discovery/media_sink_internal.h"
-#include "chrome/common/media_router/discovery/media_sink_service_base.h"
+#include "components/media_router/common/discovery/media_sink_internal.h"
+#include "components/media_router/common/discovery/media_sink_service_base.h"
 
 namespace {
 
@@ -34,8 +35,9 @@
 
   for (auto service : services) {
     sink_internal = service->GetSinkById(sink_id);
-    if (sink_internal)
+    if (sink_internal) {
       break;
+    }
   }
 
   if (sink_internal) {
@@ -85,26 +87,23 @@
 CefMediaSinkImpl::CefMediaSinkImpl(const media_router::MediaSink& sink)
     : sink_(sink) {}
 
-CefMediaSinkImpl::CefMediaSinkImpl(const media_router::MediaSink::Id& sink_id,
-                                   const std::string& sink_name)
-    : sink_(sink_id, sink_name, media_router::SinkIconType::GENERIC) {}
+CefMediaSinkImpl::CefMediaSinkImpl(
+    const media_router::MediaSink::Id& sink_id,
+    const std::string& sink_name,
+    media_router::mojom::MediaRouteProviderId provider_id)
+    : sink_(sink_id,
+            sink_name,
+            media_router::SinkIconType::GENERIC,
+            provider_id) {}
 
 CefString CefMediaSinkImpl::GetId() {
   return sink_.id();
 }
 
-bool CefMediaSinkImpl::IsValid() {
-  return true;
-}
-
 CefString CefMediaSinkImpl::GetName() {
   return sink_.name();
 }
 
-CefString CefMediaSinkImpl::GetDescription() {
-  return sink_.description().value_or("");
-}
-
 CefMediaSink::IconType CefMediaSinkImpl::GetIconType() {
   // Verify that our enum matches Chromium's values.
   static_assert(static_cast<int>(CEF_MSIT_TOTAL_COUNT) ==
@@ -120,19 +119,21 @@
 }
 
 bool CefMediaSinkImpl::IsCastSink() {
-  return sink_.provider_id() == media_router::CAST;
+  return sink_.provider_id() == media_router::mojom::MediaRouteProviderId::CAST;
 }
 
 bool CefMediaSinkImpl::IsDialSink() {
-  return sink_.provider_id() == media_router::DIAL;
+  return sink_.provider_id() == media_router::mojom::MediaRouteProviderId::DIAL;
 }
 
 bool CefMediaSinkImpl::IsCompatibleWith(CefRefPtr<CefMediaSource> source) {
   if (source) {
-    if (IsCastSink())
+    if (IsCastSink()) {
       return source->IsCastSource();
-    if (IsDialSink())
+    }
+    if (IsDialSink()) {
       return source->IsDialSource();
+    }
   }
   return false;
 }
diff --git a/src/libcef/browser/media_router/media_sink_impl.h b/src/libcef/browser/media_router/media_sink_impl.h
index bac3cae..20dbdef 100644
--- a/src/libcef/browser/media_router/media_sink_impl.h
+++ b/src/libcef/browser/media_router/media_sink_impl.h
@@ -8,20 +8,22 @@
 
 #include "include/cef_media_router.h"
 
-#include "chrome/common/media_router/media_sink.h"
+#include "components/media_router/common/media_sink.h"
 
 // Implementation of the CefMediaSink interface. May be created on any thread.
 class CefMediaSinkImpl : public CefMediaSink {
  public:
   explicit CefMediaSinkImpl(const media_router::MediaSink& sink);
   CefMediaSinkImpl(const media_router::MediaSink::Id& sink_id,
-                   const std::string& sink_name);
+                   const std::string& sink_name,
+                   media_router::mojom::MediaRouteProviderId provider_id);
+
+  CefMediaSinkImpl(const CefMediaSinkImpl&) = delete;
+  CefMediaSinkImpl& operator=(const CefMediaSinkImpl&) = delete;
 
   // CefMediaSink methods.
   CefString GetId() override;
-  bool IsValid() override;
   CefString GetName() override;
-  CefString GetDescription() override;
   IconType GetIconType() override;
   void GetDeviceInfo(
       CefRefPtr<CefMediaSinkDeviceInfoCallback> callback) override;
@@ -36,7 +38,6 @@
   const media_router::MediaSink sink_;
 
   IMPLEMENT_REFCOUNTING(CefMediaSinkImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefMediaSinkImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_MEDIA_ROUTER_MEDIA_SINK_IMPL_H_
diff --git a/src/libcef/browser/media_router/media_source_impl.cc b/src/libcef/browser/media_router/media_source_impl.cc
index 2b722c7..e8e18a4 100644
--- a/src/libcef/browser/media_router/media_source_impl.cc
+++ b/src/libcef/browser/media_router/media_source_impl.cc
@@ -15,10 +15,6 @@
   return source_.id();
 }
 
-bool CefMediaSourceImpl::IsValid() {
-  return source_.IsValid();
-}
-
 bool CefMediaSourceImpl::IsCastSource() {
   return !IsDialSource();
 }
diff --git a/src/libcef/browser/media_router/media_source_impl.h b/src/libcef/browser/media_router/media_source_impl.h
index 8e50158..0c9664d 100644
--- a/src/libcef/browser/media_router/media_source_impl.h
+++ b/src/libcef/browser/media_router/media_source_impl.h
@@ -8,7 +8,7 @@
 
 #include "include/cef_media_router.h"
 
-#include "chrome/common/media_router/media_source.h"
+#include "components/media_router/common/media_source.h"
 
 // Implementation of the CefMediaSource interface. May be created on any thread.
 class CefMediaSourceImpl : public CefMediaSource {
@@ -16,9 +16,11 @@
   explicit CefMediaSourceImpl(const media_router::MediaSource::Id& source_id);
   explicit CefMediaSourceImpl(const GURL& presentation_url);
 
+  CefMediaSourceImpl(const CefMediaSourceImpl&) = delete;
+  CefMediaSourceImpl& operator=(const CefMediaSourceImpl&) = delete;
+
   // CefMediaSource methods.
   CefString GetId() override;
-  bool IsValid() override;
   bool IsCastSource() override;
   bool IsDialSource() override;
 
@@ -29,7 +31,6 @@
   const media_router::MediaSource source_;
 
   IMPLEMENT_REFCOUNTING(CefMediaSourceImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefMediaSourceImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_MEDIA_ROUTER_MEDIA_SOURCE_IMPL_H_
diff --git a/src/libcef/browser/media_stream_registrar.cc b/src/libcef/browser/media_stream_registrar.cc
new file mode 100644
index 0000000..bdf3dd9
--- /dev/null
+++ b/src/libcef/browser/media_stream_registrar.cc
@@ -0,0 +1,110 @@
+// Copyright 2022 The Chromium Embedded Framework 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 "libcef/browser/media_stream_registrar.h"
+
+#include "libcef/browser/browser_host_base.h"
+#include "libcef/browser/thread_util.h"
+
+class CefMediaStreamUI : public content::MediaStreamUI {
+ public:
+  CefMediaStreamUI(base::WeakPtr<CefMediaStreamRegistrar> registrar,
+                   bool has_video,
+                   bool has_audio)
+      : registrar_(registrar), has_video_(has_video), has_audio_(has_audio) {}
+
+  ~CefMediaStreamUI() override {
+    if (registrar_) {
+      registrar_->UnregisterMediaStream(label_);
+    }
+  }
+
+  CefMediaStreamUI(const CefMediaStreamUI&) = delete;
+  CefMediaStreamUI& operator=(const CefMediaStreamUI&) = delete;
+
+  gfx::NativeViewId OnStarted(
+      base::RepeatingClosure stop,
+      SourceCallback source,
+      const std::string& label,
+      std::vector<content::DesktopMediaID> screen_capture_ids,
+      StateChangeCallback state_change) override {
+    if (registrar_) {
+      label_ = label;
+      registrar_->RegisterMediaStream(label, has_video_, has_audio_);
+    }
+    return 0;
+  }
+
+  void OnDeviceStoppedForSourceChange(
+      const std::string& label,
+      const content::DesktopMediaID& old_media_id,
+      const content::DesktopMediaID& new_media_id) override {}
+
+  void OnDeviceStopped(const std::string& label,
+                       const content::DesktopMediaID& media_id) override {}
+
+ private:
+  base::WeakPtr<CefMediaStreamRegistrar> registrar_;
+  const bool has_video_;
+  const bool has_audio_;
+  std::string label_;
+};
+
+CefMediaStreamRegistrar::CefMediaStreamRegistrar(CefBrowserHostBase* browser)
+    : browser_(browser) {}
+
+std::unique_ptr<content::MediaStreamUI>
+CefMediaStreamRegistrar::MaybeCreateMediaStreamUI(bool has_video,
+                                                  bool has_audio) {
+  // Only create the object if the callback will be executed.
+  if (auto client = browser_->GetClient()) {
+    if (auto handler = client->GetDisplayHandler()) {
+      return std::make_unique<CefMediaStreamUI>(weak_ptr_factory_.GetWeakPtr(),
+                                                has_video, has_audio);
+    }
+  }
+  return nullptr;
+}
+
+void CefMediaStreamRegistrar::RegisterMediaStream(const std::string& label,
+                                                  bool video,
+                                                  bool audio) {
+  CEF_REQUIRE_UIT();
+  MediaStreamInfo info = {video, audio};
+  registered_streams_.insert(std::make_pair(label, info));
+  NotifyMediaStreamChange();
+}
+
+void CefMediaStreamRegistrar::UnregisterMediaStream(const std::string& label) {
+  CEF_REQUIRE_UIT();
+  registered_streams_.erase(label);
+  NotifyMediaStreamChange();
+}
+
+void CefMediaStreamRegistrar::NotifyMediaStreamChange() {
+  bool video = false;
+  bool audio = false;
+  for (const auto& media_stream : registered_streams_) {
+    const auto& info = media_stream.second;
+    if (!video) {
+      video = info.video;
+    }
+    if (!audio) {
+      audio = info.audio;
+    }
+  }
+
+  if (audio == last_notified_info_.audio &&
+      video == last_notified_info_.video) {
+    return;
+  }
+
+  last_notified_info_ = {video, audio};
+
+  if (auto client = browser_->GetClient()) {
+    if (auto handler = client->GetDisplayHandler()) {
+      handler->OnMediaAccessChange(browser_, video, audio);
+    }
+  }
+}
diff --git a/src/libcef/browser/media_stream_registrar.h b/src/libcef/browser/media_stream_registrar.h
new file mode 100644
index 0000000..c6fc375
--- /dev/null
+++ b/src/libcef/browser/media_stream_registrar.h
@@ -0,0 +1,56 @@
+// Copyright 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_MEDIA_STREAM_REGISTRAR_H_
+#define CEF_LIBCEF_BROWSER_MEDIA_STREAM_REGISTRAR_H_
+#pragma once
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include "base/memory/weak_ptr.h"
+#include "content/public/browser/media_stream_request.h"
+
+class CefBrowserHostBase;
+class CefMediaStreamUI;
+
+class CefMediaStreamRegistrar {
+ public:
+  explicit CefMediaStreamRegistrar(CefBrowserHostBase* browser);
+
+  CefMediaStreamRegistrar(const CefMediaStreamRegistrar&) = delete;
+  CefMediaStreamRegistrar& operator=(const CefMediaStreamRegistrar&) = delete;
+
+  std::unique_ptr<content::MediaStreamUI> MaybeCreateMediaStreamUI(
+      bool has_video,
+      bool has_audio);
+
+ private:
+  friend class CefMediaStreamUI;
+
+  // Called from CefMediaStreamUI.
+  void RegisterMediaStream(const std::string& label, bool video, bool audio);
+  void UnregisterMediaStream(const std::string& label);
+
+  void NotifyMediaStreamChange();
+
+  // Guaranteed to outlive this object.
+  CefBrowserHostBase* const browser_;
+
+  struct MediaStreamInfo {
+    bool video;
+    bool audio;
+  };
+
+  // Current in use media streams.
+  std::map<std::string, MediaStreamInfo> registered_streams_;
+
+  // Last notified media stream info.
+  MediaStreamInfo last_notified_info_{};
+
+  base::WeakPtrFactory<CefMediaStreamRegistrar> weak_ptr_factory_{this};
+};
+
+#endif  // CEF_LIBCEF_BROWSER_MEDIA_STREAM_REGISTRAR_H_
diff --git a/src/libcef/browser/menu_manager.cc b/src/libcef/browser/menu_manager.cc
index 8599ede..ccc4fc0 100644
--- a/src/libcef/browser/menu_manager.cc
+++ b/src/libcef/browser/menu_manager.cc
@@ -4,27 +4,28 @@
 
 #include "libcef/browser/menu_manager.h"
 
+#include <tuple>
 #include <utility>
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 #include "libcef/browser/context_menu_params_impl.h"
 #include "libcef/browser/menu_runner.h"
 #include "libcef/browser/thread_util.h"
-#include "libcef/common/content_client.h"
+#include "libcef/common/app_manager.h"
 
-#include "base/compiler_specific.h"
 #include "base/logging.h"
 #include "cef/grit/cef_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_widget_host_view.h"
+#include "third_party/blink/public/mojom/context_menu/context_menu.mojom.h"
 
 namespace {
 
 CefString GetLabel(int message_id) {
-  base::string16 label =
-      CefContentClient::Get()->GetLocalizedString(message_id);
+  std::u16string label =
+      CefAppManager::Get()->GetContentClient()->GetLocalizedString(message_id);
   DCHECK(!label.empty());
   return label;
 }
@@ -34,21 +35,25 @@
 
 class CefRunContextMenuCallbackImpl : public CefRunContextMenuCallback {
  public:
-  typedef base::Callback<void(int, cef_event_flags_t)> Callback;
+  using Callback = base::OnceCallback<void(int, cef_event_flags_t)>;
 
-  explicit CefRunContextMenuCallbackImpl(const Callback& callback)
-      : callback_(callback) {}
+  explicit CefRunContextMenuCallbackImpl(Callback callback)
+      : callback_(std::move(callback)) {}
+
+  CefRunContextMenuCallbackImpl(const CefRunContextMenuCallbackImpl&) = delete;
+  CefRunContextMenuCallbackImpl& operator=(
+      const CefRunContextMenuCallbackImpl&) = delete;
 
   ~CefRunContextMenuCallbackImpl() {
     if (!callback_.is_null()) {
       // The callback is still pending. Cancel it now.
       if (CEF_CURRENTLY_ON_UIT()) {
-        RunNow(callback_, kInvalidCommandId, kEmptyEventFlags);
+        RunNow(std::move(callback_), kInvalidCommandId, kEmptyEventFlags);
       } else {
-        CEF_POST_TASK(
-            CEF_UIT,
-            base::Bind(&CefRunContextMenuCallbackImpl::RunNow, callback_,
-                       kInvalidCommandId, kEmptyEventFlags));
+        CEF_POST_TASK(CEF_UIT,
+                      base::BindOnce(&CefRunContextMenuCallbackImpl::RunNow,
+                                     std::move(callback_), kInvalidCommandId,
+                                     kEmptyEventFlags));
       }
     }
   }
@@ -56,13 +61,13 @@
   void Continue(int command_id, cef_event_flags_t event_flags) override {
     if (CEF_CURRENTLY_ON_UIT()) {
       if (!callback_.is_null()) {
-        RunNow(callback_, command_id, event_flags);
+        RunNow(std::move(callback_), command_id, event_flags);
         callback_.Reset();
       }
     } else {
       CEF_POST_TASK(CEF_UIT,
-                    base::Bind(&CefRunContextMenuCallbackImpl::Continue, this,
-                               command_id, event_flags));
+                    base::BindOnce(&CefRunContextMenuCallbackImpl::Continue,
+                                   this, command_id, event_flags));
     }
   }
 
@@ -71,22 +76,21 @@
   void Disconnect() { callback_.Reset(); }
 
  private:
-  static void RunNow(const Callback& callback,
+  static void RunNow(Callback callback,
                      int command_id,
                      cef_event_flags_t event_flags) {
     CEF_REQUIRE_UIT();
-    callback.Run(command_id, event_flags);
+    std::move(callback).Run(command_id, event_flags);
   }
 
   Callback callback_;
 
   IMPLEMENT_REFCOUNTING(CefRunContextMenuCallbackImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefRunContextMenuCallbackImpl);
 };
 
 }  // namespace
 
-CefMenuManager::CefMenuManager(CefBrowserHostImpl* browser,
+CefMenuManager::CefMenuManager(AlloyBrowserHostImpl* browser,
                                std::unique_ptr<CefMenuRunner> runner)
     : content::WebContentsObserver(browser->web_contents()),
       browser_(browser),
@@ -105,13 +109,15 @@
 
 void CefMenuManager::Destroy() {
   CancelContextMenu();
-  if (runner_)
+  if (runner_) {
     runner_.reset(nullptr);
+  }
 }
 
 bool CefMenuManager::IsShowingContextMenu() {
-  if (!web_contents())
+  if (!web_contents()) {
     return false;
+  }
   return web_contents()->IsShowingContextMenu();
 }
 
@@ -124,8 +130,9 @@
   // the second mouse event arrives. In this case, |HandleContextMenu()| will
   // get called multiple times - if so, don't create another context menu.
   // TODO(asvitkine): Fix the renderer so that it doesn't do this.
-  if (IsShowingContextMenu())
+  if (IsShowingContextMenu()) {
     return true;
+  }
 
   params_ = params;
   model_->Clear();
@@ -153,8 +160,8 @@
       if (model_->GetCount() > 0) {
         CefRefPtr<CefRunContextMenuCallbackImpl> callbackImpl(
             new CefRunContextMenuCallbackImpl(
-                base::Bind(&CefMenuManager::ExecuteCommandCallback,
-                           weak_ptr_factory_.GetWeakPtr())));
+                base::BindOnce(&CefMenuManager::ExecuteCommandCallback,
+                               weak_ptr_factory_.GetWeakPtr())));
 
         // This reference will be cleared when the callback is executed or
         // the callback object is deleted.
@@ -172,7 +179,7 @@
       }
 
       // Do not keep references to the parameters in the callback.
-      paramsPtr->Detach(nullptr);
+      std::ignore = paramsPtr->Detach(nullptr);
       DCHECK(paramsPtr->HasOneRef());
       DCHECK(model_->VerifyRefCount());
 
@@ -184,17 +191,25 @@
     }
   }
 
-  if (custom_menu || !runner_)
+  if (custom_menu) {
     return true;
-  return runner_->RunContextMenu(browser_, model_.get(), params_);
+  }
+
+  if (!runner_ || !runner_->RunContextMenu(browser_, model_.get(), params_)) {
+    LOG(ERROR) << "Default context menu implementation is not available; "
+                  "canceling the menu";
+    return false;
+  }
+  return true;
 }
 
 void CefMenuManager::CancelContextMenu() {
   if (IsShowingContextMenu()) {
-    if (custom_menu_callback_)
+    if (custom_menu_callback_) {
       custom_menu_callback_->Cancel();
-    else if (runner_)
+    } else if (runner_) {
       runner_->CancelContextMenu();
+    }
   }
 }
 
@@ -214,11 +229,12 @@
           event_flags);
 
       // Do not keep references to the parameters in the callback.
-      paramsPtr->Detach(nullptr);
+      std::ignore = paramsPtr->Detach(nullptr);
       DCHECK(paramsPtr->HasOneRef());
 
-      if (handled)
+      if (handled) {
         return;
+      }
     }
   }
 
@@ -228,15 +244,18 @@
 
 void CefMenuManager::MenuWillShow(CefRefPtr<CefMenuModelImpl> source) {
   // May be called for sub-menus as well.
-  if (source.get() != model_.get())
+  if (source.get() != model_.get()) {
     return;
+  }
 
-  if (!web_contents())
+  if (!web_contents()) {
     return;
+  }
 
   // May be called multiple times.
-  if (IsShowingContextMenu())
+  if (IsShowingContextMenu()) {
     return;
+  }
 
   // Notify the host before showing the context menu.
   web_contents()->SetShowingContextMenu(true);
@@ -244,11 +263,13 @@
 
 void CefMenuManager::MenuClosed(CefRefPtr<CefMenuModelImpl> source) {
   // May be called for sub-menus as well.
-  if (source.get() != model_.get())
+  if (source.get() != model_.get()) {
     return;
+  }
 
-  if (!web_contents())
+  if (!web_contents()) {
     return;
+  }
 
   DCHECK(IsShowingContextMenu());
 
@@ -263,13 +284,14 @@
 
   // Notify the host after closing the context menu.
   web_contents()->SetShowingContextMenu(false);
-  web_contents()->NotifyContextMenuClosed(params_.custom_context);
+  web_contents()->NotifyContextMenuClosed(params_.link_followed);
 }
 
 bool CefMenuManager::FormatLabel(CefRefPtr<CefMenuModelImpl> source,
-                                 base::string16& label) {
-  if (!runner_)
+                                 std::u16string& label) {
+  if (!runner_) {
     return false;
+  }
   return runner_->FormatLabel(label);
 }
 
@@ -277,8 +299,9 @@
                                             cef_event_flags_t event_flags) {
   DCHECK(IsShowingContextMenu());
   DCHECK(custom_menu_callback_);
-  if (command_id != kInvalidCommandId)
+  if (command_id != kInvalidCommandId) {
     ExecuteCommand(model_, command_id, event_flags);
+  }
   MenuClosed(model_);
   custom_menu_callback_ = nullptr;
 }
@@ -286,12 +309,12 @@
 void CefMenuManager::CreateDefaultModel() {
   if (!params_.custom_items.empty()) {
     // Custom menu items originating from the renderer process. For example,
-    // plugin placeholder menu items or Flash menu items.
-    for (size_t i = 0; i < params_.custom_items.size(); ++i) {
-      content::MenuItem menu_item = params_.custom_items[i];
-      menu_item.action += MENU_ID_CUSTOM_FIRST;
-      DCHECK_LE(static_cast<int>(menu_item.action), MENU_ID_CUSTOM_LAST);
-      model_->AddMenuItem(menu_item);
+    // plugin placeholder menu items.
+    for (auto& item : params_.custom_items) {
+      auto new_item = item->Clone();
+      new_item->action += MENU_ID_CUSTOM_FIRST;
+      DCHECK_LE(static_cast<int>(new_item->action), MENU_ID_CUSTOM_LAST);
+      model_->AddMenuItem(*new_item);
     }
     return;
   }
@@ -310,20 +333,27 @@
     model_->AddItem(MENU_ID_SELECT_ALL,
                     GetLabel(IDS_CONTENT_CONTEXT_SELECTALL));
 
-    if (!(params_.edit_flags & CM_EDITFLAG_CAN_UNDO))
+    if (!(params_.edit_flags & CM_EDITFLAG_CAN_UNDO)) {
       model_->SetEnabled(MENU_ID_UNDO, false);
-    if (!(params_.edit_flags & CM_EDITFLAG_CAN_REDO))
+    }
+    if (!(params_.edit_flags & CM_EDITFLAG_CAN_REDO)) {
       model_->SetEnabled(MENU_ID_REDO, false);
-    if (!(params_.edit_flags & CM_EDITFLAG_CAN_CUT))
+    }
+    if (!(params_.edit_flags & CM_EDITFLAG_CAN_CUT)) {
       model_->SetEnabled(MENU_ID_CUT, false);
-    if (!(params_.edit_flags & CM_EDITFLAG_CAN_COPY))
+    }
+    if (!(params_.edit_flags & CM_EDITFLAG_CAN_COPY)) {
       model_->SetEnabled(MENU_ID_COPY, false);
-    if (!(params_.edit_flags & CM_EDITFLAG_CAN_PASTE))
+    }
+    if (!(params_.edit_flags & CM_EDITFLAG_CAN_PASTE)) {
       model_->SetEnabled(MENU_ID_PASTE, false);
-    if (!(params_.edit_flags & CM_EDITFLAG_CAN_DELETE))
+    }
+    if (!(params_.edit_flags & CM_EDITFLAG_CAN_DELETE)) {
       model_->SetEnabled(MENU_ID_DELETE, false);
-    if (!(params_.edit_flags & CM_EDITFLAG_CAN_SELECT_ALL))
+    }
+    if (!(params_.edit_flags & CM_EDITFLAG_CAN_SELECT_ALL)) {
       model_->SetEnabled(MENU_ID_SELECT_ALL, false);
+    }
 
     if (!params_.misspelled_word.empty()) {
       // Always add a separator before the list of dictionary suggestions or
@@ -336,7 +366,7 @@
                                MENU_ID_SPELLCHECK_SUGGESTION_LAST;
              ++i) {
           model_->AddItem(MENU_ID_SPELLCHECK_SUGGESTION_0 + static_cast<int>(i),
-                          params_.dictionary_suggestions[i].c_str());
+                          params_.dictionary_suggestions[i]);
         }
 
         // When there are dictionary suggestions add a separator before "Add to
@@ -364,10 +394,12 @@
     model_->AddItem(MENU_ID_VIEW_SOURCE,
                     GetLabel(IDS_CONTENT_CONTEXT_VIEWPAGESOURCE));
 
-    if (!browser_->CanGoBack())
+    if (!browser_->CanGoBack()) {
       model_->SetEnabled(MENU_ID_BACK, false);
-    if (!browser_->CanGoForward())
+    }
+    if (!browser_->CanGoForward()) {
       model_->SetEnabled(MENU_ID_FORWARD, false);
+    }
   }
 }
 
@@ -375,7 +407,7 @@
   if (IsCustomContextMenuCommand(command_id)) {
     if (web_contents()) {
       web_contents()->ExecuteCustomContextMenuCommand(
-          command_id - MENU_ID_CUSTOM_FIRST, params_.custom_context);
+          command_id - MENU_ID_CUSTOM_FIRST, params_.link_followed);
     }
     return;
   }
@@ -457,16 +489,18 @@
 
 bool CefMenuManager::IsCustomContextMenuCommand(int command_id) {
   // Verify that the command ID is in the correct range.
-  if (command_id < MENU_ID_CUSTOM_FIRST || command_id > MENU_ID_CUSTOM_LAST)
+  if (command_id < MENU_ID_CUSTOM_FIRST || command_id > MENU_ID_CUSTOM_LAST) {
     return false;
+  }
 
   command_id -= MENU_ID_CUSTOM_FIRST;
 
   // Verify that the specific command ID was passed from the renderer process.
   if (!params_.custom_items.empty()) {
     for (size_t i = 0; i < params_.custom_items.size(); ++i) {
-      if (static_cast<int>(params_.custom_items[i].action) == command_id)
+      if (static_cast<int>(params_.custom_items[i]->action) == command_id) {
         return true;
+      }
     }
   }
   return false;
diff --git a/src/libcef/browser/menu_manager.h b/src/libcef/browser/menu_manager.h
index 3661479..239e3b7 100644
--- a/src/libcef/browser/menu_manager.h
+++ b/src/libcef/browser/menu_manager.h
@@ -19,14 +19,18 @@
 class WebContents;
 }  // namespace content
 
-class CefBrowserHostImpl;
+class AlloyBrowserHostImpl;
 class CefRunContextMenuCallback;
 
 class CefMenuManager : public CefMenuModelImpl::Delegate,
                        public content::WebContentsObserver {
  public:
-  CefMenuManager(CefBrowserHostImpl* browser,
+  CefMenuManager(AlloyBrowserHostImpl* browser,
                  std::unique_ptr<CefMenuRunner> runner);
+
+  CefMenuManager(const CefMenuManager&) = delete;
+  CefMenuManager& operator=(const CefMenuManager&) = delete;
+
   ~CefMenuManager() override;
 
   // Delete the runner to free any platform constructs.
@@ -47,7 +51,7 @@
   void MenuWillShow(CefRefPtr<CefMenuModelImpl> source) override;
   void MenuClosed(CefRefPtr<CefMenuModelImpl> source) override;
   bool FormatLabel(CefRefPtr<CefMenuModelImpl> source,
-                   base::string16& label) override;
+                   std::u16string& label) override;
 
   void ExecuteCommandCallback(int command_id, cef_event_flags_t event_flags);
 
@@ -59,8 +63,8 @@
   // Returns true if the specified id is a custom context menu command.
   bool IsCustomContextMenuCommand(int command_id);
 
-  // CefBrowserHostImpl pointer is guaranteed to outlive this object.
-  CefBrowserHostImpl* browser_;
+  // AlloyBrowserHostImpl pointer is guaranteed to outlive this object.
+  AlloyBrowserHostImpl* browser_;
 
   std::unique_ptr<CefMenuRunner> runner_;
 
@@ -72,8 +76,6 @@
 
   // Must be the last member.
   base::WeakPtrFactory<CefMenuManager> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefMenuManager);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_MENU_MANAGER_H_
diff --git a/src/libcef/browser/menu_model_impl.cc b/src/libcef/browser/menu_model_impl.cc
index 9b18b0c..de66b0c 100644
--- a/src/libcef/browser/menu_model_impl.cc
+++ b/src/libcef/browser/menu_model_impl.cc
@@ -10,12 +10,13 @@
 #include "libcef/browser/thread_util.h"
 #include "libcef/common/task_runner_impl.h"
 
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "content/public/common/menu_item.h"
+#include "third_party/blink/public/mojom/context_menu/context_menu.mojom.h"
 #include "ui/base/accelerators/accelerator.h"
+#include "ui/base/models/image_model.h"
 #include "ui/gfx/geometry/point.h"
+#include "ui/gfx/image/image.h"
 
 namespace {
 
@@ -32,12 +33,13 @@
   // disabled.
   explicit CefSimpleMenuModel(CefMenuModelImpl* impl) : impl_(impl) {}
 
+  CefSimpleMenuModel(const CefSimpleMenuModel&) = delete;
+  CefSimpleMenuModel& operator=(const CefSimpleMenuModel&) = delete;
+
   // MenuModel methods.
-  bool HasIcons() const override { return false; }
+  size_t GetItemCount() const override { return impl_->GetCount(); }
 
-  int GetItemCount() const override { return impl_->GetCount(); }
-
-  ItemType GetTypeAt(int index) const override {
+  ItemType GetTypeAt(size_t index) const override {
     switch (impl_->GetTypeAt(index)) {
       case MENUITEMTYPE_COMMAND:
         return TYPE_COMMAND;
@@ -50,30 +52,30 @@
       case MENUITEMTYPE_SUBMENU:
         return TYPE_SUBMENU;
       default:
-        NOTREACHED();
+        DCHECK(false);
         return TYPE_COMMAND;
     }
   }
 
-  ui::MenuSeparatorType GetSeparatorTypeAt(int index) const override {
+  ui::MenuSeparatorType GetSeparatorTypeAt(size_t index) const override {
     return ui::NORMAL_SEPARATOR;
   }
 
-  int GetCommandIdAt(int index) const override {
+  int GetCommandIdAt(size_t index) const override {
     return impl_->GetCommandIdAt(index);
   }
 
-  base::string16 GetLabelAt(int index) const override {
+  std::u16string GetLabelAt(size_t index) const override {
     return impl_->GetFormattedLabelAt(index);
   }
 
-  bool IsItemDynamicAt(int index) const override { return false; }
+  bool IsItemDynamicAt(size_t index) const override { return false; }
 
-  const gfx::FontList* GetLabelFontListAt(int index) const override {
+  const gfx::FontList* GetLabelFontListAt(size_t index) const override {
     return impl_->GetLabelFontListAt(index);
   }
 
-  bool GetAcceleratorAt(int index,
+  bool GetAcceleratorAt(size_t index,
                         ui::Accelerator* accelerator) const override {
     int key_code = 0;
     bool shift_pressed = false;
@@ -82,12 +84,15 @@
     if (impl_->GetAcceleratorAt(index, key_code, shift_pressed, ctrl_pressed,
                                 alt_pressed)) {
       int modifiers = 0;
-      if (shift_pressed)
+      if (shift_pressed) {
         modifiers |= ui::EF_SHIFT_DOWN;
-      if (ctrl_pressed)
+      }
+      if (ctrl_pressed) {
         modifiers |= ui::EF_CONTROL_DOWN;
-      if (alt_pressed)
+      }
+      if (alt_pressed) {
         modifiers |= ui::EF_ALT_DOWN;
+      }
 
       *accelerator =
           ui::Accelerator(static_cast<ui::KeyboardCode>(key_code), modifiers);
@@ -96,38 +101,41 @@
     return false;
   }
 
-  bool IsItemCheckedAt(int index) const override {
+  bool IsItemCheckedAt(size_t index) const override {
     return impl_->IsCheckedAt(index);
   }
 
-  int GetGroupIdAt(int index) const override {
+  int GetGroupIdAt(size_t index) const override {
     return impl_->GetGroupIdAt(index);
   }
 
-  bool GetIconAt(int index, gfx::Image* icon) const override { return false; }
+  ui::ImageModel GetIconAt(size_t index) const override {
+    return ui::ImageModel();
+  }
 
-  ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const override {
+  ui::ButtonMenuItemModel* GetButtonMenuItemAt(size_t index) const override {
     return nullptr;
   }
 
-  bool IsEnabledAt(int index) const override {
+  bool IsEnabledAt(size_t index) const override {
     return impl_->IsEnabledAt(index);
   }
 
-  bool IsVisibleAt(int index) const override {
+  bool IsVisibleAt(size_t index) const override {
     return impl_->IsVisibleAt(index);
   }
 
-  void ActivatedAt(int index) override { ActivatedAt(index, 0); }
+  void ActivatedAt(size_t index) override { ActivatedAt(index, 0); }
 
-  void ActivatedAt(int index, int event_flags) override {
+  void ActivatedAt(size_t index, int event_flags) override {
     impl_->ActivatedAt(index, static_cast<cef_event_flags_t>(event_flags));
   }
 
-  MenuModel* GetSubmenuModelAt(int index) const override {
+  MenuModel* GetSubmenuModelAt(size_t index) const override {
     CefRefPtr<CefMenuModel> submenu = impl_->GetSubMenuAt(index);
-    if (submenu.get())
+    if (submenu.get()) {
       return static_cast<CefMenuModelImpl*>(submenu.get())->model();
+    }
     return nullptr;
   }
 
@@ -143,14 +151,14 @@
     impl_->UnhandledCloseSubmenu(is_rtl);
   }
 
-  bool GetTextColor(int index,
+  bool GetTextColor(size_t index,
                     bool is_minor,
                     bool is_hovered,
                     SkColor* override_color) const override {
     return impl_->GetTextColor(index, is_minor, is_hovered, override_color);
   }
 
-  bool GetBackgroundColor(int index,
+  bool GetBackgroundColor(size_t index,
                           bool is_hovered,
                           SkColor* override_color) const override {
     return impl_->GetBackgroundColor(index, is_hovered, override_color);
@@ -162,8 +170,6 @@
 
  private:
   CefMenuModelImpl* impl_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefSimpleMenuModel);
 };
 
 cef_menu_color_type_t GetMenuColorType(bool is_text,
@@ -189,8 +195,9 @@
     CefRefPtr<CefMenuModelDelegate> delegate) {
   CEF_REQUIRE_UIT_RETURN(nullptr);
   DCHECK(delegate);
-  if (!delegate)
+  if (!delegate) {
     return nullptr;
+  }
 
   CefRefPtr<CefMenuModelImpl> menu_model =
       new CefMenuModelImpl(nullptr, delegate, false);
@@ -246,29 +253,33 @@
 CefMenuModelImpl::~CefMenuModelImpl() {}
 
 bool CefMenuModelImpl::IsSubMenu() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
   return is_submenu_;
 }
 
 bool CefMenuModelImpl::Clear() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   items_.clear();
   return true;
 }
 
-int CefMenuModelImpl::GetCount() {
-  if (!VerifyContext())
+size_t CefMenuModelImpl::GetCount() {
+  if (!VerifyContext()) {
     return 0;
+  }
 
-  return static_cast<int>(items_.size());
+  return items_.size();
 }
 
 bool CefMenuModelImpl::AddSeparator() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   AppendItem(
       Item(MENUITEMTYPE_SEPARATOR, kSeparatorId, CefString(), kInvalidGroupId));
@@ -276,16 +287,18 @@
 }
 
 bool CefMenuModelImpl::AddItem(int command_id, const CefString& label) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   AppendItem(Item(MENUITEMTYPE_COMMAND, command_id, label, kInvalidGroupId));
   return true;
 }
 
 bool CefMenuModelImpl::AddCheckItem(int command_id, const CefString& label) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   AppendItem(Item(MENUITEMTYPE_CHECK, command_id, label, kInvalidGroupId));
   return true;
@@ -294,8 +307,9 @@
 bool CefMenuModelImpl::AddRadioItem(int command_id,
                                     const CefString& label,
                                     int group_id) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   AppendItem(Item(MENUITEMTYPE_RADIO, command_id, label, group_id));
   return true;
@@ -303,8 +317,9 @@
 
 CefRefPtr<CefMenuModel> CefMenuModelImpl::AddSubMenu(int command_id,
                                                      const CefString& label) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return nullptr;
+  }
 
   Item item(MENUITEMTYPE_SUBMENU, command_id, label, kInvalidGroupId);
   item.submenu_ = new CefMenuModelImpl(delegate_, menu_model_delegate_, true);
@@ -312,9 +327,10 @@
   return item.submenu_.get();
 }
 
-bool CefMenuModelImpl::InsertSeparatorAt(int index) {
-  if (!VerifyContext())
+bool CefMenuModelImpl::InsertSeparatorAt(size_t index) {
+  if (!VerifyContext()) {
     return false;
+  }
 
   InsertItemAt(
       Item(MENUITEMTYPE_SEPARATOR, kSeparatorId, CefString(), kInvalidGroupId),
@@ -322,45 +338,49 @@
   return true;
 }
 
-bool CefMenuModelImpl::InsertItemAt(int index,
+bool CefMenuModelImpl::InsertItemAt(size_t index,
                                     int command_id,
                                     const CefString& label) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   InsertItemAt(Item(MENUITEMTYPE_COMMAND, command_id, label, kInvalidGroupId),
                index);
   return true;
 }
 
-bool CefMenuModelImpl::InsertCheckItemAt(int index,
+bool CefMenuModelImpl::InsertCheckItemAt(size_t index,
                                          int command_id,
                                          const CefString& label) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   InsertItemAt(Item(MENUITEMTYPE_CHECK, command_id, label, kInvalidGroupId),
                index);
   return true;
 }
 
-bool CefMenuModelImpl::InsertRadioItemAt(int index,
+bool CefMenuModelImpl::InsertRadioItemAt(size_t index,
                                          int command_id,
                                          const CefString& label,
                                          int group_id) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   InsertItemAt(Item(MENUITEMTYPE_RADIO, command_id, label, group_id), index);
   return true;
 }
 
 CefRefPtr<CefMenuModel> CefMenuModelImpl::InsertSubMenuAt(
-    int index,
+    size_t index,
     int command_id,
     const CefString& label) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return nullptr;
+  }
 
   Item item(MENUITEMTYPE_SUBMENU, command_id, label, kInvalidGroupId);
   item.submenu_ = new CefMenuModelImpl(delegate_, menu_model_delegate_, true);
@@ -372,11 +392,12 @@
   return RemoveAt(GetIndexOf(command_id));
 }
 
-bool CefMenuModelImpl::RemoveAt(int index) {
-  if (!VerifyContext())
+bool CefMenuModelImpl::RemoveAt(size_t index) {
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size())) {
+  if (index < items_.size()) {
     items_.erase(items_.begin() + index);
     return true;
   }
@@ -384,8 +405,9 @@
 }
 
 int CefMenuModelImpl::GetIndexOf(int command_id) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return kInvalidIndex;
+  }
 
   for (ItemVector::iterator i = items_.begin(); i != items_.end(); ++i) {
     if ((*i).command_id_ == command_id) {
@@ -395,20 +417,23 @@
   return kInvalidIndex;
 }
 
-int CefMenuModelImpl::GetCommandIdAt(int index) {
-  if (!VerifyContext())
+int CefMenuModelImpl::GetCommandIdAt(size_t index) {
+  if (!VerifyContext()) {
     return kInvalidCommandId;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size()))
+  if (index < items_.size()) {
     return items_[index].command_id_;
+  }
   return kInvalidCommandId;
 }
 
-bool CefMenuModelImpl::SetCommandIdAt(int index, int command_id) {
-  if (!VerifyContext())
+bool CefMenuModelImpl::SetCommandIdAt(size_t index, int command_id) {
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size())) {
+  if (index < items_.size()) {
     items_[index].command_id_ = command_id;
     return true;
   }
@@ -419,12 +444,14 @@
   return GetLabelAt(GetIndexOf(command_id));
 }
 
-CefString CefMenuModelImpl::GetLabelAt(int index) {
-  if (!VerifyContext())
+CefString CefMenuModelImpl::GetLabelAt(size_t index) {
+  if (!VerifyContext()) {
     return CefString();
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size()))
+  if (index < items_.size()) {
     return items_[index].label_;
+  }
   return CefString();
 }
 
@@ -432,11 +459,12 @@
   return SetLabelAt(GetIndexOf(command_id), label);
 }
 
-bool CefMenuModelImpl::SetLabelAt(int index, const CefString& label) {
-  if (!VerifyContext())
+bool CefMenuModelImpl::SetLabelAt(size_t index, const CefString& label) {
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size())) {
+  if (index < items_.size()) {
     items_[index].label_ = label;
     return true;
   }
@@ -447,12 +475,14 @@
   return GetTypeAt(GetIndexOf(command_id));
 }
 
-CefMenuModelImpl::MenuItemType CefMenuModelImpl::GetTypeAt(int index) {
-  if (!VerifyContext())
+CefMenuModelImpl::MenuItemType CefMenuModelImpl::GetTypeAt(size_t index) {
+  if (!VerifyContext()) {
     return MENUITEMTYPE_NONE;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size()))
+  if (index < items_.size()) {
     return items_[index].type_;
+  }
   return MENUITEMTYPE_NONE;
 }
 
@@ -460,12 +490,14 @@
   return GetGroupIdAt(GetIndexOf(command_id));
 }
 
-int CefMenuModelImpl::GetGroupIdAt(int index) {
-  if (!VerifyContext())
+int CefMenuModelImpl::GetGroupIdAt(size_t index) {
+  if (!VerifyContext()) {
     return kInvalidGroupId;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size()))
+  if (index < items_.size()) {
     return items_[index].group_id_;
+  }
   return kInvalidGroupId;
 }
 
@@ -473,11 +505,12 @@
   return SetGroupIdAt(GetIndexOf(command_id), group_id);
 }
 
-bool CefMenuModelImpl::SetGroupIdAt(int index, int group_id) {
-  if (!VerifyContext())
+bool CefMenuModelImpl::SetGroupIdAt(size_t index, int group_id) {
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size())) {
+  if (index < items_.size()) {
     items_[index].group_id_ = group_id;
     return true;
   }
@@ -488,12 +521,14 @@
   return GetSubMenuAt(GetIndexOf(command_id));
 }
 
-CefRefPtr<CefMenuModel> CefMenuModelImpl::GetSubMenuAt(int index) {
-  if (!VerifyContext())
+CefRefPtr<CefMenuModel> CefMenuModelImpl::GetSubMenuAt(size_t index) {
+  if (!VerifyContext()) {
     return nullptr;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size()))
+  if (index < items_.size()) {
     return items_[index].submenu_.get();
+  }
   return nullptr;
 }
 
@@ -501,12 +536,14 @@
   return IsVisibleAt(GetIndexOf(command_id));
 }
 
-bool CefMenuModelImpl::IsVisibleAt(int index) {
-  if (!VerifyContext())
+bool CefMenuModelImpl::IsVisibleAt(size_t index) {
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size()))
+  if (index < items_.size()) {
     return items_[index].visible_;
+  }
   return false;
 }
 
@@ -514,11 +551,12 @@
   return SetVisibleAt(GetIndexOf(command_id), visible);
 }
 
-bool CefMenuModelImpl::SetVisibleAt(int index, bool visible) {
-  if (!VerifyContext())
+bool CefMenuModelImpl::SetVisibleAt(size_t index, bool visible) {
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size())) {
+  if (index < items_.size()) {
     items_[index].visible_ = visible;
     return true;
   }
@@ -529,12 +567,14 @@
   return IsEnabledAt(GetIndexOf(command_id));
 }
 
-bool CefMenuModelImpl::IsEnabledAt(int index) {
-  if (!VerifyContext())
+bool CefMenuModelImpl::IsEnabledAt(size_t index) {
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size()))
+  if (index < items_.size()) {
     return items_[index].enabled_;
+  }
   return false;
 }
 
@@ -542,11 +582,12 @@
   return SetEnabledAt(GetIndexOf(command_id), enabled);
 }
 
-bool CefMenuModelImpl::SetEnabledAt(int index, bool enabled) {
-  if (!VerifyContext())
+bool CefMenuModelImpl::SetEnabledAt(size_t index, bool enabled) {
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size())) {
+  if (index < items_.size()) {
     items_[index].enabled_ = enabled;
     return true;
   }
@@ -557,12 +598,14 @@
   return IsCheckedAt(GetIndexOf(command_id));
 }
 
-bool CefMenuModelImpl::IsCheckedAt(int index) {
-  if (!VerifyContext())
+bool CefMenuModelImpl::IsCheckedAt(size_t index) {
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size()))
+  if (index < items_.size()) {
     return items_[index].checked_;
+  }
   return false;
 }
 
@@ -570,11 +613,12 @@
   return SetCheckedAt(GetIndexOf(command_id), checked);
 }
 
-bool CefMenuModelImpl::SetCheckedAt(int index, bool checked) {
-  if (!VerifyContext())
+bool CefMenuModelImpl::SetCheckedAt(size_t index, bool checked) {
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size())) {
+  if (index < items_.size()) {
     items_[index].checked_ = checked;
     return true;
   }
@@ -585,12 +629,14 @@
   return HasAcceleratorAt(GetIndexOf(command_id));
 }
 
-bool CefMenuModelImpl::HasAcceleratorAt(int index) {
-  if (!VerifyContext())
+bool CefMenuModelImpl::HasAcceleratorAt(size_t index) {
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size()))
+  if (index < items_.size()) {
     return items_[index].has_accelerator_;
+  }
   return false;
 }
 
@@ -603,15 +649,16 @@
                           ctrl_pressed, alt_pressed);
 }
 
-bool CefMenuModelImpl::SetAcceleratorAt(int index,
+bool CefMenuModelImpl::SetAcceleratorAt(size_t index,
                                         int key_code,
                                         bool shift_pressed,
                                         bool ctrl_pressed,
                                         bool alt_pressed) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size())) {
+  if (index < items_.size()) {
     Item& item = items_[index];
     item.has_accelerator_ = true;
     item.key_code_ = key_code;
@@ -627,11 +674,12 @@
   return RemoveAcceleratorAt(GetIndexOf(command_id));
 }
 
-bool CefMenuModelImpl::RemoveAcceleratorAt(int index) {
-  if (!VerifyContext())
+bool CefMenuModelImpl::RemoveAcceleratorAt(size_t index) {
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size())) {
+  if (index < items_.size()) {
     Item& item = items_[index];
     if (item.has_accelerator_) {
       item.has_accelerator_ = false;
@@ -654,15 +702,16 @@
                           ctrl_pressed, alt_pressed);
 }
 
-bool CefMenuModelImpl::GetAcceleratorAt(int index,
+bool CefMenuModelImpl::GetAcceleratorAt(size_t index,
                                         int& key_code,
                                         bool& shift_pressed,
                                         bool& ctrl_pressed,
                                         bool& alt_pressed) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (index >= 0 && index < static_cast<int>(items_.size())) {
+  if (index < items_.size()) {
     const Item& item = items_[index];
     if (item.has_accelerator_) {
       key_code = item.key_code_;
@@ -684,11 +733,13 @@
 bool CefMenuModelImpl::SetColorAt(int index,
                                   cef_menu_color_type_t color_type,
                                   cef_color_t color) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (color_type < 0 || color_type >= CEF_MENU_COLOR_COUNT)
+  if (color_type < 0 || color_type >= CEF_MENU_COLOR_COUNT) {
     return false;
+  }
 
   if (index == kDefaultIndex) {
     default_colors_[color_type] = color;
@@ -713,11 +764,13 @@
 bool CefMenuModelImpl::GetColorAt(int index,
                                   cef_menu_color_type_t color_type,
                                   cef_color_t& color) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (color_type < 0 || color_type >= CEF_MENU_COLOR_COUNT)
+  if (color_type < 0 || color_type >= CEF_MENU_COLOR_COUNT) {
     return false;
+  }
 
   if (index == kDefaultIndex) {
     color = default_colors_[color_type];
@@ -738,8 +791,9 @@
 }
 
 bool CefMenuModelImpl::SetFontListAt(int index, const CefString& font_list) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   if (index == kDefaultIndex) {
     if (font_list.empty()) {
@@ -764,55 +818,62 @@
   return false;
 }
 
-void CefMenuModelImpl::ActivatedAt(int index, cef_event_flags_t event_flags) {
-  if (!VerifyContext())
+void CefMenuModelImpl::ActivatedAt(size_t index,
+                                   cef_event_flags_t event_flags) {
+  if (!VerifyContext()) {
     return;
+  }
 
   const int command_id = GetCommandIdAt(index);
-  if (delegate_)
+  if (delegate_) {
     delegate_->ExecuteCommand(this, command_id, event_flags);
-  if (menu_model_delegate_)
+  }
+  if (menu_model_delegate_) {
     menu_model_delegate_->ExecuteCommand(this, command_id, event_flags);
+  }
 }
 
 void CefMenuModelImpl::MouseOutsideMenu(const gfx::Point& screen_point) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return;
+  }
 
   // Allow the callstack to unwind before notifying the delegate since it may
   // result in the menu being destroyed.
   CefTaskRunnerImpl::GetCurrentTaskRunner()->PostTask(
-      FROM_HERE,
-      base::Bind(&CefMenuModelImpl::OnMouseOutsideMenu, this, screen_point));
+      FROM_HERE, base::BindOnce(&CefMenuModelImpl::OnMouseOutsideMenu, this,
+                                screen_point));
 }
 
 void CefMenuModelImpl::UnhandledOpenSubmenu(bool is_rtl) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return;
+  }
 
   // Allow the callstack to unwind before notifying the delegate since it may
   // result in the menu being destroyed.
   CefTaskRunnerImpl::GetCurrentTaskRunner()->PostTask(
       FROM_HERE,
-      base::Bind(&CefMenuModelImpl::OnUnhandledOpenSubmenu, this, is_rtl));
+      base::BindOnce(&CefMenuModelImpl::OnUnhandledOpenSubmenu, this, is_rtl));
 }
 
 void CefMenuModelImpl::UnhandledCloseSubmenu(bool is_rtl) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return;
+  }
 
   // Allow the callstack to unwind before notifying the delegate since it may
   // result in the menu being destroyed.
   CefTaskRunnerImpl::GetCurrentTaskRunner()->PostTask(
       FROM_HERE,
-      base::Bind(&CefMenuModelImpl::OnUnhandledCloseSubmenu, this, is_rtl));
+      base::BindOnce(&CefMenuModelImpl::OnUnhandledCloseSubmenu, this, is_rtl));
 }
 
-bool CefMenuModelImpl::GetTextColor(int index,
+bool CefMenuModelImpl::GetTextColor(size_t index,
                                     bool is_accelerator,
                                     bool is_hovered,
                                     SkColor* override_color) const {
-  if (index >= 0 && index < static_cast<int>(items_.size())) {
+  if (index < items_.size()) {
     const Item& item = items_[index];
     if (!item.enabled_) {
       // Use accelerator color for disabled item text.
@@ -837,13 +898,13 @@
   return false;
 }
 
-bool CefMenuModelImpl::GetBackgroundColor(int index,
+bool CefMenuModelImpl::GetBackgroundColor(size_t index,
                                           bool is_hovered,
                                           SkColor* override_color) const {
   const cef_menu_color_type_t color_type =
       GetMenuColorType(false, false, is_hovered);
 
-  if (index >= 0 && index < static_cast<int>(items_.size())) {
+  if (index < items_.size()) {
     const Item& item = items_[index];
     if (item.colors_[color_type] != 0) {
       *override_color = item.colors_[color_type];
@@ -860,101 +921,118 @@
 }
 
 void CefMenuModelImpl::MenuWillShow() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return;
+  }
 
-  if (delegate_)
+  if (delegate_) {
     delegate_->MenuWillShow(this);
-  if (menu_model_delegate_)
+  }
+  if (menu_model_delegate_) {
     menu_model_delegate_->MenuWillShow(this);
+  }
 }
 
 void CefMenuModelImpl::MenuWillClose() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return;
+  }
 
-  if (!auto_notify_menu_closed_)
+  if (!auto_notify_menu_closed_) {
     return;
+  }
 
   // Due to how menus work on the different platforms, ActivatedAt will be
   // called after this.  It's more convenient for the delegate to be called
   // afterwards, though, so post a task.
   CefTaskRunnerImpl::GetCurrentTaskRunner()->PostTask(
-      FROM_HERE, base::Bind(&CefMenuModelImpl::OnMenuClosed, this));
+      FROM_HERE, base::BindOnce(&CefMenuModelImpl::OnMenuClosed, this));
 }
 
-base::string16 CefMenuModelImpl::GetFormattedLabelAt(int index) {
-  base::string16 label = GetLabelAt(index).ToString16();
-  if (delegate_)
+std::u16string CefMenuModelImpl::GetFormattedLabelAt(size_t index) {
+  std::u16string label = GetLabelAt(index).ToString16();
+  if (delegate_) {
     delegate_->FormatLabel(this, label);
+  }
   if (menu_model_delegate_) {
     CefString new_label = label;
-    if (menu_model_delegate_->FormatLabel(this, new_label))
+    if (menu_model_delegate_->FormatLabel(this, new_label)) {
       label = new_label;
+    }
   }
   return label;
 }
 
-const gfx::FontList* CefMenuModelImpl::GetLabelFontListAt(int index) const {
-  if (index >= 0 && index < static_cast<int>(items_.size())) {
+const gfx::FontList* CefMenuModelImpl::GetLabelFontListAt(size_t index) const {
+  if (index < items_.size()) {
     const Item& item = items_[index];
-    if (item.has_font_list_)
+    if (item.has_font_list_) {
       return &item.font_list_;
+    }
   }
 
-  if (has_default_font_list_)
+  if (has_default_font_list_) {
     return &default_font_list_;
+  }
   return nullptr;
 }
 
 bool CefMenuModelImpl::VerifyRefCount() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (!HasOneRef())
+  if (!HasOneRef()) {
     return false;
+  }
 
   for (ItemVector::iterator i = items_.begin(); i != items_.end(); ++i) {
     if ((*i).submenu_.get()) {
-      if (!(*i).submenu_->VerifyRefCount())
+      if (!(*i).submenu_->VerifyRefCount()) {
         return false;
+      }
     }
   }
 
   return true;
 }
 
-void CefMenuModelImpl::AddMenuItem(const content::MenuItem& menu_item) {
+void CefMenuModelImpl::AddMenuItem(
+    const blink::mojom::CustomContextMenuItem& menu_item) {
   const int command_id = static_cast<int>(menu_item.action);
 
   switch (menu_item.type) {
-    case content::MenuItem::OPTION:
+    case blink::mojom::CustomContextMenuItemType::kOption:
       AddItem(command_id, menu_item.label);
       break;
-    case content::MenuItem::CHECKABLE_OPTION:
+    case blink::mojom::CustomContextMenuItemType::kCheckableOption:
       AddCheckItem(command_id, menu_item.label);
       break;
-    case content::MenuItem::GROUP:
+    case blink::mojom::CustomContextMenuItemType::kGroup:
       AddRadioItem(command_id, menu_item.label, 0);
       break;
-    case content::MenuItem::SEPARATOR:
+    case blink::mojom::CustomContextMenuItemType::kSeparator:
       AddSeparator();
       break;
-    case content::MenuItem::SUBMENU: {
+    case blink::mojom::CustomContextMenuItemType::kSubMenu: {
       CefRefPtr<CefMenuModelImpl> sub_menu = static_cast<CefMenuModelImpl*>(
           AddSubMenu(command_id, menu_item.label).get());
-      for (size_t i = 0; i < menu_item.submenu.size(); ++i)
-        sub_menu->AddMenuItem(menu_item.submenu[i]);
+      for (size_t i = 0; i < menu_item.submenu.size(); ++i) {
+        sub_menu->AddMenuItem(*menu_item.submenu[i]);
+      }
       break;
     }
   }
 
-  if (!menu_item.enabled && menu_item.type != content::MenuItem::SEPARATOR)
+  if (!menu_item.enabled &&
+      menu_item.type != blink::mojom::CustomContextMenuItemType::kSeparator) {
     SetEnabled(command_id, false);
+  }
 
   if (menu_item.checked &&
-      (menu_item.type == content::MenuItem::CHECKABLE_OPTION ||
-       menu_item.type == content::MenuItem::GROUP)) {
+      (menu_item.type ==
+           blink::mojom::CustomContextMenuItemType::kCheckableOption ||
+       menu_item.type == blink::mojom::CustomContextMenuItemType::kGroup)) {
     SetChecked(command_id, true);
   }
 }
@@ -969,12 +1047,11 @@
   items_.push_back(item);
 }
 
-void CefMenuModelImpl::InsertItemAt(const Item& item, int index) {
+void CefMenuModelImpl::InsertItemAt(const Item& item, size_t index) {
   // Sanitize the index.
-  if (index < 0)
-    index = 0;
-  else if (index > static_cast<int>(items_.size()))
+  if (index > items_.size()) {
     index = items_.size();
+  }
 
   ValidateItem(item);
   items_.insert(items_.begin() + index, item);
@@ -991,8 +1068,9 @@
 }
 
 void CefMenuModelImpl::OnMouseOutsideMenu(const gfx::Point& screen_point) {
-  if (delegate_)
+  if (delegate_) {
     delegate_->MouseOutsideMenu(this, screen_point);
+  }
   if (menu_model_delegate_) {
     menu_model_delegate_->MouseOutsideMenu(
         this, CefPoint(screen_point.x(), screen_point.y()));
@@ -1000,30 +1078,36 @@
 }
 
 void CefMenuModelImpl::OnUnhandledOpenSubmenu(bool is_rtl) {
-  if (delegate_)
+  if (delegate_) {
     delegate_->UnhandledOpenSubmenu(this, is_rtl);
-  if (menu_model_delegate_)
+  }
+  if (menu_model_delegate_) {
     menu_model_delegate_->UnhandledOpenSubmenu(this, is_rtl);
+  }
 }
 
 void CefMenuModelImpl::OnUnhandledCloseSubmenu(bool is_rtl) {
-  if (delegate_)
+  if (delegate_) {
     delegate_->UnhandledCloseSubmenu(this, is_rtl);
-  if (menu_model_delegate_)
+  }
+  if (menu_model_delegate_) {
     menu_model_delegate_->UnhandledCloseSubmenu(this, is_rtl);
+  }
 }
 
 void CefMenuModelImpl::OnMenuClosed() {
-  if (delegate_)
+  if (delegate_) {
     delegate_->MenuClosed(this);
-  if (menu_model_delegate_)
+  }
+  if (menu_model_delegate_) {
     menu_model_delegate_->MenuClosed(this);
+  }
 }
 
 bool CefMenuModelImpl::VerifyContext() {
   if (base::PlatformThread::CurrentId() != supported_thread_id_) {
     // This object should only be accessed from the thread that created it.
-    NOTREACHED();
+    DCHECK(false);
     return false;
   }
 
diff --git a/src/libcef/browser/menu_model_impl.h b/src/libcef/browser/menu_model_impl.h
index fa44fbb..b896512 100644
--- a/src/libcef/browser/menu_model_impl.h
+++ b/src/libcef/browser/menu_model_impl.h
@@ -13,13 +13,10 @@
 #include "include/cef_menu_model_delegate.h"
 
 #include "base/threading/platform_thread.h"
+#include "third_party/blink/public/mojom/context_menu/context_menu.mojom-forward.h"
 #include "ui/base/models/menu_model.h"
 #include "ui/gfx/font_list.h"
 
-namespace content {
-struct MenuItem;
-}
-
 class CefMenuModelImpl : public CefMenuModel {
  public:
   class Delegate {
@@ -50,7 +47,7 @@
 
     // Allows the delegate to modify a menu item label before it's displayed.
     virtual bool FormatLabel(CefRefPtr<CefMenuModelImpl> source,
-                             base::string16& label) = 0;
+                             std::u16string& label) = 0;
 
    protected:
     virtual ~Delegate() {}
@@ -61,12 +58,16 @@
   CefMenuModelImpl(Delegate* delegate,
                    CefRefPtr<CefMenuModelDelegate> menu_model_delegate,
                    bool is_submenu);
+
+  CefMenuModelImpl(const CefMenuModelImpl&) = delete;
+  CefMenuModelImpl& operator=(const CefMenuModelImpl&) = delete;
+
   ~CefMenuModelImpl() override;
 
   // CefMenuModel methods.
   bool IsSubMenu() override;
   bool Clear() override;
-  int GetCount() override;
+  size_t GetCount() override;
   bool AddSeparator() override;
   bool AddItem(int command_id, const CefString& label) override;
   bool AddCheckItem(int command_id, const CefString& label) override;
@@ -75,67 +76,69 @@
                     int group_id) override;
   CefRefPtr<CefMenuModel> AddSubMenu(int command_id,
                                      const CefString& label) override;
-  bool InsertSeparatorAt(int index) override;
-  bool InsertItemAt(int index, int command_id, const CefString& label) override;
-  bool InsertCheckItemAt(int index,
+  bool InsertSeparatorAt(size_t index) override;
+  bool InsertItemAt(size_t index,
+                    int command_id,
+                    const CefString& label) override;
+  bool InsertCheckItemAt(size_t index,
                          int command_id,
                          const CefString& label) override;
-  bool InsertRadioItemAt(int index,
+  bool InsertRadioItemAt(size_t index,
                          int command_id,
                          const CefString& label,
                          int group_id) override;
-  CefRefPtr<CefMenuModel> InsertSubMenuAt(int index,
+  CefRefPtr<CefMenuModel> InsertSubMenuAt(size_t index,
                                           int command_id,
                                           const CefString& label) override;
   bool Remove(int command_id) override;
-  bool RemoveAt(int index) override;
+  bool RemoveAt(size_t index) override;
   int GetIndexOf(int command_id) override;
-  int GetCommandIdAt(int index) override;
-  bool SetCommandIdAt(int index, int command_id) override;
+  int GetCommandIdAt(size_t index) override;
+  bool SetCommandIdAt(size_t index, int command_id) override;
   CefString GetLabel(int command_id) override;
-  CefString GetLabelAt(int index) override;
+  CefString GetLabelAt(size_t index) override;
   bool SetLabel(int command_id, const CefString& label) override;
-  bool SetLabelAt(int index, const CefString& label) override;
+  bool SetLabelAt(size_t index, const CefString& label) override;
   MenuItemType GetType(int command_id) override;
-  MenuItemType GetTypeAt(int index) override;
+  MenuItemType GetTypeAt(size_t index) override;
   int GetGroupId(int command_id) override;
-  int GetGroupIdAt(int index) override;
+  int GetGroupIdAt(size_t index) override;
   bool SetGroupId(int command_id, int group_id) override;
-  bool SetGroupIdAt(int index, int group_id) override;
+  bool SetGroupIdAt(size_t index, int group_id) override;
   CefRefPtr<CefMenuModel> GetSubMenu(int command_id) override;
-  CefRefPtr<CefMenuModel> GetSubMenuAt(int index) override;
+  CefRefPtr<CefMenuModel> GetSubMenuAt(size_t index) override;
   bool IsVisible(int command_id) override;
-  bool IsVisibleAt(int index) override;
+  bool IsVisibleAt(size_t index) override;
   bool SetVisible(int command_id, bool visible) override;
-  bool SetVisibleAt(int index, bool visible) override;
+  bool SetVisibleAt(size_t index, bool visible) override;
   bool IsEnabled(int command_id) override;
-  bool IsEnabledAt(int index) override;
+  bool IsEnabledAt(size_t index) override;
   bool SetEnabled(int command_id, bool enabled) override;
-  bool SetEnabledAt(int index, bool enabled) override;
+  bool SetEnabledAt(size_t index, bool enabled) override;
   bool IsChecked(int command_id) override;
-  bool IsCheckedAt(int index) override;
+  bool IsCheckedAt(size_t index) override;
   bool SetChecked(int command_id, bool checked) override;
-  bool SetCheckedAt(int index, bool checked) override;
+  bool SetCheckedAt(size_t index, bool checked) override;
   bool HasAccelerator(int command_id) override;
-  bool HasAcceleratorAt(int index) override;
+  bool HasAcceleratorAt(size_t index) override;
   bool SetAccelerator(int command_id,
                       int key_code,
                       bool shift_pressed,
                       bool ctrl_pressed,
                       bool alt_pressed) override;
-  bool SetAcceleratorAt(int index,
+  bool SetAcceleratorAt(size_t index,
                         int key_code,
                         bool shift_pressed,
                         bool ctrl_pressed,
                         bool alt_pressed) override;
   bool RemoveAccelerator(int command_id) override;
-  bool RemoveAcceleratorAt(int index) override;
+  bool RemoveAcceleratorAt(size_t index) override;
   bool GetAccelerator(int command_id,
                       int& key_code,
                       bool& shift_pressed,
                       bool& ctrl_pressed,
                       bool& alt_pressed) override;
-  bool GetAcceleratorAt(int index,
+  bool GetAcceleratorAt(size_t index,
                         int& key_code,
                         bool& shift_pressed,
                         bool& ctrl_pressed,
@@ -156,27 +159,27 @@
   bool SetFontListAt(int index, const CefString& font_list) override;
 
   // Callbacks from the ui::MenuModel implementation.
-  void ActivatedAt(int index, cef_event_flags_t event_flags);
+  void ActivatedAt(size_t index, cef_event_flags_t event_flags);
   void MouseOutsideMenu(const gfx::Point& screen_point);
   void UnhandledOpenSubmenu(bool is_rtl);
   void UnhandledCloseSubmenu(bool is_rtl);
-  bool GetTextColor(int index,
+  bool GetTextColor(size_t index,
                     bool is_accelerator,
                     bool is_hovered,
                     SkColor* override_color) const;
-  bool GetBackgroundColor(int index,
+  bool GetBackgroundColor(size_t index,
                           bool is_hovered,
                           SkColor* override_color) const;
   void MenuWillShow();
   void MenuWillClose();
-  base::string16 GetFormattedLabelAt(int index);
-  const gfx::FontList* GetLabelFontListAt(int index) const;
+  std::u16string GetFormattedLabelAt(size_t index);
+  const gfx::FontList* GetLabelFontListAt(size_t index) const;
 
   // Verify that only a single reference exists to all CefMenuModelImpl objects.
   bool VerifyRefCount();
 
   // Helper for adding custom menu items originating from the renderer process.
-  void AddMenuItem(const content::MenuItem& menu_item);
+  void AddMenuItem(const blink::mojom::CustomContextMenuItem& menu_item);
 
   ui::MenuModel* model() const { return model_.get(); }
 
@@ -192,11 +195,11 @@
  private:
   struct Item;
 
-  typedef std::vector<Item> ItemVector;
+  using ItemVector = std::vector<Item>;
 
   // Functions for inserting items into |items_|.
   void AppendItem(const Item& item);
-  void InsertItemAt(const Item& item, int index);
+  void InsertItemAt(const Item& item, size_t index);
   void ValidateItem(const Item& item);
 
   // Notify the delegate asynchronously.
@@ -229,7 +232,6 @@
   bool auto_notify_menu_closed_ = true;
 
   IMPLEMENT_REFCOUNTING(CefMenuModelImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefMenuModelImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_MENU_MODEL_IMPL_H_
diff --git a/src/libcef/browser/menu_runner.h b/src/libcef/browser/menu_runner.h
index 6bb0e10..a0107db 100644
--- a/src/libcef/browser/menu_runner.h
+++ b/src/libcef/browser/menu_runner.h
@@ -6,34 +6,33 @@
 #define CEF_LIBCEF_BROWSER_MENU_RUNNER_H_
 
 #include <memory>
-
-#include "base/macros.h"
-#include "base/strings/string16.h"
+#include <string>
 
 namespace content {
 struct ContextMenuParams;
 }
 
-class CefBrowserHostImpl;
+class AlloyBrowserHostImpl;
 class CefMenuModelImpl;
 
 // Provides platform-specific menu implementations for CefMenuCreator.
 class CefMenuRunner {
  public:
-  virtual bool RunContextMenu(CefBrowserHostImpl* browser,
+  CefMenuRunner(const CefMenuRunner&) = delete;
+  CefMenuRunner& operator=(const CefMenuRunner&) = delete;
+
+  virtual bool RunContextMenu(AlloyBrowserHostImpl* browser,
                               CefMenuModelImpl* model,
                               const content::ContextMenuParams& params) = 0;
   virtual void CancelContextMenu() {}
-  virtual bool FormatLabel(base::string16& label) { return false; }
+  virtual bool FormatLabel(std::u16string& label) { return false; }
 
  protected:
-  // Allow deletion via scoped_ptr only.
+  // Allow deletion via std::unique_ptr only.
   friend std::default_delete<CefMenuRunner>;
 
-  CefMenuRunner() {}
-  virtual ~CefMenuRunner() {}
-
-  DISALLOW_COPY_AND_ASSIGN(CefMenuRunner);
+  CefMenuRunner() = default;
+  virtual ~CefMenuRunner() = default;
 };
 
 #endif  // CEF_LIBCEF_BROWSER_MENU_RUNNER_H_
diff --git a/src/libcef/browser/native/browser_platform_delegate_native.cc b/src/libcef/browser/native/browser_platform_delegate_native.cc
index b26ee3e..6547a13 100644
--- a/src/libcef/browser/native/browser_platform_delegate_native.cc
+++ b/src/libcef/browser/native/browser_platform_delegate_native.cc
@@ -4,7 +4,7 @@
 
 #include "libcef/browser/native/browser_platform_delegate_native.h"
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
@@ -12,37 +12,18 @@
 
 CefBrowserPlatformDelegateNative::CefBrowserPlatformDelegateNative(
     const CefWindowInfo& window_info,
-    SkColor background_color,
-    bool use_shared_texture,
-    bool use_external_begin_frame)
+    SkColor background_color)
     : window_info_(window_info),
       background_color_(background_color),
-      use_shared_texture_(use_shared_texture),
-      use_external_begin_frame_(use_external_begin_frame),
       windowless_handler_(nullptr) {}
 
 SkColor CefBrowserPlatformDelegateNative::GetBackgroundColor() const {
   return background_color_;
 }
 
-bool CefBrowserPlatformDelegateNative::CanUseSharedTexture() const {
-  return use_shared_texture_;
-}
-
-bool CefBrowserPlatformDelegateNative::CanUseExternalBeginFrame() const {
-  return use_external_begin_frame_;
-}
-
 void CefBrowserPlatformDelegateNative::WasResized() {
-  content::RenderViewHost* host = browser_->web_contents()->GetRenderViewHost();
-  if (host)
+  content::RenderViewHost* host = web_contents_->GetRenderViewHost();
+  if (host) {
     host->GetWidget()->SynchronizeVisualProperties();
-}
-
-bool CefBrowserPlatformDelegateNative::IsWindowless() const {
-  return false;
-}
-
-bool CefBrowserPlatformDelegateNative::IsViewsHosted() const {
-  return false;
+  }
 }
diff --git a/src/libcef/browser/native/browser_platform_delegate_native.h b/src/libcef/browser/native/browser_platform_delegate_native.h
index a7c3003..704da0d 100644
--- a/src/libcef/browser/native/browser_platform_delegate_native.h
+++ b/src/libcef/browser/native/browser_platform_delegate_native.h
@@ -5,10 +5,11 @@
 #ifndef CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_H_
 #define CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_H_
 
-#include "libcef/browser/browser_platform_delegate.h"
+#include "libcef/browser/alloy/browser_platform_delegate_alloy.h"
 
 // Base implementation of native browser functionality.
-class CefBrowserPlatformDelegateNative : public CefBrowserPlatformDelegate {
+class CefBrowserPlatformDelegateNative
+    : public CefBrowserPlatformDelegateAlloy {
  public:
   // Used by the windowless implementation to override specific functionality
   // when delegating to the native implementation.
@@ -17,20 +18,19 @@
     // Returns the parent window handle.
     virtual CefWindowHandle GetParentWindowHandle() const = 0;
 
-    // Convert from view coordinates to screen coordinates.
-    virtual gfx::Point GetParentScreenPoint(const gfx::Point& view) const = 0;
+    // Convert from view DIP coordinates to screen coordinates. If
+    // |want_dip_coords| is true return DIP instead of device (pixel)
+    // coordinates on Windows/Linux.
+    virtual gfx::Point GetParentScreenPoint(const gfx::Point& view,
+                                            bool want_dip_coords) const = 0;
 
    protected:
     virtual ~WindowlessHandler() {}
   };
 
   // CefBrowserPlatformDelegate methods:
-  bool CanUseSharedTexture() const override;
-  bool CanUseExternalBeginFrame() const override;
   SkColor GetBackgroundColor() const override;
   void WasResized() override;
-  bool IsWindowless() const override;
-  bool IsViewsHosted() const override;
 
   // Translate CEF events to Chromium/Blink Web events.
   virtual content::NativeWebKeyboardEvent TranslateWebKeyEvent(
@@ -53,24 +53,21 @@
  protected:
   // Delegates that can wrap a native delegate.
   friend class CefBrowserPlatformDelegateBackground;
+  friend class CefBrowserPlatformDelegateChrome;
   friend class CefBrowserPlatformDelegateOsr;
   friend class CefBrowserPlatformDelegateViews;
 
   CefBrowserPlatformDelegateNative(const CefWindowInfo& window_info,
-                                   SkColor background_color,
-                                   bool use_shared_texture,
-                                   bool use_external_begin_frame);
+                                   SkColor background_color);
 
   // Methods used by delegates that can wrap a native delegate.
   void set_windowless_handler(WindowlessHandler* handler) {
     windowless_handler_ = handler;
+    set_as_secondary();
   }
-  void set_browser(CefBrowserHostImpl* browser) { browser_ = browser; }
 
   CefWindowInfo window_info_;
   const SkColor background_color_;
-  const bool use_shared_texture_;
-  const bool use_external_begin_frame_;
 
   WindowlessHandler* windowless_handler_;  // Not owned by this object.
 };
diff --git a/src/libcef/browser/native/browser_platform_delegate_native_aura.cc b/src/libcef/browser/native/browser_platform_delegate_native_aura.cc
index db5ceb1..83c1277 100644
--- a/src/libcef/browser/native/browser_platform_delegate_native_aura.cc
+++ b/src/libcef/browser/native/browser_platform_delegate_native_aura.cc
@@ -4,28 +4,28 @@
 
 #include "libcef/browser/native/browser_platform_delegate_native_aura.h"
 
+#include "libcef/browser/native/menu_runner_views_aura.h"
+#include "libcef/browser/views/view_util.h"
+
 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "ui/events/blink/blink_event_util.h"
 #include "ui/events/blink/web_input_event.h"
 #include "ui/gfx/geometry/vector2d.h"
+#include "ui/views/widget/widget.h"
 
 CefBrowserPlatformDelegateNativeAura::CefBrowserPlatformDelegateNativeAura(
     const CefWindowInfo& window_info,
-    SkColor background_color,
-    bool use_shared_texture,
-    bool use_external_begin_frame)
-    : CefBrowserPlatformDelegateNative(window_info,
-                                       background_color,
-                                       use_shared_texture,
-                                       use_external_begin_frame) {}
+    SkColor background_color)
+    : CefBrowserPlatformDelegateNative(window_info, background_color) {}
 
 void CefBrowserPlatformDelegateNativeAura::SendKeyEvent(
     const CefKeyEvent& event) {
   auto view = GetHostView();
-  if (!view)
+  if (!view) {
     return;
+  }
 
   ui::KeyEvent ui_event = TranslateUiKeyEvent(event);
   view->OnKeyEvent(&ui_event);
@@ -37,8 +37,9 @@
     bool mouseUp,
     int clickCount) {
   auto view = GetHostView();
-  if (!view)
+  if (!view) {
     return;
+  }
 
   ui::MouseEvent ui_event =
       TranslateUiClickEvent(event, type, mouseUp, clickCount);
@@ -49,8 +50,9 @@
     const CefMouseEvent& event,
     bool mouseLeave) {
   auto view = GetHostView();
-  if (!view)
+  if (!view) {
     return;
+  }
 
   ui::MouseEvent ui_event = TranslateUiMoveEvent(event, mouseLeave);
   view->OnMouseEvent(&ui_event);
@@ -61,8 +63,9 @@
     int deltaX,
     int deltaY) {
   auto view = GetHostView();
-  if (!view)
+  if (!view) {
     return;
+  }
 
   ui::MouseWheelEvent ui_event = TranslateUiWheelEvent(event, deltaX, deltaY);
   view->OnMouseEvent(&ui_event);
@@ -73,6 +76,32 @@
   NOTIMPLEMENTED();
 }
 
+std::unique_ptr<CefMenuRunner>
+CefBrowserPlatformDelegateNativeAura::CreateMenuRunner() {
+  return base::WrapUnique(new CefMenuRunnerViewsAura);
+}
+
+gfx::Point CefBrowserPlatformDelegateNativeAura::GetScreenPoint(
+    const gfx::Point& view,
+    bool want_dip_coords) const {
+  if (windowless_handler_) {
+    return windowless_handler_->GetParentScreenPoint(view, want_dip_coords);
+  }
+
+  if (!window_widget_) {
+    return view;
+  }
+
+  gfx::Point screen_pt(view);
+  if (!view_util::ConvertPointToScreen(
+          window_widget_->GetRootView(), &screen_pt,
+          /*output_pixel_coords=*/!want_dip_coords)) {
+    return view;
+  }
+
+  return screen_pt;
+}
+
 content::NativeWebKeyboardEvent
 CefBrowserPlatformDelegateNativeAura::TranslateWebKeyEvent(
     const CefKeyEvent& key_event) const {
@@ -115,8 +144,8 @@
   ui::EventType event_type =
       mouseUp ? ui::ET_MOUSE_RELEASED : ui::ET_MOUSE_PRESSED;
   gfx::PointF location(mouse_event.x, mouse_event.y);
-  gfx::PointF root_location(
-      GetScreenPoint(gfx::Point(mouse_event.x, mouse_event.y)));
+  gfx::PointF root_location(GetScreenPoint(
+      gfx::Point(mouse_event.x, mouse_event.y), /*want_dip_coords=*/false));
   base::TimeTicks time_stamp = GetEventTimeStamp();
   int flags = TranslateUiEventModifiers(mouse_event.modifiers);
 
@@ -132,7 +161,7 @@
       changed_button_flags |= ui::EF_RIGHT_MOUSE_BUTTON;
       break;
     default:
-      NOTREACHED();
+      DCHECK(false);
   }
 
   ui::MouseEvent result(event_type, location, root_location, time_stamp, flags,
@@ -147,8 +176,8 @@
   ui::EventType event_type =
       mouseLeave ? ui::ET_MOUSE_EXITED : ui::ET_MOUSE_MOVED;
   gfx::PointF location(mouse_event.x, mouse_event.y);
-  gfx::PointF root_location(
-      GetScreenPoint(gfx::Point(mouse_event.x, mouse_event.y)));
+  gfx::PointF root_location(GetScreenPoint(
+      gfx::Point(mouse_event.x, mouse_event.y), /*want_dip_coords=*/false));
   base::TimeTicks time_stamp = GetEventTimeStamp();
   int flags = TranslateUiEventModifiers(mouse_event.modifiers);
 
@@ -169,8 +198,8 @@
   DCHECK(!offset.IsZero());
 
   gfx::PointF location(mouse_event.x, mouse_event.y);
-  gfx::PointF root_location(
-      GetScreenPoint(gfx::Point(mouse_event.x, mouse_event.y)));
+  gfx::PointF root_location(GetScreenPoint(
+      gfx::Point(mouse_event.x, mouse_event.y), /*want_dip_coords=*/false));
   base::TimeTicks time_stamp = GetEventTimeStamp();
   int flags = TranslateUiEventModifiers(mouse_event.modifiers);
   int changed_button_flags =
@@ -187,49 +216,85 @@
   return gfx::Vector2d(deltaX, deltaY);
 }
 
+base::OnceClosure
+CefBrowserPlatformDelegateNativeAura::GetWidgetDeleteCallback() {
+  return base::BindOnce(&CefBrowserPlatformDelegateNativeAura::WidgetDeleted,
+                        weak_ptr_factory_.GetWeakPtr());
+}
+
+// static
+base::TimeTicks CefBrowserPlatformDelegateNativeAura::GetEventTimeStamp() {
+  return base::TimeTicks::Now();
+}
+
 // static
 int CefBrowserPlatformDelegateNativeAura::TranslateUiEventModifiers(
-    uint32 cef_modifiers) {
+    uint32_t cef_modifiers) {
   int result = 0;
   // Set modifiers based on key state.
-  if (cef_modifiers & EVENTFLAG_SHIFT_DOWN)
-    result |= ui::EF_SHIFT_DOWN;
-  if (cef_modifiers & EVENTFLAG_CONTROL_DOWN)
-    result |= ui::EF_CONTROL_DOWN;
-  if (cef_modifiers & EVENTFLAG_ALT_DOWN)
-    result |= ui::EF_ALT_DOWN;
-  if (cef_modifiers & EVENTFLAG_COMMAND_DOWN)
-    result |= ui::EF_COMMAND_DOWN;
-  if (cef_modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON)
-    result |= ui::EF_LEFT_MOUSE_BUTTON;
-  if (cef_modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON)
-    result |= ui::EF_MIDDLE_MOUSE_BUTTON;
-  if (cef_modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON)
-    result |= ui::EF_RIGHT_MOUSE_BUTTON;
-  if (cef_modifiers & EVENTFLAG_CAPS_LOCK_ON)
+  if (cef_modifiers & EVENTFLAG_CAPS_LOCK_ON) {
     result |= ui::EF_CAPS_LOCK_ON;
-  if (cef_modifiers & EVENTFLAG_NUM_LOCK_ON)
+  }
+  if (cef_modifiers & EVENTFLAG_SHIFT_DOWN) {
+    result |= ui::EF_SHIFT_DOWN;
+  }
+  if (cef_modifiers & EVENTFLAG_CONTROL_DOWN) {
+    result |= ui::EF_CONTROL_DOWN;
+  }
+  if (cef_modifiers & EVENTFLAG_ALT_DOWN) {
+    result |= ui::EF_ALT_DOWN;
+  }
+  if (cef_modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) {
+    result |= ui::EF_LEFT_MOUSE_BUTTON;
+  }
+  if (cef_modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) {
+    result |= ui::EF_MIDDLE_MOUSE_BUTTON;
+  }
+  if (cef_modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) {
+    result |= ui::EF_RIGHT_MOUSE_BUTTON;
+  }
+  if (cef_modifiers & EVENTFLAG_COMMAND_DOWN) {
+    result |= ui::EF_COMMAND_DOWN;
+  }
+  if (cef_modifiers & EVENTFLAG_NUM_LOCK_ON) {
     result |= ui::EF_NUM_LOCK_ON;
-  if (cef_modifiers & EVENTFLAG_ALTGR_DOWN)
+  }
+  if (cef_modifiers & EVENTFLAG_IS_KEY_PAD) {
+    result |= ui::EF_IS_EXTENDED_KEY;
+  }
+  if (cef_modifiers & EVENTFLAG_ALTGR_DOWN) {
     result |= ui::EF_ALTGR_DOWN;
+  }
+  if (cef_modifiers & EVENTFLAG_IS_REPEAT) {
+    result |= ui::EF_IS_REPEAT;
+  }
   return result;
 }
 
 // static
 int CefBrowserPlatformDelegateNativeAura::TranslateUiChangedButtonFlags(
-    uint32 cef_modifiers) {
+    uint32_t cef_modifiers) {
   int result = 0;
-  if (cef_modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON)
+  if (cef_modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) {
     result |= ui::EF_LEFT_MOUSE_BUTTON;
-  else if (cef_modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON)
+  } else if (cef_modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) {
     result |= ui::EF_MIDDLE_MOUSE_BUTTON;
-  else if (cef_modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON)
+  } else if (cef_modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) {
     result |= ui::EF_RIGHT_MOUSE_BUTTON;
+  }
   return result;
 }
 
+void CefBrowserPlatformDelegateNativeAura::WidgetDeleted() {
+  DCHECK(window_widget_);
+  window_widget_ = nullptr;
+}
+
 content::RenderWidgetHostViewAura*
 CefBrowserPlatformDelegateNativeAura::GetHostView() const {
+  if (!web_contents_) {
+    return nullptr;
+  }
   return static_cast<content::RenderWidgetHostViewAura*>(
-      browser_->web_contents()->GetRenderWidgetHostView());
+      web_contents_->GetRenderWidgetHostView());
 }
diff --git a/src/libcef/browser/native/browser_platform_delegate_native_aura.h b/src/libcef/browser/native/browser_platform_delegate_native_aura.h
index 96b5a41..e547c5a 100644
--- a/src/libcef/browser/native/browser_platform_delegate_native_aura.h
+++ b/src/libcef/browser/native/browser_platform_delegate_native_aura.h
@@ -7,6 +7,7 @@
 
 #include "libcef/browser/native/browser_platform_delegate_native.h"
 
+#include "base/memory/weak_ptr.h"
 #include "ui/events/event.h"
 
 namespace content {
@@ -22,9 +23,7 @@
     : public CefBrowserPlatformDelegateNative {
  public:
   CefBrowserPlatformDelegateNativeAura(const CefWindowInfo& window_info,
-                                       SkColor background_color,
-                                       bool use_shared_texture,
-                                       bool use_external_begin_frame);
+                                       SkColor background_color);
 
   // CefBrowserPlatformDelegate methods:
   void SendKeyEvent(const CefKeyEvent& event) override;
@@ -37,6 +36,9 @@
                            int deltaX,
                            int deltaY) override;
   void SendTouchEvent(const CefTouchEvent& event) override;
+  std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
+  gfx::Point GetScreenPoint(const gfx::Point& view,
+                            bool want_dip_coords) const override;
 
   // CefBrowserPlatformDelegateNative methods:
   content::NativeWebKeyboardEvent TranslateWebKeyEvent(
@@ -68,14 +70,27 @@
       int deltaX,
       int deltaY) const;
   virtual gfx::Vector2d GetUiWheelEventOffset(int deltaX, int deltaY) const;
-  virtual base::TimeTicks GetEventTimeStamp() const = 0;
 
  protected:
-  static int TranslateUiEventModifiers(uint32 cef_modifiers);
-  static int TranslateUiChangedButtonFlags(uint32 cef_modifiers);
+  base::OnceClosure GetWidgetDeleteCallback();
+
+  static base::TimeTicks GetEventTimeStamp();
+  static int TranslateUiEventModifiers(uint32_t cef_modifiers);
+  static int TranslateUiChangedButtonFlags(uint32_t cef_modifiers);
+
+  // Widget hosting the web contents. It will be deleted automatically when the
+  // associated root window is destroyed.
+  views::Widget* window_widget_ = nullptr;
 
  private:
+  // Will only be called if the Widget is deleted before
+  // CefBrowserHostBase::DestroyBrowser() is called.
+  void WidgetDeleted();
+
   content::RenderWidgetHostViewAura* GetHostView() const;
+
+  base::WeakPtrFactory<CefBrowserPlatformDelegateNativeAura> weak_ptr_factory_{
+      this};
 };
 
 #endif  // CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_AURA_H_
diff --git a/src/libcef/browser/native/browser_platform_delegate_native_linux.cc b/src/libcef/browser/native/browser_platform_delegate_native_linux.cc
index b6364b2..70b148b 100644
--- a/src/libcef/browser/native/browser_platform_delegate_native_linux.cc
+++ b/src/libcef/browser/native/browser_platform_delegate_native_linux.cc
@@ -4,58 +4,37 @@
 
 #include "libcef/browser/native/browser_platform_delegate_native_linux.h"
 
-#include <sys/sysinfo.h>
-
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/browser_host_base.h"
 #include "libcef/browser/context.h"
-#include "libcef/browser/native/menu_runner_linux.h"
 #include "libcef/browser/native/window_delegate_view.h"
 #include "libcef/browser/thread_util.h"
 
 #include "base/no_destructor.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/public/browser/native_web_keyboard_event.h"
 #include "content/public/browser/render_view_host.h"
+#include "content/public/common/input/native_web_keyboard_event.h"
 #include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "ui/events/keycodes/dom/dom_key.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
-#include "ui/events/keycodes/keyboard_code_conversion_x.h"
-#include "ui/events/keycodes/keyboard_code_conversion_xkb.h"
 #include "ui/events/keycodes/keysym_to_unicode.h"
 #include "ui/gfx/font_render_params.h"
 #include "ui/views/widget/widget.h"
 
-#if defined(USE_X11)
+#if BUILDFLAG(OZONE_PLATFORM_X11)
 #include "libcef/browser/native/window_x11.h"
-#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
+#include "ui/events/keycodes/keyboard_code_conversion_x.h"
+#include "ui/events/keycodes/keyboard_code_conversion_xkb.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h"
 #endif
 
-namespace {
-
-// Returns the number of seconds since system boot.
-long GetSystemUptime() {
-  struct sysinfo info;
-  if (sysinfo(&info) == 0)
-    return info.uptime;
-  return 0;
-}
-
-}  // namespace
-
 CefBrowserPlatformDelegateNativeLinux::CefBrowserPlatformDelegateNativeLinux(
     const CefWindowInfo& window_info,
-    SkColor background_color,
-    bool use_external_begin_frame)
-    : CefBrowserPlatformDelegateNativeAura(window_info,
-                                           background_color,
-                                           false,
-                                           use_external_begin_frame),
-      host_window_created_(false),
-      window_widget_(nullptr) {}
+    SkColor background_color)
+    : CefBrowserPlatformDelegateNativeAura(window_info, background_color) {}
 
 void CefBrowserPlatformDelegateNativeLinux::BrowserDestroyed(
-    CefBrowserHostImpl* browser) {
-  CefBrowserPlatformDelegate::BrowserDestroyed(browser);
+    CefBrowserHostBase* browser) {
+  CefBrowserPlatformDelegateNativeAura::BrowserDestroyed(browser);
 
   if (host_window_created_) {
     // Release the reference added in CreateHostWindow().
@@ -66,22 +45,32 @@
 bool CefBrowserPlatformDelegateNativeLinux::CreateHostWindow() {
   DCHECK(!window_widget_);
 
-  if (window_info_.width == 0)
-    window_info_.width = 800;
-  if (window_info_.height == 0)
-    window_info_.height = 600;
+  if (window_info_.bounds.width == 0) {
+    window_info_.bounds.width = 800;
+  }
+  if (window_info_.bounds.height == 0) {
+    window_info_.bounds.height = 600;
+  }
 
-  gfx::Rect rect(window_info_.x, window_info_.y, window_info_.width,
-                 window_info_.height);
+  gfx::Rect rect(window_info_.bounds.x, window_info_.bounds.y,
+                 window_info_.bounds.width, window_info_.bounds.height);
 
-#if defined(USE_X11)
+#if BUILDFLAG(OZONE_PLATFORM_X11)
   DCHECK(!window_x11_);
+
+  x11::Window parent_window = x11::Window::None;
+  if (window_info_.parent_window != kNullWindowHandle) {
+    parent_window = static_cast<x11::Window>(window_info_.parent_window);
+  }
+
   // Create a new window object. It will delete itself when the associated X11
   // window is destroyed.
   window_x11_ =
-      new CefWindowX11(browser_, window_info_.parent_window, rect,
+      new CefWindowX11(browser_, parent_window, rect,
                        CefString(&window_info_.window_name).ToString());
-  window_info_.window = window_x11_->xwindow();
+  DCHECK_NE(window_x11_->xwindow(), x11::Window::None);
+  window_info_.window =
+      static_cast<cef_window_handle_t>(window_x11_->xwindow());
 
   host_window_created_ = true;
 
@@ -90,20 +79,19 @@
 
   CefWindowDelegateView* delegate_view = new CefWindowDelegateView(
       GetBackgroundColor(), window_x11_->TopLevelAlwaysOnTop(),
-      GetBoundsChangedCallback());
-  delegate_view->Init(window_info_.window, browser_->web_contents(),
-                      gfx::Rect(gfx::Point(), rect.size()));
+      GetBoundsChangedCallback(), GetWidgetDeleteCallback());
+  delegate_view->Init(static_cast<gfx::AcceleratedWidget>(window_info_.window),
+                      web_contents_, gfx::Rect(gfx::Point(), rect.size()));
 
   window_widget_ = delegate_view->GetWidget();
   window_widget_->Show();
 
   window_x11_->Show();
-#endif  // defined(USE_X11)
+#endif  // BUILDFLAG(OZONE_PLATFORM_X11)
 
   // As an additional requirement on Linux, we must set the colors for the
   // render widgets in webkit.
-  blink::mojom::RendererPreferences* prefs =
-      browser_->web_contents()->GetMutableRendererPrefs();
+  auto prefs = web_contents_->GetMutableRendererPrefs();
   prefs->focus_ring_color = SkColorSetARGB(255, 229, 151, 0);
 
   prefs->active_selection_bg_color = SkColorSetRGB(30, 144, 255);
@@ -112,31 +100,33 @@
   prefs->inactive_selection_fg_color = SkColorSetRGB(50, 50, 50);
 
   // Set font-related attributes.
-  static const base::NoDestructor<gfx::FontRenderParams> params(
+  static const 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;
+  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;
 
-  browser_->web_contents()->SyncRendererPrefs();
+  web_contents_->SyncRendererPrefs();
 
   return true;
 }
 
 void CefBrowserPlatformDelegateNativeLinux::CloseHostWindow() {
-#if defined(USE_X11)
-  if (window_x11_)
+#if BUILDFLAG(OZONE_PLATFORM_X11)
+  if (window_x11_) {
     window_x11_->Close();
+  }
 #endif
 }
 
 CefWindowHandle CefBrowserPlatformDelegateNativeLinux::GetHostWindowHandle()
     const {
-  if (windowless_handler_)
+  if (windowless_handler_) {
     return windowless_handler_->GetParentWindowHandle();
+  }
   return window_info_.window;
 }
 
@@ -144,37 +134,44 @@
   return window_widget_;
 }
 
-void CefBrowserPlatformDelegateNativeLinux::SendFocusEvent(bool setFocus) {
-  if (!setFocus)
+void CefBrowserPlatformDelegateNativeLinux::SetFocus(bool setFocus) {
+  if (!setFocus) {
     return;
-
-  if (browser_->web_contents()) {
-    // Give logical focus to the RenderWidgetHostViewAura in the views
-    // hierarchy. This does not change the native keyboard focus.
-    browser_->web_contents()->Focus();
   }
 
-#if defined(USE_X11)
+  if (web_contents_) {
+    // Give logical focus to the RenderWidgetHostViewAura in the views
+    // hierarchy. This does not change the native keyboard focus.
+    web_contents_->Focus();
+  }
+
+#if BUILDFLAG(OZONE_PLATFORM_X11)
   if (window_x11_) {
     // Give native focus to the DesktopNativeWidgetAura for the root window.
     // Needs to be done via the ::Window so that keyboard focus is assigned
     // correctly.
     window_x11_->Focus();
   }
-#endif  // defined(USE_X11)
+#endif  // BUILDFLAG(OZONE_PLATFORM_X11)
 }
 
 void CefBrowserPlatformDelegateNativeLinux::NotifyMoveOrResizeStarted() {
   // Call the parent method to dismiss any existing popups.
-  CefBrowserPlatformDelegate::NotifyMoveOrResizeStarted();
+  CefBrowserPlatformDelegateNativeAura::NotifyMoveOrResizeStarted();
 
-#if defined(USE_X11)
-  if (!window_x11_)
+  if (!web_contents_) {
     return;
+  }
 
-  views::DesktopWindowTreeHostX11* tree_host = window_x11_->GetHost();
-  if (!tree_host)
+#if BUILDFLAG(OZONE_PLATFORM_X11)
+  if (!window_x11_) {
     return;
+  }
+
+  views::DesktopWindowTreeHostLinux* tree_host = window_x11_->GetHost();
+  if (!tree_host) {
+    return;
+  }
 
   // Explicitly set the screen bounds so that WindowTreeHost::*Screen()
   // methods return the correct results.
@@ -184,49 +181,32 @@
   // Send updated screen rectangle information to the renderer process so that
   // popups are displayed in the correct location.
   content::RenderWidgetHostImpl::From(
-      browser_->web_contents()->GetRenderViewHost()->GetWidget())
+      web_contents_->GetRenderViewHost()->GetWidget())
       ->SendScreenRects();
-#endif  // defined(USE_X11)
+#endif  // BUILDFLAG(OZONE_PLATFORM_X11)
 }
 
 void CefBrowserPlatformDelegateNativeLinux::SizeTo(int width, int height) {
-#if defined(USE_X11)
+#if BUILDFLAG(OZONE_PLATFORM_X11)
   if (window_x11_) {
     window_x11_->SetBounds(
         gfx::Rect(window_x11_->bounds().origin(), gfx::Size(width, height)));
   }
-#endif  // defined(USE_X11)
-}
-
-gfx::Point CefBrowserPlatformDelegateNativeLinux::GetScreenPoint(
-    const gfx::Point& view) const {
-  if (windowless_handler_)
-    return windowless_handler_->GetParentScreenPoint(view);
-
-#if defined(USE_X11)
-  if (!window_x11_)
-    return view;
-
-  // We can't use aura::Window::GetBoundsInScreen on Linux because it will
-  // return bounds from DesktopWindowTreeHostX11 which in our case is relative
-  // to the parent window instead of the root window (screen).
-  const gfx::Rect& bounds_in_screen = window_x11_->GetBoundsInScreen();
-  return gfx::Point(bounds_in_screen.x() + view.x(),
-                    bounds_in_screen.y() + view.y());
-#endif  // defined(USE_X11)
-  return gfx::Point();
+#endif  // BUILDFLAG(OZONE_PLATFORM_X11)
 }
 
 void CefBrowserPlatformDelegateNativeLinux::ViewText(const std::string& text) {
   char buff[] = "/tmp/CEFSourceXXXXXX";
   int fd = mkstemp(buff);
 
-  if (fd == -1)
+  if (fd == -1) {
     return;
+  }
 
   FILE* srcOutput = fdopen(fd, "w+");
-  if (!srcOutput)
+  if (!srcOutput) {
     return;
+  }
 
   if (fputs(text.c_str(), srcOutput) < 0) {
     fclose(srcOutput);
@@ -237,14 +217,14 @@
 
   std::string newName(buff);
   newName.append(".txt");
-  if (rename(buff, newName.c_str()) != 0)
+  if (rename(buff, newName.c_str()) != 0) {
     return;
+  }
 
   std::string openCommand("xdg-open ");
   openCommand += newName;
 
-  int result = system(openCommand.c_str());
-  ALLOW_UNUSED_LOCAL(result);
+  [[maybe_unused]] int result = system(openCommand.c_str());
 }
 
 bool CefBrowserPlatformDelegateNativeLinux::HandleKeyboardEvent(
@@ -253,9 +233,6 @@
   return false;
 }
 
-// static
-void CefBrowserPlatformDelegate::HandleExternalProtocol(const GURL& url) {}
-
 CefEventHandle CefBrowserPlatformDelegateNativeLinux::GetEventHandle(
     const content::NativeWebKeyboardEvent& event) const {
   // TODO(cef): We need to return an XEvent* from this method, but
@@ -264,22 +241,6 @@
   return nullptr;
 }
 
-std::unique_ptr<CefMenuRunner>
-CefBrowserPlatformDelegateNativeLinux::CreateMenuRunner() {
-  return base::WrapUnique(new CefMenuRunnerLinux);
-}
-
-gfx::Point CefBrowserPlatformDelegateNativeLinux::GetDialogPosition(
-    const gfx::Size& size) {
-  const gfx::Size& max_size = GetMaximumDialogSize();
-  return gfx::Point((max_size.width() - size.width()) / 2,
-                    (max_size.height() - size.height()) / 2);
-}
-
-gfx::Size CefBrowserPlatformDelegateNativeLinux::GetMaximumDialogSize() {
-  return GetWindowWidget()->GetWindowBoundsInScreen().size();
-}
-
 ui::KeyEvent CefBrowserPlatformDelegateNativeLinux::TranslateUiKeyEvent(
     const CefKeyEvent& key_event) const {
   int flags = TranslateUiEventModifiers(key_event.modifiers);
@@ -287,13 +248,20 @@
       static_cast<ui::KeyboardCode>(key_event.windows_key_code);
   ui::DomCode dom_code =
       ui::KeycodeConverter::NativeKeycodeToDomCode(key_event.native_key_code);
+
+#if BUILDFLAG(OZONE_PLATFORM_X11)
   int keysym = ui::XKeysymForWindowsKeyCode(
       key_code, !!(key_event.modifiers & EVENTFLAG_SHIFT_DOWN));
-  base::char16 character = ui::GetUnicodeCharacterFromXKeySym(keysym);
+  char16_t character = ui::GetUnicodeCharacterFromXKeySym(keysym);
+#else
+  char16_t character = key_event.character;
+#endif
+
   base::TimeTicks time_stamp = GetEventTimeStamp();
 
   if (key_event.type == KEYEVENT_CHAR) {
-    return ui::KeyEvent(character, key_code, dom_code, flags, time_stamp);
+    return ui::KeyEvent::FromCharacter(character, key_code, dom_code, flags,
+                                       time_stamp);
   }
 
   ui::EventType type = ui::ET_UNKNOWN;
@@ -306,10 +274,15 @@
       type = ui::ET_KEY_RELEASED;
       break;
     default:
-      NOTREACHED();
+      DCHECK(false);
   }
 
+#if BUILDFLAG(OZONE_PLATFORM_X11)
   ui::DomKey dom_key = ui::XKeySymToDomKey(keysym, character);
+#else
+  ui::DomKey dom_key = ui::DomKey::NONE;
+#endif
+
   return ui::KeyEvent(type, key_code, dom_code, flags, dom_key, time_stamp);
 }
 
@@ -322,8 +295,3 @@
   }
   return content::NativeWebKeyboardEvent(ui_event);
 }
-
-base::TimeTicks CefBrowserPlatformDelegateNativeLinux::GetEventTimeStamp()
-    const {
-  return base::TimeTicks() + base::TimeDelta::FromSeconds(GetSystemUptime());
-}
diff --git a/src/libcef/browser/native/browser_platform_delegate_native_linux.h b/src/libcef/browser/native/browser_platform_delegate_native_linux.h
index 7f1834a..0da0cc8 100644
--- a/src/libcef/browser/native/browser_platform_delegate_native_linux.h
+++ b/src/libcef/browser/native/browser_platform_delegate_native_linux.h
@@ -7,7 +7,9 @@
 
 #include "libcef/browser/native/browser_platform_delegate_native_aura.h"
 
-#if defined(USE_X11)
+#include "ui/ozone/buildflags.h"
+
+#if BUILDFLAG(OZONE_PLATFORM_X11)
 class CefWindowX11;
 #endif
 
@@ -16,43 +18,33 @@
     : public CefBrowserPlatformDelegateNativeAura {
  public:
   CefBrowserPlatformDelegateNativeLinux(const CefWindowInfo& window_info,
-                                        SkColor background_color,
-                                        bool use_external_begin_frame);
+                                        SkColor background_color);
 
   // CefBrowserPlatformDelegate methods:
-  void BrowserDestroyed(CefBrowserHostImpl* browser) override;
+  void BrowserDestroyed(CefBrowserHostBase* browser) override;
   bool CreateHostWindow() override;
   void CloseHostWindow() override;
   CefWindowHandle GetHostWindowHandle() const override;
   views::Widget* GetWindowWidget() const override;
-  void SendFocusEvent(bool setFocus) override;
+  void SetFocus(bool setFocus) override;
   void NotifyMoveOrResizeStarted() override;
   void SizeTo(int width, int height) override;
-  gfx::Point GetScreenPoint(const gfx::Point& view) const override;
   void ViewText(const std::string& text) override;
   bool HandleKeyboardEvent(
       const content::NativeWebKeyboardEvent& event) override;
   CefEventHandle GetEventHandle(
       const content::NativeWebKeyboardEvent& event) const override;
-  std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
-  gfx::Point GetDialogPosition(const gfx::Size& size) override;
-  gfx::Size GetMaximumDialogSize() override;
 
   // CefBrowserPlatformDelegateNativeAura methods:
   ui::KeyEvent TranslateUiKeyEvent(const CefKeyEvent& key_event) const override;
   content::NativeWebKeyboardEvent TranslateWebKeyEvent(
       const CefKeyEvent& key_event) const override;
-  base::TimeTicks GetEventTimeStamp() const override;
 
  private:
   // True if the host window has been created.
-  bool host_window_created_;
+  bool host_window_created_ = false;
 
-  // Widget hosting the web contents. It will be deleted automatically when the
-  // associated root window is destroyed.
-  views::Widget* window_widget_;
-
-#if defined(USE_X11)
+#if BUILDFLAG(OZONE_PLATFORM_X11)
   CefWindowX11* window_x11_ = nullptr;
 #endif
 };
diff --git a/src/libcef/browser/native/browser_platform_delegate_native_mac.h b/src/libcef/browser/native/browser_platform_delegate_native_mac.h
index e421a39..4d88dd8 100644
--- a/src/libcef/browser/native/browser_platform_delegate_native_mac.h
+++ b/src/libcef/browser/native/browser_platform_delegate_native_mac.h
@@ -7,6 +7,12 @@
 
 #include "libcef/browser/native/browser_platform_delegate_native.h"
 
+#if defined(__OBJC__)
+@class CefWindowDelegate;
+#else
+class CefWindowDelegate;
+#endif
+
 namespace content {
 class RenderWidgetHostViewMac;
 }
@@ -19,7 +25,7 @@
                                       SkColor background_color);
 
   // CefBrowserPlatformDelegate methods:
-  void BrowserDestroyed(CefBrowserHostImpl* browser) override;
+  void BrowserDestroyed(CefBrowserHostBase* browser) override;
   bool CreateHostWindow() override;
   void CloseHostWindow() override;
   CefWindowHandle GetHostWindowHandle() const override;
@@ -33,19 +39,17 @@
                            int deltaX,
                            int deltaY) override;
   void SendTouchEvent(const CefTouchEvent& event) override;
-  void SendFocusEvent(bool setFocus) override;
-  gfx::Point GetScreenPoint(const gfx::Point& view) const override;
+  void SetFocus(bool setFocus) override;
+  gfx::Point GetScreenPoint(const gfx::Point& view,
+                            bool want_dip_coords) const override;
   void ViewText(const std::string& text) override;
   bool HandleKeyboardEvent(
       const content::NativeWebKeyboardEvent& event) override;
   CefEventHandle GetEventHandle(
       const content::NativeWebKeyboardEvent& event) const override;
-  std::unique_ptr<CefFileDialogRunner> CreateFileDialogRunner() override;
   std::unique_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner()
       override;
   std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
-  gfx::Point GetDialogPosition(const gfx::Size& size) override;
-  gfx::Size GetMaximumDialogSize() override;
 
   // CefBrowserPlatformDelegateNative methods:
   content::NativeWebKeyboardEvent TranslateWebKeyEvent(
@@ -69,7 +73,9 @@
   content::RenderWidgetHostViewMac* GetHostView() const;
 
   // True if the host window has been created.
-  bool host_window_created_;
+  bool host_window_created_ = false;
+
+  CefWindowDelegate* __strong window_delegate_;
 };
 
 #endif  // CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_MAC_H_
diff --git a/src/libcef/browser/native/browser_platform_delegate_native_mac.mm b/src/libcef/browser/native/browser_platform_delegate_native_mac.mm
index 7a73491..6c9a228 100644
--- a/src/libcef/browser/native/browser_platform_delegate_native_mac.mm
+++ b/src/libcef/browser/native/browser_platform_delegate_native_mac.mm
@@ -7,25 +7,25 @@
 #import <Cocoa/Cocoa.h>
 #import <CoreServices/CoreServices.h>
 
-#include "libcef/browser/browser_host_impl.h"
+#include "include/internal/cef_types_mac.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 #include "libcef/browser/context.h"
-#include "libcef/browser/native/file_dialog_runner_mac.h"
 #include "libcef/browser/native/javascript_dialog_runner_mac.h"
 #include "libcef/browser/native/menu_runner_mac.h"
 #include "libcef/browser/thread_util.h"
 
-#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/apple/owned_objc.h"
+#include "base/apple/scoped_nsautorelease_pool.h"
 #include "base/memory/ptr_util.h"
 #include "base/threading/thread_restrictions.h"
 #include "content/browser/renderer_host/render_widget_host_view_mac.h"
-#include "content/public/browser/native_web_keyboard_event.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/input/native_web_keyboard_event.h"
 #include "third_party/blink/public/common/input/web_input_event.h"
 #include "third_party/blink/public/common/input/web_mouse_event.h"
 #include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
-#import "ui/base/cocoa/cocoa_base_utils.h"
-#import "ui/base/cocoa/underlay_opengl_hosting_window.h"
+#include "ui/display/screen.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/keycodes/keyboard_codes_posix.h"
 #include "ui/gfx/geometry/rect.h"
@@ -34,10 +34,10 @@
 // the view is deleted.
 @interface CefBrowserHostView : NSView {
  @private
-  CefBrowserHostImpl* browser_;  // weak
+  CefBrowserHostBase* browser_;  // weak
 }
 
-@property(nonatomic, assign) CefBrowserHostImpl* browser;
+@property(nonatomic, assign) CefBrowserHostBase* browser;
 
 @end
 
@@ -49,10 +49,8 @@
   if (browser_) {
     // Force the browser to be destroyed and release the reference added in
     // PlatformCreateWindow().
-    browser_->WindowDestroyed();
+    static_cast<AlloyBrowserHostImpl*>(browser_)->WindowDestroyed();
   }
-
-  [super dealloc];
 }
 
 @end
@@ -60,28 +58,24 @@
 // Receives notifications from the browser window. Will delete itself when done.
 @interface CefWindowDelegate : NSObject <NSWindowDelegate> {
  @private
-  CefBrowserHostImpl* browser_;  // weak
-  NSWindow* window_;
+  CefBrowserHostBase* browser_;  // weak
+  NSWindow* __strong window_;
 }
-- (id)initWithWindow:(NSWindow*)window andBrowser:(CefBrowserHostImpl*)browser;
+- (id)initWithWindow:(NSWindow*)window andBrowser:(CefBrowserHostBase*)browser;
 @end
 
 @implementation CefWindowDelegate
 
-- (id)initWithWindow:(NSWindow*)window andBrowser:(CefBrowserHostImpl*)browser {
+- (id)initWithWindow:(NSWindow*)window andBrowser:(CefBrowserHostBase*)browser {
   if (self = [super init]) {
     window_ = window;
     browser_ = browser;
-
-    [window_ setDelegate:self];
   }
   return self;
 }
 
 - (void)dealloc {
   [[NSNotificationCenter defaultCenter] removeObserver:self];
-
-  [super dealloc];
 }
 
 - (BOOL)windowShouldClose:(id)window {
@@ -90,6 +84,11 @@
     return NO;
   }
 
+  // For an NSWindow object, the default is to be released on |close|. We
+  // instead want it to remain valid until all strong references are released
+  // via |cleanup:| and |BrowserDestroyed|.
+  ((NSWindow*)window).releasedWhenClosed = NO;
+
   // Clean ourselves up after clearing the stack of anything that might have the
   // window on it.
   [self performSelectorOnMainThread:@selector(cleanup:)
@@ -102,7 +101,7 @@
 
 - (void)cleanup:(id)window {
   [window_ setDelegate:nil];
-  [self release];
+  window_ = nil;
 }
 
 @end
@@ -111,9 +110,9 @@
 
 NSTimeInterval currentEventTimestamp() {
   NSEvent* currentEvent = [NSApp currentEvent];
-  if (currentEvent)
+  if (currentEvent) {
     return [currentEvent timestamp];
-  else {
+  } else {
     // FIXME(API): In case there is no current event, the timestamp could be
     // obtained by getting the time since the application started. This involves
     // taking some more static functions from Chromium code.
@@ -125,87 +124,186 @@
 
 NSUInteger NativeModifiers(int cef_modifiers) {
   NSUInteger native_modifiers = 0;
-  if (cef_modifiers & EVENTFLAG_SHIFT_DOWN)
-    native_modifiers |= NSShiftKeyMask;
-  if (cef_modifiers & EVENTFLAG_CONTROL_DOWN)
-    native_modifiers |= NSControlKeyMask;
-  if (cef_modifiers & EVENTFLAG_ALT_DOWN)
-    native_modifiers |= NSAlternateKeyMask;
-  if (cef_modifiers & EVENTFLAG_COMMAND_DOWN)
-    native_modifiers |= NSCommandKeyMask;
-  if (cef_modifiers & EVENTFLAG_CAPS_LOCK_ON)
-    native_modifiers |= NSAlphaShiftKeyMask;
-  if (cef_modifiers & EVENTFLAG_NUM_LOCK_ON)
-    native_modifiers |= NSNumericPadKeyMask;
+  if (cef_modifiers & EVENTFLAG_SHIFT_DOWN) {
+    native_modifiers |= NSEventModifierFlagShift;
+  }
+  if (cef_modifiers & EVENTFLAG_CONTROL_DOWN) {
+    native_modifiers |= NSEventModifierFlagControl;
+  }
+  if (cef_modifiers & EVENTFLAG_ALT_DOWN) {
+    native_modifiers |= NSEventModifierFlagOption;
+  }
+  if (cef_modifiers & EVENTFLAG_COMMAND_DOWN) {
+    native_modifiers |= NSEventModifierFlagCommand;
+  }
+  if (cef_modifiers & EVENTFLAG_CAPS_LOCK_ON) {
+    native_modifiers |= NSEventModifierFlagCapsLock;
+  }
+  if (cef_modifiers & EVENTFLAG_NUM_LOCK_ON) {
+    native_modifiers |= NSEventModifierFlagNumericPad;
+  }
 
   return native_modifiers;
 }
 
+constexpr int kDefaultHeight = 750;
+constexpr int kDefaultWidth = 750;
+constexpr NSWindowStyleMask kDefaultStyleMask =
+    NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
+    NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable;
+
+// Keep the frame bounds inside the display work area.
+NSRect ClampNSBoundsToWorkArea(const NSRect& frame_bounds,
+                               const gfx::Rect& display_bounds,
+                               const gfx::Rect& work_area) {
+  NSRect bounds = frame_bounds;
+
+  // Convert from DIP coordinates (top-left origin) to macOS coordinates
+  // (bottom-left origin).
+  const int work_area_y =
+      display_bounds.height() - work_area.height() - work_area.y();
+
+  if (bounds.size.width > work_area.width()) {
+    bounds.size.width = work_area.width();
+  }
+  if (bounds.size.height > work_area.height()) {
+    bounds.size.height = work_area.height();
+  }
+
+  if (bounds.origin.x < work_area.x()) {
+    bounds.origin.x = work_area.x();
+  } else if (bounds.origin.x + bounds.size.width >=
+             work_area.x() + work_area.width()) {
+    bounds.origin.x = work_area.x() + work_area.width() - bounds.size.width;
+  }
+
+  if (bounds.origin.y < work_area_y) {
+    bounds.origin.y = work_area_y;
+  } else if (bounds.origin.y + bounds.size.height >=
+             work_area_y + work_area.height()) {
+    bounds.origin.y = work_area_y + work_area.height() - bounds.size.height;
+  }
+
+  return bounds;
+}
+
+// Get frame and content area rects matching the input DIP screen bounds. The
+// resulting window frame will be kept inside the closest display work area. If
+// |input_content_bounds| is true the input size is used for the content area
+// and the input origin is used for the frame. Otherwise, both input size and
+// origin are used for the frame.
+void GetNSBoundsInDisplay(const gfx::Rect& dip_bounds,
+                          bool input_content_bounds,
+                          NSWindowStyleMask style_mask,
+                          NSRect& frame_rect,
+                          NSRect& content_rect) {
+  // Identify the closest display.
+  const auto display =
+      display::Screen::GetScreen()->GetDisplayMatching(dip_bounds);
+  const auto& display_bounds = display.bounds();
+  const auto& display_work_area = display.work_area();
+
+  // Convert from DIP coordinates (top-left origin) to macOS coordinates
+  // (bottom-left origin).
+  NSRect requested_rect = NSMakeRect(dip_bounds.x(), dip_bounds.y(),
+                                     dip_bounds.width(), dip_bounds.height());
+  requested_rect.origin.y = display_bounds.height() -
+                            requested_rect.size.height -
+                            requested_rect.origin.y;
+
+  // Calculate the equivalent frame and content bounds.
+  if (input_content_bounds) {
+    // Compute frame rect from content rect. Keep the requested origin.
+    content_rect = requested_rect;
+    frame_rect = [NSWindow frameRectForContentRect:content_rect
+                                         styleMask:style_mask];
+    frame_rect.origin = requested_rect.origin;
+  } else {
+    // Compute content rect from frame rect.
+    frame_rect = requested_rect;
+    content_rect = [NSWindow contentRectForFrameRect:frame_rect
+                                           styleMask:style_mask];
+  }
+
+  // Keep the frame inside the display work area.
+  const NSRect new_frame_rect =
+      ClampNSBoundsToWorkArea(frame_rect, display_bounds, display_work_area);
+  if (!NSEqualRects(frame_rect, new_frame_rect)) {
+    frame_rect = new_frame_rect;
+    content_rect = [NSWindow contentRectForFrameRect:frame_rect
+                                           styleMask:style_mask];
+  }
+}
+
 }  // namespace
 
 CefBrowserPlatformDelegateNativeMac::CefBrowserPlatformDelegateNativeMac(
     const CefWindowInfo& window_info,
     SkColor background_color)
-    : CefBrowserPlatformDelegateNative(window_info,
-                                       background_color,
-                                       false,
-                                       false),
-      host_window_created_(false) {}
+    : CefBrowserPlatformDelegateNative(window_info, background_color) {}
 
 void CefBrowserPlatformDelegateNativeMac::BrowserDestroyed(
-    CefBrowserHostImpl* browser) {
-  CefBrowserPlatformDelegate::BrowserDestroyed(browser);
+    CefBrowserHostBase* browser) {
+  CefBrowserPlatformDelegateNative::BrowserDestroyed(browser);
 
   if (host_window_created_) {
-    // Release the reference added in CreateHostWindow().
+    // Release the references added in CreateHostWindow().
     browser->Release();
+    window_delegate_ = nil;
   }
 }
 
 bool CefBrowserPlatformDelegateNativeMac::CreateHostWindow() {
-  base::mac::ScopedNSAutoreleasePool autorelease_pool;
+  base::apple::ScopedNSAutoreleasePool autorelease_pool;
 
-  NSWindow* newWnd = nil;
+  NSWindow* new_window = nil;
 
-  NSView* parentView =
+  NSView* parent_view =
       CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(window_info_.parent_view);
-  NSRect contentRect = {{window_info_.x, window_info_.y},
-                        {window_info_.width, window_info_.height}};
-  if (parentView == nil) {
+  NSRect browser_view_rect =
+      NSMakeRect(window_info_.bounds.x, window_info_.bounds.y,
+                 window_info_.bounds.width, window_info_.bounds.height);
+
+  if (parent_view == nil) {
+    // TODO(port): If no x,y position is specified the window will always appear
+    // in the upper-left corner. Maybe there's a better default place to put it?
+    const gfx::Rect dip_bounds(
+        window_info_.bounds.x, window_info_.bounds.y,
+        window_info_.bounds.width <= 0 ? kDefaultWidth
+                                       : window_info_.bounds.width,
+        window_info_.bounds.height <= 0 ? kDefaultHeight
+                                        : window_info_.bounds.height);
+
+    // Calculate the equivalent frame and content area bounds.
+    NSRect frame_rect, content_rect;
+    GetNSBoundsInDisplay(dip_bounds, /*input_content_bounds=*/true,
+                         kDefaultStyleMask, frame_rect, content_rect);
+
     // Create a new window.
-    NSRect screen_rect = [[NSScreen mainScreen] visibleFrame];
-    NSRect window_rect = {
-        {window_info_.x, screen_rect.size.height - window_info_.y},
-        {window_info_.width, window_info_.height}};
-    if (window_rect.size.width == 0)
-      window_rect.size.width = 750;
-    if (window_rect.size.height == 0)
-      window_rect.size.height = 750;
-
-    contentRect.origin.x = 0;
-    contentRect.origin.y = 0;
-    contentRect.size.width = window_rect.size.width;
-    contentRect.size.height = window_rect.size.height;
-
-    newWnd = [[UnderlayOpenGLHostingWindow alloc]
-        initWithContentRect:window_rect
-                  styleMask:(NSTitledWindowMask | NSClosableWindowMask |
-                             NSMiniaturizableWindowMask |
-                             NSResizableWindowMask |
-                             NSUnifiedTitleAndToolbarWindowMask)
-                    backing:NSBackingStoreBuffered
-                      defer:NO];
+    new_window = [[NSWindow alloc] initWithContentRect:content_rect
+                                             styleMask:kDefaultStyleMask
+                                               backing:NSBackingStoreBuffered
+                                                 defer:NO];
 
     // Create the delegate for control and browser window events.
-    [[CefWindowDelegate alloc] initWithWindow:newWnd andBrowser:browser_];
+    // Add a reference that will be released in BrowserDestroyed().
+    window_delegate_ = [[CefWindowDelegate alloc] initWithWindow:new_window
+                                                      andBrowser:browser_];
+    [new_window setDelegate:window_delegate_];
 
-    parentView = [newWnd contentView];
-    window_info_.parent_view = parentView;
+    parent_view = [new_window contentView];
+    browser_view_rect = [parent_view bounds];
+
+    window_info_.parent_view = CAST_NSVIEW_TO_CEF_WINDOW_HANDLE(parent_view);
 
     // Make the content view for the window have a layer. This will make all
     // sub-views have layers. This is necessary to ensure correct layer
     // ordering of all child views and their layers.
-    [parentView setWantsLayer:YES];
+    [parent_view setWantsLayer:YES];
+
+    // Place the window at the target point. This is required for proper
+    // placement if the point is on a secondary display.
+    [new_window setFrameOrigin:frame_rect.origin];
   }
 
   host_window_created_ = true;
@@ -215,27 +313,25 @@
 
   // Create the browser view.
   CefBrowserHostView* browser_view =
-      [[CefBrowserHostView alloc] initWithFrame:contentRect];
+      [[CefBrowserHostView alloc] initWithFrame:browser_view_rect];
   browser_view.browser = browser_;
-  [parentView addSubview:browser_view];
+  [parent_view addSubview:browser_view];
   [browser_view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
   [browser_view setNeedsDisplay:YES];
-  [browser_view release];
 
-  // Parent the TabContents to the browser view.
+  // Parent the WebContents to the browser view.
   const NSRect bounds = [browser_view bounds];
-  NSView* native_view =
-      browser_->web_contents()->GetNativeView().GetNativeNSView();
+  NSView* native_view = web_contents_->GetNativeView().GetNativeNSView();
   [browser_view addSubview:native_view];
   [native_view setFrame:bounds];
   [native_view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
   [native_view setNeedsDisplay:YES];
 
-  window_info_.view = browser_view;
+  window_info_.view = CAST_NSVIEW_TO_CEF_WINDOW_HANDLE(browser_view);
 
-  if (newWnd != nil && !window_info_.hidden) {
+  if (new_window != nil && !window_info_.hidden) {
     // Show the window.
-    [newWnd makeKeyAndOrderFront:nil];
+    [new_window makeKeyAndOrderFront:nil];
   }
 
   return true;
@@ -252,16 +348,18 @@
 
 CefWindowHandle CefBrowserPlatformDelegateNativeMac::GetHostWindowHandle()
     const {
-  if (windowless_handler_)
+  if (windowless_handler_) {
     return windowless_handler_->GetParentWindowHandle();
+  }
   return window_info_.view;
 }
 
 void CefBrowserPlatformDelegateNativeMac::SendKeyEvent(
     const CefKeyEvent& event) {
   auto view = GetHostView();
-  if (!view)
+  if (!view) {
     return;
+  }
 
   content::NativeWebKeyboardEvent web_event = TranslateWebKeyEvent(event);
   view->ForwardKeyboardEvent(web_event, ui::LatencyInfo());
@@ -273,8 +371,9 @@
     bool mouseUp,
     int clickCount) {
   auto view = GetHostView();
-  if (!view)
+  if (!view) {
     return;
+  }
 
   blink::WebMouseEvent web_event =
       TranslateWebClickEvent(event, type, mouseUp, clickCount);
@@ -285,8 +384,9 @@
     const CefMouseEvent& event,
     bool mouseLeave) {
   auto view = GetHostView();
-  if (!view)
+  if (!view) {
     return;
+  }
 
   blink::WebMouseEvent web_event = TranslateWebMoveEvent(event, mouseLeave);
   view->RouteOrProcessMouseEvent(web_event);
@@ -297,8 +397,9 @@
     int deltaX,
     int deltaY) {
   auto view = GetHostView();
-  if (!view)
+  if (!view) {
     return;
+  }
 
   blink::WebMouseWheelEvent web_event =
       TranslateWebWheelEvent(event, deltaX, deltaY);
@@ -310,33 +411,35 @@
   NOTIMPLEMENTED();
 }
 
-void CefBrowserPlatformDelegateNativeMac::SendFocusEvent(bool setFocus) {
+void CefBrowserPlatformDelegateNativeMac::SetFocus(bool setFocus) {
   auto view = GetHostView();
   if (view) {
     view->SetActive(setFocus);
 
     if (setFocus) {
       // Give keyboard focus to the native view.
-      NSView* view =
-          browser_->web_contents()->GetContentNativeView().GetNativeNSView();
-      DCHECK([view canBecomeKeyView]);
-      [[view window] makeFirstResponder:view];
+      NSView* nsview = web_contents_->GetContentNativeView().GetNativeNSView();
+      DCHECK([nsview canBecomeKeyView]);
+      [[nsview window] makeFirstResponder:nsview];
     }
   }
 }
 
 gfx::Point CefBrowserPlatformDelegateNativeMac::GetScreenPoint(
-    const gfx::Point& view) const {
-  if (windowless_handler_)
-    return windowless_handler_->GetParentScreenPoint(view);
+    const gfx::Point& view,
+    bool want_dip_coords) const {
+  // Mac always operates in DIP coordinates so |want_dip_coords| is ignored.
+  if (windowless_handler_) {
+    return windowless_handler_->GetParentScreenPoint(view, want_dip_coords);
+  }
 
   NSView* nsview = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(window_info_.parent_view);
   if (nsview) {
     NSRect bounds = [nsview bounds];
-    NSPoint view_pt = {view.x(), bounds.size.height - view.y()};
+    NSPoint view_pt = {static_cast<CGFloat>(view.x()),
+                       bounds.size.height - static_cast<CGFloat>(view.y())};
     NSPoint window_pt = [nsview convertPoint:view_pt toView:nil];
-    NSPoint screen_pt =
-        ui::ConvertPointFromWindowToScreen([nsview window], window_pt);
+    NSPoint screen_pt = [[nsview window] convertPointToScreen:window_pt];
     return gfx::Point(screen_pt.x, screen_pt.y);
   }
   return gfx::Point();
@@ -350,22 +453,16 @@
 bool CefBrowserPlatformDelegateNativeMac::HandleKeyboardEvent(
     const content::NativeWebKeyboardEvent& event) {
   // Give the top level menu equivalents a chance to handle the event.
-  if ([event.os_event type] == NSKeyDown)
-    return [[NSApp mainMenu] performKeyEquivalent:event.os_event];
+  NSEvent* ns_event = event.os_event.Get();
+  if (ns_event.type == NSEventTypeKeyDown) {
+    return [[NSApp mainMenu] performKeyEquivalent:ns_event];
+  }
   return false;
 }
 
-// static
-void CefBrowserPlatformDelegate::HandleExternalProtocol(const GURL& url) {}
-
 CefEventHandle CefBrowserPlatformDelegateNativeMac::GetEventHandle(
     const content::NativeWebKeyboardEvent& event) const {
-  return event.os_event;
-}
-
-std::unique_ptr<CefFileDialogRunner>
-CefBrowserPlatformDelegateNativeMac::CreateFileDialogRunner() {
-  return base::WrapUnique(new CefFileDialogRunnerMac);
+  return CAST_NSEVENT_TO_CEF_EVENT_HANDLE(event.os_event.Get());
 }
 
 std::unique_ptr<CefJavaScriptDialogRunner>
@@ -378,25 +475,12 @@
   return base::WrapUnique(new CefMenuRunnerMac);
 }
 
-gfx::Point CefBrowserPlatformDelegateNativeMac::GetDialogPosition(
-    const gfx::Size& size) {
-  // Dialogs are always re-positioned by the constrained window sheet controller
-  // so nothing interesting to return yet.
-  return gfx::Point();
-}
-
-gfx::Size CefBrowserPlatformDelegateNativeMac::GetMaximumDialogSize() {
-  // The dialog should try to fit within the overlay for the web contents.
-  // Note that, for things like print preview, this is just a suggested maximum.
-  return browser_->web_contents()->GetContainerBounds().size();
-}
-
 content::NativeWebKeyboardEvent
 CefBrowserPlatformDelegateNativeMac::TranslateWebKeyEvent(
     const CefKeyEvent& key_event) const {
-  content::NativeWebKeyboardEvent result(blink::WebInputEvent::kUndefined,
-                                         blink::WebInputEvent::kNoModifiers,
-                                         ui::EventTimeForNow());
+  content::NativeWebKeyboardEvent result(
+      blink::WebInputEvent::Type::kUndefined,
+      blink::WebInputEvent::Modifiers::kNoModifiers, ui::EventTimeForNow());
 
   // Use a synthetic NSEvent in order to obtain the windowsKeyCode member from
   // the NativeWebKeyboardEvent constructor. This is the only member which can
@@ -406,29 +490,30 @@
   NSEventType event_type;
   if (key_event.character == 0 && key_event.unmodified_character == 0) {
     // Check if both character and unmodified_characther are empty to determine
-    // if this was a NSFlagsChanged event.
+    // if this was a NSEventTypeFlagsChanged event.
     // A dead key will have an empty character, but a non-empty unmodified
     // character
-    event_type = NSFlagsChanged;
+    event_type = NSEventTypeFlagsChanged;
   } else {
     switch (key_event.type) {
       case KEYEVENT_RAWKEYDOWN:
       case KEYEVENT_KEYDOWN:
       case KEYEVENT_CHAR:
-        event_type = NSKeyDown;
+        event_type = NSEventTypeKeyDown;
         break;
       case KEYEVENT_KEYUP:
-        event_type = NSKeyUp;
+        event_type = NSEventTypeKeyUp;
         break;
     }
   }
 
   NSString* charactersIgnoringModifiers =
-      [[[NSString alloc] initWithCharacters:&key_event.unmodified_character
-                                     length:1] autorelease];
-  NSString* characters =
-      [[[NSString alloc] initWithCharacters:&key_event.character
-                                     length:1] autorelease];
+      [[NSString alloc] initWithCharacters:reinterpret_cast<const unichar*>(
+                                               &key_event.unmodified_character)
+                                    length:1];
+  NSString* characters = [[NSString alloc]
+      initWithCharacters:reinterpret_cast<const unichar*>(&key_event.character)
+                  length:1];
 
   NSEvent* synthetic_event =
       [NSEvent keyEventWithType:event_type
@@ -442,9 +527,11 @@
                             isARepeat:NO
                               keyCode:key_event.native_key_code];
 
-  result = content::NativeWebKeyboardEvent(synthetic_event);
-  if (key_event.type == KEYEVENT_CHAR)
-    result.SetType(blink::WebInputEvent::kChar);
+  result = content::NativeWebKeyboardEvent(
+      base::apple::OwnedNSEvent(synthetic_event));
+  if (key_event.type == KEYEVENT_CHAR) {
+    result.SetType(blink::WebInputEvent::Type::kChar);
+  }
 
   result.is_system_key = key_event.is_system_key;
 
@@ -462,22 +549,22 @@
 
   switch (type) {
     case MBT_LEFT:
-      result.SetType(mouseUp ? blink::WebInputEvent::kMouseUp
-                             : blink::WebInputEvent::kMouseDown);
+      result.SetType(mouseUp ? blink::WebInputEvent::Type::kMouseUp
+                             : blink::WebInputEvent::Type::kMouseDown);
       result.button = blink::WebMouseEvent::Button::kLeft;
       break;
     case MBT_MIDDLE:
-      result.SetType(mouseUp ? blink::WebInputEvent::kMouseUp
-                             : blink::WebInputEvent::kMouseDown);
+      result.SetType(mouseUp ? blink::WebInputEvent::Type::kMouseUp
+                             : blink::WebInputEvent::Type::kMouseDown);
       result.button = blink::WebMouseEvent::Button::kMiddle;
       break;
     case MBT_RIGHT:
-      result.SetType(mouseUp ? blink::WebInputEvent::kMouseUp
-                             : blink::WebInputEvent::kMouseDown);
+      result.SetType(mouseUp ? blink::WebInputEvent::Type::kMouseUp
+                             : blink::WebInputEvent::Type::kMouseDown);
       result.button = blink::WebMouseEvent::Button::kRight;
       break;
     default:
-      NOTREACHED();
+      DCHECK(false);
   }
 
   result.click_count = clickCount;
@@ -492,17 +579,18 @@
   TranslateWebMouseEvent(result, mouse_event);
 
   if (!mouseLeave) {
-    result.SetType(blink::WebInputEvent::kMouseMove);
-    if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON)
+    result.SetType(blink::WebInputEvent::Type::kMouseMove);
+    if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) {
       result.button = blink::WebMouseEvent::Button::kLeft;
-    else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON)
+    } else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) {
       result.button = blink::WebMouseEvent::Button::kMiddle;
-    else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON)
+    } else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) {
       result.button = blink::WebMouseEvent::Button::kRight;
-    else
+    } else {
       result.button = blink::WebMouseEvent::Button::kNoButton;
+    }
   } else {
-    result.SetType(blink::WebInputEvent::kMouseLeave);
+    result.SetType(blink::WebInputEvent::Type::kMouseLeave);
     result.button = blink::WebMouseEvent::Button::kNoButton;
   }
 
@@ -519,7 +607,7 @@
   blink::WebMouseWheelEvent result;
   TranslateWebMouseEvent(result, mouse_event);
 
-  result.SetType(blink::WebInputEvent::kMouseWheel);
+  result.SetType(blink::WebInputEvent::Type::kMouseWheel);
 
   static const double scrollbarPixelsPerCocoaTick = 40.0;
   result.delta_x = deltaX;
@@ -528,14 +616,15 @@
   result.wheel_ticks_y = deltaY / scrollbarPixelsPerCocoaTick;
   result.delta_units = ui::ScrollGranularity::kScrollByPrecisePixel;
 
-  if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON)
+  if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) {
     result.button = blink::WebMouseEvent::Button::kLeft;
-  else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON)
+  } else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) {
     result.button = blink::WebMouseEvent::Button::kMiddle;
-  else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON)
+  } else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) {
     result.button = blink::WebMouseEvent::Button::kRight;
-  else
+  } else {
     result.button = blink::WebMouseEvent::Button::kNoButton;
+  }
 
   return result;
 }
@@ -546,8 +635,8 @@
   // position
   result.SetPositionInWidget(mouse_event.x, mouse_event.y);
 
-  const gfx::Point& screen_pt =
-      GetScreenPoint(gfx::Point(mouse_event.x, mouse_event.y));
+  const gfx::Point& screen_pt = GetScreenPoint(
+      gfx::Point(mouse_event.x, mouse_event.y), /*want_dip_coords=*/true);
   result.SetPositionInScreen(screen_pt.x(), screen_pt.y());
 
   // modifiers
@@ -556,13 +645,16 @@
 
   // timestamp
   result.SetTimeStamp(base::TimeTicks() +
-                      base::TimeDelta::FromSeconds(currentEventTimestamp()));
+                      base::Seconds(currentEventTimestamp()));
 
   result.pointer_type = blink::WebPointerProperties::PointerType::kMouse;
 }
 
 content::RenderWidgetHostViewMac*
 CefBrowserPlatformDelegateNativeMac::GetHostView() const {
+  if (!web_contents_) {
+    return nullptr;
+  }
   return static_cast<content::RenderWidgetHostViewMac*>(
-      browser_->web_contents()->GetRenderWidgetHostView());
+      web_contents_->GetRenderWidgetHostView());
 }
diff --git a/src/libcef/browser/native/browser_platform_delegate_native_win.cc b/src/libcef/browser/native/browser_platform_delegate_native_win.cc
index 30eac2a..705ddb9 100644
--- a/src/libcef/browser/native/browser_platform_delegate_native_win.cc
+++ b/src/libcef/browser/native/browser_platform_delegate_native_win.cc
@@ -8,26 +8,25 @@
 #include <wininet.h>
 #include <winspool.h>
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 #include "libcef/browser/context.h"
-#include "libcef/browser/native/file_dialog_runner_win.h"
-#include "libcef/browser/native/javascript_dialog_runner_win.h"
-#include "libcef/browser/native/menu_runner_win.h"
+#include "libcef/browser/geometry_util.h"
 #include "libcef/browser/native/window_delegate_view.h"
 #include "libcef/browser/thread_util.h"
 
+#include "base/base_paths_win.h"
 #include "base/files/file_util.h"
-#include "base/memory/ref_counted_memory.h"
+#include "base/path_service.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/win/registry.h"
 #include "base/win/win_util.h"
-#include "content/public/browser/native_web_keyboard_event.h"
+#include "content/public/common/input/native_web_keyboard_event.h"
 #include "third_party/blink/public/common/input/web_mouse_event.h"
 #include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
 #include "ui/aura/window.h"
 #include "ui/base/win/shell.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
+#include "ui/display/win/screen_win.h"
 #include "ui/events/keycodes/dom/dom_key.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
 #include "ui/events/keycodes/keyboard_code_conversion_win.h"
@@ -42,103 +41,104 @@
 
 namespace {
 
-void WriteTempFileAndView(scoped_refptr<base::RefCountedString> str) {
+void WriteTempFileAndView(const std::string& data) {
   CEF_REQUIRE_BLOCKING();
 
   base::FilePath tmp_file;
-  if (!base::CreateTemporaryFile(&tmp_file))
+  if (!base::CreateTemporaryFile(&tmp_file)) {
     return;
+  }
 
   // The shell command will look at the file extension to identify the correct
   // program to open.
   tmp_file = tmp_file.AddExtension(L"txt");
 
-  const std::string& data = str->data();
   int write_ct = base::WriteFile(tmp_file, data.c_str(), data.size());
   DCHECK_EQ(static_cast<int>(data.size()), write_ct);
 
   ui::win::OpenFileViaShell(tmp_file);
 }
 
-// According to Mozilla in uriloader/exthandler/win/nsOSHelperAppService.cpp:
-// "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in
-// ShellExecute on long URLs (bug 161357 on bugzilla.mozilla.org). IE 5 and 6
-// support URLS of 2083 chars in length, 2K is safe."
-const int kMaxAddressLengthChars = 2048;
-
-bool HasExternalHandler(const std::string& scheme) {
-  base::win::RegKey key;
-  const std::wstring registry_path =
-      base::ASCIIToUTF16(scheme + "\\shell\\open\\command");
-  key.Open(HKEY_CLASSES_ROOT, registry_path.c_str(), KEY_READ);
-  if (key.Valid()) {
-    DWORD size = 0;
-    key.ReadValue(NULL, NULL, &size, NULL);
-    if (size > 2) {
-      // ShellExecute crashes the process when the command is empty.
-      // We check for "2" because it always returns the trailing NULL.
-      return true;
-    }
-  }
-
-  return false;
+gfx::Rect GetDisplayWorkAreaNearestPoint(gfx::Point dip_point) {
+  const auto display =
+      display::Screen::GetScreen()->GetDisplayNearestPoint(dip_point);
+  // Work area in DIP.
+  return display.work_area();
 }
 
-void ExecuteExternalProtocol(const GURL& url) {
-  CEF_REQUIRE_BLOCKING();
+CefRect GetScreenFrameRectFromDIPContentRect(HWND window,
+                                             gfx::Rect dip_rect,
+                                             DWORD style,
+                                             DWORD ex_style,
+                                             bool has_menu) {
+  // Convert from DIP using a method that can handle multiple displays with
+  // different DPI. If |window| is nullptr the closest display will be used.
+  const auto screen_rect =
+      display::win::ScreenWin::DIPToScreenRect(window, dip_rect);
 
-  if (!HasExternalHandler(url.scheme()))
-    return;
+  RECT rect = {screen_rect.x(), screen_rect.y(),
+               screen_rect.x() + screen_rect.width(),
+               screen_rect.y() + screen_rect.height()};
 
-  const std::string& address = url.spec();
-  if (address.length() > kMaxAddressLengthChars)
-    return;
+  AdjustWindowRectEx(&rect, style, has_menu, ex_style);
 
-  ShellExecuteA(NULL, "open", address.c_str(), NULL, NULL, SW_SHOWNORMAL);
+  // Keep the original origin while potentially increasing the size to include
+  // the frame non-client area.
+  return CefRect(screen_rect.x(), screen_rect.y(), rect.right - rect.left,
+                 rect.bottom - rect.top);
 }
 
-// DPI value for 1x scale factor.
-#define DPI_1X 96.0f
-
-float GetWindowScaleFactor(HWND hwnd) {
-  DCHECK(hwnd);
-
-  if (base::win::IsProcessPerMonitorDpiAware()) {
-    // Let Windows tell us the correct DPI.
-    static auto get_dpi_for_window_func = []() {
-      return reinterpret_cast<decltype(::GetDpiForWindow)*>(
-          GetProcAddress(GetModuleHandle(L"user32.dll"), "GetDpiForWindow"));
-    }();
-    if (get_dpi_for_window_func)
-      return static_cast<float>(get_dpi_for_window_func(hwnd)) / DPI_1X;
+CefRect GetAdjustedScreenFrameRect(CefRect screen_rect,
+                                   DWORD style,
+                                   DWORD ex_style,
+                                   bool has_menu) {
+  // If height or width is not provided let the OS determine the position and
+  // size similar to Chromium behavior. Note that |CW_USEDEFAULT| cannot be
+  // stored in a gfx::Rect due to clamping.
+  if (screen_rect.width == CW_USEDEFAULT ||
+      screen_rect.height == CW_USEDEFAULT) {
+    return CefRect(CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT);
   }
 
-  // Fallback to the monitor that contains the window center point.
-  RECT cr;
-  GetWindowRect(hwnd, &cr);
-  return display::Screen::GetScreen()
-      ->GetDisplayNearestPoint(
-          gfx::Point((cr.right - cr.left) / 2, (cr.bottom - cr.top) / 2))
-      .device_scale_factor();
+  if (screen_rect.x == CW_USEDEFAULT) {
+    screen_rect.x = 0;
+  }
+
+  if (screen_rect.y == CW_USEDEFAULT) {
+    screen_rect.y = 0;
+  }
+
+  // Convert to DIP using a method that can handle multiple displays with
+  // different DPI.
+  const auto dip_rect = display::win::ScreenWin::ScreenToDIPRect(
+      nullptr, gfx::Rect(screen_rect.x, screen_rect.y, screen_rect.width,
+                         screen_rect.height));
+  const auto visible_dip_rect = MakeVisibleOnScreenRect(
+      dip_rect, GetDisplayWorkAreaNearestPoint(dip_rect.origin()));
+
+  return GetScreenFrameRectFromDIPContentRect(
+      /*window=*/nullptr, visible_dip_rect, style, ex_style, has_menu);
 }
 
 }  // namespace
 
 CefBrowserPlatformDelegateNativeWin::CefBrowserPlatformDelegateNativeWin(
     const CefWindowInfo& window_info,
-    SkColor background_color,
-    bool use_shared_texture,
-    bool use_external_begin_frame)
-    : CefBrowserPlatformDelegateNativeAura(window_info,
-                                           background_color,
-                                           use_shared_texture,
-                                           use_external_begin_frame),
-      host_window_created_(false),
-      window_widget_(nullptr) {}
+    SkColor background_color)
+    : CefBrowserPlatformDelegateNativeAura(window_info, background_color) {}
+
+void CefBrowserPlatformDelegateNativeWin::set_widget(
+    views::Widget* widget,
+    CefWindowHandle widget_handle) {
+  DCHECK(!window_widget_);
+  window_widget_ = widget;
+  DCHECK(!window_info_.window);
+  window_info_.window = widget_handle;
+}
 
 void CefBrowserPlatformDelegateNativeWin::BrowserDestroyed(
-    CefBrowserHostImpl* browser) {
-  CefBrowserPlatformDelegate::BrowserDestroyed(browser);
+    CefBrowserHostBase* browser) {
+  CefBrowserPlatformDelegateNativeAura::BrowserDestroyed(browser);
 
   if (host_window_created_) {
     // Release the reference added in CreateHostWindow().
@@ -149,51 +149,65 @@
 bool CefBrowserPlatformDelegateNativeWin::CreateHostWindow() {
   RegisterWindowClass();
 
+  if (window_info_.style == 0) {
+    // Client didn't intialize the CefWindowInfo. Provide reasonable defaults.
+    window_info_.SetAsPopup(nullptr, CefString());
+  }
+
   has_frame_ = !(window_info_.style & WS_CHILD);
 
-  std::wstring windowName(CefString(&window_info_.window_name));
+  const std::wstring windowName(CefString(&window_info_.window_name));
+
+  CefRect window_rect = window_info_.bounds;
+
+  if (!window_info_.parent_window) {
+    const bool has_menu =
+        !(window_info_.style & WS_CHILD) && (window_info_.menu != NULL);
+    window_rect = GetAdjustedScreenFrameRect(window_rect, window_info_.style,
+                                             window_info_.ex_style, has_menu);
+  }
 
   // Create the new browser window.
   CreateWindowEx(window_info_.ex_style, GetWndClass(), windowName.c_str(),
-                 window_info_.style, window_info_.x, window_info_.y,
-                 window_info_.width, window_info_.height,
+                 window_info_.style, window_rect.x, window_rect.y,
+                 window_rect.width, window_rect.height,
                  window_info_.parent_window, window_info_.menu,
                  ::GetModuleHandle(NULL), this);
 
   // It's possible for CreateWindowEx to fail if the parent window was
   // destroyed between the call to CreateBrowser and the above one.
   DCHECK(window_info_.window);
-  if (!window_info_.window)
+  if (!window_info_.window) {
     return false;
+  }
 
   host_window_created_ = true;
 
   // Add a reference that will later be released in DestroyBrowser().
   browser_->AddRef();
 
-  if (!called_enable_non_client_dpi_scaling_ && has_frame_ &&
-      base::win::IsProcessPerMonitorDpiAware()) {
+  if (!called_enable_non_client_dpi_scaling_ && has_frame_) {
     // This call gets Windows to scale the non-client area when WM_DPICHANGED
     // is fired on Windows versions < 10.0.14393.0.
     // Derived signature; not available in headers.
-    static auto enable_child_window_dpi_message_func = []() {
-      using EnableChildWindowDpiMessagePtr = LRESULT(WINAPI*)(HWND, BOOL);
-      return reinterpret_cast<EnableChildWindowDpiMessagePtr>(GetProcAddress(
-          GetModuleHandle(L"user32.dll"), "EnableChildWindowDpiMessage"));
-    }();
-    if (enable_child_window_dpi_message_func)
+    using EnableChildWindowDpiMessagePtr = LRESULT(WINAPI*)(HWND, BOOL);
+    static const auto enable_child_window_dpi_message_func =
+        reinterpret_cast<EnableChildWindowDpiMessagePtr>(
+            base::win::GetUser32FunctionPointer("EnableChildWindowDpiMessage"));
+    if (enable_child_window_dpi_message_func) {
       enable_child_window_dpi_message_func(window_info_.window, TRUE);
+    }
   }
 
   DCHECK(!window_widget_);
 
-  // Convert from device coordinates to logical coordinates.
   RECT cr;
   GetClientRect(window_info_.window, &cr);
-  gfx::Point point = gfx::Point(cr.right, cr.bottom);
-  const float scale = GetWindowScaleFactor(window_info_.window);
-  point =
-      gfx::ToFlooredPoint(gfx::ScalePoint(gfx::PointF(point), 1.0f / scale));
+
+  // Convert to DIP using a method that can handle multiple displays with
+  // different DPI. Client coordinates always have origin (0,0).
+  const gfx::Rect dip_rect = display::win::ScreenWin::ScreenToDIPRect(
+      window_info_.window, gfx::Rect(0, 0, cr.right, cr.bottom));
 
   // Stay on top if top-most window hosting the web view is topmost.
   HWND top_level_window = GetAncestor(window_info_.window, GA_ROOT);
@@ -203,9 +217,10 @@
       (top_level_window_ex_styles & WS_EX_TOPMOST) == WS_EX_TOPMOST;
 
   CefWindowDelegateView* delegate_view = new CefWindowDelegateView(
-      GetBackgroundColor(), always_on_top, GetBoundsChangedCallback());
-  delegate_view->Init(window_info_.window, browser_->web_contents(),
-                      gfx::Rect(0, 0, point.x(), point.y()));
+      GetBackgroundColor(), always_on_top, GetBoundsChangedCallback(),
+      GetWidgetDeleteCallback());
+  delegate_view->Init(window_info_.window, web_contents_,
+                      gfx::Rect(0, 0, dip_rect.width(), dip_rect.height()));
 
   window_widget_ = delegate_view->GetWidget();
 
@@ -241,8 +256,9 @@
 
 CefWindowHandle CefBrowserPlatformDelegateNativeWin::GetHostWindowHandle()
     const {
-  if (windowless_handler_)
+  if (windowless_handler_) {
     return windowless_handler_->GetParentWindowHandle();
+  }
   return window_info_.window;
 }
 
@@ -250,32 +266,48 @@
   return window_widget_;
 }
 
-void CefBrowserPlatformDelegateNativeWin::SendFocusEvent(bool setFocus) {
-  if (!setFocus)
+void CefBrowserPlatformDelegateNativeWin::SetFocus(bool setFocus) {
+  if (!setFocus) {
     return;
-
-  if (browser_->web_contents()) {
-    // Give logical focus to the RenderWidgetHostViewAura in the views
-    // hierarchy. This does not change the native keyboard focus.
-    browser_->web_contents()->Focus();
   }
 
   if (window_widget_) {
-    // Give native focus to the DesktopWindowTreeHostWin associated with the
-    // root window.
+    // Give native focus to the DesktopWindowTreeHostWin ("Chrome_WidgetWin_0")
+    // associated with the root window. The currently focused HWND may be
+    // "CefBrowserWindow" if we're called in response to our WndProc receiving
+    // the WM_SETFOCUS event (possibly due to "CefBrowserWindow" recieving the
+    // top-level WM_ACTIVATE event), or some other HWND if the client calls
+    // CefBrowserHost::SetFocus(true) directly. DesktopWindowTreeHostWin may
+    // also receive focus/blur and mouse click events from the OS directly, in
+    // which case this method will not be called but the below discussion still
+    // applies.
     //
-    // The DesktopWindowTreeHostWin HandleNativeFocus/HandleNativeBlur methods
+    // The DesktopWindowTreeHostWin::HandleNativeFocus/HandleNativeBlur methods
     // are called in response to WM_SETFOCUS/WM_KILLFOCUS respectively. The
-    // implementation has been patched to call HandleActivationChanged which
-    // results in the following behaviors:
+    // DesktopWindowTreeHostWin::HandleMouseEvent method is called if the user
+    // clicks on the WebContents. These methods have all been patched to call
+    // HandleActivationChanged (indirectly via ::SetFocus in the case of mouse
+    // clicks). HandleActivationChanged will then trigger the following
+    // behaviors:
     // 1. Update focus/activation state of the aura::Window indirectly via
     //    wm::FocusController. This allows focus-related behaviors (e.g. focus
     //    rings, flashing caret, onFocus/onBlur JS events, etc.) to work as
-    //    expected (see issue #1677).
+    //    expected (see issue #1677) and also triggers an initial call to
+    //    WebContents::Focus which gives logical focus to the
+    //    RenderWidgetHostViewAura in the views hierarchy (see issue #3306).
     // 2. Update focus state of the ui::InputMethod. If this does not occur
-    //    then InputMethodBase::GetTextInputClient will return NULL and
-    //    InputMethodWin::OnChar will fail to sent character events to the
-    //    renderer (see issue #1700).
+    //    then:
+    //    (a) InputMethodBase::GetTextInputClient will return NULL and
+    //    InputMethodWin::OnChar will fail to send character events to the
+    //    renderer (see issue #1700); and
+    //    (b) InputMethodWinBase::IsWindowFocused will return false due to
+    //    ::GetFocus() returning the currently focused HWND (e.g.
+    //    "CefBrowserWindow") instead of the expected "Chrome_WidgetWin_0" HWND,
+    //    causing TSF not to handle IME events (see issue #3306). For this same
+    //    reason, ::SetFocus needs to be called before WebContents::Focus which
+    //    sends the InputMethod OnWillChangeFocusedClient notification that then
+    //    calls IsWindowFocused (e.g. WebContents::Focus is intentionally called
+    //    multiple times).
     //
     // This differs from activation in Chrome which is handled via
     // HWNDMessageHandler::PostProcessActivateMessage (Widget::Show indirectly
@@ -291,14 +323,24 @@
     // discovered.
     ::SetFocus(HWNDForWidget(window_widget_));
   }
+
+  if (web_contents_) {
+    // Give logical focus to the RenderWidgetHostViewAura in the views
+    // hierarchy. This does not change the native keyboard focus. When
+    // |window_widget_| exists this additional Focus() call is necessary to
+    // correctly assign focus/input state after native focus resulting from
+    // window activation (see the InputMethod discussion above).
+    web_contents_->Focus();
+  }
 }
 
 void CefBrowserPlatformDelegateNativeWin::NotifyMoveOrResizeStarted() {
   // Call the parent method to dismiss any existing popups.
-  CefBrowserPlatformDelegate::NotifyMoveOrResizeStarted();
+  CefBrowserPlatformDelegateNativeAura::NotifyMoveOrResizeStarted();
 
-  if (!window_widget_)
+  if (!window_widget_) {
     return;
+  }
 
   // Notify DesktopWindowTreeHostWin of move events so that screen rectangle
   // information is communicated to the renderer process and popups are
@@ -317,46 +359,20 @@
 void CefBrowserPlatformDelegateNativeWin::SizeTo(int width, int height) {
   HWND window = window_info_.window;
 
-  RECT rect = {0, 0, width, height};
-  DWORD style = GetWindowLong(window, GWL_STYLE);
-  DWORD ex_style = GetWindowLong(window, GWL_EXSTYLE);
-  bool has_menu = !(style & WS_CHILD) && (GetMenu(window) != NULL);
+  const DWORD style = GetWindowLong(window, GWL_STYLE);
+  const DWORD ex_style = GetWindowLong(window, GWL_EXSTYLE);
+  const bool has_menu = !(style & WS_CHILD) && (GetMenu(window) != NULL);
 
-  // The size value is for the client area. Calculate the whole window size
-  // based on the current style.
-  AdjustWindowRectEx(&rect, style, has_menu, ex_style);
+  const auto frame_rect = GetScreenFrameRectFromDIPContentRect(
+      window, gfx::Rect(0, 0, width, height), style, ex_style, has_menu);
 
   // Size the window. The left/top values may be negative.
-  SetWindowPos(window, NULL, 0, 0, rect.right - rect.left,
-               rect.bottom - rect.top,
+  SetWindowPos(window, NULL, 0, 0, frame_rect.width, frame_rect.height,
                SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
 }
 
-gfx::Point CefBrowserPlatformDelegateNativeWin::GetScreenPoint(
-    const gfx::Point& view) const {
-  if (windowless_handler_)
-    return windowless_handler_->GetParentScreenPoint(view);
-
-  if (!window_info_.window)
-    return view;
-
-  // Convert from logical coordinates to device coordinates.
-  const float scale = GetWindowScaleFactor(window_info_.window);
-  const gfx::Point& device_pt =
-      gfx::ToFlooredPoint(gfx::ScalePoint(gfx::PointF(view), scale));
-
-  // Convert from client coordinates to screen coordinates.
-  POINT screen_pt = {device_pt.x(), device_pt.y()};
-  ClientToScreen(window_info_.window, &screen_pt);
-
-  return gfx::Point(screen_pt.x, screen_pt.y);
-}
-
 void CefBrowserPlatformDelegateNativeWin::ViewText(const std::string& text) {
-  std::string str = text;
-  scoped_refptr<base::RefCountedString> str_ref =
-      base::RefCountedString::TakeString(&str);
-  CEF_POST_USER_VISIBLE_TASK(base::Bind(WriteTempFileAndView, str_ref));
+  CEF_POST_USER_VISIBLE_TASK(base::BindOnce(WriteTempFileAndView, text));
 }
 
 bool CefBrowserPlatformDelegateNativeWin::HandleKeyboardEvent(
@@ -364,27 +380,28 @@
   // Any unhandled keyboard/character messages are sent to DefWindowProc so that
   // shortcut keys work correctly.
   if (event.os_event) {
-    const MSG& msg = event.os_event->native_event();
+    const auto& msg = event.os_event->native_event();
     return !DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
   } else {
     MSG msg = {};
 
     msg.hwnd = GetHostWindowHandle();
-    if (!msg.hwnd)
+    if (!msg.hwnd) {
       return false;
+    }
 
     switch (event.GetType()) {
-      case blink::WebInputEvent::kRawKeyDown:
+      case blink::WebInputEvent::Type::kRawKeyDown:
         msg.message = event.is_system_key ? WM_SYSKEYDOWN : WM_KEYDOWN;
         break;
-      case blink::WebInputEvent::kKeyUp:
+      case blink::WebInputEvent::Type::kKeyUp:
         msg.message = event.is_system_key ? WM_SYSKEYUP : WM_KEYUP;
         break;
-      case blink::WebInputEvent::kChar:
+      case blink::WebInputEvent::Type::kChar:
         msg.message = event.is_system_key ? WM_SYSCHAR : WM_CHAR;
         break;
       default:
-        NOTREACHED();
+        DCHECK(false);
         return false;
     }
 
@@ -393,49 +410,21 @@
     UINT scan_code = ::MapVirtualKeyW(event.windows_key_code, MAPVK_VK_TO_VSC);
     msg.lParam = (scan_code << 16) |  // key scan code
                  1;                   // key repeat count
-    if (event.GetModifiers() & content::NativeWebKeyboardEvent::kAltKey)
+    if (event.GetModifiers() & content::NativeWebKeyboardEvent::kAltKey) {
       msg.lParam |= (1 << 29);
+    }
 
     return !DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
   }
 }
 
-// static
-void CefBrowserPlatformDelegate::HandleExternalProtocol(const GURL& url) {
-  CEF_POST_USER_VISIBLE_TASK(base::Bind(ExecuteExternalProtocol, url));
-}
-
 CefEventHandle CefBrowserPlatformDelegateNativeWin::GetEventHandle(
     const content::NativeWebKeyboardEvent& event) const {
-  if (!event.os_event)
+  if (!event.os_event) {
     return NULL;
-  return const_cast<CefEventHandle>(&event.os_event->native_event());
-}
-
-std::unique_ptr<CefFileDialogRunner>
-CefBrowserPlatformDelegateNativeWin::CreateFileDialogRunner() {
-  return base::WrapUnique(new CefFileDialogRunnerWin);
-}
-
-std::unique_ptr<CefJavaScriptDialogRunner>
-CefBrowserPlatformDelegateNativeWin::CreateJavaScriptDialogRunner() {
-  return base::WrapUnique(new CefJavaScriptDialogRunnerWin);
-}
-
-std::unique_ptr<CefMenuRunner>
-CefBrowserPlatformDelegateNativeWin::CreateMenuRunner() {
-  return base::WrapUnique(new CefMenuRunnerWin);
-}
-
-gfx::Point CefBrowserPlatformDelegateNativeWin::GetDialogPosition(
-    const gfx::Size& size) {
-  const gfx::Size& max_size = GetMaximumDialogSize();
-  return gfx::Point((max_size.width() - size.width()) / 2,
-                    (max_size.height() - size.height()) / 2);
-}
-
-gfx::Size CefBrowserPlatformDelegateNativeWin::GetMaximumDialogSize() {
-  return GetWindowWidget()->GetWindowBoundsInScreen().size();
+  }
+  return ChromeToWindowsType(
+      const_cast<CHROME_MSG*>(&event.os_event->native_event()));
 }
 
 ui::KeyEvent CefBrowserPlatformDelegateNativeWin::TranslateUiKeyEvent(
@@ -448,8 +437,8 @@
   base::TimeTicks time_stamp = GetEventTimeStamp();
 
   if (key_event.type == KEYEVENT_CHAR) {
-    return ui::KeyEvent(key_event.windows_key_code /* character */, key_code,
-                        dom_code, flags, time_stamp);
+    return ui::KeyEvent::FromCharacter(/*character=*/key_event.windows_key_code,
+                                       key_code, dom_code, flags, time_stamp);
   }
 
   ui::EventType type = ui::ET_UNKNOWN;
@@ -462,7 +451,7 @@
       type = ui::ET_KEY_RELEASED;
       break;
     default:
-      NOTREACHED();
+      DCHECK(false);
   }
 
   ui::DomKey dom_key =
@@ -493,16 +482,12 @@
   return gfx::Vector2d(scrollDeltaX, scrollDeltaY);
 }
 
-base::TimeTicks CefBrowserPlatformDelegateNativeWin::GetEventTimeStamp() const {
-  return base::TimeTicks() +
-         base::TimeDelta::FromMilliseconds(GetMessageTime());
-}
-
 // static
 void CefBrowserPlatformDelegateNativeWin::RegisterWindowClass() {
   static bool registered = false;
-  if (registered)
+  if (registered) {
     return;
+  }
 
   // Register the window class
   WNDCLASSEX wcex = {
@@ -535,13 +520,14 @@
                                                               WPARAM wParam,
                                                               LPARAM lParam) {
   CefBrowserPlatformDelegateNativeWin* platform_delegate = nullptr;
-  CefBrowserHostImpl* browser = nullptr;
+  CefBrowserHostBase* browser = nullptr;
 
   if (message != WM_NCCREATE) {
     platform_delegate = static_cast<CefBrowserPlatformDelegateNativeWin*>(
         gfx::GetWindowUserData(hwnd));
-    if (platform_delegate)
+    if (platform_delegate) {
       browser = platform_delegate->browser_;
+    }
   }
 
   switch (message) {
@@ -564,15 +550,15 @@
       gfx::SetWindowUserData(hwnd, platform_delegate);
       platform_delegate->window_info_.window = hwnd;
 
-      if (platform_delegate->has_frame_ &&
-          base::win::IsProcessPerMonitorDpiAware()) {
+      if (platform_delegate->has_frame_) {
         // This call gets Windows to scale the non-client area when
         // WM_DPICHANGED is fired on Windows versions >= 10.0.14393.0.
-        static auto enable_non_client_dpi_scaling_func = []() {
-          return reinterpret_cast<decltype(::EnableNonClientDpiScaling)*>(
-              GetProcAddress(GetModuleHandle(L"user32.dll"),
-                             "EnableNonClientDpiScaling"));
-        }();
+        using EnableNonClientDpiScalingPtr =
+            decltype(::EnableNonClientDpiScaling)*;
+        static const auto enable_non_client_dpi_scaling_func =
+            reinterpret_cast<EnableNonClientDpiScalingPtr>(
+                base::win::GetUser32FunctionPointer(
+                    "EnableNonClientDpiScaling"));
         platform_delegate->called_enable_non_client_dpi_scaling_ =
             !!(enable_non_client_dpi_scaling_func &&
                enable_non_client_dpi_scaling_func(hwnd));
@@ -587,7 +573,7 @@
         // Force the browser to be destroyed. This will result in a call to
         // BrowserDestroyed() that will release the reference added in
         // CreateHostWindow().
-        browser->WindowDestroyed();
+        static_cast<AlloyBrowserHostImpl*>(browser)->WindowDestroyed();
       }
       break;
 
@@ -606,16 +592,18 @@
 
     case WM_MOVING:
     case WM_MOVE:
-      if (browser)
+      if (browser) {
         browser->NotifyMoveOrResizeStarted();
+      }
       return 0;
 
     case WM_SETFOCUS:
       // Selecting "Close window" from the task bar menu may send a focus
       // notification even though the window is currently disabled (e.g. while
       // a modal JS dialog is displayed).
-      if (browser && ::IsWindowEnabled(hwnd))
+      if (browser && ::IsWindowEnabled(hwnd)) {
         browser->SetFocus(true);
+      }
       return 0;
 
     case WM_ERASEBKGND:
@@ -631,6 +619,15 @@
                      rect->bottom - rect->top, SWP_NOZORDER | SWP_NOACTIVATE);
       }
       break;
+
+    case WM_ENABLE:
+      if (wParam == TRUE && browser) {
+        // Give focus to the browser after EnableWindow enables this window
+        // (e.g. after a modal dialog is dismissed).
+        browser->SetFocus(true);
+        return 0;
+      }
+      break;
   }
 
   return DefWindowProc(hwnd, message, wParam, lParam);
diff --git a/src/libcef/browser/native/browser_platform_delegate_native_win.h b/src/libcef/browser/native/browser_platform_delegate_native_win.h
index e1dd0a0..6d26b5a 100644
--- a/src/libcef/browser/native/browser_platform_delegate_native_win.h
+++ b/src/libcef/browser/native/browser_platform_delegate_native_win.h
@@ -14,36 +14,29 @@
     : public CefBrowserPlatformDelegateNativeAura {
  public:
   CefBrowserPlatformDelegateNativeWin(const CefWindowInfo& window_info,
-                                      SkColor background_color,
-                                      bool use_shared_texture,
-                                      bool use_external_begin_frame);
+                                      SkColor background_color);
+
+  // Called from chrome_child_window.cc after |widget| is created.
+  void set_widget(views::Widget* widget, CefWindowHandle widget_handle);
 
   // CefBrowserPlatformDelegate methods:
-  void BrowserDestroyed(CefBrowserHostImpl* browser) override;
+  void BrowserDestroyed(CefBrowserHostBase* browser) override;
   bool CreateHostWindow() override;
   void CloseHostWindow() override;
   CefWindowHandle GetHostWindowHandle() const override;
   views::Widget* GetWindowWidget() const override;
-  void SendFocusEvent(bool setFocus) override;
+  void SetFocus(bool setFocus) override;
   void NotifyMoveOrResizeStarted() override;
   void SizeTo(int width, int height) override;
-  gfx::Point GetScreenPoint(const gfx::Point& view) const override;
   void ViewText(const std::string& text) override;
   bool HandleKeyboardEvent(
       const content::NativeWebKeyboardEvent& event) override;
   CefEventHandle GetEventHandle(
       const content::NativeWebKeyboardEvent& event) const override;
-  std::unique_ptr<CefFileDialogRunner> CreateFileDialogRunner() override;
-  std::unique_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner()
-      override;
-  std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
-  gfx::Point GetDialogPosition(const gfx::Size& size) override;
-  gfx::Size GetMaximumDialogSize() override;
 
   // CefBrowserPlatformDelegateNativeAura methods:
   ui::KeyEvent TranslateUiKeyEvent(const CefKeyEvent& key_event) const override;
   gfx::Vector2d GetUiWheelEventOffset(int deltaX, int deltaY) const override;
-  base::TimeTicks GetEventTimeStamp() const override;
 
  private:
   static void RegisterWindowClass();
@@ -54,11 +47,7 @@
                                   LPARAM lParam);
 
   // True if the host window has been created.
-  bool host_window_created_;
-
-  // Widget hosting the web contents. It will be deleted automatically when the
-  // associated root window is destroyed.
-  views::Widget* window_widget_;
+  bool host_window_created_ = false;
 
   bool has_frame_ = false;
   bool called_enable_non_client_dpi_scaling_ = false;
diff --git a/src/libcef/browser/native/cursor_util.cc b/src/libcef/browser/native/cursor_util.cc
new file mode 100644
index 0000000..2fb9204
--- /dev/null
+++ b/src/libcef/browser/native/cursor_util.cc
@@ -0,0 +1,42 @@
+// Copyright 2020 The Chromium Embedded Framework Authors. Portions copyright
+// 2012 The Chromium Authors. All rights reserved. Use of this source code is
+// governed by a BSD-style license that can be found in the LICENSE file.
+
+#include "libcef/browser/native/cursor_util.h"
+
+#include "include/cef_client.h"
+
+#include "ui/base/cursor/mojom/cursor_type.mojom.h"
+
+namespace cursor_util {
+
+bool OnCursorChange(CefRefPtr<CefBrowser> browser,
+                    const ui::Cursor& ui_cursor) {
+  auto client = browser->GetHost()->GetClient();
+  if (!client) {
+    return false;
+  }
+  auto handler = client->GetDisplayHandler();
+  if (!handler) {
+    return false;
+  }
+
+  const cef_cursor_type_t cursor_type =
+      static_cast<cef_cursor_type_t>(ui_cursor.type());
+  CefCursorInfo custom_cursor_info;
+  if (ui_cursor.type() == ui::mojom::CursorType::kCustom) {
+    custom_cursor_info.hotspot.x = ui_cursor.custom_hotspot().x();
+    custom_cursor_info.hotspot.y = ui_cursor.custom_hotspot().y();
+    custom_cursor_info.image_scale_factor = ui_cursor.image_scale_factor();
+    custom_cursor_info.buffer = ui_cursor.custom_bitmap().getPixels();
+    custom_cursor_info.size.width = ui_cursor.custom_bitmap().width();
+    custom_cursor_info.size.height = ui_cursor.custom_bitmap().height();
+  }
+
+  auto scoped_cursor_handle(ScopedCursorHandle::Create(browser, ui_cursor));
+  return handler->OnCursorChange(browser,
+                                 scoped_cursor_handle->GetCursorHandle(),
+                                 cursor_type, custom_cursor_info);
+}
+
+}  // namespace cursor_util
diff --git a/src/libcef/browser/native/cursor_util.h b/src/libcef/browser/native/cursor_util.h
new file mode 100644
index 0000000..629d0fa
--- /dev/null
+++ b/src/libcef/browser/native/cursor_util.h
@@ -0,0 +1,38 @@
+// Copyright 2020 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_NATIVE_CURSOR_UTIL_H_
+#define CEF_LIBCEF_BROWSER_NATIVE_CURSOR_UTIL_H_
+
+#include "include/cef_browser.h"
+
+#include <memory>
+
+#include "ui/base/cursor/cursor.h"
+#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
+
+#if defined(USE_AURA)
+#include "ui/base/cursor/platform_cursor.h"
+#endif
+
+namespace cursor_util {
+
+// Scoped ownership of a native cursor handle.
+class ScopedCursorHandle {
+ public:
+  virtual ~ScopedCursorHandle() = default;
+
+  static std::unique_ptr<ScopedCursorHandle> Create(
+      CefRefPtr<CefBrowser> browser,
+      const ui::Cursor& ui_cursor);
+
+  virtual cef_cursor_handle_t GetCursorHandle() = 0;
+};
+
+// Returns true if the client handled the cursor change.
+bool OnCursorChange(CefRefPtr<CefBrowser> browser, const ui::Cursor& ui_cursor);
+
+}  // namespace cursor_util
+
+#endif  // CEF_LIBCEF_BROWSER_NATIVE_CURSOR_UTIL_H_
diff --git a/src/libcef/browser/native/cursor_util_aura.cc b/src/libcef/browser/native/cursor_util_aura.cc
new file mode 100644
index 0000000..894f7bd
--- /dev/null
+++ b/src/libcef/browser/native/cursor_util_aura.cc
@@ -0,0 +1,155 @@
+// Copyright 2023 The Chromium Embedded Framework Authors. Portions copyright
+// 2012 The Chromium Authors. All rights reserved. Use of this source code is
+// governed by a BSD-style license that can be found in the LICENSE file.
+
+#include "libcef/browser/native/cursor_util.h"
+
+#include "libcef/browser/browser_host_base.h"
+
+#include "content/common/cursors/webcursor.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "ui/base/cursor/cursor_factory.h"
+#include "ui/base/cursor/mojom/cursor_type.mojom.h"
+#include "ui/display/display.h"
+#include "ui/display/display_util.h"
+#include "ui/display/screen.h"
+#include "ui/wm/core/cursor_loader.h"
+
+#if BUILDFLAG(IS_LINUX)
+#include "ui/ozone/buildflags.h"
+#if BUILDFLAG(OZONE_PLATFORM_X11)
+#include "ui/base/x/x11_cursor.h"
+#elif BUILDFLAG(IS_OZONE)
+#include "ui/ozone/common/bitmap_cursor.h"
+#endif
+#endif  // BUILDFLAG(IS_LINUX)
+
+#if BUILDFLAG(IS_WIN)
+#include "ui/base/win/win_cursor.h"
+#endif
+
+namespace cursor_util {
+
+namespace {
+
+display::Display::Rotation OrientationAngleToRotation(
+    uint16_t orientation_angle) {
+  // The Display rotation and the ScreenInfo orientation are not the same
+  // angle. The former is the physical display rotation while the later is the
+  // rotation required by the content to be shown properly on the screen, in
+  // other words, relative to the physical display.
+  if (orientation_angle == 0) {
+    return display::Display::ROTATE_0;
+  }
+  if (orientation_angle == 90) {
+    return display::Display::ROTATE_270;
+  }
+  if (orientation_angle == 180) {
+    return display::Display::ROTATE_180;
+  }
+  if (orientation_angle == 270) {
+    return display::Display::ROTATE_90;
+  }
+  DCHECK(false);
+  return display::Display::ROTATE_0;
+}
+
+// It would be better if CursorLoader took a ScreenInfo argument.
+// See https://crbug.com/1149906#c33.
+display::Display GetDisplay(CefRefPtr<CefBrowser> browser) {
+  if (auto web_contents =
+          static_cast<CefBrowserHostBase*>(browser.get())->GetWebContents()) {
+    if (auto view = web_contents->GetRenderWidgetHostView()) {
+      // Windowless browsers always return nullptr from GetNativeView().
+      if (auto native_view = view->GetNativeView()) {
+        return display::Screen::GetScreen()->GetDisplayNearestView(native_view);
+      }
+
+      // Make a minimal-effort fake Display object to satisfy the actual usage
+      // by CursorLoader::SetDisplay.
+      display::Display fake_display;
+      auto screen_info = view->GetScreenInfo();
+      fake_display.set_device_scale_factor(screen_info.device_scale_factor);
+      fake_display.set_rotation(
+          OrientationAngleToRotation(screen_info.orientation_angle));
+      return fake_display;
+    }
+  }
+
+  return display::Display::GetDefaultDisplay();
+}
+
+scoped_refptr<ui::PlatformCursor> ToPlatformCursor(
+    CefRefPtr<CefBrowser> browser,
+    const ui::Cursor& ui_cursor) {
+  wm::CursorLoader cursor_loader;
+  scoped_refptr<ui::PlatformCursor> platform_cursor;
+
+  ui::Cursor loaded_cursor = ui_cursor;
+
+  if (ui_cursor.type() == ui::mojom::CursorType::kCustom) {
+    platform_cursor = ui::CursorFactory::GetInstance()->CreateImageCursor(
+        ui::mojom::CursorType::kCustom, ui_cursor.custom_bitmap(),
+        ui_cursor.custom_hotspot(), ui_cursor.image_scale_factor());
+  } else {
+    cursor_loader.SetDisplay(GetDisplay(browser));
+
+    // Attempts to load the cursor via the platform or from pak resources.
+    cursor_loader.SetPlatformCursor(&loaded_cursor);
+    platform_cursor = loaded_cursor.platform();
+  }
+
+  return platform_cursor;
+}
+
+#if BUILDFLAG(IS_WIN)
+using CursorType = ui::WinCursor;
+inline cef_cursor_handle_t GetCursorHandleImpl(CursorType* cursor) {
+  return cursor->hcursor();
+}
+#elif BUILDFLAG(OZONE_PLATFORM_X11)
+// See https://crbug.com/1029142 for background.
+using CursorType = ui::X11Cursor;
+inline cef_cursor_handle_t GetCursorHandleImpl(CursorType* cursor) {
+  return static_cast<cef_cursor_handle_t>(cursor->xcursor());
+}
+#elif BUILDFLAG(IS_OZONE)
+using CursorType = ui::BitmapCursor;
+inline cef_cursor_handle_t GetCursorHandleImpl(CursorType* cursor) {
+  return static_cast<cef_cursor_handle_t>(cursor->platform_data());
+}
+#else
+#error Unsupported platform
+#endif
+
+class ScopedCursorHandleImpl : public ScopedCursorHandle {
+ public:
+  explicit ScopedCursorHandleImpl(
+      scoped_refptr<ui::PlatformCursor> platform_cursor) {
+    if (platform_cursor) {
+      cursor_ = CursorType::FromPlatformCursor(platform_cursor);
+    }
+  }
+
+  cef_cursor_handle_t GetCursorHandle() override {
+    if (cursor_) {
+      return GetCursorHandleImpl(cursor_.get());
+    }
+    return kNullCursorHandle;
+  }
+
+ private:
+  scoped_refptr<CursorType> cursor_;
+};
+
+}  // namespace
+
+// static
+std::unique_ptr<ScopedCursorHandle> ScopedCursorHandle::Create(
+    CefRefPtr<CefBrowser> browser,
+    const ui::Cursor& ui_cursor) {
+  return std::make_unique<ScopedCursorHandleImpl>(
+      ToPlatformCursor(browser, ui_cursor));
+}
+
+}  // namespace cursor_util
diff --git a/src/libcef/browser/native/cursor_util_mac.mm b/src/libcef/browser/native/cursor_util_mac.mm
new file mode 100644
index 0000000..18df8a6
--- /dev/null
+++ b/src/libcef/browser/native/cursor_util_mac.mm
@@ -0,0 +1,40 @@
+// Copyright 2023 The Chromium Embedded Framework 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 "include/internal/cef_types_mac.h"
+#include "libcef/browser/native/cursor_util.h"
+
+#import "ui/base/cocoa/cursor_utils.h"
+
+namespace cursor_util {
+
+namespace {
+
+class ScopedCursorHandleImpl : public ScopedCursorHandle {
+ public:
+  explicit ScopedCursorHandleImpl(NSCursor* native_cursor) {
+    if (native_cursor) {
+      cursor_ = native_cursor;
+    }
+  }
+
+  cef_cursor_handle_t GetCursorHandle() override {
+    return CAST_NSCURSOR_TO_CEF_CURSOR_HANDLE(cursor_);
+  }
+
+ private:
+  NSCursor* __strong cursor_;
+};
+
+}  // namespace
+
+// static
+std::unique_ptr<ScopedCursorHandle> ScopedCursorHandle::Create(
+    CefRefPtr<CefBrowser> /*browser*/,
+    const ui::Cursor& ui_cursor) {
+  return std::make_unique<ScopedCursorHandleImpl>(
+      ui::GetNativeCursor(ui_cursor));
+}
+
+}  // namespace cursor_util
diff --git a/src/libcef/browser/native/file_dialog_runner_mac.h b/src/libcef/browser/native/file_dialog_runner_mac.h
deleted file mode 100644
index 4fa8fdc..0000000
--- a/src/libcef/browser/native/file_dialog_runner_mac.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_BROWSER_NATIVE_FILE_DIALOG_RUNNER_MAC_H_
-#define CEF_LIBCEF_BROWSER_NATIVE_FILE_DIALOG_RUNNER_MAC_H_
-#pragma once
-
-#include "libcef/browser/file_dialog_runner.h"
-
-#include "base/memory/weak_ptr.h"
-
-@class NSView;
-
-class CefFileDialogRunnerMac : public CefFileDialogRunner {
- public:
-  CefFileDialogRunnerMac();
-
-  // CefFileDialogRunner methods:
-  void Run(CefBrowserHostImpl* browser,
-           const FileChooserParams& params,
-           RunFileChooserCallback callback) override;
-
- private:
-  static void RunOpenFileDialog(
-      base::WeakPtr<CefFileDialogRunnerMac> weak_this,
-      const CefFileDialogRunner::FileChooserParams& params,
-      NSView* view,
-      int filter_index);
-  static void RunSaveFileDialog(
-      base::WeakPtr<CefFileDialogRunnerMac> weak_this,
-      const CefFileDialogRunner::FileChooserParams& params,
-      NSView* view,
-      int filter_index);
-
-  CefFileDialogRunner::RunFileChooserCallback callback_;
-  base::WeakPtrFactory<CefFileDialogRunnerMac> weak_ptr_factory_;
-};
-
-#endif  // CEF_LIBCEF_BROWSER_NATIVE_FILE_DIALOG_RUNNER_MAC_H_
diff --git a/src/libcef/browser/native/file_dialog_runner_mac.mm b/src/libcef/browser/native/file_dialog_runner_mac.mm
deleted file mode 100644
index 25ffa1a..0000000
--- a/src/libcef/browser/native/file_dialog_runner_mac.mm
+++ /dev/null
@@ -1,406 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/native/file_dialog_runner_mac.h"
-
-#import <Cocoa/Cocoa.h>
-#import <CoreServices/CoreServices.h>
-
-#include "libcef/browser/browser_host_impl.h"
-
-#include "base/mac/mac_util.h"
-#include "base/stl_util.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_restrictions.h"
-#include "cef/grit/cef_strings.h"
-#include "chrome/grit/generated_resources.h"
-#include "net/base/mime_util.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/strings/grit/ui_strings.h"
-
-namespace {
-
-base::string16 GetDescriptionFromMimeType(const std::string& mime_type) {
-  // Check for wild card mime types and return an appropriate description.
-  static const struct {
-    const char* mime_type;
-    int string_id;
-  } kWildCardMimeTypes[] = {
-      {"audio", IDS_AUDIO_FILES},
-      {"image", IDS_IMAGE_FILES},
-      {"text", IDS_TEXT_FILES},
-      {"video", IDS_VIDEO_FILES},
-  };
-
-  for (size_t i = 0; i < base::size(kWildCardMimeTypes); ++i) {
-    if (mime_type == std::string(kWildCardMimeTypes[i].mime_type) + "/*")
-      return l10n_util::GetStringUTF16(kWildCardMimeTypes[i].string_id);
-  }
-
-  return base::string16();
-}
-
-void AddFilters(NSPopUpButton* button,
-                const std::vector<base::string16>& accept_filters,
-                bool include_all_files,
-                std::vector<std::vector<base::string16>>* all_extensions) {
-  for (size_t i = 0; i < accept_filters.size(); ++i) {
-    const base::string16& filter = accept_filters[i];
-    if (filter.empty())
-      continue;
-
-    std::vector<base::string16> extensions;
-    base::string16 description;
-
-    size_t sep_index = filter.find('|');
-    if (sep_index != std::string::npos) {
-      // Treat as a filter of the form "Filter Name|.ext1;.ext2;.ext3".
-      description = filter.substr(0, sep_index);
-
-      const std::vector<base::string16>& ext = base::SplitString(
-          filter.substr(sep_index + 1), base::ASCIIToUTF16(";"),
-          base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
-      for (size_t x = 0; x < ext.size(); ++x) {
-        const base::string16& file_ext = ext[x];
-        if (!file_ext.empty() && file_ext[0] == '.')
-          extensions.push_back(file_ext);
-      }
-    } else if (filter[0] == '.') {
-      // Treat as an extension beginning with the '.' character.
-      extensions.push_back(filter);
-    } else {
-      // Otherwise convert mime type to one or more extensions.
-      const std::string& ascii = base::UTF16ToASCII(filter);
-      std::vector<base::FilePath::StringType> ext;
-      net::GetExtensionsForMimeType(ascii, &ext);
-      if (!ext.empty()) {
-        for (size_t x = 0; x < ext.size(); ++x)
-          extensions.push_back(base::ASCIIToUTF16("." + ext[x]));
-        description = GetDescriptionFromMimeType(ascii);
-      }
-    }
-
-    if (extensions.empty())
-      continue;
-
-    // Don't display a crazy number of extensions since the NSPopUpButton width
-    // will keep growing.
-    const size_t kMaxExtensions = 10;
-
-    base::string16 ext_str;
-    for (size_t x = 0; x < std::min(kMaxExtensions, extensions.size()); ++x) {
-      const base::string16& pattern = base::ASCIIToUTF16("*") + extensions[x];
-      if (x != 0)
-        ext_str += base::ASCIIToUTF16(";");
-      ext_str += pattern;
-    }
-
-    if (extensions.size() > kMaxExtensions)
-      ext_str += base::ASCIIToUTF16(";...");
-
-    if (description.empty()) {
-      description = ext_str;
-    } else {
-      description +=
-          base::ASCIIToUTF16(" (") + ext_str + base::ASCIIToUTF16(")");
-    }
-
-    [button addItemWithTitle:base::SysUTF16ToNSString(description)];
-
-    all_extensions->push_back(extensions);
-  }
-
-  // Add the *.* filter, but only if we have added other filters (otherwise it
-  // is implied).
-  if (include_all_files && !all_extensions->empty()) {
-    [button addItemWithTitle:base::SysUTF8ToNSString("All Files (*)")];
-    all_extensions->push_back(std::vector<base::string16>());
-  }
-}
-
-}  // namespace
-
-// Used to manage the file type filter in the NSSavePanel/NSOpenPanel.
-@interface CefFilterDelegate : NSObject {
- @private
-  NSSavePanel* panel_;
-  std::vector<std::vector<base::string16>> extensions_;
-  int selected_index_;
-}
-- (id)initWithPanel:(NSSavePanel*)panel
-    andAcceptFilters:(const std::vector<base::string16>&)accept_filters
-      andFilterIndex:(int)index;
-- (void)setFilter:(int)index;
-- (int)filter;
-- (void)filterSelectionChanged:(id)sender;
-- (void)setFileExtension;
-@end
-
-@implementation CefFilterDelegate
-
-- (id)initWithPanel:(NSSavePanel*)panel
-    andAcceptFilters:(const std::vector<base::string16>&)accept_filters
-      andFilterIndex:(int)index {
-  if (self = [super init]) {
-    DCHECK(panel);
-    panel_ = panel;
-    selected_index_ = 0;
-
-    NSPopUpButton* button = [[NSPopUpButton alloc] init];
-    AddFilters(button, accept_filters, true, &extensions_);
-    [button sizeToFit];
-    [button setTarget:self];
-    [button setAction:@selector(filterSelectionChanged:)];
-
-    if (index < static_cast<int>(extensions_.size())) {
-      [button selectItemAtIndex:index];
-      [self setFilter:index];
-    }
-
-    [panel_ setAccessoryView:button];
-  }
-  return self;
-}
-
-// Set the current filter index.
-- (void)setFilter:(int)index {
-  DCHECK(index >= 0 && index < static_cast<int>(extensions_.size()));
-  selected_index_ = index;
-
-  // Set the selectable file types. For open panels this limits the files that
-  // can be selected. For save panels this applies a default file extenion when
-  // the dialog is dismissed if none is already provided.
-  NSMutableArray* acceptArray = nil;
-  if (!extensions_[index].empty()) {
-    acceptArray = [[NSMutableArray alloc] init];
-    for (size_t i = 0; i < extensions_[index].size(); ++i) {
-      [acceptArray
-          addObject:base::SysUTF16ToNSString(extensions_[index][i].substr(1))];
-    }
-  }
-  [panel_ setAllowedFileTypes:acceptArray];
-
-  if (![panel_ isKindOfClass:[NSOpenPanel class]]) {
-    // For save panels set the file extension.
-    [self setFileExtension];
-  }
-}
-
-// Returns the current filter index.
-- (int)filter {
-  return selected_index_;
-}
-
-// Called when the selected filter is changed via the NSPopUpButton.
-- (void)filterSelectionChanged:(id)sender {
-  NSPopUpButton* button = (NSPopUpButton*)sender;
-  [self setFilter:[button indexOfSelectedItem]];
-}
-
-// Set the extension on the currently selected file name.
-- (void)setFileExtension {
-  const std::vector<base::string16>& filter = extensions_[selected_index_];
-  if (filter.empty()) {
-    // All extensions are allowed so don't change anything.
-    return;
-  }
-
-  base::FilePath path(base::SysNSStringToUTF8([panel_ nameFieldStringValue]));
-
-  // If the file name currently includes an extension from |filter| then don't
-  // change anything.
-  base::string16 extension = base::UTF8ToUTF16(path.Extension());
-  if (!extension.empty()) {
-    for (size_t i = 0; i < filter.size(); ++i) {
-      if (filter[i] == extension)
-        return;
-    }
-  }
-
-  // Change the extension to the first value in |filter|.
-  path = path.ReplaceExtension(base::UTF16ToUTF8(filter[0]));
-  [panel_ setNameFieldStringValue:base::SysUTF8ToNSString(path.value())];
-}
-
-@end
-
-CefFileDialogRunnerMac::CefFileDialogRunnerMac() : weak_ptr_factory_(this) {}
-
-void CefFileDialogRunnerMac::Run(CefBrowserHostImpl* browser,
-                                 const FileChooserParams& params,
-                                 RunFileChooserCallback callback) {
-  callback_ = std::move(callback);
-
-  int filter_index = params.selected_accept_filter;
-  NSView* owner = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(browser->GetWindowHandle());
-  auto weak_this = weak_ptr_factory_.GetWeakPtr();
-
-  if (params.mode == blink::mojom::FileChooserParams::Mode::kOpen ||
-      params.mode == blink::mojom::FileChooserParams::Mode::kOpenMultiple ||
-      params.mode == blink::mojom::FileChooserParams::Mode::kUploadFolder) {
-    RunOpenFileDialog(weak_this, params, owner, filter_index);
-  } else if (params.mode == blink::mojom::FileChooserParams::Mode::kSave) {
-    RunSaveFileDialog(weak_this, params, owner, filter_index);
-  } else {
-    NOTIMPLEMENTED();
-  }
-}
-
-// static
-void CefFileDialogRunnerMac::RunOpenFileDialog(
-    base::WeakPtr<CefFileDialogRunnerMac> weak_this,
-    const CefFileDialogRunner::FileChooserParams& params,
-    NSView* view,
-    int filter_index) {
-  NSOpenPanel* openPanel = [NSOpenPanel openPanel];
-
-  base::string16 title;
-  if (!params.title.empty()) {
-    title = params.title;
-  } else {
-    title = l10n_util::GetStringUTF16(
-        params.mode == blink::mojom::FileChooserParams::Mode::kOpen
-            ? IDS_OPEN_FILE_DIALOG_TITLE
-            : (params.mode ==
-                       blink::mojom::FileChooserParams::Mode::kOpenMultiple
-                   ? IDS_OPEN_FILES_DIALOG_TITLE
-                   : IDS_SELECT_FOLDER_DIALOG_TITLE));
-  }
-  [openPanel setTitle:base::SysUTF16ToNSString(title)];
-
-  std::string filename, directory;
-  if (!params.default_file_name.empty()) {
-    if (params.mode == blink::mojom::FileChooserParams::Mode::kUploadFolder ||
-        params.default_file_name.EndsWithSeparator()) {
-      // The value is only a directory.
-      directory = params.default_file_name.value();
-    } else {
-      // The value is a file name and possibly a directory.
-      filename = params.default_file_name.BaseName().value();
-      directory = params.default_file_name.DirName().value();
-    }
-  }
-  if (!filename.empty()) {
-    [openPanel setNameFieldStringValue:base::SysUTF8ToNSString(filename)];
-  }
-  if (!directory.empty()) {
-    [openPanel setDirectoryURL:[NSURL fileURLWithPath:base::SysUTF8ToNSString(
-                                                          directory)]];
-  }
-
-  CefFilterDelegate* filter_delegate = nil;
-  if (params.mode != blink::mojom::FileChooserParams::Mode::kUploadFolder &&
-      !params.accept_types.empty()) {
-    // Add the file filter control.
-    filter_delegate =
-        [[CefFilterDelegate alloc] initWithPanel:openPanel
-                                andAcceptFilters:params.accept_types
-                                  andFilterIndex:filter_index];
-  }
-
-  // Further panel configuration.
-  [openPanel setAllowsOtherFileTypes:YES];
-  [openPanel setAllowsMultipleSelection:
-                 (params.mode ==
-                  blink::mojom::FileChooserParams::Mode::kOpenMultiple)];
-  [openPanel
-      setCanChooseFiles:(params.mode !=
-                         blink::mojom::FileChooserParams::Mode::kUploadFolder)];
-  [openPanel
-      setCanChooseDirectories:(params.mode == blink::mojom::FileChooserParams::
-                                                  Mode::kUploadFolder)];
-  [openPanel setShowsHiddenFiles:!params.hidereadonly];
-
-  // Show panel.
-  [openPanel
-      beginSheetModalForWindow:[view window]
-             completionHandler:^(NSInteger returnCode) {
-               int filter_index_to_use = (filter_delegate != nil)
-                                             ? [filter_delegate filter]
-                                             : filter_index;
-               if (returnCode == NSFileHandlingPanelOKButton) {
-                 std::vector<base::FilePath> files;
-                 files.reserve(openPanel.URLs.count);
-                 for (NSURL* url in openPanel.URLs) {
-                   if (url.isFileURL)
-                     files.push_back(base::FilePath(url.path.UTF8String));
-                 }
-                 std::move(weak_this->callback_)
-                     .Run(filter_index_to_use, files);
-               } else {
-                 std::move(weak_this->callback_)
-                     .Run(filter_index_to_use, std::vector<base::FilePath>());
-               }
-             }];
-}
-
-// static
-void CefFileDialogRunnerMac::RunSaveFileDialog(
-    base::WeakPtr<CefFileDialogRunnerMac> weak_this,
-    const CefFileDialogRunner::FileChooserParams& params,
-    NSView* view,
-    int filter_index) {
-  NSSavePanel* savePanel = [NSSavePanel savePanel];
-
-  base::string16 title;
-  if (!params.title.empty())
-    title = params.title;
-  else
-    title = l10n_util::GetStringUTF16(IDS_SAVE_AS_DIALOG_TITLE);
-  [savePanel setTitle:base::SysUTF16ToNSString(title)];
-
-  std::string filename, directory;
-  if (!params.default_file_name.empty()) {
-    if (params.default_file_name.EndsWithSeparator()) {
-      // The value is only a directory.
-      directory = params.default_file_name.value();
-    } else {
-      // The value is a file name and possibly a directory.
-      filename = params.default_file_name.BaseName().value();
-      directory = params.default_file_name.DirName().value();
-    }
-  }
-  if (!filename.empty()) {
-    [savePanel setNameFieldStringValue:base::SysUTF8ToNSString(filename)];
-  }
-  if (!directory.empty()) {
-    [savePanel setDirectoryURL:[NSURL fileURLWithPath:base::SysUTF8ToNSString(
-                                                          directory)]];
-  }
-
-  CefFilterDelegate* filter_delegate = nil;
-  if (!params.accept_types.empty()) {
-    // Add the file filter control.
-    filter_delegate =
-        [[CefFilterDelegate alloc] initWithPanel:savePanel
-                                andAcceptFilters:params.accept_types
-                                  andFilterIndex:filter_index];
-  }
-
-  [savePanel setAllowsOtherFileTypes:YES];
-  [savePanel setShowsHiddenFiles:!params.hidereadonly];
-
-  // Show panel.
-  [savePanel
-      beginSheetModalForWindow:view.window
-             completionHandler:^(NSInteger resultCode) {
-               int filter_index_to_use = (filter_delegate != nil)
-                                             ? [filter_delegate filter]
-                                             : filter_index;
-               if (resultCode == NSFileHandlingPanelOKButton) {
-                 NSURL* url = savePanel.URL;
-                 const char* path = url.path.UTF8String;
-                 std::vector<base::FilePath> files(1, base::FilePath(path));
-                 std::move(weak_this->callback_)
-                     .Run(filter_index_to_use, files);
-               } else {
-                 std::move(weak_this->callback_)
-                     .Run(filter_index_to_use, std::vector<base::FilePath>());
-               }
-             }];
-}
diff --git a/src/libcef/browser/native/file_dialog_runner_win.cc b/src/libcef/browser/native/file_dialog_runner_win.cc
deleted file mode 100644
index 83feeed..0000000
--- a/src/libcef/browser/native/file_dialog_runner_win.cc
+++ /dev/null
@@ -1,524 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/native/file_dialog_runner_win.h"
-
-#include <windows.h>
-
-#include <commdlg.h>
-#include <shlobj.h>
-#include <wrl/client.h>
-
-#include "libcef/browser/browser_host_impl.h"
-
-#include "base/files/file_util.h"
-#include "base/stl_util.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/win/registry.h"
-#include "cef/grit/cef_strings.h"
-#include "chrome/grit/generated_resources.h"
-#include "net/base/mime_util.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/win/shell.h"
-#include "ui/strings/grit/ui_strings.h"
-
-namespace {
-
-// From ui/base/dialogs/select_file_dialog_win.cc.
-
-// Get the file type description from the registry. This will be "Text Document"
-// for .txt files, "JPEG Image" for .jpg files, etc. If the registry doesn't
-// have an entry for the file type, we return false, true if the description was
-// found. 'file_ext' must be in form ".txt".
-static bool GetRegistryDescriptionFromExtension(const std::wstring& file_ext,
-                                                std::wstring* reg_description) {
-  DCHECK(reg_description);
-  base::win::RegKey reg_ext(HKEY_CLASSES_ROOT, file_ext.c_str(), KEY_READ);
-  std::wstring reg_app;
-  if (reg_ext.ReadValue(NULL, &reg_app) == ERROR_SUCCESS && !reg_app.empty()) {
-    base::win::RegKey reg_link(HKEY_CLASSES_ROOT, reg_app.c_str(), KEY_READ);
-    if (reg_link.ReadValue(NULL, reg_description) == ERROR_SUCCESS)
-      return true;
-  }
-  return false;
-}
-
-// Set up a filter for a Save/Open dialog, which will consist of |file_ext| file
-// extensions (internally separated by semicolons), |ext_desc| as the text
-// descriptions of the |file_ext| types (optional), and (optionally) the default
-// 'All Files' view. The purpose of the filter is to show only files of a
-// particular type in a Windows Save/Open dialog box. The resulting filter is
-// returned. The filters created here are:
-//   1. only files that have 'file_ext' as their extension
-//   2. all files (only added if 'include_all_files' is true)
-// Example:
-//   file_ext: { "*.txt", "*.htm;*.html" }
-//   ext_desc: { "Text Document" }
-//   returned: "Text Document\0*.txt\0HTML Document\0*.htm;*.html\0"
-//             "All Files\0*.*\0\0" (in one big string)
-// If a description is not provided for a file extension, it will be retrieved
-// from the registry. If the file extension does not exist in the registry, it
-// will be omitted from the filter, as it is likely a bogus extension.
-std::wstring FormatFilterForExtensions(
-    const std::vector<std::wstring>& file_ext,
-    const std::vector<std::wstring>& ext_desc,
-    bool include_all_files) {
-  const std::wstring all_ext = L"*.*";
-  const std::wstring all_desc =
-      l10n_util::GetStringUTF16(IDS_APP_SAVEAS_ALL_FILES) + L" (" + all_ext +
-      L")";
-
-  DCHECK(file_ext.size() >= ext_desc.size());
-
-  if (file_ext.empty())
-    include_all_files = true;
-
-  std::wstring result;
-
-  for (size_t i = 0; i < file_ext.size(); ++i) {
-    std::wstring ext = file_ext[i];
-    std::wstring desc;
-    if (i < ext_desc.size())
-      desc = ext_desc[i];
-
-    if (ext.empty()) {
-      // Force something reasonable to appear in the dialog box if there is no
-      // extension provided.
-      include_all_files = true;
-      continue;
-    }
-
-    if (desc.empty()) {
-      DCHECK(ext.find(L'.') != std::wstring::npos);
-      std::wstring first_extension = ext.substr(ext.find(L'.'));
-      size_t first_separator_index = first_extension.find(L';');
-      if (first_separator_index != std::wstring::npos)
-        first_extension = first_extension.substr(0, first_separator_index);
-
-      // Find the extension name without the preceeding '.' character.
-      std::wstring ext_name = first_extension;
-      size_t ext_index = ext_name.find_first_not_of(L'.');
-      if (ext_index != std::wstring::npos)
-        ext_name = ext_name.substr(ext_index);
-
-      if (!GetRegistryDescriptionFromExtension(first_extension, &desc)) {
-        // The extension doesn't exist in the registry.
-        include_all_files = true;
-      }
-    }
-
-    if (!desc.empty())
-      desc += L" (" + ext + L")";
-    else
-      desc = ext;
-
-    result.append(desc.c_str(), desc.size() + 1);  // Append NULL too.
-    result.append(ext.c_str(), ext.size() + 1);
-  }
-
-  if (include_all_files) {
-    result.append(all_desc.c_str(), all_desc.size() + 1);
-    result.append(all_ext.c_str(), all_ext.size() + 1);
-  }
-
-  result.append(1, '\0');  // Double NULL required.
-  return result;
-}
-
-std::wstring GetDescriptionFromMimeType(const std::string& mime_type) {
-  // Check for wild card mime types and return an appropriate description.
-  static const struct {
-    const char* mime_type;
-    int string_id;
-  } kWildCardMimeTypes[] = {
-      {"audio", IDS_AUDIO_FILES},
-      {"image", IDS_IMAGE_FILES},
-      {"text", IDS_TEXT_FILES},
-      {"video", IDS_VIDEO_FILES},
-  };
-
-  for (size_t i = 0; i < base::size(kWildCardMimeTypes); ++i) {
-    if (mime_type == std::string(kWildCardMimeTypes[i].mime_type) + "/*")
-      return l10n_util::GetStringUTF16(kWildCardMimeTypes[i].string_id);
-  }
-
-  return std::wstring();
-}
-
-std::wstring GetFilterString(
-    const std::vector<base::string16>& accept_filters) {
-  std::vector<std::wstring> extensions;
-  std::vector<std::wstring> descriptions;
-
-  for (size_t i = 0; i < accept_filters.size(); ++i) {
-    const base::string16& filter = accept_filters[i];
-    if (filter.empty())
-      continue;
-
-    size_t sep_index = filter.find('|');
-    if (sep_index != base::string16::npos) {
-      // Treat as a filter of the form "Filter Name|.ext1;.ext2;.ext3".
-      const base::string16& desc = filter.substr(0, sep_index);
-      const std::vector<base::string16>& ext = base::SplitString(
-          filter.substr(sep_index + 1), base::ASCIIToUTF16(";"),
-          base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
-      std::wstring ext_str;
-      for (size_t x = 0; x < ext.size(); ++x) {
-        const base::string16& file_ext = ext[x];
-        if (!file_ext.empty() && file_ext[0] == '.') {
-          if (!ext_str.empty())
-            ext_str += L";";
-          ext_str += L"*" + file_ext;
-        }
-      }
-      if (!ext_str.empty()) {
-        extensions.push_back(ext_str);
-        descriptions.push_back(desc);
-      }
-    } else if (filter[0] == L'.') {
-      // Treat as an extension beginning with the '.' character.
-      extensions.push_back(L"*" + filter);
-      descriptions.push_back(std::wstring());
-    } else {
-      // Otherwise convert mime type to one or more extensions.
-      const std::string& ascii = base::UTF16ToASCII(filter);
-      std::vector<base::FilePath::StringType> ext;
-      std::wstring ext_str;
-      net::GetExtensionsForMimeType(ascii, &ext);
-      if (!ext.empty()) {
-        for (size_t x = 0; x < ext.size(); ++x) {
-          if (x != 0)
-            ext_str += L";";
-          ext_str += L"*." + ext[x];
-        }
-        extensions.push_back(ext_str);
-        descriptions.push_back(GetDescriptionFromMimeType(ascii));
-      }
-    }
-  }
-
-  return FormatFilterForExtensions(extensions, descriptions, true);
-}
-
-// From chrome/browser/views/shell_dialogs_win.cc
-
-bool RunOpenFileDialog(const CefFileDialogRunner::FileChooserParams& params,
-                       HWND owner,
-                       int* filter_index,
-                       base::FilePath* path) {
-  OPENFILENAME ofn;
-
-  // We must do this otherwise the ofn's FlagsEx may be initialized to random
-  // junk in release builds which can cause the Places Bar not to show up!
-  ZeroMemory(&ofn, sizeof(ofn));
-  ofn.lStructSize = sizeof(ofn);
-  ofn.hwndOwner = owner;
-
-  wchar_t filename[MAX_PATH] = {0};
-
-  ofn.lpstrFile = filename;
-  ofn.nMaxFile = MAX_PATH;
-
-  std::wstring directory;
-  if (!params.default_file_name.empty()) {
-    if (params.default_file_name.EndsWithSeparator()) {
-      // The value is only a directory.
-      directory = params.default_file_name.value();
-    } else {
-      // The value is a file name and possibly a directory.
-      base::wcslcpy(filename, params.default_file_name.value().c_str(),
-                    base::size(filename));
-      directory = params.default_file_name.DirName().value();
-    }
-  }
-  if (!directory.empty())
-    ofn.lpstrInitialDir = directory.c_str();
-
-  std::wstring title;
-  if (!params.title.empty())
-    title = params.title;
-  else
-    title = l10n_util::GetStringUTF16(IDS_OPEN_FILE_DIALOG_TITLE);
-  if (!title.empty())
-    ofn.lpstrTitle = title.c_str();
-
-  // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory
-  // without having to close Chrome first.
-  ofn.Flags =
-      OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_ENABLESIZING;
-  if (params.hidereadonly)
-    ofn.Flags |= OFN_HIDEREADONLY;
-
-  const std::wstring& filter = GetFilterString(params.accept_types);
-  if (!filter.empty()) {
-    ofn.lpstrFilter = filter.c_str();
-    // Indices into |lpstrFilter| start at 1.
-    ofn.nFilterIndex = *filter_index + 1;
-  }
-
-  bool success = !!GetOpenFileName(&ofn);
-  if (success) {
-    *filter_index = ofn.nFilterIndex == 0 ? 0 : ofn.nFilterIndex - 1;
-    *path = base::FilePath(filename);
-  }
-  return success;
-}
-
-bool RunOpenMultiFileDialog(
-    const CefFileDialogRunner::FileChooserParams& params,
-    HWND owner,
-    int* filter_index,
-    std::vector<base::FilePath>* paths) {
-  OPENFILENAME ofn;
-
-  // We must do this otherwise the ofn's FlagsEx may be initialized to random
-  // junk in release builds which can cause the Places Bar not to show up!
-  ZeroMemory(&ofn, sizeof(ofn));
-  ofn.lStructSize = sizeof(ofn);
-  ofn.hwndOwner = owner;
-
-  std::unique_ptr<wchar_t[]> filename(new wchar_t[UNICODE_STRING_MAX_CHARS]);
-  filename[0] = 0;
-
-  ofn.lpstrFile = filename.get();
-  ofn.nMaxFile = UNICODE_STRING_MAX_CHARS;
-
-  std::wstring directory;
-  if (!params.default_file_name.empty()) {
-    if (params.default_file_name.EndsWithSeparator()) {
-      // The value is only a directory.
-      directory = params.default_file_name.value();
-    } else {
-      // The value is a file name and possibly a directory.
-      directory = params.default_file_name.DirName().value();
-    }
-  }
-  if (!directory.empty())
-    ofn.lpstrInitialDir = directory.c_str();
-
-  std::wstring title;
-  if (!params.title.empty())
-    title = params.title;
-  else
-    title = l10n_util::GetStringUTF16(IDS_OPEN_FILES_DIALOG_TITLE);
-  if (!title.empty())
-    ofn.lpstrTitle = title.c_str();
-
-  // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory
-  // without having to close Chrome first.
-  ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER |
-              OFN_ALLOWMULTISELECT | OFN_ENABLESIZING;
-  if (params.hidereadonly)
-    ofn.Flags |= OFN_HIDEREADONLY;
-
-  const std::wstring& filter = GetFilterString(params.accept_types);
-  if (!filter.empty()) {
-    ofn.lpstrFilter = filter.c_str();
-    // Indices into |lpstrFilter| start at 1.
-    ofn.nFilterIndex = *filter_index + 1;
-  }
-
-  bool success = !!GetOpenFileName(&ofn);
-
-  if (success) {
-    std::vector<base::FilePath> files;
-    const wchar_t* selection = ofn.lpstrFile;
-    while (*selection) {  // Empty string indicates end of list.
-      files.push_back(base::FilePath(selection));
-      // Skip over filename and null-terminator.
-      selection += files.back().value().length() + 1;
-    }
-    if (files.empty()) {
-      success = false;
-    } else if (files.size() == 1) {
-      // When there is one file, it contains the path and filename.
-      paths->swap(files);
-    } else {
-      // Otherwise, the first string is the path, and the remainder are
-      // filenames.
-      std::vector<base::FilePath>::iterator path = files.begin();
-      for (std::vector<base::FilePath>::iterator file = path + 1;
-           file != files.end(); ++file) {
-        paths->push_back(path->Append(*file));
-      }
-    }
-  }
-
-  if (success)
-    *filter_index = ofn.nFilterIndex == 0 ? 0 : ofn.nFilterIndex - 1;
-
-  return success;
-}
-
-// The callback function for when the select folder dialog is opened.
-int CALLBACK BrowseCallbackProc(HWND window,
-                                UINT message,
-                                LPARAM parameter,
-                                LPARAM data) {
-  if (message == BFFM_INITIALIZED) {
-    // WParam is TRUE since passing a path.
-    // data lParam member of the BROWSEINFO structure.
-    SendMessage(window, BFFM_SETSELECTION, TRUE, (LPARAM)data);
-  }
-  return 0;
-}
-
-bool RunOpenFolderDialog(const CefFileDialogRunner::FileChooserParams& params,
-                         HWND owner,
-                         base::FilePath* path) {
-  wchar_t dir_buffer[MAX_PATH + 1] = {0};
-
-  bool result = false;
-  BROWSEINFO browse_info = {0};
-  browse_info.hwndOwner = owner;
-  browse_info.pszDisplayName = dir_buffer;
-  browse_info.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS;
-
-  std::wstring title;
-  if (!params.title.empty())
-    title = params.title;
-  else
-    title = l10n_util::GetStringUTF16(IDS_SELECT_FOLDER_DIALOG_TITLE);
-  if (!title.empty())
-    browse_info.lpszTitle = title.c_str();
-
-  const std::wstring& file_path = params.default_file_name.value();
-  if (!file_path.empty()) {
-    // Highlight the current value.
-    browse_info.lParam = (LPARAM)file_path.c_str();
-    browse_info.lpfn = &BrowseCallbackProc;
-  }
-
-  LPITEMIDLIST list = SHBrowseForFolder(&browse_info);
-  if (list) {
-    STRRET out_dir_buffer;
-    ZeroMemory(&out_dir_buffer, sizeof(out_dir_buffer));
-    out_dir_buffer.uType = STRRET_WSTR;
-    Microsoft::WRL::ComPtr<IShellFolder> shell_folder;
-    if (SHGetDesktopFolder(shell_folder.GetAddressOf()) == NOERROR) {
-      HRESULT hr = shell_folder->GetDisplayNameOf(list, SHGDN_FORPARSING,
-                                                  &out_dir_buffer);
-      if (SUCCEEDED(hr) && out_dir_buffer.uType == STRRET_WSTR) {
-        *path = base::FilePath(out_dir_buffer.pOleStr);
-        CoTaskMemFree(out_dir_buffer.pOleStr);
-        result = true;
-      } else {
-        // Use old way if we don't get what we want.
-        wchar_t old_out_dir_buffer[MAX_PATH + 1];
-        if (SHGetPathFromIDList(list, old_out_dir_buffer)) {
-          *path = base::FilePath(old_out_dir_buffer);
-          result = true;
-        }
-      }
-    }
-    CoTaskMemFree(list);
-  }
-
-  return result;
-}
-
-bool RunSaveFileDialog(const CefFileDialogRunner::FileChooserParams& params,
-                       HWND owner,
-                       int* filter_index,
-                       base::FilePath* path) {
-  OPENFILENAME ofn;
-
-  // We must do this otherwise the ofn's FlagsEx may be initialized to random
-  // junk in release builds which can cause the Places Bar not to show up!
-  ZeroMemory(&ofn, sizeof(ofn));
-  ofn.lStructSize = sizeof(ofn);
-  ofn.hwndOwner = owner;
-
-  wchar_t filename[MAX_PATH] = {0};
-
-  ofn.lpstrFile = filename;
-  ofn.nMaxFile = MAX_PATH;
-
-  std::wstring directory;
-  if (!params.default_file_name.empty()) {
-    if (params.default_file_name.EndsWithSeparator()) {
-      // The value is only a directory.
-      directory = params.default_file_name.value();
-    } else {
-      // The value is a file name and possibly a directory.
-      base::wcslcpy(filename, params.default_file_name.value().c_str(),
-                    base::size(filename));
-      directory = params.default_file_name.DirName().value();
-    }
-  }
-  if (!directory.empty())
-    ofn.lpstrInitialDir = directory.c_str();
-
-  std::wstring title;
-  if (!params.title.empty())
-    title = params.title;
-  else
-    title = l10n_util::GetStringUTF16(IDS_SAVE_AS_DIALOG_TITLE);
-  if (!title.empty())
-    ofn.lpstrTitle = title.c_str();
-
-  // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory
-  // without having to close Chrome first.
-  ofn.Flags =
-      OFN_EXPLORER | OFN_ENABLESIZING | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
-  if (params.hidereadonly)
-    ofn.Flags |= OFN_HIDEREADONLY;
-  if (params.overwriteprompt)
-    ofn.Flags |= OFN_OVERWRITEPROMPT;
-
-  const std::wstring& filter = GetFilterString(params.accept_types);
-  if (!filter.empty()) {
-    ofn.lpstrFilter = filter.c_str();
-    // Indices into |lpstrFilter| start at 1.
-    ofn.nFilterIndex = *filter_index + 1;
-    // If a filter is specified and the default file name is changed then append
-    // a file extension to the new name.
-    ofn.lpstrDefExt = L"";
-  }
-
-  bool success = !!GetSaveFileName(&ofn);
-  if (success) {
-    *filter_index = ofn.nFilterIndex == 0 ? 0 : ofn.nFilterIndex - 1;
-    *path = base::FilePath(filename);
-  }
-  return success;
-}
-
-}  // namespace
-
-CefFileDialogRunnerWin::CefFileDialogRunnerWin() {}
-
-void CefFileDialogRunnerWin::Run(CefBrowserHostImpl* browser,
-                                 const FileChooserParams& params,
-                                 RunFileChooserCallback callback) {
-  int filter_index = params.selected_accept_filter;
-  std::vector<base::FilePath> files;
-
-  HWND owner = browser->GetWindowHandle();
-
-  if (params.mode == blink::mojom::FileChooserParams::Mode::kOpen) {
-    base::FilePath file;
-    if (RunOpenFileDialog(params, owner, &filter_index, &file))
-      files.push_back(file);
-  } else if (params.mode ==
-             blink::mojom::FileChooserParams::Mode::kOpenMultiple) {
-    RunOpenMultiFileDialog(params, owner, &filter_index, &files);
-  } else if (params.mode ==
-             blink::mojom::FileChooserParams::Mode::kUploadFolder) {
-    base::FilePath file;
-    if (RunOpenFolderDialog(params, owner, &file))
-      files.push_back(file);
-  } else if (params.mode == blink::mojom::FileChooserParams::Mode::kSave) {
-    base::FilePath file;
-    if (RunSaveFileDialog(params, owner, &filter_index, &file))
-      files.push_back(file);
-  } else {
-    NOTIMPLEMENTED();
-  }
-
-  std::move(callback).Run(filter_index, files);
-}
diff --git a/src/libcef/browser/native/file_dialog_runner_win.h b/src/libcef/browser/native/file_dialog_runner_win.h
deleted file mode 100644
index 78c21c0..0000000
--- a/src/libcef/browser/native/file_dialog_runner_win.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_BROWSER_NATIVE_FILE_DIALOG_RUNNER_WIN_H_
-#define CEF_LIBCEF_BROWSER_NATIVE_FILE_DIALOG_RUNNER_WIN_H_
-#pragma once
-
-#include "libcef/browser/file_dialog_runner.h"
-
-class CefFileDialogRunnerWin : public CefFileDialogRunner {
- public:
-  CefFileDialogRunnerWin();
-
-  // CefFileDialogRunner methods:
-  void Run(CefBrowserHostImpl* browser,
-           const FileChooserParams& params,
-           RunFileChooserCallback callback) override;
-};
-
-#endif  // CEF_LIBCEF_BROWSER_NATIVE_FILE_DIALOG_RUNNER_WIN_H_
diff --git a/src/libcef/browser/native/javascript_dialog_runner_mac.h b/src/libcef/browser/native/javascript_dialog_runner_mac.h
index 0cd92ec..828c08f 100644
--- a/src/libcef/browser/native/javascript_dialog_runner_mac.h
+++ b/src/libcef/browser/native/javascript_dialog_runner_mac.h
@@ -9,7 +9,7 @@
 
 #include "libcef/browser/javascript_dialog_runner.h"
 
-#include "base/mac/scoped_nsobject.h"
+#include "base/functional/callback.h"
 #include "base/memory/weak_ptr.h"
 
 #if __OBJC__
@@ -24,21 +24,22 @@
   ~CefJavaScriptDialogRunnerMac() override;
 
   // CefJavaScriptDialogRunner methods:
-  void Run(CefBrowserHostImpl* browser,
+  void Run(CefBrowserHostBase* browser,
            content::JavaScriptDialogType message_type,
-           const base::string16& display_url,
-           const base::string16& message_text,
-           const base::string16& default_prompt_text,
+           const GURL& origin_url,
+           const std::u16string& message_text,
+           const std::u16string& default_prompt_text,
            DialogClosedCallback callback) override;
+  void Handle(bool accept, const std::u16string* prompt_override) override;
   void Cancel() override;
 
   // Callback from CefJavaScriptDialogHelper when the dialog is closed.
-  void DialogClosed(bool success, const base::string16& user_input);
+  void DialogClosed(bool success, const std::u16string& user_input);
 
  private:
   DialogClosedCallback callback_;
 
-  base::scoped_nsobject<CefJavaScriptDialogHelper> helper_;
+  CefJavaScriptDialogHelper* __strong helper_;
 
   // Must be the last member.
   base::WeakPtrFactory<CefJavaScriptDialogRunnerMac> weak_ptr_factory_;
diff --git a/src/libcef/browser/native/javascript_dialog_runner_mac.mm b/src/libcef/browser/native/javascript_dialog_runner_mac.mm
index 289a539..243be68 100644
--- a/src/libcef/browser/native/javascript_dialog_runner_mac.mm
+++ b/src/libcef/browser/native/javascript_dialog_runner_mac.mm
@@ -7,16 +7,17 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "components/url_formatter/elide_url.h"
 
 // Helper object that receives the notification that the dialog/sheet is
 // going away. Is responsible for cleaning itself up.
 @interface CefJavaScriptDialogHelper : NSObject <NSAlertDelegate> {
  @private
-  base::scoped_nsobject<NSAlert> alert_;
-  NSTextField* textField_;  // WEAK; owned by alert_
+  NSAlert* __strong alert_;
+  NSTextField* __weak textField_;
 
   // Copies of the fields in CefJavaScriptDialog because they're private.
   CefJavaScriptDialogRunner::DialogClosedCallback callback_;
@@ -37,44 +38,49 @@
 
 - (id)initHelperWithCallback:
     (CefJavaScriptDialogRunner::DialogClosedCallback)callback {
-  if (self = [super init])
+  if (self = [super init]) {
     callback_ = std::move(callback);
+  }
 
   return self;
 }
 
 - (NSAlert*)alert {
-  alert_.reset([[NSAlert alloc] init]);
+  alert_ = [[NSAlert alloc] init];
   return alert_;
 }
 
 - (NSTextField*)textField {
-  textField_ = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 300, 22)];
-  [[textField_ cell] setLineBreakMode:NSLineBreakByTruncatingTail];
-  [alert_ setAccessoryView:textField_];
-  [[alert_ window] setInitialFirstResponder:textField_];
-  [textField_ release];
+  NSTextField* textField =
+      [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 300, 22)];
+  textField.cell.lineBreakMode = NSLineBreakByTruncatingTail;
 
-  return textField_;
+  alert_.accessoryView = textField;
+  alert_.window.initialFirstResponder = textField;
+
+  textField_ = textField;
+  return textField;
 }
 
 - (void)alertDidEnd:(NSAlert*)alert
          returnCode:(int)returnCode
         contextInfo:(void*)contextInfo {
-  if (returnCode == NSModalResponseStop)
+  if (returnCode == NSModalResponseStop) {
     return;
+  }
 
   bool success = returnCode == NSAlertFirstButtonReturn;
-  base::string16 input;
-  if (textField_)
-    input = base::SysNSStringToUTF16([textField_ stringValue]);
+  std::u16string input;
+  if (textField_) {
+    input = base::SysNSStringToUTF16(textField_.stringValue);
+  }
 
   std::move(callback_).Run(success, input);
 }
 
 - (void)cancel {
-  [NSApp endSheet:[alert_ window]];
-  alert_.reset();
+  [NSApp endSheet:alert_.window];
+  alert_ = nil;
 }
 
 @end
@@ -87,54 +93,58 @@
 }
 
 void CefJavaScriptDialogRunnerMac::Run(
-    CefBrowserHostImpl* browser,
+    CefBrowserHostBase* browser,
     content::JavaScriptDialogType message_type,
-    const base::string16& display_url,
-    const base::string16& message_text,
-    const base::string16& default_prompt_text,
+    const GURL& origin_url,
+    const std::u16string& message_text,
+    const std::u16string& default_prompt_text,
     DialogClosedCallback callback) {
-  DCHECK(!helper_.get());
+  DCHECK(!helper_);
   callback_ = std::move(callback);
 
   bool text_field = message_type == content::JAVASCRIPT_DIALOG_TYPE_PROMPT;
   bool one_button = message_type == content::JAVASCRIPT_DIALOG_TYPE_ALERT;
 
-  helper_.reset([[CefJavaScriptDialogHelper alloc]
+  helper_ = [[CefJavaScriptDialogHelper alloc]
       initHelperWithCallback:base::BindOnce(
                                  &CefJavaScriptDialogRunnerMac::DialogClosed,
-                                 weak_ptr_factory_.GetWeakPtr())]);
+                                 weak_ptr_factory_.GetWeakPtr())];
 
   // Show the modal dialog.
   NSAlert* alert = [helper_ alert];
   NSTextField* field = nil;
   if (text_field) {
     field = [helper_ textField];
-    [field setStringValue:base::SysUTF16ToNSString(default_prompt_text)];
+    field.stringValue = base::SysUTF16ToNSString(default_prompt_text);
   }
-  [alert setDelegate:helper_];
-  [alert setInformativeText:base::SysUTF16ToNSString(message_text)];
+  alert.delegate = helper_;
+  alert.informativeText = base::SysUTF16ToNSString(message_text);
 
-  base::string16 label;
+  std::u16string label;
   switch (message_type) {
     case content::JAVASCRIPT_DIALOG_TYPE_ALERT:
-      label = base::ASCIIToUTF16("JavaScript Alert");
+      label = u"JavaScript Alert";
       break;
     case content::JAVASCRIPT_DIALOG_TYPE_PROMPT:
-      label = base::ASCIIToUTF16("JavaScript Prompt");
+      label = u"JavaScript Prompt";
       break;
     case content::JAVASCRIPT_DIALOG_TYPE_CONFIRM:
-      label = base::ASCIIToUTF16("JavaScript Confirm");
+      label = u"JavaScript Confirm";
       break;
   }
-  if (!display_url.empty())
-    label += base::ASCIIToUTF16(" - ") + display_url;
 
-  [alert setMessageText:base::SysUTF16ToNSString(label)];
+  const std::u16string& display_url =
+      url_formatter::FormatUrlForSecurityDisplay(origin_url);
+  if (!display_url.empty()) {
+    label += u" - " + display_url;
+  }
+
+  alert.messageText = base::SysUTF16ToNSString(label);
 
   [alert addButtonWithTitle:@"OK"];
   if (!one_button) {
     NSButton* other = [alert addButtonWithTitle:@"Cancel"];
-    [other setKeyEquivalent:@"\e"];
+    other.keyEquivalent = @"\e";
   }
 
   // Calling beginSheetModalForWindow:nil is wrong API usage. For now work
@@ -152,20 +162,29 @@
                       contextInfo:this];
 #pragma clang diagnostic pop
 
-  if ([alert accessoryView])
+  if ([alert accessoryView]) {
     [[alert window] makeFirstResponder:[alert accessoryView]];
+  }
+}
+
+void CefJavaScriptDialogRunnerMac::Handle(
+    bool accept,
+    const std::u16string* prompt_override) {
+  if (helper_) {
+    DialogClosed(accept, prompt_override ? *prompt_override : std::u16string());
+  }
 }
 
 void CefJavaScriptDialogRunnerMac::Cancel() {
-  if (helper_.get()) {
+  if (helper_) {
     [helper_ cancel];
-    helper_.reset(nil);
+    helper_ = nil;
   }
 }
 
 void CefJavaScriptDialogRunnerMac::DialogClosed(
     bool success,
-    const base::string16& user_input) {
-  helper_.reset(nil);
+    const std::u16string& user_input) {
+  helper_ = nil;
   std::move(callback_).Run(success, user_input);
 }
diff --git a/src/libcef/browser/native/javascript_dialog_runner_win.cc b/src/libcef/browser/native/javascript_dialog_runner_win.cc
deleted file mode 100644
index 37b52eb..0000000
--- a/src/libcef/browser/native/javascript_dialog_runner_win.cc
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/native/javascript_dialog_runner_win.h"
-
-#include "libcef/browser/browser_host_impl.h"
-#include "libcef_dll/resource.h"
-
-#include "base/files/file_path.h"
-#include "base/path_service.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-
-class CefJavaScriptDialogRunnerWin;
-
-HHOOK CefJavaScriptDialogRunnerWin::msg_hook_ = NULL;
-int CefJavaScriptDialogRunnerWin::msg_hook_user_count_ = 0;
-
-INT_PTR CALLBACK CefJavaScriptDialogRunnerWin::DialogProc(HWND dialog,
-                                                          UINT message,
-                                                          WPARAM wparam,
-                                                          LPARAM lparam) {
-  switch (message) {
-    case WM_INITDIALOG: {
-      SetWindowLongPtr(dialog, DWLP_USER, static_cast<LONG_PTR>(lparam));
-      CefJavaScriptDialogRunnerWin* owner =
-          reinterpret_cast<CefJavaScriptDialogRunnerWin*>(lparam);
-      owner->dialog_win_ = dialog;
-      SetDlgItemText(dialog, IDC_DIALOGTEXT, owner->message_text_.c_str());
-      if (owner->message_type_ == content::JAVASCRIPT_DIALOG_TYPE_PROMPT)
-        SetDlgItemText(dialog, IDC_PROMPTEDIT,
-                       owner->default_prompt_text_.c_str());
-      break;
-    }
-    case WM_CLOSE: {
-      CefJavaScriptDialogRunnerWin* owner =
-          reinterpret_cast<CefJavaScriptDialogRunnerWin*>(
-              GetWindowLongPtr(dialog, DWLP_USER));
-      if (owner) {
-        owner->CloseDialog(false, base::string16());
-
-        // No need for the system to call DestroyWindow() because it will be
-        // called by the Cancel() method.
-        return 0;
-      }
-      break;
-    }
-    case WM_COMMAND: {
-      CefJavaScriptDialogRunnerWin* owner =
-          reinterpret_cast<CefJavaScriptDialogRunnerWin*>(
-              GetWindowLongPtr(dialog, DWLP_USER));
-      base::string16 user_input;
-      bool finish = false;
-      bool result = false;
-      switch (LOWORD(wparam)) {
-        case IDOK:
-          finish = true;
-          result = true;
-          if (owner->message_type_ == content::JAVASCRIPT_DIALOG_TYPE_PROMPT) {
-            size_t length =
-                GetWindowTextLength(GetDlgItem(dialog, IDC_PROMPTEDIT)) + 1;
-            if (length > 1) {
-              GetDlgItemText(dialog, IDC_PROMPTEDIT,
-                             base::WriteInto(&user_input, length), length);
-            }
-          }
-          break;
-        case IDCANCEL:
-          finish = true;
-          result = false;
-          break;
-      }
-      if (finish) {
-        owner->CloseDialog(result, user_input);
-      }
-      break;
-    }
-    default:
-      break;
-  }
-  return 0;
-}
-
-CefJavaScriptDialogRunnerWin::CefJavaScriptDialogRunnerWin()
-    : dialog_win_(NULL), parent_win_(NULL), hook_installed_(false) {}
-
-CefJavaScriptDialogRunnerWin::~CefJavaScriptDialogRunnerWin() {
-  Cancel();
-}
-
-void CefJavaScriptDialogRunnerWin::Run(
-    CefBrowserHostImpl* browser,
-    content::JavaScriptDialogType message_type,
-    const base::string16& display_url,
-    const base::string16& message_text,
-    const base::string16& default_prompt_text,
-    DialogClosedCallback callback) {
-  DCHECK(!dialog_win_);
-
-  message_type_ = message_type;
-  message_text_ = message_text;
-  default_prompt_text_ = default_prompt_text;
-  callback_ = std::move(callback);
-
-  InstallMessageHook();
-  hook_installed_ = true;
-
-  int dialog_type;
-  if (message_type == content::JAVASCRIPT_DIALOG_TYPE_ALERT)
-    dialog_type = IDD_ALERT;
-  else if (message_type == content::JAVASCRIPT_DIALOG_TYPE_CONFIRM)
-    dialog_type = IDD_CONFIRM;
-  else  // JAVASCRIPT_DIALOG_TYPE_PROMPT
-    dialog_type = IDD_PROMPT;
-
-  base::FilePath file_path;
-  HMODULE hModule = NULL;
-
-  // Try to load the dialog from the DLL.
-  if (base::PathService::Get(base::DIR_MODULE, &file_path)) {
-    file_path = file_path.Append(L"libcef.dll");
-    hModule = ::GetModuleHandle(file_path.value().c_str());
-  }
-  if (!hModule)
-    hModule = ::GetModuleHandle(NULL);
-  DCHECK(hModule);
-
-  parent_win_ = GetAncestor(browser->GetWindowHandle(), GA_ROOT);
-  dialog_win_ =
-      CreateDialogParam(hModule, MAKEINTRESOURCE(dialog_type), parent_win_,
-                        DialogProc, reinterpret_cast<LPARAM>(this));
-  DCHECK(dialog_win_);
-
-  if (!display_url.empty()) {
-    // Add the display URL to the window title.
-    TCHAR text[64];
-    GetWindowText(dialog_win_, text, sizeof(text) / sizeof(TCHAR));
-
-    base::string16 new_window_text =
-        text + base::ASCIIToUTF16(" - ") + display_url;
-    SetWindowText(dialog_win_, new_window_text.c_str());
-  }
-
-  // Disable the parent window so the user can't interact with it.
-  if (IsWindowEnabled(parent_win_))
-    EnableWindow(parent_win_, FALSE);
-
-  ShowWindow(dialog_win_, SW_SHOWNORMAL);
-}
-
-void CefJavaScriptDialogRunnerWin::Cancel() {
-  // Re-enable the parent before closing the popup to avoid focus/activation/
-  // z-order issues.
-  if (parent_win_ && IsWindow(parent_win_) && !IsWindowEnabled(parent_win_)) {
-    EnableWindow(parent_win_, TRUE);
-    parent_win_ = NULL;
-  }
-
-  if (dialog_win_ && IsWindow(dialog_win_)) {
-    SetWindowLongPtr(dialog_win_, DWLP_USER, NULL);
-    DestroyWindow(dialog_win_);
-    dialog_win_ = NULL;
-  }
-
-  if (hook_installed_) {
-    UninstallMessageHook();
-    hook_installed_ = false;
-  }
-}
-
-void CefJavaScriptDialogRunnerWin::CloseDialog(
-    bool success,
-    const base::string16& user_input) {
-  // Run the callback first so that RenderProcessHostImpl::IsBlocked is
-  // cleared. Otherwise, RenderWidgetHostImpl::IsIgnoringInputEvents will
-  // return true and RenderWidgetHostViewAura::OnWindowFocused will fail to
-  // re-assign browser focus.
-  std::move(callback_).Run(success, user_input);
-  Cancel();
-}
-
-// static
-LRESULT CALLBACK CefJavaScriptDialogRunnerWin::GetMsgProc(int code,
-                                                          WPARAM wparam,
-                                                          LPARAM lparam) {
-  // Mostly borrowed from http://support.microsoft.com/kb/q187988/
-  // and http://www.codeproject.com/KB/atl/cdialogmessagehook.aspx.
-  LPMSG msg = reinterpret_cast<LPMSG>(lparam);
-  if (code >= 0 && wparam == PM_REMOVE && msg->message >= WM_KEYFIRST &&
-      msg->message <= WM_KEYLAST) {
-    HWND hwnd = GetActiveWindow();
-    if (::IsWindow(hwnd) && ::IsDialogMessage(hwnd, msg)) {
-      // The value returned from this hookproc is ignored, and it cannot
-      // be used to tell Windows the message has been handled. To avoid
-      // further processing, convert the message to WM_NULL before
-      // returning.
-      msg->hwnd = NULL;
-      msg->message = WM_NULL;
-      msg->lParam = 0L;
-      msg->wParam = 0;
-    }
-  }
-
-  // Passes the hook information to the next hook procedure in
-  // the current hook chain.
-  return ::CallNextHookEx(msg_hook_, code, wparam, lparam);
-}
-
-// static
-bool CefJavaScriptDialogRunnerWin::InstallMessageHook() {
-  msg_hook_user_count_++;
-
-  // Make sure we only call this once.
-  if (msg_hook_ != NULL)
-    return true;
-
-  msg_hook_ = ::SetWindowsHookEx(WH_GETMESSAGE,
-                                 &CefJavaScriptDialogRunnerWin::GetMsgProc,
-                                 NULL, GetCurrentThreadId());
-  DCHECK(msg_hook_ != NULL);
-  return msg_hook_ != NULL;
-}
-
-// static
-bool CefJavaScriptDialogRunnerWin::UninstallMessageHook() {
-  msg_hook_user_count_--;
-  DCHECK_GE(msg_hook_user_count_, 0);
-
-  if (msg_hook_user_count_ > 0)
-    return true;
-
-  DCHECK(msg_hook_ != NULL);
-  BOOL result = ::UnhookWindowsHookEx(msg_hook_);
-  DCHECK(result);
-  msg_hook_ = NULL;
-
-  return result != FALSE;
-}
diff --git a/src/libcef/browser/native/javascript_dialog_runner_win.h b/src/libcef/browser/native/javascript_dialog_runner_win.h
deleted file mode 100644
index f8e33d8..0000000
--- a/src/libcef/browser/native/javascript_dialog_runner_win.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_BROWSER_NATIVE_JAVASCRIPT_DIALOG_RUNNER_WIN_H_
-#define CEF_LIBCEF_BROWSER_NATIVE_JAVASCRIPT_DIALOG_RUNNER_WIN_H_
-#pragma once
-
-#include <windows.h>
-
-#include "libcef/browser/javascript_dialog_runner.h"
-
-class CefJavaScriptDialogRunnerWin : public CefJavaScriptDialogRunner {
- public:
-  CefJavaScriptDialogRunnerWin();
-  ~CefJavaScriptDialogRunnerWin() override;
-
-  // CefJavaScriptDialogRunner methods:
-  void Run(CefBrowserHostImpl* browser,
-           content::JavaScriptDialogType message_type,
-           const base::string16& display_url,
-           const base::string16& message_text,
-           const base::string16& default_prompt_text,
-           DialogClosedCallback callback) override;
-  void Cancel() override;
-
- private:
-  void CloseDialog(bool success, const base::string16& user_input);
-
-  HWND dialog_win_;
-  HWND parent_win_;
-
-  content::JavaScriptDialogType message_type_;
-  base::string16 message_text_;
-  base::string16 default_prompt_text_;
-  DialogClosedCallback callback_;
-
-  bool hook_installed_;
-
-  static INT_PTR CALLBACK DialogProc(HWND dialog,
-                                     UINT message,
-                                     WPARAM wparam,
-                                     LPARAM lparam);
-
-  // Since the message loop we expect to run in isn't going to be nicely
-  // calling IsDialogMessage(), we need to hook the wnd proc and call it
-  // ourselves. See http://support.microsoft.com/kb/q187988/
-  static bool InstallMessageHook();
-  static bool UninstallMessageHook();
-  static LRESULT CALLBACK GetMsgProc(int code, WPARAM wparam, LPARAM lparam);
-  static HHOOK msg_hook_;
-  static int msg_hook_user_count_;
-};
-
-#endif  // CEF_LIBCEF_BROWSER_NATIVE_JAVASCRIPT_DIALOG_RUNNER_WIN_H_
diff --git a/src/libcef/browser/native/menu_2.cc b/src/libcef/browser/native/menu_2.cc
deleted file mode 100644
index f3ea808..0000000
--- a/src/libcef/browser/native/menu_2.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/native/menu_2.h"
-
-#include "ui/base/models/menu_model.h"
-
-namespace views {
-
-Menu2::Menu2(ui::MenuModel* model)
-    : model_(model), wrapper_(MenuWrapper::CreateWrapper(model)) {
-  Rebuild();
-}
-
-Menu2::~Menu2() {}
-
-HMENU Menu2::GetNativeMenu() const {
-  return wrapper_->GetNativeMenu();
-}
-
-void Menu2::RunMenuAt(const gfx::Point& point, Alignment alignment) {
-  wrapper_->RunMenuAt(point, alignment);
-}
-
-void Menu2::RunContextMenuAt(const gfx::Point& point) {
-  RunMenuAt(point, ALIGN_TOPLEFT);
-}
-
-void Menu2::CancelMenu() {
-  wrapper_->CancelMenu();
-}
-
-void Menu2::Rebuild() {
-  wrapper_->Rebuild(nullptr);
-}
-
-void Menu2::UpdateStates() {
-  wrapper_->UpdateStates();
-}
-
-MenuWrapper::MenuAction Menu2::GetMenuAction() const {
-  return wrapper_->GetMenuAction();
-}
-
-void Menu2::SetMinimumWidth(int width) {
-  wrapper_->SetMinimumWidth(width);
-}
-
-}  // namespace views
diff --git a/src/libcef/browser/native/menu_2.h b/src/libcef/browser/native/menu_2.h
deleted file mode 100644
index 7de1db0..0000000
--- a/src/libcef/browser/native/menu_2.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_BROWSER_NATIVE_MENU_2_H_
-#define CEF_LIBCEF_BROWSER_NATIVE_MENU_2_H_
-
-#include <memory>
-
-#include "libcef/browser/native/menu_wrapper.h"
-
-#include "base/macros.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace gfx {
-class Point;
-}
-
-namespace ui {
-class MenuModel;
-}
-
-namespace views {
-
-// A menu. Populated from a model, and relies on a delegate to execute commands.
-//
-// WARNING: do NOT create and use Menu2 on the stack. Menu2 notifies the model
-// of selection AFTER a delay. This means that if use a Menu2 on the stack
-// ActivatedAt is never invoked.
-class Menu2 {
- public:
-  // How the menu is aligned relative to the point it is shown at.
-  // The alignment is reversed by menu if text direction is right to left.
-  enum Alignment { ALIGN_TOPLEFT, ALIGN_TOPRIGHT };
-
-  // Creates a new menu populated with the contents of |model|.
-  // WARNING: this populates the menu on construction by invoking methods on
-  // the model. As such, it is typically not safe to use this as the model
-  // from the constructor. EG:
-  //   MyClass : menu_(this) {}
-  // is likely to have problems.
-  explicit Menu2(ui::MenuModel* model);
-  virtual ~Menu2();
-
-  // Runs the menu at the specified point. This method blocks until done.
-  // RunContextMenuAt is the same, but the alignment is the default for a
-  // context menu.
-  void RunMenuAt(const gfx::Point& point, Alignment alignment);
-  void RunContextMenuAt(const gfx::Point& point);
-
-  // Cancels the active menu.
-  void CancelMenu();
-
-  // Called when the model supplying data to this menu has changed, and the menu
-  // must be rebuilt.
-  void Rebuild();
-
-  // Called when the states of the menu items in the menu should be refreshed
-  // from the model.
-  void UpdateStates();
-
-  // For submenus.
-  HMENU GetNativeMenu() const;
-
-  // Get the result of the last call to RunMenuAt to determine whether an
-  // item was selected, the user navigated to a next or previous menu, or
-  // nothing.
-  MenuWrapper::MenuAction GetMenuAction() const;
-
-  // Accessors.
-  ui::MenuModel* model() const { return model_; }
-
-  // Sets the minimum width of the menu.
-  void SetMinimumWidth(int width);
-
- private:
-  ui::MenuModel* model_;
-
-  // The object that actually implements the menu.
-  std::unique_ptr<MenuWrapper> wrapper_;
-
-  DISALLOW_COPY_AND_ASSIGN(Menu2);
-};
-
-}  // namespace views
-
-#endif  // CEF_LIBCEF_BROWSER_NATIVE_MENU_2_H_
diff --git a/src/libcef/browser/native/menu_runner_linux.cc b/src/libcef/browser/native/menu_runner_linux.cc
deleted file mode 100644
index 72e8e46..0000000
--- a/src/libcef/browser/native/menu_runner_linux.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2014 The Chromium Embedded Framework 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 "libcef/browser/native/menu_runner_linux.h"
-
-#include "libcef/browser/browser_host_impl.h"
-
-#include "base/compiler_specific.h"
-#include "base/strings/string_util.h"
-#include "ui/gfx/geometry/point.h"
-
-CefMenuRunnerLinux::CefMenuRunnerLinux() {}
-
-bool CefMenuRunnerLinux::RunContextMenu(
-    CefBrowserHostImpl* browser,
-    CefMenuModelImpl* model,
-    const content::ContextMenuParams& params) {
-  menu_.reset(
-      new views::MenuRunner(model->model(), views::MenuRunner::CONTEXT_MENU));
-
-  const gfx::Point& screen_point =
-      browser->GetScreenPoint(gfx::Point(params.x, params.y));
-
-  views::Widget* parent_widget = nullptr;
-  if (!browser->IsWindowless())
-    parent_widget = browser->GetWindowWidget();
-
-  menu_->RunMenuAt(parent_widget, nullptr, gfx::Rect(screen_point, gfx::Size()),
-                   views::MenuAnchorPosition::kTopRight, ui::MENU_SOURCE_NONE);
-
-  return true;
-}
-
-void CefMenuRunnerLinux::CancelContextMenu() {
-  if (menu_)
-    menu_->Cancel();
-}
-
-bool CefMenuRunnerLinux::FormatLabel(base::string16& label) {
-  // Remove the accelerator indicator (&) from label strings.
-  const char16 replace[] = {L'&', 0};
-  return base::ReplaceChars(label, replace, base::string16(), &label);
-}
diff --git a/src/libcef/browser/native/menu_runner_linux.h b/src/libcef/browser/native/menu_runner_linux.h
deleted file mode 100644
index f48fc35..0000000
--- a/src/libcef/browser/native/menu_runner_linux.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_LINUX_H_
-#define CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_LINUX_H_
-#pragma once
-
-#include "libcef/browser/menu_runner.h"
-
-#include "ui/views/controls/menu/menu_runner.h"
-
-class CefMenuRunnerLinux : public CefMenuRunner {
- public:
-  CefMenuRunnerLinux();
-
-  // CefMenuRunner methods.
-  bool RunContextMenu(CefBrowserHostImpl* browser,
-                      CefMenuModelImpl* model,
-                      const content::ContextMenuParams& params) override;
-  void CancelContextMenu() override;
-  bool FormatLabel(base::string16& label) override;
-
- private:
-  std::unique_ptr<views::MenuRunner> menu_;
-};
-
-#endif  // CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_LINUX_H_
diff --git a/src/libcef/browser/native/menu_runner_mac.h b/src/libcef/browser/native/menu_runner_mac.h
index 8cb6a6d..125a451 100644
--- a/src/libcef/browser/native/menu_runner_mac.h
+++ b/src/libcef/browser/native/menu_runner_mac.h
@@ -8,8 +8,6 @@
 
 #include "libcef/browser/menu_runner.h"
 
-#include "base/mac/scoped_nsobject.h"
-
 #if __OBJC__
 @class MenuControllerCocoa;
 #else
@@ -22,13 +20,13 @@
   ~CefMenuRunnerMac() override;
 
   // CefMenuRunner methods.
-  bool RunContextMenu(CefBrowserHostImpl* browser,
+  bool RunContextMenu(AlloyBrowserHostImpl* browser,
                       CefMenuModelImpl* model,
                       const content::ContextMenuParams& params) override;
   void CancelContextMenu() override;
 
  private:
-  base::scoped_nsobject<MenuControllerCocoa> menu_controller_;
+  MenuControllerCocoa* __strong menu_controller_;
 };
 
 #endif  // CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_MAC_H_
diff --git a/src/libcef/browser/native/menu_runner_mac.mm b/src/libcef/browser/native/menu_runner_mac.mm
index 7270a09..1747126 100644
--- a/src/libcef/browser/native/menu_runner_mac.mm
+++ b/src/libcef/browser/native/menu_runner_mac.mm
@@ -4,12 +4,10 @@
 
 #include "libcef/browser/native/menu_runner_mac.h"
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 
-#include "base/compiler_specific.h"
 #import "base/mac/scoped_sending_event.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #import "ui/base/cocoa/menu_controller.h"
 #include "ui/gfx/geometry/point.h"
 
@@ -18,23 +16,19 @@
 CefMenuRunnerMac::~CefMenuRunnerMac() {}
 
 bool CefMenuRunnerMac::RunContextMenu(
-    CefBrowserHostImpl* browser,
+    AlloyBrowserHostImpl* browser,
     CefMenuModelImpl* model,
     const content::ContextMenuParams& params) {
   // Create a menu controller based on the model.
-  menu_controller_.reset([[MenuControllerCocoa alloc]
-               initWithModel:model->model()
-      useWithPopUpButtonCell:NO]);
+  MenuControllerCocoa* menu_controller =
+      [[MenuControllerCocoa alloc] initWithModel:model->model()
+                                        delegate:nil
+                          useWithPopUpButtonCell:NO];
 
-  // Keep the menu controller alive (by adding an additional retain) until after
-  // the menu has been dismissed. Otherwise it will crash if the browser is
-  // destroyed (and consequently the menu controller is destroyed) while the
-  // menu is still pending.
-  base::scoped_nsobject<MenuControllerCocoa> menu_controller_ref(
-      menu_controller_);
+  menu_controller_ = menu_controller;
 
   // Make sure events can be pumped while the menu is up.
-  base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
+  base::CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop allow;
 
   // One of the events that could be pumped is |window.close()|.
   // User-initiated event-tracking loops protect against this by
@@ -46,11 +40,12 @@
   // Show the menu. Blocks until the menu is dismissed.
   if (browser->IsWindowless()) {
     // Don't show the menu unless a native window handle exists.
-    if (!browser->GetWindowHandle())
+    if (!browser->GetWindowHandle()) {
       return false;
+    }
 
-    const gfx::Point& screen_point =
-        browser->GetScreenPoint(gfx::Point(params.x, params.y));
+    const gfx::Point& screen_point = browser->GetScreenPoint(
+        gfx::Point(params.x, params.y), /*want_dip_coords=*/true);
     NSPoint screen_position = NSPointFromCGPoint(screen_point.ToCGPoint());
     [[menu_controller_ menu] popUpMenuPositioningItem:nil
                                            atLocation:screen_position
@@ -67,9 +62,9 @@
     NSPoint position = [window mouseLocationOutsideOfEventStream];
 
     NSTimeInterval eventTime = [currentEvent timestamp];
-    NSEvent* clickEvent = [NSEvent mouseEventWithType:NSRightMouseDown
+    NSEvent* clickEvent = [NSEvent mouseEventWithType:NSEventTypeRightMouseDown
                                              location:position
-                                        modifierFlags:NSRightMouseDownMask
+                                        modifierFlags:0
                                             timestamp:eventTime
                                          windowNumber:[window windowNumber]
                                               context:nil
@@ -86,6 +81,7 @@
 }
 
 void CefMenuRunnerMac::CancelContextMenu() {
-  if (menu_controller_.get())
-    [menu_controller_ cancel];
+  if (menu_controller_) {
+    menu_controller_ = nil;
+  }
 }
diff --git a/src/libcef/browser/native/menu_runner_views_aura.cc b/src/libcef/browser/native/menu_runner_views_aura.cc
new file mode 100644
index 0000000..2b0accc
--- /dev/null
+++ b/src/libcef/browser/native/menu_runner_views_aura.cc
@@ -0,0 +1,53 @@
+// Copyright 2014 The Chromium Embedded Framework 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 "libcef/browser/native/menu_runner_views_aura.h"
+
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
+
+#include "base/strings/string_util.h"
+#include "ui/gfx/geometry/point.h"
+
+CefMenuRunnerViewsAura::CefMenuRunnerViewsAura() {}
+
+bool CefMenuRunnerViewsAura::RunContextMenu(
+    AlloyBrowserHostImpl* browser,
+    CefMenuModelImpl* model,
+    const content::ContextMenuParams& params) {
+  views::Widget* widget = nullptr;
+  gfx::AcceleratedWidget parent_widget = gfx::kNullAcceleratedWidget;
+  if (browser->IsWindowless()) {
+    parent_widget = browser->GetWindowHandle();
+    if (!parent_widget) {
+      LOG(ERROR) << "Window handle is required for default OSR context menu.";
+      return false;
+    }
+  } else {
+    widget = browser->GetWindowWidget();
+  }
+
+  menu_.reset(
+      new views::MenuRunner(model->model(), views::MenuRunner::CONTEXT_MENU));
+
+  gfx::Point screen_point = browser->GetScreenPoint(
+      gfx::Point(params.x, params.y), /*want_dip_coords=*/true);
+
+  menu_->RunMenuAt(widget, nullptr, gfx::Rect(screen_point, gfx::Size()),
+                   views::MenuAnchorPosition::kTopRight, ui::MENU_SOURCE_NONE,
+                   /*native_view_for_gestures=*/nullptr, parent_widget);
+
+  return true;
+}
+
+void CefMenuRunnerViewsAura::CancelContextMenu() {
+  if (menu_) {
+    menu_->Cancel();
+  }
+}
+
+bool CefMenuRunnerViewsAura::FormatLabel(std::u16string& label) {
+  // Remove the accelerator indicator (&) from label strings.
+  const std::u16string::value_type replace[] = {u'&', 0};
+  return base::ReplaceChars(label, replace, std::u16string(), &label);
+}
diff --git a/src/libcef/browser/native/menu_runner_views_aura.h b/src/libcef/browser/native/menu_runner_views_aura.h
new file mode 100644
index 0000000..c930441
--- /dev/null
+++ b/src/libcef/browser/native/menu_runner_views_aura.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2012 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_VIEWS_AURA_H_
+#define CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_VIEWS_AURA_H_
+#pragma once
+
+#include "libcef/browser/menu_runner.h"
+
+#include "ui/views/controls/menu/menu_runner.h"
+
+class CefMenuRunnerViewsAura : public CefMenuRunner {
+ public:
+  CefMenuRunnerViewsAura();
+
+  // CefMenuRunner methods.
+  bool RunContextMenu(AlloyBrowserHostImpl* browser,
+                      CefMenuModelImpl* model,
+                      const content::ContextMenuParams& params) override;
+  void CancelContextMenu() override;
+  bool FormatLabel(std::u16string& label) override;
+
+ private:
+  std::unique_ptr<views::MenuRunner> menu_;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_VIEWS_AURA_H_
diff --git a/src/libcef/browser/native/menu_runner_win.cc b/src/libcef/browser/native/menu_runner_win.cc
deleted file mode 100644
index 3ea125b..0000000
--- a/src/libcef/browser/native/menu_runner_win.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework 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 "libcef/browser/native/menu_runner_win.h"
-
-#include "libcef/browser/browser_host_impl.h"
-#include "libcef/browser/native/menu_2.h"
-
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_current.h"
-#include "ui/gfx/geometry/point.h"
-
-CefMenuRunnerWin::CefMenuRunnerWin() {}
-
-bool CefMenuRunnerWin::RunContextMenu(
-    CefBrowserHostImpl* browser,
-    CefMenuModelImpl* model,
-    const content::ContextMenuParams& params) {
-  // Create a menu based on the model.
-  menu_.reset(new views::CefNativeMenuWin(model->model(), nullptr));
-  menu_->Rebuild(nullptr);
-
-  // Make sure events can be pumped while the menu is up.
-  base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
-
-  const gfx::Point& screen_point =
-      browser->GetScreenPoint(gfx::Point(params.x, params.y));
-
-  // Show the menu. Blocks until the menu is dismissed.
-  menu_->RunMenuAt(screen_point, views::Menu2::ALIGN_TOPLEFT);
-
-  return true;
-}
diff --git a/src/libcef/browser/native/menu_runner_win.h b/src/libcef/browser/native/menu_runner_win.h
deleted file mode 100644
index 4f80797..0000000
--- a/src/libcef/browser/native/menu_runner_win.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_WIN_H_
-#define CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_WIN_H_
-#pragma once
-
-#include "libcef/browser/menu_runner.h"
-
-#include "libcef/browser/native/native_menu_win.h"
-
-class CefMenuRunnerWin : public CefMenuRunner {
- public:
-  CefMenuRunnerWin();
-
-  // CefMenuRunner methods.
-  bool RunContextMenu(CefBrowserHostImpl* browser,
-                      CefMenuModelImpl* model,
-                      const content::ContextMenuParams& params) override;
-
- private:
-  std::unique_ptr<views::CefNativeMenuWin> menu_;
-};
-
-#endif  // CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_WIN_H_
diff --git a/src/libcef/browser/native/menu_wrapper.h b/src/libcef/browser/native/menu_wrapper.h
deleted file mode 100644
index 0f4f0e3..0000000
--- a/src/libcef/browser/native/menu_wrapper.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_BROWSER_NATIVE_MENU_WRAPPER_H_
-#define CEF_LIBCEF_BROWSER_NATIVE_MENU_WRAPPER_H_
-
-#include "ui/gfx/native_widget_types.h"
-
-namespace gfx {
-class Point;
-}
-
-namespace ui {
-class MenuModel;
-}
-
-namespace views {
-
-class MenuInsertionDelegateWin;
-
-// An interface that wraps an object that implements a menu.
-class MenuWrapper {
- public:
-  // All of the possible actions that can result from RunMenuAt.
-  enum MenuAction {
-    MENU_ACTION_NONE,      // Menu cancelled, or never opened.
-    MENU_ACTION_SELECTED,  // An item was selected.
-    MENU_ACTION_PREVIOUS,  // User wants to navigate to the previous menu.
-    MENU_ACTION_NEXT,      // User wants to navigate to the next menu.
-  };
-
-  virtual ~MenuWrapper() {}
-
-  // Creates the appropriate instance of this wrapper for the current platform.
-  static MenuWrapper* CreateWrapper(ui::MenuModel* model);
-
-  // Runs the menu at the specified point. This blocks until done.
-  virtual void RunMenuAt(const gfx::Point& point, int alignment) = 0;
-
-  // Cancels the active menu.
-  virtual void CancelMenu() = 0;
-
-  // Called when the model supplying data to this menu has changed, and the menu
-  // must be rebuilt.
-  virtual void Rebuild(MenuInsertionDelegateWin* delegate) = 0;
-
-  // Called when the states of the items in the menu must be updated from the
-  // model.
-  virtual void UpdateStates() = 0;
-
-  // Retrieve a native menu handle.
-  virtual HMENU GetNativeMenu() const = 0;
-
-  // Get the result of the last call to RunMenuAt to determine whether an
-  // item was selected, the user navigated to a next or previous menu, or
-  // nothing.
-  virtual MenuAction GetMenuAction() const = 0;
-
-  // Sets the minimum width of the menu.
-  virtual void SetMinimumWidth(int width) = 0;
-};
-
-}  // namespace views
-
-#endif  // CEF_LIBCEF_BROWSER_NATIVE_MENU_WRAPPER_H_
diff --git a/src/libcef/browser/native/native_menu_win.cc b/src/libcef/browser/native/native_menu_win.cc
deleted file mode 100644
index e9d773a..0000000
--- a/src/libcef/browser/native/native_menu_win.cc
+++ /dev/null
@@ -1,774 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/native/native_menu_win.h"
-
-#include "libcef/browser/native/menu_2.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/stl_util.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/win/wrapped_window_proc.h"
-#include "skia/ext/platform_canvas.h"
-#include "skia/ext/skia_utils_win.h"
-#include "ui/base/accelerators/accelerator.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/l10n/l10n_util_win.h"
-#include "ui/base/models/menu_model.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/font_list.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/image/image.h"
-#include "ui/gfx/image/image_skia.h"
-#include "ui/gfx/text_utils.h"
-#include "ui/gfx/win/hwnd_util.h"
-#include "ui/native_theme/native_theme.h"
-#include "ui/views/controls/menu/menu_config.h"
-#include "ui/views/controls/menu/menu_insertion_delegate_win.h"
-
-using ui::NativeTheme;
-
-namespace views {
-
-// The width of an icon, including the pixels between the icon and
-// the item label.
-static const int kIconWidth = 23;
-// Margins between the top of the item and the label.
-static const int kItemTopMargin = 3;
-// Margins between the bottom of the item and the label.
-static const int kItemBottomMargin = 4;
-// Margins between the left of the item and the icon.
-static const int kItemLeftMargin = 4;
-// The width for displaying the sub-menu arrow.
-static const int kArrowWidth = 10;
-
-// Horizontal spacing between the end of an item (i.e. an icon or a checkbox)
-// and the start of its corresponding text.
-constexpr int kItemLabelSpacing = 10;
-
-namespace {
-
-// Draws the top layer of the canvas into the specified HDC. Only works
-// with a SkCanvas with a BitmapPlatformDevice. Will create a temporary
-// HDC to back the canvas if one doesn't already exist, tearing it down
-// before returning. If |src_rect| is null, copies the entire canvas.
-// Deleted from skia/ext/platform_canvas.h in https://crbug.com/675977#c13
-void DrawToNativeContext(SkCanvas* canvas,
-                         HDC destination_hdc,
-                         int x,
-                         int y,
-                         const RECT* src_rect) {
-  RECT temp_rect;
-  if (!src_rect) {
-    temp_rect.left = 0;
-    temp_rect.right = canvas->imageInfo().width();
-    temp_rect.top = 0;
-    temp_rect.bottom = canvas->imageInfo().height();
-    src_rect = &temp_rect;
-  }
-  skia::CopyHDC(skia::GetNativeDrawingContext(canvas), destination_hdc, x, y,
-                canvas->imageInfo().isOpaque(), *src_rect,
-                canvas->getTotalMatrix());
-}
-
-HFONT CreateNativeFont(const gfx::Font& font) {
-  // Extracts |fonts| properties.
-  const DWORD italic = (font.GetStyle() & gfx::Font::ITALIC) ? TRUE : FALSE;
-  const DWORD underline =
-      (font.GetStyle() & gfx::Font::UNDERLINE) ? TRUE : FALSE;
-  // The font mapper matches its absolute value against the character height of
-  // the available fonts.
-  const int height = -font.GetFontSize();
-
-  // Select the primary font which forces a mapping to a physical font.
-  return ::CreateFont(height, 0, 0, 0, static_cast<int>(font.GetWeight()),
-                      italic, underline, FALSE, DEFAULT_CHARSET,
-                      OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
-                      DEFAULT_PITCH | FF_DONTCARE,
-                      base::UTF8ToUTF16(font.GetFontName()).c_str());
-}
-
-}  // namespace
-
-struct CefNativeMenuWin::ItemData {
-  // The Windows API requires that whoever creates the menus must own the
-  // strings used for labels, and keep them around for the lifetime of the
-  // created menu. So be it.
-  base::string16 label;
-
-  // Someone needs to own submenus, it may as well be us.
-  std::unique_ptr<Menu2> submenu;
-
-  // We need a pointer back to the containing menu in various circumstances.
-  CefNativeMenuWin* native_menu_win;
-
-  // The index of the item within the menu's model.
-  int model_index;
-};
-
-// Returns the CefNativeMenuWin for a particular HMENU.
-static CefNativeMenuWin* GetCefNativeMenuWinFromHMENU(HMENU hmenu) {
-  MENUINFO mi = {0};
-  mi.cbSize = sizeof(mi);
-  mi.fMask = MIM_MENUDATA | MIM_STYLE;
-  GetMenuInfo(hmenu, &mi);
-  return reinterpret_cast<CefNativeMenuWin*>(mi.dwMenuData);
-}
-
-// A window that receives messages from Windows relevant to the native menu
-// structure we have constructed in CefNativeMenuWin.
-class CefNativeMenuWin::MenuHostWindow {
- public:
-  MenuHostWindow() {
-    RegisterClass();
-    hwnd_ = CreateWindowEx(l10n_util::GetExtendedStyles(), kWindowClassName,
-                           L"", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
-    gfx::CheckWindowCreated(hwnd_);
-    gfx::SetWindowUserData(hwnd_, this);
-  }
-
-  ~MenuHostWindow() { DestroyWindow(hwnd_); }
-
-  HWND hwnd() const { return hwnd_; }
-
- private:
-  static const wchar_t* kWindowClassName;
-
-  void RegisterClass() {
-    static bool registered = false;
-    if (registered)
-      return;
-
-    WNDCLASSEX window_class;
-    base::win::InitializeWindowClass(
-        kWindowClassName, &base::win::WrappedWindowProc<MenuHostWindowProc>,
-        CS_DBLCLKS, 0, 0, NULL, reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1),
-        NULL, NULL, NULL, &window_class);
-    ATOM clazz = RegisterClassEx(&window_class);
-    CHECK(clazz);
-    registered = true;
-  }
-
-  // Converts the WPARAM value passed to WM_MENUSELECT into an index
-  // corresponding to the menu item that was selected.
-  int GetMenuItemIndexFromWPARAM(HMENU menu, WPARAM w_param) const {
-    int count = GetMenuItemCount(menu);
-    // For normal command menu items, Windows passes a command id as the LOWORD
-    // of WPARAM for WM_MENUSELECT. We need to walk forward through the menu
-    // items to find an item with a matching ID. Ugh!
-    for (int i = 0; i < count; ++i) {
-      MENUITEMINFO mii = {0};
-      mii.cbSize = sizeof(mii);
-      mii.fMask = MIIM_ID;
-      GetMenuItemInfo(menu, i, MF_BYPOSITION, &mii);
-      if (mii.wID == w_param)
-        return i;
-    }
-    // If we didn't find a matching command ID, this means a submenu has been
-    // selected instead, and rather than passing a command ID in
-    // LOWORD(w_param), Windows has actually passed us a position, so we just
-    // return it.
-    return w_param;
-  }
-
-  CefNativeMenuWin::ItemData* GetItemData(ULONG_PTR item_data) {
-    return reinterpret_cast<CefNativeMenuWin::ItemData*>(item_data);
-  }
-
-  // Called when the user selects a specific item.
-  void OnMenuCommand(int position, HMENU menu) {
-    CefNativeMenuWin* menu_win = GetCefNativeMenuWinFromHMENU(menu);
-    ui::MenuModel* model = menu_win->model_;
-    CefNativeMenuWin* root_menu = menu_win;
-    while (root_menu->parent_)
-      root_menu = root_menu->parent_;
-
-    // Only notify the model if it didn't already send out notification.
-    // See comment in MenuMessageHook for details.
-    if (root_menu->menu_action_ == MenuWrapper::MENU_ACTION_NONE)
-      model->ActivatedAt(position);
-  }
-
-  // Called by Windows to measure the size of an owner-drawn menu item.
-  void OnMeasureItem(WPARAM w_param, MEASUREITEMSTRUCT* measure_item_struct) {
-    CefNativeMenuWin::ItemData* data =
-        GetItemData(measure_item_struct->itemData);
-    if (data) {
-      gfx::FontList font_list;
-      measure_item_struct->itemWidth =
-          gfx::GetStringWidth(data->label, font_list) + kIconWidth +
-          kItemLeftMargin + kItemLabelSpacing -
-          GetSystemMetrics(SM_CXMENUCHECK);
-      if (data->submenu.get())
-        measure_item_struct->itemWidth += kArrowWidth;
-      // If the label contains an accelerator, make room for tab.
-      if (data->label.find(L'\t') != base::string16::npos)
-        measure_item_struct->itemWidth += gfx::GetStringWidth(L" ", font_list);
-      measure_item_struct->itemHeight =
-          font_list.GetHeight() + kItemBottomMargin + kItemTopMargin;
-    } else {
-      // Measure separator size.
-      measure_item_struct->itemHeight = GetSystemMetrics(SM_CYMENU) / 2;
-      measure_item_struct->itemWidth = 0;
-    }
-  }
-
-  // Called by Windows to paint an owner-drawn menu item.
-  void OnDrawItem(UINT w_param, DRAWITEMSTRUCT* draw_item_struct) {
-    HDC dc = draw_item_struct->hDC;
-    COLORREF prev_bg_color, prev_text_color;
-
-    // Set background color and text color
-    if (draw_item_struct->itemState & ODS_SELECTED) {
-      prev_bg_color = SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT));
-      prev_text_color = SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT));
-    } else {
-      prev_bg_color = SetBkColor(dc, GetSysColor(COLOR_MENU));
-      if (draw_item_struct->itemState & ODS_DISABLED)
-        prev_text_color = SetTextColor(dc, GetSysColor(COLOR_GRAYTEXT));
-      else
-        prev_text_color = SetTextColor(dc, GetSysColor(COLOR_MENUTEXT));
-    }
-
-    if (draw_item_struct->itemData) {
-      CefNativeMenuWin::ItemData* data =
-          GetItemData(draw_item_struct->itemData);
-      // Draw the background.
-      HBRUSH hbr = CreateSolidBrush(GetBkColor(dc));
-      FillRect(dc, &draw_item_struct->rcItem, hbr);
-      DeleteObject(hbr);
-
-      // Draw the label.
-      RECT rect = draw_item_struct->rcItem;
-      rect.top += kItemTopMargin;
-      // Should we add kIconWidth only when icon.width() != 0 ?
-      rect.left += kItemLeftMargin + kIconWidth;
-      rect.right -= kItemLabelSpacing;
-      UINT format = DT_TOP | DT_SINGLELINE;
-      // Check whether the mnemonics should be underlined.
-      BOOL underline_mnemonics;
-      SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &underline_mnemonics, 0);
-      if (!underline_mnemonics)
-        format |= DT_HIDEPREFIX;
-      gfx::FontList font_list;
-      HFONT new_font = CreateNativeFont(font_list.GetPrimaryFont());
-      HGDIOBJ old_font = SelectObject(dc, new_font);
-
-      // If an accelerator is specified (with a tab delimiting the rest of the
-      // label from the accelerator), we have to justify the fist part on the
-      // left and the accelerator on the right.
-      // TODO(jungshik): This will break in RTL UI. Currently, he/ar use the
-      //                 window system UI font and will not hit here.
-      base::string16 label = data->label;
-      base::string16 accel;
-      base::string16::size_type tab_pos = label.find(L'\t');
-      if (tab_pos != base::string16::npos) {
-        accel = label.substr(tab_pos);
-        label = label.substr(0, tab_pos);
-      }
-      DrawTextEx(dc, const_cast<wchar_t*>(label.data()),
-                 static_cast<int>(label.size()), &rect, format | DT_LEFT, NULL);
-      if (!accel.empty()) {
-        DrawTextEx(dc, const_cast<wchar_t*>(accel.data()),
-                   static_cast<int>(accel.size()), &rect, format | DT_RIGHT,
-                   NULL);
-      }
-      SelectObject(dc, old_font);
-      DeleteObject(new_font);
-
-      ui::MenuModel::ItemType type =
-          data->native_menu_win->model_->GetTypeAt(data->model_index);
-
-      // Draw the icon after the label, otherwise it would be covered
-      // by the label.
-      gfx::Image icon;
-      if (data->native_menu_win->model_->GetIconAt(data->model_index, &icon)) {
-        // We currently don't support items with both icons and checkboxes.
-        const gfx::ImageSkia skia_icon = icon.AsImageSkia();
-        DCHECK(type != ui::MenuModel::TYPE_CHECK);
-        std::unique_ptr<SkCanvas> canvas = skia::CreatePlatformCanvas(
-            skia_icon.width(), skia_icon.height(), false);
-        canvas->drawBitmap(*skia_icon.bitmap(), 0, 0);
-        DrawToNativeContext(
-            canvas.get(), dc, draw_item_struct->rcItem.left + kItemLeftMargin,
-            draw_item_struct->rcItem.top +
-                (draw_item_struct->rcItem.bottom -
-                 draw_item_struct->rcItem.top - skia_icon.height()) /
-                    2,
-            NULL);
-      } else if (type == ui::MenuModel::TYPE_CHECK &&
-                 data->native_menu_win->model_->IsItemCheckedAt(
-                     data->model_index)) {
-        // Manually render a checkbox.
-        const MenuConfig& config = MenuConfig::instance();
-        NativeTheme::State state;
-        if (draw_item_struct->itemState & ODS_DISABLED) {
-          state = NativeTheme::kDisabled;
-        } else {
-          state = draw_item_struct->itemState & ODS_SELECTED
-                      ? NativeTheme::kHovered
-                      : NativeTheme::kNormal;
-        }
-
-        std::unique_ptr<SkCanvas> canvas = skia::CreatePlatformCanvas(
-            config.check_width, config.check_height, false);
-        cc::SkiaPaintCanvas paint_canvas(canvas.get());
-
-        NativeTheme::ExtraParams extra;
-        extra.menu_check.is_radio = false;
-        gfx::Rect bounds(0, 0, config.check_width, config.check_height);
-
-        // Draw the background and the check.
-        ui::NativeTheme* native_theme =
-            ui::NativeTheme::GetInstanceForNativeUi();
-        native_theme->Paint(&paint_canvas, NativeTheme::kMenuCheckBackground,
-                            state, bounds, extra);
-        native_theme->Paint(&paint_canvas, NativeTheme::kMenuCheck, state,
-                            bounds, extra);
-
-        // Draw checkbox to menu.
-        DrawToNativeContext(
-            canvas.get(), dc, draw_item_struct->rcItem.left + kItemLeftMargin,
-            draw_item_struct->rcItem.top +
-                (draw_item_struct->rcItem.bottom -
-                 draw_item_struct->rcItem.top - config.check_height) /
-                    2,
-            NULL);
-      }
-    } else {
-      // Draw the separator
-      draw_item_struct->rcItem.top +=
-          (draw_item_struct->rcItem.bottom - draw_item_struct->rcItem.top) / 3;
-      DrawEdge(dc, &draw_item_struct->rcItem, EDGE_ETCHED, BF_TOP);
-    }
-
-    SetBkColor(dc, prev_bg_color);
-    SetTextColor(dc, prev_text_color);
-  }
-
-  bool ProcessWindowMessage(HWND window,
-                            UINT message,
-                            WPARAM w_param,
-                            LPARAM l_param,
-                            LRESULT* l_result) {
-    switch (message) {
-      case WM_MENUCOMMAND:
-        OnMenuCommand(w_param, reinterpret_cast<HMENU>(l_param));
-        *l_result = 0;
-        return true;
-      case WM_MENUSELECT:
-        *l_result = 0;
-        return true;
-      case WM_MEASUREITEM:
-        OnMeasureItem(w_param, reinterpret_cast<MEASUREITEMSTRUCT*>(l_param));
-        *l_result = 0;
-        return true;
-      case WM_DRAWITEM:
-        OnDrawItem(w_param, reinterpret_cast<DRAWITEMSTRUCT*>(l_param));
-        *l_result = 0;
-        return true;
-        // TODO(beng): bring over owner draw from old menu system.
-    }
-    return false;
-  }
-
-  static LRESULT CALLBACK MenuHostWindowProc(HWND window,
-                                             UINT message,
-                                             WPARAM w_param,
-                                             LPARAM l_param) {
-    MenuHostWindow* host =
-        reinterpret_cast<MenuHostWindow*>(gfx::GetWindowUserData(window));
-    // host is null during initial construction.
-    LRESULT l_result = 0;
-    if (!host || !host->ProcessWindowMessage(window, message, w_param, l_param,
-                                             &l_result)) {
-      return DefWindowProc(window, message, w_param, l_param);
-    }
-    return l_result;
-  }
-
-  HWND hwnd_;
-
-  DISALLOW_COPY_AND_ASSIGN(MenuHostWindow);
-};
-
-struct CefNativeMenuWin::HighlightedMenuItemInfo {
-  HighlightedMenuItemInfo()
-      : has_parent(false), has_submenu(false), menu(nullptr), position(-1) {}
-
-  bool has_parent;
-  bool has_submenu;
-
-  // The menu and position. These are only set for non-disabled menu items.
-  CefNativeMenuWin* menu;
-  int position;
-};
-
-// static
-const wchar_t* CefNativeMenuWin::MenuHostWindow::kWindowClassName =
-    L"ViewsMenuHostWindow";
-
-////////////////////////////////////////////////////////////////////////////////
-// CefNativeMenuWin, public:
-
-CefNativeMenuWin::CefNativeMenuWin(ui::MenuModel* model, HWND system_menu_for)
-    : model_(model),
-      menu_(nullptr),
-      owner_draw_(l10n_util::NeedOverrideDefaultUIFont(NULL, NULL) &&
-                  !system_menu_for),
-      system_menu_for_(system_menu_for),
-      first_item_index_(0),
-      menu_action_(MENU_ACTION_NONE),
-      menu_to_select_(nullptr),
-      position_to_select_(-1),
-      parent_(nullptr),
-      destroyed_flag_(nullptr),
-      menu_to_select_factory_(this) {}
-
-CefNativeMenuWin::~CefNativeMenuWin() {
-  if (destroyed_flag_)
-    *destroyed_flag_ = true;
-  DestroyMenu(menu_);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// CefNativeMenuWin, MenuWrapper implementation:
-
-void CefNativeMenuWin::RunMenuAt(const gfx::Point& point, int alignment) {
-  CreateHostWindow();
-  UpdateStates();
-  UINT flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RECURSE;
-  flags |= GetAlignmentFlags(alignment);
-  menu_action_ = MENU_ACTION_NONE;
-
-  // Set a hook function so we can listen for keyboard events while the
-  // menu is open, and store a pointer to this object in a static
-  // variable so the hook has access to it (ugly, but it's the
-  // only way).
-  open_native_menu_win_ = this;
-  HHOOK hhook = SetWindowsHookEx(WH_MSGFILTER, MenuMessageHook,
-                                 GetModuleHandle(NULL), ::GetCurrentThreadId());
-
-  // Command dispatch is done through WM_MENUCOMMAND, handled by the host
-  // window.
-  menu_to_select_ = nullptr;
-  position_to_select_ = -1;
-  menu_to_select_factory_.InvalidateWeakPtrs();
-  bool destroyed = false;
-  destroyed_flag_ = &destroyed;
-  model_->MenuWillShow();
-  TrackPopupMenu(menu_, flags, point.x(), point.y(), 0, host_window_->hwnd(),
-                 NULL);
-  UnhookWindowsHookEx(hhook);
-  open_native_menu_win_ = nullptr;
-  if (destroyed)
-    return;
-  destroyed_flag_ = nullptr;
-  if (menu_to_select_) {
-    // Folks aren't too happy if we notify immediately. In particular, notifying
-    // the delegate can cause destruction leaving the stack in a weird
-    // state. Instead post a task, then notify. This mirrors what WM_MENUCOMMAND
-    // does.
-    menu_to_select_factory_.InvalidateWeakPtrs();
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(&CefNativeMenuWin::DelayedSelect,
-                              menu_to_select_factory_.GetWeakPtr()));
-    menu_action_ = MENU_ACTION_SELECTED;
-  }
-  // Send MenuWillClose after we schedule the select, otherwise MenuWillClose is
-  // processed after the select (MenuWillClose posts a delayed task too).
-  model_->MenuWillClose();
-}
-
-void CefNativeMenuWin::CancelMenu() {
-  EndMenu();
-}
-
-void CefNativeMenuWin::Rebuild(MenuInsertionDelegateWin* delegate) {
-  ResetNativeMenu();
-  items_.clear();
-
-  owner_draw_ = model_->HasIcons() || owner_draw_;
-  first_item_index_ = delegate ? delegate->GetInsertionIndex(menu_) : 0;
-  for (int menu_index = first_item_index_;
-       menu_index < first_item_index_ + model_->GetItemCount(); ++menu_index) {
-    int model_index = menu_index - first_item_index_;
-    if (model_->GetTypeAt(model_index) == ui::MenuModel::TYPE_SEPARATOR)
-      AddSeparatorItemAt(menu_index, model_index);
-    else
-      AddMenuItemAt(menu_index, model_index);
-  }
-}
-
-void CefNativeMenuWin::UpdateStates() {
-  // A depth-first walk of the menu items, updating states.
-  int model_index = 0;
-  ItemDataList::const_iterator it;
-  for (it = items_.begin(); it != items_.end(); ++it, ++model_index) {
-    int menu_index = model_index + first_item_index_;
-    SetMenuItemState(menu_index, model_->IsEnabledAt(model_index),
-                     model_->IsItemCheckedAt(model_index), false);
-    if (model_->IsItemDynamicAt(model_index)) {
-      // TODO(atwilson): Update the icon as well (http://crbug.com/66508).
-      SetMenuItemLabel(menu_index, model_index,
-                       model_->GetLabelAt(model_index));
-    }
-    Menu2* submenu = (*it)->submenu.get();
-    if (submenu)
-      submenu->UpdateStates();
-  }
-}
-
-HMENU CefNativeMenuWin::GetNativeMenu() const {
-  return menu_;
-}
-
-CefNativeMenuWin::MenuAction CefNativeMenuWin::GetMenuAction() const {
-  return menu_action_;
-}
-
-void CefNativeMenuWin::SetMinimumWidth(int width) {
-  NOTIMPLEMENTED();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// CefNativeMenuWin, private:
-
-// static
-CefNativeMenuWin* CefNativeMenuWin::open_native_menu_win_ = nullptr;
-
-void CefNativeMenuWin::DelayedSelect() {
-  if (menu_to_select_)
-    menu_to_select_->model_->ActivatedAt(position_to_select_);
-}
-
-// static
-bool CefNativeMenuWin::GetHighlightedMenuItemInfo(
-    HMENU menu,
-    HighlightedMenuItemInfo* info) {
-  for (int i = 0; i < ::GetMenuItemCount(menu); i++) {
-    UINT state = ::GetMenuState(menu, i, MF_BYPOSITION);
-    if (state & MF_HILITE) {
-      if (state & MF_POPUP) {
-        HMENU submenu = GetSubMenu(menu, i);
-        if (GetHighlightedMenuItemInfo(submenu, info))
-          info->has_parent = true;
-        else
-          info->has_submenu = true;
-      } else if (!(state & MF_SEPARATOR) && !(state & MF_DISABLED)) {
-        info->menu = GetCefNativeMenuWinFromHMENU(menu);
-        info->position = i;
-      }
-      return true;
-    }
-  }
-  return false;
-}
-
-// static
-LRESULT CALLBACK CefNativeMenuWin::MenuMessageHook(int n_code,
-                                                   WPARAM w_param,
-                                                   LPARAM l_param) {
-  LRESULT result = CallNextHookEx(NULL, n_code, w_param, l_param);
-
-  CefNativeMenuWin* this_ptr = open_native_menu_win_;
-  if (!this_ptr)
-    return result;
-
-  MSG* msg = reinterpret_cast<MSG*>(l_param);
-  if (msg->message == WM_LBUTTONUP || msg->message == WM_RBUTTONUP) {
-    HighlightedMenuItemInfo info;
-    if (GetHighlightedMenuItemInfo(this_ptr->menu_, &info) && info.menu) {
-      // It appears that when running a menu by way of TrackPopupMenu(Ex) win32
-      // gets confused if the underlying window paints itself. As its very easy
-      // for the underlying window to repaint itself (especially since some menu
-      // items trigger painting of the tabstrip on mouse over) we have this
-      // workaround. When the mouse is released on a menu item we remember the
-      // menu item and end the menu. When the nested message loop returns we
-      // schedule a task to notify the model. It's still possible to get a
-      // WM_MENUCOMMAND, so we have to be careful that we don't notify the model
-      // twice.
-      this_ptr->menu_to_select_ = info.menu;
-      this_ptr->position_to_select_ = info.position;
-      EndMenu();
-    }
-  } else if (msg->message == WM_KEYDOWN) {
-    HighlightedMenuItemInfo info;
-    if (GetHighlightedMenuItemInfo(this_ptr->menu_, &info)) {
-      if (msg->wParam == VK_LEFT && !info.has_parent) {
-        this_ptr->menu_action_ = MENU_ACTION_PREVIOUS;
-        ::EndMenu();
-      } else if (msg->wParam == VK_RIGHT && !info.has_parent &&
-                 !info.has_submenu) {
-        this_ptr->menu_action_ = MENU_ACTION_NEXT;
-        ::EndMenu();
-      }
-    }
-  }
-
-  return result;
-}
-
-bool CefNativeMenuWin::IsSeparatorItemAt(int menu_index) const {
-  MENUITEMINFO mii = {0};
-  mii.cbSize = sizeof(mii);
-  mii.fMask = MIIM_FTYPE;
-  GetMenuItemInfo(menu_, menu_index, MF_BYPOSITION, &mii);
-  return !!(mii.fType & MF_SEPARATOR);
-}
-
-void CefNativeMenuWin::AddMenuItemAt(int menu_index, int model_index) {
-  MENUITEMINFO mii = {0};
-  mii.cbSize = sizeof(mii);
-  mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_DATA;
-  if (!owner_draw_)
-    mii.fType = MFT_STRING;
-  else
-    mii.fType = MFT_OWNERDRAW;
-
-  std::unique_ptr<ItemData> item_data = std::make_unique<ItemData>();
-  item_data->label = base::string16();
-  ui::MenuModel::ItemType type = model_->GetTypeAt(model_index);
-  if (type == ui::MenuModel::TYPE_SUBMENU) {
-    item_data->submenu.reset(new Menu2(model_->GetSubmenuModelAt(model_index)));
-    mii.fMask |= MIIM_SUBMENU;
-    mii.hSubMenu = item_data->submenu->GetNativeMenu();
-    GetCefNativeMenuWinFromHMENU(mii.hSubMenu)->parent_ = this;
-  } else {
-    if (type == ui::MenuModel::TYPE_RADIO)
-      mii.fType |= MFT_RADIOCHECK;
-    mii.wID = model_->GetCommandIdAt(model_index);
-  }
-  item_data->native_menu_win = this;
-  item_data->model_index = model_index;
-  mii.dwItemData = reinterpret_cast<ULONG_PTR>(item_data.get());
-  items_.insert(items_.begin() + model_index, std::move(item_data));
-  UpdateMenuItemInfoForString(&mii, model_index,
-                              model_->GetLabelAt(model_index));
-  InsertMenuItem(menu_, menu_index, TRUE, &mii);
-}
-
-void CefNativeMenuWin::AddSeparatorItemAt(int menu_index, int model_index) {
-  MENUITEMINFO mii = {0};
-  mii.cbSize = sizeof(mii);
-  mii.fMask = MIIM_FTYPE;
-  mii.fType = MFT_SEPARATOR;
-  // Insert a dummy entry into our label list so we can index directly into it
-  // using item indices if need be.
-  items_.insert(items_.begin() + model_index, std::make_unique<ItemData>());
-  InsertMenuItem(menu_, menu_index, TRUE, &mii);
-}
-
-void CefNativeMenuWin::SetMenuItemState(int menu_index,
-                                        bool enabled,
-                                        bool checked,
-                                        bool is_default) {
-  if (IsSeparatorItemAt(menu_index))
-    return;
-
-  UINT state = enabled ? MFS_ENABLED : MFS_DISABLED;
-  if (checked)
-    state |= MFS_CHECKED;
-  if (is_default)
-    state |= MFS_DEFAULT;
-
-  MENUITEMINFO mii = {0};
-  mii.cbSize = sizeof(mii);
-  mii.fMask = MIIM_STATE;
-  mii.fState = state;
-  SetMenuItemInfo(menu_, menu_index, MF_BYPOSITION, &mii);
-}
-
-void CefNativeMenuWin::SetMenuItemLabel(int menu_index,
-                                        int model_index,
-                                        const base::string16& label) {
-  if (IsSeparatorItemAt(menu_index))
-    return;
-
-  MENUITEMINFO mii = {0};
-  mii.cbSize = sizeof(mii);
-  UpdateMenuItemInfoForString(&mii, model_index, label);
-  SetMenuItemInfo(menu_, menu_index, MF_BYPOSITION, &mii);
-}
-
-void CefNativeMenuWin::UpdateMenuItemInfoForString(
-    MENUITEMINFO* mii,
-    int model_index,
-    const base::string16& label) {
-  base::string16 formatted = label;
-  ui::MenuModel::ItemType type = model_->GetTypeAt(model_index);
-  // Strip out any tabs, otherwise they get interpreted as accelerators and can
-  // lead to weird behavior.
-  base::ReplaceSubstringsAfterOffset(&formatted, 0, L"\t", L" ");
-  if (type != ui::MenuModel::TYPE_SUBMENU) {
-    // Add accelerator details to the label if provided.
-    ui::Accelerator accelerator(ui::VKEY_UNKNOWN, ui::EF_NONE);
-    if (model_->GetAcceleratorAt(model_index, &accelerator)) {
-      formatted += L"\t";
-      formatted += accelerator.GetShortcutText();
-    }
-  }
-
-  // Update the owned string, since Windows will want us to keep this new
-  // version around.
-  items_[model_index]->label = formatted;
-
-  // Give Windows a pointer to the label string.
-  mii->fMask |= MIIM_STRING;
-  mii->dwTypeData = const_cast<wchar_t*>(items_[model_index]->label.c_str());
-}
-
-UINT CefNativeMenuWin::GetAlignmentFlags(int alignment) const {
-  UINT alignment_flags = TPM_TOPALIGN;
-  if (alignment == Menu2::ALIGN_TOPLEFT)
-    alignment_flags |= TPM_LEFTALIGN;
-  else if (alignment == Menu2::ALIGN_TOPRIGHT)
-    alignment_flags |= TPM_RIGHTALIGN;
-  return alignment_flags;
-}
-
-void CefNativeMenuWin::ResetNativeMenu() {
-  if (IsWindow(system_menu_for_)) {
-    if (menu_)
-      GetSystemMenu(system_menu_for_, TRUE);
-    menu_ = GetSystemMenu(system_menu_for_, FALSE);
-  } else {
-    if (menu_)
-      DestroyMenu(menu_);
-    menu_ = CreatePopupMenu();
-    // Rather than relying on the return value of TrackPopupMenuEx, which is
-    // always a command identifier, instead we tell the menu to notify us via
-    // our host window and the WM_MENUCOMMAND message.
-    MENUINFO mi = {0};
-    mi.cbSize = sizeof(mi);
-    mi.fMask = MIM_STYLE | MIM_MENUDATA;
-    mi.dwStyle = MNS_NOTIFYBYPOS;
-    mi.dwMenuData = reinterpret_cast<ULONG_PTR>(this);
-    SetMenuInfo(menu_, &mi);
-  }
-}
-
-void CefNativeMenuWin::CreateHostWindow() {
-  // This only gets called from RunMenuAt, and as such there is only ever one
-  // host window per menu hierarchy, no matter how many CefNativeMenuWin objects
-  // exist wrapping submenus.
-  if (!host_window_.get())
-    host_window_.reset(new MenuHostWindow());
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// MenuWrapper, public:
-
-// static
-MenuWrapper* MenuWrapper::CreateWrapper(ui::MenuModel* model) {
-  return new CefNativeMenuWin(model, NULL);
-}
-
-}  // namespace views
diff --git a/src/libcef/browser/native/native_menu_win.h b/src/libcef/browser/native/native_menu_win.h
deleted file mode 100644
index 414722e..0000000
--- a/src/libcef/browser/native/native_menu_win.h
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_BROWSER_NATIVE_NATIVE_MENU_WIN_H_
-#define CEF_LIBCEF_BROWSER_NATIVE_NATIVE_MENU_WIN_H_
-
-#include <memory>
-#include <vector>
-
-#include "libcef/browser/native/menu_wrapper.h"
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
-#include "base/strings/string16.h"
-
-namespace ui {
-class MenuModel;
-}
-
-namespace views {
-
-// A Windows implementation of MenuWrapper.
-// TODO(beng): rename to MenuWin once the old class is dead.
-class CefNativeMenuWin : public MenuWrapper {
- public:
-  // Construct a CefNativeMenuWin, with a model and delegate. If
-  // |system_menu_for| is non-NULL, the CefNativeMenuWin wraps the system menu
-  // for that window.
-  // The caller owns the model and the delegate.
-  CefNativeMenuWin(ui::MenuModel* model, HWND system_menu_for);
-  ~CefNativeMenuWin() override;
-
-  // Overridden from MenuWrapper:
-  void RunMenuAt(const gfx::Point& point, int alignment) override;
-  void CancelMenu() override;
-  void Rebuild(MenuInsertionDelegateWin* delegate) override;
-  void UpdateStates() override;
-  HMENU GetNativeMenu() const override;
-  MenuAction GetMenuAction() const override;
-  void SetMinimumWidth(int width) override;
-
- private:
-  // IMPORTANT: Note about indices.
-  //            Functions in this class deal in two index spaces:
-  //            1. menu_index - the index of an item within the actual Windows
-  //               native menu.
-  //            2. model_index - the index of the item within our model.
-  //            These two are most often but not always the same value! The
-  //            notable exception is when this object is used to wrap the
-  //            Windows System Menu. In this instance, the model indices start
-  //            at 0, but the insertion index into the existing menu is not.
-  //            It is important to take this into consideration when editing the
-  //            code in the functions in this class.
-
-  struct HighlightedMenuItemInfo;
-
-  // Returns true if the item at the specified index is a separator.
-  bool IsSeparatorItemAt(int menu_index) const;
-
-  // Add items. See note above about indices.
-  void AddMenuItemAt(int menu_index, int model_index);
-  void AddSeparatorItemAt(int menu_index, int model_index);
-
-  // Sets the state of the item at the specified index.
-  void SetMenuItemState(int menu_index,
-                        bool enabled,
-                        bool checked,
-                        bool is_default);
-
-  // Sets the label of the item at the specified index.
-  void SetMenuItemLabel(int menu_index,
-                        int model_index,
-                        const base::string16& label);
-
-  // Updates the local data structure with the correctly formatted version of
-  // |label| at the specified model_index, and adds string data to |mii| if
-  // the menu is not owner-draw. That's a mouthful. This function exists because
-  // of the peculiarities of the Windows menu API.
-  void UpdateMenuItemInfoForString(MENUITEMINFO* mii,
-                                   int model_index,
-                                   const base::string16& label);
-
-  // Returns the alignment flags to be passed to TrackPopupMenuEx, based on the
-  // supplied alignment and the UI text direction.
-  UINT GetAlignmentFlags(int alignment) const;
-
-  // Resets the native menu stored in |menu_| by destroying any old menu then
-  // creating a new empty one.
-  void ResetNativeMenu();
-
-  // Creates the host window that receives notifications from the menu.
-  void CreateHostWindow();
-
-  // Callback from task to notify menu it was selected.
-  void DelayedSelect();
-
-  // Given a menu that's currently popped-up, find the currently highlighted
-  // item. Returns true if a highlighted item was found.
-  static bool GetHighlightedMenuItemInfo(HMENU menu,
-                                         HighlightedMenuItemInfo* info);
-
-  // Hook to receive keyboard events while the menu is open.
-  static LRESULT CALLBACK MenuMessageHook(int n_code,
-                                          WPARAM w_param,
-                                          LPARAM l_param);
-
-  // Our attached model and delegate.
-  ui::MenuModel* model_;
-
-  HMENU menu_;
-
-  // True if the contents of menu items in this menu are drawn by the menu host
-  // window, rather than Windows.
-  bool owner_draw_;
-
-  // An object that collects all of the data associated with an individual menu
-  // item.
-  struct ItemData;
-  typedef std::vector<std::unique_ptr<ItemData>> ItemDataList;
-  ItemDataList items_;
-
-  // The window that receives notifications from the menu.
-  class MenuHostWindow;
-  friend MenuHostWindow;
-  std::unique_ptr<MenuHostWindow> host_window_;
-
-  // The HWND this menu is the system menu for, or NULL if the menu is not a
-  // system menu.
-  HWND system_menu_for_;
-
-  // The index of the first item in the model in the menu.
-  int first_item_index_;
-
-  // The action that took place during the call to RunMenuAt.
-  MenuAction menu_action_;
-
-  // See comment in MenuMessageHook for details on these.
-  CefNativeMenuWin* menu_to_select_;
-  int position_to_select_;
-
-  // If we're a submenu, this is our parent.
-  CefNativeMenuWin* parent_;
-
-  // If non-null the destructor sets this to true. This is set to non-null while
-  // the menu is showing. It is used to detect if the menu was deleted while
-  // running.
-  bool* destroyed_flag_;
-
-  base::WeakPtrFactory<CefNativeMenuWin> menu_to_select_factory_;
-
-  // Ugly: a static pointer to the instance of this class that currently
-  // has a menu open, because our hook function that receives keyboard
-  // events doesn't have a mechanism to get a user data pointer.
-  static CefNativeMenuWin* open_native_menu_win_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefNativeMenuWin);
-};
-
-}  // namespace views
-
-#endif  // CEF_LIBCEF_BROWSER_NATIVE_NATIVE_MENU_WIN_H_
diff --git a/src/libcef/browser/native/window_delegate_view.cc b/src/libcef/browser/native/window_delegate_view.cc
index 1a408dc..13b3059 100644
--- a/src/libcef/browser/native/window_delegate_view.cc
+++ b/src/libcef/browser/native/window_delegate_view.cc
@@ -15,11 +15,12 @@
 CefWindowDelegateView::CefWindowDelegateView(
     SkColor background_color,
     bool always_on_top,
-    base::RepeatingClosure on_bounds_changed)
+    base::RepeatingClosure on_bounds_changed,
+    base::OnceClosure on_delete)
     : background_color_(background_color),
-      web_view_(nullptr),
       always_on_top_(always_on_top),
-      on_bounds_changed_(on_bounds_changed) {}
+      on_bounds_changed_(std::move(on_bounds_changed)),
+      on_delete_(std::move(on_delete)) {}
 
 void CefWindowDelegateView::Init(gfx::AcceleratedWidget parent_widget,
                                  content::WebContents* web_contents,
@@ -29,6 +30,8 @@
   web_view_->SetWebContents(web_contents);
   web_view_->SetPreferredSize(bounds.size());
 
+  SetCanResize(true);
+
   views::Widget* widget = new views::Widget;
 
   // See CalculateWindowStylesFromInitParams in
@@ -47,8 +50,8 @@
   // Tell Aura not to draw the window frame on resize.
   params.remove_standard_frame = true;
   // Cause WidgetDelegate::CanActivate to return true. See comments in
-  // CefBrowserHostImpl::PlatformSetFocus.
-  params.activatable = views::Widget::InitParams::ACTIVATABLE_YES;
+  // AlloyBrowserHostImpl::PlatformSetFocus.
+  params.activatable = views::Widget::InitParams::Activatable::kYes;
 
   params.z_order = always_on_top_ ? ui::ZOrderLevel::kFloatingWindow
                                   : ui::ZOrderLevel::kNormal;
@@ -62,6 +65,10 @@
   DCHECK(widget->is_top_level());
   // |widget| must be activatable for focus handling to work correctly.
   DCHECK(widget->widget_delegate()->CanActivate());
+
+  // WidgetDelegate::DeleteDelegate() will execute the registered callback.
+  RegisterDeleteDelegateCallback(base::BindOnce(
+      &CefWindowDelegateView::DeleteDelegate, base::Unretained(this)));
 }
 
 void CefWindowDelegateView::InitContent() {
@@ -70,14 +77,22 @@
   AddChildView(web_view_);
 }
 
+void CefWindowDelegateView::DeleteDelegate() {
+  if (!on_delete_.is_null()) {
+    std::move(on_delete_).Run();
+  }
+}
+
 void CefWindowDelegateView::ViewHierarchyChanged(
     const views::ViewHierarchyChangedDetails& details) {
-  if (details.is_add && details.child == this)
+  if (details.is_add && details.child == this) {
     InitContent();
+  }
 }
 
 void CefWindowDelegateView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
   views::WidgetDelegateView::OnBoundsChanged(previous_bounds);
-  if (!on_bounds_changed_.is_null())
+  if (!on_bounds_changed_.is_null()) {
     on_bounds_changed_.Run();
+  }
 }
diff --git a/src/libcef/browser/native/window_delegate_view.h b/src/libcef/browser/native/window_delegate_view.h
index 3fb25a6..1205aea 100644
--- a/src/libcef/browser/native/window_delegate_view.h
+++ b/src/libcef/browser/native/window_delegate_view.h
@@ -22,7 +22,11 @@
  public:
   CefWindowDelegateView(SkColor background_color,
                         bool always_on_top,
-                        base::RepeatingClosure on_bounds_changed);
+                        base::RepeatingClosure on_bounds_changed,
+                        base::OnceClosure on_delete);
+
+  CefWindowDelegateView(const CefWindowDelegateView&) = delete;
+  CefWindowDelegateView& operator=(const CefWindowDelegateView&) = delete;
 
   // Create the Widget and associated root window.
   void Init(gfx::AcceleratedWidget parent_widget,
@@ -33,8 +37,9 @@
   // Initialize the Widget's content.
   void InitContent();
 
+  void DeleteDelegate();
+
   // WidgetDelegateView methods:
-  bool CanResize() const override { return true; }
   bool CanMaximize() const override { return true; }
   View* GetContentsView() override { return this; }
 
@@ -44,12 +49,12 @@
   void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
 
  private:
-  SkColor background_color_;
-  views::WebView* web_view_;
-  bool always_on_top_;
+  const SkColor background_color_;
+  const bool always_on_top_;
   base::RepeatingClosure on_bounds_changed_;
+  base::OnceClosure on_delete_;
 
-  DISALLOW_COPY_AND_ASSIGN(CefWindowDelegateView);
+  views::WebView* web_view_ = nullptr;
 };
 
 #endif  // CEF_LIBCEF_BROWSER_NATIVE_WINDOW_DELEGATE_VIEW_H_
diff --git a/src/libcef/browser/native/window_x11.cc b/src/libcef/browser/native/window_x11.cc
index 7b05589..211330b 100644
--- a/src/libcef/browser/native/window_x11.cc
+++ b/src/libcef/browser/native/window_x11.cc
@@ -4,472 +4,476 @@
 // found in the LICENSE file.
 
 #include "libcef/browser/native/window_x11.h"
+
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
+#include "libcef/browser/browser_host_base.h"
 #include "libcef/browser/thread_util.h"
 
+#include "net/base/network_interfaces.h"
 #include "ui/base/x/x11_util.h"
 #include "ui/events/platform/platform_event_source.h"
+#include "ui/events/platform/x11/x11_event_source.h"
 #include "ui/events/x/x11_event_translation.h"
-#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
-#include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h"
-
-#include <X11/Xatom.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/extensions/XInput2.h>
+#include "ui/gfx/x/connection.h"
+#include "ui/gfx/x/x11_window_event_manager.h"
+#include "ui/gfx/x/xproto_util.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h"
 
 namespace {
 
-const char kAtom[] = "ATOM";
-const char kWMDeleteWindow[] = "WM_DELETE_WINDOW";
-const char kWMProtocols[] = "WM_PROTOCOLS";
-const char kNetWMName[] = "_NET_WM_NAME";
 const char kNetWMPid[] = "_NET_WM_PID";
 const char kNetWMPing[] = "_NET_WM_PING";
 const char kNetWMState[] = "_NET_WM_STATE";
+const char kNetWMStateKeepAbove[] = "_NET_WM_STATE_KEEP_ABOVE";
+const char kWMDeleteWindow[] = "WM_DELETE_WINDOW";
+const char kWMProtocols[] = "WM_PROTOCOLS";
 const char kXdndProxy[] = "XdndProxy";
-const char kUTF8String[] = "UTF8_STRING";
 
-::Window FindChild(::Display* display, ::Window window) {
-  ::Window root;
-  ::Window parent;
-  ::Window* children;
-  ::Window child_window = x11::None;
-  unsigned int nchildren;
-  if (XQueryTree(display, window, &root, &parent, &children, &nchildren) &&
-      nchildren == 1) {
-    child_window = children[0];
-    XFree(children);
-  }
-  return child_window;
+// Return true if |window| has any property with |property_name|.
+// Deleted from ui/base/x/x11_util.h in https://crrev.com/62fc260067.
+bool PropertyExists(x11::Window window, x11::Atom property) {
+  auto response = x11::Connection::Get()
+                      ->GetProperty(x11::GetPropertyRequest{
+                          .window = window,
+                          .property = property,
+                          .long_length = 1,
+                      })
+                      .Sync();
+  return response && response->format;
 }
 
-::Window FindToplevelParent(::Display* display, ::Window window) {
-  ::Window top_level_window = window;
-  ::Window root = x11::None;
-  ::Window parent = x11::None;
-  ::Window* children = nullptr;
-  unsigned int nchildren = 0;
-  // Enumerate all parents of "window" to find the highest level window
-  // that either:
-  //   - has a parent that does not contain the _NET_WM_PID property
-  //   - has a parent that is the root window.
-  while (XQueryTree(display, window, &root, &parent, &children, &nchildren)) {
-    if (children) {
-      XFree(children);
+// Returns true if |window| is visible.
+// Deleted from ui/base/x/x11_util.h in https://crrev.com/62fc260067.
+bool IsWindowVisible(x11::Window window) {
+  auto response = x11::Connection::Get()->GetWindowAttributes({window}).Sync();
+  if (!response || response->map_state != x11::MapState::Viewable) {
+    return false;
+  }
+
+  // Minimized windows are not visible.
+  std::vector<x11::Atom> wm_states;
+  if (x11::GetArrayProperty(window, x11::GetAtom("_NET_WM_STATE"),
+                            &wm_states)) {
+    x11::Atom hidden_atom = x11::GetAtom("_NET_WM_STATE_HIDDEN");
+    if (base::Contains(wm_states, hidden_atom)) {
+      return false;
+    }
+  }
+
+  // Do not check _NET_CURRENT_DESKTOP/_NET_WM_DESKTOP since some
+  // window managers (eg. i3) have per-monitor workspaces where more
+  // than one workspace can be visible at once, but only one will be
+  // "active".
+  return true;
+}
+
+x11::Window FindChild(x11::Window window) {
+  auto query_tree = x11::Connection::Get()->QueryTree({window}).Sync();
+  if (query_tree && query_tree->children.size() == 1U) {
+    return query_tree->children[0];
+  }
+
+  return x11::Window::None;
+}
+
+x11::Window FindToplevelParent(x11::Window window) {
+  x11::Window top_level_window = window;
+
+  do {
+    auto query_tree = x11::Connection::Get()->QueryTree({window}).Sync();
+    if (!query_tree) {
+      break;
     }
 
     top_level_window = window;
-    if (!ui::PropertyExists(parent, kNetWMPid) || parent == root) {
+    if (!PropertyExists(query_tree->parent, x11::GetAtom(kNetWMPid)) ||
+        query_tree->parent == query_tree->root) {
       break;
     }
-    window = parent;
-  }
+
+    window = query_tree->parent;
+  } while (true);
+
   return top_level_window;
 }
 
 }  // namespace
 
 CEF_EXPORT XDisplay* cef_get_xdisplay() {
-  if (!CEF_CURRENTLY_ON(CEF_UIT))
+  if (!CEF_CURRENTLY_ON(CEF_UIT)) {
     return nullptr;
-  return gfx::GetXDisplay();
+  }
+  return x11::Connection::Get()->GetXlibDisplay();
 }
 
-CefWindowX11::CefWindowX11(CefRefPtr<CefBrowserHostImpl> browser,
-                           ::Window parent_xwindow,
+CefWindowX11::CefWindowX11(CefRefPtr<CefBrowserHostBase> browser,
+                           x11::Window parent_xwindow,
                            const gfx::Rect& bounds,
                            const std::string& title)
     : browser_(browser),
-      xdisplay_(gfx::GetXDisplay()),
+      connection_(x11::Connection::Get()),
       parent_xwindow_(parent_xwindow),
-      xwindow_(0),
-      window_mapped_(false),
       bounds_(bounds),
-      focus_pending_(false),
       weak_ptr_factory_(this) {
-  if (parent_xwindow_ == x11::None)
-    parent_xwindow_ = DefaultRootWindow(xdisplay_);
+  if (parent_xwindow_ == x11::Window::None) {
+    parent_xwindow_ = ui::GetX11RootWindow();
+  }
 
-  XSetWindowAttributes swa;
-  memset(&swa, 0, sizeof(swa));
-  swa.background_pixmap = x11::None;
-  swa.override_redirect = false;
-  xwindow_ = XCreateWindow(xdisplay_, parent_xwindow_, bounds.x(), bounds.y(),
-                           bounds.width(), bounds.height(),
-                           0,               // border width
-                           CopyFromParent,  // depth
-                           InputOutput,
-                           CopyFromParent,  // visual
-                           CWBackPixmap | CWOverrideRedirect, &swa);
-  CHECK(xwindow_);
+  x11::VisualId visual;
+  uint8_t depth;
+  x11::ColorMap colormap;
+  ui::XVisualManager::GetInstance()->ChooseVisualForWindow(
+      /*want_argb_visual=*/false, &visual, &depth, &colormap,
+      /*visual_has_alpha=*/nullptr);
+
+  xwindow_ = connection_->GenerateId<x11::Window>();
+
+  connection_->CreateWindow({
+      .depth = depth,
+      .wid = xwindow_,
+      .parent = parent_xwindow_,
+      .x = static_cast<int16_t>(bounds.x()),
+      .y = static_cast<int16_t>(bounds.y()),
+      .width = static_cast<uint16_t>(bounds.width()),
+      .height = static_cast<uint16_t>(bounds.height()),
+      .c_class = x11::WindowClass::InputOutput,
+      .visual = visual,
+      .background_pixel = 0,
+      .border_pixel = 0,
+      .override_redirect = x11::Bool32(false),
+      .colormap = colormap,
+  });
+
+  auto event_mask = x11::EventMask::FocusChange |
+                    x11::EventMask::StructureNotify |
+                    x11::EventMask::PropertyChange;
+  xwindow_events_ =
+      std::make_unique<x11::XScopedEventSelector>(xwindow_, event_mask);
+
+  connection_->Flush();
 
   DCHECK(ui::X11EventSource::HasInstance());
-  ui::X11EventSource::GetInstance()->AddXEventDispatcher(this);
+  connection_->AddEventObserver(this);
+  ui::X11EventSource::GetInstance()->AddPlatformEventDispatcher(this);
 
-  long event_mask = FocusChangeMask | StructureNotifyMask | PropertyChangeMask;
-  XSelectInput(xdisplay_, xwindow_, event_mask);
-  XFlush(xdisplay_);
+  std::vector<x11::Atom> protocols = {
+      x11::GetAtom(kWMDeleteWindow),
+      x11::GetAtom(kNetWMPing),
+  };
+  x11::SetArrayProperty(xwindow_, x11::GetAtom(kWMProtocols), x11::Atom::ATOM,
+                        protocols);
 
-  // TODO(erg): We currently only request window deletion events. We also
-  // should listen for activation events and anything else that GTK+ listens
-  // for, and do something useful.
-  ::Atom protocols[2];
-  protocols[0] = gfx::GetAtom(kWMDeleteWindow);
-  protocols[1] = gfx::GetAtom(kNetWMPing);
-  XSetWMProtocols(xdisplay_, xwindow_, protocols, 2);
-
-  // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
-  // the desktop environment.
-  XSetWMProperties(xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL);
+  // We need a WM_CLIENT_MACHINE value so we integrate with the desktop
+  // environment.
+  x11::SetStringProperty(xwindow_, x11::Atom::WM_CLIENT_MACHINE,
+                         x11::Atom::STRING, net::GetHostName());
 
   // Likewise, the X server needs to know this window's pid so it knows which
   // program to kill if the window hangs.
   // XChangeProperty() expects "pid" to be long.
-  static_assert(sizeof(long) >= sizeof(pid_t),
-                "pid_t should not be larger than long");
-  long pid = getpid();
-  XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom(kNetWMPid), XA_CARDINAL, 32,
-                  PropModeReplace, reinterpret_cast<unsigned char*>(&pid), 1);
+  static_assert(sizeof(uint32_t) >= sizeof(pid_t),
+                "pid_t should not be larger than uint32_t");
+  uint32_t pid = getpid();
+  x11::SetProperty(xwindow_, x11::GetAtom(kNetWMPid), x11::Atom::CARDINAL, pid);
 
   // Set the initial window name, if provided.
   if (!title.empty()) {
-    XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom(kNetWMName),
-                    gfx::GetAtom(kUTF8String), 8, PropModeReplace,
-                    reinterpret_cast<const unsigned char*>(title.c_str()),
-                    title.size());
+    x11::SetStringProperty(xwindow_, x11::Atom::WM_NAME, x11::Atom::STRING,
+                           title);
+    x11::SetStringProperty(xwindow_, x11::Atom::WM_ICON_NAME, x11::Atom::STRING,
+                           title);
   }
 }
 
 CefWindowX11::~CefWindowX11() {
-  DCHECK(!xwindow_);
+  DCHECK_EQ(xwindow_, x11::Window::None);
   DCHECK(ui::X11EventSource::HasInstance());
-  ui::X11EventSource::GetInstance()->RemoveXEventDispatcher(this);
+  connection_->RemoveEventObserver(this);
+  ui::X11EventSource::GetInstance()->RemovePlatformEventDispatcher(this);
 }
 
 void CefWindowX11::Close() {
-  XEvent ev = {0};
-  ev.xclient.type = ClientMessage;
-  ev.xclient.window = xwindow_;
-  ev.xclient.message_type = gfx::GetAtom(kWMProtocols);
-  ev.xclient.format = 32;
-  ev.xclient.data.l[0] = gfx::GetAtom(kWMDeleteWindow);
-  ev.xclient.data.l[1] = x11::CurrentTime;
-  XSendEvent(xdisplay_, xwindow_, false, NoEventMask, &ev);
+  if (xwindow_ == x11::Window::None) {
+    return;
+  }
+
+  ui::SendClientMessage(
+      xwindow_, xwindow_, x11::GetAtom(kWMProtocols),
+      {static_cast<uint32_t>(x11::GetAtom(kWMDeleteWindow)),
+       static_cast<uint32_t>(x11::Time::CurrentTime), 0, 0, 0},
+      x11::EventMask::NoEvent);
 
   auto host = GetHost();
-  if (host)
+  if (host) {
     host->Close();
+  }
 }
 
 void CefWindowX11::Show() {
-  if (xwindow_ == x11::None)
+  if (xwindow_ == x11::Window::None) {
     return;
+  }
 
   if (!window_mapped_) {
     // Before we map the window, set size hints. Otherwise, some window managers
     // will ignore toplevel XMoveWindow commands.
-    XSizeHints size_hints;
-    size_hints.flags = PPosition | PWinGravity;
+    ui::SizeHints size_hints;
+    memset(&size_hints, 0, sizeof(size_hints));
+    ui::GetWmNormalHints(xwindow_, &size_hints);
+    size_hints.flags |= ui::SIZE_HINT_P_POSITION;
     size_hints.x = bounds_.x();
     size_hints.y = bounds_.y();
-    // Set StaticGravity so that the window position is not affected by the
-    // frame width when running with window manager.
-    size_hints.win_gravity = StaticGravity;
-    XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);
+    ui::SetWmNormalHints(xwindow_, size_hints);
 
-    XMapWindow(xdisplay_, xwindow_);
+    connection_->MapWindow({xwindow_});
 
     // TODO(thomasanderson): Find out why this flush is necessary.
-    XFlush(xdisplay_);
+    connection_->Flush();
     window_mapped_ = true;
 
     // Setup the drag and drop proxy on the top level window of the application
     // to be the child of this window.
-    ::Window child = FindChild(xdisplay_, xwindow_);
-    ::Window toplevel_window = FindToplevelParent(xdisplay_, xwindow_);
-    DCHECK(toplevel_window);
-    if (child && toplevel_window) {
+    auto child = FindChild(xwindow_);
+    auto toplevel_window = FindToplevelParent(xwindow_);
+    DCHECK_NE(toplevel_window, x11::Window::None);
+    if (child != x11::Window::None && toplevel_window != x11::Window::None) {
       // Configure the drag&drop proxy property for the top-most window so
       // that all drag&drop-related messages will be sent to the child
-      // DesktopWindowTreeHostX11. The proxy property is referenced by
+      // DesktopWindowTreeHostLinux. The proxy property is referenced by
       // DesktopDragDropClientAuraX11::FindWindowFor.
-      ::Window proxy_target = gfx::kNullAcceleratedWidget;
-      ui::GetXIDProperty(toplevel_window, kXdndProxy, &proxy_target);
+      x11::Window window = x11::Window::None;
+      auto dndproxy_atom = x11::GetAtom(kXdndProxy);
+      x11::GetProperty(toplevel_window, dndproxy_atom, &window);
 
-      if (proxy_target != child) {
+      if (window != child) {
         // Set the proxy target for the top-most window.
-        XChangeProperty(xdisplay_, toplevel_window, gfx::GetAtom(kXdndProxy),
-                        XA_WINDOW, 32, PropModeReplace,
-                        reinterpret_cast<unsigned char*>(&child), 1);
+        x11::SetProperty(toplevel_window, dndproxy_atom, x11::Atom::WINDOW,
+                         child);
         // Do the same for the proxy target per the spec.
-        XChangeProperty(xdisplay_, child, gfx::GetAtom(kXdndProxy), XA_WINDOW,
-                        32, PropModeReplace,
-                        reinterpret_cast<unsigned char*>(&child), 1);
+        x11::SetProperty(child, dndproxy_atom, x11::Atom::WINDOW, child);
       }
     }
   }
 }
 
 void CefWindowX11::Hide() {
-  if (xwindow_ == x11::None)
+  if (xwindow_ == x11::Window::None) {
     return;
+  }
 
   if (window_mapped_) {
-    XWithdrawWindow(xdisplay_, xwindow_, 0);
+    ui::WithdrawWindow(xwindow_);
     window_mapped_ = false;
   }
 }
 
 void CefWindowX11::Focus() {
-  if (xwindow_ == x11::None || !window_mapped_)
+  if (xwindow_ == x11::Window::None || !window_mapped_) {
     return;
+  }
+
+  x11::Window focus_target = xwindow_;
 
   if (browser_.get()) {
-    ::Window child = FindChild(xdisplay_, xwindow_);
-    if (child && ui::IsWindowVisible(child)) {
-      // Give focus to the child DesktopWindowTreeHostX11.
-      XSetInputFocus(xdisplay_, child, RevertToParent, x11::CurrentTime);
+    auto child = FindChild(xwindow_);
+    if (child != x11::Window::None && IsWindowVisible(child)) {
+      // Give focus to the child DesktopWindowTreeHostLinux.
+      focus_target = child;
     }
-  } else {
-    XSetInputFocus(xdisplay_, xwindow_, RevertToParent, x11::CurrentTime);
   }
+
+  // Directly ask the X server to give focus to the window. Note that the call
+  // would have raised an X error if the window is not mapped.
+  connection_
+      ->SetInputFocus(
+          {x11::InputFocus::Parent, focus_target, x11::Time::CurrentTime})
+      .IgnoreError();
 }
 
 void CefWindowX11::SetBounds(const gfx::Rect& bounds) {
-  if (xwindow_ == x11::None)
+  if (xwindow_ == x11::Window::None) {
     return;
+  }
+
+  x11::ConfigureWindowRequest req{.window = xwindow_};
 
   bool origin_changed = bounds_.origin() != bounds.origin();
   bool size_changed = bounds_.size() != bounds.size();
-  XWindowChanges changes = {0};
-  unsigned value_mask = 0;
 
   if (size_changed) {
-    changes.width = bounds.width();
-    changes.height = bounds.height();
-    value_mask = CWHeight | CWWidth;
+    req.width = bounds.width();
+    req.height = bounds.height();
   }
 
   if (origin_changed) {
-    changes.x = bounds.x();
-    changes.y = bounds.y();
-    value_mask |= CWX | CWY;
+    req.x = bounds.x();
+    req.y = bounds.y();
   }
 
-  if (value_mask)
-    XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes);
+  if (origin_changed || size_changed) {
+    connection_->ConfigureWindow(req);
+  }
 }
 
 gfx::Rect CefWindowX11::GetBoundsInScreen() {
-  int x, y;
-  Window child;
-  if (XTranslateCoordinates(xdisplay_, xwindow_, DefaultRootWindow(xdisplay_),
-                            0, 0, &x, &y, &child)) {
-    return gfx::Rect(gfx::Point(x, y), bounds_.size());
+  if (auto coords =
+          connection_
+              ->TranslateCoordinates({xwindow_, ui::GetX11RootWindow(), 0, 0})
+              .Sync()) {
+    return gfx::Rect(gfx::Point(coords->dst_x, coords->dst_y), bounds_.size());
   }
+
   return gfx::Rect();
 }
 
-views::DesktopWindowTreeHostX11* CefWindowX11::GetHost() {
+views::DesktopWindowTreeHostLinux* CefWindowX11::GetHost() {
   if (browser_.get()) {
-    ::Window child = FindChild(xdisplay_, xwindow_);
-    if (child) {
-      return static_cast<views::DesktopWindowTreeHostX11*>(
-          views::DesktopWindowTreeHostLinux::GetHostForWidget(child));
+    auto child = FindChild(xwindow_);
+    if (child != x11::Window::None) {
+      return static_cast<views::DesktopWindowTreeHostLinux*>(
+          views::DesktopWindowTreeHostLinux::GetHostForWidget(
+              static_cast<gfx::AcceleratedWidget>(child)));
     }
   }
   return nullptr;
 }
 
 bool CefWindowX11::CanDispatchEvent(const ui::PlatformEvent& event) {
-  DCHECK_NE(xwindow_, x11::None);
-  return !!current_xevent_;
+  auto* dispatching_event = connection_->dispatching_event();
+  return dispatching_event && dispatching_event->window() == xwindow_;
 }
 
 uint32_t CefWindowX11::DispatchEvent(const ui::PlatformEvent& event) {
-  DCHECK_NE(xwindow_, x11::None);
+  DCHECK_NE(xwindow_, x11::Window::None);
   DCHECK(event);
-  DCHECK(current_xevent_);
 
-  ProcessXEvent(current_xevent_);
+  auto* current_xevent = connection_->dispatching_event();
+  ProcessXEvent(*current_xevent);
   return ui::POST_DISPATCH_STOP_PROPAGATION;
 }
 
-// Called by X11EventSourceLibevent to determine whether this XEventDispatcher
-// implementation is able to process the next translated event sent by it.
-void CefWindowX11::CheckCanDispatchNextPlatformEvent(XEvent* xev) {
-  current_xevent_ = IsTargetedBy(*xev) ? xev : nullptr;
-}
-
-void CefWindowX11::PlatformEventDispatchFinished() {
-  current_xevent_ = nullptr;
-}
-
-ui::PlatformEventDispatcher* CefWindowX11::GetPlatformEventDispatcher() {
-  return this;
-}
-
-bool CefWindowX11::DispatchXEvent(XEvent* xev) {
-  if (!IsTargetedBy(*xev))
-    return false;
-  ProcessXEvent(xev);
-  return true;
+void CefWindowX11::OnEvent(const x11::Event& event) {
+  if (event.window() != xwindow_) {
+    return;
+  }
+  ProcessXEvent(event);
 }
 
 void CefWindowX11::ContinueFocus() {
-  if (!focus_pending_)
+  if (!focus_pending_) {
     return;
-  if (browser_.get())
+  }
+  if (browser_.get()) {
     browser_->SetFocus(true);
+  }
   focus_pending_ = false;
 }
 
 bool CefWindowX11::TopLevelAlwaysOnTop() const {
-  ::Window toplevel_window = FindToplevelParent(xdisplay_, xwindow_);
-
-  Atom state_atom = gfx::GetAtom("_NET_WM_STATE");
-  Atom state_keep_above = gfx::GetAtom("_NET_WM_STATE_KEEP_ABOVE");
-  Atom* states;
-
-  Atom actual_type;
-  int actual_format;
-  unsigned long num_items;
-  unsigned long bytes_after;
-
-  XGetWindowProperty(xdisplay_, toplevel_window, state_atom, 0, 1024,
-                     x11::False, XA_ATOM, &actual_type, &actual_format,
-                     &num_items, &bytes_after,
-                     reinterpret_cast<unsigned char**>(&states));
-
-  bool always_on_top = false;
-
-  for (unsigned long i = 0; i < num_items; ++i) {
-    if (states[i] == state_keep_above) {
-      always_on_top = true;
-      break;
-    }
+  auto toplevel_window = FindToplevelParent(xwindow_);
+  if (toplevel_window == x11::Window::None) {
+    return false;
   }
 
-  XFree(states);
-
-  return always_on_top;
-}
-
-bool CefWindowX11::IsTargetedBy(const XEvent& xev) const {
-  ::Window target_window =
-      (xev.type == GenericEvent)
-          ? static_cast<XIDeviceEvent*>(xev.xcookie.data)->event
-          : xev.xany.window;
-  return target_window == xwindow_;
-}
-
-void CefWindowX11::ProcessXEvent(XEvent* xev) {
-  switch (xev->type) {
-    case ConfigureNotify: {
-      DCHECK_EQ(xwindow_, xev->xconfigure.event);
-      DCHECK_EQ(xwindow_, xev->xconfigure.window);
-      // It's possible that the X window may be resized by some other means
-      // than from within Aura (e.g. the X window manager can change the
-      // size). Make sure the root window size is maintained properly.
-      gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y,
-                       xev->xconfigure.width, xev->xconfigure.height);
-      bounds_ = bounds;
-
-      if (browser_.get()) {
-        ::Window child = FindChild(xdisplay_, xwindow_);
-        if (child) {
-          // Resize the child DesktopWindowTreeHostX11 to match this window.
-          XWindowChanges changes = {0};
-          changes.width = bounds.width();
-          changes.height = bounds.height();
-          XConfigureWindow(xdisplay_, child, CWHeight | CWWidth, &changes);
-
-          browser_->NotifyMoveOrResizeStarted();
-        }
-      }
-      break;
+  std::vector<x11::Atom> wm_states;
+  if (x11::GetArrayProperty(toplevel_window, x11::GetAtom(kNetWMState),
+                            &wm_states)) {
+    x11::Atom keep_above_atom = x11::GetAtom(kNetWMStateKeepAbove);
+    if (base::Contains(wm_states, keep_above_atom)) {
+      return true;
     }
-    case ClientMessage: {
-      Atom message_type = xev->xclient.message_type;
-      if (message_type == gfx::GetAtom(kWMProtocols)) {
-        Atom protocol = static_cast<Atom>(xev->xclient.data.l[0]);
-        if (protocol == gfx::GetAtom(kWMDeleteWindow)) {
-          // We have received a close message from the window manager.
-          if (!browser_ || browser_->TryCloseBrowser()) {
-            // Allow the close.
-            XDestroyWindow(xdisplay_, xwindow_);
+  }
+  return false;
+}
 
-            xwindow_ = x11::None;
+void CefWindowX11::ProcessXEvent(const x11::Event& event) {
+  if (auto* configure = event.As<x11::ConfigureNotifyEvent>()) {
+    DCHECK_EQ(xwindow_, configure->window);
+    // It's possible that the X window may be resized by some other means
+    // than from within Aura (e.g. the X window manager can change the
+    // size). Make sure the root window size is maintained properly.
+    bounds_ = gfx::Rect(configure->x, configure->y, configure->width,
+                        configure->height);
 
-            if (browser_.get()) {
-              // Force the browser to be destroyed and release the reference
-              // added in PlatformCreateWindow().
-              browser_->WindowDestroyed();
-            }
+    if (browser_.get()) {
+      auto child = FindChild(xwindow_);
+      if (child != x11::Window::None) {
+        // Resize the child DesktopWindowTreeHostLinux to match this window.
+        x11::ConfigureWindowRequest req{
+            .window = child,
+            .width = bounds_.width(),
+            .height = bounds_.height(),
+        };
+        connection_->ConfigureWindow(req);
 
-            delete this;
+        browser_->NotifyMoveOrResizeStarted();
+      }
+    }
+  } else if (auto* client = event.As<x11::ClientMessageEvent>()) {
+    if (client->type == x11::GetAtom(kWMProtocols)) {
+      x11::Atom protocol = static_cast<x11::Atom>(client->data.data32[0]);
+      if (protocol == x11::GetAtom(kWMDeleteWindow)) {
+        // We have received a close message from the window manager.
+        if (!browser_ || browser_->TryCloseBrowser()) {
+          // Allow the close.
+          connection_->DestroyWindow({xwindow_});
+          xwindow_ = x11::Window::None;
+
+          if (browser_) {
+            // Force the browser to be destroyed and release the reference
+            // added in PlatformCreateWindow().
+            static_cast<AlloyBrowserHostImpl*>(browser_.get())
+                ->WindowDestroyed();
           }
-        } else if (protocol == gfx::GetAtom(kNetWMPing)) {
-          XEvent reply_event = *xev;
-          reply_event.xclient.window = parent_xwindow_;
 
-          XSendEvent(xdisplay_, reply_event.xclient.window, false,
-                     SubstructureRedirectMask | SubstructureNotifyMask,
-                     &reply_event);
-          XFlush(xdisplay_);
+          delete this;
         }
+      } else if (protocol == x11::GetAtom(kNetWMPing)) {
+        x11::ClientMessageEvent reply_event = *client;
+        reply_event.window = parent_xwindow_;
+        x11::SendEvent(reply_event, reply_event.window,
+                       x11::EventMask::SubstructureNotify |
+                           x11::EventMask::SubstructureRedirect);
       }
-      break;
     }
-    case x11::FocusIn:
+  } else if (auto* focus = event.As<x11::FocusEvent>()) {
+    if (focus->opcode == x11::FocusEvent::In) {
       // This message is received first followed by a "_NET_ACTIVE_WINDOW"
       // message sent to the root window. When X11DesktopHandler handles the
       // "_NET_ACTIVE_WINDOW" message it will erroneously mark the WebView
-      // (hosted in a DesktopWindowTreeHostX11) as unfocused. Use a delayed
+      // (hosted in a DesktopWindowTreeHostLinux) as unfocused. Use a delayed
       // task here to restore the WebView's focus state.
       if (!focus_pending_) {
         focus_pending_ = true;
         CEF_POST_DELAYED_TASK(CEF_UIT,
-                              base::Bind(&CefWindowX11::ContinueFocus,
-                                         weak_ptr_factory_.GetWeakPtr()),
+                              base::BindOnce(&CefWindowX11::ContinueFocus,
+                                             weak_ptr_factory_.GetWeakPtr()),
                               100);
       }
-      break;
-    case x11::FocusOut:
+    } else {
       // Cancel the pending focus change if some other window has gained focus
       // while waiting for the async task to run. Otherwise we can get stuck in
       // a focus change loop.
-      if (focus_pending_)
+      if (focus_pending_) {
         focus_pending_ = false;
-      break;
-    case PropertyNotify: {
-      ::Atom changed_atom = xev->xproperty.atom;
-      if (changed_atom == gfx::GetAtom(kNetWMState)) {
-        // State change event like minimize/maximize.
-        if (browser_.get()) {
-          ::Window child = FindChild(xdisplay_, xwindow_);
-          if (child) {
-            // Forward the state change to the child DesktopWindowTreeHostX11
-            // window so that resource usage will be reduced while the window is
-            // minimized.
-            std::vector<::Atom> atom_list;
-            if (ui::GetAtomArrayProperty(xwindow_, kNetWMState, &atom_list) &&
-                !atom_list.empty()) {
-              ui::SetAtomArrayProperty(child, kNetWMState, "ATOM", atom_list);
-            } else {
-              // Set an empty list of property values to pass the check in
-              // DesktopWindowTreeHostX11::OnWMStateUpdated().
-              XChangeProperty(xdisplay_, child,
-                              gfx::GetAtom(kNetWMState),  // name
-                              gfx::GetAtom(kAtom),        // type
-                              32,  // size in bits of items in 'value'
-                              PropModeReplace, NULL,
-                              0);  // num items
-            }
-          }
+      }
+    }
+  } else if (auto* property = event.As<x11::PropertyNotifyEvent>()) {
+    const auto& wm_state_atom = x11::GetAtom(kNetWMState);
+    if (property->atom == wm_state_atom) {
+      // State change event like minimize/maximize.
+      if (browser_.get()) {
+        auto child = FindChild(xwindow_);
+        if (child != x11::Window::None) {
+          // Forward the state change to the child DesktopWindowTreeHostLinux
+          // window so that resource usage will be reduced while the window is
+          // minimized. |atom_list| may be empty.
+          std::vector<x11::Atom> atom_list;
+          x11::GetArrayProperty(xwindow_, wm_state_atom, &atom_list);
+          x11::SetArrayProperty(child, wm_state_atom, x11::Atom::ATOM,
+                                atom_list);
         }
       }
-      break;
     }
   }
 }
diff --git a/src/libcef/browser/native/window_x11.h b/src/libcef/browser/native/window_x11.h
index dbf841f..3f9616b 100644
--- a/src/libcef/browser/native/window_x11.h
+++ b/src/libcef/browser/native/window_x11.h
@@ -7,32 +7,39 @@
 #define CEF_LIBCEF_BROWSER_NATIVE_WINDOW_X11_H_
 #pragma once
 
-// Avoid including <X11/Xlib.h>
-typedef unsigned long Window;
-struct _XDisplay;
-typedef struct _XDisplay Display;
+#include <memory>
 
-#include "libcef/browser/browser_host_impl.h"
+#include "include/internal/cef_ptr.h"
 
 #include "base/memory/weak_ptr.h"
 #include "ui/events/platform/platform_event_dispatcher.h"
-#include "ui/events/platform/x11/x11_event_source.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/x/connection.h"
 #include "ui/gfx/x/x11_atom_cache.h"
 
-namespace views {
-class DesktopWindowTreeHostX11;
+namespace x11 {
+class XScopedEventSelector;
 }
 
+namespace views {
+class DesktopWindowTreeHostLinux;
+}
+
+class CefBrowserHostBase;
+
 // Object wrapper for an X11 Window.
 // Based on WindowTreeHostX11 and DesktopWindowTreeHostX11.
 class CefWindowX11 : public ui::PlatformEventDispatcher,
-                     public ui::XEventDispatcher {
+                     public x11::EventObserver {
  public:
-  CefWindowX11(CefRefPtr<CefBrowserHostImpl> browser,
-               ::Window parent_xwindow,
+  CefWindowX11(CefRefPtr<CefBrowserHostBase> browser,
+               x11::Window parent_xwindow,
                const gfx::Rect& bounds,
                const std::string& title);
+
+  CefWindowX11(const CefWindowX11&) = delete;
+  CefWindowX11& operator=(const CefWindowX11&) = delete;
+
   ~CefWindowX11() override;
 
   void Close();
@@ -46,19 +53,16 @@
 
   gfx::Rect GetBoundsInScreen();
 
-  views::DesktopWindowTreeHostX11* GetHost();
+  views::DesktopWindowTreeHostLinux* GetHost();
 
   // ui::PlatformEventDispatcher methods:
   bool CanDispatchEvent(const ui::PlatformEvent& event) override;
   uint32_t DispatchEvent(const ui::PlatformEvent& event) override;
 
-  // ui::XEventDispatcher methods:
-  void CheckCanDispatchNextPlatformEvent(XEvent* xev) override;
-  void PlatformEventDispatchFinished() override;
-  ui::PlatformEventDispatcher* GetPlatformEventDispatcher() override;
-  bool DispatchXEvent(XEvent* event) override;
+  // x11::EventObserver methods:
+  void OnEvent(const x11::Event& event) override;
 
-  ::Window xwindow() const { return xwindow_; }
+  x11::Window xwindow() const { return xwindow_; }
   gfx::Rect bounds() const { return bounds_; }
 
   bool TopLevelAlwaysOnTop() const;
@@ -66,33 +70,28 @@
  private:
   void ContinueFocus();
 
-  bool IsTargetedBy(const XEvent& xev) const;
-  void ProcessXEvent(XEvent* xev);
+  void ProcessXEvent(const x11::Event& xev);
 
-  CefRefPtr<CefBrowserHostImpl> browser_;
+  CefRefPtr<CefBrowserHostBase> browser_;
 
   // The display and the native X window hosting the root window.
-  ::Display* xdisplay_;
-  ::Window parent_xwindow_;
-  ::Window xwindow_;
+  x11::Connection* const connection_;
+  x11::Window parent_xwindow_;
+  x11::Window xwindow_;
+
+  // Events selected on |xwindow_|.
+  std::unique_ptr<x11::XScopedEventSelector> xwindow_events_;
 
   // Is the window mapped to the screen?
-  bool window_mapped_;
+  bool window_mapped_ = false;
 
   // The bounds of |xwindow_|.
   gfx::Rect bounds_;
 
-  bool focus_pending_;
-
-  // Tells if this dispatcher can process next translated event based on a
-  // previous check in ::CheckCanDispatchNextPlatformEvent based on a XID
-  // target.
-  XEvent* current_xevent_ = nullptr;
+  bool focus_pending_ = false;
 
   // Must always be the last member.
   base::WeakPtrFactory<CefWindowX11> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefWindowX11);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_NATIVE_WINDOW_X11_H_
diff --git a/src/libcef/browser/navigate_params.cc b/src/libcef/browser/navigate_params.cc
deleted file mode 100644
index be925ef..0000000
--- a/src/libcef/browser/navigate_params.cc
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/navigate_params.h"
-
-CefNavigateParams::CefNavigateParams(const GURL& a_url,
-                                     ui::PageTransition a_transition)
-    : url(a_url), transition(a_transition) {}
-
-CefNavigateParams::~CefNavigateParams() {}
diff --git a/src/libcef/browser/navigate_params.h b/src/libcef/browser/navigate_params.h
deleted file mode 100644
index 92b8980..0000000
--- a/src/libcef/browser/navigate_params.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_BROWSER_NAVIGATE_PARAMS_H_
-#define CEF_LIBCEF_BROWSER_NAVIGATE_PARAMS_H_
-#pragma once
-
-#include <string>
-
-#include "libcef/common/net/upload_data.h"
-
-#include "content/public/browser/global_request_id.h"
-#include "content/public/common/referrer.h"
-#include "ui/base/page_transition_types.h"
-#include "ui/base/window_open_disposition.h"
-#include "url/gurl.h"
-
-// Parameters that tell CefFrameHostImpl::Navigate() what to do.
-struct CefNavigateParams {
-  CefNavigateParams(const GURL& a_url, ui::PageTransition a_transition);
-  ~CefNavigateParams();
-
-  // The following parameters are sent to the renderer via CefMsg_LoadRequest.
-  // ---------------------------------------------------------------------------
-
-  // Request method.
-  std::string method;
-
-  // The URL/referrer to be loaded.
-  GURL url;
-  content::Referrer referrer;
-
-  // Usually the URL of the document in the top-level window, which may be
-  // checked by the third-party cookie blocking policy. Leaving it empty may
-  // lead to undesired cookie blocking. Third-party cookie blocking can be
-  // bypassed by setting site_for_cookies = url, but this should ideally
-  // only be done if there really is no way to determine the correct value.
-  net::SiteForCookies site_for_cookies;
-
-  // Additional HTTP request headers.
-  std::string headers;
-
-  // net::URLRequest load flags (0 by default).
-  int load_flags = 0;
-
-  // Upload data (may be NULL).
-  scoped_refptr<net::UploadData> upload_data;
-
-  // The following parameters are used to define browser behavior when servicing
-  // the navigation request.
-  // ---------------------------------------------------------------------------
-
-  // The disposition requested by the navigation source. Default is CURRENT_TAB.
-  WindowOpenDisposition disposition = WindowOpenDisposition::CURRENT_TAB;
-
-  // The transition type of the navigation.
-  ui::PageTransition transition;
-
-  // Whether this navigation was initiated by the renderer process.
-  bool is_renderer_initiated = false;
-
-  // If non-empty, the new tab contents encoding is overriden by this value.
-  std::string override_encoding;
-
-  // If false then the navigation was not initiated by a user gesture. Default
-  // is true.
-  bool user_gesture = true;
-
-  // Refers to a navigation that was parked in the browser in order to be
-  // transferred to another RVH. Only used in case of a redirection of a request
-  // to a different site that created a new RVH.
-  content::GlobalRequestID transferred_global_request_id;
-
- private:
-  CefNavigateParams();
-};
-
-#endif  // CEF_LIBCEF_BROWSER_NAVIGATE_PARAMS_H_
diff --git a/src/libcef/browser/navigation_entry_impl.cc b/src/libcef/browser/navigation_entry_impl.cc
index f06bb54..669424b 100644
--- a/src/libcef/browser/navigation_entry_impl.cc
+++ b/src/libcef/browser/navigation_entry_impl.cc
@@ -55,11 +55,9 @@
   return mutable_value()->GetHasPostData();
 }
 
-CefTime CefNavigationEntryImpl::GetCompletionTime() {
-  CefTime time;
-  CEF_VALUE_VERIFY_RETURN(false, time);
-  cef_time_from_basetime(mutable_value()->GetTimestamp(), time);
-  return time;
+CefBaseTime CefNavigationEntryImpl::GetCompletionTime() {
+  CEF_VALUE_VERIFY_RETURN(false, CefBaseTime());
+  return mutable_value()->GetTimestamp();
 }
 
 int CefNavigationEntryImpl::GetHttpStatusCode() {
diff --git a/src/libcef/browser/navigation_entry_impl.h b/src/libcef/browser/navigation_entry_impl.h
index 23d10ce..98e89f3 100644
--- a/src/libcef/browser/navigation_entry_impl.h
+++ b/src/libcef/browser/navigation_entry_impl.h
@@ -19,6 +19,9 @@
  public:
   explicit CefNavigationEntryImpl(content::NavigationEntry* value);
 
+  CefNavigationEntryImpl(const CefNavigationEntryImpl&) = delete;
+  CefNavigationEntryImpl& operator=(const CefNavigationEntryImpl&) = delete;
+
   // CefNavigationEntry methods.
   bool IsValid() override;
   CefString GetURL() override;
@@ -27,12 +30,9 @@
   CefString GetTitle() override;
   TransitionType GetTransitionType() override;
   bool HasPostData() override;
-  CefTime GetCompletionTime() override;
+  CefBaseTime GetCompletionTime() override;
   int GetHttpStatusCode() override;
   CefRefPtr<CefSSLStatus> GetSSLStatus() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefNavigationEntryImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_NAVIGATION_ENTRY_IMPL_H_
diff --git a/src/libcef/browser/net/chrome_scheme_handler.cc b/src/libcef/browser/net/chrome_scheme_handler.cc
index fcf6c8f..8aab53f 100644
--- a/src/libcef/browser/net/chrome_scheme_handler.cc
+++ b/src/libcef/browser/net/chrome_scheme_handler.cc
@@ -11,13 +11,12 @@
 #include <utility>
 
 #include "include/cef_version.h"
-#include "include/cef_web_plugin.h"
-#include "libcef/browser/content_browser_client.h"
 #include "libcef/browser/extensions/chrome_api_registration.h"
 #include "libcef/browser/frame_host_impl.h"
 #include "libcef/browser/net/internal_scheme_handler.h"
 #include "libcef/browser/thread_util.h"
-#include "libcef/common/content_client.h"
+#include "libcef/common/app_manager.h"
+#include "libcef/features/runtime.h"
 
 #include "base/command_line.h"
 #include "base/files/file_util.h"
@@ -31,18 +30,23 @@
 #include "base/values.h"
 #include "cef/grit/cef_resources.h"
 #include "chrome/browser/browser_about_handler.h"
+#include "chrome/browser/devtools/devtools_ui_bindings.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/chrome_untrusted_web_ui_configs.h"
 #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
 #include "chrome/browser/ui/webui/theme_source.h"
 #include "chrome/common/url_constants.h"
-#include "content/browser/frame_host/debug_urls.h"
-#include "content/browser/webui/content_web_ui_controller_factory.h"
+#include "content/browser/renderer_host/debug_urls.h"
 #include "content/public/browser/browser_url_handler.h"
+#include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/url_data_source.h"
 #include "content/public/browser/web_ui_controller.h"
+#include "content/public/browser/webui_config_map.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/common/url_utils.h"
 #include "content/public/common/user_agent.h"
 #include "ipc/ipc_channel.h"
+#include "third_party/blink/public/common/chrome_debug_urls.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "v8/include/v8.h"
 
@@ -61,7 +65,7 @@
 // TODO(network): Consider handling content::kChromeDevToolsScheme via WebUI
 // (DevToolsUI class) with the following changes:
 // 1. Add an entry for content::kChromeDevToolsScheme in
-//    CefContentBrowserClient::GetAdditionalWebUISchemes.
+//    AlloyContentBrowserClient::GetAdditionalWebUISchemes.
 // 2. Allow the scheme in CefWebUIControllerFactory::AllowWebUIForURL.
 // 3. Add an entry for chrome::kChromeUIDevToolsHost in kAllowedWebUIHosts and
 //    kUnlistedHosts.
@@ -72,7 +76,6 @@
 // additional changes. Do not add new hosts to this list without also manually
 // testing all related functionality in CEF.
 const char* kAllowedWebUIHosts[] = {
-    content::kChromeUIAppCacheInternalsHost,
     chrome::kChromeUIAccessibilityHost,
     content::kChromeUIBlobInternalsHost,
     chrome::kChromeUIChromeURLsHost,
@@ -90,6 +93,9 @@
     chrome::kChromeUIPrintHost,
     content::kChromeUIProcessInternalsHost,
     content::kChromeUIResourcesHost,
+#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
+    chrome::kChromeUISandboxHost,
+#endif
     content::kChromeUIServiceWorkerInternalsHost,
     chrome::kChromeUISystemInfoHost,
     chrome::kChromeUIThemeHost,
@@ -152,14 +158,20 @@
 bool IsUnlistedHost(const std::string& host) {
   for (size_t i = 0; i < sizeof(kUnlistedHosts) / sizeof(kUnlistedHosts[0]);
        ++i) {
-    if (host == kUnlistedHosts[i])
+    if (host == kUnlistedHosts[i]) {
       return true;
+    }
   }
   return false;
 }
 
 // Returns true if a host is WebUI and should be allowed to load.
 bool IsAllowedWebUIHost(const std::string& host) {
+  // Chrome runtime allows all WebUI hosts.
+  if (cef::IsChromeRuntimeEnabled()) {
+    return true;
+  }
+
   // Explicitly whitelisted WebUI hosts.
   for (size_t i = 0;
        i < sizeof(kAllowedWebUIHosts) / sizeof(kAllowedWebUIHosts[0]); ++i) {
@@ -173,7 +185,7 @@
 
 // Additional debug URLs that are not included in chrome::kChromeDebugURLs.
 const char* kAllowedDebugURLs[] = {
-    content::kChromeUIBrowserCrashURL,
+    blink::kChromeUIBrowserCrashURL,
 };
 
 void GetDebugURLs(std::vector<std::string>* urls) {
@@ -188,37 +200,29 @@
 }
 
 std::string GetOSType() {
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   return "Windows";
-#elif defined(OS_MACOSX)
+#elif BUILDFLAG(IS_MAC)
   return "Mac OS X";
-#elif defined(OS_CHROMEOS)
-  return "Chromium OS";
-#elif defined(OS_ANDROID)
-  return "Android";
-#elif defined(OS_LINUX)
+#elif BUILDFLAG(IS_LINUX)
   return "Linux";
-#elif defined(OS_FREEBSD)
-  return "FreeBSD";
-#elif defined(OS_OPENBSD)
-  return "OpenBSD";
-#elif defined(OS_SOLARIS)
-  return "Solaris";
 #else
   return "Unknown";
 #endif
 }
 
 std::string GetCommandLine() {
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   return base::WideToUTF8(
       base::CommandLine::ForCurrentProcess()->GetCommandLineString());
-#elif defined(OS_POSIX)
+#elif BUILDFLAG(IS_POSIX)
   std::string command_line = "";
-  typedef std::vector<std::string> ArgvList;
+  using ArgvList = std::vector<std::string>;
   const ArgvList& argv = base::CommandLine::ForCurrentProcess()->argv();
-  for (ArgvList::const_iterator iter = argv.begin(); iter != argv.end(); iter++)
+  for (ArgvList::const_iterator iter = argv.begin(); iter != argv.end();
+       iter++) {
     command_line += " " + *iter;
+  }
   // TODO(viettrungluu): |command_line| could really have any encoding, whereas
   // below we assumes it's UTF-8.
   return command_line;
@@ -227,8 +231,9 @@
 
 std::string GetModulePath() {
   base::FilePath path;
-  if (base::PathService::Get(base::FILE_MODULE, &path))
+  if (base::PathService::Get(base::FILE_MODULE, &path)) {
     return CefString(path.value());
+  }
   return std::string();
 }
 
@@ -284,20 +289,32 @@
   }
 
  private:
-  typedef std::map<std::string, std::string> KeyMap;
+  using KeyMap = std::map<std::string, std::string>;
   KeyMap values_;
   std::string ident_start_;
   std::string ident_end_;
 };
 
 bool OnExtensionsSupportUI(std::string* mime_type, std::string* output) {
+  *mime_type = "text/html";
+
+  if (cef::IsChromeRuntimeEnabled()) {
+    // Redirect to the Chrome documentation.
+    *output =
+        "<html><head>\n"
+        "<meta http-equiv=\"refresh\" "
+        "content=\"0;URL='https://developer.chrome.com/docs/extensions/'\"/>\n"
+        "</head></html>\n";
+    return true;
+  }
+
   static const char kDevURL[] = "https://developer.chrome.com/extensions/";
 
   std::string html =
       "<html>\n<head><title>Extensions Support</title></head>\n"
       "<body bgcolor=\"white\"><h3>Supported Chrome Extensions "
       "APIs</h3>\nFollow <a "
-      "href=\"https://bitbucket.org/chromiumembedded/cef/issues/1947\" "
+      "href=\"https://github.com/chromiumembedded/cef/issues/1947\" "
       "target=\"new\">issue #1947</a> for development progress.\n<ul>\n";
 
   bool has_top_level_name = false;
@@ -337,9 +354,7 @@
 
   html += "</ul>\n</body>\n</html>";
 
-  *mime_type = "text/html";
   *output = html;
-
   return true;
 }
 
@@ -348,7 +363,7 @@
       ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
           IDR_CEF_LICENSE_TXT);
   if (piece.empty()) {
-    NOTREACHED() << "Failed to load license txt resource.";
+    DCHECK(false) << "Failed to load license txt resource.";
     return false;
   }
 
@@ -366,7 +381,7 @@
       ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
           IDR_CEF_VERSION_HTML);
   if (tmpl.empty()) {
-    NOTREACHED() << "Failed to load version html resource.";
+    DCHECK(false) << "Failed to load version html resource.";
     return false;
   }
 
@@ -380,8 +395,9 @@
   parser.Add("OS", GetOSType());
   parser.Add("WEBKIT", content::GetWebKitVersion());
   parser.Add("JAVASCRIPT", v8::V8::GetVersion());
-  parser.Add("FLASH", std::string());  // Value populated asynchronously.
-  parser.Add("USERAGENT", CefContentClient::Get()->browser()->GetUserAgent());
+  parser.Add(
+      "USERAGENT",
+      CefAppManager::Get()->GetContentClient()->browser()->GetUserAgent());
   parser.Add("COMMANDLINE", GetCommandLine());
   parser.Add("MODULEPATH", GetModulePath());
   parser.Add("CACHEPATH", CefString(profile->GetPath().value()));
@@ -404,8 +420,9 @@
   std::sort(list.begin(), list.end());
 
   for (size_t i = 0U; i < list.size(); ++i) {
-    if (IsUnlistedHost(list[i]))
+    if (IsUnlistedHost(list[i])) {
       continue;
+    }
 
     html += "<li><a href=\"chrome://" + list[i] + "\">chrome://" + list[i] +
             "</a></li>\n";
@@ -463,6 +480,9 @@
     DCHECK(handled) << "Unhandled WebUI host: " << host;
   }
 
+  CefURLDataSource(const CefURLDataSource&) = delete;
+  CefURLDataSource& operator=(const CefURLDataSource&) = delete;
+
   ~CefURLDataSource() override = default;
 
   // content::URLDataSource implementation.
@@ -475,9 +495,7 @@
     std::move(callback).Run(output_);
   }
 
-  std::string GetMimeType(const std::string& path) override {
-    return mime_type_;
-  }
+  std::string GetMimeType(const GURL& url) override { return mime_type_; }
 
   bool AllowCaching() override { return false; }
 
@@ -488,8 +506,6 @@
 
   std::string mime_type_;
   scoped_refptr<base::RefCountedString> output_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefURLDataSource);
 };
 
 class CefWebUIController : public content::WebUIController {
@@ -503,31 +519,44 @@
         profile, std::make_unique<CefURLDataSource>(host, host_id, profile));
   }
 
-  ~CefWebUIController() override = default;
+  CefWebUIController(const CefWebUIController&) = delete;
+  CefWebUIController& operator=(const CefWebUIController&) = delete;
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefWebUIController);
+  ~CefWebUIController() override = default;
 };
 
 // Intercepts all WebUI calls and either blocks them or forwards them to the
 // Content or Chrome WebUI factory as appropriate.
 class CefWebUIControllerFactory : public content::WebUIControllerFactory {
  public:
+  CefWebUIControllerFactory(const CefWebUIControllerFactory&) = delete;
+  CefWebUIControllerFactory& operator=(const CefWebUIControllerFactory&) =
+      delete;
+
   // Returns true if WebUI is allowed to handle the specified |url|.
   static bool AllowWebUIForURL(const GURL& url) {
-    if (!url.SchemeIs(content::kChromeUIScheme))
-      return false;
+    if (cef::IsChromeRuntimeEnabled() &&
+        url.SchemeIs(content::kChromeDevToolsScheme)) {
+      return DevToolsUIBindings::IsValidFrontendURL(url);
+    }
 
-    if (IsAllowedWebUIHost(url.host()))
+    if (!url.SchemeIs(content::kChromeUIScheme) &&
+        !url.SchemeIs(content::kChromeUIUntrustedScheme)) {
+      return false;
+    }
+
+    if (IsAllowedWebUIHost(url.host())) {
       return true;
+    }
 
     return false;
   }
 
   // Returns true if WebUI is allowed to make network requests.
   static bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin) {
-    if (!AllowWebUIForURL(origin.GetURL()))
+    if (!AllowWebUIForURL(origin.GetURL())) {
       return false;
+    }
 
     if (ChromeWebUIControllerFactory::IsWebUIAllowedToMakeNetworkRequests(
             origin)) {
@@ -541,8 +570,9 @@
       content::WebUI* web_ui,
       const GURL& url) override {
     std::unique_ptr<content::WebUIController> controller;
-    if (!AllowWebUIForURL(url))
+    if (!AllowWebUIForURL(url)) {
       return controller;
+    }
 
     // Set up the chrome://theme/ source. These URLs are referenced from many
     // places (WebUI and chrome://resources which live in //ui). WebUI code
@@ -559,10 +589,12 @@
       return std::make_unique<CefWebUIController>(web_ui, url.host(), host_id);
     }
 
-    controller = content::ContentWebUIControllerFactory::GetInstance()
+    controller = content::WebUIConfigMap::GetInstance()
+                     .controller_factory()
                      ->CreateWebUIControllerForURL(web_ui, url);
-    if (controller.get())
+    if (controller) {
       return controller;
+    }
 
     return ChromeWebUIControllerFactory::GetInstance()
         ->CreateWebUIControllerForURL(web_ui, url);
@@ -571,39 +603,45 @@
   content::WebUI::TypeID GetWebUIType(content::BrowserContext* browser_context,
                                       const GURL& url) override {
     content::WebUI::TypeID type = content::WebUI::kNoWebUI;
-    if (!AllowWebUIForURL(url))
+    if (!AllowWebUIForURL(url)) {
       return type;
+    }
 
     const auto host_id = GetChromeHostId(url.host());
     if (host_id != CHROME_UNKNOWN) {
       return kCefWebUITypeID;
     }
 
-    type = content::ContentWebUIControllerFactory::GetInstance()->GetWebUIType(
-        browser_context, url);
-    if (type != content::WebUI::kNoWebUI)
+    type = content::WebUIConfigMap::GetInstance()
+               .controller_factory()
+               ->GetWebUIType(browser_context, url);
+    if (type != content::WebUI::kNoWebUI) {
       return type;
+    }
 
     type = ChromeWebUIControllerFactory::GetInstance()->GetWebUIType(
         browser_context, url);
-    if (type != content::WebUI::kNoWebUI)
+    if (type != content::WebUI::kNoWebUI) {
       return type;
+    }
 
     return content::WebUI::kNoWebUI;
   }
 
   bool UseWebUIForURL(content::BrowserContext* browser_context,
                       const GURL& url) override {
-    if (!AllowWebUIForURL(url))
+    if (!AllowWebUIForURL(url)) {
       return false;
+    }
 
     const auto host_id = GetChromeHostId(url.host());
     if (host_id != CHROME_UNKNOWN) {
       return true;
     }
 
-    if (content::ContentWebUIControllerFactory::GetInstance()->UseWebUIForURL(
-            browser_context, url) ||
+    if (content::WebUIConfigMap::GetInstance()
+            .controller_factory()
+            ->UseWebUIForURL(browser_context, url) ||
         ChromeWebUIControllerFactory::GetInstance()->UseWebUIForURL(
             browser_context, url)) {
       return true;
@@ -612,44 +650,25 @@
     return false;
   }
 
-  bool UseWebUIBindingsForURL(content::BrowserContext* browser_context,
-                              const GURL& url) override {
-    if (!AllowWebUIForURL(url))
-      return false;
-
-    const auto host_id = GetChromeHostId(url.host());
-    if (host_id != CHROME_UNKNOWN) {
-      // TODO(network): Use WebUI bindings to implement DidFinishChromeLoad.
-      return false;
-    }
-
-    if (content::ContentWebUIControllerFactory::GetInstance()
-            ->UseWebUIBindingsForURL(browser_context, url) ||
-        ChromeWebUIControllerFactory::GetInstance()->UseWebUIBindingsForURL(
-            browser_context, url)) {
-      return true;
-    }
-
-    return false;
-  }
-
   static void BrowserURLHandlerCreated(content::BrowserURLHandler* handler) {
-    // about: handler. Must come before chrome: handler, since it will
-    // rewrite about: urls to chrome: URLs and then expect chrome: to
-    // actually handle them.  Also relies on a preliminary fixup phase.
-    handler->SetFixupHandler(&FixupBrowserAboutURL);
-    handler->AddHandlerPair(&WillHandleBrowserAboutURL,
-                            content::BrowserURLHandler::null_handler());
+    // For Chrome runtime this is registered in
+    // ChromeContentBrowserClient::BrowserURLHandlerCreated().
+    if (cef::IsAlloyRuntimeEnabled()) {
+      // Handler to rewrite chrome://about and chrome://sync URLs.
+      handler->AddHandlerPair(&HandleChromeAboutAndChromeSyncRewrite,
+                              content::BrowserURLHandler::null_handler());
+    }
 
-    // chrome: & friends.
+    // chrome: & friends. For Chrome runtime the default registration is
+    // disabled is ChromeContentBrowserClient::BrowserURLHandlerCreated().
     handler->AddHandlerPair(&HandleWebUI, &HandleWebUIReverse);
   }
 
   static CefWebUIControllerFactory* GetInstance();
 
  protected:
-  CefWebUIControllerFactory() {}
-  ~CefWebUIControllerFactory() override {}
+  CefWebUIControllerFactory() = default;
+  ~CefWebUIControllerFactory() override = default;
 
  private:
   friend struct base::LazyInstanceTraitsBase<CefWebUIControllerFactory>;
@@ -658,8 +677,9 @@
 
   // Handles rewriting Web UI URLs.
   static bool HandleWebUI(GURL* url, content::BrowserContext* browser_context) {
-    if (!GetInstance()->UseWebUIForURL(browser_context, *url))
+    if (!GetInstance()->UseWebUIForURL(browser_context, *url)) {
       return false;
+    }
 
     return true;
   }
@@ -670,8 +690,6 @@
     // No need to actually reverse-rewrite the URL.
     return false;
   }
-
-  DISALLOW_COPY_AND_ASSIGN(CefWebUIControllerFactory);
 };
 
 base::LazyInstance<CefWebUIControllerFactory>::Leaky
@@ -682,64 +700,23 @@
   return &g_web_ui_controller_factory.Get();
 }
 
-void DidFinishChromeVersionLoad(CefRefPtr<CefFrame> frame) {
-  // Retieve Flash version information and update asynchronously.
-  class Visitor : public CefWebPluginInfoVisitor {
-   public:
-    Visitor(CefRefPtr<CefFrame> frame) : frame_(frame) {}
-
-    bool Visit(CefRefPtr<CefWebPluginInfo> info,
-               int count,
-               int total) override {
-      std::string name = info->GetName();
-      if (name == "Shockwave Flash") {
-        if (frame_->IsValid()) {
-          std::string version = info->GetVersion();
-          frame_->ExecuteJavaScript(
-              "document.getElementById('flash').innerText = '" + version + "';",
-              std::string(), 0);
-        }
-        return false;
-      }
-
-      return true;
-    }
-
-   private:
-    CefRefPtr<CefFrame> frame_;
-
-    IMPLEMENT_REFCOUNTING(Visitor);
-  };
-
-  CefVisitWebPluginInfo(new Visitor(frame));
-}
-
 }  // namespace
 
 void RegisterWebUIControllerFactory() {
   // Channel all WebUI handling through CefWebUIControllerFactory.
   content::WebUIControllerFactory::UnregisterFactoryForTesting(
-      content::ContentWebUIControllerFactory::GetInstance());
+      content::WebUIConfigMap::GetInstance().controller_factory());
 
   content::WebUIControllerFactory::RegisterFactory(
       CefWebUIControllerFactory::GetInstance());
+
+  RegisterChromeUntrustedWebUIConfigs();
 }
 
 void BrowserURLHandlerCreated(content::BrowserURLHandler* handler) {
   CefWebUIControllerFactory::BrowserURLHandlerCreated(handler);
 }
 
-void DidFinishChromeLoad(CefRefPtr<CefFrame> frame, const GURL& validated_url) {
-  ChromeHostId host_id = GetChromeHostId(validated_url.host());
-  switch (host_id) {
-    case CHROME_VERSION:
-      DidFinishChromeVersionLoad(frame);
-      break;
-    default:
-      break;
-  }
-}
-
 bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin) {
   return CefWebUIControllerFactory::IsWebUIAllowedToMakeNetworkRequests(origin);
 }
diff --git a/src/libcef/browser/net/chrome_scheme_handler.h b/src/libcef/browser/net/chrome_scheme_handler.h
index f65cf34..6d28be5 100644
--- a/src/libcef/browser/net/chrome_scheme_handler.h
+++ b/src/libcef/browser/net/chrome_scheme_handler.h
@@ -36,9 +36,6 @@
 // Register the WebUI handler.
 void BrowserURLHandlerCreated(content::BrowserURLHandler* handler);
 
-// Used to fire any asynchronous content updates.
-void DidFinishChromeLoad(CefRefPtr<CefFrame> frame, const GURL& validated_url);
-
 // Returns true if WebUI is allowed to make network requests.
 bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin);
 
diff --git a/src/libcef/browser/net/crlset_file_util_impl.cc b/src/libcef/browser/net/crlset_file_util_impl.cc
index fecd791..2f799ba 100644
--- a/src/libcef/browser/net/crlset_file_util_impl.cc
+++ b/src/libcef/browser/net/crlset_file_util_impl.cc
@@ -10,13 +10,13 @@
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "content/public/browser/network_service_instance.h"
-#include "services/network/network_service.h"
+#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
 
 namespace {
 
 void UpdateCRLSet(const std::string& crl_set_bytes) {
   CEF_REQUIRE_UIT();
-  content::GetNetworkService()->UpdateCRLSet(
+  content::GetCertVerifierServiceFactory()->UpdateCRLSet(
       base::as_bytes(base::make_span(crl_set_bytes)), base::DoNothing());
 }
 
@@ -38,7 +38,7 @@
 
 void CefLoadCRLSetsFile(const CefString& path) {
   if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
+    DCHECK(false) << "context not valid";
     return;
   }
 
diff --git a/src/libcef/browser/net/devtools_scheme_handler.cc b/src/libcef/browser/net/devtools_scheme_handler.cc
index e16faaa..97f1204 100644
--- a/src/libcef/browser/net/devtools_scheme_handler.cc
+++ b/src/libcef/browser/net/devtools_scheme_handler.cc
@@ -6,8 +6,8 @@
 
 #include <string>
 
+#include "libcef/browser/iothread_state.h"
 #include "libcef/browser/net/internal_scheme_handler.h"
-#include "libcef/browser/resource_context.h"
 
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_util.h"
@@ -29,8 +29,9 @@
                  Action* action) override {
     GURL url = GURL(request->GetURL().ToString());
     std::string path = url.path();
-    if (path.length() > 0)
+    if (path.length() > 0) {
       path = path.substr(1);
+    }
 
     action->bytes =
         content::DevToolsFrontendHost::GetFrontendResourceBytes(path);
@@ -40,8 +41,8 @@
 
 }  // namespace
 
-void RegisterChromeDevToolsHandler(CefResourceContext* resource_context) {
-  resource_context->RegisterSchemeHandlerFactory(
+void RegisterChromeDevToolsHandler(CefIOThreadState* iothread_state) {
+  iothread_state->RegisterSchemeHandlerFactory(
       content::kChromeDevToolsScheme, kChromeDevToolsHost,
       CreateInternalHandlerFactory(base::WrapUnique(new Delegate())));
 }
diff --git a/src/libcef/browser/net/devtools_scheme_handler.h b/src/libcef/browser/net/devtools_scheme_handler.h
index 667724c..bcde8d6 100644
--- a/src/libcef/browser/net/devtools_scheme_handler.h
+++ b/src/libcef/browser/net/devtools_scheme_handler.h
@@ -6,14 +6,14 @@
 #define CEF_LIBCEF_BROWSER_NET_DEVTOOLS_SCHEME_HANDLER_H_
 #pragma once
 
-class CefResourceContext;
+class CefIOThreadState;
 
 namespace scheme {
 
 extern const char kChromeDevToolsHost[];
 
 // Register the chrome-devtools scheme handler.
-void RegisterChromeDevToolsHandler(CefResourceContext* resource_context);
+void RegisterChromeDevToolsHandler(CefIOThreadState* iothread_state);
 
 }  // namespace scheme
 
diff --git a/src/libcef/browser/net/internal_scheme_handler.cc b/src/libcef/browser/net/internal_scheme_handler.cc
index 5deae26..5967810 100644
--- a/src/libcef/browser/net/internal_scheme_handler.cc
+++ b/src/libcef/browser/net/internal_scheme_handler.cc
@@ -8,8 +8,9 @@
 #include <string>
 #include <utility>
 
-#include "libcef/common/content_client.h"
+#include "libcef/common/app_manager.h"
 
+#include "base/notreached.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
@@ -21,8 +22,8 @@
 namespace {
 
 base::FilePath FilePathFromASCII(const std::string& str) {
-#if defined(OS_WIN)
-  return base::FilePath(base::ASCIIToUTF16(str));
+#if BUILDFLAG(IS_WIN)
+  return base::FilePath(base::ASCIIToWide(str));
 #else
   return base::FilePath(str);
 #endif
@@ -31,20 +32,25 @@
 std::string GetMimeType(const std::string& filename) {
   // Requests should not block on the disk!  On POSIX this goes to disk.
   // http://code.google.com/p/chromium/issues/detail?id=59849
-  base::ThreadRestrictions::ScopedAllowIO allow_io;
+  base::ScopedAllowBlockingForTesting allow_blocking;
 
   std::string mime_type;
   const base::FilePath& file_path = FilePathFromASCII(filename);
-  if (net::GetMimeTypeFromFile(file_path, &mime_type))
+  if (net::GetMimeTypeFromFile(file_path, &mime_type)) {
     return mime_type;
+  }
 
   // Check for newer extensions used by internal resources but not yet
   // recognized by the mime type detector.
   const std::string& extension = CefString(file_path.FinalExtension());
-  if (extension == ".woff2")
+  if (extension == ".md") {
+    return "text/markdown";
+  }
+  if (extension == ".woff2") {
     return "application/font-woff2";
+  }
 
-  NOTREACHED() << "No known mime type for file: " << filename.c_str();
+  DCHECK(false) << "No known mime type for file: " << filename.c_str();
   return "text/plain";
 }
 
@@ -52,6 +58,9 @@
  public:
   explicit RedirectHandler(const GURL& url) : url_(url) {}
 
+  RedirectHandler(const RedirectHandler&) = delete;
+  RedirectHandler& operator=(const RedirectHandler&) = delete;
+
   bool Open(CefRefPtr<CefRequest> request,
             bool& handle_request,
             CefRefPtr<CefCallback> callback) override {
@@ -61,7 +70,7 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
     response_length = 0;
     redirectUrl = url_.spec();
@@ -71,7 +80,7 @@
             int bytes_to_read,
             int& bytes_read,
             CefRefPtr<CefResourceReadCallback> callback) override {
-    NOTREACHED();
+    DCHECK(false);
     return false;
   }
 
@@ -81,7 +90,6 @@
   GURL url_;
 
   IMPLEMENT_REFCOUNTING(RedirectHandler);
-  DISALLOW_COPY_AND_ASSIGN(RedirectHandler);
 };
 
 class InternalHandler : public CefResourceHandler {
@@ -91,6 +99,9 @@
                   int size)
       : mime_type_(mime_type), reader_(reader), size_(size) {}
 
+  InternalHandler(const InternalHandler&) = delete;
+  InternalHandler& operator=(const InternalHandler&) = delete;
+
   bool Open(CefRefPtr<CefRequest> request,
             bool& handle_request,
             CefRefPtr<CefCallback> callback) override {
@@ -100,7 +111,7 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
     response_length = size_;
 
@@ -134,7 +145,6 @@
   int size_;
 
   IMPLEMENT_REFCOUNTING(InternalHandler);
-  DISALLOW_COPY_AND_ASSIGN(InternalHandler);
 };
 
 class InternalHandlerFactory : public CefSchemeHandlerFactory {
@@ -143,6 +153,9 @@
       std::unique_ptr<InternalHandlerDelegate> delegate)
       : delegate_(std::move(delegate)) {}
 
+  InternalHandlerFactory(const InternalHandlerFactory&) = delete;
+  InternalHandlerFactory& operator=(const InternalHandlerFactory&) = delete;
+
   CefRefPtr<CefResourceHandler> Create(CefRefPtr<CefBrowser> browser,
                                        CefRefPtr<CefFrame> frame,
                                        const CefString& scheme_name,
@@ -151,22 +164,25 @@
 
     InternalHandlerDelegate::Action action;
     if (delegate_->OnRequest(browser, request, &action)) {
-      if (!action.redirect_url.is_empty() && action.redirect_url.is_valid())
+      if (!action.redirect_url.is_empty() && action.redirect_url.is_valid()) {
         return new RedirectHandler(action.redirect_url);
+      }
 
-      if (action.mime_type.empty())
+      if (action.mime_type.empty()) {
         action.mime_type = GetMimeType(url.path());
+      }
 
       if (!action.bytes && action.resource_id >= 0) {
         std::string str =
             ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
                 action.resource_id);
         if (str.empty()) {
-          NOTREACHED() << "Failed to load internal resource for id: "
-                       << action.resource_id << " URL: " << url.spec().c_str();
+          DCHECK(false) << "Failed to load internal resource for id: "
+                        << action.resource_id << " URL: " << url.spec().c_str();
           return nullptr;
         }
-        action.bytes = base::RefCountedString::TakeString(&str);
+        action.bytes =
+            base::MakeRefCounted<base::RefCountedString>(std::move(str));
       }
 
       if (action.bytes) {
@@ -189,7 +205,6 @@
   std::unique_ptr<InternalHandlerDelegate> delegate_;
 
   IMPLEMENT_REFCOUNTING(InternalHandlerFactory);
-  DISALLOW_COPY_AND_ASSIGN(InternalHandlerFactory);
 };
 
 }  // namespace
diff --git a/src/libcef/browser/net/scheme_handler.cc b/src/libcef/browser/net/scheme_handler.cc
index d832a8c..347d21f 100644
--- a/src/libcef/browser/net/scheme_handler.cc
+++ b/src/libcef/browser/net/scheme_handler.cc
@@ -9,18 +9,18 @@
 #include "libcef/browser/net/chrome_scheme_handler.h"
 #include "libcef/browser/net/devtools_scheme_handler.h"
 #include "libcef/common/net/scheme_registration.h"
+#include "libcef/features/runtime.h"
 
 #include "content/public/common/url_constants.h"
 
 namespace scheme {
 
-void RegisterInternalHandlers(CefResourceContext* resource_context) {
-  scheme::RegisterChromeDevToolsHandler(resource_context);
-}
+void RegisterInternalHandlers(CefIOThreadState* iothread_state) {
+  if (!cef::IsAlloyRuntimeEnabled()) {
+    return;
+  }
 
-void DidFinishLoad(CefRefPtr<CefFrame> frame, const GURL& validated_url) {
-  if (validated_url.scheme() == content::kChromeUIScheme)
-    scheme::DidFinishChromeLoad(frame, validated_url);
+  scheme::RegisterChromeDevToolsHandler(iothread_state);
 }
 
 }  // namespace scheme
diff --git a/src/libcef/browser/net/scheme_handler.h b/src/libcef/browser/net/scheme_handler.h
index 737c187..a991be3 100644
--- a/src/libcef/browser/net/scheme_handler.h
+++ b/src/libcef/browser/net/scheme_handler.h
@@ -11,15 +11,12 @@
 #include "content/public/browser/browser_context.h"
 #include "url/gurl.h"
 
-class CefResourceContext;
+class CefIOThreadState;
 
 namespace scheme {
 
 // Register the internal scheme handlers that can be overridden.
-void RegisterInternalHandlers(CefResourceContext* resource_context);
-
-// Used to fire any asynchronous content updates.
-void DidFinishLoad(CefRefPtr<CefFrame> frame, const GURL& validated_url);
+void RegisterInternalHandlers(CefIOThreadState* iothread_state);
 
 }  // namespace scheme
 
diff --git a/src/libcef/browser/net/throttle_handler.cc b/src/libcef/browser/net/throttle_handler.cc
new file mode 100644
index 0000000..0665b44
--- /dev/null
+++ b/src/libcef/browser/net/throttle_handler.cc
@@ -0,0 +1,103 @@
+// Copyright 2020 The Chromium Embedded Framework 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 "libcef/browser/net/throttle_handler.h"
+
+#include "libcef/browser/browser_host_base.h"
+#include "libcef/browser/browser_info_manager.h"
+#include "libcef/browser/frame_host_impl.h"
+#include "libcef/common/frame_util.h"
+#include "libcef/common/request_impl.h"
+
+#include "components/navigation_interception/intercept_navigation_throttle.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/navigation_throttle.h"
+#include "content/public/browser/page_navigator.h"
+
+namespace throttle {
+
+namespace {
+
+bool NavigationOnUIThread(content::NavigationHandle* navigation_handle) {
+  CEF_REQUIRE_UIT();
+
+  const bool is_main_frame = navigation_handle->IsInMainFrame();
+  const auto global_id = frame_util::GetGlobalId(navigation_handle);
+
+  // Identify the RenderFrameHost that originated the navigation.
+  const auto parent_global_id =
+      !is_main_frame ? navigation_handle->GetParentFrame()->GetGlobalId()
+                     : frame_util::InvalidGlobalId();
+
+  const content::Referrer referrer(navigation_handle->GetReferrer().url,
+                                   navigation_handle->GetReferrer().policy);
+
+  content::OpenURLParams open_params(navigation_handle->GetURL(), referrer,
+                                     WindowOpenDisposition::CURRENT_TAB,
+                                     navigation_handle->GetPageTransition(),
+                                     navigation_handle->IsRendererInitiated());
+  open_params.user_gesture = navigation_handle->HasUserGesture();
+  open_params.initiator_origin = navigation_handle->GetInitiatorOrigin();
+  open_params.is_pdf = navigation_handle->IsPdf();
+
+  CefRefPtr<CefBrowserHostBase> browser;
+  if (!CefBrowserInfoManager::GetInstance()->MaybeAllowNavigation(
+          navigation_handle->GetWebContents()->GetPrimaryMainFrame(),
+          open_params, browser)) {
+    // Cancel the navigation.
+    return true;
+  }
+
+  bool ignore_navigation = false;
+
+  if (browser) {
+    if (auto client = browser->GetClient()) {
+      if (auto handler = client->GetRequestHandler()) {
+        CefRefPtr<CefFrame> frame;
+        if (is_main_frame) {
+          frame = browser->GetMainFrame();
+        } else {
+          frame = browser->GetFrameForGlobalId(global_id);
+        }
+        if (!frame) {
+          // Create a temporary frame object for navigation of sub-frames that
+          // don't yet exist.
+          frame = browser->browser_info()->CreateTempSubFrame(parent_global_id);
+        }
+
+        CefRefPtr<CefRequestImpl> request = new CefRequestImpl();
+        request->Set(navigation_handle);
+        request->SetReadOnly(true);
+
+        // Initiating a new navigation in OnBeforeBrowse will delete the
+        // InterceptNavigationThrottle that currently owns this callback,
+        // resulting in a crash. Use the lock to prevent that.
+        auto navigation_lock = browser->browser_info()->CreateNavigationLock();
+        ignore_navigation =
+            handler->OnBeforeBrowse(browser.get(), frame, request.get(),
+                                    navigation_handle->HasUserGesture(),
+                                    navigation_handle->WasServerRedirect());
+      }
+    }
+  }
+
+  return ignore_navigation;
+}
+
+}  // namespace
+
+void CreateThrottlesForNavigation(content::NavigationHandle* navigation_handle,
+                                  NavigationThrottleList& throttles) {
+  CEF_REQUIRE_UIT();
+
+  // Must use SynchronyMode::kSync to ensure that OnBeforeBrowse is always
+  // called before OnBeforeResourceLoad.
+  std::unique_ptr<content::NavigationThrottle> throttle =
+      std::make_unique<navigation_interception::InterceptNavigationThrottle>(
+          navigation_handle, base::BindRepeating(&NavigationOnUIThread),
+          navigation_interception::SynchronyMode::kSync);
+  throttles.push_back(std::move(throttle));
+}
+
+}  // namespace throttle
diff --git a/src/libcef/browser/net/throttle_handler.h b/src/libcef/browser/net/throttle_handler.h
new file mode 100644
index 0000000..5810fb4
--- /dev/null
+++ b/src/libcef/browser/net/throttle_handler.h
@@ -0,0 +1,27 @@
+// Copyright 2020 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_NET_THROTTLE_HANDLER_H_
+#define CEF_LIBCEF_BROWSER_NET_THROTTLE_HANDLER_H_
+#pragma once
+
+#include <memory>
+#include <vector>
+
+namespace content {
+class NavigationHandle;
+class NavigationThrottle;
+}  // namespace content
+
+namespace throttle {
+
+using NavigationThrottleList =
+    std::vector<std::unique_ptr<content::NavigationThrottle>>;
+
+void CreateThrottlesForNavigation(content::NavigationHandle* navigation_handle,
+                                  NavigationThrottleList& throttles);
+
+}  // namespace throttle
+
+#endif  // CEF_LIBCEF_BROWSER_NET_THROTTLE_HANDLER_H_
diff --git a/src/libcef/browser/net_service/browser_urlrequest_impl.cc b/src/libcef/browser/net_service/browser_urlrequest_impl.cc
index 81a363f..90f9e26 100644
--- a/src/libcef/browser/net_service/browser_urlrequest_impl.cc
+++ b/src/libcef/browser/net_service/browser_urlrequest_impl.cc
@@ -21,8 +21,10 @@
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
 #include "base/strings/string_util.h"
+#include "content/browser/renderer_host/render_frame_host_impl.h"
+#include "content/browser/storage_partition_impl.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/global_request_id.h"
 #include "content/public/browser/render_frame_host.h"
 #include "net/base/mime_util.h"
@@ -50,10 +52,18 @@
   return --request_id;
 }
 
+bool IsValidRequestID(int32_t request_id) {
+  return request_id < kInitialRequestID;
+}
+
 // Manages the mapping of request IDs to request objects.
 class RequestManager {
  public:
   RequestManager() {}
+
+  RequestManager(const RequestManager&) = delete;
+  RequestManager& operator=(const RequestManager&) = delete;
+
   ~RequestManager() { DCHECK(map_.empty()); }
 
   void Add(int32_t request_id,
@@ -67,8 +77,9 @@
   }
 
   void Remove(int32_t request_id) {
-    if (request_id > kInitialRequestID)
+    if (request_id > kInitialRequestID) {
       return;
+    }
 
     base::AutoLock lock_scope(lock_);
     RequestMap::iterator it = map_.find(request_id);
@@ -76,16 +87,17 @@
     map_.erase(it);
   }
 
-  base::Optional<CefBrowserURLRequest::RequestInfo> Get(int32_t request_id) {
-    if (request_id > kInitialRequestID)
-      return base::nullopt;
+  absl::optional<CefBrowserURLRequest::RequestInfo> Get(int32_t request_id) {
+    if (request_id > kInitialRequestID) {
+      return absl::nullopt;
+    }
 
     base::AutoLock lock_scope(lock_);
     RequestMap::const_iterator it = map_.find(request_id);
     if (it != map_.end()) {
       return it->second;
     }
-    return base::nullopt;
+    return absl::nullopt;
   }
 
  private:
@@ -93,8 +105,6 @@
 
   using RequestMap = std::map<int32_t, CefBrowserURLRequest::RequestInfo>;
   RequestMap map_;
-
-  DISALLOW_COPY_AND_ASSIGN(RequestManager);
 };
 
 #if DCHECK_IS_ON()
@@ -135,15 +145,22 @@
     DCHECK(CalledOnValidThread());
 
     const GURL& url = GURL(request_->GetURL().ToString());
-    if (!url.is_valid())
+    if (!url.is_valid()) {
       return false;
+    }
 
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::BindOnce(
-            &CefBrowserURLRequest::Context::GetURLLoaderFactoryGetterOnUIThread,
-            frame_, request_context_, weak_ptr_factory_.GetWeakPtr(),
-            task_runner_));
+    if (!request_context_) {
+      request_context_ = CefRequestContext::GetGlobalContext();
+    }
+
+    auto request_context_impl =
+        static_cast<CefRequestContextImpl*>(request_context_.get());
+
+    // Wait for the browser context to be initialized before continuing.
+    request_context_impl->ExecuteWhenBrowserContextInitialized(base::BindOnce(
+        &CefBrowserURLRequest::Context::GetURLLoaderFactoryGetterOnUIThread,
+        frame_, request_context_, weak_ptr_factory_.GetWeakPtr(),
+        task_runner_));
 
     return true;
   }
@@ -152,8 +169,9 @@
     DCHECK(CalledOnValidThread());
 
     // The request may already be complete or canceled.
-    if (!url_request_)
+    if (!url_request_) {
       return;
+    }
 
     DCHECK_EQ(status_, UR_IO_PENDING);
     status_ = UR_CANCELED;
@@ -184,55 +202,57 @@
       scoped_refptr<base::SequencedTaskRunner> task_runner) {
     CEF_REQUIRE_UIT();
 
-    // Get or create the request context and browser context.
-    CefRefPtr<CefRequestContextImpl> request_context_impl =
-        CefRequestContextImpl::GetOrCreateForRequestContext(request_context);
-    DCHECK(request_context_impl);
-    CefBrowserContext* browser_context =
-        request_context_impl->GetBrowserContext();
-    DCHECK(browser_context);
+    auto* browser_context =
+        CefRequestContextImpl::GetBrowserContext(request_context);
+    CHECK(browser_context);
 
-    int render_frame_id = MSG_ROUTING_NONE;
     scoped_refptr<net_service::URLLoaderFactoryGetter> loader_factory_getter;
+
+    // Used to route authentication and certificate callbacks through the
+    // associated StoragePartition instance.
+    mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
+        url_loader_network_observer;
+
     if (frame) {
       // The request will be associated with this frame/browser if it's valid,
       // otherwise the request will be canceled.
       content::RenderFrameHost* rfh =
           static_cast<CefFrameHostImpl*>(frame.get())->GetRenderFrameHost();
       if (rfh) {
-        // In cases where authentication is required this value will be passed
-        // as the |routing_id| parameter to
-        // NetworkServiceClient::OnAuthRequired. Despite the naming the
-        // GetWebContents method in network_service_client.cc expects it to be a
-        // FrameTreeNodeId. The |process_id| parameter will always be
-        // network::mojom::kBrowserProcessId (value 0) for these requests.
-        render_frame_id = rfh->GetFrameTreeNodeId();
-
         loader_factory_getter =
             net_service::URLLoaderFactoryGetter::Create(rfh, browser_context);
+        url_loader_network_observer =
+            static_cast<content::RenderFrameHostImpl*>(rfh)
+                ->CreateURLLoaderNetworkObserver();
       }
     } else {
       loader_factory_getter =
           net_service::URLLoaderFactoryGetter::Create(nullptr, browser_context);
+      url_loader_network_observer =
+          static_cast<content::StoragePartitionImpl*>(
+              browser_context->GetDefaultStoragePartition())
+              ->CreateAuthCertObserverForServiceWorker();
     }
 
     task_runner->PostTask(
         FROM_HERE,
         base::BindOnce(
             &CefBrowserURLRequest::Context::ContinueOnOriginatingThread, self,
-            render_frame_id, MakeRequestID(), loader_factory_getter));
+            MakeRequestID(), loader_factory_getter,
+            std::move(url_loader_network_observer)));
   }
 
   void ContinueOnOriginatingThread(
-      int render_frame_id,
       int32_t request_id,
-      scoped_refptr<net_service::URLLoaderFactoryGetter>
-          loader_factory_getter) {
+      scoped_refptr<net_service::URLLoaderFactoryGetter> loader_factory_getter,
+      mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
+          url_loader_network_observer) {
     DCHECK(CalledOnValidThread());
 
     // The request may have been canceled.
-    if (!url_request_)
+    if (!url_request_) {
       return;
+    }
 
     if (!loader_factory_getter) {
       // Cancel the request immediately.
@@ -253,11 +273,7 @@
     static_cast<CefRequestImpl*>(request_.get())
         ->Get(resource_request.get(), false);
 
-    resource_request->render_frame_id = render_frame_id;
-
     // Behave the same as a subresource load.
-    resource_request->fetch_request_context_type =
-        static_cast<int>(blink::mojom::RequestContextType::SUBRESOURCE);
     resource_request->resource_type =
         static_cast<int>(blink::mojom::ResourceType::kSubResource);
 
@@ -267,11 +283,17 @@
 
     if (request_flags & UR_FLAG_ALLOW_STORED_CREDENTIALS) {
       // Include SameSite cookies.
-      resource_request->attach_same_site_cookies = true;
       resource_request->site_for_cookies =
           net::SiteForCookies::FromOrigin(*resource_request->request_initiator);
     }
 
+    if (url_loader_network_observer) {
+      resource_request->trusted_params =
+          network::ResourceRequest::TrustedParams();
+      resource_request->trusted_params->url_loader_network_observer =
+          std::move(url_loader_network_observer);
+    }
+
     // SimpleURLLoader is picky about the body contents. Try to populate them
     // correctly below.
     auto request_body = resource_request->request_body;
@@ -304,33 +326,35 @@
     if (request_body) {
       if (request_body->elements()->size() == 1) {
         const auto& element = (*request_body->elements())[0];
-        if (element.type() == network::mojom::DataElementType::kFile) {
+        if (element.type() == network::DataElement::Tag::kFile) {
+          const auto& file_element = element.As<network::DataElementFile>();
           if (content_type.empty()) {
-            const auto& extension = element.path().Extension();
+            const auto& extension = file_element.path().Extension();
             if (!extension.empty()) {
               // Requests should not block on the disk! On POSIX this goes to
               // disk. http://code.google.com/p/chromium/issues/detail?id=59849
-              base::ThreadRestrictions::ScopedAllowIO allow_io;
+              base::ScopedAllowBlockingForTesting allow_blocking;
               // Also remove the leading period.
               net::GetMimeTypeFromExtension(extension.substr(1), &content_type);
             }
           }
-          loader_->AttachFileForUpload(element.path(), content_type);
-        } else if (element.type() == network::mojom::DataElementType::kBytes) {
+          loader_->AttachFileForUpload(file_element.path(), content_type);
+        } else if (element.type() == network::DataElement::Tag::kBytes) {
+          const auto& bytes_element = element.As<network::DataElementBytes>();
+          const auto& bytes = bytes_element.bytes();
           if (content_type.empty()) {
             content_type = net_service::kContentTypeApplicationFormURLEncoded;
           }
           loader_->AttachStringForUpload(
-              std::string(element.bytes() + element.offset(),
-                          element.length() - element.offset()),
-              content_type);
+              std::string(bytes_element.AsStringPiece()), content_type);
 
           if (request_flags & UR_FLAG_REPORT_UPLOAD_PROGRESS) {
             // Report the expected upload data size.
-            upload_data_size_ = element.length() - element.offset();
+            upload_data_size_ = bytes.size();
           }
         } else {
-          NOTIMPLEMENTED() << "Unsupported element type: " << element.type();
+          NOTIMPLEMENTED() << "Unsupported element type: "
+                           << static_cast<int>(element.type());
         }
       } else if (request_body->elements()->size() > 1) {
         NOTIMPLEMENTED() << "Multi-part form data is not supported";
@@ -352,14 +376,14 @@
     if (request_flags & UR_FLAG_STOP_ON_REDIRECT) {
       // The request will be canceled in OnRedirect.
       loader_->SetOnRedirectCallback(
-          base::Bind(&CefBrowserURLRequest::Context::OnRedirect,
-                     weak_ptr_factory_.GetWeakPtr()));
+          base::BindRepeating(&CefBrowserURLRequest::Context::OnRedirect,
+                              weak_ptr_factory_.GetWeakPtr()));
     }
 
     if (request_flags & UR_FLAG_REPORT_UPLOAD_PROGRESS) {
       loader_->SetOnUploadProgressCallback(
-          base::Bind(&CefBrowserURLRequest::Context::OnUploadProgress,
-                     weak_ptr_factory_.GetWeakPtr()));
+          base::BindRepeating(&CefBrowserURLRequest::Context::OnUploadProgress,
+                              weak_ptr_factory_.GetWeakPtr()));
     }
 
     if ((request_flags & UR_FLAG_NO_DOWNLOAD_DATA) || method == "HEAD") {
@@ -371,9 +395,9 @@
       loader_->SetOnResponseStartedCallback(
           base::BindOnce(&CefBrowserURLRequest::Context::OnResponseStarted,
                          weak_ptr_factory_.GetWeakPtr()));
-      loader_->SetOnDownloadProgressCallback(
-          base::Bind(&CefBrowserURLRequest::Context::OnDownloadProgress,
-                     weak_ptr_factory_.GetWeakPtr()));
+      loader_->SetOnDownloadProgressCallback(base::BindRepeating(
+          &CefBrowserURLRequest::Context::OnDownloadProgress,
+          weak_ptr_factory_.GetWeakPtr()));
 
       loader_->DownloadAsStream(loader_factory.get(), this);
     }
@@ -383,22 +407,28 @@
     DCHECK(CalledOnValidThread());
     DCHECK_EQ(status_, UR_IO_PENDING);
 
-    response_->SetReadOnly(false);
-    response_->SetResponseHeaders(*headers);
-    response_->SetReadOnly(true);
-
-    // Match the previous behavior of sending download progress notifications
-    // for UR_FLAG_NO_DOWNLOAD_DATA requests but not HEAD requests.
-    if (request_->GetMethod().ToString() != "HEAD") {
-      download_data_size_ = headers->GetContentLength();
-      OnDownloadProgress(0);
-    }
-
     cleanup_immediately_ = true;
-    OnComplete(true);
+
+    if (headers) {
+      response_->SetReadOnly(false);
+      response_->SetResponseHeaders(*headers);
+      response_->SetReadOnly(true);
+
+      // Match the previous behavior of sending download progress notifications
+      // for UR_FLAG_NO_DOWNLOAD_DATA requests but not HEAD requests.
+      if (request_->GetMethod().ToString() != "HEAD") {
+        download_data_size_ = headers->GetContentLength();
+        OnDownloadProgress(0);
+      }
+
+      OnComplete(true);
+    } else {
+      OnComplete(false);
+    }
   }
 
-  void OnRedirect(const net::RedirectInfo& redirect_info,
+  void OnRedirect(const GURL& url_before_redirect,
+                  const net::RedirectInfo& redirect_info,
                   const network::mojom::URLResponseHead& response_head,
                   std::vector<std::string>* removed_headers) {
     DCHECK(CalledOnValidThread());
@@ -433,8 +463,9 @@
     DCHECK_EQ(status_, UR_IO_PENDING);
 
     upload_data_size_ = total;
-    if (position == total)
+    if (position == total) {
       got_upload_progress_complete_ = true;
+    }
 
     client_->OnUploadProgress(url_request_.get(), position, total);
   }
@@ -481,8 +512,9 @@
     DCHECK(CalledOnValidThread());
 
     // The request may already be complete or canceled.
-    if (!url_request_)
+    if (!url_request_) {
       return;
+    }
 
     // Status will be UR_IO_PENDING if we're called when the request is complete
     // (via SimpleURLLoaderStreamConsumer or OnHeadersOnly). We can only call
@@ -498,8 +530,9 @@
       response_was_cached_ = loader_->LoadedFromCache();
     }
 
-    if (success)
+    if (success) {
       NotifyUploadProgressIfNecessary();
+    }
 
     client_->OnRequestComplete(url_request_.get());
 
@@ -561,8 +594,8 @@
   CefURLRequest::Status status_ = UR_IO_PENDING;
   CefRefPtr<CefResponseImpl> response_;
   bool response_was_cached_ = false;
-  int64 upload_data_size_ = 0;
-  int64 download_data_size_ = -1;
+  int64_t upload_data_size_ = 0;
+  int64_t download_data_size_ = -1;
   bool got_upload_progress_complete_ = false;
   bool cleanup_immediately_ = false;
 
@@ -573,19 +606,19 @@
 // CefBrowserURLRequest -------------------------------------------------------
 
 // static
-base::Optional<CefBrowserURLRequest::RequestInfo>
+absl::optional<CefBrowserURLRequest::RequestInfo>
 CefBrowserURLRequest::FromRequestID(int32_t request_id) {
-  return g_manager.Get().Get(request_id);
+  if (IsValidRequestID(request_id)) {
+    return g_manager.Get().Get(request_id);
+  }
+  return absl::nullopt;
 }
 
 // static
-base::Optional<CefBrowserURLRequest::RequestInfo>
+absl::optional<CefBrowserURLRequest::RequestInfo>
 CefBrowserURLRequest::FromRequestID(
     const content::GlobalRequestID& request_id) {
-  if (request_id.child_id == network::mojom::kBrowserProcessId) {
-    return FromRequestID(request_id.request_id);
-  }
-  return base::nullopt;
+  return FromRequestID(request_id.request_id);
 }
 
 CefBrowserURLRequest::CefBrowserURLRequest(
@@ -599,56 +632,64 @@
 CefBrowserURLRequest::~CefBrowserURLRequest() {}
 
 bool CefBrowserURLRequest::Start() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
   return context_->Start();
 }
 
 CefRefPtr<CefRequest> CefBrowserURLRequest::GetRequest() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return nullptr;
+  }
   return context_->request();
 }
 
 CefRefPtr<CefURLRequestClient> CefBrowserURLRequest::GetClient() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return nullptr;
+  }
   return context_->client();
 }
 
 CefURLRequest::Status CefBrowserURLRequest::GetRequestStatus() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return UR_UNKNOWN;
+  }
   return context_->status();
 }
 
 CefURLRequest::ErrorCode CefBrowserURLRequest::GetRequestError() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return ERR_NONE;
+  }
   return context_->response()->GetError();
 }
 
 CefRefPtr<CefResponse> CefBrowserURLRequest::GetResponse() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return nullptr;
+  }
   return context_->response();
 }
 
 bool CefBrowserURLRequest::ResponseWasCached() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
   return context_->response_was_cached();
 }
 
 void CefBrowserURLRequest::Cancel() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return;
+  }
   return context_->Cancel();
 }
 
 bool CefBrowserURLRequest::VerifyContext() {
   if (!context_->CalledOnValidThread()) {
-    NOTREACHED() << "called on invalid thread";
+    DCHECK(false) << "called on invalid thread";
     return false;
   }
 
diff --git a/src/libcef/browser/net_service/browser_urlrequest_impl.h b/src/libcef/browser/net_service/browser_urlrequest_impl.h
index 45f5a67..21843b9 100644
--- a/src/libcef/browser/net_service/browser_urlrequest_impl.h
+++ b/src/libcef/browser/net_service/browser_urlrequest_impl.h
@@ -9,7 +9,7 @@
 
 #include "include/cef_urlrequest.h"
 
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace content {
 struct GlobalRequestID;
@@ -27,8 +27,8 @@
                                 CefRefPtr<CefURLRequestClient>>;
 
   // Retrieve the request objects, if any, associated with |request_id|.
-  static base::Optional<RequestInfo> FromRequestID(int32_t request_id);
-  static base::Optional<RequestInfo> FromRequestID(
+  static absl::optional<RequestInfo> FromRequestID(int32_t request_id);
+  static absl::optional<RequestInfo> FromRequestID(
       const content::GlobalRequestID& request_id);
 
   // If |frame| is nullptr requests can still be intercepted but no
diff --git a/src/libcef/browser/net_service/cookie_helper.cc b/src/libcef/browser/net_service/cookie_helper.cc
index 25de20d..ba7e8e6 100644
--- a/src/libcef/browser/net_service/cookie_helper.cc
+++ b/src/libcef/browser/net_service/cookie_helper.cc
@@ -7,9 +7,10 @@
 #include "libcef/browser/thread_util.h"
 #include "libcef/common/net_service/net_service_util.h"
 
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/storage_partition.h"
+#include "content/public/common/url_constants.h"
 #include "net/base/load_flags.h"
 #include "net/cookies/cookie_options.h"
 #include "net/cookies/cookie_util.h"
@@ -17,54 +18,119 @@
 #include "services/network/public/cpp/resource_request.h"
 
 namespace net_service {
+namespace cookie_helper {
 
 namespace {
 
-// Do not keep a reference to the CookieManager returned by this method.
+// Do not keep a reference to the object returned by this method.
+CefBrowserContext* GetBrowserContext(const CefBrowserContext::Getter& getter) {
+  CEF_REQUIRE_UIT();
+  DCHECK(!getter.is_null());
+
+  // Will return nullptr if the BrowserContext has been shut down.
+  return getter.Run();
+}
+
+// Do not keep a reference to the object returned by this method.
 network::mojom::CookieManager* GetCookieManager(
     content::BrowserContext* browser_context) {
   CEF_REQUIRE_UIT();
-  return content::BrowserContext::GetDefaultStoragePartition(browser_context)
+  return browser_context->GetDefaultStoragePartition()
       ->GetCookieManagerForBrowserProcess();
 }
 
+net::CookieOptions GetCookieOptions(const network::ResourceRequest& request,
+                                    bool for_loading_cookies) {
+  // Match the logic from InterceptionJob::FetchCookies and
+  // ChromeContentBrowserClient::ShouldIgnoreSameSiteCookieRestrictionsWhenTopLevel.
+  bool should_treat_as_first_party =
+      request.url.SchemeIsCryptographic() &&
+      request.site_for_cookies.scheme() == content::kChromeUIScheme;
+  bool is_main_frame_navigation =
+      request.trusted_params &&
+      request.trusted_params->isolation_info.request_type() ==
+          net::IsolationInfo::RequestType::kMainFrame;
+
+  // Match the logic from URLRequest::SetURLChain.
+  std::vector<GURL> url_chain{request.url};
+  if (request.navigation_redirect_chain.size() >= 2) {
+    // Keep |request.url| as the final entry in the chain.
+    url_chain.insert(url_chain.begin(),
+                     request.navigation_redirect_chain.begin(),
+                     request.navigation_redirect_chain.begin() +
+                         request.navigation_redirect_chain.size() - 1);
+  }
+
+  net::CookieOptions options;
+  options.set_include_httponly();
+  if (for_loading_cookies) {
+    // Match the logic from URLRequestHttpJob::AddCookieHeaderAndStart.
+    options.set_same_site_cookie_context(
+        net::cookie_util::ComputeSameSiteContextForRequest(
+            request.method, url_chain, request.site_for_cookies,
+            request.request_initiator, is_main_frame_navigation,
+            should_treat_as_first_party));
+  } else {
+    // Match the logic from
+    // URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete.
+    options.set_same_site_cookie_context(
+        net::cookie_util::ComputeSameSiteContextForResponse(
+            url_chain, request.site_for_cookies, request.request_initiator,
+            is_main_frame_navigation, should_treat_as_first_party));
+  }
+
+  return options;
+}
+
 //
 // LOADING COOKIES.
 //
 
 void ContinueWithLoadedCookies(const AllowCookieCallback& allow_cookie_callback,
                                DoneCookieCallback done_callback,
-                               const net::CookieStatusList& cookies) {
+                               const net::CookieAccessResultList& cookies) {
   CEF_REQUIRE_IOT();
   net::CookieList allowed_cookies;
   for (const auto& status : cookies) {
     bool allow = false;
     allow_cookie_callback.Run(status.cookie, &allow);
-    if (allow)
+    if (allow) {
       allowed_cookies.push_back(status.cookie);
+    }
   }
   std::move(done_callback).Run(cookies.size(), std::move(allowed_cookies));
 }
 
 void GetCookieListCallback(const AllowCookieCallback& allow_cookie_callback,
                            DoneCookieCallback done_callback,
-                           const net::CookieStatusList& included_cookies,
-                           const net::CookieStatusList&) {
+                           const net::CookieAccessResultList& included_cookies,
+                           const net::CookieAccessResultList&) {
   CEF_REQUIRE_UIT();
   CEF_POST_TASK(CEF_IOT,
                 base::BindOnce(ContinueWithLoadedCookies, allow_cookie_callback,
                                std::move(done_callback), included_cookies));
 }
 
-void LoadCookiesOnUIThread(content::BrowserContext* browser_context,
-                           const GURL& url,
-                           const net::CookieOptions& options,
-                           const AllowCookieCallback& allow_cookie_callback,
-                           DoneCookieCallback done_callback) {
-  CEF_REQUIRE_UIT();
+void LoadCookiesOnUIThread(
+    const CefBrowserContext::Getter& browser_context_getter,
+    const GURL& url,
+    const net::CookieOptions& options,
+    net::CookiePartitionKeyCollection cookie_partition_key_collection,
+    const AllowCookieCallback& allow_cookie_callback,
+    DoneCookieCallback done_callback) {
+  auto cef_browser_context = GetBrowserContext(browser_context_getter);
+  auto browser_context =
+      cef_browser_context ? cef_browser_context->AsBrowserContext() : nullptr;
+  if (!browser_context) {
+    GetCookieListCallback(allow_cookie_callback, std::move(done_callback),
+                          net::CookieAccessResultList(),
+                          net::CookieAccessResultList());
+    return;
+  }
+
   GetCookieManager(browser_context)
       ->GetCookieList(
-          url, options,
+          url, options, cookie_partition_key_collection,
           base::BindOnce(GetCookieListCallback, allow_cookie_callback,
                          std::move(done_callback)));
 }
@@ -80,13 +146,12 @@
   int num_cookie_lines_left_;
 };
 
-void SetCanonicalCookieCallback(
-    SaveCookiesProgress* progress,
-    const net::CanonicalCookie& cookie,
-    net::CanonicalCookie::CookieInclusionStatus status) {
+void SetCanonicalCookieCallback(SaveCookiesProgress* progress,
+                                const net::CanonicalCookie& cookie,
+                                net::CookieAccessResult access_result) {
   CEF_REQUIRE_UIT();
   progress->num_cookie_lines_left_--;
-  if (status.IsInclude()) {
+  if (access_result.status.IsInclude()) {
     progress->allowed_cookies_.push_back(cookie);
   }
 
@@ -100,15 +165,23 @@
   }
 }
 
-void SaveCookiesOnUIThread(content::BrowserContext* browser_context,
-                           const GURL& url,
-                           const net::CookieOptions& options,
-                           int total_count,
-                           net::CookieList cookies,
-                           DoneCookieCallback done_callback) {
-  CEF_REQUIRE_UIT();
+void SaveCookiesOnUIThread(
+    const CefBrowserContext::Getter& browser_context_getter,
+    const GURL& url,
+    const net::CookieOptions& options,
+    int total_count,
+    net::CookieList cookies,
+    DoneCookieCallback done_callback) {
   DCHECK(!cookies.empty());
 
+  auto cef_browser_context = GetBrowserContext(browser_context_getter);
+  auto browser_context =
+      cef_browser_context ? cef_browser_context->AsBrowserContext() : nullptr;
+  if (!browser_context) {
+    std::move(done_callback).Run(0, net::CookieList());
+    return;
+  }
+
   network::mojom::CookieManager* cookie_manager =
       GetCookieManager(browser_context);
 
@@ -125,20 +198,44 @@
   for (const auto& cookie : cookies) {
     progress->num_cookie_lines_left_++;
     cookie_manager->SetCanonicalCookie(
-        cookie, url.scheme(), options,
+        cookie, url, options,
         base::BindOnce(&SetCanonicalCookieCallback, base::Unretained(progress),
                        cookie));
   }
 
   SetCanonicalCookieCallback(
       progress, net::CanonicalCookie(),
-      net::CanonicalCookie::CookieInclusionStatus(
-          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR));
+      net::CookieAccessResult(net::CookieInclusionStatus(
+          net::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR)));
 }
 
 }  // namespace
 
-void LoadCookies(content::BrowserContext* browser_context,
+bool IsCookieableScheme(
+    const GURL& url,
+    const absl::optional<std::vector<std::string>>& cookieable_schemes) {
+  if (!url.has_scheme()) {
+    return false;
+  }
+
+  if (cookieable_schemes) {
+    // The client has explicitly registered the full set of schemes that should
+    // be supported.
+    const auto url_scheme = url.scheme_piece();
+    for (auto scheme : *cookieable_schemes) {
+      if (url_scheme == scheme) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  // Schemes that support cookies by default.
+  // This should match CookieMonster::kDefaultCookieableSchemes.
+  return url.SchemeIsHTTPOrHTTPS() || url.SchemeIsWSOrWSS();
+}
+
+void LoadCookies(const CefBrowserContext::Getter& browser_context_getter,
                  const network::ResourceRequest& request,
                  const AllowCookieCallback& allow_cookie_callback,
                  DoneCookieCallback done_callback) {
@@ -152,21 +249,15 @@
     return;
   }
 
-  // Match the logic in URLRequestHttpJob::AddCookieHeaderAndStart.
-  net::CookieOptions options;
-  options.set_include_httponly();
-  options.set_same_site_cookie_context(
-      net::cookie_util::ComputeSameSiteContextForRequest(
-          request.method, request.url, request.site_for_cookies,
-          request.request_initiator, request.attach_same_site_cookies));
-
   CEF_POST_TASK(
       CEF_UIT,
-      base::BindOnce(LoadCookiesOnUIThread, browser_context, request.url,
-                     options, allow_cookie_callback, std::move(done_callback)));
+      base::BindOnce(LoadCookiesOnUIThread, browser_context_getter, request.url,
+                     GetCookieOptions(request, /*for_loading_cookies=*/true),
+                     net::CookiePartitionKeyCollection(), allow_cookie_callback,
+                     std::move(done_callback)));
 }
 
-void SaveCookies(content::BrowserContext* browser_context,
+void SaveCookies(const CefBrowserContext::Getter& browser_context_getter,
                  const network::ResourceRequest& request,
                  net::HttpResponseHeaders* headers,
                  const AllowCookieCallback& allow_cookie_callback,
@@ -184,15 +275,9 @@
   // Match the logic in
   // URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete.
   base::Time response_date;
-  if (!headers->GetDateValue(&response_date))
+  if (!headers->GetDateValue(&response_date)) {
     response_date = base::Time();
-
-  net::CookieOptions options;
-  options.set_include_httponly();
-  options.set_same_site_cookie_context(
-      net::cookie_util::ComputeSameSiteContextForRequest(
-          request.method, request.url, request.site_for_cookies,
-          request.request_initiator, request.attach_same_site_cookies));
+  }
 
   const base::StringPiece name(net_service::kHTTPSetCookieHeaderName);
   std::string cookie_string;
@@ -203,30 +288,34 @@
   while (headers->EnumerateHeader(&iter, name, &cookie_string)) {
     total_count++;
 
-    net::CanonicalCookie::CookieInclusionStatus returned_status;
+    net::CookieInclusionStatus returned_status;
     std::unique_ptr<net::CanonicalCookie> cookie = net::CanonicalCookie::Create(
         request.url, cookie_string, base::Time::Now(),
-        base::make_optional(response_date), &returned_status);
+        absl::make_optional(response_date), /*partition_key=*/absl::nullopt,
+        /*block_truncated_cookies=*/true, &returned_status);
     if (!returned_status.IsInclude()) {
       continue;
     }
 
     bool allow = false;
     allow_cookie_callback.Run(*cookie, &allow);
-    if (allow)
+    if (allow) {
       allowed_cookies.push_back(*cookie);
+    }
   }
 
   if (!allowed_cookies.empty()) {
     CEF_POST_TASK(
         CEF_UIT,
-        base::BindOnce(SaveCookiesOnUIThread, browser_context, request.url,
-                       options, total_count, std::move(allowed_cookies),
-                       std::move(done_callback)));
+        base::BindOnce(
+            SaveCookiesOnUIThread, browser_context_getter, request.url,
+            GetCookieOptions(request, /*for_loading_cookies=*/false),
+            total_count, std::move(allowed_cookies), std::move(done_callback)));
 
   } else {
     std::move(done_callback).Run(total_count, std::move(allowed_cookies));
   }
 }
 
-}  // namespace net_service
\ No newline at end of file
+}  // namespace cookie_helper
+}  // namespace net_service
diff --git a/src/libcef/browser/net_service/cookie_helper.h b/src/libcef/browser/net_service/cookie_helper.h
index 00b2a3e..c975fd1 100644
--- a/src/libcef/browser/net_service/cookie_helper.h
+++ b/src/libcef/browser/net_service/cookie_helper.h
@@ -5,12 +5,10 @@
 #ifndef CEF_LIBCEF_BROWSER_NET_SERVICE_COOKIE_HELPER_H_
 #define CEF_LIBCEF_BROWSER_NET_SERVICE_COOKIE_HELPER_H_
 
-#include "base/callback_forward.h"
-#include "net/cookies/canonical_cookie.h"
+#include "libcef/browser/browser_context.h"
 
-namespace content {
-class BrowserContext;
-}
+#include "base/functional/callback_forward.h"
+#include "net/cookies/canonical_cookie.h"
 
 namespace net {
 class HttpResponseHeaders;
@@ -21,9 +19,18 @@
 }  // namespace network
 
 namespace net_service {
+namespace cookie_helper {
+
+// Returns true if the scheme for |url| supports cookies. |cookieable_schemes|
+// is the optional list of schemes that the client has explicitly registered as
+// cookieable, which may intentionally exclude standard schemes.
+bool IsCookieableScheme(
+    const GURL& url,
+    const absl::optional<std::vector<std::string>>& cookieable_schemes);
 
 using AllowCookieCallback =
-    base::Callback<void(const net::CanonicalCookie&, bool* /* allow */)>;
+    base::RepeatingCallback<void(const net::CanonicalCookie&,
+                                 bool* /* allow */)>;
 using DoneCookieCallback =
     base::OnceCallback<void(int /* total_count */,
                             net::CookieList /* allowed_cookies */)>;
@@ -35,7 +42,7 @@
 // both retrieved and allowed by |allow_cookie_callback|. The loaded cookies
 // will not be set on |request|; that should be done in |done_callback|. Must be
 // called on the IO thread.
-void LoadCookies(content::BrowserContext* browser_context,
+void LoadCookies(const CefBrowserContext::Getter& browser_context_getter,
                  const network::ResourceRequest& request,
                  const AllowCookieCallback& allow_cookie_callback,
                  DoneCookieCallback done_callback);
@@ -46,12 +53,13 @@
 // retrieved, and |allowed_cookies| representing the list of cookies that were
 // both allowed by |allow_cookie_callback| an successfully saved. Must be called
 // on the IO thread.
-void SaveCookies(content::BrowserContext* browser_context,
+void SaveCookies(const CefBrowserContext::Getter& browser_context_getter,
                  const network::ResourceRequest& request,
                  net::HttpResponseHeaders* headers,
                  const AllowCookieCallback& allow_cookie_callback,
                  DoneCookieCallback done_callback);
 
+}  // namespace cookie_helper
 }  // namespace net_service
 
 #endif  // CEF_LIBCEF_BROWSER_NET_SERVICE_COOKIE_HELPER_H_
diff --git a/src/libcef/browser/net_service/cookie_manager_impl.cc b/src/libcef/browser/net_service/cookie_manager_impl.cc
index e7f5beb..ef32382 100644
--- a/src/libcef/browser/net_service/cookie_manager_impl.cc
+++ b/src/libcef/browser/net_service/cookie_manager_impl.cc
@@ -7,7 +7,7 @@
 #include "libcef/common/net_service/net_service_util.h"
 #include "libcef/common/time_util.h"
 
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #include "base/logging.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/storage_partition.h"
@@ -23,44 +23,50 @@
   CEF_REQUIRE_UIT();
   DCHECK(!getter.is_null());
 
-  // Will return nullptr if the BrowserContext has been destroyed.
+  // Will return nullptr if the BrowserContext has been shut down.
   return getter.Run();
 }
 
 // Do not keep a reference to the object returned by this method.
 CookieManager* GetCookieManager(CefBrowserContext* browser_context) {
   CEF_REQUIRE_UIT();
-  return content::BrowserContext::GetDefaultStoragePartition(browser_context)
+  return browser_context->AsBrowserContext()
+      ->GetDefaultStoragePartition()
       ->GetCookieManagerForBrowserProcess();
 }
 
 // Always execute the callback asynchronously.
 void RunAsyncCompletionOnUIThread(CefRefPtr<CefCompletionCallback> callback) {
-  if (!callback.get())
+  if (!callback.get()) {
     return;
-  CEF_POST_TASK(CEF_UIT,
-                base::Bind(&CefCompletionCallback::OnComplete, callback.get()));
+  }
+  CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefCompletionCallback::OnComplete,
+                                        callback.get()));
 }
 
 // Always execute the callback asynchronously.
 void SetCookieCallbackImpl(CefRefPtr<CefSetCookieCallback> callback,
-                           net::CanonicalCookie::CookieInclusionStatus status) {
-  if (!callback.get())
+                           net::CookieAccessResult access_result) {
+  if (!callback.get()) {
     return;
-  if (!status.IsInclude()) {
-    LOG(WARNING) << "SetCookie failed with reason: " << status.GetDebugString();
   }
-  CEF_POST_TASK(CEF_UIT, base::Bind(&CefSetCookieCallback::OnComplete,
-                                    callback.get(), status.IsInclude()));
+  const bool is_include = access_result.status.IsInclude();
+  if (!is_include) {
+    LOG(WARNING) << "SetCookie failed with reason: "
+                 << access_result.status.GetDebugString();
+  }
+  CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefSetCookieCallback::OnComplete,
+                                        callback.get(), is_include));
 }
 
 // Always execute the callback asynchronously.
 void DeleteCookiesCallbackImpl(CefRefPtr<CefDeleteCookiesCallback> callback,
                                uint32_t num_deleted) {
-  if (!callback.get())
+  if (!callback.get()) {
     return;
-  CEF_POST_TASK(CEF_UIT, base::Bind(&CefDeleteCookiesCallback::OnComplete,
-                                    callback.get(), num_deleted));
+  }
+  CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefDeleteCookiesCallback::OnComplete,
+                                        callback.get(), num_deleted));
 }
 
 void ExecuteVisitor(CefRefPtr<CefCookieVisitor> visitor,
@@ -69,8 +75,9 @@
   CEF_REQUIRE_UIT();
 
   auto browser_context = GetBrowserContext(browser_context_getter);
-  if (!browser_context)
+  if (!browser_context) {
     return;
+  }
 
   auto cookie_manager = GetCookieManager(browser_context);
 
@@ -85,8 +92,9 @@
       cookie_manager->DeleteCanonicalCookie(
           cc, CookieManager::DeleteCanonicalCookieCallback());
     }
-    if (!keepLooping)
+    if (!keepLooping) {
       break;
+    }
     count++;
   }
 }
@@ -96,15 +104,15 @@
     CefRefPtr<CefCookieVisitor> visitor,
     const CefBrowserContext::Getter& browser_context_getter,
     const net::CookieList& cookies) {
-  CEF_POST_TASK(CEF_UIT, base::Bind(&ExecuteVisitor, visitor,
-                                    browser_context_getter, cookies));
+  CEF_POST_TASK(CEF_UIT, base::BindOnce(&ExecuteVisitor, visitor,
+                                        browser_context_getter, cookies));
 }
 
 void GetCookiesCallbackImpl(
     CefRefPtr<CefCookieVisitor> visitor,
     const CefBrowserContext::Getter& browser_context_getter,
-    const net::CookieStatusList& include_cookies,
-    const net::CookieStatusList&) {
+    const net::CookieAccessResultList& include_cookies,
+    const net::CookieAccessResultList&) {
   net::CookieList cookies;
   for (const auto& status : include_cookies) {
     cookies.push_back(status.cookie);
@@ -120,165 +128,77 @@
     CefBrowserContext::Getter browser_context_getter,
     CefRefPtr<CefCompletionCallback> callback) {
   CEF_REQUIRE_UIT();
+  DCHECK(!initialized_);
   DCHECK(!browser_context_getter.is_null());
   DCHECK(browser_context_getter_.is_null());
   browser_context_getter_ = browser_context_getter;
-  RunAsyncCompletionOnUIThread(callback);
-}
 
-void CefCookieManagerImpl::SetSupportedSchemes(
-    const std::vector<CefString>& schemes,
-    bool include_defaults,
-    CefRefPtr<CefCompletionCallback> callback) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::Bind(&CefCookieManagerImpl::SetSupportedSchemes, this,
-                             schemes, include_defaults, callback));
-    return;
+  initialized_ = true;
+  if (!init_callbacks_.empty()) {
+    for (auto& init_callback : init_callbacks_) {
+      std::move(init_callback).Run();
+    }
+    init_callbacks_.clear();
   }
 
-  std::vector<std::string> all_schemes;
-  for (const auto& scheme : schemes)
-    all_schemes.push_back(scheme);
-
-  if (include_defaults) {
-    // Add default schemes that should always support cookies.
-    // This list should match CookieMonster::kDefaultCookieableSchemes.
-    all_schemes.push_back("http");
-    all_schemes.push_back("https");
-    all_schemes.push_back("ws");
-    all_schemes.push_back("wss");
-  }
-
-  auto browser_context = GetBrowserContext(browser_context_getter_);
-  if (!browser_context)
-    return;
-
-  // This will be forwarded to the CookieMonster that lives in the
-  // NetworkService process when the NetworkContext is created via
-  // CefContentBrowserClient::CreateNetworkContext.
-  browser_context->set_cookieable_schemes(base::make_optional(all_schemes));
   RunAsyncCompletionOnUIThread(callback);
 }
 
 bool CefCookieManagerImpl::VisitAllCookies(
     CefRefPtr<CefCookieVisitor> visitor) {
-  if (!visitor.get())
+  if (!visitor.get()) {
     return false;
+  }
 
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::Bind(base::IgnoreResult(&CefCookieManagerImpl::VisitAllCookies),
-                   this, visitor));
+  if (!ValidContext()) {
+    StoreOrTriggerInitCallback(base::BindOnce(
+        base::IgnoreResult(&CefCookieManagerImpl::VisitAllCookiesInternal),
+        this, visitor));
     return true;
   }
 
-  auto browser_context = GetBrowserContext(browser_context_getter_);
-  if (!browser_context)
-    return false;
-
-  GetCookieManager(browser_context)
-      ->GetAllCookies(base::Bind(&GetAllCookiesCallbackImpl, visitor,
-                                 browser_context_getter_));
-  return true;
+  return VisitAllCookiesInternal(visitor);
 }
 
 bool CefCookieManagerImpl::VisitUrlCookies(
     const CefString& url,
     bool includeHttpOnly,
     CefRefPtr<CefCookieVisitor> visitor) {
-  if (!visitor.get())
+  if (!visitor.get()) {
     return false;
+  }
 
   GURL gurl = GURL(url.ToString());
-  if (!gurl.is_valid())
+  if (!gurl.is_valid()) {
     return false;
+  }
 
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::Bind(base::IgnoreResult(&CefCookieManagerImpl::VisitUrlCookies),
-                   this, url, includeHttpOnly, visitor));
+  if (!ValidContext()) {
+    StoreOrTriggerInitCallback(base::BindOnce(
+        base::IgnoreResult(&CefCookieManagerImpl::VisitUrlCookiesInternal),
+        this, gurl, includeHttpOnly, visitor));
     return true;
   }
 
-  net::CookieOptions options;
-  if (includeHttpOnly)
-    options.set_include_httponly();
-  options.set_same_site_cookie_context(
-      net::CookieOptions::SameSiteCookieContext::MakeInclusive());
-
-  auto browser_context = GetBrowserContext(browser_context_getter_);
-  if (!browser_context)
-    return false;
-
-  GetCookieManager(browser_context)
-      ->GetCookieList(gurl, options,
-                      base::Bind(&GetCookiesCallbackImpl, visitor,
-                                 browser_context_getter_));
-  return true;
+  return VisitUrlCookiesInternal(gurl, includeHttpOnly, visitor);
 }
 
 bool CefCookieManagerImpl::SetCookie(const CefString& url,
                                      const CefCookie& cookie,
                                      CefRefPtr<CefSetCookieCallback> callback) {
   GURL gurl = GURL(url.ToString());
-  if (!gurl.is_valid())
+  if (!gurl.is_valid()) {
     return false;
+  }
 
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::Bind(base::IgnoreResult(&CefCookieManagerImpl::SetCookie), this,
-                   url, cookie, callback));
+  if (!ValidContext()) {
+    StoreOrTriggerInitCallback(base::BindOnce(
+        base::IgnoreResult(&CefCookieManagerImpl::SetCookieInternal), this,
+        gurl, cookie, callback));
     return true;
   }
 
-  std::string name = CefString(&cookie.name).ToString();
-  std::string value = CefString(&cookie.value).ToString();
-  std::string domain = CefString(&cookie.domain).ToString();
-  std::string path = CefString(&cookie.path).ToString();
-
-  base::Time expiration_time;
-  if (cookie.has_expires)
-    cef_time_to_basetime(cookie.expires, expiration_time);
-
-  net::CookieSameSite same_site =
-      net_service::MakeCookieSameSite(cookie.same_site);
-  net::CookiePriority priority =
-      net_service::MakeCookiePriority(cookie.priority);
-
-  auto canonical_cookie = net::CanonicalCookie::CreateSanitizedCookie(
-      gurl, name, value, domain, path,
-      base::Time(),  // Creation time.
-      expiration_time,
-      base::Time(),  // Last access time.
-      cookie.secure ? true : false, cookie.httponly ? true : false, same_site,
-      priority);
-
-  if (!canonical_cookie) {
-    SetCookieCallbackImpl(callback,
-                          net::CanonicalCookie::CookieInclusionStatus(
-                              net::CanonicalCookie::CookieInclusionStatus::
-                                  EXCLUDE_UNKNOWN_ERROR));
-    return true;
-  }
-
-  net::CookieOptions options;
-  if (cookie.httponly)
-    options.set_include_httponly();
-  options.set_same_site_cookie_context(
-      net::CookieOptions::SameSiteCookieContext::MakeInclusive());
-
-  auto browser_context = GetBrowserContext(browser_context_getter_);
-  if (!browser_context)
-    return false;
-
-  GetCookieManager(browser_context)
-      ->SetCanonicalCookie(*canonical_cookie, gurl.scheme(), options,
-                           base::Bind(SetCookieCallbackImpl, callback));
-  return true;
+  return SetCookieInternal(gurl, cookie, callback);
 }
 
 bool CefCookieManagerImpl::DeleteCookies(
@@ -287,60 +207,198 @@
     CefRefPtr<CefDeleteCookiesCallback> callback) {
   // Empty URLs are allowed but not invalid URLs.
   GURL gurl = GURL(url.ToString());
-  if (!gurl.is_empty() && !gurl.is_valid())
+  if (!gurl.is_empty() && !gurl.is_valid()) {
     return false;
+  }
 
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::Bind(base::IgnoreResult(&CefCookieManagerImpl::DeleteCookies),
-                   this, url, cookie_name, callback));
+  if (!ValidContext()) {
+    StoreOrTriggerInitCallback(base::BindOnce(
+        base::IgnoreResult(&CefCookieManagerImpl::DeleteCookiesInternal), this,
+        gurl, cookie_name, callback));
     return true;
   }
 
-  network::mojom::CookieDeletionFilterPtr deletion_filter =
-      network::mojom::CookieDeletionFilter::New();
-
-  if (gurl.is_empty()) {
-    // Delete all cookies.
-  } else if (cookie_name.empty()) {
-    // Delete all matching host cookies.
-    deletion_filter->host_name = gurl.host();
-  } else {
-    // Delete all matching host and domain cookies.
-    deletion_filter->url = gurl;
-    deletion_filter->cookie_name = cookie_name;
-  }
-
-  auto browser_context = GetBrowserContext(browser_context_getter_);
-  if (!browser_context)
-    return false;
-
-  GetCookieManager(browser_context)
-      ->DeleteCookies(std::move(deletion_filter),
-                      base::Bind(DeleteCookiesCallbackImpl, callback));
-  return true;
+  return DeleteCookiesInternal(gurl, cookie_name, callback);
 }
 
 bool CefCookieManagerImpl::FlushStore(
     CefRefPtr<CefCompletionCallback> callback) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::Bind(base::IgnoreResult(&CefCookieManagerImpl::FlushStore), this,
-                   callback));
+  if (!ValidContext()) {
+    StoreOrTriggerInitCallback(base::BindOnce(
+        base::IgnoreResult(&CefCookieManagerImpl::FlushStoreInternal), this,
+        callback));
     return true;
   }
 
+  return FlushStoreInternal(callback);
+}
+
+bool CefCookieManagerImpl::VisitAllCookiesInternal(
+    CefRefPtr<CefCookieVisitor> visitor) {
+  DCHECK(ValidContext());
+  DCHECK(visitor);
+
   auto browser_context = GetBrowserContext(browser_context_getter_);
-  if (!browser_context)
+  if (!browser_context) {
     return false;
+  }
 
   GetCookieManager(browser_context)
-      ->FlushCookieStore(base::Bind(RunAsyncCompletionOnUIThread, callback));
+      ->GetAllCookies(base::BindOnce(&GetAllCookiesCallbackImpl, visitor,
+                                     browser_context_getter_));
   return true;
 }
 
+bool CefCookieManagerImpl::VisitUrlCookiesInternal(
+    const GURL& url,
+    bool includeHttpOnly,
+    CefRefPtr<CefCookieVisitor> visitor) {
+  DCHECK(ValidContext());
+  DCHECK(visitor);
+  DCHECK(url.is_valid());
+
+  net::CookieOptions options;
+  if (includeHttpOnly) {
+    options.set_include_httponly();
+  }
+  options.set_same_site_cookie_context(
+      net::CookieOptions::SameSiteCookieContext::MakeInclusive());
+
+  auto browser_context = GetBrowserContext(browser_context_getter_);
+  if (!browser_context) {
+    return false;
+  }
+
+  GetCookieManager(browser_context)
+      ->GetCookieList(url, options, net::CookiePartitionKeyCollection(),
+                      base::BindOnce(&GetCookiesCallbackImpl, visitor,
+                                     browser_context_getter_));
+  return true;
+}
+
+bool CefCookieManagerImpl::SetCookieInternal(
+    const GURL& url,
+    const CefCookie& cookie,
+    CefRefPtr<CefSetCookieCallback> callback) {
+  DCHECK(ValidContext());
+  DCHECK(url.is_valid());
+
+  std::string name = CefString(&cookie.name).ToString();
+  std::string value = CefString(&cookie.value).ToString();
+  std::string domain = CefString(&cookie.domain).ToString();
+  std::string path = CefString(&cookie.path).ToString();
+
+  base::Time expiration_time;
+  if (cookie.has_expires) {
+    expiration_time = CefBaseTime(cookie.expires);
+  }
+
+  net::CookieSameSite same_site =
+      net_service::MakeCookieSameSite(cookie.same_site);
+  net::CookiePriority priority =
+      net_service::MakeCookiePriority(cookie.priority);
+
+  auto canonical_cookie = net::CanonicalCookie::CreateSanitizedCookie(
+      url, name, value, domain, path,
+      base::Time(),  // Creation time.
+      expiration_time,
+      base::Time(),  // Last access time.
+      cookie.secure ? true : false, cookie.httponly ? true : false, same_site,
+      priority, /*same_party=*/false, /*partition_key=*/absl::nullopt);
+
+  if (!canonical_cookie) {
+    SetCookieCallbackImpl(
+        callback, net::CookieAccessResult(net::CookieInclusionStatus(
+                      net::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR)));
+    return true;
+  }
+
+  net::CookieOptions options;
+  if (cookie.httponly) {
+    options.set_include_httponly();
+  }
+  options.set_same_site_cookie_context(
+      net::CookieOptions::SameSiteCookieContext::MakeInclusive());
+
+  auto browser_context = GetBrowserContext(browser_context_getter_);
+  if (!browser_context) {
+    return false;
+  }
+
+  GetCookieManager(browser_context)
+      ->SetCanonicalCookie(*canonical_cookie, url, options,
+                           base::BindOnce(SetCookieCallbackImpl, callback));
+  return true;
+}
+
+bool CefCookieManagerImpl::DeleteCookiesInternal(
+    const GURL& url,
+    const CefString& cookie_name,
+    CefRefPtr<CefDeleteCookiesCallback> callback) {
+  DCHECK(ValidContext());
+  DCHECK(url.is_empty() || url.is_valid());
+
+  network::mojom::CookieDeletionFilterPtr deletion_filter =
+      network::mojom::CookieDeletionFilter::New();
+
+  if (url.is_empty()) {
+    // Delete all cookies.
+  } else if (cookie_name.empty()) {
+    // Delete all matching host cookies.
+    deletion_filter->host_name = url.host();
+  } else {
+    // Delete all matching host and domain cookies.
+    deletion_filter->url = url;
+    deletion_filter->cookie_name = cookie_name;
+  }
+
+  auto browser_context = GetBrowserContext(browser_context_getter_);
+  if (!browser_context) {
+    return false;
+  }
+
+  GetCookieManager(browser_context)
+      ->DeleteCookies(std::move(deletion_filter),
+                      base::BindOnce(DeleteCookiesCallbackImpl, callback));
+  return true;
+}
+
+bool CefCookieManagerImpl::FlushStoreInternal(
+    CefRefPtr<CefCompletionCallback> callback) {
+  DCHECK(ValidContext());
+
+  auto browser_context = GetBrowserContext(browser_context_getter_);
+  if (!browser_context) {
+    return false;
+  }
+
+  GetCookieManager(browser_context)
+      ->FlushCookieStore(
+          base::BindOnce(RunAsyncCompletionOnUIThread, callback));
+  return true;
+}
+
+void CefCookieManagerImpl::StoreOrTriggerInitCallback(
+    base::OnceClosure callback) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(&CefCookieManagerImpl::StoreOrTriggerInitCallback, this,
+                       std::move(callback)));
+    return;
+  }
+
+  if (initialized_) {
+    std::move(callback).Run();
+  } else {
+    init_callbacks_.emplace_back(std::move(callback));
+  }
+}
+
+bool CefCookieManagerImpl::ValidContext() const {
+  return CEF_CURRENTLY_ON_UIT() && initialized_;
+}
+
 // CefCookieManager methods ----------------------------------------------------
 
 // static
diff --git a/src/libcef/browser/net_service/cookie_manager_impl.h b/src/libcef/browser/net_service/cookie_manager_impl.h
index 19eff86..9ae1b9c 100644
--- a/src/libcef/browser/net_service/cookie_manager_impl.h
+++ b/src/libcef/browser/net_service/cookie_manager_impl.h
@@ -17,15 +17,15 @@
  public:
   CefCookieManagerImpl();
 
+  CefCookieManagerImpl(const CefCookieManagerImpl&) = delete;
+  CefCookieManagerImpl& operator=(const CefCookieManagerImpl&) = delete;
+
   // Called on the UI thread after object creation and before any other object
   // methods are executed on the UI thread.
   void Initialize(CefBrowserContext::Getter browser_context_getter,
                   CefRefPtr<CefCompletionCallback> callback);
 
   // CefCookieManager methods.
-  void SetSupportedSchemes(const std::vector<CefString>& schemes,
-                           bool include_defaults,
-                           CefRefPtr<CefCompletionCallback> callback) override;
   bool VisitAllCookies(CefRefPtr<CefCookieVisitor> visitor) override;
   bool VisitUrlCookies(const CefString& url,
                        bool includeHttpOnly,
@@ -39,11 +39,31 @@
   bool FlushStore(CefRefPtr<CefCompletionCallback> callback) override;
 
  private:
+  bool VisitAllCookiesInternal(CefRefPtr<CefCookieVisitor> visitor);
+  bool VisitUrlCookiesInternal(const GURL& url,
+                               bool includeHttpOnly,
+                               CefRefPtr<CefCookieVisitor> visitor);
+  bool SetCookieInternal(const GURL& url,
+                         const CefCookie& cookie,
+                         CefRefPtr<CefSetCookieCallback> callback);
+  bool DeleteCookiesInternal(const GURL& url,
+                             const CefString& cookie_name,
+                             CefRefPtr<CefDeleteCookiesCallback> callback);
+  bool FlushStoreInternal(CefRefPtr<CefCompletionCallback> callback);
+
+  // If the context is fully initialized execute |callback|, otherwise
+  // store it until the context is fully initialized.
+  void StoreOrTriggerInitCallback(base::OnceClosure callback);
+
+  bool ValidContext() const;
+
   // Only accessed on the UI thread. Will be non-null after Initialize().
   CefBrowserContext::Getter browser_context_getter_;
 
+  bool initialized_ = false;
+  std::vector<base::OnceClosure> init_callbacks_;
+
   IMPLEMENT_REFCOUNTING(CefCookieManagerImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefCookieManagerImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_NET_SERVICE_COOKIE_MANAGER_IMPL_H_
diff --git a/src/libcef/browser/net_service/login_delegate.cc b/src/libcef/browser/net_service/login_delegate.cc
index ff9ffb1..da16c32 100644
--- a/src/libcef/browser/net_service/login_delegate.cc
+++ b/src/libcef/browser/net_service/login_delegate.cc
@@ -4,12 +4,12 @@
 
 #include "libcef/browser/net_service/login_delegate.h"
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/browser_host_base.h"
 #include "libcef/browser/net_service/browser_urlrequest_impl.h"
 #include "libcef/browser/thread_util.h"
 
 #include "base/memory/scoped_refptr.h"
-#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/task/sequenced_task_runner.h"
 #include "content/public/browser/global_request_id.h"
 #include "content/public/browser/web_contents.h"
 
@@ -21,7 +21,10 @@
  public:
   explicit AuthCallbackImpl(base::WeakPtr<LoginDelegate> delegate)
       : delegate_(delegate),
-        task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
+        task_runner_(base::SequencedTaskRunner::GetCurrentDefault()) {}
+
+  AuthCallbackImpl(const AuthCallbackImpl&) = delete;
+  AuthCallbackImpl& operator=(const AuthCallbackImpl&) = delete;
 
   ~AuthCallbackImpl() override {
     if (delegate_.MaybeValid()) {
@@ -63,12 +66,11 @@
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
   IMPLEMENT_REFCOUNTING(AuthCallbackImpl);
-  DISALLOW_COPY_AND_ASSIGN(AuthCallbackImpl);
 };
 
 void RunCallbackOnIOThread(
-    CefRefPtr<CefBrowserHostImpl> browser,
-    base::Optional<CefBrowserURLRequest::RequestInfo> url_request_info,
+    CefRefPtr<CefBrowserHostBase> browser,
+    absl::optional<CefBrowserURLRequest::RequestInfo> url_request_info,
     const net::AuthChallengeInfo& auth_info,
     const GURL& origin_url,
     CefRefPtr<AuthCallbackImpl> callback_impl) {
@@ -119,9 +121,9 @@
   CEF_REQUIRE_UIT();
 
   // May be nullptr for requests originating from CefURLRequest.
-  CefRefPtr<CefBrowserHostImpl> browser;
+  CefRefPtr<CefBrowserHostBase> browser;
   if (web_contents) {
-    browser = CefBrowserHostImpl::GetBrowserForContents(web_contents);
+    browser = CefBrowserHostBase::GetBrowserForContents(web_contents);
   }
 
   // |callback| needs to be executed asynchronously.
@@ -142,11 +144,11 @@
 void LoginDelegate::Cancel() {
   CEF_REQUIRE_UIT();
   if (!callback_.is_null()) {
-    std::move(callback_).Run(base::nullopt);
+    std::move(callback_).Run(absl::nullopt);
   }
 }
 
-void LoginDelegate::Start(CefRefPtr<CefBrowserHostImpl> browser,
+void LoginDelegate::Start(CefRefPtr<CefBrowserHostBase> browser,
                           const net::AuthChallengeInfo& auth_info,
                           const content::GlobalRequestID& request_id,
                           const GURL& origin_url) {
diff --git a/src/libcef/browser/net_service/login_delegate.h b/src/libcef/browser/net_service/login_delegate.h
index 1f831aa..8732ea7 100644
--- a/src/libcef/browser/net_service/login_delegate.h
+++ b/src/libcef/browser/net_service/login_delegate.h
@@ -17,7 +17,7 @@
 class WebContents;
 }  // namespace content
 
-class CefBrowserHostImpl;
+class CefBrowserHostBase;
 class GURL;
 
 namespace net_service {
@@ -36,7 +36,7 @@
   void Cancel();
 
  private:
-  void Start(CefRefPtr<CefBrowserHostImpl> browser,
+  void Start(CefRefPtr<CefBrowserHostBase> browser,
              const net::AuthChallengeInfo& auth_info,
              const content::GlobalRequestID& request_id,
              const GURL& origin_url);
diff --git a/src/libcef/browser/net_service/proxy_url_loader_factory.cc b/src/libcef/browser/net_service/proxy_url_loader_factory.cc
index c6a78f9..9394bbb 100644
--- a/src/libcef/browser/net_service/proxy_url_loader_factory.cc
+++ b/src/libcef/browser/net_service/proxy_url_loader_factory.cc
@@ -5,11 +5,17 @@
 
 #include "libcef/browser/net_service/proxy_url_loader_factory.h"
 
+#include <tuple>
+
 #include "libcef/browser/context.h"
+#include "libcef/browser/origin_whitelist_impl.h"
 #include "libcef/browser/thread_util.h"
+#include "libcef/common/cef_switches.h"
+#include "libcef/common/net/scheme_registration.h"
 #include "libcef/common/net_service/net_service_util.h"
 
 #include "base/barrier_closure.h"
+#include "base/command_line.h"
 #include "base/strings/string_number_conversions.h"
 #include "components/safe_browsing/core/common/safebrowsing_constants.h"
 #include "content/public/browser/browser_context.h"
@@ -17,8 +23,13 @@
 #include "content/public/browser/resource_context.h"
 #include "content/public/browser/web_contents.h"
 #include "mojo/public/cpp/base/big_buffer.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 #include "net/http/http_status_code.h"
+#include "net/url_request/redirect_util.h"
+#include "net/url_request/url_request.h"
 #include "services/network/public/cpp/cors/cors.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/mojom/early_hints.mojom.h"
 
 namespace net_service {
 
@@ -27,6 +38,33 @@
 // User data key for ResourceContextData.
 const void* const kResourceContextUserDataKey = &kResourceContextUserDataKey;
 
+absl::optional<std::string> GetHeaderString(
+    const net::HttpResponseHeaders* headers,
+    const std::string& header_name) {
+  std::string header_value;
+  if (!headers || !headers->GetNormalizedHeader(header_name, &header_value)) {
+    return absl::nullopt;
+  }
+  return header_value;
+}
+
+void CreateProxyHelper(
+    content::WebContents::Getter web_contents_getter,
+    mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_receiver,
+    std::unique_ptr<InterceptedRequestHandler> request_handler) {
+  ProxyURLLoaderFactory::CreateProxy(web_contents_getter,
+                                     std::move(loader_receiver),
+                                     std::move(request_handler));
+}
+
+bool DisableRequestHandlingForTesting() {
+  static bool disabled([]() -> bool {
+    return base::CommandLine::ForCurrentProcess()->HasSwitch(
+        switches::kDisableRequestHandlingForTesting);
+  }());
+  return disabled;
+}
+
 }  // namespace
 
 // Owns all of the ProxyURLLoaderFactorys for a given BrowserContext. Since
@@ -34,6 +72,9 @@
 // ResourceContext.
 class ResourceContextData : public base::SupportsUserData::Data {
  public:
+  ResourceContextData(const ResourceContextData&) = delete;
+  ResourceContextData& operator=(const ResourceContextData&) = delete;
+
   ~ResourceContextData() override {}
 
   static void AddProxyOnUIThread(
@@ -102,8 +143,44 @@
       proxies_;
 
   base::WeakPtrFactory<ResourceContextData> weak_factory_;
+};
 
-  DISALLOW_COPY_AND_ASSIGN(ResourceContextData);
+// CORS preflight requests are handled in the network process, so we just need
+// to continue all of the callbacks and then delete ourself.
+class CorsPreflightRequest : public network::mojom::TrustedHeaderClient {
+ public:
+  explicit CorsPreflightRequest(
+      mojo::PendingReceiver<network::mojom::TrustedHeaderClient> receiver)
+      : weak_factory_(this) {
+    header_client_receiver_.Bind(std::move(receiver));
+
+    header_client_receiver_.set_disconnect_handler(base::BindOnce(
+        &CorsPreflightRequest::OnDestroy, weak_factory_.GetWeakPtr()));
+  }
+
+  CorsPreflightRequest(const CorsPreflightRequest&) = delete;
+  CorsPreflightRequest& operator=(const CorsPreflightRequest&) = delete;
+
+  // mojom::TrustedHeaderClient methods:
+  void OnBeforeSendHeaders(const net::HttpRequestHeaders& headers,
+                           OnBeforeSendHeadersCallback callback) override {
+    std::move(callback).Run(net::OK, headers);
+  }
+
+  void OnHeadersReceived(const std::string& headers,
+                         const net::IPEndPoint& remote_endpoint,
+                         OnHeadersReceivedCallback callback) override {
+    std::move(callback).Run(net::OK, headers, /*redirect_url=*/GURL());
+    OnDestroy();
+  }
+
+ private:
+  void OnDestroy() { delete this; }
+
+  mojo::Receiver<network::mojom::TrustedHeaderClient> header_client_receiver_{
+      this};
+
+  base::WeakPtrFactory<CorsPreflightRequest> weak_factory_;
 };
 
 //==============================
@@ -118,13 +195,17 @@
  public:
   InterceptedRequest(
       ProxyURLLoaderFactory* factory,
-      RequestId id,
+      int32_t id,
       uint32_t options,
       const network::ResourceRequest& request,
       const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
       mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
       mojo::PendingRemote<network::mojom::URLLoaderClient> client,
       mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory);
+
+  InterceptedRequest(const InterceptedRequest&) = delete;
+  InterceptedRequest& operator=(const InterceptedRequest&) = delete;
+
   ~InterceptedRequest() override;
 
   // Restart the request. This happens on initial start and after redirect.
@@ -145,28 +226,31 @@
                          OnHeadersReceivedCallback callback) override;
 
   // mojom::URLLoaderClient methods:
-  void OnReceiveResponse(network::mojom::URLResponseHeadPtr head) override;
+  void OnReceiveEarlyHints(network::mojom::EarlyHintsPtr early_hints) override;
+  void OnReceiveResponse(
+      network::mojom::URLResponseHeadPtr head,
+      mojo::ScopedDataPipeConsumerHandle body,
+      absl::optional<mojo_base::BigBuffer> cached_metadata) override;
   void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
                          network::mojom::URLResponseHeadPtr head) override;
   void OnUploadProgress(int64_t current_position,
                         int64_t total_size,
                         OnUploadProgressCallback callback) override;
-  void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
   void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
-  void OnStartLoadingResponseBody(
-      mojo::ScopedDataPipeConsumerHandle body) override;
   void OnComplete(const network::URLLoaderCompletionStatus& status) override;
 
   // mojom::URLLoader methods:
-  void FollowRedirect(const std::vector<std::string>& removed_headers,
-                      const net::HttpRequestHeaders& modified_headers,
-                      const base::Optional<GURL>& new_url) override;
+  void FollowRedirect(
+      const std::vector<std::string>& removed_headers,
+      const net::HttpRequestHeaders& modified_headers,
+      const net::HttpRequestHeaders& modified_cors_exempt_headers,
+      const absl::optional<GURL>& new_url) override;
   void SetPriority(net::RequestPriority priority,
                    int32_t intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
   void ResumeReadingBodyFromNet() override;
 
-  const RequestId id() const { return id_; }
+  int32_t id() const { return id_; }
 
  private:
   // Helpers for determining the request handler.
@@ -181,7 +265,7 @@
 
   // Helpers for optionally overriding headers.
   void HandleResponseOrRedirectHeaders(
-      base::Optional<net::RedirectInfo> redirect_info,
+      absl::optional<net::RedirectInfo> redirect_info,
       net::CompletionOnceCallback continuation);
   void ContinueResponseOrRedirect(
       net::CompletionOnceCallback continuation,
@@ -211,22 +295,26 @@
   void OnURLLoaderError(uint32_t custom_reason, const std::string& description);
 
   // Call OnComplete on |target_client_|. If |wait_for_loader_error| is true
-  // then this object will wait for |proxied_loader_binding_| to have a
+  // then this object will wait for |proxied_loader_receiver_| to have a
   // connection error before destructing.
   void CallOnComplete(const network::URLLoaderCompletionStatus& status,
                       bool wait_for_loader_error);
 
   void SendErrorAndCompleteImmediately(int error_code);
+  void SendErrorStatusAndCompleteImmediately(
+      const network::URLLoaderCompletionStatus& status);
 
   void SendErrorCallback(int error_code, bool safebrowsing_hit);
 
   void OnUploadProgressACK();
 
   ProxyURLLoaderFactory* const factory_;
-  const RequestId id_;
+  const int32_t id_;
   const uint32_t options_;
   bool input_stream_previously_failed_ = false;
   bool request_was_redirected_ = false;
+  int redirect_limit_ = net::URLRequest::kMaxRedirects;
+  bool redirect_in_progress_ = false;
 
   // To avoid sending multiple OnReceivedError callbacks.
   bool sent_error_callback_ = false;
@@ -246,6 +334,8 @@
 
   network::ResourceRequest request_;
   network::mojom::URLResponseHeadPtr current_response_;
+  mojo::ScopedDataPipeConsumerHandle current_body_;
+  absl::optional<mojo_base::BigBuffer> current_cached_metadata_;
   scoped_refptr<net::HttpResponseHeaders> current_headers_;
   scoped_refptr<net::HttpResponseHeaders> override_headers_;
   GURL original_url_;
@@ -253,12 +343,13 @@
   GURL header_client_redirect_url_;
   const net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
 
-  mojo::Binding<network::mojom::URLLoader> proxied_loader_binding_;
-  network::mojom::URLLoaderClientPtr target_client_;
+  mojo::Receiver<network::mojom::URLLoader> proxied_loader_receiver_;
+  mojo::Remote<network::mojom::URLLoaderClient> target_client_;
 
-  mojo::Binding<network::mojom::URLLoaderClient> proxied_client_binding_;
-  network::mojom::URLLoaderPtr target_loader_;
-  network::mojom::URLLoaderFactoryPtr target_factory_;
+  mojo::Receiver<network::mojom::URLLoaderClient> proxied_client_receiver_{
+      this};
+  mojo::Remote<network::mojom::URLLoader> target_loader_;
+  mojo::Remote<network::mojom::URLLoaderFactory> target_factory_;
 
   bool current_request_uses_header_client_ = false;
   OnHeadersReceivedCallback on_headers_received_callback_;
@@ -268,8 +359,6 @@
   StreamReaderURLLoader* stream_loader_ = nullptr;
 
   base::WeakPtrFactory<InterceptedRequest> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(InterceptedRequest);
 };
 
 class InterceptDelegate : public StreamReaderURLLoader::Delegate {
@@ -278,19 +367,18 @@
                              base::WeakPtr<InterceptedRequest> request)
       : response_(std::move(response)), request_(request) {}
 
-  bool OpenInputStream(const RequestId& request_id,
+  bool OpenInputStream(int32_t request_id,
                        const network::ResourceRequest& request,
                        OpenCallback callback) override {
     return response_->OpenInputStream(request_id, request, std::move(callback));
   }
 
-  void OnInputStreamOpenFailed(const RequestId& request_id,
-                               bool* restarted) override {
+  void OnInputStreamOpenFailed(int32_t request_id, bool* restarted) override {
     request_->InputStreamFailed(false /* restart_needed */);
     *restarted = false;
   }
 
-  void GetResponseHeaders(const RequestId& request_id,
+  void GetResponseHeaders(int32_t request_id,
                           int* status_code,
                           std::string* reason_phrase,
                           std::string* mime_type,
@@ -309,7 +397,7 @@
 
 InterceptedRequest::InterceptedRequest(
     ProxyURLLoaderFactory* factory,
-    RequestId id,
+    int32_t id,
     uint32_t options,
     const network::ResourceRequest& request,
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
@@ -321,9 +409,8 @@
       options_(options),
       request_(request),
       traffic_annotation_(traffic_annotation),
-      proxied_loader_binding_(this, std::move(loader_receiver)),
+      proxied_loader_receiver_(this, std::move(loader_receiver)),
       target_client_(std::move(client)),
-      proxied_client_binding_(this),
       target_factory_(std::move(target_factory)),
       weak_factory_(this) {
   status_ = network::URLLoaderCompletionStatus(net::OK);
@@ -334,34 +421,56 @@
                           &removed_headers);
 
   // If there is a client error, clean up the request.
-  target_client_.set_connection_error_handler(base::BindOnce(
+  target_client_.set_disconnect_handler(base::BindOnce(
       &InterceptedRequest::OnURLLoaderClientError, base::Unretained(this)));
-  proxied_loader_binding_.set_connection_error_with_reason_handler(
-      base::BindOnce(&InterceptedRequest::OnURLLoaderError,
-                     base::Unretained(this)));
+  proxied_loader_receiver_.set_disconnect_with_reason_handler(base::BindOnce(
+      &InterceptedRequest::OnURLLoaderError, base::Unretained(this)));
 }
 
 InterceptedRequest::~InterceptedRequest() {
-  if (status_.error_code != net::OK)
+  if (status_.error_code != net::OK) {
     SendErrorCallback(status_.error_code, false);
+  }
   if (on_headers_received_callback_) {
     std::move(on_headers_received_callback_)
-        .Run(net::ERR_ABORTED, base::nullopt, GURL());
+        .Run(net::ERR_ABORTED, absl::nullopt, GURL());
   }
 }
 
 void InterceptedRequest::Restart() {
   stream_loader_ = nullptr;
-  if (proxied_client_binding_.is_bound()) {
-    proxied_client_binding_.Unbind();
+  if (proxied_client_receiver_.is_bound()) {
+    proxied_client_receiver_.reset();
     target_loader_.reset();
   }
 
-  if (header_client_receiver_.is_bound())
-    ignore_result(header_client_receiver_.Unbind());
+  if (header_client_receiver_.is_bound()) {
+    std::ignore = header_client_receiver_.Unbind();
+  }
 
   current_request_uses_header_client_ =
-      !!factory_->url_loader_header_client_receiver_;
+      factory_->url_loader_header_client_receiver_.is_bound();
+
+  if (request_.request_initiator &&
+      network::cors::ShouldCheckCors(request_.url, request_.request_initiator,
+                                     request_.mode)) {
+    if (scheme::IsCorsEnabledScheme(request_.url.scheme())) {
+      // Add the Origin header for CORS-enabled scheme requests.
+      request_.headers.SetHeaderIfMissing(
+          net::HttpRequestHeaders::kOrigin,
+          request_.request_initiator->Serialize());
+    } else if (!HasCrossOriginWhitelistEntry(
+                   *request_.request_initiator,
+                   url::Origin::Create(request_.url))) {
+      // Fail requests if a CORS check is required and the scheme is not CORS
+      // enabled. This matches the error condition that would be generated by
+      // CorsURLLoader::StartRequest in the network process.
+      SendErrorStatusAndCompleteImmediately(
+          network::URLLoaderCompletionStatus(network::CorsErrorStatus(
+              network::mojom::CorsError::kCorsDisabledScheme)));
+      return;
+    }
+  }
 
   const GURL original_url = request_.url;
 
@@ -393,8 +502,9 @@
     return;
   }
 
-  if (!restart_needed)
+  if (!restart_needed) {
     return;
+  }
 
   input_stream_previously_failed_ = true;
   Restart();
@@ -406,16 +516,17 @@
     const net::HttpRequestHeaders& headers,
     OnBeforeSendHeadersCallback callback) {
   if (!current_request_uses_header_client_) {
-    std::move(callback).Run(net::OK, base::nullopt);
+    std::move(callback).Run(net::OK, absl::nullopt);
     return;
   }
 
   request_.headers = headers;
-  std::move(callback).Run(net::OK, base::nullopt);
+  std::move(callback).Run(net::OK, absl::nullopt);
 
   // Resume handling of client messages after continuing from an async callback.
-  if (proxied_client_binding_)
-    proxied_client_binding_.ResumeIncomingMethodCallProcessing();
+  if (proxied_client_receiver_.is_bound()) {
+    proxied_client_receiver_.Resume();
+  }
 }
 
 void InterceptedRequest::OnHeadersReceived(
@@ -423,14 +534,14 @@
     const net::IPEndPoint& remote_endpoint,
     OnHeadersReceivedCallback callback) {
   if (!current_request_uses_header_client_) {
-    std::move(callback).Run(net::OK, base::nullopt, GURL());
+    std::move(callback).Run(net::OK, absl::nullopt, GURL());
     return;
   }
 
   current_headers_ = base::MakeRefCounted<net::HttpResponseHeaders>(headers);
   on_headers_received_callback_ = std::move(callback);
 
-  base::Optional<net::RedirectInfo> redirect_info;
+  absl::optional<net::RedirectInfo> redirect_info;
   std::string location;
   if (current_headers_->IsRedirect(&location)) {
     const GURL new_url = request_.url.Resolve(location);
@@ -446,20 +557,30 @@
 
 // URLLoaderClient methods.
 
-void InterceptedRequest::OnReceiveResponse(
-    network::mojom::URLResponseHeadPtr head) {
-  current_response_ = std::move(head);
+void InterceptedRequest::OnReceiveEarlyHints(
+    network::mojom::EarlyHintsPtr early_hints) {
+  target_client_->OnReceiveEarlyHints(std::move(early_hints));
+}
 
-  if (current_request_uses_header_client_) {
+void InterceptedRequest::OnReceiveResponse(
+    network::mojom::URLResponseHeadPtr head,
+    mojo::ScopedDataPipeConsumerHandle body,
+    absl::optional<mojo_base::BigBuffer> cached_metadata) {
+  current_response_ = std::move(head);
+  current_body_ = std::move(body);
+  current_cached_metadata_ = std::move(cached_metadata);
+
+  // |current_headers_| may be null for cached responses where OnHeadersReceived
+  // is not called.
+  if (current_request_uses_header_client_ && current_headers_) {
     // Use the headers we got from OnHeadersReceived as that'll contain
     // Set-Cookie if it existed.
-    DCHECK(current_headers_);
     current_response_->headers = current_headers_;
     current_headers_ = nullptr;
     ContinueToResponseStarted(net::OK);
   } else {
     HandleResponseOrRedirectHeaders(
-        base::nullopt,
+        absl::nullopt,
         base::BindOnce(&InterceptedRequest::ContinueToResponseStarted,
                        weak_factory_.GetWeakPtr()));
   }
@@ -468,37 +589,45 @@
 void InterceptedRequest::OnReceiveRedirect(
     const net::RedirectInfo& redirect_info,
     network::mojom::URLResponseHeadPtr head) {
-  bool needs_callback = false;
+  // Whether to notify the client. True by default so that we always notify for
+  // internal redirects that originate from the network process (for HSTS, etc).
+  // False while a redirect is in-progress to avoid duplicate notifications.
+  bool notify_client = !redirect_in_progress_;
 
   current_response_ = std::move(head);
+  current_body_.reset();
+  current_cached_metadata_.reset();
 
-  if (current_request_uses_header_client_) {
+  // |current_headers_| may be null for synthetic redirects where
+  // OnHeadersReceived is not called.
+  if (current_request_uses_header_client_ && current_headers_) {
     // Use the headers we got from OnHeadersReceived as that'll contain
-    // Set-Cookie if it existed. May be null for synthetic redirects.
-    if (current_headers_) {
-      current_response_->headers = current_headers_;
-      current_headers_ = nullptr;
-    }
-  } else {
-    needs_callback = true;
+    // Set-Cookie if it existed.
+    current_response_->headers = current_headers_;
+    current_headers_ = nullptr;
+  }
+
+  if (--redirect_limit_ == 0) {
+    SendErrorAndCompleteImmediately(net::ERR_TOO_MANY_REDIRECTS);
+    return;
   }
 
   net::RedirectInfo new_redirect_info;
 
   // When we redirect via ContinueToHandleOverrideHeaders the |redirect_info|
   // value is sometimes nonsense (HTTP_OK). Also, we won't get another call to
-  // OnHeadersReceived for the new URL so we need to execute the callback here.
+  // OnHeadersReceived for the new URL so we need to notify the client here.
   if (header_client_redirect_url_.is_valid() &&
       redirect_info.status_code == net::HTTP_OK) {
     DCHECK(current_request_uses_header_client_);
-    needs_callback = true;
+    notify_client = true;
     new_redirect_info =
         MakeRedirectResponseAndInfo(header_client_redirect_url_);
   } else {
     new_redirect_info = redirect_info;
   }
 
-  if (needs_callback) {
+  if (notify_client) {
     HandleResponseOrRedirectHeaders(
         new_redirect_info,
         base::BindOnce(&InterceptedRequest::ContinueToBeforeRedirect,
@@ -532,21 +661,10 @@
   std::move(callback).Run();
 }
 
-void InterceptedRequest::OnReceiveCachedMetadata(mojo_base::BigBuffer data) {
-  target_client_->OnReceiveCachedMetadata(std::move(data));
-}
-
 void InterceptedRequest::OnTransferSizeUpdated(int32_t transfer_size_diff) {
   target_client_->OnTransferSizeUpdated(transfer_size_diff);
 }
 
-void InterceptedRequest::OnStartLoadingResponseBody(
-    mojo::ScopedDataPipeConsumerHandle body) {
-  target_client_->OnStartLoadingResponseBody(
-      factory_->request_handler_->OnFilterResponseBody(id_, request_,
-                                                       std::move(body)));
-}
-
 void InterceptedRequest::OnComplete(
     const network::URLLoaderCompletionStatus& status) {
   // Only wait for the original loader to possibly have a custom error if the
@@ -561,17 +679,19 @@
 void InterceptedRequest::FollowRedirect(
     const std::vector<std::string>& removed_headers_ext,
     const net::HttpRequestHeaders& modified_headers_ext,
-    const base::Optional<GURL>& new_url) {
+    const net::HttpRequestHeaders& modified_cors_exempt_headers,
+    const absl::optional<GURL>& new_url) {
   std::vector<std::string> removed_headers = removed_headers_ext;
   net::HttpRequestHeaders modified_headers = modified_headers_ext;
   OnProcessRequestHeaders(new_url.value_or(GURL()), &modified_headers,
                           &removed_headers);
 
   // If |OnURLLoaderClientError| was called then we're just waiting for the
-  // connection error handler of |proxied_loader_binding_|. Don't restart the
+  // connection error handler of |proxied_loader_receiver_|. Don't restart the
   // job since that'll create another URLLoader.
-  if (!target_client_)
+  if (!target_client_) {
     return;
+  }
 
   // Normally we would call FollowRedirect on the target loader and it would
   // begin loading the redirected request. However, the client might want to
@@ -581,18 +701,21 @@
 
 void InterceptedRequest::SetPriority(net::RequestPriority priority,
                                      int32_t intra_priority_value) {
-  if (target_loader_)
+  if (target_loader_) {
     target_loader_->SetPriority(priority, intra_priority_value);
+  }
 }
 
 void InterceptedRequest::PauseReadingBodyFromNet() {
-  if (target_loader_)
+  if (target_loader_) {
     target_loader_->PauseReadingBodyFromNet();
+  }
 }
 
 void InterceptedRequest::ResumeReadingBodyFromNet() {
-  if (target_loader_)
+  if (target_loader_) {
     target_loader_->ResumeReadingBodyFromNet();
+  }
 }
 
 // Helper methods.
@@ -628,6 +751,8 @@
     current_response_ = network::mojom::URLResponseHead::New();
     current_response_->request_start = base::TimeTicks::Now();
     current_response_->response_start = base::TimeTicks::Now();
+    current_body_.reset();
+    current_cached_metadata_.reset();
 
     auto headers = MakeResponseHeaders(
         net::HTTP_TEMPORARY_REDIRECT, std::string(), std::string(),
@@ -635,21 +760,21 @@
     current_response_->headers = headers;
 
     current_response_->encoded_data_length = headers->raw_headers().length();
-    current_response_->content_length = current_response_->encoded_body_length =
-        0;
+    current_response_->content_length = 0;
+    current_response_->encoded_body_length = 0;
 
     std::string origin;
     if (request_.headers.GetHeader(net::HttpRequestHeaders::kOrigin, &origin) &&
         origin != url::Origin().Serialize()) {
       // Allow redirects of cross-origin resource loads.
-      headers->AddHeader(MakeHeader(
-          network::cors::header_names::kAccessControlAllowOrigin, origin));
+      headers->AddHeader(network::cors::header_names::kAccessControlAllowOrigin,
+                         origin);
     }
 
     if (request_.credentials_mode ==
         network::mojom::CredentialsMode::kInclude) {
-      headers->AddHeader(MakeHeader(
-          network::cors::header_names::kAccessControlAllowCredentials, "true"));
+      headers->AddHeader(
+          network::cors::header_names::kAccessControlAllowCredentials, "true");
     }
 
     const net::RedirectInfo& redirect_info =
@@ -679,44 +804,42 @@
 
 void InterceptedRequest::ContinueAfterIntercept() {
   if (!target_loader_ && target_factory_) {
-    network::mojom::URLLoaderClientPtr proxied_client;
-    proxied_client_binding_.Bind(mojo::MakeRequest(&proxied_client));
-
     // Even if this request does not use the header client, future redirects
     // might, so we need to set the option on the loader.
     uint32_t options = options_ | network::mojom::kURLLoadOptionUseHeaderClient;
     target_factory_->CreateLoaderAndStart(
-        mojo::MakeRequest(&target_loader_), id_.routing_id(), id_.request_id(),
-        options, request_, proxied_client.PassInterface(), traffic_annotation_);
+        target_loader_.BindNewPipeAndPassReceiver(), id_, options, request_,
+        proxied_client_receiver_.BindNewPipeAndPassRemote(),
+        traffic_annotation_);
   }
 }
 
 void InterceptedRequest::ContinueAfterInterceptWithOverride(
     std::unique_ptr<ResourceResponse> response) {
-  network::mojom::URLLoaderClientPtr proxied_client;
-  proxied_client_binding_.Bind(mojo::MakeRequest(&proxied_client));
-
   // StreamReaderURLLoader will synthesize TrustedHeaderClient callbacks to
   // avoid having Set-Cookie headers stripped by the IPC layer.
   current_request_uses_header_client_ = true;
-  network::mojom::TrustedHeaderClientPtr header_client;
-  header_client_receiver_.Bind(mojo::MakeRequest(&header_client));
 
   stream_loader_ = new StreamReaderURLLoader(
-      id_, request_, std::move(proxied_client), std::move(header_client),
-      traffic_annotation_,
+      id_, request_, proxied_client_receiver_.BindNewPipeAndPassRemote(),
+      header_client_receiver_.BindNewPipeAndPassRemote(), traffic_annotation_,
+      std::move(current_cached_metadata_),
       std::make_unique<InterceptDelegate>(std::move(response),
                                           weak_factory_.GetWeakPtr()));
   stream_loader_->Start();
 }
 
 void InterceptedRequest::HandleResponseOrRedirectHeaders(
-    base::Optional<net::RedirectInfo> redirect_info,
+    absl::optional<net::RedirectInfo> redirect_info,
     net::CompletionOnceCallback continuation) {
   override_headers_ = nullptr;
   redirect_url_ = redirect_info.has_value() ? redirect_info->new_url : GURL();
   original_url_ = request_.url;
 
+  if (!redirect_url_.is_empty()) {
+    redirect_in_progress_ = true;
+  }
+
   // |current_response_| may be nullptr when called from OnHeadersReceived.
   auto headers =
       current_response_ ? current_response_->headers : current_headers_;
@@ -727,8 +850,9 @@
       id_, request_, redirect_url_, headers.get());
 
   // Pause handling of client messages before waiting on an async callback.
-  if (proxied_client_binding_)
-    proxied_client_binding_.PauseIncomingMethodCallProcessing();
+  if (proxied_client_receiver_.is_bound()) {
+    proxied_client_receiver_.Pause();
+  }
 
   factory_->request_handler_->OnRequestResponse(
       id_, &request_, headers.get(), redirect_info,
@@ -769,9 +893,10 @@
   }
 
   DCHECK(on_headers_received_callback_);
-  base::Optional<std::string> headers;
-  if (override_headers_)
+  absl::optional<std::string> headers;
+  if (override_headers_) {
     headers = override_headers_->raw_headers();
+  }
   header_client_redirect_url_ = redirect_url_;
   std::move(on_headers_received_callback_).Run(net::OK, headers, redirect_url_);
 
@@ -779,8 +904,9 @@
   redirect_url_ = GURL();
 
   // Resume handling of client messages after continuing from an async callback.
-  if (proxied_client_binding_)
-    proxied_client_binding_.ResumeIncomingMethodCallProcessing();
+  if (proxied_client_receiver_.is_bound()) {
+    proxied_client_receiver_.Resume();
+  }
 }
 
 net::RedirectInfo InterceptedRequest::MakeRedirectResponseAndInfo(
@@ -791,8 +917,8 @@
       net::HttpRequestHeaders::kContentType);
 
   // Clear the Content-Length values.
-  current_response_->content_length = current_response_->encoded_body_length =
-      0;
+  current_response_->content_length = 0;
+  current_response_->encoded_body_length = 0;
   current_response_->headers->RemoveHeader(
       net::HttpRequestHeaders::kContentLength);
 
@@ -816,49 +942,61 @@
   }
 
   request_was_redirected_ = true;
+  redirect_in_progress_ = false;
 
-  if (header_client_redirect_url_.is_valid())
+  if (header_client_redirect_url_.is_valid()) {
     header_client_redirect_url_ = GURL();
+  }
 
   const GURL redirect_url = redirect_url_;
   override_headers_ = nullptr;
   redirect_url_ = GURL();
 
   // Resume handling of client messages after continuing from an async callback.
-  if (proxied_client_binding_)
-    proxied_client_binding_.ResumeIncomingMethodCallProcessing();
-
-  if (redirect_url.is_valid()) {
-    net::RedirectInfo new_redirect_info = redirect_info;
-    new_redirect_info.new_url = redirect_url;
-    target_client_->OnReceiveRedirect(new_redirect_info,
-                                      std::move(current_response_));
-    request_.url = redirect_url;
-  } else {
-    target_client_->OnReceiveRedirect(redirect_info,
-                                      std::move(current_response_));
-    request_.url = redirect_info.new_url;
+  if (proxied_client_receiver_.is_bound()) {
+    proxied_client_receiver_.Resume();
   }
 
-  // If request_ changes from POST to GET, strip POST headers.
-  const bool post_to_get =
-      request_.method == "POST" &&
-      redirect_info.new_method == net::HttpRequestHeaders::kGetMethod;
+  const auto original_url = request_.url;
+  const auto original_method = request_.method;
 
-  request_.method = redirect_info.new_method;
-  request_.site_for_cookies = redirect_info.new_site_for_cookies;
-  request_.referrer = GURL(redirect_info.new_referrer);
-  request_.referrer_policy = redirect_info.new_referrer_policy;
+  net::RedirectInfo new_redirect_info = redirect_info;
+  if (redirect_url.is_valid()) {
+    new_redirect_info.new_url = redirect_url;
+    new_redirect_info.new_site_for_cookies =
+        net::SiteForCookies::FromUrl(redirect_url);
+  }
 
-  // The request method can be changed to "GET". In this case we need to
-  // reset the request body manually, and strip the POST headers.
-  if (request_.method == net::HttpRequestHeaders::kGetMethod) {
+  target_client_->OnReceiveRedirect(new_redirect_info,
+                                    std::move(current_response_));
+
+  request_.url = new_redirect_info.new_url;
+  request_.method = new_redirect_info.new_method;
+  request_.site_for_cookies = new_redirect_info.new_site_for_cookies;
+  request_.referrer = GURL(new_redirect_info.new_referrer);
+  request_.referrer_policy = new_redirect_info.new_referrer_policy;
+
+  if (request_.trusted_params) {
+    request_.trusted_params->isolation_info =
+        request_.trusted_params->isolation_info.CreateForRedirect(
+            url::Origin::Create(request_.url));
+  }
+
+  // Remove existing Cookie headers. They may be re-added after Restart().
+  const std::vector<std::string> remove_headers{
+      net::HttpRequestHeaders::kCookie};
+
+  // Use common logic for sanitizing request headers including Origin and
+  // Content-*.
+  bool should_clear_upload;
+  net::RedirectUtil::UpdateHttpRequest(original_url, original_method,
+                                       new_redirect_info,
+                                       absl::make_optional(remove_headers),
+                                       /*modified_headers=*/absl::nullopt,
+                                       &request_.headers, &should_clear_upload);
+
+  if (should_clear_upload) {
     request_.request_body = nullptr;
-
-    if (post_to_get) {
-      request_.headers.RemoveHeader(net::HttpRequestHeaders::kContentLength);
-      request_.headers.RemoveHeader(net::HttpRequestHeaders::kContentType);
-    }
   }
 }
 
@@ -872,10 +1010,12 @@
   override_headers_ = nullptr;
   redirect_url_ = GURL();
 
+  scoped_refptr<net::HttpResponseHeaders> headers =
+      current_response_ ? current_response_->headers : nullptr;
+
   std::string location;
-  const bool is_redirect = redirect_url.is_valid() ||
-                           (current_response_->headers &&
-                            current_response_->headers->IsRedirect(&location));
+  const bool is_redirect =
+      redirect_url.is_valid() || (headers && headers->IsRedirect(&location));
   if (stream_loader_ && is_redirect) {
     // Redirecting from OnReceiveResponse generally isn't supported by the
     // NetworkService, so we can only support it when using a custom loader.
@@ -894,16 +1034,41 @@
     LOG_IF(WARNING, is_redirect) << "Redirect at this time is not supported by "
                                     "the default network loader.";
 
+    // CORS check for requests that are handled by the client. Requests handled
+    // by the network process will be checked there.
+    if (stream_loader_ && !is_redirect && request_.request_initiator &&
+        network::cors::ShouldCheckCors(request_.url, request_.request_initiator,
+                                       request_.mode)) {
+      const auto result = network::cors::CheckAccess(
+          request_.url,
+          GetHeaderString(
+              headers.get(),
+              network::cors::header_names::kAccessControlAllowOrigin),
+          GetHeaderString(
+              headers.get(),
+              network::cors::header_names::kAccessControlAllowCredentials),
+          request_.credentials_mode, *request_.request_initiator);
+      if (!result.has_value() &&
+          !HasCrossOriginWhitelistEntry(*request_.request_initiator,
+                                        url::Origin::Create(request_.url))) {
+        SendErrorStatusAndCompleteImmediately(
+            network::URLLoaderCompletionStatus(result.error()));
+        return;
+      }
+    }
+
     // Resume handling of client messages after continuing from an async
     // callback.
-    if (proxied_client_binding_)
-      proxied_client_binding_.ResumeIncomingMethodCallProcessing();
+    if (proxied_client_receiver_.is_bound()) {
+      proxied_client_receiver_.Resume();
+    }
 
-    target_client_->OnReceiveResponse(std::move(current_response_));
+    target_client_->OnReceiveResponse(
+        std::move(current_response_),
+        factory_->request_handler_->OnFilterResponseBody(
+            id_, request_, std::move(current_body_)),
+        std::move(current_cached_metadata_));
   }
-
-  if (stream_loader_)
-    stream_loader_->ContinueResponse(is_redirect);
 }
 
 void InterceptedRequest::OnDestroy() {
@@ -925,8 +1090,9 @@
 
   if (!modified_headers->IsEmpty() || !removed_headers->empty()) {
     request_.headers.MergeFrom(*modified_headers);
-    for (const std::string& name : *removed_headers)
+    for (const std::string& name : *removed_headers) {
       request_.headers.RemoveHeader(name);
+    }
   }
 }
 
@@ -940,15 +1106,18 @@
 
 void InterceptedRequest::OnURLLoaderError(uint32_t custom_reason,
                                           const std::string& description) {
-  if (custom_reason == network::mojom::URLLoader::kClientDisconnectReason)
-    SendErrorCallback(safe_browsing::GetNetErrorCodeForSafeBrowsing(), true);
+  if (custom_reason == network::mojom::URLLoader::kClientDisconnectReason &&
+      description == safe_browsing::kCustomCancelReasonForURLLoader) {
+    SendErrorCallback(safe_browsing::kNetErrorCodeForSafeBrowsing, true);
+  }
 
   got_loader_error_ = true;
 
   // If CallOnComplete was already called, then this object is ready to be
   // deleted.
-  if (!target_client_)
+  if (!target_client_) {
     OnDestroy();
+  }
 }
 
 void InterceptedRequest::CallOnComplete(
@@ -956,12 +1125,13 @@
     bool wait_for_loader_error) {
   status_ = status;
 
-  if (target_client_)
+  if (target_client_) {
     target_client_->OnComplete(status);
+  }
 
-  if (proxied_loader_binding_ &&
+  if (proxied_loader_receiver_.is_bound() &&
       (wait_for_loader_error && !got_loader_error_)) {
-    // Don't delete |this| yet, in case the |proxied_loader_binding_|'s
+    // Don't delete |this| yet, in case the |proxied_loader_receiver_|'s
     // error_handler is called with a reason to indicate an error which we want
     // to send to the client bridge. Also reset |target_client_| so we don't
     // get its error_handler called and then delete |this|.
@@ -969,7 +1139,7 @@
 
     // Since the original client is gone no need to continue loading the
     // request.
-    proxied_client_binding_.Close();
+    proxied_client_receiver_.reset();
     header_client_receiver_.reset();
     target_loader_.reset();
 
@@ -983,7 +1153,13 @@
 }
 
 void InterceptedRequest::SendErrorAndCompleteImmediately(int error_code) {
-  status_ = network::URLLoaderCompletionStatus(error_code);
+  SendErrorStatusAndCompleteImmediately(
+      network::URLLoaderCompletionStatus(error_code));
+}
+
+void InterceptedRequest::SendErrorStatusAndCompleteImmediately(
+    const network::URLLoaderCompletionStatus& status) {
+  status_ = status;
   SendErrorCallback(status_.error_code, false);
   target_client_->OnComplete(status_);
   OnDestroy();
@@ -993,8 +1169,9 @@
                                            bool safebrowsing_hit) {
   // Ensure we only send one error callback, e.g. to avoid sending two if
   // there's both a networking error and safe browsing blocked the request.
-  if (sent_error_callback_)
+  if (sent_error_callback_) {
     return;
+  }
 
   sent_error_callback_ = true;
   factory_->request_handler_->OnRequestError(id_, request_, error_code,
@@ -1014,7 +1191,7 @@
 InterceptedRequestHandler::~InterceptedRequestHandler() {}
 
 void InterceptedRequestHandler::OnBeforeRequest(
-    const RequestId& id,
+    int32_t request_id,
     network::ResourceRequest* request,
     bool request_was_redirected,
     OnBeforeRequestResultCallback callback,
@@ -1023,17 +1200,17 @@
 }
 
 void InterceptedRequestHandler::ShouldInterceptRequest(
-    const RequestId& id,
+    int32_t request_id,
     network::ResourceRequest* request,
     ShouldInterceptRequestResultCallback callback) {
   std::move(callback).Run(nullptr);
 }
 
 void InterceptedRequestHandler::OnRequestResponse(
-    const RequestId& id,
+    int32_t request_id,
     network::ResourceRequest* request,
     net::HttpResponseHeaders* headers,
-    base::Optional<net::RedirectInfo> redirect_info,
+    absl::optional<net::RedirectInfo> redirect_info,
     OnRequestResponseResultCallback callback) {
   std::move(callback).Run(
       ResponseMode::CONTINUE, nullptr,
@@ -1042,7 +1219,7 @@
 
 mojo::ScopedDataPipeConsumerHandle
 InterceptedRequestHandler::OnFilterResponseBody(
-    const RequestId& id,
+    int32_t request_id,
     const network::ResourceRequest& request,
     mojo::ScopedDataPipeConsumerHandle body) {
   return body;
@@ -1054,7 +1231,7 @@
 
 ProxyURLLoaderFactory::ProxyURLLoaderFactory(
     mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver,
-    network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
+    mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_remote,
     mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
         header_client_receiver,
     std::unique_ptr<InterceptedRequestHandler> request_handler)
@@ -1063,17 +1240,18 @@
   DCHECK(request_handler_);
 
   // Actual creation of the factory.
-  if (target_factory_info) {
-    target_factory_.Bind(std::move(target_factory_info));
-    target_factory_.set_connection_error_handler(base::BindOnce(
+  if (target_factory_remote) {
+    target_factory_.Bind(std::move(target_factory_remote));
+    target_factory_.set_disconnect_handler(base::BindOnce(
         &ProxyURLLoaderFactory::OnTargetFactoryError, base::Unretained(this)));
   }
-  proxy_bindings_.AddBinding(this, std::move(factory_receiver));
-  proxy_bindings_.set_connection_error_handler(base::BindRepeating(
+  proxy_receivers_.Add(this, std::move(factory_receiver));
+  proxy_receivers_.set_disconnect_handler(base::BindRepeating(
       &ProxyURLLoaderFactory::OnProxyBindingError, base::Unretained(this)));
 
-  if (header_client_receiver)
+  if (header_client_receiver) {
     url_loader_header_client_receiver_.Bind(std::move(header_client_receiver));
+  }
 }
 
 ProxyURLLoaderFactory::~ProxyURLLoaderFactory() {
@@ -1083,14 +1261,14 @@
 // static
 void ProxyURLLoaderFactory::CreateOnIOThread(
     mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver,
-    network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
+    mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory,
     mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
         header_client_receiver,
     content::ResourceContext* resource_context,
     std::unique_ptr<InterceptedRequestHandler> request_handler) {
   CEF_REQUIRE_IOT();
   auto proxy = new ProxyURLLoaderFactory(
-      std::move(factory_receiver), std::move(target_factory_info),
+      std::move(factory_receiver), std::move(target_factory),
       std::move(header_client_receiver), std::move(request_handler));
   ResourceContextData::AddProxy(proxy, resource_context);
 }
@@ -1114,13 +1292,14 @@
   DCHECK(request_handler);
 
   auto proxied_receiver = std::move(*factory_receiver);
-  network::mojom::URLLoaderFactoryPtrInfo target_factory_info;
-  *factory_receiver = mojo::MakeRequest(&target_factory_info);
+  mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_remote;
+  *factory_receiver = target_factory_remote.InitWithNewPipeAndPassReceiver();
 
   mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
       header_client_receiver;
-  if (header_client)
+  if (header_client) {
     header_client_receiver = header_client->InitWithNewPipeAndPassReceiver();
+  }
 
   content::ResourceContext* resource_context =
       browser_context->GetResourceContext();
@@ -1130,31 +1309,37 @@
       CEF_IOT,
       base::BindOnce(
           &ProxyURLLoaderFactory::CreateOnIOThread, std::move(proxied_receiver),
-          std::move(target_factory_info), std::move(header_client_receiver),
+          std::move(target_factory_remote), std::move(header_client_receiver),
           base::Unretained(resource_context), std::move(request_handler)));
 }
 
 // static
-ProxyURLLoaderFactory* ProxyURLLoaderFactory::CreateProxy(
+void ProxyURLLoaderFactory::CreateProxy(
     content::WebContents::Getter web_contents_getter,
     mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_receiver,
     std::unique_ptr<InterceptedRequestHandler> request_handler) {
-  CEF_REQUIRE_IOT();
   DCHECK(request_handler);
 
+  if (!CEF_CURRENTLY_ON_IOT()) {
+    CEF_POST_TASK(
+        CEF_IOT,
+        base::BindOnce(CreateProxyHelper, web_contents_getter,
+                       std::move(loader_receiver), std::move(request_handler)));
+    return;
+  }
+
   auto proxy = new ProxyURLLoaderFactory(
-      std::move(loader_receiver), nullptr,
+      std::move(loader_receiver),
+      mojo::PendingRemote<network::mojom::URLLoaderFactory>(),
       mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>(),
       std::move(request_handler));
   CEF_POST_TASK(CEF_UIT,
                 base::BindOnce(ResourceContextData::AddProxyOnUIThread,
                                base::Unretained(proxy), web_contents_getter));
-  return proxy;
 }
 
 void ProxyURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
@@ -1166,24 +1351,25 @@
     return;
   }
 
-  bool pass_through = false;
-  if (pass_through) {
+  if (DisableRequestHandlingForTesting() && request.url.SchemeIsHTTPOrHTTPS()) {
     // This is the so-called pass-through, no-op option.
-    target_factory_->CreateLoaderAndStart(
-        std::move(receiver), routing_id, request_id, options, request,
-        std::move(client), traffic_annotation);
+    if (target_factory_) {
+      target_factory_->CreateLoaderAndStart(std::move(receiver), request_id,
+                                            options, request, std::move(client),
+                                            traffic_annotation);
+    }
     return;
   }
 
   mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_clone;
-  if (target_factory_)
+  if (target_factory_) {
     target_factory_->Clone(
         target_factory_clone.InitWithNewPipeAndPassReceiver());
+  }
 
   InterceptedRequest* req = new InterceptedRequest(
-      this, RequestId(request_id, routing_id), options, request,
-      traffic_annotation, std::move(receiver), std::move(client),
-      std::move(target_factory_clone));
+      this, request_id, options, request, traffic_annotation,
+      std::move(receiver), std::move(client), std::move(target_factory_clone));
   requests_.insert(std::make_pair(request_id, base::WrapUnique(req)));
   req->Restart();
 }
@@ -1191,7 +1377,7 @@
 void ProxyURLLoaderFactory::Clone(
     mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory) {
   CEF_REQUIRE_IOT();
-  proxy_bindings_.AddBinding(this, std::move(factory));
+  proxy_receivers_.Add(this, std::move(factory));
 }
 
 void ProxyURLLoaderFactory::OnLoaderCreated(
@@ -1199,34 +1385,36 @@
     mojo::PendingReceiver<network::mojom::TrustedHeaderClient> receiver) {
   CEF_REQUIRE_IOT();
   auto request_it = requests_.find(request_id);
-  if (request_it != requests_.end())
+  if (request_it != requests_.end()) {
     request_it->second->OnLoaderCreated(std::move(receiver));
+  }
 }
 
 void ProxyURLLoaderFactory::OnLoaderForCorsPreflightCreated(
-    const ::network::ResourceRequest& request,
-    mojo::PendingReceiver<network::mojom::TrustedHeaderClient> header_client) {
+    const network::ResourceRequest& request,
+    mojo::PendingReceiver<network::mojom::TrustedHeaderClient> receiver) {
   CEF_REQUIRE_IOT();
-  // TODO(cef): Should we do something here?
+  new CorsPreflightRequest(std::move(receiver));
 }
 
 void ProxyURLLoaderFactory::OnTargetFactoryError() {
   // Stop calls to CreateLoaderAndStart() when |target_factory_| is invalid.
   target_factory_.reset();
-  proxy_bindings_.CloseAllBindings();
+  proxy_receivers_.Clear();
 
   MaybeDestroySelf();
 }
 
 void ProxyURLLoaderFactory::OnProxyBindingError() {
-  if (proxy_bindings_.empty())
+  if (proxy_receivers_.empty()) {
     target_factory_.reset();
+  }
 
   MaybeDestroySelf();
 }
 
 void ProxyURLLoaderFactory::RemoveRequest(InterceptedRequest* request) {
-  auto it = requests_.find(request->id().request_id());
+  auto it = requests_.find(request->id());
   DCHECK(it != requests_.end());
   requests_.erase(it);
 
@@ -1236,8 +1424,9 @@
 void ProxyURLLoaderFactory::MaybeDestroySelf() {
   // Even if all URLLoaderFactory pipes connected to this object have been
   // closed it has to stay alive until all active requests have completed.
-  if (target_factory_.is_bound() || !requests_.empty())
+  if (target_factory_.is_bound() || !requests_.empty()) {
     return;
+  }
 
   destroyed_ = true;
 
diff --git a/src/libcef/browser/net_service/proxy_url_loader_factory.h b/src/libcef/browser/net_service/proxy_url_loader_factory.h
index fc1b4f2..b9fdeae 100644
--- a/src/libcef/browser/net_service/proxy_url_loader_factory.h
+++ b/src/libcef/browser/net_service/proxy_url_loader_factory.h
@@ -8,18 +8,21 @@
 
 #include "libcef/browser/net_service/stream_reader_url_loader.h"
 
-#include "base/callback.h"
 #include "base/containers/unique_ptr_adapters.h"
+#include "base/functional/callback.h"
 #include "base/hash/hash.h"
-#include "base/macros.h"
-#include "base/optional.h"
 #include "base/strings/string_piece.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/web_contents.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace content {
+class ResourceContext;
+}
 
 namespace net_service {
 
@@ -31,6 +34,11 @@
 class InterceptedRequestHandler {
  public:
   InterceptedRequestHandler();
+
+  InterceptedRequestHandler(const InterceptedRequestHandler&) = delete;
+  InterceptedRequestHandler& operator=(const InterceptedRequestHandler&) =
+      delete;
+
   virtual ~InterceptedRequestHandler();
 
   // Optionally modify |request| and execute |callback| to continue the request.
@@ -42,7 +50,7 @@
       base::OnceCallback<void(bool /* intercept_request */,
                               bool /* intercept_only */)>;
   using CancelRequestCallback = base::OnceCallback<void(int /* error_code */)>;
-  virtual void OnBeforeRequest(const RequestId& id,
+  virtual void OnBeforeRequest(int32_t request_id,
                                network::ResourceRequest* request,
                                bool request_was_redirected,
                                OnBeforeRequestResultCallback callback,
@@ -53,7 +61,7 @@
   using ShouldInterceptRequestResultCallback =
       base::OnceCallback<void(std::unique_ptr<ResourceResponse>)>;
   virtual void ShouldInterceptRequest(
-      const RequestId& id,
+      int32_t request_id,
       network::ResourceRequest* request,
       ShouldInterceptRequestResultCallback callback);
 
@@ -64,7 +72,7 @@
   // values will be merged first, and then any |removed_headers| values will be
   // removed. This comparison is case sensitive.
   virtual void ProcessRequestHeaders(
-      const RequestId& id,
+      int32_t request_id,
       const network::ResourceRequest& request,
       const GURL& redirect_url,
       net::HttpRequestHeaders* modified_headers,
@@ -75,7 +83,7 @@
   // method is called in response to a redirect. Even though |head| is const the
   // |head.headers| value is non-const and any changes will be passed to the
   // client.
-  virtual void ProcessResponseHeaders(const RequestId& id,
+  virtual void ProcessResponseHeaders(int32_t request_id,
                                       const network::ResourceRequest& request,
                                       const GURL& redirect_url,
                                       net::HttpResponseHeaders* headers) {}
@@ -97,32 +105,29 @@
       scoped_refptr<net::HttpResponseHeaders> /* override_headers */,
       const GURL& /* redirect_url */)>;
   virtual void OnRequestResponse(
-      const RequestId& id,
+      int32_t request_id,
       network::ResourceRequest* request,
       net::HttpResponseHeaders* headers,
-      base::Optional<net::RedirectInfo> redirect_info,
+      absl::optional<net::RedirectInfo> redirect_info,
       OnRequestResponseResultCallback callback);
 
   // Called to optionally filter the response body.
   virtual mojo::ScopedDataPipeConsumerHandle OnFilterResponseBody(
-      const RequestId& id,
+      int32_t request_id,
       const network::ResourceRequest& request,
       mojo::ScopedDataPipeConsumerHandle body);
 
   // Called on completion notification from the loader (successful or not).
   virtual void OnRequestComplete(
-      const RequestId& id,
+      int32_t request_id,
       const network::ResourceRequest& request,
       const network::URLLoaderCompletionStatus& status) {}
 
   // Called on error.
-  virtual void OnRequestError(const RequestId& id,
+  virtual void OnRequestError(int32_t request_id,
                               const network::ResourceRequest& request,
                               int error_code,
                               bool safebrowsing_hit) {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(InterceptedRequestHandler);
 };
 
 // URL Loader Factory that supports request/response interception, processing
@@ -133,6 +138,9 @@
     : public network::mojom::URLLoaderFactory,
       public network::mojom::TrustedURLLoaderHeaderClient {
  public:
+  ProxyURLLoaderFactory(const ProxyURLLoaderFactory&) = delete;
+  ProxyURLLoaderFactory& operator=(const ProxyURLLoaderFactory&) = delete;
+
   ~ProxyURLLoaderFactory() override;
 
   // Create a proxy object on the UI thread.
@@ -144,7 +152,7 @@
       std::unique_ptr<InterceptedRequestHandler> request_handler);
 
   // Create a proxy object on the IO thread.
-  static ProxyURLLoaderFactory* CreateProxy(
+  static void CreateProxy(
       content::WebContents::Getter web_contents_getter,
       mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_request,
       std::unique_ptr<InterceptedRequestHandler> request_handler);
@@ -152,7 +160,6 @@
   // mojom::URLLoaderFactory methods:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
@@ -168,8 +175,8 @@
       mojo::PendingReceiver<network::mojom::TrustedHeaderClient> receiver)
       override;
   void OnLoaderForCorsPreflightCreated(
-      const ::network::ResourceRequest& request,
-      mojo::PendingReceiver<network::mojom::TrustedHeaderClient> header_client)
+      const network::ResourceRequest& request,
+      mojo::PendingReceiver<network::mojom::TrustedHeaderClient> receiver)
       override;
 
  private:
@@ -178,14 +185,16 @@
 
   ProxyURLLoaderFactory(
       mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver,
-      network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
+      mojo::PendingRemote<network::mojom::URLLoaderFactory>
+          target_factory_remote,
       mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
           header_client_receiver,
       std::unique_ptr<InterceptedRequestHandler> request_handler);
 
   static void CreateOnIOThread(
       mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver,
-      network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
+      mojo::PendingRemote<network::mojom::URLLoaderFactory>
+          target_factory_remote,
       mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
           header_client_receiver,
       content::ResourceContext* resource_context,
@@ -199,9 +208,9 @@
   void RemoveRequest(InterceptedRequest* request);
   void MaybeDestroySelf();
 
-  mojo::BindingSet<network::mojom::URLLoaderFactory> proxy_bindings_;
-  network::mojom::URLLoaderFactoryPtr target_factory_;
-  mojo::Binding<network::mojom::TrustedURLLoaderHeaderClient>
+  mojo::ReceiverSet<network::mojom::URLLoaderFactory> proxy_receivers_;
+  mojo::Remote<network::mojom::URLLoaderFactory> target_factory_;
+  mojo::Receiver<network::mojom::TrustedURLLoaderHeaderClient>
       url_loader_header_client_receiver_{this};
 
   std::unique_ptr<InterceptedRequestHandler> request_handler_;
@@ -213,8 +222,6 @@
   std::map<int32_t, std::unique_ptr<InterceptedRequest>> requests_;
 
   base::WeakPtrFactory<ProxyURLLoaderFactory> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProxyURLLoaderFactory);
 };
 
 }  // namespace net_service
diff --git a/src/libcef/browser/net_service/resource_handler_wrapper.cc b/src/libcef/browser/net_service/resource_handler_wrapper.cc
index 2f27bd1..957a94c 100644
--- a/src/libcef/browser/net_service/resource_handler_wrapper.cc
+++ b/src/libcef/browser/net_service/resource_handler_wrapper.cc
@@ -20,7 +20,11 @@
  public:
   explicit SkipCallbackWrapper(InputStream::SkipCallback callback)
       : callback_(std::move(callback)),
-        work_thread_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
+        work_thread_task_runner_(
+            base::SequencedTaskRunner::GetCurrentDefault()) {}
+
+  SkipCallbackWrapper(const SkipCallbackWrapper&) = delete;
+  SkipCallbackWrapper& operator=(const SkipCallbackWrapper&) = delete;
 
   ~SkipCallbackWrapper() override {
     if (!callback_.is_null()) {
@@ -30,7 +34,7 @@
     }
   }
 
-  void Continue(int64 bytes_skipped) override {
+  void Continue(int64_t bytes_skipped) override {
     if (!work_thread_task_runner_->RunsTasksInCurrentSequence()) {
       work_thread_task_runner_->PostTask(
           FROM_HERE,
@@ -50,14 +54,17 @@
   scoped_refptr<base::SequencedTaskRunner> work_thread_task_runner_;
 
   IMPLEMENT_REFCOUNTING(SkipCallbackWrapper);
-  DISALLOW_COPY_AND_ASSIGN(SkipCallbackWrapper);
 };
 
 class ReadCallbackWrapper : public CefResourceReadCallback {
  public:
   explicit ReadCallbackWrapper(InputStream::ReadCallback callback)
       : callback_(std::move(callback)),
-        work_thread_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
+        work_thread_task_runner_(
+            base::SequencedTaskRunner::GetCurrentDefault()) {}
+
+  ReadCallbackWrapper(const ReadCallbackWrapper&) = delete;
+  ReadCallbackWrapper& operator=(const ReadCallbackWrapper&) = delete;
 
   ~ReadCallbackWrapper() override {
     if (!callback_.is_null()) {
@@ -87,7 +94,6 @@
   scoped_refptr<base::SequencedTaskRunner> work_thread_task_runner_;
 
   IMPLEMENT_REFCOUNTING(ReadCallbackWrapper);
-  DISALLOW_COPY_AND_ASSIGN(ReadCallbackWrapper);
 };
 
 // Helper for accessing a CefResourceHandler without creating reference loops.
@@ -109,8 +115,9 @@
 
   void Detach() {
     base::AutoLock lock_scope(lock_);
-    if (!handler_)
+    if (!handler_) {
       return;
+    }
 
     // Execute on the expected thread.
     CEF_POST_TASK(CEF_IOT,
@@ -126,6 +133,10 @@
 
 class ReadResponseCallbackWrapper : public CefCallback {
  public:
+  ReadResponseCallbackWrapper(const ReadResponseCallbackWrapper&) = delete;
+  ReadResponseCallbackWrapper& operator=(const ReadResponseCallbackWrapper&) =
+      delete;
+
   ~ReadResponseCallbackWrapper() override {
     if (callback_) {
       // This will post to the correct thread if necessary.
@@ -178,8 +189,9 @@
 
   void DoRead() {
     CEF_REQUIRE_IOT();
-    if (!callback_)
+    if (!callback_) {
       return;
+    }
 
     auto handler = handler_provider_->handler();
     if (!handler) {
@@ -218,7 +230,6 @@
   CefRefPtr<ReadCallbackWrapper> callback_;
 
   IMPLEMENT_REFCOUNTING(ReadResponseCallbackWrapper);
-  DISALLOW_COPY_AND_ASSIGN(ReadResponseCallbackWrapper);
 };
 
 class InputStreamWrapper : public InputStream {
@@ -226,6 +237,9 @@
   explicit InputStreamWrapper(scoped_refptr<HandlerProvider> handler_provider)
       : handler_provider_(handler_provider) {}
 
+  InputStreamWrapper(const InputStreamWrapper&) = delete;
+  InputStreamWrapper& operator=(const InputStreamWrapper&) = delete;
+
   ~InputStreamWrapper() override { Cancel(); }
 
   // InputStream methods:
@@ -294,8 +308,6 @@
 
  private:
   scoped_refptr<HandlerProvider> handler_provider_;
-
-  DISALLOW_COPY_AND_ASSIGN(InputStreamWrapper);
 };
 
 class OpenCallbackWrapper : public CefCallback {
@@ -304,7 +316,11 @@
                       std::unique_ptr<InputStreamWrapper> stream)
       : callback_(std::move(callback)),
         stream_(std::move(stream)),
-        work_thread_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
+        work_thread_task_runner_(
+            base::SequencedTaskRunner::GetCurrentDefault()) {}
+
+  OpenCallbackWrapper(const OpenCallbackWrapper&) = delete;
+  OpenCallbackWrapper& operator=(const OpenCallbackWrapper&) = delete;
 
   ~OpenCallbackWrapper() override {
     if (!callback_.is_null()) {
@@ -351,7 +367,6 @@
   scoped_refptr<base::SequencedTaskRunner> work_thread_task_runner_;
 
   IMPLEMENT_REFCOUNTING(OpenCallbackWrapper);
-  DISALLOW_COPY_AND_ASSIGN(OpenCallbackWrapper);
 };
 
 void CallProcessRequestOnIOThread(
@@ -372,18 +387,21 @@
 
 class ResourceResponseWrapper : public ResourceResponse {
  public:
-  ResourceResponseWrapper(const RequestId request_id,
+  ResourceResponseWrapper(const int32_t request_id,
                           CefRefPtr<CefResourceHandler> handler)
       : request_id_(request_id),
         handler_provider_(new HandlerProvider(handler)) {}
 
+  ResourceResponseWrapper(const ResourceResponseWrapper&) = delete;
+  ResourceResponseWrapper& operator=(const ResourceResponseWrapper&) = delete;
+
   ~ResourceResponseWrapper() override {
     // Triggers a call to Cancel on the handler.
     handler_provider_->Detach();
   }
 
   // ResourceResponse methods:
-  bool OpenInputStream(const RequestId& request_id,
+  bool OpenInputStream(int32_t request_id,
                        const network::ResourceRequest& request,
                        OpenCallback callback) override {
     DCHECK_EQ(request_id, request_id_);
@@ -396,7 +414,7 @@
 
     // May be recreated on redirect.
     request_ = new CefRequestImpl();
-    request_->Set(&request, request_id.hash());
+    request_->Set(&request, request_id);
     request_->SetReadOnly(true);
 
     CefRefPtr<OpenCallbackWrapper> callbackWrapper = new OpenCallbackWrapper(
@@ -426,7 +444,7 @@
     return true;
   }
 
-  void GetResponseHeaders(const RequestId& request_id,
+  void GetResponseHeaders(int32_t request_id,
                           int* status_code,
                           std::string* reason_phrase,
                           std::string* mime_type,
@@ -476,8 +494,9 @@
 
     // A |content_length| value may already be specified if the request included
     // a Range header.
-    if (response_length >= 0 && *content_length == -1)
+    if (response_length >= 0 && *content_length == -1) {
       *content_length = response_length;
+    }
 
     CefResponse::HeaderMap headerMap;
     response->GetHeaderMap(headerMap);
@@ -487,18 +506,16 @@
   }
 
  private:
-  const RequestId request_id_;
+  const int32_t request_id_;
 
   CefRefPtr<CefRequestImpl> request_;
   scoped_refptr<HandlerProvider> handler_provider_;
-
-  DISALLOW_COPY_AND_ASSIGN(ResourceResponseWrapper);
 };
 
 }  // namespace
 
 std::unique_ptr<ResourceResponse> CreateResourceResponse(
-    const RequestId& request_id,
+    int32_t request_id,
     CefRefPtr<CefResourceHandler> handler) {
   return std::make_unique<ResourceResponseWrapper>(request_id, handler);
 }
diff --git a/src/libcef/browser/net_service/resource_handler_wrapper.h b/src/libcef/browser/net_service/resource_handler_wrapper.h
index ce7da9b..b47c95b 100644
--- a/src/libcef/browser/net_service/resource_handler_wrapper.h
+++ b/src/libcef/browser/net_service/resource_handler_wrapper.h
@@ -10,14 +10,13 @@
 
 namespace net_service {
 
-class RequestId;
 class ResourceResponse;
 
 // Create a ResourceResponse that delegates to |handler|.
 // The resulting object should be passed to
 // InterceptedRequestHandler::ShouldInterceptRequestResultCallback.
 std::unique_ptr<ResourceResponse> CreateResourceResponse(
-    const RequestId& request_id,
+    int32_t request_id,
     CefRefPtr<CefResourceHandler> handler);
 
 }  // namespace net_service
diff --git a/src/libcef/browser/net_service/resource_request_handler_wrapper.cc b/src/libcef/browser/net_service/resource_request_handler_wrapper.cc
index cb86313..7efaa7e 100644
--- a/src/libcef/browser/net_service/resource_request_handler_wrapper.cc
+++ b/src/libcef/browser/net_service/resource_request_handler_wrapper.cc
@@ -4,25 +4,27 @@
 
 #include "libcef/browser/net_service/resource_request_handler_wrapper.h"
 
-#include "libcef/browser/browser_host_impl.h"
-#include "libcef/browser/browser_platform_delegate.h"
-#include "libcef/browser/content_browser_client.h"
+#include "libcef/browser/browser_host_base.h"
 #include "libcef/browser/context.h"
+#include "libcef/browser/iothread_state.h"
 #include "libcef/browser/net_service/cookie_helper.h"
 #include "libcef/browser/net_service/proxy_url_loader_factory.h"
 #include "libcef/browser/net_service/resource_handler_wrapper.h"
 #include "libcef/browser/net_service/response_filter_wrapper.h"
-#include "libcef/browser/resource_context.h"
+#include "libcef/browser/prefs/browser_prefs.h"
 #include "libcef/browser/thread_util.h"
-#include "libcef/common/content_client.h"
+#include "libcef/common/app_manager.h"
 #include "libcef/common/net/scheme_registration.h"
 #include "libcef/common/net_service/net_service_util.h"
 #include "libcef/common/request_impl.h"
 #include "libcef/common/response_impl.h"
 
-#include "chrome/common/chrome_features.h"
+#include "chrome/browser/profiles/profile.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/prefs/pref_service.h"
+#include "content/browser/renderer_host/frame_tree_node.h"
+#include "content/browser/renderer_host/render_frame_host_impl.h"
+#include "content/browser/storage_partition_impl.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
@@ -30,7 +32,6 @@
 #include "content/public/browser/web_contents.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_status_code.h"
-#include "net/http/http_util.h"
 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
 #include "ui/base/page_transition_types.h"
 #include "url/origin.h"
@@ -42,12 +43,16 @@
 const int kLoadNoCookiesFlags =
     net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES;
 
-class RequestCallbackWrapper : public CefRequestCallback {
+class RequestCallbackWrapper : public CefCallback {
  public:
   using Callback = base::OnceCallback<void(bool /* allow */)>;
   explicit RequestCallbackWrapper(Callback callback)
       : callback_(std::move(callback)),
-        work_thread_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
+        work_thread_task_runner_(
+            base::SequencedTaskRunner::GetCurrentDefault()) {}
+
+  RequestCallbackWrapper(const RequestCallbackWrapper&) = delete;
+  RequestCallbackWrapper& operator=(const RequestCallbackWrapper&) = delete;
 
   ~RequestCallbackWrapper() override {
     if (!callback_.is_null()) {
@@ -57,11 +62,16 @@
     }
   }
 
-  void Continue(bool allow) override {
+  void Continue() override { ContinueNow(true); }
+
+  void Cancel() override { ContinueNow(false); }
+
+ private:
+  void ContinueNow(bool allow) {
     if (!work_thread_task_runner_->RunsTasksInCurrentSequence()) {
       work_thread_task_runner_->PostTask(
           FROM_HERE,
-          base::BindOnce(&RequestCallbackWrapper::Continue, this, allow));
+          base::BindOnce(&RequestCallbackWrapper::ContinueNow, this, allow));
       return;
     }
     if (!callback_.is_null()) {
@@ -69,41 +79,13 @@
     }
   }
 
-  void Cancel() override { Continue(false); }
-
- private:
   Callback callback_;
 
   scoped_refptr<base::SequencedTaskRunner> work_thread_task_runner_;
 
   IMPLEMENT_REFCOUNTING(RequestCallbackWrapper);
-  DISALLOW_COPY_AND_ASSIGN(RequestCallbackWrapper);
 };
 
-std::string GetAcceptLanguageList(content::BrowserContext* browser_context,
-                                  CefRefPtr<CefBrowserHostImpl> browser) {
-  if (browser) {
-    const CefBrowserSettings& browser_settings = browser->settings();
-    if (browser_settings.accept_language_list.length > 0) {
-      return CefString(&browser_settings.accept_language_list);
-    }
-  }
-
-  // This defaults to the value from CefRequestContextSettings via
-  // browser_prefs::CreatePrefService().
-  auto prefs = Profile::FromBrowserContext(browser_context)->GetPrefs();
-  return prefs->GetString(language::prefs::kAcceptLanguages);
-}
-
-// Match the logic in chrome/browser/net/profile_network_context_service.cc.
-std::string ComputeAcceptLanguageFromPref(const std::string& language_pref) {
-  std::string accept_languages_str =
-      base::FeatureList::IsEnabled(features::kUseNewAcceptLanguageHeader)
-          ? net::HttpUtil::ExpandLanguageList(language_pref)
-          : language_pref;
-  return net::HttpUtil::GenerateAcceptLanguageHeader(accept_languages_str);
-}
-
 class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
  public:
   struct RequestState {
@@ -131,16 +113,17 @@
     CefRefPtr<CefResponseImpl> pending_response_;
     bool request_was_redirected_ = false;
     bool was_custom_handled_ = false;
+    bool accept_language_added_ = false;
     CancelRequestCallback cancel_callback_;
   };
 
   struct PendingRequest {
-    PendingRequest(const RequestId& id,
+    PendingRequest(int32_t request_id,
                    network::ResourceRequest* request,
                    bool request_was_redirected,
                    OnBeforeRequestResultCallback callback,
                    CancelRequestCallback cancel_callback)
-        : id_(id),
+        : id_(request_id),
           request_(request),
           request_was_redirected_(request_was_redirected),
           callback_(std::move(callback)),
@@ -157,7 +140,7 @@
                             std::move(callback_), std::move(cancel_callback_));
     }
 
-    const RequestId id_;
+    const int32_t id_;
     network::ResourceRequest* const request_;
     const bool request_was_redirected_;
     OnBeforeRequestResultCallback callback_;
@@ -166,10 +149,10 @@
 
   // Observer to receive notification of CEF context or associated browser
   // destruction. Only one of the *Destroyed() methods will be called.
-  class DestructionObserver : public CefBrowserHostImpl::Observer,
+  class DestructionObserver : public CefBrowserHostBase::Observer,
                               public CefContext::Observer {
    public:
-    explicit DestructionObserver(CefBrowserHostImpl* browser) {
+    explicit DestructionObserver(CefBrowserHostBase* browser) {
       if (browser) {
         browser_info_ = browser->browser_info();
         browser->AddObserver(this);
@@ -178,17 +161,22 @@
       }
     }
 
+    DestructionObserver(const DestructionObserver&) = delete;
+    DestructionObserver& operator=(const DestructionObserver&) = delete;
+
     virtual ~DestructionObserver() {
       CEF_REQUIRE_UIT();
-      if (!registered_)
+      if (!registered_) {
         return;
+      }
 
       // Verify that the browser or context still exists before attempting to
       // remove the observer.
       if (browser_info_) {
         auto browser = browser_info_->browser();
-        if (browser)
+        if (browser) {
           browser->RemoveObserver(this);
+        }
       } else if (CefContext::Get()) {
         // Network requests may be torn down during shutdown, so we can't check
         // CONTEXT_STATE_VALID() here.
@@ -201,7 +189,7 @@
       wrapper_ = wrapper;
     }
 
-    void OnBrowserDestroyed(CefBrowserHostImpl* browser) override {
+    void OnBrowserDestroyed(CefBrowserHostBase* browser) override {
       CEF_REQUIRE_UIT();
       browser->RemoveObserver(this);
       registered_ = false;
@@ -231,7 +219,6 @@
     bool registered_ = true;
 
     base::WeakPtr<InterceptedRequestHandlerWrapper> wrapper_;
-    DISALLOW_COPY_AND_ASSIGN(DestructionObserver);
   };
 
   // Holds state information for InterceptedRequestHandlerWrapper. State is
@@ -252,20 +239,21 @@
     }
 
     void Initialize(content::BrowserContext* browser_context,
-                    CefRefPtr<CefBrowserHostImpl> browser,
+                    CefRefPtr<CefBrowserHostBase> browser,
                     CefRefPtr<CefFrame> frame,
-                    int render_process_id,
-                    int render_frame_id,
-                    int frame_tree_node_id,
+                    const content::GlobalRenderFrameHostId& global_id,
                     bool is_navigation,
                     bool is_download,
-                    const url::Origin& request_initiator) {
+                    const url::Origin& request_initiator,
+                    const base::RepeatingClosure& unhandled_request_callback) {
       CEF_REQUIRE_UIT();
 
-      browser_context_ = browser_context;
-      resource_context_ = static_cast<CefResourceContext*>(
-          browser_context->GetResourceContext());
-      DCHECK(resource_context_);
+      auto profile = Profile::FromBrowserContext(browser_context);
+      auto cef_browser_context = CefBrowserContext::FromProfile(profile);
+      browser_context_getter_ = cef_browser_context->getter();
+      iothread_state_ = cef_browser_context->iothread_state();
+      CHECK(iothread_state_);
+      cookieable_schemes_ = cef_browser_context->GetCookieableSchemes();
 
       // We register to be notified of CEF context or browser destruction so
       // that we can stop accepting new requests and cancel pending/in-progress
@@ -279,18 +267,17 @@
         frame_ = frame;
       }
 
-      render_process_id_ = render_process_id;
-      render_frame_id_ = render_frame_id;
-      frame_tree_node_id_ = frame_tree_node_id;
+      global_id_ = global_id;
       is_navigation_ = is_navigation;
       is_download_ = is_download;
       request_initiator_ = request_initiator.Serialize();
+      unhandled_request_callback_ = unhandled_request_callback;
 
       // Default values for standard headers.
-      accept_language_ = ComputeAcceptLanguageFromPref(
-          GetAcceptLanguageList(browser_context, browser));
+      accept_language_ = browser_prefs::GetAcceptLanguageList(profile);
       DCHECK(!accept_language_.empty());
-      user_agent_ = CefContentClient::Get()->browser()->GetUserAgent();
+      user_agent_ =
+          CefAppManager::Get()->GetContentClient()->browser()->GetUserAgent();
       DCHECK(!user_agent_.empty());
     }
 
@@ -306,24 +293,30 @@
         std::unique_ptr<DestructionObserver> observer) {}
 
     // Only accessed on the UI thread.
-    content::BrowserContext* browser_context_ = nullptr;
+    CefBrowserContext::Getter browser_context_getter_;
 
     bool initialized_ = false;
 
-    CefRefPtr<CefBrowserHostImpl> browser_;
+    CefRefPtr<CefBrowserHostBase> browser_;
     CefRefPtr<CefFrame> frame_;
-    CefResourceContext* resource_context_ = nullptr;
-    int render_process_id_ = 0;
-    int render_frame_id_ = -1;
-    int frame_tree_node_id_ = -1;
+    scoped_refptr<CefIOThreadState> iothread_state_;
+    CefBrowserContext::CookieableSchemes cookieable_schemes_;
+    content::GlobalRenderFrameHostId global_id_;
     bool is_navigation_ = true;
     bool is_download_ = false;
     CefString request_initiator_;
+    base::RepeatingClosure unhandled_request_callback_;
 
     // Default values for standard headers.
     std::string accept_language_;
     std::string user_agent_;
 
+    // Used to route authentication and certificate callbacks through the
+    // associated StoragePartition instance.
+    mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
+        url_loader_network_observer_;
+    bool did_try_create_url_loader_network_observer_ = false;
+
     // Used to receive destruction notification.
     std::unique_ptr<DestructionObserver> destruction_observer_;
   };
@@ -336,6 +329,9 @@
     explicit InitHelper(InterceptedRequestHandlerWrapper* wrapper)
         : wrapper_(wrapper) {}
 
+    InitHelper(const InitHelper&) = delete;
+    InitHelper& operator=(const InitHelper&) = delete;
+
     void MaybeSetInitialized(std::unique_ptr<InitState> init_state) {
       CEF_POST_TASK(CEF_IOT, base::BindOnce(&InitHelper::SetInitialized, this,
                                             std::move(init_state)));
@@ -351,8 +347,9 @@
       base::AutoLock lock_scope(lock_);
       // May be nullptr if the InterceptedRequestHandlerWrapper has already
       // been deleted.
-      if (!wrapper_)
+      if (!wrapper_) {
         return;
+      }
       wrapper_->SetInitialized(std::move(init_state));
       wrapper_ = nullptr;
     }
@@ -365,6 +362,11 @@
       : init_helper_(base::MakeRefCounted<InitHelper>(this)),
         weak_ptr_factory_(this) {}
 
+  InterceptedRequestHandlerWrapper(const InterceptedRequestHandlerWrapper&) =
+      delete;
+  InterceptedRequestHandlerWrapper& operator=(
+      const InterceptedRequestHandlerWrapper&) = delete;
+
   ~InterceptedRequestHandlerWrapper() override {
     CEF_REQUIRE_IOT();
 
@@ -402,14 +404,82 @@
 
     // Continue any pending requests.
     if (!pending_requests_.empty()) {
-      for (const auto& request : pending_requests_)
+      for (const auto& request : pending_requests_) {
         request->Run(this);
+      }
       pending_requests_.clear();
     }
   }
 
+  static void TryCreateURLLoaderNetworkObserver(
+      std::unique_ptr<PendingRequest> pending_request,
+      CefRefPtr<CefFrame> frame,
+      const CefBrowserContext::Getter& browser_context_getter,
+      base::WeakPtr<InterceptedRequestHandlerWrapper> self) {
+    CEF_REQUIRE_UIT();
+
+    mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
+        url_loader_network_observer;
+
+    if (frame) {
+      // The request will be associated with this frame/browser if it's valid,
+      // otherwise the request will be canceled.
+      content::RenderFrameHostImpl* rfh =
+          static_cast<content::RenderFrameHostImpl*>(
+              static_cast<CefFrameHostImpl*>(frame.get())
+                  ->GetRenderFrameHost());
+      if (rfh) {
+        if (rfh->frame_tree_node() &&
+            rfh->frame_tree_node()->navigation_request()) {
+          // Associate the Observer with the current NavigationRequest. This is
+          // necessary for |is_main_frame_request| to report true (the expected
+          // value) in AllowCertificateError.
+          // TODO(cef): This approach for retrieving the NavigationRequest is
+          // deprecated, see https://crbug.com/1179502#c36.
+          url_loader_network_observer =
+              rfh->GetStoragePartition()
+                  ->CreateURLLoaderNetworkObserverForNavigationRequest(
+                      *(rfh->frame_tree_node()->navigation_request()));
+        } else {
+          // Associate the Observer with the RenderFrameHost.
+          url_loader_network_observer = rfh->CreateURLLoaderNetworkObserver();
+        }
+      }
+    } else {
+      auto cef_browser_context = browser_context_getter.Run();
+      auto browser_context = cef_browser_context
+                                 ? cef_browser_context->AsBrowserContext()
+                                 : nullptr;
+      if (browser_context) {
+        url_loader_network_observer =
+            static_cast<content::StoragePartitionImpl*>(
+                browser_context->GetDefaultStoragePartition())
+                ->CreateAuthCertObserverForServiceWorker();
+      }
+    }
+
+    CEF_POST_TASK(CEF_IOT,
+                  base::BindOnce(&InterceptedRequestHandlerWrapper::
+                                     ContinueCreateURLLoaderNetworkObserver,
+                                 self, std::move(pending_request),
+                                 std::move(url_loader_network_observer)));
+  }
+
+  void ContinueCreateURLLoaderNetworkObserver(
+      std::unique_ptr<PendingRequest> pending_request,
+      mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
+          url_loader_network_observer) {
+    CEF_REQUIRE_IOT();
+
+    DCHECK(!init_state_->did_try_create_url_loader_network_observer_);
+    init_state_->did_try_create_url_loader_network_observer_ = true;
+    init_state_->url_loader_network_observer_ =
+        std::move(url_loader_network_observer);
+    pending_request->Run(this);
+  }
+
   // InterceptedRequestHandler methods:
-  void OnBeforeRequest(const RequestId& id,
+  void OnBeforeRequest(int32_t request_id,
                        network::ResourceRequest* request,
                        bool request_was_redirected,
                        OnBeforeRequestResultCallback callback,
@@ -425,18 +495,50 @@
     if (!init_state_) {
       // Queue requests until we're initialized.
       pending_requests_.push_back(std::make_unique<PendingRequest>(
-          id, request, request_was_redirected, std::move(callback),
+          request_id, request, request_was_redirected, std::move(callback),
           std::move(cancel_callback)));
       return;
     }
 
+    if (request->trusted_params &&
+        !request->trusted_params->url_loader_network_observer &&
+        !init_state_->did_try_create_url_loader_network_observer_) {
+      // Restarted/redirected requests won't already have an observer, so we
+      // need to create one.
+      CEF_POST_TASK(
+          CEF_UIT,
+          base::BindOnce(&InterceptedRequestHandlerWrapper::
+                             TryCreateURLLoaderNetworkObserver,
+                         std::make_unique<PendingRequest>(
+                             request_id, request, request_was_redirected,
+                             std::move(callback), std::move(cancel_callback)),
+                         init_state_->frame_,
+                         init_state_->browser_context_getter_,
+                         weak_ptr_factory_.GetWeakPtr()));
+      return;
+    }
+
     // State may already exist for restarted requests.
-    RequestState* state = GetOrCreateState(id);
+    RequestState* state = GetOrCreateState(request_id);
+
+    if (init_state_->did_try_create_url_loader_network_observer_) {
+      if (init_state_->url_loader_network_observer_) {
+        request->trusted_params->url_loader_network_observer =
+            std::move(init_state_->url_loader_network_observer_);
+      }
+
+      // Reset state so that the observer will be recreated on the next
+      // restart/redirect.
+      init_state_->did_try_create_url_loader_network_observer_ = false;
+    }
 
     // Add standard headers, if currently unspecified.
-    request->headers.SetHeaderIfMissing(
-        net::HttpRequestHeaders::kAcceptLanguage,
-        init_state_->accept_language_);
+    if (!request->headers.HasHeader(net::HttpRequestHeaders::kAcceptLanguage)) {
+      request->headers.SetHeaderIfMissing(
+          net::HttpRequestHeaders::kAcceptLanguage,
+          init_state_->accept_language_);
+      state->accept_language_added_ = true;
+    }
     request->headers.SetHeaderIfMissing(net::HttpRequestHeaders::kUserAgent,
                                         init_state_->user_agent_);
 
@@ -447,18 +549,19 @@
 
     CefRefPtr<CefRequestImpl> requestPtr;
     CefRefPtr<CefResourceRequestHandler> handler =
-        GetHandler(id, request, &intercept_only, requestPtr);
+        GetHandler(request_id, request, &intercept_only, requestPtr);
 
     CefRefPtr<CefSchemeHandlerFactory> scheme_factory =
-        init_state_->resource_context_->GetSchemeHandlerFactory(request->url);
+        init_state_->iothread_state_->GetSchemeHandlerFactory(request->url);
     if (scheme_factory && !requestPtr) {
-      requestPtr = MakeRequest(request, id.hash(), true);
+      requestPtr = MakeRequest(request, request_id, true);
     }
 
     // True if there's a possibility that the client might handle the request.
     const bool maybe_intercept_request = handler || scheme_factory;
-    if (!maybe_intercept_request && requestPtr)
+    if (!maybe_intercept_request && requestPtr) {
       requestPtr = nullptr;
+    }
 
     // May have a handler and/or scheme factory.
     state->Reset(handler, scheme_factory, requestPtr, request_was_redirected,
@@ -479,30 +582,38 @@
       return;
     }
 
-    MaybeLoadCookies(id, state, request, std::move(exec_callback));
+    MaybeLoadCookies(request_id, state, request, std::move(exec_callback));
   }
 
-  void MaybeLoadCookies(const RequestId& id,
+  void MaybeLoadCookies(int32_t request_id,
                         RequestState* state,
                         network::ResourceRequest* request,
                         base::OnceClosure callback) {
     CEF_REQUIRE_IOT();
 
+    if (!cookie_helper::IsCookieableScheme(request->url,
+                                           init_state_->cookieable_schemes_)) {
+      // The scheme does not support cookies.
+      std::move(callback).Run();
+      return;
+    }
+
     // We need to load/save cookies ourselves for custom-handled requests, or
     // if we're using a cookie filter.
     auto allow_cookie_callback =
         state->cookie_filter_
             ? base::BindRepeating(
                   &InterceptedRequestHandlerWrapper::AllowCookieLoad,
-                  weak_ptr_factory_.GetWeakPtr(), id)
+                  weak_ptr_factory_.GetWeakPtr(), request_id)
             : base::BindRepeating(
                   &InterceptedRequestHandlerWrapper::AllowCookieAlways);
     auto done_cookie_callback = base::BindOnce(
         &InterceptedRequestHandlerWrapper::ContinueWithLoadedCookies,
-        weak_ptr_factory_.GetWeakPtr(), id, request, std::move(callback));
-    net_service::LoadCookies(init_state_->browser_context_, *request,
-                             allow_cookie_callback,
-                             std::move(done_cookie_callback));
+        weak_ptr_factory_.GetWeakPtr(), request_id, request,
+        std::move(callback));
+    cookie_helper::LoadCookies(init_state_->browser_context_getter_, *request,
+                               allow_cookie_callback,
+                               std::move(done_cookie_callback));
   }
 
   static void AllowCookieAlways(const net::CanonicalCookie& cookie,
@@ -510,12 +621,12 @@
     *allow = true;
   }
 
-  void AllowCookieLoad(const RequestId& id,
+  void AllowCookieLoad(int32_t request_id,
                        const net::CanonicalCookie& cookie,
                        bool* allow) {
     CEF_REQUIRE_IOT();
 
-    RequestState* state = GetState(id);
+    RequestState* state = GetState(request_id);
     if (!state) {
       // The request may have been canceled while the async callback was
       // pending.
@@ -532,14 +643,14 @@
     }
   }
 
-  void ContinueWithLoadedCookies(const RequestId& id,
+  void ContinueWithLoadedCookies(int32_t request_id,
                                  network::ResourceRequest* request,
                                  base::OnceClosure callback,
                                  int total_count,
                                  net::CookieList allowed_cookies) {
     CEF_REQUIRE_IOT();
 
-    RequestState* state = GetState(id);
+    RequestState* state = GetState(request_id);
     if (!state) {
       // The request may have been canceled while the async callback was
       // pending.
@@ -568,12 +679,12 @@
   }
 
   void ShouldInterceptRequest(
-      const RequestId& id,
+      int32_t request_id,
       network::ResourceRequest* request,
       ShouldInterceptRequestResultCallback callback) override {
     CEF_REQUIRE_IOT();
 
-    RequestState* state = GetState(id);
+    RequestState* state = GetState(request_id);
     if (!state) {
       // The request may have been canceled during destruction.
       return;
@@ -592,30 +703,36 @@
       CefRefPtr<RequestCallbackWrapper> callbackPtr =
           new RequestCallbackWrapper(base::BindOnce(
               &InterceptedRequestHandlerWrapper::ContinueShouldInterceptRequest,
-              weak_ptr_factory_.GetWeakPtr(), id, base::Unretained(request),
-              std::move(callback)));
+              weak_ptr_factory_.GetWeakPtr(), request_id,
+              base::Unretained(request), std::move(callback)));
 
       cef_return_value_t retval = state->handler_->OnBeforeResourceLoad(
           init_state_->browser_, init_state_->frame_,
           state->pending_request_.get(), callbackPtr.get());
       if (retval != RV_CONTINUE_ASYNC) {
-        // Continue or cancel the request immediately.
-        callbackPtr->Continue(retval == RV_CONTINUE);
+        if (retval == RV_CONTINUE) {
+          // Continue the request immediately.
+          callbackPtr->Continue();
+        } else {
+          // Cancel the request immediately.
+          callbackPtr->Cancel();
+        }
       }
     } else {
       // The scheme factory may choose to handle it.
-      ContinueShouldInterceptRequest(id, request, std::move(callback), true);
+      ContinueShouldInterceptRequest(request_id, request, std::move(callback),
+                                     true);
     }
   }
 
   void ContinueShouldInterceptRequest(
-      const RequestId& id,
+      int32_t request_id,
       network::ResourceRequest* request,
       ShouldInterceptRequestResultCallback callback,
       bool allow) {
     CEF_REQUIRE_IOT();
 
-    RequestState* state = GetState(id);
+    RequestState* state = GetState(request_id);
     if (!state) {
       // The request may have been canceled while the async callback was
       // pending.
@@ -674,10 +791,10 @@
 
     std::unique_ptr<ResourceResponse> resource_response;
     if (resource_handler) {
-      resource_response = CreateResourceResponse(id, resource_handler);
+      resource_response = CreateResourceResponse(request_id, resource_handler);
       DCHECK(resource_response);
       state->was_custom_handled_ = true;
-    } else {
+    } else if (state->accept_language_added_) {
       // The request will be handled by the NetworkService. Remove the
       // "Accept-Language" header here so that it can be re-added in
       // URLRequestHttpJob::AddExtraHeaders with correct ordering applied.
@@ -688,40 +805,43 @@
     std::move(callback).Run(std::move(resource_response));
   }
 
-  void ProcessResponseHeaders(const RequestId& id,
+  void ProcessResponseHeaders(int32_t request_id,
                               const network::ResourceRequest& request,
                               const GURL& redirect_url,
                               net::HttpResponseHeaders* headers) override {
     CEF_REQUIRE_IOT();
 
-    RequestState* state = GetState(id);
+    RequestState* state = GetState(request_id);
     if (!state) {
       // The request may have been canceled during destruction.
       return;
     }
 
-    if (!state->handler_)
+    if (!state->handler_) {
       return;
+    }
 
-    if (!state->pending_response_)
+    if (!state->pending_response_) {
       state->pending_response_ = new CefResponseImpl();
-    else
+    } else {
       state->pending_response_->SetReadOnly(false);
+    }
 
-    if (headers)
+    if (headers) {
       state->pending_response_->SetResponseHeaders(*headers);
+    }
 
     state->pending_response_->SetReadOnly(true);
   }
 
-  void OnRequestResponse(const RequestId& id,
+  void OnRequestResponse(int32_t request_id,
                          network::ResourceRequest* request,
                          net::HttpResponseHeaders* headers,
-                         base::Optional<net::RedirectInfo> redirect_info,
+                         absl::optional<net::RedirectInfo> redirect_info,
                          OnRequestResponseResultCallback callback) override {
     CEF_REQUIRE_IOT();
 
-    RequestState* state = GetState(id);
+    RequestState* state = GetState(request_id);
     if (!state) {
       // The request may have been canceled during destruction.
       return;
@@ -735,7 +855,7 @@
     if (!state->handler_) {
       // Cookies may come from a scheme handler.
       MaybeSaveCookies(
-          id, state, request, headers,
+          request_id, state, request, headers,
           base::BindOnce(
               std::move(callback), ResponseMode::CONTINUE, nullptr,
               redirect_info.has_value() ? redirect_info->new_url : GURL()));
@@ -746,14 +866,14 @@
     DCHECK(state->pending_response_);
 
     if (redirect_info.has_value()) {
-      HandleRedirect(id, state, request, headers, *redirect_info,
+      HandleRedirect(request_id, state, request, headers, *redirect_info,
                      std::move(callback));
     } else {
-      HandleResponse(id, state, request, headers, std::move(callback));
+      HandleResponse(request_id, state, request, headers, std::move(callback));
     }
   }
 
-  void HandleRedirect(const RequestId& id,
+  void HandleRedirect(int32_t request_id,
                       RequestState* state,
                       network::ResourceRequest* request,
                       net::HttpResponseHeaders* headers,
@@ -786,10 +906,11 @@
     auto exec_callback = base::BindOnce(
         std::move(callback), ResponseMode::CONTINUE, nullptr, new_url);
 
-    MaybeSaveCookies(id, state, request, headers, std::move(exec_callback));
+    MaybeSaveCookies(request_id, state, request, headers,
+                     std::move(exec_callback));
   }
 
-  void HandleResponse(const RequestId& id,
+  void HandleResponse(int32_t request_id,
                       RequestState* state,
                       network::ResourceRequest* request,
                       net::HttpResponseHeaders* headers,
@@ -835,10 +956,11 @@
       return;
     }
 
-    MaybeSaveCookies(id, state, request, headers, std::move(exec_callback));
+    MaybeSaveCookies(request_id, state, request, headers,
+                     std::move(exec_callback));
   }
 
-  void MaybeSaveCookies(const RequestId& id,
+  void MaybeSaveCookies(int32_t request_id,
                         RequestState* state,
                         network::ResourceRequest* request,
                         net::HttpResponseHeaders* headers,
@@ -851,29 +973,36 @@
       return;
     }
 
+    if (!cookie_helper::IsCookieableScheme(request->url,
+                                           init_state_->cookieable_schemes_)) {
+      // The scheme does not support cookies.
+      std::move(callback).Run();
+      return;
+    }
+
     // We need to load/save cookies ourselves for custom-handled requests, or
     // if we're using a cookie filter.
     auto allow_cookie_callback =
         state->cookie_filter_
             ? base::BindRepeating(
                   &InterceptedRequestHandlerWrapper::AllowCookieSave,
-                  weak_ptr_factory_.GetWeakPtr(), id)
+                  weak_ptr_factory_.GetWeakPtr(), request_id)
             : base::BindRepeating(
                   &InterceptedRequestHandlerWrapper::AllowCookieAlways);
     auto done_cookie_callback = base::BindOnce(
         &InterceptedRequestHandlerWrapper::ContinueWithSavedCookies,
-        weak_ptr_factory_.GetWeakPtr(), id, std::move(callback));
-    net_service::SaveCookies(init_state_->browser_context_, *request, headers,
-                             allow_cookie_callback,
-                             std::move(done_cookie_callback));
+        weak_ptr_factory_.GetWeakPtr(), request_id, std::move(callback));
+    cookie_helper::SaveCookies(init_state_->browser_context_getter_, *request,
+                               headers, allow_cookie_callback,
+                               std::move(done_cookie_callback));
   }
 
-  void AllowCookieSave(const RequestId& id,
+  void AllowCookieSave(int32_t request_id,
                        const net::CanonicalCookie& cookie,
                        bool* allow) {
     CEF_REQUIRE_IOT();
 
-    RequestState* state = GetState(id);
+    RequestState* state = GetState(request_id);
     if (!state) {
       // The request may have been canceled while the async callback was
       // pending.
@@ -891,7 +1020,7 @@
     }
   }
 
-  void ContinueWithSavedCookies(const RequestId& id,
+  void ContinueWithSavedCookies(int32_t request_id,
                                 base::OnceClosure callback,
                                 int total_count,
                                 net::CookieList allowed_cookies) {
@@ -900,12 +1029,12 @@
   }
 
   mojo::ScopedDataPipeConsumerHandle OnFilterResponseBody(
-      const RequestId& id,
+      int32_t request_id,
       const network::ResourceRequest& request,
       mojo::ScopedDataPipeConsumerHandle body) override {
     CEF_REQUIRE_IOT();
 
-    RequestState* state = GetState(id);
+    RequestState* state = GetState(request_id);
     if (!state) {
       // The request may have been canceled during destruction.
       return body;
@@ -919,17 +1048,17 @@
         return CreateResponseFilterHandler(
             filter, std::move(body),
             base::BindOnce(&InterceptedRequestHandlerWrapper::OnFilterError,
-                           weak_ptr_factory_.GetWeakPtr(), id));
+                           weak_ptr_factory_.GetWeakPtr(), request_id));
       }
     }
 
     return body;
   }
 
-  void OnFilterError(const RequestId& id) {
+  void OnFilterError(int32_t request_id) {
     CEF_REQUIRE_IOT();
 
-    RequestState* state = GetState(id);
+    RequestState* state = GetState(request_id);
     if (!state) {
       // The request may have been canceled while the async callback was
       // pending.
@@ -942,12 +1071,12 @@
   }
 
   void OnRequestComplete(
-      const RequestId& id,
+      int32_t request_id,
       const network::ResourceRequest& request,
       const network::URLLoaderCompletionStatus& status) override {
     CEF_REQUIRE_IOT();
 
-    RequestState* state = GetState(id);
+    RequestState* state = GetState(request_id);
     if (!state) {
       // The request may have been aborted during initialization or canceled
       // during destruction. This method will always be called before a request
@@ -956,7 +1085,7 @@
       if (!pending_requests_.empty()) {
         PendingRequests::iterator it = pending_requests_.begin();
         for (; it != pending_requests_.end(); ++it) {
-          if ((*it)->id_ == id) {
+          if ((*it)->id_ == request_id) {
             pending_requests_.erase(it);
             break;
           }
@@ -981,25 +1110,27 @@
 
       CallHandlerOnComplete(state, status);
 
-      if (status.error_code != 0 && is_external) {
+      if (status.error_code != 0 && status.error_code != ERR_ABORTED &&
+          is_external) {
         bool allow_os_execution = false;
         state->handler_->OnProtocolExecution(
             init_state_->browser_, init_state_->frame_,
             state->pending_request_.get(), allow_os_execution);
-        if (allow_os_execution) {
-          CefBrowserPlatformDelegate::HandleExternalProtocol(request.url);
+        if (allow_os_execution && init_state_->unhandled_request_callback_) {
+          init_state_->unhandled_request_callback_.Run();
         }
       }
     }
 
-    RemoveState(id);
+    RemoveState(request_id);
   }
 
  private:
   void CallHandlerOnComplete(RequestState* state,
                              const network::URLLoaderCompletionStatus& status) {
-    if (!state->handler_ || !state->pending_request_)
+    if (!state->handler_ || !state->pending_request_) {
       return;
+    }
 
     // The request object may be currently flagged as writable in cases where we
     // abort a request that is waiting on a pending callack.
@@ -1026,14 +1157,12 @@
 
   // Returns the handler, if any, that should be used for this request.
   CefRefPtr<CefResourceRequestHandler> GetHandler(
-      const RequestId& id,
+      int32_t request_id,
       network::ResourceRequest* request,
       bool* intercept_only,
       CefRefPtr<CefRequestImpl>& requestPtr) const {
     CefRefPtr<CefResourceRequestHandler> handler;
 
-    const int64 request_id = id.hash();
-
     if (init_state_->browser_) {
       // Maybe the browser's client wants to handle it?
       CefRefPtr<CefClient> client =
@@ -1055,12 +1184,12 @@
     if (!handler) {
       // Maybe the request context wants to handle it?
       CefRefPtr<CefRequestContextHandler> context_handler =
-          init_state_->resource_context_->GetHandler(
-              init_state_->render_process_id_, request->render_frame_id,
-              init_state_->frame_tree_node_id_, false);
+          init_state_->iothread_state_->GetHandler(
+              init_state_->global_id_, /*require_frame_match=*/false);
       if (context_handler) {
-        if (!requestPtr)
+        if (!requestPtr) {
           requestPtr = MakeRequest(request, request_id, true);
+        }
 
         handler = context_handler->GetResourceRequestHandler(
             init_state_->browser_, init_state_->frame_, requestPtr.get(),
@@ -1072,27 +1201,29 @@
     return handler;
   }
 
-  RequestState* GetOrCreateState(const RequestId& id) {
-    RequestState* state = GetState(id);
+  RequestState* GetOrCreateState(int32_t request_id) {
+    RequestState* state = GetState(request_id);
     if (!state) {
       state = new RequestState();
-      request_map_.insert(std::make_pair(id, base::WrapUnique(state)));
+      request_map_.insert(std::make_pair(request_id, base::WrapUnique(state)));
     }
     return state;
   }
 
-  RequestState* GetState(const RequestId& id) const {
-    RequestMap::const_iterator it = request_map_.find(id);
-    if (it != request_map_.end())
+  RequestState* GetState(int32_t request_id) const {
+    RequestMap::const_iterator it = request_map_.find(request_id);
+    if (it != request_map_.end()) {
       return it->second.get();
+    }
     return nullptr;
   }
 
-  void RemoveState(const RequestId& id) {
-    RequestMap::iterator it = request_map_.find(id);
+  void RemoveState(int32_t request_id) {
+    RequestMap::iterator it = request_map_.find(request_id);
     DCHECK(it != request_map_.end());
-    if (it != request_map_.end())
+    if (it != request_map_.end()) {
       request_map_.erase(it);
+    }
   }
 
   // Stop accepting new requests and cancel pending/in-flight requests when the
@@ -1146,14 +1277,15 @@
 
   static CefRefPtr<CefRequestImpl> MakeRequest(
       const network::ResourceRequest* request,
-      int64 request_id,
+      int64_t request_id,
       bool read_only) {
     CefRefPtr<CefRequestImpl> requestPtr = new CefRequestImpl();
     requestPtr->Set(request, request_id);
-    if (read_only)
+    if (read_only) {
       requestPtr->SetReadOnly(true);
-    else
+    } else {
       requestPtr->SetTrackChanges(true);
+    }
     return requestPtr;
   }
 
@@ -1167,96 +1299,15 @@
 
   bool shutting_down_ = false;
 
-  using RequestMap = std::map<RequestId, std::unique_ptr<RequestState>>;
+  using RequestMap = std::map<int32_t, std::unique_ptr<RequestState>>;
   RequestMap request_map_;
 
   using PendingRequests = std::vector<std::unique_ptr<PendingRequest>>;
   PendingRequests pending_requests_;
 
   base::WeakPtrFactory<InterceptedRequestHandlerWrapper> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(InterceptedRequestHandlerWrapper);
 };
 
-void InitOnUIThread(
-    scoped_refptr<InterceptedRequestHandlerWrapper::InitHelper> init_helper,
-    content::WebContents::Getter web_contents_getter,
-    int frame_tree_node_id,
-    const network::ResourceRequest& request) {
-  CEF_REQUIRE_UIT();
-
-  // May return nullptr if the WebContents was destroyed while this callback was
-  // in-flight.
-  content::WebContents* web_contents = web_contents_getter.Run();
-  if (!web_contents) {
-    return;
-  }
-
-  content::BrowserContext* browser_context = web_contents->GetBrowserContext();
-  DCHECK(browser_context);
-
-  const int render_process_id =
-      web_contents->GetRenderViewHost()->GetProcess()->GetID();
-
-  content::RenderFrameHost* frame = nullptr;
-
-  if (request.render_frame_id >= 0) {
-    // TODO(network): Are these main frame checks equivalent?
-    if (request.is_main_frame ||
-        static_cast<blink::mojom::ResourceType>(request.resource_type) ==
-            blink::mojom::ResourceType::kMainFrame) {
-      frame = web_contents->GetMainFrame();
-      DCHECK(frame);
-    } else {
-      // May return null for newly created iframes.
-      frame = content::RenderFrameHost::FromID(render_process_id,
-                                               request.render_frame_id);
-      if (!frame && frame_tree_node_id >= 0) {
-        // May return null for frames in inner WebContents.
-        frame = web_contents->FindFrameByFrameTreeNodeId(frame_tree_node_id,
-                                                         render_process_id);
-      }
-      if (!frame) {
-        // Use the main frame for the CefBrowserHost.
-        frame = web_contents->GetMainFrame();
-        DCHECK(frame);
-      }
-    }
-  }
-
-  CefRefPtr<CefBrowserHostImpl> browserPtr;
-  CefRefPtr<CefFrame> framePtr;
-
-  // |frame| may be null for service worker requests.
-  if (frame) {
-    // May return nullptr for requests originating from guest views.
-    browserPtr = CefBrowserHostImpl::GetBrowserForHost(frame);
-    if (browserPtr) {
-      framePtr = browserPtr->GetFrameForHost(frame);
-      if (frame_tree_node_id < 0)
-        frame_tree_node_id = frame->GetFrameTreeNodeId();
-      DCHECK(framePtr);
-    }
-  }
-
-  const bool is_navigation = ui::PageTransitionIsNewNavigation(
-      static_cast<ui::PageTransition>(request.transition_type));
-  // TODO(navigation): Can we determine the |is_download| value?
-  const bool is_download = false;
-  url::Origin request_initiator;
-  if (request.request_initiator.has_value())
-    request_initiator = *request.request_initiator;
-
-  auto init_state =
-      std::make_unique<InterceptedRequestHandlerWrapper::InitState>();
-  init_state->Initialize(browser_context, browserPtr, framePtr,
-                         render_process_id, request.render_frame_id,
-                         frame_tree_node_id, is_navigation, is_download,
-                         request_initiator);
-
-  init_helper->MaybeSetInitialized(std::move(init_state));
-}
-
 }  // namespace
 
 std::unique_ptr<InterceptedRequestHandler> CreateInterceptedRequestHandler(
@@ -1267,29 +1318,32 @@
     bool is_download,
     const url::Origin& request_initiator) {
   CEF_REQUIRE_UIT();
-  CefRefPtr<CefBrowserHostImpl> browserPtr;
+  CHECK(browser_context);
+
+  CefRefPtr<CefBrowserHostBase> browserPtr;
   CefRefPtr<CefFrame> framePtr;
-  int render_frame_id = -1;
-  int frame_tree_node_id = -1;
 
-  // |frame| may be null for service worker requests.
+  // Default to handlers for the same process in case |frame| doesn't have an
+  // associated CefBrowserHost.
+  content::GlobalRenderFrameHostId global_id(render_process_id,
+                                             MSG_ROUTING_NONE);
+
+  // |frame| may be nullptr for service worker requests.
   if (frame) {
-    render_frame_id = frame->GetRoutingID();
-    frame_tree_node_id = frame->GetFrameTreeNodeId();
-
     // May return nullptr for requests originating from guest views.
-    browserPtr = CefBrowserHostImpl::GetBrowserForHost(frame);
+    browserPtr = CefBrowserHostBase::GetBrowserForHost(frame);
     if (browserPtr) {
       framePtr = browserPtr->GetFrameForHost(frame);
-      DCHECK(framePtr);
+      CHECK(framePtr);
+      global_id = frame->GetGlobalId();
     }
   }
 
   auto init_state =
       std::make_unique<InterceptedRequestHandlerWrapper::InitState>();
-  init_state->Initialize(browser_context, browserPtr, framePtr,
-                         render_process_id, render_frame_id, frame_tree_node_id,
-                         is_navigation, is_download, request_initiator);
+  init_state->Initialize(browser_context, browserPtr, framePtr, global_id,
+                         is_navigation, is_download, request_initiator,
+                         base::RepeatingClosure());
 
   auto wrapper = std::make_unique<InterceptedRequestHandlerWrapper>();
   wrapper->init_helper()->MaybeSetInitialized(std::move(init_state));
@@ -1300,11 +1354,77 @@
 std::unique_ptr<InterceptedRequestHandler> CreateInterceptedRequestHandler(
     content::WebContents::Getter web_contents_getter,
     int frame_tree_node_id,
-    const network::ResourceRequest& request) {
+    const network::ResourceRequest& request,
+    const base::RepeatingClosure& unhandled_request_callback) {
+  CEF_REQUIRE_UIT();
+
+  content::WebContents* web_contents = web_contents_getter.Run();
+  CHECK(web_contents);
+
+  content::BrowserContext* browser_context = web_contents->GetBrowserContext();
+  CHECK(browser_context);
+
+  content::RenderFrameHost* frame = nullptr;
+
+  if (request.is_outermost_main_frame ||
+      static_cast<blink::mojom::ResourceType>(request.resource_type) ==
+          blink::mojom::ResourceType::kMainFrame) {
+    frame = web_contents->GetPrimaryMainFrame();
+    CHECK(frame);
+  } else {
+    // May return nullptr for frames in inner WebContents.
+    auto node = content::FrameTreeNode::GloballyFindByID(frame_tree_node_id);
+    if (node) {
+      frame = node->current_frame_host();
+
+      // RFHs can move between FrameTreeNodes. Make sure this one hasn't. See
+      // documentation on RenderFrameHost::GetFrameTreeNodeId() for background.
+      if (content::WebContents::FromRenderFrameHost(frame) != web_contents) {
+        frame = nullptr;
+      }
+    }
+
+    if (!frame) {
+      // Use the main frame for the CefBrowserHost.
+      frame = web_contents->GetPrimaryMainFrame();
+      CHECK(frame);
+    }
+  }
+
+  CefRefPtr<CefBrowserHostBase> browserPtr;
+  CefRefPtr<CefFrame> framePtr;
+
+  // Default to handlers for the same process in case |frame| doesn't have an
+  // associated CefBrowserHost.
+  content::GlobalRenderFrameHostId global_id(frame->GetProcess()->GetID(),
+                                             MSG_ROUTING_NONE);
+
+  // May return nullptr for requests originating from guest views.
+  browserPtr = CefBrowserHostBase::GetBrowserForHost(frame);
+  if (browserPtr) {
+    framePtr = browserPtr->GetFrameForHost(frame);
+    DCHECK(framePtr);
+    global_id = frame->GetGlobalId();
+  }
+
+  const bool is_navigation = ui::PageTransitionIsNewNavigation(
+      static_cast<ui::PageTransition>(request.transition_type));
+  // TODO(navigation): Can we determine the |is_download| value?
+  const bool is_download = false;
+  url::Origin request_initiator;
+  if (request.request_initiator.has_value()) {
+    request_initiator = *request.request_initiator;
+  }
+
+  auto init_state =
+      std::make_unique<InterceptedRequestHandlerWrapper::InitState>();
+  init_state->Initialize(browser_context, browserPtr, framePtr, global_id,
+                         is_navigation, is_download, request_initiator,
+                         unhandled_request_callback);
+
   auto wrapper = std::make_unique<InterceptedRequestHandlerWrapper>();
-  CEF_POST_TASK(CEF_UIT, base::BindOnce(InitOnUIThread, wrapper->init_helper(),
-                                        web_contents_getter, frame_tree_node_id,
-                                        request));
+  wrapper->init_helper()->MaybeSetInitialized(std::move(init_state));
+
   return wrapper;
 }
 
diff --git a/src/libcef/browser/net_service/resource_request_handler_wrapper.h b/src/libcef/browser/net_service/resource_request_handler_wrapper.h
index 4ed933a..6052a76 100644
--- a/src/libcef/browser/net_service/resource_request_handler_wrapper.h
+++ b/src/libcef/browser/net_service/resource_request_handler_wrapper.h
@@ -5,6 +5,7 @@
 #ifndef CEF_LIBCEF_BROWSER_NET_SERVICE_RESOURCE_REQUEST_HANDLER_WRAPPER_H_
 #define CEF_LIBCEF_BROWSER_NET_SERVICE_RESOURCE_REQUEST_HANDLER_WRAPPER_H_
 
+#include "base/functional/callback_forward.h"
 #include "content/public/browser/web_contents.h"
 
 namespace content {
@@ -37,11 +38,12 @@
 
 // Create an InterceptedRequestHandler that will delegate to a
 // CefResourceRequestHandler. The resulting object should be passed to
-// ProxyURLLoaderFactory::CreateProxy. Called on the IO thread only.
+// ProxyURLLoaderFactory::CreateProxy. Called on the UI thread only.
 std::unique_ptr<InterceptedRequestHandler> CreateInterceptedRequestHandler(
     content::WebContents::Getter web_contents_getter,
     int frame_tree_node_id,
-    const network::ResourceRequest& request);
+    const network::ResourceRequest& request,
+    const base::RepeatingClosure& unhandled_request_callback);
 
 }  // namespace net_service
 
diff --git a/src/libcef/browser/net_service/response_filter_wrapper.cc b/src/libcef/browser/net_service/response_filter_wrapper.cc
index 7702868..bc185a1 100644
--- a/src/libcef/browser/net_service/response_filter_wrapper.cc
+++ b/src/libcef/browser/net_service/response_filter_wrapper.cc
@@ -6,6 +6,7 @@
 
 #include <queue>
 
+#include "base/logging.h"
 #include "mojo/public/cpp/system/simple_watcher.h"
 #include "mojo/public/cpp/system/string_data_source.h"
 
@@ -23,6 +24,9 @@
                         mojo::ScopedDataPipeConsumerHandle source_handle,
                         base::OnceClosure error_callback);
 
+  ResponseFilterWrapper(const ResponseFilterWrapper&) = delete;
+  ResponseFilterWrapper& operator=(const ResponseFilterWrapper&) = delete;
+
   // Creates and returns the output handle, or |source_handle| on failure.
   bool CreateOutputHandle(mojo::ScopedDataPipeConsumerHandle* output_handle);
 
@@ -46,8 +50,6 @@
   bool write_pending_ = false;
   std::queue<std::unique_ptr<std::string>> pending_data_;
   cef_response_filter_status_t last_status_ = RESPONSE_FILTER_NEED_MORE_DATA;
-
-  DISALLOW_COPY_AND_ASSIGN(ResponseFilterWrapper);
 };
 
 ResponseFilterWrapper::ResponseFilterWrapper(
@@ -67,7 +69,7 @@
   }
 
   mojo::ScopedDataPipeProducerHandle forwarding_handle;
-  if (CreateDataPipe(nullptr, &forwarding_handle, output_handle) !=
+  if (CreateDataPipe(nullptr, forwarding_handle, *output_handle) !=
       MOJO_RESULT_OK) {
     *output_handle = std::move(source_handle_);
     return false;
@@ -140,8 +142,9 @@
     last_status_ = filter_->Filter(
         const_cast<char*>(data_in_ptr), data_in_size, data_in_read,
         const_cast<char*>(data_out_ptr), data_out_size, data_out_written);
-    if (last_status_ == RESPONSE_FILTER_ERROR)
+    if (last_status_ == RESPONSE_FILTER_ERROR) {
       break;
+    }
 
     // Validate the out values.
     if (data_in_read > data_in_size) {
@@ -266,13 +269,15 @@
     return;
   }
 
-  if (!read_pending_ && !write_pending_)
+  if (!read_pending_ && !write_pending_) {
     Cleanup(true);
+  }
 }
 
 void ResponseFilterWrapper::Cleanup(bool success) {
-  if (!success && error_callback_)
+  if (!success && error_callback_) {
     std::move(error_callback_).Run();
+  }
   delete this;
 }
 
@@ -288,8 +293,9 @@
   auto filter_wrapper = new ResponseFilterWrapper(
       filter, std::move(source_handle), std::move(error_callback));
   mojo::ScopedDataPipeConsumerHandle output_handle;
-  if (!filter_wrapper->CreateOutputHandle(&output_handle))
+  if (!filter_wrapper->CreateOutputHandle(&output_handle)) {
     delete filter_wrapper;
+  }
   return output_handle;
 }
 
diff --git a/src/libcef/browser/net_service/response_filter_wrapper.h b/src/libcef/browser/net_service/response_filter_wrapper.h
index 241007f..a85d095 100644
--- a/src/libcef/browser/net_service/response_filter_wrapper.h
+++ b/src/libcef/browser/net_service/response_filter_wrapper.h
@@ -7,6 +7,7 @@
 
 #include "include/cef_response_filter.h"
 
+#include "base/functional/callback_forward.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 
 namespace net_service {
diff --git a/src/libcef/browser/net_service/stream_reader_url_loader.cc b/src/libcef/browser/net_service/stream_reader_url_loader.cc
index 362956a..28daf95 100644
--- a/src/libcef/browser/net_service/stream_reader_url_loader.cc
+++ b/src/libcef/browser/net_service/stream_reader_url_loader.cc
@@ -8,14 +8,14 @@
 #include "libcef/browser/thread_util.h"
 #include "libcef/common/net_service/net_service_util.h"
 
-#include "base/bind.h"
-#include "base/callback.h"
+#include "base/functional/bind.h"
+#include "base/functional/callback.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/task/post_task.h"
+#include "base/task/single_thread_task_runner.h"
+#include "base/task/thread_pool.h"
 #include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/base/io_buffer.h"
 #include "net/http/http_status_code.h"
@@ -34,15 +34,18 @@
 class OpenInputStreamWrapper
     : public base::RefCountedThreadSafe<OpenInputStreamWrapper> {
  public:
-  static base::OnceClosure Open(
+  OpenInputStreamWrapper(const OpenInputStreamWrapper&) = delete;
+  OpenInputStreamWrapper& operator=(const OpenInputStreamWrapper&) = delete;
+
+  [[nodiscard]] static base::OnceClosure Open(
       std::unique_ptr<StreamReaderURLLoader::Delegate> delegate,
       scoped_refptr<base::SequencedTaskRunner> work_thread_task_runner,
-      const RequestId& request_id,
+      int32_t request_id,
       const network::ResourceRequest& request,
-      OnInputStreamOpenedCallback callback) WARN_UNUSED_RESULT {
+      OnInputStreamOpenedCallback callback) {
     scoped_refptr<OpenInputStreamWrapper> wrapper = new OpenInputStreamWrapper(
         std::move(delegate), work_thread_task_runner,
-        base::ThreadTaskRunnerHandle::Get(), std::move(callback));
+        base::SingleThreadTaskRunner::GetCurrentDefault(), std::move(callback));
     wrapper->Start(request_id, request);
 
     return wrapper->GetCancelCallback();
@@ -60,10 +63,9 @@
         work_thread_task_runner_(work_thread_task_runner),
         job_thread_task_runner_(job_thread_task_runner),
         callback_(std::move(callback)) {}
-  virtual ~OpenInputStreamWrapper() {}
+  virtual ~OpenInputStreamWrapper() = default;
 
-  void Start(const RequestId& request_id,
-             const network::ResourceRequest& request) {
+  void Start(int32_t request_id, const network::ResourceRequest& request) {
     work_thread_task_runner_->PostTask(
         FROM_HERE,
         base::BindOnce(&OpenInputStreamWrapper::OpenOnWorkThread,
@@ -77,8 +79,9 @@
 
   void CancelOnJobThread() {
     DCHECK(job_thread_task_runner_->RunsTasksInCurrentSequence());
-    if (callback_.is_null())
+    if (callback_.is_null()) {
       return;
+    }
 
     callback_.Reset();
 
@@ -89,17 +92,19 @@
 
   void CancelOnWorkThread() {
     DCHECK(work_thread_task_runner_->RunsTasksInCurrentSequence());
-    if (is_canceled_)
+    if (is_canceled_) {
       return;
+    }
     is_canceled_ = true;
     OnCallback(nullptr);
   }
 
-  void OpenOnWorkThread(const RequestId& request_id,
+  void OpenOnWorkThread(int32_t request_id,
                         const network::ResourceRequest& request) {
     DCHECK(work_thread_task_runner_->RunsTasksInCurrentSequence());
-    if (is_canceled_)
+    if (is_canceled_) {
       return;
+    }
 
     // |delegate_| will remain valid until OnCallback() is executed on
     // |job_thread_task_runner_|.
@@ -142,8 +147,6 @@
 
   // Only accessed on |work_thread_task_runner_|.
   bool is_canceled_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(OpenInputStreamWrapper);
 };
 
 }  // namespace
@@ -161,6 +164,9 @@
       std::unique_ptr<InputStream> stream,
       scoped_refptr<base::SequencedTaskRunner> work_thread_task_runner);
 
+  InputStreamReader(const InputStreamReader&) = delete;
+  InputStreamReader& operator=(const InputStreamReader&) = delete;
+
   // Skip |skip_bytes| number of bytes from |stream_|. |callback| will be
   // executed asynchronously on the IO thread. A negative value passed to
   // |callback| will indicate an error code, a positive value will indicate the
@@ -229,8 +235,6 @@
   int pending_callback_id_ = -1;
 
   int next_callback_id_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(InputStreamReader);
 };
 
 InputStreamReader::InputStreamReader(
@@ -238,7 +242,8 @@
     scoped_refptr<base::SequencedTaskRunner> work_thread_task_runner)
     : stream_(std::move(stream)),
       work_thread_task_runner_(work_thread_task_runner),
-      job_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
+      job_thread_task_runner_(
+          base::SingleThreadTaskRunner::GetCurrentDefault()) {
   CEF_REQUIRE_IOT();
   DCHECK(stream_);
   DCHECK(work_thread_task_runner_);
@@ -311,8 +316,9 @@
                      pending_callback_id_));
 
   // Check if the callback will execute asynchronously.
-  if (result && bytes_read == 0)
+  if (result && bytes_read == 0) {
     return;
+  }
 
   RunReadCallback(result || bytes_read <= 0 ? bytes_read : net::ERR_FAILED);
 }
@@ -334,8 +340,9 @@
                        pending_callback_id_));
 
     // Check if the callback will execute asynchronously.
-    if (result && skipped == 0)
+    if (result && skipped == 0) {
       return;
+    }
 
     if (!result || skipped <= 0) {
       RunSkipCallback(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
@@ -382,13 +389,15 @@
   DCHECK(work_thread_task_runner_->RunsTasksInCurrentSequence());
 
   // Check for out of order callbacks.
-  if (pending_callback_id_ != callback_id)
+  if (pending_callback_id_ != callback_id) {
     return;
+  }
 
   DCHECK_LE(bytes_skipped, bytes_to_skip_);
 
-  if (bytes_to_skip_ > 0 && bytes_skipped > 0)
+  if (bytes_to_skip_ > 0 && bytes_skipped > 0) {
     bytes_to_skip_ -= bytes_skipped;
+  }
 
   if (bytes_skipped <= 0) {
     RunSkipCallback(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
@@ -408,8 +417,9 @@
   DCHECK(work_thread_task_runner_->RunsTasksInCurrentSequence());
 
   // Check for out of order callbacks.
-  if (pending_callback_id_ != callback_id)
+  if (pending_callback_id_ != callback_id) {
     return;
+  }
 
   RunReadCallback(bytes_read);
 }
@@ -456,53 +466,37 @@
 }
 
 //==============================
-// RequestId
-//==============================
-
-std::string RequestId::ToString() const {
-  return base::StringPrintf("RequestId(%u, %u)", request_id_, routing_id_);
-}
-
-std::string RequestId::ToString(base::StringPiece debug_label) const {
-  return base::StringPrintf("RequestId[%s](%u, %u)",
-                            debug_label.as_string().c_str(), request_id_,
-                            routing_id_);
-}
-
-std::ostream& operator<<(std::ostream& out, const RequestId& request_id) {
-  return out << request_id.ToString();
-}
-
-//==============================
 // StreamReaderURLLoader
 //=============================
 
 StreamReaderURLLoader::StreamReaderURLLoader(
-    const RequestId& request_id,
+    int32_t request_id,
     const network::ResourceRequest& request,
-    network::mojom::URLLoaderClientPtr client,
-    network::mojom::TrustedHeaderClientPtr header_client,
+    mojo::PendingRemote<network::mojom::URLLoaderClient> client,
+    mojo::PendingRemote<network::mojom::TrustedHeaderClient> header_client,
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
+    absl::optional<mojo_base::BigBuffer> cached_metadata,
     std::unique_ptr<Delegate> response_delegate)
     : request_id_(request_id),
       request_(request),
       client_(std::move(client)),
       header_client_(std::move(header_client)),
       traffic_annotation_(traffic_annotation),
+      cached_metadata_(std::move(cached_metadata)),
       response_delegate_(std::move(response_delegate)),
       writable_handle_watcher_(FROM_HERE,
                                mojo::SimpleWatcher::ArmingPolicy::MANUAL,
-                               base::SequencedTaskRunnerHandle::Get()),
+                               base::SequencedTaskRunner::GetCurrentDefault()),
       weak_factory_(this) {
   DCHECK(response_delegate_);
   // If there is a client error, clean up the request.
-  client_.set_connection_error_handler(
+  client_.set_disconnect_handler(
       base::BindOnce(&StreamReaderURLLoader::RequestComplete,
                      weak_factory_.GetWeakPtr(), net::ERR_ABORTED));
 
   // All InputStream work will be performed on this task runner.
   stream_work_task_runner_ =
-      base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock()});
+      base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});
 }
 
 StreamReaderURLLoader::~StreamReaderURLLoader() {
@@ -526,13 +520,13 @@
         base::BindOnce(&StreamReaderURLLoader::ContinueWithRequestHeaders,
                        weak_factory_.GetWeakPtr()));
   } else {
-    ContinueWithRequestHeaders(net::OK, base::nullopt);
+    ContinueWithRequestHeaders(net::OK, absl::nullopt);
   }
 }
 
 void StreamReaderURLLoader::ContinueWithRequestHeaders(
     int32_t result,
-    const base::Optional<net::HttpRequestHeaders>& headers) {
+    const absl::optional<net::HttpRequestHeaders>& headers) {
   if (result != net::OK) {
     RequestComplete(result);
     return;
@@ -557,8 +551,9 @@
 void StreamReaderURLLoader::FollowRedirect(
     const std::vector<std::string>& removed_headers,
     const net::HttpRequestHeaders& modified_headers,
-    const base::Optional<GURL>& new_url) {
-  NOTREACHED();
+    const net::HttpRequestHeaders& modified_cors_exempt_headers,
+    const absl::optional<GURL>& new_url) {
+  DCHECK(false);
 }
 
 void StreamReaderURLLoader::SetPriority(net::RequestPriority priority,
@@ -651,13 +646,15 @@
       extra_headers, false /* allow_existing_header_override */);
   pending_response->headers = headers;
 
-  if (content_length >= 0)
+  if (content_length >= 0) {
     pending_response->content_length = content_length;
+  }
 
   if (!mime_type.empty()) {
     pending_response->mime_type = mime_type;
-    if (!charset.empty())
+    if (!charset.empty()) {
       pending_response->charset = charset;
+    }
   }
 
   if (header_client_.is_bound()) {
@@ -668,15 +665,15 @@
                        std::move(pending_response)));
   } else {
     ContinueWithResponseHeaders(std::move(pending_response), net::OK,
-                                base::nullopt, base::nullopt);
+                                absl::nullopt, absl::nullopt);
   }
 }
 
 void StreamReaderURLLoader::ContinueWithResponseHeaders(
     network::mojom::URLResponseHeadPtr pending_response,
     int32_t result,
-    const base::Optional<std::string>& headers,
-    const base::Optional<GURL>& redirect_url) {
+    const absl::optional<std::string>& headers,
+    const absl::optional<GURL>& redirect_url) {
   if (result != net::OK) {
     RequestComplete(result);
     return;
@@ -700,8 +697,8 @@
   const auto has_redirect_url = redirect_url && !redirect_url->is_empty();
   if (has_redirect_url || pending_headers->IsRedirect(&location)) {
     pending_response->encoded_data_length = header_length_;
-    pending_response->content_length = pending_response->encoded_body_length =
-        0;
+    pending_response->content_length = 0;
+    pending_response->encoded_body_length = 0;
     const GURL new_location =
         has_redirect_url ? *redirect_url : request_.url.Resolve(location);
     client_->OnReceiveRedirect(
@@ -712,41 +709,24 @@
     // |this| will be deleted.
     CleanUp();
   } else {
-    client_->OnReceiveResponse(std::move(pending_response));
+    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(&StreamReaderURLLoader::OnDataPipeWritable,
+                            base::Unretained(this)));
+
+    client_->OnReceiveResponse(std::move(pending_response),
+                               std::move(consumer_handle),
+                               std::move(cached_metadata_));
+    ReadMore();
   }
 }
 
-void StreamReaderURLLoader::ContinueResponse(bool was_redirected) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  if (was_redirected) {
-    // Special case where we allow the client to perform the redirect.
-    // The client will restart the request with a new loader.
-    // |this| will be deleted.
-    CleanUp();
-  } else {
-    SendBody();
-  }
-}
-
-void StreamReaderURLLoader::SendBody() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  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(&StreamReaderURLLoader::OnDataPipeWritable,
-                          base::Unretained(this)));
-  client_->OnStartLoadingResponseBody(std::move(consumer_handle));
-
-  ReadMore();
-}
-
 void StreamReaderURLLoader::ReadMore() {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!pending_buffer_.get());
@@ -815,7 +795,7 @@
   client_->OnTransferSizeUpdated(bytes_read);
   total_bytes_read_ += bytes_read;
 
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
+  base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
       FROM_HERE, base::BindOnce(&StreamReaderURLLoader::ReadMore,
                                 weak_factory_.GetWeakPtr()));
 }
@@ -857,8 +837,9 @@
     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)
+      if (ranges.size() == 1) {
         byte_range_ = ranges[0];
+      }
     } else {
       // This happens if the range header could not be parsed or is invalid.
       return false;
@@ -871,4 +852,4 @@
   return byte_range_.IsValid() && byte_range_.first_byte_position() >= 0;
 }
 
-}  // namespace net_service
\ No newline at end of file
+}  // namespace net_service
diff --git a/src/libcef/browser/net_service/stream_reader_url_loader.h b/src/libcef/browser/net_service/stream_reader_url_loader.h
index 7ec165f..ea3ec46 100644
--- a/src/libcef/browser/net_service/stream_reader_url_loader.h
+++ b/src/libcef/browser/net_service/stream_reader_url_loader.h
@@ -8,11 +8,13 @@
 
 #include <map>
 
-#include "base/callback.h"
+#include "base/functional/callback.h"
 #include "base/threading/thread_checker.h"
+#include "mojo/public/cpp/bindings/remote.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/cpp/resource_request.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 #include "services/network/public/mojom/url_loader.mojom.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
@@ -63,54 +65,6 @@
                     ReadCallback callback) = 0;
 };
 
-// Unique identifier for RequestHandler callbacks.
-// Based on components/viz/common/surfaces/frame_sink_id.h
-class RequestId {
- public:
-  constexpr RequestId() : request_id_(0), routing_id_(0) {}
-
-  constexpr RequestId(const RequestId& other)
-      : request_id_(other.request_id_), routing_id_(other.routing_id_) {}
-
-  constexpr RequestId(uint32_t request_id, uint32_t routing_id)
-      : request_id_(request_id), routing_id_(routing_id) {}
-
-  constexpr bool is_valid() const {
-    return request_id_ != 0 || routing_id_ != 0;
-  }
-
-  constexpr uint32_t request_id() const { return request_id_; }
-
-  constexpr uint32_t routing_id() const { return routing_id_; }
-
-  bool operator==(const RequestId& other) const {
-    return request_id_ == other.request_id_ && routing_id_ == other.routing_id_;
-  }
-
-  bool operator!=(const RequestId& other) const { return !(*this == other); }
-
-  bool operator<(const RequestId& other) const {
-    return std::tie(request_id_, routing_id_) <
-           std::tie(other.request_id_, other.routing_id_);
-  }
-
-  size_t hash() const { return base::HashInts(request_id_, routing_id_); }
-
-  std::string ToString() const;
-
-  std::string ToString(base::StringPiece debug_label) const;
-
- private:
-  uint32_t request_id_;
-  uint32_t routing_id_;
-};
-
-std::ostream& operator<<(std::ostream& out, const RequestId& request_id);
-
-struct RequestIdHash {
-  size_t operator()(const RequestId& key) const { return key.hash(); }
-};
-
 // Abstract class for handling intercepted resource responses. All methods are
 // called on the IO thread unless otherwise indicated.
 class ResourceResponse {
@@ -125,13 +79,13 @@
   // |callback| to continue the request. Return false to cancel the request.
   // |request| may be different from the request used to create the
   // StreamReaderURLLoader if a redirect was followed.
-  virtual bool OpenInputStream(const RequestId& id,
+  virtual bool OpenInputStream(int32_t request_id,
                                const network::ResourceRequest& request,
                                OpenCallback callback) = 0;
 
   // This method is called to populate the response headers.
   using HeaderMap = std::multimap<std::string, std::string>;
-  virtual void GetResponseHeaders(const RequestId& id,
+  virtual void GetResponseHeaders(int32_t request_id,
                                   int* status_code,
                                   std::string* reason_phrase,
                                   std::string* mime_type,
@@ -153,27 +107,32 @@
     // This method is called if the result of calling OpenInputStream was null.
     // The |restarted| parameter is set to true if the request was restarted
     // with a new loader.
-    virtual void OnInputStreamOpenFailed(const RequestId& id,
+    virtual void OnInputStreamOpenFailed(int32_t request_id,
                                          bool* restarted) = 0;
   };
 
   StreamReaderURLLoader(
-      const RequestId& request_id,
+      int32_t request_id,
       const network::ResourceRequest& request,
-      network::mojom::URLLoaderClientPtr client,
-      network::mojom::TrustedHeaderClientPtr header_client,
+      mojo::PendingRemote<network::mojom::URLLoaderClient> client,
+      mojo::PendingRemote<network::mojom::TrustedHeaderClient> header_client,
       const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
+      absl::optional<mojo_base::BigBuffer> cached_metadata,
       std::unique_ptr<Delegate> response_delegate);
+
+  StreamReaderURLLoader(const StreamReaderURLLoader&) = delete;
+  StreamReaderURLLoader& operator=(const StreamReaderURLLoader&) = delete;
+
   ~StreamReaderURLLoader() override;
 
   void Start();
 
-  void ContinueResponse(bool was_redirected);
-
   // network::mojom::URLLoader methods:
-  void FollowRedirect(const std::vector<std::string>& removed_headers,
-                      const net::HttpRequestHeaders& modified_headers,
-                      const base::Optional<GURL>& new_url) override;
+  void FollowRedirect(
+      const std::vector<std::string>& removed_headers,
+      const net::HttpRequestHeaders& modified_headers,
+      const net::HttpRequestHeaders& modified_cors_exempt_headers,
+      const absl::optional<GURL>& new_url) override;
   void SetPriority(net::RequestPriority priority,
                    int intra_priority_value) override;
   void PauseReadingBodyFromNet() override;
@@ -182,7 +141,7 @@
  private:
   void ContinueWithRequestHeaders(
       int32_t result,
-      const base::Optional<net::HttpRequestHeaders>& headers);
+      const absl::optional<net::HttpRequestHeaders>& headers);
   void OnInputStreamOpened(std::unique_ptr<Delegate> returned_delegate,
                            std::unique_ptr<InputStream> input_stream);
 
@@ -191,10 +150,9 @@
   void ContinueWithResponseHeaders(
       network::mojom::URLResponseHeadPtr pending_response,
       int32_t result,
-      const base::Optional<std::string>& headers,
-      const base::Optional<GURL>& redirect_url);
+      const absl::optional<std::string>& headers,
+      const absl::optional<GURL>& redirect_url);
 
-  void SendBody();
   void ReadMore();
   void OnDataPipeWritable(MojoResult result);
   void OnReaderReadCompleted(int bytes_read);
@@ -205,16 +163,17 @@
   bool ParseRange(const net::HttpRequestHeaders& headers);
   bool byte_range_valid() const;
 
-  const RequestId request_id_;
+  const int32_t request_id_;
 
   size_t header_length_ = 0;
   int64_t total_bytes_read_ = 0;
 
   net::HttpByteRange byte_range_;
   network::ResourceRequest request_;
-  network::mojom::URLLoaderClientPtr client_;
-  network::mojom::TrustedHeaderClientPtr header_client_;
+  mojo::Remote<network::mojom::URLLoaderClient> client_;
+  mojo::Remote<network::mojom::TrustedHeaderClient> header_client_;
   const net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
+  absl::optional<mojo_base::BigBuffer> cached_metadata_;
   std::unique_ptr<Delegate> response_delegate_;
   scoped_refptr<InputStreamReader> input_stream_reader_;
 
@@ -228,8 +187,6 @@
   base::OnceClosure open_cancel_callback_;
 
   base::WeakPtrFactory<StreamReaderURLLoader> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(StreamReaderURLLoader);
 };
 
 }  // namespace net_service
diff --git a/src/libcef/browser/net_service/url_loader_factory_getter.cc b/src/libcef/browser/net_service/url_loader_factory_getter.cc
index c1c370a..1c8f380 100644
--- a/src/libcef/browser/net_service/url_loader_factory_getter.cc
+++ b/src/libcef/browser/net_service/url_loader_factory_getter.cc
@@ -5,12 +5,13 @@
 
 #include "libcef/browser/net_service/url_loader_factory_getter.h"
 
-#include "libcef/browser/content_browser_client.h"
 #include "libcef/browser/thread_util.h"
+#include "libcef/common/app_manager.h"
 
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/task/single_thread_task_runner.h"
 #include "content/browser/devtools/devtools_instrumentation.h"
-#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/renderer_host/render_frame_host_impl.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_client.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -18,7 +19,7 @@
 
 namespace net_service {
 
-// Based on CreateDownloadURLLoaderFactoryGetter from
+// Based on CreatePendingSharedURLLoaderFactory from
 // content/browser/download/download_manager_impl.cc.
 // static
 scoped_refptr<URLLoaderFactoryGetter> URLLoaderFactoryGetter::Create(
@@ -31,18 +32,20 @@
   // initialize additional state, and that should be done on the UI thread
   // instead of potentially racing with the WillCreateURLLoaderFactory
   // implementation.
-  auto loader_factory =
-      content::BrowserContext::GetDefaultStoragePartition(browser_context)
-          ->GetURLLoaderFactoryForBrowserProcess();
+  auto loader_factory = browser_context->GetDefaultStoragePartition()
+                            ->GetURLLoaderFactoryForBrowserProcess();
 
-  network::mojom::URLLoaderFactoryPtrInfo proxy_factory_ptr_info;
-  network::mojom::URLLoaderFactoryRequest proxy_factory_request;
+  mojo::PendingRemote<network::mojom::URLLoaderFactory> proxy_factory_remote;
+  mojo::PendingReceiver<network::mojom::URLLoaderFactory>
+      proxy_factory_receiver;
 
   // Create an intermediate pipe that can be used to proxy the request's
   // URLLoaderFactory.
-  network::mojom::URLLoaderFactoryPtrInfo maybe_proxy_factory_ptr_info;
+  mojo::PendingRemote<network::mojom::URLLoaderFactory>
+      maybe_proxy_factory_remote;
   mojo::PendingReceiver<network::mojom::URLLoaderFactory>
-      maybe_proxy_factory_request = MakeRequest(&maybe_proxy_factory_ptr_info);
+      maybe_proxy_factory_receiver =
+          maybe_proxy_factory_remote.InitWithNewPipeAndPassReceiver();
 
   bool should_proxy = false;
   int render_process_id = -1;
@@ -55,53 +58,57 @@
         content::devtools_instrumentation::WillCreateURLLoaderFactory(
             static_cast<content::RenderFrameHostImpl*>(render_frame_host),
             false /* is_navigation */, false /* is_download */,
-            &maybe_proxy_factory_request, nullptr /* factory_override */);
+            &maybe_proxy_factory_receiver, nullptr /* factory_override */);
   }
 
+  auto browser_client = CefAppManager::Get()->GetContentClient()->browser();
+
   // Allow the Content embedder to inject itself if it wants to.
-  should_proxy |= CefContentBrowserClient::Get()->WillCreateURLLoaderFactory(
+  should_proxy |= browser_client->WillCreateURLLoaderFactory(
       browser_context, render_frame_host, render_process_id,
       content::ContentBrowserClient::URLLoaderFactoryType::kDocumentSubResource,
-      url::Origin(), base::nullopt /* navigation_id */,
-      &maybe_proxy_factory_request, nullptr /* header_client */,
+      url::Origin(), absl::nullopt /* navigation_id */, ukm::SourceIdObj(),
+      &maybe_proxy_factory_receiver, nullptr /* header_client */,
       nullptr /* bypass_redirect_checks */, nullptr /* disable_secure_dns */,
-      nullptr /* factory_override */);
+      nullptr /* factory_override */,
+      nullptr /* navigation_response_task_runner */);
 
   // If anyone above indicated that they care about proxying, pass the
   // intermediate pipe along to the URLLoaderFactoryGetter.
   if (should_proxy) {
-    proxy_factory_ptr_info = std::move(maybe_proxy_factory_ptr_info);
-    proxy_factory_request = std::move(maybe_proxy_factory_request);
+    proxy_factory_remote = std::move(maybe_proxy_factory_remote);
+    proxy_factory_receiver = std::move(maybe_proxy_factory_receiver);
   }
 
   return base::WrapRefCounted(new URLLoaderFactoryGetter(
-      loader_factory->Clone(), std::move(proxy_factory_ptr_info),
-      std::move(proxy_factory_request)));
+      loader_factory->Clone(), std::move(proxy_factory_remote),
+      std::move(proxy_factory_receiver)));
 }
 
-// Based on NetworkDownloadURLLoaderFactoryGetter from
-// content/browser/download/network_download_url_loader_factory_getter.cc.
+// Based on CreateFactory from
+// content/browser/download/network_download_pending_url_loader_factory.cc.
 scoped_refptr<network::SharedURLLoaderFactory>
 URLLoaderFactoryGetter::GetURLLoaderFactory() {
   // On first call we associate with the current thread.
   if (!task_runner_) {
-    task_runner_ = base::ThreadTaskRunnerHandle::Get();
+    task_runner_ = base::SingleThreadTaskRunner::GetCurrentDefault();
   } else {
     DCHECK(task_runner_->RunsTasksInCurrentSequence());
   }
 
-  if (lazy_factory_)
+  if (lazy_factory_) {
     return lazy_factory_;
+  }
 
   // Bind on the current thread.
   auto loader_factory =
       network::SharedURLLoaderFactory::Create(std::move(loader_factory_info_));
 
-  if (proxy_factory_request_.is_pending()) {
-    loader_factory->Clone(std::move(proxy_factory_request_));
+  if (proxy_factory_receiver_.is_valid()) {
+    loader_factory->Clone(std::move(proxy_factory_receiver_));
     lazy_factory_ =
         base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
-            std::move(proxy_factory_ptr_info_));
+            std::move(proxy_factory_remote_));
   } else {
     lazy_factory_ = loader_factory;
   }
@@ -110,11 +117,12 @@
 
 URLLoaderFactoryGetter::URLLoaderFactoryGetter(
     std::unique_ptr<network::PendingSharedURLLoaderFactory> loader_factory_info,
-    network::mojom::URLLoaderFactoryPtrInfo proxy_factory_ptr_info,
-    network::mojom::URLLoaderFactoryRequest proxy_factory_request)
+    mojo::PendingRemote<network::mojom::URLLoaderFactory> proxy_factory_remote,
+    mojo::PendingReceiver<network::mojom::URLLoaderFactory>
+        proxy_factory_receiver)
     : loader_factory_info_(std::move(loader_factory_info)),
-      proxy_factory_ptr_info_(std::move(proxy_factory_ptr_info)),
-      proxy_factory_request_(std::move(proxy_factory_request)) {}
+      proxy_factory_remote_(std::move(proxy_factory_remote)),
+      proxy_factory_receiver_(std::move(proxy_factory_receiver)) {}
 
 URLLoaderFactoryGetter::~URLLoaderFactoryGetter() = default;
 
@@ -126,4 +134,4 @@
   delete this;
 }
 
-}  // namespace net_service
\ No newline at end of file
+}  // namespace net_service
diff --git a/src/libcef/browser/net_service/url_loader_factory_getter.h b/src/libcef/browser/net_service/url_loader_factory_getter.h
index 431515a..554c815 100644
--- a/src/libcef/browser/net_service/url_loader_factory_getter.h
+++ b/src/libcef/browser/net_service/url_loader_factory_getter.h
@@ -6,10 +6,9 @@
 #ifndef CEF_LIBCEF_BROWSER_NET_SERVICE_URL_LOADER_FACTORY_GETTER_H_
 #define CEF_LIBCEF_BROWSER_NET_SERVICE_URL_LOADER_FACTORY_GETTER_H_
 
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner.h"
-#include "base/sequenced_task_runner_helpers.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner_helpers.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 
 namespace content {
@@ -32,6 +31,9 @@
     : public base::RefCountedThreadSafe<URLLoaderFactoryGetter,
                                         URLLoaderFactoryGetterDeleter> {
  public:
+  URLLoaderFactoryGetter(const URLLoaderFactoryGetter&) = delete;
+  URLLoaderFactoryGetter& operator=(const URLLoaderFactoryGetter&) = delete;
+
   // Create a URLLoaderFactoryGetter on the UI thread.
   // |render_frame_host| may be nullptr.
   static scoped_refptr<URLLoaderFactoryGetter> Create(
@@ -48,22 +50,22 @@
                                           URLLoaderFactoryGetterDeleter>;
   friend struct URLLoaderFactoryGetterDeleter;
 
-  URLLoaderFactoryGetter(
-      std::unique_ptr<network::PendingSharedURLLoaderFactory>
-          loader_factory_info,
-      network::mojom::URLLoaderFactoryPtrInfo proxy_factory_ptr_info,
-      network::mojom::URLLoaderFactoryRequest proxy_factory_request);
+  URLLoaderFactoryGetter(std::unique_ptr<network::PendingSharedURLLoaderFactory>
+                             loader_factory_info,
+                         mojo::PendingRemote<network::mojom::URLLoaderFactory>
+                             proxy_factory_remote,
+                         mojo::PendingReceiver<network::mojom::URLLoaderFactory>
+                             proxy_factory_receiver);
   ~URLLoaderFactoryGetter();
 
   void DeleteOnCorrectThread() const;
 
   std::unique_ptr<network::PendingSharedURLLoaderFactory> loader_factory_info_;
   scoped_refptr<network::SharedURLLoaderFactory> lazy_factory_;
-  network::mojom::URLLoaderFactoryPtrInfo proxy_factory_ptr_info_;
-  network::mojom::URLLoaderFactoryRequest proxy_factory_request_;
+  mojo::PendingRemote<network::mojom::URLLoaderFactory> proxy_factory_remote_;
+  mojo::PendingReceiver<network::mojom::URLLoaderFactory>
+      proxy_factory_receiver_;
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(URLLoaderFactoryGetter);
 };
 
 struct URLLoaderFactoryGetterDeleter {
diff --git a/src/libcef/browser/origin_whitelist_impl.cc b/src/libcef/browser/origin_whitelist_impl.cc
index 6bd3bca..b2ff3d6 100644
--- a/src/libcef/browser/origin_whitelist_impl.cc
+++ b/src/libcef/browser/origin_whitelist_impl.cc
@@ -8,22 +8,31 @@
 #include <vector>
 
 #include "include/cef_origin_whitelist.h"
+#include "libcef/browser/browser_manager.h"
 #include "libcef/browser/context.h"
 #include "libcef/browser/thread_util.h"
-#include "libcef/common/cef_messages.h"
 
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #include "base/lazy_instance.h"
 #include "base/synchronization/lock.h"
+#include "cef/libcef/common/mojom/cef.mojom.h"
+#include "chrome/common/webui_url_constants.h"
 #include "content/public/browser/render_process_host.h"
+#include "content/public/common/url_constants.h"
+#include "extensions/common/constants.h"
 #include "url/gurl.h"
+#include "url/origin.h"
 
 namespace {
 
 // Class that manages cross-origin whitelist registrations.
 class CefOriginWhitelistManager {
  public:
-  CefOriginWhitelistManager() {}
+  CefOriginWhitelistManager() = default;
+
+  CefOriginWhitelistManager(const CefOriginWhitelistManager&) = delete;
+  CefOriginWhitelistManager& operator=(const CefOriginWhitelistManager&) =
+      delete;
 
   // Retrieve the singleton instance.
   static CefOriginWhitelistManager* GetInstance();
@@ -32,23 +41,23 @@
                       const std::string& target_protocol,
                       const std::string& target_domain,
                       bool allow_target_subdomains) {
-    Cef_CrossOriginWhiteListEntry_Params info;
-    info.source_origin = source_origin;
-    info.target_protocol = target_protocol;
-    info.target_domain = target_domain;
-    info.allow_target_subdomains = allow_target_subdomains;
+    auto info = cef::mojom::CrossOriginWhiteListEntry::New();
+    info->source_origin = source_origin;
+    info->target_protocol = target_protocol;
+    info->target_domain = target_domain;
+    info->allow_target_subdomains = allow_target_subdomains;
 
     {
       base::AutoLock lock_scope(lock_);
 
       // Verify that the origin entry doesn't already exist.
-      OriginList::const_iterator it = origin_list_.begin();
-      for (; it != origin_list_.end(); ++it) {
-        if (IsEqual(*it, info))
+      for (const auto& entry : origin_list_) {
+        if (entry == info) {
           return false;
+        }
       }
 
-      origin_list_.push_back(info);
+      origin_list_.push_back(info->Clone());
     }
 
     SendModifyCrossOriginWhitelistEntry(true, info);
@@ -59,20 +68,20 @@
                          const std::string& target_protocol,
                          const std::string& target_domain,
                          bool allow_target_subdomains) {
-    Cef_CrossOriginWhiteListEntry_Params info;
-    info.source_origin = source_origin;
-    info.target_protocol = target_protocol;
-    info.target_domain = target_domain;
-    info.allow_target_subdomains = allow_target_subdomains;
+    auto info = cef::mojom::CrossOriginWhiteListEntry::New();
+    info->source_origin = source_origin;
+    info->target_protocol = target_protocol;
+    info->target_domain = target_domain;
+    info->allow_target_subdomains = allow_target_subdomains;
 
     bool found = false;
 
     {
       base::AutoLock lock_scope(lock_);
 
-      OriginList::iterator it = origin_list_.begin();
+      CrossOriginWhiteList::iterator it = origin_list_.begin();
       for (; it != origin_list_.end(); ++it) {
-        if (IsEqual(*it, info)) {
+        if (*it == info) {
           origin_list_.erase(it);
           found = true;
           break;
@@ -80,8 +89,9 @@
       }
     }
 
-    if (!found)
+    if (!found) {
       return false;
+    }
 
     SendModifyCrossOriginWhitelistEntry(false, info);
     return true;
@@ -97,12 +107,31 @@
   }
 
   void GetCrossOriginWhitelistEntries(
-      std::vector<Cef_CrossOriginWhiteListEntry_Params>* entries) {
+      absl::optional<CrossOriginWhiteList>* entries) const {
     base::AutoLock lock_scope(lock_);
 
-    if (origin_list_.empty())
-      return;
-    entries->insert(entries->end(), origin_list_.begin(), origin_list_.end());
+    if (!origin_list_.empty()) {
+      CrossOriginWhiteList vec;
+      for (const auto& entry : origin_list_) {
+        vec.push_back(entry->Clone());
+      }
+      *entries = std::move(vec);
+    }
+  }
+
+  bool HasCrossOriginWhitelistEntry(const url::Origin& source,
+                                    const url::Origin& target) const {
+    base::AutoLock lock_scope(lock_);
+
+    if (!origin_list_.empty()) {
+      for (const auto& entry : origin_list_) {
+        if (IsMatch(source, target, entry)) {
+          return true;
+        }
+      }
+    }
+
+    return false;
   }
 
  private:
@@ -110,14 +139,15 @@
   // existing hosts.
   static void SendModifyCrossOriginWhitelistEntry(
       bool add,
-      Cef_CrossOriginWhiteListEntry_Params& params) {
+      const cef::mojom::CrossOriginWhiteListEntryPtr& info) {
     CEF_REQUIRE_UIT();
 
     content::RenderProcessHost::iterator i(
         content::RenderProcessHost::AllHostsIterator());
     for (; !i.IsAtEnd(); i.Advance()) {
-      i.GetCurrentValue()->Send(
-          new CefProcessMsg_ModifyCrossOriginWhitelistEntry(add, params));
+      auto render_manager =
+          CefBrowserManager::GetRenderManagerForProcess(i.GetCurrentValue());
+      render_manager->ModifyCrossOriginWhitelistEntry(add, info->Clone());
     }
   }
 
@@ -129,25 +159,44 @@
     content::RenderProcessHost::iterator i(
         content::RenderProcessHost::AllHostsIterator());
     for (; !i.IsAtEnd(); i.Advance()) {
-      i.GetCurrentValue()->Send(new CefProcessMsg_ClearCrossOriginWhitelist);
+      auto render_manager =
+          CefBrowserManager::GetRenderManagerForProcess(i.GetCurrentValue());
+      render_manager->ClearCrossOriginWhitelist();
     }
   }
 
-  static bool IsEqual(const Cef_CrossOriginWhiteListEntry_Params& param1,
-                      const Cef_CrossOriginWhiteListEntry_Params& param2) {
-    return (param1.source_origin == param2.source_origin &&
-            param1.target_protocol == param2.target_protocol &&
-            param1.target_domain == param2.target_domain &&
-            param1.allow_target_subdomains == param2.allow_target_subdomains);
+  static bool IsMatch(const url::Origin& source_origin,
+                      const url::Origin& target_origin,
+                      const cef::mojom::CrossOriginWhiteListEntryPtr& param) {
+    if (!source_origin.IsSameOriginWith(
+            url::Origin::Create(GURL(param->source_origin)))) {
+      // Source origin does not match.
+      return false;
+    }
+
+    if (target_origin.scheme() != param->target_protocol) {
+      // Target scheme does not match.
+      return false;
+    }
+
+    if (param->allow_target_subdomains) {
+      if (param->target_domain.empty()) {
+        // Any domain will match.
+        return true;
+      } else {
+        // Match sub-domains.
+        return target_origin.DomainIs(param->target_domain.c_str());
+      }
+    } else {
+      // Match full domain.
+      return (target_origin.host() == param->target_domain);
+    }
   }
 
-  base::Lock lock_;
+  mutable base::Lock lock_;
 
   // List of registered origins. Access must be protected by |lock_|.
-  typedef std::vector<Cef_CrossOriginWhiteListEntry_Params> OriginList;
-  OriginList origin_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefOriginWhitelistManager);
+  CrossOriginWhiteList origin_list_;
 };
 
 base::LazyInstance<CefOriginWhitelistManager>::Leaky g_manager =
@@ -157,33 +206,6 @@
   return g_manager.Pointer();
 }
 
-bool IsMatch(const GURL& source_origin,
-             const GURL& target_origin,
-             const Cef_CrossOriginWhiteListEntry_Params& param) {
-  if (source_origin.GetOrigin() != GURL(param.source_origin)) {
-    // Source origin does not match.
-    return false;
-  }
-
-  if (target_origin.scheme() != param.target_protocol) {
-    // Target scheme does not match.
-    return false;
-  }
-
-  if (param.allow_target_subdomains) {
-    if (param.target_domain.empty()) {
-      // Any domain will match.
-      return true;
-    } else {
-      // Match sub-domains.
-      return target_origin.DomainIs(param.target_domain.c_str());
-    }
-  } else {
-    // Match full domain.
-    return (target_origin.host() == param.target_domain);
-  }
-}
-
 }  // namespace
 
 bool CefAddCrossOriginWhitelistEntry(const CefString& source_origin,
@@ -192,14 +214,14 @@
                                      bool allow_target_subdomains) {
   // Verify that the context is in a valid state.
   if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED();
+    DCHECK(false);
     return false;
   }
 
   std::string source_url = source_origin;
   GURL gurl = GURL(source_url);
   if (gurl.is_empty() || !gurl.is_valid()) {
-    NOTREACHED() << "Invalid source_origin URL: " << source_url;
+    DCHECK(false) << "Invalid source_origin URL: " << source_url;
     return false;
   }
 
@@ -209,9 +231,9 @@
   } else {
     CEF_POST_TASK(
         CEF_UIT,
-        base::Bind(base::IgnoreResult(&CefAddCrossOriginWhitelistEntry),
-                   source_origin, target_protocol, target_domain,
-                   allow_target_subdomains));
+        base::BindOnce(base::IgnoreResult(&CefAddCrossOriginWhitelistEntry),
+                       source_origin, target_protocol, target_domain,
+                       allow_target_subdomains));
   }
 
   return true;
@@ -223,14 +245,14 @@
                                         bool allow_target_subdomains) {
   // Verify that the context is in a valid state.
   if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED();
+    DCHECK(false);
     return false;
   }
 
   std::string source_url = source_origin;
   GURL gurl = GURL(source_url);
   if (gurl.is_empty() || !gurl.is_valid()) {
-    NOTREACHED() << "Invalid source_origin URL: " << source_url;
+    DCHECK(false) << "Invalid source_origin URL: " << source_url;
     return false;
   }
 
@@ -240,9 +262,9 @@
   } else {
     CEF_POST_TASK(
         CEF_UIT,
-        base::Bind(base::IgnoreResult(&CefRemoveCrossOriginWhitelistEntry),
-                   source_origin, target_protocol, target_domain,
-                   allow_target_subdomains));
+        base::BindOnce(base::IgnoreResult(&CefRemoveCrossOriginWhitelistEntry),
+                       source_origin, target_protocol, target_domain,
+                       allow_target_subdomains));
   }
 
   return true;
@@ -251,7 +273,7 @@
 bool CefClearCrossOriginWhitelist() {
   // Verify that the context is in a valid state.
   if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED();
+    DCHECK(false);
     return false;
   }
 
@@ -259,32 +281,31 @@
     CefOriginWhitelistManager::GetInstance()->ClearOrigins();
   } else {
     CEF_POST_TASK(
-        CEF_UIT, base::Bind(base::IgnoreResult(&CefClearCrossOriginWhitelist)));
+        CEF_UIT,
+        base::BindOnce(base::IgnoreResult(&CefClearCrossOriginWhitelist)));
   }
 
   return true;
 }
 
 void GetCrossOriginWhitelistEntries(
-    std::vector<Cef_CrossOriginWhiteListEntry_Params>* entries) {
+    absl::optional<CrossOriginWhiteList>* entries) {
   CefOriginWhitelistManager::GetInstance()->GetCrossOriginWhitelistEntries(
       entries);
 }
 
-bool HasCrossOriginWhitelistEntry(const GURL& source, const GURL& target) {
-  std::vector<Cef_CrossOriginWhiteListEntry_Params> params;
-  CefOriginWhitelistManager::GetInstance()->GetCrossOriginWhitelistEntries(
-      &params);
-
-  if (params.empty())
-    return false;
-
-  std::vector<Cef_CrossOriginWhiteListEntry_Params>::const_iterator it =
-      params.begin();
-  for (; it != params.end(); ++it) {
-    if (IsMatch(source, target, *it))
-      return true;
+bool HasCrossOriginWhitelistEntry(const url::Origin& source,
+                                  const url::Origin& target) {
+  // Components of chrome that are implemented as extensions or platform apps
+  // are allowed to use chrome://resources/ and chrome://theme/ URLs.
+  // See also RegisterNonNetworkSubresourceURLLoaderFactories.
+  if (source.scheme() == extensions::kExtensionScheme &&
+      target.scheme() == content::kChromeUIScheme &&
+      (target.host() == chrome::kChromeUIThemeHost ||
+       target.host() == content::kChromeUIResourcesHost)) {
+    return true;
   }
 
-  return false;
+  return CefOriginWhitelistManager::GetInstance()->HasCrossOriginWhitelistEntry(
+      source, target);
 }
diff --git a/src/libcef/browser/origin_whitelist_impl.h b/src/libcef/browser/origin_whitelist_impl.h
index bca948c..c5f8236 100644
--- a/src/libcef/browser/origin_whitelist_impl.h
+++ b/src/libcef/browser/origin_whitelist_impl.h
@@ -5,24 +5,31 @@
 #ifndef CEF_LIBCEF_BROWSER_ORIGIN_WHITELIST_IMPL_H_
 #define CEF_LIBCEF_BROWSER_ORIGIN_WHITELIST_IMPL_H_
 
-#include <list>
 #include <vector>
 
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+#include "cef/libcef/common/mojom/cef.mojom-forward.h"
+
 namespace content {
 class RenderProcessHost;
 }
 
-class GURL;
+namespace url {
+class Origin;
+}
 
-struct Cef_CrossOriginWhiteListEntry_Params;
+using CrossOriginWhiteList =
+    std::vector<cef::mojom::CrossOriginWhiteListEntryPtr>;
 
 // Called to retrieve the current list of cross-origin white list entries. This
 // method is thread safe.
 void GetCrossOriginWhitelistEntries(
-    std::vector<Cef_CrossOriginWhiteListEntry_Params>* entries);
+    absl::optional<CrossOriginWhiteList>* entries);
 
 // Returns true if |source| can access |target| based on the cross-origin white
 // list settings.
-bool HasCrossOriginWhitelistEntry(const GURL& source, const GURL& target);
+bool HasCrossOriginWhitelistEntry(const url::Origin& source,
+                                  const url::Origin& target);
 
 #endif  // CEF_LIBCEF_BROWSER_ORIGIN_WHITELIST_IMPL_H_
diff --git a/src/libcef/browser/osr/browser_platform_delegate_osr.cc b/src/libcef/browser/osr/browser_platform_delegate_osr.cc
index 42e003d..d03f850 100644
--- a/src/libcef/browser/osr/browser_platform_delegate_osr.cc
+++ b/src/libcef/browser/osr/browser_platform_delegate_osr.cc
@@ -6,22 +6,28 @@
 
 #include <utility>
 
-#include "libcef/browser/browser_host_impl.h"
 #include "libcef/browser/image_impl.h"
 #include "libcef/browser/osr/osr_accessibility_util.h"
 #include "libcef/browser/osr/render_widget_host_view_osr.h"
+#include "libcef/browser/osr/touch_selection_controller_client_osr.h"
 #include "libcef/browser/osr/web_contents_view_osr.h"
+#include "libcef/browser/views/view_util.h"
 #include "libcef/common/drag_data_impl.h"
 
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "content/browser/renderer_host/render_widget_host_input_event_router.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/render_view_host.h"
+#include "ui/display/screen.h"
 #include "ui/events/base_event_utils.h"
 
 CefBrowserPlatformDelegateOsr::CefBrowserPlatformDelegateOsr(
-    std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate)
-    : native_delegate_(std::move(native_delegate)), view_osr_(nullptr) {
+    std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
+    bool use_shared_texture,
+    bool use_external_begin_frame)
+    : native_delegate_(std::move(native_delegate)),
+      use_shared_texture_(use_shared_texture),
+      use_external_begin_frame_(use_external_begin_frame) {
   native_delegate_->set_windowless_handler(this);
 }
 
@@ -32,14 +38,15 @@
 
   // Use the OSR view instead of the default platform view.
   view_osr_ = new CefWebContentsViewOSR(
-      GetBackgroundColor(), CanUseSharedTexture(), CanUseExternalBeginFrame());
+      GetBackgroundColor(), use_shared_texture_, use_external_begin_frame_);
   *view = view_osr_;
   *delegate_view = view_osr_;
 }
 
 void CefBrowserPlatformDelegateOsr::WebContentsCreated(
-    content::WebContents* web_contents) {
-  CefBrowserPlatformDelegate::WebContentsCreated(web_contents);
+    content::WebContents* web_contents,
+    bool owned) {
+  CefBrowserPlatformDelegateAlloy::WebContentsCreated(web_contents, owned);
 
   DCHECK(view_osr_);
   DCHECK(!view_osr_->web_contents());
@@ -48,53 +55,67 @@
   view_osr_->WebContentsCreated(web_contents);
 }
 
+void CefBrowserPlatformDelegateOsr::RenderViewCreated(
+    content::RenderViewHost* render_view_host) {
+  if (view_osr_) {
+    view_osr_->RenderViewCreated();
+  }
+}
+
 void CefBrowserPlatformDelegateOsr::BrowserCreated(
-    CefBrowserHostImpl* browser) {
-  CefBrowserPlatformDelegate::BrowserCreated(browser);
+    CefBrowserHostBase* browser) {
+  CefBrowserPlatformDelegateAlloy::BrowserCreated(browser);
 
   if (browser->IsPopup()) {
     // Associate the RenderWidget host view with the browser now because the
     // browser wasn't known at the time that the host view was created.
-    content::RenderViewHost* host =
-        browser->web_contents()->GetRenderViewHost();
+    content::RenderViewHost* host = web_contents_->GetRenderViewHost();
     DCHECK(host);
     CefRenderWidgetHostViewOSR* view =
         static_cast<CefRenderWidgetHostViewOSR*>(host->GetWidget()->GetView());
     // |view| will be null if the popup is a DevTools window.
-    if (view)
-      view->set_browser_impl(browser);
+    if (view) {
+      view->set_browser_impl(static_cast<AlloyBrowserHostImpl*>(browser));
+    }
   }
 }
 
+void CefBrowserPlatformDelegateOsr::NotifyBrowserDestroyed() {
+  content::RenderViewHost* host = web_contents_->GetRenderViewHost();
+  if (host) {
+    CefRenderWidgetHostViewOSR* view =
+        static_cast<CefRenderWidgetHostViewOSR*>(host->GetWidget()->GetView());
+    if (view) {
+      view->ReleaseCompositor();
+    }
+  }
+
+  CefBrowserPlatformDelegateAlloy::NotifyBrowserDestroyed();
+}
+
 void CefBrowserPlatformDelegateOsr::BrowserDestroyed(
-    CefBrowserHostImpl* browser) {
-  CefBrowserPlatformDelegate::BrowserDestroyed(browser);
+    CefBrowserHostBase* browser) {
+  CefBrowserPlatformDelegateAlloy::BrowserDestroyed(browser);
 
   view_osr_ = nullptr;
 }
 
-bool CefBrowserPlatformDelegateOsr::CanUseSharedTexture() const {
-  return native_delegate_->CanUseSharedTexture();
-}
-
-bool CefBrowserPlatformDelegateOsr::CanUseExternalBeginFrame() const {
-  return native_delegate_->CanUseExternalBeginFrame();
-}
-
 SkColor CefBrowserPlatformDelegateOsr::GetBackgroundColor() const {
   return native_delegate_->GetBackgroundColor();
 }
 
 void CefBrowserPlatformDelegateOsr::WasResized() {
   CefRenderWidgetHostViewOSR* view = GetOSRHostView();
-  if (view)
+  if (view) {
     view->WasResized();
+  }
 }
 
 void CefBrowserPlatformDelegateOsr::SendKeyEvent(const CefKeyEvent& event) {
   CefRenderWidgetHostViewOSR* view = GetOSRHostView();
-  if (!view)
+  if (!view) {
     return;
+  }
 
   content::NativeWebKeyboardEvent web_event =
       native_delegate_->TranslateWebKeyEvent(event);
@@ -107,8 +128,9 @@
     bool mouseUp,
     int clickCount) {
   CefRenderWidgetHostViewOSR* view = GetOSRHostView();
-  if (!view)
+  if (!view) {
     return;
+  }
 
   blink::WebMouseEvent web_event = native_delegate_->TranslateWebClickEvent(
       event, type, mouseUp, clickCount);
@@ -119,8 +141,9 @@
     const CefMouseEvent& event,
     bool mouseLeave) {
   CefRenderWidgetHostViewOSR* view = GetOSRHostView();
-  if (!view)
+  if (!view) {
     return;
+  }
 
   blink::WebMouseEvent web_event =
       native_delegate_->TranslateWebMoveEvent(event, mouseLeave);
@@ -132,8 +155,9 @@
     int deltaX,
     int deltaY) {
   CefRenderWidgetHostViewOSR* view = GetOSRHostView();
-  if (!view)
+  if (!view) {
     return;
+  }
 
   blink::WebMouseWheelEvent web_event =
       native_delegate_->TranslateWebWheelEvent(event, deltaX, deltaY);
@@ -142,24 +166,38 @@
 
 void CefBrowserPlatformDelegateOsr::SendTouchEvent(const CefTouchEvent& event) {
   CefRenderWidgetHostViewOSR* view = GetOSRHostView();
-  if (view)
+  if (view) {
     view->SendTouchEvent(event);
+  }
 }
 
-void CefBrowserPlatformDelegateOsr::SendFocusEvent(bool setFocus) {
+void CefBrowserPlatformDelegateOsr::SetFocus(bool setFocus) {
   CefRenderWidgetHostViewOSR* view = GetOSRHostView();
-  if (view)
-    view->SendFocusEvent(setFocus);
+  if (view) {
+    view->SetFocus(setFocus);
+  }
 }
 
 gfx::Point CefBrowserPlatformDelegateOsr::GetScreenPoint(
-    const gfx::Point& view) const {
+    const gfx::Point& view,
+    bool want_dip_coords) const {
   CefRefPtr<CefRenderHandler> handler = browser_->client()->GetRenderHandler();
   if (handler.get()) {
     int screenX = 0, screenY = 0;
     if (handler->GetScreenPoint(browser_, view.x(), view.y(), screenX,
                                 screenY)) {
-      return gfx::Point(screenX, screenY);
+      gfx::Point screen_point(screenX, screenY);
+#if !BUILDFLAG(IS_MAC)
+      // Mac always operates in DIP coordinates so |want_dip_coords| is ignored.
+      if (want_dip_coords) {
+        // Convert to DIP coordinates.
+        const auto& display = view_util::GetDisplayNearestPoint(
+            screen_point, /*input_pixel_coords=*/true);
+        view_util::ConvertPointFromPixels(&screen_point,
+                                          display.device_scale_factor());
+      }
+#endif
+      return screen_point;
     }
   }
   return view;
@@ -179,11 +217,6 @@
   return native_delegate_->GetEventHandle(event);
 }
 
-std::unique_ptr<CefFileDialogRunner>
-CefBrowserPlatformDelegateOsr::CreateFileDialogRunner() {
-  return native_delegate_->CreateFileDialogRunner();
-}
-
 std::unique_ptr<CefJavaScriptDialogRunner>
 CefBrowserPlatformDelegateOsr::CreateJavaScriptDialogRunner() {
   return native_delegate_->CreateJavaScriptDialogRunner();
@@ -198,44 +231,53 @@
   return true;
 }
 
-bool CefBrowserPlatformDelegateOsr::IsViewsHosted() const {
-  return false;
-}
-
 void CefBrowserPlatformDelegateOsr::WasHidden(bool hidden) {
   // The WebContentsImpl will notify the OSR view.
   content::WebContentsImpl* web_contents =
-      static_cast<content::WebContentsImpl*>(browser_->web_contents());
+      static_cast<content::WebContentsImpl*>(web_contents_);
   if (web_contents) {
-    if (hidden)
+    if (hidden) {
       web_contents->WasHidden();
-    else
+    } else {
       web_contents->WasShown();
+    }
   }
 }
 
+bool CefBrowserPlatformDelegateOsr::IsHidden() const {
+  CefRenderWidgetHostViewOSR* view = GetOSRHostView();
+  if (view) {
+    return view->is_hidden();
+  }
+  return true;
+}
+
 void CefBrowserPlatformDelegateOsr::NotifyScreenInfoChanged() {
   CefRenderWidgetHostViewOSR* view = GetOSRHostView();
-  if (view)
+  if (view) {
     view->OnScreenInfoChanged();
+  }
 }
 
 void CefBrowserPlatformDelegateOsr::Invalidate(cef_paint_element_type_t type) {
   CefRenderWidgetHostViewOSR* view = GetOSRHostView();
-  if (view)
+  if (view) {
     view->Invalidate(type);
+  }
 }
 
 void CefBrowserPlatformDelegateOsr::SendExternalBeginFrame() {
   CefRenderWidgetHostViewOSR* view = GetOSRHostView();
-  if (view)
+  if (view) {
     view->SendExternalBeginFrame();
+  }
 }
 
 void CefBrowserPlatformDelegateOsr::SetWindowlessFrameRate(int frame_rate) {
   CefRenderWidgetHostViewOSR* view = GetOSRHostView();
-  if (view)
+  if (view) {
     view->UpdateFrameRate();
+  }
 }
 
 void CefBrowserPlatformDelegateOsr::ImeSetComposition(
@@ -255,21 +297,24 @@
     const CefRange& replacement_range,
     int relative_cursor_pos) {
   CefRenderWidgetHostViewOSR* view = GetOSRHostView();
-  if (view)
+  if (view) {
     view->ImeCommitText(text, replacement_range, relative_cursor_pos);
+  }
 }
 
 void CefBrowserPlatformDelegateOsr::ImeFinishComposingText(
     bool keep_selection) {
   CefRenderWidgetHostViewOSR* view = GetOSRHostView();
-  if (view)
+  if (view) {
     view->ImeFinishComposingText(keep_selection);
+  }
 }
 
 void CefBrowserPlatformDelegateOsr::ImeCancelComposition() {
   CefRenderWidgetHostViewOSR* view = GetOSRHostView();
-  if (view)
+  if (view) {
     view->ImeCancelComposition();
+  }
 }
 
 void CefBrowserPlatformDelegateOsr::DragTargetDragEnter(
@@ -277,12 +322,14 @@
     const CefMouseEvent& event,
     cef_drag_operations_mask_t allowed_ops) {
   content::WebContentsImpl* web_contents =
-      static_cast<content::WebContentsImpl*>(browser_->web_contents());
-  if (!web_contents)
+      static_cast<content::WebContentsImpl*>(web_contents_);
+  if (!web_contents) {
     return;
+  }
 
-  if (current_rvh_for_drag_)
+  if (current_rvh_for_drag_) {
     DragTargetDragLeave();
+  }
 
   const gfx::Point client_pt(event.x, event.y);
   gfx::PointF transformed_pt;
@@ -300,9 +347,11 @@
   CefDragDataImpl* data_impl = static_cast<CefDragDataImpl*>(drag_data.get());
   base::AutoLock lock_scope(data_impl->lock());
   content::DropData* drop_data = data_impl->drop_data();
-  const gfx::Point& screen_pt = GetScreenPoint(client_pt);
-  blink::WebDragOperationsMask ops =
-      static_cast<blink::WebDragOperationsMask>(allowed_ops);
+  drop_data->document_is_handling_drag = document_is_handling_drag_;
+  const gfx::Point& screen_pt =
+      GetScreenPoint(client_pt, /*want_dip_coords=*/false);
+  blink::DragOperationsMask ops =
+      static_cast<blink::DragOperationsMask>(allowed_ops);
   int modifiers = TranslateWebEventModifiers(event.modifiers);
 
   current_rwh_for_drag_->FilterDropData(drop_data);
@@ -314,23 +363,27 @@
     return;
   }
 
-  current_rwh_for_drag_->DragTargetDragEnter(
-      *drop_data, transformed_pt, gfx::PointF(screen_pt), ops, modifiers);
+  current_rwh_for_drag_->DragTargetDragEnter(*drop_data, transformed_pt,
+                                             gfx::PointF(screen_pt), ops,
+                                             modifiers, base::DoNothing());
 }
 
 void CefBrowserPlatformDelegateOsr::DragTargetDragOver(
     const CefMouseEvent& event,
     cef_drag_operations_mask_t allowed_ops) {
-  if (!drag_data_)
+  if (!drag_data_) {
     return;
+  }
 
   content::WebContentsImpl* web_contents =
-      static_cast<content::WebContentsImpl*>(browser_->web_contents());
-  if (!web_contents)
+      static_cast<content::WebContentsImpl*>(web_contents_);
+  if (!web_contents) {
     return;
+  }
 
   const gfx::Point client_pt(event.x, event.y);
-  const gfx::Point& screen_pt = GetScreenPoint(client_pt);
+  const gfx::Point& screen_pt =
+      GetScreenPoint(client_pt, /*want_dip_coords=*/false);
 
   gfx::PointF transformed_pt;
   content::RenderWidgetHostImpl* target_rwh =
@@ -362,19 +415,20 @@
     DragTargetDragEnter(drag_data_, event, drag_allowed_ops_);
   }
 
-  if (!drag_data_)
+  if (!drag_data_) {
     return;
+  }
 
-  blink::WebDragOperationsMask ops =
-      static_cast<blink::WebDragOperationsMask>(allowed_ops);
+  blink::DragOperationsMask ops =
+      static_cast<blink::DragOperationsMask>(allowed_ops);
   int modifiers = TranslateWebEventModifiers(event.modifiers);
 
   target_rwh->DragTargetDragOver(transformed_pt, gfx::PointF(screen_pt), ops,
-                                 modifiers);
+                                 modifiers, base::DoNothing());
 }
 
 void CefBrowserPlatformDelegateOsr::DragTargetDragLeave() {
-  if (current_rvh_for_drag_ != browser_->web_contents()->GetRenderViewHost() ||
+  if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost() ||
       !drag_data_) {
     return;
   }
@@ -388,16 +442,19 @@
 }
 
 void CefBrowserPlatformDelegateOsr::DragTargetDrop(const CefMouseEvent& event) {
-  if (!drag_data_)
+  if (!drag_data_) {
     return;
+  }
 
   content::WebContentsImpl* web_contents =
-      static_cast<content::WebContentsImpl*>(browser_->web_contents());
-  if (!web_contents)
+      static_cast<content::WebContentsImpl*>(web_contents_);
+  if (!web_contents) {
     return;
+  }
 
   gfx::Point client_pt(event.x, event.y);
-  const gfx::Point& screen_pt = GetScreenPoint(client_pt);
+  const gfx::Point& screen_pt =
+      GetScreenPoint(client_pt, /*want_dip_coords=*/false);
 
   gfx::PointF transformed_pt;
   content::RenderWidgetHostImpl* target_rwh =
@@ -429,18 +486,21 @@
     DragTargetDragEnter(drag_data_, event, drag_allowed_ops_);
   }
 
-  if (!drag_data_)
+  if (!drag_data_) {
     return;
+  }
 
   {
     CefDragDataImpl* data_impl =
         static_cast<CefDragDataImpl*>(drag_data_.get());
     base::AutoLock lock_scope(data_impl->lock());
     content::DropData* drop_data = data_impl->drop_data();
+    drop_data->document_is_handling_drag = document_is_handling_drag_;
     int modifiers = TranslateWebEventModifiers(event.modifiers);
 
     target_rwh->DragTargetDrop(*drop_data, transformed_pt,
-                               gfx::PointF(screen_pt), modifiers);
+                               gfx::PointF(screen_pt), modifiers,
+                               base::DoNothing());
   }
 
   drag_data_ = nullptr;
@@ -448,10 +508,10 @@
 
 void CefBrowserPlatformDelegateOsr::StartDragging(
     const content::DropData& drop_data,
-    blink::WebDragOperationsMask allowed_ops,
+    blink::DragOperationsMask allowed_ops,
     const gfx::ImageSkia& image,
     const gfx::Vector2d& image_offset,
-    const content::DragEventSourceInfo& event_info,
+    const blink::mojom::DragEventSourceInfo& event_info,
     content::RenderWidgetHostImpl* source_rwh) {
   drag_start_rwh_ = source_rwh->GetWeakPtr();
 
@@ -465,19 +525,23 @@
     CefRefPtr<CefDragDataImpl> drag_data(
         new CefDragDataImpl(drop_data, cef_image, cef_image_pos));
     drag_data->SetReadOnly(true);
-    base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
+    base::CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop allow;
     handled = handler->StartDragging(
         browser_, drag_data.get(),
         static_cast<CefRenderHandler::DragOperationsMask>(allowed_ops),
-        event_info.event_location.x(), event_info.event_location.y());
+        event_info.location.x(), event_info.location.y());
   }
 
-  if (!handled)
+  if (!handled) {
     DragSourceSystemDragEnded();
+  }
 }
 
-void CefBrowserPlatformDelegateOsr::UpdateDragCursor(
-    blink::WebDragOperation operation) {
+void CefBrowserPlatformDelegateOsr::UpdateDragOperation(
+    ui::mojom::DragOperation operation,
+    bool document_is_handling_drag) {
+  document_is_handling_drag_ = document_is_handling_drag;
+
   CefRefPtr<CefRenderHandler> handler =
       browser_->GetClient()->GetRenderHandler();
   if (handler.get()) {
@@ -490,18 +554,21 @@
     int x,
     int y,
     cef_drag_operations_mask_t op) {
-  if (!drag_start_rwh_)
+  if (!drag_start_rwh_) {
     return;
+  }
 
   content::WebContentsImpl* web_contents =
-      static_cast<content::WebContentsImpl*>(browser_->web_contents());
-  if (!web_contents)
+      static_cast<content::WebContentsImpl*>(web_contents_);
+  if (!web_contents) {
     return;
+  }
 
   content::RenderWidgetHostImpl* source_rwh = drag_start_rwh_.get();
   const gfx::Point client_loc(gfx::Point(x, y));
-  const gfx::Point& screen_loc = GetScreenPoint(client_loc);
-  blink::WebDragOperation drag_op = static_cast<blink::WebDragOperation>(op);
+  const gfx::Point& screen_loc =
+      GetScreenPoint(client_loc, /*want_dip_coords=*/false);
+  ui::mojom::DragOperation drag_op = static_cast<ui::mojom::DragOperation>(op);
 
   // |client_loc| and |screen_loc| are in the root coordinate space, for
   // non-root RenderWidgetHosts they need to be transformed.
@@ -531,12 +598,15 @@
 }
 
 void CefBrowserPlatformDelegateOsr::DragSourceSystemDragEnded() {
-  if (!drag_start_rwh_)
+  if (!drag_start_rwh_) {
     return;
+  }
 
-  content::WebContents* web_contents = browser_->web_contents();
-  if (!web_contents)
+  content::WebContentsImpl* web_contents =
+      static_cast<content::WebContentsImpl*>(web_contents_);
+  if (!web_contents) {
     return;
+  }
 
   web_contents->SystemDragEnded(drag_start_rwh_.get());
 
@@ -576,20 +646,14 @@
 }
 
 gfx::Point CefBrowserPlatformDelegateOsr::GetParentScreenPoint(
-    const gfx::Point& view) const {
-  return GetScreenPoint(view);
+    const gfx::Point& view,
+    bool want_dip_coords) const {
+  return GetScreenPoint(view, want_dip_coords);
 }
 
 CefRenderWidgetHostViewOSR* CefBrowserPlatformDelegateOsr::GetOSRHostView()
     const {
-  content::WebContents* web_contents = browser_->web_contents();
-  CefRenderWidgetHostViewOSR* fs_view =
-      static_cast<CefRenderWidgetHostViewOSR*>(
-          web_contents->GetFullscreenRenderWidgetHostView());
-  if (fs_view)
-    return fs_view;
-
-  content::RenderViewHost* host = web_contents->GetRenderViewHost();
+  content::RenderViewHost* host = web_contents_->GetRenderViewHost();
   if (host) {
     return static_cast<CefRenderWidgetHostViewOSR*>(
         host->GetWidget()->GetView());
diff --git a/src/libcef/browser/osr/browser_platform_delegate_osr.h b/src/libcef/browser/osr/browser_platform_delegate_osr.h
index ffb6d85..63d8530 100644
--- a/src/libcef/browser/osr/browser_platform_delegate_osr.h
+++ b/src/libcef/browser/osr/browser_platform_delegate_osr.h
@@ -5,7 +5,7 @@
 #ifndef CEF_LIBCEF_BROWSER_OSR_BROWSER_PLATFORM_DELEGATE_OSR_H_
 #define CEF_LIBCEF_BROWSER_OSR_BROWSER_PLATFORM_DELEGATE_OSR_H_
 
-#include "libcef/browser/browser_platform_delegate.h"
+#include "libcef/browser/alloy/browser_platform_delegate_alloy.h"
 #include "libcef/browser/native/browser_platform_delegate_native.h"
 
 class CefRenderWidgetHostViewOSR;
@@ -13,23 +13,24 @@
 
 namespace content {
 class RenderWidgetHostImpl;
-}
+}  // namespace content
 
 // Base implementation of windowless browser functionality.
 class CefBrowserPlatformDelegateOsr
-    : public CefBrowserPlatformDelegate,
+    : public CefBrowserPlatformDelegateAlloy,
       public CefBrowserPlatformDelegateNative::WindowlessHandler {
  public:
   // CefBrowserPlatformDelegate methods:
   void CreateViewForWebContents(
       content::WebContentsView** view,
       content::RenderViewHostDelegateView** delegate_view) override;
-  void WebContentsCreated(content::WebContents* web_contents) override;
-  void BrowserCreated(CefBrowserHostImpl* browser) override;
-  void BrowserDestroyed(CefBrowserHostImpl* browser) override;
+  void WebContentsCreated(content::WebContents* web_contents,
+                          bool owned) override;
+  void RenderViewCreated(content::RenderViewHost* render_view_host) override;
+  void BrowserCreated(CefBrowserHostBase* browser) override;
+  void NotifyBrowserDestroyed() override;
+  void BrowserDestroyed(CefBrowserHostBase* browser) override;
   SkColor GetBackgroundColor() const override;
-  bool CanUseSharedTexture() const override;
-  bool CanUseExternalBeginFrame() const override;
   void WasResized() override;
   void SendKeyEvent(const CefKeyEvent& event) override;
   void SendMouseClickEvent(const CefMouseEvent& event,
@@ -41,20 +42,20 @@
                            int deltaX,
                            int deltaY) override;
   void SendTouchEvent(const CefTouchEvent& event) override;
-  void SendFocusEvent(bool setFocus) override;
-  gfx::Point GetScreenPoint(const gfx::Point& view) const override;
+  void SetFocus(bool setFocus) override;
+  gfx::Point GetScreenPoint(const gfx::Point& view,
+                            bool want_dip_coords) const override;
   void ViewText(const std::string& text) override;
   bool HandleKeyboardEvent(
       const content::NativeWebKeyboardEvent& event) override;
   CefEventHandle GetEventHandle(
       const content::NativeWebKeyboardEvent& event) const override;
-  std::unique_ptr<CefFileDialogRunner> CreateFileDialogRunner() override;
   std::unique_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner()
       override;
   std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
   bool IsWindowless() const override;
-  bool IsViewsHosted() const override;
   void WasHidden(bool hidden) override;
+  bool IsHidden() const override;
   void NotifyScreenInfoChanged() override;
   void Invalidate(cef_paint_element_type_t type) override;
   void SendExternalBeginFrame() override;
@@ -76,12 +77,13 @@
   void DragTargetDragLeave() override;
   void DragTargetDrop(const CefMouseEvent& event) override;
   void StartDragging(const content::DropData& drop_data,
-                     blink::WebDragOperationsMask allowed_ops,
+                     blink::DragOperationsMask allowed_ops,
                      const gfx::ImageSkia& image,
                      const gfx::Vector2d& image_offset,
-                     const content::DragEventSourceInfo& event_info,
+                     const blink::mojom::DragEventSourceInfo& event_info,
                      content::RenderWidgetHostImpl* source_rwh) override;
-  void UpdateDragCursor(blink::WebDragOperation operation) override;
+  void UpdateDragOperation(ui::mojom::DragOperation operation,
+                           bool document_is_handling_drag) override;
   void DragSourceEndedAt(int x, int y, cef_drag_operations_mask_t op) override;
   void DragSourceSystemDragEnded() override;
   void AccessibilityEventReceived(
@@ -92,12 +94,15 @@
 
   // CefBrowserPlatformDelegateNative::WindowlessHandler methods:
   CefWindowHandle GetParentWindowHandle() const override;
-  gfx::Point GetParentScreenPoint(const gfx::Point& view) const override;
+  gfx::Point GetParentScreenPoint(const gfx::Point& view,
+                                  bool want_dip_coords) const override;
 
  protected:
   // Platform-specific behaviors will be delegated to |native_delegate|.
-  explicit CefBrowserPlatformDelegateOsr(
-      std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate);
+  CefBrowserPlatformDelegateOsr(
+      std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
+      bool use_shared_texture,
+      bool use_external_begin_frame);
 
   // Returns the primary OSR host view for the underlying browser. If a
   // full-screen host view currently exists then it will be returned. Otherwise,
@@ -105,7 +110,10 @@
   CefRenderWidgetHostViewOSR* GetOSRHostView() const;
 
   std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate_;
-  CefWebContentsViewOSR* view_osr_;  // Not owned by this class.
+  const bool use_shared_texture_;
+  const bool use_external_begin_frame_;
+
+  CefWebContentsViewOSR* view_osr_ = nullptr;  // Not owned by this class.
 
   // Pending drag/drop data.
   CefRefPtr<CefDragData> drag_data_;
@@ -118,11 +126,16 @@
   // We also keep track of the RenderViewHost we're dragging over to avoid
   // sending the drag exited message after leaving the current
   // view. |current_rvh_for_drag_| should not be dereferenced.
-  void* current_rvh_for_drag_;
+  void* current_rvh_for_drag_ = nullptr;
 
   // We keep track of the RenderWidgetHost from which the current drag started,
   // in order to properly route the drag end message to it.
   base::WeakPtr<content::RenderWidgetHostImpl> drag_start_rwh_;
+
+  // Set to true when the document is handling the drag. This means that the
+  // document has registered an interest in the dropped data and the renderer
+  // process should pass the data to the document on drop.
+  bool document_is_handling_drag_ = false;
 };
 
 #endif  // CEF_LIBCEF_BROWSER_OSR_BROWSER_PLATFORM_DELEGATE_OSR_H_
diff --git a/src/libcef/browser/osr/browser_platform_delegate_osr_linux.cc b/src/libcef/browser/osr/browser_platform_delegate_osr_linux.cc
index fda16ef..0834e64 100644
--- a/src/libcef/browser/osr/browser_platform_delegate_osr_linux.cc
+++ b/src/libcef/browser/osr/browser_platform_delegate_osr_linux.cc
@@ -6,11 +6,12 @@
 
 #include <utility>
 
-#include "libcef/browser/browser_host_impl.h"
-
 CefBrowserPlatformDelegateOsrLinux::CefBrowserPlatformDelegateOsrLinux(
-    std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate)
-    : CefBrowserPlatformDelegateOsr(std::move(native_delegate)) {}
+    std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
+    bool use_external_begin_frame)
+    : CefBrowserPlatformDelegateOsr(std::move(native_delegate),
+                                    /*use_shared_texture=*/false,
+                                    use_external_begin_frame) {}
 
 CefWindowHandle CefBrowserPlatformDelegateOsrLinux::GetHostWindowHandle()
     const {
diff --git a/src/libcef/browser/osr/browser_platform_delegate_osr_linux.h b/src/libcef/browser/osr/browser_platform_delegate_osr_linux.h
index 4dc86ff..071a2cd 100644
--- a/src/libcef/browser/osr/browser_platform_delegate_osr_linux.h
+++ b/src/libcef/browser/osr/browser_platform_delegate_osr_linux.h
@@ -11,8 +11,9 @@
 class CefBrowserPlatformDelegateOsrLinux
     : public CefBrowserPlatformDelegateOsr {
  public:
-  explicit CefBrowserPlatformDelegateOsrLinux(
-      std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate);
+  CefBrowserPlatformDelegateOsrLinux(
+      std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
+      bool use_external_begin_frame);
 
   // CefBrowserPlatformDelegate methods:
   CefWindowHandle GetHostWindowHandle() const override;
diff --git a/src/libcef/browser/osr/browser_platform_delegate_osr_mac.mm b/src/libcef/browser/osr/browser_platform_delegate_osr_mac.mm
index a1f4afe..d67734f 100644
--- a/src/libcef/browser/osr/browser_platform_delegate_osr_mac.mm
+++ b/src/libcef/browser/osr/browser_platform_delegate_osr_mac.mm
@@ -6,12 +6,11 @@
 
 #include <utility>
 
-#include "libcef/browser/browser_host_impl.h"
-#include "libcef/browser/osr/render_widget_host_view_osr.h"
-
 CefBrowserPlatformDelegateOsrMac::CefBrowserPlatformDelegateOsrMac(
     std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate)
-    : CefBrowserPlatformDelegateOsr(std::move(native_delegate)) {}
+    : CefBrowserPlatformDelegateOsr(std::move(native_delegate),
+                                    /*use_shared_texture=*/false,
+                                    /*use_external_begin_frame=*/false) {}
 
 CefWindowHandle CefBrowserPlatformDelegateOsrMac::GetHostWindowHandle() const {
   return native_delegate_->window_info().parent_view;
diff --git a/src/libcef/browser/osr/browser_platform_delegate_osr_win.cc b/src/libcef/browser/osr/browser_platform_delegate_osr_win.cc
index c09e79c..9307bac 100644
--- a/src/libcef/browser/osr/browser_platform_delegate_osr_win.cc
+++ b/src/libcef/browser/osr/browser_platform_delegate_osr_win.cc
@@ -6,11 +6,13 @@
 
 #include <utility>
 
-#include "libcef/browser/browser_host_impl.h"
-
 CefBrowserPlatformDelegateOsrWin::CefBrowserPlatformDelegateOsrWin(
-    std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate)
-    : CefBrowserPlatformDelegateOsr(std::move(native_delegate)) {}
+    std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
+    bool use_shared_texture,
+    bool use_external_begin_frame)
+    : CefBrowserPlatformDelegateOsr(std::move(native_delegate),
+                                    use_shared_texture,
+                                    use_external_begin_frame) {}
 
 CefWindowHandle CefBrowserPlatformDelegateOsrWin::GetHostWindowHandle() const {
   return native_delegate_->window_info().parent_window;
diff --git a/src/libcef/browser/osr/browser_platform_delegate_osr_win.h b/src/libcef/browser/osr/browser_platform_delegate_osr_win.h
index bcc9d8b..8c07a15 100644
--- a/src/libcef/browser/osr/browser_platform_delegate_osr_win.h
+++ b/src/libcef/browser/osr/browser_platform_delegate_osr_win.h
@@ -11,7 +11,9 @@
 class CefBrowserPlatformDelegateOsrWin : public CefBrowserPlatformDelegateOsr {
  public:
   explicit CefBrowserPlatformDelegateOsrWin(
-      std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate);
+      std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
+      bool use_shared_texture,
+      bool use_external_begin_frame);
 
   // CefBrowserPlatformDelegate methods:
   CefWindowHandle GetHostWindowHandle() const override;
diff --git a/src/libcef/browser/osr/host_display_client_osr.cc b/src/libcef/browser/osr/host_display_client_osr.cc
index cc4321c..c734f67 100644
--- a/src/libcef/browser/osr/host_display_client_osr.cc
+++ b/src/libcef/browser/osr/host_display_client_osr.cc
@@ -6,11 +6,9 @@
 
 #include <utility>
 
-#include "libcef/browser/browser_host_impl.h"
 #include "libcef/browser/osr/render_widget_host_view_osr.h"
 
 #include "base/memory/shared_memory_mapping.h"
-#include "components/viz/common/resources/resource_format.h"
 #include "components/viz/common/resources/resource_sizes.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h"
@@ -20,7 +18,7 @@
 #include "third_party/skia/src/core/SkDevice.h"
 #include "ui/gfx/skia_util.h"
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 #include "skia/ext/skia_utils_win.h"
 #endif
 
@@ -29,6 +27,11 @@
   CefLayeredWindowUpdaterOSR(
       CefRenderWidgetHostViewOSR* const view,
       mojo::PendingReceiver<viz::mojom::LayeredWindowUpdater> receiver);
+
+  CefLayeredWindowUpdaterOSR(const CefLayeredWindowUpdaterOSR&) = delete;
+  CefLayeredWindowUpdaterOSR& operator=(const CefLayeredWindowUpdaterOSR&) =
+      delete;
+
   ~CefLayeredWindowUpdaterOSR() override;
 
   void SetActive(bool active);
@@ -46,8 +49,6 @@
   bool active_ = false;
   base::WritableSharedMemoryMapping shared_memory_;
   gfx::Size pixel_size_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefLayeredWindowUpdaterOSR);
 };
 
 CefLayeredWindowUpdaterOSR::CefLayeredWindowUpdaterOSR(
@@ -75,9 +76,10 @@
   // Make sure |pixel_size| is sane.
   size_t expected_bytes;
   bool size_result = viz::ResourceSizes::MaybeSizeInBytes(
-      pixel_size, viz::ResourceFormat::RGBA_8888, &expected_bytes);
-  if (!size_result)
+      pixel_size, viz::SinglePlaneFormat::kRGBA_8888, &expected_bytes);
+  if (!size_result) {
     return;
+  }
 
   pixel_size_ = pixel_size;
   shared_memory_ = region.Map();
@@ -134,7 +136,7 @@
   layered_window_updater_->SetActive(active_);
 }
 
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_LINUX)
 void CefHostDisplayClientOSR::DidCompleteSwapWithNewSize(
     const gfx::Size& size) {}
 #endif
diff --git a/src/libcef/browser/osr/host_display_client_osr.h b/src/libcef/browser/osr/host_display_client_osr.h
index 7d724c6..c0987f8 100644
--- a/src/libcef/browser/osr/host_display_client_osr.h
+++ b/src/libcef/browser/osr/host_display_client_osr.h
@@ -7,7 +7,7 @@
 
 #include <memory>
 
-#include "base/callback.h"
+#include "base/functional/callback.h"
 #include "base/memory/shared_memory_mapping.h"
 #include "components/viz/host/host_display_client.h"
 #include "ui/gfx/native_widget_types.h"
@@ -19,6 +19,10 @@
  public:
   CefHostDisplayClientOSR(CefRenderWidgetHostViewOSR* const view,
                           gfx::AcceleratedWidget widget);
+
+  CefHostDisplayClientOSR(const CefHostDisplayClientOSR&) = delete;
+  CefHostDisplayClientOSR& operator=(const CefHostDisplayClientOSR&) = delete;
+
   ~CefHostDisplayClientOSR() override;
 
   void SetActive(bool active);
@@ -33,15 +37,13 @@
       mojo::PendingReceiver<viz::mojom::LayeredWindowUpdater> receiver)
       override;
 
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_LINUX)
   void DidCompleteSwapWithNewSize(const gfx::Size& size) override;
 #endif
 
   CefRenderWidgetHostViewOSR* const view_;
   std::unique_ptr<CefLayeredWindowUpdaterOSR> layered_window_updater_;
   bool active_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(CefHostDisplayClientOSR);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_OSR_HOST_DISPLAY_CLIENT_OSR_H_
diff --git a/src/libcef/browser/osr/motion_event_osr.cc b/src/libcef/browser/osr/motion_event_osr.cc
index a4e6f14..1f83e84 100644
--- a/src/libcef/browser/osr/motion_event_osr.cc
+++ b/src/libcef/browser/osr/motion_event_osr.cc
@@ -26,7 +26,7 @@
     case CEF_POINTER_TYPE_UNKNOWN:
       return ui::MotionEvent::ToolType::UNKNOWN;
   }
-  NOTREACHED();
+  DCHECK(false);
   return ui::MotionEvent::ToolType::UNKNOWN;
 }
 
@@ -39,10 +39,11 @@
 CefMotionEventOSR::~CefMotionEventOSR() {}
 
 int CefMotionEventOSR::GetSourceDeviceId(size_t pointer_index) const {
-  if (IsValidIndex(pointer_index))
+  if (IsValidIndex(pointer_index)) {
     return pointer(pointer_index).source_device_id;
-  else
+  } else {
     return -1;
+  }
 }
 
 // Returns true if the touch was valid.
@@ -63,10 +64,12 @@
   switch (touch.type) {
     case CEF_TET_PRESSED:
       id = AddId(touch.id);
-      if (id == -1)
+      if (id == -1) {
         return false;
-      if (!AddTouch(touch, id))
+      }
+      if (!AddTouch(touch, id)) {
         return false;
+      }
       break;
 
     case CEF_TET_MOVED: {
@@ -123,18 +126,20 @@
     blink::WebTouchEvent* event,
     const CefTouchEvent& cef_event) {
   int id = LookupId(cef_event.id);
-  if (event->GetType() == blink::WebInputEvent::kTouchMove ||
-      event->GetType() == blink::WebInputEvent::kTouchCancel) {
+  if (event->GetType() == blink::WebInputEvent::Type::kTouchMove ||
+      event->GetType() == blink::WebInputEvent::Type::kTouchCancel) {
     for (size_t i = 0; i < event->touches_length; ++i) {
-      if (event->touches[i].id != id)
-        event->touches[i].state = blink::WebTouchPoint::kStateStationary;
+      if (event->touches[i].id != id) {
+        event->touches[i].state = blink::WebTouchPoint::State::kStateStationary;
+      }
     }
   }
 }
 
 int CefMotionEventOSR::LookupId(int id) {
-  if (id == -1)
+  if (id == -1) {
     return -1;
+  }
 
   for (int i = 0; i < blink::WebTouchEvent::kTouchesLengthCap; i++) {
     if (id_map_[i] == id) {
@@ -145,8 +150,9 @@
 }
 
 int CefMotionEventOSR::AddId(int id) {
-  if (id == -1 || LookupId(id) >= 0)
+  if (id == -1 || LookupId(id) >= 0) {
     return -1;
+  }
 
   for (int i = 0; i < blink::WebTouchEvent::kTouchesLengthCap; i++) {
     if (id_map_[i] == -1) {
@@ -167,8 +173,9 @@
 }
 
 bool CefMotionEventOSR::AddTouch(const CefTouchEvent& touch, int id) {
-  if (GetPointerCount() == MotionEvent::MAX_TOUCH_POINT_COUNT)
+  if (GetPointerCount() == MotionEvent::MAX_TOUCH_POINT_COUNT) {
     return false;
+  }
 
   PushPointer(GetPointerPropertiesFromTouchEvent(touch, id));
   return true;
@@ -176,8 +183,9 @@
 
 void CefMotionEventOSR::UpdateTouch(const CefTouchEvent& touch, int id) {
   int index_to_update = FindPointerIndexOfId(id);
-  if (IsValidIndex(index_to_update))
+  if (IsValidIndex(index_to_update)) {
     pointer(index_to_update) = GetPointerPropertiesFromTouchEvent(touch, id);
+  }
 }
 
 void CefMotionEventOSR::UpdateCachedAction(const CefTouchEvent& touch, int id) {
diff --git a/src/libcef/browser/osr/motion_event_osr.h b/src/libcef/browser/osr/motion_event_osr.h
index eefac5e..ffc2402 100644
--- a/src/libcef/browser/osr/motion_event_osr.h
+++ b/src/libcef/browser/osr/motion_event_osr.h
@@ -17,6 +17,10 @@
 class CefMotionEventOSR : public ui::MotionEventGeneric {
  public:
   CefMotionEventOSR();
+
+  CefMotionEventOSR(const CefMotionEventOSR&) = delete;
+  CefMotionEventOSR& operator=(const CefMotionEventOSR&) = delete;
+
   ~CefMotionEventOSR() override;
 
   int GetSourceDeviceId(size_t pointer_index) const override;
@@ -52,8 +56,6 @@
   ui::PointerProperties GetPointerPropertiesFromTouchEvent(
       const CefTouchEvent& touch,
       int id);
-
-  DISALLOW_COPY_AND_ASSIGN(CefMotionEventOSR);
 };
 
 #endif
diff --git a/src/libcef/browser/osr/osr_accessibility_util.cc b/src/libcef/browser/osr/osr_accessibility_util.cc
index bffb273..919d01d 100644
--- a/src/libcef/browser/osr/osr_accessibility_util.cc
+++ b/src/libcef/browser/osr/osr_accessibility_util.cc
@@ -17,7 +17,7 @@
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_text_utils.h"
 #include "ui/accessibility/ax_tree_update.h"
-#include "ui/gfx/transform.h"
+#include "ui/gfx/geometry/transform.h"
 
 namespace {
 using ui::ToString;
@@ -28,8 +28,9 @@
 template <>
 CefRefPtr<CefListValue> ToCefValue<int>(const std::vector<int>& vecData) {
   CefRefPtr<CefListValue> value = CefListValue::Create();
-  for (size_t i = 0; i < vecData.size(); i++)
+  for (size_t i = 0; i < vecData.size(); i++) {
     value->SetInt(i, vecData[i]);
+  }
 
   return value;
 }
@@ -43,8 +44,9 @@
   // Iterate and find which states are set.
   for (unsigned i = static_cast<unsigned>(ax::mojom::Role::kMinValue) + 1;
        i <= static_cast<unsigned>(ax::mojom::Role::kMaxValue); i++) {
-    if (state & (1 << i))
+    if (state & (1 << i)) {
       value->SetString(index++, ToString(static_cast<ax::mojom::State>(i)));
+    }
   }
   return value;
 }
@@ -69,8 +71,9 @@
 
   // Int Attributes
   void operator()(const std::pair<ax::mojom::IntAttribute, int32_t> attr) {
-    if (attr.first == ax::mojom::IntAttribute::kNone)
+    if (attr.first == ax::mojom::IntAttribute::kNone) {
       return;
+    }
 
     switch (attr.first) {
       case ax::mojom::IntAttribute::kNone:
@@ -82,6 +85,7 @@
       case ax::mojom::IntAttribute::kScrollYMin:
       case ax::mojom::IntAttribute::kScrollYMax:
       case ax::mojom::IntAttribute::kHasPopup:
+      case ax::mojom::IntAttribute::kIsPopup:
       case ax::mojom::IntAttribute::kHierarchicalLevel:
       case ax::mojom::IntAttribute::kTextSelStart:
       case ax::mojom::IntAttribute::kTextSelEnd:
@@ -102,13 +106,15 @@
       case ax::mojom::IntAttribute::kTableRowIndex:
       case ax::mojom::IntAttribute::kActivedescendantId:
       case ax::mojom::IntAttribute::kInPageLinkTargetId:
-      case ax::mojom::IntAttribute::kErrormessageId:
+      case ax::mojom::IntAttribute::kErrormessageIdDeprecated:
       case ax::mojom::IntAttribute::kDOMNodeId:
-      case ax::mojom::IntAttribute::kDropeffect:
+      case ax::mojom::IntAttribute::kDropeffectDeprecated:
       case ax::mojom::IntAttribute::kMemberOfId:
       case ax::mojom::IntAttribute::kNextFocusId:
+      case ax::mojom::IntAttribute::kNextWindowFocusId:
       case ax::mojom::IntAttribute::kNextOnLineId:
       case ax::mojom::IntAttribute::kPreviousFocusId:
+      case ax::mojom::IntAttribute::kPreviousWindowFocusId:
       case ax::mojom::IntAttribute::kPreviousOnLineId:
       case ax::mojom::IntAttribute::kSetSize:
       case ax::mojom::IntAttribute::kPosInSet:
@@ -118,7 +124,7 @@
       case ax::mojom::IntAttribute::kDefaultActionVerb:
         attributes->SetString(
             ToString(attr.first),
-            ui::ActionVerbToUnlocalizedString(
+            ui::ToString(
                 static_cast<ax::mojom::DefaultActionVerb>(attr.second)));
         break;
       case ax::mojom::IntAttribute::kInvalidState: {
@@ -150,6 +156,12 @@
           attributes->SetString(ToString(attr.first), ToString(state));
         }
       } break;
+      case ax::mojom::IntAttribute::kTextAlign: {
+        auto state = static_cast<ax::mojom::TextAlign>(attr.second);
+        if (ax::mojom::TextAlign::kNone != state) {
+          attributes->SetString(ToString(attr.first), ToString(state));
+        }
+      } break;
       case ax::mojom::IntAttribute::kNameFrom:
         attributes->SetString(
             ToString(attr.first),
@@ -173,8 +185,8 @@
         }
       } break;
       case ax::mojom::IntAttribute::kTextDirection: {
-        auto state = static_cast<ax::mojom::TextDirection>(attr.second);
-        if (ax::mojom::TextDirection::kNone != state) {
+        auto state = static_cast<ax::mojom::WritingDirection>(attr.second);
+        if (ax::mojom::WritingDirection::kNone != state) {
           attributes->SetString(ToString(attr.first), ToString(state));
         }
       } break;
@@ -194,9 +206,10 @@
         CefRefPtr<CefListValue> list = CefListValue::Create();
         int index = 0;
         // Iterate and find which states are set.
-        for (unsigned i = 0; i < base::size(textStyleArr); i++) {
-          if (attr.second & static_cast<int>(textStyleArr[i]))
+        for (unsigned i = 0; i < std::size(textStyleArr); i++) {
+          if (attr.second & static_cast<int>(textStyleArr[i])) {
             list->SetString(index++, ToString(textStyleArr[i]));
+          }
         }
         attributes->SetList(ToString(attr.first), list);
       } break;
@@ -219,19 +232,22 @@
 
   // Set Bool Attributes.
   void operator()(const std::pair<ax::mojom::BoolAttribute, bool> attr) {
-    if (attr.first != ax::mojom::BoolAttribute::kNone)
+    if (attr.first != ax::mojom::BoolAttribute::kNone) {
       attributes->SetBool(ToString(attr.first), attr.second);
+    }
   }
   // Set String Attributes.
   void operator()(
       const std::pair<ax::mojom::StringAttribute, std::string>& attr) {
-    if (attr.first != ax::mojom::StringAttribute::kNone)
+    if (attr.first != ax::mojom::StringAttribute::kNone) {
       attributes->SetString(ToString(attr.first), attr.second);
+    }
   }
   // Set Float attributes.
   void operator()(const std::pair<ax::mojom::FloatAttribute, float>& attr) {
-    if (attr.first != ax::mojom::FloatAttribute::kNone)
+    if (attr.first != ax::mojom::FloatAttribute::kNone) {
       attributes->SetDouble(ToString(attr.first), attr.second);
+    }
   }
 
   // Set Int list attributes.
@@ -246,17 +262,19 @@
         for (size_t i = 0; i < attr.second.size(); ++i) {
           auto type = static_cast<ax::mojom::MarkerType>(attr.second[i]);
 
-          if (type == ax::mojom::MarkerType::kNone)
+          if (type == ax::mojom::MarkerType::kNone) {
             continue;
+          }
 
           static ax::mojom::MarkerType marktypeArr[] = {
               ax::mojom::MarkerType::kSpelling, ax::mojom::MarkerType::kGrammar,
               ax::mojom::MarkerType::kTextMatch};
 
           // Iterate and find which markers are set.
-          for (unsigned j = 0; j < base::size(marktypeArr); j++) {
-            if (attr.second[i] & static_cast<int>(marktypeArr[j]))
+          for (unsigned j = 0; j < std::size(marktypeArr); j++) {
+            if (attr.second[i] & static_cast<int>(marktypeArr[j])) {
               list->SetString(index++, ToString(marktypeArr[j]));
+            }
           }
         }
       } else {
@@ -271,8 +289,9 @@
 CefRefPtr<CefDictionaryValue> ToCefValue(const ui::AXNodeData& node) {
   CefRefPtr<CefDictionaryValue> value = CefDictionaryValue::Create();
 
-  if (node.id != -1)
+  if (node.id != -1) {
     value->SetInt("id", node.id);
+  }
 
   value->SetString("role", ToString(node.role));
   value->SetList("state", ToCefValue(node.state));
@@ -302,13 +321,15 @@
        ++action_index) {
     auto action = static_cast<ax::mojom::Action>(action_index);
     if (node.HasAction(action)) {
-      if (!actions_strings)
+      if (!actions_strings) {
         actions_strings = CefListValue::Create();
+      }
       actions_strings->SetString(actions_idx++, ToString(action));
     }
   }
-  if (actions_strings)
+  if (actions_strings) {
     value->SetList("actions", actions_strings);
+  }
 
   CefRefPtr<CefDictionaryValue> attributes = CefDictionaryValue::Create();
   PopulateAxNodeAttributes func(attributes);
@@ -340,29 +361,37 @@
 CefRefPtr<CefDictionaryValue> ToCefValue(const ui::AXTreeData& treeData) {
   CefRefPtr<CefDictionaryValue> value = CefDictionaryValue::Create();
 
-  if (!treeData.tree_id.ToString().empty())
+  if (!treeData.tree_id.ToString().empty()) {
     value->SetString("tree_id", treeData.tree_id.ToString());
+  }
 
-  if (!treeData.parent_tree_id.ToString().empty())
+  if (!treeData.parent_tree_id.ToString().empty()) {
     value->SetString("parent_tree_id", treeData.parent_tree_id.ToString());
+  }
 
-  if (!treeData.focused_tree_id.ToString().empty())
+  if (!treeData.focused_tree_id.ToString().empty()) {
     value->SetString("focused_tree_id", treeData.focused_tree_id.ToString());
+  }
 
-  if (!treeData.doctype.empty())
+  if (!treeData.doctype.empty()) {
     value->SetString("doctype", treeData.doctype);
+  }
 
   value->SetBool("loaded", treeData.loaded);
 
-  if (treeData.loading_progress != 0.0)
+  if (treeData.loading_progress != 0.0) {
     value->SetDouble("loading_progress", treeData.loading_progress);
+  }
 
-  if (!treeData.mimetype.empty())
+  if (!treeData.mimetype.empty()) {
     value->SetString("mimetype", treeData.mimetype);
-  if (!treeData.url.empty())
+  }
+  if (!treeData.url.empty()) {
     value->SetString("url", treeData.url);
-  if (!treeData.title.empty())
+  }
+  if (!treeData.title.empty()) {
     value->SetString("title", treeData.title);
+  }
 
   if (treeData.sel_anchor_object_id != -1) {
     value->SetInt("sel_anchor_object_id", treeData.sel_anchor_object_id);
@@ -377,8 +406,9 @@
                      ToString(treeData.sel_anchor_affinity));
   }
 
-  if (treeData.focus_id != -1)
+  if (treeData.focus_id != -1) {
     value->SetInt("focus_id", treeData.focus_id);
+  }
 
   return value;
 }
@@ -392,11 +422,13 @@
     value->SetDictionary("tree_data", ToCefValue(update.tree_data));
   }
 
-  if (update.node_id_to_clear != 0)
+  if (update.node_id_to_clear != 0) {
     value->SetInt("node_id_to_clear", update.node_id_to_clear);
+  }
 
-  if (update.root_id != 0)
+  if (update.root_id != 0) {
     value->SetInt("root_id", update.root_id);
+  }
 
   value->SetList("nodes", ToCefValue(update.nodes));
 
@@ -407,17 +439,21 @@
 CefRefPtr<CefDictionaryValue> ToCefValue(const ui::AXEvent& event) {
   CefRefPtr<CefDictionaryValue> value = CefDictionaryValue::Create();
 
-  if (event.event_type != ax::mojom::Event::kNone)
+  if (event.event_type != ax::mojom::Event::kNone) {
     value->SetString("event_type", ToString(event.event_type));
+  }
 
-  if (event.id != -1)
+  if (event.id != -1) {
     value->SetInt("id", event.id);
+  }
 
-  if (event.event_from != ax::mojom::EventFrom::kNone)
+  if (event.event_from != ax::mojom::EventFrom::kNone) {
     value->SetString("event_from", ToString(event.event_from));
+  }
 
-  if (event.action_request_id != -1)
+  if (event.action_request_id != -1) {
     value->SetInt("action_request_id", event.action_request_id);
+  }
 
   return value;
 }
@@ -427,8 +463,9 @@
     const content::AXEventNotificationDetails& eventData) {
   CefRefPtr<CefDictionaryValue> value = CefDictionaryValue::Create();
 
-  if (!eventData.ax_tree_id.ToString().empty())
+  if (!eventData.ax_tree_id.ToString().empty()) {
     value->SetString("ax_tree_id", eventData.ax_tree_id.ToString());
+  }
 
   if (eventData.updates.size() > 0) {
     CefRefPtr<CefListValue> updates = CefListValue::Create();
@@ -458,15 +495,17 @@
 CefRefPtr<CefDictionaryValue> ToCefValue(const ui::AXRelativeBounds& location) {
   CefRefPtr<CefDictionaryValue> value = CefDictionaryValue::Create();
 
-  if (location.offset_container_id != -1)
+  if (location.offset_container_id != -1) {
     value->SetInt("offset_container_id", location.offset_container_id);
+  }
 
   value->SetDictionary("bounds", ToCefValue(location.bounds));
 
   // Transform matrix is private, so we set the string that Clients can parse
   // and use if needed.
-  if (location.transform && !location.transform->IsIdentity())
+  if (location.transform && !location.transform->IsIdentity()) {
     value->SetString("transform", location.transform->ToString());
+  }
 
   return value;
 }
@@ -476,11 +515,13 @@
     const content::AXLocationChangeNotificationDetails& locData) {
   CefRefPtr<CefDictionaryValue> value = CefDictionaryValue::Create();
 
-  if (locData.id != -1)
+  if (locData.id != -1) {
     value->SetInt("id", locData.id);
+  }
 
-  if (!locData.ax_tree_id.ToString().empty())
+  if (!locData.ax_tree_id.ToString().empty()) {
     value->SetString("ax_tree_id", locData.ax_tree_id.ToString());
+  }
 
   value->SetDictionary("new_location", ToCefValue(locData.new_location));
 
@@ -491,8 +532,9 @@
 CefRefPtr<CefListValue> ToCefValue(const std::vector<T>& vecData) {
   CefRefPtr<CefListValue> value = CefListValue::Create();
 
-  for (size_t i = 0; i < vecData.size(); i++)
+  for (size_t i = 0; i < vecData.size(); i++) {
     value->SetDictionary(i, ToCefValue(vecData[i]));
+  }
 
   return value;
 }
diff --git a/src/libcef/browser/osr/osr_util.cc b/src/libcef/browser/osr/osr_util.cc
index 6068889..d1069b6 100644
--- a/src/libcef/browser/osr/osr_util.cc
+++ b/src/libcef/browser/osr/osr_util.cc
@@ -10,15 +10,14 @@
 
 // The rate at which new calls to OnPaint will be generated.
 const int kDefaultFrameRate = 30;
-const int kMaximumFrameRate = 60;
 
 }  // namespace
 
 int ClampFrameRate(int frame_rate) {
-  if (frame_rate < 1)
+  if (frame_rate < 1) {
     return kDefaultFrameRate;
-  else if (frame_rate > kMaximumFrameRate)
-    return kMaximumFrameRate;
+  }
+
   return frame_rate;
 }
 
diff --git a/src/libcef/browser/osr/render_widget_host_view_osr.cc b/src/libcef/browser/osr/render_widget_host_view_osr.cc
index 77e6447..a5de89c 100644
--- a/src/libcef/browser/osr/render_widget_host_view_osr.cc
+++ b/src/libcef/browser/osr/render_widget_host_view_osr.cc
@@ -6,25 +6,25 @@
 #include "libcef/browser/osr/render_widget_host_view_osr.h"
 
 #include <stdint.h>
-
 #include <utility>
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 #include "libcef/browser/osr/osr_util.h"
 #include "libcef/browser/osr/synthetic_gesture_target_osr.h"
+#include "libcef/browser/osr/touch_selection_controller_client_osr.h"
 #include "libcef/browser/osr/video_consumer_osr.h"
 #include "libcef/browser/thread_util.h"
 
-#include "base/callback_helpers.h"
 #include "base/command_line.h"
+#include "base/functional/callback_helpers.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
 #include "cc/base/switches.h"
 #include "components/viz/common/features.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
 #include "components/viz/common/frame_sinks/delay_based_time_source.h"
+#include "components/viz/common/surfaces/frame_sink_id_allocator.h"
 #include "components/viz/common/switches.h"
 #include "content/browser/bad_message.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
@@ -37,8 +37,6 @@
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_input_event_router.h"
 #include "content/common/content_switches_internal.h"
-#include "content/common/input_messages.h"
-#include "content/common/view_messages.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/context_factory.h"
@@ -46,12 +44,14 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/common/content_switches.h"
 #include "media/base/video_frame.h"
+#include "media/capture/mojom/video_capture_buffer.mojom.h"
 #include "ui/compositor/compositor.h"
 #include "ui/events/blink/blink_event_util.h"
 #include "ui/events/gesture_detection/gesture_provider_config_helper.h"
 #include "ui/events/gesture_detection/motion_event.h"
 #include "ui/gfx/geometry/dip_util.h"
 #include "ui/gfx/geometry/size_conversions.h"
+#include "ui/touch_selection/touch_selection_controller.h"
 
 namespace {
 
@@ -61,8 +61,8 @@
 
 const float kDefaultScaleFactor = 1.0;
 
-content::ScreenInfo ScreenInfoFrom(const CefScreenInfo& src) {
-  content::ScreenInfo screenInfo;
+display::ScreenInfo ScreenInfoFrom(const CefScreenInfo& src) {
+  display::ScreenInfo screenInfo;
   screenInfo.device_scale_factor = src.device_scale_factor;
   screenInfo.depth = src.depth;
   screenInfo.depth_per_component = src.depth_per_component;
@@ -81,6 +81,10 @@
   explicit CefDelegatedFrameHostClient(CefRenderWidgetHostViewOSR* view)
       : view_(view) {}
 
+  CefDelegatedFrameHostClient(const CefDelegatedFrameHostClient&) = delete;
+  CefDelegatedFrameHostClient& operator=(const CefDelegatedFrameHostClient&) =
+      delete;
+
   ui::Layer* DelegatedFrameHostGetLayer() const override {
     return view_->GetRootLayer();
   }
@@ -95,14 +99,15 @@
     // may not match the page's, so use black as the gutter color to avoid
     // flashes of brighter colors during the transition.
     if (view_->render_widget_host()->delegate() &&
-        view_->render_widget_host()->delegate()->IsFullscreenForCurrentTab()) {
+        view_->render_widget_host()->delegate()->IsFullscreen()) {
       return SK_ColorBLACK;
     }
     return *view_->GetBackgroundColor();
   }
 
-  void OnFrameTokenChanged(uint32_t frame_token) override {
-    view_->render_widget_host()->DidProcessFrame(frame_token);
+  void OnFrameTokenChanged(uint32_t frame_token,
+                           base::TimeTicks activation_time) override {
+    view_->render_widget_host()->DidProcessFrame(frame_token, activation_time);
   }
 
   float GetDeviceScaleFactor() const override {
@@ -113,14 +118,14 @@
     return view_->render_widget_host()->CollectSurfaceIdsForEviction();
   }
 
-  void InvalidateLocalSurfaceIdOnEviction() override {}
+  void InvalidateLocalSurfaceIdOnEviction() override {
+    view_->InvalidateLocalSurfaceId();
+  }
 
   bool ShouldShowStaleContentOnEviction() override { return false; }
 
  private:
   CefRenderWidgetHostViewOSR* const view_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefDelegatedFrameHostClient);
 };
 
 ui::GestureProvider::Config CreateGestureProviderConfig() {
@@ -140,9 +145,10 @@
   return latency_info;
 }
 
-gfx::Rect GetViewBounds(CefBrowserHostImpl* browser) {
-  if (!browser)
+gfx::Rect GetViewBounds(AlloyBrowserHostImpl* browser) {
+  if (!browser) {
     return gfx::Rect();
+  }
 
   CefRect rc;
   CefRefPtr<CefRenderHandler> handler =
@@ -156,20 +162,6 @@
   return gfx::Rect(rc.x, rc.y, rc.width, rc.height);
 }
 
-float GetDeviceScaleFactor(CefBrowserHostImpl* browser) {
-  if (!browser)
-    return kDefaultScaleFactor;
-
-  CefScreenInfo screen_info(kDefaultScaleFactor, 0, 0, false, CefRect(),
-                            CefRect());
-  CefRefPtr<CefRenderHandler> handler = browser->client()->GetRenderHandler();
-  CHECK(handler);
-  if (!handler->GetScreenInfo(browser, screen_info))
-    return kDefaultScaleFactor;
-
-  return screen_info.device_scale_factor;
-}
-
 ui::ImeTextSpan::UnderlineStyle GetImeUnderlineStyle(
     cef_composition_underline_style_t style) {
   switch (style) {
@@ -183,12 +175,24 @@
       return ui::ImeTextSpan::UnderlineStyle::kNone;
   }
 
-  NOTREACHED();
+  DCHECK(false);
   return ui::ImeTextSpan::UnderlineStyle::kSolid;
 }
 
 }  // namespace
 
+// Logic copied from RenderWidgetHostViewAura::CreateSelectionController.
+void CefRenderWidgetHostViewOSR::CreateSelectionController() {
+  ui::TouchSelectionController::Config tsc_config;
+  tsc_config.max_tap_duration = base::Milliseconds(
+      ui::GestureConfiguration::GetInstance()->long_press_time_in_ms());
+  tsc_config.tap_slop = ui::GestureConfiguration::GetInstance()
+                            ->max_touch_move_in_pixels_for_click();
+  tsc_config.enable_longpress_drag_selection = false;
+  selection_controller_ = std::make_unique<ui::TouchSelectionController>(
+      selection_controller_client_.get(), tsc_config);
+}
+
 CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
     SkColor background_color,
     bool use_shared_texture,
@@ -207,14 +211,12 @@
   DCHECK(render_widget_host_);
   DCHECK(!render_widget_host_->GetView());
 
-  current_device_scale_factor_ = kDefaultScaleFactor;
-
   if (parent_host_view_) {
     browser_impl_ = parent_host_view_->browser_impl();
     DCHECK(browser_impl_);
   } else if (content::RenderViewHost::From(render_widget_host_)) {
-    // CefBrowserHostImpl might not be created at this time for popups.
-    browser_impl_ = CefBrowserHostImpl::GetBrowserForHost(
+    // AlloyBrowserHostImpl might not be created at this time for popups.
+    browser_impl_ = AlloyBrowserHostImpl::GetBrowserForHost(
         content::RenderViewHost::From(render_widget_host_));
   }
 
@@ -238,8 +240,8 @@
   // Matching the attributes from RecyclableCompositorMac.
   compositor_.reset(new ui::Compositor(
       context_factory->AllocateFrameSinkId(), context_factory,
-      base::ThreadTaskRunnerHandle::Get(), false /* enable_pixel_canvas */,
-      use_external_begin_frame));
+      base::SingleThreadTaskRunner::GetCurrentDefault(),
+      false /* enable_pixel_canvas */, use_external_begin_frame));
   compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
 
   compositor_->SetDelegate(this);
@@ -248,16 +250,18 @@
 
   content::RenderWidgetHostImpl* render_widget_host_impl =
       content::RenderWidgetHostImpl::From(render_widget_host_);
-  if (render_widget_host_impl)
+  if (render_widget_host_impl) {
     render_widget_host_impl->SetCompositorForFlingScheduler(compositor_.get());
+  }
 
   cursor_manager_.reset(new content::CursorManager(this));
 
   // This may result in a call to GetFrameSinkId().
   render_widget_host_->SetView(this);
 
-  if (GetTextInputManager())
+  if (GetTextInputManager()) {
     GetTextInputManager()->AddObserver(this);
+  }
 
   if (render_widget_host_->delegate() &&
       render_widget_host_->delegate()->GetInputEventRouter()) {
@@ -269,12 +273,35 @@
     // For child/popup views this will be called from the associated InitAs*()
     // method.
     SetRootLayerSize(false /* force */);
-    if (!render_widget_host_->is_hidden())
+    if (!render_widget_host_->is_hidden()) {
       Show();
+    }
   }
+
+  selection_controller_client_ =
+      std::make_unique<CefTouchSelectionControllerClientOSR>(this);
+  CreateSelectionController();
 }
 
 CefRenderWidgetHostViewOSR::~CefRenderWidgetHostViewOSR() {
+  ReleaseCompositor();
+  root_layer_.reset(nullptr);
+
+  DCHECK(!parent_host_view_);
+  DCHECK(!popup_host_view_);
+  DCHECK(!child_host_view_);
+  DCHECK(guest_host_views_.empty());
+
+  if (text_input_manager_) {
+    text_input_manager_->RemoveObserver(this);
+  }
+}
+
+void CefRenderWidgetHostViewOSR::ReleaseCompositor() {
+  if (!compositor_) {
+    return;  // already released
+  }
+
   // Marking the DelegatedFrameHost as removed from the window hierarchy is
   // necessary to remove all connections to its old ui::Compositor.
   if (is_showing_) {
@@ -285,15 +312,6 @@
 
   delegated_frame_host_.reset(nullptr);
   compositor_.reset(nullptr);
-  root_layer_.reset(nullptr);
-
-  DCHECK(!parent_host_view_);
-  DCHECK(!popup_host_view_);
-  DCHECK(!child_host_view_);
-  DCHECK(guest_host_views_.empty());
-
-  if (text_input_manager_)
-    text_input_manager_->RemoveObserver(this);
 }
 
 // Called for full-screen widgets.
@@ -335,12 +353,16 @@
 }
 
 bool CefRenderWidgetHostViewOSR::IsSurfaceAvailableForCopy() {
-  return delegated_frame_host_->CanCopyFromCompositingSurface();
+  return delegated_frame_host_
+             ? delegated_frame_host_->CanCopyFromCompositingSurface()
+             : false;
 }
 
-void CefRenderWidgetHostViewOSR::Show() {
-  if (is_showing_)
+void CefRenderWidgetHostViewOSR::ShowWithVisibility(
+    content::PageVisibilityState) {
+  if (is_showing_) {
     return;
+  }
 
   if (!content::GpuDataManagerImpl::GetInstance()->IsGpuCompositingDisabled() &&
       !browser_impl_ &&
@@ -350,36 +372,37 @@
 
   is_showing_ = true;
 
-  // If the viz::LocalSurfaceIdAllocation is invalid, we may have been evicted,
+  // If the viz::LocalSurfaceId is invalid, we may have been evicted,
   // and no other visual properties have since been changed. Allocate a new id
   // and start synchronizing.
-  if (!GetLocalSurfaceIdAllocation().IsValid()) {
+  if (!GetLocalSurfaceId().is_valid()) {
     AllocateLocalSurfaceId();
     SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
-                                GetLocalSurfaceIdAllocation());
+                                GetLocalSurfaceId());
   }
 
   if (render_widget_host_) {
     render_widget_host_->WasShown(
-        base::nullopt /* record_tab_switch_time_request */);
+        /*record_tab_switch_time_request=*/{});
+
+    // Call OnRenderFrameMetadataChangedAfterActivation for every frame.
+    auto provider = content::RenderWidgetHostImpl::From(render_widget_host_)
+                        ->render_frame_metadata_provider();
+    provider->AddObserver(this);
+    provider->ReportAllFrameSubmissionsForTesting(true);
   }
 
-  delegated_frame_host_->AttachToCompositor(compositor_.get());
-  delegated_frame_host_->WasShown(
-      GetLocalSurfaceIdAllocation().local_surface_id(), GetViewBounds().size(),
-      base::nullopt);
+  if (delegated_frame_host_) {
+    delegated_frame_host_->AttachToCompositor(compositor_.get());
+    delegated_frame_host_->WasShown(GetLocalSurfaceId(), GetViewBounds().size(),
+                                    /*record_tab_switch_time_request=*/{});
+  }
 
   if (!content::GpuDataManagerImpl::GetInstance()->IsGpuCompositingDisabled()) {
     // Start generating frames when we're visible and at the correct size.
     if (!video_consumer_) {
       video_consumer_.reset(new CefVideoConsumerOSR(this));
       UpdateFrameRate();
-
-      // Call OnRenderFrameMetadataChangedAfterActivation for every frame.
-      content::RenderFrameMetadataProviderImpl* provider =
-          content::RenderWidgetHostImpl::From(render_widget_host_)
-              ->render_frame_metadata_provider();
-      provider->ReportAllFrameSubmissionsForTesting(true);
     } else {
       video_consumer_->SetActive(true);
     }
@@ -387,24 +410,37 @@
 }
 
 void CefRenderWidgetHostViewOSR::Hide() {
-  if (!is_showing_)
+  if (!is_showing_) {
     return;
+  }
 
   is_showing_ = false;
 
-  if (browser_impl_.get())
+  if (browser_impl_) {
     browser_impl_->CancelContextMenu();
+  }
+
+  if (selection_controller_client_) {
+    selection_controller_client_->CloseQuickMenuAndHideHandles();
+  }
 
   if (video_consumer_) {
     video_consumer_->SetActive(false);
   }
 
-  if (render_widget_host_)
+  if (render_widget_host_) {
     render_widget_host_->WasHidden();
 
-  delegated_frame_host_->WasHidden(
-      content::DelegatedFrameHost::HiddenCause::kOther);
-  delegated_frame_host_->DetachFromCompositor();
+    auto provider = content::RenderWidgetHostImpl::From(render_widget_host_)
+                        ->render_frame_metadata_provider();
+    provider->RemoveObserver(this);
+  }
+
+  if (delegated_frame_host_) {
+    delegated_frame_host_->WasHidden(
+        content::DelegatedFrameHost::HiddenCause::kOther);
+    delegated_frame_host_->DetachFromCompositor();
+  }
 }
 
 bool CefRenderWidgetHostViewOSR::IsShowing() {
@@ -414,12 +450,18 @@
 void CefRenderWidgetHostViewOSR::EnsureSurfaceSynchronizedForWebTest() {
   ++latest_capture_sequence_number_;
   SynchronizeVisualProperties(cc::DeadlinePolicy::UseInfiniteDeadline(),
-                              base::nullopt);
+                              absl::nullopt);
+}
+
+content::TouchSelectionControllerClientManager*
+CefRenderWidgetHostViewOSR::GetTouchSelectionControllerClientManager() {
+  return selection_controller_client_.get();
 }
 
 gfx::Rect CefRenderWidgetHostViewOSR::GetViewBounds() {
-  if (IsPopupWidget())
+  if (IsPopupWidget()) {
     return popup_position_;
+  }
 
   return current_view_bounds_;
 }
@@ -434,12 +476,22 @@
   content::RenderWidgetHostViewBase::SetBackgroundColor(color);
 }
 
-base::Optional<SkColor> CefRenderWidgetHostViewOSR::GetBackgroundColor() {
+absl::optional<SkColor> CefRenderWidgetHostViewOSR::GetBackgroundColor() {
   return background_color_;
 }
 
 void CefRenderWidgetHostViewOSR::UpdateBackgroundColor() {}
 
+absl::optional<content::DisplayFeature>
+CefRenderWidgetHostViewOSR::GetDisplayFeature() {
+  return absl::nullopt;
+}
+
+void CefRenderWidgetHostViewOSR::SetDisplayFeatureForTesting(
+    const content::DisplayFeature* display_feature) {
+  DCHECK(false);
+}
+
 blink::mojom::PointerLockResult CefRenderWidgetHostViewOSR::LockMouse(
     bool request_unadjusted_movement) {
   return blink::mojom::PointerLockResult::kPermissionDenied;
@@ -463,7 +515,6 @@
     delegated_frame_host_->TakeFallbackContentFrom(
         view_cef->delegated_frame_host_.get());
   }
-  host()->GetContentRenderingTimeoutFrom(view_cef->host());
 }
 
 void CefRenderWidgetHostViewOSR::OnPresentCompositorFrame() {}
@@ -475,11 +526,10 @@
     // viz::LocalSurfaceId. However we do not want to embed surfaces while
     // hidden. Nor do we want to embed invalid ids when we are evicted. Becoming
     // visible will generate a new id, if necessary, and begin embedding.
-    UpdateLocalSurfaceIdFromEmbeddedClient(
-        metadata.local_surface_id_allocation);
+    UpdateLocalSurfaceIdFromEmbeddedClient(metadata.local_surface_id);
   } else {
     SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
-                                metadata.local_surface_id_allocation);
+                                metadata.local_surface_id);
   }
 }
 
@@ -491,33 +541,34 @@
   parent_local_surface_id_allocator_->GenerateId();
 }
 
-const viz::LocalSurfaceIdAllocation&
-CefRenderWidgetHostViewOSR::GetCurrentLocalSurfaceIdAllocation() const {
-  return parent_local_surface_id_allocator_
-      ->GetCurrentLocalSurfaceIdAllocation();
+const viz::LocalSurfaceId&
+CefRenderWidgetHostViewOSR::GetCurrentLocalSurfaceId() const {
+  return parent_local_surface_id_allocator_->GetCurrentLocalSurfaceId();
 }
 
 void CefRenderWidgetHostViewOSR::UpdateLocalSurfaceIdFromEmbeddedClient(
-    const base::Optional<viz::LocalSurfaceIdAllocation>&
-        embedded_client_local_surface_id_allocation) {
-  if (embedded_client_local_surface_id_allocation) {
+    const absl::optional<viz::LocalSurfaceId>&
+        embedded_client_local_surface_id) {
+  if (embedded_client_local_surface_id) {
     parent_local_surface_id_allocator_->UpdateFromChild(
-        *embedded_client_local_surface_id_allocation);
+        *embedded_client_local_surface_id);
   } else {
     AllocateLocalSurfaceId();
   }
 }
 
-const viz::LocalSurfaceIdAllocation&
-CefRenderWidgetHostViewOSR::GetOrCreateLocalSurfaceIdAllocation() {
-  if (!parent_local_surface_id_allocator_)
+const viz::LocalSurfaceId&
+CefRenderWidgetHostViewOSR::GetOrCreateLocalSurfaceId() {
+  if (!parent_local_surface_id_allocator_) {
     AllocateLocalSurfaceId();
-  return GetCurrentLocalSurfaceIdAllocation();
+  }
+  return GetCurrentLocalSurfaceId();
 }
 
 void CefRenderWidgetHostViewOSR::InvalidateLocalSurfaceId() {
-  if (!parent_local_surface_id_allocator_)
+  if (!parent_local_surface_id_allocator_) {
     return;
+  }
   parent_local_surface_id_allocator_->Invalidate();
 }
 
@@ -537,13 +588,27 @@
   damage_rects_[sequence] = rect;
 }
 
+void CefRenderWidgetHostViewOSR::InvalidateLocalSurfaceIdAndAllocationGroup() {
+  InvalidateLocalSurfaceId();
+}
+
+void CefRenderWidgetHostViewOSR::ClearFallbackSurfaceForCommitPending() {
+  if (delegated_frame_host_) {
+    delegated_frame_host_->ClearFallbackSurfaceForCommitPending();
+  }
+  InvalidateLocalSurfaceId();
+}
+
 void CefRenderWidgetHostViewOSR::ResetFallbackToFirstNavigationSurface() {
-  delegated_frame_host_->ResetFallbackToFirstNavigationSurface();
+  if (delegated_frame_host_) {
+    delegated_frame_host_->ResetFallbackToFirstNavigationSurface();
+  }
 }
 
 void CefRenderWidgetHostViewOSR::InitAsPopup(
     content::RenderWidgetHostView* parent_host_view,
-    const gfx::Rect& pos) {
+    const gfx::Rect& bounds,
+    const gfx::Rect& anchor_rect) {
   DCHECK_EQ(parent_host_view_, parent_host_view);
   DCHECK(browser_impl_);
 
@@ -562,16 +627,17 @@
 
   CefRect view_rect;
   handler->GetViewRect(browser_impl_.get(), view_rect);
-  gfx::Rect client_pos(pos.x() - view_rect.x, pos.y() - view_rect.y,
-                       pos.width(), pos.height());
+  gfx::Rect client_pos(bounds.x() - view_rect.x, bounds.y() - view_rect.y,
+                       bounds.width(), bounds.height());
 
   popup_position_ = client_pos;
 
   CefRect widget_pos(client_pos.x(), client_pos.y(), client_pos.width(),
                      client_pos.height());
 
-  if (handler.get())
+  if (handler.get()) {
     handler->OnPopupSize(browser_impl_.get(), widget_pos);
+  }
 
   // The size doesn't change for popups so we need to force the
   // initialization.
@@ -579,68 +645,16 @@
   Show();
 }
 
-void CefRenderWidgetHostViewOSR::InitAsFullscreen(
-    content::RenderWidgetHostView* reference_host_view) {
-  NOTREACHED() << "Fullscreen widgets are not supported in OSR";
-}
-
-void CefRenderWidgetHostViewOSR::UpdateCursor(
-    const content::WebCursor& cursor) {
-  TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::UpdateCursor");
-  if (!browser_impl_.get())
-    return;
-
-  CefRefPtr<CefRenderHandler> handler =
-      browser_impl_->GetClient()->GetRenderHandler();
-  CHECK(handler);
-
-  const auto& ui_cursor = cursor.cursor();
-
-  const cef_cursor_type_t cursor_type =
-      static_cast<cef_cursor_type_t>(ui_cursor.type());
-  CefCursorInfo custom_cursor_info;
-  if (ui_cursor.type() == ui::mojom::CursorType::kCustom) {
-    custom_cursor_info.hotspot.x = ui_cursor.custom_hotspot().x();
-    custom_cursor_info.hotspot.y = ui_cursor.custom_hotspot().y();
-    custom_cursor_info.image_scale_factor = ui_cursor.image_scale_factor();
-    custom_cursor_info.buffer = ui_cursor.custom_bitmap().getPixels();
-    custom_cursor_info.size.width = ui_cursor.custom_bitmap().width();
-    custom_cursor_info.size.height = ui_cursor.custom_bitmap().height();
-  }
-
-#if defined(USE_AURA)
-  content::WebCursor web_cursor(ui_cursor);
-
-  ui::PlatformCursor platform_cursor;
-  if (ui_cursor.type() == ui::mojom::CursorType::kCustom) {
-    // |web_cursor| owns the resulting |platform_cursor|.
-    platform_cursor = web_cursor.GetPlatformCursor(ui_cursor);
-  } else {
-    platform_cursor = GetPlatformCursor(ui_cursor.type());
-  }
-
-  handler->OnCursorChange(browser_impl_.get(), platform_cursor, cursor_type,
-                          custom_cursor_info);
-#elif defined(OS_MACOSX)
-  // |web_cursor| owns the resulting |native_cursor|.
-  content::WebCursor web_cursor(cursor);
-  CefCursorHandle native_cursor = web_cursor.GetNativeCursor();
-  handler->OnCursorChange(browser_impl_.get(), native_cursor, cursor_type,
-                          custom_cursor_info);
-#else
-  // TODO(port): Implement this method to work on other platforms as part of
-  // off-screen rendering support.
-  NOTREACHED();
-#endif
-}
+void CefRenderWidgetHostViewOSR::UpdateCursor(const ui::Cursor& cursor) {}
 
 content::CursorManager* CefRenderWidgetHostViewOSR::GetCursorManager() {
   return cursor_manager_.get();
 }
 
 void CefRenderWidgetHostViewOSR::SetIsLoading(bool is_loading) {
-  if (!is_loading)
+  if (!is_loading) {
     return;
+  }
   // Make sure gesture detection is fresh.
   gesture_provider_.ResetDetection();
   forward_touch_to_popup_ = false;
@@ -657,16 +671,19 @@
     if (has_parent_) {
       CancelWidget();
     } else {
-      if (popup_host_view_)
+      if (popup_host_view_) {
         popup_host_view_->CancelWidget();
-      if (child_host_view_)
+      }
+      if (child_host_view_) {
         child_host_view_->CancelWidget();
+      }
       if (!guest_host_views_.empty()) {
         // Guest RWHVs will be destroyed when the associated RWHVGuest is
         // destroyed. This parent RWHV may be destroyed first, so disassociate
         // the guest RWHVs here without destroying them.
-        for (auto guest_host_view : guest_host_views_)
+        for (auto guest_host_view : guest_host_views_) {
           guest_host_view->parent_host_view_ = nullptr;
+        }
         guest_host_views_.clear();
       }
       Hide();
@@ -676,10 +693,11 @@
   delete this;
 }
 
-void CefRenderWidgetHostViewOSR::SetTooltipText(
-    const base::string16& tooltip_text) {
-  if (!browser_impl_.get())
+void CefRenderWidgetHostViewOSR::UpdateTooltipUnderCursor(
+    const std::u16string& tooltip_text) {
+  if (!browser_impl_.get()) {
     return;
+  }
 
   CefString tooltip(tooltip_text);
   CefRefPtr<CefDisplayHandler> handler =
@@ -691,7 +709,7 @@
 
 gfx::Size CefRenderWidgetHostViewOSR::GetCompositorViewportPixelSize() {
   return gfx::ScaleToCeiledSize(GetRequestedRendererSize(),
-                                current_device_scale_factor_);
+                                GetDeviceScaleFactor());
 }
 
 uint32_t CefRenderWidgetHostViewOSR::GetCaptureSequenceNumber() const {
@@ -702,62 +720,69 @@
     const gfx::Rect& src_rect,
     const gfx::Size& output_size,
     base::OnceCallback<void(const SkBitmap&)> callback) {
-  delegated_frame_host_->CopyFromCompositingSurface(src_rect, output_size,
-                                                    std::move(callback));
+  if (delegated_frame_host_) {
+    delegated_frame_host_->CopyFromCompositingSurface(src_rect, output_size,
+                                                      std::move(callback));
+  }
 }
 
-void CefRenderWidgetHostViewOSR::GetScreenInfo(content::ScreenInfo* results) {
-  if (!browser_impl_.get())
-    return;
+display::ScreenInfos CefRenderWidgetHostViewOSR::GetNewScreenInfosForUpdate() {
+  display::ScreenInfo display_screen_info;
 
-  CefScreenInfo screen_info(kDefaultScaleFactor, 0, 0, false, CefRect(),
-                            CefRect());
+  if (browser_impl_) {
+    CefScreenInfo screen_info(kDefaultScaleFactor, 0, 0, false, CefRect(),
+                              CefRect());
 
-  CefRefPtr<CefRenderHandler> handler =
-      browser_impl_->client()->GetRenderHandler();
-  CHECK(handler);
-  if (!handler->GetScreenInfo(browser_impl_.get(), screen_info) ||
-      screen_info.rect.width == 0 || screen_info.rect.height == 0 ||
-      screen_info.available_rect.width == 0 ||
-      screen_info.available_rect.height == 0) {
-    // If a screen rectangle was not provided, try using the view rectangle
-    // instead. Otherwise, popup views may be drawn incorrectly, or not at
-    // all.
-    CefRect screenRect;
-    handler->GetViewRect(browser_impl_.get(), screenRect);
-    CHECK_GT(screenRect.width, 0);
-    CHECK_GT(screenRect.height, 0);
-
-    if (screen_info.rect.width == 0 || screen_info.rect.height == 0) {
-      screen_info.rect = screenRect;
-    }
-
-    if (screen_info.available_rect.width == 0 ||
+    CefRefPtr<CefRenderHandler> handler =
+        browser_impl_->client()->GetRenderHandler();
+    CHECK(handler);
+    if (!handler->GetScreenInfo(browser_impl_.get(), screen_info) ||
+        screen_info.rect.width == 0 || screen_info.rect.height == 0 ||
+        screen_info.available_rect.width == 0 ||
         screen_info.available_rect.height == 0) {
-      screen_info.available_rect = screenRect;
+      // If a screen rectangle was not provided, try using the view rectangle
+      // instead. Otherwise, popup views may be drawn incorrectly, or not at
+      // all.
+      CefRect screenRect;
+      handler->GetViewRect(browser_impl_.get(), screenRect);
+      CHECK_GT(screenRect.width, 0);
+      CHECK_GT(screenRect.height, 0);
+
+      if (screen_info.rect.width == 0 || screen_info.rect.height == 0) {
+        screen_info.rect = screenRect;
+      }
+
+      if (screen_info.available_rect.width == 0 ||
+          screen_info.available_rect.height == 0) {
+        screen_info.available_rect = screenRect;
+      }
     }
+
+    display_screen_info = ScreenInfoFrom(screen_info);
   }
 
-  *results = ScreenInfoFrom(screen_info);
+  return display::ScreenInfos(display_screen_info);
 }
 
 void CefRenderWidgetHostViewOSR::TransformPointToRootSurface(
     gfx::PointF* point) {}
 
 gfx::Rect CefRenderWidgetHostViewOSR::GetBoundsInRootWindow() {
-  if (!browser_impl_.get())
+  if (!browser_impl_.get()) {
     return gfx::Rect();
+  }
 
   CefRect rc;
   CefRefPtr<CefRenderHandler> handler =
       browser_impl_->client()->GetRenderHandler();
   CHECK(handler);
-  if (handler->GetRootScreenRect(browser_impl_.get(), rc))
+  if (handler->GetRootScreenRect(browser_impl_.get(), rc)) {
     return gfx::Rect(rc.x, rc.y, rc.width, rc.height);
+  }
   return GetViewBounds();
 }
 
-#if !defined(OS_MACOSX)
+#if !BUILDFLAG(IS_MAC)
 viz::ScopedSurfaceIdAllocator
 CefRenderWidgetHostViewOSR::DidUpdateVisualProperties(
     const cc::RenderFrameMetadata& metadata) {
@@ -773,21 +798,15 @@
                                : viz::SurfaceId();
 }
 
-content::BrowserAccessibilityManager*
-CefRenderWidgetHostViewOSR::CreateBrowserAccessibilityManager(
-    content::BrowserAccessibilityDelegate* delegate,
-    bool for_root_frame) {
-  return nullptr;
-}
-
 void CefRenderWidgetHostViewOSR::ImeSetComposition(
     const CefString& text,
     const std::vector<CefCompositionUnderline>& underlines,
     const CefRange& replacement_range,
     const CefRange& selection_range) {
   TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::ImeSetComposition");
-  if (!render_widget_host_)
+  if (!render_widget_host_) {
     return;
+  }
 
   std::vector<ui::ImeTextSpan> web_underlines;
   web_underlines.reserve(underlines.size());
@@ -813,8 +832,9 @@
     const CefRange& replacement_range,
     int relative_cursor_pos) {
   TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::ImeCommitText");
-  if (!render_widget_host_)
+  if (!render_widget_host_) {
     return;
+  }
 
   gfx::Range range(replacement_range.from, replacement_range.to);
   render_widget_host_->ImeCommitText(text, std::vector<ui::ImeTextSpan>(),
@@ -826,8 +846,9 @@
 
 void CefRenderWidgetHostViewOSR::ImeFinishComposingText(bool keep_selection) {
   TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::ImeFinishComposingText");
-  if (!render_widget_host_)
+  if (!render_widget_host_) {
     return;
+  }
 
   render_widget_host_->ImeFinishComposingText(keep_selection);
 
@@ -837,8 +858,9 @@
 
 void CefRenderWidgetHostViewOSR::ImeCancelComposition() {
   TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::ImeCancelComposition");
-  if (!render_widget_host_)
+  if (!render_widget_host_) {
     return;
+  }
 
   render_widget_host_->ImeCancelComposition();
 
@@ -846,20 +868,22 @@
   RequestImeCompositionUpdate(false);
 }
 
-void CefRenderWidgetHostViewOSR::SelectionChanged(const base::string16& text,
+void CefRenderWidgetHostViewOSR::SelectionChanged(const std::u16string& text,
                                                   size_t offset,
                                                   const gfx::Range& range) {
   RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
 
-  if (!browser_impl_.get())
+  if (!browser_impl_.get()) {
     return;
+  }
 
   CefString selected_text;
   if (!range.is_empty() && !text.empty()) {
     size_t pos = range.GetMin() - offset;
     size_t n = range.length();
-    if (pos + n <= text.length())
+    if (pos + n <= text.length()) {
       selected_text = text.substr(pos, n);
+    }
   }
 
   CefRefPtr<CefRenderHandler> handler =
@@ -871,28 +895,43 @@
                                   cef_range);
 }
 
-const viz::LocalSurfaceIdAllocation&
-CefRenderWidgetHostViewOSR::GetLocalSurfaceIdAllocation() const {
+const viz::LocalSurfaceId& CefRenderWidgetHostViewOSR::GetLocalSurfaceId()
+    const {
   return const_cast<CefRenderWidgetHostViewOSR*>(this)
-      ->GetOrCreateLocalSurfaceIdAllocation();
+      ->GetOrCreateLocalSurfaceId();
 }
 
 const viz::FrameSinkId& CefRenderWidgetHostViewOSR::GetFrameSinkId() const {
-  return delegated_frame_host_->frame_sink_id();
+  return delegated_frame_host_
+             ? delegated_frame_host_->frame_sink_id()
+             : viz::FrameSinkIdAllocator::InvalidFrameSinkId();
 }
 
 viz::FrameSinkId CefRenderWidgetHostViewOSR::GetRootFrameSinkId() {
-  return compositor_->frame_sink_id();
+  return compositor_ ? compositor_->frame_sink_id() : viz::FrameSinkId();
 }
 
-void CefRenderWidgetHostViewOSR::OnRenderFrameMetadataChangedAfterActivation() {
-  if (video_consumer_) {
-    // Need to wait for the first frame of the new size before calling
-    // SizeChanged. Otherwise, the video frame will be letterboxed.
-    auto metadata =
-        host_->render_frame_metadata_provider()->LastRenderFrameMetadata();
-    video_consumer_->SizeChanged(metadata.viewport_size_in_pixels);
-  }
+void CefRenderWidgetHostViewOSR::NotifyHostAndDelegateOnWasShown(
+    blink::mojom::RecordContentToVisibleTimeRequestPtr visible_time_request) {
+  // We don't call RenderWidgetHostViewBase::OnShowWithPageVisibility, so this
+  // method should not be called.
+  DCHECK(false);
+}
+
+void CefRenderWidgetHostViewOSR::
+    RequestSuccessfulPresentationTimeFromHostOrDelegate(
+        blink::mojom::RecordContentToVisibleTimeRequestPtr
+            visible_time_request) {
+  // We don't call RenderWidgetHostViewBase::OnShowWithPageVisibility, so this
+  // method should not be called.
+  DCHECK(false);
+}
+
+void CefRenderWidgetHostViewOSR::
+    CancelSuccessfulPresentationTimeRequestForHostAndDelegate() {
+  // We don't call RenderWidgetHostViewBase::OnShowWithPageVisibility, so this
+  // method should not be called.
+  DCHECK(false);
 }
 
 std::unique_ptr<content::SyntheticGestureTarget>
@@ -924,20 +963,62 @@
       // The first navigation does not need a new LocalSurfaceID. The renderer
       // can use the ID that was already provided.
       SynchronizeVisualProperties(cc::DeadlinePolicy::UseExistingDeadline(),
-                                  GetLocalSurfaceIdAllocation());
+                                  GetLocalSurfaceId());
     } else {
       SynchronizeVisualProperties(cc::DeadlinePolicy::UseExistingDeadline(),
-                                  base::nullopt);
+                                  absl::nullopt);
     }
   }
-  if (delegated_frame_host_)
+  if (delegated_frame_host_) {
     delegated_frame_host_->DidNavigate();
+  }
   is_first_navigation_ = false;
 }
 
 void CefRenderWidgetHostViewOSR::OnFrameComplete(
     const viz::BeginFrameAck& ack) {
-  // TODO(cef): is there something we need to track with this notification?
+  DCHECK(begin_frame_pending_);
+  DCHECK_EQ(begin_frame_source_.source_id(), ack.frame_id.source_id);
+  DCHECK_EQ(begin_frame_number_, ack.frame_id.sequence_number);
+  begin_frame_pending_ = false;
+}
+
+void CefRenderWidgetHostViewOSR::OnRenderFrameMetadataChangedAfterActivation(
+    base::TimeTicks activation_time) {
+  auto metadata =
+      host_->render_frame_metadata_provider()->LastRenderFrameMetadata();
+
+  if (video_consumer_) {
+    // Need to wait for the first frame of the new size before calling
+    // SizeChanged. Otherwise, the video frame will be letterboxed.
+    video_consumer_->SizeChanged(metadata.viewport_size_in_pixels);
+  }
+
+  gfx::PointF root_scroll_offset;
+  if (metadata.root_scroll_offset) {
+    root_scroll_offset = *metadata.root_scroll_offset;
+  }
+  if (root_scroll_offset != last_scroll_offset_) {
+    last_scroll_offset_ = root_scroll_offset;
+
+    if (!is_scroll_offset_changed_pending_) {
+      is_scroll_offset_changed_pending_ = true;
+
+      // Send the notification asynchronously.
+      CEF_POST_TASK(
+          CEF_UIT,
+          base::BindOnce(&CefRenderWidgetHostViewOSR::OnScrollOffsetChanged,
+                         weak_ptr_factory_.GetWeakPtr()));
+    }
+  }
+
+  if (metadata.selection.start != selection_start_ ||
+      metadata.selection.end != selection_end_) {
+    selection_start_ = metadata.selection.start;
+    selection_end_ = metadata.selection.end;
+    selection_controller_client_->UpdateClientSelectionBounds(selection_start_,
+                                                              selection_end_);
+  }
 }
 
 std::unique_ptr<viz::HostDisplayClient>
@@ -962,42 +1043,41 @@
 void CefRenderWidgetHostViewOSR::WasResized() {
   // Only one resize will be in-flight at a time.
   if (hold_resize_) {
-    if (!pending_resize_)
+    if (!pending_resize_) {
       pending_resize_ = true;
+    }
     return;
   }
 
   SynchronizeVisualProperties(cc::DeadlinePolicy::UseExistingDeadline(),
-                              base::nullopt);
+                              absl::nullopt);
 }
 
 void CefRenderWidgetHostViewOSR::SynchronizeVisualProperties(
     const cc::DeadlinePolicy& deadline_policy,
-    const base::Optional<viz::LocalSurfaceIdAllocation>&
-        child_local_surface_id_allocation) {
+    const absl::optional<viz::LocalSurfaceId>& child_local_surface_id) {
   SetFrameRate();
 
   const bool resized = ResizeRootLayer();
   bool surface_id_updated = false;
 
-  if (!resized && child_local_surface_id_allocation) {
+  if (!resized && child_local_surface_id) {
     // Update the current surface ID.
     parent_local_surface_id_allocator_->UpdateFromChild(
-        *child_local_surface_id_allocation);
+        *child_local_surface_id);
     surface_id_updated = true;
   }
 
   // Allocate a new surface ID if the surface has been resized or if the current
   // ID is invalid (meaning we may have been evicted).
-  if (resized || !GetCurrentLocalSurfaceIdAllocation().IsValid()) {
+  if (resized || !GetCurrentLocalSurfaceId().is_valid()) {
     AllocateLocalSurfaceId();
     surface_id_updated = true;
   }
 
   if (surface_id_updated) {
     delegated_frame_host_->EmbedSurface(
-        GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
-        GetViewBounds().size(), deadline_policy);
+        GetCurrentLocalSurfaceId(), GetViewBounds().size(), deadline_policy);
 
     // |render_widget_host_| will retrieve resize parameters from the
     // DelegatedFrameHost and this view, so SynchronizeVisualProperties must be
@@ -1010,16 +1090,19 @@
 
 void CefRenderWidgetHostViewOSR::OnScreenInfoChanged() {
   TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::OnScreenInfoChanged");
-  if (!render_widget_host_)
+  InvalidateLocalSurfaceId();
+  if (!render_widget_host_) {
     return;
+  }
 
   SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
-                              base::nullopt);
+                              absl::nullopt);
 
-  if (render_widget_host_->delegate())
+  if (render_widget_host_->delegate()) {
     render_widget_host_->delegate()->SendScreenRects();
-  else
+  } else {
     render_widget_host_->SendScreenRects();
+  }
 
   render_widget_host_->NotifyScreenInfoChanged();
 
@@ -1028,16 +1111,18 @@
   // renderer in the rwhv_aura (current_cursor_.SetScaleFactor)
 
   // Notify the guest hosts if any.
-  for (auto guest_host_view : guest_host_views_)
+  for (auto guest_host_view : guest_host_views_) {
     guest_host_view->OnScreenInfoChanged();
+  }
 }
 
 void CefRenderWidgetHostViewOSR::Invalidate(
     CefBrowserHost::PaintElementType type) {
   TRACE_EVENT1("cef", "CefRenderWidgetHostViewOSR::Invalidate", "type", type);
   if (!IsPopupWidget() && type == PET_POPUP) {
-    if (popup_host_view_)
+    if (popup_host_view_) {
       popup_host_view_->Invalidate(type);
+    }
     return;
   }
   InvalidateInternal(gfx::Rect(SizeInPixels()));
@@ -1046,25 +1131,34 @@
 void CefRenderWidgetHostViewOSR::SendExternalBeginFrame() {
   DCHECK(external_begin_frame_enabled_);
 
+  if (begin_frame_pending_) {
+    return;
+  }
+  begin_frame_pending_ = true;
+
   base::TimeTicks frame_time = base::TimeTicks::Now();
   base::TimeTicks deadline = base::TimeTicks();
   base::TimeDelta interval = viz::BeginFrameArgs::DefaultInterval();
 
   viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
       BEGINFRAME_FROM_HERE, begin_frame_source_.source_id(),
-      begin_frame_number_, frame_time, deadline, interval,
+      ++begin_frame_number_, frame_time, deadline, interval,
       viz::BeginFrameArgs::NORMAL);
 
   DCHECK(begin_frame_args.IsValid());
-  begin_frame_number_++;
 
-  if (render_widget_host_)
+  if (render_widget_host_) {
     render_widget_host_->ProgressFlingIfNeeded(frame_time);
+  }
 
-  compositor_->IssueExternalBeginFrame(
-      begin_frame_args, /* force= */ true,
-      base::BindOnce(&CefRenderWidgetHostViewOSR::OnFrameComplete,
-                     weak_ptr_factory_.GetWeakPtr()));
+  if (compositor_) {
+    compositor_->IssueExternalBeginFrame(
+        begin_frame_args, /* force= */ true,
+        base::BindOnce(&CefRenderWidgetHostViewOSR::OnFrameComplete,
+                       weak_ptr_factory_.GetWeakPtr()));
+  } else {
+    begin_frame_pending_ = false;
+  }
 
   if (!IsPopupWidget() && popup_host_view_) {
     popup_host_view_->SendExternalBeginFrame();
@@ -1076,6 +1170,10 @@
   TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::SendKeyEvent");
   content::RenderWidgetHostImpl* target_host = render_widget_host_;
 
+  if (selection_controller_client_) {
+    selection_controller_client_->CloseQuickMenuAndHideHandles();
+  }
+
   // If there are multiple widgets on the page (such as when there are
   // out-of-process iframes), pick the one that should process this event.
   if (render_widget_host_ && render_widget_host_->delegate()) {
@@ -1086,11 +1184,12 @@
   if (target_host && target_host->GetView()) {
     // Direct routing requires that events go directly to the View.
     target_host->ForwardKeyboardEventWithLatencyInfo(
-        event, ui::LatencyInfo(event.GetType() == blink::WebInputEvent::kChar ||
-                                       event.GetType() ==
-                                           blink::WebInputEvent::kRawKeyDown
-                                   ? ui::SourceEventType::KEY_PRESS
-                                   : ui::SourceEventType::OTHER));
+        event,
+        ui::LatencyInfo(event.GetType() == blink::WebInputEvent::Type::kChar ||
+                                event.GetType() ==
+                                    blink::WebInputEvent::Type::kRawKeyDown
+                            ? ui::SourceEventType::KEY_PRESS
+                            : ui::SourceEventType::OTHER));
   }
 }
 
@@ -1098,11 +1197,16 @@
     const blink::WebMouseEvent& event) {
   TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::SendMouseEvent");
   if (!IsPopupWidget()) {
-    if (browser_impl_.get() &&
-        event.GetType() == blink::WebMouseEvent::kMouseDown) {
+    if (browser_impl_ &&
+        event.GetType() == blink::WebMouseEvent::Type::kMouseDown &&
+        event.button != blink::WebPointerProperties::Button::kRight) {
       browser_impl_->CancelContextMenu();
     }
 
+    if (selection_controller_client_) {
+      selection_controller_client_->CloseQuickMenuAndHideHandles();
+    }
+
     if (popup_host_view_) {
       if (popup_host_view_->popup_position_.Contains(
               event.PositionInWidget().x(), event.PositionInWidget().y())) {
@@ -1162,8 +1266,13 @@
   TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::SendMouseWheelEvent");
 
   if (!IsPopupWidget()) {
-    if (browser_impl_.get())
+    if (browser_impl_) {
       browser_impl_->CancelContextMenu();
+    }
+
+    if (selection_controller_client_) {
+      selection_controller_client_->CloseQuickMenuAndHideHandles();
+    }
 
     if (popup_host_view_) {
       if (popup_host_view_->popup_position_.Contains(
@@ -1186,8 +1295,8 @@
         // some other callback.
         CEF_POST_TASK(
             CEF_UIT,
-            base::Bind(&CefRenderWidgetHostViewOSR::CancelWidget,
-                       popup_host_view_->weak_ptr_factory_.GetWeakPtr()));
+            base::BindOnce(&CefRenderWidgetHostViewOSR::CancelWidget,
+                           popup_host_view_->weak_ptr_factory_.GetWeakPtr()));
       }
     } else if (!guest_host_views_.empty()) {
       for (auto guest_host_view : guest_host_views_) {
@@ -1254,8 +1363,14 @@
   }
 
   // Update the touch event first.
-  if (!pointer_state_.OnTouch(event))
+  if (!pointer_state_.OnTouch(event)) {
     return;
+  }
+
+  if (selection_controller_->WillHandleTouchEvent(pointer_state_)) {
+    pointer_state_.CleanupRemovedTouchPoints(event);
+    return;
+  }
 
   ui::FilteredGestureProvider::TouchHandlingResult result =
       gesture_provider_.OnTouchEvent(pointer_state_);
@@ -1267,11 +1382,13 @@
 
   // Set unchanged touch point to StateStationary for touchmove and
   // touchcancel to make sure only send one ack per WebTouchEvent.
-  if (!result.succeeded)
+  if (!result.succeeded) {
     pointer_state_.MarkUnchangedTouchPointsAsStationary(&touch_event, event);
+  }
 
-  if (!render_widget_host_)
+  if (!render_widget_host_) {
     return;
+  }
 
   ui::LatencyInfo latency_info = CreateLatencyInfo(touch_event);
   if (ShouldRouteEvents()) {
@@ -1282,8 +1399,9 @@
                                                           latency_info);
   }
 
-  bool touch_end = touch_event.GetType() == blink::WebInputEvent::kTouchEnd ||
-                   touch_event.GetType() == blink::WebInputEvent::kTouchCancel;
+  bool touch_end =
+      touch_event.GetType() == blink::WebInputEvent::Type::kTouchEnd ||
+      touch_event.GetType() == blink::WebInputEvent::Type::kTouchCancel;
 
   if (touch_end && IsPopupWidget() && parent_host_view_ &&
       parent_host_view_->popup_host_view_ == this) {
@@ -1292,13 +1410,14 @@
 }
 
 bool CefRenderWidgetHostViewOSR::ShouldRouteEvents() const {
-  if (!render_widget_host_->delegate())
+  if (!render_widget_host_->delegate()) {
     return false;
+  }
 
   // Do not route events that are currently targeted to page popups such as
   // <select> element drop-downs, since these cannot contain cross-process
   // frames.
-  if (!render_widget_host_->delegate()->IsWidgetForMainFrame(
+  if (!render_widget_host_->delegate()->IsWidgetForPrimaryMainFrame(
           render_widget_host_)) {
     return false;
   }
@@ -1306,9 +1425,10 @@
   return !!render_widget_host_->delegate()->GetInputEventRouter();
 }
 
-void CefRenderWidgetHostViewOSR::SendFocusEvent(bool focus) {
-  if (!render_widget_host_)
+void CefRenderWidgetHostViewOSR::SetFocus(bool focus) {
+  if (!render_widget_host_) {
     return;
+  }
 
   content::RenderWidgetHostImpl* widget =
       content::RenderWidgetHostImpl::From(render_widget_host_);
@@ -1316,8 +1436,13 @@
     widget->GotFocus();
     widget->SetActive(true);
   } else {
-    if (browser_impl_.get())
+    if (browser_impl_) {
       browser_impl_->CancelContextMenu();
+    }
+
+    if (selection_controller_client_) {
+      selection_controller_client_->CloseQuickMenuAndHideHandles();
+    }
 
     widget->SetActive(false);
     widget->LostFocus();
@@ -1328,10 +1453,10 @@
     content::TextInputManager* text_input_manager,
     content::RenderWidgetHostViewBase* updated_view,
     bool did_update_state) {
-  const content::TextInputState* state =
-      text_input_manager->GetTextInputState();
-  if (state && !state->show_ime_if_needed)
+  const auto state = text_input_manager->GetTextInputState();
+  if (state && !state->show_ime_if_needed) {
     return;
+  }
 
   CefRenderHandler::TextInputMode mode = CEF_TEXT_INPUT_MODE_NONE;
   if (state && state->type != ui::TEXT_INPUT_TYPE_NONE) {
@@ -1351,9 +1476,9 @@
 
 void CefRenderWidgetHostViewOSR::ProcessAckedTouchEvent(
     const content::TouchEventWithLatencyInfo& touch,
-    content::InputEventAckState ack_result) {
+    blink::mojom::InputEventResultState ack_result) {
   const bool event_consumed =
-      ack_result == content::INPUT_EVENT_ACK_STATE_CONSUMED;
+      ack_result == blink::mojom::InputEventResultState::kConsumed;
   gesture_provider_.OnTouchEventAck(touch.event.unique_touch_event_id,
                                     event_consumed, false);
 }
@@ -1371,8 +1496,9 @@
       ui::CreateWebGestureEventFromGestureEventData(gesture);
 
   // without this check, forwarding gestures does not work!
-  if (web_event.GetType() == blink::WebInputEvent::kUndefined)
+  if (web_event.GetType() == blink::WebInputEvent::Type::kUndefined) {
     return;
+  }
 
   ui::LatencyInfo latency_info = CreateLatencyInfo(web_event);
   if (ShouldRouteEvents()) {
@@ -1389,34 +1515,45 @@
   SetFrameRate();
 
   if (video_consumer_) {
-    video_consumer_->SetFrameRate(
-        base::TimeDelta::FromMicroseconds(frame_rate_threshold_us_));
+    video_consumer_->SetFrameRate(base::Microseconds(frame_rate_threshold_us_));
   }
 
   // Notify the guest hosts if any.
-  for (auto guest_host_view : guest_host_views_)
+  for (auto guest_host_view : guest_host_views_) {
     guest_host_view->UpdateFrameRate();
+  }
 }
 
 gfx::Size CefRenderWidgetHostViewOSR::SizeInPixels() {
-  return gfx::ScaleToCeiledSize(GetViewBounds().size(),
-                                current_device_scale_factor_);
+  return gfx::ScaleToCeiledSize(GetViewBounds().size(), GetDeviceScaleFactor());
 }
 
-#if defined(OS_MACOSX)
+#if BUILDFLAG(IS_MAC)
 void CefRenderWidgetHostViewOSR::SetActive(bool active) {}
 
 void CefRenderWidgetHostViewOSR::ShowDefinitionForSelection() {}
 
 void CefRenderWidgetHostViewOSR::SpeakSelection() {}
-#endif
+
+void CefRenderWidgetHostViewOSR::SetWindowFrameInScreen(const gfx::Rect& rect) {
+}
+
+void CefRenderWidgetHostViewOSR::ShowSharePicker(
+    const std::string& title,
+    const std::string& text,
+    const std::string& url,
+    const std::vector<std::string>& file_paths,
+    blink::mojom::ShareService::ShareCallback callback) {
+  std::move(callback).Run(blink::mojom::ShareError::INTERNAL_ERROR);
+}
+#endif  // BUILDFLAG(IS_MAC)
 
 void CefRenderWidgetHostViewOSR::OnPaint(const gfx::Rect& damage_rect,
                                          const gfx::Size& pixel_size,
                                          const void* pixels) {
   TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::OnPaint");
 
-  // Workaround for https://bitbucket.org/chromiumembedded/cef/issues/2817
+  // Workaround for https://github.com/chromiumembedded/cef/issues/2817
   if (!is_showing_) {
     return;
   }
@@ -1440,16 +1577,30 @@
                    rcList, pixels, pixel_size.width(), pixel_size.height());
 
   // Release the resize hold when we reach the desired size.
-  if (hold_resize_ && pixel_size == SizeInPixels())
-    ReleaseResizeHold();
+  if (hold_resize_) {
+    DCHECK_GT(cached_scale_factor_, 0);
+    gfx::Size expected_size =
+        gfx::ScaleToCeiledSize(GetViewBounds().size(), cached_scale_factor_);
+    if (pixel_size == expected_size) {
+      ReleaseResizeHold();
+    }
+  }
 }
 
 ui::Layer* CefRenderWidgetHostViewOSR::GetRootLayer() const {
   return root_layer_.get();
 }
 
+ui::TextInputType CefRenderWidgetHostViewOSR::GetTextInputType() {
+  if (text_input_manager_ && text_input_manager_->GetTextInputState()) {
+    return text_input_manager_->GetTextInputState()->type;
+  }
+
+  return ui::TEXT_INPUT_TYPE_NONE;
+}
+
 void CefRenderWidgetHostViewOSR::SetFrameRate() {
-  CefRefPtr<CefBrowserHostImpl> browser;
+  CefRefPtr<AlloyBrowserHostImpl> browser;
   if (parent_host_view_) {
     // Use the same frame rate as the embedding browser.
     browser = parent_host_view_->browser_impl_;
@@ -1459,8 +1610,9 @@
   CHECK(browser);
 
   // Only set the frame rate one time.
-  if (frame_rate_threshold_us_ != 0)
+  if (frame_rate_threshold_us_ != 0) {
     return;
+  }
 
   int frame_rate =
       osr_util::ClampFrameRate(browser->settings().windowless_frame_rate);
@@ -1469,33 +1621,38 @@
 
   if (compositor_) {
     compositor_->SetDisplayVSyncParameters(
-        base::TimeTicks::Now(),
-        base::TimeDelta::FromMicroseconds(frame_rate_threshold_us_));
+        base::TimeTicks::Now(), base::Microseconds(frame_rate_threshold_us_));
   }
 
   if (video_consumer_) {
-    video_consumer_->SetFrameRate(
-        base::TimeDelta::FromMicroseconds(frame_rate_threshold_us_));
+    video_consumer_->SetFrameRate(base::Microseconds(frame_rate_threshold_us_));
   }
 }
 
-bool CefRenderWidgetHostViewOSR::SetDeviceScaleFactor() {
+bool CefRenderWidgetHostViewOSR::SetScreenInfo() {
   // This method should not be called while the resize hold is active.
   DCHECK(!hold_resize_);
 
-  const float new_scale_factor = ::GetDeviceScaleFactor(browser_impl_.get());
-  if (new_scale_factor == current_device_scale_factor_)
-    return false;
+  display::ScreenInfo current_info = screen_infos_.current();
 
-  current_device_scale_factor_ = new_scale_factor;
+  // This will result in a call to GetNewScreenInfosForUpdate().
+  UpdateScreenInfo();
+  if (screen_infos_.current() == current_info) {
+    // Nothing changed.
+    return false;
+  }
 
   // Notify the guest hosts if any.
   for (auto guest_host_view : guest_host_views_) {
     content::RenderWidgetHostImpl* rwhi = guest_host_view->render_widget_host();
-    if (!rwhi)
+    if (!rwhi) {
       continue;
-    if (rwhi->GetView())
-      rwhi->GetView()->set_current_device_scale_factor(new_scale_factor);
+    }
+    auto guest_view_osr =
+        static_cast<CefRenderWidgetHostViewOSR*>(rwhi->GetView());
+    if (guest_view_osr) {
+      guest_view_osr->SetScreenInfo();
+    }
   }
 
   return true;
@@ -1506,33 +1663,36 @@
   DCHECK(!hold_resize_);
 
   // Popup bounds are set in InitAsPopup.
-  if (IsPopupWidget())
+  if (IsPopupWidget()) {
     return false;
+  }
 
   const gfx::Rect& new_bounds = ::GetViewBounds(browser_impl_.get());
-  if (new_bounds == current_view_bounds_)
+  if (new_bounds == current_view_bounds_) {
     return false;
+  }
 
   current_view_bounds_ = new_bounds;
   return true;
 }
 
 bool CefRenderWidgetHostViewOSR::SetRootLayerSize(bool force) {
-  const bool scale_factor_changed = SetDeviceScaleFactor();
+  const bool screen_info_changed = SetScreenInfo();
   const bool view_bounds_changed = SetViewBounds();
-  if (!force && !scale_factor_changed && !view_bounds_changed)
+  if (!force && !screen_info_changed && !view_bounds_changed) {
     return false;
+  }
 
   GetRootLayer()->SetBounds(gfx::Rect(GetViewBounds().size()));
 
   if (compositor_) {
     compositor_local_surface_id_allocator_.GenerateId();
-    compositor_->SetScaleAndSize(current_device_scale_factor_, SizeInPixels(),
-                                 compositor_local_surface_id_allocator_
-                                     .GetCurrentLocalSurfaceIdAllocation());
+    compositor_->SetScaleAndSize(
+        GetDeviceScaleFactor(), SizeInPixels(),
+        compositor_local_surface_id_allocator_.GetCurrentLocalSurfaceId());
   }
 
-  return (scale_factor_changed || view_bounds_changed);
+  return (screen_info_changed || view_bounds_changed);
 }
 
 bool CefRenderWidgetHostViewOSR::ResizeRootLayer() {
@@ -1542,6 +1702,7 @@
       // The size has changed. Avoid resizing again until ReleaseResizeHold() is
       // called.
       hold_resize_ = true;
+      cached_scale_factor_ = GetDeviceScaleFactor();
       return true;
     }
   } else if (!pending_resize_) {
@@ -1555,16 +1716,19 @@
 void CefRenderWidgetHostViewOSR::ReleaseResizeHold() {
   DCHECK(hold_resize_);
   hold_resize_ = false;
+  cached_scale_factor_ = -1;
   if (pending_resize_) {
     pending_resize_ = false;
-    CEF_POST_TASK(CEF_UIT, base::Bind(&CefRenderWidgetHostViewOSR::WasResized,
-                                      weak_ptr_factory_.GetWeakPtr()));
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&CefRenderWidgetHostViewOSR::WasResized,
+                                 weak_ptr_factory_.GetWeakPtr()));
   }
 }
 
 void CefRenderWidgetHostViewOSR::CancelWidget() {
-  if (render_widget_host_)
+  if (render_widget_host_) {
     render_widget_host_->LostCapture();
+  }
 
   Hide();
 
@@ -1593,7 +1757,7 @@
   if (render_widget_host_ && !is_destroyed_) {
     is_destroyed_ = true;
 
-    // Don't delete the RWHI manually while owned by a scoped_ptr in RVHI.
+    // Don't delete the RWHI manually while owned by a std::unique_ptr in RVHI.
     // This matches a CHECK() in RenderWidgetHostImpl::Destroy().
     const bool also_delete = !render_widget_host_->owner_delegate();
 
@@ -1635,22 +1799,25 @@
 
 void CefRenderWidgetHostViewOSR::RequestImeCompositionUpdate(
     bool start_monitoring) {
-  if (!render_widget_host_)
+  if (!render_widget_host_) {
     return;
+  }
   render_widget_host_->RequestCompositionUpdates(false, start_monitoring);
 }
 
 void CefRenderWidgetHostViewOSR::ImeCompositionRangeChanged(
     const gfx::Range& range,
-    const std::vector<gfx::Rect>& character_bounds) {
+    const absl::optional<std::vector<gfx::Rect>>& character_bounds,
+    const absl::optional<std::vector<gfx::Rect>>& line_bounds) {
   if (browser_impl_.get()) {
     CefRange cef_range(range.start(), range.end());
     CefRenderHandler::RectList rcList;
 
-    for (size_t i = 0; i < character_bounds.size(); ++i) {
-      rcList.push_back(CefRect(character_bounds[i].x(), character_bounds[i].y(),
-                               character_bounds[i].width(),
-                               character_bounds[i].height()));
+    if (character_bounds.has_value()) {
+      for (auto& rect : character_bounds.value()) {
+        rcList.push_back(
+            CefRect(rect.x(), rect.y(), rect.width(), rect.height()));
+      }
     }
 
     CefRefPtr<CefRenderHandler> handler =
@@ -1667,8 +1834,9 @@
 
 void CefRenderWidgetHostViewOSR::UpdateBackgroundColorFromRenderer(
     SkColor color) {
-  if (color == background_color_)
+  if (color == background_color_) {
     return;
+  }
   background_color_ = color;
 
   bool opaque = SkColorGetA(color) == SK_AlphaOPAQUE;
diff --git a/src/libcef/browser/osr/render_widget_host_view_osr.h b/src/libcef/browser/osr/render_widget_host_view_osr.h
index 3e4a970..f8eca4c 100644
--- a/src/libcef/browser/osr/render_widget_host_view_osr.h
+++ b/src/libcef/browser/osr/render_widget_host_view_osr.h
@@ -14,12 +14,11 @@
 #include "include/cef_base.h"
 #include "include/cef_browser.h"
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 #include "libcef/browser/osr/host_display_client_osr.h"
 #include "libcef/browser/osr/motion_event_osr.h"
 
 #include "base/memory/weak_ptr.h"
-#include "base/optional.h"
 #include "build/build_config.h"
 #include "cc/layers/deadline_policy.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
@@ -27,8 +26,13 @@
 #include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h"
 #include "content/browser/renderer_host/render_widget_host_view_base.h"
 #include "content/browser/renderer_host/text_input_manager.h"
+#include "content/public/browser/render_frame_metadata_provider.h"
 #include "content/public/common/widget_type.h"
-#include "ui/base/mojom/cursor_type.mojom-shared.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/mojom/widget/record_content_to_visible_time_request.mojom-forward.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
+#include "ui/base/ime/text_input_client.h"
 #include "ui/compositor/compositor.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/gesture_detection/filtered_gesture_provider.h"
@@ -36,41 +40,34 @@
 #include "ui/events/gesture_detection/motion_event_generic.h"
 #include "ui/gfx/geometry/rect.h"
 
-#if defined(OS_LINUX)
-#include "ui/base/x/x11_util.h"
-#endif
-
-#if defined(OS_MACOSX)
+#if BUILDFLAG(IS_MAC)
 #include "content/browser/renderer_host/browser_compositor_view_mac.h"
 #endif
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 #include "ui/gfx/win/window_impl.h"
 #endif
 
-#if defined(USE_AURA)
-#include "ui/base/cursor/cursor.h"
-#endif
+namespace ui {
+class TouchSelectionController;
+}  // namespace ui
 
 namespace content {
+class BackingStore;
+class CursorManager;
 class DelegatedFrameHost;
 class DelegatedFrameHostClient;
 class RenderWidgetHost;
 class RenderWidgetHostImpl;
 class RenderWidgetHostViewGuest;
-class BackingStore;
-class CursorManager;
 }  // namespace content
 
 class CefCopyFrameGenerator;
 class CefSoftwareOutputDeviceOSR;
+class CefTouchSelectionControllerClientOSR;
 class CefVideoConsumerOSR;
 class CefWebContentsViewOSR;
 
-#if defined(USE_X11)
-class CefWindowX11;
-#endif
-
 ///////////////////////////////////////////////////////////////////////////////
 // CefRenderWidgetHostViewOSR
 //
@@ -89,20 +86,27 @@
 // RenderWidgetHostView class hierarchy described in render_widget_host_view.h.
 ///////////////////////////////////////////////////////////////////////////////
 
-#if defined(OS_MACOSX)
+#if BUILDFLAG(IS_MAC)
 class MacHelper;
 #endif
 
-class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
-                                   public ui::CompositorDelegate,
-                                   public content::TextInputManager::Observer,
-                                   public ui::GestureProviderClient {
+class CefRenderWidgetHostViewOSR
+    : public content::RenderWidgetHostViewBase,
+      public content::RenderFrameMetadataProvider::Observer,
+      public ui::CompositorDelegate,
+      public content::TextInputManager::Observer,
+      public ui::GestureProviderClient {
  public:
   CefRenderWidgetHostViewOSR(SkColor background_color,
                              bool use_shared_texture,
                              bool use_external_begin_frame,
                              content::RenderWidgetHost* widget,
                              CefRenderWidgetHostViewOSR* parent_host_view);
+
+  CefRenderWidgetHostViewOSR(const CefRenderWidgetHostViewOSR&) = delete;
+  CefRenderWidgetHostViewOSR& operator=(const CefRenderWidgetHostViewOSR&) =
+      delete;
+
   ~CefRenderWidgetHostViewOSR() override;
 
   // RenderWidgetHostView implementation.
@@ -115,14 +119,20 @@
   bool HasFocus() override;
   uint32_t GetCaptureSequenceNumber() const override;
   bool IsSurfaceAvailableForCopy() override;
-  void Show() override;
+  void ShowWithVisibility(
+      content::PageVisibilityState page_visibility) override;
   void Hide() override;
   bool IsShowing() override;
   void EnsureSurfaceSynchronizedForWebTest() override;
+  content::TouchSelectionControllerClientManager*
+  GetTouchSelectionControllerClientManager() override;
   gfx::Rect GetViewBounds() override;
   void SetBackgroundColor(SkColor color) override;
-  base::Optional<SkColor> GetBackgroundColor() override;
+  absl::optional<SkColor> GetBackgroundColor() override;
   void UpdateBackgroundColor() override;
+  absl::optional<content::DisplayFeature> GetDisplayFeature() override;
+  void SetDisplayFeatureForTesting(
+      const content::DisplayFeature* display_feature) override;
   blink::mojom::PointerLockResult LockMouse(
       bool request_unadjusted_movement) override;
   blink::mojom::PointerLockResult ChangeMouseLock(
@@ -130,45 +140,51 @@
   void UnlockMouse() override;
   void TakeFallbackContentFrom(content::RenderWidgetHostView* view) override;
 
-#if defined(OS_MACOSX)
+#if BUILDFLAG(IS_MAC)
   void SetActive(bool active) override;
   void ShowDefinitionForSelection() override;
   void SpeakSelection() override;
-#endif  // defined(OS_MACOSX)
+  void SetWindowFrameInScreen(const gfx::Rect& rect) override;
+  void ShowSharePicker(
+      const std::string& title,
+      const std::string& text,
+      const std::string& url,
+      const std::vector<std::string>& file_paths,
+      blink::mojom::ShareService::ShareCallback callback) override;
+#endif  // BUILDFLAG(IS_MAC)
 
   // RenderWidgetHostViewBase implementation.
+  void InvalidateLocalSurfaceIdAndAllocationGroup() override;
+  void ClearFallbackSurfaceForCommitPending() override;
   void ResetFallbackToFirstNavigationSurface() override;
   void InitAsPopup(content::RenderWidgetHostView* parent_host_view,
-                   const gfx::Rect& pos) override;
-  void InitAsFullscreen(
-      content::RenderWidgetHostView* reference_host_view) override;
-  void UpdateCursor(const content::WebCursor& cursor) override;
+                   const gfx::Rect& bounds,
+                   const gfx::Rect& anchor_rect) override;
+  void UpdateCursor(const ui::Cursor& cursor) override;
   void SetIsLoading(bool is_loading) override;
   void RenderProcessGone() override;
   void Destroy() override;
-  void SetTooltipText(const base::string16& tooltip_text) override;
+  void UpdateTooltipUnderCursor(const std::u16string& tooltip_text) override;
   content::CursorManager* GetCursorManager() override;
   gfx::Size GetCompositorViewportPixelSize() override;
   void CopyFromSurface(
       const gfx::Rect& src_rect,
       const gfx::Size& output_size,
       base::OnceCallback<void(const SkBitmap&)> callback) override;
-  void GetScreenInfo(content::ScreenInfo* results) override;
+  display::ScreenInfos GetNewScreenInfosForUpdate() override;
   void TransformPointToRootSurface(gfx::PointF* point) override;
   gfx::Rect GetBoundsInRootWindow() override;
 
-#if !defined(OS_MACOSX)
+#if !BUILDFLAG(IS_MAC)
   viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
       const cc::RenderFrameMetadata& metadata) override;
 #endif
 
   viz::SurfaceId GetCurrentSurfaceId() const override;
-  content::BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
-      content::BrowserAccessibilityDelegate* delegate,
-      bool for_root_frame) override;
   void ImeCompositionRangeChanged(
       const gfx::Range& range,
-      const std::vector<gfx::Rect>& character_bounds) override;
+      const absl::optional<std::vector<gfx::Rect>>& character_bounds,
+      const absl::optional<std::vector<gfx::Rect>>& line_bounds) override;
   std::unique_ptr<content::SyntheticGestureTarget>
   CreateSyntheticGestureTarget() override;
   bool TransformPointToCoordSpaceForView(
@@ -176,17 +192,31 @@
       RenderWidgetHostViewBase* target_view,
       gfx::PointF* transformed_point) override;
   void DidNavigate() override;
-  void SelectionChanged(const base::string16& text,
+  void SelectionChanged(const std::u16string& text,
                         size_t offset,
                         const gfx::Range& range) override;
-  const viz::LocalSurfaceIdAllocation& GetLocalSurfaceIdAllocation()
-      const override;
+  const viz::LocalSurfaceId& GetLocalSurfaceId() const override;
   const viz::FrameSinkId& GetFrameSinkId() const override;
   viz::FrameSinkId GetRootFrameSinkId() override;
-  void OnRenderFrameMetadataChangedAfterActivation() override;
+  void NotifyHostAndDelegateOnWasShown(
+      blink::mojom::RecordContentToVisibleTimeRequestPtr visible_time_request)
+      override;
+  void RequestSuccessfulPresentationTimeFromHostOrDelegate(
+      blink::mojom::RecordContentToVisibleTimeRequestPtr visible_time_request)
+      override;
+  void CancelSuccessfulPresentationTimeRequestForHostAndDelegate() override;
 
   void OnFrameComplete(const viz::BeginFrameAck& ack);
 
+  // RenderFrameMetadataProvider::Observer implementation.
+  void OnRenderFrameMetadataChangedBeforeActivation(
+      const cc::RenderFrameMetadata& metadata) override {}
+  void OnRenderFrameMetadataChangedAfterActivation(
+      base::TimeTicks activation_time) override;
+  void OnRenderFrameSubmission() override {}
+  void OnLocalSurfaceIdChanged(
+      const cc::RenderFrameMetadata& metadata) override {}
+
   // ui::CompositorDelegate implementation.
   std::unique_ptr<viz::HostDisplayClient> CreateHostDisplayClient() override;
 
@@ -197,8 +227,9 @@
       bool did_update_state) override;
 
   // ui::GestureProviderClient implementation.
-  void ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo& touch,
-                              content::InputEventAckState ack_result) override;
+  void ProcessAckedTouchEvent(
+      const content::TouchEventWithLatencyInfo& touch,
+      blink::mojom::InputEventResultState ack_result) override;
   void OnGestureEvent(const ui::GestureEventData& gesture) override;
 
   bool InstallTransparency();
@@ -206,8 +237,7 @@
   void WasResized();
   void SynchronizeVisualProperties(
       const cc::DeadlinePolicy& deadline_policy,
-      const base::Optional<viz::LocalSurfaceIdAllocation>&
-          child_local_surface_id_allocation);
+      const absl::optional<viz::LocalSurfaceId>& child_local_surface_id);
   void OnScreenInfoChanged();
   void Invalidate(CefBrowserHost::PaintElementType type);
   void SendExternalBeginFrame();
@@ -216,7 +246,7 @@
   void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event);
   void SendTouchEvent(const CefTouchEvent& event);
   bool ShouldRouteEvents() const;
-  void SendFocusEvent(bool focus);
+  void SetFocus(bool focus);
   void UpdateFrameRate();
 
   gfx::Size SizeInPixels();
@@ -240,14 +270,15 @@
   void ImeFinishComposingText(bool keep_selection);
   void ImeCancelComposition() override;
 
-  CefRefPtr<CefBrowserHostImpl> browser_impl() const { return browser_impl_; }
-  void set_browser_impl(CefRefPtr<CefBrowserHostImpl> browser) {
+  CefRefPtr<AlloyBrowserHostImpl> browser_impl() const { return browser_impl_; }
+  void set_browser_impl(CefRefPtr<AlloyBrowserHostImpl> browser) {
     browser_impl_ = browser;
   }
 
   void set_popup_host_view(CefRenderWidgetHostViewOSR* popup_view) {
-    if (popup_view != popup_host_view_)
+    if (popup_view != popup_host_view_) {
       forward_touch_to_popup_ = false;
+    }
     popup_host_view_ = popup_view;
   }
   void set_child_host_view(CefRenderWidgetHostViewOSR* popup_view) {
@@ -264,9 +295,28 @@
   void OnDidUpdateVisualPropertiesComplete(
       const cc::RenderFrameMetadata& metadata);
 
+  void ReleaseCompositor();
+
+  // Marks the current viz::LocalSurfaceId as invalid. AllocateLocalSurfaceId
+  // must be called before submitting new CompositorFrames. May be called by
+  // content::DelegatedFrameHostClient::InvalidateLocalSurfaceIdOnEviction.
+  void InvalidateLocalSurfaceId();
+
+  ui::TouchSelectionController* selection_controller() const {
+    return selection_controller_.get();
+  }
+
+  CefTouchSelectionControllerClientOSR* selection_controller_client() const {
+    return selection_controller_client_.get();
+  }
+
+  ui::TextInputType GetTextInputType();
+
+  bool is_hidden() const { return !is_showing_; }
+
  private:
   void SetFrameRate();
-  bool SetDeviceScaleFactor();
+  bool SetScreenInfo();
   bool SetViewBounds();
   bool SetRootLayerSize(bool force);
 
@@ -276,6 +326,9 @@
 
   void CancelWidget();
 
+  // Helper function to create a selection controller.
+  void CreateSelectionController();
+
   void OnScrollOffsetChanged();
 
   void AddGuestHostView(CefRenderWidgetHostViewOSR* guest_host);
@@ -299,22 +352,16 @@
   // CompositorFrame submission in anticipation of a synchronization operation
   // that does not involve a resize or a device scale factor change.
   void AllocateLocalSurfaceId();
-  const viz::LocalSurfaceIdAllocation& GetCurrentLocalSurfaceIdAllocation()
-      const;
+  const viz::LocalSurfaceId& GetCurrentLocalSurfaceId() const;
 
   // Sets the current viz::LocalSurfaceId, in cases where the embedded client
   // has allocated one. Also sets child sequence number component of the
   // viz::LocalSurfaceId allocator.
   void UpdateLocalSurfaceIdFromEmbeddedClient(
-      const base::Optional<viz::LocalSurfaceIdAllocation>&
-          local_surface_id_allocation);
+      const absl::optional<viz::LocalSurfaceId>& local_surface_id);
 
   // Returns the current viz::LocalSurfaceIdAllocation.
-  const viz::LocalSurfaceIdAllocation& GetOrCreateLocalSurfaceIdAllocation();
-
-  // Marks the current viz::LocalSurfaceId as invalid. AllocateLocalSurfaceId
-  // must be called before submitting new CompositorFrames.
-  void InvalidateLocalSurfaceId();
+  const viz::LocalSurfaceId& GetOrCreateLocalSurfaceId();
 
   void AddDamageRect(uint32_t sequence, const gfx::Rect& rect);
 
@@ -322,9 +369,13 @@
   // opaqueness changes.
   void UpdateBackgroundColorFromRenderer(SkColor color);
 
-#if defined(USE_AURA)
-  ui::PlatformCursor GetPlatformCursor(ui::mojom::CursorType type);
-#endif
+  // The last selection bounds reported to the view.
+  gfx::SelectionBound selection_start_;
+  gfx::SelectionBound selection_end_;
+
+  std::unique_ptr<CefTouchSelectionControllerClientOSR>
+      selection_controller_client_;
+  std::unique_ptr<ui::TouchSelectionController> selection_controller_;
 
   // The background color of the web content.
   SkColor background_color_;
@@ -342,15 +393,12 @@
       parent_local_surface_id_allocator_;
   viz::ParentLocalSurfaceIdAllocator compositor_local_surface_id_allocator_;
 
-#if defined(USE_X11)
-  std::unique_ptr<ui::XScopedCursor> invisible_cursor_;
-#endif
-
   std::unique_ptr<content::CursorManager> cursor_manager_;
 
   // Provides |source_id| for BeginFrameArgs that we create.
   viz::StubBeginFrameSource begin_frame_source_;
   uint64_t begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber;
+  bool begin_frame_pending_ = false;
 
   bool sync_frame_rate_ = false;
   bool external_begin_frame_enabled_ = false;
@@ -362,6 +410,8 @@
   bool hold_resize_ = false;
   bool pending_resize_ = false;
 
+  float cached_scale_factor_ = 0.0f;
+
   // The associated Model.  While |this| is being Destroyed,
   // |render_widget_host_| is NULL and the message loop is run one last time
   // Message handlers must check for a NULL |render_widget_host_|.
@@ -373,7 +423,7 @@
   CefRenderWidgetHostViewOSR* child_host_view_ = nullptr;
   std::set<CefRenderWidgetHostViewOSR*> guest_host_views_;
 
-  CefRefPtr<CefBrowserHostImpl> browser_impl_;
+  CefRefPtr<AlloyBrowserHostImpl> browser_impl_;
 
   bool is_showing_ = false;
   bool is_destroyed_ = false;
@@ -388,7 +438,7 @@
   bool pinch_zoom_enabled_;
 
   // The last scroll offset of the view.
-  gfx::Vector2dF last_scroll_offset_;
+  gfx::PointF last_scroll_offset_;
   bool is_scroll_offset_changed_pending_ = false;
 
   content::MouseWheelPhaseHandler mouse_wheel_phase_handler_;
@@ -405,8 +455,6 @@
   bool forward_touch_to_popup_ = false;
 
   base::WeakPtrFactory<CefRenderWidgetHostViewOSR> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefRenderWidgetHostViewOSR);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_OSR_RENDER_WIDGET_HOST_VIEW_OSR_H_
diff --git a/src/libcef/browser/osr/render_widget_host_view_osr_linux.cc b/src/libcef/browser/osr/render_widget_host_view_osr_linux.cc
deleted file mode 100644
index 0e4025b..0000000
--- a/src/libcef/browser/osr/render_widget_host_view_osr_linux.cc
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/osr/render_widget_host_view_osr.h"
-
-#if defined(USE_X11)
-#include <X11/Xlib.h>
-#include <X11/cursorfont.h>
-#undef Status  // Avoid conflicts with url_request_status.h
-
-#include "libcef/browser/native/window_x11.h"
-
-#include "ui/base/x/x11_util.h"
-#include "ui/gfx/x/x11_types.h"
-#endif  // defined(USE_X11)
-
-#if defined(USE_X11)
-namespace {
-
-// Based on ui/base/cursor/cursor_loader_x11.cc.
-
-int ToCursorID(ui::mojom::CursorType type) {
-  switch (type) {
-    case ui::mojom::CursorType::kPointer:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kCross:
-      return XC_crosshair;
-    case ui::mojom::CursorType::kHand:
-      return XC_hand2;
-    case ui::mojom::CursorType::kIBeam:
-      return XC_xterm;
-    case ui::mojom::CursorType::kWait:
-      return XC_watch;
-    case ui::mojom::CursorType::kHelp:
-      return XC_question_arrow;
-    case ui::mojom::CursorType::kEastResize:
-      return XC_right_side;
-    case ui::mojom::CursorType::kNorthResize:
-      return XC_top_side;
-    case ui::mojom::CursorType::kNorthEastResize:
-      return XC_top_right_corner;
-    case ui::mojom::CursorType::kNorthWestResize:
-      return XC_top_left_corner;
-    case ui::mojom::CursorType::kSouthResize:
-      return XC_bottom_side;
-    case ui::mojom::CursorType::kSouthEastResize:
-      return XC_bottom_right_corner;
-    case ui::mojom::CursorType::kSouthWestResize:
-      return XC_bottom_left_corner;
-    case ui::mojom::CursorType::kWestResize:
-      return XC_left_side;
-    case ui::mojom::CursorType::kNorthSouthResize:
-      return XC_sb_v_double_arrow;
-    case ui::mojom::CursorType::kEastWestResize:
-      return XC_sb_h_double_arrow;
-    case ui::mojom::CursorType::kNorthEastSouthWestResize:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kNorthWestSouthEastResize:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kColumnResize:
-      return XC_sb_h_double_arrow;
-    case ui::mojom::CursorType::kRowResize:
-      return XC_sb_v_double_arrow;
-    case ui::mojom::CursorType::kMiddlePanning:
-      return XC_fleur;
-    case ui::mojom::CursorType::kEastPanning:
-      return XC_sb_right_arrow;
-    case ui::mojom::CursorType::kNorthPanning:
-      return XC_sb_up_arrow;
-    case ui::mojom::CursorType::kNorthEastPanning:
-      return XC_top_right_corner;
-    case ui::mojom::CursorType::kNorthWestPanning:
-      return XC_top_left_corner;
-    case ui::mojom::CursorType::kSouthPanning:
-      return XC_sb_down_arrow;
-    case ui::mojom::CursorType::kSouthEastPanning:
-      return XC_bottom_right_corner;
-    case ui::mojom::CursorType::kSouthWestPanning:
-      return XC_bottom_left_corner;
-    case ui::mojom::CursorType::kWestPanning:
-      return XC_sb_left_arrow;
-    case ui::mojom::CursorType::kMove:
-      return XC_fleur;
-    case ui::mojom::CursorType::kVerticalText:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kCell:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kContextMenu:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kAlias:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kProgress:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kNoDrop:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kCopy:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kNotAllowed:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kZoomIn:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kZoomOut:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kGrab:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kGrabbing:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kMiddlePanningVertical:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kMiddlePanningHorizontal:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kDndNone:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kDndMove:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kDndCopy:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kDndLink:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kNull:
-      return XC_left_ptr;
-    case ui::mojom::CursorType::kCustom:
-    case ui::mojom::CursorType::kNone:
-      break;
-  }
-  NOTREACHED();
-  return 0;
-}
-
-// The following XCursorCache code was deleted from ui/base/x/x11_util.cc in
-// https://crbug.com/665574#c2
-
-// A process wide singleton that manages the usage of X cursors.
-class XCursorCache {
- public:
-  XCursorCache() {}
-  ~XCursorCache() { Clear(); }
-
-  ::Cursor GetCursor(int cursor_shape) {
-    // Lookup cursor by attempting to insert a null value, which avoids
-    // a second pass through the map after a cache miss.
-    std::pair<std::map<int, ::Cursor>::iterator, bool> it =
-        cache_.insert(std::make_pair(cursor_shape, 0));
-    if (it.second) {
-      XDisplay* display = gfx::GetXDisplay();
-      it.first->second = XCreateFontCursor(display, cursor_shape);
-    }
-    return it.first->second;
-  }
-
-  void Clear() {
-    XDisplay* display = gfx::GetXDisplay();
-    for (std::map<int, ::Cursor>::iterator it = cache_.begin();
-         it != cache_.end(); ++it) {
-      XFreeCursor(display, it->second);
-    }
-    cache_.clear();
-  }
-
- private:
-  // Maps X11 font cursor shapes to Cursor IDs.
-  std::map<int, ::Cursor> cache_;
-
-  DISALLOW_COPY_AND_ASSIGN(XCursorCache);
-};
-
-XCursorCache* cursor_cache = nullptr;
-
-// Returns an X11 Cursor, sharable across the process.
-// |cursor_shape| is an X font cursor shape, see XCreateFontCursor().
-::Cursor GetXCursor(int cursor_shape) {
-  if (!cursor_cache)
-    cursor_cache = new XCursorCache;
-  return cursor_cache->GetCursor(cursor_shape);
-}
-
-}  // namespace
-#endif  // defined(USE_X11)
-
-ui::PlatformCursor CefRenderWidgetHostViewOSR::GetPlatformCursor(
-    ui::mojom::CursorType type) {
-#if defined(USE_X11)
-  if (type == ui::mojom::CursorType::kNone) {
-    if (!invisible_cursor_) {
-      invisible_cursor_.reset(new ui::XScopedCursor(ui::CreateInvisibleCursor(),
-                                                    gfx::GetXDisplay()));
-    }
-    return invisible_cursor_->get();
-  } else {
-    return GetXCursor(ToCursorID(type));
-  }
-#endif  // defined(USE_X11)
-  return 0;
-}
diff --git a/src/libcef/browser/osr/render_widget_host_view_osr_win.cc b/src/libcef/browser/osr/render_widget_host_view_osr_win.cc
deleted file mode 100644
index 45c68a9..0000000
--- a/src/libcef/browser/osr/render_widget_host_view_osr_win.cc
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/osr/render_widget_host_view_osr.h"
-
-#include <windows.h>
-
-#include "libcef/browser/browser_host_impl.h"
-#include "libcef/browser/content_browser_client.h"
-
-#include "ui/resources/grit/ui_unscaled_resources.h"
-
-namespace {
-
-class CefCompositorHostWin : public gfx::WindowImpl {
- public:
-  CefCompositorHostWin() {
-    // Create a hidden 1x1 borderless window.
-    set_window_style(WS_POPUP | WS_SYSMENU);
-    Init(NULL, gfx::Rect(0, 0, 1, 1));
-  }
-
-  ~CefCompositorHostWin() override { DestroyWindow(hwnd()); }
-
- private:
-  CR_BEGIN_MSG_MAP_EX(CefCompositorHostWin)
-    CR_MSG_WM_PAINT(OnPaint)
-  CR_END_MSG_MAP()
-
-  CR_MSG_MAP_CLASS_DECLARATIONS(CefCompositorHostWin)
-
-  void OnPaint(HDC dc) { ValidateRect(hwnd(), NULL); }
-
-  DISALLOW_COPY_AND_ASSIGN(CefCompositorHostWin);
-};
-
-// From content/common/cursors/webcursor_win.cc.
-
-LPCWSTR ToCursorID(ui::mojom::CursorType type) {
-  switch (type) {
-    case ui::mojom::CursorType::kPointer:
-      return IDC_ARROW;
-    case ui::mojom::CursorType::kCross:
-      return IDC_CROSS;
-    case ui::mojom::CursorType::kHand:
-      return IDC_HAND;
-    case ui::mojom::CursorType::kIBeam:
-      return IDC_IBEAM;
-    case ui::mojom::CursorType::kWait:
-      return IDC_WAIT;
-    case ui::mojom::CursorType::kHelp:
-      return IDC_HELP;
-    case ui::mojom::CursorType::kEastResize:
-      return IDC_SIZEWE;
-    case ui::mojom::CursorType::kNorthResize:
-      return IDC_SIZENS;
-    case ui::mojom::CursorType::kNorthEastResize:
-      return IDC_SIZENESW;
-    case ui::mojom::CursorType::kNorthWestResize:
-      return IDC_SIZENWSE;
-    case ui::mojom::CursorType::kSouthResize:
-      return IDC_SIZENS;
-    case ui::mojom::CursorType::kSouthEastResize:
-      return IDC_SIZENWSE;
-    case ui::mojom::CursorType::kSouthWestResize:
-      return IDC_SIZENESW;
-    case ui::mojom::CursorType::kWestResize:
-      return IDC_SIZEWE;
-    case ui::mojom::CursorType::kNorthSouthResize:
-      return IDC_SIZENS;
-    case ui::mojom::CursorType::kEastWestResize:
-      return IDC_SIZEWE;
-    case ui::mojom::CursorType::kNorthEastSouthWestResize:
-      return IDC_SIZENESW;
-    case ui::mojom::CursorType::kNorthWestSouthEastResize:
-      return IDC_SIZENWSE;
-    case ui::mojom::CursorType::kColumnResize:
-      return MAKEINTRESOURCE(IDC_COLRESIZE);
-    case ui::mojom::CursorType::kRowResize:
-      return MAKEINTRESOURCE(IDC_ROWRESIZE);
-    case ui::mojom::CursorType::kMiddlePanning:
-      return MAKEINTRESOURCE(IDC_PAN_MIDDLE);
-    case ui::mojom::CursorType::kEastPanning:
-      return MAKEINTRESOURCE(IDC_PAN_EAST);
-    case ui::mojom::CursorType::kNorthPanning:
-      return MAKEINTRESOURCE(IDC_PAN_NORTH);
-    case ui::mojom::CursorType::kNorthEastPanning:
-      return MAKEINTRESOURCE(IDC_PAN_NORTH_EAST);
-    case ui::mojom::CursorType::kNorthWestPanning:
-      return MAKEINTRESOURCE(IDC_PAN_NORTH_WEST);
-    case ui::mojom::CursorType::kSouthPanning:
-      return MAKEINTRESOURCE(IDC_PAN_SOUTH);
-    case ui::mojom::CursorType::kSouthEastPanning:
-      return MAKEINTRESOURCE(IDC_PAN_SOUTH_EAST);
-    case ui::mojom::CursorType::kSouthWestPanning:
-      return MAKEINTRESOURCE(IDC_PAN_SOUTH_WEST);
-    case ui::mojom::CursorType::kWestPanning:
-      return MAKEINTRESOURCE(IDC_PAN_WEST);
-    case ui::mojom::CursorType::kMove:
-      return IDC_SIZEALL;
-    case ui::mojom::CursorType::kVerticalText:
-      return MAKEINTRESOURCE(IDC_VERTICALTEXT);
-    case ui::mojom::CursorType::kCell:
-      return MAKEINTRESOURCE(IDC_CELL);
-    case ui::mojom::CursorType::kContextMenu:
-      return IDC_ARROW;
-    case ui::mojom::CursorType::kAlias:
-      return MAKEINTRESOURCE(IDC_ALIAS);
-    case ui::mojom::CursorType::kProgress:
-      return IDC_APPSTARTING;
-    case ui::mojom::CursorType::kNoDrop:
-      return IDC_NO;
-    case ui::mojom::CursorType::kCopy:
-      return MAKEINTRESOURCE(IDC_COPYCUR);
-    case ui::mojom::CursorType::kNone:
-      return MAKEINTRESOURCE(IDC_CURSOR_NONE);
-    case ui::mojom::CursorType::kNotAllowed:
-      return IDC_NO;
-    case ui::mojom::CursorType::kZoomIn:
-      return MAKEINTRESOURCE(IDC_ZOOMIN);
-    case ui::mojom::CursorType::kZoomOut:
-      return MAKEINTRESOURCE(IDC_ZOOMOUT);
-    case ui::mojom::CursorType::kGrab:
-      return MAKEINTRESOURCE(IDC_HAND_GRAB);
-    case ui::mojom::CursorType::kGrabbing:
-      return MAKEINTRESOURCE(IDC_HAND_GRABBING);
-    case ui::mojom::CursorType::kNull:
-      return IDC_NO;
-    case ui::mojom::CursorType::kMiddlePanningVertical:
-      return MAKEINTRESOURCE(IDC_PAN_MIDDLE_VERTICAL);
-    case ui::mojom::CursorType::kMiddlePanningHorizontal:
-      return MAKEINTRESOURCE(IDC_PAN_MIDDLE_HORIZONTAL);
-    // TODO(cef): Find better cursors for these things
-    case ui::mojom::CursorType::kDndNone:
-      return IDC_ARROW;
-    case ui::mojom::CursorType::kDndMove:
-      return IDC_ARROW;
-    case ui::mojom::CursorType::kDndCopy:
-      return IDC_ARROW;
-    case ui::mojom::CursorType::kDndLink:
-      return IDC_ARROW;
-    case ui::mojom::CursorType::kCustom:
-      break;
-  }
-  NOTREACHED();
-  return NULL;
-}
-
-bool IsSystemCursorID(LPCWSTR cursor_id) {
-  return cursor_id >= IDC_ARROW;  // See WinUser.h
-}
-
-}  // namespace
-
-ui::PlatformCursor CefRenderWidgetHostViewOSR::GetPlatformCursor(
-    ui::mojom::CursorType type) {
-  HMODULE module_handle = NULL;
-  const wchar_t* cursor_id = ToCursorID(type);
-  if (!IsSystemCursorID(cursor_id)) {
-    module_handle =
-        ::GetModuleHandle(CefContentBrowserClient::Get()->GetResourceDllName());
-    if (!module_handle)
-      module_handle = ::GetModuleHandle(NULL);
-  }
-
-  return LoadCursor(module_handle, cursor_id);
-}
diff --git a/src/libcef/browser/osr/software_output_device_proxy.cc b/src/libcef/browser/osr/software_output_device_proxy.cc
index 3f33466..c4d2299 100644
--- a/src/libcef/browser/osr/software_output_device_proxy.cc
+++ b/src/libcef/browser/osr/software_output_device_proxy.cc
@@ -7,12 +7,13 @@
 #include "base/memory/shared_memory_mapping.h"
 #include "base/trace_event/trace_event.h"
 #include "components/viz/common/resources/resource_sizes.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "ui/gfx/skia_util.h"
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 #include <windows.h>
 #include "skia/ext/skia_utils_win.h"
 #include "ui/gfx/gdi_util.h"
@@ -24,13 +25,14 @@
 SoftwareOutputDeviceProxy::~SoftwareOutputDeviceProxy() = default;
 
 SoftwareOutputDeviceProxy::SoftwareOutputDeviceProxy(
-    mojom::LayeredWindowUpdaterPtr layered_window_updater)
+    mojo::PendingRemote<mojom::LayeredWindowUpdater> layered_window_updater)
     : layered_window_updater_(std::move(layered_window_updater)) {
   DCHECK(layered_window_updater_.is_bound());
 }
 
 void SoftwareOutputDeviceProxy::OnSwapBuffers(
-    SwapBuffersCallback swap_ack_callback) {
+    SwapBuffersCallback swap_ack_callback,
+    gfx::FrameData data) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(swap_ack_callback_.is_null());
 
@@ -51,16 +53,18 @@
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(!in_paint_);
 
-  if (viewport_pixel_size_ == viewport_pixel_size)
+  if (viewport_pixel_size_ == viewport_pixel_size) {
     return;
+  }
 
   viewport_pixel_size_ = viewport_pixel_size;
 
   canvas_.reset();
 
   size_t required_bytes;
-  if (!ResourceSizes::MaybeSizeInBytes(
-          viewport_pixel_size_, ResourceFormat::RGBA_8888, &required_bytes)) {
+  if (!ResourceSizes::MaybeSizeInBytes(viewport_pixel_size_,
+                                       SinglePlaneFormat::kRGBA_8888,
+                                       &required_bytes)) {
     DLOG(ERROR) << "Invalid viewport size " << viewport_pixel_size_.ToString();
     return;
   }
@@ -72,7 +76,7 @@
     return;
   }
 
-#if !defined(OS_WIN)
+#if !BUILDFLAG(IS_WIN)
   auto shm = base::ReadOnlySharedMemoryRegion::Create(required_bytes);
   if (!shm.IsValid()) {
     DLOG(ERROR) << "Failed to allocate " << required_bytes << " bytes";
@@ -118,11 +122,13 @@
 
   gfx::Rect intersected_damage_rect = damage_rect_;
   intersected_damage_rect.Intersect(gfx::Rect(viewport_pixel_size_));
-  if (intersected_damage_rect.IsEmpty())
+  if (intersected_damage_rect.IsEmpty()) {
     return;
+  }
 
-  if (!canvas_)
+  if (!canvas_) {
     return;
+  }
 
   layered_window_updater_->Draw(
       damage_rect_, base::BindOnce(&SoftwareOutputDeviceProxy::DrawAck,
diff --git a/src/libcef/browser/osr/software_output_device_proxy.h b/src/libcef/browser/osr/software_output_device_proxy.h
index 38e9ce3..fc29ae2 100644
--- a/src/libcef/browser/osr/software_output_device_proxy.h
+++ b/src/libcef/browser/osr/software_output_device_proxy.h
@@ -5,7 +5,7 @@
 #include "base/threading/thread_checker.h"
 #include "components/viz/service/display/software_output_device.h"
 #include "components/viz/service/viz_service_export.h"
-#include "services/viz/privileged/mojom/compositing/display_private.mojom.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h"
 
 namespace viz {
@@ -18,11 +18,17 @@
     : public SoftwareOutputDevice {
  public:
   explicit SoftwareOutputDeviceProxy(
-      mojom::LayeredWindowUpdaterPtr layered_window_updater);
+      mojo::PendingRemote<mojom::LayeredWindowUpdater> layered_window_updater);
+
+  SoftwareOutputDeviceProxy(const SoftwareOutputDeviceProxy&) = delete;
+  SoftwareOutputDeviceProxy& operator=(const SoftwareOutputDeviceProxy&) =
+      delete;
+
   ~SoftwareOutputDeviceProxy() override;
 
   // SoftwareOutputDevice implementation.
-  void OnSwapBuffers(SwapBuffersCallback swap_ack_callback) override;
+  void OnSwapBuffers(SwapBuffersCallback swap_ack_callback,
+                     gfx::FrameData data) override;
 
   // SoftwareOutputDeviceBase implementation.
   void Resize(const gfx::Size& viewport_pixel_size,
@@ -34,7 +40,7 @@
   // Runs |swap_ack_callback_| after draw has happened.
   void DrawAck();
 
-  mojom::LayeredWindowUpdaterPtr layered_window_updater_;
+  mojo::Remote<mojom::LayeredWindowUpdater> layered_window_updater_;
 
   std::unique_ptr<SkCanvas> canvas_;
   bool waiting_on_draw_ack_ = false;
@@ -43,8 +49,6 @@
   base::WritableSharedMemoryMapping shm_;
 
   THREAD_CHECKER(thread_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceProxy);
 };
 
 }  // namespace viz
diff --git a/src/libcef/browser/osr/synthetic_gesture_target_osr.cc b/src/libcef/browser/osr/synthetic_gesture_target_osr.cc
index 977962f..1648d53 100644
--- a/src/libcef/browser/osr/synthetic_gesture_target_osr.cc
+++ b/src/libcef/browser/osr/synthetic_gesture_target_osr.cc
@@ -5,7 +5,6 @@
 #include "libcef/browser/osr/synthetic_gesture_target_osr.h"
 
 #include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/public/common/screen_info.h"
 #include "ui/events/gesture_detection/gesture_configuration.h"
 
 CefSyntheticGestureTargetOSR::CefSyntheticGestureTargetOSR(
@@ -42,9 +41,9 @@
                                                          latency_info);
 }
 
-content::SyntheticGestureParams::GestureSourceType
+content::mojom::GestureSourceType
 CefSyntheticGestureTargetOSR::GetDefaultSyntheticGestureSourceType() const {
-  return content::SyntheticGestureParams::MOUSE_INPUT;
+  return content::mojom::GestureSourceType::kMouseInput;
 }
 
 float CefSyntheticGestureTargetOSR::GetTouchSlopInDips() const {
diff --git a/src/libcef/browser/osr/synthetic_gesture_target_osr.h b/src/libcef/browser/osr/synthetic_gesture_target_osr.h
index f6471a5..5e96534 100644
--- a/src/libcef/browser/osr/synthetic_gesture_target_osr.h
+++ b/src/libcef/browser/osr/synthetic_gesture_target_osr.h
@@ -5,7 +5,6 @@
 #ifndef CEF_LIBCEF_BROWSER_OSR_SYNTHETIC_GESTURE_TARGET_OSR_H_
 #define CEF_LIBCEF_BROWSER_OSR_SYNTHETIC_GESTURE_TARGET_OSR_H_
 
-#include "base/macros.h"
 #include "content/browser/renderer_host/input/synthetic_gesture_target_base.h"
 
 // SyntheticGestureTarget implementation for OSR.
@@ -14,6 +13,10 @@
  public:
   explicit CefSyntheticGestureTargetOSR(content::RenderWidgetHostImpl* host);
 
+  CefSyntheticGestureTargetOSR(const CefSyntheticGestureTargetOSR&) = delete;
+  CefSyntheticGestureTargetOSR& operator=(const CefSyntheticGestureTargetOSR&) =
+      delete;
+
   // SyntheticGestureTargetBase:
   void DispatchWebTouchEventToPlatform(
       const blink::WebTouchEvent& web_touch,
@@ -29,14 +32,11 @@
       const ui::LatencyInfo& latency_info) override;
 
   // SyntheticGestureTarget:
-  content::SyntheticGestureParams::GestureSourceType
-  GetDefaultSyntheticGestureSourceType() const override;
+  content::mojom::GestureSourceType GetDefaultSyntheticGestureSourceType()
+      const override;
   float GetTouchSlopInDips() const override;
   float GetSpanSlopInDips() const override;
   float GetMinScalingSpanInDips() const override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefSyntheticGestureTargetOSR);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_OSR_SYNTHETIC_GESTURE_TARGET_OSR_H_
diff --git a/src/libcef/browser/osr/touch_handle_drawable_osr.cc b/src/libcef/browser/osr/touch_handle_drawable_osr.cc
new file mode 100644
index 0000000..96b0e8d
--- /dev/null
+++ b/src/libcef/browser/osr/touch_handle_drawable_osr.cc
@@ -0,0 +1,132 @@
+// Copyright 2022 The Chromium Embedded Framework Authors.
+// Portions copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/browser/osr/touch_handle_drawable_osr.h"
+
+#include <cmath>
+
+#include "libcef/browser/osr/render_widget_host_view_osr.h"
+
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace {
+// Copied from touch_handle_drawable_aura.cc
+
+// The distance by which a handle image is offset from the focal point (i.e.
+// text baseline) downwards.
+constexpr int kSelectionHandleVerticalVisualOffset = 2;
+
+// The padding around the selection handle image can be used to extend the
+// handle so that touch events near the selection handle image are
+// targeted to the selection handle.
+constexpr int kSelectionHandlePadding = 0;
+
+}  // namespace
+
+int CefTouchHandleDrawableOSR::counter_ = 0;
+
+CefTouchHandleDrawableOSR::CefTouchHandleDrawableOSR(
+    CefRenderWidgetHostViewOSR* rwhv)
+    : rwhv_(rwhv), id_(counter_++) {}
+
+void CefTouchHandleDrawableOSR::SetEnabled(bool enabled) {
+  if (enabled == enabled_) {
+    return;
+  }
+
+  enabled_ = enabled;
+
+  CefTouchHandleState touch_handle_state;
+  touch_handle_state.touch_handle_id = id_;
+  touch_handle_state.flags = CEF_THS_FLAG_ENABLED;
+  touch_handle_state.enabled = enabled_;
+  TouchHandleStateChanged(touch_handle_state);
+}
+
+void CefTouchHandleDrawableOSR::SetOrientation(
+    ui::TouchHandleOrientation orientation,
+    bool mirror_vertical,
+    bool mirror_horizontal) {
+  if (orientation == orientation_) {
+    return;
+  }
+
+  orientation_ = orientation;
+
+  CefSize size;
+  auto browser = rwhv_->browser_impl();
+  auto handler = browser->GetClient()->GetRenderHandler();
+  handler->GetTouchHandleSize(
+      browser.get(), static_cast<cef_horizontal_alignment_t>(orientation_),
+      size);
+
+  const gfx::Size& image_size = gfx::Size(size.width, size.height);
+  int handle_width = image_size.width() + 2 * kSelectionHandlePadding;
+  int handle_height = image_size.height() + 2 * kSelectionHandlePadding;
+  relative_bounds_ =
+      gfx::RectF(-kSelectionHandlePadding,
+                 kSelectionHandleVerticalVisualOffset - kSelectionHandlePadding,
+                 handle_width, handle_height);
+
+  CefTouchHandleState touch_handle_state;
+  touch_handle_state.touch_handle_id = id_;
+  touch_handle_state.flags = CEF_THS_FLAG_ORIENTATION;
+  touch_handle_state.orientation =
+      static_cast<cef_horizontal_alignment_t>(orientation_);
+  touch_handle_state.mirror_vertical = mirror_vertical;
+  touch_handle_state.mirror_horizontal = mirror_horizontal;
+  TouchHandleStateChanged(touch_handle_state);
+}
+
+void CefTouchHandleDrawableOSR::SetOrigin(const gfx::PointF& position) {
+  if (position == origin_position_) {
+    return;
+  }
+
+  origin_position_ = position;
+
+  CefTouchHandleState touch_handle_state;
+  touch_handle_state.touch_handle_id = id_;
+  touch_handle_state.flags = CEF_THS_FLAG_ORIGIN;
+  touch_handle_state.origin = {static_cast<int>(std::round(position.x())),
+                               static_cast<int>(std::round(position.y()))};
+  TouchHandleStateChanged(touch_handle_state);
+}
+
+void CefTouchHandleDrawableOSR::SetAlpha(float alpha) {
+  if (alpha == alpha_) {
+    return;
+  }
+
+  alpha_ = alpha;
+
+  CefTouchHandleState touch_handle_state;
+  touch_handle_state.touch_handle_id = id_;
+  touch_handle_state.flags = CEF_THS_FLAG_ALPHA;
+  touch_handle_state.alpha = alpha_;
+  TouchHandleStateChanged(touch_handle_state);
+}
+
+gfx::RectF CefTouchHandleDrawableOSR::GetVisibleBounds() const {
+  gfx::RectF bounds = relative_bounds_;
+  bounds.Offset(origin_position_.x(), origin_position_.y());
+  bounds.Inset(gfx::InsetsF::TLBR(
+      kSelectionHandlePadding,
+      kSelectionHandlePadding + kSelectionHandleVerticalVisualOffset,
+      kSelectionHandlePadding, kSelectionHandlePadding));
+  return bounds;
+}
+
+float CefTouchHandleDrawableOSR::GetDrawableHorizontalPaddingRatio() const {
+  return 0.0f;
+}
+
+void CefTouchHandleDrawableOSR::TouchHandleStateChanged(
+    const CefTouchHandleState& state) {
+  auto browser = rwhv_->browser_impl();
+  auto handler = browser->GetClient()->GetRenderHandler();
+  handler->OnTouchHandleStateChanged(browser.get(), state);
+}
diff --git a/src/libcef/browser/osr/touch_handle_drawable_osr.h b/src/libcef/browser/osr/touch_handle_drawable_osr.h
new file mode 100644
index 0000000..4de5c26
--- /dev/null
+++ b/src/libcef/browser/osr/touch_handle_drawable_osr.h
@@ -0,0 +1,59 @@
+// Copyright 2022 The Chromium Embedded Framework Authors.
+// Portions copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_BROWSER_OSR_TOUCH_HANDLE_DRAWABLE_OSR_H_
+#define CEF_LIBCEF_BROWSER_OSR_TOUCH_HANDLE_DRAWABLE_OSR_H_
+
+#include "include/internal/cef_types_wrappers.h"
+
+#include "base/memory/raw_ptr.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/touch_selection/touch_handle.h"
+#include "ui/touch_selection/touch_handle_orientation.h"
+#include "ui/touch_selection/ui_touch_selection_export.h"
+
+class CefRenderWidgetHostViewOSR;
+
+// Copied from TouchHandleDrawableAura.
+class CefTouchHandleDrawableOSR : public ui::TouchHandleDrawable {
+ public:
+  explicit CefTouchHandleDrawableOSR(CefRenderWidgetHostViewOSR* rwhv);
+
+  CefTouchHandleDrawableOSR(const CefTouchHandleDrawableOSR&) = delete;
+  CefTouchHandleDrawableOSR& operator=(const CefTouchHandleDrawableOSR&) =
+      delete;
+
+ private:
+  // TouchHandleDrawable:
+  void SetEnabled(bool enabled) override;
+  void SetOrientation(ui::TouchHandleOrientation orientation,
+                      bool mirror_vertical,
+                      bool mirror_horizontal) override;
+  void SetOrigin(const gfx::PointF& position) override;
+  void SetAlpha(float alpha) override;
+  gfx::RectF GetVisibleBounds() const override;
+  float GetDrawableHorizontalPaddingRatio() const override;
+
+  // Pass the current touch handle state to the CefRenderHandler.
+  void TouchHandleStateChanged(const CefTouchHandleState& state);
+
+  raw_ptr<CefRenderWidgetHostViewOSR> rwhv_;
+
+  float alpha_ = 0.f;
+  static int counter_;
+  bool enabled_ = false;
+  int id_;
+  ui::TouchHandleOrientation orientation_ =
+      ui::TouchHandleOrientation::UNDEFINED;
+
+  // Origin position of the handle set via SetOrigin, in coordinate space of
+  // selection controller client (i.e. handle's parent).
+  gfx::PointF origin_position_;
+
+  // Handle bounds relative to the focal position.
+  gfx::RectF relative_bounds_ = gfx::RectF(0.0F, 0.0F, 24.0F, 24.0F);
+};
+
+#endif
diff --git a/src/libcef/browser/osr/touch_selection_controller_client_osr.cc b/src/libcef/browser/osr/touch_selection_controller_client_osr.cc
new file mode 100644
index 0000000..634e0f4
--- /dev/null
+++ b/src/libcef/browser/osr/touch_selection_controller_client_osr.cc
@@ -0,0 +1,550 @@
+// Copyright 2022 The Chromium Embedded Framework Authors.
+// Portions copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/browser/osr/touch_selection_controller_client_osr.h"
+
+#include <cmath>
+#include <set>
+
+#include "libcef/browser/osr/render_widget_host_view_osr.h"
+#include "libcef/browser/osr/touch_handle_drawable_osr.h"
+
+#include "base/functional/bind.h"
+#include "content/browser/renderer_host/render_widget_host_delegate.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/public/browser/context_menu_params.h"
+#include "content/public/browser/render_view_host.h"
+#include "ui/base/clipboard/clipboard.h"
+#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
+#include "ui/base/pointer/touch_editing_controller.h"
+#include "ui/gfx/geometry/point_conversions.h"
+#include "ui/gfx/geometry/size_conversions.h"
+
+namespace {
+
+// Delay before showing the quick menu, in milliseconds.
+constexpr int kQuickMenuDelayInMs = 100;
+
+constexpr cef_quick_menu_edit_state_flags_t kMenuCommands[] = {
+    QM_EDITFLAG_CAN_ELLIPSIS, QM_EDITFLAG_CAN_CUT, QM_EDITFLAG_CAN_COPY,
+    QM_EDITFLAG_CAN_PASTE};
+
+constexpr int kInvalidCommandId = -1;
+constexpr cef_event_flags_t kEmptyEventFlags =
+    static_cast<cef_event_flags_t>(0);
+
+class CefRunQuickMenuCallbackImpl : public CefRunQuickMenuCallback {
+ public:
+  using Callback = base::OnceCallback<void(int, int)>;
+
+  explicit CefRunQuickMenuCallbackImpl(Callback callback)
+      : callback_(std::move(callback)) {}
+
+  CefRunQuickMenuCallbackImpl(const CefRunQuickMenuCallbackImpl&) = delete;
+  CefRunQuickMenuCallbackImpl& operator=(const CefRunQuickMenuCallbackImpl&) =
+      delete;
+
+  ~CefRunQuickMenuCallbackImpl() {
+    if (!callback_.is_null()) {
+      // The callback is still pending. Cancel it now.
+      if (CEF_CURRENTLY_ON_UIT()) {
+        RunNow(std::move(callback_), kInvalidCommandId, kEmptyEventFlags);
+      } else {
+        CEF_POST_TASK(CEF_UIT,
+                      base::BindOnce(&CefRunQuickMenuCallbackImpl::RunNow,
+                                     std::move(callback_), kInvalidCommandId,
+                                     kEmptyEventFlags));
+      }
+    }
+  }
+
+  void Continue(int command_id, cef_event_flags_t event_flags) override {
+    if (CEF_CURRENTLY_ON_UIT()) {
+      if (!callback_.is_null()) {
+        RunNow(std::move(callback_), command_id, event_flags);
+      }
+    } else {
+      CEF_POST_TASK(CEF_UIT,
+                    base::BindOnce(&CefRunQuickMenuCallbackImpl::Continue, this,
+                                   command_id, event_flags));
+    }
+  }
+
+  void Cancel() override { Continue(kInvalidCommandId, kEmptyEventFlags); }
+
+  void Disconnect() { callback_.Reset(); }
+
+ private:
+  static void RunNow(Callback callback,
+                     int command_id,
+                     cef_event_flags_t event_flags) {
+    CEF_REQUIRE_UIT();
+    std::move(callback).Run(command_id, event_flags);
+  }
+
+  Callback callback_;
+
+  IMPLEMENT_REFCOUNTING(CefRunQuickMenuCallbackImpl);
+};
+
+}  // namespace
+
+CefTouchSelectionControllerClientOSR::CefTouchSelectionControllerClientOSR(
+    CefRenderWidgetHostViewOSR* rwhv)
+    : rwhv_(rwhv),
+      internal_client_(rwhv),
+      active_client_(&internal_client_),
+      active_menu_client_(this),
+      quick_menu_timer_(
+          FROM_HERE,
+          base::Milliseconds(kQuickMenuDelayInMs),
+          base::BindRepeating(
+              &CefTouchSelectionControllerClientOSR::ShowQuickMenu,
+              base::Unretained(this))),
+      weak_ptr_factory_(this) {
+  DCHECK(rwhv_);
+}
+
+CefTouchSelectionControllerClientOSR::~CefTouchSelectionControllerClientOSR() {
+  for (auto& observer : observers_) {
+    observer.OnManagerWillDestroy(this);
+  }
+}
+
+void CefTouchSelectionControllerClientOSR::CloseQuickMenuAndHideHandles() {
+  CloseQuickMenu();
+  rwhv_->selection_controller()->HideAndDisallowShowingAutomatically();
+}
+
+void CefTouchSelectionControllerClientOSR::OnWindowMoved() {
+  UpdateQuickMenu();
+}
+
+void CefTouchSelectionControllerClientOSR::OnTouchDown() {
+  touch_down_ = true;
+  UpdateQuickMenu();
+}
+
+void CefTouchSelectionControllerClientOSR::OnTouchUp() {
+  touch_down_ = false;
+  UpdateQuickMenu();
+}
+
+void CefTouchSelectionControllerClientOSR::OnScrollStarted() {
+  scroll_in_progress_ = true;
+  rwhv_->selection_controller()->SetTemporarilyHidden(true);
+  UpdateQuickMenu();
+}
+
+void CefTouchSelectionControllerClientOSR::OnScrollCompleted() {
+  scroll_in_progress_ = false;
+  active_client_->DidScroll();
+  rwhv_->selection_controller()->SetTemporarilyHidden(false);
+  UpdateQuickMenu();
+}
+
+bool CefTouchSelectionControllerClientOSR::HandleContextMenu(
+    const content::ContextMenuParams& params) {
+  if ((params.source_type == ui::MENU_SOURCE_LONG_PRESS ||
+       params.source_type == ui::MENU_SOURCE_LONG_TAP) &&
+      params.is_editable && params.selection_text.empty() &&
+      IsQuickMenuAvailable()) {
+    quick_menu_requested_ = true;
+    UpdateQuickMenu();
+    return true;
+  }
+
+  const bool from_touch = params.source_type == ui::MENU_SOURCE_LONG_PRESS ||
+                          params.source_type == ui::MENU_SOURCE_LONG_TAP ||
+                          params.source_type == ui::MENU_SOURCE_TOUCH;
+  if (from_touch && !params.selection_text.empty()) {
+    return true;
+  }
+
+  rwhv_->selection_controller()->HideAndDisallowShowingAutomatically();
+  return false;
+}
+
+void CefTouchSelectionControllerClientOSR::DidStopFlinging() {
+  OnScrollCompleted();
+}
+
+void CefTouchSelectionControllerClientOSR::OnSwipeToMoveCursorBegin() {
+  rwhv_->selection_controller()->OnSwipeToMoveCursorBegin();
+  OnSelectionEvent(ui::INSERTION_HANDLE_DRAG_STARTED);
+}
+
+void CefTouchSelectionControllerClientOSR::OnSwipeToMoveCursorEnd() {
+  rwhv_->selection_controller()->OnSwipeToMoveCursorEnd();
+  OnSelectionEvent(ui::INSERTION_HANDLE_DRAG_STOPPED);
+}
+
+void CefTouchSelectionControllerClientOSR::OnClientHitTestRegionUpdated(
+    ui::TouchSelectionControllerClient* client) {
+  if (client != active_client_ || !rwhv_->selection_controller() ||
+      rwhv_->selection_controller()->active_status() ==
+          ui::TouchSelectionController::INACTIVE) {
+    return;
+  }
+
+  active_client_->DidScroll();
+}
+
+void CefTouchSelectionControllerClientOSR::UpdateClientSelectionBounds(
+    const gfx::SelectionBound& start,
+    const gfx::SelectionBound& end) {
+  UpdateClientSelectionBounds(start, end, &internal_client_, this);
+}
+
+void CefTouchSelectionControllerClientOSR::UpdateClientSelectionBounds(
+    const gfx::SelectionBound& start,
+    const gfx::SelectionBound& end,
+    ui::TouchSelectionControllerClient* client,
+    ui::TouchSelectionMenuClient* menu_client) {
+  if (client != active_client_ &&
+      (start.type() == gfx::SelectionBound::EMPTY || !start.visible()) &&
+      (end.type() == gfx::SelectionBound::EMPTY || !end.visible()) &&
+      (manager_selection_start_.type() != gfx::SelectionBound::EMPTY ||
+       manager_selection_end_.type() != gfx::SelectionBound::EMPTY)) {
+    return;
+  }
+
+  active_client_ = client;
+  active_menu_client_ = menu_client;
+  manager_selection_start_ = start;
+  manager_selection_end_ = end;
+
+  // Notify TouchSelectionController if anything should change here. Only
+  // update if the client is different and not making a change to empty, or
+  // is the same client.
+  GetTouchSelectionController()->OnSelectionBoundsChanged(start, end);
+}
+
+void CefTouchSelectionControllerClientOSR::InvalidateClient(
+    ui::TouchSelectionControllerClient* client) {
+  DCHECK(client != &internal_client_);
+  if (client == active_client_) {
+    active_client_ = &internal_client_;
+    active_menu_client_ = this;
+  }
+}
+
+ui::TouchSelectionController*
+CefTouchSelectionControllerClientOSR::GetTouchSelectionController() {
+  return rwhv_->selection_controller();
+}
+
+void CefTouchSelectionControllerClientOSR::AddObserver(
+    TouchSelectionControllerClientManager::Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void CefTouchSelectionControllerClientOSR::RemoveObserver(
+    TouchSelectionControllerClientManager::Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+bool CefTouchSelectionControllerClientOSR::IsQuickMenuAvailable() const {
+  DCHECK(active_menu_client_);
+
+  const auto is_enabled = [this](cef_quick_menu_edit_state_flags_t command) {
+    return active_menu_client_->IsCommandIdEnabled(command);
+  };
+  return std::any_of(std::cbegin(kMenuCommands), std::cend(kMenuCommands),
+                     is_enabled);
+}
+
+void CefTouchSelectionControllerClientOSR::CloseQuickMenu() {
+  if (!quick_menu_running_) {
+    return;
+  }
+
+  quick_menu_running_ = false;
+
+  auto browser = rwhv_->browser_impl();
+  if (auto handler = browser->client()->GetContextMenuHandler()) {
+    handler->OnQuickMenuDismissed(browser.get(), browser->GetFocusedFrame());
+  }
+}
+
+void CefTouchSelectionControllerClientOSR::ShowQuickMenu() {
+  auto browser = rwhv_->browser_impl();
+  if (auto handler = browser->client()->GetContextMenuHandler()) {
+    gfx::RectF rect =
+        rwhv_->selection_controller()->GetVisibleRectBetweenBounds();
+
+    gfx::PointF origin = rect.origin();
+    gfx::PointF bottom_right = rect.bottom_right();
+    auto client_bounds = gfx::RectF(rwhv_->GetViewBounds());
+    origin.SetToMax(client_bounds.origin());
+    bottom_right.SetToMin(client_bounds.bottom_right());
+    if (origin.x() > bottom_right.x() || origin.y() > bottom_right.y()) {
+      return;
+    }
+
+    gfx::Vector2dF diagonal = bottom_right - origin;
+    gfx::SizeF size(diagonal.x(), diagonal.y());
+
+    int quickmenuflags = 0;
+    for (const auto& command : kMenuCommands) {
+      if (active_menu_client_->IsCommandIdEnabled(command)) {
+        quickmenuflags |= command;
+      }
+    }
+
+    CefRefPtr<CefRunQuickMenuCallbackImpl> callbackImpl(
+        new CefRunQuickMenuCallbackImpl(base::BindOnce(
+            &CefTouchSelectionControllerClientOSR::ExecuteCommand,
+            weak_ptr_factory_.GetWeakPtr())));
+
+    quick_menu_running_ = true;
+    if (!handler->RunQuickMenu(
+            browser, browser->GetFocusedFrame(),
+            {static_cast<int>(std::round(origin.x())),
+             static_cast<int>(std::round(origin.y()))},
+            {static_cast<int>(std::round(size.width())),
+             static_cast<int>(std::round(size.height()))},
+            static_cast<CefContextMenuHandler::QuickMenuEditStateFlags>(
+                quickmenuflags),
+            callbackImpl)) {
+      callbackImpl->Disconnect();
+      CloseQuickMenu();
+    }
+  }
+}
+
+void CefTouchSelectionControllerClientOSR::UpdateQuickMenu() {
+  // Hide the quick menu if there is any. This should happen even if the menu
+  // should be shown again, in order to update its location or content.
+  if (quick_menu_running_) {
+    CloseQuickMenu();
+  } else {
+    quick_menu_timer_.Stop();
+  }
+
+  // Start timer to show quick menu if necessary.
+  if (ShouldShowQuickMenu()) {
+    quick_menu_timer_.Reset();
+  }
+}
+
+bool CefTouchSelectionControllerClientOSR::SupportsAnimation() const {
+  return false;
+}
+
+bool CefTouchSelectionControllerClientOSR::InternalClient::SupportsAnimation()
+    const {
+  DCHECK(false);
+  return false;
+}
+
+void CefTouchSelectionControllerClientOSR::SetNeedsAnimate() {
+  DCHECK(false);
+}
+
+void CefTouchSelectionControllerClientOSR::InternalClient::SetNeedsAnimate() {
+  DCHECK(false);
+}
+
+void CefTouchSelectionControllerClientOSR::MoveCaret(
+    const gfx::PointF& position) {
+  active_client_->MoveCaret(position);
+}
+
+void CefTouchSelectionControllerClientOSR::InternalClient::MoveCaret(
+    const gfx::PointF& position) {
+  if (auto host_delegate = rwhv_->host()->delegate()) {
+    host_delegate->MoveCaret(gfx::ToRoundedPoint(position));
+  }
+}
+
+void CefTouchSelectionControllerClientOSR::MoveRangeSelectionExtent(
+    const gfx::PointF& extent) {
+  active_client_->MoveRangeSelectionExtent(extent);
+}
+
+void CefTouchSelectionControllerClientOSR::InternalClient::
+    MoveRangeSelectionExtent(const gfx::PointF& extent) {
+  if (auto host_delegate = rwhv_->host()->delegate()) {
+    host_delegate->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent));
+  }
+}
+
+void CefTouchSelectionControllerClientOSR::SelectBetweenCoordinates(
+    const gfx::PointF& base,
+    const gfx::PointF& extent) {
+  active_client_->SelectBetweenCoordinates(base, extent);
+}
+
+void CefTouchSelectionControllerClientOSR::InternalClient::
+    SelectBetweenCoordinates(const gfx::PointF& base,
+                             const gfx::PointF& extent) {
+  if (auto host_delegate = rwhv_->host()->delegate()) {
+    host_delegate->SelectRange(gfx::ToRoundedPoint(base),
+                               gfx::ToRoundedPoint(extent));
+  }
+}
+
+void CefTouchSelectionControllerClientOSR::OnSelectionEvent(
+    ui::SelectionEventType event) {
+  // This function (implicitly) uses active_menu_client_, so we don't go to the
+  // active view for this.
+  switch (event) {
+    case ui::SELECTION_HANDLES_SHOWN:
+      quick_menu_requested_ = true;
+      [[fallthrough]];
+    case ui::INSERTION_HANDLE_SHOWN:
+      UpdateQuickMenu();
+      break;
+    case ui::SELECTION_HANDLES_CLEARED:
+    case ui::INSERTION_HANDLE_CLEARED:
+      quick_menu_requested_ = false;
+      UpdateQuickMenu();
+      break;
+    case ui::SELECTION_HANDLE_DRAG_STARTED:
+    case ui::INSERTION_HANDLE_DRAG_STARTED:
+      handle_drag_in_progress_ = true;
+      UpdateQuickMenu();
+      break;
+    case ui::SELECTION_HANDLE_DRAG_STOPPED:
+    case ui::INSERTION_HANDLE_DRAG_STOPPED:
+      handle_drag_in_progress_ = false;
+      UpdateQuickMenu();
+      break;
+    case ui::SELECTION_HANDLES_MOVED:
+    case ui::INSERTION_HANDLE_MOVED:
+      UpdateQuickMenu();
+      break;
+    case ui::INSERTION_HANDLE_TAPPED:
+      quick_menu_requested_ = !quick_menu_requested_;
+      UpdateQuickMenu();
+      break;
+  }
+}
+
+void CefTouchSelectionControllerClientOSR::InternalClient::OnSelectionEvent(
+    ui::SelectionEventType event) {
+  DCHECK(false);
+}
+
+void CefTouchSelectionControllerClientOSR::OnDragUpdate(
+    const ui::TouchSelectionDraggable::Type type,
+    const gfx::PointF& position) {}
+
+void CefTouchSelectionControllerClientOSR::InternalClient::OnDragUpdate(
+    const ui::TouchSelectionDraggable::Type type,
+    const gfx::PointF& position) {
+  DCHECK(false);
+}
+
+std::unique_ptr<ui::TouchHandleDrawable>
+CefTouchSelectionControllerClientOSR::CreateDrawable() {
+  return std::make_unique<CefTouchHandleDrawableOSR>(rwhv_);
+}
+
+void CefTouchSelectionControllerClientOSR::DidScroll() {}
+
+std::unique_ptr<ui::TouchHandleDrawable>
+CefTouchSelectionControllerClientOSR::InternalClient::CreateDrawable() {
+  DCHECK(false);
+  return nullptr;
+}
+
+void CefTouchSelectionControllerClientOSR::InternalClient::DidScroll() {
+  DCHECK(false);
+}
+
+bool CefTouchSelectionControllerClientOSR::IsCommandIdEnabled(
+    int command_id) const {
+  bool editable = rwhv_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE;
+  bool readable = rwhv_->GetTextInputType() != ui::TEXT_INPUT_TYPE_PASSWORD;
+  bool has_selection = !rwhv_->GetSelectedText().empty();
+  switch (command_id) {
+    case QM_EDITFLAG_CAN_ELLIPSIS:
+      return true;  // Always allowed to show the ellipsis button.
+    case QM_EDITFLAG_CAN_CUT:
+      return editable && readable && has_selection;
+    case QM_EDITFLAG_CAN_COPY:
+      return readable && has_selection;
+    case QM_EDITFLAG_CAN_PASTE: {
+      std::u16string result;
+      ui::DataTransferEndpoint data_dst = ui::DataTransferEndpoint(
+          ui::EndpointType::kDefault, /*notify_if_restricted=*/false);
+      ui::Clipboard::GetForCurrentThread()->ReadText(
+          ui::ClipboardBuffer::kCopyPaste, &data_dst, &result);
+      return editable && !result.empty();
+    }
+    default:
+      return false;
+  }
+}
+
+void CefTouchSelectionControllerClientOSR::ExecuteCommand(int command_id,
+                                                          int event_flags) {
+  if (command_id == kInvalidCommandId) {
+    return;
+  }
+
+  if (command_id != QM_EDITFLAG_CAN_ELLIPSIS) {
+    rwhv_->selection_controller()->HideAndDisallowShowingAutomatically();
+  }
+
+  content::RenderWidgetHostDelegate* host_delegate = rwhv_->host()->delegate();
+  if (!host_delegate) {
+    return;
+  }
+
+  auto browser = rwhv_->browser_impl();
+  if (auto handler = browser->client()->GetContextMenuHandler()) {
+    if (handler->OnQuickMenuCommand(
+            browser.get(), browser->GetFocusedFrame(), command_id,
+            static_cast<cef_event_flags_t>(event_flags))) {
+      return;
+    }
+  }
+
+  switch (command_id) {
+    case QM_EDITFLAG_CAN_CUT:
+      host_delegate->Cut();
+      break;
+    case QM_EDITFLAG_CAN_COPY:
+      host_delegate->Copy();
+      break;
+    case QM_EDITFLAG_CAN_PASTE:
+      host_delegate->Paste();
+      break;
+    case QM_EDITFLAG_CAN_ELLIPSIS:
+      CloseQuickMenu();
+      RunContextMenu();
+      break;
+    default:
+      // Invalid command, do nothing.
+      // Also reached when callback is destroyed/cancelled.
+      break;
+  }
+}
+
+void CefTouchSelectionControllerClientOSR::RunContextMenu() {
+  const gfx::RectF anchor_rect =
+      rwhv_->selection_controller()->GetVisibleRectBetweenBounds();
+  const gfx::PointF anchor_point =
+      gfx::PointF(anchor_rect.CenterPoint().x(), anchor_rect.y());
+  rwhv_->host()->ShowContextMenuAtPoint(gfx::ToRoundedPoint(anchor_point),
+                                        ui::MENU_SOURCE_TOUCH_EDIT_MENU);
+
+  // Hide selection handles after getting rect-between-bounds from touch
+  // selection controller; otherwise, rect would be empty and the above
+  // calculations would be invalid.
+  rwhv_->selection_controller()->HideAndDisallowShowingAutomatically();
+}
+
+bool CefTouchSelectionControllerClientOSR::ShouldShowQuickMenu() {
+  return quick_menu_requested_ && !touch_down_ && !scroll_in_progress_ &&
+         !handle_drag_in_progress_ && IsQuickMenuAvailable();
+}
+
+std::u16string CefTouchSelectionControllerClientOSR::GetSelectedText() {
+  return rwhv_->GetSelectedText();
+}
diff --git a/src/libcef/browser/osr/touch_selection_controller_client_osr.h b/src/libcef/browser/osr/touch_selection_controller_client_osr.h
new file mode 100644
index 0000000..2ec8e91
--- /dev/null
+++ b/src/libcef/browser/osr/touch_selection_controller_client_osr.h
@@ -0,0 +1,160 @@
+// Copyright 2022 The Chromium Embedded Framework Authors.
+// Portions copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_BROWSER_OSR_TOUCH_SELECTION_CONTROLLER_CLIENT_OSR_H_
+#define CEF_LIBCEF_BROWSER_OSR_TOUCH_SELECTION_CONTROLLER_CLIENT_OSR_H_
+
+#include <memory>
+
+#include "base/memory/raw_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "base/timer/timer.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/touch_selection_controller_client_manager.h"
+#include "ui/touch_selection/touch_selection_controller.h"
+#include "ui/touch_selection/touch_selection_menu_runner.h"
+
+namespace content {
+struct ContextMenuParams;
+}
+
+class CefRenderWidgetHostViewOSR;
+
+// An implementation of |TouchSelectionControllerClient| to be used in OSR's
+// implementation of touch selection for contents.
+// Copied from TouchSelectionControllerClientAura.
+class CefTouchSelectionControllerClientOSR
+    : public ui::TouchSelectionControllerClient,
+      public ui::TouchSelectionMenuClient,
+      public content::TouchSelectionControllerClientManager {
+ public:
+  explicit CefTouchSelectionControllerClientOSR(
+      CefRenderWidgetHostViewOSR* rwhv);
+
+  CefTouchSelectionControllerClientOSR(
+      const CefTouchSelectionControllerClientOSR&) = delete;
+  CefTouchSelectionControllerClientOSR& operator=(
+      const CefTouchSelectionControllerClientOSR&) = delete;
+
+  ~CefTouchSelectionControllerClientOSR() override;
+
+  void CloseQuickMenuAndHideHandles();
+
+  void OnWindowMoved();
+
+  // Called on first touch down/last touch up to hide/show the quick menu.
+  void OnTouchDown();
+
+  void OnTouchUp();
+
+  // Called when touch scroll starts/completes to hide/show touch handles and
+  // the quick menu.
+  void OnScrollStarted();
+
+  void OnScrollCompleted();
+
+  // Gives an opportunity to the client to handle context menu request and show
+  // the quick menu instead, if appropriate. Returns |true| to indicate that no
+  // further handling is needed.
+  // TODO(mohsen): This is to match Chrome on Android behavior. However, it is
+  // better not to send context menu request from the renderer in this case and
+  // instead decide in the client about showing the quick menu in response to
+  // selection events. (http://crbug.com/548245)
+  bool HandleContextMenu(const content::ContextMenuParams& params);
+
+  void UpdateClientSelectionBounds(const gfx::SelectionBound& start,
+                                   const gfx::SelectionBound& end);
+
+  // TouchSelectionControllerClientManager.
+  void DidStopFlinging() override;
+  void OnSwipeToMoveCursorBegin() override;
+  void OnSwipeToMoveCursorEnd() override;
+  void OnClientHitTestRegionUpdated(
+      ui::TouchSelectionControllerClient* client) override;
+  void UpdateClientSelectionBounds(
+      const gfx::SelectionBound& start,
+      const gfx::SelectionBound& end,
+      ui::TouchSelectionControllerClient* client,
+      ui::TouchSelectionMenuClient* menu_client) override;
+  void InvalidateClient(ui::TouchSelectionControllerClient* client) override;
+  ui::TouchSelectionController* GetTouchSelectionController() override;
+  void AddObserver(
+      TouchSelectionControllerClientManager::Observer* observer) override;
+  void RemoveObserver(
+      TouchSelectionControllerClientManager::Observer* observer) override;
+
+ private:
+  class EnvEventObserver;
+
+  bool IsQuickMenuAvailable() const;
+  void CloseQuickMenu();
+  void ShowQuickMenu();
+  void UpdateQuickMenu();
+
+  // ui::TouchSelectionControllerClient:
+  bool SupportsAnimation() const override;
+  void SetNeedsAnimate() override;
+  void MoveCaret(const gfx::PointF& position) override;
+  void MoveRangeSelectionExtent(const gfx::PointF& extent) override;
+  void SelectBetweenCoordinates(const gfx::PointF& base,
+                                const gfx::PointF& extent) override;
+  void OnSelectionEvent(ui::SelectionEventType event) override;
+  void OnDragUpdate(const ui::TouchSelectionDraggable::Type type,
+                    const gfx::PointF& position) override;
+  std::unique_ptr<ui::TouchHandleDrawable> CreateDrawable() override;
+  void DidScroll() override;
+
+  // ui::TouchSelectionMenuClient:
+  bool IsCommandIdEnabled(int command_id) const override;
+  void ExecuteCommand(int command_id, int event_flags) override;
+  void RunContextMenu() override;
+  bool ShouldShowQuickMenu() override;
+  std::u16string GetSelectedText() override;
+
+  // Not owned, non-null for the lifetime of this object.
+  raw_ptr<CefRenderWidgetHostViewOSR> rwhv_;
+
+  class InternalClient final : public ui::TouchSelectionControllerClient {
+   public:
+    explicit InternalClient(CefRenderWidgetHostViewOSR* rwhv) : rwhv_(rwhv) {}
+    ~InternalClient() final {}
+
+    bool SupportsAnimation() const final;
+    void SetNeedsAnimate() final;
+    void MoveCaret(const gfx::PointF& position) final;
+    void MoveRangeSelectionExtent(const gfx::PointF& extent) final;
+    void SelectBetweenCoordinates(const gfx::PointF& base,
+                                  const gfx::PointF& extent) final;
+    void OnSelectionEvent(ui::SelectionEventType event) final;
+    void OnDragUpdate(const ui::TouchSelectionDraggable::Type type,
+                      const gfx::PointF& position) final;
+    std::unique_ptr<ui::TouchHandleDrawable> CreateDrawable() final;
+    void DidScroll() override;
+
+   private:
+    raw_ptr<CefRenderWidgetHostViewOSR> rwhv_;
+  } internal_client_;
+
+  // Keep track of which client interface to use.
+  raw_ptr<TouchSelectionControllerClient> active_client_;
+  raw_ptr<TouchSelectionMenuClient> active_menu_client_;
+  gfx::SelectionBound manager_selection_start_;
+  gfx::SelectionBound manager_selection_end_;
+
+  base::ObserverList<TouchSelectionControllerClientManager::Observer>
+      observers_;
+
+  base::RetainingOneShotTimer quick_menu_timer_;
+  bool quick_menu_requested_ = false;
+  bool quick_menu_running_ = false;
+  bool touch_down_ = false;
+  bool scroll_in_progress_ = false;
+  bool handle_drag_in_progress_ = false;
+
+  base::WeakPtrFactory<CefTouchSelectionControllerClientOSR> weak_ptr_factory_;
+};
+
+#endif
diff --git a/src/libcef/browser/osr/video_consumer_osr.cc b/src/libcef/browser/osr/video_consumer_osr.cc
index 66e656d..ee0e0c9 100644
--- a/src/libcef/browser/osr/video_consumer_osr.cc
+++ b/src/libcef/browser/osr/video_consumer_osr.cc
@@ -4,10 +4,10 @@
 
 #include "libcef/browser/osr/video_consumer_osr.h"
 
-#include "libcef/browser/browser_host_impl.h"
 #include "libcef/browser/osr/render_widget_host_view_osr.h"
 
 #include "media/base/video_frame_metadata.h"
+#include "media/capture/mojom/video_capture_buffer.mojom.h"
 #include "media/capture/mojom/video_capture_types.mojom.h"
 #include "ui/gfx/skbitmap_operations.h"
 
@@ -30,8 +30,7 @@
 
 CefVideoConsumerOSR::CefVideoConsumerOSR(CefRenderWidgetHostViewOSR* view)
     : view_(view), video_capturer_(view->CreateVideoCapturer()) {
-  video_capturer_->SetFormat(media::PIXEL_FORMAT_ARGB,
-                             gfx::ColorSpace::CreateREC709());
+  video_capturer_->SetFormat(media::PIXEL_FORMAT_ARGB);
 
   // Always use the highest resolution within constraints that doesn't exceed
   // the source size.
@@ -46,7 +45,7 @@
 
 void CefVideoConsumerOSR::SetActive(bool active) {
   if (active) {
-    video_capturer_->Start(this);
+    video_capturer_->Start(this, viz::mojom::BufferFormatPreference::kDefault);
   } else {
     video_capturer_->Stop();
   }
@@ -57,8 +56,9 @@
 }
 
 void CefVideoConsumerOSR::SizeChanged(const gfx::Size& size_in_pixels) {
-  if (size_in_pixels_ == size_in_pixels)
+  if (size_in_pixels_ == size_in_pixels) {
     return;
+  }
   size_in_pixels_ = size_in_pixels;
 
   // Capture resolution will be held constant.
@@ -67,7 +67,7 @@
 }
 
 void CefVideoConsumerOSR::RequestRefreshFrame(
-    const base::Optional<gfx::Rect>& bounds_in_pixels) {
+    const absl::optional<gfx::Rect>& bounds_in_pixels) {
   bounds_in_pixels_ = bounds_in_pixels;
   video_capturer_->RequestRefreshFrame();
 }
@@ -81,17 +81,25 @@
 //   the rest of the frame having been letterboxed to adhere to resolution
 //   constraints.
 void CefVideoConsumerOSR::OnFrameCaptured(
-    base::ReadOnlySharedMemoryRegion data,
-    ::media::mojom::VideoFrameInfoPtr info,
+    media::mojom::VideoBufferHandlePtr data,
+    media::mojom::VideoFrameInfoPtr info,
     const gfx::Rect& content_rect,
     mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
         callbacks) {
   ScopedVideoFrameDone scoped_done(std::move(callbacks));
 
-  if (!data.IsValid())
-    return;
+  CHECK(data->is_read_only_shmem_region());
+  base::ReadOnlySharedMemoryRegion& shmem_region =
+      data->get_read_only_shmem_region();
 
-  base::ReadOnlySharedMemoryMapping mapping = data.Map();
+  // The |data| parameter is not nullable and mojo type mapping for
+  // `base::ReadOnlySharedMemoryRegion` defines that nullable version of it is
+  // the same type, with null check being equivalent to IsValid() check. Given
+  // the above, we should never be able to receive a read only shmem region that
+  // is not valid - mojo will enforce it for us.
+  DCHECK(shmem_region.IsValid());
+
+  base::ReadOnlySharedMemoryMapping mapping = shmem_region.Map();
   if (!mapping.IsValid()) {
     DLOG(ERROR) << "Shared memory mapping failed.";
     return;
@@ -106,15 +114,14 @@
   // API requires a non-const pointer. So, cast away the const.
   void* const pixels = const_cast<void*>(mapping.memory());
 
-  media::VideoFrameMetadata metadata;
-  metadata.MergeInternalValuesFrom(info->metadata);
+  media::VideoFrameMetadata metadata = info->metadata;
   gfx::Rect damage_rect;
 
   if (bounds_in_pixels_) {
     // Use the bounds passed to RequestRefreshFrame().
     damage_rect = gfx::Rect(info->coded_size);
     damage_rect.Intersect(*bounds_in_pixels_);
-    bounds_in_pixels_ = base::nullopt;
+    bounds_in_pixels_ = absl::nullopt;
   } else {
     // Retrieve the rectangular region of the frame that has changed since the
     // frame with the directly preceding CAPTURE_COUNTER. If that frame was not
@@ -123,14 +130,13 @@
     // This rectangle is relative to the full frame data, i.e. [0, 0,
     // coded_size.width(), coded_size.height()]. It does not have to be
     // fully contained within visible_rect.
-    if (!metadata.GetRect(media::VideoFrameMetadata::CAPTURE_UPDATE_RECT,
-                          &damage_rect) ||
-        damage_rect.IsEmpty()) {
+    if (metadata.capture_update_rect) {
+      damage_rect = *metadata.capture_update_rect;
+    }
+    if (damage_rect.IsEmpty()) {
       damage_rect = gfx::Rect(info->coded_size);
     }
   }
 
   view_->OnPaint(damage_rect, info->coded_size, pixels);
 }
-
-void CefVideoConsumerOSR::OnStopped() {}
diff --git a/src/libcef/browser/osr/video_consumer_osr.h b/src/libcef/browser/osr/video_consumer_osr.h
index a4e2741..4616b05 100644
--- a/src/libcef/browser/osr/video_consumer_osr.h
+++ b/src/libcef/browser/osr/video_consumer_osr.h
@@ -1,41 +1,45 @@
 #ifndef LIBCEF_BROWSER_OSR_VIDEO_CONSUMER_OSR_H_
 #define LIBCEF_BROWSER_OSR_VIDEO_CONSUMER_OSR_H_
 
-#include "base/callback.h"
-#include "base/optional.h"
+#include "base/functional/callback.h"
 #include "components/viz/host/client_frame_sink_video_capturer.h"
 #include "media/capture/mojom/video_capture_types.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 class CefRenderWidgetHostViewOSR;
 
 class CefVideoConsumerOSR : public viz::mojom::FrameSinkVideoConsumer {
  public:
   explicit CefVideoConsumerOSR(CefRenderWidgetHostViewOSR* view);
+
+  CefVideoConsumerOSR(const CefVideoConsumerOSR&) = delete;
+  CefVideoConsumerOSR& operator=(const CefVideoConsumerOSR&) = delete;
+
   ~CefVideoConsumerOSR() override;
 
   void SetActive(bool active);
   void SetFrameRate(base::TimeDelta frame_rate);
   void SizeChanged(const gfx::Size& size_in_pixels);
-  void RequestRefreshFrame(const base::Optional<gfx::Rect>& bounds_in_pixels);
+  void RequestRefreshFrame(const absl::optional<gfx::Rect>& bounds_in_pixels);
 
  private:
   // viz::mojom::FrameSinkVideoConsumer implementation.
   void OnFrameCaptured(
-      base::ReadOnlySharedMemoryRegion data,
-      ::media::mojom::VideoFrameInfoPtr info,
+      media::mojom::VideoBufferHandlePtr data,
+      media::mojom::VideoFrameInfoPtr info,
       const gfx::Rect& content_rect,
       mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
           callbacks) override;
-  void OnStopped() override;
+  void OnNewCropVersion(uint32_t crop_version) override {}
+  void OnFrameWithEmptyRegionCapture() override {}
+  void OnStopped() override {}
   void OnLog(const std::string& message) override {}
 
   CefRenderWidgetHostViewOSR* const view_;
   std::unique_ptr<viz::ClientFrameSinkVideoCapturer> video_capturer_;
 
   gfx::Size size_in_pixels_;
-  base::Optional<gfx::Rect> bounds_in_pixels_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefVideoConsumerOSR);
+  absl::optional<gfx::Rect> bounds_in_pixels_;
 };
 
 #endif  // LIBCEF_BROWSER_OSR_VIDEO_CONSUMER_OSR_H_
\ No newline at end of file
diff --git a/src/libcef/browser/osr/web_contents_view_osr.cc b/src/libcef/browser/osr/web_contents_view_osr.cc
index 61a4058..d9a4898 100644
--- a/src/libcef/browser/osr/web_contents_view_osr.cc
+++ b/src/libcef/browser/osr/web_contents_view_osr.cc
@@ -5,8 +5,9 @@
 
 #include "libcef/browser/osr/web_contents_view_osr.h"
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 #include "libcef/browser/osr/render_widget_host_view_osr.h"
+#include "libcef/browser/osr/touch_selection_controller_client_osr.h"
 #include "libcef/common/drag_data_impl.h"
 
 #include "content/browser/browser_plugin/browser_plugin_embedder.h"
@@ -29,48 +30,32 @@
   DCHECK(!web_contents_);
   web_contents_ = web_contents;
 
-  auto host = web_contents_->GetRenderViewHost();
-  CefRenderWidgetHostViewOSR* view =
-      static_cast<CefRenderWidgetHostViewOSR*>(host->GetWidget()->GetView());
-  if (view)
-    view->InstallTransparency();
+  RenderViewCreated();
 }
 
-gfx::NativeView CefWebContentsViewOSR::GetNativeView() const {
-  return gfx::NativeView();
+void CefWebContentsViewOSR::RenderViewCreated() {
+  if (web_contents_) {
+    auto host = web_contents_->GetRenderViewHost();
+    CefRenderWidgetHostViewOSR* view =
+        static_cast<CefRenderWidgetHostViewOSR*>(host->GetWidget()->GetView());
+    if (view) {
+      view->InstallTransparency();
+    }
+  }
 }
 
-gfx::NativeView CefWebContentsViewOSR::GetContentNativeView() const {
-  return gfx::NativeView();
+gfx::Rect CefWebContentsViewOSR::GetContainerBounds() const {
+  return GetViewBounds();
 }
 
-gfx::NativeWindow CefWebContentsViewOSR::GetTopLevelNativeWindow() const {
-  return gfx::NativeWindow();
-}
-
-void CefWebContentsViewOSR::GetContainerBounds(gfx::Rect* out) const {
-  *out = GetViewBounds();
-}
-
-void CefWebContentsViewOSR::SizeContents(const gfx::Size& size) {}
-
-void CefWebContentsViewOSR::Focus() {}
-
-void CefWebContentsViewOSR::SetInitialFocus() {}
-
-void CefWebContentsViewOSR::StoreFocus() {}
-
-void CefWebContentsViewOSR::RestoreFocus() {}
-
-void CefWebContentsViewOSR::FocusThroughTabTraversal(bool reverse) {}
-
 void CefWebContentsViewOSR::GotFocus(
     content::RenderWidgetHostImpl* render_widget_host) {
   if (web_contents_) {
     content::WebContentsImpl* web_contents_impl =
         static_cast<content::WebContentsImpl*>(web_contents_);
-    if (web_contents_impl)
+    if (web_contents_impl) {
       web_contents_impl->NotifyWebContentsFocused(render_widget_host);
+    }
   }
 }
 
@@ -79,18 +64,16 @@
   if (web_contents_) {
     content::WebContentsImpl* web_contents_impl =
         static_cast<content::WebContentsImpl*>(web_contents_);
-    if (web_contents_impl)
+    if (web_contents_impl) {
       web_contents_impl->NotifyWebContentsLostFocus(render_widget_host);
+    }
   }
 }
 
 void CefWebContentsViewOSR::TakeFocus(bool reverse) {
-  if (web_contents_->GetDelegate())
+  if (web_contents_->GetDelegate()) {
     web_contents_->GetDelegate()->TakeFocus(web_contents_, reverse);
-}
-
-content::DropData* CefWebContentsViewOSR::GetDropData() const {
-  return nullptr;
+  }
 }
 
 gfx::Rect CefWebContentsViewOSR::GetViewBounds() const {
@@ -98,8 +81,6 @@
   return view ? view->GetViewBounds() : gfx::Rect();
 }
 
-void CefWebContentsViewOSR::CreateView(gfx::NativeView context) {}
-
 content::RenderWidgetHostViewBase* CefWebContentsViewOSR::CreateViewForWidget(
     content::RenderWidgetHost* render_widget_host) {
   if (render_widget_host->GetView()) {
@@ -124,43 +105,48 @@
                                         render_widget_host, view);
 }
 
-void CefWebContentsViewOSR::SetPageTitle(const base::string16& title) {}
+void CefWebContentsViewOSR::ShowContextMenu(
+    content::RenderFrameHost& render_frame_host,
+    const content::ContextMenuParams& params) {
+  auto selection_controller_client = GetSelectionControllerClient();
+  if (selection_controller_client &&
+      selection_controller_client->HandleContextMenu(params)) {
+    // Context menu display, if any, will be handled via
+    // AlloyWebContentsViewDelegate::ShowContextMenu.
+    return;
+  }
 
-void CefWebContentsViewOSR::RenderViewReady() {}
-
-void CefWebContentsViewOSR::RenderViewHostChanged(
-    content::RenderViewHost* old_host,
-    content::RenderViewHost* new_host) {}
-
-void CefWebContentsViewOSR::SetOverscrollControllerEnabled(bool enabled) {}
-
-#if defined(OS_MACOSX)
-bool CefWebContentsViewOSR::CloseTabAfterEventTrackingIfNeeded() {
-  return false;
-}
-#endif  // defined(OS_MACOSX)
-
-void CefWebContentsViewOSR::StartDragging(
-    const content::DropData& drop_data,
-    blink::WebDragOperationsMask allowed_ops,
-    const gfx::ImageSkia& image,
-    const gfx::Vector2d& image_offset,
-    const content::DragEventSourceInfo& event_info,
-    content::RenderWidgetHostImpl* source_rwh) {
-  CefRefPtr<CefBrowserHostImpl> browser = GetBrowser();
-  if (browser.get()) {
-    browser->StartDragging(drop_data, allowed_ops, image, image_offset,
-                           event_info, source_rwh);
-  } else if (web_contents_) {
-    web_contents_->SystemDragEnded(source_rwh);
+  if (auto browser = GetBrowser()) {
+    browser->ShowContextMenu(params);
   }
 }
 
-void CefWebContentsViewOSR::UpdateDragCursor(
-    blink::WebDragOperation operation) {
-  CefRefPtr<CefBrowserHostImpl> browser = GetBrowser();
-  if (browser.get())
-    browser->UpdateDragCursor(operation);
+void CefWebContentsViewOSR::StartDragging(
+    const content::DropData& drop_data,
+    const url::Origin& source_origin,
+    blink::DragOperationsMask allowed_ops,
+    const gfx::ImageSkia& image,
+    const gfx::Vector2d& cursor_offset,
+    const gfx::Rect& drag_obj_rect,
+    const blink::mojom::DragEventSourceInfo& event_info,
+    content::RenderWidgetHostImpl* source_rwh) {
+  CefRefPtr<AlloyBrowserHostImpl> browser = GetBrowser();
+  if (browser.get()) {
+    browser->StartDragging(drop_data, allowed_ops, image, cursor_offset,
+                           event_info, source_rwh);
+  } else if (web_contents_) {
+    static_cast<content::WebContentsImpl*>(web_contents_)
+        ->SystemDragEnded(source_rwh);
+  }
+}
+
+void CefWebContentsViewOSR::UpdateDragOperation(
+    ui::mojom::DragOperation operation,
+    bool document_is_handling_drag) {
+  CefRefPtr<AlloyBrowserHostImpl> browser = GetBrowser();
+  if (browser.get()) {
+    browser->UpdateDragOperation(operation, document_is_handling_drag);
+  }
 }
 
 CefRenderWidgetHostViewOSR* CefWebContentsViewOSR::GetView() const {
@@ -171,9 +157,16 @@
   return nullptr;
 }
 
-CefBrowserHostImpl* CefWebContentsViewOSR::GetBrowser() const {
+AlloyBrowserHostImpl* CefWebContentsViewOSR::GetBrowser() const {
   CefRenderWidgetHostViewOSR* view = GetView();
-  if (view)
+  if (view) {
     return view->browser_impl().get();
+  }
   return nullptr;
 }
+
+CefTouchSelectionControllerClientOSR*
+CefWebContentsViewOSR::GetSelectionControllerClient() const {
+  CefRenderWidgetHostViewOSR* view = GetView();
+  return view ? view->selection_controller_client() : nullptr;
+}
diff --git a/src/libcef/browser/osr/web_contents_view_osr.h b/src/libcef/browser/osr/web_contents_view_osr.h
index 088edce..13c5d87 100644
--- a/src/libcef/browser/osr/web_contents_view_osr.h
+++ b/src/libcef/browser/osr/web_contents_view_osr.h
@@ -16,8 +16,9 @@
 class WebContentsViewDelegate;
 }  // namespace content
 
-class CefBrowserHostImpl;
+class AlloyBrowserHostImpl;
 class CefRenderWidgetHostViewOSR;
+class CefTouchSelectionControllerClientOSR;
 
 // An implementation of WebContentsView for off-screen rendering.
 class CefWebContentsViewOSR : public content::WebContentsView,
@@ -26,64 +27,81 @@
   explicit CefWebContentsViewOSR(SkColor background_color,
                                  bool use_shared_texture,
                                  bool use_external_begin_frame);
+
+  CefWebContentsViewOSR(const CefWebContentsViewOSR&) = delete;
+  CefWebContentsViewOSR& operator=(const CefWebContentsViewOSR&) = delete;
+
   ~CefWebContentsViewOSR() override;
 
   void WebContentsCreated(content::WebContents* web_contents);
   content::WebContents* web_contents() const { return web_contents_; }
 
+  void RenderViewCreated();
+
   // WebContentsView methods.
-  gfx::NativeView GetNativeView() const override;
-  gfx::NativeView GetContentNativeView() const override;
-  gfx::NativeWindow GetTopLevelNativeWindow() const override;
-  void GetContainerBounds(gfx::Rect* out) const override;
-  void SizeContents(const gfx::Size& size) override;
-  void Focus() override;
-  void SetInitialFocus() override;
-  void StoreFocus() override;
-  void RestoreFocus() override;
-  void FocusThroughTabTraversal(bool reverse) override;
-  content::DropData* GetDropData() const override;
+  gfx::NativeView GetNativeView() const override { return gfx::NativeView(); }
+  gfx::NativeView GetContentNativeView() const override {
+    return gfx::NativeView();
+  }
+  gfx::NativeWindow GetTopLevelNativeWindow() const override {
+    return gfx::NativeWindow();
+  }
+  gfx::Rect GetContainerBounds() const override;
+  void Focus() override {}
+  void SetInitialFocus() override {}
+  void StoreFocus() override {}
+  void RestoreFocus() override {}
+  void FocusThroughTabTraversal(bool reverse) override {}
+  content::DropData* GetDropData() const override { return nullptr; }
   gfx::Rect GetViewBounds() const override;
-  void CreateView(gfx::NativeView context) override;
+  void CreateView(gfx::NativeView context) override {}
   content::RenderWidgetHostViewBase* CreateViewForWidget(
       content::RenderWidgetHost* render_widget_host) override;
   content::RenderWidgetHostViewBase* CreateViewForChildWidget(
       content::RenderWidgetHost* render_widget_host) override;
-  void SetPageTitle(const base::string16& title) override;
-  void RenderViewReady() override;
+  void SetPageTitle(const std::u16string& title) override {}
+  void RenderViewReady() override {}
   void RenderViewHostChanged(content::RenderViewHost* old_host,
-                             content::RenderViewHost* new_host) override;
-  void SetOverscrollControllerEnabled(bool enabled) override;
+                             content::RenderViewHost* new_host) override {}
+  void SetOverscrollControllerEnabled(bool enabled) override {}
+  void OnCapturerCountChanged() override {}
+  void UpdateWindowControlsOverlay(const gfx::Rect& bounding_rect) override {}
+  void CancelDragDropForPortalActivation() override {}
 
-#if defined(OS_MACOSX)
-  bool CloseTabAfterEventTrackingIfNeeded() override;
+#if BUILDFLAG(IS_MAC)
+  bool CloseTabAfterEventTrackingIfNeeded() override { return false; }
 #endif
 
   // RenderViewHostDelegateView methods.
+  void ShowContextMenu(content::RenderFrameHost& render_frame_host,
+                       const content::ContextMenuParams& params) override;
   void StartDragging(const content::DropData& drop_data,
-                     blink::WebDragOperationsMask allowed_ops,
+                     const url::Origin& source_origin,
+                     blink::DragOperationsMask allowed_ops,
                      const gfx::ImageSkia& image,
-                     const gfx::Vector2d& image_offset,
-                     const content::DragEventSourceInfo& event_info,
+                     const gfx::Vector2d& cursor_offset,
+                     const gfx::Rect& drag_obj_rect,
+                     const blink::mojom::DragEventSourceInfo& event_info,
                      content::RenderWidgetHostImpl* source_rwh) override;
-  void UpdateDragCursor(blink::WebDragOperation operation) override;
+  void UpdateDragOperation(ui::mojom::DragOperation operation,
+                           bool document_is_handling_drag) override;
   virtual void GotFocus(
       content::RenderWidgetHostImpl* render_widget_host) override;
   virtual void LostFocus(
       content::RenderWidgetHostImpl* render_widget_host) override;
   virtual void TakeFocus(bool reverse) override;
+  virtual void FullscreenStateChanged(bool is_fullscreen) override {}
 
  private:
   CefRenderWidgetHostViewOSR* GetView() const;
-  CefBrowserHostImpl* GetBrowser() const;
+  AlloyBrowserHostImpl* GetBrowser() const;
+  CefTouchSelectionControllerClientOSR* GetSelectionControllerClient() const;
 
   const SkColor background_color_;
   const bool use_shared_texture_;
   const bool use_external_begin_frame_;
 
   content::WebContents* web_contents_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefWebContentsViewOSR);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_OSR_WEB_CONTENTS_VIEW_OSR_H_
diff --git a/src/libcef/browser/path_util_impl.cc b/src/libcef/browser/path_util_impl.cc
index 4d30d0d..0d26a46 100644
--- a/src/libcef/browser/path_util_impl.cc
+++ b/src/libcef/browser/path_util_impl.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_path.h"
 #include "base/logging.h"
+#include "base/notreached.h"
 #include "base/path_service.h"
 #include "chrome/common/chrome_paths.h"
 
@@ -30,7 +31,7 @@
     case PK_FILE_MODULE:
       pref_key = base::FILE_MODULE;
       break;
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
     case PK_LOCAL_APP_DATA:
       pref_key = base::DIR_LOCAL_APP_DATA;
       break;
@@ -42,7 +43,7 @@
       pref_key = chrome::DIR_RESOURCES;
       break;
     default:
-      NOTREACHED() << "invalid argument";
+      DCHECK(false) << "invalid argument";
       return false;
   }
 
diff --git a/src/libcef/browser/permission_prompt.cc b/src/libcef/browser/permission_prompt.cc
new file mode 100644
index 0000000..8677958
--- /dev/null
+++ b/src/libcef/browser/permission_prompt.cc
@@ -0,0 +1,299 @@
+// Copyright 2022 The Chromium Embedded Framework Authors. Portions 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 "libcef/browser/permission_prompt.h"
+
+#include "libcef/browser/browser_host_base.h"
+#include "libcef/features/runtime.h"
+
+#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
+#include "base/notreached.h"
+#include "chrome/browser/ui/permission_bubble/permission_prompt.h"
+
+namespace permission_prompt {
+
+namespace {
+
+uint64_t g_next_prompt_id = 0;
+
+using DelegateCallback =
+    base::OnceCallback<void(cef_permission_request_result_t)>;
+
+class CefPermissionPromptCallbackImpl : public CefPermissionPromptCallback {
+ public:
+  using CallbackType = base::OnceCallback<void(cef_permission_request_result_t,
+                                               bool /*notify_delegate*/)>;
+
+  explicit CefPermissionPromptCallbackImpl(CallbackType&& callback)
+      : callback_(std::move(callback)) {}
+
+  CefPermissionPromptCallbackImpl(const CefPermissionPromptCallbackImpl&) =
+      delete;
+  CefPermissionPromptCallbackImpl& operator=(
+      const CefPermissionPromptCallbackImpl&) = delete;
+
+  // Don't need to execute the callback in this destructor because this object
+  // will always be kept alive until after the CefPermissionPrompt is destroyed,
+  // and that object will disconnect/execute the callback in its destructor.
+  ~CefPermissionPromptCallbackImpl() override = default;
+
+  void Continue(cef_permission_request_result_t result) override {
+    if (CEF_CURRENTLY_ON_UIT()) {
+      if (!callback_.is_null()) {
+        auto callback = base::BindOnce(std::move(callback_), result,
+                                       /*notify_delegate=*/true);
+        if (safe_to_run_sync_) {
+          std::move(callback).Run();
+        } else {
+          CEF_POST_TASK(CEF_UIT, std::move(callback));
+        }
+      }
+    } else {
+      CEF_POST_TASK(CEF_UIT,
+                    base::BindOnce(&CefPermissionPromptCallbackImpl::Continue,
+                                   this, result));
+    }
+  }
+
+  [[nodiscard]] CallbackType Disconnect() { return std::move(callback_); }
+  bool IsDisconnected() const { return callback_.is_null(); }
+
+  void MarkSafeToRunSync() { safe_to_run_sync_ = true; }
+
+ private:
+  // Callback execution from inside CreatePermissionPromptImpl must be async,
+  // otherwise PermissionRequestManager state will be incorrect.
+  bool safe_to_run_sync_ = false;
+
+  CallbackType callback_;
+
+  IMPLEMENT_REFCOUNTING(CefPermissionPromptCallbackImpl);
+};
+
+// Implementation based on PermissionPromptAndroid.
+class CefPermissionPrompt : public permissions::PermissionPrompt {
+ public:
+  explicit CefPermissionPrompt(Delegate* delegate) : delegate_(delegate) {
+    DCHECK(delegate_);
+  }
+
+  CefPermissionPrompt(const CefPermissionPrompt&) = delete;
+  CefPermissionPrompt& operator=(const CefPermissionPrompt&) = delete;
+
+  // Expect to be destroyed (and the UI needs to go) when:
+  // 1. A navigation happens, tab/webcontents is being closed; with the current
+  //    GetTabSwitchingBehavior() implementation, this instance survives the tab
+  //    being backgrounded.
+  // 2. The permission request is resolved (accept, deny, dismiss).
+  // 3. A higher priority request comes in.
+  ~CefPermissionPrompt() override {
+    CEF_REQUIRE_UIT();
+    if (callback_) {
+      // If the callback is non-null at this point then we still need to execute
+      // it in order to notify the client.
+      auto callback = callback_->Disconnect();
+      if (!callback.is_null()) {
+        std::move(callback).Run(CEF_PERMISSION_RESULT_IGNORE,
+                                /*notify_delegate=*/false);
+      }
+    }
+  }
+
+  // Used to associate the client callback when OnShowPermissionPrompt is
+  // handled.
+  void AttachClientCallback(
+      CefRefPtr<CefPermissionPromptCallbackImpl> callback) {
+    DCHECK(callback);
+    callback_ = callback;
+    callback_->MarkSafeToRunSync();
+  }
+
+  // Used to tie Delegate access to this object's lifespan.
+  DelegateCallback MakeDelegateCallback() {
+    return base::BindOnce(&CefPermissionPrompt::NotifyDelegate,
+                          weak_ptr_factory_.GetWeakPtr());
+  }
+
+  // PermissionPrompt methods:
+  bool UpdateAnchor() override { return true; }
+  TabSwitchingBehavior GetTabSwitchingBehavior() override {
+    return TabSwitchingBehavior::kKeepPromptAlive;
+  }
+  permissions::PermissionPromptDisposition GetPromptDisposition()
+      const override {
+    return permissions::PermissionPromptDisposition::CUSTOM_MODAL_DIALOG;
+  }
+  absl::optional<gfx::Rect> GetViewBoundsInScreen() const override {
+    return absl::nullopt;
+  }
+
+ private:
+  // We don't expose AcceptThisTime() because it's a special case for
+  // Geolocation (see DCHECK in PrefProvider::SetWebsiteSetting).
+  void NotifyDelegate(cef_permission_request_result_t result) {
+    switch (result) {
+      case CEF_PERMISSION_RESULT_ACCEPT:
+        delegate_->Accept();
+        break;
+      case CEF_PERMISSION_RESULT_DENY:
+        delegate_->Deny();
+        break;
+      case CEF_PERMISSION_RESULT_DISMISS:
+        delegate_->Dismiss();
+        break;
+      case CEF_PERMISSION_RESULT_IGNORE:
+        delegate_->Ignore();
+        break;
+    }
+  }
+
+  // |delegate_| is the PermissionRequestManager, which owns this object.
+  const raw_ptr<Delegate> delegate_;
+
+  CefRefPtr<CefPermissionPromptCallbackImpl> callback_;
+
+  base::WeakPtrFactory<CefPermissionPrompt> weak_ptr_factory_{this};
+};
+
+// |notify_delegate| will be false if called from the CefPermissionPrompt
+// destructor.
+void ExecuteResult(CefRefPtr<CefBrowserHostBase> browser,
+                   uint64_t prompt_id,
+                   DelegateCallback delegate_callback,
+                   cef_permission_request_result_t result,
+                   bool notify_delegate) {
+  CEF_REQUIRE_UIT();
+
+  if (auto client = browser->GetClient()) {
+    if (auto handler = client->GetPermissionHandler()) {
+      handler->OnDismissPermissionPrompt(browser, prompt_id, result);
+    }
+  }
+
+  if (notify_delegate) {
+    // Will be a no-op if this executes after the CefPermissionPrompt was
+    // destroyed.
+    std::move(delegate_callback).Run(result);
+  }
+}
+
+cef_permission_request_types_t GetCefRequestType(
+    permissions::RequestType type) {
+  switch (type) {
+    case permissions::RequestType::kAccessibilityEvents:
+      return CEF_PERMISSION_TYPE_ACCESSIBILITY_EVENTS;
+    case permissions::RequestType::kArSession:
+      return CEF_PERMISSION_TYPE_AR_SESSION;
+    case permissions::RequestType::kCameraPanTiltZoom:
+      return CEF_PERMISSION_TYPE_CAMERA_PAN_TILT_ZOOM;
+    case permissions::RequestType::kCameraStream:
+      return CEF_PERMISSION_TYPE_CAMERA_STREAM;
+    case permissions::RequestType::kClipboard:
+      return CEF_PERMISSION_TYPE_CLIPBOARD;
+    case permissions::RequestType::kDiskQuota:
+      return CEF_PERMISSION_TYPE_DISK_QUOTA;
+    case permissions::RequestType::kLocalFonts:
+      return CEF_PERMISSION_TYPE_LOCAL_FONTS;
+    case permissions::RequestType::kGeolocation:
+      return CEF_PERMISSION_TYPE_GEOLOCATION;
+    case permissions::RequestType::kIdleDetection:
+      return CEF_PERMISSION_TYPE_IDLE_DETECTION;
+    case permissions::RequestType::kMicStream:
+      return CEF_PERMISSION_TYPE_MIC_STREAM;
+    case permissions::RequestType::kMidi:
+      return CEF_PERMISSION_TYPE_MIDI;
+    case permissions::RequestType::kMidiSysex:
+      return CEF_PERMISSION_TYPE_MIDI_SYSEX;
+    case permissions::RequestType::kMultipleDownloads:
+      return CEF_PERMISSION_TYPE_MULTIPLE_DOWNLOADS;
+    case permissions::RequestType::kNotifications:
+      return CEF_PERMISSION_TYPE_NOTIFICATIONS;
+#if BUILDFLAG(IS_WIN)
+    case permissions::RequestType::kProtectedMediaIdentifier:
+      return CEF_PERMISSION_TYPE_PROTECTED_MEDIA_IDENTIFIER;
+#endif
+    case permissions::RequestType::kRegisterProtocolHandler:
+      return CEF_PERMISSION_TYPE_REGISTER_PROTOCOL_HANDLER;
+    case permissions::RequestType::kStorageAccess:
+      return CEF_PERMISSION_TYPE_STORAGE_ACCESS;
+    case permissions::RequestType::kTopLevelStorageAccess:
+      return CEF_PERMISSION_TYPE_TOP_LEVEL_STORAGE_ACCESS;
+    case permissions::RequestType::kVrSession:
+      return CEF_PERMISSION_TYPE_VR_SESSION;
+    case permissions::RequestType::kWindowManagement:
+      return CEF_PERMISSION_TYPE_WINDOW_MANAGEMENT;
+  }
+
+  DCHECK(false);
+  return CEF_PERMISSION_TYPE_NONE;
+}
+
+uint32_t GetRequestedPermissions(
+    permissions::PermissionPrompt::Delegate* delegate) {
+  uint32_t permissions = CEF_PERMISSION_TYPE_NONE;
+  for (const auto* request : delegate->Requests()) {
+    permissions |= GetCefRequestType(request->request_type());
+  }
+  return permissions;
+}
+
+std::unique_ptr<permissions::PermissionPrompt> CreatePermissionPromptImpl(
+    content::WebContents* web_contents,
+    permissions::PermissionPrompt::Delegate* delegate,
+    bool* default_handling) {
+  CEF_REQUIRE_UIT();
+
+  if (auto browser = CefBrowserHostBase::GetBrowserForContents(web_contents)) {
+    if (auto client = browser->GetClient()) {
+      if (auto handler = client->GetPermissionHandler()) {
+        auto permission_prompt =
+            std::make_unique<CefPermissionPrompt>(delegate);
+
+        const auto prompt_id = ++g_next_prompt_id;
+        auto callback =
+            base::BindOnce(&ExecuteResult, browser, prompt_id,
+                           permission_prompt->MakeDelegateCallback());
+
+        CefRefPtr<CefPermissionPromptCallbackImpl> callbackImpl(
+            new CefPermissionPromptCallbackImpl(std::move(callback)));
+        bool handled = handler->OnShowPermissionPrompt(
+            browser, prompt_id, delegate->GetRequestingOrigin().spec(),
+            GetRequestedPermissions(delegate), callbackImpl.get());
+
+        if (callbackImpl->IsDisconnected() || handled) {
+          // Callback execution will be async.
+          LOG_IF(ERROR, !handled)
+              << "Should return true from OnShowPermissionPrompt when "
+                 "executing the callback";
+          *default_handling = false;
+          permission_prompt->AttachClientCallback(callbackImpl);
+          return permission_prompt;
+        } else {
+          // Proceed with default handling. |callback| is discarded without
+          // execution.
+          callback = callbackImpl->Disconnect();
+        }
+      }
+    }
+  }
+
+  if (cef::IsAlloyRuntimeEnabled()) {
+    LOG(INFO) << "Implement OnShowPermissionPrompt to override default IGNORE "
+                 "handling of permission prompts.";
+  }
+
+  // Proceed with default handling. This will be IGNORE with the Alloy runtime
+  // and default UI prompt with the Chrome runtime.
+  *default_handling = true;
+  return nullptr;
+}
+
+}  // namespace
+
+void RegisterCreateCallback() {
+  SetCreatePermissionPromptFunction(&CreatePermissionPromptImpl);
+}
+
+}  // namespace permission_prompt
diff --git a/src/libcef/browser/permission_prompt.h b/src/libcef/browser/permission_prompt.h
new file mode 100644
index 0000000..224eb04
--- /dev/null
+++ b/src/libcef/browser/permission_prompt.h
@@ -0,0 +1,15 @@
+// Copyright 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_PERMISSION_PROMPT_H_
+#define CEF_LIBCEF_BROWSER_PERMISSION_PROMPT_H_
+#pragma once
+
+namespace permission_prompt {
+
+void RegisterCreateCallback();
+
+}  // namespace permission_prompt
+
+#endif  // CEF_LIBCEF_BROWSER_PERMISSION_PROMPT_H_
diff --git a/src/libcef/browser/plugins/plugin_service_filter.cc b/src/libcef/browser/plugins/plugin_service_filter.cc
deleted file mode 100644
index e1dbdcd..0000000
--- a/src/libcef/browser/plugins/plugin_service_filter.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright (c) 2015 The Chromium Embedded Framework 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 "libcef/browser/plugins/plugin_service_filter.h"
-
-#include "include/cef_request_context_handler.h"
-#include "libcef/browser/browser_context.h"
-#include "libcef/browser/thread_util.h"
-#include "libcef/browser/web_plugin_impl.h"
-#include "libcef/common/content_client.h"
-
-#include "extensions/common/constants.h"
-
-CefPluginServiceFilter::CefPluginServiceFilter() {}
-
-bool CefPluginServiceFilter::IsPluginAvailable(
-    int render_process_id,
-    int render_frame_id,
-    const GURL& url,
-    bool is_main_frame,
-    const url::Origin& main_frame_origin,
-    content::WebPluginInfo* plugin) {
-  CEF_REQUIRE_UIT();
-  DCHECK_GT(render_process_id, 0);
-
-  chrome::mojom::PluginStatus status = chrome::mojom::PluginStatus::kAllowed;
-
-  // Perform origin check here because we're passing an empty origin value to
-  // IsPluginAvailable() below.
-  const GURL& policy_url = main_frame_origin.GetURL();
-  if (!policy_url.is_empty() &&
-      policy_url.scheme() == extensions::kExtensionScheme) {
-    // Always allow extension origins to load plugins.
-    // TODO(extensions): Revisit this decision once CEF supports more than just
-    // the PDF extension.
-    return true;
-  }
-
-  // Blink requires this method to return a consistent value during renderer
-  // process initialization and page load, so we always call IsPluginAvailable()
-  // with an empty origin. If we return false then the plugin will not be listed
-  // in navigator.plugins and navigating to the plugin mime type will trigger
-  // the download code path. If we return true then individual plugin instance
-  // loads will be evaluated in CefContentRendererClient::OverrideCreatePlugin,
-  // which will result in a call to CefPluginInfoMessageFilter::PluginsLoaded to
-  // retrieve the actual load decision with a non-empty origin. That will
-  // determine whether the plugin load is allowed or the plugin placeholder is
-  // displayed.
-  return IsPluginAvailable(render_process_id, render_frame_id, url,
-                           is_main_frame, url::Origin(), plugin, &status);
-}
-
-bool CefPluginServiceFilter::CanLoadPlugin(int render_process_id,
-                                           const base::FilePath& path) {
-  return true;
-}
-
-bool CefPluginServiceFilter::IsPluginAvailable(
-    int render_process_id,
-    int render_frame_id,
-    const GURL& url,
-    bool is_main_frame,
-    const url::Origin& main_frame_origin,
-    content::WebPluginInfo* plugin,
-    chrome::mojom::PluginStatus* status) {
-  CEF_REQUIRE_UIT();
-  DCHECK_GT(render_process_id, 0);
-
-  if (*status == chrome::mojom::PluginStatus::kNotFound) {
-    // The plugin does not exist so no need to query the handler.
-    return false;
-  }
-
-  if (plugin->path == CefString(CefContentClient::kPDFPluginPath)) {
-    // Always allow the internal PDF plugin to load.
-    *status = chrome::mojom::PluginStatus::kAllowed;
-    return true;
-  }
-
-  const GURL& policy_url = main_frame_origin.GetURL();
-  if (!policy_url.is_empty() &&
-      policy_url.scheme() == extensions::kExtensionScheme) {
-    // Always allow extension origins to load plugins.
-    // TODO(extensions): Revisit this decision once CEF supports more than just
-    // the PDF extension.
-    *status = chrome::mojom::PluginStatus::kAllowed;
-    return true;
-  }
-
-  auto browser_context = CefBrowserContext::GetForIDs(
-      render_process_id, render_frame_id, -1, false);
-  CefRefPtr<CefRequestContextHandler> handler;
-  if (browser_context) {
-    handler = browser_context->GetHandler(render_process_id, render_frame_id,
-                                          -1, false);
-  }
-
-  if (!handler) {
-    // No handler so go with the default plugin load decision.
-    return *status != chrome::mojom::PluginStatus::kDisabled;
-  }
-
-  // Check for a cached plugin load decision.
-  if (browser_context->HasPluginLoadDecision(render_process_id, plugin->path,
-                                             is_main_frame, main_frame_origin,
-                                             status)) {
-    return *status != chrome::mojom::PluginStatus::kDisabled;
-  }
-
-  CefRefPtr<CefWebPluginInfoImpl> pluginInfo(new CefWebPluginInfoImpl(*plugin));
-
-  cef_plugin_policy_t plugin_policy = PLUGIN_POLICY_ALLOW;
-  switch (*status) {
-    case chrome::mojom::PluginStatus::kAllowed:
-      plugin_policy = PLUGIN_POLICY_ALLOW;
-      break;
-    case chrome::mojom::PluginStatus::kBlocked:
-    case chrome::mojom::PluginStatus::kBlockedByPolicy:
-    case chrome::mojom::PluginStatus::kOutdatedBlocked:
-    case chrome::mojom::PluginStatus::kOutdatedDisallowed:
-    case chrome::mojom::PluginStatus::kUnauthorized:
-      plugin_policy = PLUGIN_POLICY_BLOCK;
-      break;
-    case chrome::mojom::PluginStatus::kDisabled:
-      plugin_policy = PLUGIN_POLICY_DISABLE;
-      break;
-    case chrome::mojom::PluginStatus::kPlayImportantContent:
-      plugin_policy = PLUGIN_POLICY_DETECT_IMPORTANT;
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
-
-  if (handler->OnBeforePluginLoad(plugin->mime_types[0].mime_type,
-                                  url.possibly_invalid_spec(), is_main_frame,
-                                  policy_url.possibly_invalid_spec(),
-                                  pluginInfo.get(), &plugin_policy)) {
-    switch (plugin_policy) {
-      case PLUGIN_POLICY_ALLOW:
-        *status = chrome::mojom::PluginStatus::kAllowed;
-        break;
-      case PLUGIN_POLICY_DETECT_IMPORTANT:
-        *status = chrome::mojom::PluginStatus::kPlayImportantContent;
-        break;
-      case PLUGIN_POLICY_BLOCK:
-        *status = chrome::mojom::PluginStatus::kBlocked;
-        break;
-      case PLUGIN_POLICY_DISABLE:
-        *status = chrome::mojom::PluginStatus::kDisabled;
-        break;
-    }
-  }
-
-  // Cache the plugin load decision.
-  browser_context->AddPluginLoadDecision(render_process_id, plugin->path,
-                                         is_main_frame, main_frame_origin,
-                                         *status);
-
-  return *status != chrome::mojom::PluginStatus::kDisabled;
-}
diff --git a/src/libcef/browser/plugins/plugin_service_filter.h b/src/libcef/browser/plugins/plugin_service_filter.h
deleted file mode 100644
index 3322bac..0000000
--- a/src/libcef/browser/plugins/plugin_service_filter.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2015 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_PLUGINS_PLUGIN_SERVICE_FILTER_H_
-#define CEF_LIBCEF_BROWSER_PLUGINS_PLUGIN_SERVICE_FILTER_H_
-
-#include "chrome/common/plugin.mojom.h"
-#include "content/public/browser/plugin_service_filter.h"
-
-#include "include/internal/cef_types.h"
-
-#include "base/macros.h"
-
-namespace content {
-class ResourceContext;
-}
-
-class CefPluginServiceFilter : public content::PluginServiceFilter {
- public:
-  CefPluginServiceFilter();
-
-  // Called whenever the plugin list is queried. For example, when choosing the
-  // plugin to handle a mime type or when determining the plugins that will be
-  // exposed to JavaScript via 'navigator.plugins'.
-  bool IsPluginAvailable(int render_process_id,
-                         int render_frame_id,
-                         const GURL& url,
-                         bool is_main_frame,
-                         const url::Origin& main_frame_origin,
-                         content::WebPluginInfo* plugin) override;
-
-  bool CanLoadPlugin(int render_process_id,
-                     const base::FilePath& path) override;
-
-  // Called from the above IsPluginAvailable method and from
-  // PluginInfoHostImpl::Context::FindEnabledPlugin.
-  // Returns false if the plugin is not found or disabled. May call
-  // CefRequestContextHandler::OnBeforePluginLoad if possible/necessary.
-  // See related discussion in issue #2015.
-  bool IsPluginAvailable(int render_process_id,
-                         int render_frame_id,
-                         const GURL& url,
-                         bool is_main_frame,
-                         const url::Origin& main_frame_origin,
-                         content::WebPluginInfo* plugin,
-                         chrome::mojom::PluginStatus* status);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefPluginServiceFilter);
-};
-
-#endif  // CEF_LIBCEF_BROWSER_PLUGINS_PLUGIN_SERVICE_FILTER_H_
diff --git a/src/libcef/browser/prefs/browser_prefs.cc b/src/libcef/browser/prefs/browser_prefs.cc
index 5abda53..37e527f 100644
--- a/src/libcef/browser/prefs/browser_prefs.cc
+++ b/src/libcef/browser/prefs/browser_prefs.cc
@@ -5,7 +5,9 @@
 #include "libcef/browser/prefs/browser_prefs.h"
 
 #include "libcef/browser/browser_context.h"
+#include "libcef/browser/context.h"
 #include "libcef/browser/media_capture_devices_dispatcher.h"
+#include "libcef/browser/prefs/pref_registrar.h"
 #include "libcef/browser/prefs/pref_store.h"
 #include "libcef/browser/prefs/renderer_prefs.h"
 #include "libcef/common/cef_switches.h"
@@ -14,69 +16,98 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
 #include "base/values.h"
 #include "chrome/browser/accessibility/accessibility_ui.h"
 #include "chrome/browser/download/download_prefs.h"
+#include "chrome/browser/media/router/discovery/access_code/access_code_cast_feature.h"
 #include "chrome/browser/media/router/media_router_feature.h"
-#include "chrome/browser/net/prediction_options.h"
+#include "chrome/browser/media/webrtc/permission_bubble_media_access_handler.h"
 #include "chrome/browser/net/profile_network_context_service.h"
 #include "chrome/browser/net/system_network_context_manager.h"
-#include "chrome/browser/plugins/plugin_info_host_impl.h"
 #include "chrome/browser/prefs/chrome_command_line_pref_store.h"
+#include "chrome/browser/preloading/preloading_prefs.h"
 #include "chrome/browser/printing/print_preview_sticky_settings.h"
-#include "chrome/browser/renderer_host/pepper/device_id_fetcher.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ssl/ssl_config_service_manager.h"
 #include "chrome/browser/themes/theme_service.h"
+#include "chrome/browser/ui/webui/print_preview/policy_settings.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/net/safe_search_util.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/locale_settings.h"
 #include "components/certificate_transparency/pref_names.h"
+#include "components/component_updater/component_updater_service.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/content_settings/core/common/pref_names.h"
+#include "components/domain_reliability/domain_reliability_prefs.h"
 #include "components/flags_ui/pref_service_flags_storage.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/language/core/browser/language_prefs.h"
 #include "components/language/core/browser/pref_names.h"
+#include "components/media_device_salt/media_device_id_salt.h"
+#include "components/permissions/permission_actions_history.h"
+#include "components/permissions/permission_hats_trigger_helper.h"
+#include "components/policy/core/common/policy_pref_names.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/json_pref_store.h"
 #include "components/prefs/pref_filter.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
+#include "components/privacy_sandbox/tracking_protection_prefs.h"
 #include "components/proxy_config/pref_proxy_config_tracker_impl.h"
 #include "components/proxy_config/proxy_config_dictionary.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
+#include "components/safe_search_api/safe_search_util.h"
 #include "components/spellcheck/browser/pref_names.h"
 #include "components/sync_preferences/pref_service_syncable.h"
 #include "components/sync_preferences/pref_service_syncable_factory.h"
+#include "components/unified_consent/unified_consent_service.h"
 #include "components/update_client/update_client.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/buildflags/buildflags.h"
+#include "net/http/http_util.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/ui_base_switches.h"
 
-#if defined(OS_WIN)
-#include "components/os_crypt/os_crypt.h"
+#if BUILDFLAG(IS_WIN)
+#include "components/os_crypt/sync/os_crypt.h"
 #endif
 
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
-#include "chrome/browser/supervised_user/supervised_user_pref_store.h"
-#include "chrome/browser/supervised_user/supervised_user_settings_service.h"
+#include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
+#include "components/supervised_user/core/browser/supervised_user_pref_store.h"
+#include "components/supervised_user/core/browser/supervised_user_settings_service.h"
 #endif
 
 namespace browser_prefs {
 
 namespace {
 
-std::string GetAcceptLanguageList(Profile* profile) {
-  const CefRequestContextSettings& context_settings =
-      static_cast<CefBrowserContext*>(profile)->GetSettings();
-  if (context_settings.accept_language_list.length > 0) {
-    return CefString(&context_settings.accept_language_list);
+// Match the logic in chrome/browser/net/profile_network_context_service.cc.
+std::string ComputeAcceptLanguageFromPref(const std::string& language_pref) {
+  std::string accept_languages_str =
+      net::HttpUtil::ExpandLanguageList(language_pref);
+  return net::HttpUtil::GenerateAcceptLanguageHeader(accept_languages_str);
+}
+
+// Return the most relevant setting based on |profile|.
+std::string GetAcceptLanguageListSetting(Profile* profile) {
+  if (auto* browser_context = CefBrowserContext::FromProfile(profile)) {
+    const auto& settings = browser_context->settings();
+    if (settings.accept_language_list.length > 0) {
+      return CefString(&settings.accept_language_list);
+    }
   }
+
+  const auto& settings = CefContext::Get()->settings();
+  if (settings.accept_language_list.length > 0) {
+    return CefString(&settings.accept_language_list);
+  }
+
   return std::string();
 }
 
@@ -85,6 +116,15 @@
 const char kUserPrefsFileName[] = "UserPrefs.json";
 const char kLocalPrefsFileName[] = "LocalPrefs.json";
 
+void RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
+  pref_registrar::RegisterCustomPrefs(CEF_PREFERENCES_TYPE_GLOBAL, registry);
+}
+
+void RegisterProfilePrefs(PrefRegistrySimple* registry) {
+  pref_registrar::RegisterCustomPrefs(CEF_PREFERENCES_TYPE_REQUEST_CONTEXT,
+                                      registry);
+}
+
 std::unique_ptr<PrefService> CreatePrefService(Profile* profile,
                                                const base::FilePath& cache_path,
                                                bool persist_user_preferences) {
@@ -111,9 +151,8 @@
     // Get sequenced task runner for making sure that file operations are
     // executed in expected order (what was previously assured by the FILE
     // thread).
-    sequenced_task_runner = base::CreateSequencedTaskRunner(
-        {base::ThreadPool(), base::MayBlock(),
-         base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
+    sequenced_task_runner = base::ThreadPool::CreateSequencedTaskRunner(
+        {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
   }
 
   // Used to store user preferences.
@@ -133,7 +172,7 @@
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
   if (profile) {
     // Used to store supervised user preferences.
-    SupervisedUserSettingsService* supervised_user_settings =
+    auto* supervised_user_settings =
         SupervisedUserSettingsServiceFactory::GetForKey(
             profile->GetProfileKey());
 
@@ -180,15 +219,16 @@
   certificate_transparency::prefs::RegisterPrefs(registry.get());
   flags_ui::PrefServiceFlagsStorage::RegisterPrefs(registry.get());
   media_router::RegisterLocalStatePrefs(registry.get());
-  PluginInfoHostImpl::RegisterUserPrefs(registry.get());
   PrefProxyConfigTrackerImpl::RegisterPrefs(registry.get());
   ProfileNetworkContextService::RegisterLocalStatePrefs(registry.get());
   SSLConfigServiceManager::RegisterPrefs(registry.get());
   update_client::RegisterPrefs(registry.get());
 
   if (!profile) {
+    component_updater::RegisterComponentUpdateServicePrefs(registry.get());
+    domain_reliability::RegisterPrefs(registry.get());
     SystemNetworkContextManager::RegisterPrefs(registry.get());
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
     OSCrypt::RegisterLocalPrefs(registry.get());
 #endif
   }
@@ -201,19 +241,14 @@
   // Based on chrome/browser/ui/browser_ui_prefs.cc RegisterBrowserPrefs.
   registry->RegisterBooleanPref(prefs::kAllowFileSelectionDialogs, true);
 
-  // From Chrome::RegisterBrowserUserPrefs.
+  // Based on chrome/browser/ui/browser_ui_prefs.cc RegisterBrowserUserPrefs.
   registry->RegisterBooleanPref(prefs::kPrintPreviewUseSystemDefaultPrinter,
                                 false);
+  registry->RegisterBooleanPref(prefs::kWebRTCAllowLegacyTLSProtocols, false);
 
-  if (command_line->HasSwitch(switches::kEnablePreferenceTesting)) {
-    // Preferences used with unit tests.
-    registry->RegisterBooleanPref("test.bool", true);
-    registry->RegisterIntegerPref("test.int", 2);
-    registry->RegisterDoublePref("test.double", 5.0);
-    registry->RegisterStringPref("test.string", "default");
-    registry->RegisterListPref("test.list");
-    registry->RegisterDictionaryPref("test.dict");
-  }
+  // Profile preferences.
+  // Based on chrome/browser/profiles/profiles_state.cc RegisterPrefs.
+  registry->RegisterStringPref(prefs::kProfileLastUsed, std::string());
 
   if (profile) {
     // Call RegisterProfilePrefs() for all services listed by
@@ -223,13 +258,21 @@
 
     // Default profile preferences.
     AccessibilityUIMessageHandler::RegisterProfilePrefs(registry.get());
-    chrome_browser_net::RegisterPredictionOptionsProfilePrefs(registry.get());
-    DeviceIDFetcher::RegisterProfilePrefs(registry.get());
     extensions::ExtensionPrefs::RegisterProfilePrefs(registry.get());
     HostContentSettingsMap::RegisterProfilePrefs(registry.get());
     language::LanguagePrefs::RegisterProfilePrefs(registry.get());
+    media_router::RegisterAccessCodeProfilePrefs(registry.get());
     media_router::RegisterProfilePrefs(registry.get());
+    media_device_salt::MediaDeviceIDSalt::RegisterProfilePrefs(registry.get());
+    PermissionBubbleMediaAccessHandler::RegisterProfilePrefs(registry.get());
+    permissions::PermissionActionsHistory::RegisterProfilePrefs(registry.get());
+    permissions::PermissionHatsTriggerHelper::RegisterProfilePrefs(
+        registry.get());
+    prefetch::RegisterPredictionOptionsProfilePrefs(registry.get());
+    privacy_sandbox::tracking_protection::RegisterProfilePrefs(registry.get());
     ProfileNetworkContextService::RegisterProfilePrefs(registry.get());
+    safe_browsing::RegisterProfilePrefs(registry.get());
+    unified_consent::UnifiedConsentService::RegisterPrefs(registry.get());
 
     const std::string& locale =
         command_line->GetSwitchValueASCII(switches::kLang);
@@ -238,16 +281,18 @@
 
     // Print preferences.
     // Based on ProfileImpl::RegisterProfilePrefs.
-    registry->RegisterBooleanPref(prefs::kForceGoogleSafeSearch, false);
-    registry->RegisterIntegerPref(prefs::kForceYouTubeRestrict,
-                                  safe_search_util::YOUTUBE_RESTRICT_OFF);
+    registry->RegisterBooleanPref(policy::policy_prefs::kForceGoogleSafeSearch,
+                                  false);
+    registry->RegisterIntegerPref(policy::policy_prefs::kForceYouTubeRestrict,
+                                  safe_search_api::YOUTUBE_RESTRICT_OFF);
     registry->RegisterStringPref(prefs::kAllowedDomainsForApps, std::string());
     registry->RegisterBooleanPref(prefs::kPrintingEnabled, true);
     registry->RegisterBooleanPref(prefs::kPrintPreviewDisabled,
                                   !extensions::PrintPreviewEnabled());
     registry->RegisterStringPref(
         prefs::kPrintPreviewDefaultDestinationSelectionRules, std::string());
-    registry->RegisterBooleanPref(prefs::kCloudPrintSubmitEnabled, false);
+    registry->RegisterBooleanPref(prefs::kEnableMediaRouter, true);
+    printing::PolicySettings::RegisterProfilePrefs(registry.get());
     printing::PrintPreviewStickySettings::RegisterProfilePrefs(registry.get());
     DownloadPrefs::RegisterProfilePrefs(registry.get());
 
@@ -256,6 +301,19 @@
     registry->RegisterFilePathPref(prefs::kDiskCacheDir, cache_path);
     registry->RegisterIntegerPref(prefs::kDiskCacheSize, 0);
 
+    // Based on Profile::RegisterProfilePrefs.
+    registry->RegisterBooleanPref(prefs::kSearchSuggestEnabled, false);
+    registry->RegisterStringPref(prefs::kSessionExitType, std::string());
+
+    // Based on ChromeContentBrowserClient::RegisterProfilePrefs.
+    registry->RegisterBooleanPref(
+        prefs::kAccessControlAllowMethodsInCORSPreflightSpecConformant, true);
+
+    // Based on browser_prefs::RegisterProfilePrefs.
+    registry->RegisterBooleanPref(prefs::kAccessibilityPdfOcrAlwaysActive,
+                                  false);
+    registry->RegisterBooleanPref(prefs::kBlockTruncatedCookies, true);
+
     // Spell checking preferences.
     // Modify defaults from SpellcheckServiceFactory::RegisterProfilePrefs.
     std::string spellcheck_lang =
@@ -272,10 +330,6 @@
     registry->SetDefaultPrefValue(spellcheck::prefs::kSpellCheckEnable,
                                   base::Value(!enable_spelling_service_));
 
-    // Pepper flash preferences.
-    // Modify defaults from DeviceIDFetcher::RegisterProfilePrefs.
-    registry->SetDefaultPrefValue(prefs::kEnableDRM, base::Value(false));
-
     // DevTools preferences.
     // Based on DevToolsWindow::RegisterProfilePrefs.
     registry->RegisterDictionaryPref(prefs::kDevToolsPreferences);
@@ -283,16 +337,61 @@
 
     // Language preferences. Used by ProfileNetworkContextService and
     // InterceptedRequestHandlerWrapper.
-    const std::string& accept_language_list = GetAcceptLanguageList(profile);
+    const std::string& accept_language_list =
+        GetAcceptLanguageListSetting(profile);
     if (!accept_language_list.empty()) {
       registry->SetDefaultPrefValue(language::prefs::kAcceptLanguages,
                                     base::Value(accept_language_list));
     }
     registry->RegisterListPref(prefs::kWebRtcLocalIpsAllowedUrls);
+
+    // Always do this after all other profile prefs.
+    RegisterProfilePrefs(registry.get());
+  } else {
+    // Always do this after all other local state prefs.
+    RegisterLocalStatePrefs(registry.get());
   }
 
   // Build the PrefService that manages the PrefRegistry and PrefStores.
   return factory.CreateSyncable(registry.get());
 }
 
+std::string GetAcceptLanguageList(Profile* profile) {
+  // Always prefer to the CEF settings configuration, if specified.
+  std::string accept_language_list = GetAcceptLanguageListSetting(profile);
+  if (accept_language_list.empty() && profile) {
+    // Fall back to the preference value. For the Alloy runtime the default
+    // value comes from browser_prefs::CreatePrefService() above. For the Chrome
+    // runtime the default value comes from the configured locale
+    // (IDS_ACCEPT_LANGUAGES) which is then overridden by the user preference in
+    // chrome://settings/languages, all managed by language::LanguagePrefs.
+    accept_language_list =
+        profile->GetPrefs()->GetString(language::prefs::kAcceptLanguages);
+  }
+
+  if (!accept_language_list.empty()) {
+    return ComputeAcceptLanguageFromPref(accept_language_list);
+  }
+  return std::string();
+}
+
+void SetInitialProfilePrefs(Profile* profile) {
+  auto* prefs = profile->GetPrefs();
+
+  // Language preferences.
+  const std::string& accept_language_list =
+      GetAcceptLanguageListSetting(profile);
+  if (!accept_language_list.empty()) {
+    // Used by ProfileNetworkContextService and InterceptedRequestHandlerWrapper
+    // (via GetAcceptLanguageList) for request headers, and
+    // renderer_preferences_util::UpdateFromSystemSettings() for
+    // `navigator.language`.
+    prefs->SetString(language::prefs::kAcceptLanguages, accept_language_list);
+
+    // Necessary to avoid a reset of the kAcceptLanguages value in
+    // LanguagePrefs::UpdateAcceptLanguagesPref().
+    prefs->SetString(language::prefs::kSelectedLanguages, accept_language_list);
+  }
+}
+
 }  // namespace browser_prefs
diff --git a/src/libcef/browser/prefs/browser_prefs.h b/src/libcef/browser/prefs/browser_prefs.h
index 94c6d13..baad587 100644
--- a/src/libcef/browser/prefs/browser_prefs.h
+++ b/src/libcef/browser/prefs/browser_prefs.h
@@ -11,6 +11,7 @@
 class FilePath;
 }
 
+class PrefRegistrySimple;
 class PrefService;
 class Profile;
 
@@ -19,12 +20,25 @@
 // Name for the user prefs JSON file.
 extern const char kUserPrefsFileName[];
 
+// Register preferences specific to CEF.
+void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
+void RegisterProfilePrefs(PrefRegistrySimple* registry);
+
 // Create the PrefService used to manage pref registration and storage.
-// |profile| will be nullptr for the system-level PrefService.
+// |profile| will be nullptr for the system-level PrefService. Used with the
+// Alloy runtime only.
 std::unique_ptr<PrefService> CreatePrefService(Profile* profile,
                                                const base::FilePath& cache_path,
                                                bool persist_user_preferences);
 
+// Returns the value for populating the accept-language HTTP request header.
+// |browser_context| and/or |browser| may be nullptr. If |expand| is true then
+// base languages and Q values may be added.
+std::string GetAcceptLanguageList(Profile* profile);
+
+// Set preferences for a newly initialized Profile.
+void SetInitialProfilePrefs(Profile* profile);
+
 }  // namespace browser_prefs
 
 #endif  // CEF_LIBCEF_BROWSER_PREFS_BROWSER_PREFS_H_
diff --git a/src/libcef/browser/prefs/pref_helper.cc b/src/libcef/browser/prefs/pref_helper.cc
new file mode 100644
index 0000000..99aa693
--- /dev/null
+++ b/src/libcef/browser/prefs/pref_helper.cc
@@ -0,0 +1,118 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "libcef/browser/prefs/pref_helper.h"
+
+#include "libcef/browser/thread_util.h"
+#include "libcef/common/values_impl.h"
+
+#include "base/notreached.h"
+#include "base/strings/stringprintf.h"
+#include "components/prefs/pref_service.h"
+
+namespace pref_helper {
+
+namespace {
+
+const char* GetTypeString(base::Value::Type type) {
+  switch (type) {
+    case base::Value::Type::NONE:
+      return "NULL";
+    case base::Value::Type::BOOLEAN:
+      return "BOOLEAN";
+    case base::Value::Type::INTEGER:
+      return "INTEGER";
+    case base::Value::Type::DOUBLE:
+      return "DOUBLE";
+    case base::Value::Type::STRING:
+      return "STRING";
+    case base::Value::Type::BINARY:
+      return "BINARY";
+    case base::Value::Type::DICT:
+      return "DICTIONARY";
+    case base::Value::Type::LIST:
+      return "LIST";
+  }
+
+  DCHECK(false);
+  return "UNKNOWN";
+}
+
+}  // namespace
+
+bool HasPreference(PrefService* pref_service, const CefString& name) {
+  return (pref_service->FindPreference(name) != nullptr);
+}
+
+CefRefPtr<CefValue> GetPreference(PrefService* pref_service,
+                                  const CefString& name) {
+  const PrefService::Preference* pref = pref_service->FindPreference(name);
+  if (!pref) {
+    return nullptr;
+  }
+  return new CefValueImpl(pref->GetValue()->Clone());
+}
+
+CefRefPtr<CefDictionaryValue> GetAllPreferences(PrefService* pref_service,
+                                                bool include_defaults) {
+  // Returns a DeepCopy of the value.
+  auto values = pref_service->GetPreferenceValues(
+      include_defaults ? PrefService::INCLUDE_DEFAULTS
+                       : PrefService::EXCLUDE_DEFAULTS);
+
+  // CefDictionaryValueImpl takes ownership of |values| contents.
+  return new CefDictionaryValueImpl(std::move(values), /*read_only=*/false);
+}
+
+bool CanSetPreference(PrefService* pref_service, const CefString& name) {
+  const PrefService::Preference* pref = pref_service->FindPreference(name);
+  return (pref && pref->IsUserModifiable());
+}
+
+bool SetPreference(PrefService* pref_service,
+                   const CefString& name,
+                   CefRefPtr<CefValue> value,
+                   CefString& error) {
+  // The below validation logic should match PrefService::SetUserPrefValue.
+
+  const PrefService::Preference* pref = pref_service->FindPreference(name);
+  if (!pref) {
+    error = "Trying to modify an unregistered preference";
+    return false;
+  }
+
+  if (!pref->IsUserModifiable()) {
+    error = "Trying to modify a preference that is not user modifiable";
+    return false;
+  }
+
+  if (!value.get()) {
+    // Reset the preference to its default value.
+    pref_service->ClearPref(name);
+    return true;
+  }
+
+  if (!value->IsValid()) {
+    error = "A valid value is required";
+    return false;
+  }
+
+  CefValueImpl* impl = static_cast<CefValueImpl*>(value.get());
+
+  CefValueImpl::ScopedLockedValue scoped_locked_value(impl);
+  base::Value* impl_value = impl->GetValueUnsafe();
+
+  if (pref->GetType() != impl_value->type()) {
+    error = base::StringPrintf(
+        "Trying to set a preference of type %s to value of type %s",
+        GetTypeString(pref->GetType()), GetTypeString(impl_value->type()));
+    return false;
+  }
+
+  // PrefService will make a DeepCopy of |impl_value|.
+  pref_service->Set(name, *impl_value);
+  return true;
+}
+
+}  // namespace pref_helper
diff --git a/src/libcef/browser/prefs/pref_helper.h b/src/libcef/browser/prefs/pref_helper.h
new file mode 100644
index 0000000..8c85208
--- /dev/null
+++ b/src/libcef/browser/prefs/pref_helper.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_PREFS_PREF_HELPER_H_
+#define CEF_LIBCEF_BROWSER_PREFS_PREF_HELPER_H_
+
+#include "include/cef_values.h"
+
+class PrefService;
+
+namespace pref_helper {
+
+// Function names and arguments match the CefPreferenceManager interface.
+
+bool HasPreference(PrefService* pref_service, const CefString& name);
+
+CefRefPtr<CefValue> GetPreference(PrefService* pref_service,
+                                  const CefString& name);
+
+CefRefPtr<CefDictionaryValue> GetAllPreferences(PrefService* pref_service,
+                                                bool include_defaults);
+
+bool CanSetPreference(PrefService* pref_service, const CefString& name);
+
+bool SetPreference(PrefService* pref_service,
+                   const CefString& name,
+                   CefRefPtr<CefValue> value,
+                   CefString& error);
+
+}  // namespace pref_helper
+
+#endif  // CEF_LIBCEF_BROWSER_PREFS_PREF_HELPER_H_
diff --git a/src/libcef/browser/prefs/pref_registrar.cc b/src/libcef/browser/prefs/pref_registrar.cc
new file mode 100644
index 0000000..4e1b09d
--- /dev/null
+++ b/src/libcef/browser/prefs/pref_registrar.cc
@@ -0,0 +1,96 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "libcef/browser/prefs/pref_registrar.h"
+
+#include "include/cef_app.h"
+#include "include/cef_browser_process_handler.h"
+#include "include/cef_preference.h"
+#include "libcef/common/app_manager.h"
+#include "libcef/common/values_impl.h"
+
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_store.h"
+
+namespace pref_registrar {
+
+namespace {
+
+class CefPreferenceRegistrarImpl : public CefPreferenceRegistrar {
+ public:
+  explicit CefPreferenceRegistrarImpl(PrefRegistrySimple* registry)
+      : registry_(registry) {}
+
+  CefPreferenceRegistrarImpl(const CefPreferenceRegistrarImpl&) = delete;
+  CefPreferenceRegistrarImpl& operator=(const CefPreferenceRegistrarImpl&) =
+      delete;
+
+  // CefPreferenceRegistrar methods.
+  bool AddPreference(const CefString& name,
+                     CefRefPtr<CefValue> default_value) override {
+    const std::string nameStr = name;
+    if (registry_->defaults()->GetValue(nameStr, nullptr)) {
+      LOG(ERROR) << "Trying to register a previously registered preference: "
+                 << nameStr;
+      return false;
+    }
+
+    switch (default_value->GetType()) {
+      case VTYPE_INVALID:
+      case VTYPE_NULL:
+      case VTYPE_BINARY:
+        break;
+      case VTYPE_BOOL:
+        registry_->RegisterBooleanPref(nameStr, default_value->GetBool());
+        return true;
+      case VTYPE_INT:
+        registry_->RegisterIntegerPref(nameStr, default_value->GetInt());
+        return true;
+      case VTYPE_DOUBLE:
+        registry_->RegisterDoublePref(nameStr, default_value->GetDouble());
+        return true;
+      case VTYPE_STRING:
+        registry_->RegisterStringPref(nameStr, default_value->GetString());
+        return true;
+      case VTYPE_DICTIONARY:
+      case VTYPE_LIST:
+        RegisterComplexPref(nameStr, default_value);
+        return true;
+    };
+
+    LOG(ERROR) << "Invalid value type for preference: " << nameStr;
+    return false;
+  }
+
+ private:
+  void RegisterComplexPref(const std::string& name,
+                           CefRefPtr<CefValue> default_value) {
+    CefValueImpl* impl = static_cast<CefValueImpl*>(default_value.get());
+    auto impl_value = impl->CopyValue();
+
+    if (impl_value.type() == base::Value::Type::DICT) {
+      registry_->RegisterDictionaryPref(name, std::move(impl_value.GetDict()));
+    } else if (impl_value.type() == base::Value::Type::LIST) {
+      registry_->RegisterListPref(name, std::move(impl_value.GetList()));
+    } else {
+      DCHECK(false);
+    }
+  }
+
+  PrefRegistrySimple* const registry_;
+};
+
+}  // namespace
+
+void RegisterCustomPrefs(cef_preferences_type_t type,
+                         PrefRegistrySimple* registry) {
+  if (auto app = CefAppManager::Get()->GetApplication()) {
+    if (auto handler = app->GetBrowserProcessHandler()) {
+      CefPreferenceRegistrarImpl registrar(registry);
+      handler->OnRegisterCustomPreferences(type, &registrar);
+    }
+  }
+}
+
+}  // namespace pref_registrar
diff --git a/src/libcef/browser/prefs/pref_registrar.h b/src/libcef/browser/prefs/pref_registrar.h
new file mode 100644
index 0000000..b6edcf4
--- /dev/null
+++ b/src/libcef/browser/prefs/pref_registrar.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_PREFS_PREF_REGISTRAR_H_
+#define CEF_LIBCEF_BROWSER_PREFS_PREF_REGISTRAR_H_
+
+#include "include/internal/cef_types.h"
+
+class PrefRegistrySimple;
+
+namespace pref_registrar {
+
+void RegisterCustomPrefs(cef_preferences_type_t type,
+                         PrefRegistrySimple* registry);
+
+}  // namespace pref_registrar
+
+#endif  // CEF_LIBCEF_BROWSER_PREFS_PREF_REGISTRAR_H_
diff --git a/src/libcef/browser/prefs/pref_store.cc b/src/libcef/browser/prefs/pref_store.cc
index 906dc0c..0fb170b 100644
--- a/src/libcef/browser/prefs/pref_store.cc
+++ b/src/libcef/browser/prefs/pref_store.cc
@@ -19,13 +19,13 @@
       init_complete_(false),
       committed_(true) {}
 
-bool CefPrefStore::GetValue(const std::string& key,
+bool CefPrefStore::GetValue(base::StringPiece key,
                             const base::Value** value) const {
   return prefs_.GetValue(key, value);
 }
 
-std::unique_ptr<base::DictionaryValue> CefPrefStore::GetValues() const {
-  return prefs_.AsDictionaryValue();
+base::Value::Dict CefPrefStore::GetValues() const {
+  return prefs_.AsDict();
 }
 
 bool CefPrefStore::GetMutableValue(const std::string& key,
@@ -42,7 +42,7 @@
 }
 
 bool CefPrefStore::HasObservers() const {
-  return observers_.might_have_observers();
+  return !observers_.empty();
 }
 
 bool CefPrefStore::IsInitializationComplete() const {
@@ -50,19 +50,25 @@
 }
 
 void CefPrefStore::SetValue(const std::string& key,
-                            std::unique_ptr<base::Value> value,
+                            base::Value value,
                             uint32_t flags) {
-  if (prefs_.SetValue(key, base::Value::FromUniquePtrValue(std::move(value)))) {
+  if (prefs_.SetValue(key, std::move(value))) {
     committed_ = false;
     NotifyPrefValueChanged(key);
   }
 }
 
 void CefPrefStore::SetValueSilently(const std::string& key,
-                                    std::unique_ptr<base::Value> value,
+                                    base::Value value,
                                     uint32_t flags) {
-  if (prefs_.SetValue(key, base::Value::FromUniquePtrValue(std::move(value))))
+  if (prefs_.SetValue(key, std::move(value))) {
     committed_ = false;
+  }
+}
+
+void CefPrefStore::RemoveValuesByPrefixSilently(const std::string& prefix) {
+  prefs_.ClearWithPrefix(prefix);
+  committed_ = false;
 }
 
 void CefPrefStore::RemoveValue(const std::string& key, uint32_t flags) {
@@ -88,10 +94,11 @@
 void CefPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) {
   DCHECK(!pending_async_read_);
   error_delegate_.reset(error_delegate);
-  if (block_async_read_)
+  if (block_async_read_) {
     pending_async_read_ = true;
-  else
+  } else {
     NotifyInitializationCompleted();
+  }
 }
 
 void CefPrefStore::CommitPendingWrite(
@@ -104,10 +111,6 @@
 
 void CefPrefStore::SchedulePendingLossyWrites() {}
 
-void CefPrefStore::ClearMutableValues() {
-  NOTIMPLEMENTED();
-}
-
 void CefPrefStore::OnStoreDeletionFromDisk() {}
 
 void CefPrefStore::SetInitializationCompleted() {
@@ -115,65 +118,85 @@
 }
 
 void CefPrefStore::NotifyPrefValueChanged(const std::string& key) {
-  for (Observer& observer : observers_)
+  for (Observer& observer : observers_) {
     observer.OnPrefValueChanged(key);
+  }
 }
 
 void CefPrefStore::NotifyInitializationCompleted() {
   DCHECK(!init_complete_);
   init_complete_ = true;
-  if (read_success_ && read_error_ != PREF_READ_ERROR_NONE && error_delegate_)
+  if (read_success_ && read_error_ != PREF_READ_ERROR_NONE && error_delegate_) {
     error_delegate_->OnError(read_error_);
-  for (Observer& observer : observers_)
+  }
+  for (Observer& observer : observers_) {
     observer.OnInitializationCompleted(read_success_);
+  }
 }
 
 void CefPrefStore::ReportValueChanged(const std::string& key, uint32_t flags) {
-  for (Observer& observer : observers_)
+  for (Observer& observer : observers_) {
     observer.OnPrefValueChanged(key);
+  }
 }
 
 void CefPrefStore::SetString(const std::string& key, const std::string& value) {
-  SetValue(key, std::make_unique<base::Value>(value), DEFAULT_PREF_WRITE_FLAGS);
+  SetValue(key, base::Value(value), DEFAULT_PREF_WRITE_FLAGS);
 }
 
 void CefPrefStore::SetInteger(const std::string& key, int value) {
-  SetValue(key, std::make_unique<base::Value>(value), DEFAULT_PREF_WRITE_FLAGS);
+  SetValue(key, base::Value(value), DEFAULT_PREF_WRITE_FLAGS);
 }
 
 void CefPrefStore::SetBoolean(const std::string& key, bool value) {
-  SetValue(key, std::make_unique<base::Value>(value), DEFAULT_PREF_WRITE_FLAGS);
+  SetValue(key, base::Value(value), DEFAULT_PREF_WRITE_FLAGS);
 }
 
 bool CefPrefStore::GetString(const std::string& key, std::string* value) const {
   const base::Value* stored_value;
-  if (!prefs_.GetValue(key, &stored_value) || !stored_value)
+  if (!prefs_.GetValue(key, &stored_value) || !stored_value) {
     return false;
+  }
 
-  return stored_value->GetAsString(value);
+  if (value && stored_value->is_string()) {
+    *value = stored_value->GetString();
+    return true;
+  }
+  return stored_value->is_string();
 }
 
 bool CefPrefStore::GetInteger(const std::string& key, int* value) const {
   const base::Value* stored_value;
-  if (!prefs_.GetValue(key, &stored_value) || !stored_value)
+  if (!prefs_.GetValue(key, &stored_value) || !stored_value) {
     return false;
+  }
 
-  return stored_value->GetAsInteger(value);
+  if (value && stored_value->is_int()) {
+    *value = stored_value->GetInt();
+    return true;
+  }
+  return stored_value->is_int();
 }
 
 bool CefPrefStore::GetBoolean(const std::string& key, bool* value) const {
   const base::Value* stored_value;
-  if (!prefs_.GetValue(key, &stored_value) || !stored_value)
+  if (!prefs_.GetValue(key, &stored_value) || !stored_value) {
     return false;
+  }
 
-  return stored_value->GetAsBoolean(value);
+  if (value && stored_value->is_bool()) {
+    *value = stored_value->GetBool();
+    return true;
+  }
+  return stored_value->is_bool();
 }
 
 void CefPrefStore::SetBlockAsyncRead(bool block_async_read) {
   DCHECK(!init_complete_);
   block_async_read_ = block_async_read;
-  if (pending_async_read_ && !block_async_read_)
+  if (pending_async_read_ && !block_async_read_) {
     NotifyInitializationCompleted();
+  }
 }
 
 void CefPrefStore::set_read_only(bool read_only) {
diff --git a/src/libcef/browser/prefs/pref_store.h b/src/libcef/browser/prefs/pref_store.h
index 4128fac..c5dc421 100644
--- a/src/libcef/browser/prefs/pref_store.h
+++ b/src/libcef/browser/prefs/pref_store.h
@@ -9,8 +9,6 @@
 
 #include <string>
 
-#include "base/compiler_specific.h"
-#include "base/macros.h"
 #include "base/observer_list.h"
 #include "components/prefs/persistent_pref_store.h"
 #include "components/prefs/pref_value_map.h"
@@ -22,10 +20,13 @@
  public:
   CefPrefStore();
 
+  CefPrefStore(const CefPrefStore&) = delete;
+  CefPrefStore& operator=(const CefPrefStore&) = delete;
+
   // Overriden from PrefStore.
-  bool GetValue(const std::string& key,
+  bool GetValue(base::StringPiece key,
                 const base::Value** result) const override;
-  std::unique_ptr<base::DictionaryValue> GetValues() const override;
+  base::Value::Dict GetValues() const override;
   void AddObserver(PrefStore::Observer* observer) override;
   void RemoveObserver(PrefStore::Observer* observer) override;
   bool HasObservers() const override;
@@ -35,11 +36,12 @@
   bool GetMutableValue(const std::string& key, base::Value** result) override;
   void ReportValueChanged(const std::string& key, uint32_t flags) override;
   void SetValue(const std::string& key,
-                std::unique_ptr<base::Value> value,
+                base::Value value,
                 uint32_t flags) override;
   void SetValueSilently(const std::string& key,
-                        std::unique_ptr<base::Value> value,
+                        base::Value value,
                         uint32_t flags) override;
+  void RemoveValuesByPrefixSilently(const std::string& prefix) override;
   void RemoveValue(const std::string& key, uint32_t flags) override;
   bool ReadOnly() const override;
   PrefReadError GetReadError() const override;
@@ -49,7 +51,6 @@
       base::OnceClosure done_callback,
       base::OnceClosure synchronous_done_callback) override;
   void SchedulePendingLossyWrites() override;
-  void ClearMutableValues() override;
   void OnStoreDeletionFromDisk() override;
 
   // Marks the store as having completed initialization.
@@ -112,8 +113,6 @@
 
   std::unique_ptr<ReadErrorDelegate> error_delegate_;
   base::ObserverList<PrefStore::Observer, true>::Unchecked observers_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefPrefStore);
 };
 
 #endif  // COMPONENTS_PREFS_TESTING_PREF_STORE_H_
diff --git a/src/libcef/browser/prefs/renderer_prefs.cc b/src/libcef/browser/prefs/renderer_prefs.cc
index 3941837..bd40eff 100644
--- a/src/libcef/browser/prefs/renderer_prefs.cc
+++ b/src/libcef/browser/prefs/renderer_prefs.cc
@@ -6,11 +6,12 @@
 
 #include <string>
 
-#include "libcef/browser/browser_context.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 #include "libcef/browser/context.h"
 #include "libcef/browser/extensions/browser_extensions_util.h"
 #include "libcef/common/cef_switches.h"
 #include "libcef/common/extensions/extensions_util.h"
+#include "libcef/features/runtime_checks.h"
 
 #include "base/command_line.h"
 #include "base/i18n/character_encoding.h"
@@ -20,7 +21,9 @@
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/extensions/extension_webkit_preferences.h"
 #include "chrome/browser/font_family_cache.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/prefs/prefs_tab_helper.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "components/pref_registry/pref_registry_syncable.h"
@@ -31,41 +34,23 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/web_preferences.h"
+#include "content/public/common/url_constants.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/view_type_utils.h"
 #include "extensions/common/constants.h"
 #include "media/media_buildflags.h"
 #include "third_party/blink/public/common/peerconnection/webrtc_ip_handling_policy.h"
+#include "third_party/blink/public/common/web_preferences/web_preferences.h"
+#include "ui/color/color_provider_key.h"
+#include "ui/native_theme/native_theme.h"
 
 namespace renderer_prefs {
 
 namespace {
 
-// Set default values based on CEF command-line flags for preferences that are
-// not available via the PrefService. Chromium command-line flags should not
-// exist for these preferences.
-void SetDefaultPrefs(content::WebPreferences& web) {
-  const base::CommandLine* command_line =
-      base::CommandLine::ForCurrentProcess();
-
-  web.javascript_enabled =
-      !command_line->HasSwitch(switches::kDisableJavascript);
-  web.allow_scripts_to_close_windows =
-      !command_line->HasSwitch(switches::kDisableJavascriptCloseWindows);
-  web.javascript_can_access_clipboard =
-      !command_line->HasSwitch(switches::kDisableJavascriptAccessClipboard);
-  web.allow_universal_access_from_file_urls =
-      command_line->HasSwitch(switches::kAllowUniversalAccessFromFileUrls);
-  web.shrinks_standalone_images_to_fit =
-      command_line->HasSwitch(switches::kImageShrinkStandaloneToFit);
-  web.text_areas_are_resizable =
-      !command_line->HasSwitch(switches::kDisableTextAreaResize);
-}
-
 // Chrome preferences.
 // Should match ChromeContentBrowserClient::OverrideWebkitPrefs.
-void SetChromePrefs(CefBrowserContext* profile, content::WebPreferences& web) {
+void SetChromePrefs(Profile* profile, blink::web_pref::WebPreferences& web) {
   PrefService* prefs = profile->GetPrefs();
 
   // Fill per-script font preferences.
@@ -85,9 +70,6 @@
   FontFamilyCache::FillFontFamilyMap(profile,
                                      prefs::kWebKitFantasyFontFamilyMap,
                                      &web.fantasy_font_family_map);
-  FontFamilyCache::FillFontFamilyMap(profile,
-                                     prefs::kWebKitPictographFontFamilyMap,
-                                     &web.pictograph_font_family_map);
 
   web.default_font_size = prefs->GetInteger(prefs::kWebKitDefaultFontSize);
   web.default_fixed_font_size =
@@ -101,12 +83,15 @@
   web.dom_paste_enabled = prefs->GetBoolean(prefs::kWebKitDomPasteEnabled);
   web.tabs_to_links = prefs->GetBoolean(prefs::kWebkitTabsToLinks);
 
-  if (!prefs->GetBoolean(prefs::kWebKitJavascriptEnabled))
+  if (!prefs->GetBoolean(prefs::kWebKitJavascriptEnabled)) {
     web.javascript_enabled = false;
-  if (!prefs->GetBoolean(prefs::kWebKitWebSecurityEnabled))
+  }
+  if (!prefs->GetBoolean(prefs::kWebKitWebSecurityEnabled)) {
     web.web_security_enabled = false;
-  if (!prefs->GetBoolean(prefs::kWebKitPluginsEnabled))
+  }
+  if (!prefs->GetBoolean(prefs::kWebKitPluginsEnabled)) {
     web.plugins_enabled = false;
+  }
   web.loads_images_automatically =
       prefs->GetBoolean(prefs::kWebKitLoadsImagesAutomatically);
 
@@ -118,7 +103,7 @@
   web.allow_running_insecure_content =
       prefs->GetBoolean(prefs::kWebKitAllowRunningInsecureContent);
 
-  web.password_echo_enabled = browser_defaults::kPasswordEchoEnabled;
+  web.password_echo_enabled = false;
 
   web.text_areas_are_resizable =
       prefs->GetBoolean(prefs::kWebKitTextAreasAreResizable);
@@ -128,12 +113,16 @@
   if (extensions::ExtensionsEnabled()) {
     std::string image_animation_policy =
         prefs->GetString(prefs::kAnimationPolicy);
-    if (image_animation_policy == kAnimationPolicyOnce)
-      web.animation_policy = content::IMAGE_ANIMATION_POLICY_ANIMATION_ONCE;
-    else if (image_animation_policy == kAnimationPolicyNone)
-      web.animation_policy = content::IMAGE_ANIMATION_POLICY_NO_ANIMATION;
-    else
-      web.animation_policy = content::IMAGE_ANIMATION_POLICY_ALLOWED;
+    if (image_animation_policy == kAnimationPolicyOnce) {
+      web.animation_policy =
+          blink::mojom::ImageAnimationPolicy::kImageAnimationPolicyAnimateOnce;
+    } else if (image_animation_policy == kAnimationPolicyNone) {
+      web.animation_policy =
+          blink::mojom::ImageAnimationPolicy::kImageAnimationPolicyNoAnimation;
+    } else {
+      web.animation_policy =
+          blink::mojom::ImageAnimationPolicy::kImageAnimationPolicyAllowed;
+    }
   }
 
   // Make sure we will set the default_encoding with canonical encoding name.
@@ -155,16 +144,19 @@
 
 // Extension preferences.
 // Should match ChromeContentBrowserClientExtensionsPart::OverrideWebkitPrefs.
-void SetExtensionPrefs(content::RenderViewHost* rvh,
-                       content::WebPreferences& web) {
-  if (!extensions::ExtensionsEnabled())
+void SetExtensionPrefs(content::WebContents* web_contents,
+                       content::RenderViewHost* rvh,
+                       blink::web_pref::WebPreferences& web) {
+  if (!extensions::ExtensionsEnabled()) {
     return;
+  }
 
   const extensions::ExtensionRegistry* registry =
       extensions::ExtensionRegistry::Get(
           rvh->GetProcess()->GetBrowserContext());
-  if (!registry)
+  if (!registry) {
     return;
+  }
 
   // Note: it's not possible for kExtensionsScheme to change during the lifetime
   // of the process.
@@ -173,106 +165,68 @@
   // correct scheme. Without this check, chrome-guest:// schemes used by webview
   // tags as well as hosts that happen to match the id of an installed extension
   // would get the wrong preferences.
-  const GURL& site_url = rvh->GetSiteInstance()->GetSiteURL();
-  if (!site_url.SchemeIs(extensions::kExtensionScheme))
+  const GURL& site_url =
+      web_contents->GetPrimaryMainFrame()->GetSiteInstance()->GetSiteURL();
+  if (!site_url.SchemeIs(extensions::kExtensionScheme)) {
     return;
+  }
 
-  content::WebContents* web_contents =
-      content::WebContents::FromRenderViewHost(rvh);
-  extensions::ViewType view_type = extensions::GetViewType(web_contents);
   const extensions::Extension* extension =
       registry->enabled_extensions().GetByID(site_url.host());
-  extension_webkit_preferences::SetPreferences(extension, view_type, &web);
-}
-
-// Helper macro for setting a WebPreferences variable based on the value of a
-// CefBrowserSettings variable.
-#define SET_STATE(cef_var, web_var)   \
-  if (cef_var == STATE_ENABLED)       \
-    web_var = true;                   \
-  else if (cef_var == STATE_DISABLED) \
-    web_var = false;
-
-// Set preferences based on CefBrowserSettings.
-void SetCefPrefs(const CefBrowserSettings& cef, content::WebPreferences& web) {
-  if (cef.standard_font_family.length > 0) {
-    web.standard_font_family_map[content::kCommonScript] =
-        CefString(&cef.standard_font_family);
-  }
-  if (cef.fixed_font_family.length > 0) {
-    web.fixed_font_family_map[content::kCommonScript] =
-        CefString(&cef.fixed_font_family);
-  }
-  if (cef.serif_font_family.length > 0) {
-    web.serif_font_family_map[content::kCommonScript] =
-        CefString(&cef.serif_font_family);
-  }
-  if (cef.sans_serif_font_family.length > 0) {
-    web.sans_serif_font_family_map[content::kCommonScript] =
-        CefString(&cef.sans_serif_font_family);
-  }
-  if (cef.cursive_font_family.length > 0) {
-    web.cursive_font_family_map[content::kCommonScript] =
-        CefString(&cef.cursive_font_family);
-  }
-  if (cef.fantasy_font_family.length > 0) {
-    web.fantasy_font_family_map[content::kCommonScript] =
-        CefString(&cef.fantasy_font_family);
-  }
-
-  if (cef.default_font_size > 0)
-    web.default_font_size = cef.default_font_size;
-  if (cef.default_fixed_font_size > 0)
-    web.default_fixed_font_size = cef.default_fixed_font_size;
-  if (cef.minimum_font_size > 0)
-    web.minimum_font_size = cef.minimum_font_size;
-  if (cef.minimum_logical_font_size > 0)
-    web.minimum_logical_font_size = cef.minimum_logical_font_size;
-
-  if (cef.default_encoding.length > 0)
-    web.default_encoding = CefString(&cef.default_encoding);
-
-  SET_STATE(cef.remote_fonts, web.remote_fonts_enabled);
-  SET_STATE(cef.javascript, web.javascript_enabled);
-  SET_STATE(cef.javascript_close_windows, web.allow_scripts_to_close_windows);
-  SET_STATE(cef.javascript_access_clipboard,
-            web.javascript_can_access_clipboard);
-  SET_STATE(cef.javascript_dom_paste, web.dom_paste_enabled);
-  SET_STATE(cef.plugins, web.plugins_enabled);
-  SET_STATE(cef.universal_access_from_file_urls,
-            web.allow_universal_access_from_file_urls);
-  SET_STATE(cef.file_access_from_file_urls,
-            web.allow_file_access_from_file_urls);
-  SET_STATE(cef.web_security, web.web_security_enabled);
-  SET_STATE(cef.image_loading, web.loads_images_automatically);
-  SET_STATE(cef.image_shrink_standalone_to_fit,
-            web.shrinks_standalone_images_to_fit);
-  SET_STATE(cef.text_area_resize, web.text_areas_are_resizable);
-  SET_STATE(cef.tab_to_links, web.tabs_to_links);
-  SET_STATE(cef.local_storage, web.local_storage_enabled);
-  SET_STATE(cef.databases, web.databases_enabled);
-  SET_STATE(cef.application_cache, web.application_cache_enabled);
-
-  // Never explicitly enable GPU-related functions in this method because the
-  // GPU blacklist is not being checked here.
-  if (cef.webgl == STATE_DISABLED) {
-    web.webgl1_enabled = false;
-    web.webgl2_enabled = false;
-  }
+  extension_webkit_preferences::SetPreferences(extension, &web);
 }
 
 void SetString(CommandLinePrefStore* prefs,
                const std::string& key,
                const std::string& value) {
-  prefs->SetValue(key, base::WrapUnique(new base::Value(value)),
+  prefs->SetValue(key, base::Value(value),
                   WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
 }
 
 void SetBool(CommandLinePrefStore* prefs, const std::string& key, bool value) {
-  prefs->SetValue(key, base::WrapUnique(new base::Value(value)),
+  prefs->SetValue(key, base::Value(value),
                   WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
 }
 
+blink::mojom::PreferredColorScheme ToBlinkPreferredColorScheme(
+    ui::NativeTheme::PreferredColorScheme native_theme_scheme) {
+  switch (native_theme_scheme) {
+    case ui::NativeTheme::PreferredColorScheme::kDark:
+      return blink::mojom::PreferredColorScheme::kDark;
+    case ui::NativeTheme::PreferredColorScheme::kLight:
+      return blink::mojom::PreferredColorScheme::kLight;
+  }
+
+  DCHECK(false);
+}
+
+// From chrome/browser/chrome_content_browser_client.cc
+// Returns true if preferred color scheme is modified based on at least one of
+// the following -
+// |url| - Last committed url.
+// |native_theme| - For other platforms based on native theme scheme.
+bool UpdatePreferredColorScheme(blink::web_pref::WebPreferences* web_prefs,
+                                const GURL& url,
+                                content::WebContents* web_contents,
+                                const ui::NativeTheme* native_theme) {
+  auto old_preferred_color_scheme = web_prefs->preferred_color_scheme;
+
+  // Update based on native theme scheme.
+  web_prefs->preferred_color_scheme =
+      ToBlinkPreferredColorScheme(native_theme->GetPreferredColorScheme());
+
+  if (url.SchemeIs(content::kChromeUIScheme)) {
+    // WebUI should track the color mode of the ColorProvider associated with
+    // |web_contents|.
+    web_prefs->preferred_color_scheme =
+        web_contents->GetColorMode() == ui::ColorProviderKey::ColorMode::kLight
+            ? blink::mojom::PreferredColorScheme::kLight
+            : blink::mojom::PreferredColorScheme::kDark;
+  }
+
+  return old_preferred_color_scheme != web_prefs->preferred_color_scheme;
+}
+
 }  // namespace
 
 void SetCommandLinePrefDefaults(CommandLinePrefStore* prefs) {
@@ -284,14 +238,107 @@
               command_line->GetSwitchValueASCII(switches::kDefaultEncoding));
   }
 
-  if (command_line->HasSwitch(switches::kDisableJavascriptDomPaste))
+  if (command_line->HasSwitch(switches::kDisableJavascriptDomPaste)) {
     SetBool(prefs, prefs::kWebKitDomPasteEnabled, false);
-  if (command_line->HasSwitch(switches::kDisableImageLoading))
+  }
+  if (command_line->HasSwitch(switches::kDisableImageLoading)) {
     SetBool(prefs, prefs::kWebKitLoadsImagesAutomatically, false);
-  if (command_line->HasSwitch(switches::kDisableTabToLinks))
+  }
+  if (command_line->HasSwitch(switches::kDisableTabToLinks)) {
     SetBool(prefs, prefs::kWebkitTabsToLinks, false);
-  if (command_line->HasSwitch(switches::kDisablePlugins))
-    SetBool(prefs, prefs::kWebKitPluginsEnabled, false);
+  }
+}
+
+void SetDefaultPrefs(blink::web_pref::WebPreferences& web) {
+  const base::CommandLine* command_line =
+      base::CommandLine::ForCurrentProcess();
+
+  web.javascript_enabled =
+      !command_line->HasSwitch(switches::kDisableJavascript);
+  web.allow_scripts_to_close_windows =
+      !command_line->HasSwitch(switches::kDisableJavascriptCloseWindows);
+  web.javascript_can_access_clipboard =
+      !command_line->HasSwitch(switches::kDisableJavascriptAccessClipboard);
+  web.allow_universal_access_from_file_urls =
+      command_line->HasSwitch(switches::kAllowUniversalAccessFromFileUrls);
+  web.shrinks_standalone_images_to_fit =
+      command_line->HasSwitch(switches::kImageShrinkStandaloneToFit);
+  web.text_areas_are_resizable =
+      !command_line->HasSwitch(switches::kDisableTextAreaResize);
+}
+
+// Helper macro for setting a WebPreferences variable based on the value of a
+// CefBrowserSettings variable.
+#define SET_STATE(cef_var, web_var)   \
+  if (cef_var == STATE_ENABLED)       \
+    web_var = true;                   \
+  else if (cef_var == STATE_DISABLED) \
+    web_var = false;
+
+void SetCefPrefs(const CefBrowserSettings& cef,
+                 blink::web_pref::WebPreferences& web) {
+  if (cef.standard_font_family.length > 0) {
+    web.standard_font_family_map[blink::web_pref::kCommonScript] =
+        CefString(&cef.standard_font_family);
+  }
+  if (cef.fixed_font_family.length > 0) {
+    web.fixed_font_family_map[blink::web_pref::kCommonScript] =
+        CefString(&cef.fixed_font_family);
+  }
+  if (cef.serif_font_family.length > 0) {
+    web.serif_font_family_map[blink::web_pref::kCommonScript] =
+        CefString(&cef.serif_font_family);
+  }
+  if (cef.sans_serif_font_family.length > 0) {
+    web.sans_serif_font_family_map[blink::web_pref::kCommonScript] =
+        CefString(&cef.sans_serif_font_family);
+  }
+  if (cef.cursive_font_family.length > 0) {
+    web.cursive_font_family_map[blink::web_pref::kCommonScript] =
+        CefString(&cef.cursive_font_family);
+  }
+  if (cef.fantasy_font_family.length > 0) {
+    web.fantasy_font_family_map[blink::web_pref::kCommonScript] =
+        CefString(&cef.fantasy_font_family);
+  }
+
+  if (cef.default_font_size > 0) {
+    web.default_font_size = cef.default_font_size;
+  }
+  if (cef.default_fixed_font_size > 0) {
+    web.default_fixed_font_size = cef.default_fixed_font_size;
+  }
+  if (cef.minimum_font_size > 0) {
+    web.minimum_font_size = cef.minimum_font_size;
+  }
+  if (cef.minimum_logical_font_size > 0) {
+    web.minimum_logical_font_size = cef.minimum_logical_font_size;
+  }
+
+  if (cef.default_encoding.length > 0) {
+    web.default_encoding = CefString(&cef.default_encoding);
+  }
+
+  SET_STATE(cef.remote_fonts, web.remote_fonts_enabled);
+  SET_STATE(cef.javascript, web.javascript_enabled);
+  SET_STATE(cef.javascript_close_windows, web.allow_scripts_to_close_windows);
+  SET_STATE(cef.javascript_access_clipboard,
+            web.javascript_can_access_clipboard);
+  SET_STATE(cef.javascript_dom_paste, web.dom_paste_enabled);
+  SET_STATE(cef.image_loading, web.loads_images_automatically);
+  SET_STATE(cef.image_shrink_standalone_to_fit,
+            web.shrinks_standalone_images_to_fit);
+  SET_STATE(cef.text_area_resize, web.text_areas_are_resizable);
+  SET_STATE(cef.tab_to_links, web.tabs_to_links);
+  SET_STATE(cef.local_storage, web.local_storage_enabled);
+  SET_STATE(cef.databases, web.databases_enabled);
+
+  // Never explicitly enable GPU-related functions in this method because the
+  // GPU blacklist is not being checked here.
+  if (cef.webgl == STATE_DISABLED) {
+    web.webgl1_enabled = false;
+    web.webgl2_enabled = false;
+  }
 }
 
 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
@@ -299,19 +346,14 @@
   PrefsTabHelper::RegisterProfilePrefs(registry, locale);
   RegisterAnimationPolicyPrefs(registry);
 
-  // From chrome::RegisterBrowserUserPrefs.
-  registry->RegisterBooleanPref(
-      prefs::kEnableDoNotTrack, false,
-      user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+  // From chrome/browser/ui/browser_ui_prefs.cc RegisterBrowserUserPrefs.
+  registry->RegisterBooleanPref(prefs::kCaretBrowsingEnabled, false);
 
-  // TODO(guoweis): Remove next 2 options at M50.
-  registry->RegisterBooleanPref(prefs::kWebRTCMultipleRoutesEnabled, true);
-  registry->RegisterBooleanPref(prefs::kWebRTCNonProxiedUdpEnabled, true);
   registry->RegisterStringPref(prefs::kWebRTCIPHandlingPolicy,
                                blink::kWebRTCIPHandlingDefault);
   registry->RegisterStringPref(prefs::kWebRTCUDPPortRange, std::string());
 
-#if !defined(OS_MACOSX)
+#if !BUILDFLAG(IS_MAC)
   registry->RegisterBooleanPref(prefs::kFullscreenAllowed, true);
 #endif
 
@@ -325,22 +367,55 @@
 }
 
 void PopulateWebPreferences(content::RenderViewHost* rvh,
-                            content::WebPreferences& web) {
-  CefRefPtr<CefBrowserHostImpl> browser =
-      extensions::GetOwnerBrowserForHost(rvh, nullptr);
+                            blink::web_pref::WebPreferences& web,
+                            SkColor& base_background_color) {
+  REQUIRE_ALLOY_RUNTIME();
+  CefRefPtr<AlloyBrowserHostImpl> browser = static_cast<AlloyBrowserHostImpl*>(
+      extensions::GetOwnerBrowserForHost(rvh, nullptr).get());
 
   // Set defaults for preferences that are not handled by PrefService.
   SetDefaultPrefs(web);
 
   // Set preferences based on the context's PrefService.
   if (browser) {
-    CefBrowserContext* profile = static_cast<CefBrowserContext*>(
+    auto profile = Profile::FromBrowserContext(
         browser->web_contents()->GetBrowserContext());
     SetChromePrefs(profile, web);
   }
 
+  auto* native_theme = ui::NativeTheme::GetInstanceForWeb();
+  switch (native_theme->GetPreferredColorScheme()) {
+    case ui::NativeTheme::PreferredColorScheme::kDark:
+      web.preferred_color_scheme = blink::mojom::PreferredColorScheme::kDark;
+      break;
+    case ui::NativeTheme::PreferredColorScheme::kLight:
+      web.preferred_color_scheme = blink::mojom::PreferredColorScheme::kLight;
+      break;
+  }
+
+  switch (native_theme->GetPreferredContrast()) {
+    case ui::NativeTheme::PreferredContrast::kNoPreference:
+      web.preferred_contrast = blink::mojom::PreferredContrast::kNoPreference;
+      break;
+    case ui::NativeTheme::PreferredContrast::kMore:
+      web.preferred_contrast = blink::mojom::PreferredContrast::kMore;
+      break;
+    case ui::NativeTheme::PreferredContrast::kLess:
+      web.preferred_contrast = blink::mojom::PreferredContrast::kLess;
+      break;
+    case ui::NativeTheme::PreferredContrast::kCustom:
+      web.preferred_contrast = blink::mojom::PreferredContrast::kCustom;
+      break;
+  }
+
+  auto web_contents = content::WebContents::FromRenderViewHost(rvh);
+  UpdatePreferredColorScheme(
+      &web,
+      web_contents->GetPrimaryMainFrame()->GetSiteInstance()->GetSiteURL(),
+      web_contents, native_theme);
+
   // Set preferences based on the extension.
-  SetExtensionPrefs(rvh, web);
+  SetExtensionPrefs(web_contents, rvh, web);
 
   if (browser) {
     // Set preferences based on CefBrowserSettings.
@@ -349,13 +424,21 @@
     web.picture_in_picture_enabled = browser->IsPictureInPictureSupported();
 
     // Set the background color for the WebView.
-    web.base_background_color = browser->GetBackgroundColor();
+    base_background_color = browser->GetBackgroundColor();
   } else {
     // We don't know for sure that the browser will be windowless but assume
     // that the global windowless state is likely to be accurate.
-    web.base_background_color =
+    base_background_color =
         CefContext::Get()->GetBackgroundColor(nullptr, STATE_DEFAULT);
   }
 }
 
+bool PopulateWebPreferencesAfterNavigation(
+    content::WebContents* web_contents,
+    blink::web_pref::WebPreferences& web) {
+  auto* native_theme = ui::NativeTheme::GetInstanceForWeb();
+  return UpdatePreferredColorScheme(&web, web_contents->GetLastCommittedURL(),
+                                    web_contents, native_theme);
+}
+
 }  // namespace renderer_prefs
diff --git a/src/libcef/browser/prefs/renderer_prefs.h b/src/libcef/browser/prefs/renderer_prefs.h
index 3fd4b1b..7222d6e 100644
--- a/src/libcef/browser/prefs/renderer_prefs.h
+++ b/src/libcef/browser/prefs/renderer_prefs.h
@@ -8,11 +8,19 @@
 
 #include "include/internal/cef_types_wrappers.h"
 
+#include "third_party/skia/include/core/SkColor.h"
+
 class CommandLinePrefStore;
 
+namespace blink {
+namespace web_pref {
+struct WebPreferences;
+}
+}  // namespace blink
+
 namespace content {
 class RenderViewHost;
-struct WebPreferences;
+class WebContents;
 }  // namespace content
 
 namespace user_prefs {
@@ -30,10 +38,23 @@
 // for these preferences.
 void SetCommandLinePrefDefaults(CommandLinePrefStore* prefs);
 
+// Set default values based on CEF command-line flags for preferences that are
+// not available via the PrefService. Chromium command-line flags should not
+// exist for these preferences.
+void SetDefaultPrefs(blink::web_pref::WebPreferences& web);
+
+// Set preferences based on CefBrowserSettings.
+void SetCefPrefs(const CefBrowserSettings& cef,
+                 blink::web_pref::WebPreferences& web);
+
 // Populate WebPreferences based on a combination of command-line values,
 // PrefService and CefBrowserSettings.
 void PopulateWebPreferences(content::RenderViewHost* rvh,
-                            content::WebPreferences& web);
+                            blink::web_pref::WebPreferences& web,
+                            SkColor& base_background_color);
+bool PopulateWebPreferencesAfterNavigation(
+    content::WebContents* web_contents,
+    blink::web_pref::WebPreferences& web);
 
 }  // namespace renderer_prefs
 
diff --git a/src/libcef/browser/print_settings_impl.cc b/src/libcef/browser/print_settings_impl.cc
index b91942f..b789c8f 100644
--- a/src/libcef/browser/print_settings_impl.cc
+++ b/src/libcef/browser/print_settings_impl.cc
@@ -6,15 +6,17 @@
 
 #include "base/logging.h"
 
+#include "printing/mojom/print.mojom.h"
+
 CefPrintSettingsImpl::CefPrintSettingsImpl(
     std::unique_ptr<printing::PrintSettings> settings,
     bool read_only)
-    : CefValueBase<CefPrintSettings, printing::PrintSettings>(settings.get(),
-                                                              nullptr,
-                                                              kOwnerNoDelete,
-                                                              read_only,
-                                                              nullptr),
-      settings_(std::move(settings)) {}
+    : CefValueBase<CefPrintSettings, printing::PrintSettings>(
+          settings.release(),
+          nullptr,
+          kOwnerWillDelete,
+          read_only,
+          nullptr) {}
 
 bool CefPrintSettingsImpl::IsValid() {
   return !detached();
@@ -88,8 +90,9 @@
 
 void CefPrintSettingsImpl::GetPageRanges(PageRangeList& ranges) {
   CEF_VALUE_VERIFY_RETURN_VOID(false);
-  if (!ranges.empty())
+  if (!ranges.empty()) {
     ranges.clear();
+  }
   const printing::PageRanges& page_ranges = const_value().ranges();
   printing::PageRanges::const_iterator it = page_ranges.begin();
   for (; it != page_ranges.end(); ++it) {
@@ -120,7 +123,7 @@
 
 void CefPrintSettingsImpl::SetColorModel(ColorModel model) {
   CEF_VALUE_VERIFY_RETURN_VOID(true);
-  mutable_value()->set_color(static_cast<printing::ColorModel>(model));
+  mutable_value()->set_color(static_cast<printing::mojom::ColorModel>(model));
 }
 
 CefPrintSettings::ColorModel CefPrintSettingsImpl::GetColorModel() {
@@ -140,7 +143,8 @@
 
 void CefPrintSettingsImpl::SetDuplexMode(DuplexMode mode) {
   CEF_VALUE_VERIFY_RETURN_VOID(true);
-  mutable_value()->set_duplex_mode(static_cast<printing::DuplexMode>(mode));
+  mutable_value()->set_duplex_mode(
+      static_cast<printing::mojom::DuplexMode>(mode));
 }
 
 CefPrintSettings::DuplexMode CefPrintSettingsImpl::GetDuplexMode() {
@@ -149,8 +153,7 @@
 }
 
 std::unique_ptr<printing::PrintSettings> CefPrintSettingsImpl::TakeOwnership() {
-  Detach(nullptr);
-  return std::move(settings_);
+  return base::WrapUnique(Detach(nullptr));
 }
 
 // CefPrintSettings implementation.
diff --git a/src/libcef/browser/print_settings_impl.h b/src/libcef/browser/print_settings_impl.h
index 589048e..2bc356b 100644
--- a/src/libcef/browser/print_settings_impl.h
+++ b/src/libcef/browser/print_settings_impl.h
@@ -18,6 +18,9 @@
   CefPrintSettingsImpl(std::unique_ptr<printing::PrintSettings> settings,
                        bool read_only);
 
+  CefPrintSettingsImpl(const CefPrintSettingsImpl&) = delete;
+  CefPrintSettingsImpl& operator=(const CefPrintSettingsImpl&) = delete;
+
   // CefPrintSettings methods.
   bool IsValid() override;
   bool IsReadOnly() override;
@@ -44,12 +47,7 @@
   void SetDuplexMode(DuplexMode mode) override;
   DuplexMode GetDuplexMode() override;
 
-  std::unique_ptr<printing::PrintSettings> TakeOwnership() WARN_UNUSED_RESULT;
-
- private:
-  std::unique_ptr<printing::PrintSettings> settings_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefPrintSettingsImpl);
+  [[nodiscard]] std::unique_ptr<printing::PrintSettings> TakeOwnership();
 };
 
 #endif  // CEF_LIBCEF_BROWSER_PRINT_SETTINGS_IMPL_H_
diff --git a/src/libcef/browser/printing/constrained_window_views_client.cc b/src/libcef/browser/printing/constrained_window_views_client.cc
deleted file mode 100644
index 1670f41..0000000
--- a/src/libcef/browser/printing/constrained_window_views_client.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/printing/constrained_window_views_client.h"
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "chrome/browser/platform_util.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "components/web_modal/web_contents_modal_dialog_host.h"
-
-namespace {
-
-class CefConstrainedWindowViewsClient
-    : public constrained_window::ConstrainedWindowViewsClient {
- public:
-  CefConstrainedWindowViewsClient() {}
-  ~CefConstrainedWindowViewsClient() override {}
-
- private:
-  // ConstrainedWindowViewsClient:
-  web_modal::ModalDialogHost* GetModalDialogHost(
-      gfx::NativeWindow parent) override {
-    NOTREACHED();
-    return nullptr;
-  }
-  gfx::NativeView GetDialogHostView(gfx::NativeWindow parent) override {
-    NOTREACHED();
-    return gfx::NativeView();
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(CefConstrainedWindowViewsClient);
-};
-
-}  // namespace
-
-std::unique_ptr<constrained_window::ConstrainedWindowViewsClient>
-CreateCefConstrainedWindowViewsClient() {
-  return base::WrapUnique(new CefConstrainedWindowViewsClient);
-}
\ No newline at end of file
diff --git a/src/libcef/browser/printing/constrained_window_views_client.h b/src/libcef/browser/printing/constrained_window_views_client.h
deleted file mode 100644
index 0f18784..0000000
--- a/src/libcef/browser/printing/constrained_window_views_client.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_BROWSER_PRINTING_CONSTRAINED_WINDOW_VIEWS_CLIENT_H_
-#define CEF_LIBCEF_BROWSER_PRINTING_CONSTRAINED_WINDOW_VIEWS_CLIENT_H_
-
-#include <memory>
-
-#include "components/constrained_window/constrained_window_views_client.h"
-
-// Creates a ConstrainedWindowViewsClient for the Chrome environment.
-std::unique_ptr<constrained_window::ConstrainedWindowViewsClient>
-CreateCefConstrainedWindowViewsClient();
-
-#endif  // CEF_LIBCEF_BROWSER_PRINTING_CONSTRAINED_WINDOW_VIEWS_CLIENT_H_
\ No newline at end of file
diff --git a/src/libcef/browser/printing/print_dialog_linux.cc b/src/libcef/browser/printing/print_dialog_linux.cc
index 02c51b0..3bf12e6 100644
--- a/src/libcef/browser/printing/print_dialog_linux.cc
+++ b/src/libcef/browser/printing/print_dialog_linux.cc
@@ -11,15 +11,18 @@
 #include "libcef/browser/extensions/browser_extensions_util.h"
 #include "libcef/browser/print_settings_impl.h"
 #include "libcef/browser/thread_util.h"
-#include "libcef/common/content_client.h"
+#include "libcef/common/app_manager.h"
+#include "libcef/common/frame_util.h"
 
-#include "base/bind.h"
 #include "base/files/file_util.h"
+#include "base/functional/bind.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
+#include "content/public/browser/global_routing_id.h"
 #include "printing/metafile.h"
+#include "printing/mojom/print.mojom-shared.h"
 #include "printing/print_job_constants.h"
 #include "printing/print_settings.h"
 
@@ -27,11 +30,42 @@
 using printing::PageRanges;
 using printing::PrintSettings;
 
+namespace {
+
+CefRefPtr<CefBrowserHostBase> GetBrowserForContext(
+    printing::PrintingContextLinux* context) {
+  // The print preview dialog won't have a valid child ID.
+  if (!frame_util::IsValidChildId(context->render_process_id())) {
+    return nullptr;
+  }
+
+  return extensions::GetOwnerBrowserForGlobalId(
+      frame_util::MakeGlobalId(context->render_process_id(),
+                               context->render_frame_id()),
+      nullptr);
+}
+
+CefRefPtr<CefPrintHandler> GetPrintHandlerForBrowser(
+    CefRefPtr<CefBrowserHostBase> browser) {
+  if (browser) {
+    if (auto client = browser->GetClient()) {
+      return client->GetPrintHandler();
+    }
+  }
+  return nullptr;
+}
+
+}  // namespace
+
 class CefPrintDialogCallbackImpl : public CefPrintDialogCallback {
  public:
   explicit CefPrintDialogCallbackImpl(CefRefPtr<CefPrintDialogLinux> dialog)
       : dialog_(dialog) {}
 
+  CefPrintDialogCallbackImpl(const CefPrintDialogCallbackImpl&) = delete;
+  CefPrintDialogCallbackImpl& operator=(const CefPrintDialogCallbackImpl&) =
+      delete;
+
   void Continue(CefRefPtr<CefPrintSettings> settings) override {
     if (CEF_CURRENTLY_ON_UIT()) {
       if (dialog_.get()) {
@@ -39,8 +73,9 @@
         dialog_ = nullptr;
       }
     } else {
-      CEF_POST_TASK(CEF_UIT, base::Bind(&CefPrintDialogCallbackImpl::Continue,
-                                        this, settings));
+      CEF_POST_TASK(CEF_UIT,
+                    base::BindOnce(&CefPrintDialogCallbackImpl::Continue, this,
+                                   settings));
     }
   }
 
@@ -52,7 +87,7 @@
       }
     } else {
       CEF_POST_TASK(CEF_UIT,
-                    base::Bind(&CefPrintDialogCallbackImpl::Cancel, this));
+                    base::BindOnce(&CefPrintDialogCallbackImpl::Cancel, this));
     }
   }
 
@@ -62,7 +97,6 @@
   CefRefPtr<CefPrintDialogLinux> dialog_;
 
   IMPLEMENT_REFCOUNTING(CefPrintDialogCallbackImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefPrintDialogCallbackImpl);
 };
 
 class CefPrintJobCallbackImpl : public CefPrintJobCallback {
@@ -70,6 +104,9 @@
   explicit CefPrintJobCallbackImpl(CefRefPtr<CefPrintDialogLinux> dialog)
       : dialog_(dialog) {}
 
+  CefPrintJobCallbackImpl(const CefPrintJobCallbackImpl&) = delete;
+  CefPrintJobCallbackImpl& operator=(const CefPrintJobCallbackImpl&) = delete;
+
   void Continue() override {
     if (CEF_CURRENTLY_ON_UIT()) {
       if (dialog_.get()) {
@@ -78,7 +115,7 @@
       }
     } else {
       CEF_POST_TASK(CEF_UIT,
-                    base::Bind(&CefPrintJobCallbackImpl::Continue, this));
+                    base::BindOnce(&CefPrintJobCallbackImpl::Continue, this));
     }
   }
 
@@ -88,80 +125,91 @@
   CefRefPtr<CefPrintDialogLinux> dialog_;
 
   IMPLEMENT_REFCOUNTING(CefPrintJobCallbackImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefPrintJobCallbackImpl);
 };
 
-// static
-printing::PrintDialogGtkInterface* CefPrintDialogLinux::CreatePrintDialog(
-    PrintingContextLinux* context) {
+CefPrintingContextLinuxDelegate::CefPrintingContextLinuxDelegate() = default;
+
+printing::PrintDialogLinuxInterface*
+CefPrintingContextLinuxDelegate::CreatePrintDialog(
+    printing::PrintingContextLinux* context) {
   CEF_REQUIRE_UIT();
-  return new CefPrintDialogLinux(context);
+
+  printing::PrintDialogLinuxInterface* interface = nullptr;
+
+  auto browser = GetBrowserForContext(context);
+  if (!browser) {
+    LOG(ERROR) << "No associated browser in CreatePrintDialog; using default "
+                  "printing implementation.";
+  }
+
+  auto handler = GetPrintHandlerForBrowser(browser);
+  if (!handler) {
+    if (default_delegate_) {
+      interface = default_delegate_->CreatePrintDialog(context);
+      DCHECK(interface);
+    }
+  } else {
+    interface = new CefPrintDialogLinux(context, browser, handler);
+  }
+
+  if (!interface) {
+    LOG(ERROR) << "Null interface in CreatePrintDialog; printing will fail.";
+  }
+
+  return interface;
 }
 
-// static
-gfx::Size CefPrintDialogLinux::GetPdfPaperSize(
+gfx::Size CefPrintingContextLinuxDelegate::GetPdfPaperSize(
     printing::PrintingContextLinux* context) {
   CEF_REQUIRE_UIT();
 
   gfx::Size size;
 
-  CefRefPtr<CefApp> app = CefContentClient::Get()->application();
-  if (app.get()) {
-    CefRefPtr<CefBrowserProcessHandler> browser_handler =
-        app->GetBrowserProcessHandler();
-    if (browser_handler.get()) {
-      CefRefPtr<CefPrintHandler> handler = browser_handler->GetPrintHandler();
-      if (handler.get()) {
-        const printing::PrintSettings& settings = context->settings();
-        CefSize cef_size =
-            handler->GetPdfPaperSize(settings.device_units_per_inch());
-        size.SetSize(cef_size.width, cef_size.height);
-      }
+  auto browser = GetBrowserForContext(context);
+  if (!browser) {
+    LOG(ERROR) << "No associated browser in GetPdfPaperSize; using default "
+                  "printing implementation.";
+  }
+
+  auto handler = GetPrintHandlerForBrowser(browser);
+  if (!handler) {
+    if (default_delegate_) {
+      size = default_delegate_->GetPdfPaperSize(context);
+      DCHECK(!size.IsEmpty());
     }
+  } else {
+    const printing::PrintSettings& settings = context->settings();
+    CefSize cef_size = handler->GetPdfPaperSize(
+        browser.get(), settings.device_units_per_inch());
+    size.SetSize(cef_size.width, cef_size.height);
   }
 
   if (size.IsEmpty()) {
-    LOG(ERROR) << "Empty size value returned in GetPdfPaperSize; "
-                  "PDF printing will fail.";
+    LOG(ERROR) << "Empty size value returned in GetPdfPaperSize; PDF printing "
+                  "will fail.";
   }
   return size;
 }
 
-// static
-void CefPrintDialogLinux::OnPrintStart(int render_process_id,
-                                       int render_routing_id) {
-  if (!CEF_CURRENTLY_ON(CEF_UIT)) {
-    CEF_POST_TASK(CEF_UIT, base::Bind(&CefPrintDialogLinux::OnPrintStart,
-                                      render_process_id, render_routing_id));
-    return;
-  }
-
-  CefRefPtr<CefApp> app = CefContentClient::Get()->application();
-  if (!app.get())
-    return;
-
-  CefRefPtr<CefBrowserProcessHandler> browser_handler =
-      app->GetBrowserProcessHandler();
-  if (!browser_handler.get())
-    return;
-
-  CefRefPtr<CefPrintHandler> handler = browser_handler->GetPrintHandler();
-  if (!handler.get())
-    return;
-
-  CefRefPtr<CefBrowserHostImpl> browser =
-      extensions::GetOwnerBrowserForFrameRoute(render_process_id,
-                                               render_routing_id, nullptr);
-  if (browser.get())
-    handler->OnPrintStart(browser.get());
+void CefPrintingContextLinuxDelegate::SetDefaultDelegate(
+    ui::PrintingContextLinuxDelegate* delegate) {
+  DCHECK(!default_delegate_);
+  default_delegate_ = delegate;
 }
 
-CefPrintDialogLinux::CefPrintDialogLinux(PrintingContextLinux* context)
-    : context_(context) {
+CefPrintDialogLinux::CefPrintDialogLinux(PrintingContextLinux* context,
+                                         CefRefPtr<CefBrowserHostBase> browser,
+                                         CefRefPtr<CefPrintHandler> handler)
+    : context_(context), browser_(browser), handler_(handler) {
+  CEF_REQUIRE_UIT();
   DCHECK(context_);
-  browser_ = extensions::GetOwnerBrowserForFrameRoute(
-      context_->render_process_id(), context_->render_frame_id(), nullptr);
   DCHECK(browser_);
+  DCHECK(handler_);
+
+  // Paired with the ReleaseDialog() call.
+  AddRef();
+
+  handler->OnPrintStart(browser_.get());
 }
 
 CefPrintDialogLinux::~CefPrintDialogLinux() {
@@ -169,7 +217,7 @@
   // object because the PrintJobWorker which owns |context_| may already have
   // been deleted.
   CEF_REQUIRE_UIT();
-  ReleaseHandler();
+  handler_->OnPrintReset(browser_.get());
 }
 
 void CefPrintDialogLinux::UseDefaultSettings() {
@@ -181,18 +229,20 @@
   UpdateSettings(std::move(settings), false);
 }
 
+#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
+void CefPrintDialogLinux::LoadPrintSettings(
+    const printing::PrintSettings& settings) {
+  // TODO(linux): Need to read data from |settings.system_print_dialog_data()|?
+  UseDefaultSettings();
+}
+#endif
+
 void CefPrintDialogLinux::ShowDialog(
     gfx::NativeView parent_view,
     bool has_selection,
     PrintingContextLinux::PrintSettingsCallback callback) {
   CEF_REQUIRE_UIT();
 
-  SetHandler();
-  if (!handler_.get()) {
-    std::move(callback).Run(PrintingContextLinux::CANCEL);
-    return;
-  }
-
   callback_ = std::move(callback);
 
   CefRefPtr<CefPrintDialogCallbackImpl> callback_impl(
@@ -207,7 +257,7 @@
 
 void CefPrintDialogLinux::PrintDocument(
     const printing::MetafilePlayer& metafile,
-    const base::string16& document_name) {
+    const std::u16string& document_name) {
   // This runs on the print worker thread, does not block the UI thread.
   DCHECK(!CEF_CURRENTLY_ON_UIT());
 
@@ -223,8 +273,9 @@
                     base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
     success = metafile.SaveTo(&file);
     file.Close();
-    if (!success)
-      base::DeleteFile(path_to_pdf_, false);
+    if (!success) {
+      base::DeleteFile(path_to_pdf_);
+    }
   }
 
   if (!success) {
@@ -235,47 +286,21 @@
   }
 
   // No errors, continue printing.
-  CEF_POST_TASK(CEF_UIT, base::Bind(&CefPrintDialogLinux::SendDocumentToPrinter,
-                                    this, document_name));
-}
-
-void CefPrintDialogLinux::AddRefToDialog() {
-  AddRef();
+  CEF_POST_TASK(
+      CEF_UIT, base::BindOnce(&CefPrintDialogLinux::SendDocumentToPrinter, this,
+                              document_name));
 }
 
 void CefPrintDialogLinux::ReleaseDialog() {
+  context_ = nullptr;
   Release();
 }
 
-void CefPrintDialogLinux::SetHandler() {
-  if (handler_.get())
-    return;
-
-  CefRefPtr<CefApp> app = CefContentClient::Get()->application();
-  if (app.get()) {
-    CefRefPtr<CefBrowserProcessHandler> browser_handler =
-        app->GetBrowserProcessHandler();
-    if (browser_handler.get())
-      handler_ = browser_handler->GetPrintHandler();
-  }
-}
-
-void CefPrintDialogLinux::ReleaseHandler() {
-  if (handler_.get()) {
-    handler_->OnPrintReset(browser_.get());
-    handler_ = nullptr;
-  }
-}
-
 bool CefPrintDialogLinux::UpdateSettings(
     std::unique_ptr<PrintSettings> settings,
     bool get_defaults) {
   CEF_REQUIRE_UIT();
 
-  SetHandler();
-  if (!handler_.get())
-    return false;
-
   CefRefPtr<CefPrintSettingsImpl> settings_impl(
       new CefPrintSettingsImpl(std::move(settings), false));
   handler_->OnPrintSettings(browser_.get(), settings_impl.get(), get_defaults);
@@ -285,7 +310,7 @@
 }
 
 void CefPrintDialogLinux::SendDocumentToPrinter(
-    const base::string16& document_name) {
+    const std::u16string& document_name) {
   CEF_REQUIRE_UIT();
 
   if (!handler_.get()) {
@@ -308,16 +333,15 @@
   CefPrintSettingsImpl* impl =
       static_cast<CefPrintSettingsImpl*>(settings.get());
   context_->InitWithSettings(impl->TakeOwnership());
-  std::move(callback_).Run(PrintingContextLinux::OK);
+  std::move(callback_).Run(printing::mojom::ResultCode::kSuccess);
 }
 
 void CefPrintDialogLinux::OnPrintCancel() {
-  std::move(callback_).Run(PrintingContextLinux::CANCEL);
+  std::move(callback_).Run(printing::mojom::ResultCode::kCanceled);
 }
 
 void CefPrintDialogLinux::OnJobCompleted() {
-  CEF_POST_BACKGROUND_TASK(
-      base::Bind(base::IgnoreResult(&base::DeleteFile), path_to_pdf_, false));
+  CEF_POST_BACKGROUND_TASK(base::GetDeleteFileCallback(path_to_pdf_));
 
   // Printing finished. Matches AddRef() in PrintDocument();
   Release();
diff --git a/src/libcef/browser/printing/print_dialog_linux.h b/src/libcef/browser/printing/print_dialog_linux.h
index 7f01e09..5cf71ed 100644
--- a/src/libcef/browser/printing/print_dialog_linux.h
+++ b/src/libcef/browser/printing/print_dialog_linux.h
@@ -7,15 +7,15 @@
 #define LIBCEF_BROWSER_PRINTING_PRINT_DIALOG_LINUX_H_
 
 #include "include/cef_print_handler.h"
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/browser_host_base.h"
 
-#include "base/compiler_specific.h"
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner_helpers.h"
+#include "base/task/sequenced_task_runner_helpers.h"
 #include "content/public/browser/browser_thread.h"
-#include "printing/print_dialog_gtk_interface.h"
-#include "printing/printing_context_linux.h"
+#include "printing/buildflags/buildflags.h"
+#include "printing/print_dialog_linux_interface.h"
+#include "ui/linux/linux_ui.h"
 
 namespace printing {
 class MetafilePlayer;
@@ -24,33 +24,48 @@
 
 using printing::PrintingContextLinux;
 
+class CefPrintingContextLinuxDelegate
+    : public ui::PrintingContextLinuxDelegate {
+ public:
+  CefPrintingContextLinuxDelegate();
+
+  CefPrintingContextLinuxDelegate(const CefPrintingContextLinuxDelegate&) =
+      delete;
+  CefPrintingContextLinuxDelegate& operator=(
+      const CefPrintingContextLinuxDelegate&) = delete;
+
+  printing::PrintDialogLinuxInterface* CreatePrintDialog(
+      printing::PrintingContextLinux* context) override;
+  gfx::Size GetPdfPaperSize(printing::PrintingContextLinux* context) override;
+
+  void SetDefaultDelegate(ui::PrintingContextLinuxDelegate* delegate);
+
+ private:
+  ui::PrintingContextLinuxDelegate* default_delegate_ = nullptr;
+};
+
 // Needs to be freed on the UI thread to clean up its member variables.
-class CefPrintDialogLinux : public printing::PrintDialogGtkInterface,
+class CefPrintDialogLinux : public printing::PrintDialogLinuxInterface,
                             public base::RefCountedThreadSafe<
                                 CefPrintDialogLinux,
                                 content::BrowserThread::DeleteOnUIThread> {
  public:
-  // Creates and returns a print dialog.
-  static printing::PrintDialogGtkInterface* CreatePrintDialog(
-      PrintingContextLinux* context);
+  CefPrintDialogLinux(const CefPrintDialogLinux&) = delete;
+  CefPrintDialogLinux& operator=(const CefPrintDialogLinux&) = delete;
 
-  // Returns the paper size in device units.
-  static gfx::Size GetPdfPaperSize(printing::PrintingContextLinux* context);
-
-  // Notify the client when printing has started.
-  static void OnPrintStart(int render_process_id, int render_routing_id);
-
-  // PrintDialogGtkInterface implementation.
+  // PrintDialogLinuxInterface implementation.
   void UseDefaultSettings() override;
   void UpdateSettings(
       std::unique_ptr<printing::PrintSettings> settings) override;
+#if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
+  void LoadPrintSettings(const printing::PrintSettings& settings) override;
+#endif
   void ShowDialog(
       gfx::NativeView parent_view,
       bool has_selection,
       PrintingContextLinux::PrintSettingsCallback callback) override;
   void PrintDocument(const printing::MetafilePlayer& metafile,
-                     const base::string16& document_name) override;
-  void AddRefToDialog() override;
+                     const std::u16string& document_name) override;
   void ReleaseDialog() override;
 
  private:
@@ -62,18 +77,18 @@
       content::BrowserThread::UI>;
   friend class CefPrintDialogCallbackImpl;
   friend class CefPrintJobCallbackImpl;
+  friend class CefPrintingContextLinuxDelegate;
 
-  explicit CefPrintDialogLinux(PrintingContextLinux* context);
+  CefPrintDialogLinux(PrintingContextLinux* context,
+                      CefRefPtr<CefBrowserHostBase> browser,
+                      CefRefPtr<CefPrintHandler> handler);
   ~CefPrintDialogLinux() override;
 
-  void SetHandler();
-  void ReleaseHandler();
-
   bool UpdateSettings(std::unique_ptr<printing::PrintSettings> settings,
                       bool get_defaults);
 
   // Prints document named |document_name|.
-  void SendDocumentToPrinter(const base::string16& document_name);
+  void SendDocumentToPrinter(const std::u16string& document_name);
 
   // Handles print dialog response.
   void OnPrintContinue(CefRefPtr<CefPrintSettings> settings);
@@ -82,16 +97,14 @@
   // Handles print job response.
   void OnJobCompleted();
 
-  CefRefPtr<CefPrintHandler> handler_;
-
   // Printing dialog callback.
   PrintingContextLinux::PrintSettingsCallback callback_;
+
   PrintingContextLinux* context_;
-  CefRefPtr<CefBrowserHostImpl> browser_;
+  CefRefPtr<CefBrowserHostBase> browser_;
+  CefRefPtr<CefPrintHandler> handler_;
 
   base::FilePath path_to_pdf_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefPrintDialogLinux);
 };
 
 #endif  // LIBCEF_BROWSER_PRINTING_PRINT_DIALOG_LINUX_H_
diff --git a/src/libcef/browser/printing/print_util.cc b/src/libcef/browser/printing/print_util.cc
new file mode 100644
index 0000000..5c9966e
--- /dev/null
+++ b/src/libcef/browser/printing/print_util.cc
@@ -0,0 +1,147 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "libcef/browser/printing/print_util.h"
+
+#include "libcef/browser/thread_util.h"
+
+#include "base/files/file_util.h"
+#include "chrome/browser/printing/print_view_manager.h"
+#include "chrome/browser/printing/print_view_manager_common.h"
+#include "components/printing/browser/print_to_pdf/pdf_print_utils.h"
+
+namespace print_util {
+
+namespace {
+
+// Write the PDF file to disk.
+void SavePdfFile(const CefString& path,
+                 CefRefPtr<CefPdfPrintCallback> callback,
+                 scoped_refptr<base::RefCountedMemory> data) {
+  CEF_REQUIRE_BLOCKING();
+  DCHECK_GT(data->size(), 0U);
+
+  const bool ok =
+      base::WriteFile(path, reinterpret_cast<const char*>(data->data()),
+                      data->size()) == static_cast<int>(data->size());
+
+  if (callback) {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&CefPdfPrintCallback::OnPdfPrintFinished,
+                                 callback, path, ok));
+  }
+}
+
+void OnPDFCreated(const CefString& path,
+                  CefRefPtr<CefPdfPrintCallback> callback,
+                  print_to_pdf::PdfPrintResult print_result,
+                  scoped_refptr<base::RefCountedMemory> data) {
+  if (print_result != print_to_pdf::PdfPrintResult::kPrintSuccess) {
+    LOG(ERROR) << "PrintToPDF failed with error: "
+               << print_to_pdf::PdfPrintResultToString(print_result);
+    callback->OnPdfPrintFinished(CefString(), false);
+    return;
+  }
+
+  // Save the PDF file to disk and then execute the callback.
+  CEF_POST_USER_VISIBLE_TASK(
+      base::BindOnce(&SavePdfFile, path, callback, std::move(data)));
+}
+
+}  // namespace
+
+void Print(content::WebContents* web_contents, bool print_preview_disabled) {
+  // Like chrome::Print() but specifying the WebContents.
+  printing::StartPrint(web_contents, print_preview_disabled,
+                       /*has_selection=*/false);
+}
+
+// Implementation based on PageHandler::PrintToPDF.
+void PrintToPDF(content::WebContents* web_contents,
+                const CefString& path,
+                const CefPdfPrintSettings& settings,
+                CefRefPtr<CefPdfPrintCallback> callback) {
+  const bool display_header_footer = !!settings.display_header_footer;
+
+  // Defaults to no header/footer.
+  absl::optional<std::string> header_template, footer_template;
+  if (display_header_footer) {
+    if (settings.header_template.length > 0) {
+      header_template = CefString(&settings.header_template);
+    }
+    if (settings.footer_template.length > 0) {
+      footer_template = CefString(&settings.footer_template);
+    }
+  }
+
+  // Defaults to 1.0.
+  absl::optional<double> scale;
+  if (settings.scale > 0) {
+    scale = settings.scale;
+  }
+
+  // Defaults to letter size.
+  absl::optional<double> paper_width, paper_height;
+  if (settings.paper_width > 0 && settings.paper_height > 0) {
+    paper_width = settings.paper_width;
+    paper_height = settings.paper_height;
+  }
+
+  // Defaults to kDefaultMarginInInches.
+  absl::optional<double> margin_top, margin_bottom, margin_left, margin_right;
+  if (settings.margin_type == PDF_PRINT_MARGIN_NONE) {
+    margin_top = 0;
+    margin_bottom = 0;
+    margin_left = 0;
+    margin_right = 0;
+  } else if (settings.margin_type == PDF_PRINT_MARGIN_CUSTOM) {
+    if (settings.margin_top >= 0) {
+      margin_top = settings.margin_top;
+    }
+    if (settings.margin_bottom >= 0) {
+      margin_bottom = settings.margin_bottom;
+    }
+    if (settings.margin_left >= 0) {
+      margin_left = settings.margin_left;
+    }
+    if (settings.margin_right >= 0) {
+      margin_right = settings.margin_right;
+    }
+  }
+
+  absl::variant<printing::mojom::PrintPagesParamsPtr, std::string>
+      print_pages_params = print_to_pdf::GetPrintPagesParams(
+          web_contents->GetPrimaryMainFrame()->GetLastCommittedURL(),
+          !!settings.landscape, display_header_footer,
+          !!settings.print_background, scale, paper_width, paper_height,
+          margin_top, margin_bottom, margin_left, margin_right,
+          CefString(&settings.header_template),
+          CefString(&settings.footer_template), !!settings.prefer_css_page_size,
+          !!settings.generate_tagged_pdf);
+
+  if (absl::holds_alternative<std::string>(print_pages_params)) {
+    LOG(ERROR) << "PrintToPDF failed with error: "
+               << absl::get<std::string>(print_pages_params);
+    callback->OnPdfPrintFinished(CefString(), false);
+    return;
+  }
+
+  DCHECK(absl::holds_alternative<printing::mojom::PrintPagesParamsPtr>(
+      print_pages_params));
+
+  if (auto* print_manager =
+          printing::PrintViewManager::FromWebContents(web_contents)) {
+    print_manager->PrintToPdf(
+        web_contents->GetPrimaryMainFrame(), CefString(&settings.page_ranges),
+        std::move(absl::get<printing::mojom::PrintPagesParamsPtr>(
+            print_pages_params)),
+        base::BindOnce(&OnPDFCreated, path, callback));
+    return;
+  }
+
+  LOG(ERROR) << "PrintToPDF was not handled.";
+  callback->OnPdfPrintFinished(CefString(), false);
+}
+
+}  // namespace print_util
diff --git a/src/libcef/browser/printing/print_util.h b/src/libcef/browser/printing/print_util.h
new file mode 100644
index 0000000..fe12ec5
--- /dev/null
+++ b/src/libcef/browser/printing/print_util.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_PRINTING_PRINT_UTIL_H_
+#define CEF_LIBCEF_BROWSER_PRINTING_PRINT_UTIL_H_
+#pragma once
+
+#include "include/cef_browser.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace print_util {
+
+// Called from CefBrowserHostBase::Print.
+void Print(content::WebContents* web_contents, bool print_preview_disabled);
+
+// Called from CefBrowserHostBase::PrintToPDF.
+void PrintToPDF(content::WebContents* web_contents,
+                const CefString& path,
+                const CefPdfPrintSettings& settings,
+                CefRefPtr<CefPdfPrintCallback> callback);
+
+}  // namespace print_util
+
+#endif  // CEF_LIBCEF_BROWSER_PRINTING_PRINT_UTIL_H_
diff --git a/src/libcef/browser/printing/print_view_manager.cc b/src/libcef/browser/printing/print_view_manager.cc
deleted file mode 100644
index 396d1b4..0000000
--- a/src/libcef/browser/printing/print_view_manager.cc
+++ /dev/null
@@ -1,419 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/printing/print_view_manager.h"
-
-#include "include/internal/cef_types_wrappers.h"
-#include "libcef/browser/browser_info.h"
-#include "libcef/browser/browser_info_manager.h"
-#include "libcef/browser/download_manager_delegate.h"
-#include "libcef/browser/extensions/extension_web_contents_observer.h"
-
-#include <map>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/task/post_task.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/printing/print_job_manager.h"
-#include "chrome/browser/printing/print_preview_dialog_controller.h"
-#include "chrome/browser/printing/print_preview_message_handler.h"
-#include "chrome/browser/printing/print_view_manager.h"
-#include "chrome/browser/printing/printer_query.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
-#include "components/printing/common/print.mojom.h"
-#include "components/printing/common/print_messages.h"
-#include "content/browser/download/download_manager_impl.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/download_manager.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "mojo/public/cpp/bindings/associated_remote.h"
-#include "printing/metafile_skia.h"
-#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
-
-#include "libcef/browser/thread_util.h"
-
-using content::BrowserThread;
-
-namespace printing {
-
-namespace {
-
-const int PREVIEW_UIID = 12345678;
-
-// Convert CefPdfPrintSettings into base::DictionaryValue.
-void FillInDictionaryFromPdfPrintSettings(
-    const CefPdfPrintSettings& pdf_settings,
-    int request_id,
-    base::DictionaryValue& print_settings) {
-  // Fixed settings.
-  print_settings.SetIntKey(kSettingPrinterType, kPdfPrinter);
-  print_settings.SetInteger(kSettingColor, GRAY);
-  print_settings.SetInteger(kSettingDuplexMode, SIMPLEX);
-  print_settings.SetInteger(kSettingCopies, 1);
-  print_settings.SetBoolean(kSettingCollate, false);
-  print_settings.SetString(kSettingDeviceName, "");
-  print_settings.SetBoolean(kSettingRasterizePdf, false);
-  print_settings.SetBoolean(kSettingPreviewModifiable, false);
-  print_settings.SetInteger(kSettingDpiHorizontal, 0);
-  print_settings.SetInteger(kSettingDpiVertical, 0);
-  print_settings.SetInteger(kSettingPagesPerSheet, 1);
-
-  // User defined settings.
-  print_settings.SetBoolean(kSettingLandscape, !!pdf_settings.landscape);
-  print_settings.SetBoolean(kSettingShouldPrintSelectionOnly,
-                            !!pdf_settings.selection_only);
-  print_settings.SetBoolean(kSettingShouldPrintBackgrounds,
-                            !!pdf_settings.backgrounds_enabled);
-  print_settings.SetBoolean(kSettingHeaderFooterEnabled,
-                            !!pdf_settings.header_footer_enabled);
-  print_settings.SetInteger(kSettingScaleFactor, pdf_settings.scale_factor > 0
-                                                     ? pdf_settings.scale_factor
-                                                     : 100);
-
-  if (pdf_settings.header_footer_enabled) {
-    print_settings.SetString(
-        kSettingHeaderFooterTitle,
-        CefString(&pdf_settings.header_footer_title).ToString16());
-    print_settings.SetString(
-        kSettingHeaderFooterURL,
-        CefString(&pdf_settings.header_footer_url).ToString16());
-  }
-
-  if (pdf_settings.page_width > 0 && pdf_settings.page_height > 0) {
-    std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
-    dict->SetInteger(kSettingMediaSizeWidthMicrons, pdf_settings.page_width);
-    dict->SetInteger(kSettingMediaSizeHeightMicrons, pdf_settings.page_height);
-    print_settings.Set(kSettingMediaSize, std::move(dict));
-  }
-
-  int margin_type = DEFAULT_MARGINS;
-  switch (pdf_settings.margin_type) {
-    case PDF_PRINT_MARGIN_NONE:
-      margin_type = NO_MARGINS;
-      break;
-    case PDF_PRINT_MARGIN_MINIMUM:
-      margin_type = PRINTABLE_AREA_MARGINS;
-      break;
-    case PDF_PRINT_MARGIN_CUSTOM:
-      margin_type = CUSTOM_MARGINS;
-      break;
-    default:
-      break;
-  }
-
-  print_settings.SetInteger(kSettingMarginsType, margin_type);
-  if (margin_type == CUSTOM_MARGINS) {
-    std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
-    dict->SetInteger(kSettingMarginTop, pdf_settings.margin_top);
-    dict->SetInteger(kSettingMarginRight, pdf_settings.margin_right);
-    dict->SetInteger(kSettingMarginBottom, pdf_settings.margin_bottom);
-    dict->SetInteger(kSettingMarginLeft, pdf_settings.margin_left);
-    print_settings.Set(kSettingMarginsCustom, std::move(dict));
-  }
-
-  // Service settings.
-  print_settings.SetInteger(kPreviewUIID, PREVIEW_UIID);
-  print_settings.SetInteger(kPreviewRequestID, request_id);
-  print_settings.SetBoolean(kIsFirstRequest, request_id != 0);
-}
-
-void StopWorker(int document_cookie) {
-  if (document_cookie <= 0)
-    return;
-  scoped_refptr<PrintQueriesQueue> queue =
-      g_browser_process->print_job_manager()->queue();
-  std::unique_ptr<PrinterQuery> printer_query =
-      queue->PopPrinterQuery(document_cookie);
-  if (printer_query.get()) {
-    base::PostTask(
-        FROM_HERE, {BrowserThread::IO},
-        base::BindOnce(&PrinterQuery::StopWorker, std::move(printer_query)));
-  }
-}
-
-// Write the PDF file to disk.
-void SavePdfFile(scoped_refptr<base::RefCountedSharedMemoryMapping> data,
-                 const base::FilePath& path,
-                 const CefPrintViewManager::PdfPrintCallback& callback) {
-  CEF_REQUIRE_BLOCKING();
-  DCHECK_GT(data->size(), 0U);
-
-  MetafileSkia metafile;
-  metafile.InitFromData(*data);
-
-  base::File file(path,
-                  base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
-  bool ok = file.IsValid() && metafile.SaveTo(&file);
-
-  if (!callback.is_null()) {
-    base::PostTask(FROM_HERE, {BrowserThread::UI}, base::Bind(callback, ok));
-  }
-}
-
-}  // namespace
-
-struct CefPrintViewManager::PdfPrintState {
-  content::RenderFrameHost* printing_rfh_ = nullptr;
-  base::FilePath output_path_;
-  base::DictionaryValue settings_;
-  PdfPrintCallback callback_;
-};
-
-CefPrintViewManager::CefPrintViewManager(content::WebContents* web_contents)
-    : WebContentsObserver(web_contents) {
-  PrintViewManager::CreateForWebContents(web_contents);
-  PrintPreviewMessageHandler::CreateForWebContents(web_contents);
-}
-
-CefPrintViewManager::~CefPrintViewManager() {
-  TerminatePdfPrintJob();
-}
-
-bool CefPrintViewManager::PrintToPDF(content::RenderFrameHost* rfh,
-                                     const base::FilePath& path,
-                                     const CefPdfPrintSettings& settings,
-                                     const PdfPrintCallback& callback) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
-  // Don't start print again while printing is currently in progress.
-  if (pdf_print_state_)
-    return false;
-
-  // Don't print interstitials or crashed tabs.
-  if (!web_contents() || web_contents()->ShowingInterstitialPage() ||
-      web_contents()->IsCrashed()) {
-    return false;
-  }
-
-  pdf_print_state_.reset(new PdfPrintState);
-  pdf_print_state_->printing_rfh_ = rfh;
-  pdf_print_state_->output_path_ = path;
-  pdf_print_state_->callback_ = callback;
-
-  FillInDictionaryFromPdfPrintSettings(settings, ++next_pdf_request_id_,
-                                       pdf_print_state_->settings_);
-
-  mojo::AssociatedRemote<printing::mojom::PrintRenderFrame>
-      print_render_frame_remote;
-  rfh->GetRemoteAssociatedInterfaces()->GetInterface(
-      &print_render_frame_remote);
-  print_render_frame_remote->InitiatePrintPreview({},
-                                                  !!settings.selection_only);
-
-  return true;
-}
-
-bool CefPrintViewManager::PrintPreviewNow(content::RenderFrameHost* rfh,
-                                          bool has_selection) {
-  return PrintViewManager::FromWebContents(web_contents())
-      ->PrintPreviewNow(rfh, has_selection);
-}
-
-void CefPrintViewManager::RenderFrameDeleted(
-    content::RenderFrameHost* render_frame_host) {
-  if (pdf_print_state_ &&
-      render_frame_host == pdf_print_state_->printing_rfh_) {
-    TerminatePdfPrintJob();
-  }
-}
-
-void CefPrintViewManager::NavigationStopped() {
-  TerminatePdfPrintJob();
-}
-
-void CefPrintViewManager::RenderProcessGone(base::TerminationStatus status) {
-  TerminatePdfPrintJob();
-}
-
-bool CefPrintViewManager::OnMessageReceived(
-    const IPC::Message& message,
-    content::RenderFrameHost* render_frame_host) {
-  bool handled = true;
-  if (!pdf_print_state_) {
-    IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(CefPrintViewManager, message,
-                                     render_frame_host)
-      IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview,
-                          OnRequestPrintPreview)
-      IPC_MESSAGE_HANDLER(PrintHostMsg_ShowScriptedPrintPreview,
-                          OnShowScriptedPrintPreview)
-      IPC_MESSAGE_UNHANDLED(handled = false)
-    IPC_END_MESSAGE_MAP()
-    return false;
-  }
-
-  IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(CefPrintViewManager, message,
-                                   render_frame_host)
-    IPC_MESSAGE_HANDLER(PrintHostMsg_DidShowPrintDialog,
-                        OnDidShowPrintDialog_PrintToPdf)
-    IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview,
-                        OnRequestPrintPreview_PrintToPdf)
-    IPC_MESSAGE_HANDLER(PrintHostMsg_MetafileReadyForPrinting,
-                        OnMetafileReadyForPrinting_PrintToPdf)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-
-  return handled;
-}
-void CefPrintViewManager::OnRequestPrintPreview(
-    content::RenderFrameHost* rfh,
-    const PrintHostMsg_RequestPrintPreview_Params&) {
-  InitializePrintPreview(rfh->GetFrameTreeNodeId());
-}
-
-void CefPrintViewManager::OnShowScriptedPrintPreview(
-    content::RenderFrameHost* rfh,
-    bool source_is_modifiable) {
-  InitializePrintPreview(rfh->GetFrameTreeNodeId());
-}
-
-void CefPrintViewManager::OnDidShowPrintDialog_PrintToPdf(
-    content::RenderFrameHost* rfh) {}
-
-void CefPrintViewManager::OnRequestPrintPreview_PrintToPdf(
-    content::RenderFrameHost* rfh,
-    const PrintHostMsg_RequestPrintPreview_Params&) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (!pdf_print_state_)
-    return;
-
-  DCHECK_EQ(pdf_print_state_->printing_rfh_, rfh);
-
-  mojo::AssociatedRemote<printing::mojom::PrintRenderFrame>
-      print_render_frame_remote;
-  rfh->GetRemoteAssociatedInterfaces()->GetInterface(
-      &print_render_frame_remote);
-  print_render_frame_remote->PrintPreview(pdf_print_state_->settings_.Clone());
-}
-
-void CefPrintViewManager::OnMetafileReadyForPrinting_PrintToPdf(
-    content::RenderFrameHost* rfh,
-    const PrintHostMsg_DidPreviewDocument_Params& params,
-    const PrintHostMsg_PreviewIds& ids) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  StopWorker(params.document_cookie);
-
-  if (!pdf_print_state_)
-    return;
-
-  DCHECK_EQ(pdf_print_state_->printing_rfh_, rfh);
-
-  mojo::AssociatedRemote<printing::mojom::PrintRenderFrame>
-      print_render_frame_remote;
-  rfh->GetRemoteAssociatedInterfaces()->GetInterface(
-      &print_render_frame_remote);
-  print_render_frame_remote->OnPrintPreviewDialogClosed();
-
-  auto shared_buf = base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(
-      params.content.metafile_data_region);
-  if (!shared_buf) {
-    TerminatePdfPrintJob();
-    return;
-  }
-
-  const base::FilePath output_path = pdf_print_state_->output_path_;
-  const PdfPrintCallback print_callback = pdf_print_state_->callback_;
-
-  // Reset state information.
-  pdf_print_state_.reset();
-
-  // Save the PDF file to disk and then execute the callback.
-  CEF_POST_USER_VISIBLE_TASK(
-      base::Bind(&SavePdfFile, shared_buf, output_path, print_callback));
-}
-
-void CefPrintViewManager::TerminatePdfPrintJob() {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (!pdf_print_state_)
-    return;
-
-  if (!pdf_print_state_->callback_.is_null()) {
-    // Execute the callback.
-    base::PostTask(FROM_HERE, {BrowserThread::UI},
-                   base::Bind(pdf_print_state_->callback_, false));
-  }
-
-  // Reset state information.
-  pdf_print_state_.reset();
-}
-
-void CefPrintViewManager::InitializePrintPreview(int frame_tree_node_id) {
-  PrintPreviewDialogController* dialog_controller =
-      PrintPreviewDialogController::GetInstance();
-  if (!dialog_controller)
-    return;
-
-  dialog_controller->PrintPreview(web_contents());
-
-  content::WebContents* preview_contents =
-      dialog_controller->GetPrintPreviewForContents(web_contents());
-
-  extensions::CefExtensionWebContentsObserver::CreateForWebContents(
-      preview_contents);
-
-  PrintPreviewHelper::CreateForWebContents(preview_contents);
-  PrintPreviewHelper::FromWebContents(preview_contents)
-      ->Initialize(frame_tree_node_id);
-}
-
-WEB_CONTENTS_USER_DATA_KEY_IMPL(CefPrintViewManager)
-
-// CefPrintViewManager::PrintPreviewHelper
-
-CefPrintViewManager::PrintPreviewHelper::PrintPreviewHelper(
-    content::WebContents* contents)
-    : content::WebContentsObserver(contents) {}
-
-void CefPrintViewManager::PrintPreviewHelper::Initialize(
-    int parent_frame_tree_node_id) {
-  DCHECK_EQ(parent_frame_tree_node_id_,
-            content::RenderFrameHost::kNoFrameTreeNodeId);
-  DCHECK_NE(parent_frame_tree_node_id,
-            content::RenderFrameHost::kNoFrameTreeNodeId);
-  parent_frame_tree_node_id_ = parent_frame_tree_node_id;
-
-  auto context = web_contents()->GetBrowserContext();
-  auto manager = content::BrowserContext::GetDownloadManager(context);
-
-  if (!context->GetDownloadManagerDelegate()) {
-    manager->SetDelegate(new CefDownloadManagerDelegate(manager));
-  }
-
-  auto browser_info =
-      CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameTreeNode(
-          parent_frame_tree_node_id_);
-  DCHECK(browser_info);
-  if (!browser_info)
-    return;
-
-  // Associate guest state information with the owner browser.
-  browser_info->MaybeCreateFrame(web_contents()->GetMainFrame(),
-                                 true /* is_guest_view */);
-}
-
-void CefPrintViewManager::PrintPreviewHelper::WebContentsDestroyed() {
-  auto browser_info =
-      CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameTreeNode(
-          parent_frame_tree_node_id_);
-  DCHECK(browser_info);
-  if (!browser_info)
-    return;
-
-  // Disassociate guest state information with the owner browser.
-  browser_info->RemoveFrame(web_contents()->GetMainFrame());
-}
-
-WEB_CONTENTS_USER_DATA_KEY_IMPL(CefPrintViewManager::PrintPreviewHelper)
-
-}  // namespace printing
diff --git a/src/libcef/browser/printing/print_view_manager.h b/src/libcef/browser/printing/print_view_manager.h
deleted file mode 100644
index e341103..0000000
--- a/src/libcef/browser/printing/print_view_manager.h
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_BROWSER_PRINTING_PRINT_VIEW_MANAGER_H_
-#define CEF_LIBCEF_BROWSER_PRINTING_PRINT_VIEW_MANAGER_H_
-
-#include "include/internal/cef_types_wrappers.h"
-
-#include "base/macros.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "content/public/browser/web_contents_user_data.h"
-
-namespace content {
-class RenderFrameHost;
-class RenderProcessHost;
-class WebContentsObserver;
-}  // namespace content
-
-class CefBrowserInfo;
-
-struct PrintHostMsg_DidPreviewDocument_Params;
-struct PrintHostMsg_PreviewIds;
-struct PrintHostMsg_RequestPrintPreview_Params;
-
-namespace printing {
-
-// Manages the print commands for a WebContents.
-class CefPrintViewManager
-    : public content::WebContentsObserver,
-      public content::WebContentsUserData<CefPrintViewManager> {
- public:
-  ~CefPrintViewManager() override;
-
-  // Callback executed on PDF printing completion.
-  typedef base::Callback<void(bool /*ok*/)> PdfPrintCallback;
-
-  // Print the current document to a PDF file. Execute |callback| on completion.
-  bool PrintToPDF(content::RenderFrameHost* rfh,
-                  const base::FilePath& path,
-                  const CefPdfPrintSettings& settings,
-                  const PdfPrintCallback& callback);
-
-  // Call to Chrome's PrintViewManager.
-  bool PrintPreviewNow(content::RenderFrameHost* rfh, bool has_selection);
-
-  // content::WebContentsObserver implementation.
-  void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
-  void NavigationStopped() override;
-  void RenderProcessGone(base::TerminationStatus status) override;
-  bool OnMessageReceived(const IPC::Message& message,
-                         content::RenderFrameHost* render_frame_host) override;
-
-  // Used to track the lifespan of the print preview WebContents.
-  class PrintPreviewHelper
-      : public content::WebContentsObserver,
-        public content::WebContentsUserData<PrintPreviewHelper> {
-   public:
-    void Initialize(int parent_frame_tree_node_id);
-    void WebContentsDestroyed() override;
-
-   private:
-    friend class content::WebContentsUserData<PrintPreviewHelper>;
-
-    explicit PrintPreviewHelper(content::WebContents* contents);
-
-    int parent_frame_tree_node_id_ = -1;
-
-    WEB_CONTENTS_USER_DATA_KEY_DECL();
-    DISALLOW_COPY_AND_ASSIGN(PrintPreviewHelper);
-  };
-
- private:
-  explicit CefPrintViewManager(content::WebContents* web_contents);
-  friend class content::WebContentsUserData<CefPrintViewManager>;
-
-  // IPC Message handlers.
-  void OnRequestPrintPreview(content::RenderFrameHost* rfh,
-                             const PrintHostMsg_RequestPrintPreview_Params&);
-  void OnShowScriptedPrintPreview(content::RenderFrameHost* rfh,
-                                  bool source_is_modifiable);
-  void OnRequestPrintPreview_PrintToPdf(
-      content::RenderFrameHost* rfh,
-      const PrintHostMsg_RequestPrintPreview_Params&);
-  void OnDidShowPrintDialog_PrintToPdf(content::RenderFrameHost* rfh);
-  void OnMetafileReadyForPrinting_PrintToPdf(
-      content::RenderFrameHost* rfh,
-      const PrintHostMsg_DidPreviewDocument_Params& params,
-      const PrintHostMsg_PreviewIds& ids);
-  void InitializePrintPreview(int frame_tree_node_id);
-  void TerminatePdfPrintJob();
-
-  // Used for printing to PDF. Only accessed on the browser process UI thread.
-  int next_pdf_request_id_ = content::RenderFrameHost::kNoFrameTreeNodeId;
-  struct PdfPrintState;
-  std::unique_ptr<PdfPrintState> pdf_print_state_;
-  WEB_CONTENTS_USER_DATA_KEY_DECL();
-  DISALLOW_COPY_AND_ASSIGN(CefPrintViewManager);
-};
-
-}  // namespace printing
-
-#endif  // CEF_LIBCEF_BROWSER_PRINTING_PRINT_VIEW_MANAGER_H_
\ No newline at end of file
diff --git a/src/libcef/browser/printing/printing_message_filter.cc b/src/libcef/browser/printing/printing_message_filter.cc
deleted file mode 100644
index cfe0e2d..0000000
--- a/src/libcef/browser/printing/printing_message_filter.cc
+++ /dev/null
@@ -1,264 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/browser/printing/printing_message_filter.h"
-
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "base/task/post_task.h"
-#include "build/build_config.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/printing/print_job_manager.h"
-#include "chrome/browser/printing/printer_query.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/pref_names.h"
-#include "components/keyed_service/content/browser_context_keyed_service_shutdown_notifier_factory.h"
-#include "components/printing/browser/print_manager_utils.h"
-#include "components/printing/common/print_messages.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/child_process_host.h"
-
-#if defined(OS_LINUX)
-#include "libcef/browser/printing/print_dialog_linux.h"
-#endif
-
-using content::BrowserThread;
-
-namespace printing {
-
-namespace {
-
-class CefPrintingMessageFilterShutdownNotifierFactory
-    : public BrowserContextKeyedServiceShutdownNotifierFactory {
- public:
-  static CefPrintingMessageFilterShutdownNotifierFactory* GetInstance();
-
- private:
-  friend struct base::LazyInstanceTraitsBase<
-      CefPrintingMessageFilterShutdownNotifierFactory>;
-
-  CefPrintingMessageFilterShutdownNotifierFactory()
-      : BrowserContextKeyedServiceShutdownNotifierFactory(
-            "CefPrintingMessageFilter") {}
-
-  ~CefPrintingMessageFilterShutdownNotifierFactory() override {}
-
-  DISALLOW_COPY_AND_ASSIGN(CefPrintingMessageFilterShutdownNotifierFactory);
-};
-
-base::LazyInstance<CefPrintingMessageFilterShutdownNotifierFactory>::Leaky
-    g_printing_message_filter_shutdown_notifier_factory =
-        LAZY_INSTANCE_INITIALIZER;
-
-// static
-CefPrintingMessageFilterShutdownNotifierFactory*
-CefPrintingMessageFilterShutdownNotifierFactory::GetInstance() {
-  return g_printing_message_filter_shutdown_notifier_factory.Pointer();
-}
-
-}  // namespace
-
-CefPrintingMessageFilter::CefPrintingMessageFilter(int render_process_id,
-                                                   Profile* profile)
-    : content::BrowserMessageFilter(PrintMsgStart),
-      render_process_id_(render_process_id),
-      queue_(g_browser_process->print_job_manager()->queue()) {
-  DCHECK(queue_.get());
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  printing_shutdown_notifier_ =
-      CefPrintingMessageFilterShutdownNotifierFactory::GetInstance()
-          ->Get(profile)
-          ->Subscribe(base::Bind(&CefPrintingMessageFilter::ShutdownOnUIThread,
-                                 base::Unretained(this)));
-  is_printing_enabled_.Init(prefs::kPrintingEnabled, profile->GetPrefs());
-  is_printing_enabled_.MoveToSequence(
-      base::CreateSingleThreadTaskRunner({BrowserThread::IO}));
-}
-
-void CefPrintingMessageFilter::EnsureShutdownNotifierFactoryBuilt() {
-  CefPrintingMessageFilterShutdownNotifierFactory::GetInstance();
-}
-
-CefPrintingMessageFilter::~CefPrintingMessageFilter() {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
-
-void CefPrintingMessageFilter::ShutdownOnUIThread() {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  is_printing_enabled_.Destroy();
-  printing_shutdown_notifier_.reset();
-}
-
-void CefPrintingMessageFilter::OnDestruct() const {
-  BrowserThread::DeleteOnUIThread::Destruct(this);
-}
-
-bool CefPrintingMessageFilter::OnMessageReceived(const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(CefPrintingMessageFilter, message)
-    IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings,
-                                    OnGetDefaultPrintSettings)
-    IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrint, OnScriptedPrint)
-    IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_UpdatePrintSettings,
-                                    OnUpdatePrintSettings)
-    IPC_MESSAGE_HANDLER(PrintHostMsg_CheckForCancel, OnCheckForCancel)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  return handled;
-}
-
-void CefPrintingMessageFilter::OnGetDefaultPrintSettings(
-    IPC::Message* reply_msg) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-#if defined(OS_LINUX)
-  // Send notification to the client.
-  CefPrintDialogLinux::OnPrintStart(render_process_id_,
-                                    reply_msg->routing_id());
-#endif
-
-  std::unique_ptr<PrinterQuery> printer_query;
-  if (!is_printing_enabled_.GetValue()) {
-    // Reply with NULL query.
-    OnGetDefaultPrintSettingsReply(std::move(printer_query), reply_msg);
-    return;
-  }
-  printer_query = queue_->PopPrinterQuery(0);
-  if (!printer_query.get()) {
-    printer_query =
-        queue_->CreatePrinterQuery(render_process_id_, reply_msg->routing_id());
-  }
-
-  // Loads default settings. This is asynchronous, only the IPC message sender
-  // will hang until the settings are retrieved.
-  auto* printer_query_ptr = printer_query.get();
-  printer_query_ptr->GetSettings(
-      PrinterQuery::GetSettingsAskParam::DEFAULTS, 0, false, DEFAULT_MARGINS,
-      false, false,
-      base::BindOnce(&CefPrintingMessageFilter::OnGetDefaultPrintSettingsReply,
-                     this, std::move(printer_query), reply_msg));
-}
-
-void CefPrintingMessageFilter::OnGetDefaultPrintSettingsReply(
-    std::unique_ptr<PrinterQuery> printer_query,
-    IPC::Message* reply_msg) {
-  PrintMsg_Print_Params params;
-  if (!printer_query.get() ||
-      printer_query->last_status() != PrintingContext::OK) {
-    params.Reset();
-  } else {
-    RenderParamsFromPrintSettings(printer_query->settings(), &params);
-    params.document_cookie = printer_query->cookie();
-  }
-  PrintHostMsg_GetDefaultPrintSettings::WriteReplyParams(reply_msg, params);
-  Send(reply_msg);
-  // If printing was enabled.
-  if (printer_query.get()) {
-    // If user hasn't cancelled.
-    if (printer_query->cookie() && printer_query->settings().dpi()) {
-      queue_->QueuePrinterQuery(std::move(printer_query));
-    } else {
-      printer_query->StopWorker();
-    }
-  }
-}
-
-void CefPrintingMessageFilter::OnScriptedPrint(
-    const PrintHostMsg_ScriptedPrint_Params& params,
-    IPC::Message* reply_msg) {
-  std::unique_ptr<PrinterQuery> printer_query =
-      queue_->PopPrinterQuery(params.cookie);
-  if (!printer_query.get()) {
-    printer_query =
-        queue_->CreatePrinterQuery(render_process_id_, reply_msg->routing_id());
-  }
-  printer_query->GetSettings(
-      PrinterQuery::GetSettingsAskParam::ASK_USER, params.expected_pages_count,
-      params.has_selection, params.margin_type, params.is_scripted,
-      params.is_modifiable,
-      base::BindOnce(&CefPrintingMessageFilter::OnScriptedPrintReply, this,
-                     std::move(printer_query), reply_msg));
-}
-
-void CefPrintingMessageFilter::OnScriptedPrintReply(
-    std::unique_ptr<PrinterQuery> printer_query,
-    IPC::Message* reply_msg) {
-  PrintMsg_PrintPages_Params params;
-  if (printer_query->last_status() != PrintingContext::OK ||
-      !printer_query->settings().dpi()) {
-    params.Reset();
-  } else {
-    RenderParamsFromPrintSettings(printer_query->settings(), &params.params);
-    params.params.document_cookie = printer_query->cookie();
-    params.pages = PageRange::GetPages(printer_query->settings().ranges());
-  }
-  PrintHostMsg_ScriptedPrint::WriteReplyParams(reply_msg, params);
-  Send(reply_msg);
-  if (!params.params.dpi.IsEmpty() && params.params.document_cookie) {
-    queue_->QueuePrinterQuery(std::move(printer_query));
-  } else {
-    printer_query->StopWorker();
-  }
-}
-
-void CefPrintingMessageFilter::OnUpdatePrintSettings(int document_cookie,
-                                                     base::Value job_settings,
-                                                     IPC::Message* reply_msg) {
-  std::unique_ptr<PrinterQuery> printer_query;
-  if (!is_printing_enabled_.GetValue()) {
-    // Reply with NULL query.
-    OnUpdatePrintSettingsReply(std::move(printer_query), reply_msg);
-    return;
-  }
-  printer_query = queue_->PopPrinterQuery(document_cookie);
-  if (!printer_query.get()) {
-    printer_query = queue_->CreatePrinterQuery(
-        content::ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE);
-  }
-  printer_query->SetSettings(
-      std::move(job_settings),
-      base::BindOnce(&CefPrintingMessageFilter::OnUpdatePrintSettingsReply,
-                     this, std::move(printer_query), reply_msg));
-}
-
-void CefPrintingMessageFilter::OnUpdatePrintSettingsReply(
-    std::unique_ptr<PrinterQuery> printer_query,
-    IPC::Message* reply_msg) {
-  PrintMsg_PrintPages_Params params;
-  if (!printer_query.get() ||
-      printer_query->last_status() != PrintingContext::OK) {
-    params.Reset();
-  } else {
-    RenderParamsFromPrintSettings(printer_query->settings(), &params.params);
-    params.params.document_cookie = printer_query->cookie();
-    params.pages = PageRange::GetPages(printer_query->settings().ranges());
-  }
-  bool canceled = printer_query.get() &&
-                  (printer_query->last_status() == PrintingContext::CANCEL);
-  PrintHostMsg_UpdatePrintSettings::WriteReplyParams(reply_msg, params,
-                                                     canceled);
-  Send(reply_msg);
-  // If user hasn't cancelled.
-  if (printer_query.get()) {
-    if (printer_query->cookie() && printer_query->settings().dpi()) {
-      queue_->QueuePrinterQuery(std::move(printer_query));
-    } else {
-      printer_query->StopWorker();
-    }
-  }
-}
-
-void CefPrintingMessageFilter::OnCheckForCancel(
-    const PrintHostMsg_PreviewIds& ids,
-    bool* cancel) {
-  *cancel = false;
-}
-
-}  // namespace printing
diff --git a/src/libcef/browser/printing/printing_message_filter.h b/src/libcef/browser/printing/printing_message_filter.h
deleted file mode 100644
index d6d889b..0000000
--- a/src/libcef/browser/printing/printing_message_filter.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_BROWSER_PRINTING_PRINTING_MESSAGE_FILTER_H_
-#define CEF_LIBCEF_BROWSER_PRINTING_PRINTING_MESSAGE_FILTER_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-
-#include "base/macros.h"
-#include "base/values.h"
-#include "build/build_config.h"
-#include "components/keyed_service/core/keyed_service_shutdown_notifier.h"
-#include "components/prefs/pref_member.h"
-#include "content/public/browser/browser_message_filter.h"
-#include "printing/buildflags/buildflags.h"
-
-struct PrintHostMsg_PreviewIds;
-struct PrintHostMsg_ScriptedPrint_Params;
-class Profile;
-
-namespace printing {
-
-class PrintQueriesQueue;
-class PrinterQuery;
-
-// This class filters out incoming printing related IPC messages for the
-// renderer process on the IPC thread.
-class CefPrintingMessageFilter : public content::BrowserMessageFilter {
- public:
-  CefPrintingMessageFilter(int render_process_id, Profile* profile);
-
-  static void EnsureShutdownNotifierFactoryBuilt();
-
-  // content::BrowserMessageFilter methods.
-  void OnDestruct() const override;
-  bool OnMessageReceived(const IPC::Message& message) override;
-
- private:
-  friend class base::DeleteHelper<CefPrintingMessageFilter>;
-  friend class content::BrowserThread;
-
-  ~CefPrintingMessageFilter() override;
-
-  void ShutdownOnUIThread();
-
-  // Get the default print setting.
-  void OnGetDefaultPrintSettings(IPC::Message* reply_msg);
-  void OnGetDefaultPrintSettingsReply(
-      std::unique_ptr<PrinterQuery> printer_query,
-      IPC::Message* reply_msg);
-
-  // The renderer host have to show to the user the print dialog and returns
-  // the selected print settings. The task is handled by the print worker
-  // thread and the UI thread. The reply occurs on the IO thread.
-  void OnScriptedPrint(const PrintHostMsg_ScriptedPrint_Params& params,
-                       IPC::Message* reply_msg);
-  void OnScriptedPrintReply(std::unique_ptr<PrinterQuery> printer_query,
-                            IPC::Message* reply_msg);
-
-  // Modify the current print settings based on |job_settings|. The task is
-  // handled by the print worker thread and the UI thread. The reply occurs on
-  // the IO thread.
-  void OnUpdatePrintSettings(int document_cookie,
-                             base::Value job_settings,
-                             IPC::Message* reply_msg);
-  void OnUpdatePrintSettingsReply(std::unique_ptr<PrinterQuery> printer_query,
-                                  IPC::Message* reply_msg);
-
-  // Check to see if print preview has been cancelled.
-  void OnCheckForCancel(const PrintHostMsg_PreviewIds& ids, bool* cancel);
-
-  std::unique_ptr<KeyedServiceShutdownNotifier::Subscription>
-      printing_shutdown_notifier_;
-
-  BooleanPrefMember is_printing_enabled_;
-
-  const int render_process_id_;
-
-  scoped_refptr<PrintQueriesQueue> queue_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefPrintingMessageFilter);
-};
-
-}  // namespace printing
-
-#endif  // CEF_LIBCEF_BROWSER_PRINTING_PRINTING_MESSAGE_FILTER_H_
diff --git a/src/libcef/browser/process_util_impl.cc b/src/libcef/browser/process_util_impl.cc
index fb42a95..6e09c00 100644
--- a/src/libcef/browser/process_util_impl.cc
+++ b/src/libcef/browser/process_util_impl.cc
@@ -6,17 +6,18 @@
 #include "libcef/common/command_line_impl.h"
 
 #include "base/logging.h"
+#include "base/notreached.h"
 #include "base/process/launch.h"
 #include "content/public/browser/child_process_launcher_utils.h"
 
 bool CefLaunchProcess(CefRefPtr<CefCommandLine> command_line) {
   if (!command_line.get()) {
-    NOTREACHED() << "invalid parameter";
+    DCHECK(false) << "invalid parameter";
     return false;
   }
 
   if (!content::CurrentlyOnProcessLauncherTaskRunner()) {
-    NOTREACHED() << "called on invalid thread";
+    DCHECK(false) << "called on invalid thread";
     return false;
   }
 
diff --git a/src/libcef/browser/request_context_handler_map.cc b/src/libcef/browser/request_context_handler_map.cc
index 9109898..eca2290 100644
--- a/src/libcef/browser/request_context_handler_map.cc
+++ b/src/libcef/browser/request_context_handler_map.cc
@@ -4,64 +4,46 @@
 
 #include "libcef/browser/request_context_handler_map.h"
 
+#include "libcef/common/frame_util.h"
+
 CefRequestContextHandlerMap::CefRequestContextHandlerMap() = default;
 CefRequestContextHandlerMap::~CefRequestContextHandlerMap() = default;
 
 void CefRequestContextHandlerMap::AddHandler(
-    int render_process_id,
-    int render_frame_id,
-    int frame_tree_node_id,
+    const content::GlobalRenderFrameHostId& global_id,
     CefRefPtr<CefRequestContextHandler> handler) {
-  DCHECK_GE(render_process_id, 0);
-  DCHECK_GE(render_frame_id, 0);
-  DCHECK_GE(frame_tree_node_id, 0);
+  DCHECK(frame_util::IsValidGlobalId(global_id));
   DCHECK(handler);
 
-  render_id_handler_map_.insert(std::make_pair(
-      std::make_pair(render_process_id, render_frame_id), handler));
-  node_id_handler_map_.insert(std::make_pair(frame_tree_node_id, handler));
+  render_id_handler_map_.insert(std::make_pair(global_id, handler));
 }
 
-void CefRequestContextHandlerMap::RemoveHandler(int render_process_id,
-                                                int render_frame_id,
-                                                int frame_tree_node_id) {
-  DCHECK_GE(render_process_id, 0);
-  DCHECK_GE(render_frame_id, 0);
-  DCHECK_GE(frame_tree_node_id, 0);
+void CefRequestContextHandlerMap::RemoveHandler(
+    const content::GlobalRenderFrameHostId& global_id) {
+  DCHECK(frame_util::IsValidGlobalId(global_id));
 
-  auto it1 = render_id_handler_map_.find(
-      std::make_pair(render_process_id, render_frame_id));
-  if (it1 != render_id_handler_map_.end())
+  auto it1 = render_id_handler_map_.find(global_id);
+  if (it1 != render_id_handler_map_.end()) {
     render_id_handler_map_.erase(it1);
-
-  auto it2 = node_id_handler_map_.find(frame_tree_node_id);
-  if (it2 != node_id_handler_map_.end())
-    node_id_handler_map_.erase(it2);
+  }
 }
 
 CefRefPtr<CefRequestContextHandler> CefRequestContextHandlerMap::GetHandler(
-    int render_process_id,
-    int render_frame_id,
-    int frame_tree_node_id,
+    const content::GlobalRenderFrameHostId& global_id,
     bool require_frame_match) const {
-  if (render_process_id >= 0 && render_frame_id >= 0) {
-    const auto it1 = render_id_handler_map_.find(
-        std::make_pair(render_process_id, render_frame_id));
-    if (it1 != render_id_handler_map_.end())
+  if (frame_util::IsValidGlobalId(global_id)) {
+    const auto it1 = render_id_handler_map_.find(global_id);
+    if (it1 != render_id_handler_map_.end()) {
       return it1->second;
+    }
   }
 
-  if (frame_tree_node_id >= 0) {
-    const auto it2 = node_id_handler_map_.find(frame_tree_node_id);
-    if (it2 != node_id_handler_map_.end())
-      return it2->second;
-  }
-
-  if (render_process_id >= 0 && !require_frame_match) {
+  if (frame_util::IsValidChildId(global_id.child_id) && !require_frame_match) {
     // Choose an arbitrary handler for the same process.
     for (auto& kv : render_id_handler_map_) {
-      if (kv.first.first == render_process_id)
+      if (kv.first.child_id == global_id.child_id) {
         return kv.second;
+      }
     }
   }
 
diff --git a/src/libcef/browser/request_context_handler_map.h b/src/libcef/browser/request_context_handler_map.h
index 51487d5..8f2422d 100644
--- a/src/libcef/browser/request_context_handler_map.h
+++ b/src/libcef/browser/request_context_handler_map.h
@@ -11,51 +11,42 @@
 #include "include/cef_request_context.h"
 #include "include/cef_request_context_handler.h"
 
-#include "base/macros.h"
+#include "content/public/browser/global_routing_id.h"
 
 // Tracks CefRequestContextHandler associations on a single thread.
 class CefRequestContextHandlerMap {
  public:
   CefRequestContextHandlerMap();
+
+  CefRequestContextHandlerMap(const CefRequestContextHandlerMap&) = delete;
+  CefRequestContextHandlerMap& operator=(const CefRequestContextHandlerMap&) =
+      delete;
+
   ~CefRequestContextHandlerMap();
 
   // Keep track of handlers associated with specific frames. This information
-  // originates from frame create/delete notifications in CefBrowserHostImpl or
-  // CefMimeHandlerViewGuestDelegate which are forwarded via
-  // CefRequestContextImpl and CefBrowserContext.
-  void AddHandler(int render_process_id,
-                  int render_frame_id,
-                  int frame_tree_node_id,
+  // originates from frame create/delete notifications in
+  // CefBrowserContentsDelegate or CefMimeHandlerViewGuestDelegate which are
+  // forwarded via CefRequestContextImpl and CefBrowserContext.
+  void AddHandler(const content::GlobalRenderFrameHostId& global_id,
                   CefRefPtr<CefRequestContextHandler> handler);
-  void RemoveHandler(int render_process_id,
-                     int render_frame_id,
-                     int frame_tree_node_id);
+  void RemoveHandler(const content::GlobalRenderFrameHostId& global_id);
 
-  // Returns the handler that matches the specified IDs. Pass -1 for unknown
-  // values. If |require_frame_match| is true only exact matches will be
-  // returned. If |require_frame_match| is false, and there is not an exact
-  // match, then the first handler for the same |render_process_id| will be
-  // returned.
+  // Returns the handler that matches the specified IDs. If
+  // |require_frame_match| is true only exact matches will be returned. If
+  // |require_frame_match| is false, and there is not an exact match, then the
+  // first handler for the same |global_id.child_id| will be returned.
   CefRefPtr<CefRequestContextHandler> GetHandler(
-      int render_process_id,
-      int render_frame_id,
-      int frame_tree_node_id,
+      const content::GlobalRenderFrameHostId& global_id,
       bool require_frame_match) const;
 
  private:
-  // Map of (render_process_id, render_frame_id) to handler.
-  typedef std::map<std::pair<int, int>, CefRefPtr<CefRequestContextHandler>>
-      RenderIdHandlerMap;
+  // Map of global ID to handler. These IDs are guaranteed to uniquely
+  // identify a RFH for its complete lifespan. See documentation on
+  // RenderFrameHost::GetFrameTreeNodeId() for background.
+  using RenderIdHandlerMap = std::map<content::GlobalRenderFrameHostId,
+                                      CefRefPtr<CefRequestContextHandler>>;
   RenderIdHandlerMap render_id_handler_map_;
-
-  // Map of frame_tree_node_id to handler. Keeping this map is necessary
-  // because, when navigating the main frame, a new (pre-commit) network request
-  // will be created before the RenderFrameHost. Consequently we can't rely
-  // on valid render IDs. See https://crbug.com/776884 for background.
-  typedef std::map<int, CefRefPtr<CefRequestContextHandler>> NodeIdHandlerMap;
-  NodeIdHandlerMap node_id_handler_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefRequestContextHandlerMap);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_REQUEST_CONTEXT_HANDLER_MAP_
diff --git a/src/libcef/browser/request_context_impl.cc b/src/libcef/browser/request_context_impl.cc
index cace18d..6689f1e 100644
--- a/src/libcef/browser/request_context_impl.cc
+++ b/src/libcef/browser/request_context_impl.cc
@@ -4,24 +4,26 @@
 
 #include "libcef/browser/request_context_impl.h"
 #include "libcef/browser/browser_context.h"
-#include "libcef/browser/content_browser_client.h"
 #include "libcef/browser/context.h"
-#include "libcef/browser/extensions/extension_system.h"
+#include "libcef/browser/prefs/pref_helper.h"
 #include "libcef/browser/thread_util.h"
-#include "libcef/common/extensions/extensions_util.h"
+#include "libcef/common/app_manager.h"
 #include "libcef/common/task_runner_impl.h"
 #include "libcef/common/values_impl.h"
 
 #include "base/atomic_sequence_num.h"
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
+#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/plugin_service.h"
+#include "content/public/browser/child_process_host.h"
 #include "content/public/browser/ssl_host_state_delegate.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
+#include "net/dns/host_resolver.h"
 #include "services/network/public/cpp/resolve_host_client_base.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 
@@ -31,84 +33,37 @@
 
 base::AtomicSequenceNumber g_next_id;
 
-const char* GetTypeString(base::Value::Type type) {
-  switch (type) {
-    case base::Value::Type::NONE:
-      return "NULL";
-    case base::Value::Type::BOOLEAN:
-      return "BOOLEAN";
-    case base::Value::Type::INTEGER:
-      return "INTEGER";
-    case base::Value::Type::DOUBLE:
-      return "DOUBLE";
-    case base::Value::Type::STRING:
-      return "STRING";
-    case base::Value::Type::BINARY:
-      return "BINARY";
-    case base::Value::Type::DICTIONARY:
-      return "DICTIONARY";
-    case base::Value::Type::LIST:
-      return "LIST";
-    case base::Value::Type::DEAD:
-      return "DEAD";
-  }
-
-  NOTREACHED();
-  return "UNKNOWN";
-}
-
-// Helper for HostResolver::Resolve.
-struct ResolveHostHelperOld {
-  explicit ResolveHostHelperOld(CefRefPtr<CefResolveCallback> callback)
-      : callback_(callback) {}
-
-  void OnResolveCompleted(int result) {
-    std::vector<CefString> resolved_ips;
-    base::Optional<net::AddressList> maybe_address_list =
-        request_->GetAddressResults();
-    if (maybe_address_list) {
-      net::AddressList::const_iterator iter = maybe_address_list->begin();
-      for (; iter != maybe_address_list->end(); ++iter)
-        resolved_ips.push_back(iter->ToStringWithoutPort());
-    }
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::Bind(&CefResolveCallback::OnResolveCompleted, callback_,
-                   static_cast<cef_errorcode_t>(result), resolved_ips));
-
-    delete this;
-  }
-
-  CefRefPtr<CefResolveCallback> callback_;
-  std::unique_ptr<net::HostResolver::ResolveHostRequest> request_;
-};
-
 class ResolveHostHelper : public network::ResolveHostClientBase {
  public:
   explicit ResolveHostHelper(CefRefPtr<CefResolveCallback> callback)
       : callback_(callback), receiver_(this) {}
 
+  ResolveHostHelper(const ResolveHostHelper&) = delete;
+  ResolveHostHelper& operator=(const ResolveHostHelper&) = delete;
+
   void Start(CefBrowserContext* browser_context, const CefString& origin) {
     CEF_REQUIRE_UIT();
 
     browser_context->GetNetworkContext()->CreateHostResolver(
-        base::nullopt, host_resolver_.BindNewPipeAndPassReceiver());
+        net::DnsConfigOverrides(), host_resolver_.BindNewPipeAndPassReceiver());
 
     host_resolver_.set_disconnect_handler(base::BindOnce(
         &ResolveHostHelper::OnComplete, base::Unretained(this), net::ERR_FAILED,
-        net::ResolveErrorInfo(net::ERR_FAILED), base::nullopt));
+        net::ResolveErrorInfo(net::ERR_FAILED), absl::nullopt, absl::nullopt));
 
     host_resolver_->ResolveHost(
-        net::HostPortPair::FromURL(GURL(origin.ToString())),
-        net::NetworkIsolationKey::Todo(), nullptr,
+        network::mojom::HostResolverHost::NewHostPortPair(
+            net::HostPortPair::FromURL(GURL(origin.ToString()))),
+        net::NetworkAnonymizationKey::CreateTransient(), nullptr,
         receiver_.BindNewPipeAndPassRemote());
   }
 
  private:
-  void OnComplete(
-      int32_t result,
-      const ::net::ResolveErrorInfo& resolve_error_info,
-      const base::Optional<net::AddressList>& resolved_addresses) override {
+  void OnComplete(int result,
+                  const net::ResolveErrorInfo& resolve_error_info,
+                  const absl::optional<net::AddressList>& resolved_addresses,
+                  const absl::optional<net::HostResolverEndpointResults>&
+                      endpoint_results_with_metadat) override {
     CEF_REQUIRE_UIT();
 
     host_resolver_.reset();
@@ -116,9 +71,9 @@
 
     std::vector<CefString> resolved_ips;
 
-    if (result == net::OK) {
-      DCHECK(resolved_addresses && !resolved_addresses->empty());
-      for (const auto& value : resolved_addresses.value()) {
+    if (result == net::OK && resolved_addresses.has_value()) {
+      DCHECK(!resolved_addresses->empty());
+      for (const auto& value : *resolved_addresses) {
         resolved_ips.push_back(value.ToStringWithoutPort());
       }
     }
@@ -131,11 +86,20 @@
   CefRefPtr<CefResolveCallback> callback_;
 
   mojo::Remote<network::mojom::HostResolver> host_resolver_;
-  mojo::Receiver<network::mojom::ResolveHostClient> receiver_;
-
-  DISALLOW_COPY_AND_ASSIGN(ResolveHostHelper);
+  mojo::Receiver<network::mojom::ResolveHostClient> receiver_{this};
 };
 
+CefBrowserContext* GetCefBrowserContext(
+    CefRefPtr<CefRequestContext> request_context) {
+  CEF_REQUIRE_UIT();
+  CefRefPtr<CefRequestContextImpl> request_context_impl =
+      CefRequestContextImpl::GetOrCreateForRequestContext(request_context);
+  CHECK(request_context_impl);
+  auto* cef_browser_context = request_context_impl->GetBrowserContext();
+  CHECK(cef_browser_context);
+  return cef_browser_context;
+}
+
 }  // namespace
 
 // CefBrowserContext
@@ -144,7 +108,7 @@
 CefRefPtr<CefRequestContext> CefRequestContext::GetGlobalContext() {
   // Verify that the context is in a valid state.
   if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
+    DCHECK(false) << "context not valid";
     return nullptr;
   }
 
@@ -159,7 +123,7 @@
     CefRefPtr<CefRequestContextHandler> handler) {
   // Verify that the context is in a valid state.
   if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
+    DCHECK(false) << "context not valid";
     return nullptr;
   }
 
@@ -176,12 +140,13 @@
     CefRefPtr<CefRequestContextHandler> handler) {
   // Verify that the context is in a valid state.
   if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
+    DCHECK(false) << "context not valid";
     return nullptr;
   }
 
-  if (!other.get())
+  if (!other.get()) {
     return nullptr;
+  }
 
   CefRequestContextImpl::Config config;
   config.other = static_cast<CefRequestContextImpl*>(other.get());
@@ -230,28 +195,96 @@
   return CefRequestContextImpl::GetOrCreateRequestContext(config);
 }
 
+content::BrowserContext* CefRequestContextImpl::GetBrowserContext(
+    CefRefPtr<CefRequestContext> request_context) {
+  auto* browser_context =
+      GetCefBrowserContext(request_context)->AsBrowserContext();
+  CHECK(browser_context);
+  return browser_context;
+}
+
+Profile* CefRequestContextImpl::GetProfile(
+    CefRefPtr<CefRequestContext> request_context) {
+  auto* profile = GetCefBrowserContext(request_context)->AsProfile();
+  CHECK(profile);
+  return profile;
+}
+
+bool CefRequestContextImpl::VerifyBrowserContext() const {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    DCHECK(false) << "called on invalid thread";
+    return false;
+  }
+
+  if (!browser_context() || !browser_context()->IsInitialized()) {
+    DCHECK(false) << "Uninitialized context";
+    return false;
+  }
+
+  return true;
+}
+
 CefBrowserContext* CefRequestContextImpl::GetBrowserContext() {
-  EnsureBrowserContext();
+  CHECK(VerifyBrowserContext());
   return browser_context();
 }
 
+void CefRequestContextImpl::ExecuteWhenBrowserContextInitialized(
+    base::OnceClosure callback) {
+  if (!CEF_CURRENTLY_ON_UIT()) {
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(
+            &CefRequestContextImpl::ExecuteWhenBrowserContextInitialized, this,
+            std::move(callback)));
+    return;
+  }
+
+  EnsureBrowserContext();
+  browser_context()->StoreOrTriggerInitCallback(std::move(callback));
+}
+
 void CefRequestContextImpl::GetBrowserContext(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    const BrowserContextCallback& callback) {
-  if (!task_runner.get())
+    BrowserContextCallback callback) {
+  if (!task_runner.get()) {
     task_runner = CefTaskRunnerImpl::GetCurrentTaskRunner();
-  GetBrowserContextOnUIThread(task_runner, callback);
+  }
+
+  ExecuteWhenBrowserContextInitialized(base::BindOnce(
+      [](CefRefPtr<CefRequestContextImpl> context,
+         scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+         BrowserContextCallback callback) {
+        CEF_REQUIRE_UIT();
+
+        auto browser_context = context->browser_context();
+        DCHECK(browser_context->IsInitialized());
+
+        if (task_runner->BelongsToCurrentThread()) {
+          // Execute the callback immediately.
+          std::move(callback).Run(browser_context->getter());
+        } else {
+          // Execute the callback on the target thread.
+          task_runner->PostTask(
+              FROM_HERE,
+              base::BindOnce(std::move(callback), browser_context->getter()));
+        }
+      },
+      CefRefPtr<CefRequestContextImpl>(this), task_runner,
+      std::move(callback)));
 }
 
 bool CefRequestContextImpl::IsSame(CefRefPtr<CefRequestContext> other) {
   CefRequestContextImpl* other_impl =
       static_cast<CefRequestContextImpl*>(other.get());
-  if (!other_impl)
+  if (!other_impl) {
     return false;
+  }
 
   // Compare whether both are the global context.
-  if (config_.is_global && other_impl->config_.is_global)
+  if (config_.is_global && other_impl->config_.is_global) {
     return true;
+  }
 
   // Compare CefBrowserContext pointers if one has been associated.
   if (browser_context() && other_impl->browser_context()) {
@@ -267,11 +300,13 @@
 bool CefRequestContextImpl::IsSharingWith(CefRefPtr<CefRequestContext> other) {
   CefRequestContextImpl* other_impl =
       static_cast<CefRequestContextImpl*>(other.get());
-  if (!other_impl)
+  if (!other_impl) {
     return false;
+  }
 
-  if (IsSame(other))
+  if (IsSame(other)) {
     return true;
+  }
 
   CefRefPtr<CefRequestContext> pending_other = config_.other;
   if (pending_other.get()) {
@@ -314,7 +349,7 @@
 CefRefPtr<CefCookieManager> CefRequestContextImpl::GetCookieManager(
     CefRefPtr<CefCompletionCallback> callback) {
   CefRefPtr<CefCookieManagerImpl> cookie_manager = new CefCookieManagerImpl();
-  InitializeCookieManagerOnUIThread(cookie_manager, callback);
+  InitializeCookieManagerInternal(cookie_manager, callback);
   return cookie_manager.get();
 }
 
@@ -322,230 +357,136 @@
     const CefString& scheme_name,
     const CefString& domain_name,
     CefRefPtr<CefSchemeHandlerFactory> factory) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(
-                      base::IgnoreResult(
-                          &CefRequestContextImpl::RegisterSchemeHandlerFactory),
-                      this, scheme_name, domain_name, factory));
-    return true;
-  }
+  GetBrowserContext(
+      content::GetUIThreadTaskRunner({}),
+      base::BindOnce(
+          [](const CefString& scheme_name, const CefString& domain_name,
+             CefRefPtr<CefSchemeHandlerFactory> factory,
+             CefBrowserContext::Getter browser_context_getter) {
+            auto browser_context = browser_context_getter.Run();
+            if (browser_context) {
+              browser_context->RegisterSchemeHandlerFactory(
+                  scheme_name, domain_name, factory);
+            }
+          },
+          scheme_name, domain_name, factory));
 
-  // Make sure the browser context exists.
-  EnsureBrowserContext();
-
-  browser_context()->RegisterSchemeHandlerFactory(scheme_name, domain_name,
-                                                  factory);
   return true;
 }
 
 bool CefRequestContextImpl::ClearSchemeHandlerFactories() {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::BindOnce(base::IgnoreResult(
-                           &CefRequestContextImpl::ClearSchemeHandlerFactories),
-                       this));
-    return true;
-  }
+  GetBrowserContext(
+      content::GetUIThreadTaskRunner({}),
+      base::BindOnce([](CefBrowserContext::Getter browser_context_getter) {
+        auto browser_context = browser_context_getter.Run();
+        if (browser_context) {
+          browser_context->ClearSchemeHandlerFactories();
+        }
+      }));
 
-  // Make sure the browser context exists.
-  EnsureBrowserContext();
-
-  browser_context()->ClearSchemeHandlerFactories();
   return true;
 }
 
-void CefRequestContextImpl::PurgePluginListCache(bool reload_pages) {
-  GetBrowserContext(
-      base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
-      base::Bind(&CefRequestContextImpl::PurgePluginListCacheInternal, this,
-                 reload_pages));
-}
-
 bool CefRequestContextImpl::HasPreference(const CefString& name) {
-  // Verify that this method is being called on the UI thread.
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
+  if (!VerifyBrowserContext()) {
     return false;
   }
 
-  // Make sure the browser context exists.
-  EnsureBrowserContext();
-
-  PrefService* pref_service = browser_context()->GetPrefs();
-  return (pref_service->FindPreference(name) != nullptr);
+  PrefService* pref_service = browser_context()->AsProfile()->GetPrefs();
+  return pref_helper::HasPreference(pref_service, name);
 }
 
 CefRefPtr<CefValue> CefRequestContextImpl::GetPreference(
     const CefString& name) {
-  // Verify that this method is being called on the UI thread.
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
+  if (!VerifyBrowserContext()) {
     return nullptr;
   }
 
-  // Make sure the browser context exists.
-  EnsureBrowserContext();
-
-  PrefService* pref_service = browser_context()->GetPrefs();
-  const PrefService::Preference* pref = pref_service->FindPreference(name);
-  if (!pref)
-    return nullptr;
-  return new CefValueImpl(pref->GetValue()->DeepCopy());
+  PrefService* pref_service = browser_context()->AsProfile()->GetPrefs();
+  return pref_helper::GetPreference(pref_service, name);
 }
 
 CefRefPtr<CefDictionaryValue> CefRequestContextImpl::GetAllPreferences(
     bool include_defaults) {
-  // Verify that this method is being called on the UI thread.
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
+  if (!VerifyBrowserContext()) {
     return nullptr;
   }
 
-  // Make sure the browser context exists.
-  EnsureBrowserContext();
-
-  PrefService* pref_service = browser_context()->GetPrefs();
-
-  std::unique_ptr<base::DictionaryValue> values =
-      pref_service->GetPreferenceValues(include_defaults
-                                            ? PrefService::INCLUDE_DEFAULTS
-                                            : PrefService::EXCLUDE_DEFAULTS);
-
-  // CefDictionaryValueImpl takes ownership of |values|.
-  return new CefDictionaryValueImpl(values.release(), true, false);
+  PrefService* pref_service = browser_context()->AsProfile()->GetPrefs();
+  return pref_helper::GetAllPreferences(pref_service, include_defaults);
 }
 
 bool CefRequestContextImpl::CanSetPreference(const CefString& name) {
-  // Verify that this method is being called on the UI thread.
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
+  if (!VerifyBrowserContext()) {
     return false;
   }
 
-  // Make sure the browser context exists.
-  EnsureBrowserContext();
-
-  PrefService* pref_service = browser_context()->GetPrefs();
-  const PrefService::Preference* pref = pref_service->FindPreference(name);
-  return (pref && pref->IsUserModifiable());
+  PrefService* pref_service = browser_context()->AsProfile()->GetPrefs();
+  return pref_helper::CanSetPreference(pref_service, name);
 }
 
 bool CefRequestContextImpl::SetPreference(const CefString& name,
                                           CefRefPtr<CefValue> value,
                                           CefString& error) {
-  // Verify that this method is being called on the UI thread.
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
+  if (!VerifyBrowserContext()) {
     return false;
   }
 
-  // Make sure the browser context exists.
-  EnsureBrowserContext();
-
-  PrefService* pref_service = browser_context()->GetPrefs();
-
-  // The below validation logic should match PrefService::SetUserPrefValue.
-
-  const PrefService::Preference* pref = pref_service->FindPreference(name);
-  if (!pref) {
-    error = "Trying to modify an unregistered preference";
-    return false;
-  }
-
-  if (!pref->IsUserModifiable()) {
-    error = "Trying to modify a preference that is not user modifiable";
-    return false;
-  }
-
-  if (!value.get()) {
-    // Reset the preference to its default value.
-    pref_service->ClearPref(name);
-    return true;
-  }
-
-  if (!value->IsValid()) {
-    error = "A valid value is required";
-    return false;
-  }
-
-  CefValueImpl* impl = static_cast<CefValueImpl*>(value.get());
-
-  CefValueImpl::ScopedLockedValue scoped_locked_value(impl);
-  base::Value* impl_value = impl->GetValueUnsafe();
-
-  if (pref->GetType() != impl_value->type()) {
-    error = base::StringPrintf(
-        "Trying to set a preference of type %s to value of type %s",
-        GetTypeString(pref->GetType()), GetTypeString(impl_value->type()));
-    return false;
-  }
-
-  // PrefService will make a DeepCopy of |impl_value|.
-  pref_service->Set(name, *impl_value);
-  return true;
+  PrefService* pref_service = browser_context()->AsProfile()->GetPrefs();
+  return pref_helper::SetPreference(pref_service, name, value, error);
 }
 
 void CefRequestContextImpl::ClearCertificateExceptions(
     CefRefPtr<CefCompletionCallback> callback) {
   GetBrowserContext(
-      base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
-      base::Bind(&CefRequestContextImpl::ClearCertificateExceptionsInternal,
-                 this, callback));
+      content::GetUIThreadTaskRunner({}),
+      base::BindOnce(&CefRequestContextImpl::ClearCertificateExceptionsInternal,
+                     this, callback));
 }
 
 void CefRequestContextImpl::ClearHttpAuthCredentials(
     CefRefPtr<CefCompletionCallback> callback) {
   GetBrowserContext(
-      base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
-      base::Bind(&CefRequestContextImpl::ClearHttpAuthCredentialsInternal, this,
-                 callback));
+      content::GetUIThreadTaskRunner({}),
+      base::BindOnce(&CefRequestContextImpl::ClearHttpAuthCredentialsInternal,
+                     this, callback));
 }
 
 void CefRequestContextImpl::CloseAllConnections(
     CefRefPtr<CefCompletionCallback> callback) {
   GetBrowserContext(
-      base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
-      base::Bind(&CefRequestContextImpl::CloseAllConnectionsInternal, this,
-                 callback));
+      content::GetUIThreadTaskRunner({}),
+      base::BindOnce(&CefRequestContextImpl::CloseAllConnectionsInternal, this,
+                     callback));
 }
 
 void CefRequestContextImpl::ResolveHost(
     const CefString& origin,
     CefRefPtr<CefResolveCallback> callback) {
-  GetBrowserContext(base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
-                    base::Bind(&CefRequestContextImpl::ResolveHostInternal,
-                               this, origin, callback));
+  GetBrowserContext(content::GetUIThreadTaskRunner({}),
+                    base::BindOnce(&CefRequestContextImpl::ResolveHostInternal,
+                                   this, origin, callback));
 }
 
 void CefRequestContextImpl::LoadExtension(
     const CefString& root_directory,
     CefRefPtr<CefDictionaryValue> manifest,
     CefRefPtr<CefExtensionHandler> handler) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(CEF_UIT,
-                  base::BindOnce(&CefRequestContextImpl::LoadExtension, this,
-                                 root_directory, manifest, handler));
-    return;
-  }
-
-  if (!extensions::ExtensionsEnabled()) {
-    if (handler)
-      handler->OnExtensionLoadFailed(ERR_ABORTED);
-    return;
-  }
-
-  if (manifest && manifest->GetSize() > 0) {
-    CefDictionaryValueImpl* value_impl =
-        static_cast<CefDictionaryValueImpl*>(manifest.get());
-    GetBrowserContext()->extension_system()->LoadExtension(
-        base::WrapUnique(value_impl->CopyValue()), root_directory,
-        false /* builtin */, this, handler);
-  } else {
-    GetBrowserContext()->extension_system()->LoadExtension(
-        root_directory, false /* builtin */, this, handler);
-  }
+  GetBrowserContext(content::GetUIThreadTaskRunner({}),
+                    base::BindOnce(
+                        [](const CefString& root_directory,
+                           CefRefPtr<CefDictionaryValue> manifest,
+                           CefRefPtr<CefExtensionHandler> handler,
+                           CefRefPtr<CefRequestContextImpl> self,
+                           CefBrowserContext::Getter browser_context_getter) {
+                          auto browser_context = browser_context_getter.Run();
+                          if (browser_context) {
+                            browser_context->LoadExtension(
+                                root_directory, manifest, handler, self);
+                          }
+                        },
+                        root_directory, manifest, handler,
+                        CefRefPtr<CefRequestContextImpl>(this)));
 }
 
 bool CefRequestContextImpl::DidLoadExtension(const CefString& extension_id) {
@@ -562,61 +503,136 @@
     std::vector<CefString>& extension_ids) {
   extension_ids.clear();
 
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
+  if (!VerifyBrowserContext()) {
     return false;
   }
 
-  if (!extensions::ExtensionsEnabled())
-    return false;
-
-  extensions::CefExtensionSystem::ExtensionMap extension_map =
-      GetBrowserContext()->extension_system()->GetExtensions();
-  extensions::CefExtensionSystem::ExtensionMap::const_iterator it =
-      extension_map.begin();
-  for (; it != extension_map.end(); ++it)
-    extension_ids.push_back(it->second->GetIdentifier());
-
-  return true;
+  return browser_context()->GetExtensions(extension_ids);
 }
 
 CefRefPtr<CefExtension> CefRequestContextImpl::GetExtension(
     const CefString& extension_id) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
+  if (!VerifyBrowserContext()) {
     return nullptr;
   }
 
-  if (!extensions::ExtensionsEnabled())
-    return nullptr;
-
-  return GetBrowserContext()->extension_system()->GetExtension(extension_id);
+  return browser_context()->GetExtension(extension_id);
 }
 
-CefRefPtr<CefMediaRouter> CefRequestContextImpl::GetMediaRouter() {
+CefRefPtr<CefMediaRouter> CefRequestContextImpl::GetMediaRouter(
+    CefRefPtr<CefCompletionCallback> callback) {
   CefRefPtr<CefMediaRouterImpl> media_router = new CefMediaRouterImpl();
-  InitializeMediaRouterOnUIThread(media_router);
+  InitializeMediaRouterInternal(media_router, callback);
   return media_router.get();
 }
 
-void CefRequestContextImpl::OnRenderFrameCreated(int render_process_id,
-                                                 int render_frame_id,
-                                                 int frame_tree_node_id,
-                                                 bool is_main_frame,
-                                                 bool is_guest_view) {
-  browser_context_->OnRenderFrameCreated(this, render_process_id,
-                                         render_frame_id, frame_tree_node_id,
-                                         is_main_frame, is_guest_view);
+CefRefPtr<CefValue> CefRequestContextImpl::GetWebsiteSetting(
+    const CefString& requesting_url,
+    const CefString& top_level_url,
+    cef_content_setting_types_t content_type) {
+  if (!VerifyBrowserContext()) {
+    return nullptr;
+  }
+
+  auto* settings_map = HostContentSettingsMapFactory::GetForProfile(
+      browser_context()->AsProfile());
+  if (!settings_map) {
+    return nullptr;
+  }
+
+  // Either or both URLs may be invalid.
+  GURL requesting_gurl(requesting_url.ToString());
+  GURL top_level_gurl(top_level_url.ToString());
+
+  content_settings::SettingInfo info;
+  base::Value value = settings_map->GetWebsiteSetting(
+      requesting_gurl, top_level_gurl,
+      static_cast<ContentSettingsType>(content_type), &info);
+  if (value.is_none()) {
+    return nullptr;
+  }
+
+  return new CefValueImpl(std::move(value));
 }
 
-void CefRequestContextImpl::OnRenderFrameDeleted(int render_process_id,
-                                                 int render_frame_id,
-                                                 int frame_tree_node_id,
-                                                 bool is_main_frame,
-                                                 bool is_guest_view) {
-  browser_context_->OnRenderFrameDeleted(this, render_process_id,
-                                         render_frame_id, frame_tree_node_id,
-                                         is_main_frame, is_guest_view);
+void CefRequestContextImpl::SetWebsiteSetting(
+    const CefString& requesting_url,
+    const CefString& top_level_url,
+    cef_content_setting_types_t content_type,
+    CefRefPtr<CefValue> value) {
+  GetBrowserContext(
+      content::GetUIThreadTaskRunner({}),
+      base::BindOnce(&CefRequestContextImpl::SetWebsiteSettingInternal, this,
+                     requesting_url, top_level_url, content_type, value));
+}
+
+cef_content_setting_values_t CefRequestContextImpl::GetContentSetting(
+    const CefString& requesting_url,
+    const CefString& top_level_url,
+    cef_content_setting_types_t content_type) {
+  // Verify that our enums match Chromium's values.
+  static_assert(static_cast<int>(CEF_CONTENT_SETTING_TYPE_NUM_TYPES) ==
+                    static_cast<int>(ContentSettingsType::NUM_TYPES),
+                "Mismatched enum found for CEF_CONTENT_SETTING_TYPE_NUM_TYPES");
+  static_assert(
+      static_cast<int>(CEF_CONTENT_SETTING_VALUE_NUM_VALUES) ==
+          static_cast<int>(CONTENT_SETTING_NUM_SETTINGS),
+      "Mismatched enum found for CEF_CONTENT_SETTING_VALUE_NUM_VALUES");
+
+  if (!VerifyBrowserContext()) {
+    return CEF_CONTENT_SETTING_VALUE_DEFAULT;
+  }
+
+  auto* settings_map = HostContentSettingsMapFactory::GetForProfile(
+      browser_context()->AsProfile());
+  if (!settings_map) {
+    return CEF_CONTENT_SETTING_VALUE_DEFAULT;
+  }
+
+  ContentSetting value = ContentSetting::CONTENT_SETTING_DEFAULT;
+
+  if (requesting_url.empty() && top_level_url.empty()) {
+    value = settings_map->GetDefaultContentSetting(
+        static_cast<ContentSettingsType>(content_type),
+        /*provider_id=*/nullptr);
+  } else {
+    GURL requesting_gurl(requesting_url.ToString());
+    GURL top_level_gurl(top_level_url.ToString());
+    if (requesting_gurl.is_valid() || top_level_gurl.is_valid()) {
+      value = settings_map->GetContentSetting(
+          requesting_gurl, top_level_gurl,
+          static_cast<ContentSettingsType>(content_type));
+    }
+  }
+
+  return static_cast<cef_content_setting_values_t>(value);
+}
+
+void CefRequestContextImpl::SetContentSetting(
+    const CefString& requesting_url,
+    const CefString& top_level_url,
+    cef_content_setting_types_t content_type,
+    cef_content_setting_values_t value) {
+  GetBrowserContext(
+      content::GetUIThreadTaskRunner({}),
+      base::BindOnce(&CefRequestContextImpl::SetContentSettingInternal, this,
+                     requesting_url, top_level_url, content_type, value));
+}
+
+void CefRequestContextImpl::OnRenderFrameCreated(
+    const content::GlobalRenderFrameHostId& global_id,
+    bool is_main_frame,
+    bool is_guest_view) {
+  browser_context_->OnRenderFrameCreated(this, global_id, is_main_frame,
+                                         is_guest_view);
+}
+
+void CefRequestContextImpl::OnRenderFrameDeleted(
+    const content::GlobalRenderFrameHostId& global_id,
+    bool is_main_frame,
+    bool is_guest_view) {
+  browser_context_->OnRenderFrameDeleted(this, global_id, is_main_frame,
+                                         is_guest_view);
 }
 
 // static
@@ -625,11 +641,22 @@
   if (config.is_global ||
       (config.other && config.other->IsGlobal() && !config.handler)) {
     // Return the singleton global context.
-    return CefContentBrowserClient::Get()->request_context();
+    return static_cast<CefRequestContextImpl*>(
+        CefAppManager::Get()->GetGlobalRequestContext().get());
   }
 
   // The new context will be initialized later by EnsureBrowserContext().
-  return new CefRequestContextImpl(config);
+  CefRefPtr<CefRequestContextImpl> context = new CefRequestContextImpl(config);
+
+  // Initialize ASAP so that any tasks blocked on initialization will execute.
+  if (CEF_CURRENTLY_ON_UIT()) {
+    context->Initialize();
+  } else {
+    CEF_POST_TASK(CEF_UIT,
+                  base::BindOnce(&CefRequestContextImpl::Initialize, context));
+  }
+
+  return context;
 }
 
 CefRequestContextImpl::CefRequestContextImpl(
@@ -643,9 +670,8 @@
 
   if (config_.other) {
     // Share storage with |config_.other|.
-    browser_context_ =
-        CefBrowserContext::GetForContext(config_.other->GetBrowserContext());
-    DCHECK(browser_context_);
+    browser_context_ = config_.other->browser_context();
+    CHECK(browser_context_);
   }
 
   if (!browser_context_) {
@@ -659,20 +685,24 @@
     if (!cache_path.empty()) {
       // Check if a CefBrowserContext is already globally registered for
       // the specified cache path. If so then use it.
-      browser_context_ = CefBrowserContext::GetForCachePath(cache_path);
+      browser_context_ = CefBrowserContext::FromCachePath(cache_path);
     }
   }
 
+  auto initialized_cb =
+      base::BindOnce(&CefRequestContextImpl::BrowserContextInitialized, this);
+
   if (!browser_context_) {
     // Create a new CefBrowserContext instance. If the cache path is non-
     // empty then this new instance will become the globally registered
     // CefBrowserContext for that path. Otherwise, this new instance will
     // be a completely isolated "incognito mode" context.
-    browser_context_ = new CefBrowserContext(config_.settings);
-    browser_context_->Initialize();
+    browser_context_ = CefAppManager::Get()->CreateNewBrowserContext(
+        config_.settings, std::move(initialized_cb));
   } else {
     // Share the same settings as the existing context.
-    config_.settings = browser_context_->GetSettings();
+    config_.settings = browser_context_->settings();
+    browser_context_->StoreOrTriggerInitCallback(std::move(initialized_cb));
   }
 
   // We'll disassociate from |browser_context_| on destruction.
@@ -684,121 +714,182 @@
     // IsSharedWith().
     config_.other = nullptr;
   }
+}
 
-  if (config_.handler)
-    config_.handler->OnRequestContextInitialized(this);
+void CefRequestContextImpl::BrowserContextInitialized() {
+  if (config_.handler) {
+    // Always execute asynchronously so the current call stack can unwind.
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(&CefRequestContextHandler::OnRequestContextInitialized,
+                       config_.handler, CefRefPtr<CefRequestContext>(this)));
+  }
 }
 
 void CefRequestContextImpl::EnsureBrowserContext() {
   CEF_REQUIRE_UIT();
-  if (!browser_context())
+  if (!browser_context()) {
     Initialize();
+  }
   DCHECK(browser_context());
 }
 
-void CefRequestContextImpl::GetBrowserContextOnUIThread(
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    const BrowserContextCallback& callback) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT, base::Bind(&CefRequestContextImpl::GetBrowserContextOnUIThread,
-                            this, task_runner, callback));
-    return;
-  }
-
-  // Make sure the browser context exists.
-  EnsureBrowserContext();
-
-  if (task_runner->BelongsToCurrentThread()) {
-    // Execute the callback immediately.
-    callback.Run(browser_context());
-  } else {
-    // Execute the callback on the target thread.
-    task_runner->PostTask(FROM_HERE, base::Bind(callback, browser_context()));
-  }
-}
-
-void CefRequestContextImpl::PurgePluginListCacheInternal(
-    bool reload_pages,
-    CefBrowserContext* browser_context) {
-  CEF_REQUIRE_UIT();
-  browser_context->ClearPluginLoadDecision(-1);
-  content::PluginService::GetInstance()->PurgePluginListCache(browser_context,
-                                                              false);
-}
-
 void CefRequestContextImpl::ClearCertificateExceptionsInternal(
     CefRefPtr<CefCompletionCallback> callback,
-    CefBrowserContext* browser_context) {
-  CEF_REQUIRE_UIT();
+    CefBrowserContext::Getter browser_context_getter) {
+  auto browser_context = browser_context_getter.Run();
+  if (!browser_context) {
+    return;
+  }
 
   content::SSLHostStateDelegate* ssl_delegate =
-      browser_context->GetSSLHostStateDelegate();
-  if (ssl_delegate)
-    ssl_delegate->Clear(base::Callback<bool(const std::string&)>());
+      browser_context->AsBrowserContext()->GetSSLHostStateDelegate();
+  if (ssl_delegate) {
+    ssl_delegate->Clear(base::NullCallback());
+  }
 
   if (callback) {
     CEF_POST_TASK(CEF_UIT,
-                  base::Bind(&CefCompletionCallback::OnComplete, callback));
+                  base::BindOnce(&CefCompletionCallback::OnComplete, callback));
   }
 }
 
 void CefRequestContextImpl::ClearHttpAuthCredentialsInternal(
     CefRefPtr<CefCompletionCallback> callback,
-    CefBrowserContext* browser_context) {
-  CEF_REQUIRE_UIT();
+    CefBrowserContext::Getter browser_context_getter) {
+  auto browser_context = browser_context_getter.Run();
+  if (!browser_context) {
+    return;
+  }
 
   browser_context->GetNetworkContext()->ClearHttpAuthCache(
-      base::Time(), base::Bind(&CefCompletionCallback::OnComplete, callback));
+      /*start_time=*/base::Time(), /*end_time=*/base::Time::Max(),
+      base::BindOnce(&CefCompletionCallback::OnComplete, callback));
 }
 
 void CefRequestContextImpl::CloseAllConnectionsInternal(
     CefRefPtr<CefCompletionCallback> callback,
-    CefBrowserContext* browser_context) {
-  CEF_REQUIRE_UIT();
+    CefBrowserContext::Getter browser_context_getter) {
+  auto browser_context = browser_context_getter.Run();
+  if (!browser_context) {
+    return;
+  }
 
   browser_context->GetNetworkContext()->CloseAllConnections(
-      base::Bind(&CefCompletionCallback::OnComplete, callback));
+      base::BindOnce(&CefCompletionCallback::OnComplete, callback));
 }
 
 void CefRequestContextImpl::ResolveHostInternal(
     const CefString& origin,
     CefRefPtr<CefResolveCallback> callback,
-    CefBrowserContext* browser_context) {
-  CEF_REQUIRE_UIT();
+    CefBrowserContext::Getter browser_context_getter) {
+  auto browser_context = browser_context_getter.Run();
+  if (!browser_context) {
+    return;
+  }
 
   // |helper| will be deleted in ResolveHostHelper::OnComplete().
   ResolveHostHelper* helper = new ResolveHostHelper(callback);
   helper->Start(browser_context, origin);
 }
 
-void CefRequestContextImpl::InitializeCookieManagerOnUIThread(
-    CefRefPtr<CefCookieManagerImpl> cookie_manager,
-    CefRefPtr<CefCompletionCallback> callback) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::Bind(&CefRequestContextImpl::InitializeCookieManagerOnUIThread,
-                   this, cookie_manager, callback));
+void CefRequestContextImpl::SetWebsiteSettingInternal(
+    const CefString& requesting_url,
+    const CefString& top_level_url,
+    cef_content_setting_types_t content_type,
+    CefRefPtr<CefValue> value,
+    CefBrowserContext::Getter browser_context_getter) {
+  auto browser_context = browser_context_getter.Run();
+  if (!browser_context) {
     return;
   }
 
-  auto browser_context = GetBrowserContext();
-  cookie_manager->Initialize(browser_context->getter(), callback);
+  auto* settings_map = HostContentSettingsMapFactory::GetForProfile(
+      browser_context->AsProfile());
+  if (!settings_map) {
+    return;
+  }
+
+  // Starts as a NONE value.
+  base::Value new_value;
+  if (value && value->IsValid()) {
+    new_value = static_cast<CefValueImpl*>(value.get())->CopyValue();
+  }
+
+  if (requesting_url.empty() && top_level_url.empty()) {
+    settings_map->SetWebsiteSettingCustomScope(
+        ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
+        static_cast<ContentSettingsType>(content_type), std::move(new_value));
+  } else {
+    GURL requesting_gurl(requesting_url.ToString());
+    GURL top_level_gurl(top_level_url.ToString());
+    if (requesting_gurl.is_valid() || top_level_gurl.is_valid()) {
+      settings_map->SetWebsiteSettingDefaultScope(
+          requesting_gurl, top_level_gurl,
+          static_cast<ContentSettingsType>(content_type), std::move(new_value));
+    }
+  }
 }
 
-void CefRequestContextImpl::InitializeMediaRouterOnUIThread(
-    CefRefPtr<CefMediaRouterImpl> media_router) {
-  if (!CEF_CURRENTLY_ON_UIT()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::Bind(&CefRequestContextImpl::InitializeMediaRouterOnUIThread,
-                   this, media_router));
+void CefRequestContextImpl::SetContentSettingInternal(
+    const CefString& requesting_url,
+    const CefString& top_level_url,
+    cef_content_setting_types_t content_type,
+    cef_content_setting_values_t value,
+    CefBrowserContext::Getter browser_context_getter) {
+  auto browser_context = browser_context_getter.Run();
+  if (!browser_context) {
     return;
   }
 
-  auto browser_context = GetBrowserContext();
-  media_router->Initialize(browser_context->getter());
+  auto* settings_map = HostContentSettingsMapFactory::GetForProfile(
+      browser_context->AsProfile());
+  if (!settings_map) {
+    return;
+  }
+
+  if (requesting_url.empty() && top_level_url.empty()) {
+    settings_map->SetDefaultContentSetting(
+        static_cast<ContentSettingsType>(content_type),
+        static_cast<ContentSetting>(value));
+  } else {
+    GURL requesting_gurl(requesting_url.ToString());
+    GURL top_level_gurl(top_level_url.ToString());
+    if (requesting_gurl.is_valid() || top_level_gurl.is_valid()) {
+      settings_map->SetContentSettingDefaultScope(
+          requesting_gurl, top_level_gurl,
+          static_cast<ContentSettingsType>(content_type),
+          static_cast<ContentSetting>(value));
+    }
+  }
+}
+
+void CefRequestContextImpl::InitializeCookieManagerInternal(
+    CefRefPtr<CefCookieManagerImpl> cookie_manager,
+    CefRefPtr<CefCompletionCallback> callback) {
+  GetBrowserContext(content::GetUIThreadTaskRunner({}),
+                    base::BindOnce(
+                        [](CefRefPtr<CefCookieManagerImpl> cookie_manager,
+                           CefRefPtr<CefCompletionCallback> callback,
+                           CefBrowserContext::Getter browser_context_getter) {
+                          cookie_manager->Initialize(browser_context_getter,
+                                                     callback);
+                        },
+                        cookie_manager, callback));
+}
+
+void CefRequestContextImpl::InitializeMediaRouterInternal(
+    CefRefPtr<CefMediaRouterImpl> media_router,
+    CefRefPtr<CefCompletionCallback> callback) {
+  GetBrowserContext(content::GetUIThreadTaskRunner({}),
+                    base::BindOnce(
+                        [](CefRefPtr<CefMediaRouterImpl> media_router,
+                           CefRefPtr<CefCompletionCallback> callback,
+                           CefBrowserContext::Getter browser_context_getter) {
+                          media_router->Initialize(browser_context_getter,
+                                                   callback);
+                        },
+                        media_router, callback));
 }
 
 CefBrowserContext* CefRequestContextImpl::browser_context() const {
diff --git a/src/libcef/browser/request_context_impl.h b/src/libcef/browser/request_context_impl.h
index a802b26..a035fa9 100644
--- a/src/libcef/browser/request_context_impl.h
+++ b/src/libcef/browser/request_context_impl.h
@@ -2,8 +2,8 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#ifndef CEF_LIBCEF_REQUEST_CONTEXT_IMPL_H_
-#define CEF_LIBCEF_REQUEST_CONTEXT_IMPL_H_
+#ifndef CEF_LIBCEF_BROWSER_REQUEST_CONTEXT_IMPL_H_
+#define CEF_LIBCEF_BROWSER_REQUEST_CONTEXT_IMPL_H_
 #pragma once
 
 #include "include/cef_request_context.h"
@@ -12,16 +12,24 @@
 #include "libcef/browser/net_service/cookie_manager_impl.h"
 #include "libcef/browser/thread_util.h"
 
+namespace content {
+struct GlobalRenderFrameHostId;
+}
+
 class CefBrowserContext;
 
 // Implementation of the CefRequestContext interface. All methods are thread-
 // safe unless otherwise indicated. Will be deleted on the UI thread.
 class CefRequestContextImpl : public CefRequestContext {
  public:
+  CefRequestContextImpl(const CefRequestContextImpl&) = delete;
+  CefRequestContextImpl& operator=(const CefRequestContextImpl&) = delete;
+
   ~CefRequestContextImpl() override;
 
   // Creates the singleton global RequestContext. Called from
-  // CefBrowserMainParts::PreMainMessageLoopRun.
+  // AlloyBrowserMainParts::PreMainMessageLoopRun and
+  // ChromeBrowserMainExtraPartsCef::PostProfileInit.
   static CefRefPtr<CefRequestContextImpl> CreateGlobalRequestContext(
       const CefRequestContextSettings& settings);
 
@@ -30,17 +38,36 @@
   static CefRefPtr<CefRequestContextImpl> GetOrCreateForRequestContext(
       CefRefPtr<CefRequestContext> request_context);
 
-  // Returns the browser context object. Can only be called on the UI thread.
+  // Returns the BrowserContext for the specified |request_context|. Will return
+  // the global BrowserContext if |request_context| is NULL.
+  static content::BrowserContext* GetBrowserContext(
+      CefRefPtr<CefRequestContext> request_context);
+
+  // Returns the Profile for the specified |request_context|. Will return the
+  // global Profile if |request_context| is NULL.
+  static Profile* GetProfile(CefRefPtr<CefRequestContext> request_context);
+
+  // Verify that the browser context can be directly accessed (e.g. on the UI
+  // thread and initialized).
+  bool VerifyBrowserContext() const;
+
+  // Returns the browser context object. Can only be called on the UI thread
+  // after the browser context has been initialized.
   CefBrowserContext* GetBrowserContext();
 
-  // Executes |callback| either synchronously or asynchronously with the browser
-  // context object when it's available. If |task_runner| is NULL the callback
-  // will be executed on the originating thread. The resulting context object
-  // can only be accessed on the UI thread.
-  typedef base::Callback<void(CefBrowserContext*)> BrowserContextCallback;
+  // If the context is fully initialized execute |callback|, otherwise
+  // store it until the context is fully initialized.
+  void ExecuteWhenBrowserContextInitialized(base::OnceClosure callback);
+
+  // Executes |callback| either synchronously or asynchronously after the
+  // browser context object has been initialized. If |task_runner| is NULL the
+  // callback will be executed on the originating thread. The resulting getter
+  // can only be executed on the UI thread.
+  using BrowserContextCallback =
+      base::OnceCallback<void(CefBrowserContext::Getter)>;
   void GetBrowserContext(
       scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-      const BrowserContextCallback& callback);
+      BrowserContextCallback callback);
 
   bool IsSame(CefRefPtr<CefRequestContext> other) override;
   bool IsSharingWith(CefRefPtr<CefRequestContext> other) override;
@@ -54,7 +81,6 @@
       const CefString& domain_name,
       CefRefPtr<CefSchemeHandlerFactory> factory) override;
   bool ClearSchemeHandlerFactories() override;
-  void PurgePluginListCache(bool reload_pages) override;
   bool HasPreference(const CefString& name) override;
   CefRefPtr<CefValue> GetPreference(const CefString& name) override;
   CefRefPtr<CefDictionaryValue> GetAllPreferences(
@@ -77,25 +103,38 @@
   bool HasExtension(const CefString& extension_id) override;
   bool GetExtensions(std::vector<CefString>& extension_ids) override;
   CefRefPtr<CefExtension> GetExtension(const CefString& extension_id) override;
-  CefRefPtr<CefMediaRouter> GetMediaRouter() override;
+  CefRefPtr<CefMediaRouter> GetMediaRouter(
+      CefRefPtr<CefCompletionCallback> callback) override;
+  CefRefPtr<CefValue> GetWebsiteSetting(
+      const CefString& requesting_url,
+      const CefString& top_level_url,
+      cef_content_setting_types_t content_type) override;
+  void SetWebsiteSetting(const CefString& requesting_url,
+                         const CefString& top_level_url,
+                         cef_content_setting_types_t content_type,
+                         CefRefPtr<CefValue> value) override;
+  cef_content_setting_values_t GetContentSetting(
+      const CefString& requesting_url,
+      const CefString& top_level_url,
+      cef_content_setting_types_t content_type) override;
+  void SetContentSetting(const CefString& requesting_url,
+                         const CefString& top_level_url,
+                         cef_content_setting_types_t content_type,
+                         cef_content_setting_values_t value) override;
 
   const CefRequestContextSettings& settings() const { return config_.settings; }
 
-  // Called from CefBrowserHostImpl::RenderFrameCreated or
+  // Called from CefBrowserContentsDelegate::RenderFrameCreated or
   // CefMimeHandlerViewGuestDelegate::OnGuestAttached when a render frame is
   // created.
-  void OnRenderFrameCreated(int render_process_id,
-                            int render_frame_id,
-                            int frame_tree_node_id,
+  void OnRenderFrameCreated(const content::GlobalRenderFrameHostId& global_id,
                             bool is_main_frame,
                             bool is_guest_view);
 
-  // Called from CefBrowserHostImpl::FrameDeleted or
+  // Called from CefBrowserContentsDelegate::RenderFrameDeleted or
   // CefMimeHandlerViewGuestDelegate::OnGuestDetached when a render frame is
   // deleted.
-  void OnRenderFrameDeleted(int render_process_id,
-                            int render_frame_id,
-                            int frame_tree_node_id,
+  void OnRenderFrameDeleted(const content::GlobalRenderFrameHostId& global_id,
                             bool is_main_frame,
                             bool is_guest_view);
 
@@ -128,33 +167,41 @@
   explicit CefRequestContextImpl(const Config& config);
 
   void Initialize();
+  void BrowserContextInitialized();
 
   // Make sure the browser context exists. Only called on the UI thread.
   void EnsureBrowserContext();
 
-  void GetBrowserContextOnUIThread(
-      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-      const BrowserContextCallback& callback);
-
-  void PurgePluginListCacheInternal(bool reload_pages,
-                                    CefBrowserContext* browser_context);
   void ClearCertificateExceptionsInternal(
       CefRefPtr<CefCompletionCallback> callback,
-      CefBrowserContext* browser_context);
+      CefBrowserContext::Getter browser_context_getter);
   void ClearHttpAuthCredentialsInternal(
       CefRefPtr<CefCompletionCallback> callback,
-      CefBrowserContext* browser_context);
-  void CloseAllConnectionsInternal(CefRefPtr<CefCompletionCallback> callback,
-                                   CefBrowserContext* browser_context);
+      CefBrowserContext::Getter browser_context_getter);
+  void CloseAllConnectionsInternal(
+      CefRefPtr<CefCompletionCallback> callback,
+      CefBrowserContext::Getter browser_context_getter);
   void ResolveHostInternal(const CefString& origin,
                            CefRefPtr<CefResolveCallback> callback,
-                           CefBrowserContext* browser_context);
+                           CefBrowserContext::Getter browser_context_getter);
+  void SetWebsiteSettingInternal(
+      const CefString& requesting_url,
+      const CefString& top_level_url,
+      cef_content_setting_types_t content_type,
+      CefRefPtr<CefValue> value,
+      CefBrowserContext::Getter browser_context_getter);
+  void SetContentSettingInternal(
+      const CefString& requesting_url,
+      const CefString& top_level_url,
+      cef_content_setting_types_t content_type,
+      cef_content_setting_values_t value,
+      CefBrowserContext::Getter browser_context_getter);
 
-  void InitializeCookieManagerOnUIThread(
+  void InitializeCookieManagerInternal(
       CefRefPtr<CefCookieManagerImpl> cookie_manager,
       CefRefPtr<CefCompletionCallback> callback);
-  void InitializeMediaRouterOnUIThread(
-      CefRefPtr<CefMediaRouterImpl> media_router);
+  void InitializeMediaRouterInternal(CefRefPtr<CefMediaRouterImpl> media_router,
+                                     CefRefPtr<CefCompletionCallback> callback);
 
   CefBrowserContext* browser_context() const;
 
@@ -164,7 +211,6 @@
   Config config_;
 
   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefRequestContextImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefRequestContextImpl);
 };
 
-#endif  // CEF_LIBCEF_REQUEST_CONTEXT_IMPL_H_
+#endif  // CEF_LIBCEF_BROWSER_REQUEST_CONTEXT_IMPL_H_
diff --git a/src/libcef/browser/resource_context.h b/src/libcef/browser/resource_context.h
deleted file mode 100644
index e00e3b2..0000000
--- a/src/libcef/browser/resource_context.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_BROWSER_RESOURCE_CONTEXT_H_
-#define CEF_LIBCEF_BROWSER_RESOURCE_CONTEXT_H_
-#pragma once
-
-#include "include/cef_request_context.h"
-#include "include/cef_request_context_handler.h"
-#include "include/cef_scheme.h"
-
-#include "libcef/browser/request_context_handler_map.h"
-
-#include "content/public/browser/resource_context.h"
-
-class GURL;
-
-// Acts as a bridge for resource loading. Life span is controlled by
-// CefBrowserContext. Created on the UI thread but accessed and destroyed on the
-// IO thread. Network request objects are associated with the ResourceContext
-// via ProxyURLLoaderFactory. When the ResourceContext is destroyed all
-// outstanding network request objects will be canceled.
-// See browser_context.h for an object relationship diagram.
-class CefResourceContext : public content::ResourceContext {
- public:
-  explicit CefResourceContext(bool is_off_the_record);
-  ~CefResourceContext() override;
-
-  // See comments in CefRequestContextHandlerMap.
-  void AddHandler(int render_process_id,
-                  int render_frame_id,
-                  int frame_tree_node_id,
-                  CefRefPtr<CefRequestContextHandler> handler);
-  void RemoveHandler(int render_process_id,
-                     int render_frame_id,
-                     int frame_tree_node_id);
-  CefRefPtr<CefRequestContextHandler> GetHandler(
-      int render_process_id,
-      int render_frame_id,
-      int frame_tree_node_id,
-      bool require_frame_match) const;
-
-  // Manage scheme handler factories associated with this context.
-  void RegisterSchemeHandlerFactory(const std::string& scheme_name,
-                                    const std::string& domain_name,
-                                    CefRefPtr<CefSchemeHandlerFactory> factory);
-  void ClearSchemeHandlerFactories();
-  CefRefPtr<CefSchemeHandlerFactory> GetSchemeHandlerFactory(const GURL& url);
-
-  // State transferred from the BrowserContext for use on the IO thread.
-  bool IsOffTheRecord() const { return is_off_the_record_; }
-
- private:
-  void InitOnIOThread();
-
-  // Only accessed on the IO thread.
-  const bool is_off_the_record_;
-
-  // Map IDs to CefRequestContextHandler objects.
-  CefRequestContextHandlerMap handler_map_;
-
-  // Map (scheme, domain) to factories.
-  typedef std::map<std::pair<std::string, std::string>,
-                   CefRefPtr<CefSchemeHandlerFactory>>
-      SchemeHandlerFactoryMap;
-  SchemeHandlerFactoryMap scheme_handler_factory_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefResourceContext);
-};
-
-#endif  // CEF_LIBCEF_BROWSER_RESOURCE_CONTEXT_H_
diff --git a/src/libcef/browser/scheme_impl.cc b/src/libcef/browser/scheme_impl.cc
index f5423c0..3ac0c95 100644
--- a/src/libcef/browser/scheme_impl.cc
+++ b/src/libcef/browser/scheme_impl.cc
@@ -13,7 +13,7 @@
     CefRefPtr<CefSchemeHandlerFactory> factory) {
   // Verify that the context is in a valid state.
   if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
+    DCHECK(false) << "context not valid";
     return false;
   }
 
@@ -24,7 +24,7 @@
 bool CefClearSchemeHandlerFactories() {
   // Verify that the context is in a valid state.
   if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
+    DCHECK(false) << "context not valid";
     return false;
   }
 
diff --git a/src/libcef/browser/server_impl.cc b/src/libcef/browser/server_impl.cc
index 38c226c..4697d2e 100644
--- a/src/libcef/browser/server_impl.cc
+++ b/src/libcef/browser/server_impl.cc
@@ -8,10 +8,11 @@
 #include "libcef/common/request_impl.h"
 #include "libcef/common/task_runner_impl.h"
 
-#include "base/bind.h"
 #include "base/format_macros.h"
+#include "base/functional/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
+#include "base/task/thread_pool.h"
 #include "base/threading/thread.h"
 #include "net/base/net_errors.h"
 #include "net/http/http_request_headers.h"
@@ -24,24 +25,22 @@
 #define CEF_CURRENTLY_ON_HT() CurrentlyOnHandlerThread()
 #define CEF_REQUIRE_HT() DCHECK(CEF_CURRENTLY_ON_HT())
 
-#define CEF_REQUIRE_HT_RETURN(var)              \
-  if (!CEF_CURRENTLY_ON_HT()) {                 \
-    NOTREACHED() << "called on invalid thread"; \
-    return var;                                 \
+#define CEF_REQUIRE_HT_RETURN(var)               \
+  if (!CEF_CURRENTLY_ON_HT()) {                  \
+    DCHECK(false) << "called on invalid thread"; \
+    return var;                                  \
   }
 
-#define CEF_REQUIRE_HT_RETURN_VOID()            \
-  if (!CEF_CURRENTLY_ON_HT()) {                 \
-    NOTREACHED() << "called on invalid thread"; \
-    return;                                     \
+#define CEF_REQUIRE_HT_RETURN_VOID()             \
+  if (!CEF_CURRENTLY_ON_HT()) {                  \
+    DCHECK(false) << "called on invalid thread"; \
+    return;                                      \
   }
 
 #define CEF_POST_TASK_HT(task) task_runner_->PostTask(FROM_HERE, task);
 
 namespace {
 
-const char kReferrerLowerCase[] = "referer";
-
 // Wrap a string in a unique_ptr to avoid extra copies.
 std::unique_ptr<std::string> CreateUniqueString(const void* data,
                                                 size_t data_size) {
@@ -77,7 +76,8 @@
         info.headers.begin();
     for (; it != info.headers.end(); ++it) {
       // Don't include Referer in the header map.
-      if (base::LowerCaseEqualsASCII(it->first, kReferrerLowerCase)) {
+      if (base::EqualsCaseInsensitiveASCII(it->first,
+                                           net::HttpRequestHeaders::kReferer)) {
         referer = it->second;
       } else {
         header_map.insert(std::make_pair(it->first, it->second));
@@ -88,8 +88,9 @@
   CefRefPtr<CefRequestImpl> request = new CefRequestImpl();
   request->Set((is_websocket ? "ws://" : "http://") + address + info.path,
                info.method, post_data, header_map);
-  if (!referer.empty())
+  if (!referer.empty()) {
     request->SetReferrer(referer, REFERRER_POLICY_DEFAULT);
+  }
   request->SetReadOnly(true);
   return request;
 }
@@ -105,9 +106,13 @@
         connection_id_(connection_id),
         request_info_(request_info) {}
 
+  AcceptWebSocketCallback(const AcceptWebSocketCallback&) = delete;
+  AcceptWebSocketCallback& operator=(const AcceptWebSocketCallback&) = delete;
+
   ~AcceptWebSocketCallback() override {
-    if (impl_)
+    if (impl_) {
       impl_->ContinueWebSocketRequest(connection_id_, request_info_, false);
+    }
   }
 
   void Continue() override {
@@ -116,8 +121,9 @@
                     base::BindOnce(&AcceptWebSocketCallback::Continue, this));
       return;
     }
-    if (!impl_)
+    if (!impl_) {
       return;
+    }
     impl_->ContinueWebSocketRequest(connection_id_, request_info_, true);
     impl_ = nullptr;
   }
@@ -128,8 +134,9 @@
                     base::BindOnce(&AcceptWebSocketCallback::Cancel, this));
       return;
     }
-    if (!impl_)
+    if (!impl_) {
       return;
+    }
     impl_->ContinueWebSocketRequest(connection_id_, request_info_, false);
     impl_ = nullptr;
   }
@@ -140,7 +147,6 @@
   net::HttpServerRequestInfo request_info_;
 
   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(AcceptWebSocketCallback);
-  DISALLOW_COPY_AND_ASSIGN(AcceptWebSocketCallback);
 };
 
 }  // namespace
@@ -149,7 +155,7 @@
 
 // static
 void CefServer::CreateServer(const CefString& address,
-                             uint16 port,
+                             uint16_t port,
                              int backlog,
                              CefRefPtr<CefServerHandler> handler) {
   CefRefPtr<CefServerImpl> server(new CefServerImpl(handler));
@@ -172,7 +178,7 @@
 }
 
 void CefServerImpl::Start(const std::string& address,
-                          uint16 port,
+                          uint16_t port,
                           int backlog) {
   DCHECK(!address.empty());
   CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefServerImpl::StartOnUIThread, this,
@@ -180,8 +186,9 @@
 }
 
 CefRefPtr<CefTaskRunner> CefServerImpl::GetTaskRunner() {
-  if (task_runner_)
+  if (task_runner_) {
     return new CefTaskRunnerImpl(task_runner_);
+  }
   return nullptr;
 }
 
@@ -224,12 +231,14 @@
     return;
   }
 
-  if (!ValidateServer())
+  if (!ValidateServer()) {
     return;
+  }
 
   ConnectionInfo* info = GetConnectionInfo(connection_id);
-  if (!info)
+  if (!info) {
     return;
+  }
 
   if (info->is_websocket) {
     LOG(ERROR) << "Invalid attempt to send HTTP response for connection_id "
@@ -249,12 +258,14 @@
     return;
   }
 
-  if (!ValidateServer())
+  if (!ValidateServer()) {
     return;
+  }
 
   ConnectionInfo* info = GetConnectionInfo(connection_id);
-  if (!info)
+  if (!info) {
     return;
+  }
 
   if (info->is_websocket) {
     LOG(ERROR) << "Invalid attempt to send HTTP response for connection_id "
@@ -269,7 +280,7 @@
 void CefServerImpl::SendHttpResponse(int connection_id,
                                      int response_code,
                                      const CefString& content_type,
-                                     int64 content_length,
+                                     int64_t content_length,
                                      const HeaderMap& extra_headers) {
   if (!CEF_CURRENTLY_ON_HT()) {
     CEF_POST_TASK_HT(base::BindOnce(&CefServerImpl::SendHttpResponse, this,
@@ -278,12 +289,14 @@
     return;
   }
 
-  if (!ValidateServer())
+  if (!ValidateServer()) {
     return;
+  }
 
   ConnectionInfo* info = GetConnectionInfo(connection_id);
-  if (!info)
+  if (!info) {
     return;
+  }
 
   if (info->is_websocket) {
     LOG(ERROR) << "Invalid attempt to send HTTP response for connection_id "
@@ -295,8 +308,9 @@
       static_cast<net::HttpStatusCode>(response_code));
 
   HeaderMap::const_iterator it = extra_headers.begin();
-  for (; it != extra_headers.end(); ++it)
+  for (; it != extra_headers.end(); ++it) {
     response.AddHeader(it->first, it->second);
+  }
 
   response.AddHeader(net::HttpRequestHeaders::kContentType, content_type);
   if (content_length >= 0) {
@@ -314,8 +328,9 @@
 void CefServerImpl::SendRawData(int connection_id,
                                 const void* data,
                                 size_t data_size) {
-  if (!data || data_size == 0)
+  if (!data || data_size == 0) {
     return;
+  }
   SendRawDataInternal(connection_id, CreateUniqueString(data, data_size));
 }
 
@@ -334,8 +349,9 @@
 void CefServerImpl::SendWebSocketMessage(int connection_id,
                                          const void* data,
                                          size_t data_size) {
-  if (!data || data_size == 0)
+  if (!data || data_size == 0) {
     return;
+  }
   SendWebSocketMessageInternal(connection_id,
                                CreateUniqueString(data, data_size));
 }
@@ -350,18 +366,21 @@
     return;
   }
 
-  if (!ValidateServer())
+  if (!ValidateServer()) {
     return;
+  }
 
   ConnectionInfo* info = GetConnectionInfo(connection_id);
   DCHECK(info);
-  if (!info)
+  if (!info) {
     return;
+  }
 
   DCHECK(info->is_websocket);
   DCHECK(info->is_websocket_pending);
-  if (!info->is_websocket || !info->is_websocket_pending)
+  if (!info->is_websocket || !info->is_websocket_pending) {
     return;
+  }
 
   info->is_websocket_pending = false;
 
@@ -385,12 +404,14 @@
     return;
   }
 
-  if (!ValidateServer())
+  if (!ValidateServer()) {
     return;
+  }
 
   ConnectionInfo* info = GetConnectionInfo(connection_id);
-  if (!info)
+  if (!info) {
     return;
+  }
 
   if (info->is_websocket) {
     LOG(ERROR) << "Invalid attempt to send HTTP response for connection_id "
@@ -411,11 +432,13 @@
     return;
   }
 
-  if (!ValidateServer())
+  if (!ValidateServer()) {
     return;
+  }
 
-  if (!GetConnectionInfo(connection_id))
+  if (!GetConnectionInfo(connection_id)) {
     return;
+  }
 
   server_->SendRaw(connection_id, *data, MISSING_TRAFFIC_ANNOTATION);
 }
@@ -430,12 +453,14 @@
     return;
   }
 
-  if (!ValidateServer())
+  if (!ValidateServer()) {
     return;
+  }
 
   ConnectionInfo* info = GetConnectionInfo(connection_id);
-  if (!info)
+  if (!info) {
     return;
+  }
 
   if (!info->is_websocket || info->is_websocket_pending) {
     LOG(ERROR) << "Invalid attempt to send WebSocket message for connection_id "
@@ -460,8 +485,9 @@
 
   ConnectionInfo* info = GetConnectionInfo(connection_id);
   DCHECK(info);
-  if (!info)
+  if (!info) {
     return;
+  }
 
   DCHECK(!info->is_websocket);
 
@@ -476,8 +502,9 @@
 
   ConnectionInfo* info = GetConnectionInfo(connection_id);
   DCHECK(info);
-  if (!info)
+  if (!info) {
     return;
+  }
 
   DCHECK(!info->is_websocket);
   info->is_websocket = true;
@@ -495,8 +522,9 @@
   CEF_REQUIRE_HT();
 
   ConnectionInfo* info = GetConnectionInfo(connection_id);
-  if (!info)
+  if (!info) {
     return;
+  }
 
   DCHECK(info->is_websocket);
   DCHECK(!info->is_websocket_pending);
@@ -512,7 +540,7 @@
 }
 
 void CefServerImpl::StartOnUIThread(const std::string& address,
-                                    uint16 port,
+                                    uint16_t port,
                                     int backlog) {
   CEF_REQUIRE_UIT();
   DCHECK(!thread_);
@@ -521,7 +549,7 @@
       new base::Thread(base::StringPrintf("%s:%d", address.c_str(), port)));
   base::Thread::Options options;
   options.message_pump_type = base::MessagePumpType::IO;
-  if (thread->StartWithOptions(options)) {
+  if (thread->StartWithOptions(std::move(options))) {
     // Add a reference that will be released in ShutdownOnUIThread().
     AddRef();
 
@@ -534,7 +562,7 @@
 }
 
 void CefServerImpl::StartOnHandlerThread(const std::string& address,
-                                         uint16 port,
+                                         uint16_t port,
                                          int backlog) {
   CEF_REQUIRE_HT();
 
@@ -543,9 +571,10 @@
   if (socket->ListenWithAddressAndPort(address, port, backlog) == net::OK) {
     server_.reset(new net::HttpServer(std::move(socket), this));
 
-    net::IPEndPoint address;
-    if (server_->GetLocalAddress(&address) == net::OK)
-      address_ = address.ToString();
+    net::IPEndPoint ip_address;
+    if (server_->GetLocalAddress(&ip_address) == net::OK) {
+      address_ = ip_address.ToString();
+    }
   }
 
   handler_->OnServerCreated(this);
@@ -595,7 +624,7 @@
   if (thread_) {
     // Stop the handler thread as a background task so the UI thread isn't
     // blocked.
-    CEF_POST_BACKGROUND_TASK(BindOnce(
+    auto task = base::BindOnce(
         [](std::unique_ptr<base::Thread> thread) {
           // Calling PlatformThread::Join() on the UI thread is otherwise
           // disallowed.
@@ -603,7 +632,15 @@
               scoped_allow_sync_primitives;
           thread.reset();
         },
-        std::move(thread_)));
+        std::move(thread_));
+
+    // Make sure the task is executed on shutdown. Otherwise, |thread| might
+    // be released outside of the correct scope.
+    base::ThreadPool::PostTask(
+        FROM_HERE,
+        {base::TaskPriority::BEST_EFFORT,
+         base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()},
+        std::move(task));
 
     // Release the reference that was added in StartupOnUIThread().
     Release();
@@ -640,8 +677,9 @@
   CEF_REQUIRE_HT();
   ConnectionInfoMap::const_iterator it =
       connection_info_map_.find(connection_id);
-  if (it != connection_info_map_.end())
+  if (it != connection_info_map_.end()) {
     return it->second.get();
+  }
 
   LOG(ERROR) << "Invalid connection_id " << connection_id;
   return nullptr;
@@ -651,8 +689,9 @@
   CEF_REQUIRE_HT();
   ConnectionInfoMap::iterator it = connection_info_map_.find(connection_id);
   DCHECK(it != connection_info_map_.end());
-  if (it != connection_info_map_.end())
+  if (it != connection_info_map_.end()) {
     connection_info_map_.erase(it);
+  }
 }
 
 bool CefServerImpl::CurrentlyOnHandlerThread() const {
diff --git a/src/libcef/browser/server_impl.h b/src/libcef/browser/server_impl.h
index 9703f59..693ab78 100644
--- a/src/libcef/browser/server_impl.h
+++ b/src/libcef/browser/server_impl.h
@@ -11,7 +11,7 @@
 
 #include "include/cef_server.h"
 
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
 #include "net/server/http_server.h"
 
 namespace base {
@@ -22,7 +22,10 @@
  public:
   explicit CefServerImpl(CefRefPtr<CefServerHandler> handler);
 
-  void Start(const std::string& address, uint16 port, int backlog);
+  CefServerImpl(const CefServerImpl&) = delete;
+  CefServerImpl& operator=(const CefServerImpl&) = delete;
+
+  void Start(const std::string& address, uint16_t port, int backlog);
 
   // CefServer methods:
   CefRefPtr<CefTaskRunner> GetTaskRunner() override;
@@ -41,7 +44,7 @@
   void SendHttpResponse(int connection_id,
                         int response_code,
                         const CefString& content_type,
-                        int64 content_length,
+                        int64_t content_length,
                         const HeaderMap& extra_headers) override;
   void SendRawData(int connection_id,
                    const void* data,
@@ -74,9 +77,9 @@
   void OnWebSocketMessage(int connection_id, std::string data) override;
   void OnClose(int connection_id) override;
 
-  void StartOnUIThread(const std::string& address, uint16 port, int backlog);
+  void StartOnUIThread(const std::string& address, uint16_t port, int backlog);
   void StartOnHandlerThread(const std::string& address,
-                            uint16 port,
+                            uint16_t port,
                             int backlog);
 
   void ShutdownOnHandlerThread();
@@ -107,7 +110,6 @@
   ConnectionInfoMap connection_info_map_;
 
   IMPLEMENT_REFCOUNTING(CefServerImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefServerImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_SERVER_IMPL_H_
diff --git a/src/libcef/browser/simple_menu_model_impl.cc b/src/libcef/browser/simple_menu_model_impl.cc
new file mode 100644
index 0000000..82de398
--- /dev/null
+++ b/src/libcef/browser/simple_menu_model_impl.cc
@@ -0,0 +1,570 @@
+// Copyright (c) 2021 The Chromium Embedded Framework Authors.
+// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/browser/simple_menu_model_impl.h"
+
+#include <vector>
+
+#include "libcef/browser/thread_util.h"
+#include "libcef/common/task_runner_impl.h"
+
+namespace {
+
+// Value based on the documentation on SimpleMenuModel::GetIndexOfCommandId().
+const int kInvalidIndex = -1;
+const int kInvalidCommandId = -1;
+const int kInvalidGroupId = -1;
+
+cef_menu_item_type_t GetCefItemType(ui::MenuModel::ItemType type) {
+  switch (type) {
+    case ui::MenuModel::TYPE_COMMAND:
+      return MENUITEMTYPE_COMMAND;
+    case ui::MenuModel::TYPE_CHECK:
+      return MENUITEMTYPE_CHECK;
+    case ui::MenuModel::TYPE_RADIO:
+      return MENUITEMTYPE_RADIO;
+    case ui::MenuModel::TYPE_SEPARATOR:
+      return MENUITEMTYPE_SEPARATOR;
+    case ui::MenuModel::TYPE_SUBMENU:
+      return MENUITEMTYPE_SUBMENU;
+    default:
+      return MENUITEMTYPE_NONE;
+  }
+}
+
+}  // namespace
+
+CefSimpleMenuModelImpl::CefSimpleMenuModelImpl(
+    ui::SimpleMenuModel* model,
+    ui::SimpleMenuModel::Delegate* delegate,
+    StateDelegate* state_delegate,
+    bool is_owned,
+    bool is_submenu)
+    : supported_thread_id_(base::PlatformThread::CurrentId()),
+      model_(model),
+      delegate_(delegate),
+      state_delegate_(state_delegate),
+      is_owned_(is_owned),
+      is_submenu_(is_submenu) {
+  DCHECK(model_);
+  DCHECK(delegate_);
+  DCHECK(state_delegate_);
+}
+
+CefSimpleMenuModelImpl::~CefSimpleMenuModelImpl() {
+  // Detach() must be called before object destruction.
+  DCHECK(!model_);
+  DCHECK(submenumap_.empty());
+}
+
+void CefSimpleMenuModelImpl::Detach() {
+  DCHECK(VerifyContext());
+
+  if (!submenumap_.empty()) {
+    auto it = submenumap_.begin();
+    for (; it != submenumap_.end(); ++it) {
+      it->second->Detach();
+    }
+    submenumap_.clear();
+  }
+
+  if (is_owned_) {
+    delete model_;
+  }
+  model_ = nullptr;
+}
+
+bool CefSimpleMenuModelImpl::IsSubMenu() {
+  if (!VerifyContext()) {
+    return false;
+  }
+  return is_submenu_;
+}
+
+bool CefSimpleMenuModelImpl::Clear() {
+  if (!VerifyContext()) {
+    return false;
+  }
+
+  model_->Clear();
+  return true;
+}
+
+size_t CefSimpleMenuModelImpl::GetCount() {
+  if (!VerifyContext()) {
+    return 0;
+  }
+
+  return model_->GetItemCount();
+}
+
+bool CefSimpleMenuModelImpl::AddSeparator() {
+  if (!VerifyContext()) {
+    return false;
+  }
+
+  model_->AddSeparator(ui::NORMAL_SEPARATOR);
+  return true;
+}
+
+bool CefSimpleMenuModelImpl::AddItem(int command_id, const CefString& label) {
+  if (!VerifyContext()) {
+    return false;
+  }
+
+  model_->AddItem(command_id, label);
+  return true;
+}
+
+bool CefSimpleMenuModelImpl::AddCheckItem(int command_id,
+                                          const CefString& label) {
+  if (!VerifyContext()) {
+    return false;
+  }
+
+  model_->AddCheckItem(command_id, label);
+  return true;
+}
+
+bool CefSimpleMenuModelImpl::AddRadioItem(int command_id,
+                                          const CefString& label,
+                                          int group_id) {
+  if (!VerifyContext()) {
+    return false;
+  }
+
+  model_->AddRadioItem(command_id, label, group_id);
+  return true;
+}
+
+CefRefPtr<CefMenuModel> CefSimpleMenuModelImpl::AddSubMenu(
+    int command_id,
+    const CefString& label) {
+  if (!VerifyContext()) {
+    return nullptr;
+  }
+
+  auto new_menu = CreateNewSubMenu(nullptr);
+  model_->AddSubMenu(command_id, label, new_menu->model());
+  return new_menu;
+}
+
+bool CefSimpleMenuModelImpl::InsertSeparatorAt(size_t index) {
+  if (!VerifyContext()) {
+    return false;
+  }
+
+  model_->InsertSeparatorAt(index, ui::NORMAL_SEPARATOR);
+  return true;
+}
+
+bool CefSimpleMenuModelImpl::InsertItemAt(size_t index,
+                                          int command_id,
+                                          const CefString& label) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return false;
+  }
+
+  model_->InsertItemAt(index, command_id, label);
+  return true;
+}
+
+bool CefSimpleMenuModelImpl::InsertCheckItemAt(size_t index,
+                                               int command_id,
+                                               const CefString& label) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return false;
+  }
+
+  model_->InsertCheckItemAt(index, command_id, label);
+  return true;
+}
+
+bool CefSimpleMenuModelImpl::InsertRadioItemAt(size_t index,
+                                               int command_id,
+                                               const CefString& label,
+                                               int group_id) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return false;
+  }
+
+  model_->InsertRadioItemAt(index, command_id, label, group_id);
+  return true;
+}
+
+CefRefPtr<CefMenuModel> CefSimpleMenuModelImpl::InsertSubMenuAt(
+    size_t index,
+    int command_id,
+    const CefString& label) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return nullptr;
+  }
+
+  auto new_menu = CreateNewSubMenu(nullptr);
+  model_->InsertSubMenuAt(index, command_id, label, new_menu->model());
+  return new_menu;
+}
+
+bool CefSimpleMenuModelImpl::Remove(int command_id) {
+  return RemoveAt(GetIndexOf(command_id));
+}
+
+bool CefSimpleMenuModelImpl::RemoveAt(size_t index) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return false;
+  }
+
+  auto* sub_menu =
+      static_cast<ui::SimpleMenuModel*>(model_->GetSubmenuModelAt(index));
+  if (sub_menu) {
+    auto it = submenumap_.find(sub_menu);
+    if (it != submenumap_.end()) {
+      it->second->Detach();
+      submenumap_.erase(it);
+    }
+  }
+
+  model_->RemoveItemAt(index);
+  return true;
+}
+
+int CefSimpleMenuModelImpl::GetIndexOf(int command_id) {
+  if (!VerifyContext()) {
+    return kInvalidIndex;
+  }
+
+  auto index = model_->GetIndexOfCommandId(command_id);
+  if (index.has_value()) {
+    return static_cast<int>(*index);
+  }
+  return -1;
+}
+
+int CefSimpleMenuModelImpl::GetCommandIdAt(size_t index) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return kInvalidCommandId;
+  }
+
+  return model_->GetCommandIdAt(index);
+}
+
+bool CefSimpleMenuModelImpl::SetCommandIdAt(size_t index, int command_id) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+CefString CefSimpleMenuModelImpl::GetLabel(int command_id) {
+  return GetLabelAt(GetIndexOf(command_id));
+}
+
+CefString CefSimpleMenuModelImpl::GetLabelAt(size_t index) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return CefString();
+  }
+
+  return model_->GetLabelAt(index);
+}
+
+bool CefSimpleMenuModelImpl::SetLabel(int command_id, const CefString& label) {
+  return SetLabelAt(GetIndexOf(command_id), label);
+}
+
+bool CefSimpleMenuModelImpl::SetLabelAt(size_t index, const CefString& label) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return false;
+  }
+
+  model_->SetLabel(index, label);
+  return true;
+}
+
+CefSimpleMenuModelImpl::MenuItemType CefSimpleMenuModelImpl::GetType(
+    int command_id) {
+  return GetTypeAt(GetIndexOf(command_id));
+}
+
+CefSimpleMenuModelImpl::MenuItemType CefSimpleMenuModelImpl::GetTypeAt(
+    size_t index) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return MENUITEMTYPE_NONE;
+  }
+
+  return GetCefItemType(model_->GetTypeAt(index));
+}
+
+int CefSimpleMenuModelImpl::GetGroupId(int command_id) {
+  return GetGroupIdAt(GetIndexOf(command_id));
+}
+
+int CefSimpleMenuModelImpl::GetGroupIdAt(size_t index) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return kInvalidGroupId;
+  }
+
+  return model_->GetGroupIdAt(index);
+}
+
+bool CefSimpleMenuModelImpl::SetGroupId(int command_id, int group_id) {
+  return SetGroupIdAt(GetIndexOf(command_id), group_id);
+}
+
+bool CefSimpleMenuModelImpl::SetGroupIdAt(size_t index, int group_id) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+CefRefPtr<CefMenuModel> CefSimpleMenuModelImpl::GetSubMenu(int command_id) {
+  return GetSubMenuAt(GetIndexOf(command_id));
+}
+
+CefRefPtr<CefMenuModel> CefSimpleMenuModelImpl::GetSubMenuAt(size_t index) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return nullptr;
+  }
+
+  auto* sub_model =
+      static_cast<ui::SimpleMenuModel*>(model_->GetSubmenuModelAt(index));
+  auto it = submenumap_.find(sub_model);
+  if (it != submenumap_.end()) {
+    return it->second;
+  }
+  return CreateNewSubMenu(sub_model);
+}
+
+bool CefSimpleMenuModelImpl::IsVisible(int command_id) {
+  return IsVisibleAt(GetIndexOf(command_id));
+}
+
+bool CefSimpleMenuModelImpl::IsVisibleAt(size_t index) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return false;
+  }
+
+  return model_->IsVisibleAt(index);
+}
+
+bool CefSimpleMenuModelImpl::SetVisible(int command_id, bool visible) {
+  return SetVisibleAt(GetIndexOf(command_id), visible);
+}
+
+bool CefSimpleMenuModelImpl::SetVisibleAt(size_t index, bool visible) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return false;
+  }
+
+  model_->SetVisibleAt(index, visible);
+  return true;
+}
+
+bool CefSimpleMenuModelImpl::IsEnabled(int command_id) {
+  return IsEnabledAt(GetIndexOf(command_id));
+}
+
+bool CefSimpleMenuModelImpl::IsEnabledAt(size_t index) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return false;
+  }
+
+  return model_->IsEnabledAt(index);
+}
+
+bool CefSimpleMenuModelImpl::SetEnabled(int command_id, bool enabled) {
+  return SetEnabledAt(GetIndexOf(command_id), enabled);
+}
+
+bool CefSimpleMenuModelImpl::SetEnabledAt(size_t index, bool enabled) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return false;
+  }
+
+  model_->SetEnabledAt(index, enabled);
+  return true;
+}
+
+bool CefSimpleMenuModelImpl::IsChecked(int command_id) {
+  return IsCheckedAt(GetIndexOf(command_id));
+}
+
+bool CefSimpleMenuModelImpl::IsCheckedAt(size_t index) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return false;
+  }
+
+  return model_->IsItemCheckedAt(index);
+}
+
+bool CefSimpleMenuModelImpl::SetChecked(int command_id, bool checked) {
+  if (!VerifyContext() || command_id == kInvalidIndex) {
+    return false;
+  }
+
+  state_delegate_->SetChecked(command_id, checked);
+  return true;
+}
+
+bool CefSimpleMenuModelImpl::SetCheckedAt(size_t index, bool checked) {
+  return SetChecked(GetCommandIdAt(index), checked);
+}
+
+bool CefSimpleMenuModelImpl::HasAccelerator(int command_id) {
+  return HasAcceleratorAt(GetIndexOf(command_id));
+}
+
+bool CefSimpleMenuModelImpl::HasAcceleratorAt(size_t index) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return false;
+  }
+
+  ui::Accelerator accelerator;
+  return model_->GetAcceleratorAt(index, &accelerator);
+}
+
+bool CefSimpleMenuModelImpl::SetAccelerator(int command_id,
+                                            int key_code,
+                                            bool shift_pressed,
+                                            bool ctrl_pressed,
+                                            bool alt_pressed) {
+  if (!VerifyContext() || command_id == kInvalidIndex) {
+    return false;
+  }
+
+  int modifiers = 0;
+  if (shift_pressed) {
+    modifiers |= ui::EF_SHIFT_DOWN;
+  }
+  if (ctrl_pressed) {
+    modifiers |= ui::EF_CONTROL_DOWN;
+  }
+  if (alt_pressed) {
+    modifiers |= ui::EF_ALT_DOWN;
+  }
+
+  state_delegate_->SetAccelerator(
+      command_id,
+      ui::Accelerator(static_cast<ui::KeyboardCode>(key_code), modifiers));
+  return true;
+}
+
+bool CefSimpleMenuModelImpl::SetAcceleratorAt(size_t index,
+                                              int key_code,
+                                              bool shift_pressed,
+                                              bool ctrl_pressed,
+                                              bool alt_pressed) {
+  return SetAccelerator(GetCommandIdAt(index), key_code, shift_pressed,
+                        ctrl_pressed, alt_pressed);
+}
+
+bool CefSimpleMenuModelImpl::RemoveAccelerator(int command_id) {
+  if (!VerifyContext() || command_id == kInvalidIndex) {
+    return false;
+  }
+  state_delegate_->SetAccelerator(command_id, absl::nullopt);
+  return true;
+}
+
+bool CefSimpleMenuModelImpl::RemoveAcceleratorAt(size_t index) {
+  return RemoveAccelerator(GetCommandIdAt(index));
+}
+
+bool CefSimpleMenuModelImpl::GetAccelerator(int command_id,
+                                            int& key_code,
+                                            bool& shift_pressed,
+                                            bool& ctrl_pressed,
+                                            bool& alt_pressed) {
+  return GetAcceleratorAt(GetIndexOf(command_id), key_code, shift_pressed,
+                          ctrl_pressed, alt_pressed);
+}
+
+bool CefSimpleMenuModelImpl::GetAcceleratorAt(size_t index,
+                                              int& key_code,
+                                              bool& shift_pressed,
+                                              bool& ctrl_pressed,
+                                              bool& alt_pressed) {
+  if (!VerifyContext() || !ValidIndex(index)) {
+    return false;
+  }
+
+  ui::Accelerator accel;
+  if (model_->GetAcceleratorAt(index, &accel)) {
+    key_code = accel.key_code();
+    shift_pressed = accel.modifiers() & ui::EF_SHIFT_DOWN;
+    ctrl_pressed = accel.modifiers() & ui::EF_CONTROL_DOWN;
+    alt_pressed = accel.modifiers() & ui::EF_ALT_DOWN;
+    return true;
+  }
+  return false;
+}
+
+bool CefSimpleMenuModelImpl::SetColor(int command_id,
+                                      cef_menu_color_type_t color_type,
+                                      cef_color_t color) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool CefSimpleMenuModelImpl::SetColorAt(int index,
+                                        cef_menu_color_type_t color_type,
+                                        cef_color_t color) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool CefSimpleMenuModelImpl::GetColor(int command_id,
+                                      cef_menu_color_type_t color_type,
+                                      cef_color_t& color) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool CefSimpleMenuModelImpl::GetColorAt(int index,
+                                        cef_menu_color_type_t color_type,
+                                        cef_color_t& color) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool CefSimpleMenuModelImpl::SetFontList(int command_id,
+                                         const CefString& font_list) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool CefSimpleMenuModelImpl::SetFontListAt(int index,
+                                           const CefString& font_list) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool CefSimpleMenuModelImpl::VerifyContext() {
+  if (base::PlatformThread::CurrentId() != supported_thread_id_) {
+    // This object should only be accessed from the thread that created it.
+    DCHECK(false);
+    return false;
+  }
+
+  if (!model_) {
+    return false;
+  }
+
+  return true;
+}
+
+bool CefSimpleMenuModelImpl::ValidIndex(size_t index) {
+  return index < model_->GetItemCount();
+}
+
+CefRefPtr<CefSimpleMenuModelImpl> CefSimpleMenuModelImpl::CreateNewSubMenu(
+    ui::SimpleMenuModel* model) {
+  bool is_owned = false;
+  if (!model) {
+    model = new ui::SimpleMenuModel(delegate_);
+    is_owned = true;
+  }
+
+  CefRefPtr<CefSimpleMenuModelImpl> new_impl = new CefSimpleMenuModelImpl(
+      model, delegate_, state_delegate_, is_owned, /*is_submodel=*/true);
+  submenumap_.insert(std::make_pair(model, new_impl));
+  return new_impl;
+}
diff --git a/src/libcef/browser/simple_menu_model_impl.h b/src/libcef/browser/simple_menu_model_impl.h
new file mode 100644
index 0000000..00f348a
--- /dev/null
+++ b/src/libcef/browser/simple_menu_model_impl.h
@@ -0,0 +1,172 @@
+// Copyright (c) 2021 The Chromium Embedded Framework Authors.
+// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_BROWSER_SIMPLE_MENU_MODEL_IMPL_H_
+#define CEF_LIBCEF_BROWSER_SIMPLE_MENU_MODEL_IMPL_H_
+#pragma once
+
+#include <vector>
+
+#include "include/cef_menu_model.h"
+
+#include "base/threading/platform_thread.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/base/models/simple_menu_model.h"
+
+// Implementation of CefMenuModel that wraps an existing ui::SimpleMenuModel.
+class CefSimpleMenuModelImpl : public CefMenuModel {
+ public:
+  // Interface for setting state using CefMenuModel methods that will later be
+  // retrieved via the ui::SimpleMenuModel::Delegate implementation.
+  class StateDelegate {
+   public:
+    virtual void SetChecked(int command_id, bool checked) = 0;
+    virtual void SetAccelerator(int command_id,
+                                absl::optional<ui::Accelerator> accel) = 0;
+
+   protected:
+    virtual ~StateDelegate() {}
+  };
+
+  // |delegate| should be the same that was used to create |model|.
+  // If |is_owned| is true then |model| will be deleted on Detach().
+  CefSimpleMenuModelImpl(ui::SimpleMenuModel* model,
+                         ui::SimpleMenuModel::Delegate* delegate,
+                         StateDelegate* state_delegate,
+                         bool is_owned,
+                         bool is_submenu);
+
+  CefSimpleMenuModelImpl(const CefSimpleMenuModelImpl&) = delete;
+  CefSimpleMenuModelImpl& operator=(const CefSimpleMenuModelImpl&) = delete;
+
+  ~CefSimpleMenuModelImpl() override;
+
+  // Must be called before the object is deleted.
+  void Detach();
+
+  // CefMenuModel methods.
+  bool IsSubMenu() override;
+  bool Clear() override;
+  size_t GetCount() override;
+  bool AddSeparator() override;
+  bool AddItem(int command_id, const CefString& label) override;
+  bool AddCheckItem(int command_id, const CefString& label) override;
+  bool AddRadioItem(int command_id,
+                    const CefString& label,
+                    int group_id) override;
+  CefRefPtr<CefMenuModel> AddSubMenu(int command_id,
+                                     const CefString& label) override;
+  bool InsertSeparatorAt(size_t index) override;
+  bool InsertItemAt(size_t index,
+                    int command_id,
+                    const CefString& label) override;
+  bool InsertCheckItemAt(size_t index,
+                         int command_id,
+                         const CefString& label) override;
+  bool InsertRadioItemAt(size_t index,
+                         int command_id,
+                         const CefString& label,
+                         int group_id) override;
+  CefRefPtr<CefMenuModel> InsertSubMenuAt(size_t index,
+                                          int command_id,
+                                          const CefString& label) override;
+  bool Remove(int command_id) override;
+  bool RemoveAt(size_t index) override;
+  int GetIndexOf(int command_id) override;
+  int GetCommandIdAt(size_t index) override;
+  bool SetCommandIdAt(size_t index, int command_id) override;
+  CefString GetLabel(int command_id) override;
+  CefString GetLabelAt(size_t index) override;
+  bool SetLabel(int command_id, const CefString& label) override;
+  bool SetLabelAt(size_t index, const CefString& label) override;
+  MenuItemType GetType(int command_id) override;
+  MenuItemType GetTypeAt(size_t index) override;
+  int GetGroupId(int command_id) override;
+  int GetGroupIdAt(size_t index) override;
+  bool SetGroupId(int command_id, int group_id) override;
+  bool SetGroupIdAt(size_t index, int group_id) override;
+  CefRefPtr<CefMenuModel> GetSubMenu(int command_id) override;
+  CefRefPtr<CefMenuModel> GetSubMenuAt(size_t index) override;
+  bool IsVisible(int command_id) override;
+  bool IsVisibleAt(size_t index) override;
+  bool SetVisible(int command_id, bool visible) override;
+  bool SetVisibleAt(size_t index, bool visible) override;
+  bool IsEnabled(int command_id) override;
+  bool IsEnabledAt(size_t index) override;
+  bool SetEnabled(int command_id, bool enabled) override;
+  bool SetEnabledAt(size_t index, bool enabled) override;
+  bool IsChecked(int command_id) override;
+  bool IsCheckedAt(size_t index) override;
+  bool SetChecked(int command_id, bool checked) override;
+  bool SetCheckedAt(size_t index, bool checked) override;
+  bool HasAccelerator(int command_id) override;
+  bool HasAcceleratorAt(size_t index) override;
+  bool SetAccelerator(int command_id,
+                      int key_code,
+                      bool shift_pressed,
+                      bool ctrl_pressed,
+                      bool alt_pressed) override;
+  bool SetAcceleratorAt(size_t index,
+                        int key_code,
+                        bool shift_pressed,
+                        bool ctrl_pressed,
+                        bool alt_pressed) override;
+  bool RemoveAccelerator(int command_id) override;
+  bool RemoveAcceleratorAt(size_t index) override;
+  bool GetAccelerator(int command_id,
+                      int& key_code,
+                      bool& shift_pressed,
+                      bool& ctrl_pressed,
+                      bool& alt_pressed) override;
+  bool GetAcceleratorAt(size_t index,
+                        int& key_code,
+                        bool& shift_pressed,
+                        bool& ctrl_pressed,
+                        bool& alt_pressed) override;
+  bool SetColor(int command_id,
+                cef_menu_color_type_t color_type,
+                cef_color_t color) override;
+  bool SetColorAt(int index,
+                  cef_menu_color_type_t color_type,
+                  cef_color_t color) override;
+  bool GetColor(int command_id,
+                cef_menu_color_type_t color_type,
+                cef_color_t& color) override;
+  bool GetColorAt(int index,
+                  cef_menu_color_type_t color_type,
+                  cef_color_t& color) override;
+  bool SetFontList(int command_id, const CefString& font_list) override;
+  bool SetFontListAt(int index, const CefString& font_list) override;
+
+  ui::SimpleMenuModel* model() const { return model_; }
+
+ private:
+  // Verify that the object is attached and being accessed from the correct
+  // thread.
+  bool VerifyContext();
+
+  // Returns true if |index| is valid.
+  bool ValidIndex(size_t index);
+
+  CefRefPtr<CefSimpleMenuModelImpl> CreateNewSubMenu(
+      ui::SimpleMenuModel* model);
+
+  base::PlatformThreadId supported_thread_id_;
+
+  ui::SimpleMenuModel* model_;
+  ui::SimpleMenuModel::Delegate* const delegate_;
+  StateDelegate* const state_delegate_;
+  const bool is_owned_;
+  const bool is_submenu_;
+
+  // Keep the submenus alive until they're removed, or we're destroyed.
+  using SubMenuMap =
+      std::map<ui::SimpleMenuModel*, CefRefPtr<CefSimpleMenuModelImpl>>;
+  SubMenuMap submenumap_;
+
+  IMPLEMENT_REFCOUNTING(CefSimpleMenuModelImpl);
+};
+
+#endif  // CEF_LIBCEF_BROWSER_SIMPLE_MENU_MODEL_IMPL_H_
diff --git a/src/libcef/browser/speech_recognition_manager_delegate.cc b/src/libcef/browser/speech_recognition_manager_delegate.cc
index 206a329..1a7c669 100644
--- a/src/libcef/browser/speech_recognition_manager_delegate.cc
+++ b/src/libcef/browser/speech_recognition_manager_delegate.cc
@@ -7,11 +7,11 @@
 #include <set>
 #include <string>
 
+#include "libcef/browser/thread_util.h"
 #include "libcef/common/cef_switches.h"
 
-#include "base/bind.h"
 #include "base/command_line.h"
-#include "base/task/post_task.h"
+#include "base/functional/bind.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_observer.h"
@@ -76,8 +76,7 @@
   // Make sure that initiators properly set the |render_process_id| field.
   DCHECK_NE(context.render_process_id, 0);
 
-  base::PostTask(FROM_HERE, {content::BrowserThread::IO},
-                 base::BindOnce(std::move(callback), false, true));
+  CEF_POST_TASK(CEF_IOT, base::BindOnce(std::move(callback), false, true));
 }
 
 content::SpeechRecognitionEventListener*
diff --git a/src/libcef/browser/speech_recognition_manager_delegate.h b/src/libcef/browser/speech_recognition_manager_delegate.h
index 9327818..4897495 100644
--- a/src/libcef/browser/speech_recognition_manager_delegate.h
+++ b/src/libcef/browser/speech_recognition_manager_delegate.h
@@ -5,7 +5,6 @@
 #ifndef CEF_LIBCEF_BROWSER_SPEECH_RECOGNITION_MANAGER_DELEGATE_H_
 #define CEF_LIBCEF_BROWSER_SPEECH_RECOGNITION_MANAGER_DELEGATE_H_
 
-#include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
 #include "content/public/browser/speech_recognition_event_listener.h"
 #include "content/public/browser/speech_recognition_manager_delegate.h"
@@ -18,6 +17,12 @@
       public content::SpeechRecognitionEventListener {
  public:
   CefSpeechRecognitionManagerDelegate();
+
+  CefSpeechRecognitionManagerDelegate(
+      const CefSpeechRecognitionManagerDelegate&) = delete;
+  CefSpeechRecognitionManagerDelegate& operator=(
+      const CefSpeechRecognitionManagerDelegate&) = delete;
+
   ~CefSpeechRecognitionManagerDelegate() override;
 
  protected:
@@ -50,8 +55,6 @@
 
  private:
   bool filter_profanities_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefSpeechRecognitionManagerDelegate);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_SPEECH_RECOGNITION_MANAGER_DELEGATE_H_
diff --git a/src/libcef/browser/ssl_host_state_delegate.cc b/src/libcef/browser/ssl_host_state_delegate.cc
index a7f037a..9abf2e6 100644
--- a/src/libcef/browser/ssl_host_state_delegate.cc
+++ b/src/libcef/browser/ssl_host_state_delegate.cc
@@ -4,7 +4,7 @@
 
 #include "libcef/browser/ssl_host_state_delegate.h"
 
-#include "base/callback.h"
+#include "base/functional/callback.h"
 #include "net/base/hash_value.h"
 
 using content::SSLHostStateDelegate;
@@ -55,10 +55,40 @@
   return false;
 }
 
-void CefSSLHostStateDelegate::AllowCert(const std::string& host,
-                                        const net::X509Certificate& cert,
-                                        int error,
-                                        content::WebContents* web_contents) {
+void CefSSLHostStateDelegate::AllowHttpForHost(
+    const std::string& host,
+    content::StoragePartition* storage_partition) {
+  // Intentional no-op.
+}
+
+bool CefSSLHostStateDelegate::IsHttpAllowedForHost(
+    const std::string& host,
+    content::StoragePartition* storage_partition) {
+  // Intentional no-op. Return value does not matter as HTTPS-Only Mode is not
+  // enabled.
+  return false;
+}
+
+void CefSSLHostStateDelegate::SetHttpsEnforcementForHost(
+    const std::string& host,
+    bool enforce,
+    content::StoragePartition* storage_partition) {
+  // Intentional no-op.
+}
+
+bool CefSSLHostStateDelegate::IsHttpsEnforcedForHost(
+    const std::string& host,
+    content::StoragePartition* storage_partition) {
+  // Intentional no-op. Return value does not matter as HTTPS-First Mode is not
+  // enabled.
+  return false;
+}
+
+void CefSSLHostStateDelegate::AllowCert(
+    const std::string& host,
+    const net::X509Certificate& cert,
+    int error,
+    content::StoragePartition* storage_partition) {
   cert_policy_for_host_[host].Allow(cert, error);
 }
 
@@ -73,8 +103,9 @@
        it != cert_policy_for_host_.end();) {
     auto next_it = std::next(it);
 
-    if (host_filter.Run(it->first))
+    if (host_filter.Run(it->first)) {
       cert_policy_for_host_.erase(it);
+    }
 
     it = next_it;
   }
@@ -84,7 +115,7 @@
     const std::string& host,
     const net::X509Certificate& cert,
     int error,
-    content::WebContents* web_contents) {
+    content::StoragePartition* storage_partition) {
   return cert_policy_for_host_[host].Check(cert, error)
              ? SSLHostStateDelegate::ALLOWED
              : SSLHostStateDelegate::DENIED;
@@ -97,8 +128,18 @@
 
 bool CefSSLHostStateDelegate::HasAllowException(
     const std::string& host,
-    content::WebContents* web_contents) {
+    content::StoragePartition* storage_partition) {
   auto policy_iterator = cert_policy_for_host_.find(host);
   return policy_iterator != cert_policy_for_host_.end() &&
          policy_iterator->second.HasAllowException();
 }
+
+bool CefSSLHostStateDelegate::HasAllowExceptionForAnyHost(
+    content::StoragePartition* storage_partition) {
+  for (auto const& it : cert_policy_for_host_) {
+    if (it.second.HasAllowException()) {
+      return true;
+    }
+  }
+  return false;
+}
diff --git a/src/libcef/browser/ssl_host_state_delegate.h b/src/libcef/browser/ssl_host_state_delegate.h
index 3085c6e..7827938 100644
--- a/src/libcef/browser/ssl_host_state_delegate.h
+++ b/src/libcef/browser/ssl_host_state_delegate.h
@@ -44,35 +44,51 @@
 class CefSSLHostStateDelegate : public content::SSLHostStateDelegate {
  public:
   CefSSLHostStateDelegate();
+
+  CefSSLHostStateDelegate(const CefSSLHostStateDelegate&) = delete;
+  CefSSLHostStateDelegate& operator=(const CefSSLHostStateDelegate&) = delete;
+
   ~CefSSLHostStateDelegate() override;
 
   // SSLHostStateDelegate methods:
   void AllowCert(const std::string& host,
                  const net::X509Certificate& cert,
                  int error,
-                 content::WebContents* web_contents) override;
+                 content::StoragePartition* storage_partition) override;
   void Clear(const base::RepeatingCallback<bool(const std::string&)>
                  host_filter) override;
   content::SSLHostStateDelegate::CertJudgment QueryPolicy(
       const std::string& host,
       const net::X509Certificate& cert,
       int error,
-      content::WebContents* web_contents) override;
+      content::StoragePartition* storage_partition) override;
   void HostRanInsecureContent(const std::string& host,
                               int child_id,
                               InsecureContentType content_type) override;
   bool DidHostRunInsecureContent(const std::string& host,
                                  int child_id,
                                  InsecureContentType content_type) override;
+  void AllowHttpForHost(const std::string& host,
+                        content::StoragePartition* storage_partition) override;
+  bool IsHttpAllowedForHost(
+      const std::string& host,
+      content::StoragePartition* storage_partition) override;
+  void SetHttpsEnforcementForHost(
+      const std::string& host,
+      bool enforce,
+      content::StoragePartition* storage_partition) override;
+  bool IsHttpsEnforcedForHost(
+      const std::string& host,
+      content::StoragePartition* storage_partition) override;
   void RevokeUserAllowExceptions(const std::string& host) override;
   bool HasAllowException(const std::string& host,
-                         content::WebContents* web_contents) override;
+                         content::StoragePartition* storage_partition) override;
+  bool HasAllowExceptionForAnyHost(
+      content::StoragePartition* storage_partition) override;
 
  private:
   // Certificate policies for each host.
   std::map<std::string, internal::CertPolicy> cert_policy_for_host_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefSSLHostStateDelegate);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_SSL_HOST_STATE_DELEGATE_H_
diff --git a/src/libcef/browser/ssl_info_impl.h b/src/libcef/browser/ssl_info_impl.h
index f1a9124..2179a0f 100644
--- a/src/libcef/browser/ssl_info_impl.h
+++ b/src/libcef/browser/ssl_info_impl.h
@@ -15,6 +15,9 @@
  public:
   explicit CefSSLInfoImpl(const net::SSLInfo& value);
 
+  CefSSLInfoImpl(const CefSSLInfoImpl&) = delete;
+  CefSSLInfoImpl& operator=(const CefSSLInfoImpl&) = delete;
+
   // CefSSLInfo methods.
   cef_cert_status_t GetCertStatus() override;
   CefRefPtr<CefX509Certificate> GetX509Certificate() override;
@@ -24,7 +27,6 @@
   CefRefPtr<CefX509Certificate> cert_;
 
   IMPLEMENT_REFCOUNTING(CefSSLInfoImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefSSLInfoImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_SSL_INFO_IMPL_H_
diff --git a/src/libcef/browser/ssl_status_impl.cc b/src/libcef/browser/ssl_status_impl.cc
index 4330c70..f119bfa 100644
--- a/src/libcef/browser/ssl_status_impl.cc
+++ b/src/libcef/browser/ssl_status_impl.cc
@@ -33,7 +33,8 @@
 }
 
 CefRefPtr<CefX509Certificate> CefSSLStatusImpl::GetX509Certificate() {
-  if (certificate_ && !cef_certificate_)
+  if (certificate_ && !cef_certificate_) {
     cef_certificate_ = new CefX509CertificateImpl(certificate_);
+  }
   return cef_certificate_;
 }
diff --git a/src/libcef/browser/ssl_status_impl.h b/src/libcef/browser/ssl_status_impl.h
index cd07060..43ef322 100644
--- a/src/libcef/browser/ssl_status_impl.h
+++ b/src/libcef/browser/ssl_status_impl.h
@@ -15,6 +15,9 @@
  public:
   explicit CefSSLStatusImpl(const content::SSLStatus& value);
 
+  CefSSLStatusImpl(const CefSSLStatusImpl&) = delete;
+  CefSSLStatusImpl& operator=(const CefSSLStatusImpl&) = delete;
+
   // CefSSLStatus methods.
   bool IsSecureConnection() override;
   cef_cert_status_t GetCertStatus() override;
@@ -32,7 +35,6 @@
   CefRefPtr<CefX509Certificate> cef_certificate_;
 
   IMPLEMENT_REFCOUNTING(CefSSLStatusImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefSSLStatusImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_SSL_STATUS_IMPL_H_
diff --git a/src/libcef/browser/stream_impl.cc b/src/libcef/browser/stream_impl.cc
index 6672047..0244a93 100644
--- a/src/libcef/browser/stream_impl.cc
+++ b/src/libcef/browser/stream_impl.cc
@@ -15,12 +15,13 @@
   DCHECK(!fileName.empty());
 
   // TODO(cef): Do not allow file IO on all threads (issue #1187).
-  base::ThreadRestrictions::ScopedAllowIO allow_io;
+  base::ScopedAllowBlockingForTesting allow_blocking;
 
   CefRefPtr<CefStreamReader> reader;
   FILE* file = base::OpenFile(base::FilePath(fileName), "rb");
-  if (file)
+  if (file) {
     reader = new CefFileReader(file, true);
+  }
   return reader;
 }
 
@@ -29,8 +30,9 @@
   DCHECK(data != nullptr);
   DCHECK(size > 0);
   CefRefPtr<CefStreamReader> reader;
-  if (data && size > 0)
+  if (data && size > 0) {
     reader = new CefBytesReader(data, size, true);
+  }
   return reader;
 }
 
@@ -38,8 +40,9 @@
     CefRefPtr<CefReadHandler> handler) {
   DCHECK(handler.get());
   CefRefPtr<CefStreamReader> reader;
-  if (handler.get())
+  if (handler.get()) {
     reader = new CefHandlerReader(handler);
+  }
   return reader;
 }
 
@@ -48,12 +51,13 @@
   DCHECK(!fileName.empty());
 
   // TODO(cef): Do not allow file IO on all threads (issue #1187).
-  base::ThreadRestrictions::ScopedAllowIO allow_io;
+  base::ScopedAllowBlockingForTesting allow_blocking;
 
   CefRefPtr<CefStreamWriter> writer;
   FILE* file = base::OpenFile(base::FilePath(fileName), "wb");
-  if (file)
+  if (file) {
     writer = new CefFileWriter(file, true);
+  }
   return writer;
 }
 
@@ -61,8 +65,9 @@
     CefRefPtr<CefWriteHandler> handler) {
   DCHECK(handler.get());
   CefRefPtr<CefStreamWriter> writer;
-  if (handler.get())
+  if (handler.get()) {
     writer = new CefHandlerWriter(handler);
+  }
   return writer;
 }
 
@@ -73,8 +78,9 @@
 
 CefFileReader::~CefFileReader() {
   base::AutoLock lock_scope(lock_);
-  if (close_)
+  if (close_) {
     base::CloseFile(file_);
+  }
 }
 
 size_t CefFileReader::Read(void* ptr, size_t size, size_t n) {
@@ -82,18 +88,18 @@
   return fread(ptr, size, n, file_);
 }
 
-int CefFileReader::Seek(int64 offset, int whence) {
+int CefFileReader::Seek(int64_t offset, int whence) {
   base::AutoLock lock_scope(lock_);
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   return _fseeki64(file_, offset, whence);
 #else
   return fseek(file_, offset, whence);
 #endif
 }
 
-int64 CefFileReader::Tell() {
+int64_t CefFileReader::Tell() {
   base::AutoLock lock_scope(lock_);
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   return _ftelli64(file_);
 #else
   return ftell(file_);
@@ -112,8 +118,9 @@
 
 CefFileWriter::~CefFileWriter() {
   base::AutoLock lock_scope(lock_);
-  if (close_)
+  if (close_) {
     base::CloseFile(file_);
+  }
 }
 
 size_t CefFileWriter::Write(const void* ptr, size_t size, size_t n) {
@@ -121,12 +128,12 @@
   return (size_t)fwrite(ptr, size, n, file_);
 }
 
-int CefFileWriter::Seek(int64 offset, int whence) {
+int CefFileWriter::Seek(int64_t offset, int whence) {
   base::AutoLock lock_scope(lock_);
   return fseek(file_, offset, whence);
 }
 
-int64 CefFileWriter::Tell() {
+int64_t CefFileWriter::Tell() {
   base::AutoLock lock_scope(lock_);
   return ftell(file_);
 }
@@ -138,7 +145,7 @@
 
 // CefBytesReader
 
-CefBytesReader::CefBytesReader(void* data, int64 datasize, bool copy)
+CefBytesReader::CefBytesReader(void* data, int64_t datasize, bool copy)
     : data_(nullptr), datasize_(0), copy_(false), offset_(0) {
   SetData(data, datasize, copy);
 }
@@ -156,27 +163,30 @@
   return ret;
 }
 
-int CefBytesReader::Seek(int64 offset, int whence) {
+int CefBytesReader::Seek(int64_t offset, int whence) {
   int rv = -1L;
   base::AutoLock lock_scope(lock_);
   switch (whence) {
     case SEEK_CUR:
-      if (offset_ + offset > datasize_ || offset_ + offset < 0)
+      if (offset_ + offset > datasize_ || offset_ + offset < 0) {
         break;
+      }
       offset_ += offset;
       rv = 0;
       break;
     case SEEK_END: {
-      int64 offset_abs = std::abs(offset);
-      if (offset_abs > datasize_)
+      int64_t offset_abs = std::abs(offset);
+      if (offset_abs > datasize_) {
         break;
+      }
       offset_ = datasize_ - offset_abs;
       rv = 0;
       break;
     }
     case SEEK_SET:
-      if (offset > datasize_ || offset < 0)
+      if (offset > datasize_ || offset < 0) {
         break;
+      }
       offset_ = offset;
       rv = 0;
       break;
@@ -185,7 +195,7 @@
   return rv;
 }
 
-int64 CefBytesReader::Tell() {
+int64_t CefBytesReader::Tell() {
   base::AutoLock lock_scope(lock_);
   return offset_;
 }
@@ -195,10 +205,11 @@
   return (offset_ >= datasize_);
 }
 
-void CefBytesReader::SetData(void* data, int64 datasize, bool copy) {
+void CefBytesReader::SetData(void* data, int64_t datasize, bool copy) {
   base::AutoLock lock_scope(lock_);
-  if (copy_)
+  if (copy_) {
     free(data_);
+  }
 
   copy_ = copy;
   offset_ = 0;
@@ -207,8 +218,9 @@
   if (copy) {
     data_ = malloc(datasize);
     DCHECK(data_ != nullptr);
-    if (data_)
+    if (data_) {
       memcpy(data_, data, datasize);
+    }
   } else {
     data_ = data;
   }
@@ -225,14 +237,15 @@
 
 CefBytesWriter::~CefBytesWriter() {
   base::AutoLock lock_scope(lock_);
-  if (data_)
+  if (data_) {
     free(data_);
+  }
 }
 
 size_t CefBytesWriter::Write(const void* ptr, size_t size, size_t n) {
   base::AutoLock lock_scope(lock_);
   size_t rv;
-  if (offset_ + static_cast<int64>(size * n) >= datasize_ &&
+  if (offset_ + static_cast<int64_t>(size * n) >= datasize_ &&
       Grow(size * n) == 0) {
     rv = 0;
   } else {
@@ -244,27 +257,30 @@
   return rv;
 }
 
-int CefBytesWriter::Seek(int64 offset, int whence) {
+int CefBytesWriter::Seek(int64_t offset, int whence) {
   int rv = -1L;
   base::AutoLock lock_scope(lock_);
   switch (whence) {
     case SEEK_CUR:
-      if (offset_ + offset > datasize_ || offset_ + offset < 0)
+      if (offset_ + offset > datasize_ || offset_ + offset < 0) {
         break;
+      }
       offset_ += offset;
       rv = 0;
       break;
     case SEEK_END: {
-      int64 offset_abs = std::abs(offset);
-      if (offset_abs > datasize_)
+      int64_t offset_abs = std::abs(offset);
+      if (offset_abs > datasize_) {
         break;
+      }
       offset_ = datasize_ - offset_abs;
       rv = 0;
       break;
     }
     case SEEK_SET:
-      if (offset > datasize_ || offset < 0)
+      if (offset > datasize_ || offset < 0) {
         break;
+      }
       offset_ = offset;
       rv = 0;
       break;
@@ -273,7 +289,7 @@
   return rv;
 }
 
-int64 CefBytesWriter::Tell() {
+int64_t CefBytesWriter::Tell() {
   base::AutoLock lock_scope(lock_);
   return offset_;
 }
diff --git a/src/libcef/browser/stream_impl.h b/src/libcef/browser/stream_impl.h
index dde3d60..d2a11ce 100644
--- a/src/libcef/browser/stream_impl.h
+++ b/src/libcef/browser/stream_impl.h
@@ -20,8 +20,8 @@
   ~CefFileReader() override;
 
   size_t Read(void* ptr, size_t size, size_t n) override;
-  int Seek(int64 offset, int whence) override;
-  int64 Tell() override;
+  int Seek(int64_t offset, int whence) override;
+  int64_t Tell() override;
   int Eof() override;
   bool MayBlock() override { return true; }
 
@@ -41,8 +41,8 @@
   ~CefFileWriter() override;
 
   size_t Write(const void* ptr, size_t size, size_t n) override;
-  int Seek(int64 offset, int whence) override;
-  int64 Tell() override;
+  int Seek(int64_t offset, int whence) override;
+  int64_t Tell() override;
   int Flush() override;
   bool MayBlock() override { return true; }
 
@@ -58,25 +58,25 @@
 // Implementation of CefStreamReader for byte buffers.
 class CefBytesReader : public CefStreamReader {
  public:
-  CefBytesReader(void* data, int64 datasize, bool copy);
+  CefBytesReader(void* data, int64_t datasize, bool copy);
   ~CefBytesReader() override;
 
   size_t Read(void* ptr, size_t size, size_t n) override;
-  int Seek(int64 offset, int whence) override;
-  int64 Tell() override;
+  int Seek(int64_t offset, int whence) override;
+  int64_t Tell() override;
   int Eof() override;
   bool MayBlock() override { return false; }
 
-  void SetData(void* data, int64 datasize, bool copy);
+  void SetData(void* data, int64_t datasize, bool copy);
 
   void* GetData() { return data_; }
   size_t GetDataSize() { return offset_; }
 
  protected:
   void* data_;
-  int64 datasize_;
+  int64_t datasize_;
   bool copy_;
-  int64 offset_;
+  int64_t offset_;
 
   base::Lock lock_;
 
@@ -90,13 +90,13 @@
   ~CefBytesWriter() override;
 
   size_t Write(const void* ptr, size_t size, size_t n) override;
-  int Seek(int64 offset, int whence) override;
-  int64 Tell() override;
+  int Seek(int64_t offset, int whence) override;
+  int64_t Tell() override;
   int Flush() override;
   bool MayBlock() override { return false; }
 
   void* GetData() { return data_; }
-  int64 GetDataSize() { return offset_; }
+  int64_t GetDataSize() { return offset_; }
   std::string GetDataString();
 
  protected:
@@ -104,8 +104,8 @@
 
   size_t grow_;
   void* data_;
-  int64 datasize_;
-  int64 offset_;
+  int64_t datasize_;
+  int64_t offset_;
 
   base::Lock lock_;
 
@@ -121,10 +121,10 @@
   size_t Read(void* ptr, size_t size, size_t n) override {
     return handler_->Read(ptr, size, n);
   }
-  int Seek(int64 offset, int whence) override {
+  int Seek(int64_t offset, int whence) override {
     return handler_->Seek(offset, whence);
   }
-  int64 Tell() override { return handler_->Tell(); }
+  int64_t Tell() override { return handler_->Tell(); }
   int Eof() override { return handler_->Eof(); }
   bool MayBlock() override { return handler_->MayBlock(); }
 
@@ -143,10 +143,10 @@
   size_t Write(const void* ptr, size_t size, size_t n) override {
     return handler_->Write(ptr, size, n);
   }
-  int Seek(int64 offset, int whence) override {
+  int Seek(int64_t offset, int whence) override {
     return handler_->Seek(offset, whence);
   }
-  int64 Tell() override { return handler_->Tell(); }
+  int64_t Tell() override { return handler_->Tell(); }
   int Flush() override { return handler_->Flush(); }
   bool MayBlock() override { return handler_->MayBlock(); }
 
diff --git a/src/libcef/browser/test/test_helpers_impl.cc b/src/libcef/browser/test/test_helpers_impl.cc
new file mode 100644
index 0000000..1e0ea9c
--- /dev/null
+++ b/src/libcef/browser/test/test_helpers_impl.cc
@@ -0,0 +1,14 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "include/test/cef_test_helpers.h"
+
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+
+void CefSetDataDirectoryForTests(const CefString& dir) {
+  base::PathService::OverrideAndCreateIfNeeded(
+      base::DIR_SRC_TEST_DATA_ROOT, base::FilePath(dir), /*is_absolute=*/true,
+      /*create=*/false);
+}
diff --git a/src/libcef/browser/test/test_server_impl.cc b/src/libcef/browser/test/test_server_impl.cc
new file mode 100644
index 0000000..7a10f4e
--- /dev/null
+++ b/src/libcef/browser/test/test_server_impl.cc
@@ -0,0 +1,293 @@
+// Copyright 2022 The Chromium Embedded Framework 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 "libcef/browser/test/test_server_impl.h"
+
+#include "libcef/common/net/http_header_utils.h"
+
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "base/task/single_thread_task_runner.h"
+#include "base/threading/thread_checker.h"
+#include "net/http/http_request_headers.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_response.h"
+
+using namespace net::test_server;
+
+namespace {
+
+class CefTestServerConnectionImpl : public CefTestServerConnection {
+ public:
+  explicit CefTestServerConnectionImpl(
+      base::WeakPtr<HttpResponseDelegate> delegate)
+      : delegate_(delegate),
+        task_runner_(base::SingleThreadTaskRunner::GetCurrentDefault()) {
+    DCHECK(delegate_);
+    DCHECK(task_runner_);
+  }
+
+  void SendHttp200Response(const CefString& content_type,
+                           const void* data,
+                           size_t data_size) override {
+    auto response = std::make_unique<BasicHttpResponse>();
+    response->set_code(net::HTTP_OK);
+    response->set_content_type(base::StringPiece(content_type.ToString()));
+    response->set_content(
+        base::StringPiece(reinterpret_cast<const char*>(data), data_size));
+    SendBasicHttpResponse(std::move(response));
+  }
+
+  void SendHttp404Response() override {
+    auto response = std::make_unique<BasicHttpResponse>();
+    response->set_code(net::HTTP_NOT_FOUND);
+    SendBasicHttpResponse(std::move(response));
+  }
+
+  void SendHttp500Response(const CefString& error_message) override {
+    auto response = std::make_unique<BasicHttpResponse>();
+    response->set_code(net::HTTP_INTERNAL_SERVER_ERROR);
+    response->set_content_type(base::StringPiece("text/html"));
+    response->set_content(base::StringPiece(error_message.ToString()));
+    SendBasicHttpResponse(std::move(response));
+  }
+
+  void SendHttpResponse(int response_code,
+                        const CefString& content_type,
+                        const void* data,
+                        size_t data_size,
+                        const HeaderMap& extra_headers) override {
+    auto response = std::make_unique<BasicHttpResponse>();
+    response->set_code(static_cast<net::HttpStatusCode>(response_code));
+    response->set_content_type(base::StringPiece(content_type.ToString()));
+    response->set_content(
+        base::StringPiece(reinterpret_cast<const char*>(data), data_size));
+    for (const auto& [key, value] : extra_headers) {
+      response->AddCustomHeader(key.ToString(), value.ToString());
+    }
+    SendBasicHttpResponse(std::move(response));
+  }
+
+ private:
+  void SendBasicHttpResponse(std::unique_ptr<BasicHttpResponse> response) {
+    if (!task_runner_->BelongsToCurrentThread()) {
+      task_runner_->PostTask(
+          FROM_HERE,
+          base::BindOnce(&CefTestServerConnectionImpl::SendBasicHttpResponse,
+                         this, std::move(response)));
+      return;
+    }
+
+    if (delegate_) {
+      response->SendResponse(delegate_);
+    }
+  }
+
+  base::WeakPtr<HttpResponseDelegate> delegate_;
+  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+  IMPLEMENT_REFCOUNTING(CefTestServerConnectionImpl);
+};
+
+class CefHttpResponse : public HttpResponse {
+ public:
+  CefHttpResponse(CefRefPtr<CefTestServer> server,
+                  CefRefPtr<CefTestServerHandler> handler,
+                  CefRefPtr<CefRequest> request)
+      : server_(server), handler_(handler), request_(request) {
+    DCHECK(server_);
+    DCHECK(handler_);
+    DCHECK(request_);
+  }
+
+  CefHttpResponse(const CefHttpResponse&) = delete;
+  CefHttpResponse& operator=(const CefHttpResponse&) = delete;
+
+  void SendResponse(base::WeakPtr<HttpResponseDelegate> delegate) override {
+    CefRefPtr<CefTestServerConnectionImpl> connection(
+        new CefTestServerConnectionImpl(delegate));
+    const bool handled =
+        handler_->OnTestServerRequest(server_, request_, connection.get());
+    if (handled) {
+      return;
+    }
+
+    LOG(WARNING) << "Request not handled. Returning 404: "
+                 << request_->GetURL().ToString();
+    connection->SendHttp404Response();
+  }
+
+ private:
+  CefRefPtr<CefTestServer> server_;
+  CefRefPtr<CefTestServerHandler> handler_;
+  CefRefPtr<CefRequest> request_;
+};
+
+CefRefPtr<CefRequest> CreateCefRequest(const HttpRequest& request) {
+  CefRefPtr<CefPostData> post_data;
+  if (!request.content.empty()) {
+    post_data = CefPostData::Create();
+    auto element = CefPostDataElement::Create();
+    element->SetToBytes(request.content.size(), request.content.c_str());
+    post_data->AddElement(element);
+  }
+
+  CefRequest::HeaderMap header_map;
+  CefString referer;
+
+  HttpHeaderUtils::ParseHeaders(request.all_headers, header_map);
+
+  // CefRequest will strip the Referer header from the map, so we don't need to
+  // do that here.
+  for (const auto& [key, value] : header_map) {
+    if (base::EqualsCaseInsensitiveASCII(key.ToString(),
+                                         net::HttpRequestHeaders::kReferer)) {
+      referer = value;
+    }
+  }
+
+  auto cef_request = CefRequest::Create();
+  cef_request->Set(request.GetURL().spec(), request.method_string, post_data,
+                   header_map);
+  if (!referer.empty()) {
+    cef_request->SetReferrer(referer, REFERRER_POLICY_DEFAULT);
+  }
+  return cef_request;
+}
+
+}  // namespace
+
+class CefTestServerImpl::Context {
+ public:
+  Context(CefRefPtr<CefTestServer> server,
+          CefRefPtr<CefTestServerHandler> handler)
+      : server_(server), handler_(handler) {
+    DCHECK(server_);
+    DCHECK(handler_);
+  }
+
+  Context(const Context&) = delete;
+  Context& operator=(const Context&) = delete;
+
+  ~Context() {
+    // The server should not be running.
+    DCHECK(!test_server_);
+  }
+
+  bool Start(uint16_t port,
+             bool https_server,
+             cef_test_cert_type_t https_cert_type) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+
+    DCHECK(!test_server_);
+    test_server_ = std::make_unique<EmbeddedTestServer>(
+        https_server ? EmbeddedTestServer::TYPE_HTTPS
+                     : EmbeddedTestServer::TYPE_HTTP);
+
+    // Unretained is safe because Stop is called before |this| is destroyed.
+    test_server_->RegisterRequestHandler(
+        base::BindRepeating(&Context::HandleRequest, base::Unretained(this)));
+
+    if (https_server) {
+      switch (https_cert_type) {
+        case CEF_TEST_CERT_OK_IP:
+          // Default value.
+          break;
+        case CEF_TEST_CERT_OK_DOMAIN:
+          test_server_->SetSSLConfig(
+              EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
+          break;
+        case CEF_TEST_CERT_EXPIRED:
+          test_server_->SetSSLConfig(EmbeddedTestServer::CERT_EXPIRED);
+          break;
+      }
+    }
+
+    test_server_handle_ =
+        test_server_->StartAndReturnHandle(static_cast<int>(port));
+    if (!test_server_handle_) {
+      test_server_.reset();
+      return false;
+    }
+
+    origin_ = test_server_->base_url();
+    return true;
+  }
+
+  void Stop() {
+    // Should be called on the creation thread.
+    DCHECK(thread_checker_.CalledOnValidThread());
+
+    DCHECK(test_server_);
+
+    // Destruction of |test_server_handle_| will stop the server and block until
+    // the dedicated server thread has shut down.
+    test_server_handle_ = EmbeddedTestServerHandle();
+    test_server_.reset();
+
+    server_ = nullptr;
+    handler_ = nullptr;
+  }
+
+  const GURL& origin() const { return origin_; }
+
+ private:
+  std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request) {
+    // Should be on the dedicated server thread.
+    DCHECK(!thread_checker_.CalledOnValidThread());
+    return std::make_unique<CefHttpResponse>(server_, handler_,
+                                             CreateCefRequest(request));
+  }
+
+  // Safe to access on any thread.
+  CefRefPtr<CefTestServer> server_;
+  CefRefPtr<CefTestServerHandler> handler_;
+  GURL origin_;
+
+  base::ThreadChecker thread_checker_;
+
+  // Only accessed on the creation thread.
+  std::unique_ptr<EmbeddedTestServer> test_server_;
+  EmbeddedTestServerHandle test_server_handle_;
+};
+
+bool CefTestServerImpl::Start(uint16_t port,
+                              bool https_server,
+                              cef_test_cert_type_t https_cert_type,
+                              CefRefPtr<CefTestServerHandler> handler) {
+  DCHECK(!context_);
+  context_ = std::make_unique<CefTestServerImpl::Context>(this, handler);
+  if (context_->Start(port, https_server, https_cert_type)) {
+    const auto& origin = context_->origin().spec();
+    // Remove the trailing '/'
+    origin_ = origin.substr(0, origin.length() - 1);
+    return true;
+  }
+
+  context_.reset();
+  return false;
+}
+
+void CefTestServerImpl::Stop() {
+  DCHECK(context_);
+  context_->Stop();
+  context_.reset();
+}
+
+CefString CefTestServerImpl::GetOrigin() {
+  return origin_;
+}
+
+// static
+CefRefPtr<CefTestServer> CefTestServer::CreateAndStart(
+    uint16_t port,
+    bool https_server,
+    cef_test_cert_type_t https_cert_type,
+    CefRefPtr<CefTestServerHandler> handler) {
+  CefRefPtr<CefTestServerImpl> server(new CefTestServerImpl());
+  if (server->Start(port, https_server, https_cert_type, handler)) {
+    return server;
+  }
+  return nullptr;
+}
diff --git a/src/libcef/browser/test/test_server_impl.h b/src/libcef/browser/test/test_server_impl.h
new file mode 100644
index 0000000..3538601
--- /dev/null
+++ b/src/libcef/browser/test/test_server_impl.h
@@ -0,0 +1,40 @@
+// Copyright 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_TEST_TEST_SERVER_IMPL_H_
+#define CEF_LIBCEF_BROWSER_TEST_TEST_SERVER_IMPL_H_
+#pragma once
+
+#include <memory>
+
+#include "include/test/cef_test_server.h"
+
+class CefTestServerImpl : public CefTestServer {
+ public:
+  CefTestServerImpl() = default;
+
+  CefTestServerImpl(const CefTestServerImpl&) = delete;
+  CefTestServerImpl& operator=(const CefTestServerImpl&) = delete;
+
+  bool Start(uint16_t port,
+             bool https_server,
+             cef_test_cert_type_t https_cert_type,
+             CefRefPtr<CefTestServerHandler> handler);
+
+  // CefTestServer methods:
+  void Stop() override;
+  CefString GetOrigin() override;
+
+ private:
+  // Only accessed on the creation thread.
+  class Context;
+  std::unique_ptr<Context> context_;
+
+  // Safe to access on any thread.
+  CefString origin_;
+
+  IMPLEMENT_REFCOUNTING(CefTestServerImpl);
+};
+
+#endif  // CEF_LIBCEF_BROWSER_TEST_TEST_SERVER_IMPL_H_
diff --git a/src/libcef/browser/thread_util.h b/src/libcef/browser/thread_util.h
index c9d718c..11eaf82 100644
--- a/src/libcef/browser/thread_util.h
+++ b/src/libcef/browser/thread_util.h
@@ -8,7 +8,7 @@
 
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "base/threading/thread_restrictions.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -25,26 +25,35 @@
 #define CEF_REQUIRE_UIT() CEF_REQUIRE(CEF_UIT)
 #define CEF_REQUIRE_IOT() CEF_REQUIRE(CEF_IOT)
 
-#define CEF_REQUIRE_RETURN(id, var)             \
-  if (!CEF_CURRENTLY_ON(id)) {                  \
-    NOTREACHED() << "called on invalid thread"; \
-    return var;                                 \
+#define CEF_REQUIRE_RETURN(id, var)              \
+  if (!CEF_CURRENTLY_ON(id)) {                   \
+    DCHECK(false) << "called on invalid thread"; \
+    return var;                                  \
   }
 #define CEF_REQUIRE_UIT_RETURN(var) CEF_REQUIRE_RETURN(CEF_UIT, var)
 #define CEF_REQUIRE_IOT_RETURN(var) CEF_REQUIRE_RETURN(CEF_IOT, var)
 
-#define CEF_REQUIRE_RETURN_VOID(id)             \
-  if (!CEF_CURRENTLY_ON(id)) {                  \
-    NOTREACHED() << "called on invalid thread"; \
-    return;                                     \
+#define CEF_REQUIRE_RETURN_VOID(id)              \
+  if (!CEF_CURRENTLY_ON(id)) {                   \
+    DCHECK(false) << "called on invalid thread"; \
+    return;                                      \
   }
 #define CEF_REQUIRE_UIT_RETURN_VOID() CEF_REQUIRE_RETURN_VOID(CEF_UIT)
 #define CEF_REQUIRE_IOT_RETURN_VOID() CEF_REQUIRE_RETURN_VOID(CEF_IOT)
 
-#define CEF_POST_TASK(id, task) base::PostTask(FROM_HERE, {id}, task)
-#define CEF_POST_DELAYED_TASK(id, task, delay_ms) \
-  base::PostDelayedTask(FROM_HERE, {id}, task,    \
-                        base::TimeDelta::FromMilliseconds(delay_ms))
+template <int id, std::enable_if_t<id == CEF_UIT, bool> = true>
+auto CEF_TASK_RUNNER() {
+  return content::GetUIThreadTaskRunner({});
+}
+template <int id, std::enable_if_t<id == CEF_IOT, bool> = true>
+auto CEF_TASK_RUNNER() {
+  return content::GetIOThreadTaskRunner({});
+}
+
+#define CEF_POST_TASK(id, task) CEF_TASK_RUNNER<id>()->PostTask(FROM_HERE, task)
+#define CEF_POST_DELAYED_TASK(id, task, delay_ms)         \
+  CEF_TASK_RUNNER<id>()->PostDelayedTask(FROM_HERE, task, \
+                                         base::Milliseconds(delay_ms))
 
 // Post a blocking task with the specified |priority|. Tasks that have not
 // started executing at shutdown will never run. However, any task that has
@@ -53,13 +62,13 @@
 // Tasks posted with this method are not guaranteed to run sequentially. Use
 // base::CreateSequencedTaskRunner instead if sequence is important.
 // Sequenced runners at various priorities that always execute all pending tasks
-// before shutdown are available via CefContentBrowserClient::*_task_runner()
-// and exposed by the CEF API.
-#define CEF_POST_BLOCKING_TASK(priority, task)                          \
-  base::PostTask(                                                       \
-      FROM_HERE,                                                        \
-      {base::ThreadPool(), priority,                                    \
-       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN, base::MayBlock()}, \
+// before shutdown are available via CefTaskRunnerManager and exposed by the CEF
+// API.
+#define CEF_POST_BLOCKING_TASK(priority, task)                 \
+  base::ThreadPool::PostTask(                                  \
+      FROM_HERE,                                               \
+      {priority, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN, \
+       base::MayBlock()},                                      \
       task)
 
 // Post a blocking task that affects UI or responsiveness of future user
@@ -79,22 +88,26 @@
       FROM_HERE, base::BlockingType::WILL_BLOCK)
 
 // Same as IMPLEMENT_REFCOUNTING() but using the specified Destructor.
-#define IMPLEMENT_REFCOUNTING_EX(ClassName, Destructor)              \
- public:                                                             \
-  void AddRef() const OVERRIDE { ref_count_.AddRef(); }              \
-  bool Release() const OVERRIDE {                                    \
-    if (ref_count_.Release()) {                                      \
-      Destructor::Destruct(this);                                    \
-      return true;                                                   \
-    }                                                                \
-    return false;                                                    \
-  }                                                                  \
-  bool HasOneRef() const OVERRIDE { return ref_count_.HasOneRef(); } \
-  bool HasAtLeastOneRef() const OVERRIDE {                           \
-    return ref_count_.HasAtLeastOneRef();                            \
-  }                                                                  \
-                                                                     \
- private:                                                            \
+#define IMPLEMENT_REFCOUNTING_EX(ClassName, Destructor) \
+ public:                                                \
+  void AddRef() const override {                        \
+    ref_count_.AddRef();                                \
+  }                                                     \
+  bool Release() const override {                       \
+    if (ref_count_.Release()) {                         \
+      Destructor::Destruct(this);                       \
+      return true;                                      \
+    }                                                   \
+    return false;                                       \
+  }                                                     \
+  bool HasOneRef() const override {                     \
+    return ref_count_.HasOneRef();                      \
+  }                                                     \
+  bool HasAtLeastOneRef() const override {              \
+    return ref_count_.HasAtLeastOneRef();               \
+  }                                                     \
+                                                        \
+ private:                                               \
   CefRefCount ref_count_
 
 #define IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(ClassName) \
diff --git a/src/libcef/browser/trace_impl.cc b/src/libcef/browser/trace_impl.cc
index 6fdab14..1057104 100644
--- a/src/libcef/browser/trace_impl.cc
+++ b/src/libcef/browser/trace_impl.cc
@@ -12,18 +12,19 @@
 bool CefBeginTracing(const CefString& categories,
                      CefRefPtr<CefCompletionCallback> callback) {
   if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
+    DCHECK(false) << "context not valid";
     return false;
   }
 
   if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
+    DCHECK(false) << "called on invalid thread";
     return false;
   }
 
   CefTraceSubscriber* subscriber = CefContext::Get()->GetTraceSubscriber();
-  if (!subscriber)
+  if (!subscriber) {
     return false;
+  }
 
   return subscriber->BeginTracing(categories, callback);
 }
@@ -31,22 +32,23 @@
 bool CefEndTracing(const CefString& tracing_file,
                    CefRefPtr<CefEndTracingCallback> callback) {
   if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
+    DCHECK(false) << "context not valid";
     return false;
   }
 
   if (!CEF_CURRENTLY_ON_UIT()) {
-    NOTREACHED() << "called on invalid thread";
+    DCHECK(false) << "called on invalid thread";
     return false;
   }
 
   CefTraceSubscriber* subscriber = CefContext::Get()->GetTraceSubscriber();
-  if (!subscriber)
+  if (!subscriber) {
     return false;
+  }
 
   return subscriber->EndTracing(base::FilePath(tracing_file), callback);
 }
 
-int64 CefNowFromSystemTraceTime() {
+int64_t CefNowFromSystemTraceTime() {
   return base::TimeTicks::Now().ToInternalValue();
 }
diff --git a/src/libcef/browser/trace_subscriber.cc b/src/libcef/browser/trace_subscriber.cc
index 6c5c3c1..1f6c030 100644
--- a/src/libcef/browser/trace_subscriber.cc
+++ b/src/libcef/browser/trace_subscriber.cc
@@ -7,7 +7,7 @@
 #include "libcef/browser/thread_util.h"
 
 #include "base/files/file_util.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/task/single_thread_task_runner.h"
 #include "base/trace_event/trace_event.h"
 #include "content/public/browser/tracing_controller.h"
 
@@ -17,12 +17,14 @@
 // represented by |message_loop_proxy|.
 void CreateTemporaryFileOnBackgroundThread(
     scoped_refptr<base::SequencedTaskRunner> message_loop_proxy,
-    base::Callback<void(const base::FilePath&)> callback) {
+    base::OnceCallback<void(const base::FilePath&)> callback) {
   CEF_REQUIRE_BLOCKING();
   base::FilePath file_path;
-  if (!base::CreateTemporaryFile(&file_path))
+  if (!base::CreateTemporaryFile(&file_path)) {
     LOG(ERROR) << "Failed to create temporary file.";
-  message_loop_proxy->PostTask(FROM_HERE, base::Bind(callback, file_path));
+  }
+  message_loop_proxy->PostTask(FROM_HERE,
+                               base::BindOnce(std::move(callback), file_path));
 }
 
 // Release the wrapped callback object after completion.
@@ -32,6 +34,10 @@
       CefRefPtr<CefCompletionCallback> callback)
       : callback_(callback) {}
 
+  CefCompletionCallbackWrapper(const CefCompletionCallbackWrapper&) = delete;
+  CefCompletionCallbackWrapper& operator=(const CefCompletionCallbackWrapper&) =
+      delete;
+
   void OnComplete() override {
     if (callback_) {
       callback_->OnComplete();
@@ -43,7 +49,6 @@
   CefRefPtr<CefCompletionCallback> callback_;
 
   IMPLEMENT_REFCOUNTING(CefCompletionCallbackWrapper);
-  DISALLOW_COPY_AND_ASSIGN(CefCompletionCallbackWrapper);
 };
 
 }  // namespace
@@ -57,8 +62,9 @@
 
 CefTraceSubscriber::~CefTraceSubscriber() {
   CEF_REQUIRE_UIT();
-  if (collecting_trace_data_)
+  if (collecting_trace_data_) {
     TracingController::GetInstance()->StopTracing(nullptr);
+  }
 }
 
 bool CefTraceSubscriber::BeginTracing(
@@ -66,8 +72,9 @@
     CefRefPtr<CefCompletionCallback> callback) {
   CEF_REQUIRE_UIT();
 
-  if (collecting_trace_data_)
+  if (collecting_trace_data_) {
     return false;
+  }
 
   collecting_trace_data_ = true;
 
@@ -89,8 +96,9 @@
                                     CefRefPtr<CefEndTracingCallback> callback) {
   CEF_REQUIRE_UIT();
 
-  if (!collecting_trace_data_)
+  if (!collecting_trace_data_) {
     return false;
+  }
 
   if (!callback.get()) {
     // Discard the trace data.
@@ -102,19 +110,21 @@
   if (tracing_file.empty()) {
     // Create a new temporary file path on the FILE thread, then continue.
     CEF_POST_USER_VISIBLE_TASK(
-        base::Bind(CreateTemporaryFileOnBackgroundThread,
-                   base::ThreadTaskRunnerHandle::Get(),
-                   base::Bind(&CefTraceSubscriber::ContinueEndTracing,
-                              weak_factory_.GetWeakPtr(), callback)));
+        base::BindOnce(CreateTemporaryFileOnBackgroundThread,
+                       base::SingleThreadTaskRunner::GetCurrentDefault(),
+                       base::BindOnce(&CefTraceSubscriber::ContinueEndTracing,
+                                      weak_factory_.GetWeakPtr(), callback)));
     return true;
   }
 
-  base::Closure result_callback =
-      base::Bind(&CefTraceSubscriber::OnTracingFileResult,
-                 weak_factory_.GetWeakPtr(), callback, tracing_file);
+  auto result_callback =
+      base::BindOnce(&CefTraceSubscriber::OnTracingFileResult,
+                     weak_factory_.GetWeakPtr(), callback, tracing_file);
 
   TracingController::GetInstance()->StopTracing(
-      TracingController::CreateFileEndpoint(tracing_file, result_callback));
+      TracingController::CreateFileEndpoint(tracing_file,
+                                            std::move(result_callback),
+                                            base::TaskPriority::USER_VISIBLE));
   return true;
 }
 
@@ -122,8 +132,9 @@
     CefRefPtr<CefEndTracingCallback> callback,
     const base::FilePath& tracing_file) {
   CEF_REQUIRE_UIT();
-  if (!tracing_file.empty())
+  if (!tracing_file.empty()) {
     EndTracing(tracing_file, callback);
+  }
 }
 
 void CefTraceSubscriber::OnTracingFileResult(
diff --git a/src/libcef/browser/views/basic_label_button_impl.cc b/src/libcef/browser/views/basic_label_button_impl.cc
index 19f3de1..41ae1fe 100644
--- a/src/libcef/browser/views/basic_label_button_impl.cc
+++ b/src/libcef/browser/views/basic_label_button_impl.cc
@@ -21,8 +21,9 @@
   CefRefPtr<CefBasicLabelButtonImpl> label_button =
       new CefBasicLabelButtonImpl(delegate);
   label_button->Initialize();
-  if (!text.empty())
+  if (!text.empty()) {
     label_button->SetText(text);
+  }
   return label_button;
 }
 
diff --git a/src/libcef/browser/views/basic_label_button_impl.h b/src/libcef/browser/views/basic_label_button_impl.h
index 2849649..8621c71 100644
--- a/src/libcef/browser/views/basic_label_button_impl.h
+++ b/src/libcef/browser/views/basic_label_button_impl.h
@@ -17,10 +17,11 @@
                                                           CefLabelButton,
                                                           CefButtonDelegate> {
  public:
-  typedef CefLabelButtonImpl<views::LabelButton,
-                             CefLabelButton,
-                             CefButtonDelegate>
-      ParentClass;
+  using ParentClass =
+      CefLabelButtonImpl<views::LabelButton, CefLabelButton, CefButtonDelegate>;
+
+  CefBasicLabelButtonImpl(const CefBasicLabelButtonImpl&) = delete;
+  CefBasicLabelButtonImpl& operator=(const CefBasicLabelButtonImpl&) = delete;
 
   // Create a new CefLabelButton instance. |delegate| may be nullptr.
   static CefRefPtr<CefBasicLabelButtonImpl> Create(
@@ -41,7 +42,6 @@
   void InitializeRootView() override;
 
   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefBasicLabelButtonImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefBasicLabelButtonImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_BASIC_LABEL_BUTTON_IMPL_H_
diff --git a/src/libcef/browser/views/basic_label_button_view.h b/src/libcef/browser/views/basic_label_button_view.h
index e6fda32..adee1c3 100644
--- a/src/libcef/browser/views/basic_label_button_view.h
+++ b/src/libcef/browser/views/basic_label_button_view.h
@@ -15,21 +15,29 @@
 // Extend views::LabelButton with a no-argument constructor as required by the
 // CefViewView template and extend views::ButtonListener as required by the
 // CefButtonView template.
-class LabelButtonEx : public views::LabelButton, public views::ButtonListener {
+class LabelButtonEx : public views::LabelButton {
  public:
-  LabelButtonEx() : views::LabelButton(this, base::string16()) {}
+  LabelButtonEx()
+      : views::LabelButton(base::BindRepeating(
+                               [](LabelButtonEx* self, const ui::Event& event) {
+                                 self->ButtonPressed(event);
+                               },
+                               base::Unretained(this)),
+                           std::u16string()) {}
+
+  virtual void ButtonPressed(const ui::Event& event) = 0;
 };
 
 class CefBasicLabelButtonView
     : public CefLabelButtonView<LabelButtonEx, CefButtonDelegate> {
  public:
-  typedef CefLabelButtonView<LabelButtonEx, CefButtonDelegate> ParentClass;
+  using ParentClass = CefLabelButtonView<LabelButtonEx, CefButtonDelegate>;
 
   // |cef_delegate| may be nullptr.
   explicit CefBasicLabelButtonView(CefButtonDelegate* cef_delegate);
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefBasicLabelButtonView);
+  CefBasicLabelButtonView(const CefBasicLabelButtonView&) = delete;
+  CefBasicLabelButtonView& operator=(const CefBasicLabelButtonView&) = delete;
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_BASIC_LABEL_BUTTON_VIEW_H_
diff --git a/src/libcef/browser/views/basic_panel_impl.h b/src/libcef/browser/views/basic_panel_impl.h
index 209be5e..06ffb7e 100644
--- a/src/libcef/browser/views/basic_panel_impl.h
+++ b/src/libcef/browser/views/basic_panel_impl.h
@@ -16,7 +16,10 @@
 class CefBasicPanelImpl
     : public CefPanelImpl<views::View, CefPanel, CefPanelDelegate> {
  public:
-  typedef CefPanelImpl<views::View, CefPanel, CefPanelDelegate> ParentClass;
+  using ParentClass = CefPanelImpl<views::View, CefPanel, CefPanelDelegate>;
+
+  CefBasicPanelImpl(const CefBasicPanelImpl&) = delete;
+  CefBasicPanelImpl& operator=(const CefBasicPanelImpl&) = delete;
 
   // Create a new CefPanel instance. |delegate| may be nullptr.
   static CefRefPtr<CefBasicPanelImpl> Create(
@@ -36,7 +39,6 @@
   void InitializeRootView() override;
 
   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefBasicPanelImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefBasicPanelImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_BASIC_PANEL_IMPL_H_
diff --git a/src/libcef/browser/views/basic_panel_view.h b/src/libcef/browser/views/basic_panel_view.h
index 477573d..659b7cb 100644
--- a/src/libcef/browser/views/basic_panel_view.h
+++ b/src/libcef/browser/views/basic_panel_view.h
@@ -12,13 +12,13 @@
 
 class CefBasicPanelView : public CefPanelView<views::View, CefPanelDelegate> {
  public:
-  typedef CefPanelView<views::View, CefPanelDelegate> ParentClass;
+  using ParentClass = CefPanelView<views::View, CefPanelDelegate>;
 
   // |cef_delegate| may be nullptr.
   explicit CefBasicPanelView(CefPanelDelegate* cef_delegate);
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefBasicPanelView);
+  CefBasicPanelView(const CefBasicPanelView&) = delete;
+  CefBasicPanelView& operator=(const CefBasicPanelView&) = delete;
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_BASIC_PANEL_VIEW_H_
diff --git a/src/libcef/browser/views/box_layout_impl.cc b/src/libcef/browser/views/box_layout_impl.cc
index 42e375f..0305ef8 100644
--- a/src/libcef/browser/views/box_layout_impl.cc
+++ b/src/libcef/browser/views/box_layout_impl.cc
@@ -20,17 +20,20 @@
 void CefBoxLayoutImpl::SetFlexForView(CefRefPtr<CefView> view, int flex) {
   CEF_REQUIRE_VALID_RETURN_VOID();
   DCHECK_GE(flex, 0);
-  if (flex < 0)
+  if (flex < 0) {
     return;
+  }
 
   DCHECK(view && view->IsValid() && view->IsAttached());
-  if (!view || !view->IsValid() || !view->IsAttached())
+  if (!view || !view->IsValid() || !view->IsAttached()) {
     return;
+  }
 
   views::View* view_ptr = view_util::GetFor(view);
   DCHECK_EQ(view_ptr->parent(), owner_view());
-  if (view_ptr->parent() != owner_view())
+  if (view_ptr->parent() != owner_view()) {
     return;
+  }
 
   layout()->SetFlexForView(view_ptr, flex);
 }
@@ -38,13 +41,15 @@
 void CefBoxLayoutImpl::ClearFlexForView(CefRefPtr<CefView> view) {
   CEF_REQUIRE_VALID_RETURN_VOID();
   DCHECK(view && view->IsValid() && view->IsAttached());
-  if (!view || !view->IsValid() || !view->IsAttached())
+  if (!view || !view->IsValid() || !view->IsAttached()) {
     return;
+  }
 
   views::View* view_ptr = view_util::GetFor(view);
   DCHECK_EQ(view_ptr->parent(), owner_view());
-  if (view_ptr->parent() != owner_view())
+  if (view_ptr->parent() != owner_view()) {
     return;
+  }
 
   layout()->ClearFlexForView(view_ptr);
 }
@@ -56,8 +61,8 @@
   views::BoxLayout* layout = new views::BoxLayout(
       settings_.horizontal ? views::BoxLayout::Orientation::kHorizontal
                            : views::BoxLayout::Orientation::kVertical,
-      gfx::Insets(settings_.inside_border_vertical_spacing,
-                  settings_.inside_border_horizontal_spacing),
+      gfx::Insets::VH(settings_.inside_border_vertical_spacing,
+                      settings_.inside_border_horizontal_spacing),
       settings_.between_child_spacing);
   layout->set_main_axis_alignment(
       static_cast<views::BoxLayout::MainAxisAlignment>(
@@ -65,12 +70,13 @@
   layout->set_cross_axis_alignment(
       static_cast<views::BoxLayout::CrossAxisAlignment>(
           settings_.cross_axis_alignment));
-  layout->set_inside_border_insets(gfx::Insets(
+  layout->set_inside_border_insets(gfx::Insets::TLBR(
       settings_.inside_border_insets.top, settings_.inside_border_insets.left,
       settings_.inside_border_insets.bottom,
       settings_.inside_border_insets.right));
   layout->set_minimum_cross_axis_size(settings_.minimum_cross_axis_size);
-  if (settings_.default_flex > 0)
+  if (settings_.default_flex > 0) {
     layout->SetDefaultFlex(settings_.default_flex);
+  }
   return layout;
 }
diff --git a/src/libcef/browser/views/box_layout_impl.h b/src/libcef/browser/views/box_layout_impl.h
index c1c4d9c..a6ae5f1 100644
--- a/src/libcef/browser/views/box_layout_impl.h
+++ b/src/libcef/browser/views/box_layout_impl.h
@@ -14,7 +14,10 @@
 class CefBoxLayoutImpl : public CefLayoutImpl<views::BoxLayout, CefBoxLayout> {
  public:
   // Necessary for the CEF_REQUIRE_VALID_*() macros to compile.
-  typedef CefLayoutImpl<views::BoxLayout, CefBoxLayout> ParentClass;
+  using ParentClass = CefLayoutImpl<views::BoxLayout, CefBoxLayout>;
+
+  CefBoxLayoutImpl(const CefBoxLayoutImpl&) = delete;
+  CefBoxLayoutImpl& operator=(const CefBoxLayoutImpl&) = delete;
 
   // Create a new CefBoxLayout insance. |owner_view| must be non-nullptr.
   static CefRefPtr<CefBoxLayoutImpl> Create(
@@ -36,7 +39,6 @@
   CefBoxLayoutSettings settings_;
 
   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefBoxLayoutImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefBoxLayoutImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_BOX_LAYOUT_IMPL_H_
diff --git a/src/libcef/browser/views/browser_platform_delegate_views.cc b/src/libcef/browser/views/browser_platform_delegate_views.cc
index 48c09f7..fc5af6b 100644
--- a/src/libcef/browser/views/browser_platform_delegate_views.cc
+++ b/src/libcef/browser/views/browser_platform_delegate_views.cc
@@ -7,7 +7,7 @@
 #include <utility>
 
 #include "include/views/cef_window.h"
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 #include "libcef/browser/views/browser_view_impl.h"
 #include "libcef/browser/views/menu_runner_views.h"
 
@@ -23,6 +23,9 @@
   explicit PopupWindowDelegate(CefRefPtr<CefBrowserView> browser_view)
       : browser_view_(browser_view) {}
 
+  PopupWindowDelegate(const PopupWindowDelegate&) = delete;
+  PopupWindowDelegate& operator=(const PopupWindowDelegate&) = delete;
+
   void OnWindowCreated(CefRefPtr<CefWindow> window) override {
     window->AddChildView(browser_view_);
     window->Show();
@@ -35,8 +38,9 @@
 
   bool CanClose(CefRefPtr<CefWindow> window) override {
     CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
-    if (browser)
+    if (browser) {
       return browser->GetHost()->TryCloseBrowser();
+    }
     return true;
   }
 
@@ -44,7 +48,6 @@
   CefRefPtr<CefBrowserView> browser_view_;
 
   IMPLEMENT_REFCOUNTING(PopupWindowDelegate);
-  DISALLOW_COPY_AND_ASSIGN(PopupWindowDelegate);
 };
 
 }  // namespace
@@ -53,8 +56,9 @@
     std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
     CefRefPtr<CefBrowserViewImpl> browser_view)
     : native_delegate_(std::move(native_delegate)) {
-  if (browser_view)
+  if (browser_view) {
     SetBrowserView(browser_view);
+  }
   native_delegate_->set_windowless_handler(this);
 }
 
@@ -66,41 +70,50 @@
 }
 
 void CefBrowserPlatformDelegateViews::WebContentsCreated(
-    content::WebContents* web_contents) {
-  CefBrowserPlatformDelegate::WebContentsCreated(web_contents);
-
+    content::WebContents* web_contents,
+    bool owned) {
+  CefBrowserPlatformDelegateAlloy::WebContentsCreated(web_contents, owned);
+  native_delegate_->WebContentsCreated(web_contents, /*owned=*/false);
   browser_view_->WebContentsCreated(web_contents);
 }
 
-void CefBrowserPlatformDelegateViews::BrowserCreated(
-    CefBrowserHostImpl* browser) {
-  CefBrowserPlatformDelegate::BrowserCreated(browser);
+void CefBrowserPlatformDelegateViews::WebContentsDestroyed(
+    content::WebContents* web_contents) {
+  CefBrowserPlatformDelegateAlloy::WebContentsDestroyed(web_contents);
+  native_delegate_->WebContentsDestroyed(web_contents);
+}
 
-  native_delegate_->set_browser(browser);
+void CefBrowserPlatformDelegateViews::BrowserCreated(
+    CefBrowserHostBase* browser) {
+  CefBrowserPlatformDelegateAlloy::BrowserCreated(browser);
+
+  native_delegate_->BrowserCreated(browser);
   browser_view_->BrowserCreated(browser, GetBoundsChangedCallback());
 }
 
 void CefBrowserPlatformDelegateViews::NotifyBrowserCreated() {
   DCHECK(browser_view_);
   DCHECK(browser_);
-  if (browser_view_->delegate())
+  if (browser_view_->delegate()) {
     browser_view_->delegate()->OnBrowserCreated(browser_view_, browser_);
+  }
 }
 
 void CefBrowserPlatformDelegateViews::NotifyBrowserDestroyed() {
   DCHECK(browser_view_);
   DCHECK(browser_);
-  if (browser_view_->delegate())
+  if (browser_view_->delegate()) {
     browser_view_->delegate()->OnBrowserDestroyed(browser_view_, browser_);
+  }
 }
 
 void CefBrowserPlatformDelegateViews::BrowserDestroyed(
-    CefBrowserHostImpl* browser) {
-  CefBrowserPlatformDelegate::BrowserDestroyed(browser);
+    CefBrowserHostBase* browser) {
+  CefBrowserPlatformDelegateAlloy::BrowserDestroyed(browser);
 
-  native_delegate_->set_browser(nullptr);
   browser_view_->BrowserDestroyed(browser);
   browser_view_ = nullptr;
+  native_delegate_->BrowserDestroyed(browser);
 }
 
 bool CefBrowserPlatformDelegateViews::CreateHostWindow() {
@@ -110,8 +123,9 @@
 
 void CefBrowserPlatformDelegateViews::CloseHostWindow() {
   views::Widget* widget = GetWindowWidget();
-  if (widget && !widget->IsClosed())
+  if (widget && !widget->IsClosed()) {
     widget->Close();
+  }
 }
 
 CefWindowHandle CefBrowserPlatformDelegateViews::GetHostWindowHandle() const {
@@ -119,8 +133,9 @@
 }
 
 views::Widget* CefBrowserPlatformDelegateViews::GetWindowWidget() const {
-  if (browser_view_->root_view())
+  if (browser_view_->root_view()) {
     return browser_view_->root_view()->GetWidget();
+  }
   return nullptr;
 }
 
@@ -154,7 +169,7 @@
 }
 
 void CefBrowserPlatformDelegateViews::PopupBrowserCreated(
-    CefBrowserHostImpl* new_browser,
+    CefBrowserHostBase* new_browser,
     bool is_devtools) {
   CefRefPtr<CefBrowserView> new_browser_view =
       CefBrowserView::GetForBrowser(new_browser);
@@ -172,14 +187,6 @@
   }
 }
 
-bool CefBrowserPlatformDelegateViews::CanUseSharedTexture() const {
-  return native_delegate_->CanUseSharedTexture();
-}
-
-bool CefBrowserPlatformDelegateViews::CanUseExternalBeginFrame() const {
-  return native_delegate_->CanUseExternalBeginFrame();
-}
-
 SkColor CefBrowserPlatformDelegateViews::GetBackgroundColor() const {
   return native_delegate_->GetBackgroundColor();
 }
@@ -218,20 +225,29 @@
   native_delegate_->SendTouchEvent(event);
 }
 
-void CefBrowserPlatformDelegateViews::SendFocusEvent(bool setFocus) {
-  // Will result in a call to WebContents::Focus().
-  if (setFocus && browser_view_->root_view())
+void CefBrowserPlatformDelegateViews::SetFocus(bool setFocus) {
+  // Will activate the Widget and result in a call to WebContents::Focus().
+  if (setFocus && browser_view_->root_view()) {
+    if (auto widget = GetWindowWidget()) {
+      // Don't activate a minimized Widget, or it will be shown.
+      if (widget->IsMinimized()) {
+        return;
+      }
+    }
     browser_view_->root_view()->RequestFocus();
+  }
 }
 
 gfx::Point CefBrowserPlatformDelegateViews::GetScreenPoint(
-    const gfx::Point& view_pt) const {
-  if (!browser_view_->root_view())
+    const gfx::Point& view_pt,
+    bool want_dip_coords) const {
+  if (!browser_view_->root_view()) {
     return view_pt;
+  }
 
   gfx::Point screen_point = view_pt;
   view_util::ConvertPointToScreen(browser_view_->root_view(), &screen_point,
-                                  true);
+                                  /*output_pixel_coords=*/!want_dip_coords);
   return screen_point;
 }
 
@@ -250,25 +266,11 @@
   return native_delegate_->GetEventHandle(event);
 }
 
-std::unique_ptr<CefFileDialogRunner>
-CefBrowserPlatformDelegateViews::CreateFileDialogRunner() {
-  return native_delegate_->CreateFileDialogRunner();
-}
-
-std::unique_ptr<CefJavaScriptDialogRunner>
-CefBrowserPlatformDelegateViews::CreateJavaScriptDialogRunner() {
-  return native_delegate_->CreateJavaScriptDialogRunner();
-}
-
 std::unique_ptr<CefMenuRunner>
 CefBrowserPlatformDelegateViews::CreateMenuRunner() {
   return base::WrapUnique(new CefMenuRunnerViews(browser_view_.get()));
 }
 
-bool CefBrowserPlatformDelegateViews::IsWindowless() const {
-  return false;
-}
-
 bool CefBrowserPlatformDelegateViews::IsViewsHosted() const {
   return true;
 }
@@ -295,6 +297,7 @@
 }
 
 gfx::Point CefBrowserPlatformDelegateViews::GetParentScreenPoint(
-    const gfx::Point& view) const {
-  return GetScreenPoint(view);
+    const gfx::Point& view,
+    bool want_dip_coords) const {
+  return GetScreenPoint(view, want_dip_coords);
 }
diff --git a/src/libcef/browser/views/browser_platform_delegate_views.h b/src/libcef/browser/views/browser_platform_delegate_views.h
index d106194..fb2714b 100644
--- a/src/libcef/browser/views/browser_platform_delegate_views.h
+++ b/src/libcef/browser/views/browser_platform_delegate_views.h
@@ -5,13 +5,13 @@
 #ifndef CEF_LIBCEF_BROWSER_VIEWS_BROWSER_PLATFORM_DELEGATE_VIEWS_H_
 #define CEF_LIBCEF_BROWSER_VIEWS_BROWSER_PLATFORM_DELEGATE_VIEWS_H_
 
-#include "libcef/browser/browser_platform_delegate.h"
+#include "libcef/browser/alloy/browser_platform_delegate_alloy.h"
 #include "libcef/browser/native/browser_platform_delegate_native.h"
 #include "libcef/browser/views/browser_view_impl.h"
 
 // Implementation of Views-based browser functionality.
 class CefBrowserPlatformDelegateViews
-    : public CefBrowserPlatformDelegate,
+    : public CefBrowserPlatformDelegateAlloy,
       public CefBrowserPlatformDelegateNative::WindowlessHandler {
  public:
   // Platform-specific behaviors will be delegated to |native_delegate|.
@@ -21,11 +21,13 @@
       CefRefPtr<CefBrowserViewImpl> browser_view);
 
   // CefBrowserPlatformDelegate methods:
-  void WebContentsCreated(content::WebContents* web_contents) override;
-  void BrowserCreated(CefBrowserHostImpl* browser) override;
+  void WebContentsCreated(content::WebContents* web_contents,
+                          bool owned) override;
+  void WebContentsDestroyed(content::WebContents* web_contents) override;
+  void BrowserCreated(CefBrowserHostBase* browser) override;
   void NotifyBrowserCreated() override;
   void NotifyBrowserDestroyed() override;
-  void BrowserDestroyed(CefBrowserHostImpl* browser) override;
+  void BrowserDestroyed(CefBrowserHostBase* browser) override;
   bool CreateHostWindow() override;
   void CloseHostWindow() override;
   CefWindowHandle GetHostWindowHandle() const override;
@@ -37,10 +39,8 @@
       content::WebContents* new_web_contents,
       CefBrowserPlatformDelegate* new_platform_delegate,
       bool is_devtools) override;
-  void PopupBrowserCreated(CefBrowserHostImpl* new_browser,
+  void PopupBrowserCreated(CefBrowserHostBase* new_browser,
                            bool is_devtools) override;
-  bool CanUseSharedTexture() const override;
-  bool CanUseExternalBeginFrame() const override;
   SkColor GetBackgroundColor() const override;
   void WasResized() override;
   void SendKeyEvent(const CefKeyEvent& event) override;
@@ -53,25 +53,23 @@
                            int deltaX,
                            int deltaY) override;
   void SendTouchEvent(const CefTouchEvent& event) override;
-  void SendFocusEvent(bool setFocus) override;
-  gfx::Point GetScreenPoint(const gfx::Point& view) const override;
+  void SetFocus(bool setFocus) override;
+  gfx::Point GetScreenPoint(const gfx::Point& view,
+                            bool want_dip_coords) const override;
   void ViewText(const std::string& text) override;
   bool HandleKeyboardEvent(
       const content::NativeWebKeyboardEvent& event) override;
   CefEventHandle GetEventHandle(
       const content::NativeWebKeyboardEvent& event) const override;
-  std::unique_ptr<CefFileDialogRunner> CreateFileDialogRunner() override;
-  std::unique_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner()
-      override;
   std::unique_ptr<CefMenuRunner> CreateMenuRunner() override;
-  bool IsWindowless() const override;
   bool IsViewsHosted() const override;
   gfx::Point GetDialogPosition(const gfx::Size& size) override;
   gfx::Size GetMaximumDialogSize() override;
 
   // CefBrowserPlatformDelegateNative::WindowlessHandler methods:
   CefWindowHandle GetParentWindowHandle() const override;
-  gfx::Point GetParentScreenPoint(const gfx::Point& view) const override;
+  gfx::Point GetParentScreenPoint(const gfx::Point& view,
+                                  bool want_dip_coords) const override;
 
  private:
   void SetBrowserView(CefRefPtr<CefBrowserViewImpl> browser_view);
diff --git a/src/libcef/browser/views/browser_view_impl.cc b/src/libcef/browser/views/browser_view_impl.cc
index deebcc3..ddce105 100644
--- a/src/libcef/browser/views/browser_view_impl.cc
+++ b/src/libcef/browser/views/browser_view_impl.cc
@@ -4,15 +4,36 @@
 
 #include "libcef/browser/views/browser_view_impl.h"
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/browser_host_base.h"
 #include "libcef/browser/browser_util.h"
+#include "libcef/browser/chrome/views/chrome_browser_view.h"
 #include "libcef/browser/context.h"
+#include "libcef/browser/request_context_impl.h"
 #include "libcef/browser/thread_util.h"
 #include "libcef/browser/views/window_impl.h"
 
-#include "content/public/browser/native_web_keyboard_event.h"
+#include "content/public/common/input/native_web_keyboard_event.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/content_accelerators/accelerator_util.h"
 
+namespace {
+
+absl::optional<cef_gesture_command_t> GetGestureCommand(
+    ui::GestureEvent* event) {
+#if BUILDFLAG(IS_MAC)
+  if (event->details().type() == ui::ET_GESTURE_SWIPE) {
+    if (event->details().swipe_left()) {
+      return CEF_GESTURE_COMMAND_BACK;
+    } else if (event->details().swipe_right()) {
+      return CEF_GESTURE_COMMAND_FORWARD;
+    }
+  }
+#endif
+  return absl::nullopt;
+}
+
+}  // namespace
+
 // static
 CefRefPtr<CefBrowserView> CefBrowserView::CreateBrowserView(
     CefRefPtr<CefClient> client,
@@ -21,23 +42,26 @@
     CefRefPtr<CefDictionaryValue> extra_info,
     CefRefPtr<CefRequestContext> request_context,
     CefRefPtr<CefBrowserViewDelegate> delegate) {
-  return CefBrowserViewImpl::Create(client, url, settings, extra_info,
-                                    request_context, delegate);
+  return CefBrowserViewImpl::Create(CefWindowInfo(), client, url, settings,
+                                    extra_info, request_context, delegate);
 }
 
 // static
 CefRefPtr<CefBrowserView> CefBrowserView::GetForBrowser(
     CefRefPtr<CefBrowser> browser) {
   CEF_REQUIRE_UIT_RETURN(nullptr);
-  CefBrowserHostImpl* browser_impl =
-      static_cast<CefBrowserHostImpl*>(browser.get());
-  if (browser_impl && browser_impl->IsViewsHosted())
+
+  CefBrowserHostBase* browser_impl =
+      static_cast<CefBrowserHostBase*>(browser.get());
+  if (browser_impl && browser_impl->is_views_hosted()) {
     return browser_impl->GetBrowserView();
+  }
   return nullptr;
 }
 
 // static
 CefRefPtr<CefBrowserViewImpl> CefBrowserViewImpl::Create(
+    const CefWindowInfo& window_info,
     CefRefPtr<CefClient> client,
     const CefString& url,
     const CefBrowserSettings& settings,
@@ -45,9 +69,22 @@
     CefRefPtr<CefRequestContext> request_context,
     CefRefPtr<CefBrowserViewDelegate> delegate) {
   CEF_REQUIRE_UIT_RETURN(nullptr);
+
+  if (!request_context) {
+    request_context = CefRequestContext::GetGlobalContext();
+  }
+
+  // Verify that the browser context is valid. Do this here instead of risking
+  // potential browser creation failure when this view is added to the window.
+  auto request_context_impl =
+      static_cast<CefRequestContextImpl*>(request_context.get());
+  if (!request_context_impl->VerifyBrowserContext()) {
+    return nullptr;
+  }
+
   CefRefPtr<CefBrowserViewImpl> browser_view = new CefBrowserViewImpl(delegate);
-  browser_view->SetPendingBrowserCreateParams(client, url, settings, extra_info,
-                                              request_context);
+  browser_view->SetPendingBrowserCreateParams(
+      window_info, client, url, settings, extra_info, request_context);
   browser_view->Initialize();
   browser_view->SetDefaults(settings);
   return browser_view;
@@ -58,6 +95,7 @@
     const CefBrowserSettings& settings,
     CefRefPtr<CefBrowserViewDelegate> delegate) {
   CEF_REQUIRE_UIT_RETURN(nullptr);
+
   CefRefPtr<CefBrowserViewImpl> browser_view = new CefBrowserViewImpl(delegate);
   browser_view->Initialize();
   browser_view->SetDefaults(settings);
@@ -66,42 +104,44 @@
 
 void CefBrowserViewImpl::WebContentsCreated(
     content::WebContents* web_contents) {
-  if (root_view())
-    root_view()->SetWebContents(web_contents);
+  if (web_view()) {
+    web_view()->SetWebContents(web_contents);
+  }
 }
 
 void CefBrowserViewImpl::BrowserCreated(
-    CefBrowserHostImpl* browser,
+    CefBrowserHostBase* browser,
     base::RepeatingClosure on_bounds_changed) {
   browser_ = browser;
   on_bounds_changed_ = on_bounds_changed;
 }
 
-void CefBrowserViewImpl::BrowserDestroyed(CefBrowserHostImpl* browser) {
+void CefBrowserViewImpl::BrowserDestroyed(CefBrowserHostBase* browser) {
   DCHECK_EQ(browser, browser_);
   browser_ = nullptr;
 
-  if (root_view())
-    root_view()->SetWebContents(nullptr);
+  if (web_view()) {
+    web_view()->SetWebContents(nullptr);
+  }
 }
 
 bool CefBrowserViewImpl::HandleKeyboardEvent(
     const content::NativeWebKeyboardEvent& event) {
-  if (!root_view())
+  if (!root_view()) {
     return false;
+  }
 
   views::FocusManager* focus_manager = root_view()->GetFocusManager();
-  if (!focus_manager)
+  if (!focus_manager) {
     return false;
+  }
 
-  if (HandleAccelerator(event, focus_manager))
+  if (HandleAccelerator(event, focus_manager)) {
     return true;
+  }
 
   // Give the CefWindowDelegate a chance to handle the event.
-  CefRefPtr<CefWindow> window =
-      view_util::GetWindowFor(root_view()->GetWidget());
-  CefWindowImpl* window_impl = static_cast<CefWindowImpl*>(window.get());
-  if (window_impl) {
+  if (auto* window_impl = cef_window()) {
     CefKeyEvent cef_event;
     if (browser_util::GetCefKeyEvent(event, cef_event) &&
         window_impl->OnKeyEvent(cef_event)) {
@@ -119,17 +159,36 @@
   return browser_;
 }
 
+CefRefPtr<CefView> CefBrowserViewImpl::GetChromeToolbar() {
+  CEF_REQUIRE_VALID_RETURN(nullptr);
+  if (cef::IsChromeRuntimeEnabled()) {
+    return chrome_browser_view()->cef_toolbar();
+  }
+
+  return nullptr;
+}
+
 void CefBrowserViewImpl::SetPreferAccelerators(bool prefer_accelerators) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (root_view())
-    root_view()->set_allow_accelerators(prefer_accelerators);
+  if (web_view()) {
+    web_view()->set_allow_accelerators(prefer_accelerators);
+  }
+}
+
+void CefBrowserViewImpl::RequestFocus() {
+  CEF_REQUIRE_VALID_RETURN_VOID();
+  // Always execute asynchronously to work around issue #3040.
+  CEF_POST_TASK(CEF_UIT,
+                base::BindOnce(&CefBrowserViewImpl::RequestFocusInternal,
+                               weak_ptr_factory_.GetWeakPtr()));
 }
 
 void CefBrowserViewImpl::SetBackgroundColor(cef_color_t color) {
   CEF_REQUIRE_VALID_RETURN_VOID();
   ParentClass::SetBackgroundColor(color);
-  if (root_view())
-    root_view()->SetResizeBackgroundColor(color);
+  if (web_view()) {
+    web_view()->SetResizeBackgroundColor(color);
+  }
 }
 
 void CefBrowserViewImpl::Detach() {
@@ -139,20 +198,21 @@
   DCHECK(!root_view());
 
   if (browser_) {
-    // |browser_| will disappear when WindowDestroyed() indirectly calls
-    // BrowserDestroyed() so keep a reference.
-    CefRefPtr<CefBrowserHostImpl> browser = browser_;
+    // With the Alloy runtime |browser_| will disappear when WindowDestroyed()
+    // indirectly calls BrowserDestroyed() so keep a reference.
+    CefRefPtr<CefBrowserHostBase> browser = browser_;
 
     // Force the browser to be destroyed.
     browser->WindowDestroyed();
   }
 }
 
-void CefBrowserViewImpl::GetDebugInfo(base::DictionaryValue* info,
+void CefBrowserViewImpl::GetDebugInfo(base::Value::Dict* info,
                                       bool include_children) {
   ParentClass::GetDebugInfo(info, include_children);
-  if (browser_)
-    info->SetString("url", browser_->GetMainFrame()->GetURL().ToString());
+  if (browser_) {
+    info->Set("url", browser_->GetMainFrame()->GetURL().ToString());
+  }
 }
 
 void CefBrowserViewImpl::OnBrowserViewAdded() {
@@ -161,7 +221,7 @@
     // hierarchy.
     pending_browser_create_params_->browser_view = this;
 
-    CefBrowserHostImpl::Create(*pending_browser_create_params_);
+    CefBrowserHostBase::Create(*pending_browser_create_params_);
     DCHECK(browser_);
 
     pending_browser_create_params_.reset(nullptr);
@@ -169,24 +229,50 @@
 }
 
 void CefBrowserViewImpl::OnBoundsChanged() {
-  if (!on_bounds_changed_.is_null())
+  if (!on_bounds_changed_.is_null()) {
     on_bounds_changed_.Run();
+  }
+}
+
+bool CefBrowserViewImpl::OnGestureEvent(ui::GestureEvent* event) {
+  if (auto command = GetGestureCommand(event)) {
+    if (delegate() && delegate()->OnGestureCommand(this, *command)) {
+      return true;
+    }
+
+    if (!cef::IsChromeRuntimeEnabled() && browser_) {
+      // Default handling for the Alloy runtime.
+      switch (*command) {
+        case CEF_GESTURE_COMMAND_BACK:
+          browser_->GoBack();
+          break;
+        case CEF_GESTURE_COMMAND_FORWARD:
+          browser_->GoForward();
+          break;
+      }
+      return true;
+    }
+  }
+
+  return false;
 }
 
 CefBrowserViewImpl::CefBrowserViewImpl(
     CefRefPtr<CefBrowserViewDelegate> delegate)
-    : ParentClass(delegate) {}
+    : ParentClass(delegate), weak_ptr_factory_(this) {}
 
 void CefBrowserViewImpl::SetPendingBrowserCreateParams(
+    const CefWindowInfo& window_info,
     CefRefPtr<CefClient> client,
     const CefString& url,
     const CefBrowserSettings& settings,
     CefRefPtr<CefDictionaryValue> extra_info,
     CefRefPtr<CefRequestContext> request_context) {
   DCHECK(!pending_browser_create_params_);
-  pending_browser_create_params_.reset(new CefBrowserHostImpl::CreateParams());
+  pending_browser_create_params_.reset(new CefBrowserCreateParams());
+  pending_browser_create_params_->MaybeSetWindowInfo(window_info);
   pending_browser_create_params_->client = client;
-  pending_browser_create_params_->url = GURL(url.ToString());
+  pending_browser_create_params_->url = url;
   pending_browser_create_params_->settings = settings;
   pending_browser_create_params_->extra_info = extra_info;
   pending_browser_create_params_->request_context = request_context;
@@ -197,12 +283,43 @@
       CefContext::Get()->GetBackgroundColor(&settings, STATE_DISABLED));
 }
 
-CefBrowserViewView* CefBrowserViewImpl::CreateRootView() {
+views::View* CefBrowserViewImpl::CreateRootView() {
+  if (cef::IsChromeRuntimeEnabled()) {
+    return new ChromeBrowserView(this);
+  }
+
   return new CefBrowserViewView(delegate(), this);
 }
 
 void CefBrowserViewImpl::InitializeRootView() {
-  static_cast<CefBrowserViewView*>(root_view())->Initialize();
+  if (cef::IsChromeRuntimeEnabled()) {
+    chrome_browser_view()->Initialize();
+  } else {
+    static_cast<CefBrowserViewView*>(root_view())->Initialize();
+  }
+}
+
+views::WebView* CefBrowserViewImpl::web_view() const {
+  if (!root_view()) {
+    return nullptr;
+  }
+
+  if (cef::IsChromeRuntimeEnabled()) {
+    return chrome_browser_view()->contents_web_view();
+  }
+
+  return static_cast<CefBrowserViewView*>(root_view());
+}
+
+ChromeBrowserView* CefBrowserViewImpl::chrome_browser_view() const {
+  CHECK(cef::IsChromeRuntimeEnabled());
+  return static_cast<ChromeBrowserView*>(root_view());
+}
+
+CefWindowImpl* CefBrowserViewImpl::cef_window() const {
+  CefRefPtr<CefWindow> window =
+      view_util::GetWindowFor(root_view()->GetWidget());
+  return static_cast<CefWindowImpl*>(window.get());
 }
 
 bool CefBrowserViewImpl::HandleAccelerator(
@@ -211,7 +328,7 @@
   // Previous calls to TranslateMessage can generate Char events as well as
   // RawKeyDown events, even if the latter triggered an accelerator.  In these
   // cases, we discard the Char events.
-  if (event.GetType() == blink::WebInputEvent::kChar &&
+  if (event.GetType() == blink::WebInputEvent::Type::kChar &&
       ignore_next_char_event_) {
     ignore_next_char_event_ = false;
     return true;
@@ -221,7 +338,7 @@
   // always generate a Char event.
   ignore_next_char_event_ = false;
 
-  if (event.GetType() == blink::WebInputEvent::kRawKeyDown) {
+  if (event.GetType() == blink::WebInputEvent::Type::kRawKeyDown) {
     ui::Accelerator accelerator =
         ui::GetAcceleratorFromNativeWebKeyboardEvent(event);
 
@@ -231,8 +348,9 @@
     // set the flag and fix it if no event was handled.
     ignore_next_char_event_ = true;
 
-    if (focus_manager->ProcessAccelerator(accelerator))
+    if (focus_manager->ProcessAccelerator(accelerator)) {
       return true;
+    }
 
     // ProcessAccelerator didn't handle the accelerator, so we know both
     // that |this| is still valid, and that we didn't want to set the flag.
@@ -241,3 +359,7 @@
 
   return false;
 }
+
+void CefBrowserViewImpl::RequestFocusInternal() {
+  ParentClass::RequestFocus();
+}
diff --git a/src/libcef/browser/views/browser_view_impl.h b/src/libcef/browser/views/browser_view_impl.h
index f35e647..7456280 100644
--- a/src/libcef/browser/views/browser_view_impl.h
+++ b/src/libcef/browser/views/browser_view_impl.h
@@ -9,26 +9,32 @@
 #include "include/cef_client.h"
 #include "include/views/cef_browser_view.h"
 #include "include/views/cef_browser_view_delegate.h"
-
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/browser_host_base.h"
 #include "libcef/browser/views/browser_view_view.h"
 #include "libcef/browser/views/view_impl.h"
 
-#include "base/callback_forward.h"
+#include "base/functional/callback_forward.h"
+#include "base/memory/weak_ptr.h"
 #include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
 
-class CefBrowserViewImpl : public CefViewImpl<CefBrowserViewView,
-                                              CefBrowserView,
-                                              CefBrowserViewDelegate>,
-                           public CefBrowserViewView::Delegate {
+class CefBrowserHostBase;
+class CefWindowImpl;
+class ChromeBrowserView;
+
+class CefBrowserViewImpl
+    : public CefViewImpl<views::View, CefBrowserView, CefBrowserViewDelegate>,
+      public CefBrowserViewView::Delegate {
  public:
-  typedef CefViewImpl<CefBrowserViewView,
-                      CefBrowserView,
-                      CefBrowserViewDelegate>
-      ParentClass;
+  using ParentClass =
+      CefViewImpl<views::View, CefBrowserView, CefBrowserViewDelegate>;
+
+  CefBrowserViewImpl(const CefBrowserViewImpl&) = delete;
+  CefBrowserViewImpl& operator=(const CefBrowserViewImpl&) = delete;
 
   // Create a new CefBrowserView instance. |delegate| may be nullptr.
+  // |window_info| will only be used when creating a Chrome child window.
   static CefRefPtr<CefBrowserViewImpl> Create(
+      const CefWindowInfo& window_info,
       CefRefPtr<CefClient> client,
       const CefString& url,
       const CefBrowserSettings& settings,
@@ -44,9 +50,9 @@
 
   // Called from CefBrowserPlatformDelegateViews.
   void WebContentsCreated(content::WebContents* web_contents);
-  void BrowserCreated(CefBrowserHostImpl* browser,
+  void BrowserCreated(CefBrowserHostBase* browser,
                       base::RepeatingClosure on_bounds_changed);
-  void BrowserDestroyed(CefBrowserHostImpl* browser);
+  void BrowserDestroyed(CefBrowserHostBase* browser);
 
   // Called to handle accelerators when the event is unhandled by the web
   // content and the browser client.
@@ -54,21 +60,32 @@
 
   // CefBrowserView methods:
   CefRefPtr<CefBrowser> GetBrowser() override;
+  CefRefPtr<CefView> GetChromeToolbar() override;
   void SetPreferAccelerators(bool prefer_accelerators) override;
 
   // CefView methods:
   CefRefPtr<CefBrowserView> AsBrowserView() override { return this; }
+  void RequestFocus() override;
   void SetBackgroundColor(cef_color_t color) override;
 
   // CefViewAdapter methods:
   void Detach() override;
   std::string GetDebugType() override { return "BrowserView"; }
-  void GetDebugInfo(base::DictionaryValue* info,
-                    bool include_children) override;
+  void GetDebugInfo(base::Value::Dict* info, bool include_children) override;
 
   // CefBrowserViewView::Delegate methods:
   void OnBrowserViewAdded() override;
   void OnBoundsChanged() override;
+  bool OnGestureEvent(ui::GestureEvent* event) override;
+
+  // Return the WebView representation of this object.
+  views::WebView* web_view() const;
+
+  // Return the CEF specialization of BrowserView.
+  ChromeBrowserView* chrome_browser_view() const;
+
+  // Return the CefWindowImpl hosting this object.
+  CefWindowImpl* cef_window() const;
 
  private:
   // Create a new implementation object.
@@ -77,6 +94,7 @@
   explicit CefBrowserViewImpl(CefRefPtr<CefBrowserViewDelegate> delegate);
 
   void SetPendingBrowserCreateParams(
+      const CefWindowInfo& window_info,
       CefRefPtr<CefClient> client,
       const CefString& url,
       const CefBrowserSettings& settings,
@@ -86,7 +104,7 @@
   void SetDefaults(const CefBrowserSettings& settings);
 
   // CefViewImpl methods:
-  CefBrowserViewView* CreateRootView() override;
+  views::View* CreateRootView() override;
   void InitializeRootView() override;
 
   // Logic extracted from UnhandledKeyboardEventHandler::HandleKeyboardEvent for
@@ -95,18 +113,20 @@
   bool HandleAccelerator(const content::NativeWebKeyboardEvent& event,
                          views::FocusManager* focus_manager);
 
-  std::unique_ptr<CefBrowserHostImpl::CreateParams>
-      pending_browser_create_params_;
+  void RequestFocusInternal();
 
-  CefRefPtr<CefBrowserHostImpl> browser_;
+  std::unique_ptr<CefBrowserCreateParams> pending_browser_create_params_;
+
+  CefRefPtr<CefBrowserHostBase> browser_;
 
   views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
   bool ignore_next_char_event_ = false;
 
   base::RepeatingClosure on_bounds_changed_;
 
+  base::WeakPtrFactory<CefBrowserViewImpl> weak_ptr_factory_;
+
   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefBrowserViewImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefBrowserViewImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_BROWSER_VIEW_IMPL_H_
diff --git a/src/libcef/browser/views/browser_view_view.cc b/src/libcef/browser/views/browser_view_view.cc
index 35bbf94..2de10ae 100644
--- a/src/libcef/browser/views/browser_view_view.cc
+++ b/src/libcef/browser/views/browser_view_view.cc
@@ -25,8 +25,9 @@
       // this View to a CefWindow with FillLayout and then calling
       // CefWindow::Show() without first resizing the CefWindow.
       size = details.parent->GetPreferredSize();
-      if (!size.IsEmpty())
+      if (!size.IsEmpty()) {
         SetSize(size);
+      }
     }
 
     browser_view_delegate_->OnBrowserViewAdded();
@@ -37,3 +38,10 @@
   ParentClass::OnBoundsChanged(previous_bounds);
   browser_view_delegate_->OnBoundsChanged();
 }
+
+void CefBrowserViewView::OnGestureEvent(ui::GestureEvent* event) {
+  if (browser_view_delegate_->OnGestureEvent(event)) {
+    return;
+  }
+  ParentClass::OnGestureEvent(event);
+}
diff --git a/src/libcef/browser/views/browser_view_view.h b/src/libcef/browser/views/browser_view_view.h
index 7a50d8a..ba0a51a 100644
--- a/src/libcef/browser/views/browser_view_view.h
+++ b/src/libcef/browser/views/browser_view_view.h
@@ -16,13 +16,22 @@
 // CefViewView template.
 class WebViewEx : public views::WebView {
  public:
-  WebViewEx() : views::WebView(nullptr) {}
+  WebViewEx() : views::WebView(nullptr) {
+    // Mouse events on draggable regions will not be handled by the WebView.
+    // Avoid the resulting DCHECK in NativeViewHost::OnMousePressed by
+    // configuring the NativeViewHost not to process events via the view
+    // hierarchy.
+    holder()->SetCanProcessEventsWithinSubtree(false);
+  }
 };
 
 class CefBrowserViewView
     : public CefViewView<WebViewEx, CefBrowserViewDelegate> {
  public:
-  typedef CefViewView<WebViewEx, CefBrowserViewDelegate> ParentClass;
+  using ParentClass = CefViewView<WebViewEx, CefBrowserViewDelegate>;
+
+  CefBrowserViewView(const CefBrowserViewView&) = delete;
+  CefBrowserViewView& operator=(const CefBrowserViewView&) = delete;
 
   class Delegate {
    public:
@@ -32,6 +41,10 @@
     // Called when the BrowserView bounds have changed.
     virtual void OnBoundsChanged() = 0;
 
+    // Called when the BrowserView receives a gesture event.
+    // Returns true if the gesture was handled.
+    virtual bool OnGestureEvent(ui::GestureEvent* event) = 0;
+
    protected:
     virtual ~Delegate() {}
   };
@@ -45,12 +58,11 @@
   void ViewHierarchyChanged(
       const views::ViewHierarchyChangedDetails& details) override;
   void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
+  void OnGestureEvent(ui::GestureEvent* event) override;
 
  private:
   // Not owned by this object.
   Delegate* browser_view_delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefBrowserViewView);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_BROWSER_VIEW_VIEW_H_
diff --git a/src/libcef/browser/views/button_impl.h b/src/libcef/browser/views/button_impl.h
index 76456a2..247b11b 100644
--- a/src/libcef/browser/views/button_impl.h
+++ b/src/libcef/browser/views/button_impl.h
@@ -13,6 +13,7 @@
 
 #include "base/logging.h"
 #include "ui/gfx/color_utils.h"
+#include "ui/views/animation/ink_drop.h"
 #include "ui/views/controls/button/button.h"
 
 // Helpers for template boiler-plate.
@@ -24,7 +25,7 @@
 // view_impl.h for a usage overview.
 CEF_BUTTON_IMPL_T class CefButtonImpl : public CEF_VIEW_IMPL_D {
  public:
-  typedef CEF_VIEW_IMPL_D ParentClass;
+  using ParentClass = CEF_VIEW_IMPL_D;
 
   // CefButton methods. When adding new As*() methods make sure to update
   // CefViewAdapter::GetFor() in view_adapter.cc.
@@ -49,12 +50,12 @@
 
 CEF_BUTTON_IMPL_T void CEF_BUTTON_IMPL_D::SetState(cef_button_state_t state) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  views::Button::ButtonState old_state = ParentClass::root_view()->state();
+  views::Button::ButtonState old_state = ParentClass::root_view()->GetState();
   views::Button::ButtonState new_state =
       static_cast<views::Button::ButtonState>(state);
 
-  if (ParentClass::root_view()->ink_drop_mode() !=
-          views::Button::InkDropMode::OFF &&
+  if (views::InkDrop::Get(ParentClass::root_view())->ink_drop_mode() !=
+          views::InkDropHost::InkDropMode::OFF &&
       !ParentClass::root_view()->IsFocusable()) {
     // Ink drop state does not get set properly on state change when the button
     // is non-focusable.
@@ -64,7 +65,8 @@
     } else if (old_state == views::Button::STATE_PRESSED) {
       ink_state = views::InkDropState::DEACTIVATED;
     }
-    ParentClass::root_view()->AnimateInkDrop(ink_state, nullptr);
+    views::InkDrop::Get(ParentClass::root_view())
+        ->AnimateToState(ink_state, nullptr);
   }
 
   ParentClass::root_view()->SetState(new_state);
@@ -72,17 +74,17 @@
 
 CEF_BUTTON_IMPL_T cef_button_state_t CEF_BUTTON_IMPL_D::GetState() {
   CEF_REQUIRE_VALID_RETURN(CEF_BUTTON_STATE_NORMAL);
-  return static_cast<cef_button_state_t>(ParentClass::root_view()->state());
+  return static_cast<cef_button_state_t>(ParentClass::root_view()->GetState());
 }
 
 CEF_BUTTON_IMPL_T void CEF_BUTTON_IMPL_D::SetInkDropEnabled(bool enabled) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  ParentClass::root_view()->SetInkDropMode(
-      enabled ? views::InkDropHostView::InkDropMode::ON
-              : views::InkDropHostView::InkDropMode::OFF);
+  views::InkDrop::Get(ParentClass::root_view())
+      ->SetMode(enabled ? views::InkDropHost::InkDropMode::ON
+                        : views::InkDropHost::InkDropMode::OFF);
   if (enabled) {
-    ParentClass::root_view()->set_ink_drop_base_color(
-        color_utils::BlendTowardMaxContrast(
+    views::InkDrop::Get(ParentClass::root_view())
+        ->SetBaseColor(color_utils::BlendTowardMaxContrast(
             ParentClass::root_view()->background()->get_color(), 0x61));
   }
 }
@@ -101,7 +103,7 @@
 
 CEF_BUTTON_IMPL_T void CEF_BUTTON_IMPL_D::SetFocusable(bool focusable) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  ParentClass::root_view()->set_request_focus_on_press(focusable);
+  ParentClass::root_view()->SetRequestFocusOnPress(focusable);
   ParentClass::SetFocusable(focusable);
 }
 
diff --git a/src/libcef/browser/views/button_view.h b/src/libcef/browser/views/button_view.h
index 6a112c6..04441cc 100644
--- a/src/libcef/browser/views/button_view.h
+++ b/src/libcef/browser/views/button_view.h
@@ -12,6 +12,7 @@
 #include "libcef/browser/views/view_view.h"
 
 #include "base/logging.h"
+#include "ui/views/animation/ink_drop.h"
 #include "ui/views/controls/button/button.h"
 
 // Helpers for template boiler-plate.
@@ -25,11 +26,12 @@
 // basic_label_button_view.h). See comments in view_impl.h for a usage overview.
 CEF_BUTTON_VIEW_T class CefButtonView : public CEF_VIEW_VIEW_D {
  public:
-  typedef CEF_VIEW_VIEW_D ParentClass;
+  using ParentClass = CEF_VIEW_VIEW_D;
 
   // |cef_delegate| may be nullptr.
-  explicit CefButtonView(CefViewDelegateClass* cef_delegate)
-      : ParentClass(cef_delegate) {}
+  template <typename... Args>
+  explicit CefButtonView(CefViewDelegateClass* cef_delegate, Args... args)
+      : ParentClass(cef_delegate, args...) {}
 
   // Returns the CefButton associated with this view. See comments on
   // CefViewView::GetCefView.
@@ -42,32 +44,34 @@
   // views::Button methods:
   void StateChanged(views::Button::ButtonState old_state) override;
 
-  // views::ButtonListener methods:
-  void ButtonPressed(views::Button* sender, const ui::Event& event) override;
+  // LabelButtonEx methods:
+  void ButtonPressed(const ui::Event& event) override;
 };
 
 CEF_BUTTON_VIEW_T void CEF_BUTTON_VIEW_D::StateChanged(
     views::Button::ButtonState old_state) {
   ParentClass::StateChanged(old_state);
-  if (ParentClass::cef_delegate())
+  if (ParentClass::cef_delegate()) {
     ParentClass::cef_delegate()->OnButtonStateChanged(GetCefButton());
+  }
 }
 
 CEF_BUTTON_VIEW_T void CEF_BUTTON_VIEW_D::ButtonPressed(
-    views::Button* sender,
     const ui::Event& event) {
   // Callback may trigger new animation state.
-  if (ParentClass::cef_delegate())
+  if (ParentClass::cef_delegate()) {
     ParentClass::cef_delegate()->OnButtonPressed(GetCefButton());
-  if (ParentClass::ink_drop_mode() != views::Button::InkDropMode::OFF &&
+  }
+  if (views::InkDrop::Get(this)->ink_drop_mode() !=
+          views::InkDropHost::InkDropMode::OFF &&
       !ParentClass::IsFocusable() &&
-      ParentClass::state() != views::Button::STATE_PRESSED) {
+      ParentClass::GetState() != views::Button::STATE_PRESSED) {
     // Ink drop state does not get reset properly on click when the button is
     // non-focusable. Reset the ink drop state here if the state has not been
     // explicitly set to pressed by the OnButtonPressed callback calling
     // SetState (which also sets the ink drop state).
-    ParentClass::AnimateInkDrop(views::InkDropState::HIDDEN,
-                                ui::LocatedEvent::FromIfValid(&event));
+    views::InkDrop::Get(this)->AnimateToState(
+        views::InkDropState::HIDDEN, ui::LocatedEvent::FromIfValid(&event));
   }
 }
 
diff --git a/src/libcef/browser/views/display_impl.cc b/src/libcef/browser/views/display_impl.cc
index 4f6d723..43e5fda 100644
--- a/src/libcef/browser/views/display_impl.cc
+++ b/src/libcef/browser/views/display_impl.cc
@@ -45,10 +45,61 @@
 
   displays.clear();
 
-  typedef std::vector<display::Display> DisplayVector;
+  using DisplayVector = std::vector<display::Display>;
   DisplayVector vec = display::Screen::GetScreen()->GetAllDisplays();
-  for (size_t i = 0; i < vec.size(); ++i)
+  for (size_t i = 0; i < vec.size(); ++i) {
     displays.push_back(new CefDisplayImpl(vec[i]));
+  }
+}
+
+// static
+CefPoint CefDisplay::ConvertScreenPointToPixels(const CefPoint& point) {
+  CEF_REQUIRE_UIT_RETURN(CefPoint());
+#if BUILDFLAG(IS_WIN)
+  const gfx::Point pix_point =
+      view_util::ConvertPointToPixels(gfx::Point(point.x, point.y));
+  return CefPoint(pix_point.x(), pix_point.y());
+#else
+  return point;
+#endif
+}
+
+// static
+CefPoint CefDisplay::ConvertScreenPointFromPixels(const CefPoint& point) {
+  CEF_REQUIRE_UIT_RETURN(CefPoint());
+#if BUILDFLAG(IS_WIN)
+  const gfx::Point dip_point =
+      view_util::ConvertPointFromPixels(gfx::Point(point.x, point.y));
+  return CefPoint(dip_point.x(), dip_point.y());
+#else
+  return point;
+#endif
+}
+
+// static
+CefRect CefDisplay::ConvertScreenRectToPixels(const CefRect& rect) {
+  CEF_REQUIRE_UIT_RETURN(CefRect());
+#if BUILDFLAG(IS_WIN)
+  const gfx::Rect pix_rect = view_util::ConvertRectToPixels(
+      gfx::Rect(rect.x, rect.y, rect.width, rect.height));
+  return CefRect(pix_rect.x(), pix_rect.y(), pix_rect.width(),
+                 pix_rect.height());
+#else
+  return rect;
+#endif
+}
+
+// static
+CefRect CefDisplay::ConvertScreenRectFromPixels(const CefRect& rect) {
+  CEF_REQUIRE_UIT_RETURN(CefRect());
+#if BUILDFLAG(IS_WIN)
+  const gfx::Rect dip_rect = view_util::ConvertRectFromPixels(
+      gfx::Rect(rect.x, rect.y, rect.width, rect.height));
+  return CefRect(dip_rect.x(), dip_rect.y(), dip_rect.width(),
+                 dip_rect.height());
+#else
+  return rect;
+#endif
 }
 
 CefDisplayImpl::CefDisplayImpl(const display::Display& display)
@@ -60,7 +111,7 @@
   CEF_REQUIRE_UIT();
 }
 
-int64 CefDisplayImpl::GetID() {
+int64_t CefDisplayImpl::GetID() {
   CEF_REQUIRE_UIT_RETURN(-1);
   return display_.id();
 }
diff --git a/src/libcef/browser/views/display_impl.h b/src/libcef/browser/views/display_impl.h
index 79562e3..984e580 100644
--- a/src/libcef/browser/views/display_impl.h
+++ b/src/libcef/browser/views/display_impl.h
@@ -14,10 +14,14 @@
 class CefDisplayImpl : public CefDisplay {
  public:
   explicit CefDisplayImpl(const display::Display& display);
+
+  CefDisplayImpl(const CefDisplayImpl&) = delete;
+  CefDisplayImpl& operator=(const CefDisplayImpl&) = delete;
+
   ~CefDisplayImpl() override;
 
   // CefDisplay methods:
-  int64 GetID() override;
+  int64_t GetID() override;
   float GetDeviceScaleFactor() override;
   void ConvertPointToPixels(CefPoint& point) override;
   void ConvertPointFromPixels(CefPoint& point) override;
@@ -31,7 +35,6 @@
   display::Display display_;
 
   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefDisplayImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefDisplayImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_DISPLAY_IMPL_H_
diff --git a/src/libcef/browser/views/fill_layout_impl.h b/src/libcef/browser/views/fill_layout_impl.h
index e4b28a2..f075767 100644
--- a/src/libcef/browser/views/fill_layout_impl.h
+++ b/src/libcef/browser/views/fill_layout_impl.h
@@ -14,6 +14,9 @@
 class CefFillLayoutImpl
     : public CefLayoutImpl<views::FillLayout, CefFillLayout> {
  public:
+  CefFillLayoutImpl(const CefFillLayoutImpl&) = delete;
+  CefFillLayoutImpl& operator=(const CefFillLayoutImpl&) = delete;
+
   // Create a new CefFillLayout insance. |owner_view| must be non-nullptr.
   static CefRefPtr<CefFillLayout> Create(views::View* owner_view);
 
@@ -26,7 +29,6 @@
   views::FillLayout* CreateLayout() override;
 
   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefFillLayoutImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefFillLayoutImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_FILL_LAYOUT_IMPL_H_
diff --git a/src/libcef/browser/views/label_button_impl.h b/src/libcef/browser/views/label_button_impl.h
index 98dc9d8..40ca624 100644
--- a/src/libcef/browser/views/label_button_impl.h
+++ b/src/libcef/browser/views/label_button_impl.h
@@ -25,7 +25,7 @@
 // view_impl.h for a usage overview.
 CEF_LABEL_BUTTON_IMPL_T class CefLabelButtonImpl : public CEF_BUTTON_IMPL_D {
  public:
-  typedef CEF_BUTTON_IMPL_D ParentClass;
+  using ParentClass = CEF_BUTTON_IMPL_D;
 
   // CefLabelButton methods. When adding new As*() methods make sure to update
   // CefViewAdapter::GetFor() in view_adapter.cc.
@@ -48,10 +48,9 @@
   CefRefPtr<CefLabelButton> AsLabelButton() override { return this; }
 
   // CefViewAdapter methods:
-  void GetDebugInfo(base::DictionaryValue* info,
-                    bool include_children) override {
+  void GetDebugInfo(base::Value::Dict* info, bool include_children) override {
     ParentClass::GetDebugInfo(info, include_children);
-    info->SetString("text", ParentClass::root_view()->GetText());
+    info->Set("text", ParentClass::root_view()->GetText());
   }
 
  protected:
@@ -78,8 +77,9 @@
     CefRefPtr<CefImage> image) {
   CEF_REQUIRE_VALID_RETURN_VOID();
   gfx::ImageSkia image_skia;
-  if (image)
+  if (image) {
     image_skia = static_cast<CefImageImpl*>(image.get())->AsImageSkia();
+  }
   ParentClass::root_view()->SetImage(
       static_cast<views::Button::ButtonState>(button_state), image_skia);
 }
@@ -89,8 +89,9 @@
   CEF_REQUIRE_VALID_RETURN(nullptr);
   const gfx::ImageSkia& image_skia = ParentClass::root_view()->GetImage(
       static_cast<views::Button::ButtonState>(button_state));
-  if (image_skia.isNull())
+  if (image_skia.isNull()) {
     return nullptr;
+  }
   return new CefImageImpl(image_skia);
 }
 
diff --git a/src/libcef/browser/views/label_button_view.h b/src/libcef/browser/views/label_button_view.h
index e159724..a628dfd 100644
--- a/src/libcef/browser/views/label_button_view.h
+++ b/src/libcef/browser/views/label_button_view.h
@@ -22,11 +22,12 @@
 // view_impl.h for a usage overview.
 CEF_LABEL_BUTTON_VIEW_T class CefLabelButtonView : public CEF_BUTTON_VIEW_D {
  public:
-  typedef CEF_BUTTON_VIEW_D ParentClass;
+  using ParentClass = CEF_BUTTON_VIEW_D;
 
   // |cef_delegate| may be nullptr.
-  explicit CefLabelButtonView(CefViewDelegateClass* cef_delegate)
-      : ParentClass(cef_delegate) {}
+  template <typename... Args>
+  explicit CefLabelButtonView(CefViewDelegateClass* cef_delegate, Args... args)
+      : ParentClass(cef_delegate, args...) {}
 
   void Initialize() override {
     ParentClass::Initialize();
diff --git a/src/libcef/browser/views/layout_util.cc b/src/libcef/browser/views/layout_util.cc
index 305438d..1d5602e 100644
--- a/src/libcef/browser/views/layout_util.cc
+++ b/src/libcef/browser/views/layout_util.cc
@@ -19,8 +19,9 @@
  public:
   static CefRefPtr<CefLayout> GetFor(const views::View* view) {
     UserData* data = static_cast<UserData*>(view->GetUserData(UserDataKey()));
-    if (data)
+    if (data) {
       return data->layout_;
+    }
     return nullptr;
   }
 
diff --git a/src/libcef/browser/views/menu_button_impl.cc b/src/libcef/browser/views/menu_button_impl.cc
index 6547277..d74d2cf 100644
--- a/src/libcef/browser/views/menu_button_impl.cc
+++ b/src/libcef/browser/views/menu_button_impl.cc
@@ -22,12 +22,14 @@
     const CefString& text) {
   CEF_REQUIRE_UIT_RETURN(nullptr);
   DCHECK(delegate);
-  if (!delegate)
+  if (!delegate) {
     return nullptr;
+  }
   CefRefPtr<CefMenuButtonImpl> menu_button = new CefMenuButtonImpl(delegate);
   menu_button->Initialize();
-  if (!text.empty())
+  if (!text.empty()) {
     menu_button->SetText(text);
+  }
   return menu_button;
 }
 
diff --git a/src/libcef/browser/views/menu_button_impl.h b/src/libcef/browser/views/menu_button_impl.h
index 682cddb..26bb14f 100644
--- a/src/libcef/browser/views/menu_button_impl.h
+++ b/src/libcef/browser/views/menu_button_impl.h
@@ -18,10 +18,12 @@
                                                     CefMenuButton,
                                                     CefMenuButtonDelegate> {
  public:
-  typedef CefLabelButtonImpl<views::MenuButton,
-                             CefMenuButton,
-                             CefMenuButtonDelegate>
-      ParentClass;
+  using ParentClass = CefLabelButtonImpl<views::MenuButton,
+                                         CefMenuButton,
+                                         CefMenuButtonDelegate>;
+
+  CefMenuButtonImpl(const CefMenuButtonImpl&) = delete;
+  CefMenuButtonImpl& operator=(const CefMenuButtonImpl&) = delete;
 
   // Create a new CefMenuButton instance. |delegate| must not be nullptr.
   static CefRefPtr<CefMenuButtonImpl> Create(
@@ -54,7 +56,6 @@
   void InitializeRootView() override;
 
   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefMenuButtonImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefMenuButtonImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_MENU_BUTTON_IMPL_H_
diff --git a/src/libcef/browser/views/menu_button_view.cc b/src/libcef/browser/views/menu_button_view.cc
index aac7ab6..3e8974f 100644
--- a/src/libcef/browser/views/menu_button_view.cc
+++ b/src/libcef/browser/views/menu_button_view.cc
@@ -17,11 +17,13 @@
   explicit ButtonPressedLock(views::MenuButton* menu_button)
       : pressed_lock_(menu_button->button_controller()) {}
 
+  ButtonPressedLock(const ButtonPressedLock&) = delete;
+  ButtonPressedLock& operator=(const ButtonPressedLock&) = delete;
+
  private:
   views::MenuButtonController::PressedLock pressed_lock_;
 
   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(ButtonPressedLock);
-  DISALLOW_COPY_AND_ASSIGN(ButtonPressedLock);
 };
 
 }  // namespace
@@ -51,10 +53,9 @@
   label()->SetDrawStringsFlags(flags);
 }
 
-void CefMenuButtonView::ButtonPressed(views::Button* source,
-                                      const ui::Event& event) {
-  auto position = source->GetMenuPosition();
-  cef_delegate()->OnMenuButtonPressed(
-      GetCefMenuButton(), CefPoint(position.x(), position.y()),
-      new ButtonPressedLock(static_cast<views::MenuButton*>(source)));
+void CefMenuButtonView::ButtonPressed(const ui::Event& event) {
+  auto position = GetMenuPosition();
+  cef_delegate()->OnMenuButtonPressed(GetCefMenuButton(),
+                                      CefPoint(position.x(), position.y()),
+                                      new ButtonPressedLock(this));
 }
diff --git a/src/libcef/browser/views/menu_button_view.h b/src/libcef/browser/views/menu_button_view.h
index bd66e7e..e5c94d7 100644
--- a/src/libcef/browser/views/menu_button_view.h
+++ b/src/libcef/browser/views/menu_button_view.h
@@ -16,23 +16,29 @@
 // Extend views::LabelButton with a no-argument constructor as required by the
 // CefViewView template and extend views::ButtonListener as required by the
 // CefButtonView template.
-class MenuButtonEx : public views::MenuButton, public views::ButtonListener {
+class MenuButtonEx : public views::MenuButton {
  public:
-  MenuButtonEx() : views::MenuButton(base::string16(), this) {
-    // TODO(cef): MenuButton should not use ButtonListener. See
-    // http://crbug.com/585252 for details.
-    Button::listener_ = this;
-  }
+  MenuButtonEx()
+      : views::MenuButton(base::BindRepeating(
+            [](MenuButtonEx* self, const ui::Event& event) {
+              self->ButtonPressed(event);
+            },
+            base::Unretained(this))) {}
+
+  virtual void ButtonPressed(const ui::Event& event) = 0;
 };
 
 class CefMenuButtonView
     : public CefLabelButtonView<MenuButtonEx, CefMenuButtonDelegate> {
  public:
-  typedef CefLabelButtonView<MenuButtonEx, CefMenuButtonDelegate> ParentClass;
+  using ParentClass = CefLabelButtonView<MenuButtonEx, CefMenuButtonDelegate>;
 
   // |cef_delegate| must not be nullptr.
   explicit CefMenuButtonView(CefMenuButtonDelegate* cef_delegate);
 
+  CefMenuButtonView(const CefMenuButtonView&) = delete;
+  CefMenuButtonView& operator=(const CefMenuButtonView&) = delete;
+
   void Initialize() override;
 
   // Returns the CefMenuButton associated with this view. See comments on
@@ -42,11 +48,8 @@
   // Set the flags that control display of accelerator characters.
   void SetDrawStringsFlags(int flags);
 
-  // views::ButtonListener methods:
-  void ButtonPressed(views::Button* source, const ui::Event& event) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefMenuButtonView);
+  // MenuButtonEx methods:
+  void ButtonPressed(const ui::Event& event) override;
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_MENU_BUTTON_VIEW_H_
diff --git a/src/libcef/browser/views/menu_runner_views.cc b/src/libcef/browser/views/menu_runner_views.cc
index b6d976a..14b3b55 100644
--- a/src/libcef/browser/views/menu_runner_views.cc
+++ b/src/libcef/browser/views/menu_runner_views.cc
@@ -4,19 +4,20 @@
 
 #include "libcef/browser/views/menu_runner_views.h"
 
-#include "libcef/browser/browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
 #include "libcef/browser/views/browser_view_impl.h"
 
 CefMenuRunnerViews::CefMenuRunnerViews(CefBrowserViewImpl* browser_view)
     : browser_view_(browser_view) {}
 
 bool CefMenuRunnerViews::RunContextMenu(
-    CefBrowserHostImpl* browser,
+    AlloyBrowserHostImpl* browser,
     CefMenuModelImpl* model,
     const content::ContextMenuParams& params) {
   CefRefPtr<CefWindow> window = browser_view_->GetWindow();
-  if (!window)
+  if (!window) {
     return false;
+  }
 
   CefPoint screen_point(params.x, params.y);
   browser_view_->ConvertPointToScreen(screen_point);
@@ -27,12 +28,13 @@
 
 void CefMenuRunnerViews::CancelContextMenu() {
   CefRefPtr<CefWindow> window = browser_view_->GetWindow();
-  if (window)
+  if (window) {
     window->CancelMenu();
+  }
 }
 
-bool CefMenuRunnerViews::FormatLabel(base::string16& label) {
+bool CefMenuRunnerViews::FormatLabel(std::u16string& label) {
   // Remove the accelerator indicator (&) from label strings.
-  const char16 replace[] = {L'&', 0};
-  return base::ReplaceChars(label, replace, base::string16(), &label);
+  const std::u16string::value_type replace[] = {L'&', 0};
+  return base::ReplaceChars(label, replace, std::u16string(), &label);
 }
diff --git a/src/libcef/browser/views/menu_runner_views.h b/src/libcef/browser/views/menu_runner_views.h
index 9030dbb..d77ce82 100644
--- a/src/libcef/browser/views/menu_runner_views.h
+++ b/src/libcef/browser/views/menu_runner_views.h
@@ -16,11 +16,11 @@
   explicit CefMenuRunnerViews(CefBrowserViewImpl* browser_view);
 
   // CefMenuRunner methods.
-  bool RunContextMenu(CefBrowserHostImpl* browser,
+  bool RunContextMenu(AlloyBrowserHostImpl* browser,
                       CefMenuModelImpl* model,
                       const content::ContextMenuParams& params) override;
   void CancelContextMenu() override;
-  bool FormatLabel(base::string16& label) override;
+  bool FormatLabel(std::u16string& label) override;
 
  private:
   CefBrowserViewImpl* browser_view_;
diff --git a/src/libcef/browser/views/native_widget_mac.h b/src/libcef/browser/views/native_widget_mac.h
new file mode 100644
index 0000000..1bd8aa1
--- /dev/null
+++ b/src/libcef/browser/views/native_widget_mac.h
@@ -0,0 +1,57 @@
+// Copyright 2023 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_VIEWS_NATIVE_WIDGET_MAC_H_
+#define CEF_LIBCEF_BROWSER_VIEWS_NATIVE_WIDGET_MAC_H_
+#pragma once
+
+#include "include/internal/cef_ptr.h"
+
+#include "ui/views/widget/native_widget_mac.h"
+
+class BrowserView;
+class CefWindow;
+class CefWindowDelegate;
+
+class CefNativeWidgetMac : public views::NativeWidgetMac {
+ public:
+  CefNativeWidgetMac(views::internal::NativeWidgetDelegate* delegate,
+                     CefRefPtr<CefWindow> window,
+                     CefWindowDelegate* window_delegate);
+  ~CefNativeWidgetMac() override = default;
+
+  CefNativeWidgetMac(const CefNativeWidgetMac&) = delete;
+  CefNativeWidgetMac& operator=(const CefNativeWidgetMac&) = delete;
+
+  void SetBrowserView(BrowserView* browser_view);
+
+  // NativeWidgetMac:
+  void ValidateUserInterfaceItem(
+      int32_t command,
+      remote_cocoa::mojom::ValidateUserInterfaceItemResult* result) override;
+  bool WillExecuteCommand(int32_t command,
+                          WindowOpenDisposition window_open_disposition,
+                          bool is_before_first_responder) override;
+  bool ExecuteCommand(int32_t command,
+                      WindowOpenDisposition window_open_disposition,
+                      bool is_before_first_responder) override;
+  NativeWidgetMacNSWindow* CreateNSWindow(
+      const remote_cocoa::mojom::CreateWindowParams* params) override;
+  void GetWindowFrameTitlebarHeight(bool* override_titlebar_height,
+                                    float* titlebar_height) override;
+  void OnWindowFullscreenTransitionStart() override;
+  void OnWindowFullscreenTransitionComplete() override;
+  void OnWindowInitialized() override;
+
+ private:
+  const CefRefPtr<CefWindow> window_;
+  CefWindowDelegate* const window_delegate_;
+
+  // Returns true if the CefWindow is fully initialized.
+  bool IsCefWindowInitialized() const;
+
+  BrowserView* browser_view_ = nullptr;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_VIEWS_NATIVE_WIDGET_MAC_H_
diff --git a/src/libcef/browser/views/native_widget_mac.mm b/src/libcef/browser/views/native_widget_mac.mm
new file mode 100644
index 0000000..9367f31
--- /dev/null
+++ b/src/libcef/browser/views/native_widget_mac.mm
@@ -0,0 +1,159 @@
+// Copyright 2023 The Chromium Embedded Framework 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 "libcef/browser/views/native_widget_mac.h"
+
+#include "include/views/cef_window.h"
+#include "include/views/cef_window_delegate.h"
+#include "libcef/browser/views/ns_window.h"
+#include "libcef/browser/views/window_impl.h"
+
+#include "chrome/browser/apps/app_shim/app_shim_host_mac.h"
+#include "chrome/browser/apps/app_shim/app_shim_manager_mac.h"
+#import "chrome/browser/ui/cocoa/browser_window_command_handler.h"
+#import "chrome/browser/ui/cocoa/chrome_command_dispatcher_delegate.h"
+#include "chrome/browser/ui/views/frame/browser_frame_mac.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
+#import "ui/views/cocoa/native_widget_mac_ns_window_host.h"
+
+namespace {
+
+AppShimHost* GetHostForBrowser(Browser* browser) {
+  auto* const shim_manager = apps::AppShimManager::Get();
+  if (!shim_manager) {
+    return nullptr;
+  }
+  return shim_manager->GetHostForRemoteCocoaBrowser(browser);
+}
+
+}  // namespace
+
+CefNativeWidgetMac::CefNativeWidgetMac(
+    views::internal::NativeWidgetDelegate* delegate,
+    CefRefPtr<CefWindow> window,
+    CefWindowDelegate* window_delegate)
+    : views::NativeWidgetMac(delegate),
+      window_(window),
+      window_delegate_(window_delegate) {}
+
+void CefNativeWidgetMac::SetBrowserView(BrowserView* browser_view) {
+  browser_view_ = browser_view;
+}
+
+void CefNativeWidgetMac::ValidateUserInterfaceItem(
+    int32_t tag,
+    remote_cocoa::mojom::ValidateUserInterfaceItemResult* result) {
+  if (!browser_view_) {
+    result->enable = false;
+    return;
+  }
+
+  return BrowserFrameMac::ValidateUserInterfaceItem(browser_view_->browser(),
+                                                    tag, result);
+}
+
+bool CefNativeWidgetMac::WillExecuteCommand(
+    int32_t command,
+    WindowOpenDisposition window_open_disposition,
+    bool is_before_first_responder) {
+  if (!browser_view_) {
+    return false;
+  }
+
+  return BrowserFrameMac::WillExecuteCommand(browser_view_->browser(), command,
+                                             window_open_disposition,
+                                             is_before_first_responder);
+}
+
+bool CefNativeWidgetMac::ExecuteCommand(
+    int32_t command,
+    WindowOpenDisposition window_open_disposition,
+    bool is_before_first_responder) {
+  if (!browser_view_) {
+    return false;
+  }
+
+  return BrowserFrameMac::ExecuteCommand(browser_view_->browser(), command,
+                                         window_open_disposition,
+                                         is_before_first_responder);
+}
+
+NativeWidgetMacNSWindow* CefNativeWidgetMac::CreateNSWindow(
+    const remote_cocoa::mojom::CreateWindowParams* params) {
+  NSUInteger style_mask =
+      NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable |
+      NSWindowStyleMaskClosable | NSWindowStyleMaskResizable |
+      NSWindowStyleMaskTexturedBackground;
+
+  bool is_frameless = window_delegate_->IsFrameless(window_);
+
+  auto window = [[CefNSWindow alloc] initWithStyle:style_mask
+                                       isFrameless:is_frameless];
+
+  if (is_frameless) {
+    [window setTitlebarAppearsTransparent:YES];
+    [window setTitleVisibility:NSWindowTitleHidden];
+  }
+
+  if (!window_delegate_->WithStandardWindowButtons(window_)) {
+    [[window standardWindowButton:NSWindowCloseButton] setHidden:YES];
+    [[window standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
+    [[window standardWindowButton:NSWindowZoomButton] setHidden:YES];
+  }
+
+  return window;
+}
+
+void CefNativeWidgetMac::GetWindowFrameTitlebarHeight(
+    bool* override_titlebar_height,
+    float* titlebar_height) {
+  if (window_delegate_->GetTitlebarHeight(window_, titlebar_height)) {
+    *override_titlebar_height = true;
+  } else {
+    views::NativeWidgetMac::GetWindowFrameTitlebarHeight(
+        override_titlebar_height, titlebar_height);
+  }
+}
+
+void CefNativeWidgetMac::OnWindowFullscreenTransitionStart() {
+  views::NativeWidgetMac::OnWindowFullscreenTransitionStart();
+  if (IsCefWindowInitialized()) {
+    window_delegate_->OnWindowFullscreenTransition(window_, false);
+    if (browser_view_) {
+      browser_view_->FullscreenStateChanging();
+    }
+  }
+}
+
+void CefNativeWidgetMac::OnWindowFullscreenTransitionComplete() {
+  views::NativeWidgetMac::OnWindowFullscreenTransitionComplete();
+  if (IsCefWindowInitialized()) {
+    if (browser_view_) {
+      browser_view_->FullscreenStateChanged();
+    }
+    window_delegate_->OnWindowFullscreenTransition(window_, true);
+  }
+}
+
+void CefNativeWidgetMac::OnWindowInitialized() {
+  if (!browser_view_) {
+    return;
+  }
+
+  // From BrowserFrameMac::OnWindowInitialized.
+  if (auto* bridge = GetInProcessNSWindowBridge()) {
+    bridge->SetCommandDispatcher([[ChromeCommandDispatcherDelegate alloc] init],
+                                 [[BrowserWindowCommandHandler alloc] init]);
+  } else {
+    if (auto* host = GetHostForBrowser(browser_view_->browser())) {
+      host->GetAppShim()->CreateCommandDispatcherForWidget(
+          GetNSWindowHost()->bridged_native_widget_id());
+    }
+  }
+}
+
+bool CefNativeWidgetMac::IsCefWindowInitialized() const {
+  return static_cast<CefWindowImpl*>(window_.get())->initialized();
+}
diff --git a/src/libcef/browser/views/ns_window.h b/src/libcef/browser/views/ns_window.h
new file mode 100644
index 0000000..2ed159c
--- /dev/null
+++ b/src/libcef/browser/views/ns_window.h
@@ -0,0 +1,20 @@
+// Copyright 2023 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_VIEWS_NS_WINDOW_H_
+#define CEF_LIBCEF_BROWSER_VIEWS_NS_WINDOW_H_
+#pragma once
+
+#include "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h"
+
+@interface CefNSWindow : NativeWidgetMacNSWindow {
+ @private
+  bool is_frameless_;
+}
+- (id)initWithStyle:(NSUInteger)style_mask isFrameless:(bool)is_frameless;
+
+- (BOOL)shouldCenterTrafficLights;
+@end
+
+#endif  // CEF_LIBCEF_BROWSER_VIEWS_NS_WINDOW_H_
diff --git a/src/libcef/browser/views/ns_window.mm b/src/libcef/browser/views/ns_window.mm
new file mode 100644
index 0000000..5327db1
--- /dev/null
+++ b/src/libcef/browser/views/ns_window.mm
@@ -0,0 +1,105 @@
+// Copyright 2023 The Chromium Embedded Framework 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 "libcef/browser/views/ns_window.h"
+
+#include "base/i18n/rtl.h"
+#include "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
+#include "components/remote_cocoa/common/native_widget_ns_window_host.mojom.h"
+#include "ui/base/cocoa/window_size_constants.h"
+
+@interface CefThemeFrame : NativeWidgetMacNSWindowTitledFrame
+@end
+
+// NSThemeFrame (PrivateAPI) definitions.
+@interface NSThemeFrame (PrivateAPI)
+- (void)setStyleMask:(NSUInteger)styleMask;
+- (CGFloat)_titlebarHeight;
+- (BOOL)_shouldCenterTrafficLights;
+@end
+
+@implementation CefThemeFrame {
+  bool in_full_screen_;
+}
+
+// NSThemeFrame (PrivateAPI) overrides.
+- (void)setStyleMask:(NSUInteger)styleMask {
+  in_full_screen_ = (styleMask & NSWindowStyleMaskFullScreen) != 0;
+  [super setStyleMask:styleMask];
+}
+
+- (CGFloat)_titlebarHeight {
+  if (!in_full_screen_) {
+    bool override_titlebar_height = false;
+    float titlebar_height = 0;
+    auto* window = base::apple::ObjCCast<CefNSWindow>([self window]);
+    if (auto* bridge = [window bridge]) {
+      bridge->host()->GetWindowFrameTitlebarHeight(&override_titlebar_height,
+                                                   &titlebar_height);
+
+      if (override_titlebar_height) {
+        return titlebar_height;
+      }
+    }
+  }
+
+  return [super _titlebarHeight];
+}
+
+- (BOOL)_shouldCenterTrafficLights {
+  auto* window = base::apple::ObjCCast<CefNSWindow>([self window]);
+  return [window shouldCenterTrafficLights];
+}
+
+- (BOOL)_shouldFlipTrafficLightsForRTL {
+  return base::i18n::IsRTL() ? YES : NO;
+}
+
+@end
+
+@interface NSWindow (PrivateAPI)
++ (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle;
+@end
+
+@implementation CefNSWindow
+
+- (id)initWithStyle:(NSUInteger)style_mask isFrameless:(bool)is_frameless {
+  if ((self = [super initWithContentRect:ui::kWindowSizeDeterminedLater
+                               styleMask:style_mask
+                                 backing:NSBackingStoreBuffered
+                                   defer:NO])) {
+    is_frameless_ = is_frameless;
+  }
+  return self;
+}
+
+- (BOOL)shouldCenterTrafficLights {
+  return is_frameless_ ? YES : NO;
+}
+
+// NSWindow overrides.
+- (NSRect)contentRectForFrameRect:(NSRect)frameRect {
+  if (is_frameless_) {
+    return frameRect;
+  }
+  return [super contentRectForFrameRect:frameRect];
+}
+
+- (NSRect)frameRectForContentRect:(NSRect)contentRect {
+  if (is_frameless_) {
+    return contentRect;
+  }
+  return [super frameRectForContentRect:contentRect];
+}
+
+// NSWindow (PrivateAPI) overrides.
++ (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle {
+  if (Class custom_frame = [CefThemeFrame class]) {
+    return custom_frame;
+  }
+
+  return [super frameViewClassForStyleMask:windowStyle];
+}
+
+@end
diff --git a/src/libcef/browser/views/overlay_view_host.cc b/src/libcef/browser/views/overlay_view_host.cc
new file mode 100644
index 0000000..43ca479
--- /dev/null
+++ b/src/libcef/browser/views/overlay_view_host.cc
@@ -0,0 +1,327 @@
+// Copyright 2021 The Chromium Embedded Framework Authors. Portions copyright
+// 2011 The Chromium Authors. All rights reserved. Use of this source code is
+// governed by a BSD-style license that can be found in the LICENSE file.
+
+#include "libcef/browser/views/overlay_view_host.h"
+
+#include "libcef/browser/views/view_util.h"
+#include "libcef/browser/views/window_view.h"
+
+#include "base/i18n/rtl.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/theme_copying_widget.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/compositor/compositor.h"
+#include "ui/compositor/layer.h"
+
+namespace {
+
+class CefOverlayControllerImpl : public CefOverlayController {
+ public:
+  CefOverlayControllerImpl(CefOverlayViewHost* host, CefRefPtr<CefView> view)
+      : host_(host), view_(view) {}
+
+  CefOverlayControllerImpl(const CefOverlayControllerImpl&) = delete;
+  CefOverlayControllerImpl& operator=(const CefOverlayControllerImpl&) = delete;
+
+  bool IsValid() override {
+    // View validity implies that CefOverlayViewHost is still valid, because the
+    // Widget that it owns (and that owns the View) is still valid.
+    return view_ && view_->IsValid();
+  }
+
+  bool IsSame(CefRefPtr<CefOverlayController> that) override {
+    return that && that->GetContentsView()->IsSame(view_);
+  }
+
+  CefRefPtr<CefView> GetContentsView() override { return view_; }
+
+  CefRefPtr<CefWindow> GetWindow() override {
+    if (IsValid()) {
+      return view_util::GetWindowFor(host_->window_view()->GetWidget());
+    }
+    return nullptr;
+  }
+
+  cef_docking_mode_t GetDockingMode() override {
+    if (IsValid()) {
+      return host_->docking_mode();
+    }
+    return CEF_DOCKING_MODE_TOP_LEFT;
+  }
+
+  void Destroy() override {
+    if (IsValid()) {
+      host_->Destroy();
+      view_ = nullptr;
+    }
+  }
+
+  void SetBounds(const CefRect& bounds) override {
+    if (IsValid() && host_->docking_mode() == CEF_DOCKING_MODE_CUSTOM) {
+      host_->SetOverlayBounds(
+          gfx::Rect(bounds.x, bounds.y, bounds.width, bounds.height));
+    }
+  }
+
+  CefRect GetBounds() override {
+    if (IsValid()) {
+      const auto& bounds = host_->bounds();
+      return CefRect(bounds.x(), bounds.y(), bounds.width(), bounds.height());
+    }
+    return CefRect();
+  }
+
+  CefRect GetBoundsInScreen() override {
+    if (IsValid()) {
+      const auto& bounds = host_->widget()->GetWindowBoundsInScreen();
+      return CefRect(bounds.x(), bounds.y(), bounds.width(), bounds.height());
+    }
+    return CefRect();
+  }
+
+  void SetSize(const CefSize& size) override {
+    if (IsValid() && host_->docking_mode() == CEF_DOCKING_MODE_CUSTOM) {
+      // Update the size without changing the origin.
+      const auto& origin = host_->bounds().origin();
+      host_->SetOverlayBounds(
+          gfx::Rect(origin, gfx::Size(size.width, size.height)));
+    }
+  }
+
+  CefSize GetSize() override {
+    const auto& bounds = GetBounds();
+    return CefSize(bounds.width, bounds.height);
+  }
+
+  void SetPosition(const CefPoint& position) override {
+    if (IsValid() && host_->docking_mode() == CEF_DOCKING_MODE_CUSTOM) {
+      // Update the origin without changing the size.
+      const auto& size = host_->bounds().size();
+      host_->SetOverlayBounds(
+          gfx::Rect(gfx::Point(position.x, position.y), size));
+    }
+  }
+
+  CefPoint GetPosition() override {
+    const auto& bounds = GetBounds();
+    return CefPoint(bounds.x, bounds.y);
+  }
+
+  void SetInsets(const CefInsets& insets) override {
+    if (IsValid() && host_->docking_mode() != CEF_DOCKING_MODE_CUSTOM) {
+      host_->SetOverlayInsets(insets);
+    }
+  }
+
+  CefInsets GetInsets() override {
+    if (IsValid()) {
+      return host_->insets();
+    }
+    return CefInsets();
+  }
+
+  void SizeToPreferredSize() override {
+    if (IsValid()) {
+      if (host_->docking_mode() == CEF_DOCKING_MODE_CUSTOM) {
+        // Update the size without changing the origin.
+        const auto& origin = host_->bounds().origin();
+        const auto& preferred_size = host_->view()->GetPreferredSize();
+        host_->SetOverlayBounds(gfx::Rect(origin, preferred_size));
+      } else {
+        host_->MoveIfNecessary();
+      }
+    }
+  }
+
+  void SetVisible(bool visible) override {
+    if (IsValid()) {
+      if (visible) {
+        host_->MoveIfNecessary();
+        host_->widget()->Show();
+      } else {
+        host_->widget()->Hide();
+      }
+    }
+  }
+
+  bool IsVisible() override {
+    if (IsValid()) {
+      return host_->widget()->IsVisible();
+    }
+    return false;
+  }
+
+  bool IsDrawn() override { return IsVisible(); }
+
+ private:
+  CefOverlayViewHost* const host_;
+  CefRefPtr<CefView> view_;
+
+  IMPLEMENT_REFCOUNTING(CefOverlayControllerImpl);
+};
+
+}  // namespace
+
+CefOverlayViewHost::CefOverlayViewHost(CefWindowView* window_view,
+                                       cef_docking_mode_t docking_mode)
+    : window_view_(window_view), docking_mode_(docking_mode) {}
+
+void CefOverlayViewHost::Init(views::View* host_view, CefRefPtr<CefView> view) {
+  DCHECK(view);
+
+  // Match the logic in CEF_PANEL_IMPL_D::AddChildView().
+  auto controls_view = view->IsAttached()
+                           ? base::WrapUnique(view_util::GetFor(view))
+                           : view_util::PassOwnership(view);
+  DCHECK(controls_view.get());
+
+  cef_controller_ = new CefOverlayControllerImpl(this, view);
+
+  // Initialize the Widget.
+  widget_ = std::make_unique<ThemeCopyingWidget>(window_view_->GetWidget());
+  views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
+  params.delegate = this;
+  params.name = "CefOverlayViewHost";
+  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  params.parent = window_view_->GetWidget()->GetNativeView();
+  params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
+  params.activatable = views::Widget::InitParams::Activatable::kNo;
+  widget_->Init(std::move(params));
+
+  view_ = widget_->GetContentsView()->AddChildView(std::move(controls_view));
+
+  // Make the Widget background transparent. The View might still be opaque.
+  if (widget_->GetCompositor()) {
+    widget_->GetCompositor()->SetBackgroundColor(SK_ColorTRANSPARENT);
+  }
+
+  view_util::SetHostView(widget_.get(), host_view);
+
+  if (cef::IsChromeRuntimeEnabled()) {
+    // Some attributes associated with a Chrome toolbar are located via the
+    // Widget. See matching logic in BrowserView::AddedToWidget.
+    auto browser_view = BrowserView::GetBrowserViewForNativeWindow(
+        view_util::GetNativeWindow(window_view_->GetWidget()));
+    if (browser_view) {
+      widget_->SetNativeWindowProperty(BrowserView::kBrowserViewKey,
+                                       browser_view);
+    }
+  }
+
+  // Set the initial bounds after the View has been added to the Widget.
+  // Otherwise, preferred size won't calculate correctly.
+  gfx::Rect bounds;
+  if (docking_mode_ == CEF_DOCKING_MODE_CUSTOM) {
+    if (view_->size().IsEmpty()) {
+      // Size to the preferred size to start.
+      view_->SizeToPreferredSize();
+    }
+
+    // Top-left origin with existing size.
+    bounds = gfx::Rect(gfx::Point(), view_->size());
+  } else {
+    bounds = ComputeBounds();
+  }
+  SetOverlayBounds(bounds);
+
+  // Register for future bounds change notifications.
+  view_->AddObserver(this);
+
+  // Initially hidden.
+  widget_->Hide();
+}
+
+void CefOverlayViewHost::Destroy() {
+  if (widget_ && !widget_->IsClosed()) {
+    // Remove the child View immediately. It may be reused by the client.
+    auto view = view_util::GetFor(view_, /*find_known_parent=*/false);
+    widget_->GetContentsView()->RemoveChildView(view_);
+    if (view) {
+      view_util::ResumeOwnership(view);
+    }
+
+    widget_->Close();
+  }
+}
+
+void CefOverlayViewHost::MoveIfNecessary() {
+  if (bounds_changing_ || docking_mode_ == CEF_DOCKING_MODE_CUSTOM) {
+    return;
+  }
+  SetOverlayBounds(ComputeBounds());
+}
+
+void CefOverlayViewHost::SetOverlayBounds(const gfx::Rect& bounds) {
+  // Avoid re-entrancy of this method.
+  if (bounds_changing_) {
+    return;
+  }
+
+  gfx::Rect new_bounds = bounds;
+
+  // Keep the result inside the widget.
+  new_bounds.Intersect(window_view_->bounds());
+
+  if (new_bounds == bounds_) {
+    return;
+  }
+
+  bounds_changing_ = true;
+
+  bounds_ = new_bounds;
+  if (view_->size() != bounds_.size()) {
+    view_->SetSize(bounds_.size());
+  }
+  widget_->SetBounds(bounds_);
+
+  bounds_changing_ = false;
+}
+
+void CefOverlayViewHost::SetOverlayInsets(const CefInsets& insets) {
+  if (insets == insets_) {
+    return;
+  }
+  insets_ = insets;
+  MoveIfNecessary();
+}
+
+void CefOverlayViewHost::OnViewBoundsChanged(views::View* observed_view) {
+  MoveIfNecessary();
+}
+
+gfx::Rect CefOverlayViewHost::ComputeBounds() const {
+  // This method is only used with corner docking.
+  DCHECK_NE(docking_mode_, CEF_DOCKING_MODE_CUSTOM);
+
+  // Find the area we have to work with.
+  const auto& widget_bounds = window_view_->bounds();
+
+  // Ask the view how large an area it needs to draw on.
+  const auto& prefsize = view_->GetPreferredSize();
+
+  // Swap left/right docking with RTL.
+  const bool is_rtl = base::i18n::IsRTL();
+
+  // Dock to the correct corner, considering insets in the docking corner only.
+  int x = widget_bounds.x();
+  int y = widget_bounds.y();
+  if (((docking_mode_ == CEF_DOCKING_MODE_TOP_RIGHT ||
+        docking_mode_ == CEF_DOCKING_MODE_BOTTOM_RIGHT) &&
+       !is_rtl) ||
+      ((docking_mode_ == CEF_DOCKING_MODE_TOP_LEFT ||
+        docking_mode_ == CEF_DOCKING_MODE_BOTTOM_LEFT) &&
+       is_rtl)) {
+    x += widget_bounds.width() - prefsize.width() - insets_.right;
+  } else {
+    x += insets_.left;
+  }
+  if (docking_mode_ == CEF_DOCKING_MODE_BOTTOM_LEFT ||
+      docking_mode_ == CEF_DOCKING_MODE_BOTTOM_RIGHT) {
+    y += widget_bounds.height() - prefsize.height() - insets_.bottom;
+  } else {
+    y += insets_.top;
+  }
+
+  return gfx::Rect(x, y, prefsize.width(), prefsize.height());
+}
diff --git a/src/libcef/browser/views/overlay_view_host.h b/src/libcef/browser/views/overlay_view_host.h
new file mode 100644
index 0000000..e761d6c
--- /dev/null
+++ b/src/libcef/browser/views/overlay_view_host.h
@@ -0,0 +1,78 @@
+// Copyright 2021 The Chromium Embedded Framework Authors. Portions copyright
+// 2011 The Chromium Authors. All rights reserved. Use of this source code is
+// governed by a BSD-style license that can be found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_BROWSER_VIEWS_OVERLAY_VIEW_HOST_H_
+#define CEF_LIBCEF_BROWSER_VIEWS_OVERLAY_VIEW_HOST_H_
+#pragma once
+
+#include <memory>
+
+#include "include/views/cef_overlay_controller.h"
+#include "include/views/cef_view.h"
+
+#include "ui/views/view_observer.h"
+#include "ui/views/widget/widget_delegate.h"
+
+class CefWindowView;
+
+// Host class for a child Widget that behaves as an overlay control. Based on
+// Chrome's DropdownBarHost.
+class CefOverlayViewHost : public views::WidgetDelegate,
+                           public views::ViewObserver {
+ public:
+  // |window_view| is the top-level view that contains this overlay.
+  CefOverlayViewHost(CefWindowView* window_view,
+                     cef_docking_mode_t docking_mode);
+
+  CefOverlayViewHost(const CefOverlayViewHost&) = delete;
+  CefOverlayViewHost& operator=(const CefOverlayViewHost&) = delete;
+
+  // Initializes the CefOverlayViewHost. This creates the Widget that |view|
+  // paints into. On Aura platforms, |host_view| is the view whose position in
+  // the |window_view_| view hierarchy determines the z-order of the widget
+  // relative to views with layers and views with associated NativeViews.
+  void Init(views::View* host_view, CefRefPtr<CefView> view);
+
+  void Destroy();
+
+  void MoveIfNecessary();
+
+  void SetOverlayBounds(const gfx::Rect& bounds);
+  void SetOverlayInsets(const CefInsets& insets);
+
+  // views::ViewObserver methods:
+  void OnViewBoundsChanged(views::View* observed_view) override;
+
+  cef_docking_mode_t docking_mode() const { return docking_mode_; }
+  CefRefPtr<CefOverlayController> controller() const { return cef_controller_; }
+  CefWindowView* window_view() const { return window_view_; }
+  views::Widget* widget() const { return widget_.get(); }
+  views::View* view() const { return view_; }
+  gfx::Rect bounds() const { return bounds_; }
+  CefInsets insets() const { return insets_; }
+
+ private:
+  gfx::Rect ComputeBounds() const;
+
+  // The CefWindowView that created us.
+  CefWindowView* const window_view_;
+
+  const cef_docking_mode_t docking_mode_;
+
+  // Our view, which is responsible for drawing the UI.
+  views::View* view_ = nullptr;
+
+  // The Widget implementation that is created and maintained by the overlay.
+  // It contains |view_|.
+  std::unique_ptr<views::Widget> widget_;
+
+  CefRefPtr<CefOverlayController> cef_controller_;
+
+  gfx::Rect bounds_;
+  bool bounds_changing_ = false;
+
+  CefInsets insets_;
+};
+
+#endif  // CEF_LIBCEF_BROWSER_VIEWS_OVERLAY_VIEW_HOST_H_
diff --git a/src/libcef/browser/views/panel_impl.h b/src/libcef/browser/views/panel_impl.h
index 990f931..56083b2 100644
--- a/src/libcef/browser/views/panel_impl.h
+++ b/src/libcef/browser/views/panel_impl.h
@@ -27,7 +27,7 @@
 // view_impl.h for a usage overview.
 CEF_PANEL_IMPL_T class CefPanelImpl : public CEF_VIEW_IMPL_D {
  public:
-  typedef CEF_VIEW_IMPL_D ParentClass;
+  using ParentClass = CEF_VIEW_IMPL_D;
 
   // CefPanel methods. When adding new As*() methods make sure to update
   // CefViewAdapter::GetFor() in view_adapter.cc.
@@ -49,22 +49,20 @@
   CefRefPtr<CefPanel> AsPanel() override { return this; }
 
   // CefViewAdapter methods:
-  void GetDebugInfo(base::DictionaryValue* info,
-                    bool include_children) override {
+  void GetDebugInfo(base::Value::Dict* info, bool include_children) override {
     ParentClass::GetDebugInfo(info, include_children);
     if (include_children) {
       const size_t count = ParentClass::content_view()->children().size();
       if (count > 0U) {
-        std::unique_ptr<base::ListValue> children(new base::ListValue());
+        base::Value::List children;
 
         for (size_t i = 0U; i < count; ++i) {
           views::View* view = ParentClass::content_view()->children()[i];
           CefViewAdapter* adapter = CefViewAdapter::GetFor(view);
           if (adapter) {
-            std::unique_ptr<base::DictionaryValue> child_info(
-                new base::DictionaryValue());
-            adapter->GetDebugInfo(child_info.get(), include_children);
-            children->Append(std::move(child_info));
+            base::Value::Dict child_info;
+            adapter->GetDebugInfo(&child_info, include_children);
+            children.Append(std::move(child_info));
           }
         }
 
@@ -113,12 +111,15 @@
   CEF_REQUIRE_VALID_RETURN_VOID();
   DCHECK(view.get());
   DCHECK(view->IsValid());
-  DCHECK(!view->IsAttached());
-  if (!view.get() || !view->IsValid() || view->IsAttached())
+  if (!view.get() || !view->IsValid()) {
     return;
+  }
 
-  std::unique_ptr<views::View> view_ptr = view_util::PassOwnership(view);
-  ParentClass::content_view()->AddChildView(view_ptr.release());
+  auto* view_ptr = view->IsAttached()
+                       ? view_util::GetFor(view)
+                       : view_util::PassOwnership(view).release();
+  DCHECK(view_ptr);
+  ParentClass::content_view()->AddChildView(view_ptr);
 }
 
 CEF_PANEL_IMPL_T void CEF_PANEL_IMPL_D::AddChildViewAt(CefRefPtr<CefView> view,
@@ -126,18 +127,20 @@
   CEF_REQUIRE_VALID_RETURN_VOID();
   DCHECK(view.get());
   DCHECK(view->IsValid());
-  DCHECK(!view->IsAttached());
   DCHECK_GE(index, 0);
   DCHECK_LE(static_cast<unsigned int>(index),
             ParentClass::content_view()->children().size());
-  if (!view.get() || !view->IsValid() || view->IsAttached() || index < 0 ||
+  if (!view.get() || !view->IsValid() || index < 0 ||
       (static_cast<unsigned int>(index) >
        ParentClass::content_view()->children().size())) {
     return;
   }
 
-  std::unique_ptr<views::View> view_ptr = view_util::PassOwnership(view);
-  ParentClass::content_view()->AddChildViewAt(view_ptr.release(), index);
+  auto* view_ptr = view->IsAttached()
+                       ? view_util::GetFor(view)
+                       : view_util::PassOwnership(view).release();
+  DCHECK(view_ptr);
+  ParentClass::content_view()->AddChildViewAt(view_ptr, index);
 }
 
 CEF_PANEL_IMPL_T void CEF_PANEL_IMPL_D::ReorderChildView(
@@ -147,14 +150,16 @@
   DCHECK(view.get());
   DCHECK(view->IsValid());
   DCHECK(view->IsAttached());
-  if (!view.get() || !view->IsValid() || !view->IsAttached())
+  if (!view.get() || !view->IsValid() || !view->IsAttached()) {
     return;
+  }
 
   views::View* view_ptr = view_util::GetFor(view);
   DCHECK(view_ptr);
   DCHECK_EQ(view_ptr->parent(), ParentClass::content_view());
-  if (!view_ptr || view_ptr->parent() != ParentClass::content_view())
+  if (!view_ptr || view_ptr->parent() != ParentClass::content_view()) {
     return;
+  }
 
   ParentClass::content_view()->ReorderChildView(view_ptr, index);
 }
@@ -165,14 +170,16 @@
   DCHECK(view.get());
   DCHECK(view->IsValid());
   DCHECK(view->IsAttached());
-  if (!view.get() || !view->IsValid() || !view->IsAttached())
+  if (!view.get() || !view->IsValid() || !view->IsAttached()) {
     return;
+  }
 
   views::View* view_ptr = view_util::GetFor(view);
   DCHECK(view_ptr);
   DCHECK_EQ(view_ptr->parent(), ParentClass::content_view());
-  if (!view_ptr || view_ptr->parent() != ParentClass::content_view())
+  if (!view_ptr || view_ptr->parent() != ParentClass::content_view()) {
     return;
+  }
 
   ParentClass::content_view()->RemoveChildView(view_ptr);
   view_util::ResumeOwnership(view);
@@ -199,8 +206,9 @@
   DCHECK_LT(static_cast<unsigned int>(index),
             ParentClass::content_view()->children().size());
   if (index < 0 || (static_cast<unsigned int>(index) >=
-                    ParentClass::content_view()->children().size()))
+                    ParentClass::content_view()->children().size())) {
     return nullptr;
+  }
 
   CefRefPtr<CefView> view =
       view_util::GetFor(ParentClass::content_view()->children()[index], false);
diff --git a/src/libcef/browser/views/panel_view.h b/src/libcef/browser/views/panel_view.h
index 13d7808..ef6d0e2 100644
--- a/src/libcef/browser/views/panel_view.h
+++ b/src/libcef/browser/views/panel_view.h
@@ -23,11 +23,12 @@
 // view_impl.h for a usage overview.
 CEF_PANEL_VIEW_T class CefPanelView : public CEF_VIEW_VIEW_D {
  public:
-  typedef CEF_VIEW_VIEW_D ParentClass;
+  using ParentClass = CEF_VIEW_VIEW_D;
 
   // |cef_delegate| may be nullptr.
-  explicit CefPanelView(CefViewDelegateClass* cef_delegate)
-      : ParentClass(cef_delegate) {}
+  template <typename... Args>
+  explicit CefPanelView(CefViewDelegateClass* cef_delegate, Args... args)
+      : ParentClass(cef_delegate, args...) {}
 
   // Returns the CefPanel associated with this view. See comments on
   // CefViewView::GetCefView.
diff --git a/src/libcef/browser/views/scroll_view_impl.cc b/src/libcef/browser/views/scroll_view_impl.cc
index 61d3fd0..946f1e4 100644
--- a/src/libcef/browser/views/scroll_view_impl.cc
+++ b/src/libcef/browser/views/scroll_view_impl.cc
@@ -24,8 +24,9 @@
   DCHECK(view.get());
   DCHECK(view->IsValid());
   DCHECK(!view->IsAttached());
-  if (!view.get() || !view->IsValid() || view->IsAttached())
+  if (!view.get() || !view->IsValid() || view->IsAttached()) {
     return;
+  }
 
   root_view()->SetContents(view_util::PassOwnership(view));
 }
@@ -63,16 +64,15 @@
   return root_view()->GetScrollBarLayoutWidth();
 }
 
-void CefScrollViewImpl::GetDebugInfo(base::DictionaryValue* info,
+void CefScrollViewImpl::GetDebugInfo(base::Value::Dict* info,
                                      bool include_children) {
   ParentClass::GetDebugInfo(info, include_children);
   if (include_children) {
     views::View* view = root_view()->contents();
     CefViewAdapter* adapter = CefViewAdapter::GetFor(view);
     if (adapter) {
-      std::unique_ptr<base::DictionaryValue> child_info(
-          new base::DictionaryValue());
-      adapter->GetDebugInfo(child_info.get(), include_children);
+      base::Value::Dict child_info;
+      adapter->GetDebugInfo(&child_info, include_children);
       info->Set("content_view", std::move(child_info));
     }
   }
diff --git a/src/libcef/browser/views/scroll_view_impl.h b/src/libcef/browser/views/scroll_view_impl.h
index ca27690..47d47cf 100644
--- a/src/libcef/browser/views/scroll_view_impl.h
+++ b/src/libcef/browser/views/scroll_view_impl.h
@@ -15,8 +15,11 @@
 class CefScrollViewImpl
     : public CefViewImpl<CefScrollViewView, CefScrollView, CefViewDelegate> {
  public:
-  typedef CefViewImpl<CefScrollViewView, CefScrollView, CefViewDelegate>
-      ParentClass;
+  using ParentClass =
+      CefViewImpl<CefScrollViewView, CefScrollView, CefViewDelegate>;
+
+  CefScrollViewImpl(const CefScrollViewImpl&) = delete;
+  CefScrollViewImpl& operator=(const CefScrollViewImpl&) = delete;
 
   // Create a new CefScrollView instance. |delegate| may be nullptr.
   static CefRefPtr<CefScrollViewImpl> Create(
@@ -34,8 +37,7 @@
 
   // CefViewAdapter methods:
   std::string GetDebugType() override { return "ScrollView"; }
-  void GetDebugInfo(base::DictionaryValue* info,
-                    bool include_children) override;
+  void GetDebugInfo(base::Value::Dict* info, bool include_children) override;
 
  private:
   // Create a new implementation object.
@@ -48,7 +50,6 @@
   void InitializeRootView() override;
 
   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefScrollViewImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefScrollViewImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_SCROLL_VIEW_IMPL_H_
diff --git a/src/libcef/browser/views/scroll_view_view.h b/src/libcef/browser/views/scroll_view_view.h
index 62a7c4b..89d7e5d 100644
--- a/src/libcef/browser/views/scroll_view_view.h
+++ b/src/libcef/browser/views/scroll_view_view.h
@@ -15,13 +15,13 @@
 class CefScrollViewView
     : public CefViewView<views::ScrollView, CefViewDelegate> {
  public:
-  typedef CefViewView<views::ScrollView, CefViewDelegate> ParentClass;
+  using ParentClass = CefViewView<views::ScrollView, CefViewDelegate>;
 
   // |cef_delegate| may be nullptr.
   explicit CefScrollViewView(CefViewDelegate* cef_delegate);
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefScrollViewView);
+  CefScrollViewView(const CefScrollViewView&) = delete;
+  CefScrollViewView& operator=(const CefScrollViewView&) = delete;
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_SCROLL_VIEW_VIEW_H_
diff --git a/src/libcef/browser/views/textfield_impl.cc b/src/libcef/browser/views/textfield_impl.cc
index 1437fdf..f1afd97 100644
--- a/src/libcef/browser/views/textfield_impl.cc
+++ b/src/libcef/browser/views/textfield_impl.cc
@@ -6,6 +6,25 @@
 
 #include "libcef/browser/thread_util.h"
 
+namespace {
+static int CefCommandIdToChromeId(cef_text_field_commands_t command_id) {
+  switch (command_id) {
+    case cef_text_field_commands_t::CEF_TFC_CUT:
+      return views::Textfield::kCut;
+    case cef_text_field_commands_t::CEF_TFC_COPY:
+      return views::Textfield::kCopy;
+    case cef_text_field_commands_t::CEF_TFC_PASTE:
+      return views::Textfield::kPaste;
+    case cef_text_field_commands_t::CEF_TFC_UNDO:
+      return views::Textfield::kUndo;
+    case cef_text_field_commands_t::CEF_TFC_DELETE:
+      return views::Textfield::kDelete;
+    case cef_text_field_commands_t::CEF_TFC_SELECT_ALL:
+      return views::Textfield::kSelectAll;
+  }
+}
+}  // namespace
+
 // static
 CefRefPtr<CefTextfield> CefTextfield::CreateTextfield(
     CefRefPtr<CefTextfieldDelegate> delegate) {
@@ -136,10 +155,11 @@
 void CefTextfieldImpl::ApplyTextColor(cef_color_t color,
                                       const CefRange& range) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (range.from == range.to)
+  if (range.from == range.to) {
     root_view()->SetColor(color);
-  else
+  } else {
     root_view()->ApplyColor(color, gfx::Range(range.from, range.to));
+  }
 }
 
 void CefTextfieldImpl::ApplyTextStyle(cef_text_style_t style,
@@ -154,15 +174,17 @@
   }
 }
 
-bool CefTextfieldImpl::IsCommandEnabled(int command_id) {
+bool CefTextfieldImpl::IsCommandEnabled(cef_text_field_commands_t command_id) {
   CEF_REQUIRE_VALID_RETURN(false);
-  return root_view()->IsCommandIdEnabled(command_id);
+  return root_view()->IsCommandIdEnabled(CefCommandIdToChromeId(command_id));
 }
 
-void CefTextfieldImpl::ExecuteCommand(int command_id) {
+void CefTextfieldImpl::ExecuteCommand(cef_text_field_commands_t command_id) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (root_view()->IsCommandIdEnabled(command_id))
-    root_view()->ExecuteCommand(command_id, ui::EF_NONE);
+  if (root_view()->IsCommandIdEnabled(CefCommandIdToChromeId(command_id))) {
+    root_view()->ExecuteCommand(CefCommandIdToChromeId(command_id),
+                                ui::EF_NONE);
+  }
 }
 
 void CefTextfieldImpl::ClearEditHistory() {
diff --git a/src/libcef/browser/views/textfield_impl.h b/src/libcef/browser/views/textfield_impl.h
index b620fc4..8a5ac40 100644
--- a/src/libcef/browser/views/textfield_impl.h
+++ b/src/libcef/browser/views/textfield_impl.h
@@ -15,8 +15,11 @@
 class CefTextfieldImpl
     : public CefViewImpl<CefTextfieldView, CefTextfield, CefTextfieldDelegate> {
  public:
-  typedef CefViewImpl<CefTextfieldView, CefTextfield, CefTextfieldDelegate>
-      ParentClass;
+  using ParentClass =
+      CefViewImpl<CefTextfieldView, CefTextfield, CefTextfieldDelegate>;
+
+  CefTextfieldImpl(const CefTextfieldImpl&) = delete;
+  CefTextfieldImpl& operator=(const CefTextfieldImpl&) = delete;
 
   // Create a new CefTextfield instance. |delegate| may be nullptr.
   static CefRefPtr<CefTextfieldImpl> Create(
@@ -49,8 +52,8 @@
   void ApplyTextStyle(cef_text_style_t style,
                       bool add,
                       const CefRange& range) override;
-  bool IsCommandEnabled(int command_id) override;
-  void ExecuteCommand(int command_id) override;
+  bool IsCommandEnabled(cef_text_field_commands_t command_id) override;
+  void ExecuteCommand(cef_text_field_commands_t command_id) override;
   void ClearEditHistory() override;
   void SetPlaceholderText(const CefString& text) override;
   CefString GetPlaceholderText() override;
@@ -76,7 +79,6 @@
   void InitializeRootView() override;
 
   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefTextfieldImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefTextfieldImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_TEXTFIELD_IMPL_H_
diff --git a/src/libcef/browser/views/textfield_view.cc b/src/libcef/browser/views/textfield_view.cc
index 4029f87..103d108 100644
--- a/src/libcef/browser/views/textfield_view.cc
+++ b/src/libcef/browser/views/textfield_view.cc
@@ -22,18 +22,21 @@
                                       const ui::KeyEvent& key_event) {
   DCHECK_EQ(sender, this);
 
-  if (!cef_delegate())
+  if (!cef_delegate()) {
     return false;
+  }
 
   CefKeyEvent cef_key_event;
-  if (!browser_util::GetCefKeyEvent(key_event, cef_key_event))
+  if (!browser_util::GetCefKeyEvent(key_event, cef_key_event)) {
     return false;
+  }
 
   return cef_delegate()->OnKeyEvent(GetCefTextfield(), cef_key_event);
 }
 
 void CefTextfieldView::OnAfterUserAction(views::Textfield* sender) {
   DCHECK_EQ(sender, this);
-  if (cef_delegate())
+  if (cef_delegate()) {
     cef_delegate()->OnAfterUserAction(GetCefTextfield());
+  }
 }
diff --git a/src/libcef/browser/views/textfield_view.h b/src/libcef/browser/views/textfield_view.h
index b97187b..f4e4f5e 100644
--- a/src/libcef/browser/views/textfield_view.h
+++ b/src/libcef/browser/views/textfield_view.h
@@ -18,11 +18,14 @@
     : public CefViewView<views::Textfield, CefTextfieldDelegate>,
       public views::TextfieldController {
  public:
-  typedef CefViewView<views::Textfield, CefTextfieldDelegate> ParentClass;
+  using ParentClass = CefViewView<views::Textfield, CefTextfieldDelegate>;
 
   // |cef_delegate| may be nullptr.
   explicit CefTextfieldView(CefTextfieldDelegate* cef_delegate);
 
+  CefTextfieldView(const CefTextfieldView&) = delete;
+  CefTextfieldView& operator=(const CefTextfieldView&) = delete;
+
   void Initialize() override;
 
   // Returns the CefTextfield associated with this view. See comments on
@@ -37,9 +40,6 @@
   bool HandleKeyEvent(views::Textfield* sender,
                       const ui::KeyEvent& key_event) override;
   void OnAfterUserAction(views::Textfield* sender) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefTextfieldView);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_TEXTFIELD_VIEW_H_
diff --git a/src/libcef/browser/views/view_adapter.cc b/src/libcef/browser/views/view_adapter.cc
index 8f3aa4b..5c32573 100644
--- a/src/libcef/browser/views/view_adapter.cc
+++ b/src/libcef/browser/views/view_adapter.cc
@@ -4,6 +4,7 @@
 
 #include "libcef/browser/views/view_adapter.h"
 
+#include "libcef/browser/chrome/views/toolbar_view_impl.h"
 #include "libcef/browser/views/basic_label_button_impl.h"
 #include "libcef/browser/views/basic_panel_impl.h"
 #include "libcef/browser/views/browser_view_impl.h"
@@ -40,6 +41,9 @@
     adapter = static_cast<CefScrollViewImpl*>(view->AsScrollView().get());
   } else if (view->AsTextfield()) {
     adapter = static_cast<CefTextfieldImpl*>(view->AsTextfield().get());
+  } else if (view->GetTypeString().ToString() ==
+             CefToolbarViewImpl::kTypeString) {
+    adapter = static_cast<CefToolbarViewImpl*>(view.get());
   }
 
   DCHECK(adapter);
@@ -49,7 +53,8 @@
 // static
 CefViewAdapter* CefViewAdapter::GetFor(views::View* view) {
   CefRefPtr<CefView> cef_view = view_util::GetFor(view, false);
-  if (cef_view)
+  if (cef_view) {
     return GetFor(cef_view);
+  }
   return nullptr;
 }
diff --git a/src/libcef/browser/views/view_adapter.h b/src/libcef/browser/views/view_adapter.h
index 39dbf0b..958be7f 100644
--- a/src/libcef/browser/views/view_adapter.h
+++ b/src/libcef/browser/views/view_adapter.h
@@ -8,9 +8,7 @@
 
 #include "include/views/cef_view.h"
 
-namespace base {
-class DictionaryValue;
-}
+#include "base/values.h"
 
 namespace views {
 class View;
@@ -48,8 +46,7 @@
   virtual std::string GetDebugType() = 0;
 
   // Override this method to provide debug info specific to the View type.
-  virtual void GetDebugInfo(base::DictionaryValue* info,
-                            bool include_children) = 0;
+  virtual void GetDebugInfo(base::Value::Dict* info, bool include_children) = 0;
 
  protected:
   virtual ~CefViewAdapter() {}
diff --git a/src/libcef/browser/views/view_impl.h b/src/libcef/browser/views/view_impl.h
index 3cd6e10..d9e105d 100644
--- a/src/libcef/browser/views/view_impl.h
+++ b/src/libcef/browser/views/view_impl.h
@@ -299,6 +299,7 @@
 #include "base/logging.h"
 #include "base/values.h"
 #include "ui/views/background.h"
+#include "ui/views/border.h"
 #include "ui/views/view.h"
 
 // Helpers for template boiler-plate.
@@ -313,7 +314,7 @@
 CEF_VIEW_IMPL_T class CefViewImpl : public CefViewAdapter, public CefViewClass {
  public:
   // Necessary for the CEF_REQUIRE_VALID_*() macros to compile.
-  typedef CEF_VIEW_IMPL_D ParentClass;
+  using ParentClass = CEF_VIEW_IMPL_D;
 
   // Returns the content views::View object that should be the target of most
   // customization actions. May be the root view or a child of the root view.
@@ -337,23 +338,22 @@
     root_view_.reset(root_view_ref_);
   }
   void Detach() override {
-    if (root_view_)
+    if (root_view_) {
       root_view_.reset();
+    }
     root_view_ref_ = nullptr;
   }
-  void GetDebugInfo(base::DictionaryValue* info,
-                    bool include_children) override {
-    info->SetString("type", GetDebugType());
-    info->SetInteger("id", root_view()->GetID());
+  void GetDebugInfo(base::Value::Dict* info, bool include_children) override {
+    info->Set("type", GetDebugType());
+    info->Set("id", root_view()->GetID());
 
     // Use GetBounds() because some subclasses (like CefWindowImpl) override it.
     const CefRect& bounds = GetBounds();
-    std::unique_ptr<base::DictionaryValue> bounds_value(
-        new base::DictionaryValue());
-    bounds_value->SetInteger("x", bounds.x);
-    bounds_value->SetInteger("y", bounds.y);
-    bounds_value->SetInteger("width", bounds.width);
-    bounds_value->SetInteger("height", bounds.height);
+    base::Value::Dict bounds_value;
+    bounds_value.Set("x", bounds.x);
+    bounds_value.Set("y", bounds.y);
+    bounds_value.Set("width", bounds.width);
+    bounds_value.Set("height", bounds.height);
     info->Set("bounds", std::move(bounds_value));
   }
 
@@ -384,6 +384,8 @@
   CefSize GetSize() override;
   void SetPosition(const CefPoint& position) override;
   CefPoint GetPosition() override;
+  void SetInsets(const CefInsets& insets) override;
+  CefInsets GetInsets() override;
   CefSize GetPreferredSize() override;
   void SizeToPreferredSize() override;
   CefSize GetMinimumSize() override;
@@ -450,14 +452,15 @@
 
 CEF_VIEW_IMPL_T CefString CEF_VIEW_IMPL_D::ToString(bool include_children) {
   CEF_REQUIRE_UIT_RETURN(CefString());
-  std::unique_ptr<base::DictionaryValue> info(new base::DictionaryValue());
-  if (IsValid())
-    GetDebugInfo(info.get(), include_children);
-  else
-    info->SetString("type", GetDebugType());
+  base::Value::Dict info;
+  if (IsValid()) {
+    GetDebugInfo(&info, include_children);
+  } else {
+    info.Set("type", GetDebugType());
+  }
 
   std::string json_string;
-  base::JSONWriter::WriteWithOptions(*info, 0, &json_string);
+  base::JSONWriter::WriteWithOptions(info, 0, &json_string);
   return json_string;
 }
 
@@ -474,8 +477,9 @@
 CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::IsSame(CefRefPtr<CefView> that) {
   CEF_REQUIRE_UIT_RETURN(false);
   CefViewImpl* that_impl = static_cast<CefViewImpl*>(that.get());
-  if (!that_impl)
+  if (!that_impl) {
     return false;
+  }
   return this == that_impl;
 }
 
@@ -486,8 +490,9 @@
 
 CEF_VIEW_IMPL_T CefRefPtr<CefWindow> CEF_VIEW_IMPL_D::GetWindow() {
   CEF_REQUIRE_UIT_RETURN(nullptr);
-  if (root_view())
+  if (root_view()) {
     return view_util::GetWindowFor(root_view()->GetWidget());
+  }
   return nullptr;
 }
 
@@ -508,24 +513,27 @@
 
 CEF_VIEW_IMPL_T void CEF_VIEW_IMPL_D::SetGroupID(int group_id) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (root_view()->GetGroup() != -1)
+  if (root_view()->GetGroup() != -1) {
     return;
+  }
   root_view()->SetGroup(group_id);
 }
 
 CEF_VIEW_IMPL_T CefRefPtr<CefView> CEF_VIEW_IMPL_D::GetParentView() {
   CEF_REQUIRE_VALID_RETURN(nullptr);
   views::View* view = root_view()->parent();
-  if (!view)
+  if (!view) {
     return nullptr;
+  }
   return view_util::GetFor(view, true);
 }
 
 CEF_VIEW_IMPL_T CefRefPtr<CefView> CEF_VIEW_IMPL_D::GetViewForID(int id) {
   CEF_REQUIRE_VALID_RETURN(nullptr);
   views::View* view = root_view()->GetViewByID(id);
-  if (!view)
+  if (!view) {
     return nullptr;
+  }
   return view_util::GetFor(view, true);
 }
 
@@ -571,6 +579,21 @@
   return CefPoint(bounds.x, bounds.y);
 }
 
+CEF_VIEW_IMPL_T void CEF_VIEW_IMPL_D::SetInsets(const CefInsets& insets) {
+  CEF_REQUIRE_VALID_RETURN_VOID();
+  const gfx::Insets& gfx_insets =
+      gfx::Insets::TLBR(insets.top, insets.left, insets.bottom, insets.right);
+  root_view()->SetBorder(
+      gfx_insets.IsEmpty() ? nullptr : views::CreateEmptyBorder(gfx_insets));
+}
+
+CEF_VIEW_IMPL_T CefInsets CEF_VIEW_IMPL_D::GetInsets() {
+  CEF_REQUIRE_VALID_RETURN(CefInsets());
+  const auto insets = root_view()->GetInsets();
+  return CefInsets(insets.top(), insets.left(), insets.bottom(),
+                   insets.right());
+}
+
 CEF_VIEW_IMPL_T CefSize CEF_VIEW_IMPL_D::GetPreferredSize() {
   CEF_REQUIRE_VALID_RETURN(CefSize());
   const gfx::Size& size = root_view()->GetPreferredSize();
@@ -663,8 +686,9 @@
 CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::ConvertPointToScreen(CefPoint& point) {
   CEF_REQUIRE_VALID_RETURN(false);
   gfx::Point gfx_point = gfx::Point(point.x, point.y);
-  if (!view_util::ConvertPointToScreen(root_view(), &gfx_point, false))
+  if (!view_util::ConvertPointToScreen(root_view(), &gfx_point, false)) {
     return false;
+  }
   point = CefPoint(gfx_point.x(), gfx_point.y());
   return true;
 }
@@ -672,8 +696,9 @@
 CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::ConvertPointFromScreen(CefPoint& point) {
   CEF_REQUIRE_VALID_RETURN(false);
   gfx::Point gfx_point = gfx::Point(point.x, point.y);
-  if (!view_util::ConvertPointFromScreen(root_view(), &gfx_point, false))
+  if (!view_util::ConvertPointFromScreen(root_view(), &gfx_point, false)) {
     return false;
+  }
   point = CefPoint(gfx_point.x(), gfx_point.y());
   return true;
 }
@@ -681,8 +706,9 @@
 CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::ConvertPointToWindow(CefPoint& point) {
   CEF_REQUIRE_VALID_RETURN(false);
   gfx::Point gfx_point = gfx::Point(point.x, point.y);
-  if (!view_util::ConvertPointToWindow(root_view(), &gfx_point))
+  if (!view_util::ConvertPointToWindow(root_view(), &gfx_point)) {
     return false;
+  }
   point = CefPoint(gfx_point.x(), gfx_point.y());
   return true;
 }
@@ -690,8 +716,9 @@
 CEF_VIEW_IMPL_T bool CEF_VIEW_IMPL_D::ConvertPointFromWindow(CefPoint& point) {
   CEF_REQUIRE_VALID_RETURN(false);
   gfx::Point gfx_point = gfx::Point(point.x, point.y);
-  if (!view_util::ConvertPointFromWindow(root_view(), &gfx_point))
+  if (!view_util::ConvertPointFromWindow(root_view(), &gfx_point)) {
     return false;
+  }
   point = CefPoint(gfx_point.x(), gfx_point.y());
   return true;
 }
@@ -700,11 +727,13 @@
     CefRefPtr<CefView> view,
     CefPoint& point) {
   CEF_REQUIRE_VALID_RETURN(false);
-  if (!root_view()->GetWidget())
+  if (!root_view()->GetWidget()) {
     return false;
+  }
   views::View* target_view = view_util::GetFor(view);
-  if (!target_view || target_view->GetWidget() != root_view()->GetWidget())
+  if (!target_view || target_view->GetWidget() != root_view()->GetWidget()) {
     return false;
+  }
   gfx::Point gfx_point = gfx::Point(point.x, point.y);
   views::View::ConvertPointToTarget(root_view(), target_view, &gfx_point);
   point = CefPoint(gfx_point.x(), gfx_point.y());
@@ -715,11 +744,13 @@
     CefRefPtr<CefView> view,
     CefPoint& point) {
   CEF_REQUIRE_VALID_RETURN(false);
-  if (!root_view()->GetWidget())
+  if (!root_view()->GetWidget()) {
     return false;
+  }
   views::View* target_view = view_util::GetFor(view);
-  if (!target_view || target_view->GetWidget() != root_view()->GetWidget())
+  if (!target_view || target_view->GetWidget() != root_view()->GetWidget()) {
     return false;
+  }
   gfx::Point gfx_point = gfx::Point(point.x, point.y);
   views::View::ConvertPointToTarget(target_view, root_view(), &gfx_point);
   point = CefPoint(gfx_point.x(), gfx_point.y());
diff --git a/src/libcef/browser/views/view_util.cc b/src/libcef/browser/views/view_util.cc
index 4e22f99..13f42ac 100644
--- a/src/libcef/browser/views/view_util.cc
+++ b/src/libcef/browser/views/view_util.cc
@@ -8,8 +8,6 @@
 
 #include "libcef/browser/views/view_adapter.h"
 
-#include "ui/aura/window.h"
-#include "ui/aura/window_tree_host.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 #include "ui/gfx/geometry/point.h"
@@ -18,7 +16,7 @@
 #include "ui/views/widget/widget_delegate.h"
 #include "ui/views/window/non_client_view.h"
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 #include "ui/display/win/screen_win.h"
 #endif
 
@@ -47,8 +45,9 @@
   static CefRefPtr<CefView> GetFor(const views::View* view) {
     DCHECK(view);
     UserData* data = static_cast<UserData*>(view->GetUserData(UserDataKey()));
-    if (data)
+    if (data) {
       return data->view_ref_;
+    }
     return nullptr;
   }
 
@@ -56,8 +55,8 @@
   // gain a ref-counted reference to the CefView and the CefView will keep an
   // unowned reference to the views::View. Destruction of the views::View will
   // release the ref-counted reference to the CefView.
-  static std::unique_ptr<views::View> PassOwnership(CefRefPtr<CefView> cef_view)
-      WARN_UNUSED_RESULT {
+  [[nodiscard]] static std::unique_ptr<views::View> PassOwnership(
+      CefRefPtr<CefView> cef_view) {
     DCHECK(cef_view->IsValid());
     DCHECK(!cef_view->IsAttached());
 
@@ -129,18 +128,21 @@
 }
 
 CefRefPtr<CefView> GetFor(const views::View* view, bool find_known_parent) {
-  if (!view)
+  if (!view) {
     return nullptr;
+  }
 
-  if (!find_known_parent)
+  if (!find_known_parent) {
     return UserData::GetFor(view);
+  }
 
   CefRefPtr<CefView> cef_view;
   const views::View* current_view = view;
   do {
     cef_view = UserData::GetFor(current_view);
-    if (cef_view)
+    if (cef_view) {
       break;
+    }
     current_view = current_view->parent();
   } while (current_view);
 
@@ -162,14 +164,22 @@
 CefRefPtr<CefWindow> GetWindowFor(views::Widget* widget) {
   CefRefPtr<CefWindow> window;
 
+  // If |widget| is an overlay, retrieve the host Widget.
+  if (widget) {
+    if (auto widget_view = GetHostView(widget)) {
+      widget = widget_view->GetWidget();
+    }
+  }
+
   if (widget) {
     // The views::WidgetDelegate should be a CefWindowView and |content_view|
     // should be the same CefWindowView. However, just in case the views::Widget
     // was created by something else let's go about this the safer way.
     views::View* content_view = widget->widget_delegate()->GetContentsView();
     CefRefPtr<CefView> cef_view = GetFor(content_view, false);
-    if (cef_view && cef_view->AsPanel())
+    if (cef_view && cef_view->AsPanel()) {
       window = cef_view->AsPanel()->AsWindow();
+    }
 
     // The Window should always exist if we created the views::Widget.
     DCHECK(window);
@@ -181,7 +191,7 @@
 display::Display GetDisplayNearestPoint(const gfx::Point& point,
                                         bool input_pixel_coords) {
   gfx::Point find_point = point;
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   if (input_pixel_coords) {
     find_point = gfx::ToFlooredPoint(
         display::win::ScreenWin::ScreenToDIPPoint(gfx::PointF(point)));
@@ -193,7 +203,7 @@
 display::Display GetDisplayMatchingBounds(const gfx::Rect& bounds,
                                           bool input_pixel_coords) {
   gfx::Rect find_bounds = bounds;
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   if (input_pixel_coords) {
     find_bounds =
         display::win::ScreenWin::ScreenToDIPRect(nullptr, find_bounds);
@@ -202,21 +212,41 @@
   return display::Screen::GetScreen()->GetDisplayMatching(find_bounds);
 }
 
-void ConvertPointFromPixels(gfx::Point* point, int device_scale_factor) {
+void ConvertPointFromPixels(gfx::Point* point, float device_scale_factor) {
   *point = gfx::ToFlooredPoint(
       gfx::ScalePoint(gfx::PointF(*point), 1.0f / device_scale_factor));
 }
 
-void ConvertPointToPixels(gfx::Point* point, int device_scale_factor) {
+void ConvertPointToPixels(gfx::Point* point, float device_scale_factor) {
   *point = gfx::ToFlooredPoint(
       gfx::ScalePoint(gfx::PointF(*point), device_scale_factor));
 }
 
+#if BUILDFLAG(IS_WIN)
+gfx::Point ConvertPointFromPixels(const gfx::Point& point) {
+  return gfx::ToFlooredPoint(
+      display::win::ScreenWin::ScreenToDIPPoint(gfx::PointF(point)));
+}
+
+gfx::Point ConvertPointToPixels(const gfx::Point& point) {
+  return display::win::ScreenWin::DIPToScreenPoint(point);
+}
+
+gfx::Rect ConvertRectFromPixels(const gfx::Rect& rect) {
+  return display::win::ScreenWin::ScreenToDIPRect(nullptr, rect);
+}
+
+gfx::Rect ConvertRectToPixels(const gfx::Rect& rect) {
+  return display::win::ScreenWin::DIPToScreenRect(nullptr, rect);
+}
+#endif  // BUILDFLAG(IS_WIN)
+
 bool ConvertPointToScreen(views::View* view,
                           gfx::Point* point,
                           bool output_pixel_coords) {
-  if (!view->GetWidget())
+  if (!view->GetWidget()) {
     return false;
+  }
 
   views::View::ConvertPointToScreen(view, point);
 
@@ -231,8 +261,9 @@
 bool ConvertPointFromScreen(views::View* view,
                             gfx::Point* point,
                             bool input_pixel_coords) {
-  if (!view->GetWidget())
+  if (!view->GetWidget()) {
     return false;
+  }
 
   if (input_pixel_coords) {
     const display::Display& display = GetDisplayNearestPoint(*point, true);
@@ -246,8 +277,9 @@
 
 bool ConvertPointToWindow(views::View* view, gfx::Point* point) {
   views::Widget* widget = view->GetWidget();
-  if (!widget)
+  if (!widget) {
     return false;
+  }
 
   views::View::ConvertPointToWidget(view, point);
 
@@ -269,8 +301,9 @@
 
 bool ConvertPointFromWindow(views::View* view, gfx::Point* point) {
   views::Widget* widget = view->GetWidget();
-  if (!widget)
+  if (!widget) {
     return false;
+  }
 
   if (widget->non_client_view()) {
     views::NonClientFrameView* non_client_frame_view =
@@ -290,23 +323,4 @@
   return true;
 }
 
-gfx::NativeWindow GetNativeWindow(views::Widget* widget) {
-  if (widget) {
-    aura::Window* window = widget->GetNativeWindow();
-    if (window)
-      return window->GetRootWindow();
-  }
-  return nullptr;
-}
-
-CefWindowHandle GetWindowHandle(views::Widget* widget) {
-  // Same implementation as views::HWNDForView() but cross-platform.
-  if (widget) {
-    aura::Window* window = widget->GetNativeWindow();
-    if (window && window->GetRootWindow())
-      return window->GetHost()->GetAcceleratedWidget();
-  }
-  return kNullWindowHandle;
-}
-
 }  // namespace view_util
diff --git a/src/libcef/browser/views/view_util.h b/src/libcef/browser/views/view_util.h
index 6590f5b..a5fb6e5 100644
--- a/src/libcef/browser/views/view_util.h
+++ b/src/libcef/browser/views/view_util.h
@@ -9,6 +9,7 @@
 #include "include/views/cef_view.h"
 #include "include/views/cef_window.h"
 
+#include "ui/gfx/native_widget_types.h"
 #include "ui/views/view.h"
 
 namespace display {
@@ -20,8 +21,15 @@
 }
 
 namespace views {
+class NativeWidget;
+class View;
 class Widget;
+namespace internal {
+class NativeWidgetDelegate;
 }
+}  // namespace views
+
+class CefWindowDelegate;
 
 #define CEF_REQUIRE_VALID_RETURN(ret) \
   if (!ParentClass::IsValid())        \
@@ -61,8 +69,8 @@
 // views::View will keep a ref-counted reference to |view|, and |view| will keep
 // an un-owned reference to the views::View. These references will reset when
 // the views::View object is deleted or when ResumeOwnership() is called.
-std::unique_ptr<views::View> PassOwnership(CefRefPtr<CefView> view)
-    WARN_UNUSED_RESULT;
+[[nodiscard]] std::unique_ptr<views::View> PassOwnership(
+    CefRefPtr<CefView> view);
 
 // Causes |view| to resume ownership of the views::View object. Should be called
 // after removing the views::View object from its previous parent.
@@ -84,11 +92,25 @@
 
 // Convert |point| from pixel coordinates to density independent pixels (DIP)
 // using |device_scale_factor|.
-void ConvertPointFromPixels(gfx::Point* point, int device_scale_factor);
+void ConvertPointFromPixels(gfx::Point* point, float device_scale_factor);
 
 // Convert |point| to pixel coordinates from density independent pixels (DIP)
 // using |device_scale_factor|.
-void ConvertPointToPixels(gfx::Point* point, int device_scale_factor);
+void ConvertPointToPixels(gfx::Point* point, float device_scale_factor);
+
+#if BUILDFLAG(IS_WIN)
+// Convert |point| from pixel screen coordinates to DIP screen coordinates.
+gfx::Point ConvertPointFromPixels(const gfx::Point& point);
+
+// Convert |point| from DIP screen coordinates to pixel screen coordinates.
+gfx::Point ConvertPointToPixels(const gfx::Point& point);
+
+// Convert |rect| from pixel screen coordinates to DIP screen coordinates.
+gfx::Rect ConvertRectFromPixels(const gfx::Rect& rect);
+
+// Convert |rect| from DIP screen coordinates to pixel screen coordinates.
+gfx::Rect ConvertRectToPixels(const gfx::Rect& rect);
+#endif  // BUILDFLAG(IS_WIN)
 
 // Convert |point| from |view| to screen coordinates. If |output_pixel_coords|
 // is true then |point| will be output in pixel coordinates instead of density
@@ -117,9 +139,32 @@
 // Returns the native window handle for |widget|. May return nullptr.
 gfx::NativeWindow GetNativeWindow(views::Widget* widget);
 
+// Returns the native view handle for |widget|. May return nullptr.
+gfx::NativeView GetNativeView(views::Widget* widget);
+
 // Returns the platform window handle for |widget|. May return nullptr.
 CefWindowHandle GetWindowHandle(views::Widget* widget);
 
+// Returns the platform window handle for |window|. May return nullptr.
+CefWindowHandle GetWindowHandle(gfx::NativeWindow window);
+
+views::NativeWidget* CreateNativeWidget(
+    views::internal::NativeWidgetDelegate* delegate,
+    CefRefPtr<CefWindow> window,
+    CefWindowDelegate* window_delegate);
+
+// Called from CefOverlayViewHost::Init to associate |host_view| with |widget|.
+// This is necessary for GetWindowFor() to correctly return the CefWindow
+// associated with the host Widget. On Aura platforms, |host_view| is the view
+// whose position in the view hierarchy determines the z-order of the widget
+// relative to views with layers and views with associated NativeViews.
+void SetHostView(views::Widget* widget, views::View* host_view);
+views::View* GetHostView(views::Widget* widget);
+
+#if BUILDFLAG(IS_MAC)
+float GetNSWindowTitleBarHeight(views::Widget* widget);
+#endif
+
 }  // namespace view_util
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_VIEW_UTIL_H_
diff --git a/src/libcef/browser/views/view_util_aura.cc b/src/libcef/browser/views/view_util_aura.cc
new file mode 100644
index 0000000..24be331
--- /dev/null
+++ b/src/libcef/browser/views/view_util_aura.cc
@@ -0,0 +1,61 @@
+// Copyright 2016 The Chromium Embedded Framework 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 "libcef/browser/views/view_util.h"
+
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/views/view_constants_aura.h"
+#include "ui/views/widget/native_widget.h"
+#include "ui/views/widget/native_widget_delegate.h"
+#include "ui/views/widget/widget.h"
+
+namespace view_util {
+
+gfx::NativeWindow GetNativeWindow(views::Widget* widget) {
+  if (widget) {
+    return widget->GetNativeWindow();
+  }
+  return nullptr;
+}
+
+gfx::NativeView GetNativeView(views::Widget* widget) {
+  if (widget) {
+    return widget->GetNativeView();
+  }
+  return nullptr;
+}
+
+CefWindowHandle GetWindowHandle(views::Widget* widget) {
+  // Same implementation as views::HWNDForView() but cross-platform.
+  if (widget) {
+    return GetWindowHandle(widget->GetNativeWindow());
+  }
+  return kNullWindowHandle;
+}
+
+CefWindowHandle GetWindowHandle(gfx::NativeWindow window) {
+  // |window| is an aura::Window*.
+  if (window && window->GetRootWindow()) {
+    return window->GetHost()->GetAcceleratedWidget();
+  }
+  return kNullWindowHandle;
+}
+
+views::NativeWidget* CreateNativeWidget(
+    views::internal::NativeWidgetDelegate* delegate,
+    CefRefPtr<CefWindow> window,
+    CefWindowDelegate* window_delegate) {
+  return nullptr;
+}
+
+void SetHostView(views::Widget* widget, views::View* host_view) {
+  widget->GetNativeView()->SetProperty(views::kHostViewKey, host_view);
+}
+
+views::View* GetHostView(views::Widget* widget) {
+  return widget->GetNativeView()->GetProperty(views::kHostViewKey);
+}
+
+}  // namespace view_util
diff --git a/src/libcef/browser/views/view_util_mac.mm b/src/libcef/browser/views/view_util_mac.mm
new file mode 100644
index 0000000..903505d
--- /dev/null
+++ b/src/libcef/browser/views/view_util_mac.mm
@@ -0,0 +1,82 @@
+// Copyright 2021 The Chromium Embedded Framework 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 "libcef/browser/views/view_util.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include "include/internal/cef_types_mac.h"
+#include "libcef/browser/views/native_widget_mac.h"
+
+#include "ui/views/widget/widget.h"
+
+namespace view_util {
+
+namespace {
+
+constexpr char kNativeHostViewKey[] = "CefNativeHostViewKey";
+
+// For Venura 13.3.1.
+constexpr float kDefaultTitleBarHeight = 30;
+
+}  // namespace
+
+gfx::NativeWindow GetNativeWindow(views::Widget* widget) {
+  if (widget) {
+    return widget->GetNativeWindow();
+  }
+  return gfx::NativeWindow();
+}
+
+gfx::NativeView GetNativeView(views::Widget* widget) {
+  if (widget) {
+    return widget->GetNativeView();
+  }
+  return gfx::NativeView();
+}
+
+CefWindowHandle GetWindowHandle(views::Widget* widget) {
+  // |view| is a wrapper type from native_widget_types.h.
+  auto view = GetNativeView(widget);
+  if (view) {
+    return CAST_NSVIEW_TO_CEF_WINDOW_HANDLE(view.GetNativeNSView());
+  }
+  return kNullWindowHandle;
+}
+
+CefWindowHandle GetWindowHandle(gfx::NativeWindow window) {
+  // |window| is a wrapper type from native_widget_types.h.
+  if (window) {
+    NSWindow* nswindow = window.GetNativeNSWindow();
+    return CAST_NSVIEW_TO_CEF_WINDOW_HANDLE([nswindow contentView]);
+  }
+  return kNullWindowHandle;
+}
+
+views::NativeWidget* CreateNativeWidget(
+    views::internal::NativeWidgetDelegate* delegate,
+    CefRefPtr<CefWindow> window,
+    CefWindowDelegate* window_delegate) {
+  return new CefNativeWidgetMac(delegate, window, window_delegate);
+}
+
+void SetHostView(views::Widget* widget, views::View* host_view) {
+  widget->SetNativeWindowProperty(kNativeHostViewKey, host_view);
+}
+
+views::View* GetHostView(views::Widget* widget) {
+  return static_cast<views::View*>(
+      widget->GetNativeWindowProperty(kNativeHostViewKey));
+}
+
+float GetNSWindowTitleBarHeight(views::Widget* widget) {
+  if (auto window = GetNativeWindow(widget)) {
+    NSWindow* nswindow = window.GetNativeNSWindow();
+    return nswindow.frame.size.height -
+           [nswindow contentRectForFrameRect:nswindow.frame].size.height;
+  }
+  return kDefaultTitleBarHeight;
+}
+
+}  // namespace view_util
diff --git a/src/libcef/browser/views/view_view.h b/src/libcef/browser/views/view_view.h
index 4ebce17..23e6696 100644
--- a/src/libcef/browser/views/view_view.h
+++ b/src/libcef/browser/views/view_view.h
@@ -13,6 +13,7 @@
 #include "libcef/browser/views/view_util.h"
 
 #include "base/logging.h"
+#include "ui/views/accessibility/accessibility_paint_checks.h"
 #include "ui/views/background.h"
 #include "ui/views/view.h"
 
@@ -28,14 +29,15 @@
 // in view_impl.h for a usage overview.
 CEF_VIEW_VIEW_T class CefViewView : public ViewsViewClass {
  public:
-  typedef ViewsViewClass ParentClass;
+  using ParentClass = ViewsViewClass;
 
   // Should be created from CreateRootView() in a CefViewImpl-derived class.
   // Do not call complex views::View-derived methods from a CefViewView-derived
   // constructor as they may attempt to call back into CefViewImpl before
   // registration has been performed. |cef_delegate| may be nullptr.
-  explicit CefViewView(CefViewDelegateClass* cef_delegate)
-      : cef_delegate_(cef_delegate) {}
+  template <typename... Args>
+  explicit CefViewView(CefViewDelegateClass* cef_delegate, Args... args)
+      : ParentClass(args...), cef_delegate_(cef_delegate) {}
 
   // Should be called from InitializeRootView() in the CefViewImpl-derived
   // class that created this object. This method will be called after
@@ -45,6 +47,10 @@
     // Use our defaults instead of the Views framework defaults.
     ParentClass::SetBackground(
         views::CreateSolidBackground(view_util::kDefaultBackgroundColor));
+
+    // TODO(crbug.com/1218186): Remove this, if this view is focusable then it
+    // needs to add a name so that the screen reader knows what to announce.
+    ParentClass::SetProperty(views::kSkipAccessibilityPaintChecks, true);
   }
 
   // Returns the CefViewDelegate-derived delegate associated with this view.
@@ -70,6 +76,8 @@
   void Layout() override;
   void ViewHierarchyChanged(
       const views::ViewHierarchyChangedDetails& details) override;
+  void AddedToWidget() override;
+  void RemovedFromWidget() override;
   void OnFocus() override;
   void OnBlur() override;
 
@@ -84,18 +92,20 @@
       const views::ViewHierarchyChangedDetails& details);
 
   // Not owned by this object.
-  CefViewDelegateClass* cef_delegate_;
+  CefViewDelegateClass* const cef_delegate_;
 };
 
 CEF_VIEW_VIEW_T gfx::Size CEF_VIEW_VIEW_D::CalculatePreferredSize() const {
   gfx::Size result;
   if (cef_delegate()) {
     CefSize cef_size = cef_delegate()->GetPreferredSize(GetCefView());
-    if (!cef_size.IsEmpty())
+    if (!cef_size.IsEmpty()) {
       result = gfx::Size(cef_size.width, cef_size.height);
+    }
   }
-  if (result.IsEmpty())
+  if (result.IsEmpty()) {
     result = ParentClass::CalculatePreferredSize();
+  }
   if (result.IsEmpty()) {
     // Some layouts like BoxLayout expect the preferred size to be non-empty.
     // The user may have set the size explicitly. Therefore return the current
@@ -109,14 +119,16 @@
   gfx::Size result;
   if (cef_delegate()) {
     CefSize cef_size = cef_delegate()->GetMinimumSize(GetCefView());
-    if (!cef_size.IsEmpty())
+    if (!cef_size.IsEmpty()) {
       result = gfx::Size(cef_size.width, cef_size.height);
+    }
   }
   // We don't want to call ParentClass::GetMinimumSize() in all cases because
   // the default views::View implementation will call GetPreferredSize(). That
   // may result in size() being returned which keeps the View from shrinking.
-  if (result.IsEmpty() && HasMinimumSize())
+  if (result.IsEmpty() && HasMinimumSize()) {
     result = ParentClass::GetMinimumSize();
+  }
   return result;
 }
 
@@ -124,20 +136,24 @@
   gfx::Size result;
   if (cef_delegate()) {
     CefSize cef_size = cef_delegate()->GetMaximumSize(GetCefView());
-    if (!cef_size.IsEmpty())
+    if (!cef_size.IsEmpty()) {
       result = gfx::Size(cef_size.width, cef_size.height);
+    }
   }
-  if (result.IsEmpty())
+  if (result.IsEmpty()) {
     result = ParentClass::GetMaximumSize();
+  }
   return result;
 }
 
 CEF_VIEW_VIEW_T int CEF_VIEW_VIEW_D::GetHeightForWidth(int w) const {
   int result = 0;
-  if (cef_delegate())
+  if (cef_delegate()) {
     result = cef_delegate()->GetHeightForWidth(GetCefView(), w);
-  if (result == 0)
+  }
+  if (result == 0) {
     result = ParentClass::GetHeightForWidth(w);
+  }
   if (result == 0) {
     // Some layouts like FillLayout will ignore the preferred size if this view
     // has no children. We want to use the preferred size if not otherwise
@@ -151,8 +167,16 @@
   ParentClass::Layout();
 
   // If Layout() did not provide a size then use the preferred size.
-  if (ParentClass::size().IsEmpty())
+  if (ParentClass::size().IsEmpty()) {
     ParentClass::SizeToPreferredSize();
+  }
+
+  if (cef_delegate()) {
+    const auto new_bounds = ParentClass::bounds();
+    CefRect new_rect(new_bounds.x(), new_bounds.y(), new_bounds.width(),
+                     new_bounds.height());
+    cef_delegate()->OnLayoutChanged(GetCefView(), new_rect);
+  }
 }
 
 CEF_VIEW_VIEW_T void CEF_VIEW_VIEW_D::ViewHierarchyChanged(
@@ -162,50 +186,72 @@
   ParentClass::ViewHierarchyChanged(details);
 }
 
+CEF_VIEW_VIEW_T void CEF_VIEW_VIEW_D::AddedToWidget() {
+  ParentClass::AddedToWidget();
+  if (cef_delegate()) {
+    cef_delegate()->OnWindowChanged(GetCefView(), /*added=*/true);
+  }
+}
+
+CEF_VIEW_VIEW_T void CEF_VIEW_VIEW_D::RemovedFromWidget() {
+  if (cef_delegate()) {
+    cef_delegate()->OnWindowChanged(GetCefView(), /*added=*/false);
+  }
+  ParentClass::RemovedFromWidget();
+}
+
 CEF_VIEW_VIEW_T void CEF_VIEW_VIEW_D::OnFocus() {
-  if (cef_delegate())
+  if (cef_delegate()) {
     cef_delegate()->OnFocus(GetCefView());
+  }
   ParentClass::OnFocus();
 }
 
 CEF_VIEW_VIEW_T void CEF_VIEW_VIEW_D::OnBlur() {
-  if (cef_delegate())
+  if (cef_delegate()) {
     cef_delegate()->OnBlur(GetCefView());
+  }
   ParentClass::OnBlur();
 }
 
 CEF_VIEW_VIEW_T void CEF_VIEW_VIEW_D::NotifyChildViewChanged(
     const views::ViewHierarchyChangedDetails& details) {
-  if (!cef_delegate())
+  if (!cef_delegate()) {
     return;
+  }
 
   // Only interested with the parent is |this| object and the notification is
   // about an immediate child (notifications are also sent for grandchildren).
-  if (details.parent != this || details.child->parent() != this)
+  if (details.parent != this || details.child->parent() != this) {
     return;
+  }
 
   // Only notify for children that have a known CEF root view. For example,
   // don't notify when ScrollView adds child scroll bars.
   CefRefPtr<CefView> child = view_util::GetFor(details.child, false);
-  if (child)
+  if (child) {
     cef_delegate()->OnChildViewChanged(GetCefView(), details.is_add, child);
+  }
 }
 
 CEF_VIEW_VIEW_T void CEF_VIEW_VIEW_D::NotifyParentViewChanged(
     const views::ViewHierarchyChangedDetails& details) {
-  if (!cef_delegate())
+  if (!cef_delegate()) {
     return;
+  }
 
   // Only interested when the child is |this| object and notification is about
   // the immediate parent (notifications are sent for all parents).
-  if (details.child != this || details.parent != ParentClass::parent())
+  if (details.child != this || details.parent != ParentClass::parent()) {
     return;
+  }
 
   // The immediate parent might be an intermediate view so find the closest
-  // known CEF root view.
+  // known CEF root view. |parent| might be nullptr for overlays.
   CefRefPtr<CefView> parent = view_util::GetFor(details.parent, true);
-  DCHECK(parent);
-  cef_delegate()->OnParentViewChanged(GetCefView(), details.is_add, parent);
+  if (parent) {
+    cef_delegate()->OnParentViewChanged(GetCefView(), details.is_add, parent);
+  }
 }
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_VIEW_VIEW_H_
diff --git a/src/libcef/browser/views/widget_destruction_observer.h b/src/libcef/browser/views/widget_destruction_observer.h
new file mode 100644
index 0000000..c9c41ed
--- /dev/null
+++ b/src/libcef/browser/views/widget_destruction_observer.h
@@ -0,0 +1,34 @@
+// Copyright 2023 The Chromium Embedded Framework Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be found
+// in the LICENSE file.
+
+#include "base/scoped_observation.h"
+#include "ui/views/widget/widget_observer.h"
+
+// Tracks if a given widget has been destroyed.
+class WidgetDestructionObserver : public views::WidgetObserver {
+ public:
+  explicit WidgetDestructionObserver(views::Widget* widget) : widget_(widget) {
+    DCHECK(widget);
+    observation_.Observe(widget);
+  }
+  WidgetDestructionObserver(const WidgetDestructionObserver&) = delete;
+  WidgetDestructionObserver& operator=(const WidgetDestructionObserver&) =
+      delete;
+  ~WidgetDestructionObserver() override = default;
+
+  // views::WidgetObserver:
+  void OnWidgetDestroyed(views::Widget* widget) override {
+    DCHECK(widget_);
+    widget_ = nullptr;
+    observation_.Reset();
+  }
+
+  views::Widget* widget() const { return widget_; }
+
+ private:
+  views::Widget* widget_;
+
+  base::ScopedObservation<views::Widget, views::WidgetObserver> observation_{
+      this};
+};
diff --git a/src/libcef/browser/views/window_impl.cc b/src/libcef/browser/views/window_impl.cc
index eeb1fcc..da73c8a 100644
--- a/src/libcef/browser/views/window_impl.cc
+++ b/src/libcef/browser/views/window_impl.cc
@@ -5,28 +5,31 @@
 #include "libcef/browser/views/window_impl.h"
 
 #include "libcef/browser/browser_util.h"
+#include "libcef/browser/chrome/views/chrome_browser_frame.h"
 #include "libcef/browser/thread_util.h"
+#include "libcef/browser/views/browser_view_impl.h"
 #include "libcef/browser/views/display_impl.h"
 #include "libcef/browser/views/fill_layout_impl.h"
 #include "libcef/browser/views/layout_util.h"
 #include "libcef/browser/views/view_util.h"
 #include "libcef/browser/views/window_view.h"
+#include "libcef/features/runtime.h"
 
+#include "base/i18n/rtl.h"
+#include "components/constrained_window/constrained_window_views.h"
 #include "ui/base/test/ui_controls.h"
+#include "ui/compositor/compositor.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/views/controls/button/menu_button.h"
 #include "ui/views/controls/menu/menu_runner.h"
+#include "ui/views/controls/webview/webview.h"
 
 #if defined(USE_AURA)
-#include "ui/aura/test/ui_controls_factory_aura.h"
 #include "ui/aura/window.h"
-#include "ui/base/test/ui_controls_aura.h"
-#if defined(OS_LINUX) && defined(USE_X11)
-#include "ui/views/test/ui_controls_factory_desktop_aurax11.h"
-#endif
-#endif
+#endif  // defined(USE_AURA)
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
+#include "ui/aura/test/ui_controls_aurawin.h"
 #include "ui/display/win/screen_win.h"
 #endif
 
@@ -36,16 +39,10 @@
 void InitializeUITesting() {
   static bool initialized = false;
   if (!initialized) {
-    ui_controls::EnableUIControls();
-
-#if defined(USE_AURA)
-#if defined(OS_LINUX) && defined(USE_X11)
-    ui_controls::InstallUIControlsAura(
-        views::test::CreateUIControlsDesktopAura());
+#if BUILDFLAG(IS_WIN)
+    aura::test::EnableUIControlsAuraWin();
 #else
-    ui_controls::InstallUIControlsAura(
-        aura::test::CreateUIControlsAura(nullptr));
-#endif
+    ui_controls::EnableUIControls();
 #endif
 
     initialized = true;
@@ -68,6 +65,10 @@
     window_->AddPostTargetHandler(this);
   }
 
+  CefUnhandledKeyEventHandler(const CefUnhandledKeyEventHandler&) = delete;
+  CefUnhandledKeyEventHandler& operator=(const CefUnhandledKeyEventHandler&) =
+      delete;
+
   ~CefUnhandledKeyEventHandler() override {
     window_->RemovePostTargetHandler(this);
   }
@@ -97,8 +98,6 @@
 
   // |window_| is the event target that is associated with this class.
   aura::Window* window_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefUnhandledKeyEventHandler);
 };
 
 #endif  // defined(USE_AURA)
@@ -108,43 +107,74 @@
 // static
 CefRefPtr<CefWindow> CefWindow::CreateTopLevelWindow(
     CefRefPtr<CefWindowDelegate> delegate) {
-  return CefWindowImpl::Create(delegate);
+  return CefWindowImpl::Create(delegate, gfx::kNullAcceleratedWidget);
 }
 
 // static
 CefRefPtr<CefWindowImpl> CefWindowImpl::Create(
-    CefRefPtr<CefWindowDelegate> delegate) {
+    CefRefPtr<CefWindowDelegate> delegate,
+    gfx::AcceleratedWidget parent_widget) {
   CEF_REQUIRE_UIT_RETURN(nullptr);
   CefRefPtr<CefWindowImpl> window = new CefWindowImpl(delegate);
   window->Initialize();
-  window->CreateWidget();
-  if (delegate)
-    delegate->OnWindowCreated(window.get());
+  window->CreateWidget(parent_widget);
   return window;
 }
 
 void CefWindowImpl::Show() {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (widget_)
+  if (widget_) {
+    shown_as_browser_modal_ = false;
     widget_->Show();
+  }
+}
+
+void CefWindowImpl::ShowAsBrowserModalDialog(
+    CefRefPtr<CefBrowserView> browser_view) {
+  CEF_REQUIRE_VALID_RETURN_VOID();
+  if (widget_) {
+    auto* browser_view_impl =
+        static_cast<CefBrowserViewImpl*>(browser_view.get());
+
+    // |browser_view| must belong to the host widget.
+    auto* host_widget = static_cast<CefWindowView*>(root_view())->host_widget();
+    CHECK(host_widget &&
+          browser_view_impl->root_view()->GetWidget() == host_widget);
+
+    if (auto web_view = browser_view_impl->web_view()) {
+      if (auto web_contents = web_view->web_contents()) {
+        shown_as_browser_modal_ = true;
+        constrained_window::ShowModalDialog(widget_->GetNativeWindow(),
+                                            web_contents);
+
+        // NativeWebContentsModalDialogManagerViews::ManageDialog() disables
+        // movement. That has no impact on native frames but interferes with
+        // draggable regions.
+        widget_->set_movement_disabled(false);
+      }
+    }
+  }
 }
 
 void CefWindowImpl::Hide() {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (widget_)
+  if (widget_) {
     widget_->Hide();
+  }
 }
 
 void CefWindowImpl::CenterWindow(const CefSize& size) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (widget_)
+  if (widget_) {
     widget_->CenterWindow(gfx::Size(size.width, size.height));
+  }
 }
 
 void CefWindowImpl::Close() {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (widget_ && !widget_->IsClosed())
+  if (widget_ && !widget_->IsClosed()) {
     widget_->Close();
+  }
 }
 
 bool CefWindowImpl::IsClosed() {
@@ -154,27 +184,31 @@
 
 void CefWindowImpl::Activate() {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (widget_ && widget_->CanActivate() && !widget_->IsActive())
+  if (widget_ && widget_->CanActivate() && !widget_->IsActive()) {
     widget_->Activate();
+  }
 }
 
 void CefWindowImpl::Deactivate() {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (widget_ && widget_->CanActivate() && widget_->IsActive())
+  if (widget_ && widget_->CanActivate() && widget_->IsActive()) {
     widget_->Deactivate();
+  }
 }
 
 bool CefWindowImpl::IsActive() {
   CEF_REQUIRE_VALID_RETURN(false);
-  if (widget_)
+  if (widget_) {
     return widget_->IsActive();
+  }
   return false;
 }
 
 void CefWindowImpl::BringToTop() {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (widget_)
+  if (widget_) {
     widget_->StackAtTop();
+  }
 }
 
 void CefWindowImpl::SetAlwaysOnTop(bool on_top) {
@@ -188,100 +222,147 @@
 
 bool CefWindowImpl::IsAlwaysOnTop() {
   CEF_REQUIRE_VALID_RETURN(false);
-  if (widget_)
+  if (widget_) {
     return widget_->GetZOrderLevel() == ui::ZOrderLevel::kFloatingWindow;
+  }
   return false;
 }
 
 void CefWindowImpl::Maximize() {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (widget_ && !widget_->IsMaximized())
+  if (widget_ && !widget_->IsMaximized()) {
     widget_->Maximize();
+  }
 }
 
 void CefWindowImpl::Minimize() {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (widget_ && !widget_->IsMinimized())
+  if (widget_ && !widget_->IsMinimized()) {
     widget_->Minimize();
+  }
 }
 
 void CefWindowImpl::Restore() {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (widget_ && (widget_->IsMaximized() || widget_->IsMinimized()))
+  if (widget_ && (widget_->IsMaximized() || widget_->IsMinimized())) {
     widget_->Restore();
+  }
 }
 
 void CefWindowImpl::SetFullscreen(bool fullscreen) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (widget_ && fullscreen != widget_->IsFullscreen())
+  if (widget_ && fullscreen != widget_->IsFullscreen()) {
+    if (cef::IsChromeRuntimeEnabled()) {
+      // If a BrowserView exists, toggle fullscreen mode via the Chrome command
+      // for consistent behavior.
+      auto* browser_frame = static_cast<ChromeBrowserFrame*>(widget_);
+      if (browser_frame->browser_view()) {
+        browser_frame->ToggleFullscreenMode();
+        return;
+      }
+    }
+
+    // Call the Widget method directly with Alloy runtime, or Chrome runtime
+    // when no BrowserView exists.
     widget_->SetFullscreen(fullscreen);
+
+    // Use a synchronous callback notification on Windows/Linux. Chrome runtime
+    // on Windows/Linux gets notified synchronously via ChromeBrowserDelegate
+    // callbacks when a BrowserView exists. MacOS (both runtimes) gets notified
+    // asynchronously via CefNativeWidgetMac callbacks.
+#if !BUILDFLAG(IS_MAC)
+    if (delegate()) {
+      delegate()->OnWindowFullscreenTransition(this, /*is_completed=*/true);
+    }
+#endif
+  }
 }
 
 bool CefWindowImpl::IsMaximized() {
   CEF_REQUIRE_VALID_RETURN(false);
-  if (widget_)
+  if (widget_) {
     return widget_->IsMaximized();
+  }
   return false;
 }
 
 bool CefWindowImpl::IsMinimized() {
   CEF_REQUIRE_VALID_RETURN(false);
-  if (widget_)
+  if (widget_) {
     return widget_->IsMinimized();
+  }
   return false;
 }
 
 bool CefWindowImpl::IsFullscreen() {
   CEF_REQUIRE_VALID_RETURN(false);
-  if (widget_)
+  if (widget_) {
     return widget_->IsFullscreen();
+  }
   return false;
 }
 
 void CefWindowImpl::SetTitle(const CefString& title) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (root_view())
+  if (root_view()) {
     root_view()->SetTitle(title);
+  }
 }
 
 CefString CefWindowImpl::GetTitle() {
   CEF_REQUIRE_VALID_RETURN(CefString());
-  if (root_view())
+  if (root_view()) {
     return root_view()->title();
+  }
   return CefString();
 }
 
 void CefWindowImpl::SetWindowIcon(CefRefPtr<CefImage> image) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (root_view())
+  if (root_view()) {
     root_view()->SetWindowIcon(image);
+  }
 }
 
 CefRefPtr<CefImage> CefWindowImpl::GetWindowIcon() {
   CEF_REQUIRE_VALID_RETURN(nullptr);
-  if (root_view())
+  if (root_view()) {
     return root_view()->window_icon();
+  }
   return nullptr;
 }
 
 void CefWindowImpl::SetWindowAppIcon(CefRefPtr<CefImage> image) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (root_view())
+  if (root_view()) {
     root_view()->SetWindowAppIcon(image);
+  }
 }
 
 CefRefPtr<CefImage> CefWindowImpl::GetWindowAppIcon() {
   CEF_REQUIRE_VALID_RETURN(nullptr);
-  if (root_view())
+  if (root_view()) {
     return root_view()->window_app_icon();
+  }
   return nullptr;
 }
 
-void CefWindowImpl::GetDebugInfo(base::DictionaryValue* info,
+CefRefPtr<CefOverlayController> CefWindowImpl::AddOverlayView(
+    CefRefPtr<CefView> view,
+    cef_docking_mode_t docking_mode) {
+  CEF_REQUIRE_VALID_RETURN(nullptr);
+  if (root_view()) {
+    return root_view()->AddOverlayView(view, docking_mode);
+  }
+  return nullptr;
+}
+
+void CefWindowImpl::GetDebugInfo(base::Value::Dict* info,
                                  bool include_children) {
   ParentClass::GetDebugInfo(info, include_children);
-  if (root_view())
-    info->SetString("title", root_view()->title());
+  if (root_view()) {
+    info->Set("title", root_view()->title());
+  }
 }
 
 void CefWindowImpl::ShowMenu(CefRefPtr<CefMenuModel> menu_model,
@@ -308,8 +389,9 @@
 CefRect CefWindowImpl::GetBounds() {
   CEF_REQUIRE_VALID_RETURN(CefRect());
   gfx::Rect bounds;
-  if (widget_)
+  if (widget_) {
     bounds = widget_->GetWindowBoundsInScreen();
+  }
   return CefRect(bounds.x(), bounds.y(), bounds.width(), bounds.height());
 }
 
@@ -319,8 +401,9 @@
 
 void CefWindowImpl::SetSize(const CefSize& size) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (widget_)
+  if (widget_) {
     widget_->SetSize(gfx::Size(size.width, size.height));
+  }
 }
 
 void CefWindowImpl::SetPosition(const CefPoint& position) {
@@ -335,24 +418,27 @@
 void CefWindowImpl::SizeToPreferredSize() {
   CEF_REQUIRE_VALID_RETURN_VOID();
   if (widget_) {
-    if (widget_->non_client_view())
+    if (widget_->non_client_view()) {
       widget_->SetSize(widget_->non_client_view()->GetPreferredSize());
-    else
+    } else {
       widget_->SetSize(root_view()->GetPreferredSize());
+    }
   }
 }
 
 void CefWindowImpl::SetVisible(bool visible) {
-  if (visible)
+  if (visible) {
     Show();
-  else
+  } else {
     Hide();
+  }
 }
 
 bool CefWindowImpl::IsVisible() {
   CEF_REQUIRE_VALID_RETURN(false);
-  if (widget_)
+  if (widget_) {
     return widget_->IsVisible();
+  }
   return false;
 }
 
@@ -363,13 +449,20 @@
 void CefWindowImpl::SetBackgroundColor(cef_color_t color) {
   CEF_REQUIRE_VALID_RETURN_VOID();
   ParentClass::SetBackgroundColor(color);
-  if (widget_ && widget_->GetCompositor())
+  if (widget_ && widget_->GetCompositor()) {
     widget_->GetCompositor()->SetBackgroundColor(color);
+  }
 }
 
 bool CefWindowImpl::CanWidgetClose() {
-  if (delegate())
+  if (shown_as_browser_modal_) {
+    // Always allow the close for browser modal dialogs to avoid an infinite
+    // loop in WebContentsModalDialogManager::CloseAllDialogs().
+    return true;
+  }
+  if (delegate()) {
     return delegate()->CanClose(this);
+  }
   return true;
 }
 
@@ -377,6 +470,10 @@
 #if defined(USE_AURA)
   unhandled_key_event_handler_.reset();
 #endif
+
+  if (delegate()) {
+    delegate()->OnWindowClosing(this);
+  }
 }
 
 void CefWindowImpl::OnWindowViewDeleted() {
@@ -385,8 +482,9 @@
   destroyed_ = true;
   widget_ = nullptr;
 
-  if (delegate())
+  if (delegate()) {
     delegate()->OnWindowDestroyed(this);
+  }
 
   // Call Detach() here instead of waiting for the root View to be deleted so
   // that any following attempts to call CefWindow methods from the delegate
@@ -397,21 +495,24 @@
 // Will only be called if CanHandleAccelerators() returns true.
 bool CefWindowImpl::AcceleratorPressed(const ui::Accelerator& accelerator) {
   for (const auto& entry : accelerator_map_) {
-    if (entry.second == accelerator)
+    if (entry.second == accelerator) {
       return delegate()->OnAccelerator(this, entry.first);
+    }
   }
   return false;
 }
 
 bool CefWindowImpl::CanHandleAccelerators() const {
-  if (delegate() && widget_)
+  if (delegate() && widget_) {
     return widget_->IsActive();
+  }
   return false;
 }
 
 bool CefWindowImpl::OnKeyEvent(const CefKeyEvent& event) {
-  if (delegate())
+  if (delegate()) {
     return delegate()->OnKeyEvent(this, event);
+  }
   return false;
 }
 
@@ -421,24 +522,26 @@
                              cef_menu_anchor_position_t anchor_position) {
   CancelMenu();
 
-  if (!widget_)
+  if (!widget_) {
     return;
+  }
 
   CefMenuModelImpl* menu_model_impl =
       static_cast<CefMenuModelImpl*>(menu_model.get());
-  if (!menu_model_impl || !menu_model_impl->model())
+  if (!menu_model_impl || !menu_model_impl->model()) {
     return;
+  }
 
   menu_model_ = menu_model_impl;
 
   // We'll send the MenuClosed notification manually for better accuracy.
   menu_model_->set_auto_notify_menu_closed(false);
 
-  menu_runner_.reset(
-      new views::MenuRunner(menu_model_impl->model(),
-                            menu_button ? views::MenuRunner::HAS_MNEMONICS
-                                        : views::MenuRunner::CONTEXT_MENU,
-                            base::Bind(&CefWindowImpl::MenuClosed, this)));
+  menu_runner_.reset(new views::MenuRunner(
+      menu_model_impl->model(),
+      menu_button ? views::MenuRunner::HAS_MNEMONICS
+                  : views::MenuRunner::CONTEXT_MENU,
+      base::BindRepeating(&CefWindowImpl::MenuClosed, this)));
 
   menu_runner_->RunMenuAt(
       widget_, menu_button ? menu_button->button_controller() : nullptr,
@@ -455,8 +558,9 @@
 
 void CefWindowImpl::CancelMenu() {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (menu_runner_)
+  if (menu_runner_) {
     menu_runner_->Cancel();
+  }
   DCHECK(!menu_model_);
   DCHECK(!menu_runner_);
 }
@@ -465,8 +569,9 @@
   CEF_REQUIRE_VALID_RETURN(nullptr);
   if (widget_ && root_view()) {
     const display::Display& display = root_view()->GetDisplay();
-    if (display.is_valid())
+    if (display.is_valid()) {
       return new CefDisplayImpl(display);
+    }
   }
   return nullptr;
 }
@@ -496,8 +601,9 @@
 void CefWindowImpl::SetDraggableRegions(
     const std::vector<CefDraggableRegion>& regions) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (root_view())
+  if (root_view()) {
     root_view()->SetDraggableRegions(regions);
+  }
 }
 
 CefWindowHandle CefWindowImpl::GetWindowHandle() {
@@ -505,13 +611,14 @@
   return view_util::GetWindowHandle(widget_);
 }
 
-void CefWindowImpl::SendKeyPress(int key_code, uint32 event_flags) {
+void CefWindowImpl::SendKeyPress(int key_code, uint32_t event_flags) {
   CEF_REQUIRE_VALID_RETURN_VOID();
   InitializeUITesting();
 
   gfx::NativeWindow native_window = view_util::GetNativeWindow(widget_);
-  if (!native_window)
+  if (!native_window) {
     return;
+  }
 
   ui_controls::SendKeyPress(native_window,
                             static_cast<ui::KeyboardCode>(key_code),
@@ -525,12 +632,8 @@
   CEF_REQUIRE_VALID_RETURN_VOID();
   InitializeUITesting();
 
+  // Converts to pixel coordinates internally on Windows.
   gfx::Point point(screen_x, screen_y);
-#if defined(OS_WIN)
-  // Windows expects pixel coordinates.
-  point = display::win::ScreenWin::DIPToScreenPoint(point);
-#endif
-
   ui_controls::SendMouseMove(point.x(), point.y());
 }
 
@@ -538,22 +641,26 @@
                                     bool mouse_down,
                                     bool mouse_up) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (!mouse_down && !mouse_up)
+  if (!mouse_down && !mouse_up) {
     return;
+  }
 
   InitializeUITesting();
 
   ui_controls::MouseButton type = ui_controls::LEFT;
-  if (button == MBT_MIDDLE)
+  if (button == MBT_MIDDLE) {
     type = ui_controls::MIDDLE;
-  else if (button == MBT_RIGHT)
+  } else if (button == MBT_RIGHT) {
     type = ui_controls::RIGHT;
+  }
 
   int state = 0;
-  if (mouse_down)
+  if (mouse_down) {
     state |= ui_controls::DOWN;
-  if (mouse_up)
+  }
+  if (mouse_up) {
     state |= ui_controls::UP;
+  }
 
   ui_controls::SendMouseEvents(type, state);
 }
@@ -562,22 +669,28 @@
                                    int key_code,
                                    bool shift_pressed,
                                    bool ctrl_pressed,
-                                   bool alt_pressed) {
+                                   bool alt_pressed,
+                                   bool high_priority) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (!widget_)
+  if (!widget_) {
     return;
+  }
 
   AcceleratorMap::const_iterator it = accelerator_map_.find(command_id);
-  if (it != accelerator_map_.end())
+  if (it != accelerator_map_.end()) {
     RemoveAccelerator(command_id);
+  }
 
   int modifiers = 0;
-  if (shift_pressed)
+  if (shift_pressed) {
     modifiers |= ui::EF_SHIFT_DOWN;
-  if (ctrl_pressed)
+  }
+  if (ctrl_pressed) {
     modifiers |= ui::EF_CONTROL_DOWN;
-  if (alt_pressed)
+  }
+  if (alt_pressed) {
     modifiers |= ui::EF_ALT_DOWN;
+  }
   ui::Accelerator accelerator(static_cast<ui::KeyboardCode>(key_code),
                               modifiers);
 
@@ -586,17 +699,22 @@
   views::FocusManager* focus_manager = widget_->GetFocusManager();
   DCHECK(focus_manager);
   focus_manager->RegisterAccelerator(
-      accelerator, ui::AcceleratorManager::kNormalPriority, this);
+      accelerator,
+      high_priority ? ui::AcceleratorManager::kHighPriority
+                    : ui::AcceleratorManager::kNormalPriority,
+      this);
 }
 
 void CefWindowImpl::RemoveAccelerator(int command_id) {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (!widget_)
+  if (!widget_) {
     return;
+  }
 
   AcceleratorMap::iterator it = accelerator_map_.find(command_id);
-  if (it == accelerator_map_.end())
+  if (it == accelerator_map_.end()) {
     return;
+  }
 
   ui::Accelerator accelerator = it->second;
 
@@ -609,8 +727,9 @@
 
 void CefWindowImpl::RemoveAllAccelerators() {
   CEF_REQUIRE_VALID_RETURN_VOID();
-  if (!widget_)
+  if (!widget_) {
     return;
+  }
 
   accelerator_map_.clear();
 
@@ -620,7 +739,7 @@
 }
 
 CefWindowImpl::CefWindowImpl(CefRefPtr<CefWindowDelegate> delegate)
-    : ParentClass(delegate), widget_(nullptr), destroyed_(false) {}
+    : ParentClass(delegate) {}
 
 CefWindowView* CefWindowImpl::CreateRootView() {
   return new CefWindowView(delegate(), this);
@@ -630,10 +749,10 @@
   static_cast<CefWindowView*>(root_view())->Initialize();
 }
 
-void CefWindowImpl::CreateWidget() {
+void CefWindowImpl::CreateWidget(gfx::AcceleratedWidget parent_widget) {
   DCHECK(!widget_);
 
-  root_view()->CreateWidget();
+  root_view()->CreateWidget(parent_widget);
   widget_ = root_view()->GetWidget();
   DCHECK(widget_);
 
@@ -645,6 +764,11 @@
   // The Widget and root View are owned by the native window. Therefore don't
   // keep an owned reference.
   std::unique_ptr<views::View> view_ptr = view_util::PassOwnership(this);
-  views::View* view = view_ptr.release();
-  ALLOW_UNUSED_LOCAL(view);
+  [[maybe_unused]] views::View* view = view_ptr.release();
+
+  initialized_ = true;
+
+  if (delegate()) {
+    delegate()->OnWindowCreated(this);
+  }
 }
diff --git a/src/libcef/browser/views/window_impl.h b/src/libcef/browser/views/window_impl.h
index 857b830..6b137d1 100644
--- a/src/libcef/browser/views/window_impl.h
+++ b/src/libcef/browser/views/window_impl.h
@@ -28,13 +28,20 @@
       public CefWindowView::Delegate,
       public ui::AcceleratorTarget {
  public:
-  typedef CefPanelImpl<CefWindowView, CefWindow, CefWindowDelegate> ParentClass;
+  using ParentClass = CefPanelImpl<CefWindowView, CefWindow, CefWindowDelegate>;
 
-  // Create a new CefWindow instance. |delegate| may be nullptr.
-  static CefRefPtr<CefWindowImpl> Create(CefRefPtr<CefWindowDelegate> delegate);
+  CefWindowImpl(const CefWindowImpl&) = delete;
+  CefWindowImpl& operator=(const CefWindowImpl&) = delete;
+
+  // Create a new CefWindow instance. |delegate| may be nullptr. |parent_widget|
+  // will be used when creating a Chrome child window.
+  static CefRefPtr<CefWindowImpl> Create(CefRefPtr<CefWindowDelegate> delegate,
+                                         gfx::AcceleratedWidget parent_widget);
 
   // CefWindow methods:
   void Show() override;
+  void ShowAsBrowserModalDialog(
+      CefRefPtr<CefBrowserView> browser_view) override;
   void Hide() override;
   void CenterWindow(const CefSize& size) override;
   void Close() override;
@@ -58,6 +65,9 @@
   CefRefPtr<CefImage> GetWindowIcon() override;
   void SetWindowAppIcon(CefRefPtr<CefImage> image) override;
   CefRefPtr<CefImage> GetWindowAppIcon() override;
+  CefRefPtr<CefOverlayController> AddOverlayView(
+      CefRefPtr<CefView> view,
+      cef_docking_mode_t docking_mode) override;
   void ShowMenu(CefRefPtr<CefMenuModel> menu_model,
                 const CefPoint& screen_point,
                 cef_menu_anchor_position_t anchor_position) override;
@@ -67,7 +77,7 @@
   void SetDraggableRegions(
       const std::vector<CefDraggableRegion>& regions) override;
   CefWindowHandle GetWindowHandle() override;
-  void SendKeyPress(int key_code, uint32 event_flags) override;
+  void SendKeyPress(int key_code, uint32_t event_flags) override;
   void SendMouseMove(int screen_x, int screen_y) override;
   void SendMouseEvents(cef_mouse_button_type_t button,
                        bool mouse_down,
@@ -76,7 +86,8 @@
                       int key_code,
                       bool shift_pressed,
                       bool ctrl_pressed,
-                      bool alt_pressed) override;
+                      bool alt_pressed,
+                      bool high_priority) override;
   void RemoveAccelerator(int command_id) override;
   void RemoveAllAccelerators() override;
 
@@ -105,8 +116,7 @@
 
   // CefViewAdapter methods:
   std::string GetDebugType() override { return "Window"; }
-  void GetDebugInfo(base::DictionaryValue* info,
-                    bool include_children) override;
+  void GetDebugInfo(base::Value::Dict* info, bool include_children) override;
 
   // ui::AcceleratorTarget methods:
   bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
@@ -123,6 +133,7 @@
   void MenuClosed();
 
   views::Widget* widget() const { return widget_; }
+  bool initialized() const { return initialized_; }
 
  private:
   // Create a new implementation object.
@@ -135,19 +146,22 @@
   void InitializeRootView() override;
 
   // Initialize the Widget.
-  void CreateWidget();
+  void CreateWidget(gfx::AcceleratedWidget parent_widget);
 
-  views::Widget* widget_;
+  views::Widget* widget_ = nullptr;
+
+  // True if the window has been initialized.
+  bool initialized_ = false;
 
   // True if the window has been destroyed.
-  bool destroyed_;
+  bool destroyed_ = false;
 
   // The currently active menu model and runner.
   CefRefPtr<CefMenuModelImpl> menu_model_;
   std::unique_ptr<views::MenuRunner> menu_runner_;
 
   // Map of command_id to accelerator.
-  typedef std::map<int, ui::Accelerator> AcceleratorMap;
+  using AcceleratorMap = std::map<int, ui::Accelerator>;
   AcceleratorMap accelerator_map_;
 
 #if defined(USE_AURA)
@@ -155,8 +169,10 @@
   std::unique_ptr<ui::EventHandler> unhandled_key_event_handler_;
 #endif
 
+  // True if this window was shown using ShowAsBrowserModalDialog().
+  bool shown_as_browser_modal_ = false;
+
   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefWindowImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefWindowImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_WINDOW_IMPL_H_
diff --git a/src/libcef/browser/views/window_view.cc b/src/libcef/browser/views/window_view.cc
index de8cc3a..2331caa 100644
--- a/src/libcef/browser/views/window_view.cc
+++ b/src/libcef/browser/views/window_view.cc
@@ -4,25 +4,42 @@
 
 #include "libcef/browser/views/window_view.h"
 
+#include "libcef/browser/chrome/views/chrome_browser_frame.h"
+#include "libcef/browser/geometry_util.h"
 #include "libcef/browser/image_impl.h"
 #include "libcef/browser/views/window_impl.h"
+#include "libcef/features/runtime.h"
 
-#include "third_party/skia/include/core/SkRegion.h"
-#include "ui/aura/window.h"
 #include "ui/base/hit_test.h"
+#include "ui/display/screen.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/native_frame_view.h"
 
-#if defined(OS_LINUX) && defined(USE_X11)
-#include <X11/Xlib.h>
-#include "ui/gfx/x/x11_types.h"
+#if BUILDFLAG(IS_LINUX)
+#include "ui/ozone/buildflags.h"
+#if BUILDFLAG(OZONE_PLATFORM_X11)
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/x/x11_atom_cache.h"
+#include "ui/gfx/x/xproto_util.h"
+#include "ui/linux/linux_ui_delegate.h"
+#endif
 #endif
 
-#if defined(OS_WIN)
-#include "ui/display/screen.h"
+#if BUILDFLAG(IS_OZONE)
+#include "ui/ozone/public/ozone_platform.h"
+#endif
+
+#if BUILDFLAG(IS_WIN)
+#include <dwmapi.h>
+#include "base/win/windows_version.h"
+#include "ui/display/win/screen_win.h"
 #include "ui/views/win/hwnd_util.h"
 #endif
 
+#if defined(USE_AURA)
+#include "ui/aura/window.h"
+#endif
+
 namespace {
 
 // Specialize ClientView to handle Widget-related events.
@@ -36,12 +53,17 @@
     DCHECK(window_delegate_);
   }
 
-  bool CanClose() override { return window_delegate_->CanWidgetClose(); }
+  ClientViewEx(const ClientViewEx&) = delete;
+  ClientViewEx& operator=(const ClientViewEx&) = delete;
+
+  views::CloseRequestResult OnWindowCloseRequested() override {
+    return window_delegate_->CanWidgetClose()
+               ? views::CloseRequestResult::kCanClose
+               : views::CloseRequestResult::kCannotClose;
+  }
 
  private:
   CefWindowView::Delegate* window_delegate_;  // Not owned by this object.
-
-  DISALLOW_COPY_AND_ASSIGN(ClientViewEx);
 };
 
 // Extend NativeFrameView with draggable region handling.
@@ -50,19 +72,52 @@
   NativeFrameViewEx(views::Widget* widget, CefWindowView* view)
       : views::NativeFrameView(widget), widget_(widget), view_(view) {}
 
+  NativeFrameViewEx(const NativeFrameViewEx&) = delete;
+  NativeFrameViewEx& operator=(const NativeFrameViewEx&) = delete;
+
   gfx::Rect GetWindowBoundsForClientBounds(
       const gfx::Rect& client_bounds) const override {
-#if defined(OS_WIN)
-    // views::GetWindowBoundsForClientBounds() expects the input Rect to be in
-    // pixel coordinates. NativeFrameView does not implement this correctly so
-    // we need to provide our own implementation. See http://crbug.com/602692.
-    gfx::Rect pixel_bounds =
-        display::Screen::GetScreen()->DIPToScreenRectInWindow(
-            view_util::GetNativeWindow(widget_), client_bounds);
-    pixel_bounds = views::GetWindowBoundsForClientBounds(
-        static_cast<View*>(const_cast<NativeFrameViewEx*>(this)), pixel_bounds);
-    return display::Screen::GetScreen()->ScreenToDIPRectInWindow(
-        view_util::GetNativeWindow(widget_), pixel_bounds);
+#if BUILDFLAG(IS_MAC)
+    // From NativeFrameView::GetWindowBoundsForClientBounds:
+    gfx::Rect window_bounds = client_bounds;
+    // Enforce minimum size (1, 1) in case that |client_bounds| is passed with
+    // empty size.
+    if (window_bounds.IsEmpty()) {
+      window_bounds.set_size(gfx::Size(1, 1));
+    }
+
+    if (!view_->IsFrameless()) {
+      if (auto titlebar_height = view_->GetTitlebarHeight()) {
+        window_bounds.Inset(gfx::Insets::TLBR(-(*titlebar_height), 0, 0, 0));
+      }
+    }
+
+    return window_bounds;
+#elif BUILDFLAG(IS_WIN)
+    HWND window = views::HWNDForWidget(widget_);
+    CHECK(window);
+
+    const DWORD style = GetWindowLong(window, GWL_STYLE);
+    const DWORD ex_style = GetWindowLong(window, GWL_EXSTYLE);
+    const bool has_menu = !(style & WS_CHILD) && (GetMenu(window) != NULL);
+
+    // Convert from DIP to pixel coordinates using a method that can handle
+    // multiple displays with different DPI.
+    const auto screen_rect =
+        display::win::ScreenWin::DIPToScreenRect(window, client_bounds);
+
+    RECT rect = {screen_rect.x(), screen_rect.y(),
+                 screen_rect.x() + screen_rect.width(),
+                 screen_rect.y() + screen_rect.height()};
+    AdjustWindowRectEx(&rect, style, has_menu, ex_style);
+
+    // Keep the original origin while potentially increasing the size to include
+    // the frame non-client area.
+    gfx::Rect pixel_rect(screen_rect.x(), screen_rect.y(),
+                         rect.right - rect.left, rect.bottom - rect.top);
+
+    // Convert back to DIP.
+    return display::win::ScreenWin::ScreenToDIPRect(window, pixel_rect);
 #else
     // Use the default implementation.
     return views::NativeFrameView::GetWindowBoundsForClientBounds(
@@ -71,23 +126,42 @@
   }
 
   int NonClientHitTest(const gfx::Point& point) override {
-    if (widget_->IsFullscreen())
+    if (widget_->IsFullscreen()) {
       return HTCLIENT;
+    }
 
     // Test for mouse clicks that fall within the draggable region.
     SkRegion* draggable_region = view_->draggable_region();
-    if (draggable_region && draggable_region->contains(point.x(), point.y()))
+    if (draggable_region && draggable_region->contains(point.x(), point.y())) {
       return HTCAPTION;
+    }
 
     return views::NativeFrameView::NonClientHitTest(point);
   }
 
+#if BUILDFLAG(IS_WIN)
+  void OnThemeChanged() override {
+    views::NativeFrameView::OnThemeChanged();
+
+    // Value was 19 prior to Windows 10 20H1, according to
+    // https://stackoverflow.com/a/70693198
+    const DWORD dwAttribute =
+        base::win::GetVersion() >= base::win::Version::WIN10_20H1
+            ? DWMWA_USE_IMMERSIVE_DARK_MODE
+            : 19;
+
+    // From BrowserFrameViewWin::SetSystemMicaTitlebarAttributes:
+    const BOOL dark_titlebar_enabled = GetNativeTheme()->ShouldUseDarkColors();
+    DwmSetWindowAttribute(views::HWNDForWidget(widget_), dwAttribute,
+                          &dark_titlebar_enabled,
+                          sizeof(dark_titlebar_enabled));
+  }
+#endif
+
  private:
   // Not owned by this object.
   views::Widget* widget_;
   CefWindowView* view_;
-
-  DISALLOW_COPY_AND_ASSIGN(NativeFrameViewEx);
 };
 
 // The area inside the frame border that can be clicked and dragged for resizing
@@ -105,6 +179,9 @@
   CaptionlessFrameView(views::Widget* widget, CefWindowView* view)
       : widget_(widget), view_(view) {}
 
+  CaptionlessFrameView(const CaptionlessFrameView&) = delete;
+  CaptionlessFrameView& operator=(const CaptionlessFrameView&) = delete;
+
   gfx::Rect GetBoundsForClientView() const override {
     return client_view_bounds_;
   }
@@ -115,12 +192,14 @@
   }
 
   int NonClientHitTest(const gfx::Point& point) override {
-    if (widget_->IsFullscreen())
+    if (widget_->IsFullscreen()) {
       return HTCLIENT;
+    }
 
     // Sanity check.
-    if (!bounds().Contains(point))
+    if (!bounds().Contains(point)) {
       return HTNOWHERE;
+    }
 
     // Check the frame first, as we allow a small area overlapping the contents
     // to be used for resize handles.
@@ -131,19 +210,23 @@
     // fullscreen, as it can't be resized in those states.
     int resize_border_thickness = ResizeBorderThickness();
     int frame_component = GetHTComponentForFrame(
-        point, resize_border_thickness, resize_border_thickness,
+        point,
+        gfx::Insets::VH(resize_border_thickness, resize_border_thickness),
         kResizeAreaCornerSize, kResizeAreaCornerSize, can_ever_resize);
-    if (frame_component != HTNOWHERE)
+    if (frame_component != HTNOWHERE) {
       return frame_component;
+    }
 
     // Test for mouse clicks that fall within the draggable region.
     SkRegion* draggable_region = view_->draggable_region();
-    if (draggable_region && draggable_region->contains(point.x(), point.y()))
+    if (draggable_region && draggable_region->contains(point.x(), point.y())) {
       return HTCAPTION;
+    }
 
     int client_component = widget_->client_view()->NonClientHitTest(point);
-    if (client_component != HTNOWHERE)
+    if (client_component != HTNOWHERE) {
       return client_component;
+    }
 
     // Caption is a safe default.
     return HTCAPTION;
@@ -175,6 +258,7 @@
 
   void Layout() override {
     client_view_bounds_.SetRect(0, 0, width(), height());
+    views::NonClientFrameView::Layout();
   }
 
   gfx::Size CalculatePreferredSize() const override {
@@ -214,14 +298,12 @@
 
   // The bounds of the client view, in this view's coordinates.
   gfx::Rect client_view_bounds_;
-
-  DISALLOW_COPY_AND_ASSIGN(CaptionlessFrameView);
 };
 
 bool IsWindowBorderHit(int code) {
 // On Windows HTLEFT = 10 and HTBORDER = 18. Values are not ordered the same
 // in base/hit_test.h for non-Windows platforms.
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   return code >= HTLEFT && code <= HTBORDER;
 #else
   return code == HTLEFT || code == HTRIGHT || code == HTTOP ||
@@ -230,56 +312,201 @@
 #endif
 }
 
+// Based on UpdateModalDialogPosition() from
+// components/constrained_window/constrained_window_views.cc
+void UpdateModalDialogPosition(views::Widget* widget,
+                               views::Widget* host_widget) {
+  // Do not forcibly update the dialog widget position if it is being dragged.
+  if (widget->HasCapture()) {
+    return;
+  }
+
+  const gfx::Size& size = widget->GetRootView()->GetPreferredSize();
+  const gfx::Size& host_size =
+      host_widget->GetClientAreaBoundsInScreen().size();
+
+  // Center the dialog. Position is relative to the host.
+  gfx::Point position;
+  position.set_x((host_size.width() - size.width()) / 2);
+  position.set_y((host_size.height() - size.height()) / 2);
+
+  // Align the first row of pixels inside the border. This is the apparent top
+  // of the dialog.
+  position.set_y(position.y() -
+                 widget->non_client_view()->frame_view()->GetInsets().top());
+
+  const bool supports_global_screen_coordinates =
+#if !BUILDFLAG(IS_OZONE)
+      true;
+#else
+      ui::OzonePlatform::GetInstance()
+          ->GetPlatformProperties()
+          .supports_global_screen_coordinates;
+#endif
+
+  if (widget->is_top_level() && supports_global_screen_coordinates) {
+    position += host_widget->GetClientAreaBoundsInScreen().OffsetFromOrigin();
+    // If the dialog extends partially off any display, clamp its position to
+    // be fully visible within that display. If the dialog doesn't intersect
+    // with any display clamp its position to be fully on the nearest display.
+    gfx::Rect display_rect = gfx::Rect(position, size);
+    const display::Display display =
+        display::Screen::GetScreen()->GetDisplayNearestView(
+            view_util::GetNativeView(host_widget));
+    const gfx::Rect work_area = display.work_area();
+    if (!work_area.Contains(display_rect)) {
+      display_rect.AdjustToFit(work_area);
+    }
+    position = display_rect.origin();
+  }
+
+  widget->SetBounds(gfx::Rect(position, size));
+}
+
 }  // namespace
 
 CefWindowView::CefWindowView(CefWindowDelegate* cef_delegate,
                              Delegate* window_delegate)
-    : ParentClass(cef_delegate),
-      window_delegate_(window_delegate),
-      is_frameless_(false) {
+    : ParentClass(cef_delegate), window_delegate_(window_delegate) {
   DCHECK(window_delegate_);
 }
 
-void CefWindowView::CreateWidget() {
+void CefWindowView::CreateWidget(gfx::AcceleratedWidget parent_widget) {
   DCHECK(!GetWidget());
 
   // |widget| is owned by the NativeWidget and will be destroyed in response to
   // a native destruction message.
-  views::Widget* widget = new views::Widget;
+  views::Widget* widget = cef::IsChromeRuntimeEnabled() ? new ChromeBrowserFrame
+                                                        : new views::Widget;
 
   views::Widget::InitParams params;
   params.delegate = this;
-  params.type = views::Widget::InitParams::TYPE_WINDOW;
-  params.bounds = gfx::Rect(CalculatePreferredSize());
+
+  views::Widget* host_widget = nullptr;
+
   bool can_activate = true;
+  bool can_resize = true;
+
+  const bool has_native_parent = parent_widget != gfx::kNullAcceleratedWidget;
+  if (has_native_parent) {
+    params.parent_widget = parent_widget;
+
+    // Remove the window frame.
+    is_frameless_ = true;
+
+    // See CalculateWindowStylesFromInitParams in
+    // ui/views/widget/widget_hwnd_utils.cc for the conversion of |params| to
+    // Windows style flags.
+    // - Set the WS_CHILD flag.
+    params.child = true;
+    // - Set the WS_VISIBLE flag.
+    params.type = views::Widget::InitParams::TYPE_CONTROL;
+    // - Don't set the WS_EX_COMPOSITED flag.
+    params.opacity = views::Widget::InitParams::WindowOpacity::kOpaque;
+  } else {
+    params.type = views::Widget::InitParams::TYPE_WINDOW;
+  }
+
+  // WidgetDelegate::DeleteDelegate() will delete |this| after executing the
+  // registered callback.
+  SetOwnedByWidget(true);
+  RegisterDeleteDelegateCallback(
+      base::BindOnce(&CefWindowView::DeleteDelegate, base::Unretained(this)));
 
   if (cef_delegate()) {
     CefRefPtr<CefWindow> cef_window = GetCefWindow();
-    is_frameless_ = cef_delegate()->IsFrameless(cef_window);
 
-    bool is_menu = false;
-    bool can_activate_menu = true;
-    CefRefPtr<CefWindow> parent_window = cef_delegate()->GetParentWindow(
-        cef_window, &is_menu, &can_activate_menu);
-    if (parent_window && !parent_window->IsSame(cef_window)) {
-      CefWindowImpl* parent_window_impl =
-          static_cast<CefWindowImpl*>(parent_window.get());
-      params.parent = view_util::GetNativeWindow(parent_window_impl->widget());
-      if (is_menu) {
-        // Don't clip the window to parent bounds.
-        params.type = views::Widget::InitParams::TYPE_MENU;
+    auto bounds = cef_delegate()->GetInitialBounds(cef_window);
+    params.bounds = gfx::Rect(bounds.x, bounds.y, bounds.width, bounds.height);
 
-        // Don't set "always on top" for the window.
-        params.z_order = ui::ZOrderLevel::kNormal;
+    if (has_native_parent) {
+      DCHECK(!params.bounds.IsEmpty());
+    } else {
+      is_frameless_ = cef_delegate()->IsFrameless(cef_window);
 
-        can_activate = can_activate_menu;
-        if (can_activate_menu)
-          params.activatable = views::Widget::InitParams::ACTIVATABLE_YES;
+      params.native_widget =
+          view_util::CreateNativeWidget(widget, cef_window, cef_delegate());
+
+      can_resize = cef_delegate()->CanResize(cef_window);
+
+      const auto show_state = cef_delegate()->GetInitialShowState(cef_window);
+      switch (show_state) {
+        case CEF_SHOW_STATE_NORMAL:
+          params.show_state = ui::SHOW_STATE_NORMAL;
+          break;
+        case CEF_SHOW_STATE_MINIMIZED:
+          params.show_state = ui::SHOW_STATE_MINIMIZED;
+          break;
+        case CEF_SHOW_STATE_MAXIMIZED:
+          params.show_state = ui::SHOW_STATE_MAXIMIZED;
+          break;
+        case CEF_SHOW_STATE_FULLSCREEN:
+          params.show_state = ui::SHOW_STATE_FULLSCREEN;
+          break;
+      }
+
+      bool is_menu = false;
+      bool can_activate_menu = true;
+      CefRefPtr<CefWindow> parent_window = cef_delegate()->GetParentWindow(
+          cef_window, &is_menu, &can_activate_menu);
+      if (parent_window && !parent_window->IsSame(cef_window)) {
+        CefWindowImpl* parent_window_impl =
+            static_cast<CefWindowImpl*>(parent_window.get());
+        params.parent = view_util::GetNativeView(parent_window_impl->widget());
+
+        // Aura uses the same types for NativeView and NativeWindow, which can
+        // be confusing. Verify that we set |params.parent| correctly (to the
+        // expected internal::NativeWidgetPrivate) for Widget::Init usage.
+        DCHECK(views::Widget::GetWidgetForNativeView(params.parent));
+
+        if (is_menu) {
+          // Don't clip the window to parent bounds.
+          params.type = views::Widget::InitParams::TYPE_MENU;
+
+          // Don't set "always on top" for the window.
+          params.z_order = ui::ZOrderLevel::kNormal;
+
+          can_activate = can_activate_menu;
+        } else {
+          // Create a top-level window that is moveable and can exceed the
+          // bounds of the parent window. By not setting |params.child| here we
+          // cause OnBeforeWidgetInit to create a views::DesktopNativeWidgetAura
+          // instead of a views::NativeWidgetAura. We need to use this desktop
+          // variant with browser windows to get proper focus and shutdown
+          // behavior.
+
+#if !BUILDFLAG(IS_LINUX)
+          // SetModalType doesn't work on Linux (no implementation in
+          // DesktopWindowTreeHostLinux::InitModalType). See the X11-specific
+          // implementation below that may work with some window managers.
+          if (cef_delegate()->IsWindowModalDialog(cef_window)) {
+            SetModalType(ui::MODAL_TYPE_WINDOW);
+          }
+#endif
+
+          host_widget = parent_window_impl->widget();
+        }
       }
     }
   }
 
-#if defined(OS_WIN)
+  if (params.bounds.IsEmpty()) {
+    // The window will be placed on the default screen with origin (0,0).
+    params.bounds = gfx::Rect(CalculatePreferredSize());
+    if (params.bounds.IsEmpty()) {
+      // Choose a reasonable default size.
+      params.bounds.set_size({800, 600});
+    }
+  }
+
+  if (can_activate) {
+    // Cause WidgetDelegate::CanActivate to return true.
+    params.activatable = views::Widget::InitParams::Activatable::kYes;
+  }
+
+  SetCanResize(can_resize);
+
+#if BUILDFLAG(IS_WIN)
   if (is_frameless_) {
     // Don't show the native window caption. Setting this value on Linux will
     // result in window resize artifacts.
@@ -288,6 +515,7 @@
 #endif
 
   widget->Init(std::move(params));
+  widget->AddObserver(this);
 
   // |widget| should now be associated with |this|.
   DCHECK_EQ(widget, GetWidget());
@@ -299,42 +527,55 @@
     DCHECK(widget->widget_delegate()->CanActivate());
   }
 
-#if defined(OS_LINUX) && defined(USE_X11)
+#if BUILDFLAG(IS_LINUX)
+#if BUILDFLAG(OZONE_PLATFORM_X11)
+  auto x11window = static_cast<x11::Window>(view_util::GetWindowHandle(widget));
+  CHECK(x11window != x11::Window::None);
+
   if (is_frameless_) {
-    ::Window window = view_util::GetWindowHandle(widget);
-    DCHECK(window);
-    ::Display* display = gfx::GetXDisplay();
-    DCHECK(display);
-
-    // Make the window borderless. From
-    // http://stackoverflow.com/questions/1904445/borderless-windows-on-linux
-    struct MwmHints {
-      unsigned long flags;
-      unsigned long functions;
-      unsigned long decorations;
-      long input_mode;
-      unsigned long status;
-    };
-    enum {
-      MWM_HINTS_FUNCTIONS = (1L << 0),
-      MWM_HINTS_DECORATIONS = (1L << 1),
-
-      MWM_FUNC_ALL = (1L << 0),
-      MWM_FUNC_RESIZE = (1L << 1),
-      MWM_FUNC_MOVE = (1L << 2),
-      MWM_FUNC_MINIMIZE = (1L << 3),
-      MWM_FUNC_MAXIMIZE = (1L << 4),
-      MWM_FUNC_CLOSE = (1L << 5)
-    };
-
-    Atom mwmHintsProperty = XInternAtom(display, "_MOTIF_WM_HINTS", 0);
-    struct MwmHints hints = {};
-    hints.flags = MWM_HINTS_DECORATIONS;
-    hints.decorations = 0;
-    XChangeProperty(display, window, mwmHintsProperty, mwmHintsProperty, 32,
-                    PropModeReplace, (unsigned char*)&hints, 5);
+    ui::SetUseOSWindowFrame(x11window, false);
   }
-#endif  // defined(OS_LINUX) && defined(USE_X11)
+
+  if (host_widget) {
+    auto parent = static_cast<gfx::AcceleratedWidget>(
+        view_util::GetWindowHandle(host_widget));
+    CHECK(parent);
+
+    if (cef_delegate() && cef_delegate()->IsWindowModalDialog(GetCefWindow())) {
+      // The presence of _NET_WM_STATE_MODAL in _NET_SUPPORTED indicates
+      // possible window manager support. However, some window managers still
+      // don't support this properly.
+      x11::Atom modal_atom = x11::GetAtom("_NET_WM_STATE_MODAL");
+      if (ui::WmSupportsHint(modal_atom)) {
+        ui::SetWMSpecState(x11window, true, modal_atom, x11::Atom::None);
+      } else {
+        LOG(ERROR)
+            << "Window modal dialogs are not supported by the window manager";
+      }
+    }
+
+    // From GtkUiPlatformX11::SetGtkWidgetTransientFor:
+    x11::SetProperty(x11window, x11::Atom::WM_TRANSIENT_FOR, x11::Atom::WINDOW,
+                     parent);
+    x11::SetProperty(x11window, x11::GetAtom("_NET_WM_WINDOW_TYPE"),
+                     x11::Atom::ATOM,
+                     x11::GetAtom("_NET_WM_WINDOW_TYPE_DIALOG"));
+
+    ui::LinuxUiDelegate::GetInstance()->SetTransientWindowForParent(
+        parent, static_cast<gfx::AcceleratedWidget>(x11window));
+  }
+#endif
+#endif
+
+  if (host_widget) {
+    // Position |widget| relative to |host_widget|.
+    UpdateModalDialogPosition(widget, host_widget);
+
+    // Track the lifespan of |host_widget|, which may be destroyed before
+    // |widget|.
+    host_widget_destruction_observer_ =
+        std::make_unique<WidgetDestructionObserver>(host_widget);
+  }
 }
 
 CefRefPtr<CefWindow> CefWindowView::GetCefWindow() const {
@@ -346,51 +587,64 @@
 void CefWindowView::DeleteDelegate() {
   // Remove all child Views before deleting the Window so that notifications
   // resolve correctly.
-  RemoveAllChildViews(true);
+  RemoveAllChildViews();
 
   window_delegate_->OnWindowViewDeleted();
-
-  // Deletes |this|.
-  views::WidgetDelegateView::DeleteDelegate();
-}
-
-bool CefWindowView::CanResize() const {
-  if (!cef_delegate())
-    return true;
-  return cef_delegate()->CanResize(GetCefWindow());
 }
 
 bool CefWindowView::CanMinimize() const {
-  if (!cef_delegate())
+  if (!cef_delegate()) {
     return true;
+  }
   return cef_delegate()->CanMinimize(GetCefWindow());
 }
 
 bool CefWindowView::CanMaximize() const {
-  if (!cef_delegate())
+  if (!cef_delegate()) {
     return true;
+  }
   return cef_delegate()->CanMaximize(GetCefWindow());
 }
 
-base::string16 CefWindowView::GetWindowTitle() const {
+std::u16string CefWindowView::GetWindowTitle() const {
   return title_;
 }
 
-gfx::ImageSkia CefWindowView::GetWindowIcon() {
-  if (!window_icon_)
+ui::ImageModel CefWindowView::GetWindowIcon() {
+  if (!window_icon_) {
     return ParentClass::GetWindowIcon();
-  return static_cast<CefImageImpl*>(window_icon_.get())
-      ->GetForced1xScaleRepresentation(GetDisplay().device_scale_factor());
+  }
+  auto image_skia =
+      static_cast<CefImageImpl*>(window_icon_.get())
+          ->GetForced1xScaleRepresentation(GetDisplay().device_scale_factor());
+  return ui::ImageModel::FromImageSkia(image_skia);
 }
 
-gfx::ImageSkia CefWindowView::GetWindowAppIcon() {
-  if (!window_app_icon_)
+ui::ImageModel CefWindowView::GetWindowAppIcon() {
+  if (!window_app_icon_) {
     return ParentClass::GetWindowAppIcon();
-  return static_cast<CefImageImpl*>(window_app_icon_.get())
-      ->GetForced1xScaleRepresentation(GetDisplay().device_scale_factor());
+  }
+  auto image_skia =
+      static_cast<CefImageImpl*>(window_app_icon_.get())
+          ->GetForced1xScaleRepresentation(GetDisplay().device_scale_factor());
+  return ui::ImageModel::FromImageSkia(image_skia);
 }
 
 void CefWindowView::WindowClosing() {
+#if BUILDFLAG(IS_LINUX)
+#if BUILDFLAG(OZONE_PLATFORM_X11)
+  if (host_widget()) {
+    auto parent = static_cast<gfx::AcceleratedWidget>(
+        view_util::GetWindowHandle(host_widget()));
+    CHECK(parent);
+
+    // From GtkUiPlatformX11::ClearTransientFor:
+    ui::LinuxUiDelegate::GetInstance()->SetTransientWindowForParent(
+        parent, static_cast<gfx::AcceleratedWidget>(x11::Window::None));
+  }
+#endif
+#endif
+
   window_delegate_->OnWindowClosing();
 }
 
@@ -404,15 +658,15 @@
   return new ClientViewEx(widget, GetContentsView(), window_delegate_);
 }
 
-views::NonClientFrameView* CefWindowView::CreateNonClientFrameView(
-    views::Widget* widget) {
+std::unique_ptr<views::NonClientFrameView>
+CefWindowView::CreateNonClientFrameView(views::Widget* widget) {
   if (is_frameless_) {
     // Custom frame type that doesn't render a caption.
-    return new CaptionlessFrameView(widget, this);
+    return std::make_unique<CaptionlessFrameView>(widget, this);
   } else if (widget->ShouldUseNativeFrame()) {
     // DesktopNativeWidgetAura::CreateNonClientFrameView() returns
     // NativeFrameView by default. Extend that type.
-    return new NativeFrameViewEx(widget, this);
+    return std::make_unique<NativeFrameViewEx>(widget, this);
   }
 
   // Use Chromium provided CustomFrameView. In case if we would like to
@@ -429,8 +683,9 @@
     views::NonClientFrameView* ncfv = GetNonClientFrameView();
     if (ncfv) {
       int result = ncfv->NonClientHitTest(location);
-      if (IsWindowBorderHit(result))
+      if (IsWindowBorderHit(result)) {
         return false;
+      }
     }
   }
 
@@ -440,7 +695,7 @@
 }
 
 bool CefWindowView::MaybeGetMinimumSize(gfx::Size* size) const {
-#if defined(OS_LINUX)
+#if BUILDFLAG(IS_LINUX)
   // Resize is disabled on Linux by returning the preferred size as the min/max
   // size.
   if (!CanResize()) {
@@ -452,7 +707,7 @@
 }
 
 bool CefWindowView::MaybeGetMaximumSize(gfx::Size* size) const {
-#if defined(OS_LINUX)
+#if BUILDFLAG(IS_LINUX)
   // Resize is disabled on Linux by returning the preferred size as the min/max
   // size.
   if (!CanResize()) {
@@ -475,6 +730,24 @@
   ParentClass::ViewHierarchyChanged(details);
 }
 
+void CefWindowView::OnWidgetActivationChanged(views::Widget* widget,
+                                              bool active) {
+  if (cef_delegate()) {
+    cef_delegate()->OnWindowActivationChanged(GetCefWindow(), active);
+  }
+}
+
+void CefWindowView::OnWidgetBoundsChanged(views::Widget* widget,
+                                          const gfx::Rect& new_bounds) {
+  MoveOverlaysIfNecessary();
+
+  if (cef_delegate()) {
+    cef_delegate()->OnWindowBoundsChanged(
+        GetCefWindow(), {new_bounds.x(), new_bounds.y(), new_bounds.width(),
+                         new_bounds.height()});
+  }
+}
+
 display::Display CefWindowView::GetDisplay() const {
   const views::Widget* widget = GetWidget();
   if (widget) {
@@ -484,11 +757,12 @@
   return display::Display();
 }
 
-void CefWindowView::SetTitle(const base::string16& title) {
+void CefWindowView::SetTitle(const std::u16string& title) {
   title_ = title;
   views::Widget* widget = GetWidget();
-  if (widget)
+  if (widget) {
     widget->UpdateWindowTitle();
+  }
 }
 
 void CefWindowView::SetWindowIcon(CefRefPtr<CefImage> window_icon) {
@@ -499,22 +773,61 @@
 
   window_icon_ = window_icon;
   views::Widget* widget = GetWidget();
-  if (widget)
+  if (widget) {
     widget->UpdateWindowIcon();
+  }
 }
 
 void CefWindowView::SetWindowAppIcon(CefRefPtr<CefImage> window_app_icon) {
   window_app_icon_ = window_app_icon;
   views::Widget* widget = GetWidget();
-  if (widget)
+  if (widget) {
     widget->UpdateWindowIcon();
+  }
+}
+
+CefRefPtr<CefOverlayController> CefWindowView::AddOverlayView(
+    CefRefPtr<CefView> view,
+    cef_docking_mode_t docking_mode) {
+  DCHECK(view.get());
+  DCHECK(view->IsValid());
+  if (!view.get() || !view->IsValid()) {
+    return nullptr;
+  }
+
+  views::Widget* widget = GetWidget();
+  if (widget) {
+    // Owned by the View hierarchy. Acts as a z-order reference for the overlay.
+    auto overlay_host_view = AddChildView(std::make_unique<views::View>());
+
+    overlay_hosts_.push_back(
+        std::make_unique<CefOverlayViewHost>(this, docking_mode));
+
+    auto& overlay_host = overlay_hosts_.back();
+    overlay_host->Init(overlay_host_view, view);
+
+    return overlay_host->controller();
+  }
+
+  return nullptr;
+}
+
+void CefWindowView::MoveOverlaysIfNecessary() {
+  if (overlay_hosts_.empty()) {
+    return;
+  }
+  for (auto& overlay_host : overlay_hosts_) {
+    overlay_host->MoveIfNecessary();
+  }
 }
 
 void CefWindowView::SetDraggableRegions(
     const std::vector<CefDraggableRegion>& regions) {
   if (regions.empty()) {
-    if (draggable_region_)
+    if (draggable_region_) {
       draggable_region_.reset(nullptr);
+    }
+    draggable_rects_.clear();
     return;
   }
 
@@ -525,14 +838,85 @@
          region.bounds.x + region.bounds.width,
          region.bounds.y + region.bounds.height},
         region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op);
+
+    if (region.draggable) {
+      draggable_rects_.push_back({region.bounds.x, region.bounds.y,
+                                  region.bounds.width, region.bounds.height});
+    }
   }
 }
 
 views::NonClientFrameView* CefWindowView::GetNonClientFrameView() const {
   const views::Widget* widget = GetWidget();
-  if (!widget)
+  if (!widget) {
     return nullptr;
-  if (!widget->non_client_view())
+  }
+  if (!widget->non_client_view()) {
     return nullptr;
+  }
   return widget->non_client_view()->frame_view();
 }
+
+void CefWindowView::UpdateFindBarBoundingBox(gfx::Rect* bounds) const {
+  // Max distance from the edges of |bounds| to qualify for subtraction.
+  const int kMaxDistance = 10;
+
+  for (auto& overlay_host : overlay_hosts_) {
+    *bounds = SubtractOverlayFromBoundingBox(*bounds, overlay_host->bounds(),
+                                             kMaxDistance);
+  }
+
+  for (auto& rect : draggable_rects_) {
+    *bounds = SubtractOverlayFromBoundingBox(*bounds, rect, kMaxDistance);
+  }
+
+  if (auto titlebar_height = GetTitlebarHeight()) {
+    gfx::Insets inset;
+
+#if BUILDFLAG(IS_MAC)
+    // For framed windows on macOS we must add the titlebar height.
+    const bool add_titlebar_height = !is_frameless_;
+#else
+    const bool add_titlebar_height = false;
+#endif
+
+    if (add_titlebar_height) {
+      inset.set_top(*titlebar_height);
+    } else if (bounds->y() < *titlebar_height) {
+      inset.set_top(*titlebar_height - bounds->y());
+    }
+
+    if (!inset.IsEmpty()) {
+      bounds->Inset(inset);
+    }
+  }
+}
+
+views::Widget* CefWindowView::host_widget() const {
+  if (host_widget_destruction_observer_) {
+    return host_widget_destruction_observer_->widget();
+  }
+  return nullptr;
+}
+
+absl::optional<float> CefWindowView::GetTitlebarHeight() const {
+  if (cef_delegate()) {
+    float title_bar_height = 0;
+    const bool has_title_bar_height =
+        cef_delegate()->GetTitlebarHeight(GetCefWindow(), &title_bar_height);
+    if (has_title_bar_height) {
+      return title_bar_height;
+    }
+  }
+
+#if BUILDFLAG(IS_MAC)
+  if (!is_frameless_) {
+    // For framed windows on macOS we must include the titlebar height in the
+    // UpdateFindBarBoundingBox() calculation.
+    return view_util::GetNSWindowTitleBarHeight(
+        const_cast<views::Widget*>(GetWidget()));
+  }
+#endif
+
+  return absl::nullopt;
+}
diff --git a/src/libcef/browser/views/window_view.h b/src/libcef/browser/views/window_view.h
index 50093e1..b065f37 100644
--- a/src/libcef/browser/views/window_view.h
+++ b/src/libcef/browser/views/window_view.h
@@ -6,23 +6,28 @@
 #define CEF_LIBCEF_BROWSER_VIEWS_WINDOW_VIEW_H_
 #pragma once
 
+#include <vector>
+
 #include "include/views/cef_window.h"
 #include "include/views/cef_window_delegate.h"
 
+#include "libcef/browser/views/overlay_view_host.h"
 #include "libcef/browser/views/panel_view.h"
+#include "libcef/browser/views/widget_destruction_observer.h"
 
+#include "third_party/skia/include/core/SkRegion.h"
 #include "ui/display/display.h"
 #include "ui/views/widget/widget_delegate.h"
-
-class SkRegion;
+#include "ui/views/widget/widget_observer.h"
 
 // Manages the views-based root window. This object will be deleted
 // automatically when the associated root window is destroyed.
 class CefWindowView
-    : public CefPanelView<views::WidgetDelegateView, CefWindowDelegate> {
+    : public CefPanelView<views::WidgetDelegateView, CefWindowDelegate>,
+      public views::WidgetObserver {
  public:
-  typedef CefPanelView<views::WidgetDelegateView, CefWindowDelegate>
-      ParentClass;
+  using ParentClass =
+      CefPanelView<views::WidgetDelegateView, CefWindowDelegate>;
 
   class Delegate {
    public:
@@ -43,27 +48,26 @@
   // |window_delegate| must be non-nullptr.
   CefWindowView(CefWindowDelegate* cef_delegate, Delegate* window_delegate);
 
+  CefWindowView(const CefWindowView&) = delete;
+  CefWindowView& operator=(const CefWindowView&) = delete;
+
   // Create the Widget.
-  void CreateWidget();
+  void CreateWidget(gfx::AcceleratedWidget parent_widget);
 
   // Returns the CefWindow associated with this view. See comments on
   // CefViewView::GetCefView.
   CefRefPtr<CefWindow> GetCefWindow() const;
 
-  // views::WidgetDelegateView methods:
-  void DeleteDelegate() override;
-
   // views::WidgetDelegate methods:
-  bool CanResize() const override;
   bool CanMinimize() const override;
   bool CanMaximize() const override;
-  base::string16 GetWindowTitle() const override;
-  gfx::ImageSkia GetWindowIcon() override;
-  gfx::ImageSkia GetWindowAppIcon() override;
+  std::u16string GetWindowTitle() const override;
+  ui::ImageModel GetWindowIcon() override;
+  ui::ImageModel GetWindowAppIcon() override;
   void WindowClosing() override;
   views::View* GetContentsView() override;
   views::ClientView* CreateClientView(views::Widget* widget) override;
-  views::NonClientFrameView* CreateNonClientFrameView(
+  std::unique_ptr<views::NonClientFrameView> CreateNonClientFrameView(
       views::Widget* widget) override;
   bool ShouldDescendIntoChildForEventHandling(
       gfx::NativeView child,
@@ -75,12 +79,17 @@
   void ViewHierarchyChanged(
       const views::ViewHierarchyChangedDetails& details) override;
 
+  // views::WidgetObserver methods:
+  void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
+  void OnWidgetBoundsChanged(views::Widget* widget,
+                             const gfx::Rect& new_bounds) override;
+
   // Returns the Display containing this Window.
   display::Display GetDisplay() const;
 
   // Set/get the window title.
-  void SetTitle(const base::string16& title);
-  base::string16 title() const { return title_; }
+  void SetTitle(const std::u16string& title);
+  std::u16string title() const { return title_; }
 
   // Set/get the window icon. This should be a 16x16 icon suitable for use in
   // the Windows's title bar.
@@ -94,6 +103,10 @@
   void SetWindowAppIcon(CefRefPtr<CefImage> window_app_icon);
   CefRefPtr<CefImage> window_app_icon() const { return window_app_icon_; }
 
+  CefRefPtr<CefOverlayController> AddOverlayView(
+      CefRefPtr<CefView> view,
+      cef_docking_mode_t docking_mode);
+
   // Set/get the draggable regions.
   void SetDraggableRegions(const std::vector<CefDraggableRegion>& regions);
   SkRegion* draggable_region() const { return draggable_region_.get(); }
@@ -101,20 +114,40 @@
   // Returns the NonClientFrameView for this Window. May be nullptr.
   views::NonClientFrameView* GetNonClientFrameView() const;
 
+  // Optionally modify the bounding box for the Chrome Find bar.
+  void UpdateFindBarBoundingBox(gfx::Rect* bounds) const;
+
+  absl::optional<float> GetTitlebarHeight() const;
+  bool IsFrameless() const { return is_frameless_; }
+
+  // The Widget that hosts us, if we're a modal dialog. May return nullptr
+  // during initialization and destruction.
+  views::Widget* host_widget() const;
+
  private:
+  // Called when removed from the Widget and before |this| is deleted.
+  void DeleteDelegate();
+
+  void MoveOverlaysIfNecessary();
+
   // Not owned by this object.
   Delegate* window_delegate_;
 
   // True if the window is frameless. It might still be resizable and draggable.
-  bool is_frameless_;
+  bool is_frameless_ = false;
 
-  base::string16 title_;
+  std::u16string title_;
   CefRefPtr<CefImage> window_icon_;
   CefRefPtr<CefImage> window_app_icon_;
 
   std::unique_ptr<SkRegion> draggable_region_;
+  std::vector<gfx::Rect> draggable_rects_;
 
-  DISALLOW_COPY_AND_ASSIGN(CefWindowView);
+  // Tracks the Widget that hosts us, if we're a modal dialog.
+  std::unique_ptr<WidgetDestructionObserver> host_widget_destruction_observer_;
+
+  // Hosts for overlay widgets.
+  std::vector<std::unique_ptr<CefOverlayViewHost>> overlay_hosts_;
 };
 
 #endif  // CEF_LIBCEF_BROWSER_VIEWS_WINDOW_VIEW_H_
diff --git a/src/libcef/browser/web_contents_dialog_helper.cc b/src/libcef/browser/web_contents_dialog_helper.cc
deleted file mode 100644
index ffabe5d..0000000
--- a/src/libcef/browser/web_contents_dialog_helper.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2019 The Chromium Embedded Framework 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 "libcef/browser/web_contents_dialog_helper.h"
-
-#include "libcef/browser/browser_platform_delegate.h"
-
-#include "chrome/browser/platform_util.h"
-#include "components/web_modal/web_contents_modal_dialog_manager.h"
-
-#if defined(USE_AURA)
-#include "ui/views/widget/widget.h"
-#endif
-
-CefWebContentsDialogHelper::CefWebContentsDialogHelper(
-    content::WebContents* web_contents,
-    CefBrowserPlatformDelegate* browser_delegate)
-    : browser_delegate_(browser_delegate), weak_factory_(this) {
-  web_modal::WebContentsModalDialogManager::CreateForWebContents(web_contents);
-  web_modal::WebContentsModalDialogManager::FromWebContents(web_contents)
-      ->SetDelegate(this);
-}
-
-base::RepeatingClosure CefWebContentsDialogHelper::GetBoundsChangedCallback() {
-  return base::BindRepeating(&CefWebContentsDialogHelper::OnBoundsChanged,
-                             weak_factory_.GetWeakPtr());
-}
-
-bool CefWebContentsDialogHelper::IsWebContentsVisible(
-    content::WebContents* web_contents) {
-  return platform_util::IsVisible(web_contents->GetNativeView());
-}
-
-web_modal::WebContentsModalDialogHost*
-CefWebContentsDialogHelper::GetWebContentsModalDialogHost() {
-  return this;
-}
-
-gfx::NativeView CefWebContentsDialogHelper::GetHostView() const {
-#if defined(USE_AURA)
-  return browser_delegate_->GetWindowWidget()->GetNativeView();
-#else
-  NOTIMPLEMENTED();
-  return gfx::NativeView();
-#endif
-}
-
-gfx::Point CefWebContentsDialogHelper::GetDialogPosition(
-    const gfx::Size& size) {
-  return browser_delegate_->GetDialogPosition(size);
-}
-
-gfx::Size CefWebContentsDialogHelper::GetMaximumDialogSize() {
-  return browser_delegate_->GetMaximumDialogSize();
-}
-
-void CefWebContentsDialogHelper::AddObserver(
-    web_modal::ModalDialogHostObserver* observer) {
-  if (observer && !observer_list_.HasObserver(observer))
-    observer_list_.AddObserver(observer);
-}
-
-void CefWebContentsDialogHelper::RemoveObserver(
-    web_modal::ModalDialogHostObserver* observer) {
-  observer_list_.RemoveObserver(observer);
-}
-
-void CefWebContentsDialogHelper::OnBoundsChanged() {
-  for (auto& observer : observer_list_)
-    observer.OnPositionRequiresUpdate();
-}
diff --git a/src/libcef/browser/web_plugin_impl.cc b/src/libcef/browser/web_plugin_impl.cc
deleted file mode 100644
index d61449a..0000000
--- a/src/libcef/browser/web_plugin_impl.cc
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework 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 "libcef/browser/web_plugin_impl.h"
-
-#include "libcef/browser/context.h"
-#include "libcef/browser/thread_util.h"
-#include "libcef/common/widevine_loader.h"
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "content/browser/plugin_service_impl.h"
-
-namespace {
-
-void PluginsCallbackImpl(
-    CefRefPtr<CefWebPluginInfoVisitor> visitor,
-    const std::vector<content::WebPluginInfo>& all_plugins) {
-  CEF_REQUIRE_UIT();
-
-  int count = 0;
-  int total = static_cast<int>(all_plugins.size());
-
-  std::vector<content::WebPluginInfo>::const_iterator it = all_plugins.begin();
-  for (; it != all_plugins.end(); ++it, ++count) {
-    CefRefPtr<CefWebPluginInfoImpl> info(new CefWebPluginInfoImpl(*it));
-    if (!visitor->Visit(info.get(), count, total))
-      break;
-  }
-}
-
-#if !(BUILDFLAG(ENABLE_WIDEVINE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)) || \
-    defined(OS_LINUX)
-
-void DeliverWidevineCdmError(const std::string& error_message,
-                             CefRefPtr<CefRegisterCdmCallback> callback) {
-  LOG(ERROR) << error_message;
-  if (callback.get()) {
-    CEF_POST_TASK(
-        CEF_UIT,
-        base::Bind(&CefRegisterCdmCallback::OnCdmRegistrationComplete,
-                   callback.get(), CEF_CDM_REGISTRATION_ERROR_NOT_SUPPORTED,
-                   error_message));
-  }
-}
-
-#endif
-
-}  // namespace
-
-// CefWebPluginInfoImpl
-
-CefWebPluginInfoImpl::CefWebPluginInfoImpl(
-    const content::WebPluginInfo& plugin_info)
-    : plugin_info_(plugin_info) {}
-
-CefString CefWebPluginInfoImpl::GetName() {
-  return plugin_info_.name;
-}
-
-CefString CefWebPluginInfoImpl::GetPath() {
-  return plugin_info_.path.value();
-}
-
-CefString CefWebPluginInfoImpl::GetVersion() {
-  return plugin_info_.version;
-}
-
-CefString CefWebPluginInfoImpl::GetDescription() {
-  return plugin_info_.desc;
-}
-
-// Global functions.
-
-void CefVisitWebPluginInfo(CefRefPtr<CefWebPluginInfoVisitor> visitor) {
-  // Verify that the context is in a valid state.
-  if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
-    return;
-  }
-
-  if (!visitor.get()) {
-    NOTREACHED() << "invalid parameter";
-    return;
-  }
-
-  if (CEF_CURRENTLY_ON_UIT()) {
-    content::PluginServiceImpl::GetInstance()->GetPlugins(
-        base::Bind(PluginsCallbackImpl, visitor));
-  } else {
-    // Execute on the UI thread.
-    CEF_POST_TASK(CEF_UIT, base::Bind(CefVisitWebPluginInfo, visitor));
-  }
-}
-
-void CefRefreshWebPlugins() {
-  // Verify that the context is in a valid state.
-  if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
-    return;
-  }
-
-  // No thread affinity.
-  content::PluginServiceImpl::GetInstance()->RefreshPlugins();
-}
-
-void CefUnregisterInternalWebPlugin(const CefString& path) {
-  // Verify that the context is in a valid state.
-  if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
-    return;
-  }
-
-  if (path.empty()) {
-    NOTREACHED() << "invalid parameter";
-    return;
-  }
-
-  // No thread affinity.
-  content::PluginServiceImpl::GetInstance()->UnregisterInternalPlugin(
-      base::FilePath(path));
-}
-
-void CefRegisterWebPluginCrash(const CefString& path) {
-  // Verify that the context is in a valid state.
-  if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
-    return;
-  }
-
-  if (path.empty()) {
-    NOTREACHED() << "invalid parameter";
-    return;
-  }
-
-  if (CEF_CURRENTLY_ON_IOT()) {
-    content::PluginServiceImpl::GetInstance()->RegisterPluginCrash(
-        base::FilePath(path));
-  } else {
-    // Execute on the IO thread.
-    CEF_POST_TASK(CEF_IOT, base::Bind(CefRegisterWebPluginCrash, path));
-  }
-}
-
-void CefIsWebPluginUnstable(const CefString& path,
-                            CefRefPtr<CefWebPluginUnstableCallback> callback) {
-  // Verify that the context is in a valid state.
-  if (!CONTEXT_STATE_VALID()) {
-    NOTREACHED() << "context not valid";
-    return;
-  }
-
-  if (path.empty() || !callback.get()) {
-    NOTREACHED() << "invalid parameter";
-    return;
-  }
-
-  if (CEF_CURRENTLY_ON_IOT()) {
-    callback->IsUnstable(
-        path, content::PluginServiceImpl::GetInstance()->IsPluginUnstable(
-                  base::FilePath(path)));
-  } else {
-    // Execute on the IO thread.
-    CEF_POST_TASK(CEF_IOT, base::Bind(CefIsWebPluginUnstable, path, callback));
-  }
-}
-
-void CefRegisterWidevineCdm(const CefString& path,
-                            CefRefPtr<CefRegisterCdmCallback> callback) {
-#if BUILDFLAG(ENABLE_WIDEVINE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
-#if defined(OS_LINUX)
-  // Enforce the requirement that CefRegisterWidevineCdm() is called before
-  // CefInitialize() on Linux. See comments in
-  // CefWidevineLoader::AddPepperPlugins for details.
-  if (CONTEXT_STATE_VALID()) {
-    DeliverWidevineCdmError(
-        "Widevine registration is not supported after context initialization",
-        callback);
-    return;
-  }
-#endif  // defined(OS_LINUX)
-
-  CefWidevineLoader::GetInstance()->LoadWidevineCdm(path, callback);
-#else
-  DeliverWidevineCdmError("Widevine registration is not supported", callback);
-#endif  // BUILDFLAG(ENABLE_WIDEVINE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
-}
diff --git a/src/libcef/browser/web_plugin_impl.h b/src/libcef/browser/web_plugin_impl.h
deleted file mode 100644
index 2e58425..0000000
--- a/src/libcef/browser/web_plugin_impl.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_WEB_PLUGIN_IMPL_H_
-#define CEF_LIBCEF_BROWSER_WEB_PLUGIN_IMPL_H_
-#pragma once
-
-#include "content/public/common/webplugininfo.h"
-#include "include/cef_web_plugin.h"
-
-class CefWebPluginInfoImpl : public CefWebPluginInfo {
- public:
-  explicit CefWebPluginInfoImpl(const content::WebPluginInfo& plugin_info);
-
-  CefString GetName() override;
-  CefString GetPath() override;
-  CefString GetVersion() override;
-  CefString GetDescription() override;
-
- private:
-  content::WebPluginInfo plugin_info_;
-
-  IMPLEMENT_REFCOUNTING(CefWebPluginInfoImpl);
-};
-
-#endif  // CEF_LIBCEF_BROWSER_WEB_PLUGIN_IMPL_H_
diff --git a/src/libcef/browser/x509_cert_principal_impl.cc b/src/libcef/browser/x509_cert_principal_impl.cc
index 233447b..d315fdd 100644
--- a/src/libcef/browser/x509_cert_principal_impl.cc
+++ b/src/libcef/browser/x509_cert_principal_impl.cc
@@ -8,13 +8,15 @@
 
 void TransferVector(const std::vector<std::string>& source,
                     std::vector<CefString>& target) {
-  if (!target.empty())
+  if (!target.empty()) {
     target.clear();
+  }
 
   if (!source.empty()) {
     std::vector<std::string>::const_iterator it = source.begin();
-    for (; it != source.end(); ++it)
+    for (; it != source.end(); ++it) {
       target.push_back(*it);
+    }
   }
 }
 
@@ -44,11 +46,6 @@
   return value_.country_name;
 }
 
-void CefX509CertPrincipalImpl::GetStreetAddresses(
-    std::vector<CefString>& addresses) {
-  TransferVector(value_.street_addresses, addresses);
-}
-
 void CefX509CertPrincipalImpl::GetOrganizationNames(
     std::vector<CefString>& names) {
   TransferVector(value_.organization_names, names);
@@ -58,8 +55,3 @@
     std::vector<CefString>& names) {
   TransferVector(value_.organization_unit_names, names);
 }
-
-void CefX509CertPrincipalImpl::GetDomainComponents(
-    std::vector<CefString>& components) {
-  TransferVector(value_.domain_components, components);
-}
diff --git a/src/libcef/browser/x509_cert_principal_impl.h b/src/libcef/browser/x509_cert_principal_impl.h
index 20b409e..9c065d5 100644
--- a/src/libcef/browser/x509_cert_principal_impl.h
+++ b/src/libcef/browser/x509_cert_principal_impl.h
@@ -15,22 +15,22 @@
  public:
   explicit CefX509CertPrincipalImpl(const net::CertPrincipal& value);
 
+  CefX509CertPrincipalImpl(const CefX509CertPrincipalImpl&) = delete;
+  CefX509CertPrincipalImpl& operator=(const CefX509CertPrincipalImpl&) = delete;
+
   // CefX509CertPrincipal methods.
   CefString GetDisplayName() override;
   CefString GetCommonName() override;
   CefString GetLocalityName() override;
   CefString GetStateOrProvinceName() override;
   CefString GetCountryName() override;
-  void GetStreetAddresses(std::vector<CefString>& addresses) override;
   void GetOrganizationNames(std::vector<CefString>& names) override;
   void GetOrganizationUnitNames(std::vector<CefString>& names) override;
-  void GetDomainComponents(std::vector<CefString>& components) override;
 
  private:
   net::CertPrincipal value_;
 
   IMPLEMENT_REFCOUNTING(CefX509CertPrincipalImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefX509CertPrincipalImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_X509_CERT_PRINCIPAL_IMPL_H_
diff --git a/src/libcef/browser/x509_certificate_impl.cc b/src/libcef/browser/x509_certificate_impl.cc
index 0ae4c42..2aeb00b 100644
--- a/src/libcef/browser/x509_certificate_impl.cc
+++ b/src/libcef/browser/x509_certificate_impl.cc
@@ -21,8 +21,9 @@
   } else if (!net::X509Certificate::GetPEMEncoded(cert_buffer, &encoded)) {
     return nullptr;
   }
-  if (encoded.empty())
+  if (encoded.empty()) {
     return nullptr;
+  }
   return CefBinaryValue::Create(encoded.c_str(), encoded.size());
 }
 
@@ -37,14 +38,16 @@
     : cert_(cert) {}
 
 CefRefPtr<CefX509CertPrincipal> CefX509CertificateImpl::GetSubject() {
-  if (cert_)
+  if (cert_) {
     return new CefX509CertPrincipalImpl(cert_->subject());
+  }
   return nullptr;
 }
 
 CefRefPtr<CefX509CertPrincipal> CefX509CertificateImpl::GetIssuer() {
-  if (cert_)
+  if (cert_) {
     return new CefX509CertPrincipalImpl(cert_->issuer());
+  }
   return nullptr;
 }
 
@@ -56,31 +59,26 @@
   return nullptr;
 }
 
-CefTime CefX509CertificateImpl::GetValidStart() {
-  CefTime validity;
+CefBaseTime CefX509CertificateImpl::GetValidStart() {
   if (cert_) {
-    const base::Time& valid_time = cert_->valid_start();
-    if (!valid_time.is_null())
-      cef_time_from_basetime(valid_time, validity);
+    return cert_->valid_start();
   }
-  return validity;
+  return CefBaseTime();
 }
 
-CefTime CefX509CertificateImpl::GetValidExpiry() {
-  CefTime validity;
+CefBaseTime CefX509CertificateImpl::GetValidExpiry() {
   if (cert_) {
-    const base::Time& valid_time = cert_->valid_expiry();
-    if (!valid_time.is_null())
-      cef_time_from_basetime(valid_time, validity);
+    return cert_->valid_expiry();
   }
-  return validity;
+  return CefBaseTime();
 }
 
 CefRefPtr<CefBinaryValue> CefX509CertificateImpl::GetDEREncoded() {
   if (cert_) {
     const CRYPTO_BUFFER* cert_buffer = cert_->cert_buffer();
-    if (cert_buffer)
+    if (cert_buffer) {
       return EncodeCertificate(cert_buffer, true);
+    }
   }
   return nullptr;
 }
@@ -88,25 +86,28 @@
 CefRefPtr<CefBinaryValue> CefX509CertificateImpl::GetPEMEncoded() {
   if (cert_) {
     const CRYPTO_BUFFER* cert_buffer = cert_->cert_buffer();
-    if (cert_buffer)
+    if (cert_buffer) {
       return EncodeCertificate(cert_buffer, false);
+    }
   }
   return nullptr;
 }
 
 size_t CefX509CertificateImpl::GetIssuerChainSize() {
-  if (cert_)
+  if (cert_) {
     return cert_->intermediate_buffers().size();
+  }
   return 0;
 }
 
 void CefX509CertificateImpl::AcquirePrivateKey(
     base::OnceCallback<void(scoped_refptr<net::SSLPrivateKey>)>
         private_key_callback) {
-  if (identity_)
+  if (identity_) {
     identity_->AcquirePrivateKey(std::move(private_key_callback));
-  else
+  } else {
     std::move(private_key_callback).Run(nullptr);
+  }
 }
 
 void CefX509CertificateImpl::GetEncodedIssuerChain(
@@ -124,14 +125,16 @@
 
 void CefX509CertificateImpl::GetDEREncodedIssuerChain(
     CefX509Certificate::IssuerChainBinaryList& chain) {
-  if (der_encoded_issuer_chain_.empty())
+  if (der_encoded_issuer_chain_.empty()) {
     GetEncodedIssuerChain(der_encoded_issuer_chain_, true);
+  }
   chain = der_encoded_issuer_chain_;
 }
 
 void CefX509CertificateImpl::GetPEMEncodedIssuerChain(
     CefX509Certificate::IssuerChainBinaryList& chain) {
-  if (pem_encoded_issuer_chain_.empty())
+  if (pem_encoded_issuer_chain_.empty()) {
     GetEncodedIssuerChain(pem_encoded_issuer_chain_, false);
+  }
   chain = pem_encoded_issuer_chain_;
 }
diff --git a/src/libcef/browser/x509_certificate_impl.h b/src/libcef/browser/x509_certificate_impl.h
index 5a5fc37..5178ca3 100644
--- a/src/libcef/browser/x509_certificate_impl.h
+++ b/src/libcef/browser/x509_certificate_impl.h
@@ -17,7 +17,10 @@
  public:
   explicit CefX509CertificateImpl(scoped_refptr<net::X509Certificate> cert);
 
-  // Used with CefContentBrowserClient::SelectClientCertificate only.
+  CefX509CertificateImpl(const CefX509CertificateImpl&) = delete;
+  CefX509CertificateImpl& operator=(const CefX509CertificateImpl&) = delete;
+
+  // Used with AlloyContentBrowserClient::SelectClientCertificate only.
   explicit CefX509CertificateImpl(
       std::unique_ptr<net::ClientCertIdentity> identity);
 
@@ -25,8 +28,8 @@
   CefRefPtr<CefX509CertPrincipal> GetSubject() override;
   CefRefPtr<CefX509CertPrincipal> GetIssuer() override;
   CefRefPtr<CefBinaryValue> GetSerialNumber() override;
-  CefTime GetValidStart() override;
-  CefTime GetValidExpiry() override;
+  CefBaseTime GetValidStart() override;
+  CefBaseTime GetValidExpiry() override;
   CefRefPtr<CefBinaryValue> GetDEREncoded() override;
   CefRefPtr<CefBinaryValue> GetPEMEncoded() override;
   size_t GetIssuerChainSize() override;
@@ -47,7 +50,6 @@
   IssuerChainBinaryList der_encoded_issuer_chain_;
 
   IMPLEMENT_REFCOUNTING(CefX509CertificateImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefX509CertificateImpl);
 };
 
 #endif  // CEF_LIBCEF_BROWSER_X509_CERTIFICATE_IMPL_H_
diff --git a/src/libcef/browser/xml_reader_impl.cc b/src/libcef/browser/xml_reader_impl.cc
index 5a18a6f..3e30061 100644
--- a/src/libcef/browser/xml_reader_impl.cc
+++ b/src/libcef/browser/xml_reader_impl.cc
@@ -3,9 +3,12 @@
 // can be found in the LICENSE file.
 
 #include "libcef/browser/xml_reader_impl.h"
-#include "base/logging.h"
+
 #include "include/cef_stream.h"
 
+#include "base/logging.h"
+#include "base/notreached.h"
+
 // Static functions
 
 // static
@@ -13,8 +16,9 @@
                                              EncodingType encodingType,
                                              const CefString& URI) {
   CefRefPtr<CefXmlReaderImpl> impl(new CefXmlReaderImpl());
-  if (!impl->Initialize(stream, encodingType, URI))
+  if (!impl->Initialize(stream, encodingType, URI)) {
     return nullptr;
+  }
   return impl.get();
 }
 
@@ -50,12 +54,14 @@
                                 const char* msg,
                                 xmlParserSeverities severity,
                                 xmlTextReaderLocatorPtr locator) {
-  if (!msg)
+  if (!msg) {
     return;
+  }
 
   std::string error_str(msg);
-  if (!error_str.empty() && error_str[error_str.length() - 1] == '\n')
+  if (!error_str.empty() && error_str[error_str.length() - 1] == '\n') {
     error_str.resize(error_str.length() - 1);
+  }
 
   std::stringstream ss;
   ss << error_str << ", line " << xmlTextReaderLocatorLineNumber(locator);
@@ -75,12 +81,14 @@
  * the module handles the new error reporting mechanism.
  */
 void XMLCALL xml_structured_error_callback(void* userData, xmlErrorPtr error) {
-  if (!error->message)
+  if (!error->message) {
     return;
+  }
 
   std::string error_str(error->message);
-  if (!error_str.empty() && error_str[error_str.length() - 1] == '\n')
+  if (!error_str.empty() && error_str[error_str.length() - 1] == '\n') {
     error_str.resize(error_str.length() - 1);
+  }
 
   std::stringstream ss;
   ss << error_str << ", line " << error->line;
@@ -92,14 +100,16 @@
 }
 
 CefString xmlCharToString(const xmlChar* xmlStr, bool free) {
-  if (!xmlStr)
+  if (!xmlStr) {
     return CefString();
+  }
 
   const char* str = reinterpret_cast<const char*>(xmlStr);
   CefString wstr = std::string(str);
 
-  if (free)
+  if (free) {
     xmlFree(const_cast<xmlChar*>(xmlStr));
+  }
 
   return wstr;
 }
@@ -145,8 +155,9 @@
 
   // Create the input buffer.
   xmlParserInputBufferPtr input_buffer = xmlAllocParserInputBuffer(enc);
-  if (!input_buffer)
+  if (!input_buffer) {
     return false;
+  }
 
   input_buffer->context = stream.get();
   input_buffer->readcallback = xml_read_callback;
@@ -172,15 +183,17 @@
 }
 
 bool CefXmlReaderImpl::MoveToNextNode() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   return xmlTextReaderRead(reader_) == 1 ? true : false;
 }
 
 bool CefXmlReaderImpl::Close() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   // The input buffer will be freed automatically.
   xmlFreeTextReader(reader_);
@@ -189,22 +202,25 @@
 }
 
 bool CefXmlReaderImpl::HasError() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   return !error_buf_.str().empty();
 }
 
 CefString CefXmlReaderImpl::GetError() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return CefString();
+  }
 
   return error_buf_.str();
 }
 
 CefXmlReader::NodeType CefXmlReaderImpl::GetType() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return XML_NODE_UNSUPPORTED;
+  }
 
   switch (xmlTextReaderNodeType(reader_)) {
     case XML_READER_TYPE_ELEMENT:
@@ -236,64 +252,73 @@
 }
 
 int CefXmlReaderImpl::GetDepth() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return -1;
+  }
 
   return xmlTextReaderDepth(reader_);
 }
 
 CefString CefXmlReaderImpl::GetLocalName() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return CefString();
+  }
 
   return xmlCharToString(xmlTextReaderConstLocalName(reader_), false);
 }
 
 CefString CefXmlReaderImpl::GetPrefix() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return CefString();
+  }
 
   return xmlCharToString(xmlTextReaderConstPrefix(reader_), false);
 }
 
 CefString CefXmlReaderImpl::GetQualifiedName() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return CefString();
+  }
 
   return xmlCharToString(xmlTextReaderConstName(reader_), false);
 }
 
 CefString CefXmlReaderImpl::GetNamespaceURI() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return CefString();
+  }
 
   return xmlCharToString(xmlTextReaderConstNamespaceUri(reader_), false);
 }
 
 CefString CefXmlReaderImpl::GetBaseURI() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return CefString();
+  }
 
   return xmlCharToString(xmlTextReaderConstBaseUri(reader_), false);
 }
 
 CefString CefXmlReaderImpl::GetXmlLang() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return CefString();
+  }
 
   return xmlCharToString(xmlTextReaderConstXmlLang(reader_), false);
 }
 
 bool CefXmlReaderImpl::IsEmptyElement() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   return xmlTextReaderIsEmptyElement(reader_) == 1 ? true : false;
 }
 
 bool CefXmlReaderImpl::HasValue() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   if (xmlTextReaderNodeType(reader_) == XML_READER_TYPE_ENTITY_REFERENCE) {
     // Provide special handling to return entity reference values.
@@ -304,14 +329,16 @@
 }
 
 CefString CefXmlReaderImpl::GetValue() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return CefString();
+  }
 
   if (xmlTextReaderNodeType(reader_) == XML_READER_TYPE_ENTITY_REFERENCE) {
     // Provide special handling to return entity reference values.
     xmlNodePtr node = xmlTextReaderCurrentNode(reader_);
-    if (node->content != nullptr)
+    if (node->content != nullptr) {
       return xmlCharToString(node->content, false);
+    }
     return CefString();
   } else {
     return xmlCharToString(xmlTextReaderConstValue(reader_), false);
@@ -319,29 +346,33 @@
 }
 
 bool CefXmlReaderImpl::HasAttributes() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   return xmlTextReaderHasAttributes(reader_) == 1 ? true : false;
 }
 
 size_t CefXmlReaderImpl::GetAttributeCount() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return 0;
+  }
 
   return xmlTextReaderAttributeCount(reader_);
 }
 
 CefString CefXmlReaderImpl::GetAttribute(int index) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return CefString();
+  }
 
   return xmlCharToString(xmlTextReaderGetAttributeNo(reader_, index), true);
 }
 
 CefString CefXmlReaderImpl::GetAttribute(const CefString& qualifiedName) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return CefString();
+  }
 
   std::string qualifiedNameStr = qualifiedName;
   return xmlCharToString(
@@ -351,8 +382,9 @@
 
 CefString CefXmlReaderImpl::GetAttribute(const CefString& localName,
                                          const CefString& namespaceURI) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return CefString();
+  }
 
   std::string localNameStr = localName;
   std::string namespaceURIStr = namespaceURI;
@@ -363,36 +395,41 @@
 }
 
 CefString CefXmlReaderImpl::GetInnerXml() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return CefString();
+  }
 
   return xmlCharToString(xmlTextReaderReadInnerXml(reader_), true);
 }
 
 CefString CefXmlReaderImpl::GetOuterXml() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return CefString();
+  }
 
   return xmlCharToString(xmlTextReaderReadOuterXml(reader_), true);
 }
 
 int CefXmlReaderImpl::GetLineNumber() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return -1;
+  }
 
   return xmlTextReaderGetParserLineNumber(reader_);
 }
 
 bool CefXmlReaderImpl::MoveToAttribute(int index) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   return xmlTextReaderMoveToAttributeNo(reader_, index) == 1 ? true : false;
 }
 
 bool CefXmlReaderImpl::MoveToAttribute(const CefString& qualifiedName) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   std::string qualifiedNameStr = qualifiedName;
   return xmlTextReaderMoveToAttribute(reader_,
@@ -403,8 +440,9 @@
 
 bool CefXmlReaderImpl::MoveToAttribute(const CefString& localName,
                                        const CefString& namespaceURI) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   std::string localNameStr = localName;
   std::string namespaceURIStr = namespaceURI;
@@ -415,36 +453,40 @@
 }
 
 bool CefXmlReaderImpl::MoveToFirstAttribute() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   return xmlTextReaderMoveToFirstAttribute(reader_) == 1 ? true : false;
 }
 
 bool CefXmlReaderImpl::MoveToNextAttribute() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   return xmlTextReaderMoveToNextAttribute(reader_) == 1 ? true : false;
 }
 
 bool CefXmlReaderImpl::MoveToCarryingElement() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   return xmlTextReaderMoveToElement(reader_) == 1 ? true : false;
 }
 
 void CefXmlReaderImpl::AppendError(const CefString& error_str) {
-  if (!error_buf_.str().empty())
+  if (!error_buf_.str().empty()) {
     error_buf_ << L"\n";
-  error_buf_ << error_str;
+  }
+  error_buf_ << error_str.ToString();
 }
 
 bool CefXmlReaderImpl::VerifyContext() {
   if (base::PlatformThread::CurrentId() != supported_thread_id_) {
     // This object should only be accessed from the thread that created it.
-    NOTREACHED();
+    DCHECK(false);
     return false;
   }
 
diff --git a/src/libcef/browser/zip_reader_impl.cc b/src/libcef/browser/zip_reader_impl.cc
index 57bc299..32a59a7 100644
--- a/src/libcef/browser/zip_reader_impl.cc
+++ b/src/libcef/browser/zip_reader_impl.cc
@@ -5,6 +5,8 @@
 #include "libcef/browser/zip_reader_impl.h"
 #include <time.h>
 #include "base/logging.h"
+#include "base/notreached.h"
+#include "base/time/time.h"
 #include "include/cef_stream.h"
 
 // Static functions
@@ -13,8 +15,9 @@
 CefRefPtr<CefZipReader> CefZipReader::Create(
     CefRefPtr<CefStreamReader> stream) {
   CefRefPtr<CefZipReaderImpl> impl(new CefZipReaderImpl());
-  if (!impl->Initialize(stream))
+  if (!impl->Initialize(stream)) {
     return nullptr;
+  }
   return impl.get();
 }
 
@@ -55,7 +58,7 @@
       whence = SEEK_SET;
       break;
     default:
-      NOTREACHED();
+      DCHECK(false);
       return -1;
   }
   return reader->Seek(offset, whence);
@@ -87,8 +90,9 @@
     if (!VerifyContext()) {
       // Close() is supposed to be called directly. We'll try to free the reader
       // now on the wrong thread but there's no guarantee this call won't crash.
-      if (has_fileopen_)
+      if (has_fileopen_) {
         unzCloseCurrentFile(reader_);
+      }
       unzClose(reader_);
     } else {
       Close();
@@ -115,11 +119,13 @@
 }
 
 bool CefZipReaderImpl::MoveToFirstFile() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (has_fileopen_)
+  if (has_fileopen_) {
     CloseFile();
+  }
 
   has_fileinfo_ = false;
 
@@ -127,11 +133,13 @@
 }
 
 bool CefZipReaderImpl::MoveToNextFile() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (has_fileopen_)
+  if (has_fileopen_) {
     CloseFile();
+  }
 
   has_fileinfo_ = false;
 
@@ -140,11 +148,13 @@
 
 bool CefZipReaderImpl::MoveToFile(const CefString& fileName,
                                   bool caseSensitive) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (has_fileopen_)
+  if (has_fileopen_) {
     CloseFile();
+  }
 
   has_fileinfo_ = false;
 
@@ -154,11 +164,13 @@
 }
 
 bool CefZipReaderImpl::Close() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (has_fileopen_)
+  if (has_fileopen_) {
     CloseFile();
+  }
 
   int result = unzClose(reader_);
   reader_ = nullptr;
@@ -166,34 +178,37 @@
 }
 
 CefString CefZipReaderImpl::GetFileName() {
-  if (!VerifyContext() || !GetFileInfo())
+  if (!VerifyContext() || !GetFileInfo()) {
     return CefString();
+  }
 
   return filename_;
 }
 
-int64 CefZipReaderImpl::GetFileSize() {
-  if (!VerifyContext() || !GetFileInfo())
+int64_t CefZipReaderImpl::GetFileSize() {
+  if (!VerifyContext() || !GetFileInfo()) {
     return -1;
+  }
 
   return filesize_;
 }
 
-CefTime CefZipReaderImpl::GetFileLastModified() {
-  CefTime time;
-  if (!VerifyContext() || !GetFileInfo())
-    return time;
+CefBaseTime CefZipReaderImpl::GetFileLastModified() {
+  if (!VerifyContext() || !GetFileInfo()) {
+    return CefBaseTime();
+  }
 
-  cef_time_from_timet(filemodified_, &time);
-  return time;
+  return base::Time::FromTimeT(filemodified_);
 }
 
 bool CefZipReaderImpl::OpenFile(const CefString& password) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (has_fileopen_)
+  if (has_fileopen_) {
     CloseFile();
+  }
 
   bool ret;
 
@@ -204,14 +219,16 @@
     ret = (unzOpenCurrentFilePassword(reader_, passwordStr.c_str()) == UNZ_OK);
   }
 
-  if (ret)
+  if (ret) {
     has_fileopen_ = true;
+  }
   return ret;
 }
 
 bool CefZipReaderImpl::CloseFile() {
-  if (!VerifyContext() || !has_fileopen_)
+  if (!VerifyContext() || !has_fileopen_) {
     return false;
+  }
 
   has_fileopen_ = false;
   has_fileinfo_ = false;
@@ -220,29 +237,33 @@
 }
 
 int CefZipReaderImpl::ReadFile(void* buffer, size_t bufferSize) {
-  if (!VerifyContext() || !has_fileopen_)
+  if (!VerifyContext() || !has_fileopen_) {
     return -1;
+  }
 
   return unzReadCurrentFile(reader_, buffer, bufferSize);
 }
 
-int64 CefZipReaderImpl::Tell() {
-  if (!VerifyContext() || !has_fileopen_)
+int64_t CefZipReaderImpl::Tell() {
+  if (!VerifyContext() || !has_fileopen_) {
     return -1;
+  }
 
   return unztell64(reader_);
 }
 
 bool CefZipReaderImpl::Eof() {
-  if (!VerifyContext() || !has_fileopen_)
+  if (!VerifyContext() || !has_fileopen_) {
     return true;
+  }
 
   return (unzeof(reader_) == 1 ? true : false);
 }
 
 bool CefZipReaderImpl::GetFileInfo() {
-  if (has_fileinfo_)
+  if (has_fileinfo_) {
     return true;
+  }
 
   char file_name[512] = {0};
   unz_file_info file_info;
@@ -274,7 +295,7 @@
 bool CefZipReaderImpl::VerifyContext() {
   if (base::PlatformThread::CurrentId() != supported_thread_id_) {
     // This object should only be accessed from the thread that created it.
-    NOTREACHED();
+    DCHECK(false);
     return false;
   }
 
diff --git a/src/libcef/browser/zip_reader_impl.h b/src/libcef/browser/zip_reader_impl.h
index 722dbf9..a50959d 100644
--- a/src/libcef/browser/zip_reader_impl.h
+++ b/src/libcef/browser/zip_reader_impl.h
@@ -26,12 +26,12 @@
   bool MoveToFile(const CefString& fileName, bool caseSensitive) override;
   bool Close() override;
   CefString GetFileName() override;
-  int64 GetFileSize() override;
-  CefTime GetFileLastModified() override;
+  int64_t GetFileSize() override;
+  CefBaseTime GetFileLastModified() override;
   bool OpenFile(const CefString& password) override;
   bool CloseFile() override;
   int ReadFile(void* buffer, size_t bufferSize) override;
-  int64 Tell() override;
+  int64_t Tell() override;
   bool Eof() override;
 
   bool GetFileInfo();
@@ -46,7 +46,7 @@
   bool has_fileopen_;
   bool has_fileinfo_;
   CefString filename_;
-  int64 filesize_;
+  int64_t filesize_;
   time_t filemodified_;
 
   IMPLEMENT_REFCOUNTING(CefZipReaderImpl);
diff --git a/src/libcef/common/alloy/alloy_content_client.cc b/src/libcef/common/alloy/alloy_content_client.cc
new file mode 100644
index 0000000..99d72f7
--- /dev/null
+++ b/src/libcef/common/alloy/alloy_content_client.cc
@@ -0,0 +1,160 @@
+// Copyright 2015 The Chromium Embedded Framework Authors.
+// Portions copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/common/alloy/alloy_content_client.h"
+
+#include <stdint.h>
+
+#include "include/cef_stream.h"
+#include "include/cef_version.h"
+#include "libcef/common/app_manager.h"
+#include "libcef/common/cef_switches.h"
+#include "libcef/common/extensions/extensions_util.h"
+
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/json/json_reader.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_content_client.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/media/cdm_registration.h"
+#include "components/pdf/common/internal_plugin_helpers.h"
+#include "content/public/common/cdm_info.h"
+#include "content/public/common/content_constants.h"
+#include "content/public/common/content_plugin_info.h"
+#include "content/public/common/content_switches.h"
+#include "ppapi/shared_impl/ppapi_permissions.h"
+#include "third_party/widevine/cdm/buildflags.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
+#include "libcef/common/cdm_host_file_path.h"
+#endif
+
+namespace {
+
+// The following plugin-related methods are from
+// chrome/common/chrome_content_client.cc
+
+constexpr char kPDFPluginName[] = "Chromium PDF Plugin";
+constexpr char kPDFPluginExtension[] = "pdf";
+constexpr char kPDFPluginDescription[] = "Portable Document Format";
+constexpr uint32_t kPDFPluginPermissions =
+    ppapi::PERMISSION_PDF | ppapi::PERMISSION_DEV;
+
+// Appends the known built-in plugins to the given vector. Some built-in
+// plugins are "internal" which means they are compiled into the Chrome binary,
+// and some are extra shared libraries distributed with the browser (these are
+// not marked internal, aside from being automatically registered, they're just
+// regular plugins).
+void ComputeBuiltInPlugins(std::vector<content::ContentPluginInfo>* plugins) {
+  if (extensions::PdfExtensionEnabled()) {
+    content::ContentPluginInfo pdf_info;
+    pdf_info.is_internal = true;
+    pdf_info.is_out_of_process = true;
+    pdf_info.name = kPDFPluginName;
+    pdf_info.description = kPDFPluginDescription;
+    pdf_info.path = base::FilePath(ChromeContentClient::kPDFInternalPluginPath);
+    content::WebPluginMimeType pdf_mime_type(pdf::kInternalPluginMimeType,
+                                             kPDFPluginExtension,
+                                             kPDFPluginDescription);
+    pdf_info.mime_types.push_back(pdf_mime_type);
+    pdf_info.permissions = kPDFPluginPermissions;
+    plugins->push_back(pdf_info);
+  }
+}
+
+}  // namespace
+
+AlloyContentClient::AlloyContentClient() = default;
+AlloyContentClient::~AlloyContentClient() = default;
+
+void AlloyContentClient::AddPlugins(
+    std::vector<content::ContentPluginInfo>* plugins) {
+  ComputeBuiltInPlugins(plugins);
+}
+
+void AlloyContentClient::AddContentDecryptionModules(
+    std::vector<content::CdmInfo>* cdms,
+    std::vector<media::CdmHostFilePath>* cdm_host_file_paths) {
+  if (cdms) {
+    RegisterCdmInfo(cdms);
+  }
+
+#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
+  if (cdm_host_file_paths) {
+    cef::AddCdmHostFilePaths(cdm_host_file_paths);
+  }
+#endif
+}
+
+void AlloyContentClient::AddAdditionalSchemes(Schemes* schemes) {
+  CefAppManager::Get()->AddAdditionalSchemes(schemes);
+}
+
+std::u16string AlloyContentClient::GetLocalizedString(int message_id) {
+  std::u16string value =
+      ui::ResourceBundle::GetSharedInstance().GetLocalizedString(message_id);
+  if (value.empty()) {
+    LOG(ERROR) << "No localized string available for id " << message_id;
+  }
+
+  return value;
+}
+
+std::u16string AlloyContentClient::GetLocalizedString(
+    int message_id,
+    const std::u16string& replacement) {
+  std::u16string value = l10n_util::GetStringFUTF16(message_id, replacement);
+  if (value.empty()) {
+    LOG(ERROR) << "No localized string available for id " << message_id;
+  }
+
+  return value;
+}
+
+base::StringPiece AlloyContentClient::GetDataResource(
+    int resource_id,
+    ui::ResourceScaleFactor scale_factor) {
+  base::StringPiece value =
+      ui::ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(
+          resource_id, scale_factor);
+  if (value.empty()) {
+    LOG(ERROR) << "No data resource available for id " << resource_id;
+  }
+
+  return value;
+}
+
+base::RefCountedMemory* AlloyContentClient::GetDataResourceBytes(
+    int resource_id) {
+  base::RefCountedMemory* value =
+      ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
+          resource_id);
+  if (!value) {
+    LOG(ERROR) << "No data resource bytes available for id " << resource_id;
+  }
+
+  return value;
+}
+
+gfx::Image& AlloyContentClient::GetNativeImageNamed(int resource_id) {
+  gfx::Image& value =
+      ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id);
+  if (value.IsEmpty()) {
+    LOG(ERROR) << "No native image available for id " << resource_id;
+  }
+
+  return value;
+}
diff --git a/src/libcef/common/alloy/alloy_content_client.h b/src/libcef/common/alloy/alloy_content_client.h
new file mode 100644
index 0000000..968bb32
--- /dev/null
+++ b/src/libcef/common/alloy/alloy_content_client.h
@@ -0,0 +1,33 @@
+// Copyright 2015 The Chromium Embedded Framework Authors.
+// Portions copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_COMMON_ALLOY_ALLOY_CONTENT_CLIENT_H_
+#define CEF_LIBCEF_COMMON_ALLOY_ALLOY_CONTENT_CLIENT_H_
+#pragma once
+
+#include "content/public/common/content_client.h"
+
+class AlloyContentClient : public content::ContentClient {
+ public:
+  AlloyContentClient();
+  ~AlloyContentClient() override;
+
+  // content::ContentClient overrides.
+  void AddPlugins(std::vector<content::ContentPluginInfo>* plugins) override;
+  void AddContentDecryptionModules(
+      std::vector<content::CdmInfo>* cdms,
+      std::vector<media::CdmHostFilePath>* cdm_host_file_paths) override;
+  void AddAdditionalSchemes(Schemes* schemes) override;
+  std::u16string GetLocalizedString(int message_id) override;
+  std::u16string GetLocalizedString(int message_id,
+                                    const std::u16string& replacement) override;
+  base::StringPiece GetDataResource(
+      int resource_id,
+      ui::ResourceScaleFactor scale_factor) override;
+  base::RefCountedMemory* GetDataResourceBytes(int resource_id) override;
+  gfx::Image& GetNativeImageNamed(int resource_id) override;
+};
+
+#endif  // CEF_LIBCEF_COMMON_ALLOY_ALLOY_CONTENT_CLIENT_H_
diff --git a/src/libcef/common/alloy/alloy_main_delegate.cc b/src/libcef/common/alloy/alloy_main_delegate.cc
new file mode 100644
index 0000000..0c12ac8
--- /dev/null
+++ b/src/libcef/common/alloy/alloy_main_delegate.cc
@@ -0,0 +1,676 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/common/alloy/alloy_main_delegate.h"
+
+#include <tuple>
+
+#include "libcef/browser/alloy/alloy_browser_context.h"
+#include "libcef/browser/alloy/alloy_content_browser_client.h"
+#include "libcef/common/cef_switches.h"
+#include "libcef/common/command_line_impl.h"
+#include "libcef/common/crash_reporting.h"
+#include "libcef/common/extensions/extensions_util.h"
+#include "libcef/common/resource_util.h"
+#include "libcef/renderer/alloy/alloy_content_renderer_client.h"
+
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/synchronization/waitable_event.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/child/pdf_child_init.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/utility/chrome_content_utility_client.h"
+#include "components/component_updater/component_updater_paths.h"
+#include "components/content_settings/core/common/content_settings_pattern.h"
+#include "components/embedder_support/switches.h"
+#include "components/viz/common/features.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/main_function_params.h"
+#include "content/public/common/url_constants.h"
+#include "extensions/common/constants.h"
+#include "net/base/features.h"
+#include "sandbox/policy/switches.h"
+#include "services/network/public/cpp/features.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/switches.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/ui_base_features.h"
+#include "ui/base/ui_base_paths.h"
+#include "ui/base/ui_base_switches.h"
+
+#if BUILDFLAG(IS_MAC)
+#include "components/crash/core/common/objc_zombie.h"
+#include "libcef/common/util_mac.h"
+#elif BUILDFLAG(IS_POSIX)
+#include "libcef/common/util_linux.h"
+#endif
+
+#if BUILDFLAG(IS_WIN)
+#include "ui/base/resource/resource_bundle_win.h"
+#endif
+
+namespace {
+
+const char* const kNonWildcardDomainNonPortSchemes[] = {
+    extensions::kExtensionScheme, content::kChromeDevToolsScheme,
+    content::kChromeUIScheme, content::kChromeUIUntrustedScheme};
+const size_t kNonWildcardDomainNonPortSchemesSize =
+    std::size(kNonWildcardDomainNonPortSchemes);
+
+}  // namespace
+
+AlloyMainDelegate::AlloyMainDelegate(CefMainRunnerHandler* runner,
+                                     CefSettings* settings,
+                                     CefRefPtr<CefApp> application)
+    : runner_(runner), settings_(settings), application_(application) {
+#if BUILDFLAG(IS_LINUX)
+  resource_util::OverrideAssetPath();
+#endif
+}
+
+AlloyMainDelegate::~AlloyMainDelegate() {}
+
+absl::optional<int> AlloyMainDelegate::PreBrowserMain() {
+  runner_->PreBrowserMain();
+  return absl::nullopt;
+}
+
+absl::optional<int> AlloyMainDelegate::BasicStartupComplete() {
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  std::string process_type =
+      command_line->GetSwitchValueASCII(switches::kProcessType);
+
+#if BUILDFLAG(IS_POSIX)
+  // Read the crash configuration file. On Windows this is done from chrome_elf.
+  crash_reporting::BasicStartupComplete(command_line);
+#endif
+
+  const bool is_browser = process_type.empty();
+  if (is_browser) {
+    // In the browser process. Populate the global command-line object.
+    if (settings_->command_line_args_disabled) {
+      // Remove any existing command-line arguments.
+      base::CommandLine::StringVector argv;
+      argv.push_back(command_line->GetProgram().value());
+      command_line->InitFromArgv(argv);
+
+      const base::CommandLine::SwitchMap& map = command_line->GetSwitches();
+      const_cast<base::CommandLine::SwitchMap*>(&map)->clear();
+    }
+
+    bool no_sandbox = settings_->no_sandbox ? true : false;
+
+    if (settings_->browser_subprocess_path.length > 0) {
+      base::FilePath file_path =
+          base::FilePath(CefString(&settings_->browser_subprocess_path));
+      if (!file_path.empty()) {
+        command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
+                                       file_path);
+
+#if BUILDFLAG(IS_WIN)
+        // The sandbox is not supported when using a separate subprocess
+        // executable on Windows.
+        no_sandbox = true;
+#endif
+      }
+    }
+
+#if BUILDFLAG(IS_MAC)
+    if (settings_->framework_dir_path.length > 0) {
+      base::FilePath file_path =
+          base::FilePath(CefString(&settings_->framework_dir_path));
+      if (!file_path.empty()) {
+        command_line->AppendSwitchPath(switches::kFrameworkDirPath, file_path);
+      }
+    }
+
+    if (settings_->main_bundle_path.length > 0) {
+      base::FilePath file_path =
+          base::FilePath(CefString(&settings_->main_bundle_path));
+      if (!file_path.empty()) {
+        command_line->AppendSwitchPath(switches::kMainBundlePath, file_path);
+      }
+    }
+#endif
+
+    if (no_sandbox) {
+      command_line->AppendSwitch(sandbox::policy::switches::kNoSandbox);
+    }
+
+    if (settings_->user_agent.length > 0) {
+      command_line->AppendSwitchASCII(
+          embedder_support::kUserAgent,
+          CefString(&settings_->user_agent).ToString());
+    } else if (settings_->user_agent_product.length > 0) {
+      command_line->AppendSwitchASCII(
+          switches::kUserAgentProductAndVersion,
+          CefString(&settings_->user_agent_product).ToString());
+    }
+
+    if (settings_->locale.length > 0) {
+      command_line->AppendSwitchASCII(switches::kLang,
+                                      CefString(&settings_->locale).ToString());
+    } else if (!command_line->HasSwitch(switches::kLang)) {
+      command_line->AppendSwitchASCII(switches::kLang, "en-US");
+    }
+
+    base::FilePath log_file;
+    bool has_log_file_cmdline = false;
+    if (settings_->log_file.length > 0) {
+      log_file = base::FilePath(CefString(&settings_->log_file));
+    }
+    if (log_file.empty() && command_line->HasSwitch(switches::kLogFile)) {
+      log_file = command_line->GetSwitchValuePath(switches::kLogFile);
+      if (!log_file.empty()) {
+        has_log_file_cmdline = true;
+      }
+    }
+    if (log_file.empty()) {
+      log_file = resource_util::GetDefaultLogFilePath();
+    }
+    DCHECK(!log_file.empty());
+    if (!has_log_file_cmdline) {
+      command_line->AppendSwitchPath(switches::kLogFile, log_file);
+    }
+
+    if (settings_->log_severity != LOGSEVERITY_DEFAULT) {
+      std::string log_severity;
+      switch (settings_->log_severity) {
+        case LOGSEVERITY_VERBOSE:
+          log_severity = switches::kLogSeverity_Verbose;
+          break;
+        case LOGSEVERITY_INFO:
+          log_severity = switches::kLogSeverity_Info;
+          break;
+        case LOGSEVERITY_WARNING:
+          log_severity = switches::kLogSeverity_Warning;
+          break;
+        case LOGSEVERITY_ERROR:
+          log_severity = switches::kLogSeverity_Error;
+          break;
+        case LOGSEVERITY_FATAL:
+          log_severity = switches::kLogSeverity_Fatal;
+          break;
+        case LOGSEVERITY_DISABLE:
+          log_severity = switches::kLogSeverity_Disable;
+          break;
+        default:
+          break;
+      }
+      if (!log_severity.empty()) {
+        command_line->AppendSwitchASCII(switches::kLogSeverity, log_severity);
+      }
+    }
+
+    if (settings_->log_items != LOG_ITEMS_DEFAULT) {
+      std::string log_items_str;
+      if (settings_->log_items == LOG_ITEMS_NONE) {
+        log_items_str = std::string(switches::kLogItems_None);
+      } else {
+        std::vector<base::StringPiece> added_items;
+        if (settings_->log_items & LOG_ITEMS_FLAG_PROCESS_ID) {
+          added_items.push_back(base::StringPiece(switches::kLogItems_PId));
+        }
+        if (settings_->log_items & LOG_ITEMS_FLAG_THREAD_ID) {
+          added_items.push_back(base::StringPiece(switches::kLogItems_TId));
+        }
+        if (settings_->log_items & LOG_ITEMS_FLAG_TIME_STAMP) {
+          added_items.push_back(
+              base::StringPiece(switches::kLogItems_TimeStamp));
+        }
+        if (settings_->log_items & LOG_ITEMS_FLAG_TICK_COUNT) {
+          added_items.push_back(
+              base::StringPiece(switches::kLogItems_TickCount));
+        }
+        if (!added_items.empty()) {
+          log_items_str = base::JoinString(added_items, ",");
+        }
+      }
+      if (!log_items_str.empty()) {
+        command_line->AppendSwitchASCII(switches::kLogItems, log_items_str);
+      }
+    }
+
+    if (settings_->javascript_flags.length > 0) {
+      command_line->AppendSwitchASCII(
+          blink::switches::kJavaScriptFlags,
+          CefString(&settings_->javascript_flags).ToString());
+    }
+
+    if (settings_->pack_loading_disabled) {
+      command_line->AppendSwitch(switches::kDisablePackLoading);
+    } else {
+      if (settings_->resources_dir_path.length > 0) {
+        base::FilePath file_path =
+            base::FilePath(CefString(&settings_->resources_dir_path));
+        if (!file_path.empty()) {
+          command_line->AppendSwitchPath(switches::kResourcesDirPath,
+                                         file_path);
+        }
+      }
+
+      if (settings_->locales_dir_path.length > 0) {
+        base::FilePath file_path =
+            base::FilePath(CefString(&settings_->locales_dir_path));
+        if (!file_path.empty()) {
+          command_line->AppendSwitchPath(switches::kLocalesDirPath, file_path);
+        }
+      }
+    }
+
+    if (settings_->remote_debugging_port >= 1024 &&
+        settings_->remote_debugging_port <= 65535) {
+      command_line->AppendSwitchASCII(
+          switches::kRemoteDebuggingPort,
+          base::NumberToString(settings_->remote_debugging_port));
+    }
+
+    if (settings_->uncaught_exception_stack_size > 0) {
+      command_line->AppendSwitchASCII(
+          switches::kUncaughtExceptionStackSize,
+          base::NumberToString(settings_->uncaught_exception_stack_size));
+    }
+
+    std::vector<std::string> disable_features;
+
+#if BUILDFLAG(IS_WIN)
+    if (features::kCalculateNativeWinOcclusion.default_state ==
+        base::FEATURE_ENABLED_BY_DEFAULT) {
+      // TODO: Add support for occlusion detection in combination with native
+      // parent windows (see issue #2805).
+      disable_features.push_back(features::kCalculateNativeWinOcclusion.name);
+    }
+#endif  // BUILDFLAG(IS_WIN)
+
+    if (features::kBackForwardCache.default_state ==
+        base::FEATURE_ENABLED_BY_DEFAULT) {
+      // Disable BackForwardCache globally so that
+      // blink::RuntimeEnabledFeatures::BackForwardCacheEnabled reports the
+      // correct value in the renderer process (see issue #3374).
+      disable_features.push_back(features::kBackForwardCache.name);
+    }
+
+    if (blink::features::kDocumentPictureInPictureAPI.default_state ==
+        base::FEATURE_ENABLED_BY_DEFAULT) {
+      // Disable DocumentPictureInPictureAPI globally so that
+      // blink::RuntimeEnabledFeatures::DocumentPictureInPictureAPIEnabled
+      // reports the correct value in the renderer process (see issue #3448).
+      disable_features.push_back(
+          blink::features::kDocumentPictureInPictureAPI.name);
+    }
+
+    if (!disable_features.empty()) {
+      DCHECK(!base::FeatureList::GetInstance());
+      std::string disable_features_str =
+          command_line->GetSwitchValueASCII(switches::kDisableFeatures);
+      for (auto feature_str : disable_features) {
+        if (!disable_features_str.empty()) {
+          disable_features_str += ",";
+        }
+        disable_features_str += feature_str;
+      }
+      command_line->AppendSwitchASCII(switches::kDisableFeatures,
+                                      disable_features_str);
+    }
+  }
+
+  if (application_) {
+    // Give the application a chance to view/modify the command line.
+    CefRefPtr<CefCommandLineImpl> commandLinePtr(
+        new CefCommandLineImpl(command_line, false, false));
+    application_->OnBeforeCommandLineProcessing(CefString(process_type),
+                                                commandLinePtr.get());
+    std::ignore = commandLinePtr->Detach(nullptr);
+  }
+
+#if BUILDFLAG(IS_MAC)
+  // Turns all deallocated Objective-C objects into zombies. Give the browser
+  // process a longer treadmill, since crashes there have more impact.
+  ObjcEvilDoers::ZombieEnable(true, is_browser ? 10000 : 1000);
+#endif
+
+  // Initialize logging.
+  logging::LoggingSettings log_settings;
+
+  const base::FilePath& log_file =
+      command_line->GetSwitchValuePath(switches::kLogFile);
+  DCHECK(!log_file.empty());
+  log_settings.log_file_path = log_file.value().c_str();
+
+  log_settings.lock_log = logging::DONT_LOCK_LOG_FILE;
+  log_settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
+
+  logging::LogSeverity log_severity = logging::LOG_INFO;
+
+  std::string log_severity_str =
+      command_line->GetSwitchValueASCII(switches::kLogSeverity);
+  if (!log_severity_str.empty()) {
+    if (base::EqualsCaseInsensitiveASCII(log_severity_str,
+                                         switches::kLogSeverity_Verbose)) {
+      log_severity = logging::LOG_VERBOSE;
+    } else if (base::EqualsCaseInsensitiveASCII(
+                   log_severity_str, switches::kLogSeverity_Warning)) {
+      log_severity = logging::LOG_WARNING;
+    } else if (base::EqualsCaseInsensitiveASCII(log_severity_str,
+                                                switches::kLogSeverity_Error)) {
+      log_severity = logging::LOG_ERROR;
+    } else if (base::EqualsCaseInsensitiveASCII(log_severity_str,
+                                                switches::kLogSeverity_Fatal)) {
+      log_severity = logging::LOG_FATAL;
+    } else if (base::EqualsCaseInsensitiveASCII(
+                   log_severity_str, switches::kLogSeverity_Disable)) {
+      log_severity = LOGSEVERITY_DISABLE;
+    }
+  }
+
+  if (log_severity == LOGSEVERITY_DISABLE) {
+    log_settings.logging_dest = logging::LOG_NONE;
+    // By default, ERROR and FATAL messages will always be output to stderr due
+    // to the kAlwaysPrintErrorLevel value in base/logging.cc. We change the log
+    // level here so that only FATAL messages are output.
+    logging::SetMinLogLevel(logging::LOG_FATAL);
+  } else {
+    log_settings.logging_dest = logging::LOG_TO_ALL;
+    logging::SetMinLogLevel(log_severity);
+  }
+
+  // Customization of items automatically prepended to log lines.
+  std::string log_items_str =
+      command_line->GetSwitchValueASCII(switches::kLogItems);
+  if (!log_items_str.empty()) {
+    bool enable_log_of_process_id, enable_log_of_thread_id,
+        enable_log_of_time_stamp, enable_log_of_tick_count;
+    enable_log_of_process_id = enable_log_of_thread_id =
+        enable_log_of_time_stamp = enable_log_of_tick_count = false;
+
+    for (const auto& cur_item_to_log :
+         base::SplitStringPiece(log_items_str, ",", base::TRIM_WHITESPACE,
+                                base::SPLIT_WANT_NONEMPTY)) {
+      // if "none" mode is present, all items are disabled.
+      if (base::EqualsCaseInsensitiveASCII(cur_item_to_log,
+                                           switches::kLogItems_None)) {
+        enable_log_of_process_id = enable_log_of_thread_id =
+            enable_log_of_time_stamp = enable_log_of_tick_count = false;
+        break;
+      } else if (base::EqualsCaseInsensitiveASCII(cur_item_to_log,
+                                                  switches::kLogItems_PId)) {
+        enable_log_of_process_id = true;
+      } else if (base::EqualsCaseInsensitiveASCII(cur_item_to_log,
+                                                  switches::kLogItems_TId)) {
+        enable_log_of_thread_id = true;
+      } else if (base::EqualsCaseInsensitiveASCII(
+                     cur_item_to_log, switches::kLogItems_TimeStamp)) {
+        enable_log_of_time_stamp = true;
+      } else if (base::EqualsCaseInsensitiveASCII(
+                     cur_item_to_log, switches::kLogItems_TickCount)) {
+        enable_log_of_tick_count = true;
+      }
+    }
+    logging::SetLogItems(enable_log_of_process_id, enable_log_of_thread_id,
+                         enable_log_of_time_stamp, enable_log_of_tick_count);
+  }
+
+  logging::InitLogging(log_settings);
+
+  ContentSettingsPattern::SetNonWildcardDomainNonPortSchemes(
+      kNonWildcardDomainNonPortSchemes, kNonWildcardDomainNonPortSchemesSize);
+
+  content::SetContentClient(&content_client_);
+
+#if BUILDFLAG(IS_MAC)
+  util_mac::BasicStartupComplete();
+#endif
+
+  return absl::nullopt;
+}
+
+void AlloyMainDelegate::PreSandboxStartup() {
+  const base::CommandLine* command_line =
+      base::CommandLine::ForCurrentProcess();
+  const std::string& process_type =
+      command_line->GetSwitchValueASCII(switches::kProcessType);
+
+  if (process_type.empty()) {
+// Only override these paths when executing the main process.
+#if BUILDFLAG(IS_MAC)
+    util_mac::PreSandboxStartup();
+#elif BUILDFLAG(IS_POSIX)
+    util_linux::PreSandboxStartup();
+#endif
+
+    resource_util::OverrideDefaultDownloadDir();
+  }
+
+  resource_util::OverrideUserDataDir(settings_, command_line);
+
+  if (command_line->HasSwitch(switches::kDisablePackLoading)) {
+    resource_bundle_delegate_.set_pack_loading_disabled(true);
+  }
+
+  // Initialize crash reporting state for this process/module.
+  // chrome::DIR_CRASH_DUMPS must be configured before calling this function.
+  crash_reporting::PreSandboxStartup(*command_line, process_type);
+
+  // Register the component_updater PathProvider.
+  component_updater::RegisterPathProvider(chrome::DIR_COMPONENTS,
+                                          chrome::DIR_INTERNAL_PLUGINS,
+                                          chrome::DIR_USER_DATA);
+
+  InitializeResourceBundle();
+  MaybePatchGdiGetFontData();
+}
+
+absl::variant<int, content::MainFunctionParams> AlloyMainDelegate::RunProcess(
+    const std::string& process_type,
+    content::MainFunctionParams main_function_params) {
+  if (process_type.empty()) {
+    return runner_->RunMainProcess(std::move(main_function_params));
+  }
+
+  return std::move(main_function_params);
+}
+
+void AlloyMainDelegate::ProcessExiting(const std::string& process_type) {
+  ui::ResourceBundle::CleanupSharedInstance();
+}
+
+#if BUILDFLAG(IS_LINUX)
+void AlloyMainDelegate::ZygoteForked() {
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  const std::string& process_type =
+      command_line->GetSwitchValueASCII(switches::kProcessType);
+  // Initialize crash reporting state for the newly forked process.
+  crash_reporting::ZygoteForked(command_line, process_type);
+}
+#endif
+
+content::ContentBrowserClient* AlloyMainDelegate::CreateContentBrowserClient() {
+  browser_client_.reset(new AlloyContentBrowserClient);
+  return browser_client_.get();
+}
+
+content::ContentRendererClient*
+AlloyMainDelegate::CreateContentRendererClient() {
+  renderer_client_.reset(new AlloyContentRendererClient);
+  return renderer_client_.get();
+}
+
+content::ContentUtilityClient* AlloyMainDelegate::CreateContentUtilityClient() {
+  utility_client_.reset(new ChromeContentUtilityClient);
+  return utility_client_.get();
+}
+
+CefRefPtr<CefRequestContext> AlloyMainDelegate::GetGlobalRequestContext() {
+  if (!browser_client_) {
+    return nullptr;
+  }
+  return browser_client_->request_context();
+}
+
+CefBrowserContext* AlloyMainDelegate::CreateNewBrowserContext(
+    const CefRequestContextSettings& settings,
+    base::OnceClosure initialized_cb) {
+  auto context = new AlloyBrowserContext(settings);
+  context->Initialize();
+  std::move(initialized_cb).Run();
+  return context;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+AlloyMainDelegate::GetBackgroundTaskRunner() {
+  if (browser_client_) {
+    return browser_client_->background_task_runner();
+  }
+  return nullptr;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+AlloyMainDelegate::GetUserVisibleTaskRunner() {
+  if (browser_client_) {
+    return browser_client_->user_visible_task_runner();
+  }
+  return nullptr;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+AlloyMainDelegate::GetUserBlockingTaskRunner() {
+  if (browser_client_) {
+    return browser_client_->user_blocking_task_runner();
+  }
+  return nullptr;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+AlloyMainDelegate::GetRenderTaskRunner() {
+  if (renderer_client_) {
+    return renderer_client_->render_task_runner();
+  }
+  return nullptr;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+AlloyMainDelegate::GetWebWorkerTaskRunner() {
+  if (renderer_client_) {
+    return renderer_client_->GetCurrentTaskRunner();
+  }
+  return nullptr;
+}
+
+void AlloyMainDelegate::InitializeResourceBundle() {
+  const base::CommandLine* command_line =
+      base::CommandLine::ForCurrentProcess();
+  base::FilePath resources_pak_file, chrome_100_percent_pak_file,
+      chrome_200_percent_pak_file, locales_dir;
+
+  base::FilePath resources_dir;
+  if (command_line->HasSwitch(switches::kResourcesDirPath)) {
+    resources_dir =
+        command_line->GetSwitchValuePath(switches::kResourcesDirPath);
+  }
+  if (resources_dir.empty()) {
+    resources_dir = resource_util::GetResourcesDir();
+  }
+  if (!resources_dir.empty()) {
+    base::PathService::Override(chrome::DIR_RESOURCES, resources_dir);
+  }
+
+  if (!resource_bundle_delegate_.pack_loading_disabled()) {
+    if (!resources_dir.empty()) {
+      CHECK(resources_dir.IsAbsolute());
+      resources_pak_file =
+          resources_dir.Append(FILE_PATH_LITERAL("resources.pak"));
+      chrome_100_percent_pak_file =
+          resources_dir.Append(FILE_PATH_LITERAL("chrome_100_percent.pak"));
+      chrome_200_percent_pak_file =
+          resources_dir.Append(FILE_PATH_LITERAL("chrome_200_percent.pak"));
+    }
+
+    if (command_line->HasSwitch(switches::kLocalesDirPath)) {
+      locales_dir = command_line->GetSwitchValuePath(switches::kLocalesDirPath);
+    }
+
+    if (!locales_dir.empty()) {
+      base::PathService::Override(ui::DIR_LOCALES, locales_dir);
+    }
+  }
+
+#if BUILDFLAG(IS_WIN)
+  // From chrome/app/chrome_main_delegate.cc
+  // Throbber icons and cursors are still stored in chrome.dll,
+  // this can be killed once those are merged into resources.pak. See
+  // GlassBrowserFrameView::InitThrobberIcons(), https://crbug.com/368327 and
+  // https://crbug.com/1178117.
+  auto module_handle =
+      ::GetModuleHandle(CefAppManager::Get()->GetResourceDllName());
+  if (!module_handle) {
+    module_handle = ::GetModuleHandle(NULL);
+  }
+
+  ui::SetResourcesDataDLL(module_handle);
+#endif
+
+  std::string locale = command_line->GetSwitchValueASCII(switches::kLang);
+  DCHECK(!locale.empty());
+
+  const std::string loaded_locale =
+      ui::ResourceBundle::InitSharedInstanceWithLocale(
+          locale, &resource_bundle_delegate_,
+          ui::ResourceBundle::LOAD_COMMON_RESOURCES);
+  if (!loaded_locale.empty() && g_browser_process) {
+    g_browser_process->SetApplicationLocale(loaded_locale);
+  }
+
+  ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
+
+  if (!resource_bundle_delegate_.pack_loading_disabled()) {
+    if (loaded_locale.empty()) {
+      LOG(ERROR) << "Could not load locale pak for " << locale;
+    }
+
+    resource_bundle_delegate_.set_allow_pack_file_load(true);
+
+    if (base::PathExists(resources_pak_file)) {
+      resource_bundle.AddDataPackFromPath(resources_pak_file,
+                                          ui::kScaleFactorNone);
+    } else {
+      LOG(ERROR) << "Could not load resources.pak";
+    }
+
+    // Always load the 1x data pack first as the 2x data pack contains both 1x
+    // and 2x images. The 1x data pack only has 1x images, thus passes in an
+    // accurate scale factor to gfx::ImageSkia::AddRepresentation.
+    if (resource_util::IsScaleFactorSupported(ui::k100Percent)) {
+      if (base::PathExists(chrome_100_percent_pak_file)) {
+        resource_bundle.AddDataPackFromPath(chrome_100_percent_pak_file,
+                                            ui::k100Percent);
+      } else {
+        LOG(ERROR) << "Could not load chrome_100_percent.pak";
+      }
+    }
+
+    if (resource_util::IsScaleFactorSupported(ui::k200Percent)) {
+      if (base::PathExists(chrome_200_percent_pak_file)) {
+        resource_bundle.AddDataPackFromPath(chrome_200_percent_pak_file,
+                                            ui::k200Percent);
+      } else {
+        LOG(ERROR) << "Could not load chrome_200_percent.pak";
+      }
+    }
+
+    // Skip the default pak file loading that would otherwise occur in
+    // ResourceBundle::LoadChromeResources().
+    resource_bundle_delegate_.set_allow_pack_file_load(false);
+  }
+}
diff --git a/src/libcef/common/alloy/alloy_main_delegate.h b/src/libcef/common/alloy/alloy_main_delegate.h
new file mode 100644
index 0000000..911a161
--- /dev/null
+++ b/src/libcef/common/alloy/alloy_main_delegate.h
@@ -0,0 +1,105 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_COMMON_ALLOY_ALLOY_MAIN_DELEGATE_H_
+#define CEF_LIBCEF_COMMON_ALLOY_ALLOY_MAIN_DELEGATE_H_
+#pragma once
+
+#include <string>
+
+#include "include/cef_app.h"
+#include "libcef/common/alloy/alloy_content_client.h"
+#include "libcef/common/app_manager.h"
+#include "libcef/common/main_runner_handler.h"
+#include "libcef/common/resource_bundle_delegate.h"
+#include "libcef/common/task_runner_manager.h"
+
+#include "content/public/app/content_main_delegate.h"
+
+#if BUILDFLAG(IS_WIN)
+#include "components/spellcheck/common/spellcheck_features.h"
+#endif
+
+namespace base {
+class CommandLine;
+}
+
+class AlloyContentBrowserClient;
+class AlloyContentRendererClient;
+class ChromeContentUtilityClient;
+
+// Manages state specific to the CEF runtime.
+class AlloyMainDelegate : public content::ContentMainDelegate,
+                          public CefAppManager,
+                          public CefTaskRunnerManager {
+ public:
+  // |runner| and |settings| will be non-nullptr for the main process only,
+  // and will outlive this object.
+  AlloyMainDelegate(CefMainRunnerHandler* runner,
+                    CefSettings* settings,
+                    CefRefPtr<CefApp> application);
+
+  AlloyMainDelegate(const AlloyMainDelegate&) = delete;
+  AlloyMainDelegate& operator=(const AlloyMainDelegate&) = delete;
+
+  ~AlloyMainDelegate() override;
+
+  // content::ContentMainDelegate overrides.
+  absl::optional<int> PreBrowserMain() override;
+  absl::optional<int> BasicStartupComplete() override;
+  void PreSandboxStartup() override;
+  absl::variant<int, content::MainFunctionParams> RunProcess(
+      const std::string& process_type,
+      content::MainFunctionParams main_function_params) override;
+  void ProcessExiting(const std::string& process_type) override;
+#if BUILDFLAG(IS_LINUX)
+  void ZygoteForked() override;
+#endif
+  content::ContentBrowserClient* CreateContentBrowserClient() override;
+  content::ContentRendererClient* CreateContentRendererClient() override;
+  content::ContentUtilityClient* CreateContentUtilityClient() override;
+
+ protected:
+  // CefAppManager overrides.
+  CefRefPtr<CefApp> GetApplication() override { return application_; }
+  content::ContentClient* GetContentClient() override {
+    return &content_client_;
+  }
+  CefRefPtr<CefRequestContext> GetGlobalRequestContext() override;
+  CefBrowserContext* CreateNewBrowserContext(
+      const CefRequestContextSettings& settings,
+      base::OnceClosure initialized_cb) override;
+
+  // CefTaskRunnerManager overrides.
+  scoped_refptr<base::SingleThreadTaskRunner> GetBackgroundTaskRunner()
+      override;
+  scoped_refptr<base::SingleThreadTaskRunner> GetUserVisibleTaskRunner()
+      override;
+  scoped_refptr<base::SingleThreadTaskRunner> GetUserBlockingTaskRunner()
+      override;
+  scoped_refptr<base::SingleThreadTaskRunner> GetRenderTaskRunner() override;
+  scoped_refptr<base::SingleThreadTaskRunner> GetWebWorkerTaskRunner() override;
+
+ private:
+  void InitializeResourceBundle();
+
+  CefMainRunnerHandler* const runner_;
+  CefSettings* const settings_;
+  CefRefPtr<CefApp> application_;
+
+  std::unique_ptr<AlloyContentBrowserClient> browser_client_;
+  std::unique_ptr<AlloyContentRendererClient> renderer_client_;
+  std::unique_ptr<ChromeContentUtilityClient> utility_client_;
+  AlloyContentClient content_client_;
+
+  CefResourceBundleDelegate resource_bundle_delegate_;
+
+#if BUILDFLAG(IS_WIN)
+  // TODO: Add support for windows spellcheck service (see issue #3055).
+  spellcheck::ScopedDisableBrowserSpellCheckerForTesting
+      disable_browser_spellchecker_;
+#endif
+};
+
+#endif  // CEF_LIBCEF_COMMON_ALLOY_ALLOY_MAIN_DELEGATE_H_
diff --git a/src/libcef/common/alloy/alloy_main_runner_delegate.cc b/src/libcef/common/alloy/alloy_main_runner_delegate.cc
new file mode 100644
index 0000000..883a2ea
--- /dev/null
+++ b/src/libcef/common/alloy/alloy_main_runner_delegate.cc
@@ -0,0 +1,64 @@
+// Copyright 2020 The Chromium Embedded Framework Authors.
+// Portions copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/common/alloy/alloy_main_runner_delegate.h"
+
+#include "libcef/browser/alloy/chrome_browser_process_alloy.h"
+#include "libcef/common/alloy/alloy_main_delegate.h"
+#include "libcef/renderer/alloy/alloy_content_renderer_client.h"
+
+#include "content/public/browser/render_process_host.h"
+#include "ui/base/resource/resource_bundle.h"
+
+AlloyMainRunnerDelegate::AlloyMainRunnerDelegate(CefMainRunnerHandler* runner,
+                                                 CefSettings* settings,
+                                                 CefRefPtr<CefApp> application)
+    : runner_(runner), settings_(settings), application_(application) {}
+AlloyMainRunnerDelegate::~AlloyMainRunnerDelegate() = default;
+
+content::ContentMainDelegate*
+AlloyMainRunnerDelegate::GetContentMainDelegate() {
+  if (!main_delegate_) {
+    main_delegate_ =
+        std::make_unique<AlloyMainDelegate>(runner_, settings_, application_);
+  }
+  return main_delegate_.get();
+}
+
+void AlloyMainRunnerDelegate::BeforeMainThreadInitialize(
+    const CefMainArgs& args) {
+  g_browser_process = new ChromeBrowserProcessAlloy();
+}
+
+void AlloyMainRunnerDelegate::BeforeMainThreadRun(
+    bool multi_threaded_message_loop) {
+  static_cast<ChromeBrowserProcessAlloy*>(g_browser_process)->Initialize();
+}
+
+void AlloyMainRunnerDelegate::AfterUIThreadInitialize() {
+  static_cast<ChromeBrowserProcessAlloy*>(g_browser_process)
+      ->OnContextInitialized();
+}
+
+void AlloyMainRunnerDelegate::AfterUIThreadShutdown() {
+  static_cast<ChromeBrowserProcessAlloy*>(g_browser_process)
+      ->CleanupOnUIThread();
+
+  ui::ResourceBundle::GetSharedInstance().CleanupOnUIThread();
+}
+
+void AlloyMainRunnerDelegate::BeforeMainThreadShutdown() {
+  if (content::RenderProcessHost::run_renderer_in_process()) {
+    // Blocks until RenderProcess cleanup is complete.
+    AlloyContentRendererClient::Get()->RunSingleProcessCleanup();
+  }
+}
+
+void AlloyMainRunnerDelegate::AfterMainThreadShutdown() {
+  if (g_browser_process) {
+    delete g_browser_process;
+    g_browser_process = nullptr;
+  }
+}
diff --git a/src/libcef/common/alloy/alloy_main_runner_delegate.h b/src/libcef/common/alloy/alloy_main_runner_delegate.h
new file mode 100644
index 0000000..a256f96
--- /dev/null
+++ b/src/libcef/common/alloy/alloy_main_runner_delegate.h
@@ -0,0 +1,48 @@
+// Copyright 2020 The Chromium Embedded Framework Authors.
+// Portions copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_COMMON_ALLOY_ALLOY_MAIN_RUNNER_DELEGATE_
+#define CEF_LIBCEF_COMMON_ALLOY_ALLOY_MAIN_RUNNER_DELEGATE_
+
+#include <memory>
+
+#include "include/cef_base.h"
+#include "libcef/common/main_runner_delegate.h"
+#include "libcef/common/main_runner_handler.h"
+
+class AlloyMainDelegate;
+
+class AlloyMainRunnerDelegate : public CefMainRunnerDelegate {
+ public:
+  // |runner| and |settings| will be non-nullptr for the main process only, and
+  // will outlive this object.
+  AlloyMainRunnerDelegate(CefMainRunnerHandler* runner,
+                          CefSettings* settings,
+                          CefRefPtr<CefApp> application);
+
+  AlloyMainRunnerDelegate(const AlloyMainRunnerDelegate&) = delete;
+  AlloyMainRunnerDelegate& operator=(const AlloyMainRunnerDelegate&) = delete;
+
+  ~AlloyMainRunnerDelegate() override;
+
+ protected:
+  // CefMainRunnerDelegate overrides.
+  content::ContentMainDelegate* GetContentMainDelegate() override;
+  void BeforeMainThreadInitialize(const CefMainArgs& args) override;
+  void BeforeMainThreadRun(bool multi_threaded_message_loop) override;
+  void AfterUIThreadInitialize() override;
+  void AfterUIThreadShutdown() override;
+  void BeforeMainThreadShutdown() override;
+  void AfterMainThreadShutdown() override;
+
+ private:
+  std::unique_ptr<AlloyMainDelegate> main_delegate_;
+
+  CefMainRunnerHandler* const runner_;
+  CefSettings* const settings_;
+  CefRefPtr<CefApp> application_;
+};
+
+#endif  // CEF_LIBCEF_COMMON_ALLOY_ALLOY_MAIN_RUNNER_DELEGATE_
diff --git a/src/libcef/common/app_manager.cc b/src/libcef/common/app_manager.cc
new file mode 100644
index 0000000..167393a
--- /dev/null
+++ b/src/libcef/common/app_manager.cc
@@ -0,0 +1,112 @@
+// Copyright 2020 The Chromium Embedded Framework 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 "libcef/common/app_manager.h"
+
+#include "libcef/common/net/scheme_info.h"
+#include "libcef/common/net/scheme_registration.h"
+#include "libcef/common/scheme_registrar_impl.h"
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "content/public/browser/child_process_security_policy.h"
+#include "content/public/common/content_switches.h"
+
+#if BUILDFLAG(IS_WIN)
+#include <windows.h>
+#include "base/path_service.h"
+#endif
+
+namespace {
+
+CefAppManager* g_manager = nullptr;
+
+}  // namespace
+
+// static
+CefAppManager* CefAppManager::Get() {
+  return g_manager;
+}
+
+CefAppManager::CefAppManager() {
+  // Only a single instance should exist.
+  DCHECK(!g_manager);
+  g_manager = this;
+}
+
+CefAppManager::~CefAppManager() {
+  g_manager = nullptr;
+}
+
+void CefAppManager::AddCustomScheme(CefSchemeInfo* scheme_info) {
+  DCHECK(!scheme_info_list_locked_);
+  scheme_info_list_.push_back(*scheme_info);
+
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  if (!command_line->HasSwitch(switches::kProcessType)) {
+    // Register as a Web-safe scheme in the browser process so that requests for
+    // the scheme from a render process will be allowed in
+    // resource_dispatcher_host_impl.cc ShouldServiceRequest.
+    content::ChildProcessSecurityPolicy* policy =
+        content::ChildProcessSecurityPolicy::GetInstance();
+    if (!policy->IsWebSafeScheme(scheme_info->scheme_name)) {
+      policy->RegisterWebSafeScheme(scheme_info->scheme_name);
+    }
+  }
+}
+
+bool CefAppManager::HasCustomScheme(const std::string& scheme_name) {
+  DCHECK(scheme_info_list_locked_);
+  if (scheme_info_list_.empty()) {
+    return false;
+  }
+
+  SchemeInfoList::const_iterator it = scheme_info_list_.begin();
+  for (; it != scheme_info_list_.end(); ++it) {
+    if (it->scheme_name == scheme_name) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+const CefAppManager::SchemeInfoList* CefAppManager::GetCustomSchemes() {
+  DCHECK(scheme_info_list_locked_);
+  return &scheme_info_list_;
+}
+
+void CefAppManager::AddAdditionalSchemes(
+    content::ContentClient::Schemes* schemes) {
+  DCHECK(!scheme_info_list_locked_);
+
+  auto application = GetApplication();
+  if (application) {
+    CefSchemeRegistrarImpl schemeRegistrar;
+    application->OnRegisterCustomSchemes(&schemeRegistrar);
+    schemeRegistrar.GetSchemes(schemes);
+  }
+
+  scheme::AddInternalSchemes(schemes);
+
+  scheme_info_list_locked_ = true;
+}
+
+#if BUILDFLAG(IS_WIN)
+const wchar_t* CefAppManager::GetResourceDllName() {
+  static wchar_t file_path[MAX_PATH + 1] = {0};
+
+  if (file_path[0] == 0) {
+    // Retrieve the module path (usually libcef.dll).
+    base::FilePath module;
+    base::PathService::Get(base::FILE_MODULE, &module);
+    const std::wstring wstr = module.value();
+    size_t count = std::min(static_cast<size_t>(MAX_PATH), wstr.size());
+    wcsncpy(file_path, wstr.c_str(), count);
+    file_path[count] = 0;
+  }
+
+  return file_path;
+}
+#endif  // BUILDFLAG(IS_WIN)
diff --git a/src/libcef/common/app_manager.h b/src/libcef/common/app_manager.h
new file mode 100644
index 0000000..94ea967
--- /dev/null
+++ b/src/libcef/common/app_manager.h
@@ -0,0 +1,72 @@
+// Copyright 2020 The Chromium Embedded Framework 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 CEF_LIBCEF_COMMON_APP_MANAGER_H_
+#define CEF_LIBCEF_COMMON_APP_MANAGER_H_
+#pragma once
+
+#include <list>
+
+#include "include/cef_app.h"
+#include "include/cef_request_context.h"
+
+#include "base/functional/callback.h"
+#include "build/build_config.h"
+#include "content/public/common/content_client.h"
+
+class CefBrowserContext;
+struct CefSchemeInfo;
+
+// Exposes global application state in the main and render processes.
+class CefAppManager {
+ public:
+  CefAppManager(const CefAppManager&) = delete;
+  CefAppManager& operator=(const CefAppManager&) = delete;
+
+  // Returns the singleton instance that is scoped to CEF lifespan.
+  static CefAppManager* Get();
+
+  // The following methods are available in both processes.
+
+  virtual CefRefPtr<CefApp> GetApplication() = 0;
+  virtual content::ContentClient* GetContentClient() = 0;
+
+  // Custom scheme information will be registered first with all processes
+  // (url/url_util.h) via ContentClient::AddAdditionalSchemes which calls
+  // AddCustomScheme, and second with Blink (SchemeRegistry) via
+  // ContentRendererClient::WebKitInitialized which calls GetCustomSchemes.
+  void AddCustomScheme(CefSchemeInfo* scheme_info);
+  bool HasCustomScheme(const std::string& scheme_name);
+
+  using SchemeInfoList = std::list<CefSchemeInfo>;
+  const SchemeInfoList* GetCustomSchemes();
+
+  // Called from ContentClient::AddAdditionalSchemes.
+  void AddAdditionalSchemes(content::ContentClient::Schemes* schemes);
+
+  // The following methods are only available in the main (browser) process.
+
+  // Called from CefRequestContextImpl. |initialized_cb| may be executed
+  // synchronously or asynchronously.
+  virtual CefRefPtr<CefRequestContext> GetGlobalRequestContext() = 0;
+  virtual CefBrowserContext* CreateNewBrowserContext(
+      const CefRequestContextSettings& settings,
+      base::OnceClosure initialized_cb) = 0;
+
+#if BUILDFLAG(IS_WIN)
+  // Returns the module name (usually libcef.dll).
+  const wchar_t* GetResourceDllName();
+#endif
+
+ protected:
+  CefAppManager();
+  virtual ~CefAppManager();
+
+ private:
+  // Custom schemes handled by the client.
+  SchemeInfoList scheme_info_list_;
+  bool scheme_info_list_locked_ = false;
+};
+
+#endif  // CEF_LIBCEF_COMMON_APP_MANAGER_H_
diff --git a/src/libcef/common/base_impl.cc b/src/libcef/common/base_impl.cc
index 07ec5d7..9a4333e 100644
--- a/src/libcef/common/base_impl.cc
+++ b/src/libcef/common/base_impl.cc
@@ -12,311 +12,193 @@
 #include "base/threading/platform_thread.h"
 #include "base/trace_event/trace_event.h"
 
-#if defined(OS_WIN)
-#include "base/win/win_util.h"
-#endif
-
 namespace {
 
 constexpr const char kCategory[] = "cef.client";
 
 }  // namespace
 
-// The contents of this file are a compilation unit that is not called by other
-// functions in the the library. Consiquently MSVS will exclude it during the
-// linker stage if we don't call a stub function.
-#if defined(COMPILER_MSVC)
-#pragma optimize("", off)
-#endif
-
-void base_impl_stub() {}
-
-#if defined(COMPILER_MSVC)
-#pragma optimize("", on)
-#endif
-
 CEF_EXPORT void cef_trace_event_instant(const char* /* category */,
                                         const char* name,
                                         const char* arg1_name,
-                                        uint64 arg1_val,
+                                        uint64_t arg1_val,
                                         const char* arg2_name,
-                                        uint64 arg2_val,
-                                        int copy) {
+                                        uint64_t arg2_val) {
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
 
-  if (copy) {
-    if (arg1_name == nullptr && arg2_name == nullptr) {
-      TRACE_EVENT_COPY_INSTANT0(kCategory, name, TRACE_EVENT_SCOPE_THREAD);
-    } else if (arg2_name == nullptr) {
-      TRACE_EVENT_COPY_INSTANT1(kCategory, name, TRACE_EVENT_SCOPE_THREAD,
-                                arg1_name, arg1_val);
-    } else {
-      TRACE_EVENT_COPY_INSTANT2(kCategory, name, TRACE_EVENT_SCOPE_THREAD,
-                                arg1_name, arg1_val, arg2_name, arg2_val);
-    }
+  if (arg1_name == nullptr && arg2_name == nullptr) {
+    TRACE_EVENT_INSTANT0(kCategory, name, TRACE_EVENT_SCOPE_THREAD);
+  } else if (arg2_name == nullptr) {
+    TRACE_EVENT_INSTANT1(kCategory, name, TRACE_EVENT_SCOPE_THREAD, arg1_name,
+                         arg1_val);
   } else {
-    if (arg1_name == nullptr && arg2_name == nullptr) {
-      TRACE_EVENT_INSTANT0(kCategory, name, TRACE_EVENT_SCOPE_THREAD);
-    } else if (arg2_name == nullptr) {
-      TRACE_EVENT_INSTANT1(kCategory, name, TRACE_EVENT_SCOPE_THREAD, arg1_name,
-                           arg1_val);
-    } else {
-      TRACE_EVENT_INSTANT2(kCategory, name, TRACE_EVENT_SCOPE_THREAD, arg1_name,
-                           arg1_val, arg2_name, arg2_val);
-    }
+    TRACE_EVENT_INSTANT2(kCategory, name, TRACE_EVENT_SCOPE_THREAD, arg1_name,
+                         arg1_val, arg2_name, arg2_val);
   }
 }
 
 CEF_EXPORT void cef_trace_event_begin(const char* /* category */,
                                       const char* name,
                                       const char* arg1_name,
-                                      uint64 arg1_val,
+                                      uint64_t arg1_val,
                                       const char* arg2_name,
-                                      uint64 arg2_val,
-                                      int copy) {
+                                      uint64_t arg2_val) {
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
 
-  if (copy) {
-    if (arg1_name == nullptr && arg2_name == nullptr) {
-      TRACE_EVENT_BEGIN_WITH_FLAGS0(kCategory, name, TRACE_EVENT_FLAG_COPY);
-    } else if (arg2_name == nullptr) {
-      TRACE_EVENT_BEGIN_WITH_FLAGS1(kCategory, name, TRACE_EVENT_FLAG_COPY,
-                                    arg1_name, arg1_val);
-    } else {
-      TRACE_EVENT_COPY_BEGIN2(kCategory, name, arg1_name, arg1_val, arg2_name,
-                              arg2_val);
-    }
+  if (arg1_name == nullptr && arg2_name == nullptr) {
+    TRACE_EVENT_BEGIN0(kCategory, name);
+  } else if (arg2_name == nullptr) {
+    TRACE_EVENT_BEGIN1(kCategory, name, arg1_name, arg1_val);
   } else {
-    if (arg1_name == nullptr && arg2_name == nullptr) {
-      TRACE_EVENT_BEGIN0(kCategory, name);
-    } else if (arg2_name == nullptr) {
-      TRACE_EVENT_BEGIN1(kCategory, name, arg1_name, arg1_val);
-    } else {
-      TRACE_EVENT_BEGIN2(kCategory, name, arg1_name, arg1_val, arg2_name,
-                         arg2_val);
-    }
+    TRACE_EVENT_BEGIN2(kCategory, name, arg1_name, arg1_val, arg2_name,
+                       arg2_val);
   }
 }
 
 CEF_EXPORT void cef_trace_event_end(const char* /* category */,
                                     const char* name,
                                     const char* arg1_name,
-                                    uint64 arg1_val,
+                                    uint64_t arg1_val,
                                     const char* arg2_name,
-                                    uint64 arg2_val,
-                                    int copy) {
+                                    uint64_t arg2_val) {
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
 
-  if (copy) {
-    if (arg1_name == nullptr && arg2_name == nullptr) {
-      TRACE_EVENT_END_WITH_FLAGS0(kCategory, name, TRACE_EVENT_FLAG_COPY);
-    } else if (arg2_name == nullptr) {
-      TRACE_EVENT_END_WITH_FLAGS1(kCategory, name, TRACE_EVENT_FLAG_COPY,
-                                  arg1_name, arg1_val);
-    } else {
-      TRACE_EVENT_COPY_END2(kCategory, name, arg1_name, arg1_val, arg2_name,
-                            arg2_val);
-    }
+  if (arg1_name == nullptr && arg2_name == nullptr) {
+    TRACE_EVENT_END0(kCategory, name);
+  } else if (arg2_name == nullptr) {
+    TRACE_EVENT_END1(kCategory, name, arg1_name, arg1_val);
   } else {
-    if (arg1_name == nullptr && arg2_name == nullptr) {
-      TRACE_EVENT_END0(kCategory, name);
-    } else if (arg2_name == nullptr) {
-      TRACE_EVENT_END1(kCategory, name, arg1_name, arg1_val);
-    } else {
-      TRACE_EVENT_END2(kCategory, name, arg1_name, arg1_val, arg2_name,
-                       arg2_val);
-    }
+    TRACE_EVENT_END2(kCategory, name, arg1_name, arg1_val, arg2_name, arg2_val);
   }
 }
 
 CEF_EXPORT void cef_trace_counter(const char* /* category */,
                                   const char* name,
                                   const char* value1_name,
-                                  uint64 value1_val,
+                                  uint64_t value1_val,
                                   const char* value2_name,
-                                  uint64 value2_val,
-                                  int copy) {
+                                  uint64_t value2_val) {
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
 
-  if (copy) {
-    if (value1_name == nullptr && value2_name == nullptr) {
-      TRACE_COPY_COUNTER1(kCategory, name, value1_val);
-    } else {
-      TRACE_COPY_COUNTER2(kCategory, name, value1_name, value1_val, value2_name,
-                          value2_val);
-    }
+  if (value1_name == nullptr && value2_name == nullptr) {
+    TRACE_COUNTER1(kCategory, name, value1_val);
   } else {
-    if (value1_name == nullptr && value2_name == nullptr) {
-      TRACE_COUNTER1(kCategory, name, value1_val);
-    } else {
-      TRACE_COUNTER2(kCategory, name, value1_name, value1_val, value2_name,
-                     value2_val);
-    }
+    TRACE_COUNTER2(kCategory, name, value1_name, value1_val, value2_name,
+                   value2_val);
   }
 }
 
 CEF_EXPORT void cef_trace_counter_id(const char* /* category */,
                                      const char* name,
-                                     uint64 id,
+                                     uint64_t id,
                                      const char* value1_name,
-                                     uint64 value1_val,
+                                     uint64_t value1_val,
                                      const char* value2_name,
-                                     uint64 value2_val,
-                                     int copy) {
+                                     uint64_t value2_val) {
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
 
-  if (copy) {
-    if (value1_name == nullptr && value2_name == nullptr) {
-      TRACE_COPY_COUNTER_ID1(kCategory, name, id, value1_val);
-    } else {
-      TRACE_COPY_COUNTER_ID2(kCategory, name, id, value1_name, value1_val,
-                             value2_name, value2_val);
-    }
+  if (value1_name == nullptr && value2_name == nullptr) {
+    TRACE_COUNTER_ID1(kCategory, name, id, value1_val);
   } else {
-    if (value1_name == nullptr && value2_name == nullptr) {
-      TRACE_COUNTER_ID1(kCategory, name, id, value1_val);
-    } else {
-      TRACE_COUNTER_ID2(kCategory, name, id, value1_name, value1_val,
-                        value2_name, value2_val);
-    }
+    TRACE_COUNTER_ID2(kCategory, name, id, value1_name, value1_val, value2_name,
+                      value2_val);
   }
 }
 
 CEF_EXPORT void cef_trace_event_async_begin(const char* /* category */,
                                             const char* name,
-                                            uint64 id,
+                                            uint64_t id,
                                             const char* arg1_name,
-                                            uint64 arg1_val,
+                                            uint64_t arg1_val,
                                             const char* arg2_name,
-                                            uint64 arg2_val,
-                                            int copy) {
+                                            uint64_t arg2_val) {
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
 
-  if (copy) {
-    if (arg1_name == nullptr && arg2_name == nullptr) {
-      TRACE_EVENT_COPY_ASYNC_BEGIN0(kCategory, name, id);
-    } else if (arg2_name == nullptr) {
-      TRACE_EVENT_COPY_ASYNC_BEGIN1(kCategory, name, id, arg1_name, arg1_val);
-    } else {
-      TRACE_EVENT_COPY_ASYNC_BEGIN2(kCategory, name, id, arg1_name, arg1_val,
-                                    arg2_name, arg2_val);
-    }
+  if (arg1_name == nullptr && arg2_name == nullptr) {
+    TRACE_EVENT_ASYNC_BEGIN0(kCategory, name, id);
+  } else if (arg2_name == nullptr) {
+    TRACE_EVENT_ASYNC_BEGIN1(kCategory, name, id, arg1_name, arg1_val);
   } else {
-    if (arg1_name == nullptr && arg2_name == nullptr) {
-      TRACE_EVENT_ASYNC_BEGIN0(kCategory, name, id);
-    } else if (arg2_name == nullptr) {
-      TRACE_EVENT_ASYNC_BEGIN1(kCategory, name, id, arg1_name, arg1_val);
-    } else {
-      TRACE_EVENT_ASYNC_BEGIN2(kCategory, name, id, arg1_name, arg1_val,
-                               arg2_name, arg2_val);
-    }
+    TRACE_EVENT_ASYNC_BEGIN2(kCategory, name, id, arg1_name, arg1_val,
+                             arg2_name, arg2_val);
   }
 }
 
 CEF_EXPORT void cef_trace_event_async_step_into(const char* /* category */,
                                                 const char* name,
-                                                uint64 id,
-                                                uint64 step,
+                                                uint64_t id,
+                                                uint64_t step,
                                                 const char* arg1_name,
-                                                uint64 arg1_val,
-                                                int copy) {
+                                                uint64_t arg1_val) {
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
 
-  if (copy) {
-    if (arg1_name == nullptr) {
-      INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_INTO,
-                                       kCategory, name, id,
-                                       TRACE_EVENT_FLAG_COPY, "step", step);
-    } else {
-      INTERNAL_TRACE_EVENT_ADD_WITH_ID(
-          TRACE_EVENT_PHASE_ASYNC_STEP_INTO, kCategory, name, id,
-          TRACE_EVENT_FLAG_COPY, "step", step, arg1_name, arg1_val);
-    }
+  if (arg1_name == nullptr) {
+    TRACE_EVENT_ASYNC_STEP_INTO0(kCategory, name, id, step);
   } else {
-    if (arg1_name == nullptr) {
-      TRACE_EVENT_ASYNC_STEP_INTO0(kCategory, name, id, step);
-    } else {
-      TRACE_EVENT_ASYNC_STEP_INTO1(kCategory, name, id, step, arg1_name,
-                                   arg1_val);
-    }
+    TRACE_EVENT_ASYNC_STEP_INTO1(kCategory, name, id, step, arg1_name,
+                                 arg1_val);
   }
 }
 
 CEF_EXPORT void cef_trace_event_async_step_past(const char* /* category */,
                                                 const char* name,
-                                                uint64 id,
-                                                uint64 step,
+                                                uint64_t id,
+                                                uint64_t step,
                                                 const char* arg1_name,
-                                                uint64 arg1_val,
-                                                int copy) {
+                                                uint64_t arg1_val) {
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
 
-  if (copy) {
-    if (arg1_name == nullptr) {
-      INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_PAST,
-                                       kCategory, name, id,
-                                       TRACE_EVENT_FLAG_COPY, "step", step);
-    } else {
-      INTERNAL_TRACE_EVENT_ADD_WITH_ID(
-          TRACE_EVENT_PHASE_ASYNC_STEP_PAST, kCategory, name, id,
-          TRACE_EVENT_FLAG_COPY, "step", step, arg1_name, arg1_val);
-    }
+  if (arg1_name == nullptr) {
+    TRACE_EVENT_ASYNC_STEP_PAST0(kCategory, name, id, step);
   } else {
-    if (arg1_name == nullptr) {
-      TRACE_EVENT_ASYNC_STEP_PAST0(kCategory, name, id, step);
-    } else {
-      TRACE_EVENT_ASYNC_STEP_PAST1(kCategory, name, id, step, arg1_name,
-                                   arg1_val);
-    }
+    TRACE_EVENT_ASYNC_STEP_PAST1(kCategory, name, id, step, arg1_name,
+                                 arg1_val);
   }
 }
 
 CEF_EXPORT void cef_trace_event_async_end(const char* /* category */,
                                           const char* name,
-                                          uint64 id,
+                                          uint64_t id,
                                           const char* arg1_name,
-                                          uint64 arg1_val,
+                                          uint64_t arg1_val,
                                           const char* arg2_name,
-                                          uint64 arg2_val,
-                                          int copy) {
+                                          uint64_t arg2_val) {
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
 
-  if (copy) {
-    if (arg1_name == nullptr && arg2_name == nullptr) {
-      TRACE_EVENT_COPY_ASYNC_END0(kCategory, name, id);
-    } else if (arg2_name == nullptr) {
-      TRACE_EVENT_COPY_ASYNC_END1(kCategory, name, id, arg1_name, arg1_val);
-    } else {
-      TRACE_EVENT_COPY_ASYNC_END2(kCategory, name, id, arg1_name, arg1_val,
-                                  arg2_name, arg2_val);
-    }
+  if (arg1_name == nullptr && arg2_name == nullptr) {
+    TRACE_EVENT_ASYNC_END0(kCategory, name, id);
+  } else if (arg2_name == nullptr) {
+    TRACE_EVENT_ASYNC_END1(kCategory, name, id, arg1_name, arg1_val);
   } else {
-    if (arg1_name == nullptr && arg2_name == nullptr) {
-      TRACE_EVENT_ASYNC_END0(kCategory, name, id);
-    } else if (arg2_name == nullptr) {
-      TRACE_EVENT_ASYNC_END1(kCategory, name, id, arg1_name, arg1_val);
-    } else {
-      TRACE_EVENT_ASYNC_END2(kCategory, name, id, arg1_name, arg1_val,
-                             arg2_name, arg2_val);
-    }
+    TRACE_EVENT_ASYNC_END2(kCategory, name, id, arg1_name, arg1_val, arg2_name,
+                           arg2_val);
   }
 }
 
@@ -341,15 +223,9 @@
 
 CEF_EXPORT cef_platform_thread_handle_t
 cef_get_current_platform_thread_handle() {
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   return base::PlatformThread::CurrentId();
 #else
   return base::PlatformThread::CurrentHandle().platform_handle();
 #endif
 }
-
-void CefEnableHighDPISupport() {
-#if defined(OS_WIN)
-  base::win::EnableHighDPISupport();
-#endif
-}
diff --git a/src/libcef/common/cdm_host_file_path.cc b/src/libcef/common/cdm_host_file_path.cc
new file mode 100644
index 0000000..d76009f
--- /dev/null
+++ b/src/libcef/common/cdm_host_file_path.cc
@@ -0,0 +1,119 @@
+// Copyright 2022 The Chromium Embedded Framework Authors. Portions Copyright
+// 2017 The Chromium Authors. Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "libcef/common/cdm_host_file_path.h"
+
+#include "base/check.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/notreached.h"
+#include "base/path_service.h"
+#include "build/build_config.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_version.h"
+
+#if BUILDFLAG(IS_MAC)
+#include "libcef/common/util_mac.h"
+#endif
+
+namespace cef {
+
+namespace {
+
+// TODO(xhwang): Move this to a common place if needed.
+const base::FilePath::CharType kSignatureFileExtension[] =
+    FILE_PATH_LITERAL(".sig");
+
+// Returns the signature file path given the |file_path|. This function should
+// only be used when the signature file and the file are located in the same
+// directory.
+base::FilePath GetSigFilePath(const base::FilePath& file_path) {
+  return file_path.AddExtension(kSignatureFileExtension);
+}
+
+bool FileExists(const base::FilePath& path) {
+  return base::PathExists(path) && !base::DirectoryExists(path);
+}
+
+}  // namespace
+
+void AddCdmHostFilePaths(
+    std::vector<media::CdmHostFilePath>* cdm_host_file_paths) {
+  DVLOG(1) << __func__;
+  DCHECK(cdm_host_file_paths);
+  DCHECK(cdm_host_file_paths->empty());
+
+#if BUILDFLAG(IS_WIN)
+
+  // Find the full path to the current executable.
+  base::FilePath cef_exe;
+  CHECK(base::PathService::Get(base::FILE_EXE, &cef_exe));
+  const auto cef_exe_sig = GetSigFilePath(cef_exe);
+  DVLOG(2) << __func__ << ": exe_path=" << cef_exe.value()
+           << ", signature_path=" << cef_exe_sig.value();
+
+  if (FileExists(cef_exe_sig)) {
+    cdm_host_file_paths->emplace_back(cef_exe, cef_exe_sig);
+  }
+
+  // Find the full path to the module. This may be the same as the executable if
+  // libcef is statically linked.
+  base::FilePath cef_module;
+  CHECK(base::PathService::Get(base::FILE_MODULE, &cef_module));
+  if (cef_module != cef_exe) {
+    const auto cef_module_sig = GetSigFilePath(cef_module);
+    DVLOG(2) << __func__ << ": module_path=" << cef_module.value()
+             << ", signature_path=" << cef_module_sig.value();
+
+    if (FileExists(cef_module_sig)) {
+      cdm_host_file_paths->emplace_back(cef_module, cef_module_sig);
+    }
+  }
+
+#elif BUILDFLAG(IS_MAC)
+
+  // Find the full path to the current executable.
+  base::FilePath cef_exe;
+  CHECK(base::PathService::Get(base::FILE_EXE, &cef_exe));
+
+  // Find the sig file for the executable in the main Resources directory. This
+  // directory may be empty if we're not bundled.
+  const auto main_resources_path = util_mac::GetMainResourcesDirectory();
+  if (!main_resources_path.empty()) {
+    const auto exe_name = cef_exe.BaseName();
+    const auto exe_sig_path =
+        GetSigFilePath(main_resources_path.Append(exe_name));
+
+    DVLOG(2) << __func__ << ": exe_path=" << cef_exe.value()
+             << ", signature_path=" << exe_sig_path.value();
+
+    if (FileExists(exe_sig_path)) {
+      cdm_host_file_paths->emplace_back(cef_exe, exe_sig_path);
+    }
+  }
+
+  // Find the sig file for the framework in the framework Resources directory.
+  // This directory may be empty if we're not bundled.
+  const auto framework_resources_path =
+      util_mac::GetFrameworkResourcesDirectory();
+  if (!framework_resources_path.empty()) {
+    const auto framework_name = util_mac::GetFrameworkName();
+    const auto framework_path =
+        util_mac::GetFrameworkDirectory().Append(framework_name);
+    const auto framework_sig_path =
+        GetSigFilePath(framework_resources_path.Append(framework_name));
+
+    DVLOG(2) << __func__ << ": framework_path=" << framework_path.value()
+             << ", signature_path=" << framework_sig_path.value();
+
+    if (FileExists(framework_sig_path)) {
+      cdm_host_file_paths->emplace_back(framework_path, framework_sig_path);
+    }
+  }
+
+#endif  // !BUILDFLAG(IS_MAC)
+}
+
+}  // namespace cef
diff --git a/src/libcef/common/cdm_host_file_path.h b/src/libcef/common/cdm_host_file_path.h
new file mode 100644
index 0000000..4a41e69
--- /dev/null
+++ b/src/libcef/common/cdm_host_file_path.h
@@ -0,0 +1,20 @@
+// Copyright 2022 The Chromium Embedded Framework Authors. Portions Copyright
+// 2017 The Chromium Authors. Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_COMMON_CDM_HOST_FILE_PATH_H_
+#define CEF_LIBCEF_COMMON_CDM_HOST_FILE_PATH_H_
+
+#include <vector>
+
+#include "media/cdm/cdm_host_file.h"
+
+namespace cef {
+
+// Gets a list of CDM host file paths and put them in |cdm_host_file_paths|.
+void AddCdmHostFilePaths(
+    std::vector<media::CdmHostFilePath>* cdm_host_file_paths);
+
+}  // namespace cef
+
+#endif  // CEF_LIBCEF_COMMON_CDM_HOST_FILE_PATH_H_
diff --git a/src/libcef/common/cef_crash_report_upload_thread.cc b/src/libcef/common/cef_crash_report_upload_thread.cc
index 1c81feb..1557ada 100644
--- a/src/libcef/common/cef_crash_report_upload_thread.cc
+++ b/src/libcef/common/cef_crash_report_upload_thread.cc
@@ -4,6 +4,7 @@
 
 #include "libcef/common/cef_crash_report_upload_thread.h"
 
+#include "base/notreached.h"
 #include "libcef/common/cef_crash_report_utils.h"
 #include "third_party/crashpad/crashpad/client/settings.h"
 
@@ -13,8 +14,9 @@
     CrashReportDatabase* database,
     const std::string& url,
     const Options& options,
+    ProcessPendingReportsObservationCallback callback,
     int max_uploads)
-    : CrashReportUploadThread(database, url, options),
+    : CrashReportUploadThread(database, url, options, std::move(callback)),
       max_uploads_(max_uploads) {}
 
 CefCrashReportUploadThread::~CefCrashReportUploadThread() {}
@@ -43,8 +45,9 @@
     // Count how many reports have completed in the last 24 hours.
     recent_upload_ct_ = 0;
     for (const CrashReportDatabase::Report& report : reports) {
-      if (report.last_upload_attempt_time > now - kSeconds)
+      if (report.last_upload_attempt_time > now - kSeconds) {
         recent_upload_ct_++;
+      }
     }
   }
 
@@ -57,8 +60,8 @@
   // Always allow upload if it's been explicitly requested by the user.
   if (!report.upload_explicitly_requested) {
     if (!UploadsEnabled()) {
-      // Don’t attempt an upload if there’s no URL or if uploads have been
-      // disabled in the database’s settings.
+      // Don't attempt an upload if there's no URL or if uploads have been
+      // disabled in the database's settings.
       database_->SkipReportUpload(
           report.uuid, Metrics::CrashSkippedReason::kUploadsDisabled);
       return;
@@ -90,14 +93,14 @@
     case CrashReportDatabase::kReportNotFound:
     case CrashReportDatabase::kFileSystemError:
     case CrashReportDatabase::kDatabaseError:
-      // In these cases, SkipReportUpload() might not work either, but it’s best
+      // In these cases, SkipReportUpload() might not work either, but it's best
       // to at least try to get the report out of the way.
       database_->SkipReportUpload(report.uuid,
                                   Metrics::CrashSkippedReason::kDatabaseError);
       return;
 
     case CrashReportDatabase::kCannotRequestUpload:
-      NOTREACHED();
+      DCHECK(false);
       return;
   }
 
@@ -108,8 +111,9 @@
     case UploadResult::kSuccess:
       // The upload completed successfully.
       database_->RecordUploadComplete(std::move(upload_report), response_body);
-      if (MaxUploadsEnabled())
+      if (MaxUploadsEnabled()) {
         recent_upload_ct_++;
+      }
       ResetBackoff();
       break;
     case UploadResult::kPermanentFailure:
@@ -146,8 +150,9 @@
 }
 
 bool CefCrashReportUploadThread::BackoffPending() const {
-  if (!options_.rate_limit)
+  if (!options_.rate_limit) {
     return false;
+  }
 
   Settings* const settings = database_->GetSettings();
 
@@ -155,16 +160,18 @@
   if (settings->GetNextUploadAttemptTime(&next_upload_time) &&
       next_upload_time > 0) {
     const time_t now = time(nullptr);
-    if (now < next_upload_time)
+    if (now < next_upload_time) {
       return true;
+    }
   }
 
   return false;
 }
 
 void CefCrashReportUploadThread::IncreaseBackoff() {
-  if (!options_.rate_limit)
+  if (!options_.rate_limit) {
     return;
+  }
 
   const int kHour = 60 * 60;  // 1 hour
   const int kBackoffSchedule[] = {
@@ -181,10 +188,12 @@
   Settings* settings = database_->GetSettings();
 
   int backoff_step = 0;
-  if (settings->GetBackoffStep(&backoff_step) && backoff_step < 0)
+  if (settings->GetBackoffStep(&backoff_step) && backoff_step < 0) {
     backoff_step = 0;
-  if (++backoff_step > kBackoffScheduleSize)
+  }
+  if (++backoff_step > kBackoffScheduleSize) {
     backoff_step = kBackoffScheduleSize;
+  }
 
   time_t next_upload_time = time(nullptr);  // now
   next_upload_time += kBackoffSchedule[backoff_step - 1];
@@ -201,8 +210,9 @@
 }
 
 void CefCrashReportUploadThread::ResetBackoff() {
-  if (!options_.rate_limit)
+  if (!options_.rate_limit) {
     return;
+  }
 
   Settings* settings = database_->GetSettings();
   settings->SetBackoffStep(0);
diff --git a/src/libcef/common/cef_crash_report_upload_thread.h b/src/libcef/common/cef_crash_report_upload_thread.h
index b3641d6..d0921ac 100644
--- a/src/libcef/common/cef_crash_report_upload_thread.h
+++ b/src/libcef/common/cef_crash_report_upload_thread.h
@@ -12,7 +12,13 @@
   CefCrashReportUploadThread(crashpad::CrashReportDatabase* database,
                              const std::string& url,
                              const Options& options,
+                             ProcessPendingReportsObservationCallback callback,
                              int max_uploads);
+
+  CefCrashReportUploadThread(const CefCrashReportUploadThread&) = delete;
+  CefCrashReportUploadThread& operator=(const CefCrashReportUploadThread&) =
+      delete;
+
   ~CefCrashReportUploadThread();
 
  private:
@@ -36,8 +42,6 @@
   // Only used when RateLimitEnabled() is true. Value is reset each time
   // ProcessPendingReports() is called.
   int recent_upload_ct_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(CefCrashReportUploadThread);
 };
 
 #endif  // CEF_LIBCEF_COMMON_CEF_CRASH_REPORT_UPLOAD_THREAD_H_
diff --git a/src/libcef/common/cef_crash_report_utils.cc b/src/libcef/common/cef_crash_report_utils.cc
index 7242d7b..2980643 100644
--- a/src/libcef/common/cef_crash_report_utils.cc
+++ b/src/libcef/common/cef_crash_report_utils.cc
@@ -17,8 +17,9 @@
   for (size_t i = 0; true; ++i) {
     const std::string& key = "K-" + std::string(1, 'A' + i);
     ParameterMap::iterator it = in_map.find(key);
-    if (it == in_map.end())
+    if (it == in_map.end()) {
       break;
+    }
     key_map += it->second;
     in_map.erase(it);
   }
diff --git a/src/libcef/common/cef_message_generator.cc b/src/libcef/common/cef_message_generator.cc
deleted file mode 100644
index ee49889..0000000
--- a/src/libcef/common/cef_message_generator.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Get basic type definitions.
-#define IPC_MESSAGE_IMPL
-#include "libcef/common/cef_message_generator.h"
-
-// Generate constructors.
-#include "chrome/common/safe_browsing/ipc_protobuf_message_null_macros.h"
-#include "ipc/struct_constructor_macros.h"
-#include "libcef/common/cef_message_generator.h"
-
-// Generate param traits write methods.
-#include "chrome/common/safe_browsing/protobuf_message_write_macros.h"
-#include "ipc/param_traits_write_macros.h"
-namespace IPC {
-#include "libcef/common/cef_message_generator.h"
-}  // namespace IPC
-
-// Generate param traits read methods.
-#include "chrome/common/safe_browsing/protobuf_message_read_macros.h"
-#include "ipc/param_traits_read_macros.h"
-namespace IPC {
-#include "libcef/common/cef_message_generator.h"
-}  // namespace IPC
-
-// Generate param traits log methods.
-#include "chrome/common/safe_browsing/protobuf_message_log_macros.h"
-#include "ipc/param_traits_log_macros.h"
-namespace IPC {
-#include "libcef/common/cef_message_generator.h"
-}  // namespace IPC
diff --git a/src/libcef/common/cef_message_generator.h b/src/libcef/common/cef_message_generator.h
deleted file mode 100644
index 1243611..0000000
--- a/src/libcef/common/cef_message_generator.h
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Multiply-included file, hence no include guard.
-
-#include "libcef/common/cef_messages.h"
diff --git a/src/libcef/common/cef_messages.cc b/src/libcef/common/cef_messages.cc
deleted file mode 100644
index b2ebf63..0000000
--- a/src/libcef/common/cef_messages.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/common/cef_messages.h"
-
-namespace IPC {
-
-// Extracted from chrome/common/automation_messages.cc.
-
-// Only the net::UploadData ParamTraits<> definition needs this definition, so
-// keep this in the implementation file so we can forward declare UploadData in
-// the header.
-template <>
-struct ParamTraits<net::UploadElement> {
-  typedef net::UploadElement param_type;
-  static void Write(base::Pickle* m, const param_type& p) {
-    WriteParam(m, static_cast<int>(p.type()));
-    switch (p.type()) {
-      case net::UploadElement::TYPE_BYTES: {
-        m->WriteData(p.bytes(), static_cast<int>(p.bytes_length()));
-        break;
-      }
-      default: {
-        DCHECK(p.type() == net::UploadElement::TYPE_FILE);
-        WriteParam(m, p.file_path());
-        WriteParam(m, p.file_range_offset());
-        WriteParam(m, p.file_range_length());
-        WriteParam(m, p.expected_file_modification_time());
-        break;
-      }
-    }
-  }
-  static bool Read(const base::Pickle* m,
-                   base::PickleIterator* iter,
-                   param_type* r) {
-    int type;
-    if (!ReadParam(m, iter, &type))
-      return false;
-    switch (type) {
-      case net::UploadElement::TYPE_BYTES: {
-        const char* data;
-        int len;
-        if (!iter->ReadData(&data, &len))
-          return false;
-        r->SetToBytes(data, len);
-        break;
-      }
-      default: {
-        DCHECK(type == net::UploadElement::TYPE_FILE);
-        base::FilePath file_path;
-        uint64_t offset, length;
-        base::Time expected_modification_time;
-        if (!ReadParam(m, iter, &file_path))
-          return false;
-        if (!ReadParam(m, iter, &offset))
-          return false;
-        if (!ReadParam(m, iter, &length))
-          return false;
-        if (!ReadParam(m, iter, &expected_modification_time))
-          return false;
-        r->SetToFilePathRange(file_path, offset, length,
-                              expected_modification_time);
-        break;
-      }
-    }
-    return true;
-  }
-  static void Log(const param_type& p, std::string* l) {
-    l->append("<net::UploadElement>");
-  }
-};
-
-void ParamTraits<scoped_refptr<net::UploadData>>::Write(base::Pickle* m,
-                                                        const param_type& p) {
-  WriteParam(m, p.get() != nullptr);
-  if (p.get()) {
-    WriteParam(m, p->elements());
-    WriteParam(m, p->identifier());
-    WriteParam(m, p->is_chunked());
-    WriteParam(m, p->last_chunk_appended());
-  }
-}
-
-bool ParamTraits<scoped_refptr<net::UploadData>>::Read(
-    const base::Pickle* m,
-    base::PickleIterator* iter,
-    param_type* r) {
-  bool has_object;
-  if (!ReadParam(m, iter, &has_object))
-    return false;
-  if (!has_object)
-    return true;
-  net::UploadData::ElementsVector elements;
-  if (!ReadParam(m, iter, &elements))
-    return false;
-  int64_t identifier;
-  if (!ReadParam(m, iter, &identifier))
-    return false;
-  bool is_chunked = false;
-  if (!ReadParam(m, iter, &is_chunked))
-    return false;
-  bool last_chunk_appended = false;
-  if (!ReadParam(m, iter, &last_chunk_appended))
-    return false;
-  *r = new net::UploadData;
-  (*r)->swap_elements(&elements);
-  (*r)->set_identifier(identifier);
-  (*r)->set_is_chunked(is_chunked);
-  (*r)->set_last_chunk_appended(last_chunk_appended);
-  return true;
-}
-
-void ParamTraits<scoped_refptr<net::UploadData>>::Log(const param_type& p,
-                                                      std::string* l) {
-  l->append("<net::UploadData>");
-}
-
-}  // namespace IPC
diff --git a/src/libcef/common/cef_messages.h b/src/libcef/common/cef_messages.h
deleted file mode 100644
index 6662ba1..0000000
--- a/src/libcef/common/cef_messages.h
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// IPC messages for CEF.
-// Multiply-included message file, hence no include guard.
-
-#include <stdint.h>
-
-#include "libcef/common/net/upload_data.h"
-
-#include "base/memory/shared_memory_mapping.h"
-#include "base/values.h"
-#include "content/public/common/common_param_traits.h"
-#include "content/public/common/referrer.h"
-#include "ipc/ipc_message_macros.h"
-#include "ui/gfx/ipc/gfx_param_traits.h"
-
-// Singly-included section for enums and custom IPC traits.
-#ifndef CEF_LIBCEF_COMMON_CEF_MESSAGES_H_
-#define CEF_LIBCEF_COMMON_CEF_MESSAGES_H_
-
-namespace IPC {
-
-// Extracted from chrome/common/automation_messages.h.
-template <>
-struct ParamTraits<scoped_refptr<net::UploadData>> {
-  typedef scoped_refptr<net::UploadData> param_type;
-  static void Write(base::Pickle* m, const param_type& p);
-  static bool Read(const base::Pickle* m,
-                   base::PickleIterator* iter,
-                   param_type* r);
-  static void Log(const param_type& p, std::string* l);
-};
-
-}  // namespace IPC
-
-#endif  // CEF_LIBCEF_COMMON_CEF_MESSAGES_H_
-
-// TODO(cef): Re-using the message start for extensions may be problematic in
-// the future. It would be better if ipc_message_utils.h contained a value
-// reserved for consumers of the content API.
-// See: http://crbug.com/110911
-#define IPC_MESSAGE_START ExtensionMsgStart
-
-// Common types.
-
-// Parameters structure for a request.
-IPC_STRUCT_BEGIN(Cef_Request_Params)
-  // Unique request id to match requests and responses.
-  IPC_STRUCT_MEMBER(int, request_id)
-
-  // True if the request is user-initiated instead of internal.
-  IPC_STRUCT_MEMBER(bool, user_initiated)
-
-  // True if a response is expected.
-  IPC_STRUCT_MEMBER(bool, expect_response)
-
-  // Message name.
-  IPC_STRUCT_MEMBER(std::string, name)
-
-  // List of message arguments.
-  IPC_STRUCT_MEMBER(base::ListValue, arguments)
-IPC_STRUCT_END()
-
-// Parameters structure for a response.
-IPC_STRUCT_BEGIN(Cef_Response_Params)
-  // Unique request id to match requests and responses.
-  IPC_STRUCT_MEMBER(int, request_id)
-
-  // True if a response ack is expected.
-  IPC_STRUCT_MEMBER(bool, expect_response_ack)
-
-  // True on success.
-  IPC_STRUCT_MEMBER(bool, success)
-
-  // Response or error string depending on the value of |success|.
-  IPC_STRUCT_MEMBER(std::string, response)
-IPC_STRUCT_END()
-
-// Parameters structure for a cross-origin white list entry.
-IPC_STRUCT_BEGIN(Cef_CrossOriginWhiteListEntry_Params)
-  IPC_STRUCT_MEMBER(std::string, source_origin)
-  IPC_STRUCT_MEMBER(std::string, target_protocol)
-  IPC_STRUCT_MEMBER(std::string, target_domain)
-  IPC_STRUCT_MEMBER(bool, allow_target_subdomains)
-IPC_STRUCT_END()
-
-// Parameters structure for a draggable region.
-IPC_STRUCT_BEGIN(Cef_DraggableRegion_Params)
-  IPC_STRUCT_MEMBER(gfx::Rect, bounds)
-  IPC_STRUCT_MEMBER(bool, draggable)
-IPC_STRUCT_END()
-
-// Messages sent from the browser to the renderer.
-
-// Parameters for a resource request.
-IPC_STRUCT_BEGIN(CefMsg_LoadRequest_Params)
-  // The request method: GET, POST, etc.
-  IPC_STRUCT_MEMBER(std::string, method)
-
-  // The requested URL.
-  IPC_STRUCT_MEMBER(GURL, url)
-
-  // The URL to send in the "Referer" header field. Can be empty if there is
-  // no referrer.
-  IPC_STRUCT_MEMBER(GURL, referrer)
-  // One of the cef_referrer_policy_t values.
-  IPC_STRUCT_MEMBER(int, referrer_policy)
-
-  // Usually the URL of the document in the top-level window, which may be
-  // checked by the third-party cookie blocking policy. Leaving it empty may
-  // lead to undesired cookie blocking. Third-party cookie blocking can be
-  // bypassed by setting site_for_cookies = url, but this should ideally
-  // only be done if there really is no way to determine the correct value.
-  IPC_STRUCT_MEMBER(net::SiteForCookies, site_for_cookies)
-
-  // Additional HTTP request headers.
-  IPC_STRUCT_MEMBER(std::string, headers)
-
-  // net::URLRequest load flags (0 by default).
-  IPC_STRUCT_MEMBER(int, load_flags)
-
-  // Optional upload data (may be null).
-  IPC_STRUCT_MEMBER(scoped_refptr<net::UploadData>, upload_data)
-IPC_STRUCT_END()
-
-// Tell the renderer to load a request.
-IPC_MESSAGE_ROUTED1(CefMsg_LoadRequest, CefMsg_LoadRequest_Params)
-
-// Sent when the browser has a request for the renderer. The renderer may
-// respond with a CefHostMsg_Response.
-IPC_MESSAGE_ROUTED1(CefMsg_Request, Cef_Request_Params)
-
-// Optional message sent in response to a CefHostMsg_Request.
-IPC_MESSAGE_ROUTED1(CefMsg_Response, Cef_Response_Params)
-
-// Optional Ack message sent to the browser to notify that a CefHostMsg_Response
-// has been processed.
-IPC_MESSAGE_ROUTED1(CefMsg_ResponseAck, int /* request_id */)
-
-// Tells the renderer that loading has stopped.
-IPC_MESSAGE_ROUTED0(CefMsg_DidStopLoading)
-
-// Tells the render frame to load all blocked plugins with the given identifier.
-// Based on ChromeViewMsg_LoadBlockedPlugins.
-IPC_MESSAGE_ROUTED1(CefViewMsg_LoadBlockedPlugins, std::string /* identifier */)
-
-// Sent to child processes to add or remove a cross-origin whitelist entry.
-IPC_MESSAGE_CONTROL2(CefProcessMsg_ModifyCrossOriginWhitelistEntry,
-                     bool /* add */,
-                     Cef_CrossOriginWhiteListEntry_Params /* params */)
-
-// Sent to child processes to clear the cross-origin whitelist.
-IPC_MESSAGE_CONTROL0(CefProcessMsg_ClearCrossOriginWhitelist)
-
-// Messages sent from the renderer to the browser.
-
-// Parameters for a newly created render thread.
-IPC_STRUCT_BEGIN(CefProcessHostMsg_GetNewRenderThreadInfo_Params)
-  IPC_STRUCT_MEMBER(std::vector<Cef_CrossOriginWhiteListEntry_Params>,
-                    cross_origin_whitelist_entries)
-
-  IPC_STRUCT_MEMBER(base::ListValue, extra_info)
-IPC_STRUCT_END()
-
-// Retrieve information about a newly created render thread.
-IPC_SYNC_MESSAGE_CONTROL0_1(
-    CefProcessHostMsg_GetNewRenderThreadInfo,
-    CefProcessHostMsg_GetNewRenderThreadInfo_Params /* params*/)
-
-// Parameters for a newly created browser window.
-IPC_STRUCT_BEGIN(CefProcessHostMsg_GetNewBrowserInfo_Params)
-  IPC_STRUCT_MEMBER(int, browser_id)
-  IPC_STRUCT_MEMBER(bool, is_popup)
-  IPC_STRUCT_MEMBER(bool, is_windowless)
-  IPC_STRUCT_MEMBER(bool, is_guest_view)
-  IPC_STRUCT_MEMBER(base::DictionaryValue, extra_info)
-IPC_STRUCT_END()
-
-// Retrieve information about a newly created browser.
-IPC_SYNC_MESSAGE_CONTROL1_1(
-    CefProcessHostMsg_GetNewBrowserInfo,
-    int /* render_frame_routing_id */,
-    CefProcessHostMsg_GetNewBrowserInfo_Params /* params*/)
-
-// Sent by the renderer when the frame can begin receiving messages.
-IPC_MESSAGE_ROUTED0(CefHostMsg_FrameAttached)
-
-// Sent when a frame has finished loading. Based on ViewHostMsg_DidFinishLoad.
-IPC_MESSAGE_ROUTED2(CefHostMsg_DidFinishLoad,
-                    GURL /* validated_url */,
-                    int /* http_status_code */)
-
-// Sent when the renderer has a request for the browser. The browser may respond
-// with a CefMsg_Response.
-IPC_MESSAGE_ROUTED1(CefHostMsg_Request, Cef_Request_Params)
-
-// Optional message sent in response to a CefMsg_Request.
-IPC_MESSAGE_ROUTED1(CefHostMsg_Response, Cef_Response_Params)
-
-// Optional Ack message sent to the browser to notify that a CefMsg_Response
-// has been processed.
-IPC_MESSAGE_ROUTED1(CefHostMsg_ResponseAck, int /* request_id */)
-
-// Sent by the renderer when the draggable regions are updated.
-IPC_MESSAGE_ROUTED1(CefHostMsg_UpdateDraggableRegions,
-                    std::vector<Cef_DraggableRegion_Params> /* regions */)
diff --git a/src/libcef/common/cef_switches.cc b/src/libcef/common/cef_switches.cc
index 1e56b3c..b1c5a97 100644
--- a/src/libcef/common/cef_switches.cc
+++ b/src/libcef/common/cef_switches.cc
@@ -15,6 +15,14 @@
 const char kLogSeverity_Fatal[] = "fatal";
 const char kLogSeverity_Disable[] = "disable";
 
+// Customization of items automatically prepended to log lines.
+const char kLogItems[] = "log-items";
+const char kLogItems_None[] = "none";
+const char kLogItems_PId[] = "pid";
+const char kLogItems_TId[] = "tid";
+const char kLogItems_TimeStamp[] = "timestamp";
+const char kLogItems_TickCount[] = "tickcount";
+
 // Path to resources directory.
 const char kResourcesDirPath[] = "resources-dir-path";
 
@@ -61,9 +69,6 @@
 // Disable using the tab key to advance focus to links.
 const char kDisableTabToLinks[] = "disable-tab-to-links";
 
-// Disable plugins.
-const char kDisablePlugins[] = "disable-plugins";
-
 // Persist session cookies.
 const char kPersistSessionCookies[] = "persist-session-cookies";
 
@@ -88,31 +93,12 @@
 // Override the default spellchecking language which comes from locales.pak.
 const char kOverrideSpellCheckLang[] = "override-spell-check-lang";
 
-// Enable detection and use of a system-wide Pepper Flash install.
-const char kEnableSystemFlash[] = "enable-system-flash";
-
 // Disable scroll bounce (rubber-banding) on OS X Lion and newer.
 const char kDisableScrollBounce[] = "disable-scroll-bounce";
 
 // Disable the PDF extension.
 const char kDisablePdfExtension[] = "disable-pdf-extension";
 
-// Path to Widevine CDM binaries.
-const char kWidevineCdmPath[] = "widevine-cdm-path";
-
-// Default plugin policy action.
-const char kPluginPolicy[] = "plugin-policy";
-// Allow the content. This is the default value.
-const char kPluginPolicy_Allow[] = "allow";
-// Allow important content and block unimportant content based on heuristics.
-// The user can manually load blocked content.
-const char kPluginPolicy_Detect[] = "detect";
-// Block the content. The user can manually load blocked content.
-const char kPluginPolicy_Block[] = "block";
-
-// Expose preferences used only by unit tests.
-const char kEnablePreferenceTesting[] = "enable-preference-testing";
-
 // Enable print preview.
 const char kEnablePrintPreview[] = "enable-print-preview";
 
@@ -122,7 +108,22 @@
 // File used for logging DevTools protocol messages.
 const char kDevToolsProtocolLogFile[] = "devtools-protocol-log-file";
 
-#if defined(OS_MACOSX)
+// Enable use of the Chrome runtime in CEF. See issue #2969 for details.
+const char kEnableChromeRuntime[] = "enable-chrome-runtime";
+
+// Delegate all login requests to the client GetAuthCredentials callback when
+// using the Chrome runtime.
+const char kDisableChromeLoginPrompt[] = "disable-chrome-login-prompt";
+
+// Override the product component of the default User-Agent string.
+const char kUserAgentProductAndVersion[] = "user-agent-product";
+
+// Disable request handling in CEF to faciliate debugging of network-related
+// issues.
+const char kDisableRequestHandlingForTesting[] =
+    "disable-request-handling-for-testing";
+
+#if BUILDFLAG(IS_MAC)
 // Path to the framework directory.
 const char kFrameworkDirPath[] = "framework-dir-path";
 const char kMainBundlePath[] = "main-bundle-path";
diff --git a/src/libcef/common/cef_switches.h b/src/libcef/common/cef_switches.h
index 2731f77..ecc1a1b 100644
--- a/src/libcef/common/cef_switches.h
+++ b/src/libcef/common/cef_switches.h
@@ -19,6 +19,12 @@
 extern const char kLogSeverity_Error[];
 extern const char kLogSeverity_Fatal[];
 extern const char kLogSeverity_Disable[];
+extern const char kLogItems[];
+extern const char kLogItems_None[];
+extern const char kLogItems_PId[];
+extern const char kLogItems_TId[];
+extern const char kLogItems_TimeStamp[];
+extern const char kLogItems_TickCount[];
 extern const char kResourcesDirPath[];
 extern const char kLocalesDirPath[];
 extern const char kDisablePackLoading[];
@@ -33,7 +39,6 @@
 extern const char kImageShrinkStandaloneToFit[];
 extern const char kDisableTextAreaResize[];
 extern const char kDisableTabToLinks[];
-extern const char kDisablePlugins[];
 extern const char kPersistSessionCookies[];
 extern const char kPersistUserPreferences[];
 extern const char kEnableMediaStream[];
@@ -42,20 +47,17 @@
 extern const char kDisableSpellChecking[];
 extern const char kEnableSpellingService[];
 extern const char kOverrideSpellCheckLang[];
-extern const char kEnableSystemFlash[];
 extern const char kDisableScrollBounce[];
 extern const char kDisablePdfExtension[];
-extern const char kWidevineCdmPath[];
-extern const char kPluginPolicy[];
-extern const char kPluginPolicy_Allow[];
-extern const char kPluginPolicy_Detect[];
-extern const char kPluginPolicy_Block[];
-extern const char kEnablePreferenceTesting[];
 extern const char kEnablePrintPreview[];
 extern const char kDisableNewBrowserInfoTimeout[];
 extern const char kDevToolsProtocolLogFile[];
+extern const char kEnableChromeRuntime[];
+extern const char kDisableChromeLoginPrompt[];
+extern const char kUserAgentProductAndVersion[];
+extern const char kDisableRequestHandlingForTesting[];
 
-#if defined(OS_MACOSX)
+#if BUILDFLAG(IS_MAC)
 extern const char kFrameworkDirPath[];
 extern const char kMainBundlePath[];
 #endif
diff --git a/src/libcef/common/chrome/chrome_content_client_cef.cc b/src/libcef/common/chrome/chrome_content_client_cef.cc
new file mode 100644
index 0000000..e64a6c3
--- /dev/null
+++ b/src/libcef/common/chrome/chrome_content_client_cef.cc
@@ -0,0 +1,36 @@
+// Copyright 2015 The Chromium Embedded Framework Authors.
+// Portions copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/common/chrome/chrome_content_client_cef.h"
+
+#include "libcef/common/app_manager.h"
+
+#include "chrome/common/media/cdm_registration.h"
+
+#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
+#include "libcef/common/cdm_host_file_path.h"
+#endif
+
+ChromeContentClientCef::ChromeContentClientCef() = default;
+ChromeContentClientCef::~ChromeContentClientCef() = default;
+
+void ChromeContentClientCef::AddContentDecryptionModules(
+    std::vector<content::CdmInfo>* cdms,
+    std::vector<media::CdmHostFilePath>* cdm_host_file_paths) {
+  if (cdms) {
+    RegisterCdmInfo(cdms);
+  }
+
+#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
+  if (cdm_host_file_paths) {
+    cef::AddCdmHostFilePaths(cdm_host_file_paths);
+  }
+#endif
+}
+
+void ChromeContentClientCef::AddAdditionalSchemes(Schemes* schemes) {
+  ChromeContentClient::AddAdditionalSchemes(schemes);
+  CefAppManager::Get()->AddAdditionalSchemes(schemes);
+}
diff --git a/src/libcef/common/chrome/chrome_content_client_cef.h b/src/libcef/common/chrome/chrome_content_client_cef.h
new file mode 100644
index 0000000..e5ec877
--- /dev/null
+++ b/src/libcef/common/chrome/chrome_content_client_cef.h
@@ -0,0 +1,23 @@
+// Copyright 2015 The Chromium Embedded Framework Authors.
+// Portions copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_COMMON_CHROME_CHROME_CONTENT_CLIENT_CEF_H_
+#define CEF_LIBCEF_COMMON_CHROME_CHROME_CONTENT_CLIENT_CEF_H_
+
+#include "chrome/common/chrome_content_client.h"
+
+class ChromeContentClientCef : public ChromeContentClient {
+ public:
+  ChromeContentClientCef();
+  ~ChromeContentClientCef() override;
+
+  // content::ContentClient overrides.
+  void AddContentDecryptionModules(
+      std::vector<content::CdmInfo>* cdms,
+      std::vector<media::CdmHostFilePath>* cdm_host_file_paths) override;
+  void AddAdditionalSchemes(Schemes* schemes) override;
+};
+
+#endif  // CEF_LIBCEF_COMMON_CHROME_CHROME_CONTENT_CLIENT_CEF_H_
diff --git a/src/libcef/common/chrome/chrome_main_delegate_cef.cc b/src/libcef/common/chrome/chrome_main_delegate_cef.cc
new file mode 100644
index 0000000..8a8f1bb
--- /dev/null
+++ b/src/libcef/common/chrome/chrome_main_delegate_cef.cc
@@ -0,0 +1,354 @@
+// Copyright 2020 The Chromium Embedded Framework Authors.
+// Portions copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/common/chrome/chrome_main_delegate_cef.h"
+
+#include <tuple>
+
+#include "libcef/browser/chrome/chrome_browser_context.h"
+#include "libcef/browser/chrome/chrome_content_browser_client_cef.h"
+#include "libcef/common/cef_switches.h"
+#include "libcef/common/command_line_impl.h"
+#include "libcef/common/crash_reporting.h"
+#include "libcef/common/resource_util.h"
+#include "libcef/renderer/chrome/chrome_content_renderer_client_cef.h"
+
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/lazy_instance.h"
+#include "base/threading/threading_features.h"
+#include "chrome/browser/metrics/chrome_feature_list_creator.h"
+#include "chrome/browser/policy/chrome_browser_policy_connector.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "components/embedder_support/switches.h"
+#include "content/public/common/content_switches.h"
+#include "sandbox/policy/switches.h"
+#include "third_party/blink/public/common/switches.h"
+#include "ui/base/ui_base_switches.h"
+
+#if BUILDFLAG(IS_MAC)
+#include "libcef/common/util_mac.h"
+#elif BUILDFLAG(IS_POSIX)
+#include "libcef/common/util_linux.h"
+#endif
+
+#if BUILDFLAG(IS_MAC)
+#include "libcef/common/util_mac.h"
+#endif
+
+namespace {
+
+base::LazyInstance<ChromeContentRendererClientCef>::DestructorAtExit
+    g_chrome_content_renderer_client = LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
+ChromeMainDelegateCef::ChromeMainDelegateCef(CefMainRunnerHandler* runner,
+                                             CefSettings* settings,
+                                             CefRefPtr<CefApp> application)
+    : ChromeMainDelegate(base::TimeTicks::Now()),
+      runner_(runner),
+      settings_(settings),
+      application_(application) {
+#if BUILDFLAG(IS_LINUX)
+  resource_util::OverrideAssetPath();
+#endif
+}
+
+ChromeMainDelegateCef::~ChromeMainDelegateCef() = default;
+
+absl::optional<int> ChromeMainDelegateCef::BasicStartupComplete() {
+  // Returns false if startup should proceed.
+  auto result = ChromeMainDelegate::BasicStartupComplete();
+  if (result.has_value()) {
+    return result;
+  }
+
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+
+#if BUILDFLAG(IS_POSIX)
+  // Read the crash configuration file. On Windows this is done from chrome_elf.
+  crash_reporting::BasicStartupComplete(command_line);
+#endif
+
+  const std::string& process_type =
+      command_line->GetSwitchValueASCII(switches::kProcessType);
+  if (process_type.empty()) {
+    // In the browser process. Populate the global command-line object.
+    // TODO(chrome-runtime): Copy more settings from AlloyMainDelegate and test.
+    if (settings_->command_line_args_disabled) {
+      // Remove any existing command-line arguments.
+      base::CommandLine::StringVector argv;
+      argv.push_back(command_line->GetProgram().value());
+      command_line->InitFromArgv(argv);
+
+      const base::CommandLine::SwitchMap& map = command_line->GetSwitches();
+      const_cast<base::CommandLine::SwitchMap*>(&map)->clear();
+    }
+
+    bool no_sandbox = settings_->no_sandbox ? true : false;
+
+    if (no_sandbox) {
+      command_line->AppendSwitch(sandbox::policy::switches::kNoSandbox);
+    }
+
+    if (settings_->user_agent.length > 0) {
+      command_line->AppendSwitchASCII(
+          embedder_support::kUserAgent,
+          CefString(&settings_->user_agent).ToString());
+    } else if (settings_->user_agent_product.length > 0) {
+      command_line->AppendSwitchASCII(
+          switches::kUserAgentProductAndVersion,
+          CefString(&settings_->user_agent_product).ToString());
+    }
+
+    if (settings_->locale.length > 0) {
+      command_line->AppendSwitchASCII(switches::kLang,
+                                      CefString(&settings_->locale).ToString());
+    } else if (!command_line->HasSwitch(switches::kLang)) {
+      command_line->AppendSwitchASCII(switches::kLang, "en-US");
+    }
+
+    if (settings_->javascript_flags.length > 0) {
+      command_line->AppendSwitchASCII(
+          blink::switches::kJavaScriptFlags,
+          CefString(&settings_->javascript_flags).ToString());
+    }
+
+    if (settings_->remote_debugging_port >= 1024 &&
+        settings_->remote_debugging_port <= 65535) {
+      command_line->AppendSwitchASCII(
+          switches::kRemoteDebuggingPort,
+          base::NumberToString(settings_->remote_debugging_port));
+    }
+
+    if (settings_->uncaught_exception_stack_size > 0) {
+      command_line->AppendSwitchASCII(
+          switches::kUncaughtExceptionStackSize,
+          base::NumberToString(settings_->uncaught_exception_stack_size));
+    }
+
+    std::vector<std::string> disable_features;
+
+    if (!!settings_->multi_threaded_message_loop &&
+        base::kEnableHangWatcher.default_state ==
+            base::FEATURE_ENABLED_BY_DEFAULT) {
+      // Disable EnableHangWatcher when running with multi-threaded-message-loop
+      // to avoid shutdown crashes (see issue #3403).
+      disable_features.push_back(base::kEnableHangWatcher.name);
+    }
+
+    if (!disable_features.empty()) {
+      DCHECK(!base::FeatureList::GetInstance());
+      std::string disable_features_str =
+          command_line->GetSwitchValueASCII(switches::kDisableFeatures);
+      for (auto feature_str : disable_features) {
+        if (!disable_features_str.empty()) {
+          disable_features_str += ",";
+        }
+        disable_features_str += feature_str;
+      }
+      command_line->AppendSwitchASCII(switches::kDisableFeatures,
+                                      disable_features_str);
+    }
+  }
+
+  if (application_) {
+    // Give the application a chance to view/modify the command line.
+    CefRefPtr<CefCommandLineImpl> commandLinePtr(
+        new CefCommandLineImpl(command_line, false, false));
+    application_->OnBeforeCommandLineProcessing(process_type,
+                                                commandLinePtr.get());
+    std::ignore = commandLinePtr->Detach(nullptr);
+  }
+
+#if BUILDFLAG(IS_MAC)
+  util_mac::BasicStartupComplete();
+#endif
+
+  return absl::nullopt;
+}
+
+void ChromeMainDelegateCef::PreSandboxStartup() {
+  const base::CommandLine* command_line =
+      base::CommandLine::ForCurrentProcess();
+  const std::string& process_type =
+      command_line->GetSwitchValueASCII(switches::kProcessType);
+
+  if (process_type.empty()) {
+#if BUILDFLAG(IS_MAC)
+    util_mac::PreSandboxStartup();
+#elif BUILDFLAG(IS_POSIX)
+    util_linux::PreSandboxStartup();
+#endif
+  }
+
+  // Since this may be configured via CefSettings we override the value on
+  // all platforms. We can't use the default implementation on macOS because
+  // chrome::GetDefaultUserDataDirectory expects to find the Chromium version
+  // number in the app bundle path.
+  resource_util::OverrideUserDataDir(settings_, command_line);
+
+  ChromeMainDelegate::PreSandboxStartup();
+
+  // Initialize crash reporting state for this process/module.
+  // chrome::DIR_CRASH_DUMPS must be configured before calling this function.
+  crash_reporting::PreSandboxStartup(*command_line, process_type);
+}
+
+absl::optional<int> ChromeMainDelegateCef::PreBrowserMain() {
+  // The parent ChromeMainDelegate implementation creates the NSApplication
+  // instance on macOS, and we intentionally don't want to do that here.
+  // TODO(macos): Do we need l10n_util::OverrideLocaleWithCocoaLocale()?
+  runner_->PreBrowserMain();
+  return absl::nullopt;
+}
+
+absl::optional<int> ChromeMainDelegateCef::PostEarlyInitialization(
+    InvokedIn invoked_in) {
+  // Configure this before ChromeMainDelegate::PostEarlyInitialization triggers
+  // ChromeBrowserPolicyConnector creation.
+  if (settings_ && settings_->chrome_policy_id.length > 0) {
+    policy::ChromeBrowserPolicyConnector::EnablePlatformPolicySupport(
+        CefString(&settings_->chrome_policy_id).ToString());
+  }
+
+  const auto result = ChromeMainDelegate::PostEarlyInitialization(invoked_in);
+  if (!result) {
+    const auto* invoked_in_browser =
+        absl::get_if<InvokedInBrowserProcess>(&invoked_in);
+    if (invoked_in_browser) {
+      // At this point local_state has been created but ownership has not yet
+      // been passed to BrowserProcessImpl (g_browser_process is nullptr).
+      auto* local_state = chrome_content_browser_client_->startup_data()
+                              ->chrome_feature_list_creator()
+                              ->local_state();
+
+      // Don't show the profile picker on startup (see issue #3440).
+      local_state->SetBoolean(prefs::kBrowserShowProfilePickerOnStartup, false);
+    }
+  }
+
+  return result;
+}
+
+absl::variant<int, content::MainFunctionParams>
+ChromeMainDelegateCef::RunProcess(
+    const std::string& process_type,
+    content::MainFunctionParams main_function_params) {
+  if (process_type.empty()) {
+    return runner_->RunMainProcess(std::move(main_function_params));
+  }
+
+  return ChromeMainDelegate::RunProcess(process_type,
+                                        std::move(main_function_params));
+}
+
+#if BUILDFLAG(IS_LINUX)
+void ChromeMainDelegateCef::ZygoteForked() {
+  ChromeMainDelegate::ZygoteForked();
+
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  const std::string& process_type =
+      command_line->GetSwitchValueASCII(switches::kProcessType);
+
+  // Initialize crash reporting state for the newly forked process.
+  crash_reporting::ZygoteForked(command_line, process_type);
+}
+#endif  // BUILDFLAG(IS_LINUX)
+
+content::ContentClient* ChromeMainDelegateCef::CreateContentClient() {
+  return &chrome_content_client_cef_;
+}
+
+content::ContentBrowserClient*
+ChromeMainDelegateCef::CreateContentBrowserClient() {
+  // Match the logic in the parent ChromeMainDelegate implementation, but create
+  // our own object type.
+  chrome_content_browser_client_ =
+      std::make_unique<ChromeContentBrowserClientCef>();
+  return chrome_content_browser_client_.get();
+}
+
+content::ContentRendererClient*
+ChromeMainDelegateCef::CreateContentRendererClient() {
+  return g_chrome_content_renderer_client.Pointer();
+}
+
+CefRefPtr<CefRequestContext> ChromeMainDelegateCef::GetGlobalRequestContext() {
+  auto browser_client = content_browser_client();
+  if (browser_client) {
+    return browser_client->request_context();
+  }
+  return nullptr;
+}
+
+CefBrowserContext* ChromeMainDelegateCef::CreateNewBrowserContext(
+    const CefRequestContextSettings& settings,
+    base::OnceClosure initialized_cb) {
+  auto context = new ChromeBrowserContext(settings);
+  context->InitializeAsync(std::move(initialized_cb));
+  return context;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+ChromeMainDelegateCef::GetBackgroundTaskRunner() {
+  auto browser_client = content_browser_client();
+  if (browser_client) {
+    return browser_client->background_task_runner();
+  }
+  return nullptr;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+ChromeMainDelegateCef::GetUserVisibleTaskRunner() {
+  auto browser_client = content_browser_client();
+  if (browser_client) {
+    return browser_client->user_visible_task_runner();
+  }
+  return nullptr;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+ChromeMainDelegateCef::GetUserBlockingTaskRunner() {
+  auto browser_client = content_browser_client();
+  if (browser_client) {
+    return browser_client->user_blocking_task_runner();
+  }
+  return nullptr;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+ChromeMainDelegateCef::GetRenderTaskRunner() {
+  auto renderer_client = content_renderer_client();
+  if (renderer_client) {
+    return renderer_client->render_task_runner();
+  }
+  return nullptr;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+ChromeMainDelegateCef::GetWebWorkerTaskRunner() {
+  auto renderer_client = content_renderer_client();
+  if (renderer_client) {
+    return renderer_client->GetCurrentTaskRunner();
+  }
+  return nullptr;
+}
+
+ChromeContentBrowserClientCef* ChromeMainDelegateCef::content_browser_client()
+    const {
+  return static_cast<ChromeContentBrowserClientCef*>(
+      chrome_content_browser_client_.get());
+}
+
+ChromeContentRendererClientCef* ChromeMainDelegateCef::content_renderer_client()
+    const {
+  if (!g_chrome_content_renderer_client.IsCreated()) {
+    return nullptr;
+  }
+  return g_chrome_content_renderer_client.Pointer();
+}
diff --git a/src/libcef/common/chrome/chrome_main_delegate_cef.h b/src/libcef/common/chrome/chrome_main_delegate_cef.h
new file mode 100644
index 0000000..cfe768f
--- /dev/null
+++ b/src/libcef/common/chrome/chrome_main_delegate_cef.h
@@ -0,0 +1,86 @@
+// Copyright 2020 The Chromium Embedded Framework Authors.
+// Portions copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_COMMON_CHROME_CHROME_MAIN_DELEGATE_CEF_
+#define CEF_LIBCEF_COMMON_CHROME_CHROME_MAIN_DELEGATE_CEF_
+
+#include <memory>
+
+#include "include/cef_app.h"
+#include "libcef/common/app_manager.h"
+#include "libcef/common/chrome/chrome_content_client_cef.h"
+#include "libcef/common/main_runner_handler.h"
+#include "libcef/common/task_runner_manager.h"
+
+#include "chrome/app/chrome_main_delegate.h"
+
+class ChromeContentBrowserClientCef;
+class ChromeContentRendererClientCef;
+
+// CEF override of ChromeMainDelegate
+class ChromeMainDelegateCef : public ChromeMainDelegate,
+                              public CefAppManager,
+                              public CefTaskRunnerManager {
+ public:
+  // |runner| will be non-nullptr for the main process only, and will outlive
+  // this object.
+  ChromeMainDelegateCef(CefMainRunnerHandler* runner,
+                        CefSettings* settings,
+                        CefRefPtr<CefApp> application);
+
+  ChromeMainDelegateCef(const ChromeMainDelegateCef&) = delete;
+  ChromeMainDelegateCef& operator=(const ChromeMainDelegateCef&) = delete;
+
+  ~ChromeMainDelegateCef() override;
+
+  // ChromeMainDelegate overrides.
+  absl::optional<int> BasicStartupComplete() override;
+  void PreSandboxStartup() override;
+  absl::optional<int> PreBrowserMain() override;
+  absl::optional<int> PostEarlyInitialization(InvokedIn invoked_in) override;
+  absl::variant<int, content::MainFunctionParams> RunProcess(
+      const std::string& process_type,
+      content::MainFunctionParams main_function_params) override;
+#if BUILDFLAG(IS_LINUX)
+  void ZygoteForked() override;
+#endif
+  content::ContentClient* CreateContentClient() override;
+  content::ContentBrowserClient* CreateContentBrowserClient() override;
+  content::ContentRendererClient* CreateContentRendererClient() override;
+
+ protected:
+  // CefAppManager overrides.
+  CefRefPtr<CefApp> GetApplication() override { return application_; }
+  content::ContentClient* GetContentClient() override {
+    return &chrome_content_client_cef_;
+  }
+  CefRefPtr<CefRequestContext> GetGlobalRequestContext() override;
+  CefBrowserContext* CreateNewBrowserContext(
+      const CefRequestContextSettings& settings,
+      base::OnceClosure initialized_cb) override;
+
+  // CefTaskRunnerManager overrides.
+  scoped_refptr<base::SingleThreadTaskRunner> GetBackgroundTaskRunner()
+      override;
+  scoped_refptr<base::SingleThreadTaskRunner> GetUserVisibleTaskRunner()
+      override;
+  scoped_refptr<base::SingleThreadTaskRunner> GetUserBlockingTaskRunner()
+      override;
+  scoped_refptr<base::SingleThreadTaskRunner> GetRenderTaskRunner() override;
+  scoped_refptr<base::SingleThreadTaskRunner> GetWebWorkerTaskRunner() override;
+
+ private:
+  ChromeContentBrowserClientCef* content_browser_client() const;
+  ChromeContentRendererClientCef* content_renderer_client() const;
+
+  CefMainRunnerHandler* const runner_;
+  CefSettings* const settings_;
+  CefRefPtr<CefApp> application_;
+
+  // We use this instead of ChromeMainDelegate::chrome_content_client_.
+  ChromeContentClientCef chrome_content_client_cef_;
+};
+
+#endif  // CEF_LIBCEF_COMMON_CHROME_CHROME_MAIN_DELEGATE_CEF_
diff --git a/src/libcef/common/chrome/chrome_main_runner_delegate.cc b/src/libcef/common/chrome/chrome_main_runner_delegate.cc
new file mode 100644
index 0000000..004f989
--- /dev/null
+++ b/src/libcef/common/chrome/chrome_main_runner_delegate.cc
@@ -0,0 +1,101 @@
+// Copyright 2020 The Chromium Embedded Framework Authors.
+// Portions copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/common/chrome/chrome_main_runner_delegate.h"
+
+#include "libcef/common/app_manager.h"
+#include "libcef/common/chrome/chrome_main_delegate_cef.h"
+
+#include "base/command_line.h"
+#include "base/run_loop.h"
+#include "chrome/browser/browser_process_impl.h"
+#include "chrome/browser/chrome_content_browser_client.h"
+#include "chrome/common/profiler/main_thread_stack_sampling_profiler.h"
+#include "components/keep_alive_registry/keep_alive_types.h"
+#include "components/keep_alive_registry/scoped_keep_alive.h"
+#include "components/metrics/persistent_system_profile.h"
+
+ChromeMainRunnerDelegate::ChromeMainRunnerDelegate(
+    CefMainRunnerHandler* runner,
+    CefSettings* settings,
+    CefRefPtr<CefApp> application)
+    : runner_(runner), settings_(settings), application_(application) {}
+
+ChromeMainRunnerDelegate::~ChromeMainRunnerDelegate() = default;
+
+content::ContentMainDelegate*
+ChromeMainRunnerDelegate::GetContentMainDelegate() {
+  if (!main_delegate_) {
+    main_delegate_ = std::make_unique<ChromeMainDelegateCef>(runner_, settings_,
+                                                             application_);
+  }
+  return main_delegate_.get();
+}
+
+void ChromeMainRunnerDelegate::BeforeMainThreadInitialize(
+    const CefMainArgs& args) {
+#if BUILDFLAG(IS_WIN)
+  base::CommandLine::Init(0, nullptr);
+#else
+  base::CommandLine::Init(args.argc, args.argv);
+#endif
+}
+
+void ChromeMainRunnerDelegate::BeforeMainThreadRun(
+    bool multi_threaded_message_loop) {
+  if (multi_threaded_message_loop) {
+    // Detach from the main thread so that these objects can be attached and
+    // modified from the UI thread going forward.
+    metrics::GlobalPersistentSystemProfile::GetInstance()
+        ->DetachFromCurrentThread();
+  }
+}
+
+void ChromeMainRunnerDelegate::BeforeMainMessageLoopRun(
+    base::RunLoop* run_loop) {
+  // The ScopedKeepAlive instance triggers shutdown logic when released on the
+  // UI thread before terminating the message loop (e.g. from CefQuitMessageLoop
+  // or FinishShutdownOnUIThread when running with multi-threaded message loop).
+  keep_alive_ = std::make_unique<ScopedKeepAlive>(
+      KeepAliveOrigin::APP_CONTROLLER, KeepAliveRestartOption::DISABLED);
+
+  // The QuitClosure will be executed from BrowserProcessImpl::Unpin() via
+  // KeepAliveRegistry when the last ScopedKeepAlive is released.
+  // ScopedKeepAlives are also held by Browser objects.
+  DCHECK(g_browser_process);
+  static_cast<BrowserProcessImpl*>(g_browser_process)
+      ->SetQuitClosure(run_loop->QuitClosure());
+}
+
+bool ChromeMainRunnerDelegate::HandleMainMessageLoopQuit() {
+  // May be called multiple times. See comments in RunMainMessageLoopBefore.
+  keep_alive_.reset();
+
+  // Cancel direct execution of the QuitClosure() in
+  // CefMainRunner::QuitMessageLoop. We instead wait for all Chrome browser
+  // windows to exit.
+  return true;
+}
+
+void ChromeMainRunnerDelegate::BeforeUIThreadInitialize() {
+  sampling_profiler_ = std::make_unique<MainThreadStackSamplingProfiler>();
+}
+
+void ChromeMainRunnerDelegate::AfterUIThreadShutdown() {
+  static_cast<ChromeContentBrowserClient*>(
+      CefAppManager::Get()->GetContentClient()->browser())
+      ->CleanupOnUIThread();
+  main_delegate_->CleanupOnUIThread();
+
+  sampling_profiler_.reset();
+}
+
+void ChromeMainRunnerDelegate::BeforeExecuteProcess(const CefMainArgs& args) {
+  BeforeMainThreadInitialize(args);
+}
+
+void ChromeMainRunnerDelegate::AfterExecuteProcess() {
+  AfterMainThreadShutdown();
+}
diff --git a/src/libcef/common/chrome/chrome_main_runner_delegate.h b/src/libcef/common/chrome/chrome_main_runner_delegate.h
new file mode 100644
index 0000000..13216b2
--- /dev/null
+++ b/src/libcef/common/chrome/chrome_main_runner_delegate.h
@@ -0,0 +1,55 @@
+// Copyright 2020 The Chromium Embedded Framework Authors.
+// Portions copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_COMMON_CHROME_CHROME_MAIN_RUNNER_DELEGATE_CEF_
+#define CEF_LIBCEF_COMMON_CHROME_CHROME_MAIN_RUNNER_DELEGATE_CEF_
+
+#include <memory>
+
+#include "include/cef_app.h"
+#include "libcef/common/main_runner_delegate.h"
+#include "libcef/common/main_runner_handler.h"
+
+class ChromeMainDelegateCef;
+class MainThreadStackSamplingProfiler;
+class ScopedKeepAlive;
+
+class ChromeMainRunnerDelegate : public CefMainRunnerDelegate {
+ public:
+  // |runner| will be non-nullptr for the main process only, and will outlive
+  // this object.
+  ChromeMainRunnerDelegate(CefMainRunnerHandler* runner,
+                           CefSettings* settings,
+                           CefRefPtr<CefApp> application);
+
+  ChromeMainRunnerDelegate(const ChromeMainRunnerDelegate&) = delete;
+  ChromeMainRunnerDelegate& operator=(const ChromeMainRunnerDelegate&) = delete;
+
+  ~ChromeMainRunnerDelegate() override;
+
+ protected:
+  // CefMainRunnerDelegate overrides.
+  content::ContentMainDelegate* GetContentMainDelegate() override;
+  void BeforeMainThreadInitialize(const CefMainArgs& args) override;
+  void BeforeMainThreadRun(bool multi_threaded_message_loop) override;
+  void BeforeMainMessageLoopRun(base::RunLoop* run_loop) override;
+  bool HandleMainMessageLoopQuit() override;
+  void BeforeUIThreadInitialize() override;
+  void AfterUIThreadShutdown() override;
+  void BeforeExecuteProcess(const CefMainArgs& args) override;
+  void AfterExecuteProcess() override;
+
+ private:
+  std::unique_ptr<ChromeMainDelegateCef> main_delegate_;
+
+  std::unique_ptr<MainThreadStackSamplingProfiler> sampling_profiler_;
+  std::unique_ptr<ScopedKeepAlive> keep_alive_;
+
+  CefMainRunnerHandler* const runner_;
+  CefSettings* const settings_;
+  CefRefPtr<CefApp> application_;
+};
+
+#endif  // CEF_LIBCEF_COMMON_CHROME_CHROME_MAIN_RUNNER_DELEGATE_CEF_
diff --git a/src/libcef/common/command_line_impl.cc b/src/libcef/common/command_line_impl.cc
index d44dbda..64ed280 100644
--- a/src/libcef/common/command_line_impl.cc
+++ b/src/libcef/common/command_line_impl.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_path.h"
 #include "base/logging.h"
+#include "base/strings/string_util.h"
 
 CefCommandLineImpl::CefCommandLineImpl(base::CommandLine* value,
                                        bool will_delete,
@@ -32,21 +33,21 @@
 }
 
 void CefCommandLineImpl::InitFromArgv(int argc, const char* const* argv) {
-#if !defined(OS_WIN)
+#if !BUILDFLAG(IS_WIN)
   CEF_VALUE_VERIFY_RETURN_VOID(true);
   mutable_value()->InitFromArgv(argc, argv);
 #else
-  NOTREACHED() << "method not supported on this platform";
+  DCHECK(false) << "method not supported on this platform";
 #endif
 }
 
 void CefCommandLineImpl::InitFromString(const CefString& command_line) {
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   CEF_VALUE_VERIFY_RETURN_VOID(true);
-  const base::string16& str16 = command_line;
+  const std::wstring& str16 = command_line;
   mutable_value()->ParseFromString(str16);
 #else
-  NOTREACHED() << "method not supported on this platform";
+  DCHECK(false) << "method not supported on this platform";
 #endif
 }
 
@@ -64,8 +65,9 @@
   CEF_VALUE_VERIFY_RETURN_VOID(false);
   const base::CommandLine::StringVector& cmd_argv = const_value().argv();
   base::CommandLine::StringVector::const_iterator it = cmd_argv.begin();
-  for (; it != cmd_argv.end(); ++it)
+  for (; it != cmd_argv.end(); ++it) {
     argv.push_back(*it);
+  }
 }
 
 CefString CefCommandLineImpl::GetCommandLineString() {
@@ -90,31 +92,37 @@
 
 bool CefCommandLineImpl::HasSwitch(const CefString& name) {
   CEF_VALUE_VERIFY_RETURN(false, false);
-  return const_value().HasSwitch(name.ToString());
+  return const_value().HasSwitch(base::ToLowerASCII(name.ToString()));
 }
 
 CefString CefCommandLineImpl::GetSwitchValue(const CefString& name) {
   CEF_VALUE_VERIFY_RETURN(false, CefString());
-  return const_value().GetSwitchValueNative(name.ToString());
+  return const_value().GetSwitchValueNative(
+      base::ToLowerASCII(name.ToString()));
 }
 
 void CefCommandLineImpl::GetSwitches(SwitchMap& switches) {
   CEF_VALUE_VERIFY_RETURN_VOID(false);
   const base::CommandLine::SwitchMap& map = const_value().GetSwitches();
   base::CommandLine::SwitchMap::const_iterator it = map.begin();
-  for (; it != map.end(); ++it)
+  for (; it != map.end(); ++it) {
     switches.insert(std::make_pair(it->first, it->second));
+  }
 }
 
 void CefCommandLineImpl::AppendSwitch(const CefString& name) {
   CEF_VALUE_VERIFY_RETURN_VOID(true);
-  mutable_value()->AppendSwitch(name);
+  mutable_value()->AppendSwitch(name.ToString());
 }
 
 void CefCommandLineImpl::AppendSwitchWithValue(const CefString& name,
                                                const CefString& value) {
   CEF_VALUE_VERIFY_RETURN_VOID(true);
-  mutable_value()->AppendSwitchNative(name, value);
+#if BUILDFLAG(IS_WIN)
+  mutable_value()->AppendSwitchNative(name.ToString(), value.ToWString());
+#else
+  mutable_value()->AppendSwitchNative(name.ToString(), value.ToString());
+#endif
 }
 
 bool CefCommandLineImpl::HasArguments() {
@@ -126,18 +134,27 @@
   CEF_VALUE_VERIFY_RETURN_VOID(false);
   const base::CommandLine::StringVector& vec = const_value().GetArgs();
   base::CommandLine::StringVector::const_iterator it = vec.begin();
-  for (; it != vec.end(); ++it)
+  for (; it != vec.end(); ++it) {
     arguments.push_back(*it);
+  }
 }
 
 void CefCommandLineImpl::AppendArgument(const CefString& argument) {
   CEF_VALUE_VERIFY_RETURN_VOID(true);
-  mutable_value()->AppendArgNative(argument);
+#if BUILDFLAG(IS_WIN)
+  mutable_value()->AppendArgNative(argument.ToWString());
+#else
+  mutable_value()->AppendArgNative(argument.ToString());
+#endif
 }
 
 void CefCommandLineImpl::PrependWrapper(const CefString& wrapper) {
   CEF_VALUE_VERIFY_RETURN_VOID(true);
-  mutable_value()->PrependWrapper(wrapper);
+#if BUILDFLAG(IS_WIN)
+  mutable_value()->PrependWrapper(wrapper.ToWString());
+#else
+  mutable_value()->PrependWrapper(wrapper.ToString());
+#endif
 }
 
 // CefCommandLine implementation.
@@ -154,8 +171,9 @@
   static CefRefPtr<CefCommandLineImpl> commandLinePtr;
   if (!commandLinePtr.get()) {
     base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-    if (command_line)
+    if (command_line) {
       commandLinePtr = new CefCommandLineImpl(command_line, false, true);
+    }
   }
   return commandLinePtr.get();
 }
diff --git a/src/libcef/common/command_line_impl.h b/src/libcef/common/command_line_impl.h
index ed4761a..77181cd 100644
--- a/src/libcef/common/command_line_impl.h
+++ b/src/libcef/common/command_line_impl.h
@@ -19,6 +19,9 @@
                      bool will_delete,
                      bool read_only);
 
+  CefCommandLineImpl(const CefCommandLineImpl&) = delete;
+  CefCommandLineImpl& operator=(const CefCommandLineImpl&) = delete;
+
   // CefCommandLine methods.
   bool IsValid() override;
   bool IsReadOnly() override;
@@ -44,8 +47,6 @@
 
   // Must hold the controller lock while using this value.
   const base::CommandLine& command_line() { return const_value(); }
-
-  DISALLOW_COPY_AND_ASSIGN(CefCommandLineImpl);
 };
 
 #endif  // CEF_LIBCEF_COMMON_COMMAND_LINE_IMPL_H_
diff --git a/src/libcef/common/content_client.cc b/src/libcef/common/content_client.cc
deleted file mode 100644
index 99e8535..0000000
--- a/src/libcef/common/content_client.cc
+++ /dev/null
@@ -1,336 +0,0 @@
-// Copyright 2015 The Chromium Embedded Framework Authors.
-// Portions copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/common/content_client.h"
-
-#include <stdint.h>
-
-#include "include/cef_stream.h"
-#include "include/cef_version.h"
-#include "libcef/browser/extensions/pdf_extension_util.h"
-#include "libcef/common/cef_switches.h"
-#include "libcef/common/extensions/extensions_util.h"
-#include "libcef/common/net/scheme_registration.h"
-#include "libcef/common/scheme_registrar_impl.h"
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/json/json_reader.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pepper_flash.h"
-#include "content/public/browser/child_process_security_policy.h"
-#include "content/public/common/content_constants.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/pepper_plugin_info.h"
-#include "ppapi/shared_impl/ppapi_permissions.h"
-#include "third_party/widevine/cdm/buildflags.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-
-#if defined(OS_LINUX)
-#include "libcef/common/widevine_loader.h"
-#endif
-
-namespace {
-
-CefContentClient* g_content_client = nullptr;
-
-// The following plugin-related methods are from
-// chrome/common/chrome_content_client.cc
-
-const char kPDFPluginExtension[] = "pdf";
-const char kPDFPluginDescription[] = "Portable Document Format";
-const char kPDFPluginOutOfProcessMimeType[] = "application/x-google-chrome-pdf";
-const uint32_t kPDFPluginPermissions =
-    ppapi::PERMISSION_PDF | ppapi::PERMISSION_DEV;
-
-content::PepperPluginInfo::GetInterfaceFunc g_pdf_get_interface;
-content::PepperPluginInfo::PPP_InitializeModuleFunc g_pdf_initialize_module;
-content::PepperPluginInfo::PPP_ShutdownModuleFunc g_pdf_shutdown_module;
-
-// Appends the known built-in plugins to the given vector. Some built-in
-// plugins are "internal" which means they are compiled into the Chrome binary,
-// and some are extra shared libraries distributed with the browser (these are
-// not marked internal, aside from being automatically registered, they're just
-// regular plugins).
-void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
-  if (extensions::PdfExtensionEnabled()) {
-    content::PepperPluginInfo pdf_info;
-    pdf_info.is_internal = true;
-    pdf_info.is_out_of_process = true;
-    pdf_info.name = extensions::pdf_extension_util::kPdfPluginName;
-    pdf_info.description = kPDFPluginDescription;
-    pdf_info.path =
-        base::FilePath::FromUTF8Unsafe(CefContentClient::kPDFPluginPath);
-    content::WebPluginMimeType pdf_mime_type(kPDFPluginOutOfProcessMimeType,
-                                             kPDFPluginExtension,
-                                             kPDFPluginDescription);
-    pdf_info.mime_types.push_back(pdf_mime_type);
-    pdf_info.internal_entry_points.get_interface = g_pdf_get_interface;
-    pdf_info.internal_entry_points.initialize_module = g_pdf_initialize_module;
-    pdf_info.internal_entry_points.shutdown_module = g_pdf_shutdown_module;
-    pdf_info.permissions = kPDFPluginPermissions;
-    plugins->push_back(pdf_info);
-  }
-}
-
-content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
-                                                const std::string& version) {
-  content::PepperPluginInfo plugin;
-
-  plugin.is_out_of_process = true;
-  plugin.name = content::kFlashPluginName;
-  plugin.path = path;
-  plugin.permissions = kPepperFlashPermissions;
-
-  std::vector<std::string> flash_version_numbers = base::SplitString(
-      version, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
-  if (flash_version_numbers.size() < 1)
-    flash_version_numbers.push_back("11");
-  if (flash_version_numbers.size() < 2)
-    flash_version_numbers.push_back("2");
-  if (flash_version_numbers.size() < 3)
-    flash_version_numbers.push_back("999");
-  if (flash_version_numbers.size() < 4)
-    flash_version_numbers.push_back("999");
-  // E.g., "Shockwave Flash 10.2 r154":
-  plugin.description = plugin.name + " " + flash_version_numbers[0] + "." +
-                       flash_version_numbers[1] + " r" +
-                       flash_version_numbers[2];
-  plugin.version = base::JoinString(flash_version_numbers, ".");
-  content::WebPluginMimeType swf_mime_type(content::kFlashPluginSwfMimeType,
-                                           content::kFlashPluginSwfExtension,
-                                           content::kFlashPluginSwfDescription);
-  plugin.mime_types.push_back(swf_mime_type);
-  content::WebPluginMimeType spl_mime_type(content::kFlashPluginSplMimeType,
-                                           content::kFlashPluginSplExtension,
-                                           content::kFlashPluginSplDescription);
-  plugin.mime_types.push_back(spl_mime_type);
-
-  return plugin;
-}
-
-void AddPepperFlashFromCommandLine(
-    std::vector<content::PepperPluginInfo>* plugins) {
-  const base::CommandLine::StringType flash_path =
-      base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(
-          switches::kPpapiFlashPath);
-  if (flash_path.empty())
-    return;
-
-  // Also get the version from the command-line. Should be something like 11.2
-  // or 11.2.123.45.
-  std::string flash_version =
-      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-          switches::kPpapiFlashVersion);
-
-  plugins->push_back(
-      CreatePepperFlashInfo(base::FilePath(flash_path), flash_version));
-}
-
-bool GetSystemPepperFlash(content::PepperPluginInfo* plugin) {
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-
-  if (!command_line->HasSwitch(switches::kEnableSystemFlash))
-    return false;
-
-  // Do not try and find System Pepper Flash if there is a specific path on
-  // the commmand-line.
-  if (command_line->HasSwitch(switches::kPpapiFlashPath))
-    return false;
-
-  base::FilePath flash_filename;
-  if (!base::PathService::Get(chrome::FILE_PEPPER_FLASH_SYSTEM_PLUGIN,
-                              &flash_filename)) {
-    return false;
-  }
-
-  base::FilePath manifest_path(
-      flash_filename.DirName().AppendASCII("manifest.json"));
-
-  std::string manifest_data;
-  if (!base::ReadFileToString(manifest_path, &manifest_data))
-    return false;
-  auto json_manifest_value =
-      base::JSONReader::Read(manifest_data, base::JSON_ALLOW_TRAILING_COMMAS);
-  if (!json_manifest_value.has_value())
-    return false;
-  std::unique_ptr<base::Value> manifest_value(
-      base::Value::ToUniquePtrValue(std::move(json_manifest_value.value())));
-  if (!manifest_value.get())
-    return false;
-  base::DictionaryValue* manifest = nullptr;
-  if (!manifest_value->GetAsDictionary(&manifest))
-    return false;
-
-  base::Version version;
-  if (!CheckPepperFlashManifest(*manifest, &version))
-    return false;
-
-  *plugin = CreatePepperFlashInfo(flash_filename, version.GetString());
-  return true;
-}
-
-}  // namespace
-
-const char CefContentClient::kPDFPluginPath[] = "internal-pdf-viewer";
-
-CefContentClient::CefContentClient(CefRefPtr<CefApp> application)
-    : application_(application),
-      pack_loading_disabled_(false),
-      allow_pack_file_load_(false),
-      scheme_info_list_locked_(false),
-      resource_bundle_delegate_(this) {
-  DCHECK(!g_content_client);
-  g_content_client = this;
-}
-
-CefContentClient::~CefContentClient() {
-  g_content_client = nullptr;
-}
-
-// static
-CefContentClient* CefContentClient::Get() {
-  return g_content_client;
-}
-
-void CefContentClient::AddPepperPlugins(
-    std::vector<content::PepperPluginInfo>* plugins) {
-  ComputeBuiltInPlugins(plugins);
-  AddPepperFlashFromCommandLine(plugins);
-
-  content::PepperPluginInfo plugin;
-  if (GetSystemPepperFlash(&plugin))
-    plugins->push_back(plugin);
-}
-
-void CefContentClient::AddContentDecryptionModules(
-    std::vector<content::CdmInfo>* cdms,
-    std::vector<media::CdmHostFilePath>* cdm_host_file_paths) {
-#if defined(OS_LINUX)
-#if BUILDFLAG(ENABLE_WIDEVINE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
-  CefWidevineLoader::AddContentDecryptionModules(cdms, cdm_host_file_paths);
-#endif
-#endif
-}
-
-void CefContentClient::AddAdditionalSchemes(Schemes* schemes) {
-  DCHECK(!scheme_info_list_locked_);
-
-  if (application_.get()) {
-    CefSchemeRegistrarImpl schemeRegistrar;
-    application_->OnRegisterCustomSchemes(&schemeRegistrar);
-    schemeRegistrar.GetSchemes(schemes);
-  }
-
-  scheme::AddInternalSchemes(schemes);
-
-  scheme_info_list_locked_ = true;
-}
-
-base::string16 CefContentClient::GetLocalizedString(int message_id) {
-  base::string16 value =
-      ui::ResourceBundle::GetSharedInstance().GetLocalizedString(message_id);
-  if (value.empty())
-    LOG(ERROR) << "No localized string available for id " << message_id;
-
-  return value;
-}
-
-base::string16 CefContentClient::GetLocalizedString(
-    int message_id,
-    const base::string16& replacement) {
-  base::string16 value = l10n_util::GetStringFUTF16(message_id, replacement);
-  if (value.empty())
-    LOG(ERROR) << "No localized string available for id " << message_id;
-
-  return value;
-}
-
-base::StringPiece CefContentClient::GetDataResource(
-    int resource_id,
-    ui::ScaleFactor scale_factor) {
-  base::StringPiece value =
-      ui::ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(
-          resource_id, scale_factor);
-  if (value.empty())
-    LOG(ERROR) << "No data resource available for id " << resource_id;
-
-  return value;
-}
-
-base::RefCountedMemory* CefContentClient::GetDataResourceBytes(
-    int resource_id) {
-  base::RefCountedMemory* value =
-      ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
-          resource_id);
-  if (!value)
-    LOG(ERROR) << "No data resource bytes available for id " << resource_id;
-
-  return value;
-}
-
-gfx::Image& CefContentClient::GetNativeImageNamed(int resource_id) {
-  gfx::Image& value =
-      ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id);
-  if (value.IsEmpty())
-    LOG(ERROR) << "No native image available for id " << resource_id;
-
-  return value;
-}
-
-void CefContentClient::AddCustomScheme(const SchemeInfo& scheme_info) {
-  DCHECK(!scheme_info_list_locked_);
-  scheme_info_list_.push_back(scheme_info);
-
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  if (!command_line->HasSwitch(switches::kProcessType)) {
-    // Register as a Web-safe scheme in the browser process so that requests for
-    // the scheme from a render process will be allowed in
-    // resource_dispatcher_host_impl.cc ShouldServiceRequest.
-    content::ChildProcessSecurityPolicy* policy =
-        content::ChildProcessSecurityPolicy::GetInstance();
-    if (!policy->IsWebSafeScheme(scheme_info.scheme_name))
-      policy->RegisterWebSafeScheme(scheme_info.scheme_name);
-  }
-}
-
-const CefContentClient::SchemeInfoList* CefContentClient::GetCustomSchemes() {
-  DCHECK(scheme_info_list_locked_);
-  return &scheme_info_list_;
-}
-
-bool CefContentClient::HasCustomScheme(const std::string& scheme_name) {
-  DCHECK(scheme_info_list_locked_);
-  if (scheme_info_list_.empty())
-    return false;
-
-  SchemeInfoList::const_iterator it = scheme_info_list_.begin();
-  for (; it != scheme_info_list_.end(); ++it) {
-    if (it->scheme_name == scheme_name)
-      return true;
-  }
-
-  return false;
-}
-
-// static
-void CefContentClient::SetPDFEntryFunctions(
-    content::PepperPluginInfo::GetInterfaceFunc get_interface,
-    content::PepperPluginInfo::PPP_InitializeModuleFunc initialize_module,
-    content::PepperPluginInfo::PPP_ShutdownModuleFunc shutdown_module) {
-  g_pdf_get_interface = get_interface;
-  g_pdf_initialize_module = initialize_module;
-  g_pdf_shutdown_module = shutdown_module;
-}
diff --git a/src/libcef/common/content_client.h b/src/libcef/common/content_client.h
deleted file mode 100644
index 81963e1..0000000
--- a/src/libcef/common/content_client.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2015 The Chromium Embedded Framework Authors.
-// Portions copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_COMMON_CONTENT_CLIENT_H_
-#define CEF_LIBCEF_COMMON_CONTENT_CLIENT_H_
-#pragma once
-
-#include <list>
-#include <string>
-#include <vector>
-
-#include "include/cef_app.h"
-#include "libcef/common/resource_bundle_delegate.h"
-
-#include "base/compiler_specific.h"
-#include "content/public/common/content_client.h"
-#include "content/public/common/pepper_plugin_info.h"
-#include "url/url_util.h"
-
-class CefContentClient : public content::ContentClient {
- public:
-  static const char kPDFPluginPath[];
-
-  explicit CefContentClient(CefRefPtr<CefApp> application);
-  ~CefContentClient() override;
-
-  // Returns the singleton CefContentClient instance.
-  static CefContentClient* Get();
-
-  // content::ContentClient methods.
-  void AddPepperPlugins(
-      std::vector<content::PepperPluginInfo>* plugins) override;
-  void AddContentDecryptionModules(
-      std::vector<content::CdmInfo>* cdms,
-      std::vector<media::CdmHostFilePath>* cdm_host_file_paths) override;
-  void AddAdditionalSchemes(Schemes* schemes) override;
-  base::string16 GetLocalizedString(int message_id) override;
-  base::string16 GetLocalizedString(int message_id,
-                                    const base::string16& replacement) override;
-  base::StringPiece GetDataResource(int resource_id,
-                                    ui::ScaleFactor scale_factor) override;
-  base::RefCountedMemory* GetDataResourceBytes(int resource_id) override;
-  gfx::Image& GetNativeImageNamed(int resource_id) override;
-
-  // Values are registered with all processes (url/url_util.h) and with Blink
-  // (SchemeRegistry) unless otherwise indicated.
-  struct SchemeInfo {
-    // Lower-case ASCII scheme name.
-    std::string scheme_name;
-
-    // A scheme that is subject to URL canonicalization and parsing rules as
-    // defined in the Common Internet Scheme Syntax RFC 1738 Section 3.1
-    // available at http://www.ietf.org/rfc/rfc1738.txt.
-    // This value is not registered with Blink.
-    bool is_standard;
-
-    // A scheme that will be treated the same as "file". For example, normal
-    // pages cannot link to or access URLs of this scheme.
-    bool is_local;
-
-    // A scheme that can only be displayed from other content hosted with the
-    // same scheme. For example, pages in other origins cannot create iframes or
-    // hyperlinks to URLs with the scheme. For schemes that must be accessible
-    // from other schemes set this value to false, set |is_cors_enabled| to
-    // true, and use CORS "Access-Control-Allow-Origin" headers to further
-    // restrict access.
-    // This value is registered with Blink only.
-    bool is_display_isolated;
-
-    // A scheme that will be treated the same as "https". For example, loading
-    // this scheme from other secure schemes will not trigger mixed content
-    // warnings.
-    bool is_secure;
-
-    // A scheme that can be sent CORS requests. This value should be true in
-    // most cases where |is_standard| is true.
-    bool is_cors_enabled;
-
-    // A scheme that can bypass Content-Security-Policy (CSP) checks. This value
-    // should be false in most cases where |is_standard| is true.
-    bool is_csp_bypassing;
-
-    // A scheme that can perform fetch request.
-    bool is_fetch_enabled;
-  };
-  typedef std::list<SchemeInfo> SchemeInfoList;
-
-  // Custom scheme information will be registered first with all processes
-  // (url/url_util.h) via CefContentClient::AddAdditionalSchemes which calls
-  // AddCustomScheme, and second with Blink (SchemeRegistry) via
-  // CefContentRendererClient::WebKitInitialized which calls GetCustomSchemes.
-  void AddCustomScheme(const SchemeInfo& scheme_info);
-  const SchemeInfoList* GetCustomSchemes();
-  bool HasCustomScheme(const std::string& scheme_name);
-
-  CefRefPtr<CefApp> application() const { return application_; }
-
-  void set_pack_loading_disabled(bool val) { pack_loading_disabled_ = val; }
-  bool pack_loading_disabled() const { return pack_loading_disabled_; }
-  void set_allow_pack_file_load(bool val) { allow_pack_file_load_ = val; }
-  bool allow_pack_file_load() { return allow_pack_file_load_; }
-
-  static void SetPDFEntryFunctions(
-      content::PepperPluginInfo::GetInterfaceFunc get_interface,
-      content::PepperPluginInfo::PPP_InitializeModuleFunc initialize_module,
-      content::PepperPluginInfo::PPP_ShutdownModuleFunc shutdown_module);
-
-  CefResourceBundleDelegate* GetCefResourceBundleDelegate() {
-    return &resource_bundle_delegate_;
-  }
-
- private:
-  CefRefPtr<CefApp> application_;
-  bool pack_loading_disabled_;
-  bool allow_pack_file_load_;
-
-  // Custom schemes handled by the client.
-  SchemeInfoList scheme_info_list_;
-  bool scheme_info_list_locked_;
-
-  CefResourceBundleDelegate resource_bundle_delegate_;
-};
-
-#endif  // CEF_LIBCEF_COMMON_CONTENT_CLIENT_H_
diff --git a/src/libcef/common/crash_reporter_client.cc b/src/libcef/common/crash_reporter_client.cc
index 00d422b..da87128 100644
--- a/src/libcef/common/crash_reporter_client.cc
+++ b/src/libcef/common/crash_reporter_client.cc
@@ -6,27 +6,27 @@
 
 #include <utility>
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 #include <windows.h>
 #endif
 
 #include "base/environment.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
-#include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/crash/core/common/crash_key.h"
-#include "services/service_manager/embedder/switches.h"
+#include "content/public/common/content_switches.h"
 #include "third_party/crashpad/crashpad/client/annotation.h"
 
-#if defined(OS_MACOSX)
+#if BUILDFLAG(IS_MAC)
 #include "libcef/common/util_mac.h"
 #endif
 
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
 // Don't use CommandLine, FilePath or PathService on Windows. FilePath has
 // dependencies outside of kernel32, which is disallowed by chrome_elf.
 // CommandLine and PathService depend on global state that will not be
@@ -38,12 +38,12 @@
 #include "chrome/common/chrome_paths.h"
 #endif
 
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
+#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
 #include "content/public/common/content_switches.h"
 #include "libcef/common/cef_crash_report_utils.h"
 #endif
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 #include "base/debug/leak_annotations.h"
 #include "chrome/install_static/install_util.h"
 #include "components/crash/core/app/crashpad.h"
@@ -51,34 +51,36 @@
 
 namespace {
 
-#if defined(OS_WIN)
-typedef base::string16 PathString;
+#if BUILDFLAG(IS_WIN)
+using PathString = std::wstring;
 const char kPathSep = '\\';
 #else
-typedef std::string PathString;
+using PathString = std::string;
 #endif
 
 PathString GetCrashConfigPath() {
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   // Start with the path to the running executable.
   wchar_t module_path[MAX_PATH];
-  if (GetModuleFileName(nullptr, module_path, MAX_PATH) == 0)
+  if (GetModuleFileName(nullptr, module_path, MAX_PATH) == 0) {
     return PathString();
+  }
 
   PathString config_path = module_path;
 
   // Remove the executable file name.
   PathString::size_type last_backslash =
       config_path.rfind(kPathSep, config_path.size());
-  if (last_backslash != PathString::npos)
+  if (last_backslash != PathString::npos) {
     config_path.erase(last_backslash + 1);
+  }
 
   config_path += L"crash_reporter.cfg";
   return config_path;
-#elif defined(OS_POSIX)
+#elif BUILDFLAG(IS_POSIX)
   base::FilePath config_path;
 
-#if defined(OS_MACOSX)
+#if BUILDFLAG(IS_MAC)
   // Start with the path to the main app Resources directory. May be empty if
   // not running in an app bundle.
   config_path = util_mac::GetMainResourcesDirectory();
@@ -86,15 +88,16 @@
 
   if (config_path.empty()) {
     // Start with the path to the running executable.
-    if (!base::PathService::Get(base::DIR_EXE, &config_path))
+    if (!base::PathService::Get(base::DIR_EXE, &config_path)) {
       return PathString();
+    }
   }
 
   return config_path.Append(FILE_PATH_LITERAL("crash_reporter.cfg")).value();
-#endif  // defined(OS_POSIX)
+#endif  // BUILDFLAG(IS_POSIX)
 }
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 
 // On Windows, FAT32 and NTFS both limit filenames to a maximum of 255
 // characters. On POSIX systems, the typical filename length limit is 255
@@ -106,11 +109,13 @@
 const char kInvalidFileChars[] = "<>:\"/\\|?*";
 
 bool isInvalidFileCharacter(unsigned char c) {
-  if (c < ' ' || c == 0x7F)
+  if (c < ' ' || c == 0x7F) {
     return true;
+  }
   for (size_t i = 0; i < sizeof(kInvalidFileChars); ++i) {
-    if (c == kInvalidFileChars[i])
+    if (c == kInvalidFileChars[i]) {
       return true;
+    }
   }
   return false;
 }
@@ -124,8 +129,9 @@
 }
 
 std::string extractAbsolutePathStart(std::string& s) {
-  if (!isAbsolutePath(s))
+  if (!isAbsolutePath(s)) {
     return std::string();
+  }
 
   std::string start;
   if (s[0] == kPathSep) {
@@ -141,14 +147,16 @@
 }
 
 std::string sanitizePathComponentPart(const std::string& s) {
-  if (s.empty())
+  if (s.empty()) {
     return std::string();
+  }
 
   std::string result;
   result.reserve(s.length());
   for (size_t i = 0; i < s.length(); ++i) {
-    if (!isInvalidFileCharacter(s[i]))
+    if (!isInvalidFileCharacter(s[i])) {
       result.push_back(s[i]);
+    }
   }
   return result;
 }
@@ -170,13 +178,15 @@
   ext = sanitizePathComponentPart(ext);
 
   // Remove a ridiculously-long extension.
-  if (ext.length() >= maxFilenameLength)
+  if (ext.length() >= maxFilenameLength) {
     ext = std::string();
+  }
 
   // Truncate an overly-long filename, reserving one character for a dot.
   std::string::size_type max_name_len = maxFilenameLength - ext.length() - 1;
-  if (name.length() > max_name_len)
+  if (name.length() > max_name_len) {
     name = name.substr(0, max_name_len);
+  }
 
   return ext.empty() ? name : name + "." + ext;
 }
@@ -193,10 +203,12 @@
                         base::SPLIT_WANT_NONEMPTY);
   for (size_t i = 0; i < parts.size(); ++i) {
     std::string part = parts[i];
-    if (part != "." && part != "..")
+    if (part != "." && part != "..") {
       part = sanitizePathComponent(part);
-    if (!result.empty() && result[result.length() - 1] != kPathSep)
+    }
+    if (!result.empty() && result[result.length() - 1] != kPathSep) {
       result += kPathSep;
+    }
     result += part;
   }
 
@@ -204,37 +216,43 @@
 }
 
 std::string joinPath(const std::string& s1, const std::string& s2) {
-  if (s1.empty() && s2.empty())
+  if (s1.empty() && s2.empty()) {
     return std::string();
-  if (s1.empty())
+  }
+  if (s1.empty()) {
     return s2;
-  if (s2.empty())
+  }
+  if (s2.empty()) {
     return s1;
+  }
 
   // Don't try to join absolute paths on Windows.
   // Skip this check on POSIX where it's more difficult to differentiate.
-  if (isAbsolutePath(s2))
+  if (isAbsolutePath(s2)) {
     return s2;
+  }
 
   std::string result = s1;
-  if (result[result.size() - 1] != kPathSep)
+  if (result[result.size() - 1] != kPathSep) {
     result += kPathSep;
-  if (s2[0] == kPathSep)
+  }
+  if (s2[0] == kPathSep) {
     result += s2.substr(1);
-  else
+  } else {
     result += s2;
+  }
   return result;
 }
 
 // This will only be non-nullptr in the chrome_elf address space.
 CefCrashReporterClient* g_crash_reporter_client = nullptr;
 
-#endif  // defined(OS_WIN)
+#endif  // BUILDFLAG(IS_WIN)
 
 const char kKeyMapDelim = ',';
 
 std::string NormalizeCrashKey(const base::StringPiece& key) {
-  std::string str = key.as_string();
+  std::string str(key);
   std::replace(str.begin(), str.end(), kKeyMapDelim, '-');
   if (str.length() > crashpad::Annotation::kNameMaxLength) {
     return str.substr(0, crashpad::Annotation::kNameMaxLength);
@@ -260,14 +278,15 @@
 
 int ParseZeroBasedInt(const std::string& value) {
   int int_val;
-  if (base::StringToInt(value, &int_val) && int_val > 0)
+  if (base::StringToInt(value, &int_val) && int_val > 0) {
     return int_val;
+  }
   return 0;
 }
 
 }  // namespace
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 
 extern "C" {
 
@@ -304,23 +323,26 @@
   // This environment variable should be set on Windows Vista and later
   // (https://msdn.microsoft.com/library/windows/desktop/dd378457.aspx).
   std::wstring user_data_dir =
-      install_static::GetEnvironmentString16(L"LOCALAPPDATA");
+      install_static::GetEnvironmentString(L"LOCALAPPDATA");
 
   if (user_data_dir.empty()) {
     // LOCALAPPDATA was not set; fallback to the temporary files path.
     DWORD size = ::GetTempPath(0, nullptr);
-    if (!size)
+    if (!size) {
       return false;
+    }
     user_data_dir.resize(size + 1);
     size = ::GetTempPath(size + 1, &user_data_dir[0]);
-    if (!size || size >= user_data_dir.size())
+    if (!size || size >= user_data_dir.size()) {
       return false;
+    }
     user_data_dir.resize(size);
   }
 
   result->swap(user_data_dir);
-  if ((*result)[result->length() - 1] != L'\\')
+  if ((*result)[result->length() - 1] != L'\\') {
     result->push_back(L'\\');
+  }
   result->append(install_sub_directory);
   result->push_back(L'\\');
   result->append(kUserDataDirname);
@@ -334,13 +356,15 @@
   // In order to be able to start crash handling very early, we do not rely on
   // chrome's PathService entries (for DIR_CRASH_DUMPS) being available on
   // Windows. See https://crbug.com/564398.
-  if (!GetDefaultUserDataDirectory(crash_dir, install_sub_directory))
+  if (!GetDefaultUserDataDirectory(crash_dir, install_sub_directory)) {
     return false;
+  }
 
   // We have to make sure the user data dir exists on first run. See
   // http://crbug.com/591504.
-  if (!install_static::RecursiveDirectoryCreate(*crash_dir))
+  if (!install_static::RecursiveDirectoryCreate(*crash_dir)) {
     return false;
+  }
   crash_dir->append(L"\\Crashpad");
   return true;
 }
@@ -352,20 +376,23 @@
 
 // Be aware that logging is not initialized at the time this method is called.
 bool CefCrashReporterClient::ReadCrashConfigFile() {
-  if (has_crash_config_file_)
+  if (has_crash_config_file_) {
     return true;
+  }
 
   PathString config_path = GetCrashConfigPath();
-  if (config_path.empty())
+  if (config_path.empty()) {
     return false;
+  }
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   FILE* fp = _wfopen(config_path.c_str(), L"r");
 #else
   FILE* fp = fopen(config_path.c_str(), "r");
 #endif
-  if (!fp)
+  if (!fp) {
     return false;
+  }
 
   char line[1000];
 
@@ -383,8 +410,9 @@
   while (fgets(line, sizeof(line) - 1, fp) != nullptr) {
     std::string str = line;
     base::TrimString(str, base::kWhitespaceASCII, &str);
-    if (str.empty() || str[0] == '#')
+    if (str.empty() || str[0] == '#') {
       continue;
+    }
 
     if (str == "[Config]") {
       current_section = kConfigSection;
@@ -397,19 +425,22 @@
       continue;
     }
 
-    if (current_section == kNoSection)
+    if (current_section == kNoSection) {
       continue;
+    }
 
     size_t div = str.find('=');
-    if (div == std::string::npos)
+    if (div == std::string::npos) {
       continue;
+    }
 
     std::string name_str = str.substr(0, div);
     base::TrimString(name_str, base::kWhitespaceASCII, &name_str);
     std::string val_str = str.substr(div + 1);
     base::TrimString(val_str, base::kWhitespaceASCII, &val_str);
-    if (name_str.empty())
+    if (name_str.empty()) {
       continue;
+    }
 
     if (current_section == kConfigSection) {
       if (name_str == "ServerURL") {
@@ -427,18 +458,20 @@
       } else if (name_str == "MaxDatabaseAgeInDays") {
         max_db_age_ = ParseZeroBasedInt(val_str);
       }
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
       else if (name_str == "ExternalHandler") {
-        if (!val_str.empty())
+        if (!val_str.empty()) {
           external_handler_ = sanitizePath(val_str);
+        }
       } else if (name_str == "AppName") {
         if (!val_str.empty()) {
           val_str = sanitizePathComponent(val_str);
-          if (!val_str.empty())
+          if (!val_str.empty()) {
             app_name_ = val_str;
+          }
         }
       }
-#elif defined(OS_MACOSX)
+#elif BUILDFLAG(IS_MAC)
       else if (name_str == "BrowserCrashForwardingEnabled") {
         enable_browser_crash_forwarding_ = ParseBool(val_str);
       }
@@ -495,20 +528,21 @@
     };
 
     // Make sure we can fit all possible name/value pairs.
-    static_assert(base::size(ids) * crashpad::Annotation::kValueMaxSize >=
+    static_assert(std::size(ids) * crashpad::Annotation::kValueMaxSize >=
                       3 * 26 /* sizes (small, medium, large) * slots (A to Z) */
                           * (3 + 2 /* key size ("S-A") + delim size ("=,") */
                              + crashpad::Annotation::kNameMaxLength),
                   "Not enough storage for key map");
 
     size_t offset = 0;
-    for (size_t i = 0; i < base::size(ids); ++i) {
+    for (size_t i = 0; i < std::size(ids); ++i) {
       size_t length = std::min(map_keys.size() - offset,
                                crashpad::Annotation::kValueMaxSize);
       ids[i].Set(base::StringPiece(map_keys.data() + offset, length));
       offset += length;
-      if (offset >= map_keys.size())
+      if (offset >= map_keys.size()) {
         break;
+      }
     }
   }
 
@@ -533,18 +567,20 @@
   return has_crash_config_file_;
 }
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 
 // static
 void CefCrashReporterClient::InitializeCrashReportingForProcess() {
-  if (g_crash_reporter_client)
+  if (g_crash_reporter_client) {
     return;
+  }
 
   g_crash_reporter_client = new CefCrashReporterClient();
   ANNOTATE_LEAKING_OBJECT_PTR(g_crash_reporter_client);
 
-  if (!g_crash_reporter_client->ReadCrashConfigFile())
+  if (!g_crash_reporter_client->ReadCrashConfigFile()) {
     return;
+  }
 
   std::wstring process_type = install_static::GetSwitchValueFromCommandLine(
       ::GetCommandLineW(), install_static::kProcessType);
@@ -557,51 +593,51 @@
         !g_crash_reporter_client->HasCrashExternalHandler();
     if (embedded_handler) {
       crash_reporter::InitializeCrashpadWithEmbeddedHandler(
-          process_type.empty(), install_static::UTF16ToUTF8(process_type),
+          process_type.empty(), install_static::WideToUTF8(process_type),
           std::string(), base::FilePath());
     } else {
       crash_reporter::InitializeCrashpad(
-          process_type.empty(), install_static::UTF16ToUTF8(process_type));
+          process_type.empty(), install_static::WideToUTF8(process_type));
     }
   }
 }
 
 bool CefCrashReporterClient::GetAlternativeCrashDumpLocation(
-    base::string16* crash_dir) {
+    std::wstring* crash_dir) {
   // By setting the BREAKPAD_DUMP_LOCATION environment variable, an alternate
   // location to write breakpad crash dumps can be set.
-  *crash_dir =
-      install_static::GetEnvironmentString16(L"BREAKPAD_DUMP_LOCATION");
+  *crash_dir = install_static::GetEnvironmentString(L"BREAKPAD_DUMP_LOCATION");
   return !crash_dir->empty();
 }
 
 void CefCrashReporterClient::GetProductNameAndVersion(
-    const base::string16& exe_path,
-    base::string16* product_name,
-    base::string16* version,
-    base::string16* special_build,
-    base::string16* channel_name) {
-  *product_name = base::ASCIIToUTF16(product_name_);
-  *version = base::ASCIIToUTF16(product_version_);
-  *special_build = base::string16();
-  *channel_name = base::string16();
+    const std::wstring& exe_path,
+    std::wstring* product_name,
+    std::wstring* version,
+    std::wstring* special_build,
+    std::wstring* channel_name) {
+  *product_name = base::ASCIIToWide(product_name_);
+  *version = base::ASCIIToWide(product_version_);
+  *special_build = std::wstring();
+  *channel_name = std::wstring();
 }
 
-bool CefCrashReporterClient::GetCrashDumpLocation(base::string16* crash_dir) {
+bool CefCrashReporterClient::GetCrashDumpLocation(std::wstring* crash_dir) {
   // By setting the BREAKPAD_DUMP_LOCATION environment variable, an alternate
   // location to write breakpad crash dumps can be set.
-  if (GetAlternativeCrashDumpLocation(crash_dir))
+  if (GetAlternativeCrashDumpLocation(crash_dir)) {
     return true;
+  }
 
-  return GetDefaultCrashDumpLocation(crash_dir, base::UTF8ToUTF16(app_name_));
+  return GetDefaultCrashDumpLocation(crash_dir, base::UTF8ToWide(app_name_));
 }
 
 bool CefCrashReporterClient::GetCrashMetricsLocation(
-    base::string16* metrics_dir) {
-  return GetDefaultUserDataDirectory(metrics_dir, base::UTF8ToUTF16(app_name_));
+    std::wstring* metrics_dir) {
+  return GetDefaultUserDataDirectory(metrics_dir, base::UTF8ToWide(app_name_));
 }
 
-#elif defined(OS_POSIX)
+#elif BUILDFLAG(IS_POSIX)
 
 void CefCrashReporterClient::GetProductNameAndVersion(const char** product_name,
                                                       const char** version) {
@@ -616,22 +652,6 @@
   *version = product_version_;
 }
 
-#if !defined(OS_MACOSX)
-
-base::FilePath CefCrashReporterClient::GetReporterLogFilename() {
-  return base::FilePath(FILE_PATH_LITERAL("uploads.log"));
-}
-
-bool CefCrashReporterClient::EnableBreakpadForProcess(
-    const std::string& process_type) {
-  return process_type == switches::kRendererProcess ||
-         process_type == switches::kPpapiPluginProcess ||
-         process_type == service_manager::switches::kZygoteProcess ||
-         process_type == switches::kGpuProcess;
-}
-
-#endif  // !defined(OS_MACOSX)
-
 bool CefCrashReporterClient::GetCrashDumpLocation(base::FilePath* crash_dir) {
   // By setting the BREAKPAD_DUMP_LOCATION environment variable, an alternate
   // location to write breakpad crash dumps can be set.
@@ -645,7 +665,7 @@
   return base::PathService::Get(chrome::DIR_CRASH_DUMPS, crash_dir);
 }
 
-#endif  // !defined(OS_POSIX)
+#endif  // !BUILDFLAG(IS_POSIX)
 
 bool CefCrashReporterClient::GetCollectStatsConsent() {
   return true;
@@ -655,23 +675,13 @@
   return true;
 }
 
-#if defined(OS_WIN) || defined(OS_MACOSX)
 bool CefCrashReporterClient::ReportingIsEnforcedByPolicy(
     bool* crashpad_enabled) {
   *crashpad_enabled = true;
   return true;
 }
-#endif
 
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-bool CefCrashReporterClient::IsRunningUnattended() {
-  // Crash upload will only be enabled with Breakpad on Linux if this method
-  // returns false.
-  return false;
-}
-#endif
-
-std::string CefCrashReporterClient::GetCrashServerURL() {
+std::string CefCrashReporterClient::GetUploadUrl() {
   return server_url_;
 }
 
@@ -679,8 +689,9 @@
 // for supported arguments.
 void CefCrashReporterClient::GetCrashOptionalArguments(
     std::vector<std::string>* arguments) {
-  if (!rate_limit_)
+  if (!rate_limit_) {
     arguments->push_back(std::string("--no-rate-limit"));
+  }
 
   if (max_uploads_ > 0) {
     arguments->push_back(std::string("--max-uploads=") +
@@ -698,37 +709,32 @@
   }
 }
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 
-base::string16 CefCrashReporterClient::GetCrashExternalHandler(
-    const base::string16& exe_dir) {
-  if (external_handler_.empty())
+std::wstring CefCrashReporterClient::GetCrashExternalHandler(
+    const std::wstring& exe_dir) {
+  if (external_handler_.empty()) {
     return CrashReporterClient::GetCrashExternalHandler(exe_dir);
-  if (isAbsolutePath(external_handler_))
-    return base::UTF8ToUTF16(external_handler_);
+  }
+  if (isAbsolutePath(external_handler_)) {
+    return base::UTF8ToWide(external_handler_);
+  }
   return base::UTF8ToWide(
-      joinPath(base::UTF16ToUTF8(exe_dir), external_handler_));
+      joinPath(base::WideToUTF8(exe_dir), external_handler_));
 }
 
 bool CefCrashReporterClient::HasCrashExternalHandler() const {
   return !external_handler_.empty();
 }
 
-#endif  // defined(OS_WIN)
+#endif  // BUILDFLAG(IS_WIN)
 
-#if defined(OS_MACOSX)
+#if BUILDFLAG(IS_MAC)
 bool CefCrashReporterClient::EnableBrowserCrashForwarding() {
   return enable_browser_crash_forwarding_;
 }
 #endif
 
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-CefCrashReporterClient::ParameterMap CefCrashReporterClient::FilterParameters(
-    const ParameterMap& parameters) {
-  return crash_report_utils::FilterParameters(parameters);
-}
-#endif
-
 // The new Crashpad Annotation API requires that annotations be declared using
 // static storage. We work around this limitation by defining a fixed amount of
 // storage for each key size and later substituting the actual key name during
@@ -752,7 +758,7 @@
   bool Set##name##Annotation(size_t index, const base::StringPiece& value) { \
     using IDKey = crash_reporter::CrashKeyString<size_>;                     \
     static IDKey ids[] = {IDKEY_ENTRIES(#name)};                             \
-    if (index < base::size(ids)) {                                           \
+    if (index < std::size(ids)) {                                            \
       if (value.empty()) {                                                   \
         ids[index].Clear();                                                  \
       } else {                                                               \
@@ -772,12 +778,14 @@
 
 bool CefCrashReporterClient::SetCrashKeyValue(const base::StringPiece& key,
                                               const base::StringPiece& value) {
-  if (key.empty() || crash_keys_.empty())
+  if (key.empty() || crash_keys_.empty()) {
     return false;
+  }
 
   KeyMap::const_iterator it = crash_keys_.find(NormalizeCrashKey(key));
-  if (it == crash_keys_.end())
+  if (it == crash_keys_.end()) {
     return false;
+  }
 
   const KeySize size = it->second.first;
   const size_t index = it->second.second;
diff --git a/src/libcef/common/crash_reporter_client.h b/src/libcef/common/crash_reporter_client.h
index fc4f5c2..cb804c3 100644
--- a/src/libcef/common/crash_reporter_client.h
+++ b/src/libcef/common/crash_reporter_client.h
@@ -8,12 +8,9 @@
 #include <string>
 #include <vector>
 
-// Include this first to avoid compiler errors.
-#include "base/compiler_specific.h"
-
 #include "include/cef_version.h"
 
-#include "base/macros.h"
+#include "base/strings/string_piece_forward.h"
 #include "base/synchronization/lock.h"
 #include "build/build_config.h"
 #include "components/crash/core/app/crash_reporter_client.h"
@@ -25,6 +22,10 @@
 class CefCrashReporterClient : public crash_reporter::CrashReporterClient {
  public:
   CefCrashReporterClient();
+
+  CefCrashReporterClient(const CefCrashReporterClient&) = delete;
+  CefCrashReporterClient& operator=(const CefCrashReporterClient&) = delete;
+
   ~CefCrashReporterClient() override;
 
   // Reads the crash config file and returns true on success. Failure to read
@@ -33,7 +34,7 @@
   bool ReadCrashConfigFile();
   bool HasCrashConfigFile() const;
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   // Called from chrome_elf (chrome_elf/crash/crash_helper.cc) to instantiate
   // a process wide instance of CefCrashReporterClient and initialize crash
   // reporting for the process. The instance is leaked.
@@ -42,55 +43,40 @@
   // the module address space.
   static void InitializeCrashReportingForProcess();
 
-  bool GetAlternativeCrashDumpLocation(base::string16* crash_dir) override;
-  void GetProductNameAndVersion(const base::string16& exe_path,
-                                base::string16* product_name,
-                                base::string16* version,
-                                base::string16* special_build,
-                                base::string16* channel_name) override;
-  bool GetCrashDumpLocation(base::string16* crash_dir) override;
-  bool GetCrashMetricsLocation(base::string16* metrics_dir) override;
-#elif defined(OS_POSIX)
+  bool GetAlternativeCrashDumpLocation(std::wstring* crash_dir) override;
+  void GetProductNameAndVersion(const std::wstring& exe_path,
+                                std::wstring* product_name,
+                                std::wstring* version,
+                                std::wstring* special_build,
+                                std::wstring* channel_name) override;
+  bool GetCrashDumpLocation(std::wstring* crash_dir) override;
+  bool GetCrashMetricsLocation(std::wstring* metrics_dir) override;
+#elif BUILDFLAG(IS_POSIX)
   void GetProductNameAndVersion(const char** product_name,
                                 const char** version) override;
   void GetProductNameAndVersion(std::string* product_name,
                                 std::string* version,
                                 std::string* channel) override;
-#if !defined(OS_MACOSX)
-  base::FilePath GetReporterLogFilename() override;
-  bool EnableBreakpadForProcess(const std::string& process_type) override;
-#endif
   bool GetCrashDumpLocation(base::FilePath* crash_dir) override;
-#endif  // defined(OS_POSIX)
+#endif  // BUILDFLAG(IS_POSIX)
 
   // All of these methods must return true to enable crash report upload.
   bool GetCollectStatsConsent() override;
   bool GetCollectStatsInSample() override;
-#if defined(OS_WIN) || defined(OS_MACOSX)
   bool ReportingIsEnforcedByPolicy(bool* crashpad_enabled) override;
-#endif
 
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-  bool IsRunningUnattended() override;
-#endif
-
-  std::string GetCrashServerURL() override;
+  std::string GetUploadUrl() override;
   void GetCrashOptionalArguments(std::vector<std::string>* arguments) override;
 
-#if defined(OS_WIN)
-  base::string16 GetCrashExternalHandler(
-      const base::string16& exe_dir) override;
+#if BUILDFLAG(IS_WIN)
+  std::wstring GetCrashExternalHandler(const std::wstring& exe_dir) override;
   bool HasCrashExternalHandler() const;
 #endif
 
-#if defined(OS_MACOSX)
+#if BUILDFLAG(IS_MAC)
   bool EnableBrowserCrashForwarding() override;
 #endif
 
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-  ParameterMap FilterParameters(const ParameterMap& parameters) override;
-#endif
-
   // Set or clear a crash key value.
   bool SetCrashKeyValue(const base::StringPiece& key,
                         const base::StringPiece& value);
@@ -117,16 +103,14 @@
   std::string product_name_ = "cef";
   std::string product_version_ = CEF_VERSION;
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   std::string app_name_ = "CEF";
   std::string external_handler_;
 #endif
 
-#if defined(OS_MACOSX)
+#if BUILDFLAG(IS_MAC)
   bool enable_browser_crash_forwarding_ = false;
 #endif
-
-  DISALLOW_COPY_AND_ASSIGN(CefCrashReporterClient);
 };
 
 #endif  // CEF_LIBCEF_COMMON_CRASH_REPORTER_CLIENT_H_
diff --git a/src/libcef/common/crash_reporting.cc b/src/libcef/common/crash_reporting.cc
index 0af03d4..9275058 100644
--- a/src/libcef/common/crash_reporting.cc
+++ b/src/libcef/common/crash_reporting.cc
@@ -6,10 +6,12 @@
 
 #include "include/cef_crash_util.h"
 #include "libcef/common/cef_switches.h"
+#include "libcef/features/runtime.h"
 
 #include "base/base_switches.h"
 #include "base/command_line.h"
 #include "base/debug/crash_logging.h"
+#include "base/logging.h"
 #include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
@@ -17,30 +19,24 @@
 #include "components/crash/core/common/crash_key.h"
 #include "components/crash/core/common/crash_keys.h"
 #include "content/public/common/content_switches.h"
-#include "services/service_manager/embedder/switches.h"
 
-#if defined(OS_MACOSX)
-#include "base/mac/foundation_util.h"
-#include "components/crash/core/app/crashpad.h"
+#if BUILDFLAG(IS_MAC)
+#include "base/apple/foundation_util.h"
 #include "components/crash/core/common/crash_keys.h"
 #include "content/public/common/content_paths.h"
 #endif
 
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
 #include "base/lazy_instance.h"
+#include "components/crash/core/app/crashpad.h"
 #include "libcef/common/crash_reporter_client.h"
 #endif
 
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-#include "components/crash/core/app/breakpad_linux.h"
-#include "v8/include/v8-wasm-trap-handler-posix.h"
-#endif
-
 namespace crash_reporting {
 
 namespace {
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 
 const base::FilePath::CharType kChromeElfDllName[] =
     FILE_PATH_LITERAL("chrome_elf.dll");
@@ -83,41 +79,42 @@
   return false;
 }
 
-#endif  // defined(OS_WIN)
+#endif  // BUILDFLAG(IS_WIN)
 
 bool g_crash_reporting_enabled = false;
 
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
 base::LazyInstance<CefCrashReporterClient>::Leaky g_crash_reporter_client =
     LAZY_INSTANCE_INITIALIZER;
 
 void InitCrashReporter(const base::CommandLine& command_line,
                        const std::string& process_type) {
   CefCrashReporterClient* crash_client = g_crash_reporter_client.Pointer();
-  if (!crash_client->HasCrashConfigFile())
+  if (!crash_client->HasCrashConfigFile()) {
     return;
+  }
 
   crash_reporter::SetCrashReporterClient(crash_client);
 
-#if defined(OS_MACOSX)
+#if BUILDFLAG(IS_MAC)
   // TODO(mark): Right now, InitializeCrashpad() needs to be called after
   // CommandLine::Init() and configuration of chrome::DIR_CRASH_DUMPS. Ideally,
   // Crashpad initialization could occur sooner, preferably even before the
   // framework dylib is even loaded, to catch potential early crashes.
   crash_reporter::InitializeCrashpad(process_type.empty(), process_type);
 
-  if (base::mac::AmIBundled()) {
+  if (base::apple::AmIBundled()) {
     // Mac Chrome is packaged with a main app bundle and a helper app bundle.
     // The main app bundle should only be used for the browser process, so it
     // should never see a --type switch (switches::kProcessType).  Likewise,
     // the helper should always have a --type switch.
     //
     // This check is done this late so there is already a call to
-    // base::mac::IsBackgroundOnlyProcess(), so there is no change in
+    // base::apple::IsBackgroundOnlyProcess(), so there is no change in
     // startup/initialization order.
 
     // The helper's Info.plist marks it as a background only app.
-    if (base::mac::IsBackgroundOnlyProcess()) {
+    if (base::apple::IsBackgroundOnlyProcess()) {
       CHECK(command_line.HasSwitch(switches::kProcessType) &&
             !process_type.empty())
           << "Helper application requires --type.";
@@ -129,24 +126,23 @@
   }
 
   g_crash_reporting_enabled = true;
-#else   // !defined(OS_MACOSX)
-  breakpad::SetCrashServerURL(crash_client->GetCrashServerURL());
-
-  if (process_type != service_manager::switches::kZygoteProcess) {
+#else   // !BUILDFLAG(IS_MAC)
+  if (process_type != switches::kZygoteProcess) {
     // Crash reporting for subprocesses created using the zygote will be
     // initialized in ZygoteForked.
-    breakpad::InitCrashReporter(process_type);
+    crash_reporter::InitializeCrashpad(process_type.empty(), process_type);
 
     g_crash_reporting_enabled = true;
   }
-#endif  // !defined(OS_MACOSX)
+#endif  // !BUILDFLAG(IS_MAC)
 }
-#endif  // defined(OS_POSIX)
+#endif  // BUILDFLAG(IS_POSIX)
 
 // Used to exclude command-line flags from crash reporting.
 bool IsBoringCEFSwitch(const std::string& flag) {
-  if (crash_keys::IsBoringChromeSwitch(flag))
+  if (crash_keys::IsBoringChromeSwitch(flag)) {
     return true;
+  }
 
   static const char* const kIgnoreSwitches[] = {
       // CEF internals.
@@ -160,14 +156,16 @@
       "service-request-channel-token",
   };
 
-  if (!base::StartsWith(flag, "--", base::CompareCase::SENSITIVE))
+  if (!base::StartsWith(flag, "--", base::CompareCase::SENSITIVE)) {
     return false;
+  }
 
   size_t end = flag.find("=");
   size_t len = (end == std::string::npos) ? flag.length() - 2 : end - 2;
-  for (size_t i = 0; i < base::size(kIgnoreSwitches); ++i) {
-    if (flag.compare(2, len, kIgnoreSwitches[i]) == 0)
+  for (size_t i = 0; i < std::size(kIgnoreSwitches); ++i) {
+    if (flag.compare(2, len, kIgnoreSwitches[i]) == 0) {
       return true;
+    }
   }
   return false;
 }
@@ -180,26 +178,25 @@
 
 bool SetCrashKeyValue(const base::StringPiece& key,
                       const base::StringPiece& value) {
-  if (!g_crash_reporting_enabled)
+  if (!g_crash_reporting_enabled) {
     return false;
+  }
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   return SetCrashKeyValueTrampoline(key, value);
 #else
   return g_crash_reporter_client.Pointer()->SetCrashKeyValue(key, value);
 #endif
 }
 
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
 // Be aware that logging is not initialized at the time this method is called.
 void BasicStartupComplete(base::CommandLine* command_line) {
   CefCrashReporterClient* crash_client = g_crash_reporter_client.Pointer();
   if (crash_client->ReadCrashConfigFile()) {
-#if !defined(OS_MACOSX)
-    // Breakpad requires this switch.
-    command_line->AppendSwitch(switches::kEnableCrashReporter);
-
-    breakpad::SetFirstChanceExceptionHandler(v8::TryHandleWebAssemblyTrapPosix);
+#if !BUILDFLAG(IS_MAC)
+    // Crashpad requires this switch on Linux.
+    command_line->AppendSwitch(switches::kEnableCrashpad);
 #endif
   }
 }
@@ -207,11 +204,11 @@
 
 void PreSandboxStartup(const base::CommandLine& command_line,
                        const std::string& process_type) {
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
   // Initialize crash reporting here on macOS and Linux. Crash reporting on
   // Windows is initialized from context.cc.
   InitCrashReporter(command_line, process_type);
-#elif defined(OS_WIN)
+#elif BUILDFLAG(IS_WIN)
   g_crash_reporting_enabled = IsCrashReportingEnabledTrampoline();
 #endif
 
@@ -227,13 +224,13 @@
   crash_keys::SetSwitchesFromCommandLine(command_line, &IsBoringCEFSwitch);
 }
 
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_MAC)
 void ZygoteForked(base::CommandLine* command_line,
                   const std::string& process_type) {
   CefCrashReporterClient* crash_client = g_crash_reporter_client.Pointer();
   if (crash_client->HasCrashConfigFile()) {
-    // Breakpad requires this switch.
-    command_line->AppendSwitch(switches::kEnableCrashReporter);
+    // Crashpad requires this switch on Linux.
+    command_line->AppendSwitch(switches::kEnableCrashpad);
   }
 
   InitCrashReporter(*command_line, process_type);
@@ -259,3 +256,12 @@
                  << " with value: " << value.ToString();
   }
 }
+
+// From libcef/features/runtime.h:
+namespace cef {
+
+bool IsCrashReportingEnabled() {
+  return crash_reporting::Enabled();
+}
+
+}  // namespace cef
diff --git a/src/libcef/common/crash_reporting.h b/src/libcef/common/crash_reporting.h
index ab0dad2..38fcd57 100644
--- a/src/libcef/common/crash_reporting.h
+++ b/src/libcef/common/crash_reporting.h
@@ -20,16 +20,16 @@
 bool SetCrashKeyValue(const base::StringPiece& key,
                       const base::StringPiece& value);
 
-// Functions are called from similarly named methods in CefMainDelegate.
+// Functions are called from similarly named methods in AlloyMainDelegate.
 
-#if defined(OS_POSIX)
+#if BUILDFLAG(IS_POSIX)
 void BasicStartupComplete(base::CommandLine* command_line);
 #endif
 
 void PreSandboxStartup(const base::CommandLine& command_line,
                        const std::string& process_type);
 
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_MAC)
 void ZygoteForked(base::CommandLine* command_line,
                   const std::string& process_type);
 #endif
diff --git a/src/libcef/common/drag_data_impl.cc b/src/libcef/common/drag_data_impl.cc
index 1b9eeda..f294749 100644
--- a/src/libcef/common/drag_data_impl.cc
+++ b/src/libcef/common/drag_data_impl.cc
@@ -8,10 +8,10 @@
 #include "libcef/browser/stream_impl.h"
 #include "libcef/common/drag_data_impl.h"
 
-#define CHECK_READONLY_RETURN_VOID()       \
-  if (read_only_) {                        \
-    NOTREACHED() << "object is read only"; \
-    return;                                \
+#define CHECK_READONLY_RETURN_VOID()        \
+  if (read_only_) {                         \
+    DCHECK(false) << "object is read only"; \
+    return;                                 \
   }
 
 CefDragDataImpl::CefDragDataImpl(const content::DropData& data)
@@ -81,12 +81,12 @@
 
 CefString CefDragDataImpl::GetFragmentText() {
   base::AutoLock lock_scope(lock_);
-  return data_.text.is_null() ? CefString() : CefString(data_.text.string());
+  return data_.text ? CefString(*data_.text) : CefString();
 }
 
 CefString CefDragDataImpl::GetFragmentHtml() {
   base::AutoLock lock_scope(lock_);
-  return data_.html.is_null() ? CefString() : CefString(data_.html.string());
+  return data_.html ? CefString(*data_.html) : CefString();
 }
 
 CefString CefDragDataImpl::GetFragmentBaseURL() {
@@ -96,33 +96,55 @@
 
 CefString CefDragDataImpl::GetFileName() {
   base::AutoLock lock_scope(lock_);
-  base::Optional<base::FilePath> filename =
-      data_.GetSafeFilenameForImageFileContents();
+  auto filename = data_.GetSafeFilenameForImageFileContents();
   return filename ? CefString(filename->value()) : CefString();
 }
 
 size_t CefDragDataImpl::GetFileContents(CefRefPtr<CefStreamWriter> writer) {
   base::AutoLock lock_scope(lock_);
-  if (data_.file_contents.empty())
+  if (data_.file_contents.empty()) {
     return 0;
+  }
 
   char* data = const_cast<char*>(data_.file_contents.c_str());
   size_t size = data_.file_contents.size();
 
-  if (!writer.get())
+  if (!writer.get()) {
     return size;
+  }
 
   return writer->Write(data, 1, size);
 }
 
 bool CefDragDataImpl::GetFileNames(std::vector<CefString>& names) {
   base::AutoLock lock_scope(lock_);
-  if (data_.filenames.empty())
+  if (data_.filenames.empty()) {
     return false;
+  }
 
   std::vector<ui::FileInfo>::const_iterator it = data_.filenames.begin();
-  for (; it != data_.filenames.end(); ++it)
-    names.push_back(it->path.value());
+  for (; it != data_.filenames.end(); ++it) {
+    auto name = it->display_name.value();
+    if (name.empty()) {
+      name = it->path.BaseName().value();
+    }
+    names.push_back(name);
+  }
+
+  return true;
+}
+
+bool CefDragDataImpl::GetFilePaths(std::vector<CefString>& paths) {
+  base::AutoLock lock_scope(lock_);
+  if (data_.filenames.empty()) {
+    return false;
+  }
+
+  std::vector<ui::FileInfo>::const_iterator it = data_.filenames.begin();
+  for (; it != data_.filenames.end(); ++it) {
+    auto path = it->path.value();
+    paths.push_back(path);
+  }
 
   return true;
 }
@@ -148,13 +170,13 @@
 void CefDragDataImpl::SetFragmentText(const CefString& text) {
   base::AutoLock lock_scope(lock_);
   CHECK_READONLY_RETURN_VOID();
-  data_.text = base::NullableString16(text.ToString16(), false);
+  data_.text = text.ToString16();
 }
 
 void CefDragDataImpl::SetFragmentHtml(const CefString& fragment) {
   base::AutoLock lock_scope(lock_);
   CHECK_READONLY_RETURN_VOID();
-  data_.html = base::NullableString16(fragment.ToString16(), false);
+  data_.html = fragment.ToString16();
 }
 
 void CefDragDataImpl::SetFragmentBaseURL(const CefString& fragment) {
@@ -180,10 +202,16 @@
       ui::FileInfo(base::FilePath(path), base::FilePath(display_name)));
 }
 
+void CefDragDataImpl::ClearFilenames() {
+  base::AutoLock lock_scope(lock_);
+  data_.filenames.clear();
+}
+
 void CefDragDataImpl::SetReadOnly(bool read_only) {
   base::AutoLock lock_scope(lock_);
-  if (read_only_ == read_only)
+  if (read_only_ == read_only) {
     return;
+  }
 
   read_only_ = read_only;
 }
diff --git a/src/libcef/common/drag_data_impl.h b/src/libcef/common/drag_data_impl.h
index c44f83c..0f16c30 100644
--- a/src/libcef/common/drag_data_impl.h
+++ b/src/libcef/common/drag_data_impl.h
@@ -37,6 +37,7 @@
   CefString GetFileName() override;
   size_t GetFileContents(CefRefPtr<CefStreamWriter> writer) override;
   bool GetFileNames(std::vector<CefString>& names) override;
+  bool GetFilePaths(std::vector<CefString>& paths) override;
   void SetLinkURL(const CefString& url) override;
   void SetLinkTitle(const CefString& title) override;
   void SetLinkMetadata(const CefString& data) override;
@@ -45,6 +46,7 @@
   void SetFragmentBaseURL(const CefString& fragment) override;
   void ResetFileContents() override;
   void AddFile(const CefString& path, const CefString& display_name) override;
+  void ClearFilenames() override;
   CefRefPtr<CefImage> GetImage() override;
   CefPoint GetImageHotspot() override;
   bool HasImage() override;
diff --git a/src/libcef/common/extensions/api/BUILD.gn b/src/libcef/common/extensions/api/BUILD.gn
index bb9ebc4..aa2a1a4 100644
--- a/src/libcef/common/extensions/api/BUILD.gn
+++ b/src/libcef/common/extensions/api/BUILD.gn
@@ -3,41 +3,6 @@
 # governed by a BSD-style license that can be found in the LICENSE file.
 
 import("//tools/json_schema_compiler/json_features.gni")
-#import("//tools/json_schema_compiler/json_schema_api.gni")
-
-# TODO(cef): Enable if/when CEF exposes its own Mojo APIs. See README.txt for
-# details.
-#schema_sources = [
-#  # TODO(cef): Add CEF-specific Mojo APIs here.
-#]
-#
-#uncompiled_sources = [
-#]
-#
-#root_namespace = "extensions::api::cef::%(namespace)s"
-#schema_include_rules = "//cef/libcef/browser/extensions/api:extensions::api::cef::%(namespace)s"
-#schema_dependencies = [ "//extensions/common/api" ]
-#
-#generated_json_strings("api") {
-#  sources = schema_sources
-#  schemas = true
-#  configs = [ "//build/config:precompiled_headers" ]
-#  bundle_name = "Cef"
-#
-#  deps = schema_dependencies
-#}
-#
-#function_registration("api_registration") {
-#  sources = schema_sources
-#  impl_dir = "//cef/libcef/browser/extensions/api"
-#  configs = [ "//build/config:precompiled_headers" ]
-#  bundle_name = "Cef"
-#
-#  deps = [
-#    ":api",
-#  ]
-#  deps += schema_dependencies
-#}
 
 json_features("cef_api_features") {
   feature_type = "APIFeature"
diff --git a/src/libcef/common/extensions/api/README.txt b/src/libcef/common/extensions/api/README.txt
index 0fbbc8d..5e423e7 100644
--- a/src/libcef/common/extensions/api/README.txt
+++ b/src/libcef/common/extensions/api/README.txt
@@ -22,7 +22,7 @@
    files if necessary [2].
 7. Call `<class>::GetInstance();` or `<class>Factory::GetFactoryInstance();` [3]
    from EnsureBrowserContextKeyedServiceFactoriesBuilt in
-   libcef/browser/extensions/browser_context_keyed_service_factories.cc.
+   libcef/browser/browser_context_keyed_service_factories.cc.
 8. Call `DependsOn(<class>Factory::GetInstance());` from
    CefExtensionSystemFactory::CefExtensionSystemFactory in
    libcef/browser/extensions/extension_system_factory.cc if necessary [3].
diff --git a/src/libcef/common/extensions/api/_api_features.json b/src/libcef/common/extensions/api/_api_features.json
index 551fe28..db253cf 100644
--- a/src/libcef/common/extensions/api/_api_features.json
+++ b/src/libcef/common/extensions/api/_api_features.json
@@ -22,6 +22,10 @@
     "channel": "stable",
     "matches": ["<all_urls>"]
   },
+  "pdfViewerPrivate": {
+    "dependencies": ["permission:pdfViewerPrivate"],
+    "contexts": ["blessed_extension"]
+  },
   "resourcesPrivate": [
     {
       "dependencies": ["permission:resourcesPrivate"],
diff --git a/src/libcef/common/extensions/api/_permission_features.json b/src/libcef/common/extensions/api/_permission_features.json
index 54458e0..96013ad 100644
--- a/src/libcef/common/extensions/api/_permission_features.json
+++ b/src/libcef/common/extensions/api/_permission_features.json
@@ -16,6 +16,13 @@
     "channel": "stable",
     "extension_types": ["extension", "legacy_packaged_app"]
   },
+  "pdfViewerPrivate": {
+    "channel": "stable",
+    "extension_types": ["extension"],
+    "allowlist": [
+      "CBCC42ABED43A4B58FE3810E62AFFA010EB0349F"  // PDF Viewer
+    ]
+  },
   "resourcesPrivate": {
     "channel": "stable",
     "extension_types": [
@@ -30,12 +37,7 @@
     },
     {
       "channel": "stable",
-      "extension_types": ["platform_app"],
-      "whitelist": [
-        "AE27D69DBE571F4B1694F05C89B710C646792231", // Published ADT.
-        // TODO(grv): clean up once Apps developer tool is published.
-        "5107DE9024C329EEA9C9A72D94C16723790C6422"  // Apps Developer Tool.
-      ]
+      "extension_types": ["platform_app"]
     }
   ]
 }
diff --git a/src/libcef/common/extensions/chrome_generated_schemas.cc b/src/libcef/common/extensions/chrome_generated_schemas.cc
index cf7dc86..a89519c 100644
--- a/src/libcef/common/extensions/chrome_generated_schemas.cc
+++ b/src/libcef/common/extensions/chrome_generated_schemas.cc
@@ -6,7 +6,6 @@
 
 #include "libcef/browser/extensions/chrome_api_registration.h"
 
-#include "base/macros.h"
 #include "chrome/common/extensions/api/generated_schemas.h"
 
 namespace extensions {
@@ -15,15 +14,17 @@
 
 // static
 base::StringPiece ChromeGeneratedSchemas::Get(const std::string& name) {
-  if (!ChromeFunctionRegistry::IsSupported(name))
+  if (!ChromeFunctionRegistry::IsSupported(name)) {
     return base::StringPiece();
+  }
   return extensions::api::ChromeGeneratedSchemas::Get(name);
 }
 
 // static
 bool ChromeGeneratedSchemas::IsGenerated(std::string name) {
-  if (!ChromeFunctionRegistry::IsSupported(name))
+  if (!ChromeFunctionRegistry::IsSupported(name)) {
     return false;
+  }
   return extensions::api::ChromeGeneratedSchemas::IsGenerated(name);
 }
 
diff --git a/src/libcef/common/extensions/extensions_api_provider.cc b/src/libcef/common/extensions/extensions_api_provider.cc
index 64df67c..eb37673 100644
--- a/src/libcef/common/extensions/extensions_api_provider.cc
+++ b/src/libcef/common/extensions/extensions_api_provider.cc
@@ -7,7 +7,7 @@
 #include "libcef/common/extensions/chrome_generated_schemas.h"
 
 #include "cef/grit/cef_resources.h"
-//#include "cef/libcef/common/extensions/api/generated_schemas.h"
+// #include "cef/libcef/common/extensions/api/generated_schemas.h"
 #include "cef/libcef/common/extensions/api/cef_api_features.h"
 #include "cef/libcef/common/extensions/api/cef_manifest_features.h"
 #include "cef/libcef/common/extensions/api/cef_permission_features.h"
@@ -52,8 +52,9 @@
   //   return true;
 
   // Chrome APIs whitelisted by CEF.
-  if (api::cef::ChromeGeneratedSchemas::IsGenerated(name))
+  if (api::cef::ChromeGeneratedSchemas::IsGenerated(name)) {
     return true;
+  }
 
   return false;
 }
@@ -67,8 +68,9 @@
   //   return api::cef::CefGeneratedSchemas::Get(name);
 
   // Chrome APIs whitelisted by CEF.
-  if (api::cef::ChromeGeneratedSchemas::IsGenerated(name))
+  if (api::cef::ChromeGeneratedSchemas::IsGenerated(name)) {
     return api::cef::ChromeGeneratedSchemas::Get(name);
+  }
 
   return base::StringPiece();
 }
diff --git a/src/libcef/common/extensions/extensions_api_provider.h b/src/libcef/common/extensions/extensions_api_provider.h
index 805e18a..106b3cc 100644
--- a/src/libcef/common/extensions/extensions_api_provider.h
+++ b/src/libcef/common/extensions/extensions_api_provider.h
@@ -5,7 +5,6 @@
 #ifndef CEF_LIBCEF_COMMON_EXTENSIONS_EXTENSIONS_API_PROVIDER_H_
 #define CEF_LIBCEF_COMMON_EXTENSIONS_EXTENSIONS_API_PROVIDER_H_
 
-#include "base/macros.h"
 #include "extensions/common/extensions_api_provider.h"
 
 namespace extensions {
@@ -14,6 +13,9 @@
  public:
   CefExtensionsAPIProvider();
 
+  CefExtensionsAPIProvider(const CefExtensionsAPIProvider&) = delete;
+  CefExtensionsAPIProvider& operator=(const CefExtensionsAPIProvider&) = delete;
+
   // ExtensionsAPIProvider:
   void AddAPIFeatures(FeatureProvider* provider) override;
   void AddManifestFeatures(FeatureProvider* provider) override;
@@ -24,9 +26,6 @@
   base::StringPiece GetAPISchema(const std::string& name) override;
   void RegisterPermissions(PermissionsInfo* permissions_info) override;
   void RegisterManifestHandlers() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefExtensionsAPIProvider);
 };
 
 }  // namespace extensions
diff --git a/src/libcef/common/extensions/extensions_client.cc b/src/libcef/common/extensions/extensions_client.cc
index b62c0d5..dfac522 100644
--- a/src/libcef/common/extensions/extensions_client.cc
+++ b/src/libcef/common/extensions/extensions_client.cc
@@ -30,6 +30,7 @@
 
 CefExtensionsClient::CefExtensionsClient()
     : webstore_base_url_(extension_urls::kChromeWebstoreBaseURL),
+      new_webstore_base_url_(extension_urls::kNewChromeWebstoreBaseURL),
       webstore_update_url_(extension_urls::kChromeWebstoreUpdateURL) {
   AddAPIProvider(std::make_unique<CoreExtensionsAPIProvider>());
   AddAPIProvider(std::make_unique<CefExtensionsAPIProvider>());
@@ -58,15 +59,15 @@
   NOTIMPLEMENTED();
 }
 
-void CefExtensionsClient::SetScriptingWhitelist(
-    const ScriptingWhitelist& whitelist) {
-  scripting_whitelist_ = whitelist;
+void CefExtensionsClient::SetScriptingAllowlist(
+    const ScriptingAllowlist& allowlist) {
+  scripting_allowlist_ = allowlist;
 }
 
-const ExtensionsClient::ScriptingWhitelist&
-CefExtensionsClient::GetScriptingWhitelist() const {
-  // TODO(jamescook): Real whitelist.
-  return scripting_whitelist_;
+const ExtensionsClient::ScriptingAllowlist&
+CefExtensionsClient::GetScriptingAllowlist() const {
+  // TODO(jamescook): Real allowlist.
+  return scripting_allowlist_;
 }
 
 URLPatternSet CefExtensionsClient::GetPermittedChromeSchemeHosts(
@@ -84,13 +85,17 @@
   return webstore_base_url_;
 }
 
+const GURL& CefExtensionsClient::GetNewWebstoreBaseURL() const {
+  return new_webstore_base_url_;
+}
+
 const GURL& CefExtensionsClient::GetWebstoreUpdateURL() const {
   return webstore_update_url_;
 }
 
-bool CefExtensionsClient::IsBlacklistUpdateURL(const GURL& url) const {
+bool CefExtensionsClient::IsBlocklistUpdateURL(const GURL& url) const {
   // TODO(rockot): Maybe we want to do something else here. For now we accept
-  // any URL as a blacklist URL because we don't really care.
+  // any URL as a blocklist URL because we don't really care.
   return true;
 }
 
diff --git a/src/libcef/common/extensions/extensions_client.h b/src/libcef/common/extensions/extensions_client.h
index a1fd438..7caf763 100644
--- a/src/libcef/common/extensions/extensions_client.h
+++ b/src/libcef/common/extensions/extensions_client.h
@@ -6,8 +6,6 @@
 #ifndef CEF_LIBCEF_COMMON_EXTENSIONS_EXTENSIONS_CLIENT_H_
 #define CEF_LIBCEF_COMMON_EXTENSIONS_EXTENSIONS_CLIENT_H_
 
-#include "base/compiler_specific.h"
-#include "base/macros.h"
 #include "chrome/common/extensions/permissions/chrome_permission_message_provider.h"
 #include "extensions/common/extensions_client.h"
 #include "url/gurl.h"
@@ -18,6 +16,10 @@
 class CefExtensionsClient : public ExtensionsClient {
  public:
   CefExtensionsClient();
+
+  CefExtensionsClient(const CefExtensionsClient&) = delete;
+  CefExtensionsClient& operator=(const CefExtensionsClient&) = delete;
+
   ~CefExtensionsClient() override;
 
   // ExtensionsClient overrides:
@@ -29,26 +31,26 @@
   void FilterHostPermissions(const URLPatternSet& hosts,
                              URLPatternSet* new_hosts,
                              PermissionIDSet* permissions) const override;
-  void SetScriptingWhitelist(const ScriptingWhitelist& whitelist) override;
-  const ScriptingWhitelist& GetScriptingWhitelist() const override;
+  void SetScriptingAllowlist(const ScriptingAllowlist& allowlist) override;
+  const ScriptingAllowlist& GetScriptingAllowlist() const override;
   URLPatternSet GetPermittedChromeSchemeHosts(
       const Extension* extension,
       const APIPermissionSet& api_permissions) const override;
   bool IsScriptableURL(const GURL& url, std::string* error) const override;
   const GURL& GetWebstoreBaseURL() const override;
+  const GURL& GetNewWebstoreBaseURL() const override;
   const GURL& GetWebstoreUpdateURL() const override;
-  bool IsBlacklistUpdateURL(const GURL& url) const override;
+  bool IsBlocklistUpdateURL(const GURL& url) const override;
 
  private:
   const ChromePermissionMessageProvider permission_message_provider_;
 
-  ScriptingWhitelist scripting_whitelist_;
+  ScriptingAllowlist scripting_allowlist_;
 
   // Mutable to allow caching in a const method.
   const GURL webstore_base_url_;
+  const GURL new_webstore_base_url_;
   const GURL webstore_update_url_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefExtensionsClient);
 };
 
 }  // namespace extensions
diff --git a/src/libcef/common/extensions/extensions_util.cc b/src/libcef/common/extensions/extensions_util.cc
index 74f0ad8..f126530 100644
--- a/src/libcef/common/extensions/extensions_util.cc
+++ b/src/libcef/common/extensions/extensions_util.cc
@@ -25,12 +25,13 @@
 }
 
 bool PrintPreviewEnabled() {
-#if defined(OS_MACOSX)
+#if BUILDFLAG(IS_MAC)
   // Not currently supported on macOS.
   return false;
 #else
-  if (!PdfExtensionEnabled())
+  if (!PdfExtensionEnabled()) {
     return false;
+  }
 
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kDisablePrintPreview)) {
diff --git a/src/libcef/common/file_util_impl.cc b/src/libcef/common/file_util_impl.cc
index 3f97c75..48387ba 100644
--- a/src/libcef/common/file_util_impl.cc
+++ b/src/libcef/common/file_util_impl.cc
@@ -15,7 +15,7 @@
 
 bool AllowFileIO() {
   if (CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO)) {
-    NOTREACHED() << "file IO is not allowed on the current thread";
+    DCHECK(false) << "file IO is not allowed on the current thread";
     return false;
   }
   return true;
@@ -24,14 +24,16 @@
 }  // namespace
 
 bool CefCreateDirectory(const CefString& full_path) {
-  if (!AllowFileIO())
+  if (!AllowFileIO()) {
     return false;
+  }
   return base::CreateDirectory(full_path);
 }
 
 bool CefGetTempDirectory(CefString& temp_dir) {
-  if (!AllowFileIO())
+  if (!AllowFileIO()) {
     return false;
+  }
   base::FilePath result;
   if (base::GetTempDir(&result)) {
     temp_dir = result.value();
@@ -42,8 +44,9 @@
 
 bool CefCreateNewTempDirectory(const CefString& prefix,
                                CefString& new_temp_path) {
-  if (!AllowFileIO())
+  if (!AllowFileIO()) {
     return false;
+  }
   base::FilePath result;
   if (base::CreateNewTempDirectory(prefix, &result)) {
     new_temp_path = result.value();
@@ -55,8 +58,9 @@
 bool CefCreateTempDirectoryInDirectory(const CefString& base_dir,
                                        const CefString& prefix,
                                        CefString& new_dir) {
-  if (!AllowFileIO())
+  if (!AllowFileIO()) {
     return false;
+  }
   base::FilePath result;
   if (base::CreateTemporaryDirInDir(base_dir, prefix, &result)) {
     new_dir = result.value();
@@ -66,21 +70,28 @@
 }
 
 bool CefDirectoryExists(const CefString& path) {
-  if (!AllowFileIO())
+  if (!AllowFileIO()) {
     return false;
+  }
   return base::DirectoryExists(path);
 }
 
 bool CefDeleteFile(const CefString& path, bool recursive) {
-  if (!AllowFileIO())
+  if (!AllowFileIO()) {
     return false;
-  return base::DeleteFile(path, recursive);
+  }
+  if (recursive) {
+    return base::DeletePathRecursively(path);
+  } else {
+    return base::DeleteFile(path);
+  }
 }
 
 bool CefZipDirectory(const CefString& src_dir,
                      const CefString& dest_file,
                      bool include_hidden_files) {
-  if (!AllowFileIO())
+  if (!AllowFileIO()) {
     return false;
+  }
   return zip::Zip(src_dir, dest_file, include_hidden_files);
 }
diff --git a/src/libcef/common/frame_util.cc b/src/libcef/common/frame_util.cc
index 2671329..0ed3d03 100644
--- a/src/libcef/common/frame_util.cc
+++ b/src/libcef/common/frame_util.cc
@@ -4,11 +4,36 @@
 
 #include "libcef/common/frame_util.h"
 
+#include "libcef/browser/thread_util.h"
+
+#include <limits>
+#include <sstream>
+
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
+
 namespace frame_util {
 
-int64_t MakeFrameId(int32_t render_process_id, int32_t render_routing_id) {
-  return (static_cast<uint64_t>(render_process_id) << 32) |
-         static_cast<uint64_t>(render_routing_id);
+content::GlobalRenderFrameHostId GetGlobalId(
+    content::NavigationHandle* navigation_handle) {
+  CEF_REQUIRE_UIT();
+  return navigation_handle->HasCommitted()
+             ? navigation_handle->GetRenderFrameHost()->GetGlobalId()
+             : navigation_handle->GetPreviousRenderFrameHostId();
+}
+
+std::string GetFrameDebugString(int64_t frame_id) {
+  uint32_t process_id = frame_id >> 32;
+  uint32_t routing_id = std::numeric_limits<uint32_t>::max() & frame_id;
+
+  std::stringstream ss;
+  ss << frame_id << " [" << process_id << "," << routing_id << "]";
+  return ss.str();
+}
+
+std::string GetFrameDebugString(
+    const content::GlobalRenderFrameHostId& global_id) {
+  return GetFrameDebugString(MakeFrameId(global_id));
 }
 
 }  // namespace frame_util
diff --git a/src/libcef/common/frame_util.h b/src/libcef/common/frame_util.h
index 7ca5d7b..7aeedbf 100644
--- a/src/libcef/common/frame_util.h
+++ b/src/libcef/common/frame_util.h
@@ -6,12 +6,78 @@
 #define CEF_LIBCEF_COMMON_FRAME_UTIL_H_
 
 #include <stdint.h>
+#include <string>
+
+#include "base/logging.h"
+#include "content/public/browser/child_process_host.h"
+#include "content/public/browser/global_routing_id.h"
+
+namespace content {
+class NavigationHandle;
+}
 
 namespace frame_util {
 
-// Returns the frame ID, which is a 64-bit combination of |render_process_id|
-// and |render_routing_id|.
-int64_t MakeFrameId(int32_t render_process_id, int32_t render_routing_id);
+// Create a frame ID in the format exposed by the CEF API.
+inline int64_t MakeFrameId(int child_id, int frame_routing_id) {
+  return (static_cast<uint64_t>(child_id) << 32) |
+         static_cast<uint64_t>(frame_routing_id);
+}
+
+// Create a frame ID in the format exposed by the CEF API.
+inline int64_t MakeFrameId(const content::GlobalRenderFrameHostId& global_id) {
+  return MakeFrameId(global_id.child_id, global_id.frame_routing_id);
+}
+
+// Returns true if |child_id| is valid.
+inline bool IsValidChildId(int child_id) {
+  // See comments in ChildProcessHostImpl::GenerateChildProcessUniqueId().
+  return child_id != content::ChildProcessHost::kInvalidUniqueID &&
+         child_id != 0;
+}
+
+// Returns true if |frame_routing_id| is valid.
+inline bool IsValidRoutingId(int frame_routing_id) {
+  return frame_routing_id != MSG_ROUTING_NONE;
+}
+
+// Returns true if |global_id| is valid.
+inline bool IsValidGlobalId(const content::GlobalRenderFrameHostId& global_id) {
+  return IsValidChildId(global_id.child_id) &&
+         IsValidRoutingId(global_id.frame_routing_id);
+}
+
+// Create a global ID from components.
+inline content::GlobalRenderFrameHostId MakeGlobalId(
+    int child_id,
+    int frame_routing_id,
+    bool allow_invalid_frame_id = false) {
+  DCHECK(IsValidChildId(child_id));
+  DCHECK(allow_invalid_frame_id || IsValidRoutingId(frame_routing_id));
+  return content::GlobalRenderFrameHostId(child_id, frame_routing_id);
+}
+
+// Create a global ID from a frame ID.
+inline content::GlobalRenderFrameHostId MakeGlobalId(int64_t frame_id) {
+  uint32_t child_id = frame_id >> 32;
+  uint32_t frame_routing_id = std::numeric_limits<uint32_t>::max() & frame_id;
+  return MakeGlobalId(child_id, frame_routing_id);
+}
+
+// Returns an invalid global ID value.
+inline content::GlobalRenderFrameHostId InvalidGlobalId() {
+  return content::GlobalRenderFrameHostId();
+}
+
+// Returns the best match of global ID for |navigation_handle|. For pre-commit
+// navigations this will return the current RFH, if any, or an invalid ID.
+content::GlobalRenderFrameHostId GetGlobalId(
+    content::NavigationHandle* navigation_handle);
+
+// Returns a human-readable version of the ID.
+std::string GetFrameDebugString(int64_t frame_id);
+std::string GetFrameDebugString(
+    const content::GlobalRenderFrameHostId& global_id);
 
 }  // namespace frame_util
 
diff --git a/src/libcef/common/i18n_util_impl.cc b/src/libcef/common/i18n_util_impl.cc
new file mode 100644
index 0000000..b4f901b
--- /dev/null
+++ b/src/libcef/common/i18n_util_impl.cc
@@ -0,0 +1,11 @@
+// Copyright 2021 The Chromium Embedded Framework 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 "include/cef_i18n_util.h"
+
+#include "base/i18n/rtl.h"
+
+bool CefIsRTL() {
+  return base::i18n::IsRTL();
+}
diff --git a/src/libcef/common/json_impl.cc b/src/libcef/common/json_impl.cc
index d4cf45e..1b5dca7 100644
--- a/src/libcef/common/json_impl.cc
+++ b/src/libcef/common/json_impl.cc
@@ -13,19 +13,23 @@
 
 int GetJSONReaderOptions(cef_json_parser_options_t options) {
   int op = base::JSON_PARSE_RFC;
-  if (options & JSON_PARSER_ALLOW_TRAILING_COMMAS)
+  if (options & JSON_PARSER_ALLOW_TRAILING_COMMAS) {
     op |= base::JSON_ALLOW_TRAILING_COMMAS;
+  }
   return op;
 }
 
 int GetJSONWriterOptions(cef_json_writer_options_t options) {
   int op = 0;
-  if (options & JSON_WRITER_OMIT_BINARY_VALUES)
+  if (options & JSON_WRITER_OMIT_BINARY_VALUES) {
     op |= base::JSONWriter::OPTIONS_OMIT_BINARY_VALUES;
-  if (options & JSON_WRITER_OMIT_DOUBLE_TYPE_PRESERVATION)
+  }
+  if (options & JSON_WRITER_OMIT_DOUBLE_TYPE_PRESERVATION) {
     op |= base::JSONWriter::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION;
-  if (options & JSON_WRITER_PRETTY_PRINT)
+  }
+  if (options & JSON_WRITER_PRETTY_PRINT) {
     op |= base::JSONWriter::OPTIONS_PRETTY_PRINT;
+  }
   return op;
 }
 
@@ -40,15 +44,14 @@
 CefRefPtr<CefValue> CefParseJSON(const void* json,
                                  size_t json_size,
                                  cef_json_parser_options_t options) {
-  if (!json || json_size == 0)
+  if (!json || json_size == 0) {
     return nullptr;
-  base::Optional<base::Value> parse_result = base::JSONReader::Read(
+  }
+  absl::optional<base::Value> parse_result = base::JSONReader::Read(
       base::StringPiece(static_cast<const char*>(json), json_size),
       GetJSONReaderOptions(options));
   if (parse_result) {
-    return new CefValueImpl(
-        base::Value::ToUniquePtrValue(std::move(parse_result.value()))
-            .release());
+    return new CefValueImpl(std::move(parse_result.value()));
   }
   return nullptr;
 }
@@ -56,30 +59,25 @@
 CefRefPtr<CefValue> CefParseJSONAndReturnError(
     const CefString& json_string,
     cef_json_parser_options_t options,
-    cef_json_parser_error_t& error_code_out,
     CefString& error_msg_out) {
   const std::string& json = json_string.ToString();
 
   std::string error_msg;
-  base::JSONReader::ValueWithError value_and_error =
-      base::JSONReader::ReadAndReturnValueWithError(
-          json, GetJSONReaderOptions(options));
-  if (value_and_error.value) {
-    return new CefValueImpl(
-        base::Value::ToUniquePtrValue(std::move(value_and_error.value.value()))
-            .release());
+  auto result = base::JSONReader::ReadAndReturnValueWithError(
+      json, GetJSONReaderOptions(options));
+  if (result.has_value()) {
+    return new CefValueImpl(std::move(*result));
   }
 
-  error_code_out =
-      static_cast<cef_json_parser_error_t>(value_and_error.error_code);
-  error_msg_out = value_and_error.error_message;
+  error_msg_out = result.error().message;
   return nullptr;
 }
 
 CefString CefWriteJSON(CefRefPtr<CefValue> node,
                        cef_json_writer_options_t options) {
-  if (!node.get() || !node->IsValid())
+  if (!node.get() || !node->IsValid()) {
     return CefString();
+  }
 
   CefValueImpl* impl = static_cast<CefValueImpl*>(node.get());
   CefValueImpl::ScopedLockedValue scoped_value(impl);
diff --git a/src/libcef/common/main_delegate.cc b/src/libcef/common/main_delegate.cc
deleted file mode 100644
index a68020e..0000000
--- a/src/libcef/common/main_delegate.cc
+++ /dev/null
@@ -1,985 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/common/main_delegate.h"
-
-#if defined(OS_LINUX)
-#include <dlfcn.h>
-#endif
-
-#include "libcef/browser/browser_message_loop.h"
-#include "libcef/browser/content_browser_client.h"
-#include "libcef/browser/context.h"
-#include "libcef/common/cef_switches.h"
-#include "libcef/common/command_line_impl.h"
-#include "libcef/common/crash_reporting.h"
-#include "libcef/common/extensions/extensions_util.h"
-#include "libcef/renderer/content_renderer_client.h"
-
-#include "base/at_exit.h"
-#include "base/base_switches.h"
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "base/run_loop.h"
-#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/media/router/media_router_feature.h"
-#include "chrome/child/pdf_child_init.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_paths_internal.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/utility/chrome_content_utility_client.h"
-#include "components/content_settings/core/common/content_settings_pattern.h"
-#include "components/viz/common/features.h"
-#include "content/browser/browser_process_sub_thread.h"
-#include "content/browser/scheduler/browser_task_executor.h"
-#include "content/public/browser/browser_main_runner.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/main_function_params.h"
-#include "extensions/common/constants.h"
-#include "ipc/ipc_buildflags.h"
-#include "net/base/features.h"
-#include "pdf/pdf_ppapi.h"
-#include "services/network/public/cpp/features.h"
-#include "services/service_manager/sandbox/switches.h"
-#include "ui/base/layout.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/base/ui_base_features.h"
-#include "ui/base/ui_base_paths.h"
-#include "ui/base/ui_base_switches.h"
-
-#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
-#define IPC_MESSAGE_MACROS_LOG_ENABLED
-#include "content/public/common/content_ipc_logging.h"
-#define IPC_LOG_TABLE_ADD_ENTRY(msg_id, logger) \
-  content::RegisterIPCLogger(msg_id, logger)
-#include "libcef/common/cef_message_generator.h"
-#endif
-
-#if defined(OS_WIN)
-#include <Objbase.h>
-#include "base/win/registry.h"
-#endif
-
-#if defined(OS_MACOSX)
-#include "base/mac/bundle_locations.h"
-#include "base/mac/foundation_util.h"
-#include "content/public/common/content_paths.h"
-#include "libcef/common/util_mac.h"
-#endif
-
-#if defined(OS_LINUX)
-#include "base/environment.h"
-#include "base/nix/xdg_util.h"
-#endif
-
-namespace {
-
-const char* const kNonWildcardDomainNonPortSchemes[] = {
-    extensions::kExtensionScheme};
-const size_t kNonWildcardDomainNonPortSchemesSize =
-    base::size(kNonWildcardDomainNonPortSchemes);
-
-#if defined(OS_MACOSX)
-
-base::FilePath GetResourcesFilePath() {
-  return util_mac::GetFrameworkResourcesDirectory();
-}
-
-// Use a "~/Library/Logs/<app name>_debug.log" file where <app name> is the name
-// of the running executable.
-base::FilePath GetDefaultLogFile() {
-  std::string exe_name = util_mac::GetMainProcessPath().BaseName().value();
-  return base::mac::GetUserLibraryPath()
-      .Append(FILE_PATH_LITERAL("Logs"))
-      .Append(FILE_PATH_LITERAL(exe_name + "_debug.log"));
-}
-
-void OverrideFrameworkBundlePath() {
-  base::FilePath framework_path = util_mac::GetFrameworkDirectory();
-  DCHECK(!framework_path.empty());
-
-  base::mac::SetOverrideFrameworkBundlePath(framework_path);
-}
-
-void OverrideOuterBundlePath() {
-  base::FilePath bundle_path = util_mac::GetMainBundlePath();
-  DCHECK(!bundle_path.empty());
-
-  base::mac::SetOverrideOuterBundlePath(bundle_path);
-}
-
-void OverrideBaseBundleID() {
-  std::string bundle_id = util_mac::GetMainBundleID();
-  DCHECK(!bundle_id.empty());
-
-  base::mac::SetBaseBundleID(bundle_id.c_str());
-}
-
-void OverrideChildProcessPath() {
-  base::FilePath child_process_path =
-      base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
-          switches::kBrowserSubprocessPath);
-
-  if (child_process_path.empty()) {
-    child_process_path = util_mac::GetChildProcessPath();
-    DCHECK(!child_process_path.empty());
-  }
-
-  // Used by ChildProcessHost::GetChildPath and PlatformCrashpadInitialization.
-  base::PathService::Override(content::CHILD_PROCESS_EXE, child_process_path);
-}
-
-#else  // !defined(OS_MACOSX)
-
-base::FilePath GetResourcesFilePath() {
-  base::FilePath pak_dir;
-  base::PathService::Get(base::DIR_ASSETS, &pak_dir);
-  return pak_dir;
-}
-
-// Use a "debug.log" file in the running executable's directory.
-base::FilePath GetDefaultLogFile() {
-  base::FilePath log_path;
-  base::PathService::Get(base::DIR_EXE, &log_path);
-  return log_path.Append(FILE_PATH_LITERAL("debug.log"));
-}
-
-#endif  // !defined(OS_MACOSX)
-
-#if defined(OS_WIN)
-
-// Gets the Flash path if installed on the system.
-bool GetSystemFlashFilename(base::FilePath* out_path) {
-  const wchar_t kPepperFlashRegistryRoot[] =
-      L"SOFTWARE\\Macromedia\\FlashPlayerPepper";
-  const wchar_t kFlashPlayerPathValueName[] = L"PlayerPath";
-
-  base::win::RegKey path_key(HKEY_LOCAL_MACHINE, kPepperFlashRegistryRoot,
-                             KEY_READ);
-  base::string16 path_str;
-  if (FAILED(path_key.ReadValue(kFlashPlayerPathValueName, &path_str)))
-    return false;
-
-  *out_path = base::FilePath(path_str);
-  return true;
-}
-
-#elif defined(OS_MACOSX)
-
-const base::FilePath::CharType kPepperFlashSystemBaseDirectory[] =
-    FILE_PATH_LITERAL("Internet Plug-Ins/PepperFlashPlayer");
-
-#endif
-
-void OverridePepperFlashSystemPluginPath() {
-#if defined(OS_WIN) || defined(OS_MACOSX)
-  base::FilePath plugin_filename;
-#if defined(OS_WIN)
-  if (!GetSystemFlashFilename(&plugin_filename))
-    return;
-#elif defined(OS_MACOSX)
-  if (!util_mac::GetLocalLibraryDirectory(&plugin_filename))
-    return;
-  plugin_filename = plugin_filename.Append(kPepperFlashSystemBaseDirectory)
-                        .Append(chrome::kPepperFlashPluginFilename);
-#endif  // defined(OS_MACOSX)
-
-  if (!plugin_filename.empty()) {
-    base::PathService::Override(chrome::FILE_PEPPER_FLASH_SYSTEM_PLUGIN,
-                                plugin_filename);
-  }
-#else  // !(defined(OS_WIN) || defined(OS_MACOSX))
-  // A system plugin is not available on other platforms.
-  return;
-#endif
-}
-
-#if defined(OS_LINUX)
-
-// Based on chrome/common/chrome_paths_linux.cc.
-// See http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
-// for a spec on where config files go.  The net effect for most
-// systems is we use ~/.config/chromium/ for Chromium and
-// ~/.config/google-chrome/ for official builds.
-// (This also helps us sidestep issues with other apps grabbing ~/.chromium .)
-bool GetDefaultUserDataDirectory(base::FilePath* result) {
-  std::unique_ptr<base::Environment> env(base::Environment::Create());
-  base::FilePath config_dir(base::nix::GetXDGDirectory(
-      env.get(), base::nix::kXdgConfigHomeEnvVar, base::nix::kDotConfigDir));
-  *result = config_dir.Append(FILE_PATH_LITERAL("cef_user_data"));
-  return true;
-}
-
-#elif defined(OS_MACOSX)
-
-// Based on chrome/common/chrome_paths_mac.mm.
-bool GetDefaultUserDataDirectory(base::FilePath* result) {
-  if (!base::PathService::Get(base::DIR_APP_DATA, result))
-    return false;
-  *result = result->Append(FILE_PATH_LITERAL("CEF"));
-  *result = result->Append(FILE_PATH_LITERAL("User Data"));
-  return true;
-}
-
-#elif defined(OS_WIN)
-
-// Based on chrome/common/chrome_paths_win.cc.
-bool GetDefaultUserDataDirectory(base::FilePath* result) {
-  if (!base::PathService::Get(base::DIR_LOCAL_APP_DATA, result))
-    return false;
-  *result = result->Append(FILE_PATH_LITERAL("CEF"));
-  *result = result->Append(FILE_PATH_LITERAL("User Data"));
-  return true;
-}
-
-#endif
-
-base::FilePath GetUserDataPath() {
-  const CefSettings& settings = CefContext::Get()->settings();
-  if (settings.user_data_path.length > 0)
-    return base::FilePath(CefString(&settings.user_data_path));
-
-  base::FilePath result;
-  if (GetDefaultUserDataDirectory(&result))
-    return result;
-
-  if (base::PathService::Get(base::DIR_TEMP, &result))
-    return result;
-
-  NOTREACHED();
-  return result;
-}
-
-bool GetDefaultDownloadDirectory(base::FilePath* result) {
-  // This will return the safe download directory if necessary.
-  return chrome::GetUserDownloadsDirectory(result);
-}
-
-// From chrome/browser/download/download_prefs.cc.
-// Consider downloads 'dangerous' if they go to the home directory on Linux and
-// to the desktop on any platform.
-bool DownloadPathIsDangerous(const base::FilePath& download_path) {
-#if defined(OS_LINUX)
-  base::FilePath home_dir = base::GetHomeDir();
-  if (download_path == home_dir) {
-    return true;
-  }
-#endif
-
-  base::FilePath desktop_dir;
-  if (!base::PathService::Get(base::DIR_USER_DESKTOP, &desktop_dir)) {
-    NOTREACHED();
-    return false;
-  }
-  return (download_path == desktop_dir);
-}
-
-bool GetDefaultDownloadSafeDirectory(base::FilePath* result) {
-  // Start with the default download directory.
-  if (!GetDefaultDownloadDirectory(result))
-    return false;
-
-  if (DownloadPathIsDangerous(*result)) {
-#if defined(OS_WIN) || defined(OS_LINUX)
-    // Explicitly switch to the safe download directory.
-    return chrome::GetUserDownloadsDirectorySafe(result);
-#else
-    // No viable alternative on macOS.
-    return false;
-#endif
-  }
-
-  return true;
-}
-
-// Returns true if |scale_factor| is supported by this platform.
-// Same as ui::ResourceBundle::IsScaleFactorSupported.
-bool IsScaleFactorSupported(ui::ScaleFactor scale_factor) {
-  const std::vector<ui::ScaleFactor>& supported_scale_factors =
-      ui::GetSupportedScaleFactors();
-  return std::find(supported_scale_factors.begin(),
-                   supported_scale_factors.end(),
-                   scale_factor) != supported_scale_factors.end();
-}
-
-#if defined(OS_LINUX)
-// Look for binary files (*.bin, *.dat, *.pak, chrome-sandbox, libGLESv2.so,
-// libEGL.so, locales/*.pak, swiftshader/*.so) next to libcef instead of the exe
-// on Linux. This is already the default on Windows.
-void OverrideAssetPath() {
-  Dl_info dl_info;
-  if (dladdr(reinterpret_cast<const void*>(&OverrideAssetPath), &dl_info)) {
-    base::FilePath path = base::FilePath(dl_info.dli_fname).DirName();
-    base::PathService::Override(base::DIR_ASSETS, path);
-  }
-}
-#endif
-
-}  // namespace
-
-// Used to run the UI on a separate thread.
-class CefUIThread : public base::PlatformThread::Delegate {
- public:
-  explicit CefUIThread(base::OnceClosure setup_callback)
-      : setup_callback_(std::move(setup_callback)) {}
-  ~CefUIThread() override { Stop(); }
-
-  void Start() {
-    base::AutoLock lock(thread_lock_);
-    bool success = base::PlatformThread::CreateWithPriority(
-        0, this, &thread_, base::ThreadPriority::NORMAL);
-    if (!success) {
-      LOG(FATAL) << "failed to UI create thread";
-    }
-  }
-
-  void Stop() {
-    base::AutoLock lock(thread_lock_);
-
-    if (!stopping_) {
-      stopping_ = true;
-      base::PostTask(
-          FROM_HERE, {content::BrowserThread::UI},
-          base::BindOnce(&CefUIThread::ThreadQuitHelper, Unretained(this)));
-    }
-
-    // Can't join if the |thread_| is either already gone or is non-joinable.
-    if (thread_.is_null())
-      return;
-
-    base::PlatformThread::Join(thread_);
-    thread_ = base::PlatformThreadHandle();
-
-    stopping_ = false;
-  }
-
-  bool WaitUntilThreadStarted() const {
-    DCHECK(owning_sequence_checker_.CalledOnValidSequence());
-    start_event_.Wait();
-    return true;
-  }
-
-  void InitializeBrowserRunner(
-      const content::MainFunctionParams& main_function_params) {
-    // Use our own browser process runner.
-    browser_runner_ = content::BrowserMainRunner::Create();
-
-    // Initialize browser process state. Uses the current thread's message loop.
-    int exit_code = browser_runner_->Initialize(main_function_params);
-    CHECK_EQ(exit_code, -1);
-  }
-
- protected:
-  void ThreadMain() override {
-    base::PlatformThread::SetName("CefUIThread");
-
-#if defined(OS_WIN)
-    // Initializes the COM library on the current thread.
-    CoInitialize(nullptr);
-#endif
-
-    start_event_.Signal();
-
-    std::move(setup_callback_).Run();
-
-    base::RunLoop run_loop;
-    run_loop_ = &run_loop;
-    run_loop.Run();
-
-    browser_runner_->Shutdown();
-    browser_runner_.reset(nullptr);
-
-    content::BrowserTaskExecutor::Shutdown();
-
-    // Run exit callbacks on the UI thread to avoid sequence check failures.
-    base::AtExitManager::ProcessCallbacksNow();
-
-#if defined(OS_WIN)
-    // Closes the COM library on the current thread. CoInitialize must
-    // be balanced by a corresponding call to CoUninitialize.
-    CoUninitialize();
-#endif
-
-    run_loop_ = nullptr;
-  }
-
-  void ThreadQuitHelper() {
-    DCHECK(run_loop_);
-    run_loop_->QuitWhenIdle();
-  }
-
-  std::unique_ptr<content::BrowserMainRunner> browser_runner_;
-  base::OnceClosure setup_callback_;
-
-  bool stopping_ = false;
-
-  // The thread's handle.
-  base::PlatformThreadHandle thread_;
-  mutable base::Lock thread_lock_;  // Protects |thread_|.
-
-  base::RunLoop* run_loop_ = nullptr;
-
-  mutable base::WaitableEvent start_event_;
-
-  // This class is not thread-safe, use this to verify access from the owning
-  // sequence of the Thread.
-  base::SequenceChecker owning_sequence_checker_;
-};
-
-CefMainDelegate::CefMainDelegate(CefRefPtr<CefApp> application)
-    : content_client_(application) {
-  // Necessary so that exported functions from base_impl.cc will be included
-  // in the binary.
-  extern void base_impl_stub();
-  base_impl_stub();
-
-#if defined(OS_LINUX)
-  OverrideAssetPath();
-#endif
-}
-
-CefMainDelegate::~CefMainDelegate() {}
-
-void CefMainDelegate::PreCreateMainMessageLoop() {
-  InitMessagePumpFactoryForUI();
-}
-
-bool CefMainDelegate::BasicStartupComplete(int* exit_code) {
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  std::string process_type =
-      command_line->GetSwitchValueASCII(switches::kProcessType);
-
-#if defined(OS_POSIX)
-  // Read the crash configuration file. Platforms using Breakpad also add a
-  // command-line switch. On Windows this is done from chrome_elf.
-  crash_reporting::BasicStartupComplete(command_line);
-#endif
-
-  if (process_type.empty()) {
-    // In the browser process. Populate the global command-line object.
-    const CefSettings& settings = CefContext::Get()->settings();
-
-    if (settings.command_line_args_disabled) {
-      // Remove any existing command-line arguments.
-      base::CommandLine::StringVector argv;
-      argv.push_back(command_line->GetProgram().value());
-      command_line->InitFromArgv(argv);
-
-      const base::CommandLine::SwitchMap& map = command_line->GetSwitches();
-      const_cast<base::CommandLine::SwitchMap*>(&map)->clear();
-    }
-
-    bool no_sandbox = settings.no_sandbox ? true : false;
-
-    if (settings.browser_subprocess_path.length > 0) {
-      base::FilePath file_path =
-          base::FilePath(CefString(&settings.browser_subprocess_path));
-      if (!file_path.empty()) {
-        command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
-                                       file_path);
-
-#if defined(OS_WIN)
-        // The sandbox is not supported when using a separate subprocess
-        // executable on Windows.
-        no_sandbox = true;
-#endif
-      }
-    }
-
-#if defined(OS_MACOSX)
-    if (settings.framework_dir_path.length > 0) {
-      base::FilePath file_path =
-          base::FilePath(CefString(&settings.framework_dir_path));
-      if (!file_path.empty())
-        command_line->AppendSwitchPath(switches::kFrameworkDirPath, file_path);
-    }
-
-    if (settings.main_bundle_path.length > 0) {
-      base::FilePath file_path =
-          base::FilePath(CefString(&settings.main_bundle_path));
-      if (!file_path.empty())
-        command_line->AppendSwitchPath(switches::kMainBundlePath, file_path);
-    }
-#endif
-
-    if (no_sandbox)
-      command_line->AppendSwitch(service_manager::switches::kNoSandbox);
-
-    if (settings.user_agent.length > 0) {
-      command_line->AppendSwitchASCII(switches::kUserAgent,
-                                      CefString(&settings.user_agent));
-    } else if (settings.product_version.length > 0) {
-      command_line->AppendSwitchASCII(switches::kProductVersion,
-                                      CefString(&settings.product_version));
-    }
-
-    if (settings.locale.length > 0) {
-      command_line->AppendSwitchASCII(switches::kLang,
-                                      CefString(&settings.locale));
-    } else if (!command_line->HasSwitch(switches::kLang)) {
-      command_line->AppendSwitchASCII(switches::kLang, "en-US");
-    }
-
-    base::FilePath log_file;
-    bool has_log_file_cmdline = false;
-    if (settings.log_file.length > 0)
-      log_file = base::FilePath(CefString(&settings.log_file));
-    if (log_file.empty() && command_line->HasSwitch(switches::kLogFile)) {
-      log_file = command_line->GetSwitchValuePath(switches::kLogFile);
-      if (!log_file.empty())
-        has_log_file_cmdline = true;
-    }
-    if (log_file.empty())
-      log_file = GetDefaultLogFile();
-    DCHECK(!log_file.empty());
-    if (!has_log_file_cmdline)
-      command_line->AppendSwitchPath(switches::kLogFile, log_file);
-
-    if (settings.log_severity != LOGSEVERITY_DEFAULT) {
-      std::string log_severity;
-      switch (settings.log_severity) {
-        case LOGSEVERITY_VERBOSE:
-          log_severity = switches::kLogSeverity_Verbose;
-          break;
-        case LOGSEVERITY_INFO:
-          log_severity = switches::kLogSeverity_Info;
-          break;
-        case LOGSEVERITY_WARNING:
-          log_severity = switches::kLogSeverity_Warning;
-          break;
-        case LOGSEVERITY_ERROR:
-          log_severity = switches::kLogSeverity_Error;
-          break;
-        case LOGSEVERITY_FATAL:
-          log_severity = switches::kLogSeverity_Fatal;
-          break;
-        case LOGSEVERITY_DISABLE:
-          log_severity = switches::kLogSeverity_Disable;
-          break;
-        default:
-          break;
-      }
-      if (!log_severity.empty())
-        command_line->AppendSwitchASCII(switches::kLogSeverity, log_severity);
-    }
-
-    if (settings.javascript_flags.length > 0) {
-      command_line->AppendSwitchASCII(switches::kJavaScriptFlags,
-                                      CefString(&settings.javascript_flags));
-    }
-
-    if (settings.pack_loading_disabled) {
-      command_line->AppendSwitch(switches::kDisablePackLoading);
-    } else {
-      if (settings.resources_dir_path.length > 0) {
-        base::FilePath file_path =
-            base::FilePath(CefString(&settings.resources_dir_path));
-        if (!file_path.empty()) {
-          command_line->AppendSwitchPath(switches::kResourcesDirPath,
-                                         file_path);
-        }
-      }
-
-      if (settings.locales_dir_path.length > 0) {
-        base::FilePath file_path =
-            base::FilePath(CefString(&settings.locales_dir_path));
-        if (!file_path.empty())
-          command_line->AppendSwitchPath(switches::kLocalesDirPath, file_path);
-      }
-    }
-
-    if (settings.remote_debugging_port >= 1024 &&
-        settings.remote_debugging_port <= 65535) {
-      command_line->AppendSwitchASCII(
-          switches::kRemoteDebuggingPort,
-          base::NumberToString(settings.remote_debugging_port));
-    }
-
-    if (settings.uncaught_exception_stack_size > 0) {
-      command_line->AppendSwitchASCII(
-          switches::kUncaughtExceptionStackSize,
-          base::NumberToString(settings.uncaught_exception_stack_size));
-    }
-
-    std::vector<std::string> disable_features;
-
-    if (network::features::kOutOfBlinkCors.default_state ==
-        base::FEATURE_ENABLED_BY_DEFAULT) {
-      // TODO: Add support for out-of-Blink CORS (see issue #2716)
-      disable_features.push_back(network::features::kOutOfBlinkCors.name);
-    }
-
-#if defined(OS_WIN)
-    if (features::kCalculateNativeWinOcclusion.default_state ==
-        base::FEATURE_ENABLED_BY_DEFAULT) {
-      // TODO: Add support for occlusion detection in combination with native
-      // parent windows (see issue #2805).
-      disable_features.push_back(features::kCalculateNativeWinOcclusion.name);
-    }
-#endif  // defined(OS_WIN)
-
-    if (!disable_features.empty()) {
-      DCHECK(!base::FeatureList::GetInstance());
-      std::string disable_features_str =
-          command_line->GetSwitchValueASCII(switches::kDisableFeatures);
-      for (auto feature_str : disable_features) {
-        if (!disable_features_str.empty())
-          disable_features_str += ",";
-        disable_features_str += feature_str;
-      }
-      command_line->AppendSwitchASCII(switches::kDisableFeatures,
-                                      disable_features_str);
-    }
-
-    std::vector<std::string> enable_features;
-
-    if (media_router::kDialMediaRouteProvider.default_state ==
-        base::FEATURE_DISABLED_BY_DEFAULT) {
-      // Enable discovery of DIAL devices.
-      enable_features.push_back(media_router::kDialMediaRouteProvider.name);
-    }
-
-    if (media_router::kCastMediaRouteProvider.default_state ==
-        base::FEATURE_DISABLED_BY_DEFAULT) {
-      // Enable discovery of Cast devices.
-      enable_features.push_back(media_router::kCastMediaRouteProvider.name);
-    }
-
-    if (!enable_features.empty()) {
-      DCHECK(!base::FeatureList::GetInstance());
-      std::string enable_features_str =
-          command_line->GetSwitchValueASCII(switches::kEnableFeatures);
-      for (auto feature_str : enable_features) {
-        if (!enable_features_str.empty())
-          enable_features_str += ",";
-        enable_features_str += feature_str;
-      }
-      command_line->AppendSwitchASCII(switches::kEnableFeatures,
-                                      enable_features_str);
-    }
-  }
-
-  if (content_client_.application().get()) {
-    // Give the application a chance to view/modify the command line.
-    CefRefPtr<CefCommandLineImpl> commandLinePtr(
-        new CefCommandLineImpl(command_line, false, false));
-    content_client_.application()->OnBeforeCommandLineProcessing(
-        CefString(process_type), commandLinePtr.get());
-    commandLinePtr->Detach(nullptr);
-  }
-
-  // Initialize logging.
-  logging::LoggingSettings log_settings;
-
-  const base::FilePath& log_file =
-      command_line->GetSwitchValuePath(switches::kLogFile);
-  DCHECK(!log_file.empty());
-  log_settings.log_file_path = log_file.value().c_str();
-
-  log_settings.lock_log = logging::DONT_LOCK_LOG_FILE;
-  log_settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
-
-  logging::LogSeverity log_severity = logging::LOG_INFO;
-
-  std::string log_severity_str =
-      command_line->GetSwitchValueASCII(switches::kLogSeverity);
-  if (!log_severity_str.empty()) {
-    if (base::LowerCaseEqualsASCII(log_severity_str,
-                                   switches::kLogSeverity_Verbose)) {
-      log_severity = logging::LOG_VERBOSE;
-    } else if (base::LowerCaseEqualsASCII(log_severity_str,
-                                          switches::kLogSeverity_Warning)) {
-      log_severity = logging::LOG_WARNING;
-    } else if (base::LowerCaseEqualsASCII(log_severity_str,
-                                          switches::kLogSeverity_Error)) {
-      log_severity = logging::LOG_ERROR;
-    } else if (base::LowerCaseEqualsASCII(log_severity_str,
-                                          switches::kLogSeverity_Fatal)) {
-      log_severity = logging::LOG_FATAL;
-    } else if (base::LowerCaseEqualsASCII(log_severity_str,
-                                          switches::kLogSeverity_Disable)) {
-      log_severity = LOGSEVERITY_DISABLE;
-    }
-  }
-
-  if (log_severity == LOGSEVERITY_DISABLE) {
-    log_settings.logging_dest = logging::LOG_NONE;
-    // By default, ERROR and FATAL messages will always be output to stderr due
-    // to the kAlwaysPrintErrorLevel value in base/logging.cc. We change the log
-    // level here so that only FATAL messages are output.
-    logging::SetMinLogLevel(logging::LOG_FATAL);
-  } else {
-    log_settings.logging_dest = logging::LOG_TO_ALL;
-    logging::SetMinLogLevel(log_severity);
-  }
-
-  logging::InitLogging(log_settings);
-
-  ContentSettingsPattern::SetNonWildcardDomainNonPortSchemes(
-      kNonWildcardDomainNonPortSchemes, kNonWildcardDomainNonPortSchemesSize);
-
-  content::SetContentClient(&content_client_);
-
-#if defined(OS_MACOSX)
-  OverrideFrameworkBundlePath();
-  OverrideOuterBundlePath();
-  OverrideBaseBundleID();
-#endif
-
-  return false;
-}
-
-void CefMainDelegate::PreSandboxStartup() {
-  const base::CommandLine* command_line =
-      base::CommandLine::ForCurrentProcess();
-  const std::string& process_type =
-      command_line->GetSwitchValueASCII(switches::kProcessType);
-
-  if (process_type.empty()) {
-// Only override these paths when executing the main process.
-#if defined(OS_MACOSX)
-    OverrideChildProcessPath();
-#endif
-
-    OverridePepperFlashSystemPluginPath();
-
-    base::FilePath dir_default_download;
-    base::FilePath dir_default_download_safe;
-    if (GetDefaultDownloadDirectory(&dir_default_download)) {
-      base::PathService::Override(chrome::DIR_DEFAULT_DOWNLOADS,
-                                  dir_default_download);
-    }
-    if (GetDefaultDownloadSafeDirectory(&dir_default_download_safe)) {
-      base::PathService::Override(chrome::DIR_DEFAULT_DOWNLOADS_SAFE,
-                                  dir_default_download_safe);
-    }
-
-    const base::FilePath& user_data_path = GetUserDataPath();
-    base::PathService::Override(chrome::DIR_USER_DATA, user_data_path);
-
-    // Path used for crash dumps.
-    base::PathService::Override(chrome::DIR_CRASH_DUMPS, user_data_path);
-
-    // Path used for spell checking dictionary files.
-    base::PathService::OverrideAndCreateIfNeeded(
-        chrome::DIR_APP_DICTIONARIES,
-        user_data_path.AppendASCII("Dictionaries"),
-        false,  // May not be an absolute path.
-        true);  // Create if necessary.
-  }
-
-  if (command_line->HasSwitch(switches::kDisablePackLoading))
-    content_client_.set_pack_loading_disabled(true);
-
-  // Initialize crash reporting state for this process/module.
-  // chrome::DIR_CRASH_DUMPS must be configured before calling this function.
-  crash_reporting::PreSandboxStartup(*command_line, process_type);
-
-  InitializeResourceBundle();
-  MaybeInitializeGDI();
-}
-
-void CefMainDelegate::SandboxInitialized(const std::string& process_type) {
-  CefContentClient::SetPDFEntryFunctions(chrome_pdf::PPP_GetInterface,
-                                         chrome_pdf::PPP_InitializeModule,
-                                         chrome_pdf::PPP_ShutdownModule);
-}
-
-int CefMainDelegate::RunProcess(
-    const std::string& process_type,
-    const content::MainFunctionParams& main_function_params) {
-  if (process_type.empty()) {
-    const CefSettings& settings = CefContext::Get()->settings();
-    if (!settings.multi_threaded_message_loop) {
-      // Use our own browser process runner.
-      browser_runner_ = content::BrowserMainRunner::Create();
-
-      // Initialize browser process state. Results in a call to
-      // CefBrowserMain::PreMainMessageLoopStart() which creates the UI message
-      // loop.
-      int exit_code = browser_runner_->Initialize(main_function_params);
-      if (exit_code >= 0)
-        return exit_code;
-    } else {
-      // Running on the separate UI thread.
-      DCHECK(ui_thread_);
-      ui_thread_->InitializeBrowserRunner(main_function_params);
-    }
-
-    return 0;
-  }
-
-  return -1;
-}
-
-bool CefMainDelegate::CreateUIThread(base::OnceClosure setup_callback) {
-  DCHECK(!ui_thread_);
-
-  ui_thread_.reset(new CefUIThread(std::move(setup_callback)));
-  ui_thread_->Start();
-  ui_thread_->WaitUntilThreadStarted();
-
-  InitMessagePumpFactoryForUI();
-  return true;
-}
-
-void CefMainDelegate::ProcessExiting(const std::string& process_type) {
-  ui::ResourceBundle::CleanupSharedInstance();
-}
-
-#if defined(OS_LINUX)
-void CefMainDelegate::ZygoteForked() {
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  const std::string& process_type =
-      command_line->GetSwitchValueASCII(switches::kProcessType);
-  // Initialize crash reporting state for the newly forked process.
-  crash_reporting::ZygoteForked(command_line, process_type);
-}
-#endif
-
-content::ContentBrowserClient* CefMainDelegate::CreateContentBrowserClient() {
-  browser_client_.reset(new CefContentBrowserClient);
-  return browser_client_.get();
-}
-
-content::ContentRendererClient* CefMainDelegate::CreateContentRendererClient() {
-  renderer_client_.reset(new CefContentRendererClient);
-  return renderer_client_.get();
-}
-
-content::ContentUtilityClient* CefMainDelegate::CreateContentUtilityClient() {
-  utility_client_.reset(new ChromeContentUtilityClient);
-  return utility_client_.get();
-}
-
-void CefMainDelegate::ShutdownBrowser() {
-  if (browser_runner_.get()) {
-    browser_runner_->Shutdown();
-    browser_runner_.reset(nullptr);
-  }
-
-  if (ui_thread_.get()) {
-    // Blocks until the thread has stopped.
-    ui_thread_->Stop();
-    ui_thread_.reset();
-  }
-}
-
-void CefMainDelegate::InitializeResourceBundle() {
-  const base::CommandLine* command_line =
-      base::CommandLine::ForCurrentProcess();
-  base::FilePath cef_pak_file, cef_100_percent_pak_file,
-      cef_200_percent_pak_file, cef_extensions_pak_file, devtools_pak_file,
-      locales_dir;
-
-  base::FilePath resources_dir;
-  if (command_line->HasSwitch(switches::kResourcesDirPath)) {
-    resources_dir =
-        command_line->GetSwitchValuePath(switches::kResourcesDirPath);
-  }
-  if (resources_dir.empty())
-    resources_dir = GetResourcesFilePath();
-  if (!resources_dir.empty())
-    base::PathService::Override(chrome::DIR_RESOURCES, resources_dir);
-
-  if (!content_client_.pack_loading_disabled()) {
-    if (!resources_dir.empty()) {
-      CHECK(resources_dir.IsAbsolute());
-      cef_pak_file = resources_dir.Append(FILE_PATH_LITERAL("cef.pak"));
-      cef_100_percent_pak_file =
-          resources_dir.Append(FILE_PATH_LITERAL("cef_100_percent.pak"));
-      cef_200_percent_pak_file =
-          resources_dir.Append(FILE_PATH_LITERAL("cef_200_percent.pak"));
-      cef_extensions_pak_file =
-          resources_dir.Append(FILE_PATH_LITERAL("cef_extensions.pak"));
-      devtools_pak_file =
-          resources_dir.Append(FILE_PATH_LITERAL("devtools_resources.pak"));
-    }
-
-    if (command_line->HasSwitch(switches::kLocalesDirPath))
-      locales_dir = command_line->GetSwitchValuePath(switches::kLocalesDirPath);
-
-    if (!locales_dir.empty())
-      base::PathService::Override(ui::DIR_LOCALES, locales_dir);
-  }
-
-  std::string locale = command_line->GetSwitchValueASCII(switches::kLang);
-  DCHECK(!locale.empty());
-
-  const std::string loaded_locale =
-      ui::ResourceBundle::InitSharedInstanceWithLocale(
-          locale, content_client_.GetCefResourceBundleDelegate(),
-          ui::ResourceBundle::LOAD_COMMON_RESOURCES);
-  if (!loaded_locale.empty() && g_browser_process)
-    g_browser_process->SetApplicationLocale(loaded_locale);
-
-  ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
-
-  if (!content_client_.pack_loading_disabled()) {
-    if (loaded_locale.empty())
-      LOG(ERROR) << "Could not load locale pak for " << locale;
-
-    content_client_.set_allow_pack_file_load(true);
-
-    if (base::PathExists(cef_pak_file)) {
-      resource_bundle.AddDataPackFromPath(cef_pak_file, ui::SCALE_FACTOR_NONE);
-    } else {
-      LOG(ERROR) << "Could not load cef.pak";
-    }
-
-    // On OS X and Linux/Aura always load the 1x data pack first as the 2x data
-    // pack contains both 1x and 2x images.
-    const bool load_100_percent =
-#if defined(OS_WIN)
-        IsScaleFactorSupported(ui::SCALE_FACTOR_100P);
-#else
-        true;
-#endif
-
-    if (load_100_percent) {
-      if (base::PathExists(cef_100_percent_pak_file)) {
-        resource_bundle.AddDataPackFromPath(cef_100_percent_pak_file,
-                                            ui::SCALE_FACTOR_100P);
-      } else {
-        LOG(ERROR) << "Could not load cef_100_percent.pak";
-      }
-    }
-
-    if (IsScaleFactorSupported(ui::SCALE_FACTOR_200P)) {
-      if (base::PathExists(cef_200_percent_pak_file)) {
-        resource_bundle.AddDataPackFromPath(cef_200_percent_pak_file,
-                                            ui::SCALE_FACTOR_200P);
-      } else {
-        LOG(ERROR) << "Could not load cef_200_percent.pak";
-      }
-    }
-
-    if (extensions::ExtensionsEnabled() ||
-        !command_line->HasSwitch(switches::kDisablePlugins)) {
-      if (base::PathExists(cef_extensions_pak_file)) {
-        resource_bundle.AddDataPackFromPath(cef_extensions_pak_file,
-                                            ui::SCALE_FACTOR_NONE);
-      } else {
-        LOG(ERROR) << "Could not load cef_extensions.pak";
-      }
-    }
-
-    if (base::PathExists(devtools_pak_file)) {
-      resource_bundle.AddDataPackFromPath(devtools_pak_file,
-                                          ui::SCALE_FACTOR_NONE);
-    }
-
-    content_client_.set_allow_pack_file_load(false);
-  }
-}
diff --git a/src/libcef/common/main_delegate.h b/src/libcef/common/main_delegate.h
deleted file mode 100644
index fecc697..0000000
--- a/src/libcef/common/main_delegate.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_COMMON_MAIN_DELEGATE_H_
-#define CEF_LIBCEF_COMMON_MAIN_DELEGATE_H_
-#pragma once
-
-#include <string>
-
-#include "include/cef_app.h"
-#include "libcef/common/content_client.h"
-
-#include "base/compiler_specific.h"
-#include "content/public/app/content_main_delegate.h"
-
-namespace base {
-class CommandLine;
-class MessageLoop;
-class Thread;
-}  // namespace base
-
-namespace content {
-class BrowserMainRunner;
-}
-
-class CefContentBrowserClient;
-class CefContentRendererClient;
-class CefUIThread;
-class ChromeContentUtilityClient;
-
-class CefMainDelegate : public content::ContentMainDelegate {
- public:
-  explicit CefMainDelegate(CefRefPtr<CefApp> application);
-  ~CefMainDelegate() override;
-
-  void PreCreateMainMessageLoop() override;
-  bool BasicStartupComplete(int* exit_code) override;
-  void PreSandboxStartup() override;
-  void SandboxInitialized(const std::string& process_type) override;
-  int RunProcess(
-      const std::string& process_type,
-      const content::MainFunctionParams& main_function_params) override;
-  void ProcessExiting(const std::string& process_type) override;
-#if defined(OS_LINUX)
-  void ZygoteForked() override;
-#endif
-  content::ContentBrowserClient* CreateContentBrowserClient() override;
-  content::ContentRendererClient* CreateContentRendererClient() override;
-  content::ContentUtilityClient* CreateContentUtilityClient() override;
-
-  bool CreateUIThread(base::OnceClosure setup_callback);
-
-  // Shut down the browser runner.
-  void ShutdownBrowser();
-
-  CefContentBrowserClient* browser_client() { return browser_client_.get(); }
-  CefContentClient* content_client() { return &content_client_; }
-
- private:
-  void InitializeResourceBundle();
-
-  std::unique_ptr<content::BrowserMainRunner> browser_runner_;
-  std::unique_ptr<CefUIThread> ui_thread_;
-
-  std::unique_ptr<CefContentBrowserClient> browser_client_;
-  std::unique_ptr<CefContentRendererClient> renderer_client_;
-  std::unique_ptr<ChromeContentUtilityClient> utility_client_;
-  CefContentClient content_client_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefMainDelegate);
-};
-
-#endif  // CEF_LIBCEF_COMMON_MAIN_DELEGATE_H_
diff --git a/src/libcef/common/main_runner_delegate.h b/src/libcef/common/main_runner_delegate.h
new file mode 100644
index 0000000..daf4080
--- /dev/null
+++ b/src/libcef/common/main_runner_delegate.h
@@ -0,0 +1,38 @@
+// Copyright 2020 The Chromium Embedded Framework 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 CEF_LIBCEF_COMMON_MAIN_RUNNER_DELEGATE_H_
+#define CEF_LIBCEF_COMMON_MAIN_RUNNER_DELEGATE_H_
+#pragma once
+
+#include "include/cef_app.h"
+
+namespace base {
+class RunLoop;
+}
+
+namespace content {
+class ContentMainDelegate;
+}
+
+class CefMainRunnerDelegate {
+ public:
+  virtual content::ContentMainDelegate* GetContentMainDelegate() = 0;
+
+  virtual void BeforeMainThreadInitialize(const CefMainArgs& args) {}
+  virtual void BeforeMainThreadRun(bool multi_threaded_message_loop) {}
+  virtual void BeforeMainMessageLoopRun(base::RunLoop* run_loop) {}
+  virtual bool HandleMainMessageLoopQuit() { return false; }
+  virtual void BeforeUIThreadInitialize() {}
+  virtual void AfterUIThreadInitialize() {}
+  virtual void AfterUIThreadShutdown() {}
+  virtual void BeforeMainThreadShutdown() {}
+  virtual void AfterMainThreadShutdown() {}
+  virtual void BeforeExecuteProcess(const CefMainArgs& args) {}
+  virtual void AfterExecuteProcess() {}
+
+  virtual ~CefMainRunnerDelegate() {}
+};
+
+#endif  // CEF_LIBCEF_COMMON_MAIN_RUNNER_DELEGATE_H_
diff --git a/src/libcef/common/main_runner_handler.h b/src/libcef/common/main_runner_handler.h
new file mode 100644
index 0000000..1314c72
--- /dev/null
+++ b/src/libcef/common/main_runner_handler.h
@@ -0,0 +1,24 @@
+// Copyright 2020 The Chromium Embedded Framework 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 CEF_LIBCEF_COMMON_MAIN_RUNNER_HANDLER_H_
+#define CEF_LIBCEF_COMMON_MAIN_RUNNER_HANDLER_H_
+#pragma once
+
+namespace content {
+struct MainFunctionParams;
+}
+
+// Handles running of the main process.
+class CefMainRunnerHandler {
+ public:
+  virtual void PreBrowserMain() = 0;
+  virtual int RunMainProcess(
+      content::MainFunctionParams main_function_params) = 0;
+
+ protected:
+  virtual ~CefMainRunnerHandler() {}
+};
+
+#endif  // CEF_LIBCEF_COMMON_MAIN_RUNNER_HANDLER_H_
diff --git a/src/libcef/common/mojom/BUILD.gn b/src/libcef/common/mojom/BUILD.gn
new file mode 100644
index 0000000..a8b59b5
--- /dev/null
+++ b/src/libcef/common/mojom/BUILD.gn
@@ -0,0 +1,29 @@
+# Copyright 2021 The Chromium Embedded Framework Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("mojom") {
+  sources = [ "cef.mojom" ]
+
+  cpp_only = true
+  disable_variants = true
+
+  public_deps = [
+    "//content/public/common:interfaces",
+    "//mojo/public/mojom/base",
+    "//services/network/public/mojom:cookies_mojom",
+    "//services/network/public/mojom:url_loader_base",
+    "//third_party/blink/public/mojom:mojom_platform",
+    "//ui/gfx/geometry/mojom",
+    "//url/mojom:url_mojom_gurl",
+  ]
+
+  overridden_deps = [
+    "//content/public/common:interfaces",
+    "//third_party/blink/public/mojom:mojom_platform",
+  ]
+
+  component_deps = [ "//content/public/common" ]
+}
diff --git a/src/libcef/common/mojom/cef.mojom b/src/libcef/common/mojom/cef.mojom
new file mode 100644
index 0000000..fa2d0d4
--- /dev/null
+++ b/src/libcef/common/mojom/cef.mojom
@@ -0,0 +1,139 @@
+// Copyright 2021 The Chromium Embedded Framework Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module cef.mojom;
+
+import "mojo/public/mojom/base/shared_memory.mojom";
+import "mojo/public/mojom/base/string16.mojom";
+import "mojo/public/mojom/base/values.mojom";
+import "services/network/public/mojom/site_for_cookies.mojom";
+import "services/network/public/mojom/url_request.mojom";
+import "third_party/blink/public/mojom/loader/referrer.mojom";
+import "ui/gfx/geometry/mojom/geometry.mojom";
+import "url/mojom/url.mojom";
+
+// Structure passed to UpdateDraggableRegions().
+struct DraggableRegionEntry {
+  gfx.mojom.Rect bounds;
+  bool draggable;
+};
+
+// Structure passed to LoadRequest().
+struct RequestParams {
+  // Request method.
+  string method;
+
+  // The URL to be loaded.
+  url.mojom.Url url;
+
+  // The referrer for the request.
+  blink.mojom.Referrer referrer;
+
+  // Usually the URL of the document in the top-level window, which may be
+  // checked by the third-party cookie blocking policy. Leaving it empty may
+  // lead to undesired cookie blocking. Third-party cookie blocking can be
+  // bypassed by setting site_for_cookies = url, but this should ideally
+  // only be done if there really is no way to determine the correct value.
+  network.mojom.SiteForCookies site_for_cookies;
+
+  // Additional HTTP request headers.
+  string headers;
+
+  // net::URLRequest load flags (0 by default).
+  int32 load_flags;
+
+  // Upload data (may be empty).
+  network.mojom.URLRequestBody? upload_data;
+};
+
+// Interface for communicating with a frame in the renderer process.
+interface RenderFrame {
+  // Browser process has received the FrameAttached() message.
+  FrameAttachedAck();
+
+  // Browser process has intentionally detached.
+  FrameDetached();
+
+  // Send a message to the render process.
+  SendMessage(string name, mojo_base.mojom.ListValue arguments);
+
+  // Send a shared memory region to the render process.
+  SendSharedMemoryRegion(string name, mojo_base.mojom.WritableSharedMemoryRegion region);
+
+  // Send a command.
+  SendCommand(string command);
+
+  // Send a command that returns an async response.
+  // The returned |response| format is command-specific and will be invalid if
+  // an error occurred.
+  SendCommandWithResponse(string command) =>
+      (mojo_base.mojom.ReadOnlySharedMemoryRegion? response);
+
+  // Send JavaScript for execution.
+  SendJavaScript(mojo_base.mojom.String16 jsCode, string scriptUrl,
+                 int32 startLine);
+
+  // Load a request.
+  LoadRequest(RequestParams params);
+
+  // Loading has stopped.
+  DidStopLoading();
+
+  // Move or resize of the renderer's containing window has started. Used on
+  // Windows and Linux with the Alloy runtime.
+  MoveOrResizeStarted();
+};
+
+// Interface for communicating with a frame in the browser process.
+interface BrowserFrame {
+  // Send a message to the browser process.
+  SendMessage(string name, mojo_base.mojom.ListValue arguments);
+
+  // Send a shared memory region to the browser process.
+  SendSharedMemoryRegion(string name, mojo_base.mojom.WritableSharedMemoryRegion region);
+
+  // The render frame is ready to begin handling actions.
+  FrameAttached(pending_remote<RenderFrame> render_frame,
+                bool reattached);
+
+  // Draggable regions have updated.
+  UpdateDraggableRegions(array<DraggableRegionEntry>? regions);
+};
+
+struct CrossOriginWhiteListEntry {
+  string source_origin;
+  string target_protocol;
+  string target_domain;
+  bool allow_target_subdomains;
+};
+
+struct NewRenderThreadInfo {
+  array<CrossOriginWhiteListEntry>? cross_origin_whitelist_entries;
+};
+
+struct NewBrowserInfo {
+  int32 browser_id;
+  bool is_popup;
+  bool is_windowless;
+  bool is_guest_view;
+  mojo_base.mojom.DictionaryValue? extra_info;
+};
+
+// Interface for communicating with browser management in the browser process.
+interface BrowserManager {
+  // Retrieve info for a new RenderThread.
+  [Sync]
+  GetNewRenderThreadInfo() => (NewRenderThreadInfo info);
+
+  // Retrieve info for a new CefBrowser.
+  [Sync]
+  GetNewBrowserInfo(int32 render_frame_routing_id) => (NewBrowserInfo info);
+};
+
+// Interface for communicating with browser management to the render process.
+interface RenderManager {
+  // Manage cross-origin whitelist contents during the render process lifespan.
+  ModifyCrossOriginWhitelistEntry(bool add, CrossOriginWhiteListEntry entry);
+  ClearCrossOriginWhitelist();
+};
diff --git a/src/libcef/common/net/http_header_utils.cc b/src/libcef/common/net/http_header_utils.cc
index 6199d2f..60a7085 100644
--- a/src/libcef/common/net/http_header_utils.cc
+++ b/src/libcef/common/net/http_header_utils.cc
@@ -24,8 +24,9 @@
 
     if (!key.empty()) {
       // Delimit with "\r\n".
-      if (!headers.empty())
+      if (!headers.empty()) {
         headers += "\r\n";
+      }
 
       headers += std::string(key) + ": " + std::string(value);
     }
@@ -50,8 +51,9 @@
 HeaderMap::iterator FindHeaderInMap(const std::string& nameLower,
                                     HeaderMap& map) {
   for (auto it = map.begin(); it != map.end(); ++it) {
-    if (base::EqualsCaseInsensitiveASCII(it->first.ToString(), nameLower))
+    if (base::EqualsCaseInsensitiveASCII(it->first.ToString(), nameLower)) {
       return it;
+    }
   }
 
   return map.end();
diff --git a/src/libcef/common/net/http_header_utils.h b/src/libcef/common/net/http_header_utils.h
index 50a1237..45886bc 100644
--- a/src/libcef/common/net/http_header_utils.h
+++ b/src/libcef/common/net/http_header_utils.h
@@ -13,7 +13,7 @@
 
 namespace HttpHeaderUtils {
 
-typedef std::multimap<CefString, CefString> HeaderMap;
+using HeaderMap = std::multimap<CefString, CefString>;
 
 std::string GenerateHeaders(const HeaderMap& map);
 void ParseHeaders(const std::string& header_str, HeaderMap& map);
diff --git a/src/libcef/common/net/net_resource_provider.cc b/src/libcef/common/net/net_resource_provider.cc
index 229439d..eea3db7 100644
--- a/src/libcef/common/net/net_resource_provider.cc
+++ b/src/libcef/common/net/net_resource_provider.cc
@@ -4,12 +4,14 @@
 
 #include "libcef/common/net/net_resource_provider.h"
 
+#include "base/logging.h"
 #include "chrome/common/net/net_resource_provider.h"
 
 scoped_refptr<base::RefCountedMemory> NetResourceProvider(int key) {
   // Chrome performs substitution of localized strings for directory listings.
   scoped_refptr<base::RefCountedMemory> value = ChromeNetResourceProvider(key);
-  if (!value)
+  if (!value) {
     LOG(ERROR) << "No data resource available for id " << key;
+  }
   return value;
 }
diff --git a/src/libcef/common/net/scheme_info.h b/src/libcef/common/net/scheme_info.h
new file mode 100644
index 0000000..4730d00
--- /dev/null
+++ b/src/libcef/common/net/scheme_info.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2013 The Chromium Embedded Framework 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 CEF_LIBCEF_COMMON_NET_SCHEME_INFO_H_
+#define CEF_LIBCEF_COMMON_NET_SCHEME_INFO_H_
+#pragma once
+
+#include <string>
+
+// Values are registered with all processes (url/url_util.h) and with Blink
+// (SchemeRegistry) unless otherwise indicated.
+struct CefSchemeInfo {
+  // Lower-case ASCII scheme name.
+  std::string scheme_name;
+
+  // A scheme that is subject to URL canonicalization and parsing rules as
+  // defined in the Common Internet Scheme Syntax RFC 1738 Section 3.1
+  // available at http://www.ietf.org/rfc/rfc1738.txt.
+  // This value is not registered with Blink.
+  bool is_standard;
+
+  // A scheme that will be treated the same as "file". For example, normal
+  // pages cannot link to or access URLs of this scheme.
+  bool is_local;
+
+  // A scheme that can only be displayed from other content hosted with the
+  // same scheme. For example, pages in other origins cannot create iframes or
+  // hyperlinks to URLs with the scheme. For schemes that must be accessible
+  // from other schemes set this value to false, set |is_cors_enabled| to
+  // true, and use CORS "Access-Control-Allow-Origin" headers to further
+  // restrict access.
+  // This value is registered with Blink only.
+  bool is_display_isolated;
+
+  // A scheme that will be treated the same as "https". For example, loading
+  // this scheme from other secure schemes will not trigger mixed content
+  // warnings.
+  bool is_secure;
+
+  // A scheme that can be sent CORS requests. This value should be true in
+  // most cases where |is_standard| is true.
+  bool is_cors_enabled;
+
+  // A scheme that can bypass Content-Security-Policy (CSP) checks. This value
+  // should be false in most cases where |is_standard| is true.
+  bool is_csp_bypassing;
+
+  // A scheme that can perform fetch request.
+  bool is_fetch_enabled;
+};
+
+#endif  // CEF_LIBCEF_COMMON_NET_SCHEME_INFO_H_
diff --git a/src/libcef/common/net/scheme_registration.cc b/src/libcef/common/net/scheme_registration.cc
index ca1de54..7556976 100644
--- a/src/libcef/common/net/scheme_registration.cc
+++ b/src/libcef/common/net/scheme_registration.cc
@@ -4,22 +4,28 @@
 
 #include "libcef/common/net/scheme_registration.h"
 
-#include "libcef/common/content_client.h"
+#include "libcef/common/app_manager.h"
+#include "libcef/common/net/scheme_info.h"
+#include "libcef/features/runtime.h"
 
+#include "base/containers/contains.h"
 #include "content/public/common/url_constants.h"
 #include "extensions/common/constants.h"
-#include "net/net_buildflags.h"
 #include "url/url_constants.h"
 #include "url/url_util.h"
 
 namespace scheme {
 
 void AddInternalSchemes(content::ContentClient::Schemes* schemes) {
+  if (!cef::IsAlloyRuntimeEnabled()) {
+    return;
+  }
+
   // chrome: and chrome-devtools: schemes are registered in
   // RenderThreadImpl::RegisterSchemes().
   // Access restrictions for chrome-extension: and chrome-extension-resource:
-  // schemes will be applied in CefContentRendererClient::WillSendRequest().
-  static CefContentClient::SchemeInfo internal_schemes[] = {
+  // schemes will be applied in AlloyContentRendererClient::WillSendRequest().
+  static CefSchemeInfo internal_schemes[] = {
       {
           extensions::kExtensionScheme, true, /* is_standard */
           false,                              /* is_local */
@@ -32,46 +38,49 @@
 
   // The |is_display_isolated| value is excluded here because it's registered
   // with Blink only.
-  CefContentClient* client = CefContentClient::Get();
   for (size_t i = 0; i < sizeof(internal_schemes) / sizeof(internal_schemes[0]);
        ++i) {
-    if (internal_schemes[i].is_standard)
+    if (internal_schemes[i].is_standard) {
       schemes->standard_schemes.push_back(internal_schemes[i].scheme_name);
-    if (internal_schemes[i].is_local)
+    }
+    if (internal_schemes[i].is_local) {
       schemes->local_schemes.push_back(internal_schemes[i].scheme_name);
-    if (internal_schemes[i].is_secure)
+    }
+    if (internal_schemes[i].is_secure) {
       schemes->secure_schemes.push_back(internal_schemes[i].scheme_name);
-    if (internal_schemes[i].is_cors_enabled)
+    }
+    if (internal_schemes[i].is_cors_enabled) {
       schemes->cors_enabled_schemes.push_back(internal_schemes[i].scheme_name);
-    if (internal_schemes[i].is_csp_bypassing)
+    }
+    if (internal_schemes[i].is_csp_bypassing) {
       schemes->csp_bypassing_schemes.push_back(internal_schemes[i].scheme_name);
-    client->AddCustomScheme(internal_schemes[i]);
+    }
+    CefAppManager::Get()->AddCustomScheme(&internal_schemes[i]);
   }
 }
 
 bool IsInternalHandledScheme(const std::string& scheme) {
   static const char* schemes[] = {
-    url::kAboutScheme,
-    url::kBlobScheme,
-    content::kChromeDevToolsScheme,
-    content::kChromeUIScheme,
-    url::kDataScheme,
-    extensions::kExtensionScheme,
-    url::kFileScheme,
-    url::kFileSystemScheme,
-#if !BUILDFLAG(DISABLE_FTP_SUPPORT)
-    url::kFtpScheme,
-#endif
-    url::kHttpScheme,
-    url::kHttpsScheme,
-    url::kJavaScriptScheme,
-    url::kWsScheme,
-    url::kWssScheme,
+      url::kAboutScheme,
+      url::kBlobScheme,
+      content::kChromeDevToolsScheme,
+      content::kChromeUIScheme,
+      content::kChromeUIUntrustedScheme,
+      url::kDataScheme,
+      extensions::kExtensionScheme,
+      url::kFileScheme,
+      url::kFileSystemScheme,
+      url::kHttpScheme,
+      url::kHttpsScheme,
+      url::kJavaScriptScheme,
+      url::kWsScheme,
+      url::kWssScheme,
   };
 
   for (size_t i = 0; i < sizeof(schemes) / sizeof(schemes[0]); ++i) {
-    if (scheme == schemes[i])
+    if (scheme == schemes[i]) {
       return true;
+    }
   }
 
   return false;
@@ -82,4 +91,10 @@
   return url::IsStandard(scheme.c_str(), scheme_comp);
 }
 
+// Should return the same value as SecurityOrigin::isLocal and
+// SchemeRegistry::shouldTreatURLSchemeAsCorsEnabled.
+bool IsCorsEnabledScheme(const std::string& scheme) {
+  return base::Contains(url::GetCorsEnabledSchemes(), scheme);
+}
+
 }  // namespace scheme
diff --git a/src/libcef/common/net/scheme_registration.h b/src/libcef/common/net/scheme_registration.h
index c8064fd..dcbdbb6 100644
--- a/src/libcef/common/net/scheme_registration.h
+++ b/src/libcef/common/net/scheme_registration.h
@@ -22,6 +22,9 @@
 // Returns true if the specified |scheme| is a registered standard scheme.
 bool IsStandardScheme(const std::string& scheme);
 
+// Returns true if the specified |scheme| is a registered CORS enabled scheme.
+bool IsCorsEnabledScheme(const std::string& scheme);
+
 }  // namespace scheme
 
 #endif  // CEF_LIBCEF_COMMON_NET_SCHEME_REGISTRATION_H_
diff --git a/src/libcef/common/net/upload_data.cc b/src/libcef/common/net/upload_data.cc
deleted file mode 100644
index a3ca8ed..0000000
--- a/src/libcef/common/net/upload_data.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cef/libcef/common/net/upload_data.h"
-
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-
-namespace net {
-
-UploadData::UploadData()
-    : identifier_(0), is_chunked_(false), last_chunk_appended_(false) {}
-
-void UploadData::AppendBytes(const char* bytes, int bytes_len) {
-  DCHECK(!is_chunked_);
-  if (bytes_len > 0) {
-    elements_.push_back(std::make_unique<UploadElement>());
-    elements_.back()->SetToBytes(bytes, bytes_len);
-  }
-}
-
-void UploadData::AppendFileRange(const base::FilePath& file_path,
-                                 uint64_t offset,
-                                 uint64_t length,
-                                 const base::Time& expected_modification_time) {
-  DCHECK(!is_chunked_);
-  elements_.push_back(std::make_unique<UploadElement>());
-  elements_.back()->SetToFilePathRange(file_path, offset, length,
-                                       expected_modification_time);
-}
-
-UploadData::~UploadData() {}
-
-}  // namespace net
diff --git a/src/libcef/common/net/upload_data.h b/src/libcef/common/net/upload_data.h
deleted file mode 100644
index ef6c960..0000000
--- a/src/libcef/common/net/upload_data.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_COMMON_NET_UPLOAD_DATA_H_
-#define CEF_LIBCEF_COMMON_NET_UPLOAD_DATA_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "libcef/common/net/upload_element.h"
-
-#include "base/memory/ref_counted.h"
-#include "base/supports_user_data.h"
-#include "net/base/net_export.h"
-
-namespace base {
-class FilePath;
-class Time;
-}  // namespace base
-
-namespace net {
-
-//-----------------------------------------------------------------------------
-// A very concrete class representing the data to be uploaded as part of a
-// URLRequest.
-//
-// Until there is a more abstract class for this, this one derives from
-// SupportsUserData to allow users to stash random data by
-// key and ensure its destruction when UploadData is finally deleted.
-class UploadData : public base::RefCounted<UploadData>,
-                   public base::SupportsUserData {
- public:
-  UploadData();
-
-  void AppendBytes(const char* bytes, int bytes_len);
-
-  void AppendFileRange(const base::FilePath& file_path,
-                       uint64_t offset,
-                       uint64_t length,
-                       const base::Time& expected_modification_time);
-
-  // Initializes the object to send chunks of upload data over time rather
-  // than all at once. Chunked data may only contain bytes, not files.
-  void set_is_chunked(bool set) { is_chunked_ = set; }
-  bool is_chunked() const { return is_chunked_; }
-
-  // set_last_chunk_appended() is only used for serialization.
-  void set_last_chunk_appended(bool set) { last_chunk_appended_ = set; }
-  bool last_chunk_appended() const { return last_chunk_appended_; }
-
-  using ElementsVector = std::vector<std::unique_ptr<UploadElement>>;
-
-  const ElementsVector& elements() const { return elements_; }
-
-  ElementsVector* elements_mutable() { return &elements_; }
-
-  void swap_elements(ElementsVector* elements) { elements_.swap(*elements); }
-
-  // Identifies a particular upload instance, which is used by the cache to
-  // formulate a cache key.  This value should be unique across browser
-  // sessions.  A value of 0 is used to indicate an unspecified identifier.
-  void set_identifier(int64_t id) { identifier_ = id; }
-  int64_t identifier() const { return identifier_; }
-
- private:
-  friend class base::RefCounted<UploadData>;
-
-  ~UploadData() override;
-
-  ElementsVector elements_;
-  int64_t identifier_;
-  bool is_chunked_;
-  bool last_chunk_appended_;
-
-  DISALLOW_COPY_AND_ASSIGN(UploadData);
-};
-
-}  // namespace net
-
-#endif  // CEF_LIBCEF_COMMON_NET_UPLOAD_DATA_H_
diff --git a/src/libcef/common/net/upload_element.cc b/src/libcef/common/net/upload_element.cc
deleted file mode 100644
index 1a401bc..0000000
--- a/src/libcef/common/net/upload_element.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/common/net/upload_element.h"
-
-#include "net/base/file_stream.h"
-#include "net/base/net_errors.h"
-
-namespace net {
-
-UploadElement::UploadElement()
-    : type_(TYPE_BYTES),
-      bytes_start_(nullptr),
-      bytes_length_(0),
-      file_range_offset_(0),
-      file_range_length_(std::numeric_limits<uint64_t>::max()) {}
-
-UploadElement::~UploadElement() {}
-
-}  // namespace net
diff --git a/src/libcef/common/net/upload_element.h b/src/libcef/common/net/upload_element.h
deleted file mode 100644
index 9fb487d..0000000
--- a/src/libcef/common/net/upload_element.h
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_COMMON_NET_UPLOAD_ELEMENT_H_
-#define CEF_LIBCEF_COMMON_NET_UPLOAD_ELEMENT_H_
-
-#include <stdint.h>
-
-#include <limits>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/time/time.h"
-#include "net/base/net_export.h"
-
-namespace net {
-
-// A class representing an element contained by UploadData.
-class UploadElement {
- public:
-  enum Type {
-    TYPE_BYTES,
-    TYPE_FILE,
-  };
-
-  UploadElement();
-  ~UploadElement();
-
-  Type type() const { return type_; }
-
-  const char* bytes() const { return bytes_start_ ? bytes_start_ : &buf_[0]; }
-  uint64_t bytes_length() const { return buf_.size() + bytes_length_; }
-  const base::FilePath& file_path() const { return file_path_; }
-  uint64_t file_range_offset() const { return file_range_offset_; }
-  uint64_t file_range_length() const { return file_range_length_; }
-  // If NULL time is returned, we do not do the check.
-  const base::Time& expected_file_modification_time() const {
-    return expected_file_modification_time_;
-  }
-
-  void SetToBytes(const char* bytes, int bytes_len) {
-    type_ = TYPE_BYTES;
-    buf_.assign(bytes, bytes + bytes_len);
-  }
-
-  // This does not copy the given data and the caller should make sure
-  // the data is secured somewhere else (e.g. by attaching the data
-  // using SetUserData).
-  void SetToSharedBytes(const char* bytes, int bytes_len) {
-    type_ = TYPE_BYTES;
-    bytes_start_ = bytes;
-    bytes_length_ = bytes_len;
-  }
-
-  void SetToFilePath(const base::FilePath& path) {
-    SetToFilePathRange(path, 0, std::numeric_limits<uint64_t>::max(),
-                       base::Time());
-  }
-
-  // If expected_modification_time is NULL, we do not check for the file
-  // change. Also note that the granularity for comparison is time_t, not
-  // the full precision.
-  void SetToFilePathRange(const base::FilePath& path,
-                          uint64_t offset,
-                          uint64_t length,
-                          const base::Time& expected_modification_time) {
-    type_ = TYPE_FILE;
-    file_path_ = path;
-    file_range_offset_ = offset;
-    file_range_length_ = length;
-    expected_file_modification_time_ = expected_modification_time;
-  }
-
- private:
-  Type type_;
-  std::vector<char> buf_;
-  const char* bytes_start_;
-  uint64_t bytes_length_;
-  base::FilePath file_path_;
-  uint64_t file_range_offset_;
-  uint64_t file_range_length_;
-  base::Time expected_file_modification_time_;
-
-  DISALLOW_COPY_AND_ASSIGN(UploadElement);
-};
-
-#if defined(UNIT_TEST)
-inline bool operator==(const UploadElement& a, const UploadElement& b) {
-  if (a.type() != b.type())
-    return false;
-  if (a.type() == UploadElement::TYPE_BYTES)
-    return a.bytes_length() == b.bytes_length() &&
-           memcmp(a.bytes(), b.bytes(), b.bytes_length()) == 0;
-  if (a.type() == UploadElement::TYPE_FILE) {
-    return a.file_path() == b.file_path() &&
-           a.file_range_offset() == b.file_range_offset() &&
-           a.file_range_length() == b.file_range_length() &&
-           a.expected_file_modification_time() ==
-               b.expected_file_modification_time();
-  }
-  return false;
-}
-
-inline bool operator!=(const UploadElement& a, const UploadElement& b) {
-  return !(a == b);
-}
-#endif  // defined(UNIT_TEST)
-
-}  // namespace net
-
-#endif  // CEF_LIBCEF_COMMON_NET_UPLOAD_ELEMENT_H_
diff --git a/src/libcef/common/net/url_util.cc b/src/libcef/common/net/url_util.cc
new file mode 100644
index 0000000..710601d
--- /dev/null
+++ b/src/libcef/common/net/url_util.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 2021 The Chromium Embedded Framework 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 "libcef/common/net/url_util.h"
+
+#include "base/logging.h"
+#include "components/url_formatter/url_fixer.h"
+
+namespace url_util {
+
+GURL MakeGURL(const CefString& url, bool fixup) {
+  GURL gurl = GURL(url.ToString());
+  if (!url.empty() && !gurl.is_valid() && !gurl.has_scheme()) {
+    std::string fixed_scheme(url::kHttpScheme);
+    fixed_scheme.append(url::kStandardSchemeSeparator);
+    std::string new_url = url;
+    new_url.insert(0, fixed_scheme);
+    gurl = GURL(new_url);
+  }
+  if (fixup) {
+    FixupGURL(gurl);
+  }
+  return gurl;
+}
+
+bool FixupGURL(GURL& gurl) {
+  if (!gurl.is_empty()) {
+    GURL fixup_url =
+        url_formatter::FixupURL(gurl.possibly_invalid_spec(), std::string());
+    if (fixup_url.is_valid()) {
+      gurl = fixup_url;
+    } else {
+      LOG(ERROR) << "Invalid URL: " << gurl.possibly_invalid_spec();
+      gurl = GURL();
+      return false;
+    }
+  }
+  return true;
+}
+
+}  // namespace url_util
diff --git a/src/libcef/common/net/url_util.h b/src/libcef/common/net/url_util.h
new file mode 100644
index 0000000..d5c0112
--- /dev/null
+++ b/src/libcef/common/net/url_util.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2021 The Chromium Embedded Framework 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 CEF_LIBCEF_COMMON_NET_URL_UTIL_H_
+#define CEF_LIBCEF_COMMON_NET_URL_UTIL_H_
+#pragma once
+
+#include "include/cef_base.h"
+
+class GURL;
+
+namespace url_util {
+
+// Convert |url| to a GURL, adding a scheme prefix if necessary.
+// If |fixup| is true then FixupGURL() will also be called.
+GURL MakeGURL(const CefString& url, bool fixup);
+
+// Fix common problems with user-typed text. Among other things, this:
+// - Converts absolute file paths to "file://" URLs.
+// - Normalizes "about:" and "chrome:" to "chrome://" URLs
+// Modifies |gurl| if necessary. Returns true if |gurl| is empty or valid.
+bool FixupGURL(GURL& gurl);
+
+}  // namespace url_util
+
+#endif  // CEF_LIBCEF_COMMON_NET_URL_UTIL_H_
diff --git a/src/libcef/common/net_service/net_service_util.cc b/src/libcef/common/net_service/net_service_util.cc
index 3f68e24..d8cd3eb 100644
--- a/src/libcef/common/net_service/net_service_util.cc
+++ b/src/libcef/common/net_service/net_service_util.cc
@@ -5,6 +5,7 @@
 
 #include "libcef/common/net_service/net_service_util.h"
 
+#include "include/internal/cef_time_wrappers.h"
 #include "libcef/common/time_util.h"
 
 #include <set>
@@ -19,6 +20,7 @@
 #include "net/http/http_status_code.h"
 #include "net/url_request/redirect_info.h"
 #include "net/url_request/redirect_util.h"
+#include "net/url_request/referrer_policy.h"
 #include "net/url_request/url_request.h"
 #include "services/network/public/cpp/resource_request.h"
 
@@ -27,14 +29,16 @@
 namespace {
 
 // Determine the cookie domain to use for setting the specified cookie.
-// From net/cookies/cookie_store.cc.
+// From net/cookies/canonical_cookie.cc.
 bool GetCookieDomain(const GURL& url,
                      const net::ParsedCookie& pc,
                      std::string* result) {
   std::string domain_string;
-  if (pc.HasDomain())
+  if (pc.HasDomain()) {
     domain_string = pc.Domain();
-  return net::cookie_util::GetCookieDomainWithString(url, domain_string,
+  }
+  net::CookieInclusionStatus status;
+  return net::cookie_util::GetCookieDomainWithString(url, domain_string, status,
                                                      result);
 }
 
@@ -70,15 +74,6 @@
 const char kContentTypeApplicationFormURLEncoded[] =
     "application/x-www-form-urlencoded";
 
-const char kHTTPHeaderSep[] = ": ";
-
-std::string MakeHeader(const std::string& name, const std::string& value) {
-  std::string header(name);
-  header.append(kHTTPHeaderSep);
-  header.append(value);
-  return header;
-}
-
 std::string MakeStatusLine(int status_code,
                            const std::string& status_text,
                            bool for_replacement) {
@@ -122,8 +117,9 @@
     int64_t content_length,
     const std::multimap<std::string, std::string>& extra_headers,
     bool allow_existing_header_override) {
-  if (status_code <= 0)
+  if (status_code <= 0) {
     status_code = 200;
+  }
 
   auto headers = WrapRefCounted(new net::HttpResponseHeaders(
       MakeStatusLine(status_code, status_text, false)));
@@ -135,15 +131,15 @@
       status_code != net::HTTP_NO_CONTENT &&
       status_code != net::HTTP_RESET_CONTENT) {
     if (!mime_type.empty()) {
-      headers->AddHeader(MakeHeader(net::HttpRequestHeaders::kContentType,
-                                    MakeContentTypeValue(mime_type, charset)));
+      headers->AddHeader(net::HttpRequestHeaders::kContentType,
+                         MakeContentTypeValue(mime_type, charset));
       set_headers_lowercase.insert(
           base::ToLowerASCII(net::HttpRequestHeaders::kContentType));
     }
 
     if (content_length >= 0) {
-      headers->AddHeader(MakeHeader(net::HttpRequestHeaders::kContentLength,
-                                    base::NumberToString(content_length)));
+      headers->AddHeader(net::HttpRequestHeaders::kContentLength,
+                         base::NumberToString(content_length));
       set_headers_lowercase.insert(
           base::ToLowerASCII(net::HttpRequestHeaders::kContentLength));
     }
@@ -155,14 +151,15 @@
       const std::string& name_lowercase = base::ToLowerASCII(pair.first);
       if (set_headers_lowercase.find(name_lowercase) !=
           set_headers_lowercase.end()) {
-        if (allow_existing_header_override)
+        if (allow_existing_header_override) {
           headers->RemoveHeader(pair.first);
-        else
+        } else {
           continue;
+        }
       }
     }
 
-    headers->AddHeader(MakeHeader(pair.first, pair.second));
+    headers->AddHeader(pair.first, pair.second);
   }
 
   return headers;
@@ -175,8 +172,9 @@
   bool insecure_scheme_was_upgraded = false;
 
   GURL location = new_location;
-  if (status_code == 0)
+  if (status_code == 0) {
     status_code = net::HTTP_TEMPORARY_REDIRECT;
+  }
 
   // If this a redirect to HTTP of a request that had the
   // 'upgrade-insecure-requests' policy set, upgrade it to HTTPS.
@@ -189,10 +187,10 @@
     }
   }
 
-  net::URLRequest::FirstPartyURLPolicy first_party_url_policy =
+  auto first_party_url_policy =
       request.update_first_party_url_on_redirect
-          ? net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT
-          : net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL;
+          ? net::RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT
+          : net::RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL;
   return net::RedirectInfo::ComputeRedirectInfo(
       request.method, request.url, request.site_for_cookies,
       first_party_url_policy, request.referrer_policy, request.referrer.spec(),
@@ -232,11 +230,12 @@
   CefString(&cookie.path).FromString(cc.Path());
   cookie.secure = cc.IsSecure();
   cookie.httponly = cc.IsHttpOnly();
-  cef_time_from_basetime(cc.CreationDate(), cookie.creation);
-  cef_time_from_basetime(cc.LastAccessDate(), cookie.last_access);
+  cookie.creation = CefBaseTime(cc.CreationDate());
+  cookie.last_access = CefBaseTime(cc.LastAccessDate());
   cookie.has_expires = cc.IsPersistent();
-  if (cookie.has_expires)
-    cef_time_from_basetime(cc.ExpiryDate(), cookie.expires);
+  if (cookie.has_expires) {
+    cookie.expires = CefBaseTime(cc.ExpiryDate());
+  }
   cookie.same_site = MakeCefCookieSameSite(cc.SameSite());
   cookie.priority = MakeCefCookiePriority(cc.Priority());
 
@@ -248,21 +247,24 @@
                    CefCookie& cookie) {
   // Parse the cookie.
   net::ParsedCookie pc(cookie_line);
-  if (!pc.IsValid())
+  if (!pc.IsValid()) {
     return false;
+  }
 
   std::string cookie_domain;
-  if (!GetCookieDomain(url, pc, &cookie_domain))
+  if (!GetCookieDomain(url, pc, &cookie_domain)) {
     return false;
+  }
 
   std::string path_string;
-  if (pc.HasPath())
+  if (pc.HasPath()) {
     path_string = pc.Path();
+  }
   std::string cookie_path =
       net::CanonicalCookie::CanonPathWithString(url, path_string);
   base::Time creation_time = base::Time::Now();
   base::Time cookie_expires =
-      net::CanonicalCookie::CanonExpiration(pc, creation_time, creation_time);
+      net::CanonicalCookie::ParseExpiration(pc, creation_time, creation_time);
 
   CefString(&cookie.name).FromString(pc.Name());
   CefString(&cookie.value).FromString(pc.Value());
@@ -270,11 +272,12 @@
   CefString(&cookie.path).FromString(cookie_path);
   cookie.secure = pc.IsSecure();
   cookie.httponly = pc.IsHttpOnly();
-  cef_time_from_basetime(creation_time, cookie.creation);
-  cef_time_from_basetime(creation_time, cookie.last_access);
+  cookie.creation = CefBaseTime(creation_time);
+  cookie.last_access = CefBaseTime(creation_time);
   cookie.has_expires = !cookie_expires.is_null();
-  if (cookie.has_expires)
-    cef_time_from_basetime(cookie_expires, cookie.expires);
+  if (cookie.has_expires) {
+    cookie.expires = CefBaseTime(cookie_expires);
+  }
   cookie.same_site = MakeCefCookieSameSite(pc.SameSite());
   cookie.priority = MakeCefCookiePriority(pc.Priority());
 
diff --git a/src/libcef/common/net_service/net_service_util.h b/src/libcef/common/net_service/net_service_util.h
index 83e34b3..0eaa62d 100644
--- a/src/libcef/common/net_service/net_service_util.h
+++ b/src/libcef/common/net_service/net_service_util.h
@@ -34,9 +34,6 @@
 // HTTP header values.
 extern const char kContentTypeApplicationFormURLEncoded[];
 
-// Make a header name/value pair.
-std::string MakeHeader(const std::string& name, const std::string& value);
-
 // Make an HTTP response status line.
 // Set |for_replacement| to true if the result will be passed to
 // HttpResponseHeaders::ReplaceStatusLine and false if the result will
diff --git a/src/libcef/common/parser_impl.cc b/src/libcef/common/parser_impl.cc
index cd95b3b..c0e25c8 100644
--- a/src/libcef/common/parser_impl.cc
+++ b/src/libcef/common/parser_impl.cc
@@ -7,23 +7,41 @@
 #include "include/cef_parser.h"
 
 #include "base/base64.h"
+#include "base/strings/escape.h"
 #include "base/threading/thread_restrictions.h"
 #include "components/url_formatter/elide_url.h"
-#include "net/base/escape.h"
 #include "net/base/mime_util.h"
 #include "url/gurl.h"
 
+bool CefResolveURL(const CefString& base_url,
+                   const CefString& relative_url,
+                   CefString& resolved_url) {
+  GURL base_gurl(base_url.ToString());
+  if (!base_gurl.is_valid()) {
+    return false;
+  }
+
+  GURL combined_gurl = base_gurl.Resolve(relative_url.ToString());
+  if (!combined_gurl.is_valid()) {
+    return false;
+  }
+
+  resolved_url = combined_gurl.spec();
+  return true;
+}
+
 bool CefParseURL(const CefString& url, CefURLParts& parts) {
   GURL gurl(url.ToString());
-  if (!gurl.is_valid())
+  if (!gurl.is_valid()) {
     return false;
+  }
 
   CefString(&parts.spec).FromString(gurl.spec());
   CefString(&parts.scheme).FromString(gurl.scheme());
   CefString(&parts.username).FromString(gurl.username());
   CefString(&parts.password).FromString(gurl.password());
   CefString(&parts.host).FromString(gurl.host());
-  CefString(&parts.origin).FromString(gurl.GetOrigin().spec());
+  CefString(&parts.origin).FromString(gurl.DeprecatedGetOriginAsURL().spec());
   CefString(&parts.port).FromString(gurl.port());
   CefString(&parts.path).FromString(gurl.path());
   CefString(&parts.query).FromString(gurl.query());
@@ -54,19 +72,24 @@
     ss << scheme << "://";
     if (!username.empty()) {
       ss << username;
-      if (!password.empty())
+      if (!password.empty()) {
         ss << ":" << password;
+      }
       ss << "@";
     }
     ss << host;
-    if (!port.empty())
+    if (!port.empty()) {
       ss << ":" << port;
-    if (!path.empty())
+    }
+    if (!path.empty()) {
       ss << path;
-    if (!query.empty())
+    }
+    if (!query.empty()) {
       ss << "?" << query;
-    if (!fragment.empty())
+    }
+    if (!fragment.empty()) {
       ss << "#" << fragment;
+    }
     gurl = GURL(ss.str());
   }
 
@@ -86,7 +109,7 @@
 CefString CefGetMimeType(const CefString& extension) {
   // Requests should not block on the disk!  On POSIX this goes to disk.
   // http://code.google.com/p/chromium/issues/detail?id=59849
-  base::ThreadRestrictions::ScopedAllowIO allow_io;
+  base::ScopedAllowBlockingForTesting allow_blocking;
 
   std::string mime_type;
   net::GetMimeTypeFromExtension(extension, &mime_type);
@@ -95,17 +118,19 @@
 
 void CefGetExtensionsForMimeType(const CefString& mime_type,
                                  std::vector<CefString>& extensions) {
-  typedef std::vector<base::FilePath::StringType> VectorType;
+  using VectorType = std::vector<base::FilePath::StringType>;
   VectorType ext;
   net::GetExtensionsForMimeType(mime_type, &ext);
   VectorType::const_iterator it = ext.begin();
-  for (; it != ext.end(); ++it)
+  for (; it != ext.end(); ++it) {
     extensions.push_back(*it);
+  }
 }
 
 CefString CefBase64Encode(const void* data, size_t data_size) {
-  if (data_size == 0)
+  if (data_size == 0) {
     return CefString();
+  }
 
   base::StringPiece input(static_cast<const char*>(data), data_size);
   std::string output;
@@ -114,28 +139,31 @@
 }
 
 CefRefPtr<CefBinaryValue> CefBase64Decode(const CefString& data) {
-  if (data.size() == 0)
+  if (data.size() == 0) {
     return nullptr;
+  }
 
   const std::string& input = data;
   std::string output;
-  if (base::Base64Decode(input, &output))
+  if (base::Base64Decode(input, &output)) {
     return CefBinaryValue::Create(output.data(), output.size());
+  }
   return nullptr;
 }
 
 CefString CefURIEncode(const CefString& text, bool use_plus) {
-  return net::EscapeQueryParamValue(text.ToString(), use_plus);
+  return base::EscapeQueryParamValue(text.ToString(), use_plus);
 }
 
 CefString CefURIDecode(const CefString& text,
                        bool convert_to_utf8,
                        cef_uri_unescape_rule_t unescape_rule) {
-  const net::UnescapeRule::Type type =
-      static_cast<net::UnescapeRule::Type>(unescape_rule);
-  if (convert_to_utf8)
-    return net::UnescapeAndDecodeUTF8URLComponentWithAdjustments(
+  const base::UnescapeRule::Type type =
+      static_cast<base::UnescapeRule::Type>(unescape_rule);
+  if (convert_to_utf8) {
+    return base::UnescapeAndDecodeUTF8URLComponentWithAdjustments(
         text.ToString(), type, nullptr);
-  else
-    return net::UnescapeURLComponent(text.ToString(), type);
+  } else {
+    return base::UnescapeURLComponent(text.ToString(), type);
+  }
 }
diff --git a/src/libcef/common/process_message_impl.cc b/src/libcef/common/process_message_impl.cc
index ed6510c..e90ef83 100644
--- a/src/libcef/common/process_message_impl.cc
+++ b/src/libcef/common/process_message_impl.cc
@@ -3,68 +3,63 @@
 // can be found in the LICENSE file.
 
 #include "libcef/common/process_message_impl.h"
-#include "libcef/common/cef_messages.h"
+
+#include <memory>
+
 #include "libcef/common/values_impl.h"
 
 #include "base/logging.h"
 
-namespace {
-
-void CopyValue(const Cef_Request_Params& source, Cef_Request_Params& target) {
-  target.name = source.name;
-  auto copy = source.arguments.CreateDeepCopy();
-  target.arguments.Swap(copy.get());
-}
-
-}  // namespace
-
 // static
 CefRefPtr<CefProcessMessage> CefProcessMessage::Create(const CefString& name) {
-  Cef_Request_Params* params = new Cef_Request_Params();
-  params->name = name;
-  return new CefProcessMessageImpl(params, true, false);
+  return new CefProcessMessageImpl(name, CefListValue::Create());
 }
 
-CefProcessMessageImpl::CefProcessMessageImpl(Cef_Request_Params* value,
-                                             bool will_delete,
-                                             bool read_only)
-    : CefValueBase<CefProcessMessage, Cef_Request_Params>(
-          value,
-          nullptr,
-          will_delete ? kOwnerWillDelete : kOwnerNoDelete,
-          read_only,
-          nullptr) {}
+CefProcessMessageImpl::CefProcessMessageImpl(const CefString& name,
+                                             CefRefPtr<CefListValue> arguments)
+    : name_(name), arguments_(arguments) {
+  DCHECK(!name_.empty());
+  DCHECK(arguments_ && arguments_->IsValid());
+}
 
-bool CefProcessMessageImpl::CopyTo(Cef_Request_Params& target) {
-  CEF_VALUE_VERIFY_RETURN(false, false);
-  CopyValue(const_value(), target);
-  return true;
+CefProcessMessageImpl::CefProcessMessageImpl(const CefString& name,
+                                             base::Value::List arguments,
+                                             bool read_only)
+    : name_(name) {
+  DCHECK(!name_.empty());
+
+  arguments_ = new CefListValueImpl(std::move(arguments), read_only);
+}
+
+CefProcessMessageImpl::~CefProcessMessageImpl() = default;
+
+base::Value::List CefProcessMessageImpl::TakeArgumentList() {
+  DCHECK(IsValid());
+  CefListValueImpl* value_impl =
+      static_cast<CefListValueImpl*>(arguments_.get());
+  auto value = value_impl->CopyOrDetachValue(nullptr);
+  return std::move(value->GetList());
 }
 
 bool CefProcessMessageImpl::IsValid() {
-  return !detached();
+  return arguments_->IsValid();
 }
 
 bool CefProcessMessageImpl::IsReadOnly() {
-  return read_only();
+  return arguments_->IsReadOnly();
 }
 
 CefRefPtr<CefProcessMessage> CefProcessMessageImpl::Copy() {
-  CEF_VALUE_VERIFY_RETURN(false, nullptr);
-  Cef_Request_Params* params = new Cef_Request_Params();
-  CopyValue(const_value(), *params);
-  return new CefProcessMessageImpl(params, true, false);
+  if (!IsValid()) {
+    return nullptr;
+  }
+  return new CefProcessMessageImpl(name_, arguments_->Copy());
 }
 
 CefString CefProcessMessageImpl::GetName() {
-  CEF_VALUE_VERIFY_RETURN(false, CefString());
-  return const_value().name;
+  return name_;
 }
 
 CefRefPtr<CefListValue> CefProcessMessageImpl::GetArgumentList() {
-  CEF_VALUE_VERIFY_RETURN(false, nullptr);
-  return CefListValueImpl::GetOrCreateRef(
-      const_cast<base::ListValue*>(&(const_value().arguments)),
-      const_cast<Cef_Request_Params*>(&const_value()), read_only(),
-      controller());
+  return arguments_;
 }
diff --git a/src/libcef/common/process_message_impl.h b/src/libcef/common/process_message_impl.h
index 30dfc72..eadeca1 100644
--- a/src/libcef/common/process_message_impl.h
+++ b/src/libcef/common/process_message_impl.h
@@ -7,20 +7,32 @@
 #pragma once
 
 #include "include/cef_process_message.h"
-#include "libcef/common/value_base.h"
 
-struct Cef_Request_Params;
+#include "base/values.h"
 
-// CefProcessMessage implementation
-class CefProcessMessageImpl
-    : public CefValueBase<CefProcessMessage, Cef_Request_Params> {
+// CefProcessMessage implementation.
+class CefProcessMessageImpl : public CefProcessMessage {
  public:
-  CefProcessMessageImpl(Cef_Request_Params* value,
-                        bool will_delete,
+  // Constructor for referencing existing |arguments|.
+  CefProcessMessageImpl(const CefString& name,
+                        CefRefPtr<CefListValue> arguments);
+
+  // Constructor for creating a new CefListValue that takes ownership of
+  // |arguments|.
+  CefProcessMessageImpl(const CefString& name,
+                        base::Value::List arguments,
                         bool read_only);
 
-  // Copies the underlying value to the specified |target| structure.
-  bool CopyTo(Cef_Request_Params& target);
+  CefProcessMessageImpl(const CefProcessMessageImpl&) = delete;
+  CefProcessMessageImpl& operator=(const CefProcessMessageImpl&) = delete;
+
+  ~CefProcessMessageImpl() override;
+
+  // Transfer ownership of the underlying argument list to the caller, or create
+  // a copy if the argument list is already owned by something else.
+  // TODO: Pass by reference instead of ownership if/when Mojo adds support
+  // for that.
+  [[nodiscard]] base::Value::List TakeArgumentList();
 
   // CefProcessMessage methods.
   bool IsValid() override;
@@ -28,8 +40,15 @@
   CefRefPtr<CefProcessMessage> Copy() override;
   CefString GetName() override;
   CefRefPtr<CefListValue> GetArgumentList() override;
+  CefRefPtr<CefSharedMemoryRegion> GetSharedMemoryRegion() override {
+    return nullptr;
+  }
 
-  DISALLOW_COPY_AND_ASSIGN(CefProcessMessageImpl);
+ private:
+  const CefString name_;
+  CefRefPtr<CefListValue> arguments_;
+
+  IMPLEMENT_REFCOUNTING(CefProcessMessageImpl);
 };
 
 #endif  // CEF_LIBCEF_COMMON_PROCESS_MESSAGE_IMPL_H_
diff --git a/src/libcef/common/process_message_smr_impl.cc b/src/libcef/common/process_message_smr_impl.cc
new file mode 100644
index 0000000..922b272
--- /dev/null
+++ b/src/libcef/common/process_message_smr_impl.cc
@@ -0,0 +1,94 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "libcef/common/process_message_smr_impl.h"
+
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/shared_memory_mapping.h"
+
+namespace {
+
+class CefSharedMemoryRegionImpl final : public CefSharedMemoryRegion {
+ public:
+  CefSharedMemoryRegionImpl(base::WritableSharedMemoryMapping&& mapping)
+      : mapping_(std::move(mapping)) {}
+  CefSharedMemoryRegionImpl(const CefSharedMemoryRegionImpl&) = delete;
+  CefSharedMemoryRegionImpl& operator=(const CefSharedMemoryRegionImpl&) =
+      delete;
+
+  // CefSharedMemoryRegion methods
+  bool IsValid() override { return mapping_.IsValid(); }
+  size_t Size() override { return IsValid() ? mapping_.size() : 0; }
+  void* Memory() override { return mapping_.memory(); }
+
+ private:
+  base::WritableSharedMemoryMapping mapping_;
+  IMPLEMENT_REFCOUNTING(CefSharedMemoryRegionImpl);
+};
+
+}  // namespace
+
+CefProcessMessageSMRImpl::CefProcessMessageSMRImpl(
+    const CefString& name,
+    base::WritableSharedMemoryRegion&& region)
+    : name_(name), region_(std::move(region)) {
+  DCHECK(!name_.empty());
+  DCHECK(region_.IsValid());
+}
+
+CefProcessMessageSMRImpl::~CefProcessMessageSMRImpl() = default;
+
+bool CefProcessMessageSMRImpl::IsValid() {
+  return region_.IsValid();
+}
+
+CefString CefProcessMessageSMRImpl::GetName() {
+  return name_;
+}
+
+CefRefPtr<CefSharedMemoryRegion>
+CefProcessMessageSMRImpl::GetSharedMemoryRegion() {
+  return new CefSharedMemoryRegionImpl(region_.Map());
+}
+
+base::WritableSharedMemoryRegion CefProcessMessageSMRImpl::TakeRegion() {
+  return std::move(region_);
+}
+
+// static
+CefRefPtr<CefSharedProcessMessageBuilder>
+CefSharedProcessMessageBuilder::Create(const CefString& name,
+                                       size_t byte_size) {
+  return new CefSharedProcessMessageBuilderImpl(name, byte_size);
+}
+
+CefSharedProcessMessageBuilderImpl::CefSharedProcessMessageBuilderImpl(
+    const CefString& name,
+    size_t byte_size)
+    : name_(name),
+      region_(base::WritableSharedMemoryRegion::Create(byte_size)),
+      mapping_(region_.Map()) {}
+
+bool CefSharedProcessMessageBuilderImpl::IsValid() {
+  return region_.IsValid() && mapping_.IsValid();
+}
+
+size_t CefSharedProcessMessageBuilderImpl::Size() {
+  return !IsValid() ? 0 : region_.GetSize();
+}
+
+void* CefSharedProcessMessageBuilderImpl::Memory() {
+  return !IsValid() ? nullptr : mapping_.memory();
+}
+
+CefRefPtr<CefProcessMessage> CefSharedProcessMessageBuilderImpl::Build() {
+  if (!IsValid()) {
+    return nullptr;
+  }
+
+  // Invalidate mappping
+  mapping_ = base::WritableSharedMemoryMapping();
+  return new CefProcessMessageSMRImpl(name_, std::move(region_));
+}
\ No newline at end of file
diff --git a/src/libcef/common/process_message_smr_impl.h b/src/libcef/common/process_message_smr_impl.h
new file mode 100644
index 0000000..1f36feb
--- /dev/null
+++ b/src/libcef/common/process_message_smr_impl.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_COMMON_PROCESS_MESSAGE_SMR_IMPL_H_
+#define CEF_LIBCEF_COMMON_PROCESS_MESSAGE_SMR_IMPL_H_
+#pragma once
+
+#include "include/cef_process_message.h"
+#include "include/cef_shared_process_message_builder.h"
+
+#include "base/memory/writable_shared_memory_region.h"
+
+class CefProcessMessageSMRImpl final : public CefProcessMessage {
+ public:
+  CefProcessMessageSMRImpl(const CefString& name,
+                           base::WritableSharedMemoryRegion&& region);
+  CefProcessMessageSMRImpl(const CefProcessMessageSMRImpl&) = delete;
+  CefProcessMessageSMRImpl& operator=(const CefProcessMessageSMRImpl&) = delete;
+  ~CefProcessMessageSMRImpl() override;
+
+  // CefProcessMessage methods.
+  bool IsValid() override;
+  bool IsReadOnly() override { return true; }
+  CefRefPtr<CefProcessMessage> Copy() override { return nullptr; }
+  CefString GetName() override;
+  CefRefPtr<CefListValue> GetArgumentList() override { return nullptr; }
+  CefRefPtr<CefSharedMemoryRegion> GetSharedMemoryRegion() override;
+  [[nodiscard]] base::WritableSharedMemoryRegion TakeRegion();
+
+ private:
+  const CefString name_;
+  base::WritableSharedMemoryRegion region_;
+
+  IMPLEMENT_REFCOUNTING(CefProcessMessageSMRImpl);
+};
+
+class CefSharedProcessMessageBuilderImpl final
+    : public CefSharedProcessMessageBuilder {
+ public:
+  CefSharedProcessMessageBuilderImpl(const CefString& name, size_t byte_size);
+  CefSharedProcessMessageBuilderImpl(const CefProcessMessageSMRImpl&) = delete;
+  CefSharedProcessMessageBuilderImpl& operator=(
+      const CefSharedProcessMessageBuilderImpl&) = delete;
+
+  bool IsValid() override;
+  size_t Size() override;
+  void* Memory() override;
+  CefRefPtr<CefProcessMessage> Build() override;
+
+ private:
+  const CefString name_;
+  base::WritableSharedMemoryRegion region_;
+  base::WritableSharedMemoryMapping mapping_;
+
+  IMPLEMENT_REFCOUNTING(CefSharedProcessMessageBuilderImpl);
+};
+
+#endif  // CEF_LIBCEF_COMMON_PROCESS_MESSAGE_SMR_IMPL_H_
diff --git a/src/libcef/common/request_impl.cc b/src/libcef/common/request_impl.cc
index 05f7c54..0244180 100644
--- a/src/libcef/common/request_impl.cc
+++ b/src/libcef/common/request_impl.cc
@@ -8,20 +8,17 @@
 #include <utility>
 #include <vector>
 
-#include "libcef/browser/navigate_params.h"
-#include "libcef/common/cef_messages.h"
 #include "libcef/common/net/http_header_utils.h"
-#include "libcef/common/net/upload_data.h"
 #include "libcef/common/net_service/net_service_util.h"
 #include "libcef/common/request_impl.h"
 
 #include "base/command_line.h"
 #include "base/logging.h"
+#include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
-#include "components/navigation_interception/navigation_params.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/navigation_handle.h"
 #include "content/public/common/content_switches.h"
 #include "net/base/elements_upload_data_stream.h"
 #include "net/base/load_flags.h"
@@ -32,6 +29,7 @@
 #include "net/http/http_request_headers.h"
 #include "net/http/http_util.h"
 #include "net/url_request/redirect_info.h"
+#include "net/url_request/referrer_policy.h"
 #include "services/network/public/cpp/data_element.h"
 #include "services/network/public/cpp/network_switches.h"
 #include "services/network/public/cpp/resource_request.h"
@@ -43,64 +41,19 @@
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/platform/web_url_error.h"
 #include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/public/platform/web_url_request_util.h"
 #include "third_party/blink/public/web/web_security_policy.h"
 
 namespace {
 
-const char kReferrerLowerCase[] = "referer";
-const char kCacheControlLowerCase[] = "cache-control";
-const char kCacheControlDirectiveNoCacheLowerCase[] = "no-cache";
-const char kCacheControlDirectiveNoStoreLowerCase[] = "no-store";
-const char kCacheControlDirectiveOnlyIfCachedLowerCase[] = "only-if-cached";
+const char kCacheControlDirectiveNoCache[] = "no-cache";
+const char kCacheControlDirectiveNoStore[] = "no-store";
+const char kCacheControlDirectiveOnlyIfCached[] = "only-if-cached";
 
 // Mask of values that configure the cache policy.
 const int kURCachePolicyMask =
     (UR_FLAG_SKIP_CACHE | UR_FLAG_ONLY_FROM_CACHE | UR_FLAG_DISABLE_CACHE);
 
-// A subclass of net::UploadBytesElementReader that keeps the associated
-// UploadElement alive until the request completes.
-class BytesElementReader : public net::UploadBytesElementReader {
- public:
-  explicit BytesElementReader(std::unique_ptr<net::UploadElement> element)
-      : net::UploadBytesElementReader(element->bytes(),
-                                      element->bytes_length()),
-        element_(std::move(element)) {
-    DCHECK_EQ(net::UploadElement::TYPE_BYTES, element_->type());
-  }
-
- private:
-  std::unique_ptr<net::UploadElement> element_;
-
-  DISALLOW_COPY_AND_ASSIGN(BytesElementReader);
-};
-
-scoped_refptr<base::SequencedTaskRunner> GetFileTaskRunner() {
-  return base::CreateSequencedTaskRunner(
-      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE});
-}
-
-// A subclass of net::UploadFileElementReader that keeps the associated
-// UploadElement alive until the request completes.
-class FileElementReader : public net::UploadFileElementReader {
- public:
-  explicit FileElementReader(std::unique_ptr<net::UploadElement> element)
-      : net::UploadFileElementReader(
-            GetFileTaskRunner().get(),
-            element->file_path(),
-            element->file_range_offset(),
-            element->file_range_length(),
-            element->expected_file_modification_time()),
-        element_(std::move(element)) {
-    DCHECK_EQ(net::UploadElement::TYPE_FILE, element_->type());
-  }
-
- private:
-  scoped_refptr<base::SequencedTaskRunner> task_runner_;
-  std::unique_ptr<net::UploadElement> element_;
-
-  DISALLOW_COPY_AND_ASSIGN(FileElementReader);
-};
-
 // Returns the cef_urlrequest_flags_t policy specified by the Cache-Control
 // request header directives, if any. The directives are case-insensitive and
 // some have an optional argument. Multiple directives are comma-separated.
@@ -113,8 +66,8 @@
   {
     CefRequest::HeaderMap::const_iterator it = headerMap.begin();
     for (; it != headerMap.end(); ++it) {
-      if (base::LowerCaseEqualsASCII(it->first.ToString(),
-                                     kCacheControlLowerCase)) {
+      if (base::EqualsCaseInsensitiveASCII(
+              it->first.ToString(), net::HttpRequestHeaders::kCacheControl)) {
         line = it->second;
         break;
       }
@@ -129,14 +82,14 @@
     std::vector<base::StringPiece> pieces = base::SplitStringPiece(
         line, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
     for (const auto& piece : pieces) {
-      if (base::LowerCaseEqualsASCII(piece,
-                                     kCacheControlDirectiveNoCacheLowerCase)) {
+      if (base::EqualsCaseInsensitiveASCII(piece,
+                                           kCacheControlDirectiveNoCache)) {
         flags |= UR_FLAG_SKIP_CACHE;
-      } else if (base::LowerCaseEqualsASCII(
-                     piece, kCacheControlDirectiveOnlyIfCachedLowerCase)) {
+      } else if (base::EqualsCaseInsensitiveASCII(
+                     piece, kCacheControlDirectiveOnlyIfCached)) {
         flags |= UR_FLAG_ONLY_FROM_CACHE;
-      } else if (base::LowerCaseEqualsASCII(
-                     piece, kCacheControlDirectiveNoStoreLowerCase)) {
+      } else if (base::EqualsCaseInsensitiveASCII(
+                     piece, kCacheControlDirectiveNoStore)) {
         flags |= UR_FLAG_DISABLE_CACHE;
       }
     }
@@ -147,9 +100,9 @@
 
 // Convert cef_urlrequest_flags_t to blink::WebCachePolicy.
 blink::mojom::FetchCacheMode GetFetchCacheMode(int ur_flags) {
-  const bool skip_cache{ur_flags & UR_FLAG_SKIP_CACHE};
-  const bool only_from_cache{ur_flags & UR_FLAG_ONLY_FROM_CACHE};
-  const bool disable_cache{ur_flags & UR_FLAG_DISABLE_CACHE};
+  const bool skip_cache{!!(ur_flags & UR_FLAG_SKIP_CACHE)};
+  const bool only_from_cache{!!(ur_flags & UR_FLAG_ONLY_FROM_CACHE)};
+  const bool disable_cache{!!(ur_flags & UR_FLAG_DISABLE_CACHE)};
   if (only_from_cache && (skip_cache || disable_cache)) {
     // The request will always fail because only_from_cache and
     // skip_cache/disable_cache are mutually exclusive.
@@ -165,30 +118,24 @@
   return blink::mojom::FetchCacheMode::kDefault;
 }
 
-blink::WebString FilePathStringToWebString(
-    const base::FilePath::StringType& str) {
-#if defined(OS_POSIX)
-  return blink::WebString::FromUTF8(str);
-#elif defined(OS_WIN)
-  return blink::WebString::FromUTF16(str);
-#endif
-}
-
 // Read |headers| into |map|.
 void GetHeaderMap(const net::HttpRequestHeaders& headers,
                   CefRequest::HeaderMap& map) {
   map.clear();
 
-  if (headers.IsEmpty())
+  if (headers.IsEmpty()) {
     return;
+  }
 
   net::HttpRequestHeaders::Iterator it(headers);
   while (it.GetNext()) {
     const std::string& name = it.name();
 
     // Do not include Referer in the header map.
-    if (!base::LowerCaseEqualsASCII(name, kReferrerLowerCase))
+    if (!base::EqualsCaseInsensitiveASCII(name,
+                                          net::HttpRequestHeaders::kReferer)) {
       map.insert(std::make_pair(name, it.value()));
+    }
   };
 }
 
@@ -202,32 +149,27 @@
     const CefString& name = it->first;
 
     // Do not include Referer in the header map.
-    if (!base::LowerCaseEqualsASCII(name.ToString(), kReferrerLowerCase))
+    if (!base::EqualsCaseInsensitiveASCII(name.ToString(),
+                                          net::HttpRequestHeaders::kReferer)) {
       map.insert(std::make_pair(name, it->second));
+    }
   }
 }
 
-// Type used in UploadDataStream.
-typedef std::vector<std::unique_ptr<net::UploadElementReader>>
-    UploadElementReaders;
-
 }  // namespace
 
-#define CHECK_READONLY_RETURN(val)         \
-  if (read_only_) {                        \
-    NOTREACHED() << "object is read only"; \
-    return val;                            \
+#define CHECK_READONLY_RETURN(val)          \
+  if (read_only_) {                         \
+    DCHECK(false) << "object is read only"; \
+    return val;                             \
   }
 
-#define CHECK_READONLY_RETURN_VOID()       \
-  if (read_only_) {                        \
-    NOTREACHED() << "object is read only"; \
-    return;                                \
+#define CHECK_READONLY_RETURN_VOID()        \
+  if (read_only_) {                         \
+    DCHECK(false) << "object is read only"; \
+    return;                                 \
   }
 
-#define SETBOOLFLAG(obj, flags, method, FLAG) \
-  obj.method((flags & (FLAG)) == (FLAG))
-
 // CefRequest -----------------------------------------------------------------
 
 // static
@@ -241,7 +183,7 @@
 CefRequestImpl::CefRequestImpl() {
   // Verify that our enum matches Chromium's values.
   static_assert(static_cast<int>(REFERRER_POLICY_LAST_VALUE) ==
-                    static_cast<int>(net::URLRequest::MAX_REFERRER_POLICY),
+                    static_cast<int>(net::ReferrerPolicy::MAX),
                 "enum mismatch");
 
   base::AutoLock lock_scope(lock_);
@@ -343,8 +285,9 @@
   HttpHeaderUtils::MakeASCIILower(&nameLower);
 
   auto it = HttpHeaderUtils::FindHeaderInMap(nameLower, headermap_);
-  if (it != headermap_.end())
+  if (it != headermap_.end()) {
     return it->second;
+  }
 
   return CefString();
 }
@@ -355,20 +298,22 @@
   base::AutoLock lock_scope(lock_);
   CHECK_READONLY_RETURN_VOID();
 
-  std::string nameLower = name;
-  HttpHeaderUtils::MakeASCIILower(&nameLower);
+  const std::string& nameStr = name;
 
   // Do not include Referer in the header map.
-  if (nameLower == kReferrerLowerCase)
+  if (base::EqualsCaseInsensitiveASCII(nameStr,
+                                       net::HttpRequestHeaders::kReferer)) {
     return;
+  }
 
   Changed(kChangedHeaderMap);
 
   // There may be multiple values, so remove any first.
   for (auto it = headermap_.begin(); it != headermap_.end();) {
-    if (base::EqualsCaseInsensitiveASCII(it->first.ToString(), nameLower)) {
-      if (!overwrite)
+    if (base::EqualsCaseInsensitiveASCII(it->first.ToString(), nameStr)) {
+      if (!overwrite) {
         return;
+      }
       it = headermap_.erase(it);
     } else {
       ++it;
@@ -441,13 +386,13 @@
   return transition_type_;
 }
 
-uint64 CefRequestImpl::GetIdentifier() {
+uint64_t CefRequestImpl::GetIdentifier() {
   base::AutoLock lock_scope(lock_);
   return identifier_;
 }
 
 void CefRequestImpl::Set(const network::ResourceRequest* request,
-                         uint64 identifier) {
+                         uint64_t identifier) {
   base::AutoLock lock_scope(lock_);
   CHECK_READONLY_RETURN_VOID();
 
@@ -489,16 +434,18 @@
                          bool changed_only) const {
   base::AutoLock lock_scope(lock_);
 
-  if (ShouldSet(kChangedUrl, changed_only))
+  if (ShouldSet(kChangedUrl, changed_only)) {
     request->url = url_;
+  }
 
-  if (ShouldSet(kChangedMethod, changed_only))
+  if (ShouldSet(kChangedMethod, changed_only)) {
     request->method = method_;
+  }
 
   if (ShouldSet(kChangedReferrer, changed_only)) {
     request->referrer = referrer_url_;
     request->referrer_policy =
-        static_cast<net::URLRequest::ReferrerPolicy>(referrer_policy_);
+        static_cast<net::ReferrerPolicy>(referrer_policy_);
   }
 
   if (ShouldSet(kChangedHeaderMap, changed_only)) {
@@ -542,9 +489,8 @@
     }
 
     if (!(flags & UR_FLAG_ALLOW_STORED_CREDENTIALS)) {
-      net_flags |= net::LOAD_DO_NOT_SEND_AUTH_DATA |
-                   net::LOAD_DO_NOT_SEND_COOKIES |
-                   net::LOAD_DO_NOT_SAVE_COOKIES;
+      // This will disable all credentials including cookies, auth tokens, etc.
+      request->credentials_mode = network::mojom::CredentialsMode::kOmit;
     }
 
     request->load_flags = net_flags;
@@ -577,53 +523,51 @@
   ::GetHeaderMap(headers, headermap_);
 }
 
-void CefRequestImpl::Set(
-    const navigation_interception::NavigationParams& params,
-    bool is_main_frame) {
+void CefRequestImpl::Set(content::NavigationHandle* navigation_handle) {
   base::AutoLock lock_scope(lock_);
   CHECK_READONLY_RETURN_VOID();
 
   Reset();
 
-  url_ = params.url();
-  method_ = params.is_post() ? "POST" : "GET";
+  url_ = navigation_handle->GetURL();
+  method_ = navigation_handle->IsPost() ? "POST" : "GET";
 
-  const auto& sanitized_referrer =
-      content::Referrer::SanitizeForRequest(params.url(), params.referrer());
-  referrer_url_ = sanitized_referrer.url;
+  const auto& sanitized_referrer = content::Referrer::SanitizeForRequest(
+      navigation_handle->GetURL(), navigation_handle->GetReferrer());
+  referrer_url_ = sanitized_referrer->url;
   referrer_policy_ =
-      BlinkReferrerPolicyToNetReferrerPolicy(sanitized_referrer.policy);
+      BlinkReferrerPolicyToNetReferrerPolicy(sanitized_referrer->policy);
 
-  resource_type_ = is_main_frame ? RT_MAIN_FRAME : RT_SUB_FRAME;
-  transition_type_ =
-      static_cast<cef_transition_type_t>(params.transition_type());
+  resource_type_ =
+      navigation_handle->IsInMainFrame() ? RT_MAIN_FRAME : RT_SUB_FRAME;
+  transition_type_ = static_cast<cef_transition_type_t>(
+      navigation_handle->GetPageTransition());
 }
 
 // static
-void CefRequestImpl::Get(const CefMsg_LoadRequest_Params& params,
+void CefRequestImpl::Get(const cef::mojom::RequestParamsPtr& params,
                          blink::WebURLRequest& request) {
-  request.SetUrl(params.url);
-  request.SetRequestorOrigin(blink::WebSecurityOrigin::Create(params.url));
-  if (!params.method.empty())
-    request.SetHttpMethod(blink::WebString::FromASCII(params.method));
+  request.SetUrl(params->url);
+  request.SetRequestorOrigin(blink::WebSecurityOrigin::Create(params->url));
+  if (!params->method.empty()) {
+    request.SetHttpMethod(blink::WebString::FromASCII(params->method));
+  }
 
-  if (params.referrer.is_valid()) {
+  if (params->referrer && params->referrer->url.is_valid()) {
     const blink::WebString& referrer =
         blink::WebSecurityPolicy::GenerateReferrerHeader(
-            NetReferrerPolicyToBlinkReferrerPolicy(
-                static_cast<cef_referrer_policy_t>(params.referrer_policy)),
-            params.url, blink::WebString::FromUTF8(params.referrer.spec()));
+            params->referrer->policy, params->url,
+            blink::WebString::FromUTF8(params->referrer->url.spec()));
     if (!referrer.IsEmpty()) {
       request.SetReferrerString(referrer);
-      request.SetReferrerPolicy(NetReferrerPolicyToBlinkReferrerPolicy(
-          static_cast<cef_referrer_policy_t>(params.referrer_policy)));
+      request.SetReferrerPolicy(params->referrer->policy);
     }
   }
 
   CefRequest::HeaderMap headerMap;
-  if (!params.headers.empty()) {
-    for (net::HttpUtil::HeadersIterator i(params.headers.begin(),
-                                          params.headers.end(), "\n\r");
+  if (!params->headers.empty()) {
+    for (net::HttpUtil::HeadersIterator i(params->headers.begin(),
+                                          params->headers.end(), "\n\r");
          i.GetNext();) {
       request.AddHttpHeaderField(blink::WebString::FromUTF8(i.name()),
                                  blink::WebString::FromUTF8(i.values()));
@@ -631,10 +575,9 @@
     }
   }
 
-  if (params.upload_data.get()) {
-    const base::string16& method = request.HttpMethod().Utf16();
-    if (method == base::ASCIIToUTF16("GET") ||
-        method == base::ASCIIToUTF16("HEAD")) {
+  if (params->upload_data) {
+    const std::u16string& method = request.HttpMethod().Utf16();
+    if (method == u"GET" || method == u"HEAD") {
       request.SetHttpMethod(blink::WebString::FromASCII("POST"));
     }
 
@@ -649,31 +592,15 @@
               net_service::kContentTypeApplicationFormURLEncoded));
     }
 
-    blink::WebHTTPBody body;
-    body.Initialize();
-
-    for (const auto& element : params.upload_data->elements()) {
-      if (element->type() == net::UploadElement::TYPE_BYTES) {
-        blink::WebData data;
-        data.Assign(element->bytes(), element->bytes_length());
-        body.AppendData(data);
-      } else if (element->type() == net::UploadElement::TYPE_FILE) {
-        body.AppendFileRange(
-            FilePathStringToWebString(element->file_path().value()),
-            element->file_range_offset(), element->file_range_length(),
-            element->expected_file_modification_time());
-      } else {
-        NOTREACHED();
-      }
-    }
-
-    request.SetHttpBody(body);
+    request.SetHttpBody(
+        blink::GetWebHTTPBodyForRequestBody(*params->upload_data));
   }
 
-  if (!params.site_for_cookies.IsNull())
-    request.SetSiteForCookies(params.site_for_cookies);
+  if (!params->site_for_cookies.IsNull()) {
+    request.SetSiteForCookies(params->site_for_cookies);
+  }
 
-  int flags = params.load_flags;
+  int flags = params->load_flags;
   if (!(flags & kURCachePolicyMask)) {
     // Only consider the Cache-Control directives when a cache policy is not
     // explicitly set on the request.
@@ -681,55 +608,60 @@
   }
   request.SetCacheMode(GetFetchCacheMode(flags));
 
-  SETBOOLFLAG(request, params.load_flags, SetAllowStoredCredentials,
-              UR_FLAG_ALLOW_STORED_CREDENTIALS);
-  SETBOOLFLAG(request, params.load_flags, SetReportUploadProgress,
-              UR_FLAG_REPORT_UPLOAD_PROGRESS);
+  request.SetCredentialsMode(
+      (params->load_flags & UR_FLAG_ALLOW_STORED_CREDENTIALS)
+          ? network::mojom::CredentialsMode::kInclude
+          : network::mojom::CredentialsMode::kOmit);
+  request.SetReportUploadProgress(params->load_flags &
+                                  UR_FLAG_REPORT_UPLOAD_PROGRESS);
 }
 
-void CefRequestImpl::Get(CefNavigateParams& params) const {
+void CefRequestImpl::Get(cef::mojom::RequestParamsPtr& params) const {
   base::AutoLock lock_scope(lock_);
 
-  params.url = url_;
-  params.method = method_;
+  params->url = url_;
+  params->method = method_;
 
   // Referrer policy will be applied later in the request pipeline.
-  params.referrer.url = referrer_url_;
-  params.referrer.policy =
-      NetReferrerPolicyToBlinkReferrerPolicy(referrer_policy_);
+  params->referrer = blink::mojom::Referrer::New(
+      referrer_url_, NetReferrerPolicyToBlinkReferrerPolicy(referrer_policy_));
 
-  if (!headermap_.empty())
-    params.headers = HttpHeaderUtils::GenerateHeaders(headermap_);
+  if (!headermap_.empty()) {
+    params->headers = HttpHeaderUtils::GenerateHeaders(headermap_);
+  }
 
   if (postdata_) {
     CefPostDataImpl* impl = static_cast<CefPostDataImpl*>(postdata_.get());
-    params.upload_data = new net::UploadData();
-    impl->Get(*params.upload_data.get());
+    params->upload_data = impl->GetBody();
   }
 
-  params.site_for_cookies = site_for_cookies_;
-  params.load_flags = flags_;
+  params->site_for_cookies = site_for_cookies_;
+  params->load_flags = flags_;
 }
 
 void CefRequestImpl::SetReadOnly(bool read_only) {
   base::AutoLock lock_scope(lock_);
-  if (read_only_ == read_only)
+  if (read_only_ == read_only) {
     return;
+  }
 
   read_only_ = read_only;
 
-  if (postdata_.get())
+  if (postdata_.get()) {
     static_cast<CefPostDataImpl*>(postdata_.get())->SetReadOnly(read_only);
+  }
 }
 
 void CefRequestImpl::SetTrackChanges(bool track_changes,
                                      bool backup_on_change) {
   base::AutoLock lock_scope(lock_);
-  if (track_changes_ == track_changes)
+  if (track_changes_ == track_changes) {
     return;
+  }
 
-  if (!track_changes && backup_on_change_)
+  if (!track_changes && backup_on_change_) {
     backup_.reset();
+  }
 
   track_changes_ = track_changes;
   backup_on_change_ = track_changes ? backup_on_change : false;
@@ -746,28 +678,34 @@
   DCHECK(!read_only_);
   DCHECK(track_changes_);
   DCHECK(backup_on_change_);
-  if (!backup_)
+  if (!backup_) {
     return;
+  }
 
   // Restore the original values if a backup exists.
-  if (backup_->backups_ & kChangedUrl)
+  if (backup_->backups_ & kChangedUrl) {
     url_ = backup_->url_;
-  if (backup_->backups_ & kChangedMethod)
+  }
+  if (backup_->backups_ & kChangedMethod) {
     method_ = backup_->method_;
+  }
   if (backup_->backups_ & kChangedReferrer) {
     referrer_url_ = backup_->referrer_url_;
     referrer_policy_ = backup_->referrer_policy_;
   }
-  if (backup_->backups_ & kChangedPostData)
+  if (backup_->backups_ & kChangedPostData) {
     postdata_ = backup_->postdata_;
+  }
   if (backup_->backups_ & kChangedHeaderMap) {
     DCHECK(backup_->headermap_);
     headermap_.swap(*backup_->headermap_);
   }
-  if (backup_->backups_ & kChangedFlags)
+  if (backup_->backups_ & kChangedFlags) {
     flags_ = backup_->flags_;
-  if (backup_->backups_ & kChangedSiteForCookies)
+  }
+  if (backup_->backups_ & kChangedSiteForCookies) {
     site_for_cookies_ = backup_->site_for_cookies_;
+  }
 
   backup_.reset();
 }
@@ -813,7 +751,7 @@
     case REFERRER_POLICY_NO_REFERRER:
       return network::mojom::ReferrerPolicy::kNever;
   }
-  NOTREACHED();
+  DCHECK(false);
   return network::mojom::ReferrerPolicy::kDefault;
 }
 
@@ -840,18 +778,20 @@
     case network::mojom::ReferrerPolicy::kDefault:
       return REFERRER_POLICY_DEFAULT;
   }
-  NOTREACHED();
+  DCHECK(false);
   return REFERRER_POLICY_DEFAULT;
 }
 
 void CefRequestImpl::Changed(uint8_t changes) {
   lock_.AssertAcquired();
-  if (!track_changes_)
+  if (!track_changes_) {
     return;
+  }
 
   if (backup_on_change_) {
-    if (!backup_)
+    if (!backup_) {
       backup_.reset(new Backup());
+    }
 
     // Set the backup values if not already set.
     if ((changes & kChangedUrl) && !(backup_->backups_ & kChangedUrl)) {
@@ -899,16 +839,19 @@
   lock_.AssertAcquired();
 
   // Always change if changes are not being tracked.
-  if (!track_changes_)
+  if (!track_changes_) {
     return true;
+  }
 
   // Always change if changed-only was not requested.
-  if (!changed_only)
+  if (!changed_only) {
     return true;
+  }
 
   // Change if the |changes| bit flag has been set.
-  if ((changes_ & changes) == changes)
+  if ((changes_ & changes) == changes) {
     return true;
+  }
 
   if ((changes & kChangedPostData) == kChangedPostData) {
     // Change if the post data object was modified directly.
@@ -1048,74 +991,11 @@
   return body;
 }
 
-void CefPostDataImpl::Set(const net::UploadData& data) {
-  {
-    base::AutoLock lock_scope(lock_);
-    CHECK_READONLY_RETURN_VOID();
-  }
-
-  CefRefPtr<CefPostDataElement> postelem;
-
-  for (const auto& element : data.elements()) {
-    postelem = CefPostDataElement::Create();
-    static_cast<CefPostDataElementImpl*>(postelem.get())->Set(*element);
-    AddElement(postelem);
-  }
-}
-
-void CefPostDataImpl::Set(const net::UploadDataStream& data_stream) {
-  {
-    base::AutoLock lock_scope(lock_);
-    CHECK_READONLY_RETURN_VOID();
-  }
-
-  CefRefPtr<CefPostDataElement> postelem;
-
-  const UploadElementReaders* elements = data_stream.GetElementReaders();
-  if (elements) {
-    UploadElementReaders::const_iterator it = elements->begin();
-    for (; it != elements->end(); ++it) {
-      postelem = CefPostDataElement::Create();
-      static_cast<CefPostDataElementImpl*>(postelem.get())->Set(**it);
-      if (postelem->GetType() != PDE_TYPE_EMPTY)
-        AddElement(postelem);
-      else if (!has_excluded_elements_)
-        has_excluded_elements_ = true;
-    }
-  }
-}
-
-void CefPostDataImpl::Get(net::UploadData& data) const {
-  base::AutoLock lock_scope(lock_);
-
-  net::UploadData::ElementsVector data_elements;
-  for (const auto& element : elements_) {
-    std::unique_ptr<net::UploadElement> data_element =
-        std::make_unique<net::UploadElement>();
-    static_cast<CefPostDataElementImpl*>(element.get())
-        ->Get(*data_element.get());
-    data_elements.push_back(std::move(data_element));
-  }
-  data.swap_elements(&data_elements);
-}
-
-std::unique_ptr<net::UploadDataStream> CefPostDataImpl::Get() const {
-  base::AutoLock lock_scope(lock_);
-
-  UploadElementReaders element_readers;
-  for (const auto& element : elements_) {
-    element_readers.push_back(
-        static_cast<CefPostDataElementImpl*>(element.get())->Get());
-  }
-
-  return std::make_unique<net::ElementsUploadDataStream>(
-      std::move(element_readers), 0);
-}
-
 void CefPostDataImpl::SetReadOnly(bool read_only) {
   base::AutoLock lock_scope(lock_);
-  if (read_only_ == read_only)
+  if (read_only_ == read_only) {
     return;
+  }
 
   read_only_ = read_only;
 
@@ -1127,8 +1007,9 @@
 
 void CefPostDataImpl::SetTrackChanges(bool track_changes) {
   base::AutoLock lock_scope(lock_);
-  if (track_changes_ == track_changes)
+  if (track_changes_ == track_changes) {
     return;
+  }
 
   track_changes_ = track_changes;
   has_changes_ = false;
@@ -1142,13 +1023,15 @@
 
 bool CefPostDataImpl::HasChanges() const {
   base::AutoLock lock_scope(lock_);
-  if (has_changes_)
+  if (has_changes_) {
     return true;
+  }
 
   ElementVector::const_iterator it = elements_.begin();
   for (; it != elements_.end(); ++it) {
-    if (static_cast<CefPostDataElementImpl*>(it->get())->HasChanges())
+    if (static_cast<CefPostDataElementImpl*>(it->get())->HasChanges()) {
       return true;
+    }
   }
 
   return false;
@@ -1156,8 +1039,9 @@
 
 void CefPostDataImpl::Changed() {
   lock_.AssertAcquired();
-  if (track_changes_ && !has_changes_)
+  if (track_changes_ && !has_changes_) {
     has_changes_ = true;
+  }
 }
 
 // CefPostDataElement ---------------------------------------------------------
@@ -1219,8 +1103,9 @@
   // Assign the new data
   void* data = malloc(size);
   DCHECK(data != nullptr);
-  if (data == nullptr)
+  if (data == nullptr) {
     return;
+  }
 
   memcpy(data, bytes, size);
 
@@ -1240,8 +1125,9 @@
   base::AutoLock lock_scope(lock_);
   DCHECK(type_ == PDE_TYPE_FILE);
   CefString filename;
-  if (type_ == PDE_TYPE_FILE)
+  if (type_ == PDE_TYPE_FILE) {
     filename.FromString(data_.filename.str, data_.filename.length, false);
+  }
   return filename;
 }
 
@@ -1249,8 +1135,9 @@
   base::AutoLock lock_scope(lock_);
   DCHECK(type_ == PDE_TYPE_BYTES);
   size_t size = 0;
-  if (type_ == PDE_TYPE_BYTES)
+  if (type_ == PDE_TYPE_BYTES) {
     size = data_.bytes.size;
+  }
   return size;
 }
 
@@ -1271,10 +1158,13 @@
     CHECK_READONLY_RETURN_VOID();
   }
 
-  if (element.type() == network::mojom::DataElementType::kBytes) {
-    SetToBytes(element.length(), element.bytes());
-  } else if (element.type() == network::mojom::DataElementType::kFile) {
-    SetToFile(element.path().value());
+  if (element.type() == network::DataElement::Tag::kBytes) {
+    const auto& bytes_element = element.As<network::DataElementBytes>();
+    const auto& bytes = bytes_element.bytes();
+    SetToBytes(bytes.size(), bytes.data());
+  } else if (element.type() == network::DataElement::Tag::kFile) {
+    const auto& file_element = element.As<network::DataElementFile>();
+    SetToFile(file_element.path().value());
   }
 }
 
@@ -1288,94 +1178,24 @@
     body.AppendFileRange(path, 0, std::numeric_limits<uint64_t>::max(),
                          base::Time());
   } else {
-    NOTREACHED();
-  }
-}
-
-void CefPostDataElementImpl::Set(const net::UploadElement& element) {
-  {
-    base::AutoLock lock_scope(lock_);
-    CHECK_READONLY_RETURN_VOID();
-  }
-
-  if (element.type() == net::UploadElement::TYPE_BYTES) {
-    SetToBytes(element.bytes_length(), element.bytes());
-  } else if (element.type() == net::UploadElement::TYPE_FILE) {
-    SetToFile(element.file_path().value());
-  } else {
-    NOTREACHED();
-  }
-}
-
-void CefPostDataElementImpl::Set(
-    const net::UploadElementReader& element_reader) {
-  {
-    base::AutoLock lock_scope(lock_);
-    CHECK_READONLY_RETURN_VOID();
-  }
-
-  const net::UploadBytesElementReader* bytes_reader =
-      element_reader.AsBytesReader();
-  if (bytes_reader) {
-    SetToBytes(bytes_reader->length(), bytes_reader->bytes());
-    return;
-  }
-
-  const net::UploadFileElementReader* file_reader =
-      element_reader.AsFileReader();
-  if (file_reader) {
-    SetToFile(file_reader->path().value());
-    return;
-  }
-
-  // Chunked uploads cannot currently be represented.
-  SetToEmpty();
-}
-
-void CefPostDataElementImpl::Get(net::UploadElement& element) const {
-  base::AutoLock lock_scope(lock_);
-
-  if (type_ == PDE_TYPE_BYTES) {
-    element.SetToBytes(static_cast<char*>(data_.bytes.bytes), data_.bytes.size);
-  } else if (type_ == PDE_TYPE_FILE) {
-    base::FilePath path = base::FilePath(CefString(&data_.filename));
-    element.SetToFilePath(path);
-  } else {
-    NOTREACHED();
-  }
-}
-
-std::unique_ptr<net::UploadElementReader> CefPostDataElementImpl::Get() const {
-  base::AutoLock lock_scope(lock_);
-
-  if (type_ == PDE_TYPE_BYTES) {
-    net::UploadElement* element = new net::UploadElement();
-    element->SetToBytes(static_cast<char*>(data_.bytes.bytes),
-                        data_.bytes.size);
-    return std::make_unique<BytesElementReader>(base::WrapUnique(element));
-  } else if (type_ == PDE_TYPE_FILE) {
-    net::UploadElement* element = new net::UploadElement();
-    base::FilePath path = base::FilePath(CefString(&data_.filename));
-    element->SetToFilePath(path);
-    return std::make_unique<FileElementReader>(base::WrapUnique(element));
-  } else {
-    NOTREACHED();
-    return nullptr;
+    DCHECK(false);
   }
 }
 
 void CefPostDataElementImpl::SetReadOnly(bool read_only) {
   base::AutoLock lock_scope(lock_);
-  if (read_only_ == read_only)
+  if (read_only_ == read_only) {
     return;
+  }
 
   read_only_ = read_only;
 }
 
 void CefPostDataElementImpl::SetTrackChanges(bool track_changes) {
   base::AutoLock lock_scope(lock_);
-  if (track_changes_ == track_changes)
+  if (track_changes_ == track_changes) {
     return;
+  }
 
   track_changes_ = track_changes;
   has_changes_ = false;
@@ -1388,18 +1208,21 @@
 
 void CefPostDataElementImpl::Changed() {
   lock_.AssertAcquired();
-  if (track_changes_ && !has_changes_)
+  if (track_changes_ && !has_changes_) {
     has_changes_ = true;
+  }
 }
 
 void CefPostDataElementImpl::Cleanup() {
-  if (type_ == PDE_TYPE_EMPTY)
+  if (type_ == PDE_TYPE_EMPTY) {
     return;
+  }
 
-  if (type_ == PDE_TYPE_BYTES)
+  if (type_ == PDE_TYPE_BYTES) {
     free(data_.bytes.bytes);
-  else if (type_ == PDE_TYPE_FILE)
+  } else if (type_ == PDE_TYPE_FILE) {
     cef_string_clear(&data_.filename);
+  }
   type_ = PDE_TYPE_EMPTY;
   memset(&data_, 0, sizeof(data_));
 }
diff --git a/src/libcef/common/request_impl.h b/src/libcef/common/request_impl.h
index aa6462e..dadbfde 100644
--- a/src/libcef/common/request_impl.h
+++ b/src/libcef/common/request_impl.h
@@ -13,6 +13,7 @@
 #include "include/cef_request.h"
 
 #include "base/synchronization/lock.h"
+#include "cef/libcef/common/mojom/cef.mojom.h"
 #include "net/cookies/site_for_cookies.h"
 #include "services/network/public/mojom/referrer_policy.mojom-shared.h"
 #include "url/gurl.h"
@@ -21,17 +22,13 @@
 class WebURLRequest;
 }  // namespace blink
 
-namespace navigation_interception {
-class NavigationParams;
-}
+namespace content {
+class NavigationHandle;
+}  // namespace content
 
 namespace net {
 class HttpRequestHeaders;
 struct RedirectInfo;
-class UploadData;
-class UploadDataStream;
-class UploadElement;
-class UploadElementReader;
 }  // namespace net
 
 namespace network {
@@ -40,9 +37,6 @@
 class ResourceRequestBody;
 }  // namespace network
 
-struct CefMsg_LoadRequest_Params;
-struct CefNavigateParams;
-
 // Implementation of CefRequest
 class CefRequestImpl : public CefRequest {
  public:
@@ -86,10 +80,10 @@
   void SetFirstPartyForCookies(const CefString& url) override;
   ResourceType GetResourceType() override;
   TransitionType GetTransitionType() override;
-  uint64 GetIdentifier() override;
+  uint64_t GetIdentifier() override;
 
   // Populate this object from the ResourceRequest object.
-  void Set(const network::ResourceRequest* request, uint64 identifier);
+  void Set(const network::ResourceRequest* request, uint64_t identifier);
 
   // Populate the ResourceRequest object from this object.
   // If |changed_only| is true then only the changed fields will be updated.
@@ -98,24 +92,21 @@
   // Populate this object from the RedirectInfo object.
   void Set(const net::RedirectInfo& redirect_info);
 
-  // Populate this object from teh HttpRequestHeaders object.
+  // Populate this object from the HttpRequestHeaders object.
   void Set(const net::HttpRequestHeaders& headers);
 
   // Populate this object from the NavigationParams object.
-  // TODO(cef): Remove the |is_main_frame| argument once NavigationParams is
-  // reliable in reporting that value.
-  // Called from content_browser_client.cc NavigationOnUIThread().
-  void Set(const navigation_interception::NavigationParams& params,
-           bool is_main_frame);
+  // Called from throttle_handler.cc NavigationOnUIThread().
+  void Set(content::NavigationHandle* navigation_handle);
 
   // Populate the WebURLRequest object based on the contents of |params|.
   // Called from CefBrowserImpl::LoadRequest().
-  static void Get(const CefMsg_LoadRequest_Params& params,
+  static void Get(const cef::mojom::RequestParamsPtr& params,
                   blink::WebURLRequest& request);
 
-  // Populate the CefNavigateParams object from this object.
-  // Called from CefBrowserHostImpl::LoadRequest().
-  void Get(CefNavigateParams& params) const;
+  // Populate the RequestParams object from this object.
+  // Called from CefFrameHostImpl::LoadRequest().
+  void Get(cef::mojom::RequestParamsPtr& params) const;
 
   void SetReadOnly(bool read_only);
 
@@ -154,7 +145,7 @@
   HeaderMap headermap_;
   ResourceType resource_type_;
   TransitionType transition_type_;
-  uint64 identifier_;
+  uint64_t identifier_;
 
   // The below members are used by CefURLRequest.
   int flags_;
@@ -208,10 +199,6 @@
 
   void Set(const network::ResourceRequestBody& body);
   scoped_refptr<network::ResourceRequestBody> GetBody() const;
-  void Set(const net::UploadData& data);
-  void Set(const net::UploadDataStream& data_stream);
-  void Get(net::UploadData& data) const;
-  std::unique_ptr<net::UploadDataStream> Get() const;
 
   void SetReadOnly(bool read_only);
 
@@ -259,10 +246,6 @@
 
   void Set(const network::DataElement& element);
   void Get(network::ResourceRequestBody& body) const;
-  void Set(const net::UploadElement& element);
-  void Set(const net::UploadElementReader& element_reader);
-  void Get(net::UploadElement& element) const;
-  std::unique_ptr<net::UploadElementReader> Get() const;
 
   void SetReadOnly(bool read_only);
 
diff --git a/src/libcef/common/resource_bundle_delegate.cc b/src/libcef/common/resource_bundle_delegate.cc
index 6746fd1..bfa0da0 100644
--- a/src/libcef/common/resource_bundle_delegate.cc
+++ b/src/libcef/common/resource_bundle_delegate.cc
@@ -1,13 +1,12 @@
 #include "libcef/common/resource_bundle_delegate.h"
 
-#include "libcef/common/content_client.h"
+#include "libcef/common/app_manager.h"
 
 base::FilePath CefResourceBundleDelegate::GetPathForResourcePack(
     const base::FilePath& pack_path,
-    ui::ScaleFactor scale_factor) {
+    ui::ResourceScaleFactor scale_factor) {
   // Only allow the cef pack file to load.
-  if (!content_client_->pack_loading_disabled() &&
-      content_client_->allow_pack_file_load()) {
+  if (!pack_loading_disabled_ && allow_pack_file_load_) {
     return pack_path;
   }
   return base::FilePath();
@@ -16,8 +15,9 @@
 base::FilePath CefResourceBundleDelegate::GetPathForLocalePack(
     const base::FilePath& pack_path,
     const std::string& locale) {
-  if (!content_client_->pack_loading_disabled())
+  if (!pack_loading_disabled_) {
     return pack_path;
+  }
   return base::FilePath();
 }
 
@@ -29,22 +29,29 @@
   return gfx::Image();
 }
 
-base::RefCountedStaticMemory* CefResourceBundleDelegate::LoadDataResourceBytes(
+base::RefCountedMemory* CefResourceBundleDelegate::LoadDataResourceBytes(
     int resource_id,
-    ui::ScaleFactor scale_factor) {
+    ui::ResourceScaleFactor scale_factor) {
   return nullptr;
 }
 
-bool CefResourceBundleDelegate::GetRawDataResource(int resource_id,
-                                                   ui::ScaleFactor scale_factor,
-                                                   base::StringPiece* value) {
-  if (content_client_->application().get()) {
+absl::optional<std::string> CefResourceBundleDelegate::LoadDataResourceString(
+    int resource_id) {
+  return absl::nullopt;
+}
+
+bool CefResourceBundleDelegate::GetRawDataResource(
+    int resource_id,
+    ui::ResourceScaleFactor scale_factor,
+    base::StringPiece* value) const {
+  auto application = CefAppManager::Get()->GetApplication();
+  if (application) {
     CefRefPtr<CefResourceBundleHandler> handler =
-        content_client_->application()->GetResourceBundleHandler();
+        application->GetResourceBundleHandler();
     if (handler.get()) {
       void* data = nullptr;
       size_t data_size = 0;
-      if (scale_factor != ui::SCALE_FACTOR_NONE) {
+      if (scale_factor != ui::kScaleFactorNone) {
         if (handler->GetDataResourceForScale(
                 resource_id, static_cast<cef_scale_factor_t>(scale_factor),
                 data, data_size)) {
@@ -56,20 +63,23 @@
     }
   }
 
-  return (content_client_->pack_loading_disabled() || !value->empty());
+  return (pack_loading_disabled_ || !value->empty());
 }
 
-bool CefResourceBundleDelegate::GetLocalizedString(int message_id,
-                                                   base::string16* value) {
-  if (content_client_->application().get()) {
+bool CefResourceBundleDelegate::GetLocalizedString(
+    int message_id,
+    std::u16string* value) const {
+  auto application = CefAppManager::Get()->GetApplication();
+  if (application) {
     CefRefPtr<CefResourceBundleHandler> handler =
-        content_client_->application()->GetResourceBundleHandler();
+        application->GetResourceBundleHandler();
     if (handler.get()) {
       CefString cef_str;
-      if (handler->GetLocalizedString(message_id, cef_str))
+      if (handler->GetLocalizedString(message_id, cef_str)) {
         *value = cef_str;
+      }
     }
   }
 
-  return (content_client_->pack_loading_disabled() || !value->empty());
+  return (pack_loading_disabled_ || !value->empty());
 }
diff --git a/src/libcef/common/resource_bundle_delegate.h b/src/libcef/common/resource_bundle_delegate.h
index ca6d5fd..7c8acef 100644
--- a/src/libcef/common/resource_bundle_delegate.h
+++ b/src/libcef/common/resource_bundle_delegate.h
@@ -9,31 +9,38 @@
 
 #include "ui/base/resource/resource_bundle.h"
 
-class CefContentClient;
+class AlloyContentClient;
 
 class CefResourceBundleDelegate : public ui::ResourceBundle::Delegate {
  public:
-  CefResourceBundleDelegate(CefContentClient* content_client)
-      : content_client_(content_client) {}
+  CefResourceBundleDelegate() {}
+
+  void set_pack_loading_disabled(bool val) { pack_loading_disabled_ = val; }
+  bool pack_loading_disabled() const { return pack_loading_disabled_; }
+  void set_allow_pack_file_load(bool val) { allow_pack_file_load_ = val; }
+  bool allow_pack_file_load() const { return allow_pack_file_load_; }
 
  private:
   // ui::ResourceBundle::Delegate methods.
-  base::FilePath GetPathForResourcePack(const base::FilePath& pack_path,
-                                        ui::ScaleFactor scale_factor) override;
+  base::FilePath GetPathForResourcePack(
+      const base::FilePath& pack_path,
+      ui::ResourceScaleFactor scale_factor) override;
   base::FilePath GetPathForLocalePack(const base::FilePath& pack_path,
                                       const std::string& locale) override;
   gfx::Image GetImageNamed(int resource_id) override;
   gfx::Image GetNativeImageNamed(int resource_id) override;
-  base::RefCountedStaticMemory* LoadDataResourceBytes(
+  base::RefCountedMemory* LoadDataResourceBytes(
       int resource_id,
-      ui::ScaleFactor scale_factor) override;
+      ui::ResourceScaleFactor scale_factor) override;
+  absl::optional<std::string> LoadDataResourceString(int resource_id) override;
   bool GetRawDataResource(int resource_id,
-                          ui::ScaleFactor scale_factor,
-                          base::StringPiece* value) override;
-  bool GetLocalizedString(int message_id, base::string16* value) override;
+                          ui::ResourceScaleFactor scale_factor,
+                          base::StringPiece* value) const override;
+  bool GetLocalizedString(int message_id, std::u16string* value) const override;
 
  private:
-  CefContentClient* content_client_;
+  bool pack_loading_disabled_ = false;
+  bool allow_pack_file_load_ = false;
 };
 
 #endif  // CEF_LIBCEF_COMMON_RESOURCE_BUNDLE_DELEGATE_H_
diff --git a/src/libcef/common/resource_bundle_impl.cc b/src/libcef/common/resource_bundle_impl.cc
index 2f4d20c..7af873b 100644
--- a/src/libcef/common/resource_bundle_impl.cc
+++ b/src/libcef/common/resource_bundle_impl.cc
@@ -4,40 +4,39 @@
 
 #include "libcef/common/resource_bundle_impl.h"
 
+#include "base/memory/ref_counted_memory.h"
 #include "ui/base/resource/resource_bundle.h"
 
 CefResourceBundleImpl::CefResourceBundleImpl() {}
 
 CefString CefResourceBundleImpl::GetLocalizedString(int string_id) {
-  if (!ui::ResourceBundle::HasSharedInstance())
+  if (!ui::ResourceBundle::HasSharedInstance()) {
     return CefString();
+  }
 
   return ui::ResourceBundle::GetSharedInstance().GetLocalizedString(string_id);
 }
 
-bool CefResourceBundleImpl::GetDataResource(int resource_id,
-                                            void*& data,
-                                            size_t& data_size) {
-  return GetDataResourceForScale(resource_id, SCALE_FACTOR_NONE, data,
-                                 data_size);
+CefRefPtr<CefBinaryValue> CefResourceBundleImpl::GetDataResource(
+    int resource_id) {
+  return GetDataResourceForScale(resource_id, SCALE_FACTOR_NONE);
 }
 
-bool CefResourceBundleImpl::GetDataResourceForScale(int resource_id,
-                                                    ScaleFactor scale_factor,
-                                                    void*& data,
-                                                    size_t& data_size) {
-  if (!ui::ResourceBundle::HasSharedInstance())
-    return false;
+CefRefPtr<CefBinaryValue> CefResourceBundleImpl::GetDataResourceForScale(
+    int resource_id,
+    ScaleFactor scale_factor) {
+  if (!ui::ResourceBundle::HasSharedInstance()) {
+    return nullptr;
+  }
 
-  const base::StringPiece& result =
-      ui::ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(
-          resource_id, static_cast<ui::ScaleFactor>(scale_factor));
-  if (result.empty())
-    return false;
+  base::RefCountedMemory* result =
+      ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
+          resource_id, static_cast<ui::ResourceScaleFactor>(scale_factor));
+  if (!result) {
+    return nullptr;
+  }
 
-  data = const_cast<char*>(result.data());
-  data_size = result.size();
-  return true;
+  return CefBinaryValue::Create(result->data(), result->size());
 }
 
 // static
diff --git a/src/libcef/common/resource_bundle_impl.h b/src/libcef/common/resource_bundle_impl.h
index cc02682..e759dae 100644
--- a/src/libcef/common/resource_bundle_impl.h
+++ b/src/libcef/common/resource_bundle_impl.h
@@ -12,19 +12,18 @@
  public:
   CefResourceBundleImpl();
 
+  CefResourceBundleImpl(const CefResourceBundleImpl&) = delete;
+  CefResourceBundleImpl& operator=(const CefResourceBundleImpl&) = delete;
+
   // CefResourceBundle methods.
   CefString GetLocalizedString(int string_id) override;
-  bool GetDataResource(int resource_id,
-                       void*& data,
-                       size_t& data_size) override;
-  bool GetDataResourceForScale(int resource_id,
-                               ScaleFactor scale_factor,
-                               void*& data,
-                               size_t& data_size) override;
+  CefRefPtr<CefBinaryValue> GetDataResource(int resource_id) override;
+  CefRefPtr<CefBinaryValue> GetDataResourceForScale(
+      int resource_id,
+      ScaleFactor scale_factor) override;
 
  private:
   IMPLEMENT_REFCOUNTING(CefResourceBundleImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefResourceBundleImpl);
 };
 
 #endif  // CEF_LIBCEF_COMMON_RESOURCE_BUNDLE_IMPL_H_
diff --git a/src/libcef/common/resource_util.cc b/src/libcef/common/resource_util.cc
new file mode 100644
index 0000000..b0bf7fa
--- /dev/null
+++ b/src/libcef/common/resource_util.cc
@@ -0,0 +1,239 @@
+// Copyright 2017 The Chromium Embedded Framework Authors. Portions copyright
+// 2011 The Chromium Authors. All rights reserved. Use of this source code is
+// governed by a BSD-style license that can be found in the LICENSE file.
+
+#include "libcef/common/resource_util.h"
+
+#if BUILDFLAG(IS_LINUX)
+#include <dlfcn.h>
+#endif
+
+#include "libcef/features/runtime.h"
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/notreached.h"
+#include "base/path_service.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_paths_internal.h"
+#include "chrome/common/chrome_switches.h"
+#include "ui/base/layout.h"
+
+#if BUILDFLAG(IS_MAC)
+#include "base/apple/foundation_util.h"
+#include "libcef/common/util_mac.h"
+#endif
+
+#if BUILDFLAG(IS_LINUX)
+#include "base/environment.h"
+#include "base/nix/xdg_util.h"
+#endif
+
+#if BUILDFLAG(IS_WIN)
+#include "base/win/registry.h"
+#endif
+
+namespace resource_util {
+
+namespace {
+
+#if BUILDFLAG(IS_LINUX)
+
+// Based on chrome/common/chrome_paths_linux.cc.
+// See http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
+// for a spec on where config files go. The net result on most systems is that
+// we use "~/.config/cef_user_data".
+bool GetDefaultUserDataDirectory(base::FilePath* result) {
+  std::unique_ptr<base::Environment> env(base::Environment::Create());
+  base::FilePath config_dir(base::nix::GetXDGDirectory(
+      env.get(), base::nix::kXdgConfigHomeEnvVar, base::nix::kDotConfigDir));
+  *result = config_dir.Append(FILE_PATH_LITERAL("cef_user_data"));
+  return true;
+}
+
+#elif BUILDFLAG(IS_MAC)
+
+// Based on chrome/common/chrome_paths_mac.mm.
+bool GetDefaultUserDataDirectory(base::FilePath* result) {
+  if (!base::PathService::Get(base::DIR_APP_DATA, result)) {
+    return false;
+  }
+  *result = result->Append(FILE_PATH_LITERAL("CEF"));
+  *result = result->Append(FILE_PATH_LITERAL("User Data"));
+  return true;
+}
+
+#elif BUILDFLAG(IS_WIN)
+
+// Based on chrome/common/chrome_paths_win.cc.
+bool GetDefaultUserDataDirectory(base::FilePath* result) {
+  if (!base::PathService::Get(base::DIR_LOCAL_APP_DATA, result)) {
+    return false;
+  }
+  *result = result->Append(FILE_PATH_LITERAL("CEF"));
+  *result = result->Append(FILE_PATH_LITERAL("User Data"));
+  return true;
+}
+
+#endif
+
+base::FilePath GetUserDataPath(CefSettings* settings,
+                               const base::CommandLine* command_line) {
+  // |settings| will be non-nullptr in the main process only.
+  if (settings) {
+    CefString root_cache_path;
+    if (settings->root_cache_path.length > 0) {
+      root_cache_path = CefString(&settings->root_cache_path);
+    }
+    if (!root_cache_path.empty()) {
+      return base::FilePath(root_cache_path);
+    }
+  }
+
+  // This may be set for sub-processes.
+  base::FilePath result =
+      command_line->GetSwitchValuePath(switches::kUserDataDir);
+  if (!result.empty()) {
+    return result;
+  }
+
+  if (GetDefaultUserDataDirectory(&result)) {
+    return result;
+  }
+
+  if (base::PathService::Get(base::DIR_TEMP, &result)) {
+    return result;
+  }
+
+  DCHECK(false);
+  return result;
+}
+
+// Consider downloads 'dangerous' if they go to the home directory on Linux and
+// to the desktop on any platform.
+// From chrome/browser/download/download_prefs.cc.
+bool DownloadPathIsDangerous(const base::FilePath& download_path) {
+#if BUILDFLAG(IS_LINUX)
+  base::FilePath home_dir = base::GetHomeDir();
+  if (download_path == home_dir) {
+    return true;
+  }
+#endif
+
+  base::FilePath desktop_dir;
+  if (!base::PathService::Get(base::DIR_USER_DESKTOP, &desktop_dir)) {
+    DCHECK(false);
+    return false;
+  }
+  return (download_path == desktop_dir);
+}
+
+bool GetDefaultDownloadDirectory(base::FilePath* result) {
+  // This will return the safe download directory if necessary.
+  return chrome::GetUserDownloadsDirectory(result);
+}
+
+bool GetDefaultDownloadSafeDirectory(base::FilePath* result) {
+  // Start with the default download directory.
+  if (!GetDefaultDownloadDirectory(result)) {
+    return false;
+  }
+
+  if (DownloadPathIsDangerous(*result)) {
+#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
+    // Explicitly switch to the safe download directory.
+    return chrome::GetUserDownloadsDirectorySafe(result);
+#else
+    // No viable alternative on macOS.
+    return false;
+#endif
+  }
+
+  return true;
+}
+
+}  // namespace
+
+#if BUILDFLAG(IS_MAC)
+
+base::FilePath GetResourcesDir() {
+  return util_mac::GetFrameworkResourcesDirectory();
+}
+
+// Use a "~/Library/Logs/<app name>_debug.log" file where <app name> is the name
+// of the running executable.
+base::FilePath GetDefaultLogFilePath() {
+  std::string exe_name = util_mac::GetMainProcessPath().BaseName().value();
+  return base::apple::GetUserLibraryPath()
+      .Append(FILE_PATH_LITERAL("Logs"))
+      .Append(FILE_PATH_LITERAL(exe_name + "_debug.log"));
+}
+
+#else  // !BUILDFLAG(IS_MAC)
+
+base::FilePath GetResourcesDir() {
+  base::FilePath pak_dir;
+  base::PathService::Get(base::DIR_ASSETS, &pak_dir);
+  return pak_dir;
+}
+
+// Use a "debug.log" file in the running executable's directory.
+base::FilePath GetDefaultLogFilePath() {
+  base::FilePath log_path;
+  base::PathService::Get(base::DIR_EXE, &log_path);
+  return log_path.Append(FILE_PATH_LITERAL("debug.log"));
+}
+
+#endif  // !BUILDFLAG(IS_MAC)
+
+void OverrideDefaultDownloadDir() {
+  base::FilePath dir_default_download;
+  base::FilePath dir_default_download_safe;
+  if (GetDefaultDownloadDirectory(&dir_default_download)) {
+    base::PathService::Override(chrome::DIR_DEFAULT_DOWNLOADS,
+                                dir_default_download);
+  }
+  if (GetDefaultDownloadSafeDirectory(&dir_default_download_safe)) {
+    base::PathService::Override(chrome::DIR_DEFAULT_DOWNLOADS_SAFE,
+                                dir_default_download_safe);
+  }
+}
+
+void OverrideUserDataDir(CefSettings* settings,
+                         const base::CommandLine* command_line) {
+  const base::FilePath& user_data_path =
+      GetUserDataPath(settings, command_line);
+  base::PathService::Override(chrome::DIR_USER_DATA, user_data_path);
+
+  // Path used for crash dumps.
+  base::PathService::Override(chrome::DIR_CRASH_DUMPS, user_data_path);
+
+  // Path used for spell checking dictionary files.
+  base::PathService::OverrideAndCreateIfNeeded(
+      chrome::DIR_APP_DICTIONARIES,
+      user_data_path.Append(FILE_PATH_LITERAL("Dictionaries")),
+      false,  // May not be an absolute path.
+      true);  // Create if necessary.
+}
+
+// Same as ui::ResourceBundle::IsScaleFactorSupported.
+bool IsScaleFactorSupported(ui::ResourceScaleFactor scale_factor) {
+  const auto& supported_scale_factors = ui::GetSupportedResourceScaleFactors();
+  return std::find(supported_scale_factors.begin(),
+                   supported_scale_factors.end(),
+                   scale_factor) != supported_scale_factors.end();
+}
+
+#if BUILDFLAG(IS_LINUX)
+void OverrideAssetPath() {
+  Dl_info dl_info;
+  if (dladdr(reinterpret_cast<const void*>(&OverrideAssetPath), &dl_info)) {
+    base::FilePath path = base::FilePath(dl_info.dli_fname).DirName();
+    base::PathService::Override(base::DIR_ASSETS, path);
+  }
+}
+#endif
+
+}  // namespace resource_util
diff --git a/src/libcef/common/resource_util.h b/src/libcef/common/resource_util.h
new file mode 100644
index 0000000..a23912e
--- /dev/null
+++ b/src/libcef/common/resource_util.h
@@ -0,0 +1,44 @@
+// Copyright 2017 The Chromium Embedded Framework Authors. Portions copyright
+// 2011 The Chromium Authors. All rights reserved. Use of this source code is
+// governed by a BSD-style license that can be found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_COMMON_RESOURCE_UTIL_H_
+#define CEF_LIBCEF_COMMON_RESOURCE_UTIL_H_
+#pragma once
+
+#include "include/cef_base.h"
+
+#include "ui/base/resource/resource_scale_factor.h"
+
+namespace base {
+class CommandLine;
+class FilePath;
+}  // namespace base
+
+namespace resource_util {
+
+// Returns the directory that contains resource files (*.bin, *.dat, *.pak,
+// etc).
+base::FilePath GetResourcesDir();
+
+// Returns the default path for the debug.log file.
+base::FilePath GetDefaultLogFilePath();
+
+// Called from MainDelegate::PreSandboxStartup.
+void OverrideDefaultDownloadDir();
+void OverrideUserDataDir(CefSettings* settings,
+                         const base::CommandLine* command_line);
+
+// Returns true if |scale_factor| is supported by this platform.
+bool IsScaleFactorSupported(ui::ResourceScaleFactor scale_factor);
+
+#if BUILDFLAG(IS_LINUX)
+// Look for binary files (*.bin, *.dat, *.pak, chrome-sandbox, libGLESv2.so,
+// libEGL.so, locales/*.pak, swiftshader/*.so) next to libcef instead of the exe
+// on Linux. This is already the default on Windows.
+void OverrideAssetPath();
+#endif
+
+}  // namespace resource_util
+
+#endif  // CEF_LIBCEF_COMMON_RESOURCE_UTIL_H_
diff --git a/src/libcef/common/response_impl.cc b/src/libcef/common/response_impl.cc
index c55a173..2127045 100644
--- a/src/libcef/common/response_impl.cc
+++ b/src/libcef/common/response_impl.cc
@@ -18,10 +18,10 @@
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/platform/web_url_response.h"
 
-#define CHECK_READONLY_RETURN_VOID()       \
-  if (read_only_) {                        \
-    NOTREACHED() << "object is read only"; \
-    return;                                \
+#define CHECK_READONLY_RETURN_VOID()        \
+  if (read_only_) {                         \
+    DCHECK(false) << "object is read only"; \
+    return;                                 \
   }
 
 // CefResponse ----------------------------------------------------------------
@@ -104,8 +104,9 @@
   HttpHeaderUtils::MakeASCIILower(&nameLower);
 
   auto it = HttpHeaderUtils::FindHeaderInMap(nameLower, header_map_);
-  if (it != header_map_.end())
+  if (it != header_map_.end()) {
     return it->second;
+  }
 
   return CefString();
 }
@@ -122,8 +123,9 @@
   // There may be multiple values, so remove any first.
   for (auto it = header_map_.begin(); it != header_map_.end();) {
     if (base::EqualsCaseInsensitiveASCII(it->first.ToString(), nameLower)) {
-      if (!overwrite)
+      if (!overwrite) {
         return;
+      }
       it = header_map_.erase(it);
     } else {
       ++it;
@@ -159,12 +161,14 @@
   base::AutoLock lock_scope(lock_);
 
   std::string mime_type = mime_type_;
-  if (mime_type.empty())
+  if (mime_type.empty()) {
     mime_type = "text/html";
+  }
 
   std::multimap<std::string, std::string> extra_headers;
-  for (const auto& pair : header_map_)
+  for (const auto& pair : header_map_) {
     extra_headers.insert(std::make_pair(pair.first, pair.second));
+  }
 
   return net_service::MakeResponseHeaders(
       status_code_, status_text_, mime_type, charset_, -1, extra_headers,
@@ -180,8 +184,9 @@
 
   size_t iter = 0;
   std::string name, value;
-  while (headers.EnumerateHeaderLines(&iter, &name, &value))
+  while (headers.EnumerateHeaderLines(&iter, &name, &value)) {
     header_map_.insert(std::make_pair(name, value));
+  }
 
   status_code_ = headers.response_code();
   status_text_ = headers.GetStatusText();
diff --git a/src/libcef/common/response_manager.cc b/src/libcef/common/response_manager.cc
deleted file mode 100644
index 2e97c4a..0000000
--- a/src/libcef/common/response_manager.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework 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 "libcef/common/response_manager.h"
-#include "libcef/common/cef_messages.h"
-
-#include "base/logging.h"
-
-CefResponseManager::CefResponseManager() : next_request_id_(0) {}
-
-int CefResponseManager::GetNextRequestId() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return ++next_request_id_;
-}
-
-int CefResponseManager::RegisterHandler(CefRefPtr<Handler> handler) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  int request_id = GetNextRequestId();
-  TRACE_EVENT_ASYNC_BEGIN1("cef", "CefResponseManager::Handler", request_id,
-                           "request_id", request_id);
-  handlers_.insert(std::make_pair(request_id, handler));
-  return request_id;
-}
-
-bool CefResponseManager::RunHandler(const Cef_Response_Params& params) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK_GT(params.request_id, 0);
-  HandlerMap::iterator it = handlers_.find(params.request_id);
-  if (it != handlers_.end()) {
-    TRACE_EVENT0("cef", "CefResponseManager::RunHandler");
-    it->second->OnResponse(params);
-    handlers_.erase(it);
-    TRACE_EVENT_ASYNC_END1("cef", "CefResponseManager::Handler",
-                           params.request_id, "success", 1);
-    return true;
-  }
-  TRACE_EVENT_ASYNC_END1("cef", "CefResponseManager::Handler",
-                         params.request_id, "success", 0);
-  return false;
-}
-
-void CefResponseManager::RegisterAckHandler(int request_id,
-                                            CefRefPtr<AckHandler> handler) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  ack_handlers_.insert(std::make_pair(request_id, handler));
-}
-
-bool CefResponseManager::RunAckHandler(int request_id) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK_GT(request_id, 0);
-  AckHandlerMap::iterator it = ack_handlers_.find(request_id);
-  if (it != ack_handlers_.end()) {
-    it->second->OnResponseAck();
-    ack_handlers_.erase(it);
-    return true;
-  }
-  return false;
-}
diff --git a/src/libcef/common/response_manager.h b/src/libcef/common/response_manager.h
deleted file mode 100644
index 3e47c76..0000000
--- a/src/libcef/common/response_manager.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework 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 CEF_LIBCEF_COMMON_RESPONSE_MANAGER_H_
-#define CEF_LIBCEF_COMMON_RESPONSE_MANAGER_H_
-#pragma once
-
-#include <map>
-
-#include "include/cef_base.h"
-
-#include "base/sequence_checker.h"
-
-struct Cef_Response_Params;
-
-// This class is not thread-safe.
-class CefResponseManager {
- public:
-  // Used for handling response messages.
-  class Handler : public virtual CefBaseRefCounted {
-   public:
-    virtual void OnResponse(const Cef_Response_Params& params) = 0;
-  };
-
-  // Used for handling response ack messages.
-  class AckHandler : public virtual CefBaseRefCounted {
-   public:
-    virtual void OnResponseAck() = 0;
-  };
-
-  CefResponseManager();
-
-  // Returns the next unique request id.
-  int GetNextRequestId();
-
-  // Register a response handler and return the unique request id.
-  int RegisterHandler(CefRefPtr<Handler> handler);
-
-  // Run the response handler for the specified request id. Returns true if a
-  // handler was run.
-  bool RunHandler(const Cef_Response_Params& params);
-
-  // Register a response ack handler for the specified request id.
-  void RegisterAckHandler(int request_id, CefRefPtr<AckHandler> handler);
-
-  // Run the response ack handler for the specified request id. Returns true if
-  // a handler was run.
-  bool RunAckHandler(int request_id);
-
- private:
-  // Used for generating unique request ids.
-  int next_request_id_;
-
-  // Map of unique request ids to Handler references.
-  typedef std::map<int, CefRefPtr<Handler>> HandlerMap;
-  HandlerMap handlers_;
-
-  // Map of unique request ids to AckHandler references.
-  typedef std::map<int, CefRefPtr<AckHandler>> AckHandlerMap;
-  AckHandlerMap ack_handlers_;
-
-  SEQUENCE_CHECKER(sequence_checker_);
-};
-
-#endif  // CEF_LIBCEF_COMMON_RESPONSE_MANAGER_H_
diff --git a/src/libcef/common/scheme_registrar_impl.cc b/src/libcef/common/scheme_registrar_impl.cc
index 870d797..a31734f 100644
--- a/src/libcef/common/scheme_registrar_impl.cc
+++ b/src/libcef/common/scheme_registrar_impl.cc
@@ -6,10 +6,11 @@
 
 #include <string>
 
-#include "libcef/common/content_client.h"
+#include "libcef/common/app_manager.h"
+#include "libcef/common/net/scheme_info.h"
 #include "libcef/common/net/scheme_registration.h"
 
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #include "base/logging.h"
 #include "base/strings/string_util.h"
 
@@ -17,8 +18,9 @@
 
 void AppendArray(const std::vector<std::string>& source,
                  std::vector<std::string>* target) {
-  if (source.empty())
+  if (source.empty()) {
     return;
+  }
   target->insert(target->end(), source.begin(), source.end());
 }
 }  // namespace
@@ -45,21 +47,26 @@
 
   // The |is_display_isolated| value is excluded here because it's registered
   // with Blink only.
-  if (is_standard)
+  if (is_standard) {
     schemes_.standard_schemes.push_back(scheme);
-  if (is_local)
+  }
+  if (is_local) {
     schemes_.local_schemes.push_back(scheme);
-  if (is_secure)
+  }
+  if (is_secure) {
     schemes_.secure_schemes.push_back(scheme);
-  if (is_cors_enabled)
+  }
+  if (is_cors_enabled) {
     schemes_.cors_enabled_schemes.push_back(scheme);
-  if (is_csp_bypassing)
+  }
+  if (is_csp_bypassing) {
     schemes_.csp_bypassing_schemes.push_back(scheme);
+  }
 
-  CefContentClient::SchemeInfo scheme_info = {
+  CefSchemeInfo scheme_info = {
       scheme,    is_standard,     is_local,         is_display_isolated,
       is_secure, is_cors_enabled, is_csp_bypassing, is_fetch_enabled};
-  CefContentClient::Get()->AddCustomScheme(scheme_info);
+  CefAppManager::Get()->AddCustomScheme(&scheme_info);
 
   return true;
 }
diff --git a/src/libcef/common/scheme_registrar_impl.h b/src/libcef/common/scheme_registrar_impl.h
index ed71266..375b437 100644
--- a/src/libcef/common/scheme_registrar_impl.h
+++ b/src/libcef/common/scheme_registrar_impl.h
@@ -17,6 +17,9 @@
  public:
   CefSchemeRegistrarImpl();
 
+  CefSchemeRegistrarImpl(const CefSchemeRegistrarImpl&) = delete;
+  CefSchemeRegistrarImpl& operator=(const CefSchemeRegistrarImpl&) = delete;
+
   // CefSchemeRegistrar methods.
   bool AddCustomScheme(const CefString& scheme_name, int options) override;
 
@@ -25,8 +28,6 @@
  private:
   content::ContentClient::Schemes schemes_;
   std::set<std::string> registered_schemes_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefSchemeRegistrarImpl);
 };
 
 #endif  // CEF_LIBCEF_COMMON_SCHEME_REGISTRAR_IMPL_H_
diff --git a/src/libcef/common/service_manifests/cef_content_browser_overlay_manifest.cc b/src/libcef/common/service_manifests/cef_content_browser_overlay_manifest.cc
deleted file mode 100644
index c254c76..0000000
--- a/src/libcef/common/service_manifests/cef_content_browser_overlay_manifest.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/common/service_manifests/cef_content_browser_overlay_manifest.h"
-
-#include "base/command_line.h"
-#include "base/no_destructor.h"
-#include "build/build_config.h"
-#include "components/metrics/public/mojom/call_stack_profile_collector.mojom.h"
-#include "extensions/buildflags/buildflags.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-
-#if defined(OS_WIN)
-#include "chrome/common/conflicts/module_event_sink_win.mojom.h"
-#endif
-
-const service_manager::Manifest& GetCefContentBrowserOverlayManifest() {
-  static base::NoDestructor<service_manager::Manifest> manifest {
-    service_manager::ManifestBuilder()
-        .ExposeCapability("gpu",
-                          service_manager::Manifest::InterfaceList<
-                              metrics::mojom::CallStackProfileCollector>())
-        .ExposeCapability("renderer",
-                          service_manager::Manifest::InterfaceList<
-#if defined(OS_WIN)
-                              mojom::ModuleEventSink,
-#endif
-                              metrics::mojom::CallStackProfileCollector>())
-        .RequireCapability("chrome_printing", "converter")
-        .Build()
-  };
-  return *manifest;
-}
diff --git a/src/libcef/common/service_manifests/cef_content_browser_overlay_manifest.h b/src/libcef/common/service_manifests/cef_content_browser_overlay_manifest.h
deleted file mode 100644
index 844a5e8..0000000
--- a/src/libcef/common/service_manifests/cef_content_browser_overlay_manifest.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_COMMON_SERVICE_MANIFESTS_CEF_CONTENT_BROWSER_OVERLAY_MANIFEST_H_
-#define CEF_LIBCEF_COMMON_SERVICE_MANIFESTS_CEF_CONTENT_BROWSER_OVERLAY_MANIFEST_H_
-
-#include "services/service_manager/public/cpp/manifest.h"
-
-// Returns the Manifest CEF amends to Content's content_browser service
-// manifest. This allows CEF to extend the capabilities exposed and/or
-// required by content_browser service instances, as well as declaring any
-// additional in- and out-of-process per-profile packaged services.
-const service_manager::Manifest& GetCefContentBrowserOverlayManifest();
-
-#endif  // CEF_LIBCEF_COMMON_SERVICE_MANIFESTS_CEF_CONTENT_BROWSER_OVERLAY_MANIFEST_H_
diff --git a/src/libcef/common/string_list_impl.cc b/src/libcef/common/string_list_impl.cc
index ce2517f..0b32ecf 100644
--- a/src/libcef/common/string_list_impl.cc
+++ b/src/libcef/common/string_list_impl.cc
@@ -8,10 +8,12 @@
 
 #include "base/logging.h"
 
-typedef std::vector<CefString> StringList;
+namespace {
+using StringList = std::vector<CefString>;
+}  // namespace
 
 CEF_EXPORT cef_string_list_t cef_string_list_alloc() {
-  return new StringList;
+  return reinterpret_cast<cef_string_list_t>(new StringList);
 }
 
 CEF_EXPORT size_t cef_string_list_size(cef_string_list_t list) {
@@ -27,8 +29,9 @@
   DCHECK(value);
   StringList* impl = reinterpret_cast<StringList*>(list);
   DCHECK_LT(index, impl->size());
-  if (index >= impl->size())
+  if (index >= impl->size()) {
     return false;
+  }
   const CefString& str = (*impl)[index];
   return cef_string_copy(str.c_str(), str.length(), value);
 }
@@ -55,5 +58,5 @@
 CEF_EXPORT cef_string_list_t cef_string_list_copy(cef_string_list_t list) {
   DCHECK(list);
   StringList* impl = reinterpret_cast<StringList*>(list);
-  return new StringList(*impl);
+  return reinterpret_cast<cef_string_list_t>(new StringList(*impl));
 }
diff --git a/src/libcef/common/string_map_impl.cc b/src/libcef/common/string_map_impl.cc
index 16e682f..3dd71ea 100644
--- a/src/libcef/common/string_map_impl.cc
+++ b/src/libcef/common/string_map_impl.cc
@@ -3,15 +3,48 @@
 // can be found in the LICENSE file.
 
 #include <map>
+#include <vector>
 
 #include "include/internal/cef_string_map.h"
 
 #include "base/logging.h"
 
-typedef std::map<CefString, CefString> StringMap;
+namespace {
+
+class StringMap {
+  using Map = std::map<CefString, CefString>;
+  using value_type = Map::value_type;
+
+ public:
+  using const_iterator = Map::const_iterator;
+
+  size_t size() const { return map_ref_.size(); }
+  size_t count(const CefString& key) const { return map_.count(key); }
+  const_iterator find(const CefString& value) const { return map_.find(value); }
+  const_iterator cend() const { return map_.cend(); }
+  const value_type& operator[](size_t pos) const { return *map_ref_[pos]; }
+
+  void insert(value_type&& value) {
+    // does not invalidate iterators
+    const auto [it, inserted] = map_.insert(std::move(value));
+    if (inserted) {
+      map_ref_.push_back(std::move(it));
+    }
+  }
+  void clear() {
+    map_ref_.clear();
+    map_.clear();
+  }
+
+ private:
+  Map map_;
+  std::vector<Map::const_iterator> map_ref_;
+};
+
+}  // namespace
 
 CEF_EXPORT cef_string_map_t cef_string_map_alloc() {
-  return new StringMap;
+  return reinterpret_cast<cef_string_map_t>(new StringMap);
 }
 
 CEF_EXPORT size_t cef_string_map_size(cef_string_map_t map) {
@@ -27,8 +60,9 @@
   DCHECK(value);
   StringMap* impl = reinterpret_cast<StringMap*>(map);
   StringMap::const_iterator it = impl->find(CefString(key));
-  if (it == impl->end())
+  if (it == impl->cend()) {
     return 0;
+  }
 
   const CefString& val = it->second;
   return cef_string_set(val.c_str(), val.length(), value, true);
@@ -41,15 +75,12 @@
   DCHECK(key);
   StringMap* impl = reinterpret_cast<StringMap*>(map);
   DCHECK_LT(index, impl->size());
-  if (index >= impl->size())
+  if (index >= impl->size()) {
     return 0;
-
-  StringMap::const_iterator it = impl->begin();
-  for (size_t ct = 0; it != impl->end(); ++it, ct++) {
-    if (ct == index)
-      return cef_string_set(it->first.c_str(), it->first.length(), key, true);
   }
-  return 0;
+
+  const auto& [k, _] = (*impl)[index];
+  return cef_string_set(k.c_str(), k.length(), key, true);
 }
 
 CEF_EXPORT int cef_string_map_value(cef_string_map_t map,
@@ -59,17 +90,12 @@
   DCHECK(value);
   StringMap* impl = reinterpret_cast<StringMap*>(map);
   DCHECK_LT(index, impl->size());
-  if (index >= impl->size())
+  if (index >= impl->size()) {
     return 0;
-
-  StringMap::const_iterator it = impl->begin();
-  for (size_t ct = 0; it != impl->end(); ++it, ct++) {
-    if (ct == index) {
-      return cef_string_set(it->second.c_str(), it->second.length(), value,
-                            true);
-    }
   }
-  return 0;
+
+  const auto& [_, v] = (*impl)[index];
+  return cef_string_set(v.c_str(), v.length(), value, true);
 }
 
 CEF_EXPORT int cef_string_map_append(cef_string_map_t map,
diff --git a/src/libcef/common/string_multimap_impl.cc b/src/libcef/common/string_multimap_impl.cc
index e2fe6e0..56e6d55 100644
--- a/src/libcef/common/string_multimap_impl.cc
+++ b/src/libcef/common/string_multimap_impl.cc
@@ -3,15 +3,47 @@
 // can be found in the LICENSE file.
 
 #include <map>
+#include <vector>
 
 #include "include/internal/cef_string_multimap.h"
 
 #include "base/logging.h"
 
-typedef std::multimap<CefString, CefString> StringMultimap;
+namespace {
+
+class StringMultimap {
+  using Map = std::multimap<CefString, CefString>;
+  using value_type = Map::value_type;
+
+ public:
+  using const_iterator = Map::const_iterator;
+
+  size_t size() const { return map_ref_.size(); }
+  size_t count(const CefString& key) const { return map_.count(key); }
+  const value_type operator[](size_t pos) const { return *map_ref_[pos]; }
+
+  std::pair<const_iterator, const_iterator> equal_range(
+      const CefString& key) const {
+    return map_.equal_range(key);
+  }
+  void insert(value_type&& value) {
+    auto it = map_.insert(std::move(value));  // does not invalidate iterators
+    map_ref_.push_back(std::move(it));
+  }
+  void clear() {
+    map_ref_.clear();
+    map_.clear();
+  }
+
+ private:
+  Map map_;
+  std::vector<Map::const_iterator> map_ref_;
+};
+
+}  // namespace
 
 CEF_EXPORT cef_string_multimap_t cef_string_multimap_alloc() {
-  return new StringMultimap;
+  return reinterpret_cast<cef_string_multimap_t>(new StringMultimap);
 }
 
 CEF_EXPORT size_t cef_string_multimap_size(cef_string_multimap_t map) {
@@ -40,18 +72,21 @@
   CefString key_str(key);
 
   DCHECK_LT(value_index, impl->count(key_str));
-  if (value_index >= impl->count(key_str))
+  if (value_index >= impl->count(key_str)) {
     return 0;
+  }
 
-  std::pair<StringMultimap::iterator, StringMultimap::iterator> range_it =
-      impl->equal_range(key_str);
+  std::pair<StringMultimap::const_iterator, StringMultimap::const_iterator>
+      range_it = impl->equal_range(key_str);
 
   size_t count = value_index;
-  while (count-- && range_it.first != range_it.second)
+  while (count-- && range_it.first != range_it.second) {
     range_it.first++;
+  }
 
-  if (range_it.first == range_it.second)
+  if (range_it.first == range_it.second) {
     return 0;
+  }
 
   const CefString& val = range_it.first->second;
   return cef_string_set(val.c_str(), val.length(), value, true);
@@ -64,15 +99,12 @@
   DCHECK(key);
   StringMultimap* impl = reinterpret_cast<StringMultimap*>(map);
   DCHECK_LT(index, impl->size());
-  if (index >= impl->size())
+  if (index >= impl->size()) {
     return 0;
-
-  StringMultimap::const_iterator it = impl->begin();
-  for (size_t ct = 0; it != impl->end(); ++it, ct++) {
-    if (ct == index)
-      return cef_string_set(it->first.c_str(), it->first.length(), key, true);
   }
-  return 0;
+
+  const auto& [k, _] = (*impl)[index];
+  return cef_string_set(k.c_str(), k.length(), key, true);
 }
 
 CEF_EXPORT int cef_string_multimap_value(cef_string_multimap_t map,
@@ -82,17 +114,12 @@
   DCHECK(value);
   StringMultimap* impl = reinterpret_cast<StringMultimap*>(map);
   DCHECK_LT(index, impl->size());
-  if (index >= impl->size())
+  if (index >= impl->size()) {
     return 0;
-
-  StringMultimap::const_iterator it = impl->begin();
-  for (size_t ct = 0; it != impl->end(); ++it, ct++) {
-    if (ct == index) {
-      return cef_string_set(it->second.c_str(), it->second.length(), value,
-                            true);
-    }
   }
-  return 0;
+
+  const auto& [_, v] = (*impl)[index];
+  return cef_string_set(v.c_str(), v.length(), value, true);
 }
 
 CEF_EXPORT int cef_string_multimap_append(cef_string_multimap_t map,
diff --git a/src/libcef/common/string_types_impl.cc b/src/libcef/common/string_types_impl.cc
index b9b18f2..aed3f6d 100644
--- a/src/libcef/common/string_types_impl.cc
+++ b/src/libcef/common/string_types_impl.cc
@@ -8,7 +8,6 @@
 
 #include "base/i18n/case_conversion.h"
 #include "base/logging.h"
-#include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 
@@ -22,7 +21,7 @@
   delete[] str;
 }
 
-void string_utf16_dtor(char16* str) {
+void string_utf16_dtor(char16_t* str) {
   delete[] str;
 }
 
@@ -43,8 +42,9 @@
   if (copy) {
     if (src && src_len > 0) {
       output->str = new wchar_t[src_len + 1];
-      if (!output->str)
+      if (!output->str) {
         return 0;
+      }
 
       memcpy(output->str, src, src_len * sizeof(wchar_t));
       output->str[src_len] = 0;
@@ -67,8 +67,9 @@
   if (copy) {
     if (src && src_len > 0) {
       output->str = new char[src_len + 1];
-      if (!output->str)
+      if (!output->str) {
         return 0;
+      }
 
       memcpy(output->str, src, src_len * sizeof(char));
       output->str[src_len] = 0;
@@ -83,7 +84,7 @@
   return 1;
 }
 
-CEF_EXPORT int cef_string_utf16_set(const char16* src,
+CEF_EXPORT int cef_string_utf16_set(const char16_t* src,
                                     size_t src_len,
                                     cef_string_utf16_t* output,
                                     int copy) {
@@ -91,17 +92,18 @@
 
   if (copy) {
     if (src && src_len > 0) {
-      output->str = new char16[src_len + 1];
-      if (!output->str)
+      output->str = new char16_t[src_len + 1];
+      if (!output->str) {
         return 0;
+      }
 
-      memcpy(output->str, src, src_len * sizeof(char16));
+      memcpy(output->str, src, src_len * sizeof(char16_t));
       output->str[src_len] = 0;
       output->length = src_len;
       output->dtor = string_utf16_dtor;
     }
   } else {
-    output->str = const_cast<char16*>(src);
+    output->str = const_cast<char16_t*>(src);
     output->length = src_len;
     output->dtor = nullptr;
   }
@@ -110,8 +112,9 @@
 
 CEF_EXPORT void cef_string_wide_clear(cef_string_wide_t* str) {
   DCHECK(str != nullptr);
-  if (str->dtor && str->str)
+  if (str->dtor && str->str) {
     str->dtor(str->str);
+  }
 
   str->str = nullptr;
   str->length = 0;
@@ -120,8 +123,9 @@
 
 CEF_EXPORT void cef_string_utf8_clear(cef_string_utf8_t* str) {
   DCHECK(str != nullptr);
-  if (str->dtor && str->str)
+  if (str->dtor && str->str) {
     str->dtor(str->str);
+  }
 
   str->str = nullptr;
   str->length = 0;
@@ -130,8 +134,9 @@
 
 CEF_EXPORT void cef_string_utf16_clear(cef_string_utf16_t* str) {
   DCHECK(str != nullptr);
-  if (str->dtor && str->str)
+  if (str->dtor && str->str) {
     str->dtor(str->str);
+  }
 
   str->str = nullptr;
   str->length = 0;
@@ -140,47 +145,57 @@
 
 CEF_EXPORT int cef_string_wide_cmp(const cef_string_wide_t* str1,
                                    const cef_string_wide_t* str2) {
-  if (str1->length == 0 && str2->length == 0)
+  if (str1->length == 0 && str2->length == 0) {
     return 0;
+  }
   int r = wcsncmp(str1->str, str2->str, std::min(str1->length, str2->length));
   if (r == 0) {
-    if (str1->length > str2->length)
+    if (str1->length > str2->length) {
       return 1;
-    else if (str1->length < str2->length)
+    } else if (str1->length < str2->length) {
       return -1;
+    }
   }
   return r;
 }
 
 CEF_EXPORT int cef_string_utf8_cmp(const cef_string_utf8_t* str1,
                                    const cef_string_utf8_t* str2) {
-  if (str1->length == 0 && str2->length == 0)
+  if (str1->length == 0 && str2->length == 0) {
     return 0;
+  }
   int r = strncmp(str1->str, str2->str, std::min(str1->length, str2->length));
   if (r == 0) {
-    if (str1->length > str2->length)
+    if (str1->length > str2->length) {
       return 1;
-    else if (str1->length < str2->length)
+    } else if (str1->length < str2->length) {
       return -1;
+    }
   }
   return r;
 }
 
 CEF_EXPORT int cef_string_utf16_cmp(const cef_string_utf16_t* str1,
                                     const cef_string_utf16_t* str2) {
-  if (str1->length == 0 && str2->length == 0)
+  if (str1->length == 0 && str2->length == 0) {
     return 0;
+  }
 #if defined(WCHAR_T_IS_UTF32)
-  int r = base::c16memcmp(str1->str, str2->str,
-                          std::min(str1->length, str2->length));
+  int r = std::char_traits<std::u16string::value_type>::compare(
+      reinterpret_cast<std::u16string::value_type*>(str1->str),
+      reinterpret_cast<std::u16string::value_type*>(str2->str),
+      std::min(str1->length, str2->length));
 #else
-  int r = wcsncmp(str1->str, str2->str, std::min(str1->length, str2->length));
+  int r = wcsncmp(reinterpret_cast<wchar_t*>(str1->str),
+                  reinterpret_cast<wchar_t*>(str2->str),
+                  std::min(str1->length, str2->length));
 #endif
   if (r == 0) {
-    if (str1->length > str2->length)
+    if (str1->length > str2->length) {
       return 1;
-    else if (str1->length < str2->length)
+    } else if (str1->length < str2->length) {
       return -1;
+    }
   }
   return r;
 }
@@ -190,8 +205,9 @@
                                        cef_string_utf8_t* output) {
   std::string str;
   bool ret = base::WideToUTF8(src, src_len, &str);
-  if (!cef_string_utf8_set(str.c_str(), str.length(), output, true))
+  if (!cef_string_utf8_set(str.c_str(), str.length(), output, true)) {
     return false;
+  }
   return ret;
 }
 
@@ -200,48 +216,57 @@
                                        cef_string_wide_t* output) {
   std::wstring str;
   bool ret = base::UTF8ToWide(src, src_len, &str);
-  if (!cef_string_wide_set(str.c_str(), str.length(), output, true))
+  if (!cef_string_wide_set(str.c_str(), str.length(), output, true)) {
     return false;
+  }
   return ret;
 }
 
 CEF_EXPORT int cef_string_wide_to_utf16(const wchar_t* src,
                                         size_t src_len,
                                         cef_string_utf16_t* output) {
-  base::string16 str;
+  std::u16string str;
   bool ret = base::WideToUTF16(src, src_len, &str);
-  if (!cef_string_utf16_set(str.c_str(), str.length(), output, true))
+  if (!cef_string_utf16_set(reinterpret_cast<const char16_t*>(str.c_str()),
+                            str.length(), output, true)) {
     return false;
+  }
   return ret;
 }
 
-CEF_EXPORT int cef_string_utf16_to_wide(const char16* src,
+CEF_EXPORT int cef_string_utf16_to_wide(const char16_t* src,
                                         size_t src_len,
                                         cef_string_wide_t* output) {
   std::wstring str;
-  bool ret = base::UTF16ToWide(src, src_len, &str);
-  if (!cef_string_wide_set(str.c_str(), str.length(), output, true))
+  bool ret = base::UTF16ToWide(
+      reinterpret_cast<const std::u16string::value_type*>(src), src_len, &str);
+  if (!cef_string_wide_set(str.c_str(), str.length(), output, true)) {
     return false;
+  }
   return ret;
 }
 
 CEF_EXPORT int cef_string_utf8_to_utf16(const char* src,
                                         size_t src_len,
                                         cef_string_utf16_t* output) {
-  base::string16 str;
+  std::u16string str;
   bool ret = base::UTF8ToUTF16(src, src_len, &str);
-  if (!cef_string_utf16_set(str.c_str(), str.length(), output, true))
+  if (!cef_string_utf16_set(reinterpret_cast<const char16_t*>(str.c_str()),
+                            str.length(), output, true)) {
     return false;
+  }
   return ret;
 }
 
-CEF_EXPORT int cef_string_utf16_to_utf8(const char16* src,
+CEF_EXPORT int cef_string_utf16_to_utf8(const char16_t* src,
                                         size_t src_len,
                                         cef_string_utf8_t* output) {
   std::string str;
-  bool ret = base::UTF16ToUTF8(src, src_len, &str);
-  if (!cef_string_utf8_set(str.c_str(), str.length(), output, true))
+  bool ret = base::UTF16ToUTF8(
+      reinterpret_cast<const std::u16string::value_type*>(src), src_len, &str);
+  if (!cef_string_utf8_set(str.c_str(), str.length(), output, true)) {
     return false;
+  }
   return ret;
 }
 
@@ -255,8 +280,9 @@
 CEF_EXPORT int cef_string_ascii_to_utf16(const char* src,
                                          size_t src_len,
                                          cef_string_utf16_t* output) {
-  const base::string16& str = base::ASCIIToUTF16(std::string(src, src_len));
-  return cef_string_utf16_set(str.c_str(), str.length(), output, true);
+  const std::u16string& str = base::ASCIIToUTF16(std::string(src, src_len));
+  return cef_string_utf16_set(reinterpret_cast<const char16_t*>(str.c_str()),
+                              str.length(), output, true);
 }
 
 CEF_EXPORT cef_string_userfree_wide_t cef_string_userfree_wide_alloc() {
@@ -293,16 +319,20 @@
   delete str;
 }
 
-CEF_EXPORT int cef_string_utf16_to_lower(const char16* src,
+CEF_EXPORT int cef_string_utf16_to_lower(const char16_t* src,
                                          size_t src_len,
                                          cef_string_utf16_t* output) {
-  const base::string16& str = base::i18n::ToLower(base::string16(src, src_len));
-  return cef_string_utf16_set(str.c_str(), str.length(), output, true);
+  const std::u16string& str = base::i18n::ToLower(std::u16string(
+      reinterpret_cast<const std::u16string::value_type*>(src), src_len));
+  return cef_string_utf16_set(reinterpret_cast<const char16_t*>(str.c_str()),
+                              str.length(), output, true);
 }
 
-CEF_EXPORT int cef_string_utf16_to_upper(const char16* src,
+CEF_EXPORT int cef_string_utf16_to_upper(const char16_t* src,
                                          size_t src_len,
                                          cef_string_utf16_t* output) {
-  const base::string16& str = base::i18n::ToUpper(base::string16(src, src_len));
-  return cef_string_utf16_set(str.c_str(), str.length(), output, true);
+  const std::u16string& str = base::i18n::ToUpper(std::u16string(
+      reinterpret_cast<const std::u16string::value_type*>(src), src_len));
+  return cef_string_utf16_set(reinterpret_cast<const char16_t*>(str.c_str()),
+                              str.length(), output, true);
 }
diff --git a/src/libcef/common/string_util.cc b/src/libcef/common/string_util.cc
new file mode 100644
index 0000000..bb18779
--- /dev/null
+++ b/src/libcef/common/string_util.cc
@@ -0,0 +1,72 @@
+// Copyright 2021 The Chromium Embedded Framework Authors. Portions copyright
+// 2011 The Chromium Authors. All rights reserved. Use of this source code is
+// governed by a BSD-style license that can be found in the LICENSE file.
+
+#include "libcef/common/string_util.h"
+
+#include "base/memory/read_only_shared_memory_region.h"
+#include "base/memory/ref_counted_memory.h"
+#include "third_party/blink/public/platform/web_string.h"
+
+namespace string_util {
+
+void GetCefString(const blink::WebString& source, CefString& cef_string) {
+#if defined(CEF_STRING_TYPE_UTF8)
+  cef_string.FromString(source.Utf8());
+#else
+  cef_string.FromString16(source.Utf16());
+#endif
+}
+
+void GetCefString(scoped_refptr<base::RefCountedMemory> source,
+                  CefString& cef_string) {
+  if (source && source->size() > 0U) {
+#if defined(CEF_STRING_TYPE_UTF8) || defined(CEF_STRING_TYPE_UTF16)
+    // Reference existing UTF8 or UTF16 data.
+    cef_string.FromString(source->front_as<CefString::char_type>(),
+                          source->size() / sizeof(CefString::char_type),
+                          /*copy=*/false);
+#else
+    // Must convert from UTF16.
+    cef_string.FromString16(
+        source->front_as<std::u16string::value_type>(),
+        source->size() / sizeof(std::u16string::value_type));
+#endif
+  } else {
+    cef_string.clear();
+  }
+}
+
+base::ReadOnlySharedMemoryRegion CreateSharedMemoryRegion(
+    const blink::WebString& source) {
+  base::ReadOnlySharedMemoryRegion region;
+
+  if (!source.IsEmpty()) {
+#if defined(CEF_STRING_TYPE_UTF8)
+    const std::string& string = source.Utf8();
+    const size_t byte_size = string.length();
+#else
+    const std::u16string& string = source.Utf16();
+    const size_t byte_size =
+        string.length() * sizeof(std::u16string::value_type);
+#endif
+    auto mapped_region = base::ReadOnlySharedMemoryRegion::Create(byte_size);
+    if (mapped_region.IsValid()) {
+      memcpy(mapped_region.mapping.memory(), string.data(), byte_size);
+      region = std::move(mapped_region.region);
+    }
+  }
+
+  return region;
+}
+
+void ExecuteWithScopedCefString(base::ReadOnlySharedMemoryRegion region,
+                                ScopedCefStringCallback callback) {
+  auto shared_buf =
+      base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(region);
+  CefString str;
+  GetCefString(shared_buf, str);
+  std::move(callback).Run(str);
+}
+
+}  // namespace string_util
\ No newline at end of file
diff --git a/src/libcef/common/string_util.h b/src/libcef/common/string_util.h
new file mode 100644
index 0000000..f972765
--- /dev/null
+++ b/src/libcef/common/string_util.h
@@ -0,0 +1,44 @@
+// Copyright 2021 The Chromium Embedded Framework Authors. Portions copyright
+// 2011 The Chromium Authors. All rights reserved. Use of this source code is
+// governed by a BSD-style license that can be found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_COMMON_STRING_UTIL_H_
+#define CEF_LIBCEF_COMMON_STRING_UTIL_H_
+#pragma once
+
+#include "include/cef_base.h"
+
+#include "base/functional/callback.h"
+#include "base/memory/scoped_refptr.h"
+
+namespace base {
+class ReadOnlySharedMemoryRegion;
+class RefCountedMemory;
+}  // namespace base
+
+namespace blink {
+class WebString;
+}
+
+namespace string_util {
+
+// Convert |source| to |cef_string|, avoiding UTF conversions if possible.
+void GetCefString(const blink::WebString& source, CefString& cef_string);
+void GetCefString(scoped_refptr<base::RefCountedMemory> source,
+                  CefString& cef_string);
+
+// Read |source| into shared memory, avoiding UTF conversions if possible.
+// Use ExecuteWithScopedCefString() to retrieve the value on the receiving end
+// with zero UTF conversions and zero copies if possible.
+base::ReadOnlySharedMemoryRegion CreateSharedMemoryRegion(
+    const blink::WebString& source);
+
+using ScopedCefStringCallback = base::OnceCallback<void(const CefString&)>;
+
+// Helper for executing |callback| with |region| as a scoped CefString.
+void ExecuteWithScopedCefString(base::ReadOnlySharedMemoryRegion region,
+                                ScopedCefStringCallback callback);
+
+}  // namespace string_util
+
+#endif  // CEF_LIBCEF_COMMON_STRING_UTIL_H_
diff --git a/src/libcef/common/task_impl.cc b/src/libcef/common/task_impl.cc
index e03744c..a709c4b 100644
--- a/src/libcef/common/task_impl.cc
+++ b/src/libcef/common/task_impl.cc
@@ -5,14 +5,19 @@
 #include "include/cef_task.h"
 #include "libcef/common/task_runner_impl.h"
 
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #include "base/location.h"
+#include "base/logging.h"
+#include "base/time/time.h"
 
 bool CefCurrentlyOn(CefThreadId threadId) {
   scoped_refptr<base::SequencedTaskRunner> task_runner =
       CefTaskRunnerImpl::GetTaskRunner(threadId);
-  if (task_runner.get())
+  if (task_runner.get()) {
     return task_runner->RunsTasksInCurrentSequence();
+  }
+
+  LOG(WARNING) << "No task runner for threadId " << threadId;
   return false;
 }
 
@@ -21,20 +26,24 @@
       CefTaskRunnerImpl::GetTaskRunner(threadId);
   if (task_runner.get()) {
     return task_runner->PostTask(FROM_HERE,
-                                 base::Bind(&CefTask::Execute, task.get()));
+                                 base::BindOnce(&CefTask::Execute, task.get()));
   }
+
+  LOG(WARNING) << "No task runner for threadId " << threadId;
   return false;
 }
 
 bool CefPostDelayedTask(CefThreadId threadId,
                         CefRefPtr<CefTask> task,
-                        int64 delay_ms) {
+                        int64_t delay_ms) {
   scoped_refptr<base::SequencedTaskRunner> task_runner =
       CefTaskRunnerImpl::GetTaskRunner(threadId);
   if (task_runner.get()) {
     return task_runner->PostDelayedTask(
-        FROM_HERE, base::Bind(&CefTask::Execute, task.get()),
-        base::TimeDelta::FromMilliseconds(delay_ms));
+        FROM_HERE, base::BindOnce(&CefTask::Execute, task.get()),
+        base::Milliseconds(delay_ms));
   }
+
+  LOG(WARNING) << "No task runner for threadId " << threadId;
   return false;
 }
diff --git a/src/libcef/common/task_runner_impl.cc b/src/libcef/common/task_runner_impl.cc
index 1487289..46f2744 100644
--- a/src/libcef/common/task_runner_impl.cc
+++ b/src/libcef/common/task_runner_impl.cc
@@ -3,15 +3,15 @@
 // can be found in the LICENSE file.
 
 #include "libcef/common/task_runner_impl.h"
-#include "libcef/browser/content_browser_client.h"
-#include "libcef/common/content_client.h"
-#include "libcef/renderer/content_renderer_client.h"
 
-#include "base/bind.h"
+#include "libcef/common/task_runner_manager.h"
+
+#include "base/functional/bind.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/task/single_thread_task_runner.h"
+#include "base/task/thread_pool.h"
+#include "base/time/time.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/child_process_launcher_utils.h"
@@ -24,8 +24,9 @@
 CefRefPtr<CefTaskRunner> CefTaskRunner::GetForCurrentThread() {
   scoped_refptr<base::SingleThreadTaskRunner> task_runner =
       CefTaskRunnerImpl::GetCurrentTaskRunner();
-  if (task_runner.get())
+  if (task_runner.get()) {
     return new CefTaskRunnerImpl(task_runner);
+  }
   return nullptr;
 }
 
@@ -33,8 +34,9 @@
 CefRefPtr<CefTaskRunner> CefTaskRunner::GetForThread(CefThreadId threadId) {
   scoped_refptr<base::SingleThreadTaskRunner> task_runner =
       CefTaskRunnerImpl::GetTaskRunner(threadId);
-  if (task_runner.get())
+  if (task_runner.get()) {
     return new CefTaskRunnerImpl(task_runner);
+  }
 
   LOG(WARNING) << "Invalid thread id " << threadId;
   return nullptr;
@@ -51,81 +53,69 @@
 // static
 scoped_refptr<base::SingleThreadTaskRunner> CefTaskRunnerImpl::GetTaskRunner(
     CefThreadId threadId) {
-  // Render process.
-  if (threadId == TID_RENDERER) {
-    CefContentRendererClient* client = CefContentRendererClient::Get();
-    if (client)
-      return client->render_task_runner();
+  auto* manager = CefTaskRunnerManager::Get();
+  if (!manager) {
     return nullptr;
   }
 
-  // Browser process.
-  CefContentBrowserClient* client = CefContentBrowserClient::Get();
-  if (!client)
-    return nullptr;
-
-  int id = -1;
   switch (threadId) {
     case TID_UI:
-      id = BrowserThread::UI;
+      if (BrowserThread::IsThreadInitialized(BrowserThread::UI)) {
+        return content::GetUIThreadTaskRunner({});
+      }
       break;
     case TID_FILE_BACKGROUND:
-      return client->background_task_runner();
+      return manager->GetBackgroundTaskRunner();
     case TID_FILE_USER_VISIBLE:
-      return client->user_visible_task_runner();
+      return manager->GetUserVisibleTaskRunner();
     case TID_FILE_USER_BLOCKING:
-      return client->user_blocking_task_runner();
+      return manager->GetUserBlockingTaskRunner();
     case TID_PROCESS_LAUNCHER:
       return content::GetProcessLauncherTaskRunner();
     case TID_IO:
-      id = BrowserThread::IO;
+      if (BrowserThread::IsThreadInitialized(BrowserThread::IO)) {
+        return content::GetIOThreadTaskRunner({});
+      }
       break;
+    case TID_RENDERER:
+      return manager->GetRenderTaskRunner();
     default:
       break;
   };
 
-  if (id >= 0 &&
-      BrowserThread::IsThreadInitialized(static_cast<BrowserThread::ID>(id))) {
-    // Specify USER_BLOCKING so that BrowserTaskExecutor::GetTaskRunner always
-    // gives us the same TaskRunner object.
-    return base::CreateSingleThreadTaskRunner(
-        {static_cast<BrowserThread::ID>(id),
-         base::TaskPriority::USER_BLOCKING});
-  }
-
   return nullptr;
 }
 
 // static
 scoped_refptr<base::SingleThreadTaskRunner>
 CefTaskRunnerImpl::GetCurrentTaskRunner() {
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner;
+  auto* manager = CefTaskRunnerManager::Get();
+  if (!manager) {
+    return nullptr;
+  }
 
   // For named browser process threads return the same TaskRunner as
   // GetTaskRunner(). Otherwise BelongsToThread() will return incorrect results.
   BrowserThread::ID current_id;
   if (BrowserThread::GetCurrentThreadIdentifier(&current_id) &&
       BrowserThread::IsThreadInitialized(current_id)) {
-    // Specify USER_BLOCKING so that BrowserTaskExecutor::GetTaskRunner always
-    // gives us the same TaskRunner object.
-    task_runner = base::CreateSingleThreadTaskRunner(
-        {current_id, base::TaskPriority::USER_BLOCKING});
+    if (current_id == BrowserThread::UI) {
+      return content::GetUIThreadTaskRunner({});
+    } else if (current_id == BrowserThread::IO) {
+      return content::GetIOThreadTaskRunner({});
+    } else {
+      DCHECK(false);
+    }
   }
 
-  if (!task_runner.get()) {
-    // Check for a MessageLoopProxy. This covers all of the named browser and
-    // render process threads, plus a few extra.
-    task_runner = base::ThreadTaskRunnerHandle::Get();
+  // Check for a MessageLoopProxy. This covers all of the named browser and
+  // render process threads, plus a few extra.
+  if (auto task_runner = base::SingleThreadTaskRunner::GetCurrentDefault()) {
+    return task_runner;
   }
 
-  if (!task_runner.get()) {
-    // Check for a WebWorker thread.
-    CefContentRendererClient* client = CefContentRendererClient::Get();
-    if (client)
-      task_runner = client->GetCurrentTaskRunner();
-  }
-
-  return task_runner;
+  // Check for a WebWorker thread.
+  return manager->GetWebWorkerTaskRunner();
 }
 
 bool CefTaskRunnerImpl::IsSame(CefRefPtr<CefTaskRunner> that) {
@@ -145,12 +135,12 @@
 
 bool CefTaskRunnerImpl::PostTask(CefRefPtr<CefTask> task) {
   return task_runner_->PostTask(FROM_HERE,
-                                base::Bind(&CefTask::Execute, task.get()));
+                                base::BindOnce(&CefTask::Execute, task.get()));
 }
 
 bool CefTaskRunnerImpl::PostDelayedTask(CefRefPtr<CefTask> task,
-                                        int64 delay_ms) {
+                                        int64_t delay_ms) {
   return task_runner_->PostDelayedTask(
-      FROM_HERE, base::Bind(&CefTask::Execute, task.get()),
-      base::TimeDelta::FromMilliseconds(delay_ms));
+      FROM_HERE, base::BindOnce(&CefTask::Execute, task.get()),
+      base::Milliseconds(delay_ms));
 }
diff --git a/src/libcef/common/task_runner_impl.h b/src/libcef/common/task_runner_impl.h
index 8991718..8afbfab 100644
--- a/src/libcef/common/task_runner_impl.h
+++ b/src/libcef/common/task_runner_impl.h
@@ -8,13 +8,16 @@
 
 #include "include/cef_task.h"
 
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
 
 class CefTaskRunnerImpl : public CefTaskRunner {
  public:
   explicit CefTaskRunnerImpl(
       scoped_refptr<base::SingleThreadTaskRunner> task_runner);
 
+  CefTaskRunnerImpl(const CefTaskRunnerImpl&) = delete;
+  CefTaskRunnerImpl& operator=(const CefTaskRunnerImpl&) = delete;
+
   // Returns the task runner associated with |threadId|.
   static scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(
       CefThreadId threadId);
@@ -26,13 +29,12 @@
   bool BelongsToCurrentThread() override;
   bool BelongsToThread(CefThreadId threadId) override;
   bool PostTask(CefRefPtr<CefTask> task) override;
-  bool PostDelayedTask(CefRefPtr<CefTask> task, int64 delay_ms) override;
+  bool PostDelayedTask(CefRefPtr<CefTask> task, int64_t delay_ms) override;
 
  private:
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 
   IMPLEMENT_REFCOUNTING(CefTaskRunnerImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefTaskRunnerImpl);
 };
 
 #endif  // CEF_LIBCEF_COMMON_TASK_RUNNER_IMPL_H_
diff --git a/src/libcef/common/task_runner_manager.cc b/src/libcef/common/task_runner_manager.cc
new file mode 100644
index 0000000..2318e58
--- /dev/null
+++ b/src/libcef/common/task_runner_manager.cc
@@ -0,0 +1,28 @@
+// Copyright 2020 The Chromium Embedded Framework 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 "libcef/common/task_runner_manager.h"
+
+#include "base/logging.h"
+
+namespace {
+
+CefTaskRunnerManager* g_manager = nullptr;
+
+}  // namespace
+
+// static
+CefTaskRunnerManager* CefTaskRunnerManager::Get() {
+  return g_manager;
+}
+
+CefTaskRunnerManager::CefTaskRunnerManager() {
+  // Only a single instance should exist.
+  DCHECK(!g_manager);
+  g_manager = this;
+}
+
+CefTaskRunnerManager::~CefTaskRunnerManager() {
+  g_manager = nullptr;
+}
diff --git a/src/libcef/common/task_runner_manager.h b/src/libcef/common/task_runner_manager.h
new file mode 100644
index 0000000..4f0ea13
--- /dev/null
+++ b/src/libcef/common/task_runner_manager.h
@@ -0,0 +1,37 @@
+// Copyright 2020 The Chromium Embedded Framework 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 CEF_LIBCEF_COMMON_TASK_RUNNER_MANAGER_H_
+#define CEF_LIBCEF_COMMON_TASK_RUNNER_MANAGER_H_
+#pragma once
+
+#include "base/task/single_thread_task_runner.h"
+
+// Exposes global sequenced task runners in the main and render processes.
+// Prefer using base::ThreadPool for tasks that do not need to be globally
+// sequenced and CefTaskRunner for retrieving named CefThreadId runners.
+class CefTaskRunnerManager {
+ public:
+  // Returns the singleton instance that is scoped to CEF lifespan.
+  static CefTaskRunnerManager* Get();
+
+  // Available in the main process:
+  virtual scoped_refptr<base::SingleThreadTaskRunner>
+  GetBackgroundTaskRunner() = 0;
+  virtual scoped_refptr<base::SingleThreadTaskRunner>
+  GetUserVisibleTaskRunner() = 0;
+  virtual scoped_refptr<base::SingleThreadTaskRunner>
+  GetUserBlockingTaskRunner() = 0;
+
+  // Available in the render process:
+  virtual scoped_refptr<base::SingleThreadTaskRunner> GetRenderTaskRunner() = 0;
+  virtual scoped_refptr<base::SingleThreadTaskRunner>
+  GetWebWorkerTaskRunner() = 0;
+
+ protected:
+  CefTaskRunnerManager();
+  virtual ~CefTaskRunnerManager();
+};
+
+#endif  // CEF_LIBCEF_COMMON_TASK_RUNNER_MANAGER_H_
diff --git a/src/libcef/common/test/translator_test_impl.cc b/src/libcef/common/test/translator_test_impl.cc
index 1962b50..93a8d5e 100644
--- a/src/libcef/common/test/translator_test_impl.cc
+++ b/src/libcef/common/test/translator_test_impl.cc
@@ -9,6 +9,11 @@
  public:
   explicit CefTranslatorTestRefPtrLibraryImpl(int value) : value_(value) {}
 
+  CefTranslatorTestRefPtrLibraryImpl(
+      const CefTranslatorTestRefPtrLibraryImpl&) = delete;
+  CefTranslatorTestRefPtrLibraryImpl& operator=(
+      const CefTranslatorTestRefPtrLibraryImpl&) = delete;
+
   int GetValue() override { return value_; }
 
   void SetValue(int value) override { value_ = value; }
@@ -17,7 +22,6 @@
   int value_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(CefTranslatorTestRefPtrLibraryImpl);
   IMPLEMENT_REFCOUNTING(CefTranslatorTestRefPtrLibraryImpl);
 };
 
@@ -33,6 +37,11 @@
   CefTranslatorTestRefPtrLibraryChildImpl(int value, int other_value)
       : value_(value), other_value_(other_value) {}
 
+  CefTranslatorTestRefPtrLibraryChildImpl(
+      const CefTranslatorTestRefPtrLibraryChildImpl&) = delete;
+  CefTranslatorTestRefPtrLibraryChildImpl& operator=(
+      const CefTranslatorTestRefPtrLibraryChildImpl&) = delete;
+
   int GetValue() override { return value_; }
 
   void SetValue(int value) override { value_ = value; }
@@ -46,7 +55,6 @@
   int other_value_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(CefTranslatorTestRefPtrLibraryChildImpl);
   IMPLEMENT_REFCOUNTING(CefTranslatorTestRefPtrLibraryChildImpl);
 };
 
@@ -66,6 +74,11 @@
         other_value_(other_value),
         other_other_value_(other_other_value) {}
 
+  CefTranslatorTestRefPtrLibraryChildChildImpl(
+      const CefTranslatorTestRefPtrLibraryChildChildImpl&) = delete;
+  CefTranslatorTestRefPtrLibraryChildChildImpl& operator=(
+      const CefTranslatorTestRefPtrLibraryChildChildImpl&) = delete;
+
   int GetValue() override { return value_; }
 
   void SetValue(int value) override { value_ = value; }
@@ -84,7 +97,6 @@
   int other_other_value_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(CefTranslatorTestRefPtrLibraryChildChildImpl);
   IMPLEMENT_REFCOUNTING(CefTranslatorTestRefPtrLibraryChildChildImpl);
 };
 
@@ -102,15 +114,17 @@
  public:
   explicit CefTranslatorTestScopedLibraryImpl(int value) : value_(value) {}
 
+  CefTranslatorTestScopedLibraryImpl(
+      const CefTranslatorTestScopedLibraryImpl&) = delete;
+  CefTranslatorTestScopedLibraryImpl& operator=(
+      const CefTranslatorTestScopedLibraryImpl&) = delete;
+
   int GetValue() override { return value_; }
 
   void SetValue(int value) override { value_ = value; }
 
  protected:
   int value_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefTranslatorTestScopedLibraryImpl);
 };
 
 // static
@@ -126,6 +140,11 @@
   CefTranslatorTestScopedLibraryChildImpl(int value, int other_value)
       : value_(value), other_value_(other_value) {}
 
+  CefTranslatorTestScopedLibraryChildImpl(
+      const CefTranslatorTestScopedLibraryChildImpl&) = delete;
+  CefTranslatorTestScopedLibraryChildImpl& operator=(
+      const CefTranslatorTestScopedLibraryChildImpl&) = delete;
+
   int GetValue() override { return value_; }
 
   void SetValue(int value) override { value_ = value; }
@@ -137,9 +156,6 @@
  protected:
   int value_;
   int other_value_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefTranslatorTestScopedLibraryChildImpl);
 };
 
 // static
@@ -159,6 +175,11 @@
         other_value_(other_value),
         other_other_value_(other_other_value) {}
 
+  CefTranslatorTestScopedLibraryChildChildImpl(
+      const CefTranslatorTestScopedLibraryChildChildImpl&) = delete;
+  CefTranslatorTestScopedLibraryChildChildImpl& operator=(
+      const CefTranslatorTestScopedLibraryChildChildImpl&) = delete;
+
   int GetValue() override { return value_; }
 
   void SetValue(int value) override { value_ = value; }
@@ -175,9 +196,6 @@
   int value_;
   int other_value_;
   int other_other_value_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefTranslatorTestScopedLibraryChildChildImpl);
 };
 
 // static
@@ -192,7 +210,10 @@
 
 class CefTranslatorTestImpl : public CefTranslatorTest {
  public:
-  CefTranslatorTestImpl() {}
+  CefTranslatorTestImpl() = default;
+
+  CefTranslatorTestImpl(const CefTranslatorTestImpl&) = delete;
+  CefTranslatorTestImpl& operator=(const CefTranslatorTestImpl&) = delete;
 
   // PRIMITIVE VALUES
 
@@ -223,14 +244,16 @@
   // PRIMITIVE LIST VALUES
 
   bool SetIntList(const std::vector<int>& val) override {
-    if (val.size() != 2U)
+    if (val.size() != 2U) {
       return false;
+    }
     return val[0] == TEST_INT_VAL && val[1] == TEST_INT_VAL2;
   }
 
   bool GetIntListByRef(IntList& val) override {
-    if (val.size() != GetIntListSize())
+    if (val.size() != GetIntListSize()) {
       return false;
+    }
     val.clear();
     val.push_back(TEST_INT_VAL);
     val.push_back(TEST_INT_VAL2);
@@ -252,15 +275,17 @@
   // STRING LIST VALUES
 
   bool SetStringList(const std::vector<CefString>& val) override {
-    if (val.size() != 3U)
+    if (val.size() != 3U) {
       return false;
+    }
     return val[0] == TEST_STRING_VAL && val[1] == TEST_STRING_VAL2 &&
            val[2] == TEST_STRING_VAL3;
   }
 
   bool GetStringListByRef(StringList& val) override {
-    if (val.size() != 0U)
+    if (val.size() != 0U) {
       return false;
+    }
     val.push_back(TEST_STRING_VAL);
     val.push_back(TEST_STRING_VAL2);
     val.push_back(TEST_STRING_VAL3);
@@ -270,26 +295,31 @@
   // STRING MAP VALUES
 
   bool SetStringMap(const StringMap& val) override {
-    if (val.size() != 3U)
+    if (val.size() != 3U) {
       return false;
+    }
 
     StringMap::const_iterator it;
 
     it = val.find(TEST_STRING_KEY);
-    if (it == val.end() || it->second != TEST_STRING_VAL)
+    if (it == val.end() || it->second != TEST_STRING_VAL) {
       return false;
+    }
     it = val.find(TEST_STRING_KEY2);
-    if (it == val.end() || it->second != TEST_STRING_VAL2)
+    if (it == val.end() || it->second != TEST_STRING_VAL2) {
       return false;
+    }
     it = val.find(TEST_STRING_KEY3);
-    if (it == val.end() || it->second != TEST_STRING_VAL3)
+    if (it == val.end() || it->second != TEST_STRING_VAL3) {
       return false;
+    }
     return true;
   }
 
   bool GetStringMapByRef(std::map<CefString, CefString>& val) override {
-    if (val.size() != 0U)
+    if (val.size() != 0U) {
       return false;
+    }
 
     val.insert(std::make_pair(TEST_STRING_KEY, TEST_STRING_VAL));
     val.insert(std::make_pair(TEST_STRING_KEY2, TEST_STRING_VAL2));
@@ -301,26 +331,31 @@
 
   bool SetStringMultimap(
       const std::multimap<CefString, CefString>& val) override {
-    if (val.size() != 3U)
+    if (val.size() != 3U) {
       return false;
+    }
 
     StringMultimap::const_iterator it;
 
     it = val.find(TEST_STRING_KEY);
-    if (it == val.end() || it->second != TEST_STRING_VAL)
+    if (it == val.end() || it->second != TEST_STRING_VAL) {
       return false;
+    }
     it = val.find(TEST_STRING_KEY2);
-    if (it == val.end() || it->second != TEST_STRING_VAL2)
+    if (it == val.end() || it->second != TEST_STRING_VAL2) {
       return false;
+    }
     it = val.find(TEST_STRING_KEY3);
-    if (it == val.end() || it->second != TEST_STRING_VAL3)
+    if (it == val.end() || it->second != TEST_STRING_VAL3) {
       return false;
+    }
     return true;
   }
 
   bool GetStringMultimapByRef(StringMultimap& val) override {
-    if (val.size() != 0U)
+    if (val.size() != 0U) {
       return false;
+    }
 
     val.insert(std::make_pair(TEST_STRING_KEY, TEST_STRING_VAL));
     val.insert(std::make_pair(TEST_STRING_KEY2, TEST_STRING_VAL2));
@@ -343,15 +378,17 @@
   // STRUCT LIST VALUES
 
   bool SetPointList(const std::vector<CefPoint>& val) override {
-    if (val.size() != 2U)
+    if (val.size() != 2U) {
       return false;
+    }
     return val[0].x == TEST_X_VAL && val[0].y == TEST_Y_VAL &&
            val[1].x == TEST_X_VAL2 && val[1].y == TEST_Y_VAL2;
   }
 
   bool GetPointListByRef(PointList& val) override {
-    if (val.size() != GetPointListSize())
+    if (val.size() != GetPointListSize()) {
       return false;
+    }
     val.clear();
     val.push_back(CefPoint(TEST_X_VAL, TEST_Y_VAL));
     val.push_back(CefPoint(TEST_X_VAL2, TEST_Y_VAL2));
@@ -392,16 +429,18 @@
       const std::vector<CefRefPtr<CefTranslatorTestRefPtrLibrary>>& val,
       int val1,
       int val2) override {
-    if (val.size() != 2U)
+    if (val.size() != 2U) {
       return false;
+    }
     return val[0]->GetValue() == val1 && val[1]->GetValue() == val2;
   }
 
   bool GetRefPtrLibraryListByRef(RefPtrLibraryList& val,
                                  int val1,
                                  int val2) override {
-    if (val.size() != GetRefPtrLibraryListSize())
+    if (val.size() != GetRefPtrLibraryListSize()) {
       return false;
+    }
     val.clear();
     val.push_back(new CefTranslatorTestRefPtrLibraryChildImpl(val1, 0));
     val.push_back(new CefTranslatorTestRefPtrLibraryImpl(val2));
@@ -437,8 +476,9 @@
       const std::vector<CefRefPtr<CefTranslatorTestRefPtrClient>>& val,
       int val1,
       int val2) override {
-    if (val.size() != 2U)
+    if (val.size() != 2U) {
       return false;
+    }
     return val[0]->GetValue() == val1 && val[1]->GetValue() == val2;
   }
 
@@ -446,8 +486,9 @@
       RefPtrClientList& val,
       CefRefPtr<CefTranslatorTestRefPtrClient> val1,
       CefRefPtr<CefTranslatorTestRefPtrClient> val2) override {
-    if (val.size() != GetRefPtrClientListSize())
+    if (val.size() != GetRefPtrClientListSize()) {
       return false;
+    }
     val.clear();
     val.push_back(val1);
     val.push_back(val2);
@@ -521,8 +562,9 @@
       const std::vector<CefRawPtr<CefTranslatorTestScopedLibrary>>& val,
       int val1,
       int val2) override {
-    if (val.size() != 2U)
+    if (val.size() != 2U) {
       return false;
+    }
     return val[0]->GetValue() == val1 && val[1]->GetValue() == val2;
   }
 
@@ -543,14 +585,14 @@
       const std::vector<CefRawPtr<CefTranslatorTestScopedClient>>& val,
       int val1,
       int val2) override {
-    if (val.size() != 2U)
+    if (val.size() != 2U) {
       return false;
+    }
     return val[0]->GetValue() == val1 && val[1]->GetValue() == val2;
   }
 
  private:
   IMPLEMENT_REFCOUNTING(CefTranslatorTestImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefTranslatorTestImpl);
 };
 
 // static
diff --git a/src/libcef/common/thread_impl.cc b/src/libcef/common/thread_impl.cc
index adcce19..b08a647 100644
--- a/src/libcef/common/thread_impl.cc
+++ b/src/libcef/common/thread_impl.cc
@@ -6,7 +6,7 @@
 
 #include "libcef/common/task_runner_impl.h"
 
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #include "base/threading/thread_restrictions.h"
 
 namespace {
@@ -29,7 +29,7 @@
     bool stoppable,
     cef_com_init_mode_t com_init_mode) {
   if (!CefTaskRunnerImpl::GetCurrentTaskRunner()) {
-    NOTREACHED() << "called on invalid thread";
+    DCHECK(false) << "called on invalid thread";
     return nullptr;
   }
 
@@ -49,7 +49,7 @@
       // Delete |thread_| on the correct thread.
       owner_task_runner_->PostTask(
           FROM_HERE,
-          base::Bind(StopAndDestroy, base::Unretained(thread_.release())));
+          base::BindOnce(StopAndDestroy, base::Unretained(thread_.release())));
     } else {
       StopAndDestroy(thread_.release());
     }
@@ -63,8 +63,9 @@
                            cef_com_init_mode_t com_init_mode) {
   owner_task_runner_ = CefTaskRunnerImpl::GetCurrentTaskRunner();
   DCHECK(owner_task_runner_);
-  if (!owner_task_runner_)
+  if (!owner_task_runner_) {
     return false;
+  }
 
   thread_.reset(new base::Thread(display_name));
 
@@ -72,13 +73,13 @@
 
   switch (priority) {
     case TP_BACKGROUND:
-      options.priority = base::ThreadPriority::BACKGROUND;
+      options.thread_type = base::ThreadType::kBackground;
       break;
     case TP_DISPLAY:
-      options.priority = base::ThreadPriority::DISPLAY;
+      options.thread_type = base::ThreadType::kDisplayCritical;
       break;
     case TP_REALTIME_AUDIO:
-      options.priority = base::ThreadPriority::REALTIME_AUDIO;
+      options.thread_type = base::ThreadType::kRealtimeAudio;
       break;
     default:
       break;
@@ -97,15 +98,16 @@
 
   options.joinable = stoppable;
 
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   if (com_init_mode != COM_INIT_MODE_NONE) {
-    if (com_init_mode == COM_INIT_MODE_STA)
+    if (com_init_mode == COM_INIT_MODE_STA) {
       options.message_pump_type = base::MessagePumpType::UI;
+    }
     thread_->init_com_with_mta(com_init_mode == COM_INIT_MODE_MTA);
   }
 #endif
 
-  if (!thread_->StartWithOptions(options)) {
+  if (!thread_->StartWithOptions(std::move(options))) {
     thread_.reset();
     return false;
   }
@@ -124,22 +126,25 @@
 }
 
 void CefThreadImpl::Stop() {
-  if (!owner_task_runner_)
+  if (!owner_task_runner_) {
     return;
+  }
   if (!owner_task_runner_->RunsTasksInCurrentSequence()) {
-    NOTREACHED() << "called on invalid thread";
+    DCHECK(false) << "called on invalid thread";
     return;
   }
 
-  if (thread_)
+  if (thread_) {
     StopAndDestroy(thread_.release());
+  }
 }
 
 bool CefThreadImpl::IsRunning() {
-  if (!owner_task_runner_)
+  if (!owner_task_runner_) {
     return false;
+  }
   if (!owner_task_runner_->RunsTasksInCurrentSequence()) {
-    NOTREACHED() << "called on invalid thread";
+    DCHECK(false) << "called on invalid thread";
     return false;
   }
 
diff --git a/src/libcef/common/thread_impl.h b/src/libcef/common/thread_impl.h
index 34bfc9e..49e0380 100644
--- a/src/libcef/common/thread_impl.h
+++ b/src/libcef/common/thread_impl.h
@@ -13,6 +13,10 @@
 class CefThreadImpl : public CefThread {
  public:
   CefThreadImpl();
+
+  CefThreadImpl(const CefThreadImpl&) = delete;
+  CefThreadImpl& operator=(const CefThreadImpl&) = delete;
+
   ~CefThreadImpl();
 
   bool Create(const CefString& display_name,
@@ -36,7 +40,6 @@
   scoped_refptr<base::SequencedTaskRunner> owner_task_runner_;
 
   IMPLEMENT_REFCOUNTING(CefThreadImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefThreadImpl);
 };
 
 #endif  // CEF_LIBCEF_COMMON_THREAD_IMPL_H_
diff --git a/src/libcef/common/time_impl.cc b/src/libcef/common/time_impl.cc
index 67f3163..b2981ac 100644
--- a/src/libcef/common/time_impl.cc
+++ b/src/libcef/common/time_impl.cc
@@ -2,9 +2,27 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
+#include "include/internal/cef_time_wrappers.h"
+#include "include/internal/cef_types_wrappers.h"
 #include "libcef/common/time_util.h"
 
-#include "base/macros.h"
+#include <limits>
+#include <tuple>
+
+#if BUILDFLAG(IS_WIN)
+namespace {
+
+// From MSDN, FILETIME "Contains a 64-bit value representing the number of
+// 100-nanosecond intervals since January 1, 1601 (UTC)." This value must
+// be less than 0x8000000000000000. Otherwise, the function
+// FileTimeToSystemTime fails.
+// From base/time/time_win.cc:
+bool CanConvertToFileTime(int64_t us) {
+  return us >= 0 && us <= (std::numeric_limits<int64_t>::max() / 10);
+}
+
+}  // namespace
+#endif  // BUILDFLAG(IS_WIN)
 
 void cef_time_to_basetime(const cef_time_t& cef_time, base::Time& time) {
   base::Time::Exploded exploded;
@@ -16,18 +34,15 @@
   exploded.minute = cef_time.minute;
   exploded.second = cef_time.second;
   exploded.millisecond = cef_time.millisecond;
-  ignore_result(base::Time::FromUTCExploded(exploded, &time));
+  std::ignore = base::Time::FromUTCExploded(exploded, &time);
 }
 
 void cef_time_from_basetime(const base::Time& time, cef_time_t& cef_time) {
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
   int64_t t = time.ToDeltaSinceWindowsEpoch().InMicroseconds();
-  // From MSDN, FILETIME "Contains a 64-bit value representing the number of
-  // 100-nanosecond intervals since January 1, 1601 (UTC)." This value must
-  // be less than 0x8000000000000000. Otherwise, the function
-  // FileTimeToSystemTime fails.
-  if (t < 0 || static_cast<uint64_t>(t * 10) >= 0x8000000000000000)
+  if (!CanConvertToFileTime(t)) {
     return;
+  }
 #endif
 
   base::Time::Exploded exploded;
@@ -43,8 +58,9 @@
 }
 
 CEF_EXPORT int cef_time_to_timet(const cef_time_t* cef_time, time_t* time) {
-  if (!cef_time || !time)
+  if (!cef_time || !time) {
     return 0;
+  }
 
   base::Time base_time;
   cef_time_to_basetime(*cef_time, base_time);
@@ -53,8 +69,9 @@
 }
 
 CEF_EXPORT int cef_time_from_timet(time_t time, cef_time_t* cef_time) {
-  if (!cef_time)
+  if (!cef_time) {
     return 0;
+  }
 
   base::Time base_time = base::Time::FromTimeT(time);
   cef_time_from_basetime(base_time, *cef_time);
@@ -62,8 +79,9 @@
 }
 
 CEF_EXPORT int cef_time_to_doublet(const cef_time_t* cef_time, double* time) {
-  if (!cef_time || !time)
+  if (!cef_time || !time) {
     return 0;
+  }
 
   base::Time base_time;
   cef_time_to_basetime(*cef_time, base_time);
@@ -72,8 +90,9 @@
 }
 
 CEF_EXPORT int cef_time_from_doublet(double time, cef_time_t* cef_time) {
-  if (!cef_time)
+  if (!cef_time) {
     return 0;
+  }
 
   base::Time base_time = base::Time::FromDoubleT(time);
   cef_time_from_basetime(base_time, *cef_time);
@@ -81,19 +100,25 @@
 }
 
 CEF_EXPORT int cef_time_now(cef_time_t* cef_time) {
-  if (!cef_time)
+  if (!cef_time) {
     return 0;
+  }
 
   base::Time base_time = base::Time::Now();
   cef_time_from_basetime(base_time, *cef_time);
   return 1;
 }
 
+CEF_EXPORT cef_basetime_t cef_basetime_now() {
+  return CefBaseTime(base::Time::Now());
+}
+
 CEF_EXPORT int cef_time_delta(const cef_time_t* cef_time1,
                               const cef_time_t* cef_time2,
                               long long* delta) {
-  if (!cef_time1 || !cef_time2 || !delta)
+  if (!cef_time1 || !cef_time2 || !delta) {
     return 0;
+  }
 
   base::Time base_time1, base_time2;
   cef_time_to_basetime(*cef_time1, base_time1);
@@ -103,3 +128,45 @@
   *delta = time_delta.InMilliseconds();
   return 1;
 }
+
+CEF_EXPORT int cef_time_to_basetime(const cef_time_t* from,
+                                    cef_basetime_t* to) {
+  if (!from || !to) {
+    return 0;
+  }
+
+  base::Time::Exploded exploded;
+  exploded.year = from->year;
+  exploded.month = from->month;
+  exploded.day_of_week = from->day_of_week;
+  exploded.day_of_month = from->day_of_month;
+  exploded.hour = from->hour;
+  exploded.minute = from->minute;
+  exploded.second = from->second;
+  exploded.millisecond = from->millisecond;
+  base::Time time;
+  bool result = base::Time::FromUTCExploded(exploded, &time);
+  *to = CefBaseTime(time);
+  return result ? 1 : 0;
+}
+
+CEF_EXPORT int cef_time_from_basetime(const cef_basetime_t from,
+                                      cef_time_t* to) {
+  if (!to) {
+    return 0;
+  }
+
+  base::Time time = CefBaseTime(from);
+
+  base::Time::Exploded exploded;
+  time.UTCExplode(&exploded);
+  to->year = exploded.year;
+  to->month = exploded.month;
+  to->day_of_week = exploded.day_of_week;
+  to->day_of_month = exploded.day_of_month;
+  to->hour = exploded.hour;
+  to->minute = exploded.minute;
+  to->second = exploded.second;
+  to->millisecond = exploded.millisecond;
+  return exploded.HasValidValues() ? 1 : 0;
+}
diff --git a/src/libcef/common/tracker.cc b/src/libcef/common/tracker.cc
index 5e5c509..499f6d8 100644
--- a/src/libcef/common/tracker.cc
+++ b/src/libcef/common/tracker.cc
@@ -11,26 +11,30 @@
 CefTrackNode::~CefTrackNode() {}
 
 void CefTrackNode::InsertTrackPrev(CefTrackNode* object) {
-  if (track_prev_)
+  if (track_prev_) {
     track_prev_->SetTrackNext(object);
+  }
   object->SetTrackNext(this);
   object->SetTrackPrev(track_prev_);
   track_prev_ = object;
 }
 
 void CefTrackNode::InsertTrackNext(CefTrackNode* object) {
-  if (track_next_)
+  if (track_next_) {
     track_next_->SetTrackPrev(object);
+  }
   object->SetTrackPrev(this);
   object->SetTrackNext(track_next_);
   track_next_ = object;
 }
 
 void CefTrackNode::RemoveTracking() {
-  if (track_next_)
+  if (track_next_) {
     track_next_->SetTrackPrev(track_prev_);
-  if (track_prev_)
+  }
+  if (track_prev_) {
     track_prev_->SetTrackNext(track_next_);
+  }
   track_next_ = nullptr;
   track_prev_ = nullptr;
 }
diff --git a/src/libcef/common/urlrequest_impl.cc b/src/libcef/common/urlrequest_impl.cc
index f86b1a6..7311559 100644
--- a/src/libcef/common/urlrequest_impl.cc
+++ b/src/libcef/common/urlrequest_impl.cc
@@ -4,12 +4,12 @@
 
 #include "include/cef_urlrequest.h"
 #include "libcef/browser/net_service/browser_urlrequest_impl.h"
-#include "libcef/common/content_client.h"
+#include "libcef/common/app_manager.h"
 #include "libcef/common/task_runner_impl.h"
-#include "libcef/renderer/render_urlrequest_impl.h"
+#include "libcef/features/runtime_checks.h"
 
 #include "base/logging.h"
-#include "base/message_loop/message_loop.h"
+#include "base/notreached.h"
 #include "content/public/common/content_client.h"
 
 // static
@@ -18,31 +18,26 @@
     CefRefPtr<CefURLRequestClient> client,
     CefRefPtr<CefRequestContext> request_context) {
   if (!request.get() || !client.get()) {
-    NOTREACHED() << "called with invalid parameters";
+    DCHECK(false) << "called with invalid parameters";
     return nullptr;
   }
 
   if (!CefTaskRunnerImpl::GetCurrentTaskRunner()) {
-    NOTREACHED() << "called on invalid thread";
+    DCHECK(false) << "called on invalid thread";
     return nullptr;
   }
 
-  if (CefContentClient::Get()->browser()) {
+  auto content_client = CefAppManager::Get()->GetContentClient();
+  if (content_client->browser()) {
     // In the browser process.
     CefRefPtr<CefBrowserURLRequest> impl =
         new CefBrowserURLRequest(nullptr, request, client, request_context);
-    if (impl->Start())
+    if (impl->Start()) {
       return impl.get();
-    return nullptr;
-  } else if (CefContentClient::Get()->renderer()) {
-    // In the render process.
-    CefRefPtr<CefRenderURLRequest> impl =
-        new CefRenderURLRequest(nullptr, request, client);
-    if (impl->Start())
-      return impl.get();
+    }
     return nullptr;
   } else {
-    NOTREACHED() << "called in unsupported process";
+    DCHECK(false) << "called in unsupported process";
     return nullptr;
   }
 }
diff --git a/src/libcef/common/util_linux.cc b/src/libcef/common/util_linux.cc
new file mode 100644
index 0000000..e6b0909
--- /dev/null
+++ b/src/libcef/common/util_linux.cc
@@ -0,0 +1,37 @@
+// Copyright 2022 The Chromium Embedded Framework Authors. Portions copyright
+// 2011 The Chromium Authors. All rights reserved. Use of this source code is
+// governed by a BSD-style license that can be found in the LICENSE file.
+
+#include "libcef/common/util_linux.h"
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "content/public/common/content_paths.h"
+#include "content/public/common/content_switches.h"
+
+namespace util_linux {
+
+namespace {
+
+void OverrideChildProcessPath() {
+  base::FilePath child_process_path =
+      base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
+          switches::kBrowserSubprocessPath);
+  if (child_process_path.empty()) {
+    return;
+  }
+
+  // Used by ChildProcessHost::GetChildPath and PlatformCrashpadInitialization.
+  base::PathService::OverrideAndCreateIfNeeded(
+      content::CHILD_PROCESS_EXE, child_process_path, /*is_absolute=*/true,
+      /*create=*/false);
+}
+
+}  // namespace
+
+void PreSandboxStartup() {
+  OverrideChildProcessPath();
+}
+
+}  // namespace util_linux
diff --git a/src/libcef/common/util_linux.h b/src/libcef/common/util_linux.h
new file mode 100644
index 0000000..2eeb6ef
--- /dev/null
+++ b/src/libcef/common/util_linux.h
@@ -0,0 +1,16 @@
+// Copyright 2022 The Chromium Embedded Framework Authors. Portions copyright
+// 2011 The Chromium Authors. All rights reserved. Use of this source code is
+// governed by a BSD-style license that can be found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_COMMON_UTIL_LINUX_H_
+#define CEF_LIBCEF_COMMON_UTIL_LINUX_H_
+#pragma once
+
+namespace util_linux {
+
+// Called from MainDelegate::PreSandboxStartup for the main process.
+void PreSandboxStartup();
+
+}  // namespace util_linux
+
+#endif  // CEF_LIBCEF_COMMON_UTIL_LINUX_H_
diff --git a/src/libcef/common/util_mac.h b/src/libcef/common/util_mac.h
index 1d07209..426dfdb 100644
--- a/src/libcef/common/util_mac.h
+++ b/src/libcef/common/util_mac.h
@@ -8,15 +8,16 @@
 
 #include <string>
 
-namespace base {
-class FilePath;
-}
+#include "base/files/file_path.h"
 
 namespace util_mac {
 
 // Returns the path to the NSLibraryDirectory (e.g. "~/Library").
 bool GetLocalLibraryDirectory(base::FilePath* result);
 
+// Returns the framework name (e.g. "Chromium Embedded Framework").
+base::FilePath::StringType GetFrameworkName();
+
 // Returns the path to the CEF framework directory inside the top-level app
 // bundle (e.g. "myapp.app/Contents/Frameworks/Chromium Embedded
 // Framework.framework"). May return an empty value if not running in an app
@@ -45,10 +46,11 @@
 // running in an app bundle.
 base::FilePath GetMainResourcesDirectory();
 
-// Returns the path to the child process executable (e.g. "myapp.app/
-// Contents/Frameworks/myapp Helper.app/Contents/MacOS/myapp Helper"). May
-// return an empty value if not running in an app bundle.
-base::FilePath GetChildProcessPath();
+// Called from MainDelegate::PreSandboxStartup for the main process.
+void PreSandboxStartup();
+
+// Called from MainDelegate::BasicStartupComplete for all processes.
+void BasicStartupComplete();
 
 }  // namespace util_mac
 
diff --git a/src/libcef/common/util_mac.mm b/src/libcef/common/util_mac.mm
index dae9b45..d6c8d1d 100644
--- a/src/libcef/common/util_mac.mm
+++ b/src/libcef/common/util_mac.mm
@@ -6,13 +6,15 @@
 
 #include "libcef/common/cef_switches.h"
 
+#include "base/apple/bundle_locations.h"
+#include "base/apple/foundation_util.h"
 #include "base/base_paths.h"
 #include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/mac/bundle_locations.h"
-#include "base/mac/foundation_util.h"
+#include "base/logging.h"
 #include "base/path_service.h"
 #include "base/strings/sys_string_conversions.h"
+#include "content/public/common/content_paths.h"
+#include "content/public/common/content_switches.h"
 
 namespace util_mac {
 
@@ -21,38 +23,96 @@
 // Returns the path to the Frameworks directory inside the top-level app bundle.
 base::FilePath GetFrameworksPath() {
   base::FilePath bundle_path = GetMainBundlePath();
-  if (bundle_path.empty())
+  if (bundle_path.empty()) {
     return base::FilePath();
+  }
 
   return bundle_path.Append(FILE_PATH_LITERAL("Contents"))
       .Append(FILE_PATH_LITERAL("Frameworks"));
 }
 
+void OverrideFrameworkBundlePath() {
+  base::FilePath framework_path = GetFrameworkDirectory();
+  DCHECK(!framework_path.empty());
+
+  base::apple::SetOverrideFrameworkBundlePath(framework_path);
+}
+
+void OverrideOuterBundlePath() {
+  base::FilePath bundle_path = GetMainBundlePath();
+  DCHECK(!bundle_path.empty());
+
+  base::apple::SetOverrideOuterBundlePath(bundle_path);
+}
+
+void OverrideBaseBundleID() {
+  std::string bundle_id = GetMainBundleID();
+  DCHECK(!bundle_id.empty());
+
+  base::apple::SetBaseBundleID(bundle_id.c_str());
+}
+
+base::FilePath GetNormalChildProcessPath() {
+  base::FilePath frameworks_path = GetFrameworksPath();
+  if (frameworks_path.empty()) {
+    return base::FilePath();
+  }
+
+  std::string exe_name = GetMainProcessPath().BaseName().value();
+  return frameworks_path.Append(FILE_PATH_LITERAL(exe_name + " Helper.app"))
+      .Append(FILE_PATH_LITERAL("Contents"))
+      .Append(FILE_PATH_LITERAL("MacOS"))
+      .Append(FILE_PATH_LITERAL(exe_name + " Helper"));
+}
+
+void OverrideChildProcessPath() {
+  base::FilePath child_process_path =
+      base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
+          switches::kBrowserSubprocessPath);
+
+  if (child_process_path.empty()) {
+    child_process_path = GetNormalChildProcessPath();
+    CHECK(!child_process_path.empty());
+  }
+
+  // Used by ChildProcessHost::GetChildPath and PlatformCrashpadInitialization.
+  base::PathService::OverrideAndCreateIfNeeded(
+      content::CHILD_PROCESS_EXE, child_process_path, /*is_absolute=*/true,
+      /*create=*/false);
+}
+
 }  // namespace
 
 bool GetLocalLibraryDirectory(base::FilePath* result) {
-  return base::mac::GetLocalDirectory(NSLibraryDirectory, result);
+  return base::apple::GetLocalDirectory(NSLibraryDirectory, result);
+}
+
+base::FilePath::StringType GetFrameworkName() {
+  return FILE_PATH_LITERAL("Chromium Embedded Framework");
 }
 
 base::FilePath GetFrameworkDirectory() {
   base::FilePath frameworks_path =
       base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
           switches::kFrameworkDirPath);
-  if (!frameworks_path.empty())
+  if (!frameworks_path.empty()) {
     return frameworks_path;
+  }
 
   frameworks_path = GetFrameworksPath();
-  if (frameworks_path.empty())
+  if (frameworks_path.empty()) {
     return base::FilePath();
+  }
 
-  return frameworks_path.Append(
-      FILE_PATH_LITERAL("Chromium Embedded Framework.framework"));
+  return frameworks_path.Append(GetFrameworkName())
+      .AddExtension(FILE_PATH_LITERAL(".framework"));
 }
 
 base::FilePath GetFrameworkResourcesDirectory() {
   base::FilePath frameworks_path = GetFrameworkDirectory();
-  if (frameworks_path.empty())
+  if (frameworks_path.empty()) {
     return base::FilePath();
+  }
 
   return frameworks_path.Append(FILE_PATH_LITERAL("Resources"));
 }
@@ -68,36 +128,36 @@
   base::FilePath main_bundle_path =
       base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
           switches::kMainBundlePath);
-  if (!main_bundle_path.empty())
+  if (!main_bundle_path.empty()) {
     return main_bundle_path;
+  }
 
-  return base::mac::GetAppBundlePath(GetMainProcessPath());
+  return base::apple::GetAppBundlePath(GetMainProcessPath());
 }
 
 std::string GetMainBundleID() {
-  NSBundle* bundle = base::mac::OuterBundle();
+  NSBundle* bundle = base::apple::OuterBundle();
   return base::SysNSStringToUTF8([bundle bundleIdentifier]);
 }
 
 base::FilePath GetMainResourcesDirectory() {
   base::FilePath bundle_path = GetMainBundlePath();
-  if (bundle_path.empty())
+  if (bundle_path.empty()) {
     return base::FilePath();
+  }
 
   return bundle_path.Append(FILE_PATH_LITERAL("Contents"))
       .Append(FILE_PATH_LITERAL("Resources"));
 }
 
-base::FilePath GetChildProcessPath() {
-  base::FilePath frameworks_path = GetFrameworksPath();
-  if (frameworks_path.empty())
-    return base::FilePath();
+void PreSandboxStartup() {
+  OverrideChildProcessPath();
+}
 
-  std::string exe_name = GetMainProcessPath().BaseName().value();
-  return frameworks_path.Append(FILE_PATH_LITERAL(exe_name + " Helper.app"))
-      .Append(FILE_PATH_LITERAL("Contents"))
-      .Append(FILE_PATH_LITERAL("MacOS"))
-      .Append(FILE_PATH_LITERAL(exe_name + " Helper"));
+void BasicStartupComplete() {
+  OverrideFrameworkBundlePath();
+  OverrideOuterBundlePath();
+  OverrideBaseBundleID();
 }
 
 }  // namespace util_mac
diff --git a/src/libcef/common/value_base.cc b/src/libcef/common/value_base.cc
index f8c741b..55989be 100644
--- a/src/libcef/common/value_base.cc
+++ b/src/libcef/common/value_base.cc
@@ -62,8 +62,9 @@
     // Remove all references.
     if (reference_map_.size() > 0) {
       ReferenceMap::iterator it = reference_map_.begin();
-      for (; it != reference_map_.end(); ++it)
+      for (; it != reference_map_.end(); ++it) {
         it->second->OnControlRemoved();
+      }
       reference_map_.clear();
     }
 
@@ -73,8 +74,9 @@
     ReferenceMap::iterator it = reference_map_.find(value);
     if (it != reference_map_.end()) {
       // Remove the reference.
-      if (notify_object)
+      if (notify_object) {
         it->second->OnControlRemoved();
+      }
       reference_map_.erase(it);
     }
   }
@@ -90,8 +92,9 @@
     return owner_object_;
   } else {
     ReferenceMap::iterator it = reference_map_.find(value);
-    if (it != reference_map_.end())
+    if (it != reference_map_.end()) {
       return it->second;
+    }
     return nullptr;
   }
 }
@@ -120,12 +123,14 @@
   // Controller should already be locked.
   DCHECK(locked());
 
-  if (dependency_map_.empty())
+  if (dependency_map_.empty()) {
     return;
+  }
 
   DependencyMap::iterator it_dependency = dependency_map_.find(value);
-  if (it_dependency == dependency_map_.end())
+  if (it_dependency == dependency_map_.end()) {
     return;
+  }
 
   // Start with the set of dependencies for the current value.
   DependencySet remove_set = it_dependency->second;
@@ -189,8 +194,9 @@
         // Evaluate each child.
         DependencySet::iterator it_other_set = it_other->second.begin();
         for (; it_other_set != it_other->second.end(); ++it_other_set) {
-          if (it_me->second.find(*it_other_set) == it_me->second.end())
+          if (it_me->second.find(*it_other_set) == it_me->second.end()) {
             it_me->second.insert(*it_other_set);
+          }
         }
       }
     }
@@ -203,8 +209,9 @@
   // Controller should already be locked.
   DCHECK(locked());
 
-  if (owner_value_ == old_value)
+  if (owner_value_ == old_value) {
     owner_value_ = new_value;
+  }
 
   if (!reference_map_.empty()) {
     ReferenceMap::iterator it = reference_map_.find(old_value);
diff --git a/src/libcef/common/value_base.h b/src/libcef/common/value_base.h
index 3fd1c92..c860563 100644
--- a/src/libcef/common/value_base.h
+++ b/src/libcef/common/value_base.h
@@ -12,6 +12,7 @@
 
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
+#include "base/notreached.h"
 #include "base/synchronization/lock.h"
 #include "base/thread_annotations.h"
 #include "base/threading/platform_thread.h"
@@ -35,12 +36,18 @@
     explicit AutoLock(CefValueController* impl)
         : impl_(impl), verified_(impl && impl->VerifyThread()) {
       DCHECK(impl);
-      if (verified_)
+      if (verified_) {
         impl_->lock();
+      }
     }
+
+    AutoLock(const AutoLock&) = delete;
+    AutoLock& operator=(const AutoLock&) = delete;
+
     ~AutoLock() {
-      if (verified_)
+      if (verified_) {
         impl_->unlock();
+      }
     }
 
     inline bool verified() { return verified_; }
@@ -48,12 +55,13 @@
    private:
     scoped_refptr<CefValueController> impl_;
     bool verified_;
-
-    DISALLOW_COPY_AND_ASSIGN(AutoLock);
   };
 
   CefValueController();
 
+  CefValueController(const CefValueController&) = delete;
+  CefValueController& operator=(const CefValueController&) = delete;
+
   // Returns true if this controller is thread safe.
   virtual bool thread_safe() = 0;
 
@@ -76,7 +84,7 @@
   inline bool VerifyThread() {
     if (!thread_safe() && !on_correct_thread()) {
       // This object should only be accessed from the thread that created it.
-      NOTREACHED() << "object accessed from incorrect thread.";
+      DCHECK(false) << "object accessed from incorrect thread.";
       return false;
     }
     return true;
@@ -124,15 +132,13 @@
   Object* owner_object_;
 
   // Map of reference objects.
-  typedef std::map<void*, Object*> ReferenceMap;
+  using ReferenceMap = std::map<void*, Object*>;
   ReferenceMap reference_map_;
 
   // Map of dependency objects.
-  typedef std::set<void*> DependencySet;
-  typedef std::map<void*, DependencySet> DependencyMap;
+  using DependencySet = std::set<void*>;
+  using DependencyMap = std::map<void*, DependencySet>;
   DependencyMap dependency_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefValueController);
 };
 
 // Thread-safe access control implementation.
@@ -140,6 +146,10 @@
  public:
   explicit CefValueControllerThreadSafe() : locked_thread_id_(0) {}
 
+  CefValueControllerThreadSafe(const CefValueControllerThreadSafe&) = delete;
+  CefValueControllerThreadSafe& operator=(const CefValueControllerThreadSafe&) =
+      delete;
+
   // CefValueController methods.
   bool thread_safe() override { return true; }
   bool on_correct_thread() override { return true; }
@@ -159,8 +169,6 @@
  private:
   base::Lock lock_;
   base::PlatformThreadId locked_thread_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefValueControllerThreadSafe);
 };
 
 // Non-thread-safe access control implementation.
@@ -169,6 +177,11 @@
   explicit CefValueControllerNonThreadSafe()
       : thread_id_(base::PlatformThread::CurrentId()) {}
 
+  CefValueControllerNonThreadSafe(const CefValueControllerNonThreadSafe&) =
+      delete;
+  CefValueControllerNonThreadSafe& operator=(
+      const CefValueControllerNonThreadSafe&) = delete;
+
   // CefValueController methods.
   bool thread_safe() override { return false; }
   bool on_correct_thread() override {
@@ -181,8 +194,6 @@
 
  private:
   base::PlatformThreadId thread_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefValueControllerNonThreadSafe);
 };
 
 // Helper macros for verifying context.
@@ -261,14 +272,19 @@
       controller_->AddReference(value_, this);
 
       // Add a dependency on the parent value.
-      if (parent_value)
+      if (parent_value) {
         controller_->AddDependency(parent_value, value_);
+      }
     }
   }
 
+  CefValueBase(const CefValueBase&) = delete;
+  CefValueBase& operator=(const CefValueBase&) = delete;
+
   ~CefValueBase() override {
-    if (controller_.get() && value_)
+    if (controller_.get() && value_) {
       Delete();
+    }
   }
 
   // True if the underlying value is referenced instead of owned.
@@ -280,11 +296,18 @@
   // True if access to the underlying value is read-only.
   inline bool read_only() const { return read_only_; }
 
+  // Convert a writable value to read-only. The reverse could be surprising and
+  // is therefore not supported.
+  void MarkReadOnly() {
+    DCHECK(!read_only_);
+    read_only_ = true;
+  }
+
   // True if the underlying value has been detached.
-  inline bool detached() { return !controller_.get(); }
+  inline bool detached() const { return !controller_.get(); }
 
   // Returns the controller.
-  inline CefValueController* controller() { return controller_.get(); }
+  inline CefValueController* controller() const { return controller_.get(); }
 
   // Deletes the underlying value.
   void Delete() {
@@ -309,12 +332,9 @@
   // Detaches the underlying value and returns a pointer to it. If this is an
   // owner and a |new_controller| value is specified any existing references
   // will be passed to the new controller.
-  ValueType* Detach(CefValueController* new_controller) {
+  [[nodiscard]] ValueType* Detach(CefValueController* new_controller) {
     CEF_VALUE_VERIFY_RETURN(false, nullptr);
 
-    // A |new_controller| value is required for mode kOwnerWillDelete.
-    DCHECK(!will_delete() || new_controller);
-
     if (new_controller && !reference()) {
       // Pass any existing references and dependencies to the new controller.
       // They will be removed from this controller.
@@ -333,10 +353,10 @@
   }
 
   // Verify that the value is attached.
-  inline bool VerifyAttached() {
+  inline bool VerifyAttached() const {
     if (detached()) {
       // This object should not be accessed after being detached.
-      NOTREACHED() << "object accessed after being detached.";
+      DCHECK(false) << "object accessed after being detached.";
       return false;
     }
     return true;
@@ -358,27 +378,33 @@
   virtual void DeleteValue(ValueType* value) { delete value; }
 
   // Returns a mutable reference to the value.
-  inline ValueType* mutable_value() {
+  inline ValueType* mutable_value() const {
     DCHECK(value_);
     DCHECK(!read_only_);
     DCHECK(controller()->locked());
     return value_;
   }
+
   // Returns a const reference to the value.
-  inline const ValueType& const_value() {
+  inline const ValueType& const_value() const {
     DCHECK(value_);
     DCHECK(controller()->locked());
     return *value_;
   }
 
+  // Returns an mutable reference to the value without checking read-only state.
+  inline ValueType* mutable_value_unchecked() const {
+    return const_cast<ValueType*>(&const_value());
+  }
+
   // Verify that the value can be accessed.
-  inline bool VerifyAccess(bool modify) {
+  inline bool VerifyAccess(bool modify) const {
     // The controller must already be locked.
     DCHECK(controller()->locked());
 
     if (read_only() && modify) {
       // This object cannot be modified.
-      NOTREACHED() << "mutation attempted on read-only object.";
+      DCHECK(false) << "mutation attempted on read-only object.";
       return false;
     }
 
@@ -388,8 +414,9 @@
   // Used to indicate that this object owns the controller.
   inline void SetOwnsController() {
     CefValueController::AutoLock lock_scope(controller_.get());
-    if (lock_scope.verified())
+    if (lock_scope.verified()) {
       controller_->SetOwner(value_, this);
+    }
   }
 
   // Encapsulates value locking and verification logic.
@@ -400,13 +427,14 @@
       verified_ = (auto_lock_.verified() && impl->VerifyAccess(modify));
     }
 
+    AutoLock(const AutoLock&) = delete;
+    AutoLock& operator=(const AutoLock&) = delete;
+
     inline bool verified() { return verified_; }
 
    private:
     CefValueController::AutoLock auto_lock_;
     bool verified_;
-
-    DISALLOW_COPY_AND_ASSIGN(AutoLock);
   };
 
  private:
@@ -416,8 +444,6 @@
   scoped_refptr<CefValueController> controller_;
 
   IMPLEMENT_REFCOUNTING(CefValueBase);
-
-  DISALLOW_COPY_AND_ASSIGN(CefValueBase);
 };
 
 #endif  // CEF_LIBCEF_COMMON_VALUE_BASE_H_
diff --git a/src/libcef/common/values_impl.cc b/src/libcef/common/values_impl.cc
index 5884116..a95d8f5 100644
--- a/src/libcef/common/values_impl.cc
+++ b/src/libcef/common/values_impl.cc
@@ -9,11 +9,35 @@
 
 #include "base/memory/ptr_util.h"
 
+namespace {
+
+// Removes empty dictionaries from |dict|, potentially nested.
+// Does not modify empty lists.
+// From chrome/browser/chromeos/extensions/echo_private/echo_private_api.cc
+void RemoveEmptyValueDicts(base::Value::Dict& dict) {
+  auto it = dict.begin();
+  while (it != dict.end()) {
+    base::Value& value = it->second;
+    if (value.is_dict()) {
+      base::Value::Dict& sub_dict = value.GetDict();
+      RemoveEmptyValueDicts(sub_dict);
+      if (sub_dict.empty()) {
+        it = dict.erase(it);
+        continue;
+      }
+    }
+    it++;
+  }
+}
+
+}  // namespace
+
 // CefValueImpl implementation.
 
 // static
 CefRefPtr<CefValue> CefValue::Create() {
-  return new CefValueImpl(new base::Value());
+  // Start with VTYPE_NULL instead of VTYPE_INVALID for backwards compatibility.
+  return new CefValueImpl(base::Value());
 }
 
 // static
@@ -30,25 +54,22 @@
   }
 
   if (value->is_dict()) {
-    base::DictionaryValue* dict_value =
-        static_cast<base::DictionaryValue*>(value);
     return new CefValueImpl(CefDictionaryValueImpl::GetOrCreateRef(
-        dict_value, parent_value, read_only, controller));
+        value, parent_value, read_only, controller));
   }
 
   if (value->is_list()) {
-    base::ListValue* list_value = static_cast<base::ListValue*>(value);
     return new CefValueImpl(CefListValueImpl::GetOrCreateRef(
-        list_value, parent_value, read_only, controller));
+        value, parent_value, read_only, controller));
   }
 
-  return new CefValueImpl(value->DeepCopy());
+  return new CefValueImpl(value->Clone());
 }
 
 CefValueImpl::CefValueImpl() {}
 
-CefValueImpl::CefValueImpl(base::Value* value) {
-  SetValue(value);
+CefValueImpl::CefValueImpl(base::Value value) {
+  SetValue(std::move(value));
 }
 
 CefValueImpl::CefValueImpl(CefRefPtr<CefBinaryValue> value)
@@ -62,12 +83,31 @@
 
 CefValueImpl::~CefValueImpl() {}
 
-void CefValueImpl::SetValue(base::Value* value) {
+void CefValueImpl::SetValue(base::Value value) {
   base::AutoLock lock_scope(lock_);
-  SetValueInternal(value);
+  SetValueInternal(absl::make_optional(std::move(value)));
 }
 
-base::Value* CefValueImpl::CopyOrDetachValue(
+base::Value CefValueImpl::CopyValue() {
+  base::AutoLock lock_scope(lock_);
+
+  if (binary_value_) {
+    return static_cast<CefBinaryValueImpl*>(binary_value_.get())->CopyValue();
+  }
+
+  if (dictionary_value_) {
+    return static_cast<CefDictionaryValueImpl*>(dictionary_value_.get())
+        ->CopyValue();
+  }
+
+  if (list_value_) {
+    return static_cast<CefListValueImpl*>(list_value_.get())->CopyValue();
+  }
+
+  return value_->Clone();
+}
+
+std::unique_ptr<base::Value> CefValueImpl::CopyOrDetachValue(
     CefValueController* new_controller) {
   base::AutoLock lock_scope(lock_);
 
@@ -86,7 +126,7 @@
         ->CopyOrDetachValue(new_controller);
   }
 
-  return value_->DeepCopy();
+  return std::make_unique<base::Value>(value_->Clone());
 }
 
 void CefValueImpl::SwapValue(base::Value* new_value,
@@ -99,24 +139,25 @@
         new_value, new_parent_value, new_controller);
   } else if (dictionary_value_) {
     dictionary_value_ = CefDictionaryValueImpl::GetOrCreateRef(
-        static_cast<base::DictionaryValue*>(new_value), new_parent_value, false,
-        new_controller);
+        new_value, new_parent_value, false, new_controller);
   } else if (list_value_) {
-    list_value_ = CefListValueImpl::GetOrCreateRef(
-        static_cast<base::ListValue*>(new_value), new_parent_value, false,
-        new_controller);
+    list_value_ = CefListValueImpl::GetOrCreateRef(new_value, new_parent_value,
+                                                   false, new_controller);
   }
 }
 
 bool CefValueImpl::IsValid() {
   base::AutoLock lock_scope(lock_);
 
-  if (binary_value_)
+  if (binary_value_) {
     return binary_value_->IsValid();
-  if (dictionary_value_)
+  }
+  if (dictionary_value_) {
     return dictionary_value_->IsValid();
-  if (list_value_)
+  }
+  if (list_value_) {
     return list_value_->IsValid();
+  }
 
   return (value_ != nullptr);
 }
@@ -124,12 +165,15 @@
 bool CefValueImpl::IsOwned() {
   base::AutoLock lock_scope(lock_);
 
-  if (binary_value_)
+  if (binary_value_) {
     return binary_value_->IsOwned();
-  if (dictionary_value_)
+  }
+  if (dictionary_value_) {
     return dictionary_value_->IsOwned();
-  if (list_value_)
+  }
+  if (list_value_) {
     return list_value_->IsOwned();
+  }
 
   return false;
 }
@@ -137,73 +181,91 @@
 bool CefValueImpl::IsReadOnly() {
   base::AutoLock lock_scope(lock_);
 
-  if (binary_value_)
+  if (binary_value_) {
     return true;
-  if (dictionary_value_)
+  }
+  if (dictionary_value_) {
     return dictionary_value_->IsReadOnly();
-  if (list_value_)
+  }
+  if (list_value_) {
     return list_value_->IsReadOnly();
+  }
 
   return false;
 }
 
 bool CefValueImpl::IsSame(CefRefPtr<CefValue> that) {
-  if (that.get() == this)
+  if (that.get() == this) {
     return true;
-  if (!that.get() || that->GetType() != GetType())
+  }
+  if (!that.get() || that->GetType() != GetType()) {
     return false;
+  }
 
   CefValueImpl* impl = static_cast<CefValueImpl*>(that.get());
 
   base::AutoLock lock_scope(lock_);
   base::AutoLock lock_scope2(impl->lock_);
 
-  if (binary_value_)
+  if (binary_value_) {
     return binary_value_->IsSame(impl->binary_value_);
-  if (dictionary_value_)
+  }
+  if (dictionary_value_) {
     return dictionary_value_->IsSame(impl->dictionary_value_);
-  if (list_value_)
+  }
+  if (list_value_) {
     return list_value_->IsSame(impl->list_value_);
+  }
 
   // Simple types are never the same.
   return false;
 }
 
 bool CefValueImpl::IsEqual(CefRefPtr<CefValue> that) {
-  if (that.get() == this)
+  if (that.get() == this) {
     return true;
-  if (!that.get() || that->GetType() != GetType())
+  }
+  if (!that.get() || that->GetType() != GetType()) {
     return false;
+  }
 
   CefValueImpl* impl = static_cast<CefValueImpl*>(that.get());
 
   base::AutoLock lock_scope(lock_);
   base::AutoLock lock_scope2(impl->lock_);
 
-  if (binary_value_)
+  if (binary_value_) {
     return binary_value_->IsEqual(impl->binary_value_);
-  if (dictionary_value_)
+  }
+  if (dictionary_value_) {
     return dictionary_value_->IsEqual(impl->dictionary_value_);
-  if (list_value_)
+  }
+  if (list_value_) {
     return list_value_->IsEqual(impl->list_value_);
+  }
 
-  if (!value_)  // Invalid types are equal.
+  if (!value_) {  // Invalid types are equal.
     return true;
+  }
 
-  return value_->Equals(impl->value_.get());
+  return *value_ == *(impl->value_.get());
 }
 
 CefRefPtr<CefValue> CefValueImpl::Copy() {
   base::AutoLock lock_scope(lock_);
 
-  if (binary_value_)
+  if (binary_value_) {
     return new CefValueImpl(binary_value_->Copy());
-  if (dictionary_value_)
+  }
+  if (dictionary_value_) {
     return new CefValueImpl(dictionary_value_->Copy(false));
-  if (list_value_)
+  }
+  if (list_value_) {
     return new CefValueImpl(list_value_->Copy());
-  if (value_)
-    return new CefValueImpl(value_->DeepCopy());
+  }
+  if (value_) {
+    return new CefValueImpl(value_->Clone());
+  }
 
   return new CefValueImpl();
 }
@@ -211,12 +273,15 @@
 CefValueType CefValueImpl::GetType() {
   base::AutoLock lock_scope(lock_);
 
-  if (binary_value_)
+  if (binary_value_) {
     return VTYPE_BINARY;
-  if (dictionary_value_)
+  }
+  if (dictionary_value_) {
     return VTYPE_DICTIONARY;
-  if (list_value_)
+  }
+  if (list_value_) {
     return VTYPE_LIST;
+  }
 
   if (value_) {
     switch (value_->type()) {
@@ -231,7 +296,7 @@
       case base::Value::Type::STRING:
         return VTYPE_STRING;
       default:
-        NOTREACHED();
+        DCHECK(false);
         break;
     }
   }
@@ -243,8 +308,9 @@
   base::AutoLock lock_scope(lock_);
 
   bool ret_value = false;
-  if (value_)
-    value_->GetAsBoolean(&ret_value);
+  if (value_ && value_->is_bool()) {
+    ret_value = value_->GetBool();
+  }
   return ret_value;
 }
 
@@ -252,8 +318,9 @@
   base::AutoLock lock_scope(lock_);
 
   int ret_value = 0;
-  if (value_)
-    value_->GetAsInteger(&ret_value);
+  if (value_ && value_->is_int()) {
+    ret_value = value_->GetInt();
+  }
   return ret_value;
 }
 
@@ -261,8 +328,9 @@
   base::AutoLock lock_scope(lock_);
 
   double ret_value = 0;
-  if (value_)
-    value_->GetAsDouble(&ret_value);
+  if (value_ && value_->is_double()) {
+    ret_value = value_->GetDouble();
+  }
   return ret_value;
 }
 
@@ -270,8 +338,9 @@
   base::AutoLock lock_scope(lock_);
 
   std::string ret_value;
-  if (value_)
-    value_->GetAsString(&ret_value);
+  if (value_ && value_->is_string()) {
+    ret_value = value_->GetString();
+  }
   return ret_value;
 }
 
@@ -291,52 +360,52 @@
 }
 
 bool CefValueImpl::SetNull() {
-  SetValue(new base::Value());
+  SetValue(base::Value());
   return true;
 }
 
 bool CefValueImpl::SetBool(bool value) {
-  SetValue(new base::Value(value));
+  SetValue(base::Value(value));
   return true;
 }
 
 bool CefValueImpl::SetInt(int value) {
-  SetValue(new base::Value(value));
+  SetValue(base::Value(value));
   return true;
 }
 
 bool CefValueImpl::SetDouble(double value) {
-  SetValue(new base::Value(value));
+  SetValue(base::Value(value));
   return true;
 }
 
 bool CefValueImpl::SetString(const CefString& value) {
-  SetValue(new base::Value(value.ToString()));
+  SetValue(base::Value(value.ToString()));
   return true;
 }
 
 bool CefValueImpl::SetBinary(CefRefPtr<CefBinaryValue> value) {
   base::AutoLock lock_scope(lock_);
-  SetValueInternal(nullptr);
+  SetValueInternal(absl::nullopt);
   binary_value_ = value;
   return true;
 }
 
 bool CefValueImpl::SetDictionary(CefRefPtr<CefDictionaryValue> value) {
   base::AutoLock lock_scope(lock_);
-  SetValueInternal(nullptr);
+  SetValueInternal(absl::nullopt);
   dictionary_value_ = value;
   return true;
 }
 
 bool CefValueImpl::SetList(CefRefPtr<CefListValue> value) {
   base::AutoLock lock_scope(lock_);
-  SetValueInternal(nullptr);
+  SetValueInternal(absl::nullopt);
   list_value_ = value;
   return true;
 }
 
-void CefValueImpl::SetValueInternal(base::Value* value) {
+void CefValueImpl::SetValueInternal(absl::optional<base::Value> value) {
   lock_.AssertAcquired();
 
   value_.reset(nullptr);
@@ -345,20 +414,21 @@
   list_value_ = nullptr;
 
   if (value) {
-    switch (value->type()) {
+    switch ((*value).type()) {
       case base::Value::Type::BINARY:
-        binary_value_ = new CefBinaryValueImpl(value, true);
-        return;
-      case base::Value::Type::DICTIONARY:
-        dictionary_value_ = new CefDictionaryValueImpl(
-            static_cast<base::DictionaryValue*>(value), true, false);
-        return;
+        binary_value_ = new CefBinaryValueImpl(std::move(*value));
+        break;
+      case base::Value::Type::DICT:
+        dictionary_value_ =
+            new CefDictionaryValueImpl(std::move(*value), /*read_only=*/false);
+        break;
       case base::Value::Type::LIST:
-        list_value_ = new CefListValueImpl(static_cast<base::ListValue*>(value),
-                                           true, false);
-        return;
+        list_value_ =
+            new CefListValueImpl(std::move(*value), /*read_only=*/false);
+        break;
       default:
-        value_.reset(value);
+        value_ = std::make_unique<base::Value>(std::move(*value));
+        break;
     }
   }
 }
@@ -382,8 +452,9 @@
   lock_.Acquire();
 
   CefValueController* controller = GetValueController();
-  if (controller)
+  if (controller) {
     controller->lock();
+  }
 }
 
 void CefValueImpl::ReleaseLock() NO_THREAD_SAFETY_ANALYSIS {
@@ -418,11 +489,12 @@
                                                  size_t data_size) {
   DCHECK(data);
   DCHECK_GT(data_size, (size_t)0);
-  if (!data || data_size == 0)
+  if (!data || data_size == 0) {
     return nullptr;
+  }
 
-  return new CefBinaryValueImpl(static_cast<char*>(const_cast<void*>(data)),
-                                data_size);
+  const auto ptr = static_cast<const uint8_t*>(data);
+  return new CefBinaryValueImpl(base::make_span(ptr, data_size));
 }
 
 // static
@@ -435,48 +507,46 @@
   DCHECK(controller);
 
   CefValueController::Object* object = controller->Get(value);
-  if (object)
+  if (object) {
     return static_cast<CefBinaryValueImpl*>(object);
+  }
 
   return new CefBinaryValueImpl(value, parent_value,
                                 CefBinaryValueImpl::kReference, controller);
 }
 
+CefBinaryValueImpl::CefBinaryValueImpl(base::Value value)
+    : CefBinaryValueImpl(new base::Value(std::move(value)),
+                         /*will_delete=*/true) {}
+
 CefBinaryValueImpl::CefBinaryValueImpl(base::Value* value, bool will_delete)
-    : CefValueBase<CefBinaryValue, base::Value>(
-          value,
-          nullptr,
-          will_delete ? kOwnerWillDelete : kOwnerNoDelete,
-          true,
-          nullptr) {}
+    : CefBinaryValueImpl(value,
+                         nullptr,
+                         will_delete ? kOwnerWillDelete : kOwnerNoDelete,
+                         nullptr) {}
 
-CefBinaryValueImpl::CefBinaryValueImpl(char* data, size_t data_size)
-    : CefValueBase<CefBinaryValue, base::Value>(
-          new base::Value(std::vector<char>(data, data + data_size)),
-          nullptr,
-          kOwnerWillDelete,
-          true,
-          nullptr) {}
+CefBinaryValueImpl::CefBinaryValueImpl(base::span<const uint8_t> value)
+    : CefBinaryValueImpl(new base::Value(value),
+                         nullptr,
+                         kOwnerWillDelete,
+                         nullptr) {}
 
-base::Value* CefBinaryValueImpl::CopyValue() {
-  CEF_VALUE_VERIFY_RETURN(false, nullptr);
-  return const_value().DeepCopy();
+base::Value CefBinaryValueImpl::CopyValue() {
+  CEF_VALUE_VERIFY_RETURN(false, base::Value());
+  return const_value().Clone();
 }
 
-base::Value* CefBinaryValueImpl::CopyOrDetachValue(
+std::unique_ptr<base::Value> CefBinaryValueImpl::CopyOrDetachValue(
     CefValueController* new_controller) {
-  base::Value* new_value;
-
   if (!will_delete()) {
     // Copy the value.
-    new_value = CopyValue();
-  } else {
-    // Take ownership of the value.
-    new_value = Detach(new_controller);
+    return std::make_unique<base::Value>(CopyValue());
   }
 
-  DCHECK(new_value);
-  return new_value;
+  // Take ownership of the value.
+  auto value = base::WrapUnique(Detach(new_controller));
+  DCHECK(value.get());
+  return value;
 }
 
 bool CefBinaryValueImpl::IsSameValue(const base::Value* that) {
@@ -486,14 +556,15 @@
 
 bool CefBinaryValueImpl::IsEqualValue(const base::Value* that) {
   CEF_VALUE_VERIFY_RETURN(false, false);
-  return const_value().Equals(that);
+  return const_value() == *that;
 }
 
-base::Value* CefBinaryValueImpl::GetValueUnsafe() {
-  if (!VerifyAttached())
+base::Value* CefBinaryValueImpl::GetValueUnsafe() const {
+  if (!VerifyAttached()) {
     return nullptr;
+  }
   controller()->AssertLockAcquired();
-  return const_cast<base::Value*>(&const_value());
+  return mutable_value_unchecked();
 }
 
 bool CefBinaryValueImpl::IsValid() {
@@ -505,10 +576,12 @@
 }
 
 bool CefBinaryValueImpl::IsSame(CefRefPtr<CefBinaryValue> that) {
-  if (!that.get())
+  if (!that.get()) {
     return false;
-  if (that.get() == this)
+  }
+  if (that.get() == this) {
     return true;
+  }
 
   CEF_VALUE_VERIFY_RETURN(false, false);
   return static_cast<CefBinaryValueImpl*>(that.get())
@@ -516,10 +589,12 @@
 }
 
 bool CefBinaryValueImpl::IsEqual(CefRefPtr<CefBinaryValue> that) {
-  if (!that.get())
+  if (!that.get()) {
     return false;
-  if (that.get() == this)
+  }
+  if (that.get() == this) {
     return true;
+  }
 
   CEF_VALUE_VERIFY_RETURN(false, false);
   return static_cast<CefBinaryValueImpl*>(that.get())
@@ -528,8 +603,12 @@
 
 CefRefPtr<CefBinaryValue> CefBinaryValueImpl::Copy() {
   CEF_VALUE_VERIFY_RETURN(false, nullptr);
-  return new CefBinaryValueImpl(const_value().DeepCopy(), nullptr,
-                                CefBinaryValueImpl::kOwnerWillDelete, nullptr);
+  return new CefBinaryValueImpl(const_value().Clone());
+}
+
+const void* CefBinaryValueImpl::GetRawData() {
+  CEF_VALUE_VERIFY_RETURN(false, nullptr);
+  return const_value().GetBlob().data();
 }
 
 size_t CefBinaryValueImpl::GetSize() {
@@ -542,15 +621,17 @@
                                    size_t data_offset) {
   DCHECK(buffer);
   DCHECK_GT(buffer_size, (size_t)0);
-  if (!buffer || buffer_size == 0)
+  if (!buffer || buffer_size == 0) {
     return 0;
+  }
 
   CEF_VALUE_VERIFY_RETURN(false, 0);
 
   size_t size = const_value().GetBlob().size();
   DCHECK_LT(data_offset, size);
-  if (data_offset >= size)
+  if (data_offset >= size) {
     return 0;
+  }
 
   size = std::min(buffer_size, size - data_offset);
   auto* data = const_value().GetBlob().data();
@@ -565,77 +646,86 @@
     : CefValueBase<CefBinaryValue, base::Value>(value,
                                                 parent_value,
                                                 value_mode,
-                                                true,
+                                                /*read_only=*/true,
                                                 controller) {}
 
 // CefDictionaryValueImpl implementation.
 
 // static
 CefRefPtr<CefDictionaryValue> CefDictionaryValue::Create() {
-  return new CefDictionaryValueImpl(new base::DictionaryValue(), true, false);
+  return new CefDictionaryValueImpl(base::Value(base::Value::Type::DICT),
+                                    /*read_only=*/false);
 }
 
 // static
 CefRefPtr<CefDictionaryValue> CefDictionaryValueImpl::GetOrCreateRef(
-    base::DictionaryValue* value,
+    base::Value* value,
     void* parent_value,
     bool read_only,
     CefValueController* controller) {
   CefValueController::Object* object = controller->Get(value);
-  if (object)
+  if (object) {
     return static_cast<CefDictionaryValueImpl*>(object);
+  }
 
   return new CefDictionaryValueImpl(value, parent_value,
                                     CefDictionaryValueImpl::kReference,
                                     read_only, controller);
 }
 
-CefDictionaryValueImpl::CefDictionaryValueImpl(base::DictionaryValue* value,
+CefDictionaryValueImpl::CefDictionaryValueImpl(base::Value value,
+                                               bool read_only)
+    : CefDictionaryValueImpl(new base::Value(std::move(value)),
+                             /*will_delete=*/true,
+                             read_only) {}
+
+CefDictionaryValueImpl::CefDictionaryValueImpl(base::Value::Dict value,
+                                               bool read_only)
+    : CefDictionaryValueImpl(base::Value(std::move(value)), read_only) {}
+
+CefDictionaryValueImpl::CefDictionaryValueImpl(base::Value* value,
                                                bool will_delete,
                                                bool read_only)
-    : CefValueBase<CefDictionaryValue, base::DictionaryValue>(
-          value,
-          nullptr,
-          will_delete ? kOwnerWillDelete : kOwnerNoDelete,
-          read_only,
-          nullptr) {}
+    : CefDictionaryValueImpl(value,
+                             nullptr,
+                             will_delete ? kOwnerWillDelete : kOwnerNoDelete,
+                             read_only,
+                             nullptr) {}
 
-base::DictionaryValue* CefDictionaryValueImpl::CopyValue() {
-  CEF_VALUE_VERIFY_RETURN(false, nullptr);
-  return const_value().DeepCopy();
+base::Value CefDictionaryValueImpl::CopyValue() {
+  CEF_VALUE_VERIFY_RETURN(false, base::Value());
+  return const_value().Clone();
 }
 
-base::DictionaryValue* CefDictionaryValueImpl::CopyOrDetachValue(
+std::unique_ptr<base::Value> CefDictionaryValueImpl::CopyOrDetachValue(
     CefValueController* new_controller) {
-  base::DictionaryValue* new_value;
-
   if (!will_delete()) {
     // Copy the value.
-    new_value = CopyValue();
-  } else {
-    // Take ownership of the value.
-    new_value = Detach(new_controller);
+    return std::make_unique<base::Value>(CopyValue());
   }
 
-  DCHECK(new_value);
-  return new_value;
+  // Take ownership of the value.
+  auto value = base::WrapUnique(Detach(new_controller));
+  DCHECK(value.get());
+  return value;
 }
 
-bool CefDictionaryValueImpl::IsSameValue(const base::DictionaryValue* that) {
+bool CefDictionaryValueImpl::IsSameValue(const base::Value* that) {
   CEF_VALUE_VERIFY_RETURN(false, false);
   return (&const_value() == that);
 }
 
-bool CefDictionaryValueImpl::IsEqualValue(const base::DictionaryValue* that) {
+bool CefDictionaryValueImpl::IsEqualValue(const base::Value* that) {
   CEF_VALUE_VERIFY_RETURN(false, false);
-  return const_value().Equals(that);
+  return const_value() == *that;
 }
 
-base::DictionaryValue* CefDictionaryValueImpl::GetValueUnsafe() {
-  if (!VerifyAttached())
+base::Value* CefDictionaryValueImpl::GetValueUnsafe() const {
+  if (!VerifyAttached()) {
     return nullptr;
+  }
   controller()->AssertLockAcquired();
-  return const_cast<base::DictionaryValue*>(&const_value());
+  return mutable_value_unchecked();
 }
 
 bool CefDictionaryValueImpl::IsValid() {
@@ -651,10 +741,12 @@
 }
 
 bool CefDictionaryValueImpl::IsSame(CefRefPtr<CefDictionaryValue> that) {
-  if (!that.get())
+  if (!that.get()) {
     return false;
-  if (that.get() == this)
+  }
+  if (that.get() == this) {
     return true;
+  }
 
   CEF_VALUE_VERIFY_RETURN(false, false);
   return static_cast<CefDictionaryValueImpl*>(that.get())
@@ -662,10 +754,12 @@
 }
 
 bool CefDictionaryValueImpl::IsEqual(CefRefPtr<CefDictionaryValue> that) {
-  if (!that.get())
+  if (!that.get()) {
     return false;
-  if (that.get() == this)
+  }
+  if (that.get() == this) {
     return true;
+  }
 
   CEF_VALUE_VERIFY_RETURN(false, false);
   return static_cast<CefDictionaryValueImpl*>(that.get())
@@ -676,22 +770,17 @@
     bool exclude_empty_children) {
   CEF_VALUE_VERIFY_RETURN(false, nullptr);
 
-  base::DictionaryValue* value;
+  auto value = const_value().Clone();
   if (exclude_empty_children) {
-    value = const_cast<base::DictionaryValue&>(const_value())
-                .DeepCopyWithoutEmptyChildren()
-                .release();
-  } else {
-    value = const_value().DeepCopy();
+    RemoveEmptyValueDicts(value.GetDict());
   }
 
-  return new CefDictionaryValueImpl(
-      value, nullptr, CefDictionaryValueImpl::kOwnerWillDelete, false, nullptr);
+  return new CefDictionaryValueImpl(std::move(value), /*read_only=*/false);
 }
 
 size_t CefDictionaryValueImpl::GetSize() {
   CEF_VALUE_VERIFY_RETURN(false, 0);
-  return const_value().size();
+  return const_value().GetDict().size();
 }
 
 bool CefDictionaryValueImpl::Clear() {
@@ -700,21 +789,20 @@
   // Detach any dependent values.
   controller()->RemoveDependencies(mutable_value());
 
-  mutable_value()->Clear();
+  mutable_value()->GetDict().clear();
   return true;
 }
 
 bool CefDictionaryValueImpl::HasKey(const CefString& key) {
   CEF_VALUE_VERIFY_RETURN(false, 0);
-  return const_value().HasKey(base::StringPiece(key));
+  return const_value().GetDict().contains(base::StringPiece(key.ToString()));
 }
 
 bool CefDictionaryValueImpl::GetKeys(KeyList& keys) {
   CEF_VALUE_VERIFY_RETURN(false, 0);
 
-  for (base::DictionaryValue::Iterator i(const_value()); !i.IsAtEnd();
-       i.Advance()) {
-    keys.push_back(i.key());
+  for (const auto item : const_value().GetDict()) {
+    keys.push_back(item.first);
   }
 
   return true;
@@ -728,10 +816,10 @@
 CefValueType CefDictionaryValueImpl::GetType(const CefString& key) {
   CEF_VALUE_VERIFY_RETURN(false, VTYPE_INVALID);
 
-  const base::Value* out_value = nullptr;
-  if (const_value().GetWithoutPathExpansion(base::StringPiece(key),
-                                            &out_value)) {
-    switch (out_value->type()) {
+  const base::Value* value =
+      const_value().GetDict().Find(base::StringPiece(key.ToString()));
+  if (value) {
+    switch (value->type()) {
       case base::Value::Type::NONE:
         return VTYPE_NULL;
       case base::Value::Type::BOOLEAN:
@@ -744,12 +832,10 @@
         return VTYPE_STRING;
       case base::Value::Type::BINARY:
         return VTYPE_BINARY;
-      case base::Value::Type::DICTIONARY:
+      case base::Value::Type::DICT:
         return VTYPE_DICTIONARY;
       case base::Value::Type::LIST:
         return VTYPE_LIST;
-      case base::Value::Type::DEAD:
-        return VTYPE_INVALID;
     }
   }
 
@@ -759,13 +845,12 @@
 CefRefPtr<CefValue> CefDictionaryValueImpl::GetValue(const CefString& key) {
   CEF_VALUE_VERIFY_RETURN(false, nullptr);
 
-  const base::Value* out_value = nullptr;
-  if (const_value().GetWithoutPathExpansion(base::StringPiece(key),
-                                            &out_value)) {
-    return CefValueImpl::GetOrCreateRefOrCopy(
-        const_cast<base::Value*>(out_value),
-        const_cast<base::DictionaryValue*>(&const_value()), read_only(),
-        controller());
+  const base::Value* value =
+      const_value().GetDict().Find(base::StringPiece(key.ToString()));
+  if (value) {
+    return CefValueImpl::GetOrCreateRefOrCopy(const_cast<base::Value*>(value),
+                                              mutable_value_unchecked(),
+                                              read_only(), controller());
   }
 
   return nullptr;
@@ -774,11 +859,13 @@
 bool CefDictionaryValueImpl::GetBool(const CefString& key) {
   CEF_VALUE_VERIFY_RETURN(false, false);
 
-  const base::Value* out_value = nullptr;
   bool ret_value = false;
 
-  if (const_value().GetWithoutPathExpansion(base::StringPiece(key), &out_value))
-    out_value->GetAsBoolean(&ret_value);
+  const base::Value* value =
+      const_value().GetDict().Find(base::StringPiece(key.ToString()));
+  if (value && value->is_bool()) {
+    ret_value = value->GetBool();
+  }
 
   return ret_value;
 }
@@ -786,11 +873,13 @@
 int CefDictionaryValueImpl::GetInt(const CefString& key) {
   CEF_VALUE_VERIFY_RETURN(false, 0);
 
-  const base::Value* out_value = nullptr;
   int ret_value = 0;
 
-  if (const_value().GetWithoutPathExpansion(base::StringPiece(key), &out_value))
-    out_value->GetAsInteger(&ret_value);
+  const base::Value* value =
+      const_value().GetDict().Find(base::StringPiece(key.ToString()));
+  if (value && value->is_int()) {
+    ret_value = value->GetInt();
+  }
 
   return ret_value;
 }
@@ -798,11 +887,13 @@
 double CefDictionaryValueImpl::GetDouble(const CefString& key) {
   CEF_VALUE_VERIFY_RETURN(false, 0);
 
-  const base::Value* out_value = nullptr;
   double ret_value = 0;
 
-  if (const_value().GetWithoutPathExpansion(base::StringPiece(key), &out_value))
-    out_value->GetAsDouble(&ret_value);
+  const base::Value* value =
+      const_value().GetDict().Find(base::StringPiece(key.ToString()));
+  if (value && value->is_double()) {
+    ret_value = value->GetDouble();
+  }
 
   return ret_value;
 }
@@ -810,11 +901,13 @@
 CefString CefDictionaryValueImpl::GetString(const CefString& key) {
   CEF_VALUE_VERIFY_RETURN(false, CefString());
 
-  const base::Value* out_value = nullptr;
   std::string ret_value;
 
-  if (const_value().GetWithoutPathExpansion(base::StringPiece(key), &out_value))
-    out_value->GetAsString(&ret_value);
+  const base::Value* value =
+      const_value().GetDict().Find(base::StringPiece(key.ToString()));
+  if (value && value->is_string()) {
+    ret_value = value->GetString();
+  }
 
   return ret_value;
 }
@@ -823,15 +916,12 @@
     const CefString& key) {
   CEF_VALUE_VERIFY_RETURN(false, nullptr);
 
-  const base::Value* out_value = nullptr;
-
-  if (const_value().GetWithoutPathExpansion(base::StringPiece(key),
-                                            &out_value) &&
-      out_value->is_blob()) {
-    base::Value* binary_value = const_cast<base::Value*>(out_value);
+  const base::Value* value =
+      const_value().GetDict().Find(base::StringPiece(key.ToString()));
+  if (value && value->is_blob()) {
+    base::Value* binary_value = const_cast<base::Value*>(value);
     return CefBinaryValueImpl::GetOrCreateRef(
-        binary_value, const_cast<base::DictionaryValue*>(&const_value()),
-        controller());
+        binary_value, mutable_value_unchecked(), controller());
   }
 
   return nullptr;
@@ -841,16 +931,12 @@
     const CefString& key) {
   CEF_VALUE_VERIFY_RETURN(false, nullptr);
 
-  const base::Value* out_value = nullptr;
-
-  if (const_value().GetWithoutPathExpansion(base::StringPiece(key),
-                                            &out_value) &&
-      out_value->is_dict()) {
-    base::DictionaryValue* dict_value = static_cast<base::DictionaryValue*>(
-        const_cast<base::Value*>(out_value));
+  const base::Value* value =
+      const_value().GetDict().Find(base::StringPiece(key.ToString()));
+  if (value && value->is_dict()) {
+    base::Value* dict_value = const_cast<base::Value*>(value);
     return CefDictionaryValueImpl::GetOrCreateRef(
-        dict_value, const_cast<base::DictionaryValue*>(&const_value()),
-        read_only(), controller());
+        dict_value, mutable_value_unchecked(), read_only(), controller());
   }
 
   return nullptr;
@@ -859,16 +945,12 @@
 CefRefPtr<CefListValue> CefDictionaryValueImpl::GetList(const CefString& key) {
   CEF_VALUE_VERIFY_RETURN(false, nullptr);
 
-  const base::Value* out_value = nullptr;
-
-  if (const_value().GetWithoutPathExpansion(base::StringPiece(key),
-                                            &out_value) &&
-      out_value->is_list()) {
-    base::ListValue* list_value =
-        static_cast<base::ListValue*>(const_cast<base::Value*>(out_value));
+  const base::Value* value =
+      const_value().GetDict().Find(base::StringPiece(key.ToString()));
+  if (value && value->is_list()) {
+    base::Value* list_value = const_cast<base::Value*>(value);
     return CefListValueImpl::GetOrCreateRef(
-        list_value, const_cast<base::DictionaryValue*>(&const_value()),
-        read_only(), controller());
+        list_value, mutable_value_unchecked(), read_only(), controller());
   }
 
   return nullptr;
@@ -881,40 +963,40 @@
   CefValueImpl* impl = static_cast<CefValueImpl*>(value.get());
   DCHECK(impl);
 
-  base::Value* new_value = impl->CopyOrDetachValue(controller());
-  base::Value* actual_value = SetInternal(key, new_value);
+  base::Value* actual_value =
+      SetInternal(key, impl->CopyOrDetachValue(controller()));
   impl->SwapValue(actual_value, mutable_value(), controller());
   return true;
 }
 
 bool CefDictionaryValueImpl::SetNull(const CefString& key) {
   CEF_VALUE_VERIFY_RETURN(true, false);
-  SetInternal(key, new base::Value());
+  SetInternal(key, std::make_unique<base::Value>());
   return true;
 }
 
 bool CefDictionaryValueImpl::SetBool(const CefString& key, bool value) {
   CEF_VALUE_VERIFY_RETURN(true, false);
-  SetInternal(key, new base::Value(value));
+  SetInternal(key, std::make_unique<base::Value>(value));
   return true;
 }
 
 bool CefDictionaryValueImpl::SetInt(const CefString& key, int value) {
   CEF_VALUE_VERIFY_RETURN(true, false);
-  SetInternal(key, new base::Value(value));
+  SetInternal(key, std::make_unique<base::Value>(value));
   return true;
 }
 
 bool CefDictionaryValueImpl::SetDouble(const CefString& key, double value) {
   CEF_VALUE_VERIFY_RETURN(true, false);
-  SetInternal(key, new base::Value(value));
+  SetInternal(key, std::make_unique<base::Value>(value));
   return true;
 }
 
 bool CefDictionaryValueImpl::SetString(const CefString& key,
                                        const CefString& value) {
   CEF_VALUE_VERIFY_RETURN(true, false);
-  SetInternal(key, new base::Value(value.ToString()));
+  SetInternal(key, std::make_unique<base::Value>(value.ToString()));
   return true;
 }
 
@@ -954,110 +1036,143 @@
 }
 
 bool CefDictionaryValueImpl::RemoveInternal(const CefString& key) {
-  std::unique_ptr<base::Value> out_value;
-  if (!mutable_value()->RemoveWithoutPathExpansion(base::StringPiece(key),
-                                                   &out_value)) {
+  // The ExtractKey() call below which removes the Value from the dictionary
+  // will return a new Value object with the moved contents of the Value that
+  // exists in the implementation std::map. Consequently we use FindKey() to
+  // retrieve the actual Value pointer as it current exists first, for later
+  // comparison purposes.
+  const base::Value* actual_value =
+      const_value().GetDict().Find(base::StringPiece(key.ToString()));
+  if (!actual_value) {
+    return false;
+  }
+
+  // |actual_value| is no longer valid after this call.
+  absl::optional<base::Value> out_value =
+      mutable_value()->GetDict().Extract(base::StringPiece(key.ToString()));
+  if (!out_value.has_value()) {
     return false;
   }
 
   // Remove the value.
-  controller()->Remove(out_value.get(), true);
+  controller()->Remove(const_cast<base::Value*>(actual_value), true);
 
   // Only list and dictionary types may have dependencies.
   if (out_value->is_list() || out_value->is_dict()) {
-    controller()->RemoveDependencies(out_value.get());
+    controller()->RemoveDependencies(const_cast<base::Value*>(actual_value));
   }
 
   return true;
 }
 
-base::Value* CefDictionaryValueImpl::SetInternal(const CefString& key,
-                                                 base::Value* value) {
+base::Value* CefDictionaryValueImpl::SetInternal(
+    const CefString& key,
+    std::unique_ptr<base::Value> value) {
   DCHECK(value);
+
   RemoveInternal(key);
-  mutable_value()->SetWithoutPathExpansion(
-      base::StringPiece(key), base::WrapUnique<base::Value>(value));
-  return value;
+
+  // base::Value now uses move semantics which means that Set() will move the
+  // contents of the passed-in base::Value instead of keeping the same object.
+  // Set() then returns the actual Value pointer as it currently exists.
+  base::Value* actual_value = mutable_value()->GetDict().Set(
+      base::StringPiece(key.ToString()), std::move(*value));
+  CHECK(actual_value);
+
+  // |value| will be deleted when this method returns. Update the controller to
+  // reference |actual_value| instead.
+  controller()->Swap(value.get(), actual_value);
+
+  return actual_value;
 }
 
-CefDictionaryValueImpl::CefDictionaryValueImpl(base::DictionaryValue* value,
+CefDictionaryValueImpl::CefDictionaryValueImpl(base::Value* value,
                                                void* parent_value,
                                                ValueMode value_mode,
                                                bool read_only,
                                                CefValueController* controller)
-    : CefValueBase<CefDictionaryValue, base::DictionaryValue>(value,
-                                                              parent_value,
-                                                              value_mode,
-                                                              read_only,
-                                                              controller) {}
+    : CefValueBase<CefDictionaryValue, base::Value>(value,
+                                                    parent_value,
+                                                    value_mode,
+                                                    read_only,
+                                                    controller) {
+  DCHECK(value->is_dict());
+}
 
 // CefListValueImpl implementation.
 
 // static
 CefRefPtr<CefListValue> CefListValue::Create() {
-  return new CefListValueImpl(new base::ListValue(), true, false);
+  return new CefListValueImpl(base::Value(base::Value::Type::LIST),
+                              /*read_only=*/false);
 }
 
 // static
 CefRefPtr<CefListValue> CefListValueImpl::GetOrCreateRef(
-    base::ListValue* value,
+    base::Value* value,
     void* parent_value,
     bool read_only,
     CefValueController* controller) {
   CefValueController::Object* object = controller->Get(value);
-  if (object)
+  if (object) {
     return static_cast<CefListValueImpl*>(object);
+  }
 
   return new CefListValueImpl(value, parent_value, CefListValueImpl::kReference,
                               read_only, controller);
 }
 
-CefListValueImpl::CefListValueImpl(base::ListValue* value,
+CefListValueImpl::CefListValueImpl(base::Value value, bool read_only)
+    : CefListValueImpl(new base::Value(std::move(value)),
+                       /*will_delete=*/true,
+                       read_only) {}
+
+CefListValueImpl::CefListValueImpl(base::Value::List value, bool read_only)
+    : CefListValueImpl(base::Value(std::move(value)), read_only) {}
+
+CefListValueImpl::CefListValueImpl(base::Value* value,
                                    bool will_delete,
                                    bool read_only)
-    : CefValueBase<CefListValue, base::ListValue>(
-          value,
-          nullptr,
-          will_delete ? kOwnerWillDelete : kOwnerNoDelete,
-          read_only,
-          nullptr) {}
+    : CefListValueImpl(value,
+                       nullptr,
+                       will_delete ? kOwnerWillDelete : kOwnerNoDelete,
+                       read_only,
+                       nullptr) {}
 
-base::ListValue* CefListValueImpl::CopyValue() {
-  CEF_VALUE_VERIFY_RETURN(false, nullptr);
-  return const_value().DeepCopy();
+base::Value CefListValueImpl::CopyValue() {
+  CEF_VALUE_VERIFY_RETURN(false, base::Value());
+  return const_value().Clone();
 }
 
-base::ListValue* CefListValueImpl::CopyOrDetachValue(
+std::unique_ptr<base::Value> CefListValueImpl::CopyOrDetachValue(
     CefValueController* new_controller) {
-  base::ListValue* new_value;
-
   if (!will_delete()) {
     // Copy the value.
-    new_value = CopyValue();
-  } else {
-    // Take ownership of the value.
-    new_value = Detach(new_controller);
+    return std::make_unique<base::Value>(CopyValue());
   }
 
-  DCHECK(new_value);
-  return new_value;
+  // Take ownership of the value.
+  auto value = base::WrapUnique(Detach(new_controller));
+  DCHECK(value.get());
+  return value;
 }
 
-bool CefListValueImpl::IsSameValue(const base::ListValue* that) {
+bool CefListValueImpl::IsSameValue(const base::Value* that) {
   CEF_VALUE_VERIFY_RETURN(false, false);
   return (&const_value() == that);
 }
 
-bool CefListValueImpl::IsEqualValue(const base::ListValue* that) {
+bool CefListValueImpl::IsEqualValue(const base::Value* that) {
   CEF_VALUE_VERIFY_RETURN(false, false);
-  return const_value().Equals(that);
+  return const_value() == *that;
 }
 
-base::ListValue* CefListValueImpl::GetValueUnsafe() {
-  if (!VerifyAttached())
+base::Value* CefListValueImpl::GetValueUnsafe() const {
+  if (!VerifyAttached()) {
     return nullptr;
+  }
   controller()->AssertLockAcquired();
-  return const_cast<base::ListValue*>(&const_value());
+  return mutable_value_unchecked();
 }
 
 bool CefListValueImpl::IsValid() {
@@ -1073,10 +1188,12 @@
 }
 
 bool CefListValueImpl::IsSame(CefRefPtr<CefListValue> that) {
-  if (!that.get())
+  if (!that.get()) {
     return false;
-  if (that.get() == this)
+  }
+  if (that.get() == this) {
     return true;
+  }
 
   CEF_VALUE_VERIFY_RETURN(false, false);
   return static_cast<CefListValueImpl*>(that.get())
@@ -1084,10 +1201,12 @@
 }
 
 bool CefListValueImpl::IsEqual(CefRefPtr<CefListValue> that) {
-  if (!that.get())
+  if (!that.get()) {
     return false;
-  if (that.get() == this)
+  }
+  if (that.get() == this) {
     return true;
+  }
 
   CEF_VALUE_VERIFY_RETURN(false, false);
   return static_cast<CefListValueImpl*>(that.get())
@@ -1097,29 +1216,33 @@
 CefRefPtr<CefListValue> CefListValueImpl::Copy() {
   CEF_VALUE_VERIFY_RETURN(false, nullptr);
 
-  return new CefListValueImpl(const_value().DeepCopy(), nullptr,
-                              CefListValueImpl::kOwnerWillDelete, false,
-                              nullptr);
+  return new CefListValueImpl(const_value().Clone(), /*read_only=*/false);
 }
 
 bool CefListValueImpl::SetSize(size_t size) {
   CEF_VALUE_VERIFY_RETURN(true, false);
 
-  size_t current_size = const_value().GetSize();
+  size_t current_size = const_value().GetList().size();
   if (size < current_size) {
     // Clean up any values above the requested size.
-    for (size_t i = current_size - 1; i >= size; --i)
+    for (size_t i = current_size - 1; i >= size; --i) {
       RemoveInternal(i);
+    }
   } else if (size > 0) {
     // Expand the list size.
-    mutable_value()->Set(size - 1, std::make_unique<base::Value>());
+    // TODO: This approach seems inefficient. See https://crbug.com/1187066#c17
+    // for background.
+    auto& list = mutable_value()->GetList();
+    while (list.size() < size) {
+      list.Append(base::Value());
+    }
   }
   return true;
 }
 
 size_t CefListValueImpl::GetSize() {
   CEF_VALUE_VERIFY_RETURN(false, 0);
-  return const_value().GetSize();
+  return const_value().GetList().size();
 }
 
 bool CefListValueImpl::Clear() {
@@ -1128,7 +1251,7 @@
   // Detach any dependent values.
   controller()->RemoveDependencies(mutable_value());
 
-  mutable_value()->Clear();
+  mutable_value()->GetList().clear();
   return true;
 }
 
@@ -1140,9 +1263,10 @@
 CefValueType CefListValueImpl::GetType(size_t index) {
   CEF_VALUE_VERIFY_RETURN(false, VTYPE_INVALID);
 
-  const base::Value* out_value = nullptr;
-  if (const_value().Get(index, &out_value)) {
-    switch (out_value->type()) {
+  const auto& list = const_value().GetList();
+  if (index < list.size()) {
+    const base::Value& value = list[index];
+    switch (value.type()) {
       case base::Value::Type::NONE:
         return VTYPE_NULL;
       case base::Value::Type::BOOLEAN:
@@ -1155,12 +1279,10 @@
         return VTYPE_STRING;
       case base::Value::Type::BINARY:
         return VTYPE_BINARY;
-      case base::Value::Type::DICTIONARY:
+      case base::Value::Type::DICT:
         return VTYPE_DICTIONARY;
       case base::Value::Type::LIST:
         return VTYPE_LIST;
-      case base::Value::Type::DEAD:
-        return VTYPE_INVALID;
     }
   }
 
@@ -1170,12 +1292,12 @@
 CefRefPtr<CefValue> CefListValueImpl::GetValue(size_t index) {
   CEF_VALUE_VERIFY_RETURN(false, nullptr);
 
-  const base::Value* out_value = nullptr;
-  if (const_value().Get(index, &out_value)) {
-    return CefValueImpl::GetOrCreateRefOrCopy(
-        const_cast<base::Value*>(out_value),
-        const_cast<base::ListValue*>(&const_value()), read_only(),
-        controller());
+  const auto& list = const_value().GetList();
+  if (index < list.size()) {
+    const base::Value& value = list[index];
+    return CefValueImpl::GetOrCreateRefOrCopy(const_cast<base::Value*>(&value),
+                                              mutable_value_unchecked(),
+                                              read_only(), controller());
   }
 
   return nullptr;
@@ -1184,11 +1306,14 @@
 bool CefListValueImpl::GetBool(size_t index) {
   CEF_VALUE_VERIFY_RETURN(false, false);
 
-  const base::Value* out_value = nullptr;
   bool ret_value = false;
-
-  if (const_value().Get(index, &out_value))
-    out_value->GetAsBoolean(&ret_value);
+  const auto& list = const_value().GetList();
+  if (index < list.size()) {
+    const base::Value& value = list[index];
+    if (value.is_bool()) {
+      ret_value = value.GetBool();
+    }
+  }
 
   return ret_value;
 }
@@ -1196,11 +1321,14 @@
 int CefListValueImpl::GetInt(size_t index) {
   CEF_VALUE_VERIFY_RETURN(false, 0);
 
-  const base::Value* out_value = nullptr;
   int ret_value = 0;
-
-  if (const_value().Get(index, &out_value))
-    out_value->GetAsInteger(&ret_value);
+  const auto& list = const_value().GetList();
+  if (index < list.size()) {
+    const base::Value& value = list[index];
+    if (value.is_int()) {
+      ret_value = value.GetInt();
+    }
+  }
 
   return ret_value;
 }
@@ -1208,11 +1336,14 @@
 double CefListValueImpl::GetDouble(size_t index) {
   CEF_VALUE_VERIFY_RETURN(false, 0);
 
-  const base::Value* out_value = nullptr;
   double ret_value = 0;
-
-  if (const_value().Get(index, &out_value))
-    out_value->GetAsDouble(&ret_value);
+  const auto& list = const_value().GetList();
+  if (index < list.size()) {
+    const base::Value& value = list[index];
+    if (value.is_double()) {
+      ret_value = value.GetDouble();
+    }
+  }
 
   return ret_value;
 }
@@ -1220,11 +1351,14 @@
 CefString CefListValueImpl::GetString(size_t index) {
   CEF_VALUE_VERIFY_RETURN(false, CefString());
 
-  const base::Value* out_value = nullptr;
   std::string ret_value;
-
-  if (const_value().Get(index, &out_value))
-    out_value->GetAsString(&ret_value);
+  const auto& list = const_value().GetList();
+  if (index < list.size()) {
+    const base::Value& value = list[index];
+    if (value.is_string()) {
+      ret_value = value.GetString();
+    }
+  }
 
   return ret_value;
 }
@@ -1232,13 +1366,13 @@
 CefRefPtr<CefBinaryValue> CefListValueImpl::GetBinary(size_t index) {
   CEF_VALUE_VERIFY_RETURN(false, nullptr);
 
-  const base::Value* out_value = nullptr;
-
-  if (const_value().Get(index, &out_value) && out_value->is_blob()) {
-    base::Value* binary_value = const_cast<base::Value*>(out_value);
-    return CefBinaryValueImpl::GetOrCreateRef(
-        binary_value, const_cast<base::ListValue*>(&const_value()),
-        controller());
+  const auto& list = const_value().GetList();
+  if (index < list.size()) {
+    base::Value& value = const_cast<base::Value&>(list[index]);
+    if (value.is_blob()) {
+      return CefBinaryValueImpl::GetOrCreateRef(
+          &value, mutable_value_unchecked(), controller());
+    }
   }
 
   return nullptr;
@@ -1247,14 +1381,13 @@
 CefRefPtr<CefDictionaryValue> CefListValueImpl::GetDictionary(size_t index) {
   CEF_VALUE_VERIFY_RETURN(false, nullptr);
 
-  const base::Value* out_value = nullptr;
-
-  if (const_value().Get(index, &out_value) && out_value->is_dict()) {
-    base::DictionaryValue* dict_value = static_cast<base::DictionaryValue*>(
-        const_cast<base::Value*>(out_value));
-    return CefDictionaryValueImpl::GetOrCreateRef(
-        dict_value, const_cast<base::ListValue*>(&const_value()), read_only(),
-        controller());
+  const auto& list = const_value().GetList();
+  if (index < list.size()) {
+    base::Value& value = const_cast<base::Value&>(list[index]);
+    if (value.is_dict()) {
+      return CefDictionaryValueImpl::GetOrCreateRef(
+          &value, mutable_value_unchecked(), read_only(), controller());
+    }
   }
 
   return nullptr;
@@ -1263,14 +1396,13 @@
 CefRefPtr<CefListValue> CefListValueImpl::GetList(size_t index) {
   CEF_VALUE_VERIFY_RETURN(false, nullptr);
 
-  const base::Value* out_value = nullptr;
-
-  if (const_value().Get(index, &out_value) && out_value->is_list()) {
-    base::ListValue* list_value =
-        static_cast<base::ListValue*>(const_cast<base::Value*>(out_value));
-    return CefListValueImpl::GetOrCreateRef(
-        list_value, const_cast<base::ListValue*>(&const_value()), read_only(),
-        controller());
+  const auto& list = const_value().GetList();
+  if (index < list.size()) {
+    base::Value& value = const_cast<base::Value&>(list[index]);
+    if (value.is_list()) {
+      return CefListValueImpl::GetOrCreateRef(&value, mutable_value_unchecked(),
+                                              read_only(), controller());
+    }
   }
 
   return nullptr;
@@ -1282,39 +1414,39 @@
   CefValueImpl* impl = static_cast<CefValueImpl*>(value.get());
   DCHECK(impl);
 
-  base::Value* new_value = impl->CopyOrDetachValue(controller());
-  base::Value* actual_value = SetInternal(index, new_value);
+  base::Value* actual_value =
+      SetInternal(index, impl->CopyOrDetachValue(controller()));
   impl->SwapValue(actual_value, mutable_value(), controller());
   return true;
 }
 
 bool CefListValueImpl::SetNull(size_t index) {
   CEF_VALUE_VERIFY_RETURN(true, false);
-  SetInternal(index, new base::Value());
+  SetInternal(index, std::make_unique<base::Value>());
   return true;
 }
 
 bool CefListValueImpl::SetBool(size_t index, bool value) {
   CEF_VALUE_VERIFY_RETURN(true, false);
-  SetInternal(index, new base::Value(value));
+  SetInternal(index, std::make_unique<base::Value>(value));
   return true;
 }
 
 bool CefListValueImpl::SetInt(size_t index, int value) {
   CEF_VALUE_VERIFY_RETURN(true, false);
-  SetInternal(index, new base::Value(value));
+  SetInternal(index, std::make_unique<base::Value>(value));
   return true;
 }
 
 bool CefListValueImpl::SetDouble(size_t index, double value) {
   CEF_VALUE_VERIFY_RETURN(true, false);
-  SetInternal(index, new base::Value(value));
+  SetInternal(index, std::make_unique<base::Value>(value));
   return true;
 }
 
 bool CefListValueImpl::SetString(size_t index, const CefString& value) {
   CEF_VALUE_VERIFY_RETURN(true, false);
-  SetInternal(index, new base::Value(value.ToString()));
+  SetInternal(index, std::make_unique<base::Value>(value.ToString()));
   return true;
 }
 
@@ -1352,60 +1484,75 @@
 }
 
 bool CefListValueImpl::RemoveInternal(size_t index) {
-  // base::Value now uses move semantics which means that Remove() will return
-  // a new base::Value object with the moved contents of the base::Value that
-  // exists in the implementation std::vector. Consequently we use Get() to
-  // retrieve the actual base::Value pointer as it exists in the std::vector.
-  const base::Value* actual_value = nullptr;
-  if (!const_value().Get(index, &actual_value))
+  auto& list = mutable_value()->GetList();
+  if (index >= list.size()) {
     return false;
-  DCHECK(actual_value);
+  }
 
-  std::unique_ptr<base::Value> out_value;
-  if (!mutable_value()->Remove(index, &out_value))
-    return false;
+  // The std::move() call below which removes the Value from the list will
+  // return a new Value object with the moved contents of the Value that exists
+  // in the implementation std::vector. Consequently we use operator[] to
+  // retrieve the actual Value pointer as it current exists first, for later
+  // comparison purposes.
+  const base::Value& actual_value = list[index];
+
+  // |actual_value| is no longer valid after this call.
+  auto out_value = std::move(list[index]);
+  list.erase(list.begin() + index);
 
   // Remove the value.
-  controller()->Remove(const_cast<base::Value*>(actual_value), true);
+  controller()->Remove(const_cast<base::Value*>(&actual_value), true);
 
   // Only list and dictionary types may have dependencies.
-  if (out_value->is_list() || out_value->is_dict()) {
-    controller()->RemoveDependencies(const_cast<base::Value*>(actual_value));
+  if (out_value.is_list() || out_value.is_dict()) {
+    controller()->RemoveDependencies(const_cast<base::Value*>(&actual_value));
   }
 
   return true;
 }
 
-base::Value* CefListValueImpl::SetInternal(size_t index, base::Value* value) {
+base::Value* CefListValueImpl::SetInternal(size_t index,
+                                           std::unique_ptr<base::Value> value) {
   DCHECK(value);
 
-  if (RemoveInternal(index))
-    mutable_value()->Insert(index, base::WrapUnique(value));
-  else
-    mutable_value()->Set(index, base::WrapUnique(value));
+  auto& list = mutable_value()->GetList();
+  if (RemoveInternal(index)) {
+    CHECK_LE(index, list.size());
+    list.Insert(list.begin() + index, std::move(*value));
+  } else {
+    if (index >= list.size()) {
+      // Expand the list size.
+      // TODO: This approach seems inefficient. See
+      // https://crbug.com/1187066#c17 for background.
+      while (list.size() <= index) {
+        list.Append(base::Value());
+      }
+    }
+    list[index] = std::move(*value);
+  }
 
   // base::Value now uses move semantics which means that Insert()/Set() will
   // move the contents of the passed-in base::Value instead of keeping the same
-  // object. Consequently we use Get() to retrieve the actual base::Value
+  // object. Consequently we use operator[] to retrieve the actual base::Value
   // pointer as it exists in the std::vector.
-  const base::Value* actual_value = nullptr;
-  const_value().Get(index, &actual_value);
-  DCHECK(actual_value);
+  const base::Value& actual_value = list[index];
 
-  // |value| will have been deleted at this point. Update the controller to
+  // |value| will be deleted when this method returns. Update the controller to
   // reference |actual_value| instead.
-  controller()->Swap(value, const_cast<base::Value*>(actual_value));
+  controller()->Swap(value.get(), const_cast<base::Value*>(&actual_value));
 
-  return const_cast<base::Value*>(actual_value);
+  return const_cast<base::Value*>(&actual_value);
 }
 
-CefListValueImpl::CefListValueImpl(base::ListValue* value,
+CefListValueImpl::CefListValueImpl(base::Value* value,
                                    void* parent_value,
                                    ValueMode value_mode,
                                    bool read_only,
                                    CefValueController* controller)
-    : CefValueBase<CefListValue, base::ListValue>(value,
-                                                  parent_value,
-                                                  value_mode,
-                                                  read_only,
-                                                  controller) {}
+    : CefValueBase<CefListValue, base::Value>(value,
+                                              parent_value,
+                                              value_mode,
+                                              read_only,
+                                              controller) {
+  DCHECK(value->is_list());
+}
diff --git a/src/libcef/common/values_impl.h b/src/libcef/common/values_impl.h
index d188411..17c91eb 100644
--- a/src/libcef/common/values_impl.h
+++ b/src/libcef/common/values_impl.h
@@ -6,6 +6,7 @@
 #define CEF_LIBCEF_COMMON_VALUES_IMPL_H_
 #pragma once
 
+#include <memory>
 #include <vector>
 
 #include "include/cef_values.h"
@@ -28,30 +29,37 @@
 
   // Take ownership of |value|. Do not pass in a value owned by something else
   // (use GetOrCreateRefOrCopy instead).
-  explicit CefValueImpl(base::Value* value);
+  explicit CefValueImpl(base::Value value);
 
   // Keep a reference to |value|.
   explicit CefValueImpl(CefRefPtr<CefBinaryValue> value);
   explicit CefValueImpl(CefRefPtr<CefDictionaryValue> value);
   explicit CefValueImpl(CefRefPtr<CefListValue> value);
 
+  CefValueImpl(const CefValueImpl&) = delete;
+  CefValueImpl& operator=(const CefValueImpl&) = delete;
+
   ~CefValueImpl() override;
 
   // Take ownership of |value|. Do not pass in a value owned by something else
   // (use GetOrCreateRefOrCopy or Set*() instead).
-  void SetValue(base::Value* value);
+  void SetValue(base::Value value);
+
+  // Return a copy of the value.
+  [[nodiscard]] base::Value CopyValue();
 
   // Copy a simple value or transfer ownership of a complex value. If ownership
   // of the value is tranferred then this object's internal reference to the
   // value will be updated and remain valid. base::Value now uses move semantics
   // so we need to perform the copy and swap in two steps.
-  base::Value* CopyOrDetachValue(CefValueController* new_controller);
+  [[nodiscard]] std::unique_ptr<base::Value> CopyOrDetachValue(
+      CefValueController* new_controller);
   void SwapValue(base::Value* new_value,
                  void* new_parent_value,
                  CefValueController* new_controller);
 
   // Returns a reference to the underlying data. Access must be protected by
-  // calling AcquireLock/ReleaseLock.
+  // calling AcquireLock/ReleaseLock (e.g. use ScopedLockedValue).
   base::Value* GetValueUnsafe() const;
 
   // CefValue methods.
@@ -85,17 +93,20 @@
     explicit ScopedLockedValue(CefRefPtr<CefValueImpl> impl) : impl_(impl) {
       impl_->AcquireLock();
     }
+
+    ScopedLockedValue(const ScopedLockedValue&) = delete;
+    ScopedLockedValue& operator=(const ScopedLockedValue&) = delete;
+
     ~ScopedLockedValue() { impl_->ReleaseLock(); }
 
     base::Value* value() const { return impl_->GetValueUnsafe(); }
 
    private:
     CefRefPtr<CefValueImpl> impl_;
-    DISALLOW_COPY_AND_ASSIGN(ScopedLockedValue);
   };
 
  private:
-  void SetValueInternal(base::Value* value);
+  void SetValueInternal(absl::optional<base::Value> value);
 
   // Returns the controller for the current value, if any.
   CefValueController* GetValueController() const;
@@ -116,7 +127,6 @@
   CefRefPtr<CefListValue> list_value_;
 
   IMPLEMENT_REFCOUNTING(CefValueImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefValueImpl);
 };
 
 // CefBinaryValue implementation
@@ -128,6 +138,10 @@
       void* parent_value,
       CefValueController* controller);
 
+  // Take ownership of |value|. Do not pass in a value owned by something else
+  // (use GetOrCreateRef or constructor variant with |will_delete| argument).
+  explicit CefBinaryValueImpl(base::Value value);
+
   // Reference an existing value (set |will_delete| to false) or take ownership
   // of an existing value (set |will_delete| to true). When referencing an
   // existing value you must explicitly call Detach(nullptr) when |value| is no
@@ -137,21 +151,25 @@
   CefBinaryValueImpl(base::Value* value, bool will_delete);
 
   // The data will always be copied.
-  CefBinaryValueImpl(char* data, size_t data_size);
+  explicit CefBinaryValueImpl(base::span<const uint8_t> value);
+
+  CefBinaryValueImpl(const CefBinaryValueImpl&) = delete;
+  CefBinaryValueImpl& operator=(const CefBinaryValueImpl&) = delete;
 
   // Return a copy of the value.
-  base::Value* CopyValue();
+  [[nodiscard]] base::Value CopyValue();
 
   // If this value is a reference then return a copy. Otherwise, detach and
   // transfer ownership of the value.
-  base::Value* CopyOrDetachValue(CefValueController* new_controller);
+  [[nodiscard]] std::unique_ptr<base::Value> CopyOrDetachValue(
+      CefValueController* new_controller);
 
   bool IsSameValue(const base::Value* that);
   bool IsEqualValue(const base::Value* that);
 
   // Returns the underlying value. Access must be protected by calling
   // lock/unlock on the controller.
-  base::Value* GetValueUnsafe();
+  base::Value* GetValueUnsafe() const;
 
   // CefBinaryValue methods.
   bool IsValid() override;
@@ -159,6 +177,7 @@
   bool IsSame(CefRefPtr<CefBinaryValue> that) override;
   bool IsEqual(CefRefPtr<CefBinaryValue> that) override;
   CefRefPtr<CefBinaryValue> Copy() override;
+  const void* GetRawData() override;
   size_t GetSize() override;
   size_t GetData(void* buffer, size_t buffer_size, size_t data_offset) override;
 
@@ -169,44 +188,49 @@
                      void* parent_value,
                      ValueMode value_mode,
                      CefValueController* controller);
-
-  DISALLOW_COPY_AND_ASSIGN(CefBinaryValueImpl);
 };
 
 // CefDictionaryValue implementation
 class CefDictionaryValueImpl
-    : public CefValueBase<CefDictionaryValue, base::DictionaryValue> {
+    : public CefValueBase<CefDictionaryValue, base::Value> {
  public:
   // Get or create a reference value.
   static CefRefPtr<CefDictionaryValue> GetOrCreateRef(
-      base::DictionaryValue* value,
+      base::Value* value,
       void* parent_value,
       bool read_only,
       CefValueController* controller);
 
+  // Take ownership of |value|. Do not pass in a value owned by something else
+  // (use GetOrCreateRef or constructor variant with |will_delete| argument).
+  CefDictionaryValueImpl(base::Value value, bool read_only);
+  CefDictionaryValueImpl(base::Value::Dict value, bool read_only);
+
   // Reference an existing value (set |will_delete| to false) or take ownership
   // of an existing value (set |will_delete| to true). When referencing an
   // existing value you must explicitly call Detach(nullptr) when |value| is no
   // longer valid. Use GetOrCreateRef instead of this constructor if |value| is
   // owned by some other object and you do not plan to explicitly call
   // Detach(nullptr).
-  CefDictionaryValueImpl(base::DictionaryValue* value,
-                         bool will_delete,
-                         bool read_only);
+  CefDictionaryValueImpl(base::Value* value, bool will_delete, bool read_only);
+
+  CefDictionaryValueImpl(const CefDictionaryValueImpl&) = delete;
+  CefDictionaryValueImpl& operator=(const CefDictionaryValueImpl&) = delete;
 
   // Return a copy of the value.
-  base::DictionaryValue* CopyValue();
+  [[nodiscard]] base::Value CopyValue();
 
   // If this value is a reference then return a copy. Otherwise, detach and
   // transfer ownership of the value.
-  base::DictionaryValue* CopyOrDetachValue(CefValueController* new_controller);
+  [[nodiscard]] std::unique_ptr<base::Value> CopyOrDetachValue(
+      CefValueController* new_controller);
 
-  bool IsSameValue(const base::DictionaryValue* that);
-  bool IsEqualValue(const base::DictionaryValue* that);
+  bool IsSameValue(const base::Value* that);
+  bool IsEqualValue(const base::Value* that);
 
   // Returns the underlying value. Access must be protected by calling
   // lock/unlock on the controller.
-  base::DictionaryValue* GetValueUnsafe();
+  base::Value* GetValueUnsafe() const;
 
   // CefDictionaryValue methods.
   bool IsValid() override;
@@ -243,48 +267,56 @@
 
  private:
   // See the CefValueBase constructor for usage.
-  CefDictionaryValueImpl(base::DictionaryValue* value,
+  CefDictionaryValueImpl(base::Value* value,
                          void* parent_value,
                          ValueMode value_mode,
                          bool read_only,
                          CefValueController* controller);
 
   bool RemoveInternal(const CefString& key);
-  base::Value* SetInternal(const CefString& key, base::Value* value);
-
-  DISALLOW_COPY_AND_ASSIGN(CefDictionaryValueImpl);
+  base::Value* SetInternal(const CefString& key,
+                           std::unique_ptr<base::Value> value);
 };
 
 // CefListValue implementation
-class CefListValueImpl : public CefValueBase<CefListValue, base::ListValue> {
+class CefListValueImpl : public CefValueBase<CefListValue, base::Value> {
  public:
   // Get or create a reference value.
-  static CefRefPtr<CefListValue> GetOrCreateRef(base::ListValue* value,
+  static CefRefPtr<CefListValue> GetOrCreateRef(base::Value* value,
                                                 void* parent_value,
                                                 bool read_only,
                                                 CefValueController* controller);
 
+  // Take ownership of |value|. Do not pass in a value owned by something else
+  // (use GetOrCreateRef or constructor variant with |will_delete| argument).
+  CefListValueImpl(base::Value value, bool read_only);
+  CefListValueImpl(base::Value::List value, bool read_only);
+
   // Reference an existing value (set |will_delete| to false) or take ownership
   // of an existing value (set |will_delete| to true). When referencing an
   // existing value you must explicitly call Detach(nullptr) when |value| is no
   // longer valid. Use GetOrCreateRef instead of this constructor if |value| is
   // owned by some other object and you do not plan to explicitly call
   // Detach(nullptr).
-  CefListValueImpl(base::ListValue* value, bool will_delete, bool read_only);
+  CefListValueImpl(base::Value* value, bool will_delete, bool read_only);
+
+  CefListValueImpl(const CefListValueImpl&) = delete;
+  CefListValueImpl& operator=(const CefListValueImpl&) = delete;
 
   // Return a copy of the value.
-  base::ListValue* CopyValue();
+  [[nodiscard]] base::Value CopyValue();
 
   // If this value is a reference then return a copy. Otherwise, detach and
   // transfer ownership of the value.
-  base::ListValue* CopyOrDetachValue(CefValueController* new_controller);
+  [[nodiscard]] std::unique_ptr<base::Value> CopyOrDetachValue(
+      CefValueController* new_controller);
 
-  bool IsSameValue(const base::ListValue* that);
-  bool IsEqualValue(const base::ListValue* that);
+  bool IsSameValue(const base::Value* that);
+  bool IsEqualValue(const base::Value* that);
 
   // Returns the underlying value. Access must be protected by calling
   // lock/unlock on the controller.
-  base::ListValue* GetValueUnsafe();
+  base::Value* GetValueUnsafe() const;
 
   // CefListValue methods.
   bool IsValid() override;
@@ -319,16 +351,14 @@
 
  private:
   // See the CefValueBase constructor for usage.
-  CefListValueImpl(base::ListValue* value,
+  CefListValueImpl(base::Value* value,
                    void* parent_value,
                    ValueMode value_mode,
                    bool read_only,
                    CefValueController* controller);
 
   bool RemoveInternal(size_t index);
-  base::Value* SetInternal(size_t index, base::Value* value);
-
-  DISALLOW_COPY_AND_ASSIGN(CefListValueImpl);
+  base::Value* SetInternal(size_t index, std::unique_ptr<base::Value> value);
 };
 
 #endif  // CEF_LIBCEF_COMMON_VALUES_IMPL_H_
diff --git a/src/libcef/common/waitable_event_impl.cc b/src/libcef/common/waitable_event_impl.cc
index 81217bb..2ead5e0 100644
--- a/src/libcef/common/waitable_event_impl.cc
+++ b/src/libcef/common/waitable_event_impl.cc
@@ -6,13 +6,14 @@
 
 #include "include/cef_task.h"
 
+#include "base/notreached.h"
 #include "base/time/time.h"
 
 namespace {
 
 bool AllowWait() {
   if (CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO)) {
-    NOTREACHED() << "waiting is not allowed on the current thread";
+    DCHECK(false) << "waiting is not allowed on the current thread";
     return false;
   }
   return true;
@@ -48,13 +49,15 @@
 }
 
 void CefWaitableEventImpl::Wait() {
-  if (!AllowWait())
+  if (!AllowWait()) {
     return;
+  }
   event_.Wait();
 }
 
-bool CefWaitableEventImpl::TimedWait(int64 max_ms) {
-  if (!AllowWait())
+bool CefWaitableEventImpl::TimedWait(int64_t max_ms) {
+  if (!AllowWait()) {
     return false;
-  return event_.TimedWait(base::TimeDelta::FromMilliseconds(max_ms));
+  }
+  return event_.TimedWait(base::Milliseconds(max_ms));
 }
diff --git a/src/libcef/common/waitable_event_impl.h b/src/libcef/common/waitable_event_impl.h
index 96908c1..13b6b0e 100644
--- a/src/libcef/common/waitable_event_impl.h
+++ b/src/libcef/common/waitable_event_impl.h
@@ -14,18 +14,20 @@
  public:
   CefWaitableEventImpl(bool automatic_reset, bool initially_signaled);
 
+  CefWaitableEventImpl(const CefWaitableEventImpl&) = delete;
+  CefWaitableEventImpl& operator=(const CefWaitableEventImpl&) = delete;
+
   // CefWaitableEvent methods:
   void Reset() override;
   void Signal() override;
   bool IsSignaled() override;
   void Wait() override;
-  bool TimedWait(int64 max_ms) override;
+  bool TimedWait(int64_t max_ms) override;
 
  private:
   base::WaitableEvent event_;
 
   IMPLEMENT_REFCOUNTING(CefWaitableEventImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefWaitableEventImpl);
 };
 
 #endif  // CEF_LIBCEF_COMMON_WAITABLE_EVENT_IMPL_H_
diff --git a/src/libcef/common/widevine_loader.cc b/src/libcef/common/widevine_loader.cc
deleted file mode 100644
index f2d9e30..0000000
--- a/src/libcef/common/widevine_loader.cc
+++ /dev/null
@@ -1,507 +0,0 @@
-// Copyright 2016 The Chromium Embedded Framework Authors. Portions 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 "libcef/common/widevine_loader.h"
-
-#if BUILDFLAG(ENABLE_WIDEVINE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
-
-#include "libcef/browser/context.h"
-#include "libcef/browser/thread_util.h"
-#include "libcef/common/cef_switches.h"
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/json/json_string_value_serializer.h"
-#include "base/memory/ptr_util.h"
-#include "base/native_library.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_split.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/browser/plugin_service_impl.h"
-#include "content/public/browser/cdm_registry.h"
-#include "content/public/common/cdm_info.h"
-#include "content/public/common/content_switches.h"
-#include "media/cdm/cdm_host_file.h"
-#include "media/cdm/supported_cdm_versions.h"
-#include "services/service_manager/embedder/switches.h"
-#include "services/service_manager/sandbox/switches.h"
-#include "third_party/widevine/cdm/widevine_cdm_common.h"  // nogncheck
-
-namespace {
-
-base::LazyInstance<CefWidevineLoader>::Leaky g_widevine_loader =
-    LAZY_INSTANCE_INITIALIZER;
-
-// Based on chrome/browser/component_updater/widevine_cdm_component_installer.cc
-
-// Name of the Widevine CDM OS in the component manifest.
-const char kWidevineCdmOs[] =
-#if defined(OS_MACOSX)
-    "mac";
-#elif defined(OS_WIN)
-    "win";
-#else  // OS_LINUX, etc. TODO(viettrungluu): Separate out Chrome OS and Android?
-    "linux";
-#endif
-
-// Name of the Widevine CDM architecture in the component manifest.
-const char kWidevineCdmArch[] =
-#if defined(ARCH_CPU_X86)
-    "ia32";  // This differs from the component updater which uses "x86".
-#elif defined(ARCH_CPU_X86_64)
-    "x64";
-#else  // TODO(viettrungluu): Support an ARM check?
-    "???";
-#endif
-
-// The CDM OS and architecture.
-const char kCdmOsName[] = "os";
-const char kCdmArchName[] = "arch";
-
-//  The CDM version (e.g. "1.4.8.903").
-const char kCdmVersionName[] = "version";
-
-// The CDM manifest includes several custom values, all beginning with "x-cdm-".
-// All values are strings.
-// All values that are lists are delimited by commas. No trailing commas.
-// For example, "1,2,4".
-const char kCdmValueDelimiter[] = ",";
-// The following entries are required.
-//  Interface versions are lists of integers (e.g. "1" or "1,2,4").
-//  These are checked in this file before registering the CDM.
-//  All match the interface versions from content_decryption_module.h that the
-//  CDM supports.
-//    Matches CDM_MODULE_VERSION.
-const char kCdmModuleVersionsName[] = "x-cdm-module-versions";
-//    Matches supported ContentDecryptionModule_* version(s).
-const char kCdmInterfaceVersionsName[] = "x-cdm-interface-versions";
-//    Matches supported Host_* version(s).
-const char kCdmHostVersionsName[] = "x-cdm-host-versions";
-//  The codecs list is a list of simple codec names (e.g. "vp8,vorbis").
-//  The list is passed to other parts of Chrome.
-const char kCdmCodecsListName[] = "x-cdm-codecs";
-//  Whether persistent license is supported by the CDM: "true" or "false".
-const char kCdmPersistentLicenseSupportName[] =
-    "x-cdm-persistent-license-support";
-const char kCdmSupportedEncryptionSchemesName[] =
-    "x-cdm-supported-encryption-schemes";
-
-// The following strings are used to specify supported codecs in the
-// parameter |kCdmCodecsListName|.
-const char kCdmSupportedCodecVp8[] = "vp8";
-const char kCdmSupportedCodecVp9[] = "vp9.0";
-#if BUILDFLAG(USE_PROPRIETARY_CODECS)
-const char kCdmSupportedCodecAvc1[] = "avc1";
-#endif
-
-// The following strings are used to specify supported encryption schemes in
-// the parameter |kCdmSupportedEncryptionSchemesName|.
-const char kCdmSupportedEncryptionSchemeCenc[] = "cenc";
-const char kCdmSupportedEncryptionSchemeCbcs[] = "cbcs";
-
-// Arguments passed to MakeCdmInfo.
-struct CdmInfoArgs {
-  base::FilePath path;
-  std::string version;
-  content::CdmCapability capability;
-};
-
-std::unique_ptr<base::DictionaryValue> ParseManifestFile(
-    const base::FilePath& manifest_path) {
-  CEF_REQUIRE_BLOCKING();
-
-  // Manifest file should be < 1kb. Read at most 2kb.
-  std::string manifest_contents;
-  if (!base::ReadFileToStringWithMaxSize(manifest_path, &manifest_contents,
-                                         2048)) {
-    return nullptr;
-  }
-
-  JSONStringValueDeserializer deserializer(manifest_contents);
-  std::unique_ptr<base::Value> manifest(
-      deserializer.Deserialize(nullptr, nullptr));
-
-  if (!manifest.get() || !manifest->is_dict())
-    return nullptr;
-
-  // Transfer ownership to the caller.
-  return base::WrapUnique(
-      static_cast<base::DictionaryValue*>(manifest.release()));
-}
-
-std::string GetManifestValue(const base::DictionaryValue& manifest,
-                             const std::string& key,
-                             std::string* error_message) {
-  std::stringstream ss;
-  std::string value;
-  if (!manifest.GetString(key, &value)) {
-    ss << "Manifest missing " << key;
-    *error_message = ss.str();
-  } else if (value.empty()) {
-    ss << "Manifest has empty " << key;
-    *error_message = ss.str();
-  }
-  return value;
-}
-
-typedef bool (*VersionCheckFunc)(int version);
-
-bool CheckForCompatibleVersion(const base::DictionaryValue& manifest,
-                               const std::string version_name,
-                               VersionCheckFunc version_check_func,
-                               std::string* error_message) {
-  std::string versions_string =
-      GetManifestValue(manifest, version_name, error_message);
-  if (versions_string.empty())
-    return false;
-
-  for (const base::StringPiece& ver_str :
-       base::SplitStringPiece(versions_string, kCdmValueDelimiter,
-                              base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
-    int version = 0;
-    if (base::StringToInt(ver_str, &version))
-      if (version_check_func(version))
-        return true;
-  }
-
-  std::stringstream ss;
-  ss << "Manifest has no supported " << version_name << " in '"
-     << versions_string << "'";
-  *error_message = ss.str();
-  return false;
-}
-
-// Returns whether the CDM's OS/platform and module/interface/host API versions,
-// as specified in the manifest, are compatible with this Chromium binary.
-bool IsCompatibleWithChrome(const base::DictionaryValue& manifest,
-                            std::string* error_message) {
-  return GetManifestValue(manifest, kCdmOsName, error_message) ==
-             kWidevineCdmOs &&
-         GetManifestValue(manifest, kCdmArchName, error_message) ==
-             kWidevineCdmArch &&
-         CheckForCompatibleVersion(manifest, kCdmModuleVersionsName,
-                                   media::IsSupportedCdmModuleVersion,
-                                   error_message) &&
-         CheckForCompatibleVersion(manifest, kCdmInterfaceVersionsName,
-                                   media::IsSupportedCdmInterfaceVersion,
-                                   error_message) &&
-         CheckForCompatibleVersion(manifest, kCdmHostVersionsName,
-                                   media::IsSupportedCdmHostVersion,
-                                   error_message);
-}
-
-// Returns true and updates |video_codecs| if the appropriate manifest entry is
-// valid. Returns false and does not modify |video_codecs| if the manifest entry
-// is incorrectly formatted.
-bool GetCodecs(const base::DictionaryValue& manifest,
-               std::vector<media::VideoCodec>* video_codecs,
-               std::string* error_message) {
-  DCHECK(video_codecs);
-
-  const base::Value* value = manifest.FindKey(kCdmCodecsListName);
-  if (!value) {
-    std::stringstream ss;
-    ss << "Widevine CDM component manifest is missing codecs.";
-    *error_message = ss.str();
-    return true;
-  }
-
-  if (!value->is_string()) {
-    std::stringstream ss;
-    ss << "Manifest entry " << kCdmCodecsListName << " is not a string.";
-    *error_message = ss.str();
-    return false;
-  }
-
-  const std::string& codecs = value->GetString();
-  if (codecs.empty()) {
-    std::stringstream ss;
-    ss << "Widevine CDM component manifest has empty codecs list.";
-    *error_message = ss.str();
-    return true;
-  }
-
-  std::vector<media::VideoCodec> result;
-  const std::vector<base::StringPiece> supported_codecs =
-      base::SplitStringPiece(codecs, kCdmValueDelimiter, base::TRIM_WHITESPACE,
-                             base::SPLIT_WANT_NONEMPTY);
-
-  for (const auto& codec : supported_codecs) {
-    if (codec == kCdmSupportedCodecVp8)
-      result.push_back(media::VideoCodec::kCodecVP8);
-    else if (codec == kCdmSupportedCodecVp9)
-      result.push_back(media::VideoCodec::kCodecVP9);
-#if BUILDFLAG(USE_PROPRIETARY_CODECS)
-    else if (codec == kCdmSupportedCodecAvc1)
-      result.push_back(media::VideoCodec::kCodecH264);
-#endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
-  }
-
-  video_codecs->swap(result);
-  return true;
-}
-
-// Returns true and updates |encryption_schemes| if the appropriate manifest
-// entry is valid. Returns false and does not modify |encryption_schemes| if the
-// manifest entry is incorrectly formatted. It is assumed that all CDMs support
-// 'cenc', so if the manifest entry is missing, the result will indicate support
-// for 'cenc' only. Incorrect types in the manifest entry will log the error and
-// fail. Unrecognized values will be reported but otherwise ignored.
-bool GetEncryptionSchemes(
-    const base::DictionaryValue& manifest,
-    base::flat_set<media::EncryptionScheme>* encryption_schemes,
-    std::string* error_message) {
-  DCHECK(encryption_schemes);
-
-  const base::Value* value =
-      manifest.FindKey(kCdmSupportedEncryptionSchemesName);
-  if (!value) {
-    // No manifest entry found, so assume only 'cenc' supported for backwards
-    // compatibility.
-    encryption_schemes->insert(media::EncryptionScheme::kCenc);
-    return true;
-  }
-
-  if (!value->is_list()) {
-    std::stringstream ss;
-    ss << "Manifest entry " << kCdmSupportedEncryptionSchemesName
-       << " is not a list.";
-    *error_message = ss.str();
-    return false;
-  }
-
-  const base::span<const base::Value> list = value->GetList();
-  base::flat_set<media::EncryptionScheme> result;
-  for (const auto& item : list) {
-    if (!item.is_string()) {
-      std::stringstream ss;
-      ss << "Unrecognized item type in manifest entry "
-         << kCdmSupportedEncryptionSchemesName;
-      *error_message = ss.str();
-      return false;
-    }
-
-    const std::string& scheme = item.GetString();
-    if (scheme == kCdmSupportedEncryptionSchemeCenc) {
-      result.insert(media::EncryptionScheme::kCenc);
-    } else if (scheme == kCdmSupportedEncryptionSchemeCbcs) {
-      result.insert(media::EncryptionScheme::kCbcs);
-    } else {
-      std::stringstream ss;
-      ss << "Unrecognized encryption scheme " << scheme << " in manifest entry "
-         << kCdmSupportedEncryptionSchemesName;
-      *error_message = ss.str();
-    }
-  }
-
-  // As the manifest entry exists, it must specify at least one valid value.
-  if (result.empty())
-    return false;
-
-  encryption_schemes->swap(result);
-  return true;
-}
-
-// Returns true and updates |session_types| if the appropriate manifest entry is
-// valid. Returns false if the manifest entry is incorrectly formatted.
-bool GetSessionTypes(const base::DictionaryValue& manifest,
-                     base::flat_set<media::CdmSessionType>* session_types,
-                     std::string* error_message) {
-  DCHECK(session_types);
-
-  bool is_persistent_license_supported = false;
-  const base::Value* value = manifest.FindKey(kCdmPersistentLicenseSupportName);
-  if (value) {
-    if (!value->is_bool())
-      return false;
-    is_persistent_license_supported = value->GetBool();
-  }
-
-  // Temporary session is always supported.
-  session_types->insert(media::CdmSessionType::kTemporary);
-  if (is_persistent_license_supported)
-    session_types->insert(media::CdmSessionType::kPersistentLicense);
-
-  return true;
-}
-
-// Verify and load the contents of |base_path|.
-cef_cdm_registration_error_t LoadWidevineCdmInfo(
-    const base::FilePath& base_path,
-    CdmInfoArgs* args,
-    std::string* error_message) {
-  std::stringstream ss;
-
-  args->path = base_path.AppendASCII(
-      base::GetNativeLibraryName(kWidevineCdmLibraryName));
-  if (!base::PathExists(args->path)) {
-    ss << "Missing file " << args->path.value();
-    *error_message = ss.str();
-    return CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS;
-  }
-
-  base::FilePath manifest_path = base_path.AppendASCII("manifest.json");
-  if (!base::PathExists(manifest_path)) {
-    ss << "Missing manifest file " << manifest_path.value();
-    *error_message = ss.str();
-    return CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS;
-  }
-
-  std::unique_ptr<base::DictionaryValue> manifest =
-      ParseManifestFile(manifest_path);
-  if (!manifest) {
-    ss << "Failed to parse manifest file " << manifest_path.value();
-    *error_message = ss.str();
-    return CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS;
-  }
-
-  if (!IsCompatibleWithChrome(*manifest, error_message))
-    return CEF_CDM_REGISTRATION_ERROR_INCOMPATIBLE;
-
-  args->version = GetManifestValue(*manifest, kCdmVersionName, error_message);
-  if (args->version.empty())
-    return CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS;
-
-  if (!GetCodecs(*manifest, &args->capability.video_codecs, error_message) ||
-      !GetEncryptionSchemes(*manifest, &args->capability.encryption_schemes,
-                            error_message) ||
-      !GetSessionTypes(*manifest, &args->capability.session_types,
-                       error_message)) {
-    return CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS;
-  }
-
-  return CEF_CDM_REGISTRATION_ERROR_NONE;
-}
-
-void DeliverWidevineCdmCallback(cef_cdm_registration_error_t result,
-                                const std::string& error_message,
-                                CefRefPtr<CefRegisterCdmCallback> callback) {
-  CEF_REQUIRE_UIT();
-
-  if (result != CEF_CDM_REGISTRATION_ERROR_NONE)
-    LOG(ERROR) << "Widevine CDM registration failed; " << error_message;
-  else if (!error_message.empty())
-    LOG(WARNING) << "Widevine CDM registration warning; " << error_message;
-
-  if (callback)
-    callback->OnCdmRegistrationComplete(result, error_message);
-}
-
-content::CdmInfo MakeCdmInfo(const CdmInfoArgs& args) {
-  return content::CdmInfo(kWidevineCdmDisplayName, kWidevineCdmGuid,
-                          base::Version(args.version), args.path,
-                          kWidevineCdmFileSystemId, args.capability,
-                          kWidevineKeySystem, false);
-}
-
-void RegisterWidevineCdmOnUIThread(std::unique_ptr<CdmInfoArgs> args,
-                                   CefRefPtr<CefRegisterCdmCallback> callback) {
-  CEF_REQUIRE_UIT();
-
-  // Register Widevine with the CdmRegistry.
-  content::CdmRegistry::GetInstance()->RegisterCdm(MakeCdmInfo(*args));
-
-  DeliverWidevineCdmCallback(CEF_CDM_REGISTRATION_ERROR_NONE, std::string(),
-                             callback);
-}
-
-void LoadWidevineCdmInfoOnBlockingThread(
-    const base::FilePath& base_path,
-    CefRefPtr<CefRegisterCdmCallback> callback) {
-  CEF_REQUIRE_BLOCKING();
-
-  std::unique_ptr<CdmInfoArgs> args = std::make_unique<CdmInfoArgs>();
-  std::string error_message;
-  cef_cdm_registration_error_t result =
-      LoadWidevineCdmInfo(base_path, args.get(), &error_message);
-  if (result != CEF_CDM_REGISTRATION_ERROR_NONE) {
-    CEF_POST_TASK(CEF_UIT, base::BindOnce(DeliverWidevineCdmCallback, result,
-                                          error_message, callback));
-    return;
-  }
-
-  // Continue execution on the UI thread.
-  CEF_POST_TASK(CEF_UIT, base::BindOnce(RegisterWidevineCdmOnUIThread,
-                                        std::move(args), callback));
-}
-
-}  // namespace
-
-// static
-CefWidevineLoader* CefWidevineLoader::GetInstance() {
-  return &g_widevine_loader.Get();
-}
-
-void CefWidevineLoader::LoadWidevineCdm(
-    const base::FilePath& path,
-    CefRefPtr<CefRegisterCdmCallback> callback) {
-  if (!CONTEXT_STATE_VALID()) {
-    // Loading will proceed from OnContextInitialized().
-    load_pending_ = true;
-    path_ = path;
-    callback_ = callback;
-    return;
-  }
-
-  CEF_POST_USER_VISIBLE_TASK(
-      base::BindOnce(LoadWidevineCdmInfoOnBlockingThread, path, callback));
-}
-
-void CefWidevineLoader::OnContextInitialized() {
-  CEF_REQUIRE_UIT();
-  if (load_pending_) {
-    load_pending_ = false;
-    LoadWidevineCdm(path_, callback_);
-    callback_ = nullptr;
-  }
-}
-
-#if defined(OS_LINUX)
-
-// static
-void CefWidevineLoader::AddContentDecryptionModules(
-    std::vector<content::CdmInfo>* cdms,
-    std::vector<media::CdmHostFilePath>* cdm_host_file_paths) {
-  const base::CommandLine& command_line =
-      *base::CommandLine::ForCurrentProcess();
-
-  // Perform early plugin registration in the zygote process when the sandbox is
-  // enabled to avoid "cannot open shared object file: Operation not permitted"
-  // errors during plugin loading. This is because the Zygote process must pre-
-  // load all plugins before initializing the sandbox.
-  if (command_line.GetSwitchValueASCII(switches::kProcessType) !=
-          service_manager::switches::kZygoteProcess ||
-      command_line.HasSwitch(service_manager::switches::kNoSandbox)) {
-    return;
-  }
-
-  // The Widevine CDM path is passed to the zygote process via
-  // CefContentBrowserClient::AppendExtraCommandLineSwitches.
-  const base::FilePath& base_path =
-      command_line.GetSwitchValuePath(switches::kWidevineCdmPath);
-  if (base_path.empty())
-    return;
-
-  // Load contents of the plugin directory synchronously. This only occurs once
-  // on zygote process startup so should not have a huge performance penalty.
-  CdmInfoArgs args;
-  std::string error_message;
-  cef_cdm_registration_error_t result =
-      LoadWidevineCdmInfo(base_path, &args, &error_message);
-  if (result != CEF_CDM_REGISTRATION_ERROR_NONE) {
-    LOG(ERROR) << "Widevine CDM registration failed; " << error_message;
-    return;
-  }
-
-  cdms->push_back(MakeCdmInfo(args));
-}
-
-#endif  // defined(OS_LINUX)
-
-CefWidevineLoader::CefWidevineLoader() {}
-
-CefWidevineLoader::~CefWidevineLoader() {}
-
-#endif  // BUILDFLAG(ENABLE_WIDEVINE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
diff --git a/src/libcef/common/widevine_loader.h b/src/libcef/common/widevine_loader.h
deleted file mode 100644
index fef829e..0000000
--- a/src/libcef/common/widevine_loader.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2016 The Chromium Embedded Framework 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 CEF_LIBCEF_COMMON_WIDEVINE_LOADER_H_
-#define CEF_LIBCEF_COMMON_WIDEVINE_LOADER_H_
-#pragma once
-
-#include "build/build_config.h"
-#include "media/media_buildflags.h"
-#include "third_party/widevine/cdm/buildflags.h"
-
-#if BUILDFLAG(ENABLE_WIDEVINE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
-
-#include <vector>
-
-#include "include/cef_web_plugin.h"
-
-#include "base/lazy_instance.h"
-
-namespace content {
-struct CdmInfo;
-}
-
-namespace media {
-struct CdmHostFilePath;
-}
-
-class CefWidevineLoader {
- public:
-  // Returns the singleton instance of this object.
-  static CefWidevineLoader* GetInstance();
-
-  // Load the Widevine CDM. May be called before or after context creation. See
-  // comments in cef_web_plugin.h.
-  void LoadWidevineCdm(const base::FilePath& path,
-                       CefRefPtr<CefRegisterCdmCallback> callback);
-
-  // Plugin registration is triggered here if LoadWidevineCdm() was called
-  // before context creation.
-  void OnContextInitialized();
-
-#if defined(OS_LINUX)
-  // The zygote process which is used when the sandbox is enabled on Linux
-  // requires early loading of CDM modules. Other processes will receive
-  // load notification in the usual way.
-  // Called from CefContentClient::AddContentDecryptionModules.
-  static void AddContentDecryptionModules(
-      std::vector<content::CdmInfo>* cdms,
-      std::vector<media::CdmHostFilePath>* cdm_host_file_paths);
-
-  const base::FilePath& path() { return path_; }
-#endif
-
- private:
-  friend struct base::LazyInstanceTraitsBase<CefWidevineLoader>;
-
-  // Members are only accessed before context initialization or on the UI
-  // thread.
-  bool load_pending_ = false;
-  base::FilePath path_;
-  CefRefPtr<CefRegisterCdmCallback> callback_;
-
-  CefWidevineLoader();
-  ~CefWidevineLoader();
-};
-
-#endif  // BUILDFLAG(ENABLE_WIDEVINE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
-
-#endif  // CEF_LIBCEF_COMMON_WIDEVINE_LOADER_H_
diff --git a/src/libcef/features/BUILD.gn b/src/libcef/features/BUILD.gn
index 01f5975..7968429 100644
--- a/src/libcef/features/BUILD.gn
+++ b/src/libcef/features/BUILD.gn
@@ -88,7 +88,12 @@
 # Configuration for all targets that include CEF source code library-side.
 config("config") {
   # CEF sources use includes relative to the CEF root directory.
-  include_dirs = [ "//cef" ]
+  include_dirs = [
+    "//cef",
+
+    # CEF generates some header files that also need to be discoverable.
+    "$root_build_dir/includes",
+  ]
   defines = [
     "BUILDING_CEF_SHARED",
     "USING_CHROMIUM_INCLUDES",
diff --git a/src/libcef/features/runtime.h b/src/libcef/features/runtime.h
new file mode 100644
index 0000000..f010d67
--- /dev/null
+++ b/src/libcef/features/runtime.h
@@ -0,0 +1,47 @@
+// Copyright 2020 The Chromium Embedded Framework 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 CEF_LIBCEF_FEATURES_RUNTIME_H_
+#define CEF_LIBCEF_FEATURES_RUNTIME_H_
+#pragma once
+
+#include "cef/libcef/features/features.h"
+
+namespace cef {
+
+#if BUILDFLAG(ENABLE_CEF)
+
+inline bool IsCefBuildEnabled() {
+  return true;
+}
+
+// True if CEF was initialized with the Alloy runtime.
+bool IsAlloyRuntimeEnabled();
+
+// True if CEF was initialized with the Chrome runtime.
+bool IsChromeRuntimeEnabled();
+
+// True if CEF crash reporting is enabled.
+bool IsCrashReportingEnabled();
+
+#else
+
+inline bool IsCefBuildEnabled() {
+  return false;
+}
+inline bool IsAlloyRuntimeEnabled() {
+  return false;
+}
+inline bool IsChromeRuntimeEnabled() {
+  return false;
+}
+inline bool IsCrashReportingEnabled() {
+  return false;
+}
+
+#endif
+
+}  // namespace cef
+
+#endif  // CEF_LIBCEF_FEATURES_RUNTIME_H_
diff --git a/src/libcef/features/runtime_checks.h b/src/libcef/features/runtime_checks.h
new file mode 100644
index 0000000..23f5c5e
--- /dev/null
+++ b/src/libcef/features/runtime_checks.h
@@ -0,0 +1,18 @@
+// Copyright 2020 The Chromium Embedded Framework 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 CEF_LIBCEF_FEATURES_RUNTIME_CHECKS_H_
+#define CEF_LIBCEF_FEATURES_RUNTIME_CHECKS_H_
+#pragma once
+
+#include "base/logging.h"
+#include "cef/libcef/features/runtime.h"
+
+#define REQUIRE_ALLOY_RUNTIME() \
+  CHECK(cef::IsAlloyRuntimeEnabled()) << "Alloy runtime is required"
+
+#define REQUIRE_CHROME_RUNTIME() \
+  CHECK(cef::IsChromeRuntimeEnabled()) << "Chrome runtime is required"
+
+#endif  // CEF_LIBCEF_FEATURES_RUNTIME_CHECKS_H_
diff --git a/src/libcef/renderer/alloy/alloy_content_renderer_client.cc b/src/libcef/renderer/alloy/alloy_content_renderer_client.cc
new file mode 100644
index 0000000..30ba04c
--- /dev/null
+++ b/src/libcef/renderer/alloy/alloy_content_renderer_client.cc
@@ -0,0 +1,586 @@
+// Copyright (c) 2013 The Chromium Embedded Framework Authors.
+// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/renderer/alloy/alloy_content_renderer_client.h"
+
+#include <utility>
+
+#include "build/build_config.h"
+
+// Enable deprecation warnings on Windows. See http://crbug.com/585142.
+#if BUILDFLAG(IS_WIN)
+#if defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic error "-Wdeprecated-declarations"
+#else
+#pragma warning(push)
+#pragma warning(default : 4996)
+#endif
+#endif
+
+#include "libcef/browser/alloy/alloy_content_browser_client.h"
+#include "libcef/browser/context.h"
+#include "libcef/common/alloy/alloy_content_client.h"
+#include "libcef/common/app_manager.h"
+#include "libcef/common/cef_switches.h"
+#include "libcef/common/extensions/extensions_client.h"
+#include "libcef/common/extensions/extensions_util.h"
+#include "libcef/common/request_impl.h"
+#include "libcef/features/runtime_checks.h"
+#include "libcef/renderer/alloy/alloy_render_thread_observer.h"
+#include "libcef/renderer/alloy/url_loader_throttle_provider_impl.h"
+#include "libcef/renderer/browser_impl.h"
+#include "libcef/renderer/extensions/extensions_renderer_client.h"
+#include "libcef/renderer/extensions/print_render_frame_helper_delegate.h"
+#include "libcef/renderer/render_frame_observer.h"
+#include "libcef/renderer/render_manager.h"
+#include "libcef/renderer/thread_util.h"
+
+#include "base/command_line.h"
+#include "base/memory/ptr_util.h"
+#include "base/metrics/user_metrics_action.h"
+#include "base/path_service.h"
+#include "base/process/current_process.h"
+#include "base/stl_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pdf_util.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/renderer/browser_exposed_renderer_interfaces.h"
+#include "chrome/renderer/chrome_content_renderer_client.h"
+#include "chrome/renderer/extensions/chrome_extensions_renderer_client.h"
+#include "chrome/renderer/loadtimes_extension_bindings.h"
+#include "chrome/renderer/media/chrome_key_systems.h"
+#include "chrome/renderer/plugins/chrome_plugin_placeholder.h"
+#include "components/content_settings/core/common/content_settings_types.h"
+#include "components/nacl/common/nacl_constants.h"
+#include "components/pdf/common/internal_plugin_helpers.h"
+#include "components/pdf/renderer/internal_plugin_renderer_helpers.h"
+#include "components/printing/renderer/print_render_frame_helper.h"
+#include "components/spellcheck/renderer/spellcheck.h"
+#include "components/spellcheck/renderer/spellcheck_provider.h"
+#include "components/visitedlink/renderer/visitedlink_reader.h"
+#include "components/web_cache/renderer/web_cache_impl.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/child/child_thread.h"
+#include "content/public/common/content_constants.h"
+#include "content/public/common/content_paths.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/renderer/render_frame.h"
+#include "extensions/common/manifest_handlers/csp_info.h"
+#include "extensions/common/switches.h"
+#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.h"
+#include "extensions/renderer/renderer_extension_registry.h"
+#include "ipc/ipc_sync_channel.h"
+#include "media/base/media.h"
+#include "mojo/public/cpp/bindings/binder_map.h"
+#include "mojo/public/cpp/bindings/generic_pending_receiver.h"
+#include "printing/print_settings.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
+#include "third_party/blink/public/platform/scheduler/web_renderer_process_type.h"
+#include "third_party/blink/public/platform/url_conversion.h"
+#include "third_party/blink/public/platform/web_runtime_features.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/public/web/web_console_message.h"
+#include "third_party/blink/public/web/web_element.h"
+#include "third_party/blink/public/web/web_frame.h"
+#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_script_controller.h"
+#include "third_party/blink/public/web/web_security_policy.h"
+#include "third_party/blink/public/web/web_view.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if BUILDFLAG(IS_MAC)
+#include "base/mac/mac_util.h"
+#include "base/strings/sys_string_conversions.h"
+#endif
+
+AlloyContentRendererClient::AlloyContentRendererClient()
+    : main_entry_time_(base::TimeTicks::Now()),
+      render_manager_(new CefRenderManager) {
+  if (extensions::ExtensionsEnabled()) {
+    extensions_client_.reset(new extensions::CefExtensionsClient);
+    extensions::ExtensionsClient::Set(extensions_client_.get());
+    extensions_renderer_client_ =
+        std::make_unique<extensions::CefExtensionsRendererClient>(this);
+    extensions::ExtensionsRendererClient::Set(
+        extensions_renderer_client_.get());
+  }
+}
+
+AlloyContentRendererClient::~AlloyContentRendererClient() {}
+
+// static
+AlloyContentRendererClient* AlloyContentRendererClient::Get() {
+  REQUIRE_ALLOY_RUNTIME();
+  return static_cast<AlloyContentRendererClient*>(
+      CefAppManager::Get()->GetContentClient()->renderer());
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+AlloyContentRendererClient::GetCurrentTaskRunner() {
+  // Check if currently on the render thread.
+  if (CEF_CURRENTLY_ON_RT()) {
+    return render_task_runner_;
+  }
+  return nullptr;
+}
+
+void AlloyContentRendererClient::RunSingleProcessCleanup() {
+  DCHECK(content::RenderProcessHost::run_renderer_in_process());
+
+  // Make sure the render thread was actually started.
+  if (!render_task_runner_.get()) {
+    return;
+  }
+
+  if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
+    RunSingleProcessCleanupOnUIThread();
+  } else {
+    CEF_POST_TASK(
+        CEF_UIT,
+        base::BindOnce(
+            &AlloyContentRendererClient::RunSingleProcessCleanupOnUIThread,
+            base::Unretained(this)));
+  }
+
+  // Wait for the render thread cleanup to complete. Spin instead of using
+  // base::WaitableEvent because calling Wait() is not allowed on the UI
+  // thread.
+  bool complete = false;
+  do {
+    {
+      base::AutoLock lock_scope(single_process_cleanup_lock_);
+      complete = single_process_cleanup_complete_;
+    }
+    if (!complete) {
+      base::PlatformThread::YieldCurrentThread();
+    }
+  } while (!complete);
+}
+
+void AlloyContentRendererClient::PostIOThreadCreated(
+    base::SingleThreadTaskRunner*) {
+  // TODO(cef): Enable these once the implementation supports it.
+  blink::WebRuntimeFeatures::EnableNotifications(false);
+  blink::WebRuntimeFeatures::EnablePushMessaging(false);
+}
+
+void AlloyContentRendererClient::RenderThreadStarted() {
+  const base::CommandLine* command_line =
+      base::CommandLine::ForCurrentProcess();
+
+  render_task_runner_ = base::SingleThreadTaskRunner::GetCurrentDefault();
+  observer_ = std::make_unique<AlloyRenderThreadObserver>();
+  web_cache_impl_ = std::make_unique<web_cache::WebCacheImpl>();
+  visited_link_slave_ = std::make_unique<visitedlink::VisitedLinkReader>();
+
+  content::RenderThread* thread = content::RenderThread::Get();
+
+  const bool is_extension = CefRenderManager::IsExtensionProcess();
+
+  thread->SetRendererProcessType(
+      is_extension
+          ? blink::scheduler::WebRendererProcessType::kExtensionRenderer
+          : blink::scheduler::WebRendererProcessType::kRenderer);
+
+  if (is_extension) {
+    // The process name was set to "Renderer" in RendererMain(). Update it to
+    // "Extension Renderer" to highlight that it's hosting an extension.
+    base::CurrentProcess::GetInstance().SetProcessType(
+        base::CurrentProcessType::PROCESS_RENDERER_EXTENSION);
+  }
+
+  thread->AddObserver(observer_.get());
+
+  if (!command_line->HasSwitch(switches::kDisableSpellChecking)) {
+    spellcheck_ = std::make_unique<SpellCheck>(this);
+  }
+
+  if (content::RenderProcessHost::run_renderer_in_process()) {
+    // When running in single-process mode register as a destruction observer
+    // on the render thread's MessageLoop.
+    base::CurrentThread::Get()->AddDestructionObserver(this);
+  }
+
+#if BUILDFLAG(IS_MAC)
+  {
+    base::apple::ScopedCFTypeRef<CFStringRef> key(
+        base::SysUTF8ToCFStringRef("NSScrollViewRubberbanding"));
+    base::apple::ScopedCFTypeRef<CFStringRef> value;
+
+    // If the command-line switch is specified then set the value that will be
+    // checked in RenderThreadImpl::Init(). Otherwise, remove the application-
+    // level value.
+    if (command_line->HasSwitch(switches::kDisableScrollBounce)) {
+      value.reset(base::SysUTF8ToCFStringRef("false"));
+    }
+
+    CFPreferencesSetAppValue(key, value, kCFPreferencesCurrentApplication);
+    CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
+  }
+#endif  // BUILDFLAG(IS_MAC)
+
+  if (extensions::ExtensionsEnabled()) {
+    extensions_renderer_client_->RenderThreadStarted();
+  }
+}
+
+void AlloyContentRendererClient::ExposeInterfacesToBrowser(
+    mojo::BinderMap* binders) {
+  auto task_runner = base::SequencedTaskRunner::GetCurrentDefault();
+
+  binders->Add<web_cache::mojom::WebCache>(
+      base::BindRepeating(&web_cache::WebCacheImpl::BindReceiver,
+                          base::Unretained(web_cache_impl_.get())),
+      task_runner);
+
+  binders->Add<visitedlink::mojom::VisitedLinkNotificationSink>(
+      visited_link_slave_->GetBindCallback(), task_runner);
+
+  if (spellcheck_) {
+    binders->Add<spellcheck::mojom::SpellChecker>(
+        base::BindRepeating(
+            [](SpellCheck* spellcheck,
+               mojo::PendingReceiver<spellcheck::mojom::SpellChecker>
+                   receiver) { spellcheck->BindReceiver(std::move(receiver)); },
+            base::Unretained(spellcheck_.get())),
+        task_runner);
+  }
+
+  render_manager_->ExposeInterfacesToBrowser(binders);
+}
+
+void AlloyContentRendererClient::RenderThreadConnected() {
+  // Register extensions last because it will trigger WebKit initialization.
+  blink::WebScriptController::RegisterExtension(
+      extensions_v8::LoadTimesExtension::Get());
+
+  render_manager_->RenderThreadConnected();
+}
+
+void AlloyContentRendererClient::RenderFrameCreated(
+    content::RenderFrame* render_frame) {
+  auto render_frame_observer = new CefRenderFrameObserver(render_frame);
+
+  if (extensions::ExtensionsEnabled()) {
+    extensions_renderer_client_->RenderFrameCreated(
+        render_frame, render_frame_observer->registry());
+
+    render_frame_observer->associated_interfaces()
+        ->AddInterface<extensions::mojom::MimeHandlerViewContainerManager>(
+            base::BindRepeating(
+                &extensions::MimeHandlerViewContainerManager::BindReceiver,
+                render_frame->GetRoutingID()));
+  }
+
+  const base::CommandLine* command_line =
+      base::CommandLine::ForCurrentProcess();
+  if (!command_line->HasSwitch(switches::kDisableSpellChecking)) {
+    new SpellCheckProvider(render_frame, spellcheck_.get(), this);
+  }
+
+  bool browser_created;
+  absl::optional<bool> is_windowless;
+  render_manager_->RenderFrameCreated(render_frame, render_frame_observer,
+                                      browser_created, is_windowless);
+  if (browser_created) {
+    OnBrowserCreated(render_frame->GetWebView(), is_windowless);
+  }
+
+  if (is_windowless.has_value()) {
+    new printing::PrintRenderFrameHelper(
+        render_frame,
+        base::WrapUnique(
+            new extensions::CefPrintRenderFrameHelperDelegate(*is_windowless)));
+  }
+}
+
+void AlloyContentRendererClient::WebViewCreated(
+    blink::WebView* web_view,
+    bool was_created_by_renderer,
+    const url::Origin* outermost_origin) {
+  bool browser_created;
+  absl::optional<bool> is_windowless;
+  render_manager_->WebViewCreated(web_view, browser_created, is_windowless);
+  if (browser_created) {
+    OnBrowserCreated(web_view, is_windowless);
+  }
+}
+
+bool AlloyContentRendererClient::IsPluginHandledExternally(
+    content::RenderFrame* render_frame,
+    const blink::WebElement& plugin_element,
+    const GURL& original_url,
+    const std::string& mime_type) {
+  if (!extensions::ExtensionsEnabled()) {
+    return false;
+  }
+
+  DCHECK(plugin_element.HasHTMLTagName("object") ||
+         plugin_element.HasHTMLTagName("embed"));
+  // Blink will next try to load a WebPlugin which would end up in
+  // OverrideCreatePlugin, sending another IPC only to find out the plugin is
+  // not supported. Here it suffices to return false but there should perhaps be
+  // a more unified approach to avoid sending the IPC twice.
+  chrome::mojom::PluginInfoPtr plugin_info = chrome::mojom::PluginInfo::New();
+  ChromeContentRendererClient::GetPluginInfoHost()->GetPluginInfo(
+      original_url, render_frame->GetWebFrame()->Top()->GetSecurityOrigin(),
+      mime_type, &plugin_info);
+  // TODO(ekaramad): Not continuing here due to a disallowed status should take
+  // us to CreatePlugin. See if more in depths investigation of |status| is
+  // necessary here (see https://crbug.com/965747). For now, returning false
+  // should take us to CreatePlugin after HTMLPlugInElement which is called
+  // through HTMLPlugInElement::LoadPlugin code path.
+  if (plugin_info->status != chrome::mojom::PluginStatus::kAllowed &&
+      plugin_info->status !=
+          chrome::mojom::PluginStatus::kPlayImportantContent) {
+    // We could get here when a MimeHandlerView is loaded inside a <webview>
+    // which is using permissions API (see WebViewPluginTests).
+    ChromeExtensionsRendererClient::DidBlockMimeHandlerViewForDisallowedPlugin(
+        plugin_element);
+    return false;
+  }
+  if (plugin_info->actual_mime_type == pdf::kInternalPluginMimeType) {
+    // Only actually treat the internal PDF plugin as externally handled if
+    // used within an origin allowed to create the internal PDF plugin;
+    // otherwise, let Blink try to create the in-process PDF plugin.
+    if (IsPdfInternalPluginAllowedOrigin(
+            render_frame->GetWebFrame()->GetSecurityOrigin())) {
+      return true;
+    }
+  }
+  return ChromeExtensionsRendererClient::MaybeCreateMimeHandlerView(
+      plugin_element, original_url, plugin_info->actual_mime_type,
+      plugin_info->plugin);
+}
+
+bool AlloyContentRendererClient::OverrideCreatePlugin(
+    content::RenderFrame* render_frame,
+    const blink::WebPluginParams& params,
+    blink::WebPlugin** plugin) {
+  std::string orig_mime_type = params.mime_type.Utf8();
+  if (extensions::ExtensionsEnabled() &&
+      !extensions_renderer_client_->OverrideCreatePlugin(render_frame,
+                                                         params)) {
+    return false;
+  }
+
+  GURL url(params.url);
+  chrome::mojom::PluginInfoPtr plugin_info = chrome::mojom::PluginInfo::New();
+  ChromeContentRendererClient::GetPluginInfoHost()->GetPluginInfo(
+      url, render_frame->GetWebFrame()->Top()->GetSecurityOrigin(),
+      orig_mime_type, &plugin_info);
+  *plugin = ChromeContentRendererClient::CreatePlugin(render_frame, params,
+                                                      *plugin_info);
+  return true;
+}
+
+void AlloyContentRendererClient::WillSendRequest(
+    blink::WebLocalFrame* frame,
+    ui::PageTransition transition_type,
+    const blink::WebURL& url,
+    const net::SiteForCookies& site_for_cookies,
+    const url::Origin* initiator_origin,
+    GURL* new_url) {
+  if (extensions::ExtensionsEnabled()) {
+    extensions_renderer_client_->WillSendRequest(frame, transition_type, url,
+                                                 site_for_cookies,
+                                                 initiator_origin, new_url);
+    if (!new_url->is_empty()) {
+      return;
+    }
+  }
+}
+
+uint64_t AlloyContentRendererClient::VisitedLinkHash(const char* canonical_url,
+                                                     size_t length) {
+  return visited_link_slave_->ComputeURLFingerprint(canonical_url, length);
+}
+
+bool AlloyContentRendererClient::IsLinkVisited(uint64_t link_hash) {
+  return visited_link_slave_->IsVisited(link_hash);
+}
+
+bool AlloyContentRendererClient::IsOriginIsolatedPepperPlugin(
+    const base::FilePath& plugin_path) {
+  // Isolate all the plugins (including the PDF plugin).
+  return true;
+}
+
+void AlloyContentRendererClient::GetSupportedKeySystems(
+    media::GetSupportedKeySystemsCB cb) {
+  GetChromeKeySystems(std::move(cb));
+}
+
+void AlloyContentRendererClient::RunScriptsAtDocumentStart(
+    content::RenderFrame* render_frame) {
+  if (extensions::ExtensionsEnabled()) {
+    extensions_renderer_client_->RunScriptsAtDocumentStart(render_frame);
+  }
+}
+
+void AlloyContentRendererClient::RunScriptsAtDocumentEnd(
+    content::RenderFrame* render_frame) {
+  if (extensions::ExtensionsEnabled()) {
+    extensions_renderer_client_->RunScriptsAtDocumentEnd(render_frame);
+  }
+}
+
+void AlloyContentRendererClient::RunScriptsAtDocumentIdle(
+    content::RenderFrame* render_frame) {
+  if (extensions::ExtensionsEnabled()) {
+    extensions_renderer_client_->RunScriptsAtDocumentIdle(render_frame);
+  }
+}
+
+void AlloyContentRendererClient::DevToolsAgentAttached() {
+  // WebWorkers may be creating agents on a different thread.
+  if (!render_task_runner_->BelongsToCurrentThread()) {
+    render_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&AlloyContentRendererClient::DevToolsAgentAttached,
+                       base::Unretained(this)));
+    return;
+  }
+
+  render_manager_->DevToolsAgentAttached();
+}
+
+void AlloyContentRendererClient::DevToolsAgentDetached() {
+  // WebWorkers may be creating agents on a different thread.
+  if (!render_task_runner_->BelongsToCurrentThread()) {
+    render_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&AlloyContentRendererClient::DevToolsAgentDetached,
+                       base::Unretained(this)));
+    return;
+  }
+
+  render_manager_->DevToolsAgentDetached();
+}
+
+std::unique_ptr<blink::URLLoaderThrottleProvider>
+AlloyContentRendererClient::CreateURLLoaderThrottleProvider(
+    blink::URLLoaderThrottleProviderType provider_type) {
+  return std::make_unique<CefURLLoaderThrottleProviderImpl>(provider_type,
+                                                            this);
+}
+
+void AlloyContentRendererClient::AppendContentSecurityPolicy(
+    const blink::WebURL& url,
+    blink::WebVector<blink::WebContentSecurityPolicyHeader>* csp) {
+  if (!extensions::ExtensionsEnabled()) {
+    return;
+  }
+
+  // Don't apply default CSP to PDF renderers.
+  // TODO(crbug.com/1252096): Lock down the CSP once style and script are no
+  // longer injected inline by `pdf::PluginResponseWriter`. That class may be a
+  // better place to define such CSP, or we may continue doing so here.
+  if (pdf::IsPdfRenderer()) {
+    return;
+  }
+
+  DCHECK(csp);
+  GURL gurl(url);
+  const extensions::Extension* extension =
+      extensions::RendererExtensionRegistry::Get()->GetExtensionOrAppByURL(
+          gurl);
+  if (!extension) {
+    return;
+  }
+
+  // Append a minimum CSP to ensure the extension can't relax the default
+  // applied CSP through means like Service Worker.
+  const std::string* default_csp =
+      extensions::CSPInfo::GetMinimumCSPToAppend(*extension, gurl.path());
+  if (!default_csp) {
+    return;
+  }
+
+  csp->push_back({blink::WebString::FromUTF8(*default_csp),
+                  network::mojom::ContentSecurityPolicyType::kEnforce,
+                  network::mojom::ContentSecurityPolicySource::kHTTP});
+}
+
+void AlloyContentRendererClient::GetInterface(
+    const std::string& interface_name,
+    mojo::ScopedMessagePipeHandle interface_pipe) {
+  // TODO(crbug.com/977637): Get rid of the use of this implementation of
+  // |service_manager::LocalInterfaceProvider|. This was done only to avoid
+  // churning spellcheck code while eliminating the "chrome" and
+  // "chrome_renderer" services. Spellcheck is (and should remain) the only
+  // consumer of this implementation.
+  content::RenderThread::Get()->BindHostReceiver(
+      mojo::GenericPendingReceiver(interface_name, std::move(interface_pipe)));
+}
+
+void AlloyContentRendererClient::WillDestroyCurrentMessageLoop() {
+  base::AutoLock lock_scope(single_process_cleanup_lock_);
+  single_process_cleanup_complete_ = true;
+}
+
+void AlloyContentRendererClient::OnBrowserCreated(
+    blink::WebView* web_view,
+    absl::optional<bool> is_windowless) {
+#if BUILDFLAG(IS_MAC)
+  const bool windowless = is_windowless.has_value() && *is_windowless;
+
+  // FIXME: It would be better if this API would be a callback from the
+  // WebKit layer, or if it would be exposed as an WebView instance method; the
+  // current implementation uses a static variable, and WebKit needs to be
+  // patched in order to make it work for each WebView instance
+  web_view->SetUseExternalPopupMenusThisInstance(!windowless);
+#endif
+}
+
+void AlloyContentRendererClient::RunSingleProcessCleanupOnUIThread() {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  // Clean up the single existing RenderProcessHost.
+  content::RenderProcessHost* host = nullptr;
+  content::RenderProcessHost::iterator iterator(
+      content::RenderProcessHost::AllHostsIterator());
+  if (!iterator.IsAtEnd()) {
+    host = iterator.GetCurrentValue();
+    host->Cleanup();
+    iterator.Advance();
+    DCHECK(iterator.IsAtEnd());
+  }
+  DCHECK(host);
+
+  // Clear the run_renderer_in_process() flag to avoid a DCHECK in the
+  // RenderProcessHost destructor.
+  content::RenderProcessHost::SetRunRendererInProcess(false);
+
+  // Deletion of the RenderProcessHost object will stop the render thread and
+  // result in a call to WillDestroyCurrentMessageLoop.
+  // Cleanup() will cause deletion to be posted as a task on the UI thread but
+  // this task will only execute when running in multi-threaded message loop
+  // mode (because otherwise the UI message loop has already stopped). Therefore
+  // we need to explicitly delete the object when not running in this mode.
+  if (!CefContext::Get()->settings().multi_threaded_message_loop) {
+    delete host;
+  }
+}
+
+// Enable deprecation warnings on Windows. See http://crbug.com/585142.
+#if BUILDFLAG(IS_WIN)
+#if defined(__clang__)
+#pragma GCC diagnostic pop
+#else
+#pragma warning(pop)
+#endif
+#endif
diff --git a/src/libcef/renderer/alloy/alloy_content_renderer_client.h b/src/libcef/renderer/alloy/alloy_content_renderer_client.h
new file mode 100644
index 0000000..74c9a69
--- /dev/null
+++ b/src/libcef/renderer/alloy/alloy_content_renderer_client.h
@@ -0,0 +1,156 @@
+// Copyright (c) 2013 The Chromium Embedded Framework Authors.
+// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_RENDERER_ALLOY_ALLOY_CONTENT_RENDERER_CLIENT_H_
+#define CEF_LIBCEF_RENDERER_ALLOY_ALLOY_CONTENT_RENDERER_CLIENT_H_
+#pragma once
+
+#include <list>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "libcef/renderer/browser_impl.h"
+
+#include "base/task/current_thread.h"
+#include "base/task/single_thread_task_runner.h"
+#include "chrome/common/plugin.mojom.h"
+#include "content/public/renderer/content_renderer_client.h"
+#include "content/public/renderer/render_thread.h"
+#include "mojo/public/cpp/bindings/generic_pending_receiver.h"
+#include "services/service_manager/public/cpp/local_interface_provider.h"
+
+namespace extensions {
+class CefExtensionsRendererClient;
+class Dispatcher;
+class DispatcherDelegate;
+class ExtensionsClient;
+class ExtensionsRendererClient;
+class ResourceRequestPolicy;
+}  // namespace extensions
+
+namespace visitedlink {
+class VisitedLinkReader;
+}
+
+namespace web_cache {
+class WebCacheImpl;
+}
+
+class AlloyRenderThreadObserver;
+class CefRenderManager;
+class SpellCheck;
+
+class AlloyContentRendererClient
+    : public content::ContentRendererClient,
+      public service_manager::LocalInterfaceProvider,
+      public base::CurrentThread::DestructionObserver {
+ public:
+  AlloyContentRendererClient();
+
+  AlloyContentRendererClient(const AlloyContentRendererClient&) = delete;
+  AlloyContentRendererClient& operator=(const AlloyContentRendererClient&) =
+      delete;
+
+  ~AlloyContentRendererClient() override;
+
+  // Returns the singleton AlloyContentRendererClient instance.
+  // This method is deprecated and should not be used in new callsites.
+  static AlloyContentRendererClient* Get();
+
+  // Render thread task runner.
+  base::SingleThreadTaskRunner* render_task_runner() const {
+    return render_task_runner_.get();
+  }
+
+  // Returns the task runner for the current thread. Returns NULL if the current
+  // thread is not the main render process thread.
+  scoped_refptr<base::SingleThreadTaskRunner> GetCurrentTaskRunner();
+
+  // Perform cleanup work that needs to occur before shutdown when running in
+  // single-process mode. Blocks until cleanup is complete.
+  void RunSingleProcessCleanup();
+
+  // ContentRendererClient implementation.
+  void PostIOThreadCreated(
+      base::SingleThreadTaskRunner* io_thread_task_runner) override;
+  void RenderThreadStarted() override;
+  void ExposeInterfacesToBrowser(mojo::BinderMap* binders) override;
+  void RenderThreadConnected() override;
+  void RenderFrameCreated(content::RenderFrame* render_frame) override;
+  void WebViewCreated(blink::WebView* web_view,
+                      bool was_created_by_renderer,
+                      const url::Origin* outermost_origin) override;
+  bool IsPluginHandledExternally(content::RenderFrame* render_frame,
+                                 const blink::WebElement& plugin_element,
+                                 const GURL& original_url,
+                                 const std::string& mime_type) override;
+  bool OverrideCreatePlugin(content::RenderFrame* render_frame,
+                            const blink::WebPluginParams& params,
+                            blink::WebPlugin** plugin) override;
+  void WillSendRequest(blink::WebLocalFrame* frame,
+                       ui::PageTransition transition_type,
+                       const blink::WebURL& url,
+                       const net::SiteForCookies& site_for_cookies,
+                       const url::Origin* initiator_origin,
+                       GURL* new_url) override;
+  uint64_t VisitedLinkHash(const char* canonical_url, size_t length) override;
+  bool IsLinkVisited(uint64_t link_hash) override;
+  bool IsOriginIsolatedPepperPlugin(const base::FilePath& plugin_path) override;
+  void GetSupportedKeySystems(media::GetSupportedKeySystemsCB cb) override;
+  void RunScriptsAtDocumentStart(content::RenderFrame* render_frame) override;
+  void RunScriptsAtDocumentEnd(content::RenderFrame* render_frame) override;
+  void RunScriptsAtDocumentIdle(content::RenderFrame* render_frame) override;
+  void DevToolsAgentAttached() override;
+  void DevToolsAgentDetached() override;
+  std::unique_ptr<blink::URLLoaderThrottleProvider>
+  CreateURLLoaderThrottleProvider(
+      blink::URLLoaderThrottleProviderType provider_type) override;
+  void AppendContentSecurityPolicy(
+      const blink::WebURL& url,
+      blink::WebVector<blink::WebContentSecurityPolicyHeader>* csp) override;
+
+  // service_manager::LocalInterfaceProvider implementation.
+  void GetInterface(const std::string& name,
+                    mojo::ScopedMessagePipeHandle request_handle) override;
+
+  // MessageLoopCurrent::DestructionObserver implementation.
+  void WillDestroyCurrentMessageLoop() override;
+
+  AlloyRenderThreadObserver* GetAlloyObserver() const {
+    return observer_.get();
+  }
+
+ private:
+  void OnBrowserCreated(blink::WebView* web_view,
+                        absl::optional<bool> is_windowless);
+
+  // Perform cleanup work for single-process mode.
+  void RunSingleProcessCleanupOnUIThread();
+
+  // Time at which this object was created. This is very close to the time at
+  // which the RendererMain function was entered.
+  base::TimeTicks main_entry_time_;
+
+  std::unique_ptr<CefRenderManager> render_manager_;
+
+  scoped_refptr<base::SingleThreadTaskRunner> render_task_runner_;
+  std::unique_ptr<AlloyRenderThreadObserver> observer_;
+  std::unique_ptr<web_cache::WebCacheImpl> web_cache_impl_;
+  std::unique_ptr<SpellCheck> spellcheck_;
+  std::unique_ptr<visitedlink::VisitedLinkReader> visited_link_slave_;
+
+  std::unique_ptr<extensions::ExtensionsClient> extensions_client_;
+  std::unique_ptr<extensions::CefExtensionsRendererClient>
+      extensions_renderer_client_;
+
+  // Used in single-process mode to test when cleanup is complete.
+  // Access must be protected by |single_process_cleanup_lock_|.
+  bool single_process_cleanup_complete_ = false;
+  base::Lock single_process_cleanup_lock_;
+};
+
+#endif  // CEF_LIBCEF_RENDERER_ALLOY_ALLOY_CONTENT_RENDERER_CLIENT_H_
diff --git a/src/libcef/renderer/alloy/alloy_render_thread_observer.cc b/src/libcef/renderer/alloy/alloy_render_thread_observer.cc
new file mode 100644
index 0000000..37c6e35
--- /dev/null
+++ b/src/libcef/renderer/alloy/alloy_render_thread_observer.cc
@@ -0,0 +1,68 @@
+/// Copyright (c) 2013 The Chromium Embedded Framework Authors.
+// Portions (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/renderer/alloy/alloy_render_thread_observer.h"
+
+#include "libcef/common/net/net_resource_provider.h"
+
+#include "base/no_destructor.h"
+#include "chrome/common/renderer_configuration.mojom.h"
+#include "net/base/net_module.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
+
+AlloyRenderThreadObserver::AlloyRenderThreadObserver() {
+  net::NetModule::SetResourceProvider(NetResourceProvider);
+}
+
+AlloyRenderThreadObserver::~AlloyRenderThreadObserver() {}
+
+chrome::mojom::DynamicParamsPtr AlloyRenderThreadObserver::GetDynamicParams()
+    const {
+  {
+    base::AutoLock lock(dynamic_params_lock_);
+    if (dynamic_params_) {
+      return dynamic_params_.Clone();
+    }
+  }
+  return chrome::mojom::DynamicParams::New();
+}
+
+void AlloyRenderThreadObserver::RegisterMojoInterfaces(
+    blink::AssociatedInterfaceRegistry* associated_interfaces) {
+  associated_interfaces->AddInterface<chrome::mojom::RendererConfiguration>(
+      base::BindRepeating(
+          &AlloyRenderThreadObserver::OnRendererConfigurationAssociatedRequest,
+          base::Unretained(this)));
+}
+
+void AlloyRenderThreadObserver::UnregisterMojoInterfaces(
+    blink::AssociatedInterfaceRegistry* associated_interfaces) {
+  associated_interfaces->RemoveInterface(
+      chrome::mojom::RendererConfiguration::Name_);
+}
+
+void AlloyRenderThreadObserver::SetInitialConfiguration(
+    bool is_incognito_process,
+    mojo::PendingReceiver<chrome::mojom::ChromeOSListener>
+        chromeos_listener_receiver,
+    mojo::PendingRemote<content_settings::mojom::ContentSettingsManager>
+        content_settings_manager,
+    mojo::PendingRemote<chrome::mojom::BoundSessionRequestThrottledListener>
+        bound_session_request_throttled_listener) {
+  is_incognito_process_ = is_incognito_process;
+}
+
+void AlloyRenderThreadObserver::SetConfiguration(
+    chrome::mojom::DynamicParamsPtr params) {
+  base::AutoLock lock(dynamic_params_lock_);
+  dynamic_params_ = std::move(params);
+}
+
+void AlloyRenderThreadObserver::OnRendererConfigurationAssociatedRequest(
+    mojo::PendingAssociatedReceiver<chrome::mojom::RendererConfiguration>
+        receiver) {
+  renderer_configuration_receivers_.Add(this, std::move(receiver));
+}
diff --git a/src/libcef/renderer/alloy/alloy_render_thread_observer.h b/src/libcef/renderer/alloy/alloy_render_thread_observer.h
new file mode 100644
index 0000000..2b4ed44
--- /dev/null
+++ b/src/libcef/renderer/alloy/alloy_render_thread_observer.h
@@ -0,0 +1,68 @@
+// Copyright (c) 2013 The Chromium Embedded Framework Authors.
+// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_RENDERER_ALLOY_ALLOY_RENDER_THREAD_OBSERVER_H_
+#define CEF_LIBCEF_RENDERER_ALLOY_ALLOY_RENDER_THREAD_OBSERVER_H_
+
+#include <memory>
+
+#include "base/synchronization/lock.h"
+#include "base/thread_annotations.h"
+#include "chrome/common/renderer_configuration.mojom.h"
+#include "components/content_settings/core/common/content_settings.h"
+#include "content/public/renderer/render_thread_observer.h"
+#include "mojo/public/cpp/bindings/associated_receiver_set.h"
+
+// This class sends and receives control messages in the renderer process.
+class AlloyRenderThreadObserver : public content::RenderThreadObserver,
+                                  public chrome::mojom::RendererConfiguration {
+ public:
+  AlloyRenderThreadObserver();
+
+  AlloyRenderThreadObserver(const AlloyRenderThreadObserver&) = delete;
+  AlloyRenderThreadObserver& operator=(const AlloyRenderThreadObserver&) =
+      delete;
+
+  ~AlloyRenderThreadObserver() override;
+
+  bool IsIncognitoProcess() const { return is_incognito_process_; }
+
+  // Return a copy of the dynamic parameters - those that may change while the
+  // render process is running.
+  chrome::mojom::DynamicParamsPtr GetDynamicParams() const;
+
+ private:
+  // content::RenderThreadObserver:
+  void RegisterMojoInterfaces(
+      blink::AssociatedInterfaceRegistry* associated_interfaces) override;
+  void UnregisterMojoInterfaces(
+      blink::AssociatedInterfaceRegistry* associated_interfaces) override;
+
+  // chrome::mojom::RendererConfiguration:
+  void SetInitialConfiguration(
+      bool is_incognito_process,
+      mojo::PendingReceiver<chrome::mojom::ChromeOSListener>
+          chromeos_listener_receiver,
+      mojo::PendingRemote<content_settings::mojom::ContentSettingsManager>
+          content_settings_manager,
+      mojo::PendingRemote<chrome::mojom::BoundSessionRequestThrottledListener>
+          bound_session_request_throttled_listener) override;
+  void SetConfiguration(chrome::mojom::DynamicParamsPtr params) override;
+
+  void OnRendererConfigurationAssociatedRequest(
+      mojo::PendingAssociatedReceiver<chrome::mojom::RendererConfiguration>
+          receiver);
+
+  bool is_incognito_process_ = false;
+
+  mojo::AssociatedReceiverSet<chrome::mojom::RendererConfiguration>
+      renderer_configuration_receivers_;
+
+  chrome::mojom::DynamicParamsPtr dynamic_params_
+      GUARDED_BY(dynamic_params_lock_);
+  mutable base::Lock dynamic_params_lock_;
+};
+
+#endif  // CEF_LIBCEF_RENDERER_ALLOY_ALLOY_RENDER_THREAD_OBSERVER_H_
diff --git a/src/libcef/renderer/alloy/url_loader_throttle_provider_impl.cc b/src/libcef/renderer/alloy/url_loader_throttle_provider_impl.cc
new file mode 100644
index 0000000..d2ee4bd
--- /dev/null
+++ b/src/libcef/renderer/alloy/url_loader_throttle_provider_impl.cc
@@ -0,0 +1,75 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/renderer/alloy/url_loader_throttle_provider_impl.h"
+
+#include "libcef/common/extensions/extensions_util.h"
+#include "libcef/renderer/alloy/alloy_content_renderer_client.h"
+#include "libcef/renderer/alloy/alloy_render_thread_observer.h"
+
+#include <utility>
+
+#include "base/feature_list.h"
+#include "chrome/common/google_url_loader_throttle.h"
+#include "components/signin/public/base/signin_buildflags.h"
+#include "content/public/common/content_features.h"
+#include "content/public/renderer/render_frame.h"
+#include "services/network/public/cpp/features.h"
+#include "third_party/blink/public/common/loader/resource_type_util.h"
+#include "third_party/blink/public/platform/web_url.h"
+
+CefURLLoaderThrottleProviderImpl::CefURLLoaderThrottleProviderImpl(
+    blink::URLLoaderThrottleProviderType type,
+    AlloyContentRendererClient* alloy_content_renderer_client)
+    : type_(type),
+      alloy_content_renderer_client_(alloy_content_renderer_client) {
+  DETACH_FROM_THREAD(thread_checker_);
+}
+
+CefURLLoaderThrottleProviderImpl::~CefURLLoaderThrottleProviderImpl() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+}
+
+CefURLLoaderThrottleProviderImpl::CefURLLoaderThrottleProviderImpl(
+    const CefURLLoaderThrottleProviderImpl& other)
+    : type_(other.type_),
+      alloy_content_renderer_client_(other.alloy_content_renderer_client_) {
+  DETACH_FROM_THREAD(thread_checker_);
+}
+
+std::unique_ptr<blink::URLLoaderThrottleProvider>
+CefURLLoaderThrottleProviderImpl::Clone() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  return base::WrapUnique(new CefURLLoaderThrottleProviderImpl(*this));
+}
+
+blink::WebVector<std::unique_ptr<blink::URLLoaderThrottle>>
+CefURLLoaderThrottleProviderImpl::CreateThrottles(
+    int render_frame_id,
+    const blink::WebURLRequest& request) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+  blink::WebVector<std::unique_ptr<blink::URLLoaderThrottle>> throttles;
+
+  const network::mojom::RequestDestination request_destination =
+      request.GetRequestDestination();
+
+  // Some throttles have already been added in the browser for frame resources.
+  // Don't add them for frame requests.
+  bool is_frame_resource =
+      blink::IsRequestDestinationFrame(request_destination);
+
+  DCHECK(!is_frame_resource ||
+         type_ == blink::URLLoaderThrottleProviderType::kFrame);
+
+  throttles.emplace_back(std::make_unique<GoogleURLLoaderThrottle>(
+#if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS)
+      /*bound_session_request_throttled_listener=*/nullptr,
+#endif
+      alloy_content_renderer_client_->GetAlloyObserver()->GetDynamicParams()));
+
+  return throttles;
+}
+
+void CefURLLoaderThrottleProviderImpl::SetOnline(bool is_online) {}
diff --git a/src/libcef/renderer/alloy/url_loader_throttle_provider_impl.h b/src/libcef/renderer/alloy/url_loader_throttle_provider_impl.h
new file mode 100644
index 0000000..ccc336b
--- /dev/null
+++ b/src/libcef/renderer/alloy/url_loader_throttle_provider_impl.h
@@ -0,0 +1,49 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_RENDERER_ALLOY_URL_LOADER_THROTTLE_PROVIDER_IMPL_H_
+#define CEF_LIBCEF_RENDERER_ALLOY_URL_LOADER_THROTTLE_PROVIDER_IMPL_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/threading/thread_checker.h"
+#include "third_party/blink/public/platform/url_loader_throttle_provider.h"
+
+class AlloyContentRendererClient;
+
+// Instances must be constructed on the render thread, and then used and
+// destructed on a single thread, which can be different from the render thread.
+class CefURLLoaderThrottleProviderImpl
+    : public blink::URLLoaderThrottleProvider {
+ public:
+  CefURLLoaderThrottleProviderImpl(
+      blink::URLLoaderThrottleProviderType type,
+      AlloyContentRendererClient* alloy_content_renderer_client);
+
+  CefURLLoaderThrottleProviderImpl& operator=(
+      const CefURLLoaderThrottleProviderImpl&) = delete;
+
+  ~CefURLLoaderThrottleProviderImpl() override;
+
+  // blink::URLLoaderThrottleProvider implementation.
+  std::unique_ptr<blink::URLLoaderThrottleProvider> Clone() override;
+  blink::WebVector<std::unique_ptr<blink::URLLoaderThrottle>> CreateThrottles(
+      int render_frame_id,
+      const blink::WebURLRequest& request) override;
+  void SetOnline(bool is_online) override;
+
+ private:
+  // This copy constructor works in conjunction with Clone(), not intended for
+  // general use.
+  CefURLLoaderThrottleProviderImpl(
+      const CefURLLoaderThrottleProviderImpl& other);
+
+  blink::URLLoaderThrottleProviderType type_;
+  AlloyContentRendererClient* const alloy_content_renderer_client_;
+
+  THREAD_CHECKER(thread_checker_);
+};
+
+#endif  // CEF_LIBCEF_RENDERER_ALLOY_URL_LOADER_THROTTLE_PROVIDER_IMPL_H_
diff --git a/src/libcef/renderer/blink_glue.cc b/src/libcef/renderer/blink_glue.cc
index 8f2c13e..632c980 100644
--- a/src/libcef/renderer/blink_glue.cc
+++ b/src/libcef/renderer/blink_glue.cc
@@ -5,6 +5,7 @@
 
 #include "libcef/renderer/blink_glue.h"
 
+#include "third_party/blink/public/mojom/v8_cache_options.mojom-blink.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url_response.h"
 #include "third_party/blink/public/web/web_document.h"
@@ -13,23 +14,28 @@
 #include "third_party/blink/public/web/web_node.h"
 #include "third_party/blink/public/web/web_view_client.h"
 
-#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
+#include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/dom/node.h"
 #include "third_party/blink/renderer/core/editing/serializers/serialization.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h"
 #include "third_party/blink/renderer/core/exported/web_view_impl.h"
 #include "third_party/blink/renderer/core/frame/frame_owner.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/core/loader/frame_load_request.h"
+#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/script/classic_script.h"
 #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
 #include "third_party/blink/renderer/platform/bindings/v8_binding.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+#include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h"
 #include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
 #undef LOG
 
@@ -37,63 +43,90 @@
 
 namespace blink_glue {
 
+namespace {
+
+blink::ExecutionContext* GetExecutionContext(v8::Local<v8::Context> context) {
+  blink::LocalFrame* frame = blink::ToLocalFrameIfNotDetached(context);
+  if (frame &&
+      frame->DomWindow()->CanExecuteScripts(blink::kAboutToExecuteScript)) {
+    return frame->GetDocument()->GetExecutionContext();
+  }
+  return nullptr;
+}
+
+}  // namespace
+
 const int64_t kInvalidFrameId = -1;
 
 bool CanGoBack(blink::WebView* view) {
-  if (!view)
+  if (!view) {
     return false;
-  blink::WebViewImpl* impl = reinterpret_cast<blink::WebViewImpl*>(view);
-  return (impl->Client()->HistoryBackListCount() > 0);
+  }
+  return view->HistoryBackListCount() > 0;
 }
 
 bool CanGoForward(blink::WebView* view) {
-  if (!view)
+  if (!view) {
     return false;
-  blink::WebViewImpl* impl = reinterpret_cast<blink::WebViewImpl*>(view);
-  return (impl->Client()->HistoryForwardListCount() > 0);
+  }
+  return view->HistoryForwardListCount() > 0;
 }
 
 void GoBack(blink::WebView* view) {
-  if (!view)
+  if (!view) {
     return;
+  }
 
   blink::WebFrame* main_frame = view->MainFrame();
   if (main_frame && main_frame->IsWebLocalFrame()) {
-    blink::WebViewImpl* view_impl = reinterpret_cast<blink::WebViewImpl*>(view);
-    if (view_impl->Client()->HistoryBackListCount() > 0) {
+    if (view->HistoryBackListCount() > 0) {
       blink::Frame* core_frame = blink::WebFrame::ToCoreFrame(*main_frame);
       blink::To<blink::LocalFrame>(core_frame)
           ->GetLocalFrameHostRemote()
-          .GoToEntryAtOffset(-1, true /* has_user_gesture */);
+          .GoToEntryAtOffset(-1, /*has_user_gesture=*/true, absl::nullopt);
     }
   }
 }
 
 void GoForward(blink::WebView* view) {
-  if (!view)
+  if (!view) {
     return;
+  }
 
   blink::WebFrame* main_frame = view->MainFrame();
   if (main_frame && main_frame->IsWebLocalFrame()) {
-    blink::WebViewImpl* view_impl = reinterpret_cast<blink::WebViewImpl*>(view);
-    if (view_impl->Client()->HistoryForwardListCount() > 0) {
+    if (view->HistoryForwardListCount() > 0) {
       blink::Frame* core_frame = blink::WebFrame::ToCoreFrame(*main_frame);
       blink::To<blink::LocalFrame>(core_frame)
           ->GetLocalFrameHostRemote()
-          .GoToEntryAtOffset(1, true /* has_user_gesture */);
+          .GoToEntryAtOffset(1, /*has_user_gesture=*/true, absl::nullopt);
     }
   }
 }
 
-std::string DumpDocumentText(blink::WebLocalFrame* frame) {
+bool IsInBackForwardCache(blink::WebLocalFrame* frame) {
+  blink::Frame* core_frame = blink::WebFrame::ToCoreFrame(*frame);
+  return blink::To<blink::LocalFrame>(core_frame)
+      ->GetPage()
+      ->GetPageScheduler()
+      ->IsInBackForwardCache();
+}
+
+blink::WebString DumpDocumentText(blink::WebLocalFrame* frame) {
   // We use the document element's text instead of the body text here because
   // not all documents have a body, such as XML documents.
   blink::WebElement document_element = frame->GetDocument().DocumentElement();
-  if (document_element.IsNull())
-    return std::string();
+  if (document_element.IsNull()) {
+    return blink::WebString();
+  }
 
   blink::Element* web_element = document_element.Unwrap<blink::Element>();
-  return blink::WebString(web_element->innerText()).Utf8();
+  return blink::WebString(web_element->innerText());
+}
+
+blink::WebString DumpDocumentMarkup(blink::WebLocalFrame* frame) {
+  return blink::CreateMarkup(
+      blink::To<blink::WebLocalFrameImpl>(frame)->GetFrame()->GetDocument());
 }
 
 cef_dom_node_type_t GetNodeType(const blink::WebNode& node) {
@@ -147,13 +180,9 @@
 
   // Execute the function call using the V8ScriptRunner so that inspector
   // instrumentation works.
-  blink::LocalFrame* frame = blink::ToLocalFrameIfNotDetached(context);
-  DCHECK(frame);
-  if (frame &&
-      frame->GetDocument()->CanExecuteScripts(blink::kAboutToExecuteScript)) {
+  if (auto execution_context = GetExecutionContext(context)) {
     func_rv = blink::V8ScriptRunner::CallFunction(
-        function, frame->GetDocument()->ToExecutionContext(), receiver, argc,
-        args, isolate);
+        function, execution_context, receiver, argc, args, isolate);
   }
 
   return func_rv;
@@ -164,75 +193,90 @@
   return web_element->IsTextControl();
 }
 
-v8::MaybeLocal<v8::Value> ExecuteV8ScriptAndReturnValue(
+v8::Local<v8::Value> ExecuteV8ScriptAndReturnValue(
     const blink::WebString& source,
     const blink::WebString& source_url,
     int start_line,
     v8::Local<v8::Context> context,
-    v8::Isolate* isolate,
-    v8::TryCatch& tryCatch,
-    blink::SanitizeScriptErrors sanitizeScriptErrors) {
-  // Based on ScriptController::executeScriptAndReturnValue
-  DCHECK(isolate);
-
-  if (start_line < 1)
+    v8::TryCatch& tryCatch) {
+  if (start_line < 1) {
     start_line = 1;
+  }
 
-  const blink::ScriptSourceCode ssc = blink::ScriptSourceCode(
-      source, blink::ScriptSourceLocationType::kInternal,
-      nullptr, /* cache_handler */
-      blink::KURL(source_url),
+  blink::LocalFrame* frame = blink::ToLocalFrameIfNotDetached(context);
+  if (!frame) {
+    return v8::Local<v8::Value>();
+  }
+
+  auto* script = blink::ClassicScript::Create(
+      source, blink::KURL(source_url), blink::KURL(source_url),
+      blink::ScriptFetchOptions(), blink::ScriptSourceLocationType::kInternal,
+      blink::SanitizeScriptErrors::kDoNotSanitize, /*cache_handler=*/nullptr,
       WTF::TextPosition(WTF::OrdinalNumber::FromOneBasedInt(start_line),
                         WTF::OrdinalNumber::FromZeroBasedInt(0)));
 
-  v8::MaybeLocal<v8::Value> result;
+  // The Rethrow() message is unused due to kDoNotSanitize but it still needs
+  // to be non-nullopt for exceptions to be re-thrown as expected.
+  auto result = blink::V8ScriptRunner::CompileAndRunScript(
+      blink::ScriptState::From(context), script,
+      blink::ExecuteScriptPolicy::kExecuteScriptWhenScriptsDisabled,
+      blink::V8ScriptRunner::RethrowErrorsOption::Rethrow(""));
 
-  blink::LocalFrame* frame = blink::ToLocalFrameIfNotDetached(context);
-  if (!frame)
-    return result;
-
-  blink::V8CacheOptions v8CacheOptions(blink::kV8CacheOptionsDefault);
-  if (frame && frame->GetSettings())
-    v8CacheOptions = frame->GetSettings()->GetV8CacheOptions();
-
-  // Based on V8ScriptRunner::CompileAndRunInternalScript:
-  v8::ScriptCompiler::CompileOptions compile_options;
-  blink::V8CodeCache::ProduceCacheOptions produce_cache_options;
-  v8::ScriptCompiler::NoCacheReason no_cache_reason;
-  std::tie(compile_options, produce_cache_options, no_cache_reason) =
-      blink::V8CodeCache::GetCompileOptions(v8CacheOptions, ssc);
-
-  // Currently internal scripts don't have cache handlers, so we should not
-  // produce cache for them.
-  DCHECK_EQ(produce_cache_options,
-            blink::V8CodeCache::ProduceCacheOptions::kNoProduceCache);
-
-  v8::Local<v8::Script> script;
-  // Use default ReferrerScriptInfo here:
-  // - nonce: empty for internal script, and
-  // - parser_state: always "not parser inserted" for internal scripts.
-  if (!blink::V8ScriptRunner::CompileScript(
-           blink::ScriptState::From(context), ssc, sanitizeScriptErrors,
-           compile_options, no_cache_reason, blink::ReferrerScriptInfo())
-           .ToLocal(&script)) {
-    DCHECK(tryCatch.HasCaught());
-    return result;
+  if (result.GetResultType() ==
+      blink::ScriptEvaluationResult::ResultType::kSuccess) {
+    return result.GetSuccessValue();
   }
 
-  return blink::V8ScriptRunner::RunCompiledScript(
-      isolate, script, blink::ToExecutionContext(context));
+  DCHECK(tryCatch.HasCaught());
+  return v8::Local<v8::Value>();
+}
+
+v8::MicrotaskQueue* GetMicrotaskQueue(v8::Local<v8::Context> context) {
+  if (auto execution_context = GetExecutionContext(context)) {
+    return execution_context->GetMicrotaskQueue();
+  }
+  return nullptr;
 }
 
 bool IsScriptForbidden() {
   return blink::ScriptForbiddenScope::IsScriptForbidden();
 }
 
-void RegisterURLSchemeAsLocal(const blink::WebString& scheme) {
-  blink::SchemeRegistry::RegisterURLSchemeAsLocal(scheme);
-}
+std::unique_ptr<CefObserverRegistration>
+RegisterExecutionContextLifecycleStateObserver(
+    v8::Local<v8::Context> context,
+    CefExecutionContextLifecycleStateObserver* observer) {
+  class Observer : public blink::GarbageCollected<Observer>,
+                   public blink::ExecutionContextLifecycleStateObserver {
+   public:
+    Observer(blink::ExecutionContext* execution_context,
+             CefExecutionContextLifecycleStateObserver* observer)
+        : blink::ExecutionContextLifecycleStateObserver(execution_context),
+          observer_(observer) {
+      UpdateStateIfNeeded();
+    }
 
-void RegisterURLSchemeAsSecure(const blink::WebString& scheme) {
-  blink::SchemeRegistry::RegisterURLSchemeAsSecure(scheme);
+    void ContextLifecycleStateChanged(
+        blink::mojom::blink::FrameLifecycleState state) override {
+      observer_->ContextLifecycleStateChanged(state);
+    }
+
+    void ContextDestroyed() override {}
+
+   private:
+    CefExecutionContextLifecycleStateObserver* observer_;
+  };
+
+  class Registration : public CefObserverRegistration {
+   public:
+    Registration(blink::Persistent<Observer> observer) : observer_(observer) {}
+
+   private:
+    blink::Persistent<Observer> observer_;
+  };
+
+  return std::make_unique<Registration>(blink::MakeGarbageCollected<Observer>(
+      blink::ExecutionContext::From(context), observer));
 }
 
 void RegisterURLSchemeAsSupportingFetchAPI(const blink::WebString& scheme) {
@@ -256,4 +300,19 @@
   return core_frame->Owner() && core_frame->Owner()->IsPlugin();
 }
 
+// Based on WebLocalFrameImpl::StartNavigation which was removed in
+// https://crrev.com/de4fc2a5fe.
+void StartNavigation(blink::WebLocalFrame* frame,
+                     const blink::WebURLRequest& request) {
+  DCHECK(!request.IsNull());
+  DCHECK(!request.Url().ProtocolIs("javascript"));
+
+  blink::FrameLoadRequest frame_load_request(nullptr,
+                                             request.ToResourceRequest());
+  blink::Frame* core_frame = blink::WebFrame::ToCoreFrame(*frame);
+  blink::To<blink::LocalFrame>(core_frame)
+      ->Loader()
+      .StartNavigation(frame_load_request, blink::WebFrameLoadType::kStandard);
+}
+
 }  // namespace blink_glue
diff --git a/src/libcef/renderer/blink_glue.h b/src/libcef/renderer/blink_glue.h
index 21d6bc1..95d7df3 100644
--- a/src/libcef/renderer/blink_glue.h
+++ b/src/libcef/renderer/blink_glue.h
@@ -13,8 +13,8 @@
 
 #include "include/internal/cef_types.h"
 
+#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink-forward.h"
 #include "third_party/blink/public/platform/web_common.h"
-#include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
 #include "v8/include/v8.h"
 
 namespace blink {
@@ -22,6 +22,7 @@
 class WebLocalFrame;
 class WebNode;
 class WebString;
+class WebURLRequest;
 class WebURLResponse;
 class WebView;
 }  // namespace blink
@@ -35,8 +36,12 @@
 BLINK_EXPORT void GoBack(blink::WebView* view);
 BLINK_EXPORT void GoForward(blink::WebView* view);
 
+BLINK_EXPORT bool IsInBackForwardCache(blink::WebLocalFrame* frame);
+
 // Returns the text of the document element.
-BLINK_EXPORT std::string DumpDocumentText(blink::WebLocalFrame* frame);
+BLINK_EXPORT blink::WebString DumpDocumentText(blink::WebLocalFrame* frame);
+// Returns the markup of the document element.
+BLINK_EXPORT blink::WebString DumpDocumentMarkup(blink::WebLocalFrame* frame);
 
 // Expose additional actions on WebNode.
 BLINK_EXPORT cef_dom_node_type_t GetNodeType(const blink::WebNode& node);
@@ -55,19 +60,43 @@
     v8::Local<v8::Value> args[],
     v8::Isolate* isolate);
 
-BLINK_EXPORT v8::MaybeLocal<v8::Value> ExecuteV8ScriptAndReturnValue(
+BLINK_EXPORT v8::Local<v8::Value> ExecuteV8ScriptAndReturnValue(
     const blink::WebString& source,
     const blink::WebString& source_url,
     int start_line,
     v8::Local<v8::Context> context,
-    v8::Isolate* isolate,
-    v8::TryCatch& tryCatch,
-    blink::SanitizeScriptErrors sanitizeScriptErrors);
+    v8::TryCatch& tryCatch);
+
+BLINK_EXPORT v8::MicrotaskQueue* GetMicrotaskQueue(
+    v8::Local<v8::Context> context);
 
 BLINK_EXPORT bool IsScriptForbidden();
 
-BLINK_EXPORT void RegisterURLSchemeAsLocal(const blink::WebString& scheme);
-BLINK_EXPORT void RegisterURLSchemeAsSecure(const blink::WebString& scheme);
+class BLINK_EXPORT CefObserverRegistration {
+ public:
+  CefObserverRegistration() = default;
+
+  CefObserverRegistration(const CefObserverRegistration&) = delete;
+  CefObserverRegistration& operator=(const CefObserverRegistration&) = delete;
+
+  virtual ~CefObserverRegistration() = default;
+};
+
+class BLINK_EXPORT CefExecutionContextLifecycleStateObserver {
+ public:
+  virtual void ContextLifecycleStateChanged(
+      blink::mojom::blink::FrameLifecycleState state) {}
+
+ protected:
+  virtual ~CefExecutionContextLifecycleStateObserver() = default;
+};
+
+// Register an ExecutionContextLifecycleStateObserver. Remains registered until
+// the returned object is destroyed.
+BLINK_EXPORT std::unique_ptr<CefObserverRegistration>
+RegisterExecutionContextLifecycleStateObserver(
+    v8::Local<v8::Context> context,
+    CefExecutionContextLifecycleStateObserver* observer);
 
 BLINK_EXPORT void RegisterURLSchemeAsSupportingFetchAPI(
     const blink::WebString& scheme);
@@ -76,13 +105,15 @@
 class BLINK_EXPORT CefScriptForbiddenScope final {
  public:
   CefScriptForbiddenScope();
+
+  CefScriptForbiddenScope(const CefScriptForbiddenScope&) = delete;
+  CefScriptForbiddenScope& operator=(const CefScriptForbiddenScope&) = delete;
+
   ~CefScriptForbiddenScope();
 
  private:
   struct Impl;
   std::unique_ptr<Impl> impl_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefScriptForbiddenScope);
 };
 
 BLINK_EXPORT bool ResponseWasCached(const blink::WebURLResponse& response);
@@ -90,6 +121,9 @@
 // Returns true if the frame owner is a plugin.
 BLINK_EXPORT bool HasPluginFrameOwner(blink::WebLocalFrame* frame);
 
+BLINK_EXPORT void StartNavigation(blink::WebLocalFrame* frame,
+                                  const blink::WebURLRequest& request);
+
 }  // namespace blink_glue
 
 #endif  // CEF_LIBCEF_RENDERER_BLINK_GLUE_H_
diff --git a/src/libcef/renderer/browser_impl.cc b/src/libcef/renderer/browser_impl.cc
index 0e67ca0..94cbb0e 100644
--- a/src/libcef/renderer/browser_impl.cc
+++ b/src/libcef/renderer/browser_impl.cc
@@ -8,19 +8,16 @@
 #include <string>
 #include <vector>
 
-#include "libcef/common/cef_messages.h"
-#include "libcef/common/content_client.h"
+#include "libcef/common/app_manager.h"
 #include "libcef/renderer/blink_glue.h"
-#include "libcef/renderer/content_renderer_client.h"
 #include "libcef/renderer/render_frame_util.h"
+#include "libcef/renderer/render_manager.h"
 #include "libcef/renderer/thread_util.h"
 
-#include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "content/public/renderer/document_state.h"
 #include "content/public/renderer/render_frame.h"
-#include "content/public/renderer/render_view.h"
+#include "content/renderer/document_state.h"
 #include "content/renderer/navigation_state.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url_error.h"
@@ -37,55 +34,61 @@
 
 // static
 CefRefPtr<CefBrowserImpl> CefBrowserImpl::GetBrowserForView(
-    content::RenderView* view) {
-  return CefContentRendererClient::Get()->GetBrowserForView(view);
+    blink::WebView* view) {
+  return CefRenderManager::Get()->GetBrowserForView(view);
 }
 
 // static
 CefRefPtr<CefBrowserImpl> CefBrowserImpl::GetBrowserForMainFrame(
     blink::WebFrame* frame) {
-  return CefContentRendererClient::Get()->GetBrowserForMainFrame(frame);
+  return CefRenderManager::Get()->GetBrowserForMainFrame(frame);
 }
 
 // CefBrowser methods.
 // -----------------------------------------------------------------------------
 
+bool CefBrowserImpl::IsValid() {
+  CEF_REQUIRE_RT_RETURN(false);
+  return !!GetWebView();
+}
+
 CefRefPtr<CefBrowserHost> CefBrowserImpl::GetHost() {
-  NOTREACHED() << "GetHost cannot be called from the render process";
+  DCHECK(false) << "GetHost cannot be called from the render process";
   return nullptr;
 }
 
 bool CefBrowserImpl::CanGoBack() {
   CEF_REQUIRE_RT_RETURN(false);
 
-  return blink_glue::CanGoBack(render_view()->GetWebView());
+  return blink_glue::CanGoBack(GetWebView());
 }
 
 void CefBrowserImpl::GoBack() {
   CEF_REQUIRE_RT_RETURN_VOID();
 
-  blink_glue::GoBack(render_view()->GetWebView());
+  blink_glue::GoBack(GetWebView());
 }
 
 bool CefBrowserImpl::CanGoForward() {
   CEF_REQUIRE_RT_RETURN(false);
 
-  return blink_glue::CanGoForward(render_view()->GetWebView());
+  return blink_glue::CanGoForward(GetWebView());
 }
 
 void CefBrowserImpl::GoForward() {
   CEF_REQUIRE_RT_RETURN_VOID();
 
-  blink_glue::GoForward(render_view()->GetWebView());
+  blink_glue::GoForward(GetWebView());
 }
 
 bool CefBrowserImpl::IsLoading() {
   CEF_REQUIRE_RT_RETURN(false);
 
-  if (render_view()->GetWebView()) {
-    blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
-    if (main_frame)
+  if (GetWebView()) {
+    blink::WebFrame* main_frame = GetWebView()->MainFrame();
+    if (main_frame) {
       return main_frame->ToWebLocalFrame()->IsLoading();
+    }
   }
   return false;
 }
@@ -93,8 +96,8 @@
 void CefBrowserImpl::Reload() {
   CEF_REQUIRE_RT_RETURN_VOID();
 
-  if (render_view()->GetWebView()) {
-    blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
+  if (GetWebView()) {
+    blink::WebFrame* main_frame = GetWebView()->MainFrame();
     if (main_frame && main_frame->IsWebLocalFrame()) {
       main_frame->ToWebLocalFrame()->StartReload(
           blink::WebFrameLoadType::kReload);
@@ -105,8 +108,8 @@
 void CefBrowserImpl::ReloadIgnoreCache() {
   CEF_REQUIRE_RT_RETURN_VOID();
 
-  if (render_view()->GetWebView()) {
-    blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
+  if (GetWebView()) {
+    blink::WebFrame* main_frame = GetWebView()->MainFrame();
     if (main_frame && main_frame->IsWebLocalFrame()) {
       main_frame->ToWebLocalFrame()->StartReload(
           blink::WebFrameLoadType::kReloadBypassingCache);
@@ -117,10 +120,10 @@
 void CefBrowserImpl::StopLoad() {
   CEF_REQUIRE_RT_RETURN_VOID();
 
-  if (render_view()->GetWebView()) {
-    blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
+  if (GetWebView()) {
+    blink::WebFrame* main_frame = GetWebView()->MainFrame();
     if (main_frame && main_frame->IsWebLocalFrame()) {
-      main_frame->ToWebLocalFrame()->StopLoading();
+      main_frame->ToWebLocalFrame()->DeprecatedStopLoading();
     }
   }
 }
@@ -147,8 +150,8 @@
 bool CefBrowserImpl::HasDocument() {
   CEF_REQUIRE_RT_RETURN(false);
 
-  if (render_view()->GetWebView()) {
-    blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
+  if (GetWebView()) {
+    blink::WebFrame* main_frame = GetWebView()->MainFrame();
     if (main_frame && main_frame->IsWebLocalFrame()) {
       return !main_frame->ToWebLocalFrame()->GetDocument().IsNull();
     }
@@ -159,8 +162,8 @@
 CefRefPtr<CefFrame> CefBrowserImpl::GetMainFrame() {
   CEF_REQUIRE_RT_RETURN(nullptr);
 
-  if (render_view()->GetWebView()) {
-    blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
+  if (GetWebView()) {
+    blink::WebFrame* main_frame = GetWebView()->MainFrame();
     if (main_frame && main_frame->IsWebLocalFrame()) {
       return GetWebFrameImpl(main_frame->ToWebLocalFrame()).get();
     }
@@ -171,14 +174,13 @@
 CefRefPtr<CefFrame> CefBrowserImpl::GetFocusedFrame() {
   CEF_REQUIRE_RT_RETURN(nullptr);
 
-  if (render_view()->GetWebView() &&
-      render_view()->GetWebView()->FocusedFrame()) {
-    return GetWebFrameImpl(render_view()->GetWebView()->FocusedFrame()).get();
+  if (GetWebView() && GetWebView()->FocusedFrame()) {
+    return GetWebFrameImpl(GetWebView()->FocusedFrame()).get();
   }
   return nullptr;
 }
 
-CefRefPtr<CefFrame> CefBrowserImpl::GetFrame(int64 identifier) {
+CefRefPtr<CefFrame> CefBrowserImpl::GetFrame(int64_t identifier) {
   CEF_REQUIRE_RT_RETURN(nullptr);
 
   return GetWebFrameImpl(identifier).get();
@@ -187,14 +189,15 @@
 CefRefPtr<CefFrame> CefBrowserImpl::GetFrame(const CefString& name) {
   CEF_REQUIRE_RT_RETURN(nullptr);
 
-  blink::WebView* web_view = render_view()->GetWebView();
+  blink::WebView* web_view = GetWebView();
   if (web_view) {
     const blink::WebString& frame_name =
         blink::WebString::FromUTF16(name.ToString16());
     // Search by assigned frame name (Frame::name).
     blink::WebFrame* frame = web_view->MainFrame();
-    if (frame && frame->IsWebLocalFrame())
+    if (frame && frame->IsWebLocalFrame()) {
       frame = frame->ToWebLocalFrame()->FindFrameByName(frame_name);
+    }
     if (!frame) {
       // Search by unique frame name (Frame::uniqueName).
       const std::string& searchname = name;
@@ -208,8 +211,9 @@
         }
       }
     }
-    if (frame && frame->IsWebLocalFrame())
+    if (frame && frame->IsWebLocalFrame()) {
       return GetWebFrameImpl(frame->ToWebLocalFrame()).get();
+    }
   }
 
   return nullptr;
@@ -220,9 +224,9 @@
 
   int count = 0;
 
-  if (render_view()->GetWebView()) {
-    for (blink::WebFrame* frame = render_view()->GetWebView()->MainFrame();
-         frame; frame = frame->TraverseNext()) {
+  if (GetWebView()) {
+    for (blink::WebFrame* frame = GetWebView()->MainFrame(); frame;
+         frame = frame->TraverseNext()) {
       count++;
     }
   }
@@ -230,18 +234,20 @@
   return count;
 }
 
-void CefBrowserImpl::GetFrameIdentifiers(std::vector<int64>& identifiers) {
+void CefBrowserImpl::GetFrameIdentifiers(std::vector<int64_t>& identifiers) {
   CEF_REQUIRE_RT_RETURN_VOID();
 
-  if (identifiers.size() > 0)
+  if (identifiers.size() > 0) {
     identifiers.clear();
+  }
 
-  if (render_view()->GetWebView()) {
-    for (blink::WebFrame* frame = render_view()->GetWebView()->MainFrame();
-         frame; frame = frame->TraverseNext()) {
-      if (frame->IsWebLocalFrame())
+  if (GetWebView()) {
+    for (blink::WebFrame* frame = GetWebView()->MainFrame(); frame;
+         frame = frame->TraverseNext()) {
+      if (frame->IsWebLocalFrame()) {
         identifiers.push_back(
             render_frame_util::GetIdentifier(frame->ToWebLocalFrame()));
+      }
     }
   }
 }
@@ -249,14 +255,16 @@
 void CefBrowserImpl::GetFrameNames(std::vector<CefString>& names) {
   CEF_REQUIRE_RT_RETURN_VOID();
 
-  if (names.size() > 0)
+  if (names.size() > 0) {
     names.clear();
+  }
 
-  if (render_view()->GetWebView()) {
-    for (blink::WebFrame* frame = render_view()->GetWebView()->MainFrame();
-         frame; frame = frame->TraverseNext()) {
-      if (frame->IsWebLocalFrame())
+  if (GetWebView()) {
+    for (blink::WebFrame* frame = GetWebView()->MainFrame(); frame;
+         frame = frame->TraverseNext()) {
+      if (frame->IsWebLocalFrame()) {
         names.push_back(render_frame_util::GetName(frame->ToWebLocalFrame()));
+      }
     }
   }
 }
@@ -264,11 +272,11 @@
 // CefBrowserImpl public methods.
 // -----------------------------------------------------------------------------
 
-CefBrowserImpl::CefBrowserImpl(content::RenderView* render_view,
+CefBrowserImpl::CefBrowserImpl(blink::WebView* web_view,
                                int browser_id,
                                bool is_popup,
                                bool is_windowless)
-    : content::RenderViewObserver(render_view),
+    : blink::WebViewObserver(web_view),
       browser_id_(browser_id),
       is_popup_(is_popup),
       is_windowless_(is_windowless) {}
@@ -282,8 +290,9 @@
 
   // Frames are re-used between page loads. Only add the frame to the map once.
   FrameMap::const_iterator it = frames_.find(frame_id);
-  if (it != frames_.end())
+  if (it != frames_.end()) {
     return it->second;
+  }
 
   CefRefPtr<CefFrameImpl> framePtr(new CefFrameImpl(this, frame, frame_id));
   frames_.insert(std::make_pair(frame_id, framePtr));
@@ -293,8 +302,8 @@
 
 CefRefPtr<CefFrameImpl> CefBrowserImpl::GetWebFrameImpl(int64_t frame_id) {
   if (frame_id == blink_glue::kInvalidFrameId) {
-    if (render_view()->GetWebView()) {
-      blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
+    if (GetWebView()) {
+      blink::WebFrame* main_frame = GetWebView()->MainFrame();
       if (main_frame && main_frame->IsWebLocalFrame()) {
         return GetWebFrameImpl(main_frame->ToWebLocalFrame());
       }
@@ -304,13 +313,14 @@
 
   // Check if we already know about the frame.
   FrameMap::const_iterator it = frames_.find(frame_id);
-  if (it != frames_.end())
+  if (it != frames_.end()) {
     return it->second;
+  }
 
-  if (render_view()->GetWebView()) {
+  if (GetWebView()) {
     // Check if the frame exists but we don't know about it yet.
-    for (blink::WebFrame* frame = render_view()->GetWebView()->MainFrame();
-         frame; frame = frame->TraverseNext()) {
+    for (blink::WebFrame* frame = GetWebView()->MainFrame(); frame;
+         frame = frame->TraverseNext()) {
       if (frame->IsWebLocalFrame() &&
           render_frame_util::GetIdentifier(frame->ToWebLocalFrame()) ==
               frame_id) {
@@ -328,8 +338,9 @@
 
   if (!frame_objects_.empty()) {
     FrameObjectMap::const_iterator it = frame_objects_.find(frame_id);
-    if (it != frame_objects_.end())
+    if (it != frame_objects_.end()) {
       manager = it->second;
+    }
   }
 
   if (!manager.get()) {
@@ -345,14 +356,15 @@
 
 void CefBrowserImpl::OnDestruct() {
   // Notify that the browser window has been destroyed.
-  CefRefPtr<CefApp> app = CefContentClient::Get()->application();
+  CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
   if (app.get()) {
     CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
-    if (handler.get())
+    if (handler.get()) {
       handler->OnBrowserDestroyed(this);
+    }
   }
 
-  CefContentRendererClient::Get()->OnBrowserDestroyed(this);
+  CefRenderManager::Get()->OnBrowserDestroyed(this);
 }
 
 void CefBrowserImpl::FrameDetached(int64_t frame_id) {
@@ -367,19 +379,20 @@
   if (!frame_objects_.empty()) {
     // Remove any tracked objects associated with the frame.
     FrameObjectMap::iterator it = frame_objects_.find(frame_id);
-    if (it != frame_objects_.end())
+    if (it != frame_objects_.end()) {
       frame_objects_.erase(it);
+    }
   }
 }
 
 void CefBrowserImpl::OnLoadingStateChange(bool isLoading) {
-  CefRefPtr<CefApp> app = CefContentClient::Get()->application();
+  CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
   if (app.get()) {
     CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
     if (handler.get()) {
       CefRefPtr<CefLoadHandler> load_handler = handler->GetLoadHandler();
       if (load_handler.get()) {
-        blink::WebView* web_view = render_view()->GetWebView();
+        blink::WebView* web_view = GetWebView();
         const bool canGoBack = blink_glue::CanGoBack(web_view);
         const bool canGoForward = blink_glue::CanGoForward(web_view);
 
@@ -391,6 +404,19 @@
           return;
         }
 
+        if (was_in_bfcache_) {
+          // Send the expected callbacks when exiting the BFCache.
+          DCHECK(!isLoading);
+          load_handler->OnLoadingStateChange(this, /*isLoading=*/true,
+                                             canGoBack, canGoForward);
+
+          auto main_frame = GetMainFrame();
+          load_handler->OnLoadStart(this, main_frame, TT_EXPLICIT);
+          load_handler->OnLoadEnd(this, main_frame, 0);
+
+          was_in_bfcache_ = false;
+        }
+
         load_handler->OnLoadingStateChange(this, isLoading, canGoBack,
                                            canGoForward);
         last_loading_state_.reset(
@@ -399,3 +425,10 @@
     }
   }
 }
+
+void CefBrowserImpl::OnEnterBFCache() {
+  // Reset loading state so that notifications will be resent if/when exiting
+  // BFCache.
+  was_in_bfcache_ = true;
+  last_loading_state_.reset();
+}
diff --git a/src/libcef/renderer/browser_impl.h b/src/libcef/renderer/browser_impl.h
index 99d343c..b0da154 100644
--- a/src/libcef/renderer/browser_impl.h
+++ b/src/libcef/renderer/browser_impl.h
@@ -19,11 +19,12 @@
 #include "libcef/common/tracker.h"
 #include "libcef/renderer/frame_impl.h"
 
-#include "content/public/renderer/render_view_observer.h"
+#include "third_party/blink/public/web/web_view_observer.h"
 
 namespace blink {
 class WebFrame;
 class WebNode;
+class WebView;
 }  // namespace blink
 
 // Renderer plumbing for CEF features. There is a one-to-one relationship
@@ -31,15 +32,16 @@
 // side.
 //
 // RenderViewObserver: Interface for observing RenderView notifications.
-class CefBrowserImpl : public CefBrowser, public content::RenderViewObserver {
+class CefBrowserImpl : public CefBrowser, public blink::WebViewObserver {
  public:
   // Returns the browser associated with the specified RenderView.
-  static CefRefPtr<CefBrowserImpl> GetBrowserForView(content::RenderView* view);
+  static CefRefPtr<CefBrowserImpl> GetBrowserForView(blink::WebView* view);
   // Returns the browser associated with the specified main WebFrame.
   static CefRefPtr<CefBrowserImpl> GetBrowserForMainFrame(
       blink::WebFrame* frame);
 
   // CefBrowser methods.
+  bool IsValid() override;
   CefRefPtr<CefBrowserHost> GetHost() override;
   bool CanGoBack() override;
   void GoBack() override;
@@ -55,16 +57,20 @@
   bool HasDocument() override;
   CefRefPtr<CefFrame> GetMainFrame() override;
   CefRefPtr<CefFrame> GetFocusedFrame() override;
-  CefRefPtr<CefFrame> GetFrame(int64 identifier) override;
+  CefRefPtr<CefFrame> GetFrame(int64_t identifier) override;
   CefRefPtr<CefFrame> GetFrame(const CefString& name) override;
   size_t GetFrameCount() override;
-  void GetFrameIdentifiers(std::vector<int64>& identifiers) override;
+  void GetFrameIdentifiers(std::vector<int64_t>& identifiers) override;
   void GetFrameNames(std::vector<CefString>& names) override;
 
-  CefBrowserImpl(content::RenderView* render_view,
+  CefBrowserImpl(blink::WebView* web_view,
                  int browser_id,
                  bool is_popup,
                  bool is_windowless);
+
+  CefBrowserImpl(const CefBrowserImpl&) = delete;
+  CefBrowserImpl& operator=(const CefBrowserImpl&) = delete;
+
   ~CefBrowserImpl() override;
 
   // Returns the matching CefFrameImpl reference or creates a new one.
@@ -77,15 +83,13 @@
   int browser_id() const { return browser_id_; }
   bool is_popup() const { return is_popup_; }
   bool is_windowless() const { return is_windowless_; }
-  content::RenderView* render_view() const {
-    return content::RenderViewObserver::render_view();
-  }
 
-  // RenderViewObserver methods.
+  // blink::WebViewObserver methods.
   void OnDestruct() override;
   void FrameDetached(int64_t frame_id);
 
   void OnLoadingStateChange(bool isLoading);
+  void OnEnterBFCache();
 
  private:
   // ID of the browser that this RenderView is associated with. During loading
@@ -96,12 +100,15 @@
   bool is_windowless_;
 
   // Map of unique frame ids to CefFrameImpl references.
-  typedef std::map<int64, CefRefPtr<CefFrameImpl>> FrameMap;
+  using FrameMap = std::map<int64_t, CefRefPtr<CefFrameImpl>>;
   FrameMap frames_;
 
+  // True if the browser was in the BFCache.
+  bool was_in_bfcache_ = false;
+
   // Map of unique frame ids to CefTrackManager objects that need to be cleaned
   // up when the frame is deleted.
-  typedef std::map<int64, CefRefPtr<CefTrackManager>> FrameObjectMap;
+  using FrameObjectMap = std::map<int64_t, CefRefPtr<CefTrackManager>>;
   FrameObjectMap frame_objects_;
 
   struct LoadingState {
@@ -122,7 +129,6 @@
   std::unique_ptr<LoadingState> last_loading_state_;
 
   IMPLEMENT_REFCOUNTING(CefBrowserImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefBrowserImpl);
 };
 
 #endif  // CEF_LIBCEF_RENDERER_BROWSER_IMPL_H_
diff --git a/src/libcef/renderer/chrome/chrome_content_renderer_client_cef.cc b/src/libcef/renderer/chrome/chrome_content_renderer_client_cef.cc
new file mode 100644
index 0000000..5d23426
--- /dev/null
+++ b/src/libcef/renderer/chrome/chrome_content_renderer_client_cef.cc
@@ -0,0 +1,103 @@
+// Copyright 2020 The Chromium Embedded Framework Authors.
+// Portions copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/renderer/chrome/chrome_content_renderer_client_cef.h"
+
+#include "libcef/renderer/render_frame_observer.h"
+#include "libcef/renderer/render_manager.h"
+#include "libcef/renderer/thread_util.h"
+
+#include "content/public/renderer/render_thread.h"
+
+ChromeContentRendererClientCef::ChromeContentRendererClientCef()
+    : render_manager_(new CefRenderManager) {}
+
+ChromeContentRendererClientCef::~ChromeContentRendererClientCef() = default;
+
+scoped_refptr<base::SingleThreadTaskRunner>
+ChromeContentRendererClientCef::GetCurrentTaskRunner() {
+  // Check if currently on the render thread.
+  if (CEF_CURRENTLY_ON_RT()) {
+    return render_task_runner_;
+  }
+  return nullptr;
+}
+
+void ChromeContentRendererClientCef::RenderThreadStarted() {
+  ChromeContentRendererClient::RenderThreadStarted();
+
+  render_task_runner_ = base::SingleThreadTaskRunner::GetCurrentDefault();
+}
+
+void ChromeContentRendererClientCef::RenderThreadConnected() {
+  ChromeContentRendererClient::RenderThreadConnected();
+
+  render_manager_->RenderThreadConnected();
+}
+
+void ChromeContentRendererClientCef::RenderFrameCreated(
+    content::RenderFrame* render_frame) {
+  ChromeContentRendererClient::RenderFrameCreated(render_frame);
+
+  // Will delete itself when no longer needed.
+  CefRenderFrameObserver* render_frame_observer =
+      new CefRenderFrameObserver(render_frame);
+
+  bool browser_created;
+  absl::optional<bool> is_windowless;
+  render_manager_->RenderFrameCreated(render_frame, render_frame_observer,
+                                      browser_created, is_windowless);
+  if (is_windowless.has_value() && *is_windowless) {
+    LOG(ERROR) << "The chrome runtime does not support windowless browsers";
+  }
+}
+
+void ChromeContentRendererClientCef::WebViewCreated(
+    blink::WebView* web_view,
+    bool was_created_by_renderer,
+    const url::Origin* outermost_origin) {
+  ChromeContentRendererClient::WebViewCreated(web_view, was_created_by_renderer,
+                                              outermost_origin);
+
+  bool browser_created;
+  absl::optional<bool> is_windowless;
+  render_manager_->WebViewCreated(web_view, browser_created, is_windowless);
+  if (is_windowless.has_value() && *is_windowless) {
+    LOG(ERROR) << "The chrome runtime does not support windowless browsers";
+  }
+}
+
+void ChromeContentRendererClientCef::DevToolsAgentAttached() {
+  // WebWorkers may be creating agents on a different thread.
+  if (!render_task_runner_->BelongsToCurrentThread()) {
+    render_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&ChromeContentRendererClientCef::DevToolsAgentAttached,
+                       base::Unretained(this)));
+    return;
+  }
+
+  render_manager_->DevToolsAgentAttached();
+}
+
+void ChromeContentRendererClientCef::DevToolsAgentDetached() {
+  // WebWorkers may be creating agents on a different thread.
+  if (!render_task_runner_->BelongsToCurrentThread()) {
+    render_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&ChromeContentRendererClientCef::DevToolsAgentDetached,
+                       base::Unretained(this)));
+    return;
+  }
+
+  render_manager_->DevToolsAgentDetached();
+}
+
+void ChromeContentRendererClientCef::ExposeInterfacesToBrowser(
+    mojo::BinderMap* binders) {
+  ChromeContentRendererClient::ExposeInterfacesToBrowser(binders);
+
+  render_manager_->ExposeInterfacesToBrowser(binders);
+}
\ No newline at end of file
diff --git a/src/libcef/renderer/chrome/chrome_content_renderer_client_cef.h b/src/libcef/renderer/chrome/chrome_content_renderer_client_cef.h
new file mode 100644
index 0000000..09e4951
--- /dev/null
+++ b/src/libcef/renderer/chrome/chrome_content_renderer_client_cef.h
@@ -0,0 +1,55 @@
+// Copyright 2020 The Chromium Embedded Framework Authors.
+// Portions copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CEF_LIBCEF_RENDERER_CHROME_CHROME_CONTENT_RENDERER_CLIENT_CEF_
+#define CEF_LIBCEF_RENDERER_CHROME_CHROME_CONTENT_RENDERER_CLIENT_CEF_
+
+#include <memory>
+
+#include "base/memory/scoped_refptr.h"
+#include "base/task/single_thread_task_runner.h"
+#include "chrome/renderer/chrome_content_renderer_client.h"
+
+class CefRenderManager;
+
+// CEF override of ChromeContentRendererClient.
+class ChromeContentRendererClientCef : public ChromeContentRendererClient {
+ public:
+  ChromeContentRendererClientCef();
+
+  ChromeContentRendererClientCef(const ChromeContentRendererClientCef&) =
+      delete;
+  ChromeContentRendererClientCef& operator=(
+      const ChromeContentRendererClientCef&) = delete;
+
+  ~ChromeContentRendererClientCef() override;
+
+  // Render thread task runner.
+  base::SingleThreadTaskRunner* render_task_runner() const {
+    return render_task_runner_.get();
+  }
+
+  // Returns the task runner for the current thread. Returns NULL if the current
+  // thread is not the main render process thread.
+  scoped_refptr<base::SingleThreadTaskRunner> GetCurrentTaskRunner();
+
+  // ChromeContentRendererClient overrides.
+  void RenderThreadStarted() override;
+  void RenderThreadConnected() override;
+  void RenderFrameCreated(content::RenderFrame* render_frame) override;
+  void WebViewCreated(blink::WebView* web_view,
+                      bool was_created_by_renderer,
+                      const url::Origin* outermost_origin) override;
+  void DevToolsAgentAttached() override;
+  void DevToolsAgentDetached() override;
+  void ExposeInterfacesToBrowser(mojo::BinderMap* binders) override;
+
+ private:
+  std::unique_ptr<CefRenderManager> render_manager_;
+
+  scoped_refptr<base::SingleThreadTaskRunner> render_task_runner_;
+};
+
+#endif  // CEF_LIBCEF_RENDERER_CHROME_CHROME_CONTENT_RENDERER_CLIENT_CEF_
diff --git a/src/libcef/renderer/content_renderer_client.cc b/src/libcef/renderer/content_renderer_client.cc
deleted file mode 100644
index 8115e07..0000000
--- a/src/libcef/renderer/content_renderer_client.cc
+++ /dev/null
@@ -1,830 +0,0 @@
-// Copyright (c) 2013 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/renderer/content_renderer_client.h"
-
-#include <utility>
-
-#include "base/compiler_specific.h"
-
-// Enable deprecation warnings on Windows. See http://crbug.com/585142.
-#if defined(OS_WIN)
-#if defined(__clang__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic error "-Wdeprecated-declarations"
-#else
-#pragma warning(push)
-#pragma warning(default : 4996)
-#endif
-#endif
-
-#include "libcef/browser/content_browser_client.h"
-#include "libcef/browser/context.h"
-#include "libcef/common/cef_messages.h"
-#include "libcef/common/cef_switches.h"
-#include "libcef/common/content_client.h"
-#include "libcef/common/extensions/extensions_client.h"
-#include "libcef/common/extensions/extensions_util.h"
-#include "libcef/common/request_impl.h"
-#include "libcef/common/values_impl.h"
-#include "libcef/renderer/blink_glue.h"
-#include "libcef/renderer/browser_impl.h"
-#include "libcef/renderer/extensions/extensions_renderer_client.h"
-#include "libcef/renderer/extensions/print_render_frame_helper_delegate.h"
-#include "libcef/renderer/render_frame_observer.h"
-#include "libcef/renderer/render_thread_observer.h"
-#include "libcef/renderer/thread_util.h"
-#include "libcef/renderer/url_loader_throttle_provider_impl.h"
-#include "libcef/renderer/v8_impl.h"
-
-#include "base/command_line.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/metrics/user_metrics_action.h"
-#include "base/path_service.h"
-#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
-#include "build/build_config.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/renderer/browser_exposed_renderer_interfaces.h"
-#include "chrome/renderer/chrome_content_renderer_client.h"
-#include "chrome/renderer/extensions/chrome_extensions_renderer_client.h"
-#include "chrome/renderer/loadtimes_extension_bindings.h"
-#include "chrome/renderer/media/chrome_key_systems.h"
-#include "chrome/renderer/pepper/chrome_pdf_print_client.h"
-#include "chrome/renderer/pepper/pepper_helper.h"
-#include "chrome/renderer/plugins/chrome_plugin_placeholder.h"
-#include "components/content_settings/core/common/content_settings_types.h"
-#include "components/nacl/common/nacl_constants.h"
-#include "components/printing/renderer/print_render_frame_helper.h"
-#include "components/spellcheck/renderer/spellcheck.h"
-#include "components/spellcheck/renderer/spellcheck_provider.h"
-#include "components/visitedlink/renderer/visitedlink_reader.h"
-#include "components/web_cache/renderer/web_cache_impl.h"
-#include "content/common/frame_messages.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/child/child_thread.h"
-#include "content/public/common/content_constants.h"
-#include "content/public/common/content_paths.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/url_constants.h"
-#include "content/public/renderer/plugin_instance_throttler.h"
-#include "content/public/renderer/render_view.h"
-#include "content/public/renderer/render_view_visitor.h"
-#include "content/renderer/render_widget.h"
-#include "extensions/common/switches.h"
-#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.h"
-#include "extensions/renderer/renderer_extension_registry.h"
-#include "ipc/ipc_sync_channel.h"
-#include "media/base/media.h"
-#include "mojo/public/cpp/bindings/binder_map.h"
-#include "mojo/public/cpp/bindings/generic_pending_receiver.h"
-#include "printing/print_settings.h"
-#include "services/network/public/cpp/is_potentially_trustworthy.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
-#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/scheduler/web_renderer_process_type.h"
-#include "third_party/blink/public/platform/url_conversion.h"
-#include "third_party/blink/public/platform/web_runtime_features.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/public/web/web_console_message.h"
-#include "third_party/blink/public/web/web_element.h"
-#include "third_party/blink/public/web/web_frame.h"
-#include "third_party/blink/public/web/web_local_frame.h"
-#include "third_party/blink/public/web/web_prerenderer_client.h"
-#include "third_party/blink/public/web/web_security_policy.h"
-#include "third_party/blink/public/web/web_view.h"
-#include "ui/base/l10n/l10n_util.h"
-
-#if defined(OS_MACOSX)
-#include "base/mac/mac_util.h"
-#include "base/strings/sys_string_conversions.h"
-#endif
-
-namespace {
-
-// Stub implementation of blink::WebPrerendererClient.
-class CefPrerendererClient : public content::RenderViewObserver,
-                             public blink::WebPrerendererClient {
- public:
-  explicit CefPrerendererClient(content::RenderView* render_view)
-      : content::RenderViewObserver(render_view) {
-    DCHECK(render_view);
-    render_view->GetWebView()->SetPrerendererClient(this);
-  }
-
- private:
-  ~CefPrerendererClient() override {}
-
-  // RenderViewObserver methods:
-  void OnDestruct() override { delete this; }
-
-  // WebPrerendererClient methods:
-  bool IsPrefetchOnly() override { return false; }
-};
-
-bool IsStandaloneExtensionProcess() {
-  return extensions::ExtensionsEnabled() &&
-         extensions::CefExtensionsRendererClient::
-             IsStandaloneExtensionProcess();
-}
-
-}  // namespace
-
-// Placeholder object for guest views.
-class CefGuestView : public content::RenderViewObserver {
- public:
-  CefGuestView(content::RenderView* render_view, bool is_windowless)
-      : content::RenderViewObserver(render_view),
-        is_windowless_(is_windowless) {}
-
-  bool is_windowless() const { return is_windowless_; }
-
- private:
-  // RenderViewObserver methods.
-  void OnDestruct() override {
-    CefContentRendererClient::Get()->OnGuestViewDestroyed(this);
-  }
-
-  const bool is_windowless_;
-};
-
-CefContentRendererClient::CefContentRendererClient()
-    : main_entry_time_(base::TimeTicks::Now()),
-      devtools_agent_count_(0),
-      uncaught_exception_stack_size_(0),
-      single_process_cleanup_complete_(false) {
-  if (extensions::ExtensionsEnabled()) {
-    extensions_client_.reset(new extensions::CefExtensionsClient);
-    extensions::ExtensionsClient::Set(extensions_client_.get());
-    extensions_renderer_client_.reset(
-        new extensions::CefExtensionsRendererClient);
-    extensions::ExtensionsRendererClient::Set(
-        extensions_renderer_client_.get());
-  }
-}
-
-CefContentRendererClient::~CefContentRendererClient() {}
-
-// static
-CefContentRendererClient* CefContentRendererClient::Get() {
-  return static_cast<CefContentRendererClient*>(
-      CefContentClient::Get()->renderer());
-}
-
-CefRefPtr<CefBrowserImpl> CefContentRendererClient::GetBrowserForView(
-    content::RenderView* view) {
-  CEF_REQUIRE_RT_RETURN(nullptr);
-
-  BrowserMap::const_iterator it = browsers_.find(view);
-  if (it != browsers_.end())
-    return it->second;
-  return nullptr;
-}
-
-CefRefPtr<CefBrowserImpl> CefContentRendererClient::GetBrowserForMainFrame(
-    blink::WebFrame* frame) {
-  CEF_REQUIRE_RT_RETURN(nullptr);
-
-  BrowserMap::const_iterator it = browsers_.begin();
-  for (; it != browsers_.end(); ++it) {
-    content::RenderView* render_view = it->second->render_view();
-    if (render_view && render_view->GetWebView() &&
-        render_view->GetWebView()->MainFrame() == frame) {
-      return it->second;
-    }
-  }
-
-  return nullptr;
-}
-
-void CefContentRendererClient::OnBrowserDestroyed(CefBrowserImpl* browser) {
-  BrowserMap::iterator it = browsers_.begin();
-  for (; it != browsers_.end(); ++it) {
-    if (it->second.get() == browser) {
-      browsers_.erase(it);
-      return;
-    }
-  }
-
-  // No browser was found in the map.
-  NOTREACHED();
-}
-
-CefGuestView* CefContentRendererClient::GetGuestViewForView(
-    content::RenderView* view) {
-  CEF_REQUIRE_RT_RETURN(nullptr);
-
-  GuestViewMap::const_iterator it = guest_views_.find(view);
-  if (it != guest_views_.end())
-    return it->second.get();
-  return nullptr;
-}
-
-void CefContentRendererClient::OnGuestViewDestroyed(CefGuestView* guest_view) {
-  GuestViewMap::iterator it = guest_views_.begin();
-  for (; it != guest_views_.end(); ++it) {
-    if (it->second.get() == guest_view) {
-      guest_views_.erase(it);
-      return;
-    }
-  }
-
-  // No guest view was found in the map.
-  NOTREACHED();
-}
-
-blink::WebURLLoaderFactory*
-CefContentRendererClient::GetDefaultURLLoaderFactory() {
-  if (!default_url_loader_factory_) {
-    default_url_loader_factory_ =
-        blink::Platform::Current()->CreateDefaultURLLoaderFactory();
-  }
-  return default_url_loader_factory_.get();
-}
-
-void CefContentRendererClient::WebKitInitialized() {
-  const base::CommandLine* command_line =
-      base::CommandLine::ForCurrentProcess();
-
-  // Create global objects associated with the default Isolate.
-  CefV8IsolateCreated();
-
-  // TODO(cef): Enable these once the implementation supports it.
-  blink::WebRuntimeFeatures::EnableNotifications(false);
-
-  const CefContentClient::SchemeInfoList* schemes =
-      CefContentClient::Get()->GetCustomSchemes();
-  if (!schemes->empty()) {
-    // Register the custom schemes. The |is_standard| value is excluded here
-    // because it's not explicitly registered with Blink.
-    CefContentClient::SchemeInfoList::const_iterator it = schemes->begin();
-    for (; it != schemes->end(); ++it) {
-      const CefContentClient::SchemeInfo& info = *it;
-      const blink::WebString& scheme =
-          blink::WebString::FromUTF8(info.scheme_name);
-      if (info.is_local)
-        blink_glue::RegisterURLSchemeAsLocal(scheme);
-      if (info.is_display_isolated)
-        blink::WebSecurityPolicy::RegisterURLSchemeAsDisplayIsolated(scheme);
-      if (info.is_secure)
-        blink_glue::RegisterURLSchemeAsSecure(scheme);
-      if (info.is_fetch_enabled)
-        blink_glue::RegisterURLSchemeAsSupportingFetchAPI(scheme);
-    }
-  }
-
-  if (!cross_origin_whitelist_entries_.empty()) {
-    // Add the cross-origin white list entries.
-    for (size_t i = 0; i < cross_origin_whitelist_entries_.size(); ++i) {
-      const Cef_CrossOriginWhiteListEntry_Params& entry =
-          cross_origin_whitelist_entries_[i];
-      GURL gurl = GURL(entry.source_origin);
-      blink::WebSecurityPolicy::AddOriginAccessAllowListEntry(
-          gurl, blink::WebString::FromUTF8(entry.target_protocol),
-          blink::WebString::FromUTF8(entry.target_domain),
-          /*destination_port=*/0,
-          entry.allow_target_subdomains
-              ? network::mojom::CorsDomainMatchMode::kAllowSubdomains
-              : network::mojom::CorsDomainMatchMode::kDisallowSubdomains,
-          network::mojom::CorsPortMatchMode::kAllowAnyPort,
-          network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
-    }
-    cross_origin_whitelist_entries_.clear();
-  }
-
-  // The number of stack trace frames to capture for uncaught exceptions.
-  if (command_line->HasSwitch(switches::kUncaughtExceptionStackSize)) {
-    int uncaught_exception_stack_size = 0;
-    base::StringToInt(command_line->GetSwitchValueASCII(
-                          switches::kUncaughtExceptionStackSize),
-                      &uncaught_exception_stack_size);
-
-    if (uncaught_exception_stack_size > 0) {
-      uncaught_exception_stack_size_ = uncaught_exception_stack_size;
-      CefV8SetUncaughtExceptionStackSize(uncaught_exception_stack_size_);
-    }
-  }
-
-  // Notify the render process handler.
-  CefRefPtr<CefApp> application = CefContentClient::Get()->application();
-  if (application.get()) {
-    CefRefPtr<CefRenderProcessHandler> handler =
-        application->GetRenderProcessHandler();
-    if (handler.get())
-      handler->OnWebKitInitialized();
-  }
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-CefContentRendererClient::GetCurrentTaskRunner() {
-  // Check if currently on the render thread.
-  if (CEF_CURRENTLY_ON_RT())
-    return render_task_runner_;
-  return nullptr;
-}
-
-void CefContentRendererClient::RunSingleProcessCleanup() {
-  DCHECK(content::RenderProcessHost::run_renderer_in_process());
-
-  // Make sure the render thread was actually started.
-  if (!render_task_runner_.get())
-    return;
-
-  if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
-    RunSingleProcessCleanupOnUIThread();
-  } else {
-    base::PostTask(
-        FROM_HERE, {content::BrowserThread::UI},
-        base::Bind(&CefContentRendererClient::RunSingleProcessCleanupOnUIThread,
-                   base::Unretained(this)));
-  }
-
-  // Wait for the render thread cleanup to complete. Spin instead of using
-  // base::WaitableEvent because calling Wait() is not allowed on the UI
-  // thread.
-  bool complete = false;
-  do {
-    {
-      base::AutoLock lock_scope(single_process_cleanup_lock_);
-      complete = single_process_cleanup_complete_;
-    }
-    if (!complete)
-      base::PlatformThread::YieldCurrentThread();
-  } while (!complete);
-}
-
-void CefContentRendererClient::RenderThreadStarted() {
-  const base::CommandLine* command_line =
-      base::CommandLine::ForCurrentProcess();
-
-  render_task_runner_ = base::ThreadTaskRunnerHandle::Get();
-  observer_ = std::make_unique<CefRenderThreadObserver>();
-  web_cache_impl_ = std::make_unique<web_cache::WebCacheImpl>();
-  visited_link_slave_ = std::make_unique<visitedlink::VisitedLinkReader>();
-
-  content::RenderThread* thread = content::RenderThread::Get();
-
-  thread->SetRendererProcessType(
-      IsStandaloneExtensionProcess()
-          ? blink::scheduler::WebRendererProcessType::kExtensionRenderer
-          : blink::scheduler::WebRendererProcessType::kRenderer);
-
-  thread->AddObserver(observer_.get());
-
-  if (!command_line->HasSwitch(switches::kDisableSpellChecking)) {
-    spellcheck_ = std::make_unique<SpellCheck>(this);
-  }
-
-  if (content::RenderProcessHost::run_renderer_in_process()) {
-    // When running in single-process mode register as a destruction observer
-    // on the render thread's MessageLoop.
-    base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
-  }
-
-#if defined(OS_MACOSX)
-  {
-    base::ScopedCFTypeRef<CFStringRef> key(
-        base::SysUTF8ToCFStringRef("NSScrollViewRubberbanding"));
-    base::ScopedCFTypeRef<CFStringRef> value;
-
-    // If the command-line switch is specified then set the value that will be
-    // checked in RenderThreadImpl::Init(). Otherwise, remove the application-
-    // level value.
-    if (command_line->HasSwitch(switches::kDisableScrollBounce))
-      value.reset(base::SysUTF8ToCFStringRef("false"));
-
-    CFPreferencesSetAppValue(key, value, kCFPreferencesCurrentApplication);
-    CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
-  }
-#endif  // defined(OS_MACOSX)
-
-  if (extensions::PdfExtensionEnabled()) {
-    pdf_print_client_.reset(new ChromePDFPrintClient());
-    pdf::PepperPDFHost::SetPrintClient(pdf_print_client_.get());
-  }
-
-  for (auto& origin_or_hostname_pattern :
-       network::SecureOriginAllowlist::GetInstance().GetCurrentAllowlist()) {
-    blink::WebSecurityPolicy::AddOriginToTrustworthySafelist(
-        blink::WebString::FromUTF8(origin_or_hostname_pattern));
-  }
-
-  if (extensions::ExtensionsEnabled())
-    extensions_renderer_client_->RenderThreadStarted();
-}
-
-void CefContentRendererClient::ExposeInterfacesToBrowser(
-    mojo::BinderMap* binders) {
-  auto task_runner = base::SequencedTaskRunnerHandle::Get();
-
-  binders->Add(base::BindRepeating(&web_cache::WebCacheImpl::BindReceiver,
-                                   base::Unretained(web_cache_impl_.get())),
-               task_runner);
-
-  binders->Add(visited_link_slave_->GetBindCallback(), task_runner);
-
-  if (spellcheck_) {
-    binders->Add(
-        base::BindRepeating(
-            [](SpellCheck* spellcheck,
-               mojo::PendingReceiver<spellcheck::mojom::SpellChecker>
-                   receiver) { spellcheck->BindReceiver(std::move(receiver)); },
-            base::Unretained(spellcheck_.get())),
-        task_runner);
-  }
-}
-
-void CefContentRendererClient::RenderThreadConnected() {
-  content::RenderThread* thread = content::RenderThread::Get();
-
-  // Retrieve the new render thread information synchronously.
-  CefProcessHostMsg_GetNewRenderThreadInfo_Params params;
-  thread->Send(new CefProcessHostMsg_GetNewRenderThreadInfo(&params));
-
-  // Cross-origin entries need to be added after WebKit is initialized.
-  cross_origin_whitelist_entries_ = params.cross_origin_whitelist_entries;
-
-  // Notify the render process handler.
-  CefRefPtr<CefApp> application = CefContentClient::Get()->application();
-  if (application.get()) {
-    CefRefPtr<CefRenderProcessHandler> handler =
-        application->GetRenderProcessHandler();
-    if (handler.get()) {
-      CefRefPtr<CefListValueImpl> listValuePtr(
-          new CefListValueImpl(&params.extra_info, false, true));
-      handler->OnRenderThreadCreated(listValuePtr.get());
-      listValuePtr->Detach(nullptr);
-    }
-  }
-
-  // Register extensions last because it will trigger WebKit initialization.
-  thread->RegisterExtension(extensions_v8::LoadTimesExtension::Get());
-
-  WebKitInitialized();
-}
-
-void CefContentRendererClient::RenderFrameCreated(
-    content::RenderFrame* render_frame) {
-  CefRenderFrameObserver* render_frame_observer =
-      new CefRenderFrameObserver(render_frame);
-  service_manager::BinderRegistry* registry = render_frame_observer->registry();
-
-  new PepperHelper(render_frame);
-
-  if (extensions::ExtensionsEnabled()) {
-    extensions_renderer_client_->RenderFrameCreated(render_frame, registry);
-
-    blink::AssociatedInterfaceRegistry* associated_interfaces =
-        render_frame_observer->associated_interfaces();
-    associated_interfaces->AddInterface(base::BindRepeating(
-        &extensions::MimeHandlerViewContainerManager::BindReceiver,
-        render_frame->GetRoutingID()));
-  }
-
-  const base::CommandLine* command_line =
-      base::CommandLine::ForCurrentProcess();
-  if (!command_line->HasSwitch(switches::kDisableSpellChecking)) {
-    new SpellCheckProvider(render_frame, spellcheck_.get(), this);
-  }
-
-  base::Optional<bool> is_windowless;
-
-  auto browser = MaybeCreateBrowser(render_frame->GetRenderView(), render_frame,
-                                    &is_windowless);
-  if (browser) {
-    // Attach the frame to the observer for message routing purposes.
-    render_frame_observer->AttachFrame(
-        browser->GetWebFrameImpl(render_frame->GetWebFrame()).get());
-  }
-
-  if (is_windowless.has_value()) {
-    new printing::PrintRenderFrameHelper(
-        render_frame,
-        base::WrapUnique(
-            new extensions::CefPrintRenderFrameHelperDelegate(*is_windowless)));
-  }
-}
-
-void CefContentRendererClient::RenderViewCreated(
-    content::RenderView* render_view) {
-  new CefPrerendererClient(render_view);
-
-  MaybeCreateBrowser(render_view, render_view->GetMainRenderFrame(), nullptr);
-}
-
-bool CefContentRendererClient::IsPluginHandledExternally(
-    content::RenderFrame* render_frame,
-    const blink::WebElement& plugin_element,
-    const GURL& original_url,
-    const std::string& mime_type) {
-  if (!extensions::ExtensionsEnabled())
-    return false;
-
-  DCHECK(plugin_element.HasHTMLTagName("object") ||
-         plugin_element.HasHTMLTagName("embed"));
-  // Blink will next try to load a WebPlugin which would end up in
-  // OverrideCreatePlugin, sending another IPC only to find out the plugin is
-  // not supported. Here it suffices to return false but there should perhaps be
-  // a more unified approach to avoid sending the IPC twice.
-  chrome::mojom::PluginInfoPtr plugin_info = chrome::mojom::PluginInfo::New();
-  ChromeContentRendererClient::GetPluginInfoHost()->GetPluginInfo(
-      render_frame->GetRoutingID(), original_url,
-      render_frame->GetWebFrame()->Top()->GetSecurityOrigin(), mime_type,
-      &plugin_info);
-  // TODO(ekaramad): Not continuing here due to a disallowed status should take
-  // us to CreatePlugin. See if more in depths investigation of |status| is
-  // necessary here (see https://crbug.com/965747). For now, returning false
-  // should take us to CreatePlugin after HTMLPlugInElement which is called
-  // through HTMLPlugInElement::LoadPlugin code path.
-  if (plugin_info->status != chrome::mojom::PluginStatus::kAllowed &&
-      plugin_info->status !=
-          chrome::mojom::PluginStatus::kPlayImportantContent) {
-    // We could get here when a MimeHandlerView is loaded inside a <webview>
-    // which is using permissions API (see WebViewPluginTests).
-    ChromeExtensionsRendererClient::DidBlockMimeHandlerViewForDisallowedPlugin(
-        plugin_element);
-    return false;
-  }
-  return ChromeExtensionsRendererClient::MaybeCreateMimeHandlerView(
-      plugin_element, original_url, plugin_info->actual_mime_type,
-      plugin_info->plugin);
-}
-
-bool CefContentRendererClient::OverrideCreatePlugin(
-    content::RenderFrame* render_frame,
-    const blink::WebPluginParams& params,
-    blink::WebPlugin** plugin) {
-  std::string orig_mime_type = params.mime_type.Utf8();
-  if (extensions::ExtensionsEnabled() &&
-      !extensions_renderer_client_->OverrideCreatePlugin(render_frame,
-                                                         params)) {
-    return false;
-  }
-
-  GURL url(params.url);
-  chrome::mojom::PluginInfoPtr plugin_info = chrome::mojom::PluginInfo::New();
-  ChromeContentRendererClient::GetPluginInfoHost()->GetPluginInfo(
-      render_frame->GetRoutingID(), url,
-      render_frame->GetWebFrame()->Top()->GetSecurityOrigin(), orig_mime_type,
-      &plugin_info);
-  *plugin = ChromeContentRendererClient::CreatePlugin(render_frame, params,
-                                                      *plugin_info);
-  return true;
-}
-
-void CefContentRendererClient::WillSendRequest(
-    blink::WebLocalFrame* frame,
-    ui::PageTransition transition_type,
-    const blink::WebURL& url,
-    const net::SiteForCookies& site_for_cookies,
-    const url::Origin* initiator_origin,
-    GURL* new_url,
-    bool* attach_same_site_cookies) {
-  if (extensions::ExtensionsEnabled()) {
-    extensions_renderer_client_->WillSendRequest(
-        frame, transition_type, url, site_for_cookies, initiator_origin,
-        new_url, attach_same_site_cookies);
-    if (!new_url->is_empty())
-      return;
-  }
-}
-
-uint64_t CefContentRendererClient::VisitedLinkHash(const char* canonical_url,
-                                                   size_t length) {
-  return visited_link_slave_->ComputeURLFingerprint(canonical_url, length);
-}
-
-bool CefContentRendererClient::IsLinkVisited(uint64_t link_hash) {
-  return visited_link_slave_->IsVisited(link_hash);
-}
-
-bool CefContentRendererClient::IsOriginIsolatedPepperPlugin(
-    const base::FilePath& plugin_path) {
-  return plugin_path ==
-         base::FilePath::FromUTF8Unsafe(CefContentClient::kPDFPluginPath);
-}
-
-content::BrowserPluginDelegate*
-CefContentRendererClient::CreateBrowserPluginDelegate(
-    content::RenderFrame* render_frame,
-    const content::WebPluginInfo& info,
-    const std::string& mime_type,
-    const GURL& original_url) {
-  DCHECK(extensions::ExtensionsEnabled());
-  return extensions::CefExtensionsRendererClient::CreateBrowserPluginDelegate(
-      render_frame, info, mime_type, original_url);
-}
-
-void CefContentRendererClient::AddSupportedKeySystems(
-    std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems) {
-  AddChromeKeySystems(key_systems);
-}
-
-void CefContentRendererClient::RunScriptsAtDocumentStart(
-    content::RenderFrame* render_frame) {
-  if (extensions::ExtensionsEnabled())
-    extensions_renderer_client_->RunScriptsAtDocumentStart(render_frame);
-}
-
-void CefContentRendererClient::RunScriptsAtDocumentEnd(
-    content::RenderFrame* render_frame) {
-  if (extensions::ExtensionsEnabled())
-    extensions_renderer_client_->RunScriptsAtDocumentEnd(render_frame);
-}
-
-void CefContentRendererClient::RunScriptsAtDocumentIdle(
-    content::RenderFrame* render_frame) {
-  if (extensions::ExtensionsEnabled())
-    extensions_renderer_client_->RunScriptsAtDocumentIdle(render_frame);
-}
-
-void CefContentRendererClient::DevToolsAgentAttached() {
-  // WebWorkers may be creating agents on a different thread.
-  if (!render_task_runner_->BelongsToCurrentThread()) {
-    render_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&CefContentRendererClient::DevToolsAgentAttached,
-                       base::Unretained(this)));
-    return;
-  }
-
-  ++devtools_agent_count_;
-}
-
-void CefContentRendererClient::DevToolsAgentDetached() {
-  // WebWorkers may be creating agents on a different thread.
-  if (!render_task_runner_->BelongsToCurrentThread()) {
-    render_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&CefContentRendererClient::DevToolsAgentDetached,
-                       base::Unretained(this)));
-    return;
-  }
-
-  --devtools_agent_count_;
-  if (devtools_agent_count_ == 0 && uncaught_exception_stack_size_ > 0) {
-    // When the last DevToolsAgent is detached the stack size is set to 0.
-    // Restore the user-specified stack size here.
-    CefV8SetUncaughtExceptionStackSize(uncaught_exception_stack_size_);
-  }
-}
-
-std::unique_ptr<content::URLLoaderThrottleProvider>
-CefContentRendererClient::CreateURLLoaderThrottleProvider(
-    content::URLLoaderThrottleProviderType provider_type) {
-  return std::make_unique<CefURLLoaderThrottleProviderImpl>(provider_type);
-}
-
-bool CefContentRendererClient::RequiresWebComponentsV0(const GURL& url) {
-  // TODO(1025782): For now, file:// URLs are allowed to access Web Components
-  // v0 features. This will be removed once origin trials support file:// URLs
-  // for this purpose.
-  return url.SchemeIs(content::kChromeUIScheme) || url.SchemeIs("file");
-}
-
-void CefContentRendererClient::GetInterface(
-    const std::string& interface_name,
-    mojo::ScopedMessagePipeHandle interface_pipe) {
-  // TODO(crbug.com/977637): Get rid of the use of this implementation of
-  // |service_manager::LocalInterfaceProvider|. This was done only to avoid
-  // churning spellcheck code while eliminating the "chrome" and
-  // "chrome_renderer" services. Spellcheck is (and should remain) the only
-  // consumer of this implementation.
-  content::RenderThread::Get()->BindHostReceiver(
-      mojo::GenericPendingReceiver(interface_name, std::move(interface_pipe)));
-}
-
-void CefContentRendererClient::WillDestroyCurrentMessageLoop() {
-  base::AutoLock lock_scope(single_process_cleanup_lock_);
-  single_process_cleanup_complete_ = true;
-}
-
-CefRefPtr<CefBrowserImpl> CefContentRendererClient::MaybeCreateBrowser(
-    content::RenderView* render_view,
-    content::RenderFrame* render_frame,
-    base::Optional<bool>* is_windowless) {
-  if (!render_view || !render_frame)
-    return nullptr;
-
-  // Don't create another browser or guest view object if one already exists for
-  // the view.
-  auto browser = GetBrowserForView(render_view);
-  if (browser) {
-    if (is_windowless) {
-      *is_windowless = browser->is_windowless();
-    }
-    return browser;
-  }
-
-  auto guest_view = GetGuestViewForView(render_view);
-  if (guest_view) {
-    if (is_windowless) {
-      *is_windowless = guest_view->is_windowless();
-    }
-    return nullptr;
-  }
-
-  const int render_frame_routing_id = render_frame->GetRoutingID();
-
-  // Retrieve the browser information synchronously. This will also register
-  // the routing ids with the browser info object in the browser process.
-  CefProcessHostMsg_GetNewBrowserInfo_Params params;
-  content::RenderThread::Get()->Send(new CefProcessHostMsg_GetNewBrowserInfo(
-      render_frame_routing_id, &params));
-
-  if (is_windowless) {
-    *is_windowless = params.is_windowless;
-  }
-
-  if (params.browser_id == 0) {
-    // The popup may have been canceled during creation.
-    return nullptr;
-  }
-
-  if (params.is_guest_view || params.browser_id < 0) {
-    // Don't create a CefBrowser for guest views, or if the new browser info
-    // response has timed out.
-    guest_views_.insert(std::make_pair(
-        render_view,
-        std::make_unique<CefGuestView>(render_view, params.is_windowless)));
-    return nullptr;
-  }
-
-#if defined(OS_MACOSX)
-  // FIXME: It would be better if this API would be a callback from the
-  // WebKit layer, or if it would be exposed as an WebView instance method; the
-  // current implementation uses a static variable, and WebKit needs to be
-  // patched in order to make it work for each WebView instance
-  render_view->GetWebView()->SetUseExternalPopupMenusThisInstance(
-      !params.is_windowless);
-#endif
-
-  browser = new CefBrowserImpl(render_view, params.browser_id, params.is_popup,
-                               params.is_windowless);
-  browsers_.insert(std::make_pair(render_view, browser));
-
-  // Notify the render process handler.
-  CefRefPtr<CefApp> application = CefContentClient::Get()->application();
-  if (application.get()) {
-    CefRefPtr<CefRenderProcessHandler> handler =
-        application->GetRenderProcessHandler();
-    if (handler.get()) {
-      CefRefPtr<CefDictionaryValueImpl> dictValuePtr(
-          new CefDictionaryValueImpl(&params.extra_info, false, true));
-      handler->OnBrowserCreated(browser.get(), dictValuePtr.get());
-      dictValuePtr->Detach(nullptr);
-    }
-  }
-
-  return browser;
-}
-
-void CefContentRendererClient::RunSingleProcessCleanupOnUIThread() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-  // Clean up the single existing RenderProcessHost.
-  content::RenderProcessHost* host = nullptr;
-  content::RenderProcessHost::iterator iterator(
-      content::RenderProcessHost::AllHostsIterator());
-  if (!iterator.IsAtEnd()) {
-    host = iterator.GetCurrentValue();
-    host->Cleanup();
-    iterator.Advance();
-    DCHECK(iterator.IsAtEnd());
-  }
-  DCHECK(host);
-
-  // Clear the run_renderer_in_process() flag to avoid a DCHECK in the
-  // RenderProcessHost destructor.
-  content::RenderProcessHost::SetRunRendererInProcess(false);
-
-  // Deletion of the RenderProcessHost object will stop the render thread and
-  // result in a call to WillDestroyCurrentMessageLoop.
-  // Cleanup() will cause deletion to be posted as a task on the UI thread but
-  // this task will only execute when running in multi-threaded message loop
-  // mode (because otherwise the UI message loop has already stopped). Therefore
-  // we need to explicitly delete the object when not running in this mode.
-  if (!CefContext::Get()->settings().multi_threaded_message_loop)
-    delete host;
-}
-
-// Enable deprecation warnings on Windows. See http://crbug.com/585142.
-#if defined(OS_WIN)
-#if defined(__clang__)
-#pragma GCC diagnostic pop
-#else
-#pragma warning(pop)
-#endif
-#endif
diff --git a/src/libcef/renderer/content_renderer_client.h b/src/libcef/renderer/content_renderer_client.h
deleted file mode 100644
index 19e83d6..0000000
--- a/src/libcef/renderer/content_renderer_client.h
+++ /dev/null
@@ -1,206 +0,0 @@
-// Copyright (c) 2013 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_RENDERER_CONTENT_RENDERER_CLIENT_H_
-#define CEF_LIBCEF_RENDERER_CONTENT_RENDERER_CLIENT_H_
-#pragma once
-
-#include <list>
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "libcef/renderer/browser_impl.h"
-
-#include "base/compiler_specific.h"
-#include "base/message_loop/message_loop_current.h"
-#include "base/optional.h"
-#include "base/sequenced_task_runner.h"
-#include "chrome/common/plugin.mojom.h"
-#include "content/public/renderer/content_renderer_client.h"
-#include "content/public/renderer/render_thread.h"
-#include "mojo/public/cpp/bindings/generic_pending_receiver.h"
-#include "services/service_manager/public/cpp/local_interface_provider.h"
-
-namespace blink {
-class WebURLLoaderFactory;
-}
-
-namespace extensions {
-class CefExtensionsRendererClient;
-class Dispatcher;
-class DispatcherDelegate;
-class ExtensionsClient;
-class ExtensionsGuestViewContainerDispatcher;
-class ExtensionsRendererClient;
-class ResourceRequestPolicy;
-}  // namespace extensions
-
-namespace visitedlink {
-class VisitedLinkReader;
-}
-
-namespace web_cache {
-class WebCacheImpl;
-}
-
-class CefGuestView;
-class CefRenderThreadObserver;
-struct Cef_CrossOriginWhiteListEntry_Params;
-class ChromePDFPrintClient;
-class SpellCheck;
-
-class CefContentRendererClient
-    : public content::ContentRendererClient,
-      public service_manager::LocalInterfaceProvider,
-      public base::MessageLoopCurrent::DestructionObserver {
- public:
-  CefContentRendererClient();
-  ~CefContentRendererClient() override;
-
-  // Returns the singleton CefContentRendererClient instance.
-  static CefContentRendererClient* Get();
-
-  // Returns the browser associated with the specified RenderView.
-  CefRefPtr<CefBrowserImpl> GetBrowserForView(content::RenderView* view);
-
-  // Returns the browser associated with the specified main WebFrame.
-  CefRefPtr<CefBrowserImpl> GetBrowserForMainFrame(blink::WebFrame* frame);
-
-  // Called from CefBrowserImpl::OnDestruct().
-  void OnBrowserDestroyed(CefBrowserImpl* browser);
-
-  // Returns the guest view associated with the specified RenderView if any.
-  CefGuestView* GetGuestViewForView(content::RenderView* view);
-
-  // Called from CefGuestView::OnDestruct().
-  void OnGuestViewDestroyed(CefGuestView* guest_view);
-
-  // Render thread task runner.
-  base::SingleThreadTaskRunner* render_task_runner() const {
-    return render_task_runner_.get();
-  }
-
-  int uncaught_exception_stack_size() const {
-    return uncaught_exception_stack_size_;
-  }
-
-  // Returns a factory that only supports unintercepted http(s) and blob
-  // requests. Used by CefRenderURLRequest.
-  blink::WebURLLoaderFactory* GetDefaultURLLoaderFactory();
-
-  void WebKitInitialized();
-
-  // Returns the task runner for the current thread. Returns NULL if the current
-  // thread is not the main render process thread.
-  scoped_refptr<base::SingleThreadTaskRunner> GetCurrentTaskRunner();
-
-  // Perform cleanup work that needs to occur before shutdown when running in
-  // single-process mode. Blocks until cleanup is complete.
-  void RunSingleProcessCleanup();
-
-  // ContentRendererClient implementation.
-  void RenderThreadStarted() override;
-  void ExposeInterfacesToBrowser(mojo::BinderMap* binders) override;
-  void RenderThreadConnected() override;
-  void RenderFrameCreated(content::RenderFrame* render_frame) override;
-  void RenderViewCreated(content::RenderView* render_view) override;
-  bool IsPluginHandledExternally(content::RenderFrame* render_frame,
-                                 const blink::WebElement& plugin_element,
-                                 const GURL& original_url,
-                                 const std::string& mime_type) override;
-  bool OverrideCreatePlugin(content::RenderFrame* render_frame,
-                            const blink::WebPluginParams& params,
-                            blink::WebPlugin** plugin) override;
-  void WillSendRequest(blink::WebLocalFrame* frame,
-                       ui::PageTransition transition_type,
-                       const blink::WebURL& url,
-                       const net::SiteForCookies& site_for_cookies,
-                       const url::Origin* initiator_origin,
-                       GURL* new_url,
-                       bool* attach_same_site_cookies) override;
-  uint64_t VisitedLinkHash(const char* canonical_url, size_t length) override;
-  bool IsLinkVisited(uint64_t link_hash) override;
-  bool IsOriginIsolatedPepperPlugin(const base::FilePath& plugin_path) override;
-  content::BrowserPluginDelegate* CreateBrowserPluginDelegate(
-      content::RenderFrame* render_frame,
-      const content::WebPluginInfo& info,
-      const std::string& mime_type,
-      const GURL& original_url) override;
-  void AddSupportedKeySystems(
-      std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems)
-      override;
-  void RunScriptsAtDocumentStart(content::RenderFrame* render_frame) override;
-  void RunScriptsAtDocumentEnd(content::RenderFrame* render_frame) override;
-  void RunScriptsAtDocumentIdle(content::RenderFrame* render_frame) override;
-  void DevToolsAgentAttached() override;
-  void DevToolsAgentDetached() override;
-  std::unique_ptr<content::URLLoaderThrottleProvider>
-  CreateURLLoaderThrottleProvider(
-      content::URLLoaderThrottleProviderType provider_type) override;
-  bool RequiresWebComponentsV0(const GURL& url) override;
-
-  // service_manager::LocalInterfaceProvider implementation.
-  void GetInterface(const std::string& name,
-                    mojo::ScopedMessagePipeHandle request_handle) override;
-
-  // MessageLoopCurrent::DestructionObserver implementation.
-  void WillDestroyCurrentMessageLoop() override;
-
- private:
-  // Maybe create a new browser object, return the existing one, or return
-  // nullptr for guest views.
-  CefRefPtr<CefBrowserImpl> MaybeCreateBrowser(
-      content::RenderView* render_view,
-      content::RenderFrame* render_frame,
-      base::Optional<bool>* is_windowless);
-
-  // Perform cleanup work for single-process mode.
-  void RunSingleProcessCleanupOnUIThread();
-
-  // Time at which this object was created. This is very close to the time at
-  // which the RendererMain function was entered.
-  base::TimeTicks main_entry_time_;
-
-  scoped_refptr<base::SingleThreadTaskRunner> render_task_runner_;
-  std::unique_ptr<CefRenderThreadObserver> observer_;
-  std::unique_ptr<web_cache::WebCacheImpl> web_cache_impl_;
-  std::unique_ptr<SpellCheck> spellcheck_;
-  std::unique_ptr<visitedlink::VisitedLinkReader> visited_link_slave_;
-
-  std::unique_ptr<blink::WebURLLoaderFactory> default_url_loader_factory_;
-
-  // Map of RenderView pointers to CefBrowserImpl references.
-  typedef std::map<content::RenderView*, CefRefPtr<CefBrowserImpl>> BrowserMap;
-  BrowserMap browsers_;
-
-  // Map of RenderView poiners to CefGuestView implementations.
-  typedef std::map<content::RenderView*, std::unique_ptr<CefGuestView>>
-      GuestViewMap;
-  GuestViewMap guest_views_;
-
-  // Cross-origin white list entries that need to be registered with WebKit.
-  typedef std::vector<Cef_CrossOriginWhiteListEntry_Params> CrossOriginList;
-  CrossOriginList cross_origin_whitelist_entries_;
-
-  std::unique_ptr<ChromePDFPrintClient> pdf_print_client_;
-
-  std::unique_ptr<extensions::ExtensionsClient> extensions_client_;
-  std::unique_ptr<extensions::CefExtensionsRendererClient>
-      extensions_renderer_client_;
-
-  int devtools_agent_count_;
-  int uncaught_exception_stack_size_;
-
-  // Used in single-process mode to test when cleanup is complete.
-  // Access must be protected by |single_process_cleanup_lock_|.
-  bool single_process_cleanup_complete_;
-  base::Lock single_process_cleanup_lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefContentRendererClient);
-};
-
-#endif  // CEF_LIBCEF_RENDERER_CONTENT_RENDERER_CLIENT_H_
diff --git a/src/libcef/renderer/dom_document_impl.cc b/src/libcef/renderer/dom_document_impl.cc
index 4685cff..09cc213 100644
--- a/src/libcef/renderer/dom_document_impl.cc
+++ b/src/libcef/renderer/dom_document_impl.cc
@@ -38,16 +38,20 @@
 }
 
 CefDOMDocumentImpl::Type CefDOMDocumentImpl::GetType() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return DOM_DOCUMENT_TYPE_UNKNOWN;
+  }
 
   const WebDocument& document = frame_->GetDocument();
-  if (document.IsHTMLDocument())
+  if (document.IsHTMLDocument()) {
     return DOM_DOCUMENT_TYPE_HTML;
-  if (document.IsXHTMLDocument())
+  }
+  if (document.IsXHTMLDocument()) {
     return DOM_DOCUMENT_TYPE_XHTML;
-  if (document.IsPluginDocument())
+  }
+  if (document.IsPluginDocument()) {
     return DOM_DOCUMENT_TYPE_PLUGIN;
+  }
   return DOM_DOCUMENT_TYPE_UNKNOWN;
 }
 
@@ -68,13 +72,15 @@
 
 CefString CefDOMDocumentImpl::GetTitle() {
   CefString str;
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return str;
+  }
 
   const WebDocument& document = frame_->GetDocument();
   const WebString& title = document.Title();
-  if (!title.IsNull())
+  if (!title.IsNull()) {
     str = title.Utf16();
+  }
 
   return str;
 }
@@ -91,74 +97,88 @@
 }
 
 bool CefDOMDocumentImpl::HasSelection() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   return frame_->HasSelection();
 }
 
 int CefDOMDocumentImpl::GetSelectionStartOffset() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return 0;
+  }
 
-  if (!frame_->HasSelection())
+  if (!frame_->HasSelection()) {
     return 0;
+  }
 
   const WebRange& range = frame_->SelectionRange();
-  if (range.IsNull())
+  if (range.IsNull()) {
     return 0;
+  }
 
   return range.StartOffset();
 }
 
 int CefDOMDocumentImpl::GetSelectionEndOffset() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return 0;
+  }
 
-  if (!frame_->HasSelection())
+  if (!frame_->HasSelection()) {
     return 0;
+  }
 
   const WebRange& range = frame_->SelectionRange();
-  if (range.IsNull())
+  if (range.IsNull()) {
     return 0;
+  }
 
   return range.EndOffset();
 }
 
 CefString CefDOMDocumentImpl::GetSelectionAsMarkup() {
   CefString str;
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return str;
+  }
 
-  if (!frame_->HasSelection())
+  if (!frame_->HasSelection()) {
     return str;
+  }
 
   const WebString& markup = frame_->SelectionAsMarkup();
-  if (!markup.IsNull())
+  if (!markup.IsNull()) {
     str = markup.Utf16();
+  }
 
   return str;
 }
 
 CefString CefDOMDocumentImpl::GetSelectionAsText() {
   CefString str;
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return str;
+  }
 
-  if (!frame_->HasSelection())
+  if (!frame_->HasSelection()) {
     return str;
+  }
 
   const WebString& text = frame_->SelectionAsText();
-  if (!text.IsNull())
+  if (!text.IsNull()) {
     str = text.Utf16();
+  }
 
   return str;
 }
 
 CefString CefDOMDocumentImpl::GetBaseURL() {
   CefString str;
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return str;
+  }
 
   const WebDocument& document = frame_->GetDocument();
   const WebURL& url = document.BaseURL();
@@ -172,8 +192,9 @@
 
 CefString CefDOMDocumentImpl::GetCompleteURL(const CefString& partialURL) {
   CefString str;
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return str;
+  }
 
   const WebDocument& document = frame_->GetDocument();
   const WebURL& url =
@@ -188,18 +209,21 @@
 
 CefRefPtr<CefDOMNode> CefDOMDocumentImpl::GetOrCreateNode(
     const blink::WebNode& node) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return nullptr;
+  }
 
   // Nodes may potentially be null.
-  if (node.IsNull())
+  if (node.IsNull()) {
     return nullptr;
+  }
 
   if (!node_map_.empty()) {
     // Locate the existing node, if any.
     NodeMap::const_iterator it = node_map_.find(node);
-    if (it != node_map_.end())
+    if (it != node_map_.end()) {
       return it->second;
+    }
   }
 
   // Create the new node object.
@@ -209,19 +233,22 @@
 }
 
 void CefDOMDocumentImpl::RemoveNode(const blink::WebNode& node) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return;
+  }
 
   if (!node_map_.empty()) {
     NodeMap::iterator it = node_map_.find(node);
-    if (it != node_map_.end())
+    if (it != node_map_.end()) {
       node_map_.erase(it);
+    }
   }
 }
 
 void CefDOMDocumentImpl::Detach() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return;
+  }
 
   // If you hit this assert it means that you are keeping references to node
   // objects beyond the valid scope.
@@ -233,8 +260,9 @@
 
   if (!node_map_.empty()) {
     NodeMap::const_iterator it = node_map_.begin();
-    for (; it != node_map_.end(); ++it)
+    for (; it != node_map_.end(); ++it) {
       static_cast<CefDOMNodeImpl*>(it->second)->Detach();
+    }
     node_map_.clear();
   }
 
@@ -243,7 +271,7 @@
 
 bool CefDOMDocumentImpl::VerifyContext() {
   if (!CEF_CURRENTLY_ON_RT() || frame_ == nullptr) {
-    NOTREACHED();
+    DCHECK(false);
     return false;
   }
   return true;
diff --git a/src/libcef/renderer/dom_document_impl.h b/src/libcef/renderer/dom_document_impl.h
index 85e50ee..87d8701 100644
--- a/src/libcef/renderer/dom_document_impl.h
+++ b/src/libcef/renderer/dom_document_impl.h
@@ -54,7 +54,7 @@
   CefBrowserImpl* browser_;
   blink::WebLocalFrame* frame_;
 
-  typedef std::map<blink::WebNode, CefDOMNode*> NodeMap;
+  using NodeMap = std::map<blink::WebNode, CefDOMNode*>;
   NodeMap node_map_;
 
   IMPLEMENT_REFCOUNTING(CefDOMDocumentImpl);
diff --git a/src/libcef/renderer/dom_node_impl.cc b/src/libcef/renderer/dom_node_impl.cc
index 5cf1e8b..92ce523 100644
--- a/src/libcef/renderer/dom_node_impl.cc
+++ b/src/libcef/renderer/dom_node_impl.cc
@@ -30,6 +30,81 @@
 using blink::WebNode;
 using blink::WebSelectElement;
 using blink::WebString;
+using FormControlType = WebFormControlElement::Type;
+
+namespace {
+
+cef_dom_form_control_type_t GetCefFormControlType(FormControlType type) {
+  switch (type) {
+    case FormControlType::kButtonButton:
+      return DOM_FORM_CONTROL_TYPE_BUTTON_BUTTON;
+    case FormControlType::kButtonSubmit:
+      return DOM_FORM_CONTROL_TYPE_BUTTON_SUBMIT;
+    case FormControlType::kButtonReset:
+      return DOM_FORM_CONTROL_TYPE_BUTTON_RESET;
+    case FormControlType::kButtonSelectList:
+      return DOM_FORM_CONTROL_TYPE_BUTTON_SELECT_LIST;
+    case FormControlType::kFieldset:
+      return DOM_FORM_CONTROL_TYPE_FIELDSET;
+    case FormControlType::kInputButton:
+      return DOM_FORM_CONTROL_TYPE_INPUT_BUTTON;
+    case FormControlType::kInputCheckbox:
+      return DOM_FORM_CONTROL_TYPE_INPUT_CHECKBOX;
+    case FormControlType::kInputColor:
+      return DOM_FORM_CONTROL_TYPE_INPUT_COLOR;
+    case FormControlType::kInputDate:
+      return DOM_FORM_CONTROL_TYPE_INPUT_DATE;
+    case FormControlType::kInputDatetimeLocal:
+      return DOM_FORM_CONTROL_TYPE_INPUT_DATETIME_LOCAL;
+    case FormControlType::kInputEmail:
+      return DOM_FORM_CONTROL_TYPE_INPUT_EMAIL;
+    case FormControlType::kInputFile:
+      return DOM_FORM_CONTROL_TYPE_INPUT_FILE;
+    case FormControlType::kInputHidden:
+      return DOM_FORM_CONTROL_TYPE_INPUT_HIDDEN;
+    case FormControlType::kInputImage:
+      return DOM_FORM_CONTROL_TYPE_INPUT_IMAGE;
+    case FormControlType::kInputMonth:
+      return DOM_FORM_CONTROL_TYPE_INPUT_MONTH;
+    case FormControlType::kInputNumber:
+      return DOM_FORM_CONTROL_TYPE_INPUT_NUMBER;
+    case FormControlType::kInputPassword:
+      return DOM_FORM_CONTROL_TYPE_INPUT_PASSWORD;
+    case FormControlType::kInputRadio:
+      return DOM_FORM_CONTROL_TYPE_INPUT_RADIO;
+    case FormControlType::kInputRange:
+      return DOM_FORM_CONTROL_TYPE_INPUT_RANGE;
+    case FormControlType::kInputReset:
+      return DOM_FORM_CONTROL_TYPE_INPUT_RESET;
+    case FormControlType::kInputSearch:
+      return DOM_FORM_CONTROL_TYPE_INPUT_SEARCH;
+    case FormControlType::kInputSubmit:
+      return DOM_FORM_CONTROL_TYPE_INPUT_SUBMIT;
+    case FormControlType::kInputTelephone:
+      return DOM_FORM_CONTROL_TYPE_INPUT_TELEPHONE;
+    case FormControlType::kInputText:
+      return DOM_FORM_CONTROL_TYPE_INPUT_TEXT;
+    case FormControlType::kInputTime:
+      return DOM_FORM_CONTROL_TYPE_INPUT_TIME;
+    case FormControlType::kInputUrl:
+      return DOM_FORM_CONTROL_TYPE_INPUT_URL;
+    case FormControlType::kInputWeek:
+      return DOM_FORM_CONTROL_TYPE_INPUT_WEEK;
+    case FormControlType::kOutput:
+      return DOM_FORM_CONTROL_TYPE_OUTPUT;
+    case FormControlType::kSelectOne:
+      return DOM_FORM_CONTROL_TYPE_SELECT_ONE;
+    case FormControlType::kSelectMultiple:
+      return DOM_FORM_CONTROL_TYPE_SELECT_MULTIPLE;
+    case FormControlType::kSelectList:
+      return DOM_FORM_CONTROL_TYPE_SELECT_LIST;
+    case FormControlType::kTextArea:
+      return DOM_FORM_CONTROL_TYPE_TEXT_AREA;
+  }
+  return DOM_FORM_CONTROL_TYPE_UNSUPPORTED;
+}
+
+}  // namespace
 
 CefDOMNodeImpl::CefDOMNodeImpl(CefRefPtr<CefDOMDocumentImpl> document,
                                const blink::WebNode& node)
@@ -45,45 +120,51 @@
 }
 
 CefDOMNodeImpl::Type CefDOMNodeImpl::GetType() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return DOM_NODE_TYPE_UNSUPPORTED;
+  }
 
   return blink_glue::GetNodeType(node_);
 }
 
 bool CefDOMNodeImpl::IsText() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   return node_.IsTextNode();
 }
 
 bool CefDOMNodeImpl::IsElement() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   return node_.IsElementNode();
 }
 
 // Logic copied from RenderViewImpl::IsEditableNode.
 bool CefDOMNodeImpl::IsEditable() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (node_.IsContentEditable())
+  if (node_.IsContentEditable()) {
     return true;
+  }
 
   if (node_.IsElementNode()) {
-    const WebElement& element = node_.ToConst<WebElement>();
-    if (blink_glue::IsTextControlElement(element))
+    const WebElement& element = node_.To<WebElement>();
+    if (blink_glue::IsTextControlElement(element)) {
       return true;
+    }
 
     // Also return true if it has an ARIA role of 'textbox'.
     for (unsigned i = 0; i < element.AttributeCount(); ++i) {
-      if (base::LowerCaseEqualsASCII(element.AttributeLocalName(i).Utf8(),
-                                     "role")) {
-        if (base::LowerCaseEqualsASCII(element.AttributeValue(i).Utf8(),
-                                       "textbox")) {
+      if (base::EqualsCaseInsensitiveASCII(element.AttributeLocalName(i).Utf8(),
+                                           "role")) {
+        if (base::EqualsCaseInsensitiveASCII(element.AttributeValue(i).Utf8(),
+                                             "textbox")) {
           return true;
         }
         break;
@@ -95,86 +176,77 @@
 }
 
 bool CefDOMNodeImpl::IsFormControlElement() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   if (node_.IsElementNode()) {
-    const WebElement& element = node_.ToConst<WebElement>();
+    const WebElement& element = node_.To<WebElement>();
     return element.IsFormControlElement();
   }
 
   return false;
 }
 
-CefString CefDOMNodeImpl::GetFormControlElementType() {
-  CefString str;
-  if (!VerifyContext())
-    return str;
+CefDOMNodeImpl::FormControlType CefDOMNodeImpl::GetFormControlElementType() {
+  if (!VerifyContext()) {
+    return DOM_FORM_CONTROL_TYPE_UNSUPPORTED;
+  }
 
   if (node_.IsElementNode()) {
-    const WebElement& element = node_.ToConst<WebElement>();
+    const WebElement& element = node_.To<WebElement>();
     if (element.IsFormControlElement()) {
       // Retrieve the type from the form control element.
       const WebFormControlElement& formElement =
-          node_.ToConst<WebFormControlElement>();
-
-      const base::string16& form_control_type =
-          formElement.FormControlType().Utf16();
-      str = form_control_type;
+          node_.To<WebFormControlElement>();
+      return GetCefFormControlType(formElement.FormControlType());
     }
   }
 
-  return str;
+  return DOM_FORM_CONTROL_TYPE_UNSUPPORTED;
 }
 
 bool CefDOMNodeImpl::IsSame(CefRefPtr<CefDOMNode> that) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   CefDOMNodeImpl* impl = static_cast<CefDOMNodeImpl*>(that.get());
-  if (!impl || !impl->VerifyContext())
+  if (!impl || !impl->VerifyContext()) {
     return false;
+  }
 
   return node_.Equals(impl->node_);
 }
 
 CefString CefDOMNodeImpl::GetName() {
   CefString str;
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return str;
+  }
 
   const WebString& name = blink_glue::GetNodeName(node_);
-  if (!name.IsNull())
+  if (!name.IsNull()) {
     str = name.Utf16();
+  }
 
   return str;
 }
 
 CefString CefDOMNodeImpl::GetValue() {
   CefString str;
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return str;
+  }
 
   if (node_.IsElementNode()) {
-    const WebElement& element = node_.ToConst<WebElement>();
+    const WebElement& element = node_.To<WebElement>();
     if (element.IsFormControlElement()) {
       // Retrieve the value from the form control element.
       const WebFormControlElement& formElement =
-          node_.ToConst<WebFormControlElement>();
+          node_.To<WebFormControlElement>();
 
-      base::string16 value;
-      const base::string16& form_control_type =
-          formElement.FormControlType().Utf16();
-      if (form_control_type == base::ASCIIToUTF16("text")) {
-        const WebInputElement& input_element =
-            formElement.ToConst<WebInputElement>();
-        value = input_element.Value().Utf16();
-      } else if (form_control_type == base::ASCIIToUTF16("select-one")) {
-        const WebSelectElement& select_element =
-            formElement.ToConst<WebSelectElement>();
-        value = select_element.Value().Utf16();
-      }
-
+      std::u16string value = formElement.Value().Utf16();
       base::TrimWhitespace(value, base::TRIM_LEADING, &value);
       str = value;
     }
@@ -182,19 +254,22 @@
 
   if (str.empty()) {
     const WebString& value = node_.NodeValue();
-    if (!value.IsNull())
+    if (!value.IsNull()) {
       str = value.Utf16();
+    }
   }
 
   return str;
 }
 
 bool CefDOMNodeImpl::SetValue(const CefString& value) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
-  if (node_.IsElementNode())
+  if (node_.IsElementNode()) {
     return false;
+  }
 
   return blink_glue::SetNodeValue(node_,
                                   WebString::FromUTF16(value.ToString16()));
@@ -202,156 +277,174 @@
 
 CefString CefDOMNodeImpl::GetAsMarkup() {
   CefString str;
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return str;
+  }
 
   const WebString& markup = blink_glue::CreateNodeMarkup(node_);
-  if (!markup.IsNull())
+  if (!markup.IsNull()) {
     str = markup.Utf16();
+  }
 
   return str;
 }
 
 CefRefPtr<CefDOMDocument> CefDOMNodeImpl::GetDocument() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return nullptr;
+  }
 
   return document_.get();
 }
 
 CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetParent() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return nullptr;
+  }
 
   return document_->GetOrCreateNode(node_.ParentNode());
 }
 
 CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetPreviousSibling() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return nullptr;
+  }
 
   return document_->GetOrCreateNode(node_.PreviousSibling());
 }
 
 CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetNextSibling() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return nullptr;
+  }
 
   return document_->GetOrCreateNode(node_.NextSibling());
 }
 
 bool CefDOMNodeImpl::HasChildren() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   return !node_.FirstChild().IsNull();
 }
 
 CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetFirstChild() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return nullptr;
+  }
 
   return document_->GetOrCreateNode(node_.FirstChild());
 }
 
 CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetLastChild() {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return nullptr;
+  }
 
   return document_->GetOrCreateNode(node_.LastChild());
 }
 
 CefString CefDOMNodeImpl::GetElementTagName() {
   CefString str;
-  if (!VerifyContext())
-    return str;
-
-  if (!node_.IsElementNode()) {
-    NOTREACHED();
+  if (!VerifyContext()) {
     return str;
   }
 
-  const WebElement& element = node_.ToConst<blink::WebElement>();
+  if (!node_.IsElementNode()) {
+    DCHECK(false);
+    return str;
+  }
+
+  const WebElement& element = node_.To<blink::WebElement>();
   const WebString& tagname = element.TagName();
-  if (!tagname.IsNull())
+  if (!tagname.IsNull()) {
     str = tagname.Utf16();
+  }
 
   return str;
 }
 
 bool CefDOMNodeImpl::HasElementAttributes() {
-  if (!VerifyContext())
-    return false;
-
-  if (!node_.IsElementNode()) {
-    NOTREACHED();
+  if (!VerifyContext()) {
     return false;
   }
 
-  const WebElement& element = node_.ToConst<blink::WebElement>();
+  if (!node_.IsElementNode()) {
+    DCHECK(false);
+    return false;
+  }
+
+  const WebElement& element = node_.To<blink::WebElement>();
   return (element.AttributeCount() > 0);
 }
 
 bool CefDOMNodeImpl::HasElementAttribute(const CefString& attrName) {
-  if (!VerifyContext())
-    return false;
-
-  if (!node_.IsElementNode()) {
-    NOTREACHED();
+  if (!VerifyContext()) {
     return false;
   }
 
-  const WebElement& element = node_.ToConst<blink::WebElement>();
+  if (!node_.IsElementNode()) {
+    DCHECK(false);
+    return false;
+  }
+
+  const WebElement& element = node_.To<blink::WebElement>();
   return element.HasAttribute(WebString::FromUTF16(attrName.ToString16()));
 }
 
 CefString CefDOMNodeImpl::GetElementAttribute(const CefString& attrName) {
   CefString str;
-  if (!VerifyContext())
-    return str;
-
-  if (!node_.IsElementNode()) {
-    NOTREACHED();
+  if (!VerifyContext()) {
     return str;
   }
 
-  const WebElement& element = node_.ToConst<blink::WebElement>();
+  if (!node_.IsElementNode()) {
+    DCHECK(false);
+    return str;
+  }
+
+  const WebElement& element = node_.To<blink::WebElement>();
   const WebString& attr =
       element.GetAttribute(WebString::FromUTF16(attrName.ToString16()));
-  if (!attr.IsNull())
+  if (!attr.IsNull()) {
     str = attr.Utf16();
+  }
 
   return str;
 }
 
 void CefDOMNodeImpl::GetElementAttributes(AttributeMap& attrMap) {
-  if (!VerifyContext())
-    return;
-
-  if (!node_.IsElementNode()) {
-    NOTREACHED();
+  if (!VerifyContext()) {
     return;
   }
 
-  const WebElement& element = node_.ToConst<blink::WebElement>();
-  unsigned int len = element.AttributeCount();
-  if (len == 0)
+  if (!node_.IsElementNode()) {
+    DCHECK(false);
     return;
+  }
+
+  const WebElement& element = node_.To<blink::WebElement>();
+  unsigned int len = element.AttributeCount();
+  if (len == 0) {
+    return;
+  }
 
   for (unsigned int i = 0; i < len; ++i) {
-    base::string16 name = element.AttributeLocalName(i).Utf16();
-    base::string16 value = element.AttributeValue(i).Utf16();
+    std::u16string name = element.AttributeLocalName(i).Utf16();
+    std::u16string value = element.AttributeValue(i).Utf16();
     attrMap.insert(std::make_pair(name, value));
   }
 }
 
 bool CefDOMNodeImpl::SetElementAttribute(const CefString& attrName,
                                          const CefString& value) {
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return false;
+  }
 
   if (!node_.IsElementNode()) {
-    NOTREACHED();
+    DCHECK(false);
     return false;
   }
 
@@ -363,35 +456,38 @@
 
 CefString CefDOMNodeImpl::GetElementInnerText() {
   CefString str;
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return str;
+  }
 
   if (!node_.IsElementNode()) {
-    NOTREACHED();
+    DCHECK(false);
     return str;
   }
 
   WebElement element = node_.To<blink::WebElement>();
   const WebString& text = element.TextContent();
-  if (!text.IsNull())
+  if (!text.IsNull()) {
     str = text.Utf16();
+  }
 
   return str;
 }
 
 CefRect CefDOMNodeImpl::GetElementBounds() {
   CefRect rect;
-  if (!VerifyContext())
+  if (!VerifyContext()) {
     return rect;
+  }
 
   if (!node_.IsElementNode()) {
-    NOTREACHED();
+    DCHECK(false);
     return rect;
   }
 
   WebElement element = node_.To<blink::WebElement>();
-  blink::WebRect rc = element.BoundsInViewport();
-  rect.Set(rc.x, rc.y, rc.width, rc.height);
+  const auto& rc = element.BoundsInWidget();
+  rect.Set(rc.x(), rc.y(), rc.width(), rc.height());
 
   return rect;
 }
@@ -403,13 +499,14 @@
 
 bool CefDOMNodeImpl::VerifyContext() {
   if (!document_.get()) {
-    NOTREACHED();
+    DCHECK(false);
     return false;
   }
-  if (!document_->VerifyContext())
+  if (!document_->VerifyContext()) {
     return false;
+  }
   if (node_.IsNull()) {
-    NOTREACHED();
+    DCHECK(false);
     return false;
   }
   return true;
diff --git a/src/libcef/renderer/dom_node_impl.h b/src/libcef/renderer/dom_node_impl.h
index e736477..55116fc 100644
--- a/src/libcef/renderer/dom_node_impl.h
+++ b/src/libcef/renderer/dom_node_impl.h
@@ -23,7 +23,7 @@
   bool IsElement() override;
   bool IsEditable() override;
   bool IsFormControlElement() override;
-  CefString GetFormControlElementType() override;
+  FormControlType GetFormControlElementType() override;
   bool IsSame(CefRefPtr<CefDOMNode> that) override;
   CefString GetName() override;
   CefString GetValue() override;
diff --git a/src/libcef/renderer/extensions/extensions_dispatcher_delegate.h b/src/libcef/renderer/extensions/extensions_dispatcher_delegate.h
index 3730f8f..5ccebb6 100644
--- a/src/libcef/renderer/extensions/extensions_dispatcher_delegate.h
+++ b/src/libcef/renderer/extensions/extensions_dispatcher_delegate.h
@@ -5,7 +5,6 @@
 #ifndef CEF_LIBCEF_RENDERER_EXTENSIONS_EXTENSIONS_DISPATCHER_DELEGATE_H_
 #define CEF_LIBCEF_RENDERER_EXTENSIONS_EXTENSIONS_DISPATCHER_DELEGATE_H_
 
-#include "base/macros.h"
 #include "extensions/renderer/dispatcher_delegate.h"
 
 namespace extensions {
@@ -13,13 +12,16 @@
 class CefExtensionsDispatcherDelegate : public DispatcherDelegate {
  public:
   CefExtensionsDispatcherDelegate();
+
+  CefExtensionsDispatcherDelegate(const CefExtensionsDispatcherDelegate&) =
+      delete;
+  CefExtensionsDispatcherDelegate& operator=(
+      const CefExtensionsDispatcherDelegate&) = delete;
+
   ~CefExtensionsDispatcherDelegate() override;
 
   void PopulateSourceMap(
       extensions::ResourceBundleSourceMap* source_map) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CefExtensionsDispatcherDelegate);
 };
 
 }  // namespace extensions
diff --git a/src/libcef/renderer/extensions/extensions_renderer_client.cc b/src/libcef/renderer/extensions/extensions_renderer_client.cc
index a0c16f2..fb72409 100644
--- a/src/libcef/renderer/extensions/extensions_renderer_client.cc
+++ b/src/libcef/renderer/extensions/extensions_renderer_client.cc
@@ -4,27 +4,21 @@
 
 #include "libcef/renderer/extensions/extensions_renderer_client.h"
 
-#include "libcef/common/cef_messages.h"
+#include "libcef/renderer/alloy/alloy_content_renderer_client.h"
+#include "libcef/renderer/alloy/alloy_render_thread_observer.h"
 #include "libcef/renderer/extensions/extensions_dispatcher_delegate.h"
-#include "libcef/renderer/render_thread_observer.h"
 
-#include "base/command_line.h"
+#include "base/stl_util.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/renderer/extensions/extension_process_policy.h"
 #include "chrome/renderer/extensions/resource_request_policy.h"
 #include "content/public/common/content_constants.h"
-#include "content/public/common/content_switches.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/public/renderer/render_thread.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/permissions/permissions_data.h"
-#include "extensions/common/switches.h"
 #include "extensions/renderer/dispatcher.h"
 #include "extensions/renderer/extension_frame_helper.h"
 #include "extensions/renderer/extensions_render_frame_observer.h"
-#include "extensions/renderer/guest_view/extensions_guest_view_container.h"
-#include "extensions/renderer/guest_view/extensions_guest_view_container_dispatcher.h"
-#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h"
 #include "extensions/renderer/renderer_extension_registry.h"
 #include "extensions/renderer/script_context.h"
 #include "third_party/blink/public/web/web_document.h"
@@ -45,12 +39,15 @@
 
 }  // namespace
 
-CefExtensionsRendererClient::CefExtensionsRendererClient() {}
+CefExtensionsRendererClient::CefExtensionsRendererClient(
+    AlloyContentRendererClient* alloy_content_renderer_client)
+    : alloy_content_renderer_client_(alloy_content_renderer_client) {}
 
 CefExtensionsRendererClient::~CefExtensionsRendererClient() {}
 
 bool CefExtensionsRendererClient::IsIncognitoProcess() const {
-  return CefRenderThreadObserver::is_incognito_process();
+  return alloy_content_renderer_client_->GetAlloyObserver()
+      ->IsIncognitoProcess();
 }
 
 int CefExtensionsRendererClient::GetLowestIsolatedWorldId() const {
@@ -84,16 +81,14 @@
 void CefExtensionsRendererClient::RenderThreadStarted() {
   content::RenderThread* thread = content::RenderThread::Get();
 
-  extension_dispatcher_.reset(new extensions::Dispatcher(
-      std::make_unique<extensions::CefExtensionsDispatcherDelegate>()));
+  extension_dispatcher_ = std::make_unique<extensions::Dispatcher>(
+      std::make_unique<extensions::CefExtensionsDispatcherDelegate>());
   extension_dispatcher_->OnRenderThreadStarted(thread);
-  resource_request_policy_.reset(
-      new extensions::ResourceRequestPolicy(extension_dispatcher_.get()));
-  guest_view_container_dispatcher_.reset(
-      new extensions::ExtensionsGuestViewContainerDispatcher());
+  resource_request_policy_ =
+      std::make_unique<extensions::ResourceRequestPolicy>(
+          extension_dispatcher_.get());
 
   thread->AddObserver(extension_dispatcher_.get());
-  thread->AddObserver(guest_view_container_dispatcher_.get());
 }
 
 void CefExtensionsRendererClient::RenderFrameCreated(
@@ -108,13 +103,14 @@
 bool CefExtensionsRendererClient::OverrideCreatePlugin(
     content::RenderFrame* render_frame,
     const blink::WebPluginParams& params) {
-  if (params.mime_type.Utf8() != content::kBrowserPluginMimeType)
+  if (params.mime_type.Utf8() != content::kBrowserPluginMimeType) {
     return true;
+  }
 
   bool guest_view_api_available = false;
   extension_dispatcher_->script_context_set_iterator()->ForEach(
-      render_frame, base::Bind(&IsGuestViewApiAvailableToScriptContext,
-                               &guest_view_api_available));
+      render_frame, base::BindRepeating(&IsGuestViewApiAvailableToScriptContext,
+                                        &guest_view_api_available));
   return !guest_view_api_available;
 }
 
@@ -124,35 +120,12 @@
     const blink::WebURL& url,
     const net::SiteForCookies& site_for_cookies,
     const url::Origin* initiator_origin,
-    GURL* new_url,
-    bool* attach_same_site_cookies) {
-  if (initiator_origin &&
-      initiator_origin->scheme() == extensions::kExtensionScheme) {
-    const extensions::RendererExtensionRegistry* extension_registry =
-        extensions::RendererExtensionRegistry::Get();
-    const Extension* extension =
-        extension_registry->GetByID(initiator_origin->host());
-    if (extension) {
-      int tab_id = extensions::ExtensionFrameHelper::Get(
-                       content::RenderFrame::FromWebFrame(frame))
-                       ->tab_id();
-      GURL request_url(url);
-      if (extension->permissions_data()->GetPageAccess(request_url, tab_id,
-                                                       nullptr) ==
-              extensions::PermissionsData::PageAccess::kAllowed ||
-          extension->permissions_data()->GetContentScriptAccess(
-              request_url, tab_id, nullptr) ==
-              extensions::PermissionsData::PageAccess::kAllowed) {
-        *attach_same_site_cookies = true;
-      }
-    }
-  }
-
+    GURL* new_url) {
   // Check whether the request should be allowed. If not allowed, we reset the
   // URL to something invalid to prevent the request and cause an error.
   if (url.ProtocolIs(extensions::kExtensionScheme) &&
-      !resource_request_policy_->CanRequestResource(GURL(url), frame,
-                                                    transition_type)) {
+      !resource_request_policy_->CanRequestResource(
+          GURL(url), frame, transition_type, initiator_origin)) {
     *new_url = GURL(chrome::kExtensionInvalidRequestURL);
   }
 }
@@ -172,23 +145,4 @@
   extension_dispatcher_->RunScriptsAtDocumentIdle(render_frame);
 }
 
-// static
-bool CefExtensionsRendererClient::IsStandaloneExtensionProcess() {
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-      extensions::switches::kExtensionProcess);
-}
-
-// static
-content::BrowserPluginDelegate*
-CefExtensionsRendererClient::CreateBrowserPluginDelegate(
-    content::RenderFrame* render_frame,
-    const content::WebPluginInfo& info,
-    const std::string& mime_type,
-    const GURL& original_url) {
-  if (mime_type == content::kBrowserPluginMimeType)
-    return new extensions::ExtensionsGuestViewContainer(render_frame);
-  return new extensions::MimeHandlerViewContainer(render_frame, info, mime_type,
-                                                  original_url);
-}
-
 }  // namespace extensions
diff --git a/src/libcef/renderer/extensions/extensions_renderer_client.h b/src/libcef/renderer/extensions/extensions_renderer_client.h
index b82c3a9..9537652 100644
--- a/src/libcef/renderer/extensions/extensions_renderer_client.h
+++ b/src/libcef/renderer/extensions/extensions_renderer_client.h
@@ -8,11 +8,11 @@
 #include <memory>
 #include <string>
 
-#include "base/macros.h"
 #include "extensions/renderer/extensions_renderer_client.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "ui/base/page_transition_types.h"
 
+class AlloyContentRendererClient;
 class GURL;
 
 namespace blink {
@@ -40,12 +40,17 @@
 
 class Dispatcher;
 class DispatcherDelegate;
-class ExtensionsGuestViewContainerDispatcher;
 class ResourceRequestPolicy;
 
 class CefExtensionsRendererClient : public ExtensionsRendererClient {
  public:
-  CefExtensionsRendererClient();
+  explicit CefExtensionsRendererClient(
+      AlloyContentRendererClient* alloy_content_renderer_client);
+
+  CefExtensionsRendererClient(const CefExtensionsRendererClient&) = delete;
+  CefExtensionsRendererClient& operator=(const CefExtensionsRendererClient&) =
+      delete;
+
   ~CefExtensionsRendererClient() override;
 
   // ExtensionsRendererClient implementation.
@@ -59,7 +64,7 @@
       const GURL& scope,
       const GURL& script_url) const override;
 
-  // See CefContentRendererClient methods with the same names.
+  // See AlloyContentRendererClient methods with the same names.
   void RenderThreadStarted();
   void RenderFrameCreated(content::RenderFrame* render_frame,
                           service_manager::BinderRegistry* registry);
@@ -70,26 +75,16 @@
                        const blink::WebURL& url,
                        const net::SiteForCookies& site_for_cookies,
                        const url::Origin* initiator_origin,
-                       GURL* new_url,
-                       bool* attach_same_site_cookies);
+                       GURL* new_url);
   void RunScriptsAtDocumentStart(content::RenderFrame* render_frame);
   void RunScriptsAtDocumentEnd(content::RenderFrame* render_frame);
   void RunScriptsAtDocumentIdle(content::RenderFrame* render_frame);
 
-  static bool IsStandaloneExtensionProcess();
-  static content::BrowserPluginDelegate* CreateBrowserPluginDelegate(
-      content::RenderFrame* render_frame,
-      const content::WebPluginInfo& info,
-      const std::string& mime_type,
-      const GURL& original_url);
-
  private:
-  std::unique_ptr<extensions::Dispatcher> extension_dispatcher_;
-  std::unique_ptr<extensions::ExtensionsGuestViewContainerDispatcher>
-      guest_view_container_dispatcher_;
-  std::unique_ptr<extensions::ResourceRequestPolicy> resource_request_policy_;
+  AlloyContentRendererClient* const alloy_content_renderer_client_;
 
-  DISALLOW_COPY_AND_ASSIGN(CefExtensionsRendererClient);
+  std::unique_ptr<extensions::Dispatcher> extension_dispatcher_;
+  std::unique_ptr<extensions::ResourceRequestPolicy> resource_request_policy_;
 };
 
 }  // namespace extensions
diff --git a/src/libcef/renderer/extensions/print_render_frame_helper_delegate.cc b/src/libcef/renderer/extensions/print_render_frame_helper_delegate.cc
index 40434fb..690ee3d 100644
--- a/src/libcef/renderer/extensions/print_render_frame_helper_delegate.cc
+++ b/src/libcef/renderer/extensions/print_render_frame_helper_delegate.cc
@@ -12,10 +12,11 @@
 #include "base/strings/string_util.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/pdf_util.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/renderer/render_frame.h"
 #include "extensions/common/constants.h"
-#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h"
+#include "extensions/renderer/guest_view/mime_handler_view/post_message_support.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/blink/public/web/web_document.h"
 #include "third_party/blink/public/web/web_element.h"
@@ -27,25 +28,19 @@
     bool is_windowless)
     : is_windowless_(is_windowless) {}
 
-CefPrintRenderFrameHelperDelegate::~CefPrintRenderFrameHelperDelegate() {}
+CefPrintRenderFrameHelperDelegate::~CefPrintRenderFrameHelperDelegate() =
+    default;
 
 // Return the PDF object element if |frame| is the out of process PDF extension.
 blink::WebElement CefPrintRenderFrameHelperDelegate::GetPdfElement(
     blink::WebLocalFrame* frame) {
-  GURL url = frame->GetDocument().Url();
-  bool inside_print_preview = url.GetOrigin() == chrome::kChromeUIPrintURL;
-  bool inside_pdf_extension =
-      url.SchemeIs(extensions::kExtensionScheme) &&
-      url.host_piece() == extension_misc::kPdfExtensionId;
-  if (inside_print_preview || inside_pdf_extension) {
-    // <object> with id="plugin" is created in
-    // chrome/browser/resources/pdf/pdf.js.
-    auto plugin_element = frame->GetDocument().GetElementById("plugin");
-    if (!plugin_element.IsNull()) {
-      return plugin_element;
-    }
-    NOTREACHED();
+  if (frame->Parent() &&
+      IsPdfInternalPluginAllowedOrigin(frame->Parent()->GetSecurityOrigin())) {
+    auto plugin_element = frame->GetDocument().QuerySelector("embed");
+    DCHECK(!plugin_element.IsNull());
+    return plugin_element;
   }
+
   return blink::WebElement();
 }
 
@@ -53,6 +48,10 @@
   return !is_windowless_ && PrintPreviewEnabled();
 }
 
+bool CefPrintRenderFrameHelperDelegate::ShouldGenerateTaggedPDF() {
+  return true;
+}
+
 bool CefPrintRenderFrameHelperDelegate::OverridePrint(
     blink::WebLocalFrame* frame) {
   auto* post_message_support =
@@ -62,9 +61,9 @@
     // instructs the PDF plugin to print. This is to make window.print() on a
     // PDF plugin document correctly print the PDF. See
     // https://crbug.com/448720.
-    base::DictionaryValue message;
-    message.SetString("type", "print");
-    post_message_support->PostMessageFromValue(message);
+    base::Value::Dict message;
+    message.Set("type", "print");
+    post_message_support->PostMessageFromValue(base::Value(std::move(message)));
     return true;
   }
   return false;
diff --git a/src/libcef/renderer/extensions/print_render_frame_helper_delegate.h b/src/libcef/renderer/extensions/print_render_frame_helper_delegate.h
index 9ecc29d..77eb591 100644
--- a/src/libcef/renderer/extensions/print_render_frame_helper_delegate.h
+++ b/src/libcef/renderer/extensions/print_render_frame_helper_delegate.h
@@ -17,6 +17,7 @@
 
   blink::WebElement GetPdfElement(blink::WebLocalFrame* frame) override;
   bool IsPrintPreviewEnabled() override;
+  bool ShouldGenerateTaggedPDF() override;
   bool OverridePrint(blink::WebLocalFrame* frame) override;
 
  private:
diff --git a/src/libcef/renderer/frame_impl.cc b/src/libcef/renderer/frame_impl.cc
index 648721d..cea76fa 100644
--- a/src/libcef/renderer/frame_impl.cc
+++ b/src/libcef/renderer/frame_impl.cc
@@ -4,10 +4,10 @@
 
 #include "libcef/renderer/frame_impl.h"
 
-#include "base/compiler_specific.h"
+#include "build/build_config.h"
 
 // Enable deprecation warnings on Windows. See http://crbug.com/585142.
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 #if defined(__clang__)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic error "-Wdeprecated-declarations"
@@ -17,23 +17,26 @@
 #endif
 #endif
 
-#include "libcef/common/cef_messages.h"
-#include "libcef/common/content_client.h"
+#include "include/cef_urlrequest.h"
+#include "libcef/common/app_manager.h"
+#include "libcef/common/frame_util.h"
 #include "libcef/common/net/http_header_utils.h"
 #include "libcef/common/process_message_impl.h"
+#include "libcef/common/process_message_smr_impl.h"
 #include "libcef/common/request_impl.h"
-#include "libcef/common/response_manager.h"
+#include "libcef/common/string_util.h"
 #include "libcef/renderer/blink_glue.h"
 #include "libcef/renderer/browser_impl.h"
 #include "libcef/renderer/dom_document_impl.h"
 #include "libcef/renderer/render_frame_util.h"
-#include "libcef/renderer/render_urlrequest_impl.h"
 #include "libcef/renderer/thread_util.h"
 #include "libcef/renderer/v8_impl.h"
 
+#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "content/public/renderer/render_view.h"
 #include "content/renderer/render_frame_impl.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink.h"
 #include "third_party/blink/public/platform/web_data.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url.h"
@@ -45,14 +48,25 @@
 #include "third_party/blink/public/web/web_navigation_control.h"
 #include "third_party/blink/public/web/web_script_source.h"
 #include "third_party/blink/public/web/web_view.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+
+namespace {
+
+// Maximum number of times to retry the browser connection.
+constexpr size_t kConnectionRetryMaxCt = 3U;
+
+// Length of time to wait before initiating a browser connection retry.
+constexpr auto kConnectionRetryDelay = base::Seconds(1);
+
+// Length of time to wait for the browser connection ACK before timing out.
+constexpr auto kConnectionTimeout = base::Seconds(10);
+
+}  // namespace
 
 CefFrameImpl::CefFrameImpl(CefBrowserImpl* browser,
                            blink::WebLocalFrame* frame,
                            int64_t frame_id)
-    : browser_(browser),
-      frame_(frame),
-      frame_id_(frame_id),
-      response_manager_(new CefResponseManager) {}
+    : browser_(browser), frame_(frame), frame_id_(frame_id) {}
 
 CefFrameImpl::~CefFrameImpl() {}
 
@@ -63,42 +77,42 @@
 }
 
 void CefFrameImpl::Undo() {
-  ExecuteCommand("Undo");
+  SendCommand("Undo");
 }
 
 void CefFrameImpl::Redo() {
-  ExecuteCommand("Redo");
+  SendCommand("Redo");
 }
 
 void CefFrameImpl::Cut() {
-  ExecuteCommand("Cut");
+  SendCommand("Cut");
 }
 
 void CefFrameImpl::Copy() {
-  ExecuteCommand("Copy");
+  SendCommand("Copy");
 }
 
 void CefFrameImpl::Paste() {
-  ExecuteCommand("Paste");
+  SendCommand("Paste");
 }
 
 void CefFrameImpl::Delete() {
-  ExecuteCommand("Delete");
+  SendCommand("Delete");
 }
 
 void CefFrameImpl::SelectAll() {
-  ExecuteCommand("SelectAll");
+  SendCommand("SelectAll");
 }
 
 void CefFrameImpl::ViewSource() {
-  NOTREACHED() << "ViewSource cannot be called from the renderer process";
+  DCHECK(false) << "ViewSource cannot be called from the renderer process";
 }
 
 void CefFrameImpl::GetSource(CefRefPtr<CefStringVisitor> visitor) {
   CEF_REQUIRE_RT_RETURN_VOID();
   if (frame_) {
-    const CefString& content =
-        std::string(blink::WebFrameContentDumper::DumpAsMarkup(frame_).Utf8());
+    CefString content;
+    string_util::GetCefString(blink_glue::DumpDocumentMarkup(frame_), content);
     visitor->Visit(content);
   }
 }
@@ -106,7 +120,8 @@
 void CefFrameImpl::GetText(CefRefPtr<CefStringVisitor> visitor) {
   CEF_REQUIRE_RT_RETURN_VOID();
   if (frame_) {
-    const CefString& content = blink_glue::DumpDocumentText(frame_);
+    CefString content;
+    string_util::GetCefString(blink_glue::DumpDocumentText(frame_), content);
     visitor->Visit(content);
   }
 }
@@ -114,75 +129,49 @@
 void CefFrameImpl::LoadRequest(CefRefPtr<CefRequest> request) {
   CEF_REQUIRE_RT_RETURN_VOID();
 
-  if (!frame_)
+  if (!frame_) {
     return;
-
-  CefMsg_LoadRequest_Params params;
-  params.url = GURL(std::string(request->GetURL()));
-  params.method = request->GetMethod();
-  params.site_for_cookies = net::SiteForCookies::FromUrl(
-      GURL(request->GetFirstPartyForCookies().ToString()));
-
-  CefRequest::HeaderMap headerMap;
-  request->GetHeaderMap(headerMap);
-  if (!headerMap.empty())
-    params.headers = HttpHeaderUtils::GenerateHeaders(headerMap);
-
-  CefRefPtr<CefPostData> postData = request->GetPostData();
-  if (postData.get()) {
-    CefPostDataImpl* impl = static_cast<CefPostDataImpl*>(postData.get());
-    params.upload_data = new net::UploadData();
-    impl->Get(*params.upload_data.get());
   }
 
-  params.load_flags = request->GetFlags();
-
-  OnLoadRequest(params);
+  auto params = cef::mojom::RequestParams::New();
+  static_cast<CefRequestImpl*>(request.get())->Get(params);
+  LoadRequest(std::move(params));
 }
 
 void CefFrameImpl::LoadURL(const CefString& url) {
   CEF_REQUIRE_RT_RETURN_VOID();
 
-  if (!frame_)
+  if (!frame_) {
     return;
+  }
 
-  CefMsg_LoadRequest_Params params;
-  params.url = GURL(url.ToString());
-  params.method = "GET";
-
-  OnLoadRequest(params);
+  auto params = cef::mojom::RequestParams::New();
+  params->url = GURL(url.ToString());
+  params->method = "GET";
+  LoadRequest(std::move(params));
 }
 
 void CefFrameImpl::ExecuteJavaScript(const CefString& jsCode,
                                      const CefString& scriptUrl,
                                      int startLine) {
-  CEF_REQUIRE_RT_RETURN_VOID();
-
-  if (jsCode.empty())
-    return;
-  if (startLine < 1)
-    startLine = 1;
-
-  if (frame_) {
-    GURL gurl = GURL(scriptUrl.ToString());
-    frame_->ExecuteScript(blink::WebScriptSource(
-        blink::WebString::FromUTF16(jsCode.ToString16()), gurl, startLine));
-  }
+  SendJavaScript(jsCode, scriptUrl, startLine);
 }
 
 bool CefFrameImpl::IsMain() {
   CEF_REQUIRE_RT_RETURN(false);
 
-  if (frame_)
+  if (frame_) {
     return (frame_->Parent() == nullptr);
+  }
   return false;
 }
 
 bool CefFrameImpl::IsFocused() {
   CEF_REQUIRE_RT_RETURN(false);
 
-  if (frame_ && frame_->View())
+  if (frame_ && frame_->View()) {
     return (frame_->View()->FocusedFrame() == frame_);
+  }
   return false;
 }
 
@@ -190,12 +179,13 @@
   CefString name;
   CEF_REQUIRE_RT_RETURN(name);
 
-  if (frame_)
+  if (frame_) {
     name = render_frame_util::GetName(frame_);
+  }
   return name;
 }
 
-int64 CefFrameImpl::GetIdentifier() {
+int64_t CefFrameImpl::GetIdentifier() {
   CEF_REQUIRE_RT_RETURN(0);
 
   return frame_id_;
@@ -206,8 +196,9 @@
 
   if (frame_) {
     blink::WebFrame* parent = frame_->Parent();
-    if (parent && parent->IsWebLocalFrame())
+    if (parent && parent->IsWebLocalFrame()) {
       return browser_->GetWebFrameImpl(parent->ToWebLocalFrame()).get();
+    }
   }
 
   return nullptr;
@@ -245,87 +236,103 @@
 void CefFrameImpl::VisitDOM(CefRefPtr<CefDOMVisitor> visitor) {
   CEF_REQUIRE_RT_RETURN_VOID();
 
-  if (!frame_)
+  if (!frame_) {
     return;
+  }
 
   // Create a CefDOMDocumentImpl object that is valid only for the scope of this
   // method.
   CefRefPtr<CefDOMDocumentImpl> documentImpl;
   const blink::WebDocument& document = frame_->GetDocument();
-  if (!document.IsNull())
+  if (!document.IsNull()) {
     documentImpl = new CefDOMDocumentImpl(browser_, frame_);
+  }
 
   visitor->Visit(documentImpl.get());
 
-  if (documentImpl.get())
+  if (documentImpl.get()) {
     documentImpl->Detach();
+  }
 }
 
 CefRefPtr<CefURLRequest> CefFrameImpl::CreateURLRequest(
     CefRefPtr<CefRequest> request,
     CefRefPtr<CefURLRequestClient> client) {
-  CEF_REQUIRE_RT_RETURN(nullptr);
-
-  if (!request || !client || !frame_)
-    return nullptr;
-
-  CefRefPtr<CefRenderURLRequest> impl =
-      new CefRenderURLRequest(this, request, client);
-  if (impl->Start())
-    return impl.get();
+  DCHECK(false) << "CreateURLRequest cannot be called from the render process";
   return nullptr;
 }
 
 void CefFrameImpl::SendProcessMessage(CefProcessId target_process,
                                       CefRefPtr<CefProcessMessage> message) {
-  Cef_Request_Params params;
-  CefProcessMessageImpl* impl =
-      static_cast<CefProcessMessageImpl*>(message.get());
-  if (impl->CopyTo(params)) {
-    SendProcessMessage(target_process, params.name, &params.arguments, true);
+  CEF_REQUIRE_RT_RETURN_VOID();
+  DCHECK_EQ(PID_BROWSER, target_process);
+  DCHECK(message && message->IsValid());
+  if (!message || !message->IsValid()) {
+    return;
   }
-}
 
-blink::WebURLLoaderFactory* CefFrameImpl::GetURLLoaderFactory() {
-  CEF_REQUIRE_RT();
-  if (!url_loader_factory_ && frame_) {
-    auto render_frame = content::RenderFrameImpl::FromWebFrame(frame_);
-    if (render_frame) {
-      url_loader_factory_ = render_frame->CreateURLLoaderFactory();
-    }
+  if (message->GetArgumentList() != nullptr) {
+    // Invalidate the message object immediately by taking the argument list.
+    auto argument_list =
+        static_cast<CefProcessMessageImpl*>(message.get())->TakeArgumentList();
+    SendToBrowserFrame(
+        __FUNCTION__,
+        base::BindOnce(
+            [](const CefString& name, base::Value::List argument_list,
+               const BrowserFrameType& render_frame) {
+              render_frame->SendMessage(name, std::move(argument_list));
+            },
+            message->GetName(), std::move(argument_list)));
+  } else {
+    auto region =
+        static_cast<CefProcessMessageSMRImpl*>(message.get())->TakeRegion();
+    SendToBrowserFrame(
+        __FUNCTION__,
+        base::BindOnce(
+            [](const CefString& name, base::WritableSharedMemoryRegion region,
+               const BrowserFrameType& render_frame) {
+              render_frame->SendSharedMemoryRegion(name, std::move(region));
+            },
+            message->GetName(), std::move(region)));
   }
-  return url_loader_factory_.get();
 }
 
 void CefFrameImpl::OnAttached() {
-  Send(new CefHostMsg_FrameAttached(MSG_ROUTING_NONE));
+  // Called indirectly from RenderFrameCreated.
+  ConnectBrowserFrame(ConnectReason::RENDER_FRAME_CREATED);
 }
 
-bool CefFrameImpl::OnMessageReceived(const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(CefFrameImpl, message)
-    IPC_MESSAGE_HANDLER(CefMsg_Request, OnRequest)
-    IPC_MESSAGE_HANDLER(CefMsg_Response, OnResponse)
-    IPC_MESSAGE_HANDLER(CefMsg_ResponseAck, OnResponseAck)
-    IPC_MESSAGE_HANDLER(CefMsg_LoadRequest, OnLoadRequest)
-    IPC_MESSAGE_HANDLER(CefMsg_DidStopLoading, OnDidStopLoading)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  return handled;
+void CefFrameImpl::OnWasShown() {
+  if (browser_connection_state_ == ConnectionState::DISCONNECTED) {
+    // Reconnect a frame that has exited the bfcache.
+    ConnectBrowserFrame(ConnectReason::WAS_SHOWN);
+  }
+}
+
+void CefFrameImpl::OnDidCommitProvisionalLoad() {
+  did_commit_provisional_load_ = true;
+  MaybeInitializeScriptContext();
 }
 
 void CefFrameImpl::OnDidFinishLoad() {
   // Ignore notifications from the embedded frame hosting a mime-type plugin.
   // We'll eventually receive a notification from the owner frame.
-  if (blink_glue::HasPluginFrameOwner(frame_))
+  if (blink_glue::HasPluginFrameOwner(frame_)) {
     return;
+  }
+
+  if (!blink::RuntimeEnabledFeatures::BackForwardCacheEnabled() && IsMain()) {
+    // Refresh draggable regions. Otherwise, we may not receive updated regions
+    // after navigation because LocalFrameView::UpdateDocumentAnnotatedRegion
+    // lacks sufficient context. When bfcache is disabled we use this method
+    // instead of DidStopLoading() because it provides more accurate timing.
+    OnDraggableRegionsChanged();
+  }
 
   blink::WebDocumentLoader* dl = frame_->GetDocumentLoader();
-  const int http_status_code = dl->GetResponse().HttpStatusCode();
-  Send(new CefHostMsg_DidFinishLoad(MSG_ROUTING_NONE, dl->GetUrl(),
-                                    http_status_code));
+  const int http_status_code = dl->GetWebResponse().HttpStatusCode();
 
-  CefRefPtr<CefApp> app = CefContentClient::Get()->application();
+  CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
   if (app) {
     CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
     if (handler) {
@@ -338,186 +345,467 @@
 }
 
 void CefFrameImpl::OnDraggableRegionsChanged() {
+  // Match the behavior in ChromeRenderFrameObserver::DraggableRegionsChanged.
+  // Only the main frame is allowed to control draggable regions, to avoid other
+  // frames manipulate the regions in the browser process.
+  if (frame_->Parent() != nullptr) {
+    return;
+  }
+
   blink::WebVector<blink::WebDraggableRegion> webregions =
       frame_->GetDocument().DraggableRegions();
-  std::vector<Cef_DraggableRegion_Params> regions;
-  for (size_t i = 0; i < webregions.size(); ++i) {
-    Cef_DraggableRegion_Params region;
+  std::vector<cef::mojom::DraggableRegionEntryPtr> regions;
+  if (!webregions.empty()) {
     auto render_frame = content::RenderFrameImpl::FromWebFrame(frame_);
-    render_frame->ConvertViewportToWindow(&webregions[i].bounds);
-    region.bounds = webregions[i].bounds;
-    region.draggable = webregions[i].draggable;
-    regions.push_back(region);
+
+    regions.reserve(webregions.size());
+    for (const auto& webregion : webregions) {
+      auto region = cef::mojom::DraggableRegionEntry::New(webregion.bounds,
+                                                          webregion.draggable);
+      render_frame->ConvertViewportToWindow(&region->bounds);
+      regions.push_back(std::move(region));
+    }
   }
-  Send(new CefHostMsg_UpdateDraggableRegions(MSG_ROUTING_NONE, regions));
+
+  using RegionsArg =
+      absl::optional<std::vector<cef::mojom::DraggableRegionEntryPtr>>;
+  RegionsArg regions_arg =
+      regions.empty() ? absl::nullopt : absl::make_optional(std::move(regions));
+
+  SendToBrowserFrame(
+      __FUNCTION__,
+      base::BindOnce(
+          [](RegionsArg regions_arg, const BrowserFrameType& browser_frame) {
+            browser_frame->UpdateDraggableRegions(std::move(regions_arg));
+          },
+          std::move(regions_arg)));
+}
+
+void CefFrameImpl::OnContextCreated(v8::Local<v8::Context> context) {
+  context_created_ = true;
+
+  CHECK(frame_);
+  while (!queued_context_actions_.empty()) {
+    auto& action = queued_context_actions_.front();
+    std::move(action.second).Run(frame_);
+    queued_context_actions_.pop();
+  }
+
+  execution_context_lifecycle_state_observer_ =
+      blink_glue::RegisterExecutionContextLifecycleStateObserver(context, this);
+}
+
+void CefFrameImpl::OnContextReleased() {
+  execution_context_lifecycle_state_observer_.reset();
 }
 
 void CefFrameImpl::OnDetached() {
+  // Called when this frame has been detached from the view. This *will* be
+  // called for child frames when a parent frame is detached.
   // The browser may hold the last reference to |this|. Take a reference here to
   // keep |this| alive until after this method returns.
   CefRefPtr<CefFrameImpl> self = this;
 
+  frame_ = nullptr;
+
   browser_->FrameDetached(frame_id_);
 
+  OnDisconnect(DisconnectReason::DETACHED);
+
   browser_ = nullptr;
-  frame_ = nullptr;
-  url_loader_factory_.reset();
-  response_manager_.reset();
+
+  // In case we never attached.
+  while (!queued_browser_actions_.empty()) {
+    auto& action = queued_browser_actions_.front();
+    LOG(WARNING) << action.first << " sent to detached " << GetDebugString()
+                 << " will be ignored";
+    queued_browser_actions_.pop();
+  }
+
+  // In case we're destroyed without the context being created.
+  while (!queued_context_actions_.empty()) {
+    auto& action = queued_context_actions_.front();
+    LOG(WARNING) << action.first << " sent to detached " << GetDebugString()
+                 << " will be ignored";
+    queued_context_actions_.pop();
+  }
 }
 
-void CefFrameImpl::ExecuteCommand(const std::string& command) {
+void CefFrameImpl::ExecuteOnLocalFrame(const std::string& function_name,
+                                       LocalFrameAction action) {
   CEF_REQUIRE_RT_RETURN_VOID();
-  if (frame_)
-    frame_->ExecuteCommand(blink::WebString::FromUTF8(command));
-}
 
-void CefFrameImpl::SendProcessMessage(CefProcessId target_process,
-                                      const std::string& name,
-                                      base::ListValue* arguments,
-                                      bool user_initiated) {
-  DCHECK_EQ(PID_BROWSER, target_process);
-  DCHECK(!name.empty());
-
-  if (!frame_)
-    return;
-
-  Cef_Request_Params params;
-  params.name = name;
-  if (arguments)
-    params.arguments.Swap(arguments);
-  params.user_initiated = user_initiated;
-  params.request_id = -1;
-  params.expect_response = false;
-
-  Send(new CefHostMsg_Request(MSG_ROUTING_NONE, params));
-}
-
-void CefFrameImpl::Send(IPC::Message* message) {
-  if (!frame_) {
-    delete message;
+  if (!context_created_) {
+    queued_context_actions_.push(
+        std::make_pair(function_name, std::move(action)));
+    MaybeInitializeScriptContext();
     return;
   }
 
-  auto render_frame = content::RenderFrame::FromWebFrame(frame_);
-  message->set_routing_id(render_frame->GetRoutingID());
-  render_frame->Send(message);
-}
-
-void CefFrameImpl::OnRequest(const Cef_Request_Params& params) {
-  DCHECK(browser_);
-  DCHECK(frame_);
-
-  bool success = false;
-  std::string response;
-  bool expect_response_ack = false;
-
-  TRACE_EVENT2("cef", "CefBrowserImpl::OnRequest", "request_id",
-               params.request_id, "expect_response",
-               params.expect_response ? 1 : 0);
-
-  if (params.user_initiated) {
-    // Give the user a chance to handle the request.
-    CefRefPtr<CefApp> app = CefContentClient::Get()->application();
-    if (app.get()) {
-      CefRefPtr<CefRenderProcessHandler> handler =
-          app->GetRenderProcessHandler();
-      if (handler.get()) {
-        CefRefPtr<CefProcessMessageImpl> message(new CefProcessMessageImpl(
-            const_cast<Cef_Request_Params*>(&params), false, true));
-        success = handler->OnProcessMessageReceived(browser_, this, PID_BROWSER,
-                                                    message.get());
-        message->Detach(nullptr);
-      }
-    }
-  } else if (params.name == "execute-code") {
-    // Execute code.
-    DCHECK_EQ(params.arguments.GetSize(), (size_t)4);
-
-    bool is_javascript = false;
-    std::string code, script_url;
-    int script_start_line = 0;
-
-    params.arguments.GetBoolean(0, &is_javascript);
-    params.arguments.GetString(1, &code);
-    DCHECK(!code.empty());
-    params.arguments.GetString(2, &script_url);
-    params.arguments.GetInteger(3, &script_start_line);
-    DCHECK_GE(script_start_line, 0);
-
-    if (is_javascript) {
-      frame_->ExecuteScript(
-          blink::WebScriptSource(blink::WebString::FromUTF8(code),
-                                 GURL(script_url), script_start_line));
-      success = true;
-    } else {
-      // TODO(cef): implement support for CSS code.
-      NOTIMPLEMENTED();
-    }
-  } else if (params.name == "execute-command") {
-    // Execute command.
-    DCHECK_EQ(params.arguments.GetSize(), (size_t)1);
-
-    std::string command;
-
-    params.arguments.GetString(0, &command);
-    DCHECK(!command.empty());
-
-    if (base::LowerCaseEqualsASCII(command, "getsource")) {
-      response = blink::WebFrameContentDumper::DumpAsMarkup(frame_).Utf8();
-      success = true;
-    } else if (base::LowerCaseEqualsASCII(command, "gettext")) {
-      response = blink_glue::DumpDocumentText(frame_);
-      success = true;
-    } else if (frame_->ExecuteCommand(blink::WebString::FromUTF8(command))) {
-      success = true;
-    }
+  if (frame_) {
+    std::move(action).Run(frame_);
   } else {
-    // Invalid request.
-    NOTREACHED();
-  }
-
-  if (params.expect_response) {
-    DCHECK_GE(params.request_id, 0);
-
-    // Send a response to the browser.
-    Cef_Response_Params response_params;
-    response_params.request_id = params.request_id;
-    response_params.success = success;
-    response_params.response = response;
-    response_params.expect_response_ack = expect_response_ack;
-    Send(new CefHostMsg_Response(MSG_ROUTING_NONE, response_params));
+    LOG(WARNING) << function_name << " sent to detached " << GetDebugString()
+                 << " will be ignored";
   }
 }
 
-void CefFrameImpl::OnResponse(const Cef_Response_Params& params) {
-  response_manager_->RunHandler(params);
-  if (params.expect_response_ack)
-    Send(new CefHostMsg_ResponseAck(MSG_ROUTING_NONE, params.request_id));
+void CefFrameImpl::ConnectBrowserFrame(ConnectReason reason) {
+  DCHECK(browser_connection_state_ == ConnectionState::DISCONNECTED ||
+         browser_connection_state_ == ConnectionState::RECONNECT_PENDING);
+
+  if (VLOG_IS_ON(1)) {
+    std::string reason_str;
+    switch (reason) {
+      case ConnectReason::RENDER_FRAME_CREATED:
+        reason_str = "RENDER_FRAME_CREATED";
+        break;
+      case ConnectReason::WAS_SHOWN:
+        reason_str = "WAS_SHOWN";
+        break;
+      case ConnectReason::RETRY:
+        reason_str = base::StringPrintf(
+            "RETRY %zu/%zu", browser_connect_retry_ct_, kConnectionRetryMaxCt);
+        break;
+    }
+    VLOG(1) << GetDebugString() << " connection request (reason=" << reason_str
+            << ")";
+  }
+
+  // Don't attempt to connect an invalid or bfcache'd frame. If a bfcache'd
+  // frame returns to active status a reconnect will be triggered via
+  // OnWasShown().
+  if (!frame_ || blink_glue::IsInBackForwardCache(frame_)) {
+    browser_connection_state_ = ConnectionState::DISCONNECTED;
+    browser_connect_timer_.Stop();
+    VLOG(1) << GetDebugString() << " connection retry canceled (reason="
+            << (frame_ ? "BFCACHED" : "INVALID") << ")";
+    return;
+  }
+
+  browser_connection_state_ = ConnectionState::CONNECTION_PENDING;
+  browser_connect_timer_.Start(FROM_HERE, kConnectionTimeout, this,
+                               &CefFrameImpl::OnBrowserFrameTimeout);
+
+  auto& browser_frame = GetBrowserFrame(/*expect_acked=*/false);
+  CHECK(browser_frame);
+
+  // True if this connection is a retry or if the frame just exited the
+  // BackForwardCache.
+  const bool reattached =
+      browser_connect_retry_ct_ > 0 || reason == ConnectReason::WAS_SHOWN;
+
+  // If the channel is working we should get a call to FrameAttachedAck().
+  // Otherwise, OnDisconnect() should be called to retry the
+  // connection.
+  browser_frame->FrameAttached(receiver_.BindNewPipeAndPassRemote(),
+                               reattached);
+  receiver_.set_disconnect_handler(
+      base::BindOnce(&CefFrameImpl::OnDisconnect, this,
+                     DisconnectReason::RENDER_FRAME_DISCONNECT));
 }
 
-void CefFrameImpl::OnResponseAck(int request_id) {
-  response_manager_->RunAckHandler(request_id);
+const mojo::Remote<cef::mojom::BrowserFrame>& CefFrameImpl::GetBrowserFrame(
+    bool expect_acked) {
+  DCHECK_EQ(expect_acked,
+            browser_connection_state_ == ConnectionState::CONNECTION_ACKED);
+
+  if (!browser_frame_.is_bound()) {
+    auto render_frame = content::RenderFrameImpl::FromWebFrame(frame_);
+    if (render_frame) {
+      // Triggers creation of a CefBrowserFrame in the browser process.
+      render_frame->GetBrowserInterfaceBroker()->GetInterface(
+          browser_frame_.BindNewPipeAndPassReceiver());
+      browser_frame_.set_disconnect_handler(
+          base::BindOnce(&CefFrameImpl::OnDisconnect, this,
+                         DisconnectReason::BROWSER_FRAME_DISCONNECT));
+    }
+  }
+  return browser_frame_;
 }
 
-void CefFrameImpl::OnDidStopLoading() {
+void CefFrameImpl::OnBrowserFrameTimeout() {
+  LOG(ERROR) << GetDebugString() << " connection timeout";
+  OnDisconnect(DisconnectReason::CONNECT_TIMEOUT);
+}
+
+void CefFrameImpl::OnDisconnect(DisconnectReason reason) {
+  // Ignore multiple calls in close proximity (which may occur if both
+  // |browser_frame_| and |receiver_| disconnect). |frame_| will be nullptr
+  // when called from/after OnDetached().
+  if (frame_ &&
+      browser_connection_state_ == ConnectionState::RECONNECT_PENDING) {
+    return;
+  }
+
+  if (VLOG_IS_ON(1)) {
+    std::string reason_str;
+    switch (reason) {
+      case DisconnectReason::DETACHED:
+        reason_str = "DETACHED";
+        break;
+      case DisconnectReason::BROWSER_FRAME_DETACHED:
+        reason_str = "BROWSER_FRAME_DETACHED";
+        break;
+      case DisconnectReason::CONNECT_TIMEOUT:
+        reason_str = "CONNECT_TIMEOUT";
+        break;
+      case DisconnectReason::RENDER_FRAME_DISCONNECT:
+        reason_str = "RENDER_FRAME_DISCONNECT";
+        break;
+      case DisconnectReason::BROWSER_FRAME_DISCONNECT:
+        reason_str = "BROWSER_FRAME_DISCONNECT";
+        break;
+    };
+
+    std::string state_str;
+    switch (browser_connection_state_) {
+      case ConnectionState::DISCONNECTED:
+        state_str = "DISCONNECTED";
+        break;
+      case ConnectionState::CONNECTION_PENDING:
+        state_str = "CONNECTION_PENDING";
+        break;
+      case ConnectionState::CONNECTION_ACKED:
+        state_str = "CONNECTION_ACKED";
+        break;
+      case ConnectionState::RECONNECT_PENDING:
+        state_str = "RECONNECT_PENDING";
+        break;
+    }
+
+    if (!frame_) {
+      state_str += ", FRAME_INVALID";
+    }
+
+    VLOG(1) << GetDebugString() << " disconnected (reason=" << reason_str
+            << ", current_state=" << state_str << ")";
+  }
+
+  browser_frame_.reset();
+  receiver_.reset();
+  browser_connection_state_ = ConnectionState::DISCONNECTED;
+  browser_connect_timer_.Stop();
+
+  // Only retry if the frame is still valid and the browser process has not
+  // intentionally detached.
+  if (frame_ && reason != DisconnectReason::BROWSER_FRAME_DETACHED) {
+    if (browser_connect_retry_ct_++ < kConnectionRetryMaxCt) {
+      VLOG(1) << GetDebugString() << " connection retry scheduled";
+
+      // Retry after a delay in case the frame is currently navigating, being
+      // destroyed, or entering the bfcache. In the navigation case the retry
+      // will likely succeed. In the destruction case the retry will be
+      // ignored/canceled due to OnDetached(). In the bfcache case the status
+      // may not be updated immediately, so we allow the reconnect timer to
+      // trigger and check the status in ConnectBrowserFrame() instead.
+      browser_connection_state_ = ConnectionState::RECONNECT_PENDING;
+      browser_connect_timer_.Start(
+          FROM_HERE, kConnectionRetryDelay,
+          base::BindOnce(&CefFrameImpl::ConnectBrowserFrame, this,
+                         ConnectReason::RETRY));
+    } else {
+      // Trigger a crash in official builds.
+      LOG(FATAL) << GetDebugString() << " connection retry failed";
+    }
+  }
+}
+
+void CefFrameImpl::SendToBrowserFrame(const std::string& function_name,
+                                      BrowserFrameAction action) {
+  if (!frame_) {
+    // We've been detached.
+    LOG(WARNING) << function_name << " sent to detached " << GetDebugString()
+                 << " will be ignored";
+    return;
+  }
+
+  if (browser_connection_state_ != ConnectionState::CONNECTION_ACKED) {
+    // Queue actions until we're notified by the browser that it's ready to
+    // handle them.
+    queued_browser_actions_.push(
+        std::make_pair(function_name, std::move(action)));
+    return;
+  }
+
+  auto& browser_frame = GetBrowserFrame();
+  CHECK(browser_frame);
+
+  std::move(action).Run(browser_frame);
+}
+
+void CefFrameImpl::MaybeInitializeScriptContext() {
+  if (did_initialize_script_context_) {
+    return;
+  }
+
+  if (!did_commit_provisional_load_) {
+    // Too soon for context initialization.
+    return;
+  }
+
+  if (queued_context_actions_.empty()) {
+    // Don't need early context initialization. Avoid it due to performance
+    // consequences.
+    return;
+  }
+
+  did_initialize_script_context_ = true;
+
+  // Explicitly force creation of the script context. This occurred implicitly
+  // via DidCommitProvisionalLoad prior to https://crrev.com/5150754880a.
+  // Otherwise, a script context may never be created for a frame that doesn't
+  // contain JS code.
+  v8::HandleScope handle_scope(blink::MainThreadIsolate());
+  frame_->MainWorldScriptContext();
+}
+
+void CefFrameImpl::FrameAttachedAck() {
+  // Sent from the browser process in response to ConnectBrowserFrame() sending
+  // FrameAttached().
+  CHECK_EQ(ConnectionState::CONNECTION_PENDING, browser_connection_state_);
+  browser_connection_state_ = ConnectionState::CONNECTION_ACKED;
+  browser_connect_retry_ct_ = 0;
+  browser_connect_timer_.Stop();
+
+  auto& browser_frame = GetBrowserFrame();
+  CHECK(browser_frame);
+
+  while (!queued_browser_actions_.empty()) {
+    std::move(queued_browser_actions_.front().second).Run(browser_frame);
+    queued_browser_actions_.pop();
+  }
+}
+
+void CefFrameImpl::FrameDetached() {
+  // Sent from the browser process in response to CefFrameHostImpl::Detach().
+  CHECK_EQ(ConnectionState::CONNECTION_ACKED, browser_connection_state_);
+  OnDisconnect(DisconnectReason::BROWSER_FRAME_DETACHED);
+}
+
+void CefFrameImpl::SendMessage(const std::string& name,
+                               base::Value::List arguments) {
+  if (auto app = CefAppManager::Get()->GetApplication()) {
+    if (auto handler = app->GetRenderProcessHandler()) {
+      CefRefPtr<CefProcessMessageImpl> message(
+          new CefProcessMessageImpl(name, std::move(arguments),
+                                    /*read_only=*/true));
+      handler->OnProcessMessageReceived(browser_, this, PID_BROWSER,
+                                        message.get());
+    }
+  }
+}
+
+void CefFrameImpl::SendSharedMemoryRegion(
+    const std::string& name,
+    base::WritableSharedMemoryRegion region) {
+  if (auto app = CefAppManager::Get()->GetApplication()) {
+    if (auto handler = app->GetRenderProcessHandler()) {
+      CefRefPtr<CefProcessMessage> message(
+          new CefProcessMessageSMRImpl(name, std::move(region)));
+      handler->OnProcessMessageReceived(browser_, this, PID_BROWSER, message);
+    }
+  }
+}
+
+void CefFrameImpl::SendCommand(const std::string& command) {
+  ExecuteOnLocalFrame(
+      __FUNCTION__,
+      base::BindOnce(
+          [](const std::string& command, blink::WebLocalFrame* frame) {
+            frame->ExecuteCommand(blink::WebString::FromUTF8(command));
+          },
+          command));
+}
+
+void CefFrameImpl::SendCommandWithResponse(
+    const std::string& command,
+    cef::mojom::RenderFrame::SendCommandWithResponseCallback callback) {
+  ExecuteOnLocalFrame(
+      __FUNCTION__,
+      base::BindOnce(
+          [](const std::string& command,
+             cef::mojom::RenderFrame::SendCommandWithResponseCallback callback,
+             blink::WebLocalFrame* frame) {
+            blink::WebString response;
+
+            if (base::EqualsCaseInsensitiveASCII(command, "getsource")) {
+              response = blink_glue::DumpDocumentMarkup(frame);
+            } else if (base::EqualsCaseInsensitiveASCII(command, "gettext")) {
+              response = blink_glue::DumpDocumentText(frame);
+            }
+
+            std::move(callback).Run(
+                string_util::CreateSharedMemoryRegion(response));
+          },
+          command, std::move(callback)));
+}
+
+void CefFrameImpl::SendJavaScript(const std::u16string& jsCode,
+                                  const std::string& scriptUrl,
+                                  int32_t startLine) {
+  ExecuteOnLocalFrame(
+      __FUNCTION__,
+      base::BindOnce(
+          [](const std::u16string& jsCode, const std::string& scriptUrl,
+             blink::WebLocalFrame* frame) {
+            frame->ExecuteScript(blink::WebScriptSource(
+                blink::WebString::FromUTF16(jsCode), GURL(scriptUrl)));
+          },
+          jsCode, scriptUrl));
+}
+
+void CefFrameImpl::LoadRequest(cef::mojom::RequestParamsPtr params) {
+  ExecuteOnLocalFrame(
+      __FUNCTION__,
+      base::BindOnce(
+          [](cef::mojom::RequestParamsPtr params, blink::WebLocalFrame* frame) {
+            blink::WebURLRequest request;
+            CefRequestImpl::Get(params, request);
+            blink_glue::StartNavigation(frame, request);
+          },
+          std::move(params)));
+}
+
+void CefFrameImpl::DidStopLoading() {
   // We should only receive this notification for the highest-level LocalFrame
-  // in this frame's in-process subtree. If there are multiple of these for the
-  // same browser then the other occurrences will be discarded in
+  // in this frame's in-process subtree. If there are multiple of these for
+  // the same browser then the other occurrences will be discarded in
   // OnLoadingStateChange.
   browser_->OnLoadingStateChange(false);
+
+  if (blink::RuntimeEnabledFeatures::BackForwardCacheEnabled()) {
+    // Refresh draggable regions. Otherwise, we may not receive updated regions
+    // after navigation because LocalFrameView::UpdateDocumentAnnotatedRegion
+    // lacks sufficient context. When bfcache is enabled we can't rely on
+    // OnDidFinishLoad() as the frame may not actually be reloaded.
+    OnDraggableRegionsChanged();
+  }
 }
 
-void CefFrameImpl::OnLoadRequest(const CefMsg_LoadRequest_Params& params) {
-  DCHECK(frame_);
+void CefFrameImpl::MoveOrResizeStarted() {
+  if (frame_) {
+    auto web_view = frame_->View();
+    if (web_view) {
+      web_view->CancelPagePopup();
+    }
+  }
+}
 
-  blink::WebURLRequest request;
-  CefRequestImpl::Get(params, request);
+void CefFrameImpl::ContextLifecycleStateChanged(
+    blink::mojom::blink::FrameLifecycleState state) {
+  if (state == blink::mojom::FrameLifecycleState::kFrozen && IsMain() &&
+      blink_glue::IsInBackForwardCache(frame_)) {
+    browser_->OnEnterBFCache();
+  }
+}
 
-  frame_->StartNavigation(request);
+std::string CefFrameImpl::GetDebugString() const {
+  return "frame " + frame_util::GetFrameDebugString(frame_id_);
 }
 
 // Enable deprecation warnings on Windows. See http://crbug.com/585142.
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 #if defined(__clang__)
 #pragma GCC diagnostic pop
 #else
diff --git a/src/libcef/renderer/frame_impl.h b/src/libcef/renderer/frame_impl.h
index 3859beb..1251e2d 100644
--- a/src/libcef/renderer/frame_impl.h
+++ b/src/libcef/renderer/frame_impl.h
@@ -6,39 +6,48 @@
 #define CEF_LIBCEF_RENDERER_FRAME_IMPL_H_
 #pragma once
 
+#include <queue>
 #include <string>
+
 #include "include/cef_frame.h"
 #include "include/cef_v8.h"
+#include "libcef/renderer/blink_glue.h"
+
+#include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
+#include "cef/libcef/common/mojom/cef.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
 
 namespace base {
 class ListValue;
 }
 
 namespace blink {
+class ResourceLoadInfoNotifierWrapper;
 class WebLocalFrame;
-class WebURLLoaderFactory;
 }  // namespace blink
 
-namespace IPC {
-class Message;
-}
-
 class GURL;
 
 class CefBrowserImpl;
-class CefResponseManager;
-struct CefMsg_LoadRequest_Params;
-struct Cef_Request_Params;
-struct Cef_Response_Params;
 
 // Implementation of CefFrame. CefFrameImpl objects are owned by the
 // CefBrowerImpl and will be detached when the browser is notified that the
 // associated renderer WebFrame will close.
-class CefFrameImpl : public CefFrame {
+class CefFrameImpl
+    : public CefFrame,
+      public cef::mojom::RenderFrame,
+      public blink_glue::CefExecutionContextLifecycleStateObserver {
  public:
   CefFrameImpl(CefBrowserImpl* browser,
                blink::WebLocalFrame* frame,
                int64_t frame_id);
+
+  CefFrameImpl(const CefFrameImpl&) = delete;
+  CefFrameImpl& operator=(const CefFrameImpl&) = delete;
+
   ~CefFrameImpl() override;
 
   // CefFrame implementation.
@@ -61,7 +70,7 @@
   bool IsMain() override;
   bool IsFocused() override;
   CefString GetName() override;
-  int64 GetIdentifier() override;
+  int64_t GetIdentifier() override;
   CefRefPtr<CefFrame> GetParent() override;
   CefString GetURL() override;
   CefRefPtr<CefBrowser> GetBrowser() override;
@@ -73,48 +82,124 @@
   void SendProcessMessage(CefProcessId target_process,
                           CefRefPtr<CefProcessMessage> message) override;
 
-  // Used by CefRenderURLRequest.
-  blink::WebURLLoaderFactory* GetURLLoaderFactory();
-
   // Forwarded from CefRenderFrameObserver.
   void OnAttached();
-  bool OnMessageReceived(const IPC::Message& message);
+  void OnWasShown();
+  void OnDidCommitProvisionalLoad();
   void OnDidFinishLoad();
   void OnDraggableRegionsChanged();
+  void OnContextCreated(v8::Local<v8::Context> context);
+  void OnContextReleased();
   void OnDetached();
 
   blink::WebLocalFrame* web_frame() const { return frame_; }
 
  private:
-  void ExecuteCommand(const std::string& command);
+  // Execute an action on the associated WebLocalFrame. This will queue the
+  // action if the JavaScript context is not yet created.
+  using LocalFrameAction =
+      base::OnceCallback<void(blink::WebLocalFrame* frame)>;
+  void ExecuteOnLocalFrame(const std::string& function_name,
+                           LocalFrameAction action);
 
-  // Avoids unnecessary string type conversions.
-  void SendProcessMessage(CefProcessId target_process,
-                          const std::string& name,
-                          base::ListValue* arguments,
-                          bool user_initiated);
+  enum class ConnectReason {
+    RENDER_FRAME_CREATED,
+    WAS_SHOWN,
+    RETRY,
+  };
 
-  // Send a message to the RenderFrame associated with this frame.
-  void Send(IPC::Message* message);
+  // Initiate the connection to the BrowserFrame channel.
+  void ConnectBrowserFrame(ConnectReason reason);
 
-  // OnMessageReceived message handlers.
-  void OnRequest(const Cef_Request_Params& params);
-  void OnResponse(const Cef_Response_Params& params);
-  void OnResponseAck(int request_id);
-  void OnDidStopLoading();
-  void OnLoadRequest(const CefMsg_LoadRequest_Params& params);
+  // Returns the remote BrowserFrame object.
+  using BrowserFrameType = mojo::Remote<cef::mojom::BrowserFrame>;
+  const BrowserFrameType& GetBrowserFrame(bool expect_acked = true);
+
+  // Called if the BrowserFrame connection attempt times out.
+  void OnBrowserFrameTimeout();
+
+  enum class DisconnectReason {
+    DETACHED,
+    BROWSER_FRAME_DETACHED,
+    CONNECT_TIMEOUT,
+    RENDER_FRAME_DISCONNECT,
+    BROWSER_FRAME_DISCONNECT,
+  };
+
+  // Called if/when a disconnect occurs. This may occur due to frame navigation,
+  // destruction, or insertion into the bfcache (when the browser-side frame
+  // representation is destroyed and closes the connection).
+  void OnDisconnect(DisconnectReason reason);
+
+  // Send an action to the remote BrowserFrame. This will queue the action if
+  // the remote frame is not yet attached.
+  using BrowserFrameAction = base::OnceCallback<void(const BrowserFrameType&)>;
+  void SendToBrowserFrame(const std::string& function_name,
+                          BrowserFrameAction action);
+
+  void MaybeInitializeScriptContext();
+
+  // cef::mojom::RenderFrame methods:
+  void FrameAttachedAck() override;
+  void FrameDetached() override;
+  void SendMessage(const std::string& name,
+                   base::Value::List arguments) override;
+  void SendSharedMemoryRegion(const std::string& name,
+                              base::WritableSharedMemoryRegion region) override;
+  void SendCommand(const std::string& command) override;
+  void SendCommandWithResponse(
+      const std::string& command,
+      cef::mojom::RenderFrame::SendCommandWithResponseCallback callback)
+      override;
+  void SendJavaScript(const std::u16string& jsCode,
+                      const std::string& scriptUrl,
+                      int32_t startLine) override;
+  void LoadRequest(cef::mojom::RequestParamsPtr params) override;
+  void DidStopLoading() override;
+  void MoveOrResizeStarted() override;
+
+  // blink_glue::CefExecutionContextLifecycleStateObserver methods:
+  void ContextLifecycleStateChanged(
+      blink::mojom::blink::FrameLifecycleState state) override;
+
+  std::string GetDebugString() const;
 
   CefBrowserImpl* browser_;
   blink::WebLocalFrame* frame_;
-  const int64 frame_id_;
+  const int64_t frame_id_;
 
-  std::unique_ptr<blink::WebURLLoaderFactory> url_loader_factory_;
+  bool did_commit_provisional_load_ = false;
+  bool did_initialize_script_context_ = false;
 
-  // Manages response registrations.
-  std::unique_ptr<CefResponseManager> response_manager_;
+  bool context_created_ = false;
+  std::queue<std::pair<std::string, LocalFrameAction>> queued_context_actions_;
+
+  // Number of times that browser reconnect has been attempted.
+  size_t browser_connect_retry_ct_ = 0;
+
+  // Current browser connection state.
+  enum class ConnectionState {
+    DISCONNECTED,
+    CONNECTION_PENDING,
+    CONNECTION_ACKED,
+    RECONNECT_PENDING,
+  } browser_connection_state_ = ConnectionState::DISCONNECTED;
+
+  base::OneShotTimer browser_connect_timer_;
+
+  std::queue<std::pair<std::string, BrowserFrameAction>>
+      queued_browser_actions_;
+
+  mojo::Receiver<cef::mojom::RenderFrame> receiver_{this};
+
+  mojo::Remote<cef::mojom::BrowserFrame> browser_frame_;
+
+  std::unique_ptr<blink_glue::CefObserverRegistration>
+      execution_context_lifecycle_state_observer_;
+
+  base::WeakPtrFactory<CefFrameImpl> weak_ptr_factory_{this};
 
   IMPLEMENT_REFCOUNTING(CefFrameImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefFrameImpl);
 };
 
 #endif  // CEF_LIBCEF_RENDERER_FRAME_IMPL_H_
diff --git a/src/libcef/renderer/render_frame_observer.cc b/src/libcef/renderer/render_frame_observer.cc
index f3bf062..45d59df 100644
--- a/src/libcef/renderer/render_frame_observer.cc
+++ b/src/libcef/renderer/render_frame_observer.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be found
 // in the LICENSE file.
 
-#include "base/compiler_specific.h"
+#include "build/build_config.h"
 
 // Enable deprecation warnings on Windows. See http://crbug.com/585142.
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 #if defined(__clang__)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic error "-Wdeprecated-declarations"
@@ -17,18 +17,16 @@
 
 #include "libcef/renderer/render_frame_observer.h"
 
-#include "libcef/common/content_client.h"
+#include "libcef/common/app_manager.h"
 #include "libcef/renderer/blink_glue.h"
 #include "libcef/renderer/browser_impl.h"
 #include "libcef/renderer/dom_document_impl.h"
 #include "libcef/renderer/v8_impl.h"
 
 #include "content/public/renderer/render_frame.h"
-#include "content/public/renderer/render_view.h"
-#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
-#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
 #include "third_party/blink/public/web/blink.h"
 #include "third_party/blink/public/web/web_document.h"
+#include "third_party/blink/public/web/web_element.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/public/web/web_node.h"
 
@@ -36,25 +34,15 @@
     content::RenderFrame* render_frame)
     : content::RenderFrameObserver(render_frame) {}
 
-CefRenderFrameObserver::~CefRenderFrameObserver() {}
-
-void CefRenderFrameObserver::OnInterfaceRequestForFrame(
-    const std::string& interface_name,
-    mojo::ScopedMessagePipeHandle* interface_pipe) {
-  registry_.TryBindInterface(interface_name, interface_pipe);
-}
-
-bool CefRenderFrameObserver::OnAssociatedInterfaceRequestForFrame(
-    const std::string& interface_name,
-    mojo::ScopedInterfaceEndpointHandle* handle) {
-  return associated_interfaces_.TryBindInterface(interface_name, handle);
-}
+CefRenderFrameObserver::~CefRenderFrameObserver() = default;
 
 void CefRenderFrameObserver::DidCommitProvisionalLoad(
-    bool is_same_document_navigation,
     ui::PageTransition transition) {
-  if (!frame_)
+  if (!frame_) {
     return;
+  }
+
+  frame_->OnDidCommitProvisionalLoad();
 
   if (frame_->GetParent() == nullptr) {
     blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
@@ -65,6 +53,12 @@
   OnLoadStart();
 }
 
+void CefRenderFrameObserver::WasShown() {
+  if (frame_) {
+    frame_->OnWasShown();
+  }
+}
+
 void CefRenderFrameObserver::DidFailProvisionalLoad() {
   if (frame_) {
     OnLoadError();
@@ -77,7 +71,7 @@
   }
 }
 
-void CefRenderFrameObserver::FrameDetached() {
+void CefRenderFrameObserver::WillDetach() {
   if (frame_) {
     frame_->OnDetached();
     frame_ = nullptr;
@@ -86,21 +80,25 @@
 
 void CefRenderFrameObserver::FocusedElementChanged(
     const blink::WebElement& element) {
-  if (!frame_)
+  if (!frame_) {
     return;
+  }
 
   blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
   CefRefPtr<CefBrowserImpl> browserPtr =
       CefBrowserImpl::GetBrowserForMainFrame(frame->Top());
-  if (!browserPtr)
+  if (!browserPtr) {
     return;
+  }
 
   CefRefPtr<CefRenderProcessHandler> handler;
-  CefRefPtr<CefApp> application = CefContentClient::Get()->application();
-  if (application)
+  CefRefPtr<CefApp> application = CefAppManager::Get()->GetApplication();
+  if (application) {
     handler = application->GetRenderProcessHandler();
-  if (!handler)
+  }
+  if (!handler) {
     return;
+  }
 
   CefRefPtr<CefFrameImpl> framePtr = browserPtr->GetWebFrameImpl(frame);
 
@@ -109,8 +107,9 @@
     return;
   }
 
-  if (element.GetDocument().IsNull())
+  if (element.GetDocument().IsNull()) {
     return;
+  }
 
   CefRefPtr<CefDOMDocumentImpl> documentImpl =
       new CefDOMDocumentImpl(browserPtr.get(), frame);
@@ -128,33 +127,39 @@
 void CefRenderFrameObserver::DidCreateScriptContext(
     v8::Handle<v8::Context> context,
     int world_id) {
-  if (!frame_)
+  if (!frame_) {
     return;
+  }
 
   blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
   CefRefPtr<CefBrowserImpl> browserPtr =
       CefBrowserImpl::GetBrowserForMainFrame(frame->Top());
-  if (!browserPtr)
+  if (!browserPtr) {
     return;
+  }
 
   CefRefPtr<CefRenderProcessHandler> handler;
-  CefRefPtr<CefApp> application = CefContentClient::Get()->application();
-  if (application)
+  CefRefPtr<CefApp> application = CefAppManager::Get()->GetApplication();
+  if (application) {
     handler = application->GetRenderProcessHandler();
-  if (!handler)
-    return;
+  }
 
   CefRefPtr<CefFrameImpl> framePtr = browserPtr->GetWebFrameImpl(frame);
 
-  v8::Isolate* isolate = blink::MainThreadIsolate();
-  v8::HandleScope handle_scope(isolate);
-  v8::Context::Scope scope(context);
-  v8::MicrotasksScope microtasks_scope(isolate,
-                                       v8::MicrotasksScope::kRunMicrotasks);
+  if (handler) {
+    v8::Isolate* isolate = blink::MainThreadIsolate();
+    v8::HandleScope handle_scope(isolate);
+    v8::Context::Scope scope(context);
+    v8::MicrotasksScope microtasks_scope(isolate,
+                                         v8::MicrotasksScope::kRunMicrotasks);
 
-  CefRefPtr<CefV8Context> contextPtr(new CefV8ContextImpl(isolate, context));
+    CefRefPtr<CefV8Context> contextPtr(new CefV8ContextImpl(isolate, context));
 
-  handler->OnContextCreated(browserPtr.get(), framePtr.get(), contextPtr);
+    handler->OnContextCreated(browserPtr.get(), framePtr.get(), contextPtr);
+  }
+
+  // Do this last, in case the client callback modified the window object.
+  framePtr->OnContextCreated(context);
 }
 
 void CefRenderFrameObserver::WillReleaseScriptContext(
@@ -163,31 +168,34 @@
   blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
   CefRefPtr<CefBrowserImpl> browserPtr =
       CefBrowserImpl::GetBrowserForMainFrame(frame->Top());
-  if (browserPtr) {
-    CefRefPtr<CefApp> application = CefContentClient::Get()->application();
-    if (application) {
-      CefRefPtr<CefRenderProcessHandler> handler =
-          application->GetRenderProcessHandler();
-      if (handler) {
-        CefRefPtr<CefFrameImpl> framePtr = browserPtr->GetWebFrameImpl(frame);
-
-        v8::Isolate* isolate = blink::MainThreadIsolate();
-        v8::HandleScope handle_scope(isolate);
-
-        // The released context should not be used for script execution.
-        // Depending on how the context is released this may or may not already
-        // be set.
-        blink_glue::CefScriptForbiddenScope forbidScript;
-
-        CefRefPtr<CefV8Context> contextPtr(
-            new CefV8ContextImpl(isolate, context));
-
-        handler->OnContextReleased(browserPtr.get(), framePtr.get(),
-                                   contextPtr);
-      }
-    }
+  if (!browserPtr) {
+    return;
   }
 
+  CefRefPtr<CefRenderProcessHandler> handler;
+  CefRefPtr<CefApp> application = CefAppManager::Get()->GetApplication();
+  if (application) {
+    handler = application->GetRenderProcessHandler();
+  }
+
+  CefRefPtr<CefFrameImpl> framePtr = browserPtr->GetWebFrameImpl(frame);
+
+  if (handler) {
+    v8::Isolate* isolate = blink::MainThreadIsolate();
+    v8::HandleScope handle_scope(isolate);
+
+    // The released context should not be used for script execution.
+    // Depending on how the context is released this may or may not already
+    // be set.
+    blink_glue::CefScriptForbiddenScope forbidScript;
+
+    CefRefPtr<CefV8Context> contextPtr(new CefV8ContextImpl(isolate, context));
+
+    handler->OnContextReleased(browserPtr.get(), framePtr.get(), contextPtr);
+  }
+
+  framePtr->OnContextReleased();
+
   CefV8ReleaseContext(context);
 }
 
@@ -195,11 +203,16 @@
   delete this;
 }
 
-bool CefRenderFrameObserver::OnMessageReceived(const IPC::Message& message) {
-  if (frame_) {
-    return frame_->OnMessageReceived(message);
-  }
-  return false;
+void CefRenderFrameObserver::OnInterfaceRequestForFrame(
+    const std::string& interface_name,
+    mojo::ScopedMessagePipeHandle* interface_pipe) {
+  registry_.TryBindInterface(interface_name, interface_pipe);
+}
+
+bool CefRenderFrameObserver::OnAssociatedInterfaceRequestForFrame(
+    const std::string& interface_name,
+    mojo::ScopedInterfaceEndpointHandle* handle) {
+  return associated_interfaces_.TryBindInterface(interface_name, handle);
 }
 
 void CefRenderFrameObserver::AttachFrame(CefFrameImpl* frame) {
@@ -210,7 +223,7 @@
 }
 
 void CefRenderFrameObserver::OnLoadStart() {
-  CefRefPtr<CefApp> app = CefContentClient::Get()->application();
+  CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
   if (app.get()) {
     CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
     if (handler.get()) {
@@ -226,7 +239,7 @@
 }
 
 void CefRenderFrameObserver::OnLoadError() {
-  CefRefPtr<CefApp> app = CefContentClient::Get()->application();
+  CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
   if (app.get()) {
     CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
     if (handler.get()) {
@@ -237,19 +250,18 @@
         const cef_errorcode_t errorCode =
             static_cast<cef_errorcode_t>(net::ERR_ABORTED);
         const std::string& errorText = net::ErrorToString(errorCode);
-        const GURL failedUrl(frame_->GetURL().c_str());
         blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
         CefRefPtr<CefBrowserImpl> browserPtr =
             CefBrowserImpl::GetBrowserForMainFrame(frame->Top());
         load_handler->OnLoadError(browserPtr.get(), frame_, errorCode,
-                                  errorText, failedUrl.spec());
+                                  errorText, frame_->GetURL());
       }
     }
   }
 }
 
 // Enable deprecation warnings on Windows. See http://crbug.com/585142.
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 #if defined(__clang__)
 #pragma GCC diagnostic pop
 #else
diff --git a/src/libcef/renderer/render_frame_observer.h b/src/libcef/renderer/render_frame_observer.h
index d395e4b..4964832 100644
--- a/src/libcef/renderer/render_frame_observer.h
+++ b/src/libcef/renderer/render_frame_observer.h
@@ -6,6 +6,7 @@
 #define LIBCEF_RENDERER_RENDER_FRAME_OBSERVER_H_
 
 #include "content/public/renderer/render_frame_observer.h"
+
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
 
@@ -19,20 +20,18 @@
 class CefRenderFrameObserver : public content::RenderFrameObserver {
  public:
   explicit CefRenderFrameObserver(content::RenderFrame* render_frame);
+
+  CefRenderFrameObserver(const CefRenderFrameObserver&) = delete;
+  CefRenderFrameObserver& operator=(const CefRenderFrameObserver&) = delete;
+
   ~CefRenderFrameObserver() override;
 
   // RenderFrameObserver methods:
-  void OnInterfaceRequestForFrame(
-      const std::string& interface_name,
-      mojo::ScopedMessagePipeHandle* interface_pipe) override;
-  bool OnAssociatedInterfaceRequestForFrame(
-      const std::string& interface_name,
-      mojo::ScopedInterfaceEndpointHandle* handle) override;
-  void DidCommitProvisionalLoad(bool is_same_document_navigation,
-                                ui::PageTransition transition) override;
+  void WasShown() override;
+  void DidCommitProvisionalLoad(ui::PageTransition transition) override;
   void DidFailProvisionalLoad() override;
   void DidFinishLoad() override;
-  void FrameDetached() override;
+  void WillDetach() override;
   void FocusedElementChanged(const blink::WebElement& element) override;
   void DraggableRegionsChanged() override;
   void DidCreateScriptContext(v8::Handle<v8::Context> context,
@@ -40,7 +39,12 @@
   void WillReleaseScriptContext(v8::Handle<v8::Context> context,
                                 int world_id) override;
   void OnDestruct() override;
-  bool OnMessageReceived(const IPC::Message& message) override;
+  void OnInterfaceRequestForFrame(
+      const std::string& interface_name,
+      mojo::ScopedMessagePipeHandle* interface_pipe) override;
+  bool OnAssociatedInterfaceRequestForFrame(
+      const std::string& interface_name,
+      mojo::ScopedInterfaceEndpointHandle* handle) override;
 
   service_manager::BinderRegistry* registry() { return &registry_; }
   blink::AssociatedInterfaceRegistry* associated_interfaces() {
@@ -53,11 +57,14 @@
   void OnLoadStart();
   void OnLoadError();
 
-  service_manager::BinderRegistry registry_;
-  blink::AssociatedInterfaceRegistry associated_interfaces_;
   CefFrameImpl* frame_ = nullptr;
 
-  DISALLOW_COPY_AND_ASSIGN(CefRenderFrameObserver);
+  service_manager::BinderRegistry registry_;
+
+  // For interfaces which must be associated with some IPC::ChannelProxy,
+  // meaning that messages on the interface retain FIFO with respect to legacy
+  // Chrome IPC messages sent or dispatched on the channel.
+  blink::AssociatedInterfaceRegistry associated_interfaces_;
 };
 
 #endif  // LIBCEF_RENDERER_RENDER_FRAME_OBSERVER_H_
diff --git a/src/libcef/renderer/render_frame_util.cc b/src/libcef/renderer/render_frame_util.cc
index 9cb0098..62d9549 100644
--- a/src/libcef/renderer/render_frame_util.cc
+++ b/src/libcef/renderer/render_frame_util.cc
@@ -10,7 +10,6 @@
 
 #include "base/logging.h"
 #include "content/public/renderer/render_thread.h"
-#include "content/public/renderer/render_view.h"
 #include "content/renderer/render_frame_impl.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 
@@ -37,8 +36,9 @@
   content::RenderFrameImpl* render_frame =
       content::RenderFrameImpl::FromWebFrame(frame);
   DCHECK(render_frame);
-  if (render_frame)
+  if (render_frame) {
     return render_frame->unique_name();
+  }
   return std::string();
 }
 
diff --git a/src/libcef/renderer/render_manager.cc b/src/libcef/renderer/render_manager.cc
new file mode 100644
index 0000000..771d75e
--- /dev/null
+++ b/src/libcef/renderer/render_manager.cc
@@ -0,0 +1,411 @@
+// Copyright 2015 The Chromium Embedded Framework 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 "libcef/renderer/render_manager.h"
+
+#include <tuple>
+
+#include "build/build_config.h"
+
+// Enable deprecation warnings on Windows. See http://crbug.com/585142.
+#if BUILDFLAG(IS_WIN)
+#if defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic error "-Wdeprecated-declarations"
+#else
+#pragma warning(push)
+#pragma warning(default : 4996)
+#endif
+#endif
+
+#include "libcef/common/app_manager.h"
+#include "libcef/common/cef_switches.h"
+#include "libcef/common/net/scheme_info.h"
+#include "libcef/common/values_impl.h"
+#include "libcef/renderer/blink_glue.h"
+#include "libcef/renderer/browser_impl.h"
+#include "libcef/renderer/render_frame_observer.h"
+#include "libcef/renderer/thread_util.h"
+#include "libcef/renderer/v8_impl.h"
+
+#include "base/command_line.h"
+#include "base/strings/string_number_conversions.h"
+#include "cef/libcef/common/mojom/cef.mojom.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/renderer/render_frame.h"
+#include "content/public/renderer/render_thread.h"
+#include "extensions/common/switches.h"
+#include "mojo/public/cpp/bindings/binder_map.h"
+#include "services/network/public/mojom/cors_origin_pattern.mojom.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/public/web/web_frame.h"
+#include "third_party/blink/public/web/web_security_policy.h"
+#include "third_party/blink/public/web/web_view.h"
+#include "third_party/blink/public/web/web_view_observer.h"
+
+namespace {
+
+CefRenderManager* g_manager = nullptr;
+
+}  // namespace
+
+// Placeholder object for guest views.
+class CefGuestView : public blink::WebViewObserver {
+ public:
+  CefGuestView(CefRenderManager* manager,
+               blink::WebView* web_view,
+               bool is_windowless)
+      : blink::WebViewObserver(web_view),
+        manager_(manager),
+        is_windowless_(is_windowless) {}
+
+  bool is_windowless() const { return is_windowless_; }
+
+ private:
+  // RenderViewObserver methods.
+  void OnDestruct() override { manager_->OnGuestViewDestroyed(this); }
+
+  CefRenderManager* const manager_;
+  const bool is_windowless_;
+};
+
+CefRenderManager::CefRenderManager() {
+  DCHECK(!g_manager);
+  g_manager = this;
+}
+
+CefRenderManager::~CefRenderManager() {
+  g_manager = nullptr;
+}
+
+// static
+CefRenderManager* CefRenderManager::Get() {
+  CEF_REQUIRE_RT_RETURN(nullptr);
+  return g_manager;
+}
+
+void CefRenderManager::RenderThreadConnected() {
+  // Retrieve the new render thread information synchronously.
+  auto params = cef::mojom::NewRenderThreadInfo::New();
+  GetBrowserManager()->GetNewRenderThreadInfo(&params);
+
+  // Cross-origin entries need to be added after WebKit is initialized.
+  if (params->cross_origin_whitelist_entries) {
+    cross_origin_whitelist_entries_.swap(
+        *params->cross_origin_whitelist_entries);
+  }
+
+  WebKitInitialized();
+}
+
+void CefRenderManager::RenderFrameCreated(
+    content::RenderFrame* render_frame,
+    CefRenderFrameObserver* render_frame_observer,
+    bool& browser_created,
+    absl::optional<bool>& is_windowless) {
+  auto browser = MaybeCreateBrowser(render_frame->GetWebView(), render_frame,
+                                    &browser_created, &is_windowless);
+  if (browser) {
+    // Attach the frame to the observer for message routing purposes.
+    render_frame_observer->AttachFrame(
+        browser->GetWebFrameImpl(render_frame->GetWebFrame()).get());
+  }
+}
+
+void CefRenderManager::WebViewCreated(blink::WebView* web_view,
+                                      bool& browser_created,
+                                      absl::optional<bool>& is_windowless) {
+  content::RenderFrame* render_frame = nullptr;
+  if (web_view->MainFrame()->IsWebLocalFrame()) {
+    render_frame = content::RenderFrame::FromWebFrame(
+        web_view->MainFrame()->ToWebLocalFrame());
+  }
+
+  MaybeCreateBrowser(web_view, render_frame, &browser_created, &is_windowless);
+}
+
+void CefRenderManager::DevToolsAgentAttached() {
+  ++devtools_agent_count_;
+}
+
+void CefRenderManager::DevToolsAgentDetached() {
+  --devtools_agent_count_;
+  if (devtools_agent_count_ == 0 && uncaught_exception_stack_size_ > 0) {
+    // When the last DevToolsAgent is detached the stack size is set to 0.
+    // Restore the user-specified stack size here.
+    CefV8SetUncaughtExceptionStackSize(uncaught_exception_stack_size_);
+  }
+}
+
+void CefRenderManager::ExposeInterfacesToBrowser(mojo::BinderMap* binders) {
+  auto task_runner = base::SequencedTaskRunner::GetCurrentDefault();
+
+  binders->Add<cef::mojom::RenderManager>(
+      base::BindRepeating(
+          [](CefRenderManager* render_manager,
+             mojo::PendingReceiver<cef::mojom::RenderManager> receiver) {
+            render_manager->BindReceiver(std::move(receiver));
+          },
+          base::Unretained(this)),
+      task_runner);
+}
+
+CefRefPtr<CefBrowserImpl> CefRenderManager::GetBrowserForView(
+    blink::WebView* view) {
+  BrowserMap::const_iterator it = browsers_.find(view);
+  if (it != browsers_.end()) {
+    return it->second;
+  }
+  return nullptr;
+}
+
+CefRefPtr<CefBrowserImpl> CefRenderManager::GetBrowserForMainFrame(
+    blink::WebFrame* frame) {
+  BrowserMap::const_iterator it = browsers_.begin();
+  for (; it != browsers_.end(); ++it) {
+    auto web_view = it->second->GetWebView();
+    if (web_view && web_view->MainFrame() == frame) {
+      return it->second;
+    }
+  }
+
+  return nullptr;
+}
+
+mojo::Remote<cef::mojom::BrowserManager>&
+CefRenderManager::GetBrowserManager() {
+  if (!browser_manager_) {
+    content::RenderThread::Get()->BindHostReceiver(
+        browser_manager_.BindNewPipeAndPassReceiver());
+  }
+  return browser_manager_;
+}
+
+// static
+bool CefRenderManager::IsExtensionProcess() {
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(
+      extensions::switches::kExtensionProcess);
+}
+
+// static
+bool CefRenderManager::IsPdfProcess() {
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kPdfRenderer);
+}
+
+void CefRenderManager::BindReceiver(
+    mojo::PendingReceiver<cef::mojom::RenderManager> receiver) {
+  receivers_.Add(this, std::move(receiver));
+}
+
+void CefRenderManager::ModifyCrossOriginWhitelistEntry(
+    bool add,
+    cef::mojom::CrossOriginWhiteListEntryPtr entry) {
+  GURL gurl = GURL(entry->source_origin);
+  if (add) {
+    blink::WebSecurityPolicy::AddOriginAccessAllowListEntry(
+        gurl, blink::WebString::FromUTF8(entry->target_protocol),
+        blink::WebString::FromUTF8(entry->target_domain),
+        /*destination_port=*/0,
+        entry->allow_target_subdomains
+            ? network::mojom::CorsDomainMatchMode::kAllowSubdomains
+            : network::mojom::CorsDomainMatchMode::kDisallowSubdomains,
+        network::mojom::CorsPortMatchMode::kAllowAnyPort,
+        network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
+  } else {
+    blink::WebSecurityPolicy::ClearOriginAccessListForOrigin(gurl);
+  }
+}
+
+void CefRenderManager::ClearCrossOriginWhitelist() {
+  blink::WebSecurityPolicy::ClearOriginAccessList();
+}
+
+void CefRenderManager::WebKitInitialized() {
+  const base::CommandLine* command_line =
+      base::CommandLine::ForCurrentProcess();
+
+  // Create global objects associated with the default Isolate.
+  CefV8IsolateCreated();
+
+  const CefAppManager::SchemeInfoList* schemes =
+      CefAppManager::Get()->GetCustomSchemes();
+  if (!schemes->empty()) {
+    // Register the custom schemes. Some attributes are excluded here because
+    // they use url/url_util.h APIs instead.
+    CefAppManager::SchemeInfoList::const_iterator it = schemes->begin();
+    for (; it != schemes->end(); ++it) {
+      const CefSchemeInfo& info = *it;
+      const blink::WebString& scheme =
+          blink::WebString::FromUTF8(info.scheme_name);
+      if (info.is_display_isolated) {
+        blink::WebSecurityPolicy::RegisterURLSchemeAsDisplayIsolated(scheme);
+      }
+      if (info.is_fetch_enabled) {
+        blink_glue::RegisterURLSchemeAsSupportingFetchAPI(scheme);
+      }
+    }
+  }
+
+  if (!cross_origin_whitelist_entries_.empty()) {
+    // Add the cross-origin white list entries.
+    for (auto& entry : cross_origin_whitelist_entries_) {
+      ModifyCrossOriginWhitelistEntry(/*add=*/true, std::move(entry));
+    }
+    cross_origin_whitelist_entries_.clear();
+  }
+
+  // The number of stack trace frames to capture for uncaught exceptions.
+  if (command_line->HasSwitch(switches::kUncaughtExceptionStackSize)) {
+    int uncaught_exception_stack_size = 0;
+    base::StringToInt(command_line->GetSwitchValueASCII(
+                          switches::kUncaughtExceptionStackSize),
+                      &uncaught_exception_stack_size);
+
+    if (uncaught_exception_stack_size > 0) {
+      uncaught_exception_stack_size_ = uncaught_exception_stack_size;
+      CefV8SetUncaughtExceptionStackSize(uncaught_exception_stack_size_);
+    }
+  }
+
+  // Notify the render process handler.
+  CefRefPtr<CefApp> application = CefAppManager::Get()->GetApplication();
+  if (application.get()) {
+    CefRefPtr<CefRenderProcessHandler> handler =
+        application->GetRenderProcessHandler();
+    if (handler.get()) {
+      handler->OnWebKitInitialized();
+    }
+  }
+}
+
+CefRefPtr<CefBrowserImpl> CefRenderManager::MaybeCreateBrowser(
+    blink::WebView* web_view,
+    content::RenderFrame* render_frame,
+    bool* browser_created,
+    absl::optional<bool>* is_windowless) {
+  if (browser_created) {
+    *browser_created = false;
+  }
+
+  if (!web_view || !render_frame) {
+    return nullptr;
+  }
+
+  // Don't create another browser or guest view object if one already exists for
+  // the view.
+  auto browser = GetBrowserForView(web_view);
+  if (browser) {
+    if (is_windowless) {
+      *is_windowless = browser->is_windowless();
+    }
+    return browser;
+  }
+
+  auto guest_view = GetGuestViewForView(web_view);
+  if (guest_view) {
+    if (is_windowless) {
+      *is_windowless = guest_view->is_windowless();
+    }
+    return nullptr;
+  }
+
+  const bool is_pdf = IsPdfProcess();
+
+  auto params = cef::mojom::NewBrowserInfo::New();
+  if (!is_pdf) {
+    // Retrieve browser information synchronously.
+    GetBrowserManager()->GetNewBrowserInfo(render_frame->GetRoutingID(),
+                                           &params);
+    if (params->browser_id == 0) {
+      // The popup may have been canceled during creation.
+      return nullptr;
+    }
+  }
+
+  if (is_windowless) {
+    *is_windowless = params->is_windowless;
+  }
+
+  if (is_pdf || params->is_guest_view || params->browser_id < 0) {
+    // Don't create a CefBrowser for a PDF renderer, guest view, or if the new
+    // browser info response has timed out.
+    guest_views_.insert(std::make_pair(
+        web_view,
+        std::make_unique<CefGuestView>(this, web_view, params->is_windowless)));
+    return nullptr;
+  }
+
+  browser = new CefBrowserImpl(web_view, params->browser_id, params->is_popup,
+                               params->is_windowless);
+  browsers_.insert(std::make_pair(web_view, browser));
+
+  // Notify the render process handler.
+  CefRefPtr<CefApp> application = CefAppManager::Get()->GetApplication();
+  if (application.get()) {
+    CefRefPtr<CefRenderProcessHandler> handler =
+        application->GetRenderProcessHandler();
+    if (handler.get()) {
+      CefRefPtr<CefDictionaryValueImpl> dictValuePtr;
+      if (params->extra_info) {
+        dictValuePtr =
+            new CefDictionaryValueImpl(std::move(*params->extra_info),
+                                       /*read_only=*/true);
+      }
+      handler->OnBrowserCreated(browser.get(), dictValuePtr.get());
+    }
+  }
+
+  if (browser_created) {
+    *browser_created = true;
+  }
+
+  return browser;
+}
+
+void CefRenderManager::OnBrowserDestroyed(CefBrowserImpl* browser) {
+  BrowserMap::iterator it = browsers_.begin();
+  for (; it != browsers_.end(); ++it) {
+    if (it->second.get() == browser) {
+      browsers_.erase(it);
+      return;
+    }
+  }
+
+  // No browser was found in the map.
+  DCHECK(false);
+}
+
+CefGuestView* CefRenderManager::GetGuestViewForView(blink::WebView* view) {
+  CEF_REQUIRE_RT_RETURN(nullptr);
+
+  GuestViewMap::const_iterator it = guest_views_.find(view);
+  if (it != guest_views_.end()) {
+    return it->second.get();
+  }
+  return nullptr;
+}
+
+void CefRenderManager::OnGuestViewDestroyed(CefGuestView* guest_view) {
+  GuestViewMap::iterator it = guest_views_.begin();
+  for (; it != guest_views_.end(); ++it) {
+    if (it->second.get() == guest_view) {
+      guest_views_.erase(it);
+      return;
+    }
+  }
+
+  // No guest view was found in the map.
+  DCHECK(false);
+}
+
+// Enable deprecation warnings on Windows. See http://crbug.com/585142.
+#if BUILDFLAG(IS_WIN)
+#if defined(__clang__)
+#pragma GCC diagnostic pop
+#else
+#pragma warning(pop)
+#endif
+#endif
diff --git a/src/libcef/renderer/render_manager.h b/src/libcef/renderer/render_manager.h
new file mode 100644
index 0000000..754ad2a
--- /dev/null
+++ b/src/libcef/renderer/render_manager.h
@@ -0,0 +1,131 @@
+// Copyright 2015 The Chromium Embedded Framework 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 CEF_LIBCEF_RENDERER_RENDER_MANAGER_H_
+#define CEF_LIBCEF_RENDERER_RENDER_MANAGER_H_
+#pragma once
+
+#include <map>
+#include <memory>
+
+#include "include/internal/cef_ptr.h"
+
+#include "cef/libcef/common/mojom/cef.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace blink {
+class WebFrame;
+class WebView;
+}  // namespace blink
+
+namespace content {
+class RenderFrame;
+}  // namespace content
+
+namespace mojo {
+class BinderMap;
+}  // namespace mojo
+
+class CefBrowserImpl;
+class CefGuestView;
+class CefRenderFrameObserver;
+
+// Singleton object for managing BrowserImpl instances. Only accessed on the
+// main renderer thread.
+class CefRenderManager : public cef::mojom::RenderManager {
+ public:
+  CefRenderManager();
+
+  CefRenderManager(const CefRenderManager&) = delete;
+  CefRenderManager& operator=(const CefRenderManager&) = delete;
+
+  ~CefRenderManager();
+
+  // Returns this singleton instance of this class.
+  static CefRenderManager* Get();
+
+  // Called from ContentRendererClient methods of the same name.
+  void RenderThreadConnected();
+  void RenderFrameCreated(content::RenderFrame* render_frame,
+                          CefRenderFrameObserver* render_frame_observer,
+                          bool& browser_created,
+                          absl::optional<bool>& is_windowless);
+  void WebViewCreated(blink::WebView* web_view,
+                      bool& browser_created,
+                      absl::optional<bool>& is_windowless);
+  void DevToolsAgentAttached();
+  void DevToolsAgentDetached();
+  void ExposeInterfacesToBrowser(mojo::BinderMap* binders);
+
+  // Returns the browser associated with the specified RenderView.
+  CefRefPtr<CefBrowserImpl> GetBrowserForView(blink::WebView* view);
+
+  // Returns the browser associated with the specified main WebFrame.
+  CefRefPtr<CefBrowserImpl> GetBrowserForMainFrame(blink::WebFrame* frame);
+
+  // Connects to CefBrowserManager in the browser process.
+  mojo::Remote<cef::mojom::BrowserManager>& GetBrowserManager();
+
+  // Returns true if this renderer process is hosting an extension.
+  static bool IsExtensionProcess();
+
+  // Returns true if this renderer process is hosting a PDF.
+  static bool IsPdfProcess();
+
+ private:
+  friend class CefBrowserImpl;
+  friend class CefGuestView;
+
+  // Binds receivers for the RenderManager interface.
+  void BindReceiver(mojo::PendingReceiver<cef::mojom::RenderManager> receiver);
+
+  // cef::mojom::RenderManager methods:
+  void ModifyCrossOriginWhitelistEntry(
+      bool add,
+      cef::mojom::CrossOriginWhiteListEntryPtr entry) override;
+  void ClearCrossOriginWhitelist() override;
+
+  void WebKitInitialized();
+
+  // Maybe create a new browser object, return the existing one, or return
+  // nullptr for guest views.
+  CefRefPtr<CefBrowserImpl> MaybeCreateBrowser(
+      blink::WebView* web_view,
+      content::RenderFrame* render_frame,
+      bool* browser_created,
+      absl::optional<bool>* is_windowless);
+
+  // Called from CefBrowserImpl::OnDestruct().
+  void OnBrowserDestroyed(CefBrowserImpl* browser);
+
+  // Returns the guest view associated with the specified RenderView if any.
+  CefGuestView* GetGuestViewForView(blink::WebView* view);
+
+  // Called from CefGuestView::OnDestruct().
+  void OnGuestViewDestroyed(CefGuestView* guest_view);
+
+  // Map of RenderView pointers to CefBrowserImpl references.
+  using BrowserMap = std::map<blink::WebView*, CefRefPtr<CefBrowserImpl>>;
+  BrowserMap browsers_;
+
+  // Map of RenderView poiners to CefGuestView implementations.
+  using GuestViewMap = std::map<blink::WebView*, std::unique_ptr<CefGuestView>>;
+  GuestViewMap guest_views_;
+
+  // Cross-origin white list entries that need to be registered with WebKit.
+  std::vector<cef::mojom::CrossOriginWhiteListEntryPtr>
+      cross_origin_whitelist_entries_;
+
+  int devtools_agent_count_ = 0;
+  int uncaught_exception_stack_size_ = 0;
+
+  mojo::ReceiverSet<cef::mojom::RenderManager> receivers_;
+
+  mojo::Remote<cef::mojom::BrowserManager> browser_manager_;
+};
+
+#endif  // CEF_LIBCEF_RENDERER_RENDER_MANAGER_H_
diff --git a/src/libcef/renderer/render_thread_observer.cc b/src/libcef/renderer/render_thread_observer.cc
deleted file mode 100644
index e4c3bdf..0000000
--- a/src/libcef/renderer/render_thread_observer.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-/// Copyright (c) 2013 The Chromium Embedded Framework Authors.
-// Portions (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/renderer/render_thread_observer.h"
-
-#include "libcef/common/cef_messages.h"
-#include "libcef/common/net/net_resource_provider.h"
-#include "libcef/renderer/blink_glue.h"
-#include "libcef/renderer/content_renderer_client.h"
-
-#include "components/visitedlink/renderer/visitedlink_reader.h"
-#include "content/public/child/child_thread.h"
-#include "content/public/renderer/render_thread.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "net/base/net_module.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/public/web/web_security_policy.h"
-
-namespace {
-
-chrome::mojom::DynamicParams* GetDynamicConfigParams() {
-  static base::NoDestructor<chrome::mojom::DynamicParams> dynamic_params;
-  return dynamic_params.get();
-}
-
-}  // namespace
-
-bool CefRenderThreadObserver::is_incognito_process_ = false;
-
-CefRenderThreadObserver::CefRenderThreadObserver() {
-  net::NetModule::SetResourceProvider(NetResourceProvider);
-}
-
-CefRenderThreadObserver::~CefRenderThreadObserver() {}
-
-// static
-const chrome::mojom::DynamicParams&
-CefRenderThreadObserver::GetDynamicParams() {
-  return *GetDynamicConfigParams();
-}
-
-bool CefRenderThreadObserver::OnControlMessageReceived(
-    const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(CefRenderThreadObserver, message)
-    IPC_MESSAGE_HANDLER(CefProcessMsg_ModifyCrossOriginWhitelistEntry,
-                        OnModifyCrossOriginWhitelistEntry)
-    IPC_MESSAGE_HANDLER(CefProcessMsg_ClearCrossOriginWhitelist,
-                        OnClearCrossOriginWhitelist)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  return handled;
-}
-
-void CefRenderThreadObserver::RegisterMojoInterfaces(
-    blink::AssociatedInterfaceRegistry* associated_interfaces) {
-  associated_interfaces->AddInterface(base::Bind(
-      &CefRenderThreadObserver::OnRendererConfigurationAssociatedRequest,
-      base::Unretained(this)));
-}
-
-void CefRenderThreadObserver::UnregisterMojoInterfaces(
-    blink::AssociatedInterfaceRegistry* associated_interfaces) {
-  associated_interfaces->RemoveInterface(
-      chrome::mojom::RendererConfiguration::Name_);
-}
-
-void CefRenderThreadObserver::SetInitialConfiguration(
-    bool is_incognito_process,
-    mojo::PendingReceiver<chrome::mojom::ChromeOSListener> chromeos_listener) {
-  is_incognito_process_ = is_incognito_process;
-}
-
-void CefRenderThreadObserver::SetConfiguration(
-    chrome::mojom::DynamicParamsPtr params) {
-  *GetDynamicConfigParams() = std::move(*params);
-}
-
-void CefRenderThreadObserver::SetContentSettingRules(
-    const RendererContentSettingRules& rules) {}
-
-void CefRenderThreadObserver::OnRendererConfigurationAssociatedRequest(
-    mojo::PendingAssociatedReceiver<chrome::mojom::RendererConfiguration>
-        receiver) {
-  renderer_configuration_receivers_.Add(this, std::move(receiver));
-}
-
-void CefRenderThreadObserver::OnModifyCrossOriginWhitelistEntry(
-    bool add,
-    const Cef_CrossOriginWhiteListEntry_Params& params) {
-  GURL gurl = GURL(params.source_origin);
-  if (add) {
-    blink::WebSecurityPolicy::AddOriginAccessAllowListEntry(
-        gurl, blink::WebString::FromUTF8(params.target_protocol),
-        blink::WebString::FromUTF8(params.target_domain),
-        /*destination_port=*/0,
-        params.allow_target_subdomains
-            ? network::mojom::CorsDomainMatchMode::kAllowSubdomains
-            : network::mojom::CorsDomainMatchMode::kDisallowSubdomains,
-        network::mojom::CorsPortMatchMode::kAllowAnyPort,
-        network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
-  } else {
-    blink::WebSecurityPolicy::ClearOriginAccessListForOrigin(gurl);
-  }
-}
-
-void CefRenderThreadObserver::OnClearCrossOriginWhitelist() {
-  blink::WebSecurityPolicy::ClearOriginAccessList();
-}
diff --git a/src/libcef/renderer/render_thread_observer.h b/src/libcef/renderer/render_thread_observer.h
deleted file mode 100644
index 2044fc8..0000000
--- a/src/libcef/renderer/render_thread_observer.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2013 The Chromium Embedded Framework Authors.
-// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_RENDERER_RENDER_THREAD_OBSERVER_H_
-#define CEF_LIBCEF_RENDERER_RENDER_THREAD_OBSERVER_H_
-
-#include <memory>
-
-#include "base/compiler_specific.h"
-#include "chrome/common/renderer_configuration.mojom.h"
-#include "components/content_settings/core/common/content_settings.h"
-#include "content/public/renderer/render_thread_observer.h"
-#include "mojo/public/cpp/bindings/associated_binding_set.h"
-#include "mojo/public/cpp/bindings/associated_receiver_set.h"
-
-struct Cef_CrossOriginWhiteListEntry_Params;
-
-// This class sends and receives control messages in the renderer process.
-class CefRenderThreadObserver : public content::RenderThreadObserver,
-                                public chrome::mojom::RendererConfiguration {
- public:
-  CefRenderThreadObserver();
-  ~CefRenderThreadObserver() override;
-
-  static bool is_incognito_process() { return is_incognito_process_; }
-
-  // Return the dynamic parameters - those that may change while the
-  // render process is running.
-  static const chrome::mojom::DynamicParams& GetDynamicParams();
-
- private:
-  // content::RenderThreadObserver:
-  bool OnControlMessageReceived(const IPC::Message& message) override;
-  void RegisterMojoInterfaces(
-      blink::AssociatedInterfaceRegistry* associated_interfaces) override;
-  void UnregisterMojoInterfaces(
-      blink::AssociatedInterfaceRegistry* associated_interfaces) override;
-
-  // chrome::mojom::RendererConfiguration:
-  void SetInitialConfiguration(
-      bool is_incognito_process,
-      mojo::PendingReceiver<chrome::mojom::ChromeOSListener> chromeos_listener)
-      override;
-  void SetConfiguration(chrome::mojom::DynamicParamsPtr params) override;
-  void SetContentSettingRules(
-      const RendererContentSettingRules& rules) override;
-
-  void OnRendererConfigurationAssociatedRequest(
-      mojo::PendingAssociatedReceiver<chrome::mojom::RendererConfiguration>
-          receiver);
-
-  // Message handlers called on the render thread.
-  void OnModifyCrossOriginWhitelistEntry(
-      bool add,
-      const Cef_CrossOriginWhiteListEntry_Params& params);
-  void OnClearCrossOriginWhitelist();
-
-  static bool is_incognito_process_;
-
-  mojo::AssociatedReceiverSet<chrome::mojom::RendererConfiguration>
-      renderer_configuration_receivers_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefRenderThreadObserver);
-};
-
-#endif  // CEF_LIBCEF_RENDERER_RENDER_THREAD_OBSERVER_H_
diff --git a/src/libcef/renderer/render_urlrequest_impl.cc b/src/libcef/renderer/render_urlrequest_impl.cc
deleted file mode 100644
index 4c5d25b..0000000
--- a/src/libcef/renderer/render_urlrequest_impl.cc
+++ /dev/null
@@ -1,509 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework 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 "libcef/renderer/render_urlrequest_impl.h"
-
-#include <stdint.h>
-
-#include "libcef/common/request_impl.h"
-#include "libcef/common/response_impl.h"
-#include "libcef/common/task_runner_impl.h"
-#include "libcef/renderer/blink_glue.h"
-#include "libcef/renderer/content_renderer_client.h"
-
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "net/base/request_priority.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
-#include "third_party/blink/public/platform/web_security_origin.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/public/platform/web_url_error.h"
-#include "third_party/blink/public/platform/web_url_loader.h"
-#include "third_party/blink/public/platform/web_url_loader_client.h"
-#include "third_party/blink/public/platform/web_url_loader_factory.h"
-#include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/public/platform/web_url_response.h"
-
-using blink::WebString;
-using blink::WebURL;
-using blink::WebURLError;
-using blink::WebURLLoader;
-using blink::WebURLRequest;
-using blink::WebURLResponse;
-
-namespace {
-
-class CefWebURLLoaderClient : public blink::WebURLLoaderClient {
- public:
-  CefWebURLLoaderClient(CefRenderURLRequest::Context* context,
-                        int request_flags);
-  ~CefWebURLLoaderClient() override;
-
-  // blink::WebURLLoaderClient methods.
-  void DidSendData(uint64_t bytes_sent,
-                   uint64_t total_bytes_to_be_sent) override;
-  void DidReceiveResponse(const WebURLResponse& response) override;
-  void DidReceiveData(const char* data, int dataLength) override;
-  void DidFinishLoading(base::TimeTicks finish_time,
-                        int64_t total_encoded_data_length,
-                        int64_t total_encoded_body_length,
-                        int64_t total_decoded_body_length,
-                        bool should_report_corb_blocking) override;
-  void DidFail(const WebURLError&,
-               int64_t total_encoded_data_length,
-               int64_t total_encoded_body_length,
-               int64_t total_decoded_body_length) override;
-  void DidStartLoadingResponseBody(
-      mojo::ScopedDataPipeConsumerHandle response_body) override;
-  bool WillFollowRedirect(const WebURL& new_url,
-                          const net::SiteForCookies& new_site_for_cookies,
-                          const WebString& new_referrer,
-                          network::mojom::ReferrerPolicy new_referrer_policy,
-                          const WebString& new_method,
-                          const WebURLResponse& passed_redirect_response,
-                          bool& report_raw_headers) override;
-
- protected:
-  // The context_ pointer will outlive this object.
-  CefRenderURLRequest::Context* context_;
-  int request_flags_;
-};
-
-}  // namespace
-
-// CefRenderURLRequest::Context -----------------------------------------------
-
-class CefRenderURLRequest::Context
-    : public base::RefCountedThreadSafe<CefRenderURLRequest::Context> {
- public:
-  Context(CefRefPtr<CefRenderURLRequest> url_request,
-          CefRefPtr<CefFrame> frame,
-          CefRefPtr<CefRequest> request,
-          CefRefPtr<CefURLRequestClient> client)
-      : url_request_(url_request),
-        frame_(frame),
-        request_(request),
-        client_(client),
-        task_runner_(CefTaskRunnerImpl::GetCurrentTaskRunner()),
-        status_(UR_IO_PENDING),
-        error_code_(ERR_NONE),
-        body_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
-        response_was_cached_(false),
-        upload_data_size_(0),
-        got_upload_progress_complete_(false),
-        download_data_received_(0),
-        download_data_total_(-1) {
-    // Mark the request as read-only.
-    static_cast<CefRequestImpl*>(request_.get())->SetReadOnly(true);
-  }
-
-  inline bool CalledOnValidThread() {
-    return task_runner_->RunsTasksInCurrentSequence();
-  }
-
-  bool Start() {
-    DCHECK(CalledOnValidThread());
-
-    GURL url = GURL(request_->GetURL().ToString());
-    if (!url.is_valid())
-      return false;
-
-    url_client_.reset(new CefWebURLLoaderClient(this, request_->GetFlags()));
-
-    std::unique_ptr<network::ResourceRequest> resource_request =
-        std::make_unique<network::ResourceRequest>();
-    static_cast<CefRequestImpl*>(request_.get())
-        ->Get(resource_request.get(), false);
-    resource_request->priority = net::MEDIUM;
-
-    // Behave the same as a subresource load.
-    resource_request->fetch_request_context_type =
-        static_cast<int>(blink::mojom::RequestContextType::SUBRESOURCE);
-    resource_request->resource_type =
-        static_cast<int>(blink::mojom::ResourceType::kSubResource);
-
-    // Need load timing info for WebURLLoaderImpl::PopulateURLResponse to
-    // properly set cached status.
-    resource_request->enable_load_timing = true;
-
-    // Set the origin to match the request. The requirement for an origin is
-    // DCHECK'd in ResourceDispatcherHostImpl::ContinuePendingBeginRequest.
-    resource_request->request_initiator = url::Origin::Create(url);
-
-    if (request_->GetFlags() & UR_FLAG_ALLOW_STORED_CREDENTIALS) {
-      // Include SameSite cookies.
-      resource_request->attach_same_site_cookies = true;
-      resource_request->site_for_cookies =
-          net::SiteForCookies::FromOrigin(*resource_request->request_initiator);
-    }
-
-    if (resource_request->request_body) {
-      const auto& elements = *resource_request->request_body->elements();
-      if (elements.size() > 0) {
-        const auto& element = elements[0];
-        if (element.type() == network::mojom::DataElementType::kBytes) {
-          upload_data_size_ = element.length() - element.offset();
-        }
-      }
-    }
-
-    blink::WebURLLoaderFactory* factory = nullptr;
-    if (frame_) {
-      // This factory supports all requests.
-      factory = static_cast<CefFrameImpl*>(frame_.get())->GetURLLoaderFactory();
-    }
-    if (!factory) {
-      // This factory only supports unintercepted http(s) and blob requests.
-      factory = CefContentRendererClient::Get()->GetDefaultURLLoaderFactory();
-    }
-
-    loader_ = factory->CreateURLLoader(
-        blink::WebURLRequest(),
-        blink::scheduler::WebResourceLoadingTaskRunnerHandle::
-            CreateUnprioritized(task_runner_.get()));
-    loader_->LoadAsynchronously(
-        std::move(resource_request), nullptr /* extra_data */,
-        0 /* requestor_id */, false /* download_to_network_cache_only */,
-        false /* no_mime_sniffing */, url_client_.get());
-    return true;
-  }
-
-  void Cancel() {
-    DCHECK(CalledOnValidThread());
-
-    // The request may already be complete.
-    if (!loader_.get() || status_ != UR_IO_PENDING)
-      return;
-
-    status_ = UR_CANCELED;
-    error_code_ = ERR_ABORTED;
-
-    // Will result in a call to OnError().
-    loader_->Cancel();
-  }
-
-  void OnStopRedirect(const WebURL& redirect_url,
-                      const WebURLResponse& response) {
-    DCHECK(CalledOnValidThread());
-
-    response_was_cached_ = blink_glue::ResponseWasCached(response);
-    response_ = CefResponse::Create();
-    CefResponseImpl* responseImpl =
-        static_cast<CefResponseImpl*>(response_.get());
-
-    // In case of StopOnRedirect we only set these fields. Everything else is
-    // left blank. This also replicates the behaviour of the browser urlrequest
-    // fetcher.
-    responseImpl->SetStatus(response.HttpStatusCode());
-    responseImpl->SetURL(redirect_url.GetString().Utf16());
-    responseImpl->SetReadOnly(true);
-
-    status_ = UR_CANCELED;
-    error_code_ = ERR_ABORTED;
-
-    OnComplete();
-  }
-
-  void OnResponse(const WebURLResponse& response) {
-    DCHECK(CalledOnValidThread());
-
-    response_was_cached_ = blink_glue::ResponseWasCached(response);
-    response_ = CefResponse::Create();
-    CefResponseImpl* responseImpl =
-        static_cast<CefResponseImpl*>(response_.get());
-    responseImpl->Set(response);
-    responseImpl->SetReadOnly(true);
-
-    download_data_total_ = response.ExpectedContentLength();
-  }
-
-  void OnError(const WebURLError& error) {
-    DCHECK(CalledOnValidThread());
-
-    if (status_ == UR_IO_PENDING) {
-      status_ = UR_FAILED;
-      error_code_ = static_cast<cef_errorcode_t>(error.reason());
-    }
-
-    OnComplete();
-  }
-
-  void OnComplete() {
-    DCHECK(CalledOnValidThread());
-
-    if (body_handle_.is_valid()) {
-      return;
-    }
-
-    if (status_ == UR_IO_PENDING) {
-      status_ = UR_SUCCESS;
-      NotifyUploadProgressIfNecessary();
-    }
-
-    if (loader_.get())
-      loader_.reset(nullptr);
-
-    DCHECK(url_request_.get());
-    client_->OnRequestComplete(url_request_.get());
-
-    // This may result in the Context object being deleted.
-    url_request_ = nullptr;
-  }
-
-  void OnBodyReadable(MojoResult, const mojo::HandleSignalsState&) {
-    const void* buffer = nullptr;
-    uint32_t read_bytes = 0;
-    MojoResult result = body_handle_->BeginReadData(&buffer, &read_bytes,
-                                                    MOJO_READ_DATA_FLAG_NONE);
-    if (result == MOJO_RESULT_SHOULD_WAIT) {
-      body_watcher_.ArmOrNotify();
-      return;
-    }
-
-    if (result == MOJO_RESULT_FAILED_PRECONDITION) {
-      // Whole body has been read.
-      body_handle_.reset();
-      body_watcher_.Cancel();
-      OnComplete();
-      return;
-    }
-
-    if (result != MOJO_RESULT_OK) {
-      // Something went wrong.
-      body_handle_.reset();
-      body_watcher_.Cancel();
-      OnComplete();
-      return;
-    }
-
-    download_data_received_ += read_bytes;
-
-    client_->OnDownloadProgress(url_request_.get(), download_data_received_,
-                                download_data_total_);
-
-    if (!(request_->GetFlags() & UR_FLAG_NO_DOWNLOAD_DATA)) {
-      client_->OnDownloadData(url_request_.get(), buffer, read_bytes);
-    }
-
-    body_handle_->EndReadData(read_bytes);
-    body_watcher_.ArmOrNotify();
-  }
-
-  void OnStartLoadingResponseBody(
-      mojo::ScopedDataPipeConsumerHandle response_body) {
-    DCHECK(CalledOnValidThread());
-    DCHECK(response_body);
-    DCHECK(!body_handle_);
-    body_handle_ = std::move(response_body);
-
-    body_watcher_.Watch(
-        body_handle_.get(),
-        MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
-        MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
-        base::BindRepeating(&CefRenderURLRequest::Context::OnBodyReadable,
-                            base::Unretained(this)));
-    body_watcher_.ArmOrNotify();
-  }
-
-  void OnDownloadProgress(int64_t current) {
-    DCHECK(CalledOnValidThread());
-    DCHECK(url_request_.get());
-
-    NotifyUploadProgressIfNecessary();
-
-    download_data_received_ += current;
-    client_->OnDownloadProgress(url_request_.get(), download_data_received_,
-                                download_data_total_);
-  }
-
-  void OnDownloadData(const char* data, int dataLength) {
-    DCHECK(CalledOnValidThread());
-    DCHECK(url_request_.get());
-    client_->OnDownloadData(url_request_.get(), data, dataLength);
-  }
-
-  void OnUploadProgress(int64_t current, int64_t total) {
-    DCHECK(CalledOnValidThread());
-    DCHECK(url_request_.get());
-    if (current == total)
-      got_upload_progress_complete_ = true;
-    client_->OnUploadProgress(url_request_.get(), current, total);
-  }
-
-  CefRefPtr<CefRequest> request() const { return request_; }
-  CefRefPtr<CefURLRequestClient> client() const { return client_; }
-  CefURLRequest::Status status() const { return status_; }
-  CefURLRequest::ErrorCode error_code() const { return error_code_; }
-  CefRefPtr<CefResponse> response() const { return response_; }
-  bool response_was_cached() const { return response_was_cached_; }
-
- private:
-  friend class base::RefCountedThreadSafe<CefRenderURLRequest::Context>;
-
-  virtual ~Context() {}
-
-  void NotifyUploadProgressIfNecessary() {
-    if (!got_upload_progress_complete_ && upload_data_size_ > 0) {
-      // Upload notifications are sent using a timer and may not occur if the
-      // request completes too quickly. We therefore send the notification here
-      // if necessary.
-      url_client_->DidSendData(upload_data_size_, upload_data_size_);
-      got_upload_progress_complete_ = true;
-    }
-  }
-
-  // Members only accessed on the initialization thread.
-  CefRefPtr<CefRenderURLRequest> url_request_;
-  CefRefPtr<CefFrame> frame_;
-  CefRefPtr<CefRequest> request_;
-  CefRefPtr<CefURLRequestClient> client_;
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-  CefURLRequest::Status status_;
-  CefURLRequest::ErrorCode error_code_;
-  CefRefPtr<CefResponse> response_;
-  mojo::ScopedDataPipeConsumerHandle body_handle_;
-  mojo::SimpleWatcher body_watcher_;
-  bool response_was_cached_;
-  std::unique_ptr<blink::WebURLLoader> loader_;
-  std::unique_ptr<CefWebURLLoaderClient> url_client_;
-  int64_t upload_data_size_;
-  bool got_upload_progress_complete_;
-  int64_t download_data_received_;
-  int64_t download_data_total_;
-};
-
-// CefWebURLLoaderClient --------------------------------------------------
-
-namespace {
-
-CefWebURLLoaderClient::CefWebURLLoaderClient(
-    CefRenderURLRequest::Context* context,
-    int request_flags)
-    : context_(context), request_flags_(request_flags) {}
-
-CefWebURLLoaderClient::~CefWebURLLoaderClient() {}
-
-void CefWebURLLoaderClient::DidSendData(uint64_t bytes_sent,
-                                        uint64_t total_bytes_to_be_sent) {
-  if (request_flags_ & UR_FLAG_REPORT_UPLOAD_PROGRESS)
-    context_->OnUploadProgress(bytes_sent, total_bytes_to_be_sent);
-}
-
-void CefWebURLLoaderClient::DidReceiveResponse(const WebURLResponse& response) {
-  context_->OnResponse(response);
-}
-
-void CefWebURLLoaderClient::DidReceiveData(const char* data, int dataLength) {
-  context_->OnDownloadProgress(dataLength);
-
-  if (!(request_flags_ & UR_FLAG_NO_DOWNLOAD_DATA))
-    context_->OnDownloadData(data, dataLength);
-}
-
-void CefWebURLLoaderClient::DidFinishLoading(base::TimeTicks finish_time,
-                                             int64_t total_encoded_data_length,
-                                             int64_t total_encoded_body_length,
-                                             int64_t total_decoded_body_length,
-                                             bool should_report_corb_blocking) {
-  context_->OnComplete();
-}
-
-void CefWebURLLoaderClient::DidFail(const WebURLError& error,
-                                    int64_t total_encoded_data_length,
-                                    int64_t total_encoded_body_length,
-                                    int64_t total_decoded_body_length) {
-  context_->OnError(error);
-}
-
-void CefWebURLLoaderClient::DidStartLoadingResponseBody(
-    mojo::ScopedDataPipeConsumerHandle response_body) {
-  context_->OnStartLoadingResponseBody(std::move(response_body));
-}
-
-bool CefWebURLLoaderClient::WillFollowRedirect(
-    const WebURL& new_url,
-    const net::SiteForCookies& new_site_for_cookies,
-    const WebString& new_referrer,
-    network::mojom::ReferrerPolicy new_referrer_policy,
-    const WebString& new_method,
-    const WebURLResponse& passed_redirect_response,
-    bool& report_raw_headers) {
-  if (request_flags_ & UR_FLAG_STOP_ON_REDIRECT) {
-    context_->OnStopRedirect(new_url, passed_redirect_response);
-    return false;
-  }
-  return true;
-}
-
-}  // namespace
-
-// CefRenderURLRequest --------------------------------------------------------
-
-CefRenderURLRequest::CefRenderURLRequest(
-    CefRefPtr<CefFrame> frame,
-    CefRefPtr<CefRequest> request,
-    CefRefPtr<CefURLRequestClient> client) {
-  context_ = new Context(this, frame, request, client);
-}
-
-CefRenderURLRequest::~CefRenderURLRequest() {}
-
-bool CefRenderURLRequest::Start() {
-  if (!VerifyContext())
-    return false;
-  return context_->Start();
-}
-
-CefRefPtr<CefRequest> CefRenderURLRequest::GetRequest() {
-  if (!VerifyContext())
-    return nullptr;
-  return context_->request();
-}
-
-CefRefPtr<CefURLRequestClient> CefRenderURLRequest::GetClient() {
-  if (!VerifyContext())
-    return nullptr;
-  return context_->client();
-}
-
-CefURLRequest::Status CefRenderURLRequest::GetRequestStatus() {
-  if (!VerifyContext())
-    return UR_UNKNOWN;
-  return context_->status();
-}
-
-CefURLRequest::ErrorCode CefRenderURLRequest::GetRequestError() {
-  if (!VerifyContext())
-    return ERR_NONE;
-  return context_->error_code();
-}
-
-CefRefPtr<CefResponse> CefRenderURLRequest::GetResponse() {
-  if (!VerifyContext())
-    return nullptr;
-  return context_->response();
-}
-
-bool CefRenderURLRequest::ResponseWasCached() {
-  if (!VerifyContext())
-    return false;
-  return context_->response_was_cached();
-}
-
-void CefRenderURLRequest::Cancel() {
-  if (!VerifyContext())
-    return;
-  return context_->Cancel();
-}
-
-bool CefRenderURLRequest::VerifyContext() {
-  DCHECK(context_.get());
-  if (!context_->CalledOnValidThread()) {
-    NOTREACHED() << "called on invalid thread";
-    return false;
-  }
-
-  return true;
-}
diff --git a/src/libcef/renderer/render_urlrequest_impl.h b/src/libcef/renderer/render_urlrequest_impl.h
deleted file mode 100644
index a705864..0000000
--- a/src/libcef/renderer/render_urlrequest_impl.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2012 The Chromium Embedded Framework 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 CEF_LIBCEF_RENDERER_RENDER_URLREQUEST_IMPL_H_
-#define CEF_LIBCEF_RENDERER_RENDER_URLREQUEST_IMPL_H_
-
-#include "include/cef_frame.h"
-#include "include/cef_urlrequest.h"
-
-#include "base/memory/ref_counted.h"
-
-class CefRenderURLRequest : public CefURLRequest {
- public:
-  class Context;
-
-  // If |frame| is nullptr the default URLLoaderFactory will be used. That
-  // factory only supports http(s) and blob requests that cannot be
-  // intercepted in the browser process.
-  CefRenderURLRequest(CefRefPtr<CefFrame> frame,
-                      CefRefPtr<CefRequest> request,
-                      CefRefPtr<CefURLRequestClient> client);
-  ~CefRenderURLRequest() override;
-
-  bool Start();
-
-  // CefURLRequest methods.
-  CefRefPtr<CefRequest> GetRequest() override;
-  CefRefPtr<CefURLRequestClient> GetClient() override;
-  Status GetRequestStatus() override;
-  ErrorCode GetRequestError() override;
-  CefRefPtr<CefResponse> GetResponse() override;
-  bool ResponseWasCached() override;
-  void Cancel() override;
-
- private:
-  bool VerifyContext();
-
-  scoped_refptr<Context> context_;
-
-  IMPLEMENT_REFCOUNTING(CefRenderURLRequest);
-};
-
-#endif  // CEF_LIBCEF_RENDERER_RENDER_URLREQUEST_IMPL_H_
diff --git a/src/libcef/renderer/thread_util.h b/src/libcef/renderer/thread_util.h
index 7087b5e..d293cd3 100644
--- a/src/libcef/renderer/thread_util.h
+++ b/src/libcef/renderer/thread_util.h
@@ -6,7 +6,7 @@
 #define CEF_LIBCEF_RENDERER_THREAD_UTIL_H_
 #pragma once
 
-#include "libcef/renderer/content_renderer_client.h"
+#include "libcef/common/task_runner_manager.h"
 
 #include "base/location.h"
 #include "base/logging.h"
@@ -16,25 +16,26 @@
 
 #define CEF_REQUIRE_RT() DCHECK(CEF_CURRENTLY_ON_RT())
 
-#define CEF_REQUIRE_RT_RETURN(var)              \
-  if (!CEF_CURRENTLY_ON_RT()) {                 \
-    NOTREACHED() << "called on invalid thread"; \
-    return var;                                 \
+#define CEF_REQUIRE_RT_RETURN(var)               \
+  if (!CEF_CURRENTLY_ON_RT()) {                  \
+    DCHECK(false) << "called on invalid thread"; \
+    return var;                                  \
   }
 
-#define CEF_REQUIRE_RT_RETURN_VOID()            \
-  if (!CEF_CURRENTLY_ON_RT()) {                 \
-    NOTREACHED() << "called on invalid thread"; \
-    return;                                     \
+#define CEF_REQUIRE_RT_RETURN_VOID()             \
+  if (!CEF_CURRENTLY_ON_RT()) {                  \
+    DCHECK(false) << "called on invalid thread"; \
+    return;                                      \
   }
 
-#define CEF_RENDER_LOOP() \
-  (CefContentRendererClient::Get()->render_task_runner())
+#define CEF_RENDER_TASK_RUNNER() \
+  (CefTaskRunnerManager::Get()->GetRenderTaskRunner())
 
-#define CEF_POST_TASK_RT(task) CEF_RENDER_LOOP()->PostTask(FROM_HERE, task)
-#define CEF_POST_DELAYED_TASK_RT(task, delay_ms) \
-  CEF_RENDER_LOOP()->PostDelayedTask(            \
-      FROM_HERE, task, base::TimeDelta::FromMilliseconds(delay_ms))
+#define CEF_POST_TASK_RT(task) \
+  CEF_RENDER_TASK_RUNNER()->PostTask(FROM_HERE, task)
+#define CEF_POST_DELAYED_TASK_RT(task, delay_ms)             \
+  CEF_RENDER_TASK_RUNNER()->PostDelayedTask(FROM_HERE, task, \
+                                            base::Milliseconds(delay_ms))
 
 // Use this template in conjuction with RefCountedThreadSafe when you want to
 // ensure that an object is deleted on the render thread.
@@ -44,7 +45,7 @@
     if (CEF_CURRENTLY_ON_RT()) {
       delete x;
     } else {
-      if (!CEF_RENDER_LOOP()->DeleteSoon(FROM_HERE, x)) {
+      if (!CEF_RENDER_TASK_RUNNER()->DeleteSoon(FROM_HERE, x)) {
 #if defined(UNIT_TEST)
         // Only logged under unit testing because leaks at shutdown
         // are acceptable under normal circumstances.
diff --git a/src/libcef/renderer/url_loader_throttle_provider_impl.cc b/src/libcef/renderer/url_loader_throttle_provider_impl.cc
deleted file mode 100644
index 61f6f8d..0000000
--- a/src/libcef/renderer/url_loader_throttle_provider_impl.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "libcef/renderer/url_loader_throttle_provider_impl.h"
-
-#include "libcef/common/extensions/extensions_util.h"
-#include "libcef/renderer/render_thread_observer.h"
-
-#include <utility>
-
-#include "base/feature_list.h"
-#include "chrome/common/google_url_loader_throttle.h"
-#include "content/public/common/content_features.h"
-#include "content/public/renderer/render_frame.h"
-#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h"
-#include "services/network/public/cpp/features.h"
-#include "third_party/blink/public/common/loader/resource_type_util.h"
-#include "third_party/blink/public/platform/web_url.h"
-
-CefURLLoaderThrottleProviderImpl::CefURLLoaderThrottleProviderImpl(
-    content::URLLoaderThrottleProviderType type)
-    : type_(type) {
-  DETACH_FROM_THREAD(thread_checker_);
-}
-
-CefURLLoaderThrottleProviderImpl::~CefURLLoaderThrottleProviderImpl() {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-}
-
-CefURLLoaderThrottleProviderImpl::CefURLLoaderThrottleProviderImpl(
-    const CefURLLoaderThrottleProviderImpl& other)
-    : type_(other.type_) {
-  DETACH_FROM_THREAD(thread_checker_);
-}
-
-std::unique_ptr<content::URLLoaderThrottleProvider>
-CefURLLoaderThrottleProviderImpl::Clone() {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  return base::WrapUnique(new CefURLLoaderThrottleProviderImpl(*this));
-}
-
-std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
-CefURLLoaderThrottleProviderImpl::CreateThrottles(
-    int render_frame_id,
-    const blink::WebURLRequest& request) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
-  std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles;
-
-  const network::mojom::RequestDestination request_destination =
-      request.GetRequestDestination();
-
-  // Some throttles have already been added in the browser for frame resources.
-  // Don't add them for frame requests.
-  bool is_frame_resource =
-      blink::IsRequestDestinationFrame(request_destination);
-
-  DCHECK(!is_frame_resource ||
-         type_ == content::URLLoaderThrottleProviderType::kFrame);
-
-  if (extensions::ExtensionsEnabled() &&
-      type_ == content::URLLoaderThrottleProviderType::kFrame &&
-      request_destination == network::mojom::RequestDestination::kObject) {
-    content::RenderFrame* render_frame =
-        content::RenderFrame::FromRoutingID(render_frame_id);
-    auto mime_handlers =
-        extensions::MimeHandlerViewContainer::FromRenderFrame(render_frame);
-    GURL gurl(request.Url());
-    for (auto* handler : mime_handlers) {
-      auto throttle = handler->MaybeCreatePluginThrottle(gurl);
-      if (throttle) {
-        throttles.push_back(std::move(throttle));
-        break;
-      }
-    }
-  }
-
-  throttles.push_back(std::make_unique<GoogleURLLoaderThrottle>(
-      CefRenderThreadObserver::GetDynamicParams()));
-
-  return throttles;
-}
-
-void CefURLLoaderThrottleProviderImpl::SetOnline(bool is_online) {}
diff --git a/src/libcef/renderer/url_loader_throttle_provider_impl.h b/src/libcef/renderer/url_loader_throttle_provider_impl.h
deleted file mode 100644
index 1fe2ca0..0000000
--- a/src/libcef/renderer/url_loader_throttle_provider_impl.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CEF_LIBCEF_RENDERER_URL_LOADER_THROTTLE_PROVIDER_IMPL_H_
-#define CEF_LIBCEF_RENDERER_URL_LOADER_THROTTLE_PROVIDER_IMPL_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/threading/thread_checker.h"
-#include "content/public/renderer/url_loader_throttle_provider.h"
-
-// Instances must be constructed on the render thread, and then used and
-// destructed on a single thread, which can be different from the render thread.
-class CefURLLoaderThrottleProviderImpl
-    : public content::URLLoaderThrottleProvider {
- public:
-  explicit CefURLLoaderThrottleProviderImpl(
-      content::URLLoaderThrottleProviderType type);
-
-  ~CefURLLoaderThrottleProviderImpl() override;
-
-  // content::URLLoaderThrottleProvider implementation.
-  std::unique_ptr<content::URLLoaderThrottleProvider> Clone() override;
-  std::vector<std::unique_ptr<blink::URLLoaderThrottle>> CreateThrottles(
-      int render_frame_id,
-      const blink::WebURLRequest& request) override;
-  void SetOnline(bool is_online) override;
-
- private:
-  // This copy constructor works in conjunction with Clone(), not intended for
-  // general use.
-  CefURLLoaderThrottleProviderImpl(
-      const CefURLLoaderThrottleProviderImpl& other);
-
-  content::URLLoaderThrottleProviderType type_;
-
-  THREAD_CHECKER(thread_checker_);
-
-  DISALLOW_ASSIGN(CefURLLoaderThrottleProviderImpl);
-};
-
-#endif  // CEF_LIBCEF_RENDERER_URL_LOADER_THROTTLE_PROVIDER_IMPL_H_
diff --git a/src/libcef/renderer/v8_impl.cc b/src/libcef/renderer/v8_impl.cc
index 63070b7..f610b73 100644
--- a/src/libcef/renderer/v8_impl.cc
+++ b/src/libcef/renderer/v8_impl.cc
@@ -10,10 +10,10 @@
 #include <string>
 
 #include "base/command_line.h"
-#include "base/compiler_specific.h"
+#include "build/build_config.h"
 
 // Enable deprecation warnings for MSVC and Clang. See http://crbug.com/585142.
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 #if defined(__clang__)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic error "-Wdeprecated-declarations"
@@ -25,8 +25,8 @@
 
 #include "libcef/renderer/v8_impl.h"
 
+#include "libcef/common/app_manager.h"
 #include "libcef/common/cef_switches.h"
-#include "libcef/common/content_client.h"
 #include "libcef/common/task_runner_impl.h"
 #include "libcef/common/tracker.h"
 #include "libcef/renderer/blink_glue.h"
@@ -34,13 +34,15 @@
 #include "libcef/renderer/render_frame_util.h"
 #include "libcef/renderer/thread_util.h"
 
-#include "base/bind.h"
+#include "base/auto_reset.h"
+#include "base/functional/bind.h"
 #include "base/lazy_instance.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/threading/thread_local.h"
+#include "third_party/abseil-cpp/absl/base/attributes.h"
 #include "third_party/blink/public/web/blink.h"
 #include "third_party/blink/public/web/web_frame.h"
 #include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_script_controller.h"
 #include "url/gurl.h"
 
 namespace {
@@ -82,20 +84,34 @@
       .ToLocal(result);
 }
 
+// Chromium uses the default Isolate for the main render process thread and a
+// new Isolate for each WebWorker thread. Continue this pattern by tracking
+// Isolate information on a per-thread basis. This implementation will need to
+// be re-worked (perhaps using a map keyed on v8::Isolate::GetCurrent()) if
+// in the future Chromium begins using the same Isolate across multiple threads.
+class CefV8IsolateManager;
+ABSL_CONST_INIT thread_local CefV8IsolateManager* g_isolate_manager = nullptr;
+
 // Manages memory and state information associated with a single Isolate.
 class CefV8IsolateManager {
  public:
   CefV8IsolateManager()
-      : isolate_(v8::Isolate::GetCurrent()),
-        task_runner_(CefContentRendererClient::Get()->GetCurrentTaskRunner()),
+      : resetter_(&g_isolate_manager, this),
+        isolate_(v8::Isolate::GetCurrent()),
+        task_runner_(CEF_RENDER_TASK_RUNNER()),
         message_listener_registered_(false),
         worker_id_(0) {
     DCHECK(isolate_);
     DCHECK(task_runner_.get());
   }
-  ~CefV8IsolateManager() {
+  ~CefV8IsolateManager() = default;
+
+  static CefV8IsolateManager* Get() { return g_isolate_manager; }
+
+  void Destroy() {
     DCHECK_EQ(isolate_, v8::Isolate::GetCurrent());
     DCHECK(context_map_.empty());
+    delete this;
   }
 
   scoped_refptr<CefV8ContextState> GetContextState(
@@ -104,16 +120,18 @@
     DCHECK(context.IsEmpty() || isolate_ == context->GetIsolate());
 
     if (context.IsEmpty()) {
-      if (isolate_->InContext())
+      if (isolate_->InContext()) {
         context = isolate_->GetCurrentContext();
-      else
+      } else {
         return scoped_refptr<CefV8ContextState>();
+      }
     }
 
     int hash = context->Global()->GetIdentityHash();
     ContextMap::const_iterator it = context_map_.find(hash);
-    if (it != context_map_.end())
+    if (it != context_map_.end()) {
       return it->second;
+    }
 
     scoped_refptr<CefV8ContextState> state = new CefV8ContextState();
     context_map_.insert(std::make_pair(hash, state));
@@ -144,8 +162,9 @@
   }
 
   void SetUncaughtExceptionStackSize(int stack_size) {
-    if (stack_size <= 0)
+    if (stack_size <= 0) {
       return;
+    }
 
     if (!message_listener_registered_) {
       isolate_->AddMessageListener(&MessageListenerCallbackImpl);
@@ -171,10 +190,12 @@
   const GURL& worker_url() const { return worker_url_; }
 
  private:
+  const base::AutoReset<CefV8IsolateManager*> resetter_;
+
   v8::Isolate* isolate_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 
-  typedef std::map<int, scoped_refptr<CefV8ContextState>> ContextMap;
+  using ContextMap = std::map<int, scoped_refptr<CefV8ContextState>>;
   ContextMap context_map_;
 
   // Used for globally tracked objects that are not associated with a particular
@@ -189,43 +210,6 @@
   GURL worker_url_;
 };
 
-// Chromium uses the default Isolate for the main render process thread and a
-// new Isolate for each WebWorker thread. Continue this pattern by tracking
-// Isolate information on a per-thread basis. This implementation will need to
-// be re-worked (perhaps using a map keyed on v8::Isolate::GetCurrent()) if
-// in the future Chromium begins using the same Isolate across multiple threads.
-class CefV8StateManager {
- public:
-  CefV8StateManager() {}
-
-  void CreateIsolateManager() {
-    DCHECK(!current_tls_.Get());
-    current_tls_.Set(new CefV8IsolateManager());
-  }
-
-  void DestroyIsolateManager() {
-    DCHECK(current_tls_.Get());
-    delete current_tls_.Get();
-    current_tls_.Set(nullptr);
-  }
-
-  CefV8IsolateManager* GetIsolateManager() {
-    CefV8IsolateManager* manager = current_tls_.Get();
-    DCHECK(manager);
-    return manager;
-  }
-
- private:
-  base::ThreadLocalPointer<CefV8IsolateManager> current_tls_;
-};
-
-base::LazyInstance<CefV8StateManager>::Leaky g_v8_state =
-    LAZY_INSTANCE_INITIALIZER;
-
-CefV8IsolateManager* GetIsolateManager() {
-  return g_v8_state.Pointer()->GetIsolateManager();
-}
-
 class V8TrackObject : public CefTrackNode {
  public:
   explicit V8TrackObject(v8::Isolate* isolate)
@@ -244,13 +228,14 @@
   int AdjustExternallyAllocatedMemory(int change_in_bytes) {
     int new_value = external_memory_ + change_in_bytes;
     if (new_value < 0) {
-      NOTREACHED() << "External memory usage cannot be less than 0 bytes";
+      DCHECK(false) << "External memory usage cannot be less than 0 bytes";
       change_in_bytes = -(external_memory_);
       new_value = 0;
     }
 
-    if (change_in_bytes != 0)
+    if (change_in_bytes != 0) {
       isolate_->AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
+    }
     external_memory_ = new_value;
 
     return new_value;
@@ -290,8 +275,10 @@
   static V8TrackObject* Unwrap(v8::Local<v8::Context> context,
                                v8::Local<v8::Object> object) {
     v8::Local<v8::Value> value;
-    if (GetPrivate(context, object, kCefTrackObject, &value))
+    if (GetPrivate(context, object, kCefTrackObject, &value) &&
+        value->IsExternal()) {
       return static_cast<V8TrackObject*>(v8::External::Cast(*value)->Value());
+    }
 
     return nullptr;
   }
@@ -318,20 +305,14 @@
  public:
   explicit V8TrackArrayBuffer(
       v8::Isolate* isolate,
-      void* buffer,
       CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback)
-      : isolate_(isolate),
-        buffer_(buffer),
-        release_callback_(release_callback) {
+      : isolate_(isolate), release_callback_(release_callback) {
     DCHECK(isolate_);
     isolate_->AdjustAmountOfExternalAllocatedMemory(
         static_cast<int>(sizeof(V8TrackArrayBuffer)));
   }
 
   ~V8TrackArrayBuffer() {
-    if (buffer_ != nullptr) {
-      release_callback_->ReleaseBuffer(buffer_);
-    }
     isolate_->AdjustAmountOfExternalAllocatedMemory(
         -static_cast<int>(sizeof(V8TrackArrayBuffer)));
   }
@@ -340,8 +321,6 @@
     return release_callback_;
   }
 
-  void Detach() { buffer_ = nullptr; }
-
   // Attach this track object to the specified V8 object.
   void AttachTo(v8::Local<v8::Context> context,
                 v8::Local<v8::ArrayBuffer> arrayBuffer) {
@@ -353,16 +332,17 @@
   static V8TrackArrayBuffer* Unwrap(v8::Local<v8::Context> context,
                                     v8::Local<v8::Object> object) {
     v8::Local<v8::Value> value;
-    if (GetPrivate(context, object, kCefTrackObject, &value))
+    if (GetPrivate(context, object, kCefTrackObject, &value) &&
+        value->IsExternal()) {
       return static_cast<V8TrackArrayBuffer*>(
           v8::External::Cast(*value)->Value());
+    }
 
     return nullptr;
   }
 
  private:
   v8::Isolate* isolate_;
-  void* buffer_;
   CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback_;
 };
 
@@ -386,8 +366,9 @@
   CefString function_name() const { return function_name_; }
 
   CefV8Handler* handler() const {
-    if (!handler_)
+    if (!handler_) {
       return nullptr;
+    }
     return handler_.get();
   }
 
@@ -463,7 +444,7 @@
 }
 
 #if defined(CEF_STRING_TYPE_UTF16)
-void v8impl_string_dtor(char16* str) {
+void v8impl_string_dtor(char16_t* str) {
   delete[] str;
 }
 #elif defined(CEF_STRING_TYPE_UTF8)
@@ -476,14 +457,16 @@
 void GetCefString(v8::Isolate* isolate,
                   v8::Local<v8::String> str,
                   CefString& out) {
-  if (str.IsEmpty())
+  if (str.IsEmpty()) {
     return;
+  }
 
 #if defined(CEF_STRING_TYPE_WIDE)
   // Allocate enough space for a worst-case conversion.
   int len = str->Utf8Length();
-  if (len == 0)
+  if (len == 0) {
     return;
+  }
   char* buf = new char[len + 1];
   str->WriteUtf8(isolate, buf, len + 1);
 
@@ -495,15 +478,17 @@
 #else  // !defined(CEF_STRING_TYPE_WIDE)
 #if defined(CEF_STRING_TYPE_UTF16)
   int len = str->Length();
-  if (len == 0)
+  if (len == 0) {
     return;
-  char16* buf = new char16[len + 1];
+  }
+  char16_t* buf = new char16_t[len + 1];
   str->Write(isolate, reinterpret_cast<uint16_t*>(buf), 0, len + 1);
 #else
   // Allocate enough space for a worst-case conversion.
   int len = str->Utf8Length();
-  if (len == 0)
+  if (len == 0) {
     return;
+  }
   char* buf = new char[len + 1];
   str->WriteUtf8(isolate, buf, len + 1);
 #endif
@@ -529,8 +514,9 @@
     return;
   }
   CefV8ValueList params;
-  for (int i = 0; i < info.Length(); i++)
+  for (int i = 0; i < info.Length(); i++) {
     params.push_back(new CefV8ValueImpl(isolate, context, info[i]));
+  }
 
   CefRefPtr<CefV8Value> object =
       new CefV8ValueImpl(isolate, context, info.This());
@@ -567,8 +553,9 @@
   CefRefPtr<CefV8Accessor> accessorPtr;
 
   V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
-  if (tracker)
+  if (tracker) {
     accessorPtr = tracker->GetAccessor();
+  }
 
   if (accessorPtr.get()) {
     CefRefPtr<CefV8Value> retval;
@@ -605,8 +592,9 @@
   CefRefPtr<CefV8Accessor> accessorPtr;
 
   V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
-  if (tracker)
+  if (tracker) {
     accessorPtr = tracker->GetAccessor();
+  }
 
   if (accessorPtr.get()) {
     CefRefPtr<CefV8Value> object = new CefV8ValueImpl(isolate, context, obj);
@@ -648,10 +636,12 @@
   CefRefPtr<CefV8Interceptor> interceptorPtr;
 
   V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
-  if (tracker)
+  if (tracker) {
     interceptorPtr = tracker->GetInterceptor();
-  if (!interceptorPtr.get())
+  }
+  if (!interceptorPtr.get()) {
     return;
+  }
 
   CefRefPtr<CefV8Value> object = new CefV8ValueImpl(isolate, context, obj);
   CefRefPtr<CefV8Value> retval;
@@ -680,11 +670,13 @@
   CefRefPtr<CefV8Interceptor> interceptorPtr;
 
   V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
-  if (tracker)
+  if (tracker) {
     interceptorPtr = tracker->GetInterceptor();
+  }
 
-  if (!interceptorPtr.get())
+  if (!interceptorPtr.get()) {
     return;
+  }
   CefRefPtr<CefV8Value> object = new CefV8ValueImpl(isolate, context, obj);
   CefRefPtr<CefV8Value> cefValue = new CefV8ValueImpl(isolate, context, value);
   CefString exception;
@@ -708,8 +700,9 @@
   v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
       v8::Isolate* isolate,
       v8::Handle<v8::String> name) override {
-    if (!handler_)
+    if (!handler_) {
       return v8::Local<v8::FunctionTemplate>();
+    }
 
     CefString func_name;
     GetCefString(isolate, name, func_name);
@@ -734,14 +727,16 @@
         end_position_(0),
         start_column_(0),
         end_column_(0) {
-    if (message.IsEmpty())
+    if (message.IsEmpty()) {
       return;
+    }
 
     v8::Isolate* isolate = context->GetIsolate();
     GetCefString(isolate, message->Get(), message_);
     v8::MaybeLocal<v8::String> source_line = message->GetSourceLine(context);
-    if (!source_line.IsEmpty())
+    if (!source_line.IsEmpty()) {
       GetCefString(isolate, source_line.ToLocalChecked(), source_line_);
+    }
 
     if (!message->GetScriptResourceName().IsEmpty()) {
       GetCefString(
@@ -751,8 +746,9 @@
     }
 
     v8::Maybe<int> line_number = message->GetLineNumber(context);
-    if (!line_number.IsNothing())
+    if (!line_number.IsNothing()) {
       line_number_ = line_number.ToChecked();
+    }
     start_position_ = message->GetStartPosition();
     end_position_ = message->GetEndPosition();
     start_column_ = message->GetStartColumn(context).FromJust();
@@ -783,16 +779,18 @@
 
 void MessageListenerCallbackImpl(v8::Handle<v8::Message> message,
                                  v8::Handle<v8::Value> data) {
-  CefRefPtr<CefApp> application = CefContentClient::Get()->application();
-  if (!application.get())
+  CefRefPtr<CefApp> application = CefAppManager::Get()->GetApplication();
+  if (!application.get()) {
     return;
+  }
 
   CefRefPtr<CefRenderProcessHandler> handler =
       application->GetRenderProcessHandler();
-  if (!handler.get())
+  if (!handler.get()) {
     return;
+  }
 
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
   v8::Local<v8::StackTrace> v8Stack = message->GetStackTrace();
   CefRefPtr<CefV8StackTrace> stackTrace =
@@ -813,23 +811,24 @@
 // Global functions.
 
 void CefV8IsolateCreated() {
-  g_v8_state.Pointer()->CreateIsolateManager();
+  new CefV8IsolateManager();
 }
 
 void CefV8IsolateDestroyed() {
-  g_v8_state.Pointer()->DestroyIsolateManager();
+  auto* isolate_manager = CefV8IsolateManager::Get();
+  isolate_manager->Destroy();
 }
 
 void CefV8ReleaseContext(v8::Local<v8::Context> context) {
-  GetIsolateManager()->ReleaseContext(context);
+  CefV8IsolateManager::Get()->ReleaseContext(context);
 }
 
 void CefV8SetUncaughtExceptionStackSize(int stack_size) {
-  GetIsolateManager()->SetUncaughtExceptionStackSize(stack_size);
+  CefV8IsolateManager::Get()->SetUncaughtExceptionStackSize(stack_size);
 }
 
 void CefV8SetWorkerAttributes(int worker_id, const GURL& worker_url) {
-  GetIsolateManager()->SetWorkerAttributes(worker_id, worker_url);
+  CefV8IsolateManager::Get()->SetWorkerAttributes(worker_id, worker_url);
 }
 
 bool CefRegisterExtension(const CefString& extension_name,
@@ -838,7 +837,7 @@
   // Verify that this method was called on the correct thread.
   CEF_REQUIRE_RT_RETURN(false);
 
-  CefV8IsolateManager* isolate_manager = GetIsolateManager();
+  auto* isolate_manager = CefV8IsolateManager::Get();
 
   V8TrackString* name = new V8TrackString(extension_name);
   isolate_manager->AddGlobalTrackObject(name);
@@ -855,33 +854,33 @@
   std::unique_ptr<v8::Extension> wrapper(new ExtensionWrapper(
       name->GetString(), code->GetString(), handler.get()));
 
-  content::RenderThread::Get()->RegisterExtension(std::move(wrapper));
+  blink::WebScriptController::RegisterExtension(std::move(wrapper));
   return true;
 }
 
 // Helper macros
 
-#define CEF_V8_HAS_ISOLATE() (!!GetIsolateManager())
-#define CEF_V8_REQUIRE_ISOLATE_RETURN(var)     \
-  if (!CEF_V8_HAS_ISOLATE()) {                 \
-    NOTREACHED() << "V8 isolate is not valid"; \
-    return var;                                \
+#define CEF_V8_HAS_ISOLATE() (!!CefV8IsolateManager::Get())
+#define CEF_V8_REQUIRE_ISOLATE_RETURN(var)      \
+  if (!CEF_V8_HAS_ISOLATE()) {                  \
+    DCHECK(false) << "V8 isolate is not valid"; \
+    return var;                                 \
   }
 
 #define CEF_V8_CURRENTLY_ON_MLT() \
   (!handle_.get() || handle_->BelongsToCurrentThread())
-#define CEF_V8_REQUIRE_MLT_RETURN(var)            \
-  CEF_V8_REQUIRE_ISOLATE_RETURN(var);             \
-  if (!CEF_V8_CURRENTLY_ON_MLT()) {               \
-    NOTREACHED() << "called on incorrect thread"; \
-    return var;                                   \
+#define CEF_V8_REQUIRE_MLT_RETURN(var)             \
+  CEF_V8_REQUIRE_ISOLATE_RETURN(var);              \
+  if (!CEF_V8_CURRENTLY_ON_MLT()) {                \
+    DCHECK(false) << "called on incorrect thread"; \
+    return var;                                    \
   }
 
 #define CEF_V8_HANDLE_IS_VALID() (handle_.get() && handle_->IsValid())
 #define CEF_V8_REQUIRE_VALID_HANDLE_RETURN(ret) \
   CEF_V8_REQUIRE_MLT_RETURN(ret);               \
   if (!CEF_V8_HANDLE_IS_VALID()) {              \
-    NOTREACHED() << "V8 handle is not valid";   \
+    DCHECK(false) << "V8 handle is not valid";  \
     return ret;                                 \
   }
 
@@ -889,11 +888,11 @@
   (CEF_V8_HAS_ISOLATE() && CEF_V8_CURRENTLY_ON_MLT() && \
    CEF_V8_HANDLE_IS_VALID())
 
-#define CEF_V8_REQUIRE_OBJECT_RETURN(ret)        \
-  CEF_V8_REQUIRE_VALID_HANDLE_RETURN(ret);       \
-  if (type_ != TYPE_OBJECT) {                    \
-    NOTREACHED() << "V8 value is not an object"; \
-    return ret;                                  \
+#define CEF_V8_REQUIRE_OBJECT_RETURN(ret)         \
+  CEF_V8_REQUIRE_VALID_HANDLE_RETURN(ret);        \
+  if (type_ != TYPE_OBJECT) {                     \
+    DCHECK(false) << "V8 value is not an object"; \
+    return ret;                                   \
   }
 
 // CefV8HandleBase
@@ -911,7 +910,7 @@
     : isolate_(isolate) {
   DCHECK(isolate_);
 
-  CefV8IsolateManager* manager = GetIsolateManager();
+  CefV8IsolateManager* manager = CefV8IsolateManager::Get();
   DCHECK(manager);
   DCHECK_EQ(isolate_, manager->isolate());
 
@@ -925,7 +924,7 @@
 CefRefPtr<CefV8Context> CefV8Context::GetCurrentContext() {
   CefRefPtr<CefV8Context> context;
   CEF_V8_REQUIRE_ISOLATE_RETURN(context);
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   if (isolate->InContext()) {
     v8::HandleScope handle_scope(isolate);
     context = new CefV8ContextImpl(isolate, isolate->GetCurrentContext());
@@ -937,7 +936,7 @@
 CefRefPtr<CefV8Context> CefV8Context::GetEnteredContext() {
   CefRefPtr<CefV8Context> context;
   CEF_V8_REQUIRE_ISOLATE_RETURN(context);
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   if (isolate->InContext()) {
     v8::HandleScope handle_scope(isolate);
     context =
@@ -949,7 +948,7 @@
 // static
 bool CefV8Context::InContext() {
   CEF_V8_REQUIRE_ISOLATE_RETURN(false);
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   return isolate->InContext();
 }
 
@@ -957,7 +956,8 @@
 
 CefV8ContextImpl::CefV8ContextImpl(v8::Isolate* isolate,
                                    v8::Local<v8::Context> context)
-    : handle_(new Handle(isolate, context, context)), enter_count_(0) {}
+    : handle_(new Handle(isolate, context, context)),
+      microtask_queue_(blink_glue::GetMicrotaskQueue(context)) {}
 
 CefV8ContextImpl::~CefV8ContextImpl() {
   DLOG_ASSERT(0 == enter_count_);
@@ -976,8 +976,9 @@
   CEF_V8_REQUIRE_VALID_HANDLE_RETURN(browser);
 
   blink::WebLocalFrame* webframe = GetWebFrame();
-  if (webframe)
+  if (webframe) {
     browser = CefBrowserImpl::GetBrowserForMainFrame(webframe->Top());
+  }
 
   return browser;
 }
@@ -1001,8 +1002,9 @@
 CefRefPtr<CefV8Value> CefV8ContextImpl::GetGlobal() {
   CEF_V8_REQUIRE_VALID_HANDLE_RETURN(nullptr);
 
-  if (blink_glue::IsScriptForbidden())
+  if (blink_glue::IsScriptForbidden()) {
     return nullptr;
+  }
 
   v8::Isolate* isolate = handle_->isolate();
   v8::HandleScope handle_scope(isolate);
@@ -1014,16 +1016,17 @@
 bool CefV8ContextImpl::Enter() {
   CEF_V8_REQUIRE_VALID_HANDLE_RETURN(false);
 
-  if (blink_glue::IsScriptForbidden())
+  if (blink_glue::IsScriptForbidden()) {
     return false;
+  }
 
   v8::Isolate* isolate = handle_->isolate();
   v8::HandleScope handle_scope(isolate);
 
   if (!microtasks_scope_) {
     // Increment the MicrotasksScope recursion level.
-    microtasks_scope_.reset(
-        new v8::MicrotasksScope(isolate, v8::MicrotasksScope::kRunMicrotasks));
+    microtasks_scope_.reset(new v8::MicrotasksScope(
+        isolate, microtask_queue_, v8::MicrotasksScope::kRunMicrotasks));
   }
 
   ++enter_count_;
@@ -1035,8 +1038,9 @@
 bool CefV8ContextImpl::Exit() {
   CEF_V8_REQUIRE_VALID_HANDLE_RETURN(false);
 
-  if (blink_glue::IsScriptForbidden())
+  if (blink_glue::IsScriptForbidden()) {
     return false;
+  }
 
   if (enter_count_ <= 0) {
     LOG(ERROR) << "Call to CefV8Context::Exit() without matching call to "
@@ -1060,8 +1064,9 @@
   CEF_V8_REQUIRE_VALID_HANDLE_RETURN(false);
 
   CefV8ContextImpl* impl = static_cast<CefV8ContextImpl*>(that.get());
-  if (!impl || !impl->IsValid())
+  if (!impl || !impl->IsValid()) {
     return false;
+  }
 
   return (handle_->GetPersistentV8Handle() ==
           impl->handle_->GetPersistentV8Handle());
@@ -1077,11 +1082,12 @@
 
   CEF_V8_REQUIRE_VALID_HANDLE_RETURN(false);
 
-  if (blink_glue::IsScriptForbidden())
+  if (blink_glue::IsScriptForbidden()) {
     return false;
+  }
 
   if (code.empty()) {
-    NOTREACHED() << "invalid input parameter";
+    DCHECK(false) << "invalid input parameter";
     return false;
   }
 
@@ -1098,19 +1104,18 @@
   v8::TryCatch try_catch(isolate);
   try_catch.SetVerbose(true);
 
-  v8::MaybeLocal<v8::Value> func_rv = blink_glue::ExecuteV8ScriptAndReturnValue(
-      source, source_url, start_line, context, isolate, try_catch,
-      blink::SanitizeScriptErrors::kSanitize);
+  v8::Local<v8::Value> func_rv = blink_glue::ExecuteV8ScriptAndReturnValue(
+      source, source_url, start_line, context, try_catch);
 
   if (try_catch.HasCaught()) {
     exception = new CefV8ExceptionImpl(context, try_catch.Message());
     return false;
   } else if (!func_rv.IsEmpty()) {
-    retval = new CefV8ValueImpl(isolate, context, func_rv.ToLocalChecked());
+    retval = new CefV8ValueImpl(isolate, context, func_rv);
     return true;
   }
 
-  NOTREACHED();
+  DCHECK(false);
   return false;
 }
 
@@ -1121,8 +1126,9 @@
 blink::WebLocalFrame* CefV8ContextImpl::GetWebFrame() {
   CEF_REQUIRE_RT();
 
-  if (blink_glue::IsScriptForbidden())
+  if (blink_glue::IsScriptForbidden()) {
     return nullptr;
+  }
 
   v8::HandleScope handle_scope(handle_->isolate());
   v8::Local<v8::Context> context = GetV8Context();
@@ -1150,10 +1156,11 @@
       if (context_state_.get()) {
         // If the associated context is still valid then delete |tracker_|.
         // Otherwise, |tracker_| will already have been deleted.
-        if (context_state_->IsValid())
+        if (context_state_->IsValid()) {
           context_state_->DeleteTrackObject(tracker_);
+        }
       } else {
-        GetIsolateManager()->DeleteGlobalTrackObject(tracker_);
+        CefV8IsolateManager::Get()->DeleteGlobalTrackObject(tracker_);
       }
     } else {
       delete tracker_;
@@ -1172,8 +1179,9 @@
 CefV8ValueImpl::Handle::handleType CefV8ValueImpl::Handle::GetNewV8Handle(
     bool should_persist) {
   DCHECK(IsValid());
-  if (should_persist && !should_persist_)
+  if (should_persist && !should_persist_) {
     should_persist_ = true;
+  }
   return handleType::New(isolate(), handle_);
 }
 
@@ -1186,7 +1194,7 @@
   if (!BelongsToCurrentThread()) {
     task_runner()->PostTask(
         FROM_HERE,
-        base::Bind(&CefV8ValueImpl::Handle::SetWeakIfNecessary, this));
+        base::BindOnce(&CefV8ValueImpl::Handle::SetWeakIfNecessary, this));
     return;
   }
 
@@ -1208,7 +1216,7 @@
         // |tracker_| will be deleted when:
         // A. The process shuts down, or
         // B. SecondWeakCallback is called for the weak handle.
-        GetIsolateManager()->AddGlobalTrackObject(tracker_);
+        CefV8IsolateManager::Get()->AddGlobalTrackObject(tracker_);
       }
     }
 
@@ -1241,7 +1249,7 @@
 // static
 CefRefPtr<CefV8Value> CefV8Value::CreateUndefined() {
   CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
   impl->InitUndefined();
   return impl.get();
@@ -1250,7 +1258,7 @@
 // static
 CefRefPtr<CefV8Value> CefV8Value::CreateNull() {
   CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
   impl->InitNull();
   return impl.get();
@@ -1259,25 +1267,25 @@
 // static
 CefRefPtr<CefV8Value> CefV8Value::CreateBool(bool value) {
   CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
   impl->InitBool(value);
   return impl.get();
 }
 
 // static
-CefRefPtr<CefV8Value> CefV8Value::CreateInt(int32 value) {
+CefRefPtr<CefV8Value> CefV8Value::CreateInt(int32_t value) {
   CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
   impl->InitInt(value);
   return impl.get();
 }
 
 // static
-CefRefPtr<CefV8Value> CefV8Value::CreateUInt(uint32 value) {
+CefRefPtr<CefV8Value> CefV8Value::CreateUInt(uint32_t value) {
   CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
   impl->InitUInt(value);
   return impl.get();
@@ -1286,16 +1294,16 @@
 // static
 CefRefPtr<CefV8Value> CefV8Value::CreateDouble(double value) {
   CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
   impl->InitDouble(value);
   return impl.get();
 }
 
 // static
-CefRefPtr<CefV8Value> CefV8Value::CreateDate(const CefTime& value) {
+CefRefPtr<CefV8Value> CefV8Value::CreateDate(CefBaseTime value) {
   CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
   impl->InitDate(value);
   return impl.get();
@@ -1304,7 +1312,7 @@
 // static
 CefRefPtr<CefV8Value> CefV8Value::CreateString(const CefString& value) {
   CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
   CefString str(value);
   impl->InitString(str);
@@ -1317,12 +1325,12 @@
     CefRefPtr<CefV8Interceptor> interceptor) {
   CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
 
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   v8::HandleScope handle_scope(isolate);
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return nullptr;
   }
 
@@ -1342,7 +1350,7 @@
 
     v8::MaybeLocal<v8::Object> maybe_object = tmpl->NewInstance(context);
     if (!maybe_object.ToLocal<v8::Object>(&obj)) {
-      NOTREACHED() << "Failed to create V8 Object with interceptor";
+      DCHECK(false) << "Failed to create V8 Object with interceptor";
       return nullptr;
     }
   } else {
@@ -1368,12 +1376,12 @@
 CefRefPtr<CefV8Value> CefV8Value::CreateArray(int length) {
   CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
 
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   v8::HandleScope handle_scope(isolate);
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return nullptr;
   }
 
@@ -1399,19 +1407,36 @@
     CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback) {
   CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
 
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   v8::HandleScope handle_scope(isolate);
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return nullptr;
   }
 
   // Create a tracker object that will cause the user data reference to be
   // released when the V8 object is destroyed.
   V8TrackArrayBuffer* tracker =
-      new V8TrackArrayBuffer(isolate, buffer, release_callback);
-  v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, buffer, length);
+      new V8TrackArrayBuffer(isolate, release_callback);
+
+  if (release_callback) {
+    release_callback->AddRef();
+  }
+
+  auto deleter = [](void* data, size_t length, void* deleter_data) {
+    auto* release_callback =
+        reinterpret_cast<CefV8ArrayBufferReleaseCallback*>(deleter_data);
+    if (release_callback) {
+      release_callback->ReleaseBuffer(data);
+      release_callback->Release();
+    }
+  };
+
+  std::unique_ptr<v8::BackingStore> backing = v8::ArrayBuffer::NewBackingStore(
+      buffer, length, deleter, release_callback.get());
+  v8::Local<v8::ArrayBuffer> ab =
+      v8::ArrayBuffer::New(isolate, std::move(backing));
 
   // Attach the tracker object.
   tracker->AttachTo(context, ab);
@@ -1428,16 +1453,16 @@
   CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
 
   if (!handler.get()) {
-    NOTREACHED() << "invalid parameter";
+    DCHECK(false) << "invalid parameter";
     return nullptr;
   }
 
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   v8::HandleScope handle_scope(isolate);
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return nullptr;
   }
 
@@ -1452,7 +1477,7 @@
   v8::MaybeLocal<v8::Function> maybe_func = tmpl->GetFunction(context);
   v8::Local<v8::Function> func;
   if (!maybe_func.ToLocal(&func)) {
-    NOTREACHED() << "failed to create V8 function";
+    DCHECK(false) << "failed to create V8 function";
     return nullptr;
   }
 
@@ -1473,6 +1498,33 @@
   return impl.get();
 }
 
+// static
+CefRefPtr<CefV8Value> CefV8Value::CreatePromise() {
+  CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
+  v8::HandleScope handle_scope(isolate);
+
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  if (context.IsEmpty()) {
+    DCHECK(false) << "not currently in a V8 context";
+    return nullptr;
+  }
+
+  v8::Local<v8::Promise::Resolver> promise_resolver =
+      v8::Promise::Resolver::New(context).ToLocalChecked();
+
+  // Create a tracker object that will cause the user data reference to be
+  // released when the V8 object is destroyed.
+  V8TrackObject* tracker = new V8TrackObject(isolate);
+
+  // Attach the tracker object.
+  tracker->AttachTo(context, promise_resolver);
+
+  CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
+  impl->InitObject(promise_resolver, tracker);
+  return impl.get();
+}
+
 // CefV8ValueImpl
 
 CefV8ValueImpl::CefV8ValueImpl(v8::Isolate* isolate)
@@ -1489,10 +1541,12 @@
 }
 
 CefV8ValueImpl::~CefV8ValueImpl() {
-  if (type_ == TYPE_STRING)
+  if (type_ == TYPE_STRING) {
     cef_string_clear(&string_value_);
-  if (handle_.get())
+  }
+  if (handle_.get()) {
     handle_->SetWeakIfNecessary();
+  }
 }
 
 void CefV8ValueImpl::InitFromV8Value(v8::Local<v8::Context> context,
@@ -1515,8 +1569,8 @@
     InitDouble(value->ToNumber(context).ToLocalChecked()->Value());
   } else if (value->IsDate()) {
     // Convert from milliseconds to seconds.
-    InitDate(
-        CefTime(value->ToNumber(context).ToLocalChecked()->Value() / 1000));
+    InitDate(base::Time::FromJsTime(
+        value->ToNumber(context).ToLocalChecked()->Value()));
   } else if (value->IsString()) {
     CefString rv;
     GetCefString(context->GetIsolate(),
@@ -1543,13 +1597,13 @@
   bool_value_ = value;
 }
 
-void CefV8ValueImpl::InitInt(int32 value) {
+void CefV8ValueImpl::InitInt(int32_t value) {
   DCHECK_EQ(type_, TYPE_INVALID);
   type_ = TYPE_INT;
   int_value_ = value;
 }
 
-void CefV8ValueImpl::InitUInt(uint32 value) {
+void CefV8ValueImpl::InitUInt(uint32_t value) {
   DCHECK_EQ(type_, TYPE_INVALID);
   type_ = TYPE_UINT;
   uint_value_ = value;
@@ -1561,7 +1615,7 @@
   double_value_ = value;
 }
 
-void CefV8ValueImpl::InitDate(const CefTime& value) {
+void CefV8ValueImpl::InitDate(CefBaseTime value) {
   DCHECK_EQ(type_, TYPE_INVALID);
   type_ = TYPE_DATE;
   date_value_ = value;
@@ -1601,13 +1655,14 @@
     case TYPE_INT:
       return v8::Int32::New(isolate_, int_value_);
     case TYPE_UINT:
-      return v8::Uint32::New(isolate_, uint_value_);
+      return v8::Uint32::NewFromUnsigned(isolate_, uint_value_);
     case TYPE_DOUBLE:
       return v8::Number::New(isolate_, double_value_);
     case TYPE_DATE:
       // Convert from seconds to milliseconds.
       return v8::Date::New(isolate_->GetCurrentContext(),
-                           CefTime(date_value_).GetDoubleT() * 1000)
+                           static_cast<base::Time>(CefBaseTime(date_value_))
+                               .ToJsTimeIgnoringNull())
           .ToLocalChecked();
     case TYPE_STRING:
       return GetV8String(isolate_, CefString(&string_value_));
@@ -1617,7 +1672,7 @@
       break;
   }
 
-  NOTREACHED() << "Invalid type for CefV8ValueImpl";
+  DCHECK(false) << "Invalid type for CefV8ValueImpl";
   return v8::Local<v8::Value>();
 }
 
@@ -1705,12 +1760,23 @@
   }
 }
 
+bool CefV8ValueImpl::IsPromise() {
+  CEF_V8_REQUIRE_MLT_RETURN(false);
+  if (type_ == TYPE_OBJECT) {
+    v8::HandleScope handle_scope(handle_->isolate());
+    return handle_->GetNewV8Handle(false)->IsPromise();
+  } else {
+    return false;
+  }
+}
+
 bool CefV8ValueImpl::IsSame(CefRefPtr<CefV8Value> that) {
   CEF_V8_REQUIRE_MLT_RETURN(false);
 
   CefV8ValueImpl* thatValue = static_cast<CefV8ValueImpl*>(that.get());
-  if (!thatValue || !thatValue->IsValid() || type_ != thatValue->type_)
+  if (!thatValue || !thatValue->IsValid() || type_ != thatValue->type_) {
     return false;
+  }
 
   switch (type_) {
     case TYPE_UNDEFINED:
@@ -1725,8 +1791,7 @@
     case TYPE_DOUBLE:
       return (double_value_ == thatValue->double_value_);
     case TYPE_DATE:
-      return (CefTime(date_value_).GetTimeT() ==
-              CefTime(thatValue->date_value_).GetTimeT());
+      return (date_value_.val == thatValue->date_value_.val);
     case TYPE_STRING:
       return (CefString(&string_value_) ==
               CefString(&thatValue->string_value_));
@@ -1743,48 +1808,54 @@
 
 bool CefV8ValueImpl::GetBoolValue() {
   CEF_V8_REQUIRE_ISOLATE_RETURN(false);
-  if (type_ == TYPE_BOOL)
+  if (type_ == TYPE_BOOL) {
     return bool_value_;
+  }
   return false;
 }
 
-int32 CefV8ValueImpl::GetIntValue() {
+int32_t CefV8ValueImpl::GetIntValue() {
   CEF_V8_REQUIRE_ISOLATE_RETURN(0);
-  if (type_ == TYPE_INT || type_ == TYPE_UINT)
+  if (type_ == TYPE_INT || type_ == TYPE_UINT) {
     return int_value_;
+  }
   return 0;
 }
 
-uint32 CefV8ValueImpl::GetUIntValue() {
+uint32_t CefV8ValueImpl::GetUIntValue() {
   CEF_V8_REQUIRE_ISOLATE_RETURN(0);
-  if (type_ == TYPE_INT || type_ == TYPE_UINT)
+  if (type_ == TYPE_INT || type_ == TYPE_UINT) {
     return uint_value_;
+  }
   return 0;
 }
 
 double CefV8ValueImpl::GetDoubleValue() {
   CEF_V8_REQUIRE_ISOLATE_RETURN(0.);
-  if (type_ == TYPE_DOUBLE)
+  if (type_ == TYPE_DOUBLE) {
     return double_value_;
-  else if (type_ == TYPE_INT)
+  } else if (type_ == TYPE_INT) {
     return int_value_;
-  else if (type_ == TYPE_UINT)
+  } else if (type_ == TYPE_UINT) {
     return uint_value_;
+  }
   return 0.;
 }
 
-CefTime CefV8ValueImpl::GetDateValue() {
-  CEF_V8_REQUIRE_ISOLATE_RETURN(CefTime(0.));
-  if (type_ == TYPE_DATE)
+CefBaseTime CefV8ValueImpl::GetDateValue() {
+  CEF_V8_REQUIRE_ISOLATE_RETURN(CefBaseTime());
+  if (type_ == TYPE_DATE) {
     return date_value_;
-  return CefTime(0.);
+  }
+  return CefBaseTime();
 }
 
 CefString CefV8ValueImpl::GetStringValue() {
   CefString rv;
   CEF_V8_REQUIRE_ISOLATE_RETURN(rv);
-  if (type_ == TYPE_STRING)
+  if (type_ == TYPE_STRING) {
     rv = CefString(&string_value_);
+  }
   return rv;
 }
 
@@ -1796,7 +1867,7 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return false;
   }
 
@@ -1847,7 +1918,7 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return false;
   }
 
@@ -1860,7 +1931,7 @@
   CEF_V8_REQUIRE_OBJECT_RETURN(false);
 
   if (index < 0) {
-    NOTREACHED() << "invalid input parameter";
+    DCHECK(false) << "invalid input parameter";
     return false;
   }
 
@@ -1869,7 +1940,7 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return false;
   }
 
@@ -1886,7 +1957,7 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return false;
   }
 
@@ -1903,7 +1974,7 @@
   CEF_V8_REQUIRE_OBJECT_RETURN(false);
 
   if (index < 0) {
-    NOTREACHED() << "invalid input parameter";
+    DCHECK(false) << "invalid input parameter";
     return false;
   }
 
@@ -1912,7 +1983,7 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return false;
   }
 
@@ -1933,7 +2004,7 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return nullptr;
   }
 
@@ -1954,7 +2025,7 @@
   CEF_V8_REQUIRE_OBJECT_RETURN(nullptr);
 
   if (index < 0) {
-    NOTREACHED() << "invalid input parameter";
+    DCHECK(false) << "invalid input parameter";
     return nullptr;
   }
 
@@ -1963,7 +2034,7 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return nullptr;
   }
 
@@ -1992,12 +2063,12 @@
 
     v8::Local<v8::Context> context = isolate->GetCurrentContext();
     if (context.IsEmpty()) {
-      NOTREACHED() << "not currently in a V8 context";
+      DCHECK(false) << "not currently in a V8 context";
       return false;
     }
 
-    v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
-    v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
+    v8::Local<v8::Value> v8value = handle_->GetNewV8Handle(false);
+    v8::Local<v8::Object> obj = v8value->ToObject(context).ToLocalChecked();
 
     v8::TryCatch try_catch(isolate);
     try_catch.SetVerbose(true);
@@ -2016,7 +2087,7 @@
       return (!HasCaught(context, try_catch) && set.FromJust());
     }
   } else {
-    NOTREACHED() << "invalid input parameter";
+    DCHECK(false) << "invalid input parameter";
     return false;
   }
 }
@@ -2025,7 +2096,7 @@
   CEF_V8_REQUIRE_OBJECT_RETURN(false);
 
   if (index < 0) {
-    NOTREACHED() << "invalid input parameter";
+    DCHECK(false) << "invalid input parameter";
     return false;
   }
 
@@ -2036,19 +2107,19 @@
 
     v8::Local<v8::Context> context = isolate->GetCurrentContext();
     if (context.IsEmpty()) {
-      NOTREACHED() << "not currently in a V8 context";
+      DCHECK(false) << "not currently in a V8 context";
       return false;
     }
 
-    v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
-    v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
+    v8::Local<v8::Value> v8value = handle_->GetNewV8Handle(false);
+    v8::Local<v8::Object> obj = v8value->ToObject(context).ToLocalChecked();
 
     v8::TryCatch try_catch(isolate);
     try_catch.SetVerbose(true);
     v8::Maybe<bool> set = obj->Set(context, index, impl->GetV8Value(true));
     return (!HasCaught(context, try_catch) && set.FromJust());
   } else {
-    NOTREACHED() << "invalid input parameter";
+    DCHECK(false) << "invalid input parameter";
     return false;
   }
 }
@@ -2063,7 +2134,7 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return false;
   }
 
@@ -2073,12 +2144,14 @@
   CefRefPtr<CefV8Accessor> accessorPtr;
 
   V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
-  if (tracker)
+  if (tracker) {
     accessorPtr = tracker->GetAccessor();
+  }
 
   // Verify that an accessor exists for this object.
-  if (!accessorPtr.get())
+  if (!accessorPtr.get()) {
     return false;
+  }
 
   v8::AccessorNameGetterCallback getter = AccessorNameGetterCallbackImpl;
   v8::AccessorNameSetterCallback setter =
@@ -2103,7 +2176,7 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return false;
   }
 
@@ -2114,10 +2187,10 @@
 
   uint32_t len = arr_keys->Length();
   for (uint32_t i = 0; i < len; ++i) {
-    v8::Local<v8::Value> value =
+    v8::Local<v8::Value> arr_value =
         arr_keys->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked();
     CefString str;
-    GetCefString(isolate, value->ToString(context).ToLocalChecked(), str);
+    GetCefString(isolate, arr_value->ToString(context).ToLocalChecked(), str);
     keys.push_back(str);
   }
   return true;
@@ -2131,7 +2204,7 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return false;
   }
 
@@ -2155,7 +2228,7 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return nullptr;
   }
 
@@ -2163,8 +2236,9 @@
   v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
 
   V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
-  if (tracker)
+  if (tracker) {
     return tracker->GetUserData();
+  }
 
   return nullptr;
 }
@@ -2177,7 +2251,7 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return 0;
   }
 
@@ -2185,8 +2259,9 @@
   v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
 
   V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
-  if (tracker)
+  if (tracker) {
     return tracker->GetExternallyAllocatedMemory();
+  }
 
   return 0;
 }
@@ -2199,7 +2274,7 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return 0;
   }
 
@@ -2207,8 +2282,9 @@
   v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
 
   V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
-  if (tracker)
+  if (tracker) {
     return tracker->AdjustExternallyAllocatedMemory(change_in_bytes);
+  }
 
   return 0;
 }
@@ -2221,13 +2297,13 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return 0;
   }
 
   v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
   if (!value->IsArray()) {
-    NOTREACHED() << "V8 value is not an array";
+    DCHECK(false) << "V8 value is not an array";
     return 0;
   }
 
@@ -2245,21 +2321,22 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return nullptr;
   }
 
   v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
   if (!value->IsArrayBuffer()) {
-    NOTREACHED() << "V8 value is not an array buffer";
+    DCHECK(false) << "V8 value is not an array buffer";
     return nullptr;
   }
 
   v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
 
   V8TrackArrayBuffer* tracker = V8TrackArrayBuffer::Unwrap(context, obj);
-  if (tracker)
+  if (tracker) {
     return tracker->GetReleaseCallback();
+  }
 
   return nullptr;
 }
@@ -2272,13 +2349,13 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return false;
   }
 
   v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
   if (!value->IsArrayBuffer()) {
-    NOTREACHED() << "V8 value is not an array buffer";
+    DCHECK(false) << "V8 value is not an array buffer";
     return false;
   }
   v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
@@ -2287,12 +2364,65 @@
     return false;
   }
   arr->Detach();
-  V8TrackArrayBuffer* tracker = V8TrackArrayBuffer::Unwrap(context, obj);
-  tracker->Detach();
 
   return true;
 }
 
+size_t CefV8ValueImpl::GetArrayBufferByteLength() {
+  size_t rv = 0;
+  CEF_V8_REQUIRE_ISOLATE_RETURN(rv);
+  if (type_ != TYPE_OBJECT) {
+    DCHECK(false) << "V8 value is not an object";
+    return rv;
+  }
+
+  v8::Isolate* isolate = handle_->isolate();
+  v8::HandleScope handle_scope(isolate);
+
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  if (context.IsEmpty()) {
+    DCHECK(false) << "not currently in a V8 context";
+    return rv;
+  }
+
+  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
+  if (!value->IsArrayBuffer()) {
+    DCHECK(false) << "V8 value is not an array buffer";
+    return rv;
+  }
+
+  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
+  return v8::Local<v8::ArrayBuffer>::Cast(obj)->ByteLength();
+}
+
+void* CefV8ValueImpl::GetArrayBufferData() {
+  void* rv = nullptr;
+  CEF_V8_REQUIRE_ISOLATE_RETURN(rv);
+  if (type_ != TYPE_OBJECT) {
+    DCHECK(false) << "V8 value is not an object";
+    return rv;
+  }
+
+  v8::Isolate* isolate = handle_->isolate();
+  v8::HandleScope handle_scope(isolate);
+
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  if (context.IsEmpty()) {
+    DCHECK(false) << "not currently in a V8 context";
+    return rv;
+  }
+
+  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
+  if (!value->IsArrayBuffer()) {
+    DCHECK(false) << "V8 value is not an array buffer";
+    return rv;
+  }
+
+  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
+  v8::Local<v8::ArrayBuffer> arr = v8::Local<v8::ArrayBuffer>::Cast(obj);
+  return arr->Data();
+}
+
 CefString CefV8ValueImpl::GetFunctionName() {
   CefString rv;
   CEF_V8_REQUIRE_OBJECT_RETURN(rv);
@@ -2302,13 +2432,13 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return rv;
   }
 
   v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
   if (!value->IsFunction()) {
-    NOTREACHED() << "V8 value is not a function";
+    DCHECK(false) << "V8 value is not a function";
     return rv;
   }
 
@@ -2327,20 +2457,21 @@
 
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   if (context.IsEmpty()) {
-    NOTREACHED() << "not currently in a V8 context";
+    DCHECK(false) << "not currently in a V8 context";
     return nullptr;
   }
 
   v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
   if (!value->IsFunction()) {
-    NOTREACHED() << "V8 value is not a function";
+    DCHECK(false) << "V8 value is not a function";
     return nullptr;
   }
 
   v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
   V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
-  if (tracker)
+  if (tracker) {
     return tracker->GetHandler();
+  }
 
   return nullptr;
 }
@@ -2363,16 +2494,16 @@
   v8::HandleScope handle_scope(isolate);
   v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
   if (!value->IsFunction()) {
-    NOTREACHED() << "V8 value is not a function";
+    DCHECK(false) << "V8 value is not a function";
     return nullptr;
   }
 
   if (context.get() && !context->IsValid()) {
-    NOTREACHED() << "invalid V8 context parameter";
+    DCHECK(false) << "invalid V8 context parameter";
     return nullptr;
   }
   if (object.get() && (!object->IsValid() || !object->IsObject())) {
-    NOTREACHED() << "invalid V8 object parameter";
+    DCHECK(false) << "invalid V8 object parameter";
     return nullptr;
   }
 
@@ -2380,7 +2511,7 @@
   if (argc > 0) {
     for (int i = 0; i < argc; ++i) {
       if (!arguments[i].get() || !arguments[i]->IsValid()) {
-        NOTREACHED() << "invalid V8 arguments parameter";
+        DCHECK(false) << "invalid V8 arguments parameter";
         return nullptr;
       }
     }
@@ -2433,22 +2564,94 @@
     }
   }
 
-  if (argv)
+  if (argv) {
     delete[] argv;
+  }
 
   return retval;
 }
 
+bool CefV8ValueImpl::ResolvePromise(CefRefPtr<CefV8Value> arg) {
+  CEF_V8_REQUIRE_OBJECT_RETURN(false);
+
+  v8::Isolate* isolate = handle_->isolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
+  if (!value->IsPromise()) {
+    DCHECK(false) << "V8 value is not a Promise";
+    return false;
+  }
+
+  if (arg.get() && !arg->IsValid()) {
+    DCHECK(false) << "invalid V8 arg parameter";
+    return false;
+  }
+
+  v8::Local<v8::Context> context_local = isolate->GetCurrentContext();
+
+  v8::Context::Scope context_scope(context_local);
+
+  v8::Local<v8::Object> obj = value->ToObject(context_local).ToLocalChecked();
+  v8::Local<v8::Promise::Resolver> promise =
+      v8::Local<v8::Promise::Resolver>::Cast(obj);
+
+  v8::TryCatch try_catch(isolate);
+  try_catch.SetVerbose(true);
+
+  if (arg.get()) {
+    promise
+        ->Resolve(context_local,
+                  static_cast<CefV8ValueImpl*>(arg.get())->GetV8Value(true))
+        .ToChecked();
+  } else {
+    promise->Resolve(context_local, v8::Undefined(isolate)).ToChecked();
+  }
+
+  return !HasCaught(context_local, try_catch);
+}
+
+bool CefV8ValueImpl::RejectPromise(const CefString& errorMsg) {
+  CEF_V8_REQUIRE_OBJECT_RETURN(false);
+
+  v8::Isolate* isolate = handle_->isolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
+  if (!value->IsPromise()) {
+    DCHECK(false) << "V8 value is not a Promise";
+    return false;
+  }
+
+  v8::Local<v8::Context> context_local = isolate->GetCurrentContext();
+
+  v8::Context::Scope context_scope(context_local);
+
+  v8::Local<v8::Object> obj = value->ToObject(context_local).ToLocalChecked();
+  v8::Local<v8::Promise::Resolver> promise =
+      v8::Local<v8::Promise::Resolver>::Cast(obj);
+
+  v8::TryCatch try_catch(isolate);
+  try_catch.SetVerbose(true);
+
+  promise
+      ->Reject(context_local,
+               v8::Exception::Error(GetV8String(isolate, errorMsg)))
+      .ToChecked();
+
+  return !HasCaught(context_local, try_catch);
+}
+
 bool CefV8ValueImpl::HasCaught(v8::Local<v8::Context> context,
                                v8::TryCatch& try_catch) {
   if (try_catch.HasCaught()) {
     last_exception_ = new CefV8ExceptionImpl(context, try_catch.Message());
-    if (rethrow_exceptions_)
+    if (rethrow_exceptions_) {
       try_catch.ReThrow();
+    }
     return true;
   } else {
-    if (last_exception_.get())
+    if (last_exception_.get()) {
       last_exception_ = nullptr;
+    }
     return false;
   }
 }
@@ -2459,12 +2662,13 @@
 CefRefPtr<CefV8StackTrace> CefV8StackTrace::GetCurrent(int frame_limit) {
   CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
 
-  v8::Isolate* isolate = GetIsolateManager()->isolate();
+  v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate();
   v8::HandleScope handle_scope(isolate);
   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
       isolate, frame_limit, v8::StackTrace::kDetailed);
-  if (stackTrace.IsEmpty())
+  if (stackTrace.IsEmpty()) {
     return nullptr;
+  }
   return new CefV8StackTraceImpl(isolate, stackTrace);
 }
 
@@ -2476,9 +2680,10 @@
     int frame_count = handle->GetFrameCount();
     if (frame_count > 0) {
       frames_.reserve(frame_count);
-      for (int i = 0; i < frame_count; ++i)
+      for (int i = 0; i < frame_count; ++i) {
         frames_.push_back(
             new CefV8StackFrameImpl(isolate, handle->GetFrame(isolate, i)));
+      }
     }
   }
 }
@@ -2494,8 +2699,9 @@
 }
 
 CefRefPtr<CefV8StackFrame> CefV8StackTraceImpl::GetFrame(int index) {
-  if (index < 0 || index >= static_cast<int>(frames_.size()))
+  if (index < 0 || index >= static_cast<int>(frames_.size())) {
     return nullptr;
+  }
   return frames_[index];
 }
 
@@ -2504,8 +2710,9 @@
 CefV8StackFrameImpl::CefV8StackFrameImpl(v8::Isolate* isolate,
                                          v8::Local<v8::StackFrame> handle)
     : line_number_(0), column_(0), is_eval_(false), is_constructor_(false) {
-  if (handle.IsEmpty())
+  if (handle.IsEmpty()) {
     return;
+  }
   GetCefString(isolate, handle->GetScriptName(), script_name_);
   GetCefString(isolate, handle->GetScriptNameOrSourceURL(),
                script_name_or_source_url_);
@@ -2551,7 +2758,7 @@
 }
 
 // Enable deprecation warnings on Windows. See http://crbug.com/585142.
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
 #if defined(__clang__)
 #pragma GCC diagnostic pop
 #else
diff --git a/src/libcef/renderer/v8_impl.h b/src/libcef/renderer/v8_impl.h
index bc37af3..11ff77a 100644
--- a/src/libcef/renderer/v8_impl.h
+++ b/src/libcef/renderer/v8_impl.h
@@ -14,7 +14,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
+#include "base/task/single_thread_task_runner.h"
 #include "v8/include/v8.h"
 
 class CefTrackNode;
@@ -129,14 +129,17 @@
 template <typename v8class>
 class CefV8Handle : public CefV8HandleBase {
  public:
-  typedef v8::Local<v8class> handleType;
-  typedef v8::Persistent<v8class> persistentType;
+  using handleType = v8::Local<v8class>;
+  using persistentType = v8::Persistent<v8class>;
 
   CefV8Handle(v8::Isolate* isolate,
               v8::Local<v8::Context> context,
               handleType v)
       : CefV8HandleBase(isolate, context), handle_(isolate, v) {}
 
+  CefV8Handle(const CefV8Handle&) = delete;
+  CefV8Handle& operator=(const CefV8Handle&) = delete;
+
   handleType GetNewV8Handle() {
     DCHECK(IsValid());
     return handleType::New(isolate(), handle_);
@@ -148,8 +151,6 @@
   ~CefV8Handle() override { handle_.Reset(); }
 
   persistentType handle_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefV8Handle);
 };
 
 // Specialization for v8::Value with empty implementation to avoid incorrect
@@ -160,6 +161,10 @@
 class CefV8ContextImpl : public CefV8Context {
  public:
   CefV8ContextImpl(v8::Isolate* isolate, v8::Local<v8::Context> context);
+
+  CefV8ContextImpl(const CefV8ContextImpl&) = delete;
+  CefV8ContextImpl& operator=(const CefV8ContextImpl&) = delete;
+
   ~CefV8ContextImpl() override;
 
   CefRefPtr<CefTaskRunner> GetTaskRunner() override;
@@ -180,14 +185,14 @@
   blink::WebLocalFrame* GetWebFrame();
 
  private:
-  typedef CefV8Handle<v8::Context> Handle;
+  using Handle = CefV8Handle<v8::Context>;
   scoped_refptr<Handle> handle_;
+  v8::MicrotaskQueue* const microtask_queue_;
 
-  int enter_count_;
+  int enter_count_ = 0;
   std::unique_ptr<v8::MicrotasksScope> microtasks_scope_;
 
   IMPLEMENT_REFCOUNTING(CefV8ContextImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefV8ContextImpl);
 };
 
 class CefV8ValueImpl : public CefV8Value {
@@ -196,6 +201,10 @@
   CefV8ValueImpl(v8::Isolate* isolate,
                  v8::Local<v8::Context> context,
                  v8::Local<v8::Value> value);
+
+  CefV8ValueImpl(const CefV8ValueImpl&) = delete;
+  CefV8ValueImpl& operator=(const CefV8ValueImpl&) = delete;
+
   ~CefV8ValueImpl() override;
 
   // Used for initializing the CefV8ValueImpl. Should be called a single time
@@ -205,10 +214,10 @@
   void InitUndefined();
   void InitNull();
   void InitBool(bool value);
-  void InitInt(int32 value);
-  void InitUInt(uint32 value);
+  void InitInt(int32_t value);
+  void InitUInt(uint32_t value);
   void InitDouble(double value);
-  void InitDate(const CefTime& value);
+  void InitDate(CefBaseTime value);
   void InitString(CefString& value);
   void InitObject(v8::Local<v8::Value> value, CefTrackNode* tracker);
 
@@ -229,12 +238,13 @@
   bool IsArray() override;
   bool IsArrayBuffer() override;
   bool IsFunction() override;
+  bool IsPromise() override;
   bool IsSame(CefRefPtr<CefV8Value> value) override;
   bool GetBoolValue() override;
-  int32 GetIntValue() override;
-  uint32 GetUIntValue() override;
+  int32_t GetIntValue() override;
+  uint32_t GetUIntValue() override;
   double GetDoubleValue() override;
-  CefTime GetDateValue() override;
+  CefBaseTime GetDateValue() override;
   CefString GetStringValue() override;
   bool IsUserCreated() override;
   bool HasException() override;
@@ -264,6 +274,8 @@
   CefRefPtr<CefV8ArrayBufferReleaseCallback> GetArrayBufferReleaseCallback()
       override;
   bool NeuterArrayBuffer() override;
+  size_t GetArrayBufferByteLength() override;
+  void* GetArrayBufferData() override;
   CefString GetFunctionName() override;
   CefRefPtr<CefV8Handler> GetFunctionHandler() override;
   CefRefPtr<CefV8Value> ExecuteFunction(
@@ -274,20 +286,26 @@
       CefRefPtr<CefV8Value> object,
       const CefV8ValueList& arguments) override;
 
+  bool ResolvePromise(CefRefPtr<CefV8Value> arg) override;
+  bool RejectPromise(const CefString& errorMsg) override;
+
  private:
   // Test for and record any exception.
   bool HasCaught(v8::Local<v8::Context> context, v8::TryCatch& try_catch);
 
   class Handle : public CefV8HandleBase {
    public:
-    typedef v8::Local<v8::Value> handleType;
-    typedef v8::Persistent<v8::Value> persistentType;
+    using handleType = v8::Local<v8::Value>;
+    using persistentType = v8::Persistent<v8::Value>;
 
     Handle(v8::Isolate* isolate,
            v8::Local<v8::Context> context,
            handleType v,
            CefTrackNode* tracker);
 
+    Handle(const Handle&) = delete;
+    Handle& operator=(const Handle&) = delete;
+
     handleType GetNewV8Handle(bool should_persist);
 
     persistentType& GetPersistentV8Handle();
@@ -313,8 +331,6 @@
 
     // True if the handle has been set as weak.
     bool is_set_weak_;
-
-    DISALLOW_COPY_AND_ASSIGN(Handle);
   };
 
   v8::Isolate* isolate_;
@@ -334,10 +350,10 @@
 
   union {
     bool bool_value_;
-    int32 int_value_;
-    uint32 uint_value_;
+    int32_t int_value_;
+    uint32_t uint_value_;
     double double_value_;
-    cef_time_t date_value_;
+    cef_basetime_t date_value_;
     cef_string_t string_value_;
   };
 
@@ -348,12 +364,15 @@
   bool rethrow_exceptions_;
 
   IMPLEMENT_REFCOUNTING(CefV8ValueImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefV8ValueImpl);
 };
 
 class CefV8StackTraceImpl : public CefV8StackTrace {
  public:
   CefV8StackTraceImpl(v8::Isolate* isolate, v8::Local<v8::StackTrace> handle);
+
+  CefV8StackTraceImpl(const CefV8StackTraceImpl&) = delete;
+  CefV8StackTraceImpl& operator=(const CefV8StackTraceImpl&) = delete;
+
   ~CefV8StackTraceImpl() override;
 
   bool IsValid() override;
@@ -364,12 +383,15 @@
   std::vector<CefRefPtr<CefV8StackFrame>> frames_;
 
   IMPLEMENT_REFCOUNTING(CefV8StackTraceImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefV8StackTraceImpl);
 };
 
 class CefV8StackFrameImpl : public CefV8StackFrame {
  public:
   CefV8StackFrameImpl(v8::Isolate* isolate, v8::Local<v8::StackFrame> handle);
+
+  CefV8StackFrameImpl(const CefV8StackFrameImpl&) = delete;
+  CefV8StackFrameImpl& operator=(const CefV8StackFrameImpl&) = delete;
+
   ~CefV8StackFrameImpl() override;
 
   bool IsValid() override;
@@ -391,7 +413,6 @@
   bool is_constructor_;
 
   IMPLEMENT_REFCOUNTING(CefV8StackFrameImpl);
-  DISALLOW_COPY_AND_ASSIGN(CefV8StackFrameImpl);
 };
 
 #endif  // CEF_LIBCEF_RENDERER_V8_IMPL_H_
diff --git a/src/libcef/resources/about_version.html b/src/libcef/resources/about_version.html
index 8739575..024755f 100644
--- a/src/libcef/resources/about_version.html
+++ b/src/libcef/resources/about_version.html
@@ -96,9 +96,6 @@
           <td class="label" valign="top">JavaScript</td>
           <td class="value">$$JAVASCRIPT$$</td>
         </tr>
-          <tr><td class="label" valign="top">Flash</td>
-          <td class="value" id="flash">$$FLASH$$</td>
-        </tr>
         <tr>
           <td class="label" valign="top">User Agent</td>
           <td class="value">$$USERAGENT$$</td>
diff --git a/src/libcef/resources/cef_strings.grd b/src/libcef/resources/cef_strings.grd
index 3bd509c..a3d59a2 100644
--- a/src/libcef/resources/cef_strings.grd
+++ b/src/libcef/resources/cef_strings.grd
@@ -12,6 +12,7 @@
       <emit emit_type='prepend'></emit>
     </output>
 
+    <output filename="cef_strings_af.pak" type="data_package" lang="af" />
     <output filename="cef_strings_am.pak" type="data_package" lang="am" />
     <output filename="cef_strings_ar.pak" type="data_package" lang="ar" />
     <if expr="pp_ifdef('use_third_party_translations')">
@@ -100,9 +101,14 @@
       <output filename="cef_strings_ug.pak" type="data_package" lang="ug" />
     </if>
     <output filename="cef_strings_uk.pak" type="data_package" lang="uk" />
+    <output filename="cef_strings_ur.pak" type="data_package" lang="ur" />
     <output filename="cef_strings_vi.pak" type="data_package" lang="vi" />
     <output filename="cef_strings_zh-CN.pak" type="data_package" lang="zh-CN" />
     <output filename="cef_strings_zh-TW.pak" type="data_package" lang="zh-TW" />
+    <if expr="enable_pseudolocales">
+      <output filename="cef_strings_ar-XB.pak" type="data_package" lang="ar-XB" />
+      <output filename="cef_strings_en-XA.pak" type="data_package" lang="en-XA" />
+    </if>
   </outputs>
   <release seq="1" allow_pseudo="false">
     <messages fallback_to_english="true">
diff --git a/src/libcef/resources/framework-Info.plist b/src/libcef/resources/framework-Info.plist
index 21f1d20..a2169b3 100644
--- a/src/libcef/resources/framework-Info.plist
+++ b/src/libcef/resources/framework-Info.plist
@@ -7,7 +7,7 @@
 	<key>CFBundleExecutable</key>

 	<string>${EXECUTABLE_NAME}</string>

 	<key>CFBundleIdentifier</key>

-	<string>org.chromium.ContentShell.framework</string>

+	<string>org.cef.framework</string>

 	<key>CFBundleInfoDictionaryVersion</key>

 	<string>6.0</string>

 	<key>CFBundlePackageType</key>

diff --git a/src/libcef_dll/CMakeLists.txt.in b/src/libcef_dll/CMakeLists.txt.in
index a218553..72a2d99 100644
--- a/src/libcef_dll/CMakeLists.txt.in
+++ b/src/libcef_dll/CMakeLists.txt.in
@@ -4,8 +4,8 @@
 
 # Append platform specific sources to a list of sources.
 macro(LIBCEF_APPEND_PLATFORM_SOURCES name_of_list)
-  if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin" AND ${name_of_list}_MACOSX)
-    list(APPEND ${name_of_list} ${${name_of_list}_MACOSX})
+  if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin" AND ${name_of_list}_MAC)
+    list(APPEND ${name_of_list} ${${name_of_list}_MAC})
   endif()
   if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" AND ${name_of_list}_LINUX)
     list(APPEND ${name_of_list} ${${name_of_list}_LINUX})
@@ -28,16 +28,16 @@
     'includes_capi',
     'autogen_capi_includes',
     'includes_wrapper',
-    'includes_wrapper_mac:MACOSX',
+    'includes_wrapper_mac:MAC',
     'includes_win:WINDOWS',
     'includes_win_capi:WINDOWS',
-    'includes_mac:MACOSX',
-    'includes_mac_capi:MACOSX',
+    'includes_mac:MAC',
+    'includes_mac_capi:MAC',
     'includes_linux:LINUX',
     'includes_linux_capi:LINUX',
     'libcef_dll_wrapper_sources_base',
     'libcef_dll_wrapper_sources_common',
-    'libcef_dll_wrapper_sources_mac:MACOSX',
+    'libcef_dll_wrapper_sources_mac:MAC',
     'autogen_client_side',
   ],
 }}
diff --git a/src/libcef_dll/base/cef_atomic_flag.cc b/src/libcef_dll/base/cef_atomic_flag.cc
new file mode 100644
index 0000000..94846db
--- /dev/null
+++ b/src/libcef_dll/base/cef_atomic_flag.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "include/base/cef_atomic_flag.h"
+
+#include "include/base/cef_logging.h"
+
+namespace base {
+
+AtomicFlag::AtomicFlag() {
+  // It doesn't matter where the AtomicFlag is built so long as it's always
+  // Set() from the same sequence after. Note: the sequencing requirements are
+  // necessary for IsSet()'s callers to know which sequence's memory operations
+  // they are synchronized with.
+  set_thread_checker_.DetachFromThread();
+}
+
+AtomicFlag::~AtomicFlag() = default;
+
+void AtomicFlag::Set() {
+  DCHECK(set_thread_checker_.CalledOnValidThread());
+  flag_.store(1, std::memory_order_release);
+}
+
+void AtomicFlag::UnsafeResetForTesting() {
+  set_thread_checker_.DetachFromThread();
+  flag_.store(0, std::memory_order_release);
+}
+
+}  // namespace base
diff --git a/src/libcef_dll/base/cef_atomicops_x86_gcc.cc b/src/libcef_dll/base/cef_atomicops_x86_gcc.cc
deleted file mode 100644
index f3dff5e..0000000
--- a/src/libcef_dll/base/cef_atomicops_x86_gcc.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This module gets enough CPU information to optimize the
-// atomicops module on x86.
-
-#include <stdint.h>
-#include <string.h>
-
-#include "include/base/cef_atomicops.h"
-
-// This file only makes sense with atomicops_internals_x86_gcc.h -- it
-// depends on structs that are defined in that file.  If atomicops.h
-// doesn't sub-include that file, then we aren't needed, and shouldn't
-// try to do anything.
-#ifdef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_GCC_H_
-
-// Inline cpuid instruction.  In PIC compilations, %ebx contains the address
-// of the global offset table.  To avoid breaking such executables, this code
-// must preserve that register's value across cpuid instructions.
-#if defined(__i386__)
-#define cpuid(a, b, c, d, inp)             \
-  asm("mov %%ebx, %%edi\n"                 \
-      "cpuid\n"                            \
-      "xchg %%edi, %%ebx\n"                \
-      : "=a"(a), "=D"(b), "=c"(c), "=d"(d) \
-      : "a"(inp))
-#elif defined(__x86_64__)
-#define cpuid(a, b, c, d, inp)             \
-  asm("mov %%rbx, %%rdi\n"                 \
-      "cpuid\n"                            \
-      "xchg %%rdi, %%rbx\n"                \
-      : "=a"(a), "=D"(b), "=c"(c), "=d"(d) \
-      : "a"(inp))
-#endif
-
-#if defined(cpuid)  // initialize the struct only on x86
-
-// Set the flags so that code will run correctly and conservatively, so even
-// if we haven't been initialized yet, we're probably single threaded, and our
-// default values should hopefully be pretty safe.
-struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = {
-    false,  // bug can't exist before process spawns multiple threads
-};
-
-namespace {
-
-// Initialize the AtomicOps_Internalx86CPUFeatures struct.
-void AtomicOps_Internalx86CPUFeaturesInit() {
-  uint32_t eax;
-  uint32_t ebx;
-  uint32_t ecx;
-  uint32_t edx;
-
-  // Get vendor string (issue CPUID with eax = 0)
-  cpuid(eax, ebx, ecx, edx, 0);
-  char vendor[13];
-  memcpy(vendor, &ebx, 4);
-  memcpy(vendor + 4, &edx, 4);
-  memcpy(vendor + 8, &ecx, 4);
-  vendor[12] = 0;
-
-  // get feature flags in ecx/edx, and family/model in eax
-  cpuid(eax, ebx, ecx, edx, 1);
-
-  int family = (eax >> 8) & 0xf;  // family and model fields
-  int model = (eax >> 4) & 0xf;
-  if (family == 0xf) {  // use extended family and model fields
-    family += (eax >> 20) & 0xff;
-    model += ((eax >> 16) & 0xf) << 4;
-  }
-
-  // Opteron Rev E has a bug in which on very rare occasions a locked
-  // instruction doesn't act as a read-acquire barrier if followed by a
-  // non-locked read-modify-write instruction.  Rev F has this bug in
-  // pre-release versions, but not in versions released to customers,
-  // so we test only for Rev E, which is family 15, model 32..63 inclusive.
-  if (strcmp(vendor, "AuthenticAMD") == 0 &&  // AMD
-      family == 15 && 32 <= model && model <= 63) {
-    AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true;
-  } else {
-    AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false;
-  }
-}
-
-class AtomicOpsx86Initializer {
- public:
-  AtomicOpsx86Initializer() { AtomicOps_Internalx86CPUFeaturesInit(); }
-};
-
-// A global to get use initialized on startup via static initialization :/
-AtomicOpsx86Initializer g_initer;
-
-}  // namespace
-
-#endif  // if x86
-
-#endif  // ifdef CEF_INCLUDE_BASE_CEF_ATOMICOPS_INTERNALS_X86_GCC_H_
diff --git a/src/libcef_dll/base/cef_bind_helpers.cc b/src/libcef_dll/base/cef_bind_helpers.cc
deleted file mode 100644
index 73f48fc..0000000
--- a/src/libcef_dll/base/cef_bind_helpers.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "include/base/cef_bind_helpers.h"
-
-#include "include/base/cef_callback.h"
-
-namespace base {
-
-void DoNothing() {}
-
-}  // namespace base
diff --git a/src/libcef_dll/base/cef_callback_helpers.cc b/src/libcef_dll/base/cef_callback_helpers.cc
index 624e509..1f75fba 100644
--- a/src/libcef_dll/base/cef_callback_helpers.cc
+++ b/src/libcef_dll/base/cef_callback_helpers.cc
@@ -4,37 +4,41 @@
 
 #include "include/base/cef_callback_helpers.h"
 
-#include "include/base/cef_callback.h"
-
 namespace base {
 
-ScopedClosureRunner::ScopedClosureRunner() {}
+ScopedClosureRunner::ScopedClosureRunner() = default;
 
-ScopedClosureRunner::ScopedClosureRunner(const Closure& closure)
-    : closure_(closure) {}
+ScopedClosureRunner::ScopedClosureRunner(OnceClosure closure)
+    : closure_(std::move(closure)) {}
+
+ScopedClosureRunner::ScopedClosureRunner(ScopedClosureRunner&& other)
+    : closure_(other.Release()) {}
+
+ScopedClosureRunner& ScopedClosureRunner::operator=(
+    ScopedClosureRunner&& other) {
+  if (this != &other) {
+    RunAndReset();
+    ReplaceClosure(other.Release());
+  }
+  return *this;
+}
 
 ScopedClosureRunner::~ScopedClosureRunner() {
-  if (!closure_.is_null())
-    closure_.Run();
+  RunAndReset();
 }
 
-void ScopedClosureRunner::Reset() {
-  Closure old_closure = Release();
-  if (!old_closure.is_null())
-    old_closure.Run();
+void ScopedClosureRunner::RunAndReset() {
+  if (closure_) {
+    std::move(closure_).Run();
+  }
 }
 
-void ScopedClosureRunner::Reset(const Closure& closure) {
-  Closure old_closure = Release();
-  closure_ = closure;
-  if (!old_closure.is_null())
-    old_closure.Run();
+void ScopedClosureRunner::ReplaceClosure(OnceClosure closure) {
+  closure_ = std::move(closure);
 }
 
-Closure ScopedClosureRunner::Release() {
-  Closure result = closure_;
-  closure_.Reset();
-  return result;
+OnceClosure ScopedClosureRunner::Release() {
+  return std::move(closure_);
 }
 
 }  // namespace base
diff --git a/src/libcef_dll/base/cef_callback_internal.cc b/src/libcef_dll/base/cef_callback_internal.cc
index dead93f..ae2a474 100644
--- a/src/libcef_dll/base/cef_callback_internal.cc
+++ b/src/libcef_dll/base/cef_callback_internal.cc
@@ -9,33 +9,93 @@
 namespace base {
 namespace cef_internal {
 
-void BindStateBase::AddRef() {
-  AtomicRefCountInc(&ref_count_);
+namespace {
+
+bool QueryCancellationTraitsForNonCancellables(
+    const BindStateBase*,
+    BindStateBase::CancellationQueryMode mode) {
+  switch (mode) {
+    case BindStateBase::IS_CANCELLED:
+      return false;
+    case BindStateBase::MAYBE_VALID:
+      return true;
+  }
+  DCHECK(false);
+  return false;
 }
 
-void BindStateBase::Release() {
-  if (!AtomicRefCountDec(&ref_count_))
-    destructor_(this);
+}  // namespace
+
+void BindStateBaseRefCountTraits::Destruct(const BindStateBase* bind_state) {
+  bind_state->destructor_(bind_state);
+}
+
+BindStateBase::BindStateBase(InvokeFuncStorage polymorphic_invoke,
+                             void (*destructor)(const BindStateBase*))
+    : BindStateBase(polymorphic_invoke,
+                    destructor,
+                    &QueryCancellationTraitsForNonCancellables) {}
+
+BindStateBase::BindStateBase(
+    InvokeFuncStorage polymorphic_invoke,
+    void (*destructor)(const BindStateBase*),
+    bool (*query_cancellation_traits)(const BindStateBase*,
+                                      CancellationQueryMode))
+    : polymorphic_invoke_(polymorphic_invoke),
+      destructor_(destructor),
+      query_cancellation_traits_(query_cancellation_traits) {}
+
+CallbackBase& CallbackBase::operator=(CallbackBase&& c) noexcept = default;
+CallbackBase::CallbackBase(const CallbackBaseCopyable& c)
+    : bind_state_(c.bind_state_) {}
+
+CallbackBase& CallbackBase::operator=(const CallbackBaseCopyable& c) {
+  bind_state_ = c.bind_state_;
+  return *this;
+}
+
+CallbackBase::CallbackBase(CallbackBaseCopyable&& c) noexcept
+    : bind_state_(std::move(c.bind_state_)) {}
+
+CallbackBase& CallbackBase::operator=(CallbackBaseCopyable&& c) noexcept {
+  bind_state_ = std::move(c.bind_state_);
+  return *this;
 }
 
 void CallbackBase::Reset() {
-  polymorphic_invoke_ = NULL;
   // NULL the bind_state_ last, since it may be holding the last ref to whatever
   // object owns us, and we may be deleted after that.
-  bind_state_ = NULL;
+  bind_state_ = nullptr;
 }
 
-bool CallbackBase::Equals(const CallbackBase& other) const {
-  return bind_state_.get() == other.bind_state_.get() &&
-         polymorphic_invoke_ == other.polymorphic_invoke_;
+bool CallbackBase::IsCancelled() const {
+  DCHECK(bind_state_);
+  return bind_state_->IsCancelled();
 }
 
-CallbackBase::CallbackBase(BindStateBase* bind_state)
-    : bind_state_(bind_state), polymorphic_invoke_(NULL) {
-  DCHECK(!bind_state_.get() || bind_state_->ref_count_ == 1);
+bool CallbackBase::MaybeValid() const {
+  DCHECK(bind_state_);
+  return bind_state_->MaybeValid();
 }
 
-CallbackBase::~CallbackBase() {}
+bool CallbackBase::EqualsInternal(const CallbackBase& other) const {
+  return bind_state_ == other.bind_state_;
+}
+
+CallbackBase::~CallbackBase() = default;
+
+CallbackBaseCopyable::CallbackBaseCopyable(const CallbackBaseCopyable& c) {
+  bind_state_ = c.bind_state_;
+}
+
+CallbackBaseCopyable& CallbackBaseCopyable::operator=(
+    const CallbackBaseCopyable& c) {
+  bind_state_ = c.bind_state_;
+  return *this;
+}
+
+CallbackBaseCopyable& CallbackBaseCopyable::operator=(
+    CallbackBaseCopyable&& c) noexcept = default;
 
 }  // namespace cef_internal
 }  // namespace base
diff --git a/src/libcef_dll/base/cef_logging.cc b/src/libcef_dll/base/cef_logging.cc
index 3560291..f8a7668 100644
--- a/src/libcef_dll/base/cef_logging.cc
+++ b/src/libcef_dll/base/cef_logging.cc
@@ -190,7 +190,7 @@
 // This has already been defined in the header, but defining it again as DWORD
 // ensures that the type used in the header is equivalent to DWORD. If not,
 // the redefinition is a compile error.
-typedef DWORD SystemErrorCode;
+using SystemErrorCode = DWORD;
 #endif
 
 SystemErrorCode GetLastSystemErrorCode() {
@@ -209,7 +209,7 @@
   char msgbuf[error_message_buffer_size];
   DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
   DWORD len = FormatMessageA(flags, NULL, error_code, 0, msgbuf,
-                             arraysize(msgbuf), NULL);
+                             static_cast<DWORD>(std::size(msgbuf)), NULL);
   std::stringstream ss;
   if (len) {
     std::string s(msgbuf);
@@ -256,12 +256,25 @@
 }  // namespace cef
 
 std::ostream& operator<<(std::ostream& out, const wchar_t* wstr) {
-  std::wstring tmp_str(wstr);
-  if (!tmp_str.empty()) {
+  const auto length = wstr ? std::char_traits<wchar_t>::length(wstr) : 0U;
+  if (length > 0) {
     cef_string_utf8_t str = {0};
-    cef_string_wide_to_utf8(wstr, tmp_str.size(), &str);
+    cef_string_wide_to_utf8(wstr, length, &str);
     out << str.str;
     cef_string_utf8_clear(&str);
   }
   return out;
 }
+
+#if defined(WCHAR_T_IS_UTF32)
+std::ostream& operator<<(std::ostream& out, const char16_t* wstr) {
+  const auto length = wstr ? std::char_traits<char16_t>::length(wstr) : 0U;
+  if (length > 0) {
+    cef_string_utf8_t str = {0};
+    cef_string_utf16_to_utf8(wstr, length, &str);
+    out << str.str;
+    cef_string_utf8_clear(&str);
+  }
+  return out;
+}
+#endif
diff --git a/src/libcef_dll/base/cef_ref_counted.cc b/src/libcef_dll/base/cef_ref_counted.cc
index fdd22b1..cb3ef85 100644
--- a/src/libcef_dll/base/cef_ref_counted.cc
+++ b/src/libcef_dll/base/cef_ref_counted.cc
@@ -4,54 +4,95 @@
 
 #include "include/base/cef_ref_counted.h"
 
+#include <limits>
+#include <type_traits>
+
 namespace base {
+namespace {
+
+#if DCHECK_IS_ON()
+std::atomic_int g_cross_thread_ref_count_access_allow_count(0);
+#endif
+
+}  // namespace
 
 namespace cef_subtle {
 
 bool RefCountedThreadSafeBase::HasOneRef() const {
-  return AtomicRefCountIsOne(
-      &const_cast<RefCountedThreadSafeBase*>(this)->ref_count_);
+  return ref_count_.IsOne();
 }
 
 bool RefCountedThreadSafeBase::HasAtLeastOneRef() const {
-  return !AtomicRefCountIsZero(
-      &const_cast<RefCountedThreadSafeBase*>(this)->ref_count_);
+  return !ref_count_.IsZero();
 }
 
-RefCountedThreadSafeBase::RefCountedThreadSafeBase() : ref_count_(0) {
 #if DCHECK_IS_ON()
-  in_dtor_ = false;
-#endif
-}
-
 RefCountedThreadSafeBase::~RefCountedThreadSafeBase() {
-#if DCHECK_IS_ON()
   DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without "
                       "calling Release()";
+}
 #endif
+
+// For security and correctness, we check the arithmetic on ref counts.
+//
+// In an attempt to avoid binary bloat (from inlining the `CHECK`), we define
+// these functions out-of-line. However, compilers are wily. Further testing may
+// show that `NOINLINE` helps or hurts.
+//
+#if defined(ARCH_CPU_64_BITS)
+void RefCountedBase::AddRefImpl() const {
+  // An attacker could induce use-after-free bugs, and potentially exploit them,
+  // by creating so many references to a ref-counted object that the reference
+  // count overflows. On 32-bit architectures, there is not enough address space
+  // to succeed. But on 64-bit architectures, it might indeed be possible.
+  // Therefore, we can elide the check for arithmetic overflow on 32-bit, but we
+  // must check on 64-bit.
+  //
+  // Make sure the addition didn't wrap back around to 0. This form of check
+  // works because we assert that `ref_count_` is an unsigned integer type.
+  CHECK(++ref_count_ != 0);
 }
 
-void RefCountedThreadSafeBase::AddRef() const {
-#if DCHECK_IS_ON()
-  DCHECK(!in_dtor_);
-#endif
-  AtomicRefCountInc(&ref_count_);
+void RefCountedBase::ReleaseImpl() const {
+  // Make sure the subtraction didn't wrap back around from 0 to the max value.
+  // That could cause memory leaks, and may induce application-semantic
+  // correctness or safety bugs. (E.g. what if we really needed that object to
+  // be destroyed at the right time?)
+  //
+  // Note that unlike with overflow, underflow could also happen on 32-bit
+  // architectures. Arguably, we should do this check on32-bit machines too.
+  CHECK(--ref_count_ != std::numeric_limits<decltype(ref_count_)>::max());
 }
+#endif
 
+#if !defined(ARCH_CPU_X86_FAMILY)
 bool RefCountedThreadSafeBase::Release() const {
-#if DCHECK_IS_ON()
-  DCHECK(!in_dtor_);
-  DCHECK(!AtomicRefCountIsZero(&ref_count_));
-#endif
-  if (!AtomicRefCountDec(&ref_count_)) {
-#if DCHECK_IS_ON()
-    in_dtor_ = true;
-#endif
-    return true;
-  }
-  return false;
+  return ReleaseImpl();
 }
+void RefCountedThreadSafeBase::AddRef() const {
+  AddRefImpl();
+}
+void RefCountedThreadSafeBase::AddRefWithCheck() const {
+  AddRefWithCheckImpl();
+}
+#endif
+
+#if DCHECK_IS_ON()
+bool RefCountedBase::CalledOnValidThread() const {
+  return thread_checker_.CalledOnValidThread() ||
+         g_cross_thread_ref_count_access_allow_count.load() != 0;
+}
+#endif
+
+#if DCHECK_IS_ON()
+ScopedAllowCrossThreadRefCountAccess::ScopedAllowCrossThreadRefCountAccess() {
+  ++g_cross_thread_ref_count_access_allow_count;
+}
+
+ScopedAllowCrossThreadRefCountAccess::~ScopedAllowCrossThreadRefCountAccess() {
+  --g_cross_thread_ref_count_access_allow_count;
+}
+#endif
 
 }  // namespace cef_subtle
-
 }  // namespace base
diff --git a/src/libcef_dll/base/cef_string16.cc b/src/libcef_dll/base/cef_string16.cc
deleted file mode 100644
index 16dea8c..0000000
--- a/src/libcef_dll/base/cef_string16.cc
+++ /dev/null
@@ -1,96 +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 "include/base/cef_string16.h"
-
-#if defined(OS_POSIX)
-#if defined(WCHAR_T_IS_UTF16)
-
-#error This file should not be used on 2-byte wchar_t systems
-// If this winds up being needed on 2-byte wchar_t systems, either the
-// definitions below can be used, or the host system's wide character
-// functions like wmemcmp can be wrapped.
-
-#elif defined(WCHAR_T_IS_UTF32)
-
-#include <cstring>
-#include <ostream>
-
-#include "include/internal/cef_string_types.h"
-
-namespace cef {
-namespace base {
-
-int c16memcmp(const char16* s1, const char16* s2, size_t n) {
-  // We cannot call memcmp because that changes the semantics.
-  while (n-- > 0) {
-    if (*s1 != *s2) {
-      // We cannot use (*s1 - *s2) because char16 is unsigned.
-      return ((*s1 < *s2) ? -1 : 1);
-    }
-    ++s1;
-    ++s2;
-  }
-  return 0;
-}
-
-size_t c16len(const char16* s) {
-  const char16* s_orig = s;
-  while (*s) {
-    ++s;
-  }
-  return s - s_orig;
-}
-
-const char16* c16memchr(const char16* s, char16 c, size_t n) {
-  while (n-- > 0) {
-    if (*s == c) {
-      return s;
-    }
-    ++s;
-  }
-  return 0;
-}
-
-char16* c16memmove(char16* s1, const char16* s2, size_t n) {
-  return static_cast<char16*>(memmove(s1, s2, n * sizeof(char16)));
-}
-
-char16* c16memcpy(char16* s1, const char16* s2, size_t n) {
-  return static_cast<char16*>(memcpy(s1, s2, n * sizeof(char16)));
-}
-
-char16* c16memset(char16* s, char16 c, size_t n) {
-  char16* s_orig = s;
-  while (n-- > 0) {
-    *s = c;
-    ++s;
-  }
-  return s_orig;
-}
-
-}  // namespace base
-}  // namespace cef
-
-namespace base {
-
-std::ostream& operator<<(std::ostream& out, const string16& str) {
-  cef_string_utf8_t cef_str = {0};
-  cef_string_utf16_to_utf8(str.c_str(), str.size(), &cef_str);
-  out << cef_str.str;
-  cef_string_utf8_clear(&cef_str);
-  return out;
-}
-
-void PrintTo(const string16& str, std::ostream* out) {
-  *out << str;
-}
-
-}  // namespace base
-
-template class std::basic_string<cef::base::char16,
-                                 cef::base::string16_char_traits>;
-
-#endif  // WCHAR_T_IS_UTF32
-#endif  // OS_POSIX
diff --git a/src/libcef_dll/base/cef_weak_ptr.cc b/src/libcef_dll/base/cef_weak_ptr.cc
index 3e52831..1f2d304 100644
--- a/src/libcef_dll/base/cef_weak_ptr.cc
+++ b/src/libcef_dll/base/cef_weak_ptr.cc
@@ -7,65 +7,95 @@
 namespace base {
 namespace cef_internal {
 
-WeakReference::Flag::Flag() : is_valid_(true) {
+WeakReference::Flag::Flag() {
   // Flags only become bound when checked for validity, or invalidated,
   // so that we can check that later validity/invalidation operations on
-  // the same Flag take place on the same thread.
+  // the same Flag take place on the same threadd thread.
   thread_checker_.DetachFromThread();
 }
 
 void WeakReference::Flag::Invalidate() {
   // The flag being invalidated with a single ref implies that there are no
   // weak pointers in existence. Allow deletion on other thread in this case.
+#if DCHECK_IS_ON()
   DCHECK(thread_checker_.CalledOnValidThread() || HasOneRef())
-      << "WeakPtrs must be invalidated on the same thread.";
-  is_valid_ = false;
+      << "WeakPtrs must be invalidated on the same thread as where "
+      << "they are bound.\n";
+#endif
+  invalidated_.Set();
 }
 
 bool WeakReference::Flag::IsValid() const {
-  DCHECK(thread_checker_.CalledOnValidThread())
-      << "WeakPtrs must be checked on the same thread.";
-  return is_valid_;
+  // WeakPtrs must be checked on the same threadd thread.
+  DCHECK(thread_checker_.CalledOnValidThread());
+  return !invalidated_.IsSet();
 }
 
-WeakReference::Flag::~Flag() {}
-
-WeakReference::WeakReference() {}
-
-WeakReference::WeakReference(const Flag* flag) : flag_(flag) {}
-
-WeakReference::~WeakReference() {}
-
-bool WeakReference::is_valid() const {
-  return flag_.get() && flag_->IsValid();
+bool WeakReference::Flag::MaybeValid() const {
+  return !invalidated_.IsSet();
 }
 
-WeakReferenceOwner::WeakReferenceOwner() {}
+void WeakReference::Flag::DetachFromThread() {
+  thread_checker_.DetachFromThread();
+}
+
+WeakReference::Flag::~Flag() = default;
+
+WeakReference::WeakReference() = default;
+
+WeakReference::WeakReference(const scoped_refptr<Flag>& flag) : flag_(flag) {}
+
+WeakReference::~WeakReference() = default;
+
+WeakReference::WeakReference(WeakReference&& other) noexcept = default;
+
+WeakReference::WeakReference(const WeakReference& other) = default;
+
+bool WeakReference::IsValid() const {
+  return flag_ && flag_->IsValid();
+}
+
+bool WeakReference::MaybeValid() const {
+  return flag_ && flag_->MaybeValid();
+}
+
+WeakReferenceOwner::WeakReferenceOwner()
+    : flag_(MakeRefCounted<WeakReference::Flag>()) {}
 
 WeakReferenceOwner::~WeakReferenceOwner() {
-  Invalidate();
+  flag_->Invalidate();
 }
 
 WeakReference WeakReferenceOwner::GetRef() const {
-  // If we hold the last reference to the Flag then create a new one.
-  if (!HasRefs())
-    flag_ = new WeakReference::Flag();
+  // If we hold the last reference to the Flag then detach the ThreadChecker.
+  if (!HasRefs()) {
+    flag_->DetachFromThread();
+  }
 
-  return WeakReference(flag_.get());
+  return WeakReference(flag_);
 }
 
 void WeakReferenceOwner::Invalidate() {
-  if (flag_.get()) {
-    flag_->Invalidate();
-    flag_ = NULL;
-  }
+  flag_->Invalidate();
+  flag_ = MakeRefCounted<WeakReference::Flag>();
 }
 
-WeakPtrBase::WeakPtrBase() {}
+WeakPtrBase::WeakPtrBase() : ptr_(0) {}
 
-WeakPtrBase::~WeakPtrBase() {}
+WeakPtrBase::~WeakPtrBase() = default;
 
-WeakPtrBase::WeakPtrBase(const WeakReference& ref) : ref_(ref) {}
+WeakPtrBase::WeakPtrBase(const WeakReference& ref, uintptr_t ptr)
+    : ref_(ref), ptr_(ptr) {
+  DCHECK(ptr_);
+}
+
+WeakPtrFactoryBase::WeakPtrFactoryBase(uintptr_t ptr) : ptr_(ptr) {
+  DCHECK(ptr_);
+}
+
+WeakPtrFactoryBase::~WeakPtrFactoryBase() {
+  ptr_ = 0;
+}
 
 }  // namespace cef_internal
 }  // namespace base
diff --git a/src/libcef_dll/cpptoc/accessibility_handler_cpptoc.cc b/src/libcef_dll/cpptoc/accessibility_handler_cpptoc.cc
index 609884a..69190db 100644
--- a/src/libcef_dll/cpptoc/accessibility_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/accessibility_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=fd840fce008edc7699ad649e5f114ec7dc0259e1$
+// $hash=3ad767f0b424a886e1783b416f532fbaf6b8cbbe$
 //
 
 #include "libcef_dll/cpptoc/accessibility_handler_cpptoc.h"
@@ -28,12 +28,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: value; type: refptr_diff
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return;
+  }
 
   // Execute
   CefAccessibilityHandlerCppToC::Get(self)->OnAccessibilityTreeChange(
@@ -48,12 +50,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: value; type: refptr_diff
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return;
+  }
 
   // Execute
   CefAccessibilityHandlerCppToC::Get(self)->OnAccessibilityLocationChange(
@@ -84,7 +88,7 @@
     cef_accessibility_handler_t>::UnwrapDerived(CefWrapperType type,
                                                 cef_accessibility_handler_t*
                                                     s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/accessibility_handler_cpptoc.h b/src/libcef_dll/cpptoc/accessibility_handler_cpptoc.h
index c0d41e1..faf2710 100644
--- a/src/libcef_dll/cpptoc/accessibility_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/accessibility_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=5bf6a0415807090dfca56e879aa010846a24bcf5$
+// $hash=0d1469b1473cbef38092a2b0624ac33faa6e1d89$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_ACCESSIBILITY_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/app_cpptoc.cc b/src/libcef_dll/cpptoc/app_cpptoc.cc
index b6b9c77..8bd882f 100644
--- a/src/libcef_dll/cpptoc/app_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/app_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=44e223e0d74d87cfc4aeee6bfad7e6582390a0ad$
+// $hash=3b8d5f1990e9638e0baf2c3351c779f53c8b868a$
 //
 
 #include "libcef_dll/cpptoc/app_cpptoc.h"
@@ -30,12 +30,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: command_line; type: refptr_diff
   DCHECK(command_line);
-  if (!command_line)
+  if (!command_line) {
     return;
+  }
   // Unverified params: process_type
 
   // Execute
@@ -49,12 +51,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: registrar; type: rawptr_diff
   DCHECK(registrar);
-  if (!registrar)
+  if (!registrar) {
     return;
+  }
 
   // Translate param: registrar; type: rawptr_diff
   CefOwnPtr<CefSchemeRegistrar> registrarPtr(
@@ -69,8 +73,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefResourceBundleHandler> _retval =
@@ -85,8 +90,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowserProcessHandler> _retval =
@@ -101,8 +107,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefRenderProcessHandler> _retval =
@@ -134,7 +141,7 @@
 CefCppToCRefCounted<CefAppCppToC, CefApp, cef_app_t>::UnwrapDerived(
     CefWrapperType type,
     cef_app_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/app_cpptoc.h b/src/libcef_dll/cpptoc/app_cpptoc.h
index 43ddd7f..fe94e85 100644
--- a/src/libcef_dll/cpptoc/app_cpptoc.h
+++ b/src/libcef_dll/cpptoc/app_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0326da69d7ade92ca68cef231ded42b149406dee$
+// $hash=a4d3edb584e87581659ded4e0bb20739b2b0efea$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_APP_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/audio_handler_cpptoc.cc b/src/libcef_dll/cpptoc/audio_handler_cpptoc.cc
index fc8dc3f..15bbdd7 100644
--- a/src/libcef_dll/cpptoc/audio_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/audio_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4568fbb1f264fe9a900784aa3040c406a919ad37$
+// $hash=b4b1529613a3609c6d5eee063c2f633475e0c68c$
 //
 
 #include "libcef_dll/cpptoc/audio_handler_cpptoc.h"
@@ -29,16 +29,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: params; type: simple_byref
   DCHECK(params);
-  if (!params)
+  if (!params) {
     return 0;
+  }
 
   // Translate param: params; type: simple_byref
   CefAudioParameters paramsVal = params ? *params : CefAudioParameters();
@@ -48,8 +51,9 @@
       CefBrowserCToCpp::Wrap(browser), paramsVal);
 
   // Restore param: params; type: simple_byref
-  if (params)
+  if (params) {
     *params = paramsVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -65,16 +69,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: params; type: simple_byref_const
   DCHECK(params);
-  if (!params)
+  if (!params) {
     return;
+  }
 
   // Translate param: params; type: simple_byref_const
   CefAudioParameters paramsVal = params ? *params : CefAudioParameters();
@@ -89,22 +96,25 @@
                                      struct _cef_browser_t* browser,
                                      const float** data,
                                      int frames,
-                                     int64 pts) {
+                                     int64_t pts) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return;
+  }
 
   // Execute
   CefAudioHandlerCppToC::Get(self)->OnAudioStreamPacket(
@@ -119,12 +129,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefAudioHandlerCppToC::Get(self)->OnAudioStreamStopped(
@@ -140,16 +152,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: message; type: string_byref_const
   DCHECK(message);
-  if (!message)
+  if (!message) {
     return;
+  }
 
   // Execute
   CefAudioHandlerCppToC::Get(self)->OnAudioStreamError(
@@ -180,7 +195,7 @@
     CefAudioHandler,
     cef_audio_handler_t>::UnwrapDerived(CefWrapperType type,
                                         cef_audio_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/audio_handler_cpptoc.h b/src/libcef_dll/cpptoc/audio_handler_cpptoc.h
index b4778c8..1d57454 100644
--- a/src/libcef_dll/cpptoc/audio_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/audio_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=27689a3c353f267fb650ec5b7dc095e0a6be8b13$
+// $hash=6d31cfb9774514e0a15c999903fa4eb9ce76634d$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_AUDIO_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/auth_callback_cpptoc.cc b/src/libcef_dll/cpptoc/auth_callback_cpptoc.cc
index 784d851..0f5c4db 100644
--- a/src/libcef_dll/cpptoc/auth_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/auth_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=921314be850e42ffee64ca025993a732949bf123$
+// $hash=708e231fbc5c80191b2a9ba3d6295a6b5ecf925e$
 //
 
 #include "libcef_dll/cpptoc/auth_callback_cpptoc.h"
@@ -27,8 +27,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: username, password
 
   // Execute
@@ -42,8 +43,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefAuthCallbackCppToC::Get(self)->Cancel();
@@ -70,7 +72,7 @@
     CefAuthCallback,
     cef_auth_callback_t>::UnwrapDerived(CefWrapperType type,
                                         cef_auth_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/auth_callback_cpptoc.h b/src/libcef_dll/cpptoc/auth_callback_cpptoc.h
index 860ee3c..6a1dd70 100644
--- a/src/libcef_dll/cpptoc/auth_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/auth_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=20fac721ac760ab05005f456bb3f08d85aef1d80$
+// $hash=be94cb2e319c4a42e8bc9ee41b78935834e8a59c$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_AUTH_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/base_ref_counted_cpptoc.cc b/src/libcef_dll/cpptoc/base_ref_counted_cpptoc.cc
index 78d7e95..4dae84c 100644
--- a/src/libcef_dll/cpptoc/base_ref_counted_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/base_ref_counted_cpptoc.cc
@@ -12,7 +12,7 @@
     CefBaseRefCounted,
     cef_base_ref_counted_t>::UnwrapDerived(CefWrapperType type,
                                            cef_base_ref_counted_t* s) {
-  NOTREACHED();
+  DCHECK(false);
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/base_scoped_cpptoc.cc b/src/libcef_dll/cpptoc/base_scoped_cpptoc.cc
index 02387ca..9fa8c47 100644
--- a/src/libcef_dll/cpptoc/base_scoped_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/base_scoped_cpptoc.cc
@@ -10,7 +10,7 @@
 CefOwnPtr<CefBaseScoped>
 CefCppToCScoped<CefBaseScopedCppToC, CefBaseScoped, cef_base_scoped_t>::
     UnwrapDerivedOwn(CefWrapperType type, cef_base_scoped_t* s) {
-  NOTREACHED();
+  DCHECK(false);
   return CefOwnPtr<CefBaseScoped>();
 }
 
@@ -18,7 +18,7 @@
 CefRawPtr<CefBaseScoped>
 CefCppToCScoped<CefBaseScopedCppToC, CefBaseScoped, cef_base_scoped_t>::
     UnwrapDerivedRaw(CefWrapperType type, cef_base_scoped_t* s) {
-  NOTREACHED();
+  DCHECK(false);
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/before_download_callback_cpptoc.cc b/src/libcef_dll/cpptoc/before_download_callback_cpptoc.cc
index 93c6095..c5df87e 100644
--- a/src/libcef_dll/cpptoc/before_download_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/before_download_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e353aad49690f92eaa2771a7d4293d8c41a75d5c$
+// $hash=fbd5a0f83b2df711f30cd7694877708c5a3b2d50$
 //
 
 #include "libcef_dll/cpptoc/before_download_callback_cpptoc.h"
@@ -28,8 +28,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: download_path
 
   // Execute
@@ -57,7 +58,7 @@
                     CefBeforeDownloadCallback,
                     cef_before_download_callback_t>::
     UnwrapDerived(CefWrapperType type, cef_before_download_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/before_download_callback_cpptoc.h b/src/libcef_dll/cpptoc/before_download_callback_cpptoc.h
index bdeac01..9f2944c 100644
--- a/src/libcef_dll/cpptoc/before_download_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/before_download_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0193ffd9be77a8b1af71f28e0a0ba12a88a2be91$
+// $hash=76dfadaa2d0f5ef6cdb8621cad3136e89b33ae25$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_BEFORE_DOWNLOAD_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/binary_value_cpptoc.cc b/src/libcef_dll/cpptoc/binary_value_cpptoc.cc
index 276aefd..99273f1 100644
--- a/src/libcef_dll/cpptoc/binary_value_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/binary_value_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d83e342a1d94a14e39b1eba174e0b8892fd52728$
+// $hash=8da36dc268f2f9beb26abc105656f3b04b1d46ed$
 //
 
 #include "libcef_dll/cpptoc/binary_value_cpptoc.h"
@@ -25,8 +25,9 @@
 
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBinaryValue> _retval = CefBinaryValue::Create(data, data_size);
@@ -45,8 +46,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefBinaryValueCppToC::Get(self)->IsValid();
@@ -61,8 +63,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefBinaryValueCppToC::Get(self)->IsOwned();
@@ -78,12 +81,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefBinaryValueCppToC::Get(self)->IsSame(
@@ -100,12 +105,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefBinaryValueCppToC::Get(self)->IsEqual(
@@ -122,8 +129,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBinaryValue> _retval = CefBinaryValueCppToC::Get(self)->Copy();
@@ -132,14 +140,34 @@
   return CefBinaryValueCppToC::Wrap(_retval);
 }
 
+const void* CEF_CALLBACK
+binary_value_get_raw_data(struct _cef_binary_value_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+
+  // This manual implementation can be removed once support for 'const void*'
+  // is integrated into the CEF translator tool (issue #3591).
+
+  // Execute
+  const void* _retval = CefBinaryValueCppToC::Get(self)->GetRawData();
+
+  // Return type: simple_byaddr
+  return _retval;
+}
+
 size_t CEF_CALLBACK binary_value_get_size(struct _cef_binary_value_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefBinaryValueCppToC::Get(self)->GetSize();
@@ -157,12 +185,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: buffer; type: simple_byaddr
   DCHECK(buffer);
-  if (!buffer)
+  if (!buffer) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefBinaryValueCppToC::Get(self)->GetData(buffer, buffer_size,
@@ -182,6 +212,7 @@
   GetStruct()->is_same = binary_value_is_same;
   GetStruct()->is_equal = binary_value_is_equal;
   GetStruct()->copy = binary_value_copy;
+  GetStruct()->get_raw_data = binary_value_get_raw_data;
   GetStruct()->get_size = binary_value_get_size;
   GetStruct()->get_data = binary_value_get_data;
 }
@@ -196,7 +227,7 @@
 CefRefPtr<CefBinaryValue>
 CefCppToCRefCounted<CefBinaryValueCppToC, CefBinaryValue, cef_binary_value_t>::
     UnwrapDerived(CefWrapperType type, cef_binary_value_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/binary_value_cpptoc.h b/src/libcef_dll/cpptoc/binary_value_cpptoc.h
index 9cff59c..3f6a9e3 100644
--- a/src/libcef_dll/cpptoc/binary_value_cpptoc.h
+++ b/src/libcef_dll/cpptoc/binary_value_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=fccbd66b11f9f798fd1330b586d6172478a0cf81$
+// $hash=bdc631b2bd2c0a68146e823e0ff23e1b3a455023$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_BINARY_VALUE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/browser_cpptoc.cc b/src/libcef_dll/cpptoc/browser_cpptoc.cc
index f036cc5..e19be10 100644
--- a/src/libcef_dll/cpptoc/browser_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/browser_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=48f8372a4b5104ce459b4aedf625c3cfd221d017$
+// $hash=095894b34598f0352049ba3d8a56a80b9b2ad68e$
 //
 
 #include "libcef_dll/cpptoc/browser_cpptoc.h"
@@ -23,6 +23,23 @@
 
 // MEMBER FUNCTIONS - Body may be edited by hand.
 
+int CEF_CALLBACK browser_is_valid(struct _cef_browser_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefBrowserCppToC::Get(self)->IsValid();
+
+  // Return type: bool
+  return _retval;
+}
+
 struct _cef_browser_host_t* CEF_CALLBACK
 browser_get_host(struct _cef_browser_t* self) {
   shutdown_checker::AssertNotShutdown();
@@ -30,8 +47,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowserHost> _retval = CefBrowserCppToC::Get(self)->GetHost();
@@ -46,8 +64,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefBrowserCppToC::Get(self)->CanGoBack();
@@ -62,8 +81,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserCppToC::Get(self)->GoBack();
@@ -75,8 +95,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefBrowserCppToC::Get(self)->CanGoForward();
@@ -91,8 +112,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserCppToC::Get(self)->GoForward();
@@ -104,8 +126,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefBrowserCppToC::Get(self)->IsLoading();
@@ -120,8 +143,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserCppToC::Get(self)->Reload();
@@ -133,8 +157,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserCppToC::Get(self)->ReloadIgnoreCache();
@@ -146,8 +171,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserCppToC::Get(self)->StopLoad();
@@ -159,8 +185,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefBrowserCppToC::Get(self)->GetIdentifier();
@@ -176,12 +203,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -197,8 +226,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefBrowserCppToC::Get(self)->IsPopup();
@@ -213,8 +243,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefBrowserCppToC::Get(self)->HasDocument();
@@ -230,8 +261,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefFrame> _retval = CefBrowserCppToC::Get(self)->GetMainFrame();
@@ -247,8 +279,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefFrame> _retval = CefBrowserCppToC::Get(self)->GetFocusedFrame();
@@ -258,14 +291,15 @@
 }
 
 struct _cef_frame_t* CEF_CALLBACK
-browser_get_frame_byident(struct _cef_browser_t* self, int64 identifier) {
+browser_get_frame_byident(struct _cef_browser_t* self, int64_t identifier) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefFrame> _retval =
@@ -282,8 +316,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Unverified params: name
 
   // Execute
@@ -300,8 +335,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefBrowserCppToC::Get(self)->GetFrameCount();
@@ -312,21 +348,23 @@
 
 void CEF_CALLBACK browser_get_frame_identifiers(struct _cef_browser_t* self,
                                                 size_t* identifiersCount,
-                                                int64* identifiers) {
+                                                int64_t* identifiers) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: identifiers; type: simple_vec_byref
   DCHECK(identifiersCount && (*identifiersCount == 0 || identifiers));
-  if (!identifiersCount || (*identifiersCount > 0 && !identifiers))
+  if (!identifiersCount || (*identifiersCount > 0 && !identifiers)) {
     return;
+  }
 
   // Translate param: identifiers; type: simple_vec_byref
-  std::vector<int64> identifiersList;
+  std::vector<int64_t> identifiersList;
   if (identifiersCount && *identifiersCount > 0 && identifiers) {
     for (size_t i = 0; i < *identifiersCount; ++i) {
       identifiersList.push_back(identifiers[i]);
@@ -354,12 +392,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: names; type: string_vec_byref
   DCHECK(names);
-  if (!names)
+  if (!names) {
     return;
+  }
 
   // Translate param: names; type: string_vec_byref
   std::vector<CefString> namesList;
@@ -378,6 +418,7 @@
 // CONSTRUCTOR - Do not edit by hand.
 
 CefBrowserCppToC::CefBrowserCppToC() {
+  GetStruct()->is_valid = browser_is_valid;
   GetStruct()->get_host = browser_get_host;
   GetStruct()->can_go_back = browser_can_go_back;
   GetStruct()->go_back = browser_go_back;
@@ -411,7 +452,7 @@
 CefCppToCRefCounted<CefBrowserCppToC, CefBrowser, cef_browser_t>::UnwrapDerived(
     CefWrapperType type,
     cef_browser_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/browser_cpptoc.h b/src/libcef_dll/cpptoc/browser_cpptoc.h
index 3e20603..1a10254 100644
--- a/src/libcef_dll/cpptoc/browser_cpptoc.h
+++ b/src/libcef_dll/cpptoc/browser_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=fe511e2e092abc4f91a953606be5872a7395a732$
+// $hash=01e044c521a174528e137e4b131d9df95875eb65$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_BROWSER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/browser_host_cpptoc.cc b/src/libcef_dll/cpptoc/browser_host_cpptoc.cc
index 124782d..2f30f8c 100644
--- a/src/libcef_dll/cpptoc/browser_host_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/browser_host_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=516b55b7ea53e2de2b096e85ba0eb83f2a2693f3$
+// $hash=a5c3b05b23c536eba7ce2e7242c3840e93729b29$
 //
 
 #include "libcef_dll/cpptoc/browser_host_cpptoc.h"
@@ -27,6 +27,7 @@
 #include "libcef_dll/ctocpp/pdf_print_callback_ctocpp.h"
 #include "libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h"
 #include "libcef_dll/shutdown_checker.h"
+#include "libcef_dll/template_util.h"
 #include "libcef_dll/transfer_util.h"
 
 // GLOBAL FUNCTIONS - Body may be edited by hand.
@@ -44,22 +45,34 @@
 
   // Verify param: windowInfo; type: struct_byref_const
   DCHECK(windowInfo);
-  if (!windowInfo)
+  if (!windowInfo) {
     return 0;
+  }
+  if (!template_util::has_valid_size(windowInfo)) {
+    DCHECK(false) << "invalid windowInfo->[base.]size";
+    return 0;
+  }
   // Verify param: settings; type: struct_byref_const
   DCHECK(settings);
-  if (!settings)
+  if (!settings) {
     return 0;
+  }
+  if (!template_util::has_valid_size(settings)) {
+    DCHECK(false) << "invalid settings->[base.]size";
+    return 0;
+  }
   // Unverified params: client, url, extra_info, request_context
 
   // Translate param: windowInfo; type: struct_byref_const
   CefWindowInfo windowInfoObj;
-  if (windowInfo)
+  if (windowInfo) {
     windowInfoObj.Set(*windowInfo, false);
+  }
   // Translate param: settings; type: struct_byref_const
   CefBrowserSettings settingsObj;
-  if (settings)
+  if (settings) {
     settingsObj.Set(*settings, false);
+  }
 
   // Execute
   bool _retval = CefBrowserHost::CreateBrowser(
@@ -84,22 +97,34 @@
 
   // Verify param: windowInfo; type: struct_byref_const
   DCHECK(windowInfo);
-  if (!windowInfo)
+  if (!windowInfo) {
     return NULL;
+  }
+  if (!template_util::has_valid_size(windowInfo)) {
+    DCHECK(false) << "invalid windowInfo->[base.]size";
+    return NULL;
+  }
   // Verify param: settings; type: struct_byref_const
   DCHECK(settings);
-  if (!settings)
+  if (!settings) {
     return NULL;
+  }
+  if (!template_util::has_valid_size(settings)) {
+    DCHECK(false) << "invalid settings->[base.]size";
+    return NULL;
+  }
   // Unverified params: client, url, extra_info, request_context
 
   // Translate param: windowInfo; type: struct_byref_const
   CefWindowInfo windowInfoObj;
-  if (windowInfo)
+  if (windowInfo) {
     windowInfoObj.Set(*windowInfo, false);
+  }
   // Translate param: settings; type: struct_byref_const
   CefBrowserSettings settingsObj;
-  if (settings)
+  if (settings) {
     settingsObj.Set(*settings, false);
+  }
 
   // Execute
   CefRefPtr<CefBrowser> _retval = CefBrowserHost::CreateBrowserSync(
@@ -122,8 +147,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowser> _retval = CefBrowserHostCppToC::Get(self)->GetBrowser();
@@ -139,8 +165,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->CloseBrowser(force_close ? true : false);
@@ -153,8 +180,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefBrowserHostCppToC::Get(self)->TryCloseBrowser();
@@ -170,8 +198,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->SetFocus(focus ? true : false);
@@ -184,8 +213,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return kNullWindowHandle;
+  }
 
   // Execute
   cef_window_handle_t _retval =
@@ -202,8 +232,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return kNullWindowHandle;
+  }
 
   // Execute
   cef_window_handle_t _retval =
@@ -219,8 +250,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefBrowserHostCppToC::Get(self)->HasView();
@@ -236,8 +268,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefClient> _retval = CefBrowserHostCppToC::Get(self)->GetClient();
@@ -253,8 +286,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefRequestContext> _retval =
@@ -264,6 +298,57 @@
   return CefRequestContextCppToC::Wrap(_retval);
 }
 
+int CEF_CALLBACK browser_host_can_zoom(struct _cef_browser_host_t* self,
+                                       cef_zoom_command_t command) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefBrowserHostCppToC::Get(self)->CanZoom(command);
+
+  // Return type: bool
+  return _retval;
+}
+
+void CEF_CALLBACK browser_host_zoom(struct _cef_browser_host_t* self,
+                                    cef_zoom_command_t command) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+
+  // Execute
+  CefBrowserHostCppToC::Get(self)->Zoom(command);
+}
+
+double CEF_CALLBACK
+browser_host_get_default_zoom_level(struct _cef_browser_host_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  double _retval = CefBrowserHostCppToC::Get(self)->GetDefaultZoomLevel();
+
+  // Return type: simple
+  return _retval;
+}
+
 double CEF_CALLBACK
 browser_host_get_zoom_level(struct _cef_browser_host_t* self) {
   shutdown_checker::AssertNotShutdown();
@@ -271,8 +356,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   double _retval = CefBrowserHostCppToC::Get(self)->GetZoomLevel();
@@ -288,8 +374,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->SetZoomLevel(zoomLevel);
@@ -301,23 +388,20 @@
                              const cef_string_t* title,
                              const cef_string_t* default_file_path,
                              cef_string_list_t accept_filters,
-                             int selected_accept_filter,
                              cef_run_file_dialog_callback_t* callback) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
-  // Verify param: selected_accept_filter; type: simple_byval
-  DCHECK_GE(selected_accept_filter, 0);
-  if (selected_accept_filter < 0)
-    return;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return;
+  }
   // Unverified params: title, default_file_path, accept_filters
 
   // Translate param: accept_filters; type: string_vec_byref_const
@@ -327,7 +411,7 @@
   // Execute
   CefBrowserHostCppToC::Get(self)->RunFileDialog(
       mode, CefString(title), CefString(default_file_path), accept_filtersList,
-      selected_accept_filter, CefRunFileDialogCallbackCToCpp::Wrap(callback));
+      CefRunFileDialogCallbackCToCpp::Wrap(callback));
 }
 
 void CEF_CALLBACK browser_host_start_download(struct _cef_browser_host_t* self,
@@ -337,12 +421,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: url; type: string_byref_const
   DCHECK(url);
-  if (!url)
+  if (!url) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->StartDownload(CefString(url));
@@ -352,7 +438,7 @@
 browser_host_download_image(struct _cef_browser_host_t* self,
                             const cef_string_t* image_url,
                             int is_favicon,
-                            uint32 max_image_size,
+                            uint32_t max_image_size,
                             int bypass_cache,
                             cef_download_image_callback_t* callback) {
   shutdown_checker::AssertNotShutdown();
@@ -360,16 +446,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: image_url; type: string_byref_const
   DCHECK(image_url);
-  if (!image_url)
+  if (!image_url) {
     return;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->DownloadImage(
@@ -384,8 +473,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->Print();
@@ -401,22 +491,30 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: path; type: string_byref_const
   DCHECK(path);
-  if (!path)
+  if (!path) {
     return;
+  }
   // Verify param: settings; type: struct_byref_const
   DCHECK(settings);
-  if (!settings)
+  if (!settings) {
     return;
+  }
+  if (!template_util::has_valid_size(settings)) {
+    DCHECK(false) << "invalid settings->[base.]size";
+    return;
+  }
   // Unverified params: callback
 
   // Translate param: settings; type: struct_byref_const
   CefPdfPrintSettings settingsObj;
-  if (settings)
+  if (settings) {
     settingsObj.Set(*settings, false);
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->PrintToPDF(
@@ -424,7 +522,6 @@
 }
 
 void CEF_CALLBACK browser_host_find(struct _cef_browser_host_t* self,
-                                    int identifier,
                                     const cef_string_t* searchText,
                                     int forward,
                                     int matchCase,
@@ -434,17 +531,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: searchText; type: string_byref_const
   DCHECK(searchText);
-  if (!searchText)
+  if (!searchText) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->Find(
-      identifier, CefString(searchText), forward ? true : false,
-      matchCase ? true : false, findNext ? true : false);
+      CefString(searchText), forward ? true : false, matchCase ? true : false,
+      findNext ? true : false);
 }
 
 void CEF_CALLBACK browser_host_stop_finding(struct _cef_browser_host_t* self,
@@ -454,8 +553,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->StopFinding(clearSelection ? true : false);
@@ -472,18 +572,21 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: windowInfo, client, settings, inspect_element_at
 
   // Translate param: windowInfo; type: struct_byref_const
   CefWindowInfo windowInfoObj;
-  if (windowInfo)
+  if (windowInfo) {
     windowInfoObj.Set(*windowInfo, false);
+  }
   // Translate param: settings; type: struct_byref_const
   CefBrowserSettings settingsObj;
-  if (settings)
+  if (settings) {
     settingsObj.Set(*settings, false);
+  }
   // Translate param: inspect_element_at; type: simple_byref_const
   CefPoint inspect_element_atVal =
       inspect_element_at ? *inspect_element_at : CefPoint();
@@ -501,8 +604,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->CloseDevTools();
@@ -514,8 +618,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefBrowserHostCppToC::Get(self)->HasDevTools();
@@ -533,12 +638,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: message; type: simple_byaddr
   DCHECK(message);
-  if (!message)
+  if (!message) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefBrowserHostCppToC::Get(self)->SendDevToolsMessage(
@@ -558,12 +665,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: method; type: string_byref_const
   DCHECK(method);
-  if (!method)
+  if (!method) {
     return 0;
+  }
   // Unverified params: params
 
   // Execute
@@ -583,12 +692,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: observer; type: refptr_diff
   DCHECK(observer);
-  if (!observer)
+  if (!observer) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefRegistration> _retval =
@@ -608,12 +719,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: visitor; type: refptr_diff
   DCHECK(visitor);
-  if (!visitor)
+  if (!visitor) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->GetNavigationEntries(
@@ -622,39 +735,6 @@
 }
 
 void CEF_CALLBACK
-browser_host_set_mouse_cursor_change_disabled(struct _cef_browser_host_t* self,
-                                              int disabled) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return;
-
-  // Execute
-  CefBrowserHostCppToC::Get(self)->SetMouseCursorChangeDisabled(
-      disabled ? true : false);
-}
-
-int CEF_CALLBACK
-browser_host_is_mouse_cursor_change_disabled(struct _cef_browser_host_t* self) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return 0;
-
-  // Execute
-  bool _retval = CefBrowserHostCppToC::Get(self)->IsMouseCursorChangeDisabled();
-
-  // Return type: bool
-  return _retval;
-}
-
-void CEF_CALLBACK
 browser_host_replace_misspelling(struct _cef_browser_host_t* self,
                                  const cef_string_t* word) {
   shutdown_checker::AssertNotShutdown();
@@ -662,12 +742,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: word; type: string_byref_const
   DCHECK(word);
-  if (!word)
+  if (!word) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->ReplaceMisspelling(CefString(word));
@@ -681,12 +763,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: word; type: string_byref_const
   DCHECK(word);
-  if (!word)
+  if (!word) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->AddWordToDictionary(CefString(word));
@@ -699,8 +783,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefBrowserHostCppToC::Get(self)->IsWindowRenderingDisabled();
@@ -715,8 +800,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->WasResized();
@@ -729,8 +815,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->WasHidden(hidden ? true : false);
@@ -743,8 +830,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->NotifyScreenInfoChanged();
@@ -757,8 +845,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->Invalidate(type);
@@ -771,40 +860,40 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->SendExternalBeginFrame();
 }
 
-void CEF_CALLBACK
-browser_host_send_key_event(struct _cef_browser_host_t* self,
-                            const struct _cef_key_event_t* event) {
+void CEF_CALLBACK browser_host_send_key_event(struct _cef_browser_host_t* self,
+                                              const cef_key_event_t* event) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
-  // Verify param: event; type: struct_byref_const
+  }
+  // Verify param: event; type: simple_byref_const
   DCHECK(event);
-  if (!event)
+  if (!event) {
     return;
+  }
 
-  // Translate param: event; type: struct_byref_const
-  CefKeyEvent eventObj;
-  if (event)
-    eventObj.Set(*event, false);
+  // Translate param: event; type: simple_byref_const
+  CefKeyEvent eventVal = event ? *event : CefKeyEvent();
 
   // Execute
-  CefBrowserHostCppToC::Get(self)->SendKeyEvent(eventObj);
+  CefBrowserHostCppToC::Get(self)->SendKeyEvent(eventVal);
 }
 
 void CEF_CALLBACK
 browser_host_send_mouse_click_event(struct _cef_browser_host_t* self,
-                                    const struct _cef_mouse_event_t* event,
+                                    const cef_mouse_event_t* event,
                                     cef_mouse_button_type_t type,
                                     int mouseUp,
                                     int clickCount) {
@@ -813,52 +902,52 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
-  // Verify param: event; type: struct_byref_const
+  }
+  // Verify param: event; type: simple_byref_const
   DCHECK(event);
-  if (!event)
+  if (!event) {
     return;
+  }
 
-  // Translate param: event; type: struct_byref_const
-  CefMouseEvent eventObj;
-  if (event)
-    eventObj.Set(*event, false);
+  // Translate param: event; type: simple_byref_const
+  CefMouseEvent eventVal = event ? *event : CefMouseEvent();
 
   // Execute
   CefBrowserHostCppToC::Get(self)->SendMouseClickEvent(
-      eventObj, type, mouseUp ? true : false, clickCount);
+      eventVal, type, mouseUp ? true : false, clickCount);
 }
 
 void CEF_CALLBACK
 browser_host_send_mouse_move_event(struct _cef_browser_host_t* self,
-                                   const struct _cef_mouse_event_t* event,
+                                   const cef_mouse_event_t* event,
                                    int mouseLeave) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
-  // Verify param: event; type: struct_byref_const
+  }
+  // Verify param: event; type: simple_byref_const
   DCHECK(event);
-  if (!event)
+  if (!event) {
     return;
+  }
 
-  // Translate param: event; type: struct_byref_const
-  CefMouseEvent eventObj;
-  if (event)
-    eventObj.Set(*event, false);
+  // Translate param: event; type: simple_byref_const
+  CefMouseEvent eventVal = event ? *event : CefMouseEvent();
 
   // Execute
   CefBrowserHostCppToC::Get(self)->SendMouseMoveEvent(
-      eventObj, mouseLeave ? true : false);
+      eventVal, mouseLeave ? true : false);
 }
 
 void CEF_CALLBACK
 browser_host_send_mouse_wheel_event(struct _cef_browser_host_t* self,
-                                    const struct _cef_mouse_event_t* event,
+                                    const cef_mouse_event_t* event,
                                     int deltaX,
                                     int deltaY) {
   shutdown_checker::AssertNotShutdown();
@@ -866,59 +955,45 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
-  // Verify param: event; type: struct_byref_const
+  }
+  // Verify param: event; type: simple_byref_const
   DCHECK(event);
-  if (!event)
+  if (!event) {
     return;
+  }
 
-  // Translate param: event; type: struct_byref_const
-  CefMouseEvent eventObj;
-  if (event)
-    eventObj.Set(*event, false);
+  // Translate param: event; type: simple_byref_const
+  CefMouseEvent eventVal = event ? *event : CefMouseEvent();
 
   // Execute
-  CefBrowserHostCppToC::Get(self)->SendMouseWheelEvent(eventObj, deltaX,
+  CefBrowserHostCppToC::Get(self)->SendMouseWheelEvent(eventVal, deltaX,
                                                        deltaY);
 }
 
 void CEF_CALLBACK
 browser_host_send_touch_event(struct _cef_browser_host_t* self,
-                              const struct _cef_touch_event_t* event) {
+                              const cef_touch_event_t* event) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
-  // Verify param: event; type: struct_byref_const
+  }
+  // Verify param: event; type: simple_byref_const
   DCHECK(event);
-  if (!event)
+  if (!event) {
     return;
+  }
 
-  // Translate param: event; type: struct_byref_const
-  CefTouchEvent eventObj;
-  if (event)
-    eventObj.Set(*event, false);
+  // Translate param: event; type: simple_byref_const
+  CefTouchEvent eventVal = event ? *event : CefTouchEvent();
 
   // Execute
-  CefBrowserHostCppToC::Get(self)->SendTouchEvent(eventObj);
-}
-
-void CEF_CALLBACK
-browser_host_send_focus_event(struct _cef_browser_host_t* self, int setFocus) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return;
-
-  // Execute
-  CefBrowserHostCppToC::Get(self)->SendFocusEvent(setFocus ? true : false);
+  CefBrowserHostCppToC::Get(self)->SendTouchEvent(eventVal);
 }
 
 void CEF_CALLBACK
@@ -928,8 +1003,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->SendCaptureLostEvent();
@@ -942,8 +1018,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->NotifyMoveOrResizeStarted();
@@ -956,8 +1033,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefBrowserHostCppToC::Get(self)->GetWindowlessFrameRate();
@@ -974,8 +1052,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->SetWindowlessFrameRate(frame_rate);
@@ -993,16 +1072,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: replacement_range; type: simple_byref_const
   DCHECK(replacement_range);
-  if (!replacement_range)
+  if (!replacement_range) {
     return;
+  }
   // Verify param: selection_range; type: simple_byref_const
   DCHECK(selection_range);
-  if (!selection_range)
+  if (!selection_range) {
     return;
+  }
   // Unverified params: text, underlines
 
   // Translate param: underlines; type: simple_vec_byref_const
@@ -1035,12 +1117,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: replacement_range; type: simple_byref_const
   DCHECK(replacement_range);
-  if (!replacement_range)
+  if (!replacement_range) {
     return;
+  }
   // Unverified params: text
 
   // Translate param: replacement_range; type: simple_byref_const
@@ -1060,8 +1144,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->ImeFinishComposingText(
@@ -1075,8 +1160,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->ImeCancelComposition();
@@ -1085,57 +1171,58 @@
 void CEF_CALLBACK
 browser_host_drag_target_drag_enter(struct _cef_browser_host_t* self,
                                     struct _cef_drag_data_t* drag_data,
-                                    const struct _cef_mouse_event_t* event,
+                                    const cef_mouse_event_t* event,
                                     cef_drag_operations_mask_t allowed_ops) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: drag_data; type: refptr_same
   DCHECK(drag_data);
-  if (!drag_data)
+  if (!drag_data) {
     return;
-  // Verify param: event; type: struct_byref_const
+  }
+  // Verify param: event; type: simple_byref_const
   DCHECK(event);
-  if (!event)
+  if (!event) {
     return;
+  }
 
-  // Translate param: event; type: struct_byref_const
-  CefMouseEvent eventObj;
-  if (event)
-    eventObj.Set(*event, false);
+  // Translate param: event; type: simple_byref_const
+  CefMouseEvent eventVal = event ? *event : CefMouseEvent();
 
   // Execute
   CefBrowserHostCppToC::Get(self)->DragTargetDragEnter(
-      CefDragDataCppToC::Unwrap(drag_data), eventObj, allowed_ops);
+      CefDragDataCppToC::Unwrap(drag_data), eventVal, allowed_ops);
 }
 
 void CEF_CALLBACK
 browser_host_drag_target_drag_over(struct _cef_browser_host_t* self,
-                                   const struct _cef_mouse_event_t* event,
+                                   const cef_mouse_event_t* event,
                                    cef_drag_operations_mask_t allowed_ops) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
-  // Verify param: event; type: struct_byref_const
+  }
+  // Verify param: event; type: simple_byref_const
   DCHECK(event);
-  if (!event)
+  if (!event) {
     return;
+  }
 
-  // Translate param: event; type: struct_byref_const
-  CefMouseEvent eventObj;
-  if (event)
-    eventObj.Set(*event, false);
+  // Translate param: event; type: simple_byref_const
+  CefMouseEvent eventVal = event ? *event : CefMouseEvent();
 
   // Execute
-  CefBrowserHostCppToC::Get(self)->DragTargetDragOver(eventObj, allowed_ops);
+  CefBrowserHostCppToC::Get(self)->DragTargetDragOver(eventVal, allowed_ops);
 }
 
 void CEF_CALLBACK
@@ -1145,8 +1232,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->DragTargetDragLeave();
@@ -1154,26 +1242,26 @@
 
 void CEF_CALLBACK
 browser_host_drag_target_drop(struct _cef_browser_host_t* self,
-                              const struct _cef_mouse_event_t* event) {
+                              const cef_mouse_event_t* event) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
-  // Verify param: event; type: struct_byref_const
+  }
+  // Verify param: event; type: simple_byref_const
   DCHECK(event);
-  if (!event)
+  if (!event) {
     return;
+  }
 
-  // Translate param: event; type: struct_byref_const
-  CefMouseEvent eventObj;
-  if (event)
-    eventObj.Set(*event, false);
+  // Translate param: event; type: simple_byref_const
+  CefMouseEvent eventVal = event ? *event : CefMouseEvent();
 
   // Execute
-  CefBrowserHostCppToC::Get(self)->DragTargetDrop(eventObj);
+  CefBrowserHostCppToC::Get(self)->DragTargetDrop(eventVal);
 }
 
 void CEF_CALLBACK
@@ -1186,8 +1274,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->DragSourceEndedAt(x, y, op);
@@ -1200,8 +1289,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->DragSourceSystemDragEnded();
@@ -1214,8 +1304,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefNavigationEntry> _retval =
@@ -1233,8 +1324,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->SetAccessibilityState(accessibility_state);
@@ -1250,16 +1342,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: min_size; type: simple_byref_const
   DCHECK(min_size);
-  if (!min_size)
+  if (!min_size) {
     return;
+  }
   // Verify param: max_size; type: simple_byref_const
   DCHECK(max_size);
-  if (!max_size)
+  if (!max_size) {
     return;
+  }
 
   // Translate param: min_size; type: simple_byref_const
   CefSize min_sizeVal = min_size ? *min_size : CefSize();
@@ -1278,8 +1373,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefExtension> _retval =
@@ -1296,8 +1392,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefBrowserHostCppToC::Get(self)->IsBackgroundHost();
@@ -1313,8 +1410,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserHostCppToC::Get(self)->SetAudioMuted(mute ? true : false);
@@ -1326,8 +1424,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefBrowserHostCppToC::Get(self)->IsAudioMuted();
@@ -1336,6 +1435,77 @@
   return _retval;
 }
 
+int CEF_CALLBACK browser_host_is_fullscreen(struct _cef_browser_host_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefBrowserHostCppToC::Get(self)->IsFullscreen();
+
+  // Return type: bool
+  return _retval;
+}
+
+void CEF_CALLBACK browser_host_exit_fullscreen(struct _cef_browser_host_t* self,
+                                               int will_cause_resize) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+
+  // Execute
+  CefBrowserHostCppToC::Get(self)->ExitFullscreen(will_cause_resize ? true
+                                                                    : false);
+}
+
+int CEF_CALLBACK
+browser_host_can_execute_chrome_command(struct _cef_browser_host_t* self,
+                                        int command_id) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval =
+      CefBrowserHostCppToC::Get(self)->CanExecuteChromeCommand(command_id);
+
+  // Return type: bool
+  return _retval;
+}
+
+void CEF_CALLBACK
+browser_host_execute_chrome_command(struct _cef_browser_host_t* self,
+                                    int command_id,
+                                    cef_window_open_disposition_t disposition) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+
+  // Execute
+  CefBrowserHostCppToC::Get(self)->ExecuteChromeCommand(command_id,
+                                                        disposition);
+}
+
 }  // namespace
 
 // CONSTRUCTOR - Do not edit by hand.
@@ -1350,6 +1520,9 @@
   GetStruct()->has_view = browser_host_has_view;
   GetStruct()->get_client = browser_host_get_client;
   GetStruct()->get_request_context = browser_host_get_request_context;
+  GetStruct()->can_zoom = browser_host_can_zoom;
+  GetStruct()->zoom = browser_host_zoom;
+  GetStruct()->get_default_zoom_level = browser_host_get_default_zoom_level;
   GetStruct()->get_zoom_level = browser_host_get_zoom_level;
   GetStruct()->set_zoom_level = browser_host_set_zoom_level;
   GetStruct()->run_file_dialog = browser_host_run_file_dialog;
@@ -1367,10 +1540,6 @@
   GetStruct()->add_dev_tools_message_observer =
       browser_host_add_dev_tools_message_observer;
   GetStruct()->get_navigation_entries = browser_host_get_navigation_entries;
-  GetStruct()->set_mouse_cursor_change_disabled =
-      browser_host_set_mouse_cursor_change_disabled;
-  GetStruct()->is_mouse_cursor_change_disabled =
-      browser_host_is_mouse_cursor_change_disabled;
   GetStruct()->replace_misspelling = browser_host_replace_misspelling;
   GetStruct()->add_word_to_dictionary = browser_host_add_word_to_dictionary;
   GetStruct()->is_window_rendering_disabled =
@@ -1387,7 +1556,6 @@
   GetStruct()->send_mouse_move_event = browser_host_send_mouse_move_event;
   GetStruct()->send_mouse_wheel_event = browser_host_send_mouse_wheel_event;
   GetStruct()->send_touch_event = browser_host_send_touch_event;
-  GetStruct()->send_focus_event = browser_host_send_focus_event;
   GetStruct()->send_capture_lost_event = browser_host_send_capture_lost_event;
   GetStruct()->notify_move_or_resize_started =
       browser_host_notify_move_or_resize_started;
@@ -1415,6 +1583,11 @@
   GetStruct()->is_background_host = browser_host_is_background_host;
   GetStruct()->set_audio_muted = browser_host_set_audio_muted;
   GetStruct()->is_audio_muted = browser_host_is_audio_muted;
+  GetStruct()->is_fullscreen = browser_host_is_fullscreen;
+  GetStruct()->exit_fullscreen = browser_host_exit_fullscreen;
+  GetStruct()->can_execute_chrome_command =
+      browser_host_can_execute_chrome_command;
+  GetStruct()->execute_chrome_command = browser_host_execute_chrome_command;
 }
 
 // DESTRUCTOR - Do not edit by hand.
@@ -1427,7 +1600,7 @@
 CefRefPtr<CefBrowserHost>
 CefCppToCRefCounted<CefBrowserHostCppToC, CefBrowserHost, cef_browser_host_t>::
     UnwrapDerived(CefWrapperType type, cef_browser_host_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/browser_host_cpptoc.h b/src/libcef_dll/cpptoc/browser_host_cpptoc.h
index d901588..2f88bb3 100644
--- a/src/libcef_dll/cpptoc/browser_host_cpptoc.h
+++ b/src/libcef_dll/cpptoc/browser_host_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=749d0e8cba77daca947e37b9f868778c2cb6f011$
+// $hash=e51f496e40bd2b3b9573d2ca084e578bb1df1407$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_BROWSER_HOST_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/browser_process_handler_cpptoc.cc b/src/libcef_dll/cpptoc/browser_process_handler_cpptoc.cc
index 226adc9..3e29a36 100644
--- a/src/libcef_dll/cpptoc/browser_process_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/browser_process_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,25 +9,51 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6c70366a25d8ad81d0adf85e2a867906f90ee695$
+// $hash=5b13f3f4cac21266cab10ca5153ccebe99d6869b$
 //
 
 #include "libcef_dll/cpptoc/browser_process_handler_cpptoc.h"
-#include "libcef_dll/cpptoc/print_handler_cpptoc.h"
+#include "libcef_dll/cpptoc/client_cpptoc.h"
 #include "libcef_dll/ctocpp/command_line_ctocpp.h"
-#include "libcef_dll/ctocpp/list_value_ctocpp.h"
+#include "libcef_dll/ctocpp/preference_registrar_ctocpp.h"
 
 namespace {
 
 // MEMBER FUNCTIONS - Body may be edited by hand.
 
+void CEF_CALLBACK browser_process_handler_on_register_custom_preferences(
+    struct _cef_browser_process_handler_t* self,
+    cef_preferences_type_t type,
+    struct _cef_preference_registrar_t* registrar) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: registrar; type: rawptr_diff
+  DCHECK(registrar);
+  if (!registrar) {
+    return;
+  }
+
+  // Translate param: registrar; type: rawptr_diff
+  CefOwnPtr<CefPreferenceRegistrar> registrarPtr(
+      CefPreferenceRegistrarCToCpp::Wrap(registrar));
+
+  // Execute
+  CefBrowserProcessHandlerCppToC::Get(self)->OnRegisterCustomPreferences(
+      type, registrarPtr.get());
+}
+
 void CEF_CALLBACK browser_process_handler_on_context_initialized(
     struct _cef_browser_process_handler_t* self) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserProcessHandlerCppToC::Get(self)->OnContextInitialized();
@@ -39,81 +65,66 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: command_line; type: refptr_diff
   DCHECK(command_line);
-  if (!command_line)
+  if (!command_line) {
     return;
+  }
 
   // Execute
   CefBrowserProcessHandlerCppToC::Get(self)->OnBeforeChildProcessLaunch(
       CefCommandLineCToCpp::Wrap(command_line));
 }
 
-void CEF_CALLBACK browser_process_handler_on_render_process_thread_created(
-    struct _cef_browser_process_handler_t* self,
-    struct _cef_list_value_t* extra_info) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return;
-  // Verify param: extra_info; type: refptr_diff
-  DCHECK(extra_info);
-  if (!extra_info)
-    return;
-
-  // Execute
-  CefBrowserProcessHandlerCppToC::Get(self)->OnRenderProcessThreadCreated(
-      CefListValueCToCpp::Wrap(extra_info));
-}
-
-struct _cef_print_handler_t* CEF_CALLBACK
-browser_process_handler_get_print_handler(
-    struct _cef_browser_process_handler_t* self) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return NULL;
-
-  // Execute
-  CefRefPtr<CefPrintHandler> _retval =
-      CefBrowserProcessHandlerCppToC::Get(self)->GetPrintHandler();
-
-  // Return type: refptr_same
-  return CefPrintHandlerCppToC::Wrap(_retval);
-}
-
 void CEF_CALLBACK browser_process_handler_on_schedule_message_pump_work(
     struct _cef_browser_process_handler_t* self,
-    int64 delay_ms) {
+    int64_t delay_ms) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserProcessHandlerCppToC::Get(self)->OnScheduleMessagePumpWork(
       delay_ms);
 }
 
+struct _cef_client_t* CEF_CALLBACK browser_process_handler_get_default_client(
+    struct _cef_browser_process_handler_t* self) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefClient> _retval =
+      CefBrowserProcessHandlerCppToC::Get(self)->GetDefaultClient();
+
+  // Return type: refptr_same
+  return CefClientCppToC::Wrap(_retval);
+}
+
 }  // namespace
 
 // CONSTRUCTOR - Do not edit by hand.
 
 CefBrowserProcessHandlerCppToC::CefBrowserProcessHandlerCppToC() {
+  GetStruct()->on_register_custom_preferences =
+      browser_process_handler_on_register_custom_preferences;
   GetStruct()->on_context_initialized =
       browser_process_handler_on_context_initialized;
   GetStruct()->on_before_child_process_launch =
       browser_process_handler_on_before_child_process_launch;
-  GetStruct()->on_render_process_thread_created =
-      browser_process_handler_on_render_process_thread_created;
-  GetStruct()->get_print_handler = browser_process_handler_get_print_handler;
   GetStruct()->on_schedule_message_pump_work =
       browser_process_handler_on_schedule_message_pump_work;
+  GetStruct()->get_default_client = browser_process_handler_get_default_client;
 }
 
 // DESTRUCTOR - Do not edit by hand.
@@ -127,7 +138,7 @@
     cef_browser_process_handler_t>::UnwrapDerived(CefWrapperType type,
                                                   cef_browser_process_handler_t*
                                                       s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/browser_process_handler_cpptoc.h b/src/libcef_dll/cpptoc/browser_process_handler_cpptoc.h
index bfc8b05..19b902d 100644
--- a/src/libcef_dll/cpptoc/browser_process_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/browser_process_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7664d494a2e87495b34430b814474f3e4031c9a5$
+// $hash=508373dbbfcb411f218ad9688d56b49380d8ca75$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_BROWSER_PROCESS_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/callback_cpptoc.cc b/src/libcef_dll/cpptoc/callback_cpptoc.cc
index 54bd00c..daee6ee 100644
--- a/src/libcef_dll/cpptoc/callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=23c54bbef1c4d4e13b46f746df1d4123d2378548$
+// $hash=9040a3e4e5208ec11e2b29195a0bfa1c3f5ecffa$
 //
 
 #include "libcef_dll/cpptoc/callback_cpptoc.h"
@@ -25,8 +25,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefCallbackCppToC::Get(self)->Continue();
@@ -38,8 +39,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefCallbackCppToC::Get(self)->Cancel();
@@ -64,7 +66,7 @@
 CefRefPtr<CefCallback>
 CefCppToCRefCounted<CefCallbackCppToC, CefCallback, cef_callback_t>::
     UnwrapDerived(CefWrapperType type, cef_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/callback_cpptoc.h b/src/libcef_dll/cpptoc/callback_cpptoc.h
index c978585..611c202 100644
--- a/src/libcef_dll/cpptoc/callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3be29effc92de5236544395b9b513cf5e74ae194$
+// $hash=f0c92901c6462ad03d3c95c0ba92129784c808e1$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/client_cpptoc.cc b/src/libcef_dll/cpptoc/client_cpptoc.cc
index 9e54e6a..01750b8 100644
--- a/src/libcef_dll/cpptoc/client_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/client_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,11 +9,12 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=04cee2c6a1910d7084c556f1bde99ba971b354d2$
+// $hash=f6d88f6c8228166318cc64924f6f64036b2eb44f$
 //
 
 #include "libcef_dll/cpptoc/client_cpptoc.h"
 #include "libcef_dll/cpptoc/audio_handler_cpptoc.h"
+#include "libcef_dll/cpptoc/command_handler_cpptoc.h"
 #include "libcef_dll/cpptoc/context_menu_handler_cpptoc.h"
 #include "libcef_dll/cpptoc/dialog_handler_cpptoc.h"
 #include "libcef_dll/cpptoc/display_handler_cpptoc.h"
@@ -21,10 +22,13 @@
 #include "libcef_dll/cpptoc/drag_handler_cpptoc.h"
 #include "libcef_dll/cpptoc/find_handler_cpptoc.h"
 #include "libcef_dll/cpptoc/focus_handler_cpptoc.h"
+#include "libcef_dll/cpptoc/frame_handler_cpptoc.h"
 #include "libcef_dll/cpptoc/jsdialog_handler_cpptoc.h"
 #include "libcef_dll/cpptoc/keyboard_handler_cpptoc.h"
 #include "libcef_dll/cpptoc/life_span_handler_cpptoc.h"
 #include "libcef_dll/cpptoc/load_handler_cpptoc.h"
+#include "libcef_dll/cpptoc/permission_handler_cpptoc.h"
+#include "libcef_dll/cpptoc/print_handler_cpptoc.h"
 #include "libcef_dll/cpptoc/render_handler_cpptoc.h"
 #include "libcef_dll/cpptoc/request_handler_cpptoc.h"
 #include "libcef_dll/ctocpp/browser_ctocpp.h"
@@ -40,8 +44,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefAudioHandler> _retval =
@@ -51,13 +56,31 @@
   return CefAudioHandlerCppToC::Wrap(_retval);
 }
 
+struct _cef_command_handler_t* CEF_CALLBACK
+client_get_command_handler(struct _cef_client_t* self) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefCommandHandler> _retval =
+      CefClientCppToC::Get(self)->GetCommandHandler();
+
+  // Return type: refptr_same
+  return CefCommandHandlerCppToC::Wrap(_retval);
+}
+
 struct _cef_context_menu_handler_t* CEF_CALLBACK
 client_get_context_menu_handler(struct _cef_client_t* self) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefContextMenuHandler> _retval =
@@ -72,8 +95,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDialogHandler> _retval =
@@ -88,8 +112,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDisplayHandler> _retval =
@@ -104,8 +129,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDownloadHandler> _retval =
@@ -120,8 +146,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDragHandler> _retval =
@@ -136,8 +163,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefFindHandler> _retval =
@@ -152,8 +180,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefFocusHandler> _retval =
@@ -163,13 +192,48 @@
   return CefFocusHandlerCppToC::Wrap(_retval);
 }
 
+struct _cef_frame_handler_t* CEF_CALLBACK
+client_get_frame_handler(struct _cef_client_t* self) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefFrameHandler> _retval =
+      CefClientCppToC::Get(self)->GetFrameHandler();
+
+  // Return type: refptr_same
+  return CefFrameHandlerCppToC::Wrap(_retval);
+}
+
+struct _cef_permission_handler_t* CEF_CALLBACK
+client_get_permission_handler(struct _cef_client_t* self) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefPermissionHandler> _retval =
+      CefClientCppToC::Get(self)->GetPermissionHandler();
+
+  // Return type: refptr_same
+  return CefPermissionHandlerCppToC::Wrap(_retval);
+}
+
 struct _cef_jsdialog_handler_t* CEF_CALLBACK
 client_get_jsdialog_handler(struct _cef_client_t* self) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefJSDialogHandler> _retval =
@@ -184,8 +248,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefKeyboardHandler> _retval =
@@ -200,8 +265,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefLifeSpanHandler> _retval =
@@ -216,8 +282,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefLoadHandler> _retval =
@@ -227,13 +294,31 @@
   return CefLoadHandlerCppToC::Wrap(_retval);
 }
 
+struct _cef_print_handler_t* CEF_CALLBACK
+client_get_print_handler(struct _cef_client_t* self) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefPrintHandler> _retval =
+      CefClientCppToC::Get(self)->GetPrintHandler();
+
+  // Return type: refptr_same
+  return CefPrintHandlerCppToC::Wrap(_retval);
+}
+
 struct _cef_render_handler_t* CEF_CALLBACK
 client_get_render_handler(struct _cef_client_t* self) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefRenderHandler> _retval =
@@ -248,8 +333,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefRequestHandler> _retval =
@@ -268,20 +354,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return 0;
+  }
   // Verify param: message; type: refptr_diff
   DCHECK(message);
-  if (!message)
+  if (!message) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefClientCppToC::Get(self)->OnProcessMessageReceived(
@@ -298,6 +388,7 @@
 
 CefClientCppToC::CefClientCppToC() {
   GetStruct()->get_audio_handler = client_get_audio_handler;
+  GetStruct()->get_command_handler = client_get_command_handler;
   GetStruct()->get_context_menu_handler = client_get_context_menu_handler;
   GetStruct()->get_dialog_handler = client_get_dialog_handler;
   GetStruct()->get_display_handler = client_get_display_handler;
@@ -305,10 +396,13 @@
   GetStruct()->get_drag_handler = client_get_drag_handler;
   GetStruct()->get_find_handler = client_get_find_handler;
   GetStruct()->get_focus_handler = client_get_focus_handler;
+  GetStruct()->get_frame_handler = client_get_frame_handler;
+  GetStruct()->get_permission_handler = client_get_permission_handler;
   GetStruct()->get_jsdialog_handler = client_get_jsdialog_handler;
   GetStruct()->get_keyboard_handler = client_get_keyboard_handler;
   GetStruct()->get_life_span_handler = client_get_life_span_handler;
   GetStruct()->get_load_handler = client_get_load_handler;
+  GetStruct()->get_print_handler = client_get_print_handler;
   GetStruct()->get_render_handler = client_get_render_handler;
   GetStruct()->get_request_handler = client_get_request_handler;
   GetStruct()->on_process_message_received = client_on_process_message_received;
@@ -323,7 +417,7 @@
 CefCppToCRefCounted<CefClientCppToC, CefClient, cef_client_t>::UnwrapDerived(
     CefWrapperType type,
     cef_client_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/client_cpptoc.h b/src/libcef_dll/cpptoc/client_cpptoc.h
index 788f65d..3898b87 100644
--- a/src/libcef_dll/cpptoc/client_cpptoc.h
+++ b/src/libcef_dll/cpptoc/client_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6e9a6091b190b39ce9f39b4464d19f96bf5e52a6$
+// $hash=6dd8a3977d8a7d75da7399a9c15a160afbfcf744$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_CLIENT_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/command_handler_cpptoc.cc b/src/libcef_dll/cpptoc/command_handler_cpptoc.cc
new file mode 100644
index 0000000..6d9eb8d
--- /dev/null
+++ b/src/libcef_dll/cpptoc/command_handler_cpptoc.cc
@@ -0,0 +1,180 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=04f92bf7dfa4cfeec409e2418f69e63beff276ff$
+//
+
+#include "libcef_dll/cpptoc/command_handler_cpptoc.h"
+#include "libcef_dll/ctocpp/browser_ctocpp.h"
+#include "libcef_dll/shutdown_checker.h"
+
+namespace {
+
+// MEMBER FUNCTIONS - Body may be edited by hand.
+
+int CEF_CALLBACK
+command_handler_on_chrome_command(struct _cef_command_handler_t* self,
+                                  cef_browser_t* browser,
+                                  int command_id,
+                                  cef_window_open_disposition_t disposition) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefCommandHandlerCppToC::Get(self)->OnChromeCommand(
+      CefBrowserCToCpp::Wrap(browser), command_id, disposition);
+
+  // Return type: bool
+  return _retval;
+}
+
+int CEF_CALLBACK command_handler_is_chrome_app_menu_item_visible(
+    struct _cef_command_handler_t* self,
+    cef_browser_t* browser,
+    int command_id) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefCommandHandlerCppToC::Get(self)->IsChromeAppMenuItemVisible(
+      CefBrowserCToCpp::Wrap(browser), command_id);
+
+  // Return type: bool
+  return _retval;
+}
+
+int CEF_CALLBACK command_handler_is_chrome_app_menu_item_enabled(
+    struct _cef_command_handler_t* self,
+    cef_browser_t* browser,
+    int command_id) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefCommandHandlerCppToC::Get(self)->IsChromeAppMenuItemEnabled(
+      CefBrowserCToCpp::Wrap(browser), command_id);
+
+  // Return type: bool
+  return _retval;
+}
+
+int CEF_CALLBACK command_handler_is_chrome_page_action_icon_visible(
+    struct _cef_command_handler_t* self,
+    cef_chrome_page_action_icon_type_t icon_type) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval =
+      CefCommandHandlerCppToC::Get(self)->IsChromePageActionIconVisible(
+          icon_type);
+
+  // Return type: bool
+  return _retval;
+}
+
+int CEF_CALLBACK command_handler_is_chrome_toolbar_button_visible(
+    struct _cef_command_handler_t* self,
+    cef_chrome_toolbar_button_type_t button_type) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval =
+      CefCommandHandlerCppToC::Get(self)->IsChromeToolbarButtonVisible(
+          button_type);
+
+  // Return type: bool
+  return _retval;
+}
+
+}  // namespace
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefCommandHandlerCppToC::CefCommandHandlerCppToC() {
+  GetStruct()->on_chrome_command = command_handler_on_chrome_command;
+  GetStruct()->is_chrome_app_menu_item_visible =
+      command_handler_is_chrome_app_menu_item_visible;
+  GetStruct()->is_chrome_app_menu_item_enabled =
+      command_handler_is_chrome_app_menu_item_enabled;
+  GetStruct()->is_chrome_page_action_icon_visible =
+      command_handler_is_chrome_page_action_icon_visible;
+  GetStruct()->is_chrome_toolbar_button_visible =
+      command_handler_is_chrome_toolbar_button_visible;
+}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefCommandHandlerCppToC::~CefCommandHandlerCppToC() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+CefRefPtr<CefCommandHandler> CefCppToCRefCounted<
+    CefCommandHandlerCppToC,
+    CefCommandHandler,
+    cef_command_handler_t>::UnwrapDerived(CefWrapperType type,
+                                          cef_command_handler_t* s) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCppToCRefCounted<CefCommandHandlerCppToC,
+                                   CefCommandHandler,
+                                   cef_command_handler_t>::kWrapperType =
+    WT_COMMAND_HANDLER;
diff --git a/src/libcef_dll/cpptoc/command_handler_cpptoc.h b/src/libcef_dll/cpptoc/command_handler_cpptoc.h
new file mode 100644
index 0000000..3c1a73e
--- /dev/null
+++ b/src/libcef_dll/cpptoc/command_handler_cpptoc.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=beb365f3b4d93d967612c9d8505240d7b727fd08$
+//
+
+#ifndef CEF_LIBCEF_DLL_CPPTOC_COMMAND_HANDLER_CPPTOC_H_
+#define CEF_LIBCEF_DLL_CPPTOC_COMMAND_HANDLER_CPPTOC_H_
+#pragma once
+
+#if !defined(WRAPPING_CEF_SHARED)
+#error This file can be included wrapper-side only
+#endif
+
+#include "include/capi/cef_command_handler_capi.h"
+#include "include/cef_command_handler.h"
+#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
+
+// Wrap a C++ class with a C structure.
+// This class may be instantiated and accessed wrapper-side only.
+class CefCommandHandlerCppToC
+    : public CefCppToCRefCounted<CefCommandHandlerCppToC,
+                                 CefCommandHandler,
+                                 cef_command_handler_t> {
+ public:
+  CefCommandHandlerCppToC();
+  virtual ~CefCommandHandlerCppToC();
+};
+
+#endif  // CEF_LIBCEF_DLL_CPPTOC_COMMAND_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/command_line_cpptoc.cc b/src/libcef_dll/cpptoc/command_line_cpptoc.cc
index 067b9d1..cfcfe16 100644
--- a/src/libcef_dll/cpptoc/command_line_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/command_line_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c2e91da671aba98135e71145f6b27f92b892d425$
+// $hash=0feacec72c147c19404395cb872cf47f02a4d092$
 //
 
 #include "libcef_dll/cpptoc/command_line_cpptoc.h"
@@ -45,8 +45,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefCommandLineCppToC::Get(self)->IsValid();
@@ -59,8 +60,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefCommandLineCppToC::Get(self)->IsReadOnly();
@@ -74,8 +76,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefCommandLine> _retval = CefCommandLineCppToC::Get(self)->Copy();
@@ -90,12 +93,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: argv; type: simple_byaddr
   DCHECK(argv);
-  if (!argv)
+  if (!argv) {
     return;
+  }
 
   // Execute
   CefCommandLineCppToC::Get(self)->InitFromArgv(argc, argv);
@@ -107,12 +112,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: command_line; type: string_byref_const
   DCHECK(command_line);
-  if (!command_line)
+  if (!command_line) {
     return;
+  }
 
   // Execute
   CefCommandLineCppToC::Get(self)->InitFromString(CefString(command_line));
@@ -122,8 +129,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefCommandLineCppToC::Get(self)->Reset();
@@ -134,12 +142,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: argv; type: string_vec_byref
   DCHECK(argv);
-  if (!argv)
+  if (!argv) {
     return;
+  }
 
   // Translate param: argv; type: string_vec_byref
   std::vector<CefString> argvList;
@@ -158,8 +168,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefCommandLineCppToC::Get(self)->GetCommandLineString();
@@ -173,8 +184,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefCommandLineCppToC::Get(self)->GetProgram();
@@ -188,12 +200,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: program; type: string_byref_const
   DCHECK(program);
-  if (!program)
+  if (!program) {
     return;
+  }
 
   // Execute
   CefCommandLineCppToC::Get(self)->SetProgram(CefString(program));
@@ -203,8 +217,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefCommandLineCppToC::Get(self)->HasSwitches();
@@ -218,12 +233,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefCommandLineCppToC::Get(self)->HasSwitch(CefString(name));
@@ -238,12 +255,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -258,12 +277,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: switches; type: string_map_single_byref
   DCHECK(switches);
-  if (!switches)
+  if (!switches) {
     return;
+  }
 
   // Translate param: switches; type: string_map_single_byref
   std::map<CefString, CefString> switchesMap;
@@ -282,12 +303,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
 
   // Execute
   CefCommandLineCppToC::Get(self)->AppendSwitch(CefString(name));
@@ -300,16 +323,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
   // Verify param: value; type: string_byref_const
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return;
+  }
 
   // Execute
   CefCommandLineCppToC::Get(self)->AppendSwitchWithValue(CefString(name),
@@ -320,8 +346,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefCommandLineCppToC::Get(self)->HasArguments();
@@ -335,12 +362,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: arguments; type: string_vec_byref
   DCHECK(arguments);
-  if (!arguments)
+  if (!arguments) {
     return;
+  }
 
   // Translate param: arguments; type: string_vec_byref
   std::vector<CefString> argumentsList;
@@ -359,12 +388,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: argument; type: string_byref_const
   DCHECK(argument);
-  if (!argument)
+  if (!argument) {
     return;
+  }
 
   // Execute
   CefCommandLineCppToC::Get(self)->AppendArgument(CefString(argument));
@@ -375,12 +406,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: wrapper; type: string_byref_const
   DCHECK(wrapper);
-  if (!wrapper)
+  if (!wrapper) {
     return;
+  }
 
   // Execute
   CefCommandLineCppToC::Get(self)->PrependWrapper(CefString(wrapper));
@@ -421,7 +454,7 @@
 CefRefPtr<CefCommandLine>
 CefCppToCRefCounted<CefCommandLineCppToC, CefCommandLine, cef_command_line_t>::
     UnwrapDerived(CefWrapperType type, cef_command_line_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/command_line_cpptoc.h b/src/libcef_dll/cpptoc/command_line_cpptoc.h
index 78da59e..45eb004 100644
--- a/src/libcef_dll/cpptoc/command_line_cpptoc.h
+++ b/src/libcef_dll/cpptoc/command_line_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1af599620e55743a48e67a53254ff6f3006e5842$
+// $hash=f8af58d9e62d25a46593ccebc487734730f6a1a3$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_COMMAND_LINE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/completion_callback_cpptoc.cc b/src/libcef_dll/cpptoc/completion_callback_cpptoc.cc
index d5cd187..2e51445 100644
--- a/src/libcef_dll/cpptoc/completion_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/completion_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ce5faec2604b151f3872baae02247038c41dfbbd$
+// $hash=d1faca27c390ce09058aebddcf7e0a55bdbea45c$
 //
 
 #include "libcef_dll/cpptoc/completion_callback_cpptoc.h"
@@ -26,8 +26,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefCompletionCallbackCppToC::Get(self)->OnComplete();
@@ -53,7 +54,7 @@
     CefCompletionCallback,
     cef_completion_callback_t>::UnwrapDerived(CefWrapperType type,
                                               cef_completion_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/completion_callback_cpptoc.h b/src/libcef_dll/cpptoc/completion_callback_cpptoc.h
index 5fa78fc..f57a9e4 100644
--- a/src/libcef_dll/cpptoc/completion_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/completion_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e28df65801eb92f405294a952d0de78ff1eddb12$
+// $hash=407df18b90244b245e73c4f69a199663df079f0d$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_COMPLETION_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/context_menu_handler_cpptoc.cc b/src/libcef_dll/cpptoc/context_menu_handler_cpptoc.cc
index bbafc39..2bde3f2 100644
--- a/src/libcef_dll/cpptoc/context_menu_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/context_menu_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9616dc7c84524da3f8549ce399bff1ff4c624ebc$
+// $hash=acd29552be49802a4b18bbce49109ac8df466e88$
 //
 
 #include "libcef_dll/cpptoc/context_menu_handler_cpptoc.h"
@@ -18,6 +18,7 @@
 #include "libcef_dll/ctocpp/frame_ctocpp.h"
 #include "libcef_dll/ctocpp/menu_model_ctocpp.h"
 #include "libcef_dll/ctocpp/run_context_menu_callback_ctocpp.h"
+#include "libcef_dll/ctocpp/run_quick_menu_callback_ctocpp.h"
 #include "libcef_dll/shutdown_checker.h"
 
 namespace {
@@ -35,24 +36,29 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return;
+  }
   // Verify param: params; type: refptr_diff
   DCHECK(params);
-  if (!params)
+  if (!params) {
     return;
+  }
   // Verify param: model; type: refptr_diff
   DCHECK(model);
-  if (!model)
+  if (!model) {
     return;
+  }
 
   // Execute
   CefContextMenuHandlerCppToC::Get(self)->OnBeforeContextMenu(
@@ -73,28 +79,34 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return 0;
+  }
   // Verify param: params; type: refptr_diff
   DCHECK(params);
-  if (!params)
+  if (!params) {
     return 0;
+  }
   // Verify param: model; type: refptr_diff
   DCHECK(model);
-  if (!model)
+  if (!model) {
     return 0;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefContextMenuHandlerCppToC::Get(self)->RunContextMenu(
@@ -118,20 +130,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return 0;
+  }
   // Verify param: params; type: refptr_diff
   DCHECK(params);
-  if (!params)
+  if (!params) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefContextMenuHandlerCppToC::Get(self)->OnContextMenuCommand(
@@ -151,22 +167,143 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return;
+  }
 
   // Execute
   CefContextMenuHandlerCppToC::Get(self)->OnContextMenuDismissed(
       CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame));
 }
 
+int CEF_CALLBACK context_menu_handler_run_quick_menu(
+    struct _cef_context_menu_handler_t* self,
+    cef_browser_t* browser,
+    struct _cef_frame_t* frame,
+    const cef_point_t* location,
+    const cef_size_t* size,
+    cef_quick_menu_edit_state_flags_t edit_state_flags,
+    cef_run_quick_menu_callback_t* callback) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return 0;
+  }
+  // Verify param: frame; type: refptr_diff
+  DCHECK(frame);
+  if (!frame) {
+    return 0;
+  }
+  // Verify param: location; type: simple_byref_const
+  DCHECK(location);
+  if (!location) {
+    return 0;
+  }
+  // Verify param: size; type: simple_byref_const
+  DCHECK(size);
+  if (!size) {
+    return 0;
+  }
+  // Verify param: callback; type: refptr_diff
+  DCHECK(callback);
+  if (!callback) {
+    return 0;
+  }
+
+  // Translate param: location; type: simple_byref_const
+  CefPoint locationVal = location ? *location : CefPoint();
+  // Translate param: size; type: simple_byref_const
+  CefSize sizeVal = size ? *size : CefSize();
+
+  // Execute
+  bool _retval = CefContextMenuHandlerCppToC::Get(self)->RunQuickMenu(
+      CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame), locationVal,
+      sizeVal, edit_state_flags, CefRunQuickMenuCallbackCToCpp::Wrap(callback));
+
+  // Return type: bool
+  return _retval;
+}
+
+int CEF_CALLBACK context_menu_handler_on_quick_menu_command(
+    struct _cef_context_menu_handler_t* self,
+    cef_browser_t* browser,
+    struct _cef_frame_t* frame,
+    int command_id,
+    cef_event_flags_t event_flags) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return 0;
+  }
+  // Verify param: frame; type: refptr_diff
+  DCHECK(frame);
+  if (!frame) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefContextMenuHandlerCppToC::Get(self)->OnQuickMenuCommand(
+      CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame), command_id,
+      event_flags);
+
+  // Return type: bool
+  return _retval;
+}
+
+void CEF_CALLBACK context_menu_handler_on_quick_menu_dismissed(
+    struct _cef_context_menu_handler_t* self,
+    cef_browser_t* browser,
+    struct _cef_frame_t* frame) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return;
+  }
+  // Verify param: frame; type: refptr_diff
+  DCHECK(frame);
+  if (!frame) {
+    return;
+  }
+
+  // Execute
+  CefContextMenuHandlerCppToC::Get(self)->OnQuickMenuDismissed(
+      CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame));
+}
+
 }  // namespace
 
 // CONSTRUCTOR - Do not edit by hand.
@@ -179,6 +316,11 @@
       context_menu_handler_on_context_menu_command;
   GetStruct()->on_context_menu_dismissed =
       context_menu_handler_on_context_menu_dismissed;
+  GetStruct()->run_quick_menu = context_menu_handler_run_quick_menu;
+  GetStruct()->on_quick_menu_command =
+      context_menu_handler_on_quick_menu_command;
+  GetStruct()->on_quick_menu_dismissed =
+      context_menu_handler_on_quick_menu_dismissed;
 }
 
 // DESTRUCTOR - Do not edit by hand.
@@ -193,7 +335,7 @@
     CefContextMenuHandler,
     cef_context_menu_handler_t>::UnwrapDerived(CefWrapperType type,
                                                cef_context_menu_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/context_menu_handler_cpptoc.h b/src/libcef_dll/cpptoc/context_menu_handler_cpptoc.h
index ade011b..fe010bf 100644
--- a/src/libcef_dll/cpptoc/context_menu_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/context_menu_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0b171771131fc299f0ee38b5ff7fb2cd427aa2ea$
+// $hash=68dd3aa1b0a216bdc63aa9ed3008b0b5815f8040$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_CONTEXT_MENU_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/context_menu_params_cpptoc.cc b/src/libcef_dll/cpptoc/context_menu_params_cpptoc.cc
index bca60db..069760e 100644
--- a/src/libcef_dll/cpptoc/context_menu_params_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/context_menu_params_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b6e2bf6704ad9ca5dc40c6dd7674f575d0dc1e67$
+// $hash=dbedbe557d28ffb247be6e185f838a9cbc999eb8$
 //
 
 #include "libcef_dll/cpptoc/context_menu_params_cpptoc.h"
@@ -27,8 +27,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefContextMenuParamsCppToC::Get(self)->GetXCoord();
@@ -44,8 +45,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefContextMenuParamsCppToC::Get(self)->GetYCoord();
@@ -61,8 +63,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CM_TYPEFLAG_NONE;
+  }
 
   // Execute
   cef_context_menu_type_flags_t _retval =
@@ -79,8 +82,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefContextMenuParamsCppToC::Get(self)->GetLinkUrl();
@@ -96,8 +100,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -114,8 +119,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefContextMenuParamsCppToC::Get(self)->GetSourceUrl();
@@ -131,8 +137,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefContextMenuParamsCppToC::Get(self)->HasImageContents();
@@ -148,8 +155,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefContextMenuParamsCppToC::Get(self)->GetTitleText();
@@ -165,8 +173,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefContextMenuParamsCppToC::Get(self)->GetPageUrl();
@@ -182,8 +191,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefContextMenuParamsCppToC::Get(self)->GetFrameUrl();
@@ -199,8 +209,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefContextMenuParamsCppToC::Get(self)->GetFrameCharset();
@@ -216,8 +227,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CM_MEDIATYPE_NONE;
+  }
 
   // Execute
   cef_context_menu_media_type_t _retval =
@@ -235,8 +247,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CM_MEDIAFLAG_NONE;
+  }
 
   // Execute
   cef_context_menu_media_state_flags_t _retval =
@@ -253,8 +266,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefContextMenuParamsCppToC::Get(self)->GetSelectionText();
@@ -270,8 +284,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -289,12 +304,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: suggestions; type: string_vec_byref
   DCHECK(suggestions);
-  if (!suggestions)
+  if (!suggestions) {
     return 0;
+  }
 
   // Translate param: suggestions; type: string_vec_byref
   std::vector<CefString> suggestionsList;
@@ -320,8 +337,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefContextMenuParamsCppToC::Get(self)->IsEditable();
@@ -337,8 +355,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefContextMenuParamsCppToC::Get(self)->IsSpellCheckEnabled();
@@ -355,8 +374,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CM_EDITFLAG_NONE;
+  }
 
   // Execute
   cef_context_menu_edit_state_flags_t _retval =
@@ -373,8 +393,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefContextMenuParamsCppToC::Get(self)->IsCustomMenu();
@@ -383,23 +404,6 @@
   return _retval;
 }
 
-int CEF_CALLBACK
-context_menu_params_is_pepper_menu(struct _cef_context_menu_params_t* self) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return 0;
-
-  // Execute
-  bool _retval = CefContextMenuParamsCppToC::Get(self)->IsPepperMenu();
-
-  // Return type: bool
-  return _retval;
-}
-
 }  // namespace
 
 // CONSTRUCTOR - Do not edit by hand.
@@ -429,7 +433,6 @@
       context_menu_params_is_spell_check_enabled;
   GetStruct()->get_edit_state_flags = context_menu_params_get_edit_state_flags;
   GetStruct()->is_custom_menu = context_menu_params_is_custom_menu;
-  GetStruct()->is_pepper_menu = context_menu_params_is_pepper_menu;
 }
 
 // DESTRUCTOR - Do not edit by hand.
@@ -444,7 +447,7 @@
     CefContextMenuParams,
     cef_context_menu_params_t>::UnwrapDerived(CefWrapperType type,
                                               cef_context_menu_params_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/context_menu_params_cpptoc.h b/src/libcef_dll/cpptoc/context_menu_params_cpptoc.h
index ca22e21..ccae20a 100644
--- a/src/libcef_dll/cpptoc/context_menu_params_cpptoc.h
+++ b/src/libcef_dll/cpptoc/context_menu_params_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b1ca103dfbfa17ce040d0d178163d102951aaa61$
+// $hash=289e9100aeb329f9ec7d1696354e31f2eb7d8ce9$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_CONTEXT_MENU_PARAMS_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/cookie_access_filter_cpptoc.cc b/src/libcef_dll/cpptoc/cookie_access_filter_cpptoc.cc
index ab91716..6ae17f1 100644
--- a/src/libcef_dll/cpptoc/cookie_access_filter_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/cookie_access_filter_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=669e20095016a2e40a0925b9715fc0b15229ff32$
+// $hash=d7bbbf41f806f415ac983a9a9f9475ab7783cb10$
 //
 
 #include "libcef_dll/cpptoc/cookie_access_filter_cpptoc.h"
@@ -17,6 +17,7 @@
 #include "libcef_dll/ctocpp/frame_ctocpp.h"
 #include "libcef_dll/ctocpp/request_ctocpp.h"
 #include "libcef_dll/ctocpp/response_ctocpp.h"
+#include "libcef_dll/template_util.h"
 
 namespace {
 
@@ -31,22 +32,30 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return 0;
+  }
   // Verify param: cookie; type: struct_byref_const
   DCHECK(cookie);
-  if (!cookie)
+  if (!cookie) {
     return 0;
+  }
+  if (!template_util::has_valid_size(cookie)) {
+    DCHECK(false) << "invalid cookie->[base.]size";
+    return 0;
+  }
   // Unverified params: browser, frame
 
   // Translate param: cookie; type: struct_byref_const
   CefCookie cookieObj;
-  if (cookie)
+  if (cookie) {
     cookieObj.Set(*cookie, false);
+  }
 
   // Execute
   bool _retval = CefCookieAccessFilterCppToC::Get(self)->CanSendCookie(
@@ -67,26 +76,35 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return 0;
+  }
   // Verify param: response; type: refptr_diff
   DCHECK(response);
-  if (!response)
+  if (!response) {
     return 0;
+  }
   // Verify param: cookie; type: struct_byref_const
   DCHECK(cookie);
-  if (!cookie)
+  if (!cookie) {
     return 0;
+  }
+  if (!template_util::has_valid_size(cookie)) {
+    DCHECK(false) << "invalid cookie->[base.]size";
+    return 0;
+  }
   // Unverified params: browser, frame
 
   // Translate param: cookie; type: struct_byref_const
   CefCookie cookieObj;
-  if (cookie)
+  if (cookie) {
     cookieObj.Set(*cookie, false);
+  }
 
   // Execute
   bool _retval = CefCookieAccessFilterCppToC::Get(self)->CanSaveCookie(
@@ -117,7 +135,7 @@
     CefCookieAccessFilter,
     cef_cookie_access_filter_t>::UnwrapDerived(CefWrapperType type,
                                                cef_cookie_access_filter_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/cookie_access_filter_cpptoc.h b/src/libcef_dll/cpptoc/cookie_access_filter_cpptoc.h
index 302f394..d3e1504 100644
--- a/src/libcef_dll/cpptoc/cookie_access_filter_cpptoc.h
+++ b/src/libcef_dll/cpptoc/cookie_access_filter_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c1edc5ee4581ea6437f316432cc6746e4213eeb2$
+// $hash=e0b8da1120abbbb306c6cc789ec94e38dc07ceb0$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_COOKIE_ACCESS_FILTER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/cookie_manager_cpptoc.cc b/src/libcef_dll/cpptoc/cookie_manager_cpptoc.cc
index 6f59b4f..9be4ec8 100644
--- a/src/libcef_dll/cpptoc/cookie_manager_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/cookie_manager_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1c3e3acd8548a82404f33b728223893809a95ee8$
+// $hash=fc593830dcad16182301bd0033d3932e06820e1b$
 //
 
 #include "libcef_dll/cpptoc/cookie_manager_cpptoc.h"
@@ -17,7 +17,7 @@
 #include "libcef_dll/ctocpp/cookie_visitor_ctocpp.h"
 #include "libcef_dll/ctocpp/delete_cookies_callback_ctocpp.h"
 #include "libcef_dll/ctocpp/set_cookie_callback_ctocpp.h"
-#include "libcef_dll/transfer_util.h"
+#include "libcef_dll/template_util.h"
 
 // GLOBAL FUNCTIONS - Body may be edited by hand.
 
@@ -39,44 +39,20 @@
 
 // MEMBER FUNCTIONS - Body may be edited by hand.
 
-void CEF_CALLBACK
-cookie_manager_set_supported_schemes(struct _cef_cookie_manager_t* self,
-                                     cef_string_list_t schemes,
-                                     int include_defaults,
-                                     cef_completion_callback_t* callback) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return;
-  // Verify param: schemes; type: string_vec_byref_const
-  DCHECK(schemes);
-  if (!schemes)
-    return;
-  // Unverified params: callback
-
-  // Translate param: schemes; type: string_vec_byref_const
-  std::vector<CefString> schemesList;
-  transfer_string_list_contents(schemes, schemesList);
-
-  // Execute
-  CefCookieManagerCppToC::Get(self)->SetSupportedSchemes(
-      schemesList, include_defaults ? true : false,
-      CefCompletionCallbackCToCpp::Wrap(callback));
-}
-
 int CEF_CALLBACK
 cookie_manager_visit_all_cookies(struct _cef_cookie_manager_t* self,
                                  struct _cef_cookie_visitor_t* visitor) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: visitor; type: refptr_diff
   DCHECK(visitor);
-  if (!visitor)
+  if (!visitor) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefCookieManagerCppToC::Get(self)->VisitAllCookies(
@@ -94,16 +70,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: url; type: string_byref_const
   DCHECK(url);
-  if (!url)
+  if (!url) {
     return 0;
+  }
   // Verify param: visitor; type: refptr_diff
   DCHECK(visitor);
-  if (!visitor)
+  if (!visitor) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefCookieManagerCppToC::Get(self)->VisitUrlCookies(
@@ -122,22 +101,30 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: url; type: string_byref_const
   DCHECK(url);
-  if (!url)
+  if (!url) {
     return 0;
+  }
   // Verify param: cookie; type: struct_byref_const
   DCHECK(cookie);
-  if (!cookie)
+  if (!cookie) {
     return 0;
+  }
+  if (!template_util::has_valid_size(cookie)) {
+    DCHECK(false) << "invalid cookie->[base.]size";
+    return 0;
+  }
   // Unverified params: callback
 
   // Translate param: cookie; type: struct_byref_const
   CefCookie cookieObj;
-  if (cookie)
+  if (cookie) {
     cookieObj.Set(*cookie, false);
+  }
 
   // Execute
   bool _retval = CefCookieManagerCppToC::Get(self)->SetCookie(
@@ -155,8 +142,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Unverified params: url, cookie_name, callback
 
   // Execute
@@ -174,8 +162,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Unverified params: callback
 
   // Execute
@@ -191,7 +180,6 @@
 // CONSTRUCTOR - Do not edit by hand.
 
 CefCookieManagerCppToC::CefCookieManagerCppToC() {
-  GetStruct()->set_supported_schemes = cookie_manager_set_supported_schemes;
   GetStruct()->visit_all_cookies = cookie_manager_visit_all_cookies;
   GetStruct()->visit_url_cookies = cookie_manager_visit_url_cookies;
   GetStruct()->set_cookie = cookie_manager_set_cookie;
@@ -209,7 +197,7 @@
     CefCookieManager,
     cef_cookie_manager_t>::UnwrapDerived(CefWrapperType type,
                                          cef_cookie_manager_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/cookie_manager_cpptoc.h b/src/libcef_dll/cpptoc/cookie_manager_cpptoc.h
index 69e733a..9f4094f 100644
--- a/src/libcef_dll/cpptoc/cookie_manager_cpptoc.h
+++ b/src/libcef_dll/cpptoc/cookie_manager_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=25c5eda0e5265f5905b144e5b23951fe7d11cf80$
+// $hash=3c70ed00438c00d85c27407d1c0947d2b310f401$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_COOKIE_MANAGER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/cookie_visitor_cpptoc.cc b/src/libcef_dll/cpptoc/cookie_visitor_cpptoc.cc
index 247e4fc..a49ffe9 100644
--- a/src/libcef_dll/cpptoc/cookie_visitor_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/cookie_visitor_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,11 +9,12 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ac8389b701fc37f7aa4dbccff339d8a88b2a7741$
+// $hash=ccecac02125e1608fe96c9646b6d9529434396e9$
 //
 
 #include "libcef_dll/cpptoc/cookie_visitor_cpptoc.h"
 #include "libcef_dll/shutdown_checker.h"
+#include "libcef_dll/template_util.h"
 
 namespace {
 
@@ -29,21 +30,29 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: cookie; type: struct_byref_const
   DCHECK(cookie);
-  if (!cookie)
+  if (!cookie) {
     return 0;
+  }
+  if (!template_util::has_valid_size(cookie)) {
+    DCHECK(false) << "invalid cookie->[base.]size";
+    return 0;
+  }
   // Verify param: deleteCookie; type: bool_byref
   DCHECK(deleteCookie);
-  if (!deleteCookie)
+  if (!deleteCookie) {
     return 0;
+  }
 
   // Translate param: cookie; type: struct_byref_const
   CefCookie cookieObj;
-  if (cookie)
+  if (cookie) {
     cookieObj.Set(*cookie, false);
+  }
   // Translate param: deleteCookie; type: bool_byref
   bool deleteCookieBool = (deleteCookie && *deleteCookie) ? true : false;
 
@@ -52,8 +61,9 @@
       cookieObj, count, total, deleteCookieBool);
 
   // Restore param: deleteCookie; type: bool_byref
-  if (deleteCookie)
+  if (deleteCookie) {
     *deleteCookie = deleteCookieBool ? true : false;
+  }
 
   // Return type: bool
   return _retval;
@@ -79,7 +89,7 @@
     CefCookieVisitor,
     cef_cookie_visitor_t>::UnwrapDerived(CefWrapperType type,
                                          cef_cookie_visitor_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/cookie_visitor_cpptoc.h b/src/libcef_dll/cpptoc/cookie_visitor_cpptoc.h
index e56f6e1..f0dd94f 100644
--- a/src/libcef_dll/cpptoc/cookie_visitor_cpptoc.h
+++ b/src/libcef_dll/cpptoc/cookie_visitor_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=379f307a22ad62e86672608e048c255734b3f94a$
+// $hash=45985eb9f0544a0c90fea396ec66c921e44f55a5$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_COOKIE_VISITOR_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/cpptoc_ref_counted.h b/src/libcef_dll/cpptoc/cpptoc_ref_counted.h
index dd90a79..d7a04e7 100644
--- a/src/libcef_dll/cpptoc/cpptoc_ref_counted.h
+++ b/src/libcef_dll/cpptoc/cpptoc_ref_counted.h
@@ -7,7 +7,6 @@
 #pragma once
 
 #include "include/base/cef_logging.h"
-#include "include/base/cef_macros.h"
 #include "include/capi/cef_base_capi.h"
 #include "include/cef_base.h"
 #include "libcef_dll/wrapper_types.h"
@@ -18,11 +17,15 @@
 template <class ClassName, class BaseName, class StructName>
 class CefCppToCRefCounted : public CefBaseRefCounted {
  public:
+  CefCppToCRefCounted(const CefCppToCRefCounted&) = delete;
+  CefCppToCRefCounted& operator=(const CefCppToCRefCounted&) = delete;
+
   // Create a new wrapper instance and associated structure reference for
   // passing an object instance the other side.
   static StructName* Wrap(CefRefPtr<BaseName> c) {
-    if (!c.get())
+    if (!c.get()) {
       return nullptr;
+    }
 
     // Wrap our object with the CefCppToCRefCounted class.
     ClassName* wrapper = new ClassName();
@@ -37,16 +40,18 @@
   // Retrieve the underlying object instance for a structure reference passed
   // back from the other side.
   static CefRefPtr<BaseName> Unwrap(StructName* s) {
-    if (!s)
+    if (!s) {
       return nullptr;
+    }
 
     // Cast our structure to the wrapper structure type.
     WrapperStruct* wrapperStruct = GetWrapperStruct(s);
 
     // If the type does not match this object then we need to unwrap as the
     // derived type.
-    if (wrapperStruct->type_ != kWrapperType)
+    if (wrapperStruct->type_ != kWrapperType) {
       return UnwrapDerived(wrapperStruct->type_, s);
+    }
 
     // Add the underlying object instance to a smart pointer.
     CefRefPtr<BaseName> objectPtr(wrapperStruct->object_);
@@ -105,7 +110,7 @@
     base->has_at_least_one_ref = struct_has_at_least_one_ref;
   }
 
-  virtual ~CefCppToCRefCounted() {}
+  virtual ~CefCppToCRefCounted() = default;
 
  private:
   // Used to associate this wrapper object, the underlying object instance and
@@ -141,8 +146,9 @@
 
   static void CEF_CALLBACK struct_add_ref(cef_base_ref_counted_t* base) {
     DCHECK(base);
-    if (!base)
+    if (!base) {
       return;
+    }
 
     WrapperStruct* wrapperStruct =
         GetWrapperStruct(reinterpret_cast<StructName*>(base));
@@ -154,8 +160,9 @@
 
   static int CEF_CALLBACK struct_release(cef_base_ref_counted_t* base) {
     DCHECK(base);
-    if (!base)
+    if (!base) {
       return 0;
+    }
 
     WrapperStruct* wrapperStruct =
         GetWrapperStruct(reinterpret_cast<StructName*>(base));
@@ -167,8 +174,9 @@
 
   static int CEF_CALLBACK struct_has_one_ref(cef_base_ref_counted_t* base) {
     DCHECK(base);
-    if (!base)
+    if (!base) {
       return 0;
+    }
 
     WrapperStruct* wrapperStruct =
         GetWrapperStruct(reinterpret_cast<StructName*>(base));
@@ -181,8 +189,9 @@
   static int CEF_CALLBACK
   struct_has_at_least_one_ref(cef_base_ref_counted_t* base) {
     DCHECK(base);
-    if (!base)
+    if (!base) {
       return 0;
+    }
 
     WrapperStruct* wrapperStruct =
         GetWrapperStruct(reinterpret_cast<StructName*>(base));
@@ -196,8 +205,6 @@
   CefRefCount ref_count_;
 
   static CefWrapperType kWrapperType;
-
-  DISALLOW_COPY_AND_ASSIGN(CefCppToCRefCounted);
 };
 
 #endif  // CEF_LIBCEF_DLL_CPPTOC_CPPTOC_REF_COUNTED_H_
diff --git a/src/libcef_dll/cpptoc/cpptoc_scoped.h b/src/libcef_dll/cpptoc/cpptoc_scoped.h
index b552404..11fe3d9 100644
--- a/src/libcef_dll/cpptoc/cpptoc_scoped.h
+++ b/src/libcef_dll/cpptoc/cpptoc_scoped.h
@@ -7,10 +7,8 @@
 #pragma once
 
 #include "include/base/cef_logging.h"
-#include "include/base/cef_macros.h"
 #include "include/capi/cef_base_capi.h"
 #include "include/cef_base.h"
-#include "libcef_dll/ptr_util.h"
 #include "libcef_dll/wrapper_types.h"
 
 // Wrap a C++ class with a C structure. This is used when the class
@@ -19,6 +17,9 @@
 template <class ClassName, class BaseName, class StructName>
 class CefCppToCScoped : public CefBaseScoped {
  public:
+  CefCppToCScoped(const CefCppToCScoped&) = delete;
+  CefCppToCScoped& operator=(const CefCppToCScoped&) = delete;
+
   // Create a new wrapper instance and associated structure reference for
   // passing an object instance the other side. The wrapper object will be
   // deleted when |del| is called on the associated structure. The wrapped
@@ -33,8 +34,9 @@
   //   struct->del(struct);
   // }
   static StructName* WrapOwn(CefOwnPtr<BaseName> c) {
-    if (!c)
+    if (!c) {
       return nullptr;
+    }
 
     // Wrap our object with the CefCppToC class.
     ClassName* wrapper = new ClassName();
@@ -59,8 +61,9 @@
   //   // Access |struct| here but you can't delete it.
   // }
   static CefOwnPtr<ClassName> WrapRaw(CefRawPtr<BaseName> c) {
-    if (!c)
+    if (!c) {
       return CefOwnPtr<ClassName>();
+    }
 
     // Wrap our object with the CefCppToC class.
     ClassName* wrapper = new ClassName();
@@ -79,16 +82,18 @@
   //   // |struct| has been deleted and should no longer be accessed.
   // }
   static CefOwnPtr<BaseName> UnwrapOwn(StructName* s) {
-    if (!s)
+    if (!s) {
       return CefOwnPtr<BaseName>();
+    }
 
     // Cast our structure to the wrapper structure type.
     WrapperStruct* wrapperStruct = GetWrapperStruct(s);
 
     // If the type does not match this object then we need to unwrap as the
     // derived type.
-    if (wrapperStruct->type_ != kWrapperType)
+    if (wrapperStruct->type_ != kWrapperType) {
       return UnwrapDerivedOwn(wrapperStruct->type_, s);
+    }
 
     // We should own the underlying object currently.
     DCHECK(wrapperStruct->wrapper_->owned_);
@@ -113,16 +118,18 @@
   //   // |struct| is still valid.
   // }
   static CefRawPtr<BaseName> UnwrapRaw(StructName* s) {
-    if (!s)
+    if (!s) {
       return nullptr;
+    }
 
     // Cast our structure to the wrapper structure type.
     WrapperStruct* wrapperStruct = GetWrapperStruct(s);
 
     // If the type does not match this object then we need to unwrap as the
     // derived type.
-    if (wrapperStruct->type_ != kWrapperType)
+    if (wrapperStruct->type_ != kWrapperType) {
       return UnwrapDerivedRaw(wrapperStruct->type_, s);
+    }
 
     // Return the underlying object instance.
     return wrapperStruct->object_;
@@ -163,8 +170,9 @@
 
   virtual ~CefCppToCScoped() {
     // Only delete the underlying object if we own it.
-    if (owned_ && wrapper_struct_.object_)
+    if (owned_ && wrapper_struct_.object_) {
       delete wrapper_struct_.object_;
+    }
   }
 
  private:
@@ -183,8 +191,9 @@
 
     cef_base_scoped_t* base = reinterpret_cast<cef_base_scoped_t*>(GetStruct());
     base->size = sizeof(StructName);
-    if (owned)
+    if (owned) {
       base->del = struct_del;
+    }
   }
 
   static WrapperStruct* GetWrapperStruct(StructName* s) {
@@ -204,8 +213,9 @@
 
   static void CEF_CALLBACK struct_del(cef_base_scoped_t* base) {
     DCHECK(base);
-    if (!base)
+    if (!base) {
       return;
+    }
 
     WrapperStruct* wrapperStruct =
         GetWrapperStruct(reinterpret_cast<StructName*>(base));
@@ -221,8 +231,6 @@
   bool owned_;
 
   static CefWrapperType kWrapperType;
-
-  DISALLOW_COPY_AND_ASSIGN(CefCppToCScoped);
 };
 
 #endif  // CEF_LIBCEF_DLL_CPPTOC_CPPTOC_SCOPED_H_
diff --git a/src/libcef_dll/cpptoc/delete_cookies_callback_cpptoc.cc b/src/libcef_dll/cpptoc/delete_cookies_callback_cpptoc.cc
index 9b54837..fe37e02 100644
--- a/src/libcef_dll/cpptoc/delete_cookies_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/delete_cookies_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3c8aba8fdaad1ff7034735a44c5cb811b89384c9$
+// $hash=72ebc189ce2a4bcfc796b818409d3b742651fda9$
 //
 
 #include "libcef_dll/cpptoc/delete_cookies_callback_cpptoc.h"
@@ -27,8 +27,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefDeleteCookiesCallbackCppToC::Get(self)->OnComplete(num_deleted);
@@ -55,7 +56,7 @@
     cef_delete_cookies_callback_t>::UnwrapDerived(CefWrapperType type,
                                                   cef_delete_cookies_callback_t*
                                                       s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/delete_cookies_callback_cpptoc.h b/src/libcef_dll/cpptoc/delete_cookies_callback_cpptoc.h
index 5a2cbfb..bc1ebd9 100644
--- a/src/libcef_dll/cpptoc/delete_cookies_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/delete_cookies_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0a9aa85a1bc30f434486b029e85a2e4f775fa875$
+// $hash=9ef76b4e16c9ee12b2c5956a3e4789fe2e40d9f0$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_DELETE_COOKIES_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/dev_tools_message_observer_cpptoc.cc b/src/libcef_dll/cpptoc/dev_tools_message_observer_cpptoc.cc
index 600796a..2fe36d1 100644
--- a/src/libcef_dll/cpptoc/dev_tools_message_observer_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/dev_tools_message_observer_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c4a7b4d679f1f2ed47fc31df3e2099962d5cb9d6$
+// $hash=d32b3a49e312971ee0c825fe765c584c033d65e9$
 //
 
 #include "libcef_dll/cpptoc/dev_tools_message_observer_cpptoc.h"
@@ -30,16 +30,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: message; type: simple_byaddr
   DCHECK(message);
-  if (!message)
+  if (!message) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDevToolsMessageObserverCppToC::Get(self)->OnDevToolsMessage(
@@ -61,12 +64,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Unverified params: result
 
   // Execute
@@ -86,16 +91,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: method; type: string_byref_const
   DCHECK(method);
-  if (!method)
+  if (!method) {
     return;
+  }
   // Unverified params: params
 
   // Execute
@@ -111,12 +119,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefDevToolsMessageObserverCppToC::Get(self)->OnDevToolsAgentAttached(
@@ -131,12 +141,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefDevToolsMessageObserverCppToC::Get(self)->OnDevToolsAgentDetached(
@@ -172,7 +184,7 @@
                     CefDevToolsMessageObserver,
                     cef_dev_tools_message_observer_t>::
     UnwrapDerived(CefWrapperType type, cef_dev_tools_message_observer_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/dev_tools_message_observer_cpptoc.h b/src/libcef_dll/cpptoc/dev_tools_message_observer_cpptoc.h
index 9d39fd1..6ab9e5c 100644
--- a/src/libcef_dll/cpptoc/dev_tools_message_observer_cpptoc.h
+++ b/src/libcef_dll/cpptoc/dev_tools_message_observer_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d48f93f3817dab7daf0e30a6fa94b1a173356383$
+// $hash=4f034b01b5709e8012ff089e000216008f6232b6$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_DEV_TOOLS_MESSAGE_OBSERVER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/dialog_handler_cpptoc.cc b/src/libcef_dll/cpptoc/dialog_handler_cpptoc.cc
index 9837428..99ece24 100644
--- a/src/libcef_dll/cpptoc/dialog_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/dialog_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=67f9af743f81c6fa7e4f1cdf7e626115fc83333f$
+// $hash=675f5f8b6e0738bb12326d53e3e8bfbb3e645f9b$
 //
 
 #include "libcef_dll/cpptoc/dialog_handler_cpptoc.h"
@@ -29,27 +29,25 @@
                               const cef_string_t* title,
                               const cef_string_t* default_file_path,
                               cef_string_list_t accept_filters,
-                              int selected_accept_filter,
                               cef_file_dialog_callback_t* callback) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
-  // Verify param: selected_accept_filter; type: simple_byval
-  DCHECK_GE(selected_accept_filter, 0);
-  if (selected_accept_filter < 0)
-    return 0;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return 0;
+  }
   // Unverified params: title, default_file_path, accept_filters
 
   // Translate param: accept_filters; type: string_vec_byref_const
@@ -59,7 +57,7 @@
   // Execute
   bool _retval = CefDialogHandlerCppToC::Get(self)->OnFileDialog(
       CefBrowserCToCpp::Wrap(browser), mode, CefString(title),
-      CefString(default_file_path), accept_filtersList, selected_accept_filter,
+      CefString(default_file_path), accept_filtersList,
       CefFileDialogCallbackCToCpp::Wrap(callback));
 
   // Return type: bool
@@ -86,7 +84,7 @@
     CefDialogHandler,
     cef_dialog_handler_t>::UnwrapDerived(CefWrapperType type,
                                          cef_dialog_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/dialog_handler_cpptoc.h b/src/libcef_dll/cpptoc/dialog_handler_cpptoc.h
index ae4f430..dcd8805 100644
--- a/src/libcef_dll/cpptoc/dialog_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/dialog_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8d7433f549cc246d02da12b5aec26e040ceecb79$
+// $hash=fca3fb90b8a74c5cdf3dc16e1489668ce80c7c07$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_DIALOG_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/dictionary_value_cpptoc.cc b/src/libcef_dll/cpptoc/dictionary_value_cpptoc.cc
index e5fd825..5a81ce0 100644
--- a/src/libcef_dll/cpptoc/dictionary_value_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/dictionary_value_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ad265f41a490c88e7b4fd64022fcf78eddb8cc35$
+// $hash=ed7d4723843c212ea634d3d9fe3121591de1c71d$
 //
 
 #include "libcef_dll/cpptoc/dictionary_value_cpptoc.h"
@@ -44,8 +44,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDictionaryValueCppToC::Get(self)->IsValid();
@@ -61,8 +62,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDictionaryValueCppToC::Get(self)->IsOwned();
@@ -78,8 +80,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDictionaryValueCppToC::Get(self)->IsReadOnly();
@@ -96,12 +99,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDictionaryValueCppToC::Get(self)->IsSame(
@@ -119,12 +124,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDictionaryValueCppToC::Get(self)->IsEqual(
@@ -142,8 +149,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDictionaryValue> _retval =
@@ -161,8 +169,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefDictionaryValueCppToC::Get(self)->GetSize();
@@ -177,8 +186,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDictionaryValueCppToC::Get(self)->Clear();
@@ -194,12 +204,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDictionaryValueCppToC::Get(self)->HasKey(CefString(key));
@@ -215,12 +227,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: keys; type: string_vec_byref
   DCHECK(keys);
-  if (!keys)
+  if (!keys) {
     return 0;
+  }
 
   // Translate param: keys; type: string_vec_byref
   std::vector<CefString> keysList;
@@ -244,12 +258,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDictionaryValueCppToC::Get(self)->Remove(CefString(key));
@@ -266,12 +282,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return VTYPE_INVALID;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return VTYPE_INVALID;
+  }
 
   // Execute
   cef_value_type_t _retval =
@@ -289,12 +307,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefValue> _retval =
@@ -311,12 +331,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDictionaryValueCppToC::Get(self)->GetBool(CefString(key));
@@ -332,12 +354,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return 0;
+  }
 
   // Execute
   int _retval = CefDictionaryValueCppToC::Get(self)->GetInt(CefString(key));
@@ -354,12 +378,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return 0;
+  }
 
   // Execute
   double _retval =
@@ -377,12 +403,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -400,12 +428,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBinaryValue> _retval =
@@ -423,12 +453,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDictionaryValue> _retval =
@@ -446,12 +478,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefListValue> _retval =
@@ -470,16 +504,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return 0;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDictionaryValueCppToC::Get(self)->SetValue(
@@ -496,12 +533,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDictionaryValueCppToC::Get(self)->SetNull(CefString(key));
@@ -518,12 +557,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDictionaryValueCppToC::Get(self)->SetBool(
@@ -541,12 +582,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -565,12 +608,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -589,12 +634,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return 0;
+  }
   // Unverified params: value
 
   // Execute
@@ -614,16 +661,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return 0;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDictionaryValueCppToC::Get(self)->SetBinary(
@@ -642,16 +692,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return 0;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDictionaryValueCppToC::Get(self)->SetDictionary(
@@ -669,16 +722,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return 0;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDictionaryValueCppToC::Get(self)->SetList(
@@ -736,7 +792,7 @@
     CefDictionaryValue,
     cef_dictionary_value_t>::UnwrapDerived(CefWrapperType type,
                                            cef_dictionary_value_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/dictionary_value_cpptoc.h b/src/libcef_dll/cpptoc/dictionary_value_cpptoc.h
index 4fe5e78..038b573 100644
--- a/src/libcef_dll/cpptoc/dictionary_value_cpptoc.h
+++ b/src/libcef_dll/cpptoc/dictionary_value_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=083bd5ba100fb82c10769e8e073b9d931914fb03$
+// $hash=dd73e5b97103c4ad27620af89886e49bfbdc8d21$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_DICTIONARY_VALUE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/display_handler_cpptoc.cc b/src/libcef_dll/cpptoc/display_handler_cpptoc.cc
index 469c359..f8ea5f5 100644
--- a/src/libcef_dll/cpptoc/display_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/display_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1e329026cfad131337e794e5501367604f62fdb6$
+// $hash=c0ff4cb4baaaeb981c9c143e6379a7ae1927c51e$
 //
 
 #include "libcef_dll/cpptoc/display_handler_cpptoc.h"
@@ -32,20 +32,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return;
+  }
   // Verify param: url; type: string_byref_const
   DCHECK(url);
-  if (!url)
+  if (!url) {
     return;
+  }
 
   // Execute
   CefDisplayHandlerCppToC::Get(self)->OnAddressChange(
@@ -62,12 +66,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Unverified params: title
 
   // Execute
@@ -84,12 +90,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Unverified params: icon_urls
 
   // Translate param: icon_urls; type: string_vec_byref_const
@@ -110,12 +118,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefDisplayHandlerCppToC::Get(self)->OnFullscreenModeChange(
@@ -130,12 +140,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Unverified params: text
 
   // Translate param: text; type: string_byref
@@ -158,12 +170,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Unverified params: value
 
   // Execute
@@ -183,12 +197,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Unverified params: message, source
 
   // Execute
@@ -209,16 +225,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: new_size; type: simple_byref_const
   DCHECK(new_size);
-  if (!new_size)
+  if (!new_size) {
     return 0;
+  }
 
   // Translate param: new_size; type: simple_byref_const
   CefSize new_sizeVal = new_size ? *new_size : CefSize();
@@ -240,18 +259,82 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefDisplayHandlerCppToC::Get(self)->OnLoadingProgressChange(
       CefBrowserCToCpp::Wrap(browser), progress);
 }
 
+int CEF_CALLBACK
+display_handler_on_cursor_change(struct _cef_display_handler_t* self,
+                                 cef_browser_t* browser,
+                                 cef_cursor_handle_t cursor,
+                                 cef_cursor_type_t type,
+                                 const cef_cursor_info_t* custom_cursor_info) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return 0;
+  }
+  // Verify param: custom_cursor_info; type: simple_byref_const
+  DCHECK(custom_cursor_info);
+  if (!custom_cursor_info) {
+    return 0;
+  }
+
+  // Translate param: custom_cursor_info; type: simple_byref_const
+  CefCursorInfo custom_cursor_infoVal =
+      custom_cursor_info ? *custom_cursor_info : CefCursorInfo();
+
+  // Execute
+  bool _retval = CefDisplayHandlerCppToC::Get(self)->OnCursorChange(
+      CefBrowserCToCpp::Wrap(browser), cursor, type, custom_cursor_infoVal);
+
+  // Return type: bool
+  return _retval;
+}
+
+void CEF_CALLBACK
+display_handler_on_media_access_change(struct _cef_display_handler_t* self,
+                                       cef_browser_t* browser,
+                                       int has_video_access,
+                                       int has_audio_access) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return;
+  }
+
+  // Execute
+  CefDisplayHandlerCppToC::Get(self)->OnMediaAccessChange(
+      CefBrowserCToCpp::Wrap(browser), has_video_access ? true : false,
+      has_audio_access ? true : false);
+}
+
 }  // namespace
 
 // CONSTRUCTOR - Do not edit by hand.
@@ -268,6 +351,8 @@
   GetStruct()->on_auto_resize = display_handler_on_auto_resize;
   GetStruct()->on_loading_progress_change =
       display_handler_on_loading_progress_change;
+  GetStruct()->on_cursor_change = display_handler_on_cursor_change;
+  GetStruct()->on_media_access_change = display_handler_on_media_access_change;
 }
 
 // DESTRUCTOR - Do not edit by hand.
@@ -282,7 +367,7 @@
     CefDisplayHandler,
     cef_display_handler_t>::UnwrapDerived(CefWrapperType type,
                                           cef_display_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/display_handler_cpptoc.h b/src/libcef_dll/cpptoc/display_handler_cpptoc.h
index 10d7d50..ccc1e43 100644
--- a/src/libcef_dll/cpptoc/display_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/display_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0ee7315137ad11a49a7bad20aee747ba3910517e$
+// $hash=8ba6fb9ce96e92ba80a05258060e530ddf822264$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_DISPLAY_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/domdocument_cpptoc.cc b/src/libcef_dll/cpptoc/domdocument_cpptoc.cc
index 5e451fe..254893d 100644
--- a/src/libcef_dll/cpptoc/domdocument_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/domdocument_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=312e73a1e276ba266640055115c6b8f78920fcbb$
+// $hash=c2dd1bf044dc413a46e8482869711ed60f7129c7$
 //
 
 #include "libcef_dll/cpptoc/domdocument_cpptoc.h"
@@ -27,8 +27,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return DOM_DOCUMENT_TYPE_UNKNOWN;
+  }
 
   // Execute
   cef_dom_document_type_t _retval = CefDOMDocumentCppToC::Get(self)->GetType();
@@ -44,8 +45,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDOMNode> _retval =
@@ -62,8 +64,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDOMNode> _retval = CefDOMDocumentCppToC::Get(self)->GetBody();
@@ -79,8 +82,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDOMNode> _retval = CefDOMDocumentCppToC::Get(self)->GetHead();
@@ -96,8 +100,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDOMDocumentCppToC::Get(self)->GetTitle();
@@ -114,12 +119,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: id; type: string_byref_const
   DCHECK(id);
-  if (!id)
+  if (!id) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDOMNode> _retval =
@@ -136,8 +143,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDOMNode> _retval =
@@ -153,8 +161,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDOMDocumentCppToC::Get(self)->HasSelection();
@@ -170,8 +179,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefDOMDocumentCppToC::Get(self)->GetSelectionStartOffset();
@@ -187,8 +197,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefDOMDocumentCppToC::Get(self)->GetSelectionEndOffset();
@@ -204,8 +215,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDOMDocumentCppToC::Get(self)->GetSelectionAsMarkup();
@@ -221,8 +233,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDOMDocumentCppToC::Get(self)->GetSelectionAsText();
@@ -238,8 +251,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDOMDocumentCppToC::Get(self)->GetBaseURL();
@@ -256,12 +270,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: partialURL; type: string_byref_const
   DCHECK(partialURL);
-  if (!partialURL)
+  if (!partialURL) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -303,7 +319,7 @@
 CefRefPtr<CefDOMDocument>
 CefCppToCRefCounted<CefDOMDocumentCppToC, CefDOMDocument, cef_domdocument_t>::
     UnwrapDerived(CefWrapperType type, cef_domdocument_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/domdocument_cpptoc.h b/src/libcef_dll/cpptoc/domdocument_cpptoc.h
index 1265756..bdf946c 100644
--- a/src/libcef_dll/cpptoc/domdocument_cpptoc.h
+++ b/src/libcef_dll/cpptoc/domdocument_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f3031620487ad950d4d71c15cb9ee37ee2857000$
+// $hash=6a5b9bb0155acb8c5e6f796e68463825e00a8e53$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_DOMDOCUMENT_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/domnode_cpptoc.cc b/src/libcef_dll/cpptoc/domnode_cpptoc.cc
index c1f334b..444ce4e 100644
--- a/src/libcef_dll/cpptoc/domnode_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/domnode_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7931740b8c5860b0397dadc0208eb03098faa765$
+// $hash=7dd2dd5a49c722abcd0b76b89c73758c199d77bb$
 //
 
 #include "libcef_dll/cpptoc/domnode_cpptoc.h"
@@ -27,8 +27,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return DOM_NODE_TYPE_UNSUPPORTED;
+  }
 
   // Execute
   cef_dom_node_type_t _retval = CefDOMNodeCppToC::Get(self)->GetType();
@@ -43,8 +44,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDOMNodeCppToC::Get(self)->IsText();
@@ -59,8 +61,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDOMNodeCppToC::Get(self)->IsElement();
@@ -75,8 +78,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDOMNodeCppToC::Get(self)->IsEditable();
@@ -91,8 +95,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
-    return 0;
+  if (!self) {
+    return DOM_NODE_TYPE_UNSUPPORTED;
+  }
 
   // Execute
   bool _retval = CefDOMNodeCppToC::Get(self)->IsFormControlElement();
@@ -101,21 +106,23 @@
   return _retval;
 }
 
-cef_string_userfree_t CEF_CALLBACK
+cef_dom_form_control_type_t CEF_CALLBACK
 domnode_get_form_control_element_type(struct _cef_domnode_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
-    return NULL;
+  if (!self) {
+    return DOM_FORM_CONTROL_TYPE_UNSUPPORTED;
+  }
 
   // Execute
-  CefString _retval = CefDOMNodeCppToC::Get(self)->GetFormControlElementType();
+  cef_dom_form_control_type_t _retval =
+      CefDOMNodeCppToC::Get(self)->GetFormControlElementType();
 
-  // Return type: string
-  return _retval.DetachToUserFree();
+  // Return type: simple
+  return _retval;
 }
 
 int CEF_CALLBACK domnode_is_same(struct _cef_domnode_t* self,
@@ -125,12 +132,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -147,8 +156,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDOMNodeCppToC::Get(self)->GetName();
@@ -164,8 +174,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDOMNodeCppToC::Get(self)->GetValue();
@@ -181,12 +192,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: value; type: string_byref_const
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDOMNodeCppToC::Get(self)->SetValue(CefString(value));
@@ -202,8 +215,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDOMNodeCppToC::Get(self)->GetAsMarkup();
@@ -219,8 +233,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDOMDocument> _retval =
@@ -237,8 +252,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDOMNode> _retval = CefDOMNodeCppToC::Get(self)->GetParent();
@@ -254,8 +270,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDOMNode> _retval =
@@ -272,8 +289,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDOMNode> _retval = CefDOMNodeCppToC::Get(self)->GetNextSibling();
@@ -288,8 +306,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDOMNodeCppToC::Get(self)->HasChildren();
@@ -305,8 +324,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDOMNode> _retval = CefDOMNodeCppToC::Get(self)->GetFirstChild();
@@ -322,8 +342,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDOMNode> _retval = CefDOMNodeCppToC::Get(self)->GetLastChild();
@@ -339,8 +360,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDOMNodeCppToC::Get(self)->GetElementTagName();
@@ -355,8 +377,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDOMNodeCppToC::Get(self)->HasElementAttributes();
@@ -372,12 +395,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: attrName; type: string_byref_const
   DCHECK(attrName);
-  if (!attrName)
+  if (!attrName) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -395,12 +420,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: attrName; type: string_byref_const
   DCHECK(attrName);
-  if (!attrName)
+  if (!attrName) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -417,12 +444,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: attrMap; type: string_map_single_byref
   DCHECK(attrMap);
-  if (!attrMap)
+  if (!attrMap) {
     return;
+  }
 
   // Translate param: attrMap; type: string_map_single_byref
   std::map<CefString, CefString> attrMapMap;
@@ -444,16 +473,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: attrName; type: string_byref_const
   DCHECK(attrName);
-  if (!attrName)
+  if (!attrName) {
     return 0;
+  }
   // Verify param: value; type: string_byref_const
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDOMNodeCppToC::Get(self)->SetElementAttribute(
@@ -470,8 +502,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDOMNodeCppToC::Get(self)->GetElementInnerText();
@@ -487,8 +520,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval = CefDOMNodeCppToC::Get(self)->GetElementBounds();
@@ -542,7 +576,7 @@
 CefCppToCRefCounted<CefDOMNodeCppToC, CefDOMNode, cef_domnode_t>::UnwrapDerived(
     CefWrapperType type,
     cef_domnode_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/domnode_cpptoc.h b/src/libcef_dll/cpptoc/domnode_cpptoc.h
index 080cdc4..c11783f 100644
--- a/src/libcef_dll/cpptoc/domnode_cpptoc.h
+++ b/src/libcef_dll/cpptoc/domnode_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2465c7db31ad903b30220188e139b5e2af213e11$
+// $hash=18f223a2671334b8bd8d463a94b5a3c0191141e8$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_DOMNODE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/domvisitor_cpptoc.cc b/src/libcef_dll/cpptoc/domvisitor_cpptoc.cc
index acfd227..dcb36eb 100644
--- a/src/libcef_dll/cpptoc/domvisitor_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/domvisitor_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d5685ce2cd2731697bf1bd0993b3754374a1a739$
+// $hash=fccbe16b1237f36acf744609774b304eb6de8b98$
 //
 
 #include "libcef_dll/cpptoc/domvisitor_cpptoc.h"
@@ -27,12 +27,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: document; type: refptr_diff
   DCHECK(document);
-  if (!document)
+  if (!document) {
     return;
+  }
 
   // Execute
   CefDOMVisitorCppToC::Get(self)->Visit(CefDOMDocumentCToCpp::Wrap(document));
@@ -56,7 +58,7 @@
 CefRefPtr<CefDOMVisitor>
 CefCppToCRefCounted<CefDOMVisitorCppToC, CefDOMVisitor, cef_domvisitor_t>::
     UnwrapDerived(CefWrapperType type, cef_domvisitor_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/domvisitor_cpptoc.h b/src/libcef_dll/cpptoc/domvisitor_cpptoc.h
index 03ee1bd..3cd81a5 100644
--- a/src/libcef_dll/cpptoc/domvisitor_cpptoc.h
+++ b/src/libcef_dll/cpptoc/domvisitor_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=18ce927902e19740f0be8707b51ca4bb2296e5a5$
+// $hash=2a64ff6edd81d5158997158c91e75b85dbd8da39$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_DOMVISITOR_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/download_handler_cpptoc.cc b/src/libcef_dll/cpptoc/download_handler_cpptoc.cc
index 4c191dc..94edd4c 100644
--- a/src/libcef_dll/cpptoc/download_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/download_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8ea9a11f03f3a303839fd15a0fd55fc2e0b9cd1c$
+// $hash=d388bfeaf7f74152201d083d9142659d0a799391$
 //
 
 #include "libcef_dll/cpptoc/download_handler_cpptoc.h"
@@ -23,6 +23,44 @@
 
 // MEMBER FUNCTIONS - Body may be edited by hand.
 
+int CEF_CALLBACK
+download_handler_can_download(struct _cef_download_handler_t* self,
+                              cef_browser_t* browser,
+                              const cef_string_t* url,
+                              const cef_string_t* request_method) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return 0;
+  }
+  // Verify param: url; type: string_byref_const
+  DCHECK(url);
+  if (!url) {
+    return 0;
+  }
+  // Verify param: request_method; type: string_byref_const
+  DCHECK(request_method);
+  if (!request_method) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefDownloadHandlerCppToC::Get(self)->CanDownload(
+      CefBrowserCToCpp::Wrap(browser), CefString(url),
+      CefString(request_method));
+
+  // Return type: bool
+  return _retval;
+}
+
 void CEF_CALLBACK
 download_handler_on_before_download(struct _cef_download_handler_t* self,
                                     cef_browser_t* browser,
@@ -34,24 +72,29 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: download_item; type: refptr_diff
   DCHECK(download_item);
-  if (!download_item)
+  if (!download_item) {
     return;
+  }
   // Verify param: suggested_name; type: string_byref_const
   DCHECK(suggested_name);
-  if (!suggested_name)
+  if (!suggested_name) {
     return;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return;
+  }
 
   // Execute
   CefDownloadHandlerCppToC::Get(self)->OnBeforeDownload(
@@ -70,20 +113,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: download_item; type: refptr_diff
   DCHECK(download_item);
-  if (!download_item)
+  if (!download_item) {
     return;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return;
+  }
 
   // Execute
   CefDownloadHandlerCppToC::Get(self)->OnDownloadUpdated(
@@ -97,6 +144,7 @@
 // CONSTRUCTOR - Do not edit by hand.
 
 CefDownloadHandlerCppToC::CefDownloadHandlerCppToC() {
+  GetStruct()->can_download = download_handler_can_download;
   GetStruct()->on_before_download = download_handler_on_before_download;
   GetStruct()->on_download_updated = download_handler_on_download_updated;
 }
@@ -113,7 +161,7 @@
     CefDownloadHandler,
     cef_download_handler_t>::UnwrapDerived(CefWrapperType type,
                                            cef_download_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/download_handler_cpptoc.h b/src/libcef_dll/cpptoc/download_handler_cpptoc.h
index 756f245..1c1c6dd 100644
--- a/src/libcef_dll/cpptoc/download_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/download_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=eba4baa6d1dfe09c59314d597d52fa3edd467ee3$
+// $hash=1b301493e2f905a2761858e2d6623765a540f918$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_DOWNLOAD_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/download_image_callback_cpptoc.cc b/src/libcef_dll/cpptoc/download_image_callback_cpptoc.cc
index fa74575..8d2bf5f 100644
--- a/src/libcef_dll/cpptoc/download_image_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/download_image_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c6a390757ebc1cef06464e09bf30a9c19a4e9687$
+// $hash=87ae44d30e4e9b8b28d58910b995212063380ef3$
 //
 
 #include "libcef_dll/cpptoc/download_image_callback_cpptoc.h"
@@ -30,12 +30,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: image_url; type: string_byref_const
   DCHECK(image_url);
-  if (!image_url)
+  if (!image_url) {
     return;
+  }
   // Unverified params: image
 
   // Execute
@@ -65,7 +67,7 @@
     cef_download_image_callback_t>::UnwrapDerived(CefWrapperType type,
                                                   cef_download_image_callback_t*
                                                       s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/download_image_callback_cpptoc.h b/src/libcef_dll/cpptoc/download_image_callback_cpptoc.h
index 8294678..8e517c7 100644
--- a/src/libcef_dll/cpptoc/download_image_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/download_image_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7571f82b08c4cf0abea130e73571449a0a85d656$
+// $hash=9a9250d7e4f3d2018c4b441e6616930627625b59$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_DOWNLOAD_IMAGE_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/download_item_callback_cpptoc.cc b/src/libcef_dll/cpptoc/download_item_callback_cpptoc.cc
index d4f5088..914b547 100644
--- a/src/libcef_dll/cpptoc/download_item_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/download_item_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ee4e0abc682de9b25e143d2c685d46d2bb10f33d$
+// $hash=222759f34997871512b5f89edc78d1b3a0b0cc69$
 //
 
 #include "libcef_dll/cpptoc/download_item_callback_cpptoc.h"
@@ -26,8 +26,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefDownloadItemCallbackCppToC::Get(self)->Cancel();
@@ -40,8 +41,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefDownloadItemCallbackCppToC::Get(self)->Pause();
@@ -54,8 +56,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefDownloadItemCallbackCppToC::Get(self)->Resume();
@@ -84,7 +87,7 @@
     cef_download_item_callback_t>::UnwrapDerived(CefWrapperType type,
                                                  cef_download_item_callback_t*
                                                      s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/download_item_callback_cpptoc.h b/src/libcef_dll/cpptoc/download_item_callback_cpptoc.h
index 5f662c2..858baa2 100644
--- a/src/libcef_dll/cpptoc/download_item_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/download_item_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9262bc6379b8626f3fa0c7dcda4520bde8376880$
+// $hash=1c85860b0d21f2efc1610ed47af70ed570f63926$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_DOWNLOAD_ITEM_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/download_item_cpptoc.cc b/src/libcef_dll/cpptoc/download_item_cpptoc.cc
index 1fe98af..383c6b8 100644
--- a/src/libcef_dll/cpptoc/download_item_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/download_item_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=afaa0b2d6c7abf246c66ba853be937b6905074f1$
+// $hash=e9af4e17ed4b52627002dd4b7c47acee51e81764$
 //
 
 #include "libcef_dll/cpptoc/download_item_cpptoc.h"
@@ -25,8 +25,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDownloadItemCppToC::Get(self)->IsValid();
@@ -42,8 +43,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDownloadItemCppToC::Get(self)->IsInProgress();
@@ -58,8 +60,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDownloadItemCppToC::Get(self)->IsComplete();
@@ -74,8 +77,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDownloadItemCppToC::Get(self)->IsCanceled();
@@ -84,18 +88,56 @@
   return _retval;
 }
 
-int64 CEF_CALLBACK
+int CEF_CALLBACK
+download_item_is_interrupted(struct _cef_download_item_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefDownloadItemCppToC::Get(self)->IsInterrupted();
+
+  // Return type: bool
+  return _retval;
+}
+
+cef_download_interrupt_reason_t CEF_CALLBACK
+download_item_get_interrupt_reason(struct _cef_download_item_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CEF_DOWNLOAD_INTERRUPT_REASON_NONE;
+  }
+
+  // Execute
+  cef_download_interrupt_reason_t _retval =
+      CefDownloadItemCppToC::Get(self)->GetInterruptReason();
+
+  // Return type: simple
+  return _retval;
+}
+
+int64_t CEF_CALLBACK
 download_item_get_current_speed(struct _cef_download_item_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
-  int64 _retval = CefDownloadItemCppToC::Get(self)->GetCurrentSpeed();
+  int64_t _retval = CefDownloadItemCppToC::Get(self)->GetCurrentSpeed();
 
   // Return type: simple
   return _retval;
@@ -108,8 +150,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefDownloadItemCppToC::Get(self)->GetPercentComplete();
@@ -118,69 +161,73 @@
   return _retval;
 }
 
-int64 CEF_CALLBACK
+int64_t CEF_CALLBACK
 download_item_get_total_bytes(struct _cef_download_item_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
-  int64 _retval = CefDownloadItemCppToC::Get(self)->GetTotalBytes();
+  int64_t _retval = CefDownloadItemCppToC::Get(self)->GetTotalBytes();
 
   // Return type: simple
   return _retval;
 }
 
-int64 CEF_CALLBACK
+int64_t CEF_CALLBACK
 download_item_get_received_bytes(struct _cef_download_item_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
-  int64 _retval = CefDownloadItemCppToC::Get(self)->GetReceivedBytes();
+  int64_t _retval = CefDownloadItemCppToC::Get(self)->GetReceivedBytes();
 
   // Return type: simple
   return _retval;
 }
 
-cef_time_t CEF_CALLBACK
+cef_basetime_t CEF_CALLBACK
 download_item_get_start_time(struct _cef_download_item_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
-    return CefTime();
+  if (!self) {
+    return CefBaseTime();
+  }
 
   // Execute
-  cef_time_t _retval = CefDownloadItemCppToC::Get(self)->GetStartTime();
+  cef_basetime_t _retval = CefDownloadItemCppToC::Get(self)->GetStartTime();
 
   // Return type: simple
   return _retval;
 }
 
-cef_time_t CEF_CALLBACK
+cef_basetime_t CEF_CALLBACK
 download_item_get_end_time(struct _cef_download_item_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
-    return CefTime();
+  if (!self) {
+    return CefBaseTime();
+  }
 
   // Execute
-  cef_time_t _retval = CefDownloadItemCppToC::Get(self)->GetEndTime();
+  cef_basetime_t _retval = CefDownloadItemCppToC::Get(self)->GetEndTime();
 
   // Return type: simple
   return _retval;
@@ -193,8 +240,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDownloadItemCppToC::Get(self)->GetFullPath();
@@ -203,17 +251,18 @@
   return _retval.DetachToUserFree();
 }
 
-uint32 CEF_CALLBACK download_item_get_id(struct _cef_download_item_t* self) {
+uint32_t CEF_CALLBACK download_item_get_id(struct _cef_download_item_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
-  uint32 _retval = CefDownloadItemCppToC::Get(self)->GetId();
+  uint32_t _retval = CefDownloadItemCppToC::Get(self)->GetId();
 
   // Return type: simple
   return _retval;
@@ -226,8 +275,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDownloadItemCppToC::Get(self)->GetURL();
@@ -243,8 +293,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDownloadItemCppToC::Get(self)->GetOriginalUrl();
@@ -260,8 +311,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDownloadItemCppToC::Get(self)->GetSuggestedFileName();
@@ -277,8 +329,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDownloadItemCppToC::Get(self)->GetContentDisposition();
@@ -294,8 +347,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDownloadItemCppToC::Get(self)->GetMimeType();
@@ -313,6 +367,8 @@
   GetStruct()->is_in_progress = download_item_is_in_progress;
   GetStruct()->is_complete = download_item_is_complete;
   GetStruct()->is_canceled = download_item_is_canceled;
+  GetStruct()->is_interrupted = download_item_is_interrupted;
+  GetStruct()->get_interrupt_reason = download_item_get_interrupt_reason;
   GetStruct()->get_current_speed = download_item_get_current_speed;
   GetStruct()->get_percent_complete = download_item_get_percent_complete;
   GetStruct()->get_total_bytes = download_item_get_total_bytes;
@@ -340,7 +396,7 @@
     CefDownloadItem,
     cef_download_item_t>::UnwrapDerived(CefWrapperType type,
                                         cef_download_item_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/download_item_cpptoc.h b/src/libcef_dll/cpptoc/download_item_cpptoc.h
index 596af38..dcf26cf 100644
--- a/src/libcef_dll/cpptoc/download_item_cpptoc.h
+++ b/src/libcef_dll/cpptoc/download_item_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=528851326b066ec08ba504200046937f3f90e4c3$
+// $hash=3817a67cd4da8a318fe118f775a86a3daa22af67$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_DOWNLOAD_ITEM_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/drag_data_cpptoc.cc b/src/libcef_dll/cpptoc/drag_data_cpptoc.cc
index 3adeda7..cb95765 100644
--- a/src/libcef_dll/cpptoc/drag_data_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/drag_data_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ce7b68a16458e0d2c6c31e49a5f9896f8f3f1c8b$
+// $hash=14322f994bd6eb8732cef20a3a70fc8ebbf32dea$
 //
 
 #include "libcef_dll/cpptoc/drag_data_cpptoc.h"
@@ -43,8 +43,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDragData> _retval = CefDragDataCppToC::Get(self)->Clone();
@@ -59,8 +60,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDragDataCppToC::Get(self)->IsReadOnly();
@@ -75,8 +77,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDragDataCppToC::Get(self)->IsLink();
@@ -91,8 +94,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDragDataCppToC::Get(self)->IsFragment();
@@ -107,8 +111,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDragDataCppToC::Get(self)->IsFile();
@@ -124,8 +129,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDragDataCppToC::Get(self)->GetLinkURL();
@@ -141,8 +147,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDragDataCppToC::Get(self)->GetLinkTitle();
@@ -158,8 +165,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDragDataCppToC::Get(self)->GetLinkMetadata();
@@ -175,8 +183,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDragDataCppToC::Get(self)->GetFragmentText();
@@ -192,8 +201,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDragDataCppToC::Get(self)->GetFragmentHtml();
@@ -209,8 +219,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDragDataCppToC::Get(self)->GetFragmentBaseURL();
@@ -226,8 +237,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefDragDataCppToC::Get(self)->GetFileName();
@@ -244,8 +256,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Unverified params: writer
 
   // Execute
@@ -263,12 +276,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: names; type: string_vec_byref
   DCHECK(names);
-  if (!names)
+  if (!names) {
     return 0;
+  }
 
   // Translate param: names; type: string_vec_byref
   std::vector<CefString> namesList;
@@ -285,6 +300,38 @@
   return _retval;
 }
 
+int CEF_CALLBACK
+drag_data_get_file_paths(struct _cef_drag_data_t* self,
+                         cef_string_list_t paths) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: paths; type: string_vec_byref
+  DCHECK(paths);
+  if (!paths) {
+    return 0;
+  }
+
+  // Translate param: paths; type: string_vec_byref
+  std::vector<CefString> pathsList;
+  transfer_string_list_contents(paths, pathsList);
+
+  // Execute
+  bool _retval = CefDragDataCppToC::Get(self)->GetFilePaths(pathsList);
+
+  // Restore param: paths; type: string_vec_byref
+  cef_string_list_clear(paths);
+  transfer_string_list_contents(pathsList, paths);
+
+  // Return type: bool
+  return _retval;
+}
+
 void CEF_CALLBACK drag_data_set_link_url(struct _cef_drag_data_t* self,
                                          const cef_string_t* url) {
   shutdown_checker::AssertNotShutdown();
@@ -292,8 +339,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: url
 
   // Execute
@@ -307,8 +355,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: title
 
   // Execute
@@ -322,8 +371,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: data
 
   // Execute
@@ -337,8 +387,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: text
 
   // Execute
@@ -352,8 +403,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: html
 
   // Execute
@@ -368,8 +420,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: base_url
 
   // Execute
@@ -382,8 +435,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefDragDataCppToC::Get(self)->ResetFileContents();
@@ -397,12 +451,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: path; type: string_byref_const
   DCHECK(path);
-  if (!path)
+  if (!path) {
     return;
+  }
   // Unverified params: display_name
 
   // Execute
@@ -410,6 +466,20 @@
                                         CefString(display_name));
 }
 
+void CEF_CALLBACK drag_data_clear_filenames(struct _cef_drag_data_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+
+  // Execute
+  CefDragDataCppToC::Get(self)->ClearFilenames();
+}
+
 struct _cef_image_t* CEF_CALLBACK
 drag_data_get_image(struct _cef_drag_data_t* self) {
   shutdown_checker::AssertNotShutdown();
@@ -417,8 +487,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefImage> _retval = CefDragDataCppToC::Get(self)->GetImage();
@@ -434,8 +505,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefPoint();
+  }
 
   // Execute
   cef_point_t _retval = CefDragDataCppToC::Get(self)->GetImageHotspot();
@@ -450,8 +522,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDragDataCppToC::Get(self)->HasImage();
@@ -479,6 +552,7 @@
   GetStruct()->get_file_name = drag_data_get_file_name;
   GetStruct()->get_file_contents = drag_data_get_file_contents;
   GetStruct()->get_file_names = drag_data_get_file_names;
+  GetStruct()->get_file_paths = drag_data_get_file_paths;
   GetStruct()->set_link_url = drag_data_set_link_url;
   GetStruct()->set_link_title = drag_data_set_link_title;
   GetStruct()->set_link_metadata = drag_data_set_link_metadata;
@@ -487,6 +561,7 @@
   GetStruct()->set_fragment_base_url = drag_data_set_fragment_base_url;
   GetStruct()->reset_file_contents = drag_data_reset_file_contents;
   GetStruct()->add_file = drag_data_add_file;
+  GetStruct()->clear_filenames = drag_data_clear_filenames;
   GetStruct()->get_image = drag_data_get_image;
   GetStruct()->get_image_hotspot = drag_data_get_image_hotspot;
   GetStruct()->has_image = drag_data_has_image;
@@ -502,7 +577,7 @@
 CefRefPtr<CefDragData>
 CefCppToCRefCounted<CefDragDataCppToC, CefDragData, cef_drag_data_t>::
     UnwrapDerived(CefWrapperType type, cef_drag_data_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/drag_data_cpptoc.h b/src/libcef_dll/cpptoc/drag_data_cpptoc.h
index 5fae231..1628e09 100644
--- a/src/libcef_dll/cpptoc/drag_data_cpptoc.h
+++ b/src/libcef_dll/cpptoc/drag_data_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ef1484f9c3402407bb30e660f30223baa14ca978$
+// $hash=4ce3b8cfc691f8cb7aa224a00d7835283c5039ab$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_DRAG_DATA_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/drag_handler_cpptoc.cc b/src/libcef_dll/cpptoc/drag_handler_cpptoc.cc
index cfb5296..e7ad525 100644
--- a/src/libcef_dll/cpptoc/drag_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/drag_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0eb91a630975532db7316d0452b43190f01a2a8c$
+// $hash=eddbb7f93fd3ffa2548b4286ab8cc854366ffc94$
 //
 
 #include "libcef_dll/cpptoc/drag_handler_cpptoc.h"
@@ -31,16 +31,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: dragData; type: refptr_diff
   DCHECK(dragData);
-  if (!dragData)
+  if (!dragData) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDragHandlerCppToC::Get(self)->OnDragEnter(
@@ -61,20 +64,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return;
+  }
   // Verify param: regions; type: simple_vec_byref_const
   DCHECK(regionsCount == 0 || regions);
-  if (regionsCount > 0 && !regions)
+  if (regionsCount > 0 && !regions) {
     return;
+  }
 
   // Translate param: regions; type: simple_vec_byref_const
   std::vector<CefDraggableRegion> regionsList;
@@ -111,7 +118,7 @@
 CefRefPtr<CefDragHandler>
 CefCppToCRefCounted<CefDragHandlerCppToC, CefDragHandler, cef_drag_handler_t>::
     UnwrapDerived(CefWrapperType type, cef_drag_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/drag_handler_cpptoc.h b/src/libcef_dll/cpptoc/drag_handler_cpptoc.h
index 3f055fe..e8f136b 100644
--- a/src/libcef_dll/cpptoc/drag_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/drag_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=39f1e6f246b89d6fd6fdabaf5b3281d5c89cd745$
+// $hash=9d82217b402aa41686392b0ba81169f4b41035e7$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_DRAG_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/end_tracing_callback_cpptoc.cc b/src/libcef_dll/cpptoc/end_tracing_callback_cpptoc.cc
index 65e87b8..059abfd 100644
--- a/src/libcef_dll/cpptoc/end_tracing_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/end_tracing_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=335d8035333e24d5fd8ab4a89279bca09b2629b0$
+// $hash=ec060a21597376bf3cb198d526c83e457869ca64$
 //
 
 #include "libcef_dll/cpptoc/end_tracing_callback_cpptoc.h"
@@ -27,12 +27,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: tracing_file; type: string_byref_const
   DCHECK(tracing_file);
-  if (!tracing_file)
+  if (!tracing_file) {
     return;
+  }
 
   // Execute
   CefEndTracingCallbackCppToC::Get(self)->OnEndTracingComplete(
@@ -60,7 +62,7 @@
     CefEndTracingCallback,
     cef_end_tracing_callback_t>::UnwrapDerived(CefWrapperType type,
                                                cef_end_tracing_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/end_tracing_callback_cpptoc.h b/src/libcef_dll/cpptoc/end_tracing_callback_cpptoc.h
index 33e7a87..c629169 100644
--- a/src/libcef_dll/cpptoc/end_tracing_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/end_tracing_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1651e2c4c6f69e8617844128e3c13a33698e5994$
+// $hash=81dc12ded9752671497f775c397ca120632c4ddb$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_END_TRACING_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/extension_cpptoc.cc b/src/libcef_dll/cpptoc/extension_cpptoc.cc
index b9e6f01..93685ce 100644
--- a/src/libcef_dll/cpptoc/extension_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/extension_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0ba733877b885661d95e5767f05a4ce943982bbc$
+// $hash=d2d5ac3885b178c1fbbf59de4ce71d8cbb6a495d$
 //
 
 #include "libcef_dll/cpptoc/extension_cpptoc.h"
@@ -29,8 +29,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefExtensionCppToC::Get(self)->GetIdentifier();
@@ -46,8 +47,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefExtensionCppToC::Get(self)->GetPath();
@@ -63,8 +65,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDictionaryValue> _retval =
@@ -81,12 +84,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -103,8 +108,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefExtensionHandler> _retval =
@@ -121,8 +127,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefRequestContext> _retval =
@@ -138,8 +145,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefExtensionCppToC::Get(self)->IsLoaded();
@@ -154,8 +162,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefExtensionCppToC::Get(self)->Unload();
@@ -186,7 +195,7 @@
 CefRefPtr<CefExtension>
 CefCppToCRefCounted<CefExtensionCppToC, CefExtension, cef_extension_t>::
     UnwrapDerived(CefWrapperType type, cef_extension_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/extension_cpptoc.h b/src/libcef_dll/cpptoc/extension_cpptoc.h
index c4ad833..32eca73 100644
--- a/src/libcef_dll/cpptoc/extension_cpptoc.h
+++ b/src/libcef_dll/cpptoc/extension_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4482d892bdd649dbd6d103afbc76f9718c6cc163$
+// $hash=924265d65cc81f721d9757d8b4a325260e1848d1$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_EXTENSION_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/extension_handler_cpptoc.cc b/src/libcef_dll/cpptoc/extension_handler_cpptoc.cc
index a338dce..6713b84 100644
--- a/src/libcef_dll/cpptoc/extension_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/extension_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ccd5999e0c5b68720a67e185c2ae1cf46da77963$
+// $hash=268a62ebd9b7d8b14dc1510af1d395768d24e20f$
 //
 
 #include "libcef_dll/cpptoc/extension_handler_cpptoc.h"
@@ -18,6 +18,7 @@
 #include "libcef_dll/ctocpp/extension_ctocpp.h"
 #include "libcef_dll/ctocpp/get_extension_resource_callback_ctocpp.h"
 #include "libcef_dll/shutdown_checker.h"
+#include "libcef_dll/template_util.h"
 
 namespace {
 
@@ -31,8 +32,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefExtensionHandlerCppToC::Get(self)->OnExtensionLoadFailed(result);
@@ -46,12 +48,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: extension; type: refptr_diff
   DCHECK(extension);
-  if (!extension)
+  if (!extension) {
     return;
+  }
 
   // Execute
   CefExtensionHandlerCppToC::Get(self)->OnExtensionLoaded(
@@ -66,12 +70,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: extension; type: refptr_diff
   DCHECK(extension);
-  if (!extension)
+  if (!extension) {
     return;
+  }
 
   // Execute
   CefExtensionHandlerCppToC::Get(self)->OnExtensionUnloaded(
@@ -89,34 +95,45 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: extension; type: refptr_diff
   DCHECK(extension);
-  if (!extension)
+  if (!extension) {
     return 0;
+  }
   // Verify param: url; type: string_byref_const
   DCHECK(url);
-  if (!url)
+  if (!url) {
     return 0;
+  }
   // Verify param: client; type: refptr_same_byref
   DCHECK(client);
-  if (!client)
+  if (!client) {
     return 0;
+  }
   // Verify param: settings; type: struct_byref
   DCHECK(settings);
-  if (!settings)
+  if (!settings) {
     return 0;
+  }
+  if (!template_util::has_valid_size(settings)) {
+    DCHECK(false) << "invalid settings->[base.]size";
+    return 0;
+  }
 
   // Translate param: client; type: refptr_same_byref
   CefRefPtr<CefClient> clientPtr;
-  if (client && *client)
+  if (client && *client) {
     clientPtr = CefClientCppToC::Unwrap(*client);
+  }
   CefClient* clientOrig = clientPtr.get();
   // Translate param: settings; type: struct_byref
   CefBrowserSettings settingsObj;
-  if (settings)
+  if (settings) {
     settingsObj.AttachTo(*settings);
+  }
 
   // Execute
   bool _retval =
@@ -135,8 +152,9 @@
     }
   }
   // Restore param: settings; type: struct_byref
-  if (settings)
+  if (settings) {
     settingsObj.DetachTo(*settings);
+  }
 
   // Return type: bool
   return _retval;
@@ -158,50 +176,69 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: extension; type: refptr_diff
   DCHECK(extension);
-  if (!extension)
+  if (!extension) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: active_browser; type: refptr_diff
   DCHECK(active_browser);
-  if (!active_browser)
+  if (!active_browser) {
     return 0;
+  }
   // Verify param: url; type: string_byref_const
   DCHECK(url);
-  if (!url)
+  if (!url) {
     return 0;
+  }
   // Verify param: windowInfo; type: struct_byref
   DCHECK(windowInfo);
-  if (!windowInfo)
+  if (!windowInfo) {
     return 0;
+  }
+  if (!template_util::has_valid_size(windowInfo)) {
+    DCHECK(false) << "invalid windowInfo->[base.]size";
+    return 0;
+  }
   // Verify param: client; type: refptr_same_byref
   DCHECK(client);
-  if (!client)
+  if (!client) {
     return 0;
+  }
   // Verify param: settings; type: struct_byref
   DCHECK(settings);
-  if (!settings)
+  if (!settings) {
     return 0;
+  }
+  if (!template_util::has_valid_size(settings)) {
+    DCHECK(false) << "invalid settings->[base.]size";
+    return 0;
+  }
 
   // Translate param: windowInfo; type: struct_byref
   CefWindowInfo windowInfoObj;
-  if (windowInfo)
+  if (windowInfo) {
     windowInfoObj.AttachTo(*windowInfo);
+  }
   // Translate param: client; type: refptr_same_byref
   CefRefPtr<CefClient> clientPtr;
-  if (client && *client)
+  if (client && *client) {
     clientPtr = CefClientCppToC::Unwrap(*client);
+  }
   CefClient* clientOrig = clientPtr.get();
   // Translate param: settings; type: struct_byref
   CefBrowserSettings settingsObj;
-  if (settings)
+  if (settings) {
     settingsObj.AttachTo(*settings);
+  }
 
   // Execute
   bool _retval = CefExtensionHandlerCppToC::Get(self)->OnBeforeBrowser(
@@ -210,8 +247,9 @@
       active ? true : false, windowInfoObj, clientPtr, settingsObj);
 
   // Restore param: windowInfo; type: struct_byref
-  if (windowInfo)
+  if (windowInfo) {
     windowInfoObj.DetachTo(*windowInfo);
+  }
   // Restore param: client; type: refptr_same_byref
   if (client) {
     if (clientPtr.get()) {
@@ -223,8 +261,9 @@
     }
   }
   // Restore param: settings; type: struct_byref
-  if (settings)
+  if (settings) {
     settingsObj.DetachTo(*settings);
+  }
 
   // Return type: bool
   return _retval;
@@ -240,16 +279,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: extension; type: refptr_diff
   DCHECK(extension);
-  if (!extension)
+  if (!extension) {
     return NULL;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowser> _retval =
@@ -272,20 +314,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: extension; type: refptr_diff
   DCHECK(extension);
-  if (!extension)
+  if (!extension) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: target_browser; type: refptr_diff
   DCHECK(target_browser);
-  if (!target_browser)
+  if (!target_browser) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefExtensionHandlerCppToC::Get(self)->CanAccessBrowser(
@@ -307,24 +353,29 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: extension; type: refptr_diff
   DCHECK(extension);
-  if (!extension)
+  if (!extension) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: file; type: string_byref_const
   DCHECK(file);
-  if (!file)
+  if (!file) {
     return 0;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefExtensionHandlerCppToC::Get(self)->GetExtensionResource(
@@ -365,7 +416,7 @@
     CefExtensionHandler,
     cef_extension_handler_t>::UnwrapDerived(CefWrapperType type,
                                             cef_extension_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/extension_handler_cpptoc.h b/src/libcef_dll/cpptoc/extension_handler_cpptoc.h
index 02e6752..13b489b 100644
--- a/src/libcef_dll/cpptoc/extension_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/extension_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2672174eeafe66d56aa010b327da95531750be53$
+// $hash=db012b196983395c9684bf1275b638e9ccc57949$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_EXTENSION_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/file_dialog_callback_cpptoc.cc b/src/libcef_dll/cpptoc/file_dialog_callback_cpptoc.cc
index a547568..d10cff2 100644
--- a/src/libcef_dll/cpptoc/file_dialog_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/file_dialog_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0d74adcfb0f820227588ba350859821b842ea3b3$
+// $hash=e203837c6db2beb403d762b9edef23817da8eefc$
 //
 
 #include "libcef_dll/cpptoc/file_dialog_callback_cpptoc.h"
@@ -22,19 +22,15 @@
 
 void CEF_CALLBACK
 file_dialog_callback_cont(struct _cef_file_dialog_callback_t* self,
-                          int selected_accept_filter,
                           cef_string_list_t file_paths) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
-  // Verify param: selected_accept_filter; type: simple_byval
-  DCHECK_GE(selected_accept_filter, 0);
-  if (selected_accept_filter < 0)
-    return;
+  }
   // Unverified params: file_paths
 
   // Translate param: file_paths; type: string_vec_byref_const
@@ -42,8 +38,7 @@
   transfer_string_list_contents(file_paths, file_pathsList);
 
   // Execute
-  CefFileDialogCallbackCppToC::Get(self)->Continue(selected_accept_filter,
-                                                   file_pathsList);
+  CefFileDialogCallbackCppToC::Get(self)->Continue(file_pathsList);
 }
 
 void CEF_CALLBACK
@@ -53,8 +48,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefFileDialogCallbackCppToC::Get(self)->Cancel();
@@ -81,7 +77,7 @@
     CefFileDialogCallback,
     cef_file_dialog_callback_t>::UnwrapDerived(CefWrapperType type,
                                                cef_file_dialog_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/file_dialog_callback_cpptoc.h b/src/libcef_dll/cpptoc/file_dialog_callback_cpptoc.h
index dd2df12..f0a754b 100644
--- a/src/libcef_dll/cpptoc/file_dialog_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/file_dialog_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ca547272f7d8af961ac13db6906ffee9c654f4df$
+// $hash=2db275ca5be351037a0e19531fb2ed4c3af4498d$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_FILE_DIALOG_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/find_handler_cpptoc.cc b/src/libcef_dll/cpptoc/find_handler_cpptoc.cc
index 8f0634a..e2a192e 100644
--- a/src/libcef_dll/cpptoc/find_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/find_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f7bc88a19079bb8133f3fabd7f8d0170c75f9a08$
+// $hash=2df390a069798f60909a11621b3984e7a02cce40$
 //
 
 #include "libcef_dll/cpptoc/find_handler_cpptoc.h"
@@ -32,16 +32,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: selectionRect; type: simple_byref_const
   DCHECK(selectionRect);
-  if (!selectionRect)
+  if (!selectionRect) {
     return;
+  }
 
   // Translate param: selectionRect; type: simple_byref_const
   CefRect selectionRectVal = selectionRect ? *selectionRect : CefRect();
@@ -70,7 +73,7 @@
 CefRefPtr<CefFindHandler>
 CefCppToCRefCounted<CefFindHandlerCppToC, CefFindHandler, cef_find_handler_t>::
     UnwrapDerived(CefWrapperType type, cef_find_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/find_handler_cpptoc.h b/src/libcef_dll/cpptoc/find_handler_cpptoc.h
index 78fefd9..cf30c54 100644
--- a/src/libcef_dll/cpptoc/find_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/find_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0a946a06bef0d92627ff304ef13e75fddbaffc46$
+// $hash=fd8c0866622e63f6564c0b00107ebcb0c82d60fe$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_FIND_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/focus_handler_cpptoc.cc b/src/libcef_dll/cpptoc/focus_handler_cpptoc.cc
index b3e4083..31acfc5 100644
--- a/src/libcef_dll/cpptoc/focus_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/focus_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f506b931a2f5de1d742319863e8d12e7f097d945$
+// $hash=0c39dbbfcbc1d5722ea173a74d287e752f7acfc8$
 //
 
 #include "libcef_dll/cpptoc/focus_handler_cpptoc.h"
@@ -28,12 +28,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefFocusHandlerCppToC::Get(self)->OnTakeFocus(CefBrowserCToCpp::Wrap(browser),
@@ -48,12 +50,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefFocusHandlerCppToC::Get(self)->OnSetFocus(
@@ -70,12 +74,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefFocusHandlerCppToC::Get(self)->OnGotFocus(CefBrowserCToCpp::Wrap(browser));
@@ -103,7 +109,7 @@
     CefFocusHandler,
     cef_focus_handler_t>::UnwrapDerived(CefWrapperType type,
                                         cef_focus_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/focus_handler_cpptoc.h b/src/libcef_dll/cpptoc/focus_handler_cpptoc.h
index baad3c0..1dc59c4 100644
--- a/src/libcef_dll/cpptoc/focus_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/focus_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=dc0aff48844d6f1d2d006b55a9059ffb6bd10e32$
+// $hash=b4e1894b64083f0045302da4840abf664c5a2429$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_FOCUS_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/frame_cpptoc.cc b/src/libcef_dll/cpptoc/frame_cpptoc.cc
index 4f903f8..234bf4c 100644
--- a/src/libcef_dll/cpptoc/frame_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/frame_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=11321a717870d88eef5252908ef9816af632664e$
+// $hash=5f0591547b3df5d32d9772d40d484285fb29efa3$
 //
 
 #include "libcef_dll/cpptoc/frame_cpptoc.h"
@@ -33,8 +33,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefFrameCppToC::Get(self)->IsValid();
@@ -49,8 +50,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefFrameCppToC::Get(self)->Undo();
@@ -62,8 +64,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefFrameCppToC::Get(self)->Redo();
@@ -75,8 +78,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefFrameCppToC::Get(self)->Cut();
@@ -88,8 +92,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefFrameCppToC::Get(self)->Copy();
@@ -101,8 +106,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefFrameCppToC::Get(self)->Paste();
@@ -114,8 +120,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefFrameCppToC::Get(self)->Delete();
@@ -127,8 +134,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefFrameCppToC::Get(self)->SelectAll();
@@ -140,8 +148,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefFrameCppToC::Get(self)->ViewSource();
@@ -154,12 +163,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: visitor; type: refptr_diff
   DCHECK(visitor);
-  if (!visitor)
+  if (!visitor) {
     return;
+  }
 
   // Execute
   CefFrameCppToC::Get(self)->GetSource(CefStringVisitorCToCpp::Wrap(visitor));
@@ -172,12 +183,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: visitor; type: refptr_diff
   DCHECK(visitor);
-  if (!visitor)
+  if (!visitor) {
     return;
+  }
 
   // Execute
   CefFrameCppToC::Get(self)->GetText(CefStringVisitorCToCpp::Wrap(visitor));
@@ -190,12 +203,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: request; type: refptr_same
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return;
+  }
 
   // Execute
   CefFrameCppToC::Get(self)->LoadRequest(CefRequestCppToC::Unwrap(request));
@@ -208,12 +223,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: url; type: string_byref_const
   DCHECK(url);
-  if (!url)
+  if (!url) {
     return;
+  }
 
   // Execute
   CefFrameCppToC::Get(self)->LoadURL(CefString(url));
@@ -228,12 +245,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: code; type: string_byref_const
   DCHECK(code);
-  if (!code)
+  if (!code) {
     return;
+  }
   // Unverified params: script_url
 
   // Execute
@@ -247,8 +266,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefFrameCppToC::Get(self)->IsMain();
@@ -263,8 +283,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefFrameCppToC::Get(self)->IsFocused();
@@ -279,8 +300,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefFrameCppToC::Get(self)->GetName();
@@ -289,17 +311,18 @@
   return _retval.DetachToUserFree();
 }
 
-int64 CEF_CALLBACK frame_get_identifier(struct _cef_frame_t* self) {
+int64_t CEF_CALLBACK frame_get_identifier(struct _cef_frame_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
-  int64 _retval = CefFrameCppToC::Get(self)->GetIdentifier();
+  int64_t _retval = CefFrameCppToC::Get(self)->GetIdentifier();
 
   // Return type: simple
   return _retval;
@@ -311,8 +334,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefFrame> _retval = CefFrameCppToC::Get(self)->GetParent();
@@ -327,8 +351,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefFrameCppToC::Get(self)->GetURL();
@@ -343,8 +368,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowser> _retval = CefFrameCppToC::Get(self)->GetBrowser();
@@ -360,8 +386,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefV8Context> _retval = CefFrameCppToC::Get(self)->GetV8Context();
@@ -377,12 +404,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: visitor; type: refptr_diff
   DCHECK(visitor);
-  if (!visitor)
+  if (!visitor) {
     return;
+  }
 
   // Execute
   CefFrameCppToC::Get(self)->VisitDOM(CefDOMVisitorCToCpp::Wrap(visitor));
@@ -397,16 +426,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: request; type: refptr_same
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return NULL;
+  }
   // Verify param: client; type: refptr_diff
   DCHECK(client);
-  if (!client)
+  if (!client) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefURLRequest> _retval =
@@ -427,12 +459,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: message; type: refptr_same
   DCHECK(message);
-  if (!message)
+  if (!message) {
     return;
+  }
 
   // Execute
   CefFrameCppToC::Get(self)->SendProcessMessage(
@@ -482,7 +516,7 @@
 CefCppToCRefCounted<CefFrameCppToC, CefFrame, cef_frame_t>::UnwrapDerived(
     CefWrapperType type,
     cef_frame_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/frame_cpptoc.h b/src/libcef_dll/cpptoc/frame_cpptoc.h
index 9709d2b..dab9469 100644
--- a/src/libcef_dll/cpptoc/frame_cpptoc.h
+++ b/src/libcef_dll/cpptoc/frame_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0e8ff8890e2d71c776ce964b3811a555c4a23527$
+// $hash=e2af583c7a4b0b6b071e9e96ce8645375902673d$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_FRAME_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/frame_handler_cpptoc.cc b/src/libcef_dll/cpptoc/frame_handler_cpptoc.cc
new file mode 100644
index 0000000..68ae7a4
--- /dev/null
+++ b/src/libcef_dll/cpptoc/frame_handler_cpptoc.cc
@@ -0,0 +1,167 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=73bfc92f74c8cd32ae894b99710c1de5bd5099a0$
+//
+
+#include "libcef_dll/cpptoc/frame_handler_cpptoc.h"
+#include "libcef_dll/ctocpp/browser_ctocpp.h"
+#include "libcef_dll/ctocpp/frame_ctocpp.h"
+#include "libcef_dll/shutdown_checker.h"
+
+namespace {
+
+// MEMBER FUNCTIONS - Body may be edited by hand.
+
+void CEF_CALLBACK
+frame_handler_on_frame_created(struct _cef_frame_handler_t* self,
+                               cef_browser_t* browser,
+                               cef_frame_t* frame) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return;
+  }
+  // Verify param: frame; type: refptr_diff
+  DCHECK(frame);
+  if (!frame) {
+    return;
+  }
+
+  // Execute
+  CefFrameHandlerCppToC::Get(self)->OnFrameCreated(
+      CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame));
+}
+
+void CEF_CALLBACK
+frame_handler_on_frame_attached(struct _cef_frame_handler_t* self,
+                                cef_browser_t* browser,
+                                cef_frame_t* frame,
+                                int reattached) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return;
+  }
+  // Verify param: frame; type: refptr_diff
+  DCHECK(frame);
+  if (!frame) {
+    return;
+  }
+
+  // Execute
+  CefFrameHandlerCppToC::Get(self)->OnFrameAttached(
+      CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame),
+      reattached ? true : false);
+}
+
+void CEF_CALLBACK
+frame_handler_on_frame_detached(struct _cef_frame_handler_t* self,
+                                cef_browser_t* browser,
+                                cef_frame_t* frame) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return;
+  }
+  // Verify param: frame; type: refptr_diff
+  DCHECK(frame);
+  if (!frame) {
+    return;
+  }
+
+  // Execute
+  CefFrameHandlerCppToC::Get(self)->OnFrameDetached(
+      CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame));
+}
+
+void CEF_CALLBACK
+frame_handler_on_main_frame_changed(struct _cef_frame_handler_t* self,
+                                    cef_browser_t* browser,
+                                    cef_frame_t* old_frame,
+                                    cef_frame_t* new_frame) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return;
+  }
+  // Unverified params: old_frame, new_frame
+
+  // Execute
+  CefFrameHandlerCppToC::Get(self)->OnMainFrameChanged(
+      CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(old_frame),
+      CefFrameCToCpp::Wrap(new_frame));
+}
+
+}  // namespace
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefFrameHandlerCppToC::CefFrameHandlerCppToC() {
+  GetStruct()->on_frame_created = frame_handler_on_frame_created;
+  GetStruct()->on_frame_attached = frame_handler_on_frame_attached;
+  GetStruct()->on_frame_detached = frame_handler_on_frame_detached;
+  GetStruct()->on_main_frame_changed = frame_handler_on_main_frame_changed;
+}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefFrameHandlerCppToC::~CefFrameHandlerCppToC() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+CefRefPtr<CefFrameHandler> CefCppToCRefCounted<
+    CefFrameHandlerCppToC,
+    CefFrameHandler,
+    cef_frame_handler_t>::UnwrapDerived(CefWrapperType type,
+                                        cef_frame_handler_t* s) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCppToCRefCounted<CefFrameHandlerCppToC,
+                                   CefFrameHandler,
+                                   cef_frame_handler_t>::kWrapperType =
+    WT_FRAME_HANDLER;
diff --git a/src/libcef_dll/cpptoc/frame_handler_cpptoc.h b/src/libcef_dll/cpptoc/frame_handler_cpptoc.h
new file mode 100644
index 0000000..c553a2d
--- /dev/null
+++ b/src/libcef_dll/cpptoc/frame_handler_cpptoc.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=72b035624f1edff425da000635d111f72186fffc$
+//
+
+#ifndef CEF_LIBCEF_DLL_CPPTOC_FRAME_HANDLER_CPPTOC_H_
+#define CEF_LIBCEF_DLL_CPPTOC_FRAME_HANDLER_CPPTOC_H_
+#pragma once
+
+#if !defined(WRAPPING_CEF_SHARED)
+#error This file can be included wrapper-side only
+#endif
+
+#include "include/capi/cef_frame_handler_capi.h"
+#include "include/cef_frame_handler.h"
+#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
+
+// Wrap a C++ class with a C structure.
+// This class may be instantiated and accessed wrapper-side only.
+class CefFrameHandlerCppToC : public CefCppToCRefCounted<CefFrameHandlerCppToC,
+                                                         CefFrameHandler,
+                                                         cef_frame_handler_t> {
+ public:
+  CefFrameHandlerCppToC();
+  virtual ~CefFrameHandlerCppToC();
+};
+
+#endif  // CEF_LIBCEF_DLL_CPPTOC_FRAME_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/get_extension_resource_callback_cpptoc.cc b/src/libcef_dll/cpptoc/get_extension_resource_callback_cpptoc.cc
index 8c11f6c..3d5a0d8 100644
--- a/src/libcef_dll/cpptoc/get_extension_resource_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/get_extension_resource_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e3b6f2b73933086fdbe54f3073e1182f4f0cd7fb$
+// $hash=961058ad701237a60c8ccbe6ce98c3654c1ae51e$
 //
 
 #include "libcef_dll/cpptoc/get_extension_resource_callback_cpptoc.h"
@@ -28,8 +28,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: stream
 
   // Execute
@@ -44,8 +45,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefGetExtensionResourceCallbackCppToC::Get(self)->Cancel();
@@ -74,7 +76,7 @@
                     cef_get_extension_resource_callback_t>::
     UnwrapDerived(CefWrapperType type,
                   cef_get_extension_resource_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/get_extension_resource_callback_cpptoc.h b/src/libcef_dll/cpptoc/get_extension_resource_callback_cpptoc.h
index 8430d6f..0056536 100644
--- a/src/libcef_dll/cpptoc/get_extension_resource_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/get_extension_resource_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c17b85008c84465dd7c687148dd37b540bb3f9e5$
+// $hash=76b58a0d3f719bb4899c87ec701d89a96a45ae31$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_GET_EXTENSION_RESOURCE_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/image_cpptoc.cc b/src/libcef_dll/cpptoc/image_cpptoc.cc
index c28e1c6..cb40093 100644
--- a/src/libcef_dll/cpptoc/image_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/image_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=5477e0f2a6661422b3e2d719e97f8e76ce0a631c$
+// $hash=beb7882398ddea540b847e5c9fb44ed19f91f125$
 //
 
 #include "libcef_dll/cpptoc/image_cpptoc.h"
@@ -40,8 +40,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefImageCppToC::Get(self)->IsEmpty();
@@ -57,12 +58,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -85,12 +88,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: pixel_data; type: simple_byaddr
   DCHECK(pixel_data);
-  if (!pixel_data)
+  if (!pixel_data) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefImageCppToC::Get(self)->AddBitmap(
@@ -110,12 +115,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: png_data; type: simple_byaddr
   DCHECK(png_data);
-  if (!png_data)
+  if (!png_data) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -134,12 +141,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: jpeg_data; type: simple_byaddr
   DCHECK(jpeg_data);
-  if (!jpeg_data)
+  if (!jpeg_data) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefImageCppToC::Get(self)->AddJPEG(scale_factor, jpeg_data,
@@ -155,8 +164,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefImageCppToC::Get(self)->GetWidth();
@@ -171,8 +181,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefImageCppToC::Get(self)->GetHeight();
@@ -188,8 +199,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefImageCppToC::Get(self)->HasRepresentation(scale_factor);
@@ -205,8 +217,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefImageCppToC::Get(self)->RemoveRepresentation(scale_factor);
@@ -225,20 +238,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: actual_scale_factor; type: simple_byref
   DCHECK(actual_scale_factor);
-  if (!actual_scale_factor)
+  if (!actual_scale_factor) {
     return 0;
+  }
   // Verify param: pixel_width; type: simple_byref
   DCHECK(pixel_width);
-  if (!pixel_width)
+  if (!pixel_width) {
     return 0;
+  }
   // Verify param: pixel_height; type: simple_byref
   DCHECK(pixel_height);
-  if (!pixel_height)
+  if (!pixel_height) {
     return 0;
+  }
 
   // Translate param: actual_scale_factor; type: simple_byref
   float actual_scale_factorVal = actual_scale_factor ? *actual_scale_factor : 0;
@@ -252,14 +269,17 @@
       scale_factor, actual_scale_factorVal, pixel_widthVal, pixel_heightVal);
 
   // Restore param: actual_scale_factor; type: simple_byref
-  if (actual_scale_factor)
+  if (actual_scale_factor) {
     *actual_scale_factor = actual_scale_factorVal;
+  }
   // Restore param: pixel_width; type: simple_byref
-  if (pixel_width)
+  if (pixel_width) {
     *pixel_width = pixel_widthVal;
+  }
   // Restore param: pixel_height; type: simple_byref
-  if (pixel_height)
+  if (pixel_height) {
     *pixel_height = pixel_heightVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -277,16 +297,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: pixel_width; type: simple_byref
   DCHECK(pixel_width);
-  if (!pixel_width)
+  if (!pixel_width) {
     return NULL;
+  }
   // Verify param: pixel_height; type: simple_byref
   DCHECK(pixel_height);
-  if (!pixel_height)
+  if (!pixel_height) {
     return NULL;
+  }
 
   // Translate param: pixel_width; type: simple_byref
   int pixel_widthVal = pixel_width ? *pixel_width : 0;
@@ -298,11 +321,13 @@
       scale_factor, color_type, alpha_type, pixel_widthVal, pixel_heightVal);
 
   // Restore param: pixel_width; type: simple_byref
-  if (pixel_width)
+  if (pixel_width) {
     *pixel_width = pixel_widthVal;
+  }
   // Restore param: pixel_height; type: simple_byref
-  if (pixel_height)
+  if (pixel_height) {
     *pixel_height = pixel_heightVal;
+  }
 
   // Return type: refptr_same
   return CefBinaryValueCppToC::Wrap(_retval);
@@ -319,16 +344,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: pixel_width; type: simple_byref
   DCHECK(pixel_width);
-  if (!pixel_width)
+  if (!pixel_width) {
     return NULL;
+  }
   // Verify param: pixel_height; type: simple_byref
   DCHECK(pixel_height);
-  if (!pixel_height)
+  if (!pixel_height) {
     return NULL;
+  }
 
   // Translate param: pixel_width; type: simple_byref
   int pixel_widthVal = pixel_width ? *pixel_width : 0;
@@ -341,11 +369,13 @@
       pixel_heightVal);
 
   // Restore param: pixel_width; type: simple_byref
-  if (pixel_width)
+  if (pixel_width) {
     *pixel_width = pixel_widthVal;
+  }
   // Restore param: pixel_height; type: simple_byref
-  if (pixel_height)
+  if (pixel_height) {
     *pixel_height = pixel_heightVal;
+  }
 
   // Return type: refptr_same
   return CefBinaryValueCppToC::Wrap(_retval);
@@ -362,16 +392,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: pixel_width; type: simple_byref
   DCHECK(pixel_width);
-  if (!pixel_width)
+  if (!pixel_width) {
     return NULL;
+  }
   // Verify param: pixel_height; type: simple_byref
   DCHECK(pixel_height);
-  if (!pixel_height)
+  if (!pixel_height) {
     return NULL;
+  }
 
   // Translate param: pixel_width; type: simple_byref
   int pixel_widthVal = pixel_width ? *pixel_width : 0;
@@ -383,11 +416,13 @@
       scale_factor, quality, pixel_widthVal, pixel_heightVal);
 
   // Restore param: pixel_width; type: simple_byref
-  if (pixel_width)
+  if (pixel_width) {
     *pixel_width = pixel_widthVal;
+  }
   // Restore param: pixel_height; type: simple_byref
-  if (pixel_height)
+  if (pixel_height) {
     *pixel_height = pixel_heightVal;
+  }
 
   // Return type: refptr_same
   return CefBinaryValueCppToC::Wrap(_retval);
@@ -424,7 +459,7 @@
 CefCppToCRefCounted<CefImageCppToC, CefImage, cef_image_t>::UnwrapDerived(
     CefWrapperType type,
     cef_image_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/image_cpptoc.h b/src/libcef_dll/cpptoc/image_cpptoc.h
index e462543..3f63462 100644
--- a/src/libcef_dll/cpptoc/image_cpptoc.h
+++ b/src/libcef_dll/cpptoc/image_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3424ee809a8269adb20112e55ac448e00f1c2e13$
+// $hash=4ce026e90daa0a4d5d4be0baf1e8dbd3ede5974f$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_IMAGE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc b/src/libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc
index 9837cda..c1e59a4 100644
--- a/src/libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=58e277efebc83d236217f73e080a39e603323ef0$
+// $hash=893e80b636f7ecd2b0e0fae18d1a0e1e568cd3ac$
 //
 
 #include "libcef_dll/cpptoc/jsdialog_callback_cpptoc.h"
@@ -27,8 +27,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: user_input
 
   // Execute
@@ -56,7 +57,7 @@
     CefJSDialogCallback,
     cef_jsdialog_callback_t>::UnwrapDerived(CefWrapperType type,
                                             cef_jsdialog_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/jsdialog_callback_cpptoc.h b/src/libcef_dll/cpptoc/jsdialog_callback_cpptoc.h
index d424a98..772ae28 100644
--- a/src/libcef_dll/cpptoc/jsdialog_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/jsdialog_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9ca357bc7ca56079e4136481bcefba7fe8925b04$
+// $hash=37aac75252a6f35a8abe927ca603849ce98ac1e1$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_JSDIALOG_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc b/src/libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc
index 98daa48..271ca07 100644
--- a/src/libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7ddba7a186923cfd813d205ac5a239459f1c7532$
+// $hash=0e5888697a0b34492333d0e07af507ebedee4b3b$
 //
 
 #include "libcef_dll/cpptoc/jsdialog_handler_cpptoc.h"
@@ -35,20 +35,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return 0;
+  }
   // Verify param: suppress_message; type: bool_byref
   DCHECK(suppress_message);
-  if (!suppress_message)
+  if (!suppress_message) {
     return 0;
+  }
   // Unverified params: origin_url, message_text, default_prompt_text
 
   // Translate param: suppress_message; type: bool_byref
@@ -62,8 +66,9 @@
       CefJSDialogCallbackCToCpp::Wrap(callback), suppress_messageBool);
 
   // Restore param: suppress_message; type: bool_byref
-  if (suppress_message)
+  if (suppress_message) {
     *suppress_message = suppress_messageBool ? true : false;
+  }
 
   // Return type: bool
   return _retval;
@@ -80,16 +85,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return 0;
+  }
   // Unverified params: message_text
 
   // Execute
@@ -109,12 +117,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefJSDialogHandlerCppToC::Get(self)->OnResetDialogState(
@@ -129,12 +139,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefJSDialogHandlerCppToC::Get(self)->OnDialogClosed(
@@ -165,7 +177,7 @@
     CefJSDialogHandler,
     cef_jsdialog_handler_t>::UnwrapDerived(CefWrapperType type,
                                            cef_jsdialog_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/jsdialog_handler_cpptoc.h b/src/libcef_dll/cpptoc/jsdialog_handler_cpptoc.h
index f7f87c3..93f193d 100644
--- a/src/libcef_dll/cpptoc/jsdialog_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/jsdialog_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=82f825e1d4f428e30d33559bc48d0e4d5e978ff5$
+// $hash=c6a25a7ceb346f562302df398305f3d09a7c587d$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_JSDIALOG_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/keyboard_handler_cpptoc.cc b/src/libcef_dll/cpptoc/keyboard_handler_cpptoc.cc
index 426c947..6a282cd 100644
--- a/src/libcef_dll/cpptoc/keyboard_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/keyboard_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8ce97d9d7c49e82243e0c2dc0b31b54b234f49e5$
+// $hash=f663466a6f1faeac7a351bb5af13cb40224b3dc6$
 //
 
 #include "libcef_dll/cpptoc/keyboard_handler_cpptoc.h"
@@ -23,7 +23,7 @@
 int CEF_CALLBACK
 keyboard_handler_on_pre_key_event(struct _cef_keyboard_handler_t* self,
                                   cef_browser_t* browser,
-                                  const struct _cef_key_event_t* event,
+                                  const cef_key_event_t* event,
                                   cef_event_handle_t os_event,
                                   int* is_keyboard_shortcut) {
   shutdown_checker::AssertNotShutdown();
@@ -31,37 +31,40 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
-  // Verify param: event; type: struct_byref_const
+  }
+  // Verify param: event; type: simple_byref_const
   DCHECK(event);
-  if (!event)
+  if (!event) {
     return 0;
+  }
   // Verify param: is_keyboard_shortcut; type: bool_byaddr
   DCHECK(is_keyboard_shortcut);
-  if (!is_keyboard_shortcut)
+  if (!is_keyboard_shortcut) {
     return 0;
+  }
 
-  // Translate param: event; type: struct_byref_const
-  CefKeyEvent eventObj;
-  if (event)
-    eventObj.Set(*event, false);
+  // Translate param: event; type: simple_byref_const
+  CefKeyEvent eventVal = event ? *event : CefKeyEvent();
   // Translate param: is_keyboard_shortcut; type: bool_byaddr
   bool is_keyboard_shortcutBool =
       (is_keyboard_shortcut && *is_keyboard_shortcut) ? true : false;
 
   // Execute
   bool _retval = CefKeyboardHandlerCppToC::Get(self)->OnPreKeyEvent(
-      CefBrowserCToCpp::Wrap(browser), eventObj, os_event,
+      CefBrowserCToCpp::Wrap(browser), eventVal, os_event,
       &is_keyboard_shortcutBool);
 
   // Restore param: is_keyboard_shortcut; type: bool_byaddr
-  if (is_keyboard_shortcut)
+  if (is_keyboard_shortcut) {
     *is_keyboard_shortcut = is_keyboard_shortcutBool ? true : false;
+  }
 
   // Return type: bool
   return _retval;
@@ -70,32 +73,33 @@
 int CEF_CALLBACK
 keyboard_handler_on_key_event(struct _cef_keyboard_handler_t* self,
                               cef_browser_t* browser,
-                              const struct _cef_key_event_t* event,
+                              const cef_key_event_t* event,
                               cef_event_handle_t os_event) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
-  // Verify param: event; type: struct_byref_const
+  }
+  // Verify param: event; type: simple_byref_const
   DCHECK(event);
-  if (!event)
+  if (!event) {
     return 0;
+  }
 
-  // Translate param: event; type: struct_byref_const
-  CefKeyEvent eventObj;
-  if (event)
-    eventObj.Set(*event, false);
+  // Translate param: event; type: simple_byref_const
+  CefKeyEvent eventVal = event ? *event : CefKeyEvent();
 
   // Execute
   bool _retval = CefKeyboardHandlerCppToC::Get(self)->OnKeyEvent(
-      CefBrowserCToCpp::Wrap(browser), eventObj, os_event);
+      CefBrowserCToCpp::Wrap(browser), eventVal, os_event);
 
   // Return type: bool
   return _retval;
@@ -122,7 +126,7 @@
     CefKeyboardHandler,
     cef_keyboard_handler_t>::UnwrapDerived(CefWrapperType type,
                                            cef_keyboard_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/keyboard_handler_cpptoc.h b/src/libcef_dll/cpptoc/keyboard_handler_cpptoc.h
index 07a04ae..9ce294a 100644
--- a/src/libcef_dll/cpptoc/keyboard_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/keyboard_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b9790a5aeff5475ecdcc42559e8a84b3e351b38a$
+// $hash=0798f508afacf2ed239982052247da9cd7f366e9$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_KEYBOARD_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/life_span_handler_cpptoc.cc b/src/libcef_dll/cpptoc/life_span_handler_cpptoc.cc
index 644a3db..bc361ce 100644
--- a/src/libcef_dll/cpptoc/life_span_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/life_span_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3cbbd379676d77a0aadd503ba89a8fbef2f355a3$
+// $hash=4990c06888649a2cb06ba7028f16f9cd762f3ad0$
 //
 
 #include "libcef_dll/cpptoc/life_span_handler_cpptoc.h"
@@ -18,6 +18,7 @@
 #include "libcef_dll/ctocpp/dictionary_value_ctocpp.h"
 #include "libcef_dll/ctocpp/frame_ctocpp.h"
 #include "libcef_dll/shutdown_checker.h"
+#include "libcef_dll/template_util.h"
 
 namespace {
 
@@ -31,7 +32,7 @@
     const cef_string_t* target_frame_name,
     cef_window_open_disposition_t target_disposition,
     int user_gesture,
-    const struct _cef_popup_features_t* popupFeatures,
+    const cef_popup_features_t* popupFeatures,
     cef_window_info_t* windowInfo,
     cef_client_t** client,
     struct _cef_browser_settings_t* settings,
@@ -42,63 +43,83 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return 0;
-  // Verify param: popupFeatures; type: struct_byref_const
+  }
+  // Verify param: popupFeatures; type: simple_byref_const
   DCHECK(popupFeatures);
-  if (!popupFeatures)
+  if (!popupFeatures) {
     return 0;
+  }
   // Verify param: windowInfo; type: struct_byref
   DCHECK(windowInfo);
-  if (!windowInfo)
+  if (!windowInfo) {
     return 0;
+  }
+  if (!template_util::has_valid_size(windowInfo)) {
+    DCHECK(false) << "invalid windowInfo->[base.]size";
+    return 0;
+  }
   // Verify param: client; type: refptr_same_byref
   DCHECK(client);
-  if (!client)
+  if (!client) {
     return 0;
+  }
   // Verify param: settings; type: struct_byref
   DCHECK(settings);
-  if (!settings)
+  if (!settings) {
     return 0;
+  }
+  if (!template_util::has_valid_size(settings)) {
+    DCHECK(false) << "invalid settings->[base.]size";
+    return 0;
+  }
   // Verify param: extra_info; type: refptr_diff_byref
   DCHECK(extra_info);
-  if (!extra_info)
+  if (!extra_info) {
     return 0;
+  }
   // Verify param: no_javascript_access; type: bool_byaddr
   DCHECK(no_javascript_access);
-  if (!no_javascript_access)
+  if (!no_javascript_access) {
     return 0;
+  }
   // Unverified params: target_url, target_frame_name
 
-  // Translate param: popupFeatures; type: struct_byref_const
-  CefPopupFeatures popupFeaturesObj;
-  if (popupFeatures)
-    popupFeaturesObj.Set(*popupFeatures, false);
+  // Translate param: popupFeatures; type: simple_byref_const
+  CefPopupFeatures popupFeaturesVal =
+      popupFeatures ? *popupFeatures : CefPopupFeatures();
   // Translate param: windowInfo; type: struct_byref
   CefWindowInfo windowInfoObj;
-  if (windowInfo)
+  if (windowInfo) {
     windowInfoObj.AttachTo(*windowInfo);
+  }
   // Translate param: client; type: refptr_same_byref
   CefRefPtr<CefClient> clientPtr;
-  if (client && *client)
+  if (client && *client) {
     clientPtr = CefClientCppToC::Unwrap(*client);
+  }
   CefClient* clientOrig = clientPtr.get();
   // Translate param: settings; type: struct_byref
   CefBrowserSettings settingsObj;
-  if (settings)
+  if (settings) {
     settingsObj.AttachTo(*settings);
+  }
   // Translate param: extra_info; type: refptr_diff_byref
   CefRefPtr<CefDictionaryValue> extra_infoPtr;
-  if (extra_info && *extra_info)
+  if (extra_info && *extra_info) {
     extra_infoPtr = CefDictionaryValueCToCpp::Wrap(*extra_info);
+  }
   CefDictionaryValue* extra_infoOrig = extra_infoPtr.get();
   // Translate param: no_javascript_access; type: bool_byaddr
   bool no_javascript_accessBool =
@@ -108,12 +129,13 @@
   bool _retval = CefLifeSpanHandlerCppToC::Get(self)->OnBeforePopup(
       CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame),
       CefString(target_url), CefString(target_frame_name), target_disposition,
-      user_gesture ? true : false, popupFeaturesObj, windowInfoObj, clientPtr,
+      user_gesture ? true : false, popupFeaturesVal, windowInfoObj, clientPtr,
       settingsObj, extra_infoPtr, &no_javascript_accessBool);
 
   // Restore param: windowInfo; type: struct_byref
-  if (windowInfo)
+  if (windowInfo) {
     windowInfoObj.DetachTo(*windowInfo);
+  }
   // Restore param: client; type: refptr_same_byref
   if (client) {
     if (clientPtr.get()) {
@@ -125,8 +147,9 @@
     }
   }
   // Restore param: settings; type: struct_byref
-  if (settings)
+  if (settings) {
     settingsObj.DetachTo(*settings);
+  }
   // Restore param: extra_info; type: refptr_diff_byref
   if (extra_info) {
     if (extra_infoPtr.get()) {
@@ -138,13 +161,134 @@
     }
   }
   // Restore param: no_javascript_access; type: bool_byaddr
-  if (no_javascript_access)
+  if (no_javascript_access) {
     *no_javascript_access = no_javascript_accessBool ? true : false;
+  }
 
   // Return type: bool
   return _retval;
 }
 
+void CEF_CALLBACK life_span_handler_on_before_dev_tools_popup(
+    struct _cef_life_span_handler_t* self,
+    cef_browser_t* browser,
+    cef_window_info_t* windowInfo,
+    cef_client_t** client,
+    struct _cef_browser_settings_t* settings,
+    struct _cef_dictionary_value_t** extra_info,
+    int* use_default_window) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return;
+  }
+  // Verify param: windowInfo; type: struct_byref
+  DCHECK(windowInfo);
+  if (!windowInfo) {
+    return;
+  }
+  if (!template_util::has_valid_size(windowInfo)) {
+    DCHECK(false) << "invalid windowInfo->[base.]size";
+    return;
+  }
+  // Verify param: client; type: refptr_same_byref
+  DCHECK(client);
+  if (!client) {
+    return;
+  }
+  // Verify param: settings; type: struct_byref
+  DCHECK(settings);
+  if (!settings) {
+    return;
+  }
+  if (!template_util::has_valid_size(settings)) {
+    DCHECK(false) << "invalid settings->[base.]size";
+    return;
+  }
+  // Verify param: extra_info; type: refptr_diff_byref
+  DCHECK(extra_info);
+  if (!extra_info) {
+    return;
+  }
+  // Verify param: use_default_window; type: bool_byaddr
+  DCHECK(use_default_window);
+  if (!use_default_window) {
+    return;
+  }
+
+  // Translate param: windowInfo; type: struct_byref
+  CefWindowInfo windowInfoObj;
+  if (windowInfo) {
+    windowInfoObj.AttachTo(*windowInfo);
+  }
+  // Translate param: client; type: refptr_same_byref
+  CefRefPtr<CefClient> clientPtr;
+  if (client && *client) {
+    clientPtr = CefClientCppToC::Unwrap(*client);
+  }
+  CefClient* clientOrig = clientPtr.get();
+  // Translate param: settings; type: struct_byref
+  CefBrowserSettings settingsObj;
+  if (settings) {
+    settingsObj.AttachTo(*settings);
+  }
+  // Translate param: extra_info; type: refptr_diff_byref
+  CefRefPtr<CefDictionaryValue> extra_infoPtr;
+  if (extra_info && *extra_info) {
+    extra_infoPtr = CefDictionaryValueCToCpp::Wrap(*extra_info);
+  }
+  CefDictionaryValue* extra_infoOrig = extra_infoPtr.get();
+  // Translate param: use_default_window; type: bool_byaddr
+  bool use_default_windowBool =
+      (use_default_window && *use_default_window) ? true : false;
+
+  // Execute
+  CefLifeSpanHandlerCppToC::Get(self)->OnBeforeDevToolsPopup(
+      CefBrowserCToCpp::Wrap(browser), windowInfoObj, clientPtr, settingsObj,
+      extra_infoPtr, &use_default_windowBool);
+
+  // Restore param: windowInfo; type: struct_byref
+  if (windowInfo) {
+    windowInfoObj.DetachTo(*windowInfo);
+  }
+  // Restore param: client; type: refptr_same_byref
+  if (client) {
+    if (clientPtr.get()) {
+      if (clientPtr.get() != clientOrig) {
+        *client = CefClientCppToC::Wrap(clientPtr);
+      }
+    } else {
+      *client = nullptr;
+    }
+  }
+  // Restore param: settings; type: struct_byref
+  if (settings) {
+    settingsObj.DetachTo(*settings);
+  }
+  // Restore param: extra_info; type: refptr_diff_byref
+  if (extra_info) {
+    if (extra_infoPtr.get()) {
+      if (extra_infoPtr.get() != extra_infoOrig) {
+        *extra_info = CefDictionaryValueCToCpp::Unwrap(extra_infoPtr);
+      }
+    } else {
+      *extra_info = nullptr;
+    }
+  }
+  // Restore param: use_default_window; type: bool_byaddr
+  if (use_default_window) {
+    *use_default_window = use_default_windowBool ? true : false;
+  }
+}
+
 void CEF_CALLBACK
 life_span_handler_on_after_created(struct _cef_life_span_handler_t* self,
                                    cef_browser_t* browser) {
@@ -153,12 +297,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefLifeSpanHandlerCppToC::Get(self)->OnAfterCreated(
@@ -173,12 +319,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefLifeSpanHandlerCppToC::Get(self)->DoClose(
@@ -196,12 +344,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefLifeSpanHandlerCppToC::Get(self)->OnBeforeClose(
@@ -214,6 +364,8 @@
 
 CefLifeSpanHandlerCppToC::CefLifeSpanHandlerCppToC() {
   GetStruct()->on_before_popup = life_span_handler_on_before_popup;
+  GetStruct()->on_before_dev_tools_popup =
+      life_span_handler_on_before_dev_tools_popup;
   GetStruct()->on_after_created = life_span_handler_on_after_created;
   GetStruct()->do_close = life_span_handler_do_close;
   GetStruct()->on_before_close = life_span_handler_on_before_close;
@@ -231,7 +383,7 @@
     CefLifeSpanHandler,
     cef_life_span_handler_t>::UnwrapDerived(CefWrapperType type,
                                             cef_life_span_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/life_span_handler_cpptoc.h b/src/libcef_dll/cpptoc/life_span_handler_cpptoc.h
index 4e624b0..531314a 100644
--- a/src/libcef_dll/cpptoc/life_span_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/life_span_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e37f0c26fd35ee2f0563f8376f6b5c8dbba9d571$
+// $hash=74c66feec24c563e6f3f32230dcb0dbf45ed9350$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_LIFE_SPAN_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/list_value_cpptoc.cc b/src/libcef_dll/cpptoc/list_value_cpptoc.cc
index c96f2fb..e296fbc 100644
--- a/src/libcef_dll/cpptoc/list_value_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/list_value_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=fb9b9acf2ce3e3a2ba72b2a20e886eb8530b97b4$
+// $hash=1431751cc07f3678e8e893c638391c9701a9e4fb$
 //
 
 #include "libcef_dll/cpptoc/list_value_cpptoc.h"
@@ -42,8 +42,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefListValueCppToC::Get(self)->IsValid();
@@ -58,8 +59,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefListValueCppToC::Get(self)->IsOwned();
@@ -74,8 +76,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefListValueCppToC::Get(self)->IsReadOnly();
@@ -91,12 +94,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -113,12 +118,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -135,8 +142,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefListValue> _retval = CefListValueCppToC::Get(self)->Copy();
@@ -152,8 +160,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefListValueCppToC::Get(self)->SetSize(size);
@@ -168,8 +177,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefListValueCppToC::Get(self)->GetSize();
@@ -184,8 +194,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefListValueCppToC::Get(self)->Clear();
@@ -201,8 +212,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefListValueCppToC::Get(self)->Remove(index);
@@ -218,8 +230,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return VTYPE_INVALID;
+  }
 
   // Execute
   cef_value_type_t _retval = CefListValueCppToC::Get(self)->GetType(index);
@@ -235,8 +248,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefValue> _retval = CefListValueCppToC::Get(self)->GetValue(index);
@@ -252,8 +266,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefListValueCppToC::Get(self)->GetBool(index);
@@ -269,8 +284,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefListValueCppToC::Get(self)->GetInt(index);
@@ -286,8 +302,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   double _retval = CefListValueCppToC::Get(self)->GetDouble(index);
@@ -303,8 +320,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefListValueCppToC::Get(self)->GetString(index);
@@ -320,8 +338,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBinaryValue> _retval =
@@ -338,8 +357,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDictionaryValue> _retval =
@@ -356,8 +376,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefListValue> _retval =
@@ -375,12 +396,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefListValueCppToC::Get(self)->SetValue(
@@ -397,8 +420,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefListValueCppToC::Get(self)->SetNull(index);
@@ -415,8 +439,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -434,8 +459,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefListValueCppToC::Get(self)->SetInt(index, value);
@@ -452,8 +478,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefListValueCppToC::Get(self)->SetDouble(index, value);
@@ -470,8 +497,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Unverified params: value
 
   // Execute
@@ -490,12 +518,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefListValueCppToC::Get(self)->SetBinary(
@@ -513,12 +543,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefListValueCppToC::Get(self)->SetDictionary(
@@ -536,12 +568,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefListValueCppToC::Get(self)->SetList(
@@ -596,7 +630,7 @@
 CefRefPtr<CefListValue>
 CefCppToCRefCounted<CefListValueCppToC, CefListValue, cef_list_value_t>::
     UnwrapDerived(CefWrapperType type, cef_list_value_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/list_value_cpptoc.h b/src/libcef_dll/cpptoc/list_value_cpptoc.h
index ca62e49..3e7b9c5 100644
--- a/src/libcef_dll/cpptoc/list_value_cpptoc.h
+++ b/src/libcef_dll/cpptoc/list_value_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=62f8954aaa96e74dabf98f75695dd8e1e92ebc75$
+// $hash=bb4f6bacea8366b11d1526059c5ad4c3df495630$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_LIST_VALUE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/load_handler_cpptoc.cc b/src/libcef_dll/cpptoc/load_handler_cpptoc.cc
index bf663a6..1d81fa3 100644
--- a/src/libcef_dll/cpptoc/load_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/load_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e404a832b0a8a2d9ddc086c7f4763a4513d8a730$
+// $hash=f43c1cfc04bdda9c887a0f01a97d23b159e47b04$
 //
 
 #include "libcef_dll/cpptoc/load_handler_cpptoc.h"
@@ -32,12 +32,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefLoadHandlerCppToC::Get(self)->OnLoadingStateChange(
@@ -55,16 +57,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return;
+  }
 
   // Execute
   CefLoadHandlerCppToC::Get(self)->OnLoadStart(CefBrowserCToCpp::Wrap(browser),
@@ -81,16 +86,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return;
+  }
 
   // Execute
   CefLoadHandlerCppToC::Get(self)->OnLoadEnd(CefBrowserCToCpp::Wrap(browser),
@@ -109,20 +117,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return;
+  }
   // Verify param: failedUrl; type: string_byref_const
   DCHECK(failedUrl);
-  if (!failedUrl)
+  if (!failedUrl) {
     return;
+  }
   // Unverified params: errorText
 
   // Execute
@@ -152,7 +164,7 @@
 CefRefPtr<CefLoadHandler>
 CefCppToCRefCounted<CefLoadHandlerCppToC, CefLoadHandler, cef_load_handler_t>::
     UnwrapDerived(CefWrapperType type, cef_load_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/load_handler_cpptoc.h b/src/libcef_dll/cpptoc/load_handler_cpptoc.h
index b9b474c..b17e774 100644
--- a/src/libcef_dll/cpptoc/load_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/load_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8f54b9d21cbb223077027f755dd276d7589a32e4$
+// $hash=60feef3855499ffd313c9e10fe4e8a6304acc871$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_LOAD_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/media_access_callback_cpptoc.cc b/src/libcef_dll/cpptoc/media_access_callback_cpptoc.cc
new file mode 100644
index 0000000..5dd841c
--- /dev/null
+++ b/src/libcef_dll/cpptoc/media_access_callback_cpptoc.cc
@@ -0,0 +1,83 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=dd6210f86f9b0a4cc2a6b735fcf3b98a5e541789$
+//
+
+#include "libcef_dll/cpptoc/media_access_callback_cpptoc.h"
+#include "libcef_dll/shutdown_checker.h"
+
+namespace {
+
+// MEMBER FUNCTIONS - Body may be edited by hand.
+
+void CEF_CALLBACK
+media_access_callback_cont(struct _cef_media_access_callback_t* self,
+                           uint32_t allowed_permissions) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+
+  // Execute
+  CefMediaAccessCallbackCppToC::Get(self)->Continue(allowed_permissions);
+}
+
+void CEF_CALLBACK
+media_access_callback_cancel(struct _cef_media_access_callback_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+
+  // Execute
+  CefMediaAccessCallbackCppToC::Get(self)->Cancel();
+}
+
+}  // namespace
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefMediaAccessCallbackCppToC::CefMediaAccessCallbackCppToC() {
+  GetStruct()->cont = media_access_callback_cont;
+  GetStruct()->cancel = media_access_callback_cancel;
+}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefMediaAccessCallbackCppToC::~CefMediaAccessCallbackCppToC() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+CefRefPtr<CefMediaAccessCallback> CefCppToCRefCounted<
+    CefMediaAccessCallbackCppToC,
+    CefMediaAccessCallback,
+    cef_media_access_callback_t>::UnwrapDerived(CefWrapperType type,
+                                                cef_media_access_callback_t*
+                                                    s) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCppToCRefCounted<CefMediaAccessCallbackCppToC,
+                                   CefMediaAccessCallback,
+                                   cef_media_access_callback_t>::kWrapperType =
+    WT_MEDIA_ACCESS_CALLBACK;
diff --git a/src/libcef_dll/cpptoc/media_access_callback_cpptoc.h b/src/libcef_dll/cpptoc/media_access_callback_cpptoc.h
new file mode 100644
index 0000000..9609f4e
--- /dev/null
+++ b/src/libcef_dll/cpptoc/media_access_callback_cpptoc.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=4b3da65396a9a358cbcdb289e275062a7b4402d5$
+//
+
+#ifndef CEF_LIBCEF_DLL_CPPTOC_MEDIA_ACCESS_CALLBACK_CPPTOC_H_
+#define CEF_LIBCEF_DLL_CPPTOC_MEDIA_ACCESS_CALLBACK_CPPTOC_H_
+#pragma once
+
+#if !defined(BUILDING_CEF_SHARED)
+#error This file can be included DLL-side only
+#endif
+
+#include "include/capi/cef_permission_handler_capi.h"
+#include "include/cef_permission_handler.h"
+#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
+
+// Wrap a C++ class with a C structure.
+// This class may be instantiated and accessed DLL-side only.
+class CefMediaAccessCallbackCppToC
+    : public CefCppToCRefCounted<CefMediaAccessCallbackCppToC,
+                                 CefMediaAccessCallback,
+                                 cef_media_access_callback_t> {
+ public:
+  CefMediaAccessCallbackCppToC();
+  virtual ~CefMediaAccessCallbackCppToC();
+};
+
+#endif  // CEF_LIBCEF_DLL_CPPTOC_MEDIA_ACCESS_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/media_observer_cpptoc.cc b/src/libcef_dll/cpptoc/media_observer_cpptoc.cc
index 5026161..10bb22b 100644
--- a/src/libcef_dll/cpptoc/media_observer_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/media_observer_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=35f0e881b5a98c1da73789ecb72254fbe254a350$
+// $hash=22f71b1cb703d48b29d6e4eefb294fd713b5bf0e$
 //
 
 #include "libcef_dll/cpptoc/media_observer_cpptoc.h"
@@ -30,12 +30,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: sinks; type: refptr_vec_diff_byref_const
   DCHECK(sinksCount == 0 || sinks);
-  if (sinksCount > 0 && !sinks)
+  if (sinksCount > 0 && !sinks) {
     return;
+  }
 
   // Translate param: sinks; type: refptr_vec_diff_byref_const
   std::vector<CefRefPtr<CefMediaSink>> sinksList;
@@ -59,12 +61,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: routes; type: refptr_vec_diff_byref_const
   DCHECK(routesCount == 0 || routes);
-  if (routesCount > 0 && !routes)
+  if (routesCount > 0 && !routes) {
     return;
+  }
 
   // Translate param: routes; type: refptr_vec_diff_byref_const
   std::vector<CefRefPtr<CefMediaRoute>> routesList;
@@ -88,12 +92,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: route; type: refptr_diff
   DCHECK(route);
-  if (!route)
+  if (!route) {
     return;
+  }
 
   // Execute
   CefMediaObserverCppToC::Get(self)->OnRouteStateChanged(
@@ -110,16 +116,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: route; type: refptr_diff
   DCHECK(route);
-  if (!route)
+  if (!route) {
     return;
+  }
   // Verify param: message; type: simple_byaddr
   DCHECK(message);
-  if (!message)
+  if (!message) {
     return;
+  }
 
   // Execute
   CefMediaObserverCppToC::Get(self)->OnRouteMessageReceived(
@@ -150,7 +159,7 @@
     CefMediaObserver,
     cef_media_observer_t>::UnwrapDerived(CefWrapperType type,
                                          cef_media_observer_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/media_observer_cpptoc.h b/src/libcef_dll/cpptoc/media_observer_cpptoc.h
index 77745a0..0161197 100644
--- a/src/libcef_dll/cpptoc/media_observer_cpptoc.h
+++ b/src/libcef_dll/cpptoc/media_observer_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=14ef1b6f920a375e585174e4057c66221f3e1c05$
+// $hash=79a189744a4f09ec791d9636b247f090aa2cae58$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_MEDIA_OBSERVER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/media_route_cpptoc.cc b/src/libcef_dll/cpptoc/media_route_cpptoc.cc
index a0f3624..ebd18ba 100644
--- a/src/libcef_dll/cpptoc/media_route_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/media_route_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=47181b936b29037dd4ff5169d7175ac538f5be56$
+// $hash=3273e6b77a9d01d328b538480cfd2fb0ed45201c$
 //
 
 #include "libcef_dll/cpptoc/media_route_cpptoc.h"
@@ -28,8 +28,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefMediaRouteCppToC::Get(self)->GetId();
@@ -45,8 +46,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefMediaSource> _retval =
@@ -63,8 +65,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefMediaSink> _retval = CefMediaRouteCppToC::Get(self)->GetSink();
@@ -82,12 +85,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: message; type: simple_byaddr
   DCHECK(message);
-  if (!message)
+  if (!message) {
     return;
+  }
 
   // Execute
   CefMediaRouteCppToC::Get(self)->SendRouteMessage(message, message_size);
@@ -99,8 +104,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMediaRouteCppToC::Get(self)->Terminate();
@@ -128,7 +134,7 @@
 CefRefPtr<CefMediaRoute>
 CefCppToCRefCounted<CefMediaRouteCppToC, CefMediaRoute, cef_media_route_t>::
     UnwrapDerived(CefWrapperType type, cef_media_route_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/media_route_cpptoc.h b/src/libcef_dll/cpptoc/media_route_cpptoc.h
index a30c27d..c204275 100644
--- a/src/libcef_dll/cpptoc/media_route_cpptoc.h
+++ b/src/libcef_dll/cpptoc/media_route_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=26fe0f9bd956318d0e6c7e0216024b5b839429c2$
+// $hash=3489d6674c9411c8240767db40adff59a6f2ae4e$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_MEDIA_ROUTE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/media_route_create_callback_cpptoc.cc b/src/libcef_dll/cpptoc/media_route_create_callback_cpptoc.cc
index bef28ee..e54a418 100644
--- a/src/libcef_dll/cpptoc/media_route_create_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/media_route_create_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=a27462c4bcc0ef4856230997718f95edae5c1ef1$
+// $hash=35856cbf3eaacfdeceed8d49fa1e6ae066d21fe7$
 //
 
 #include "libcef_dll/cpptoc/media_route_create_callback_cpptoc.h"
@@ -30,8 +30,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: error, route
 
   // Execute
@@ -60,7 +61,7 @@
                     CefMediaRouteCreateCallback,
                     cef_media_route_create_callback_t>::
     UnwrapDerived(CefWrapperType type, cef_media_route_create_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/media_route_create_callback_cpptoc.h b/src/libcef_dll/cpptoc/media_route_create_callback_cpptoc.h
index 019d215..b28004c 100644
--- a/src/libcef_dll/cpptoc/media_route_create_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/media_route_create_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8085b195054f43f67d4ee21d8b69b9e0ee8e2ac3$
+// $hash=d40e59390639a5fb850103f7b8a458e3bc1c8f55$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_MEDIA_ROUTE_CREATE_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/media_router_cpptoc.cc b/src/libcef_dll/cpptoc/media_router_cpptoc.cc
index 9bad391..176424d 100644
--- a/src/libcef_dll/cpptoc/media_router_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/media_router_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,26 +9,31 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6b52fceffec99c0f274b5031266c20da5480d0c1$
+// $hash=e98de61436e52c5be6153cc4e3644962259eddeb$
 //
 
 #include "libcef_dll/cpptoc/media_router_cpptoc.h"
 #include "libcef_dll/cpptoc/media_sink_cpptoc.h"
 #include "libcef_dll/cpptoc/media_source_cpptoc.h"
 #include "libcef_dll/cpptoc/registration_cpptoc.h"
+#include "libcef_dll/ctocpp/completion_callback_ctocpp.h"
 #include "libcef_dll/ctocpp/media_observer_ctocpp.h"
 #include "libcef_dll/ctocpp/media_route_create_callback_ctocpp.h"
 #include "libcef_dll/shutdown_checker.h"
 
 // GLOBAL FUNCTIONS - Body may be edited by hand.
 
-CEF_EXPORT cef_media_router_t* cef_media_router_get_global() {
+CEF_EXPORT cef_media_router_t* cef_media_router_get_global(
+    cef_completion_callback_t* callback) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
+  // Unverified params: callback
+
   // Execute
-  CefRefPtr<CefMediaRouter> _retval = CefMediaRouter::GetGlobalMediaRouter();
+  CefRefPtr<CefMediaRouter> _retval = CefMediaRouter::GetGlobalMediaRouter(
+      CefCompletionCallbackCToCpp::Wrap(callback));
 
   // Return type: refptr_same
   return CefMediaRouterCppToC::Wrap(_retval);
@@ -46,12 +51,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: observer; type: refptr_diff
   DCHECK(observer);
-  if (!observer)
+  if (!observer) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefRegistration> _retval =
@@ -70,12 +77,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: urn; type: string_byref_const
   DCHECK(urn);
-  if (!urn)
+  if (!urn) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefMediaSource> _retval =
@@ -92,8 +101,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMediaRouterCppToC::Get(self)->NotifyCurrentSinks();
@@ -109,20 +119,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: source; type: refptr_same
   DCHECK(source);
-  if (!source)
+  if (!source) {
     return;
+  }
   // Verify param: sink; type: refptr_same
   DCHECK(sink);
-  if (!sink)
+  if (!sink) {
     return;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return;
+  }
 
   // Execute
   CefMediaRouterCppToC::Get(self)->CreateRoute(
@@ -137,8 +151,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMediaRouterCppToC::Get(self)->NotifyCurrentRoutes();
@@ -166,7 +181,7 @@
 CefRefPtr<CefMediaRouter>
 CefCppToCRefCounted<CefMediaRouterCppToC, CefMediaRouter, cef_media_router_t>::
     UnwrapDerived(CefWrapperType type, cef_media_router_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/media_router_cpptoc.h b/src/libcef_dll/cpptoc/media_router_cpptoc.h
index e8aaab5..f7d5c93 100644
--- a/src/libcef_dll/cpptoc/media_router_cpptoc.h
+++ b/src/libcef_dll/cpptoc/media_router_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=cea747c7202b95684b7208a312da818ddb094c0a$
+// $hash=9b393780a7f736211be3b2ac604af8b59226db5e$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_MEDIA_ROUTER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/media_sink_cpptoc.cc b/src/libcef_dll/cpptoc/media_sink_cpptoc.cc
index 2a6258f..0b71f1c 100644
--- a/src/libcef_dll/cpptoc/media_sink_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/media_sink_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f9893b2a7c5cd519d32d06a022e503340aa66bc3$
+// $hash=34cf5c3fde544a2f8a323ea3f55ed88db0010672$
 //
 
 #include "libcef_dll/cpptoc/media_sink_cpptoc.h"
@@ -28,8 +28,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefMediaSinkCppToC::Get(self)->GetId();
@@ -38,22 +39,6 @@
   return _retval.DetachToUserFree();
 }
 
-int CEF_CALLBACK media_sink_is_valid(struct _cef_media_sink_t* self) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return 0;
-
-  // Execute
-  bool _retval = CefMediaSinkCppToC::Get(self)->IsValid();
-
-  // Return type: bool
-  return _retval;
-}
-
 cef_string_userfree_t CEF_CALLBACK
 media_sink_get_name(struct _cef_media_sink_t* self) {
   shutdown_checker::AssertNotShutdown();
@@ -61,8 +46,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefMediaSinkCppToC::Get(self)->GetName();
@@ -71,23 +57,6 @@
   return _retval.DetachToUserFree();
 }
 
-cef_string_userfree_t CEF_CALLBACK
-media_sink_get_description(struct _cef_media_sink_t* self) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return NULL;
-
-  // Execute
-  CefString _retval = CefMediaSinkCppToC::Get(self)->GetDescription();
-
-  // Return type: string
-  return _retval.DetachToUserFree();
-}
-
 cef_media_sink_icon_type_t CEF_CALLBACK
 media_sink_get_icon_type(struct _cef_media_sink_t* self) {
   shutdown_checker::AssertNotShutdown();
@@ -95,8 +64,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CEF_MSIT_GENERIC;
+  }
 
   // Execute
   cef_media_sink_icon_type_t _retval =
@@ -114,12 +84,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return;
+  }
 
   // Execute
   CefMediaSinkCppToC::Get(self)->GetDeviceInfo(
@@ -132,8 +104,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMediaSinkCppToC::Get(self)->IsCastSink();
@@ -148,8 +121,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMediaSinkCppToC::Get(self)->IsDialSink();
@@ -166,12 +140,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: source; type: refptr_same
   DCHECK(source);
-  if (!source)
+  if (!source) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMediaSinkCppToC::Get(self)->IsCompatibleWith(
@@ -187,9 +163,7 @@
 
 CefMediaSinkCppToC::CefMediaSinkCppToC() {
   GetStruct()->get_id = media_sink_get_id;
-  GetStruct()->is_valid = media_sink_is_valid;
   GetStruct()->get_name = media_sink_get_name;
-  GetStruct()->get_description = media_sink_get_description;
   GetStruct()->get_icon_type = media_sink_get_icon_type;
   GetStruct()->get_device_info = media_sink_get_device_info;
   GetStruct()->is_cast_sink = media_sink_is_cast_sink;
@@ -207,7 +181,7 @@
 CefRefPtr<CefMediaSink>
 CefCppToCRefCounted<CefMediaSinkCppToC, CefMediaSink, cef_media_sink_t>::
     UnwrapDerived(CefWrapperType type, cef_media_sink_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/media_sink_cpptoc.h b/src/libcef_dll/cpptoc/media_sink_cpptoc.h
index 315e520..3252cf2 100644
--- a/src/libcef_dll/cpptoc/media_sink_cpptoc.h
+++ b/src/libcef_dll/cpptoc/media_sink_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=409478c735898bd4e13315183e185a80ae570b74$
+// $hash=233a4ba3634b10b92d605e85bb49ccb7f4e0abe3$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_MEDIA_SINK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/media_sink_device_info_callback_cpptoc.cc b/src/libcef_dll/cpptoc/media_sink_device_info_callback_cpptoc.cc
index 33ca0b7..ffc288a 100644
--- a/src/libcef_dll/cpptoc/media_sink_device_info_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/media_sink_device_info_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,11 +9,12 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c22023ad9e7d7d80d72729dbebdf03f0b60f4dc9$
+// $hash=9e43a07b0d4886995b29b55315fe8397641293df$
 //
 
 #include "libcef_dll/cpptoc/media_sink_device_info_callback_cpptoc.h"
 #include "libcef_dll/shutdown_checker.h"
+#include "libcef_dll/template_util.h"
 
 namespace {
 
@@ -27,17 +28,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: device_info; type: struct_byref_const
   DCHECK(device_info);
-  if (!device_info)
+  if (!device_info) {
     return;
+  }
+  if (!template_util::has_valid_size(device_info)) {
+    DCHECK(false) << "invalid device_info->[base.]size";
+    return;
+  }
 
   // Translate param: device_info; type: struct_byref_const
   CefMediaSinkDeviceInfo device_infoObj;
-  if (device_info)
+  if (device_info) {
     device_infoObj.Set(*device_info, false);
+  }
 
   // Execute
   CefMediaSinkDeviceInfoCallbackCppToC::Get(self)->OnMediaSinkDeviceInfo(
@@ -66,7 +74,7 @@
                     cef_media_sink_device_info_callback_t>::
     UnwrapDerived(CefWrapperType type,
                   cef_media_sink_device_info_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/media_sink_device_info_callback_cpptoc.h b/src/libcef_dll/cpptoc/media_sink_device_info_callback_cpptoc.h
index 87c5d5c..0522de7 100644
--- a/src/libcef_dll/cpptoc/media_sink_device_info_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/media_sink_device_info_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=5313c2346d5db18dca956f2dac98b73e049a4995$
+// $hash=66fb13a617c9405f7829e797b21a663e5275e61d$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_MEDIA_SINK_DEVICE_INFO_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/media_source_cpptoc.cc b/src/libcef_dll/cpptoc/media_source_cpptoc.cc
index 09b9394..f84810e 100644
--- a/src/libcef_dll/cpptoc/media_source_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/media_source_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ddd51b3c8020de1b10b00eef06d745a498168323$
+// $hash=28f41d6cd0959174263b1cf5d1da37b4fe4c463b$
 //
 
 #include "libcef_dll/cpptoc/media_source_cpptoc.h"
@@ -26,8 +26,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefMediaSourceCppToC::Get(self)->GetId();
@@ -36,30 +37,15 @@
   return _retval.DetachToUserFree();
 }
 
-int CEF_CALLBACK media_source_is_valid(struct _cef_media_source_t* self) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return 0;
-
-  // Execute
-  bool _retval = CefMediaSourceCppToC::Get(self)->IsValid();
-
-  // Return type: bool
-  return _retval;
-}
-
 int CEF_CALLBACK media_source_is_cast_source(struct _cef_media_source_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMediaSourceCppToC::Get(self)->IsCastSource();
@@ -74,8 +60,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMediaSourceCppToC::Get(self)->IsDialSource();
@@ -90,7 +77,6 @@
 
 CefMediaSourceCppToC::CefMediaSourceCppToC() {
   GetStruct()->get_id = media_source_get_id;
-  GetStruct()->is_valid = media_source_is_valid;
   GetStruct()->is_cast_source = media_source_is_cast_source;
   GetStruct()->is_dial_source = media_source_is_dial_source;
 }
@@ -105,7 +91,7 @@
 CefRefPtr<CefMediaSource>
 CefCppToCRefCounted<CefMediaSourceCppToC, CefMediaSource, cef_media_source_t>::
     UnwrapDerived(CefWrapperType type, cef_media_source_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/media_source_cpptoc.h b/src/libcef_dll/cpptoc/media_source_cpptoc.h
index e8810bc..25f10d6 100644
--- a/src/libcef_dll/cpptoc/media_source_cpptoc.h
+++ b/src/libcef_dll/cpptoc/media_source_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=aceafab724145242461fc9f5e7c76a365bb6d54c$
+// $hash=ac61adb518bfd33bcc31e62410a1849dbf73dc3f$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_MEDIA_SOURCE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/menu_model_cpptoc.cc b/src/libcef_dll/cpptoc/menu_model_cpptoc.cc
index be37782..c8b2573 100644
--- a/src/libcef_dll/cpptoc/menu_model_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/menu_model_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=eb78e3b37b654734b8b28449b713cc3eb3b9070d$
+// $hash=e41fe8c89bde5a6883bb523230c3067900c85827$
 //
 
 #include "libcef_dll/cpptoc/menu_model_cpptoc.h"
@@ -26,8 +26,9 @@
 
   // Verify param: delegate; type: refptr_diff
   DCHECK(delegate);
-  if (!delegate)
+  if (!delegate) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefMenuModel> _retval =
@@ -47,8 +48,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->IsSubMenu();
@@ -63,8 +65,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->Clear();
@@ -73,17 +76,18 @@
   return _retval;
 }
 
-int CEF_CALLBACK menu_model_get_count(struct _cef_menu_model_t* self) {
+size_t CEF_CALLBACK menu_model_get_count(struct _cef_menu_model_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
-  int _retval = CefMenuModelCppToC::Get(self)->GetCount();
+  size_t _retval = CefMenuModelCppToC::Get(self)->GetCount();
 
   // Return type: simple
   return _retval;
@@ -95,8 +99,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->AddSeparator();
@@ -113,12 +118,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: label; type: string_byref_const
   DCHECK(label);
-  if (!label)
+  if (!label) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -136,12 +143,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: label; type: string_byref_const
   DCHECK(label);
-  if (!label)
+  if (!label) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -160,12 +169,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: label; type: string_byref_const
   DCHECK(label);
-  if (!label)
+  if (!label) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->AddRadioItem(
@@ -184,12 +195,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: label; type: string_byref_const
   DCHECK(label);
-  if (!label)
+  if (!label) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefMenuModel> _retval =
@@ -200,14 +213,15 @@
 }
 
 int CEF_CALLBACK menu_model_insert_separator_at(struct _cef_menu_model_t* self,
-                                                int index) {
+                                                size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->InsertSeparatorAt(index);
@@ -217,7 +231,7 @@
 }
 
 int CEF_CALLBACK menu_model_insert_item_at(struct _cef_menu_model_t* self,
-                                           int index,
+                                           size_t index,
                                            int command_id,
                                            const cef_string_t* label) {
   shutdown_checker::AssertNotShutdown();
@@ -225,12 +239,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: label; type: string_byref_const
   DCHECK(label);
-  if (!label)
+  if (!label) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->InsertItemAt(index, command_id,
@@ -241,7 +257,7 @@
 }
 
 int CEF_CALLBACK menu_model_insert_check_item_at(struct _cef_menu_model_t* self,
-                                                 int index,
+                                                 size_t index,
                                                  int command_id,
                                                  const cef_string_t* label) {
   shutdown_checker::AssertNotShutdown();
@@ -249,12 +265,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: label; type: string_byref_const
   DCHECK(label);
-  if (!label)
+  if (!label) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->InsertCheckItemAt(
@@ -265,7 +283,7 @@
 }
 
 int CEF_CALLBACK menu_model_insert_radio_item_at(struct _cef_menu_model_t* self,
-                                                 int index,
+                                                 size_t index,
                                                  int command_id,
                                                  const cef_string_t* label,
                                                  int group_id) {
@@ -274,12 +292,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: label; type: string_byref_const
   DCHECK(label);
-  if (!label)
+  if (!label) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->InsertRadioItemAt(
@@ -291,7 +311,7 @@
 
 struct _cef_menu_model_t* CEF_CALLBACK
 menu_model_insert_sub_menu_at(struct _cef_menu_model_t* self,
-                              int index,
+                              size_t index,
                               int command_id,
                               const cef_string_t* label) {
   shutdown_checker::AssertNotShutdown();
@@ -299,12 +319,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: label; type: string_byref_const
   DCHECK(label);
-  if (!label)
+  if (!label) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefMenuModel> _retval =
@@ -322,8 +344,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->Remove(command_id);
@@ -333,14 +356,15 @@
 }
 
 int CEF_CALLBACK menu_model_remove_at(struct _cef_menu_model_t* self,
-                                      int index) {
+                                      size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->RemoveAt(index);
@@ -356,8 +380,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefMenuModelCppToC::Get(self)->GetIndexOf(command_id);
@@ -367,14 +392,15 @@
 }
 
 int CEF_CALLBACK menu_model_get_command_id_at(struct _cef_menu_model_t* self,
-                                              int index) {
+                                              size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefMenuModelCppToC::Get(self)->GetCommandIdAt(index);
@@ -384,15 +410,16 @@
 }
 
 int CEF_CALLBACK menu_model_set_command_id_at(struct _cef_menu_model_t* self,
-                                              int index,
+                                              size_t index,
                                               int command_id) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -409,8 +436,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefMenuModelCppToC::Get(self)->GetLabel(command_id);
@@ -420,14 +448,15 @@
 }
 
 cef_string_userfree_t CEF_CALLBACK
-menu_model_get_label_at(struct _cef_menu_model_t* self, int index) {
+menu_model_get_label_at(struct _cef_menu_model_t* self, size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefMenuModelCppToC::Get(self)->GetLabelAt(index);
@@ -444,12 +473,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: label; type: string_byref_const
   DCHECK(label);
-  if (!label)
+  if (!label) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -460,19 +491,21 @@
 }
 
 int CEF_CALLBACK menu_model_set_label_at(struct _cef_menu_model_t* self,
-                                         int index,
+                                         size_t index,
                                          const cef_string_t* label) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: label; type: string_byref_const
   DCHECK(label);
-  if (!label)
+  if (!label) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -489,8 +522,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return MENUITEMTYPE_NONE;
+  }
 
   // Execute
   cef_menu_item_type_t _retval =
@@ -501,14 +535,15 @@
 }
 
 cef_menu_item_type_t CEF_CALLBACK
-menu_model_get_type_at(struct _cef_menu_model_t* self, int index) {
+menu_model_get_type_at(struct _cef_menu_model_t* self, size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return MENUITEMTYPE_NONE;
+  }
 
   // Execute
   cef_menu_item_type_t _retval =
@@ -525,8 +560,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefMenuModelCppToC::Get(self)->GetGroupId(command_id);
@@ -536,14 +572,15 @@
 }
 
 int CEF_CALLBACK menu_model_get_group_id_at(struct _cef_menu_model_t* self,
-                                            int index) {
+                                            size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefMenuModelCppToC::Get(self)->GetGroupIdAt(index);
@@ -560,8 +597,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -572,15 +610,16 @@
 }
 
 int CEF_CALLBACK menu_model_set_group_id_at(struct _cef_menu_model_t* self,
-                                            int index,
+                                            size_t index,
                                             int group_id) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->SetGroupIdAt(index, group_id);
@@ -596,8 +635,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefMenuModel> _retval =
@@ -608,14 +648,15 @@
 }
 
 struct _cef_menu_model_t* CEF_CALLBACK
-menu_model_get_sub_menu_at(struct _cef_menu_model_t* self, int index) {
+menu_model_get_sub_menu_at(struct _cef_menu_model_t* self, size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefMenuModel> _retval =
@@ -632,8 +673,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->IsVisible(command_id);
@@ -643,14 +685,15 @@
 }
 
 int CEF_CALLBACK menu_model_is_visible_at(struct _cef_menu_model_t* self,
-                                          int index) {
+                                          size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->IsVisibleAt(index);
@@ -667,8 +710,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->SetVisible(
@@ -679,15 +723,16 @@
 }
 
 int CEF_CALLBACK menu_model_set_visible_at(struct _cef_menu_model_t* self,
-                                           int index,
+                                           size_t index,
                                            int visible) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->SetVisibleAt(
@@ -704,8 +749,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->IsEnabled(command_id);
@@ -715,14 +761,15 @@
 }
 
 int CEF_CALLBACK menu_model_is_enabled_at(struct _cef_menu_model_t* self,
-                                          int index) {
+                                          size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->IsEnabledAt(index);
@@ -739,8 +786,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->SetEnabled(
@@ -751,15 +799,16 @@
 }
 
 int CEF_CALLBACK menu_model_set_enabled_at(struct _cef_menu_model_t* self,
-                                           int index,
+                                           size_t index,
                                            int enabled) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->SetEnabledAt(
@@ -776,8 +825,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->IsChecked(command_id);
@@ -787,14 +837,15 @@
 }
 
 int CEF_CALLBACK menu_model_is_checked_at(struct _cef_menu_model_t* self,
-                                          int index) {
+                                          size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->IsCheckedAt(index);
@@ -811,8 +862,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->SetChecked(
@@ -823,15 +875,16 @@
 }
 
 int CEF_CALLBACK menu_model_set_checked_at(struct _cef_menu_model_t* self,
-                                           int index,
+                                           size_t index,
                                            int checked) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->SetCheckedAt(
@@ -848,8 +901,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->HasAccelerator(command_id);
@@ -859,14 +913,15 @@
 }
 
 int CEF_CALLBACK menu_model_has_accelerator_at(struct _cef_menu_model_t* self,
-                                               int index) {
+                                               size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->HasAcceleratorAt(index);
@@ -886,8 +941,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->SetAccelerator(
@@ -899,7 +955,7 @@
 }
 
 int CEF_CALLBACK menu_model_set_accelerator_at(struct _cef_menu_model_t* self,
-                                               int index,
+                                               size_t index,
                                                int key_code,
                                                int shift_pressed,
                                                int ctrl_pressed,
@@ -909,8 +965,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->SetAcceleratorAt(
@@ -928,8 +985,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->RemoveAccelerator(command_id);
@@ -939,14 +997,15 @@
 }
 
 int CEF_CALLBACK
-menu_model_remove_accelerator_at(struct _cef_menu_model_t* self, int index) {
+menu_model_remove_accelerator_at(struct _cef_menu_model_t* self, size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefMenuModelCppToC::Get(self)->RemoveAcceleratorAt(index);
@@ -966,24 +1025,29 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: key_code; type: simple_byref
   DCHECK(key_code);
-  if (!key_code)
+  if (!key_code) {
     return 0;
+  }
   // Verify param: shift_pressed; type: bool_byref
   DCHECK(shift_pressed);
-  if (!shift_pressed)
+  if (!shift_pressed) {
     return 0;
+  }
   // Verify param: ctrl_pressed; type: bool_byref
   DCHECK(ctrl_pressed);
-  if (!ctrl_pressed)
+  if (!ctrl_pressed) {
     return 0;
+  }
   // Verify param: alt_pressed; type: bool_byref
   DCHECK(alt_pressed);
-  if (!alt_pressed)
+  if (!alt_pressed) {
     return 0;
+  }
 
   // Translate param: key_code; type: simple_byref
   int key_codeVal = key_code ? *key_code : 0;
@@ -1000,24 +1064,28 @@
       alt_pressedBool);
 
   // Restore param: key_code; type: simple_byref
-  if (key_code)
+  if (key_code) {
     *key_code = key_codeVal;
+  }
   // Restore param: shift_pressed; type: bool_byref
-  if (shift_pressed)
+  if (shift_pressed) {
     *shift_pressed = shift_pressedBool ? true : false;
+  }
   // Restore param: ctrl_pressed; type: bool_byref
-  if (ctrl_pressed)
+  if (ctrl_pressed) {
     *ctrl_pressed = ctrl_pressedBool ? true : false;
+  }
   // Restore param: alt_pressed; type: bool_byref
-  if (alt_pressed)
+  if (alt_pressed) {
     *alt_pressed = alt_pressedBool ? true : false;
+  }
 
   // Return type: bool
   return _retval;
 }
 
 int CEF_CALLBACK menu_model_get_accelerator_at(struct _cef_menu_model_t* self,
-                                               int index,
+                                               size_t index,
                                                int* key_code,
                                                int* shift_pressed,
                                                int* ctrl_pressed,
@@ -1027,24 +1095,29 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: key_code; type: simple_byref
   DCHECK(key_code);
-  if (!key_code)
+  if (!key_code) {
     return 0;
+  }
   // Verify param: shift_pressed; type: bool_byref
   DCHECK(shift_pressed);
-  if (!shift_pressed)
+  if (!shift_pressed) {
     return 0;
+  }
   // Verify param: ctrl_pressed; type: bool_byref
   DCHECK(ctrl_pressed);
-  if (!ctrl_pressed)
+  if (!ctrl_pressed) {
     return 0;
+  }
   // Verify param: alt_pressed; type: bool_byref
   DCHECK(alt_pressed);
-  if (!alt_pressed)
+  if (!alt_pressed) {
     return 0;
+  }
 
   // Translate param: key_code; type: simple_byref
   int key_codeVal = key_code ? *key_code : 0;
@@ -1060,17 +1133,21 @@
       index, key_codeVal, shift_pressedBool, ctrl_pressedBool, alt_pressedBool);
 
   // Restore param: key_code; type: simple_byref
-  if (key_code)
+  if (key_code) {
     *key_code = key_codeVal;
+  }
   // Restore param: shift_pressed; type: bool_byref
-  if (shift_pressed)
+  if (shift_pressed) {
     *shift_pressed = shift_pressedBool ? true : false;
+  }
   // Restore param: ctrl_pressed; type: bool_byref
-  if (ctrl_pressed)
+  if (ctrl_pressed) {
     *ctrl_pressed = ctrl_pressedBool ? true : false;
+  }
   // Restore param: alt_pressed; type: bool_byref
-  if (alt_pressed)
+  if (alt_pressed) {
     *alt_pressed = alt_pressedBool ? true : false;
+  }
 
   // Return type: bool
   return _retval;
@@ -1085,8 +1162,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1105,8 +1183,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1125,12 +1204,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: color; type: simple_byref
   DCHECK(color);
-  if (!color)
+  if (!color) {
     return 0;
+  }
 
   // Translate param: color; type: simple_byref
   cef_color_t colorVal = color ? *color : 0;
@@ -1140,8 +1221,9 @@
       CefMenuModelCppToC::Get(self)->GetColor(command_id, color_type, colorVal);
 
   // Restore param: color; type: simple_byref
-  if (color)
+  if (color) {
     *color = colorVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1156,12 +1238,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: color; type: simple_byref
   DCHECK(color);
-  if (!color)
+  if (!color) {
     return 0;
+  }
 
   // Translate param: color; type: simple_byref
   cef_color_t colorVal = color ? *color : 0;
@@ -1171,8 +1255,9 @@
       CefMenuModelCppToC::Get(self)->GetColorAt(index, color_type, colorVal);
 
   // Restore param: color; type: simple_byref
-  if (color)
+  if (color) {
     *color = colorVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1186,8 +1271,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Unverified params: font_list
 
   // Execute
@@ -1206,8 +1292,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Unverified params: font_list
 
   // Execute
@@ -1291,7 +1378,7 @@
 CefRefPtr<CefMenuModel>
 CefCppToCRefCounted<CefMenuModelCppToC, CefMenuModel, cef_menu_model_t>::
     UnwrapDerived(CefWrapperType type, cef_menu_model_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/menu_model_cpptoc.h b/src/libcef_dll/cpptoc/menu_model_cpptoc.h
index 0abf1bf..9344a72 100644
--- a/src/libcef_dll/cpptoc/menu_model_cpptoc.h
+++ b/src/libcef_dll/cpptoc/menu_model_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=12c4868cce94b5e3773ffcd539ba33558f65fd7f$
+// $hash=5f39f05bb39da5ede094d0e9789c5ef1dee1cf7f$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_MENU_MODEL_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/menu_model_delegate_cpptoc.cc b/src/libcef_dll/cpptoc/menu_model_delegate_cpptoc.cc
index ef0cb47..7c07093 100644
--- a/src/libcef_dll/cpptoc/menu_model_delegate_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/menu_model_delegate_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=65dec86d6113bdacec295b3b46c6f35ed299f42a$
+// $hash=e3f7a1bb81a732eddd8995d14490216d147f510c$
 //
 
 #include "libcef_dll/cpptoc/menu_model_delegate_cpptoc.h"
@@ -30,12 +30,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: menu_model; type: refptr_diff
   DCHECK(menu_model);
-  if (!menu_model)
+  if (!menu_model) {
     return;
+  }
 
   // Execute
   CefMenuModelDelegateCppToC::Get(self)->ExecuteCommand(
@@ -51,16 +53,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: menu_model; type: refptr_diff
   DCHECK(menu_model);
-  if (!menu_model)
+  if (!menu_model) {
     return;
+  }
   // Verify param: screen_point; type: simple_byref_const
   DCHECK(screen_point);
-  if (!screen_point)
+  if (!screen_point) {
     return;
+  }
 
   // Translate param: screen_point; type: simple_byref_const
   CefPoint screen_pointVal = screen_point ? *screen_point : CefPoint();
@@ -79,12 +84,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: menu_model; type: refptr_diff
   DCHECK(menu_model);
-  if (!menu_model)
+  if (!menu_model) {
     return;
+  }
 
   // Execute
   CefMenuModelDelegateCppToC::Get(self)->UnhandledOpenSubmenu(
@@ -100,12 +107,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: menu_model; type: refptr_diff
   DCHECK(menu_model);
-  if (!menu_model)
+  if (!menu_model) {
     return;
+  }
 
   // Execute
   CefMenuModelDelegateCppToC::Get(self)->UnhandledCloseSubmenu(
@@ -120,12 +129,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: menu_model; type: refptr_diff
   DCHECK(menu_model);
-  if (!menu_model)
+  if (!menu_model) {
     return;
+  }
 
   // Execute
   CefMenuModelDelegateCppToC::Get(self)->MenuWillShow(
@@ -140,12 +151,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: menu_model; type: refptr_diff
   DCHECK(menu_model);
-  if (!menu_model)
+  if (!menu_model) {
     return;
+  }
 
   // Execute
   CefMenuModelDelegateCppToC::Get(self)->MenuClosed(
@@ -161,16 +174,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: menu_model; type: refptr_diff
   DCHECK(menu_model);
-  if (!menu_model)
+  if (!menu_model) {
     return 0;
+  }
   // Verify param: label; type: string_byref
   DCHECK(label);
-  if (!label)
+  if (!label) {
     return 0;
+  }
 
   // Translate param: label; type: string_byref
   CefString labelStr(label);
@@ -211,7 +227,7 @@
     CefMenuModelDelegate,
     cef_menu_model_delegate_t>::UnwrapDerived(CefWrapperType type,
                                               cef_menu_model_delegate_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/menu_model_delegate_cpptoc.h b/src/libcef_dll/cpptoc/menu_model_delegate_cpptoc.h
index 6bec7b3..50a03ba 100644
--- a/src/libcef_dll/cpptoc/menu_model_delegate_cpptoc.h
+++ b/src/libcef_dll/cpptoc/menu_model_delegate_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=45a9a9cb0e55a5878d0342c313d5e734945b0f13$
+// $hash=2277b8692532f706316bb97ffe611394a00e1023$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_MENU_MODEL_DELEGATE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/navigation_entry_cpptoc.cc b/src/libcef_dll/cpptoc/navigation_entry_cpptoc.cc
index a97a4ba..277e3f9 100644
--- a/src/libcef_dll/cpptoc/navigation_entry_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/navigation_entry_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=cdcd1b3b9458442c480e69c5f7cee2ed48587e8b$
+// $hash=72992a0b2546d13e29617ad20d69c31243b68305$
 //
 
 #include "libcef_dll/cpptoc/navigation_entry_cpptoc.h"
@@ -27,8 +27,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefNavigationEntryCppToC::Get(self)->IsValid();
@@ -44,8 +45,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefNavigationEntryCppToC::Get(self)->GetURL();
@@ -61,8 +63,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefNavigationEntryCppToC::Get(self)->GetDisplayURL();
@@ -78,8 +81,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefNavigationEntryCppToC::Get(self)->GetOriginalURL();
@@ -95,8 +99,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefNavigationEntryCppToC::Get(self)->GetTitle();
@@ -112,8 +117,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return TT_EXPLICIT;
+  }
 
   // Execute
   cef_transition_type_t _retval =
@@ -130,8 +136,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefNavigationEntryCppToC::Get(self)->HasPostData();
@@ -140,18 +147,20 @@
   return _retval;
 }
 
-cef_time_t CEF_CALLBACK
+cef_basetime_t CEF_CALLBACK
 navigation_entry_get_completion_time(struct _cef_navigation_entry_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
-    return CefTime();
+  if (!self) {
+    return CefBaseTime();
+  }
 
   // Execute
-  cef_time_t _retval = CefNavigationEntryCppToC::Get(self)->GetCompletionTime();
+  cef_basetime_t _retval =
+      CefNavigationEntryCppToC::Get(self)->GetCompletionTime();
 
   // Return type: simple
   return _retval;
@@ -164,8 +173,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefNavigationEntryCppToC::Get(self)->GetHttpStatusCode();
@@ -181,8 +191,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefSSLStatus> _retval =
@@ -221,7 +232,7 @@
     CefNavigationEntry,
     cef_navigation_entry_t>::UnwrapDerived(CefWrapperType type,
                                            cef_navigation_entry_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/navigation_entry_cpptoc.h b/src/libcef_dll/cpptoc/navigation_entry_cpptoc.h
index 20d8519..38285d8 100644
--- a/src/libcef_dll/cpptoc/navigation_entry_cpptoc.h
+++ b/src/libcef_dll/cpptoc/navigation_entry_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9482954c3bc3d6261594f7610d27f4c368c84f8e$
+// $hash=213e6404f2260e81c41b20a42ae7788af80710dc$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_NAVIGATION_ENTRY_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/navigation_entry_visitor_cpptoc.cc b/src/libcef_dll/cpptoc/navigation_entry_visitor_cpptoc.cc
index 04754e4..cefcf43 100644
--- a/src/libcef_dll/cpptoc/navigation_entry_visitor_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/navigation_entry_visitor_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=59b1875dfe400b08651488a293a1381a236dce05$
+// $hash=f1a90fb1b3cda0cec9e9b4349c722761be164d22$
 //
 
 #include "libcef_dll/cpptoc/navigation_entry_visitor_cpptoc.h"
@@ -31,12 +31,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: entry; type: refptr_diff
   DCHECK(entry);
-  if (!entry)
+  if (!entry) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefNavigationEntryVisitorCppToC::Get(self)->Visit(
@@ -67,7 +69,7 @@
                     CefNavigationEntryVisitor,
                     cef_navigation_entry_visitor_t>::
     UnwrapDerived(CefWrapperType type, cef_navigation_entry_visitor_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/navigation_entry_visitor_cpptoc.h b/src/libcef_dll/cpptoc/navigation_entry_visitor_cpptoc.h
index ff5218b..77bb1a6 100644
--- a/src/libcef_dll/cpptoc/navigation_entry_visitor_cpptoc.h
+++ b/src/libcef_dll/cpptoc/navigation_entry_visitor_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3ddb0546cdf9464eb96fc255ec1a5d2449d93825$
+// $hash=e2fe9b1846135732e7596c2ff7ab6efadbb5a519$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_NAVIGATION_ENTRY_VISITOR_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/pdf_print_callback_cpptoc.cc b/src/libcef_dll/cpptoc/pdf_print_callback_cpptoc.cc
index 56e92bc..c4f4cfa 100644
--- a/src/libcef_dll/cpptoc/pdf_print_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/pdf_print_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1b0468f3f28054e3ce6304fb341b5747289c24b7$
+// $hash=1ed6b4ab7a3ceeab451ba1b898ed91a88f483004$
 //
 
 #include "libcef_dll/cpptoc/pdf_print_callback_cpptoc.h"
@@ -28,12 +28,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: path; type: string_byref_const
   DCHECK(path);
-  if (!path)
+  if (!path) {
     return;
+  }
 
   // Execute
   CefPdfPrintCallbackCppToC::Get(self)->OnPdfPrintFinished(CefString(path),
@@ -60,7 +62,7 @@
     CefPdfPrintCallback,
     cef_pdf_print_callback_t>::UnwrapDerived(CefWrapperType type,
                                              cef_pdf_print_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/pdf_print_callback_cpptoc.h b/src/libcef_dll/cpptoc/pdf_print_callback_cpptoc.h
index 3633df6..79130c8 100644
--- a/src/libcef_dll/cpptoc/pdf_print_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/pdf_print_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ab53cbd4d37273668814d44914434a097fb95aa0$
+// $hash=5e9c671740881e345231547607160ce167d37728$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_PDF_PRINT_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/permission_handler_cpptoc.cc b/src/libcef_dll/cpptoc/permission_handler_cpptoc.cc
new file mode 100644
index 0000000..f30578a
--- /dev/null
+++ b/src/libcef_dll/cpptoc/permission_handler_cpptoc.cc
@@ -0,0 +1,170 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=0386addd1e401049523c8b13439412a802fb4211$
+//
+
+#include "libcef_dll/cpptoc/permission_handler_cpptoc.h"
+#include "libcef_dll/ctocpp/browser_ctocpp.h"
+#include "libcef_dll/ctocpp/frame_ctocpp.h"
+#include "libcef_dll/ctocpp/media_access_callback_ctocpp.h"
+#include "libcef_dll/ctocpp/permission_prompt_callback_ctocpp.h"
+#include "libcef_dll/shutdown_checker.h"
+
+namespace {
+
+// MEMBER FUNCTIONS - Body may be edited by hand.
+
+int CEF_CALLBACK permission_handler_on_request_media_access_permission(
+    struct _cef_permission_handler_t* self,
+    cef_browser_t* browser,
+    cef_frame_t* frame,
+    const cef_string_t* requesting_origin,
+    uint32_t requested_permissions,
+    cef_media_access_callback_t* callback) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return 0;
+  }
+  // Verify param: frame; type: refptr_diff
+  DCHECK(frame);
+  if (!frame) {
+    return 0;
+  }
+  // Verify param: requesting_origin; type: string_byref_const
+  DCHECK(requesting_origin);
+  if (!requesting_origin) {
+    return 0;
+  }
+  // Verify param: callback; type: refptr_diff
+  DCHECK(callback);
+  if (!callback) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval =
+      CefPermissionHandlerCppToC::Get(self)->OnRequestMediaAccessPermission(
+          CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame),
+          CefString(requesting_origin), requested_permissions,
+          CefMediaAccessCallbackCToCpp::Wrap(callback));
+
+  // Return type: bool
+  return _retval;
+}
+
+int CEF_CALLBACK permission_handler_on_show_permission_prompt(
+    struct _cef_permission_handler_t* self,
+    cef_browser_t* browser,
+    uint64_t prompt_id,
+    const cef_string_t* requesting_origin,
+    uint32_t requested_permissions,
+    cef_permission_prompt_callback_t* callback) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return 0;
+  }
+  // Verify param: requesting_origin; type: string_byref_const
+  DCHECK(requesting_origin);
+  if (!requesting_origin) {
+    return 0;
+  }
+  // Verify param: callback; type: refptr_diff
+  DCHECK(callback);
+  if (!callback) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefPermissionHandlerCppToC::Get(self)->OnShowPermissionPrompt(
+      CefBrowserCToCpp::Wrap(browser), prompt_id, CefString(requesting_origin),
+      requested_permissions, CefPermissionPromptCallbackCToCpp::Wrap(callback));
+
+  // Return type: bool
+  return _retval;
+}
+
+void CEF_CALLBACK permission_handler_on_dismiss_permission_prompt(
+    struct _cef_permission_handler_t* self,
+    cef_browser_t* browser,
+    uint64_t prompt_id,
+    cef_permission_request_result_t result) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return;
+  }
+
+  // Execute
+  CefPermissionHandlerCppToC::Get(self)->OnDismissPermissionPrompt(
+      CefBrowserCToCpp::Wrap(browser), prompt_id, result);
+}
+
+}  // namespace
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefPermissionHandlerCppToC::CefPermissionHandlerCppToC() {
+  GetStruct()->on_request_media_access_permission =
+      permission_handler_on_request_media_access_permission;
+  GetStruct()->on_show_permission_prompt =
+      permission_handler_on_show_permission_prompt;
+  GetStruct()->on_dismiss_permission_prompt =
+      permission_handler_on_dismiss_permission_prompt;
+}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefPermissionHandlerCppToC::~CefPermissionHandlerCppToC() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+CefRefPtr<CefPermissionHandler> CefCppToCRefCounted<
+    CefPermissionHandlerCppToC,
+    CefPermissionHandler,
+    cef_permission_handler_t>::UnwrapDerived(CefWrapperType type,
+                                             cef_permission_handler_t* s) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCppToCRefCounted<CefPermissionHandlerCppToC,
+                                   CefPermissionHandler,
+                                   cef_permission_handler_t>::kWrapperType =
+    WT_PERMISSION_HANDLER;
diff --git a/src/libcef_dll/cpptoc/permission_handler_cpptoc.h b/src/libcef_dll/cpptoc/permission_handler_cpptoc.h
new file mode 100644
index 0000000..0ac7a85
--- /dev/null
+++ b/src/libcef_dll/cpptoc/permission_handler_cpptoc.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=85771f8c4169ad8465d7d53294a2da107ed1a03c$
+//
+
+#ifndef CEF_LIBCEF_DLL_CPPTOC_PERMISSION_HANDLER_CPPTOC_H_
+#define CEF_LIBCEF_DLL_CPPTOC_PERMISSION_HANDLER_CPPTOC_H_
+#pragma once
+
+#if !defined(WRAPPING_CEF_SHARED)
+#error This file can be included wrapper-side only
+#endif
+
+#include "include/capi/cef_permission_handler_capi.h"
+#include "include/cef_permission_handler.h"
+#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
+
+// Wrap a C++ class with a C structure.
+// This class may be instantiated and accessed wrapper-side only.
+class CefPermissionHandlerCppToC
+    : public CefCppToCRefCounted<CefPermissionHandlerCppToC,
+                                 CefPermissionHandler,
+                                 cef_permission_handler_t> {
+ public:
+  CefPermissionHandlerCppToC();
+  virtual ~CefPermissionHandlerCppToC();
+};
+
+#endif  // CEF_LIBCEF_DLL_CPPTOC_PERMISSION_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/permission_prompt_callback_cpptoc.cc b/src/libcef_dll/cpptoc/permission_prompt_callback_cpptoc.cc
new file mode 100644
index 0000000..ea67443
--- /dev/null
+++ b/src/libcef_dll/cpptoc/permission_prompt_callback_cpptoc.cc
@@ -0,0 +1,67 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=3ff7759e8f2dac0ae01122918c5ba0556b244532$
+//
+
+#include "libcef_dll/cpptoc/permission_prompt_callback_cpptoc.h"
+#include "libcef_dll/shutdown_checker.h"
+
+namespace {
+
+// MEMBER FUNCTIONS - Body may be edited by hand.
+
+void CEF_CALLBACK
+permission_prompt_callback_cont(struct _cef_permission_prompt_callback_t* self,
+                                cef_permission_request_result_t result) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+
+  // Execute
+  CefPermissionPromptCallbackCppToC::Get(self)->Continue(result);
+}
+
+}  // namespace
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefPermissionPromptCallbackCppToC::CefPermissionPromptCallbackCppToC() {
+  GetStruct()->cont = permission_prompt_callback_cont;
+}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefPermissionPromptCallbackCppToC::~CefPermissionPromptCallbackCppToC() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+CefRefPtr<CefPermissionPromptCallback>
+CefCppToCRefCounted<CefPermissionPromptCallbackCppToC,
+                    CefPermissionPromptCallback,
+                    cef_permission_prompt_callback_t>::
+    UnwrapDerived(CefWrapperType type, cef_permission_prompt_callback_t* s) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType
+    CefCppToCRefCounted<CefPermissionPromptCallbackCppToC,
+                        CefPermissionPromptCallback,
+                        cef_permission_prompt_callback_t>::kWrapperType =
+        WT_PERMISSION_PROMPT_CALLBACK;
diff --git a/src/libcef_dll/cpptoc/permission_prompt_callback_cpptoc.h b/src/libcef_dll/cpptoc/permission_prompt_callback_cpptoc.h
new file mode 100644
index 0000000..6779788
--- /dev/null
+++ b/src/libcef_dll/cpptoc/permission_prompt_callback_cpptoc.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=1fa140e60746b9a65c7ff9216577128cb1d2fb35$
+//
+
+#ifndef CEF_LIBCEF_DLL_CPPTOC_PERMISSION_PROMPT_CALLBACK_CPPTOC_H_
+#define CEF_LIBCEF_DLL_CPPTOC_PERMISSION_PROMPT_CALLBACK_CPPTOC_H_
+#pragma once
+
+#if !defined(BUILDING_CEF_SHARED)
+#error This file can be included DLL-side only
+#endif
+
+#include "include/capi/cef_permission_handler_capi.h"
+#include "include/cef_permission_handler.h"
+#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
+
+// Wrap a C++ class with a C structure.
+// This class may be instantiated and accessed DLL-side only.
+class CefPermissionPromptCallbackCppToC
+    : public CefCppToCRefCounted<CefPermissionPromptCallbackCppToC,
+                                 CefPermissionPromptCallback,
+                                 cef_permission_prompt_callback_t> {
+ public:
+  CefPermissionPromptCallbackCppToC();
+  virtual ~CefPermissionPromptCallbackCppToC();
+};
+
+#endif  // CEF_LIBCEF_DLL_CPPTOC_PERMISSION_PROMPT_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/post_data_cpptoc.cc b/src/libcef_dll/cpptoc/post_data_cpptoc.cc
index 20ef306..9ab657e 100644
--- a/src/libcef_dll/cpptoc/post_data_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/post_data_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8ef0b53920c747cb67c9ddca0082b9c36307200b$
+// $hash=1c9f3d740266fe84bfa1d6105eaffaf2866a8876$
 //
 
 #include "libcef_dll/cpptoc/post_data_cpptoc.h"
@@ -36,8 +36,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefPostDataCppToC::Get(self)->IsReadOnly();
@@ -51,8 +52,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefPostDataCppToC::Get(self)->HasExcludedElements();
@@ -65,8 +67,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefPostDataCppToC::Get(self)->GetElementCount();
@@ -82,12 +85,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: elements; type: refptr_vec_same_byref
   DCHECK(elementsCount && (*elementsCount == 0 || elements));
-  if (!elementsCount || (*elementsCount > 0 && !elements))
+  if (!elementsCount || (*elementsCount > 0 && !elements)) {
     return;
+  }
 
   // Translate param: elements; type: refptr_vec_same_byref
   std::vector<CefRefPtr<CefPostDataElement>> elementsList;
@@ -117,12 +122,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: element; type: refptr_same
   DCHECK(element);
-  if (!element)
+  if (!element) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefPostDataCppToC::Get(self)->RemoveElement(
@@ -138,12 +145,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: element; type: refptr_same
   DCHECK(element);
-  if (!element)
+  if (!element) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefPostDataCppToC::Get(self)->AddElement(
@@ -157,8 +166,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPostDataCppToC::Get(self)->RemoveElements();
@@ -186,7 +196,7 @@
 CefRefPtr<CefPostData>
 CefCppToCRefCounted<CefPostDataCppToC, CefPostData, cef_post_data_t>::
     UnwrapDerived(CefWrapperType type, cef_post_data_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/post_data_cpptoc.h b/src/libcef_dll/cpptoc/post_data_cpptoc.h
index 78a09c0..59518a2 100644
--- a/src/libcef_dll/cpptoc/post_data_cpptoc.h
+++ b/src/libcef_dll/cpptoc/post_data_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=bda55d6e344a4164b2e95a350d57e8224851c092$
+// $hash=784458fd59458b07ba3c6eacac3803b9901c354c$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_POST_DATA_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/post_data_element_cpptoc.cc b/src/libcef_dll/cpptoc/post_data_element_cpptoc.cc
index c9c3473..ef494b3 100644
--- a/src/libcef_dll/cpptoc/post_data_element_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/post_data_element_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3d0ca8d8f17478eebc8e50181ed0c10a7c28df4f$
+// $hash=28878433f4b543be6353184d8f930099ea0c9f41$
 //
 
 #include "libcef_dll/cpptoc/post_data_element_cpptoc.h"
@@ -35,8 +35,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefPostDataElementCppToC::Get(self)->IsReadOnly();
@@ -50,8 +51,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPostDataElementCppToC::Get(self)->SetToEmpty();
@@ -63,12 +65,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: fileName; type: string_byref_const
   DCHECK(fileName);
-  if (!fileName)
+  if (!fileName) {
     return;
+  }
 
   // Execute
   CefPostDataElementCppToC::Get(self)->SetToFile(CefString(fileName));
@@ -81,12 +85,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: bytes; type: simple_byaddr
   DCHECK(bytes);
-  if (!bytes)
+  if (!bytes) {
     return;
+  }
 
   // Execute
   CefPostDataElementCppToC::Get(self)->SetToBytes(size, bytes);
@@ -97,8 +103,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return PDE_TYPE_EMPTY;
+  }
 
   // Execute
   cef_postdataelement_type_t _retval =
@@ -113,8 +120,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefPostDataElementCppToC::Get(self)->GetFile();
@@ -128,8 +136,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefPostDataElementCppToC::Get(self)->GetBytesCount();
@@ -145,12 +154,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: bytes; type: simple_byaddr
   DCHECK(bytes);
-  if (!bytes)
+  if (!bytes) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefPostDataElementCppToC::Get(self)->GetBytes(size, bytes);
@@ -184,7 +195,7 @@
     CefPostDataElement,
     cef_post_data_element_t>::UnwrapDerived(CefWrapperType type,
                                             cef_post_data_element_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/post_data_element_cpptoc.h b/src/libcef_dll/cpptoc/post_data_element_cpptoc.h
index 21f89ae..5b57b20 100644
--- a/src/libcef_dll/cpptoc/post_data_element_cpptoc.h
+++ b/src/libcef_dll/cpptoc/post_data_element_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e186563dbf1f9cc2cb3a5c464477a4367ceb759a$
+// $hash=6d48d5f01f5cebcdca0fcfa7ce2b39a049fdc9cd$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_POST_DATA_ELEMENT_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/preference_manager_cpptoc.cc b/src/libcef_dll/cpptoc/preference_manager_cpptoc.cc
new file mode 100644
index 0000000..e58c869
--- /dev/null
+++ b/src/libcef_dll/cpptoc/preference_manager_cpptoc.cc
@@ -0,0 +1,193 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=ea61753d9dc6c4e0e95db78e2f0d07ab0d65c769$
+//
+
+#include "libcef_dll/cpptoc/preference_manager_cpptoc.h"
+#include "libcef_dll/cpptoc/dictionary_value_cpptoc.h"
+#include "libcef_dll/cpptoc/request_context_cpptoc.h"
+#include "libcef_dll/cpptoc/value_cpptoc.h"
+
+// GLOBAL FUNCTIONS - Body may be edited by hand.
+
+CEF_EXPORT cef_preference_manager_t* cef_preference_manager_get_global() {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  CefRefPtr<CefPreferenceManager> _retval =
+      CefPreferenceManager::GetGlobalPreferenceManager();
+
+  // Return type: refptr_same
+  return CefPreferenceManagerCppToC::Wrap(_retval);
+}
+
+namespace {
+
+// MEMBER FUNCTIONS - Body may be edited by hand.
+
+int CEF_CALLBACK
+preference_manager_has_preference(struct _cef_preference_manager_t* self,
+                                  const cef_string_t* name) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: name; type: string_byref_const
+  DCHECK(name);
+  if (!name) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval =
+      CefPreferenceManagerCppToC::Get(self)->HasPreference(CefString(name));
+
+  // Return type: bool
+  return _retval;
+}
+
+struct _cef_value_t* CEF_CALLBACK
+preference_manager_get_preference(struct _cef_preference_manager_t* self,
+                                  const cef_string_t* name) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+  // Verify param: name; type: string_byref_const
+  DCHECK(name);
+  if (!name) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefValue> _retval =
+      CefPreferenceManagerCppToC::Get(self)->GetPreference(CefString(name));
+
+  // Return type: refptr_same
+  return CefValueCppToC::Wrap(_retval);
+}
+
+struct _cef_dictionary_value_t* CEF_CALLBACK
+preference_manager_get_all_preferences(struct _cef_preference_manager_t* self,
+                                       int include_defaults) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefDictionaryValue> _retval =
+      CefPreferenceManagerCppToC::Get(self)->GetAllPreferences(
+          include_defaults ? true : false);
+
+  // Return type: refptr_same
+  return CefDictionaryValueCppToC::Wrap(_retval);
+}
+
+int CEF_CALLBACK
+preference_manager_can_set_preference(struct _cef_preference_manager_t* self,
+                                      const cef_string_t* name) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: name; type: string_byref_const
+  DCHECK(name);
+  if (!name) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval =
+      CefPreferenceManagerCppToC::Get(self)->CanSetPreference(CefString(name));
+
+  // Return type: bool
+  return _retval;
+}
+
+int CEF_CALLBACK
+preference_manager_set_preference(struct _cef_preference_manager_t* self,
+                                  const cef_string_t* name,
+                                  struct _cef_value_t* value,
+                                  cef_string_t* error) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: name; type: string_byref_const
+  DCHECK(name);
+  if (!name) {
+    return 0;
+  }
+  // Verify param: error; type: string_byref
+  DCHECK(error);
+  if (!error) {
+    return 0;
+  }
+  // Unverified params: value
+
+  // Translate param: error; type: string_byref
+  CefString errorStr(error);
+
+  // Execute
+  bool _retval = CefPreferenceManagerCppToC::Get(self)->SetPreference(
+      CefString(name), CefValueCppToC::Unwrap(value), errorStr);
+
+  // Return type: bool
+  return _retval;
+}
+
+}  // namespace
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefPreferenceManagerCppToC::CefPreferenceManagerCppToC() {
+  GetStruct()->has_preference = preference_manager_has_preference;
+  GetStruct()->get_preference = preference_manager_get_preference;
+  GetStruct()->get_all_preferences = preference_manager_get_all_preferences;
+  GetStruct()->can_set_preference = preference_manager_can_set_preference;
+  GetStruct()->set_preference = preference_manager_set_preference;
+}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefPreferenceManagerCppToC::~CefPreferenceManagerCppToC() {}
+
+template <>
+CefRefPtr<CefPreferenceManager> CefCppToCRefCounted<
+    CefPreferenceManagerCppToC,
+    CefPreferenceManager,
+    cef_preference_manager_t>::UnwrapDerived(CefWrapperType type,
+                                             cef_preference_manager_t* s) {
+  if (type == WT_REQUEST_CONTEXT) {
+    return CefRequestContextCppToC::Unwrap(
+        reinterpret_cast<cef_request_context_t*>(s));
+  }
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCppToCRefCounted<CefPreferenceManagerCppToC,
+                                   CefPreferenceManager,
+                                   cef_preference_manager_t>::kWrapperType =
+    WT_PREFERENCE_MANAGER;
diff --git a/src/libcef_dll/cpptoc/preference_manager_cpptoc.h b/src/libcef_dll/cpptoc/preference_manager_cpptoc.h
new file mode 100644
index 0000000..8c0a634
--- /dev/null
+++ b/src/libcef_dll/cpptoc/preference_manager_cpptoc.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=1a942f4b4935d0c3741ca58c3dc84c6c365827c6$
+//
+
+#ifndef CEF_LIBCEF_DLL_CPPTOC_PREFERENCE_MANAGER_CPPTOC_H_
+#define CEF_LIBCEF_DLL_CPPTOC_PREFERENCE_MANAGER_CPPTOC_H_
+#pragma once
+
+#if !defined(BUILDING_CEF_SHARED)
+#error This file can be included DLL-side only
+#endif
+
+#include "include/capi/cef_preference_capi.h"
+#include "include/cef_preference.h"
+#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
+
+// Wrap a C++ class with a C structure.
+// This class may be instantiated and accessed DLL-side only.
+class CefPreferenceManagerCppToC
+    : public CefCppToCRefCounted<CefPreferenceManagerCppToC,
+                                 CefPreferenceManager,
+                                 cef_preference_manager_t> {
+ public:
+  CefPreferenceManagerCppToC();
+  virtual ~CefPreferenceManagerCppToC();
+};
+
+#endif  // CEF_LIBCEF_DLL_CPPTOC_PREFERENCE_MANAGER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/preference_registrar_cpptoc.cc b/src/libcef_dll/cpptoc/preference_registrar_cpptoc.cc
new file mode 100644
index 0000000..65241b3
--- /dev/null
+++ b/src/libcef_dll/cpptoc/preference_registrar_cpptoc.cc
@@ -0,0 +1,85 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=5b964d4de1850160f24a5cc43d4d51bc622cc546$
+//
+
+#include "libcef_dll/cpptoc/preference_registrar_cpptoc.h"
+#include "libcef_dll/cpptoc/value_cpptoc.h"
+
+namespace {
+
+// MEMBER FUNCTIONS - Body may be edited by hand.
+
+int CEF_CALLBACK
+preference_registrar_add_preference(struct _cef_preference_registrar_t* self,
+                                    const cef_string_t* name,
+                                    struct _cef_value_t* default_value) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: name; type: string_byref_const
+  DCHECK(name);
+  if (!name) {
+    return 0;
+  }
+  // Verify param: default_value; type: refptr_same
+  DCHECK(default_value);
+  if (!default_value) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefPreferenceRegistrarCppToC::Get(self)->AddPreference(
+      CefString(name), CefValueCppToC::Unwrap(default_value));
+
+  // Return type: bool
+  return _retval;
+}
+
+}  // namespace
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefPreferenceRegistrarCppToC::CefPreferenceRegistrarCppToC() {
+  GetStruct()->add_preference = preference_registrar_add_preference;
+}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefPreferenceRegistrarCppToC::~CefPreferenceRegistrarCppToC() {}
+
+template <>
+CefOwnPtr<CefPreferenceRegistrar> CefCppToCScoped<CefPreferenceRegistrarCppToC,
+                                                  CefPreferenceRegistrar,
+                                                  cef_preference_registrar_t>::
+    UnwrapDerivedOwn(CefWrapperType type, cef_preference_registrar_t* s) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return CefOwnPtr<CefPreferenceRegistrar>();
+}
+
+template <>
+CefRawPtr<CefPreferenceRegistrar> CefCppToCScoped<CefPreferenceRegistrarCppToC,
+                                                  CefPreferenceRegistrar,
+                                                  cef_preference_registrar_t>::
+    UnwrapDerivedRaw(CefWrapperType type, cef_preference_registrar_t* s) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCppToCScoped<CefPreferenceRegistrarCppToC,
+                               CefPreferenceRegistrar,
+                               cef_preference_registrar_t>::kWrapperType =
+    WT_PREFERENCE_REGISTRAR;
diff --git a/src/libcef_dll/cpptoc/preference_registrar_cpptoc.h b/src/libcef_dll/cpptoc/preference_registrar_cpptoc.h
new file mode 100644
index 0000000..897a199
--- /dev/null
+++ b/src/libcef_dll/cpptoc/preference_registrar_cpptoc.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=a276311e31965315ceb5e7f293eaee8140a79acb$
+//
+
+#ifndef CEF_LIBCEF_DLL_CPPTOC_PREFERENCE_REGISTRAR_CPPTOC_H_
+#define CEF_LIBCEF_DLL_CPPTOC_PREFERENCE_REGISTRAR_CPPTOC_H_
+#pragma once
+
+#if !defined(BUILDING_CEF_SHARED)
+#error This file can be included DLL-side only
+#endif
+
+#include "include/capi/cef_preference_capi.h"
+#include "include/cef_preference.h"
+#include "libcef_dll/cpptoc/cpptoc_scoped.h"
+
+// Wrap a C++ class with a C structure.
+// This class may be instantiated and accessed DLL-side only.
+class CefPreferenceRegistrarCppToC
+    : public CefCppToCScoped<CefPreferenceRegistrarCppToC,
+                             CefPreferenceRegistrar,
+                             cef_preference_registrar_t> {
+ public:
+  CefPreferenceRegistrarCppToC();
+  virtual ~CefPreferenceRegistrarCppToC();
+};
+
+#endif  // CEF_LIBCEF_DLL_CPPTOC_PREFERENCE_REGISTRAR_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/print_dialog_callback_cpptoc.cc b/src/libcef_dll/cpptoc/print_dialog_callback_cpptoc.cc
index ed0c6ef..f72391b 100644
--- a/src/libcef_dll/cpptoc/print_dialog_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/print_dialog_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=dd4497ea885d54be767940af4148f3c7c9f22298$
+// $hash=c70076350cd4523b0506236e187e3b3320a9dc5f$
 //
 
 #include "libcef_dll/cpptoc/print_dialog_callback_cpptoc.h"
@@ -28,12 +28,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: settings; type: refptr_same
   DCHECK(settings);
-  if (!settings)
+  if (!settings) {
     return;
+  }
 
   // Execute
   CefPrintDialogCallbackCppToC::Get(self)->Continue(
@@ -47,8 +49,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPrintDialogCallbackCppToC::Get(self)->Cancel();
@@ -76,7 +79,7 @@
     cef_print_dialog_callback_t>::UnwrapDerived(CefWrapperType type,
                                                 cef_print_dialog_callback_t*
                                                     s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/print_dialog_callback_cpptoc.h b/src/libcef_dll/cpptoc/print_dialog_callback_cpptoc.h
index c225dba..281ef13 100644
--- a/src/libcef_dll/cpptoc/print_dialog_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/print_dialog_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=cb1d9f76304854b4beeac4ca95c8e66f988d6736$
+// $hash=ee6fd2ddae3899be82feca1e37cce919363bae99$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_PRINT_DIALOG_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/print_handler_cpptoc.cc b/src/libcef_dll/cpptoc/print_handler_cpptoc.cc
index c1ae9a6..58d74d6 100644
--- a/src/libcef_dll/cpptoc/print_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/print_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=565613dbb99435d203b41dbb8717334527a4acb7$
+// $hash=2249e1f0ad86dad3cfac6755c79e3a114d11f4f9$
 //
 
 #include "libcef_dll/cpptoc/print_handler_cpptoc.h"
@@ -31,12 +31,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefPrintHandlerCppToC::Get(self)->OnPrintStart(
@@ -53,16 +55,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: settings; type: refptr_diff
   DCHECK(settings);
-  if (!settings)
+  if (!settings) {
     return;
+  }
 
   // Execute
   CefPrintHandlerCppToC::Get(self)->OnPrintSettings(
@@ -80,16 +85,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefPrintHandlerCppToC::Get(self)->OnPrintDialog(
@@ -111,24 +119,29 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: document_name; type: string_byref_const
   DCHECK(document_name);
-  if (!document_name)
+  if (!document_name) {
     return 0;
+  }
   // Verify param: pdf_file_path; type: string_byref_const
   DCHECK(pdf_file_path);
-  if (!pdf_file_path)
+  if (!pdf_file_path) {
     return 0;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefPrintHandlerCppToC::Get(self)->OnPrintJob(
@@ -147,12 +160,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefPrintHandlerCppToC::Get(self)->OnPrintReset(
@@ -161,18 +176,25 @@
 
 cef_size_t CEF_CALLBACK
 print_handler_get_pdf_paper_size(struct _cef_print_handler_t* self,
+                                 cef_browser_t* browser,
                                  int device_units_per_inch) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return CefSize();
+  }
 
   // Execute
-  cef_size_t _retval =
-      CefPrintHandlerCppToC::Get(self)->GetPdfPaperSize(device_units_per_inch);
+  cef_size_t _retval = CefPrintHandlerCppToC::Get(self)->GetPdfPaperSize(
+      CefBrowserCToCpp::Wrap(browser), device_units_per_inch);
 
   // Return type: simple
   return _retval;
@@ -203,7 +225,7 @@
     CefPrintHandler,
     cef_print_handler_t>::UnwrapDerived(CefWrapperType type,
                                         cef_print_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/print_handler_cpptoc.h b/src/libcef_dll/cpptoc/print_handler_cpptoc.h
index e334ba4..f2d71b3 100644
--- a/src/libcef_dll/cpptoc/print_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/print_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1d17820ee8a5c67aea024f69f7c651949bf5e9aa$
+// $hash=cd0bb4e9c12f53896be544b28ae3c6f38b3504e2$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_PRINT_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/print_job_callback_cpptoc.cc b/src/libcef_dll/cpptoc/print_job_callback_cpptoc.cc
index 04cabb9..e204873 100644
--- a/src/libcef_dll/cpptoc/print_job_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/print_job_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f79bd331e5b7091c916778dd4d850da4b9bbbc4d$
+// $hash=282e8760f3b06ad59158a4c07b8f44932e827b1d$
 //
 
 #include "libcef_dll/cpptoc/print_job_callback_cpptoc.h"
@@ -26,8 +26,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPrintJobCallbackCppToC::Get(self)->Continue();
@@ -53,7 +54,7 @@
     CefPrintJobCallback,
     cef_print_job_callback_t>::UnwrapDerived(CefWrapperType type,
                                              cef_print_job_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/print_job_callback_cpptoc.h b/src/libcef_dll/cpptoc/print_job_callback_cpptoc.h
index 680257a..cc59010 100644
--- a/src/libcef_dll/cpptoc/print_job_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/print_job_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=574630f06356876279d93d2eafb2b10bcc2f1b06$
+// $hash=54a355e9511b5d0956f1a7269ee21766fa7f8c87$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_PRINT_JOB_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/print_settings_cpptoc.cc b/src/libcef_dll/cpptoc/print_settings_cpptoc.cc
index 2675930..70e17b2 100644
--- a/src/libcef_dll/cpptoc/print_settings_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/print_settings_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=a4cc31347e4f06a79f9d308cee502bb18be09996$
+// $hash=8f43b6d00d772cb989a29bba70187f9df04ab0bf$
 //
 
 #include "libcef_dll/cpptoc/print_settings_cpptoc.h"
@@ -40,8 +40,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefPrintSettingsCppToC::Get(self)->IsValid();
@@ -57,8 +58,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefPrintSettingsCppToC::Get(self)->IsReadOnly();
@@ -75,8 +77,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPrintSettingsCppToC::Get(self)->SetOrientation(landscape ? true : false);
@@ -89,8 +92,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefPrintSettingsCppToC::Get(self)->IsLandscape();
@@ -109,16 +113,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: physical_size_device_units; type: simple_byref_const
   DCHECK(physical_size_device_units);
-  if (!physical_size_device_units)
+  if (!physical_size_device_units) {
     return;
+  }
   // Verify param: printable_area_device_units; type: simple_byref_const
   DCHECK(printable_area_device_units);
-  if (!printable_area_device_units)
+  if (!printable_area_device_units) {
     return;
+  }
 
   // Translate param: physical_size_device_units; type: simple_byref_const
   CefSize physical_size_device_unitsVal =
@@ -141,8 +148,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: name
 
   // Execute
@@ -156,8 +164,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefPrintSettingsCppToC::Get(self)->GetDeviceName();
@@ -173,8 +182,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPrintSettingsCppToC::Get(self)->SetDPI(dpi);
@@ -186,8 +196,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefPrintSettingsCppToC::Get(self)->GetDPI();
@@ -205,12 +216,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: ranges; type: simple_vec_byref_const
   DCHECK(rangesCount == 0 || ranges);
-  if (rangesCount > 0 && !ranges)
+  if (rangesCount > 0 && !ranges) {
     return;
+  }
 
   // Translate param: ranges; type: simple_vec_byref_const
   std::vector<CefRange> rangesList;
@@ -232,8 +245,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefPrintSettingsCppToC::Get(self)->GetPageRangesCount();
@@ -251,12 +265,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: ranges; type: simple_vec_byref
   DCHECK(rangesCount && (*rangesCount == 0 || ranges));
-  if (!rangesCount || (*rangesCount > 0 && !ranges))
+  if (!rangesCount || (*rangesCount > 0 && !ranges)) {
     return;
+  }
 
   // Translate param: ranges; type: simple_vec_byref
   std::vector<CefRange> rangesList;
@@ -288,8 +304,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPrintSettingsCppToC::Get(self)->SetSelectionOnly(selection_only ? true
@@ -303,8 +320,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefPrintSettingsCppToC::Get(self)->IsSelectionOnly();
@@ -320,8 +338,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPrintSettingsCppToC::Get(self)->SetCollate(collate ? true : false);
@@ -334,8 +353,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefPrintSettingsCppToC::Get(self)->WillCollate();
@@ -352,8 +372,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPrintSettingsCppToC::Get(self)->SetColorModel(model);
@@ -366,8 +387,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return COLOR_MODEL_UNKNOWN;
+  }
 
   // Execute
   cef_color_model_t _retval =
@@ -384,8 +406,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPrintSettingsCppToC::Get(self)->SetCopies(copies);
@@ -397,8 +420,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefPrintSettingsCppToC::Get(self)->GetCopies();
@@ -415,8 +439,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPrintSettingsCppToC::Get(self)->SetDuplexMode(mode);
@@ -429,8 +454,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return DUPLEX_MODE_UNKNOWN;
+  }
 
   // Execute
   cef_duplex_mode_t _retval =
@@ -482,7 +508,7 @@
     CefPrintSettings,
     cef_print_settings_t>::UnwrapDerived(CefWrapperType type,
                                          cef_print_settings_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/print_settings_cpptoc.h b/src/libcef_dll/cpptoc/print_settings_cpptoc.h
index 9a289a2..c7ece39 100644
--- a/src/libcef_dll/cpptoc/print_settings_cpptoc.h
+++ b/src/libcef_dll/cpptoc/print_settings_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=30197dfacc1edef6d11a3a0151141749b3a4e36e$
+// $hash=596144335f97b41394808d0de0908c2a69d04d7a$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_PRINT_SETTINGS_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/process_message_cpptoc.cc b/src/libcef_dll/cpptoc/process_message_cpptoc.cc
index 22cff8d..4a5830a 100644
--- a/src/libcef_dll/cpptoc/process_message_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/process_message_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,11 +9,12 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7cb7bbf83d9ae4cd85a4493036150f4c47c8b879$
+// $hash=f422c73d022a8794c0cbb01f4bb3fbb2a3f7e045$
 //
 
 #include "libcef_dll/cpptoc/process_message_cpptoc.h"
 #include "libcef_dll/cpptoc/list_value_cpptoc.h"
+#include "libcef_dll/cpptoc/shared_memory_region_cpptoc.h"
 #include "libcef_dll/shutdown_checker.h"
 
 // GLOBAL FUNCTIONS - Body may be edited by hand.
@@ -26,8 +27,9 @@
 
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefProcessMessage> _retval =
@@ -47,8 +49,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefProcessMessageCppToC::Get(self)->IsValid();
@@ -64,8 +67,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefProcessMessageCppToC::Get(self)->IsReadOnly();
@@ -81,8 +85,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefProcessMessage> _retval =
@@ -99,8 +104,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefProcessMessageCppToC::Get(self)->GetName();
@@ -116,8 +122,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefListValue> _retval =
@@ -127,6 +134,25 @@
   return CefListValueCppToC::Wrap(_retval);
 }
 
+struct _cef_shared_memory_region_t* CEF_CALLBACK
+process_message_get_shared_memory_region(struct _cef_process_message_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefSharedMemoryRegion> _retval =
+      CefProcessMessageCppToC::Get(self)->GetSharedMemoryRegion();
+
+  // Return type: refptr_same
+  return CefSharedMemoryRegionCppToC::Wrap(_retval);
+}
+
 }  // namespace
 
 // CONSTRUCTOR - Do not edit by hand.
@@ -137,6 +163,8 @@
   GetStruct()->copy = process_message_copy;
   GetStruct()->get_name = process_message_get_name;
   GetStruct()->get_argument_list = process_message_get_argument_list;
+  GetStruct()->get_shared_memory_region =
+      process_message_get_shared_memory_region;
 }
 
 // DESTRUCTOR - Do not edit by hand.
@@ -151,7 +179,7 @@
     CefProcessMessage,
     cef_process_message_t>::UnwrapDerived(CefWrapperType type,
                                           cef_process_message_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/process_message_cpptoc.h b/src/libcef_dll/cpptoc/process_message_cpptoc.h
index 614b569..e3f2485 100644
--- a/src/libcef_dll/cpptoc/process_message_cpptoc.h
+++ b/src/libcef_dll/cpptoc/process_message_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=593f843c0c82f66bba1e16943dd8a381ddbedd4f$
+// $hash=6d4c104d51d4d34c0ec8b767a13db58a6fb0fef8$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_PROCESS_MESSAGE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/read_handler_cpptoc.cc b/src/libcef_dll/cpptoc/read_handler_cpptoc.cc
index e431ec4..33e7bab 100644
--- a/src/libcef_dll/cpptoc/read_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/read_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=17dd4be0a0f3c4ff17da7837b6d01094d690243d$
+// $hash=297d49ea4c02ae7ca19359c30bdcac380a45d95c$
 //
 
 #include "libcef_dll/cpptoc/read_handler_cpptoc.h"
@@ -28,12 +28,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: ptr; type: simple_byaddr
   DCHECK(ptr);
-  if (!ptr)
+  if (!ptr) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefReadHandlerCppToC::Get(self)->Read(ptr, size, n);
@@ -43,15 +45,16 @@
 }
 
 int CEF_CALLBACK read_handler_seek(struct _cef_read_handler_t* self,
-                                   int64 offset,
+                                   int64_t offset,
                                    int whence) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefReadHandlerCppToC::Get(self)->Seek(offset, whence);
@@ -60,17 +63,18 @@
   return _retval;
 }
 
-int64 CEF_CALLBACK read_handler_tell(struct _cef_read_handler_t* self) {
+int64_t CEF_CALLBACK read_handler_tell(struct _cef_read_handler_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
-  int64 _retval = CefReadHandlerCppToC::Get(self)->Tell();
+  int64_t _retval = CefReadHandlerCppToC::Get(self)->Tell();
 
   // Return type: simple
   return _retval;
@@ -82,8 +86,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefReadHandlerCppToC::Get(self)->Eof();
@@ -98,8 +103,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefReadHandlerCppToC::Get(self)->MayBlock();
@@ -130,7 +136,7 @@
 CefRefPtr<CefReadHandler>
 CefCppToCRefCounted<CefReadHandlerCppToC, CefReadHandler, cef_read_handler_t>::
     UnwrapDerived(CefWrapperType type, cef_read_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/read_handler_cpptoc.h b/src/libcef_dll/cpptoc/read_handler_cpptoc.h
index 54d49ba..4c4ddc6 100644
--- a/src/libcef_dll/cpptoc/read_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/read_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ad93c34f2e152573b9ff385a8c4d5f115fc89f9b$
+// $hash=8a5eb8ffc9a8857ac10a6586e954dc532d10618a$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_READ_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/register_cdm_callback_cpptoc.cc b/src/libcef_dll/cpptoc/register_cdm_callback_cpptoc.cc
deleted file mode 100644
index d3db64f..0000000
--- a/src/libcef_dll/cpptoc/register_cdm_callback_cpptoc.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=4ec6b7d3ac59768907b1096d463f76a6caa45c1e$
-//
-
-#include "libcef_dll/cpptoc/register_cdm_callback_cpptoc.h"
-#include "libcef_dll/shutdown_checker.h"
-
-namespace {
-
-// MEMBER FUNCTIONS - Body may be edited by hand.
-
-void CEF_CALLBACK register_cdm_callback_on_cdm_registration_complete(
-    struct _cef_register_cdm_callback_t* self,
-    cef_cdm_registration_error_t result,
-    const cef_string_t* error_message) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return;
-  // Unverified params: error_message
-
-  // Execute
-  CefRegisterCdmCallbackCppToC::Get(self)->OnCdmRegistrationComplete(
-      result, CefString(error_message));
-}
-
-}  // namespace
-
-// CONSTRUCTOR - Do not edit by hand.
-
-CefRegisterCdmCallbackCppToC::CefRegisterCdmCallbackCppToC() {
-  GetStruct()->on_cdm_registration_complete =
-      register_cdm_callback_on_cdm_registration_complete;
-}
-
-// DESTRUCTOR - Do not edit by hand.
-
-CefRegisterCdmCallbackCppToC::~CefRegisterCdmCallbackCppToC() {
-  shutdown_checker::AssertNotShutdown();
-}
-
-template <>
-CefRefPtr<CefRegisterCdmCallback> CefCppToCRefCounted<
-    CefRegisterCdmCallbackCppToC,
-    CefRegisterCdmCallback,
-    cef_register_cdm_callback_t>::UnwrapDerived(CefWrapperType type,
-                                                cef_register_cdm_callback_t*
-                                                    s) {
-  NOTREACHED() << "Unexpected class type: " << type;
-  return nullptr;
-}
-
-template <>
-CefWrapperType CefCppToCRefCounted<CefRegisterCdmCallbackCppToC,
-                                   CefRegisterCdmCallback,
-                                   cef_register_cdm_callback_t>::kWrapperType =
-    WT_REGISTER_CDM_CALLBACK;
diff --git a/src/libcef_dll/cpptoc/register_cdm_callback_cpptoc.h b/src/libcef_dll/cpptoc/register_cdm_callback_cpptoc.h
deleted file mode 100644
index 290c9c3..0000000
--- a/src/libcef_dll/cpptoc/register_cdm_callback_cpptoc.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=c27e3384b7800e52335f9c4be4a14ef68ee9ce7d$
-//
-
-#ifndef CEF_LIBCEF_DLL_CPPTOC_REGISTER_CDM_CALLBACK_CPPTOC_H_
-#define CEF_LIBCEF_DLL_CPPTOC_REGISTER_CDM_CALLBACK_CPPTOC_H_
-#pragma once
-
-#if !defined(WRAPPING_CEF_SHARED)
-#error This file can be included wrapper-side only
-#endif
-
-#include "include/capi/cef_browser_capi.h"
-#include "include/capi/cef_web_plugin_capi.h"
-#include "include/cef_browser.h"
-#include "include/cef_web_plugin.h"
-#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
-
-// Wrap a C++ class with a C structure.
-// This class may be instantiated and accessed wrapper-side only.
-class CefRegisterCdmCallbackCppToC
-    : public CefCppToCRefCounted<CefRegisterCdmCallbackCppToC,
-                                 CefRegisterCdmCallback,
-                                 cef_register_cdm_callback_t> {
- public:
-  CefRegisterCdmCallbackCppToC();
-  virtual ~CefRegisterCdmCallbackCppToC();
-};
-
-#endif  // CEF_LIBCEF_DLL_CPPTOC_REGISTER_CDM_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/registration_cpptoc.cc b/src/libcef_dll/cpptoc/registration_cpptoc.cc
index d620215..0f0733a 100644
--- a/src/libcef_dll/cpptoc/registration_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/registration_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=37c8c576c5bccd43f6124095e4ad55e88bc1a185$
+// $hash=b8ae4bec56faeb74fd5ddad0cacb053a17babc08$
 //
 
 #include "libcef_dll/cpptoc/registration_cpptoc.h"
@@ -31,7 +31,7 @@
                     CefRegistration,
                     cef_registration_t>::UnwrapDerived(CefWrapperType type,
                                                        cef_registration_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/registration_cpptoc.h b/src/libcef_dll/cpptoc/registration_cpptoc.h
index 3e1eb52..8fd4ce1 100644
--- a/src/libcef_dll/cpptoc/registration_cpptoc.h
+++ b/src/libcef_dll/cpptoc/registration_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e27d69c1509e74c7f5d69f5829c27fa65e47fc2d$
+// $hash=461d6b9297ebd61bf8d2df2e3960458a9a3705f6$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_REGISTRATION_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/render_handler_cpptoc.cc b/src/libcef_dll/cpptoc/render_handler_cpptoc.cc
index 0ab491e..500db84 100644
--- a/src/libcef_dll/cpptoc/render_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/render_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2e22f210ff06337ac41e71a00b9dc6edce08e6d8$
+// $hash=84d77427734eaa5d0200c61599089678864ea2dc$
 //
 
 #include "libcef_dll/cpptoc/render_handler_cpptoc.h"
@@ -29,8 +29,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefAccessibilityHandler> _retval =
@@ -49,16 +50,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: rect; type: simple_byref
   DCHECK(rect);
-  if (!rect)
+  if (!rect) {
     return 0;
+  }
 
   // Translate param: rect; type: simple_byref
   CefRect rectVal = rect ? *rect : CefRect();
@@ -68,8 +72,9 @@
       CefBrowserCToCpp::Wrap(browser), rectVal);
 
   // Restore param: rect; type: simple_byref
-  if (rect)
+  if (rect) {
     *rect = rectVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -84,16 +89,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: rect; type: simple_byref
   DCHECK(rect);
-  if (!rect)
+  if (!rect) {
     return;
+  }
 
   // Translate param: rect; type: simple_byref
   CefRect rectVal = rect ? *rect : CefRect();
@@ -103,8 +111,9 @@
       CefBrowserCToCpp::Wrap(browser), rectVal);
 
   // Restore param: rect; type: simple_byref
-  if (rect)
+  if (rect) {
     *rect = rectVal;
+  }
 }
 
 int CEF_CALLBACK
@@ -119,20 +128,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: screenX; type: simple_byref
   DCHECK(screenX);
-  if (!screenX)
+  if (!screenX) {
     return 0;
+  }
   // Verify param: screenY; type: simple_byref
   DCHECK(screenY);
-  if (!screenY)
+  if (!screenY) {
     return 0;
+  }
 
   // Translate param: screenX; type: simple_byref
   int screenXVal = screenX ? *screenX : 0;
@@ -144,11 +157,13 @@
       CefBrowserCToCpp::Wrap(browser), viewX, viewY, screenXVal, screenYVal);
 
   // Restore param: screenX; type: simple_byref
-  if (screenX)
+  if (screenX) {
     *screenX = screenXVal;
+  }
   // Restore param: screenY; type: simple_byref
-  if (screenY)
+  if (screenY) {
     *screenY = screenYVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -157,35 +172,37 @@
 int CEF_CALLBACK
 render_handler_get_screen_info(struct _cef_render_handler_t* self,
                                cef_browser_t* browser,
-                               struct _cef_screen_info_t* screen_info) {
+                               cef_screen_info_t* screen_info) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
-  // Verify param: screen_info; type: struct_byref
+  }
+  // Verify param: screen_info; type: simple_byref
   DCHECK(screen_info);
-  if (!screen_info)
+  if (!screen_info) {
     return 0;
+  }
 
-  // Translate param: screen_info; type: struct_byref
-  CefScreenInfo screen_infoObj;
-  if (screen_info)
-    screen_infoObj.AttachTo(*screen_info);
+  // Translate param: screen_info; type: simple_byref
+  CefScreenInfo screen_infoVal = screen_info ? *screen_info : CefScreenInfo();
 
   // Execute
   bool _retval = CefRenderHandlerCppToC::Get(self)->GetScreenInfo(
-      CefBrowserCToCpp::Wrap(browser), screen_infoObj);
+      CefBrowserCToCpp::Wrap(browser), screen_infoVal);
 
-  // Restore param: screen_info; type: struct_byref
-  if (screen_info)
-    screen_infoObj.DetachTo(*screen_info);
+  // Restore param: screen_info; type: simple_byref
+  if (screen_info) {
+    *screen_info = screen_infoVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -200,12 +217,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefRenderHandlerCppToC::Get(self)->OnPopupShow(
@@ -221,16 +240,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: rect; type: simple_byref_const
   DCHECK(rect);
-  if (!rect)
+  if (!rect) {
     return;
+  }
 
   // Translate param: rect; type: simple_byref_const
   CefRect rectVal = rect ? *rect : CefRect();
@@ -253,20 +275,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: dirtyRects; type: simple_vec_byref_const
   DCHECK(dirtyRectsCount == 0 || dirtyRects);
-  if (dirtyRectsCount > 0 && !dirtyRects)
+  if (dirtyRectsCount > 0 && !dirtyRects) {
     return;
+  }
   // Verify param: buffer; type: simple_byaddr
   DCHECK(buffer);
-  if (!buffer)
+  if (!buffer) {
     return;
+  }
 
   // Translate param: dirtyRects; type: simple_vec_byref_const
   std::vector<CefRect> dirtyRectsList;
@@ -295,20 +321,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: dirtyRects; type: simple_vec_byref_const
   DCHECK(dirtyRectsCount == 0 || dirtyRects);
-  if (dirtyRectsCount > 0 && !dirtyRects)
+  if (dirtyRectsCount > 0 && !dirtyRects) {
     return;
+  }
   // Verify param: shared_handle; type: simple_byaddr
   DCHECK(shared_handle);
-  if (!shared_handle)
+  if (!shared_handle) {
     return;
+  }
 
   // Translate param: dirtyRects; type: simple_vec_byref_const
   std::vector<CefRect> dirtyRectsList;
@@ -324,36 +354,72 @@
       CefBrowserCToCpp::Wrap(browser), type, dirtyRectsList, shared_handle);
 }
 
-void CEF_CALLBACK render_handler_on_cursor_change(
-    struct _cef_render_handler_t* self,
-    cef_browser_t* browser,
-    cef_cursor_handle_t cursor,
-    cef_cursor_type_t type,
-    const struct _cef_cursor_info_t* custom_cursor_info) {
+void CEF_CALLBACK
+render_handler_get_touch_handle_size(struct _cef_render_handler_t* self,
+                                     cef_browser_t* browser,
+                                     cef_horizontal_alignment_t orientation,
+                                     cef_size_t* size) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
-  // Verify param: custom_cursor_info; type: struct_byref_const
-  DCHECK(custom_cursor_info);
-  if (!custom_cursor_info)
+  }
+  // Verify param: size; type: simple_byref
+  DCHECK(size);
+  if (!size) {
     return;
+  }
 
-  // Translate param: custom_cursor_info; type: struct_byref_const
-  CefCursorInfo custom_cursor_infoObj;
-  if (custom_cursor_info)
-    custom_cursor_infoObj.Set(*custom_cursor_info, false);
+  // Translate param: size; type: simple_byref
+  CefSize sizeVal = size ? *size : CefSize();
 
   // Execute
-  CefRenderHandlerCppToC::Get(self)->OnCursorChange(
-      CefBrowserCToCpp::Wrap(browser), cursor, type, custom_cursor_infoObj);
+  CefRenderHandlerCppToC::Get(self)->GetTouchHandleSize(
+      CefBrowserCToCpp::Wrap(browser), orientation, sizeVal);
+
+  // Restore param: size; type: simple_byref
+  if (size) {
+    *size = sizeVal;
+  }
+}
+
+void CEF_CALLBACK render_handler_on_touch_handle_state_changed(
+    struct _cef_render_handler_t* self,
+    cef_browser_t* browser,
+    const cef_touch_handle_state_t* state) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser);
+  if (!browser) {
+    return;
+  }
+  // Verify param: state; type: simple_byref_const
+  DCHECK(state);
+  if (!state) {
+    return;
+  }
+
+  // Translate param: state; type: simple_byref_const
+  CefTouchHandleState stateVal = state ? *state : CefTouchHandleState();
+
+  // Execute
+  CefRenderHandlerCppToC::Get(self)->OnTouchHandleStateChanged(
+      CefBrowserCToCpp::Wrap(browser), stateVal);
 }
 
 int CEF_CALLBACK
@@ -368,16 +434,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: drag_data; type: refptr_diff
   DCHECK(drag_data);
-  if (!drag_data)
+  if (!drag_data) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefRenderHandlerCppToC::Get(self)->StartDragging(
@@ -397,12 +466,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefRenderHandlerCppToC::Get(self)->UpdateDragCursor(
@@ -419,12 +490,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefRenderHandlerCppToC::Get(self)->OnScrollOffsetChanged(
@@ -442,20 +515,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: selected_range; type: simple_byref_const
   DCHECK(selected_range);
-  if (!selected_range)
+  if (!selected_range) {
     return;
+  }
   // Verify param: character_bounds; type: simple_vec_byref_const
   DCHECK(character_boundsCount == 0 || character_bounds);
-  if (character_boundsCount > 0 && !character_bounds)
+  if (character_boundsCount > 0 && !character_bounds) {
     return;
+  }
 
   // Translate param: selected_range; type: simple_byref_const
   CefRange selected_rangeVal = selected_range ? *selected_range : CefRange();
@@ -483,12 +560,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Unverified params: selected_text, selected_range
 
   // Translate param: selected_range; type: simple_byref_const
@@ -509,12 +588,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefRenderHandlerCppToC::Get(self)->OnVirtualKeyboardRequested(
@@ -536,7 +617,9 @@
   GetStruct()->on_popup_size = render_handler_on_popup_size;
   GetStruct()->on_paint = render_handler_on_paint;
   GetStruct()->on_accelerated_paint = render_handler_on_accelerated_paint;
-  GetStruct()->on_cursor_change = render_handler_on_cursor_change;
+  GetStruct()->get_touch_handle_size = render_handler_get_touch_handle_size;
+  GetStruct()->on_touch_handle_state_changed =
+      render_handler_on_touch_handle_state_changed;
   GetStruct()->start_dragging = render_handler_start_dragging;
   GetStruct()->update_drag_cursor = render_handler_update_drag_cursor;
   GetStruct()->on_scroll_offset_changed =
@@ -561,7 +644,7 @@
     CefRenderHandler,
     cef_render_handler_t>::UnwrapDerived(CefWrapperType type,
                                          cef_render_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/render_handler_cpptoc.h b/src/libcef_dll/cpptoc/render_handler_cpptoc.h
index a4cadcc..f56251d 100644
--- a/src/libcef_dll/cpptoc/render_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/render_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4078c8aa17effd6bbe1deeab9d0f996a9f5f3a60$
+// $hash=a0cdfb84f8b30f01dd01556ad3e1725e043641e0$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_RENDER_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/render_process_handler_cpptoc.cc b/src/libcef_dll/cpptoc/render_process_handler_cpptoc.cc
index 39c64f4..253e450 100644
--- a/src/libcef_dll/cpptoc/render_process_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/render_process_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=41d141e97c1a248bdf7834b583bb417333b55955$
+// $hash=41a3981a7d293d6a13bba9961192d4fc7f0a49f1$
 //
 
 #include "libcef_dll/cpptoc/render_process_handler_cpptoc.h"
@@ -18,7 +18,6 @@
 #include "libcef_dll/ctocpp/dictionary_value_ctocpp.h"
 #include "libcef_dll/ctocpp/domnode_ctocpp.h"
 #include "libcef_dll/ctocpp/frame_ctocpp.h"
-#include "libcef_dll/ctocpp/list_value_ctocpp.h"
 #include "libcef_dll/ctocpp/process_message_ctocpp.h"
 #include "libcef_dll/ctocpp/v8context_ctocpp.h"
 #include "libcef_dll/ctocpp/v8exception_ctocpp.h"
@@ -28,31 +27,14 @@
 
 // MEMBER FUNCTIONS - Body may be edited by hand.
 
-void CEF_CALLBACK render_process_handler_on_render_thread_created(
-    struct _cef_render_process_handler_t* self,
-    struct _cef_list_value_t* extra_info) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return;
-  // Verify param: extra_info; type: refptr_diff
-  DCHECK(extra_info);
-  if (!extra_info)
-    return;
-
-  // Execute
-  CefRenderProcessHandlerCppToC::Get(self)->OnRenderThreadCreated(
-      CefListValueCToCpp::Wrap(extra_info));
-}
-
 void CEF_CALLBACK render_process_handler_on_web_kit_initialized(
     struct _cef_render_process_handler_t* self) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefRenderProcessHandlerCppToC::Get(self)->OnWebKitInitialized();
@@ -65,16 +47,15 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
-  // Verify param: extra_info; type: refptr_diff
-  DCHECK(extra_info);
-  if (!extra_info)
-    return;
+  }
+  // Unverified params: extra_info
 
   // Execute
   CefRenderProcessHandlerCppToC::Get(self)->OnBrowserCreated(
@@ -88,12 +69,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefRenderProcessHandlerCppToC::Get(self)->OnBrowserDestroyed(
@@ -105,8 +88,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefLoadHandler> _retval =
@@ -124,20 +108,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return;
+  }
   // Verify param: context; type: refptr_diff
   DCHECK(context);
-  if (!context)
+  if (!context) {
     return;
+  }
 
   // Execute
   CefRenderProcessHandlerCppToC::Get(self)->OnContextCreated(
@@ -153,20 +141,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return;
+  }
   // Verify param: context; type: refptr_diff
   DCHECK(context);
-  if (!context)
+  if (!context) {
     return;
+  }
 
   // Execute
   CefRenderProcessHandlerCppToC::Get(self)->OnContextReleased(
@@ -184,28 +176,34 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return;
+  }
   // Verify param: context; type: refptr_diff
   DCHECK(context);
-  if (!context)
+  if (!context) {
     return;
+  }
   // Verify param: exception; type: refptr_diff
   DCHECK(exception);
-  if (!exception)
+  if (!exception) {
     return;
+  }
   // Verify param: stackTrace; type: refptr_diff
   DCHECK(stackTrace);
-  if (!stackTrace)
+  if (!stackTrace) {
     return;
+  }
 
   // Execute
   CefRenderProcessHandlerCppToC::Get(self)->OnUncaughtException(
@@ -222,12 +220,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
   // Unverified params: frame, node
 
   // Execute
@@ -245,20 +245,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return 0;
+  }
   // Verify param: message; type: refptr_diff
   DCHECK(message);
-  if (!message)
+  if (!message) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -275,8 +279,6 @@
 // CONSTRUCTOR - Do not edit by hand.
 
 CefRenderProcessHandlerCppToC::CefRenderProcessHandlerCppToC() {
-  GetStruct()->on_render_thread_created =
-      render_process_handler_on_render_thread_created;
   GetStruct()->on_web_kit_initialized =
       render_process_handler_on_web_kit_initialized;
   GetStruct()->on_browser_created = render_process_handler_on_browser_created;
@@ -304,7 +306,7 @@
     cef_render_process_handler_t>::UnwrapDerived(CefWrapperType type,
                                                  cef_render_process_handler_t*
                                                      s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/render_process_handler_cpptoc.h b/src/libcef_dll/cpptoc/render_process_handler_cpptoc.h
index ebafce5..124c4a5 100644
--- a/src/libcef_dll/cpptoc/render_process_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/render_process_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=bb8a36e35b6f5dae03f31cac87b6090796277dbd$
+// $hash=1686827d48e7c0d75a603a2b6b8ca05b4f158340$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_RENDER_PROCESS_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/request_callback_cpptoc.cc b/src/libcef_dll/cpptoc/request_callback_cpptoc.cc
deleted file mode 100644
index c0bcbc4..0000000
--- a/src/libcef_dll/cpptoc/request_callback_cpptoc.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=6564dd6b1da89671525b39541e0a7e45415c8bed$
-//
-
-#include "libcef_dll/cpptoc/request_callback_cpptoc.h"
-#include "libcef_dll/shutdown_checker.h"
-
-namespace {
-
-// MEMBER FUNCTIONS - Body may be edited by hand.
-
-void CEF_CALLBACK request_callback_cont(struct _cef_request_callback_t* self,
-                                        int allow) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return;
-
-  // Execute
-  CefRequestCallbackCppToC::Get(self)->Continue(allow ? true : false);
-}
-
-void CEF_CALLBACK
-request_callback_cancel(struct _cef_request_callback_t* self) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return;
-
-  // Execute
-  CefRequestCallbackCppToC::Get(self)->Cancel();
-}
-
-}  // namespace
-
-// CONSTRUCTOR - Do not edit by hand.
-
-CefRequestCallbackCppToC::CefRequestCallbackCppToC() {
-  GetStruct()->cont = request_callback_cont;
-  GetStruct()->cancel = request_callback_cancel;
-}
-
-// DESTRUCTOR - Do not edit by hand.
-
-CefRequestCallbackCppToC::~CefRequestCallbackCppToC() {
-  shutdown_checker::AssertNotShutdown();
-}
-
-template <>
-CefRefPtr<CefRequestCallback> CefCppToCRefCounted<
-    CefRequestCallbackCppToC,
-    CefRequestCallback,
-    cef_request_callback_t>::UnwrapDerived(CefWrapperType type,
-                                           cef_request_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
-  return nullptr;
-}
-
-template <>
-CefWrapperType CefCppToCRefCounted<CefRequestCallbackCppToC,
-                                   CefRequestCallback,
-                                   cef_request_callback_t>::kWrapperType =
-    WT_REQUEST_CALLBACK;
diff --git a/src/libcef_dll/cpptoc/request_callback_cpptoc.h b/src/libcef_dll/cpptoc/request_callback_cpptoc.h
deleted file mode 100644
index a7000e8..0000000
--- a/src/libcef_dll/cpptoc/request_callback_cpptoc.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=a2f22e0169bde2d05e6d85e1e769cb03a03a7c12$
-//
-
-#ifndef CEF_LIBCEF_DLL_CPPTOC_REQUEST_CALLBACK_CPPTOC_H_
-#define CEF_LIBCEF_DLL_CPPTOC_REQUEST_CALLBACK_CPPTOC_H_
-#pragma once
-
-#if !defined(BUILDING_CEF_SHARED)
-#error This file can be included DLL-side only
-#endif
-
-#include "include/capi/cef_request_callback_capi.h"
-#include "include/cef_request_callback.h"
-#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
-
-// Wrap a C++ class with a C structure.
-// This class may be instantiated and accessed DLL-side only.
-class CefRequestCallbackCppToC
-    : public CefCppToCRefCounted<CefRequestCallbackCppToC,
-                                 CefRequestCallback,
-                                 cef_request_callback_t> {
- public:
-  CefRequestCallbackCppToC();
-  virtual ~CefRequestCallbackCppToC();
-};
-
-#endif  // CEF_LIBCEF_DLL_CPPTOC_REQUEST_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/request_context_cpptoc.cc b/src/libcef_dll/cpptoc/request_context_cpptoc.cc
index c252e42..453898d 100644
--- a/src/libcef_dll/cpptoc/request_context_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/request_context_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=5168000f75f7911dce0bffcf47341e4ee1c2a275$
+// $hash=19ec3227b1676b8a359d6ea1264dea80ed717049$
 //
 
 #include "libcef_dll/cpptoc/request_context_cpptoc.h"
@@ -23,6 +23,7 @@
 #include "libcef_dll/ctocpp/request_context_handler_ctocpp.h"
 #include "libcef_dll/ctocpp/resolve_callback_ctocpp.h"
 #include "libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h"
+#include "libcef_dll/template_util.h"
 #include "libcef_dll/transfer_util.h"
 
 // GLOBAL FUNCTIONS - Body may be edited by hand.
@@ -44,14 +45,20 @@
 
   // Verify param: settings; type: struct_byref_const
   DCHECK(settings);
-  if (!settings)
+  if (!settings) {
     return NULL;
+  }
+  if (!template_util::has_valid_size(settings)) {
+    DCHECK(false) << "invalid settings->[base.]size";
+    return NULL;
+  }
   // Unverified params: handler
 
   // Translate param: settings; type: struct_byref_const
   CefRequestContextSettings settingsObj;
-  if (settings)
+  if (settings) {
     settingsObj.Set(*settings, false);
+  }
 
   // Execute
   CefRefPtr<CefRequestContext> _retval = CefRequestContext::CreateContext(
@@ -68,8 +75,9 @@
 
   // Verify param: other; type: refptr_same
   DCHECK(other);
-  if (!other)
+  if (!other) {
     return NULL;
+  }
   // Unverified params: handler
 
   // Execute
@@ -90,12 +98,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: other; type: refptr_same
   DCHECK(other);
-  if (!other)
+  if (!other) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefRequestContextCppToC::Get(self)->IsSame(
@@ -111,12 +121,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: other; type: refptr_same
   DCHECK(other);
-  if (!other)
+  if (!other) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefRequestContextCppToC::Get(self)->IsSharingWith(
@@ -131,8 +143,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefRequestContextCppToC::Get(self)->IsGlobal();
@@ -146,8 +159,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefRequestContextHandler> _retval =
@@ -162,8 +176,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefRequestContextCppToC::Get(self)->GetCachePath();
@@ -178,8 +193,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Unverified params: callback
 
   // Execute
@@ -199,12 +215,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: scheme_name; type: string_byref_const
   DCHECK(scheme_name);
-  if (!scheme_name)
+  if (!scheme_name) {
     return 0;
+  }
   // Unverified params: domain_name, factory
 
   // Execute
@@ -222,8 +240,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -233,140 +252,15 @@
   return _retval;
 }
 
-void CEF_CALLBACK
-request_context_purge_plugin_list_cache(struct _cef_request_context_t* self,
-                                        int reload_pages) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return;
-
-  // Execute
-  CefRequestContextCppToC::Get(self)->PurgePluginListCache(
-      reload_pages ? true : false);
-}
-
-int CEF_CALLBACK
-request_context_has_preference(struct _cef_request_context_t* self,
-                               const cef_string_t* name) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return 0;
-  // Verify param: name; type: string_byref_const
-  DCHECK(name);
-  if (!name)
-    return 0;
-
-  // Execute
-  bool _retval =
-      CefRequestContextCppToC::Get(self)->HasPreference(CefString(name));
-
-  // Return type: bool
-  return _retval;
-}
-
-struct _cef_value_t* CEF_CALLBACK
-request_context_get_preference(struct _cef_request_context_t* self,
-                               const cef_string_t* name) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return NULL;
-  // Verify param: name; type: string_byref_const
-  DCHECK(name);
-  if (!name)
-    return NULL;
-
-  // Execute
-  CefRefPtr<CefValue> _retval =
-      CefRequestContextCppToC::Get(self)->GetPreference(CefString(name));
-
-  // Return type: refptr_same
-  return CefValueCppToC::Wrap(_retval);
-}
-
-struct _cef_dictionary_value_t* CEF_CALLBACK
-request_context_get_all_preferences(struct _cef_request_context_t* self,
-                                    int include_defaults) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return NULL;
-
-  // Execute
-  CefRefPtr<CefDictionaryValue> _retval =
-      CefRequestContextCppToC::Get(self)->GetAllPreferences(
-          include_defaults ? true : false);
-
-  // Return type: refptr_same
-  return CefDictionaryValueCppToC::Wrap(_retval);
-}
-
-int CEF_CALLBACK
-request_context_can_set_preference(struct _cef_request_context_t* self,
-                                   const cef_string_t* name) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return 0;
-  // Verify param: name; type: string_byref_const
-  DCHECK(name);
-  if (!name)
-    return 0;
-
-  // Execute
-  bool _retval =
-      CefRequestContextCppToC::Get(self)->CanSetPreference(CefString(name));
-
-  // Return type: bool
-  return _retval;
-}
-
-int CEF_CALLBACK
-request_context_set_preference(struct _cef_request_context_t* self,
-                               const cef_string_t* name,
-                               struct _cef_value_t* value,
-                               cef_string_t* error) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return 0;
-  // Verify param: name; type: string_byref_const
-  DCHECK(name);
-  if (!name)
-    return 0;
-  // Verify param: error; type: string_byref
-  DCHECK(error);
-  if (!error)
-    return 0;
-  // Unverified params: value
-
-  // Translate param: error; type: string_byref
-  CefString errorStr(error);
-
-  // Execute
-  bool _retval = CefRequestContextCppToC::Get(self)->SetPreference(
-      CefString(name), CefValueCppToC::Unwrap(value), errorStr);
-
-  // Return type: bool
-  return _retval;
-}
-
 void CEF_CALLBACK request_context_clear_certificate_exceptions(
     struct _cef_request_context_t* self,
     cef_completion_callback_t* callback) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: callback
 
   // Execute
@@ -380,8 +274,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: callback
 
   // Execute
@@ -395,8 +290,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: callback
 
   // Execute
@@ -411,16 +307,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: origin; type: string_byref_const
   DCHECK(origin);
-  if (!origin)
+  if (!origin) {
     return;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return;
+  }
 
   // Execute
   CefRequestContextCppToC::Get(self)->ResolveHost(
@@ -435,12 +334,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: root_directory; type: string_byref_const
   DCHECK(root_directory);
-  if (!root_directory)
+  if (!root_directory) {
     return;
+  }
   // Unverified params: manifest, handler
 
   // Execute
@@ -455,12 +356,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: extension_id; type: string_byref_const
   DCHECK(extension_id);
-  if (!extension_id)
+  if (!extension_id) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefRequestContextCppToC::Get(self)->DidLoadExtension(
@@ -476,12 +379,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: extension_id; type: string_byref_const
   DCHECK(extension_id);
-  if (!extension_id)
+  if (!extension_id) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -497,12 +402,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: extension_ids; type: string_vec_byref
   DCHECK(extension_ids);
-  if (!extension_ids)
+  if (!extension_ids) {
     return 0;
+  }
 
   // Translate param: extension_ids; type: string_vec_byref
   std::vector<CefString> extension_idsList;
@@ -526,12 +433,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: extension_id; type: string_byref_const
   DCHECK(extension_id);
-  if (!extension_id)
+  if (!extension_id) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefExtension> _retval =
@@ -542,21 +451,237 @@
 }
 
 cef_media_router_t* CEF_CALLBACK
-request_context_get_media_router(struct _cef_request_context_t* self) {
+request_context_get_media_router(struct _cef_request_context_t* self,
+                                 cef_completion_callback_t* callback) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
+  // Unverified params: callback
 
   // Execute
   CefRefPtr<CefMediaRouter> _retval =
-      CefRequestContextCppToC::Get(self)->GetMediaRouter();
+      CefRequestContextCppToC::Get(self)->GetMediaRouter(
+          CefCompletionCallbackCToCpp::Wrap(callback));
 
   // Return type: refptr_same
   return CefMediaRouterCppToC::Wrap(_retval);
 }
 
+struct _cef_value_t* CEF_CALLBACK
+request_context_get_website_setting(struct _cef_request_context_t* self,
+                                    const cef_string_t* requesting_url,
+                                    const cef_string_t* top_level_url,
+                                    cef_content_setting_types_t content_type) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+  // Unverified params: requesting_url, top_level_url
+
+  // Execute
+  CefRefPtr<CefValue> _retval =
+      CefRequestContextCppToC::Get(self)->GetWebsiteSetting(
+          CefString(requesting_url), CefString(top_level_url), content_type);
+
+  // Return type: refptr_same
+  return CefValueCppToC::Wrap(_retval);
+}
+
+void CEF_CALLBACK
+request_context_set_website_setting(struct _cef_request_context_t* self,
+                                    const cef_string_t* requesting_url,
+                                    const cef_string_t* top_level_url,
+                                    cef_content_setting_types_t content_type,
+                                    struct _cef_value_t* value) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Unverified params: requesting_url, top_level_url, value
+
+  // Execute
+  CefRequestContextCppToC::Get(self)->SetWebsiteSetting(
+      CefString(requesting_url), CefString(top_level_url), content_type,
+      CefValueCppToC::Unwrap(value));
+}
+
+cef_content_setting_values_t CEF_CALLBACK
+request_context_get_content_setting(struct _cef_request_context_t* self,
+                                    const cef_string_t* requesting_url,
+                                    const cef_string_t* top_level_url,
+                                    cef_content_setting_types_t content_type) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CEF_CONTENT_SETTING_VALUE_DEFAULT;
+  }
+  // Unverified params: requesting_url, top_level_url
+
+  // Execute
+  cef_content_setting_values_t _retval =
+      CefRequestContextCppToC::Get(self)->GetContentSetting(
+          CefString(requesting_url), CefString(top_level_url), content_type);
+
+  // Return type: simple
+  return _retval;
+}
+
+void CEF_CALLBACK
+request_context_set_content_setting(struct _cef_request_context_t* self,
+                                    const cef_string_t* requesting_url,
+                                    const cef_string_t* top_level_url,
+                                    cef_content_setting_types_t content_type,
+                                    cef_content_setting_values_t value) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Unverified params: requesting_url, top_level_url
+
+  // Execute
+  CefRequestContextCppToC::Get(self)->SetContentSetting(
+      CefString(requesting_url), CefString(top_level_url), content_type, value);
+}
+
+int CEF_CALLBACK
+request_context_has_preference(struct _cef_preference_manager_t* self,
+                               const cef_string_t* name) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: name; type: string_byref_const
+  DCHECK(name);
+  if (!name) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefRequestContextCppToC::Get(
+                     reinterpret_cast<cef_request_context_t*>(self))
+                     ->HasPreference(CefString(name));
+
+  // Return type: bool
+  return _retval;
+}
+
+struct _cef_value_t* CEF_CALLBACK
+request_context_get_preference(struct _cef_preference_manager_t* self,
+                               const cef_string_t* name) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+  // Verify param: name; type: string_byref_const
+  DCHECK(name);
+  if (!name) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefValue> _retval =
+      CefRequestContextCppToC::Get(
+          reinterpret_cast<cef_request_context_t*>(self))
+          ->GetPreference(CefString(name));
+
+  // Return type: refptr_same
+  return CefValueCppToC::Wrap(_retval);
+}
+
+struct _cef_dictionary_value_t* CEF_CALLBACK
+request_context_get_all_preferences(struct _cef_preference_manager_t* self,
+                                    int include_defaults) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefDictionaryValue> _retval =
+      CefRequestContextCppToC::Get(
+          reinterpret_cast<cef_request_context_t*>(self))
+          ->GetAllPreferences(include_defaults ? true : false);
+
+  // Return type: refptr_same
+  return CefDictionaryValueCppToC::Wrap(_retval);
+}
+
+int CEF_CALLBACK
+request_context_can_set_preference(struct _cef_preference_manager_t* self,
+                                   const cef_string_t* name) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: name; type: string_byref_const
+  DCHECK(name);
+  if (!name) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefRequestContextCppToC::Get(
+                     reinterpret_cast<cef_request_context_t*>(self))
+                     ->CanSetPreference(CefString(name));
+
+  // Return type: bool
+  return _retval;
+}
+
+int CEF_CALLBACK
+request_context_set_preference(struct _cef_preference_manager_t* self,
+                               const cef_string_t* name,
+                               struct _cef_value_t* value,
+                               cef_string_t* error) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: name; type: string_byref_const
+  DCHECK(name);
+  if (!name) {
+    return 0;
+  }
+  // Verify param: error; type: string_byref
+  DCHECK(error);
+  if (!error) {
+    return 0;
+  }
+  // Unverified params: value
+
+  // Translate param: error; type: string_byref
+  CefString errorStr(error);
+
+  // Execute
+  bool _retval = CefRequestContextCppToC::Get(
+                     reinterpret_cast<cef_request_context_t*>(self))
+                     ->SetPreference(CefString(name),
+                                     CefValueCppToC::Unwrap(value), errorStr);
+
+  // Return type: bool
+  return _retval;
+}
+
 }  // namespace
 
 // CONSTRUCTOR - Do not edit by hand.
@@ -572,13 +697,6 @@
       request_context_register_scheme_handler_factory;
   GetStruct()->clear_scheme_handler_factories =
       request_context_clear_scheme_handler_factories;
-  GetStruct()->purge_plugin_list_cache =
-      request_context_purge_plugin_list_cache;
-  GetStruct()->has_preference = request_context_has_preference;
-  GetStruct()->get_preference = request_context_get_preference;
-  GetStruct()->get_all_preferences = request_context_get_all_preferences;
-  GetStruct()->can_set_preference = request_context_can_set_preference;
-  GetStruct()->set_preference = request_context_set_preference;
   GetStruct()->clear_certificate_exceptions =
       request_context_clear_certificate_exceptions;
   GetStruct()->clear_http_auth_credentials =
@@ -591,6 +709,15 @@
   GetStruct()->get_extensions = request_context_get_extensions;
   GetStruct()->get_extension = request_context_get_extension;
   GetStruct()->get_media_router = request_context_get_media_router;
+  GetStruct()->get_website_setting = request_context_get_website_setting;
+  GetStruct()->set_website_setting = request_context_set_website_setting;
+  GetStruct()->get_content_setting = request_context_get_content_setting;
+  GetStruct()->set_content_setting = request_context_set_content_setting;
+  GetStruct()->base.has_preference = request_context_has_preference;
+  GetStruct()->base.get_preference = request_context_get_preference;
+  GetStruct()->base.get_all_preferences = request_context_get_all_preferences;
+  GetStruct()->base.can_set_preference = request_context_can_set_preference;
+  GetStruct()->base.set_preference = request_context_set_preference;
 }
 
 // DESTRUCTOR - Do not edit by hand.
@@ -603,7 +730,7 @@
     CefRequestContext,
     cef_request_context_t>::UnwrapDerived(CefWrapperType type,
                                           cef_request_context_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/request_context_cpptoc.h b/src/libcef_dll/cpptoc/request_context_cpptoc.h
index 451b6f8..f798fef 100644
--- a/src/libcef_dll/cpptoc/request_context_cpptoc.h
+++ b/src/libcef_dll/cpptoc/request_context_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ea7cba74131f394dddd0c33df1d6788436fd8581$
+// $hash=07ccff0f6993fe1634467a76d9996081fca0ec3a$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_REQUEST_CONTEXT_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/request_context_handler_cpptoc.cc b/src/libcef_dll/cpptoc/request_context_handler_cpptoc.cc
index 3812397..3497eb5 100644
--- a/src/libcef_dll/cpptoc/request_context_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/request_context_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f7c9de5f1d996c73233fe89a3a53bb9a8f92da11$
+// $hash=c247859a657da56e23b37918bd647b81c5ae316c$
 //
 
 #include "libcef_dll/cpptoc/request_context_handler_cpptoc.h"
@@ -18,7 +18,6 @@
 #include "libcef_dll/ctocpp/frame_ctocpp.h"
 #include "libcef_dll/ctocpp/request_context_ctocpp.h"
 #include "libcef_dll/ctocpp/request_ctocpp.h"
-#include "libcef_dll/ctocpp/web_plugin_info_ctocpp.h"
 
 namespace {
 
@@ -30,55 +29,20 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: request_context; type: refptr_diff
   DCHECK(request_context);
-  if (!request_context)
+  if (!request_context) {
     return;
+  }
 
   // Execute
   CefRequestContextHandlerCppToC::Get(self)->OnRequestContextInitialized(
       CefRequestContextCToCpp::Wrap(request_context));
 }
 
-int CEF_CALLBACK request_context_handler_on_before_plugin_load(
-    struct _cef_request_context_handler_t* self,
-    const cef_string_t* mime_type,
-    const cef_string_t* plugin_url,
-    int is_main_frame,
-    const cef_string_t* top_origin_url,
-    struct _cef_web_plugin_info_t* plugin_info,
-    cef_plugin_policy_t* plugin_policy) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return 0;
-  // Verify param: mime_type; type: string_byref_const
-  DCHECK(mime_type);
-  if (!mime_type)
-    return 0;
-  // Verify param: plugin_info; type: refptr_diff
-  DCHECK(plugin_info);
-  if (!plugin_info)
-    return 0;
-  // Verify param: plugin_policy; type: simple_byaddr
-  DCHECK(plugin_policy);
-  if (!plugin_policy)
-    return 0;
-  // Unverified params: plugin_url, top_origin_url
-
-  // Execute
-  bool _retval = CefRequestContextHandlerCppToC::Get(self)->OnBeforePluginLoad(
-      CefString(mime_type), CefString(plugin_url), is_main_frame ? true : false,
-      CefString(top_origin_url), CefWebPluginInfoCToCpp::Wrap(plugin_info),
-      plugin_policy);
-
-  // Return type: bool
-  return _retval;
-}
-
 struct _cef_resource_request_handler_t* CEF_CALLBACK
 request_context_handler_get_resource_request_handler(
     struct _cef_request_context_handler_t* self,
@@ -92,16 +56,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return NULL;
+  }
   // Verify param: disable_default_handling; type: bool_byref
   DCHECK(disable_default_handling);
-  if (!disable_default_handling)
+  if (!disable_default_handling) {
     return NULL;
+  }
   // Unverified params: browser, frame, request_initiator
 
   // Translate param: disable_default_handling; type: bool_byref
@@ -117,8 +84,9 @@
           disable_default_handlingBool);
 
   // Restore param: disable_default_handling; type: bool_byref
-  if (disable_default_handling)
+  if (disable_default_handling) {
     *disable_default_handling = disable_default_handlingBool ? true : false;
+  }
 
   // Return type: refptr_same
   return CefResourceRequestHandlerCppToC::Wrap(_retval);
@@ -131,8 +99,6 @@
 CefRequestContextHandlerCppToC::CefRequestContextHandlerCppToC() {
   GetStruct()->on_request_context_initialized =
       request_context_handler_on_request_context_initialized;
-  GetStruct()->on_before_plugin_load =
-      request_context_handler_on_before_plugin_load;
   GetStruct()->get_resource_request_handler =
       request_context_handler_get_resource_request_handler;
 }
@@ -148,7 +114,7 @@
     cef_request_context_handler_t>::UnwrapDerived(CefWrapperType type,
                                                   cef_request_context_handler_t*
                                                       s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/request_context_handler_cpptoc.h b/src/libcef_dll/cpptoc/request_context_handler_cpptoc.h
index 1f386dc..7a002b9 100644
--- a/src/libcef_dll/cpptoc/request_context_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/request_context_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=16255caf8417becd716db31c87e58c2bbffce4c8$
+// $hash=0985ec29d8f7825abf5542f7bff3a0477431fc1a$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_REQUEST_CONTEXT_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/request_cpptoc.cc b/src/libcef_dll/cpptoc/request_cpptoc.cc
index db08249..2b7d54a 100644
--- a/src/libcef_dll/cpptoc/request_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/request_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=50c2166b6a1c9699b480e7bcc1f0da7e4d5b938e$
+// $hash=665dc752dccd84d278f794b5c6c76093f285112c$
 //
 
 #include "libcef_dll/cpptoc/request_cpptoc.h"
@@ -36,8 +36,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefRequestCppToC::Get(self)->IsReadOnly();
@@ -51,8 +52,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefRequestCppToC::Get(self)->GetURL();
@@ -66,12 +68,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: url; type: string_byref_const
   DCHECK(url);
-  if (!url)
+  if (!url) {
     return;
+  }
 
   // Execute
   CefRequestCppToC::Get(self)->SetURL(CefString(url));
@@ -82,8 +86,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefRequestCppToC::Get(self)->GetMethod();
@@ -97,12 +102,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: method; type: string_byref_const
   DCHECK(method);
-  if (!method)
+  if (!method) {
     return;
+  }
 
   // Execute
   CefRequestCppToC::Get(self)->SetMethod(CefString(method));
@@ -114,8 +121,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: referrer_url
 
   // Execute
@@ -127,8 +135,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefRequestCppToC::Get(self)->GetReferrerURL();
@@ -142,8 +151,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return REFERRER_POLICY_DEFAULT;
+  }
 
   // Execute
   cef_referrer_policy_t _retval =
@@ -158,8 +168,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefPostData> _retval = CefRequestCppToC::Get(self)->GetPostData();
@@ -173,12 +184,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: postData; type: refptr_same
   DCHECK(postData);
-  if (!postData)
+  if (!postData) {
     return;
+  }
 
   // Execute
   CefRequestCppToC::Get(self)->SetPostData(CefPostDataCppToC::Unwrap(postData));
@@ -189,12 +202,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: headerMap; type: string_map_multi_byref
   DCHECK(headerMap);
-  if (!headerMap)
+  if (!headerMap) {
     return;
+  }
 
   // Translate param: headerMap; type: string_map_multi_byref
   std::multimap<CefString, CefString> headerMapMultimap;
@@ -213,12 +228,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: headerMap; type: string_map_multi_byref_const
   DCHECK(headerMap);
-  if (!headerMap)
+  if (!headerMap) {
     return;
+  }
 
   // Translate param: headerMap; type: string_map_multi_byref_const
   std::multimap<CefString, CefString> headerMapMultimap;
@@ -234,12 +251,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -256,12 +275,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
   // Unverified params: value
 
   // Execute
@@ -277,20 +298,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: url; type: string_byref_const
   DCHECK(url);
-  if (!url)
+  if (!url) {
     return;
+  }
   // Verify param: method; type: string_byref_const
   DCHECK(method);
-  if (!method)
+  if (!method) {
     return;
+  }
   // Verify param: headerMap; type: string_map_multi_byref_const
   DCHECK(headerMap);
-  if (!headerMap)
+  if (!headerMap) {
     return;
+  }
   // Unverified params: postData
 
   // Translate param: headerMap; type: string_map_multi_byref_const
@@ -307,8 +332,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return UR_FLAG_NONE;
+  }
 
   // Execute
   int _retval = CefRequestCppToC::Get(self)->GetFlags();
@@ -321,8 +347,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefRequestCppToC::Get(self)->SetFlags(flags);
@@ -333,8 +360,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefRequestCppToC::Get(self)->GetFirstPartyForCookies();
@@ -349,8 +377,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: url
 
   // Execute
@@ -362,8 +391,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return RT_SUB_RESOURCE;
+  }
 
   // Execute
   cef_resource_type_t _retval = CefRequestCppToC::Get(self)->GetResourceType();
@@ -377,8 +407,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return TT_EXPLICIT;
+  }
 
   // Execute
   cef_transition_type_t _retval =
@@ -388,15 +419,16 @@
   return _retval;
 }
 
-uint64 CEF_CALLBACK request_get_identifier(struct _cef_request_t* self) {
+uint64_t CEF_CALLBACK request_get_identifier(struct _cef_request_t* self) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
-  uint64 _retval = CefRequestCppToC::Get(self)->GetIdentifier();
+  uint64_t _retval = CefRequestCppToC::Get(self)->GetIdentifier();
 
   // Return type: simple
   return _retval;
@@ -442,7 +474,7 @@
 CefCppToCRefCounted<CefRequestCppToC, CefRequest, cef_request_t>::UnwrapDerived(
     CefWrapperType type,
     cef_request_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/request_cpptoc.h b/src/libcef_dll/cpptoc/request_cpptoc.h
index 478f22e..723e1de 100644
--- a/src/libcef_dll/cpptoc/request_cpptoc.h
+++ b/src/libcef_dll/cpptoc/request_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ee87fe2283f86a6801ca7650b8883ba2c2d4598f$
+// $hash=406c30cba514a450568bc341a7facf5495ab58a5$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_REQUEST_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/request_handler_cpptoc.cc b/src/libcef_dll/cpptoc/request_handler_cpptoc.cc
index bef261d..0c8da73 100644
--- a/src/libcef_dll/cpptoc/request_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/request_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,15 +9,15 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=716501855da0203723eb18bfb9e518c7b155f110$
+// $hash=c487cecbbd674cf04f14e4b3e0f018145f238373$
 //
 
 #include "libcef_dll/cpptoc/request_handler_cpptoc.h"
 #include "libcef_dll/cpptoc/resource_request_handler_cpptoc.h"
 #include "libcef_dll/ctocpp/auth_callback_ctocpp.h"
 #include "libcef_dll/ctocpp/browser_ctocpp.h"
+#include "libcef_dll/ctocpp/callback_ctocpp.h"
 #include "libcef_dll/ctocpp/frame_ctocpp.h"
-#include "libcef_dll/ctocpp/request_callback_ctocpp.h"
 #include "libcef_dll/ctocpp/request_ctocpp.h"
 #include "libcef_dll/ctocpp/select_client_certificate_callback_ctocpp.h"
 #include "libcef_dll/ctocpp/sslinfo_ctocpp.h"
@@ -40,20 +40,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return 0;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefRequestHandlerCppToC::Get(self)->OnBeforeBrowse(
@@ -77,20 +81,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return 0;
+  }
   // Verify param: target_url; type: string_byref_const
   DCHECK(target_url);
-  if (!target_url)
+  if (!target_url) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefRequestHandlerCppToC::Get(self)->OnOpenURLFromTab(
@@ -116,24 +124,29 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return NULL;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return NULL;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return NULL;
+  }
   // Verify param: disable_default_handling; type: bool_byref
   DCHECK(disable_default_handling);
-  if (!disable_default_handling)
+  if (!disable_default_handling) {
     return NULL;
+  }
   // Unverified params: request_initiator
 
   // Translate param: disable_default_handling; type: bool_byref
@@ -149,8 +162,9 @@
           disable_default_handlingBool);
 
   // Restore param: disable_default_handling; type: bool_byref
-  if (disable_default_handling)
+  if (disable_default_handling) {
     *disable_default_handling = disable_default_handlingBool ? true : false;
+  }
 
   // Return type: refptr_same
   return CefResourceRequestHandlerCppToC::Wrap(_retval);
@@ -171,24 +185,29 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: origin_url; type: string_byref_const
   DCHECK(origin_url);
-  if (!origin_url)
+  if (!origin_url) {
     return 0;
+  }
   // Verify param: host; type: string_byref_const
   DCHECK(host);
-  if (!host)
+  if (!host) {
     return 0;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return 0;
+  }
   // Unverified params: realm, scheme
 
   // Execute
@@ -202,76 +221,45 @@
 }
 
 int CEF_CALLBACK
-request_handler_on_quota_request(struct _cef_request_handler_t* self,
-                                 cef_browser_t* browser,
-                                 const cef_string_t* origin_url,
-                                 int64 new_size,
-                                 cef_request_callback_t* callback) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return 0;
-  // Verify param: browser; type: refptr_diff
-  DCHECK(browser);
-  if (!browser)
-    return 0;
-  // Verify param: origin_url; type: string_byref_const
-  DCHECK(origin_url);
-  if (!origin_url)
-    return 0;
-  // Verify param: callback; type: refptr_diff
-  DCHECK(callback);
-  if (!callback)
-    return 0;
-
-  // Execute
-  bool _retval = CefRequestHandlerCppToC::Get(self)->OnQuotaRequest(
-      CefBrowserCToCpp::Wrap(browser), CefString(origin_url), new_size,
-      CefRequestCallbackCToCpp::Wrap(callback));
-
-  // Return type: bool
-  return _retval;
-}
-
-int CEF_CALLBACK
 request_handler_on_certificate_error(struct _cef_request_handler_t* self,
                                      cef_browser_t* browser,
                                      cef_errorcode_t cert_error,
                                      const cef_string_t* request_url,
                                      struct _cef_sslinfo_t* ssl_info,
-                                     cef_request_callback_t* callback) {
+                                     cef_callback_t* callback) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: request_url; type: string_byref_const
   DCHECK(request_url);
-  if (!request_url)
+  if (!request_url) {
     return 0;
+  }
   // Verify param: ssl_info; type: refptr_diff
   DCHECK(ssl_info);
-  if (!ssl_info)
+  if (!ssl_info) {
     return 0;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefRequestHandlerCppToC::Get(self)->OnCertificateError(
       CefBrowserCToCpp::Wrap(browser), cert_error, CefString(request_url),
-      CefSSLInfoCToCpp::Wrap(ssl_info),
-      CefRequestCallbackCToCpp::Wrap(callback));
+      CefSSLInfoCToCpp::Wrap(ssl_info), CefCallbackCToCpp::Wrap(callback));
 
   // Return type: bool
   return _retval;
@@ -291,24 +279,29 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return 0;
+  }
   // Verify param: host; type: string_byref_const
   DCHECK(host);
-  if (!host)
+  if (!host) {
     return 0;
+  }
   // Verify param: certificates; type: refptr_vec_diff_byref_const
   DCHECK(certificatesCount == 0 || certificates);
-  if (certificatesCount > 0 && !certificates)
+  if (certificatesCount > 0 && !certificates) {
     return 0;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return 0;
+  }
 
   // Translate param: certificates; type: refptr_vec_diff_byref_const
   std::vector<CefRefPtr<CefX509Certificate>> certificatesList;
@@ -331,31 +324,6 @@
 }
 
 void CEF_CALLBACK
-request_handler_on_plugin_crashed(struct _cef_request_handler_t* self,
-                                  cef_browser_t* browser,
-                                  const cef_string_t* plugin_path) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return;
-  // Verify param: browser; type: refptr_diff
-  DCHECK(browser);
-  if (!browser)
-    return;
-  // Verify param: plugin_path; type: string_byref_const
-  DCHECK(plugin_path);
-  if (!plugin_path)
-    return;
-
-  // Execute
-  CefRequestHandlerCppToC::Get(self)->OnPluginCrashed(
-      CefBrowserCToCpp::Wrap(browser), CefString(plugin_path));
-}
-
-void CEF_CALLBACK
 request_handler_on_render_view_ready(struct _cef_request_handler_t* self,
                                      cef_browser_t* browser) {
   shutdown_checker::AssertNotShutdown();
@@ -363,12 +331,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefRequestHandlerCppToC::Get(self)->OnRenderViewReady(
@@ -384,12 +354,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefRequestHandlerCppToC::Get(self)->OnRenderProcessTerminated(
@@ -404,12 +376,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefRequestHandlerCppToC::Get(self)->OnDocumentAvailableInMainFrame(
@@ -426,11 +400,9 @@
   GetStruct()->get_resource_request_handler =
       request_handler_get_resource_request_handler;
   GetStruct()->get_auth_credentials = request_handler_get_auth_credentials;
-  GetStruct()->on_quota_request = request_handler_on_quota_request;
   GetStruct()->on_certificate_error = request_handler_on_certificate_error;
   GetStruct()->on_select_client_certificate =
       request_handler_on_select_client_certificate;
-  GetStruct()->on_plugin_crashed = request_handler_on_plugin_crashed;
   GetStruct()->on_render_view_ready = request_handler_on_render_view_ready;
   GetStruct()->on_render_process_terminated =
       request_handler_on_render_process_terminated;
@@ -450,7 +422,7 @@
     CefRequestHandler,
     cef_request_handler_t>::UnwrapDerived(CefWrapperType type,
                                           cef_request_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/request_handler_cpptoc.h b/src/libcef_dll/cpptoc/request_handler_cpptoc.h
index 4d7c1df..73ff5d4 100644
--- a/src/libcef_dll/cpptoc/request_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/request_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=bccd3bcc8f2fbd0aea2f41b08c54a3c99e3d218f$
+// $hash=0167d427e72426d439b11b2655caac2b79a7b8de$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_REQUEST_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/resolve_callback_cpptoc.cc b/src/libcef_dll/cpptoc/resolve_callback_cpptoc.cc
index 5cf8dd1..17548f2 100644
--- a/src/libcef_dll/cpptoc/resolve_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/resolve_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f7af7bfb68cb621f8aa6686bc0895854d33f9b06$
+// $hash=e71369876af6d78b7f94e54b7ea5cf19c091a12a$
 //
 
 #include "libcef_dll/cpptoc/resolve_callback_cpptoc.h"
@@ -29,8 +29,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: resolved_ips
 
   // Translate param: resolved_ips; type: string_vec_byref_const
@@ -62,7 +63,7 @@
     CefResolveCallback,
     cef_resolve_callback_t>::UnwrapDerived(CefWrapperType type,
                                            cef_resolve_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/resolve_callback_cpptoc.h b/src/libcef_dll/cpptoc/resolve_callback_cpptoc.h
index f576011..cd35ce3 100644
--- a/src/libcef_dll/cpptoc/resolve_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/resolve_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c1c4d90577819019fc7e3667b34101e1a36b8db7$
+// $hash=aea5c318f99d23b06478b765f81720890aa098b3$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_RESOLVE_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/resource_bundle_cpptoc.cc b/src/libcef_dll/cpptoc/resource_bundle_cpptoc.cc
index 3a9235c..81e78d5 100644
--- a/src/libcef_dll/cpptoc/resource_bundle_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/resource_bundle_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,10 +9,11 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ba0a12367019906d32dae965d7d1b5245d02b442$
+// $hash=fc8189d4a430b02f6de35a53188be505db59bfa4$
 //
 
 #include "libcef_dll/cpptoc/resource_bundle_cpptoc.h"
+#include "libcef_dll/cpptoc/binary_value_cpptoc.h"
 
 // GLOBAL FUNCTIONS - Body may be edited by hand.
 
@@ -36,8 +37,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -47,83 +49,42 @@
   return _retval.DetachToUserFree();
 }
 
-int CEF_CALLBACK
+struct _cef_binary_value_t* CEF_CALLBACK
 resource_bundle_get_data_resource(struct _cef_resource_bundle_t* self,
-                                  int resource_id,
-                                  void** data,
-                                  size_t* data_size) {
+                                  int resource_id) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
-    return 0;
-  // Verify param: data; type: simple_byref
-  DCHECK(data);
-  if (!data)
-    return 0;
-  // Verify param: data_size; type: simple_byref
-  DCHECK(data_size);
-  if (!data_size)
-    return 0;
-
-  // Translate param: data; type: simple_byref
-  void* dataVal = data ? *data : NULL;
-  // Translate param: data_size; type: simple_byref
-  size_t data_sizeVal = data_size ? *data_size : 0;
+  if (!self) {
+    return NULL;
+  }
 
   // Execute
-  bool _retval = CefResourceBundleCppToC::Get(self)->GetDataResource(
-      resource_id, dataVal, data_sizeVal);
+  CefRefPtr<CefBinaryValue> _retval =
+      CefResourceBundleCppToC::Get(self)->GetDataResource(resource_id);
 
-  // Restore param: data; type: simple_byref
-  if (data)
-    *data = dataVal;
-  // Restore param: data_size; type: simple_byref
-  if (data_size)
-    *data_size = data_sizeVal;
-
-  // Return type: bool
-  return _retval;
+  // Return type: refptr_same
+  return CefBinaryValueCppToC::Wrap(_retval);
 }
 
-int CEF_CALLBACK
+struct _cef_binary_value_t* CEF_CALLBACK
 resource_bundle_get_data_resource_for_scale(struct _cef_resource_bundle_t* self,
                                             int resource_id,
-                                            cef_scale_factor_t scale_factor,
-                                            void** data,
-                                            size_t* data_size) {
+                                            cef_scale_factor_t scale_factor) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
-    return 0;
-  // Verify param: data; type: simple_byref
-  DCHECK(data);
-  if (!data)
-    return 0;
-  // Verify param: data_size; type: simple_byref
-  DCHECK(data_size);
-  if (!data_size)
-    return 0;
-
-  // Translate param: data; type: simple_byref
-  void* dataVal = data ? *data : NULL;
-  // Translate param: data_size; type: simple_byref
-  size_t data_sizeVal = data_size ? *data_size : 0;
+  if (!self) {
+    return NULL;
+  }
 
   // Execute
-  bool _retval = CefResourceBundleCppToC::Get(self)->GetDataResourceForScale(
-      resource_id, scale_factor, dataVal, data_sizeVal);
+  CefRefPtr<CefBinaryValue> _retval =
+      CefResourceBundleCppToC::Get(self)->GetDataResourceForScale(resource_id,
+                                                                  scale_factor);
 
-  // Restore param: data; type: simple_byref
-  if (data)
-    *data = dataVal;
-  // Restore param: data_size; type: simple_byref
-  if (data_size)
-    *data_size = data_sizeVal;
-
-  // Return type: bool
-  return _retval;
+  // Return type: refptr_same
+  return CefBinaryValueCppToC::Wrap(_retval);
 }
 
 }  // namespace
@@ -147,7 +108,7 @@
     CefResourceBundle,
     cef_resource_bundle_t>::UnwrapDerived(CefWrapperType type,
                                           cef_resource_bundle_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/resource_bundle_cpptoc.h b/src/libcef_dll/cpptoc/resource_bundle_cpptoc.h
index 2339c97..8102bff 100644
--- a/src/libcef_dll/cpptoc/resource_bundle_cpptoc.h
+++ b/src/libcef_dll/cpptoc/resource_bundle_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8164a4e23b7fc82cdcf231d0393b197077926d68$
+// $hash=c126e6379765b577e7251c418bd3fe4dbe392522$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_RESOURCE_BUNDLE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.cc b/src/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.cc
index 1211fa4..5133784 100644
--- a/src/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b041280729bcbe060d591caccd43deeb208d02b2$
+// $hash=7f625b08e4c82a608dd7178b571f80fce5fe0d70$
 //
 
 #include "libcef_dll/cpptoc/resource_bundle_handler_cpptoc.h"
@@ -28,12 +28,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: string; type: string_byref
   DCHECK(string);
-  if (!string)
+  if (!string) {
     return 0;
+  }
 
   // Translate param: string; type: string_byref
   CefString stringStr(string);
@@ -56,16 +58,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: data; type: simple_byref
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return 0;
+  }
   // Verify param: data_size; type: simple_byref
   DCHECK(data_size);
-  if (!data_size)
+  if (!data_size) {
     return 0;
+  }
 
   // Translate param: data; type: simple_byref
   void* dataVal = data ? *data : NULL;
@@ -77,11 +82,13 @@
       resource_id, dataVal, data_sizeVal);
 
   // Restore param: data; type: simple_byref
-  if (data)
+  if (data) {
     *data = dataVal;
+  }
   // Restore param: data_size; type: simple_byref
-  if (data_size)
+  if (data_size) {
     *data_size = data_sizeVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -98,16 +105,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: data; type: simple_byref
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return 0;
+  }
   // Verify param: data_size; type: simple_byref
   DCHECK(data_size);
-  if (!data_size)
+  if (!data_size) {
     return 0;
+  }
 
   // Translate param: data; type: simple_byref
   void* dataVal = data ? *data : NULL;
@@ -120,11 +130,13 @@
           resource_id, scale_factor, dataVal, data_sizeVal);
 
   // Restore param: data; type: simple_byref
-  if (data)
+  if (data) {
     *data = dataVal;
+  }
   // Restore param: data_size; type: simple_byref
-  if (data_size)
+  if (data_size) {
     *data_size = data_sizeVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -155,7 +167,7 @@
     cef_resource_bundle_handler_t>::UnwrapDerived(CefWrapperType type,
                                                   cef_resource_bundle_handler_t*
                                                       s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.h b/src/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.h
index e83a405..3b74d91 100644
--- a/src/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=14d8ddea86b253b3963da1e2fd9ddb17a1306451$
+// $hash=f6e9e2a12912ea7b9ab5060481e323c180698725$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_RESOURCE_BUNDLE_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/resource_handler_cpptoc.cc b/src/libcef_dll/cpptoc/resource_handler_cpptoc.cc
index d515ba5..4756623 100644
--- a/src/libcef_dll/cpptoc/resource_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/resource_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4f0405f57b7364001a3ecf56c8d6502f7eaf818a$
+// $hash=b88df417b6c03aa94901820a7cc4682cf3bceb51$
 //
 
 #include "libcef_dll/cpptoc/resource_handler_cpptoc.h"
@@ -33,20 +33,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return 0;
+  }
   // Verify param: handle_request; type: bool_byref
   DCHECK(handle_request);
-  if (!handle_request)
+  if (!handle_request) {
     return 0;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return 0;
+  }
 
   // Translate param: handle_request; type: bool_byref
   bool handle_requestBool = (handle_request && *handle_request) ? true : false;
@@ -57,8 +61,9 @@
       CefCallbackCToCpp::Wrap(callback));
 
   // Restore param: handle_request; type: bool_byref
-  if (handle_request)
+  if (handle_request) {
     *handle_request = handle_requestBool ? true : false;
+  }
 
   // Return type: bool
   return _retval;
@@ -73,16 +78,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return 0;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefResourceHandlerCppToC::Get(self)->ProcessRequest(
@@ -95,30 +103,34 @@
 void CEF_CALLBACK
 resource_handler_get_response_headers(struct _cef_resource_handler_t* self,
                                       struct _cef_response_t* response,
-                                      int64* response_length,
+                                      int64_t* response_length,
                                       cef_string_t* redirectUrl) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: response; type: refptr_diff
   DCHECK(response);
-  if (!response)
+  if (!response) {
     return;
+  }
   // Verify param: response_length; type: simple_byref
   DCHECK(response_length);
-  if (!response_length)
+  if (!response_length) {
     return;
+  }
   // Verify param: redirectUrl; type: string_byref
   DCHECK(redirectUrl);
-  if (!redirectUrl)
+  if (!redirectUrl) {
     return;
+  }
 
   // Translate param: response_length; type: simple_byref
-  int64 response_lengthVal = response_length ? *response_length : 0;
+  int64_t response_lengthVal = response_length ? *response_length : 0;
   // Translate param: redirectUrl; type: string_byref
   CefString redirectUrlStr(redirectUrl);
 
@@ -127,32 +139,36 @@
       CefResponseCToCpp::Wrap(response), response_lengthVal, redirectUrlStr);
 
   // Restore param: response_length; type: simple_byref
-  if (response_length)
+  if (response_length) {
     *response_length = response_lengthVal;
+  }
 }
 
 int CEF_CALLBACK resource_handler_skip(struct _cef_resource_handler_t* self,
-                                       int64 bytes_to_skip,
-                                       int64* bytes_skipped,
+                                       int64_t bytes_to_skip,
+                                       int64_t* bytes_skipped,
                                        cef_resource_skip_callback_t* callback) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: bytes_skipped; type: simple_byref
   DCHECK(bytes_skipped);
-  if (!bytes_skipped)
+  if (!bytes_skipped) {
     return 0;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return 0;
+  }
 
   // Translate param: bytes_skipped; type: simple_byref
-  int64 bytes_skippedVal = bytes_skipped ? *bytes_skipped : 0;
+  int64_t bytes_skippedVal = bytes_skipped ? *bytes_skipped : 0;
 
   // Execute
   bool _retval = CefResourceHandlerCppToC::Get(self)->Skip(
@@ -160,8 +176,9 @@
       CefResourceSkipCallbackCToCpp::Wrap(callback));
 
   // Restore param: bytes_skipped; type: simple_byref
-  if (bytes_skipped)
+  if (bytes_skipped) {
     *bytes_skipped = bytes_skippedVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -177,20 +194,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: data_out; type: simple_byaddr
   DCHECK(data_out);
-  if (!data_out)
+  if (!data_out) {
     return 0;
+  }
   // Verify param: bytes_read; type: simple_byref
   DCHECK(bytes_read);
-  if (!bytes_read)
+  if (!bytes_read) {
     return 0;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return 0;
+  }
 
   // Translate param: bytes_read; type: simple_byref
   int bytes_readVal = bytes_read ? *bytes_read : 0;
@@ -201,8 +222,9 @@
       CefResourceReadCallbackCToCpp::Wrap(callback));
 
   // Restore param: bytes_read; type: simple_byref
-  if (bytes_read)
+  if (bytes_read) {
     *bytes_read = bytes_readVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -219,20 +241,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: data_out; type: simple_byaddr
   DCHECK(data_out);
-  if (!data_out)
+  if (!data_out) {
     return 0;
+  }
   // Verify param: bytes_read; type: simple_byref
   DCHECK(bytes_read);
-  if (!bytes_read)
+  if (!bytes_read) {
     return 0;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return 0;
+  }
 
   // Translate param: bytes_read; type: simple_byref
   int bytes_readVal = bytes_read ? *bytes_read : 0;
@@ -243,8 +269,9 @@
       CefCallbackCToCpp::Wrap(callback));
 
   // Restore param: bytes_read; type: simple_byref
-  if (bytes_read)
+  if (bytes_read) {
     *bytes_read = bytes_readVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -257,8 +284,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefResourceHandlerCppToC::Get(self)->Cancel();
@@ -290,7 +318,7 @@
     CefResourceHandler,
     cef_resource_handler_t>::UnwrapDerived(CefWrapperType type,
                                            cef_resource_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/resource_handler_cpptoc.h b/src/libcef_dll/cpptoc/resource_handler_cpptoc.h
index ce1750a..fc57f64 100644
--- a/src/libcef_dll/cpptoc/resource_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/resource_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c2767ff40514f4b4901656da7e7b8fe004eecc1c$
+// $hash=3853a8b89137fdd6c71bc86f801536517bde7c88$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_RESOURCE_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/resource_read_callback_cpptoc.cc b/src/libcef_dll/cpptoc/resource_read_callback_cpptoc.cc
index e1f1c1c..cb55e8d 100644
--- a/src/libcef_dll/cpptoc/resource_read_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/resource_read_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3e7417f66df20a3329577fceaceb329f835290e4$
+// $hash=c7fa8f548cc0e606e09fe76532b3d2bc19473b16$
 //
 
 #include "libcef_dll/cpptoc/resource_read_callback_cpptoc.h"
@@ -27,8 +27,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefResourceReadCallbackCppToC::Get(self)->Continue(bytes_read);
@@ -55,7 +56,7 @@
     cef_resource_read_callback_t>::UnwrapDerived(CefWrapperType type,
                                                  cef_resource_read_callback_t*
                                                      s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/resource_read_callback_cpptoc.h b/src/libcef_dll/cpptoc/resource_read_callback_cpptoc.h
index 51c38b4..f152b5d 100644
--- a/src/libcef_dll/cpptoc/resource_read_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/resource_read_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=35d620ce2f1cb16c858f37cf8c5c518bc36b5aea$
+// $hash=f5efbaafb5a54dfb9deb422cf31a0908c8a4cfc3$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_RESOURCE_READ_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/resource_request_handler_cpptoc.cc b/src/libcef_dll/cpptoc/resource_request_handler_cpptoc.cc
index 09a7d55..b212629 100644
--- a/src/libcef_dll/cpptoc/resource_request_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/resource_request_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b21e07c41e050dd666e5e25a3b9041e67d1fd299$
+// $hash=6cda6276be92cb33660e4cff45fb664515facec1$
 //
 
 #include "libcef_dll/cpptoc/resource_request_handler_cpptoc.h"
@@ -17,8 +17,8 @@
 #include "libcef_dll/cpptoc/resource_handler_cpptoc.h"
 #include "libcef_dll/cpptoc/response_filter_cpptoc.h"
 #include "libcef_dll/ctocpp/browser_ctocpp.h"
+#include "libcef_dll/ctocpp/callback_ctocpp.h"
 #include "libcef_dll/ctocpp/frame_ctocpp.h"
-#include "libcef_dll/ctocpp/request_callback_ctocpp.h"
 #include "libcef_dll/ctocpp/request_ctocpp.h"
 #include "libcef_dll/ctocpp/response_ctocpp.h"
 
@@ -35,12 +35,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return NULL;
+  }
   // Unverified params: browser, frame
 
   // Execute
@@ -59,28 +61,30 @@
     cef_browser_t* browser,
     cef_frame_t* frame,
     cef_request_t* request,
-    cef_request_callback_t* callback) {
+    cef_callback_t* callback) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return RV_CONTINUE;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return RV_CONTINUE;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return RV_CONTINUE;
+  }
   // Unverified params: browser, frame
 
   // Execute
   cef_return_value_t _retval =
       CefResourceRequestHandlerCppToC::Get(self)->OnBeforeResourceLoad(
           CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame),
-          CefRequestCToCpp::Wrap(request),
-          CefRequestCallbackCToCpp::Wrap(callback));
+          CefRequestCToCpp::Wrap(request), CefCallbackCToCpp::Wrap(callback));
 
   // Return type: simple
   return _retval;
@@ -95,12 +99,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return NULL;
+  }
   // Unverified params: browser, frame
 
   // Execute
@@ -123,20 +129,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return;
+  }
   // Verify param: response; type: refptr_diff
   DCHECK(response);
-  if (!response)
+  if (!response) {
     return;
+  }
   // Verify param: new_url; type: string_byref
   DCHECK(new_url);
-  if (!new_url)
+  if (!new_url) {
     return;
+  }
   // Unverified params: browser, frame
 
   // Translate param: new_url; type: string_byref
@@ -158,16 +168,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return 0;
+  }
   // Verify param: response; type: refptr_diff
   DCHECK(response);
-  if (!response)
+  if (!response) {
     return 0;
+  }
   // Unverified params: browser, frame
 
   // Execute
@@ -189,16 +202,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return NULL;
+  }
   // Verify param: response; type: refptr_diff
   DCHECK(response);
-  if (!response)
+  if (!response) {
     return NULL;
+  }
   // Unverified params: browser, frame
 
   // Execute
@@ -218,20 +234,23 @@
     cef_request_t* request,
     struct _cef_response_t* response,
     cef_urlrequest_status_t status,
-    int64 received_content_length) {
+    int64_t received_content_length) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return;
+  }
   // Verify param: response; type: refptr_diff
   DCHECK(response);
-  if (!response)
+  if (!response) {
     return;
+  }
   // Unverified params: browser, frame
 
   // Execute
@@ -250,16 +269,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return;
+  }
   // Verify param: allow_os_execution; type: bool_byref
   DCHECK(allow_os_execution);
-  if (!allow_os_execution)
+  if (!allow_os_execution) {
     return;
+  }
   // Unverified params: browser, frame
 
   // Translate param: allow_os_execution; type: bool_byref
@@ -272,8 +294,9 @@
       CefRequestCToCpp::Wrap(request), allow_os_executionBool);
 
   // Restore param: allow_os_execution; type: bool_byref
-  if (allow_os_execution)
+  if (allow_os_execution) {
     *allow_os_execution = allow_os_executionBool ? true : false;
+  }
 }
 
 }  // namespace
@@ -309,7 +332,7 @@
                     CefResourceRequestHandler,
                     cef_resource_request_handler_t>::
     UnwrapDerived(CefWrapperType type, cef_resource_request_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/resource_request_handler_cpptoc.h b/src/libcef_dll/cpptoc/resource_request_handler_cpptoc.h
index 2a7f3cc..7010001 100644
--- a/src/libcef_dll/cpptoc/resource_request_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/resource_request_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6279d2c726b5418595c1cdd7c4557de590af60a0$
+// $hash=0b8d614a76b9027970354dc850f7b491348a2941$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_RESOURCE_REQUEST_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/resource_skip_callback_cpptoc.cc b/src/libcef_dll/cpptoc/resource_skip_callback_cpptoc.cc
index 906583e..1379f92 100644
--- a/src/libcef_dll/cpptoc/resource_skip_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/resource_skip_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1cb83ab583c93ae5b46cdd75a1a053d806a2d388$
+// $hash=cd09888724297c57eac0b71ebbe54e097588cfd2$
 //
 
 #include "libcef_dll/cpptoc/resource_skip_callback_cpptoc.h"
@@ -21,14 +21,15 @@
 
 void CEF_CALLBACK
 resource_skip_callback_cont(struct _cef_resource_skip_callback_t* self,
-                            int64 bytes_skipped) {
+                            int64_t bytes_skipped) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefResourceSkipCallbackCppToC::Get(self)->Continue(bytes_skipped);
@@ -55,7 +56,7 @@
     cef_resource_skip_callback_t>::UnwrapDerived(CefWrapperType type,
                                                  cef_resource_skip_callback_t*
                                                      s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/resource_skip_callback_cpptoc.h b/src/libcef_dll/cpptoc/resource_skip_callback_cpptoc.h
index 3d7bde6..d7a8271 100644
--- a/src/libcef_dll/cpptoc/resource_skip_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/resource_skip_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=cd59d4e2414727eda67fe7994eba8737ddb9c336$
+// $hash=5e756fb08a289333025a894573332555a1ab8e1f$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_RESOURCE_SKIP_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/response_cpptoc.cc b/src/libcef_dll/cpptoc/response_cpptoc.cc
index 8d0f6ae..ee44c1d 100644
--- a/src/libcef_dll/cpptoc/response_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/response_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=becfb6e4e0d47746f10295fa4843c9baebc786b5$
+// $hash=f0c69112a4eba6862aa54a4df7fa10f7e361edf7$
 //
 
 #include "libcef_dll/cpptoc/response_cpptoc.h"
@@ -35,8 +35,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefResponseCppToC::Get(self)->IsReadOnly();
@@ -49,8 +50,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return ERR_NONE;
+  }
 
   // Execute
   cef_errorcode_t _retval = CefResponseCppToC::Get(self)->GetError();
@@ -64,8 +66,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefResponseCppToC::Get(self)->SetError(error);
@@ -75,8 +78,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefResponseCppToC::Get(self)->GetStatus();
@@ -90,8 +94,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefResponseCppToC::Get(self)->SetStatus(status);
@@ -102,8 +107,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefResponseCppToC::Get(self)->GetStatusText();
@@ -117,8 +123,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: statusText
 
   // Execute
@@ -130,8 +137,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefResponseCppToC::Get(self)->GetMimeType();
@@ -145,8 +153,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: mimeType
 
   // Execute
@@ -158,8 +167,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefResponseCppToC::Get(self)->GetCharset();
@@ -173,8 +183,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: charset
 
   // Execute
@@ -187,12 +198,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -209,12 +222,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
   // Unverified params: value
 
   // Execute
@@ -227,12 +242,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: headerMap; type: string_map_multi_byref
   DCHECK(headerMap);
-  if (!headerMap)
+  if (!headerMap) {
     return;
+  }
 
   // Translate param: headerMap; type: string_map_multi_byref
   std::multimap<CefString, CefString> headerMapMultimap;
@@ -251,12 +268,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: headerMap; type: string_map_multi_byref_const
   DCHECK(headerMap);
-  if (!headerMap)
+  if (!headerMap) {
     return;
+  }
 
   // Translate param: headerMap; type: string_map_multi_byref_const
   std::multimap<CefString, CefString> headerMapMultimap;
@@ -271,8 +290,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefResponseCppToC::Get(self)->GetURL();
@@ -286,8 +306,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: url
 
   // Execute
@@ -326,7 +347,7 @@
 CefRefPtr<CefResponse>
 CefCppToCRefCounted<CefResponseCppToC, CefResponse, cef_response_t>::
     UnwrapDerived(CefWrapperType type, cef_response_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/response_cpptoc.h b/src/libcef_dll/cpptoc/response_cpptoc.h
index 74f393b..b84c699 100644
--- a/src/libcef_dll/cpptoc/response_cpptoc.h
+++ b/src/libcef_dll/cpptoc/response_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=77aefe2ee459cef3a90edcedcaf25980c97c91eb$
+// $hash=624d1cb515a9f5f44d6e63574021689ccfe09b76$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_RESPONSE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/response_filter_cpptoc.cc b/src/libcef_dll/cpptoc/response_filter_cpptoc.cc
index 7359546..faac250 100644
--- a/src/libcef_dll/cpptoc/response_filter_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/response_filter_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=464d0d568a1b3712452c0f8406057bd598440f20$
+// $hash=403513566867d0fd85166242648f269fac987ca5$
 //
 
 #include "libcef_dll/cpptoc/response_filter_cpptoc.h"
@@ -26,8 +26,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefResponseFilterCppToC::Get(self)->InitFilter();
@@ -49,20 +50,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return RESPONSE_FILTER_ERROR;
+  }
   // Verify param: data_in_read; type: simple_byref
   DCHECK(data_in_read);
-  if (!data_in_read)
+  if (!data_in_read) {
     return RESPONSE_FILTER_ERROR;
+  }
   // Verify param: data_out; type: simple_byaddr
   DCHECK(data_out);
-  if (!data_out)
+  if (!data_out) {
     return RESPONSE_FILTER_ERROR;
+  }
   // Verify param: data_out_written; type: simple_byref
   DCHECK(data_out_written);
-  if (!data_out_written)
+  if (!data_out_written) {
     return RESPONSE_FILTER_ERROR;
+  }
   // Unverified params: data_in
 
   // Translate param: data_in_read; type: simple_byref
@@ -77,11 +82,13 @@
           data_out_writtenVal);
 
   // Restore param: data_in_read; type: simple_byref
-  if (data_in_read)
+  if (data_in_read) {
     *data_in_read = data_in_readVal;
+  }
   // Restore param: data_out_written; type: simple_byref
-  if (data_out_written)
+  if (data_out_written) {
     *data_out_written = data_out_writtenVal;
+  }
 
   // Return type: simple
   return _retval;
@@ -108,7 +115,7 @@
     CefResponseFilter,
     cef_response_filter_t>::UnwrapDerived(CefWrapperType type,
                                           cef_response_filter_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/response_filter_cpptoc.h b/src/libcef_dll/cpptoc/response_filter_cpptoc.h
index 1b77e5c..c17599d 100644
--- a/src/libcef_dll/cpptoc/response_filter_cpptoc.h
+++ b/src/libcef_dll/cpptoc/response_filter_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1cdc6d51716626972e346cc2eaf03d396067ea8a$
+// $hash=55d4dc0a6467d6d084de5e1114be0fcd36ae89b9$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_RESPONSE_FILTER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/run_context_menu_callback_cpptoc.cc b/src/libcef_dll/cpptoc/run_context_menu_callback_cpptoc.cc
index 591f757..171da8a 100644
--- a/src/libcef_dll/cpptoc/run_context_menu_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/run_context_menu_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7445defe1636c34ac7fc05e2acb02330cf71ef6e$
+// $hash=e0ae5295de1a999b825687b01fcb494d2901dacc$
 //
 
 #include "libcef_dll/cpptoc/run_context_menu_callback_cpptoc.h"
@@ -28,8 +28,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefRunContextMenuCallbackCppToC::Get(self)->Continue(command_id, event_flags);
@@ -42,8 +43,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefRunContextMenuCallbackCppToC::Get(self)->Cancel();
@@ -70,7 +72,7 @@
                     CefRunContextMenuCallback,
                     cef_run_context_menu_callback_t>::
     UnwrapDerived(CefWrapperType type, cef_run_context_menu_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/run_context_menu_callback_cpptoc.h b/src/libcef_dll/cpptoc/run_context_menu_callback_cpptoc.h
index b5329a6..954af27 100644
--- a/src/libcef_dll/cpptoc/run_context_menu_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/run_context_menu_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0bdb34b3f23060c3bdc9f81f20bd1a31fe843713$
+// $hash=a41928b718004e3e8cc92ba620b20f76ad9181b7$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_RUN_CONTEXT_MENU_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.cc b/src/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.cc
index 0166fa3..eb2e83c 100644
--- a/src/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d2364091da1298fe5b7d1e168cc21016128660bf$
+// $hash=e55e25cbcc3f016810209ddad7d351f021306820$
 //
 
 #include "libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h"
@@ -22,19 +22,15 @@
 
 void CEF_CALLBACK run_file_dialog_callback_on_file_dialog_dismissed(
     struct _cef_run_file_dialog_callback_t* self,
-    int selected_accept_filter,
     cef_string_list_t file_paths) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
-  // Verify param: selected_accept_filter; type: simple_byval
-  DCHECK_GE(selected_accept_filter, 0);
-  if (selected_accept_filter < 0)
-    return;
+  }
   // Unverified params: file_paths
 
   // Translate param: file_paths; type: string_vec_byref_const
@@ -43,7 +39,7 @@
 
   // Execute
   CefRunFileDialogCallbackCppToC::Get(self)->OnFileDialogDismissed(
-      selected_accept_filter, file_pathsList);
+      file_pathsList);
 }
 
 }  // namespace
@@ -67,7 +63,7 @@
                     CefRunFileDialogCallback,
                     cef_run_file_dialog_callback_t>::
     UnwrapDerived(CefWrapperType type, cef_run_file_dialog_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h b/src/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h
index 93ca495..c5dac2e 100644
--- a/src/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f683c2febb92bc08f9e5f82cc0ec35c334026ca2$
+// $hash=7f45e5e5b3772e10b2eb6901c3e27e835a873163$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_RUN_FILE_DIALOG_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/run_quick_menu_callback_cpptoc.cc b/src/libcef_dll/cpptoc/run_quick_menu_callback_cpptoc.cc
new file mode 100644
index 0000000..d9f5969
--- /dev/null
+++ b/src/libcef_dll/cpptoc/run_quick_menu_callback_cpptoc.cc
@@ -0,0 +1,85 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=005e5ae02a04bc6fdd626063b1f83e465e21e498$
+//
+
+#include "libcef_dll/cpptoc/run_quick_menu_callback_cpptoc.h"
+#include "libcef_dll/shutdown_checker.h"
+
+namespace {
+
+// MEMBER FUNCTIONS - Body may be edited by hand.
+
+void CEF_CALLBACK
+run_quick_menu_callback_cont(struct _cef_run_quick_menu_callback_t* self,
+                             int command_id,
+                             cef_event_flags_t event_flags) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+
+  // Execute
+  CefRunQuickMenuCallbackCppToC::Get(self)->Continue(command_id, event_flags);
+}
+
+void CEF_CALLBACK
+run_quick_menu_callback_cancel(struct _cef_run_quick_menu_callback_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+
+  // Execute
+  CefRunQuickMenuCallbackCppToC::Get(self)->Cancel();
+}
+
+}  // namespace
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefRunQuickMenuCallbackCppToC::CefRunQuickMenuCallbackCppToC() {
+  GetStruct()->cont = run_quick_menu_callback_cont;
+  GetStruct()->cancel = run_quick_menu_callback_cancel;
+}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefRunQuickMenuCallbackCppToC::~CefRunQuickMenuCallbackCppToC() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+CefRefPtr<CefRunQuickMenuCallback> CefCppToCRefCounted<
+    CefRunQuickMenuCallbackCppToC,
+    CefRunQuickMenuCallback,
+    cef_run_quick_menu_callback_t>::UnwrapDerived(CefWrapperType type,
+                                                  cef_run_quick_menu_callback_t*
+                                                      s) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType
+    CefCppToCRefCounted<CefRunQuickMenuCallbackCppToC,
+                        CefRunQuickMenuCallback,
+                        cef_run_quick_menu_callback_t>::kWrapperType =
+        WT_RUN_QUICK_MENU_CALLBACK;
diff --git a/src/libcef_dll/cpptoc/run_quick_menu_callback_cpptoc.h b/src/libcef_dll/cpptoc/run_quick_menu_callback_cpptoc.h
new file mode 100644
index 0000000..b8fa640
--- /dev/null
+++ b/src/libcef_dll/cpptoc/run_quick_menu_callback_cpptoc.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=acc845289f80273062c7fde7d81e0c034a80f4e1$
+//
+
+#ifndef CEF_LIBCEF_DLL_CPPTOC_RUN_QUICK_MENU_CALLBACK_CPPTOC_H_
+#define CEF_LIBCEF_DLL_CPPTOC_RUN_QUICK_MENU_CALLBACK_CPPTOC_H_
+#pragma once
+
+#if !defined(BUILDING_CEF_SHARED)
+#error This file can be included DLL-side only
+#endif
+
+#include "include/capi/cef_context_menu_handler_capi.h"
+#include "include/cef_context_menu_handler.h"
+#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
+
+// Wrap a C++ class with a C structure.
+// This class may be instantiated and accessed DLL-side only.
+class CefRunQuickMenuCallbackCppToC
+    : public CefCppToCRefCounted<CefRunQuickMenuCallbackCppToC,
+                                 CefRunQuickMenuCallback,
+                                 cef_run_quick_menu_callback_t> {
+ public:
+  CefRunQuickMenuCallbackCppToC();
+  virtual ~CefRunQuickMenuCallbackCppToC();
+};
+
+#endif  // CEF_LIBCEF_DLL_CPPTOC_RUN_QUICK_MENU_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.cc b/src/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.cc
index 9944830..0ca3d6c 100644
--- a/src/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2303bd78ed1cf87d4093a46ff6b0830e0f7e5090$
+// $hash=6220412461641a8ca21d4b521f3eb9e7db3ccb63$
 //
 
 #include "libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h"
@@ -31,16 +31,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: scheme_name; type: string_byref_const
   DCHECK(scheme_name);
-  if (!scheme_name)
+  if (!scheme_name) {
     return NULL;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return NULL;
+  }
   // Unverified params: browser, frame
 
   // Execute
@@ -72,7 +75,7 @@
     cef_scheme_handler_factory_t>::UnwrapDerived(CefWrapperType type,
                                                  cef_scheme_handler_factory_t*
                                                      s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h b/src/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h
index 5b07e2d..75daf7c 100644
--- a/src/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h
+++ b/src/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=63f4989c0dad8b36a2fc9152e657173e42af698e$
+// $hash=746b9d06b417c9730fa98fa456a08e5c53e5475b$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_SCHEME_HANDLER_FACTORY_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/scheme_registrar_cpptoc.cc b/src/libcef_dll/cpptoc/scheme_registrar_cpptoc.cc
index aefb1d9..d259652 100644
--- a/src/libcef_dll/cpptoc/scheme_registrar_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/scheme_registrar_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=64e26329466a4e6f497b648abbcb60bb5619b033$
+// $hash=850c94d117e9f4b80bc46f8748e0c278c8ef1dcb$
 //
 
 #include "libcef_dll/cpptoc/scheme_registrar_cpptoc.h"
@@ -25,12 +25,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: scheme_name; type: string_byref_const
   DCHECK(scheme_name);
-  if (!scheme_name)
+  if (!scheme_name) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefSchemeRegistrarCppToC::Get(self)->AddCustomScheme(
@@ -58,7 +60,7 @@
     CefSchemeRegistrar,
     cef_scheme_registrar_t>::UnwrapDerivedOwn(CefWrapperType type,
                                               cef_scheme_registrar_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return CefOwnPtr<CefSchemeRegistrar>();
 }
 
@@ -68,7 +70,7 @@
     CefSchemeRegistrar,
     cef_scheme_registrar_t>::UnwrapDerivedRaw(CefWrapperType type,
                                               cef_scheme_registrar_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/scheme_registrar_cpptoc.h b/src/libcef_dll/cpptoc/scheme_registrar_cpptoc.h
index 9a77c40..3966e21 100644
--- a/src/libcef_dll/cpptoc/scheme_registrar_cpptoc.h
+++ b/src/libcef_dll/cpptoc/scheme_registrar_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4e6d84fb9e3dd4b4f232686ebe01b12ab96daa9f$
+// $hash=92c5fb1f7d14753510b029f71579a26970f0304c$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_SCHEME_REGISTRAR_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/select_client_certificate_callback_cpptoc.cc b/src/libcef_dll/cpptoc/select_client_certificate_callback_cpptoc.cc
index 3b315ae..1390590 100644
--- a/src/libcef_dll/cpptoc/select_client_certificate_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/select_client_certificate_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=cc2fc42f673c2a27a73e5237f1c9533bf550aa33$
+// $hash=e873562bb3cc869d61a4a234b770ecd52c190c52$
 //
 
 #include "libcef_dll/cpptoc/select_client_certificate_callback_cpptoc.h"
@@ -28,8 +28,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: cert
 
   // Execute
@@ -60,7 +61,7 @@
                     cef_select_client_certificate_callback_t>::
     UnwrapDerived(CefWrapperType type,
                   cef_select_client_certificate_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/select_client_certificate_callback_cpptoc.h b/src/libcef_dll/cpptoc/select_client_certificate_callback_cpptoc.h
index e35a6d6..1001cdc 100644
--- a/src/libcef_dll/cpptoc/select_client_certificate_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/select_client_certificate_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=48bb19280dc30b73274f95d7e144ceb7439f859a$
+// $hash=a8aaabd6df08000d4add9785980560b8427b9d68$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_SELECT_CLIENT_CERTIFICATE_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/server_cpptoc.cc b/src/libcef_dll/cpptoc/server_cpptoc.cc
index fe98b85..2cbf9a7 100644
--- a/src/libcef_dll/cpptoc/server_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/server_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0a1970879ddc0bd40f5a564542ab8b11414a6b0a$
+// $hash=36b8cdbb6821347abd764616baa7b1582a2d8779$
 //
 
 #include "libcef_dll/cpptoc/server_cpptoc.h"
@@ -21,7 +21,7 @@
 // GLOBAL FUNCTIONS - Body may be edited by hand.
 
 CEF_EXPORT void cef_server_create(const cef_string_t* address,
-                                  uint16 port,
+                                  uint16_t port,
                                   int backlog,
                                   struct _cef_server_handler_t* handler) {
   shutdown_checker::AssertNotShutdown();
@@ -30,12 +30,14 @@
 
   // Verify param: address; type: string_byref_const
   DCHECK(address);
-  if (!address)
+  if (!address) {
     return;
+  }
   // Verify param: handler; type: refptr_diff
   DCHECK(handler);
-  if (!handler)
+  if (!handler) {
     return;
+  }
 
   // Execute
   CefServer::CreateServer(CefString(address), port, backlog,
@@ -53,8 +55,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTaskRunner> _retval =
@@ -70,8 +73,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefServerCppToC::Get(self)->Shutdown();
@@ -83,8 +87,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefServerCppToC::Get(self)->IsRunning();
@@ -100,8 +105,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefServerCppToC::Get(self)->GetAddress();
@@ -116,8 +122,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefServerCppToC::Get(self)->HasConnection();
@@ -133,8 +140,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefServerCppToC::Get(self)->IsValidConnection(connection_id);
@@ -153,16 +161,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: content_type; type: string_byref_const
   DCHECK(content_type);
-  if (!content_type)
+  if (!content_type) {
     return;
+  }
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return;
+  }
 
   // Execute
   CefServerCppToC::Get(self)->SendHttp200Response(
@@ -176,8 +187,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefServerCppToC::Get(self)->SendHttp404Response(connection_id);
@@ -192,12 +204,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: error_message; type: string_byref_const
   DCHECK(error_message);
-  if (!error_message)
+  if (!error_message) {
     return;
+  }
 
   // Execute
   CefServerCppToC::Get(self)->SendHttp500Response(connection_id,
@@ -209,19 +223,21 @@
                           int connection_id,
                           int response_code,
                           const cef_string_t* content_type,
-                          int64 content_length,
+                          int64_t content_length,
                           cef_string_multimap_t extra_headers) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: content_type; type: string_byref_const
   DCHECK(content_type);
-  if (!content_type)
+  if (!content_type) {
     return;
+  }
   // Unverified params: extra_headers
 
   // Translate param: extra_headers; type: string_map_multi_byref_const
@@ -243,12 +259,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return;
+  }
 
   // Execute
   CefServerCppToC::Get(self)->SendRawData(connection_id, data, data_size);
@@ -261,8 +279,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefServerCppToC::Get(self)->CloseConnection(connection_id);
@@ -277,12 +296,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return;
+  }
 
   // Execute
   CefServerCppToC::Get(self)->SendWebSocketMessage(connection_id, data,
@@ -320,7 +341,7 @@
 CefCppToCRefCounted<CefServerCppToC, CefServer, cef_server_t>::UnwrapDerived(
     CefWrapperType type,
     cef_server_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/server_cpptoc.h b/src/libcef_dll/cpptoc/server_cpptoc.h
index 4891bc5..fd191b0 100644
--- a/src/libcef_dll/cpptoc/server_cpptoc.h
+++ b/src/libcef_dll/cpptoc/server_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=69a46f4d4a439a917ffcd68951e7cae2a8bb61c3$
+// $hash=edf9787173ef035101e1d1805f2926b6028530f8$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_SERVER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/server_handler_cpptoc.cc b/src/libcef_dll/cpptoc/server_handler_cpptoc.cc
index d3442b7..75b7b07 100644
--- a/src/libcef_dll/cpptoc/server_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/server_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=82bf8ff61f6a36118817a1130aae9656cc3032e9$
+// $hash=8708ab56ea13185a17f585bb156114f7825408c1$
 //
 
 #include "libcef_dll/cpptoc/server_handler_cpptoc.h"
@@ -30,12 +30,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: server; type: refptr_diff
   DCHECK(server);
-  if (!server)
+  if (!server) {
     return;
+  }
 
   // Execute
   CefServerHandlerCppToC::Get(self)->OnServerCreated(
@@ -50,12 +52,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: server; type: refptr_diff
   DCHECK(server);
-  if (!server)
+  if (!server) {
     return;
+  }
 
   // Execute
   CefServerHandlerCppToC::Get(self)->OnServerDestroyed(
@@ -71,12 +75,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: server; type: refptr_diff
   DCHECK(server);
-  if (!server)
+  if (!server) {
     return;
+  }
 
   // Execute
   CefServerHandlerCppToC::Get(self)->OnClientConnected(
@@ -92,12 +98,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: server; type: refptr_diff
   DCHECK(server);
-  if (!server)
+  if (!server) {
     return;
+  }
 
   // Execute
   CefServerHandlerCppToC::Get(self)->OnClientDisconnected(
@@ -115,20 +123,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: server; type: refptr_diff
   DCHECK(server);
-  if (!server)
+  if (!server) {
     return;
+  }
   // Verify param: client_address; type: string_byref_const
   DCHECK(client_address);
-  if (!client_address)
+  if (!client_address) {
     return;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return;
+  }
 
   // Execute
   CefServerHandlerCppToC::Get(self)->OnHttpRequest(
@@ -148,24 +160,29 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: server; type: refptr_diff
   DCHECK(server);
-  if (!server)
+  if (!server) {
     return;
+  }
   // Verify param: client_address; type: string_byref_const
   DCHECK(client_address);
-  if (!client_address)
+  if (!client_address) {
     return;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return;
+  }
 
   // Execute
   CefServerHandlerCppToC::Get(self)->OnWebSocketRequest(
@@ -182,12 +199,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: server; type: refptr_diff
   DCHECK(server);
-  if (!server)
+  if (!server) {
     return;
+  }
 
   // Execute
   CefServerHandlerCppToC::Get(self)->OnWebSocketConnected(
@@ -205,16 +224,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: server; type: refptr_diff
   DCHECK(server);
-  if (!server)
+  if (!server) {
     return;
+  }
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return;
+  }
 
   // Execute
   CefServerHandlerCppToC::Get(self)->OnWebSocketMessage(
@@ -248,7 +270,7 @@
     CefServerHandler,
     cef_server_handler_t>::UnwrapDerived(CefWrapperType type,
                                          cef_server_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/server_handler_cpptoc.h b/src/libcef_dll/cpptoc/server_handler_cpptoc.h
index 1702f46..c452567 100644
--- a/src/libcef_dll/cpptoc/server_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/server_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7af0f6f99a4070d688fe113a1efcac821bc92e55$
+// $hash=ba72a7b9571b7e2d9d490a02972855eca1ff987f$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_SERVER_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/set_cookie_callback_cpptoc.cc b/src/libcef_dll/cpptoc/set_cookie_callback_cpptoc.cc
index 01cf68a..2ebd6d2 100644
--- a/src/libcef_dll/cpptoc/set_cookie_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/set_cookie_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=890a15d49f22e1050caff41e10b78e588b96e189$
+// $hash=65a2338d30ce4e012afe4e272f3c04ca65116f94$
 //
 
 #include "libcef_dll/cpptoc/set_cookie_callback_cpptoc.h"
@@ -27,8 +27,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefSetCookieCallbackCppToC::Get(self)->OnComplete(success ? true : false);
@@ -54,7 +55,7 @@
     CefSetCookieCallback,
     cef_set_cookie_callback_t>::UnwrapDerived(CefWrapperType type,
                                               cef_set_cookie_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/set_cookie_callback_cpptoc.h b/src/libcef_dll/cpptoc/set_cookie_callback_cpptoc.h
index e4ba0eb..85c3442 100644
--- a/src/libcef_dll/cpptoc/set_cookie_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/set_cookie_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=256712a2f53f4b334c36736169646befb12f49bb$
+// $hash=886b832f912900c89787888566d4d5e803c91ebc$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_SET_COOKIE_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/shared_memory_region_cpptoc.cc b/src/libcef_dll/cpptoc/shared_memory_region_cpptoc.cc
new file mode 100644
index 0000000..c3165d7
--- /dev/null
+++ b/src/libcef_dll/cpptoc/shared_memory_region_cpptoc.cc
@@ -0,0 +1,107 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=4356ad718a385149741e4c8bbbe5d5290466ed40$
+//
+
+#include "libcef_dll/cpptoc/shared_memory_region_cpptoc.h"
+#include "libcef_dll/shutdown_checker.h"
+
+namespace {
+
+// MEMBER FUNCTIONS - Body may be edited by hand.
+
+int CEF_CALLBACK
+shared_memory_region_is_valid(struct _cef_shared_memory_region_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefSharedMemoryRegionCppToC::Get(self)->IsValid();
+
+  // Return type: bool
+  return _retval;
+}
+
+size_t CEF_CALLBACK
+shared_memory_region_size(struct _cef_shared_memory_region_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  size_t _retval = CefSharedMemoryRegionCppToC::Get(self)->Size();
+
+  // Return type: simple
+  return _retval;
+}
+
+void* CEF_CALLBACK
+shared_memory_region_memory(struct _cef_shared_memory_region_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+
+  // This manual implementation can be removed once support for 'void*'
+  // is integrated into the CEF translator tool (issue #3591).
+
+  // Execute
+  void* _retval = CefSharedMemoryRegionCppToC::Get(self)->Memory();
+
+  // Return type: simple_byaddr
+  return _retval;
+}
+
+}  // namespace
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefSharedMemoryRegionCppToC::CefSharedMemoryRegionCppToC() {
+  GetStruct()->is_valid = shared_memory_region_is_valid;
+  GetStruct()->size = shared_memory_region_size;
+  GetStruct()->memory = shared_memory_region_memory;
+}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefSharedMemoryRegionCppToC::~CefSharedMemoryRegionCppToC() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+CefRefPtr<CefSharedMemoryRegion> CefCppToCRefCounted<
+    CefSharedMemoryRegionCppToC,
+    CefSharedMemoryRegion,
+    cef_shared_memory_region_t>::UnwrapDerived(CefWrapperType type,
+                                               cef_shared_memory_region_t* s) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCppToCRefCounted<CefSharedMemoryRegionCppToC,
+                                   CefSharedMemoryRegion,
+                                   cef_shared_memory_region_t>::kWrapperType =
+    WT_SHARED_MEMORY_REGION;
diff --git a/src/libcef_dll/cpptoc/shared_memory_region_cpptoc.h b/src/libcef_dll/cpptoc/shared_memory_region_cpptoc.h
new file mode 100644
index 0000000..85fc6d5
--- /dev/null
+++ b/src/libcef_dll/cpptoc/shared_memory_region_cpptoc.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=65f87b7ef4fffcdd5fb70969719b9bb8fa4c8a7b$
+//
+
+#ifndef CEF_LIBCEF_DLL_CPPTOC_SHARED_MEMORY_REGION_CPPTOC_H_
+#define CEF_LIBCEF_DLL_CPPTOC_SHARED_MEMORY_REGION_CPPTOC_H_
+#pragma once
+
+#if !defined(BUILDING_CEF_SHARED)
+#error This file can be included DLL-side only
+#endif
+
+#include "include/capi/cef_shared_memory_region_capi.h"
+#include "include/cef_shared_memory_region.h"
+#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
+
+// Wrap a C++ class with a C structure.
+// This class may be instantiated and accessed DLL-side only.
+class CefSharedMemoryRegionCppToC
+    : public CefCppToCRefCounted<CefSharedMemoryRegionCppToC,
+                                 CefSharedMemoryRegion,
+                                 cef_shared_memory_region_t> {
+ public:
+  CefSharedMemoryRegionCppToC();
+  virtual ~CefSharedMemoryRegionCppToC();
+};
+
+#endif  // CEF_LIBCEF_DLL_CPPTOC_SHARED_MEMORY_REGION_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/shared_process_message_builder_cpptoc.cc b/src/libcef_dll/cpptoc/shared_process_message_builder_cpptoc.cc
new file mode 100644
index 0000000..1c56096
--- /dev/null
+++ b/src/libcef_dll/cpptoc/shared_process_message_builder_cpptoc.cc
@@ -0,0 +1,150 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=820d021d1a2ca4ef4b3fa858f10649676ca46bc8$
+//
+
+#include "libcef_dll/cpptoc/shared_process_message_builder_cpptoc.h"
+#include "libcef_dll/cpptoc/process_message_cpptoc.h"
+#include "libcef_dll/shutdown_checker.h"
+
+// GLOBAL FUNCTIONS - Body may be edited by hand.
+
+CEF_EXPORT cef_shared_process_message_builder_t*
+cef_shared_process_message_builder_create(const cef_string_t* name,
+                                          size_t byte_size) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: name; type: string_byref_const
+  DCHECK(name);
+  if (!name) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefSharedProcessMessageBuilder> _retval =
+      CefSharedProcessMessageBuilder::Create(CefString(name), byte_size);
+
+  // Return type: refptr_same
+  return CefSharedProcessMessageBuilderCppToC::Wrap(_retval);
+}
+
+namespace {
+
+// MEMBER FUNCTIONS - Body may be edited by hand.
+
+int CEF_CALLBACK shared_process_message_builder_is_valid(
+    struct _cef_shared_process_message_builder_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefSharedProcessMessageBuilderCppToC::Get(self)->IsValid();
+
+  // Return type: bool
+  return _retval;
+}
+
+size_t CEF_CALLBACK shared_process_message_builder_size(
+    struct _cef_shared_process_message_builder_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  size_t _retval = CefSharedProcessMessageBuilderCppToC::Get(self)->Size();
+
+  // Return type: simple
+  return _retval;
+}
+
+void* CEF_CALLBACK shared_process_message_builder_memory(
+    struct _cef_shared_process_message_builder_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  void* _retval = CefSharedProcessMessageBuilderCppToC::Get(self)->Memory();
+
+  // Return type: simple
+  return _retval;
+}
+
+cef_process_message_t* CEF_CALLBACK shared_process_message_builder_build(
+    struct _cef_shared_process_message_builder_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefProcessMessage> _retval =
+      CefSharedProcessMessageBuilderCppToC::Get(self)->Build();
+
+  // Return type: refptr_same
+  return CefProcessMessageCppToC::Wrap(_retval);
+}
+
+}  // namespace
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefSharedProcessMessageBuilderCppToC::CefSharedProcessMessageBuilderCppToC() {
+  GetStruct()->is_valid = shared_process_message_builder_is_valid;
+  GetStruct()->size = shared_process_message_builder_size;
+  GetStruct()->memory = shared_process_message_builder_memory;
+  GetStruct()->build = shared_process_message_builder_build;
+}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefSharedProcessMessageBuilderCppToC::~CefSharedProcessMessageBuilderCppToC() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+CefRefPtr<CefSharedProcessMessageBuilder>
+CefCppToCRefCounted<CefSharedProcessMessageBuilderCppToC,
+                    CefSharedProcessMessageBuilder,
+                    cef_shared_process_message_builder_t>::
+    UnwrapDerived(CefWrapperType type,
+                  cef_shared_process_message_builder_t* s) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType
+    CefCppToCRefCounted<CefSharedProcessMessageBuilderCppToC,
+                        CefSharedProcessMessageBuilder,
+                        cef_shared_process_message_builder_t>::kWrapperType =
+        WT_SHARED_PROCESS_MESSAGE_BUILDER;
diff --git a/src/libcef_dll/cpptoc/shared_process_message_builder_cpptoc.h b/src/libcef_dll/cpptoc/shared_process_message_builder_cpptoc.h
new file mode 100644
index 0000000..442e2e1
--- /dev/null
+++ b/src/libcef_dll/cpptoc/shared_process_message_builder_cpptoc.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=da417f77c868bf40de0bff713b6eb935ffb845ea$
+//
+
+#ifndef CEF_LIBCEF_DLL_CPPTOC_SHARED_PROCESS_MESSAGE_BUILDER_CPPTOC_H_
+#define CEF_LIBCEF_DLL_CPPTOC_SHARED_PROCESS_MESSAGE_BUILDER_CPPTOC_H_
+#pragma once
+
+#if !defined(BUILDING_CEF_SHARED)
+#error This file can be included DLL-side only
+#endif
+
+#include "include/capi/cef_shared_process_message_builder_capi.h"
+#include "include/cef_shared_process_message_builder.h"
+#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
+
+// Wrap a C++ class with a C structure.
+// This class may be instantiated and accessed DLL-side only.
+class CefSharedProcessMessageBuilderCppToC
+    : public CefCppToCRefCounted<CefSharedProcessMessageBuilderCppToC,
+                                 CefSharedProcessMessageBuilder,
+                                 cef_shared_process_message_builder_t> {
+ public:
+  CefSharedProcessMessageBuilderCppToC();
+  virtual ~CefSharedProcessMessageBuilderCppToC();
+};
+
+#endif  // CEF_LIBCEF_DLL_CPPTOC_SHARED_PROCESS_MESSAGE_BUILDER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/sslinfo_cpptoc.cc b/src/libcef_dll/cpptoc/sslinfo_cpptoc.cc
index 05cb3a1..265d1f7 100644
--- a/src/libcef_dll/cpptoc/sslinfo_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/sslinfo_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=898e5c53161716e6fb4d14a28ca19ab66c7342b8$
+// $hash=2bad9d84eb0e3bc50b938832cae6af38837e5ba7$
 //
 
 #include "libcef_dll/cpptoc/sslinfo_cpptoc.h"
@@ -27,8 +27,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CERT_STATUS_NONE;
+  }
 
   // Execute
   cef_cert_status_t _retval = CefSSLInfoCppToC::Get(self)->GetCertStatus();
@@ -44,8 +45,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefX509Certificate> _retval =
@@ -75,7 +77,7 @@
 CefCppToCRefCounted<CefSSLInfoCppToC, CefSSLInfo, cef_sslinfo_t>::UnwrapDerived(
     CefWrapperType type,
     cef_sslinfo_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/sslinfo_cpptoc.h b/src/libcef_dll/cpptoc/sslinfo_cpptoc.h
index 286f014..bb95768 100644
--- a/src/libcef_dll/cpptoc/sslinfo_cpptoc.h
+++ b/src/libcef_dll/cpptoc/sslinfo_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d2788a51d643ea4e96de0c6c884ebd48dff448a8$
+// $hash=2eaaaeef70817cde9783efe192d0f57cb73ddfad$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_SSLINFO_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/sslstatus_cpptoc.cc b/src/libcef_dll/cpptoc/sslstatus_cpptoc.cc
index 2145bf2..e6b6bf2 100644
--- a/src/libcef_dll/cpptoc/sslstatus_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/sslstatus_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=cb03f04718426ea7b69d19191eeb0a23e3b62829$
+// $hash=5c03427a3976bd488c9a90ca0456835b6582f59a$
 //
 
 #include "libcef_dll/cpptoc/sslstatus_cpptoc.h"
@@ -26,8 +26,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefSSLStatusCppToC::Get(self)->IsSecureConnection();
@@ -43,8 +44,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CERT_STATUS_NONE;
+  }
 
   // Execute
   cef_cert_status_t _retval = CefSSLStatusCppToC::Get(self)->GetCertStatus();
@@ -60,8 +62,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return SSL_CONNECTION_VERSION_UNKNOWN;
+  }
 
   // Execute
   cef_ssl_version_t _retval = CefSSLStatusCppToC::Get(self)->GetSSLVersion();
@@ -77,8 +80,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return SSL_CONTENT_NORMAL_CONTENT;
+  }
 
   // Execute
   cef_ssl_content_status_t _retval =
@@ -95,8 +99,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefX509Certificate> _retval =
@@ -128,7 +133,7 @@
 CefRefPtr<CefSSLStatus>
 CefCppToCRefCounted<CefSSLStatusCppToC, CefSSLStatus, cef_sslstatus_t>::
     UnwrapDerived(CefWrapperType type, cef_sslstatus_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/sslstatus_cpptoc.h b/src/libcef_dll/cpptoc/sslstatus_cpptoc.h
index dcd611f..4e5379f 100644
--- a/src/libcef_dll/cpptoc/sslstatus_cpptoc.h
+++ b/src/libcef_dll/cpptoc/sslstatus_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1cbc6274827a813be840e38be550b538fe2c2eee$
+// $hash=dba266754e189de39172bddaacf0dfa3fdd79351$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_SSLSTATUS_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/stream_reader_cpptoc.cc b/src/libcef_dll/cpptoc/stream_reader_cpptoc.cc
index b77a3dd..2f9e217 100644
--- a/src/libcef_dll/cpptoc/stream_reader_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/stream_reader_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=02a72f4e6ace34f8ddeec8f2b9055cc304a5dfcd$
+// $hash=2a09370f896a73d7e617fb4f6d856b89db0d5531$
 //
 
 #include "libcef_dll/cpptoc/stream_reader_cpptoc.h"
@@ -26,8 +26,9 @@
 
   // Verify param: fileName; type: string_byref_const
   DCHECK(fileName);
-  if (!fileName)
+  if (!fileName) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefStreamReader> _retval =
@@ -45,8 +46,9 @@
 
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefStreamReader> _retval =
@@ -64,8 +66,9 @@
 
   // Verify param: handler; type: refptr_diff
   DCHECK(handler);
-  if (!handler)
+  if (!handler) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefStreamReader> _retval =
@@ -88,12 +91,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: ptr; type: simple_byaddr
   DCHECK(ptr);
-  if (!ptr)
+  if (!ptr) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefStreamReaderCppToC::Get(self)->Read(ptr, size, n);
@@ -103,15 +108,16 @@
 }
 
 int CEF_CALLBACK stream_reader_seek(struct _cef_stream_reader_t* self,
-                                    int64 offset,
+                                    int64_t offset,
                                     int whence) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefStreamReaderCppToC::Get(self)->Seek(offset, whence);
@@ -120,17 +126,18 @@
   return _retval;
 }
 
-int64 CEF_CALLBACK stream_reader_tell(struct _cef_stream_reader_t* self) {
+int64_t CEF_CALLBACK stream_reader_tell(struct _cef_stream_reader_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
-  int64 _retval = CefStreamReaderCppToC::Get(self)->Tell();
+  int64_t _retval = CefStreamReaderCppToC::Get(self)->Tell();
 
   // Return type: simple
   return _retval;
@@ -142,8 +149,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefStreamReaderCppToC::Get(self)->Eof();
@@ -158,8 +166,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefStreamReaderCppToC::Get(self)->MayBlock();
@@ -192,7 +201,7 @@
     CefStreamReader,
     cef_stream_reader_t>::UnwrapDerived(CefWrapperType type,
                                         cef_stream_reader_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/stream_reader_cpptoc.h b/src/libcef_dll/cpptoc/stream_reader_cpptoc.h
index 43920cf..d4d5dc5 100644
--- a/src/libcef_dll/cpptoc/stream_reader_cpptoc.h
+++ b/src/libcef_dll/cpptoc/stream_reader_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9268eb237a0f114dfeb98d0e9cbd144914f38a9b$
+// $hash=6482aca1d5d2c06d39d226f2d085580abc8eee99$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_STREAM_READER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/stream_writer_cpptoc.cc b/src/libcef_dll/cpptoc/stream_writer_cpptoc.cc
index f436027..9047eb2 100644
--- a/src/libcef_dll/cpptoc/stream_writer_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/stream_writer_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=43e882cb3dde29f9602b3feff5fe868a9f1245a9$
+// $hash=01b28525b4e9c9d1245d7d910f1a45716ade9963$
 //
 
 #include "libcef_dll/cpptoc/stream_writer_cpptoc.h"
@@ -26,8 +26,9 @@
 
   // Verify param: fileName; type: string_byref_const
   DCHECK(fileName);
-  if (!fileName)
+  if (!fileName) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefStreamWriter> _retval =
@@ -45,8 +46,9 @@
 
   // Verify param: handler; type: refptr_diff
   DCHECK(handler);
-  if (!handler)
+  if (!handler) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefStreamWriter> _retval =
@@ -69,12 +71,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: ptr; type: simple_byaddr
   DCHECK(ptr);
-  if (!ptr)
+  if (!ptr) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefStreamWriterCppToC::Get(self)->Write(ptr, size, n);
@@ -84,15 +88,16 @@
 }
 
 int CEF_CALLBACK stream_writer_seek(struct _cef_stream_writer_t* self,
-                                    int64 offset,
+                                    int64_t offset,
                                     int whence) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefStreamWriterCppToC::Get(self)->Seek(offset, whence);
@@ -101,17 +106,18 @@
   return _retval;
 }
 
-int64 CEF_CALLBACK stream_writer_tell(struct _cef_stream_writer_t* self) {
+int64_t CEF_CALLBACK stream_writer_tell(struct _cef_stream_writer_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
-  int64 _retval = CefStreamWriterCppToC::Get(self)->Tell();
+  int64_t _retval = CefStreamWriterCppToC::Get(self)->Tell();
 
   // Return type: simple
   return _retval;
@@ -123,8 +129,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefStreamWriterCppToC::Get(self)->Flush();
@@ -139,8 +146,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefStreamWriterCppToC::Get(self)->MayBlock();
@@ -173,7 +181,7 @@
     CefStreamWriter,
     cef_stream_writer_t>::UnwrapDerived(CefWrapperType type,
                                         cef_stream_writer_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/stream_writer_cpptoc.h b/src/libcef_dll/cpptoc/stream_writer_cpptoc.h
index c7f607d..0a5ed64 100644
--- a/src/libcef_dll/cpptoc/stream_writer_cpptoc.h
+++ b/src/libcef_dll/cpptoc/stream_writer_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1e8cc9fc4bad94fa2d42eb1fef1e5445f59c1033$
+// $hash=7b95fc6bea4023038075ee6712eaceb6c0a153a8$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_STREAM_WRITER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/string_visitor_cpptoc.cc b/src/libcef_dll/cpptoc/string_visitor_cpptoc.cc
index b469696..e1a2541 100644
--- a/src/libcef_dll/cpptoc/string_visitor_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/string_visitor_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=094143a0f6278a87c471719eff0ce99adb7dfca4$
+// $hash=5f35fe588faecf26ddcc03d51c7a2b655cbd773e$
 //
 
 #include "libcef_dll/cpptoc/string_visitor_cpptoc.h"
@@ -26,8 +26,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: string
 
   // Execute
@@ -54,7 +55,7 @@
     CefStringVisitor,
     cef_string_visitor_t>::UnwrapDerived(CefWrapperType type,
                                          cef_string_visitor_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/string_visitor_cpptoc.h b/src/libcef_dll/cpptoc/string_visitor_cpptoc.h
index df8234b..86a2b46 100644
--- a/src/libcef_dll/cpptoc/string_visitor_cpptoc.h
+++ b/src/libcef_dll/cpptoc/string_visitor_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1d097de9a493606b05869d9e2961b1c231ff7e31$
+// $hash=8f717e4df178cef8f90d5af081094a4952fcc90e$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_STRING_VISITOR_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/task_cpptoc.cc b/src/libcef_dll/cpptoc/task_cpptoc.cc
index dcdf58f..eb71797 100644
--- a/src/libcef_dll/cpptoc/task_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/task_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d8c8f08bf2cc720f3eb386cc31a23cff25eb12f1$
+// $hash=118e67ac52da6f21cd4b60a318a04c0ecbce3d55$
 //
 
 #include "libcef_dll/cpptoc/task_cpptoc.h"
@@ -22,8 +22,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTaskCppToC::Get(self)->Execute();
@@ -46,7 +47,7 @@
 CefCppToCRefCounted<CefTaskCppToC, CefTask, cef_task_t>::UnwrapDerived(
     CefWrapperType type,
     cef_task_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/task_cpptoc.h b/src/libcef_dll/cpptoc/task_cpptoc.h
index f1b042d..9a702d9 100644
--- a/src/libcef_dll/cpptoc/task_cpptoc.h
+++ b/src/libcef_dll/cpptoc/task_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=474b1264fa7822a0ab6f8cc8a2a1a0d3b4fa4039$
+// $hash=32859b75e638cd76a9319561b675fa3583818905$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_TASK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/task_runner_cpptoc.cc b/src/libcef_dll/cpptoc/task_runner_cpptoc.cc
index 388d3f8..bbaa198 100644
--- a/src/libcef_dll/cpptoc/task_runner_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/task_runner_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8653934432648c7d636bc39d14a16a536352241c$
+// $hash=646804cf761ea9becc1e0001ae16b1f4d49e3000$
 //
 
 #include "libcef_dll/cpptoc/task_runner_cpptoc.h"
@@ -54,12 +54,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -76,8 +78,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefTaskRunnerCppToC::Get(self)->BelongsToCurrentThread();
@@ -93,8 +96,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefTaskRunnerCppToC::Get(self)->BelongsToThread(threadId);
@@ -110,12 +114,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: task; type: refptr_diff
   DCHECK(task);
-  if (!task)
+  if (!task) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -127,18 +133,20 @@
 
 int CEF_CALLBACK task_runner_post_delayed_task(struct _cef_task_runner_t* self,
                                                cef_task_t* task,
-                                               int64 delay_ms) {
+                                               int64_t delay_ms) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: task; type: refptr_diff
   DCHECK(task);
-  if (!task)
+  if (!task) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefTaskRunnerCppToC::Get(self)->PostDelayedTask(
@@ -171,7 +179,7 @@
 CefRefPtr<CefTaskRunner>
 CefCppToCRefCounted<CefTaskRunnerCppToC, CefTaskRunner, cef_task_runner_t>::
     UnwrapDerived(CefWrapperType type, cef_task_runner_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/task_runner_cpptoc.h b/src/libcef_dll/cpptoc/task_runner_cpptoc.h
index 5bcb05e..d462c7e 100644
--- a/src/libcef_dll/cpptoc/task_runner_cpptoc.h
+++ b/src/libcef_dll/cpptoc/task_runner_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=cca577fe44a13eff1a329d3c2525e02b49742fc8$
+// $hash=66efea72ce623fbf542496f15d0b5fe33d426286$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_TASK_RUNNER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/test/test_server_connection_cpptoc.cc b/src/libcef_dll/cpptoc/test/test_server_connection_cpptoc.cc
new file mode 100644
index 0000000..1fad537
--- /dev/null
+++ b/src/libcef_dll/cpptoc/test/test_server_connection_cpptoc.cc
@@ -0,0 +1,161 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=7467f59c7417d18d7a8ea7690fce9d01b4855d5c$
+//
+
+#include "libcef_dll/cpptoc/test/test_server_connection_cpptoc.h"
+#include "libcef_dll/shutdown_checker.h"
+#include "libcef_dll/transfer_util.h"
+
+namespace {
+
+// MEMBER FUNCTIONS - Body may be edited by hand.
+
+void CEF_CALLBACK test_server_connection_send_http200response(
+    struct _cef_test_server_connection_t* self,
+    const cef_string_t* content_type,
+    const void* data,
+    size_t data_size) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: content_type; type: string_byref_const
+  DCHECK(content_type);
+  if (!content_type) {
+    return;
+  }
+  // Verify param: data; type: simple_byaddr
+  DCHECK(data);
+  if (!data) {
+    return;
+  }
+
+  // Execute
+  CefTestServerConnectionCppToC::Get(self)->SendHttp200Response(
+      CefString(content_type), data, data_size);
+}
+
+void CEF_CALLBACK test_server_connection_send_http404response(
+    struct _cef_test_server_connection_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+
+  // Execute
+  CefTestServerConnectionCppToC::Get(self)->SendHttp404Response();
+}
+
+void CEF_CALLBACK test_server_connection_send_http500response(
+    struct _cef_test_server_connection_t* self,
+    const cef_string_t* error_message) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: error_message; type: string_byref_const
+  DCHECK(error_message);
+  if (!error_message) {
+    return;
+  }
+
+  // Execute
+  CefTestServerConnectionCppToC::Get(self)->SendHttp500Response(
+      CefString(error_message));
+}
+
+void CEF_CALLBACK test_server_connection_send_http_response(
+    struct _cef_test_server_connection_t* self,
+    int response_code,
+    const cef_string_t* content_type,
+    const void* data,
+    size_t data_size,
+    cef_string_multimap_t extra_headers) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: content_type; type: string_byref_const
+  DCHECK(content_type);
+  if (!content_type) {
+    return;
+  }
+  // Verify param: data; type: simple_byaddr
+  DCHECK(data);
+  if (!data) {
+    return;
+  }
+  // Unverified params: extra_headers
+
+  // Translate param: extra_headers; type: string_map_multi_byref_const
+  std::multimap<CefString, CefString> extra_headersMultimap;
+  transfer_string_multimap_contents(extra_headers, extra_headersMultimap);
+
+  // Execute
+  CefTestServerConnectionCppToC::Get(self)->SendHttpResponse(
+      response_code, CefString(content_type), data, data_size,
+      extra_headersMultimap);
+}
+
+}  // namespace
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefTestServerConnectionCppToC::CefTestServerConnectionCppToC() {
+  GetStruct()->send_http200response =
+      test_server_connection_send_http200response;
+  GetStruct()->send_http404response =
+      test_server_connection_send_http404response;
+  GetStruct()->send_http500response =
+      test_server_connection_send_http500response;
+  GetStruct()->send_http_response = test_server_connection_send_http_response;
+}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefTestServerConnectionCppToC::~CefTestServerConnectionCppToC() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+CefRefPtr<CefTestServerConnection> CefCppToCRefCounted<
+    CefTestServerConnectionCppToC,
+    CefTestServerConnection,
+    cef_test_server_connection_t>::UnwrapDerived(CefWrapperType type,
+                                                 cef_test_server_connection_t*
+                                                     s) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCppToCRefCounted<CefTestServerConnectionCppToC,
+                                   CefTestServerConnection,
+                                   cef_test_server_connection_t>::kWrapperType =
+    WT_TEST_SERVER_CONNECTION;
diff --git a/src/libcef_dll/cpptoc/test/test_server_connection_cpptoc.h b/src/libcef_dll/cpptoc/test/test_server_connection_cpptoc.h
new file mode 100644
index 0000000..92baadf
--- /dev/null
+++ b/src/libcef_dll/cpptoc/test/test_server_connection_cpptoc.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=da4666f75e56bfc41483f5d5627e9db612364ffb$
+//
+
+#ifndef CEF_LIBCEF_DLL_CPPTOC_TEST_TEST_SERVER_CONNECTION_CPPTOC_H_
+#define CEF_LIBCEF_DLL_CPPTOC_TEST_TEST_SERVER_CONNECTION_CPPTOC_H_
+#pragma once
+
+#if !defined(BUILDING_CEF_SHARED)
+#error This file can be included DLL-side only
+#endif
+
+#include "include/capi/test/cef_test_server_capi.h"
+#include "include/test/cef_test_server.h"
+#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
+
+// Wrap a C++ class with a C structure.
+// This class may be instantiated and accessed DLL-side only.
+class CefTestServerConnectionCppToC
+    : public CefCppToCRefCounted<CefTestServerConnectionCppToC,
+                                 CefTestServerConnection,
+                                 cef_test_server_connection_t> {
+ public:
+  CefTestServerConnectionCppToC();
+  virtual ~CefTestServerConnectionCppToC();
+};
+
+#endif  // CEF_LIBCEF_DLL_CPPTOC_TEST_TEST_SERVER_CONNECTION_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/test/test_server_cpptoc.cc b/src/libcef_dll/cpptoc/test/test_server_cpptoc.cc
new file mode 100644
index 0000000..f59ab1e
--- /dev/null
+++ b/src/libcef_dll/cpptoc/test/test_server_cpptoc.cc
@@ -0,0 +1,108 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=bd4999e5bbad96be1e3897cfe9dc59bb1c186fba$
+//
+
+#include "libcef_dll/cpptoc/test/test_server_cpptoc.h"
+#include "libcef_dll/ctocpp/test/test_server_handler_ctocpp.h"
+#include "libcef_dll/shutdown_checker.h"
+
+// GLOBAL FUNCTIONS - Body may be edited by hand.
+
+CEF_EXPORT cef_test_server_t* cef_test_server_create_and_start(
+    uint16_t port,
+    int https_server,
+    cef_test_cert_type_t https_cert_type,
+    struct _cef_test_server_handler_t* handler) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: handler; type: refptr_diff
+  DCHECK(handler);
+  if (!handler) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefTestServer> _retval = CefTestServer::CreateAndStart(
+      port, https_server ? true : false, https_cert_type,
+      CefTestServerHandlerCToCpp::Wrap(handler));
+
+  // Return type: refptr_same
+  return CefTestServerCppToC::Wrap(_retval);
+}
+
+namespace {
+
+// MEMBER FUNCTIONS - Body may be edited by hand.
+
+void CEF_CALLBACK test_server_stop(struct _cef_test_server_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+
+  // Execute
+  CefTestServerCppToC::Get(self)->Stop();
+}
+
+cef_string_userfree_t CEF_CALLBACK
+test_server_get_origin(struct _cef_test_server_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+
+  // Execute
+  CefString _retval = CefTestServerCppToC::Get(self)->GetOrigin();
+
+  // Return type: string
+  return _retval.DetachToUserFree();
+}
+
+}  // namespace
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefTestServerCppToC::CefTestServerCppToC() {
+  GetStruct()->stop = test_server_stop;
+  GetStruct()->get_origin = test_server_get_origin;
+}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefTestServerCppToC::~CefTestServerCppToC() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+CefRefPtr<CefTestServer>
+CefCppToCRefCounted<CefTestServerCppToC, CefTestServer, cef_test_server_t>::
+    UnwrapDerived(CefWrapperType type, cef_test_server_t* s) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCppToCRefCounted<CefTestServerCppToC,
+                                   CefTestServer,
+                                   cef_test_server_t>::kWrapperType =
+    WT_TEST_SERVER;
diff --git a/src/libcef_dll/cpptoc/test/test_server_cpptoc.h b/src/libcef_dll/cpptoc/test/test_server_cpptoc.h
new file mode 100644
index 0000000..0c3bed6
--- /dev/null
+++ b/src/libcef_dll/cpptoc/test/test_server_cpptoc.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=f6f3d0a111ecd4f978ed7a1c9493679d027367fd$
+//
+
+#ifndef CEF_LIBCEF_DLL_CPPTOC_TEST_TEST_SERVER_CPPTOC_H_
+#define CEF_LIBCEF_DLL_CPPTOC_TEST_TEST_SERVER_CPPTOC_H_
+#pragma once
+
+#if !defined(BUILDING_CEF_SHARED)
+#error This file can be included DLL-side only
+#endif
+
+#include "include/capi/test/cef_test_server_capi.h"
+#include "include/test/cef_test_server.h"
+#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
+
+// Wrap a C++ class with a C structure.
+// This class may be instantiated and accessed DLL-side only.
+class CefTestServerCppToC : public CefCppToCRefCounted<CefTestServerCppToC,
+                                                       CefTestServer,
+                                                       cef_test_server_t> {
+ public:
+  CefTestServerCppToC();
+  virtual ~CefTestServerCppToC();
+};
+
+#endif  // CEF_LIBCEF_DLL_CPPTOC_TEST_TEST_SERVER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/test/test_server_handler_cpptoc.cc b/src/libcef_dll/cpptoc/test/test_server_handler_cpptoc.cc
new file mode 100644
index 0000000..d2c9d6f
--- /dev/null
+++ b/src/libcef_dll/cpptoc/test/test_server_handler_cpptoc.cc
@@ -0,0 +1,92 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=786c2d8a0269b342c7c3ee49f5bb337341072d31$
+//
+
+#include "libcef_dll/cpptoc/test/test_server_handler_cpptoc.h"
+#include "libcef_dll/ctocpp/request_ctocpp.h"
+#include "libcef_dll/ctocpp/test/test_server_connection_ctocpp.h"
+#include "libcef_dll/ctocpp/test/test_server_ctocpp.h"
+#include "libcef_dll/shutdown_checker.h"
+
+namespace {
+
+// MEMBER FUNCTIONS - Body may be edited by hand.
+
+int CEF_CALLBACK test_server_handler_on_test_server_request(
+    struct _cef_test_server_handler_t* self,
+    cef_test_server_t* server,
+    cef_request_t* request,
+    struct _cef_test_server_connection_t* connection) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: server; type: refptr_diff
+  DCHECK(server);
+  if (!server) {
+    return 0;
+  }
+  // Verify param: request; type: refptr_diff
+  DCHECK(request);
+  if (!request) {
+    return 0;
+  }
+  // Verify param: connection; type: refptr_diff
+  DCHECK(connection);
+  if (!connection) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefTestServerHandlerCppToC::Get(self)->OnTestServerRequest(
+      CefTestServerCToCpp::Wrap(server), CefRequestCToCpp::Wrap(request),
+      CefTestServerConnectionCToCpp::Wrap(connection));
+
+  // Return type: bool
+  return _retval;
+}
+
+}  // namespace
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefTestServerHandlerCppToC::CefTestServerHandlerCppToC() {
+  GetStruct()->on_test_server_request =
+      test_server_handler_on_test_server_request;
+}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefTestServerHandlerCppToC::~CefTestServerHandlerCppToC() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+CefRefPtr<CefTestServerHandler> CefCppToCRefCounted<
+    CefTestServerHandlerCppToC,
+    CefTestServerHandler,
+    cef_test_server_handler_t>::UnwrapDerived(CefWrapperType type,
+                                              cef_test_server_handler_t* s) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCppToCRefCounted<CefTestServerHandlerCppToC,
+                                   CefTestServerHandler,
+                                   cef_test_server_handler_t>::kWrapperType =
+    WT_TEST_SERVER_HANDLER;
diff --git a/src/libcef_dll/cpptoc/test/test_server_handler_cpptoc.h b/src/libcef_dll/cpptoc/test/test_server_handler_cpptoc.h
new file mode 100644
index 0000000..d844b6b
--- /dev/null
+++ b/src/libcef_dll/cpptoc/test/test_server_handler_cpptoc.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=c52f8327259f74779b2bb7e16a84b5c245da482b$
+//
+
+#ifndef CEF_LIBCEF_DLL_CPPTOC_TEST_TEST_SERVER_HANDLER_CPPTOC_H_
+#define CEF_LIBCEF_DLL_CPPTOC_TEST_TEST_SERVER_HANDLER_CPPTOC_H_
+#pragma once
+
+#if !defined(WRAPPING_CEF_SHARED)
+#error This file can be included wrapper-side only
+#endif
+
+#include "include/capi/test/cef_test_server_capi.h"
+#include "include/test/cef_test_server.h"
+#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
+
+// Wrap a C++ class with a C structure.
+// This class may be instantiated and accessed wrapper-side only.
+class CefTestServerHandlerCppToC
+    : public CefCppToCRefCounted<CefTestServerHandlerCppToC,
+                                 CefTestServerHandler,
+                                 cef_test_server_handler_t> {
+ public:
+  CefTestServerHandlerCppToC();
+  virtual ~CefTestServerHandlerCppToC();
+};
+
+#endif  // CEF_LIBCEF_DLL_CPPTOC_TEST_TEST_SERVER_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/test/translator_test_cpptoc.cc b/src/libcef_dll/cpptoc/test/translator_test_cpptoc.cc
index b29eb09..822312f 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/test/translator_test_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ef822c70266564f220ec8911a3b05be5cdc18cb3$
+// $hash=39e09b21c40f62f1ec2f9685f065682607405666$
 //
 
 #include "libcef_dll/cpptoc/test/translator_test_cpptoc.h"
@@ -50,8 +50,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTranslatorTestCppToC::Get(self)->GetVoid();
@@ -63,8 +64,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefTranslatorTestCppToC::Get(self)->GetBool();
@@ -79,8 +81,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefTranslatorTestCppToC::Get(self)->GetInt();
@@ -96,8 +99,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   double _retval = CefTranslatorTestCppToC::Get(self)->GetDouble();
@@ -113,8 +117,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   long _retval = CefTranslatorTestCppToC::Get(self)->GetLong();
@@ -130,8 +135,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefTranslatorTestCppToC::Get(self)->GetSizet();
@@ -146,8 +152,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefTranslatorTestCppToC::Get(self)->SetVoid();
@@ -163,8 +170,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -181,8 +189,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefTranslatorTestCppToC::Get(self)->SetInt(val);
@@ -198,8 +207,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefTranslatorTestCppToC::Get(self)->SetDouble(val);
@@ -215,8 +225,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefTranslatorTestCppToC::Get(self)->SetLong(val);
@@ -232,8 +243,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefTranslatorTestCppToC::Get(self)->SetSizet(val);
@@ -251,12 +263,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: simple_vec_byref_const
   DCHECK(valCount == 0 || val);
-  if (valCount > 0 && !val)
+  if (valCount > 0 && !val) {
     return 0;
+  }
 
   // Translate param: val; type: simple_vec_byref_const
   std::vector<int> valList;
@@ -283,12 +297,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: simple_vec_byref
   DCHECK(valCount && (*valCount == 0 || val));
-  if (!valCount || (*valCount > 0 && !val))
+  if (!valCount || (*valCount > 0 && !val)) {
     return 0;
+  }
 
   // Translate param: val; type: simple_vec_byref
   std::vector<int> valList;
@@ -322,8 +338,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefTranslatorTestCppToC::Get(self)->GetIntListSize();
@@ -339,8 +356,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefTranslatorTestCppToC::Get(self)->GetString();
@@ -356,12 +374,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: string_byref_const
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefTranslatorTestCppToC::Get(self)->SetString(CefString(val));
@@ -378,12 +398,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: val; type: string_byref
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return;
+  }
 
   // Translate param: val; type: string_byref
   CefString valStr(val);
@@ -400,12 +422,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: string_vec_byref_const
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Translate param: val; type: string_vec_byref_const
   std::vector<CefString> valList;
@@ -426,12 +450,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: string_vec_byref
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Translate param: val; type: string_vec_byref
   std::vector<CefString> valList;
@@ -457,12 +483,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: string_map_single_byref_const
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Translate param: val; type: string_map_single_byref_const
   std::map<CefString, CefString> valMap;
@@ -483,12 +511,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: string_map_single_byref
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Translate param: val; type: string_map_single_byref
   std::map<CefString, CefString> valMap;
@@ -513,12 +543,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: string_map_multi_byref_const
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Translate param: val; type: string_map_multi_byref_const
   std::multimap<CefString, CefString> valMultimap;
@@ -540,12 +572,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: string_map_multi_byref
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Translate param: val; type: string_map_multi_byref
   std::multimap<CefString, CefString> valMultimap;
@@ -570,8 +604,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefPoint();
+  }
 
   // Execute
   cef_point_t _retval = CefTranslatorTestCppToC::Get(self)->GetPoint();
@@ -587,12 +622,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: simple_byref_const
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Translate param: val; type: simple_byref_const
   CefPoint valVal = val ? *val : CefPoint();
@@ -612,12 +649,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: val; type: simple_byref
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return;
+  }
 
   // Translate param: val; type: simple_byref
   CefPoint valVal = val ? *val : CefPoint();
@@ -626,8 +665,9 @@
   CefTranslatorTestCppToC::Get(self)->GetPointByRef(valVal);
 
   // Restore param: val; type: simple_byref
-  if (val)
+  if (val) {
     *val = valVal;
+  }
 }
 
 int CEF_CALLBACK
@@ -639,12 +679,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: simple_vec_byref_const
   DCHECK(valCount == 0 || val);
-  if (valCount > 0 && !val)
+  if (valCount > 0 && !val) {
     return 0;
+  }
 
   // Translate param: val; type: simple_vec_byref_const
   std::vector<CefPoint> valList;
@@ -671,12 +713,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: simple_vec_byref
   DCHECK(valCount && (*valCount == 0 || val));
-  if (!valCount || (*valCount > 0 && !val))
+  if (!valCount || (*valCount > 0 && !val)) {
     return 0;
+  }
 
   // Translate param: val; type: simple_vec_byref
   std::vector<CefPoint> valList;
@@ -710,8 +754,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefTranslatorTestCppToC::Get(self)->GetPointListSize();
@@ -728,8 +773,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTranslatorTestRefPtrLibrary> _retval =
@@ -747,12 +793,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: refptr_same
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Execute
   int _retval = CefTranslatorTestCppToC::Get(self)->SetRefPtrLibrary(
@@ -771,12 +819,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: val; type: refptr_same
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTranslatorTestRefPtrLibrary> _retval =
@@ -795,12 +845,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: refptr_same
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Execute
   int _retval = CefTranslatorTestCppToC::Get(self)->SetChildRefPtrLibrary(
@@ -819,12 +871,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: val; type: refptr_same
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTranslatorTestRefPtrLibrary> _retval =
@@ -846,12 +900,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: refptr_vec_same_byref_const
   DCHECK(valCount == 0 || val);
-  if (valCount > 0 && !val)
+  if (valCount > 0 && !val) {
     return 0;
+  }
 
   // Translate param: val; type: refptr_vec_same_byref_const
   std::vector<CefRefPtr<CefTranslatorTestRefPtrLibrary>> valList;
@@ -882,12 +938,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: refptr_vec_same_byref
   DCHECK(valCount && (*valCount == 0 || val));
-  if (!valCount || (*valCount > 0 && !val))
+  if (!valCount || (*valCount > 0 && !val)) {
     return 0;
+  }
 
   // Translate param: val; type: refptr_vec_same_byref
   std::vector<CefRefPtr<CefTranslatorTestRefPtrLibrary>> valList;
@@ -922,8 +980,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval =
@@ -941,12 +1000,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: refptr_diff
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Execute
   int _retval = CefTranslatorTestCppToC::Get(self)->SetRefPtrClient(
@@ -965,12 +1026,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: val; type: refptr_diff
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTranslatorTestRefPtrClient> _retval =
@@ -989,12 +1052,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: refptr_diff
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Execute
   int _retval = CefTranslatorTestCppToC::Get(self)->SetChildRefPtrClient(
@@ -1013,12 +1078,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: val; type: refptr_diff
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTranslatorTestRefPtrClient> _retval =
@@ -1040,12 +1107,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: refptr_vec_diff_byref_const
   DCHECK(valCount == 0 || val);
-  if (valCount > 0 && !val)
+  if (valCount > 0 && !val) {
     return 0;
+  }
 
   // Translate param: val; type: refptr_vec_diff_byref_const
   std::vector<CefRefPtr<CefTranslatorTestRefPtrClient>> valList;
@@ -1076,20 +1145,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: refptr_vec_diff_byref
   DCHECK(valCount && (*valCount == 0 || val));
-  if (!valCount || (*valCount > 0 && !val))
+  if (!valCount || (*valCount > 0 && !val)) {
     return 0;
+  }
   // Verify param: val1; type: refptr_diff
   DCHECK(val1);
-  if (!val1)
+  if (!val1) {
     return 0;
+  }
   // Verify param: val2; type: refptr_diff
   DCHECK(val2);
-  if (!val2)
+  if (!val2) {
     return 0;
+  }
 
   // Translate param: val; type: refptr_vec_diff_byref
   std::vector<CefRefPtr<CefTranslatorTestRefPtrClient>> valList;
@@ -1125,8 +1198,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval =
@@ -1144,15 +1218,16 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefOwnPtr<CefTranslatorTestScopedLibrary> _retval =
       CefTranslatorTestCppToC::Get(self)->GetOwnPtrLibrary(val);
 
   // Return type: ownptr_same
-  return CefTranslatorTestScopedLibraryCppToC::WrapOwn(OWN_PASS(_retval));
+  return CefTranslatorTestScopedLibraryCppToC::WrapOwn(std::move(_retval));
 }
 
 int CEF_CALLBACK translator_test_set_own_ptr_library(
@@ -1163,12 +1238,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: ownptr_same
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Execute
   int _retval = CefTranslatorTestCppToC::Get(self)->SetOwnPtrLibrary(
@@ -1187,12 +1264,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: val; type: ownptr_same
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return NULL;
+  }
 
   // Execute
   CefOwnPtr<CefTranslatorTestScopedLibrary> _retval =
@@ -1200,7 +1279,7 @@
           CefTranslatorTestScopedLibraryCppToC::UnwrapOwn(val));
 
   // Return type: ownptr_same
-  return CefTranslatorTestScopedLibraryCppToC::WrapOwn(OWN_PASS(_retval));
+  return CefTranslatorTestScopedLibraryCppToC::WrapOwn(std::move(_retval));
 }
 
 int CEF_CALLBACK translator_test_set_child_own_ptr_library(
@@ -1211,12 +1290,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: ownptr_same
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Execute
   int _retval = CefTranslatorTestCppToC::Get(self)->SetChildOwnPtrLibrary(
@@ -1235,12 +1316,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: val; type: ownptr_same
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return NULL;
+  }
 
   // Execute
   CefOwnPtr<CefTranslatorTestScopedLibrary> _retval =
@@ -1248,7 +1331,7 @@
           CefTranslatorTestScopedLibraryChildCppToC::UnwrapOwn(val));
 
   // Return type: ownptr_same
-  return CefTranslatorTestScopedLibraryCppToC::WrapOwn(OWN_PASS(_retval));
+  return CefTranslatorTestScopedLibraryCppToC::WrapOwn(std::move(_retval));
 }
 
 int CEF_CALLBACK translator_test_set_own_ptr_client(
@@ -1259,12 +1342,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: ownptr_diff
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Translate param: val; type: ownptr_diff
   CefOwnPtr<CefTranslatorTestScopedClient> valPtr(
@@ -1272,7 +1357,7 @@
 
   // Execute
   int _retval =
-      CefTranslatorTestCppToC::Get(self)->SetOwnPtrClient(OWN_PASS(valPtr));
+      CefTranslatorTestCppToC::Get(self)->SetOwnPtrClient(std::move(valPtr));
 
   // Return type: simple
   return _retval;
@@ -1287,12 +1372,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: val; type: ownptr_diff
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return NULL;
+  }
 
   // Translate param: val; type: ownptr_diff
   CefOwnPtr<CefTranslatorTestScopedClient> valPtr(
@@ -1301,10 +1388,10 @@
   // Execute
   CefOwnPtr<CefTranslatorTestScopedClient> _retval =
       CefTranslatorTestCppToC::Get(self)->SetOwnPtrClientAndReturn(
-          OWN_PASS(valPtr));
+          std::move(valPtr));
 
   // Return type: ownptr_diff
-  return CefTranslatorTestScopedClientCToCpp::UnwrapOwn(OWN_PASS(_retval));
+  return CefTranslatorTestScopedClientCToCpp::UnwrapOwn(std::move(_retval));
 }
 
 int CEF_CALLBACK translator_test_set_child_own_ptr_client(
@@ -1315,12 +1402,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: ownptr_diff
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Translate param: val; type: ownptr_diff
   CefOwnPtr<CefTranslatorTestScopedClientChild> valPtr(
@@ -1328,7 +1417,7 @@
 
   // Execute
   int _retval = CefTranslatorTestCppToC::Get(self)->SetChildOwnPtrClient(
-      OWN_PASS(valPtr));
+      std::move(valPtr));
 
   // Return type: simple
   return _retval;
@@ -1343,12 +1432,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: val; type: ownptr_diff
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return NULL;
+  }
 
   // Translate param: val; type: ownptr_diff
   CefOwnPtr<CefTranslatorTestScopedClientChild> valPtr(
@@ -1357,10 +1448,10 @@
   // Execute
   CefOwnPtr<CefTranslatorTestScopedClient> _retval =
       CefTranslatorTestCppToC::Get(self)->SetChildOwnPtrClientAndReturnParent(
-          OWN_PASS(valPtr));
+          std::move(valPtr));
 
   // Return type: ownptr_diff
-  return CefTranslatorTestScopedClientCToCpp::UnwrapOwn(OWN_PASS(_retval));
+  return CefTranslatorTestScopedClientCToCpp::UnwrapOwn(std::move(_retval));
 }
 
 int CEF_CALLBACK translator_test_set_raw_ptr_library(
@@ -1371,12 +1462,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: rawptr_same
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Execute
   int _retval = CefTranslatorTestCppToC::Get(self)->SetRawPtrLibrary(
@@ -1394,12 +1487,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: rawptr_same
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Execute
   int _retval = CefTranslatorTestCppToC::Get(self)->SetChildRawPtrLibrary(
@@ -1420,12 +1515,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: rawptr_vec_same_byref_const
   DCHECK(valCount == 0 || val);
-  if (valCount > 0 && !val)
+  if (valCount > 0 && !val) {
     return 0;
+  }
 
   // Translate param: val; type: rawptr_vec_same_byref_const
   std::vector<CefRawPtr<CefTranslatorTestScopedLibrary>> valList;
@@ -1453,12 +1550,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: rawptr_diff
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Translate param: val; type: rawptr_diff
   CefOwnPtr<CefTranslatorTestScopedClient> valPtr(
@@ -1480,12 +1579,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: rawptr_diff
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Translate param: val; type: rawptr_diff
   CefOwnPtr<CefTranslatorTestScopedClientChild> valPtr(
@@ -1510,12 +1611,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: val; type: rawptr_vec_diff_byref_const
   DCHECK(valCount == 0 || val);
-  if (valCount > 0 && !val)
+  if (valCount > 0 && !val) {
     return 0;
+  }
 
   // Translate param: val; type: rawptr_vec_diff_byref_const
   std::vector<CefRawPtr<CefTranslatorTestScopedClient>> valList;
@@ -1644,7 +1747,7 @@
     CefTranslatorTest,
     cef_translator_test_t>::UnwrapDerived(CefWrapperType type,
                                           cef_translator_test_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/test/translator_test_cpptoc.h b/src/libcef_dll/cpptoc/test/translator_test_cpptoc.h
index 71cd0ea..c84b470 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_cpptoc.h
+++ b/src/libcef_dll/cpptoc/test/translator_test_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=553eca04097ec4d280e35f92cea280bf0a05b3f7$
+// $hash=5f0f8e9729af10fb258c197facf57ae150969f1a$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_TEST_TRANSLATOR_TEST_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_client_child_cpptoc.cc b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_client_child_cpptoc.cc
index 00a5a27..70f7835 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_client_child_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_client_child_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=bfd3c7ee0176b3e62e5c196e415a2bd62409e9b8$
+// $hash=e94e27d12aa7fa48ea890cb8ab99f2e400d7ff23$
 //
 
 #include "libcef_dll/cpptoc/test/translator_test_ref_ptr_client_child_cpptoc.h"
@@ -26,8 +26,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -44,8 +45,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -82,7 +84,7 @@
                     cef_translator_test_ref_ptr_client_child_t>::
     UnwrapDerived(CefWrapperType type,
                   cef_translator_test_ref_ptr_client_child_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_client_child_cpptoc.h b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_client_child_cpptoc.h
index c891da7..71d3384 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_client_child_cpptoc.h
+++ b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_client_child_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9003c2082a7c6a97b494e2e077d3d631a5a323ec$
+// $hash=b6731cceb5f02011f2bafe6afa336b95355a1bf0$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_TEST_TRANSLATOR_TEST_REF_PTR_CLIENT_CHILD_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_client_cpptoc.cc b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_client_cpptoc.cc
index 884be99..d502501 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_client_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_client_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=83b45b70a01ab7ae99b015e0017446f623e484b6$
+// $hash=5c0280db7af6bc6332f308b53a3189d1e64b63d0$
 //
 
 #include "libcef_dll/cpptoc/test/translator_test_ref_ptr_client_cpptoc.h"
@@ -27,8 +27,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefTranslatorTestRefPtrClientCppToC::Get(self)->GetValue();
@@ -62,7 +63,7 @@
     return CefTranslatorTestRefPtrClientChildCppToC::Unwrap(
         reinterpret_cast<cef_translator_test_ref_ptr_client_child_t*>(s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_client_cpptoc.h b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_client_cpptoc.h
index a195262..e8a5309 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_client_cpptoc.h
+++ b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_client_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=99c3402ebfd13194ae9f4be79db0e157fceebebc$
+// $hash=871a3626f0e6928f2b1094b6fd01175f2bc82a29$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_TEST_TRANSLATOR_TEST_REF_PTR_CLIENT_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_child_cpptoc.cc b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_child_cpptoc.cc
index 4069921..6e77ab5 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_child_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_child_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=33192fd0739040880706fdd31b99e4bc9a191c22$
+// $hash=09d1f7c2030dd94ea04b11428eaa2820365c39b0$
 //
 
 #include "libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_child_cpptoc.h"
@@ -46,8 +46,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefTranslatorTestRefPtrLibraryChildChildCppToC::Get(self)
@@ -66,8 +67,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTranslatorTestRefPtrLibraryChildChildCppToC::Get(self)->SetOtherOtherValue(
@@ -81,8 +83,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -103,8 +106,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTranslatorTestRefPtrLibraryChildChildCppToC::Get(
@@ -120,8 +124,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -142,8 +147,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTranslatorTestRefPtrLibraryChildChildCppToC::Get(
@@ -186,7 +192,7 @@
                     cef_translator_test_ref_ptr_library_child_child_t>::
     UnwrapDerived(CefWrapperType type,
                   cef_translator_test_ref_ptr_library_child_child_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_child_cpptoc.h b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_child_cpptoc.h
index 50b37bb..c17f718 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_child_cpptoc.h
+++ b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_child_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=50d8ca28ea29e5d2aa0a0eac08b3dc3582f7ff82$
+// $hash=c578229af8491c038b4a036ca870c5dd268b9244$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_TEST_TRANSLATOR_TEST_REF_PTR_LIBRARY_CHILD_CHILD_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_cpptoc.cc b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_cpptoc.cc
index 045926e..3619115 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=82b0faf6b4c952550427001b82efaa6565a417e5$
+// $hash=77ac3c6f92cae7e91d7c1961c302fcf4da441cb7$
 //
 
 #include "libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_cpptoc.h"
@@ -43,8 +43,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -62,8 +63,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTranslatorTestRefPtrLibraryChildCppToC::Get(self)->SetOtherValue(value);
@@ -76,8 +78,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -97,8 +100,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTranslatorTestRefPtrLibraryChildCppToC::Get(
@@ -139,7 +143,7 @@
         reinterpret_cast<cef_translator_test_ref_ptr_library_child_child_t*>(
             s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_cpptoc.h b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_cpptoc.h
index 74acb4a..0ed5238 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_cpptoc.h
+++ b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_child_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f001fb9941662962bd6c9ab33ad9003ad0ee9426$
+// $hash=f138313a94a2c2943926df60ee5293f5dc9f62b8$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_TEST_TRANSLATOR_TEST_REF_PTR_LIBRARY_CHILD_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_cpptoc.cc b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_cpptoc.cc
index aad36d8..093ce48 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1a3544234150172b70642cde285bfb7cba255a28$
+// $hash=a7585041fd58edc7c8a2760cf360cc3abcf90853$
 //
 
 #include "libcef_dll/cpptoc/test/translator_test_ref_ptr_library_cpptoc.h"
@@ -44,8 +44,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefTranslatorTestRefPtrLibraryCppToC::Get(self)->GetValue();
@@ -62,8 +63,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTranslatorTestRefPtrLibraryCppToC::Get(self)->SetValue(value);
@@ -100,7 +102,7 @@
         reinterpret_cast<cef_translator_test_ref_ptr_library_child_child_t*>(
             s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_cpptoc.h b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_cpptoc.h
index d01f510..e1420e8 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_cpptoc.h
+++ b/src/libcef_dll/cpptoc/test/translator_test_ref_ptr_library_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c99baff2907c8d42a842732da7364c3750409690$
+// $hash=f431a7518ff642f5b307dbd716bfcd75c5bcb37a$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_TEST_TRANSLATOR_TEST_REF_PTR_LIBRARY_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/test/translator_test_scoped_client_child_cpptoc.cc b/src/libcef_dll/cpptoc/test/translator_test_scoped_client_child_cpptoc.cc
index fff8153..cf8058b 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_scoped_client_child_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/test/translator_test_scoped_client_child_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ac547adab31b6d47cfe874aded1f5d26a749b524$
+// $hash=caeeb7277830a5e9a81ba96a9385f65f53e1983f$
 //
 
 #include "libcef_dll/cpptoc/test/translator_test_scoped_client_child_cpptoc.h"
@@ -23,8 +23,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -39,8 +40,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -75,7 +77,7 @@
                 cef_translator_test_scoped_client_child_t>::
     UnwrapDerivedOwn(CefWrapperType type,
                      cef_translator_test_scoped_client_child_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return CefOwnPtr<CefTranslatorTestScopedClientChild>();
 }
 
@@ -86,7 +88,7 @@
                 cef_translator_test_scoped_client_child_t>::
     UnwrapDerivedRaw(CefWrapperType type,
                      cef_translator_test_scoped_client_child_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/test/translator_test_scoped_client_child_cpptoc.h b/src/libcef_dll/cpptoc/test/translator_test_scoped_client_child_cpptoc.h
index 67783f5..894345c 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_scoped_client_child_cpptoc.h
+++ b/src/libcef_dll/cpptoc/test/translator_test_scoped_client_child_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=93db4735756895c8b3bfcb15fab1186bc2494a99$
+// $hash=7a7900759a192fa0586d1ab7e2706c513ed9b715$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_TEST_TRANSLATOR_TEST_SCOPED_CLIENT_CHILD_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/test/translator_test_scoped_client_cpptoc.cc b/src/libcef_dll/cpptoc/test/translator_test_scoped_client_cpptoc.cc
index 469fa3a..38a3f9f 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_scoped_client_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/test/translator_test_scoped_client_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=5058f826ad475b0930ddd77fd4029e050c27fca2$
+// $hash=8b65a39b9871e8185e8923ef48a54dd38e42af95$
 //
 
 #include "libcef_dll/cpptoc/test/translator_test_scoped_client_cpptoc.h"
@@ -24,8 +24,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefTranslatorTestScopedClientCppToC::Get(self)->GetValue();
@@ -54,12 +55,10 @@
     UnwrapDerivedOwn(CefWrapperType type,
                      cef_translator_test_scoped_client_t* s) {
   if (type == WT_TRANSLATOR_TEST_SCOPED_CLIENT_CHILD) {
-    return OWN_RETURN_AS(
-        CefTranslatorTestScopedClientChildCppToC::UnwrapOwn(
-            reinterpret_cast<cef_translator_test_scoped_client_child_t*>(s)),
-        CefTranslatorTestScopedClient);
+    return CefTranslatorTestScopedClientChildCppToC::UnwrapOwn(
+        reinterpret_cast<cef_translator_test_scoped_client_child_t*>(s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return CefOwnPtr<CefTranslatorTestScopedClient>();
 }
 
@@ -74,7 +73,7 @@
     return CefTranslatorTestScopedClientChildCppToC::UnwrapRaw(
         reinterpret_cast<cef_translator_test_scoped_client_child_t*>(s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/test/translator_test_scoped_client_cpptoc.h b/src/libcef_dll/cpptoc/test/translator_test_scoped_client_cpptoc.h
index 547ba7e..d73036b 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_scoped_client_cpptoc.h
+++ b/src/libcef_dll/cpptoc/test/translator_test_scoped_client_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1e85ddaeea70900cf89e907d8b247917c69ce693$
+// $hash=bf705a17d41da4d434c122928b0f55c8760d3689$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_TEST_TRANSLATOR_TEST_SCOPED_CLIENT_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/test/translator_test_scoped_library_child_child_cpptoc.cc b/src/libcef_dll/cpptoc/test/translator_test_scoped_library_child_child_cpptoc.cc
index 4f29c88..b8ef700 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_scoped_library_child_child_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/test/translator_test_scoped_library_child_child_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c833c2d3e1fe4bcae98906f85e6f5751c17c267a$
+// $hash=4208fa6b25929be4a48ba1beefc454a08fc22759$
 //
 
 #include "libcef_dll/cpptoc/test/translator_test_scoped_library_child_child_cpptoc.h"
@@ -29,7 +29,7 @@
 
   // Return type: ownptr_same
   return CefTranslatorTestScopedLibraryChildChildCppToC::WrapOwn(
-      OWN_PASS(_retval));
+      std::move(_retval));
 }
 
 namespace {
@@ -42,8 +42,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefTranslatorTestScopedLibraryChildChildCppToC::Get(self)
@@ -60,8 +61,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTranslatorTestScopedLibraryChildChildCppToC::Get(self)->SetOtherOtherValue(
@@ -73,8 +75,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -93,8 +96,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTranslatorTestScopedLibraryChildChildCppToC::Get(
@@ -107,8 +111,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -127,8 +132,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTranslatorTestScopedLibraryChildChildCppToC::Get(
@@ -168,7 +174,7 @@
                 cef_translator_test_scoped_library_child_child_t>::
     UnwrapDerivedOwn(CefWrapperType type,
                      cef_translator_test_scoped_library_child_child_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return CefOwnPtr<CefTranslatorTestScopedLibraryChildChild>();
 }
 
@@ -179,7 +185,7 @@
                 cef_translator_test_scoped_library_child_child_t>::
     UnwrapDerivedRaw(CefWrapperType type,
                      cef_translator_test_scoped_library_child_child_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/test/translator_test_scoped_library_child_child_cpptoc.h b/src/libcef_dll/cpptoc/test/translator_test_scoped_library_child_child_cpptoc.h
index aa55900..3602a4b 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_scoped_library_child_child_cpptoc.h
+++ b/src/libcef_dll/cpptoc/test/translator_test_scoped_library_child_child_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=dbfcd01f7e1c8da03770348614b25330f43915eb$
+// $hash=333a572bf8bb3cde5058ae36410b571d777cd157$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_TEST_TRANSLATOR_TEST_SCOPED_LIBRARY_CHILD_CHILD_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/test/translator_test_scoped_library_child_cpptoc.cc b/src/libcef_dll/cpptoc/test/translator_test_scoped_library_child_cpptoc.cc
index c139dba..607e1b9 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_scoped_library_child_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/test/translator_test_scoped_library_child_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=71958dc400edbcd7bbdb409c7293c0b23b2a7e59$
+// $hash=f6f6e03a419a412c7c4f15c252fef53c543c5397$
 //
 
 #include "libcef_dll/cpptoc/test/translator_test_scoped_library_child_cpptoc.h"
@@ -26,7 +26,7 @@
       CefTranslatorTestScopedLibraryChild::Create(value, other_value);
 
   // Return type: ownptr_same
-  return CefTranslatorTestScopedLibraryChildCppToC::WrapOwn(OWN_PASS(_retval));
+  return CefTranslatorTestScopedLibraryChildCppToC::WrapOwn(std::move(_retval));
 }
 
 namespace {
@@ -38,8 +38,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -55,8 +56,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTranslatorTestScopedLibraryChildCppToC::Get(self)->SetOtherValue(value);
@@ -67,8 +69,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -86,8 +89,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTranslatorTestScopedLibraryChildCppToC::Get(
@@ -122,13 +126,10 @@
     UnwrapDerivedOwn(CefWrapperType type,
                      cef_translator_test_scoped_library_child_t* s) {
   if (type == WT_TRANSLATOR_TEST_SCOPED_LIBRARY_CHILD_CHILD) {
-    return OWN_RETURN_AS(
-        CefTranslatorTestScopedLibraryChildChildCppToC::UnwrapOwn(
-            reinterpret_cast<cef_translator_test_scoped_library_child_child_t*>(
-                s)),
-        CefTranslatorTestScopedLibraryChild);
+    return CefTranslatorTestScopedLibraryChildChildCppToC::UnwrapOwn(
+        reinterpret_cast<cef_translator_test_scoped_library_child_child_t*>(s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return CefOwnPtr<CefTranslatorTestScopedLibraryChild>();
 }
 
@@ -143,7 +144,7 @@
     return CefTranslatorTestScopedLibraryChildChildCppToC::UnwrapRaw(
         reinterpret_cast<cef_translator_test_scoped_library_child_child_t*>(s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/test/translator_test_scoped_library_child_cpptoc.h b/src/libcef_dll/cpptoc/test/translator_test_scoped_library_child_cpptoc.h
index c04b32f..e1c516a 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_scoped_library_child_cpptoc.h
+++ b/src/libcef_dll/cpptoc/test/translator_test_scoped_library_child_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0bf426bddd50da6814967740ea3af864c9f10f8d$
+// $hash=df48c52988d69bfd94bc4245d1c2069f45512f7a$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_TEST_TRANSLATOR_TEST_SCOPED_LIBRARY_CHILD_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/test/translator_test_scoped_library_cpptoc.cc b/src/libcef_dll/cpptoc/test/translator_test_scoped_library_cpptoc.cc
index 3e64e82..4a5c6c9 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_scoped_library_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/test/translator_test_scoped_library_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=aaf55c2bc6deb407e8c2822726250c3a8dd06a37$
+// $hash=6bcea51c7388efe763a5e5e1afe9db461bff777d$
 //
 
 #include "libcef_dll/cpptoc/test/translator_test_scoped_library_cpptoc.h"
@@ -27,7 +27,7 @@
       CefTranslatorTestScopedLibrary::Create(value);
 
   // Return type: ownptr_same
-  return CefTranslatorTestScopedLibraryCppToC::WrapOwn(OWN_PASS(_retval));
+  return CefTranslatorTestScopedLibraryCppToC::WrapOwn(std::move(_retval));
 }
 
 namespace {
@@ -39,8 +39,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefTranslatorTestScopedLibraryCppToC::Get(self)->GetValue();
@@ -55,8 +56,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTranslatorTestScopedLibraryCppToC::Get(self)->SetValue(value);
@@ -83,19 +85,14 @@
     UnwrapDerivedOwn(CefWrapperType type,
                      cef_translator_test_scoped_library_t* s) {
   if (type == WT_TRANSLATOR_TEST_SCOPED_LIBRARY_CHILD) {
-    return OWN_RETURN_AS(
-        CefTranslatorTestScopedLibraryChildCppToC::UnwrapOwn(
-            reinterpret_cast<cef_translator_test_scoped_library_child_t*>(s)),
-        CefTranslatorTestScopedLibrary);
+    return CefTranslatorTestScopedLibraryChildCppToC::UnwrapOwn(
+        reinterpret_cast<cef_translator_test_scoped_library_child_t*>(s));
   }
   if (type == WT_TRANSLATOR_TEST_SCOPED_LIBRARY_CHILD_CHILD) {
-    return OWN_RETURN_AS(
-        CefTranslatorTestScopedLibraryChildChildCppToC::UnwrapOwn(
-            reinterpret_cast<cef_translator_test_scoped_library_child_child_t*>(
-                s)),
-        CefTranslatorTestScopedLibrary);
+    return CefTranslatorTestScopedLibraryChildChildCppToC::UnwrapOwn(
+        reinterpret_cast<cef_translator_test_scoped_library_child_child_t*>(s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return CefOwnPtr<CefTranslatorTestScopedLibrary>();
 }
 
@@ -114,7 +111,7 @@
     return CefTranslatorTestScopedLibraryChildChildCppToC::UnwrapRaw(
         reinterpret_cast<cef_translator_test_scoped_library_child_child_t*>(s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/test/translator_test_scoped_library_cpptoc.h b/src/libcef_dll/cpptoc/test/translator_test_scoped_library_cpptoc.h
index 5aed9dd..f038406 100644
--- a/src/libcef_dll/cpptoc/test/translator_test_scoped_library_cpptoc.h
+++ b/src/libcef_dll/cpptoc/test/translator_test_scoped_library_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=167132fbef27711ddc4e15003e6ec9af08cb4e9c$
+// $hash=029af2aa3f312b751ca30b039f22e5c4fbd42295$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_TEST_TRANSLATOR_TEST_SCOPED_LIBRARY_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/thread_cpptoc.cc b/src/libcef_dll/cpptoc/thread_cpptoc.cc
index 749b573..1906114 100644
--- a/src/libcef_dll/cpptoc/thread_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/thread_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f417535f2fb1f11f13efb5b5dfedf87f1062b70e$
+// $hash=f7d9700dd9445bf363712c5ccafdcbcb438d7917$
 //
 
 #include "libcef_dll/cpptoc/thread_cpptoc.h"
@@ -50,8 +50,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTaskRunner> _retval =
@@ -68,8 +69,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return kInvalidPlatformThreadId;
+  }
 
   // Execute
   cef_platform_thread_id_t _retval =
@@ -85,8 +87,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefThreadCppToC::Get(self)->Stop();
@@ -98,8 +101,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefThreadCppToC::Get(self)->IsRunning();
@@ -130,7 +134,7 @@
 CefCppToCRefCounted<CefThreadCppToC, CefThread, cef_thread_t>::UnwrapDerived(
     CefWrapperType type,
     cef_thread_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/thread_cpptoc.h b/src/libcef_dll/cpptoc/thread_cpptoc.h
index 2a644d3..37f0be3 100644
--- a/src/libcef_dll/cpptoc/thread_cpptoc.h
+++ b/src/libcef_dll/cpptoc/thread_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8a39bcb93a93bb8b7c8e8794847e82b3a4c13053$
+// $hash=684bc72317e634d7357bdea53bf7dfe81d9d536b$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_THREAD_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/urlrequest_client_cpptoc.cc b/src/libcef_dll/cpptoc/urlrequest_client_cpptoc.cc
index 12954be..119b58e 100644
--- a/src/libcef_dll/cpptoc/urlrequest_client_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/urlrequest_client_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ba49a4bef9c1ae2b5380fe7ef72313d0434e08a1$
+// $hash=a06a115eda2d02beb98b73713fd60119a21eb67c$
 //
 
 #include "libcef_dll/cpptoc/urlrequest_client_cpptoc.h"
@@ -29,12 +29,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return;
+  }
 
   // Execute
   CefURLRequestClientCppToC::Get(self)->OnRequestComplete(
@@ -44,19 +46,21 @@
 void CEF_CALLBACK
 urlrequest_client_on_upload_progress(struct _cef_urlrequest_client_t* self,
                                      cef_urlrequest_t* request,
-                                     int64 current,
-                                     int64 total) {
+                                     int64_t current,
+                                     int64_t total) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return;
+  }
 
   // Execute
   CefURLRequestClientCppToC::Get(self)->OnUploadProgress(
@@ -66,19 +70,21 @@
 void CEF_CALLBACK
 urlrequest_client_on_download_progress(struct _cef_urlrequest_client_t* self,
                                        cef_urlrequest_t* request,
-                                       int64 current,
-                                       int64 total) {
+                                       int64_t current,
+                                       int64_t total) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return;
+  }
 
   // Execute
   CefURLRequestClientCppToC::Get(self)->OnDownloadProgress(
@@ -95,16 +101,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return;
+  }
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return;
+  }
 
   // Execute
   CefURLRequestClientCppToC::Get(self)->OnDownloadData(
@@ -124,20 +133,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: host; type: string_byref_const
   DCHECK(host);
-  if (!host)
+  if (!host) {
     return 0;
+  }
   // Verify param: scheme; type: string_byref_const
   DCHECK(scheme);
-  if (!scheme)
+  if (!scheme) {
     return 0;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback);
-  if (!callback)
+  if (!callback) {
     return 0;
+  }
   // Unverified params: realm
 
   // Execute
@@ -173,7 +186,7 @@
     CefURLRequestClient,
     cef_urlrequest_client_t>::UnwrapDerived(CefWrapperType type,
                                             cef_urlrequest_client_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/urlrequest_client_cpptoc.h b/src/libcef_dll/cpptoc/urlrequest_client_cpptoc.h
index 02c93de..551f69c 100644
--- a/src/libcef_dll/cpptoc/urlrequest_client_cpptoc.h
+++ b/src/libcef_dll/cpptoc/urlrequest_client_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d78449c8011aa41c46a61bbf177ef09263f28b6c$
+// $hash=da593bcc58bec4b7dc1159fdc2fd2b8f472a6c93$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_URLREQUEST_CLIENT_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/urlrequest_cpptoc.cc b/src/libcef_dll/cpptoc/urlrequest_cpptoc.cc
index c352aff..5b73db4 100644
--- a/src/libcef_dll/cpptoc/urlrequest_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/urlrequest_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=81e91e1d45ee86a325f375002d82241a381fde91$
+// $hash=ec163d8f228ca2c347b8c6a76b814e45d0d46d28$
 //
 
 #include "libcef_dll/cpptoc/urlrequest_cpptoc.h"
@@ -31,12 +31,14 @@
 
   // Verify param: request; type: refptr_same
   DCHECK(request);
-  if (!request)
+  if (!request) {
     return NULL;
+  }
   // Verify param: client; type: refptr_diff
   DCHECK(client);
-  if (!client)
+  if (!client) {
     return NULL;
+  }
   // Unverified params: request_context
 
   // Execute
@@ -60,8 +62,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefRequest> _retval = CefURLRequestCppToC::Get(self)->GetRequest();
@@ -77,8 +80,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefURLRequestClient> _retval =
@@ -95,8 +99,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return UR_UNKNOWN;
+  }
 
   // Execute
   cef_urlrequest_status_t _retval =
@@ -113,8 +118,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return ERR_NONE;
+  }
 
   // Execute
   cef_errorcode_t _retval = CefURLRequestCppToC::Get(self)->GetRequestError();
@@ -130,8 +136,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefResponse> _retval =
@@ -148,8 +155,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefURLRequestCppToC::Get(self)->ResponseWasCached();
@@ -164,8 +172,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefURLRequestCppToC::Get(self)->Cancel();
@@ -195,7 +204,7 @@
 CefRefPtr<CefURLRequest>
 CefCppToCRefCounted<CefURLRequestCppToC, CefURLRequest, cef_urlrequest_t>::
     UnwrapDerived(CefWrapperType type, cef_urlrequest_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/urlrequest_cpptoc.h b/src/libcef_dll/cpptoc/urlrequest_cpptoc.h
index d6fba5d..3ed15df 100644
--- a/src/libcef_dll/cpptoc/urlrequest_cpptoc.h
+++ b/src/libcef_dll/cpptoc/urlrequest_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0cb270bce0e74831fb24a5aafbde34e460464e63$
+// $hash=f870036a626bd6ba126425b586b0a3116030c8d6$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_URLREQUEST_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/v8accessor_cpptoc.cc b/src/libcef_dll/cpptoc/v8accessor_cpptoc.cc
index 6528463..72fdd26 100644
--- a/src/libcef_dll/cpptoc/v8accessor_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/v8accessor_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=21cc15ad9b1f176e4c399cc74fcc459b32d38fee$
+// $hash=a6bbf97ac7f70e325509631a3bbdbf4b8b860d0c$
 //
 
 #include "libcef_dll/cpptoc/v8accessor_cpptoc.h"
@@ -27,29 +27,35 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return 0;
+  }
   // Verify param: object; type: refptr_diff
   DCHECK(object);
-  if (!object)
+  if (!object) {
     return 0;
+  }
   // Verify param: retval; type: refptr_diff_byref
   DCHECK(retval);
-  if (!retval)
+  if (!retval) {
     return 0;
+  }
   // Verify param: exception; type: string_byref
   DCHECK(exception);
-  if (!exception)
+  if (!exception) {
     return 0;
+  }
 
   // Translate param: retval; type: refptr_diff_byref
   CefRefPtr<CefV8Value> retvalPtr;
-  if (retval && *retval)
+  if (retval && *retval) {
     retvalPtr = CefV8ValueCToCpp::Wrap(*retval);
+  }
   CefV8Value* retvalOrig = retvalPtr.get();
   // Translate param: exception; type: string_byref
   CefString exceptionStr(exception);
@@ -81,24 +87,29 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return 0;
+  }
   // Verify param: object; type: refptr_diff
   DCHECK(object);
-  if (!object)
+  if (!object) {
     return 0;
+  }
   // Verify param: value; type: refptr_diff
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
   // Verify param: exception; type: string_byref
   DCHECK(exception);
-  if (!exception)
+  if (!exception) {
     return 0;
+  }
 
   // Translate param: exception; type: string_byref
   CefString exceptionStr(exception);
@@ -129,7 +140,7 @@
 CefRefPtr<CefV8Accessor>
 CefCppToCRefCounted<CefV8AccessorCppToC, CefV8Accessor, cef_v8accessor_t>::
     UnwrapDerived(CefWrapperType type, cef_v8accessor_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/v8accessor_cpptoc.h b/src/libcef_dll/cpptoc/v8accessor_cpptoc.h
index 9cbc10a..fb40f86 100644
--- a/src/libcef_dll/cpptoc/v8accessor_cpptoc.h
+++ b/src/libcef_dll/cpptoc/v8accessor_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e399801d4c1cf8c9dc9ca7800f26127b9006c207$
+// $hash=b8975b107d5912bdcc3e66229119fed6316d269c$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_V8ACCESSOR_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/v8array_buffer_release_callback_cpptoc.cc b/src/libcef_dll/cpptoc/v8array_buffer_release_callback_cpptoc.cc
index dd31275..9093115 100644
--- a/src/libcef_dll/cpptoc/v8array_buffer_release_callback_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/v8array_buffer_release_callback_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4c83d1414180cb0e03443f76eb4a49472c532a86$
+// $hash=44561e34afa6d45b0c6c324e345bef6c0e9f31b8$
 //
 
 #include "libcef_dll/cpptoc/v8array_buffer_release_callback_cpptoc.h"
@@ -24,12 +24,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: buffer; type: simple_byaddr
   DCHECK(buffer);
-  if (!buffer)
+  if (!buffer) {
     return;
+  }
 
   // Execute
   CefV8ArrayBufferReleaseCallbackCppToC::Get(self)->ReleaseBuffer(buffer);
@@ -55,7 +57,7 @@
                     cef_v8array_buffer_release_callback_t>::
     UnwrapDerived(CefWrapperType type,
                   cef_v8array_buffer_release_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/v8array_buffer_release_callback_cpptoc.h b/src/libcef_dll/cpptoc/v8array_buffer_release_callback_cpptoc.h
index 4243dfb..650881c 100644
--- a/src/libcef_dll/cpptoc/v8array_buffer_release_callback_cpptoc.h
+++ b/src/libcef_dll/cpptoc/v8array_buffer_release_callback_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=13f0f100ae8f6fc66b8a387e35d78ad3bbf74b2f$
+// $hash=f3cb7f220bf24ad178eed9b14d8b6e3d1baed6d5$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_V8ARRAY_BUFFER_RELEASE_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/v8context_cpptoc.cc b/src/libcef_dll/cpptoc/v8context_cpptoc.cc
index 5c49980..5c8f625 100644
--- a/src/libcef_dll/cpptoc/v8context_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/v8context_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=982d6b3a8201bbd3d32070c3ca522d849bc2d1f0$
+// $hash=06e55741773f12f9804a5f981f94a010e5293e14$
 //
 
 #include "libcef_dll/cpptoc/v8context_cpptoc.h"
@@ -60,8 +60,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTaskRunner> _retval =
@@ -75,8 +76,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ContextCppToC::Get(self)->IsValid();
@@ -90,8 +92,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowser> _retval = CefV8ContextCppToC::Get(self)->GetBrowser();
@@ -104,8 +107,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefFrame> _retval = CefV8ContextCppToC::Get(self)->GetFrame();
@@ -119,8 +123,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefV8Value> _retval = CefV8ContextCppToC::Get(self)->GetGlobal();
@@ -133,8 +138,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ContextCppToC::Get(self)->Enter();
@@ -147,8 +153,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ContextCppToC::Get(self)->Exit();
@@ -162,12 +169,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -186,31 +195,37 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: code; type: string_byref_const
   DCHECK(code);
-  if (!code)
+  if (!code) {
     return 0;
+  }
   // Verify param: retval; type: refptr_same_byref
   DCHECK(retval);
-  if (!retval)
+  if (!retval) {
     return 0;
+  }
   // Verify param: exception; type: refptr_same_byref
   DCHECK(exception);
-  if (!exception)
+  if (!exception) {
     return 0;
+  }
   // Unverified params: script_url
 
   // Translate param: retval; type: refptr_same_byref
   CefRefPtr<CefV8Value> retvalPtr;
-  if (retval && *retval)
+  if (retval && *retval) {
     retvalPtr = CefV8ValueCppToC::Unwrap(*retval);
+  }
   CefV8Value* retvalOrig = retvalPtr.get();
   // Translate param: exception; type: refptr_same_byref
   CefRefPtr<CefV8Exception> exceptionPtr;
-  if (exception && *exception)
+  if (exception && *exception) {
     exceptionPtr = CefV8ExceptionCppToC::Unwrap(*exception);
+  }
   CefV8Exception* exceptionOrig = exceptionPtr.get();
 
   // Execute
@@ -267,7 +282,7 @@
 CefRefPtr<CefV8Context>
 CefCppToCRefCounted<CefV8ContextCppToC, CefV8Context, cef_v8context_t>::
     UnwrapDerived(CefWrapperType type, cef_v8context_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/v8context_cpptoc.h b/src/libcef_dll/cpptoc/v8context_cpptoc.h
index 20c6ece..5b7746d 100644
--- a/src/libcef_dll/cpptoc/v8context_cpptoc.h
+++ b/src/libcef_dll/cpptoc/v8context_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f381dc42f5cfceb2de87f58518dfeb2a8163a502$
+// $hash=251051522f71e61a56b0844596a6ca2d858915c8$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_V8CONTEXT_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/v8exception_cpptoc.cc b/src/libcef_dll/cpptoc/v8exception_cpptoc.cc
index 92c9f5c..2e4964a 100644
--- a/src/libcef_dll/cpptoc/v8exception_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/v8exception_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=52a9308e9fe89367da969b258b0fc1aa7e315737$
+// $hash=049d20ef13c88453fffe0e5ed7648096b92073cb$
 //
 
 #include "libcef_dll/cpptoc/v8exception_cpptoc.h"
@@ -23,8 +23,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefV8ExceptionCppToC::Get(self)->GetMessage();
@@ -38,8 +39,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefV8ExceptionCppToC::Get(self)->GetSourceLine();
@@ -53,8 +55,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefV8ExceptionCppToC::Get(self)->GetScriptResourceName();
@@ -67,8 +70,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefV8ExceptionCppToC::Get(self)->GetLineNumber();
@@ -82,8 +86,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefV8ExceptionCppToC::Get(self)->GetStartPosition();
@@ -96,8 +101,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefV8ExceptionCppToC::Get(self)->GetEndPosition();
@@ -110,8 +116,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefV8ExceptionCppToC::Get(self)->GetStartColumn();
@@ -124,8 +131,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefV8ExceptionCppToC::Get(self)->GetEndColumn();
@@ -157,7 +165,7 @@
 CefRefPtr<CefV8Exception>
 CefCppToCRefCounted<CefV8ExceptionCppToC, CefV8Exception, cef_v8exception_t>::
     UnwrapDerived(CefWrapperType type, cef_v8exception_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/v8exception_cpptoc.h b/src/libcef_dll/cpptoc/v8exception_cpptoc.h
index b0e1a37..d9f8725 100644
--- a/src/libcef_dll/cpptoc/v8exception_cpptoc.h
+++ b/src/libcef_dll/cpptoc/v8exception_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4c02f299865ed4f85feaad75dafa55bd8f571cc1$
+// $hash=438f4efa56776c515c7c42c6a7dae68937729fef$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_V8EXCEPTION_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/v8handler_cpptoc.cc b/src/libcef_dll/cpptoc/v8handler_cpptoc.cc
index f1162a3..0d26b87 100644
--- a/src/libcef_dll/cpptoc/v8handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/v8handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e0f75f572dbb0e9c838dbc88a5bfdd4d73a8e880$
+// $hash=9b1ad32d9167bdaaeee14834a82b13927ac71c82$
 //
 
 #include "libcef_dll/cpptoc/v8handler_cpptoc.h"
@@ -29,28 +29,34 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return 0;
+  }
   // Verify param: object; type: refptr_diff
   DCHECK(object);
-  if (!object)
+  if (!object) {
     return 0;
+  }
   // Verify param: arguments; type: refptr_vec_diff_byref_const
   DCHECK(argumentsCount == 0 || arguments);
-  if (argumentsCount > 0 && !arguments)
+  if (argumentsCount > 0 && !arguments) {
     return 0;
+  }
   // Verify param: retval; type: refptr_diff_byref
   DCHECK(retval);
-  if (!retval)
+  if (!retval) {
     return 0;
+  }
   // Verify param: exception; type: string_byref
   DCHECK(exception);
-  if (!exception)
+  if (!exception) {
     return 0;
+  }
 
   // Translate param: arguments; type: refptr_vec_diff_byref_const
   std::vector<CefRefPtr<CefV8Value>> argumentsList;
@@ -62,8 +68,9 @@
   }
   // Translate param: retval; type: refptr_diff_byref
   CefRefPtr<CefV8Value> retvalPtr;
-  if (retval && *retval)
+  if (retval && *retval) {
     retvalPtr = CefV8ValueCToCpp::Wrap(*retval);
+  }
   CefV8Value* retvalOrig = retvalPtr.get();
   // Translate param: exception; type: string_byref
   CefString exceptionStr(exception);
@@ -104,7 +111,7 @@
 CefRefPtr<CefV8Handler>
 CefCppToCRefCounted<CefV8HandlerCppToC, CefV8Handler, cef_v8handler_t>::
     UnwrapDerived(CefWrapperType type, cef_v8handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/v8handler_cpptoc.h b/src/libcef_dll/cpptoc/v8handler_cpptoc.h
index bdebd3a..f3122ff 100644
--- a/src/libcef_dll/cpptoc/v8handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/v8handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2ecd1ec476ad4f5fb9367ef5b49dab8d9c25fd7d$
+// $hash=25ab4ee4f4c72c6be2e4df28dfaa8bbe5ec522d6$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_V8HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/v8interceptor_cpptoc.cc b/src/libcef_dll/cpptoc/v8interceptor_cpptoc.cc
index 1abd989..e0f3cdd 100644
--- a/src/libcef_dll/cpptoc/v8interceptor_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/v8interceptor_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b44f4ce34e379b323220e4fda22e7ef4138b483e$
+// $hash=c8d0d84851df03db685c0a87a53780d64ce425db$
 //
 
 #include "libcef_dll/cpptoc/v8interceptor_cpptoc.h"
@@ -27,29 +27,35 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return 0;
+  }
   // Verify param: object; type: refptr_diff
   DCHECK(object);
-  if (!object)
+  if (!object) {
     return 0;
+  }
   // Verify param: retval; type: refptr_diff_byref
   DCHECK(retval);
-  if (!retval)
+  if (!retval) {
     return 0;
+  }
   // Verify param: exception; type: string_byref
   DCHECK(exception);
-  if (!exception)
+  if (!exception) {
     return 0;
+  }
 
   // Translate param: retval; type: refptr_diff_byref
   CefRefPtr<CefV8Value> retvalPtr;
-  if (retval && *retval)
+  if (retval && *retval) {
     retvalPtr = CefV8ValueCToCpp::Wrap(*retval);
+  }
   CefV8Value* retvalOrig = retvalPtr.get();
   // Translate param: exception; type: string_byref
   CefString exceptionStr(exception);
@@ -81,29 +87,35 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return 0;
+  }
   // Verify param: object; type: refptr_diff
   DCHECK(object);
-  if (!object)
+  if (!object) {
     return 0;
+  }
   // Verify param: retval; type: refptr_diff_byref
   DCHECK(retval);
-  if (!retval)
+  if (!retval) {
     return 0;
+  }
   // Verify param: exception; type: string_byref
   DCHECK(exception);
-  if (!exception)
+  if (!exception) {
     return 0;
+  }
 
   // Translate param: retval; type: refptr_diff_byref
   CefRefPtr<CefV8Value> retvalPtr;
-  if (retval && *retval)
+  if (retval && *retval) {
     retvalPtr = CefV8ValueCToCpp::Wrap(*retval);
+  }
   CefV8Value* retvalOrig = retvalPtr.get();
   // Translate param: exception; type: string_byref
   CefString exceptionStr(exception);
@@ -135,24 +147,29 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return 0;
+  }
   // Verify param: object; type: refptr_diff
   DCHECK(object);
-  if (!object)
+  if (!object) {
     return 0;
+  }
   // Verify param: value; type: refptr_diff
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
   // Verify param: exception; type: string_byref
   DCHECK(exception);
-  if (!exception)
+  if (!exception) {
     return 0;
+  }
 
   // Translate param: exception; type: string_byref
   CefString exceptionStr(exception);
@@ -174,24 +191,29 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return 0;
+  }
   // Verify param: object; type: refptr_diff
   DCHECK(object);
-  if (!object)
+  if (!object) {
     return 0;
+  }
   // Verify param: value; type: refptr_diff
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
   // Verify param: exception; type: string_byref
   DCHECK(exception);
-  if (!exception)
+  if (!exception) {
     return 0;
+  }
 
   // Translate param: exception; type: string_byref
   CefString exceptionStr(exception);
@@ -226,7 +248,7 @@
     CefV8Interceptor,
     cef_v8interceptor_t>::UnwrapDerived(CefWrapperType type,
                                         cef_v8interceptor_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/v8interceptor_cpptoc.h b/src/libcef_dll/cpptoc/v8interceptor_cpptoc.h
index 8146da4..07f4a62 100644
--- a/src/libcef_dll/cpptoc/v8interceptor_cpptoc.h
+++ b/src/libcef_dll/cpptoc/v8interceptor_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2b68dd0f39073afa0d7ae83dbf9c4aa7e7772823$
+// $hash=17704763b12cf8c125a358d2db96037f13613b17$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_V8INTERCEPTOR_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/v8stack_frame_cpptoc.cc b/src/libcef_dll/cpptoc/v8stack_frame_cpptoc.cc
index 7bd243b..7345c80 100644
--- a/src/libcef_dll/cpptoc/v8stack_frame_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/v8stack_frame_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=95cf5f4a9561fd25c98ef424df8a9d6047c24cc8$
+// $hash=0f0803623b8296300984dd5f93802b32f536a604$
 //
 
 #include "libcef_dll/cpptoc/v8stack_frame_cpptoc.h"
@@ -22,8 +22,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8StackFrameCppToC::Get(self)->IsValid();
@@ -37,8 +38,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefV8StackFrameCppToC::Get(self)->GetScriptName();
@@ -52,8 +54,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -68,8 +71,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefV8StackFrameCppToC::Get(self)->GetFunctionName();
@@ -83,8 +87,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefV8StackFrameCppToC::Get(self)->GetLineNumber();
@@ -97,8 +102,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefV8StackFrameCppToC::Get(self)->GetColumn();
@@ -111,8 +117,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8StackFrameCppToC::Get(self)->IsEval();
@@ -126,8 +133,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8StackFrameCppToC::Get(self)->IsConstructor();
@@ -162,7 +170,7 @@
     CefV8StackFrame,
     cef_v8stack_frame_t>::UnwrapDerived(CefWrapperType type,
                                         cef_v8stack_frame_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/v8stack_frame_cpptoc.h b/src/libcef_dll/cpptoc/v8stack_frame_cpptoc.h
index 8bf914c..fabdf22 100644
--- a/src/libcef_dll/cpptoc/v8stack_frame_cpptoc.h
+++ b/src/libcef_dll/cpptoc/v8stack_frame_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=928142686ea53b977fe4b1f4447d249e38cf913b$
+// $hash=a804ebb160de9a40b1e8ce65e1dfca67e5ffb658$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_V8STACK_FRAME_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/v8stack_trace_cpptoc.cc b/src/libcef_dll/cpptoc/v8stack_trace_cpptoc.cc
index c936252..8e88dfe 100644
--- a/src/libcef_dll/cpptoc/v8stack_trace_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/v8stack_trace_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=39ca29830cc55c7ebbb4786e811d20fa675156af$
+// $hash=994446939847e01ee1c2ce3b3c3f1988bbe97a10$
 //
 
 #include "libcef_dll/cpptoc/v8stack_trace_cpptoc.h"
@@ -40,8 +40,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8StackTraceCppToC::Get(self)->IsValid();
@@ -57,8 +58,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefV8StackTraceCppToC::Get(self)->GetFrameCount();
@@ -74,8 +76,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefV8StackFrame> _retval =
@@ -107,7 +110,7 @@
     CefV8StackTrace,
     cef_v8stack_trace_t>::UnwrapDerived(CefWrapperType type,
                                         cef_v8stack_trace_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/v8stack_trace_cpptoc.h b/src/libcef_dll/cpptoc/v8stack_trace_cpptoc.h
index d79e429..c037447 100644
--- a/src/libcef_dll/cpptoc/v8stack_trace_cpptoc.h
+++ b/src/libcef_dll/cpptoc/v8stack_trace_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d75ffc77a6f3128512fefcc7471f8dd151fa36f2$
+// $hash=7d064189557bf22631a1daf8a757128680743960$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_V8STACK_TRACE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/v8value_cpptoc.cc b/src/libcef_dll/cpptoc/v8value_cpptoc.cc
index 2dd49d2..dcac030 100644
--- a/src/libcef_dll/cpptoc/v8value_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/v8value_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=5a6ed12d3af81274817888347d60b580e8f5de10$
+// $hash=21d8fb47eb282f40fb9d602f44b8c1fd4ff44dea$
 //
 
 #include "libcef_dll/cpptoc/v8value_cpptoc.h"
@@ -54,7 +54,7 @@
   return CefV8ValueCppToC::Wrap(_retval);
 }
 
-CEF_EXPORT cef_v8value_t* cef_v8value_create_int(int32 value) {
+CEF_EXPORT cef_v8value_t* cef_v8value_create_int(int32_t value) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
@@ -64,7 +64,7 @@
   return CefV8ValueCppToC::Wrap(_retval);
 }
 
-CEF_EXPORT cef_v8value_t* cef_v8value_create_uint(uint32 value) {
+CEF_EXPORT cef_v8value_t* cef_v8value_create_uint(uint32_t value) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
@@ -84,19 +84,11 @@
   return CefV8ValueCppToC::Wrap(_retval);
 }
 
-CEF_EXPORT cef_v8value_t* cef_v8value_create_date(const cef_time_t* date) {
+CEF_EXPORT cef_v8value_t* cef_v8value_create_date(cef_basetime_t date) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
-  // Verify param: date; type: simple_byref_const
-  DCHECK(date);
-  if (!date)
-    return NULL;
-
-  // Translate param: date; type: simple_byref_const
-  CefTime dateVal = date ? *date : CefTime();
-
   // Execute
-  CefRefPtr<CefV8Value> _retval = CefV8Value::CreateDate(dateVal);
+  CefRefPtr<CefV8Value> _retval = CefV8Value::CreateDate(date);
 
   // Return type: refptr_same
   return CefV8ValueCppToC::Wrap(_retval);
@@ -146,14 +138,12 @@
     cef_v8array_buffer_release_callback_t* release_callback) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
-  // Verify param: buffer; type: simple_byaddr
-  DCHECK(buffer);
-  if (!buffer)
-    return NULL;
   // Verify param: release_callback; type: refptr_diff
   DCHECK(release_callback);
-  if (!release_callback)
+  if (!release_callback) {
     return NULL;
+  }
+  // Unverified params: buffer
 
   // Execute
   CefRefPtr<CefV8Value> _retval = CefV8Value::CreateArrayBuffer(
@@ -171,12 +161,14 @@
 
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return NULL;
+  }
   // Verify param: handler; type: refptr_diff
   DCHECK(handler);
-  if (!handler)
+  if (!handler) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefV8Value> _retval = CefV8Value::CreateFunction(
@@ -186,6 +178,16 @@
   return CefV8ValueCppToC::Wrap(_retval);
 }
 
+CEF_EXPORT cef_v8value_t* cef_v8value_create_promise() {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  CefRefPtr<CefV8Value> _retval = CefV8Value::CreatePromise();
+
+  // Return type: refptr_same
+  return CefV8ValueCppToC::Wrap(_retval);
+}
+
 namespace {
 
 // MEMBER FUNCTIONS - Body may be edited by hand.
@@ -194,8 +196,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->IsValid();
@@ -208,8 +211,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->IsUndefined();
@@ -222,8 +226,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->IsNull();
@@ -236,8 +241,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->IsBool();
@@ -250,8 +256,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->IsInt();
@@ -264,8 +271,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->IsUInt();
@@ -278,8 +286,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->IsDouble();
@@ -292,8 +301,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->IsDate();
@@ -306,8 +316,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->IsString();
@@ -320,8 +331,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->IsObject();
@@ -334,8 +346,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->IsArray();
@@ -348,8 +361,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->IsArrayBuffer();
@@ -362,8 +376,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->IsFunction();
@@ -372,17 +387,34 @@
   return _retval;
 }
 
+int CEF_CALLBACK v8value_is_promise(struct _cef_v8value_t* self) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefV8ValueCppToC::Get(self)->IsPromise();
+
+  // Return type: bool
+  return _retval;
+}
+
 int CEF_CALLBACK v8value_is_same(struct _cef_v8value_t* self,
                                  struct _cef_v8value_t* that) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -396,8 +428,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->GetBoolValue();
@@ -406,29 +439,31 @@
   return _retval;
 }
 
-int32 CEF_CALLBACK v8value_get_int_value(struct _cef_v8value_t* self) {
+int32_t CEF_CALLBACK v8value_get_int_value(struct _cef_v8value_t* self) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
-  int32 _retval = CefV8ValueCppToC::Get(self)->GetIntValue();
+  int32_t _retval = CefV8ValueCppToC::Get(self)->GetIntValue();
 
   // Return type: simple
   return _retval;
 }
 
-uint32 CEF_CALLBACK v8value_get_uint_value(struct _cef_v8value_t* self) {
+uint32_t CEF_CALLBACK v8value_get_uint_value(struct _cef_v8value_t* self) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
-  uint32 _retval = CefV8ValueCppToC::Get(self)->GetUIntValue();
+  uint32_t _retval = CefV8ValueCppToC::Get(self)->GetUIntValue();
 
   // Return type: simple
   return _retval;
@@ -438,8 +473,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   double _retval = CefV8ValueCppToC::Get(self)->GetDoubleValue();
@@ -448,15 +484,17 @@
   return _retval;
 }
 
-cef_time_t CEF_CALLBACK v8value_get_date_value(struct _cef_v8value_t* self) {
+cef_basetime_t CEF_CALLBACK
+v8value_get_date_value(struct _cef_v8value_t* self) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
-    return CefTime();
+  if (!self) {
+    return CefBaseTime();
+  }
 
   // Execute
-  cef_time_t _retval = CefV8ValueCppToC::Get(self)->GetDateValue();
+  cef_basetime_t _retval = CefV8ValueCppToC::Get(self)->GetDateValue();
 
   // Return type: simple
   return _retval;
@@ -467,8 +505,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefV8ValueCppToC::Get(self)->GetStringValue();
@@ -481,8 +520,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->IsUserCreated();
@@ -495,8 +535,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->HasException();
@@ -510,8 +551,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefV8Exception> _retval =
@@ -525,8 +567,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->ClearException();
@@ -539,8 +582,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->WillRethrowExceptions();
@@ -554,8 +598,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -570,8 +615,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Unverified params: key
 
   // Execute
@@ -586,12 +632,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->HasValue(index);
@@ -605,8 +653,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Unverified params: key
 
   // Execute
@@ -621,12 +670,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->DeleteValue(index);
@@ -640,8 +691,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Unverified params: key
 
   // Execute
@@ -657,12 +709,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefV8Value> _retval = CefV8ValueCppToC::Get(self)->GetValue(index);
@@ -678,12 +732,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
   // Unverified params: key
 
   // Execute
@@ -700,16 +756,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return 0;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->SetValue(
@@ -727,8 +786,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Unverified params: key
 
   // Execute
@@ -744,12 +804,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: keys; type: string_vec_byref
   DCHECK(keys);
-  if (!keys)
+  if (!keys) {
     return 0;
+  }
 
   // Translate param: keys; type: string_vec_byref
   std::vector<CefString> keysList;
@@ -771,8 +833,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Unverified params: user_data
 
   // Execute
@@ -788,8 +851,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBaseRefCounted> _retval =
@@ -804,8 +868,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefV8ValueCppToC::Get(self)->GetExternallyAllocatedMemory();
@@ -820,8 +885,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefV8ValueCppToC::Get(self)->AdjustExternallyAllocatedMemory(
@@ -835,8 +901,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefV8ValueCppToC::Get(self)->GetArrayLength();
@@ -850,8 +917,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefV8ArrayBufferReleaseCallback> _retval =
@@ -865,8 +933,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefV8ValueCppToC::Get(self)->NeuterArrayBuffer();
@@ -875,13 +944,46 @@
   return _retval;
 }
 
+size_t CEF_CALLBACK
+v8value_get_array_buffer_byte_length(struct _cef_v8value_t* self) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  size_t _retval = CefV8ValueCppToC::Get(self)->GetArrayBufferByteLength();
+
+  // Return type: simple
+  return _retval;
+}
+
+void* CEF_CALLBACK v8value_get_array_buffer_data(struct _cef_v8value_t* self) {
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+
+  // This manual implementation can be removed once support for 'void*'
+  // is integrated into the CEF translator tool (issue #3591).
+
+  // Execute
+  void* _retval = CefV8ValueCppToC::Get(self)->GetArrayBufferData();
+
+  // Return type: simple_byaddr
+  return _retval;
+}
+
 cef_string_userfree_t CEF_CALLBACK
 v8value_get_function_name(struct _cef_v8value_t* self) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefV8ValueCppToC::Get(self)->GetFunctionName();
@@ -895,8 +997,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefV8Handler> _retval =
@@ -914,12 +1017,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: arguments; type: refptr_vec_same_byref_const
   DCHECK(argumentsCount == 0 || arguments);
-  if (argumentsCount > 0 && !arguments)
+  if (argumentsCount > 0 && !arguments) {
     return NULL;
+  }
   // Unverified params: object
 
   // Translate param: arguments; type: refptr_vec_same_byref_const
@@ -949,16 +1054,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: context; type: refptr_same
   DCHECK(context);
-  if (!context)
+  if (!context) {
     return NULL;
+  }
   // Verify param: arguments; type: refptr_vec_same_byref_const
   DCHECK(argumentsCount == 0 || arguments);
-  if (argumentsCount > 0 && !arguments)
+  if (argumentsCount > 0 && !arguments) {
     return NULL;
+  }
   // Unverified params: object
 
   // Translate param: arguments; type: refptr_vec_same_byref_const
@@ -981,6 +1089,46 @@
   return CefV8ValueCppToC::Wrap(_retval);
 }
 
+int CEF_CALLBACK v8value_resolve_promise(struct _cef_v8value_t* self,
+                                         struct _cef_v8value_t* arg) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Unverified params: arg
+
+  // Execute
+  bool _retval = CefV8ValueCppToC::Get(self)->ResolvePromise(
+      CefV8ValueCppToC::Unwrap(arg));
+
+  // Return type: bool
+  return _retval;
+}
+
+int CEF_CALLBACK v8value_reject_promise(struct _cef_v8value_t* self,
+                                        const cef_string_t* errorMsg) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: errorMsg; type: string_byref_const
+  DCHECK(errorMsg);
+  if (!errorMsg) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval =
+      CefV8ValueCppToC::Get(self)->RejectPromise(CefString(errorMsg));
+
+  // Return type: bool
+  return _retval;
+}
+
 }  // namespace
 
 // CONSTRUCTOR - Do not edit by hand.
@@ -999,6 +1147,7 @@
   GetStruct()->is_array = v8value_is_array;
   GetStruct()->is_array_buffer = v8value_is_array_buffer;
   GetStruct()->is_function = v8value_is_function;
+  GetStruct()->is_promise = v8value_is_promise;
   GetStruct()->is_same = v8value_is_same;
   GetStruct()->get_bool_value = v8value_get_bool_value;
   GetStruct()->get_int_value = v8value_get_int_value;
@@ -1032,11 +1181,16 @@
   GetStruct()->get_array_buffer_release_callback =
       v8value_get_array_buffer_release_callback;
   GetStruct()->neuter_array_buffer = v8value_neuter_array_buffer;
+  GetStruct()->get_array_buffer_byte_length =
+      v8value_get_array_buffer_byte_length;
+  GetStruct()->get_array_buffer_data = v8value_get_array_buffer_data;
   GetStruct()->get_function_name = v8value_get_function_name;
   GetStruct()->get_function_handler = v8value_get_function_handler;
   GetStruct()->execute_function = v8value_execute_function;
   GetStruct()->execute_function_with_context =
       v8value_execute_function_with_context;
+  GetStruct()->resolve_promise = v8value_resolve_promise;
+  GetStruct()->reject_promise = v8value_reject_promise;
 }
 
 // DESTRUCTOR - Do not edit by hand.
@@ -1048,7 +1202,7 @@
 CefCppToCRefCounted<CefV8ValueCppToC, CefV8Value, cef_v8value_t>::UnwrapDerived(
     CefWrapperType type,
     cef_v8value_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/v8value_cpptoc.h b/src/libcef_dll/cpptoc/v8value_cpptoc.h
index 4e9faba..87862ae 100644
--- a/src/libcef_dll/cpptoc/v8value_cpptoc.h
+++ b/src/libcef_dll/cpptoc/v8value_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=50b66fea70f0b25aec23a1c24edeac8ae6b9915c$
+// $hash=5b314dd35111aa303aa5d695e75839076f874c90$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_V8VALUE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/value_cpptoc.cc b/src/libcef_dll/cpptoc/value_cpptoc.cc
index b0f53a6..1c80ff2 100644
--- a/src/libcef_dll/cpptoc/value_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/value_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4acbaa4608fbac62442f6f6cf921e7c51c930539$
+// $hash=356224055a712a772976ab1166fe101f98228827$
 //
 
 #include "libcef_dll/cpptoc/value_cpptoc.h"
@@ -42,8 +42,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefValueCppToC::Get(self)->IsValid();
@@ -58,8 +59,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefValueCppToC::Get(self)->IsOwned();
@@ -74,8 +76,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefValueCppToC::Get(self)->IsReadOnly();
@@ -91,12 +94,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -113,12 +118,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -134,8 +141,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefValue> _retval = CefValueCppToC::Get(self)->Copy();
@@ -150,8 +158,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return VTYPE_INVALID;
+  }
 
   // Execute
   cef_value_type_t _retval = CefValueCppToC::Get(self)->GetType();
@@ -166,8 +175,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefValueCppToC::Get(self)->GetBool();
@@ -182,8 +192,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefValueCppToC::Get(self)->GetInt();
@@ -198,8 +209,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   double _retval = CefValueCppToC::Get(self)->GetDouble();
@@ -214,8 +226,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefValueCppToC::Get(self)->GetString();
@@ -231,8 +244,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBinaryValue> _retval = CefValueCppToC::Get(self)->GetBinary();
@@ -248,8 +262,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDictionaryValue> _retval =
@@ -266,8 +281,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefListValue> _retval = CefValueCppToC::Get(self)->GetList();
@@ -282,8 +298,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefValueCppToC::Get(self)->SetNull();
@@ -298,8 +315,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefValueCppToC::Get(self)->SetBool(value ? true : false);
@@ -314,8 +332,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefValueCppToC::Get(self)->SetInt(value);
@@ -330,8 +349,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefValueCppToC::Get(self)->SetDouble(value);
@@ -347,8 +367,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Unverified params: value
 
   // Execute
@@ -365,12 +386,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -387,12 +410,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefValueCppToC::Get(self)->SetDictionary(
@@ -409,12 +434,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value);
-  if (!value)
+  if (!value) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -464,7 +491,7 @@
 CefCppToCRefCounted<CefValueCppToC, CefValue, cef_value_t>::UnwrapDerived(
     CefWrapperType type,
     cef_value_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/value_cpptoc.h b/src/libcef_dll/cpptoc/value_cpptoc.h
index 72948d2..512155e 100644
--- a/src/libcef_dll/cpptoc/value_cpptoc.h
+++ b/src/libcef_dll/cpptoc/value_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=85450d06a35f819a703ee947b2b932f2dc13e4ca$
+// $hash=19a491010366c91259449297ea4fb37414ae2a8e$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VALUE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/box_layout_cpptoc.cc b/src/libcef_dll/cpptoc/views/box_layout_cpptoc.cc
index 8ee48ea..ee43257 100644
--- a/src/libcef_dll/cpptoc/views/box_layout_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/box_layout_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6a8359ec33d2f2e18551fe0b1abf91df68c4417f$
+// $hash=909f89cc8243a1438a31bc2d5e0957c18b65a9b0$
 //
 
 #include "libcef_dll/cpptoc/views/box_layout_cpptoc.h"
@@ -29,12 +29,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefBoxLayoutCppToC::Get(self)->SetFlexForView(CefViewCppToC::Unwrap(view),
@@ -48,12 +50,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefBoxLayoutCppToC::Get(self)->ClearFlexForView(CefViewCppToC::Unwrap(view));
@@ -66,8 +70,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBoxLayout> _retval =
@@ -85,8 +90,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefFillLayout> _retval =
@@ -103,8 +109,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -137,7 +144,7 @@
 CefRefPtr<CefBoxLayout>
 CefCppToCRefCounted<CefBoxLayoutCppToC, CefBoxLayout, cef_box_layout_t>::
     UnwrapDerived(CefWrapperType type, cef_box_layout_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/box_layout_cpptoc.h b/src/libcef_dll/cpptoc/views/box_layout_cpptoc.h
index fedff1c..fc41243 100644
--- a/src/libcef_dll/cpptoc/views/box_layout_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/box_layout_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9e9add48dabc81d6b8eb58131db0018443f04dda$
+// $hash=3f9e4984c1e1eff7e51ab13f9f7fe2ab249657ec$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_BOX_LAYOUT_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/browser_view_cpptoc.cc b/src/libcef_dll/cpptoc/views/browser_view_cpptoc.cc
index 99f0508..f550e82 100644
--- a/src/libcef_dll/cpptoc/views/browser_view_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/browser_view_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=41288fac368c771f9c673f231f6f632f6c6ec255$
+// $hash=8ed7a2cd363a38cde65551fa5366085d9fa5b919$
 //
 
 #include "libcef_dll/cpptoc/views/browser_view_cpptoc.h"
@@ -26,6 +26,7 @@
 #include "libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.h"
 #include "libcef_dll/ctocpp/views/view_delegate_ctocpp.h"
 #include "libcef_dll/shutdown_checker.h"
+#include "libcef_dll/template_util.h"
 
 // GLOBAL FUNCTIONS - Body may be edited by hand.
 
@@ -42,14 +43,20 @@
 
   // Verify param: settings; type: struct_byref_const
   DCHECK(settings);
-  if (!settings)
+  if (!settings) {
     return NULL;
+  }
+  if (!template_util::has_valid_size(settings)) {
+    DCHECK(false) << "invalid settings->[base.]size";
+    return NULL;
+  }
   // Unverified params: client, url, extra_info, request_context, delegate
 
   // Translate param: settings; type: struct_byref_const
   CefBrowserSettings settingsObj;
-  if (settings)
+  if (settings) {
     settingsObj.Set(*settings, false);
+  }
 
   // Execute
   CefRefPtr<CefBrowserView> _retval = CefBrowserView::CreateBrowserView(
@@ -70,8 +77,9 @@
 
   // Verify param: browser; type: refptr_same
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowserView> _retval =
@@ -92,8 +100,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowser> _retval = CefBrowserViewCppToC::Get(self)->GetBrowser();
@@ -102,6 +111,25 @@
   return CefBrowserCppToC::Wrap(_retval);
 }
 
+struct _cef_view_t* CEF_CALLBACK
+browser_view_get_chrome_toolbar(struct _cef_browser_view_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefView> _retval =
+      CefBrowserViewCppToC::Get(self)->GetChromeToolbar();
+
+  // Return type: refptr_same
+  return CefViewCppToC::Wrap(_retval);
+}
+
 void CEF_CALLBACK
 browser_view_set_prefer_accelerators(struct _cef_browser_view_t* self,
                                      int prefer_accelerators) {
@@ -110,8 +138,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserViewCppToC::Get(self)->SetPreferAccelerators(
@@ -125,8 +154,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowserView> _retval =
@@ -143,8 +173,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefButton> _retval =
@@ -161,8 +192,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefPanel> _retval =
@@ -180,8 +212,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefScrollView> _retval =
@@ -199,8 +232,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTextfield> _retval =
@@ -218,8 +252,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -237,8 +272,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -255,8 +291,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -273,8 +310,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -292,12 +330,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -315,8 +355,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefViewDelegate> _retval =
@@ -334,8 +375,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefWindow> _retval =
@@ -352,8 +394,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -370,8 +413,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserViewCppToC::Get(reinterpret_cast<cef_browser_view_t*>(self))
@@ -384,8 +428,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -403,8 +448,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserViewCppToC::Get(reinterpret_cast<cef_browser_view_t*>(self))
@@ -418,8 +464,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -437,8 +484,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -456,12 +504,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: bounds; type: simple_byref_const
   DCHECK(bounds);
-  if (!bounds)
+  if (!bounds) {
     return;
+  }
 
   // Translate param: bounds; type: simple_byref_const
   CefRect boundsVal = bounds ? *bounds : CefRect();
@@ -477,8 +527,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval =
@@ -496,8 +547,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval =
@@ -515,12 +567,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: size; type: simple_byref_const
   DCHECK(size);
-  if (!size)
+  if (!size) {
     return;
+  }
 
   // Translate param: size; type: simple_byref_const
   CefSize sizeVal = size ? *size : CefSize();
@@ -536,8 +590,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -555,12 +610,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: position; type: simple_byref_const
   DCHECK(position);
-  if (!position)
+  if (!position) {
     return;
+  }
 
   // Translate param: position; type: simple_byref_const
   CefPoint positionVal = position ? *position : CefPoint();
@@ -576,8 +633,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefPoint();
+  }
 
   // Execute
   cef_point_t _retval =
@@ -588,6 +646,49 @@
   return _retval;
 }
 
+void CEF_CALLBACK browser_view_set_insets(struct _cef_view_t* self,
+                                          const cef_insets_t* insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: insets; type: simple_byref_const
+  DCHECK(insets);
+  if (!insets) {
+    return;
+  }
+
+  // Translate param: insets; type: simple_byref_const
+  CefInsets insetsVal = insets ? *insets : CefInsets();
+
+  // Execute
+  CefBrowserViewCppToC::Get(reinterpret_cast<cef_browser_view_t*>(self))
+      ->SetInsets(insetsVal);
+}
+
+cef_insets_t CEF_CALLBACK browser_view_get_insets(struct _cef_view_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CefInsets();
+  }
+
+  // Execute
+  cef_insets_t _retval =
+      CefBrowserViewCppToC::Get(reinterpret_cast<cef_browser_view_t*>(self))
+          ->GetInsets();
+
+  // Return type: simple
+  return _retval;
+}
+
 cef_size_t CEF_CALLBACK
 browser_view_get_preferred_size(struct _cef_view_t* self) {
   shutdown_checker::AssertNotShutdown();
@@ -595,8 +696,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -614,8 +716,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserViewCppToC::Get(reinterpret_cast<cef_browser_view_t*>(self))
@@ -629,8 +732,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -648,8 +752,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -667,8 +772,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -685,8 +791,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserViewCppToC::Get(reinterpret_cast<cef_browser_view_t*>(self))
@@ -700,8 +807,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserViewCppToC::Get(reinterpret_cast<cef_browser_view_t*>(self))
@@ -714,8 +822,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -732,8 +841,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -751,8 +861,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserViewCppToC::Get(reinterpret_cast<cef_browser_view_t*>(self))
@@ -765,8 +876,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -784,8 +896,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserViewCppToC::Get(reinterpret_cast<cef_browser_view_t*>(self))
@@ -798,8 +911,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -817,8 +931,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -835,8 +950,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserViewCppToC::Get(reinterpret_cast<cef_browser_view_t*>(self))
@@ -850,8 +966,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefBrowserViewCppToC::Get(reinterpret_cast<cef_browser_view_t*>(self))
@@ -865,8 +982,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   cef_color_t _retval =
@@ -884,12 +1002,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -900,8 +1020,9 @@
           ->ConvertPointToScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -915,12 +1036,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -931,8 +1054,9 @@
           ->ConvertPointFromScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -945,12 +1069,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -961,8 +1087,9 @@
           ->ConvertPointToWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -976,12 +1103,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -992,8 +1121,9 @@
           ->ConvertPointFromWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1007,16 +1137,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1027,8 +1160,9 @@
           ->ConvertPointToView(CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1042,16 +1176,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1062,8 +1199,9 @@
           ->ConvertPointFromView(CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1075,6 +1213,7 @@
 
 CefBrowserViewCppToC::CefBrowserViewCppToC() {
   GetStruct()->get_browser = browser_view_get_browser;
+  GetStruct()->get_chrome_toolbar = browser_view_get_chrome_toolbar;
   GetStruct()->set_prefer_accelerators = browser_view_set_prefer_accelerators;
   GetStruct()->base.as_browser_view = browser_view_as_browser_view;
   GetStruct()->base.as_button = browser_view_as_button;
@@ -1101,6 +1240,8 @@
   GetStruct()->base.get_size = browser_view_get_size;
   GetStruct()->base.set_position = browser_view_set_position;
   GetStruct()->base.get_position = browser_view_get_position;
+  GetStruct()->base.set_insets = browser_view_set_insets;
+  GetStruct()->base.get_insets = browser_view_get_insets;
   GetStruct()->base.get_preferred_size = browser_view_get_preferred_size;
   GetStruct()->base.size_to_preferred_size =
       browser_view_size_to_preferred_size;
@@ -1143,7 +1284,7 @@
 CefRefPtr<CefBrowserView>
 CefCppToCRefCounted<CefBrowserViewCppToC, CefBrowserView, cef_browser_view_t>::
     UnwrapDerived(CefWrapperType type, cef_browser_view_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/browser_view_cpptoc.h b/src/libcef_dll/cpptoc/views/browser_view_cpptoc.h
index 49fb304..2f9fd83 100644
--- a/src/libcef_dll/cpptoc/views/browser_view_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/browser_view_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c6c62820ebb45bb8970a35a6b5d2d90dda6f18f2$
+// $hash=f981c5f7247ec57926549c145c47a7cdcbdd80a0$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_BROWSER_VIEW_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.cc b/src/libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.cc
index 4e4ec1b..6967bea 100644
--- a/src/libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c9ea7a1dae87105f7abfbd2e95747bc3380a9dc6$
+// $hash=f82440b30a75049733b4dd200494ab06d52c68b3$
 //
 
 #include "libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.h"
@@ -18,6 +18,7 @@
 #include "libcef_dll/ctocpp/views/browser_view_ctocpp.h"
 #include "libcef_dll/ctocpp/views/view_ctocpp.h"
 #include "libcef_dll/shutdown_checker.h"
+#include "libcef_dll/template_util.h"
 
 namespace {
 
@@ -32,16 +33,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser_view; type: refptr_diff
   DCHECK(browser_view);
-  if (!browser_view)
+  if (!browser_view) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefBrowserViewDelegateCppToC::Get(self)->OnBrowserCreated(
@@ -58,16 +62,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: browser_view; type: refptr_diff
   DCHECK(browser_view);
-  if (!browser_view)
+  if (!browser_view) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser);
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   // Execute
   CefBrowserViewDelegateCppToC::Get(self)->OnBrowserDestroyed(
@@ -87,25 +94,30 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: browser_view; type: refptr_diff
   DCHECK(browser_view);
-  if (!browser_view)
+  if (!browser_view) {
     return NULL;
+  }
   // Verify param: settings; type: struct_byref_const
   DCHECK(settings);
-  if (!settings)
+  if (!settings) {
     return NULL;
-  // Verify param: client; type: refptr_same
-  DCHECK(client);
-  if (!client)
+  }
+  if (!template_util::has_valid_size(settings)) {
+    DCHECK(false) << "invalid settings->[base.]size";
     return NULL;
+  }
+  // Unverified params: client
 
   // Translate param: settings; type: struct_byref_const
   CefBrowserSettings settingsObj;
-  if (settings)
+  if (settings) {
     settingsObj.Set(*settings, false);
+  }
 
   // Execute
   CefRefPtr<CefBrowserViewDelegate> _retval =
@@ -127,16 +139,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: browser_view; type: refptr_diff
   DCHECK(browser_view);
-  if (!browser_view)
+  if (!browser_view) {
     return 0;
+  }
   // Verify param: popup_browser_view; type: refptr_diff
   DCHECK(popup_browser_view);
-  if (!popup_browser_view)
+  if (!popup_browser_view) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -149,6 +164,86 @@
   return _retval;
 }
 
+cef_chrome_toolbar_type_t CEF_CALLBACK
+browser_view_delegate_get_chrome_toolbar_type(
+    struct _cef_browser_view_delegate_t* self,
+    cef_browser_view_t* browser_view) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CEF_CTT_NONE;
+  }
+  // Verify param: browser_view; type: refptr_diff
+  DCHECK(browser_view);
+  if (!browser_view) {
+    return CEF_CTT_NONE;
+  }
+
+  // Execute
+  cef_chrome_toolbar_type_t _retval =
+      CefBrowserViewDelegateCppToC::Get(self)->GetChromeToolbarType(
+          CefBrowserViewCToCpp::Wrap(browser_view));
+
+  // Return type: simple
+  return _retval;
+}
+
+int CEF_CALLBACK
+browser_view_delegate_use_frameless_window_for_picture_in_picture(
+    struct _cef_browser_view_delegate_t* self,
+    cef_browser_view_t* browser_view) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: browser_view; type: refptr_diff
+  DCHECK(browser_view);
+  if (!browser_view) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefBrowserViewDelegateCppToC::Get(self)
+                     ->UseFramelessWindowForPictureInPicture(
+                         CefBrowserViewCToCpp::Wrap(browser_view));
+
+  // Return type: bool
+  return _retval;
+}
+
+int CEF_CALLBACK browser_view_delegate_on_gesture_command(
+    struct _cef_browser_view_delegate_t* self,
+    cef_browser_view_t* browser_view,
+    cef_gesture_command_t gesture_command) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: browser_view; type: refptr_diff
+  DCHECK(browser_view);
+  if (!browser_view) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefBrowserViewDelegateCppToC::Get(self)->OnGestureCommand(
+      CefBrowserViewCToCpp::Wrap(browser_view), gesture_command);
+
+  // Return type: bool
+  return _retval;
+}
+
 cef_size_t CEF_CALLBACK
 browser_view_delegate_get_preferred_size(struct _cef_view_delegate_t* self,
                                          cef_view_t* view) {
@@ -157,12 +252,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefBrowserViewDelegateCppToC::Get(
@@ -181,12 +278,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefBrowserViewDelegateCppToC::Get(
@@ -205,12 +304,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefBrowserViewDelegateCppToC::Get(
@@ -230,12 +331,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
 
   // Execute
   int _retval = CefBrowserViewDelegateCppToC::Get(
@@ -256,16 +359,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
   // Verify param: parent; type: refptr_diff
   DCHECK(parent);
-  if (!parent)
+  if (!parent) {
     return;
+  }
 
   // Execute
   CefBrowserViewDelegateCppToC::Get(
@@ -284,16 +390,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
   // Verify param: child; type: refptr_diff
   DCHECK(child);
-  if (!child)
+  if (!child) {
     return;
+  }
 
   // Execute
   CefBrowserViewDelegateCppToC::Get(
@@ -303,6 +412,62 @@
 }
 
 void CEF_CALLBACK
+browser_view_delegate_on_window_changed(struct _cef_view_delegate_t* self,
+                                        cef_view_t* view,
+                                        int added) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: view; type: refptr_diff
+  DCHECK(view);
+  if (!view) {
+    return;
+  }
+
+  // Execute
+  CefBrowserViewDelegateCppToC::Get(
+      reinterpret_cast<cef_browser_view_delegate_t*>(self))
+      ->OnWindowChanged(CefViewCToCpp::Wrap(view), added ? true : false);
+}
+
+void CEF_CALLBACK
+browser_view_delegate_on_layout_changed(struct _cef_view_delegate_t* self,
+                                        cef_view_t* view,
+                                        const cef_rect_t* new_bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: view; type: refptr_diff
+  DCHECK(view);
+  if (!view) {
+    return;
+  }
+  // Verify param: new_bounds; type: simple_byref_const
+  DCHECK(new_bounds);
+  if (!new_bounds) {
+    return;
+  }
+
+  // Translate param: new_bounds; type: simple_byref_const
+  CefRect new_boundsVal = new_bounds ? *new_bounds : CefRect();
+
+  // Execute
+  CefBrowserViewDelegateCppToC::Get(
+      reinterpret_cast<cef_browser_view_delegate_t*>(self))
+      ->OnLayoutChanged(CefViewCToCpp::Wrap(view), new_boundsVal);
+}
+
+void CEF_CALLBACK
 browser_view_delegate_on_focus(struct _cef_view_delegate_t* self,
                                cef_view_t* view) {
   shutdown_checker::AssertNotShutdown();
@@ -310,12 +475,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefBrowserViewDelegateCppToC::Get(
@@ -331,12 +498,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefBrowserViewDelegateCppToC::Get(
@@ -356,6 +525,11 @@
       browser_view_delegate_get_delegate_for_popup_browser_view;
   GetStruct()->on_popup_browser_view_created =
       browser_view_delegate_on_popup_browser_view_created;
+  GetStruct()->get_chrome_toolbar_type =
+      browser_view_delegate_get_chrome_toolbar_type;
+  GetStruct()->use_frameless_window_for_picture_in_picture =
+      browser_view_delegate_use_frameless_window_for_picture_in_picture;
+  GetStruct()->on_gesture_command = browser_view_delegate_on_gesture_command;
   GetStruct()->base.get_preferred_size =
       browser_view_delegate_get_preferred_size;
   GetStruct()->base.get_minimum_size = browser_view_delegate_get_minimum_size;
@@ -366,6 +540,8 @@
       browser_view_delegate_on_parent_view_changed;
   GetStruct()->base.on_child_view_changed =
       browser_view_delegate_on_child_view_changed;
+  GetStruct()->base.on_window_changed = browser_view_delegate_on_window_changed;
+  GetStruct()->base.on_layout_changed = browser_view_delegate_on_layout_changed;
   GetStruct()->base.on_focus = browser_view_delegate_on_focus;
   GetStruct()->base.on_blur = browser_view_delegate_on_blur;
 }
@@ -383,7 +559,7 @@
     cef_browser_view_delegate_t>::UnwrapDerived(CefWrapperType type,
                                                 cef_browser_view_delegate_t*
                                                     s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.h b/src/libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.h
index 03de933..f0761f3 100644
--- a/src/libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=01f1b9ba8c2505b5a8bd532d6039c1b4ce803eb7$
+// $hash=b091e620040d148171ce5c99d5376cb00356eb37$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_BROWSER_VIEW_DELEGATE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/button_cpptoc.cc b/src/libcef_dll/cpptoc/views/button_cpptoc.cc
index 5cd2ef1..0bb9e8b 100644
--- a/src/libcef_dll/cpptoc/views/button_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/button_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9dde9e370abff08479bf0e7f81b59356c7646f41$
+// $hash=a6162679f74abe571ba59ff3811704fdb186a414$
 //
 
 #include "libcef_dll/cpptoc/views/button_cpptoc.h"
@@ -35,8 +35,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefLabelButton> _retval =
@@ -53,8 +54,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefButtonCppToC::Get(self)->SetState(state);
@@ -66,8 +68,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CEF_BUTTON_STATE_NORMAL;
+  }
 
   // Execute
   cef_button_state_t _retval = CefButtonCppToC::Get(self)->GetState();
@@ -83,8 +86,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefButtonCppToC::Get(self)->SetInkDropEnabled(enabled ? true : false);
@@ -97,12 +101,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: tooltip_text; type: string_byref_const
   DCHECK(tooltip_text);
-  if (!tooltip_text)
+  if (!tooltip_text) {
     return;
+  }
 
   // Execute
   CefButtonCppToC::Get(self)->SetTooltipText(CefString(tooltip_text));
@@ -115,12 +121,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
 
   // Execute
   CefButtonCppToC::Get(self)->SetAccessibleName(CefString(name));
@@ -133,8 +141,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowserView> _retval =
@@ -151,8 +160,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefButton> _retval =
@@ -168,8 +178,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefPanel> _retval =
@@ -186,8 +197,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefScrollView> _retval =
@@ -204,8 +216,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTextfield> _retval =
@@ -223,8 +236,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -242,8 +256,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -260,8 +275,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -277,8 +293,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -295,12 +312,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefButtonCppToC::Get(reinterpret_cast<cef_button_t*>(self))
@@ -317,8 +336,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefViewDelegate> _retval =
@@ -335,8 +355,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefWindow> _retval =
@@ -352,8 +373,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -369,8 +391,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefButtonCppToC::Get(reinterpret_cast<cef_button_t*>(self))->SetID(id);
@@ -382,8 +405,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -399,8 +423,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefButtonCppToC::Get(reinterpret_cast<cef_button_t*>(self))
@@ -414,8 +439,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -433,8 +459,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -452,12 +479,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: bounds; type: simple_byref_const
   DCHECK(bounds);
-  if (!bounds)
+  if (!bounds) {
     return;
+  }
 
   // Translate param: bounds; type: simple_byref_const
   CefRect boundsVal = bounds ? *bounds : CefRect();
@@ -473,8 +502,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval =
@@ -490,8 +520,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval =
@@ -509,12 +540,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: size; type: simple_byref_const
   DCHECK(size);
-  if (!size)
+  if (!size) {
     return;
+  }
 
   // Translate param: size; type: simple_byref_const
   CefSize sizeVal = size ? *size : CefSize();
@@ -529,8 +562,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -547,12 +581,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: position; type: simple_byref_const
   DCHECK(position);
-  if (!position)
+  if (!position) {
     return;
+  }
 
   // Translate param: position; type: simple_byref_const
   CefPoint positionVal = position ? *position : CefPoint();
@@ -568,8 +604,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefPoint();
+  }
 
   // Execute
   cef_point_t _retval =
@@ -580,14 +617,57 @@
   return _retval;
 }
 
+void CEF_CALLBACK button_set_insets(struct _cef_view_t* self,
+                                    const cef_insets_t* insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: insets; type: simple_byref_const
+  DCHECK(insets);
+  if (!insets) {
+    return;
+  }
+
+  // Translate param: insets; type: simple_byref_const
+  CefInsets insetsVal = insets ? *insets : CefInsets();
+
+  // Execute
+  CefButtonCppToC::Get(reinterpret_cast<cef_button_t*>(self))
+      ->SetInsets(insetsVal);
+}
+
+cef_insets_t CEF_CALLBACK button_get_insets(struct _cef_view_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CefInsets();
+  }
+
+  // Execute
+  cef_insets_t _retval =
+      CefButtonCppToC::Get(reinterpret_cast<cef_button_t*>(self))->GetInsets();
+
+  // Return type: simple
+  return _retval;
+}
+
 cef_size_t CEF_CALLBACK button_get_preferred_size(struct _cef_view_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -604,8 +684,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefButtonCppToC::Get(reinterpret_cast<cef_button_t*>(self))
@@ -618,8 +699,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -636,8 +718,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -655,8 +738,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefButtonCppToC::Get(reinterpret_cast<cef_button_t*>(self))
@@ -672,8 +756,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefButtonCppToC::Get(reinterpret_cast<cef_button_t*>(self))
@@ -686,8 +771,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefButtonCppToC::Get(reinterpret_cast<cef_button_t*>(self))
@@ -700,8 +786,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -717,8 +804,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -734,8 +822,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefButtonCppToC::Get(reinterpret_cast<cef_button_t*>(self))
@@ -748,8 +837,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -766,8 +856,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefButtonCppToC::Get(reinterpret_cast<cef_button_t*>(self))
@@ -780,8 +871,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefButtonCppToC::Get(reinterpret_cast<cef_button_t*>(self))
@@ -797,8 +889,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefButtonCppToC::Get(reinterpret_cast<cef_button_t*>(self))
@@ -814,8 +907,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefButtonCppToC::Get(reinterpret_cast<cef_button_t*>(self))->RequestFocus();
@@ -828,8 +922,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefButtonCppToC::Get(reinterpret_cast<cef_button_t*>(self))
@@ -842,8 +937,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   cef_color_t _retval =
@@ -861,12 +957,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -876,8 +974,9 @@
                      ->ConvertPointToScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -890,12 +989,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -905,8 +1006,9 @@
                      ->ConvertPointFromScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -919,12 +1021,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -934,8 +1038,9 @@
                      ->ConvertPointToWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -948,12 +1053,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -963,8 +1070,9 @@
                      ->ConvertPointFromWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -978,16 +1086,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -998,8 +1109,9 @@
           ->ConvertPointToView(CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1013,16 +1125,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1033,8 +1148,9 @@
           ->ConvertPointFromView(CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1076,6 +1192,8 @@
   GetStruct()->base.get_size = button_get_size;
   GetStruct()->base.set_position = button_set_position;
   GetStruct()->base.get_position = button_get_position;
+  GetStruct()->base.set_insets = button_set_insets;
+  GetStruct()->base.get_insets = button_get_insets;
   GetStruct()->base.get_preferred_size = button_get_preferred_size;
   GetStruct()->base.size_to_preferred_size = button_size_to_preferred_size;
   GetStruct()->base.get_minimum_size = button_get_minimum_size;
@@ -1122,7 +1240,7 @@
   if (type == WT_MENU_BUTTON) {
     return CefMenuButtonCppToC::Unwrap(reinterpret_cast<cef_menu_button_t*>(s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/button_cpptoc.h b/src/libcef_dll/cpptoc/views/button_cpptoc.h
index 1d37862..ed70f48 100644
--- a/src/libcef_dll/cpptoc/views/button_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/button_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b94f64a13280f6f469c408f2348ed59d906bcd12$
+// $hash=3fc906cb8937c58418501c33ba81462806b26860$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_BUTTON_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/button_delegate_cpptoc.cc b/src/libcef_dll/cpptoc/views/button_delegate_cpptoc.cc
index 0b343f1..def1dd5 100644
--- a/src/libcef_dll/cpptoc/views/button_delegate_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/button_delegate_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=54ea52665f0558439e3c7f885962d75ce3992a0d$
+// $hash=6c1d9cfcafa7425bf5530eba7be024d9d07c466b$
 //
 
 #include "libcef_dll/cpptoc/views/button_delegate_cpptoc.h"
@@ -30,12 +30,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: button; type: refptr_diff
   DCHECK(button);
-  if (!button)
+  if (!button) {
     return;
+  }
 
   // Execute
   CefButtonDelegateCppToC::Get(self)->OnButtonPressed(
@@ -50,12 +52,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: button; type: refptr_diff
   DCHECK(button);
-  if (!button)
+  if (!button) {
     return;
+  }
 
   // Execute
   CefButtonDelegateCppToC::Get(self)->OnButtonStateChanged(
@@ -70,12 +74,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefButtonDelegateCppToC::Get(
@@ -94,12 +100,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefButtonDelegateCppToC::Get(
@@ -118,12 +126,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefButtonDelegateCppToC::Get(
@@ -143,12 +153,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
 
   // Execute
   int _retval = CefButtonDelegateCppToC::Get(
@@ -169,16 +181,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
   // Verify param: parent; type: refptr_diff
   DCHECK(parent);
-  if (!parent)
+  if (!parent) {
     return;
+  }
 
   // Execute
   CefButtonDelegateCppToC::Get(reinterpret_cast<cef_button_delegate_t*>(self))
@@ -196,16 +211,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
   // Verify param: child; type: refptr_diff
   DCHECK(child);
-  if (!child)
+  if (!child) {
     return;
+  }
 
   // Execute
   CefButtonDelegateCppToC::Get(reinterpret_cast<cef_button_delegate_t*>(self))
@@ -213,6 +231,60 @@
                            CefViewCToCpp::Wrap(child));
 }
 
+void CEF_CALLBACK
+button_delegate_on_window_changed(struct _cef_view_delegate_t* self,
+                                  cef_view_t* view,
+                                  int added) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: view; type: refptr_diff
+  DCHECK(view);
+  if (!view) {
+    return;
+  }
+
+  // Execute
+  CefButtonDelegateCppToC::Get(reinterpret_cast<cef_button_delegate_t*>(self))
+      ->OnWindowChanged(CefViewCToCpp::Wrap(view), added ? true : false);
+}
+
+void CEF_CALLBACK
+button_delegate_on_layout_changed(struct _cef_view_delegate_t* self,
+                                  cef_view_t* view,
+                                  const cef_rect_t* new_bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: view; type: refptr_diff
+  DCHECK(view);
+  if (!view) {
+    return;
+  }
+  // Verify param: new_bounds; type: simple_byref_const
+  DCHECK(new_bounds);
+  if (!new_bounds) {
+    return;
+  }
+
+  // Translate param: new_bounds; type: simple_byref_const
+  CefRect new_boundsVal = new_bounds ? *new_bounds : CefRect();
+
+  // Execute
+  CefButtonDelegateCppToC::Get(reinterpret_cast<cef_button_delegate_t*>(self))
+      ->OnLayoutChanged(CefViewCToCpp::Wrap(view), new_boundsVal);
+}
+
 void CEF_CALLBACK button_delegate_on_focus(struct _cef_view_delegate_t* self,
                                            cef_view_t* view) {
   shutdown_checker::AssertNotShutdown();
@@ -220,12 +292,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefButtonDelegateCppToC::Get(reinterpret_cast<cef_button_delegate_t*>(self))
@@ -239,12 +313,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefButtonDelegateCppToC::Get(reinterpret_cast<cef_button_delegate_t*>(self))
@@ -267,6 +343,8 @@
       button_delegate_on_parent_view_changed;
   GetStruct()->base.on_child_view_changed =
       button_delegate_on_child_view_changed;
+  GetStruct()->base.on_window_changed = button_delegate_on_window_changed;
+  GetStruct()->base.on_layout_changed = button_delegate_on_layout_changed;
   GetStruct()->base.on_focus = button_delegate_on_focus;
   GetStruct()->base.on_blur = button_delegate_on_blur;
 }
@@ -287,7 +365,7 @@
     return CefMenuButtonDelegateCppToC::Unwrap(
         reinterpret_cast<cef_menu_button_delegate_t*>(s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/button_delegate_cpptoc.h b/src/libcef_dll/cpptoc/views/button_delegate_cpptoc.h
index b4da9c6..b342d8c 100644
--- a/src/libcef_dll/cpptoc/views/button_delegate_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/button_delegate_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2d19c78b51c5a0d9606a4e6c18153e37300fbf9f$
+// $hash=455b4eb400cc642cfb4cf0089b12059b8be31af6$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_BUTTON_DELEGATE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/display_cpptoc.cc b/src/libcef_dll/cpptoc/views/display_cpptoc.cc
index 59bc325..e056d24 100644
--- a/src/libcef_dll/cpptoc/views/display_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/display_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d4f5ea07778b1ad3a08a1826dced47de771f9b02$
+// $hash=bddabd9fc04400c15bd2ea41f2677c110dadb299$
 //
 
 #include "libcef_dll/cpptoc/views/display_cpptoc.h"
@@ -39,8 +39,9 @@
 
   // Verify param: point; type: simple_byref_const
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return NULL;
+  }
 
   // Translate param: point; type: simple_byref_const
   CefPoint pointVal = point ? *point : CefPoint();
@@ -62,8 +63,9 @@
 
   // Verify param: bounds; type: simple_byref_const
   DCHECK(bounds);
-  if (!bounds)
+  if (!bounds) {
     return NULL;
+  }
 
   // Translate param: bounds; type: simple_byref_const
   CefRect boundsVal = bounds ? *bounds : CefRect();
@@ -96,8 +98,9 @@
 
   // Verify param: displays; type: refptr_vec_same_byref
   DCHECK(displaysCount && (*displaysCount == 0 || displays));
-  if (!displaysCount || (*displaysCount > 0 && !displays))
+  if (!displaysCount || (*displaysCount > 0 && !displays)) {
     return;
+  }
 
   // Translate param: displays; type: refptr_vec_same_byref
   std::vector<CefRefPtr<CefDisplay>> displaysList;
@@ -121,21 +124,110 @@
   }
 }
 
+CEF_EXPORT cef_point_t
+cef_display_convert_screen_point_to_pixels(const cef_point_t* point) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: point; type: simple_byref_const
+  DCHECK(point);
+  if (!point) {
+    return CefPoint();
+  }
+
+  // Translate param: point; type: simple_byref_const
+  CefPoint pointVal = point ? *point : CefPoint();
+
+  // Execute
+  cef_point_t _retval = CefDisplay::ConvertScreenPointToPixels(pointVal);
+
+  // Return type: simple
+  return _retval;
+}
+
+CEF_EXPORT cef_point_t
+cef_display_convert_screen_point_from_pixels(const cef_point_t* point) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: point; type: simple_byref_const
+  DCHECK(point);
+  if (!point) {
+    return CefPoint();
+  }
+
+  // Translate param: point; type: simple_byref_const
+  CefPoint pointVal = point ? *point : CefPoint();
+
+  // Execute
+  cef_point_t _retval = CefDisplay::ConvertScreenPointFromPixels(pointVal);
+
+  // Return type: simple
+  return _retval;
+}
+
+CEF_EXPORT cef_rect_t
+cef_display_convert_screen_rect_to_pixels(const cef_rect_t* rect) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: rect; type: simple_byref_const
+  DCHECK(rect);
+  if (!rect) {
+    return CefRect();
+  }
+
+  // Translate param: rect; type: simple_byref_const
+  CefRect rectVal = rect ? *rect : CefRect();
+
+  // Execute
+  cef_rect_t _retval = CefDisplay::ConvertScreenRectToPixels(rectVal);
+
+  // Return type: simple
+  return _retval;
+}
+
+CEF_EXPORT cef_rect_t
+cef_display_convert_screen_rect_from_pixels(const cef_rect_t* rect) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: rect; type: simple_byref_const
+  DCHECK(rect);
+  if (!rect) {
+    return CefRect();
+  }
+
+  // Translate param: rect; type: simple_byref_const
+  CefRect rectVal = rect ? *rect : CefRect();
+
+  // Execute
+  cef_rect_t _retval = CefDisplay::ConvertScreenRectFromPixels(rectVal);
+
+  // Return type: simple
+  return _retval;
+}
+
 namespace {
 
 // MEMBER FUNCTIONS - Body may be edited by hand.
 
-int64 CEF_CALLBACK display_get_id(struct _cef_display_t* self) {
+int64_t CEF_CALLBACK display_get_id(struct _cef_display_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
-  int64 _retval = CefDisplayCppToC::Get(self)->GetID();
+  int64_t _retval = CefDisplayCppToC::Get(self)->GetID();
 
   // Return type: simple
   return _retval;
@@ -148,8 +240,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   float _retval = CefDisplayCppToC::Get(self)->GetDeviceScaleFactor();
@@ -165,12 +258,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -179,8 +274,9 @@
   CefDisplayCppToC::Get(self)->ConvertPointToPixels(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 }
 
 void CEF_CALLBACK display_convert_point_from_pixels(struct _cef_display_t* self,
@@ -190,12 +286,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -204,8 +302,9 @@
   CefDisplayCppToC::Get(self)->ConvertPointFromPixels(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 }
 
 cef_rect_t CEF_CALLBACK display_get_bounds(struct _cef_display_t* self) {
@@ -214,8 +313,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval = CefDisplayCppToC::Get(self)->GetBounds();
@@ -230,8 +330,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval = CefDisplayCppToC::Get(self)->GetWorkArea();
@@ -246,8 +347,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefDisplayCppToC::Get(self)->GetRotation();
@@ -281,7 +383,7 @@
 CefCppToCRefCounted<CefDisplayCppToC, CefDisplay, cef_display_t>::UnwrapDerived(
     CefWrapperType type,
     cef_display_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/display_cpptoc.h b/src/libcef_dll/cpptoc/views/display_cpptoc.h
index ec5a038..13eb6a6 100644
--- a/src/libcef_dll/cpptoc/views/display_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/display_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=79e090cec779d0e737ebbf4bd303d5e70b4c9b5f$
+// $hash=73811073aeb490787e777b5e7f8e41ef34cd6369$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_DISPLAY_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/fill_layout_cpptoc.cc b/src/libcef_dll/cpptoc/views/fill_layout_cpptoc.cc
index b120278..99cc9dd 100644
--- a/src/libcef_dll/cpptoc/views/fill_layout_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/fill_layout_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=cb375aa1dd0f29b5c43133bf6763bb2a0bb920bd$
+// $hash=3107bde9f33663e0141afa3fef9051c53eac11d8$
 //
 
 #include "libcef_dll/cpptoc/views/fill_layout_cpptoc.h"
@@ -27,8 +27,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBoxLayout> _retval =
@@ -46,8 +47,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefFillLayout> _retval =
@@ -64,8 +66,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -96,7 +99,7 @@
 CefRefPtr<CefFillLayout>
 CefCppToCRefCounted<CefFillLayoutCppToC, CefFillLayout, cef_fill_layout_t>::
     UnwrapDerived(CefWrapperType type, cef_fill_layout_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/fill_layout_cpptoc.h b/src/libcef_dll/cpptoc/views/fill_layout_cpptoc.h
index a4ba76e..a695842 100644
--- a/src/libcef_dll/cpptoc/views/fill_layout_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/fill_layout_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f9e4f2b10d60816bbd13c2545527e0619201b0ea$
+// $hash=88b95199af576610e6ce7e71603fb3c8b1426046$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_FILL_LAYOUT_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/label_button_cpptoc.cc b/src/libcef_dll/cpptoc/views/label_button_cpptoc.cc
index 7dc8013..dfb6fc3 100644
--- a/src/libcef_dll/cpptoc/views/label_button_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/label_button_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=5d0c0d1982ef193450f5b331f6ad378ddbd8dbcc$
+// $hash=44c962ffbc0ae5b8e7870d5e1845fd339196fbac$
 //
 
 #include "libcef_dll/cpptoc/views/label_button_cpptoc.h"
@@ -37,8 +37,9 @@
 
   // Verify param: delegate; type: refptr_diff
   DCHECK(delegate);
-  if (!delegate)
+  if (!delegate) {
     return NULL;
+  }
   // Unverified params: text
 
   // Execute
@@ -60,8 +61,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefMenuButton> _retval =
@@ -78,12 +80,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: text; type: string_byref_const
   DCHECK(text);
-  if (!text)
+  if (!text) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(self)->SetText(CefString(text));
@@ -96,8 +100,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefLabelButtonCppToC::Get(self)->GetText();
@@ -114,8 +119,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: image
 
   // Execute
@@ -131,8 +137,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefImage> _retval =
@@ -150,8 +157,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(self)->SetTextColor(for_state, color);
@@ -165,8 +173,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(self)->SetEnabledTextColors(color);
@@ -179,12 +188,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: font_list; type: string_byref_const
   DCHECK(font_list);
-  if (!font_list)
+  if (!font_list) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(self)->SetFontList(CefString(font_list));
@@ -198,8 +209,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(self)->SetHorizontalAlignment(alignment);
@@ -213,12 +225,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: size; type: simple_byref_const
   DCHECK(size);
-  if (!size)
+  if (!size) {
     return;
+  }
 
   // Translate param: size; type: simple_byref_const
   CefSize sizeVal = size ? *size : CefSize();
@@ -235,12 +249,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: size; type: simple_byref_const
   DCHECK(size);
-  if (!size)
+  if (!size) {
     return;
+  }
 
   // Translate param: size; type: simple_byref_const
   CefSize sizeVal = size ? *size : CefSize();
@@ -256,8 +272,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefLabelButton> _retval =
@@ -275,8 +292,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(reinterpret_cast<cef_label_button_t*>(self))
@@ -290,8 +308,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CEF_BUTTON_STATE_NORMAL;
+  }
 
   // Execute
   cef_button_state_t _retval =
@@ -309,8 +328,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(reinterpret_cast<cef_label_button_t*>(self))
@@ -325,12 +345,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: tooltip_text; type: string_byref_const
   DCHECK(tooltip_text);
-  if (!tooltip_text)
+  if (!tooltip_text) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(reinterpret_cast<cef_label_button_t*>(self))
@@ -344,12 +366,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(reinterpret_cast<cef_label_button_t*>(self))
@@ -363,8 +387,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowserView> _retval =
@@ -381,8 +406,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefButton> _retval =
@@ -399,8 +425,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefPanel> _retval =
@@ -418,8 +445,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefScrollView> _retval =
@@ -437,8 +465,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTextfield> _retval =
@@ -456,8 +485,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -475,8 +505,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -493,8 +524,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -511,8 +543,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -530,12 +563,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -553,8 +588,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefViewDelegate> _retval =
@@ -572,8 +608,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefWindow> _retval =
@@ -590,8 +627,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -608,8 +646,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(reinterpret_cast<cef_label_button_t*>(self))
@@ -622,8 +661,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -641,8 +681,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(reinterpret_cast<cef_label_button_t*>(self))
@@ -656,8 +697,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -675,8 +717,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -694,12 +737,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: bounds; type: simple_byref_const
   DCHECK(bounds);
-  if (!bounds)
+  if (!bounds) {
     return;
+  }
 
   // Translate param: bounds; type: simple_byref_const
   CefRect boundsVal = bounds ? *bounds : CefRect();
@@ -715,8 +760,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval =
@@ -734,8 +780,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval =
@@ -753,12 +800,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: size; type: simple_byref_const
   DCHECK(size);
-  if (!size)
+  if (!size) {
     return;
+  }
 
   // Translate param: size; type: simple_byref_const
   CefSize sizeVal = size ? *size : CefSize();
@@ -774,8 +823,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -793,12 +843,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: position; type: simple_byref_const
   DCHECK(position);
-  if (!position)
+  if (!position) {
     return;
+  }
 
   // Translate param: position; type: simple_byref_const
   CefPoint positionVal = position ? *position : CefPoint();
@@ -814,8 +866,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefPoint();
+  }
 
   // Execute
   cef_point_t _retval =
@@ -826,6 +879,49 @@
   return _retval;
 }
 
+void CEF_CALLBACK label_button_set_insets(struct _cef_view_t* self,
+                                          const cef_insets_t* insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: insets; type: simple_byref_const
+  DCHECK(insets);
+  if (!insets) {
+    return;
+  }
+
+  // Translate param: insets; type: simple_byref_const
+  CefInsets insetsVal = insets ? *insets : CefInsets();
+
+  // Execute
+  CefLabelButtonCppToC::Get(reinterpret_cast<cef_label_button_t*>(self))
+      ->SetInsets(insetsVal);
+}
+
+cef_insets_t CEF_CALLBACK label_button_get_insets(struct _cef_view_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CefInsets();
+  }
+
+  // Execute
+  cef_insets_t _retval =
+      CefLabelButtonCppToC::Get(reinterpret_cast<cef_label_button_t*>(self))
+          ->GetInsets();
+
+  // Return type: simple
+  return _retval;
+}
+
 cef_size_t CEF_CALLBACK
 label_button_get_preferred_size(struct _cef_view_t* self) {
   shutdown_checker::AssertNotShutdown();
@@ -833,8 +929,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -852,8 +949,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(reinterpret_cast<cef_label_button_t*>(self))
@@ -867,8 +965,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -886,8 +985,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -905,8 +1005,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -923,8 +1024,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(reinterpret_cast<cef_label_button_t*>(self))
@@ -938,8 +1040,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(reinterpret_cast<cef_label_button_t*>(self))
@@ -952,8 +1055,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -970,8 +1074,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -989,8 +1094,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(reinterpret_cast<cef_label_button_t*>(self))
@@ -1003,8 +1109,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1022,8 +1129,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(reinterpret_cast<cef_label_button_t*>(self))
@@ -1036,8 +1144,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1055,8 +1164,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1073,8 +1183,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(reinterpret_cast<cef_label_button_t*>(self))
@@ -1088,8 +1199,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefLabelButtonCppToC::Get(reinterpret_cast<cef_label_button_t*>(self))
@@ -1103,8 +1215,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   cef_color_t _retval =
@@ -1122,12 +1235,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1138,8 +1253,9 @@
           ->ConvertPointToScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1153,12 +1269,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1169,8 +1287,9 @@
           ->ConvertPointFromScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1183,12 +1302,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1199,8 +1320,9 @@
           ->ConvertPointToWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1214,12 +1336,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1230,8 +1354,9 @@
           ->ConvertPointFromWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1245,16 +1370,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1265,8 +1393,9 @@
           ->ConvertPointToView(CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1280,16 +1409,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1300,8 +1432,9 @@
           ->ConvertPointFromView(CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1355,6 +1488,8 @@
   GetStruct()->base.base.get_size = label_button_get_size;
   GetStruct()->base.base.set_position = label_button_set_position;
   GetStruct()->base.base.get_position = label_button_get_position;
+  GetStruct()->base.base.set_insets = label_button_set_insets;
+  GetStruct()->base.base.get_insets = label_button_get_insets;
   GetStruct()->base.base.get_preferred_size = label_button_get_preferred_size;
   GetStruct()->base.base.size_to_preferred_size =
       label_button_size_to_preferred_size;
@@ -1404,7 +1539,7 @@
   if (type == WT_MENU_BUTTON) {
     return CefMenuButtonCppToC::Unwrap(reinterpret_cast<cef_menu_button_t*>(s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/label_button_cpptoc.h b/src/libcef_dll/cpptoc/views/label_button_cpptoc.h
index e625878..dad5d89 100644
--- a/src/libcef_dll/cpptoc/views/label_button_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/label_button_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2e89e27310c9cf4b1663f74dd642382c9e1112f2$
+// $hash=8e86fa292ee6e5debd2525e71eaa3ae8e42c8e55$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_LABEL_BUTTON_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/layout_cpptoc.cc b/src/libcef_dll/cpptoc/views/layout_cpptoc.cc
index 0fbc92f..40a7e37 100644
--- a/src/libcef_dll/cpptoc/views/layout_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/layout_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b690e5907fc196ab782442abcc218bf296537625$
+// $hash=6369dff04489cebf256d28015e676f2a5c09f48e$
 //
 
 #include "libcef_dll/cpptoc/views/layout_cpptoc.h"
@@ -28,8 +28,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBoxLayout> _retval = CefLayoutCppToC::Get(self)->AsBoxLayout();
@@ -45,8 +46,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefFillLayout> _retval = CefLayoutCppToC::Get(self)->AsFillLayout();
@@ -61,8 +63,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefLayoutCppToC::Get(self)->IsValid();
@@ -98,7 +101,7 @@
   if (type == WT_FILL_LAYOUT) {
     return CefFillLayoutCppToC::Unwrap(reinterpret_cast<cef_fill_layout_t*>(s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/layout_cpptoc.h b/src/libcef_dll/cpptoc/views/layout_cpptoc.h
index 329de4b..76c9930 100644
--- a/src/libcef_dll/cpptoc/views/layout_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/layout_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d8ff67a7549ec8e5cea4e089a9942acaed9cb466$
+// $hash=d0adda3ed7bbb825b0c9959960f832d23f75ccdc$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_LAYOUT_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/menu_button_cpptoc.cc b/src/libcef_dll/cpptoc/views/menu_button_cpptoc.cc
index b4418fd..84b51b4 100644
--- a/src/libcef_dll/cpptoc/views/menu_button_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/menu_button_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=47415544c8e36043a2a115453055bf98b888ecf1$
+// $hash=c386e6143a554182ff6e4beb9e8dd813a5753a55$
 //
 
 #include "libcef_dll/cpptoc/views/menu_button_cpptoc.h"
@@ -38,8 +38,9 @@
 
   // Verify param: delegate; type: refptr_diff
   DCHECK(delegate);
-  if (!delegate)
+  if (!delegate) {
     return NULL;
+  }
   // Unverified params: text
 
   // Execute
@@ -64,16 +65,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: menu_model; type: refptr_same
   DCHECK(menu_model);
-  if (!menu_model)
+  if (!menu_model) {
     return;
+  }
   // Verify param: screen_point; type: simple_byref_const
   DCHECK(screen_point);
-  if (!screen_point)
+  if (!screen_point) {
     return;
+  }
 
   // Translate param: screen_point; type: simple_byref_const
   CefPoint screen_pointVal = screen_point ? *screen_point : CefPoint();
@@ -89,8 +93,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(self)->TriggerMenu();
@@ -103,8 +108,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefMenuButton> _retval =
@@ -122,12 +128,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: text; type: string_byref_const
   DCHECK(text);
-  if (!text)
+  if (!text) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -141,8 +149,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -161,8 +170,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: image
 
   // Execute
@@ -178,8 +188,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefImage> _retval =
@@ -198,8 +209,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -214,8 +226,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -229,12 +242,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: font_list; type: string_byref_const
   DCHECK(font_list);
-  if (!font_list)
+  if (!font_list) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -249,8 +264,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -264,12 +280,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: size; type: simple_byref_const
   DCHECK(size);
-  if (!size)
+  if (!size) {
     return;
+  }
 
   // Translate param: size; type: simple_byref_const
   CefSize sizeVal = size ? *size : CefSize();
@@ -286,12 +304,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: size; type: simple_byref_const
   DCHECK(size);
-  if (!size)
+  if (!size) {
     return;
+  }
 
   // Translate param: size; type: simple_byref_const
   CefSize sizeVal = size ? *size : CefSize();
@@ -308,8 +328,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefLabelButton> _retval =
@@ -327,8 +348,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -342,8 +364,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CEF_BUTTON_STATE_NORMAL;
+  }
 
   // Execute
   cef_button_state_t _retval =
@@ -361,8 +384,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -377,12 +401,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: tooltip_text; type: string_byref_const
   DCHECK(tooltip_text);
-  if (!tooltip_text)
+  if (!tooltip_text) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -396,12 +422,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -415,8 +443,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowserView> _retval =
@@ -433,8 +462,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefButton> _retval =
@@ -451,8 +481,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefPanel> _retval =
@@ -470,8 +501,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefScrollView> _retval =
@@ -489,8 +521,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTextfield> _retval =
@@ -508,8 +541,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -527,8 +561,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -545,8 +580,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -563,8 +599,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -582,12 +619,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -605,8 +644,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefViewDelegate> _retval =
@@ -624,8 +664,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefWindow> _retval =
@@ -642,8 +683,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -660,8 +702,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -674,8 +717,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -693,8 +737,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -708,8 +753,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -727,8 +773,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -746,12 +793,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: bounds; type: simple_byref_const
   DCHECK(bounds);
-  if (!bounds)
+  if (!bounds) {
     return;
+  }
 
   // Translate param: bounds; type: simple_byref_const
   CefRect boundsVal = bounds ? *bounds : CefRect();
@@ -767,8 +816,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval =
@@ -786,8 +836,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval =
@@ -805,12 +856,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: size; type: simple_byref_const
   DCHECK(size);
-  if (!size)
+  if (!size) {
     return;
+  }
 
   // Translate param: size; type: simple_byref_const
   CefSize sizeVal = size ? *size : CefSize();
@@ -826,8 +879,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -845,12 +899,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: position; type: simple_byref_const
   DCHECK(position);
-  if (!position)
+  if (!position) {
     return;
+  }
 
   // Translate param: position; type: simple_byref_const
   CefPoint positionVal = position ? *position : CefPoint();
@@ -866,8 +922,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefPoint();
+  }
 
   // Execute
   cef_point_t _retval =
@@ -878,6 +935,49 @@
   return _retval;
 }
 
+void CEF_CALLBACK menu_button_set_insets(struct _cef_view_t* self,
+                                         const cef_insets_t* insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: insets; type: simple_byref_const
+  DCHECK(insets);
+  if (!insets) {
+    return;
+  }
+
+  // Translate param: insets; type: simple_byref_const
+  CefInsets insetsVal = insets ? *insets : CefInsets();
+
+  // Execute
+  CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
+      ->SetInsets(insetsVal);
+}
+
+cef_insets_t CEF_CALLBACK menu_button_get_insets(struct _cef_view_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CefInsets();
+  }
+
+  // Execute
+  cef_insets_t _retval =
+      CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
+          ->GetInsets();
+
+  // Return type: simple
+  return _retval;
+}
+
 cef_size_t CEF_CALLBACK
 menu_button_get_preferred_size(struct _cef_view_t* self) {
   shutdown_checker::AssertNotShutdown();
@@ -885,8 +985,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -903,8 +1004,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -917,8 +1019,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -935,8 +1038,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -954,8 +1058,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -972,8 +1077,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -987,8 +1093,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -1001,8 +1108,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1019,8 +1127,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1038,8 +1147,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -1052,8 +1162,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1071,8 +1182,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -1085,8 +1197,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1104,8 +1217,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1122,8 +1236,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -1137,8 +1252,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefMenuButtonCppToC::Get(reinterpret_cast<cef_menu_button_t*>(self))
@@ -1152,8 +1268,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   cef_color_t _retval =
@@ -1171,12 +1288,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1187,8 +1306,9 @@
           ->ConvertPointToScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1201,12 +1321,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1217,8 +1339,9 @@
           ->ConvertPointFromScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1231,12 +1354,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1247,8 +1372,9 @@
           ->ConvertPointToWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1261,12 +1387,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1277,8 +1405,9 @@
           ->ConvertPointFromWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1292,16 +1421,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1312,8 +1444,9 @@
           ->ConvertPointToView(CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1327,16 +1460,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1347,8 +1483,9 @@
           ->ConvertPointFromView(CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1407,6 +1544,8 @@
   GetStruct()->base.base.base.get_size = menu_button_get_size;
   GetStruct()->base.base.base.set_position = menu_button_set_position;
   GetStruct()->base.base.base.get_position = menu_button_get_position;
+  GetStruct()->base.base.base.set_insets = menu_button_set_insets;
+  GetStruct()->base.base.base.get_insets = menu_button_get_insets;
   GetStruct()->base.base.base.get_preferred_size =
       menu_button_get_preferred_size;
   GetStruct()->base.base.base.size_to_preferred_size =
@@ -1454,7 +1593,7 @@
 CefRefPtr<CefMenuButton>
 CefCppToCRefCounted<CefMenuButtonCppToC, CefMenuButton, cef_menu_button_t>::
     UnwrapDerived(CefWrapperType type, cef_menu_button_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/menu_button_cpptoc.h b/src/libcef_dll/cpptoc/views/menu_button_cpptoc.h
index fb655ac..52f93e0 100644
--- a/src/libcef_dll/cpptoc/views/menu_button_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/menu_button_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9759a92b82addfcf2c75b3f8ae7d9164c9ffb338$
+// $hash=f2f44594e4cbcb3ef1ee3eb39d3d498f7a6cafbc$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_MENU_BUTTON_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/menu_button_delegate_cpptoc.cc b/src/libcef_dll/cpptoc/views/menu_button_delegate_cpptoc.cc
index b70103f..7aba939 100644
--- a/src/libcef_dll/cpptoc/views/menu_button_delegate_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/menu_button_delegate_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b434cff14ab679afd18ea45fa06e37cdfe063270$
+// $hash=bc673e6ca9a0a67ef0ac5b95a6618575ed79daf5$
 //
 
 #include "libcef_dll/cpptoc/views/menu_button_delegate_cpptoc.h"
@@ -33,20 +33,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: menu_button; type: refptr_diff
   DCHECK(menu_button);
-  if (!menu_button)
+  if (!menu_button) {
     return;
+  }
   // Verify param: screen_point; type: simple_byref_const
   DCHECK(screen_point);
-  if (!screen_point)
+  if (!screen_point) {
     return;
+  }
   // Verify param: button_pressed_lock; type: refptr_diff
   DCHECK(button_pressed_lock);
-  if (!button_pressed_lock)
+  if (!button_pressed_lock) {
     return;
+  }
 
   // Translate param: screen_point; type: simple_byref_const
   CefPoint screen_pointVal = screen_point ? *screen_point : CefPoint();
@@ -65,12 +69,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: button; type: refptr_diff
   DCHECK(button);
-  if (!button)
+  if (!button) {
     return;
+  }
 
   // Execute
   CefMenuButtonDelegateCppToC::Get(
@@ -86,12 +92,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: button; type: refptr_diff
   DCHECK(button);
-  if (!button)
+  if (!button) {
     return;
+  }
 
   // Execute
   CefMenuButtonDelegateCppToC::Get(
@@ -107,12 +115,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefMenuButtonDelegateCppToC::Get(
@@ -131,12 +141,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefMenuButtonDelegateCppToC::Get(
@@ -155,12 +167,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefMenuButtonDelegateCppToC::Get(
@@ -180,12 +194,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
 
   // Execute
   int _retval = CefMenuButtonDelegateCppToC::Get(
@@ -206,16 +222,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
   // Verify param: parent; type: refptr_diff
   DCHECK(parent);
-  if (!parent)
+  if (!parent) {
     return;
+  }
 
   // Execute
   CefMenuButtonDelegateCppToC::Get(
@@ -234,16 +253,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
   // Verify param: child; type: refptr_diff
   DCHECK(child);
-  if (!child)
+  if (!child) {
     return;
+  }
 
   // Execute
   CefMenuButtonDelegateCppToC::Get(
@@ -253,6 +275,62 @@
 }
 
 void CEF_CALLBACK
+menu_button_delegate_on_window_changed(struct _cef_view_delegate_t* self,
+                                       cef_view_t* view,
+                                       int added) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: view; type: refptr_diff
+  DCHECK(view);
+  if (!view) {
+    return;
+  }
+
+  // Execute
+  CefMenuButtonDelegateCppToC::Get(
+      reinterpret_cast<cef_menu_button_delegate_t*>(self))
+      ->OnWindowChanged(CefViewCToCpp::Wrap(view), added ? true : false);
+}
+
+void CEF_CALLBACK
+menu_button_delegate_on_layout_changed(struct _cef_view_delegate_t* self,
+                                       cef_view_t* view,
+                                       const cef_rect_t* new_bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: view; type: refptr_diff
+  DCHECK(view);
+  if (!view) {
+    return;
+  }
+  // Verify param: new_bounds; type: simple_byref_const
+  DCHECK(new_bounds);
+  if (!new_bounds) {
+    return;
+  }
+
+  // Translate param: new_bounds; type: simple_byref_const
+  CefRect new_boundsVal = new_bounds ? *new_bounds : CefRect();
+
+  // Execute
+  CefMenuButtonDelegateCppToC::Get(
+      reinterpret_cast<cef_menu_button_delegate_t*>(self))
+      ->OnLayoutChanged(CefViewCToCpp::Wrap(view), new_boundsVal);
+}
+
+void CEF_CALLBACK
 menu_button_delegate_on_focus(struct _cef_view_delegate_t* self,
                               cef_view_t* view) {
   shutdown_checker::AssertNotShutdown();
@@ -260,12 +338,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefMenuButtonDelegateCppToC::Get(
@@ -281,12 +361,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefMenuButtonDelegateCppToC::Get(
@@ -316,6 +398,10 @@
       menu_button_delegate_on_parent_view_changed;
   GetStruct()->base.base.on_child_view_changed =
       menu_button_delegate_on_child_view_changed;
+  GetStruct()->base.base.on_window_changed =
+      menu_button_delegate_on_window_changed;
+  GetStruct()->base.base.on_layout_changed =
+      menu_button_delegate_on_layout_changed;
   GetStruct()->base.base.on_focus = menu_button_delegate_on_focus;
   GetStruct()->base.base.on_blur = menu_button_delegate_on_blur;
 }
@@ -332,7 +418,7 @@
     CefMenuButtonDelegate,
     cef_menu_button_delegate_t>::UnwrapDerived(CefWrapperType type,
                                                cef_menu_button_delegate_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/menu_button_delegate_cpptoc.h b/src/libcef_dll/cpptoc/views/menu_button_delegate_cpptoc.h
index a0b19b9..5f70f5a 100644
--- a/src/libcef_dll/cpptoc/views/menu_button_delegate_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/menu_button_delegate_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f66bb8cf66c62d799895d08ba65743b1b3a8df4f$
+// $hash=9178b58c1b03965fc20636f3efd97c2385618574$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_MENU_BUTTON_DELEGATE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/menu_button_pressed_lock_cpptoc.cc b/src/libcef_dll/cpptoc/views/menu_button_pressed_lock_cpptoc.cc
index f5c9fff..e35fc0e 100644
--- a/src/libcef_dll/cpptoc/views/menu_button_pressed_lock_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/menu_button_pressed_lock_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=85de615d0f69853565613b907ca8ed785996726f$
+// $hash=b0777f496f71e5770150561ce6bbb37caff94182$
 //
 
 #include "libcef_dll/cpptoc/views/menu_button_pressed_lock_cpptoc.h"
@@ -31,7 +31,7 @@
                     CefMenuButtonPressedLock,
                     cef_menu_button_pressed_lock_t>::
     UnwrapDerived(CefWrapperType type, cef_menu_button_pressed_lock_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/menu_button_pressed_lock_cpptoc.h b/src/libcef_dll/cpptoc/views/menu_button_pressed_lock_cpptoc.h
index a2a3aab..79a8566 100644
--- a/src/libcef_dll/cpptoc/views/menu_button_pressed_lock_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/menu_button_pressed_lock_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9dad26affe3481306f8d876256dcf09b06dea18b$
+// $hash=5d7f30f1265294fc8617b444bd35bee3da172746$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_MENU_BUTTON_PRESSED_LOCK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/overlay_controller_cpptoc.cc b/src/libcef_dll/cpptoc/views/overlay_controller_cpptoc.cc
new file mode 100644
index 0000000..b0007ee
--- /dev/null
+++ b/src/libcef_dll/cpptoc/views/overlay_controller_cpptoc.cc
@@ -0,0 +1,440 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=714f6a3397b0c294cf77f23061d07c3e9b548989$
+//
+
+#include "libcef_dll/cpptoc/views/overlay_controller_cpptoc.h"
+#include "libcef_dll/cpptoc/views/view_cpptoc.h"
+#include "libcef_dll/cpptoc/views/window_cpptoc.h"
+#include "libcef_dll/shutdown_checker.h"
+
+namespace {
+
+// MEMBER FUNCTIONS - Body may be edited by hand.
+
+int CEF_CALLBACK
+overlay_controller_is_valid(struct _cef_overlay_controller_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefOverlayControllerCppToC::Get(self)->IsValid();
+
+  // Return type: bool
+  return _retval;
+}
+
+int CEF_CALLBACK
+overlay_controller_is_same(struct _cef_overlay_controller_t* self,
+                           struct _cef_overlay_controller_t* that) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: that; type: refptr_same
+  DCHECK(that);
+  if (!that) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefOverlayControllerCppToC::Get(self)->IsSame(
+      CefOverlayControllerCppToC::Unwrap(that));
+
+  // Return type: bool
+  return _retval;
+}
+
+struct _cef_view_t* CEF_CALLBACK
+overlay_controller_get_contents_view(struct _cef_overlay_controller_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefView> _retval =
+      CefOverlayControllerCppToC::Get(self)->GetContentsView();
+
+  // Return type: refptr_same
+  return CefViewCppToC::Wrap(_retval);
+}
+
+struct _cef_window_t* CEF_CALLBACK
+overlay_controller_get_window(struct _cef_overlay_controller_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefWindow> _retval =
+      CefOverlayControllerCppToC::Get(self)->GetWindow();
+
+  // Return type: refptr_same
+  return CefWindowCppToC::Wrap(_retval);
+}
+
+cef_docking_mode_t CEF_CALLBACK
+overlay_controller_get_docking_mode(struct _cef_overlay_controller_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CEF_DOCKING_MODE_TOP_LEFT;
+  }
+
+  // Execute
+  cef_docking_mode_t _retval =
+      CefOverlayControllerCppToC::Get(self)->GetDockingMode();
+
+  // Return type: simple
+  return _retval;
+}
+
+void CEF_CALLBACK
+overlay_controller_destroy(struct _cef_overlay_controller_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+
+  // Execute
+  CefOverlayControllerCppToC::Get(self)->Destroy();
+}
+
+void CEF_CALLBACK
+overlay_controller_set_bounds(struct _cef_overlay_controller_t* self,
+                              const cef_rect_t* bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: bounds; type: simple_byref_const
+  DCHECK(bounds);
+  if (!bounds) {
+    return;
+  }
+
+  // Translate param: bounds; type: simple_byref_const
+  CefRect boundsVal = bounds ? *bounds : CefRect();
+
+  // Execute
+  CefOverlayControllerCppToC::Get(self)->SetBounds(boundsVal);
+}
+
+cef_rect_t CEF_CALLBACK
+overlay_controller_get_bounds(struct _cef_overlay_controller_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CefRect();
+  }
+
+  // Execute
+  cef_rect_t _retval = CefOverlayControllerCppToC::Get(self)->GetBounds();
+
+  // Return type: simple
+  return _retval;
+}
+
+cef_rect_t CEF_CALLBACK overlay_controller_get_bounds_in_screen(
+    struct _cef_overlay_controller_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CefRect();
+  }
+
+  // Execute
+  cef_rect_t _retval =
+      CefOverlayControllerCppToC::Get(self)->GetBoundsInScreen();
+
+  // Return type: simple
+  return _retval;
+}
+
+void CEF_CALLBACK
+overlay_controller_set_size(struct _cef_overlay_controller_t* self,
+                            const cef_size_t* size) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: size; type: simple_byref_const
+  DCHECK(size);
+  if (!size) {
+    return;
+  }
+
+  // Translate param: size; type: simple_byref_const
+  CefSize sizeVal = size ? *size : CefSize();
+
+  // Execute
+  CefOverlayControllerCppToC::Get(self)->SetSize(sizeVal);
+}
+
+cef_size_t CEF_CALLBACK
+overlay_controller_get_size(struct _cef_overlay_controller_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CefSize();
+  }
+
+  // Execute
+  cef_size_t _retval = CefOverlayControllerCppToC::Get(self)->GetSize();
+
+  // Return type: simple
+  return _retval;
+}
+
+void CEF_CALLBACK
+overlay_controller_set_position(struct _cef_overlay_controller_t* self,
+                                const cef_point_t* position) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: position; type: simple_byref_const
+  DCHECK(position);
+  if (!position) {
+    return;
+  }
+
+  // Translate param: position; type: simple_byref_const
+  CefPoint positionVal = position ? *position : CefPoint();
+
+  // Execute
+  CefOverlayControllerCppToC::Get(self)->SetPosition(positionVal);
+}
+
+cef_point_t CEF_CALLBACK
+overlay_controller_get_position(struct _cef_overlay_controller_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CefPoint();
+  }
+
+  // Execute
+  cef_point_t _retval = CefOverlayControllerCppToC::Get(self)->GetPosition();
+
+  // Return type: simple
+  return _retval;
+}
+
+void CEF_CALLBACK
+overlay_controller_set_insets(struct _cef_overlay_controller_t* self,
+                              const cef_insets_t* insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: insets; type: simple_byref_const
+  DCHECK(insets);
+  if (!insets) {
+    return;
+  }
+
+  // Translate param: insets; type: simple_byref_const
+  CefInsets insetsVal = insets ? *insets : CefInsets();
+
+  // Execute
+  CefOverlayControllerCppToC::Get(self)->SetInsets(insetsVal);
+}
+
+cef_insets_t CEF_CALLBACK
+overlay_controller_get_insets(struct _cef_overlay_controller_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CefInsets();
+  }
+
+  // Execute
+  cef_insets_t _retval = CefOverlayControllerCppToC::Get(self)->GetInsets();
+
+  // Return type: simple
+  return _retval;
+}
+
+void CEF_CALLBACK overlay_controller_size_to_preferred_size(
+    struct _cef_overlay_controller_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+
+  // Execute
+  CefOverlayControllerCppToC::Get(self)->SizeToPreferredSize();
+}
+
+void CEF_CALLBACK
+overlay_controller_set_visible(struct _cef_overlay_controller_t* self,
+                               int visible) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+
+  // Execute
+  CefOverlayControllerCppToC::Get(self)->SetVisible(visible ? true : false);
+}
+
+int CEF_CALLBACK
+overlay_controller_is_visible(struct _cef_overlay_controller_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefOverlayControllerCppToC::Get(self)->IsVisible();
+
+  // Return type: bool
+  return _retval;
+}
+
+int CEF_CALLBACK
+overlay_controller_is_drawn(struct _cef_overlay_controller_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefOverlayControllerCppToC::Get(self)->IsDrawn();
+
+  // Return type: bool
+  return _retval;
+}
+
+}  // namespace
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefOverlayControllerCppToC::CefOverlayControllerCppToC() {
+  GetStruct()->is_valid = overlay_controller_is_valid;
+  GetStruct()->is_same = overlay_controller_is_same;
+  GetStruct()->get_contents_view = overlay_controller_get_contents_view;
+  GetStruct()->get_window = overlay_controller_get_window;
+  GetStruct()->get_docking_mode = overlay_controller_get_docking_mode;
+  GetStruct()->destroy = overlay_controller_destroy;
+  GetStruct()->set_bounds = overlay_controller_set_bounds;
+  GetStruct()->get_bounds = overlay_controller_get_bounds;
+  GetStruct()->get_bounds_in_screen = overlay_controller_get_bounds_in_screen;
+  GetStruct()->set_size = overlay_controller_set_size;
+  GetStruct()->get_size = overlay_controller_get_size;
+  GetStruct()->set_position = overlay_controller_set_position;
+  GetStruct()->get_position = overlay_controller_get_position;
+  GetStruct()->set_insets = overlay_controller_set_insets;
+  GetStruct()->get_insets = overlay_controller_get_insets;
+  GetStruct()->size_to_preferred_size =
+      overlay_controller_size_to_preferred_size;
+  GetStruct()->set_visible = overlay_controller_set_visible;
+  GetStruct()->is_visible = overlay_controller_is_visible;
+  GetStruct()->is_drawn = overlay_controller_is_drawn;
+}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefOverlayControllerCppToC::~CefOverlayControllerCppToC() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+CefRefPtr<CefOverlayController> CefCppToCRefCounted<
+    CefOverlayControllerCppToC,
+    CefOverlayController,
+    cef_overlay_controller_t>::UnwrapDerived(CefWrapperType type,
+                                             cef_overlay_controller_t* s) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCppToCRefCounted<CefOverlayControllerCppToC,
+                                   CefOverlayController,
+                                   cef_overlay_controller_t>::kWrapperType =
+    WT_OVERLAY_CONTROLLER;
diff --git a/src/libcef_dll/cpptoc/views/overlay_controller_cpptoc.h b/src/libcef_dll/cpptoc/views/overlay_controller_cpptoc.h
new file mode 100644
index 0000000..b89f8b4
--- /dev/null
+++ b/src/libcef_dll/cpptoc/views/overlay_controller_cpptoc.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=8d50609d2e79539752a8118f831e853b845892f4$
+//
+
+#ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_OVERLAY_CONTROLLER_CPPTOC_H_
+#define CEF_LIBCEF_DLL_CPPTOC_VIEWS_OVERLAY_CONTROLLER_CPPTOC_H_
+#pragma once
+
+#if !defined(BUILDING_CEF_SHARED)
+#error This file can be included DLL-side only
+#endif
+
+#include "include/capi/views/cef_overlay_controller_capi.h"
+#include "include/capi/views/cef_view_capi.h"
+#include "include/capi/views/cef_window_capi.h"
+#include "include/views/cef_overlay_controller.h"
+#include "include/views/cef_view.h"
+#include "include/views/cef_window.h"
+#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
+
+// Wrap a C++ class with a C structure.
+// This class may be instantiated and accessed DLL-side only.
+class CefOverlayControllerCppToC
+    : public CefCppToCRefCounted<CefOverlayControllerCppToC,
+                                 CefOverlayController,
+                                 cef_overlay_controller_t> {
+ public:
+  CefOverlayControllerCppToC();
+  virtual ~CefOverlayControllerCppToC();
+};
+
+#endif  // CEF_LIBCEF_DLL_CPPTOC_VIEWS_OVERLAY_CONTROLLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/panel_cpptoc.cc b/src/libcef_dll/cpptoc/views/panel_cpptoc.cc
index 8c8b168..ac3cda7 100644
--- a/src/libcef_dll/cpptoc/views/panel_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/panel_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=16383327a932a7da5991ac84d9689cea25318bdc$
+// $hash=fba634e939f8074f3a5ddc6717ac93dd9d5d502f$
 //
 
 #include "libcef_dll/cpptoc/views/panel_cpptoc.h"
@@ -53,8 +53,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefWindow> _retval = CefPanelCppToC::Get(self)->AsWindow();
@@ -70,8 +71,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefFillLayout> _retval =
@@ -83,27 +85,28 @@
 
 cef_box_layout_t* CEF_CALLBACK
 panel_set_to_box_layout(struct _cef_panel_t* self,
-                        const struct _cef_box_layout_settings_t* settings) {
+                        const cef_box_layout_settings_t* settings) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
-  // Verify param: settings; type: struct_byref_const
+  }
+  // Verify param: settings; type: simple_byref_const
   DCHECK(settings);
-  if (!settings)
+  if (!settings) {
     return NULL;
+  }
 
-  // Translate param: settings; type: struct_byref_const
-  CefBoxLayoutSettings settingsObj;
-  if (settings)
-    settingsObj.Set(*settings, false);
+  // Translate param: settings; type: simple_byref_const
+  CefBoxLayoutSettings settingsVal =
+      settings ? *settings : CefBoxLayoutSettings();
 
   // Execute
   CefRefPtr<CefBoxLayout> _retval =
-      CefPanelCppToC::Get(self)->SetToBoxLayout(settingsObj);
+      CefPanelCppToC::Get(self)->SetToBoxLayout(settingsVal);
 
   // Return type: refptr_same
   return CefBoxLayoutCppToC::Wrap(_retval);
@@ -115,8 +118,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefLayout> _retval = CefPanelCppToC::Get(self)->GetLayout();
@@ -131,8 +135,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPanelCppToC::Get(self)->Layout();
@@ -145,12 +150,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefPanelCppToC::Get(self)->AddChildView(CefViewCppToC::Unwrap(view));
@@ -164,16 +171,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return;
+  }
 
   // Execute
   CefPanelCppToC::Get(self)->AddChildViewAt(CefViewCppToC::Unwrap(view), index);
@@ -187,12 +197,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefPanelCppToC::Get(self)->ReorderChildView(CefViewCppToC::Unwrap(view),
@@ -206,12 +218,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefPanelCppToC::Get(self)->RemoveChildView(CefViewCppToC::Unwrap(view));
@@ -223,8 +237,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPanelCppToC::Get(self)->RemoveAllChildViews();
@@ -236,8 +251,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefPanelCppToC::Get(self)->GetChildViewCount();
@@ -253,12 +269,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval = CefPanelCppToC::Get(self)->GetChildViewAt(index);
@@ -274,8 +292,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowserView> _retval =
@@ -292,8 +311,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefButton> _retval =
@@ -309,8 +329,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefPanel> _retval =
@@ -326,8 +347,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefScrollView> _retval =
@@ -343,8 +365,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTextfield> _retval =
@@ -361,8 +384,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))
@@ -379,8 +403,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))
@@ -396,8 +421,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -413,8 +439,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -431,12 +458,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))
@@ -453,8 +482,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefViewDelegate> _retval =
@@ -470,8 +500,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefWindow> _retval =
@@ -487,8 +518,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -504,8 +536,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))->SetID(id);
@@ -517,8 +550,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -534,8 +568,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))
@@ -549,8 +584,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -568,8 +604,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -587,12 +624,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: bounds; type: simple_byref_const
   DCHECK(bounds);
-  if (!bounds)
+  if (!bounds) {
     return;
+  }
 
   // Translate param: bounds; type: simple_byref_const
   CefRect boundsVal = bounds ? *bounds : CefRect();
@@ -608,8 +647,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval =
@@ -625,8 +665,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval = CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))
@@ -643,12 +684,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: size; type: simple_byref_const
   DCHECK(size);
-  if (!size)
+  if (!size) {
     return;
+  }
 
   // Translate param: size; type: simple_byref_const
   CefSize sizeVal = size ? *size : CefSize();
@@ -663,8 +706,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -681,12 +725,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: position; type: simple_byref_const
   DCHECK(position);
-  if (!position)
+  if (!position) {
     return;
+  }
 
   // Translate param: position; type: simple_byref_const
   CefPoint positionVal = position ? *position : CefPoint();
@@ -702,8 +748,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefPoint();
+  }
 
   // Execute
   cef_point_t _retval =
@@ -713,14 +760,57 @@
   return _retval;
 }
 
+void CEF_CALLBACK panel_set_insets(struct _cef_view_t* self,
+                                   const cef_insets_t* insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: insets; type: simple_byref_const
+  DCHECK(insets);
+  if (!insets) {
+    return;
+  }
+
+  // Translate param: insets; type: simple_byref_const
+  CefInsets insetsVal = insets ? *insets : CefInsets();
+
+  // Execute
+  CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))
+      ->SetInsets(insetsVal);
+}
+
+cef_insets_t CEF_CALLBACK panel_get_insets(struct _cef_view_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CefInsets();
+  }
+
+  // Execute
+  cef_insets_t _retval =
+      CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))->GetInsets();
+
+  // Return type: simple
+  return _retval;
+}
+
 cef_size_t CEF_CALLBACK panel_get_preferred_size(struct _cef_view_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))
@@ -736,8 +826,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))
@@ -750,8 +841,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))
@@ -767,8 +859,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))
@@ -785,8 +878,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))
@@ -802,8 +896,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))->InvalidateLayout();
@@ -815,8 +910,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))
@@ -829,8 +925,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -846,8 +943,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -863,8 +961,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))
@@ -877,8 +976,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -894,8 +994,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))
@@ -908,8 +1009,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -925,8 +1027,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))
@@ -942,8 +1045,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))->RequestFocus();
@@ -956,8 +1060,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefPanelCppToC::Get(reinterpret_cast<cef_panel_t*>(self))
@@ -970,8 +1075,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   cef_color_t _retval =
@@ -989,12 +1095,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1004,8 +1112,9 @@
                      ->ConvertPointToScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1018,12 +1127,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1033,8 +1144,9 @@
                      ->ConvertPointFromScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1047,12 +1159,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1062,8 +1176,9 @@
                      ->ConvertPointToWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1076,12 +1191,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1091,8 +1208,9 @@
                      ->ConvertPointFromWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1106,16 +1224,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1126,8 +1247,9 @@
           ->ConvertPointToView(CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1141,16 +1263,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1161,8 +1286,9 @@
           ->ConvertPointFromView(CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1210,6 +1336,8 @@
   GetStruct()->base.get_size = panel_get_size;
   GetStruct()->base.set_position = panel_set_position;
   GetStruct()->base.get_position = panel_get_position;
+  GetStruct()->base.set_insets = panel_set_insets;
+  GetStruct()->base.get_insets = panel_get_insets;
   GetStruct()->base.get_preferred_size = panel_get_preferred_size;
   GetStruct()->base.size_to_preferred_size = panel_size_to_preferred_size;
   GetStruct()->base.get_minimum_size = panel_get_minimum_size;
@@ -1250,7 +1378,7 @@
   if (type == WT_WINDOW) {
     return CefWindowCppToC::Unwrap(reinterpret_cast<cef_window_t*>(s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/panel_cpptoc.h b/src/libcef_dll/cpptoc/views/panel_cpptoc.h
index ee902a4..7411c0d 100644
--- a/src/libcef_dll/cpptoc/views/panel_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/panel_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=bde3be5e373d61a9d40368e78757fd22fa01fdd7$
+// $hash=2c4b5c88fc2a00039dc5eb01aaa90ecd7c2ea0ad$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_PANEL_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/panel_delegate_cpptoc.cc b/src/libcef_dll/cpptoc/views/panel_delegate_cpptoc.cc
index 82fb2b1..8110fdc 100644
--- a/src/libcef_dll/cpptoc/views/panel_delegate_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/panel_delegate_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=69b5f96bfef5ed4e368ff868fc8968d38a1159bb$
+// $hash=66de178d38a1c9b72867b1eac9ff3c1f7b301c89$
 //
 
 #include "libcef_dll/cpptoc/views/panel_delegate_cpptoc.h"
@@ -29,12 +29,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -53,12 +55,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -77,12 +81,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -102,12 +108,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -128,16 +136,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
   // Verify param: parent; type: refptr_diff
   DCHECK(parent);
-  if (!parent)
+  if (!parent) {
     return;
+  }
 
   // Execute
   CefPanelDelegateCppToC::Get(reinterpret_cast<cef_panel_delegate_t*>(self))
@@ -155,16 +166,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
   // Verify param: child; type: refptr_diff
   DCHECK(child);
-  if (!child)
+  if (!child) {
     return;
+  }
 
   // Execute
   CefPanelDelegateCppToC::Get(reinterpret_cast<cef_panel_delegate_t*>(self))
@@ -172,6 +186,60 @@
                            CefViewCToCpp::Wrap(child));
 }
 
+void CEF_CALLBACK
+panel_delegate_on_window_changed(struct _cef_view_delegate_t* self,
+                                 cef_view_t* view,
+                                 int added) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: view; type: refptr_diff
+  DCHECK(view);
+  if (!view) {
+    return;
+  }
+
+  // Execute
+  CefPanelDelegateCppToC::Get(reinterpret_cast<cef_panel_delegate_t*>(self))
+      ->OnWindowChanged(CefViewCToCpp::Wrap(view), added ? true : false);
+}
+
+void CEF_CALLBACK
+panel_delegate_on_layout_changed(struct _cef_view_delegate_t* self,
+                                 cef_view_t* view,
+                                 const cef_rect_t* new_bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: view; type: refptr_diff
+  DCHECK(view);
+  if (!view) {
+    return;
+  }
+  // Verify param: new_bounds; type: simple_byref_const
+  DCHECK(new_bounds);
+  if (!new_bounds) {
+    return;
+  }
+
+  // Translate param: new_bounds; type: simple_byref_const
+  CefRect new_boundsVal = new_bounds ? *new_bounds : CefRect();
+
+  // Execute
+  CefPanelDelegateCppToC::Get(reinterpret_cast<cef_panel_delegate_t*>(self))
+      ->OnLayoutChanged(CefViewCToCpp::Wrap(view), new_boundsVal);
+}
+
 void CEF_CALLBACK panel_delegate_on_focus(struct _cef_view_delegate_t* self,
                                           cef_view_t* view) {
   shutdown_checker::AssertNotShutdown();
@@ -179,12 +247,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefPanelDelegateCppToC::Get(reinterpret_cast<cef_panel_delegate_t*>(self))
@@ -198,12 +268,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefPanelDelegateCppToC::Get(reinterpret_cast<cef_panel_delegate_t*>(self))
@@ -223,6 +295,8 @@
       panel_delegate_on_parent_view_changed;
   GetStruct()->base.on_child_view_changed =
       panel_delegate_on_child_view_changed;
+  GetStruct()->base.on_window_changed = panel_delegate_on_window_changed;
+  GetStruct()->base.on_layout_changed = panel_delegate_on_layout_changed;
   GetStruct()->base.on_focus = panel_delegate_on_focus;
   GetStruct()->base.on_blur = panel_delegate_on_blur;
 }
@@ -243,7 +317,7 @@
     return CefWindowDelegateCppToC::Unwrap(
         reinterpret_cast<cef_window_delegate_t*>(s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/panel_delegate_cpptoc.h b/src/libcef_dll/cpptoc/views/panel_delegate_cpptoc.h
index fa721f1..578ce7c 100644
--- a/src/libcef_dll/cpptoc/views/panel_delegate_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/panel_delegate_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4b4762a13ba74d480900cd013195c1aeaf85b1ea$
+// $hash=1eedf21b5a9e1edb24e6c24de55c991388b50c7c$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_PANEL_DELEGATE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/scroll_view_cpptoc.cc b/src/libcef_dll/cpptoc/views/scroll_view_cpptoc.cc
index 38910e5..5ba3a63 100644
--- a/src/libcef_dll/cpptoc/views/scroll_view_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/scroll_view_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d2be86a1a89f55279682893e5a98366dd9c8f668$
+// $hash=171b3ef450c160ece605980988dd80af9dd97958$
 //
 
 #include "libcef_dll/cpptoc/views/scroll_view_cpptoc.h"
@@ -51,12 +51,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefScrollViewCppToC::Get(self)->SetContentView(CefViewCppToC::Unwrap(view));
@@ -69,8 +71,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval = CefScrollViewCppToC::Get(self)->GetContentView();
@@ -86,8 +89,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval = CefScrollViewCppToC::Get(self)->GetVisibleContentRect();
@@ -103,8 +107,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefScrollViewCppToC::Get(self)->HasHorizontalScrollbar();
@@ -120,8 +125,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefScrollViewCppToC::Get(self)->GetHorizontalScrollbarHeight();
@@ -137,8 +143,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefScrollViewCppToC::Get(self)->HasVerticalScrollbar();
@@ -154,8 +161,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefScrollViewCppToC::Get(self)->GetVerticalScrollbarWidth();
@@ -171,8 +179,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowserView> _retval =
@@ -189,8 +198,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefButton> _retval =
@@ -207,8 +217,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefPanel> _retval =
@@ -226,8 +237,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefScrollView> _retval =
@@ -245,8 +257,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTextfield> _retval =
@@ -264,8 +277,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -283,8 +297,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -301,8 +316,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -319,8 +335,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -338,12 +355,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -361,8 +380,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefViewDelegate> _retval =
@@ -380,8 +400,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefWindow> _retval =
@@ -398,8 +419,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -416,8 +438,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefScrollViewCppToC::Get(reinterpret_cast<cef_scroll_view_t*>(self))
@@ -430,8 +453,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -449,8 +473,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefScrollViewCppToC::Get(reinterpret_cast<cef_scroll_view_t*>(self))
@@ -464,8 +489,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -483,8 +509,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -502,12 +529,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: bounds; type: simple_byref_const
   DCHECK(bounds);
-  if (!bounds)
+  if (!bounds) {
     return;
+  }
 
   // Translate param: bounds; type: simple_byref_const
   CefRect boundsVal = bounds ? *bounds : CefRect();
@@ -523,8 +552,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval =
@@ -542,8 +572,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval =
@@ -561,12 +592,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: size; type: simple_byref_const
   DCHECK(size);
-  if (!size)
+  if (!size) {
     return;
+  }
 
   // Translate param: size; type: simple_byref_const
   CefSize sizeVal = size ? *size : CefSize();
@@ -582,8 +615,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -601,12 +635,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: position; type: simple_byref_const
   DCHECK(position);
-  if (!position)
+  if (!position) {
     return;
+  }
 
   // Translate param: position; type: simple_byref_const
   CefPoint positionVal = position ? *position : CefPoint();
@@ -622,8 +658,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefPoint();
+  }
 
   // Execute
   cef_point_t _retval =
@@ -634,6 +671,49 @@
   return _retval;
 }
 
+void CEF_CALLBACK scroll_view_set_insets(struct _cef_view_t* self,
+                                         const cef_insets_t* insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: insets; type: simple_byref_const
+  DCHECK(insets);
+  if (!insets) {
+    return;
+  }
+
+  // Translate param: insets; type: simple_byref_const
+  CefInsets insetsVal = insets ? *insets : CefInsets();
+
+  // Execute
+  CefScrollViewCppToC::Get(reinterpret_cast<cef_scroll_view_t*>(self))
+      ->SetInsets(insetsVal);
+}
+
+cef_insets_t CEF_CALLBACK scroll_view_get_insets(struct _cef_view_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CefInsets();
+  }
+
+  // Execute
+  cef_insets_t _retval =
+      CefScrollViewCppToC::Get(reinterpret_cast<cef_scroll_view_t*>(self))
+          ->GetInsets();
+
+  // Return type: simple
+  return _retval;
+}
+
 cef_size_t CEF_CALLBACK
 scroll_view_get_preferred_size(struct _cef_view_t* self) {
   shutdown_checker::AssertNotShutdown();
@@ -641,8 +721,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -659,8 +740,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefScrollViewCppToC::Get(reinterpret_cast<cef_scroll_view_t*>(self))
@@ -673,8 +755,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -691,8 +774,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -710,8 +794,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -728,8 +813,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefScrollViewCppToC::Get(reinterpret_cast<cef_scroll_view_t*>(self))
@@ -743,8 +829,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefScrollViewCppToC::Get(reinterpret_cast<cef_scroll_view_t*>(self))
@@ -757,8 +844,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -775,8 +863,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -794,8 +883,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefScrollViewCppToC::Get(reinterpret_cast<cef_scroll_view_t*>(self))
@@ -808,8 +898,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -827,8 +918,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefScrollViewCppToC::Get(reinterpret_cast<cef_scroll_view_t*>(self))
@@ -841,8 +933,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -860,8 +953,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -878,8 +972,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefScrollViewCppToC::Get(reinterpret_cast<cef_scroll_view_t*>(self))
@@ -893,8 +988,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefScrollViewCppToC::Get(reinterpret_cast<cef_scroll_view_t*>(self))
@@ -908,8 +1004,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   cef_color_t _retval =
@@ -927,12 +1024,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -943,8 +1042,9 @@
           ->ConvertPointToScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -957,12 +1057,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -973,8 +1075,9 @@
           ->ConvertPointFromScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -987,12 +1090,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1003,8 +1108,9 @@
           ->ConvertPointToWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1017,12 +1123,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1033,8 +1141,9 @@
           ->ConvertPointFromWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1048,16 +1157,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1068,8 +1180,9 @@
           ->ConvertPointToView(CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1083,16 +1196,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1103,8 +1219,9 @@
           ->ConvertPointFromView(CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1149,6 +1266,8 @@
   GetStruct()->base.get_size = scroll_view_get_size;
   GetStruct()->base.set_position = scroll_view_set_position;
   GetStruct()->base.get_position = scroll_view_get_position;
+  GetStruct()->base.set_insets = scroll_view_set_insets;
+  GetStruct()->base.get_insets = scroll_view_get_insets;
   GetStruct()->base.get_preferred_size = scroll_view_get_preferred_size;
   GetStruct()->base.size_to_preferred_size = scroll_view_size_to_preferred_size;
   GetStruct()->base.get_minimum_size = scroll_view_get_minimum_size;
@@ -1190,7 +1309,7 @@
 CefRefPtr<CefScrollView>
 CefCppToCRefCounted<CefScrollViewCppToC, CefScrollView, cef_scroll_view_t>::
     UnwrapDerived(CefWrapperType type, cef_scroll_view_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/scroll_view_cpptoc.h b/src/libcef_dll/cpptoc/views/scroll_view_cpptoc.h
index ba7a9b8..1861706 100644
--- a/src/libcef_dll/cpptoc/views/scroll_view_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/scroll_view_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=fb8f1a2be6ab62c96c876e3bf07bcbb6df3a34b0$
+// $hash=f0b7e40e7ec1e3870dbc7f25430978c46eb1a51f$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_SCROLL_VIEW_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/textfield_cpptoc.cc b/src/libcef_dll/cpptoc/views/textfield_cpptoc.cc
index ff4b01c..c41aad0 100644
--- a/src/libcef_dll/cpptoc/views/textfield_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/textfield_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9ee756d7e93888230541b494da5559d736260b5c$
+// $hash=d974792994decce11fe5d5feedc9041203c6c3c1$
 //
 
 #include "libcef_dll/cpptoc/views/textfield_cpptoc.h"
@@ -52,8 +52,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(self)->SetPasswordInput(password_input ? true
@@ -66,8 +67,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefTextfieldCppToC::Get(self)->IsPasswordInput();
@@ -83,8 +85,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(self)->SetReadOnly(read_only ? true : false);
@@ -96,8 +99,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefTextfieldCppToC::Get(self)->IsReadOnly();
@@ -113,8 +117,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefTextfieldCppToC::Get(self)->GetText();
@@ -130,12 +135,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: text; type: string_byref_const
   DCHECK(text);
-  if (!text)
+  if (!text) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(self)->SetText(CefString(text));
@@ -148,12 +155,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: text; type: string_byref_const
   DCHECK(text);
-  if (!text)
+  if (!text) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(self)->AppendText(CefString(text));
@@ -167,12 +176,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: text; type: string_byref_const
   DCHECK(text);
-  if (!text)
+  if (!text) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(self)->InsertOrReplaceText(CefString(text));
@@ -184,8 +195,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefTextfieldCppToC::Get(self)->HasSelection();
@@ -201,8 +213,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefTextfieldCppToC::Get(self)->GetSelectedText();
@@ -218,8 +231,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(self)->SelectAll(reversed ? true : false);
@@ -231,8 +245,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(self)->ClearSelection();
@@ -245,8 +260,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRange();
+  }
 
   // Execute
   cef_range_t _retval = CefTextfieldCppToC::Get(self)->GetSelectedRange();
@@ -262,12 +278,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: range; type: simple_byref_const
   DCHECK(range);
-  if (!range)
+  if (!range) {
     return;
+  }
 
   // Translate param: range; type: simple_byref_const
   CefRange rangeVal = range ? *range : CefRange();
@@ -283,8 +301,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefTextfieldCppToC::Get(self)->GetCursorPosition();
@@ -300,8 +319,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(self)->SetTextColor(color);
@@ -314,8 +334,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   cef_color_t _retval = CefTextfieldCppToC::Get(self)->GetTextColor();
@@ -332,8 +353,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(self)->SetSelectionTextColor(color);
@@ -346,8 +368,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   cef_color_t _retval = CefTextfieldCppToC::Get(self)->GetSelectionTextColor();
@@ -364,8 +387,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(self)->SetSelectionBackgroundColor(color);
@@ -378,8 +402,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   cef_color_t _retval =
@@ -396,12 +421,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: font_list; type: string_byref_const
   DCHECK(font_list);
-  if (!font_list)
+  if (!font_list) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(self)->SetFontList(CefString(font_list));
@@ -415,12 +442,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: range; type: simple_byref_const
   DCHECK(range);
-  if (!range)
+  if (!range) {
     return;
+  }
 
   // Translate param: range; type: simple_byref_const
   CefRange rangeVal = range ? *range : CefRange();
@@ -438,12 +467,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: range; type: simple_byref_const
   DCHECK(range);
-  if (!range)
+  if (!range) {
     return;
+  }
 
   // Translate param: range; type: simple_byref_const
   CefRange rangeVal = range ? *range : CefRange();
@@ -453,15 +484,17 @@
                                                 rangeVal);
 }
 
-int CEF_CALLBACK textfield_is_command_enabled(struct _cef_textfield_t* self,
-                                              int command_id) {
+int CEF_CALLBACK
+textfield_is_command_enabled(struct _cef_textfield_t* self,
+                             cef_text_field_commands_t command_id) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefTextfieldCppToC::Get(self)->IsCommandEnabled(command_id);
@@ -470,15 +503,17 @@
   return _retval;
 }
 
-void CEF_CALLBACK textfield_execute_command(struct _cef_textfield_t* self,
-                                            int command_id) {
+void CEF_CALLBACK
+textfield_execute_command(struct _cef_textfield_t* self,
+                          cef_text_field_commands_t command_id) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(self)->ExecuteCommand(command_id);
@@ -490,8 +525,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(self)->ClearEditHistory();
@@ -504,12 +540,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: text; type: string_byref_const
   DCHECK(text);
-  if (!text)
+  if (!text) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(self)->SetPlaceholderText(CefString(text));
@@ -522,8 +560,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefTextfieldCppToC::Get(self)->GetPlaceholderText();
@@ -540,8 +579,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(self)->SetPlaceholderTextColor(color);
@@ -554,12 +594,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: name; type: string_byref_const
   DCHECK(name);
-  if (!name)
+  if (!name) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(self)->SetAccessibleName(CefString(name));
@@ -572,8 +614,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowserView> _retval =
@@ -590,8 +633,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefButton> _retval =
@@ -608,8 +652,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefPanel> _retval =
@@ -627,8 +672,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefScrollView> _retval =
@@ -645,8 +691,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTextfield> _retval =
@@ -664,8 +711,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -683,8 +731,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -701,8 +750,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -719,8 +769,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -738,12 +789,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -761,8 +814,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefViewDelegate> _retval =
@@ -780,8 +834,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefWindow> _retval =
@@ -798,8 +853,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -816,8 +872,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(reinterpret_cast<cef_textfield_t*>(self))->SetID(id);
@@ -829,8 +886,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -848,8 +906,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(reinterpret_cast<cef_textfield_t*>(self))
@@ -863,8 +922,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -882,8 +942,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -901,12 +962,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: bounds; type: simple_byref_const
   DCHECK(bounds);
-  if (!bounds)
+  if (!bounds) {
     return;
+  }
 
   // Translate param: bounds; type: simple_byref_const
   CefRect boundsVal = bounds ? *bounds : CefRect();
@@ -922,8 +985,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval =
@@ -941,8 +1005,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval =
@@ -960,12 +1025,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: size; type: simple_byref_const
   DCHECK(size);
-  if (!size)
+  if (!size) {
     return;
+  }
 
   // Translate param: size; type: simple_byref_const
   CefSize sizeVal = size ? *size : CefSize();
@@ -981,8 +1048,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -1000,12 +1068,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: position; type: simple_byref_const
   DCHECK(position);
-  if (!position)
+  if (!position) {
     return;
+  }
 
   // Translate param: position; type: simple_byref_const
   CefPoint positionVal = position ? *position : CefPoint();
@@ -1021,8 +1091,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefPoint();
+  }
 
   // Execute
   cef_point_t _retval =
@@ -1033,14 +1104,58 @@
   return _retval;
 }
 
+void CEF_CALLBACK textfield_set_insets(struct _cef_view_t* self,
+                                       const cef_insets_t* insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: insets; type: simple_byref_const
+  DCHECK(insets);
+  if (!insets) {
+    return;
+  }
+
+  // Translate param: insets; type: simple_byref_const
+  CefInsets insetsVal = insets ? *insets : CefInsets();
+
+  // Execute
+  CefTextfieldCppToC::Get(reinterpret_cast<cef_textfield_t*>(self))
+      ->SetInsets(insetsVal);
+}
+
+cef_insets_t CEF_CALLBACK textfield_get_insets(struct _cef_view_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CefInsets();
+  }
+
+  // Execute
+  cef_insets_t _retval =
+      CefTextfieldCppToC::Get(reinterpret_cast<cef_textfield_t*>(self))
+          ->GetInsets();
+
+  // Return type: simple
+  return _retval;
+}
+
 cef_size_t CEF_CALLBACK textfield_get_preferred_size(struct _cef_view_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -1057,8 +1172,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(reinterpret_cast<cef_textfield_t*>(self))
@@ -1071,8 +1187,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -1089,8 +1206,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -1108,8 +1226,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -1126,8 +1245,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(reinterpret_cast<cef_textfield_t*>(self))
@@ -1140,8 +1260,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(reinterpret_cast<cef_textfield_t*>(self))
@@ -1154,8 +1275,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1172,8 +1294,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1190,8 +1313,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(reinterpret_cast<cef_textfield_t*>(self))
@@ -1204,8 +1328,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1223,8 +1348,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(reinterpret_cast<cef_textfield_t*>(self))
@@ -1237,8 +1363,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1256,8 +1383,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1274,8 +1402,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(reinterpret_cast<cef_textfield_t*>(self))
@@ -1289,8 +1418,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefTextfieldCppToC::Get(reinterpret_cast<cef_textfield_t*>(self))
@@ -1304,8 +1434,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   cef_color_t _retval =
@@ -1323,12 +1454,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1339,8 +1472,9 @@
           ->ConvertPointToScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1353,12 +1487,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1369,8 +1505,9 @@
           ->ConvertPointFromScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1383,12 +1520,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1399,8 +1538,9 @@
           ->ConvertPointToWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1413,12 +1553,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1429,8 +1571,9 @@
           ->ConvertPointFromWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1444,16 +1587,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1464,8 +1610,9 @@
           ->ConvertPointToView(CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1479,16 +1626,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1499,8 +1649,9 @@
           ->ConvertPointFromView(CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1570,6 +1721,8 @@
   GetStruct()->base.get_size = textfield_get_size;
   GetStruct()->base.set_position = textfield_set_position;
   GetStruct()->base.get_position = textfield_get_position;
+  GetStruct()->base.set_insets = textfield_set_insets;
+  GetStruct()->base.get_insets = textfield_get_insets;
   GetStruct()->base.get_preferred_size = textfield_get_preferred_size;
   GetStruct()->base.size_to_preferred_size = textfield_size_to_preferred_size;
   GetStruct()->base.get_minimum_size = textfield_get_minimum_size;
@@ -1608,7 +1761,7 @@
 CefRefPtr<CefTextfield>
 CefCppToCRefCounted<CefTextfieldCppToC, CefTextfield, cef_textfield_t>::
     UnwrapDerived(CefWrapperType type, cef_textfield_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/textfield_cpptoc.h b/src/libcef_dll/cpptoc/views/textfield_cpptoc.h
index 3c2e9dc..7908353 100644
--- a/src/libcef_dll/cpptoc/views/textfield_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/textfield_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=93c32090811a83e148622725bdc21914c665f72e$
+// $hash=0b5018c0b9d42f4ee100098365c46e0ea723ea29$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_TEXTFIELD_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/textfield_delegate_cpptoc.cc b/src/libcef_dll/cpptoc/views/textfield_delegate_cpptoc.cc
index da860f7..edd9544 100644
--- a/src/libcef_dll/cpptoc/views/textfield_delegate_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/textfield_delegate_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=5c2d33803cefd442d3995d06f2fb0e8adc26aa4d$
+// $hash=6af00869e573d59adf07c86ba895ee13db7131e7$
 //
 
 #include "libcef_dll/cpptoc/views/textfield_delegate_cpptoc.h"
@@ -24,31 +24,32 @@
 int CEF_CALLBACK
 textfield_delegate_on_key_event(struct _cef_textfield_delegate_t* self,
                                 cef_textfield_t* textfield,
-                                const struct _cef_key_event_t* event) {
+                                const cef_key_event_t* event) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: textfield; type: refptr_diff
   DCHECK(textfield);
-  if (!textfield)
+  if (!textfield) {
     return 0;
-  // Verify param: event; type: struct_byref_const
+  }
+  // Verify param: event; type: simple_byref_const
   DCHECK(event);
-  if (!event)
+  if (!event) {
     return 0;
+  }
 
-  // Translate param: event; type: struct_byref_const
-  CefKeyEvent eventObj;
-  if (event)
-    eventObj.Set(*event, false);
+  // Translate param: event; type: simple_byref_const
+  CefKeyEvent eventVal = event ? *event : CefKeyEvent();
 
   // Execute
   bool _retval = CefTextfieldDelegateCppToC::Get(self)->OnKeyEvent(
-      CefTextfieldCToCpp::Wrap(textfield), eventObj);
+      CefTextfieldCToCpp::Wrap(textfield), eventVal);
 
   // Return type: bool
   return _retval;
@@ -62,12 +63,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: textfield; type: refptr_diff
   DCHECK(textfield);
-  if (!textfield)
+  if (!textfield) {
     return;
+  }
 
   // Execute
   CefTextfieldDelegateCppToC::Get(self)->OnAfterUserAction(
@@ -82,12 +85,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefTextfieldDelegateCppToC::Get(
@@ -106,12 +111,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefTextfieldDelegateCppToC::Get(
@@ -130,12 +137,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefTextfieldDelegateCppToC::Get(
@@ -155,12 +164,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
 
   // Execute
   int _retval = CefTextfieldDelegateCppToC::Get(
@@ -181,16 +192,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
   // Verify param: parent; type: refptr_diff
   DCHECK(parent);
-  if (!parent)
+  if (!parent) {
     return;
+  }
 
   // Execute
   CefTextfieldDelegateCppToC::Get(
@@ -209,16 +223,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
   // Verify param: child; type: refptr_diff
   DCHECK(child);
-  if (!child)
+  if (!child) {
     return;
+  }
 
   // Execute
   CefTextfieldDelegateCppToC::Get(
@@ -227,6 +244,62 @@
                            CefViewCToCpp::Wrap(child));
 }
 
+void CEF_CALLBACK
+textfield_delegate_on_window_changed(struct _cef_view_delegate_t* self,
+                                     cef_view_t* view,
+                                     int added) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: view; type: refptr_diff
+  DCHECK(view);
+  if (!view) {
+    return;
+  }
+
+  // Execute
+  CefTextfieldDelegateCppToC::Get(
+      reinterpret_cast<cef_textfield_delegate_t*>(self))
+      ->OnWindowChanged(CefViewCToCpp::Wrap(view), added ? true : false);
+}
+
+void CEF_CALLBACK
+textfield_delegate_on_layout_changed(struct _cef_view_delegate_t* self,
+                                     cef_view_t* view,
+                                     const cef_rect_t* new_bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: view; type: refptr_diff
+  DCHECK(view);
+  if (!view) {
+    return;
+  }
+  // Verify param: new_bounds; type: simple_byref_const
+  DCHECK(new_bounds);
+  if (!new_bounds) {
+    return;
+  }
+
+  // Translate param: new_bounds; type: simple_byref_const
+  CefRect new_boundsVal = new_bounds ? *new_bounds : CefRect();
+
+  // Execute
+  CefTextfieldDelegateCppToC::Get(
+      reinterpret_cast<cef_textfield_delegate_t*>(self))
+      ->OnLayoutChanged(CefViewCToCpp::Wrap(view), new_boundsVal);
+}
+
 void CEF_CALLBACK textfield_delegate_on_focus(struct _cef_view_delegate_t* self,
                                               cef_view_t* view) {
   shutdown_checker::AssertNotShutdown();
@@ -234,12 +307,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefTextfieldDelegateCppToC::Get(
@@ -254,12 +329,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefTextfieldDelegateCppToC::Get(
@@ -283,6 +360,8 @@
       textfield_delegate_on_parent_view_changed;
   GetStruct()->base.on_child_view_changed =
       textfield_delegate_on_child_view_changed;
+  GetStruct()->base.on_window_changed = textfield_delegate_on_window_changed;
+  GetStruct()->base.on_layout_changed = textfield_delegate_on_layout_changed;
   GetStruct()->base.on_focus = textfield_delegate_on_focus;
   GetStruct()->base.on_blur = textfield_delegate_on_blur;
 }
@@ -299,7 +378,7 @@
     CefTextfieldDelegate,
     cef_textfield_delegate_t>::UnwrapDerived(CefWrapperType type,
                                              cef_textfield_delegate_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/textfield_delegate_cpptoc.h b/src/libcef_dll/cpptoc/views/textfield_delegate_cpptoc.h
index 4d2513a..2ad4735 100644
--- a/src/libcef_dll/cpptoc/views/textfield_delegate_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/textfield_delegate_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=846e39b812ceed2719b128433890e0706bf9f439$
+// $hash=33ba2bd44c946bf204f2f7a929b8d208768ca3dd$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_TEXTFIELD_DELEGATE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/view_cpptoc.cc b/src/libcef_dll/cpptoc/views/view_cpptoc.cc
index f61483b..7368e54 100644
--- a/src/libcef_dll/cpptoc/views/view_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/view_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=cdddd584b0d4f91a93f0f635023d7d21040b7ade$
+// $hash=8ea7eff414ea832334a4b3cb92a3efe8a44e9653$
 //
 
 #include "libcef_dll/cpptoc/views/view_cpptoc.h"
@@ -35,8 +35,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowserView> _retval = CefViewCppToC::Get(self)->AsBrowserView();
@@ -51,8 +52,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefButton> _retval = CefViewCppToC::Get(self)->AsButton();
@@ -67,8 +69,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefPanel> _retval = CefViewCppToC::Get(self)->AsPanel();
@@ -83,8 +86,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefScrollView> _retval = CefViewCppToC::Get(self)->AsScrollView();
@@ -99,8 +103,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTextfield> _retval = CefViewCppToC::Get(self)->AsTextfield();
@@ -116,8 +121,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefViewCppToC::Get(self)->GetTypeString();
@@ -133,8 +139,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -150,8 +157,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefViewCppToC::Get(self)->IsValid();
@@ -166,8 +174,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefViewCppToC::Get(self)->IsAttached();
@@ -183,12 +192,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefViewCppToC::Get(self)->IsSame(CefViewCppToC::Unwrap(that));
@@ -204,8 +215,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefViewDelegate> _retval = CefViewCppToC::Get(self)->GetDelegate();
@@ -220,8 +232,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefWindow> _retval = CefViewCppToC::Get(self)->GetWindow();
@@ -236,8 +249,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefViewCppToC::Get(self)->GetID();
@@ -252,8 +266,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefViewCppToC::Get(self)->SetID(id);
@@ -265,8 +280,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefViewCppToC::Get(self)->GetGroupID();
@@ -281,8 +297,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefViewCppToC::Get(self)->SetGroupID(group_id);
@@ -295,8 +312,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval = CefViewCppToC::Get(self)->GetParentView();
@@ -312,8 +330,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval = CefViewCppToC::Get(self)->GetViewForID(id);
@@ -329,12 +348,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: bounds; type: simple_byref_const
   DCHECK(bounds);
-  if (!bounds)
+  if (!bounds) {
     return;
+  }
 
   // Translate param: bounds; type: simple_byref_const
   CefRect boundsVal = bounds ? *bounds : CefRect();
@@ -349,8 +370,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval = CefViewCppToC::Get(self)->GetBounds();
@@ -365,8 +387,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval = CefViewCppToC::Get(self)->GetBoundsInScreen();
@@ -382,12 +405,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: size; type: simple_byref_const
   DCHECK(size);
-  if (!size)
+  if (!size) {
     return;
+  }
 
   // Translate param: size; type: simple_byref_const
   CefSize sizeVal = size ? *size : CefSize();
@@ -402,8 +427,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefViewCppToC::Get(self)->GetSize();
@@ -419,12 +445,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: position; type: simple_byref_const
   DCHECK(position);
-  if (!position)
+  if (!position) {
     return;
+  }
 
   // Translate param: position; type: simple_byref_const
   CefPoint positionVal = position ? *position : CefPoint();
@@ -439,8 +467,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefPoint();
+  }
 
   // Execute
   cef_point_t _retval = CefViewCppToC::Get(self)->GetPosition();
@@ -449,14 +478,55 @@
   return _retval;
 }
 
+void CEF_CALLBACK view_set_insets(struct _cef_view_t* self,
+                                  const cef_insets_t* insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: insets; type: simple_byref_const
+  DCHECK(insets);
+  if (!insets) {
+    return;
+  }
+
+  // Translate param: insets; type: simple_byref_const
+  CefInsets insetsVal = insets ? *insets : CefInsets();
+
+  // Execute
+  CefViewCppToC::Get(self)->SetInsets(insetsVal);
+}
+
+cef_insets_t CEF_CALLBACK view_get_insets(struct _cef_view_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CefInsets();
+  }
+
+  // Execute
+  cef_insets_t _retval = CefViewCppToC::Get(self)->GetInsets();
+
+  // Return type: simple
+  return _retval;
+}
+
 cef_size_t CEF_CALLBACK view_get_preferred_size(struct _cef_view_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefViewCppToC::Get(self)->GetPreferredSize();
@@ -471,8 +541,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefViewCppToC::Get(self)->SizeToPreferredSize();
@@ -484,8 +555,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefViewCppToC::Get(self)->GetMinimumSize();
@@ -500,8 +572,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefViewCppToC::Get(self)->GetMaximumSize();
@@ -517,8 +590,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefViewCppToC::Get(self)->GetHeightForWidth(width);
@@ -533,8 +607,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefViewCppToC::Get(self)->InvalidateLayout();
@@ -546,8 +621,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefViewCppToC::Get(self)->SetVisible(visible ? true : false);
@@ -559,8 +635,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefViewCppToC::Get(self)->IsVisible();
@@ -575,8 +652,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefViewCppToC::Get(self)->IsDrawn();
@@ -591,8 +669,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefViewCppToC::Get(self)->SetEnabled(enabled ? true : false);
@@ -604,8 +683,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefViewCppToC::Get(self)->IsEnabled();
@@ -620,8 +700,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefViewCppToC::Get(self)->SetFocusable(focusable ? true : false);
@@ -633,8 +714,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefViewCppToC::Get(self)->IsFocusable();
@@ -649,8 +731,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefViewCppToC::Get(self)->IsAccessibilityFocusable();
@@ -665,8 +748,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefViewCppToC::Get(self)->RequestFocus();
@@ -679,8 +763,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefViewCppToC::Get(self)->SetBackgroundColor(color);
@@ -692,8 +777,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   cef_color_t _retval = CefViewCppToC::Get(self)->GetBackgroundColor();
@@ -709,12 +795,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -723,8 +811,9 @@
   bool _retval = CefViewCppToC::Get(self)->ConvertPointToScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -737,12 +826,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -751,8 +842,9 @@
   bool _retval = CefViewCppToC::Get(self)->ConvertPointFromScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -765,12 +857,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -779,8 +873,9 @@
   bool _retval = CefViewCppToC::Get(self)->ConvertPointToWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -793,12 +888,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -807,8 +904,9 @@
   bool _retval = CefViewCppToC::Get(self)->ConvertPointFromWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -822,16 +920,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -841,8 +942,9 @@
       CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -856,16 +958,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -875,8 +980,9 @@
       CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -912,6 +1018,8 @@
   GetStruct()->get_size = view_get_size;
   GetStruct()->set_position = view_set_position;
   GetStruct()->get_position = view_get_position;
+  GetStruct()->set_insets = view_set_insets;
+  GetStruct()->get_insets = view_get_insets;
   GetStruct()->get_preferred_size = view_get_preferred_size;
   GetStruct()->size_to_preferred_size = view_size_to_preferred_size;
   GetStruct()->get_minimum_size = view_get_minimum_size;
@@ -974,7 +1082,7 @@
   if (type == WT_WINDOW) {
     return CefWindowCppToC::Unwrap(reinterpret_cast<cef_window_t*>(s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/view_cpptoc.h b/src/libcef_dll/cpptoc/views/view_cpptoc.h
index 097fff5..efb5975 100644
--- a/src/libcef_dll/cpptoc/views/view_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/view_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8154a3c9ac11598bdc5e473d0b4f6660e041f31b$
+// $hash=0d24d12448e97907667f8347a38818e0a4d713ed$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_VIEW_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/view_delegate_cpptoc.cc b/src/libcef_dll/cpptoc/views/view_delegate_cpptoc.cc
index 64f6f03..40bbcea 100644
--- a/src/libcef_dll/cpptoc/views/view_delegate_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/view_delegate_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f29ee71b497bc4f8ec55026e1e017d3d32dbc493$
+// $hash=a5ca3a4f1b8c666eee1a198e455dab6ca623650c$
 //
 
 #include "libcef_dll/cpptoc/views/view_delegate_cpptoc.h"
@@ -34,12 +34,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefViewDelegateCppToC::Get(self)->GetPreferredSize(
@@ -57,12 +59,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefViewDelegateCppToC::Get(self)->GetMinimumSize(
@@ -80,12 +84,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefViewDelegateCppToC::Get(self)->GetMaximumSize(
@@ -104,12 +110,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
 
   // Execute
   int _retval = CefViewDelegateCppToC::Get(self)->GetHeightForWidth(
@@ -129,16 +137,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
   // Verify param: parent; type: refptr_diff
   DCHECK(parent);
-  if (!parent)
+  if (!parent) {
     return;
+  }
 
   // Execute
   CefViewDelegateCppToC::Get(self)->OnParentViewChanged(
@@ -156,16 +167,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
   // Verify param: child; type: refptr_diff
   DCHECK(child);
-  if (!child)
+  if (!child) {
     return;
+  }
 
   // Execute
   CefViewDelegateCppToC::Get(self)->OnChildViewChanged(
@@ -173,6 +187,60 @@
       CefViewCToCpp::Wrap(child));
 }
 
+void CEF_CALLBACK
+view_delegate_on_window_changed(struct _cef_view_delegate_t* self,
+                                cef_view_t* view,
+                                int added) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: view; type: refptr_diff
+  DCHECK(view);
+  if (!view) {
+    return;
+  }
+
+  // Execute
+  CefViewDelegateCppToC::Get(self)->OnWindowChanged(CefViewCToCpp::Wrap(view),
+                                                    added ? true : false);
+}
+
+void CEF_CALLBACK
+view_delegate_on_layout_changed(struct _cef_view_delegate_t* self,
+                                cef_view_t* view,
+                                const cef_rect_t* new_bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: view; type: refptr_diff
+  DCHECK(view);
+  if (!view) {
+    return;
+  }
+  // Verify param: new_bounds; type: simple_byref_const
+  DCHECK(new_bounds);
+  if (!new_bounds) {
+    return;
+  }
+
+  // Translate param: new_bounds; type: simple_byref_const
+  CefRect new_boundsVal = new_bounds ? *new_bounds : CefRect();
+
+  // Execute
+  CefViewDelegateCppToC::Get(self)->OnLayoutChanged(CefViewCToCpp::Wrap(view),
+                                                    new_boundsVal);
+}
+
 void CEF_CALLBACK view_delegate_on_focus(struct _cef_view_delegate_t* self,
                                          cef_view_t* view) {
   shutdown_checker::AssertNotShutdown();
@@ -180,12 +248,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefViewDelegateCppToC::Get(self)->OnFocus(CefViewCToCpp::Wrap(view));
@@ -198,12 +268,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefViewDelegateCppToC::Get(self)->OnBlur(CefViewCToCpp::Wrap(view));
@@ -220,6 +292,8 @@
   GetStruct()->get_height_for_width = view_delegate_get_height_for_width;
   GetStruct()->on_parent_view_changed = view_delegate_on_parent_view_changed;
   GetStruct()->on_child_view_changed = view_delegate_on_child_view_changed;
+  GetStruct()->on_window_changed = view_delegate_on_window_changed;
+  GetStruct()->on_layout_changed = view_delegate_on_layout_changed;
   GetStruct()->on_focus = view_delegate_on_focus;
   GetStruct()->on_blur = view_delegate_on_blur;
 }
@@ -260,7 +334,7 @@
     return CefWindowDelegateCppToC::Unwrap(
         reinterpret_cast<cef_window_delegate_t*>(s));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/view_delegate_cpptoc.h b/src/libcef_dll/cpptoc/views/view_delegate_cpptoc.h
index e5f630d..a6903ef 100644
--- a/src/libcef_dll/cpptoc/views/view_delegate_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/view_delegate_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=bea8e33cf1ccef0c18bdb548042f18c659528567$
+// $hash=384b7d1f2df446d35d6ba46e62d89976d88fef7c$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_VIEW_DELEGATE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/views/window_cpptoc.cc b/src/libcef_dll/cpptoc/views/window_cpptoc.cc
index 3e953dd..e901863 100644
--- a/src/libcef_dll/cpptoc/views/window_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/window_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9543a25fe57ff1139ac9a7fb9df7f6cf272381e1$
+// $hash=38a50bca35881beb6400f3ad5d81b0a5ec86331d$
 //
 
 #include "libcef_dll/cpptoc/views/window_cpptoc.h"
@@ -21,6 +21,7 @@
 #include "libcef_dll/cpptoc/views/display_cpptoc.h"
 #include "libcef_dll/cpptoc/views/fill_layout_cpptoc.h"
 #include "libcef_dll/cpptoc/views/layout_cpptoc.h"
+#include "libcef_dll/cpptoc/views/overlay_controller_cpptoc.h"
 #include "libcef_dll/cpptoc/views/panel_cpptoc.h"
 #include "libcef_dll/cpptoc/views/scroll_view_cpptoc.h"
 #include "libcef_dll/cpptoc/views/textfield_cpptoc.h"
@@ -57,21 +58,45 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->Show();
 }
 
+void CEF_CALLBACK
+window_show_as_browser_modal_dialog(struct _cef_window_t* self,
+                                    cef_browser_view_t* browser_view) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: browser_view; type: refptr_same
+  DCHECK(browser_view);
+  if (!browser_view) {
+    return;
+  }
+
+  // Execute
+  CefWindowCppToC::Get(self)->ShowAsBrowserModalDialog(
+      CefBrowserViewCppToC::Unwrap(browser_view));
+}
+
 void CEF_CALLBACK window_hide(struct _cef_window_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->Hide();
@@ -84,12 +109,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: size; type: simple_byref_const
   DCHECK(size);
-  if (!size)
+  if (!size) {
     return;
+  }
 
   // Translate param: size; type: simple_byref_const
   CefSize sizeVal = size ? *size : CefSize();
@@ -104,8 +131,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->Close();
@@ -117,8 +145,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWindowCppToC::Get(self)->IsClosed();
@@ -133,8 +162,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->Activate();
@@ -146,8 +176,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->Deactivate();
@@ -159,8 +190,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWindowCppToC::Get(self)->IsActive();
@@ -175,8 +207,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->BringToTop();
@@ -189,8 +222,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->SetAlwaysOnTop(on_top ? true : false);
@@ -202,8 +236,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWindowCppToC::Get(self)->IsAlwaysOnTop();
@@ -218,8 +253,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->Maximize();
@@ -231,8 +267,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->Minimize();
@@ -244,8 +281,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->Restore();
@@ -258,8 +296,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->SetFullscreen(fullscreen ? true : false);
@@ -271,8 +310,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWindowCppToC::Get(self)->IsMaximized();
@@ -287,8 +327,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWindowCppToC::Get(self)->IsMinimized();
@@ -303,8 +344,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWindowCppToC::Get(self)->IsFullscreen();
@@ -320,8 +362,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: title
 
   // Execute
@@ -335,8 +378,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefWindowCppToC::Get(self)->GetTitle();
@@ -352,12 +396,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: image; type: refptr_same
   DCHECK(image);
-  if (!image)
+  if (!image) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->SetWindowIcon(CefImageCppToC::Unwrap(image));
@@ -369,8 +415,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefImage> _retval = CefWindowCppToC::Get(self)->GetWindowIcon();
@@ -386,12 +433,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: image; type: refptr_same
   DCHECK(image);
-  if (!image)
+  if (!image) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->SetWindowAppIcon(CefImageCppToC::Unwrap(image));
@@ -404,8 +453,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefImage> _retval = CefWindowCppToC::Get(self)->GetWindowAppIcon();
@@ -414,6 +464,33 @@
   return CefImageCppToC::Wrap(_retval);
 }
 
+cef_overlay_controller_t* CEF_CALLBACK
+window_add_overlay_view(struct _cef_window_t* self,
+                        cef_view_t* view,
+                        cef_docking_mode_t docking_mode) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return NULL;
+  }
+  // Verify param: view; type: refptr_same
+  DCHECK(view);
+  if (!view) {
+    return NULL;
+  }
+
+  // Execute
+  CefRefPtr<CefOverlayController> _retval =
+      CefWindowCppToC::Get(self)->AddOverlayView(CefViewCppToC::Unwrap(view),
+                                                 docking_mode);
+
+  // Return type: refptr_same
+  return CefOverlayControllerCppToC::Wrap(_retval);
+}
+
 void CEF_CALLBACK window_show_menu(struct _cef_window_t* self,
                                    cef_menu_model_t* menu_model,
                                    const cef_point_t* screen_point,
@@ -423,16 +500,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: menu_model; type: refptr_same
   DCHECK(menu_model);
-  if (!menu_model)
+  if (!menu_model) {
     return;
+  }
   // Verify param: screen_point; type: simple_byref_const
   DCHECK(screen_point);
-  if (!screen_point)
+  if (!screen_point) {
     return;
+  }
 
   // Translate param: screen_point; type: simple_byref_const
   CefPoint screen_pointVal = screen_point ? *screen_point : CefPoint();
@@ -448,8 +528,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->CancelMenu();
@@ -461,8 +542,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefDisplay> _retval = CefWindowCppToC::Get(self)->GetDisplay();
@@ -478,8 +560,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval =
@@ -498,8 +581,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Unverified params: regions
 
   // Translate param: regions; type: simple_vec_byref_const
@@ -522,8 +606,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return kNullWindowHandle;
+  }
 
   // Execute
   cef_window_handle_t _retval = CefWindowCppToC::Get(self)->GetWindowHandle();
@@ -534,14 +619,15 @@
 
 void CEF_CALLBACK window_send_key_press(struct _cef_window_t* self,
                                         int key_code,
-                                        uint32 event_flags) {
+                                        uint32_t event_flags) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->SendKeyPress(key_code, event_flags);
@@ -555,8 +641,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->SendMouseMove(screen_x, screen_y);
@@ -571,8 +658,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->SendMouseEvents(button, mouse_down ? true : false,
@@ -584,19 +672,22 @@
                                          int key_code,
                                          int shift_pressed,
                                          int ctrl_pressed,
-                                         int alt_pressed) {
+                                         int alt_pressed,
+                                         int high_priority) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->SetAccelerator(
       command_id, key_code, shift_pressed ? true : false,
-      ctrl_pressed ? true : false, alt_pressed ? true : false);
+      ctrl_pressed ? true : false, alt_pressed ? true : false,
+      high_priority ? true : false);
 }
 
 void CEF_CALLBACK window_remove_accelerator(struct _cef_window_t* self,
@@ -606,8 +697,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->RemoveAccelerator(command_id);
@@ -619,8 +711,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(self)->RemoveAllAccelerators();
@@ -632,8 +725,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefWindow> _retval =
@@ -650,8 +744,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefFillLayout> _retval =
@@ -664,28 +759,29 @@
 
 cef_box_layout_t* CEF_CALLBACK
 window_set_to_box_layout(struct _cef_panel_t* self,
-                         const struct _cef_box_layout_settings_t* settings) {
+                         const cef_box_layout_settings_t* settings) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
-  // Verify param: settings; type: struct_byref_const
+  }
+  // Verify param: settings; type: simple_byref_const
   DCHECK(settings);
-  if (!settings)
+  if (!settings) {
     return NULL;
+  }
 
-  // Translate param: settings; type: struct_byref_const
-  CefBoxLayoutSettings settingsObj;
-  if (settings)
-    settingsObj.Set(*settings, false);
+  // Translate param: settings; type: simple_byref_const
+  CefBoxLayoutSettings settingsVal =
+      settings ? *settings : CefBoxLayoutSettings();
 
   // Execute
   CefRefPtr<CefBoxLayout> _retval =
       CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
-          ->SetToBoxLayout(settingsObj);
+          ->SetToBoxLayout(settingsVal);
 
   // Return type: refptr_same
   return CefBoxLayoutCppToC::Wrap(_retval);
@@ -697,8 +793,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefLayout> _retval =
@@ -714,8 +811,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))->Layout();
@@ -728,12 +826,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -748,16 +848,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -772,12 +875,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -791,12 +896,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -809,8 +916,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -823,8 +931,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -841,12 +950,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -864,8 +975,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBrowserView> _retval =
@@ -882,8 +994,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefButton> _retval =
@@ -899,8 +1012,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefPanel> _retval =
@@ -917,8 +1031,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefScrollView> _retval =
@@ -935,8 +1050,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefTextfield> _retval =
@@ -954,8 +1070,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -973,8 +1090,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -991,8 +1109,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1008,8 +1127,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1025,12 +1145,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: that; type: refptr_same
   DCHECK(that);
-  if (!that)
+  if (!that) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -1047,8 +1169,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefViewDelegate> _retval =
@@ -1065,8 +1188,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefWindow> _retval =
@@ -1082,8 +1206,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -1099,8 +1224,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))->SetID(id);
@@ -1112,8 +1238,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -1129,8 +1256,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -1143,8 +1271,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -1162,8 +1291,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefView> _retval =
@@ -1181,12 +1311,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: bounds; type: simple_byref_const
   DCHECK(bounds);
-  if (!bounds)
+  if (!bounds) {
     return;
+  }
 
   // Translate param: bounds; type: simple_byref_const
   CefRect boundsVal = bounds ? *bounds : CefRect();
@@ -1202,8 +1334,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval =
@@ -1219,8 +1352,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefRect();
+  }
 
   // Execute
   cef_rect_t _retval =
@@ -1238,12 +1372,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: size; type: simple_byref_const
   DCHECK(size);
-  if (!size)
+  if (!size) {
     return;
+  }
 
   // Translate param: size; type: simple_byref_const
   CefSize sizeVal = size ? *size : CefSize();
@@ -1258,8 +1394,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -1276,12 +1413,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: position; type: simple_byref_const
   DCHECK(position);
-  if (!position)
+  if (!position) {
     return;
+  }
 
   // Translate param: position; type: simple_byref_const
   CefPoint positionVal = position ? *position : CefPoint();
@@ -1297,8 +1436,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefPoint();
+  }
 
   // Execute
   cef_point_t _retval =
@@ -1309,14 +1449,57 @@
   return _retval;
 }
 
+void CEF_CALLBACK window_set_insets(struct _cef_view_t* self,
+                                    const cef_insets_t* insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: insets; type: simple_byref_const
+  DCHECK(insets);
+  if (!insets) {
+    return;
+  }
+
+  // Translate param: insets; type: simple_byref_const
+  CefInsets insetsVal = insets ? *insets : CefInsets();
+
+  // Execute
+  CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
+      ->SetInsets(insetsVal);
+}
+
+cef_insets_t CEF_CALLBACK window_get_insets(struct _cef_view_t* self) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CefInsets();
+  }
+
+  // Execute
+  cef_insets_t _retval =
+      CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))->GetInsets();
+
+  // Return type: simple
+  return _retval;
+}
+
 cef_size_t CEF_CALLBACK window_get_preferred_size(struct _cef_view_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -1333,8 +1516,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -1347,8 +1531,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -1365,8 +1550,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -1384,8 +1570,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -1401,8 +1588,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -1415,8 +1603,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -1429,8 +1618,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1446,8 +1636,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1463,8 +1654,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -1477,8 +1669,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -1495,8 +1688,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -1509,8 +1703,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -1526,8 +1721,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -1543,8 +1739,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))->RequestFocus();
@@ -1557,8 +1754,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWindowCppToC::Get(reinterpret_cast<cef_window_t*>(self))
@@ -1571,8 +1769,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   cef_color_t _retval =
@@ -1590,12 +1789,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1605,8 +1806,9 @@
                      ->ConvertPointToScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1619,12 +1821,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1634,8 +1838,9 @@
                      ->ConvertPointFromScreen(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1648,12 +1853,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1663,8 +1870,9 @@
                      ->ConvertPointToWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1677,12 +1885,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1692,8 +1902,9 @@
                      ->ConvertPointFromWindow(pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1707,16 +1918,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1727,8 +1941,9 @@
           ->ConvertPointToView(CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1742,16 +1957,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_same
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
   // Verify param: point; type: simple_byref
   DCHECK(point);
-  if (!point)
+  if (!point) {
     return 0;
+  }
 
   // Translate param: point; type: simple_byref
   CefPoint pointVal = point ? *point : CefPoint();
@@ -1762,8 +1980,9 @@
           ->ConvertPointFromView(CefViewCppToC::Unwrap(view), pointVal);
 
   // Restore param: point; type: simple_byref
-  if (point)
+  if (point) {
     *point = pointVal;
+  }
 
   // Return type: bool
   return _retval;
@@ -1775,6 +1994,8 @@
 
 CefWindowCppToC::CefWindowCppToC() {
   GetStruct()->show = window_show;
+  GetStruct()->show_as_browser_modal_dialog =
+      window_show_as_browser_modal_dialog;
   GetStruct()->hide = window_hide;
   GetStruct()->center_window = window_center_window;
   GetStruct()->close = window_close;
@@ -1798,6 +2019,7 @@
   GetStruct()->get_window_icon = window_get_window_icon;
   GetStruct()->set_window_app_icon = window_set_window_app_icon;
   GetStruct()->get_window_app_icon = window_get_window_app_icon;
+  GetStruct()->add_overlay_view = window_add_overlay_view;
   GetStruct()->show_menu = window_show_menu;
   GetStruct()->cancel_menu = window_cancel_menu;
   GetStruct()->get_display = window_get_display;
@@ -1848,6 +2070,8 @@
   GetStruct()->base.base.get_size = window_get_size;
   GetStruct()->base.base.set_position = window_set_position;
   GetStruct()->base.base.get_position = window_get_position;
+  GetStruct()->base.base.set_insets = window_set_insets;
+  GetStruct()->base.base.get_insets = window_get_insets;
   GetStruct()->base.base.get_preferred_size = window_get_preferred_size;
   GetStruct()->base.base.size_to_preferred_size = window_size_to_preferred_size;
   GetStruct()->base.base.get_minimum_size = window_get_minimum_size;
@@ -1890,7 +2114,7 @@
 CefCppToCRefCounted<CefWindowCppToC, CefWindow, cef_window_t>::UnwrapDerived(
     CefWrapperType type,
     cef_window_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/window_cpptoc.h b/src/libcef_dll/cpptoc/views/window_cpptoc.h
index 800f64a..501b052 100644
--- a/src/libcef_dll/cpptoc/views/window_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/window_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=fabf09f314badc143b51db3cdd2a590e0f23da13$
+// $hash=6700d328968cb5c0141cd2d93ce66835e97a9d66$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_WINDOW_CPPTOC_H_
@@ -20,7 +20,9 @@
 #error This file can be included DLL-side only
 #endif
 
+#include "include/capi/views/cef_browser_view_capi.h"
 #include "include/capi/views/cef_window_capi.h"
+#include "include/views/cef_browser_view.h"
 #include "include/views/cef_window.h"
 #include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
 
diff --git a/src/libcef_dll/cpptoc/views/window_delegate_cpptoc.cc b/src/libcef_dll/cpptoc/views/window_delegate_cpptoc.cc
index 59b706d..bc0335e 100644
--- a/src/libcef_dll/cpptoc/views/window_delegate_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/views/window_delegate_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=52b31a63bbe83937a9f5dc557accfc1e84af6d84$
+// $hash=61afa22f2b3401bab08c3faeb872e3de7a99ca5b$
 //
 
 #include "libcef_dll/cpptoc/views/window_delegate_cpptoc.h"
@@ -29,12 +29,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: window; type: refptr_diff
   DCHECK(window);
-  if (!window)
+  if (!window) {
     return;
+  }
 
   // Execute
   CefWindowDelegateCppToC::Get(self)->OnWindowCreated(
@@ -42,6 +44,28 @@
 }
 
 void CEF_CALLBACK
+window_delegate_on_window_closing(struct _cef_window_delegate_t* self,
+                                  cef_window_t* window) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: window; type: refptr_diff
+  DCHECK(window);
+  if (!window) {
+    return;
+  }
+
+  // Execute
+  CefWindowDelegateCppToC::Get(self)->OnWindowClosing(
+      CefWindowCToCpp::Wrap(window));
+}
+
+void CEF_CALLBACK
 window_delegate_on_window_destroyed(struct _cef_window_delegate_t* self,
                                     cef_window_t* window) {
   shutdown_checker::AssertNotShutdown();
@@ -49,18 +73,97 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: window; type: refptr_diff
   DCHECK(window);
-  if (!window)
+  if (!window) {
     return;
+  }
 
   // Execute
   CefWindowDelegateCppToC::Get(self)->OnWindowDestroyed(
       CefWindowCToCpp::Wrap(window));
 }
 
+void CEF_CALLBACK window_delegate_on_window_activation_changed(
+    struct _cef_window_delegate_t* self,
+    cef_window_t* window,
+    int active) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: window; type: refptr_diff
+  DCHECK(window);
+  if (!window) {
+    return;
+  }
+
+  // Execute
+  CefWindowDelegateCppToC::Get(self)->OnWindowActivationChanged(
+      CefWindowCToCpp::Wrap(window), active ? true : false);
+}
+
+void CEF_CALLBACK
+window_delegate_on_window_bounds_changed(struct _cef_window_delegate_t* self,
+                                         cef_window_t* window,
+                                         const cef_rect_t* new_bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: window; type: refptr_diff
+  DCHECK(window);
+  if (!window) {
+    return;
+  }
+  // Verify param: new_bounds; type: simple_byref_const
+  DCHECK(new_bounds);
+  if (!new_bounds) {
+    return;
+  }
+
+  // Translate param: new_bounds; type: simple_byref_const
+  CefRect new_boundsVal = new_bounds ? *new_bounds : CefRect();
+
+  // Execute
+  CefWindowDelegateCppToC::Get(self)->OnWindowBoundsChanged(
+      CefWindowCToCpp::Wrap(window), new_boundsVal);
+}
+
+void CEF_CALLBACK window_delegate_on_window_fullscreen_transition(
+    struct _cef_window_delegate_t* self,
+    cef_window_t* window,
+    int is_completed) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: window; type: refptr_diff
+  DCHECK(window);
+  if (!window) {
+    return;
+  }
+
+  // Execute
+  CefWindowDelegateCppToC::Get(self)->OnWindowFullscreenTransition(
+      CefWindowCToCpp::Wrap(window), is_completed ? true : false);
+}
+
 cef_window_t* CEF_CALLBACK
 window_delegate_get_parent_window(struct _cef_window_delegate_t* self,
                                   cef_window_t* window,
@@ -71,20 +174,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: window; type: refptr_diff
   DCHECK(window);
-  if (!window)
+  if (!window) {
     return NULL;
+  }
   // Verify param: is_menu; type: bool_byaddr
   DCHECK(is_menu);
-  if (!is_menu)
+  if (!is_menu) {
     return NULL;
+  }
   // Verify param: can_activate_menu; type: bool_byaddr
   DCHECK(can_activate_menu);
-  if (!can_activate_menu)
+  if (!can_activate_menu) {
     return NULL;
+  }
 
   // Translate param: is_menu; type: bool_byaddr
   bool is_menuBool = (is_menu && *is_menu) ? true : false;
@@ -98,17 +205,95 @@
           CefWindowCToCpp::Wrap(window), &is_menuBool, &can_activate_menuBool);
 
   // Restore param: is_menu; type: bool_byaddr
-  if (is_menu)
+  if (is_menu) {
     *is_menu = is_menuBool ? true : false;
+  }
   // Restore param: can_activate_menu; type: bool_byaddr
-  if (can_activate_menu)
+  if (can_activate_menu) {
     *can_activate_menu = can_activate_menuBool ? true : false;
+  }
 
   // Return type: refptr_diff
   return CefWindowCToCpp::Unwrap(_retval);
 }
 
 int CEF_CALLBACK
+window_delegate_is_window_modal_dialog(struct _cef_window_delegate_t* self,
+                                       cef_window_t* window) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: window; type: refptr_diff
+  DCHECK(window);
+  if (!window) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefWindowDelegateCppToC::Get(self)->IsWindowModalDialog(
+      CefWindowCToCpp::Wrap(window));
+
+  // Return type: bool
+  return _retval;
+}
+
+cef_rect_t CEF_CALLBACK
+window_delegate_get_initial_bounds(struct _cef_window_delegate_t* self,
+                                   cef_window_t* window) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CefRect();
+  }
+  // Verify param: window; type: refptr_diff
+  DCHECK(window);
+  if (!window) {
+    return CefRect();
+  }
+
+  // Execute
+  cef_rect_t _retval = CefWindowDelegateCppToC::Get(self)->GetInitialBounds(
+      CefWindowCToCpp::Wrap(window));
+
+  // Return type: simple
+  return _retval;
+}
+
+cef_show_state_t CEF_CALLBACK
+window_delegate_get_initial_show_state(struct _cef_window_delegate_t* self,
+                                       cef_window_t* window) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return CEF_SHOW_STATE_NORMAL;
+  }
+  // Verify param: window; type: refptr_diff
+  DCHECK(window);
+  if (!window) {
+    return CEF_SHOW_STATE_NORMAL;
+  }
+
+  // Execute
+  cef_show_state_t _retval =
+      CefWindowDelegateCppToC::Get(self)->GetInitialShowState(
+          CefWindowCToCpp::Wrap(window));
+
+  // Return type: simple
+  return _retval;
+}
+
+int CEF_CALLBACK
 window_delegate_is_frameless(struct _cef_window_delegate_t* self,
                              cef_window_t* window) {
   shutdown_checker::AssertNotShutdown();
@@ -116,12 +301,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: window; type: refptr_diff
   DCHECK(window);
-  if (!window)
+  if (!window) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWindowDelegateCppToC::Get(self)->IsFrameless(
@@ -131,6 +318,62 @@
   return _retval;
 }
 
+int CEF_CALLBACK window_delegate_with_standard_window_buttons(
+    struct _cef_window_delegate_t* self,
+    cef_window_t* window) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: window; type: refptr_diff
+  DCHECK(window);
+  if (!window) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefWindowDelegateCppToC::Get(self)->WithStandardWindowButtons(
+      CefWindowCToCpp::Wrap(window));
+
+  // Return type: bool
+  return _retval;
+}
+
+int CEF_CALLBACK
+window_delegate_get_titlebar_height(struct _cef_window_delegate_t* self,
+                                    cef_window_t* window,
+                                    float* titlebar_height) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return 0;
+  }
+  // Verify param: window; type: refptr_diff
+  DCHECK(window);
+  if (!window) {
+    return 0;
+  }
+  // Verify param: titlebar_height; type: simple_byaddr
+  DCHECK(titlebar_height);
+  if (!titlebar_height) {
+    return 0;
+  }
+
+  // Execute
+  bool _retval = CefWindowDelegateCppToC::Get(self)->GetTitlebarHeight(
+      CefWindowCToCpp::Wrap(window), titlebar_height);
+
+  // Return type: bool
+  return _retval;
+}
+
 int CEF_CALLBACK window_delegate_can_resize(struct _cef_window_delegate_t* self,
                                             cef_window_t* window) {
   shutdown_checker::AssertNotShutdown();
@@ -138,12 +381,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: window; type: refptr_diff
   DCHECK(window);
-  if (!window)
+  if (!window) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWindowDelegateCppToC::Get(self)->CanResize(
@@ -161,12 +406,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: window; type: refptr_diff
   DCHECK(window);
-  if (!window)
+  if (!window) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWindowDelegateCppToC::Get(self)->CanMaximize(
@@ -184,12 +431,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: window; type: refptr_diff
   DCHECK(window);
-  if (!window)
+  if (!window) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWindowDelegateCppToC::Get(self)->CanMinimize(
@@ -206,12 +455,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: window; type: refptr_diff
   DCHECK(window);
-  if (!window)
+  if (!window) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWindowDelegateCppToC::Get(self)->CanClose(
@@ -230,12 +481,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: window; type: refptr_diff
   DCHECK(window);
-  if (!window)
+  if (!window) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWindowDelegateCppToC::Get(self)->OnAccelerator(
@@ -248,31 +501,32 @@
 int CEF_CALLBACK
 window_delegate_on_key_event(struct _cef_window_delegate_t* self,
                              cef_window_t* window,
-                             const struct _cef_key_event_t* event) {
+                             const cef_key_event_t* event) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: window; type: refptr_diff
   DCHECK(window);
-  if (!window)
+  if (!window) {
     return 0;
-  // Verify param: event; type: struct_byref_const
+  }
+  // Verify param: event; type: simple_byref_const
   DCHECK(event);
-  if (!event)
+  if (!event) {
     return 0;
+  }
 
-  // Translate param: event; type: struct_byref_const
-  CefKeyEvent eventObj;
-  if (event)
-    eventObj.Set(*event, false);
+  // Translate param: event; type: simple_byref_const
+  CefKeyEvent eventVal = event ? *event : CefKeyEvent();
 
   // Execute
   bool _retval = CefWindowDelegateCppToC::Get(self)->OnKeyEvent(
-      CefWindowCToCpp::Wrap(window), eventObj);
+      CefWindowCToCpp::Wrap(window), eventVal);
 
   // Return type: bool
   return _retval;
@@ -286,12 +540,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefWindowDelegateCppToC::Get(
@@ -310,12 +566,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefWindowDelegateCppToC::Get(
@@ -334,12 +592,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return CefSize();
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval = CefWindowDelegateCppToC::Get(
@@ -359,12 +619,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return 0;
+  }
 
   // Execute
   int _retval = CefWindowDelegateCppToC::Get(
@@ -385,16 +647,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
   // Verify param: parent; type: refptr_diff
   DCHECK(parent);
-  if (!parent)
+  if (!parent) {
     return;
+  }
 
   // Execute
   CefWindowDelegateCppToC::Get(reinterpret_cast<cef_window_delegate_t*>(self))
@@ -412,16 +677,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
   // Verify param: child; type: refptr_diff
   DCHECK(child);
-  if (!child)
+  if (!child) {
     return;
+  }
 
   // Execute
   CefWindowDelegateCppToC::Get(reinterpret_cast<cef_window_delegate_t*>(self))
@@ -429,6 +697,60 @@
                            CefViewCToCpp::Wrap(child));
 }
 
+void CEF_CALLBACK
+window_delegate_on_window_changed(struct _cef_view_delegate_t* self,
+                                  cef_view_t* view,
+                                  int added) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: view; type: refptr_diff
+  DCHECK(view);
+  if (!view) {
+    return;
+  }
+
+  // Execute
+  CefWindowDelegateCppToC::Get(reinterpret_cast<cef_window_delegate_t*>(self))
+      ->OnWindowChanged(CefViewCToCpp::Wrap(view), added ? true : false);
+}
+
+void CEF_CALLBACK
+window_delegate_on_layout_changed(struct _cef_view_delegate_t* self,
+                                  cef_view_t* view,
+                                  const cef_rect_t* new_bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self) {
+    return;
+  }
+  // Verify param: view; type: refptr_diff
+  DCHECK(view);
+  if (!view) {
+    return;
+  }
+  // Verify param: new_bounds; type: simple_byref_const
+  DCHECK(new_bounds);
+  if (!new_bounds) {
+    return;
+  }
+
+  // Translate param: new_bounds; type: simple_byref_const
+  CefRect new_boundsVal = new_bounds ? *new_bounds : CefRect();
+
+  // Execute
+  CefWindowDelegateCppToC::Get(reinterpret_cast<cef_window_delegate_t*>(self))
+      ->OnLayoutChanged(CefViewCToCpp::Wrap(view), new_boundsVal);
+}
+
 void CEF_CALLBACK window_delegate_on_focus(struct _cef_view_delegate_t* self,
                                            cef_view_t* view) {
   shutdown_checker::AssertNotShutdown();
@@ -436,12 +758,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefWindowDelegateCppToC::Get(reinterpret_cast<cef_window_delegate_t*>(self))
@@ -455,12 +779,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: view; type: refptr_diff
   DCHECK(view);
-  if (!view)
+  if (!view) {
     return;
+  }
 
   // Execute
   CefWindowDelegateCppToC::Get(reinterpret_cast<cef_window_delegate_t*>(self))
@@ -473,9 +799,22 @@
 
 CefWindowDelegateCppToC::CefWindowDelegateCppToC() {
   GetStruct()->on_window_created = window_delegate_on_window_created;
+  GetStruct()->on_window_closing = window_delegate_on_window_closing;
   GetStruct()->on_window_destroyed = window_delegate_on_window_destroyed;
+  GetStruct()->on_window_activation_changed =
+      window_delegate_on_window_activation_changed;
+  GetStruct()->on_window_bounds_changed =
+      window_delegate_on_window_bounds_changed;
+  GetStruct()->on_window_fullscreen_transition =
+      window_delegate_on_window_fullscreen_transition;
   GetStruct()->get_parent_window = window_delegate_get_parent_window;
+  GetStruct()->is_window_modal_dialog = window_delegate_is_window_modal_dialog;
+  GetStruct()->get_initial_bounds = window_delegate_get_initial_bounds;
+  GetStruct()->get_initial_show_state = window_delegate_get_initial_show_state;
   GetStruct()->is_frameless = window_delegate_is_frameless;
+  GetStruct()->with_standard_window_buttons =
+      window_delegate_with_standard_window_buttons;
+  GetStruct()->get_titlebar_height = window_delegate_get_titlebar_height;
   GetStruct()->can_resize = window_delegate_can_resize;
   GetStruct()->can_maximize = window_delegate_can_maximize;
   GetStruct()->can_minimize = window_delegate_can_minimize;
@@ -492,6 +831,8 @@
       window_delegate_on_parent_view_changed;
   GetStruct()->base.base.on_child_view_changed =
       window_delegate_on_child_view_changed;
+  GetStruct()->base.base.on_window_changed = window_delegate_on_window_changed;
+  GetStruct()->base.base.on_layout_changed = window_delegate_on_layout_changed;
   GetStruct()->base.base.on_focus = window_delegate_on_focus;
   GetStruct()->base.base.on_blur = window_delegate_on_blur;
 }
@@ -508,7 +849,7 @@
     CefWindowDelegate,
     cef_window_delegate_t>::UnwrapDerived(CefWrapperType type,
                                           cef_window_delegate_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/views/window_delegate_cpptoc.h b/src/libcef_dll/cpptoc/views/window_delegate_cpptoc.h
index 17b1076..441a2ca 100644
--- a/src/libcef_dll/cpptoc/views/window_delegate_cpptoc.h
+++ b/src/libcef_dll/cpptoc/views/window_delegate_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b88ec555034d3c63e80d13471f7da921ea8ef70a$
+// $hash=b4d82958ac79ac843f904c4aa8010a6909ca06fa$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_VIEWS_WINDOW_DELEGATE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/waitable_event_cpptoc.cc b/src/libcef_dll/cpptoc/waitable_event_cpptoc.cc
index 07ace17..39b3e4e 100644
--- a/src/libcef_dll/cpptoc/waitable_event_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/waitable_event_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9251c1a72b2ece747624e43953dbd476e68a62a2$
+// $hash=4c688a2d144f2eb55e47735f048596fd8f4914eb$
 //
 
 #include "libcef_dll/cpptoc/waitable_event_cpptoc.h"
@@ -42,8 +42,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWaitableEventCppToC::Get(self)->Reset();
@@ -55,8 +56,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWaitableEventCppToC::Get(self)->Signal();
@@ -69,8 +71,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWaitableEventCppToC::Get(self)->IsSignaled();
@@ -85,22 +88,24 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
 
   // Execute
   CefWaitableEventCppToC::Get(self)->Wait();
 }
 
 int CEF_CALLBACK waitable_event_timed_wait(struct _cef_waitable_event_t* self,
-                                           int64 max_ms) {
+                                           int64_t max_ms) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWaitableEventCppToC::Get(self)->TimedWait(max_ms);
@@ -133,7 +138,7 @@
     CefWaitableEvent,
     cef_waitable_event_t>::UnwrapDerived(CefWrapperType type,
                                          cef_waitable_event_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/waitable_event_cpptoc.h b/src/libcef_dll/cpptoc/waitable_event_cpptoc.h
index 60cb2fe..1e1ba61 100644
--- a/src/libcef_dll/cpptoc/waitable_event_cpptoc.h
+++ b/src/libcef_dll/cpptoc/waitable_event_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d9c0c0cbb9298c485ae33ebcd51449bcc9d2ad68$
+// $hash=c3d08738052ecc67921493df15ea0df38c040314$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_WAITABLE_EVENT_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/web_plugin_info_cpptoc.cc b/src/libcef_dll/cpptoc/web_plugin_info_cpptoc.cc
deleted file mode 100644
index bb993eb..0000000
--- a/src/libcef_dll/cpptoc/web_plugin_info_cpptoc.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=17553c276ccdfd3d27c552d8ae7bedfe7a458f9a$
-//
-
-#include "libcef_dll/cpptoc/web_plugin_info_cpptoc.h"
-#include "libcef_dll/shutdown_checker.h"
-
-namespace {
-
-// MEMBER FUNCTIONS - Body may be edited by hand.
-
-cef_string_userfree_t CEF_CALLBACK
-web_plugin_info_get_name(struct _cef_web_plugin_info_t* self) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return NULL;
-
-  // Execute
-  CefString _retval = CefWebPluginInfoCppToC::Get(self)->GetName();
-
-  // Return type: string
-  return _retval.DetachToUserFree();
-}
-
-cef_string_userfree_t CEF_CALLBACK
-web_plugin_info_get_path(struct _cef_web_plugin_info_t* self) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return NULL;
-
-  // Execute
-  CefString _retval = CefWebPluginInfoCppToC::Get(self)->GetPath();
-
-  // Return type: string
-  return _retval.DetachToUserFree();
-}
-
-cef_string_userfree_t CEF_CALLBACK
-web_plugin_info_get_version(struct _cef_web_plugin_info_t* self) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return NULL;
-
-  // Execute
-  CefString _retval = CefWebPluginInfoCppToC::Get(self)->GetVersion();
-
-  // Return type: string
-  return _retval.DetachToUserFree();
-}
-
-cef_string_userfree_t CEF_CALLBACK
-web_plugin_info_get_description(struct _cef_web_plugin_info_t* self) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return NULL;
-
-  // Execute
-  CefString _retval = CefWebPluginInfoCppToC::Get(self)->GetDescription();
-
-  // Return type: string
-  return _retval.DetachToUserFree();
-}
-
-}  // namespace
-
-// CONSTRUCTOR - Do not edit by hand.
-
-CefWebPluginInfoCppToC::CefWebPluginInfoCppToC() {
-  GetStruct()->get_name = web_plugin_info_get_name;
-  GetStruct()->get_path = web_plugin_info_get_path;
-  GetStruct()->get_version = web_plugin_info_get_version;
-  GetStruct()->get_description = web_plugin_info_get_description;
-}
-
-// DESTRUCTOR - Do not edit by hand.
-
-CefWebPluginInfoCppToC::~CefWebPluginInfoCppToC() {
-  shutdown_checker::AssertNotShutdown();
-}
-
-template <>
-CefRefPtr<CefWebPluginInfo> CefCppToCRefCounted<
-    CefWebPluginInfoCppToC,
-    CefWebPluginInfo,
-    cef_web_plugin_info_t>::UnwrapDerived(CefWrapperType type,
-                                          cef_web_plugin_info_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
-  return nullptr;
-}
-
-template <>
-CefWrapperType CefCppToCRefCounted<CefWebPluginInfoCppToC,
-                                   CefWebPluginInfo,
-                                   cef_web_plugin_info_t>::kWrapperType =
-    WT_WEB_PLUGIN_INFO;
diff --git a/src/libcef_dll/cpptoc/web_plugin_info_cpptoc.h b/src/libcef_dll/cpptoc/web_plugin_info_cpptoc.h
deleted file mode 100644
index 59844d5..0000000
--- a/src/libcef_dll/cpptoc/web_plugin_info_cpptoc.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=fce7bf500cfdd2e1e21655477a167272e4f89310$
-//
-
-#ifndef CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_INFO_CPPTOC_H_
-#define CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_INFO_CPPTOC_H_
-#pragma once
-
-#if !defined(BUILDING_CEF_SHARED)
-#error This file can be included DLL-side only
-#endif
-
-#include "include/capi/cef_browser_capi.h"
-#include "include/capi/cef_web_plugin_capi.h"
-#include "include/cef_browser.h"
-#include "include/cef_web_plugin.h"
-#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
-
-// Wrap a C++ class with a C structure.
-// This class may be instantiated and accessed DLL-side only.
-class CefWebPluginInfoCppToC
-    : public CefCppToCRefCounted<CefWebPluginInfoCppToC,
-                                 CefWebPluginInfo,
-                                 cef_web_plugin_info_t> {
- public:
-  CefWebPluginInfoCppToC();
-  virtual ~CefWebPluginInfoCppToC();
-};
-
-#endif  // CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_INFO_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.cc b/src/libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.cc
deleted file mode 100644
index 117f343..0000000
--- a/src/libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=9bf14398237548c7290ae748ac62833f3d0f1830$
-//
-
-#include "libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.h"
-#include "libcef_dll/ctocpp/web_plugin_info_ctocpp.h"
-#include "libcef_dll/shutdown_checker.h"
-
-namespace {
-
-// MEMBER FUNCTIONS - Body may be edited by hand.
-
-int CEF_CALLBACK
-web_plugin_info_visitor_visit(struct _cef_web_plugin_info_visitor_t* self,
-                              cef_web_plugin_info_t* info,
-                              int count,
-                              int total) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return 0;
-  // Verify param: info; type: refptr_diff
-  DCHECK(info);
-  if (!info)
-    return 0;
-
-  // Execute
-  bool _retval = CefWebPluginInfoVisitorCppToC::Get(self)->Visit(
-      CefWebPluginInfoCToCpp::Wrap(info), count, total);
-
-  // Return type: bool
-  return _retval;
-}
-
-}  // namespace
-
-// CONSTRUCTOR - Do not edit by hand.
-
-CefWebPluginInfoVisitorCppToC::CefWebPluginInfoVisitorCppToC() {
-  GetStruct()->visit = web_plugin_info_visitor_visit;
-}
-
-// DESTRUCTOR - Do not edit by hand.
-
-CefWebPluginInfoVisitorCppToC::~CefWebPluginInfoVisitorCppToC() {
-  shutdown_checker::AssertNotShutdown();
-}
-
-template <>
-CefRefPtr<CefWebPluginInfoVisitor> CefCppToCRefCounted<
-    CefWebPluginInfoVisitorCppToC,
-    CefWebPluginInfoVisitor,
-    cef_web_plugin_info_visitor_t>::UnwrapDerived(CefWrapperType type,
-                                                  cef_web_plugin_info_visitor_t*
-                                                      s) {
-  NOTREACHED() << "Unexpected class type: " << type;
-  return nullptr;
-}
-
-template <>
-CefWrapperType
-    CefCppToCRefCounted<CefWebPluginInfoVisitorCppToC,
-                        CefWebPluginInfoVisitor,
-                        cef_web_plugin_info_visitor_t>::kWrapperType =
-        WT_WEB_PLUGIN_INFO_VISITOR;
diff --git a/src/libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.h b/src/libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.h
deleted file mode 100644
index 0a7767e..0000000
--- a/src/libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=45695bea6b9ce6484f1321fd84bf11521d732b2c$
-//
-
-#ifndef CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_INFO_VISITOR_CPPTOC_H_
-#define CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_INFO_VISITOR_CPPTOC_H_
-#pragma once
-
-#if !defined(WRAPPING_CEF_SHARED)
-#error This file can be included wrapper-side only
-#endif
-
-#include "include/capi/cef_browser_capi.h"
-#include "include/capi/cef_web_plugin_capi.h"
-#include "include/cef_browser.h"
-#include "include/cef_web_plugin.h"
-#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
-
-// Wrap a C++ class with a C structure.
-// This class may be instantiated and accessed wrapper-side only.
-class CefWebPluginInfoVisitorCppToC
-    : public CefCppToCRefCounted<CefWebPluginInfoVisitorCppToC,
-                                 CefWebPluginInfoVisitor,
-                                 cef_web_plugin_info_visitor_t> {
- public:
-  CefWebPluginInfoVisitorCppToC();
-  virtual ~CefWebPluginInfoVisitorCppToC();
-};
-
-#endif  // CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_INFO_VISITOR_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.cc b/src/libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.cc
deleted file mode 100644
index f62517b..0000000
--- a/src/libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=a0757524464550a80541e4a57f1a8d285098fcdd$
-//
-
-#include "libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.h"
-#include "libcef_dll/shutdown_checker.h"
-
-namespace {
-
-// MEMBER FUNCTIONS - Body may be edited by hand.
-
-void CEF_CALLBACK web_plugin_unstable_callback_is_unstable(
-    struct _cef_web_plugin_unstable_callback_t* self,
-    const cef_string_t* path,
-    int unstable) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return;
-  // Verify param: path; type: string_byref_const
-  DCHECK(path);
-  if (!path)
-    return;
-
-  // Execute
-  CefWebPluginUnstableCallbackCppToC::Get(self)->IsUnstable(
-      CefString(path), unstable ? true : false);
-}
-
-}  // namespace
-
-// CONSTRUCTOR - Do not edit by hand.
-
-CefWebPluginUnstableCallbackCppToC::CefWebPluginUnstableCallbackCppToC() {
-  GetStruct()->is_unstable = web_plugin_unstable_callback_is_unstable;
-}
-
-// DESTRUCTOR - Do not edit by hand.
-
-CefWebPluginUnstableCallbackCppToC::~CefWebPluginUnstableCallbackCppToC() {
-  shutdown_checker::AssertNotShutdown();
-}
-
-template <>
-CefRefPtr<CefWebPluginUnstableCallback>
-CefCppToCRefCounted<CefWebPluginUnstableCallbackCppToC,
-                    CefWebPluginUnstableCallback,
-                    cef_web_plugin_unstable_callback_t>::
-    UnwrapDerived(CefWrapperType type, cef_web_plugin_unstable_callback_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
-  return nullptr;
-}
-
-template <>
-CefWrapperType
-    CefCppToCRefCounted<CefWebPluginUnstableCallbackCppToC,
-                        CefWebPluginUnstableCallback,
-                        cef_web_plugin_unstable_callback_t>::kWrapperType =
-        WT_WEB_PLUGIN_UNSTABLE_CALLBACK;
diff --git a/src/libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.h b/src/libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.h
deleted file mode 100644
index 44007f0..0000000
--- a/src/libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=3cd5a5c45b499f6bd65776affa5bab00d7994678$
-//
-
-#ifndef CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_UNSTABLE_CALLBACK_CPPTOC_H_
-#define CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_UNSTABLE_CALLBACK_CPPTOC_H_
-#pragma once
-
-#if !defined(WRAPPING_CEF_SHARED)
-#error This file can be included wrapper-side only
-#endif
-
-#include "include/capi/cef_browser_capi.h"
-#include "include/capi/cef_web_plugin_capi.h"
-#include "include/cef_browser.h"
-#include "include/cef_web_plugin.h"
-#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
-
-// Wrap a C++ class with a C structure.
-// This class may be instantiated and accessed wrapper-side only.
-class CefWebPluginUnstableCallbackCppToC
-    : public CefCppToCRefCounted<CefWebPluginUnstableCallbackCppToC,
-                                 CefWebPluginUnstableCallback,
-                                 cef_web_plugin_unstable_callback_t> {
- public:
-  CefWebPluginUnstableCallbackCppToC();
-  virtual ~CefWebPluginUnstableCallbackCppToC();
-};
-
-#endif  // CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_UNSTABLE_CALLBACK_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/write_handler_cpptoc.cc b/src/libcef_dll/cpptoc/write_handler_cpptoc.cc
index d268b33..f0a9e59 100644
--- a/src/libcef_dll/cpptoc/write_handler_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/write_handler_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6a7b209717d88fb7868b7a098b9a569920f6b255$
+// $hash=c3caec6488343dacaf00231a9304bcd4b3c95d9e$
 //
 
 #include "libcef_dll/cpptoc/write_handler_cpptoc.h"
@@ -28,12 +28,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: ptr; type: simple_byaddr
   DCHECK(ptr);
-  if (!ptr)
+  if (!ptr) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefWriteHandlerCppToC::Get(self)->Write(ptr, size, n);
@@ -43,15 +45,16 @@
 }
 
 int CEF_CALLBACK write_handler_seek(struct _cef_write_handler_t* self,
-                                    int64 offset,
+                                    int64_t offset,
                                     int whence) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefWriteHandlerCppToC::Get(self)->Seek(offset, whence);
@@ -60,17 +63,18 @@
   return _retval;
 }
 
-int64 CEF_CALLBACK write_handler_tell(struct _cef_write_handler_t* self) {
+int64_t CEF_CALLBACK write_handler_tell(struct _cef_write_handler_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
-  int64 _retval = CefWriteHandlerCppToC::Get(self)->Tell();
+  int64_t _retval = CefWriteHandlerCppToC::Get(self)->Tell();
 
   // Return type: simple
   return _retval;
@@ -82,8 +86,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefWriteHandlerCppToC::Get(self)->Flush();
@@ -98,8 +103,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefWriteHandlerCppToC::Get(self)->MayBlock();
@@ -132,7 +138,7 @@
     CefWriteHandler,
     cef_write_handler_t>::UnwrapDerived(CefWrapperType type,
                                         cef_write_handler_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/write_handler_cpptoc.h b/src/libcef_dll/cpptoc/write_handler_cpptoc.h
index 4f1754b..60a0ba7 100644
--- a/src/libcef_dll/cpptoc/write_handler_cpptoc.h
+++ b/src/libcef_dll/cpptoc/write_handler_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=5b10bd732535800c090c3000f95a2e7c8bdfe773$
+// $hash=94c67ea9a0a7a44b92ef2d322f7dd34490f5b8e6$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_WRITE_HANDLER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/x509cert_principal_cpptoc.cc b/src/libcef_dll/cpptoc/x509cert_principal_cpptoc.cc
index 409292a..5237967 100644
--- a/src/libcef_dll/cpptoc/x509cert_principal_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/x509cert_principal_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8780097b60810a7f952f0a2169ebc925cb63b5e1$
+// $hash=74394106da192b6b9fc284bbf8899ae3d5ea0b8d$
 //
 
 #include "libcef_dll/cpptoc/x509cert_principal_cpptoc.h"
@@ -27,8 +27,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefX509CertPrincipalCppToC::Get(self)->GetDisplayName();
@@ -44,8 +45,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefX509CertPrincipalCppToC::Get(self)->GetCommonName();
@@ -61,8 +63,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefX509CertPrincipalCppToC::Get(self)->GetLocalityName();
@@ -79,8 +82,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -97,8 +101,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefX509CertPrincipalCppToC::Get(self)->GetCountryName();
@@ -107,33 +112,6 @@
   return _retval.DetachToUserFree();
 }
 
-void CEF_CALLBACK
-x509cert_principal_get_street_addresses(struct _cef_x509cert_principal_t* self,
-                                        cef_string_list_t addresses) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return;
-  // Verify param: addresses; type: string_vec_byref
-  DCHECK(addresses);
-  if (!addresses)
-    return;
-
-  // Translate param: addresses; type: string_vec_byref
-  std::vector<CefString> addressesList;
-  transfer_string_list_contents(addresses, addressesList);
-
-  // Execute
-  CefX509CertPrincipalCppToC::Get(self)->GetStreetAddresses(addressesList);
-
-  // Restore param: addresses; type: string_vec_byref
-  cef_string_list_clear(addresses);
-  transfer_string_list_contents(addressesList, addresses);
-}
-
 void CEF_CALLBACK x509cert_principal_get_organization_names(
     struct _cef_x509cert_principal_t* self,
     cef_string_list_t names) {
@@ -142,12 +120,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: names; type: string_vec_byref
   DCHECK(names);
-  if (!names)
+  if (!names) {
     return;
+  }
 
   // Translate param: names; type: string_vec_byref
   std::vector<CefString> namesList;
@@ -169,12 +149,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: names; type: string_vec_byref
   DCHECK(names);
-  if (!names)
+  if (!names) {
     return;
+  }
 
   // Translate param: names; type: string_vec_byref
   std::vector<CefString> namesList;
@@ -188,33 +170,6 @@
   transfer_string_list_contents(namesList, names);
 }
 
-void CEF_CALLBACK
-x509cert_principal_get_domain_components(struct _cef_x509cert_principal_t* self,
-                                         cef_string_list_t components) {
-  shutdown_checker::AssertNotShutdown();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  DCHECK(self);
-  if (!self)
-    return;
-  // Verify param: components; type: string_vec_byref
-  DCHECK(components);
-  if (!components)
-    return;
-
-  // Translate param: components; type: string_vec_byref
-  std::vector<CefString> componentsList;
-  transfer_string_list_contents(components, componentsList);
-
-  // Execute
-  CefX509CertPrincipalCppToC::Get(self)->GetDomainComponents(componentsList);
-
-  // Restore param: components; type: string_vec_byref
-  cef_string_list_clear(components);
-  transfer_string_list_contents(componentsList, components);
-}
-
 }  // namespace
 
 // CONSTRUCTOR - Do not edit by hand.
@@ -226,12 +181,10 @@
   GetStruct()->get_state_or_province_name =
       x509cert_principal_get_state_or_province_name;
   GetStruct()->get_country_name = x509cert_principal_get_country_name;
-  GetStruct()->get_street_addresses = x509cert_principal_get_street_addresses;
   GetStruct()->get_organization_names =
       x509cert_principal_get_organization_names;
   GetStruct()->get_organization_unit_names =
       x509cert_principal_get_organization_unit_names;
-  GetStruct()->get_domain_components = x509cert_principal_get_domain_components;
 }
 
 // DESTRUCTOR - Do not edit by hand.
@@ -246,7 +199,7 @@
     CefX509CertPrincipal,
     cef_x509cert_principal_t>::UnwrapDerived(CefWrapperType type,
                                              cef_x509cert_principal_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/x509cert_principal_cpptoc.h b/src/libcef_dll/cpptoc/x509cert_principal_cpptoc.h
index 6600abc..8aba2d6 100644
--- a/src/libcef_dll/cpptoc/x509cert_principal_cpptoc.h
+++ b/src/libcef_dll/cpptoc/x509cert_principal_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1479667eef11356f361b39fb04156231adcb551d$
+// $hash=6e97a51d6d111d04e88c67e98eff127d7ca09dc1$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_X509CERT_PRINCIPAL_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/x509certificate_cpptoc.cc b/src/libcef_dll/cpptoc/x509certificate_cpptoc.cc
index 5a7e026..e9e1793 100644
--- a/src/libcef_dll/cpptoc/x509certificate_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/x509certificate_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b65d54f4da2586c066c6027fc3f3dbfdde465841$
+// $hash=e9f8f124502684b0e814730ea52aed7c87fef3b3$
 //
 
 #include "libcef_dll/cpptoc/x509certificate_cpptoc.h"
@@ -29,8 +29,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefX509CertPrincipal> _retval =
@@ -47,8 +48,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefX509CertPrincipal> _retval =
@@ -65,8 +67,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBinaryValue> _retval =
@@ -76,35 +79,38 @@
   return CefBinaryValueCppToC::Wrap(_retval);
 }
 
-cef_time_t CEF_CALLBACK
+cef_basetime_t CEF_CALLBACK
 x509certificate_get_valid_start(struct _cef_x509certificate_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
-    return CefTime();
+  if (!self) {
+    return CefBaseTime();
+  }
 
   // Execute
-  cef_time_t _retval = CefX509CertificateCppToC::Get(self)->GetValidStart();
+  cef_basetime_t _retval = CefX509CertificateCppToC::Get(self)->GetValidStart();
 
   // Return type: simple
   return _retval;
 }
 
-cef_time_t CEF_CALLBACK
+cef_basetime_t CEF_CALLBACK
 x509certificate_get_valid_expiry(struct _cef_x509certificate_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
-    return CefTime();
+  if (!self) {
+    return CefBaseTime();
+  }
 
   // Execute
-  cef_time_t _retval = CefX509CertificateCppToC::Get(self)->GetValidExpiry();
+  cef_basetime_t _retval =
+      CefX509CertificateCppToC::Get(self)->GetValidExpiry();
 
   // Return type: simple
   return _retval;
@@ -117,8 +123,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBinaryValue> _retval =
@@ -135,8 +142,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBinaryValue> _retval =
@@ -153,8 +161,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefX509CertificateCppToC::Get(self)->GetIssuerChainSize();
@@ -172,12 +181,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: chain; type: refptr_vec_same_byref
   DCHECK(chainCount && (*chainCount == 0 || chain));
-  if (!chainCount || (*chainCount > 0 && !chain))
+  if (!chainCount || (*chainCount > 0 && !chain)) {
     return;
+  }
 
   // Translate param: chain; type: refptr_vec_same_byref
   std::vector<CefRefPtr<CefBinaryValue>> chainList;
@@ -210,12 +221,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return;
+  }
   // Verify param: chain; type: refptr_vec_same_byref
   DCHECK(chainCount && (*chainCount == 0 || chain));
-  if (!chainCount || (*chainCount > 0 && !chain))
+  if (!chainCount || (*chainCount > 0 && !chain)) {
     return;
+  }
 
   // Translate param: chain; type: refptr_vec_same_byref
   std::vector<CefRefPtr<CefBinaryValue>> chainList;
@@ -270,7 +283,7 @@
     CefX509Certificate,
     cef_x509certificate_t>::UnwrapDerived(CefWrapperType type,
                                           cef_x509certificate_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/x509certificate_cpptoc.h b/src/libcef_dll/cpptoc/x509certificate_cpptoc.h
index 1d0000f..6ef9027 100644
--- a/src/libcef_dll/cpptoc/x509certificate_cpptoc.h
+++ b/src/libcef_dll/cpptoc/x509certificate_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1bde7dcc51e94b88d49b7e277708bd4230272ee0$
+// $hash=11090b23faf77d87bde0a603e74a0697be58fa7c$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_X509CERTIFICATE_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/xml_reader_cpptoc.cc b/src/libcef_dll/cpptoc/xml_reader_cpptoc.cc
index cb241b1..a258cfc 100644
--- a/src/libcef_dll/cpptoc/xml_reader_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/xml_reader_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ba90249fc88623c9e1dc7f4b0d5a2c17e6f9b664$
+// $hash=438fff1d95401704336388ff2b971403e4074ad1$
 //
 
 #include "libcef_dll/cpptoc/xml_reader_cpptoc.h"
@@ -28,12 +28,14 @@
 
   // Verify param: stream; type: refptr_same
   DCHECK(stream);
-  if (!stream)
+  if (!stream) {
     return NULL;
+  }
   // Verify param: URI; type: string_byref_const
   DCHECK(URI);
-  if (!URI)
+  if (!URI) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefXmlReader> _retval = CefXmlReader::Create(
@@ -53,8 +55,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefXmlReaderCppToC::Get(self)->MoveToNextNode();
@@ -69,8 +72,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefXmlReaderCppToC::Get(self)->Close();
@@ -85,8 +89,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefXmlReaderCppToC::Get(self)->HasError();
@@ -102,8 +107,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefXmlReaderCppToC::Get(self)->GetError();
@@ -119,8 +125,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return XML_NODE_UNSUPPORTED;
+  }
 
   // Execute
   cef_xml_node_type_t _retval = CefXmlReaderCppToC::Get(self)->GetType();
@@ -135,8 +142,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefXmlReaderCppToC::Get(self)->GetDepth();
@@ -152,8 +160,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefXmlReaderCppToC::Get(self)->GetLocalName();
@@ -169,8 +178,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefXmlReaderCppToC::Get(self)->GetPrefix();
@@ -186,8 +196,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefXmlReaderCppToC::Get(self)->GetQualifiedName();
@@ -203,8 +214,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefXmlReaderCppToC::Get(self)->GetNamespaceURI();
@@ -220,8 +232,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefXmlReaderCppToC::Get(self)->GetBaseURI();
@@ -237,8 +250,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefXmlReaderCppToC::Get(self)->GetXmlLang();
@@ -253,8 +267,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefXmlReaderCppToC::Get(self)->IsEmptyElement();
@@ -269,8 +284,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefXmlReaderCppToC::Get(self)->HasValue();
@@ -286,8 +302,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefXmlReaderCppToC::Get(self)->GetValue();
@@ -302,8 +319,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefXmlReaderCppToC::Get(self)->HasAttributes();
@@ -319,8 +337,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   size_t _retval = CefXmlReaderCppToC::Get(self)->GetAttributeCount();
@@ -336,12 +355,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefXmlReaderCppToC::Get(self)->GetAttribute(index);
@@ -358,12 +379,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: qualifiedName; type: string_byref_const
   DCHECK(qualifiedName);
-  if (!qualifiedName)
+  if (!qualifiedName) {
     return NULL;
+  }
 
   // Execute
   CefString _retval =
@@ -382,16 +405,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
   // Verify param: localName; type: string_byref_const
   DCHECK(localName);
-  if (!localName)
+  if (!localName) {
     return NULL;
+  }
   // Verify param: namespaceURI; type: string_byref_const
   DCHECK(namespaceURI);
-  if (!namespaceURI)
+  if (!namespaceURI) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefXmlReaderCppToC::Get(self)->GetAttribute(
@@ -408,8 +434,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefXmlReaderCppToC::Get(self)->GetInnerXml();
@@ -425,8 +452,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefXmlReaderCppToC::Get(self)->GetOuterXml();
@@ -441,8 +469,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   int _retval = CefXmlReaderCppToC::Get(self)->GetLineNumber();
@@ -459,12 +488,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefXmlReaderCppToC::Get(self)->MoveToAttribute(index);
@@ -481,12 +512,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: qualifiedName; type: string_byref_const
   DCHECK(qualifiedName);
-  if (!qualifiedName)
+  if (!qualifiedName) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -505,16 +538,19 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: localName; type: string_byref_const
   DCHECK(localName);
-  if (!localName)
+  if (!localName) {
     return 0;
+  }
   // Verify param: namespaceURI; type: string_byref_const
   DCHECK(namespaceURI);
-  if (!namespaceURI)
+  if (!namespaceURI) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefXmlReaderCppToC::Get(self)->MoveToAttribute(
@@ -531,8 +567,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefXmlReaderCppToC::Get(self)->MoveToFirstAttribute();
@@ -548,8 +585,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefXmlReaderCppToC::Get(self)->MoveToNextAttribute();
@@ -565,8 +603,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefXmlReaderCppToC::Get(self)->MoveToCarryingElement();
@@ -621,7 +660,7 @@
 CefRefPtr<CefXmlReader>
 CefCppToCRefCounted<CefXmlReaderCppToC, CefXmlReader, cef_xml_reader_t>::
     UnwrapDerived(CefWrapperType type, cef_xml_reader_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/xml_reader_cpptoc.h b/src/libcef_dll/cpptoc/xml_reader_cpptoc.h
index ba72e4b..0a69e23 100644
--- a/src/libcef_dll/cpptoc/xml_reader_cpptoc.h
+++ b/src/libcef_dll/cpptoc/xml_reader_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c0156e6e184a530e6be658669a46f918ca301ab5$
+// $hash=1305b95acf584a0a0e5fd412e948f195233f476b$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_XML_READER_CPPTOC_H_
diff --git a/src/libcef_dll/cpptoc/zip_reader_cpptoc.cc b/src/libcef_dll/cpptoc/zip_reader_cpptoc.cc
index 55a7a98..ebb06a1 100644
--- a/src/libcef_dll/cpptoc/zip_reader_cpptoc.cc
+++ b/src/libcef_dll/cpptoc/zip_reader_cpptoc.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e5b0f5920957b5db2ff2caff30f5547d4dd3e95f$
+// $hash=81049bd86aaa1a24f963364c61f766dd086598d5$
 //
 
 #include "libcef_dll/cpptoc/zip_reader_cpptoc.h"
@@ -26,8 +26,9 @@
 
   // Verify param: stream; type: refptr_same
   DCHECK(stream);
-  if (!stream)
+  if (!stream) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefZipReader> _retval =
@@ -47,8 +48,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefZipReaderCppToC::Get(self)->MoveToFirstFile();
@@ -63,8 +65,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefZipReaderCppToC::Get(self)->MoveToNextFile();
@@ -81,12 +84,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: fileName; type: string_byref_const
   DCHECK(fileName);
-  if (!fileName)
+  if (!fileName) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefZipReaderCppToC::Get(self)->MoveToFile(
@@ -102,8 +107,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefZipReaderCppToC::Get(self)->Close();
@@ -119,8 +125,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefZipReaderCppToC::Get(self)->GetFileName();
@@ -129,34 +136,36 @@
   return _retval.DetachToUserFree();
 }
 
-int64 CEF_CALLBACK zip_reader_get_file_size(struct _cef_zip_reader_t* self) {
+int64_t CEF_CALLBACK zip_reader_get_file_size(struct _cef_zip_reader_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
-  int64 _retval = CefZipReaderCppToC::Get(self)->GetFileSize();
+  int64_t _retval = CefZipReaderCppToC::Get(self)->GetFileSize();
 
   // Return type: simple
   return _retval;
 }
 
-cef_time_t CEF_CALLBACK
+cef_basetime_t CEF_CALLBACK
 zip_reader_get_file_last_modified(struct _cef_zip_reader_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
-    return CefTime();
+  if (!self) {
+    return CefBaseTime();
+  }
 
   // Execute
-  cef_time_t _retval = CefZipReaderCppToC::Get(self)->GetFileLastModified();
+  cef_basetime_t _retval = CefZipReaderCppToC::Get(self)->GetFileLastModified();
 
   // Return type: simple
   return _retval;
@@ -169,8 +178,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Unverified params: password
 
   // Execute
@@ -186,8 +196,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefZipReaderCppToC::Get(self)->CloseFile();
@@ -204,12 +215,14 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
   // Verify param: buffer; type: simple_byaddr
   DCHECK(buffer);
-  if (!buffer)
+  if (!buffer) {
     return 0;
+  }
 
   // Execute
   int _retval = CefZipReaderCppToC::Get(self)->ReadFile(buffer, bufferSize);
@@ -218,17 +231,18 @@
   return _retval;
 }
 
-int64 CEF_CALLBACK zip_reader_tell(struct _cef_zip_reader_t* self) {
+int64_t CEF_CALLBACK zip_reader_tell(struct _cef_zip_reader_t* self) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
-  int64 _retval = CefZipReaderCppToC::Get(self)->Tell();
+  int64_t _retval = CefZipReaderCppToC::Get(self)->Tell();
 
   // Return type: simple
   return _retval;
@@ -240,8 +254,9 @@
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   DCHECK(self);
-  if (!self)
+  if (!self) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefZipReaderCppToC::Get(self)->Eof();
@@ -279,7 +294,7 @@
 CefRefPtr<CefZipReader>
 CefCppToCRefCounted<CefZipReaderCppToC, CefZipReader, cef_zip_reader_t>::
     UnwrapDerived(CefWrapperType type, cef_zip_reader_t* s) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/cpptoc/zip_reader_cpptoc.h b/src/libcef_dll/cpptoc/zip_reader_cpptoc.h
index 554840d..06233d3 100644
--- a/src/libcef_dll/cpptoc/zip_reader_cpptoc.h
+++ b/src/libcef_dll/cpptoc/zip_reader_cpptoc.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=07d189631f14e4b6af97b3bd01394dae866efade$
+// $hash=488ca93df16ff22fdd9d397aab117990f01f3331$
 //
 
 #ifndef CEF_LIBCEF_DLL_CPPTOC_ZIP_READER_CPPTOC_H_
diff --git a/src/libcef_dll/ctocpp/accessibility_handler_ctocpp.cc b/src/libcef_dll/ctocpp/accessibility_handler_ctocpp.cc
index 3327abf..3d09c48 100644
--- a/src/libcef_dll/ctocpp/accessibility_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/accessibility_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8bd602ae38dd8210a27c6fc0671c97d79268633c$
+// $hash=1833e824ccf9b8b5aa8a22ab4f0e731b3296603c$
 //
 
 #include "libcef_dll/ctocpp/accessibility_handler_ctocpp.h"
@@ -24,15 +24,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_accessibility_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_accessibility_tree_change))
+  if (CEF_MEMBER_MISSING(_struct, on_accessibility_tree_change)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: value; type: refptr_diff
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return;
+  }
 
   // Execute
   _struct->on_accessibility_tree_change(_struct, CefValueCppToC::Wrap(value));
@@ -44,15 +46,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_accessibility_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_accessibility_location_change))
+  if (CEF_MEMBER_MISSING(_struct, on_accessibility_location_change)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: value; type: refptr_diff
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return;
+  }
 
   // Execute
   _struct->on_accessibility_location_change(_struct,
@@ -75,7 +79,7 @@
     CefAccessibilityHandler,
     cef_accessibility_handler_t>::UnwrapDerived(CefWrapperType type,
                                                 CefAccessibilityHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/accessibility_handler_ctocpp.h b/src/libcef_dll/ctocpp/accessibility_handler_ctocpp.h
index c4544f6..0a94e2e 100644
--- a/src/libcef_dll/ctocpp/accessibility_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/accessibility_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=80cb1a6def2d011b59ebd72953d404bff04ba31c$
+// $hash=3bfebc6542251128247e89a55fba8cbb3bc7061d$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_ACCESSIBILITY_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/app_ctocpp.cc b/src/libcef_dll/ctocpp/app_ctocpp.cc
index 4f90c06..30d0fb1 100644
--- a/src/libcef_dll/ctocpp/app_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/app_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4f70dc8d5391cb5254f038ec2b3b56804b447087$
+// $hash=fb2f03e369354152db16f5a6b6c6b93e87c42fa5$
 //
 
 #include "libcef_dll/ctocpp/app_ctocpp.h"
@@ -26,15 +26,17 @@
     const CefString& process_type,
     CefRefPtr<CefCommandLine> command_line) {
   cef_app_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_before_command_line_processing))
+  if (CEF_MEMBER_MISSING(_struct, on_before_command_line_processing)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: command_line; type: refptr_diff
   DCHECK(command_line.get());
-  if (!command_line.get())
+  if (!command_line.get()) {
     return;
+  }
   // Unverified params: process_type
 
   // Execute
@@ -47,15 +49,17 @@
 void CefAppCToCpp::OnRegisterCustomSchemes(
     CefRawPtr<CefSchemeRegistrar> registrar) {
   cef_app_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_register_custom_schemes))
+  if (CEF_MEMBER_MISSING(_struct, on_register_custom_schemes)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: registrar; type: rawptr_diff
   DCHECK(registrar);
-  if (!registrar)
+  if (!registrar) {
     return;
+  }
 
   // Translate param: registrar; type: rawptr_diff
   CefOwnPtr<CefSchemeRegistrarCppToC> registrarPtr(
@@ -68,8 +72,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefResourceBundleHandler> CefAppCToCpp::GetResourceBundleHandler() {
   cef_app_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_resource_bundle_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_resource_bundle_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -84,8 +89,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefBrowserProcessHandler> CefAppCToCpp::GetBrowserProcessHandler() {
   cef_app_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_browser_process_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_browser_process_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -100,8 +106,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefRenderProcessHandler> CefAppCToCpp::GetRenderProcessHandler() {
   cef_app_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_render_process_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_render_process_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -125,7 +132,7 @@
 cef_app_t* CefCToCppRefCounted<CefAppCToCpp, CefApp, cef_app_t>::UnwrapDerived(
     CefWrapperType type,
     CefApp* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/app_ctocpp.h b/src/libcef_dll/ctocpp/app_ctocpp.h
index 125afd4..80424a3 100644
--- a/src/libcef_dll/ctocpp/app_ctocpp.h
+++ b/src/libcef_dll/ctocpp/app_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=5d865c197ea6caabc9c68b40e65d211499e462c5$
+// $hash=ea433c4f09f9cc1c432e3406dacfe27ec81c20cb$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_APP_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/audio_handler_ctocpp.cc b/src/libcef_dll/ctocpp/audio_handler_ctocpp.cc
index 74d23aa..c58f703 100644
--- a/src/libcef_dll/ctocpp/audio_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/audio_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d7f2fb8ad6fe2bd0ab928b09ab596b12e9049ddf$
+// $hash=976fbf502a9f2d21ad92b3c64d3ca8d414f9869c$
 //
 
 #include "libcef_dll/ctocpp/audio_handler_ctocpp.h"
@@ -24,15 +24,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_audio_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_audio_parameters))
+  if (CEF_MEMBER_MISSING(_struct, get_audio_parameters)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->get_audio_parameters(
@@ -50,15 +52,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_audio_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_audio_stream_started))
+  if (CEF_MEMBER_MISSING(_struct, on_audio_stream_started)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_audio_stream_started(_struct, CefBrowserCppToC::Wrap(browser),
@@ -69,23 +73,26 @@
 void CefAudioHandlerCToCpp::OnAudioStreamPacket(CefRefPtr<CefBrowser> browser,
                                                 const float** data,
                                                 int frames,
-                                                int64 pts) {
+                                                int64_t pts) {
   shutdown_checker::AssertNotShutdown();
 
   cef_audio_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_audio_stream_packet))
+  if (CEF_MEMBER_MISSING(_struct, on_audio_stream_packet)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return;
+  }
 
   // Execute
   _struct->on_audio_stream_packet(_struct, CefBrowserCppToC::Wrap(browser),
@@ -98,15 +105,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_audio_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_audio_stream_stopped))
+  if (CEF_MEMBER_MISSING(_struct, on_audio_stream_stopped)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_audio_stream_stopped(_struct, CefBrowserCppToC::Wrap(browser));
@@ -118,19 +127,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_audio_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_audio_stream_error))
+  if (CEF_MEMBER_MISSING(_struct, on_audio_stream_error)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: message; type: string_byref_const
   DCHECK(!message.empty());
-  if (message.empty())
+  if (message.empty()) {
     return;
+  }
 
   // Execute
   _struct->on_audio_stream_error(_struct, CefBrowserCppToC::Wrap(browser),
@@ -153,7 +165,7 @@
                     CefAudioHandler,
                     cef_audio_handler_t>::UnwrapDerived(CefWrapperType type,
                                                         CefAudioHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/audio_handler_ctocpp.h b/src/libcef_dll/ctocpp/audio_handler_ctocpp.h
index 16a0a76..c2d5b64 100644
--- a/src/libcef_dll/ctocpp/audio_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/audio_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e5517ccac966337ef7dc576a24eedfe1154b2813$
+// $hash=93c0cae17d2e380e7a0268ba658b1449cc0bc71c$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_AUDIO_HANDLER_CTOCPP_H_
@@ -42,7 +42,7 @@
   void OnAudioStreamPacket(CefRefPtr<CefBrowser> browser,
                            const float** data,
                            int frames,
-                           int64 pts) override;
+                           int64_t pts) override;
   void OnAudioStreamStopped(CefRefPtr<CefBrowser> browser) override;
   void OnAudioStreamError(CefRefPtr<CefBrowser> browser,
                           const CefString& message) override;
diff --git a/src/libcef_dll/ctocpp/auth_callback_ctocpp.cc b/src/libcef_dll/ctocpp/auth_callback_ctocpp.cc
index a9a1711..ee3b551 100644
--- a/src/libcef_dll/ctocpp/auth_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/auth_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=54b2a86796e3c6936aa4475004d620677666a796$
+// $hash=b2c9b6c79bcd7f510d9cb521a15f761eda23e7ef$
 //
 
 #include "libcef_dll/ctocpp/auth_callback_ctocpp.h"
@@ -23,8 +23,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_auth_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cont))
+  if (CEF_MEMBER_MISSING(_struct, cont)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -38,8 +39,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_auth_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cancel))
+  if (CEF_MEMBER_MISSING(_struct, cancel)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -63,7 +65,7 @@
                     CefAuthCallback,
                     cef_auth_callback_t>::UnwrapDerived(CefWrapperType type,
                                                         CefAuthCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/auth_callback_ctocpp.h b/src/libcef_dll/ctocpp/auth_callback_ctocpp.h
index e5c973b..f6242bd 100644
--- a/src/libcef_dll/ctocpp/auth_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/auth_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=199cea821f0726c069942b34ea25eeb4fc99ea25$
+// $hash=60f444d40338eb245860b389d087e12af15cbf20$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_AUTH_CALLBACK_CTOCPP_H_
@@ -34,8 +34,8 @@
   virtual ~CefAuthCallbackCToCpp();
 
   // CefAuthCallback methods.
-  void Continue(const CefString& username, const CefString& password) OVERRIDE;
-  void Cancel() OVERRIDE;
+  void Continue(const CefString& username, const CefString& password) override;
+  void Cancel() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_AUTH_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/base_ref_counted_ctocpp.cc b/src/libcef_dll/ctocpp/base_ref_counted_ctocpp.cc
index 4b14e3f..a5c14d1 100644
--- a/src/libcef_dll/ctocpp/base_ref_counted_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/base_ref_counted_ctocpp.cc
@@ -12,7 +12,7 @@
     CefBaseRefCounted,
     cef_base_ref_counted_t>::UnwrapDerived(CefWrapperType type,
                                            CefBaseRefCounted* c) {
-  NOTREACHED();
+  DCHECK(false);
   return NULL;
 }
 
diff --git a/src/libcef_dll/ctocpp/base_scoped_ctocpp.cc b/src/libcef_dll/ctocpp/base_scoped_ctocpp.cc
index 40accb5..35b1624 100644
--- a/src/libcef_dll/ctocpp/base_scoped_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/base_scoped_ctocpp.cc
@@ -10,7 +10,7 @@
 cef_base_scoped_t*
 CefCToCppScoped<CefBaseScopedCToCpp, CefBaseScoped, cef_base_scoped_t>::
     UnwrapDerivedOwn(CefWrapperType type, CefOwnPtr<CefBaseScoped> c) {
-  NOTREACHED();
+  DCHECK(false);
   return NULL;
 }
 
@@ -18,7 +18,7 @@
 cef_base_scoped_t*
 CefCToCppScoped<CefBaseScopedCToCpp, CefBaseScoped, cef_base_scoped_t>::
     UnwrapDerivedRaw(CefWrapperType type, CefRawPtr<CefBaseScoped> c) {
-  NOTREACHED();
+  DCHECK(false);
   return NULL;
 }
 
diff --git a/src/libcef_dll/ctocpp/before_download_callback_ctocpp.cc b/src/libcef_dll/ctocpp/before_download_callback_ctocpp.cc
index 9dc1a71..94161a7 100644
--- a/src/libcef_dll/ctocpp/before_download_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/before_download_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=be4b247da2987252e1471149aade76c4d4a34394$
+// $hash=5fee76af45a3305b58bd6a58455fb3e834368077$
 //
 
 #include "libcef_dll/ctocpp/before_download_callback_ctocpp.h"
@@ -23,8 +23,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_before_download_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cont))
+  if (CEF_MEMBER_MISSING(_struct, cont)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -51,7 +52,7 @@
     cef_before_download_callback_t>::UnwrapDerived(CefWrapperType type,
                                                    CefBeforeDownloadCallback*
                                                        c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/before_download_callback_ctocpp.h b/src/libcef_dll/ctocpp/before_download_callback_ctocpp.h
index ec68a09..23739dd 100644
--- a/src/libcef_dll/ctocpp/before_download_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/before_download_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6f17e4bcee192e06ece3358a1fb99edebd088936$
+// $hash=743f5b5893055b96eb373b93368c727b3d36d3c6$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_BEFORE_DOWNLOAD_CALLBACK_CTOCPP_H_
@@ -35,7 +35,7 @@
   virtual ~CefBeforeDownloadCallbackCToCpp();
 
   // CefBeforeDownloadCallback methods.
-  void Continue(const CefString& download_path, bool show_dialog) OVERRIDE;
+  void Continue(const CefString& download_path, bool show_dialog) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_BEFORE_DOWNLOAD_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/binary_value_ctocpp.cc b/src/libcef_dll/ctocpp/binary_value_ctocpp.cc
index 96a878c..3dd1553 100644
--- a/src/libcef_dll/ctocpp/binary_value_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/binary_value_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=352b1570cd74cce646f914bf25fc97a749f15898$
+// $hash=f42bab3d9e4ff45faf1fd8071646a8e5bed64177$
 //
 
 #include "libcef_dll/ctocpp/binary_value_ctocpp.h"
@@ -26,8 +26,9 @@
 
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return nullptr;
+  }
 
   // Execute
   cef_binary_value_t* _retval = cef_binary_value_create(data, data_size);
@@ -42,8 +43,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_binary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -58,8 +60,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_binary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_owned))
+  if (CEF_MEMBER_MISSING(_struct, is_owned)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -75,15 +78,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_binary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefBinaryValueCToCpp::Unwrap(that));
@@ -97,15 +102,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_binary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_equal))
+  if (CEF_MEMBER_MISSING(_struct, is_equal)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_equal(_struct, CefBinaryValueCToCpp::Unwrap(that));
@@ -119,8 +126,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_binary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, copy))
+  if (CEF_MEMBER_MISSING(_struct, copy)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -131,12 +139,31 @@
   return CefBinaryValueCToCpp::Wrap(_retval);
 }
 
+NO_SANITIZE("cfi-icall") const void* CefBinaryValueCToCpp::GetRawData() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_binary_value_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_raw_data)) {
+    return nullptr;
+  }
+
+  // This manual implementation can be removed once support for 'const void*'
+  // is integrated into the CEF translator tool (issue #3591).
+
+  // Execute
+  const void* _retval = _struct->get_raw_data(_struct);
+
+  // Return type: simple_byaddr
+  return _retval;
+}
+
 NO_SANITIZE("cfi-icall") size_t CefBinaryValueCToCpp::GetSize() {
   shutdown_checker::AssertNotShutdown();
 
   cef_binary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_size))
+  if (CEF_MEMBER_MISSING(_struct, get_size)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -154,15 +181,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_binary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_data))
+  if (CEF_MEMBER_MISSING(_struct, get_data)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: buffer; type: simple_byaddr
   DCHECK(buffer);
-  if (!buffer)
+  if (!buffer) {
     return 0;
+  }
 
   // Execute
   size_t _retval = _struct->get_data(_struct, buffer, buffer_size, data_offset);
@@ -185,7 +214,7 @@
 cef_binary_value_t*
 CefCToCppRefCounted<CefBinaryValueCToCpp, CefBinaryValue, cef_binary_value_t>::
     UnwrapDerived(CefWrapperType type, CefBinaryValue* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/binary_value_ctocpp.h b/src/libcef_dll/ctocpp/binary_value_ctocpp.h
index ef84ff0..fa1902b 100644
--- a/src/libcef_dll/ctocpp/binary_value_ctocpp.h
+++ b/src/libcef_dll/ctocpp/binary_value_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=eca472fd8d1ebb66dba55157e6522c72fb72203c$
+// $hash=2e0ac9b73ba6bdb4b07ee0f8c445974359c5862f$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_BINARY_VALUE_CTOCPP_H_
@@ -34,13 +34,14 @@
   virtual ~CefBinaryValueCToCpp();
 
   // CefBinaryValue methods.
-  bool IsValid() OVERRIDE;
-  bool IsOwned() OVERRIDE;
-  bool IsSame(CefRefPtr<CefBinaryValue> that) OVERRIDE;
-  bool IsEqual(CefRefPtr<CefBinaryValue> that) OVERRIDE;
-  CefRefPtr<CefBinaryValue> Copy() OVERRIDE;
-  size_t GetSize() OVERRIDE;
-  size_t GetData(void* buffer, size_t buffer_size, size_t data_offset) OVERRIDE;
+  bool IsValid() override;
+  bool IsOwned() override;
+  bool IsSame(CefRefPtr<CefBinaryValue> that) override;
+  bool IsEqual(CefRefPtr<CefBinaryValue> that) override;
+  CefRefPtr<CefBinaryValue> Copy() override;
+  const void* GetRawData() override;
+  size_t GetSize() override;
+  size_t GetData(void* buffer, size_t buffer_size, size_t data_offset) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_BINARY_VALUE_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/browser_ctocpp.cc b/src/libcef_dll/ctocpp/browser_ctocpp.cc
index 3c9584a..98db03b 100644
--- a/src/libcef_dll/ctocpp/browser_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/browser_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9d16a2ca7a348181df0b026b3013d362170f7085$
+// $hash=315497b4073b309e7976214a92204d6aede24fb1$
 //
 
 #include "libcef_dll/ctocpp/browser_ctocpp.h"
@@ -21,12 +21,30 @@
 
 // VIRTUAL METHODS - Body may be edited by hand.
 
+NO_SANITIZE("cfi-icall") bool CefBrowserCToCpp::IsValid() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_browser_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = _struct->is_valid(_struct);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
 NO_SANITIZE("cfi-icall") CefRefPtr<CefBrowserHost> CefBrowserCToCpp::GetHost() {
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_host))
+  if (CEF_MEMBER_MISSING(_struct, get_host)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -41,8 +59,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, can_go_back))
+  if (CEF_MEMBER_MISSING(_struct, can_go_back)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -57,8 +76,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, go_back))
+  if (CEF_MEMBER_MISSING(_struct, go_back)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -70,8 +90,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, can_go_forward))
+  if (CEF_MEMBER_MISSING(_struct, can_go_forward)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -86,8 +107,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, go_forward))
+  if (CEF_MEMBER_MISSING(_struct, go_forward)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -99,8 +121,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_loading))
+  if (CEF_MEMBER_MISSING(_struct, is_loading)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -115,8 +138,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, reload))
+  if (CEF_MEMBER_MISSING(_struct, reload)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -128,8 +152,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, reload_ignore_cache))
+  if (CEF_MEMBER_MISSING(_struct, reload_ignore_cache)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -141,8 +166,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, stop_load))
+  if (CEF_MEMBER_MISSING(_struct, stop_load)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -154,8 +180,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_identifier))
+  if (CEF_MEMBER_MISSING(_struct, get_identifier)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -171,15 +198,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefBrowserCToCpp::Unwrap(that));
@@ -192,8 +221,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_popup))
+  if (CEF_MEMBER_MISSING(_struct, is_popup)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -208,8 +238,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_document))
+  if (CEF_MEMBER_MISSING(_struct, has_document)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -224,8 +255,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_main_frame))
+  if (CEF_MEMBER_MISSING(_struct, get_main_frame)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -241,8 +273,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_focused_frame))
+  if (CEF_MEMBER_MISSING(_struct, get_focused_frame)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -254,12 +287,13 @@
 }
 
 NO_SANITIZE("cfi-icall")
-CefRefPtr<CefFrame> CefBrowserCToCpp::GetFrame(int64 identifier) {
+CefRefPtr<CefFrame> CefBrowserCToCpp::GetFrame(int64_t identifier) {
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_frame_byident))
+  if (CEF_MEMBER_MISSING(_struct, get_frame_byident)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -275,8 +309,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_frame))
+  if (CEF_MEMBER_MISSING(_struct, get_frame)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -293,8 +328,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_frame_count))
+  if (CEF_MEMBER_MISSING(_struct, get_frame_count)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -306,24 +342,25 @@
 }
 
 NO_SANITIZE("cfi-icall")
-void CefBrowserCToCpp::GetFrameIdentifiers(std::vector<int64>& identifiers) {
+void CefBrowserCToCpp::GetFrameIdentifiers(std::vector<int64_t>& identifiers) {
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_frame_identifiers))
+  if (CEF_MEMBER_MISSING(_struct, get_frame_identifiers)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: identifiers; type: simple_vec_byref
   size_t identifiersSize = identifiers.size();
   size_t identifiersCount = std::max(GetFrameCount(), identifiersSize);
-  int64* identifiersList = NULL;
+  int64_t* identifiersList = NULL;
   if (identifiersCount > 0) {
-    identifiersList = new int64[identifiersCount];
+    identifiersList = new int64_t[identifiersCount];
     DCHECK(identifiersList);
     if (identifiersList) {
-      memset(identifiersList, 0, sizeof(int64) * identifiersCount);
+      memset(identifiersList, 0, sizeof(int64_t) * identifiersCount);
     }
     if (identifiersList && identifiersSize > 0) {
       for (size_t i = 0; i < identifiersSize; ++i) {
@@ -350,16 +387,18 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_frame_names))
+  if (CEF_MEMBER_MISSING(_struct, get_frame_names)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: names; type: string_vec_byref
   cef_string_list_t namesList = cef_string_list_alloc();
   DCHECK(namesList);
-  if (namesList)
+  if (namesList) {
     transfer_string_list_contents(names, namesList);
+  }
 
   // Execute
   _struct->get_frame_names(_struct, namesList);
@@ -387,7 +426,7 @@
 CefCToCppRefCounted<CefBrowserCToCpp, CefBrowser, cef_browser_t>::UnwrapDerived(
     CefWrapperType type,
     CefBrowser* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/browser_ctocpp.h b/src/libcef_dll/ctocpp/browser_ctocpp.h
index 0cae983..1d6bb12 100644
--- a/src/libcef_dll/ctocpp/browser_ctocpp.h
+++ b/src/libcef_dll/ctocpp/browser_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=422ef21aa832c006ef67641e44667c88dc5a6b1b$
+// $hash=a55c1986eac8be1d5d3c9f1fd3b2883bf8957449$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_BROWSER_CTOCPP_H_
@@ -36,26 +36,27 @@
   virtual ~CefBrowserCToCpp();
 
   // CefBrowser methods.
-  CefRefPtr<CefBrowserHost> GetHost() OVERRIDE;
-  bool CanGoBack() OVERRIDE;
-  void GoBack() OVERRIDE;
-  bool CanGoForward() OVERRIDE;
-  void GoForward() OVERRIDE;
-  bool IsLoading() OVERRIDE;
-  void Reload() OVERRIDE;
-  void ReloadIgnoreCache() OVERRIDE;
-  void StopLoad() OVERRIDE;
-  int GetIdentifier() OVERRIDE;
-  bool IsSame(CefRefPtr<CefBrowser> that) OVERRIDE;
-  bool IsPopup() OVERRIDE;
-  bool HasDocument() OVERRIDE;
-  CefRefPtr<CefFrame> GetMainFrame() OVERRIDE;
-  CefRefPtr<CefFrame> GetFocusedFrame() OVERRIDE;
-  CefRefPtr<CefFrame> GetFrame(int64 identifier) OVERRIDE;
-  CefRefPtr<CefFrame> GetFrame(const CefString& name) OVERRIDE;
-  size_t GetFrameCount() OVERRIDE;
-  void GetFrameIdentifiers(std::vector<int64>& identifiers) OVERRIDE;
-  void GetFrameNames(std::vector<CefString>& names) OVERRIDE;
+  bool IsValid() override;
+  CefRefPtr<CefBrowserHost> GetHost() override;
+  bool CanGoBack() override;
+  void GoBack() override;
+  bool CanGoForward() override;
+  void GoForward() override;
+  bool IsLoading() override;
+  void Reload() override;
+  void ReloadIgnoreCache() override;
+  void StopLoad() override;
+  int GetIdentifier() override;
+  bool IsSame(CefRefPtr<CefBrowser> that) override;
+  bool IsPopup() override;
+  bool HasDocument() override;
+  CefRefPtr<CefFrame> GetMainFrame() override;
+  CefRefPtr<CefFrame> GetFocusedFrame() override;
+  CefRefPtr<CefFrame> GetFrame(int64_t identifier) override;
+  CefRefPtr<CefFrame> GetFrame(const CefString& name) override;
+  size_t GetFrameCount() override;
+  void GetFrameIdentifiers(std::vector<int64_t>& identifiers) override;
+  void GetFrameNames(std::vector<CefString>& names) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_BROWSER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/browser_host_ctocpp.cc b/src/libcef_dll/ctocpp/browser_host_ctocpp.cc
index 68b407e..a6eea8e 100644
--- a/src/libcef_dll/ctocpp/browser_host_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/browser_host_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=a362e11e85ce68488bbb0f5232b01f53cffeec1d$
+// $hash=b06e3bbc86769bbc2485d4ab9530b5c39dc73243$
 //
 
 #include "libcef_dll/ctocpp/browser_host_ctocpp.h"
@@ -86,8 +86,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_browser))
+  if (CEF_MEMBER_MISSING(_struct, get_browser)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -103,8 +104,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, close_browser))
+  if (CEF_MEMBER_MISSING(_struct, close_browser)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -116,8 +118,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, try_close_browser))
+  if (CEF_MEMBER_MISSING(_struct, try_close_browser)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -132,8 +135,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_focus))
+  if (CEF_MEMBER_MISSING(_struct, set_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -146,8 +150,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_window_handle))
+  if (CEF_MEMBER_MISSING(_struct, get_window_handle)) {
     return kNullWindowHandle;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -163,8 +168,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_opener_window_handle))
+  if (CEF_MEMBER_MISSING(_struct, get_opener_window_handle)) {
     return kNullWindowHandle;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -179,8 +185,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_view))
+  if (CEF_MEMBER_MISSING(_struct, has_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -196,8 +203,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_client))
+  if (CEF_MEMBER_MISSING(_struct, get_client)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -213,8 +221,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_request_context))
+  if (CEF_MEMBER_MISSING(_struct, get_request_context)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -225,12 +234,63 @@
   return CefRequestContextCToCpp::Wrap(_retval);
 }
 
+NO_SANITIZE("cfi-icall")
+bool CefBrowserHostCToCpp::CanZoom(cef_zoom_command_t command) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_browser_host_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, can_zoom)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = _struct->can_zoom(_struct, command);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+void CefBrowserHostCToCpp::Zoom(cef_zoom_command_t command) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_browser_host_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, zoom)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->zoom(_struct, command);
+}
+
+NO_SANITIZE("cfi-icall") double CefBrowserHostCToCpp::GetDefaultZoomLevel() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_browser_host_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_default_zoom_level)) {
+    return 0;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  double _retval = _struct->get_default_zoom_level(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
 NO_SANITIZE("cfi-icall") double CefBrowserHostCToCpp::GetZoomLevel() {
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_zoom_level))
+  if (CEF_MEMBER_MISSING(_struct, get_zoom_level)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -246,8 +306,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_zoom_level))
+  if (CEF_MEMBER_MISSING(_struct, set_zoom_level)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -261,41 +322,39 @@
     const CefString& title,
     const CefString& default_file_path,
     const std::vector<CefString>& accept_filters,
-    int selected_accept_filter,
     CefRefPtr<CefRunFileDialogCallback> callback) {
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, run_file_dialog))
+  if (CEF_MEMBER_MISSING(_struct, run_file_dialog)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
-  // Verify param: selected_accept_filter; type: simple_byval
-  DCHECK_GE(selected_accept_filter, 0);
-  if (selected_accept_filter < 0)
-    return;
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return;
+  }
   // Unverified params: title, default_file_path, accept_filters
 
   // Translate param: accept_filters; type: string_vec_byref_const
   cef_string_list_t accept_filtersList = cef_string_list_alloc();
   DCHECK(accept_filtersList);
-  if (accept_filtersList)
+  if (accept_filtersList) {
     transfer_string_list_contents(accept_filters, accept_filtersList);
+  }
 
   // Execute
   _struct->run_file_dialog(_struct, mode, title.GetStruct(),
                            default_file_path.GetStruct(), accept_filtersList,
-                           selected_accept_filter,
                            CefRunFileDialogCallbackCppToC::Wrap(callback));
 
   // Restore param:accept_filters; type: string_vec_byref_const
-  if (accept_filtersList)
+  if (accept_filtersList) {
     cef_string_list_free(accept_filtersList);
+  }
 }
 
 NO_SANITIZE("cfi-icall")
@@ -303,15 +362,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, start_download))
+  if (CEF_MEMBER_MISSING(_struct, start_download)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: url; type: string_byref_const
   DCHECK(!url.empty());
-  if (url.empty())
+  if (url.empty()) {
     return;
+  }
 
   // Execute
   _struct->start_download(_struct, url.GetStruct());
@@ -321,25 +382,28 @@
 void CefBrowserHostCToCpp::DownloadImage(
     const CefString& image_url,
     bool is_favicon,
-    uint32 max_image_size,
+    uint32_t max_image_size,
     bool bypass_cache,
     CefRefPtr<CefDownloadImageCallback> callback) {
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, download_image))
+  if (CEF_MEMBER_MISSING(_struct, download_image)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: image_url; type: string_byref_const
   DCHECK(!image_url.empty());
-  if (image_url.empty())
+  if (image_url.empty()) {
     return;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return;
+  }
 
   // Execute
   _struct->download_image(_struct, image_url.GetStruct(), is_favicon,
@@ -351,8 +415,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, print))
+  if (CEF_MEMBER_MISSING(_struct, print)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -367,15 +432,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, print_to_pdf))
+  if (CEF_MEMBER_MISSING(_struct, print_to_pdf)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: path; type: string_byref_const
   DCHECK(!path.empty());
-  if (path.empty())
+  if (path.empty()) {
     return;
+  }
   // Unverified params: callback
 
   // Execute
@@ -384,27 +451,27 @@
 }
 
 NO_SANITIZE("cfi-icall")
-void CefBrowserHostCToCpp::Find(int identifier,
-                                const CefString& searchText,
+void CefBrowserHostCToCpp::Find(const CefString& searchText,
                                 bool forward,
                                 bool matchCase,
                                 bool findNext) {
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, find))
+  if (CEF_MEMBER_MISSING(_struct, find)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: searchText; type: string_byref_const
   DCHECK(!searchText.empty());
-  if (searchText.empty())
+  if (searchText.empty()) {
     return;
+  }
 
   // Execute
-  _struct->find(_struct, identifier, searchText.GetStruct(), forward, matchCase,
-                findNext);
+  _struct->find(_struct, searchText.GetStruct(), forward, matchCase, findNext);
 }
 
 NO_SANITIZE("cfi-icall")
@@ -412,8 +479,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, stop_finding))
+  if (CEF_MEMBER_MISSING(_struct, stop_finding)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -429,8 +497,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, show_dev_tools))
+  if (CEF_MEMBER_MISSING(_struct, show_dev_tools)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -445,8 +514,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, close_dev_tools))
+  if (CEF_MEMBER_MISSING(_struct, close_dev_tools)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -458,8 +528,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_dev_tools))
+  if (CEF_MEMBER_MISSING(_struct, has_dev_tools)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -476,15 +547,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_dev_tools_message))
+  if (CEF_MEMBER_MISSING(_struct, send_dev_tools_message)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: message; type: simple_byaddr
   DCHECK(message);
-  if (!message)
+  if (!message) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->send_dev_tools_message(_struct, message, message_size);
@@ -501,15 +574,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, execute_dev_tools_method))
+  if (CEF_MEMBER_MISSING(_struct, execute_dev_tools_method)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: method; type: string_byref_const
   DCHECK(!method.empty());
-  if (method.empty())
+  if (method.empty()) {
     return 0;
+  }
   // Unverified params: params
 
   // Execute
@@ -527,15 +602,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, add_dev_tools_message_observer))
+  if (CEF_MEMBER_MISSING(_struct, add_dev_tools_message_observer)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: observer; type: refptr_diff
   DCHECK(observer.get());
-  if (!observer.get())
+  if (!observer.get()) {
     return nullptr;
+  }
 
   // Execute
   cef_registration_t* _retval = _struct->add_dev_tools_message_observer(
@@ -552,15 +629,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_navigation_entries))
+  if (CEF_MEMBER_MISSING(_struct, get_navigation_entries)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: visitor; type: refptr_diff
   DCHECK(visitor.get());
-  if (!visitor.get())
+  if (!visitor.get()) {
     return;
+  }
 
   // Execute
   _struct->get_navigation_entries(
@@ -568,50 +647,21 @@
 }
 
 NO_SANITIZE("cfi-icall")
-void CefBrowserHostCToCpp::SetMouseCursorChangeDisabled(bool disabled) {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_mouse_cursor_change_disabled))
-    return;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  _struct->set_mouse_cursor_change_disabled(_struct, disabled);
-}
-
-NO_SANITIZE("cfi-icall")
-bool CefBrowserHostCToCpp::IsMouseCursorChangeDisabled() {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_mouse_cursor_change_disabled))
-    return false;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  int _retval = _struct->is_mouse_cursor_change_disabled(_struct);
-
-  // Return type: bool
-  return _retval ? true : false;
-}
-
-NO_SANITIZE("cfi-icall")
 void CefBrowserHostCToCpp::ReplaceMisspelling(const CefString& word) {
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, replace_misspelling))
+  if (CEF_MEMBER_MISSING(_struct, replace_misspelling)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: word; type: string_byref_const
   DCHECK(!word.empty());
-  if (word.empty())
+  if (word.empty()) {
     return;
+  }
 
   // Execute
   _struct->replace_misspelling(_struct, word.GetStruct());
@@ -622,15 +672,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, add_word_to_dictionary))
+  if (CEF_MEMBER_MISSING(_struct, add_word_to_dictionary)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: word; type: string_byref_const
   DCHECK(!word.empty());
-  if (word.empty())
+  if (word.empty()) {
     return;
+  }
 
   // Execute
   _struct->add_word_to_dictionary(_struct, word.GetStruct());
@@ -641,8 +693,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_window_rendering_disabled))
+  if (CEF_MEMBER_MISSING(_struct, is_window_rendering_disabled)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -657,8 +710,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, was_resized))
+  if (CEF_MEMBER_MISSING(_struct, was_resized)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -670,8 +724,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, was_hidden))
+  if (CEF_MEMBER_MISSING(_struct, was_hidden)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -683,8 +738,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, notify_screen_info_changed))
+  if (CEF_MEMBER_MISSING(_struct, notify_screen_info_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -697,8 +753,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, invalidate))
+  if (CEF_MEMBER_MISSING(_struct, invalidate)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -710,8 +767,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_external_begin_frame))
+  if (CEF_MEMBER_MISSING(_struct, send_external_begin_frame)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -724,8 +782,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_key_event))
+  if (CEF_MEMBER_MISSING(_struct, send_key_event)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -741,8 +800,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_mouse_click_event))
+  if (CEF_MEMBER_MISSING(_struct, send_mouse_click_event)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -756,8 +816,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_mouse_move_event))
+  if (CEF_MEMBER_MISSING(_struct, send_mouse_move_event)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -772,8 +833,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_mouse_wheel_event))
+  if (CEF_MEMBER_MISSING(_struct, send_mouse_wheel_event)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -786,8 +848,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_touch_event))
+  if (CEF_MEMBER_MISSING(_struct, send_touch_event)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -795,26 +858,13 @@
   _struct->send_touch_event(_struct, &event);
 }
 
-NO_SANITIZE("cfi-icall")
-void CefBrowserHostCToCpp::SendFocusEvent(bool setFocus) {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_focus_event))
-    return;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  _struct->send_focus_event(_struct, setFocus);
-}
-
 NO_SANITIZE("cfi-icall") void CefBrowserHostCToCpp::SendCaptureLostEvent() {
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_capture_lost_event))
+  if (CEF_MEMBER_MISSING(_struct, send_capture_lost_event)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -827,8 +877,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, notify_move_or_resize_started))
+  if (CEF_MEMBER_MISSING(_struct, notify_move_or_resize_started)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -840,8 +891,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_windowless_frame_rate))
+  if (CEF_MEMBER_MISSING(_struct, get_windowless_frame_rate)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -857,8 +909,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_windowless_frame_rate))
+  if (CEF_MEMBER_MISSING(_struct, set_windowless_frame_rate)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -875,8 +928,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, ime_set_composition))
+  if (CEF_MEMBER_MISSING(_struct, ime_set_composition)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -901,8 +955,9 @@
                                &selection_range);
 
   // Restore param:underlines; type: simple_vec_byref_const
-  if (underlinesList)
+  if (underlinesList) {
     delete[] underlinesList;
+  }
 }
 
 NO_SANITIZE("cfi-icall")
@@ -912,8 +967,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, ime_commit_text))
+  if (CEF_MEMBER_MISSING(_struct, ime_commit_text)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -929,8 +985,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, ime_finish_composing_text))
+  if (CEF_MEMBER_MISSING(_struct, ime_finish_composing_text)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -942,8 +999,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, ime_cancel_composition))
+  if (CEF_MEMBER_MISSING(_struct, ime_cancel_composition)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -958,15 +1016,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, drag_target_drag_enter))
+  if (CEF_MEMBER_MISSING(_struct, drag_target_drag_enter)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: drag_data; type: refptr_same
   DCHECK(drag_data.get());
-  if (!drag_data.get())
+  if (!drag_data.get()) {
     return;
+  }
 
   // Execute
   _struct->drag_target_drag_enter(_struct, CefDragDataCToCpp::Unwrap(drag_data),
@@ -979,8 +1039,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, drag_target_drag_over))
+  if (CEF_MEMBER_MISSING(_struct, drag_target_drag_over)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -992,8 +1053,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, drag_target_drag_leave))
+  if (CEF_MEMBER_MISSING(_struct, drag_target_drag_leave)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1006,8 +1068,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, drag_target_drop))
+  if (CEF_MEMBER_MISSING(_struct, drag_target_drop)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1022,8 +1085,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, drag_source_ended_at))
+  if (CEF_MEMBER_MISSING(_struct, drag_source_ended_at)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1036,8 +1100,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, drag_source_system_drag_ended))
+  if (CEF_MEMBER_MISSING(_struct, drag_source_system_drag_ended)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1051,8 +1116,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_visible_navigation_entry))
+  if (CEF_MEMBER_MISSING(_struct, get_visible_navigation_entry)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1070,8 +1136,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_accessibility_state))
+  if (CEF_MEMBER_MISSING(_struct, set_accessibility_state)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1086,8 +1153,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_auto_resize_enabled))
+  if (CEF_MEMBER_MISSING(_struct, set_auto_resize_enabled)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1100,8 +1168,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_extension))
+  if (CEF_MEMBER_MISSING(_struct, get_extension)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1116,8 +1185,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_background_host))
+  if (CEF_MEMBER_MISSING(_struct, is_background_host)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1132,8 +1202,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_audio_muted))
+  if (CEF_MEMBER_MISSING(_struct, set_audio_muted)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1145,8 +1216,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_host_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_audio_muted))
+  if (CEF_MEMBER_MISSING(_struct, is_audio_muted)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1157,6 +1229,73 @@
   return _retval ? true : false;
 }
 
+NO_SANITIZE("cfi-icall") bool CefBrowserHostCToCpp::IsFullscreen() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_browser_host_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, is_fullscreen)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = _struct->is_fullscreen(_struct);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+void CefBrowserHostCToCpp::ExitFullscreen(bool will_cause_resize) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_browser_host_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, exit_fullscreen)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->exit_fullscreen(_struct, will_cause_resize);
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefBrowserHostCToCpp::CanExecuteChromeCommand(int command_id) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_browser_host_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, can_execute_chrome_command)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = _struct->can_execute_chrome_command(_struct, command_id);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+void CefBrowserHostCToCpp::ExecuteChromeCommand(
+    int command_id,
+    cef_window_open_disposition_t disposition) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_browser_host_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, execute_chrome_command)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->execute_chrome_command(_struct, command_id, disposition);
+}
+
 // CONSTRUCTOR - Do not edit by hand.
 
 CefBrowserHostCToCpp::CefBrowserHostCToCpp() {}
@@ -1171,7 +1310,7 @@
 cef_browser_host_t*
 CefCToCppRefCounted<CefBrowserHostCToCpp, CefBrowserHost, cef_browser_host_t>::
     UnwrapDerived(CefWrapperType type, CefBrowserHost* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/browser_host_ctocpp.h b/src/libcef_dll/ctocpp/browser_host_ctocpp.h
index 4987e5a..2cc1212 100644
--- a/src/libcef_dll/ctocpp/browser_host_ctocpp.h
+++ b/src/libcef_dll/ctocpp/browser_host_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c9abd1293472afbac964aac4cd7dd4cac9dd8e58$
+// $hash=e07873b7e67c06fb54dafa370eca83d2c698ffb9$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_BROWSER_HOST_CTOCPP_H_
@@ -37,105 +37,108 @@
   virtual ~CefBrowserHostCToCpp();
 
   // CefBrowserHost methods.
-  CefRefPtr<CefBrowser> GetBrowser() OVERRIDE;
-  void CloseBrowser(bool force_close) OVERRIDE;
-  bool TryCloseBrowser() OVERRIDE;
-  void SetFocus(bool focus) OVERRIDE;
-  CefWindowHandle GetWindowHandle() OVERRIDE;
-  CefWindowHandle GetOpenerWindowHandle() OVERRIDE;
-  bool HasView() OVERRIDE;
-  CefRefPtr<CefClient> GetClient() OVERRIDE;
-  CefRefPtr<CefRequestContext> GetRequestContext() OVERRIDE;
-  double GetZoomLevel() OVERRIDE;
-  void SetZoomLevel(double zoomLevel) OVERRIDE;
+  CefRefPtr<CefBrowser> GetBrowser() override;
+  void CloseBrowser(bool force_close) override;
+  bool TryCloseBrowser() override;
+  void SetFocus(bool focus) override;
+  CefWindowHandle GetWindowHandle() override;
+  CefWindowHandle GetOpenerWindowHandle() override;
+  bool HasView() override;
+  CefRefPtr<CefClient> GetClient() override;
+  CefRefPtr<CefRequestContext> GetRequestContext() override;
+  bool CanZoom(cef_zoom_command_t command) override;
+  void Zoom(cef_zoom_command_t command) override;
+  double GetDefaultZoomLevel() override;
+  double GetZoomLevel() override;
+  void SetZoomLevel(double zoomLevel) override;
   void RunFileDialog(FileDialogMode mode,
                      const CefString& title,
                      const CefString& default_file_path,
                      const std::vector<CefString>& accept_filters,
-                     int selected_accept_filter,
-                     CefRefPtr<CefRunFileDialogCallback> callback) OVERRIDE;
-  void StartDownload(const CefString& url) OVERRIDE;
+                     CefRefPtr<CefRunFileDialogCallback> callback) override;
+  void StartDownload(const CefString& url) override;
   void DownloadImage(const CefString& image_url,
                      bool is_favicon,
-                     uint32 max_image_size,
+                     uint32_t max_image_size,
                      bool bypass_cache,
-                     CefRefPtr<CefDownloadImageCallback> callback) OVERRIDE;
-  void Print() OVERRIDE;
+                     CefRefPtr<CefDownloadImageCallback> callback) override;
+  void Print() override;
   void PrintToPDF(const CefString& path,
                   const CefPdfPrintSettings& settings,
-                  CefRefPtr<CefPdfPrintCallback> callback) OVERRIDE;
-  void Find(int identifier,
-            const CefString& searchText,
+                  CefRefPtr<CefPdfPrintCallback> callback) override;
+  void Find(const CefString& searchText,
             bool forward,
             bool matchCase,
-            bool findNext) OVERRIDE;
-  void StopFinding(bool clearSelection) OVERRIDE;
+            bool findNext) override;
+  void StopFinding(bool clearSelection) override;
   void ShowDevTools(const CefWindowInfo& windowInfo,
                     CefRefPtr<CefClient> client,
                     const CefBrowserSettings& settings,
-                    const CefPoint& inspect_element_at) OVERRIDE;
-  void CloseDevTools() OVERRIDE;
-  bool HasDevTools() OVERRIDE;
-  bool SendDevToolsMessage(const void* message, size_t message_size) OVERRIDE;
+                    const CefPoint& inspect_element_at) override;
+  void CloseDevTools() override;
+  bool HasDevTools() override;
+  bool SendDevToolsMessage(const void* message, size_t message_size) override;
   int ExecuteDevToolsMethod(int message_id,
                             const CefString& method,
-                            CefRefPtr<CefDictionaryValue> params) OVERRIDE;
+                            CefRefPtr<CefDictionaryValue> params) override;
   CefRefPtr<CefRegistration> AddDevToolsMessageObserver(
-      CefRefPtr<CefDevToolsMessageObserver> observer) OVERRIDE;
+      CefRefPtr<CefDevToolsMessageObserver> observer) override;
   void GetNavigationEntries(CefRefPtr<CefNavigationEntryVisitor> visitor,
-                            bool current_only) OVERRIDE;
-  void SetMouseCursorChangeDisabled(bool disabled) OVERRIDE;
-  bool IsMouseCursorChangeDisabled() OVERRIDE;
-  void ReplaceMisspelling(const CefString& word) OVERRIDE;
-  void AddWordToDictionary(const CefString& word) OVERRIDE;
-  bool IsWindowRenderingDisabled() OVERRIDE;
-  void WasResized() OVERRIDE;
-  void WasHidden(bool hidden) OVERRIDE;
-  void NotifyScreenInfoChanged() OVERRIDE;
-  void Invalidate(PaintElementType type) OVERRIDE;
-  void SendExternalBeginFrame() OVERRIDE;
-  void SendKeyEvent(const CefKeyEvent& event) OVERRIDE;
+                            bool current_only) override;
+  void ReplaceMisspelling(const CefString& word) override;
+  void AddWordToDictionary(const CefString& word) override;
+  bool IsWindowRenderingDisabled() override;
+  void WasResized() override;
+  void WasHidden(bool hidden) override;
+  void NotifyScreenInfoChanged() override;
+  void Invalidate(PaintElementType type) override;
+  void SendExternalBeginFrame() override;
+  void SendKeyEvent(const CefKeyEvent& event) override;
   void SendMouseClickEvent(const CefMouseEvent& event,
                            MouseButtonType type,
                            bool mouseUp,
-                           int clickCount) OVERRIDE;
-  void SendMouseMoveEvent(const CefMouseEvent& event, bool mouseLeave) OVERRIDE;
+                           int clickCount) override;
+  void SendMouseMoveEvent(const CefMouseEvent& event, bool mouseLeave) override;
   void SendMouseWheelEvent(const CefMouseEvent& event,
                            int deltaX,
-                           int deltaY) OVERRIDE;
-  void SendTouchEvent(const CefTouchEvent& event) OVERRIDE;
-  void SendFocusEvent(bool setFocus) OVERRIDE;
-  void SendCaptureLostEvent() OVERRIDE;
-  void NotifyMoveOrResizeStarted() OVERRIDE;
-  int GetWindowlessFrameRate() OVERRIDE;
-  void SetWindowlessFrameRate(int frame_rate) OVERRIDE;
+                           int deltaY) override;
+  void SendTouchEvent(const CefTouchEvent& event) override;
+  void SendCaptureLostEvent() override;
+  void NotifyMoveOrResizeStarted() override;
+  int GetWindowlessFrameRate() override;
+  void SetWindowlessFrameRate(int frame_rate) override;
   void ImeSetComposition(const CefString& text,
                          const std::vector<CefCompositionUnderline>& underlines,
                          const CefRange& replacement_range,
-                         const CefRange& selection_range) OVERRIDE;
+                         const CefRange& selection_range) override;
   void ImeCommitText(const CefString& text,
                      const CefRange& replacement_range,
-                     int relative_cursor_pos) OVERRIDE;
-  void ImeFinishComposingText(bool keep_selection) OVERRIDE;
-  void ImeCancelComposition() OVERRIDE;
+                     int relative_cursor_pos) override;
+  void ImeFinishComposingText(bool keep_selection) override;
+  void ImeCancelComposition() override;
   void DragTargetDragEnter(CefRefPtr<CefDragData> drag_data,
                            const CefMouseEvent& event,
-                           DragOperationsMask allowed_ops) OVERRIDE;
+                           DragOperationsMask allowed_ops) override;
   void DragTargetDragOver(const CefMouseEvent& event,
-                          DragOperationsMask allowed_ops) OVERRIDE;
-  void DragTargetDragLeave() OVERRIDE;
-  void DragTargetDrop(const CefMouseEvent& event) OVERRIDE;
-  void DragSourceEndedAt(int x, int y, DragOperationsMask op) OVERRIDE;
-  void DragSourceSystemDragEnded() OVERRIDE;
-  CefRefPtr<CefNavigationEntry> GetVisibleNavigationEntry() OVERRIDE;
-  void SetAccessibilityState(cef_state_t accessibility_state) OVERRIDE;
+                          DragOperationsMask allowed_ops) override;
+  void DragTargetDragLeave() override;
+  void DragTargetDrop(const CefMouseEvent& event) override;
+  void DragSourceEndedAt(int x, int y, DragOperationsMask op) override;
+  void DragSourceSystemDragEnded() override;
+  CefRefPtr<CefNavigationEntry> GetVisibleNavigationEntry() override;
+  void SetAccessibilityState(cef_state_t accessibility_state) override;
   void SetAutoResizeEnabled(bool enabled,
                             const CefSize& min_size,
-                            const CefSize& max_size) OVERRIDE;
-  CefRefPtr<CefExtension> GetExtension() OVERRIDE;
-  bool IsBackgroundHost() OVERRIDE;
-  void SetAudioMuted(bool mute) OVERRIDE;
-  bool IsAudioMuted() OVERRIDE;
+                            const CefSize& max_size) override;
+  CefRefPtr<CefExtension> GetExtension() override;
+  bool IsBackgroundHost() override;
+  void SetAudioMuted(bool mute) override;
+  bool IsAudioMuted() override;
+  bool IsFullscreen() override;
+  void ExitFullscreen(bool will_cause_resize) override;
+  bool CanExecuteChromeCommand(int command_id) override;
+  void ExecuteChromeCommand(int command_id,
+                            cef_window_open_disposition_t disposition) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_BROWSER_HOST_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/browser_process_handler_ctocpp.cc b/src/libcef_dll/ctocpp/browser_process_handler_ctocpp.cc
index e69b60c..092d917 100644
--- a/src/libcef_dll/ctocpp/browser_process_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/browser_process_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,21 +9,48 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=622d56aec0a5d6485a586bd6d993df7af4fa2d62$
+// $hash=533775387bf1001675aeb94a62bc4ece1eb11125$
 //
 
 #include "libcef_dll/ctocpp/browser_process_handler_ctocpp.h"
 #include "libcef_dll/cpptoc/command_line_cpptoc.h"
-#include "libcef_dll/cpptoc/list_value_cpptoc.h"
-#include "libcef_dll/ctocpp/print_handler_ctocpp.h"
+#include "libcef_dll/cpptoc/preference_registrar_cpptoc.h"
+#include "libcef_dll/ctocpp/client_ctocpp.h"
 
 // VIRTUAL METHODS - Body may be edited by hand.
 
 NO_SANITIZE("cfi-icall")
+void CefBrowserProcessHandlerCToCpp::OnRegisterCustomPreferences(
+    cef_preferences_type_t type,
+    CefRawPtr<CefPreferenceRegistrar> registrar) {
+  cef_browser_process_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_register_custom_preferences)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: registrar; type: rawptr_diff
+  DCHECK(registrar);
+  if (!registrar) {
+    return;
+  }
+
+  // Translate param: registrar; type: rawptr_diff
+  CefOwnPtr<CefPreferenceRegistrarCppToC> registrarPtr(
+      CefPreferenceRegistrarCppToC::WrapRaw(registrar));
+
+  // Execute
+  _struct->on_register_custom_preferences(_struct, type,
+                                          registrarPtr->GetStruct());
+}
+
+NO_SANITIZE("cfi-icall")
 void CefBrowserProcessHandlerCToCpp::OnContextInitialized() {
   cef_browser_process_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_context_initialized))
+  if (CEF_MEMBER_MISSING(_struct, on_context_initialized)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -35,15 +62,17 @@
 void CefBrowserProcessHandlerCToCpp::OnBeforeChildProcessLaunch(
     CefRefPtr<CefCommandLine> command_line) {
   cef_browser_process_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_before_child_process_launch))
+  if (CEF_MEMBER_MISSING(_struct, on_before_child_process_launch)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: command_line; type: refptr_diff
   DCHECK(command_line.get());
-  if (!command_line.get())
+  if (!command_line.get()) {
     return;
+  }
 
   // Execute
   _struct->on_before_child_process_launch(
@@ -51,44 +80,12 @@
 }
 
 NO_SANITIZE("cfi-icall")
-void CefBrowserProcessHandlerCToCpp::OnRenderProcessThreadCreated(
-    CefRefPtr<CefListValue> extra_info) {
+void CefBrowserProcessHandlerCToCpp::OnScheduleMessagePumpWork(
+    int64_t delay_ms) {
   cef_browser_process_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_render_process_thread_created))
+  if (CEF_MEMBER_MISSING(_struct, on_schedule_message_pump_work)) {
     return;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: extra_info; type: refptr_diff
-  DCHECK(extra_info.get());
-  if (!extra_info.get())
-    return;
-
-  // Execute
-  _struct->on_render_process_thread_created(
-      _struct, CefListValueCppToC::Wrap(extra_info));
-}
-
-NO_SANITIZE("cfi-icall")
-CefRefPtr<CefPrintHandler> CefBrowserProcessHandlerCToCpp::GetPrintHandler() {
-  cef_browser_process_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_print_handler))
-    return nullptr;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  cef_print_handler_t* _retval = _struct->get_print_handler(_struct);
-
-  // Return type: refptr_same
-  return CefPrintHandlerCToCpp::Wrap(_retval);
-}
-
-NO_SANITIZE("cfi-icall")
-void CefBrowserProcessHandlerCToCpp::OnScheduleMessagePumpWork(int64 delay_ms) {
-  cef_browser_process_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_schedule_message_pump_work))
-    return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -96,6 +93,22 @@
   _struct->on_schedule_message_pump_work(_struct, delay_ms);
 }
 
+NO_SANITIZE("cfi-icall")
+CefRefPtr<CefClient> CefBrowserProcessHandlerCToCpp::GetDefaultClient() {
+  cef_browser_process_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_default_client)) {
+    return nullptr;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_client_t* _retval = _struct->get_default_client(_struct);
+
+  // Return type: refptr_same
+  return CefClientCToCpp::Wrap(_retval);
+}
+
 // CONSTRUCTOR - Do not edit by hand.
 
 CefBrowserProcessHandlerCToCpp::CefBrowserProcessHandlerCToCpp() {}
@@ -110,7 +123,7 @@
     CefBrowserProcessHandler,
     cef_browser_process_handler_t>::UnwrapDerived(CefWrapperType type,
                                                   CefBrowserProcessHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/browser_process_handler_ctocpp.h b/src/libcef_dll/ctocpp/browser_process_handler_ctocpp.h
index 344ce82..2e61fc2 100644
--- a/src/libcef_dll/ctocpp/browser_process_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/browser_process_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d07e79689f98b41fd7a0fb8c45dcae12a945cfe4$
+// $hash=5dd3fc70331d85a1c7ce5e402bc1e2f050fbe467$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_BROWSER_PROCESS_HANDLER_CTOCPP_H_
@@ -35,13 +35,14 @@
   virtual ~CefBrowserProcessHandlerCToCpp();
 
   // CefBrowserProcessHandler methods.
+  void OnRegisterCustomPreferences(
+      cef_preferences_type_t type,
+      CefRawPtr<CefPreferenceRegistrar> registrar) override;
   void OnContextInitialized() override;
   void OnBeforeChildProcessLaunch(
       CefRefPtr<CefCommandLine> command_line) override;
-  void OnRenderProcessThreadCreated(
-      CefRefPtr<CefListValue> extra_info) override;
-  CefRefPtr<CefPrintHandler> GetPrintHandler() override;
-  void OnScheduleMessagePumpWork(int64 delay_ms) override;
+  void OnScheduleMessagePumpWork(int64_t delay_ms) override;
+  CefRefPtr<CefClient> GetDefaultClient() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_BROWSER_PROCESS_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/callback_ctocpp.cc b/src/libcef_dll/ctocpp/callback_ctocpp.cc
index 3a19009..dd31632 100644
--- a/src/libcef_dll/ctocpp/callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6d697bd19634711e28262d9df97887fd1abf47d6$
+// $hash=a41feff4617bc9beb0512a1350f3ac700b18ea2e$
 //
 
 #include "libcef_dll/ctocpp/callback_ctocpp.h"
@@ -21,8 +21,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cont))
+  if (CEF_MEMBER_MISSING(_struct, cont)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -34,8 +35,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cancel))
+  if (CEF_MEMBER_MISSING(_struct, cancel)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -57,7 +59,7 @@
 cef_callback_t*
 CefCToCppRefCounted<CefCallbackCToCpp, CefCallback, cef_callback_t>::
     UnwrapDerived(CefWrapperType type, CefCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/callback_ctocpp.h b/src/libcef_dll/ctocpp/callback_ctocpp.h
index 0f72d08..1e59651 100644
--- a/src/libcef_dll/ctocpp/callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ff9e0075f199c0dc641059bd34b4366657de3125$
+// $hash=33a36c40703e1a794c2d8365f0ed692bad529e4b$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_CALLBACK_CTOCPP_H_
@@ -34,8 +34,8 @@
   virtual ~CefCallbackCToCpp();
 
   // CefCallback methods.
-  void Continue() OVERRIDE;
-  void Cancel() OVERRIDE;
+  void Continue() override;
+  void Cancel() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/client_ctocpp.cc b/src/libcef_dll/ctocpp/client_ctocpp.cc
index 3176ebd..c4d3ef9 100644
--- a/src/libcef_dll/ctocpp/client_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/client_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0e4556cf21b4d75aefbfa90963c6b5c9aba33bad$
+// $hash=ec38c71520cffd0d1ff4f1ee83819c411b14c795$
 //
 
 #include "libcef_dll/ctocpp/client_ctocpp.h"
@@ -17,6 +17,7 @@
 #include "libcef_dll/cpptoc/frame_cpptoc.h"
 #include "libcef_dll/cpptoc/process_message_cpptoc.h"
 #include "libcef_dll/ctocpp/audio_handler_ctocpp.h"
+#include "libcef_dll/ctocpp/command_handler_ctocpp.h"
 #include "libcef_dll/ctocpp/context_menu_handler_ctocpp.h"
 #include "libcef_dll/ctocpp/dialog_handler_ctocpp.h"
 #include "libcef_dll/ctocpp/display_handler_ctocpp.h"
@@ -24,10 +25,13 @@
 #include "libcef_dll/ctocpp/drag_handler_ctocpp.h"
 #include "libcef_dll/ctocpp/find_handler_ctocpp.h"
 #include "libcef_dll/ctocpp/focus_handler_ctocpp.h"
+#include "libcef_dll/ctocpp/frame_handler_ctocpp.h"
 #include "libcef_dll/ctocpp/jsdialog_handler_ctocpp.h"
 #include "libcef_dll/ctocpp/keyboard_handler_ctocpp.h"
 #include "libcef_dll/ctocpp/life_span_handler_ctocpp.h"
 #include "libcef_dll/ctocpp/load_handler_ctocpp.h"
+#include "libcef_dll/ctocpp/permission_handler_ctocpp.h"
+#include "libcef_dll/ctocpp/print_handler_ctocpp.h"
 #include "libcef_dll/ctocpp/render_handler_ctocpp.h"
 #include "libcef_dll/ctocpp/request_handler_ctocpp.h"
 
@@ -36,8 +40,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefAudioHandler> CefClientCToCpp::GetAudioHandler() {
   cef_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_audio_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_audio_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -49,10 +54,27 @@
 }
 
 NO_SANITIZE("cfi-icall")
+CefRefPtr<CefCommandHandler> CefClientCToCpp::GetCommandHandler() {
+  cef_client_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_command_handler)) {
+    return nullptr;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_command_handler_t* _retval = _struct->get_command_handler(_struct);
+
+  // Return type: refptr_same
+  return CefCommandHandlerCToCpp::Wrap(_retval);
+}
+
+NO_SANITIZE("cfi-icall")
 CefRefPtr<CefContextMenuHandler> CefClientCToCpp::GetContextMenuHandler() {
   cef_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_context_menu_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_context_menu_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -67,8 +89,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefDialogHandler> CefClientCToCpp::GetDialogHandler() {
   cef_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_dialog_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_dialog_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -82,8 +105,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefDisplayHandler> CefClientCToCpp::GetDisplayHandler() {
   cef_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_display_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_display_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -97,8 +121,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefDownloadHandler> CefClientCToCpp::GetDownloadHandler() {
   cef_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_download_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_download_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -112,8 +137,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefDragHandler> CefClientCToCpp::GetDragHandler() {
   cef_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_drag_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_drag_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -127,8 +153,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefFindHandler> CefClientCToCpp::GetFindHandler() {
   cef_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_find_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_find_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -142,8 +169,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefFocusHandler> CefClientCToCpp::GetFocusHandler() {
   cef_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_focus_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_focus_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -155,10 +183,43 @@
 }
 
 NO_SANITIZE("cfi-icall")
+CefRefPtr<CefFrameHandler> CefClientCToCpp::GetFrameHandler() {
+  cef_client_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_frame_handler)) {
+    return nullptr;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_frame_handler_t* _retval = _struct->get_frame_handler(_struct);
+
+  // Return type: refptr_same
+  return CefFrameHandlerCToCpp::Wrap(_retval);
+}
+
+NO_SANITIZE("cfi-icall")
+CefRefPtr<CefPermissionHandler> CefClientCToCpp::GetPermissionHandler() {
+  cef_client_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_permission_handler)) {
+    return nullptr;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_permission_handler_t* _retval = _struct->get_permission_handler(_struct);
+
+  // Return type: refptr_same
+  return CefPermissionHandlerCToCpp::Wrap(_retval);
+}
+
+NO_SANITIZE("cfi-icall")
 CefRefPtr<CefJSDialogHandler> CefClientCToCpp::GetJSDialogHandler() {
   cef_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_jsdialog_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_jsdialog_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -172,8 +233,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefKeyboardHandler> CefClientCToCpp::GetKeyboardHandler() {
   cef_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_keyboard_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_keyboard_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -187,8 +249,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefLifeSpanHandler> CefClientCToCpp::GetLifeSpanHandler() {
   cef_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_life_span_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_life_span_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -202,8 +265,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefLoadHandler> CefClientCToCpp::GetLoadHandler() {
   cef_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_load_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_load_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -215,10 +279,27 @@
 }
 
 NO_SANITIZE("cfi-icall")
+CefRefPtr<CefPrintHandler> CefClientCToCpp::GetPrintHandler() {
+  cef_client_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_print_handler)) {
+    return nullptr;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_print_handler_t* _retval = _struct->get_print_handler(_struct);
+
+  // Return type: refptr_same
+  return CefPrintHandlerCToCpp::Wrap(_retval);
+}
+
+NO_SANITIZE("cfi-icall")
 CefRefPtr<CefRenderHandler> CefClientCToCpp::GetRenderHandler() {
   cef_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_render_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_render_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -232,8 +313,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefRequestHandler> CefClientCToCpp::GetRequestHandler() {
   cef_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_request_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_request_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -251,23 +333,27 @@
     CefProcessId source_process,
     CefRefPtr<CefProcessMessage> message) {
   cef_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_process_message_received))
+  if (CEF_MEMBER_MISSING(_struct, on_process_message_received)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return false;
+  }
   // Verify param: message; type: refptr_diff
   DCHECK(message.get());
-  if (!message.get())
+  if (!message.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->on_process_message_received(
@@ -291,7 +377,7 @@
 CefCToCppRefCounted<CefClientCToCpp, CefClient, cef_client_t>::UnwrapDerived(
     CefWrapperType type,
     CefClient* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/client_ctocpp.h b/src/libcef_dll/ctocpp/client_ctocpp.h
index d42e9f2..f38dae9 100644
--- a/src/libcef_dll/ctocpp/client_ctocpp.h
+++ b/src/libcef_dll/ctocpp/client_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f751ee624cc3b8570cba8caa051c51bb7aeccaa7$
+// $hash=28e1869fba61dd480e1194722393eb2b83ccba5e$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_CLIENT_CTOCPP_H_
@@ -34,6 +34,7 @@
 
   // CefClient methods.
   CefRefPtr<CefAudioHandler> GetAudioHandler() override;
+  CefRefPtr<CefCommandHandler> GetCommandHandler() override;
   CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() override;
   CefRefPtr<CefDialogHandler> GetDialogHandler() override;
   CefRefPtr<CefDisplayHandler> GetDisplayHandler() override;
@@ -41,10 +42,13 @@
   CefRefPtr<CefDragHandler> GetDragHandler() override;
   CefRefPtr<CefFindHandler> GetFindHandler() override;
   CefRefPtr<CefFocusHandler> GetFocusHandler() override;
+  CefRefPtr<CefFrameHandler> GetFrameHandler() override;
+  CefRefPtr<CefPermissionHandler> GetPermissionHandler() override;
   CefRefPtr<CefJSDialogHandler> GetJSDialogHandler() override;
   CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() override;
   CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override;
   CefRefPtr<CefLoadHandler> GetLoadHandler() override;
+  CefRefPtr<CefPrintHandler> GetPrintHandler() override;
   CefRefPtr<CefRenderHandler> GetRenderHandler() override;
   CefRefPtr<CefRequestHandler> GetRequestHandler() override;
   bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
diff --git a/src/libcef_dll/ctocpp/command_handler_ctocpp.cc b/src/libcef_dll/ctocpp/command_handler_ctocpp.cc
new file mode 100644
index 0000000..0499990
--- /dev/null
+++ b/src/libcef_dll/ctocpp/command_handler_ctocpp.cc
@@ -0,0 +1,165 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=f2eb90b2952e6958a01be325567b35d83c0643e6$
+//
+
+#include "libcef_dll/ctocpp/command_handler_ctocpp.h"
+#include "libcef_dll/cpptoc/browser_cpptoc.h"
+#include "libcef_dll/shutdown_checker.h"
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall")
+bool CefCommandHandlerCToCpp::OnChromeCommand(
+    CefRefPtr<CefBrowser> browser,
+    int command_id,
+    cef_window_open_disposition_t disposition) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_command_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_chrome_command)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->on_chrome_command(
+      _struct, CefBrowserCppToC::Wrap(browser), command_id, disposition);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefCommandHandlerCToCpp::IsChromeAppMenuItemVisible(
+    CefRefPtr<CefBrowser> browser,
+    int command_id) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_command_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, is_chrome_app_menu_item_visible)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->is_chrome_app_menu_item_visible(
+      _struct, CefBrowserCppToC::Wrap(browser), command_id);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefCommandHandlerCToCpp::IsChromeAppMenuItemEnabled(
+    CefRefPtr<CefBrowser> browser,
+    int command_id) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_command_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, is_chrome_app_menu_item_enabled)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->is_chrome_app_menu_item_enabled(
+      _struct, CefBrowserCppToC::Wrap(browser), command_id);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefCommandHandlerCToCpp::IsChromePageActionIconVisible(
+    cef_chrome_page_action_icon_type_t icon_type) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_command_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, is_chrome_page_action_icon_visible)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = _struct->is_chrome_page_action_icon_visible(_struct, icon_type);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefCommandHandlerCToCpp::IsChromeToolbarButtonVisible(
+    cef_chrome_toolbar_button_type_t button_type) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_command_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, is_chrome_toolbar_button_visible)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = _struct->is_chrome_toolbar_button_visible(_struct, button_type);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefCommandHandlerCToCpp::CefCommandHandlerCToCpp() {}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefCommandHandlerCToCpp::~CefCommandHandlerCToCpp() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+cef_command_handler_t* CefCToCppRefCounted<
+    CefCommandHandlerCToCpp,
+    CefCommandHandler,
+    cef_command_handler_t>::UnwrapDerived(CefWrapperType type,
+                                          CefCommandHandler* c) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCToCppRefCounted<CefCommandHandlerCToCpp,
+                                   CefCommandHandler,
+                                   cef_command_handler_t>::kWrapperType =
+    WT_COMMAND_HANDLER;
diff --git a/src/libcef_dll/ctocpp/command_handler_ctocpp.h b/src/libcef_dll/ctocpp/command_handler_ctocpp.h
new file mode 100644
index 0000000..c5bf823
--- /dev/null
+++ b/src/libcef_dll/ctocpp/command_handler_ctocpp.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=ad0096887a1662a2cc3804248365e56fc20d6eaa$
+//
+
+#ifndef CEF_LIBCEF_DLL_CTOCPP_COMMAND_HANDLER_CTOCPP_H_
+#define CEF_LIBCEF_DLL_CTOCPP_COMMAND_HANDLER_CTOCPP_H_
+#pragma once
+
+#if !defined(BUILDING_CEF_SHARED)
+#error This file can be included DLL-side only
+#endif
+
+#include "include/capi/cef_command_handler_capi.h"
+#include "include/cef_command_handler.h"
+#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
+
+// Wrap a C structure with a C++ class.
+// This class may be instantiated and accessed DLL-side only.
+class CefCommandHandlerCToCpp
+    : public CefCToCppRefCounted<CefCommandHandlerCToCpp,
+                                 CefCommandHandler,
+                                 cef_command_handler_t> {
+ public:
+  CefCommandHandlerCToCpp();
+  virtual ~CefCommandHandlerCToCpp();
+
+  // CefCommandHandler methods.
+  bool OnChromeCommand(CefRefPtr<CefBrowser> browser,
+                       int command_id,
+                       cef_window_open_disposition_t disposition) override;
+  bool IsChromeAppMenuItemVisible(CefRefPtr<CefBrowser> browser,
+                                  int command_id) override;
+  bool IsChromeAppMenuItemEnabled(CefRefPtr<CefBrowser> browser,
+                                  int command_id) override;
+  bool IsChromePageActionIconVisible(
+      cef_chrome_page_action_icon_type_t icon_type) override;
+  bool IsChromeToolbarButtonVisible(
+      cef_chrome_toolbar_button_type_t button_type) override;
+};
+
+#endif  // CEF_LIBCEF_DLL_CTOCPP_COMMAND_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/command_line_ctocpp.cc b/src/libcef_dll/ctocpp/command_line_ctocpp.cc
index 9ecbc2e..4ff4159 100644
--- a/src/libcef_dll/ctocpp/command_line_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/command_line_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7d5995f534719bf6466eb174f50027cc57db98ef$
+// $hash=aeb30347dcf0a11ee20524f07fe7eb980c2163f2$
 //
 
 #include "libcef_dll/ctocpp/command_line_ctocpp.h"
@@ -23,7 +23,7 @@
   const char* api_hash = cef_api_hash(0);
   if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) {
     // The libcef API hash does not match the current header API hash.
-    NOTREACHED();
+    DCHECK(false);
     return nullptr;
   }
 
@@ -41,7 +41,7 @@
   const char* api_hash = cef_api_hash(0);
   if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) {
     // The libcef API hash does not match the current header API hash.
-    NOTREACHED();
+    DCHECK(false);
     return nullptr;
   }
 
@@ -58,8 +58,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefCommandLineCToCpp::IsValid() {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -72,8 +73,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefCommandLineCToCpp::IsReadOnly() {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_read_only))
+  if (CEF_MEMBER_MISSING(_struct, is_read_only)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -87,8 +89,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefCommandLine> CefCommandLineCToCpp::Copy() {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, copy))
+  if (CEF_MEMBER_MISSING(_struct, copy)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -102,15 +105,17 @@
 NO_SANITIZE("cfi-icall")
 void CefCommandLineCToCpp::InitFromArgv(int argc, const char* const* argv) {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, init_from_argv))
+  if (CEF_MEMBER_MISSING(_struct, init_from_argv)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: argv; type: simple_byaddr
   DCHECK(argv);
-  if (!argv)
+  if (!argv) {
     return;
+  }
 
   // Execute
   _struct->init_from_argv(_struct, argc, argv);
@@ -119,15 +124,17 @@
 NO_SANITIZE("cfi-icall")
 void CefCommandLineCToCpp::InitFromString(const CefString& command_line) {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, init_from_string))
+  if (CEF_MEMBER_MISSING(_struct, init_from_string)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: command_line; type: string_byref_const
   DCHECK(!command_line.empty());
-  if (command_line.empty())
+  if (command_line.empty()) {
     return;
+  }
 
   // Execute
   _struct->init_from_string(_struct, command_line.GetStruct());
@@ -135,8 +142,9 @@
 
 NO_SANITIZE("cfi-icall") void CefCommandLineCToCpp::Reset() {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, reset))
+  if (CEF_MEMBER_MISSING(_struct, reset)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -147,16 +155,18 @@
 NO_SANITIZE("cfi-icall")
 void CefCommandLineCToCpp::GetArgv(std::vector<CefString>& argv) {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_argv))
+  if (CEF_MEMBER_MISSING(_struct, get_argv)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: argv; type: string_vec_byref
   cef_string_list_t argvList = cef_string_list_alloc();
   DCHECK(argvList);
-  if (argvList)
+  if (argvList) {
     transfer_string_list_contents(argv, argvList);
+  }
 
   // Execute
   _struct->get_argv(_struct, argvList);
@@ -172,8 +182,9 @@
 NO_SANITIZE("cfi-icall")
 CefString CefCommandLineCToCpp::GetCommandLineString() {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_command_line_string))
+  if (CEF_MEMBER_MISSING(_struct, get_command_line_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -188,8 +199,9 @@
 
 NO_SANITIZE("cfi-icall") CefString CefCommandLineCToCpp::GetProgram() {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_program))
+  if (CEF_MEMBER_MISSING(_struct, get_program)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -205,15 +217,17 @@
 NO_SANITIZE("cfi-icall")
 void CefCommandLineCToCpp::SetProgram(const CefString& program) {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_program))
+  if (CEF_MEMBER_MISSING(_struct, set_program)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: program; type: string_byref_const
   DCHECK(!program.empty());
-  if (program.empty())
+  if (program.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_program(_struct, program.GetStruct());
@@ -221,8 +235,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefCommandLineCToCpp::HasSwitches() {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_switches))
+  if (CEF_MEMBER_MISSING(_struct, has_switches)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -236,15 +251,17 @@
 NO_SANITIZE("cfi-icall")
 bool CefCommandLineCToCpp::HasSwitch(const CefString& name) {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_switch))
+  if (CEF_MEMBER_MISSING(_struct, has_switch)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->has_switch(_struct, name.GetStruct());
@@ -256,15 +273,17 @@
 NO_SANITIZE("cfi-icall")
 CefString CefCommandLineCToCpp::GetSwitchValue(const CefString& name) {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_switch_value))
+  if (CEF_MEMBER_MISSING(_struct, get_switch_value)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return CefString();
+  }
 
   // Execute
   cef_string_userfree_t _retval =
@@ -279,16 +298,18 @@
 NO_SANITIZE("cfi-icall")
 void CefCommandLineCToCpp::GetSwitches(SwitchMap& switches) {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_switches))
+  if (CEF_MEMBER_MISSING(_struct, get_switches)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: switches; type: string_map_single_byref
   cef_string_map_t switchesMap = cef_string_map_alloc();
   DCHECK(switchesMap);
-  if (switchesMap)
+  if (switchesMap) {
     transfer_string_map_contents(switches, switchesMap);
+  }
 
   // Execute
   _struct->get_switches(_struct, switchesMap);
@@ -304,15 +325,17 @@
 NO_SANITIZE("cfi-icall")
 void CefCommandLineCToCpp::AppendSwitch(const CefString& name) {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, append_switch))
+  if (CEF_MEMBER_MISSING(_struct, append_switch)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return;
+  }
 
   // Execute
   _struct->append_switch(_struct, name.GetStruct());
@@ -322,19 +345,22 @@
 void CefCommandLineCToCpp::AppendSwitchWithValue(const CefString& name,
                                                  const CefString& value) {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, append_switch_with_value))
+  if (CEF_MEMBER_MISSING(_struct, append_switch_with_value)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return;
+  }
   // Verify param: value; type: string_byref_const
   DCHECK(!value.empty());
-  if (value.empty())
+  if (value.empty()) {
     return;
+  }
 
   // Execute
   _struct->append_switch_with_value(_struct, name.GetStruct(),
@@ -343,8 +369,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefCommandLineCToCpp::HasArguments() {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_arguments))
+  if (CEF_MEMBER_MISSING(_struct, has_arguments)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -358,16 +385,18 @@
 NO_SANITIZE("cfi-icall")
 void CefCommandLineCToCpp::GetArguments(ArgumentList& arguments) {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_arguments))
+  if (CEF_MEMBER_MISSING(_struct, get_arguments)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: arguments; type: string_vec_byref
   cef_string_list_t argumentsList = cef_string_list_alloc();
   DCHECK(argumentsList);
-  if (argumentsList)
+  if (argumentsList) {
     transfer_string_list_contents(arguments, argumentsList);
+  }
 
   // Execute
   _struct->get_arguments(_struct, argumentsList);
@@ -383,15 +412,17 @@
 NO_SANITIZE("cfi-icall")
 void CefCommandLineCToCpp::AppendArgument(const CefString& argument) {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, append_argument))
+  if (CEF_MEMBER_MISSING(_struct, append_argument)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: argument; type: string_byref_const
   DCHECK(!argument.empty());
-  if (argument.empty())
+  if (argument.empty()) {
     return;
+  }
 
   // Execute
   _struct->append_argument(_struct, argument.GetStruct());
@@ -400,15 +431,17 @@
 NO_SANITIZE("cfi-icall")
 void CefCommandLineCToCpp::PrependWrapper(const CefString& wrapper) {
   cef_command_line_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, prepend_wrapper))
+  if (CEF_MEMBER_MISSING(_struct, prepend_wrapper)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: wrapper; type: string_byref_const
   DCHECK(!wrapper.empty());
-  if (wrapper.empty())
+  if (wrapper.empty()) {
     return;
+  }
 
   // Execute
   _struct->prepend_wrapper(_struct, wrapper.GetStruct());
@@ -426,7 +459,7 @@
 cef_command_line_t*
 CefCToCppRefCounted<CefCommandLineCToCpp, CefCommandLine, cef_command_line_t>::
     UnwrapDerived(CefWrapperType type, CefCommandLine* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/command_line_ctocpp.h b/src/libcef_dll/ctocpp/command_line_ctocpp.h
index 080eaf2..7beaa99 100644
--- a/src/libcef_dll/ctocpp/command_line_ctocpp.h
+++ b/src/libcef_dll/ctocpp/command_line_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=de597fbd256308a25adcd6ac0d27b1293ce6a088$
+// $hash=c91f76be5a60016fa78afe2813b0d4df3bb422e7$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_COMMAND_LINE_CTOCPP_H_
@@ -35,27 +35,27 @@
   virtual ~CefCommandLineCToCpp();
 
   // CefCommandLine methods.
-  bool IsValid() OVERRIDE;
-  bool IsReadOnly() OVERRIDE;
-  CefRefPtr<CefCommandLine> Copy() OVERRIDE;
-  void InitFromArgv(int argc, const char* const* argv) OVERRIDE;
-  void InitFromString(const CefString& command_line) OVERRIDE;
-  void Reset() OVERRIDE;
-  void GetArgv(std::vector<CefString>& argv) OVERRIDE;
-  CefString GetCommandLineString() OVERRIDE;
-  CefString GetProgram() OVERRIDE;
-  void SetProgram(const CefString& program) OVERRIDE;
-  bool HasSwitches() OVERRIDE;
-  bool HasSwitch(const CefString& name) OVERRIDE;
-  CefString GetSwitchValue(const CefString& name) OVERRIDE;
-  void GetSwitches(SwitchMap& switches) OVERRIDE;
-  void AppendSwitch(const CefString& name) OVERRIDE;
+  bool IsValid() override;
+  bool IsReadOnly() override;
+  CefRefPtr<CefCommandLine> Copy() override;
+  void InitFromArgv(int argc, const char* const* argv) override;
+  void InitFromString(const CefString& command_line) override;
+  void Reset() override;
+  void GetArgv(std::vector<CefString>& argv) override;
+  CefString GetCommandLineString() override;
+  CefString GetProgram() override;
+  void SetProgram(const CefString& program) override;
+  bool HasSwitches() override;
+  bool HasSwitch(const CefString& name) override;
+  CefString GetSwitchValue(const CefString& name) override;
+  void GetSwitches(SwitchMap& switches) override;
+  void AppendSwitch(const CefString& name) override;
   void AppendSwitchWithValue(const CefString& name,
-                             const CefString& value) OVERRIDE;
-  bool HasArguments() OVERRIDE;
-  void GetArguments(ArgumentList& arguments) OVERRIDE;
-  void AppendArgument(const CefString& argument) OVERRIDE;
-  void PrependWrapper(const CefString& wrapper) OVERRIDE;
+                             const CefString& value) override;
+  bool HasArguments() override;
+  void GetArguments(ArgumentList& arguments) override;
+  void AppendArgument(const CefString& argument) override;
+  void PrependWrapper(const CefString& wrapper) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_COMMAND_LINE_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/completion_callback_ctocpp.cc b/src/libcef_dll/ctocpp/completion_callback_ctocpp.cc
index 4d9c8fa..930ef04 100644
--- a/src/libcef_dll/ctocpp/completion_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/completion_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2193f30ba657212718712739c7b48dd9b84b7bb8$
+// $hash=3c645623a6fdcc8eb1dc721fc84ca63a85cdbe3c$
 //
 
 #include "libcef_dll/ctocpp/completion_callback_ctocpp.h"
@@ -21,8 +21,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_completion_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_complete))
+  if (CEF_MEMBER_MISSING(_struct, on_complete)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -46,7 +47,7 @@
     CefCompletionCallback,
     cef_completion_callback_t>::UnwrapDerived(CefWrapperType type,
                                               CefCompletionCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/completion_callback_ctocpp.h b/src/libcef_dll/ctocpp/completion_callback_ctocpp.h
index c15136d..37956aa 100644
--- a/src/libcef_dll/ctocpp/completion_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/completion_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8c963d9ea85918f6942e95c24dce6769a7f881c5$
+// $hash=bbdf6c23d87122deb5d3100430547b2c608497a9$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_COMPLETION_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/context_menu_handler_ctocpp.cc b/src/libcef_dll/ctocpp/context_menu_handler_ctocpp.cc
index a4a0799..f1db148 100644
--- a/src/libcef_dll/ctocpp/context_menu_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/context_menu_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d0eec19bee7cbc38c676ef6ca936483cc93bb7fc$
+// $hash=2c8888f9fcfe40cf08eb2c9e4fff20a64c3ead7d$
 //
 
 #include "libcef_dll/ctocpp/context_menu_handler_ctocpp.h"
@@ -18,6 +18,7 @@
 #include "libcef_dll/cpptoc/frame_cpptoc.h"
 #include "libcef_dll/cpptoc/menu_model_cpptoc.h"
 #include "libcef_dll/cpptoc/run_context_menu_callback_cpptoc.h"
+#include "libcef_dll/cpptoc/run_quick_menu_callback_cpptoc.h"
 #include "libcef_dll/shutdown_checker.h"
 
 // VIRTUAL METHODS - Body may be edited by hand.
@@ -31,27 +32,32 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_before_context_menu))
+  if (CEF_MEMBER_MISSING(_struct, on_before_context_menu)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return;
+  }
   // Verify param: params; type: refptr_diff
   DCHECK(params.get());
-  if (!params.get())
+  if (!params.get()) {
     return;
+  }
   // Verify param: model; type: refptr_diff
   DCHECK(model.get());
-  if (!model.get())
+  if (!model.get()) {
     return;
+  }
 
   // Execute
   _struct->on_before_context_menu(_struct, CefBrowserCppToC::Wrap(browser),
@@ -70,31 +76,37 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, run_context_menu))
+  if (CEF_MEMBER_MISSING(_struct, run_context_menu)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return false;
+  }
   // Verify param: params; type: refptr_diff
   DCHECK(params.get());
-  if (!params.get())
+  if (!params.get()) {
     return false;
+  }
   // Verify param: model; type: refptr_diff
   DCHECK(model.get());
-  if (!model.get())
+  if (!model.get()) {
     return false;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->run_context_menu(
@@ -116,23 +128,27 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_context_menu_command))
+  if (CEF_MEMBER_MISSING(_struct, on_context_menu_command)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return false;
+  }
   // Verify param: params; type: refptr_diff
   DCHECK(params.get());
-  if (!params.get())
+  if (!params.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->on_context_menu_command(
@@ -150,25 +166,135 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_context_menu_dismissed))
+  if (CEF_MEMBER_MISSING(_struct, on_context_menu_dismissed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return;
+  }
 
   // Execute
   _struct->on_context_menu_dismissed(_struct, CefBrowserCppToC::Wrap(browser),
                                      CefFrameCppToC::Wrap(frame));
 }
 
+NO_SANITIZE("cfi-icall")
+bool CefContextMenuHandlerCToCpp::RunQuickMenu(
+    CefRefPtr<CefBrowser> browser,
+    CefRefPtr<CefFrame> frame,
+    const CefPoint& location,
+    const CefSize& size,
+    QuickMenuEditStateFlags edit_state_flags,
+    CefRefPtr<CefRunQuickMenuCallback> callback) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_context_menu_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, run_quick_menu)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return false;
+  }
+  // Verify param: frame; type: refptr_diff
+  DCHECK(frame.get());
+  if (!frame.get()) {
+    return false;
+  }
+  // Verify param: callback; type: refptr_diff
+  DCHECK(callback.get());
+  if (!callback.get()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->run_quick_menu(
+      _struct, CefBrowserCppToC::Wrap(browser), CefFrameCppToC::Wrap(frame),
+      &location, &size, edit_state_flags,
+      CefRunQuickMenuCallbackCppToC::Wrap(callback));
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefContextMenuHandlerCToCpp::OnQuickMenuCommand(
+    CefRefPtr<CefBrowser> browser,
+    CefRefPtr<CefFrame> frame,
+    int command_id,
+    EventFlags event_flags) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_context_menu_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_quick_menu_command)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return false;
+  }
+  // Verify param: frame; type: refptr_diff
+  DCHECK(frame.get());
+  if (!frame.get()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->on_quick_menu_command(
+      _struct, CefBrowserCppToC::Wrap(browser), CefFrameCppToC::Wrap(frame),
+      command_id, event_flags);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+void CefContextMenuHandlerCToCpp::OnQuickMenuDismissed(
+    CefRefPtr<CefBrowser> browser,
+    CefRefPtr<CefFrame> frame) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_context_menu_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_quick_menu_dismissed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return;
+  }
+  // Verify param: frame; type: refptr_diff
+  DCHECK(frame.get());
+  if (!frame.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_quick_menu_dismissed(_struct, CefBrowserCppToC::Wrap(browser),
+                                   CefFrameCppToC::Wrap(frame));
+}
+
 // CONSTRUCTOR - Do not edit by hand.
 
 CefContextMenuHandlerCToCpp::CefContextMenuHandlerCToCpp() {}
@@ -185,7 +311,7 @@
     CefContextMenuHandler,
     cef_context_menu_handler_t>::UnwrapDerived(CefWrapperType type,
                                                CefContextMenuHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/context_menu_handler_ctocpp.h b/src/libcef_dll/ctocpp/context_menu_handler_ctocpp.h
index 6129ea7..852d36c 100644
--- a/src/libcef_dll/ctocpp/context_menu_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/context_menu_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=11042b06316a1448f4f597941d059fc12bf5d7ca$
+// $hash=200acf8c2308059416e4f920d66bb98c6f234ffe$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_CONTEXT_MENU_HANDLER_CTOCPP_H_
@@ -51,6 +51,18 @@
                             EventFlags event_flags) override;
   void OnContextMenuDismissed(CefRefPtr<CefBrowser> browser,
                               CefRefPtr<CefFrame> frame) override;
+  bool RunQuickMenu(CefRefPtr<CefBrowser> browser,
+                    CefRefPtr<CefFrame> frame,
+                    const CefPoint& location,
+                    const CefSize& size,
+                    QuickMenuEditStateFlags edit_state_flags,
+                    CefRefPtr<CefRunQuickMenuCallback> callback) override;
+  bool OnQuickMenuCommand(CefRefPtr<CefBrowser> browser,
+                          CefRefPtr<CefFrame> frame,
+                          int command_id,
+                          EventFlags event_flags) override;
+  void OnQuickMenuDismissed(CefRefPtr<CefBrowser> browser,
+                            CefRefPtr<CefFrame> frame) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_CONTEXT_MENU_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/context_menu_params_ctocpp.cc b/src/libcef_dll/ctocpp/context_menu_params_ctocpp.cc
index 407702a..efc2cea 100644
--- a/src/libcef_dll/ctocpp/context_menu_params_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/context_menu_params_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7a5343c03a9b84f8831be8b9c7e5d2f35c62983c$
+// $hash=75967117879bf3ecf86bc170fa5161fc00ab236b$
 //
 
 #include "libcef_dll/ctocpp/context_menu_params_ctocpp.h"
@@ -22,8 +22,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_xcoord))
+  if (CEF_MEMBER_MISSING(_struct, get_xcoord)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -38,8 +39,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_ycoord))
+  if (CEF_MEMBER_MISSING(_struct, get_ycoord)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -55,8 +57,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_type_flags))
+  if (CEF_MEMBER_MISSING(_struct, get_type_flags)) {
     return CM_TYPEFLAG_NONE;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -71,8 +74,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_link_url))
+  if (CEF_MEMBER_MISSING(_struct, get_link_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -90,8 +94,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_unfiltered_link_url))
+  if (CEF_MEMBER_MISSING(_struct, get_unfiltered_link_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -108,8 +113,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_source_url))
+  if (CEF_MEMBER_MISSING(_struct, get_source_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -126,8 +132,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_image_contents))
+  if (CEF_MEMBER_MISSING(_struct, has_image_contents)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -142,8 +149,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_title_text))
+  if (CEF_MEMBER_MISSING(_struct, get_title_text)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -160,8 +168,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_page_url))
+  if (CEF_MEMBER_MISSING(_struct, get_page_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -178,8 +187,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_frame_url))
+  if (CEF_MEMBER_MISSING(_struct, get_frame_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -197,8 +207,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_frame_charset))
+  if (CEF_MEMBER_MISSING(_struct, get_frame_charset)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -216,8 +227,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_media_type))
+  if (CEF_MEMBER_MISSING(_struct, get_media_type)) {
     return CM_MEDIATYPE_NONE;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -234,8 +246,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_media_state_flags))
+  if (CEF_MEMBER_MISSING(_struct, get_media_state_flags)) {
     return CM_MEDIAFLAG_NONE;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -252,8 +265,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_selection_text))
+  if (CEF_MEMBER_MISSING(_struct, get_selection_text)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -271,8 +285,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_misspelled_word))
+  if (CEF_MEMBER_MISSING(_struct, get_misspelled_word)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -291,16 +306,18 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_dictionary_suggestions))
+  if (CEF_MEMBER_MISSING(_struct, get_dictionary_suggestions)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: suggestions; type: string_vec_byref
   cef_string_list_t suggestionsList = cef_string_list_alloc();
   DCHECK(suggestionsList);
-  if (suggestionsList)
+  if (suggestionsList) {
     transfer_string_list_contents(suggestions, suggestionsList);
+  }
 
   // Execute
   int _retval = _struct->get_dictionary_suggestions(_struct, suggestionsList);
@@ -320,8 +337,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_editable))
+  if (CEF_MEMBER_MISSING(_struct, is_editable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -337,8 +355,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_spell_check_enabled))
+  if (CEF_MEMBER_MISSING(_struct, is_spell_check_enabled)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -355,8 +374,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_edit_state_flags))
+  if (CEF_MEMBER_MISSING(_struct, get_edit_state_flags)) {
     return CM_EDITFLAG_NONE;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -372,8 +392,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_custom_menu))
+  if (CEF_MEMBER_MISSING(_struct, is_custom_menu)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -384,22 +405,6 @@
   return _retval ? true : false;
 }
 
-NO_SANITIZE("cfi-icall") bool CefContextMenuParamsCToCpp::IsPepperMenu() {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_context_menu_params_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_pepper_menu))
-    return false;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  int _retval = _struct->is_pepper_menu(_struct);
-
-  // Return type: bool
-  return _retval ? true : false;
-}
-
 // CONSTRUCTOR - Do not edit by hand.
 
 CefContextMenuParamsCToCpp::CefContextMenuParamsCToCpp() {}
@@ -416,7 +421,7 @@
     CefContextMenuParams,
     cef_context_menu_params_t>::UnwrapDerived(CefWrapperType type,
                                               CefContextMenuParams* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/context_menu_params_ctocpp.h b/src/libcef_dll/ctocpp/context_menu_params_ctocpp.h
index dca52b9..e800861 100644
--- a/src/libcef_dll/ctocpp/context_menu_params_ctocpp.h
+++ b/src/libcef_dll/ctocpp/context_menu_params_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4f6f41aa30704aeb2d3dbb6b54d430ea3392bf29$
+// $hash=d4a3ee70f42b74bd849215f0f569d07164bf29a7$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_CONTEXT_MENU_PARAMS_CTOCPP_H_
@@ -36,27 +36,26 @@
   virtual ~CefContextMenuParamsCToCpp();
 
   // CefContextMenuParams methods.
-  int GetXCoord() OVERRIDE;
-  int GetYCoord() OVERRIDE;
-  TypeFlags GetTypeFlags() OVERRIDE;
-  CefString GetLinkUrl() OVERRIDE;
-  CefString GetUnfilteredLinkUrl() OVERRIDE;
-  CefString GetSourceUrl() OVERRIDE;
-  bool HasImageContents() OVERRIDE;
-  CefString GetTitleText() OVERRIDE;
-  CefString GetPageUrl() OVERRIDE;
-  CefString GetFrameUrl() OVERRIDE;
-  CefString GetFrameCharset() OVERRIDE;
-  MediaType GetMediaType() OVERRIDE;
-  MediaStateFlags GetMediaStateFlags() OVERRIDE;
-  CefString GetSelectionText() OVERRIDE;
-  CefString GetMisspelledWord() OVERRIDE;
-  bool GetDictionarySuggestions(std::vector<CefString>& suggestions) OVERRIDE;
-  bool IsEditable() OVERRIDE;
-  bool IsSpellCheckEnabled() OVERRIDE;
-  EditStateFlags GetEditStateFlags() OVERRIDE;
-  bool IsCustomMenu() OVERRIDE;
-  bool IsPepperMenu() OVERRIDE;
+  int GetXCoord() override;
+  int GetYCoord() override;
+  TypeFlags GetTypeFlags() override;
+  CefString GetLinkUrl() override;
+  CefString GetUnfilteredLinkUrl() override;
+  CefString GetSourceUrl() override;
+  bool HasImageContents() override;
+  CefString GetTitleText() override;
+  CefString GetPageUrl() override;
+  CefString GetFrameUrl() override;
+  CefString GetFrameCharset() override;
+  MediaType GetMediaType() override;
+  MediaStateFlags GetMediaStateFlags() override;
+  CefString GetSelectionText() override;
+  CefString GetMisspelledWord() override;
+  bool GetDictionarySuggestions(std::vector<CefString>& suggestions) override;
+  bool IsEditable() override;
+  bool IsSpellCheckEnabled() override;
+  EditStateFlags GetEditStateFlags() override;
+  bool IsCustomMenu() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_CONTEXT_MENU_PARAMS_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/cookie_access_filter_ctocpp.cc b/src/libcef_dll/ctocpp/cookie_access_filter_ctocpp.cc
index be1c709..c1fc161 100644
--- a/src/libcef_dll/ctocpp/cookie_access_filter_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/cookie_access_filter_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=18ad9a46ee3ff980745b796013de06379659f611$
+// $hash=2982f6957159b86ce039dfe9e67726a30bb98636$
 //
 
 #include "libcef_dll/ctocpp/cookie_access_filter_ctocpp.h"
@@ -26,15 +26,17 @@
                                                 CefRefPtr<CefRequest> request,
                                                 const CefCookie& cookie) {
   cef_cookie_access_filter_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, can_send_cookie))
+  if (CEF_MEMBER_MISSING(_struct, can_send_cookie)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return false;
+  }
   // Unverified params: browser, frame
 
   // Execute
@@ -53,19 +55,22 @@
                                                 CefRefPtr<CefResponse> response,
                                                 const CefCookie& cookie) {
   cef_cookie_access_filter_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, can_save_cookie))
+  if (CEF_MEMBER_MISSING(_struct, can_save_cookie)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return false;
+  }
   // Verify param: response; type: refptr_diff
   DCHECK(response.get());
-  if (!response.get())
+  if (!response.get()) {
     return false;
+  }
   // Unverified params: browser, frame
 
   // Execute
@@ -92,7 +97,7 @@
     CefCookieAccessFilter,
     cef_cookie_access_filter_t>::UnwrapDerived(CefWrapperType type,
                                                CefCookieAccessFilter* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/cookie_access_filter_ctocpp.h b/src/libcef_dll/ctocpp/cookie_access_filter_ctocpp.h
index 3f815a2..0da8312 100644
--- a/src/libcef_dll/ctocpp/cookie_access_filter_ctocpp.h
+++ b/src/libcef_dll/ctocpp/cookie_access_filter_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=00521e32f472f47ba28a758e51d522f3f50f4db3$
+// $hash=b325a81a438e8e510eb826bc4e6acf5df04281c8$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_COOKIE_ACCESS_FILTER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/cookie_manager_ctocpp.cc b/src/libcef_dll/ctocpp/cookie_manager_ctocpp.cc
index 1b7cd53..5eea1e9 100644
--- a/src/libcef_dll/ctocpp/cookie_manager_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/cookie_manager_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ce618780672b92c6a5f4468b24bdf6c15abe7a82$
+// $hash=18732d77c6a843954449ea97aa26f0ce0b7a776a$
 //
 
 #include "libcef_dll/ctocpp/cookie_manager_ctocpp.h"
@@ -17,7 +17,6 @@
 #include "libcef_dll/cpptoc/cookie_visitor_cpptoc.h"
 #include "libcef_dll/cpptoc/delete_cookies_callback_cpptoc.h"
 #include "libcef_dll/cpptoc/set_cookie_callback_cpptoc.h"
-#include "libcef_dll/transfer_util.h"
 
 // STATIC METHODS - Body may be edited by hand.
 
@@ -39,46 +38,20 @@
 // VIRTUAL METHODS - Body may be edited by hand.
 
 NO_SANITIZE("cfi-icall")
-void CefCookieManagerCToCpp::SetSupportedSchemes(
-    const std::vector<CefString>& schemes,
-    bool include_defaults,
-    CefRefPtr<CefCompletionCallback> callback) {
-  cef_cookie_manager_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_supported_schemes))
-    return;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Unverified params: callback
-
-  // Translate param: schemes; type: string_vec_byref_const
-  cef_string_list_t schemesList = cef_string_list_alloc();
-  DCHECK(schemesList);
-  if (schemesList)
-    transfer_string_list_contents(schemes, schemesList);
-
-  // Execute
-  _struct->set_supported_schemes(_struct, schemesList, include_defaults,
-                                 CefCompletionCallbackCppToC::Wrap(callback));
-
-  // Restore param:schemes; type: string_vec_byref_const
-  if (schemesList)
-    cef_string_list_free(schemesList);
-}
-
-NO_SANITIZE("cfi-icall")
 bool CefCookieManagerCToCpp::VisitAllCookies(
     CefRefPtr<CefCookieVisitor> visitor) {
   cef_cookie_manager_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, visit_all_cookies))
+  if (CEF_MEMBER_MISSING(_struct, visit_all_cookies)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: visitor; type: refptr_diff
   DCHECK(visitor.get());
-  if (!visitor.get())
+  if (!visitor.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->visit_all_cookies(
@@ -94,19 +67,22 @@
     bool includeHttpOnly,
     CefRefPtr<CefCookieVisitor> visitor) {
   cef_cookie_manager_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, visit_url_cookies))
+  if (CEF_MEMBER_MISSING(_struct, visit_url_cookies)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: url; type: string_byref_const
   DCHECK(!url.empty());
-  if (url.empty())
+  if (url.empty()) {
     return false;
+  }
   // Verify param: visitor; type: refptr_diff
   DCHECK(visitor.get());
-  if (!visitor.get())
+  if (!visitor.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -123,15 +99,17 @@
     const CefCookie& cookie,
     CefRefPtr<CefSetCookieCallback> callback) {
   cef_cookie_manager_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_cookie))
+  if (CEF_MEMBER_MISSING(_struct, set_cookie)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: url; type: string_byref_const
   DCHECK(!url.empty());
-  if (url.empty())
+  if (url.empty()) {
     return false;
+  }
   // Unverified params: callback
 
   // Execute
@@ -148,8 +126,9 @@
     const CefString& cookie_name,
     CefRefPtr<CefDeleteCookiesCallback> callback) {
   cef_cookie_manager_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, delete_cookies))
+  if (CEF_MEMBER_MISSING(_struct, delete_cookies)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -168,8 +147,9 @@
 bool CefCookieManagerCToCpp::FlushStore(
     CefRefPtr<CefCompletionCallback> callback) {
   cef_cookie_manager_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, flush_store))
+  if (CEF_MEMBER_MISSING(_struct, flush_store)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -197,7 +177,7 @@
                     CefCookieManager,
                     cef_cookie_manager_t>::UnwrapDerived(CefWrapperType type,
                                                          CefCookieManager* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/cookie_manager_ctocpp.h b/src/libcef_dll/ctocpp/cookie_manager_ctocpp.h
index cea787f..418fd7d 100644
--- a/src/libcef_dll/ctocpp/cookie_manager_ctocpp.h
+++ b/src/libcef_dll/ctocpp/cookie_manager_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=cc4a6a350ccd9d68869efae79a4d5717169e2ff8$
+// $hash=47bcf17fac9734852100b8e44bbead84b4ef78dc$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_COOKIE_MANAGER_CTOCPP_H_
@@ -20,7 +20,6 @@
 #error This file can be included wrapper-side only
 #endif
 
-#include <vector>
 #include "include/capi/cef_cookie_capi.h"
 #include "include/cef_cookie.h"
 #include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
@@ -36,20 +35,17 @@
   virtual ~CefCookieManagerCToCpp();
 
   // CefCookieManager methods.
-  void SetSupportedSchemes(const std::vector<CefString>& schemes,
-                           bool include_defaults,
-                           CefRefPtr<CefCompletionCallback> callback) OVERRIDE;
-  bool VisitAllCookies(CefRefPtr<CefCookieVisitor> visitor) OVERRIDE;
+  bool VisitAllCookies(CefRefPtr<CefCookieVisitor> visitor) override;
   bool VisitUrlCookies(const CefString& url,
                        bool includeHttpOnly,
-                       CefRefPtr<CefCookieVisitor> visitor) OVERRIDE;
+                       CefRefPtr<CefCookieVisitor> visitor) override;
   bool SetCookie(const CefString& url,
                  const CefCookie& cookie,
-                 CefRefPtr<CefSetCookieCallback> callback) OVERRIDE;
+                 CefRefPtr<CefSetCookieCallback> callback) override;
   bool DeleteCookies(const CefString& url,
                      const CefString& cookie_name,
-                     CefRefPtr<CefDeleteCookiesCallback> callback) OVERRIDE;
-  bool FlushStore(CefRefPtr<CefCompletionCallback> callback) OVERRIDE;
+                     CefRefPtr<CefDeleteCookiesCallback> callback) override;
+  bool FlushStore(CefRefPtr<CefCompletionCallback> callback) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_COOKIE_MANAGER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/cookie_visitor_ctocpp.cc b/src/libcef_dll/ctocpp/cookie_visitor_ctocpp.cc
index 41bb066..28e5543 100644
--- a/src/libcef_dll/ctocpp/cookie_visitor_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/cookie_visitor_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2fb5cbc3fb182cdc5548139ca7256916148984d7$
+// $hash=aec8ab7d90938c62b52faa199823912b3cbc0b11$
 //
 
 #include "libcef_dll/ctocpp/cookie_visitor_ctocpp.h"
@@ -25,8 +25,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_cookie_visitor_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, visit))
+  if (CEF_MEMBER_MISSING(_struct, visit)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -60,7 +61,7 @@
                     CefCookieVisitor,
                     cef_cookie_visitor_t>::UnwrapDerived(CefWrapperType type,
                                                          CefCookieVisitor* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/cookie_visitor_ctocpp.h b/src/libcef_dll/ctocpp/cookie_visitor_ctocpp.h
index d49a42a..cfc8498 100644
--- a/src/libcef_dll/ctocpp/cookie_visitor_ctocpp.h
+++ b/src/libcef_dll/ctocpp/cookie_visitor_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6eb302aca9a6178b9418310105104f079830f4a0$
+// $hash=70fdf3c9319fd0ca0c0653ded314d645f8f39dfb$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_COOKIE_VISITOR_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/ctocpp_ref_counted.h b/src/libcef_dll/ctocpp/ctocpp_ref_counted.h
index 91260f5..429d246 100644
--- a/src/libcef_dll/ctocpp/ctocpp_ref_counted.h
+++ b/src/libcef_dll/ctocpp/ctocpp_ref_counted.h
@@ -7,7 +7,6 @@
 #pragma once
 
 #include "include/base/cef_logging.h"
-#include "include/base/cef_macros.h"
 #include "include/capi/cef_base_capi.h"
 #include "include/cef_base.h"
 #include "libcef_dll/wrapper_types.h"
@@ -18,6 +17,9 @@
 template <class ClassName, class BaseName, class StructName>
 class CefCToCppRefCounted : public BaseName {
  public:
+  CefCToCppRefCounted(const CefCToCppRefCounted&) = delete;
+  CefCToCppRefCounted& operator=(const CefCToCppRefCounted&) = delete;
+
   // Create a new wrapper instance for a structure reference received from the
   // other side.
   static CefRefPtr<BaseName> Wrap(StructName* s);
@@ -37,8 +39,8 @@
   bool HasAtLeastOneRef() const { return UnderlyingHasAtLeastOneRef(); }
 
  protected:
-  CefCToCppRefCounted() {}
-  virtual ~CefCToCppRefCounted() {}
+  CefCToCppRefCounted() = default;
+  virtual ~CefCToCppRefCounted() = default;
 
   // If returning the structure across the DLL boundary use Unwrap() instead.
   StructName* GetStruct() const {
@@ -63,16 +65,18 @@
   void UnderlyingAddRef() const {
     cef_base_ref_counted_t* base =
         reinterpret_cast<cef_base_ref_counted_t*>(GetStruct());
-    if (base->add_ref)
+    if (base->add_ref) {
       base->add_ref(base);
+    }
   }
 
   NO_SANITIZE("cfi-icall")
   bool UnderlyingRelease() const {
     cef_base_ref_counted_t* base =
         reinterpret_cast<cef_base_ref_counted_t*>(GetStruct());
-    if (!base->release)
+    if (!base->release) {
       return false;
+    }
     return base->release(base) ? true : false;
   }
 
@@ -80,8 +84,9 @@
   bool UnderlyingHasOneRef() const {
     cef_base_ref_counted_t* base =
         reinterpret_cast<cef_base_ref_counted_t*>(GetStruct());
-    if (!base->has_one_ref)
+    if (!base->has_one_ref) {
       return false;
+    }
     return base->has_one_ref(base) ? true : false;
   }
 
@@ -89,16 +94,15 @@
   bool UnderlyingHasAtLeastOneRef() const {
     cef_base_ref_counted_t* base =
         reinterpret_cast<cef_base_ref_counted_t*>(GetStruct());
-    if (!base->has_one_ref)
+    if (!base->has_at_least_one_ref) {
       return false;
+    }
     return base->has_at_least_one_ref(base) ? true : false;
   }
 
   CefRefCount ref_count_;
 
   static CefWrapperType kWrapperType;
-
-  DISALLOW_COPY_AND_ASSIGN(CefCToCppRefCounted);
 };
 
 template <class ClassName, class BaseName, class StructName>
@@ -111,8 +115,9 @@
 template <class ClassName, class BaseName, class StructName>
 CefRefPtr<BaseName> CefCToCppRefCounted<ClassName, BaseName, StructName>::Wrap(
     StructName* s) {
-  if (!s)
+  if (!s) {
     return nullptr;
+  }
 
   // Wrap their structure with the CefCToCppRefCounted object.
   WrapperStruct* wrapperStruct = new WrapperStruct;
@@ -131,15 +136,17 @@
 template <class ClassName, class BaseName, class StructName>
 StructName* CefCToCppRefCounted<ClassName, BaseName, StructName>::Unwrap(
     CefRefPtr<BaseName> c) {
-  if (!c.get())
+  if (!c.get()) {
     return nullptr;
+  }
 
   WrapperStruct* wrapperStruct = GetWrapperStruct(c.get());
 
   // If the type does not match this object then we need to unwrap as the
   // derived type.
-  if (wrapperStruct->type_ != kWrapperType)
+  if (wrapperStruct->type_ != kWrapperType) {
     return UnwrapDerived(wrapperStruct->type_, c.get());
+  }
 
   // Add a reference to the CefCppToC wrapper object on the other side that
   // will be released once the structure is received.
diff --git a/src/libcef_dll/ctocpp/ctocpp_scoped.h b/src/libcef_dll/ctocpp/ctocpp_scoped.h
index 5ceddcb..be1bb84 100644
--- a/src/libcef_dll/ctocpp/ctocpp_scoped.h
+++ b/src/libcef_dll/ctocpp/ctocpp_scoped.h
@@ -7,10 +7,8 @@
 #pragma once
 
 #include "include/base/cef_logging.h"
-#include "include/base/cef_macros.h"
 #include "include/capi/cef_base_capi.h"
 #include "include/cef_base.h"
-#include "libcef_dll/ptr_util.h"
 #include "libcef_dll/wrapper_types.h"
 
 // Wrap a C structure with a C++ class. This is used when the implementation
@@ -19,6 +17,9 @@
 template <class ClassName, class BaseName, class StructName>
 class CefCToCppScoped : public BaseName {
  public:
+  CefCToCppScoped(const CefCToCppScoped&) = delete;
+  CefCToCppScoped& operator=(const CefCToCppScoped&) = delete;
+
   // Create a new wrapper instance for a structure reference received from the
   // other side. The caller owns the CToCpp wrapper instance but not necessarily
   // the underling object on the CppToC side (depends if s->del is non-NULL).
@@ -49,7 +50,7 @@
   //
   // void MyMethod(CefOwnPtr<MyType> obj) {
   //   // Ownership of the underlying MyType object is passed to my_method().
-  //   my_method(MyTypeCToCpp::UnwrapOwn(obj.Pass()));
+  //   my_method(MyTypeCToCpp::UnwrapOwn(std::move(obj)));
   //   // |obj| is now NULL.
   // }
   static StructName* UnwrapOwn(CefOwnPtr<BaseName> c);
@@ -68,8 +69,8 @@
   static void operator delete(void* ptr);
 
  protected:
-  CefCToCppScoped() {}
-  virtual ~CefCToCppScoped() {}
+  CefCToCppScoped() = default;
+  virtual ~CefCToCppScoped() = default;
 
   // If returning the structure across the DLL boundary use Unwrap() instead.
   StructName* GetStruct() const {
@@ -93,8 +94,6 @@
                                       CefRawPtr<BaseName> c);
 
   static CefWrapperType kWrapperType;
-
-  DISALLOW_COPY_AND_ASSIGN(CefCToCppScoped);
 };
 
 template <class ClassName, class BaseName, class StructName>
@@ -107,8 +106,9 @@
 template <class ClassName, class BaseName, class StructName>
 CefOwnPtr<BaseName> CefCToCppScoped<ClassName, BaseName, StructName>::Wrap(
     StructName* s) {
-  if (!s)
+  if (!s) {
     return CefOwnPtr<BaseName>();
+  }
 
   // Wrap their structure with the CefCToCpp object.
   WrapperStruct* wrapperStruct = new WrapperStruct;
@@ -121,15 +121,17 @@
 template <class ClassName, class BaseName, class StructName>
 StructName* CefCToCppScoped<ClassName, BaseName, StructName>::UnwrapOwn(
     CefOwnPtr<BaseName> c) {
-  if (!c.get())
+  if (!c.get()) {
     return nullptr;
+  }
 
   WrapperStruct* wrapperStruct = GetWrapperStruct(c.get());
 
   // If the type does not match this object then we need to unwrap as the
   // derived type.
-  if (wrapperStruct->type_ != kWrapperType)
-    return UnwrapDerivedOwn(wrapperStruct->type_, OWN_PASS(c));
+  if (wrapperStruct->type_ != kWrapperType) {
+    return UnwrapDerivedOwn(wrapperStruct->type_, std::move(c));
+  }
 
   StructName* orig_struct = wrapperStruct->struct_;
 
@@ -150,15 +152,17 @@
 template <class ClassName, class BaseName, class StructName>
 StructName* CefCToCppScoped<ClassName, BaseName, StructName>::UnwrapRaw(
     CefRawPtr<BaseName> c) {
-  if (!c)
+  if (!c) {
     return nullptr;
+  }
 
   WrapperStruct* wrapperStruct = GetWrapperStruct(c);
 
   // If the type does not match this object then we need to unwrap as the
   // derived type.
-  if (wrapperStruct->type_ != kWrapperType)
+  if (wrapperStruct->type_ != kWrapperType) {
     return UnwrapDerivedRaw(wrapperStruct->type_, c);
+  }
 
   // Return the original structure.
   return wrapperStruct->struct_;
@@ -178,8 +182,9 @@
 
   // If we own the object (base->del != NULL) then notify the other side that
   // the object has been deleted.
-  if (base && base->del)
+  if (base && base->del) {
     base->del(base);
+  }
 
   // Delete the wrapper structure without executing ~CefCToCppScoped() an
   // additional time.
diff --git a/src/libcef_dll/ctocpp/delete_cookies_callback_ctocpp.cc b/src/libcef_dll/ctocpp/delete_cookies_callback_ctocpp.cc
index fc7c5a8..51ab2d3 100644
--- a/src/libcef_dll/ctocpp/delete_cookies_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/delete_cookies_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c9c0bf488733d065951d9c989e622fedb67536a0$
+// $hash=26d697d88a0312f47a3fe212b4c77cdb4e8b5800$
 //
 
 #include "libcef_dll/ctocpp/delete_cookies_callback_ctocpp.h"
@@ -22,8 +22,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_delete_cookies_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_complete))
+  if (CEF_MEMBER_MISSING(_struct, on_complete)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -47,7 +48,7 @@
     CefDeleteCookiesCallback,
     cef_delete_cookies_callback_t>::UnwrapDerived(CefWrapperType type,
                                                   CefDeleteCookiesCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/delete_cookies_callback_ctocpp.h b/src/libcef_dll/ctocpp/delete_cookies_callback_ctocpp.h
index 2544804..7e7bdaf 100644
--- a/src/libcef_dll/ctocpp/delete_cookies_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/delete_cookies_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=5548d59ccea5a28af2db242115214b3226b9fb03$
+// $hash=e064baa776ef2fb9b70d51ec556613859a222067$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_DELETE_COOKIES_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/dev_tools_message_observer_ctocpp.cc b/src/libcef_dll/ctocpp/dev_tools_message_observer_ctocpp.cc
index c3d6210..994ae24 100644
--- a/src/libcef_dll/ctocpp/dev_tools_message_observer_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/dev_tools_message_observer_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e8d1eaf4b8cdfd79a260de33fb3be05a2948c81e$
+// $hash=145f7445eb4094e268b6a135a61535fdd780507e$
 //
 
 #include "libcef_dll/ctocpp/dev_tools_message_observer_ctocpp.h"
@@ -26,19 +26,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dev_tools_message_observer_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_dev_tools_message))
+  if (CEF_MEMBER_MISSING(_struct, on_dev_tools_message)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: message; type: simple_byaddr
   DCHECK(message);
-  if (!message)
+  if (!message) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->on_dev_tools_message(
@@ -58,15 +61,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dev_tools_message_observer_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_dev_tools_method_result))
+  if (CEF_MEMBER_MISSING(_struct, on_dev_tools_method_result)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Unverified params: result
 
   // Execute
@@ -83,19 +88,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dev_tools_message_observer_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_dev_tools_event))
+  if (CEF_MEMBER_MISSING(_struct, on_dev_tools_event)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: method; type: string_byref_const
   DCHECK(!method.empty());
-  if (method.empty())
+  if (method.empty()) {
     return;
+  }
   // Unverified params: params
 
   // Execute
@@ -109,15 +117,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dev_tools_message_observer_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_dev_tools_agent_attached))
+  if (CEF_MEMBER_MISSING(_struct, on_dev_tools_agent_attached)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_dev_tools_agent_attached(_struct,
@@ -130,15 +140,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dev_tools_message_observer_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_dev_tools_agent_detached))
+  if (CEF_MEMBER_MISSING(_struct, on_dev_tools_agent_detached)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_dev_tools_agent_detached(_struct,
@@ -162,7 +174,7 @@
     cef_dev_tools_message_observer_t>::UnwrapDerived(CefWrapperType type,
                                                      CefDevToolsMessageObserver*
                                                          c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/dev_tools_message_observer_ctocpp.h b/src/libcef_dll/ctocpp/dev_tools_message_observer_ctocpp.h
index d793fa5..c328e21 100644
--- a/src/libcef_dll/ctocpp/dev_tools_message_observer_ctocpp.h
+++ b/src/libcef_dll/ctocpp/dev_tools_message_observer_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=26b1ef9d351b0ce4a7ca0d61c53a8374ba21168b$
+// $hash=13f5ab113bea9ee958f3d92e1c10898fd182c14e$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_DEV_TOOLS_MESSAGE_OBSERVER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/dialog_handler_ctocpp.cc b/src/libcef_dll/ctocpp/dialog_handler_ctocpp.cc
index facff52..f4072f3 100644
--- a/src/libcef_dll/ctocpp/dialog_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/dialog_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ad47bb8d870deaf5d51606f6c2bce0105eccdd4b$
+// $hash=51a99f5889f00d4074a7e975ec95b889f1bd55d8$
 //
 
 #include "libcef_dll/ctocpp/dialog_handler_ctocpp.h"
@@ -27,45 +27,45 @@
     const CefString& title,
     const CefString& default_file_path,
     const std::vector<CefString>& accept_filters,
-    int selected_accept_filter,
     CefRefPtr<CefFileDialogCallback> callback) {
   shutdown_checker::AssertNotShutdown();
 
   cef_dialog_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_file_dialog))
+  if (CEF_MEMBER_MISSING(_struct, on_file_dialog)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
-  // Verify param: selected_accept_filter; type: simple_byval
-  DCHECK_GE(selected_accept_filter, 0);
-  if (selected_accept_filter < 0)
-    return false;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return false;
+  }
   // Unverified params: title, default_file_path, accept_filters
 
   // Translate param: accept_filters; type: string_vec_byref_const
   cef_string_list_t accept_filtersList = cef_string_list_alloc();
   DCHECK(accept_filtersList);
-  if (accept_filtersList)
+  if (accept_filtersList) {
     transfer_string_list_contents(accept_filters, accept_filtersList);
+  }
 
   // Execute
   int _retval = _struct->on_file_dialog(
       _struct, CefBrowserCppToC::Wrap(browser), mode, title.GetStruct(),
-      default_file_path.GetStruct(), accept_filtersList, selected_accept_filter,
+      default_file_path.GetStruct(), accept_filtersList,
       CefFileDialogCallbackCppToC::Wrap(callback));
 
   // Restore param:accept_filters; type: string_vec_byref_const
-  if (accept_filtersList)
+  if (accept_filtersList) {
     cef_string_list_free(accept_filtersList);
+  }
 
   // Return type: bool
   return _retval ? true : false;
@@ -87,7 +87,7 @@
                     CefDialogHandler,
                     cef_dialog_handler_t>::UnwrapDerived(CefWrapperType type,
                                                          CefDialogHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/dialog_handler_ctocpp.h b/src/libcef_dll/ctocpp/dialog_handler_ctocpp.h
index 668f432..32be4bc 100644
--- a/src/libcef_dll/ctocpp/dialog_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/dialog_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=85f21f598361819e2a463b94edd5e31dcc5b2648$
+// $hash=32bf297fed4117e7a49ec5286fa05a51b2bf106b$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_DIALOG_HANDLER_CTOCPP_H_
@@ -41,7 +41,6 @@
                     const CefString& title,
                     const CefString& default_file_path,
                     const std::vector<CefString>& accept_filters,
-                    int selected_accept_filter,
                     CefRefPtr<CefFileDialogCallback> callback) override;
 };
 
diff --git a/src/libcef_dll/ctocpp/dictionary_value_ctocpp.cc b/src/libcef_dll/ctocpp/dictionary_value_ctocpp.cc
index 9259984..1937d21 100644
--- a/src/libcef_dll/ctocpp/dictionary_value_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/dictionary_value_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e7dcf32d390886ac5690380fbf034c8daadec891$
+// $hash=21357f7bdec9fe05f50147f4605572ed795e6bcc$
 //
 
 #include "libcef_dll/ctocpp/dictionary_value_ctocpp.h"
@@ -40,8 +40,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -56,8 +57,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_owned))
+  if (CEF_MEMBER_MISSING(_struct, is_owned)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -72,8 +74,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_read_only))
+  if (CEF_MEMBER_MISSING(_struct, is_read_only)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -89,15 +92,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -112,15 +117,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_equal))
+  if (CEF_MEMBER_MISSING(_struct, is_equal)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -136,8 +143,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, copy))
+  if (CEF_MEMBER_MISSING(_struct, copy)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -153,8 +161,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_size))
+  if (CEF_MEMBER_MISSING(_struct, get_size)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -169,8 +178,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, clear))
+  if (CEF_MEMBER_MISSING(_struct, clear)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -186,15 +196,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_key))
+  if (CEF_MEMBER_MISSING(_struct, has_key)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->has_key(_struct, key.GetStruct());
@@ -207,16 +219,18 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_keys))
+  if (CEF_MEMBER_MISSING(_struct, get_keys)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: keys; type: string_vec_byref
   cef_string_list_t keysList = cef_string_list_alloc();
   DCHECK(keysList);
-  if (keysList)
+  if (keysList) {
     transfer_string_list_contents(keys, keysList);
+  }
 
   // Execute
   int _retval = _struct->get_keys(_struct, keysList);
@@ -237,15 +251,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, remove))
+  if (CEF_MEMBER_MISSING(_struct, remove)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->remove(_struct, key.GetStruct());
@@ -259,15 +275,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_type))
+  if (CEF_MEMBER_MISSING(_struct, get_type)) {
     return VTYPE_INVALID;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return VTYPE_INVALID;
+  }
 
   // Execute
   cef_value_type_t _retval = _struct->get_type(_struct, key.GetStruct());
@@ -281,15 +299,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_value))
+  if (CEF_MEMBER_MISSING(_struct, get_value)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return nullptr;
+  }
 
   // Execute
   cef_value_t* _retval = _struct->get_value(_struct, key.GetStruct());
@@ -303,15 +323,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_bool))
+  if (CEF_MEMBER_MISSING(_struct, get_bool)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->get_bool(_struct, key.GetStruct());
@@ -325,15 +347,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_int))
+  if (CEF_MEMBER_MISSING(_struct, get_int)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return 0;
+  }
 
   // Execute
   int _retval = _struct->get_int(_struct, key.GetStruct());
@@ -347,15 +371,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_double))
+  if (CEF_MEMBER_MISSING(_struct, get_double)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return 0;
+  }
 
   // Execute
   double _retval = _struct->get_double(_struct, key.GetStruct());
@@ -369,15 +395,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_string))
+  if (CEF_MEMBER_MISSING(_struct, get_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return CefString();
+  }
 
   // Execute
   cef_string_userfree_t _retval = _struct->get_string(_struct, key.GetStruct());
@@ -394,15 +422,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_binary))
+  if (CEF_MEMBER_MISSING(_struct, get_binary)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return nullptr;
+  }
 
   // Execute
   cef_binary_value_t* _retval = _struct->get_binary(_struct, key.GetStruct());
@@ -417,15 +447,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_dictionary))
+  if (CEF_MEMBER_MISSING(_struct, get_dictionary)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return nullptr;
+  }
 
   // Execute
   cef_dictionary_value_t* _retval =
@@ -441,15 +473,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_list))
+  if (CEF_MEMBER_MISSING(_struct, get_list)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return nullptr;
+  }
 
   // Execute
   cef_list_value_t* _retval = _struct->get_list(_struct, key.GetStruct());
@@ -464,19 +498,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_value))
+  if (CEF_MEMBER_MISSING(_struct, set_value)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return false;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_value(_struct, key.GetStruct(),
@@ -491,15 +528,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_null))
+  if (CEF_MEMBER_MISSING(_struct, set_null)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_null(_struct, key.GetStruct());
@@ -513,15 +552,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_bool))
+  if (CEF_MEMBER_MISSING(_struct, set_bool)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_bool(_struct, key.GetStruct(), value);
@@ -535,15 +576,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_int))
+  if (CEF_MEMBER_MISSING(_struct, set_int)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_int(_struct, key.GetStruct(), value);
@@ -557,15 +600,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_double))
+  if (CEF_MEMBER_MISSING(_struct, set_double)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_double(_struct, key.GetStruct(), value);
@@ -580,15 +625,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_string))
+  if (CEF_MEMBER_MISSING(_struct, set_string)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return false;
+  }
   // Unverified params: value
 
   // Execute
@@ -605,19 +652,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_binary))
+  if (CEF_MEMBER_MISSING(_struct, set_binary)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return false;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_binary(_struct, key.GetStruct(),
@@ -634,19 +684,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_dictionary))
+  if (CEF_MEMBER_MISSING(_struct, set_dictionary)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return false;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_dictionary(
@@ -662,19 +715,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_dictionary_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_list))
+  if (CEF_MEMBER_MISSING(_struct, set_list)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return false;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_list(_struct, key.GetStruct(),
@@ -700,7 +756,7 @@
     CefDictionaryValue,
     cef_dictionary_value_t>::UnwrapDerived(CefWrapperType type,
                                            CefDictionaryValue* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/dictionary_value_ctocpp.h b/src/libcef_dll/ctocpp/dictionary_value_ctocpp.h
index b1db791..ba9843f 100644
--- a/src/libcef_dll/ctocpp/dictionary_value_ctocpp.h
+++ b/src/libcef_dll/ctocpp/dictionary_value_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3bb1b095b2bb4e2030635f4ef3000eb8949dfbe1$
+// $hash=68a7aff9f01e57edaeaa53bfbbc4c6121ebb3a1b$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_DICTIONARY_VALUE_CTOCPP_H_
@@ -35,37 +35,37 @@
   virtual ~CefDictionaryValueCToCpp();
 
   // CefDictionaryValue methods.
-  bool IsValid() OVERRIDE;
-  bool IsOwned() OVERRIDE;
-  bool IsReadOnly() OVERRIDE;
-  bool IsSame(CefRefPtr<CefDictionaryValue> that) OVERRIDE;
-  bool IsEqual(CefRefPtr<CefDictionaryValue> that) OVERRIDE;
-  CefRefPtr<CefDictionaryValue> Copy(bool exclude_empty_children) OVERRIDE;
-  size_t GetSize() OVERRIDE;
-  bool Clear() OVERRIDE;
-  bool HasKey(const CefString& key) OVERRIDE;
-  bool GetKeys(KeyList& keys) OVERRIDE;
-  bool Remove(const CefString& key) OVERRIDE;
-  CefValueType GetType(const CefString& key) OVERRIDE;
-  CefRefPtr<CefValue> GetValue(const CefString& key) OVERRIDE;
-  bool GetBool(const CefString& key) OVERRIDE;
-  int GetInt(const CefString& key) OVERRIDE;
-  double GetDouble(const CefString& key) OVERRIDE;
-  CefString GetString(const CefString& key) OVERRIDE;
-  CefRefPtr<CefBinaryValue> GetBinary(const CefString& key) OVERRIDE;
-  CefRefPtr<CefDictionaryValue> GetDictionary(const CefString& key) OVERRIDE;
-  CefRefPtr<CefListValue> GetList(const CefString& key) OVERRIDE;
-  bool SetValue(const CefString& key, CefRefPtr<CefValue> value) OVERRIDE;
-  bool SetNull(const CefString& key) OVERRIDE;
-  bool SetBool(const CefString& key, bool value) OVERRIDE;
-  bool SetInt(const CefString& key, int value) OVERRIDE;
-  bool SetDouble(const CefString& key, double value) OVERRIDE;
-  bool SetString(const CefString& key, const CefString& value) OVERRIDE;
+  bool IsValid() override;
+  bool IsOwned() override;
+  bool IsReadOnly() override;
+  bool IsSame(CefRefPtr<CefDictionaryValue> that) override;
+  bool IsEqual(CefRefPtr<CefDictionaryValue> that) override;
+  CefRefPtr<CefDictionaryValue> Copy(bool exclude_empty_children) override;
+  size_t GetSize() override;
+  bool Clear() override;
+  bool HasKey(const CefString& key) override;
+  bool GetKeys(KeyList& keys) override;
+  bool Remove(const CefString& key) override;
+  CefValueType GetType(const CefString& key) override;
+  CefRefPtr<CefValue> GetValue(const CefString& key) override;
+  bool GetBool(const CefString& key) override;
+  int GetInt(const CefString& key) override;
+  double GetDouble(const CefString& key) override;
+  CefString GetString(const CefString& key) override;
+  CefRefPtr<CefBinaryValue> GetBinary(const CefString& key) override;
+  CefRefPtr<CefDictionaryValue> GetDictionary(const CefString& key) override;
+  CefRefPtr<CefListValue> GetList(const CefString& key) override;
+  bool SetValue(const CefString& key, CefRefPtr<CefValue> value) override;
+  bool SetNull(const CefString& key) override;
+  bool SetBool(const CefString& key, bool value) override;
+  bool SetInt(const CefString& key, int value) override;
+  bool SetDouble(const CefString& key, double value) override;
+  bool SetString(const CefString& key, const CefString& value) override;
   bool SetBinary(const CefString& key,
-                 CefRefPtr<CefBinaryValue> value) OVERRIDE;
+                 CefRefPtr<CefBinaryValue> value) override;
   bool SetDictionary(const CefString& key,
-                     CefRefPtr<CefDictionaryValue> value) OVERRIDE;
-  bool SetList(const CefString& key, CefRefPtr<CefListValue> value) OVERRIDE;
+                     CefRefPtr<CefDictionaryValue> value) override;
+  bool SetList(const CefString& key, CefRefPtr<CefListValue> value) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_DICTIONARY_VALUE_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/display_handler_ctocpp.cc b/src/libcef_dll/ctocpp/display_handler_ctocpp.cc
index 7139bb8..363fb7f 100644
--- a/src/libcef_dll/ctocpp/display_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/display_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=11c971f10c02ae341f62e70dca05528f78c8d1a2$
+// $hash=6715a3573be4b019dfe5e818d74d0979e081d839$
 //
 
 #include "libcef_dll/ctocpp/display_handler_ctocpp.h"
@@ -27,23 +27,27 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_display_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_address_change))
+  if (CEF_MEMBER_MISSING(_struct, on_address_change)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return;
+  }
   // Verify param: url; type: string_byref_const
   DCHECK(!url.empty());
-  if (url.empty())
+  if (url.empty()) {
     return;
+  }
 
   // Execute
   _struct->on_address_change(_struct, CefBrowserCppToC::Wrap(browser),
@@ -56,15 +60,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_display_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_title_change))
+  if (CEF_MEMBER_MISSING(_struct, on_title_change)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Unverified params: title
 
   // Execute
@@ -79,30 +85,34 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_display_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_favicon_urlchange))
+  if (CEF_MEMBER_MISSING(_struct, on_favicon_urlchange)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Unverified params: icon_urls
 
   // Translate param: icon_urls; type: string_vec_byref_const
   cef_string_list_t icon_urlsList = cef_string_list_alloc();
   DCHECK(icon_urlsList);
-  if (icon_urlsList)
+  if (icon_urlsList) {
     transfer_string_list_contents(icon_urls, icon_urlsList);
+  }
 
   // Execute
   _struct->on_favicon_urlchange(_struct, CefBrowserCppToC::Wrap(browser),
                                 icon_urlsList);
 
   // Restore param:icon_urls; type: string_vec_byref_const
-  if (icon_urlsList)
+  if (icon_urlsList) {
     cef_string_list_free(icon_urlsList);
+  }
 }
 
 NO_SANITIZE("cfi-icall")
@@ -112,15 +122,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_display_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_fullscreen_mode_change))
+  if (CEF_MEMBER_MISSING(_struct, on_fullscreen_mode_change)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_fullscreen_mode_change(_struct, CefBrowserCppToC::Wrap(browser),
@@ -133,15 +145,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_display_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_tooltip))
+  if (CEF_MEMBER_MISSING(_struct, on_tooltip)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Unverified params: text
 
   // Execute
@@ -158,15 +172,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_display_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_status_message))
+  if (CEF_MEMBER_MISSING(_struct, on_status_message)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Unverified params: value
 
   // Execute
@@ -183,15 +199,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_display_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_console_message))
+  if (CEF_MEMBER_MISSING(_struct, on_console_message)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Unverified params: message, source
 
   // Execute
@@ -209,15 +227,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_display_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_auto_resize))
+  if (CEF_MEMBER_MISSING(_struct, on_auto_resize)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->on_auto_resize(
@@ -234,21 +254,77 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_display_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_loading_progress_change))
+  if (CEF_MEMBER_MISSING(_struct, on_loading_progress_change)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_loading_progress_change(_struct, CefBrowserCppToC::Wrap(browser),
                                       progress);
 }
 
+NO_SANITIZE("cfi-icall")
+bool CefDisplayHandlerCToCpp::OnCursorChange(
+    CefRefPtr<CefBrowser> browser,
+    CefCursorHandle cursor,
+    cef_cursor_type_t type,
+    const CefCursorInfo& custom_cursor_info) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_display_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_cursor_change)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return false;
+  }
+
+  // Execute
+  int _retval =
+      _struct->on_cursor_change(_struct, CefBrowserCppToC::Wrap(browser),
+                                cursor, type, &custom_cursor_info);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+void CefDisplayHandlerCToCpp::OnMediaAccessChange(CefRefPtr<CefBrowser> browser,
+                                                  bool has_video_access,
+                                                  bool has_audio_access) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_display_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_media_access_change)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_media_access_change(_struct, CefBrowserCppToC::Wrap(browser),
+                                  has_video_access, has_audio_access);
+}
+
 // CONSTRUCTOR - Do not edit by hand.
 
 CefDisplayHandlerCToCpp::CefDisplayHandlerCToCpp() {}
@@ -265,7 +341,7 @@
     CefDisplayHandler,
     cef_display_handler_t>::UnwrapDerived(CefWrapperType type,
                                           CefDisplayHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/display_handler_ctocpp.h b/src/libcef_dll/ctocpp/display_handler_ctocpp.h
index 7bdd7a0..e896499 100644
--- a/src/libcef_dll/ctocpp/display_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/display_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2a5e7a2afb4d183e4688ef7aec8d12d2bc1d5212$
+// $hash=d45cff7bbeeb6398470dfb56e3e0f4258add36a2$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_DISPLAY_HANDLER_CTOCPP_H_
@@ -57,6 +57,13 @@
                     const CefSize& new_size) override;
   void OnLoadingProgressChange(CefRefPtr<CefBrowser> browser,
                                double progress) override;
+  bool OnCursorChange(CefRefPtr<CefBrowser> browser,
+                      CefCursorHandle cursor,
+                      cef_cursor_type_t type,
+                      const CefCursorInfo& custom_cursor_info) override;
+  void OnMediaAccessChange(CefRefPtr<CefBrowser> browser,
+                           bool has_video_access,
+                           bool has_audio_access) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_DISPLAY_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/domdocument_ctocpp.cc b/src/libcef_dll/ctocpp/domdocument_ctocpp.cc
index e1b9ce8..be759bb 100644
--- a/src/libcef_dll/ctocpp/domdocument_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/domdocument_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6cb38f54146095f4335340ef3183115c4142c30b$
+// $hash=7605dec503f07e4490341d3b60d2a4c0179a3d53$
 //
 
 #include "libcef_dll/ctocpp/domdocument_ctocpp.h"
@@ -22,8 +22,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domdocument_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_type))
+  if (CEF_MEMBER_MISSING(_struct, get_type)) {
     return DOM_DOCUMENT_TYPE_UNKNOWN;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -39,8 +40,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domdocument_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_document))
+  if (CEF_MEMBER_MISSING(_struct, get_document)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -55,8 +57,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domdocument_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_body))
+  if (CEF_MEMBER_MISSING(_struct, get_body)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -71,8 +74,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domdocument_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_head))
+  if (CEF_MEMBER_MISSING(_struct, get_head)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -87,8 +91,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domdocument_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_title))
+  if (CEF_MEMBER_MISSING(_struct, get_title)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -107,15 +112,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domdocument_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_element_by_id))
+  if (CEF_MEMBER_MISSING(_struct, get_element_by_id)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: id; type: string_byref_const
   DCHECK(!id.empty());
-  if (id.empty())
+  if (id.empty()) {
     return nullptr;
+  }
 
   // Execute
   cef_domnode_t* _retval = _struct->get_element_by_id(_struct, id.GetStruct());
@@ -129,8 +136,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domdocument_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_focused_node))
+  if (CEF_MEMBER_MISSING(_struct, get_focused_node)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -145,8 +153,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domdocument_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_selection))
+  if (CEF_MEMBER_MISSING(_struct, has_selection)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -161,8 +170,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domdocument_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_selection_start_offset))
+  if (CEF_MEMBER_MISSING(_struct, get_selection_start_offset)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -177,8 +187,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domdocument_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_selection_end_offset))
+  if (CEF_MEMBER_MISSING(_struct, get_selection_end_offset)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -194,8 +205,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domdocument_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_selection_as_markup))
+  if (CEF_MEMBER_MISSING(_struct, get_selection_as_markup)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -212,8 +224,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domdocument_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_selection_as_text))
+  if (CEF_MEMBER_MISSING(_struct, get_selection_as_text)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -230,8 +243,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domdocument_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_base_url))
+  if (CEF_MEMBER_MISSING(_struct, get_base_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -249,15 +263,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domdocument_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_complete_url))
+  if (CEF_MEMBER_MISSING(_struct, get_complete_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: partialURL; type: string_byref_const
   DCHECK(!partialURL.empty());
-  if (partialURL.empty())
+  if (partialURL.empty()) {
     return CefString();
+  }
 
   // Execute
   cef_string_userfree_t _retval =
@@ -283,7 +299,7 @@
 cef_domdocument_t*
 CefCToCppRefCounted<CefDOMDocumentCToCpp, CefDOMDocument, cef_domdocument_t>::
     UnwrapDerived(CefWrapperType type, CefDOMDocument* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/domdocument_ctocpp.h b/src/libcef_dll/ctocpp/domdocument_ctocpp.h
index 4c97a95..29fe326 100644
--- a/src/libcef_dll/ctocpp/domdocument_ctocpp.h
+++ b/src/libcef_dll/ctocpp/domdocument_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=77af57c3b139249d9bf00529d2baa5f231e3ea23$
+// $hash=987816a9b106341068d08f3cd9254c98cf77f6ad$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_DOMDOCUMENT_CTOCPP_H_
@@ -34,20 +34,20 @@
   virtual ~CefDOMDocumentCToCpp();
 
   // CefDOMDocument methods.
-  Type GetType() OVERRIDE;
-  CefRefPtr<CefDOMNode> GetDocument() OVERRIDE;
-  CefRefPtr<CefDOMNode> GetBody() OVERRIDE;
-  CefRefPtr<CefDOMNode> GetHead() OVERRIDE;
-  CefString GetTitle() OVERRIDE;
-  CefRefPtr<CefDOMNode> GetElementById(const CefString& id) OVERRIDE;
-  CefRefPtr<CefDOMNode> GetFocusedNode() OVERRIDE;
-  bool HasSelection() OVERRIDE;
-  int GetSelectionStartOffset() OVERRIDE;
-  int GetSelectionEndOffset() OVERRIDE;
-  CefString GetSelectionAsMarkup() OVERRIDE;
-  CefString GetSelectionAsText() OVERRIDE;
-  CefString GetBaseURL() OVERRIDE;
-  CefString GetCompleteURL(const CefString& partialURL) OVERRIDE;
+  Type GetType() override;
+  CefRefPtr<CefDOMNode> GetDocument() override;
+  CefRefPtr<CefDOMNode> GetBody() override;
+  CefRefPtr<CefDOMNode> GetHead() override;
+  CefString GetTitle() override;
+  CefRefPtr<CefDOMNode> GetElementById(const CefString& id) override;
+  CefRefPtr<CefDOMNode> GetFocusedNode() override;
+  bool HasSelection() override;
+  int GetSelectionStartOffset() override;
+  int GetSelectionEndOffset() override;
+  CefString GetSelectionAsMarkup() override;
+  CefString GetSelectionAsText() override;
+  CefString GetBaseURL() override;
+  CefString GetCompleteURL(const CefString& partialURL) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_DOMDOCUMENT_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/domnode_ctocpp.cc b/src/libcef_dll/ctocpp/domnode_ctocpp.cc
index a7a2261..22cedbc 100644
--- a/src/libcef_dll/ctocpp/domnode_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/domnode_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3f18ade9d60d3b383161ac49e65f61eb62887774$
+// $hash=37ed8551da23d022650ec89ce0fb82b8eec55eae$
 //
 
 #include "libcef_dll/ctocpp/domnode_ctocpp.h"
@@ -23,8 +23,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_type))
+  if (CEF_MEMBER_MISSING(_struct, get_type)) {
     return DOM_NODE_TYPE_UNSUPPORTED;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -39,8 +40,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_text))
+  if (CEF_MEMBER_MISSING(_struct, is_text)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -55,8 +57,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_element))
+  if (CEF_MEMBER_MISSING(_struct, is_element)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -71,8 +74,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_editable))
+  if (CEF_MEMBER_MISSING(_struct, is_editable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -87,8 +91,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_form_control_element))
-    return false;
+  if (CEF_MEMBER_MISSING(_struct, is_form_control_element)) {
+    return DOM_NODE_TYPE_UNSUPPORTED;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -100,23 +105,22 @@
 }
 
 NO_SANITIZE("cfi-icall")
-CefString CefDOMNodeCToCpp::GetFormControlElementType() {
+CefDOMNode::FormControlType CefDOMNodeCToCpp::GetFormControlElementType() {
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_form_control_element_type))
-    return CefString();
+  if (CEF_MEMBER_MISSING(_struct, get_form_control_element_type)) {
+    return DOM_FORM_CONTROL_TYPE_UNSUPPORTED;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  cef_string_userfree_t _retval =
+  cef_dom_form_control_type_t _retval =
       _struct->get_form_control_element_type(_struct);
 
-  // Return type: string
-  CefString _retvalStr;
-  _retvalStr.AttachToUserFree(_retval);
-  return _retvalStr;
+  // Return type: simple
+  return _retval;
 }
 
 NO_SANITIZE("cfi-icall")
@@ -124,15 +128,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefDOMNodeCToCpp::Unwrap(that));
@@ -145,8 +151,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_name))
+  if (CEF_MEMBER_MISSING(_struct, get_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -163,8 +170,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_value))
+  if (CEF_MEMBER_MISSING(_struct, get_value)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -182,15 +190,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_value))
+  if (CEF_MEMBER_MISSING(_struct, set_value)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: value; type: string_byref_const
   DCHECK(!value.empty());
-  if (value.empty())
+  if (value.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_value(_struct, value.GetStruct());
@@ -203,8 +213,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_as_markup))
+  if (CEF_MEMBER_MISSING(_struct, get_as_markup)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -222,8 +233,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_document))
+  if (CEF_MEMBER_MISSING(_struct, get_document)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -238,8 +250,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_parent))
+  if (CEF_MEMBER_MISSING(_struct, get_parent)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -255,8 +268,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_previous_sibling))
+  if (CEF_MEMBER_MISSING(_struct, get_previous_sibling)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -272,8 +286,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_next_sibling))
+  if (CEF_MEMBER_MISSING(_struct, get_next_sibling)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -288,8 +303,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_children))
+  if (CEF_MEMBER_MISSING(_struct, has_children)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -305,8 +321,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_first_child))
+  if (CEF_MEMBER_MISSING(_struct, get_first_child)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -322,8 +339,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_last_child))
+  if (CEF_MEMBER_MISSING(_struct, get_last_child)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -338,8 +356,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_element_tag_name))
+  if (CEF_MEMBER_MISSING(_struct, get_element_tag_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -356,8 +375,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_element_attributes))
+  if (CEF_MEMBER_MISSING(_struct, has_element_attributes)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -373,15 +393,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_element_attribute))
+  if (CEF_MEMBER_MISSING(_struct, has_element_attribute)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: attrName; type: string_byref_const
   DCHECK(!attrName.empty());
-  if (attrName.empty())
+  if (attrName.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->has_element_attribute(_struct, attrName.GetStruct());
@@ -395,15 +417,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_element_attribute))
+  if (CEF_MEMBER_MISSING(_struct, get_element_attribute)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: attrName; type: string_byref_const
   DCHECK(!attrName.empty());
-  if (attrName.empty())
+  if (attrName.empty()) {
     return CefString();
+  }
 
   // Execute
   cef_string_userfree_t _retval =
@@ -420,16 +444,18 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_element_attributes))
+  if (CEF_MEMBER_MISSING(_struct, get_element_attributes)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: attrMap; type: string_map_single_byref
   cef_string_map_t attrMapMap = cef_string_map_alloc();
   DCHECK(attrMapMap);
-  if (attrMapMap)
+  if (attrMapMap) {
     transfer_string_map_contents(attrMap, attrMapMap);
+  }
 
   // Execute
   _struct->get_element_attributes(_struct, attrMapMap);
@@ -448,19 +474,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_element_attribute))
+  if (CEF_MEMBER_MISSING(_struct, set_element_attribute)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: attrName; type: string_byref_const
   DCHECK(!attrName.empty());
-  if (attrName.empty())
+  if (attrName.empty()) {
     return false;
+  }
   // Verify param: value; type: string_byref_const
   DCHECK(!value.empty());
-  if (value.empty())
+  if (value.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_element_attribute(_struct, attrName.GetStruct(),
@@ -474,8 +503,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_element_inner_text))
+  if (CEF_MEMBER_MISSING(_struct, get_element_inner_text)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -492,8 +522,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domnode_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_element_bounds))
+  if (CEF_MEMBER_MISSING(_struct, get_element_bounds)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -519,7 +550,7 @@
 CefCToCppRefCounted<CefDOMNodeCToCpp, CefDOMNode, cef_domnode_t>::UnwrapDerived(
     CefWrapperType type,
     CefDOMNode* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/domnode_ctocpp.h b/src/libcef_dll/ctocpp/domnode_ctocpp.h
index f240618..f517d36 100644
--- a/src/libcef_dll/ctocpp/domnode_ctocpp.h
+++ b/src/libcef_dll/ctocpp/domnode_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3336f2ea70c4ca369801bc8a459aff5ed10f4605$
+// $hash=bdfecd683960bdf5cb2ef10617cc7cc0bf9112aa$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_DOMNODE_CTOCPP_H_
@@ -33,33 +33,33 @@
   virtual ~CefDOMNodeCToCpp();
 
   // CefDOMNode methods.
-  Type GetType() OVERRIDE;
-  bool IsText() OVERRIDE;
-  bool IsElement() OVERRIDE;
-  bool IsEditable() OVERRIDE;
-  bool IsFormControlElement() OVERRIDE;
-  CefString GetFormControlElementType() OVERRIDE;
-  bool IsSame(CefRefPtr<CefDOMNode> that) OVERRIDE;
-  CefString GetName() OVERRIDE;
-  CefString GetValue() OVERRIDE;
-  bool SetValue(const CefString& value) OVERRIDE;
-  CefString GetAsMarkup() OVERRIDE;
-  CefRefPtr<CefDOMDocument> GetDocument() OVERRIDE;
-  CefRefPtr<CefDOMNode> GetParent() OVERRIDE;
-  CefRefPtr<CefDOMNode> GetPreviousSibling() OVERRIDE;
-  CefRefPtr<CefDOMNode> GetNextSibling() OVERRIDE;
-  bool HasChildren() OVERRIDE;
-  CefRefPtr<CefDOMNode> GetFirstChild() OVERRIDE;
-  CefRefPtr<CefDOMNode> GetLastChild() OVERRIDE;
-  CefString GetElementTagName() OVERRIDE;
-  bool HasElementAttributes() OVERRIDE;
-  bool HasElementAttribute(const CefString& attrName) OVERRIDE;
-  CefString GetElementAttribute(const CefString& attrName) OVERRIDE;
-  void GetElementAttributes(AttributeMap& attrMap) OVERRIDE;
+  Type GetType() override;
+  bool IsText() override;
+  bool IsElement() override;
+  bool IsEditable() override;
+  bool IsFormControlElement() override;
+  FormControlType GetFormControlElementType() override;
+  bool IsSame(CefRefPtr<CefDOMNode> that) override;
+  CefString GetName() override;
+  CefString GetValue() override;
+  bool SetValue(const CefString& value) override;
+  CefString GetAsMarkup() override;
+  CefRefPtr<CefDOMDocument> GetDocument() override;
+  CefRefPtr<CefDOMNode> GetParent() override;
+  CefRefPtr<CefDOMNode> GetPreviousSibling() override;
+  CefRefPtr<CefDOMNode> GetNextSibling() override;
+  bool HasChildren() override;
+  CefRefPtr<CefDOMNode> GetFirstChild() override;
+  CefRefPtr<CefDOMNode> GetLastChild() override;
+  CefString GetElementTagName() override;
+  bool HasElementAttributes() override;
+  bool HasElementAttribute(const CefString& attrName) override;
+  CefString GetElementAttribute(const CefString& attrName) override;
+  void GetElementAttributes(AttributeMap& attrMap) override;
   bool SetElementAttribute(const CefString& attrName,
-                           const CefString& value) OVERRIDE;
-  CefString GetElementInnerText() OVERRIDE;
-  CefRect GetElementBounds() OVERRIDE;
+                           const CefString& value) override;
+  CefString GetElementInnerText() override;
+  CefRect GetElementBounds() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_DOMNODE_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/domvisitor_ctocpp.cc b/src/libcef_dll/ctocpp/domvisitor_ctocpp.cc
index f17b5f3..af3a78a 100644
--- a/src/libcef_dll/ctocpp/domvisitor_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/domvisitor_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e34ff7db1264daf93af8cb95913daa3750ada3b0$
+// $hash=8418f3ac65c441630719aa8f6f44dfcbaf778f2f$
 //
 
 #include "libcef_dll/ctocpp/domvisitor_ctocpp.h"
@@ -23,15 +23,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_domvisitor_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, visit))
+  if (CEF_MEMBER_MISSING(_struct, visit)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: document; type: refptr_diff
   DCHECK(document.get());
-  if (!document.get())
+  if (!document.get()) {
     return;
+  }
 
   // Execute
   _struct->visit(_struct, CefDOMDocumentCppToC::Wrap(document));
@@ -51,7 +53,7 @@
 cef_domvisitor_t*
 CefCToCppRefCounted<CefDOMVisitorCToCpp, CefDOMVisitor, cef_domvisitor_t>::
     UnwrapDerived(CefWrapperType type, CefDOMVisitor* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/domvisitor_ctocpp.h b/src/libcef_dll/ctocpp/domvisitor_ctocpp.h
index 88f779b..0504b52 100644
--- a/src/libcef_dll/ctocpp/domvisitor_ctocpp.h
+++ b/src/libcef_dll/ctocpp/domvisitor_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c8f5a5d42188269bd9732f28485d36284b1cb45b$
+// $hash=9f8a534b9feef5b972259d972bf30ad838e1a788$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_DOMVISITOR_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/download_handler_ctocpp.cc b/src/libcef_dll/ctocpp/download_handler_ctocpp.cc
index 9a433ea..8d77c59 100644
--- a/src/libcef_dll/ctocpp/download_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/download_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=667fe6d2620ca95df5e503f6332cf3e2342032ff$
+// $hash=23264ad881e05de87c12279841ec0f8c071c5503$
 //
 
 #include "libcef_dll/ctocpp/download_handler_ctocpp.h"
@@ -22,6 +22,44 @@
 // VIRTUAL METHODS - Body may be edited by hand.
 
 NO_SANITIZE("cfi-icall")
+bool CefDownloadHandlerCToCpp::CanDownload(CefRefPtr<CefBrowser> browser,
+                                           const CefString& url,
+                                           const CefString& request_method) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_download_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, can_download)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return false;
+  }
+  // Verify param: url; type: string_byref_const
+  DCHECK(!url.empty());
+  if (url.empty()) {
+    return false;
+  }
+  // Verify param: request_method; type: string_byref_const
+  DCHECK(!request_method.empty());
+  if (request_method.empty()) {
+    return false;
+  }
+
+  // Execute
+  int _retval =
+      _struct->can_download(_struct, CefBrowserCppToC::Wrap(browser),
+                            url.GetStruct(), request_method.GetStruct());
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
 void CefDownloadHandlerCToCpp::OnBeforeDownload(
     CefRefPtr<CefBrowser> browser,
     CefRefPtr<CefDownloadItem> download_item,
@@ -30,27 +68,32 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_before_download))
+  if (CEF_MEMBER_MISSING(_struct, on_before_download)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: download_item; type: refptr_diff
   DCHECK(download_item.get());
-  if (!download_item.get())
+  if (!download_item.get()) {
     return;
+  }
   // Verify param: suggested_name; type: string_byref_const
   DCHECK(!suggested_name.empty());
-  if (suggested_name.empty())
+  if (suggested_name.empty()) {
     return;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return;
+  }
 
   // Execute
   _struct->on_before_download(_struct, CefBrowserCppToC::Wrap(browser),
@@ -67,23 +110,27 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_download_updated))
+  if (CEF_MEMBER_MISSING(_struct, on_download_updated)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: download_item; type: refptr_diff
   DCHECK(download_item.get());
-  if (!download_item.get())
+  if (!download_item.get()) {
     return;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return;
+  }
 
   // Execute
   _struct->on_download_updated(_struct, CefBrowserCppToC::Wrap(browser),
@@ -107,7 +154,7 @@
     CefDownloadHandler,
     cef_download_handler_t>::UnwrapDerived(CefWrapperType type,
                                            CefDownloadHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/download_handler_ctocpp.h b/src/libcef_dll/ctocpp/download_handler_ctocpp.h
index b394739..d825320 100644
--- a/src/libcef_dll/ctocpp/download_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/download_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=52a2a7f06afb8a82f469cb96b3c49aa914a2a87f$
+// $hash=486d31ad20241c84c224f0b8c90fe0c0f915ad18$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_HANDLER_CTOCPP_H_
@@ -35,6 +35,9 @@
   virtual ~CefDownloadHandlerCToCpp();
 
   // CefDownloadHandler methods.
+  bool CanDownload(CefRefPtr<CefBrowser> browser,
+                   const CefString& url,
+                   const CefString& request_method) override;
   void OnBeforeDownload(CefRefPtr<CefBrowser> browser,
                         CefRefPtr<CefDownloadItem> download_item,
                         const CefString& suggested_name,
diff --git a/src/libcef_dll/ctocpp/download_image_callback_ctocpp.cc b/src/libcef_dll/ctocpp/download_image_callback_ctocpp.cc
index 0ca242e..d26719d 100644
--- a/src/libcef_dll/ctocpp/download_image_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/download_image_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ec0d6a1abada255681087caf7a9db1bba5e90a7b$
+// $hash=c23c4882077e50ffcf64425b3a5476ad3cfb9cb8$
 //
 
 #include "libcef_dll/ctocpp/download_image_callback_ctocpp.h"
@@ -26,15 +26,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_image_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_download_image_finished))
+  if (CEF_MEMBER_MISSING(_struct, on_download_image_finished)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: image_url; type: string_byref_const
   DCHECK(!image_url.empty());
-  if (image_url.empty())
+  if (image_url.empty()) {
     return;
+  }
   // Unverified params: image
 
   // Execute
@@ -59,7 +61,7 @@
     CefDownloadImageCallback,
     cef_download_image_callback_t>::UnwrapDerived(CefWrapperType type,
                                                   CefDownloadImageCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/download_image_callback_ctocpp.h b/src/libcef_dll/ctocpp/download_image_callback_ctocpp.h
index bd28afa..5c7b7cc 100644
--- a/src/libcef_dll/ctocpp/download_image_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/download_image_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b98f56b5265b6a1be28ee7c13112dc3e03e93469$
+// $hash=c281c09951a9b4f85556d0a9008b2524326254dd$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_IMAGE_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/download_item_callback_ctocpp.cc b/src/libcef_dll/ctocpp/download_item_callback_ctocpp.cc
index 0360f62..557b2c6 100644
--- a/src/libcef_dll/ctocpp/download_item_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/download_item_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=bf55af2dad90c3fe81e337640709f31005ba8a8e$
+// $hash=12c936fbf246741f64131f68557538017701298c$
 //
 
 #include "libcef_dll/ctocpp/download_item_callback_ctocpp.h"
@@ -21,8 +21,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cancel))
+  if (CEF_MEMBER_MISSING(_struct, cancel)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -34,8 +35,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, pause))
+  if (CEF_MEMBER_MISSING(_struct, pause)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -47,8 +49,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, resume))
+  if (CEF_MEMBER_MISSING(_struct, resume)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -72,7 +75,7 @@
     CefDownloadItemCallback,
     cef_download_item_callback_t>::UnwrapDerived(CefWrapperType type,
                                                  CefDownloadItemCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/download_item_callback_ctocpp.h b/src/libcef_dll/ctocpp/download_item_callback_ctocpp.h
index 258a4d7..0f52a41 100644
--- a/src/libcef_dll/ctocpp/download_item_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/download_item_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ba5b388ff5ba71224499779e8410b8354e05363c$
+// $hash=013ef6edbf734cdf4e6d00ba5b8be6c46284e2ca$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_ITEM_CALLBACK_CTOCPP_H_
@@ -35,9 +35,9 @@
   virtual ~CefDownloadItemCallbackCToCpp();
 
   // CefDownloadItemCallback methods.
-  void Cancel() OVERRIDE;
-  void Pause() OVERRIDE;
-  void Resume() OVERRIDE;
+  void Cancel() override;
+  void Pause() override;
+  void Resume() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_ITEM_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/download_item_ctocpp.cc b/src/libcef_dll/ctocpp/download_item_ctocpp.cc
index c29b480..369d80c 100644
--- a/src/libcef_dll/ctocpp/download_item_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/download_item_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2df7e7e66fe8562a16d2d3f1b9068eac73eb444c$
+// $hash=36f3d78a68210e51b75e59dd8521c5d8bbfc12e9$
 //
 
 #include "libcef_dll/ctocpp/download_item_ctocpp.h"
@@ -21,8 +21,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -37,8 +38,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_in_progress))
+  if (CEF_MEMBER_MISSING(_struct, is_in_progress)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -53,8 +55,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_complete))
+  if (CEF_MEMBER_MISSING(_struct, is_complete)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -69,8 +72,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_canceled))
+  if (CEF_MEMBER_MISSING(_struct, is_canceled)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -81,17 +85,54 @@
   return _retval ? true : false;
 }
 
-NO_SANITIZE("cfi-icall") int64 CefDownloadItemCToCpp::GetCurrentSpeed() {
+NO_SANITIZE("cfi-icall") bool CefDownloadItemCToCpp::IsInterrupted() {
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_current_speed))
-    return 0;
+  if (CEF_MEMBER_MISSING(_struct, is_interrupted)) {
+    return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int64 _retval = _struct->get_current_speed(_struct);
+  int _retval = _struct->is_interrupted(_struct);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+cef_download_interrupt_reason_t CefDownloadItemCToCpp::GetInterruptReason() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_download_item_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_interrupt_reason)) {
+    return CEF_DOWNLOAD_INTERRUPT_REASON_NONE;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_download_interrupt_reason_t _retval =
+      _struct->get_interrupt_reason(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall") int64_t CefDownloadItemCToCpp::GetCurrentSpeed() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_download_item_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_current_speed)) {
+    return 0;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int64_t _retval = _struct->get_current_speed(_struct);
 
   // Return type: simple
   return _retval;
@@ -101,8 +142,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_percent_complete))
+  if (CEF_MEMBER_MISSING(_struct, get_percent_complete)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -113,65 +155,69 @@
   return _retval;
 }
 
-NO_SANITIZE("cfi-icall") int64 CefDownloadItemCToCpp::GetTotalBytes() {
+NO_SANITIZE("cfi-icall") int64_t CefDownloadItemCToCpp::GetTotalBytes() {
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_total_bytes))
+  if (CEF_MEMBER_MISSING(_struct, get_total_bytes)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int64 _retval = _struct->get_total_bytes(_struct);
+  int64_t _retval = _struct->get_total_bytes(_struct);
 
   // Return type: simple
   return _retval;
 }
 
-NO_SANITIZE("cfi-icall") int64 CefDownloadItemCToCpp::GetReceivedBytes() {
+NO_SANITIZE("cfi-icall") int64_t CefDownloadItemCToCpp::GetReceivedBytes() {
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_received_bytes))
+  if (CEF_MEMBER_MISSING(_struct, get_received_bytes)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int64 _retval = _struct->get_received_bytes(_struct);
+  int64_t _retval = _struct->get_received_bytes(_struct);
 
   // Return type: simple
   return _retval;
 }
 
-NO_SANITIZE("cfi-icall") CefTime CefDownloadItemCToCpp::GetStartTime() {
+NO_SANITIZE("cfi-icall") CefBaseTime CefDownloadItemCToCpp::GetStartTime() {
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_start_time))
-    return CefTime();
+  if (CEF_MEMBER_MISSING(_struct, get_start_time)) {
+    return CefBaseTime();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  cef_time_t _retval = _struct->get_start_time(_struct);
+  cef_basetime_t _retval = _struct->get_start_time(_struct);
 
   // Return type: simple
   return _retval;
 }
 
-NO_SANITIZE("cfi-icall") CefTime CefDownloadItemCToCpp::GetEndTime() {
+NO_SANITIZE("cfi-icall") CefBaseTime CefDownloadItemCToCpp::GetEndTime() {
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_end_time))
-    return CefTime();
+  if (CEF_MEMBER_MISSING(_struct, get_end_time)) {
+    return CefBaseTime();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  cef_time_t _retval = _struct->get_end_time(_struct);
+  cef_basetime_t _retval = _struct->get_end_time(_struct);
 
   // Return type: simple
   return _retval;
@@ -181,8 +227,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_full_path))
+  if (CEF_MEMBER_MISSING(_struct, get_full_path)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -195,17 +242,18 @@
   return _retvalStr;
 }
 
-NO_SANITIZE("cfi-icall") uint32 CefDownloadItemCToCpp::GetId() {
+NO_SANITIZE("cfi-icall") uint32_t CefDownloadItemCToCpp::GetId() {
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_id))
+  if (CEF_MEMBER_MISSING(_struct, get_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  uint32 _retval = _struct->get_id(_struct);
+  uint32_t _retval = _struct->get_id(_struct);
 
   // Return type: simple
   return _retval;
@@ -215,8 +263,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_url))
+  if (CEF_MEMBER_MISSING(_struct, get_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -233,8 +282,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_original_url))
+  if (CEF_MEMBER_MISSING(_struct, get_original_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -252,8 +302,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_suggested_file_name))
+  if (CEF_MEMBER_MISSING(_struct, get_suggested_file_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -271,8 +322,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_content_disposition))
+  if (CEF_MEMBER_MISSING(_struct, get_content_disposition)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -289,8 +341,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_download_item_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_mime_type))
+  if (CEF_MEMBER_MISSING(_struct, get_mime_type)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -319,7 +372,7 @@
                     CefDownloadItem,
                     cef_download_item_t>::UnwrapDerived(CefWrapperType type,
                                                         CefDownloadItem* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/download_item_ctocpp.h b/src/libcef_dll/ctocpp/download_item_ctocpp.h
index 9c9a3fa..b517cc1 100644
--- a/src/libcef_dll/ctocpp/download_item_ctocpp.h
+++ b/src/libcef_dll/ctocpp/download_item_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=a7cd44cf21351fde788e0756af8d3b9ddb72669a$
+// $hash=4422e2d57ebf8624ca57ad064cd78963c5de26ba$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_ITEM_CTOCPP_H_
@@ -34,23 +34,25 @@
   virtual ~CefDownloadItemCToCpp();
 
   // CefDownloadItem methods.
-  bool IsValid() OVERRIDE;
-  bool IsInProgress() OVERRIDE;
-  bool IsComplete() OVERRIDE;
-  bool IsCanceled() OVERRIDE;
-  int64 GetCurrentSpeed() OVERRIDE;
-  int GetPercentComplete() OVERRIDE;
-  int64 GetTotalBytes() OVERRIDE;
-  int64 GetReceivedBytes() OVERRIDE;
-  CefTime GetStartTime() OVERRIDE;
-  CefTime GetEndTime() OVERRIDE;
-  CefString GetFullPath() OVERRIDE;
-  uint32 GetId() OVERRIDE;
-  CefString GetURL() OVERRIDE;
-  CefString GetOriginalUrl() OVERRIDE;
-  CefString GetSuggestedFileName() OVERRIDE;
-  CefString GetContentDisposition() OVERRIDE;
-  CefString GetMimeType() OVERRIDE;
+  bool IsValid() override;
+  bool IsInProgress() override;
+  bool IsComplete() override;
+  bool IsCanceled() override;
+  bool IsInterrupted() override;
+  cef_download_interrupt_reason_t GetInterruptReason() override;
+  int64_t GetCurrentSpeed() override;
+  int GetPercentComplete() override;
+  int64_t GetTotalBytes() override;
+  int64_t GetReceivedBytes() override;
+  CefBaseTime GetStartTime() override;
+  CefBaseTime GetEndTime() override;
+  CefString GetFullPath() override;
+  uint32_t GetId() override;
+  CefString GetURL() override;
+  CefString GetOriginalUrl() override;
+  CefString GetSuggestedFileName() override;
+  CefString GetContentDisposition() override;
+  CefString GetMimeType() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_ITEM_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/drag_data_ctocpp.cc b/src/libcef_dll/ctocpp/drag_data_ctocpp.cc
index 3078d21..26307bd 100644
--- a/src/libcef_dll/ctocpp/drag_data_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/drag_data_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3c09e3dd7fb76abe189934ca434a74af29ac9954$
+// $hash=1dadac1c1138021a5f38e52ccb8f9863f5a387b5$
 //
 
 #include "libcef_dll/ctocpp/drag_data_ctocpp.h"
@@ -38,8 +38,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, clone))
+  if (CEF_MEMBER_MISSING(_struct, clone)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -54,8 +55,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_read_only))
+  if (CEF_MEMBER_MISSING(_struct, is_read_only)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -70,8 +72,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_link))
+  if (CEF_MEMBER_MISSING(_struct, is_link)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -86,8 +89,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_fragment))
+  if (CEF_MEMBER_MISSING(_struct, is_fragment)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -102,8 +106,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_file))
+  if (CEF_MEMBER_MISSING(_struct, is_file)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -118,8 +123,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_link_url))
+  if (CEF_MEMBER_MISSING(_struct, get_link_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -136,8 +142,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_link_title))
+  if (CEF_MEMBER_MISSING(_struct, get_link_title)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -154,8 +161,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_link_metadata))
+  if (CEF_MEMBER_MISSING(_struct, get_link_metadata)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -172,8 +180,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_fragment_text))
+  if (CEF_MEMBER_MISSING(_struct, get_fragment_text)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -190,8 +199,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_fragment_html))
+  if (CEF_MEMBER_MISSING(_struct, get_fragment_html)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -208,8 +218,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_fragment_base_url))
+  if (CEF_MEMBER_MISSING(_struct, get_fragment_base_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -226,8 +237,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_file_name))
+  if (CEF_MEMBER_MISSING(_struct, get_file_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -245,8 +257,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_file_contents))
+  if (CEF_MEMBER_MISSING(_struct, get_file_contents)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -265,16 +278,18 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_file_names))
+  if (CEF_MEMBER_MISSING(_struct, get_file_names)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: names; type: string_vec_byref
   cef_string_list_t namesList = cef_string_list_alloc();
   DCHECK(namesList);
-  if (namesList)
+  if (namesList) {
     transfer_string_list_contents(names, namesList);
+  }
 
   // Execute
   int _retval = _struct->get_file_names(_struct, namesList);
@@ -291,12 +306,45 @@
 }
 
 NO_SANITIZE("cfi-icall")
+bool CefDragDataCToCpp::GetFilePaths(std::vector<CefString>& paths) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_drag_data_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_file_paths)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Translate param: paths; type: string_vec_byref
+  cef_string_list_t pathsList = cef_string_list_alloc();
+  DCHECK(pathsList);
+  if (pathsList) {
+    transfer_string_list_contents(paths, pathsList);
+  }
+
+  // Execute
+  int _retval = _struct->get_file_paths(_struct, pathsList);
+
+  // Restore param:paths; type: string_vec_byref
+  if (pathsList) {
+    paths.clear();
+    transfer_string_list_contents(pathsList, paths);
+    cef_string_list_free(pathsList);
+  }
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
 void CefDragDataCToCpp::SetLinkURL(const CefString& url) {
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_link_url))
+  if (CEF_MEMBER_MISSING(_struct, set_link_url)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -311,8 +359,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_link_title))
+  if (CEF_MEMBER_MISSING(_struct, set_link_title)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -327,8 +376,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_link_metadata))
+  if (CEF_MEMBER_MISSING(_struct, set_link_metadata)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -343,8 +393,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_fragment_text))
+  if (CEF_MEMBER_MISSING(_struct, set_fragment_text)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -359,8 +410,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_fragment_html))
+  if (CEF_MEMBER_MISSING(_struct, set_fragment_html)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -375,8 +427,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_fragment_base_url))
+  if (CEF_MEMBER_MISSING(_struct, set_fragment_base_url)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -390,8 +443,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, reset_file_contents))
+  if (CEF_MEMBER_MISSING(_struct, reset_file_contents)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -405,27 +459,44 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, add_file))
+  if (CEF_MEMBER_MISSING(_struct, add_file)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: path; type: string_byref_const
   DCHECK(!path.empty());
-  if (path.empty())
+  if (path.empty()) {
     return;
+  }
   // Unverified params: display_name
 
   // Execute
   _struct->add_file(_struct, path.GetStruct(), display_name.GetStruct());
 }
 
+NO_SANITIZE("cfi-icall") void CefDragDataCToCpp::ClearFilenames() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_drag_data_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, clear_filenames)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->clear_filenames(_struct);
+}
+
 NO_SANITIZE("cfi-icall") CefRefPtr<CefImage> CefDragDataCToCpp::GetImage() {
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_image))
+  if (CEF_MEMBER_MISSING(_struct, get_image)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -440,8 +511,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_image_hotspot))
+  if (CEF_MEMBER_MISSING(_struct, get_image_hotspot)) {
     return CefPoint();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -456,8 +528,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_image))
+  if (CEF_MEMBER_MISSING(_struct, has_image)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -482,7 +555,7 @@
 cef_drag_data_t*
 CefCToCppRefCounted<CefDragDataCToCpp, CefDragData, cef_drag_data_t>::
     UnwrapDerived(CefWrapperType type, CefDragData* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/drag_data_ctocpp.h b/src/libcef_dll/ctocpp/drag_data_ctocpp.h
index 954404a..7e07f0e 100644
--- a/src/libcef_dll/ctocpp/drag_data_ctocpp.h
+++ b/src/libcef_dll/ctocpp/drag_data_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=fde29293045566e5af81f49fa8a3cce687a4a79f$
+// $hash=fee8d107d6baed8cb7d838613ab4b95134e04c59$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_DRAG_DATA_CTOCPP_H_
@@ -35,31 +35,33 @@
   virtual ~CefDragDataCToCpp();
 
   // CefDragData methods.
-  CefRefPtr<CefDragData> Clone() OVERRIDE;
-  bool IsReadOnly() OVERRIDE;
-  bool IsLink() OVERRIDE;
-  bool IsFragment() OVERRIDE;
-  bool IsFile() OVERRIDE;
-  CefString GetLinkURL() OVERRIDE;
-  CefString GetLinkTitle() OVERRIDE;
-  CefString GetLinkMetadata() OVERRIDE;
-  CefString GetFragmentText() OVERRIDE;
-  CefString GetFragmentHtml() OVERRIDE;
-  CefString GetFragmentBaseURL() OVERRIDE;
-  CefString GetFileName() OVERRIDE;
-  size_t GetFileContents(CefRefPtr<CefStreamWriter> writer) OVERRIDE;
-  bool GetFileNames(std::vector<CefString>& names) OVERRIDE;
-  void SetLinkURL(const CefString& url) OVERRIDE;
-  void SetLinkTitle(const CefString& title) OVERRIDE;
-  void SetLinkMetadata(const CefString& data) OVERRIDE;
-  void SetFragmentText(const CefString& text) OVERRIDE;
-  void SetFragmentHtml(const CefString& html) OVERRIDE;
-  void SetFragmentBaseURL(const CefString& base_url) OVERRIDE;
-  void ResetFileContents() OVERRIDE;
-  void AddFile(const CefString& path, const CefString& display_name) OVERRIDE;
-  CefRefPtr<CefImage> GetImage() OVERRIDE;
-  CefPoint GetImageHotspot() OVERRIDE;
-  bool HasImage() OVERRIDE;
+  CefRefPtr<CefDragData> Clone() override;
+  bool IsReadOnly() override;
+  bool IsLink() override;
+  bool IsFragment() override;
+  bool IsFile() override;
+  CefString GetLinkURL() override;
+  CefString GetLinkTitle() override;
+  CefString GetLinkMetadata() override;
+  CefString GetFragmentText() override;
+  CefString GetFragmentHtml() override;
+  CefString GetFragmentBaseURL() override;
+  CefString GetFileName() override;
+  size_t GetFileContents(CefRefPtr<CefStreamWriter> writer) override;
+  bool GetFileNames(std::vector<CefString>& names) override;
+  bool GetFilePaths(std::vector<CefString>& paths) override;
+  void SetLinkURL(const CefString& url) override;
+  void SetLinkTitle(const CefString& title) override;
+  void SetLinkMetadata(const CefString& data) override;
+  void SetFragmentText(const CefString& text) override;
+  void SetFragmentHtml(const CefString& html) override;
+  void SetFragmentBaseURL(const CefString& base_url) override;
+  void ResetFileContents() override;
+  void AddFile(const CefString& path, const CefString& display_name) override;
+  void ClearFilenames() override;
+  CefRefPtr<CefImage> GetImage() override;
+  CefPoint GetImageHotspot() override;
+  bool HasImage() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_DRAG_DATA_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/drag_handler_ctocpp.cc b/src/libcef_dll/ctocpp/drag_handler_ctocpp.cc
index bc72af3..a440d49 100644
--- a/src/libcef_dll/ctocpp/drag_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/drag_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1aa70a0c640336bc3569f151bfba80d675b4c07e$
+// $hash=de7454fdcb2d48f43bb22d95d989050c3dce0f16$
 //
 
 #include "libcef_dll/ctocpp/drag_handler_ctocpp.h"
@@ -27,19 +27,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_drag_enter))
+  if (CEF_MEMBER_MISSING(_struct, on_drag_enter)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: dragData; type: refptr_diff
   DCHECK(dragData.get());
-  if (!dragData.get())
+  if (!dragData.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->on_drag_enter(_struct, CefBrowserCppToC::Wrap(browser),
@@ -57,19 +60,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_drag_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_draggable_regions_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_draggable_regions_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return;
+  }
 
   // Translate param: regions; type: simple_vec_byref_const
   const size_t regionsCount = regions.size();
@@ -90,8 +96,9 @@
       regionsCount, regionsList);
 
   // Restore param:regions; type: simple_vec_byref_const
-  if (regionsList)
+  if (regionsList) {
     delete[] regionsList;
+  }
 }
 
 // CONSTRUCTOR - Do not edit by hand.
@@ -108,7 +115,7 @@
 cef_drag_handler_t*
 CefCToCppRefCounted<CefDragHandlerCToCpp, CefDragHandler, cef_drag_handler_t>::
     UnwrapDerived(CefWrapperType type, CefDragHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/drag_handler_ctocpp.h b/src/libcef_dll/ctocpp/drag_handler_ctocpp.h
index a6ea567..153cf49 100644
--- a/src/libcef_dll/ctocpp/drag_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/drag_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e0f301338abe21b6d6ad6d38f6497d87fa3d9c91$
+// $hash=a8523e82439b30828b0774d2eff240ea215b96d6$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_DRAG_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/end_tracing_callback_ctocpp.cc b/src/libcef_dll/ctocpp/end_tracing_callback_ctocpp.cc
index 8f6f9cd..4915433 100644
--- a/src/libcef_dll/ctocpp/end_tracing_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/end_tracing_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9a3a21ab271832d967d4212b1fa9362691eb3bdc$
+// $hash=870f78147369bc35912730714caef7559fa41c99$
 //
 
 #include "libcef_dll/ctocpp/end_tracing_callback_ctocpp.h"
@@ -23,15 +23,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_end_tracing_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_end_tracing_complete))
+  if (CEF_MEMBER_MISSING(_struct, on_end_tracing_complete)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: tracing_file; type: string_byref_const
   DCHECK(!tracing_file.empty());
-  if (tracing_file.empty())
+  if (tracing_file.empty()) {
     return;
+  }
 
   // Execute
   _struct->on_end_tracing_complete(_struct, tracing_file.GetStruct());
@@ -53,7 +55,7 @@
     CefEndTracingCallback,
     cef_end_tracing_callback_t>::UnwrapDerived(CefWrapperType type,
                                                CefEndTracingCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/end_tracing_callback_ctocpp.h b/src/libcef_dll/ctocpp/end_tracing_callback_ctocpp.h
index 39a622a..c915803 100644
--- a/src/libcef_dll/ctocpp/end_tracing_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/end_tracing_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=78fcf71ee6c9b5eb813286bb6b9ab3474c6ee1b4$
+// $hash=d798b3255a8ad2aea9d4afbe3492eaad538d8d0a$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_END_TRACING_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/extension_ctocpp.cc b/src/libcef_dll/ctocpp/extension_ctocpp.cc
index ad70e9f..4533afb 100644
--- a/src/libcef_dll/ctocpp/extension_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/extension_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c276b1767d8f7930dd3be2c2409efda2159428b0$
+// $hash=dd6eb9dad8ce6a01307fb48ec0fc4f9a2a61e4ee$
 //
 
 #include "libcef_dll/ctocpp/extension_ctocpp.h"
@@ -24,8 +24,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_extension_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_identifier))
+  if (CEF_MEMBER_MISSING(_struct, get_identifier)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -42,8 +43,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_extension_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_path))
+  if (CEF_MEMBER_MISSING(_struct, get_path)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -61,8 +63,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_extension_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_manifest))
+  if (CEF_MEMBER_MISSING(_struct, get_manifest)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -78,15 +81,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_extension_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefExtensionCToCpp::Unwrap(that));
@@ -100,8 +105,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_extension_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -117,8 +123,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_extension_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_loader_context))
+  if (CEF_MEMBER_MISSING(_struct, get_loader_context)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -133,8 +140,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_extension_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_loaded))
+  if (CEF_MEMBER_MISSING(_struct, is_loaded)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -149,8 +157,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_extension_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, unload))
+  if (CEF_MEMBER_MISSING(_struct, unload)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -172,7 +181,7 @@
 cef_extension_t*
 CefCToCppRefCounted<CefExtensionCToCpp, CefExtension, cef_extension_t>::
     UnwrapDerived(CefWrapperType type, CefExtension* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/extension_ctocpp.h b/src/libcef_dll/ctocpp/extension_ctocpp.h
index 8f18906..b186810 100644
--- a/src/libcef_dll/ctocpp/extension_ctocpp.h
+++ b/src/libcef_dll/ctocpp/extension_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3c31d21941156e368e6628298123a212591447cf$
+// $hash=07a08b9dd260059e77dfb433f43686cbc5569bea$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_EXTENSION_CTOCPP_H_
@@ -38,14 +38,14 @@
   virtual ~CefExtensionCToCpp();
 
   // CefExtension methods.
-  CefString GetIdentifier() OVERRIDE;
-  CefString GetPath() OVERRIDE;
-  CefRefPtr<CefDictionaryValue> GetManifest() OVERRIDE;
-  bool IsSame(CefRefPtr<CefExtension> that) OVERRIDE;
-  CefRefPtr<CefExtensionHandler> GetHandler() OVERRIDE;
-  CefRefPtr<CefRequestContext> GetLoaderContext() OVERRIDE;
-  bool IsLoaded() OVERRIDE;
-  void Unload() OVERRIDE;
+  CefString GetIdentifier() override;
+  CefString GetPath() override;
+  CefRefPtr<CefDictionaryValue> GetManifest() override;
+  bool IsSame(CefRefPtr<CefExtension> that) override;
+  CefRefPtr<CefExtensionHandler> GetHandler() override;
+  CefRefPtr<CefRequestContext> GetLoaderContext() override;
+  bool IsLoaded() override;
+  void Unload() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_EXTENSION_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/extension_handler_ctocpp.cc b/src/libcef_dll/ctocpp/extension_handler_ctocpp.cc
index c712339..ea0ab8e 100644
--- a/src/libcef_dll/ctocpp/extension_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/extension_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e2150893079724b7435ca143122b17096be5a8f5$
+// $hash=b1961c4ff6c203edef2f48bdbb5ac773815a15c7$
 //
 
 #include "libcef_dll/ctocpp/extension_handler_ctocpp.h"
@@ -26,8 +26,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_extension_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_extension_load_failed))
+  if (CEF_MEMBER_MISSING(_struct, on_extension_load_failed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -41,15 +42,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_extension_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_extension_loaded))
+  if (CEF_MEMBER_MISSING(_struct, on_extension_loaded)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: extension; type: refptr_diff
   DCHECK(extension.get());
-  if (!extension.get())
+  if (!extension.get()) {
     return;
+  }
 
   // Execute
   _struct->on_extension_loaded(_struct, CefExtensionCppToC::Wrap(extension));
@@ -61,15 +64,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_extension_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_extension_unloaded))
+  if (CEF_MEMBER_MISSING(_struct, on_extension_unloaded)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: extension; type: refptr_diff
   DCHECK(extension.get());
-  if (!extension.get())
+  if (!extension.get()) {
     return;
+  }
 
   // Execute
   _struct->on_extension_unloaded(_struct, CefExtensionCppToC::Wrap(extension));
@@ -84,24 +89,28 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_extension_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_before_background_browser))
+  if (CEF_MEMBER_MISSING(_struct, on_before_background_browser)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: extension; type: refptr_diff
   DCHECK(extension.get());
-  if (!extension.get())
+  if (!extension.get()) {
     return false;
+  }
   // Verify param: url; type: string_byref_const
   DCHECK(!url.empty());
-  if (url.empty())
+  if (url.empty()) {
     return false;
+  }
 
   // Translate param: client; type: refptr_same_byref
   cef_client_t* clientStruct = NULL;
-  if (client.get())
+  if (client.get()) {
     clientStruct = CefClientCToCpp::Unwrap(client);
+  }
   cef_client_t* clientOrig = clientStruct;
 
   // Execute
@@ -136,32 +145,38 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_extension_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_before_browser))
+  if (CEF_MEMBER_MISSING(_struct, on_before_browser)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: extension; type: refptr_diff
   DCHECK(extension.get());
-  if (!extension.get())
+  if (!extension.get()) {
     return false;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: active_browser; type: refptr_diff
   DCHECK(active_browser.get());
-  if (!active_browser.get())
+  if (!active_browser.get()) {
     return false;
+  }
   // Verify param: url; type: string_byref_const
   DCHECK(!url.empty());
-  if (url.empty())
+  if (url.empty()) {
     return false;
+  }
 
   // Translate param: client; type: refptr_same_byref
   cef_client_t* clientStruct = NULL;
-  if (client.get())
+  if (client.get()) {
     clientStruct = CefClientCToCpp::Unwrap(client);
+  }
   cef_client_t* clientOrig = clientStruct;
 
   // Execute
@@ -191,19 +206,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_extension_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_active_browser))
+  if (CEF_MEMBER_MISSING(_struct, get_active_browser)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: extension; type: refptr_diff
   DCHECK(extension.get());
-  if (!extension.get())
+  if (!extension.get()) {
     return nullptr;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return nullptr;
+  }
 
   // Execute
   cef_browser_t* _retval = _struct->get_active_browser(
@@ -223,23 +241,27 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_extension_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, can_access_browser))
+  if (CEF_MEMBER_MISSING(_struct, can_access_browser)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: extension; type: refptr_diff
   DCHECK(extension.get());
-  if (!extension.get())
+  if (!extension.get()) {
     return false;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: target_browser; type: refptr_diff
   DCHECK(target_browser.get());
-  if (!target_browser.get())
+  if (!target_browser.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->can_access_browser(
@@ -260,27 +282,32 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_extension_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_extension_resource))
+  if (CEF_MEMBER_MISSING(_struct, get_extension_resource)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: extension; type: refptr_diff
   DCHECK(extension.get());
-  if (!extension.get())
+  if (!extension.get()) {
     return false;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: file; type: string_byref_const
   DCHECK(!file.empty());
-  if (file.empty())
+  if (file.empty()) {
     return false;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->get_extension_resource(
@@ -308,7 +335,7 @@
     CefExtensionHandler,
     cef_extension_handler_t>::UnwrapDerived(CefWrapperType type,
                                             CefExtensionHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/extension_handler_ctocpp.h b/src/libcef_dll/ctocpp/extension_handler_ctocpp.h
index dac16a7..eab84e7 100644
--- a/src/libcef_dll/ctocpp/extension_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/extension_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=fab935d5efc290c7dd7d663609ba152df6e1be81$
+// $hash=5e432e7dd8e10b681b96bad3694ba2d0bf79fad6$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_EXTENSION_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/file_dialog_callback_ctocpp.cc b/src/libcef_dll/ctocpp/file_dialog_callback_ctocpp.cc
index 53c49ba..46ad4e2 100644
--- a/src/libcef_dll/ctocpp/file_dialog_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/file_dialog_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=19a439c707a5ccfa865eabb3a2a3ec8150104ba5$
+// $hash=01a59b2a4850603dcb6df74f33431d13bcf2c5c9$
 //
 
 #include "libcef_dll/ctocpp/file_dialog_callback_ctocpp.h"
@@ -20,42 +20,41 @@
 
 NO_SANITIZE("cfi-icall")
 void CefFileDialogCallbackCToCpp::Continue(
-    int selected_accept_filter,
     const std::vector<CefString>& file_paths) {
   shutdown_checker::AssertNotShutdown();
 
   cef_file_dialog_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cont))
+  if (CEF_MEMBER_MISSING(_struct, cont)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
-  // Verify param: selected_accept_filter; type: simple_byval
-  DCHECK_GE(selected_accept_filter, 0);
-  if (selected_accept_filter < 0)
-    return;
   // Unverified params: file_paths
 
   // Translate param: file_paths; type: string_vec_byref_const
   cef_string_list_t file_pathsList = cef_string_list_alloc();
   DCHECK(file_pathsList);
-  if (file_pathsList)
+  if (file_pathsList) {
     transfer_string_list_contents(file_paths, file_pathsList);
+  }
 
   // Execute
-  _struct->cont(_struct, selected_accept_filter, file_pathsList);
+  _struct->cont(_struct, file_pathsList);
 
   // Restore param:file_paths; type: string_vec_byref_const
-  if (file_pathsList)
+  if (file_pathsList) {
     cef_string_list_free(file_pathsList);
+  }
 }
 
 NO_SANITIZE("cfi-icall") void CefFileDialogCallbackCToCpp::Cancel() {
   shutdown_checker::AssertNotShutdown();
 
   cef_file_dialog_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cancel))
+  if (CEF_MEMBER_MISSING(_struct, cancel)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -79,7 +78,7 @@
     CefFileDialogCallback,
     cef_file_dialog_callback_t>::UnwrapDerived(CefWrapperType type,
                                                CefFileDialogCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/file_dialog_callback_ctocpp.h b/src/libcef_dll/ctocpp/file_dialog_callback_ctocpp.h
index 1f1292e..266a8b7 100644
--- a/src/libcef_dll/ctocpp/file_dialog_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/file_dialog_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6dcb54aa208a5e974b7b0d7d8da229960cb3da55$
+// $hash=75544d28b1d0f0cdfc2f8cb1bd3f521cfe676bce$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_FILE_DIALOG_CALLBACK_CTOCPP_H_
@@ -36,9 +36,8 @@
   virtual ~CefFileDialogCallbackCToCpp();
 
   // CefFileDialogCallback methods.
-  void Continue(int selected_accept_filter,
-                const std::vector<CefString>& file_paths) OVERRIDE;
-  void Cancel() OVERRIDE;
+  void Continue(const std::vector<CefString>& file_paths) override;
+  void Cancel() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_FILE_DIALOG_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/find_handler_ctocpp.cc b/src/libcef_dll/ctocpp/find_handler_ctocpp.cc
index a35094d..89b9b6b 100644
--- a/src/libcef_dll/ctocpp/find_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/find_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4899d7b77e91c0a5c46dad615f2e1b32f8077c40$
+// $hash=f39b33835f8368cc507c189fd54f63740b338f43$
 //
 
 #include "libcef_dll/ctocpp/find_handler_ctocpp.h"
@@ -28,15 +28,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_find_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_find_result))
+  if (CEF_MEMBER_MISSING(_struct, on_find_result)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_find_result(_struct, CefBrowserCppToC::Wrap(browser), identifier,
@@ -58,7 +60,7 @@
 cef_find_handler_t*
 CefCToCppRefCounted<CefFindHandlerCToCpp, CefFindHandler, cef_find_handler_t>::
     UnwrapDerived(CefWrapperType type, CefFindHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/find_handler_ctocpp.h b/src/libcef_dll/ctocpp/find_handler_ctocpp.h
index 2668638..98f75b2 100644
--- a/src/libcef_dll/ctocpp/find_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/find_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=5af48b5e0fa05de0b6b7bc31e2f4b1b2fa4c045b$
+// $hash=8b86bd425ab5e9283d8fc8ac96b54740bf495cbb$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_FIND_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/focus_handler_ctocpp.cc b/src/libcef_dll/ctocpp/focus_handler_ctocpp.cc
index 4a9575b..5e6eacc 100644
--- a/src/libcef_dll/ctocpp/focus_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/focus_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=14a73b2c762047ce55f3e40837050b5f5e950bac$
+// $hash=0fa4cd5767bcd31e0629bd625fb7e97811265fba$
 //
 
 #include "libcef_dll/ctocpp/focus_handler_ctocpp.h"
@@ -24,15 +24,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_focus_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_take_focus))
+  if (CEF_MEMBER_MISSING(_struct, on_take_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_take_focus(_struct, CefBrowserCppToC::Wrap(browser), next);
@@ -44,15 +46,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_focus_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_set_focus))
+  if (CEF_MEMBER_MISSING(_struct, on_set_focus)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -67,15 +71,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_focus_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_got_focus))
+  if (CEF_MEMBER_MISSING(_struct, on_got_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_got_focus(_struct, CefBrowserCppToC::Wrap(browser));
@@ -97,7 +103,7 @@
                     CefFocusHandler,
                     cef_focus_handler_t>::UnwrapDerived(CefWrapperType type,
                                                         CefFocusHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/focus_handler_ctocpp.h b/src/libcef_dll/ctocpp/focus_handler_ctocpp.h
index 66b4a29..6c0f922 100644
--- a/src/libcef_dll/ctocpp/focus_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/focus_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=31490e9d66718e2b1763e8016a6b4d39a1ad2947$
+// $hash=6a454cd9846e772380a72c5429d114f73cc3c1f5$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_FOCUS_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/frame_ctocpp.cc b/src/libcef_dll/ctocpp/frame_ctocpp.cc
index d197647..21849c9 100644
--- a/src/libcef_dll/ctocpp/frame_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/frame_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=180295a757845728ac0b6b2fd778e7a16574ab56$
+// $hash=52b39b5e284097cb9f674258a89680ca23adb2bb$
 //
 
 #include "libcef_dll/ctocpp/frame_ctocpp.h"
@@ -29,8 +29,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -45,8 +46,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, undo))
+  if (CEF_MEMBER_MISSING(_struct, undo)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -58,8 +60,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, redo))
+  if (CEF_MEMBER_MISSING(_struct, redo)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -71,8 +74,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cut))
+  if (CEF_MEMBER_MISSING(_struct, cut)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -84,8 +88,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, copy))
+  if (CEF_MEMBER_MISSING(_struct, copy)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -97,8 +102,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, paste))
+  if (CEF_MEMBER_MISSING(_struct, paste)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -110,8 +116,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, del))
+  if (CEF_MEMBER_MISSING(_struct, del)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -123,8 +130,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, select_all))
+  if (CEF_MEMBER_MISSING(_struct, select_all)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -136,8 +144,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, view_source))
+  if (CEF_MEMBER_MISSING(_struct, view_source)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -150,15 +159,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_source))
+  if (CEF_MEMBER_MISSING(_struct, get_source)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: visitor; type: refptr_diff
   DCHECK(visitor.get());
-  if (!visitor.get())
+  if (!visitor.get()) {
     return;
+  }
 
   // Execute
   _struct->get_source(_struct, CefStringVisitorCppToC::Wrap(visitor));
@@ -169,15 +180,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_text))
+  if (CEF_MEMBER_MISSING(_struct, get_text)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: visitor; type: refptr_diff
   DCHECK(visitor.get());
-  if (!visitor.get())
+  if (!visitor.get()) {
     return;
+  }
 
   // Execute
   _struct->get_text(_struct, CefStringVisitorCppToC::Wrap(visitor));
@@ -188,15 +201,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, load_request))
+  if (CEF_MEMBER_MISSING(_struct, load_request)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_same
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return;
+  }
 
   // Execute
   _struct->load_request(_struct, CefRequestCToCpp::Unwrap(request));
@@ -206,15 +221,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, load_url))
+  if (CEF_MEMBER_MISSING(_struct, load_url)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: url; type: string_byref_const
   DCHECK(!url.empty());
-  if (url.empty())
+  if (url.empty()) {
     return;
+  }
 
   // Execute
   _struct->load_url(_struct, url.GetStruct());
@@ -227,15 +244,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, execute_java_script))
+  if (CEF_MEMBER_MISSING(_struct, execute_java_script)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: code; type: string_byref_const
   DCHECK(!code.empty());
-  if (code.empty())
+  if (code.empty()) {
     return;
+  }
   // Unverified params: script_url
 
   // Execute
@@ -247,8 +266,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_main))
+  if (CEF_MEMBER_MISSING(_struct, is_main)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -263,8 +283,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_focused))
+  if (CEF_MEMBER_MISSING(_struct, is_focused)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -279,8 +300,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_name))
+  if (CEF_MEMBER_MISSING(_struct, get_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -293,17 +315,18 @@
   return _retvalStr;
 }
 
-NO_SANITIZE("cfi-icall") int64 CefFrameCToCpp::GetIdentifier() {
+NO_SANITIZE("cfi-icall") int64_t CefFrameCToCpp::GetIdentifier() {
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_identifier))
+  if (CEF_MEMBER_MISSING(_struct, get_identifier)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int64 _retval = _struct->get_identifier(_struct);
+  int64_t _retval = _struct->get_identifier(_struct);
 
   // Return type: simple
   return _retval;
@@ -313,8 +336,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_parent))
+  if (CEF_MEMBER_MISSING(_struct, get_parent)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -329,8 +353,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_url))
+  if (CEF_MEMBER_MISSING(_struct, get_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -347,8 +372,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_browser))
+  if (CEF_MEMBER_MISSING(_struct, get_browser)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -364,8 +390,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_v8context))
+  if (CEF_MEMBER_MISSING(_struct, get_v8context)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -381,15 +408,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, visit_dom))
+  if (CEF_MEMBER_MISSING(_struct, visit_dom)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: visitor; type: refptr_diff
   DCHECK(visitor.get());
-  if (!visitor.get())
+  if (!visitor.get()) {
     return;
+  }
 
   // Execute
   _struct->visit_dom(_struct, CefDOMVisitorCppToC::Wrap(visitor));
@@ -402,19 +431,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, create_urlrequest))
+  if (CEF_MEMBER_MISSING(_struct, create_urlrequest)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_same
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return nullptr;
+  }
   // Verify param: client; type: refptr_diff
   DCHECK(client.get());
-  if (!client.get())
+  if (!client.get()) {
     return nullptr;
+  }
 
   // Execute
   cef_urlrequest_t* _retval =
@@ -431,15 +463,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_process_message))
+  if (CEF_MEMBER_MISSING(_struct, send_process_message)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: message; type: refptr_same
   DCHECK(message.get());
-  if (!message.get())
+  if (!message.get()) {
     return;
+  }
 
   // Execute
   _struct->send_process_message(_struct, target_process,
@@ -461,7 +495,7 @@
 CefCToCppRefCounted<CefFrameCToCpp, CefFrame, cef_frame_t>::UnwrapDerived(
     CefWrapperType type,
     CefFrame* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/frame_ctocpp.h b/src/libcef_dll/ctocpp/frame_ctocpp.h
index a423b69..37ead05 100644
--- a/src/libcef_dll/ctocpp/frame_ctocpp.h
+++ b/src/libcef_dll/ctocpp/frame_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ddb09e01a1a6f2e928a2a3c414bef889adb7dc65$
+// $hash=6215ffe1d66a8b1fd9c9acbebfc792e5acc68490$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_FRAME_CTOCPP_H_
@@ -39,36 +39,36 @@
   virtual ~CefFrameCToCpp();
 
   // CefFrame methods.
-  bool IsValid() OVERRIDE;
-  void Undo() OVERRIDE;
-  void Redo() OVERRIDE;
-  void Cut() OVERRIDE;
-  void Copy() OVERRIDE;
-  void Paste() OVERRIDE;
-  void Delete() OVERRIDE;
-  void SelectAll() OVERRIDE;
-  void ViewSource() OVERRIDE;
-  void GetSource(CefRefPtr<CefStringVisitor> visitor) OVERRIDE;
-  void GetText(CefRefPtr<CefStringVisitor> visitor) OVERRIDE;
-  void LoadRequest(CefRefPtr<CefRequest> request) OVERRIDE;
-  void LoadURL(const CefString& url) OVERRIDE;
+  bool IsValid() override;
+  void Undo() override;
+  void Redo() override;
+  void Cut() override;
+  void Copy() override;
+  void Paste() override;
+  void Delete() override;
+  void SelectAll() override;
+  void ViewSource() override;
+  void GetSource(CefRefPtr<CefStringVisitor> visitor) override;
+  void GetText(CefRefPtr<CefStringVisitor> visitor) override;
+  void LoadRequest(CefRefPtr<CefRequest> request) override;
+  void LoadURL(const CefString& url) override;
   void ExecuteJavaScript(const CefString& code,
                          const CefString& script_url,
-                         int start_line) OVERRIDE;
-  bool IsMain() OVERRIDE;
-  bool IsFocused() OVERRIDE;
-  CefString GetName() OVERRIDE;
-  int64 GetIdentifier() OVERRIDE;
-  CefRefPtr<CefFrame> GetParent() OVERRIDE;
-  CefString GetURL() OVERRIDE;
-  CefRefPtr<CefBrowser> GetBrowser() OVERRIDE;
-  CefRefPtr<CefV8Context> GetV8Context() OVERRIDE;
-  void VisitDOM(CefRefPtr<CefDOMVisitor> visitor) OVERRIDE;
+                         int start_line) override;
+  bool IsMain() override;
+  bool IsFocused() override;
+  CefString GetName() override;
+  int64_t GetIdentifier() override;
+  CefRefPtr<CefFrame> GetParent() override;
+  CefString GetURL() override;
+  CefRefPtr<CefBrowser> GetBrowser() override;
+  CefRefPtr<CefV8Context> GetV8Context() override;
+  void VisitDOM(CefRefPtr<CefDOMVisitor> visitor) override;
   CefRefPtr<CefURLRequest> CreateURLRequest(
       CefRefPtr<CefRequest> request,
-      CefRefPtr<CefURLRequestClient> client) OVERRIDE;
+      CefRefPtr<CefURLRequestClient> client) override;
   void SendProcessMessage(CefProcessId target_process,
-                          CefRefPtr<CefProcessMessage> message) OVERRIDE;
+                          CefRefPtr<CefProcessMessage> message) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_FRAME_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/frame_handler_ctocpp.cc b/src/libcef_dll/ctocpp/frame_handler_ctocpp.cc
new file mode 100644
index 0000000..eb2a809
--- /dev/null
+++ b/src/libcef_dll/ctocpp/frame_handler_ctocpp.cc
@@ -0,0 +1,157 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=7556f5356f91f554c88cadd534f2260081b23e39$
+//
+
+#include "libcef_dll/ctocpp/frame_handler_ctocpp.h"
+#include "libcef_dll/cpptoc/browser_cpptoc.h"
+#include "libcef_dll/cpptoc/frame_cpptoc.h"
+#include "libcef_dll/shutdown_checker.h"
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall")
+void CefFrameHandlerCToCpp::OnFrameCreated(CefRefPtr<CefBrowser> browser,
+                                           CefRefPtr<CefFrame> frame) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_frame_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_frame_created)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return;
+  }
+  // Verify param: frame; type: refptr_diff
+  DCHECK(frame.get());
+  if (!frame.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_frame_created(_struct, CefBrowserCppToC::Wrap(browser),
+                            CefFrameCppToC::Wrap(frame));
+}
+
+NO_SANITIZE("cfi-icall")
+void CefFrameHandlerCToCpp::OnFrameAttached(CefRefPtr<CefBrowser> browser,
+                                            CefRefPtr<CefFrame> frame,
+                                            bool reattached) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_frame_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_frame_attached)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return;
+  }
+  // Verify param: frame; type: refptr_diff
+  DCHECK(frame.get());
+  if (!frame.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_frame_attached(_struct, CefBrowserCppToC::Wrap(browser),
+                             CefFrameCppToC::Wrap(frame), reattached);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefFrameHandlerCToCpp::OnFrameDetached(CefRefPtr<CefBrowser> browser,
+                                            CefRefPtr<CefFrame> frame) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_frame_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_frame_detached)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return;
+  }
+  // Verify param: frame; type: refptr_diff
+  DCHECK(frame.get());
+  if (!frame.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_frame_detached(_struct, CefBrowserCppToC::Wrap(browser),
+                             CefFrameCppToC::Wrap(frame));
+}
+
+NO_SANITIZE("cfi-icall")
+void CefFrameHandlerCToCpp::OnMainFrameChanged(CefRefPtr<CefBrowser> browser,
+                                               CefRefPtr<CefFrame> old_frame,
+                                               CefRefPtr<CefFrame> new_frame) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_frame_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_main_frame_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return;
+  }
+  // Unverified params: old_frame, new_frame
+
+  // Execute
+  _struct->on_main_frame_changed(_struct, CefBrowserCppToC::Wrap(browser),
+                                 CefFrameCppToC::Wrap(old_frame),
+                                 CefFrameCppToC::Wrap(new_frame));
+}
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefFrameHandlerCToCpp::CefFrameHandlerCToCpp() {}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefFrameHandlerCToCpp::~CefFrameHandlerCToCpp() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+cef_frame_handler_t*
+CefCToCppRefCounted<CefFrameHandlerCToCpp,
+                    CefFrameHandler,
+                    cef_frame_handler_t>::UnwrapDerived(CefWrapperType type,
+                                                        CefFrameHandler* c) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCToCppRefCounted<CefFrameHandlerCToCpp,
+                                   CefFrameHandler,
+                                   cef_frame_handler_t>::kWrapperType =
+    WT_FRAME_HANDLER;
diff --git a/src/libcef_dll/ctocpp/frame_handler_ctocpp.h b/src/libcef_dll/ctocpp/frame_handler_ctocpp.h
new file mode 100644
index 0000000..be28fb8
--- /dev/null
+++ b/src/libcef_dll/ctocpp/frame_handler_ctocpp.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=a1366f78329888eadf9121d7df819687d82a40c7$
+//
+
+#ifndef CEF_LIBCEF_DLL_CTOCPP_FRAME_HANDLER_CTOCPP_H_
+#define CEF_LIBCEF_DLL_CTOCPP_FRAME_HANDLER_CTOCPP_H_
+#pragma once
+
+#if !defined(BUILDING_CEF_SHARED)
+#error This file can be included DLL-side only
+#endif
+
+#include "include/capi/cef_frame_handler_capi.h"
+#include "include/cef_frame_handler.h"
+#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
+
+// Wrap a C structure with a C++ class.
+// This class may be instantiated and accessed DLL-side only.
+class CefFrameHandlerCToCpp : public CefCToCppRefCounted<CefFrameHandlerCToCpp,
+                                                         CefFrameHandler,
+                                                         cef_frame_handler_t> {
+ public:
+  CefFrameHandlerCToCpp();
+  virtual ~CefFrameHandlerCToCpp();
+
+  // CefFrameHandler methods.
+  void OnFrameCreated(CefRefPtr<CefBrowser> browser,
+                      CefRefPtr<CefFrame> frame) override;
+  void OnFrameAttached(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame,
+                       bool reattached) override;
+  void OnFrameDetached(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame) override;
+  void OnMainFrameChanged(CefRefPtr<CefBrowser> browser,
+                          CefRefPtr<CefFrame> old_frame,
+                          CefRefPtr<CefFrame> new_frame) override;
+};
+
+#endif  // CEF_LIBCEF_DLL_CTOCPP_FRAME_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/get_extension_resource_callback_ctocpp.cc b/src/libcef_dll/ctocpp/get_extension_resource_callback_ctocpp.cc
index fa79122..d0129a1 100644
--- a/src/libcef_dll/ctocpp/get_extension_resource_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/get_extension_resource_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c36d12cf40153d3c86ee21e31a3b29a0f01146fc$
+// $hash=5327e7e6f275416ba3e88025691c75dedcee72ef$
 //
 
 #include "libcef_dll/ctocpp/get_extension_resource_callback_ctocpp.h"
@@ -24,8 +24,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_get_extension_resource_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cont))
+  if (CEF_MEMBER_MISSING(_struct, cont)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -39,8 +40,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_get_extension_resource_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cancel))
+  if (CEF_MEMBER_MISSING(_struct, cancel)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -66,7 +68,7 @@
                     CefGetExtensionResourceCallback,
                     cef_get_extension_resource_callback_t>::
     UnwrapDerived(CefWrapperType type, CefGetExtensionResourceCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/get_extension_resource_callback_ctocpp.h b/src/libcef_dll/ctocpp/get_extension_resource_callback_ctocpp.h
index 7d07e0f..afebabd 100644
--- a/src/libcef_dll/ctocpp/get_extension_resource_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/get_extension_resource_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7eea721db8dde8bc9d2b4d47b63b07ab41f91591$
+// $hash=fd92d3650c1f3f04b84d9a0847631463b9e9ca2c$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_GET_EXTENSION_RESOURCE_CALLBACK_CTOCPP_H_
@@ -37,8 +37,8 @@
   virtual ~CefGetExtensionResourceCallbackCToCpp();
 
   // CefGetExtensionResourceCallback methods.
-  void Continue(CefRefPtr<CefStreamReader> stream) OVERRIDE;
-  void Cancel() OVERRIDE;
+  void Continue(CefRefPtr<CefStreamReader> stream) override;
+  void Cancel() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_GET_EXTENSION_RESOURCE_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/image_ctocpp.cc b/src/libcef_dll/ctocpp/image_ctocpp.cc
index c578170..b52d5ca 100644
--- a/src/libcef_dll/ctocpp/image_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/image_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=bf467f48bb553cc7308bce0fd74d3dcedaf8b8ad$
+// $hash=feca0218f8ab6da39dcf3db81d3d3b36fcb7f27d$
 //
 
 #include "libcef_dll/ctocpp/image_ctocpp.h"
@@ -36,8 +36,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_image_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_empty))
+  if (CEF_MEMBER_MISSING(_struct, is_empty)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -52,15 +53,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_image_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefImageCToCpp::Unwrap(that));
@@ -80,15 +83,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_image_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, add_bitmap))
+  if (CEF_MEMBER_MISSING(_struct, add_bitmap)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: pixel_data; type: simple_byaddr
   DCHECK(pixel_data);
-  if (!pixel_data)
+  if (!pixel_data) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -106,15 +111,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_image_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, add_png))
+  if (CEF_MEMBER_MISSING(_struct, add_png)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: png_data; type: simple_byaddr
   DCHECK(png_data);
-  if (!png_data)
+  if (!png_data) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -131,15 +138,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_image_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, add_jpeg))
+  if (CEF_MEMBER_MISSING(_struct, add_jpeg)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: jpeg_data; type: simple_byaddr
   DCHECK(jpeg_data);
-  if (!jpeg_data)
+  if (!jpeg_data) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -153,8 +162,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_image_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_width))
+  if (CEF_MEMBER_MISSING(_struct, get_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -169,8 +179,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_image_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_height))
+  if (CEF_MEMBER_MISSING(_struct, get_height)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -186,8 +197,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_image_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_representation))
+  if (CEF_MEMBER_MISSING(_struct, has_representation)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -203,8 +215,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_image_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, remove_representation))
+  if (CEF_MEMBER_MISSING(_struct, remove_representation)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -223,8 +236,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_image_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_representation_info))
+  if (CEF_MEMBER_MISSING(_struct, get_representation_info)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -246,8 +260,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_image_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_as_bitmap))
+  if (CEF_MEMBER_MISSING(_struct, get_as_bitmap)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -268,8 +283,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_image_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_as_png))
+  if (CEF_MEMBER_MISSING(_struct, get_as_png)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -289,8 +305,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_image_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_as_jpeg))
+  if (CEF_MEMBER_MISSING(_struct, get_as_jpeg)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -317,7 +334,7 @@
 CefCToCppRefCounted<CefImageCToCpp, CefImage, cef_image_t>::UnwrapDerived(
     CefWrapperType type,
     CefImage* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/image_ctocpp.h b/src/libcef_dll/ctocpp/image_ctocpp.h
index c2e3586..8d635fd 100644
--- a/src/libcef_dll/ctocpp/image_ctocpp.h
+++ b/src/libcef_dll/ctocpp/image_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=63b29975a77c78b9961af9eb88ddc67dd79e32a4$
+// $hash=13afe421110fa07e94c1724d21302b018a71a633$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_IMAGE_CTOCPP_H_
@@ -33,42 +33,42 @@
   virtual ~CefImageCToCpp();
 
   // CefImage methods.
-  bool IsEmpty() OVERRIDE;
-  bool IsSame(CefRefPtr<CefImage> that) OVERRIDE;
+  bool IsEmpty() override;
+  bool IsSame(CefRefPtr<CefImage> that) override;
   bool AddBitmap(float scale_factor,
                  int pixel_width,
                  int pixel_height,
                  cef_color_type_t color_type,
                  cef_alpha_type_t alpha_type,
                  const void* pixel_data,
-                 size_t pixel_data_size) OVERRIDE;
+                 size_t pixel_data_size) override;
   bool AddPNG(float scale_factor,
               const void* png_data,
-              size_t png_data_size) OVERRIDE;
+              size_t png_data_size) override;
   bool AddJPEG(float scale_factor,
                const void* jpeg_data,
-               size_t jpeg_data_size) OVERRIDE;
-  size_t GetWidth() OVERRIDE;
-  size_t GetHeight() OVERRIDE;
-  bool HasRepresentation(float scale_factor) OVERRIDE;
-  bool RemoveRepresentation(float scale_factor) OVERRIDE;
+               size_t jpeg_data_size) override;
+  size_t GetWidth() override;
+  size_t GetHeight() override;
+  bool HasRepresentation(float scale_factor) override;
+  bool RemoveRepresentation(float scale_factor) override;
   bool GetRepresentationInfo(float scale_factor,
                              float& actual_scale_factor,
                              int& pixel_width,
-                             int& pixel_height) OVERRIDE;
+                             int& pixel_height) override;
   CefRefPtr<CefBinaryValue> GetAsBitmap(float scale_factor,
                                         cef_color_type_t color_type,
                                         cef_alpha_type_t alpha_type,
                                         int& pixel_width,
-                                        int& pixel_height) OVERRIDE;
+                                        int& pixel_height) override;
   CefRefPtr<CefBinaryValue> GetAsPNG(float scale_factor,
                                      bool with_transparency,
                                      int& pixel_width,
-                                     int& pixel_height) OVERRIDE;
+                                     int& pixel_height) override;
   CefRefPtr<CefBinaryValue> GetAsJPEG(float scale_factor,
                                       int quality,
                                       int& pixel_width,
-                                      int& pixel_height) OVERRIDE;
+                                      int& pixel_height) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_IMAGE_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc b/src/libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc
index 2eef937..0fd0f34 100644
--- a/src/libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=07dbe8f9680d767646cafcdaa5e790003d059cf5$
+// $hash=28d076cb242561f0c5de9b0274f7af860b152119$
 //
 
 #include "libcef_dll/ctocpp/jsdialog_callback_ctocpp.h"
@@ -23,8 +23,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_jsdialog_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cont))
+  if (CEF_MEMBER_MISSING(_struct, cont)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -50,7 +51,7 @@
     CefJSDialogCallback,
     cef_jsdialog_callback_t>::UnwrapDerived(CefWrapperType type,
                                             CefJSDialogCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/jsdialog_callback_ctocpp.h b/src/libcef_dll/ctocpp/jsdialog_callback_ctocpp.h
index b08bf7e..a73df8a 100644
--- a/src/libcef_dll/ctocpp/jsdialog_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/jsdialog_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8fd698821e3a1a621a19a0e650d5c31eb90013fb$
+// $hash=5e91e201bc50f771d1ded89088fffcb0da8d34d7$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_JSDIALOG_CALLBACK_CTOCPP_H_
@@ -35,7 +35,7 @@
   virtual ~CefJSDialogCallbackCToCpp();
 
   // CefJSDialogCallback methods.
-  void Continue(bool success, const CefString& user_input) OVERRIDE;
+  void Continue(bool success, const CefString& user_input) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_JSDIALOG_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc b/src/libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc
index 6d28bd1..20d41aa 100644
--- a/src/libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c3d58fe1274c19d04eb2ef801747b1f2012b86ce$
+// $hash=329506b8051faec631eb200b1a0b8da46bcb4185$
 //
 
 #include "libcef_dll/ctocpp/jsdialog_handler_ctocpp.h"
@@ -31,19 +31,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_jsdialog_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_jsdialog))
+  if (CEF_MEMBER_MISSING(_struct, on_jsdialog)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return false;
+  }
   // Unverified params: origin_url, message_text, default_prompt_text
 
   // Translate param: suppress_message; type: bool_byref
@@ -71,19 +74,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_jsdialog_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_before_unload_dialog))
+  if (CEF_MEMBER_MISSING(_struct, on_before_unload_dialog)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return false;
+  }
   // Unverified params: message_text
 
   // Execute
@@ -101,15 +107,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_jsdialog_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_reset_dialog_state))
+  if (CEF_MEMBER_MISSING(_struct, on_reset_dialog_state)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_reset_dialog_state(_struct, CefBrowserCppToC::Wrap(browser));
@@ -120,15 +128,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_jsdialog_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_dialog_closed))
+  if (CEF_MEMBER_MISSING(_struct, on_dialog_closed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_dialog_closed(_struct, CefBrowserCppToC::Wrap(browser));
@@ -150,7 +160,7 @@
     CefJSDialogHandler,
     cef_jsdialog_handler_t>::UnwrapDerived(CefWrapperType type,
                                            CefJSDialogHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/jsdialog_handler_ctocpp.h b/src/libcef_dll/ctocpp/jsdialog_handler_ctocpp.h
index 2707864..740330b 100644
--- a/src/libcef_dll/ctocpp/jsdialog_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/jsdialog_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b24b389259c2ddfb2881760280a94759f4d3b636$
+// $hash=55b3bcb925cfaf44f79c0e03fc55878d748f55ce$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_JSDIALOG_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/keyboard_handler_ctocpp.cc b/src/libcef_dll/ctocpp/keyboard_handler_ctocpp.cc
index b81a87b..7c4d878 100644
--- a/src/libcef_dll/ctocpp/keyboard_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/keyboard_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=853cd02f42c843f486d936058a0f012d6099834c$
+// $hash=0fc307ce2060ccf455514543b4dfd694300cf79a$
 //
 
 #include "libcef_dll/ctocpp/keyboard_handler_ctocpp.h"
@@ -26,19 +26,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_keyboard_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_pre_key_event))
+  if (CEF_MEMBER_MISSING(_struct, on_pre_key_event)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: is_keyboard_shortcut; type: bool_byaddr
   DCHECK(is_keyboard_shortcut);
-  if (!is_keyboard_shortcut)
+  if (!is_keyboard_shortcut) {
     return false;
+  }
 
   // Translate param: is_keyboard_shortcut; type: bool_byaddr
   int is_keyboard_shortcutInt =
@@ -50,8 +53,9 @@
                                 &event, os_event, &is_keyboard_shortcutInt);
 
   // Restore param:is_keyboard_shortcut; type: bool_byaddr
-  if (is_keyboard_shortcut)
+  if (is_keyboard_shortcut) {
     *is_keyboard_shortcut = is_keyboard_shortcutInt ? true : false;
+  }
 
   // Return type: bool
   return _retval ? true : false;
@@ -64,15 +68,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_keyboard_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_key_event))
+  if (CEF_MEMBER_MISSING(_struct, on_key_event)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->on_key_event(_struct, CefBrowserCppToC::Wrap(browser),
@@ -98,7 +104,7 @@
     CefKeyboardHandler,
     cef_keyboard_handler_t>::UnwrapDerived(CefWrapperType type,
                                            CefKeyboardHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/keyboard_handler_ctocpp.h b/src/libcef_dll/ctocpp/keyboard_handler_ctocpp.h
index c5cfae6..65c681e 100644
--- a/src/libcef_dll/ctocpp/keyboard_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/keyboard_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=813bbfd94f49935fcce61d26ed9351b6e89f2a58$
+// $hash=a25080ecb1a098b748d8384bc5af591ea773deff$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_KEYBOARD_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/life_span_handler_ctocpp.cc b/src/libcef_dll/ctocpp/life_span_handler_ctocpp.cc
index 4afdd9b..e07ed00 100644
--- a/src/libcef_dll/ctocpp/life_span_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/life_span_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=243cd9194d5b67b3ba35ae8b3f7c58588c0ccebb$
+// $hash=d85695db88a025b1f7e4e4604f3085da29d5eabf$
 //
 
 #include "libcef_dll/ctocpp/life_span_handler_ctocpp.h"
@@ -38,34 +38,40 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_life_span_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_before_popup))
+  if (CEF_MEMBER_MISSING(_struct, on_before_popup)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return false;
+  }
   // Verify param: no_javascript_access; type: bool_byaddr
   DCHECK(no_javascript_access);
-  if (!no_javascript_access)
+  if (!no_javascript_access) {
     return false;
+  }
   // Unverified params: target_url, target_frame_name
 
   // Translate param: client; type: refptr_same_byref
   cef_client_t* clientStruct = NULL;
-  if (client.get())
+  if (client.get()) {
     clientStruct = CefClientCToCpp::Unwrap(client);
+  }
   cef_client_t* clientOrig = clientStruct;
   // Translate param: extra_info; type: refptr_diff_byref
   cef_dictionary_value_t* extra_infoStruct = NULL;
-  if (extra_info.get())
+  if (extra_info.get()) {
     extra_infoStruct = CefDictionaryValueCppToC::Wrap(extra_info);
+  }
   cef_dictionary_value_t* extra_infoOrig = extra_infoStruct;
   // Translate param: no_javascript_access; type: bool_byaddr
   int no_javascript_accessInt =
@@ -95,27 +101,100 @@
     extra_info = nullptr;
   }
   // Restore param:no_javascript_access; type: bool_byaddr
-  if (no_javascript_access)
+  if (no_javascript_access) {
     *no_javascript_access = no_javascript_accessInt ? true : false;
+  }
 
   // Return type: bool
   return _retval ? true : false;
 }
 
 NO_SANITIZE("cfi-icall")
+void CefLifeSpanHandlerCToCpp::OnBeforeDevToolsPopup(
+    CefRefPtr<CefBrowser> browser,
+    CefWindowInfo& windowInfo,
+    CefRefPtr<CefClient>& client,
+    CefBrowserSettings& settings,
+    CefRefPtr<CefDictionaryValue>& extra_info,
+    bool* use_default_window) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_life_span_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_before_dev_tools_popup)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return;
+  }
+  // Verify param: use_default_window; type: bool_byaddr
+  DCHECK(use_default_window);
+  if (!use_default_window) {
+    return;
+  }
+
+  // Translate param: client; type: refptr_same_byref
+  cef_client_t* clientStruct = NULL;
+  if (client.get()) {
+    clientStruct = CefClientCToCpp::Unwrap(client);
+  }
+  cef_client_t* clientOrig = clientStruct;
+  // Translate param: extra_info; type: refptr_diff_byref
+  cef_dictionary_value_t* extra_infoStruct = NULL;
+  if (extra_info.get()) {
+    extra_infoStruct = CefDictionaryValueCppToC::Wrap(extra_info);
+  }
+  cef_dictionary_value_t* extra_infoOrig = extra_infoStruct;
+  // Translate param: use_default_window; type: bool_byaddr
+  int use_default_windowInt = use_default_window ? *use_default_window : 0;
+
+  // Execute
+  _struct->on_before_dev_tools_popup(_struct, CefBrowserCppToC::Wrap(browser),
+                                     &windowInfo, &clientStruct, &settings,
+                                     &extra_infoStruct, &use_default_windowInt);
+
+  // Restore param:client; type: refptr_same_byref
+  if (clientStruct) {
+    if (clientStruct != clientOrig) {
+      client = CefClientCToCpp::Wrap(clientStruct);
+    }
+  } else {
+    client = nullptr;
+  }
+  // Restore param:extra_info; type: refptr_diff_byref
+  if (extra_infoStruct) {
+    if (extra_infoStruct != extra_infoOrig) {
+      extra_info = CefDictionaryValueCppToC::Unwrap(extra_infoStruct);
+    }
+  } else {
+    extra_info = nullptr;
+  }
+  // Restore param:use_default_window; type: bool_byaddr
+  if (use_default_window) {
+    *use_default_window = use_default_windowInt ? true : false;
+  }
+}
+
+NO_SANITIZE("cfi-icall")
 void CefLifeSpanHandlerCToCpp::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
   shutdown_checker::AssertNotShutdown();
 
   cef_life_span_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_after_created))
+  if (CEF_MEMBER_MISSING(_struct, on_after_created)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_after_created(_struct, CefBrowserCppToC::Wrap(browser));
@@ -126,15 +205,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_life_span_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, do_close))
+  if (CEF_MEMBER_MISSING(_struct, do_close)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->do_close(_struct, CefBrowserCppToC::Wrap(browser));
@@ -148,15 +229,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_life_span_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_before_close))
+  if (CEF_MEMBER_MISSING(_struct, on_before_close)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_before_close(_struct, CefBrowserCppToC::Wrap(browser));
@@ -178,7 +261,7 @@
     CefLifeSpanHandler,
     cef_life_span_handler_t>::UnwrapDerived(CefWrapperType type,
                                             CefLifeSpanHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/life_span_handler_ctocpp.h b/src/libcef_dll/ctocpp/life_span_handler_ctocpp.h
index dcf1e18..dc0995a 100644
--- a/src/libcef_dll/ctocpp/life_span_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/life_span_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2163444626efca350f6377da7fbce6e2d2291ca4$
+// $hash=53f00e60e361c79c69a8f19474a234d5011454f5$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_LIFE_SPAN_HANDLER_CTOCPP_H_
@@ -49,6 +49,12 @@
                      CefBrowserSettings& settings,
                      CefRefPtr<CefDictionaryValue>& extra_info,
                      bool* no_javascript_access) override;
+  void OnBeforeDevToolsPopup(CefRefPtr<CefBrowser> browser,
+                             CefWindowInfo& windowInfo,
+                             CefRefPtr<CefClient>& client,
+                             CefBrowserSettings& settings,
+                             CefRefPtr<CefDictionaryValue>& extra_info,
+                             bool* use_default_window) override;
   void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
   bool DoClose(CefRefPtr<CefBrowser> browser) override;
   void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
diff --git a/src/libcef_dll/ctocpp/list_value_ctocpp.cc b/src/libcef_dll/ctocpp/list_value_ctocpp.cc
index 1c3e9d1..3e43ac9 100644
--- a/src/libcef_dll/ctocpp/list_value_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/list_value_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b4d3794c5760e7d21e00accfc8e3c260e5bd3e1d$
+// $hash=5b2b8bab4a1dc4d4f26918156aaad2ee4c3caf4a$
 //
 
 #include "libcef_dll/ctocpp/list_value_ctocpp.h"
@@ -38,8 +38,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -54,8 +55,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_owned))
+  if (CEF_MEMBER_MISSING(_struct, is_owned)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -70,8 +72,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_read_only))
+  if (CEF_MEMBER_MISSING(_struct, is_read_only)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -87,15 +90,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefListValueCToCpp::Unwrap(that));
@@ -109,15 +114,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_equal))
+  if (CEF_MEMBER_MISSING(_struct, is_equal)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_equal(_struct, CefListValueCToCpp::Unwrap(that));
@@ -130,8 +137,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, copy))
+  if (CEF_MEMBER_MISSING(_struct, copy)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -146,8 +154,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_size))
+  if (CEF_MEMBER_MISSING(_struct, set_size)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -162,8 +171,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_size))
+  if (CEF_MEMBER_MISSING(_struct, get_size)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -178,8 +188,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, clear))
+  if (CEF_MEMBER_MISSING(_struct, clear)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -194,8 +205,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, remove))
+  if (CEF_MEMBER_MISSING(_struct, remove)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -211,8 +223,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_type))
+  if (CEF_MEMBER_MISSING(_struct, get_type)) {
     return VTYPE_INVALID;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -228,8 +241,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_value))
+  if (CEF_MEMBER_MISSING(_struct, get_value)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -244,8 +258,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_bool))
+  if (CEF_MEMBER_MISSING(_struct, get_bool)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -260,8 +275,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_int))
+  if (CEF_MEMBER_MISSING(_struct, get_int)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -276,8 +292,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_double))
+  if (CEF_MEMBER_MISSING(_struct, get_double)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -292,8 +309,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_string))
+  if (CEF_MEMBER_MISSING(_struct, get_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -311,8 +329,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_binary))
+  if (CEF_MEMBER_MISSING(_struct, get_binary)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -328,8 +347,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_dictionary))
+  if (CEF_MEMBER_MISSING(_struct, get_dictionary)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -345,8 +365,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_list))
+  if (CEF_MEMBER_MISSING(_struct, get_list)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -362,15 +383,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_value))
+  if (CEF_MEMBER_MISSING(_struct, set_value)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: value; type: refptr_same
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -384,8 +407,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_null))
+  if (CEF_MEMBER_MISSING(_struct, set_null)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -401,8 +425,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_bool))
+  if (CEF_MEMBER_MISSING(_struct, set_bool)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -418,8 +443,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_int))
+  if (CEF_MEMBER_MISSING(_struct, set_int)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -435,8 +461,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_double))
+  if (CEF_MEMBER_MISSING(_struct, set_double)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -452,8 +479,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_string))
+  if (CEF_MEMBER_MISSING(_struct, set_string)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -472,15 +500,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_binary))
+  if (CEF_MEMBER_MISSING(_struct, set_binary)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: value; type: refptr_same
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -496,15 +526,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_dictionary))
+  if (CEF_MEMBER_MISSING(_struct, set_dictionary)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: value; type: refptr_same
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_dictionary(
@@ -519,15 +551,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_list_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_list))
+  if (CEF_MEMBER_MISSING(_struct, set_list)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: value; type: refptr_same
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -551,7 +585,7 @@
 cef_list_value_t*
 CefCToCppRefCounted<CefListValueCToCpp, CefListValue, cef_list_value_t>::
     UnwrapDerived(CefWrapperType type, CefListValue* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/list_value_ctocpp.h b/src/libcef_dll/ctocpp/list_value_ctocpp.h
index e505aa3..d09dfb9 100644
--- a/src/libcef_dll/ctocpp/list_value_ctocpp.h
+++ b/src/libcef_dll/ctocpp/list_value_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4e5f157e3be26a5111877cfd083be887bfc0de45$
+// $hash=99b478c698261aa2aaf566b283fc938aacf3b2bf$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_LIST_VALUE_CTOCPP_H_
@@ -34,35 +34,35 @@
   virtual ~CefListValueCToCpp();
 
   // CefListValue methods.
-  bool IsValid() OVERRIDE;
-  bool IsOwned() OVERRIDE;
-  bool IsReadOnly() OVERRIDE;
-  bool IsSame(CefRefPtr<CefListValue> that) OVERRIDE;
-  bool IsEqual(CefRefPtr<CefListValue> that) OVERRIDE;
-  CefRefPtr<CefListValue> Copy() OVERRIDE;
-  bool SetSize(size_t size) OVERRIDE;
-  size_t GetSize() OVERRIDE;
-  bool Clear() OVERRIDE;
-  bool Remove(size_t index) OVERRIDE;
-  CefValueType GetType(size_t index) OVERRIDE;
-  CefRefPtr<CefValue> GetValue(size_t index) OVERRIDE;
-  bool GetBool(size_t index) OVERRIDE;
-  int GetInt(size_t index) OVERRIDE;
-  double GetDouble(size_t index) OVERRIDE;
-  CefString GetString(size_t index) OVERRIDE;
-  CefRefPtr<CefBinaryValue> GetBinary(size_t index) OVERRIDE;
-  CefRefPtr<CefDictionaryValue> GetDictionary(size_t index) OVERRIDE;
-  CefRefPtr<CefListValue> GetList(size_t index) OVERRIDE;
-  bool SetValue(size_t index, CefRefPtr<CefValue> value) OVERRIDE;
-  bool SetNull(size_t index) OVERRIDE;
-  bool SetBool(size_t index, bool value) OVERRIDE;
-  bool SetInt(size_t index, int value) OVERRIDE;
-  bool SetDouble(size_t index, double value) OVERRIDE;
-  bool SetString(size_t index, const CefString& value) OVERRIDE;
-  bool SetBinary(size_t index, CefRefPtr<CefBinaryValue> value) OVERRIDE;
+  bool IsValid() override;
+  bool IsOwned() override;
+  bool IsReadOnly() override;
+  bool IsSame(CefRefPtr<CefListValue> that) override;
+  bool IsEqual(CefRefPtr<CefListValue> that) override;
+  CefRefPtr<CefListValue> Copy() override;
+  bool SetSize(size_t size) override;
+  size_t GetSize() override;
+  bool Clear() override;
+  bool Remove(size_t index) override;
+  CefValueType GetType(size_t index) override;
+  CefRefPtr<CefValue> GetValue(size_t index) override;
+  bool GetBool(size_t index) override;
+  int GetInt(size_t index) override;
+  double GetDouble(size_t index) override;
+  CefString GetString(size_t index) override;
+  CefRefPtr<CefBinaryValue> GetBinary(size_t index) override;
+  CefRefPtr<CefDictionaryValue> GetDictionary(size_t index) override;
+  CefRefPtr<CefListValue> GetList(size_t index) override;
+  bool SetValue(size_t index, CefRefPtr<CefValue> value) override;
+  bool SetNull(size_t index) override;
+  bool SetBool(size_t index, bool value) override;
+  bool SetInt(size_t index, int value) override;
+  bool SetDouble(size_t index, double value) override;
+  bool SetString(size_t index, const CefString& value) override;
+  bool SetBinary(size_t index, CefRefPtr<CefBinaryValue> value) override;
   bool SetDictionary(size_t index,
-                     CefRefPtr<CefDictionaryValue> value) OVERRIDE;
-  bool SetList(size_t index, CefRefPtr<CefListValue> value) OVERRIDE;
+                     CefRefPtr<CefDictionaryValue> value) override;
+  bool SetList(size_t index, CefRefPtr<CefListValue> value) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_LIST_VALUE_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/load_handler_ctocpp.cc b/src/libcef_dll/ctocpp/load_handler_ctocpp.cc
index f96f9d5..d9eec1a 100644
--- a/src/libcef_dll/ctocpp/load_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/load_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=07a706c04c5b002b645d0c898249343d7e7ae442$
+// $hash=cf0d34b49335d629c3cc9d8420cc834cb0430fe4$
 //
 
 #include "libcef_dll/ctocpp/load_handler_ctocpp.h"
@@ -27,15 +27,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_load_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_loading_state_change))
+  if (CEF_MEMBER_MISSING(_struct, on_loading_state_change)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_loading_state_change(_struct, CefBrowserCppToC::Wrap(browser),
@@ -49,19 +51,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_load_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_load_start))
+  if (CEF_MEMBER_MISSING(_struct, on_load_start)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return;
+  }
 
   // Execute
   _struct->on_load_start(_struct, CefBrowserCppToC::Wrap(browser),
@@ -75,19 +80,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_load_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_load_end))
+  if (CEF_MEMBER_MISSING(_struct, on_load_end)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return;
+  }
 
   // Execute
   _struct->on_load_end(_struct, CefBrowserCppToC::Wrap(browser),
@@ -103,23 +111,27 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_load_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_load_error))
+  if (CEF_MEMBER_MISSING(_struct, on_load_error)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return;
+  }
   // Verify param: failedUrl; type: string_byref_const
   DCHECK(!failedUrl.empty());
-  if (failedUrl.empty())
+  if (failedUrl.empty()) {
     return;
+  }
   // Unverified params: errorText
 
   // Execute
@@ -142,7 +154,7 @@
 cef_load_handler_t*
 CefCToCppRefCounted<CefLoadHandlerCToCpp, CefLoadHandler, cef_load_handler_t>::
     UnwrapDerived(CefWrapperType type, CefLoadHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/load_handler_ctocpp.h b/src/libcef_dll/ctocpp/load_handler_ctocpp.h
index 6f6aa2e..8a6bbff 100644
--- a/src/libcef_dll/ctocpp/load_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/load_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=22460d6f937eddf1ec07dcea2325bba205101d47$
+// $hash=d05ba1799ed6cc227ab5d314ce8a96187b7a3069$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_LOAD_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/media_access_callback_ctocpp.cc b/src/libcef_dll/ctocpp/media_access_callback_ctocpp.cc
new file mode 100644
index 0000000..5efbed0
--- /dev/null
+++ b/src/libcef_dll/ctocpp/media_access_callback_ctocpp.cc
@@ -0,0 +1,73 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=cc22e20810193cde875d9aa027dc140639060787$
+//
+
+#include "libcef_dll/ctocpp/media_access_callback_ctocpp.h"
+#include "libcef_dll/shutdown_checker.h"
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall")
+void CefMediaAccessCallbackCToCpp::Continue(uint32_t allowed_permissions) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_media_access_callback_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, cont)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->cont(_struct, allowed_permissions);
+}
+
+NO_SANITIZE("cfi-icall") void CefMediaAccessCallbackCToCpp::Cancel() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_media_access_callback_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, cancel)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->cancel(_struct);
+}
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefMediaAccessCallbackCToCpp::CefMediaAccessCallbackCToCpp() {}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefMediaAccessCallbackCToCpp::~CefMediaAccessCallbackCToCpp() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+cef_media_access_callback_t* CefCToCppRefCounted<
+    CefMediaAccessCallbackCToCpp,
+    CefMediaAccessCallback,
+    cef_media_access_callback_t>::UnwrapDerived(CefWrapperType type,
+                                                CefMediaAccessCallback* c) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCToCppRefCounted<CefMediaAccessCallbackCToCpp,
+                                   CefMediaAccessCallback,
+                                   cef_media_access_callback_t>::kWrapperType =
+    WT_MEDIA_ACCESS_CALLBACK;
diff --git a/src/libcef_dll/ctocpp/media_access_callback_ctocpp.h b/src/libcef_dll/ctocpp/media_access_callback_ctocpp.h
new file mode 100644
index 0000000..b590937
--- /dev/null
+++ b/src/libcef_dll/ctocpp/media_access_callback_ctocpp.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=36268cf93134620f9e6e79c4fc96c67cb8fa9570$
+//
+
+#ifndef CEF_LIBCEF_DLL_CTOCPP_MEDIA_ACCESS_CALLBACK_CTOCPP_H_
+#define CEF_LIBCEF_DLL_CTOCPP_MEDIA_ACCESS_CALLBACK_CTOCPP_H_
+#pragma once
+
+#if !defined(WRAPPING_CEF_SHARED)
+#error This file can be included wrapper-side only
+#endif
+
+#include "include/capi/cef_permission_handler_capi.h"
+#include "include/cef_permission_handler.h"
+#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
+
+// Wrap a C structure with a C++ class.
+// This class may be instantiated and accessed wrapper-side only.
+class CefMediaAccessCallbackCToCpp
+    : public CefCToCppRefCounted<CefMediaAccessCallbackCToCpp,
+                                 CefMediaAccessCallback,
+                                 cef_media_access_callback_t> {
+ public:
+  CefMediaAccessCallbackCToCpp();
+  virtual ~CefMediaAccessCallbackCToCpp();
+
+  // CefMediaAccessCallback methods.
+  void Continue(uint32_t allowed_permissions) override;
+  void Cancel() override;
+};
+
+#endif  // CEF_LIBCEF_DLL_CTOCPP_MEDIA_ACCESS_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/media_observer_ctocpp.cc b/src/libcef_dll/ctocpp/media_observer_ctocpp.cc
index 1d43b8d..78f7010 100644
--- a/src/libcef_dll/ctocpp/media_observer_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/media_observer_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6eed652a4bd13cf685980f7ea0b838d73e6071ba$
+// $hash=9b1b93f78443553cdf07bf096add8eda430ad13b$
 //
 
 #include "libcef_dll/ctocpp/media_observer_ctocpp.h"
@@ -25,8 +25,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_observer_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_sinks))
+  if (CEF_MEMBER_MISSING(_struct, on_sinks)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -47,8 +48,9 @@
   _struct->on_sinks(_struct, sinksCount, sinksList);
 
   // Restore param:sinks; type: refptr_vec_diff_byref_const
-  if (sinksList)
+  if (sinksList) {
     delete[] sinksList;
+  }
 }
 
 NO_SANITIZE("cfi-icall")
@@ -57,8 +59,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_observer_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_routes))
+  if (CEF_MEMBER_MISSING(_struct, on_routes)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -79,8 +82,9 @@
   _struct->on_routes(_struct, routesCount, routesList);
 
   // Restore param:routes; type: refptr_vec_diff_byref_const
-  if (routesList)
+  if (routesList) {
     delete[] routesList;
+  }
 }
 
 NO_SANITIZE("cfi-icall")
@@ -89,15 +93,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_observer_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_route_state_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_route_state_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: route; type: refptr_diff
   DCHECK(route.get());
-  if (!route.get())
+  if (!route.get()) {
     return;
+  }
 
   // Execute
   _struct->on_route_state_changed(_struct, CefMediaRouteCppToC::Wrap(route),
@@ -112,19 +118,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_observer_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_route_message_received))
+  if (CEF_MEMBER_MISSING(_struct, on_route_message_received)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: route; type: refptr_diff
   DCHECK(route.get());
-  if (!route.get())
+  if (!route.get()) {
     return;
+  }
   // Verify param: message; type: simple_byaddr
   DCHECK(message);
-  if (!message)
+  if (!message) {
     return;
+  }
 
   // Execute
   _struct->on_route_message_received(_struct, CefMediaRouteCppToC::Wrap(route),
@@ -147,7 +156,7 @@
                     CefMediaObserver,
                     cef_media_observer_t>::UnwrapDerived(CefWrapperType type,
                                                          CefMediaObserver* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/media_observer_ctocpp.h b/src/libcef_dll/ctocpp/media_observer_ctocpp.h
index e314c49..45ded09 100644
--- a/src/libcef_dll/ctocpp/media_observer_ctocpp.h
+++ b/src/libcef_dll/ctocpp/media_observer_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4c2e71870e5f8a31052431a5242f91392607502d$
+// $hash=af2c09e08b7a2c8c89fdbe314c074fe0d7f825cf$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_MEDIA_OBSERVER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/media_route_create_callback_ctocpp.cc b/src/libcef_dll/ctocpp/media_route_create_callback_ctocpp.cc
index 22c00e5..633da03 100644
--- a/src/libcef_dll/ctocpp/media_route_create_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/media_route_create_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=93dd08de00931b1c00ec0307cc70496455936b0c$
+// $hash=87e133cdd2e856ab8a9d45d990972e08a7a69fbc$
 //
 
 #include "libcef_dll/ctocpp/media_route_create_callback_ctocpp.h"
@@ -26,8 +26,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_route_create_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_media_route_create_finished))
+  if (CEF_MEMBER_MISSING(_struct, on_media_route_create_finished)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -54,7 +55,7 @@
                     CefMediaRouteCreateCallback,
                     cef_media_route_create_callback_t>::
     UnwrapDerived(CefWrapperType type, CefMediaRouteCreateCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/media_route_create_callback_ctocpp.h b/src/libcef_dll/ctocpp/media_route_create_callback_ctocpp.h
index 0d92b94..d590439 100644
--- a/src/libcef_dll/ctocpp/media_route_create_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/media_route_create_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ac5657bccd7830fde1d3dddfad69d87dff2ae684$
+// $hash=ecf8319d38a7ef9e5b5730c55ca299b3a8056018$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_MEDIA_ROUTE_CREATE_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/media_route_ctocpp.cc b/src/libcef_dll/ctocpp/media_route_ctocpp.cc
index b9f17fa..1af9764 100644
--- a/src/libcef_dll/ctocpp/media_route_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/media_route_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7fe34c4b79d10a88bfcf5ec46a54cf52d3657e87$
+// $hash=92edc8064b198b90008142f6d839810a498350d1$
 //
 
 #include "libcef_dll/ctocpp/media_route_ctocpp.h"
@@ -23,8 +23,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_route_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_id))
+  if (CEF_MEMBER_MISSING(_struct, get_id)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -42,8 +43,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_route_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_source))
+  if (CEF_MEMBER_MISSING(_struct, get_source)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -59,8 +61,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_route_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_sink))
+  if (CEF_MEMBER_MISSING(_struct, get_sink)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -77,15 +80,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_route_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_route_message))
+  if (CEF_MEMBER_MISSING(_struct, send_route_message)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: message; type: simple_byaddr
   DCHECK(message);
-  if (!message)
+  if (!message) {
     return;
+  }
 
   // Execute
   _struct->send_route_message(_struct, message, message_size);
@@ -95,8 +100,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_route_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, terminate))
+  if (CEF_MEMBER_MISSING(_struct, terminate)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -118,7 +124,7 @@
 cef_media_route_t*
 CefCToCppRefCounted<CefMediaRouteCToCpp, CefMediaRoute, cef_media_route_t>::
     UnwrapDerived(CefWrapperType type, CefMediaRoute* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/media_route_ctocpp.h b/src/libcef_dll/ctocpp/media_route_ctocpp.h
index c1f68b6..a574266 100644
--- a/src/libcef_dll/ctocpp/media_route_ctocpp.h
+++ b/src/libcef_dll/ctocpp/media_route_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=cb792f909646d1ccd3644877ce2393080465471a$
+// $hash=c8f6db85d4b577c287a587a72aa11d6e10f55d78$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_MEDIA_ROUTE_CTOCPP_H_
@@ -34,11 +34,11 @@
   virtual ~CefMediaRouteCToCpp();
 
   // CefMediaRoute methods.
-  CefString GetId() OVERRIDE;
-  CefRefPtr<CefMediaSource> GetSource() OVERRIDE;
-  CefRefPtr<CefMediaSink> GetSink() OVERRIDE;
-  void SendRouteMessage(const void* message, size_t message_size) OVERRIDE;
-  void Terminate() OVERRIDE;
+  CefString GetId() override;
+  CefRefPtr<CefMediaSource> GetSource() override;
+  CefRefPtr<CefMediaSink> GetSink() override;
+  void SendRouteMessage(const void* message, size_t message_size) override;
+  void Terminate() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_MEDIA_ROUTE_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/media_router_ctocpp.cc b/src/libcef_dll/ctocpp/media_router_ctocpp.cc
index d90f7de..ad0c7b8 100644
--- a/src/libcef_dll/ctocpp/media_router_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/media_router_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,10 +9,11 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4b8ab6373fcb0a84a818c2c5ef8982600346f34b$
+// $hash=af200e153fda6b0d33e42d2dfd05346d6e2ae7f4$
 //
 
 #include "libcef_dll/ctocpp/media_router_ctocpp.h"
+#include "libcef_dll/cpptoc/completion_callback_cpptoc.h"
 #include "libcef_dll/cpptoc/media_observer_cpptoc.h"
 #include "libcef_dll/cpptoc/media_route_create_callback_cpptoc.h"
 #include "libcef_dll/ctocpp/media_sink_ctocpp.h"
@@ -23,13 +24,17 @@
 // STATIC METHODS - Body may be edited by hand.
 
 NO_SANITIZE("cfi-icall")
-CefRefPtr<CefMediaRouter> CefMediaRouter::GetGlobalMediaRouter() {
+CefRefPtr<CefMediaRouter> CefMediaRouter::GetGlobalMediaRouter(
+    CefRefPtr<CefCompletionCallback> callback) {
   shutdown_checker::AssertNotShutdown();
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
+  // Unverified params: callback
+
   // Execute
-  cef_media_router_t* _retval = cef_media_router_get_global();
+  cef_media_router_t* _retval =
+      cef_media_router_get_global(CefCompletionCallbackCppToC::Wrap(callback));
 
   // Return type: refptr_same
   return CefMediaRouterCToCpp::Wrap(_retval);
@@ -43,15 +48,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_router_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, add_observer))
+  if (CEF_MEMBER_MISSING(_struct, add_observer)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: observer; type: refptr_diff
   DCHECK(observer.get());
-  if (!observer.get())
+  if (!observer.get()) {
     return nullptr;
+  }
 
   // Execute
   cef_registration_t* _retval =
@@ -67,15 +74,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_router_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_source))
+  if (CEF_MEMBER_MISSING(_struct, get_source)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: urn; type: string_byref_const
   DCHECK(!urn.empty());
-  if (urn.empty())
+  if (urn.empty()) {
     return nullptr;
+  }
 
   // Execute
   cef_media_source_t* _retval = _struct->get_source(_struct, urn.GetStruct());
@@ -88,8 +97,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_router_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, notify_current_sinks))
+  if (CEF_MEMBER_MISSING(_struct, notify_current_sinks)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -105,23 +115,27 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_router_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, create_route))
+  if (CEF_MEMBER_MISSING(_struct, create_route)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: source; type: refptr_same
   DCHECK(source.get());
-  if (!source.get())
+  if (!source.get()) {
     return;
+  }
   // Verify param: sink; type: refptr_same
   DCHECK(sink.get());
-  if (!sink.get())
+  if (!sink.get()) {
     return;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return;
+  }
 
   // Execute
   _struct->create_route(_struct, CefMediaSourceCToCpp::Unwrap(source),
@@ -133,8 +147,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_router_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, notify_current_routes))
+  if (CEF_MEMBER_MISSING(_struct, notify_current_routes)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -156,7 +171,7 @@
 cef_media_router_t*
 CefCToCppRefCounted<CefMediaRouterCToCpp, CefMediaRouter, cef_media_router_t>::
     UnwrapDerived(CefWrapperType type, CefMediaRouter* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/media_router_ctocpp.h b/src/libcef_dll/ctocpp/media_router_ctocpp.h
index 7a022bb..c48028d 100644
--- a/src/libcef_dll/ctocpp/media_router_ctocpp.h
+++ b/src/libcef_dll/ctocpp/media_router_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e3d62de09a699415a839cadda52cca2582d90063$
+// $hash=ef079450730cdf1b8720a84d83b361c6423a091a$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_MEDIA_ROUTER_CTOCPP_H_
@@ -35,13 +35,13 @@
 
   // CefMediaRouter methods.
   CefRefPtr<CefRegistration> AddObserver(
-      CefRefPtr<CefMediaObserver> observer) OVERRIDE;
-  CefRefPtr<CefMediaSource> GetSource(const CefString& urn) OVERRIDE;
-  void NotifyCurrentSinks() OVERRIDE;
+      CefRefPtr<CefMediaObserver> observer) override;
+  CefRefPtr<CefMediaSource> GetSource(const CefString& urn) override;
+  void NotifyCurrentSinks() override;
   void CreateRoute(CefRefPtr<CefMediaSource> source,
                    CefRefPtr<CefMediaSink> sink,
-                   CefRefPtr<CefMediaRouteCreateCallback> callback) OVERRIDE;
-  void NotifyCurrentRoutes() OVERRIDE;
+                   CefRefPtr<CefMediaRouteCreateCallback> callback) override;
+  void NotifyCurrentRoutes() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_MEDIA_ROUTER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/media_sink_ctocpp.cc b/src/libcef_dll/ctocpp/media_sink_ctocpp.cc
index 402dcde..1e91fc6 100644
--- a/src/libcef_dll/ctocpp/media_sink_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/media_sink_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8aa27e34aea83e91b04d21764f3ab985b04bbf9b$
+// $hash=453d7d2c9ecc4872b77510595ae7bf78e2c39bba$
 //
 
 #include "libcef_dll/ctocpp/media_sink_ctocpp.h"
@@ -23,8 +23,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_sink_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_id))
+  if (CEF_MEMBER_MISSING(_struct, get_id)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -37,28 +38,13 @@
   return _retvalStr;
 }
 
-NO_SANITIZE("cfi-icall") bool CefMediaSinkCToCpp::IsValid() {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_media_sink_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
-    return false;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  int _retval = _struct->is_valid(_struct);
-
-  // Return type: bool
-  return _retval ? true : false;
-}
-
 NO_SANITIZE("cfi-icall") CefString CefMediaSinkCToCpp::GetName() {
   shutdown_checker::AssertNotShutdown();
 
   cef_media_sink_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_name))
+  if (CEF_MEMBER_MISSING(_struct, get_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -71,31 +57,14 @@
   return _retvalStr;
 }
 
-NO_SANITIZE("cfi-icall") CefString CefMediaSinkCToCpp::GetDescription() {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_media_sink_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_description))
-    return CefString();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  cef_string_userfree_t _retval = _struct->get_description(_struct);
-
-  // Return type: string
-  CefString _retvalStr;
-  _retvalStr.AttachToUserFree(_retval);
-  return _retvalStr;
-}
-
 NO_SANITIZE("cfi-icall")
 CefMediaSink::IconType CefMediaSinkCToCpp::GetIconType() {
   shutdown_checker::AssertNotShutdown();
 
   cef_media_sink_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_icon_type))
+  if (CEF_MEMBER_MISSING(_struct, get_icon_type)) {
     return CEF_MSIT_GENERIC;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -112,15 +81,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_sink_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_device_info))
+  if (CEF_MEMBER_MISSING(_struct, get_device_info)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return;
+  }
 
   // Execute
   _struct->get_device_info(
@@ -131,8 +102,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_sink_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_cast_sink))
+  if (CEF_MEMBER_MISSING(_struct, is_cast_sink)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -147,8 +119,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_sink_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_dial_sink))
+  if (CEF_MEMBER_MISSING(_struct, is_dial_sink)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -164,15 +137,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_sink_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_compatible_with))
+  if (CEF_MEMBER_MISSING(_struct, is_compatible_with)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: source; type: refptr_same
   DCHECK(source.get());
-  if (!source.get())
+  if (!source.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_compatible_with(
@@ -196,7 +171,7 @@
 cef_media_sink_t*
 CefCToCppRefCounted<CefMediaSinkCToCpp, CefMediaSink, cef_media_sink_t>::
     UnwrapDerived(CefWrapperType type, CefMediaSink* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/media_sink_ctocpp.h b/src/libcef_dll/ctocpp/media_sink_ctocpp.h
index 4370410..80e0393 100644
--- a/src/libcef_dll/ctocpp/media_sink_ctocpp.h
+++ b/src/libcef_dll/ctocpp/media_sink_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=81437a10eeb422cf962af49b782275dd24bea500$
+// $hash=f1a192a4341ed6fe0d4b6f8b065b372401e0f055$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_MEDIA_SINK_CTOCPP_H_
@@ -34,16 +34,14 @@
   virtual ~CefMediaSinkCToCpp();
 
   // CefMediaSink methods.
-  CefString GetId() OVERRIDE;
-  bool IsValid() OVERRIDE;
-  CefString GetName() OVERRIDE;
-  CefString GetDescription() OVERRIDE;
-  IconType GetIconType() OVERRIDE;
+  CefString GetId() override;
+  CefString GetName() override;
+  IconType GetIconType() override;
   void GetDeviceInfo(
-      CefRefPtr<CefMediaSinkDeviceInfoCallback> callback) OVERRIDE;
-  bool IsCastSink() OVERRIDE;
-  bool IsDialSink() OVERRIDE;
-  bool IsCompatibleWith(CefRefPtr<CefMediaSource> source) OVERRIDE;
+      CefRefPtr<CefMediaSinkDeviceInfoCallback> callback) override;
+  bool IsCastSink() override;
+  bool IsDialSink() override;
+  bool IsCompatibleWith(CefRefPtr<CefMediaSource> source) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_MEDIA_SINK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/media_sink_device_info_callback_ctocpp.cc b/src/libcef_dll/ctocpp/media_sink_device_info_callback_ctocpp.cc
index fdd5822..82f8b67 100644
--- a/src/libcef_dll/ctocpp/media_sink_device_info_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/media_sink_device_info_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c56362ea79609562dacc4bf8303f2bd920ddeada$
+// $hash=067877a410a4ae9d7d671d5826a5c93eb6cdad37$
 //
 
 #include "libcef_dll/ctocpp/media_sink_device_info_callback_ctocpp.h"
@@ -23,8 +23,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_sink_device_info_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_media_sink_device_info))
+  if (CEF_MEMBER_MISSING(_struct, on_media_sink_device_info)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -48,7 +49,7 @@
                     CefMediaSinkDeviceInfoCallback,
                     cef_media_sink_device_info_callback_t>::
     UnwrapDerived(CefWrapperType type, CefMediaSinkDeviceInfoCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/media_sink_device_info_callback_ctocpp.h b/src/libcef_dll/ctocpp/media_sink_device_info_callback_ctocpp.h
index c5cfef8..0639523 100644
--- a/src/libcef_dll/ctocpp/media_sink_device_info_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/media_sink_device_info_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e48d0b8482168d355e04460ea6ea5b7662dbe4fd$
+// $hash=4f2660ef656d3041a8b0905855d0149b299d3c7c$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_MEDIA_SINK_DEVICE_INFO_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/media_source_ctocpp.cc b/src/libcef_dll/ctocpp/media_source_ctocpp.cc
index 25acc58..b7481a3 100644
--- a/src/libcef_dll/ctocpp/media_source_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/media_source_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2b4f20db4eccd1429c748f39db19852cd1644b4a$
+// $hash=f05652f759e16a6f2a3bc5f640ede99e3e123b4d$
 //
 
 #include "libcef_dll/ctocpp/media_source_ctocpp.h"
@@ -21,8 +21,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_source_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_id))
+  if (CEF_MEMBER_MISSING(_struct, get_id)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -35,28 +36,13 @@
   return _retvalStr;
 }
 
-NO_SANITIZE("cfi-icall") bool CefMediaSourceCToCpp::IsValid() {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_media_source_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
-    return false;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  int _retval = _struct->is_valid(_struct);
-
-  // Return type: bool
-  return _retval ? true : false;
-}
-
 NO_SANITIZE("cfi-icall") bool CefMediaSourceCToCpp::IsCastSource() {
   shutdown_checker::AssertNotShutdown();
 
   cef_media_source_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_cast_source))
+  if (CEF_MEMBER_MISSING(_struct, is_cast_source)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -71,8 +57,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_media_source_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_dial_source))
+  if (CEF_MEMBER_MISSING(_struct, is_dial_source)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -97,7 +84,7 @@
 cef_media_source_t*
 CefCToCppRefCounted<CefMediaSourceCToCpp, CefMediaSource, cef_media_source_t>::
     UnwrapDerived(CefWrapperType type, CefMediaSource* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/media_source_ctocpp.h b/src/libcef_dll/ctocpp/media_source_ctocpp.h
index fd54e19..743c813 100644
--- a/src/libcef_dll/ctocpp/media_source_ctocpp.h
+++ b/src/libcef_dll/ctocpp/media_source_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=73aeb0f58611c0d7a9fa13f1d9268912e0fba0bd$
+// $hash=36c26e21479231ade66738aee8f10c01f9d0cd22$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_MEDIA_SOURCE_CTOCPP_H_
@@ -34,10 +34,9 @@
   virtual ~CefMediaSourceCToCpp();
 
   // CefMediaSource methods.
-  CefString GetId() OVERRIDE;
-  bool IsValid() OVERRIDE;
-  bool IsCastSource() OVERRIDE;
-  bool IsDialSource() OVERRIDE;
+  CefString GetId() override;
+  bool IsCastSource() override;
+  bool IsDialSource() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_MEDIA_SOURCE_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/menu_model_ctocpp.cc b/src/libcef_dll/ctocpp/menu_model_ctocpp.cc
index a280bac..5585499 100644
--- a/src/libcef_dll/ctocpp/menu_model_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/menu_model_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=fb562ef19ca1a0c2094548aae3f6a213d08480f8$
+// $hash=048b61ed29f9db56cba1a55354c367f941a59b14$
 //
 
 #include "libcef_dll/ctocpp/menu_model_ctocpp.h"
@@ -27,8 +27,9 @@
 
   // Verify param: delegate; type: refptr_diff
   DCHECK(delegate.get());
-  if (!delegate.get())
+  if (!delegate.get()) {
     return nullptr;
+  }
 
   // Execute
   cef_menu_model_t* _retval =
@@ -44,8 +45,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_sub_menu))
+  if (CEF_MEMBER_MISSING(_struct, is_sub_menu)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -60,8 +62,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, clear))
+  if (CEF_MEMBER_MISSING(_struct, clear)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -72,17 +75,18 @@
   return _retval ? true : false;
 }
 
-NO_SANITIZE("cfi-icall") int CefMenuModelCToCpp::GetCount() {
+NO_SANITIZE("cfi-icall") size_t CefMenuModelCToCpp::GetCount() {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_count))
+  if (CEF_MEMBER_MISSING(_struct, get_count)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int _retval = _struct->get_count(_struct);
+  size_t _retval = _struct->get_count(_struct);
 
   // Return type: simple
   return _retval;
@@ -92,8 +96,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, add_separator))
+  if (CEF_MEMBER_MISSING(_struct, add_separator)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -109,15 +114,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, add_item))
+  if (CEF_MEMBER_MISSING(_struct, add_item)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: label; type: string_byref_const
   DCHECK(!label.empty());
-  if (label.empty())
+  if (label.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->add_item(_struct, command_id, label.GetStruct());
@@ -131,15 +138,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, add_check_item))
+  if (CEF_MEMBER_MISSING(_struct, add_check_item)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: label; type: string_byref_const
   DCHECK(!label.empty());
-  if (label.empty())
+  if (label.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->add_check_item(_struct, command_id, label.GetStruct());
@@ -155,15 +164,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, add_radio_item))
+  if (CEF_MEMBER_MISSING(_struct, add_radio_item)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: label; type: string_byref_const
   DCHECK(!label.empty());
-  if (label.empty())
+  if (label.empty()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -179,15 +190,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, add_sub_menu))
+  if (CEF_MEMBER_MISSING(_struct, add_sub_menu)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: label; type: string_byref_const
   DCHECK(!label.empty());
-  if (label.empty())
+  if (label.empty()) {
     return nullptr;
+  }
 
   // Execute
   cef_menu_model_t* _retval =
@@ -197,12 +210,14 @@
   return CefMenuModelCToCpp::Wrap(_retval);
 }
 
-NO_SANITIZE("cfi-icall") bool CefMenuModelCToCpp::InsertSeparatorAt(int index) {
+NO_SANITIZE("cfi-icall")
+bool CefMenuModelCToCpp::InsertSeparatorAt(size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, insert_separator_at))
+  if (CEF_MEMBER_MISSING(_struct, insert_separator_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -214,21 +229,23 @@
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefMenuModelCToCpp::InsertItemAt(int index,
+bool CefMenuModelCToCpp::InsertItemAt(size_t index,
                                       int command_id,
                                       const CefString& label) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, insert_item_at))
+  if (CEF_MEMBER_MISSING(_struct, insert_item_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: label; type: string_byref_const
   DCHECK(!label.empty());
-  if (label.empty())
+  if (label.empty()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -239,21 +256,23 @@
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefMenuModelCToCpp::InsertCheckItemAt(int index,
+bool CefMenuModelCToCpp::InsertCheckItemAt(size_t index,
                                            int command_id,
                                            const CefString& label) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, insert_check_item_at))
+  if (CEF_MEMBER_MISSING(_struct, insert_check_item_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: label; type: string_byref_const
   DCHECK(!label.empty());
-  if (label.empty())
+  if (label.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->insert_check_item_at(_struct, index, command_id,
@@ -264,22 +283,24 @@
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefMenuModelCToCpp::InsertRadioItemAt(int index,
+bool CefMenuModelCToCpp::InsertRadioItemAt(size_t index,
                                            int command_id,
                                            const CefString& label,
                                            int group_id) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, insert_radio_item_at))
+  if (CEF_MEMBER_MISSING(_struct, insert_radio_item_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: label; type: string_byref_const
   DCHECK(!label.empty());
-  if (label.empty())
+  if (label.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->insert_radio_item_at(_struct, index, command_id,
@@ -291,21 +312,23 @@
 
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefMenuModel> CefMenuModelCToCpp::InsertSubMenuAt(
-    int index,
+    size_t index,
     int command_id,
     const CefString& label) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, insert_sub_menu_at))
+  if (CEF_MEMBER_MISSING(_struct, insert_sub_menu_at)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: label; type: string_byref_const
   DCHECK(!label.empty());
-  if (label.empty())
+  if (label.empty()) {
     return nullptr;
+  }
 
   // Execute
   cef_menu_model_t* _retval = _struct->insert_sub_menu_at(
@@ -319,8 +342,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, remove))
+  if (CEF_MEMBER_MISSING(_struct, remove)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -331,12 +355,13 @@
   return _retval ? true : false;
 }
 
-NO_SANITIZE("cfi-icall") bool CefMenuModelCToCpp::RemoveAt(int index) {
+NO_SANITIZE("cfi-icall") bool CefMenuModelCToCpp::RemoveAt(size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, remove_at))
+  if (CEF_MEMBER_MISSING(_struct, remove_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -351,8 +376,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_index_of))
+  if (CEF_MEMBER_MISSING(_struct, get_index_of)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -363,12 +389,13 @@
   return _retval;
 }
 
-NO_SANITIZE("cfi-icall") int CefMenuModelCToCpp::GetCommandIdAt(int index) {
+NO_SANITIZE("cfi-icall") int CefMenuModelCToCpp::GetCommandIdAt(size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_command_id_at))
+  if (CEF_MEMBER_MISSING(_struct, get_command_id_at)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -380,12 +407,13 @@
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefMenuModelCToCpp::SetCommandIdAt(int index, int command_id) {
+bool CefMenuModelCToCpp::SetCommandIdAt(size_t index, int command_id) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_command_id_at))
+  if (CEF_MEMBER_MISSING(_struct, set_command_id_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -401,8 +429,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_label))
+  if (CEF_MEMBER_MISSING(_struct, get_label)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -415,12 +444,14 @@
   return _retvalStr;
 }
 
-NO_SANITIZE("cfi-icall") CefString CefMenuModelCToCpp::GetLabelAt(int index) {
+NO_SANITIZE("cfi-icall")
+CefString CefMenuModelCToCpp::GetLabelAt(size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_label_at))
+  if (CEF_MEMBER_MISSING(_struct, get_label_at)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -438,15 +469,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_label))
+  if (CEF_MEMBER_MISSING(_struct, set_label)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: label; type: string_byref_const
   DCHECK(!label.empty());
-  if (label.empty())
+  if (label.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_label(_struct, command_id, label.GetStruct());
@@ -456,19 +489,21 @@
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefMenuModelCToCpp::SetLabelAt(int index, const CefString& label) {
+bool CefMenuModelCToCpp::SetLabelAt(size_t index, const CefString& label) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_label_at))
+  if (CEF_MEMBER_MISSING(_struct, set_label_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: label; type: string_byref_const
   DCHECK(!label.empty());
-  if (label.empty())
+  if (label.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_label_at(_struct, index, label.GetStruct());
@@ -482,8 +517,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_type))
+  if (CEF_MEMBER_MISSING(_struct, get_type)) {
     return MENUITEMTYPE_NONE;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -495,12 +531,13 @@
 }
 
 NO_SANITIZE("cfi-icall")
-CefMenuModel::MenuItemType CefMenuModelCToCpp::GetTypeAt(int index) {
+CefMenuModel::MenuItemType CefMenuModelCToCpp::GetTypeAt(size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_type_at))
+  if (CEF_MEMBER_MISSING(_struct, get_type_at)) {
     return MENUITEMTYPE_NONE;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -515,8 +552,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_group_id))
+  if (CEF_MEMBER_MISSING(_struct, get_group_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -527,12 +565,13 @@
   return _retval;
 }
 
-NO_SANITIZE("cfi-icall") int CefMenuModelCToCpp::GetGroupIdAt(int index) {
+NO_SANITIZE("cfi-icall") int CefMenuModelCToCpp::GetGroupIdAt(size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_group_id_at))
+  if (CEF_MEMBER_MISSING(_struct, get_group_id_at)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -548,8 +587,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_group_id))
+  if (CEF_MEMBER_MISSING(_struct, set_group_id)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -561,12 +601,13 @@
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefMenuModelCToCpp::SetGroupIdAt(int index, int group_id) {
+bool CefMenuModelCToCpp::SetGroupIdAt(size_t index, int group_id) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_group_id_at))
+  if (CEF_MEMBER_MISSING(_struct, set_group_id_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -582,8 +623,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_sub_menu))
+  if (CEF_MEMBER_MISSING(_struct, get_sub_menu)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -595,12 +637,13 @@
 }
 
 NO_SANITIZE("cfi-icall")
-CefRefPtr<CefMenuModel> CefMenuModelCToCpp::GetSubMenuAt(int index) {
+CefRefPtr<CefMenuModel> CefMenuModelCToCpp::GetSubMenuAt(size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_sub_menu_at))
+  if (CEF_MEMBER_MISSING(_struct, get_sub_menu_at)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -615,8 +658,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_visible))
+  if (CEF_MEMBER_MISSING(_struct, is_visible)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -627,12 +671,13 @@
   return _retval ? true : false;
 }
 
-NO_SANITIZE("cfi-icall") bool CefMenuModelCToCpp::IsVisibleAt(int index) {
+NO_SANITIZE("cfi-icall") bool CefMenuModelCToCpp::IsVisibleAt(size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_visible_at))
+  if (CEF_MEMBER_MISSING(_struct, is_visible_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -648,8 +693,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_visible))
+  if (CEF_MEMBER_MISSING(_struct, set_visible)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -661,12 +707,13 @@
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefMenuModelCToCpp::SetVisibleAt(int index, bool visible) {
+bool CefMenuModelCToCpp::SetVisibleAt(size_t index, bool visible) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_visible_at))
+  if (CEF_MEMBER_MISSING(_struct, set_visible_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -681,8 +728,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_enabled))
+  if (CEF_MEMBER_MISSING(_struct, is_enabled)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -693,12 +741,13 @@
   return _retval ? true : false;
 }
 
-NO_SANITIZE("cfi-icall") bool CefMenuModelCToCpp::IsEnabledAt(int index) {
+NO_SANITIZE("cfi-icall") bool CefMenuModelCToCpp::IsEnabledAt(size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_enabled_at))
+  if (CEF_MEMBER_MISSING(_struct, is_enabled_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -714,8 +763,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_enabled))
+  if (CEF_MEMBER_MISSING(_struct, set_enabled)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -727,12 +777,13 @@
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefMenuModelCToCpp::SetEnabledAt(int index, bool enabled) {
+bool CefMenuModelCToCpp::SetEnabledAt(size_t index, bool enabled) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_enabled_at))
+  if (CEF_MEMBER_MISSING(_struct, set_enabled_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -747,8 +798,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_checked))
+  if (CEF_MEMBER_MISSING(_struct, is_checked)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -759,12 +811,13 @@
   return _retval ? true : false;
 }
 
-NO_SANITIZE("cfi-icall") bool CefMenuModelCToCpp::IsCheckedAt(int index) {
+NO_SANITIZE("cfi-icall") bool CefMenuModelCToCpp::IsCheckedAt(size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_checked_at))
+  if (CEF_MEMBER_MISSING(_struct, is_checked_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -780,8 +833,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_checked))
+  if (CEF_MEMBER_MISSING(_struct, set_checked)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -793,12 +847,13 @@
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefMenuModelCToCpp::SetCheckedAt(int index, bool checked) {
+bool CefMenuModelCToCpp::SetCheckedAt(size_t index, bool checked) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_checked_at))
+  if (CEF_MEMBER_MISSING(_struct, set_checked_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -814,8 +869,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_accelerator))
+  if (CEF_MEMBER_MISSING(_struct, has_accelerator)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -826,12 +882,14 @@
   return _retval ? true : false;
 }
 
-NO_SANITIZE("cfi-icall") bool CefMenuModelCToCpp::HasAcceleratorAt(int index) {
+NO_SANITIZE("cfi-icall")
+bool CefMenuModelCToCpp::HasAcceleratorAt(size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_accelerator_at))
+  if (CEF_MEMBER_MISSING(_struct, has_accelerator_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -851,8 +909,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_accelerator))
+  if (CEF_MEMBER_MISSING(_struct, set_accelerator)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -865,7 +924,7 @@
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefMenuModelCToCpp::SetAcceleratorAt(int index,
+bool CefMenuModelCToCpp::SetAcceleratorAt(size_t index,
                                           int key_code,
                                           bool shift_pressed,
                                           bool ctrl_pressed,
@@ -873,8 +932,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_accelerator_at))
+  if (CEF_MEMBER_MISSING(_struct, set_accelerator_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -891,8 +951,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, remove_accelerator))
+  if (CEF_MEMBER_MISSING(_struct, remove_accelerator)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -904,12 +965,13 @@
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefMenuModelCToCpp::RemoveAcceleratorAt(int index) {
+bool CefMenuModelCToCpp::RemoveAcceleratorAt(size_t index) {
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, remove_accelerator_at))
+  if (CEF_MEMBER_MISSING(_struct, remove_accelerator_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -929,8 +991,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_accelerator))
+  if (CEF_MEMBER_MISSING(_struct, get_accelerator)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -958,7 +1021,7 @@
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefMenuModelCToCpp::GetAcceleratorAt(int index,
+bool CefMenuModelCToCpp::GetAcceleratorAt(size_t index,
                                           int& key_code,
                                           bool& shift_pressed,
                                           bool& ctrl_pressed,
@@ -966,8 +1029,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_accelerator_at))
+  if (CEF_MEMBER_MISSING(_struct, get_accelerator_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1001,8 +1065,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_color))
+  if (CEF_MEMBER_MISSING(_struct, set_color)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1020,8 +1085,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_color_at))
+  if (CEF_MEMBER_MISSING(_struct, set_color_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1039,8 +1105,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_color))
+  if (CEF_MEMBER_MISSING(_struct, get_color)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1058,8 +1125,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_color_at))
+  if (CEF_MEMBER_MISSING(_struct, get_color_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1076,8 +1144,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_font_list))
+  if (CEF_MEMBER_MISSING(_struct, set_font_list)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1096,8 +1165,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_font_list_at))
+  if (CEF_MEMBER_MISSING(_struct, set_font_list_at)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1125,7 +1195,7 @@
 cef_menu_model_t*
 CefCToCppRefCounted<CefMenuModelCToCpp, CefMenuModel, cef_menu_model_t>::
     UnwrapDerived(CefWrapperType type, CefMenuModel* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/menu_model_ctocpp.h b/src/libcef_dll/ctocpp/menu_model_ctocpp.h
index 4081530..d6ed8d0 100644
--- a/src/libcef_dll/ctocpp/menu_model_ctocpp.h
+++ b/src/libcef_dll/ctocpp/menu_model_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=81606be28dd5d07eaab14a00570a6fd5fed7d8b8$
+// $hash=1b1c5e3e3cca0da704d30c6577a0c083c3fb389b$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_MENU_MODEL_CTOCPP_H_
@@ -34,96 +34,98 @@
   virtual ~CefMenuModelCToCpp();
 
   // CefMenuModel methods.
-  bool IsSubMenu() OVERRIDE;
-  bool Clear() OVERRIDE;
-  int GetCount() OVERRIDE;
-  bool AddSeparator() OVERRIDE;
-  bool AddItem(int command_id, const CefString& label) OVERRIDE;
-  bool AddCheckItem(int command_id, const CefString& label) OVERRIDE;
+  bool IsSubMenu() override;
+  bool Clear() override;
+  size_t GetCount() override;
+  bool AddSeparator() override;
+  bool AddItem(int command_id, const CefString& label) override;
+  bool AddCheckItem(int command_id, const CefString& label) override;
   bool AddRadioItem(int command_id,
                     const CefString& label,
-                    int group_id) OVERRIDE;
+                    int group_id) override;
   CefRefPtr<CefMenuModel> AddSubMenu(int command_id,
-                                     const CefString& label) OVERRIDE;
-  bool InsertSeparatorAt(int index) OVERRIDE;
-  bool InsertItemAt(int index, int command_id, const CefString& label) OVERRIDE;
-  bool InsertCheckItemAt(int index,
+                                     const CefString& label) override;
+  bool InsertSeparatorAt(size_t index) override;
+  bool InsertItemAt(size_t index,
+                    int command_id,
+                    const CefString& label) override;
+  bool InsertCheckItemAt(size_t index,
                          int command_id,
-                         const CefString& label) OVERRIDE;
-  bool InsertRadioItemAt(int index,
+                         const CefString& label) override;
+  bool InsertRadioItemAt(size_t index,
                          int command_id,
                          const CefString& label,
-                         int group_id) OVERRIDE;
-  CefRefPtr<CefMenuModel> InsertSubMenuAt(int index,
+                         int group_id) override;
+  CefRefPtr<CefMenuModel> InsertSubMenuAt(size_t index,
                                           int command_id,
-                                          const CefString& label) OVERRIDE;
-  bool Remove(int command_id) OVERRIDE;
-  bool RemoveAt(int index) OVERRIDE;
-  int GetIndexOf(int command_id) OVERRIDE;
-  int GetCommandIdAt(int index) OVERRIDE;
-  bool SetCommandIdAt(int index, int command_id) OVERRIDE;
-  CefString GetLabel(int command_id) OVERRIDE;
-  CefString GetLabelAt(int index) OVERRIDE;
-  bool SetLabel(int command_id, const CefString& label) OVERRIDE;
-  bool SetLabelAt(int index, const CefString& label) OVERRIDE;
-  MenuItemType GetType(int command_id) OVERRIDE;
-  MenuItemType GetTypeAt(int index) OVERRIDE;
-  int GetGroupId(int command_id) OVERRIDE;
-  int GetGroupIdAt(int index) OVERRIDE;
-  bool SetGroupId(int command_id, int group_id) OVERRIDE;
-  bool SetGroupIdAt(int index, int group_id) OVERRIDE;
-  CefRefPtr<CefMenuModel> GetSubMenu(int command_id) OVERRIDE;
-  CefRefPtr<CefMenuModel> GetSubMenuAt(int index) OVERRIDE;
-  bool IsVisible(int command_id) OVERRIDE;
-  bool IsVisibleAt(int index) OVERRIDE;
-  bool SetVisible(int command_id, bool visible) OVERRIDE;
-  bool SetVisibleAt(int index, bool visible) OVERRIDE;
-  bool IsEnabled(int command_id) OVERRIDE;
-  bool IsEnabledAt(int index) OVERRIDE;
-  bool SetEnabled(int command_id, bool enabled) OVERRIDE;
-  bool SetEnabledAt(int index, bool enabled) OVERRIDE;
-  bool IsChecked(int command_id) OVERRIDE;
-  bool IsCheckedAt(int index) OVERRIDE;
-  bool SetChecked(int command_id, bool checked) OVERRIDE;
-  bool SetCheckedAt(int index, bool checked) OVERRIDE;
-  bool HasAccelerator(int command_id) OVERRIDE;
-  bool HasAcceleratorAt(int index) OVERRIDE;
+                                          const CefString& label) override;
+  bool Remove(int command_id) override;
+  bool RemoveAt(size_t index) override;
+  int GetIndexOf(int command_id) override;
+  int GetCommandIdAt(size_t index) override;
+  bool SetCommandIdAt(size_t index, int command_id) override;
+  CefString GetLabel(int command_id) override;
+  CefString GetLabelAt(size_t index) override;
+  bool SetLabel(int command_id, const CefString& label) override;
+  bool SetLabelAt(size_t index, const CefString& label) override;
+  MenuItemType GetType(int command_id) override;
+  MenuItemType GetTypeAt(size_t index) override;
+  int GetGroupId(int command_id) override;
+  int GetGroupIdAt(size_t index) override;
+  bool SetGroupId(int command_id, int group_id) override;
+  bool SetGroupIdAt(size_t index, int group_id) override;
+  CefRefPtr<CefMenuModel> GetSubMenu(int command_id) override;
+  CefRefPtr<CefMenuModel> GetSubMenuAt(size_t index) override;
+  bool IsVisible(int command_id) override;
+  bool IsVisibleAt(size_t index) override;
+  bool SetVisible(int command_id, bool visible) override;
+  bool SetVisibleAt(size_t index, bool visible) override;
+  bool IsEnabled(int command_id) override;
+  bool IsEnabledAt(size_t index) override;
+  bool SetEnabled(int command_id, bool enabled) override;
+  bool SetEnabledAt(size_t index, bool enabled) override;
+  bool IsChecked(int command_id) override;
+  bool IsCheckedAt(size_t index) override;
+  bool SetChecked(int command_id, bool checked) override;
+  bool SetCheckedAt(size_t index, bool checked) override;
+  bool HasAccelerator(int command_id) override;
+  bool HasAcceleratorAt(size_t index) override;
   bool SetAccelerator(int command_id,
                       int key_code,
                       bool shift_pressed,
                       bool ctrl_pressed,
-                      bool alt_pressed) OVERRIDE;
-  bool SetAcceleratorAt(int index,
+                      bool alt_pressed) override;
+  bool SetAcceleratorAt(size_t index,
                         int key_code,
                         bool shift_pressed,
                         bool ctrl_pressed,
-                        bool alt_pressed) OVERRIDE;
-  bool RemoveAccelerator(int command_id) OVERRIDE;
-  bool RemoveAcceleratorAt(int index) OVERRIDE;
+                        bool alt_pressed) override;
+  bool RemoveAccelerator(int command_id) override;
+  bool RemoveAcceleratorAt(size_t index) override;
   bool GetAccelerator(int command_id,
                       int& key_code,
                       bool& shift_pressed,
                       bool& ctrl_pressed,
-                      bool& alt_pressed) OVERRIDE;
-  bool GetAcceleratorAt(int index,
+                      bool& alt_pressed) override;
+  bool GetAcceleratorAt(size_t index,
                         int& key_code,
                         bool& shift_pressed,
                         bool& ctrl_pressed,
-                        bool& alt_pressed) OVERRIDE;
+                        bool& alt_pressed) override;
   bool SetColor(int command_id,
                 cef_menu_color_type_t color_type,
-                cef_color_t color) OVERRIDE;
+                cef_color_t color) override;
   bool SetColorAt(int index,
                   cef_menu_color_type_t color_type,
-                  cef_color_t color) OVERRIDE;
+                  cef_color_t color) override;
   bool GetColor(int command_id,
                 cef_menu_color_type_t color_type,
-                cef_color_t& color) OVERRIDE;
+                cef_color_t& color) override;
   bool GetColorAt(int index,
                   cef_menu_color_type_t color_type,
-                  cef_color_t& color) OVERRIDE;
-  bool SetFontList(int command_id, const CefString& font_list) OVERRIDE;
-  bool SetFontListAt(int index, const CefString& font_list) OVERRIDE;
+                  cef_color_t& color) override;
+  bool SetFontList(int command_id, const CefString& font_list) override;
+  bool SetFontListAt(int index, const CefString& font_list) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_MENU_MODEL_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/menu_model_delegate_ctocpp.cc b/src/libcef_dll/ctocpp/menu_model_delegate_ctocpp.cc
index 92e8fb4..fcd8062 100644
--- a/src/libcef_dll/ctocpp/menu_model_delegate_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/menu_model_delegate_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c423c0e433e50b85f28dea833aa19e12404f3139$
+// $hash=f734e948a17b74234c1b1bc294b8856ce58ff49e$
 //
 
 #include "libcef_dll/ctocpp/menu_model_delegate_ctocpp.h"
@@ -26,15 +26,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, execute_command))
+  if (CEF_MEMBER_MISSING(_struct, execute_command)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: menu_model; type: refptr_diff
   DCHECK(menu_model.get());
-  if (!menu_model.get())
+  if (!menu_model.get()) {
     return;
+  }
 
   // Execute
   _struct->execute_command(_struct, CefMenuModelCppToC::Wrap(menu_model),
@@ -48,15 +50,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, mouse_outside_menu))
+  if (CEF_MEMBER_MISSING(_struct, mouse_outside_menu)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: menu_model; type: refptr_diff
   DCHECK(menu_model.get());
-  if (!menu_model.get())
+  if (!menu_model.get()) {
     return;
+  }
 
   // Execute
   _struct->mouse_outside_menu(_struct, CefMenuModelCppToC::Wrap(menu_model),
@@ -70,15 +74,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, unhandled_open_submenu))
+  if (CEF_MEMBER_MISSING(_struct, unhandled_open_submenu)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: menu_model; type: refptr_diff
   DCHECK(menu_model.get());
-  if (!menu_model.get())
+  if (!menu_model.get()) {
     return;
+  }
 
   // Execute
   _struct->unhandled_open_submenu(_struct, CefMenuModelCppToC::Wrap(menu_model),
@@ -92,15 +98,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, unhandled_close_submenu))
+  if (CEF_MEMBER_MISSING(_struct, unhandled_close_submenu)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: menu_model; type: refptr_diff
   DCHECK(menu_model.get());
-  if (!menu_model.get())
+  if (!menu_model.get()) {
     return;
+  }
 
   // Execute
   _struct->unhandled_close_submenu(
@@ -113,15 +121,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, menu_will_show))
+  if (CEF_MEMBER_MISSING(_struct, menu_will_show)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: menu_model; type: refptr_diff
   DCHECK(menu_model.get());
-  if (!menu_model.get())
+  if (!menu_model.get()) {
     return;
+  }
 
   // Execute
   _struct->menu_will_show(_struct, CefMenuModelCppToC::Wrap(menu_model));
@@ -133,15 +143,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, menu_closed))
+  if (CEF_MEMBER_MISSING(_struct, menu_closed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: menu_model; type: refptr_diff
   DCHECK(menu_model.get());
-  if (!menu_model.get())
+  if (!menu_model.get()) {
     return;
+  }
 
   // Execute
   _struct->menu_closed(_struct, CefMenuModelCppToC::Wrap(menu_model));
@@ -153,15 +165,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_model_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, format_label))
+  if (CEF_MEMBER_MISSING(_struct, format_label)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: menu_model; type: refptr_diff
   DCHECK(menu_model.get());
-  if (!menu_model.get())
+  if (!menu_model.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->format_label(
@@ -187,7 +201,7 @@
     CefMenuModelDelegate,
     cef_menu_model_delegate_t>::UnwrapDerived(CefWrapperType type,
                                               CefMenuModelDelegate* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/menu_model_delegate_ctocpp.h b/src/libcef_dll/ctocpp/menu_model_delegate_ctocpp.h
index 4984072..7762f4e 100644
--- a/src/libcef_dll/ctocpp/menu_model_delegate_ctocpp.h
+++ b/src/libcef_dll/ctocpp/menu_model_delegate_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6c64e0f39bd2f6bba5cf6ba3a7d70f494e5b5d42$
+// $hash=6ac8a9990cf50850d8f8716096094d1180215be9$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_MENU_MODEL_DELEGATE_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/navigation_entry_ctocpp.cc b/src/libcef_dll/ctocpp/navigation_entry_ctocpp.cc
index ee443c2..e8133b6 100644
--- a/src/libcef_dll/ctocpp/navigation_entry_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/navigation_entry_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c6f680dcbbea79f362a1d7686d7af902be9f0f9b$
+// $hash=4adb66632fea25a6f73e03ee839cc77567841db2$
 //
 
 #include "libcef_dll/ctocpp/navigation_entry_ctocpp.h"
@@ -22,8 +22,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_navigation_entry_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -38,8 +39,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_navigation_entry_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_url))
+  if (CEF_MEMBER_MISSING(_struct, get_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -56,8 +58,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_navigation_entry_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_display_url))
+  if (CEF_MEMBER_MISSING(_struct, get_display_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -74,8 +77,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_navigation_entry_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_original_url))
+  if (CEF_MEMBER_MISSING(_struct, get_original_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -92,8 +96,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_navigation_entry_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_title))
+  if (CEF_MEMBER_MISSING(_struct, get_title)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -112,8 +117,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_navigation_entry_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_transition_type))
+  if (CEF_MEMBER_MISSING(_struct, get_transition_type)) {
     return TT_EXPLICIT;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -128,8 +134,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_navigation_entry_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_post_data))
+  if (CEF_MEMBER_MISSING(_struct, has_post_data)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -140,17 +147,19 @@
   return _retval ? true : false;
 }
 
-NO_SANITIZE("cfi-icall") CefTime CefNavigationEntryCToCpp::GetCompletionTime() {
+NO_SANITIZE("cfi-icall")
+CefBaseTime CefNavigationEntryCToCpp::GetCompletionTime() {
   shutdown_checker::AssertNotShutdown();
 
   cef_navigation_entry_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_completion_time))
-    return CefTime();
+  if (CEF_MEMBER_MISSING(_struct, get_completion_time)) {
+    return CefBaseTime();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  cef_time_t _retval = _struct->get_completion_time(_struct);
+  cef_basetime_t _retval = _struct->get_completion_time(_struct);
 
   // Return type: simple
   return _retval;
@@ -160,8 +169,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_navigation_entry_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_http_status_code))
+  if (CEF_MEMBER_MISSING(_struct, get_http_status_code)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -177,8 +187,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_navigation_entry_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_sslstatus))
+  if (CEF_MEMBER_MISSING(_struct, get_sslstatus)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -205,7 +216,7 @@
     CefNavigationEntry,
     cef_navigation_entry_t>::UnwrapDerived(CefWrapperType type,
                                            CefNavigationEntry* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/navigation_entry_ctocpp.h b/src/libcef_dll/ctocpp/navigation_entry_ctocpp.h
index 02ee0d3..3551378 100644
--- a/src/libcef_dll/ctocpp/navigation_entry_ctocpp.h
+++ b/src/libcef_dll/ctocpp/navigation_entry_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7276d243be0acdd65e29503571afcc55d6eb00fd$
+// $hash=09c6bbd82ec82943b6f310c5ffb347bfbef2654c$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_NAVIGATION_ENTRY_CTOCPP_H_
@@ -35,16 +35,16 @@
   virtual ~CefNavigationEntryCToCpp();
 
   // CefNavigationEntry methods.
-  bool IsValid() OVERRIDE;
-  CefString GetURL() OVERRIDE;
-  CefString GetDisplayURL() OVERRIDE;
-  CefString GetOriginalURL() OVERRIDE;
-  CefString GetTitle() OVERRIDE;
-  TransitionType GetTransitionType() OVERRIDE;
-  bool HasPostData() OVERRIDE;
-  CefTime GetCompletionTime() OVERRIDE;
-  int GetHttpStatusCode() OVERRIDE;
-  CefRefPtr<CefSSLStatus> GetSSLStatus() OVERRIDE;
+  bool IsValid() override;
+  CefString GetURL() override;
+  CefString GetDisplayURL() override;
+  CefString GetOriginalURL() override;
+  CefString GetTitle() override;
+  TransitionType GetTransitionType() override;
+  bool HasPostData() override;
+  CefBaseTime GetCompletionTime() override;
+  int GetHttpStatusCode() override;
+  CefRefPtr<CefSSLStatus> GetSSLStatus() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_NAVIGATION_ENTRY_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/navigation_entry_visitor_ctocpp.cc b/src/libcef_dll/ctocpp/navigation_entry_visitor_ctocpp.cc
index 9191785..1f90bf7 100644
--- a/src/libcef_dll/ctocpp/navigation_entry_visitor_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/navigation_entry_visitor_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e927c676714bc7ebebb03468d963881da643eb50$
+// $hash=a9eb25ebb857e3e63d6e261f8e4b2b171c8fcf34$
 //
 
 #include "libcef_dll/ctocpp/navigation_entry_visitor_ctocpp.h"
@@ -26,15 +26,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_navigation_entry_visitor_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, visit))
+  if (CEF_MEMBER_MISSING(_struct, visit)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: entry; type: refptr_diff
   DCHECK(entry.get());
-  if (!entry.get())
+  if (!entry.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->visit(_struct, CefNavigationEntryCppToC::Wrap(entry),
@@ -61,7 +63,7 @@
     cef_navigation_entry_visitor_t>::UnwrapDerived(CefWrapperType type,
                                                    CefNavigationEntryVisitor*
                                                        c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/navigation_entry_visitor_ctocpp.h b/src/libcef_dll/ctocpp/navigation_entry_visitor_ctocpp.h
index 0858945..bcaa2c9 100644
--- a/src/libcef_dll/ctocpp/navigation_entry_visitor_ctocpp.h
+++ b/src/libcef_dll/ctocpp/navigation_entry_visitor_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d4079700fe4abeacdcaf8dd40493df062736f785$
+// $hash=3dbe29abccbfa1d1cc7014630bbe312d9de42ac8$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_NAVIGATION_ENTRY_VISITOR_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/pdf_print_callback_ctocpp.cc b/src/libcef_dll/ctocpp/pdf_print_callback_ctocpp.cc
index eb59895..d46bb5a 100644
--- a/src/libcef_dll/ctocpp/pdf_print_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/pdf_print_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0b9a4766622f15290ae7328c08f1b28eb2d2275d$
+// $hash=f235c0f4a088d1b4487af49d98c5d08044b1419c$
 //
 
 #include "libcef_dll/ctocpp/pdf_print_callback_ctocpp.h"
@@ -23,15 +23,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_pdf_print_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_pdf_print_finished))
+  if (CEF_MEMBER_MISSING(_struct, on_pdf_print_finished)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: path; type: string_byref_const
   DCHECK(!path.empty());
-  if (path.empty())
+  if (path.empty()) {
     return;
+  }
 
   // Execute
   _struct->on_pdf_print_finished(_struct, path.GetStruct(), ok);
@@ -53,7 +55,7 @@
     CefPdfPrintCallback,
     cef_pdf_print_callback_t>::UnwrapDerived(CefWrapperType type,
                                              CefPdfPrintCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/pdf_print_callback_ctocpp.h b/src/libcef_dll/ctocpp/pdf_print_callback_ctocpp.h
index b48c70b..7abf1c1 100644
--- a/src/libcef_dll/ctocpp/pdf_print_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/pdf_print_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6e5e0048a9472dd5ac056b81abaf08c0d58dead2$
+// $hash=0387fbd8f6ad59dac67959eeded82630a2bba935$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_PDF_PRINT_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/permission_handler_ctocpp.cc b/src/libcef_dll/ctocpp/permission_handler_ctocpp.cc
new file mode 100644
index 0000000..25146ec
--- /dev/null
+++ b/src/libcef_dll/ctocpp/permission_handler_ctocpp.cc
@@ -0,0 +1,162 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=2461a078bc8ccb378b66d02981ca0dbe0f631452$
+//
+
+#include "libcef_dll/ctocpp/permission_handler_ctocpp.h"
+#include "libcef_dll/cpptoc/browser_cpptoc.h"
+#include "libcef_dll/cpptoc/frame_cpptoc.h"
+#include "libcef_dll/cpptoc/media_access_callback_cpptoc.h"
+#include "libcef_dll/cpptoc/permission_prompt_callback_cpptoc.h"
+#include "libcef_dll/shutdown_checker.h"
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall")
+bool CefPermissionHandlerCToCpp::OnRequestMediaAccessPermission(
+    CefRefPtr<CefBrowser> browser,
+    CefRefPtr<CefFrame> frame,
+    const CefString& requesting_origin,
+    uint32_t requested_permissions,
+    CefRefPtr<CefMediaAccessCallback> callback) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_permission_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_request_media_access_permission)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return false;
+  }
+  // Verify param: frame; type: refptr_diff
+  DCHECK(frame.get());
+  if (!frame.get()) {
+    return false;
+  }
+  // Verify param: requesting_origin; type: string_byref_const
+  DCHECK(!requesting_origin.empty());
+  if (requesting_origin.empty()) {
+    return false;
+  }
+  // Verify param: callback; type: refptr_diff
+  DCHECK(callback.get());
+  if (!callback.get()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->on_request_media_access_permission(
+      _struct, CefBrowserCppToC::Wrap(browser), CefFrameCppToC::Wrap(frame),
+      requesting_origin.GetStruct(), requested_permissions,
+      CefMediaAccessCallbackCppToC::Wrap(callback));
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefPermissionHandlerCToCpp::OnShowPermissionPrompt(
+    CefRefPtr<CefBrowser> browser,
+    uint64_t prompt_id,
+    const CefString& requesting_origin,
+    uint32_t requested_permissions,
+    CefRefPtr<CefPermissionPromptCallback> callback) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_permission_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_show_permission_prompt)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return false;
+  }
+  // Verify param: requesting_origin; type: string_byref_const
+  DCHECK(!requesting_origin.empty());
+  if (requesting_origin.empty()) {
+    return false;
+  }
+  // Verify param: callback; type: refptr_diff
+  DCHECK(callback.get());
+  if (!callback.get()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->on_show_permission_prompt(
+      _struct, CefBrowserCppToC::Wrap(browser), prompt_id,
+      requesting_origin.GetStruct(), requested_permissions,
+      CefPermissionPromptCallbackCppToC::Wrap(callback));
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+void CefPermissionHandlerCToCpp::OnDismissPermissionPrompt(
+    CefRefPtr<CefBrowser> browser,
+    uint64_t prompt_id,
+    cef_permission_request_result_t result) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_permission_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_dismiss_permission_prompt)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_dismiss_permission_prompt(
+      _struct, CefBrowserCppToC::Wrap(browser), prompt_id, result);
+}
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefPermissionHandlerCToCpp::CefPermissionHandlerCToCpp() {}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefPermissionHandlerCToCpp::~CefPermissionHandlerCToCpp() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+cef_permission_handler_t* CefCToCppRefCounted<
+    CefPermissionHandlerCToCpp,
+    CefPermissionHandler,
+    cef_permission_handler_t>::UnwrapDerived(CefWrapperType type,
+                                             CefPermissionHandler* c) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCToCppRefCounted<CefPermissionHandlerCToCpp,
+                                   CefPermissionHandler,
+                                   cef_permission_handler_t>::kWrapperType =
+    WT_PERMISSION_HANDLER;
diff --git a/src/libcef_dll/ctocpp/permission_handler_ctocpp.h b/src/libcef_dll/ctocpp/permission_handler_ctocpp.h
new file mode 100644
index 0000000..6f4d521
--- /dev/null
+++ b/src/libcef_dll/ctocpp/permission_handler_ctocpp.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=71589a699700902297887e1f07de72df32630f15$
+//
+
+#ifndef CEF_LIBCEF_DLL_CTOCPP_PERMISSION_HANDLER_CTOCPP_H_
+#define CEF_LIBCEF_DLL_CTOCPP_PERMISSION_HANDLER_CTOCPP_H_
+#pragma once
+
+#if !defined(BUILDING_CEF_SHARED)
+#error This file can be included DLL-side only
+#endif
+
+#include "include/capi/cef_permission_handler_capi.h"
+#include "include/cef_permission_handler.h"
+#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
+
+// Wrap a C structure with a C++ class.
+// This class may be instantiated and accessed DLL-side only.
+class CefPermissionHandlerCToCpp
+    : public CefCToCppRefCounted<CefPermissionHandlerCToCpp,
+                                 CefPermissionHandler,
+                                 cef_permission_handler_t> {
+ public:
+  CefPermissionHandlerCToCpp();
+  virtual ~CefPermissionHandlerCToCpp();
+
+  // CefPermissionHandler methods.
+  bool OnRequestMediaAccessPermission(
+      CefRefPtr<CefBrowser> browser,
+      CefRefPtr<CefFrame> frame,
+      const CefString& requesting_origin,
+      uint32_t requested_permissions,
+      CefRefPtr<CefMediaAccessCallback> callback) override;
+  bool OnShowPermissionPrompt(
+      CefRefPtr<CefBrowser> browser,
+      uint64_t prompt_id,
+      const CefString& requesting_origin,
+      uint32_t requested_permissions,
+      CefRefPtr<CefPermissionPromptCallback> callback) override;
+  void OnDismissPermissionPrompt(
+      CefRefPtr<CefBrowser> browser,
+      uint64_t prompt_id,
+      cef_permission_request_result_t result) override;
+};
+
+#endif  // CEF_LIBCEF_DLL_CTOCPP_PERMISSION_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/permission_prompt_callback_ctocpp.cc b/src/libcef_dll/ctocpp/permission_prompt_callback_ctocpp.cc
new file mode 100644
index 0000000..1e2caed
--- /dev/null
+++ b/src/libcef_dll/ctocpp/permission_prompt_callback_ctocpp.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=a84aa33807e480e03cc065b3b195d2fcf766cbfb$
+//
+
+#include "libcef_dll/ctocpp/permission_prompt_callback_ctocpp.h"
+#include "libcef_dll/shutdown_checker.h"
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall")
+void CefPermissionPromptCallbackCToCpp::Continue(
+    cef_permission_request_result_t result) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_permission_prompt_callback_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, cont)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->cont(_struct, result);
+}
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefPermissionPromptCallbackCToCpp::CefPermissionPromptCallbackCToCpp() {}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefPermissionPromptCallbackCToCpp::~CefPermissionPromptCallbackCToCpp() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+cef_permission_prompt_callback_t*
+CefCToCppRefCounted<CefPermissionPromptCallbackCToCpp,
+                    CefPermissionPromptCallback,
+                    cef_permission_prompt_callback_t>::
+    UnwrapDerived(CefWrapperType type, CefPermissionPromptCallback* c) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType
+    CefCToCppRefCounted<CefPermissionPromptCallbackCToCpp,
+                        CefPermissionPromptCallback,
+                        cef_permission_prompt_callback_t>::kWrapperType =
+        WT_PERMISSION_PROMPT_CALLBACK;
diff --git a/src/libcef_dll/ctocpp/permission_prompt_callback_ctocpp.h b/src/libcef_dll/ctocpp/permission_prompt_callback_ctocpp.h
new file mode 100644
index 0000000..be82ab7
--- /dev/null
+++ b/src/libcef_dll/ctocpp/permission_prompt_callback_ctocpp.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=8b2ed4405822451f9bae6ae35d589611b6c8e0f3$
+//
+
+#ifndef CEF_LIBCEF_DLL_CTOCPP_PERMISSION_PROMPT_CALLBACK_CTOCPP_H_
+#define CEF_LIBCEF_DLL_CTOCPP_PERMISSION_PROMPT_CALLBACK_CTOCPP_H_
+#pragma once
+
+#if !defined(WRAPPING_CEF_SHARED)
+#error This file can be included wrapper-side only
+#endif
+
+#include "include/capi/cef_permission_handler_capi.h"
+#include "include/cef_permission_handler.h"
+#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
+
+// Wrap a C structure with a C++ class.
+// This class may be instantiated and accessed wrapper-side only.
+class CefPermissionPromptCallbackCToCpp
+    : public CefCToCppRefCounted<CefPermissionPromptCallbackCToCpp,
+                                 CefPermissionPromptCallback,
+                                 cef_permission_prompt_callback_t> {
+ public:
+  CefPermissionPromptCallbackCToCpp();
+  virtual ~CefPermissionPromptCallbackCToCpp();
+
+  // CefPermissionPromptCallback methods.
+  void Continue(cef_permission_request_result_t result) override;
+};
+
+#endif  // CEF_LIBCEF_DLL_CTOCPP_PERMISSION_PROMPT_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/post_data_ctocpp.cc b/src/libcef_dll/ctocpp/post_data_ctocpp.cc
index 73b7fcd..ac3410c 100644
--- a/src/libcef_dll/ctocpp/post_data_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/post_data_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=895c319a8cdcb9d38eeeb55e98cb9bdb44a51b90$
+// $hash=35bed657bdfd1e13a8b76b44a0d58d1473663e9d$
 //
 
 #include "libcef_dll/ctocpp/post_data_ctocpp.h"
@@ -32,8 +32,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefPostDataCToCpp::IsReadOnly() {
   cef_post_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_read_only))
+  if (CEF_MEMBER_MISSING(_struct, is_read_only)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -46,8 +47,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefPostDataCToCpp::HasExcludedElements() {
   cef_post_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_excluded_elements))
+  if (CEF_MEMBER_MISSING(_struct, has_excluded_elements)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -60,8 +62,9 @@
 
 NO_SANITIZE("cfi-icall") size_t CefPostDataCToCpp::GetElementCount() {
   cef_post_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_element_count))
+  if (CEF_MEMBER_MISSING(_struct, get_element_count)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -75,8 +78,9 @@
 NO_SANITIZE("cfi-icall")
 void CefPostDataCToCpp::GetElements(ElementVector& elements) {
   cef_post_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_elements))
+  if (CEF_MEMBER_MISSING(_struct, get_elements)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -113,15 +117,17 @@
 NO_SANITIZE("cfi-icall")
 bool CefPostDataCToCpp::RemoveElement(CefRefPtr<CefPostDataElement> element) {
   cef_post_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, remove_element))
+  if (CEF_MEMBER_MISSING(_struct, remove_element)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: element; type: refptr_same
   DCHECK(element.get());
-  if (!element.get())
+  if (!element.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->remove_element(
@@ -134,15 +140,17 @@
 NO_SANITIZE("cfi-icall")
 bool CefPostDataCToCpp::AddElement(CefRefPtr<CefPostDataElement> element) {
   cef_post_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, add_element))
+  if (CEF_MEMBER_MISSING(_struct, add_element)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: element; type: refptr_same
   DCHECK(element.get());
-  if (!element.get())
+  if (!element.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -154,8 +162,9 @@
 
 NO_SANITIZE("cfi-icall") void CefPostDataCToCpp::RemoveElements() {
   cef_post_data_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, remove_elements))
+  if (CEF_MEMBER_MISSING(_struct, remove_elements)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -175,7 +184,7 @@
 cef_post_data_t*
 CefCToCppRefCounted<CefPostDataCToCpp, CefPostData, cef_post_data_t>::
     UnwrapDerived(CefWrapperType type, CefPostData* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/post_data_ctocpp.h b/src/libcef_dll/ctocpp/post_data_ctocpp.h
index 469f3ed..7666035 100644
--- a/src/libcef_dll/ctocpp/post_data_ctocpp.h
+++ b/src/libcef_dll/ctocpp/post_data_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0710e94a6132f440de0c46ce73ca1d4a36af2857$
+// $hash=e70d58d7c779528d03b49ead50c162ebf0eb0ca7$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_POST_DATA_CTOCPP_H_
@@ -34,13 +34,13 @@
   virtual ~CefPostDataCToCpp();
 
   // CefPostData methods.
-  bool IsReadOnly() OVERRIDE;
-  bool HasExcludedElements() OVERRIDE;
-  size_t GetElementCount() OVERRIDE;
-  void GetElements(ElementVector& elements) OVERRIDE;
-  bool RemoveElement(CefRefPtr<CefPostDataElement> element) OVERRIDE;
-  bool AddElement(CefRefPtr<CefPostDataElement> element) OVERRIDE;
-  void RemoveElements() OVERRIDE;
+  bool IsReadOnly() override;
+  bool HasExcludedElements() override;
+  size_t GetElementCount() override;
+  void GetElements(ElementVector& elements) override;
+  bool RemoveElement(CefRefPtr<CefPostDataElement> element) override;
+  bool AddElement(CefRefPtr<CefPostDataElement> element) override;
+  void RemoveElements() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_POST_DATA_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/post_data_element_ctocpp.cc b/src/libcef_dll/ctocpp/post_data_element_ctocpp.cc
index 24c73c8..07d71de 100644
--- a/src/libcef_dll/ctocpp/post_data_element_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/post_data_element_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=89f51160ee669abdfee47c627c7b7fec0b034b2b$
+// $hash=aa7dd08d585fb1c151ac70040266b2cc6daaa8fd$
 //
 
 #include "libcef_dll/ctocpp/post_data_element_ctocpp.h"
@@ -31,8 +31,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefPostDataElementCToCpp::IsReadOnly() {
   cef_post_data_element_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_read_only))
+  if (CEF_MEMBER_MISSING(_struct, is_read_only)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -45,8 +46,9 @@
 
 NO_SANITIZE("cfi-icall") void CefPostDataElementCToCpp::SetToEmpty() {
   cef_post_data_element_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_to_empty))
+  if (CEF_MEMBER_MISSING(_struct, set_to_empty)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -57,15 +59,17 @@
 NO_SANITIZE("cfi-icall")
 void CefPostDataElementCToCpp::SetToFile(const CefString& fileName) {
   cef_post_data_element_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_to_file))
+  if (CEF_MEMBER_MISSING(_struct, set_to_file)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: fileName; type: string_byref_const
   DCHECK(!fileName.empty());
-  if (fileName.empty())
+  if (fileName.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_to_file(_struct, fileName.GetStruct());
@@ -74,15 +78,17 @@
 NO_SANITIZE("cfi-icall")
 void CefPostDataElementCToCpp::SetToBytes(size_t size, const void* bytes) {
   cef_post_data_element_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_to_bytes))
+  if (CEF_MEMBER_MISSING(_struct, set_to_bytes)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: bytes; type: simple_byaddr
   DCHECK(bytes);
-  if (!bytes)
+  if (!bytes) {
     return;
+  }
 
   // Execute
   _struct->set_to_bytes(_struct, size, bytes);
@@ -91,8 +97,9 @@
 NO_SANITIZE("cfi-icall")
 CefPostDataElement::Type CefPostDataElementCToCpp::GetType() {
   cef_post_data_element_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_type))
+  if (CEF_MEMBER_MISSING(_struct, get_type)) {
     return PDE_TYPE_EMPTY;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -105,8 +112,9 @@
 
 NO_SANITIZE("cfi-icall") CefString CefPostDataElementCToCpp::GetFile() {
   cef_post_data_element_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_file))
+  if (CEF_MEMBER_MISSING(_struct, get_file)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -121,8 +129,9 @@
 
 NO_SANITIZE("cfi-icall") size_t CefPostDataElementCToCpp::GetBytesCount() {
   cef_post_data_element_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_bytes_count))
+  if (CEF_MEMBER_MISSING(_struct, get_bytes_count)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -136,15 +145,17 @@
 NO_SANITIZE("cfi-icall")
 size_t CefPostDataElementCToCpp::GetBytes(size_t size, void* bytes) {
   cef_post_data_element_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_bytes))
+  if (CEF_MEMBER_MISSING(_struct, get_bytes)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: bytes; type: simple_byaddr
   DCHECK(bytes);
-  if (!bytes)
+  if (!bytes) {
     return 0;
+  }
 
   // Execute
   size_t _retval = _struct->get_bytes(_struct, size, bytes);
@@ -167,7 +178,7 @@
     CefPostDataElement,
     cef_post_data_element_t>::UnwrapDerived(CefWrapperType type,
                                             CefPostDataElement* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/post_data_element_ctocpp.h b/src/libcef_dll/ctocpp/post_data_element_ctocpp.h
index c49cf53..e422be5 100644
--- a/src/libcef_dll/ctocpp/post_data_element_ctocpp.h
+++ b/src/libcef_dll/ctocpp/post_data_element_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ee4fd5dcea725326c5885cf30c4b0bc5dbd76a01$
+// $hash=a81732545889a9d401edb7f5540e0762bb787526$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_POST_DATA_ELEMENT_CTOCPP_H_
@@ -35,14 +35,14 @@
   virtual ~CefPostDataElementCToCpp();
 
   // CefPostDataElement methods.
-  bool IsReadOnly() OVERRIDE;
-  void SetToEmpty() OVERRIDE;
-  void SetToFile(const CefString& fileName) OVERRIDE;
-  void SetToBytes(size_t size, const void* bytes) OVERRIDE;
-  Type GetType() OVERRIDE;
-  CefString GetFile() OVERRIDE;
-  size_t GetBytesCount() OVERRIDE;
-  size_t GetBytes(size_t size, void* bytes) OVERRIDE;
+  bool IsReadOnly() override;
+  void SetToEmpty() override;
+  void SetToFile(const CefString& fileName) override;
+  void SetToBytes(size_t size, const void* bytes) override;
+  Type GetType() override;
+  CefString GetFile() override;
+  size_t GetBytesCount() override;
+  size_t GetBytes(size_t size, void* bytes) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_POST_DATA_ELEMENT_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/preference_manager_ctocpp.cc b/src/libcef_dll/ctocpp/preference_manager_ctocpp.cc
new file mode 100644
index 0000000..ab598f0
--- /dev/null
+++ b/src/libcef_dll/ctocpp/preference_manager_ctocpp.cc
@@ -0,0 +1,175 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=b992dc943eedb028a5018c6204aa6ce9a106b367$
+//
+
+#include "libcef_dll/ctocpp/preference_manager_ctocpp.h"
+#include "libcef_dll/ctocpp/dictionary_value_ctocpp.h"
+#include "libcef_dll/ctocpp/request_context_ctocpp.h"
+#include "libcef_dll/ctocpp/value_ctocpp.h"
+
+// STATIC METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall")
+CefRefPtr<CefPreferenceManager>
+CefPreferenceManager::GetGlobalPreferenceManager() {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_preference_manager_t* _retval = cef_preference_manager_get_global();
+
+  // Return type: refptr_same
+  return CefPreferenceManagerCToCpp::Wrap(_retval);
+}
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall")
+bool CefPreferenceManagerCToCpp::HasPreference(const CefString& name) {
+  cef_preference_manager_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, has_preference)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: name; type: string_byref_const
+  DCHECK(!name.empty());
+  if (name.empty()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->has_preference(_struct, name.GetStruct());
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+CefRefPtr<CefValue> CefPreferenceManagerCToCpp::GetPreference(
+    const CefString& name) {
+  cef_preference_manager_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_preference)) {
+    return nullptr;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: name; type: string_byref_const
+  DCHECK(!name.empty());
+  if (name.empty()) {
+    return nullptr;
+  }
+
+  // Execute
+  cef_value_t* _retval = _struct->get_preference(_struct, name.GetStruct());
+
+  // Return type: refptr_same
+  return CefValueCToCpp::Wrap(_retval);
+}
+
+NO_SANITIZE("cfi-icall")
+CefRefPtr<CefDictionaryValue> CefPreferenceManagerCToCpp::GetAllPreferences(
+    bool include_defaults) {
+  cef_preference_manager_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_all_preferences)) {
+    return nullptr;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_dictionary_value_t* _retval =
+      _struct->get_all_preferences(_struct, include_defaults);
+
+  // Return type: refptr_same
+  return CefDictionaryValueCToCpp::Wrap(_retval);
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefPreferenceManagerCToCpp::CanSetPreference(const CefString& name) {
+  cef_preference_manager_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, can_set_preference)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: name; type: string_byref_const
+  DCHECK(!name.empty());
+  if (name.empty()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->can_set_preference(_struct, name.GetStruct());
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefPreferenceManagerCToCpp::SetPreference(const CefString& name,
+                                               CefRefPtr<CefValue> value,
+                                               CefString& error) {
+  cef_preference_manager_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, set_preference)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: name; type: string_byref_const
+  DCHECK(!name.empty());
+  if (name.empty()) {
+    return false;
+  }
+  // Unverified params: value
+
+  // Execute
+  int _retval = _struct->set_preference(_struct, name.GetStruct(),
+                                        CefValueCToCpp::Unwrap(value),
+                                        error.GetWritableStruct());
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefPreferenceManagerCToCpp::CefPreferenceManagerCToCpp() {}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefPreferenceManagerCToCpp::~CefPreferenceManagerCToCpp() {}
+
+template <>
+cef_preference_manager_t* CefCToCppRefCounted<
+    CefPreferenceManagerCToCpp,
+    CefPreferenceManager,
+    cef_preference_manager_t>::UnwrapDerived(CefWrapperType type,
+                                             CefPreferenceManager* c) {
+  if (type == WT_REQUEST_CONTEXT) {
+    return reinterpret_cast<cef_preference_manager_t*>(
+        CefRequestContextCToCpp::Unwrap(
+            reinterpret_cast<CefRequestContext*>(c)));
+  }
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCToCppRefCounted<CefPreferenceManagerCToCpp,
+                                   CefPreferenceManager,
+                                   cef_preference_manager_t>::kWrapperType =
+    WT_PREFERENCE_MANAGER;
diff --git a/src/libcef_dll/ctocpp/preference_manager_ctocpp.h b/src/libcef_dll/ctocpp/preference_manager_ctocpp.h
new file mode 100644
index 0000000..585a1be
--- /dev/null
+++ b/src/libcef_dll/ctocpp/preference_manager_ctocpp.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=89ee6916279697654c516137ee56f5cbef07e4c0$
+//
+
+#ifndef CEF_LIBCEF_DLL_CTOCPP_PREFERENCE_MANAGER_CTOCPP_H_
+#define CEF_LIBCEF_DLL_CTOCPP_PREFERENCE_MANAGER_CTOCPP_H_
+#pragma once
+
+#if !defined(WRAPPING_CEF_SHARED)
+#error This file can be included wrapper-side only
+#endif
+
+#include "include/capi/cef_preference_capi.h"
+#include "include/cef_preference.h"
+#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
+
+// Wrap a C structure with a C++ class.
+// This class may be instantiated and accessed wrapper-side only.
+class CefPreferenceManagerCToCpp
+    : public CefCToCppRefCounted<CefPreferenceManagerCToCpp,
+                                 CefPreferenceManager,
+                                 cef_preference_manager_t> {
+ public:
+  CefPreferenceManagerCToCpp();
+  virtual ~CefPreferenceManagerCToCpp();
+
+  // CefPreferenceManager methods.
+  bool HasPreference(const CefString& name) override;
+  CefRefPtr<CefValue> GetPreference(const CefString& name) override;
+  CefRefPtr<CefDictionaryValue> GetAllPreferences(
+      bool include_defaults) override;
+  bool CanSetPreference(const CefString& name) override;
+  bool SetPreference(const CefString& name,
+                     CefRefPtr<CefValue> value,
+                     CefString& error) override;
+};
+
+#endif  // CEF_LIBCEF_DLL_CTOCPP_PREFERENCE_MANAGER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/preference_registrar_ctocpp.cc b/src/libcef_dll/ctocpp/preference_registrar_ctocpp.cc
new file mode 100644
index 0000000..98c9f7f
--- /dev/null
+++ b/src/libcef_dll/ctocpp/preference_registrar_ctocpp.cc
@@ -0,0 +1,80 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=c677cabce869cc187866e07f53fcf235018d8978$
+//
+
+#include "libcef_dll/ctocpp/preference_registrar_ctocpp.h"
+#include "libcef_dll/ctocpp/value_ctocpp.h"
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall")
+bool CefPreferenceRegistrarCToCpp::AddPreference(
+    const CefString& name,
+    CefRefPtr<CefValue> default_value) {
+  cef_preference_registrar_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, add_preference)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: name; type: string_byref_const
+  DCHECK(!name.empty());
+  if (name.empty()) {
+    return false;
+  }
+  // Verify param: default_value; type: refptr_same
+  DCHECK(default_value.get());
+  if (!default_value.get()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->add_preference(_struct, name.GetStruct(),
+                                        CefValueCToCpp::Unwrap(default_value));
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefPreferenceRegistrarCToCpp::CefPreferenceRegistrarCToCpp() {}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefPreferenceRegistrarCToCpp::~CefPreferenceRegistrarCToCpp() {}
+
+template <>
+cef_preference_registrar_t* CefCToCppScoped<CefPreferenceRegistrarCToCpp,
+                                            CefPreferenceRegistrar,
+                                            cef_preference_registrar_t>::
+    UnwrapDerivedOwn(CefWrapperType type, CefOwnPtr<CefPreferenceRegistrar> c) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+cef_preference_registrar_t* CefCToCppScoped<CefPreferenceRegistrarCToCpp,
+                                            CefPreferenceRegistrar,
+                                            cef_preference_registrar_t>::
+    UnwrapDerivedRaw(CefWrapperType type, CefRawPtr<CefPreferenceRegistrar> c) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCToCppScoped<CefPreferenceRegistrarCToCpp,
+                               CefPreferenceRegistrar,
+                               cef_preference_registrar_t>::kWrapperType =
+    WT_PREFERENCE_REGISTRAR;
diff --git a/src/libcef_dll/ctocpp/preference_registrar_ctocpp.h b/src/libcef_dll/ctocpp/preference_registrar_ctocpp.h
new file mode 100644
index 0000000..b6b10d3
--- /dev/null
+++ b/src/libcef_dll/ctocpp/preference_registrar_ctocpp.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=bcd7981d2a8feae116d3c658f430f9753c11612d$
+//
+
+#ifndef CEF_LIBCEF_DLL_CTOCPP_PREFERENCE_REGISTRAR_CTOCPP_H_
+#define CEF_LIBCEF_DLL_CTOCPP_PREFERENCE_REGISTRAR_CTOCPP_H_
+#pragma once
+
+#if !defined(WRAPPING_CEF_SHARED)
+#error This file can be included wrapper-side only
+#endif
+
+#include "include/capi/cef_preference_capi.h"
+#include "include/cef_preference.h"
+#include "libcef_dll/ctocpp/ctocpp_scoped.h"
+
+// Wrap a C structure with a C++ class.
+// This class may be instantiated and accessed wrapper-side only.
+class CefPreferenceRegistrarCToCpp
+    : public CefCToCppScoped<CefPreferenceRegistrarCToCpp,
+                             CefPreferenceRegistrar,
+                             cef_preference_registrar_t> {
+ public:
+  CefPreferenceRegistrarCToCpp();
+  virtual ~CefPreferenceRegistrarCToCpp();
+
+  // CefPreferenceRegistrar methods.
+  bool AddPreference(const CefString& name,
+                     CefRefPtr<CefValue> default_value) override;
+};
+
+#endif  // CEF_LIBCEF_DLL_CTOCPP_PREFERENCE_REGISTRAR_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/print_dialog_callback_ctocpp.cc b/src/libcef_dll/ctocpp/print_dialog_callback_ctocpp.cc
index 0dd8ca5..907eafe 100644
--- a/src/libcef_dll/ctocpp/print_dialog_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/print_dialog_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c013c03a8fd2436c90587a96bb4960869888667a$
+// $hash=0c0a1efb7a6ed661e2947b9b820e1fb5b57e0ad3$
 //
 
 #include "libcef_dll/ctocpp/print_dialog_callback_ctocpp.h"
@@ -24,15 +24,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_dialog_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cont))
+  if (CEF_MEMBER_MISSING(_struct, cont)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: settings; type: refptr_same
   DCHECK(settings.get());
-  if (!settings.get())
+  if (!settings.get()) {
     return;
+  }
 
   // Execute
   _struct->cont(_struct, CefPrintSettingsCToCpp::Unwrap(settings));
@@ -42,8 +44,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_dialog_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cancel))
+  if (CEF_MEMBER_MISSING(_struct, cancel)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -67,7 +70,7 @@
     CefPrintDialogCallback,
     cef_print_dialog_callback_t>::UnwrapDerived(CefWrapperType type,
                                                 CefPrintDialogCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/print_dialog_callback_ctocpp.h b/src/libcef_dll/ctocpp/print_dialog_callback_ctocpp.h
index 74a09b9..cf5e9cb 100644
--- a/src/libcef_dll/ctocpp/print_dialog_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/print_dialog_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3df7f45bbfe22ab9ff61f15dc9234c5a47ec72b9$
+// $hash=7c49e07c9ba8bfc8f7620952b19140828a3bf011$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_PRINT_DIALOG_CALLBACK_CTOCPP_H_
@@ -35,8 +35,8 @@
   virtual ~CefPrintDialogCallbackCToCpp();
 
   // CefPrintDialogCallback methods.
-  void Continue(CefRefPtr<CefPrintSettings> settings) OVERRIDE;
-  void Cancel() OVERRIDE;
+  void Continue(CefRefPtr<CefPrintSettings> settings) override;
+  void Cancel() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_PRINT_DIALOG_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/print_handler_ctocpp.cc b/src/libcef_dll/ctocpp/print_handler_ctocpp.cc
index 1fe5155..81b6f72 100644
--- a/src/libcef_dll/ctocpp/print_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/print_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b9fc8704be8fced9d4fe3ac048aaa716e1b14d0b$
+// $hash=95827cf69c533ca04e0e49e45d5e36b507378aeb$
 //
 
 #include "libcef_dll/ctocpp/print_handler_ctocpp.h"
@@ -26,15 +26,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_print_start))
+  if (CEF_MEMBER_MISSING(_struct, on_print_start)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_print_start(_struct, CefBrowserCppToC::Wrap(browser));
@@ -48,19 +50,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_print_settings))
+  if (CEF_MEMBER_MISSING(_struct, on_print_settings)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: settings; type: refptr_diff
   DCHECK(settings.get());
-  if (!settings.get())
+  if (!settings.get()) {
     return;
+  }
 
   // Execute
   _struct->on_print_settings(_struct, CefBrowserCppToC::Wrap(browser),
@@ -76,19 +81,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_print_dialog))
+  if (CEF_MEMBER_MISSING(_struct, on_print_dialog)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->on_print_dialog(
@@ -108,27 +116,32 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_print_job))
+  if (CEF_MEMBER_MISSING(_struct, on_print_job)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: document_name; type: string_byref_const
   DCHECK(!document_name.empty());
-  if (document_name.empty())
+  if (document_name.empty()) {
     return false;
+  }
   // Verify param: pdf_file_path; type: string_byref_const
   DCHECK(!pdf_file_path.empty());
-  if (pdf_file_path.empty())
+  if (pdf_file_path.empty()) {
     return false;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->on_print_job(
@@ -144,33 +157,43 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_print_reset))
+  if (CEF_MEMBER_MISSING(_struct, on_print_reset)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_print_reset(_struct, CefBrowserCppToC::Wrap(browser));
 }
 
 NO_SANITIZE("cfi-icall")
-CefSize CefPrintHandlerCToCpp::GetPdfPaperSize(int device_units_per_inch) {
+CefSize CefPrintHandlerCToCpp::GetPdfPaperSize(CefRefPtr<CefBrowser> browser,
+                                               int device_units_per_inch) {
   shutdown_checker::AssertNotShutdown();
 
   cef_print_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_pdf_paper_size))
+  if (CEF_MEMBER_MISSING(_struct, get_pdf_paper_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return CefSize();
+  }
+
   // Execute
-  cef_size_t _retval =
-      _struct->get_pdf_paper_size(_struct, device_units_per_inch);
+  cef_size_t _retval = _struct->get_pdf_paper_size(
+      _struct, CefBrowserCppToC::Wrap(browser), device_units_per_inch);
 
   // Return type: simple
   return _retval;
@@ -192,7 +215,7 @@
                     CefPrintHandler,
                     cef_print_handler_t>::UnwrapDerived(CefWrapperType type,
                                                         CefPrintHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/print_handler_ctocpp.h b/src/libcef_dll/ctocpp/print_handler_ctocpp.h
index 99acc36..5e7722f 100644
--- a/src/libcef_dll/ctocpp/print_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/print_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9cc2a681b89d2958e4537a0e22c3b710702a69f6$
+// $hash=b1d082ab9bea88f46372a371b68b9b4c25a96ca2$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_PRINT_HANDLER_CTOCPP_H_
@@ -46,7 +46,8 @@
                   const CefString& pdf_file_path,
                   CefRefPtr<CefPrintJobCallback> callback) override;
   void OnPrintReset(CefRefPtr<CefBrowser> browser) override;
-  CefSize GetPdfPaperSize(int device_units_per_inch) override;
+  CefSize GetPdfPaperSize(CefRefPtr<CefBrowser> browser,
+                          int device_units_per_inch) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_PRINT_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/print_job_callback_ctocpp.cc b/src/libcef_dll/ctocpp/print_job_callback_ctocpp.cc
index d5b3943..66d50c9 100644
--- a/src/libcef_dll/ctocpp/print_job_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/print_job_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f378864057814460c2cee92c0a31e1e2333220ff$
+// $hash=4ceb6cf047750386cd44026b4b3f7a2caa1dac9e$
 //
 
 #include "libcef_dll/ctocpp/print_job_callback_ctocpp.h"
@@ -21,8 +21,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_job_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cont))
+  if (CEF_MEMBER_MISSING(_struct, cont)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -46,7 +47,7 @@
     CefPrintJobCallback,
     cef_print_job_callback_t>::UnwrapDerived(CefWrapperType type,
                                              CefPrintJobCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/print_job_callback_ctocpp.h b/src/libcef_dll/ctocpp/print_job_callback_ctocpp.h
index fb51a00..6f7710e 100644
--- a/src/libcef_dll/ctocpp/print_job_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/print_job_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=a47d4676a9231ef14492dfc8e61643c583df7f68$
+// $hash=6ac2e8d5475582b66e40e297b192bdbdc8acbeed$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_PRINT_JOB_CALLBACK_CTOCPP_H_
@@ -35,7 +35,7 @@
   virtual ~CefPrintJobCallbackCToCpp();
 
   // CefPrintJobCallback methods.
-  void Continue() OVERRIDE;
+  void Continue() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_PRINT_JOB_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/print_settings_ctocpp.cc b/src/libcef_dll/ctocpp/print_settings_ctocpp.cc
index 4584c63..9e22a83 100644
--- a/src/libcef_dll/ctocpp/print_settings_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/print_settings_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=bb2d141ebf3f887910043a250bf18f95b87d5fc3$
+// $hash=388d22bd24b0e340d9509abec2b654680ac6779d$
 //
 
 #include "libcef_dll/ctocpp/print_settings_ctocpp.h"
@@ -37,8 +37,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -53,8 +54,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_read_only))
+  if (CEF_MEMBER_MISSING(_struct, is_read_only)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -70,8 +72,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_orientation))
+  if (CEF_MEMBER_MISSING(_struct, set_orientation)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -83,8 +86,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_landscape))
+  if (CEF_MEMBER_MISSING(_struct, is_landscape)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -103,8 +107,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_printer_printable_area))
+  if (CEF_MEMBER_MISSING(_struct, set_printer_printable_area)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -119,8 +124,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_device_name))
+  if (CEF_MEMBER_MISSING(_struct, set_device_name)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -134,8 +140,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_device_name))
+  if (CEF_MEMBER_MISSING(_struct, get_device_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -152,8 +159,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_dpi))
+  if (CEF_MEMBER_MISSING(_struct, set_dpi)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -165,8 +173,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_dpi))
+  if (CEF_MEMBER_MISSING(_struct, get_dpi)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -182,8 +191,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_page_ranges))
+  if (CEF_MEMBER_MISSING(_struct, set_page_ranges)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -204,16 +214,18 @@
   _struct->set_page_ranges(_struct, rangesCount, rangesList);
 
   // Restore param:ranges; type: simple_vec_byref_const
-  if (rangesList)
+  if (rangesList) {
     delete[] rangesList;
+  }
 }
 
 NO_SANITIZE("cfi-icall") size_t CefPrintSettingsCToCpp::GetPageRangesCount() {
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_page_ranges_count))
+  if (CEF_MEMBER_MISSING(_struct, get_page_ranges_count)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -229,8 +241,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_page_ranges))
+  if (CEF_MEMBER_MISSING(_struct, get_page_ranges)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -269,8 +282,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_selection_only))
+  if (CEF_MEMBER_MISSING(_struct, set_selection_only)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -282,8 +296,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_selection_only))
+  if (CEF_MEMBER_MISSING(_struct, is_selection_only)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -298,8 +313,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_collate))
+  if (CEF_MEMBER_MISSING(_struct, set_collate)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -311,8 +327,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, will_collate))
+  if (CEF_MEMBER_MISSING(_struct, will_collate)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -328,8 +345,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_color_model))
+  if (CEF_MEMBER_MISSING(_struct, set_color_model)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -342,8 +360,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_color_model))
+  if (CEF_MEMBER_MISSING(_struct, get_color_model)) {
     return COLOR_MODEL_UNKNOWN;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -358,8 +377,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_copies))
+  if (CEF_MEMBER_MISSING(_struct, set_copies)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -371,8 +391,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_copies))
+  if (CEF_MEMBER_MISSING(_struct, get_copies)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -388,8 +409,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_duplex_mode))
+  if (CEF_MEMBER_MISSING(_struct, set_duplex_mode)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -402,8 +424,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_print_settings_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_duplex_mode))
+  if (CEF_MEMBER_MISSING(_struct, get_duplex_mode)) {
     return DUPLEX_MODE_UNKNOWN;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -430,7 +453,7 @@
                     CefPrintSettings,
                     cef_print_settings_t>::UnwrapDerived(CefWrapperType type,
                                                          CefPrintSettings* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/print_settings_ctocpp.h b/src/libcef_dll/ctocpp/print_settings_ctocpp.h
index 6a811cd..3c23fc1 100644
--- a/src/libcef_dll/ctocpp/print_settings_ctocpp.h
+++ b/src/libcef_dll/ctocpp/print_settings_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9fd8b11b774211cbeb1a8921f64d472b062afee7$
+// $hash=75238f577e768438cead970fa7362e4b04856894$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_PRINT_SETTINGS_CTOCPP_H_
@@ -35,30 +35,30 @@
   virtual ~CefPrintSettingsCToCpp();
 
   // CefPrintSettings methods.
-  bool IsValid() OVERRIDE;
-  bool IsReadOnly() OVERRIDE;
-  void SetOrientation(bool landscape) OVERRIDE;
-  bool IsLandscape() OVERRIDE;
+  bool IsValid() override;
+  bool IsReadOnly() override;
+  void SetOrientation(bool landscape) override;
+  bool IsLandscape() override;
   void SetPrinterPrintableArea(const CefSize& physical_size_device_units,
                                const CefRect& printable_area_device_units,
-                               bool landscape_needs_flip) OVERRIDE;
-  void SetDeviceName(const CefString& name) OVERRIDE;
-  CefString GetDeviceName() OVERRIDE;
-  void SetDPI(int dpi) OVERRIDE;
-  int GetDPI() OVERRIDE;
-  void SetPageRanges(const PageRangeList& ranges) OVERRIDE;
-  size_t GetPageRangesCount() OVERRIDE;
-  void GetPageRanges(PageRangeList& ranges) OVERRIDE;
-  void SetSelectionOnly(bool selection_only) OVERRIDE;
-  bool IsSelectionOnly() OVERRIDE;
-  void SetCollate(bool collate) OVERRIDE;
-  bool WillCollate() OVERRIDE;
-  void SetColorModel(ColorModel model) OVERRIDE;
-  ColorModel GetColorModel() OVERRIDE;
-  void SetCopies(int copies) OVERRIDE;
-  int GetCopies() OVERRIDE;
-  void SetDuplexMode(DuplexMode mode) OVERRIDE;
-  DuplexMode GetDuplexMode() OVERRIDE;
+                               bool landscape_needs_flip) override;
+  void SetDeviceName(const CefString& name) override;
+  CefString GetDeviceName() override;
+  void SetDPI(int dpi) override;
+  int GetDPI() override;
+  void SetPageRanges(const PageRangeList& ranges) override;
+  size_t GetPageRangesCount() override;
+  void GetPageRanges(PageRangeList& ranges) override;
+  void SetSelectionOnly(bool selection_only) override;
+  bool IsSelectionOnly() override;
+  void SetCollate(bool collate) override;
+  bool WillCollate() override;
+  void SetColorModel(ColorModel model) override;
+  ColorModel GetColorModel() override;
+  void SetCopies(int copies) override;
+  int GetCopies() override;
+  void SetDuplexMode(DuplexMode mode) override;
+  DuplexMode GetDuplexMode() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_PRINT_SETTINGS_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/process_message_ctocpp.cc b/src/libcef_dll/ctocpp/process_message_ctocpp.cc
index 7963d96..53226af 100644
--- a/src/libcef_dll/ctocpp/process_message_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/process_message_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,11 +9,12 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=74d0487f35e81f0d220f947f0b203b04b193929f$
+// $hash=f542bb5ffcf0d7543e424741a62e93c58cc2e3ee$
 //
 
 #include "libcef_dll/ctocpp/process_message_ctocpp.h"
 #include "libcef_dll/ctocpp/list_value_ctocpp.h"
+#include "libcef_dll/ctocpp/shared_memory_region_ctocpp.h"
 #include "libcef_dll/shutdown_checker.h"
 
 // STATIC METHODS - Body may be edited by hand.
@@ -26,8 +27,9 @@
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return nullptr;
+  }
 
   // Execute
   cef_process_message_t* _retval = cef_process_message_create(name.GetStruct());
@@ -42,8 +44,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_process_message_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -58,8 +61,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_process_message_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_read_only))
+  if (CEF_MEMBER_MISSING(_struct, is_read_only)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -75,8 +79,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_process_message_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, copy))
+  if (CEF_MEMBER_MISSING(_struct, copy)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -91,8 +96,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_process_message_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_name))
+  if (CEF_MEMBER_MISSING(_struct, get_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -110,8 +116,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_process_message_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_argument_list))
+  if (CEF_MEMBER_MISSING(_struct, get_argument_list)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -122,6 +129,26 @@
   return CefListValueCToCpp::Wrap(_retval);
 }
 
+NO_SANITIZE("cfi-icall")
+CefRefPtr<CefSharedMemoryRegion>
+CefProcessMessageCToCpp::GetSharedMemoryRegion() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_process_message_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_shared_memory_region)) {
+    return nullptr;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_shared_memory_region_t* _retval =
+      _struct->get_shared_memory_region(_struct);
+
+  // Return type: refptr_same
+  return CefSharedMemoryRegionCToCpp::Wrap(_retval);
+}
+
 // CONSTRUCTOR - Do not edit by hand.
 
 CefProcessMessageCToCpp::CefProcessMessageCToCpp() {}
@@ -138,7 +165,7 @@
     CefProcessMessage,
     cef_process_message_t>::UnwrapDerived(CefWrapperType type,
                                           CefProcessMessage* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/process_message_ctocpp.h b/src/libcef_dll/ctocpp/process_message_ctocpp.h
index 1f364d8..87b569c 100644
--- a/src/libcef_dll/ctocpp/process_message_ctocpp.h
+++ b/src/libcef_dll/ctocpp/process_message_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6364b8b5300ddb055b789acf13367f24272feb51$
+// $hash=cf099f71fe1c451ca650912e7ba34ef54f2aa61b$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_PROCESS_MESSAGE_CTOCPP_H_
@@ -35,11 +35,12 @@
   virtual ~CefProcessMessageCToCpp();
 
   // CefProcessMessage methods.
-  bool IsValid() OVERRIDE;
-  bool IsReadOnly() OVERRIDE;
-  CefRefPtr<CefProcessMessage> Copy() OVERRIDE;
-  CefString GetName() OVERRIDE;
-  CefRefPtr<CefListValue> GetArgumentList() OVERRIDE;
+  bool IsValid() override;
+  bool IsReadOnly() override;
+  CefRefPtr<CefProcessMessage> Copy() override;
+  CefString GetName() override;
+  CefRefPtr<CefListValue> GetArgumentList() override;
+  CefRefPtr<CefSharedMemoryRegion> GetSharedMemoryRegion() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_PROCESS_MESSAGE_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/read_handler_ctocpp.cc b/src/libcef_dll/ctocpp/read_handler_ctocpp.cc
index e270abf..6cb33b0 100644
--- a/src/libcef_dll/ctocpp/read_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/read_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=a43a5f260d313c39d52223998140fa07657bc318$
+// $hash=b13f9e52b84e1d9be3f7a43927002ae2e57d4636$
 //
 
 #include "libcef_dll/ctocpp/read_handler_ctocpp.h"
@@ -22,15 +22,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_read_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, read))
+  if (CEF_MEMBER_MISSING(_struct, read)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: ptr; type: simple_byaddr
   DCHECK(ptr);
-  if (!ptr)
+  if (!ptr) {
     return 0;
+  }
 
   // Execute
   size_t _retval = _struct->read(_struct, ptr, size, n);
@@ -40,12 +42,13 @@
 }
 
 NO_SANITIZE("cfi-icall")
-int CefReadHandlerCToCpp::Seek(int64 offset, int whence) {
+int CefReadHandlerCToCpp::Seek(int64_t offset, int whence) {
   shutdown_checker::AssertNotShutdown();
 
   cef_read_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, seek))
+  if (CEF_MEMBER_MISSING(_struct, seek)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -56,17 +59,18 @@
   return _retval;
 }
 
-NO_SANITIZE("cfi-icall") int64 CefReadHandlerCToCpp::Tell() {
+NO_SANITIZE("cfi-icall") int64_t CefReadHandlerCToCpp::Tell() {
   shutdown_checker::AssertNotShutdown();
 
   cef_read_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, tell))
+  if (CEF_MEMBER_MISSING(_struct, tell)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int64 _retval = _struct->tell(_struct);
+  int64_t _retval = _struct->tell(_struct);
 
   // Return type: simple
   return _retval;
@@ -76,8 +80,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_read_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, eof))
+  if (CEF_MEMBER_MISSING(_struct, eof)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -92,8 +97,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_read_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, may_block))
+  if (CEF_MEMBER_MISSING(_struct, may_block)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -118,7 +124,7 @@
 cef_read_handler_t*
 CefCToCppRefCounted<CefReadHandlerCToCpp, CefReadHandler, cef_read_handler_t>::
     UnwrapDerived(CefWrapperType type, CefReadHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/read_handler_ctocpp.h b/src/libcef_dll/ctocpp/read_handler_ctocpp.h
index 07996fc..2dd9613 100644
--- a/src/libcef_dll/ctocpp/read_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/read_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b95ddcc2d32bf697b5480554b45f92dbe48beb6c$
+// $hash=9ff5c66c86a68f0a11093ca3e871261be66c16b9$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_READ_HANDLER_CTOCPP_H_
@@ -35,8 +35,8 @@
 
   // CefReadHandler methods.
   size_t Read(void* ptr, size_t size, size_t n) override;
-  int Seek(int64 offset, int whence) override;
-  int64 Tell() override;
+  int Seek(int64_t offset, int whence) override;
+  int64_t Tell() override;
   int Eof() override;
   bool MayBlock() override;
 };
diff --git a/src/libcef_dll/ctocpp/register_cdm_callback_ctocpp.cc b/src/libcef_dll/ctocpp/register_cdm_callback_ctocpp.cc
deleted file mode 100644
index 45dc9a4..0000000
--- a/src/libcef_dll/ctocpp/register_cdm_callback_ctocpp.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=cb7f7a8bc8e7b414eceba18bd4164b857d21ff34$
-//
-
-#include "libcef_dll/ctocpp/register_cdm_callback_ctocpp.h"
-#include "libcef_dll/shutdown_checker.h"
-
-// VIRTUAL METHODS - Body may be edited by hand.
-
-NO_SANITIZE("cfi-icall")
-void CefRegisterCdmCallbackCToCpp::OnCdmRegistrationComplete(
-    cef_cdm_registration_error_t result,
-    const CefString& error_message) {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_register_cdm_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_cdm_registration_complete))
-    return;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Unverified params: error_message
-
-  // Execute
-  _struct->on_cdm_registration_complete(_struct, result,
-                                        error_message.GetStruct());
-}
-
-// CONSTRUCTOR - Do not edit by hand.
-
-CefRegisterCdmCallbackCToCpp::CefRegisterCdmCallbackCToCpp() {}
-
-// DESTRUCTOR - Do not edit by hand.
-
-CefRegisterCdmCallbackCToCpp::~CefRegisterCdmCallbackCToCpp() {
-  shutdown_checker::AssertNotShutdown();
-}
-
-template <>
-cef_register_cdm_callback_t* CefCToCppRefCounted<
-    CefRegisterCdmCallbackCToCpp,
-    CefRegisterCdmCallback,
-    cef_register_cdm_callback_t>::UnwrapDerived(CefWrapperType type,
-                                                CefRegisterCdmCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
-  return nullptr;
-}
-
-template <>
-CefWrapperType CefCToCppRefCounted<CefRegisterCdmCallbackCToCpp,
-                                   CefRegisterCdmCallback,
-                                   cef_register_cdm_callback_t>::kWrapperType =
-    WT_REGISTER_CDM_CALLBACK;
diff --git a/src/libcef_dll/ctocpp/register_cdm_callback_ctocpp.h b/src/libcef_dll/ctocpp/register_cdm_callback_ctocpp.h
deleted file mode 100644
index f21ad13..0000000
--- a/src/libcef_dll/ctocpp/register_cdm_callback_ctocpp.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=bc37eb2fa694426b48707fdbfc216aadd21c4d6d$
-//
-
-#ifndef CEF_LIBCEF_DLL_CTOCPP_REGISTER_CDM_CALLBACK_CTOCPP_H_
-#define CEF_LIBCEF_DLL_CTOCPP_REGISTER_CDM_CALLBACK_CTOCPP_H_
-#pragma once
-
-#if !defined(BUILDING_CEF_SHARED)
-#error This file can be included DLL-side only
-#endif
-
-#include "include/capi/cef_browser_capi.h"
-#include "include/capi/cef_web_plugin_capi.h"
-#include "include/cef_browser.h"
-#include "include/cef_web_plugin.h"
-#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
-
-// Wrap a C structure with a C++ class.
-// This class may be instantiated and accessed DLL-side only.
-class CefRegisterCdmCallbackCToCpp
-    : public CefCToCppRefCounted<CefRegisterCdmCallbackCToCpp,
-                                 CefRegisterCdmCallback,
-                                 cef_register_cdm_callback_t> {
- public:
-  CefRegisterCdmCallbackCToCpp();
-  virtual ~CefRegisterCdmCallbackCToCpp();
-
-  // CefRegisterCdmCallback methods.
-  void OnCdmRegistrationComplete(cef_cdm_registration_error_t result,
-                                 const CefString& error_message) override;
-};
-
-#endif  // CEF_LIBCEF_DLL_CTOCPP_REGISTER_CDM_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/registration_ctocpp.cc b/src/libcef_dll/ctocpp/registration_ctocpp.cc
index ad14288..ae4f319 100644
--- a/src/libcef_dll/ctocpp/registration_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/registration_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=89f0f0c0ae2485adbf8140a419969901e5766b51$
+// $hash=004bfcbf30ee0b2ecc97828c943d1302c033b7d9$
 //
 
 #include "libcef_dll/ctocpp/registration_ctocpp.h"
@@ -31,7 +31,7 @@
                     CefRegistration,
                     cef_registration_t>::UnwrapDerived(CefWrapperType type,
                                                        CefRegistration* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/registration_ctocpp.h b/src/libcef_dll/ctocpp/registration_ctocpp.h
index 9485a68..b60a76f 100644
--- a/src/libcef_dll/ctocpp/registration_ctocpp.h
+++ b/src/libcef_dll/ctocpp/registration_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6d458b0a8e42e3f3347d5101f8d3f1f88264ecc7$
+// $hash=8b9f37f2e0d395e737bc158d7d4bfb5f5e85e5c4$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_REGISTRATION_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/render_handler_ctocpp.cc b/src/libcef_dll/ctocpp/render_handler_ctocpp.cc
index 171f78d..724ba35 100644
--- a/src/libcef_dll/ctocpp/render_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/render_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f592f3806c9f87ee6c691b9f072cee4d6bb4650e$
+// $hash=0720ce9a5427a1a1a161898e059b84cfbbbecbfb$
 //
 
 #include "libcef_dll/ctocpp/render_handler_ctocpp.h"
@@ -26,8 +26,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_render_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_accessibility_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_accessibility_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -45,15 +46,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_render_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_root_screen_rect))
+  if (CEF_MEMBER_MISSING(_struct, get_root_screen_rect)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->get_root_screen_rect(
@@ -69,15 +72,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_render_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_view_rect))
+  if (CEF_MEMBER_MISSING(_struct, get_view_rect)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->get_view_rect(_struct, CefBrowserCppToC::Wrap(browser), &rect);
@@ -92,15 +97,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_render_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_screen_point))
+  if (CEF_MEMBER_MISSING(_struct, get_screen_point)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -117,15 +124,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_render_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_screen_info))
+  if (CEF_MEMBER_MISSING(_struct, get_screen_info)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->get_screen_info(
@@ -141,15 +150,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_render_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_popup_show))
+  if (CEF_MEMBER_MISSING(_struct, on_popup_show)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_popup_show(_struct, CefBrowserCppToC::Wrap(browser), show);
@@ -161,15 +172,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_render_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_popup_size))
+  if (CEF_MEMBER_MISSING(_struct, on_popup_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_popup_size(_struct, CefBrowserCppToC::Wrap(browser), &rect);
@@ -185,19 +198,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_render_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_paint))
+  if (CEF_MEMBER_MISSING(_struct, on_paint)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: buffer; type: simple_byaddr
   DCHECK(buffer);
-  if (!buffer)
+  if (!buffer) {
     return;
+  }
 
   // Translate param: dirtyRects; type: simple_vec_byref_const
   const size_t dirtyRectsCount = dirtyRects.size();
@@ -217,8 +233,9 @@
                     dirtyRectsCount, dirtyRectsList, buffer, width, height);
 
   // Restore param:dirtyRects; type: simple_vec_byref_const
-  if (dirtyRectsList)
+  if (dirtyRectsList) {
     delete[] dirtyRectsList;
+  }
 }
 
 NO_SANITIZE("cfi-icall")
@@ -229,19 +246,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_render_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_accelerated_paint))
+  if (CEF_MEMBER_MISSING(_struct, on_accelerated_paint)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: shared_handle; type: simple_byaddr
   DCHECK(shared_handle);
-  if (!shared_handle)
+  if (!shared_handle) {
     return;
+  }
 
   // Translate param: dirtyRects; type: simple_vec_byref_const
   const size_t dirtyRectsCount = dirtyRects.size();
@@ -261,32 +281,58 @@
                                 dirtyRectsCount, dirtyRectsList, shared_handle);
 
   // Restore param:dirtyRects; type: simple_vec_byref_const
-  if (dirtyRectsList)
+  if (dirtyRectsList) {
     delete[] dirtyRectsList;
+  }
 }
 
 NO_SANITIZE("cfi-icall")
-void CefRenderHandlerCToCpp::OnCursorChange(
+void CefRenderHandlerCToCpp::GetTouchHandleSize(
     CefRefPtr<CefBrowser> browser,
-    CefCursorHandle cursor,
-    CursorType type,
-    const CefCursorInfo& custom_cursor_info) {
+    cef_horizontal_alignment_t orientation,
+    CefSize& size) {
   shutdown_checker::AssertNotShutdown();
 
   cef_render_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_cursor_change))
+  if (CEF_MEMBER_MISSING(_struct, get_touch_handle_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
-  _struct->on_cursor_change(_struct, CefBrowserCppToC::Wrap(browser), cursor,
-                            type, &custom_cursor_info);
+  _struct->get_touch_handle_size(_struct, CefBrowserCppToC::Wrap(browser),
+                                 orientation, &size);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefRenderHandlerCToCpp::OnTouchHandleStateChanged(
+    CefRefPtr<CefBrowser> browser,
+    const CefTouchHandleState& state) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_render_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_touch_handle_state_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser; type: refptr_diff
+  DCHECK(browser.get());
+  if (!browser.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_touch_handle_state_changed(
+      _struct, CefBrowserCppToC::Wrap(browser), &state);
 }
 
 NO_SANITIZE("cfi-icall")
@@ -298,19 +344,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_render_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, start_dragging))
+  if (CEF_MEMBER_MISSING(_struct, start_dragging)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: drag_data; type: refptr_diff
   DCHECK(drag_data.get());
-  if (!drag_data.get())
+  if (!drag_data.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->start_dragging(
@@ -327,15 +376,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_render_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, update_drag_cursor))
+  if (CEF_MEMBER_MISSING(_struct, update_drag_cursor)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->update_drag_cursor(_struct, CefBrowserCppToC::Wrap(browser),
@@ -350,15 +401,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_render_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_scroll_offset_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_scroll_offset_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_scroll_offset_changed(_struct, CefBrowserCppToC::Wrap(browser), x,
@@ -373,15 +426,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_render_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_ime_composition_range_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_ime_composition_range_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Translate param: character_bounds; type: simple_vec_byref_const
   const size_t character_boundsCount = character_bounds.size();
@@ -402,8 +457,9 @@
       character_boundsCount, character_boundsList);
 
   // Restore param:character_bounds; type: simple_vec_byref_const
-  if (character_boundsList)
+  if (character_boundsList) {
     delete[] character_boundsList;
+  }
 }
 
 NO_SANITIZE("cfi-icall")
@@ -414,15 +470,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_render_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_text_selection_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_text_selection_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Unverified params: selected_text, selected_range
 
   // Execute
@@ -438,15 +496,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_render_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_virtual_keyboard_requested))
+  if (CEF_MEMBER_MISSING(_struct, on_virtual_keyboard_requested)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_virtual_keyboard_requested(
@@ -469,7 +529,7 @@
                     CefRenderHandler,
                     cef_render_handler_t>::UnwrapDerived(CefWrapperType type,
                                                          CefRenderHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/render_handler_ctocpp.h b/src/libcef_dll/ctocpp/render_handler_ctocpp.h
index d0e1247..bd21445 100644
--- a/src/libcef_dll/ctocpp/render_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/render_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ed8882abe62f08d4746a646307ef74d4987780c4$
+// $hash=e10b3b9a07b4b6929a4168ad657c0046200c1d75$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_RENDER_HANDLER_CTOCPP_H_
@@ -57,10 +57,11 @@
                           PaintElementType type,
                           const RectList& dirtyRects,
                           void* shared_handle) override;
-  void OnCursorChange(CefRefPtr<CefBrowser> browser,
-                      CefCursorHandle cursor,
-                      CursorType type,
-                      const CefCursorInfo& custom_cursor_info) override;
+  void GetTouchHandleSize(CefRefPtr<CefBrowser> browser,
+                          cef_horizontal_alignment_t orientation,
+                          CefSize& size) override;
+  void OnTouchHandleStateChanged(CefRefPtr<CefBrowser> browser,
+                                 const CefTouchHandleState& state) override;
   bool StartDragging(CefRefPtr<CefBrowser> browser,
                      CefRefPtr<CefDragData> drag_data,
                      DragOperationsMask allowed_ops,
diff --git a/src/libcef_dll/ctocpp/render_process_handler_ctocpp.cc b/src/libcef_dll/ctocpp/render_process_handler_ctocpp.cc
index dce8cb0..dac2784 100644
--- a/src/libcef_dll/ctocpp/render_process_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/render_process_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=084106863bdaf595427b0d121362e207b15c66bf$
+// $hash=1bb6593092ca6768ea5a4d07cd9afbe23460e612$
 //
 
 #include "libcef_dll/ctocpp/render_process_handler_ctocpp.h"
@@ -17,7 +17,6 @@
 #include "libcef_dll/cpptoc/dictionary_value_cpptoc.h"
 #include "libcef_dll/cpptoc/domnode_cpptoc.h"
 #include "libcef_dll/cpptoc/frame_cpptoc.h"
-#include "libcef_dll/cpptoc/list_value_cpptoc.h"
 #include "libcef_dll/cpptoc/process_message_cpptoc.h"
 #include "libcef_dll/cpptoc/v8context_cpptoc.h"
 #include "libcef_dll/cpptoc/v8exception_cpptoc.h"
@@ -27,29 +26,11 @@
 // VIRTUAL METHODS - Body may be edited by hand.
 
 NO_SANITIZE("cfi-icall")
-void CefRenderProcessHandlerCToCpp::OnRenderThreadCreated(
-    CefRefPtr<CefListValue> extra_info) {
-  cef_render_process_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_render_thread_created))
-    return;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: extra_info; type: refptr_diff
-  DCHECK(extra_info.get());
-  if (!extra_info.get())
-    return;
-
-  // Execute
-  _struct->on_render_thread_created(_struct,
-                                    CefListValueCppToC::Wrap(extra_info));
-}
-
-NO_SANITIZE("cfi-icall")
 void CefRenderProcessHandlerCToCpp::OnWebKitInitialized() {
   cef_render_process_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_web_kit_initialized))
+  if (CEF_MEMBER_MISSING(_struct, on_web_kit_initialized)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -62,19 +43,18 @@
     CefRefPtr<CefBrowser> browser,
     CefRefPtr<CefDictionaryValue> extra_info) {
   cef_render_process_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_browser_created))
+  if (CEF_MEMBER_MISSING(_struct, on_browser_created)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
-  // Verify param: extra_info; type: refptr_diff
-  DCHECK(extra_info.get());
-  if (!extra_info.get())
-    return;
+  }
+  // Unverified params: extra_info
 
   // Execute
   _struct->on_browser_created(_struct, CefBrowserCppToC::Wrap(browser),
@@ -85,15 +65,17 @@
 void CefRenderProcessHandlerCToCpp::OnBrowserDestroyed(
     CefRefPtr<CefBrowser> browser) {
   cef_render_process_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_browser_destroyed))
+  if (CEF_MEMBER_MISSING(_struct, on_browser_destroyed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_browser_destroyed(_struct, CefBrowserCppToC::Wrap(browser));
@@ -102,8 +84,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefLoadHandler> CefRenderProcessHandlerCToCpp::GetLoadHandler() {
   cef_render_process_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_load_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_load_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -120,23 +103,27 @@
     CefRefPtr<CefFrame> frame,
     CefRefPtr<CefV8Context> context) {
   cef_render_process_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_context_created))
+  if (CEF_MEMBER_MISSING(_struct, on_context_created)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return;
+  }
   // Verify param: context; type: refptr_diff
   DCHECK(context.get());
-  if (!context.get())
+  if (!context.get()) {
     return;
+  }
 
   // Execute
   _struct->on_context_created(_struct, CefBrowserCppToC::Wrap(browser),
@@ -150,23 +137,27 @@
     CefRefPtr<CefFrame> frame,
     CefRefPtr<CefV8Context> context) {
   cef_render_process_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_context_released))
+  if (CEF_MEMBER_MISSING(_struct, on_context_released)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return;
+  }
   // Verify param: context; type: refptr_diff
   DCHECK(context.get());
-  if (!context.get())
+  if (!context.get()) {
     return;
+  }
 
   // Execute
   _struct->on_context_released(_struct, CefBrowserCppToC::Wrap(browser),
@@ -182,31 +173,37 @@
     CefRefPtr<CefV8Exception> exception,
     CefRefPtr<CefV8StackTrace> stackTrace) {
   cef_render_process_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_uncaught_exception))
+  if (CEF_MEMBER_MISSING(_struct, on_uncaught_exception)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return;
+  }
   // Verify param: context; type: refptr_diff
   DCHECK(context.get());
-  if (!context.get())
+  if (!context.get()) {
     return;
+  }
   // Verify param: exception; type: refptr_diff
   DCHECK(exception.get());
-  if (!exception.get())
+  if (!exception.get()) {
     return;
+  }
   // Verify param: stackTrace; type: refptr_diff
   DCHECK(stackTrace.get());
-  if (!stackTrace.get())
+  if (!stackTrace.get()) {
     return;
+  }
 
   // Execute
   _struct->on_uncaught_exception(
@@ -221,15 +218,17 @@
     CefRefPtr<CefFrame> frame,
     CefRefPtr<CefDOMNode> node) {
   cef_render_process_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_focused_node_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_focused_node_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
   // Unverified params: frame, node
 
   // Execute
@@ -245,23 +244,27 @@
     CefProcessId source_process,
     CefRefPtr<CefProcessMessage> message) {
   cef_render_process_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_process_message_received))
+  if (CEF_MEMBER_MISSING(_struct, on_process_message_received)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return false;
+  }
   // Verify param: message; type: refptr_diff
   DCHECK(message.get());
-  if (!message.get())
+  if (!message.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->on_process_message_received(
@@ -286,7 +289,7 @@
     CefRenderProcessHandler,
     cef_render_process_handler_t>::UnwrapDerived(CefWrapperType type,
                                                  CefRenderProcessHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/render_process_handler_ctocpp.h b/src/libcef_dll/ctocpp/render_process_handler_ctocpp.h
index 82ea35e..dcf49a6 100644
--- a/src/libcef_dll/ctocpp/render_process_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/render_process_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=37559903bacc38b0c955e1471f0d0dbeb79b11a8$
+// $hash=1e5030658a4775df8e1eb8bbd54c43cdacf4572a$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_RENDER_PROCESS_HANDLER_CTOCPP_H_
@@ -35,7 +35,6 @@
   virtual ~CefRenderProcessHandlerCToCpp();
 
   // CefRenderProcessHandler methods.
-  void OnRenderThreadCreated(CefRefPtr<CefListValue> extra_info) override;
   void OnWebKitInitialized() override;
   void OnBrowserCreated(CefRefPtr<CefBrowser> browser,
                         CefRefPtr<CefDictionaryValue> extra_info) override;
diff --git a/src/libcef_dll/ctocpp/request_callback_ctocpp.cc b/src/libcef_dll/ctocpp/request_callback_ctocpp.cc
deleted file mode 100644
index eb81c8c..0000000
--- a/src/libcef_dll/ctocpp/request_callback_ctocpp.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=b1c7af22f4bb4b7da664dc6bb7bd057efda70222$
-//
-
-#include "libcef_dll/ctocpp/request_callback_ctocpp.h"
-#include "libcef_dll/shutdown_checker.h"
-
-// VIRTUAL METHODS - Body may be edited by hand.
-
-NO_SANITIZE("cfi-icall") void CefRequestCallbackCToCpp::Continue(bool allow) {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_request_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cont))
-    return;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  _struct->cont(_struct, allow);
-}
-
-NO_SANITIZE("cfi-icall") void CefRequestCallbackCToCpp::Cancel() {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_request_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cancel))
-    return;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  _struct->cancel(_struct);
-}
-
-// CONSTRUCTOR - Do not edit by hand.
-
-CefRequestCallbackCToCpp::CefRequestCallbackCToCpp() {}
-
-// DESTRUCTOR - Do not edit by hand.
-
-CefRequestCallbackCToCpp::~CefRequestCallbackCToCpp() {
-  shutdown_checker::AssertNotShutdown();
-}
-
-template <>
-cef_request_callback_t* CefCToCppRefCounted<
-    CefRequestCallbackCToCpp,
-    CefRequestCallback,
-    cef_request_callback_t>::UnwrapDerived(CefWrapperType type,
-                                           CefRequestCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
-  return nullptr;
-}
-
-template <>
-CefWrapperType CefCToCppRefCounted<CefRequestCallbackCToCpp,
-                                   CefRequestCallback,
-                                   cef_request_callback_t>::kWrapperType =
-    WT_REQUEST_CALLBACK;
diff --git a/src/libcef_dll/ctocpp/request_callback_ctocpp.h b/src/libcef_dll/ctocpp/request_callback_ctocpp.h
deleted file mode 100644
index c6c6175..0000000
--- a/src/libcef_dll/ctocpp/request_callback_ctocpp.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=11018a46ec73650d65701ec3464f7eb438b2e6c2$
-//
-
-#ifndef CEF_LIBCEF_DLL_CTOCPP_REQUEST_CALLBACK_CTOCPP_H_
-#define CEF_LIBCEF_DLL_CTOCPP_REQUEST_CALLBACK_CTOCPP_H_
-#pragma once
-
-#if !defined(WRAPPING_CEF_SHARED)
-#error This file can be included wrapper-side only
-#endif
-
-#include "include/capi/cef_request_callback_capi.h"
-#include "include/cef_request_callback.h"
-#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
-
-// Wrap a C structure with a C++ class.
-// This class may be instantiated and accessed wrapper-side only.
-class CefRequestCallbackCToCpp
-    : public CefCToCppRefCounted<CefRequestCallbackCToCpp,
-                                 CefRequestCallback,
-                                 cef_request_callback_t> {
- public:
-  CefRequestCallbackCToCpp();
-  virtual ~CefRequestCallbackCToCpp();
-
-  // CefRequestCallback methods.
-  void Continue(bool allow) OVERRIDE;
-  void Cancel() OVERRIDE;
-};
-
-#endif  // CEF_LIBCEF_DLL_CTOCPP_REQUEST_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/request_context_ctocpp.cc b/src/libcef_dll/ctocpp/request_context_ctocpp.cc
index b3a9ac4..d1a68a1 100644
--- a/src/libcef_dll/ctocpp/request_context_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/request_context_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=a29d8f9e49143e42a0ae0204c7d439c76b3c371c$
+// $hash=17602248a48e405470bdf7b6a34866cdf67a5780$
 //
 
 #include "libcef_dll/ctocpp/request_context_ctocpp.h"
@@ -62,8 +62,9 @@
 
   // Verify param: other; type: refptr_same
   DCHECK(other.get());
-  if (!other.get())
+  if (!other.get()) {
     return nullptr;
+  }
   // Unverified params: handler
 
   // Execute
@@ -80,15 +81,17 @@
 NO_SANITIZE("cfi-icall")
 bool CefRequestContextCToCpp::IsSame(CefRefPtr<CefRequestContext> other) {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: other; type: refptr_same
   DCHECK(other.get());
-  if (!other.get())
+  if (!other.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -102,15 +105,17 @@
 bool CefRequestContextCToCpp::IsSharingWith(
     CefRefPtr<CefRequestContext> other) {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_sharing_with))
+  if (CEF_MEMBER_MISSING(_struct, is_sharing_with)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: other; type: refptr_same
   DCHECK(other.get());
-  if (!other.get())
+  if (!other.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -122,8 +127,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefRequestContextCToCpp::IsGlobal() {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_global))
+  if (CEF_MEMBER_MISSING(_struct, is_global)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -137,8 +143,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefRequestContextHandler> CefRequestContextCToCpp::GetHandler() {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -151,8 +158,9 @@
 
 NO_SANITIZE("cfi-icall") CefString CefRequestContextCToCpp::GetCachePath() {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_cache_path))
+  if (CEF_MEMBER_MISSING(_struct, get_cache_path)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -169,8 +177,9 @@
 CefRefPtr<CefCookieManager> CefRequestContextCToCpp::GetCookieManager(
     CefRefPtr<CefCompletionCallback> callback) {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_cookie_manager))
+  if (CEF_MEMBER_MISSING(_struct, get_cookie_manager)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -190,15 +199,17 @@
     const CefString& domain_name,
     CefRefPtr<CefSchemeHandlerFactory> factory) {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, register_scheme_handler_factory))
+  if (CEF_MEMBER_MISSING(_struct, register_scheme_handler_factory)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: scheme_name; type: string_byref_const
   DCHECK(!scheme_name.empty());
-  if (scheme_name.empty())
+  if (scheme_name.empty()) {
     return false;
+  }
   // Unverified params: domain_name, factory
 
   // Execute
@@ -213,8 +224,9 @@
 NO_SANITIZE("cfi-icall")
 bool CefRequestContextCToCpp::ClearSchemeHandlerFactories() {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, clear_scheme_handler_factories))
+  if (CEF_MEMBER_MISSING(_struct, clear_scheme_handler_factories)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -226,126 +238,12 @@
 }
 
 NO_SANITIZE("cfi-icall")
-void CefRequestContextCToCpp::PurgePluginListCache(bool reload_pages) {
-  cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, purge_plugin_list_cache))
-    return;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  _struct->purge_plugin_list_cache(_struct, reload_pages);
-}
-
-NO_SANITIZE("cfi-icall")
-bool CefRequestContextCToCpp::HasPreference(const CefString& name) {
-  cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_preference))
-    return false;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: name; type: string_byref_const
-  DCHECK(!name.empty());
-  if (name.empty())
-    return false;
-
-  // Execute
-  int _retval = _struct->has_preference(_struct, name.GetStruct());
-
-  // Return type: bool
-  return _retval ? true : false;
-}
-
-NO_SANITIZE("cfi-icall")
-CefRefPtr<CefValue> CefRequestContextCToCpp::GetPreference(
-    const CefString& name) {
-  cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_preference))
-    return nullptr;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: name; type: string_byref_const
-  DCHECK(!name.empty());
-  if (name.empty())
-    return nullptr;
-
-  // Execute
-  cef_value_t* _retval = _struct->get_preference(_struct, name.GetStruct());
-
-  // Return type: refptr_same
-  return CefValueCToCpp::Wrap(_retval);
-}
-
-NO_SANITIZE("cfi-icall")
-CefRefPtr<CefDictionaryValue> CefRequestContextCToCpp::GetAllPreferences(
-    bool include_defaults) {
-  cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_all_preferences))
-    return nullptr;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  cef_dictionary_value_t* _retval =
-      _struct->get_all_preferences(_struct, include_defaults);
-
-  // Return type: refptr_same
-  return CefDictionaryValueCToCpp::Wrap(_retval);
-}
-
-NO_SANITIZE("cfi-icall")
-bool CefRequestContextCToCpp::CanSetPreference(const CefString& name) {
-  cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, can_set_preference))
-    return false;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: name; type: string_byref_const
-  DCHECK(!name.empty());
-  if (name.empty())
-    return false;
-
-  // Execute
-  int _retval = _struct->can_set_preference(_struct, name.GetStruct());
-
-  // Return type: bool
-  return _retval ? true : false;
-}
-
-NO_SANITIZE("cfi-icall")
-bool CefRequestContextCToCpp::SetPreference(const CefString& name,
-                                            CefRefPtr<CefValue> value,
-                                            CefString& error) {
-  cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_preference))
-    return false;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: name; type: string_byref_const
-  DCHECK(!name.empty());
-  if (name.empty())
-    return false;
-  // Unverified params: value
-
-  // Execute
-  int _retval = _struct->set_preference(_struct, name.GetStruct(),
-                                        CefValueCToCpp::Unwrap(value),
-                                        error.GetWritableStruct());
-
-  // Return type: bool
-  return _retval ? true : false;
-}
-
-NO_SANITIZE("cfi-icall")
 void CefRequestContextCToCpp::ClearCertificateExceptions(
     CefRefPtr<CefCompletionCallback> callback) {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, clear_certificate_exceptions))
+  if (CEF_MEMBER_MISSING(_struct, clear_certificate_exceptions)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -360,8 +258,9 @@
 void CefRequestContextCToCpp::ClearHttpAuthCredentials(
     CefRefPtr<CefCompletionCallback> callback) {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, clear_http_auth_credentials))
+  if (CEF_MEMBER_MISSING(_struct, clear_http_auth_credentials)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -376,8 +275,9 @@
 void CefRequestContextCToCpp::CloseAllConnections(
     CefRefPtr<CefCompletionCallback> callback) {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, close_all_connections))
+  if (CEF_MEMBER_MISSING(_struct, close_all_connections)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -393,19 +293,22 @@
     const CefString& origin,
     CefRefPtr<CefResolveCallback> callback) {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, resolve_host))
+  if (CEF_MEMBER_MISSING(_struct, resolve_host)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: origin; type: string_byref_const
   DCHECK(!origin.empty());
-  if (origin.empty())
+  if (origin.empty()) {
     return;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return;
+  }
 
   // Execute
   _struct->resolve_host(_struct, origin.GetStruct(),
@@ -418,15 +321,17 @@
     CefRefPtr<CefDictionaryValue> manifest,
     CefRefPtr<CefExtensionHandler> handler) {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, load_extension))
+  if (CEF_MEMBER_MISSING(_struct, load_extension)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: root_directory; type: string_byref_const
   DCHECK(!root_directory.empty());
-  if (root_directory.empty())
+  if (root_directory.empty()) {
     return;
+  }
   // Unverified params: manifest, handler
 
   // Execute
@@ -438,15 +343,17 @@
 NO_SANITIZE("cfi-icall")
 bool CefRequestContextCToCpp::DidLoadExtension(const CefString& extension_id) {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, did_load_extension))
+  if (CEF_MEMBER_MISSING(_struct, did_load_extension)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: extension_id; type: string_byref_const
   DCHECK(!extension_id.empty());
-  if (extension_id.empty())
+  if (extension_id.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->did_load_extension(_struct, extension_id.GetStruct());
@@ -458,15 +365,17 @@
 NO_SANITIZE("cfi-icall")
 bool CefRequestContextCToCpp::HasExtension(const CefString& extension_id) {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_extension))
+  if (CEF_MEMBER_MISSING(_struct, has_extension)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: extension_id; type: string_byref_const
   DCHECK(!extension_id.empty());
-  if (extension_id.empty())
+  if (extension_id.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->has_extension(_struct, extension_id.GetStruct());
@@ -479,16 +388,18 @@
 bool CefRequestContextCToCpp::GetExtensions(
     std::vector<CefString>& extension_ids) {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_extensions))
+  if (CEF_MEMBER_MISSING(_struct, get_extensions)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: extension_ids; type: string_vec_byref
   cef_string_list_t extension_idsList = cef_string_list_alloc();
   DCHECK(extension_idsList);
-  if (extension_idsList)
+  if (extension_idsList) {
     transfer_string_list_contents(extension_ids, extension_idsList);
+  }
 
   // Execute
   int _retval = _struct->get_extensions(_struct, extension_idsList);
@@ -508,15 +419,17 @@
 CefRefPtr<CefExtension> CefRequestContextCToCpp::GetExtension(
     const CefString& extension_id) {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_extension))
+  if (CEF_MEMBER_MISSING(_struct, get_extension)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: extension_id; type: string_byref_const
   DCHECK(!extension_id.empty());
-  if (extension_id.empty())
+  if (extension_id.empty()) {
     return nullptr;
+  }
 
   // Execute
   cef_extension_t* _retval =
@@ -527,18 +440,227 @@
 }
 
 NO_SANITIZE("cfi-icall")
-CefRefPtr<CefMediaRouter> CefRequestContextCToCpp::GetMediaRouter() {
+CefRefPtr<CefMediaRouter> CefRequestContextCToCpp::GetMediaRouter(
+    CefRefPtr<CefCompletionCallback> callback) {
   cef_request_context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_media_router))
+  if (CEF_MEMBER_MISSING(_struct, get_media_router)) {
     return nullptr;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Unverified params: callback
+
+  // Execute
+  cef_media_router_t* _retval = _struct->get_media_router(
+      _struct, CefCompletionCallbackCppToC::Wrap(callback));
+
+  // Return type: refptr_same
+  return CefMediaRouterCToCpp::Wrap(_retval);
+}
+
+NO_SANITIZE("cfi-icall")
+CefRefPtr<CefValue> CefRequestContextCToCpp::GetWebsiteSetting(
+    const CefString& requesting_url,
+    const CefString& top_level_url,
+    cef_content_setting_types_t content_type) {
+  cef_request_context_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_website_setting)) {
+    return nullptr;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Unverified params: requesting_url, top_level_url
+
+  // Execute
+  cef_value_t* _retval =
+      _struct->get_website_setting(_struct, requesting_url.GetStruct(),
+                                   top_level_url.GetStruct(), content_type);
+
+  // Return type: refptr_same
+  return CefValueCToCpp::Wrap(_retval);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefRequestContextCToCpp::SetWebsiteSetting(
+    const CefString& requesting_url,
+    const CefString& top_level_url,
+    cef_content_setting_types_t content_type,
+    CefRefPtr<CefValue> value) {
+  cef_request_context_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, set_website_setting)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Unverified params: requesting_url, top_level_url, value
+
+  // Execute
+  _struct->set_website_setting(_struct, requesting_url.GetStruct(),
+                               top_level_url.GetStruct(), content_type,
+                               CefValueCToCpp::Unwrap(value));
+}
+
+NO_SANITIZE("cfi-icall")
+cef_content_setting_values_t CefRequestContextCToCpp::GetContentSetting(
+    const CefString& requesting_url,
+    const CefString& top_level_url,
+    cef_content_setting_types_t content_type) {
+  cef_request_context_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_content_setting)) {
+    return CEF_CONTENT_SETTING_VALUE_DEFAULT;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Unverified params: requesting_url, top_level_url
+
+  // Execute
+  cef_content_setting_values_t _retval =
+      _struct->get_content_setting(_struct, requesting_url.GetStruct(),
+                                   top_level_url.GetStruct(), content_type);
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall")
+void CefRequestContextCToCpp::SetContentSetting(
+    const CefString& requesting_url,
+    const CefString& top_level_url,
+    cef_content_setting_types_t content_type,
+    cef_content_setting_values_t value) {
+  cef_request_context_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, set_content_setting)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Unverified params: requesting_url, top_level_url
+
+  // Execute
+  _struct->set_content_setting(_struct, requesting_url.GetStruct(),
+                               top_level_url.GetStruct(), content_type, value);
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefRequestContextCToCpp::HasPreference(const CefString& name) {
+  cef_preference_manager_t* _struct =
+      reinterpret_cast<cef_preference_manager_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, has_preference)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: name; type: string_byref_const
+  DCHECK(!name.empty());
+  if (name.empty()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->has_preference(_struct, name.GetStruct());
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+CefRefPtr<CefValue> CefRequestContextCToCpp::GetPreference(
+    const CefString& name) {
+  cef_preference_manager_t* _struct =
+      reinterpret_cast<cef_preference_manager_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, get_preference)) {
+    return nullptr;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: name; type: string_byref_const
+  DCHECK(!name.empty());
+  if (name.empty()) {
+    return nullptr;
+  }
+
+  // Execute
+  cef_value_t* _retval = _struct->get_preference(_struct, name.GetStruct());
+
+  // Return type: refptr_same
+  return CefValueCToCpp::Wrap(_retval);
+}
+
+NO_SANITIZE("cfi-icall")
+CefRefPtr<CefDictionaryValue> CefRequestContextCToCpp::GetAllPreferences(
+    bool include_defaults) {
+  cef_preference_manager_t* _struct =
+      reinterpret_cast<cef_preference_manager_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, get_all_preferences)) {
+    return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  cef_media_router_t* _retval = _struct->get_media_router(_struct);
+  cef_dictionary_value_t* _retval =
+      _struct->get_all_preferences(_struct, include_defaults);
 
   // Return type: refptr_same
-  return CefMediaRouterCToCpp::Wrap(_retval);
+  return CefDictionaryValueCToCpp::Wrap(_retval);
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefRequestContextCToCpp::CanSetPreference(const CefString& name) {
+  cef_preference_manager_t* _struct =
+      reinterpret_cast<cef_preference_manager_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, can_set_preference)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: name; type: string_byref_const
+  DCHECK(!name.empty());
+  if (name.empty()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->can_set_preference(_struct, name.GetStruct());
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefRequestContextCToCpp::SetPreference(const CefString& name,
+                                            CefRefPtr<CefValue> value,
+                                            CefString& error) {
+  cef_preference_manager_t* _struct =
+      reinterpret_cast<cef_preference_manager_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, set_preference)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: name; type: string_byref_const
+  DCHECK(!name.empty());
+  if (name.empty()) {
+    return false;
+  }
+  // Unverified params: value
+
+  // Execute
+  int _retval = _struct->set_preference(_struct, name.GetStruct(),
+                                        CefValueCToCpp::Unwrap(value),
+                                        error.GetWritableStruct());
+
+  // Return type: bool
+  return _retval ? true : false;
 }
 
 // CONSTRUCTOR - Do not edit by hand.
@@ -555,7 +677,7 @@
     CefRequestContext,
     cef_request_context_t>::UnwrapDerived(CefWrapperType type,
                                           CefRequestContext* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/request_context_ctocpp.h b/src/libcef_dll/ctocpp/request_context_ctocpp.h
index f5d9f6e..b123581 100644
--- a/src/libcef_dll/ctocpp/request_context_ctocpp.h
+++ b/src/libcef_dll/ctocpp/request_context_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7841eec57c44171080b5d958ca03760cbe23f22b$
+// $hash=b55016db9d45bab1e3716e790257f5bed768c66e$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_REQUEST_CONTEXT_CTOCPP_H_
@@ -40,42 +40,60 @@
   virtual ~CefRequestContextCToCpp();
 
   // CefRequestContext methods.
-  bool IsSame(CefRefPtr<CefRequestContext> other) OVERRIDE;
-  bool IsSharingWith(CefRefPtr<CefRequestContext> other) OVERRIDE;
-  bool IsGlobal() OVERRIDE;
-  CefRefPtr<CefRequestContextHandler> GetHandler() OVERRIDE;
-  CefString GetCachePath() OVERRIDE;
+  bool IsSame(CefRefPtr<CefRequestContext> other) override;
+  bool IsSharingWith(CefRefPtr<CefRequestContext> other) override;
+  bool IsGlobal() override;
+  CefRefPtr<CefRequestContextHandler> GetHandler() override;
+  CefString GetCachePath() override;
   CefRefPtr<CefCookieManager> GetCookieManager(
-      CefRefPtr<CefCompletionCallback> callback) OVERRIDE;
+      CefRefPtr<CefCompletionCallback> callback) override;
   bool RegisterSchemeHandlerFactory(
       const CefString& scheme_name,
       const CefString& domain_name,
-      CefRefPtr<CefSchemeHandlerFactory> factory) OVERRIDE;
-  bool ClearSchemeHandlerFactories() OVERRIDE;
-  void PurgePluginListCache(bool reload_pages) OVERRIDE;
-  bool HasPreference(const CefString& name) OVERRIDE;
-  CefRefPtr<CefValue> GetPreference(const CefString& name) OVERRIDE;
-  CefRefPtr<CefDictionaryValue> GetAllPreferences(
-      bool include_defaults) OVERRIDE;
-  bool CanSetPreference(const CefString& name) OVERRIDE;
-  bool SetPreference(const CefString& name,
-                     CefRefPtr<CefValue> value,
-                     CefString& error) OVERRIDE;
+      CefRefPtr<CefSchemeHandlerFactory> factory) override;
+  bool ClearSchemeHandlerFactories() override;
   void ClearCertificateExceptions(
-      CefRefPtr<CefCompletionCallback> callback) OVERRIDE;
+      CefRefPtr<CefCompletionCallback> callback) override;
   void ClearHttpAuthCredentials(
-      CefRefPtr<CefCompletionCallback> callback) OVERRIDE;
-  void CloseAllConnections(CefRefPtr<CefCompletionCallback> callback) OVERRIDE;
+      CefRefPtr<CefCompletionCallback> callback) override;
+  void CloseAllConnections(CefRefPtr<CefCompletionCallback> callback) override;
   void ResolveHost(const CefString& origin,
-                   CefRefPtr<CefResolveCallback> callback) OVERRIDE;
+                   CefRefPtr<CefResolveCallback> callback) override;
   void LoadExtension(const CefString& root_directory,
                      CefRefPtr<CefDictionaryValue> manifest,
-                     CefRefPtr<CefExtensionHandler> handler) OVERRIDE;
-  bool DidLoadExtension(const CefString& extension_id) OVERRIDE;
-  bool HasExtension(const CefString& extension_id) OVERRIDE;
-  bool GetExtensions(std::vector<CefString>& extension_ids) OVERRIDE;
-  CefRefPtr<CefExtension> GetExtension(const CefString& extension_id) OVERRIDE;
-  CefRefPtr<CefMediaRouter> GetMediaRouter() OVERRIDE;
+                     CefRefPtr<CefExtensionHandler> handler) override;
+  bool DidLoadExtension(const CefString& extension_id) override;
+  bool HasExtension(const CefString& extension_id) override;
+  bool GetExtensions(std::vector<CefString>& extension_ids) override;
+  CefRefPtr<CefExtension> GetExtension(const CefString& extension_id) override;
+  CefRefPtr<CefMediaRouter> GetMediaRouter(
+      CefRefPtr<CefCompletionCallback> callback) override;
+  CefRefPtr<CefValue> GetWebsiteSetting(
+      const CefString& requesting_url,
+      const CefString& top_level_url,
+      cef_content_setting_types_t content_type) override;
+  void SetWebsiteSetting(const CefString& requesting_url,
+                         const CefString& top_level_url,
+                         cef_content_setting_types_t content_type,
+                         CefRefPtr<CefValue> value) override;
+  cef_content_setting_values_t GetContentSetting(
+      const CefString& requesting_url,
+      const CefString& top_level_url,
+      cef_content_setting_types_t content_type) override;
+  void SetContentSetting(const CefString& requesting_url,
+                         const CefString& top_level_url,
+                         cef_content_setting_types_t content_type,
+                         cef_content_setting_values_t value) override;
+
+  // CefPreferenceManager methods.
+  bool HasPreference(const CefString& name) override;
+  CefRefPtr<CefValue> GetPreference(const CefString& name) override;
+  CefRefPtr<CefDictionaryValue> GetAllPreferences(
+      bool include_defaults) override;
+  bool CanSetPreference(const CefString& name) override;
+  bool SetPreference(const CefString& name,
+                     CefRefPtr<CefValue> value,
+                     CefString& error) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_REQUEST_CONTEXT_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/request_context_handler_ctocpp.cc b/src/libcef_dll/ctocpp/request_context_handler_ctocpp.cc
index 3e24ead..c769ff2 100644
--- a/src/libcef_dll/ctocpp/request_context_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/request_context_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=afc36702ea14f7e553999aad62155a4bd189b3b4$
+// $hash=85cfe06a67d84dde8c980d3c888f88eb382a9f55$
 //
 
 #include "libcef_dll/ctocpp/request_context_handler_ctocpp.h"
@@ -17,7 +17,6 @@
 #include "libcef_dll/cpptoc/frame_cpptoc.h"
 #include "libcef_dll/cpptoc/request_context_cpptoc.h"
 #include "libcef_dll/cpptoc/request_cpptoc.h"
-#include "libcef_dll/cpptoc/web_plugin_info_cpptoc.h"
 #include "libcef_dll/ctocpp/resource_request_handler_ctocpp.h"
 
 // VIRTUAL METHODS - Body may be edited by hand.
@@ -26,15 +25,17 @@
 void CefRequestContextHandlerCToCpp::OnRequestContextInitialized(
     CefRefPtr<CefRequestContext> request_context) {
   cef_request_context_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_request_context_initialized))
+  if (CEF_MEMBER_MISSING(_struct, on_request_context_initialized)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request_context; type: refptr_diff
   DCHECK(request_context.get());
-  if (!request_context.get())
+  if (!request_context.get()) {
     return;
+  }
 
   // Execute
   _struct->on_request_context_initialized(
@@ -42,44 +43,6 @@
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefRequestContextHandlerCToCpp::OnBeforePluginLoad(
-    const CefString& mime_type,
-    const CefString& plugin_url,
-    bool is_main_frame,
-    const CefString& top_origin_url,
-    CefRefPtr<CefWebPluginInfo> plugin_info,
-    PluginPolicy* plugin_policy) {
-  cef_request_context_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_before_plugin_load))
-    return false;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: mime_type; type: string_byref_const
-  DCHECK(!mime_type.empty());
-  if (mime_type.empty())
-    return false;
-  // Verify param: plugin_info; type: refptr_diff
-  DCHECK(plugin_info.get());
-  if (!plugin_info.get())
-    return false;
-  // Verify param: plugin_policy; type: simple_byaddr
-  DCHECK(plugin_policy);
-  if (!plugin_policy)
-    return false;
-  // Unverified params: plugin_url, top_origin_url
-
-  // Execute
-  int _retval = _struct->on_before_plugin_load(
-      _struct, mime_type.GetStruct(), plugin_url.GetStruct(), is_main_frame,
-      top_origin_url.GetStruct(), CefWebPluginInfoCppToC::Wrap(plugin_info),
-      plugin_policy);
-
-  // Return type: bool
-  return _retval ? true : false;
-}
-
-NO_SANITIZE("cfi-icall")
 CefRefPtr<CefResourceRequestHandler>
 CefRequestContextHandlerCToCpp::GetResourceRequestHandler(
     CefRefPtr<CefBrowser> browser,
@@ -90,15 +53,17 @@
     const CefString& request_initiator,
     bool& disable_default_handling) {
   cef_request_context_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_resource_request_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_resource_request_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return nullptr;
+  }
   // Unverified params: browser, frame, request_initiator
 
   // Translate param: disable_default_handling; type: bool_byref
@@ -132,7 +97,7 @@
     CefRequestContextHandler,
     cef_request_context_handler_t>::UnwrapDerived(CefWrapperType type,
                                                   CefRequestContextHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/request_context_handler_ctocpp.h b/src/libcef_dll/ctocpp/request_context_handler_ctocpp.h
index 50dcccf..004f130 100644
--- a/src/libcef_dll/ctocpp/request_context_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/request_context_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c73c0a4833d4fd80e27c48d6a00f961f3d93084f$
+// $hash=8f4c9ab7910a1497890d9bb3bc7aef80e23b7306$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_REQUEST_CONTEXT_HANDLER_CTOCPP_H_
@@ -37,12 +37,6 @@
   // CefRequestContextHandler methods.
   void OnRequestContextInitialized(
       CefRefPtr<CefRequestContext> request_context) override;
-  bool OnBeforePluginLoad(const CefString& mime_type,
-                          const CefString& plugin_url,
-                          bool is_main_frame,
-                          const CefString& top_origin_url,
-                          CefRefPtr<CefWebPluginInfo> plugin_info,
-                          PluginPolicy* plugin_policy) override;
   CefRefPtr<CefResourceRequestHandler> GetResourceRequestHandler(
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
diff --git a/src/libcef_dll/ctocpp/request_ctocpp.cc b/src/libcef_dll/ctocpp/request_ctocpp.cc
index 3279406..a123b11 100644
--- a/src/libcef_dll/ctocpp/request_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/request_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=68730b3bdc2f7d7fb673a3321fa6e4b17f8a4011$
+// $hash=f8ac1c909cbcf2dfa78c14cfc790b5ea01b11dde$
 //
 
 #include "libcef_dll/ctocpp/request_ctocpp.h"
@@ -32,8 +32,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefRequestCToCpp::IsReadOnly() {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_read_only))
+  if (CEF_MEMBER_MISSING(_struct, is_read_only)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -46,8 +47,9 @@
 
 NO_SANITIZE("cfi-icall") CefString CefRequestCToCpp::GetURL() {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_url))
+  if (CEF_MEMBER_MISSING(_struct, get_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -62,15 +64,17 @@
 
 NO_SANITIZE("cfi-icall") void CefRequestCToCpp::SetURL(const CefString& url) {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_url))
+  if (CEF_MEMBER_MISSING(_struct, set_url)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: url; type: string_byref_const
   DCHECK(!url.empty());
-  if (url.empty())
+  if (url.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_url(_struct, url.GetStruct());
@@ -78,8 +82,9 @@
 
 NO_SANITIZE("cfi-icall") CefString CefRequestCToCpp::GetMethod() {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_method))
+  if (CEF_MEMBER_MISSING(_struct, get_method)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -95,15 +100,17 @@
 NO_SANITIZE("cfi-icall")
 void CefRequestCToCpp::SetMethod(const CefString& method) {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_method))
+  if (CEF_MEMBER_MISSING(_struct, set_method)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: method; type: string_byref_const
   DCHECK(!method.empty());
-  if (method.empty())
+  if (method.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_method(_struct, method.GetStruct());
@@ -113,8 +120,9 @@
 void CefRequestCToCpp::SetReferrer(const CefString& referrer_url,
                                    ReferrerPolicy policy) {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_referrer))
+  if (CEF_MEMBER_MISSING(_struct, set_referrer)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -126,8 +134,9 @@
 
 NO_SANITIZE("cfi-icall") CefString CefRequestCToCpp::GetReferrerURL() {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_referrer_url))
+  if (CEF_MEMBER_MISSING(_struct, get_referrer_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -143,8 +152,9 @@
 NO_SANITIZE("cfi-icall")
 CefRequest::ReferrerPolicy CefRequestCToCpp::GetReferrerPolicy() {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_referrer_policy))
+  if (CEF_MEMBER_MISSING(_struct, get_referrer_policy)) {
     return REFERRER_POLICY_DEFAULT;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -158,8 +168,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefPostData> CefRequestCToCpp::GetPostData() {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_post_data))
+  if (CEF_MEMBER_MISSING(_struct, get_post_data)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -173,15 +184,17 @@
 NO_SANITIZE("cfi-icall")
 void CefRequestCToCpp::SetPostData(CefRefPtr<CefPostData> postData) {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_post_data))
+  if (CEF_MEMBER_MISSING(_struct, set_post_data)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: postData; type: refptr_same
   DCHECK(postData.get());
-  if (!postData.get())
+  if (!postData.get()) {
     return;
+  }
 
   // Execute
   _struct->set_post_data(_struct, CefPostDataCToCpp::Unwrap(postData));
@@ -190,16 +203,18 @@
 NO_SANITIZE("cfi-icall")
 void CefRequestCToCpp::GetHeaderMap(HeaderMap& headerMap) {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_header_map))
+  if (CEF_MEMBER_MISSING(_struct, get_header_map)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: headerMap; type: string_map_multi_byref
   cef_string_multimap_t headerMapMultimap = cef_string_multimap_alloc();
   DCHECK(headerMapMultimap);
-  if (headerMapMultimap)
+  if (headerMapMultimap) {
     transfer_string_multimap_contents(headerMap, headerMapMultimap);
+  }
 
   // Execute
   _struct->get_header_map(_struct, headerMapMultimap);
@@ -215,37 +230,42 @@
 NO_SANITIZE("cfi-icall")
 void CefRequestCToCpp::SetHeaderMap(const HeaderMap& headerMap) {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_header_map))
+  if (CEF_MEMBER_MISSING(_struct, set_header_map)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: headerMap; type: string_map_multi_byref_const
   cef_string_multimap_t headerMapMultimap = cef_string_multimap_alloc();
   DCHECK(headerMapMultimap);
-  if (headerMapMultimap)
+  if (headerMapMultimap) {
     transfer_string_multimap_contents(headerMap, headerMapMultimap);
+  }
 
   // Execute
   _struct->set_header_map(_struct, headerMapMultimap);
 
   // Restore param:headerMap; type: string_map_multi_byref_const
-  if (headerMapMultimap)
+  if (headerMapMultimap) {
     cef_string_multimap_free(headerMapMultimap);
+  }
 }
 
 NO_SANITIZE("cfi-icall")
 CefString CefRequestCToCpp::GetHeaderByName(const CefString& name) {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_header_by_name))
+  if (CEF_MEMBER_MISSING(_struct, get_header_by_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return CefString();
+  }
 
   // Execute
   cef_string_userfree_t _retval =
@@ -262,15 +282,17 @@
                                        const CefString& value,
                                        bool overwrite) {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_header_by_name))
+  if (CEF_MEMBER_MISSING(_struct, set_header_by_name)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return;
+  }
   // Unverified params: value
 
   // Execute
@@ -284,40 +306,46 @@
                            CefRefPtr<CefPostData> postData,
                            const HeaderMap& headerMap) {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set))
+  if (CEF_MEMBER_MISSING(_struct, set)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: url; type: string_byref_const
   DCHECK(!url.empty());
-  if (url.empty())
+  if (url.empty()) {
     return;
+  }
   // Verify param: method; type: string_byref_const
   DCHECK(!method.empty());
-  if (method.empty())
+  if (method.empty()) {
     return;
+  }
   // Unverified params: postData
 
   // Translate param: headerMap; type: string_map_multi_byref_const
   cef_string_multimap_t headerMapMultimap = cef_string_multimap_alloc();
   DCHECK(headerMapMultimap);
-  if (headerMapMultimap)
+  if (headerMapMultimap) {
     transfer_string_multimap_contents(headerMap, headerMapMultimap);
+  }
 
   // Execute
   _struct->set(_struct, url.GetStruct(), method.GetStruct(),
                CefPostDataCToCpp::Unwrap(postData), headerMapMultimap);
 
   // Restore param:headerMap; type: string_map_multi_byref_const
-  if (headerMapMultimap)
+  if (headerMapMultimap) {
     cef_string_multimap_free(headerMapMultimap);
+  }
 }
 
 NO_SANITIZE("cfi-icall") int CefRequestCToCpp::GetFlags() {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_flags))
+  if (CEF_MEMBER_MISSING(_struct, get_flags)) {
     return UR_FLAG_NONE;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -330,8 +358,9 @@
 
 NO_SANITIZE("cfi-icall") void CefRequestCToCpp::SetFlags(int flags) {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_flags))
+  if (CEF_MEMBER_MISSING(_struct, set_flags)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -341,8 +370,9 @@
 
 NO_SANITIZE("cfi-icall") CefString CefRequestCToCpp::GetFirstPartyForCookies() {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_first_party_for_cookies))
+  if (CEF_MEMBER_MISSING(_struct, get_first_party_for_cookies)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -358,8 +388,9 @@
 NO_SANITIZE("cfi-icall")
 void CefRequestCToCpp::SetFirstPartyForCookies(const CefString& url) {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_first_party_for_cookies))
+  if (CEF_MEMBER_MISSING(_struct, set_first_party_for_cookies)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -372,8 +403,9 @@
 NO_SANITIZE("cfi-icall")
 CefRequest::ResourceType CefRequestCToCpp::GetResourceType() {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_resource_type))
+  if (CEF_MEMBER_MISSING(_struct, get_resource_type)) {
     return RT_SUB_RESOURCE;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -387,8 +419,9 @@
 NO_SANITIZE("cfi-icall")
 CefRequest::TransitionType CefRequestCToCpp::GetTransitionType() {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_transition_type))
+  if (CEF_MEMBER_MISSING(_struct, get_transition_type)) {
     return TT_EXPLICIT;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -399,15 +432,16 @@
   return _retval;
 }
 
-NO_SANITIZE("cfi-icall") uint64 CefRequestCToCpp::GetIdentifier() {
+NO_SANITIZE("cfi-icall") uint64_t CefRequestCToCpp::GetIdentifier() {
   cef_request_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_identifier))
+  if (CEF_MEMBER_MISSING(_struct, get_identifier)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  uint64 _retval = _struct->get_identifier(_struct);
+  uint64_t _retval = _struct->get_identifier(_struct);
 
   // Return type: simple
   return _retval;
@@ -426,7 +460,7 @@
 CefCToCppRefCounted<CefRequestCToCpp, CefRequest, cef_request_t>::UnwrapDerived(
     CefWrapperType type,
     CefRequest* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/request_ctocpp.h b/src/libcef_dll/ctocpp/request_ctocpp.h
index 7cf586e..d76bdde 100644
--- a/src/libcef_dll/ctocpp/request_ctocpp.h
+++ b/src/libcef_dll/ctocpp/request_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=08dbc905e15058879ec55a1921031eb04460801e$
+// $hash=cede9199ca4b019787a67fe4bc2cb739759f3cd6$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_REQUEST_CTOCPP_H_
@@ -33,34 +33,34 @@
   virtual ~CefRequestCToCpp();
 
   // CefRequest methods.
-  bool IsReadOnly() OVERRIDE;
-  CefString GetURL() OVERRIDE;
-  void SetURL(const CefString& url) OVERRIDE;
-  CefString GetMethod() OVERRIDE;
-  void SetMethod(const CefString& method) OVERRIDE;
+  bool IsReadOnly() override;
+  CefString GetURL() override;
+  void SetURL(const CefString& url) override;
+  CefString GetMethod() override;
+  void SetMethod(const CefString& method) override;
   void SetReferrer(const CefString& referrer_url,
-                   ReferrerPolicy policy) OVERRIDE;
-  CefString GetReferrerURL() OVERRIDE;
-  ReferrerPolicy GetReferrerPolicy() OVERRIDE;
-  CefRefPtr<CefPostData> GetPostData() OVERRIDE;
-  void SetPostData(CefRefPtr<CefPostData> postData) OVERRIDE;
-  void GetHeaderMap(HeaderMap& headerMap) OVERRIDE;
-  void SetHeaderMap(const HeaderMap& headerMap) OVERRIDE;
-  CefString GetHeaderByName(const CefString& name) OVERRIDE;
+                   ReferrerPolicy policy) override;
+  CefString GetReferrerURL() override;
+  ReferrerPolicy GetReferrerPolicy() override;
+  CefRefPtr<CefPostData> GetPostData() override;
+  void SetPostData(CefRefPtr<CefPostData> postData) override;
+  void GetHeaderMap(HeaderMap& headerMap) override;
+  void SetHeaderMap(const HeaderMap& headerMap) override;
+  CefString GetHeaderByName(const CefString& name) override;
   void SetHeaderByName(const CefString& name,
                        const CefString& value,
-                       bool overwrite) OVERRIDE;
+                       bool overwrite) override;
   void Set(const CefString& url,
            const CefString& method,
            CefRefPtr<CefPostData> postData,
-           const HeaderMap& headerMap) OVERRIDE;
-  int GetFlags() OVERRIDE;
-  void SetFlags(int flags) OVERRIDE;
-  CefString GetFirstPartyForCookies() OVERRIDE;
-  void SetFirstPartyForCookies(const CefString& url) OVERRIDE;
-  ResourceType GetResourceType() OVERRIDE;
-  TransitionType GetTransitionType() OVERRIDE;
-  uint64 GetIdentifier() OVERRIDE;
+           const HeaderMap& headerMap) override;
+  int GetFlags() override;
+  void SetFlags(int flags) override;
+  CefString GetFirstPartyForCookies() override;
+  void SetFirstPartyForCookies(const CefString& url) override;
+  ResourceType GetResourceType() override;
+  TransitionType GetTransitionType() override;
+  uint64_t GetIdentifier() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_REQUEST_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/request_handler_ctocpp.cc b/src/libcef_dll/ctocpp/request_handler_ctocpp.cc
index 0260f23..57ca2f5 100644
--- a/src/libcef_dll/ctocpp/request_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/request_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,14 +9,14 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=fdcb73f79369fe74f65f75d54f08aaec0f0e4dbf$
+// $hash=19152f67304ceaf2d54f0b8133f317974145d40e$
 //
 
 #include "libcef_dll/ctocpp/request_handler_ctocpp.h"
 #include "libcef_dll/cpptoc/auth_callback_cpptoc.h"
 #include "libcef_dll/cpptoc/browser_cpptoc.h"
+#include "libcef_dll/cpptoc/callback_cpptoc.h"
 #include "libcef_dll/cpptoc/frame_cpptoc.h"
-#include "libcef_dll/cpptoc/request_callback_cpptoc.h"
 #include "libcef_dll/cpptoc/request_cpptoc.h"
 #include "libcef_dll/cpptoc/select_client_certificate_callback_cpptoc.h"
 #include "libcef_dll/cpptoc/sslinfo_cpptoc.h"
@@ -35,23 +35,27 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_before_browse))
+  if (CEF_MEMBER_MISSING(_struct, on_before_browse)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return false;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->on_before_browse(
@@ -72,23 +76,27 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_open_urlfrom_tab))
+  if (CEF_MEMBER_MISSING(_struct, on_open_urlfrom_tab)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return false;
+  }
   // Verify param: target_url; type: string_byref_const
   DCHECK(!target_url.empty());
-  if (target_url.empty())
+  if (target_url.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->on_open_urlfrom_tab(
@@ -112,23 +120,27 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_resource_request_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_resource_request_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return nullptr;
+  }
   // Verify param: frame; type: refptr_diff
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return nullptr;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return nullptr;
+  }
   // Unverified params: request_initiator
 
   // Translate param: disable_default_handling; type: bool_byref
@@ -161,27 +173,32 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_auth_credentials))
+  if (CEF_MEMBER_MISSING(_struct, get_auth_credentials)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: origin_url; type: string_byref_const
   DCHECK(!origin_url.empty());
-  if (origin_url.empty())
+  if (origin_url.empty()) {
     return false;
+  }
   // Verify param: host; type: string_byref_const
   DCHECK(!host.empty());
-  if (host.empty())
+  if (host.empty()) {
     return false;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return false;
+  }
   // Unverified params: realm, scheme
 
   // Execute
@@ -195,78 +212,47 @@
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefRequestHandlerCToCpp::OnQuotaRequest(
-    CefRefPtr<CefBrowser> browser,
-    const CefString& origin_url,
-    int64 new_size,
-    CefRefPtr<CefRequestCallback> callback) {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_quota_request))
-    return false;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: browser; type: refptr_diff
-  DCHECK(browser.get());
-  if (!browser.get())
-    return false;
-  // Verify param: origin_url; type: string_byref_const
-  DCHECK(!origin_url.empty());
-  if (origin_url.empty())
-    return false;
-  // Verify param: callback; type: refptr_diff
-  DCHECK(callback.get());
-  if (!callback.get())
-    return false;
-
-  // Execute
-  int _retval = _struct->on_quota_request(
-      _struct, CefBrowserCppToC::Wrap(browser), origin_url.GetStruct(),
-      new_size, CefRequestCallbackCppToC::Wrap(callback));
-
-  // Return type: bool
-  return _retval ? true : false;
-}
-
-NO_SANITIZE("cfi-icall")
 bool CefRequestHandlerCToCpp::OnCertificateError(
     CefRefPtr<CefBrowser> browser,
     cef_errorcode_t cert_error,
     const CefString& request_url,
     CefRefPtr<CefSSLInfo> ssl_info,
-    CefRefPtr<CefRequestCallback> callback) {
+    CefRefPtr<CefCallback> callback) {
   shutdown_checker::AssertNotShutdown();
 
   cef_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_certificate_error))
+  if (CEF_MEMBER_MISSING(_struct, on_certificate_error)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: request_url; type: string_byref_const
   DCHECK(!request_url.empty());
-  if (request_url.empty())
+  if (request_url.empty()) {
     return false;
+  }
   // Verify param: ssl_info; type: refptr_diff
   DCHECK(ssl_info.get());
-  if (!ssl_info.get())
+  if (!ssl_info.get()) {
     return false;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->on_certificate_error(
       _struct, CefBrowserCppToC::Wrap(browser), cert_error,
       request_url.GetStruct(), CefSSLInfoCppToC::Wrap(ssl_info),
-      CefRequestCallbackCppToC::Wrap(callback));
+      CefCallbackCppToC::Wrap(callback));
 
   // Return type: bool
   return _retval ? true : false;
@@ -283,23 +269,27 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_select_client_certificate))
+  if (CEF_MEMBER_MISSING(_struct, on_select_client_certificate)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return false;
+  }
   // Verify param: host; type: string_byref_const
   DCHECK(!host.empty());
-  if (host.empty())
+  if (host.empty()) {
     return false;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return false;
+  }
 
   // Translate param: certificates; type: refptr_vec_diff_byref_const
   const size_t certificatesCount = certificates.size();
@@ -321,52 +311,30 @@
       CefSelectClientCertificateCallbackCppToC::Wrap(callback));
 
   // Restore param:certificates; type: refptr_vec_diff_byref_const
-  if (certificatesList)
+  if (certificatesList) {
     delete[] certificatesList;
+  }
 
   // Return type: bool
   return _retval ? true : false;
 }
 
 NO_SANITIZE("cfi-icall")
-void CefRequestHandlerCToCpp::OnPluginCrashed(CefRefPtr<CefBrowser> browser,
-                                              const CefString& plugin_path) {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_plugin_crashed))
-    return;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: browser; type: refptr_diff
-  DCHECK(browser.get());
-  if (!browser.get())
-    return;
-  // Verify param: plugin_path; type: string_byref_const
-  DCHECK(!plugin_path.empty());
-  if (plugin_path.empty())
-    return;
-
-  // Execute
-  _struct->on_plugin_crashed(_struct, CefBrowserCppToC::Wrap(browser),
-                             plugin_path.GetStruct());
-}
-
-NO_SANITIZE("cfi-icall")
 void CefRequestHandlerCToCpp::OnRenderViewReady(CefRefPtr<CefBrowser> browser) {
   shutdown_checker::AssertNotShutdown();
 
   cef_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_render_view_ready))
+  if (CEF_MEMBER_MISSING(_struct, on_render_view_ready)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_render_view_ready(_struct, CefBrowserCppToC::Wrap(browser));
@@ -379,15 +347,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_render_process_terminated))
+  if (CEF_MEMBER_MISSING(_struct, on_render_process_terminated)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_render_process_terminated(
@@ -400,15 +370,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_document_available_in_main_frame))
+  if (CEF_MEMBER_MISSING(_struct, on_document_available_in_main_frame)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_document_available_in_main_frame(_struct,
@@ -431,7 +403,7 @@
     CefRequestHandler,
     cef_request_handler_t>::UnwrapDerived(CefWrapperType type,
                                           CefRequestHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/request_handler_ctocpp.h b/src/libcef_dll/ctocpp/request_handler_ctocpp.h
index 8122cb6..38ef594 100644
--- a/src/libcef_dll/ctocpp/request_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/request_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=be2bb80e8816f0eaad34382f05e2bec59dfe7fa7$
+// $hash=4f8f1876fa5ee304f9e4481212df662fa05da02d$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_REQUEST_HANDLER_CTOCPP_H_
@@ -61,15 +61,11 @@
                           const CefString& realm,
                           const CefString& scheme,
                           CefRefPtr<CefAuthCallback> callback) override;
-  bool OnQuotaRequest(CefRefPtr<CefBrowser> browser,
-                      const CefString& origin_url,
-                      int64 new_size,
-                      CefRefPtr<CefRequestCallback> callback) override;
   bool OnCertificateError(CefRefPtr<CefBrowser> browser,
                           cef_errorcode_t cert_error,
                           const CefString& request_url,
                           CefRefPtr<CefSSLInfo> ssl_info,
-                          CefRefPtr<CefRequestCallback> callback) override;
+                          CefRefPtr<CefCallback> callback) override;
   bool OnSelectClientCertificate(
       CefRefPtr<CefBrowser> browser,
       bool isProxy,
@@ -77,8 +73,6 @@
       int port,
       const X509CertificateList& certificates,
       CefRefPtr<CefSelectClientCertificateCallback> callback) override;
-  void OnPluginCrashed(CefRefPtr<CefBrowser> browser,
-                       const CefString& plugin_path) override;
   void OnRenderViewReady(CefRefPtr<CefBrowser> browser) override;
   void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
                                  TerminationStatus status) override;
diff --git a/src/libcef_dll/ctocpp/resolve_callback_ctocpp.cc b/src/libcef_dll/ctocpp/resolve_callback_ctocpp.cc
index 2c09456..26f802b 100644
--- a/src/libcef_dll/ctocpp/resolve_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/resolve_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=37265d073717bef3508ba6c42f944e7b27c7b1dd$
+// $hash=26f0b2cca6c62191dcdc1f70e415cd615a66cee5$
 //
 
 #include "libcef_dll/ctocpp/resolve_callback_ctocpp.h"
@@ -25,8 +25,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_resolve_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_resolve_completed))
+  if (CEF_MEMBER_MISSING(_struct, on_resolve_completed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -35,15 +36,17 @@
   // Translate param: resolved_ips; type: string_vec_byref_const
   cef_string_list_t resolved_ipsList = cef_string_list_alloc();
   DCHECK(resolved_ipsList);
-  if (resolved_ipsList)
+  if (resolved_ipsList) {
     transfer_string_list_contents(resolved_ips, resolved_ipsList);
+  }
 
   // Execute
   _struct->on_resolve_completed(_struct, result, resolved_ipsList);
 
   // Restore param:resolved_ips; type: string_vec_byref_const
-  if (resolved_ipsList)
+  if (resolved_ipsList) {
     cef_string_list_free(resolved_ipsList);
+  }
 }
 
 // CONSTRUCTOR - Do not edit by hand.
@@ -62,7 +65,7 @@
     CefResolveCallback,
     cef_resolve_callback_t>::UnwrapDerived(CefWrapperType type,
                                            CefResolveCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/resolve_callback_ctocpp.h b/src/libcef_dll/ctocpp/resolve_callback_ctocpp.h
index f54953e..f9e115e 100644
--- a/src/libcef_dll/ctocpp/resolve_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/resolve_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=619ab895c105edfa7802d25fcdc6f5e8bb969295$
+// $hash=648f3d66272798ab00f7a97d33126aef193d5fa5$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_RESOLVE_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/resource_bundle_ctocpp.cc b/src/libcef_dll/ctocpp/resource_bundle_ctocpp.cc
index c4746fb..bbba4d8 100644
--- a/src/libcef_dll/ctocpp/resource_bundle_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/resource_bundle_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,10 +9,11 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=026dabca1d46cfbe911d71ede9d5bb79cb7c553d$
+// $hash=2351c980bcf0be831b2803207665595003a6ae9b$
 //
 
 #include "libcef_dll/ctocpp/resource_bundle_ctocpp.h"
+#include "libcef_dll/ctocpp/binary_value_ctocpp.h"
 
 // STATIC METHODS - Body may be edited by hand.
 
@@ -32,8 +33,9 @@
 NO_SANITIZE("cfi-icall")
 CefString CefResourceBundleCToCpp::GetLocalizedString(int string_id) {
   cef_resource_bundle_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_localized_string))
+  if (CEF_MEMBER_MISSING(_struct, get_localized_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -48,40 +50,40 @@
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefResourceBundleCToCpp::GetDataResource(int resource_id,
-                                              void*& data,
-                                              size_t& data_size) {
+CefRefPtr<CefBinaryValue> CefResourceBundleCToCpp::GetDataResource(
+    int resource_id) {
   cef_resource_bundle_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_data_resource))
-    return false;
+  if (CEF_MEMBER_MISSING(_struct, get_data_resource)) {
+    return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int _retval =
-      _struct->get_data_resource(_struct, resource_id, &data, &data_size);
+  cef_binary_value_t* _retval =
+      _struct->get_data_resource(_struct, resource_id);
 
-  // Return type: bool
-  return _retval ? true : false;
+  // Return type: refptr_same
+  return CefBinaryValueCToCpp::Wrap(_retval);
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefResourceBundleCToCpp::GetDataResourceForScale(int resource_id,
-                                                      ScaleFactor scale_factor,
-                                                      void*& data,
-                                                      size_t& data_size) {
+CefRefPtr<CefBinaryValue> CefResourceBundleCToCpp::GetDataResourceForScale(
+    int resource_id,
+    ScaleFactor scale_factor) {
   cef_resource_bundle_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_data_resource_for_scale))
-    return false;
+  if (CEF_MEMBER_MISSING(_struct, get_data_resource_for_scale)) {
+    return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int _retval = _struct->get_data_resource_for_scale(
-      _struct, resource_id, scale_factor, &data, &data_size);
+  cef_binary_value_t* _retval =
+      _struct->get_data_resource_for_scale(_struct, resource_id, scale_factor);
 
-  // Return type: bool
-  return _retval ? true : false;
+  // Return type: refptr_same
+  return CefBinaryValueCToCpp::Wrap(_retval);
 }
 
 // CONSTRUCTOR - Do not edit by hand.
@@ -98,7 +100,7 @@
     CefResourceBundle,
     cef_resource_bundle_t>::UnwrapDerived(CefWrapperType type,
                                           CefResourceBundle* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/resource_bundle_ctocpp.h b/src/libcef_dll/ctocpp/resource_bundle_ctocpp.h
index a99cc2e..9d0444e 100644
--- a/src/libcef_dll/ctocpp/resource_bundle_ctocpp.h
+++ b/src/libcef_dll/ctocpp/resource_bundle_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c0d4e71c707c9d63a00ca1a497aaede3e429e970$
+// $hash=e18e48353500f27c27160812032cadc398fe00f9$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_RESOURCE_BUNDLE_CTOCPP_H_
@@ -35,14 +35,11 @@
   virtual ~CefResourceBundleCToCpp();
 
   // CefResourceBundle methods.
-  CefString GetLocalizedString(int string_id) OVERRIDE;
-  bool GetDataResource(int resource_id,
-                       void*& data,
-                       size_t& data_size) OVERRIDE;
-  bool GetDataResourceForScale(int resource_id,
-                               ScaleFactor scale_factor,
-                               void*& data,
-                               size_t& data_size) OVERRIDE;
+  CefString GetLocalizedString(int string_id) override;
+  CefRefPtr<CefBinaryValue> GetDataResource(int resource_id) override;
+  CefRefPtr<CefBinaryValue> GetDataResourceForScale(
+      int resource_id,
+      ScaleFactor scale_factor) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_RESOURCE_BUNDLE_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.cc b/src/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.cc
index 3e6536b..71b5b8c 100644
--- a/src/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e0a6432bb54e21c91fb9a82c708b04b36822c067$
+// $hash=a89889b633cfe23052e084a41e2bd6dc3abaca78$
 //
 
 #include "libcef_dll/ctocpp/resource_bundle_handler_ctocpp.h"
@@ -23,8 +23,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_resource_bundle_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_localized_string))
+  if (CEF_MEMBER_MISSING(_struct, get_localized_string)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -43,8 +44,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_resource_bundle_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_data_resource))
+  if (CEF_MEMBER_MISSING(_struct, get_data_resource)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -65,8 +67,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_resource_bundle_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_data_resource_for_scale))
+  if (CEF_MEMBER_MISSING(_struct, get_data_resource_for_scale)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -94,7 +97,7 @@
     CefResourceBundleHandler,
     cef_resource_bundle_handler_t>::UnwrapDerived(CefWrapperType type,
                                                   CefResourceBundleHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.h b/src/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.h
index 7d49d11..0b427b1 100644
--- a/src/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0785b3534e482f12660e57106820da346885aad0$
+// $hash=52b1821c0ed82e859eddbb113d4a73ba2b178548$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_RESOURCE_BUNDLE_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/resource_handler_ctocpp.cc b/src/libcef_dll/ctocpp/resource_handler_ctocpp.cc
index 5646f86..44756e7 100644
--- a/src/libcef_dll/ctocpp/resource_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/resource_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e26de314e30f8de5b6f082d0dda6e63b8e720368$
+// $hash=c5c801a75133b150cef77b8dc88a544064cc74f0$
 //
 
 #include "libcef_dll/ctocpp/resource_handler_ctocpp.h"
@@ -29,19 +29,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_resource_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, open))
+  if (CEF_MEMBER_MISSING(_struct, open)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return false;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return false;
+  }
 
   // Translate param: handle_request; type: bool_byref
   int handle_requestInt = handle_request;
@@ -64,19 +67,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_resource_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, process_request))
+  if (CEF_MEMBER_MISSING(_struct, process_request)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return false;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -90,20 +96,22 @@
 NO_SANITIZE("cfi-icall")
 void CefResourceHandlerCToCpp::GetResponseHeaders(
     CefRefPtr<CefResponse> response,
-    int64& response_length,
+    int64_t& response_length,
     CefString& redirectUrl) {
   shutdown_checker::AssertNotShutdown();
 
   cef_resource_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_response_headers))
+  if (CEF_MEMBER_MISSING(_struct, get_response_headers)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: response; type: refptr_diff
   DCHECK(response.get());
-  if (!response.get())
+  if (!response.get()) {
     return;
+  }
 
   // Execute
   _struct->get_response_headers(_struct, CefResponseCppToC::Wrap(response),
@@ -113,21 +121,23 @@
 
 NO_SANITIZE("cfi-icall")
 bool CefResourceHandlerCToCpp::Skip(
-    int64 bytes_to_skip,
-    int64& bytes_skipped,
+    int64_t bytes_to_skip,
+    int64_t& bytes_skipped,
     CefRefPtr<CefResourceSkipCallback> callback) {
   shutdown_checker::AssertNotShutdown();
 
   cef_resource_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, skip))
+  if (CEF_MEMBER_MISSING(_struct, skip)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->skip(_struct, bytes_to_skip, &bytes_skipped,
@@ -146,19 +156,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_resource_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, read))
+  if (CEF_MEMBER_MISSING(_struct, read)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: data_out; type: simple_byaddr
   DCHECK(data_out);
-  if (!data_out)
+  if (!data_out) {
     return false;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->read(_struct, data_out, bytes_to_read, &bytes_read,
@@ -176,19 +189,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_resource_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, read_response))
+  if (CEF_MEMBER_MISSING(_struct, read_response)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: data_out; type: simple_byaddr
   DCHECK(data_out);
-  if (!data_out)
+  if (!data_out) {
     return false;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -203,8 +219,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_resource_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cancel))
+  if (CEF_MEMBER_MISSING(_struct, cancel)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -228,7 +245,7 @@
     CefResourceHandler,
     cef_resource_handler_t>::UnwrapDerived(CefWrapperType type,
                                            CefResourceHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/resource_handler_ctocpp.h b/src/libcef_dll/ctocpp/resource_handler_ctocpp.h
index 6ed8af6..aea0c4f 100644
--- a/src/libcef_dll/ctocpp/resource_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/resource_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9a0955b4412d7b25b7c232de5c9fc882ee19d636$
+// $hash=8fb252b18d67a1b189bd8eafeabde08bf28f0904$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_RESOURCE_HANDLER_CTOCPP_H_
@@ -41,10 +41,10 @@
   bool ProcessRequest(CefRefPtr<CefRequest> request,
                       CefRefPtr<CefCallback> callback) override;
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override;
-  bool Skip(int64 bytes_to_skip,
-            int64& bytes_skipped,
+  bool Skip(int64_t bytes_to_skip,
+            int64_t& bytes_skipped,
             CefRefPtr<CefResourceSkipCallback> callback) override;
   bool Read(void* data_out,
             int bytes_to_read,
diff --git a/src/libcef_dll/ctocpp/resource_read_callback_ctocpp.cc b/src/libcef_dll/ctocpp/resource_read_callback_ctocpp.cc
index cc899a0..1c4abb0 100644
--- a/src/libcef_dll/ctocpp/resource_read_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/resource_read_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=125f79d2fcbf968b7fd2d872b03a711274583eb1$
+// $hash=453b8327acaa3268d910e7bbc14e735b176d8c47$
 //
 
 #include "libcef_dll/ctocpp/resource_read_callback_ctocpp.h"
@@ -22,8 +22,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_resource_read_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cont))
+  if (CEF_MEMBER_MISSING(_struct, cont)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -47,7 +48,7 @@
     CefResourceReadCallback,
     cef_resource_read_callback_t>::UnwrapDerived(CefWrapperType type,
                                                  CefResourceReadCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/resource_read_callback_ctocpp.h b/src/libcef_dll/ctocpp/resource_read_callback_ctocpp.h
index 57af0ff..37b79c9 100644
--- a/src/libcef_dll/ctocpp/resource_read_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/resource_read_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=623833bb4eb1b7acbd3b3d7f119760178ae137e1$
+// $hash=aeb2eaecc30bb2498b709af0ec45dd6b5dc9b392$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_RESOURCE_READ_CALLBACK_CTOCPP_H_
@@ -35,7 +35,7 @@
   virtual ~CefResourceReadCallbackCToCpp();
 
   // CefResourceReadCallback methods.
-  void Continue(int bytes_read) OVERRIDE;
+  void Continue(int bytes_read) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_RESOURCE_READ_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/resource_request_handler_ctocpp.cc b/src/libcef_dll/ctocpp/resource_request_handler_ctocpp.cc
index 66634fd..ec48cb6 100644
--- a/src/libcef_dll/ctocpp/resource_request_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/resource_request_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,13 +9,13 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4b688dcc74e4949b8e9a236c16530d77323d2b32$
+// $hash=c83807dbfe712034b49de15498c682b0f0e42d71$
 //
 
 #include "libcef_dll/ctocpp/resource_request_handler_ctocpp.h"
 #include "libcef_dll/cpptoc/browser_cpptoc.h"
+#include "libcef_dll/cpptoc/callback_cpptoc.h"
 #include "libcef_dll/cpptoc/frame_cpptoc.h"
-#include "libcef_dll/cpptoc/request_callback_cpptoc.h"
 #include "libcef_dll/cpptoc/request_cpptoc.h"
 #include "libcef_dll/cpptoc/response_cpptoc.h"
 #include "libcef_dll/ctocpp/cookie_access_filter_ctocpp.h"
@@ -31,15 +31,17 @@
     CefRefPtr<CefFrame> frame,
     CefRefPtr<CefRequest> request) {
   cef_resource_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_cookie_access_filter))
+  if (CEF_MEMBER_MISSING(_struct, get_cookie_access_filter)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return nullptr;
+  }
   // Unverified params: browser, frame
 
   // Execute
@@ -57,28 +59,30 @@
     CefRefPtr<CefBrowser> browser,
     CefRefPtr<CefFrame> frame,
     CefRefPtr<CefRequest> request,
-    CefRefPtr<CefRequestCallback> callback) {
+    CefRefPtr<CefCallback> callback) {
   cef_resource_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_before_resource_load))
+  if (CEF_MEMBER_MISSING(_struct, on_before_resource_load)) {
     return RV_CONTINUE;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return RV_CONTINUE;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return RV_CONTINUE;
+  }
   // Unverified params: browser, frame
 
   // Execute
   cef_return_value_t _retval = _struct->on_before_resource_load(
       _struct, CefBrowserCppToC::Wrap(browser), CefFrameCppToC::Wrap(frame),
-      CefRequestCppToC::Wrap(request),
-      CefRequestCallbackCppToC::Wrap(callback));
+      CefRequestCppToC::Wrap(request), CefCallbackCppToC::Wrap(callback));
 
   // Return type: simple
   return _retval;
@@ -91,15 +95,17 @@
     CefRefPtr<CefFrame> frame,
     CefRefPtr<CefRequest> request) {
   cef_resource_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_resource_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_resource_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return nullptr;
+  }
   // Unverified params: browser, frame
 
   // Execute
@@ -119,19 +125,22 @@
     CefRefPtr<CefResponse> response,
     CefString& new_url) {
   cef_resource_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_resource_redirect))
+  if (CEF_MEMBER_MISSING(_struct, on_resource_redirect)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return;
+  }
   // Verify param: response; type: refptr_diff
   DCHECK(response.get());
-  if (!response.get())
+  if (!response.get()) {
     return;
+  }
   // Unverified params: browser, frame
 
   // Execute
@@ -148,19 +157,22 @@
     CefRefPtr<CefRequest> request,
     CefRefPtr<CefResponse> response) {
   cef_resource_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_resource_response))
+  if (CEF_MEMBER_MISSING(_struct, on_resource_response)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return false;
+  }
   // Verify param: response; type: refptr_diff
   DCHECK(response.get());
-  if (!response.get())
+  if (!response.get()) {
     return false;
+  }
   // Unverified params: browser, frame
 
   // Execute
@@ -180,19 +192,22 @@
     CefRefPtr<CefRequest> request,
     CefRefPtr<CefResponse> response) {
   cef_resource_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_resource_response_filter))
+  if (CEF_MEMBER_MISSING(_struct, get_resource_response_filter)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return nullptr;
+  }
   // Verify param: response; type: refptr_diff
   DCHECK(response.get());
-  if (!response.get())
+  if (!response.get()) {
     return nullptr;
+  }
   // Unverified params: browser, frame
 
   // Execute
@@ -211,21 +226,24 @@
     CefRefPtr<CefRequest> request,
     CefRefPtr<CefResponse> response,
     URLRequestStatus status,
-    int64 received_content_length) {
+    int64_t received_content_length) {
   cef_resource_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_resource_load_complete))
+  if (CEF_MEMBER_MISSING(_struct, on_resource_load_complete)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return;
+  }
   // Verify param: response; type: refptr_diff
   DCHECK(response.get());
-  if (!response.get())
+  if (!response.get()) {
     return;
+  }
   // Unverified params: browser, frame
 
   // Execute
@@ -242,15 +260,17 @@
     CefRefPtr<CefRequest> request,
     bool& allow_os_execution) {
   cef_resource_request_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_protocol_execution))
+  if (CEF_MEMBER_MISSING(_struct, on_protocol_execution)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return;
+  }
   // Unverified params: browser, frame
 
   // Translate param: allow_os_execution; type: bool_byref
@@ -280,7 +300,7 @@
     cef_resource_request_handler_t>::UnwrapDerived(CefWrapperType type,
                                                    CefResourceRequestHandler*
                                                        c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/resource_request_handler_ctocpp.h b/src/libcef_dll/ctocpp/resource_request_handler_ctocpp.h
index fe00e89..f590da5 100644
--- a/src/libcef_dll/ctocpp/resource_request_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/resource_request_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6ab9b4e37284582d67a4a6e63ab7e1d331b1442f$
+// $hash=7d93191b6f6cc58914df4909e3170d11fc826452$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_RESOURCE_REQUEST_HANDLER_CTOCPP_H_
@@ -39,11 +39,10 @@
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request) override;
-  ReturnValue OnBeforeResourceLoad(
-      CefRefPtr<CefBrowser> browser,
-      CefRefPtr<CefFrame> frame,
-      CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) override;
+  ReturnValue OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser,
+                                   CefRefPtr<CefFrame> frame,
+                                   CefRefPtr<CefRequest> request,
+                                   CefRefPtr<CefCallback> callback) override;
   CefRefPtr<CefResourceHandler> GetResourceHandler(
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
@@ -67,7 +66,7 @@
                               CefRefPtr<CefRequest> request,
                               CefRefPtr<CefResponse> response,
                               URLRequestStatus status,
-                              int64 received_content_length) override;
+                              int64_t received_content_length) override;
   void OnProtocolExecution(CefRefPtr<CefBrowser> browser,
                            CefRefPtr<CefFrame> frame,
                            CefRefPtr<CefRequest> request,
diff --git a/src/libcef_dll/ctocpp/resource_skip_callback_ctocpp.cc b/src/libcef_dll/ctocpp/resource_skip_callback_ctocpp.cc
index 3402923..ab7c844 100644
--- a/src/libcef_dll/ctocpp/resource_skip_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/resource_skip_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2233b3c4dd73427daaf72910a7944ce0ecb63e46$
+// $hash=454b004b9ea5060a540663985fcc76cbf250d69b$
 //
 
 #include "libcef_dll/ctocpp/resource_skip_callback_ctocpp.h"
@@ -18,12 +18,13 @@
 // VIRTUAL METHODS - Body may be edited by hand.
 
 NO_SANITIZE("cfi-icall")
-void CefResourceSkipCallbackCToCpp::Continue(int64 bytes_skipped) {
+void CefResourceSkipCallbackCToCpp::Continue(int64_t bytes_skipped) {
   shutdown_checker::AssertNotShutdown();
 
   cef_resource_skip_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cont))
+  if (CEF_MEMBER_MISSING(_struct, cont)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -47,7 +48,7 @@
     CefResourceSkipCallback,
     cef_resource_skip_callback_t>::UnwrapDerived(CefWrapperType type,
                                                  CefResourceSkipCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/resource_skip_callback_ctocpp.h b/src/libcef_dll/ctocpp/resource_skip_callback_ctocpp.h
index bb11b0b..772b8f4 100644
--- a/src/libcef_dll/ctocpp/resource_skip_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/resource_skip_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3b921fa2ac60c6a97a544223275bbc02ce26b899$
+// $hash=199035206a81ce991d025997baf3e64007d74c65$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_RESOURCE_SKIP_CALLBACK_CTOCPP_H_
@@ -35,7 +35,7 @@
   virtual ~CefResourceSkipCallbackCToCpp();
 
   // CefResourceSkipCallback methods.
-  void Continue(int64 bytes_skipped) OVERRIDE;
+  void Continue(int64_t bytes_skipped) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_RESOURCE_SKIP_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/response_ctocpp.cc b/src/libcef_dll/ctocpp/response_ctocpp.cc
index b7779ea..ff72a75 100644
--- a/src/libcef_dll/ctocpp/response_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/response_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=343ac0d93557b9f3a6e9e2500a4e2ab36b632312$
+// $hash=4a42afa43cf782789da01e2bc97fe635e530db7b$
 //
 
 #include "libcef_dll/ctocpp/response_ctocpp.h"
@@ -31,8 +31,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefResponseCToCpp::IsReadOnly() {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_read_only))
+  if (CEF_MEMBER_MISSING(_struct, is_read_only)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -45,8 +46,9 @@
 
 NO_SANITIZE("cfi-icall") cef_errorcode_t CefResponseCToCpp::GetError() {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_error))
+  if (CEF_MEMBER_MISSING(_struct, get_error)) {
     return ERR_NONE;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -60,8 +62,9 @@
 NO_SANITIZE("cfi-icall")
 void CefResponseCToCpp::SetError(cef_errorcode_t error) {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_error))
+  if (CEF_MEMBER_MISSING(_struct, set_error)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -71,8 +74,9 @@
 
 NO_SANITIZE("cfi-icall") int CefResponseCToCpp::GetStatus() {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_status))
+  if (CEF_MEMBER_MISSING(_struct, get_status)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -85,8 +89,9 @@
 
 NO_SANITIZE("cfi-icall") void CefResponseCToCpp::SetStatus(int status) {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_status))
+  if (CEF_MEMBER_MISSING(_struct, set_status)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -96,8 +101,9 @@
 
 NO_SANITIZE("cfi-icall") CefString CefResponseCToCpp::GetStatusText() {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_status_text))
+  if (CEF_MEMBER_MISSING(_struct, get_status_text)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -113,8 +119,9 @@
 NO_SANITIZE("cfi-icall")
 void CefResponseCToCpp::SetStatusText(const CefString& statusText) {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_status_text))
+  if (CEF_MEMBER_MISSING(_struct, set_status_text)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -126,8 +133,9 @@
 
 NO_SANITIZE("cfi-icall") CefString CefResponseCToCpp::GetMimeType() {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_mime_type))
+  if (CEF_MEMBER_MISSING(_struct, get_mime_type)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -143,8 +151,9 @@
 NO_SANITIZE("cfi-icall")
 void CefResponseCToCpp::SetMimeType(const CefString& mimeType) {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_mime_type))
+  if (CEF_MEMBER_MISSING(_struct, set_mime_type)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -156,8 +165,9 @@
 
 NO_SANITIZE("cfi-icall") CefString CefResponseCToCpp::GetCharset() {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_charset))
+  if (CEF_MEMBER_MISSING(_struct, get_charset)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -173,8 +183,9 @@
 NO_SANITIZE("cfi-icall")
 void CefResponseCToCpp::SetCharset(const CefString& charset) {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_charset))
+  if (CEF_MEMBER_MISSING(_struct, set_charset)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -187,15 +198,17 @@
 NO_SANITIZE("cfi-icall")
 CefString CefResponseCToCpp::GetHeaderByName(const CefString& name) {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_header_by_name))
+  if (CEF_MEMBER_MISSING(_struct, get_header_by_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return CefString();
+  }
 
   // Execute
   cef_string_userfree_t _retval =
@@ -212,15 +225,17 @@
                                         const CefString& value,
                                         bool overwrite) {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_header_by_name))
+  if (CEF_MEMBER_MISSING(_struct, set_header_by_name)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return;
+  }
   // Unverified params: value
 
   // Execute
@@ -231,16 +246,18 @@
 NO_SANITIZE("cfi-icall")
 void CefResponseCToCpp::GetHeaderMap(HeaderMap& headerMap) {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_header_map))
+  if (CEF_MEMBER_MISSING(_struct, get_header_map)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: headerMap; type: string_map_multi_byref
   cef_string_multimap_t headerMapMultimap = cef_string_multimap_alloc();
   DCHECK(headerMapMultimap);
-  if (headerMapMultimap)
+  if (headerMapMultimap) {
     transfer_string_multimap_contents(headerMap, headerMapMultimap);
+  }
 
   // Execute
   _struct->get_header_map(_struct, headerMapMultimap);
@@ -256,29 +273,33 @@
 NO_SANITIZE("cfi-icall")
 void CefResponseCToCpp::SetHeaderMap(const HeaderMap& headerMap) {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_header_map))
+  if (CEF_MEMBER_MISSING(_struct, set_header_map)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: headerMap; type: string_map_multi_byref_const
   cef_string_multimap_t headerMapMultimap = cef_string_multimap_alloc();
   DCHECK(headerMapMultimap);
-  if (headerMapMultimap)
+  if (headerMapMultimap) {
     transfer_string_multimap_contents(headerMap, headerMapMultimap);
+  }
 
   // Execute
   _struct->set_header_map(_struct, headerMapMultimap);
 
   // Restore param:headerMap; type: string_map_multi_byref_const
-  if (headerMapMultimap)
+  if (headerMapMultimap) {
     cef_string_multimap_free(headerMapMultimap);
+  }
 }
 
 NO_SANITIZE("cfi-icall") CefString CefResponseCToCpp::GetURL() {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_url))
+  if (CEF_MEMBER_MISSING(_struct, get_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -293,8 +314,9 @@
 
 NO_SANITIZE("cfi-icall") void CefResponseCToCpp::SetURL(const CefString& url) {
   cef_response_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_url))
+  if (CEF_MEMBER_MISSING(_struct, set_url)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -316,7 +338,7 @@
 cef_response_t*
 CefCToCppRefCounted<CefResponseCToCpp, CefResponse, cef_response_t>::
     UnwrapDerived(CefWrapperType type, CefResponse* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/response_ctocpp.h b/src/libcef_dll/ctocpp/response_ctocpp.h
index c3a179b..00a1279 100644
--- a/src/libcef_dll/ctocpp/response_ctocpp.h
+++ b/src/libcef_dll/ctocpp/response_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=59826865807e14e451ec90e7188f48da3748b325$
+// $hash=3ec4c709bcd18d24997d554134b1b01e17bbd0fb$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_RESPONSE_CTOCPP_H_
@@ -34,25 +34,25 @@
   virtual ~CefResponseCToCpp();
 
   // CefResponse methods.
-  bool IsReadOnly() OVERRIDE;
-  cef_errorcode_t GetError() OVERRIDE;
-  void SetError(cef_errorcode_t error) OVERRIDE;
-  int GetStatus() OVERRIDE;
-  void SetStatus(int status) OVERRIDE;
-  CefString GetStatusText() OVERRIDE;
-  void SetStatusText(const CefString& statusText) OVERRIDE;
-  CefString GetMimeType() OVERRIDE;
-  void SetMimeType(const CefString& mimeType) OVERRIDE;
-  CefString GetCharset() OVERRIDE;
-  void SetCharset(const CefString& charset) OVERRIDE;
-  CefString GetHeaderByName(const CefString& name) OVERRIDE;
+  bool IsReadOnly() override;
+  cef_errorcode_t GetError() override;
+  void SetError(cef_errorcode_t error) override;
+  int GetStatus() override;
+  void SetStatus(int status) override;
+  CefString GetStatusText() override;
+  void SetStatusText(const CefString& statusText) override;
+  CefString GetMimeType() override;
+  void SetMimeType(const CefString& mimeType) override;
+  CefString GetCharset() override;
+  void SetCharset(const CefString& charset) override;
+  CefString GetHeaderByName(const CefString& name) override;
   void SetHeaderByName(const CefString& name,
                        const CefString& value,
-                       bool overwrite) OVERRIDE;
-  void GetHeaderMap(HeaderMap& headerMap) OVERRIDE;
-  void SetHeaderMap(const HeaderMap& headerMap) OVERRIDE;
-  CefString GetURL() OVERRIDE;
-  void SetURL(const CefString& url) OVERRIDE;
+                       bool overwrite) override;
+  void GetHeaderMap(HeaderMap& headerMap) override;
+  void SetHeaderMap(const HeaderMap& headerMap) override;
+  CefString GetURL() override;
+  void SetURL(const CefString& url) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_RESPONSE_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/response_filter_ctocpp.cc b/src/libcef_dll/ctocpp/response_filter_ctocpp.cc
index 9bcc589..9149d60 100644
--- a/src/libcef_dll/ctocpp/response_filter_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/response_filter_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f317870833b17779de0a9cb0f0516aface361613$
+// $hash=55cc0e8d94b38923a37942b57ffe26ac9be16ccf$
 //
 
 #include "libcef_dll/ctocpp/response_filter_ctocpp.h"
@@ -21,8 +21,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_response_filter_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, init_filter))
+  if (CEF_MEMBER_MISSING(_struct, init_filter)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -44,15 +45,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_response_filter_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, filter))
+  if (CEF_MEMBER_MISSING(_struct, filter)) {
     return RESPONSE_FILTER_ERROR;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: data_out; type: simple_byaddr
   DCHECK(data_out);
-  if (!data_out)
+  if (!data_out) {
     return RESPONSE_FILTER_ERROR;
+  }
   // Unverified params: data_in
 
   // Execute
@@ -80,7 +83,7 @@
     CefResponseFilter,
     cef_response_filter_t>::UnwrapDerived(CefWrapperType type,
                                           CefResponseFilter* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/response_filter_ctocpp.h b/src/libcef_dll/ctocpp/response_filter_ctocpp.h
index 35d4eb9..a15d97f 100644
--- a/src/libcef_dll/ctocpp/response_filter_ctocpp.h
+++ b/src/libcef_dll/ctocpp/response_filter_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=33af4ee0e319f8a1585b9b331101cacf51aa686f$
+// $hash=b9ca51a2ee848580b14c1a06b49b2b9e048ab798$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_RESPONSE_FILTER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/run_context_menu_callback_ctocpp.cc b/src/libcef_dll/ctocpp/run_context_menu_callback_ctocpp.cc
index 995cba4..e4e04de 100644
--- a/src/libcef_dll/ctocpp/run_context_menu_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/run_context_menu_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2f1eac0f40c023b5257161efd4b4b1911f1ab8b6$
+// $hash=71acbdd04b0d9ed591ec351684b09f1375308cd6$
 //
 
 #include "libcef_dll/ctocpp/run_context_menu_callback_ctocpp.h"
@@ -19,12 +19,13 @@
 
 NO_SANITIZE("cfi-icall")
 void CefRunContextMenuCallbackCToCpp::Continue(int command_id,
-                                               EventFlags event_flags) {
+                                               cef_event_flags_t event_flags) {
   shutdown_checker::AssertNotShutdown();
 
   cef_run_context_menu_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cont))
+  if (CEF_MEMBER_MISSING(_struct, cont)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -36,8 +37,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_run_context_menu_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cancel))
+  if (CEF_MEMBER_MISSING(_struct, cancel)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -62,7 +64,7 @@
     cef_run_context_menu_callback_t>::UnwrapDerived(CefWrapperType type,
                                                     CefRunContextMenuCallback*
                                                         c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/run_context_menu_callback_ctocpp.h b/src/libcef_dll/ctocpp/run_context_menu_callback_ctocpp.h
index 33759d3..90d9cd6 100644
--- a/src/libcef_dll/ctocpp/run_context_menu_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/run_context_menu_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2a475530e05300e2326247f9bdabeb4cfdf7217e$
+// $hash=7663b13ecb057bba0158685bc34783f37ef2f030$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_RUN_CONTEXT_MENU_CALLBACK_CTOCPP_H_
@@ -35,8 +35,8 @@
   virtual ~CefRunContextMenuCallbackCToCpp();
 
   // CefRunContextMenuCallback methods.
-  void Continue(int command_id, EventFlags event_flags) OVERRIDE;
-  void Cancel() OVERRIDE;
+  void Continue(int command_id, cef_event_flags_t event_flags) override;
+  void Cancel() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_RUN_CONTEXT_MENU_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.cc b/src/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.cc
index 32fb4fb..90b3fc0 100644
--- a/src/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0065d3160cbd59f9fe8f5272acbca0a90a5eda81$
+// $hash=88c6cc75c33fd04ded84b3a8f99bcb537d462a0d$
 //
 
 #include "libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h"
@@ -20,35 +20,32 @@
 
 NO_SANITIZE("cfi-icall")
 void CefRunFileDialogCallbackCToCpp::OnFileDialogDismissed(
-    int selected_accept_filter,
     const std::vector<CefString>& file_paths) {
   shutdown_checker::AssertNotShutdown();
 
   cef_run_file_dialog_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_file_dialog_dismissed))
+  if (CEF_MEMBER_MISSING(_struct, on_file_dialog_dismissed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
-  // Verify param: selected_accept_filter; type: simple_byval
-  DCHECK_GE(selected_accept_filter, 0);
-  if (selected_accept_filter < 0)
-    return;
   // Unverified params: file_paths
 
   // Translate param: file_paths; type: string_vec_byref_const
   cef_string_list_t file_pathsList = cef_string_list_alloc();
   DCHECK(file_pathsList);
-  if (file_pathsList)
+  if (file_pathsList) {
     transfer_string_list_contents(file_paths, file_pathsList);
+  }
 
   // Execute
-  _struct->on_file_dialog_dismissed(_struct, selected_accept_filter,
-                                    file_pathsList);
+  _struct->on_file_dialog_dismissed(_struct, file_pathsList);
 
   // Restore param:file_paths; type: string_vec_byref_const
-  if (file_pathsList)
+  if (file_pathsList) {
     cef_string_list_free(file_pathsList);
+  }
 }
 
 // CONSTRUCTOR - Do not edit by hand.
@@ -68,7 +65,7 @@
     cef_run_file_dialog_callback_t>::UnwrapDerived(CefWrapperType type,
                                                    CefRunFileDialogCallback*
                                                        c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h b/src/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h
index 4c8b517..e109d0d 100644
--- a/src/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0783d7d71c2e1a69fdaf9a76e72a2c12d49e8363$
+// $hash=5793fe937c3f7fb75ee7d79ab6bd6e93411bd954$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_RUN_FILE_DIALOG_CALLBACK_CTOCPP_H_
@@ -38,8 +38,7 @@
   virtual ~CefRunFileDialogCallbackCToCpp();
 
   // CefRunFileDialogCallback methods.
-  void OnFileDialogDismissed(int selected_accept_filter,
-                             const std::vector<CefString>& file_paths) override;
+  void OnFileDialogDismissed(const std::vector<CefString>& file_paths) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_RUN_FILE_DIALOG_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/run_quick_menu_callback_ctocpp.cc b/src/libcef_dll/ctocpp/run_quick_menu_callback_ctocpp.cc
new file mode 100644
index 0000000..5d3da07
--- /dev/null
+++ b/src/libcef_dll/ctocpp/run_quick_menu_callback_ctocpp.cc
@@ -0,0 +1,75 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=b1531352b058e448d89cee9e34c9ff512f7b61dc$
+//
+
+#include "libcef_dll/ctocpp/run_quick_menu_callback_ctocpp.h"
+#include "libcef_dll/shutdown_checker.h"
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall")
+void CefRunQuickMenuCallbackCToCpp::Continue(int command_id,
+                                             cef_event_flags_t event_flags) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_run_quick_menu_callback_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, cont)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->cont(_struct, command_id, event_flags);
+}
+
+NO_SANITIZE("cfi-icall") void CefRunQuickMenuCallbackCToCpp::Cancel() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_run_quick_menu_callback_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, cancel)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->cancel(_struct);
+}
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefRunQuickMenuCallbackCToCpp::CefRunQuickMenuCallbackCToCpp() {}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefRunQuickMenuCallbackCToCpp::~CefRunQuickMenuCallbackCToCpp() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+cef_run_quick_menu_callback_t* CefCToCppRefCounted<
+    CefRunQuickMenuCallbackCToCpp,
+    CefRunQuickMenuCallback,
+    cef_run_quick_menu_callback_t>::UnwrapDerived(CefWrapperType type,
+                                                  CefRunQuickMenuCallback* c) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType
+    CefCToCppRefCounted<CefRunQuickMenuCallbackCToCpp,
+                        CefRunQuickMenuCallback,
+                        cef_run_quick_menu_callback_t>::kWrapperType =
+        WT_RUN_QUICK_MENU_CALLBACK;
diff --git a/src/libcef_dll/ctocpp/run_quick_menu_callback_ctocpp.h b/src/libcef_dll/ctocpp/run_quick_menu_callback_ctocpp.h
new file mode 100644
index 0000000..155b0b9
--- /dev/null
+++ b/src/libcef_dll/ctocpp/run_quick_menu_callback_ctocpp.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=c079137f43167df4c21e63f38cdd8c33f4423445$
+//
+
+#ifndef CEF_LIBCEF_DLL_CTOCPP_RUN_QUICK_MENU_CALLBACK_CTOCPP_H_
+#define CEF_LIBCEF_DLL_CTOCPP_RUN_QUICK_MENU_CALLBACK_CTOCPP_H_
+#pragma once
+
+#if !defined(WRAPPING_CEF_SHARED)
+#error This file can be included wrapper-side only
+#endif
+
+#include "include/capi/cef_context_menu_handler_capi.h"
+#include "include/cef_context_menu_handler.h"
+#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
+
+// Wrap a C structure with a C++ class.
+// This class may be instantiated and accessed wrapper-side only.
+class CefRunQuickMenuCallbackCToCpp
+    : public CefCToCppRefCounted<CefRunQuickMenuCallbackCToCpp,
+                                 CefRunQuickMenuCallback,
+                                 cef_run_quick_menu_callback_t> {
+ public:
+  CefRunQuickMenuCallbackCToCpp();
+  virtual ~CefRunQuickMenuCallbackCToCpp();
+
+  // CefRunQuickMenuCallback methods.
+  void Continue(int command_id, cef_event_flags_t event_flags) override;
+  void Cancel() override;
+};
+
+#endif  // CEF_LIBCEF_DLL_CTOCPP_RUN_QUICK_MENU_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.cc b/src/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.cc
index 014a77c..ecc14c3 100644
--- a/src/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ba596df840e36426b87e0744fcf55e179a915c5e$
+// $hash=3e078458c9ec423ac8ea129888485e600896e03f$
 //
 
 #include "libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h"
@@ -27,19 +27,22 @@
     const CefString& scheme_name,
     CefRefPtr<CefRequest> request) {
   cef_scheme_handler_factory_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, create))
+  if (CEF_MEMBER_MISSING(_struct, create)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: scheme_name; type: string_byref_const
   DCHECK(!scheme_name.empty());
-  if (scheme_name.empty())
+  if (scheme_name.empty()) {
     return nullptr;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return nullptr;
+  }
   // Unverified params: browser, frame
 
   // Execute
@@ -65,7 +68,7 @@
     CefSchemeHandlerFactory,
     cef_scheme_handler_factory_t>::UnwrapDerived(CefWrapperType type,
                                                  CefSchemeHandlerFactory* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h b/src/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h
index cf51b1b..6e20d97 100644
--- a/src/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h
+++ b/src/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ce60f732df5ba8d6bf345f0451ca75a8a634e4e8$
+// $hash=8553de031f140b9c850e487863fc91b97633314b$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_SCHEME_HANDLER_FACTORY_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/scheme_registrar_ctocpp.cc b/src/libcef_dll/ctocpp/scheme_registrar_ctocpp.cc
index ef41462..d5dc40d 100644
--- a/src/libcef_dll/ctocpp/scheme_registrar_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/scheme_registrar_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=96867bd89ff762e10642ac8c037b187a03dab85e$
+// $hash=d38b1cdd4e0df15235315e9efeb5c4ab3b92930b$
 //
 
 #include "libcef_dll/ctocpp/scheme_registrar_ctocpp.h"
@@ -20,15 +20,17 @@
 bool CefSchemeRegistrarCToCpp::AddCustomScheme(const CefString& scheme_name,
                                                int options) {
   cef_scheme_registrar_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, add_custom_scheme))
+  if (CEF_MEMBER_MISSING(_struct, add_custom_scheme)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: scheme_name; type: string_byref_const
   DCHECK(!scheme_name.empty());
-  if (scheme_name.empty())
+  if (scheme_name.empty()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -52,7 +54,7 @@
     CefSchemeRegistrar,
     cef_scheme_registrar_t>::UnwrapDerivedOwn(CefWrapperType type,
                                               CefOwnPtr<CefSchemeRegistrar> c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
@@ -62,7 +64,7 @@
     CefSchemeRegistrar,
     cef_scheme_registrar_t>::UnwrapDerivedRaw(CefWrapperType type,
                                               CefRawPtr<CefSchemeRegistrar> c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/scheme_registrar_ctocpp.h b/src/libcef_dll/ctocpp/scheme_registrar_ctocpp.h
index e27a93a..8ac7075 100644
--- a/src/libcef_dll/ctocpp/scheme_registrar_ctocpp.h
+++ b/src/libcef_dll/ctocpp/scheme_registrar_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=5b599c1296d8643dd104d2ecb65528d85b6be6d5$
+// $hash=a30e0b019ab6b34998563c8bf46f7b0c8089c3ba$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_SCHEME_REGISTRAR_CTOCPP_H_
@@ -35,7 +35,7 @@
   virtual ~CefSchemeRegistrarCToCpp();
 
   // CefSchemeRegistrar methods.
-  bool AddCustomScheme(const CefString& scheme_name, int options) OVERRIDE;
+  bool AddCustomScheme(const CefString& scheme_name, int options) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_SCHEME_REGISTRAR_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/select_client_certificate_callback_ctocpp.cc b/src/libcef_dll/ctocpp/select_client_certificate_callback_ctocpp.cc
index 3b63ea8..2e57a24 100644
--- a/src/libcef_dll/ctocpp/select_client_certificate_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/select_client_certificate_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9074ca50ffc28d04a31a322d86e8b6118782a724$
+// $hash=626530c59232a37a7f7a744637d11875a7d0d0f7$
 //
 
 #include "libcef_dll/ctocpp/select_client_certificate_callback_ctocpp.h"
@@ -24,8 +24,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_select_client_certificate_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, select))
+  if (CEF_MEMBER_MISSING(_struct, select)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -53,7 +54,7 @@
                     CefSelectClientCertificateCallback,
                     cef_select_client_certificate_callback_t>::
     UnwrapDerived(CefWrapperType type, CefSelectClientCertificateCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/select_client_certificate_callback_ctocpp.h b/src/libcef_dll/ctocpp/select_client_certificate_callback_ctocpp.h
index d23e0a3..4b62165 100644
--- a/src/libcef_dll/ctocpp/select_client_certificate_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/select_client_certificate_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c1ae778f52e24fdb61ed52ca4b79f32b8a336f8f$
+// $hash=49b4af5d293d5d88b27bea26aca6c410f86c6e59$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_SELECT_CLIENT_CERTIFICATE_CALLBACK_CTOCPP_H_
@@ -35,7 +35,7 @@
   virtual ~CefSelectClientCertificateCallbackCToCpp();
 
   // CefSelectClientCertificateCallback methods.
-  void Select(CefRefPtr<CefX509Certificate> cert) OVERRIDE;
+  void Select(CefRefPtr<CefX509Certificate> cert) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_SELECT_CLIENT_CERTIFICATE_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/server_ctocpp.cc b/src/libcef_dll/ctocpp/server_ctocpp.cc
index cee398b..6991b7a 100644
--- a/src/libcef_dll/ctocpp/server_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/server_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e33f5d5355018c27df765228ce01ea4d21ac1663$
+// $hash=c8c7a86f0fb91ad4ddca453253038e540b63f313$
 //
 
 #include "libcef_dll/ctocpp/server_ctocpp.h"
@@ -22,7 +22,7 @@
 
 NO_SANITIZE("cfi-icall")
 void CefServer::CreateServer(const CefString& address,
-                             uint16 port,
+                             uint16_t port,
                              int backlog,
                              CefRefPtr<CefServerHandler> handler) {
   shutdown_checker::AssertNotShutdown();
@@ -31,12 +31,14 @@
 
   // Verify param: address; type: string_byref_const
   DCHECK(!address.empty());
-  if (address.empty())
+  if (address.empty()) {
     return;
+  }
   // Verify param: handler; type: refptr_diff
   DCHECK(handler.get());
-  if (!handler.get())
+  if (!handler.get()) {
     return;
+  }
 
   // Execute
   cef_server_create(address.GetStruct(), port, backlog,
@@ -50,8 +52,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_task_runner))
+  if (CEF_MEMBER_MISSING(_struct, get_task_runner)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -66,8 +69,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, shutdown))
+  if (CEF_MEMBER_MISSING(_struct, shutdown)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -79,8 +83,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_running))
+  if (CEF_MEMBER_MISSING(_struct, is_running)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -95,8 +100,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_address))
+  if (CEF_MEMBER_MISSING(_struct, get_address)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -113,8 +119,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_connection))
+  if (CEF_MEMBER_MISSING(_struct, has_connection)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -130,8 +137,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid_connection))
+  if (CEF_MEMBER_MISSING(_struct, is_valid_connection)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -150,19 +158,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_http200response))
+  if (CEF_MEMBER_MISSING(_struct, send_http200response)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: content_type; type: string_byref_const
   DCHECK(!content_type.empty());
-  if (content_type.empty())
+  if (content_type.empty()) {
     return;
+  }
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return;
+  }
 
   // Execute
   _struct->send_http200response(_struct, connection_id,
@@ -174,8 +185,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_http404response))
+  if (CEF_MEMBER_MISSING(_struct, send_http404response)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -189,15 +201,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_http500response))
+  if (CEF_MEMBER_MISSING(_struct, send_http500response)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: error_message; type: string_byref_const
   DCHECK(!error_message.empty());
-  if (error_message.empty())
+  if (error_message.empty()) {
     return;
+  }
 
   // Execute
   _struct->send_http500response(_struct, connection_id,
@@ -208,27 +222,30 @@
 void CefServerCToCpp::SendHttpResponse(int connection_id,
                                        int response_code,
                                        const CefString& content_type,
-                                       int64 content_length,
+                                       int64_t content_length,
                                        const HeaderMap& extra_headers) {
   shutdown_checker::AssertNotShutdown();
 
   cef_server_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_http_response))
+  if (CEF_MEMBER_MISSING(_struct, send_http_response)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: content_type; type: string_byref_const
   DCHECK(!content_type.empty());
-  if (content_type.empty())
+  if (content_type.empty()) {
     return;
+  }
   // Unverified params: extra_headers
 
   // Translate param: extra_headers; type: string_map_multi_byref_const
   cef_string_multimap_t extra_headersMultimap = cef_string_multimap_alloc();
   DCHECK(extra_headersMultimap);
-  if (extra_headersMultimap)
+  if (extra_headersMultimap) {
     transfer_string_multimap_contents(extra_headers, extra_headersMultimap);
+  }
 
   // Execute
   _struct->send_http_response(_struct, connection_id, response_code,
@@ -236,8 +253,9 @@
                               extra_headersMultimap);
 
   // Restore param:extra_headers; type: string_map_multi_byref_const
-  if (extra_headersMultimap)
+  if (extra_headersMultimap) {
     cef_string_multimap_free(extra_headersMultimap);
+  }
 }
 
 NO_SANITIZE("cfi-icall")
@@ -247,15 +265,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_raw_data))
+  if (CEF_MEMBER_MISSING(_struct, send_raw_data)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return;
+  }
 
   // Execute
   _struct->send_raw_data(_struct, connection_id, data, data_size);
@@ -266,8 +286,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, close_connection))
+  if (CEF_MEMBER_MISSING(_struct, close_connection)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -282,15 +303,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_web_socket_message))
+  if (CEF_MEMBER_MISSING(_struct, send_web_socket_message)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return;
+  }
 
   // Execute
   _struct->send_web_socket_message(_struct, connection_id, data, data_size);
@@ -311,7 +334,7 @@
 CefCToCppRefCounted<CefServerCToCpp, CefServer, cef_server_t>::UnwrapDerived(
     CefWrapperType type,
     CefServer* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/server_ctocpp.h b/src/libcef_dll/ctocpp/server_ctocpp.h
index f95cd0e..daae220 100644
--- a/src/libcef_dll/ctocpp/server_ctocpp.h
+++ b/src/libcef_dll/ctocpp/server_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9cb2173041cc6127fcc511cb011dde29bb0995c3$
+// $hash=f46aa5f341aa11d832e6e90847eaa3fa3c8a84a8$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_SERVER_CTOCPP_H_
@@ -33,31 +33,31 @@
   virtual ~CefServerCToCpp();
 
   // CefServer methods.
-  CefRefPtr<CefTaskRunner> GetTaskRunner() OVERRIDE;
-  void Shutdown() OVERRIDE;
-  bool IsRunning() OVERRIDE;
-  CefString GetAddress() OVERRIDE;
-  bool HasConnection() OVERRIDE;
-  bool IsValidConnection(int connection_id) OVERRIDE;
+  CefRefPtr<CefTaskRunner> GetTaskRunner() override;
+  void Shutdown() override;
+  bool IsRunning() override;
+  CefString GetAddress() override;
+  bool HasConnection() override;
+  bool IsValidConnection(int connection_id) override;
   void SendHttp200Response(int connection_id,
                            const CefString& content_type,
                            const void* data,
-                           size_t data_size) OVERRIDE;
-  void SendHttp404Response(int connection_id) OVERRIDE;
+                           size_t data_size) override;
+  void SendHttp404Response(int connection_id) override;
   void SendHttp500Response(int connection_id,
-                           const CefString& error_message) OVERRIDE;
+                           const CefString& error_message) override;
   void SendHttpResponse(int connection_id,
                         int response_code,
                         const CefString& content_type,
-                        int64 content_length,
-                        const HeaderMap& extra_headers) OVERRIDE;
+                        int64_t content_length,
+                        const HeaderMap& extra_headers) override;
   void SendRawData(int connection_id,
                    const void* data,
-                   size_t data_size) OVERRIDE;
-  void CloseConnection(int connection_id) OVERRIDE;
+                   size_t data_size) override;
+  void CloseConnection(int connection_id) override;
   void SendWebSocketMessage(int connection_id,
                             const void* data,
-                            size_t data_size) OVERRIDE;
+                            size_t data_size) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_SERVER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/server_handler_ctocpp.cc b/src/libcef_dll/ctocpp/server_handler_ctocpp.cc
index 8c5c45d..112af23 100644
--- a/src/libcef_dll/ctocpp/server_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/server_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=eda7a02f86a6f75b5c2befa5cc3c02bf290a6782$
+// $hash=f94b3d675dfb95c556fb4b3f8c618507aeca89ad$
 //
 
 #include "libcef_dll/ctocpp/server_handler_ctocpp.h"
@@ -25,15 +25,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_server_created))
+  if (CEF_MEMBER_MISSING(_struct, on_server_created)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: server; type: refptr_diff
   DCHECK(server.get());
-  if (!server.get())
+  if (!server.get()) {
     return;
+  }
 
   // Execute
   _struct->on_server_created(_struct, CefServerCppToC::Wrap(server));
@@ -44,15 +46,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_server_destroyed))
+  if (CEF_MEMBER_MISSING(_struct, on_server_destroyed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: server; type: refptr_diff
   DCHECK(server.get());
-  if (!server.get())
+  if (!server.get()) {
     return;
+  }
 
   // Execute
   _struct->on_server_destroyed(_struct, CefServerCppToC::Wrap(server));
@@ -64,15 +68,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_client_connected))
+  if (CEF_MEMBER_MISSING(_struct, on_client_connected)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: server; type: refptr_diff
   DCHECK(server.get());
-  if (!server.get())
+  if (!server.get()) {
     return;
+  }
 
   // Execute
   _struct->on_client_connected(_struct, CefServerCppToC::Wrap(server),
@@ -85,15 +91,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_client_disconnected))
+  if (CEF_MEMBER_MISSING(_struct, on_client_disconnected)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: server; type: refptr_diff
   DCHECK(server.get());
-  if (!server.get())
+  if (!server.get()) {
     return;
+  }
 
   // Execute
   _struct->on_client_disconnected(_struct, CefServerCppToC::Wrap(server),
@@ -108,23 +116,27 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_http_request))
+  if (CEF_MEMBER_MISSING(_struct, on_http_request)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: server; type: refptr_diff
   DCHECK(server.get());
-  if (!server.get())
+  if (!server.get()) {
     return;
+  }
   // Verify param: client_address; type: string_byref_const
   DCHECK(!client_address.empty());
-  if (client_address.empty())
+  if (client_address.empty()) {
     return;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return;
+  }
 
   // Execute
   _struct->on_http_request(_struct, CefServerCppToC::Wrap(server),
@@ -142,27 +154,32 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_web_socket_request))
+  if (CEF_MEMBER_MISSING(_struct, on_web_socket_request)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: server; type: refptr_diff
   DCHECK(server.get());
-  if (!server.get())
+  if (!server.get()) {
     return;
+  }
   // Verify param: client_address; type: string_byref_const
   DCHECK(!client_address.empty());
-  if (client_address.empty())
+  if (client_address.empty()) {
     return;
+  }
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return;
+  }
 
   // Execute
   _struct->on_web_socket_request(_struct, CefServerCppToC::Wrap(server),
@@ -177,15 +194,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_web_socket_connected))
+  if (CEF_MEMBER_MISSING(_struct, on_web_socket_connected)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: server; type: refptr_diff
   DCHECK(server.get());
-  if (!server.get())
+  if (!server.get()) {
     return;
+  }
 
   // Execute
   _struct->on_web_socket_connected(_struct, CefServerCppToC::Wrap(server),
@@ -200,19 +219,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_server_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_web_socket_message))
+  if (CEF_MEMBER_MISSING(_struct, on_web_socket_message)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: server; type: refptr_diff
   DCHECK(server.get());
-  if (!server.get())
+  if (!server.get()) {
     return;
+  }
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return;
+  }
 
   // Execute
   _struct->on_web_socket_message(_struct, CefServerCppToC::Wrap(server),
@@ -235,7 +257,7 @@
                     CefServerHandler,
                     cef_server_handler_t>::UnwrapDerived(CefWrapperType type,
                                                          CefServerHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/server_handler_ctocpp.h b/src/libcef_dll/ctocpp/server_handler_ctocpp.h
index e381cbc..fbb9d76 100644
--- a/src/libcef_dll/ctocpp/server_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/server_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=30d2dee5c66e3a98cd788f74a5856d068dc68e58$
+// $hash=0bed1f616f1ae42a7eb755dba59b329cd600abff$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_SERVER_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/set_cookie_callback_ctocpp.cc b/src/libcef_dll/ctocpp/set_cookie_callback_ctocpp.cc
index 1380a25..c4482cb 100644
--- a/src/libcef_dll/ctocpp/set_cookie_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/set_cookie_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=a00d1d8d0e2a5a7a63b8f9669301186ffc2fc664$
+// $hash=392363e82a7131e201fe074eda87020b8c2716de$
 //
 
 #include "libcef_dll/ctocpp/set_cookie_callback_ctocpp.h"
@@ -22,8 +22,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_set_cookie_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_complete))
+  if (CEF_MEMBER_MISSING(_struct, on_complete)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -47,7 +48,7 @@
     CefSetCookieCallback,
     cef_set_cookie_callback_t>::UnwrapDerived(CefWrapperType type,
                                               CefSetCookieCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/set_cookie_callback_ctocpp.h b/src/libcef_dll/ctocpp/set_cookie_callback_ctocpp.h
index 34e2ec7..0678071 100644
--- a/src/libcef_dll/ctocpp/set_cookie_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/set_cookie_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=18bb4e458cc3c1027baa21090f35c5a29018705d$
+// $hash=26be0ed7d7165630ee23b480419768f1fd9b95fe$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_SET_COOKIE_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/shared_memory_region_ctocpp.cc b/src/libcef_dll/ctocpp/shared_memory_region_ctocpp.cc
new file mode 100644
index 0000000..e9000f0
--- /dev/null
+++ b/src/libcef_dll/ctocpp/shared_memory_region_ctocpp.cc
@@ -0,0 +1,96 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=a396f422ed18fe4aae90d4fef3750b4726279c7e$
+//
+
+#include "libcef_dll/ctocpp/shared_memory_region_ctocpp.h"
+#include "libcef_dll/shutdown_checker.h"
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall") bool CefSharedMemoryRegionCToCpp::IsValid() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_shared_memory_region_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = _struct->is_valid(_struct);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall") size_t CefSharedMemoryRegionCToCpp::Size() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_shared_memory_region_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, size)) {
+    return 0;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  size_t _retval = _struct->size(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall") void* CefSharedMemoryRegionCToCpp::Memory() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_shared_memory_region_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, memory)) {
+    return NULL;
+  }
+
+  // This manual implementation can be removed once support for 'void*'
+  // is integrated into the CEF translator tool (issue #3591).
+
+  // Execute
+  void* _retval = _struct->memory(_struct);
+
+  // Return type: simple_byaddr
+  return _retval;
+}
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefSharedMemoryRegionCToCpp::CefSharedMemoryRegionCToCpp() {}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefSharedMemoryRegionCToCpp::~CefSharedMemoryRegionCToCpp() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+cef_shared_memory_region_t* CefCToCppRefCounted<
+    CefSharedMemoryRegionCToCpp,
+    CefSharedMemoryRegion,
+    cef_shared_memory_region_t>::UnwrapDerived(CefWrapperType type,
+                                               CefSharedMemoryRegion* c) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCToCppRefCounted<CefSharedMemoryRegionCToCpp,
+                                   CefSharedMemoryRegion,
+                                   cef_shared_memory_region_t>::kWrapperType =
+    WT_SHARED_MEMORY_REGION;
diff --git a/src/libcef_dll/ctocpp/shared_memory_region_ctocpp.h b/src/libcef_dll/ctocpp/shared_memory_region_ctocpp.h
new file mode 100644
index 0000000..490bfdf
--- /dev/null
+++ b/src/libcef_dll/ctocpp/shared_memory_region_ctocpp.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=a81ba6b7aca8e1f7e6e6ef41e727ddcffc06f204$
+//
+
+#ifndef CEF_LIBCEF_DLL_CTOCPP_SHARED_MEMORY_REGION_CTOCPP_H_
+#define CEF_LIBCEF_DLL_CTOCPP_SHARED_MEMORY_REGION_CTOCPP_H_
+#pragma once
+
+#if !defined(WRAPPING_CEF_SHARED)
+#error This file can be included wrapper-side only
+#endif
+
+#include "include/capi/cef_shared_memory_region_capi.h"
+#include "include/cef_shared_memory_region.h"
+#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
+
+// Wrap a C structure with a C++ class.
+// This class may be instantiated and accessed wrapper-side only.
+class CefSharedMemoryRegionCToCpp
+    : public CefCToCppRefCounted<CefSharedMemoryRegionCToCpp,
+                                 CefSharedMemoryRegion,
+                                 cef_shared_memory_region_t> {
+ public:
+  CefSharedMemoryRegionCToCpp();
+  virtual ~CefSharedMemoryRegionCToCpp();
+
+  // CefSharedMemoryRegion methods.
+  bool IsValid() override;
+  size_t Size() override;
+  void* Memory() override;
+};
+
+#endif  // CEF_LIBCEF_DLL_CTOCPP_SHARED_MEMORY_REGION_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/shared_process_message_builder_ctocpp.cc b/src/libcef_dll/ctocpp/shared_process_message_builder_ctocpp.cc
new file mode 100644
index 0000000..35839ea
--- /dev/null
+++ b/src/libcef_dll/ctocpp/shared_process_message_builder_ctocpp.cc
@@ -0,0 +1,137 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=439e6639c3e7a3f99de34d6c499b1c6766dc7fa7$
+//
+
+#include "libcef_dll/ctocpp/shared_process_message_builder_ctocpp.h"
+#include "libcef_dll/ctocpp/process_message_ctocpp.h"
+#include "libcef_dll/shutdown_checker.h"
+
+// STATIC METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall")
+CefRefPtr<CefSharedProcessMessageBuilder>
+CefSharedProcessMessageBuilder::Create(const CefString& name,
+                                       size_t byte_size) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: name; type: string_byref_const
+  DCHECK(!name.empty());
+  if (name.empty()) {
+    return nullptr;
+  }
+
+  // Execute
+  cef_shared_process_message_builder_t* _retval =
+      cef_shared_process_message_builder_create(name.GetStruct(), byte_size);
+
+  // Return type: refptr_same
+  return CefSharedProcessMessageBuilderCToCpp::Wrap(_retval);
+}
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall") bool CefSharedProcessMessageBuilderCToCpp::IsValid() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_shared_process_message_builder_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = _struct->is_valid(_struct);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall") size_t CefSharedProcessMessageBuilderCToCpp::Size() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_shared_process_message_builder_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, size)) {
+    return 0;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  size_t _retval = _struct->size(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall") void* CefSharedProcessMessageBuilderCToCpp::Memory() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_shared_process_message_builder_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, memory)) {
+    return NULL;
+  }
+
+  // Execute
+  void* _retval = _struct->memory(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall")
+CefRefPtr<CefProcessMessage> CefSharedProcessMessageBuilderCToCpp::Build() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_shared_process_message_builder_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, build)) {
+    return nullptr;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_process_message_t* _retval = _struct->build(_struct);
+
+  // Return type: refptr_same
+  return CefProcessMessageCToCpp::Wrap(_retval);
+}
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefSharedProcessMessageBuilderCToCpp::CefSharedProcessMessageBuilderCToCpp() {}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefSharedProcessMessageBuilderCToCpp::~CefSharedProcessMessageBuilderCToCpp() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+cef_shared_process_message_builder_t*
+CefCToCppRefCounted<CefSharedProcessMessageBuilderCToCpp,
+                    CefSharedProcessMessageBuilder,
+                    cef_shared_process_message_builder_t>::
+    UnwrapDerived(CefWrapperType type, CefSharedProcessMessageBuilder* c) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType
+    CefCToCppRefCounted<CefSharedProcessMessageBuilderCToCpp,
+                        CefSharedProcessMessageBuilder,
+                        cef_shared_process_message_builder_t>::kWrapperType =
+        WT_SHARED_PROCESS_MESSAGE_BUILDER;
diff --git a/src/libcef_dll/ctocpp/shared_process_message_builder_ctocpp.h b/src/libcef_dll/ctocpp/shared_process_message_builder_ctocpp.h
new file mode 100644
index 0000000..ea4f038
--- /dev/null
+++ b/src/libcef_dll/ctocpp/shared_process_message_builder_ctocpp.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=de0791f744ddb7e9e9256bb120f233cb64826188$
+//
+
+#ifndef CEF_LIBCEF_DLL_CTOCPP_SHARED_PROCESS_MESSAGE_BUILDER_CTOCPP_H_
+#define CEF_LIBCEF_DLL_CTOCPP_SHARED_PROCESS_MESSAGE_BUILDER_CTOCPP_H_
+#pragma once
+
+#if !defined(WRAPPING_CEF_SHARED)
+#error This file can be included wrapper-side only
+#endif
+
+#include "include/capi/cef_shared_process_message_builder_capi.h"
+#include "include/cef_shared_process_message_builder.h"
+#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
+
+// Wrap a C structure with a C++ class.
+// This class may be instantiated and accessed wrapper-side only.
+class CefSharedProcessMessageBuilderCToCpp
+    : public CefCToCppRefCounted<CefSharedProcessMessageBuilderCToCpp,
+                                 CefSharedProcessMessageBuilder,
+                                 cef_shared_process_message_builder_t> {
+ public:
+  CefSharedProcessMessageBuilderCToCpp();
+  virtual ~CefSharedProcessMessageBuilderCToCpp();
+
+  // CefSharedProcessMessageBuilder methods.
+  bool IsValid() override;
+  size_t Size() override;
+  void* Memory() override;
+  CefRefPtr<CefProcessMessage> Build() override;
+};
+
+#endif  // CEF_LIBCEF_DLL_CTOCPP_SHARED_PROCESS_MESSAGE_BUILDER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/sslinfo_ctocpp.cc b/src/libcef_dll/ctocpp/sslinfo_ctocpp.cc
index 37cca7a..0aa6fd9 100644
--- a/src/libcef_dll/ctocpp/sslinfo_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/sslinfo_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=bcc26f8afe20b67daeb6feb8578f195649b2bc59$
+// $hash=0390ebb66bafe64b20f8c55f156a5c118035e5fc$
 //
 
 #include "libcef_dll/ctocpp/sslinfo_ctocpp.h"
@@ -22,8 +22,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_sslinfo_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_cert_status))
+  if (CEF_MEMBER_MISSING(_struct, get_cert_status)) {
     return CERT_STATUS_NONE;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -39,8 +40,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_sslinfo_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_x509certificate))
+  if (CEF_MEMBER_MISSING(_struct, get_x509certificate)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -66,7 +68,7 @@
 CefCToCppRefCounted<CefSSLInfoCToCpp, CefSSLInfo, cef_sslinfo_t>::UnwrapDerived(
     CefWrapperType type,
     CefSSLInfo* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/sslinfo_ctocpp.h b/src/libcef_dll/ctocpp/sslinfo_ctocpp.h
index 22114e7..80ed6f1 100644
--- a/src/libcef_dll/ctocpp/sslinfo_ctocpp.h
+++ b/src/libcef_dll/ctocpp/sslinfo_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=27ba3a4f6fa0c2dd2d9dd88a6e21eab436610405$
+// $hash=d08212eed1df4078ed5bb72dd7fc6d478f476ecb$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_SSLINFO_CTOCPP_H_
@@ -33,8 +33,8 @@
   virtual ~CefSSLInfoCToCpp();
 
   // CefSSLInfo methods.
-  cef_cert_status_t GetCertStatus() OVERRIDE;
-  CefRefPtr<CefX509Certificate> GetX509Certificate() OVERRIDE;
+  cef_cert_status_t GetCertStatus() override;
+  CefRefPtr<CefX509Certificate> GetX509Certificate() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_SSLINFO_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/sslstatus_ctocpp.cc b/src/libcef_dll/ctocpp/sslstatus_ctocpp.cc
index 0dcbaa8..67585a5 100644
--- a/src/libcef_dll/ctocpp/sslstatus_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/sslstatus_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=61b177e6dc50166afe90999fbc9771d4f69254c5$
+// $hash=82e87e32f0c6e2da2ae52a8f3af76e22790ee911$
 //
 
 #include "libcef_dll/ctocpp/sslstatus_ctocpp.h"
@@ -22,8 +22,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_sslstatus_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_secure_connection))
+  if (CEF_MEMBER_MISSING(_struct, is_secure_connection)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -38,8 +39,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_sslstatus_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_cert_status))
+  if (CEF_MEMBER_MISSING(_struct, get_cert_status)) {
     return CERT_STATUS_NONE;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -54,8 +56,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_sslstatus_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_sslversion))
+  if (CEF_MEMBER_MISSING(_struct, get_sslversion)) {
     return SSL_CONNECTION_VERSION_UNKNOWN;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -71,8 +74,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_sslstatus_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_content_status))
+  if (CEF_MEMBER_MISSING(_struct, get_content_status)) {
     return SSL_CONTENT_NORMAL_CONTENT;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -88,8 +92,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_sslstatus_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_x509certificate))
+  if (CEF_MEMBER_MISSING(_struct, get_x509certificate)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -114,7 +119,7 @@
 cef_sslstatus_t*
 CefCToCppRefCounted<CefSSLStatusCToCpp, CefSSLStatus, cef_sslstatus_t>::
     UnwrapDerived(CefWrapperType type, CefSSLStatus* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/sslstatus_ctocpp.h b/src/libcef_dll/ctocpp/sslstatus_ctocpp.h
index 258f34d..c36c525 100644
--- a/src/libcef_dll/ctocpp/sslstatus_ctocpp.h
+++ b/src/libcef_dll/ctocpp/sslstatus_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4021a70f4b22fa6af86310906d9d14ccc1cec9da$
+// $hash=af612f99d0ccc287b152a20b3e9956af223f82e0$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_SSLSTATUS_CTOCPP_H_
@@ -34,11 +34,11 @@
   virtual ~CefSSLStatusCToCpp();
 
   // CefSSLStatus methods.
-  bool IsSecureConnection() OVERRIDE;
-  cef_cert_status_t GetCertStatus() OVERRIDE;
-  cef_ssl_version_t GetSSLVersion() OVERRIDE;
-  cef_ssl_content_status_t GetContentStatus() OVERRIDE;
-  CefRefPtr<CefX509Certificate> GetX509Certificate() OVERRIDE;
+  bool IsSecureConnection() override;
+  cef_cert_status_t GetCertStatus() override;
+  cef_ssl_version_t GetSSLVersion() override;
+  cef_ssl_content_status_t GetContentStatus() override;
+  CefRefPtr<CefX509Certificate> GetX509Certificate() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_SSLSTATUS_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/stream_reader_ctocpp.cc b/src/libcef_dll/ctocpp/stream_reader_ctocpp.cc
index e92e1bb..1c758cf 100644
--- a/src/libcef_dll/ctocpp/stream_reader_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/stream_reader_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=82b24259bb9ee73f15743e8b9970f5eeb7e47e7e$
+// $hash=c96da6d6c400b9d7ed7f60d94502fe933b63aba1$
 //
 
 #include "libcef_dll/ctocpp/stream_reader_ctocpp.h"
@@ -27,8 +27,9 @@
 
   // Verify param: fileName; type: string_byref_const
   DCHECK(!fileName.empty());
-  if (fileName.empty())
+  if (fileName.empty()) {
     return nullptr;
+  }
 
   // Execute
   cef_stream_reader_t* _retval =
@@ -47,8 +48,9 @@
 
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return nullptr;
+  }
 
   // Execute
   cef_stream_reader_t* _retval = cef_stream_reader_create_for_data(data, size);
@@ -66,8 +68,9 @@
 
   // Verify param: handler; type: refptr_diff
   DCHECK(handler.get());
-  if (!handler.get())
+  if (!handler.get()) {
     return nullptr;
+  }
 
   // Execute
   cef_stream_reader_t* _retval =
@@ -84,15 +87,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_stream_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, read))
+  if (CEF_MEMBER_MISSING(_struct, read)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: ptr; type: simple_byaddr
   DCHECK(ptr);
-  if (!ptr)
+  if (!ptr) {
     return 0;
+  }
 
   // Execute
   size_t _retval = _struct->read(_struct, ptr, size, n);
@@ -102,12 +107,13 @@
 }
 
 NO_SANITIZE("cfi-icall")
-int CefStreamReaderCToCpp::Seek(int64 offset, int whence) {
+int CefStreamReaderCToCpp::Seek(int64_t offset, int whence) {
   shutdown_checker::AssertNotShutdown();
 
   cef_stream_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, seek))
+  if (CEF_MEMBER_MISSING(_struct, seek)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -118,17 +124,18 @@
   return _retval;
 }
 
-NO_SANITIZE("cfi-icall") int64 CefStreamReaderCToCpp::Tell() {
+NO_SANITIZE("cfi-icall") int64_t CefStreamReaderCToCpp::Tell() {
   shutdown_checker::AssertNotShutdown();
 
   cef_stream_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, tell))
+  if (CEF_MEMBER_MISSING(_struct, tell)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int64 _retval = _struct->tell(_struct);
+  int64_t _retval = _struct->tell(_struct);
 
   // Return type: simple
   return _retval;
@@ -138,8 +145,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_stream_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, eof))
+  if (CEF_MEMBER_MISSING(_struct, eof)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -154,8 +162,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_stream_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, may_block))
+  if (CEF_MEMBER_MISSING(_struct, may_block)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -182,7 +191,7 @@
                     CefStreamReader,
                     cef_stream_reader_t>::UnwrapDerived(CefWrapperType type,
                                                         CefStreamReader* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/stream_reader_ctocpp.h b/src/libcef_dll/ctocpp/stream_reader_ctocpp.h
index 9bf9123..b96992d 100644
--- a/src/libcef_dll/ctocpp/stream_reader_ctocpp.h
+++ b/src/libcef_dll/ctocpp/stream_reader_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=fda3483ae3ca295184f60189c0c47c1e88994700$
+// $hash=f9d6d1b80e4e2d30bddc9eb6e473c1f530186654$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_STREAM_READER_CTOCPP_H_
@@ -34,11 +34,11 @@
   virtual ~CefStreamReaderCToCpp();
 
   // CefStreamReader methods.
-  size_t Read(void* ptr, size_t size, size_t n) OVERRIDE;
-  int Seek(int64 offset, int whence) OVERRIDE;
-  int64 Tell() OVERRIDE;
-  int Eof() OVERRIDE;
-  bool MayBlock() OVERRIDE;
+  size_t Read(void* ptr, size_t size, size_t n) override;
+  int Seek(int64_t offset, int whence) override;
+  int64_t Tell() override;
+  int Eof() override;
+  bool MayBlock() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_STREAM_READER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/stream_writer_ctocpp.cc b/src/libcef_dll/ctocpp/stream_writer_ctocpp.cc
index b664a56..b2f3391 100644
--- a/src/libcef_dll/ctocpp/stream_writer_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/stream_writer_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1db7fdb06286f5c56a73b837e1f2bc30ae5ae536$
+// $hash=dcffd9ca0bb9504371e7c207e6e9768f9f4c31ae$
 //
 
 #include "libcef_dll/ctocpp/stream_writer_ctocpp.h"
@@ -27,8 +27,9 @@
 
   // Verify param: fileName; type: string_byref_const
   DCHECK(!fileName.empty());
-  if (fileName.empty())
+  if (fileName.empty()) {
     return nullptr;
+  }
 
   // Execute
   cef_stream_writer_t* _retval =
@@ -47,8 +48,9 @@
 
   // Verify param: handler; type: refptr_diff
   DCHECK(handler.get());
-  if (!handler.get())
+  if (!handler.get()) {
     return nullptr;
+  }
 
   // Execute
   cef_stream_writer_t* _retval = cef_stream_writer_create_for_handler(
@@ -65,15 +67,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_stream_writer_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, write))
+  if (CEF_MEMBER_MISSING(_struct, write)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: ptr; type: simple_byaddr
   DCHECK(ptr);
-  if (!ptr)
+  if (!ptr) {
     return 0;
+  }
 
   // Execute
   size_t _retval = _struct->write(_struct, ptr, size, n);
@@ -83,12 +87,13 @@
 }
 
 NO_SANITIZE("cfi-icall")
-int CefStreamWriterCToCpp::Seek(int64 offset, int whence) {
+int CefStreamWriterCToCpp::Seek(int64_t offset, int whence) {
   shutdown_checker::AssertNotShutdown();
 
   cef_stream_writer_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, seek))
+  if (CEF_MEMBER_MISSING(_struct, seek)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -99,17 +104,18 @@
   return _retval;
 }
 
-NO_SANITIZE("cfi-icall") int64 CefStreamWriterCToCpp::Tell() {
+NO_SANITIZE("cfi-icall") int64_t CefStreamWriterCToCpp::Tell() {
   shutdown_checker::AssertNotShutdown();
 
   cef_stream_writer_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, tell))
+  if (CEF_MEMBER_MISSING(_struct, tell)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int64 _retval = _struct->tell(_struct);
+  int64_t _retval = _struct->tell(_struct);
 
   // Return type: simple
   return _retval;
@@ -119,8 +125,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_stream_writer_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, flush))
+  if (CEF_MEMBER_MISSING(_struct, flush)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -135,8 +142,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_stream_writer_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, may_block))
+  if (CEF_MEMBER_MISSING(_struct, may_block)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -163,7 +171,7 @@
                     CefStreamWriter,
                     cef_stream_writer_t>::UnwrapDerived(CefWrapperType type,
                                                         CefStreamWriter* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/stream_writer_ctocpp.h b/src/libcef_dll/ctocpp/stream_writer_ctocpp.h
index 096a1b0..8bbf766 100644
--- a/src/libcef_dll/ctocpp/stream_writer_ctocpp.h
+++ b/src/libcef_dll/ctocpp/stream_writer_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=aaca7be8cdc8d2b3142e505dd38d1785de58b1cb$
+// $hash=e5131e9cf438a098db3ceec47c2a666f703b6d10$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_STREAM_WRITER_CTOCPP_H_
@@ -34,11 +34,11 @@
   virtual ~CefStreamWriterCToCpp();
 
   // CefStreamWriter methods.
-  size_t Write(const void* ptr, size_t size, size_t n) OVERRIDE;
-  int Seek(int64 offset, int whence) OVERRIDE;
-  int64 Tell() OVERRIDE;
-  int Flush() OVERRIDE;
-  bool MayBlock() OVERRIDE;
+  size_t Write(const void* ptr, size_t size, size_t n) override;
+  int Seek(int64_t offset, int whence) override;
+  int64_t Tell() override;
+  int Flush() override;
+  bool MayBlock() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_STREAM_WRITER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/string_visitor_ctocpp.cc b/src/libcef_dll/ctocpp/string_visitor_ctocpp.cc
index 243d413..34991d0 100644
--- a/src/libcef_dll/ctocpp/string_visitor_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/string_visitor_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b4199e85d500f9c22ce48472b0dc14eb581f8d84$
+// $hash=a2b53161507c06e907247b24022b7d5d62358fd9$
 //
 
 #include "libcef_dll/ctocpp/string_visitor_ctocpp.h"
@@ -22,8 +22,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_string_visitor_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, visit))
+  if (CEF_MEMBER_MISSING(_struct, visit)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -49,7 +50,7 @@
                     CefStringVisitor,
                     cef_string_visitor_t>::UnwrapDerived(CefWrapperType type,
                                                          CefStringVisitor* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/string_visitor_ctocpp.h b/src/libcef_dll/ctocpp/string_visitor_ctocpp.h
index 366c654..53e15ed 100644
--- a/src/libcef_dll/ctocpp/string_visitor_ctocpp.h
+++ b/src/libcef_dll/ctocpp/string_visitor_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=69a583ccea07a3e2b3bd5f61446a22b3fdcac125$
+// $hash=6e693b6dd1a72803aa7243d7cd5de54354338c37$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_STRING_VISITOR_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/task_ctocpp.cc b/src/libcef_dll/ctocpp/task_ctocpp.cc
index a5feb30..48050c5 100644
--- a/src/libcef_dll/ctocpp/task_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/task_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3a86994454947714f641ccc5c318b4afc9841cca$
+// $hash=2af462fcea47a649e9f17e4101c37f1f69bba508$
 //
 
 #include "libcef_dll/ctocpp/task_ctocpp.h"
@@ -18,8 +18,9 @@
 
 NO_SANITIZE("cfi-icall") void CefTaskCToCpp::Execute() {
   cef_task_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, execute))
+  if (CEF_MEMBER_MISSING(_struct, execute)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -40,7 +41,7 @@
 CefCToCppRefCounted<CefTaskCToCpp, CefTask, cef_task_t>::UnwrapDerived(
     CefWrapperType type,
     CefTask* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/task_ctocpp.h b/src/libcef_dll/ctocpp/task_ctocpp.h
index be99274..ccd90ed 100644
--- a/src/libcef_dll/ctocpp/task_ctocpp.h
+++ b/src/libcef_dll/ctocpp/task_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=70354f833d79fc211f5e9aaef273fbd638fe57f3$
+// $hash=e722a5b9ae2bb6e3d3236a199930600dc3b5e0f8$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_TASK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/task_runner_ctocpp.cc b/src/libcef_dll/ctocpp/task_runner_ctocpp.cc
index 4980169..adecc29 100644
--- a/src/libcef_dll/ctocpp/task_runner_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/task_runner_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3d4ea30711c0e3c716585f14b4122cdd57eba499$
+// $hash=f058d18f988de0b2bbc131907080bdef50fe6290$
 //
 
 #include "libcef_dll/ctocpp/task_runner_ctocpp.h"
@@ -51,15 +51,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_task_runner_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefTaskRunnerCToCpp::Unwrap(that));
@@ -72,8 +74,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_task_runner_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, belongs_to_current_thread))
+  if (CEF_MEMBER_MISSING(_struct, belongs_to_current_thread)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -89,8 +92,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_task_runner_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, belongs_to_thread))
+  if (CEF_MEMBER_MISSING(_struct, belongs_to_thread)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -106,15 +110,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_task_runner_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, post_task))
+  if (CEF_MEMBER_MISSING(_struct, post_task)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: task; type: refptr_diff
   DCHECK(task.get());
-  if (!task.get())
+  if (!task.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->post_task(_struct, CefTaskCppToC::Wrap(task));
@@ -125,19 +131,21 @@
 
 NO_SANITIZE("cfi-icall")
 bool CefTaskRunnerCToCpp::PostDelayedTask(CefRefPtr<CefTask> task,
-                                          int64 delay_ms) {
+                                          int64_t delay_ms) {
   shutdown_checker::AssertNotShutdown();
 
   cef_task_runner_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, post_delayed_task))
+  if (CEF_MEMBER_MISSING(_struct, post_delayed_task)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: task; type: refptr_diff
   DCHECK(task.get());
-  if (!task.get())
+  if (!task.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -161,7 +169,7 @@
 cef_task_runner_t*
 CefCToCppRefCounted<CefTaskRunnerCToCpp, CefTaskRunner, cef_task_runner_t>::
     UnwrapDerived(CefWrapperType type, CefTaskRunner* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/task_runner_ctocpp.h b/src/libcef_dll/ctocpp/task_runner_ctocpp.h
index baa257c..5e2d8d3 100644
--- a/src/libcef_dll/ctocpp/task_runner_ctocpp.h
+++ b/src/libcef_dll/ctocpp/task_runner_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=cfd8f2fd4562fa69006b6983bf495e48b19cc4f5$
+// $hash=614f17d01c97522a373ef4a4710202bbe6b76d11$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_TASK_RUNNER_CTOCPP_H_
@@ -34,11 +34,11 @@
   virtual ~CefTaskRunnerCToCpp();
 
   // CefTaskRunner methods.
-  bool IsSame(CefRefPtr<CefTaskRunner> that) OVERRIDE;
-  bool BelongsToCurrentThread() OVERRIDE;
-  bool BelongsToThread(CefThreadId threadId) OVERRIDE;
-  bool PostTask(CefRefPtr<CefTask> task) OVERRIDE;
-  bool PostDelayedTask(CefRefPtr<CefTask> task, int64 delay_ms) OVERRIDE;
+  bool IsSame(CefRefPtr<CefTaskRunner> that) override;
+  bool BelongsToCurrentThread() override;
+  bool BelongsToThread(CefThreadId threadId) override;
+  bool PostTask(CefRefPtr<CefTask> task) override;
+  bool PostDelayedTask(CefRefPtr<CefTask> task, int64_t delay_ms) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_TASK_RUNNER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/test/test_server_connection_ctocpp.cc b/src/libcef_dll/ctocpp/test/test_server_connection_ctocpp.cc
new file mode 100644
index 0000000..af3b160
--- /dev/null
+++ b/src/libcef_dll/ctocpp/test/test_server_connection_ctocpp.cc
@@ -0,0 +1,157 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=fe9776e1f16f92742ad5215b0f990223f8647c59$
+//
+
+#include "libcef_dll/ctocpp/test/test_server_connection_ctocpp.h"
+#include "libcef_dll/shutdown_checker.h"
+#include "libcef_dll/transfer_util.h"
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall")
+void CefTestServerConnectionCToCpp::SendHttp200Response(
+    const CefString& content_type,
+    const void* data,
+    size_t data_size) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_test_server_connection_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, send_http200response)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: content_type; type: string_byref_const
+  DCHECK(!content_type.empty());
+  if (content_type.empty()) {
+    return;
+  }
+  // Verify param: data; type: simple_byaddr
+  DCHECK(data);
+  if (!data) {
+    return;
+  }
+
+  // Execute
+  _struct->send_http200response(_struct, content_type.GetStruct(), data,
+                                data_size);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefTestServerConnectionCToCpp::SendHttp404Response() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_test_server_connection_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, send_http404response)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->send_http404response(_struct);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefTestServerConnectionCToCpp::SendHttp500Response(
+    const CefString& error_message) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_test_server_connection_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, send_http500response)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: error_message; type: string_byref_const
+  DCHECK(!error_message.empty());
+  if (error_message.empty()) {
+    return;
+  }
+
+  // Execute
+  _struct->send_http500response(_struct, error_message.GetStruct());
+}
+
+NO_SANITIZE("cfi-icall")
+void CefTestServerConnectionCToCpp::SendHttpResponse(
+    int response_code,
+    const CefString& content_type,
+    const void* data,
+    size_t data_size,
+    const HeaderMap& extra_headers) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_test_server_connection_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, send_http_response)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: content_type; type: string_byref_const
+  DCHECK(!content_type.empty());
+  if (content_type.empty()) {
+    return;
+  }
+  // Verify param: data; type: simple_byaddr
+  DCHECK(data);
+  if (!data) {
+    return;
+  }
+  // Unverified params: extra_headers
+
+  // Translate param: extra_headers; type: string_map_multi_byref_const
+  cef_string_multimap_t extra_headersMultimap = cef_string_multimap_alloc();
+  DCHECK(extra_headersMultimap);
+  if (extra_headersMultimap) {
+    transfer_string_multimap_contents(extra_headers, extra_headersMultimap);
+  }
+
+  // Execute
+  _struct->send_http_response(_struct, response_code, content_type.GetStruct(),
+                              data, data_size, extra_headersMultimap);
+
+  // Restore param:extra_headers; type: string_map_multi_byref_const
+  if (extra_headersMultimap) {
+    cef_string_multimap_free(extra_headersMultimap);
+  }
+}
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefTestServerConnectionCToCpp::CefTestServerConnectionCToCpp() {}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefTestServerConnectionCToCpp::~CefTestServerConnectionCToCpp() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+cef_test_server_connection_t* CefCToCppRefCounted<
+    CefTestServerConnectionCToCpp,
+    CefTestServerConnection,
+    cef_test_server_connection_t>::UnwrapDerived(CefWrapperType type,
+                                                 CefTestServerConnection* c) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCToCppRefCounted<CefTestServerConnectionCToCpp,
+                                   CefTestServerConnection,
+                                   cef_test_server_connection_t>::kWrapperType =
+    WT_TEST_SERVER_CONNECTION;
diff --git a/src/libcef_dll/ctocpp/test/test_server_connection_ctocpp.h b/src/libcef_dll/ctocpp/test/test_server_connection_ctocpp.h
new file mode 100644
index 0000000..0c2788d
--- /dev/null
+++ b/src/libcef_dll/ctocpp/test/test_server_connection_ctocpp.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=99b84d1e02eeeaa485722c9d685bfed90a8bd356$
+//
+
+#ifndef CEF_LIBCEF_DLL_CTOCPP_TEST_TEST_SERVER_CONNECTION_CTOCPP_H_
+#define CEF_LIBCEF_DLL_CTOCPP_TEST_TEST_SERVER_CONNECTION_CTOCPP_H_
+#pragma once
+
+#if !defined(WRAPPING_CEF_SHARED)
+#error This file can be included wrapper-side only
+#endif
+
+#include "include/capi/test/cef_test_server_capi.h"
+#include "include/test/cef_test_server.h"
+#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
+
+// Wrap a C structure with a C++ class.
+// This class may be instantiated and accessed wrapper-side only.
+class CefTestServerConnectionCToCpp
+    : public CefCToCppRefCounted<CefTestServerConnectionCToCpp,
+                                 CefTestServerConnection,
+                                 cef_test_server_connection_t> {
+ public:
+  CefTestServerConnectionCToCpp();
+  virtual ~CefTestServerConnectionCToCpp();
+
+  // CefTestServerConnection methods.
+  void SendHttp200Response(const CefString& content_type,
+                           const void* data,
+                           size_t data_size) override;
+  void SendHttp404Response() override;
+  void SendHttp500Response(const CefString& error_message) override;
+  void SendHttpResponse(int response_code,
+                        const CefString& content_type,
+                        const void* data,
+                        size_t data_size,
+                        const HeaderMap& extra_headers) override;
+};
+
+#endif  // CEF_LIBCEF_DLL_CTOCPP_TEST_TEST_SERVER_CONNECTION_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/test/test_server_ctocpp.cc b/src/libcef_dll/ctocpp/test/test_server_ctocpp.cc
new file mode 100644
index 0000000..062dd87
--- /dev/null
+++ b/src/libcef_dll/ctocpp/test/test_server_ctocpp.cc
@@ -0,0 +1,103 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=9d289e78e4406bbe55872a7132531c0b9673bc47$
+//
+
+#include "libcef_dll/ctocpp/test/test_server_ctocpp.h"
+#include "libcef_dll/cpptoc/test/test_server_handler_cpptoc.h"
+#include "libcef_dll/shutdown_checker.h"
+
+// STATIC METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall")
+CefRefPtr<CefTestServer> CefTestServer::CreateAndStart(
+    uint16_t port,
+    bool https_server,
+    cef_test_cert_type_t https_cert_type,
+    CefRefPtr<CefTestServerHandler> handler) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: handler; type: refptr_diff
+  DCHECK(handler.get());
+  if (!handler.get()) {
+    return nullptr;
+  }
+
+  // Execute
+  cef_test_server_t* _retval = cef_test_server_create_and_start(
+      port, https_server, https_cert_type,
+      CefTestServerHandlerCppToC::Wrap(handler));
+
+  // Return type: refptr_same
+  return CefTestServerCToCpp::Wrap(_retval);
+}
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall") void CefTestServerCToCpp::Stop() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_test_server_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, stop)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->stop(_struct);
+}
+
+NO_SANITIZE("cfi-icall") CefString CefTestServerCToCpp::GetOrigin() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_test_server_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_origin)) {
+    return CefString();
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_string_userfree_t _retval = _struct->get_origin(_struct);
+
+  // Return type: string
+  CefString _retvalStr;
+  _retvalStr.AttachToUserFree(_retval);
+  return _retvalStr;
+}
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefTestServerCToCpp::CefTestServerCToCpp() {}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefTestServerCToCpp::~CefTestServerCToCpp() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+cef_test_server_t*
+CefCToCppRefCounted<CefTestServerCToCpp, CefTestServer, cef_test_server_t>::
+    UnwrapDerived(CefWrapperType type, CefTestServer* c) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCToCppRefCounted<CefTestServerCToCpp,
+                                   CefTestServer,
+                                   cef_test_server_t>::kWrapperType =
+    WT_TEST_SERVER;
diff --git a/src/libcef_dll/ctocpp/test/test_server_ctocpp.h b/src/libcef_dll/ctocpp/test/test_server_ctocpp.h
new file mode 100644
index 0000000..1d95f6b
--- /dev/null
+++ b/src/libcef_dll/ctocpp/test/test_server_ctocpp.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=06d5fbd145898540f060616efbd6f81e1bee7498$
+//
+
+#ifndef CEF_LIBCEF_DLL_CTOCPP_TEST_TEST_SERVER_CTOCPP_H_
+#define CEF_LIBCEF_DLL_CTOCPP_TEST_TEST_SERVER_CTOCPP_H_
+#pragma once
+
+#if !defined(WRAPPING_CEF_SHARED)
+#error This file can be included wrapper-side only
+#endif
+
+#include "include/capi/test/cef_test_server_capi.h"
+#include "include/test/cef_test_server.h"
+#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
+
+// Wrap a C structure with a C++ class.
+// This class may be instantiated and accessed wrapper-side only.
+class CefTestServerCToCpp : public CefCToCppRefCounted<CefTestServerCToCpp,
+                                                       CefTestServer,
+                                                       cef_test_server_t> {
+ public:
+  CefTestServerCToCpp();
+  virtual ~CefTestServerCToCpp();
+
+  // CefTestServer methods.
+  void Stop() override;
+  CefString GetOrigin() override;
+};
+
+#endif  // CEF_LIBCEF_DLL_CTOCPP_TEST_TEST_SERVER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/test/test_server_handler_ctocpp.cc b/src/libcef_dll/ctocpp/test/test_server_handler_ctocpp.cc
new file mode 100644
index 0000000..f1f18ce
--- /dev/null
+++ b/src/libcef_dll/ctocpp/test/test_server_handler_ctocpp.cc
@@ -0,0 +1,87 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=43130e567ff34056d282a006b0023c5892b83afa$
+//
+
+#include "libcef_dll/ctocpp/test/test_server_handler_ctocpp.h"
+#include "libcef_dll/cpptoc/request_cpptoc.h"
+#include "libcef_dll/cpptoc/test/test_server_connection_cpptoc.h"
+#include "libcef_dll/cpptoc/test/test_server_cpptoc.h"
+#include "libcef_dll/shutdown_checker.h"
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall")
+bool CefTestServerHandlerCToCpp::OnTestServerRequest(
+    CefRefPtr<CefTestServer> server,
+    CefRefPtr<CefRequest> request,
+    CefRefPtr<CefTestServerConnection> connection) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_test_server_handler_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_test_server_request)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: server; type: refptr_diff
+  DCHECK(server.get());
+  if (!server.get()) {
+    return false;
+  }
+  // Verify param: request; type: refptr_diff
+  DCHECK(request.get());
+  if (!request.get()) {
+    return false;
+  }
+  // Verify param: connection; type: refptr_diff
+  DCHECK(connection.get());
+  if (!connection.get()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->on_test_server_request(
+      _struct, CefTestServerCppToC::Wrap(server),
+      CefRequestCppToC::Wrap(request),
+      CefTestServerConnectionCppToC::Wrap(connection));
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefTestServerHandlerCToCpp::CefTestServerHandlerCToCpp() {}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefTestServerHandlerCToCpp::~CefTestServerHandlerCToCpp() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+cef_test_server_handler_t* CefCToCppRefCounted<
+    CefTestServerHandlerCToCpp,
+    CefTestServerHandler,
+    cef_test_server_handler_t>::UnwrapDerived(CefWrapperType type,
+                                              CefTestServerHandler* c) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCToCppRefCounted<CefTestServerHandlerCToCpp,
+                                   CefTestServerHandler,
+                                   cef_test_server_handler_t>::kWrapperType =
+    WT_TEST_SERVER_HANDLER;
diff --git a/src/libcef_dll/ctocpp/test/test_server_handler_ctocpp.h b/src/libcef_dll/ctocpp/test/test_server_handler_ctocpp.h
new file mode 100644
index 0000000..b390bf7
--- /dev/null
+++ b/src/libcef_dll/ctocpp/test/test_server_handler_ctocpp.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=c0a7d6e6596314771567fafa185ac777bdc61a65$
+//
+
+#ifndef CEF_LIBCEF_DLL_CTOCPP_TEST_TEST_SERVER_HANDLER_CTOCPP_H_
+#define CEF_LIBCEF_DLL_CTOCPP_TEST_TEST_SERVER_HANDLER_CTOCPP_H_
+#pragma once
+
+#if !defined(BUILDING_CEF_SHARED)
+#error This file can be included DLL-side only
+#endif
+
+#include "include/capi/test/cef_test_server_capi.h"
+#include "include/test/cef_test_server.h"
+#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
+
+// Wrap a C structure with a C++ class.
+// This class may be instantiated and accessed DLL-side only.
+class CefTestServerHandlerCToCpp
+    : public CefCToCppRefCounted<CefTestServerHandlerCToCpp,
+                                 CefTestServerHandler,
+                                 cef_test_server_handler_t> {
+ public:
+  CefTestServerHandlerCToCpp();
+  virtual ~CefTestServerHandlerCToCpp();
+
+  // CefTestServerHandler methods.
+  bool OnTestServerRequest(
+      CefRefPtr<CefTestServer> server,
+      CefRefPtr<CefRequest> request,
+      CefRefPtr<CefTestServerConnection> connection) override;
+};
+
+#endif  // CEF_LIBCEF_DLL_CTOCPP_TEST_TEST_SERVER_HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/test/translator_test_ctocpp.cc b/src/libcef_dll/ctocpp/test/translator_test_ctocpp.cc
index 3638913..26b00db 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/test/translator_test_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4ccc62b0449038044535576aed814a925db93432$
+// $hash=e45ac9d949f5bc30b13e69cf655120250e0ccdc4$
 //
 
 #include "libcef_dll/ctocpp/test/translator_test_ctocpp.h"
@@ -46,8 +46,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_void))
+  if (CEF_MEMBER_MISSING(_struct, get_void)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -59,8 +60,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_bool))
+  if (CEF_MEMBER_MISSING(_struct, get_bool)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -75,8 +77,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_int))
+  if (CEF_MEMBER_MISSING(_struct, get_int)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -91,8 +94,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_double))
+  if (CEF_MEMBER_MISSING(_struct, get_double)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -107,8 +111,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_long))
+  if (CEF_MEMBER_MISSING(_struct, get_long)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -123,8 +128,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_sizet))
+  if (CEF_MEMBER_MISSING(_struct, get_sizet)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -139,8 +145,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_void))
+  if (CEF_MEMBER_MISSING(_struct, set_void)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -155,8 +162,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_bool))
+  if (CEF_MEMBER_MISSING(_struct, set_bool)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -171,8 +179,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_int))
+  if (CEF_MEMBER_MISSING(_struct, set_int)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -187,8 +196,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_double))
+  if (CEF_MEMBER_MISSING(_struct, set_double)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -203,8 +213,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_long))
+  if (CEF_MEMBER_MISSING(_struct, set_long)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -219,8 +230,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_sizet))
+  if (CEF_MEMBER_MISSING(_struct, set_sizet)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -236,8 +248,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_int_list))
+  if (CEF_MEMBER_MISSING(_struct, set_int_list)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -258,8 +271,9 @@
   int _retval = _struct->set_int_list(_struct, valCount, valList);
 
   // Restore param:val; type: simple_vec_byref_const
-  if (valList)
+  if (valList) {
     delete[] valList;
+  }
 
   // Return type: bool
   return _retval ? true : false;
@@ -270,8 +284,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_int_list_by_ref))
+  if (CEF_MEMBER_MISSING(_struct, get_int_list_by_ref)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -312,8 +327,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_int_list_size))
+  if (CEF_MEMBER_MISSING(_struct, get_int_list_size)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -328,8 +344,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_string))
+  if (CEF_MEMBER_MISSING(_struct, get_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -347,15 +364,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_string))
+  if (CEF_MEMBER_MISSING(_struct, set_string)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: string_byref_const
   DCHECK(!val.empty());
-  if (val.empty())
+  if (val.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_string(_struct, val.GetStruct());
@@ -369,8 +388,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_string_by_ref))
+  if (CEF_MEMBER_MISSING(_struct, get_string_by_ref)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -383,23 +403,26 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_string_list))
+  if (CEF_MEMBER_MISSING(_struct, set_string_list)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: val; type: string_vec_byref_const
   cef_string_list_t valList = cef_string_list_alloc();
   DCHECK(valList);
-  if (valList)
+  if (valList) {
     transfer_string_list_contents(val, valList);
+  }
 
   // Execute
   int _retval = _struct->set_string_list(_struct, valList);
 
   // Restore param:val; type: string_vec_byref_const
-  if (valList)
+  if (valList) {
     cef_string_list_free(valList);
+  }
 
   // Return type: bool
   return _retval ? true : false;
@@ -410,16 +433,18 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_string_list_by_ref))
+  if (CEF_MEMBER_MISSING(_struct, get_string_list_by_ref)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: val; type: string_vec_byref
   cef_string_list_t valList = cef_string_list_alloc();
   DCHECK(valList);
-  if (valList)
+  if (valList) {
     transfer_string_list_contents(val, valList);
+  }
 
   // Execute
   int _retval = _struct->get_string_list_by_ref(_struct, valList);
@@ -440,23 +465,26 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_string_map))
+  if (CEF_MEMBER_MISSING(_struct, set_string_map)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: val; type: string_map_single_byref_const
   cef_string_map_t valMap = cef_string_map_alloc();
   DCHECK(valMap);
-  if (valMap)
+  if (valMap) {
     transfer_string_map_contents(val, valMap);
+  }
 
   // Execute
   int _retval = _struct->set_string_map(_struct, valMap);
 
   // Restore param:val; type: string_map_single_byref_const
-  if (valMap)
+  if (valMap) {
     cef_string_map_free(valMap);
+  }
 
   // Return type: bool
   return _retval ? true : false;
@@ -468,16 +496,18 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_string_map_by_ref))
+  if (CEF_MEMBER_MISSING(_struct, get_string_map_by_ref)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: val; type: string_map_single_byref
   cef_string_map_t valMap = cef_string_map_alloc();
   DCHECK(valMap);
-  if (valMap)
+  if (valMap) {
     transfer_string_map_contents(val, valMap);
+  }
 
   // Execute
   int _retval = _struct->get_string_map_by_ref(_struct, valMap);
@@ -499,23 +529,26 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_string_multimap))
+  if (CEF_MEMBER_MISSING(_struct, set_string_multimap)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: val; type: string_map_multi_byref_const
   cef_string_multimap_t valMultimap = cef_string_multimap_alloc();
   DCHECK(valMultimap);
-  if (valMultimap)
+  if (valMultimap) {
     transfer_string_multimap_contents(val, valMultimap);
+  }
 
   // Execute
   int _retval = _struct->set_string_multimap(_struct, valMultimap);
 
   // Restore param:val; type: string_map_multi_byref_const
-  if (valMultimap)
+  if (valMultimap) {
     cef_string_multimap_free(valMultimap);
+  }
 
   // Return type: bool
   return _retval ? true : false;
@@ -526,16 +559,18 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_string_multimap_by_ref))
+  if (CEF_MEMBER_MISSING(_struct, get_string_multimap_by_ref)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: val; type: string_map_multi_byref
   cef_string_multimap_t valMultimap = cef_string_multimap_alloc();
   DCHECK(valMultimap);
-  if (valMultimap)
+  if (valMultimap) {
     transfer_string_multimap_contents(val, valMultimap);
+  }
 
   // Execute
   int _retval = _struct->get_string_multimap_by_ref(_struct, valMultimap);
@@ -555,8 +590,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_point))
+  if (CEF_MEMBER_MISSING(_struct, get_point)) {
     return CefPoint();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -572,8 +608,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_point))
+  if (CEF_MEMBER_MISSING(_struct, set_point)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -589,8 +626,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_point_by_ref))
+  if (CEF_MEMBER_MISSING(_struct, get_point_by_ref)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -603,8 +641,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_point_list))
+  if (CEF_MEMBER_MISSING(_struct, set_point_list)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -625,8 +664,9 @@
   int _retval = _struct->set_point_list(_struct, valCount, valList);
 
   // Restore param:val; type: simple_vec_byref_const
-  if (valList)
+  if (valList) {
     delete[] valList;
+  }
 
   // Return type: bool
   return _retval ? true : false;
@@ -637,8 +677,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_point_list_by_ref))
+  if (CEF_MEMBER_MISSING(_struct, get_point_list_by_ref)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -679,8 +720,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_point_list_size))
+  if (CEF_MEMBER_MISSING(_struct, get_point_list_size)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -697,8 +739,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_ref_ptr_library))
+  if (CEF_MEMBER_MISSING(_struct, get_ref_ptr_library)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -716,15 +759,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_ref_ptr_library))
+  if (CEF_MEMBER_MISSING(_struct, set_ref_ptr_library)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: refptr_same
   DCHECK(val.get());
-  if (!val.get())
+  if (!val.get()) {
     return 0;
+  }
 
   // Execute
   int _retval = _struct->set_ref_ptr_library(
@@ -741,15 +786,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_ref_ptr_library_and_return))
+  if (CEF_MEMBER_MISSING(_struct, set_ref_ptr_library_and_return)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: refptr_same
   DCHECK(val.get());
-  if (!val.get())
+  if (!val.get()) {
     return nullptr;
+  }
 
   // Execute
   cef_translator_test_ref_ptr_library_t* _retval =
@@ -766,15 +813,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_child_ref_ptr_library))
+  if (CEF_MEMBER_MISSING(_struct, set_child_ref_ptr_library)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: refptr_same
   DCHECK(val.get());
-  if (!val.get())
+  if (!val.get()) {
     return 0;
+  }
 
   // Execute
   int _retval = _struct->set_child_ref_ptr_library(
@@ -791,15 +840,18 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_child_ref_ptr_library_and_return_parent))
+  if (CEF_MEMBER_MISSING(_struct,
+                         set_child_ref_ptr_library_and_return_parent)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: refptr_same
   DCHECK(val.get());
-  if (!val.get())
+  if (!val.get()) {
     return nullptr;
+  }
 
   // Execute
   cef_translator_test_ref_ptr_library_t* _retval =
@@ -818,8 +870,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_ref_ptr_library_list))
+  if (CEF_MEMBER_MISSING(_struct, set_ref_ptr_library_list)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -841,8 +894,9 @@
       _struct->set_ref_ptr_library_list(_struct, valCount, valList, val1, val2);
 
   // Restore param:val; type: refptr_vec_same_byref_const
-  if (valList)
+  if (valList) {
     delete[] valList;
+  }
 
   // Return type: bool
   return _retval ? true : false;
@@ -855,8 +909,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_ref_ptr_library_list_by_ref))
+  if (CEF_MEMBER_MISSING(_struct, get_ref_ptr_library_list_by_ref)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -900,8 +955,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_ref_ptr_library_list_size))
+  if (CEF_MEMBER_MISSING(_struct, get_ref_ptr_library_list_size)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -918,15 +974,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_ref_ptr_client))
+  if (CEF_MEMBER_MISSING(_struct, set_ref_ptr_client)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: refptr_diff
   DCHECK(val.get());
-  if (!val.get())
+  if (!val.get()) {
     return 0;
+  }
 
   // Execute
   int _retval = _struct->set_ref_ptr_client(
@@ -943,15 +1001,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_ref_ptr_client_and_return))
+  if (CEF_MEMBER_MISSING(_struct, set_ref_ptr_client_and_return)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: refptr_diff
   DCHECK(val.get());
-  if (!val.get())
+  if (!val.get()) {
     return nullptr;
+  }
 
   // Execute
   cef_translator_test_ref_ptr_client_t* _retval =
@@ -968,15 +1028,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_child_ref_ptr_client))
+  if (CEF_MEMBER_MISSING(_struct, set_child_ref_ptr_client)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: refptr_diff
   DCHECK(val.get());
-  if (!val.get())
+  if (!val.get()) {
     return 0;
+  }
 
   // Execute
   int _retval = _struct->set_child_ref_ptr_client(
@@ -993,15 +1055,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_child_ref_ptr_client_and_return_parent))
+  if (CEF_MEMBER_MISSING(_struct, set_child_ref_ptr_client_and_return_parent)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: refptr_diff
   DCHECK(val.get());
-  if (!val.get())
+  if (!val.get()) {
     return nullptr;
+  }
 
   // Execute
   cef_translator_test_ref_ptr_client_t* _retval =
@@ -1020,8 +1084,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_ref_ptr_client_list))
+  if (CEF_MEMBER_MISSING(_struct, set_ref_ptr_client_list)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1043,8 +1108,9 @@
       _struct->set_ref_ptr_client_list(_struct, valCount, valList, val1, val2);
 
   // Restore param:val; type: refptr_vec_diff_byref_const
-  if (valList)
+  if (valList) {
     delete[] valList;
+  }
 
   // Return type: bool
   return _retval ? true : false;
@@ -1058,19 +1124,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_ref_ptr_client_list_by_ref))
+  if (CEF_MEMBER_MISSING(_struct, get_ref_ptr_client_list_by_ref)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val1; type: refptr_diff
   DCHECK(val1.get());
-  if (!val1.get())
+  if (!val1.get()) {
     return false;
+  }
   // Verify param: val2; type: refptr_diff
   DCHECK(val2.get());
-  if (!val2.get())
+  if (!val2.get()) {
     return false;
+  }
 
   // Translate param: val; type: refptr_vec_diff_byref
   size_t valSize = val.size();
@@ -1114,8 +1183,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_ref_ptr_client_list_size))
+  if (CEF_MEMBER_MISSING(_struct, get_ref_ptr_client_list_size)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1132,8 +1202,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_own_ptr_library))
+  if (CEF_MEMBER_MISSING(_struct, get_own_ptr_library)) {
     return CefOwnPtr<CefTranslatorTestScopedLibrary>();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1151,19 +1222,21 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_own_ptr_library))
+  if (CEF_MEMBER_MISSING(_struct, set_own_ptr_library)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: ownptr_same
   DCHECK(val.get());
-  if (!val.get())
+  if (!val.get()) {
     return 0;
+  }
 
   // Execute
   int _retval = _struct->set_own_ptr_library(
-      _struct, CefTranslatorTestScopedLibraryCToCpp::UnwrapOwn(OWN_PASS(val)));
+      _struct, CefTranslatorTestScopedLibraryCToCpp::UnwrapOwn(std::move(val)));
 
   // Return type: simple
   return _retval;
@@ -1176,21 +1249,23 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_own_ptr_library_and_return))
+  if (CEF_MEMBER_MISSING(_struct, set_own_ptr_library_and_return)) {
     return CefOwnPtr<CefTranslatorTestScopedLibrary>();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: ownptr_same
   DCHECK(val.get());
-  if (!val.get())
+  if (!val.get()) {
     return CefOwnPtr<CefTranslatorTestScopedLibrary>();
+  }
 
   // Execute
   cef_translator_test_scoped_library_t* _retval =
       _struct->set_own_ptr_library_and_return(
           _struct,
-          CefTranslatorTestScopedLibraryCToCpp::UnwrapOwn(OWN_PASS(val)));
+          CefTranslatorTestScopedLibraryCToCpp::UnwrapOwn(std::move(val)));
 
   // Return type: ownptr_same
   return CefTranslatorTestScopedLibraryCToCpp::Wrap(_retval);
@@ -1202,20 +1277,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_child_own_ptr_library))
+  if (CEF_MEMBER_MISSING(_struct, set_child_own_ptr_library)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: ownptr_same
   DCHECK(val.get());
-  if (!val.get())
+  if (!val.get()) {
     return 0;
+  }
 
   // Execute
   int _retval = _struct->set_child_own_ptr_library(
       _struct,
-      CefTranslatorTestScopedLibraryChildCToCpp::UnwrapOwn(OWN_PASS(val)));
+      CefTranslatorTestScopedLibraryChildCToCpp::UnwrapOwn(std::move(val)));
 
   // Return type: simple
   return _retval;
@@ -1228,21 +1305,24 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_child_own_ptr_library_and_return_parent))
+  if (CEF_MEMBER_MISSING(_struct,
+                         set_child_own_ptr_library_and_return_parent)) {
     return CefOwnPtr<CefTranslatorTestScopedLibrary>();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: ownptr_same
   DCHECK(val.get());
-  if (!val.get())
+  if (!val.get()) {
     return CefOwnPtr<CefTranslatorTestScopedLibrary>();
+  }
 
   // Execute
   cef_translator_test_scoped_library_t* _retval =
       _struct->set_child_own_ptr_library_and_return_parent(
           _struct,
-          CefTranslatorTestScopedLibraryChildCToCpp::UnwrapOwn(OWN_PASS(val)));
+          CefTranslatorTestScopedLibraryChildCToCpp::UnwrapOwn(std::move(val)));
 
   // Return type: ownptr_same
   return CefTranslatorTestScopedLibraryCToCpp::Wrap(_retval);
@@ -1254,19 +1334,21 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_own_ptr_client))
+  if (CEF_MEMBER_MISSING(_struct, set_own_ptr_client)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: ownptr_diff
   DCHECK(val.get());
-  if (!val.get())
+  if (!val.get()) {
     return 0;
+  }
 
   // Execute
   int _retval = _struct->set_own_ptr_client(
-      _struct, CefTranslatorTestScopedClientCppToC::WrapOwn(OWN_PASS(val)));
+      _struct, CefTranslatorTestScopedClientCppToC::WrapOwn(std::move(val)));
 
   // Return type: simple
   return _retval;
@@ -1279,20 +1361,23 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_own_ptr_client_and_return))
+  if (CEF_MEMBER_MISSING(_struct, set_own_ptr_client_and_return)) {
     return CefOwnPtr<CefTranslatorTestScopedClient>();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: ownptr_diff
   DCHECK(val.get());
-  if (!val.get())
+  if (!val.get()) {
     return CefOwnPtr<CefTranslatorTestScopedClient>();
+  }
 
   // Execute
   cef_translator_test_scoped_client_t* _retval =
       _struct->set_own_ptr_client_and_return(
-          _struct, CefTranslatorTestScopedClientCppToC::WrapOwn(OWN_PASS(val)));
+          _struct,
+          CefTranslatorTestScopedClientCppToC::WrapOwn(std::move(val)));
 
   // Return type: ownptr_diff
   return CefTranslatorTestScopedClientCppToC::UnwrapOwn(_retval);
@@ -1304,20 +1389,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_child_own_ptr_client))
+  if (CEF_MEMBER_MISSING(_struct, set_child_own_ptr_client)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: ownptr_diff
   DCHECK(val.get());
-  if (!val.get())
+  if (!val.get()) {
     return 0;
+  }
 
   // Execute
   int _retval = _struct->set_child_own_ptr_client(
       _struct,
-      CefTranslatorTestScopedClientChildCppToC::WrapOwn(OWN_PASS(val)));
+      CefTranslatorTestScopedClientChildCppToC::WrapOwn(std::move(val)));
 
   // Return type: simple
   return _retval;
@@ -1330,21 +1417,23 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_child_own_ptr_client_and_return_parent))
+  if (CEF_MEMBER_MISSING(_struct, set_child_own_ptr_client_and_return_parent)) {
     return CefOwnPtr<CefTranslatorTestScopedClient>();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: ownptr_diff
   DCHECK(val.get());
-  if (!val.get())
+  if (!val.get()) {
     return CefOwnPtr<CefTranslatorTestScopedClient>();
+  }
 
   // Execute
   cef_translator_test_scoped_client_t* _retval =
       _struct->set_child_own_ptr_client_and_return_parent(
           _struct,
-          CefTranslatorTestScopedClientChildCppToC::WrapOwn(OWN_PASS(val)));
+          CefTranslatorTestScopedClientChildCppToC::WrapOwn(std::move(val)));
 
   // Return type: ownptr_diff
   return CefTranslatorTestScopedClientCppToC::UnwrapOwn(_retval);
@@ -1356,15 +1445,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_raw_ptr_library))
+  if (CEF_MEMBER_MISSING(_struct, set_raw_ptr_library)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: rawptr_same
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Execute
   int _retval = _struct->set_raw_ptr_library(
@@ -1380,15 +1471,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_child_raw_ptr_library))
+  if (CEF_MEMBER_MISSING(_struct, set_child_raw_ptr_library)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: rawptr_same
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Execute
   int _retval = _struct->set_child_raw_ptr_library(
@@ -1406,8 +1499,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_raw_ptr_library_list))
+  if (CEF_MEMBER_MISSING(_struct, set_raw_ptr_library_list)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1429,8 +1523,9 @@
       _struct->set_raw_ptr_library_list(_struct, valCount, valList, val1, val2);
 
   // Restore param:val; type: rawptr_vec_same_byref_const
-  if (valList)
+  if (valList) {
     delete[] valList;
+  }
 
   // Return type: bool
   return _retval ? true : false;
@@ -1442,15 +1537,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_raw_ptr_client))
+  if (CEF_MEMBER_MISSING(_struct, set_raw_ptr_client)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: rawptr_diff
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Translate param: val; type: rawptr_diff
   CefOwnPtr<CefTranslatorTestScopedClientCppToC> valPtr(
@@ -1469,15 +1566,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_child_raw_ptr_client))
+  if (CEF_MEMBER_MISSING(_struct, set_child_raw_ptr_client)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: val; type: rawptr_diff
   DCHECK(val);
-  if (!val)
+  if (!val) {
     return 0;
+  }
 
   // Translate param: val; type: rawptr_diff
   CefOwnPtr<CefTranslatorTestScopedClientChildCppToC> valPtr(
@@ -1498,8 +1597,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_raw_ptr_client_list))
+  if (CEF_MEMBER_MISSING(_struct, set_raw_ptr_client_list)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1528,8 +1628,9 @@
       delete CefTranslatorTestScopedClientCppToC::GetWrapper(valList[i]);
     }
   }
-  if (valList)
+  if (valList) {
     delete[] valList;
+  }
 
   // Return type: bool
   return _retval ? true : false;
@@ -1551,7 +1652,7 @@
     CefTranslatorTest,
     cef_translator_test_t>::UnwrapDerived(CefWrapperType type,
                                           CefTranslatorTest* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/test/translator_test_ctocpp.h b/src/libcef_dll/ctocpp/test/translator_test_ctocpp.h
index 93db13b..8384cef 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_ctocpp.h
+++ b/src/libcef_dll/ctocpp/test/translator_test_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e7302b507c09d89d0b5735136ed6e47867e56a00$
+// $hash=915917340262b6243b06022fe96cc1e96625cac9$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_CTOCPP_H_
@@ -37,100 +37,100 @@
   virtual ~CefTranslatorTestCToCpp();
 
   // CefTranslatorTest methods.
-  void GetVoid() OVERRIDE;
-  bool GetBool() OVERRIDE;
-  int GetInt() OVERRIDE;
-  double GetDouble() OVERRIDE;
-  long GetLong() OVERRIDE;
-  size_t GetSizet() OVERRIDE;
-  bool SetVoid() OVERRIDE;
-  bool SetBool(bool val) OVERRIDE;
-  bool SetInt(int val) OVERRIDE;
-  bool SetDouble(double val) OVERRIDE;
-  bool SetLong(long val) OVERRIDE;
-  bool SetSizet(size_t val) OVERRIDE;
-  bool SetIntList(const std::vector<int>& val) OVERRIDE;
-  bool GetIntListByRef(IntList& val) OVERRIDE;
-  size_t GetIntListSize() OVERRIDE;
-  CefString GetString() OVERRIDE;
-  bool SetString(const CefString& val) OVERRIDE;
-  void GetStringByRef(CefString& val) OVERRIDE;
-  bool SetStringList(const std::vector<CefString>& val) OVERRIDE;
-  bool GetStringListByRef(StringList& val) OVERRIDE;
-  bool SetStringMap(const StringMap& val) OVERRIDE;
-  bool GetStringMapByRef(std::map<CefString, CefString>& val) OVERRIDE;
+  void GetVoid() override;
+  bool GetBool() override;
+  int GetInt() override;
+  double GetDouble() override;
+  long GetLong() override;
+  size_t GetSizet() override;
+  bool SetVoid() override;
+  bool SetBool(bool val) override;
+  bool SetInt(int val) override;
+  bool SetDouble(double val) override;
+  bool SetLong(long val) override;
+  bool SetSizet(size_t val) override;
+  bool SetIntList(const std::vector<int>& val) override;
+  bool GetIntListByRef(IntList& val) override;
+  size_t GetIntListSize() override;
+  CefString GetString() override;
+  bool SetString(const CefString& val) override;
+  void GetStringByRef(CefString& val) override;
+  bool SetStringList(const std::vector<CefString>& val) override;
+  bool GetStringListByRef(StringList& val) override;
+  bool SetStringMap(const StringMap& val) override;
+  bool GetStringMapByRef(std::map<CefString, CefString>& val) override;
   bool SetStringMultimap(
-      const std::multimap<CefString, CefString>& val) OVERRIDE;
-  bool GetStringMultimapByRef(StringMultimap& val) OVERRIDE;
-  CefPoint GetPoint() OVERRIDE;
-  bool SetPoint(const CefPoint& val) OVERRIDE;
-  void GetPointByRef(CefPoint& val) OVERRIDE;
-  bool SetPointList(const std::vector<CefPoint>& val) OVERRIDE;
-  bool GetPointListByRef(PointList& val) OVERRIDE;
-  size_t GetPointListSize() OVERRIDE;
-  CefRefPtr<CefTranslatorTestRefPtrLibrary> GetRefPtrLibrary(int val) OVERRIDE;
-  int SetRefPtrLibrary(CefRefPtr<CefTranslatorTestRefPtrLibrary> val) OVERRIDE;
+      const std::multimap<CefString, CefString>& val) override;
+  bool GetStringMultimapByRef(StringMultimap& val) override;
+  CefPoint GetPoint() override;
+  bool SetPoint(const CefPoint& val) override;
+  void GetPointByRef(CefPoint& val) override;
+  bool SetPointList(const std::vector<CefPoint>& val) override;
+  bool GetPointListByRef(PointList& val) override;
+  size_t GetPointListSize() override;
+  CefRefPtr<CefTranslatorTestRefPtrLibrary> GetRefPtrLibrary(int val) override;
+  int SetRefPtrLibrary(CefRefPtr<CefTranslatorTestRefPtrLibrary> val) override;
   CefRefPtr<CefTranslatorTestRefPtrLibrary> SetRefPtrLibraryAndReturn(
-      CefRefPtr<CefTranslatorTestRefPtrLibrary> val) OVERRIDE;
+      CefRefPtr<CefTranslatorTestRefPtrLibrary> val) override;
   int SetChildRefPtrLibrary(
-      CefRefPtr<CefTranslatorTestRefPtrLibraryChild> val) OVERRIDE;
+      CefRefPtr<CefTranslatorTestRefPtrLibraryChild> val) override;
   CefRefPtr<CefTranslatorTestRefPtrLibrary>
   SetChildRefPtrLibraryAndReturnParent(
-      CefRefPtr<CefTranslatorTestRefPtrLibraryChild> val) OVERRIDE;
+      CefRefPtr<CefTranslatorTestRefPtrLibraryChild> val) override;
   bool SetRefPtrLibraryList(
       const std::vector<CefRefPtr<CefTranslatorTestRefPtrLibrary>>& val,
       int val1,
-      int val2) OVERRIDE;
+      int val2) override;
   bool GetRefPtrLibraryListByRef(RefPtrLibraryList& val,
                                  int val1,
-                                 int val2) OVERRIDE;
-  size_t GetRefPtrLibraryListSize() OVERRIDE;
-  int SetRefPtrClient(CefRefPtr<CefTranslatorTestRefPtrClient> val) OVERRIDE;
+                                 int val2) override;
+  size_t GetRefPtrLibraryListSize() override;
+  int SetRefPtrClient(CefRefPtr<CefTranslatorTestRefPtrClient> val) override;
   CefRefPtr<CefTranslatorTestRefPtrClient> SetRefPtrClientAndReturn(
-      CefRefPtr<CefTranslatorTestRefPtrClient> val) OVERRIDE;
+      CefRefPtr<CefTranslatorTestRefPtrClient> val) override;
   int SetChildRefPtrClient(
-      CefRefPtr<CefTranslatorTestRefPtrClientChild> val) OVERRIDE;
+      CefRefPtr<CefTranslatorTestRefPtrClientChild> val) override;
   CefRefPtr<CefTranslatorTestRefPtrClient> SetChildRefPtrClientAndReturnParent(
-      CefRefPtr<CefTranslatorTestRefPtrClientChild> val) OVERRIDE;
+      CefRefPtr<CefTranslatorTestRefPtrClientChild> val) override;
   bool SetRefPtrClientList(
       const std::vector<CefRefPtr<CefTranslatorTestRefPtrClient>>& val,
       int val1,
-      int val2) OVERRIDE;
+      int val2) override;
   bool GetRefPtrClientListByRef(
       RefPtrClientList& val,
       CefRefPtr<CefTranslatorTestRefPtrClient> val1,
-      CefRefPtr<CefTranslatorTestRefPtrClient> val2) OVERRIDE;
-  size_t GetRefPtrClientListSize() OVERRIDE;
-  CefOwnPtr<CefTranslatorTestScopedLibrary> GetOwnPtrLibrary(int val) OVERRIDE;
-  int SetOwnPtrLibrary(CefOwnPtr<CefTranslatorTestScopedLibrary> val) OVERRIDE;
+      CefRefPtr<CefTranslatorTestRefPtrClient> val2) override;
+  size_t GetRefPtrClientListSize() override;
+  CefOwnPtr<CefTranslatorTestScopedLibrary> GetOwnPtrLibrary(int val) override;
+  int SetOwnPtrLibrary(CefOwnPtr<CefTranslatorTestScopedLibrary> val) override;
   CefOwnPtr<CefTranslatorTestScopedLibrary> SetOwnPtrLibraryAndReturn(
-      CefOwnPtr<CefTranslatorTestScopedLibrary> val) OVERRIDE;
+      CefOwnPtr<CefTranslatorTestScopedLibrary> val) override;
   int SetChildOwnPtrLibrary(
-      CefOwnPtr<CefTranslatorTestScopedLibraryChild> val) OVERRIDE;
+      CefOwnPtr<CefTranslatorTestScopedLibraryChild> val) override;
   CefOwnPtr<CefTranslatorTestScopedLibrary>
   SetChildOwnPtrLibraryAndReturnParent(
-      CefOwnPtr<CefTranslatorTestScopedLibraryChild> val) OVERRIDE;
-  int SetOwnPtrClient(CefOwnPtr<CefTranslatorTestScopedClient> val) OVERRIDE;
+      CefOwnPtr<CefTranslatorTestScopedLibraryChild> val) override;
+  int SetOwnPtrClient(CefOwnPtr<CefTranslatorTestScopedClient> val) override;
   CefOwnPtr<CefTranslatorTestScopedClient> SetOwnPtrClientAndReturn(
-      CefOwnPtr<CefTranslatorTestScopedClient> val) OVERRIDE;
+      CefOwnPtr<CefTranslatorTestScopedClient> val) override;
   int SetChildOwnPtrClient(
-      CefOwnPtr<CefTranslatorTestScopedClientChild> val) OVERRIDE;
+      CefOwnPtr<CefTranslatorTestScopedClientChild> val) override;
   CefOwnPtr<CefTranslatorTestScopedClient> SetChildOwnPtrClientAndReturnParent(
-      CefOwnPtr<CefTranslatorTestScopedClientChild> val) OVERRIDE;
-  int SetRawPtrLibrary(CefRawPtr<CefTranslatorTestScopedLibrary> val) OVERRIDE;
+      CefOwnPtr<CefTranslatorTestScopedClientChild> val) override;
+  int SetRawPtrLibrary(CefRawPtr<CefTranslatorTestScopedLibrary> val) override;
   int SetChildRawPtrLibrary(
-      CefRawPtr<CefTranslatorTestScopedLibraryChild> val) OVERRIDE;
+      CefRawPtr<CefTranslatorTestScopedLibraryChild> val) override;
   bool SetRawPtrLibraryList(
       const std::vector<CefRawPtr<CefTranslatorTestScopedLibrary>>& val,
       int val1,
-      int val2) OVERRIDE;
-  int SetRawPtrClient(CefRawPtr<CefTranslatorTestScopedClient> val) OVERRIDE;
+      int val2) override;
+  int SetRawPtrClient(CefRawPtr<CefTranslatorTestScopedClient> val) override;
   int SetChildRawPtrClient(
-      CefRawPtr<CefTranslatorTestScopedClientChild> val) OVERRIDE;
+      CefRawPtr<CefTranslatorTestScopedClientChild> val) override;
   bool SetRawPtrClientList(
       const std::vector<CefRawPtr<CefTranslatorTestScopedClient>>& val,
       int val1,
-      int val2) OVERRIDE;
+      int val2) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_client_child_ctocpp.cc b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_client_child_ctocpp.cc
index 411ccbf..cc33e22 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_client_child_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_client_child_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2453173215db3e380519cc01ccf4e6716728a3e6$
+// $hash=83723bcac7d4a071aeece77b37ddd6b459b931fc$
 //
 
 #include "libcef_dll/ctocpp/test/translator_test_ref_ptr_client_child_ctocpp.h"
@@ -22,8 +22,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_ref_ptr_client_child_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_other_value))
+  if (CEF_MEMBER_MISSING(_struct, get_other_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -40,8 +41,9 @@
 
   cef_translator_test_ref_ptr_client_t* _struct =
       reinterpret_cast<cef_translator_test_ref_ptr_client_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_value))
+  if (CEF_MEMBER_MISSING(_struct, get_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -70,7 +72,7 @@
                     CefTranslatorTestRefPtrClientChild,
                     cef_translator_test_ref_ptr_client_child_t>::
     UnwrapDerived(CefWrapperType type, CefTranslatorTestRefPtrClientChild* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_client_child_ctocpp.h b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_client_child_ctocpp.h
index ef7166e..d59c50c 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_client_child_ctocpp.h
+++ b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_client_child_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=a9a72db9d83fecf02678a6da859a4dc475914d28$
+// $hash=971a30d8a2814ecdddb08763016621ce94b9da92$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_REF_PTR_CLIENT_CHILD_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_client_ctocpp.cc b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_client_ctocpp.cc
index 0043cce..0d54de1 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_client_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_client_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=a92bb99010dc728a39413e46e68a19cd2ac2906b$
+// $hash=ce7854af973f443c580f9f026be9db6c4cff6182$
 //
 
 #include "libcef_dll/ctocpp/test/translator_test_ref_ptr_client_ctocpp.h"
@@ -22,8 +22,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_ref_ptr_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_value))
+  if (CEF_MEMBER_MISSING(_struct, get_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -55,7 +56,7 @@
         CefTranslatorTestRefPtrClientChildCToCpp::Unwrap(
             reinterpret_cast<CefTranslatorTestRefPtrClientChild*>(c)));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_client_ctocpp.h b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_client_ctocpp.h
index 3dae892..968847f 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_client_ctocpp.h
+++ b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_client_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=89be8d7884c7bee2df32fe683210d8728729bfee$
+// $hash=a083f0198c6c93ee0fccdb262dce8dc567abbf9c$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_REF_PTR_CLIENT_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_child_ctocpp.cc b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_child_ctocpp.cc
index ae1ec4e..5c37516 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_child_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_child_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=393e66b4a61fb024e637495a6015f571ae9f2934$
+// $hash=91e5a9096b509e43530e031ae8e46d90380e0796$
 //
 
 #include "libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_child_ctocpp.h"
@@ -42,8 +42,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_ref_ptr_library_child_child_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_other_other_value))
+  if (CEF_MEMBER_MISSING(_struct, get_other_other_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -60,8 +61,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_ref_ptr_library_child_child_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_other_other_value))
+  if (CEF_MEMBER_MISSING(_struct, set_other_other_value)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -76,8 +78,9 @@
   cef_translator_test_ref_ptr_library_child_t* _struct =
       reinterpret_cast<cef_translator_test_ref_ptr_library_child_t*>(
           GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_other_value))
+  if (CEF_MEMBER_MISSING(_struct, get_other_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -95,8 +98,9 @@
   cef_translator_test_ref_ptr_library_child_t* _struct =
       reinterpret_cast<cef_translator_test_ref_ptr_library_child_t*>(
           GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_other_value))
+  if (CEF_MEMBER_MISSING(_struct, set_other_value)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -110,8 +114,9 @@
 
   cef_translator_test_ref_ptr_library_t* _struct =
       reinterpret_cast<cef_translator_test_ref_ptr_library_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_value))
+  if (CEF_MEMBER_MISSING(_struct, get_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -128,8 +133,9 @@
 
   cef_translator_test_ref_ptr_library_t* _struct =
       reinterpret_cast<cef_translator_test_ref_ptr_library_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_value))
+  if (CEF_MEMBER_MISSING(_struct, set_value)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -156,7 +162,7 @@
                     cef_translator_test_ref_ptr_library_child_child_t>::
     UnwrapDerived(CefWrapperType type,
                   CefTranslatorTestRefPtrLibraryChildChild* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_child_ctocpp.h b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_child_ctocpp.h
index ded3e56..f6a503a 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_child_ctocpp.h
+++ b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_child_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8e4db948f3b947ffc17aa0b020307f5b05584fda$
+// $hash=49af27e043172c178c3ef4f37805069e6af739e6$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_REF_PTR_LIBRARY_CHILD_CHILD_CTOCPP_H_
@@ -36,16 +36,16 @@
   virtual ~CefTranslatorTestRefPtrLibraryChildChildCToCpp();
 
   // CefTranslatorTestRefPtrLibraryChildChild methods.
-  int GetOtherOtherValue() OVERRIDE;
-  void SetOtherOtherValue(int value) OVERRIDE;
+  int GetOtherOtherValue() override;
+  void SetOtherOtherValue(int value) override;
 
   // CefTranslatorTestRefPtrLibraryChild methods.
-  int GetOtherValue() OVERRIDE;
-  void SetOtherValue(int value) OVERRIDE;
+  int GetOtherValue() override;
+  void SetOtherValue(int value) override;
 
   // CefTranslatorTestRefPtrLibrary methods.
-  int GetValue() OVERRIDE;
-  void SetValue(int value) OVERRIDE;
+  int GetValue() override;
+  void SetValue(int value) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_REF_PTR_LIBRARY_CHILD_CHILD_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_ctocpp.cc b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_ctocpp.cc
index 204ef36..3039bf7 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=752d19a05cc2fd993f6a501894bd06aebfee72f2$
+// $hash=cd059e94feaa5f002332fcb6fac40fcd1cb14dca$
 //
 
 #include "libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_ctocpp.h"
@@ -40,8 +40,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_ref_ptr_library_child_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_other_value))
+  if (CEF_MEMBER_MISSING(_struct, get_other_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -57,8 +58,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_ref_ptr_library_child_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_other_value))
+  if (CEF_MEMBER_MISSING(_struct, set_other_value)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -72,8 +74,9 @@
 
   cef_translator_test_ref_ptr_library_t* _struct =
       reinterpret_cast<cef_translator_test_ref_ptr_library_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_value))
+  if (CEF_MEMBER_MISSING(_struct, get_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -90,8 +93,9 @@
 
   cef_translator_test_ref_ptr_library_t* _struct =
       reinterpret_cast<cef_translator_test_ref_ptr_library_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_value))
+  if (CEF_MEMBER_MISSING(_struct, set_value)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -122,7 +126,7 @@
         CefTranslatorTestRefPtrLibraryChildChildCToCpp::Unwrap(
             reinterpret_cast<CefTranslatorTestRefPtrLibraryChildChild*>(c)));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_ctocpp.h b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_ctocpp.h
index 461435d..a5e5b71 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_ctocpp.h
+++ b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_child_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=940f6bd84685ec544f18320104afda0062b7ad51$
+// $hash=ef77c876031b14fdee487305c5cfded6a9cb910f$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_REF_PTR_LIBRARY_CHILD_CTOCPP_H_
@@ -35,12 +35,12 @@
   virtual ~CefTranslatorTestRefPtrLibraryChildCToCpp();
 
   // CefTranslatorTestRefPtrLibraryChild methods.
-  int GetOtherValue() OVERRIDE;
-  void SetOtherValue(int value) OVERRIDE;
+  int GetOtherValue() override;
+  void SetOtherValue(int value) override;
 
   // CefTranslatorTestRefPtrLibrary methods.
-  int GetValue() OVERRIDE;
-  void SetValue(int value) OVERRIDE;
+  int GetValue() override;
+  void SetValue(int value) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_REF_PTR_LIBRARY_CHILD_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_ctocpp.cc b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_ctocpp.cc
index 3e1809a..3e54eee 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8bb13d683dd6c3dd98a0990de4b3e2396e9f9a1e$
+// $hash=7540736b997ff0f093265301b1476e18933c492f$
 //
 
 #include "libcef_dll/ctocpp/test/translator_test_ref_ptr_library_ctocpp.h"
@@ -40,8 +40,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_ref_ptr_library_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_value))
+  if (CEF_MEMBER_MISSING(_struct, get_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -57,8 +58,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_translator_test_ref_ptr_library_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_value))
+  if (CEF_MEMBER_MISSING(_struct, set_value)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -92,7 +94,7 @@
         CefTranslatorTestRefPtrLibraryChildChildCToCpp::Unwrap(
             reinterpret_cast<CefTranslatorTestRefPtrLibraryChildChild*>(c)));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_ctocpp.h b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_ctocpp.h
index 9e5c285..94ff9da 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_ctocpp.h
+++ b/src/libcef_dll/ctocpp/test/translator_test_ref_ptr_library_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=26f49fae992d673accdd8d31dfc2c763a75087cb$
+// $hash=9fa8897ee5081b7cd95a6cb791fb69871f61406e$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_REF_PTR_LIBRARY_CTOCPP_H_
@@ -35,8 +35,8 @@
   virtual ~CefTranslatorTestRefPtrLibraryCToCpp();
 
   // CefTranslatorTestRefPtrLibrary methods.
-  int GetValue() OVERRIDE;
-  void SetValue(int value) OVERRIDE;
+  int GetValue() override;
+  void SetValue(int value) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_REF_PTR_LIBRARY_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/test/translator_test_scoped_client_child_ctocpp.cc b/src/libcef_dll/ctocpp/test/translator_test_scoped_client_child_ctocpp.cc
index 53062a8..5ba6cd5 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_scoped_client_child_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/test/translator_test_scoped_client_child_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d9e908faae3ca204ade3cceff3471419b234dddb$
+// $hash=b37005aa19984166b1f103e260cb49f6becec364$
 //
 
 #include "libcef_dll/ctocpp/test/translator_test_scoped_client_child_ctocpp.h"
@@ -19,8 +19,9 @@
 NO_SANITIZE("cfi-icall")
 int CefTranslatorTestScopedClientChildCToCpp::GetOtherValue() {
   cef_translator_test_scoped_client_child_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_other_value))
+  if (CEF_MEMBER_MISSING(_struct, get_other_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -35,8 +36,9 @@
 int CefTranslatorTestScopedClientChildCToCpp::GetValue() {
   cef_translator_test_scoped_client_t* _struct =
       reinterpret_cast<cef_translator_test_scoped_client_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_value))
+  if (CEF_MEMBER_MISSING(_struct, get_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -64,7 +66,7 @@
                 cef_translator_test_scoped_client_child_t>::
     UnwrapDerivedOwn(CefWrapperType type,
                      CefOwnPtr<CefTranslatorTestScopedClientChild> c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
@@ -75,7 +77,7 @@
                 cef_translator_test_scoped_client_child_t>::
     UnwrapDerivedRaw(CefWrapperType type,
                      CefRawPtr<CefTranslatorTestScopedClientChild> c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/test/translator_test_scoped_client_child_ctocpp.h b/src/libcef_dll/ctocpp/test/translator_test_scoped_client_child_ctocpp.h
index 2f33b51..36339c1 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_scoped_client_child_ctocpp.h
+++ b/src/libcef_dll/ctocpp/test/translator_test_scoped_client_child_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=883e6a51cedcbe20292e6da6dd97709068e032e3$
+// $hash=ec4bff6137c66581b34dc2ef11beb02276de163a$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_SCOPED_CLIENT_CHILD_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/test/translator_test_scoped_client_ctocpp.cc b/src/libcef_dll/ctocpp/test/translator_test_scoped_client_ctocpp.cc
index fb57aa7..a0b9e4b 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_scoped_client_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/test/translator_test_scoped_client_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=5c7f3edee8fa09ae414ccc7cacfaaa9713cdbf2c$
+// $hash=0ce373fa99a3d48d9a512355dfc4d3c26aa18f87$
 //
 
 #include "libcef_dll/ctocpp/test/translator_test_scoped_client_ctocpp.h"
@@ -19,8 +19,9 @@
 
 NO_SANITIZE("cfi-icall") int CefTranslatorTestScopedClientCToCpp::GetValue() {
   cef_translator_test_scoped_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_value))
+  if (CEF_MEMBER_MISSING(_struct, get_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -53,7 +54,7 @@
                 reinterpret_cast<CefTranslatorTestScopedClientChild*>(
                     c.release()))));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
@@ -68,10 +69,9 @@
     return reinterpret_cast<cef_translator_test_scoped_client_t*>(
         CefTranslatorTestScopedClientChildCToCpp::UnwrapRaw(
             CefRawPtr<CefTranslatorTestScopedClientChild>(
-                reinterpret_cast<CefTranslatorTestScopedClientChild*>(
-                    CEF_RAW_PTR_GET(c)))));
+                reinterpret_cast<CefTranslatorTestScopedClientChild*>(c))));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/test/translator_test_scoped_client_ctocpp.h b/src/libcef_dll/ctocpp/test/translator_test_scoped_client_ctocpp.h
index c2dd242..caeaf69 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_scoped_client_ctocpp.h
+++ b/src/libcef_dll/ctocpp/test/translator_test_scoped_client_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=38ae3f615e92571aab894b0a7e4844a2ee69f20b$
+// $hash=d511f3a8273e4d9c6acff3d183b7bfa84e1385e3$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_SCOPED_CLIENT_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/test/translator_test_scoped_library_child_child_ctocpp.cc b/src/libcef_dll/ctocpp/test/translator_test_scoped_library_child_child_ctocpp.cc
index 653ed7a..d0605a1 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_scoped_library_child_child_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/test/translator_test_scoped_library_child_child_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=fc692610bce3f501fc3cbcf316da081d29a03cd9$
+// $hash=7021be9737238bd48745b5cfbfad8c0191f847fe$
 //
 
 #include "libcef_dll/ctocpp/test/translator_test_scoped_library_child_child_ctocpp.h"
@@ -37,8 +37,9 @@
 NO_SANITIZE("cfi-icall")
 int CefTranslatorTestScopedLibraryChildChildCToCpp::GetOtherOtherValue() {
   cef_translator_test_scoped_library_child_child_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_other_other_value))
+  if (CEF_MEMBER_MISSING(_struct, get_other_other_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -53,8 +54,9 @@
 void CefTranslatorTestScopedLibraryChildChildCToCpp::SetOtherOtherValue(
     int value) {
   cef_translator_test_scoped_library_child_child_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_other_other_value))
+  if (CEF_MEMBER_MISSING(_struct, set_other_other_value)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -67,8 +69,9 @@
   cef_translator_test_scoped_library_child_t* _struct =
       reinterpret_cast<cef_translator_test_scoped_library_child_t*>(
           GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_other_value))
+  if (CEF_MEMBER_MISSING(_struct, get_other_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -84,8 +87,9 @@
   cef_translator_test_scoped_library_child_t* _struct =
       reinterpret_cast<cef_translator_test_scoped_library_child_t*>(
           GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_other_value))
+  if (CEF_MEMBER_MISSING(_struct, set_other_value)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -97,8 +101,9 @@
 int CefTranslatorTestScopedLibraryChildChildCToCpp::GetValue() {
   cef_translator_test_scoped_library_t* _struct =
       reinterpret_cast<cef_translator_test_scoped_library_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_value))
+  if (CEF_MEMBER_MISSING(_struct, get_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -113,8 +118,9 @@
 void CefTranslatorTestScopedLibraryChildChildCToCpp::SetValue(int value) {
   cef_translator_test_scoped_library_t* _struct =
       reinterpret_cast<cef_translator_test_scoped_library_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_value))
+  if (CEF_MEMBER_MISSING(_struct, set_value)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -139,7 +145,7 @@
                 cef_translator_test_scoped_library_child_child_t>::
     UnwrapDerivedOwn(CefWrapperType type,
                      CefOwnPtr<CefTranslatorTestScopedLibraryChildChild> c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
@@ -150,7 +156,7 @@
                 cef_translator_test_scoped_library_child_child_t>::
     UnwrapDerivedRaw(CefWrapperType type,
                      CefRawPtr<CefTranslatorTestScopedLibraryChildChild> c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/test/translator_test_scoped_library_child_child_ctocpp.h b/src/libcef_dll/ctocpp/test/translator_test_scoped_library_child_child_ctocpp.h
index 232ad75..8b3fd34 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_scoped_library_child_child_ctocpp.h
+++ b/src/libcef_dll/ctocpp/test/translator_test_scoped_library_child_child_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1470375f5966c1b47a38265ce12172b5d05f3254$
+// $hash=b6fc182f3444ce3926bff6d2b30d14aeca4cb9ba$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_SCOPED_LIBRARY_CHILD_CHILD_CTOCPP_H_
@@ -35,16 +35,16 @@
   virtual ~CefTranslatorTestScopedLibraryChildChildCToCpp();
 
   // CefTranslatorTestScopedLibraryChildChild methods.
-  int GetOtherOtherValue() OVERRIDE;
-  void SetOtherOtherValue(int value) OVERRIDE;
+  int GetOtherOtherValue() override;
+  void SetOtherOtherValue(int value) override;
 
   // CefTranslatorTestScopedLibraryChild methods.
-  int GetOtherValue() OVERRIDE;
-  void SetOtherValue(int value) OVERRIDE;
+  int GetOtherValue() override;
+  void SetOtherValue(int value) override;
 
   // CefTranslatorTestScopedLibrary methods.
-  int GetValue() OVERRIDE;
-  void SetValue(int value) OVERRIDE;
+  int GetValue() override;
+  void SetValue(int value) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_SCOPED_LIBRARY_CHILD_CHILD_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/test/translator_test_scoped_library_child_ctocpp.cc b/src/libcef_dll/ctocpp/test/translator_test_scoped_library_child_ctocpp.cc
index 3225b86..f17fb5c 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_scoped_library_child_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/test/translator_test_scoped_library_child_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e76720f37e225d0c2f30938ec59b1e73e61b9017$
+// $hash=7fd424327ace29415b68a9c9fb15216e33c7c142$
 //
 
 #include "libcef_dll/ctocpp/test/translator_test_scoped_library_child_ctocpp.h"
@@ -35,8 +35,9 @@
 NO_SANITIZE("cfi-icall")
 int CefTranslatorTestScopedLibraryChildCToCpp::GetOtherValue() {
   cef_translator_test_scoped_library_child_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_other_value))
+  if (CEF_MEMBER_MISSING(_struct, get_other_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -50,8 +51,9 @@
 NO_SANITIZE("cfi-icall")
 void CefTranslatorTestScopedLibraryChildCToCpp::SetOtherValue(int value) {
   cef_translator_test_scoped_library_child_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_other_value))
+  if (CEF_MEMBER_MISSING(_struct, set_other_value)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -63,8 +65,9 @@
 int CefTranslatorTestScopedLibraryChildCToCpp::GetValue() {
   cef_translator_test_scoped_library_t* _struct =
       reinterpret_cast<cef_translator_test_scoped_library_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_value))
+  if (CEF_MEMBER_MISSING(_struct, get_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -79,8 +82,9 @@
 void CefTranslatorTestScopedLibraryChildCToCpp::SetValue(int value) {
   cef_translator_test_scoped_library_t* _struct =
       reinterpret_cast<cef_translator_test_scoped_library_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_value))
+  if (CEF_MEMBER_MISSING(_struct, set_value)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -112,7 +116,7 @@
                 reinterpret_cast<CefTranslatorTestScopedLibraryChildChild*>(
                     c.release()))));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
@@ -128,9 +132,9 @@
         CefTranslatorTestScopedLibraryChildChildCToCpp::UnwrapRaw(
             CefRawPtr<CefTranslatorTestScopedLibraryChildChild>(
                 reinterpret_cast<CefTranslatorTestScopedLibraryChildChild*>(
-                    CEF_RAW_PTR_GET(c)))));
+                    c))));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/test/translator_test_scoped_library_child_ctocpp.h b/src/libcef_dll/ctocpp/test/translator_test_scoped_library_child_ctocpp.h
index a45890d..e4ab2f9 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_scoped_library_child_ctocpp.h
+++ b/src/libcef_dll/ctocpp/test/translator_test_scoped_library_child_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0018f0e4d7a63bb8ab959a9f98268d696894dd7d$
+// $hash=954fc390e3b474eedcf0bbb3df41e717c00449d3$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_SCOPED_LIBRARY_CHILD_CTOCPP_H_
@@ -35,12 +35,12 @@
   virtual ~CefTranslatorTestScopedLibraryChildCToCpp();
 
   // CefTranslatorTestScopedLibraryChild methods.
-  int GetOtherValue() OVERRIDE;
-  void SetOtherValue(int value) OVERRIDE;
+  int GetOtherValue() override;
+  void SetOtherValue(int value) override;
 
   // CefTranslatorTestScopedLibrary methods.
-  int GetValue() OVERRIDE;
-  void SetValue(int value) OVERRIDE;
+  int GetValue() override;
+  void SetValue(int value) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_SCOPED_LIBRARY_CHILD_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/test/translator_test_scoped_library_ctocpp.cc b/src/libcef_dll/ctocpp/test/translator_test_scoped_library_ctocpp.cc
index 5673197..675bb2f 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_scoped_library_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/test/translator_test_scoped_library_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f7a516322c3b9b51a545f7b826dbfb509a7194e7$
+// $hash=042f660ffd41b420a394bc93cdaccf75984cf999$
 //
 
 #include "libcef_dll/ctocpp/test/translator_test_scoped_library_ctocpp.h"
@@ -35,8 +35,9 @@
 
 NO_SANITIZE("cfi-icall") int CefTranslatorTestScopedLibraryCToCpp::GetValue() {
   cef_translator_test_scoped_library_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_value))
+  if (CEF_MEMBER_MISSING(_struct, get_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -50,8 +51,9 @@
 NO_SANITIZE("cfi-icall")
 void CefTranslatorTestScopedLibraryCToCpp::SetValue(int value) {
   cef_translator_test_scoped_library_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_value))
+  if (CEF_MEMBER_MISSING(_struct, set_value)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -88,7 +90,7 @@
                 reinterpret_cast<CefTranslatorTestScopedLibraryChildChild*>(
                     c.release()))));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
@@ -103,17 +105,16 @@
     return reinterpret_cast<cef_translator_test_scoped_library_t*>(
         CefTranslatorTestScopedLibraryChildCToCpp::UnwrapRaw(
             CefRawPtr<CefTranslatorTestScopedLibraryChild>(
-                reinterpret_cast<CefTranslatorTestScopedLibraryChild*>(
-                    CEF_RAW_PTR_GET(c)))));
+                reinterpret_cast<CefTranslatorTestScopedLibraryChild*>(c))));
   }
   if (type == WT_TRANSLATOR_TEST_SCOPED_LIBRARY_CHILD_CHILD) {
     return reinterpret_cast<cef_translator_test_scoped_library_t*>(
         CefTranslatorTestScopedLibraryChildChildCToCpp::UnwrapRaw(
             CefRawPtr<CefTranslatorTestScopedLibraryChildChild>(
                 reinterpret_cast<CefTranslatorTestScopedLibraryChildChild*>(
-                    CEF_RAW_PTR_GET(c)))));
+                    c))));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/test/translator_test_scoped_library_ctocpp.h b/src/libcef_dll/ctocpp/test/translator_test_scoped_library_ctocpp.h
index 11600e0..c40e19e 100644
--- a/src/libcef_dll/ctocpp/test/translator_test_scoped_library_ctocpp.h
+++ b/src/libcef_dll/ctocpp/test/translator_test_scoped_library_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=35349ead1a95bca88b7076a79e1c8ad7be025d08$
+// $hash=5fafb4986f557d448f6f234fd49ea899eac81af1$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_SCOPED_LIBRARY_CTOCPP_H_
@@ -35,8 +35,8 @@
   virtual ~CefTranslatorTestScopedLibraryCToCpp();
 
   // CefTranslatorTestScopedLibrary methods.
-  int GetValue() OVERRIDE;
-  void SetValue(int value) OVERRIDE;
+  int GetValue() override;
+  void SetValue(int value) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_TEST_TRANSLATOR_TEST_SCOPED_LIBRARY_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/thread_ctocpp.cc b/src/libcef_dll/ctocpp/thread_ctocpp.cc
index 26cf529..34c7dcd 100644
--- a/src/libcef_dll/ctocpp/thread_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/thread_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=10047fa557a7b02daa67063a01f1f19c45d17120$
+// $hash=74736c3227b7b9961f04ab93f5644a16fe0a21b9$
 //
 
 #include "libcef_dll/ctocpp/thread_ctocpp.h"
@@ -47,8 +47,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_thread_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_task_runner))
+  if (CEF_MEMBER_MISSING(_struct, get_task_runner)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -64,8 +65,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_thread_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_platform_thread_id))
+  if (CEF_MEMBER_MISSING(_struct, get_platform_thread_id)) {
     return kInvalidPlatformThreadId;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -80,8 +82,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_thread_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, stop))
+  if (CEF_MEMBER_MISSING(_struct, stop)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -93,8 +96,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_thread_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_running))
+  if (CEF_MEMBER_MISSING(_struct, is_running)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -120,7 +124,7 @@
 CefCToCppRefCounted<CefThreadCToCpp, CefThread, cef_thread_t>::UnwrapDerived(
     CefWrapperType type,
     CefThread* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/thread_ctocpp.h b/src/libcef_dll/ctocpp/thread_ctocpp.h
index 880cc7e..5bdc357 100644
--- a/src/libcef_dll/ctocpp/thread_ctocpp.h
+++ b/src/libcef_dll/ctocpp/thread_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=cfe482fc913cfa603b98d58e4579e5af667b0ce5$
+// $hash=63729fa2f06672498bde63eaa8151b20db9e6fd8$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_THREAD_CTOCPP_H_
@@ -33,10 +33,10 @@
   virtual ~CefThreadCToCpp();
 
   // CefThread methods.
-  CefRefPtr<CefTaskRunner> GetTaskRunner() OVERRIDE;
-  cef_platform_thread_id_t GetPlatformThreadId() OVERRIDE;
-  void Stop() OVERRIDE;
-  bool IsRunning() OVERRIDE;
+  CefRefPtr<CefTaskRunner> GetTaskRunner() override;
+  cef_platform_thread_id_t GetPlatformThreadId() override;
+  void Stop() override;
+  bool IsRunning() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_THREAD_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/urlrequest_client_ctocpp.cc b/src/libcef_dll/ctocpp/urlrequest_client_ctocpp.cc
index fbc7676..31242d9 100644
--- a/src/libcef_dll/ctocpp/urlrequest_client_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/urlrequest_client_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b08f8ba4d2ee2aaf4ee5f805d9cd6d0159a84969$
+// $hash=4d593132f79049ee1f5bc752b17d0a5c3a9aff91$
 //
 
 #include "libcef_dll/ctocpp/urlrequest_client_ctocpp.h"
@@ -25,15 +25,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_urlrequest_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_request_complete))
+  if (CEF_MEMBER_MISSING(_struct, on_request_complete)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return;
+  }
 
   // Execute
   _struct->on_request_complete(_struct, CefURLRequestCppToC::Wrap(request));
@@ -42,20 +44,22 @@
 NO_SANITIZE("cfi-icall")
 void CefURLRequestClientCToCpp::OnUploadProgress(
     CefRefPtr<CefURLRequest> request,
-    int64 current,
-    int64 total) {
+    int64_t current,
+    int64_t total) {
   shutdown_checker::AssertNotShutdown();
 
   cef_urlrequest_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_upload_progress))
+  if (CEF_MEMBER_MISSING(_struct, on_upload_progress)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return;
+  }
 
   // Execute
   _struct->on_upload_progress(_struct, CefURLRequestCppToC::Wrap(request),
@@ -65,20 +69,22 @@
 NO_SANITIZE("cfi-icall")
 void CefURLRequestClientCToCpp::OnDownloadProgress(
     CefRefPtr<CefURLRequest> request,
-    int64 current,
-    int64 total) {
+    int64_t current,
+    int64_t total) {
   shutdown_checker::AssertNotShutdown();
 
   cef_urlrequest_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_download_progress))
+  if (CEF_MEMBER_MISSING(_struct, on_download_progress)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return;
+  }
 
   // Execute
   _struct->on_download_progress(_struct, CefURLRequestCppToC::Wrap(request),
@@ -92,19 +98,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_urlrequest_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_download_data))
+  if (CEF_MEMBER_MISSING(_struct, on_download_data)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: request; type: refptr_diff
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return;
+  }
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return;
+  }
 
   // Execute
   _struct->on_download_data(_struct, CefURLRequestCppToC::Wrap(request), data,
@@ -122,23 +131,27 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_urlrequest_client_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_auth_credentials))
+  if (CEF_MEMBER_MISSING(_struct, get_auth_credentials)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: host; type: string_byref_const
   DCHECK(!host.empty());
-  if (host.empty())
+  if (host.empty()) {
     return false;
+  }
   // Verify param: scheme; type: string_byref_const
   DCHECK(!scheme.empty());
-  if (scheme.empty())
+  if (scheme.empty()) {
     return false;
+  }
   // Verify param: callback; type: refptr_diff
   DCHECK(callback.get());
-  if (!callback.get())
+  if (!callback.get()) {
     return false;
+  }
   // Unverified params: realm
 
   // Execute
@@ -166,7 +179,7 @@
     CefURLRequestClient,
     cef_urlrequest_client_t>::UnwrapDerived(CefWrapperType type,
                                             CefURLRequestClient* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/urlrequest_client_ctocpp.h b/src/libcef_dll/ctocpp/urlrequest_client_ctocpp.h
index 41f7902..1ae761c 100644
--- a/src/libcef_dll/ctocpp/urlrequest_client_ctocpp.h
+++ b/src/libcef_dll/ctocpp/urlrequest_client_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2a531ac29630c829e393105fcd54e12263e82193$
+// $hash=0b70adb9a01fcb166ffa6b310825a4d9679a8d23$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_URLREQUEST_CLIENT_CTOCPP_H_
@@ -37,11 +37,11 @@
   // CefURLRequestClient methods.
   void OnRequestComplete(CefRefPtr<CefURLRequest> request) override;
   void OnUploadProgress(CefRefPtr<CefURLRequest> request,
-                        int64 current,
-                        int64 total) override;
+                        int64_t current,
+                        int64_t total) override;
   void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
-                          int64 current,
-                          int64 total) override;
+                          int64_t current,
+                          int64_t total) override;
   void OnDownloadData(CefRefPtr<CefURLRequest> request,
                       const void* data,
                       size_t data_length) override;
diff --git a/src/libcef_dll/ctocpp/urlrequest_ctocpp.cc b/src/libcef_dll/ctocpp/urlrequest_ctocpp.cc
index d25fb82..1b65fc5 100644
--- a/src/libcef_dll/ctocpp/urlrequest_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/urlrequest_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=59e8bd7a950727fdcd6234401df65ca60ea33ba2$
+// $hash=6d08f44b6705e919027d22f22a432bebe47d20da$
 //
 
 #include "libcef_dll/ctocpp/urlrequest_ctocpp.h"
@@ -32,12 +32,14 @@
 
   // Verify param: request; type: refptr_same
   DCHECK(request.get());
-  if (!request.get())
+  if (!request.get()) {
     return nullptr;
+  }
   // Verify param: client; type: refptr_diff
   DCHECK(client.get());
-  if (!client.get())
+  if (!client.get()) {
     return nullptr;
+  }
   // Unverified params: request_context
 
   // Execute
@@ -57,8 +59,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_urlrequest_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_request))
+  if (CEF_MEMBER_MISSING(_struct, get_request)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -74,8 +77,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_urlrequest_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_client))
+  if (CEF_MEMBER_MISSING(_struct, get_client)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -91,8 +95,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_urlrequest_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_request_status))
+  if (CEF_MEMBER_MISSING(_struct, get_request_status)) {
     return UR_UNKNOWN;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -108,8 +113,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_urlrequest_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_request_error))
+  if (CEF_MEMBER_MISSING(_struct, get_request_error)) {
     return ERR_NONE;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -125,8 +131,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_urlrequest_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_response))
+  if (CEF_MEMBER_MISSING(_struct, get_response)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -141,8 +148,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_urlrequest_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, response_was_cached))
+  if (CEF_MEMBER_MISSING(_struct, response_was_cached)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -157,8 +165,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_urlrequest_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cancel))
+  if (CEF_MEMBER_MISSING(_struct, cancel)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -180,7 +189,7 @@
 cef_urlrequest_t*
 CefCToCppRefCounted<CefURLRequestCToCpp, CefURLRequest, cef_urlrequest_t>::
     UnwrapDerived(CefWrapperType type, CefURLRequest* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/urlrequest_ctocpp.h b/src/libcef_dll/ctocpp/urlrequest_ctocpp.h
index 9f1a053..7a2bff5 100644
--- a/src/libcef_dll/ctocpp/urlrequest_ctocpp.h
+++ b/src/libcef_dll/ctocpp/urlrequest_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3ab70d366cf2fe9f3c1bf296445a16225f18a20e$
+// $hash=8c953a3dd5cdec5cba6160e848884c2f7c9b3ac6$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_URLREQUEST_CTOCPP_H_
@@ -34,13 +34,13 @@
   virtual ~CefURLRequestCToCpp();
 
   // CefURLRequest methods.
-  CefRefPtr<CefRequest> GetRequest() OVERRIDE;
-  CefRefPtr<CefURLRequestClient> GetClient() OVERRIDE;
-  Status GetRequestStatus() OVERRIDE;
-  ErrorCode GetRequestError() OVERRIDE;
-  CefRefPtr<CefResponse> GetResponse() OVERRIDE;
-  bool ResponseWasCached() OVERRIDE;
-  void Cancel() OVERRIDE;
+  CefRefPtr<CefRequest> GetRequest() override;
+  CefRefPtr<CefURLRequestClient> GetClient() override;
+  Status GetRequestStatus() override;
+  ErrorCode GetRequestError() override;
+  CefRefPtr<CefResponse> GetResponse() override;
+  bool ResponseWasCached() override;
+  void Cancel() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_URLREQUEST_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/v8accessor_ctocpp.cc b/src/libcef_dll/ctocpp/v8accessor_ctocpp.cc
index 87a9f02..efeff04 100644
--- a/src/libcef_dll/ctocpp/v8accessor_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/v8accessor_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=ba0cb1e58376451d6ab1a9bddf36629a79d10b95$
+// $hash=82799d0f81c3d54dc77361245f26786ea1875199$
 //
 
 #include "libcef_dll/ctocpp/v8accessor_ctocpp.h"
@@ -23,24 +23,28 @@
                               CefRefPtr<CefV8Value>& retval,
                               CefString& exception) {
   cef_v8accessor_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get))
+  if (CEF_MEMBER_MISSING(_struct, get)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return false;
+  }
   // Verify param: object; type: refptr_diff
   DCHECK(object.get());
-  if (!object.get())
+  if (!object.get()) {
     return false;
+  }
 
   // Translate param: retval; type: refptr_diff_byref
   cef_v8value_t* retvalStruct = NULL;
-  if (retval.get())
+  if (retval.get()) {
     retvalStruct = CefV8ValueCppToC::Wrap(retval);
+  }
   cef_v8value_t* retvalOrig = retvalStruct;
 
   // Execute
@@ -67,23 +71,27 @@
                               const CefRefPtr<CefV8Value> value,
                               CefString& exception) {
   cef_v8accessor_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set))
+  if (CEF_MEMBER_MISSING(_struct, set)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return false;
+  }
   // Verify param: object; type: refptr_diff
   DCHECK(object.get());
-  if (!object.get())
+  if (!object.get()) {
     return false;
+  }
   // Verify param: value; type: refptr_diff
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set(
@@ -106,7 +114,7 @@
 cef_v8accessor_t*
 CefCToCppRefCounted<CefV8AccessorCToCpp, CefV8Accessor, cef_v8accessor_t>::
     UnwrapDerived(CefWrapperType type, CefV8Accessor* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/v8accessor_ctocpp.h b/src/libcef_dll/ctocpp/v8accessor_ctocpp.h
index b30175e..45c4de9 100644
--- a/src/libcef_dll/ctocpp/v8accessor_ctocpp.h
+++ b/src/libcef_dll/ctocpp/v8accessor_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8e7a47e0cc8cea5d9aa39e243657107ae51b1b93$
+// $hash=1d8a3afd0e6a0344a9c5f6e301b517e5f906c186$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_V8ACCESSOR_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/v8array_buffer_release_callback_ctocpp.cc b/src/libcef_dll/ctocpp/v8array_buffer_release_callback_ctocpp.cc
index a37b7b3..b20c55c 100644
--- a/src/libcef_dll/ctocpp/v8array_buffer_release_callback_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/v8array_buffer_release_callback_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=a9e8a08fe2206b4dd9a9f0655b149465f81c14c5$
+// $hash=d7aa0e86c66737e1ec4db2188a1aba3967c95919$
 //
 
 #include "libcef_dll/ctocpp/v8array_buffer_release_callback_ctocpp.h"
@@ -19,15 +19,17 @@
 NO_SANITIZE("cfi-icall")
 void CefV8ArrayBufferReleaseCallbackCToCpp::ReleaseBuffer(void* buffer) {
   cef_v8array_buffer_release_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, release_buffer))
+  if (CEF_MEMBER_MISSING(_struct, release_buffer)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: buffer; type: simple_byaddr
   DCHECK(buffer);
-  if (!buffer)
+  if (!buffer) {
     return;
+  }
 
   // Execute
   _struct->release_buffer(_struct, buffer);
@@ -49,7 +51,7 @@
                     CefV8ArrayBufferReleaseCallback,
                     cef_v8array_buffer_release_callback_t>::
     UnwrapDerived(CefWrapperType type, CefV8ArrayBufferReleaseCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/v8array_buffer_release_callback_ctocpp.h b/src/libcef_dll/ctocpp/v8array_buffer_release_callback_ctocpp.h
index 4c16715..4a52925 100644
--- a/src/libcef_dll/ctocpp/v8array_buffer_release_callback_ctocpp.h
+++ b/src/libcef_dll/ctocpp/v8array_buffer_release_callback_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=a8516449a68fa70c51ae471bf754d73879929d33$
+// $hash=4f9c4bb702d2824ee94dd334244cd9ba14609025$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_V8ARRAY_BUFFER_RELEASE_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/v8context_ctocpp.cc b/src/libcef_dll/ctocpp/v8context_ctocpp.cc
index 048387c..bdc5bce 100644
--- a/src/libcef_dll/ctocpp/v8context_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/v8context_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=17bb7b970832cbd12edb0378b9529a22a7d0ee03$
+// $hash=6bdcf32699e33c7e46b8b9ac67220a6edd0bd73a$
 //
 
 #include "libcef_dll/ctocpp/v8context_ctocpp.h"
@@ -58,8 +58,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefTaskRunner> CefV8ContextCToCpp::GetTaskRunner() {
   cef_v8context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_task_runner))
+  if (CEF_MEMBER_MISSING(_struct, get_task_runner)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -72,8 +73,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ContextCToCpp::IsValid() {
   cef_v8context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -87,8 +89,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefBrowser> CefV8ContextCToCpp::GetBrowser() {
   cef_v8context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_browser))
+  if (CEF_MEMBER_MISSING(_struct, get_browser)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -101,8 +104,9 @@
 
 NO_SANITIZE("cfi-icall") CefRefPtr<CefFrame> CefV8ContextCToCpp::GetFrame() {
   cef_v8context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_frame))
+  if (CEF_MEMBER_MISSING(_struct, get_frame)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -115,8 +119,9 @@
 
 NO_SANITIZE("cfi-icall") CefRefPtr<CefV8Value> CefV8ContextCToCpp::GetGlobal() {
   cef_v8context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_global))
+  if (CEF_MEMBER_MISSING(_struct, get_global)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -129,8 +134,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ContextCToCpp::Enter() {
   cef_v8context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, enter))
+  if (CEF_MEMBER_MISSING(_struct, enter)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -143,8 +149,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ContextCToCpp::Exit() {
   cef_v8context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, exit))
+  if (CEF_MEMBER_MISSING(_struct, exit)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -158,15 +165,17 @@
 NO_SANITIZE("cfi-icall")
 bool CefV8ContextCToCpp::IsSame(CefRefPtr<CefV8Context> that) {
   cef_v8context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefV8ContextCToCpp::Unwrap(that));
@@ -182,26 +191,30 @@
                               CefRefPtr<CefV8Value>& retval,
                               CefRefPtr<CefV8Exception>& exception) {
   cef_v8context_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, eval))
+  if (CEF_MEMBER_MISSING(_struct, eval)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: code; type: string_byref_const
   DCHECK(!code.empty());
-  if (code.empty())
+  if (code.empty()) {
     return false;
+  }
   // Unverified params: script_url
 
   // Translate param: retval; type: refptr_same_byref
   cef_v8value_t* retvalStruct = NULL;
-  if (retval.get())
+  if (retval.get()) {
     retvalStruct = CefV8ValueCToCpp::Unwrap(retval);
+  }
   cef_v8value_t* retvalOrig = retvalStruct;
   // Translate param: exception; type: refptr_same_byref
   cef_v8exception_t* exceptionStruct = NULL;
-  if (exception.get())
+  if (exception.get()) {
     exceptionStruct = CefV8ExceptionCToCpp::Unwrap(exception);
+  }
   cef_v8exception_t* exceptionOrig = exceptionStruct;
 
   // Execute
@@ -241,7 +254,7 @@
 cef_v8context_t*
 CefCToCppRefCounted<CefV8ContextCToCpp, CefV8Context, cef_v8context_t>::
     UnwrapDerived(CefWrapperType type, CefV8Context* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/v8context_ctocpp.h b/src/libcef_dll/ctocpp/v8context_ctocpp.h
index 79141fb..7ab4e0b 100644
--- a/src/libcef_dll/ctocpp/v8context_ctocpp.h
+++ b/src/libcef_dll/ctocpp/v8context_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6beb66276c6d884570c8f8903fd67d39a9e6f986$
+// $hash=c5159f67aa8d77aca23153cf6c35468af27dba14$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_V8CONTEXT_CTOCPP_H_
@@ -34,19 +34,19 @@
   virtual ~CefV8ContextCToCpp();
 
   // CefV8Context methods.
-  CefRefPtr<CefTaskRunner> GetTaskRunner() OVERRIDE;
-  bool IsValid() OVERRIDE;
-  CefRefPtr<CefBrowser> GetBrowser() OVERRIDE;
-  CefRefPtr<CefFrame> GetFrame() OVERRIDE;
-  CefRefPtr<CefV8Value> GetGlobal() OVERRIDE;
-  bool Enter() OVERRIDE;
-  bool Exit() OVERRIDE;
-  bool IsSame(CefRefPtr<CefV8Context> that) OVERRIDE;
+  CefRefPtr<CefTaskRunner> GetTaskRunner() override;
+  bool IsValid() override;
+  CefRefPtr<CefBrowser> GetBrowser() override;
+  CefRefPtr<CefFrame> GetFrame() override;
+  CefRefPtr<CefV8Value> GetGlobal() override;
+  bool Enter() override;
+  bool Exit() override;
+  bool IsSame(CefRefPtr<CefV8Context> that) override;
   bool Eval(const CefString& code,
             const CefString& script_url,
             int start_line,
             CefRefPtr<CefV8Value>& retval,
-            CefRefPtr<CefV8Exception>& exception) OVERRIDE;
+            CefRefPtr<CefV8Exception>& exception) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_V8CONTEXT_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/v8exception_ctocpp.cc b/src/libcef_dll/ctocpp/v8exception_ctocpp.cc
index 6f18a3c..af6b345 100644
--- a/src/libcef_dll/ctocpp/v8exception_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/v8exception_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0a09365e00f932df7d9beba64b1aa772b1a06998$
+// $hash=a1a9c4ad40c25c80390f0168261569c1b2141e86$
 //
 
 #include "libcef_dll/ctocpp/v8exception_ctocpp.h"
@@ -18,8 +18,9 @@
 
 NO_SANITIZE("cfi-icall") CefString CefV8ExceptionCToCpp::GetMessage() {
   cef_v8exception_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_message))
+  if (CEF_MEMBER_MISSING(_struct, get_message)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -34,8 +35,9 @@
 
 NO_SANITIZE("cfi-icall") CefString CefV8ExceptionCToCpp::GetSourceLine() {
   cef_v8exception_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_source_line))
+  if (CEF_MEMBER_MISSING(_struct, get_source_line)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -51,8 +53,9 @@
 NO_SANITIZE("cfi-icall")
 CefString CefV8ExceptionCToCpp::GetScriptResourceName() {
   cef_v8exception_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_script_resource_name))
+  if (CEF_MEMBER_MISSING(_struct, get_script_resource_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -67,8 +70,9 @@
 
 NO_SANITIZE("cfi-icall") int CefV8ExceptionCToCpp::GetLineNumber() {
   cef_v8exception_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_line_number))
+  if (CEF_MEMBER_MISSING(_struct, get_line_number)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -81,8 +85,9 @@
 
 NO_SANITIZE("cfi-icall") int CefV8ExceptionCToCpp::GetStartPosition() {
   cef_v8exception_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_start_position))
+  if (CEF_MEMBER_MISSING(_struct, get_start_position)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -95,8 +100,9 @@
 
 NO_SANITIZE("cfi-icall") int CefV8ExceptionCToCpp::GetEndPosition() {
   cef_v8exception_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_end_position))
+  if (CEF_MEMBER_MISSING(_struct, get_end_position)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -109,8 +115,9 @@
 
 NO_SANITIZE("cfi-icall") int CefV8ExceptionCToCpp::GetStartColumn() {
   cef_v8exception_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_start_column))
+  if (CEF_MEMBER_MISSING(_struct, get_start_column)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -123,8 +130,9 @@
 
 NO_SANITIZE("cfi-icall") int CefV8ExceptionCToCpp::GetEndColumn() {
   cef_v8exception_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_end_column))
+  if (CEF_MEMBER_MISSING(_struct, get_end_column)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -147,7 +155,7 @@
 cef_v8exception_t*
 CefCToCppRefCounted<CefV8ExceptionCToCpp, CefV8Exception, cef_v8exception_t>::
     UnwrapDerived(CefWrapperType type, CefV8Exception* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/v8exception_ctocpp.h b/src/libcef_dll/ctocpp/v8exception_ctocpp.h
index 4c79567..0256b62 100644
--- a/src/libcef_dll/ctocpp/v8exception_ctocpp.h
+++ b/src/libcef_dll/ctocpp/v8exception_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d5fbe63e64a74c8217af3d551f65a85ded5214fd$
+// $hash=ed15db160fa19964fe5c9902c279fa1b44bd0dbe$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_V8EXCEPTION_CTOCPP_H_
@@ -34,14 +34,14 @@
   virtual ~CefV8ExceptionCToCpp();
 
   // CefV8Exception methods.
-  CefString GetMessage() OVERRIDE;
-  CefString GetSourceLine() OVERRIDE;
-  CefString GetScriptResourceName() OVERRIDE;
-  int GetLineNumber() OVERRIDE;
-  int GetStartPosition() OVERRIDE;
-  int GetEndPosition() OVERRIDE;
-  int GetStartColumn() OVERRIDE;
-  int GetEndColumn() OVERRIDE;
+  CefString GetMessage() override;
+  CefString GetSourceLine() override;
+  CefString GetScriptResourceName() override;
+  int GetLineNumber() override;
+  int GetStartPosition() override;
+  int GetEndPosition() override;
+  int GetStartColumn() override;
+  int GetEndColumn() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_V8EXCEPTION_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/v8handler_ctocpp.cc b/src/libcef_dll/ctocpp/v8handler_ctocpp.cc
index 7566f77..6260c1b 100644
--- a/src/libcef_dll/ctocpp/v8handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/v8handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=271072f761428ca4b308b0ee5418148f11126c27$
+// $hash=4a30d78ab05a200e8d93b9e8da2c4cb3a8ff4acd$
 //
 
 #include "libcef_dll/ctocpp/v8handler_ctocpp.h"
@@ -24,19 +24,22 @@
                                  CefRefPtr<CefV8Value>& retval,
                                  CefString& exception) {
   cef_v8handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, execute))
+  if (CEF_MEMBER_MISSING(_struct, execute)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return false;
+  }
   // Verify param: object; type: refptr_diff
   DCHECK(object.get());
-  if (!object.get())
+  if (!object.get()) {
     return false;
+  }
 
   // Translate param: arguments; type: refptr_vec_diff_byref_const
   const size_t argumentsCount = arguments.size();
@@ -52,8 +55,9 @@
   }
   // Translate param: retval; type: refptr_diff_byref
   cef_v8value_t* retvalStruct = NULL;
-  if (retval.get())
+  if (retval.get()) {
     retvalStruct = CefV8ValueCppToC::Wrap(retval);
+  }
   cef_v8value_t* retvalOrig = retvalStruct;
 
   // Execute
@@ -62,8 +66,9 @@
       argumentsList, &retvalStruct, exception.GetWritableStruct());
 
   // Restore param:arguments; type: refptr_vec_diff_byref_const
-  if (argumentsList)
+  if (argumentsList) {
     delete[] argumentsList;
+  }
   // Restore param:retval; type: refptr_diff_byref
   if (retvalStruct) {
     if (retvalStruct != retvalOrig) {
@@ -89,7 +94,7 @@
 cef_v8handler_t*
 CefCToCppRefCounted<CefV8HandlerCToCpp, CefV8Handler, cef_v8handler_t>::
     UnwrapDerived(CefWrapperType type, CefV8Handler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/v8handler_ctocpp.h b/src/libcef_dll/ctocpp/v8handler_ctocpp.h
index fea2184..cd5a0e4 100644
--- a/src/libcef_dll/ctocpp/v8handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/v8handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=49e06b49baadb1a40c4b5602d9b97c969614c31e$
+// $hash=442444a8b361b3ce3f599181fe8057d175e1cc20$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_V8HANDLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/v8interceptor_ctocpp.cc b/src/libcef_dll/ctocpp/v8interceptor_ctocpp.cc
index 8d130cb..37dd493 100644
--- a/src/libcef_dll/ctocpp/v8interceptor_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/v8interceptor_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=03d79fc410f4c1f268f34abf0e13483fe4c62172$
+// $hash=49e110abc14cd4c30a1a7aec0157285d3e886a84$
 //
 
 #include "libcef_dll/ctocpp/v8interceptor_ctocpp.h"
@@ -23,24 +23,28 @@
                                  CefRefPtr<CefV8Value>& retval,
                                  CefString& exception) {
   cef_v8interceptor_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_byname))
+  if (CEF_MEMBER_MISSING(_struct, get_byname)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return false;
+  }
   // Verify param: object; type: refptr_diff
   DCHECK(object.get());
-  if (!object.get())
+  if (!object.get()) {
     return false;
+  }
 
   // Translate param: retval; type: refptr_diff_byref
   cef_v8value_t* retvalStruct = NULL;
-  if (retval.get())
+  if (retval.get()) {
     retvalStruct = CefV8ValueCppToC::Wrap(retval);
+  }
   cef_v8value_t* retvalOrig = retvalStruct;
 
   // Execute
@@ -67,24 +71,28 @@
                                  CefRefPtr<CefV8Value>& retval,
                                  CefString& exception) {
   cef_v8interceptor_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_byindex))
+  if (CEF_MEMBER_MISSING(_struct, get_byindex)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return false;
+  }
   // Verify param: object; type: refptr_diff
   DCHECK(object.get());
-  if (!object.get())
+  if (!object.get()) {
     return false;
+  }
 
   // Translate param: retval; type: refptr_diff_byref
   cef_v8value_t* retvalStruct = NULL;
-  if (retval.get())
+  if (retval.get()) {
     retvalStruct = CefV8ValueCppToC::Wrap(retval);
+  }
   cef_v8value_t* retvalOrig = retvalStruct;
 
   // Execute
@@ -111,23 +119,27 @@
                                  const CefRefPtr<CefV8Value> value,
                                  CefString& exception) {
   cef_v8interceptor_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_byname))
+  if (CEF_MEMBER_MISSING(_struct, set_byname)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return false;
+  }
   // Verify param: object; type: refptr_diff
   DCHECK(object.get());
-  if (!object.get())
+  if (!object.get()) {
     return false;
+  }
   // Verify param: value; type: refptr_diff
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_byname(
@@ -144,23 +156,27 @@
                                  const CefRefPtr<CefV8Value> value,
                                  CefString& exception) {
   cef_v8interceptor_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_byindex))
+  if (CEF_MEMBER_MISSING(_struct, set_byindex)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return false;
+  }
   // Verify param: object; type: refptr_diff
   DCHECK(object.get());
-  if (!object.get())
+  if (!object.get()) {
     return false;
+  }
   // Verify param: value; type: refptr_diff
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_byindex(
@@ -185,7 +201,7 @@
                     CefV8Interceptor,
                     cef_v8interceptor_t>::UnwrapDerived(CefWrapperType type,
                                                         CefV8Interceptor* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/v8interceptor_ctocpp.h b/src/libcef_dll/ctocpp/v8interceptor_ctocpp.h
index 992ea73..de862c1 100644
--- a/src/libcef_dll/ctocpp/v8interceptor_ctocpp.h
+++ b/src/libcef_dll/ctocpp/v8interceptor_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=78ea48543b579b38c382062d0912e4aac70e0603$
+// $hash=11fbbb5b1de3f96d332ec3653780826677ffcdf2$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_V8INTERCEPTOR_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/v8stack_frame_ctocpp.cc b/src/libcef_dll/ctocpp/v8stack_frame_ctocpp.cc
index d1a0357..2311cac 100644
--- a/src/libcef_dll/ctocpp/v8stack_frame_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/v8stack_frame_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=251396f9d749a62b14644a314fbeb5e31505420d$
+// $hash=8883a3a31a9a48371dcc5b35ea7820a52f105bf1$
 //
 
 #include "libcef_dll/ctocpp/v8stack_frame_ctocpp.h"
@@ -18,8 +18,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8StackFrameCToCpp::IsValid() {
   cef_v8stack_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -32,8 +33,9 @@
 
 NO_SANITIZE("cfi-icall") CefString CefV8StackFrameCToCpp::GetScriptName() {
   cef_v8stack_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_script_name))
+  if (CEF_MEMBER_MISSING(_struct, get_script_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -49,8 +51,9 @@
 NO_SANITIZE("cfi-icall")
 CefString CefV8StackFrameCToCpp::GetScriptNameOrSourceURL() {
   cef_v8stack_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_script_name_or_source_url))
+  if (CEF_MEMBER_MISSING(_struct, get_script_name_or_source_url)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -66,8 +69,9 @@
 
 NO_SANITIZE("cfi-icall") CefString CefV8StackFrameCToCpp::GetFunctionName() {
   cef_v8stack_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_function_name))
+  if (CEF_MEMBER_MISSING(_struct, get_function_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -82,8 +86,9 @@
 
 NO_SANITIZE("cfi-icall") int CefV8StackFrameCToCpp::GetLineNumber() {
   cef_v8stack_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_line_number))
+  if (CEF_MEMBER_MISSING(_struct, get_line_number)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -96,8 +101,9 @@
 
 NO_SANITIZE("cfi-icall") int CefV8StackFrameCToCpp::GetColumn() {
   cef_v8stack_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_column))
+  if (CEF_MEMBER_MISSING(_struct, get_column)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -110,8 +116,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8StackFrameCToCpp::IsEval() {
   cef_v8stack_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_eval))
+  if (CEF_MEMBER_MISSING(_struct, is_eval)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -124,8 +131,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8StackFrameCToCpp::IsConstructor() {
   cef_v8stack_frame_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_constructor))
+  if (CEF_MEMBER_MISSING(_struct, is_constructor)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -150,7 +158,7 @@
                     CefV8StackFrame,
                     cef_v8stack_frame_t>::UnwrapDerived(CefWrapperType type,
                                                         CefV8StackFrame* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/v8stack_frame_ctocpp.h b/src/libcef_dll/ctocpp/v8stack_frame_ctocpp.h
index 1956de5..474cd1a 100644
--- a/src/libcef_dll/ctocpp/v8stack_frame_ctocpp.h
+++ b/src/libcef_dll/ctocpp/v8stack_frame_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=a3706e4e68205837e899ac8ad5ee03094576d31d$
+// $hash=366d110fdfaf3d241c26e9ec276f7c363ecd313f$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_V8STACK_FRAME_CTOCPP_H_
@@ -34,14 +34,14 @@
   virtual ~CefV8StackFrameCToCpp();
 
   // CefV8StackFrame methods.
-  bool IsValid() OVERRIDE;
-  CefString GetScriptName() OVERRIDE;
-  CefString GetScriptNameOrSourceURL() OVERRIDE;
-  CefString GetFunctionName() OVERRIDE;
-  int GetLineNumber() OVERRIDE;
-  int GetColumn() OVERRIDE;
-  bool IsEval() OVERRIDE;
-  bool IsConstructor() OVERRIDE;
+  bool IsValid() override;
+  CefString GetScriptName() override;
+  CefString GetScriptNameOrSourceURL() override;
+  CefString GetFunctionName() override;
+  int GetLineNumber() override;
+  int GetColumn() override;
+  bool IsEval() override;
+  bool IsConstructor() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_V8STACK_FRAME_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/v8stack_trace_ctocpp.cc b/src/libcef_dll/ctocpp/v8stack_trace_ctocpp.cc
index c400835..0198dcc 100644
--- a/src/libcef_dll/ctocpp/v8stack_trace_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/v8stack_trace_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e8c1ba613fd96ac7872f84e15bf560350f957ec4$
+// $hash=f35d094b71513d6d1201e53eda87148b415d286d$
 //
 
 #include "libcef_dll/ctocpp/v8stack_trace_ctocpp.h"
@@ -37,8 +37,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_v8stack_trace_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -53,8 +54,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_v8stack_trace_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_frame_count))
+  if (CEF_MEMBER_MISSING(_struct, get_frame_count)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -70,8 +72,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_v8stack_trace_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_frame))
+  if (CEF_MEMBER_MISSING(_struct, get_frame)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -98,7 +101,7 @@
                     CefV8StackTrace,
                     cef_v8stack_trace_t>::UnwrapDerived(CefWrapperType type,
                                                         CefV8StackTrace* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/v8stack_trace_ctocpp.h b/src/libcef_dll/ctocpp/v8stack_trace_ctocpp.h
index 2670c51..1e076ac 100644
--- a/src/libcef_dll/ctocpp/v8stack_trace_ctocpp.h
+++ b/src/libcef_dll/ctocpp/v8stack_trace_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6f3af4b8ac1a836e8ce76a60e86ad39fa79dbbc0$
+// $hash=361eefa5a258faf92d09e28787293fa29bbed742$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_V8STACK_TRACE_CTOCPP_H_
@@ -34,9 +34,9 @@
   virtual ~CefV8StackTraceCToCpp();
 
   // CefV8StackTrace methods.
-  bool IsValid() OVERRIDE;
-  int GetFrameCount() OVERRIDE;
-  CefRefPtr<CefV8StackFrame> GetFrame(int index) OVERRIDE;
+  bool IsValid() override;
+  int GetFrameCount() override;
+  CefRefPtr<CefV8StackFrame> GetFrame(int index) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_V8STACK_TRACE_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/v8value_ctocpp.cc b/src/libcef_dll/ctocpp/v8value_ctocpp.cc
index b8dc379..5474dc4 100644
--- a/src/libcef_dll/ctocpp/v8value_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/v8value_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=d50470b45303a24f4c2589ad8d629f3d273ac23f$
+// $hash=f67b0996d7e2133f3f28f2d8ba5446c5ff40aaba$
 //
 
 #include "libcef_dll/ctocpp/v8value_ctocpp.h"
@@ -56,7 +56,7 @@
 }
 
 NO_SANITIZE("cfi-icall")
-CefRefPtr<CefV8Value> CefV8Value::CreateInt(int32 value) {
+CefRefPtr<CefV8Value> CefV8Value::CreateInt(int32_t value) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
@@ -67,7 +67,7 @@
 }
 
 NO_SANITIZE("cfi-icall")
-CefRefPtr<CefV8Value> CefV8Value::CreateUInt(uint32 value) {
+CefRefPtr<CefV8Value> CefV8Value::CreateUInt(uint32_t value) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
@@ -89,11 +89,11 @@
 }
 
 NO_SANITIZE("cfi-icall")
-CefRefPtr<CefV8Value> CefV8Value::CreateDate(const CefTime& date) {
+CefRefPtr<CefV8Value> CefV8Value::CreateDate(CefBaseTime date) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  cef_v8value_t* _retval = cef_v8value_create_date(&date);
+  cef_v8value_t* _retval = cef_v8value_create_date(date);
 
   // Return type: refptr_same
   return CefV8ValueCToCpp::Wrap(_retval);
@@ -147,14 +147,12 @@
     CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
-  // Verify param: buffer; type: simple_byaddr
-  DCHECK(buffer);
-  if (!buffer)
-    return nullptr;
   // Verify param: release_callback; type: refptr_diff
   DCHECK(release_callback.get());
-  if (!release_callback.get())
+  if (!release_callback.get()) {
     return nullptr;
+  }
+  // Unverified params: buffer
 
   // Execute
   cef_v8value_t* _retval = cef_v8value_create_array_buffer(
@@ -173,12 +171,14 @@
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return nullptr;
+  }
   // Verify param: handler; type: refptr_diff
   DCHECK(handler.get());
-  if (!handler.get())
+  if (!handler.get()) {
     return nullptr;
+  }
 
   // Execute
   cef_v8value_t* _retval = cef_v8value_create_function(
@@ -188,12 +188,23 @@
   return CefV8ValueCToCpp::Wrap(_retval);
 }
 
+NO_SANITIZE("cfi-icall") CefRefPtr<CefV8Value> CefV8Value::CreatePromise() {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_v8value_t* _retval = cef_v8value_create_promise();
+
+  // Return type: refptr_same
+  return CefV8ValueCToCpp::Wrap(_retval);
+}
+
 // VIRTUAL METHODS - Body may be edited by hand.
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::IsValid() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -206,8 +217,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::IsUndefined() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_undefined))
+  if (CEF_MEMBER_MISSING(_struct, is_undefined)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -220,8 +232,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::IsNull() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_null))
+  if (CEF_MEMBER_MISSING(_struct, is_null)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -234,8 +247,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::IsBool() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_bool))
+  if (CEF_MEMBER_MISSING(_struct, is_bool)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -248,8 +262,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::IsInt() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_int))
+  if (CEF_MEMBER_MISSING(_struct, is_int)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -262,8 +277,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::IsUInt() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_uint))
+  if (CEF_MEMBER_MISSING(_struct, is_uint)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -276,8 +292,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::IsDouble() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_double))
+  if (CEF_MEMBER_MISSING(_struct, is_double)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -290,8 +307,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::IsDate() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_date))
+  if (CEF_MEMBER_MISSING(_struct, is_date)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -304,8 +322,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::IsString() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_string))
+  if (CEF_MEMBER_MISSING(_struct, is_string)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -318,8 +337,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::IsObject() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_object))
+  if (CEF_MEMBER_MISSING(_struct, is_object)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -332,8 +352,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::IsArray() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_array))
+  if (CEF_MEMBER_MISSING(_struct, is_array)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -346,8 +367,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::IsArrayBuffer() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_array_buffer))
+  if (CEF_MEMBER_MISSING(_struct, is_array_buffer)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -360,8 +382,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::IsFunction() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_function))
+  if (CEF_MEMBER_MISSING(_struct, is_function)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -372,18 +395,35 @@
   return _retval ? true : false;
 }
 
+NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::IsPromise() {
+  cef_v8value_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, is_promise)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = _struct->is_promise(_struct);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
 NO_SANITIZE("cfi-icall")
 bool CefV8ValueCToCpp::IsSame(CefRefPtr<CefV8Value> that) {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefV8ValueCToCpp::Unwrap(that));
@@ -394,8 +434,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::GetBoolValue() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_bool_value))
+  if (CEF_MEMBER_MISSING(_struct, get_bool_value)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -406,29 +447,31 @@
   return _retval ? true : false;
 }
 
-NO_SANITIZE("cfi-icall") int32 CefV8ValueCToCpp::GetIntValue() {
+NO_SANITIZE("cfi-icall") int32_t CefV8ValueCToCpp::GetIntValue() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_int_value))
+  if (CEF_MEMBER_MISSING(_struct, get_int_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int32 _retval = _struct->get_int_value(_struct);
+  int32_t _retval = _struct->get_int_value(_struct);
 
   // Return type: simple
   return _retval;
 }
 
-NO_SANITIZE("cfi-icall") uint32 CefV8ValueCToCpp::GetUIntValue() {
+NO_SANITIZE("cfi-icall") uint32_t CefV8ValueCToCpp::GetUIntValue() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_uint_value))
+  if (CEF_MEMBER_MISSING(_struct, get_uint_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  uint32 _retval = _struct->get_uint_value(_struct);
+  uint32_t _retval = _struct->get_uint_value(_struct);
 
   // Return type: simple
   return _retval;
@@ -436,8 +479,9 @@
 
 NO_SANITIZE("cfi-icall") double CefV8ValueCToCpp::GetDoubleValue() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_double_value))
+  if (CEF_MEMBER_MISSING(_struct, get_double_value)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -448,15 +492,16 @@
   return _retval;
 }
 
-NO_SANITIZE("cfi-icall") CefTime CefV8ValueCToCpp::GetDateValue() {
+NO_SANITIZE("cfi-icall") CefBaseTime CefV8ValueCToCpp::GetDateValue() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_date_value))
-    return CefTime();
+  if (CEF_MEMBER_MISSING(_struct, get_date_value)) {
+    return CefBaseTime();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  cef_time_t _retval = _struct->get_date_value(_struct);
+  cef_basetime_t _retval = _struct->get_date_value(_struct);
 
   // Return type: simple
   return _retval;
@@ -464,8 +509,9 @@
 
 NO_SANITIZE("cfi-icall") CefString CefV8ValueCToCpp::GetStringValue() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_string_value))
+  if (CEF_MEMBER_MISSING(_struct, get_string_value)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -480,8 +526,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::IsUserCreated() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_user_created))
+  if (CEF_MEMBER_MISSING(_struct, is_user_created)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -494,8 +541,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::HasException() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_exception))
+  if (CEF_MEMBER_MISSING(_struct, has_exception)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -509,8 +557,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefV8Exception> CefV8ValueCToCpp::GetException() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_exception))
+  if (CEF_MEMBER_MISSING(_struct, get_exception)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -523,8 +572,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::ClearException() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, clear_exception))
+  if (CEF_MEMBER_MISSING(_struct, clear_exception)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -537,8 +587,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::WillRethrowExceptions() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, will_rethrow_exceptions))
+  if (CEF_MEMBER_MISSING(_struct, will_rethrow_exceptions)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -552,8 +603,9 @@
 NO_SANITIZE("cfi-icall")
 bool CefV8ValueCToCpp::SetRethrowExceptions(bool rethrow) {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_rethrow_exceptions))
+  if (CEF_MEMBER_MISSING(_struct, set_rethrow_exceptions)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -566,8 +618,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::HasValue(const CefString& key) {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_value_bykey))
+  if (CEF_MEMBER_MISSING(_struct, has_value_bykey)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -582,15 +635,17 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::HasValue(int index) {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_value_byindex))
+  if (CEF_MEMBER_MISSING(_struct, has_value_byindex)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->has_value_byindex(_struct, index);
@@ -602,8 +657,9 @@
 NO_SANITIZE("cfi-icall")
 bool CefV8ValueCToCpp::DeleteValue(const CefString& key) {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, delete_value_bykey))
+  if (CEF_MEMBER_MISSING(_struct, delete_value_bykey)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -618,15 +674,17 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::DeleteValue(int index) {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, delete_value_byindex))
+  if (CEF_MEMBER_MISSING(_struct, delete_value_byindex)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->delete_value_byindex(_struct, index);
@@ -638,8 +696,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefV8Value> CefV8ValueCToCpp::GetValue(const CefString& key) {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_value_bykey))
+  if (CEF_MEMBER_MISSING(_struct, get_value_bykey)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -655,15 +714,17 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefV8Value> CefV8ValueCToCpp::GetValue(int index) {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_value_byindex))
+  if (CEF_MEMBER_MISSING(_struct, get_value_byindex)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return nullptr;
+  }
 
   // Execute
   cef_v8value_t* _retval = _struct->get_value_byindex(_struct, index);
@@ -677,15 +738,17 @@
                                 CefRefPtr<CefV8Value> value,
                                 PropertyAttribute attribute) {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_value_bykey))
+  if (CEF_MEMBER_MISSING(_struct, set_value_bykey)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: value; type: refptr_same
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return false;
+  }
   // Unverified params: key
 
   // Execute
@@ -699,19 +762,22 @@
 NO_SANITIZE("cfi-icall")
 bool CefV8ValueCToCpp::SetValue(int index, CefRefPtr<CefV8Value> value) {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_value_byindex))
+  if (CEF_MEMBER_MISSING(_struct, set_value_byindex)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return false;
+  }
   // Verify param: value; type: refptr_same
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_value_byindex(_struct, index,
@@ -726,8 +792,9 @@
                                 AccessControl settings,
                                 PropertyAttribute attribute) {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_value_byaccessor))
+  if (CEF_MEMBER_MISSING(_struct, set_value_byaccessor)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -744,16 +811,18 @@
 NO_SANITIZE("cfi-icall")
 bool CefV8ValueCToCpp::GetKeys(std::vector<CefString>& keys) {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_keys))
+  if (CEF_MEMBER_MISSING(_struct, get_keys)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: keys; type: string_vec_byref
   cef_string_list_t keysList = cef_string_list_alloc();
   DCHECK(keysList);
-  if (keysList)
+  if (keysList) {
     transfer_string_list_contents(keys, keysList);
+  }
 
   // Execute
   int _retval = _struct->get_keys(_struct, keysList);
@@ -772,8 +841,9 @@
 NO_SANITIZE("cfi-icall")
 bool CefV8ValueCToCpp::SetUserData(CefRefPtr<CefBaseRefCounted> user_data) {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_user_data))
+  if (CEF_MEMBER_MISSING(_struct, set_user_data)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -790,8 +860,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefBaseRefCounted> CefV8ValueCToCpp::GetUserData() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_user_data))
+  if (CEF_MEMBER_MISSING(_struct, get_user_data)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -804,8 +875,9 @@
 
 NO_SANITIZE("cfi-icall") int CefV8ValueCToCpp::GetExternallyAllocatedMemory() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_externally_allocated_memory))
+  if (CEF_MEMBER_MISSING(_struct, get_externally_allocated_memory)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -819,8 +891,9 @@
 NO_SANITIZE("cfi-icall")
 int CefV8ValueCToCpp::AdjustExternallyAllocatedMemory(int change_in_bytes) {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, adjust_externally_allocated_memory))
+  if (CEF_MEMBER_MISSING(_struct, adjust_externally_allocated_memory)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -834,8 +907,9 @@
 
 NO_SANITIZE("cfi-icall") int CefV8ValueCToCpp::GetArrayLength() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_array_length))
+  if (CEF_MEMBER_MISSING(_struct, get_array_length)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -850,8 +924,9 @@
 CefRefPtr<CefV8ArrayBufferReleaseCallback>
 CefV8ValueCToCpp::GetArrayBufferReleaseCallback() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_array_buffer_release_callback))
+  if (CEF_MEMBER_MISSING(_struct, get_array_buffer_release_callback)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -865,8 +940,9 @@
 
 NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::NeuterArrayBuffer() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, neuter_array_buffer))
+  if (CEF_MEMBER_MISSING(_struct, neuter_array_buffer)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -877,10 +953,42 @@
   return _retval ? true : false;
 }
 
+NO_SANITIZE("cfi-icall") size_t CefV8ValueCToCpp::GetArrayBufferByteLength() {
+  cef_v8value_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_array_buffer_byte_length)) {
+    return 0;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  size_t _retval = _struct->get_array_buffer_byte_length(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall") void* CefV8ValueCToCpp::GetArrayBufferData() {
+  cef_v8value_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_array_buffer_data)) {
+    return nullptr;
+  }
+
+  // This manual implementation can be removed once support for 'void*'
+  // is integrated into the CEF translator tool (issue #3591).
+
+  // Execute
+  void* _retval = _struct->get_array_buffer_data(_struct);
+
+  // Return type: simple_byaddr
+  return _retval;
+}
+
 NO_SANITIZE("cfi-icall") CefString CefV8ValueCToCpp::GetFunctionName() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_function_name))
+  if (CEF_MEMBER_MISSING(_struct, get_function_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -896,8 +1004,9 @@
 NO_SANITIZE("cfi-icall")
 CefRefPtr<CefV8Handler> CefV8ValueCToCpp::GetFunctionHandler() {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_function_handler))
+  if (CEF_MEMBER_MISSING(_struct, get_function_handler)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -913,8 +1022,9 @@
     CefRefPtr<CefV8Value> object,
     const CefV8ValueList& arguments) {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, execute_function))
+  if (CEF_MEMBER_MISSING(_struct, execute_function)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -938,8 +1048,9 @@
       _struct, CefV8ValueCToCpp::Unwrap(object), argumentsCount, argumentsList);
 
   // Restore param:arguments; type: refptr_vec_same_byref_const
-  if (argumentsList)
+  if (argumentsList) {
     delete[] argumentsList;
+  }
 
   // Return type: refptr_same
   return CefV8ValueCToCpp::Wrap(_retval);
@@ -951,15 +1062,17 @@
     CefRefPtr<CefV8Value> object,
     const CefV8ValueList& arguments) {
   cef_v8value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, execute_function_with_context))
+  if (CEF_MEMBER_MISSING(_struct, execute_function_with_context)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: context; type: refptr_same
   DCHECK(context.get());
-  if (!context.get())
+  if (!context.get()) {
     return nullptr;
+  }
   // Unverified params: object
 
   // Translate param: arguments; type: refptr_vec_same_byref_const
@@ -981,13 +1094,55 @@
       CefV8ValueCToCpp::Unwrap(object), argumentsCount, argumentsList);
 
   // Restore param:arguments; type: refptr_vec_same_byref_const
-  if (argumentsList)
+  if (argumentsList) {
     delete[] argumentsList;
+  }
 
   // Return type: refptr_same
   return CefV8ValueCToCpp::Wrap(_retval);
 }
 
+NO_SANITIZE("cfi-icall")
+bool CefV8ValueCToCpp::ResolvePromise(CefRefPtr<CefV8Value> arg) {
+  cef_v8value_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, resolve_promise)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Unverified params: arg
+
+  // Execute
+  int _retval =
+      _struct->resolve_promise(_struct, CefV8ValueCToCpp::Unwrap(arg));
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefV8ValueCToCpp::RejectPromise(const CefString& errorMsg) {
+  cef_v8value_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, reject_promise)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: errorMsg; type: string_byref_const
+  DCHECK(!errorMsg.empty());
+  if (errorMsg.empty()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->reject_promise(_struct, errorMsg.GetStruct());
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
 // CONSTRUCTOR - Do not edit by hand.
 
 CefV8ValueCToCpp::CefV8ValueCToCpp() {}
@@ -1001,7 +1156,7 @@
 CefCToCppRefCounted<CefV8ValueCToCpp, CefV8Value, cef_v8value_t>::UnwrapDerived(
     CefWrapperType type,
     CefV8Value* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/v8value_ctocpp.h b/src/libcef_dll/ctocpp/v8value_ctocpp.h
index 7ad13d7..dd0fb6e 100644
--- a/src/libcef_dll/ctocpp/v8value_ctocpp.h
+++ b/src/libcef_dll/ctocpp/v8value_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1173914ff14a10ab522cdaa4eb99a2774fabfb21$
+// $hash=c81cc0910be6678c0512c5423b8fc5dc1df42743$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_V8VALUE_CTOCPP_H_
@@ -34,63 +34,68 @@
   virtual ~CefV8ValueCToCpp();
 
   // CefV8Value methods.
-  bool IsValid() OVERRIDE;
-  bool IsUndefined() OVERRIDE;
-  bool IsNull() OVERRIDE;
-  bool IsBool() OVERRIDE;
-  bool IsInt() OVERRIDE;
-  bool IsUInt() OVERRIDE;
-  bool IsDouble() OVERRIDE;
-  bool IsDate() OVERRIDE;
-  bool IsString() OVERRIDE;
-  bool IsObject() OVERRIDE;
-  bool IsArray() OVERRIDE;
-  bool IsArrayBuffer() OVERRIDE;
-  bool IsFunction() OVERRIDE;
-  bool IsSame(CefRefPtr<CefV8Value> that) OVERRIDE;
-  bool GetBoolValue() OVERRIDE;
-  int32 GetIntValue() OVERRIDE;
-  uint32 GetUIntValue() OVERRIDE;
-  double GetDoubleValue() OVERRIDE;
-  CefTime GetDateValue() OVERRIDE;
-  CefString GetStringValue() OVERRIDE;
-  bool IsUserCreated() OVERRIDE;
-  bool HasException() OVERRIDE;
-  CefRefPtr<CefV8Exception> GetException() OVERRIDE;
-  bool ClearException() OVERRIDE;
-  bool WillRethrowExceptions() OVERRIDE;
-  bool SetRethrowExceptions(bool rethrow) OVERRIDE;
-  bool HasValue(const CefString& key) OVERRIDE;
-  bool HasValue(int index) OVERRIDE;
-  bool DeleteValue(const CefString& key) OVERRIDE;
-  bool DeleteValue(int index) OVERRIDE;
-  CefRefPtr<CefV8Value> GetValue(const CefString& key) OVERRIDE;
-  CefRefPtr<CefV8Value> GetValue(int index) OVERRIDE;
+  bool IsValid() override;
+  bool IsUndefined() override;
+  bool IsNull() override;
+  bool IsBool() override;
+  bool IsInt() override;
+  bool IsUInt() override;
+  bool IsDouble() override;
+  bool IsDate() override;
+  bool IsString() override;
+  bool IsObject() override;
+  bool IsArray() override;
+  bool IsArrayBuffer() override;
+  bool IsFunction() override;
+  bool IsPromise() override;
+  bool IsSame(CefRefPtr<CefV8Value> that) override;
+  bool GetBoolValue() override;
+  int32_t GetIntValue() override;
+  uint32_t GetUIntValue() override;
+  double GetDoubleValue() override;
+  CefBaseTime GetDateValue() override;
+  CefString GetStringValue() override;
+  bool IsUserCreated() override;
+  bool HasException() override;
+  CefRefPtr<CefV8Exception> GetException() override;
+  bool ClearException() override;
+  bool WillRethrowExceptions() override;
+  bool SetRethrowExceptions(bool rethrow) override;
+  bool HasValue(const CefString& key) override;
+  bool HasValue(int index) override;
+  bool DeleteValue(const CefString& key) override;
+  bool DeleteValue(int index) override;
+  CefRefPtr<CefV8Value> GetValue(const CefString& key) override;
+  CefRefPtr<CefV8Value> GetValue(int index) override;
   bool SetValue(const CefString& key,
                 CefRefPtr<CefV8Value> value,
-                PropertyAttribute attribute) OVERRIDE;
-  bool SetValue(int index, CefRefPtr<CefV8Value> value) OVERRIDE;
+                PropertyAttribute attribute) override;
+  bool SetValue(int index, CefRefPtr<CefV8Value> value) override;
   bool SetValue(const CefString& key,
                 AccessControl settings,
-                PropertyAttribute attribute) OVERRIDE;
-  bool GetKeys(std::vector<CefString>& keys) OVERRIDE;
-  bool SetUserData(CefRefPtr<CefBaseRefCounted> user_data) OVERRIDE;
-  CefRefPtr<CefBaseRefCounted> GetUserData() OVERRIDE;
-  int GetExternallyAllocatedMemory() OVERRIDE;
-  int AdjustExternallyAllocatedMemory(int change_in_bytes) OVERRIDE;
-  int GetArrayLength() OVERRIDE;
+                PropertyAttribute attribute) override;
+  bool GetKeys(std::vector<CefString>& keys) override;
+  bool SetUserData(CefRefPtr<CefBaseRefCounted> user_data) override;
+  CefRefPtr<CefBaseRefCounted> GetUserData() override;
+  int GetExternallyAllocatedMemory() override;
+  int AdjustExternallyAllocatedMemory(int change_in_bytes) override;
+  int GetArrayLength() override;
   CefRefPtr<CefV8ArrayBufferReleaseCallback> GetArrayBufferReleaseCallback()
-      OVERRIDE;
-  bool NeuterArrayBuffer() OVERRIDE;
-  CefString GetFunctionName() OVERRIDE;
-  CefRefPtr<CefV8Handler> GetFunctionHandler() OVERRIDE;
+      override;
+  bool NeuterArrayBuffer() override;
+  size_t GetArrayBufferByteLength() override;
+  void* GetArrayBufferData() override;
+  CefString GetFunctionName() override;
+  CefRefPtr<CefV8Handler> GetFunctionHandler() override;
   CefRefPtr<CefV8Value> ExecuteFunction(
       CefRefPtr<CefV8Value> object,
-      const CefV8ValueList& arguments) OVERRIDE;
+      const CefV8ValueList& arguments) override;
   CefRefPtr<CefV8Value> ExecuteFunctionWithContext(
       CefRefPtr<CefV8Context> context,
       CefRefPtr<CefV8Value> object,
-      const CefV8ValueList& arguments) OVERRIDE;
+      const CefV8ValueList& arguments) override;
+  bool ResolvePromise(CefRefPtr<CefV8Value> arg) override;
+  bool RejectPromise(const CefString& errorMsg) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_V8VALUE_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/value_ctocpp.cc b/src/libcef_dll/ctocpp/value_ctocpp.cc
index b03a989..33432f4 100644
--- a/src/libcef_dll/ctocpp/value_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/value_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7711f5c2b432b11bf4ab1d194c09a1cb7a8fcd05$
+// $hash=9e6bc91e58ee92cf2c2b855d0eea2a0db0743e4a$
 //
 
 #include "libcef_dll/ctocpp/value_ctocpp.h"
@@ -38,8 +38,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -54,8 +55,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_owned))
+  if (CEF_MEMBER_MISSING(_struct, is_owned)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -70,8 +72,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_read_only))
+  if (CEF_MEMBER_MISSING(_struct, is_read_only)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -86,15 +89,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefValueCToCpp::Unwrap(that));
@@ -108,15 +113,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_equal))
+  if (CEF_MEMBER_MISSING(_struct, is_equal)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_equal(_struct, CefValueCToCpp::Unwrap(that));
@@ -129,8 +136,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, copy))
+  if (CEF_MEMBER_MISSING(_struct, copy)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -145,8 +153,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_type))
+  if (CEF_MEMBER_MISSING(_struct, get_type)) {
     return VTYPE_INVALID;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -161,8 +170,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_bool))
+  if (CEF_MEMBER_MISSING(_struct, get_bool)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -177,8 +187,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_int))
+  if (CEF_MEMBER_MISSING(_struct, get_int)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -193,8 +204,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_double))
+  if (CEF_MEMBER_MISSING(_struct, get_double)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -209,8 +221,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_string))
+  if (CEF_MEMBER_MISSING(_struct, get_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -227,8 +240,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_binary))
+  if (CEF_MEMBER_MISSING(_struct, get_binary)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -244,8 +258,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_dictionary))
+  if (CEF_MEMBER_MISSING(_struct, get_dictionary)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -260,8 +275,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_list))
+  if (CEF_MEMBER_MISSING(_struct, get_list)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -276,8 +292,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_null))
+  if (CEF_MEMBER_MISSING(_struct, set_null)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -292,8 +309,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_bool))
+  if (CEF_MEMBER_MISSING(_struct, set_bool)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -308,8 +326,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_int))
+  if (CEF_MEMBER_MISSING(_struct, set_int)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -324,8 +343,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_double))
+  if (CEF_MEMBER_MISSING(_struct, set_double)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -341,8 +361,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_string))
+  if (CEF_MEMBER_MISSING(_struct, set_string)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -360,15 +381,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_binary))
+  if (CEF_MEMBER_MISSING(_struct, set_binary)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: value; type: refptr_same
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -383,15 +406,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_dictionary))
+  if (CEF_MEMBER_MISSING(_struct, set_dictionary)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: value; type: refptr_same
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -406,15 +431,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_value_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_list))
+  if (CEF_MEMBER_MISSING(_struct, set_list)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: value; type: refptr_same
   DCHECK(value.get());
-  if (!value.get())
+  if (!value.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->set_list(_struct, CefListValueCToCpp::Unwrap(value));
@@ -438,7 +465,7 @@
 CefCToCppRefCounted<CefValueCToCpp, CefValue, cef_value_t>::UnwrapDerived(
     CefWrapperType type,
     CefValue* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/value_ctocpp.h b/src/libcef_dll/ctocpp/value_ctocpp.h
index 6c757ef..9b31150 100644
--- a/src/libcef_dll/ctocpp/value_ctocpp.h
+++ b/src/libcef_dll/ctocpp/value_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=f72dd0d0687b5b7626b651a298a5ed017686e649$
+// $hash=80621c9fcd1e112984ddb490da40034e9731d530$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VALUE_CTOCPP_H_
@@ -33,28 +33,28 @@
   virtual ~CefValueCToCpp();
 
   // CefValue methods.
-  bool IsValid() OVERRIDE;
-  bool IsOwned() OVERRIDE;
-  bool IsReadOnly() OVERRIDE;
-  bool IsSame(CefRefPtr<CefValue> that) OVERRIDE;
-  bool IsEqual(CefRefPtr<CefValue> that) OVERRIDE;
-  CefRefPtr<CefValue> Copy() OVERRIDE;
-  CefValueType GetType() OVERRIDE;
-  bool GetBool() OVERRIDE;
-  int GetInt() OVERRIDE;
-  double GetDouble() OVERRIDE;
-  CefString GetString() OVERRIDE;
-  CefRefPtr<CefBinaryValue> GetBinary() OVERRIDE;
-  CefRefPtr<CefDictionaryValue> GetDictionary() OVERRIDE;
-  CefRefPtr<CefListValue> GetList() OVERRIDE;
-  bool SetNull() OVERRIDE;
-  bool SetBool(bool value) OVERRIDE;
-  bool SetInt(int value) OVERRIDE;
-  bool SetDouble(double value) OVERRIDE;
-  bool SetString(const CefString& value) OVERRIDE;
-  bool SetBinary(CefRefPtr<CefBinaryValue> value) OVERRIDE;
-  bool SetDictionary(CefRefPtr<CefDictionaryValue> value) OVERRIDE;
-  bool SetList(CefRefPtr<CefListValue> value) OVERRIDE;
+  bool IsValid() override;
+  bool IsOwned() override;
+  bool IsReadOnly() override;
+  bool IsSame(CefRefPtr<CefValue> that) override;
+  bool IsEqual(CefRefPtr<CefValue> that) override;
+  CefRefPtr<CefValue> Copy() override;
+  CefValueType GetType() override;
+  bool GetBool() override;
+  int GetInt() override;
+  double GetDouble() override;
+  CefString GetString() override;
+  CefRefPtr<CefBinaryValue> GetBinary() override;
+  CefRefPtr<CefDictionaryValue> GetDictionary() override;
+  CefRefPtr<CefListValue> GetList() override;
+  bool SetNull() override;
+  bool SetBool(bool value) override;
+  bool SetInt(int value) override;
+  bool SetDouble(double value) override;
+  bool SetString(const CefString& value) override;
+  bool SetBinary(CefRefPtr<CefBinaryValue> value) override;
+  bool SetDictionary(CefRefPtr<CefDictionaryValue> value) override;
+  bool SetList(CefRefPtr<CefListValue> value) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_VALUE_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/views/box_layout_ctocpp.cc b/src/libcef_dll/ctocpp/views/box_layout_ctocpp.cc
index 9e046c9..ccbc6ff 100644
--- a/src/libcef_dll/ctocpp/views/box_layout_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/box_layout_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0345e3e77f8c55057284809bbfa45747ae75e777$
+// $hash=9467c10a9769147a4da5b74ea01015d8e54e9677$
 //
 
 #include "libcef_dll/ctocpp/views/box_layout_ctocpp.h"
@@ -24,15 +24,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_box_layout_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_flex_for_view))
+  if (CEF_MEMBER_MISSING(_struct, set_flex_for_view)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->set_flex_for_view(_struct, CefViewCToCpp::Unwrap(view), flex);
@@ -43,15 +45,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_box_layout_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, clear_flex_for_view))
+  if (CEF_MEMBER_MISSING(_struct, clear_flex_for_view)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->clear_flex_for_view(_struct, CefViewCToCpp::Unwrap(view));
@@ -62,8 +66,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_layout_t* _struct = reinterpret_cast<cef_layout_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_box_layout))
+  if (CEF_MEMBER_MISSING(_struct, as_box_layout)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -79,8 +84,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_layout_t* _struct = reinterpret_cast<cef_layout_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_fill_layout))
+  if (CEF_MEMBER_MISSING(_struct, as_fill_layout)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -95,8 +101,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_layout_t* _struct = reinterpret_cast<cef_layout_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -121,7 +128,7 @@
 cef_box_layout_t*
 CefCToCppRefCounted<CefBoxLayoutCToCpp, CefBoxLayout, cef_box_layout_t>::
     UnwrapDerived(CefWrapperType type, CefBoxLayout* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/box_layout_ctocpp.h b/src/libcef_dll/ctocpp/views/box_layout_ctocpp.h
index a3f0875..6639e64 100644
--- a/src/libcef_dll/ctocpp/views/box_layout_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/box_layout_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=62ff39b6f227b2d35a4324a02c5ece9128a14c7c$
+// $hash=c14b6372ec4705cdcbcebc6d7367fe0c3c544001$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_BOX_LAYOUT_CTOCPP_H_
@@ -36,13 +36,13 @@
   virtual ~CefBoxLayoutCToCpp();
 
   // CefBoxLayout methods.
-  void SetFlexForView(CefRefPtr<CefView> view, int flex) OVERRIDE;
-  void ClearFlexForView(CefRefPtr<CefView> view) OVERRIDE;
+  void SetFlexForView(CefRefPtr<CefView> view, int flex) override;
+  void ClearFlexForView(CefRefPtr<CefView> view) override;
 
   // CefLayout methods.
-  CefRefPtr<CefBoxLayout> AsBoxLayout() OVERRIDE;
-  CefRefPtr<CefFillLayout> AsFillLayout() OVERRIDE;
-  bool IsValid() OVERRIDE;
+  CefRefPtr<CefBoxLayout> AsBoxLayout() override;
+  CefRefPtr<CefFillLayout> AsFillLayout() override;
+  bool IsValid() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_VIEWS_BOX_LAYOUT_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/views/browser_view_ctocpp.cc b/src/libcef_dll/ctocpp/views/browser_view_ctocpp.cc
index 7ee8785..92fc1cb 100644
--- a/src/libcef_dll/ctocpp/views/browser_view_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/browser_view_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=cefedca66680117ea721d46e4fbbaa47fac607aa$
+// $hash=a0b2ffd53a9d1c0054348f323cfdd548cdbeca86$
 //
 
 #include "libcef_dll/ctocpp/views/browser_view_ctocpp.h"
@@ -63,8 +63,9 @@
 
   // Verify param: browser; type: refptr_same
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return nullptr;
+  }
 
   // Execute
   cef_browser_view_t* _retval =
@@ -81,8 +82,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_browser))
+  if (CEF_MEMBER_MISSING(_struct, get_browser)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -94,12 +96,31 @@
 }
 
 NO_SANITIZE("cfi-icall")
+CefRefPtr<CefView> CefBrowserViewCToCpp::GetChromeToolbar() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_browser_view_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_chrome_toolbar)) {
+    return nullptr;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_view_t* _retval = _struct->get_chrome_toolbar(_struct);
+
+  // Return type: refptr_same
+  return CefViewCToCpp::Wrap(_retval);
+}
+
+NO_SANITIZE("cfi-icall")
 void CefBrowserViewCToCpp::SetPreferAccelerators(bool prefer_accelerators) {
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_prefer_accelerators))
+  if (CEF_MEMBER_MISSING(_struct, set_prefer_accelerators)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -112,8 +133,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_browser_view))
+  if (CEF_MEMBER_MISSING(_struct, as_browser_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -128,8 +150,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_button))
+  if (CEF_MEMBER_MISSING(_struct, as_button)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -144,8 +167,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_panel))
+  if (CEF_MEMBER_MISSING(_struct, as_panel)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -161,8 +185,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_scroll_view))
+  if (CEF_MEMBER_MISSING(_struct, as_scroll_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -178,8 +203,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_textfield))
+  if (CEF_MEMBER_MISSING(_struct, as_textfield)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -194,8 +220,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_type_string))
+  if (CEF_MEMBER_MISSING(_struct, get_type_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -213,8 +240,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, to_string))
+  if (CEF_MEMBER_MISSING(_struct, to_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -231,8 +259,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -247,8 +276,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_attached))
+  if (CEF_MEMBER_MISSING(_struct, is_attached)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -264,15 +294,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefViewCToCpp::Unwrap(that));
@@ -286,8 +318,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_delegate))
+  if (CEF_MEMBER_MISSING(_struct, get_delegate)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -303,8 +336,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_window))
+  if (CEF_MEMBER_MISSING(_struct, get_window)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -319,8 +353,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_id))
+  if (CEF_MEMBER_MISSING(_struct, get_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -335,8 +370,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_id))
+  if (CEF_MEMBER_MISSING(_struct, set_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -348,8 +384,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_group_id))
+  if (CEF_MEMBER_MISSING(_struct, get_group_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -364,8 +401,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_group_id))
+  if (CEF_MEMBER_MISSING(_struct, set_group_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -378,8 +416,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_parent_view))
+  if (CEF_MEMBER_MISSING(_struct, get_parent_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -395,8 +434,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_view_for_id))
+  if (CEF_MEMBER_MISSING(_struct, get_view_for_id)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -412,8 +452,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_bounds))
+  if (CEF_MEMBER_MISSING(_struct, set_bounds)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -425,8 +466,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_bounds))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -441,8 +483,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -458,8 +501,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_size))
+  if (CEF_MEMBER_MISSING(_struct, set_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -471,8 +515,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_size))
+  if (CEF_MEMBER_MISSING(_struct, get_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -488,8 +533,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_position))
+  if (CEF_MEMBER_MISSING(_struct, set_position)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -501,8 +547,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_position))
+  if (CEF_MEMBER_MISSING(_struct, get_position)) {
     return CefPoint();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -513,12 +560,45 @@
   return _retval;
 }
 
+NO_SANITIZE("cfi-icall")
+void CefBrowserViewCToCpp::SetInsets(const CefInsets& insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, set_insets)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->set_insets(_struct, &insets);
+}
+
+NO_SANITIZE("cfi-icall") CefInsets CefBrowserViewCToCpp::GetInsets() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, get_insets)) {
+    return CefInsets();
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_insets_t _retval = _struct->get_insets(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
 NO_SANITIZE("cfi-icall") CefSize CefBrowserViewCToCpp::GetPreferredSize() {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, get_preferred_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -533,8 +613,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -546,8 +627,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_minimum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -562,8 +644,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_maximum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -579,8 +662,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_height_for_width))
+  if (CEF_MEMBER_MISSING(_struct, get_height_for_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -595,8 +679,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, invalidate_layout))
+  if (CEF_MEMBER_MISSING(_struct, invalidate_layout)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -608,8 +693,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_visible))
+  if (CEF_MEMBER_MISSING(_struct, set_visible)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -621,8 +707,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_visible))
+  if (CEF_MEMBER_MISSING(_struct, is_visible)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -637,8 +724,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_drawn))
+  if (CEF_MEMBER_MISSING(_struct, is_drawn)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -653,8 +741,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_enabled))
+  if (CEF_MEMBER_MISSING(_struct, set_enabled)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -666,8 +755,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_enabled))
+  if (CEF_MEMBER_MISSING(_struct, is_enabled)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -683,8 +773,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_focusable))
+  if (CEF_MEMBER_MISSING(_struct, set_focusable)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -696,8 +787,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -712,8 +804,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -728,8 +821,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, request_focus))
+  if (CEF_MEMBER_MISSING(_struct, request_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -742,8 +836,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_background_color))
+  if (CEF_MEMBER_MISSING(_struct, set_background_color)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -756,8 +851,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_background_color))
+  if (CEF_MEMBER_MISSING(_struct, get_background_color)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -773,8 +869,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -790,8 +887,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -807,8 +905,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -824,8 +923,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -842,15 +942,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_to_view(
@@ -866,15 +968,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_from_view(
@@ -898,7 +1002,7 @@
 cef_browser_view_t*
 CefCToCppRefCounted<CefBrowserViewCToCpp, CefBrowserView, cef_browser_view_t>::
     UnwrapDerived(CefWrapperType type, CefBrowserView* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/browser_view_ctocpp.h b/src/libcef_dll/ctocpp/views/browser_view_ctocpp.h
index 3c45bba..526b63f 100644
--- a/src/libcef_dll/ctocpp/views/browser_view_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/browser_view_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9a09044f3f15be6f0c98a57d1d10839e89daab23$
+// $hash=3369ae36dfebd0283661566cf91fa57dbfec29e4$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_BROWSER_VIEW_CTOCPP_H_
@@ -34,58 +34,61 @@
   virtual ~CefBrowserViewCToCpp();
 
   // CefBrowserView methods.
-  CefRefPtr<CefBrowser> GetBrowser() OVERRIDE;
-  void SetPreferAccelerators(bool prefer_accelerators) OVERRIDE;
+  CefRefPtr<CefBrowser> GetBrowser() override;
+  CefRefPtr<CefView> GetChromeToolbar() override;
+  void SetPreferAccelerators(bool prefer_accelerators) override;
 
   // CefView methods.
-  CefRefPtr<CefBrowserView> AsBrowserView() OVERRIDE;
-  CefRefPtr<CefButton> AsButton() OVERRIDE;
-  CefRefPtr<CefPanel> AsPanel() OVERRIDE;
-  CefRefPtr<CefScrollView> AsScrollView() OVERRIDE;
-  CefRefPtr<CefTextfield> AsTextfield() OVERRIDE;
-  CefString GetTypeString() OVERRIDE;
-  CefString ToString(bool include_children) OVERRIDE;
-  bool IsValid() OVERRIDE;
-  bool IsAttached() OVERRIDE;
-  bool IsSame(CefRefPtr<CefView> that) OVERRIDE;
-  CefRefPtr<CefViewDelegate> GetDelegate() OVERRIDE;
-  CefRefPtr<CefWindow> GetWindow() OVERRIDE;
-  int GetID() OVERRIDE;
-  void SetID(int id) OVERRIDE;
-  int GetGroupID() OVERRIDE;
-  void SetGroupID(int group_id) OVERRIDE;
-  CefRefPtr<CefView> GetParentView() OVERRIDE;
-  CefRefPtr<CefView> GetViewForID(int id) OVERRIDE;
-  void SetBounds(const CefRect& bounds) OVERRIDE;
-  CefRect GetBounds() OVERRIDE;
-  CefRect GetBoundsInScreen() OVERRIDE;
-  void SetSize(const CefSize& size) OVERRIDE;
-  CefSize GetSize() OVERRIDE;
-  void SetPosition(const CefPoint& position) OVERRIDE;
-  CefPoint GetPosition() OVERRIDE;
-  CefSize GetPreferredSize() OVERRIDE;
-  void SizeToPreferredSize() OVERRIDE;
-  CefSize GetMinimumSize() OVERRIDE;
-  CefSize GetMaximumSize() OVERRIDE;
-  int GetHeightForWidth(int width) OVERRIDE;
-  void InvalidateLayout() OVERRIDE;
-  void SetVisible(bool visible) OVERRIDE;
-  bool IsVisible() OVERRIDE;
-  bool IsDrawn() OVERRIDE;
-  void SetEnabled(bool enabled) OVERRIDE;
-  bool IsEnabled() OVERRIDE;
-  void SetFocusable(bool focusable) OVERRIDE;
-  bool IsFocusable() OVERRIDE;
-  bool IsAccessibilityFocusable() OVERRIDE;
-  void RequestFocus() OVERRIDE;
-  void SetBackgroundColor(cef_color_t color) OVERRIDE;
-  cef_color_t GetBackgroundColor() OVERRIDE;
-  bool ConvertPointToScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointToWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
-  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
+  CefRefPtr<CefBrowserView> AsBrowserView() override;
+  CefRefPtr<CefButton> AsButton() override;
+  CefRefPtr<CefPanel> AsPanel() override;
+  CefRefPtr<CefScrollView> AsScrollView() override;
+  CefRefPtr<CefTextfield> AsTextfield() override;
+  CefString GetTypeString() override;
+  CefString ToString(bool include_children) override;
+  bool IsValid() override;
+  bool IsAttached() override;
+  bool IsSame(CefRefPtr<CefView> that) override;
+  CefRefPtr<CefViewDelegate> GetDelegate() override;
+  CefRefPtr<CefWindow> GetWindow() override;
+  int GetID() override;
+  void SetID(int id) override;
+  int GetGroupID() override;
+  void SetGroupID(int group_id) override;
+  CefRefPtr<CefView> GetParentView() override;
+  CefRefPtr<CefView> GetViewForID(int id) override;
+  void SetBounds(const CefRect& bounds) override;
+  CefRect GetBounds() override;
+  CefRect GetBoundsInScreen() override;
+  void SetSize(const CefSize& size) override;
+  CefSize GetSize() override;
+  void SetPosition(const CefPoint& position) override;
+  CefPoint GetPosition() override;
+  void SetInsets(const CefInsets& insets) override;
+  CefInsets GetInsets() override;
+  CefSize GetPreferredSize() override;
+  void SizeToPreferredSize() override;
+  CefSize GetMinimumSize() override;
+  CefSize GetMaximumSize() override;
+  int GetHeightForWidth(int width) override;
+  void InvalidateLayout() override;
+  void SetVisible(bool visible) override;
+  bool IsVisible() override;
+  bool IsDrawn() override;
+  void SetEnabled(bool enabled) override;
+  bool IsEnabled() override;
+  void SetFocusable(bool focusable) override;
+  bool IsFocusable() override;
+  bool IsAccessibilityFocusable() override;
+  void RequestFocus() override;
+  void SetBackgroundColor(cef_color_t color) override;
+  cef_color_t GetBackgroundColor() override;
+  bool ConvertPointToScreen(CefPoint& point) override;
+  bool ConvertPointFromScreen(CefPoint& point) override;
+  bool ConvertPointToWindow(CefPoint& point) override;
+  bool ConvertPointFromWindow(CefPoint& point) override;
+  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) override;
+  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_VIEWS_BROWSER_VIEW_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.cc b/src/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.cc
index 52a43d1..92c9ab2 100644
--- a/src/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=31420c63af54d0862f106caad051e85ed7a6772d$
+// $hash=a3ab5cba4139ac15763ef0df69988b1bfc00b2bf$
 //
 
 #include "libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.h"
@@ -28,19 +28,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_view_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_browser_created))
+  if (CEF_MEMBER_MISSING(_struct, on_browser_created)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser_view; type: refptr_diff
   DCHECK(browser_view.get());
-  if (!browser_view.get())
+  if (!browser_view.get()) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_browser_created(_struct, CefBrowserViewCppToC::Wrap(browser_view),
@@ -54,19 +57,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_view_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_browser_destroyed))
+  if (CEF_MEMBER_MISSING(_struct, on_browser_destroyed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser_view; type: refptr_diff
   DCHECK(browser_view.get());
-  if (!browser_view.get())
+  if (!browser_view.get()) {
     return;
+  }
   // Verify param: browser; type: refptr_diff
   DCHECK(browser.get());
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   // Execute
   _struct->on_browser_destroyed(_struct,
@@ -84,19 +90,18 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_view_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_delegate_for_popup_browser_view))
+  if (CEF_MEMBER_MISSING(_struct, get_delegate_for_popup_browser_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser_view; type: refptr_diff
   DCHECK(browser_view.get());
-  if (!browser_view.get())
+  if (!browser_view.get()) {
     return nullptr;
-  // Verify param: client; type: refptr_same
-  DCHECK(client.get());
-  if (!client.get())
-    return nullptr;
+  }
+  // Unverified params: client
 
   // Execute
   cef_browser_view_delegate_t* _retval =
@@ -116,19 +121,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_browser_view_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_popup_browser_view_created))
+  if (CEF_MEMBER_MISSING(_struct, on_popup_browser_view_created)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: browser_view; type: refptr_diff
   DCHECK(browser_view.get());
-  if (!browser_view.get())
+  if (!browser_view.get()) {
     return false;
+  }
   // Verify param: popup_browser_view; type: refptr_diff
   DCHECK(popup_browser_view.get());
-  if (!popup_browser_view.get())
+  if (!popup_browser_view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->on_popup_browser_view_created(
@@ -140,21 +148,104 @@
 }
 
 NO_SANITIZE("cfi-icall")
+CefBrowserViewDelegate::ChromeToolbarType
+CefBrowserViewDelegateCToCpp::GetChromeToolbarType(
+    CefRefPtr<CefBrowserView> browser_view) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_browser_view_delegate_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_chrome_toolbar_type)) {
+    return CEF_CTT_NONE;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser_view; type: refptr_diff
+  DCHECK(browser_view.get());
+  if (!browser_view.get()) {
+    return CEF_CTT_NONE;
+  }
+
+  // Execute
+  cef_chrome_toolbar_type_t _retval = _struct->get_chrome_toolbar_type(
+      _struct, CefBrowserViewCppToC::Wrap(browser_view));
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefBrowserViewDelegateCToCpp::UseFramelessWindowForPictureInPicture(
+    CefRefPtr<CefBrowserView> browser_view) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_browser_view_delegate_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct,
+                         use_frameless_window_for_picture_in_picture)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser_view; type: refptr_diff
+  DCHECK(browser_view.get());
+  if (!browser_view.get()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->use_frameless_window_for_picture_in_picture(
+      _struct, CefBrowserViewCppToC::Wrap(browser_view));
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefBrowserViewDelegateCToCpp::OnGestureCommand(
+    CefRefPtr<CefBrowserView> browser_view,
+    cef_gesture_command_t gesture_command) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_browser_view_delegate_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_gesture_command)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser_view; type: refptr_diff
+  DCHECK(browser_view.get());
+  if (!browser_view.get()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->on_gesture_command(
+      _struct, CefBrowserViewCppToC::Wrap(browser_view), gesture_command);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
 CefSize CefBrowserViewDelegateCToCpp::GetPreferredSize(
     CefRefPtr<CefView> view) {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, get_preferred_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -170,15 +261,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_minimum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -194,15 +287,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_maximum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -219,15 +314,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_height_for_width))
+  if (CEF_MEMBER_MISSING(_struct, get_height_for_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -246,19 +343,22 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_parent_view_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_parent_view_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
   // Verify param: parent; type: refptr_diff
   DCHECK(parent.get());
-  if (!parent.get())
+  if (!parent.get()) {
     return;
+  }
 
   // Execute
   _struct->on_parent_view_changed(_struct, CefViewCppToC::Wrap(view), added,
@@ -274,19 +374,22 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_child_view_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_child_view_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
   // Verify param: child; type: refptr_diff
   DCHECK(child.get());
-  if (!child.get())
+  if (!child.get()) {
     return;
+  }
 
   // Execute
   _struct->on_child_view_changed(_struct, CefViewCppToC::Wrap(view), added,
@@ -294,20 +397,68 @@
 }
 
 NO_SANITIZE("cfi-icall")
+void CefBrowserViewDelegateCToCpp::OnWindowChanged(CefRefPtr<CefView> view,
+                                                   bool added) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_delegate_t* _struct =
+      reinterpret_cast<cef_view_delegate_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, on_window_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: view; type: refptr_diff
+  DCHECK(view.get());
+  if (!view.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_window_changed(_struct, CefViewCppToC::Wrap(view), added);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefBrowserViewDelegateCToCpp::OnLayoutChanged(CefRefPtr<CefView> view,
+                                                   const CefRect& new_bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_delegate_t* _struct =
+      reinterpret_cast<cef_view_delegate_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, on_layout_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: view; type: refptr_diff
+  DCHECK(view.get());
+  if (!view.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_layout_changed(_struct, CefViewCppToC::Wrap(view), &new_bounds);
+}
+
+NO_SANITIZE("cfi-icall")
 void CefBrowserViewDelegateCToCpp::OnFocus(CefRefPtr<CefView> view) {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_focus))
+  if (CEF_MEMBER_MISSING(_struct, on_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->on_focus(_struct, CefViewCppToC::Wrap(view));
@@ -319,15 +470,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_blur))
+  if (CEF_MEMBER_MISSING(_struct, on_blur)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->on_blur(_struct, CefViewCppToC::Wrap(view));
@@ -349,7 +502,7 @@
     CefBrowserViewDelegate,
     cef_browser_view_delegate_t>::UnwrapDerived(CefWrapperType type,
                                                 CefBrowserViewDelegate* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.h b/src/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.h
index b2a1831..0f0f9a1 100644
--- a/src/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=085e93a68068064e7d6d96b6f12123434c4ee37a$
+// $hash=2157bfb760455bcd97d4e30eba9db474c7b3cabd$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_BROWSER_VIEW_DELEGATE_CTOCPP_H_
@@ -51,6 +51,12 @@
   bool OnPopupBrowserViewCreated(CefRefPtr<CefBrowserView> browser_view,
                                  CefRefPtr<CefBrowserView> popup_browser_view,
                                  bool is_devtools) override;
+  ChromeToolbarType GetChromeToolbarType(
+      CefRefPtr<CefBrowserView> browser_view) override;
+  bool UseFramelessWindowForPictureInPicture(
+      CefRefPtr<CefBrowserView> browser_view) override;
+  bool OnGestureCommand(CefRefPtr<CefBrowserView> browser_view,
+                        cef_gesture_command_t gesture_command) override;
 
   // CefViewDelegate methods.
   CefSize GetPreferredSize(CefRefPtr<CefView> view) override;
@@ -63,6 +69,9 @@
   void OnChildViewChanged(CefRefPtr<CefView> view,
                           bool added,
                           CefRefPtr<CefView> child) override;
+  void OnWindowChanged(CefRefPtr<CefView> view, bool added) override;
+  void OnLayoutChanged(CefRefPtr<CefView> view,
+                       const CefRect& new_bounds) override;
   void OnFocus(CefRefPtr<CefView> view) override;
   void OnBlur(CefRefPtr<CefView> view) override;
 };
diff --git a/src/libcef_dll/ctocpp/views/button_ctocpp.cc b/src/libcef_dll/ctocpp/views/button_ctocpp.cc
index 506a94a..4910151 100644
--- a/src/libcef_dll/ctocpp/views/button_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/button_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3fb1a282c85f146a38d8694f5f7bf1914fe16d38$
+// $hash=6e10aa09a1ea84f2f6e4dae41e0fe226fb0f628e$
 //
 
 #include "libcef_dll/ctocpp/views/button_ctocpp.h"
@@ -31,8 +31,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, as_label_button))
+  if (CEF_MEMBER_MISSING(_struct, as_label_button)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -48,8 +49,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_state))
+  if (CEF_MEMBER_MISSING(_struct, set_state)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -61,8 +63,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_state))
+  if (CEF_MEMBER_MISSING(_struct, get_state)) {
     return CEF_BUTTON_STATE_NORMAL;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -77,8 +80,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_ink_drop_enabled))
+  if (CEF_MEMBER_MISSING(_struct, set_ink_drop_enabled)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -91,15 +95,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_tooltip_text))
+  if (CEF_MEMBER_MISSING(_struct, set_tooltip_text)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: tooltip_text; type: string_byref_const
   DCHECK(!tooltip_text.empty());
-  if (tooltip_text.empty())
+  if (tooltip_text.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_tooltip_text(_struct, tooltip_text.GetStruct());
@@ -110,15 +116,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_accessible_name))
+  if (CEF_MEMBER_MISSING(_struct, set_accessible_name)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_accessible_name(_struct, name.GetStruct());
@@ -129,8 +137,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_browser_view))
+  if (CEF_MEMBER_MISSING(_struct, as_browser_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -145,8 +154,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_button))
+  if (CEF_MEMBER_MISSING(_struct, as_button)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -161,8 +171,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_panel))
+  if (CEF_MEMBER_MISSING(_struct, as_panel)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -178,8 +189,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_scroll_view))
+  if (CEF_MEMBER_MISSING(_struct, as_scroll_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -195,8 +207,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_textfield))
+  if (CEF_MEMBER_MISSING(_struct, as_textfield)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -211,8 +224,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_type_string))
+  if (CEF_MEMBER_MISSING(_struct, get_type_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -230,8 +244,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, to_string))
+  if (CEF_MEMBER_MISSING(_struct, to_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -248,8 +263,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -264,8 +280,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_attached))
+  if (CEF_MEMBER_MISSING(_struct, is_attached)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -280,15 +297,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefViewCToCpp::Unwrap(that));
@@ -302,8 +321,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_delegate))
+  if (CEF_MEMBER_MISSING(_struct, get_delegate)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -318,8 +338,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_window))
+  if (CEF_MEMBER_MISSING(_struct, get_window)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -334,8 +355,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_id))
+  if (CEF_MEMBER_MISSING(_struct, get_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -350,8 +372,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_id))
+  if (CEF_MEMBER_MISSING(_struct, set_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -363,8 +386,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_group_id))
+  if (CEF_MEMBER_MISSING(_struct, get_group_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -379,8 +403,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_group_id))
+  if (CEF_MEMBER_MISSING(_struct, set_group_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -392,8 +417,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_parent_view))
+  if (CEF_MEMBER_MISSING(_struct, get_parent_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -409,8 +435,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_view_for_id))
+  if (CEF_MEMBER_MISSING(_struct, get_view_for_id)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -426,8 +453,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_bounds))
+  if (CEF_MEMBER_MISSING(_struct, set_bounds)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -439,8 +467,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_bounds))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -455,8 +484,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -471,8 +501,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_size))
+  if (CEF_MEMBER_MISSING(_struct, set_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -484,8 +515,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_size))
+  if (CEF_MEMBER_MISSING(_struct, get_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -501,8 +533,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_position))
+  if (CEF_MEMBER_MISSING(_struct, set_position)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -514,8 +547,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_position))
+  if (CEF_MEMBER_MISSING(_struct, get_position)) {
     return CefPoint();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -526,12 +560,45 @@
   return _retval;
 }
 
+NO_SANITIZE("cfi-icall")
+void CefButtonCToCpp::SetInsets(const CefInsets& insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, set_insets)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->set_insets(_struct, &insets);
+}
+
+NO_SANITIZE("cfi-icall") CefInsets CefButtonCToCpp::GetInsets() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, get_insets)) {
+    return CefInsets();
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_insets_t _retval = _struct->get_insets(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
 NO_SANITIZE("cfi-icall") CefSize CefButtonCToCpp::GetPreferredSize() {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, get_preferred_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -546,8 +613,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -559,8 +627,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_minimum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -575,8 +644,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_maximum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -591,8 +661,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_height_for_width))
+  if (CEF_MEMBER_MISSING(_struct, get_height_for_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -607,8 +678,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, invalidate_layout))
+  if (CEF_MEMBER_MISSING(_struct, invalidate_layout)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -620,8 +692,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_visible))
+  if (CEF_MEMBER_MISSING(_struct, set_visible)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -633,8 +706,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_visible))
+  if (CEF_MEMBER_MISSING(_struct, is_visible)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -649,8 +723,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_drawn))
+  if (CEF_MEMBER_MISSING(_struct, is_drawn)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -665,8 +740,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_enabled))
+  if (CEF_MEMBER_MISSING(_struct, set_enabled)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -678,8 +754,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_enabled))
+  if (CEF_MEMBER_MISSING(_struct, is_enabled)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -694,8 +771,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_focusable))
+  if (CEF_MEMBER_MISSING(_struct, set_focusable)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -707,8 +785,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -723,8 +802,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -739,8 +819,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, request_focus))
+  if (CEF_MEMBER_MISSING(_struct, request_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -753,8 +834,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_background_color))
+  if (CEF_MEMBER_MISSING(_struct, set_background_color)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -766,8 +848,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_background_color))
+  if (CEF_MEMBER_MISSING(_struct, get_background_color)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -783,8 +866,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -800,8 +884,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -817,8 +902,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -834,8 +920,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -852,15 +939,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_to_view(
@@ -876,15 +965,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_from_view(
@@ -917,7 +1008,7 @@
     return reinterpret_cast<cef_button_t*>(
         CefMenuButtonCToCpp::Unwrap(reinterpret_cast<CefMenuButton*>(c)));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/button_ctocpp.h b/src/libcef_dll/ctocpp/views/button_ctocpp.h
index 192d2c8..4f4362e 100644
--- a/src/libcef_dll/ctocpp/views/button_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/button_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=54c17da1bcad99263468117e4ee4aa96174b91c3$
+// $hash=d6be48f8326ec9e541ace36d0b467cf6b1fbc065$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_BUTTON_CTOCPP_H_
@@ -35,62 +35,64 @@
   virtual ~CefButtonCToCpp();
 
   // CefButton methods.
-  CefRefPtr<CefLabelButton> AsLabelButton() OVERRIDE;
-  void SetState(cef_button_state_t state) OVERRIDE;
-  cef_button_state_t GetState() OVERRIDE;
-  void SetInkDropEnabled(bool enabled) OVERRIDE;
-  void SetTooltipText(const CefString& tooltip_text) OVERRIDE;
-  void SetAccessibleName(const CefString& name) OVERRIDE;
+  CefRefPtr<CefLabelButton> AsLabelButton() override;
+  void SetState(cef_button_state_t state) override;
+  cef_button_state_t GetState() override;
+  void SetInkDropEnabled(bool enabled) override;
+  void SetTooltipText(const CefString& tooltip_text) override;
+  void SetAccessibleName(const CefString& name) override;
 
   // CefView methods.
-  CefRefPtr<CefBrowserView> AsBrowserView() OVERRIDE;
-  CefRefPtr<CefButton> AsButton() OVERRIDE;
-  CefRefPtr<CefPanel> AsPanel() OVERRIDE;
-  CefRefPtr<CefScrollView> AsScrollView() OVERRIDE;
-  CefRefPtr<CefTextfield> AsTextfield() OVERRIDE;
-  CefString GetTypeString() OVERRIDE;
-  CefString ToString(bool include_children) OVERRIDE;
-  bool IsValid() OVERRIDE;
-  bool IsAttached() OVERRIDE;
-  bool IsSame(CefRefPtr<CefView> that) OVERRIDE;
-  CefRefPtr<CefViewDelegate> GetDelegate() OVERRIDE;
-  CefRefPtr<CefWindow> GetWindow() OVERRIDE;
-  int GetID() OVERRIDE;
-  void SetID(int id) OVERRIDE;
-  int GetGroupID() OVERRIDE;
-  void SetGroupID(int group_id) OVERRIDE;
-  CefRefPtr<CefView> GetParentView() OVERRIDE;
-  CefRefPtr<CefView> GetViewForID(int id) OVERRIDE;
-  void SetBounds(const CefRect& bounds) OVERRIDE;
-  CefRect GetBounds() OVERRIDE;
-  CefRect GetBoundsInScreen() OVERRIDE;
-  void SetSize(const CefSize& size) OVERRIDE;
-  CefSize GetSize() OVERRIDE;
-  void SetPosition(const CefPoint& position) OVERRIDE;
-  CefPoint GetPosition() OVERRIDE;
-  CefSize GetPreferredSize() OVERRIDE;
-  void SizeToPreferredSize() OVERRIDE;
-  CefSize GetMinimumSize() OVERRIDE;
-  CefSize GetMaximumSize() OVERRIDE;
-  int GetHeightForWidth(int width) OVERRIDE;
-  void InvalidateLayout() OVERRIDE;
-  void SetVisible(bool visible) OVERRIDE;
-  bool IsVisible() OVERRIDE;
-  bool IsDrawn() OVERRIDE;
-  void SetEnabled(bool enabled) OVERRIDE;
-  bool IsEnabled() OVERRIDE;
-  void SetFocusable(bool focusable) OVERRIDE;
-  bool IsFocusable() OVERRIDE;
-  bool IsAccessibilityFocusable() OVERRIDE;
-  void RequestFocus() OVERRIDE;
-  void SetBackgroundColor(cef_color_t color) OVERRIDE;
-  cef_color_t GetBackgroundColor() OVERRIDE;
-  bool ConvertPointToScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointToWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
-  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
+  CefRefPtr<CefBrowserView> AsBrowserView() override;
+  CefRefPtr<CefButton> AsButton() override;
+  CefRefPtr<CefPanel> AsPanel() override;
+  CefRefPtr<CefScrollView> AsScrollView() override;
+  CefRefPtr<CefTextfield> AsTextfield() override;
+  CefString GetTypeString() override;
+  CefString ToString(bool include_children) override;
+  bool IsValid() override;
+  bool IsAttached() override;
+  bool IsSame(CefRefPtr<CefView> that) override;
+  CefRefPtr<CefViewDelegate> GetDelegate() override;
+  CefRefPtr<CefWindow> GetWindow() override;
+  int GetID() override;
+  void SetID(int id) override;
+  int GetGroupID() override;
+  void SetGroupID(int group_id) override;
+  CefRefPtr<CefView> GetParentView() override;
+  CefRefPtr<CefView> GetViewForID(int id) override;
+  void SetBounds(const CefRect& bounds) override;
+  CefRect GetBounds() override;
+  CefRect GetBoundsInScreen() override;
+  void SetSize(const CefSize& size) override;
+  CefSize GetSize() override;
+  void SetPosition(const CefPoint& position) override;
+  CefPoint GetPosition() override;
+  void SetInsets(const CefInsets& insets) override;
+  CefInsets GetInsets() override;
+  CefSize GetPreferredSize() override;
+  void SizeToPreferredSize() override;
+  CefSize GetMinimumSize() override;
+  CefSize GetMaximumSize() override;
+  int GetHeightForWidth(int width) override;
+  void InvalidateLayout() override;
+  void SetVisible(bool visible) override;
+  bool IsVisible() override;
+  bool IsDrawn() override;
+  void SetEnabled(bool enabled) override;
+  bool IsEnabled() override;
+  void SetFocusable(bool focusable) override;
+  bool IsFocusable() override;
+  bool IsAccessibilityFocusable() override;
+  void RequestFocus() override;
+  void SetBackgroundColor(cef_color_t color) override;
+  cef_color_t GetBackgroundColor() override;
+  bool ConvertPointToScreen(CefPoint& point) override;
+  bool ConvertPointFromScreen(CefPoint& point) override;
+  bool ConvertPointToWindow(CefPoint& point) override;
+  bool ConvertPointFromWindow(CefPoint& point) override;
+  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) override;
+  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_VIEWS_BUTTON_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/views/button_delegate_ctocpp.cc b/src/libcef_dll/ctocpp/views/button_delegate_ctocpp.cc
index c440bd3..39f8c79 100644
--- a/src/libcef_dll/ctocpp/views/button_delegate_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/button_delegate_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=17852d5b4f41fd2e6d5e3b33b61d014bc4131dc3$
+// $hash=91c554eefa0d182363ba9b50f952f68a8f69ac0d$
 //
 
 #include "libcef_dll/ctocpp/views/button_delegate_ctocpp.h"
@@ -25,15 +25,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_button_pressed))
+  if (CEF_MEMBER_MISSING(_struct, on_button_pressed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: button; type: refptr_diff
   DCHECK(button.get());
-  if (!button.get())
+  if (!button.get()) {
     return;
+  }
 
   // Execute
   _struct->on_button_pressed(_struct, CefButtonCppToC::Wrap(button));
@@ -45,15 +47,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_button_state_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_button_state_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: button; type: refptr_diff
   DCHECK(button.get());
-  if (!button.get())
+  if (!button.get()) {
     return;
+  }
 
   // Execute
   _struct->on_button_state_changed(_struct, CefButtonCppToC::Wrap(button));
@@ -65,15 +69,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, get_preferred_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -89,15 +95,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_minimum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -113,15 +121,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_maximum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -138,15 +148,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_height_for_width))
+  if (CEF_MEMBER_MISSING(_struct, get_height_for_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -164,19 +176,22 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_parent_view_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_parent_view_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
   // Verify param: parent; type: refptr_diff
   DCHECK(parent.get());
-  if (!parent.get())
+  if (!parent.get()) {
     return;
+  }
 
   // Execute
   _struct->on_parent_view_changed(_struct, CefViewCppToC::Wrap(view), added,
@@ -191,19 +206,22 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_child_view_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_child_view_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
   // Verify param: child; type: refptr_diff
   DCHECK(child.get());
-  if (!child.get())
+  if (!child.get()) {
     return;
+  }
 
   // Execute
   _struct->on_child_view_changed(_struct, CefViewCppToC::Wrap(view), added,
@@ -211,20 +229,68 @@
 }
 
 NO_SANITIZE("cfi-icall")
+void CefButtonDelegateCToCpp::OnWindowChanged(CefRefPtr<CefView> view,
+                                              bool added) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_delegate_t* _struct =
+      reinterpret_cast<cef_view_delegate_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, on_window_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: view; type: refptr_diff
+  DCHECK(view.get());
+  if (!view.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_window_changed(_struct, CefViewCppToC::Wrap(view), added);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefButtonDelegateCToCpp::OnLayoutChanged(CefRefPtr<CefView> view,
+                                              const CefRect& new_bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_delegate_t* _struct =
+      reinterpret_cast<cef_view_delegate_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, on_layout_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: view; type: refptr_diff
+  DCHECK(view.get());
+  if (!view.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_layout_changed(_struct, CefViewCppToC::Wrap(view), &new_bounds);
+}
+
+NO_SANITIZE("cfi-icall")
 void CefButtonDelegateCToCpp::OnFocus(CefRefPtr<CefView> view) {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_focus))
+  if (CEF_MEMBER_MISSING(_struct, on_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->on_focus(_struct, CefViewCppToC::Wrap(view));
@@ -236,15 +302,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_blur))
+  if (CEF_MEMBER_MISSING(_struct, on_blur)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->on_blur(_struct, CefViewCppToC::Wrap(view));
@@ -271,7 +339,7 @@
         CefMenuButtonDelegateCToCpp::Unwrap(
             reinterpret_cast<CefMenuButtonDelegate*>(c)));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/button_delegate_ctocpp.h b/src/libcef_dll/ctocpp/views/button_delegate_ctocpp.h
index 3c0e004..a01a96b 100644
--- a/src/libcef_dll/ctocpp/views/button_delegate_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/button_delegate_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6e52653a50e0930437a93fa1f9ac01b8c3b39c02$
+// $hash=13140a32b465eaf52f13693cd244a9b47eda5068$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_BUTTON_DELEGATE_CTOCPP_H_
@@ -51,6 +51,9 @@
   void OnChildViewChanged(CefRefPtr<CefView> view,
                           bool added,
                           CefRefPtr<CefView> child) override;
+  void OnWindowChanged(CefRefPtr<CefView> view, bool added) override;
+  void OnLayoutChanged(CefRefPtr<CefView> view,
+                       const CefRect& new_bounds) override;
   void OnFocus(CefRefPtr<CefView> view) override;
   void OnBlur(CefRefPtr<CefView> view) override;
 };
diff --git a/src/libcef_dll/ctocpp/views/display_ctocpp.cc b/src/libcef_dll/ctocpp/views/display_ctocpp.cc
index 5f09dcc..67beb50 100644
--- a/src/libcef_dll/ctocpp/views/display_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/display_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=50521680b4ef13badbac42fa1a5e28d5ddf46194$
+// $hash=d53ce4c040c4839540a656901efd75e55720de98$
 //
 
 #include "libcef_dll/ctocpp/views/display_ctocpp.h"
@@ -110,19 +110,72 @@
   }
 }
 
-// VIRTUAL METHODS - Body may be edited by hand.
-
-NO_SANITIZE("cfi-icall") int64 CefDisplayCToCpp::GetID() {
+NO_SANITIZE("cfi-icall")
+CefPoint CefDisplay::ConvertScreenPointToPixels(const CefPoint& point) {
   shutdown_checker::AssertNotShutdown();
 
-  cef_display_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_id))
-    return 0;
-
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int64 _retval = _struct->get_id(_struct);
+  cef_point_t _retval = cef_display_convert_screen_point_to_pixels(&point);
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall")
+CefPoint CefDisplay::ConvertScreenPointFromPixels(const CefPoint& point) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_point_t _retval = cef_display_convert_screen_point_from_pixels(&point);
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall")
+CefRect CefDisplay::ConvertScreenRectToPixels(const CefRect& rect) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_rect_t _retval = cef_display_convert_screen_rect_to_pixels(&rect);
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall")
+CefRect CefDisplay::ConvertScreenRectFromPixels(const CefRect& rect) {
+  shutdown_checker::AssertNotShutdown();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_rect_t _retval = cef_display_convert_screen_rect_from_pixels(&rect);
+
+  // Return type: simple
+  return _retval;
+}
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall") int64_t CefDisplayCToCpp::GetID() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_display_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_id)) {
+    return 0;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int64_t _retval = _struct->get_id(_struct);
 
   // Return type: simple
   return _retval;
@@ -132,8 +185,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_display_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_device_scale_factor))
+  if (CEF_MEMBER_MISSING(_struct, get_device_scale_factor)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -149,8 +203,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_display_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_pixels))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_pixels)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -163,8 +218,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_display_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_pixels))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_pixels)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -176,8 +232,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_display_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_bounds))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -192,8 +249,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_display_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_work_area))
+  if (CEF_MEMBER_MISSING(_struct, get_work_area)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -208,8 +266,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_display_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_rotation))
+  if (CEF_MEMBER_MISSING(_struct, get_rotation)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -235,7 +294,7 @@
 CefCToCppRefCounted<CefDisplayCToCpp, CefDisplay, cef_display_t>::UnwrapDerived(
     CefWrapperType type,
     CefDisplay* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/display_ctocpp.h b/src/libcef_dll/ctocpp/views/display_ctocpp.h
index 6e60795..5bc3bfc 100644
--- a/src/libcef_dll/ctocpp/views/display_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/display_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8414b880b6fbb3ea8dba03250a387fa2f525edf6$
+// $hash=344eaf627105f0a3b80b44e1d576baa7f2cdc47d$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_DISPLAY_CTOCPP_H_
@@ -33,13 +33,13 @@
   virtual ~CefDisplayCToCpp();
 
   // CefDisplay methods.
-  int64 GetID() OVERRIDE;
-  float GetDeviceScaleFactor() OVERRIDE;
-  void ConvertPointToPixels(CefPoint& point) OVERRIDE;
-  void ConvertPointFromPixels(CefPoint& point) OVERRIDE;
-  CefRect GetBounds() OVERRIDE;
-  CefRect GetWorkArea() OVERRIDE;
-  int GetRotation() OVERRIDE;
+  int64_t GetID() override;
+  float GetDeviceScaleFactor() override;
+  void ConvertPointToPixels(CefPoint& point) override;
+  void ConvertPointFromPixels(CefPoint& point) override;
+  CefRect GetBounds() override;
+  CefRect GetWorkArea() override;
+  int GetRotation() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_VIEWS_DISPLAY_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/views/fill_layout_ctocpp.cc b/src/libcef_dll/ctocpp/views/fill_layout_ctocpp.cc
index d85016a..4b07ec7 100644
--- a/src/libcef_dll/ctocpp/views/fill_layout_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/fill_layout_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c23b9c61162d6f4e69a04dca457d014a272ca4cf$
+// $hash=28c2bd41db1604637488919fca1375385100595a$
 //
 
 #include "libcef_dll/ctocpp/views/fill_layout_ctocpp.h"
@@ -23,8 +23,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_layout_t* _struct = reinterpret_cast<cef_layout_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_box_layout))
+  if (CEF_MEMBER_MISSING(_struct, as_box_layout)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -40,8 +41,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_layout_t* _struct = reinterpret_cast<cef_layout_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_fill_layout))
+  if (CEF_MEMBER_MISSING(_struct, as_fill_layout)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -56,8 +58,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_layout_t* _struct = reinterpret_cast<cef_layout_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -82,7 +85,7 @@
 cef_fill_layout_t*
 CefCToCppRefCounted<CefFillLayoutCToCpp, CefFillLayout, cef_fill_layout_t>::
     UnwrapDerived(CefWrapperType type, CefFillLayout* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/fill_layout_ctocpp.h b/src/libcef_dll/ctocpp/views/fill_layout_ctocpp.h
index 39461c0..06b0380 100644
--- a/src/libcef_dll/ctocpp/views/fill_layout_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/fill_layout_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8eb4ca176ea5985fcbe291dc5e05b65dade7bb77$
+// $hash=5d52b0af136f7ac008cb89a29ce65942932b9f64$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_FILL_LAYOUT_CTOCPP_H_
@@ -36,9 +36,9 @@
   // CefFillLayout methods.
 
   // CefLayout methods.
-  CefRefPtr<CefBoxLayout> AsBoxLayout() OVERRIDE;
-  CefRefPtr<CefFillLayout> AsFillLayout() OVERRIDE;
-  bool IsValid() OVERRIDE;
+  CefRefPtr<CefBoxLayout> AsBoxLayout() override;
+  CefRefPtr<CefFillLayout> AsFillLayout() override;
+  bool IsValid() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_VIEWS_FILL_LAYOUT_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/views/label_button_ctocpp.cc b/src/libcef_dll/ctocpp/views/label_button_ctocpp.cc
index 7dc4bd3..b5c4d73 100644
--- a/src/libcef_dll/ctocpp/views/label_button_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/label_button_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6682fd73dd4a88b7082ea6032a9a169f27295cc8$
+// $hash=af38c90a350f9426e17f24fab089d90b38af0623$
 //
 
 #include "libcef_dll/ctocpp/views/label_button_ctocpp.h"
@@ -38,8 +38,9 @@
 
   // Verify param: delegate; type: refptr_diff
   DCHECK(delegate.get());
-  if (!delegate.get())
+  if (!delegate.get()) {
     return nullptr;
+  }
   // Unverified params: text
 
   // Execute
@@ -57,8 +58,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_label_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, as_menu_button))
+  if (CEF_MEMBER_MISSING(_struct, as_menu_button)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -74,15 +76,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_label_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_text))
+  if (CEF_MEMBER_MISSING(_struct, set_text)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: text; type: string_byref_const
   DCHECK(!text.empty());
-  if (text.empty())
+  if (text.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_text(_struct, text.GetStruct());
@@ -92,8 +96,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_label_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_text))
+  if (CEF_MEMBER_MISSING(_struct, get_text)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -112,8 +117,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_label_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_image))
+  if (CEF_MEMBER_MISSING(_struct, set_image)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -129,8 +135,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_label_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_image))
+  if (CEF_MEMBER_MISSING(_struct, get_image)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -147,8 +154,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_label_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_text_color))
+  if (CEF_MEMBER_MISSING(_struct, set_text_color)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -161,8 +169,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_label_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_enabled_text_colors))
+  if (CEF_MEMBER_MISSING(_struct, set_enabled_text_colors)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -175,15 +184,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_label_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_font_list))
+  if (CEF_MEMBER_MISSING(_struct, set_font_list)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: font_list; type: string_byref_const
   DCHECK(!font_list.empty());
-  if (font_list.empty())
+  if (font_list.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_font_list(_struct, font_list.GetStruct());
@@ -195,8 +206,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_label_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_horizontal_alignment))
+  if (CEF_MEMBER_MISSING(_struct, set_horizontal_alignment)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -209,8 +221,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_label_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, set_minimum_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -223,8 +236,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_label_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, set_maximum_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -237,8 +251,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = reinterpret_cast<cef_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_label_button))
+  if (CEF_MEMBER_MISSING(_struct, as_label_button)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -254,8 +269,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = reinterpret_cast<cef_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_state))
+  if (CEF_MEMBER_MISSING(_struct, set_state)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -267,8 +283,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = reinterpret_cast<cef_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_state))
+  if (CEF_MEMBER_MISSING(_struct, get_state)) {
     return CEF_BUTTON_STATE_NORMAL;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -284,8 +301,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = reinterpret_cast<cef_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_ink_drop_enabled))
+  if (CEF_MEMBER_MISSING(_struct, set_ink_drop_enabled)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -298,15 +316,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = reinterpret_cast<cef_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_tooltip_text))
+  if (CEF_MEMBER_MISSING(_struct, set_tooltip_text)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: tooltip_text; type: string_byref_const
   DCHECK(!tooltip_text.empty());
-  if (tooltip_text.empty())
+  if (tooltip_text.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_tooltip_text(_struct, tooltip_text.GetStruct());
@@ -317,15 +337,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = reinterpret_cast<cef_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_accessible_name))
+  if (CEF_MEMBER_MISSING(_struct, set_accessible_name)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_accessible_name(_struct, name.GetStruct());
@@ -336,8 +358,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_browser_view))
+  if (CEF_MEMBER_MISSING(_struct, as_browser_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -352,8 +375,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_button))
+  if (CEF_MEMBER_MISSING(_struct, as_button)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -368,8 +392,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_panel))
+  if (CEF_MEMBER_MISSING(_struct, as_panel)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -385,8 +410,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_scroll_view))
+  if (CEF_MEMBER_MISSING(_struct, as_scroll_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -402,8 +428,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_textfield))
+  if (CEF_MEMBER_MISSING(_struct, as_textfield)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -418,8 +445,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_type_string))
+  if (CEF_MEMBER_MISSING(_struct, get_type_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -437,8 +465,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, to_string))
+  if (CEF_MEMBER_MISSING(_struct, to_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -455,8 +484,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -471,8 +501,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_attached))
+  if (CEF_MEMBER_MISSING(_struct, is_attached)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -488,15 +519,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefViewCToCpp::Unwrap(that));
@@ -510,8 +543,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_delegate))
+  if (CEF_MEMBER_MISSING(_struct, get_delegate)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -527,8 +561,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_window))
+  if (CEF_MEMBER_MISSING(_struct, get_window)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -543,8 +578,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_id))
+  if (CEF_MEMBER_MISSING(_struct, get_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -559,8 +595,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_id))
+  if (CEF_MEMBER_MISSING(_struct, set_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -572,8 +609,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_group_id))
+  if (CEF_MEMBER_MISSING(_struct, get_group_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -588,8 +626,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_group_id))
+  if (CEF_MEMBER_MISSING(_struct, set_group_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -602,8 +641,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_parent_view))
+  if (CEF_MEMBER_MISSING(_struct, get_parent_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -619,8 +659,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_view_for_id))
+  if (CEF_MEMBER_MISSING(_struct, get_view_for_id)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -636,8 +677,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_bounds))
+  if (CEF_MEMBER_MISSING(_struct, set_bounds)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -649,8 +691,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_bounds))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -665,8 +708,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -682,8 +726,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_size))
+  if (CEF_MEMBER_MISSING(_struct, set_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -695,8 +740,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_size))
+  if (CEF_MEMBER_MISSING(_struct, get_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -712,8 +758,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_position))
+  if (CEF_MEMBER_MISSING(_struct, set_position)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -725,8 +772,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_position))
+  if (CEF_MEMBER_MISSING(_struct, get_position)) {
     return CefPoint();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -737,12 +785,45 @@
   return _retval;
 }
 
+NO_SANITIZE("cfi-icall")
+void CefLabelButtonCToCpp::SetInsets(const CefInsets& insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, set_insets)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->set_insets(_struct, &insets);
+}
+
+NO_SANITIZE("cfi-icall") CefInsets CefLabelButtonCToCpp::GetInsets() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, get_insets)) {
+    return CefInsets();
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_insets_t _retval = _struct->get_insets(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
 NO_SANITIZE("cfi-icall") CefSize CefLabelButtonCToCpp::GetPreferredSize() {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, get_preferred_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -757,8 +838,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -770,8 +852,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_minimum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -786,8 +869,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_maximum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -803,8 +887,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_height_for_width))
+  if (CEF_MEMBER_MISSING(_struct, get_height_for_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -819,8 +904,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, invalidate_layout))
+  if (CEF_MEMBER_MISSING(_struct, invalidate_layout)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -832,8 +918,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_visible))
+  if (CEF_MEMBER_MISSING(_struct, set_visible)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -845,8 +932,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_visible))
+  if (CEF_MEMBER_MISSING(_struct, is_visible)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -861,8 +949,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_drawn))
+  if (CEF_MEMBER_MISSING(_struct, is_drawn)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -877,8 +966,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_enabled))
+  if (CEF_MEMBER_MISSING(_struct, set_enabled)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -890,8 +980,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_enabled))
+  if (CEF_MEMBER_MISSING(_struct, is_enabled)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -907,8 +998,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_focusable))
+  if (CEF_MEMBER_MISSING(_struct, set_focusable)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -920,8 +1012,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -936,8 +1029,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -952,8 +1046,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, request_focus))
+  if (CEF_MEMBER_MISSING(_struct, request_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -966,8 +1061,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_background_color))
+  if (CEF_MEMBER_MISSING(_struct, set_background_color)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -980,8 +1076,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_background_color))
+  if (CEF_MEMBER_MISSING(_struct, get_background_color)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -997,8 +1094,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1014,8 +1112,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1031,8 +1130,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1048,8 +1148,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1066,15 +1167,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_to_view(
@@ -1090,15 +1193,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_from_view(
@@ -1126,7 +1231,7 @@
     return reinterpret_cast<cef_label_button_t*>(
         CefMenuButtonCToCpp::Unwrap(reinterpret_cast<CefMenuButton*>(c)));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/label_button_ctocpp.h b/src/libcef_dll/ctocpp/views/label_button_ctocpp.h
index a46a9a1..d7f20dc 100644
--- a/src/libcef_dll/ctocpp/views/label_button_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/label_button_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=34cf1281025c4db90d4a11237a68799276bd74d6$
+// $hash=e54619e16a7a8f21cdeeb4ddfcedf3504c258d35$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_LABEL_BUTTON_CTOCPP_H_
@@ -36,76 +36,78 @@
   virtual ~CefLabelButtonCToCpp();
 
   // CefLabelButton methods.
-  CefRefPtr<CefMenuButton> AsMenuButton() OVERRIDE;
-  void SetText(const CefString& text) OVERRIDE;
-  CefString GetText() OVERRIDE;
+  CefRefPtr<CefMenuButton> AsMenuButton() override;
+  void SetText(const CefString& text) override;
+  CefString GetText() override;
   void SetImage(cef_button_state_t button_state,
-                CefRefPtr<CefImage> image) OVERRIDE;
-  CefRefPtr<CefImage> GetImage(cef_button_state_t button_state) OVERRIDE;
-  void SetTextColor(cef_button_state_t for_state, cef_color_t color) OVERRIDE;
-  void SetEnabledTextColors(cef_color_t color) OVERRIDE;
-  void SetFontList(const CefString& font_list) OVERRIDE;
-  void SetHorizontalAlignment(cef_horizontal_alignment_t alignment) OVERRIDE;
-  void SetMinimumSize(const CefSize& size) OVERRIDE;
-  void SetMaximumSize(const CefSize& size) OVERRIDE;
+                CefRefPtr<CefImage> image) override;
+  CefRefPtr<CefImage> GetImage(cef_button_state_t button_state) override;
+  void SetTextColor(cef_button_state_t for_state, cef_color_t color) override;
+  void SetEnabledTextColors(cef_color_t color) override;
+  void SetFontList(const CefString& font_list) override;
+  void SetHorizontalAlignment(cef_horizontal_alignment_t alignment) override;
+  void SetMinimumSize(const CefSize& size) override;
+  void SetMaximumSize(const CefSize& size) override;
 
   // CefButton methods.
-  CefRefPtr<CefLabelButton> AsLabelButton() OVERRIDE;
-  void SetState(cef_button_state_t state) OVERRIDE;
-  cef_button_state_t GetState() OVERRIDE;
-  void SetInkDropEnabled(bool enabled) OVERRIDE;
-  void SetTooltipText(const CefString& tooltip_text) OVERRIDE;
-  void SetAccessibleName(const CefString& name) OVERRIDE;
+  CefRefPtr<CefLabelButton> AsLabelButton() override;
+  void SetState(cef_button_state_t state) override;
+  cef_button_state_t GetState() override;
+  void SetInkDropEnabled(bool enabled) override;
+  void SetTooltipText(const CefString& tooltip_text) override;
+  void SetAccessibleName(const CefString& name) override;
 
   // CefView methods.
-  CefRefPtr<CefBrowserView> AsBrowserView() OVERRIDE;
-  CefRefPtr<CefButton> AsButton() OVERRIDE;
-  CefRefPtr<CefPanel> AsPanel() OVERRIDE;
-  CefRefPtr<CefScrollView> AsScrollView() OVERRIDE;
-  CefRefPtr<CefTextfield> AsTextfield() OVERRIDE;
-  CefString GetTypeString() OVERRIDE;
-  CefString ToString(bool include_children) OVERRIDE;
-  bool IsValid() OVERRIDE;
-  bool IsAttached() OVERRIDE;
-  bool IsSame(CefRefPtr<CefView> that) OVERRIDE;
-  CefRefPtr<CefViewDelegate> GetDelegate() OVERRIDE;
-  CefRefPtr<CefWindow> GetWindow() OVERRIDE;
-  int GetID() OVERRIDE;
-  void SetID(int id) OVERRIDE;
-  int GetGroupID() OVERRIDE;
-  void SetGroupID(int group_id) OVERRIDE;
-  CefRefPtr<CefView> GetParentView() OVERRIDE;
-  CefRefPtr<CefView> GetViewForID(int id) OVERRIDE;
-  void SetBounds(const CefRect& bounds) OVERRIDE;
-  CefRect GetBounds() OVERRIDE;
-  CefRect GetBoundsInScreen() OVERRIDE;
-  void SetSize(const CefSize& size) OVERRIDE;
-  CefSize GetSize() OVERRIDE;
-  void SetPosition(const CefPoint& position) OVERRIDE;
-  CefPoint GetPosition() OVERRIDE;
-  CefSize GetPreferredSize() OVERRIDE;
-  void SizeToPreferredSize() OVERRIDE;
-  CefSize GetMinimumSize() OVERRIDE;
-  CefSize GetMaximumSize() OVERRIDE;
-  int GetHeightForWidth(int width) OVERRIDE;
-  void InvalidateLayout() OVERRIDE;
-  void SetVisible(bool visible) OVERRIDE;
-  bool IsVisible() OVERRIDE;
-  bool IsDrawn() OVERRIDE;
-  void SetEnabled(bool enabled) OVERRIDE;
-  bool IsEnabled() OVERRIDE;
-  void SetFocusable(bool focusable) OVERRIDE;
-  bool IsFocusable() OVERRIDE;
-  bool IsAccessibilityFocusable() OVERRIDE;
-  void RequestFocus() OVERRIDE;
-  void SetBackgroundColor(cef_color_t color) OVERRIDE;
-  cef_color_t GetBackgroundColor() OVERRIDE;
-  bool ConvertPointToScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointToWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
-  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
+  CefRefPtr<CefBrowserView> AsBrowserView() override;
+  CefRefPtr<CefButton> AsButton() override;
+  CefRefPtr<CefPanel> AsPanel() override;
+  CefRefPtr<CefScrollView> AsScrollView() override;
+  CefRefPtr<CefTextfield> AsTextfield() override;
+  CefString GetTypeString() override;
+  CefString ToString(bool include_children) override;
+  bool IsValid() override;
+  bool IsAttached() override;
+  bool IsSame(CefRefPtr<CefView> that) override;
+  CefRefPtr<CefViewDelegate> GetDelegate() override;
+  CefRefPtr<CefWindow> GetWindow() override;
+  int GetID() override;
+  void SetID(int id) override;
+  int GetGroupID() override;
+  void SetGroupID(int group_id) override;
+  CefRefPtr<CefView> GetParentView() override;
+  CefRefPtr<CefView> GetViewForID(int id) override;
+  void SetBounds(const CefRect& bounds) override;
+  CefRect GetBounds() override;
+  CefRect GetBoundsInScreen() override;
+  void SetSize(const CefSize& size) override;
+  CefSize GetSize() override;
+  void SetPosition(const CefPoint& position) override;
+  CefPoint GetPosition() override;
+  void SetInsets(const CefInsets& insets) override;
+  CefInsets GetInsets() override;
+  CefSize GetPreferredSize() override;
+  void SizeToPreferredSize() override;
+  CefSize GetMinimumSize() override;
+  CefSize GetMaximumSize() override;
+  int GetHeightForWidth(int width) override;
+  void InvalidateLayout() override;
+  void SetVisible(bool visible) override;
+  bool IsVisible() override;
+  bool IsDrawn() override;
+  void SetEnabled(bool enabled) override;
+  bool IsEnabled() override;
+  void SetFocusable(bool focusable) override;
+  bool IsFocusable() override;
+  bool IsAccessibilityFocusable() override;
+  void RequestFocus() override;
+  void SetBackgroundColor(cef_color_t color) override;
+  cef_color_t GetBackgroundColor() override;
+  bool ConvertPointToScreen(CefPoint& point) override;
+  bool ConvertPointFromScreen(CefPoint& point) override;
+  bool ConvertPointToWindow(CefPoint& point) override;
+  bool ConvertPointFromWindow(CefPoint& point) override;
+  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) override;
+  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_VIEWS_LABEL_BUTTON_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/views/layout_ctocpp.cc b/src/libcef_dll/ctocpp/views/layout_ctocpp.cc
index 0de8c3a..52baad2 100644
--- a/src/libcef_dll/ctocpp/views/layout_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/layout_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0acbb84fac664d4f43b0d32586dcdec0b81cd082$
+// $hash=d2db6c2b3eb8abd37305f85e5270e3e5c4d7547b$
 //
 
 #include "libcef_dll/ctocpp/views/layout_ctocpp.h"
@@ -24,8 +24,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_layout_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, as_box_layout))
+  if (CEF_MEMBER_MISSING(_struct, as_box_layout)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -41,8 +42,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_layout_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, as_fill_layout))
+  if (CEF_MEMBER_MISSING(_struct, as_fill_layout)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -57,8 +59,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_layout_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -92,7 +95,7 @@
     return reinterpret_cast<cef_layout_t*>(
         CefFillLayoutCToCpp::Unwrap(reinterpret_cast<CefFillLayout*>(c)));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/layout_ctocpp.h b/src/libcef_dll/ctocpp/views/layout_ctocpp.h
index b09181f..6ffa76d 100644
--- a/src/libcef_dll/ctocpp/views/layout_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/layout_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0cc6a8abd2da2a8b8aa42a5f515b86696b390711$
+// $hash=f50cae9c7f44f282497cff43e8b89fc76f60e51b$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_LAYOUT_CTOCPP_H_
@@ -37,9 +37,9 @@
   virtual ~CefLayoutCToCpp();
 
   // CefLayout methods.
-  CefRefPtr<CefBoxLayout> AsBoxLayout() OVERRIDE;
-  CefRefPtr<CefFillLayout> AsFillLayout() OVERRIDE;
-  bool IsValid() OVERRIDE;
+  CefRefPtr<CefBoxLayout> AsBoxLayout() override;
+  CefRefPtr<CefFillLayout> AsFillLayout() override;
+  bool IsValid() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_VIEWS_LAYOUT_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/views/menu_button_ctocpp.cc b/src/libcef_dll/ctocpp/views/menu_button_ctocpp.cc
index 146ed18..97c9b87 100644
--- a/src/libcef_dll/ctocpp/views/menu_button_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/menu_button_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2ae5da63dbe303051882b451b59db219782bdd87$
+// $hash=456470ac4ea861866ebb9358f85e982ef1c73ef9$
 //
 
 #include "libcef_dll/ctocpp/views/menu_button_ctocpp.h"
@@ -39,8 +39,9 @@
 
   // Verify param: delegate; type: refptr_diff
   DCHECK(delegate.get());
-  if (!delegate.get())
+  if (!delegate.get()) {
     return nullptr;
+  }
   // Unverified params: text
 
   // Execute
@@ -60,15 +61,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, show_menu))
+  if (CEF_MEMBER_MISSING(_struct, show_menu)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: menu_model; type: refptr_same
   DCHECK(menu_model.get());
-  if (!menu_model.get())
+  if (!menu_model.get()) {
     return;
+  }
 
   // Execute
   _struct->show_menu(_struct, CefMenuModelCToCpp::Unwrap(menu_model),
@@ -79,8 +82,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_button_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, trigger_menu))
+  if (CEF_MEMBER_MISSING(_struct, trigger_menu)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -94,8 +98,9 @@
 
   cef_label_button_t* _struct =
       reinterpret_cast<cef_label_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_menu_button))
+  if (CEF_MEMBER_MISSING(_struct, as_menu_button)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -112,15 +117,17 @@
 
   cef_label_button_t* _struct =
       reinterpret_cast<cef_label_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_text))
+  if (CEF_MEMBER_MISSING(_struct, set_text)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: text; type: string_byref_const
   DCHECK(!text.empty());
-  if (text.empty())
+  if (text.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_text(_struct, text.GetStruct());
@@ -131,8 +138,9 @@
 
   cef_label_button_t* _struct =
       reinterpret_cast<cef_label_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_text))
+  if (CEF_MEMBER_MISSING(_struct, get_text)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -152,8 +160,9 @@
 
   cef_label_button_t* _struct =
       reinterpret_cast<cef_label_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_image))
+  if (CEF_MEMBER_MISSING(_struct, set_image)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -170,8 +179,9 @@
 
   cef_label_button_t* _struct =
       reinterpret_cast<cef_label_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_image))
+  if (CEF_MEMBER_MISSING(_struct, get_image)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -189,8 +199,9 @@
 
   cef_label_button_t* _struct =
       reinterpret_cast<cef_label_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_text_color))
+  if (CEF_MEMBER_MISSING(_struct, set_text_color)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -204,8 +215,9 @@
 
   cef_label_button_t* _struct =
       reinterpret_cast<cef_label_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_enabled_text_colors))
+  if (CEF_MEMBER_MISSING(_struct, set_enabled_text_colors)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -219,15 +231,17 @@
 
   cef_label_button_t* _struct =
       reinterpret_cast<cef_label_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_font_list))
+  if (CEF_MEMBER_MISSING(_struct, set_font_list)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: font_list; type: string_byref_const
   DCHECK(!font_list.empty());
-  if (font_list.empty())
+  if (font_list.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_font_list(_struct, font_list.GetStruct());
@@ -240,8 +254,9 @@
 
   cef_label_button_t* _struct =
       reinterpret_cast<cef_label_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_horizontal_alignment))
+  if (CEF_MEMBER_MISSING(_struct, set_horizontal_alignment)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -255,8 +270,9 @@
 
   cef_label_button_t* _struct =
       reinterpret_cast<cef_label_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, set_minimum_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -270,8 +286,9 @@
 
   cef_label_button_t* _struct =
       reinterpret_cast<cef_label_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, set_maximum_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -284,8 +301,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = reinterpret_cast<cef_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_label_button))
+  if (CEF_MEMBER_MISSING(_struct, as_label_button)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -301,8 +319,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = reinterpret_cast<cef_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_state))
+  if (CEF_MEMBER_MISSING(_struct, set_state)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -314,8 +333,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = reinterpret_cast<cef_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_state))
+  if (CEF_MEMBER_MISSING(_struct, get_state)) {
     return CEF_BUTTON_STATE_NORMAL;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -331,8 +351,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = reinterpret_cast<cef_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_ink_drop_enabled))
+  if (CEF_MEMBER_MISSING(_struct, set_ink_drop_enabled)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -345,15 +366,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = reinterpret_cast<cef_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_tooltip_text))
+  if (CEF_MEMBER_MISSING(_struct, set_tooltip_text)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: tooltip_text; type: string_byref_const
   DCHECK(!tooltip_text.empty());
-  if (tooltip_text.empty())
+  if (tooltip_text.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_tooltip_text(_struct, tooltip_text.GetStruct());
@@ -364,15 +387,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_button_t* _struct = reinterpret_cast<cef_button_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_accessible_name))
+  if (CEF_MEMBER_MISSING(_struct, set_accessible_name)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_accessible_name(_struct, name.GetStruct());
@@ -383,8 +408,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_browser_view))
+  if (CEF_MEMBER_MISSING(_struct, as_browser_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -399,8 +425,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_button))
+  if (CEF_MEMBER_MISSING(_struct, as_button)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -415,8 +442,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_panel))
+  if (CEF_MEMBER_MISSING(_struct, as_panel)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -432,8 +460,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_scroll_view))
+  if (CEF_MEMBER_MISSING(_struct, as_scroll_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -449,8 +478,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_textfield))
+  if (CEF_MEMBER_MISSING(_struct, as_textfield)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -465,8 +495,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_type_string))
+  if (CEF_MEMBER_MISSING(_struct, get_type_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -484,8 +515,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, to_string))
+  if (CEF_MEMBER_MISSING(_struct, to_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -502,8 +534,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -518,8 +551,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_attached))
+  if (CEF_MEMBER_MISSING(_struct, is_attached)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -535,15 +569,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefViewCToCpp::Unwrap(that));
@@ -557,8 +593,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_delegate))
+  if (CEF_MEMBER_MISSING(_struct, get_delegate)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -573,8 +610,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_window))
+  if (CEF_MEMBER_MISSING(_struct, get_window)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -589,8 +627,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_id))
+  if (CEF_MEMBER_MISSING(_struct, get_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -605,8 +644,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_id))
+  if (CEF_MEMBER_MISSING(_struct, set_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -618,8 +658,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_group_id))
+  if (CEF_MEMBER_MISSING(_struct, get_group_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -634,8 +675,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_group_id))
+  if (CEF_MEMBER_MISSING(_struct, set_group_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -648,8 +690,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_parent_view))
+  if (CEF_MEMBER_MISSING(_struct, get_parent_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -665,8 +708,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_view_for_id))
+  if (CEF_MEMBER_MISSING(_struct, get_view_for_id)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -682,8 +726,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_bounds))
+  if (CEF_MEMBER_MISSING(_struct, set_bounds)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -695,8 +740,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_bounds))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -711,8 +757,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -728,8 +775,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_size))
+  if (CEF_MEMBER_MISSING(_struct, set_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -741,8 +789,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_size))
+  if (CEF_MEMBER_MISSING(_struct, get_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -758,8 +807,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_position))
+  if (CEF_MEMBER_MISSING(_struct, set_position)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -771,8 +821,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_position))
+  if (CEF_MEMBER_MISSING(_struct, get_position)) {
     return CefPoint();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -783,12 +834,45 @@
   return _retval;
 }
 
+NO_SANITIZE("cfi-icall")
+void CefMenuButtonCToCpp::SetInsets(const CefInsets& insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, set_insets)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->set_insets(_struct, &insets);
+}
+
+NO_SANITIZE("cfi-icall") CefInsets CefMenuButtonCToCpp::GetInsets() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, get_insets)) {
+    return CefInsets();
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_insets_t _retval = _struct->get_insets(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
 NO_SANITIZE("cfi-icall") CefSize CefMenuButtonCToCpp::GetPreferredSize() {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, get_preferred_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -803,8 +887,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -816,8 +901,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_minimum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -832,8 +918,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_maximum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -848,8 +935,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_height_for_width))
+  if (CEF_MEMBER_MISSING(_struct, get_height_for_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -864,8 +952,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, invalidate_layout))
+  if (CEF_MEMBER_MISSING(_struct, invalidate_layout)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -877,8 +966,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_visible))
+  if (CEF_MEMBER_MISSING(_struct, set_visible)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -890,8 +980,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_visible))
+  if (CEF_MEMBER_MISSING(_struct, is_visible)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -906,8 +997,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_drawn))
+  if (CEF_MEMBER_MISSING(_struct, is_drawn)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -922,8 +1014,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_enabled))
+  if (CEF_MEMBER_MISSING(_struct, set_enabled)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -935,8 +1028,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_enabled))
+  if (CEF_MEMBER_MISSING(_struct, is_enabled)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -952,8 +1046,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_focusable))
+  if (CEF_MEMBER_MISSING(_struct, set_focusable)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -965,8 +1060,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -981,8 +1077,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -997,8 +1094,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, request_focus))
+  if (CEF_MEMBER_MISSING(_struct, request_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1011,8 +1109,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_background_color))
+  if (CEF_MEMBER_MISSING(_struct, set_background_color)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1024,8 +1123,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_background_color))
+  if (CEF_MEMBER_MISSING(_struct, get_background_color)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1041,8 +1141,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1058,8 +1159,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1075,8 +1177,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1092,8 +1195,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1110,15 +1214,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_to_view(
@@ -1134,15 +1240,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_from_view(
@@ -1166,7 +1274,7 @@
 cef_menu_button_t*
 CefCToCppRefCounted<CefMenuButtonCToCpp, CefMenuButton, cef_menu_button_t>::
     UnwrapDerived(CefWrapperType type, CefMenuButton* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/menu_button_ctocpp.h b/src/libcef_dll/ctocpp/views/menu_button_ctocpp.h
index fbc5e3f..7729375 100644
--- a/src/libcef_dll/ctocpp/views/menu_button_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/menu_button_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7e2978dea2942c4ceeeb9d57609ee3fb0fa5bc4a$
+// $hash=0323c84d6099ab582a71a40f8065013cecc126cd$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_MENU_BUTTON_CTOCPP_H_
@@ -36,80 +36,82 @@
   // CefMenuButton methods.
   void ShowMenu(CefRefPtr<CefMenuModel> menu_model,
                 const CefPoint& screen_point,
-                cef_menu_anchor_position_t anchor_position) OVERRIDE;
-  void TriggerMenu() OVERRIDE;
+                cef_menu_anchor_position_t anchor_position) override;
+  void TriggerMenu() override;
 
   // CefLabelButton methods.
-  CefRefPtr<CefMenuButton> AsMenuButton() OVERRIDE;
-  void SetText(const CefString& text) OVERRIDE;
-  CefString GetText() OVERRIDE;
+  CefRefPtr<CefMenuButton> AsMenuButton() override;
+  void SetText(const CefString& text) override;
+  CefString GetText() override;
   void SetImage(cef_button_state_t button_state,
-                CefRefPtr<CefImage> image) OVERRIDE;
-  CefRefPtr<CefImage> GetImage(cef_button_state_t button_state) OVERRIDE;
-  void SetTextColor(cef_button_state_t for_state, cef_color_t color) OVERRIDE;
-  void SetEnabledTextColors(cef_color_t color) OVERRIDE;
-  void SetFontList(const CefString& font_list) OVERRIDE;
-  void SetHorizontalAlignment(cef_horizontal_alignment_t alignment) OVERRIDE;
-  void SetMinimumSize(const CefSize& size) OVERRIDE;
-  void SetMaximumSize(const CefSize& size) OVERRIDE;
+                CefRefPtr<CefImage> image) override;
+  CefRefPtr<CefImage> GetImage(cef_button_state_t button_state) override;
+  void SetTextColor(cef_button_state_t for_state, cef_color_t color) override;
+  void SetEnabledTextColors(cef_color_t color) override;
+  void SetFontList(const CefString& font_list) override;
+  void SetHorizontalAlignment(cef_horizontal_alignment_t alignment) override;
+  void SetMinimumSize(const CefSize& size) override;
+  void SetMaximumSize(const CefSize& size) override;
 
   // CefButton methods.
-  CefRefPtr<CefLabelButton> AsLabelButton() OVERRIDE;
-  void SetState(cef_button_state_t state) OVERRIDE;
-  cef_button_state_t GetState() OVERRIDE;
-  void SetInkDropEnabled(bool enabled) OVERRIDE;
-  void SetTooltipText(const CefString& tooltip_text) OVERRIDE;
-  void SetAccessibleName(const CefString& name) OVERRIDE;
+  CefRefPtr<CefLabelButton> AsLabelButton() override;
+  void SetState(cef_button_state_t state) override;
+  cef_button_state_t GetState() override;
+  void SetInkDropEnabled(bool enabled) override;
+  void SetTooltipText(const CefString& tooltip_text) override;
+  void SetAccessibleName(const CefString& name) override;
 
   // CefView methods.
-  CefRefPtr<CefBrowserView> AsBrowserView() OVERRIDE;
-  CefRefPtr<CefButton> AsButton() OVERRIDE;
-  CefRefPtr<CefPanel> AsPanel() OVERRIDE;
-  CefRefPtr<CefScrollView> AsScrollView() OVERRIDE;
-  CefRefPtr<CefTextfield> AsTextfield() OVERRIDE;
-  CefString GetTypeString() OVERRIDE;
-  CefString ToString(bool include_children) OVERRIDE;
-  bool IsValid() OVERRIDE;
-  bool IsAttached() OVERRIDE;
-  bool IsSame(CefRefPtr<CefView> that) OVERRIDE;
-  CefRefPtr<CefViewDelegate> GetDelegate() OVERRIDE;
-  CefRefPtr<CefWindow> GetWindow() OVERRIDE;
-  int GetID() OVERRIDE;
-  void SetID(int id) OVERRIDE;
-  int GetGroupID() OVERRIDE;
-  void SetGroupID(int group_id) OVERRIDE;
-  CefRefPtr<CefView> GetParentView() OVERRIDE;
-  CefRefPtr<CefView> GetViewForID(int id) OVERRIDE;
-  void SetBounds(const CefRect& bounds) OVERRIDE;
-  CefRect GetBounds() OVERRIDE;
-  CefRect GetBoundsInScreen() OVERRIDE;
-  void SetSize(const CefSize& size) OVERRIDE;
-  CefSize GetSize() OVERRIDE;
-  void SetPosition(const CefPoint& position) OVERRIDE;
-  CefPoint GetPosition() OVERRIDE;
-  CefSize GetPreferredSize() OVERRIDE;
-  void SizeToPreferredSize() OVERRIDE;
-  CefSize GetMinimumSize() OVERRIDE;
-  CefSize GetMaximumSize() OVERRIDE;
-  int GetHeightForWidth(int width) OVERRIDE;
-  void InvalidateLayout() OVERRIDE;
-  void SetVisible(bool visible) OVERRIDE;
-  bool IsVisible() OVERRIDE;
-  bool IsDrawn() OVERRIDE;
-  void SetEnabled(bool enabled) OVERRIDE;
-  bool IsEnabled() OVERRIDE;
-  void SetFocusable(bool focusable) OVERRIDE;
-  bool IsFocusable() OVERRIDE;
-  bool IsAccessibilityFocusable() OVERRIDE;
-  void RequestFocus() OVERRIDE;
-  void SetBackgroundColor(cef_color_t color) OVERRIDE;
-  cef_color_t GetBackgroundColor() OVERRIDE;
-  bool ConvertPointToScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointToWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
-  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
+  CefRefPtr<CefBrowserView> AsBrowserView() override;
+  CefRefPtr<CefButton> AsButton() override;
+  CefRefPtr<CefPanel> AsPanel() override;
+  CefRefPtr<CefScrollView> AsScrollView() override;
+  CefRefPtr<CefTextfield> AsTextfield() override;
+  CefString GetTypeString() override;
+  CefString ToString(bool include_children) override;
+  bool IsValid() override;
+  bool IsAttached() override;
+  bool IsSame(CefRefPtr<CefView> that) override;
+  CefRefPtr<CefViewDelegate> GetDelegate() override;
+  CefRefPtr<CefWindow> GetWindow() override;
+  int GetID() override;
+  void SetID(int id) override;
+  int GetGroupID() override;
+  void SetGroupID(int group_id) override;
+  CefRefPtr<CefView> GetParentView() override;
+  CefRefPtr<CefView> GetViewForID(int id) override;
+  void SetBounds(const CefRect& bounds) override;
+  CefRect GetBounds() override;
+  CefRect GetBoundsInScreen() override;
+  void SetSize(const CefSize& size) override;
+  CefSize GetSize() override;
+  void SetPosition(const CefPoint& position) override;
+  CefPoint GetPosition() override;
+  void SetInsets(const CefInsets& insets) override;
+  CefInsets GetInsets() override;
+  CefSize GetPreferredSize() override;
+  void SizeToPreferredSize() override;
+  CefSize GetMinimumSize() override;
+  CefSize GetMaximumSize() override;
+  int GetHeightForWidth(int width) override;
+  void InvalidateLayout() override;
+  void SetVisible(bool visible) override;
+  bool IsVisible() override;
+  bool IsDrawn() override;
+  void SetEnabled(bool enabled) override;
+  bool IsEnabled() override;
+  void SetFocusable(bool focusable) override;
+  bool IsFocusable() override;
+  bool IsAccessibilityFocusable() override;
+  void RequestFocus() override;
+  void SetBackgroundColor(cef_color_t color) override;
+  cef_color_t GetBackgroundColor() override;
+  bool ConvertPointToScreen(CefPoint& point) override;
+  bool ConvertPointFromScreen(CefPoint& point) override;
+  bool ConvertPointToWindow(CefPoint& point) override;
+  bool ConvertPointFromWindow(CefPoint& point) override;
+  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) override;
+  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_VIEWS_MENU_BUTTON_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/views/menu_button_delegate_ctocpp.cc b/src/libcef_dll/ctocpp/views/menu_button_delegate_ctocpp.cc
index de3a3e2..ce023f0 100644
--- a/src/libcef_dll/ctocpp/views/menu_button_delegate_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/menu_button_delegate_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e22af57f1e6505996368140760d9a249bf9189e9$
+// $hash=a27cc5bc8d6400e77100d275ba2609bbf3ef9e0f$
 //
 
 #include "libcef_dll/ctocpp/views/menu_button_delegate_ctocpp.h"
@@ -29,19 +29,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_menu_button_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_menu_button_pressed))
+  if (CEF_MEMBER_MISSING(_struct, on_menu_button_pressed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: menu_button; type: refptr_diff
   DCHECK(menu_button.get());
-  if (!menu_button.get())
+  if (!menu_button.get()) {
     return;
+  }
   // Verify param: button_pressed_lock; type: refptr_diff
   DCHECK(button_pressed_lock.get());
-  if (!button_pressed_lock.get())
+  if (!button_pressed_lock.get()) {
     return;
+  }
 
   // Execute
   _struct->on_menu_button_pressed(
@@ -55,15 +58,17 @@
 
   cef_button_delegate_t* _struct =
       reinterpret_cast<cef_button_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_button_pressed))
+  if (CEF_MEMBER_MISSING(_struct, on_button_pressed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: button; type: refptr_diff
   DCHECK(button.get());
-  if (!button.get())
+  if (!button.get()) {
     return;
+  }
 
   // Execute
   _struct->on_button_pressed(_struct, CefButtonCppToC::Wrap(button));
@@ -76,15 +81,17 @@
 
   cef_button_delegate_t* _struct =
       reinterpret_cast<cef_button_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_button_state_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_button_state_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: button; type: refptr_diff
   DCHECK(button.get());
-  if (!button.get())
+  if (!button.get()) {
     return;
+  }
 
   // Execute
   _struct->on_button_state_changed(_struct, CefButtonCppToC::Wrap(button));
@@ -96,15 +103,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, get_preferred_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -120,15 +129,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_minimum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -144,15 +155,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_maximum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -169,15 +182,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_height_for_width))
+  if (CEF_MEMBER_MISSING(_struct, get_height_for_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -196,19 +211,22 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_parent_view_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_parent_view_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
   // Verify param: parent; type: refptr_diff
   DCHECK(parent.get());
-  if (!parent.get())
+  if (!parent.get()) {
     return;
+  }
 
   // Execute
   _struct->on_parent_view_changed(_struct, CefViewCppToC::Wrap(view), added,
@@ -223,19 +241,22 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_child_view_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_child_view_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
   // Verify param: child; type: refptr_diff
   DCHECK(child.get());
-  if (!child.get())
+  if (!child.get()) {
     return;
+  }
 
   // Execute
   _struct->on_child_view_changed(_struct, CefViewCppToC::Wrap(view), added,
@@ -243,20 +264,68 @@
 }
 
 NO_SANITIZE("cfi-icall")
+void CefMenuButtonDelegateCToCpp::OnWindowChanged(CefRefPtr<CefView> view,
+                                                  bool added) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_delegate_t* _struct =
+      reinterpret_cast<cef_view_delegate_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, on_window_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: view; type: refptr_diff
+  DCHECK(view.get());
+  if (!view.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_window_changed(_struct, CefViewCppToC::Wrap(view), added);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefMenuButtonDelegateCToCpp::OnLayoutChanged(CefRefPtr<CefView> view,
+                                                  const CefRect& new_bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_delegate_t* _struct =
+      reinterpret_cast<cef_view_delegate_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, on_layout_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: view; type: refptr_diff
+  DCHECK(view.get());
+  if (!view.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_layout_changed(_struct, CefViewCppToC::Wrap(view), &new_bounds);
+}
+
+NO_SANITIZE("cfi-icall")
 void CefMenuButtonDelegateCToCpp::OnFocus(CefRefPtr<CefView> view) {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_focus))
+  if (CEF_MEMBER_MISSING(_struct, on_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->on_focus(_struct, CefViewCppToC::Wrap(view));
@@ -268,15 +337,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_blur))
+  if (CEF_MEMBER_MISSING(_struct, on_blur)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->on_blur(_struct, CefViewCppToC::Wrap(view));
@@ -298,7 +369,7 @@
     CefMenuButtonDelegate,
     cef_menu_button_delegate_t>::UnwrapDerived(CefWrapperType type,
                                                CefMenuButtonDelegate* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/menu_button_delegate_ctocpp.h b/src/libcef_dll/ctocpp/views/menu_button_delegate_ctocpp.h
index c49cb47..f890629 100644
--- a/src/libcef_dll/ctocpp/views/menu_button_delegate_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/menu_button_delegate_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=524d6cee4ca930e3ea4db6f08ab72e3d4578d19a$
+// $hash=962c2d2bc800670d19838fa2a34ab4faa8203531$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_MENU_BUTTON_DELEGATE_CTOCPP_H_
@@ -57,6 +57,9 @@
   void OnChildViewChanged(CefRefPtr<CefView> view,
                           bool added,
                           CefRefPtr<CefView> child) override;
+  void OnWindowChanged(CefRefPtr<CefView> view, bool added) override;
+  void OnLayoutChanged(CefRefPtr<CefView> view,
+                       const CefRect& new_bounds) override;
   void OnFocus(CefRefPtr<CefView> view) override;
   void OnBlur(CefRefPtr<CefView> view) override;
 };
diff --git a/src/libcef_dll/ctocpp/views/menu_button_pressed_lock_ctocpp.cc b/src/libcef_dll/ctocpp/views/menu_button_pressed_lock_ctocpp.cc
index b36bbfa..94aa17d 100644
--- a/src/libcef_dll/ctocpp/views/menu_button_pressed_lock_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/menu_button_pressed_lock_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=34a0389265fe422b1def87bb4c94115411c77c08$
+// $hash=75e19487438e6afe67c650ff5bf616a709c7273b$
 //
 
 #include "libcef_dll/ctocpp/views/menu_button_pressed_lock_ctocpp.h"
@@ -32,7 +32,7 @@
     cef_menu_button_pressed_lock_t>::UnwrapDerived(CefWrapperType type,
                                                    CefMenuButtonPressedLock*
                                                        c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/menu_button_pressed_lock_ctocpp.h b/src/libcef_dll/ctocpp/views/menu_button_pressed_lock_ctocpp.h
index ef8e36a..3a2ce08 100644
--- a/src/libcef_dll/ctocpp/views/menu_button_pressed_lock_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/menu_button_pressed_lock_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1727eb9fe6e45fbd1d5479fde119a58485af1022$
+// $hash=8c0bc19bcd5b9f53b0ee556fb0117e9a6115eb7f$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_MENU_BUTTON_PRESSED_LOCK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/views/overlay_controller_ctocpp.cc b/src/libcef_dll/ctocpp/views/overlay_controller_ctocpp.cc
new file mode 100644
index 0000000..2ca86d7
--- /dev/null
+++ b/src/libcef_dll/ctocpp/views/overlay_controller_ctocpp.cc
@@ -0,0 +1,366 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=c4c46d19e0b5234bca4f1051d0113af666dc2c09$
+//
+
+#include "libcef_dll/ctocpp/views/overlay_controller_ctocpp.h"
+#include "libcef_dll/ctocpp/views/view_ctocpp.h"
+#include "libcef_dll/ctocpp/views/window_ctocpp.h"
+#include "libcef_dll/shutdown_checker.h"
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+NO_SANITIZE("cfi-icall") bool CefOverlayControllerCToCpp::IsValid() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = _struct->is_valid(_struct);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefOverlayControllerCToCpp::IsSame(CefRefPtr<CefOverlayController> that) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: that; type: refptr_same
+  DCHECK(that.get());
+  if (!that.get()) {
+    return false;
+  }
+
+  // Execute
+  int _retval =
+      _struct->is_same(_struct, CefOverlayControllerCToCpp::Unwrap(that));
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+CefRefPtr<CefView> CefOverlayControllerCToCpp::GetContentsView() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_contents_view)) {
+    return nullptr;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_view_t* _retval = _struct->get_contents_view(_struct);
+
+  // Return type: refptr_same
+  return CefViewCToCpp::Wrap(_retval);
+}
+
+NO_SANITIZE("cfi-icall")
+CefRefPtr<CefWindow> CefOverlayControllerCToCpp::GetWindow() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_window)) {
+    return nullptr;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_window_t* _retval = _struct->get_window(_struct);
+
+  // Return type: refptr_same
+  return CefWindowCToCpp::Wrap(_retval);
+}
+
+NO_SANITIZE("cfi-icall")
+cef_docking_mode_t CefOverlayControllerCToCpp::GetDockingMode() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_docking_mode)) {
+    return CEF_DOCKING_MODE_TOP_LEFT;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_docking_mode_t _retval = _struct->get_docking_mode(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall") void CefOverlayControllerCToCpp::Destroy() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, destroy)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->destroy(_struct);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefOverlayControllerCToCpp::SetBounds(const CefRect& bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, set_bounds)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->set_bounds(_struct, &bounds);
+}
+
+NO_SANITIZE("cfi-icall") CefRect CefOverlayControllerCToCpp::GetBounds() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_bounds)) {
+    return CefRect();
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_rect_t _retval = _struct->get_bounds(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall")
+CefRect CefOverlayControllerCToCpp::GetBoundsInScreen() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen)) {
+    return CefRect();
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_rect_t _retval = _struct->get_bounds_in_screen(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall")
+void CefOverlayControllerCToCpp::SetSize(const CefSize& size) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, set_size)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->set_size(_struct, &size);
+}
+
+NO_SANITIZE("cfi-icall") CefSize CefOverlayControllerCToCpp::GetSize() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_size)) {
+    return CefSize();
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_size_t _retval = _struct->get_size(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall")
+void CefOverlayControllerCToCpp::SetPosition(const CefPoint& position) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, set_position)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->set_position(_struct, &position);
+}
+
+NO_SANITIZE("cfi-icall") CefPoint CefOverlayControllerCToCpp::GetPosition() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_position)) {
+    return CefPoint();
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_point_t _retval = _struct->get_position(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall")
+void CefOverlayControllerCToCpp::SetInsets(const CefInsets& insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, set_insets)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->set_insets(_struct, &insets);
+}
+
+NO_SANITIZE("cfi-icall") CefInsets CefOverlayControllerCToCpp::GetInsets() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_insets)) {
+    return CefInsets();
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_insets_t _retval = _struct->get_insets(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall")
+void CefOverlayControllerCToCpp::SizeToPreferredSize() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->size_to_preferred_size(_struct);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefOverlayControllerCToCpp::SetVisible(bool visible) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, set_visible)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->set_visible(_struct, visible);
+}
+
+NO_SANITIZE("cfi-icall") bool CefOverlayControllerCToCpp::IsVisible() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, is_visible)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = _struct->is_visible(_struct);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall") bool CefOverlayControllerCToCpp::IsDrawn() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_overlay_controller_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, is_drawn)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = _struct->is_drawn(_struct);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefOverlayControllerCToCpp::CefOverlayControllerCToCpp() {}
+
+// DESTRUCTOR - Do not edit by hand.
+
+CefOverlayControllerCToCpp::~CefOverlayControllerCToCpp() {
+  shutdown_checker::AssertNotShutdown();
+}
+
+template <>
+cef_overlay_controller_t* CefCToCppRefCounted<
+    CefOverlayControllerCToCpp,
+    CefOverlayController,
+    cef_overlay_controller_t>::UnwrapDerived(CefWrapperType type,
+                                             CefOverlayController* c) {
+  DCHECK(false) << "Unexpected class type: " << type;
+  return nullptr;
+}
+
+template <>
+CefWrapperType CefCToCppRefCounted<CefOverlayControllerCToCpp,
+                                   CefOverlayController,
+                                   cef_overlay_controller_t>::kWrapperType =
+    WT_OVERLAY_CONTROLLER;
diff --git a/src/libcef_dll/ctocpp/views/overlay_controller_ctocpp.h b/src/libcef_dll/ctocpp/views/overlay_controller_ctocpp.h
new file mode 100644
index 0000000..e8c47e0
--- /dev/null
+++ b/src/libcef_dll/ctocpp/views/overlay_controller_ctocpp.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
+// reserved. Use of this source code is governed by a BSD-style license that
+// can be found in the LICENSE file.
+//
+// ---------------------------------------------------------------------------
+//
+// This file was generated by the CEF translator tool. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+// $hash=a8dd9d8eb796f499231143866c2d8f45e9b25d0c$
+//
+
+#ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_OVERLAY_CONTROLLER_CTOCPP_H_
+#define CEF_LIBCEF_DLL_CTOCPP_VIEWS_OVERLAY_CONTROLLER_CTOCPP_H_
+#pragma once
+
+#if !defined(WRAPPING_CEF_SHARED)
+#error This file can be included wrapper-side only
+#endif
+
+#include "include/capi/views/cef_overlay_controller_capi.h"
+#include "include/capi/views/cef_view_capi.h"
+#include "include/capi/views/cef_window_capi.h"
+#include "include/views/cef_overlay_controller.h"
+#include "include/views/cef_view.h"
+#include "include/views/cef_window.h"
+#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
+
+// Wrap a C structure with a C++ class.
+// This class may be instantiated and accessed wrapper-side only.
+class CefOverlayControllerCToCpp
+    : public CefCToCppRefCounted<CefOverlayControllerCToCpp,
+                                 CefOverlayController,
+                                 cef_overlay_controller_t> {
+ public:
+  CefOverlayControllerCToCpp();
+  virtual ~CefOverlayControllerCToCpp();
+
+  // CefOverlayController methods.
+  bool IsValid() override;
+  bool IsSame(CefRefPtr<CefOverlayController> that) override;
+  CefRefPtr<CefView> GetContentsView() override;
+  CefRefPtr<CefWindow> GetWindow() override;
+  cef_docking_mode_t GetDockingMode() override;
+  void Destroy() override;
+  void SetBounds(const CefRect& bounds) override;
+  CefRect GetBounds() override;
+  CefRect GetBoundsInScreen() override;
+  void SetSize(const CefSize& size) override;
+  CefSize GetSize() override;
+  void SetPosition(const CefPoint& position) override;
+  CefPoint GetPosition() override;
+  void SetInsets(const CefInsets& insets) override;
+  CefInsets GetInsets() override;
+  void SizeToPreferredSize() override;
+  void SetVisible(bool visible) override;
+  bool IsVisible() override;
+  bool IsDrawn() override;
+};
+
+#endif  // CEF_LIBCEF_DLL_CTOCPP_VIEWS_OVERLAY_CONTROLLER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/views/panel_ctocpp.cc b/src/libcef_dll/ctocpp/views/panel_ctocpp.cc
index e5e4003..cf0f2ac 100644
--- a/src/libcef_dll/ctocpp/views/panel_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/panel_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=9821af1835fd4289a117b3dba1b893b5bf83dd55$
+// $hash=c757b375edf4dd35fb31c4ae81048aa795b2518b$
 //
 
 #include "libcef_dll/ctocpp/views/panel_ctocpp.h"
@@ -51,8 +51,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, as_window))
+  if (CEF_MEMBER_MISSING(_struct, as_window)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -68,8 +69,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_to_fill_layout))
+  if (CEF_MEMBER_MISSING(_struct, set_to_fill_layout)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -86,8 +88,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_to_box_layout))
+  if (CEF_MEMBER_MISSING(_struct, set_to_box_layout)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -102,8 +105,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_layout))
+  if (CEF_MEMBER_MISSING(_struct, get_layout)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -118,8 +122,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, layout))
+  if (CEF_MEMBER_MISSING(_struct, layout)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -132,15 +137,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, add_child_view))
+  if (CEF_MEMBER_MISSING(_struct, add_child_view)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->add_child_view(_struct, CefViewCToCpp::Unwrap(view));
@@ -151,19 +158,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, add_child_view_at))
+  if (CEF_MEMBER_MISSING(_struct, add_child_view_at)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return;
+  }
 
   // Execute
   _struct->add_child_view_at(_struct, CefViewCToCpp::Unwrap(view), index);
@@ -174,15 +184,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, reorder_child_view))
+  if (CEF_MEMBER_MISSING(_struct, reorder_child_view)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->reorder_child_view(_struct, CefViewCToCpp::Unwrap(view), index);
@@ -193,15 +205,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, remove_child_view))
+  if (CEF_MEMBER_MISSING(_struct, remove_child_view)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->remove_child_view(_struct, CefViewCToCpp::Unwrap(view));
@@ -211,8 +225,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, remove_all_child_views))
+  if (CEF_MEMBER_MISSING(_struct, remove_all_child_views)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -224,8 +239,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_child_view_count))
+  if (CEF_MEMBER_MISSING(_struct, get_child_view_count)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -241,15 +257,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_child_view_at))
+  if (CEF_MEMBER_MISSING(_struct, get_child_view_at)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return nullptr;
+  }
 
   // Execute
   cef_view_t* _retval = _struct->get_child_view_at(_struct, index);
@@ -263,8 +281,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_browser_view))
+  if (CEF_MEMBER_MISSING(_struct, as_browser_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -279,8 +298,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_button))
+  if (CEF_MEMBER_MISSING(_struct, as_button)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -295,8 +315,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_panel))
+  if (CEF_MEMBER_MISSING(_struct, as_panel)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -312,8 +333,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_scroll_view))
+  if (CEF_MEMBER_MISSING(_struct, as_scroll_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -328,8 +350,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_textfield))
+  if (CEF_MEMBER_MISSING(_struct, as_textfield)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -344,8 +367,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_type_string))
+  if (CEF_MEMBER_MISSING(_struct, get_type_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -363,8 +387,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, to_string))
+  if (CEF_MEMBER_MISSING(_struct, to_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -381,8 +406,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -397,8 +423,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_attached))
+  if (CEF_MEMBER_MISSING(_struct, is_attached)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -413,15 +440,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefViewCToCpp::Unwrap(that));
@@ -435,8 +464,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_delegate))
+  if (CEF_MEMBER_MISSING(_struct, get_delegate)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -451,8 +481,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_window))
+  if (CEF_MEMBER_MISSING(_struct, get_window)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -467,8 +498,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_id))
+  if (CEF_MEMBER_MISSING(_struct, get_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -483,8 +515,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_id))
+  if (CEF_MEMBER_MISSING(_struct, set_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -496,8 +529,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_group_id))
+  if (CEF_MEMBER_MISSING(_struct, get_group_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -512,8 +546,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_group_id))
+  if (CEF_MEMBER_MISSING(_struct, set_group_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -525,8 +560,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_parent_view))
+  if (CEF_MEMBER_MISSING(_struct, get_parent_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -542,8 +578,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_view_for_id))
+  if (CEF_MEMBER_MISSING(_struct, get_view_for_id)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -558,8 +595,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_bounds))
+  if (CEF_MEMBER_MISSING(_struct, set_bounds)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -571,8 +609,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_bounds))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -587,8 +626,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -603,8 +643,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_size))
+  if (CEF_MEMBER_MISSING(_struct, set_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -616,8 +657,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_size))
+  if (CEF_MEMBER_MISSING(_struct, get_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -633,8 +675,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_position))
+  if (CEF_MEMBER_MISSING(_struct, set_position)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -646,8 +689,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_position))
+  if (CEF_MEMBER_MISSING(_struct, get_position)) {
     return CefPoint();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -658,12 +702,45 @@
   return _retval;
 }
 
+NO_SANITIZE("cfi-icall")
+void CefPanelCToCpp::SetInsets(const CefInsets& insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, set_insets)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->set_insets(_struct, &insets);
+}
+
+NO_SANITIZE("cfi-icall") CefInsets CefPanelCToCpp::GetInsets() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, get_insets)) {
+    return CefInsets();
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_insets_t _retval = _struct->get_insets(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
 NO_SANITIZE("cfi-icall") CefSize CefPanelCToCpp::GetPreferredSize() {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, get_preferred_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -678,8 +755,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -691,8 +769,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_minimum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -707,8 +786,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_maximum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -723,8 +803,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_height_for_width))
+  if (CEF_MEMBER_MISSING(_struct, get_height_for_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -739,8 +820,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, invalidate_layout))
+  if (CEF_MEMBER_MISSING(_struct, invalidate_layout)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -752,8 +834,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_visible))
+  if (CEF_MEMBER_MISSING(_struct, set_visible)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -765,8 +848,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_visible))
+  if (CEF_MEMBER_MISSING(_struct, is_visible)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -781,8 +865,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_drawn))
+  if (CEF_MEMBER_MISSING(_struct, is_drawn)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -797,8 +882,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_enabled))
+  if (CEF_MEMBER_MISSING(_struct, set_enabled)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -810,8 +896,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_enabled))
+  if (CEF_MEMBER_MISSING(_struct, is_enabled)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -826,8 +913,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_focusable))
+  if (CEF_MEMBER_MISSING(_struct, set_focusable)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -839,8 +927,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -855,8 +944,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -871,8 +961,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, request_focus))
+  if (CEF_MEMBER_MISSING(_struct, request_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -885,8 +976,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_background_color))
+  if (CEF_MEMBER_MISSING(_struct, set_background_color)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -898,8 +990,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_background_color))
+  if (CEF_MEMBER_MISSING(_struct, get_background_color)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -915,8 +1008,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -932,8 +1026,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -949,8 +1044,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -966,8 +1062,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -984,15 +1081,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_to_view(
@@ -1008,15 +1107,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_from_view(
@@ -1045,7 +1146,7 @@
     return reinterpret_cast<cef_panel_t*>(
         CefWindowCToCpp::Unwrap(reinterpret_cast<CefWindow*>(c)));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/panel_ctocpp.h b/src/libcef_dll/ctocpp/views/panel_ctocpp.h
index 5e37994..ee6410b 100644
--- a/src/libcef_dll/ctocpp/views/panel_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/panel_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=a2ad3c9f6314f8c05b6d807ec887c1aa67780cb6$
+// $hash=c0c4823d1084bd1ea4f2065e93b51a56718bed87$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_PANEL_CTOCPP_H_
@@ -41,69 +41,71 @@
   virtual ~CefPanelCToCpp();
 
   // CefPanel methods.
-  CefRefPtr<CefWindow> AsWindow() OVERRIDE;
-  CefRefPtr<CefFillLayout> SetToFillLayout() OVERRIDE;
+  CefRefPtr<CefWindow> AsWindow() override;
+  CefRefPtr<CefFillLayout> SetToFillLayout() override;
   CefRefPtr<CefBoxLayout> SetToBoxLayout(
-      const CefBoxLayoutSettings& settings) OVERRIDE;
-  CefRefPtr<CefLayout> GetLayout() OVERRIDE;
-  void Layout() OVERRIDE;
-  void AddChildView(CefRefPtr<CefView> view) OVERRIDE;
-  void AddChildViewAt(CefRefPtr<CefView> view, int index) OVERRIDE;
-  void ReorderChildView(CefRefPtr<CefView> view, int index) OVERRIDE;
-  void RemoveChildView(CefRefPtr<CefView> view) OVERRIDE;
-  void RemoveAllChildViews() OVERRIDE;
-  size_t GetChildViewCount() OVERRIDE;
-  CefRefPtr<CefView> GetChildViewAt(int index) OVERRIDE;
+      const CefBoxLayoutSettings& settings) override;
+  CefRefPtr<CefLayout> GetLayout() override;
+  void Layout() override;
+  void AddChildView(CefRefPtr<CefView> view) override;
+  void AddChildViewAt(CefRefPtr<CefView> view, int index) override;
+  void ReorderChildView(CefRefPtr<CefView> view, int index) override;
+  void RemoveChildView(CefRefPtr<CefView> view) override;
+  void RemoveAllChildViews() override;
+  size_t GetChildViewCount() override;
+  CefRefPtr<CefView> GetChildViewAt(int index) override;
 
   // CefView methods.
-  CefRefPtr<CefBrowserView> AsBrowserView() OVERRIDE;
-  CefRefPtr<CefButton> AsButton() OVERRIDE;
-  CefRefPtr<CefPanel> AsPanel() OVERRIDE;
-  CefRefPtr<CefScrollView> AsScrollView() OVERRIDE;
-  CefRefPtr<CefTextfield> AsTextfield() OVERRIDE;
-  CefString GetTypeString() OVERRIDE;
-  CefString ToString(bool include_children) OVERRIDE;
-  bool IsValid() OVERRIDE;
-  bool IsAttached() OVERRIDE;
-  bool IsSame(CefRefPtr<CefView> that) OVERRIDE;
-  CefRefPtr<CefViewDelegate> GetDelegate() OVERRIDE;
-  CefRefPtr<CefWindow> GetWindow() OVERRIDE;
-  int GetID() OVERRIDE;
-  void SetID(int id) OVERRIDE;
-  int GetGroupID() OVERRIDE;
-  void SetGroupID(int group_id) OVERRIDE;
-  CefRefPtr<CefView> GetParentView() OVERRIDE;
-  CefRefPtr<CefView> GetViewForID(int id) OVERRIDE;
-  void SetBounds(const CefRect& bounds) OVERRIDE;
-  CefRect GetBounds() OVERRIDE;
-  CefRect GetBoundsInScreen() OVERRIDE;
-  void SetSize(const CefSize& size) OVERRIDE;
-  CefSize GetSize() OVERRIDE;
-  void SetPosition(const CefPoint& position) OVERRIDE;
-  CefPoint GetPosition() OVERRIDE;
-  CefSize GetPreferredSize() OVERRIDE;
-  void SizeToPreferredSize() OVERRIDE;
-  CefSize GetMinimumSize() OVERRIDE;
-  CefSize GetMaximumSize() OVERRIDE;
-  int GetHeightForWidth(int width) OVERRIDE;
-  void InvalidateLayout() OVERRIDE;
-  void SetVisible(bool visible) OVERRIDE;
-  bool IsVisible() OVERRIDE;
-  bool IsDrawn() OVERRIDE;
-  void SetEnabled(bool enabled) OVERRIDE;
-  bool IsEnabled() OVERRIDE;
-  void SetFocusable(bool focusable) OVERRIDE;
-  bool IsFocusable() OVERRIDE;
-  bool IsAccessibilityFocusable() OVERRIDE;
-  void RequestFocus() OVERRIDE;
-  void SetBackgroundColor(cef_color_t color) OVERRIDE;
-  cef_color_t GetBackgroundColor() OVERRIDE;
-  bool ConvertPointToScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointToWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
-  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
+  CefRefPtr<CefBrowserView> AsBrowserView() override;
+  CefRefPtr<CefButton> AsButton() override;
+  CefRefPtr<CefPanel> AsPanel() override;
+  CefRefPtr<CefScrollView> AsScrollView() override;
+  CefRefPtr<CefTextfield> AsTextfield() override;
+  CefString GetTypeString() override;
+  CefString ToString(bool include_children) override;
+  bool IsValid() override;
+  bool IsAttached() override;
+  bool IsSame(CefRefPtr<CefView> that) override;
+  CefRefPtr<CefViewDelegate> GetDelegate() override;
+  CefRefPtr<CefWindow> GetWindow() override;
+  int GetID() override;
+  void SetID(int id) override;
+  int GetGroupID() override;
+  void SetGroupID(int group_id) override;
+  CefRefPtr<CefView> GetParentView() override;
+  CefRefPtr<CefView> GetViewForID(int id) override;
+  void SetBounds(const CefRect& bounds) override;
+  CefRect GetBounds() override;
+  CefRect GetBoundsInScreen() override;
+  void SetSize(const CefSize& size) override;
+  CefSize GetSize() override;
+  void SetPosition(const CefPoint& position) override;
+  CefPoint GetPosition() override;
+  void SetInsets(const CefInsets& insets) override;
+  CefInsets GetInsets() override;
+  CefSize GetPreferredSize() override;
+  void SizeToPreferredSize() override;
+  CefSize GetMinimumSize() override;
+  CefSize GetMaximumSize() override;
+  int GetHeightForWidth(int width) override;
+  void InvalidateLayout() override;
+  void SetVisible(bool visible) override;
+  bool IsVisible() override;
+  bool IsDrawn() override;
+  void SetEnabled(bool enabled) override;
+  bool IsEnabled() override;
+  void SetFocusable(bool focusable) override;
+  bool IsFocusable() override;
+  bool IsAccessibilityFocusable() override;
+  void RequestFocus() override;
+  void SetBackgroundColor(cef_color_t color) override;
+  cef_color_t GetBackgroundColor() override;
+  bool ConvertPointToScreen(CefPoint& point) override;
+  bool ConvertPointFromScreen(CefPoint& point) override;
+  bool ConvertPointToWindow(CefPoint& point) override;
+  bool ConvertPointFromWindow(CefPoint& point) override;
+  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) override;
+  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_VIEWS_PANEL_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/views/panel_delegate_ctocpp.cc b/src/libcef_dll/ctocpp/views/panel_delegate_ctocpp.cc
index 9e904ce..b021b29 100644
--- a/src/libcef_dll/ctocpp/views/panel_delegate_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/panel_delegate_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c6d5a6d79d6e0ccb4e35b2f4bda92b2b99ba70bf$
+// $hash=046029bba50f8d46cf3c5192d891aee370f21565$
 //
 
 #include "libcef_dll/ctocpp/views/panel_delegate_ctocpp.h"
@@ -25,15 +25,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, get_preferred_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -49,15 +51,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_minimum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -73,15 +77,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_maximum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -98,15 +104,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_height_for_width))
+  if (CEF_MEMBER_MISSING(_struct, get_height_for_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -124,19 +132,22 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_parent_view_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_parent_view_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
   // Verify param: parent; type: refptr_diff
   DCHECK(parent.get());
-  if (!parent.get())
+  if (!parent.get()) {
     return;
+  }
 
   // Execute
   _struct->on_parent_view_changed(_struct, CefViewCppToC::Wrap(view), added,
@@ -151,19 +162,22 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_child_view_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_child_view_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
   // Verify param: child; type: refptr_diff
   DCHECK(child.get());
-  if (!child.get())
+  if (!child.get()) {
     return;
+  }
 
   // Execute
   _struct->on_child_view_changed(_struct, CefViewCppToC::Wrap(view), added,
@@ -171,20 +185,68 @@
 }
 
 NO_SANITIZE("cfi-icall")
+void CefPanelDelegateCToCpp::OnWindowChanged(CefRefPtr<CefView> view,
+                                             bool added) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_delegate_t* _struct =
+      reinterpret_cast<cef_view_delegate_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, on_window_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: view; type: refptr_diff
+  DCHECK(view.get());
+  if (!view.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_window_changed(_struct, CefViewCppToC::Wrap(view), added);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefPanelDelegateCToCpp::OnLayoutChanged(CefRefPtr<CefView> view,
+                                             const CefRect& new_bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_delegate_t* _struct =
+      reinterpret_cast<cef_view_delegate_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, on_layout_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: view; type: refptr_diff
+  DCHECK(view.get());
+  if (!view.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_layout_changed(_struct, CefViewCppToC::Wrap(view), &new_bounds);
+}
+
+NO_SANITIZE("cfi-icall")
 void CefPanelDelegateCToCpp::OnFocus(CefRefPtr<CefView> view) {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_focus))
+  if (CEF_MEMBER_MISSING(_struct, on_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->on_focus(_struct, CefViewCppToC::Wrap(view));
@@ -196,15 +258,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_blur))
+  if (CEF_MEMBER_MISSING(_struct, on_blur)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->on_blur(_struct, CefViewCppToC::Wrap(view));
@@ -231,7 +295,7 @@
         CefWindowDelegateCToCpp::Unwrap(
             reinterpret_cast<CefWindowDelegate*>(c)));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/panel_delegate_ctocpp.h b/src/libcef_dll/ctocpp/views/panel_delegate_ctocpp.h
index 4c8748e..62fd16d 100644
--- a/src/libcef_dll/ctocpp/views/panel_delegate_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/panel_delegate_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e5532f84397754cb9c2da1beeea8107ea5ab258b$
+// $hash=dcad633b9f91da4e5b08cfa8be122b6797211b46$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_PANEL_DELEGATE_CTOCPP_H_
@@ -47,6 +47,9 @@
   void OnChildViewChanged(CefRefPtr<CefView> view,
                           bool added,
                           CefRefPtr<CefView> child) override;
+  void OnWindowChanged(CefRefPtr<CefView> view, bool added) override;
+  void OnLayoutChanged(CefRefPtr<CefView> view,
+                       const CefRect& new_bounds) override;
   void OnFocus(CefRefPtr<CefView> view) override;
   void OnBlur(CefRefPtr<CefView> view) override;
 };
diff --git a/src/libcef_dll/ctocpp/views/scroll_view_ctocpp.cc b/src/libcef_dll/ctocpp/views/scroll_view_ctocpp.cc
index 9233777..300823e 100644
--- a/src/libcef_dll/ctocpp/views/scroll_view_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/scroll_view_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=1f55cd5b15e391c8e20faf3d060c46d36ead0a96$
+// $hash=b41b92f818aca51a1f14e5d3d57fa42d13f8590a$
 //
 
 #include "libcef_dll/ctocpp/views/scroll_view_ctocpp.h"
@@ -48,15 +48,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_scroll_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_content_view))
+  if (CEF_MEMBER_MISSING(_struct, set_content_view)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->set_content_view(_struct, CefViewCToCpp::Unwrap(view));
@@ -67,8 +69,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_scroll_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_content_view))
+  if (CEF_MEMBER_MISSING(_struct, get_content_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -83,8 +86,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_scroll_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_visible_content_rect))
+  if (CEF_MEMBER_MISSING(_struct, get_visible_content_rect)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -99,8 +103,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_scroll_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_horizontal_scrollbar))
+  if (CEF_MEMBER_MISSING(_struct, has_horizontal_scrollbar)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -116,8 +121,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_scroll_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_horizontal_scrollbar_height))
+  if (CEF_MEMBER_MISSING(_struct, get_horizontal_scrollbar_height)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -132,8 +138,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_scroll_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_vertical_scrollbar))
+  if (CEF_MEMBER_MISSING(_struct, has_vertical_scrollbar)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -148,8 +155,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_scroll_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_vertical_scrollbar_width))
+  if (CEF_MEMBER_MISSING(_struct, get_vertical_scrollbar_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -165,8 +173,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_browser_view))
+  if (CEF_MEMBER_MISSING(_struct, as_browser_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -181,8 +190,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_button))
+  if (CEF_MEMBER_MISSING(_struct, as_button)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -197,8 +207,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_panel))
+  if (CEF_MEMBER_MISSING(_struct, as_panel)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -214,8 +225,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_scroll_view))
+  if (CEF_MEMBER_MISSING(_struct, as_scroll_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -231,8 +243,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_textfield))
+  if (CEF_MEMBER_MISSING(_struct, as_textfield)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -247,8 +260,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_type_string))
+  if (CEF_MEMBER_MISSING(_struct, get_type_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -266,8 +280,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, to_string))
+  if (CEF_MEMBER_MISSING(_struct, to_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -284,8 +299,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -300,8 +316,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_attached))
+  if (CEF_MEMBER_MISSING(_struct, is_attached)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -317,15 +334,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefViewCToCpp::Unwrap(that));
@@ -339,8 +358,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_delegate))
+  if (CEF_MEMBER_MISSING(_struct, get_delegate)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -355,8 +375,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_window))
+  if (CEF_MEMBER_MISSING(_struct, get_window)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -371,8 +392,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_id))
+  if (CEF_MEMBER_MISSING(_struct, get_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -387,8 +409,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_id))
+  if (CEF_MEMBER_MISSING(_struct, set_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -400,8 +423,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_group_id))
+  if (CEF_MEMBER_MISSING(_struct, get_group_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -416,8 +440,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_group_id))
+  if (CEF_MEMBER_MISSING(_struct, set_group_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -430,8 +455,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_parent_view))
+  if (CEF_MEMBER_MISSING(_struct, get_parent_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -447,8 +473,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_view_for_id))
+  if (CEF_MEMBER_MISSING(_struct, get_view_for_id)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -464,8 +491,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_bounds))
+  if (CEF_MEMBER_MISSING(_struct, set_bounds)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -477,8 +505,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_bounds))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -493,8 +522,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -510,8 +540,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_size))
+  if (CEF_MEMBER_MISSING(_struct, set_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -523,8 +554,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_size))
+  if (CEF_MEMBER_MISSING(_struct, get_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -540,8 +572,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_position))
+  if (CEF_MEMBER_MISSING(_struct, set_position)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -553,8 +586,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_position))
+  if (CEF_MEMBER_MISSING(_struct, get_position)) {
     return CefPoint();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -565,12 +599,45 @@
   return _retval;
 }
 
+NO_SANITIZE("cfi-icall")
+void CefScrollViewCToCpp::SetInsets(const CefInsets& insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, set_insets)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->set_insets(_struct, &insets);
+}
+
+NO_SANITIZE("cfi-icall") CefInsets CefScrollViewCToCpp::GetInsets() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, get_insets)) {
+    return CefInsets();
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_insets_t _retval = _struct->get_insets(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
 NO_SANITIZE("cfi-icall") CefSize CefScrollViewCToCpp::GetPreferredSize() {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, get_preferred_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -585,8 +652,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -598,8 +666,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_minimum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -614,8 +683,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_maximum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -630,8 +700,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_height_for_width))
+  if (CEF_MEMBER_MISSING(_struct, get_height_for_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -646,8 +717,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, invalidate_layout))
+  if (CEF_MEMBER_MISSING(_struct, invalidate_layout)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -659,8 +731,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_visible))
+  if (CEF_MEMBER_MISSING(_struct, set_visible)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -672,8 +745,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_visible))
+  if (CEF_MEMBER_MISSING(_struct, is_visible)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -688,8 +762,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_drawn))
+  if (CEF_MEMBER_MISSING(_struct, is_drawn)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -704,8 +779,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_enabled))
+  if (CEF_MEMBER_MISSING(_struct, set_enabled)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -717,8 +793,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_enabled))
+  if (CEF_MEMBER_MISSING(_struct, is_enabled)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -734,8 +811,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_focusable))
+  if (CEF_MEMBER_MISSING(_struct, set_focusable)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -747,8 +825,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -763,8 +842,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -779,8 +859,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, request_focus))
+  if (CEF_MEMBER_MISSING(_struct, request_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -793,8 +874,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_background_color))
+  if (CEF_MEMBER_MISSING(_struct, set_background_color)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -806,8 +888,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_background_color))
+  if (CEF_MEMBER_MISSING(_struct, get_background_color)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -823,8 +906,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -840,8 +924,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -857,8 +942,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -874,8 +960,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -892,15 +979,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_to_view(
@@ -916,15 +1005,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_from_view(
@@ -948,7 +1039,7 @@
 cef_scroll_view_t*
 CefCToCppRefCounted<CefScrollViewCToCpp, CefScrollView, cef_scroll_view_t>::
     UnwrapDerived(CefWrapperType type, CefScrollView* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/scroll_view_ctocpp.h b/src/libcef_dll/ctocpp/views/scroll_view_ctocpp.h
index 258f965..5ceb93d 100644
--- a/src/libcef_dll/ctocpp/views/scroll_view_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/scroll_view_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=4e98f8d65f5844c90f1b9fc2a7c6ecde10a11d84$
+// $hash=3a3c2eee1765f8a1d86044eadc75eca9c6fae25f$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_SCROLL_VIEW_CTOCPP_H_
@@ -34,63 +34,65 @@
   virtual ~CefScrollViewCToCpp();
 
   // CefScrollView methods.
-  void SetContentView(CefRefPtr<CefView> view) OVERRIDE;
-  CefRefPtr<CefView> GetContentView() OVERRIDE;
-  CefRect GetVisibleContentRect() OVERRIDE;
-  bool HasHorizontalScrollbar() OVERRIDE;
-  int GetHorizontalScrollbarHeight() OVERRIDE;
-  bool HasVerticalScrollbar() OVERRIDE;
-  int GetVerticalScrollbarWidth() OVERRIDE;
+  void SetContentView(CefRefPtr<CefView> view) override;
+  CefRefPtr<CefView> GetContentView() override;
+  CefRect GetVisibleContentRect() override;
+  bool HasHorizontalScrollbar() override;
+  int GetHorizontalScrollbarHeight() override;
+  bool HasVerticalScrollbar() override;
+  int GetVerticalScrollbarWidth() override;
 
   // CefView methods.
-  CefRefPtr<CefBrowserView> AsBrowserView() OVERRIDE;
-  CefRefPtr<CefButton> AsButton() OVERRIDE;
-  CefRefPtr<CefPanel> AsPanel() OVERRIDE;
-  CefRefPtr<CefScrollView> AsScrollView() OVERRIDE;
-  CefRefPtr<CefTextfield> AsTextfield() OVERRIDE;
-  CefString GetTypeString() OVERRIDE;
-  CefString ToString(bool include_children) OVERRIDE;
-  bool IsValid() OVERRIDE;
-  bool IsAttached() OVERRIDE;
-  bool IsSame(CefRefPtr<CefView> that) OVERRIDE;
-  CefRefPtr<CefViewDelegate> GetDelegate() OVERRIDE;
-  CefRefPtr<CefWindow> GetWindow() OVERRIDE;
-  int GetID() OVERRIDE;
-  void SetID(int id) OVERRIDE;
-  int GetGroupID() OVERRIDE;
-  void SetGroupID(int group_id) OVERRIDE;
-  CefRefPtr<CefView> GetParentView() OVERRIDE;
-  CefRefPtr<CefView> GetViewForID(int id) OVERRIDE;
-  void SetBounds(const CefRect& bounds) OVERRIDE;
-  CefRect GetBounds() OVERRIDE;
-  CefRect GetBoundsInScreen() OVERRIDE;
-  void SetSize(const CefSize& size) OVERRIDE;
-  CefSize GetSize() OVERRIDE;
-  void SetPosition(const CefPoint& position) OVERRIDE;
-  CefPoint GetPosition() OVERRIDE;
-  CefSize GetPreferredSize() OVERRIDE;
-  void SizeToPreferredSize() OVERRIDE;
-  CefSize GetMinimumSize() OVERRIDE;
-  CefSize GetMaximumSize() OVERRIDE;
-  int GetHeightForWidth(int width) OVERRIDE;
-  void InvalidateLayout() OVERRIDE;
-  void SetVisible(bool visible) OVERRIDE;
-  bool IsVisible() OVERRIDE;
-  bool IsDrawn() OVERRIDE;
-  void SetEnabled(bool enabled) OVERRIDE;
-  bool IsEnabled() OVERRIDE;
-  void SetFocusable(bool focusable) OVERRIDE;
-  bool IsFocusable() OVERRIDE;
-  bool IsAccessibilityFocusable() OVERRIDE;
-  void RequestFocus() OVERRIDE;
-  void SetBackgroundColor(cef_color_t color) OVERRIDE;
-  cef_color_t GetBackgroundColor() OVERRIDE;
-  bool ConvertPointToScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointToWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
-  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
+  CefRefPtr<CefBrowserView> AsBrowserView() override;
+  CefRefPtr<CefButton> AsButton() override;
+  CefRefPtr<CefPanel> AsPanel() override;
+  CefRefPtr<CefScrollView> AsScrollView() override;
+  CefRefPtr<CefTextfield> AsTextfield() override;
+  CefString GetTypeString() override;
+  CefString ToString(bool include_children) override;
+  bool IsValid() override;
+  bool IsAttached() override;
+  bool IsSame(CefRefPtr<CefView> that) override;
+  CefRefPtr<CefViewDelegate> GetDelegate() override;
+  CefRefPtr<CefWindow> GetWindow() override;
+  int GetID() override;
+  void SetID(int id) override;
+  int GetGroupID() override;
+  void SetGroupID(int group_id) override;
+  CefRefPtr<CefView> GetParentView() override;
+  CefRefPtr<CefView> GetViewForID(int id) override;
+  void SetBounds(const CefRect& bounds) override;
+  CefRect GetBounds() override;
+  CefRect GetBoundsInScreen() override;
+  void SetSize(const CefSize& size) override;
+  CefSize GetSize() override;
+  void SetPosition(const CefPoint& position) override;
+  CefPoint GetPosition() override;
+  void SetInsets(const CefInsets& insets) override;
+  CefInsets GetInsets() override;
+  CefSize GetPreferredSize() override;
+  void SizeToPreferredSize() override;
+  CefSize GetMinimumSize() override;
+  CefSize GetMaximumSize() override;
+  int GetHeightForWidth(int width) override;
+  void InvalidateLayout() override;
+  void SetVisible(bool visible) override;
+  bool IsVisible() override;
+  bool IsDrawn() override;
+  void SetEnabled(bool enabled) override;
+  bool IsEnabled() override;
+  void SetFocusable(bool focusable) override;
+  bool IsFocusable() override;
+  bool IsAccessibilityFocusable() override;
+  void RequestFocus() override;
+  void SetBackgroundColor(cef_color_t color) override;
+  cef_color_t GetBackgroundColor() override;
+  bool ConvertPointToScreen(CefPoint& point) override;
+  bool ConvertPointFromScreen(CefPoint& point) override;
+  bool ConvertPointToWindow(CefPoint& point) override;
+  bool ConvertPointFromWindow(CefPoint& point) override;
+  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) override;
+  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_VIEWS_SCROLL_VIEW_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/views/textfield_ctocpp.cc b/src/libcef_dll/ctocpp/views/textfield_ctocpp.cc
index a45edd6..2048008 100644
--- a/src/libcef_dll/ctocpp/views/textfield_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/textfield_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=0f677bbeb351b9d71e00c622971d4593c99b99d5$
+// $hash=96c0f67c377e496e3824d6dc13969a728c4d5cb6$
 //
 
 #include "libcef_dll/ctocpp/views/textfield_ctocpp.h"
@@ -49,8 +49,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_password_input))
+  if (CEF_MEMBER_MISSING(_struct, set_password_input)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -62,8 +63,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_password_input))
+  if (CEF_MEMBER_MISSING(_struct, is_password_input)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -78,8 +80,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_read_only))
+  if (CEF_MEMBER_MISSING(_struct, set_read_only)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -91,8 +94,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_read_only))
+  if (CEF_MEMBER_MISSING(_struct, is_read_only)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -107,8 +111,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_text))
+  if (CEF_MEMBER_MISSING(_struct, get_text)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -126,15 +131,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_text))
+  if (CEF_MEMBER_MISSING(_struct, set_text)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: text; type: string_byref_const
   DCHECK(!text.empty());
-  if (text.empty())
+  if (text.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_text(_struct, text.GetStruct());
@@ -145,15 +152,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, append_text))
+  if (CEF_MEMBER_MISSING(_struct, append_text)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: text; type: string_byref_const
   DCHECK(!text.empty());
-  if (text.empty())
+  if (text.empty()) {
     return;
+  }
 
   // Execute
   _struct->append_text(_struct, text.GetStruct());
@@ -164,15 +173,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, insert_or_replace_text))
+  if (CEF_MEMBER_MISSING(_struct, insert_or_replace_text)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: text; type: string_byref_const
   DCHECK(!text.empty());
-  if (text.empty())
+  if (text.empty()) {
     return;
+  }
 
   // Execute
   _struct->insert_or_replace_text(_struct, text.GetStruct());
@@ -182,8 +193,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_selection))
+  if (CEF_MEMBER_MISSING(_struct, has_selection)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -198,8 +210,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_selected_text))
+  if (CEF_MEMBER_MISSING(_struct, get_selected_text)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -216,8 +229,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, select_all))
+  if (CEF_MEMBER_MISSING(_struct, select_all)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -229,8 +243,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, clear_selection))
+  if (CEF_MEMBER_MISSING(_struct, clear_selection)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -242,8 +257,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_selected_range))
+  if (CEF_MEMBER_MISSING(_struct, get_selected_range)) {
     return CefRange();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -259,8 +275,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, select_range))
+  if (CEF_MEMBER_MISSING(_struct, select_range)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -272,8 +289,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_cursor_position))
+  if (CEF_MEMBER_MISSING(_struct, get_cursor_position)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -289,8 +307,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_text_color))
+  if (CEF_MEMBER_MISSING(_struct, set_text_color)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -302,8 +321,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_text_color))
+  if (CEF_MEMBER_MISSING(_struct, get_text_color)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -319,8 +339,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_selection_text_color))
+  if (CEF_MEMBER_MISSING(_struct, set_selection_text_color)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -333,8 +354,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_selection_text_color))
+  if (CEF_MEMBER_MISSING(_struct, get_selection_text_color)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -350,8 +372,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_selection_background_color))
+  if (CEF_MEMBER_MISSING(_struct, set_selection_background_color)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -364,8 +387,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_selection_background_color))
+  if (CEF_MEMBER_MISSING(_struct, get_selection_background_color)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -381,15 +405,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_font_list))
+  if (CEF_MEMBER_MISSING(_struct, set_font_list)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: font_list; type: string_byref_const
   DCHECK(!font_list.empty());
-  if (font_list.empty())
+  if (font_list.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_font_list(_struct, font_list.GetStruct());
@@ -401,8 +427,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, apply_text_color))
+  if (CEF_MEMBER_MISSING(_struct, apply_text_color)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -417,8 +444,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, apply_text_style))
+  if (CEF_MEMBER_MISSING(_struct, apply_text_style)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -427,12 +455,14 @@
 }
 
 NO_SANITIZE("cfi-icall")
-bool CefTextfieldCToCpp::IsCommandEnabled(int command_id) {
+bool CefTextfieldCToCpp::IsCommandEnabled(
+    cef_text_field_commands_t command_id) {
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_command_enabled))
+  if (CEF_MEMBER_MISSING(_struct, is_command_enabled)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -444,12 +474,13 @@
 }
 
 NO_SANITIZE("cfi-icall")
-void CefTextfieldCToCpp::ExecuteCommand(int command_id) {
+void CefTextfieldCToCpp::ExecuteCommand(cef_text_field_commands_t command_id) {
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, execute_command))
+  if (CEF_MEMBER_MISSING(_struct, execute_command)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -461,8 +492,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, clear_edit_history))
+  if (CEF_MEMBER_MISSING(_struct, clear_edit_history)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -475,15 +507,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_placeholder_text))
+  if (CEF_MEMBER_MISSING(_struct, set_placeholder_text)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: text; type: string_byref_const
   DCHECK(!text.empty());
-  if (text.empty())
+  if (text.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_placeholder_text(_struct, text.GetStruct());
@@ -493,8 +527,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_placeholder_text))
+  if (CEF_MEMBER_MISSING(_struct, get_placeholder_text)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -512,8 +547,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_placeholder_text_color))
+  if (CEF_MEMBER_MISSING(_struct, set_placeholder_text_color)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -526,15 +562,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_accessible_name))
+  if (CEF_MEMBER_MISSING(_struct, set_accessible_name)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: name; type: string_byref_const
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return;
+  }
 
   // Execute
   _struct->set_accessible_name(_struct, name.GetStruct());
@@ -545,8 +583,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_browser_view))
+  if (CEF_MEMBER_MISSING(_struct, as_browser_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -561,8 +600,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_button))
+  if (CEF_MEMBER_MISSING(_struct, as_button)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -577,8 +617,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_panel))
+  if (CEF_MEMBER_MISSING(_struct, as_panel)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -594,8 +635,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_scroll_view))
+  if (CEF_MEMBER_MISSING(_struct, as_scroll_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -611,8 +653,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_textfield))
+  if (CEF_MEMBER_MISSING(_struct, as_textfield)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -627,8 +670,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_type_string))
+  if (CEF_MEMBER_MISSING(_struct, get_type_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -646,8 +690,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, to_string))
+  if (CEF_MEMBER_MISSING(_struct, to_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -664,8 +709,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -680,8 +726,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_attached))
+  if (CEF_MEMBER_MISSING(_struct, is_attached)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -697,15 +744,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefViewCToCpp::Unwrap(that));
@@ -719,8 +768,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_delegate))
+  if (CEF_MEMBER_MISSING(_struct, get_delegate)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -735,8 +785,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_window))
+  if (CEF_MEMBER_MISSING(_struct, get_window)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -751,8 +802,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_id))
+  if (CEF_MEMBER_MISSING(_struct, get_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -767,8 +819,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_id))
+  if (CEF_MEMBER_MISSING(_struct, set_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -780,8 +833,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_group_id))
+  if (CEF_MEMBER_MISSING(_struct, get_group_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -796,8 +850,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_group_id))
+  if (CEF_MEMBER_MISSING(_struct, set_group_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -810,8 +865,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_parent_view))
+  if (CEF_MEMBER_MISSING(_struct, get_parent_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -827,8 +883,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_view_for_id))
+  if (CEF_MEMBER_MISSING(_struct, get_view_for_id)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -844,8 +901,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_bounds))
+  if (CEF_MEMBER_MISSING(_struct, set_bounds)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -857,8 +915,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_bounds))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -873,8 +932,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -889,8 +949,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_size))
+  if (CEF_MEMBER_MISSING(_struct, set_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -902,8 +963,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_size))
+  if (CEF_MEMBER_MISSING(_struct, get_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -919,8 +981,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_position))
+  if (CEF_MEMBER_MISSING(_struct, set_position)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -932,8 +995,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_position))
+  if (CEF_MEMBER_MISSING(_struct, get_position)) {
     return CefPoint();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -944,12 +1008,45 @@
   return _retval;
 }
 
+NO_SANITIZE("cfi-icall")
+void CefTextfieldCToCpp::SetInsets(const CefInsets& insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, set_insets)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->set_insets(_struct, &insets);
+}
+
+NO_SANITIZE("cfi-icall") CefInsets CefTextfieldCToCpp::GetInsets() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, get_insets)) {
+    return CefInsets();
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_insets_t _retval = _struct->get_insets(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
 NO_SANITIZE("cfi-icall") CefSize CefTextfieldCToCpp::GetPreferredSize() {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, get_preferred_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -964,8 +1061,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -977,8 +1075,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_minimum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -993,8 +1092,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_maximum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1009,8 +1109,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_height_for_width))
+  if (CEF_MEMBER_MISSING(_struct, get_height_for_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1025,8 +1126,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, invalidate_layout))
+  if (CEF_MEMBER_MISSING(_struct, invalidate_layout)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1038,8 +1140,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_visible))
+  if (CEF_MEMBER_MISSING(_struct, set_visible)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1051,8 +1154,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_visible))
+  if (CEF_MEMBER_MISSING(_struct, is_visible)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1067,8 +1171,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_drawn))
+  if (CEF_MEMBER_MISSING(_struct, is_drawn)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1083,8 +1188,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_enabled))
+  if (CEF_MEMBER_MISSING(_struct, set_enabled)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1096,8 +1202,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_enabled))
+  if (CEF_MEMBER_MISSING(_struct, is_enabled)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1112,8 +1219,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_focusable))
+  if (CEF_MEMBER_MISSING(_struct, set_focusable)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1125,8 +1233,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1141,8 +1250,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1157,8 +1267,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, request_focus))
+  if (CEF_MEMBER_MISSING(_struct, request_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1171,8 +1282,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_background_color))
+  if (CEF_MEMBER_MISSING(_struct, set_background_color)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1184,8 +1296,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_background_color))
+  if (CEF_MEMBER_MISSING(_struct, get_background_color)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1201,8 +1314,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1218,8 +1332,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1235,8 +1350,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1252,8 +1368,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1270,15 +1387,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_to_view(
@@ -1294,15 +1413,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_from_view(
@@ -1326,7 +1447,7 @@
 cef_textfield_t*
 CefCToCppRefCounted<CefTextfieldCToCpp, CefTextfield, cef_textfield_t>::
     UnwrapDerived(CefWrapperType type, CefTextfield* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/textfield_ctocpp.h b/src/libcef_dll/ctocpp/views/textfield_ctocpp.h
index b132013..3325a22 100644
--- a/src/libcef_dll/ctocpp/views/textfield_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/textfield_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=8c3c6f34acb740232874335312c7a28699f32806$
+// $hash=cdc3237fbd889409f8e9aa2116689a3e1c1229c7$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_TEXTFIELD_CTOCPP_H_
@@ -34,89 +34,91 @@
   virtual ~CefTextfieldCToCpp();
 
   // CefTextfield methods.
-  void SetPasswordInput(bool password_input) OVERRIDE;
-  bool IsPasswordInput() OVERRIDE;
-  void SetReadOnly(bool read_only) OVERRIDE;
-  bool IsReadOnly() OVERRIDE;
-  CefString GetText() OVERRIDE;
-  void SetText(const CefString& text) OVERRIDE;
-  void AppendText(const CefString& text) OVERRIDE;
-  void InsertOrReplaceText(const CefString& text) OVERRIDE;
-  bool HasSelection() OVERRIDE;
-  CefString GetSelectedText() OVERRIDE;
-  void SelectAll(bool reversed) OVERRIDE;
-  void ClearSelection() OVERRIDE;
-  CefRange GetSelectedRange() OVERRIDE;
-  void SelectRange(const CefRange& range) OVERRIDE;
-  size_t GetCursorPosition() OVERRIDE;
-  void SetTextColor(cef_color_t color) OVERRIDE;
-  cef_color_t GetTextColor() OVERRIDE;
-  void SetSelectionTextColor(cef_color_t color) OVERRIDE;
-  cef_color_t GetSelectionTextColor() OVERRIDE;
-  void SetSelectionBackgroundColor(cef_color_t color) OVERRIDE;
-  cef_color_t GetSelectionBackgroundColor() OVERRIDE;
-  void SetFontList(const CefString& font_list) OVERRIDE;
-  void ApplyTextColor(cef_color_t color, const CefRange& range) OVERRIDE;
+  void SetPasswordInput(bool password_input) override;
+  bool IsPasswordInput() override;
+  void SetReadOnly(bool read_only) override;
+  bool IsReadOnly() override;
+  CefString GetText() override;
+  void SetText(const CefString& text) override;
+  void AppendText(const CefString& text) override;
+  void InsertOrReplaceText(const CefString& text) override;
+  bool HasSelection() override;
+  CefString GetSelectedText() override;
+  void SelectAll(bool reversed) override;
+  void ClearSelection() override;
+  CefRange GetSelectedRange() override;
+  void SelectRange(const CefRange& range) override;
+  size_t GetCursorPosition() override;
+  void SetTextColor(cef_color_t color) override;
+  cef_color_t GetTextColor() override;
+  void SetSelectionTextColor(cef_color_t color) override;
+  cef_color_t GetSelectionTextColor() override;
+  void SetSelectionBackgroundColor(cef_color_t color) override;
+  cef_color_t GetSelectionBackgroundColor() override;
+  void SetFontList(const CefString& font_list) override;
+  void ApplyTextColor(cef_color_t color, const CefRange& range) override;
   void ApplyTextStyle(cef_text_style_t style,
                       bool add,
-                      const CefRange& range) OVERRIDE;
-  bool IsCommandEnabled(int command_id) OVERRIDE;
-  void ExecuteCommand(int command_id) OVERRIDE;
-  void ClearEditHistory() OVERRIDE;
-  void SetPlaceholderText(const CefString& text) OVERRIDE;
-  CefString GetPlaceholderText() OVERRIDE;
-  void SetPlaceholderTextColor(cef_color_t color) OVERRIDE;
-  void SetAccessibleName(const CefString& name) OVERRIDE;
+                      const CefRange& range) override;
+  bool IsCommandEnabled(cef_text_field_commands_t command_id) override;
+  void ExecuteCommand(cef_text_field_commands_t command_id) override;
+  void ClearEditHistory() override;
+  void SetPlaceholderText(const CefString& text) override;
+  CefString GetPlaceholderText() override;
+  void SetPlaceholderTextColor(cef_color_t color) override;
+  void SetAccessibleName(const CefString& name) override;
 
   // CefView methods.
-  CefRefPtr<CefBrowserView> AsBrowserView() OVERRIDE;
-  CefRefPtr<CefButton> AsButton() OVERRIDE;
-  CefRefPtr<CefPanel> AsPanel() OVERRIDE;
-  CefRefPtr<CefScrollView> AsScrollView() OVERRIDE;
-  CefRefPtr<CefTextfield> AsTextfield() OVERRIDE;
-  CefString GetTypeString() OVERRIDE;
-  CefString ToString(bool include_children) OVERRIDE;
-  bool IsValid() OVERRIDE;
-  bool IsAttached() OVERRIDE;
-  bool IsSame(CefRefPtr<CefView> that) OVERRIDE;
-  CefRefPtr<CefViewDelegate> GetDelegate() OVERRIDE;
-  CefRefPtr<CefWindow> GetWindow() OVERRIDE;
-  int GetID() OVERRIDE;
-  void SetID(int id) OVERRIDE;
-  int GetGroupID() OVERRIDE;
-  void SetGroupID(int group_id) OVERRIDE;
-  CefRefPtr<CefView> GetParentView() OVERRIDE;
-  CefRefPtr<CefView> GetViewForID(int id) OVERRIDE;
-  void SetBounds(const CefRect& bounds) OVERRIDE;
-  CefRect GetBounds() OVERRIDE;
-  CefRect GetBoundsInScreen() OVERRIDE;
-  void SetSize(const CefSize& size) OVERRIDE;
-  CefSize GetSize() OVERRIDE;
-  void SetPosition(const CefPoint& position) OVERRIDE;
-  CefPoint GetPosition() OVERRIDE;
-  CefSize GetPreferredSize() OVERRIDE;
-  void SizeToPreferredSize() OVERRIDE;
-  CefSize GetMinimumSize() OVERRIDE;
-  CefSize GetMaximumSize() OVERRIDE;
-  int GetHeightForWidth(int width) OVERRIDE;
-  void InvalidateLayout() OVERRIDE;
-  void SetVisible(bool visible) OVERRIDE;
-  bool IsVisible() OVERRIDE;
-  bool IsDrawn() OVERRIDE;
-  void SetEnabled(bool enabled) OVERRIDE;
-  bool IsEnabled() OVERRIDE;
-  void SetFocusable(bool focusable) OVERRIDE;
-  bool IsFocusable() OVERRIDE;
-  bool IsAccessibilityFocusable() OVERRIDE;
-  void RequestFocus() OVERRIDE;
-  void SetBackgroundColor(cef_color_t color) OVERRIDE;
-  cef_color_t GetBackgroundColor() OVERRIDE;
-  bool ConvertPointToScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointToWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
-  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
+  CefRefPtr<CefBrowserView> AsBrowserView() override;
+  CefRefPtr<CefButton> AsButton() override;
+  CefRefPtr<CefPanel> AsPanel() override;
+  CefRefPtr<CefScrollView> AsScrollView() override;
+  CefRefPtr<CefTextfield> AsTextfield() override;
+  CefString GetTypeString() override;
+  CefString ToString(bool include_children) override;
+  bool IsValid() override;
+  bool IsAttached() override;
+  bool IsSame(CefRefPtr<CefView> that) override;
+  CefRefPtr<CefViewDelegate> GetDelegate() override;
+  CefRefPtr<CefWindow> GetWindow() override;
+  int GetID() override;
+  void SetID(int id) override;
+  int GetGroupID() override;
+  void SetGroupID(int group_id) override;
+  CefRefPtr<CefView> GetParentView() override;
+  CefRefPtr<CefView> GetViewForID(int id) override;
+  void SetBounds(const CefRect& bounds) override;
+  CefRect GetBounds() override;
+  CefRect GetBoundsInScreen() override;
+  void SetSize(const CefSize& size) override;
+  CefSize GetSize() override;
+  void SetPosition(const CefPoint& position) override;
+  CefPoint GetPosition() override;
+  void SetInsets(const CefInsets& insets) override;
+  CefInsets GetInsets() override;
+  CefSize GetPreferredSize() override;
+  void SizeToPreferredSize() override;
+  CefSize GetMinimumSize() override;
+  CefSize GetMaximumSize() override;
+  int GetHeightForWidth(int width) override;
+  void InvalidateLayout() override;
+  void SetVisible(bool visible) override;
+  bool IsVisible() override;
+  bool IsDrawn() override;
+  void SetEnabled(bool enabled) override;
+  bool IsEnabled() override;
+  void SetFocusable(bool focusable) override;
+  bool IsFocusable() override;
+  bool IsAccessibilityFocusable() override;
+  void RequestFocus() override;
+  void SetBackgroundColor(cef_color_t color) override;
+  cef_color_t GetBackgroundColor() override;
+  bool ConvertPointToScreen(CefPoint& point) override;
+  bool ConvertPointFromScreen(CefPoint& point) override;
+  bool ConvertPointToWindow(CefPoint& point) override;
+  bool ConvertPointFromWindow(CefPoint& point) override;
+  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) override;
+  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_VIEWS_TEXTFIELD_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/views/textfield_delegate_ctocpp.cc b/src/libcef_dll/ctocpp/views/textfield_delegate_ctocpp.cc
index b95da92..1f42b61 100644
--- a/src/libcef_dll/ctocpp/views/textfield_delegate_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/textfield_delegate_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=b2179a4404a247783c97e3926fc2cf19fb1f46c6$
+// $hash=0554c435e85fb7efb50f22cc7c3e184af48f0ea0$
 //
 
 #include "libcef_dll/ctocpp/views/textfield_delegate_ctocpp.h"
@@ -25,15 +25,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_key_event))
+  if (CEF_MEMBER_MISSING(_struct, on_key_event)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: textfield; type: refptr_diff
   DCHECK(textfield.get());
-  if (!textfield.get())
+  if (!textfield.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->on_key_event(
@@ -49,15 +51,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_textfield_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_after_user_action))
+  if (CEF_MEMBER_MISSING(_struct, on_after_user_action)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: textfield; type: refptr_diff
   DCHECK(textfield.get());
-  if (!textfield.get())
+  if (!textfield.get()) {
     return;
+  }
 
   // Execute
   _struct->on_after_user_action(_struct, CefTextfieldCppToC::Wrap(textfield));
@@ -69,15 +73,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, get_preferred_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -93,15 +99,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_minimum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -117,15 +125,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_maximum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -142,15 +152,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_height_for_width))
+  if (CEF_MEMBER_MISSING(_struct, get_height_for_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -169,19 +181,22 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_parent_view_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_parent_view_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
   // Verify param: parent; type: refptr_diff
   DCHECK(parent.get());
-  if (!parent.get())
+  if (!parent.get()) {
     return;
+  }
 
   // Execute
   _struct->on_parent_view_changed(_struct, CefViewCppToC::Wrap(view), added,
@@ -196,19 +211,22 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_child_view_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_child_view_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
   // Verify param: child; type: refptr_diff
   DCHECK(child.get());
-  if (!child.get())
+  if (!child.get()) {
     return;
+  }
 
   // Execute
   _struct->on_child_view_changed(_struct, CefViewCppToC::Wrap(view), added,
@@ -216,20 +234,68 @@
 }
 
 NO_SANITIZE("cfi-icall")
+void CefTextfieldDelegateCToCpp::OnWindowChanged(CefRefPtr<CefView> view,
+                                                 bool added) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_delegate_t* _struct =
+      reinterpret_cast<cef_view_delegate_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, on_window_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: view; type: refptr_diff
+  DCHECK(view.get());
+  if (!view.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_window_changed(_struct, CefViewCppToC::Wrap(view), added);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefTextfieldDelegateCToCpp::OnLayoutChanged(CefRefPtr<CefView> view,
+                                                 const CefRect& new_bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_delegate_t* _struct =
+      reinterpret_cast<cef_view_delegate_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, on_layout_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: view; type: refptr_diff
+  DCHECK(view.get());
+  if (!view.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_layout_changed(_struct, CefViewCppToC::Wrap(view), &new_bounds);
+}
+
+NO_SANITIZE("cfi-icall")
 void CefTextfieldDelegateCToCpp::OnFocus(CefRefPtr<CefView> view) {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_focus))
+  if (CEF_MEMBER_MISSING(_struct, on_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->on_focus(_struct, CefViewCppToC::Wrap(view));
@@ -241,15 +307,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_blur))
+  if (CEF_MEMBER_MISSING(_struct, on_blur)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->on_blur(_struct, CefViewCppToC::Wrap(view));
@@ -271,7 +339,7 @@
     CefTextfieldDelegate,
     cef_textfield_delegate_t>::UnwrapDerived(CefWrapperType type,
                                              CefTextfieldDelegate* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/textfield_delegate_ctocpp.h b/src/libcef_dll/ctocpp/views/textfield_delegate_ctocpp.h
index cb9b26e..76d15ee 100644
--- a/src/libcef_dll/ctocpp/views/textfield_delegate_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/textfield_delegate_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=5945bc681b8f5e31bebe8a22d6f870ed714f0446$
+// $hash=65dedd950d154a0125b094bb1488e787726545cb$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_TEXTFIELD_DELEGATE_CTOCPP_H_
@@ -52,6 +52,9 @@
   void OnChildViewChanged(CefRefPtr<CefView> view,
                           bool added,
                           CefRefPtr<CefView> child) override;
+  void OnWindowChanged(CefRefPtr<CefView> view, bool added) override;
+  void OnLayoutChanged(CefRefPtr<CefView> view,
+                       const CefRect& new_bounds) override;
   void OnFocus(CefRefPtr<CefView> view) override;
   void OnBlur(CefRefPtr<CefView> view) override;
 };
diff --git a/src/libcef_dll/ctocpp/views/view_ctocpp.cc b/src/libcef_dll/ctocpp/views/view_ctocpp.cc
index a8ba2c8..71850b5 100644
--- a/src/libcef_dll/ctocpp/views/view_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/view_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2866cdd50d8546d7a9b7e4294aacab628933fc4b$
+// $hash=425f9800e0f8228d483e55a00f65c3c894df6360$
 //
 
 #include "libcef_dll/ctocpp/views/view_ctocpp.h"
@@ -31,8 +31,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, as_browser_view))
+  if (CEF_MEMBER_MISSING(_struct, as_browser_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -47,8 +48,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, as_button))
+  if (CEF_MEMBER_MISSING(_struct, as_button)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -63,8 +65,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, as_panel))
+  if (CEF_MEMBER_MISSING(_struct, as_panel)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -80,8 +83,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, as_scroll_view))
+  if (CEF_MEMBER_MISSING(_struct, as_scroll_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -96,8 +100,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, as_textfield))
+  if (CEF_MEMBER_MISSING(_struct, as_textfield)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -112,8 +117,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_type_string))
+  if (CEF_MEMBER_MISSING(_struct, get_type_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -131,8 +137,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, to_string))
+  if (CEF_MEMBER_MISSING(_struct, to_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -149,8 +156,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -165,8 +173,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_attached))
+  if (CEF_MEMBER_MISSING(_struct, is_attached)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -181,15 +190,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefViewCToCpp::Unwrap(that));
@@ -203,8 +214,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_delegate))
+  if (CEF_MEMBER_MISSING(_struct, get_delegate)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -219,8 +231,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_window))
+  if (CEF_MEMBER_MISSING(_struct, get_window)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -235,8 +248,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_id))
+  if (CEF_MEMBER_MISSING(_struct, get_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -251,8 +265,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_id))
+  if (CEF_MEMBER_MISSING(_struct, set_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -264,8 +279,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_group_id))
+  if (CEF_MEMBER_MISSING(_struct, get_group_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -280,8 +296,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_group_id))
+  if (CEF_MEMBER_MISSING(_struct, set_group_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -293,8 +310,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_parent_view))
+  if (CEF_MEMBER_MISSING(_struct, get_parent_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -310,8 +328,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_view_for_id))
+  if (CEF_MEMBER_MISSING(_struct, get_view_for_id)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -326,8 +345,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_bounds))
+  if (CEF_MEMBER_MISSING(_struct, set_bounds)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -339,8 +359,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_bounds))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -355,8 +376,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -371,8 +393,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_size))
+  if (CEF_MEMBER_MISSING(_struct, set_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -384,8 +407,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_size))
+  if (CEF_MEMBER_MISSING(_struct, get_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -401,8 +425,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_position))
+  if (CEF_MEMBER_MISSING(_struct, set_position)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -414,8 +439,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_position))
+  if (CEF_MEMBER_MISSING(_struct, get_position)) {
     return CefPoint();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -426,12 +452,45 @@
   return _retval;
 }
 
+NO_SANITIZE("cfi-icall")
+void CefViewCToCpp::SetInsets(const CefInsets& insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, set_insets)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->set_insets(_struct, &insets);
+}
+
+NO_SANITIZE("cfi-icall") CefInsets CefViewCToCpp::GetInsets() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_insets)) {
+    return CefInsets();
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_insets_t _retval = _struct->get_insets(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
 NO_SANITIZE("cfi-icall") CefSize CefViewCToCpp::GetPreferredSize() {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, get_preferred_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -446,8 +505,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -459,8 +519,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_minimum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -475,8 +536,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_maximum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -491,8 +553,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_height_for_width))
+  if (CEF_MEMBER_MISSING(_struct, get_height_for_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -507,8 +570,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, invalidate_layout))
+  if (CEF_MEMBER_MISSING(_struct, invalidate_layout)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -520,8 +584,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_visible))
+  if (CEF_MEMBER_MISSING(_struct, set_visible)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -533,8 +598,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_visible))
+  if (CEF_MEMBER_MISSING(_struct, is_visible)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -549,8 +615,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_drawn))
+  if (CEF_MEMBER_MISSING(_struct, is_drawn)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -565,8 +632,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_enabled))
+  if (CEF_MEMBER_MISSING(_struct, set_enabled)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -578,8 +646,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_enabled))
+  if (CEF_MEMBER_MISSING(_struct, is_enabled)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -594,8 +663,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_focusable))
+  if (CEF_MEMBER_MISSING(_struct, set_focusable)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -607,8 +677,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -623,8 +694,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -639,8 +711,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, request_focus))
+  if (CEF_MEMBER_MISSING(_struct, request_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -653,8 +726,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_background_color))
+  if (CEF_MEMBER_MISSING(_struct, set_background_color)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -666,8 +740,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_background_color))
+  if (CEF_MEMBER_MISSING(_struct, get_background_color)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -683,8 +758,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -700,8 +776,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -717,8 +794,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -734,8 +812,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -752,15 +831,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_to_view(
@@ -776,15 +857,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_from_view(
@@ -841,7 +924,7 @@
     return reinterpret_cast<cef_view_t*>(
         CefWindowCToCpp::Unwrap(reinterpret_cast<CefWindow*>(c)));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/view_ctocpp.h b/src/libcef_dll/ctocpp/views/view_ctocpp.h
index 38e0c2a..65b2cc0 100644
--- a/src/libcef_dll/ctocpp/views/view_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/view_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=993cdec1a5c9c78f9c11eed22cd692139fb00d92$
+// $hash=5af9a065bd30e46fad816250442dd6b3d31834fd$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_VIEW_CTOCPP_H_
@@ -45,54 +45,56 @@
   virtual ~CefViewCToCpp();
 
   // CefView methods.
-  CefRefPtr<CefBrowserView> AsBrowserView() OVERRIDE;
-  CefRefPtr<CefButton> AsButton() OVERRIDE;
-  CefRefPtr<CefPanel> AsPanel() OVERRIDE;
-  CefRefPtr<CefScrollView> AsScrollView() OVERRIDE;
-  CefRefPtr<CefTextfield> AsTextfield() OVERRIDE;
-  CefString GetTypeString() OVERRIDE;
-  CefString ToString(bool include_children) OVERRIDE;
-  bool IsValid() OVERRIDE;
-  bool IsAttached() OVERRIDE;
-  bool IsSame(CefRefPtr<CefView> that) OVERRIDE;
-  CefRefPtr<CefViewDelegate> GetDelegate() OVERRIDE;
-  CefRefPtr<CefWindow> GetWindow() OVERRIDE;
-  int GetID() OVERRIDE;
-  void SetID(int id) OVERRIDE;
-  int GetGroupID() OVERRIDE;
-  void SetGroupID(int group_id) OVERRIDE;
-  CefRefPtr<CefView> GetParentView() OVERRIDE;
-  CefRefPtr<CefView> GetViewForID(int id) OVERRIDE;
-  void SetBounds(const CefRect& bounds) OVERRIDE;
-  CefRect GetBounds() OVERRIDE;
-  CefRect GetBoundsInScreen() OVERRIDE;
-  void SetSize(const CefSize& size) OVERRIDE;
-  CefSize GetSize() OVERRIDE;
-  void SetPosition(const CefPoint& position) OVERRIDE;
-  CefPoint GetPosition() OVERRIDE;
-  CefSize GetPreferredSize() OVERRIDE;
-  void SizeToPreferredSize() OVERRIDE;
-  CefSize GetMinimumSize() OVERRIDE;
-  CefSize GetMaximumSize() OVERRIDE;
-  int GetHeightForWidth(int width) OVERRIDE;
-  void InvalidateLayout() OVERRIDE;
-  void SetVisible(bool visible) OVERRIDE;
-  bool IsVisible() OVERRIDE;
-  bool IsDrawn() OVERRIDE;
-  void SetEnabled(bool enabled) OVERRIDE;
-  bool IsEnabled() OVERRIDE;
-  void SetFocusable(bool focusable) OVERRIDE;
-  bool IsFocusable() OVERRIDE;
-  bool IsAccessibilityFocusable() OVERRIDE;
-  void RequestFocus() OVERRIDE;
-  void SetBackgroundColor(cef_color_t color) OVERRIDE;
-  cef_color_t GetBackgroundColor() OVERRIDE;
-  bool ConvertPointToScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointToWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
-  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
+  CefRefPtr<CefBrowserView> AsBrowserView() override;
+  CefRefPtr<CefButton> AsButton() override;
+  CefRefPtr<CefPanel> AsPanel() override;
+  CefRefPtr<CefScrollView> AsScrollView() override;
+  CefRefPtr<CefTextfield> AsTextfield() override;
+  CefString GetTypeString() override;
+  CefString ToString(bool include_children) override;
+  bool IsValid() override;
+  bool IsAttached() override;
+  bool IsSame(CefRefPtr<CefView> that) override;
+  CefRefPtr<CefViewDelegate> GetDelegate() override;
+  CefRefPtr<CefWindow> GetWindow() override;
+  int GetID() override;
+  void SetID(int id) override;
+  int GetGroupID() override;
+  void SetGroupID(int group_id) override;
+  CefRefPtr<CefView> GetParentView() override;
+  CefRefPtr<CefView> GetViewForID(int id) override;
+  void SetBounds(const CefRect& bounds) override;
+  CefRect GetBounds() override;
+  CefRect GetBoundsInScreen() override;
+  void SetSize(const CefSize& size) override;
+  CefSize GetSize() override;
+  void SetPosition(const CefPoint& position) override;
+  CefPoint GetPosition() override;
+  void SetInsets(const CefInsets& insets) override;
+  CefInsets GetInsets() override;
+  CefSize GetPreferredSize() override;
+  void SizeToPreferredSize() override;
+  CefSize GetMinimumSize() override;
+  CefSize GetMaximumSize() override;
+  int GetHeightForWidth(int width) override;
+  void InvalidateLayout() override;
+  void SetVisible(bool visible) override;
+  bool IsVisible() override;
+  bool IsDrawn() override;
+  void SetEnabled(bool enabled) override;
+  bool IsEnabled() override;
+  void SetFocusable(bool focusable) override;
+  bool IsFocusable() override;
+  bool IsAccessibilityFocusable() override;
+  void RequestFocus() override;
+  void SetBackgroundColor(cef_color_t color) override;
+  cef_color_t GetBackgroundColor() override;
+  bool ConvertPointToScreen(CefPoint& point) override;
+  bool ConvertPointFromScreen(CefPoint& point) override;
+  bool ConvertPointToWindow(CefPoint& point) override;
+  bool ConvertPointFromWindow(CefPoint& point) override;
+  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) override;
+  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_VIEWS_VIEW_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/views/view_delegate_ctocpp.cc b/src/libcef_dll/ctocpp/views/view_delegate_ctocpp.cc
index 021aa8e..2a4a098 100644
--- a/src/libcef_dll/ctocpp/views/view_delegate_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/view_delegate_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7303b34e865e03fae0c070d9df8157f9b343fe7c$
+// $hash=024caf54f7f453df5c9ff4e5b62f5f69960f6a1b$
 //
 
 #include "libcef_dll/ctocpp/views/view_delegate_ctocpp.h"
@@ -29,15 +29,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, get_preferred_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -52,15 +54,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_minimum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -75,15 +79,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_maximum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -99,15 +105,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_height_for_width))
+  if (CEF_MEMBER_MISSING(_struct, get_height_for_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -124,19 +132,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_parent_view_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_parent_view_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
   // Verify param: parent; type: refptr_diff
   DCHECK(parent.get());
-  if (!parent.get())
+  if (!parent.get()) {
     return;
+  }
 
   // Execute
   _struct->on_parent_view_changed(_struct, CefViewCppToC::Wrap(view), added,
@@ -150,19 +161,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_child_view_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_child_view_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
   // Verify param: child; type: refptr_diff
   DCHECK(child.get());
-  if (!child.get())
+  if (!child.get()) {
     return;
+  }
 
   // Execute
   _struct->on_child_view_changed(_struct, CefViewCppToC::Wrap(view), added,
@@ -170,19 +184,65 @@
 }
 
 NO_SANITIZE("cfi-icall")
-void CefViewDelegateCToCpp::OnFocus(CefRefPtr<CefView> view) {
+void CefViewDelegateCToCpp::OnWindowChanged(CefRefPtr<CefView> view,
+                                            bool added) {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_focus))
+  if (CEF_MEMBER_MISSING(_struct, on_window_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
+
+  // Execute
+  _struct->on_window_changed(_struct, CefViewCppToC::Wrap(view), added);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefViewDelegateCToCpp::OnLayoutChanged(CefRefPtr<CefView> view,
+                                            const CefRect& new_bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_delegate_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_layout_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: view; type: refptr_diff
+  DCHECK(view.get());
+  if (!view.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_layout_changed(_struct, CefViewCppToC::Wrap(view), &new_bounds);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefViewDelegateCToCpp::OnFocus(CefRefPtr<CefView> view) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_delegate_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_focus)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: view; type: refptr_diff
+  DCHECK(view.get());
+  if (!view.get()) {
+    return;
+  }
 
   // Execute
   _struct->on_focus(_struct, CefViewCppToC::Wrap(view));
@@ -193,15 +253,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_blur))
+  if (CEF_MEMBER_MISSING(_struct, on_blur)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->on_blur(_struct, CefViewCppToC::Wrap(view));
@@ -252,7 +314,7 @@
         CefWindowDelegateCToCpp::Unwrap(
             reinterpret_cast<CefWindowDelegate*>(c)));
   }
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/view_delegate_ctocpp.h b/src/libcef_dll/ctocpp/views/view_delegate_ctocpp.h
index d7a87ce..2a8024b 100644
--- a/src/libcef_dll/ctocpp/views/view_delegate_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/view_delegate_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=50285c0d5d83ec0de6bb0542a2c2b32517217b4e$
+// $hash=c433d8e9462e7a948338bfe9192f247fdc253614$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_VIEW_DELEGATE_CTOCPP_H_
@@ -46,6 +46,9 @@
   void OnChildViewChanged(CefRefPtr<CefView> view,
                           bool added,
                           CefRefPtr<CefView> child) override;
+  void OnWindowChanged(CefRefPtr<CefView> view, bool added) override;
+  void OnLayoutChanged(CefRefPtr<CefView> view,
+                       const CefRect& new_bounds) override;
   void OnFocus(CefRefPtr<CefView> view) override;
   void OnBlur(CefRefPtr<CefView> view) override;
 };
diff --git a/src/libcef_dll/ctocpp/views/window_ctocpp.cc b/src/libcef_dll/ctocpp/views/window_ctocpp.cc
index 79bd058..66ca9db 100644
--- a/src/libcef_dll/ctocpp/views/window_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/window_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=50c86d019c16b2efb58ea99ca3f763eaaf297397$
+// $hash=c8f164d20875c8071837c04abb44e09672d894af$
 //
 
 #include "libcef_dll/ctocpp/views/window_ctocpp.h"
@@ -23,6 +23,7 @@
 #include "libcef_dll/ctocpp/views/display_ctocpp.h"
 #include "libcef_dll/ctocpp/views/fill_layout_ctocpp.h"
 #include "libcef_dll/ctocpp/views/layout_ctocpp.h"
+#include "libcef_dll/ctocpp/views/overlay_controller_ctocpp.h"
 #include "libcef_dll/ctocpp/views/panel_ctocpp.h"
 #include "libcef_dll/ctocpp/views/scroll_view_ctocpp.h"
 #include "libcef_dll/ctocpp/views/textfield_ctocpp.h"
@@ -54,8 +55,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, show))
+  if (CEF_MEMBER_MISSING(_struct, show)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -63,12 +65,36 @@
   _struct->show(_struct);
 }
 
+NO_SANITIZE("cfi-icall")
+void CefWindowCToCpp::ShowAsBrowserModalDialog(
+    CefRefPtr<CefBrowserView> browser_view) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_window_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, show_as_browser_modal_dialog)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: browser_view; type: refptr_same
+  DCHECK(browser_view.get());
+  if (!browser_view.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->show_as_browser_modal_dialog(
+      _struct, CefBrowserViewCToCpp::Unwrap(browser_view));
+}
+
 NO_SANITIZE("cfi-icall") void CefWindowCToCpp::Hide() {
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, hide))
+  if (CEF_MEMBER_MISSING(_struct, hide)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -81,8 +107,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, center_window))
+  if (CEF_MEMBER_MISSING(_struct, center_window)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -94,8 +121,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, close))
+  if (CEF_MEMBER_MISSING(_struct, close)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -107,8 +135,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_closed))
+  if (CEF_MEMBER_MISSING(_struct, is_closed)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -123,8 +152,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, activate))
+  if (CEF_MEMBER_MISSING(_struct, activate)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -136,8 +166,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, deactivate))
+  if (CEF_MEMBER_MISSING(_struct, deactivate)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -149,8 +180,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_active))
+  if (CEF_MEMBER_MISSING(_struct, is_active)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -165,8 +197,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, bring_to_top))
+  if (CEF_MEMBER_MISSING(_struct, bring_to_top)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -178,8 +211,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_always_on_top))
+  if (CEF_MEMBER_MISSING(_struct, set_always_on_top)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -191,8 +225,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_always_on_top))
+  if (CEF_MEMBER_MISSING(_struct, is_always_on_top)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -207,8 +242,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, maximize))
+  if (CEF_MEMBER_MISSING(_struct, maximize)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -220,8 +256,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, minimize))
+  if (CEF_MEMBER_MISSING(_struct, minimize)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -233,8 +270,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, restore))
+  if (CEF_MEMBER_MISSING(_struct, restore)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -246,8 +284,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_fullscreen))
+  if (CEF_MEMBER_MISSING(_struct, set_fullscreen)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -259,8 +298,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_maximized))
+  if (CEF_MEMBER_MISSING(_struct, is_maximized)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -275,8 +315,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_minimized))
+  if (CEF_MEMBER_MISSING(_struct, is_minimized)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -291,8 +332,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_fullscreen))
+  if (CEF_MEMBER_MISSING(_struct, is_fullscreen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -308,8 +350,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_title))
+  if (CEF_MEMBER_MISSING(_struct, set_title)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -323,8 +366,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_title))
+  if (CEF_MEMBER_MISSING(_struct, get_title)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -342,15 +386,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_window_icon))
+  if (CEF_MEMBER_MISSING(_struct, set_window_icon)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: image; type: refptr_same
   DCHECK(image.get());
-  if (!image.get())
+  if (!image.get()) {
     return;
+  }
 
   // Execute
   _struct->set_window_icon(_struct, CefImageCToCpp::Unwrap(image));
@@ -360,8 +406,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_window_icon))
+  if (CEF_MEMBER_MISSING(_struct, get_window_icon)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -377,15 +424,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_window_app_icon))
+  if (CEF_MEMBER_MISSING(_struct, set_window_app_icon)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: image; type: refptr_same
   DCHECK(image.get());
-  if (!image.get())
+  if (!image.get()) {
     return;
+  }
 
   // Execute
   _struct->set_window_app_icon(_struct, CefImageCToCpp::Unwrap(image));
@@ -396,8 +445,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_window_app_icon))
+  if (CEF_MEMBER_MISSING(_struct, get_window_app_icon)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -409,21 +459,50 @@
 }
 
 NO_SANITIZE("cfi-icall")
+CefRefPtr<CefOverlayController> CefWindowCToCpp::AddOverlayView(
+    CefRefPtr<CefView> view,
+    cef_docking_mode_t docking_mode) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_window_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, add_overlay_view)) {
+    return nullptr;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: view; type: refptr_same
+  DCHECK(view.get());
+  if (!view.get()) {
+    return nullptr;
+  }
+
+  // Execute
+  cef_overlay_controller_t* _retval = _struct->add_overlay_view(
+      _struct, CefViewCToCpp::Unwrap(view), docking_mode);
+
+  // Return type: refptr_same
+  return CefOverlayControllerCToCpp::Wrap(_retval);
+}
+
+NO_SANITIZE("cfi-icall")
 void CefWindowCToCpp::ShowMenu(CefRefPtr<CefMenuModel> menu_model,
                                const CefPoint& screen_point,
                                cef_menu_anchor_position_t anchor_position) {
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, show_menu))
+  if (CEF_MEMBER_MISSING(_struct, show_menu)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: menu_model; type: refptr_same
   DCHECK(menu_model.get());
-  if (!menu_model.get())
+  if (!menu_model.get()) {
     return;
+  }
 
   // Execute
   _struct->show_menu(_struct, CefMenuModelCToCpp::Unwrap(menu_model),
@@ -434,8 +513,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, cancel_menu))
+  if (CEF_MEMBER_MISSING(_struct, cancel_menu)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -447,8 +527,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_display))
+  if (CEF_MEMBER_MISSING(_struct, get_display)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -464,8 +545,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_client_area_bounds_in_screen))
+  if (CEF_MEMBER_MISSING(_struct, get_client_area_bounds_in_screen)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -482,8 +564,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_draggable_regions))
+  if (CEF_MEMBER_MISSING(_struct, set_draggable_regions)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -506,16 +589,18 @@
   _struct->set_draggable_regions(_struct, regionsCount, regionsList);
 
   // Restore param:regions; type: simple_vec_byref_const
-  if (regionsList)
+  if (regionsList) {
     delete[] regionsList;
+  }
 }
 
 NO_SANITIZE("cfi-icall") CefWindowHandle CefWindowCToCpp::GetWindowHandle() {
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_window_handle))
+  if (CEF_MEMBER_MISSING(_struct, get_window_handle)) {
     return kNullWindowHandle;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -527,12 +612,13 @@
 }
 
 NO_SANITIZE("cfi-icall")
-void CefWindowCToCpp::SendKeyPress(int key_code, uint32 event_flags) {
+void CefWindowCToCpp::SendKeyPress(int key_code, uint32_t event_flags) {
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_key_press))
+  if (CEF_MEMBER_MISSING(_struct, send_key_press)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -545,8 +631,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_mouse_move))
+  if (CEF_MEMBER_MISSING(_struct, send_mouse_move)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -561,8 +648,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, send_mouse_events))
+  if (CEF_MEMBER_MISSING(_struct, send_mouse_events)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -575,18 +663,20 @@
                                      int key_code,
                                      bool shift_pressed,
                                      bool ctrl_pressed,
-                                     bool alt_pressed) {
+                                     bool alt_pressed,
+                                     bool high_priority) {
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, set_accelerator))
+  if (CEF_MEMBER_MISSING(_struct, set_accelerator)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
   _struct->set_accelerator(_struct, command_id, key_code, shift_pressed,
-                           ctrl_pressed, alt_pressed);
+                           ctrl_pressed, alt_pressed, high_priority);
 }
 
 NO_SANITIZE("cfi-icall")
@@ -594,8 +684,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, remove_accelerator))
+  if (CEF_MEMBER_MISSING(_struct, remove_accelerator)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -607,8 +698,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, remove_all_accelerators))
+  if (CEF_MEMBER_MISSING(_struct, remove_all_accelerators)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -620,8 +712,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = reinterpret_cast<cef_panel_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_window))
+  if (CEF_MEMBER_MISSING(_struct, as_window)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -637,8 +730,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = reinterpret_cast<cef_panel_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_to_fill_layout))
+  if (CEF_MEMBER_MISSING(_struct, set_to_fill_layout)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -655,8 +749,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = reinterpret_cast<cef_panel_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_to_box_layout))
+  if (CEF_MEMBER_MISSING(_struct, set_to_box_layout)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -671,8 +766,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = reinterpret_cast<cef_panel_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_layout))
+  if (CEF_MEMBER_MISSING(_struct, get_layout)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -687,8 +783,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = reinterpret_cast<cef_panel_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, layout))
+  if (CEF_MEMBER_MISSING(_struct, layout)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -701,15 +798,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = reinterpret_cast<cef_panel_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, add_child_view))
+  if (CEF_MEMBER_MISSING(_struct, add_child_view)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->add_child_view(_struct, CefViewCToCpp::Unwrap(view));
@@ -720,19 +819,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = reinterpret_cast<cef_panel_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, add_child_view_at))
+  if (CEF_MEMBER_MISSING(_struct, add_child_view_at)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return;
+  }
 
   // Execute
   _struct->add_child_view_at(_struct, CefViewCToCpp::Unwrap(view), index);
@@ -743,15 +845,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = reinterpret_cast<cef_panel_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, reorder_child_view))
+  if (CEF_MEMBER_MISSING(_struct, reorder_child_view)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->reorder_child_view(_struct, CefViewCToCpp::Unwrap(view), index);
@@ -762,15 +866,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = reinterpret_cast<cef_panel_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, remove_child_view))
+  if (CEF_MEMBER_MISSING(_struct, remove_child_view)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->remove_child_view(_struct, CefViewCToCpp::Unwrap(view));
@@ -780,8 +886,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = reinterpret_cast<cef_panel_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, remove_all_child_views))
+  if (CEF_MEMBER_MISSING(_struct, remove_all_child_views)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -793,8 +900,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = reinterpret_cast<cef_panel_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_child_view_count))
+  if (CEF_MEMBER_MISSING(_struct, get_child_view_count)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -810,15 +918,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_panel_t* _struct = reinterpret_cast<cef_panel_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_child_view_at))
+  if (CEF_MEMBER_MISSING(_struct, get_child_view_at)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return nullptr;
+  }
 
   // Execute
   cef_view_t* _retval = _struct->get_child_view_at(_struct, index);
@@ -832,8 +942,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_browser_view))
+  if (CEF_MEMBER_MISSING(_struct, as_browser_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -848,8 +959,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_button))
+  if (CEF_MEMBER_MISSING(_struct, as_button)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -864,8 +976,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_panel))
+  if (CEF_MEMBER_MISSING(_struct, as_panel)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -881,8 +994,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_scroll_view))
+  if (CEF_MEMBER_MISSING(_struct, as_scroll_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -898,8 +1012,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, as_textfield))
+  if (CEF_MEMBER_MISSING(_struct, as_textfield)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -914,8 +1029,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_type_string))
+  if (CEF_MEMBER_MISSING(_struct, get_type_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -933,8 +1049,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, to_string))
+  if (CEF_MEMBER_MISSING(_struct, to_string)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -951,8 +1068,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_valid))
+  if (CEF_MEMBER_MISSING(_struct, is_valid)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -967,8 +1085,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_attached))
+  if (CEF_MEMBER_MISSING(_struct, is_attached)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -983,15 +1102,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_same))
+  if (CEF_MEMBER_MISSING(_struct, is_same)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: that; type: refptr_same
   DCHECK(that.get());
-  if (!that.get())
+  if (!that.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_same(_struct, CefViewCToCpp::Unwrap(that));
@@ -1005,8 +1126,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_delegate))
+  if (CEF_MEMBER_MISSING(_struct, get_delegate)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1021,8 +1143,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_window))
+  if (CEF_MEMBER_MISSING(_struct, get_window)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1037,8 +1160,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_id))
+  if (CEF_MEMBER_MISSING(_struct, get_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1053,8 +1177,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_id))
+  if (CEF_MEMBER_MISSING(_struct, set_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1066,8 +1191,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_group_id))
+  if (CEF_MEMBER_MISSING(_struct, get_group_id)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1082,8 +1208,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_group_id))
+  if (CEF_MEMBER_MISSING(_struct, set_group_id)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1095,8 +1222,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_parent_view))
+  if (CEF_MEMBER_MISSING(_struct, get_parent_view)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1112,8 +1240,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_view_for_id))
+  if (CEF_MEMBER_MISSING(_struct, get_view_for_id)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1129,8 +1258,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_bounds))
+  if (CEF_MEMBER_MISSING(_struct, set_bounds)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1142,8 +1272,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_bounds))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1158,8 +1289,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen))
+  if (CEF_MEMBER_MISSING(_struct, get_bounds_in_screen)) {
     return CefRect();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1174,8 +1306,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_size))
+  if (CEF_MEMBER_MISSING(_struct, set_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1187,8 +1320,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_size))
+  if (CEF_MEMBER_MISSING(_struct, get_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1204,8 +1338,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_position))
+  if (CEF_MEMBER_MISSING(_struct, set_position)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1217,8 +1352,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_position))
+  if (CEF_MEMBER_MISSING(_struct, get_position)) {
     return CefPoint();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1229,12 +1365,45 @@
   return _retval;
 }
 
+NO_SANITIZE("cfi-icall")
+void CefWindowCToCpp::SetInsets(const CefInsets& insets) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, set_insets)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  _struct->set_insets(_struct, &insets);
+}
+
+NO_SANITIZE("cfi-icall") CefInsets CefWindowCToCpp::GetInsets() {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, get_insets)) {
+    return CefInsets();
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_insets_t _retval = _struct->get_insets(_struct);
+
+  // Return type: simple
+  return _retval;
+}
+
 NO_SANITIZE("cfi-icall") CefSize CefWindowCToCpp::GetPreferredSize() {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, get_preferred_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1249,8 +1418,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, size_to_preferred_size)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1262,8 +1432,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_minimum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1278,8 +1449,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_maximum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1294,8 +1466,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_height_for_width))
+  if (CEF_MEMBER_MISSING(_struct, get_height_for_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1310,8 +1483,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, invalidate_layout))
+  if (CEF_MEMBER_MISSING(_struct, invalidate_layout)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1323,8 +1497,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_visible))
+  if (CEF_MEMBER_MISSING(_struct, set_visible)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1336,8 +1511,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_visible))
+  if (CEF_MEMBER_MISSING(_struct, is_visible)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1352,8 +1528,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_drawn))
+  if (CEF_MEMBER_MISSING(_struct, is_drawn)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1368,8 +1545,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_enabled))
+  if (CEF_MEMBER_MISSING(_struct, set_enabled)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1381,8 +1559,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_enabled))
+  if (CEF_MEMBER_MISSING(_struct, is_enabled)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1397,8 +1576,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_focusable))
+  if (CEF_MEMBER_MISSING(_struct, set_focusable)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1410,8 +1590,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1426,8 +1607,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable))
+  if (CEF_MEMBER_MISSING(_struct, is_accessibility_focusable)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1442,8 +1624,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, request_focus))
+  if (CEF_MEMBER_MISSING(_struct, request_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1456,8 +1639,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, set_background_color))
+  if (CEF_MEMBER_MISSING(_struct, set_background_color)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1469,8 +1653,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_background_color))
+  if (CEF_MEMBER_MISSING(_struct, get_background_color)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1486,8 +1671,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1503,8 +1689,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_screen)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1520,8 +1707,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1537,8 +1725,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_window)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -1555,15 +1744,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_to_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_to_view(
@@ -1579,15 +1770,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view))
+  if (CEF_MEMBER_MISSING(_struct, convert_point_from_view)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_same
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->convert_point_from_view(
@@ -1612,7 +1805,7 @@
 CefCToCppRefCounted<CefWindowCToCpp, CefWindow, cef_window_t>::UnwrapDerived(
     CefWrapperType type,
     CefWindow* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/window_ctocpp.h b/src/libcef_dll/ctocpp/views/window_ctocpp.h
index 6d0ec71..97f0ffe 100644
--- a/src/libcef_dll/ctocpp/views/window_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/window_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=2206227226ce95ce062425eda932fa88af151b35$
+// $hash=d0c31c38bf29c9b44f645e69a912b6b8a4030066$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_WINDOW_CTOCPP_H_
@@ -21,7 +21,9 @@
 #endif
 
 #include <vector>
+#include "include/capi/views/cef_browser_view_capi.h"
 #include "include/capi/views/cef_window_capi.h"
+#include "include/views/cef_browser_view.h"
 #include "include/views/cef_window.h"
 #include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
 
@@ -34,116 +36,124 @@
   virtual ~CefWindowCToCpp();
 
   // CefWindow methods.
-  void Show() OVERRIDE;
-  void Hide() OVERRIDE;
-  void CenterWindow(const CefSize& size) OVERRIDE;
-  void Close() OVERRIDE;
-  bool IsClosed() OVERRIDE;
-  void Activate() OVERRIDE;
-  void Deactivate() OVERRIDE;
-  bool IsActive() OVERRIDE;
-  void BringToTop() OVERRIDE;
-  void SetAlwaysOnTop(bool on_top) OVERRIDE;
-  bool IsAlwaysOnTop() OVERRIDE;
-  void Maximize() OVERRIDE;
-  void Minimize() OVERRIDE;
-  void Restore() OVERRIDE;
-  void SetFullscreen(bool fullscreen) OVERRIDE;
-  bool IsMaximized() OVERRIDE;
-  bool IsMinimized() OVERRIDE;
-  bool IsFullscreen() OVERRIDE;
-  void SetTitle(const CefString& title) OVERRIDE;
-  CefString GetTitle() OVERRIDE;
-  void SetWindowIcon(CefRefPtr<CefImage> image) OVERRIDE;
-  CefRefPtr<CefImage> GetWindowIcon() OVERRIDE;
-  void SetWindowAppIcon(CefRefPtr<CefImage> image) OVERRIDE;
-  CefRefPtr<CefImage> GetWindowAppIcon() OVERRIDE;
+  void Show() override;
+  void ShowAsBrowserModalDialog(
+      CefRefPtr<CefBrowserView> browser_view) override;
+  void Hide() override;
+  void CenterWindow(const CefSize& size) override;
+  void Close() override;
+  bool IsClosed() override;
+  void Activate() override;
+  void Deactivate() override;
+  bool IsActive() override;
+  void BringToTop() override;
+  void SetAlwaysOnTop(bool on_top) override;
+  bool IsAlwaysOnTop() override;
+  void Maximize() override;
+  void Minimize() override;
+  void Restore() override;
+  void SetFullscreen(bool fullscreen) override;
+  bool IsMaximized() override;
+  bool IsMinimized() override;
+  bool IsFullscreen() override;
+  void SetTitle(const CefString& title) override;
+  CefString GetTitle() override;
+  void SetWindowIcon(CefRefPtr<CefImage> image) override;
+  CefRefPtr<CefImage> GetWindowIcon() override;
+  void SetWindowAppIcon(CefRefPtr<CefImage> image) override;
+  CefRefPtr<CefImage> GetWindowAppIcon() override;
+  CefRefPtr<CefOverlayController> AddOverlayView(
+      CefRefPtr<CefView> view,
+      cef_docking_mode_t docking_mode) override;
   void ShowMenu(CefRefPtr<CefMenuModel> menu_model,
                 const CefPoint& screen_point,
-                cef_menu_anchor_position_t anchor_position) OVERRIDE;
-  void CancelMenu() OVERRIDE;
-  CefRefPtr<CefDisplay> GetDisplay() OVERRIDE;
-  CefRect GetClientAreaBoundsInScreen() OVERRIDE;
+                cef_menu_anchor_position_t anchor_position) override;
+  void CancelMenu() override;
+  CefRefPtr<CefDisplay> GetDisplay() override;
+  CefRect GetClientAreaBoundsInScreen() override;
   void SetDraggableRegions(
-      const std::vector<CefDraggableRegion>& regions) OVERRIDE;
-  CefWindowHandle GetWindowHandle() OVERRIDE;
-  void SendKeyPress(int key_code, uint32 event_flags) OVERRIDE;
-  void SendMouseMove(int screen_x, int screen_y) OVERRIDE;
+      const std::vector<CefDraggableRegion>& regions) override;
+  CefWindowHandle GetWindowHandle() override;
+  void SendKeyPress(int key_code, uint32_t event_flags) override;
+  void SendMouseMove(int screen_x, int screen_y) override;
   void SendMouseEvents(cef_mouse_button_type_t button,
                        bool mouse_down,
-                       bool mouse_up) OVERRIDE;
+                       bool mouse_up) override;
   void SetAccelerator(int command_id,
                       int key_code,
                       bool shift_pressed,
                       bool ctrl_pressed,
-                      bool alt_pressed) OVERRIDE;
-  void RemoveAccelerator(int command_id) OVERRIDE;
-  void RemoveAllAccelerators() OVERRIDE;
+                      bool alt_pressed,
+                      bool high_priority) override;
+  void RemoveAccelerator(int command_id) override;
+  void RemoveAllAccelerators() override;
 
   // CefPanel methods.
-  CefRefPtr<CefWindow> AsWindow() OVERRIDE;
-  CefRefPtr<CefFillLayout> SetToFillLayout() OVERRIDE;
+  CefRefPtr<CefWindow> AsWindow() override;
+  CefRefPtr<CefFillLayout> SetToFillLayout() override;
   CefRefPtr<CefBoxLayout> SetToBoxLayout(
-      const CefBoxLayoutSettings& settings) OVERRIDE;
-  CefRefPtr<CefLayout> GetLayout() OVERRIDE;
-  void Layout() OVERRIDE;
-  void AddChildView(CefRefPtr<CefView> view) OVERRIDE;
-  void AddChildViewAt(CefRefPtr<CefView> view, int index) OVERRIDE;
-  void ReorderChildView(CefRefPtr<CefView> view, int index) OVERRIDE;
-  void RemoveChildView(CefRefPtr<CefView> view) OVERRIDE;
-  void RemoveAllChildViews() OVERRIDE;
-  size_t GetChildViewCount() OVERRIDE;
-  CefRefPtr<CefView> GetChildViewAt(int index) OVERRIDE;
+      const CefBoxLayoutSettings& settings) override;
+  CefRefPtr<CefLayout> GetLayout() override;
+  void Layout() override;
+  void AddChildView(CefRefPtr<CefView> view) override;
+  void AddChildViewAt(CefRefPtr<CefView> view, int index) override;
+  void ReorderChildView(CefRefPtr<CefView> view, int index) override;
+  void RemoveChildView(CefRefPtr<CefView> view) override;
+  void RemoveAllChildViews() override;
+  size_t GetChildViewCount() override;
+  CefRefPtr<CefView> GetChildViewAt(int index) override;
 
   // CefView methods.
-  CefRefPtr<CefBrowserView> AsBrowserView() OVERRIDE;
-  CefRefPtr<CefButton> AsButton() OVERRIDE;
-  CefRefPtr<CefPanel> AsPanel() OVERRIDE;
-  CefRefPtr<CefScrollView> AsScrollView() OVERRIDE;
-  CefRefPtr<CefTextfield> AsTextfield() OVERRIDE;
-  CefString GetTypeString() OVERRIDE;
-  CefString ToString(bool include_children) OVERRIDE;
-  bool IsValid() OVERRIDE;
-  bool IsAttached() OVERRIDE;
-  bool IsSame(CefRefPtr<CefView> that) OVERRIDE;
-  CefRefPtr<CefViewDelegate> GetDelegate() OVERRIDE;
-  CefRefPtr<CefWindow> GetWindow() OVERRIDE;
-  int GetID() OVERRIDE;
-  void SetID(int id) OVERRIDE;
-  int GetGroupID() OVERRIDE;
-  void SetGroupID(int group_id) OVERRIDE;
-  CefRefPtr<CefView> GetParentView() OVERRIDE;
-  CefRefPtr<CefView> GetViewForID(int id) OVERRIDE;
-  void SetBounds(const CefRect& bounds) OVERRIDE;
-  CefRect GetBounds() OVERRIDE;
-  CefRect GetBoundsInScreen() OVERRIDE;
-  void SetSize(const CefSize& size) OVERRIDE;
-  CefSize GetSize() OVERRIDE;
-  void SetPosition(const CefPoint& position) OVERRIDE;
-  CefPoint GetPosition() OVERRIDE;
-  CefSize GetPreferredSize() OVERRIDE;
-  void SizeToPreferredSize() OVERRIDE;
-  CefSize GetMinimumSize() OVERRIDE;
-  CefSize GetMaximumSize() OVERRIDE;
-  int GetHeightForWidth(int width) OVERRIDE;
-  void InvalidateLayout() OVERRIDE;
-  void SetVisible(bool visible) OVERRIDE;
-  bool IsVisible() OVERRIDE;
-  bool IsDrawn() OVERRIDE;
-  void SetEnabled(bool enabled) OVERRIDE;
-  bool IsEnabled() OVERRIDE;
-  void SetFocusable(bool focusable) OVERRIDE;
-  bool IsFocusable() OVERRIDE;
-  bool IsAccessibilityFocusable() OVERRIDE;
-  void RequestFocus() OVERRIDE;
-  void SetBackgroundColor(cef_color_t color) OVERRIDE;
-  cef_color_t GetBackgroundColor() OVERRIDE;
-  bool ConvertPointToScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromScreen(CefPoint& point) OVERRIDE;
-  bool ConvertPointToWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointFromWindow(CefPoint& point) OVERRIDE;
-  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
-  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) OVERRIDE;
+  CefRefPtr<CefBrowserView> AsBrowserView() override;
+  CefRefPtr<CefButton> AsButton() override;
+  CefRefPtr<CefPanel> AsPanel() override;
+  CefRefPtr<CefScrollView> AsScrollView() override;
+  CefRefPtr<CefTextfield> AsTextfield() override;
+  CefString GetTypeString() override;
+  CefString ToString(bool include_children) override;
+  bool IsValid() override;
+  bool IsAttached() override;
+  bool IsSame(CefRefPtr<CefView> that) override;
+  CefRefPtr<CefViewDelegate> GetDelegate() override;
+  CefRefPtr<CefWindow> GetWindow() override;
+  int GetID() override;
+  void SetID(int id) override;
+  int GetGroupID() override;
+  void SetGroupID(int group_id) override;
+  CefRefPtr<CefView> GetParentView() override;
+  CefRefPtr<CefView> GetViewForID(int id) override;
+  void SetBounds(const CefRect& bounds) override;
+  CefRect GetBounds() override;
+  CefRect GetBoundsInScreen() override;
+  void SetSize(const CefSize& size) override;
+  CefSize GetSize() override;
+  void SetPosition(const CefPoint& position) override;
+  CefPoint GetPosition() override;
+  void SetInsets(const CefInsets& insets) override;
+  CefInsets GetInsets() override;
+  CefSize GetPreferredSize() override;
+  void SizeToPreferredSize() override;
+  CefSize GetMinimumSize() override;
+  CefSize GetMaximumSize() override;
+  int GetHeightForWidth(int width) override;
+  void InvalidateLayout() override;
+  void SetVisible(bool visible) override;
+  bool IsVisible() override;
+  bool IsDrawn() override;
+  void SetEnabled(bool enabled) override;
+  bool IsEnabled() override;
+  void SetFocusable(bool focusable) override;
+  bool IsFocusable() override;
+  bool IsAccessibilityFocusable() override;
+  void RequestFocus() override;
+  void SetBackgroundColor(cef_color_t color) override;
+  cef_color_t GetBackgroundColor() override;
+  bool ConvertPointToScreen(CefPoint& point) override;
+  bool ConvertPointFromScreen(CefPoint& point) override;
+  bool ConvertPointToWindow(CefPoint& point) override;
+  bool ConvertPointFromWindow(CefPoint& point) override;
+  bool ConvertPointToView(CefRefPtr<CefView> view, CefPoint& point) override;
+  bool ConvertPointFromView(CefRefPtr<CefView> view, CefPoint& point) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_VIEWS_WINDOW_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/views/window_delegate_ctocpp.cc b/src/libcef_dll/ctocpp/views/window_delegate_ctocpp.cc
index 833ced7..2dae99e 100644
--- a/src/libcef_dll/ctocpp/views/window_delegate_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/views/window_delegate_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=42f9fdcc49577f6d052e4f357138efe4443a72d9$
+// $hash=bb69763a25cd013a50504d762a81c0a4454ce8eb$
 //
 
 #include "libcef_dll/ctocpp/views/window_delegate_ctocpp.h"
@@ -24,40 +24,136 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_window_created))
+  if (CEF_MEMBER_MISSING(_struct, on_window_created)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: window; type: refptr_diff
   DCHECK(window.get());
-  if (!window.get())
+  if (!window.get()) {
     return;
+  }
 
   // Execute
   _struct->on_window_created(_struct, CefWindowCppToC::Wrap(window));
 }
 
 NO_SANITIZE("cfi-icall")
+void CefWindowDelegateCToCpp::OnWindowClosing(CefRefPtr<CefWindow> window) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_window_delegate_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_window_closing)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: window; type: refptr_diff
+  DCHECK(window.get());
+  if (!window.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_window_closing(_struct, CefWindowCppToC::Wrap(window));
+}
+
+NO_SANITIZE("cfi-icall")
 void CefWindowDelegateCToCpp::OnWindowDestroyed(CefRefPtr<CefWindow> window) {
   shutdown_checker::AssertNotShutdown();
 
   cef_window_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_window_destroyed))
+  if (CEF_MEMBER_MISSING(_struct, on_window_destroyed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: window; type: refptr_diff
   DCHECK(window.get());
-  if (!window.get())
+  if (!window.get()) {
     return;
+  }
 
   // Execute
   _struct->on_window_destroyed(_struct, CefWindowCppToC::Wrap(window));
 }
 
 NO_SANITIZE("cfi-icall")
+void CefWindowDelegateCToCpp::OnWindowActivationChanged(
+    CefRefPtr<CefWindow> window,
+    bool active) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_window_delegate_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_window_activation_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: window; type: refptr_diff
+  DCHECK(window.get());
+  if (!window.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_window_activation_changed(_struct, CefWindowCppToC::Wrap(window),
+                                        active);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefWindowDelegateCToCpp::OnWindowBoundsChanged(CefRefPtr<CefWindow> window,
+                                                    const CefRect& new_bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_window_delegate_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_window_bounds_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: window; type: refptr_diff
+  DCHECK(window.get());
+  if (!window.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_window_bounds_changed(_struct, CefWindowCppToC::Wrap(window),
+                                    &new_bounds);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefWindowDelegateCToCpp::OnWindowFullscreenTransition(
+    CefRefPtr<CefWindow> window,
+    bool is_completed) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_window_delegate_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, on_window_fullscreen_transition)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: window; type: refptr_diff
+  DCHECK(window.get());
+  if (!window.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_window_fullscreen_transition(
+      _struct, CefWindowCppToC::Wrap(window), is_completed);
+}
+
+NO_SANITIZE("cfi-icall")
 CefRefPtr<CefWindow> CefWindowDelegateCToCpp::GetParentWindow(
     CefRefPtr<CefWindow> window,
     bool* is_menu,
@@ -65,23 +161,27 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_parent_window))
+  if (CEF_MEMBER_MISSING(_struct, get_parent_window)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: window; type: refptr_diff
   DCHECK(window.get());
-  if (!window.get())
+  if (!window.get()) {
     return nullptr;
+  }
   // Verify param: is_menu; type: bool_byaddr
   DCHECK(is_menu);
-  if (!is_menu)
+  if (!is_menu) {
     return nullptr;
+  }
   // Verify param: can_activate_menu; type: bool_byaddr
   DCHECK(can_activate_menu);
-  if (!can_activate_menu)
+  if (!can_activate_menu) {
     return nullptr;
+  }
 
   // Translate param: is_menu; type: bool_byaddr
   int is_menuInt = is_menu ? *is_menu : 0;
@@ -94,30 +194,110 @@
                                  &is_menuInt, &can_activate_menuInt);
 
   // Restore param:is_menu; type: bool_byaddr
-  if (is_menu)
+  if (is_menu) {
     *is_menu = is_menuInt ? true : false;
+  }
   // Restore param:can_activate_menu; type: bool_byaddr
-  if (can_activate_menu)
+  if (can_activate_menu) {
     *can_activate_menu = can_activate_menuInt ? true : false;
+  }
 
   // Return type: refptr_diff
   return CefWindowCppToC::Unwrap(_retval);
 }
 
 NO_SANITIZE("cfi-icall")
+bool CefWindowDelegateCToCpp::IsWindowModalDialog(CefRefPtr<CefWindow> window) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_window_delegate_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, is_window_modal_dialog)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: window; type: refptr_diff
+  DCHECK(window.get());
+  if (!window.get()) {
+    return false;
+  }
+
+  // Execute
+  int _retval =
+      _struct->is_window_modal_dialog(_struct, CefWindowCppToC::Wrap(window));
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+CefRect CefWindowDelegateCToCpp::GetInitialBounds(CefRefPtr<CefWindow> window) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_window_delegate_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_initial_bounds)) {
+    return CefRect();
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: window; type: refptr_diff
+  DCHECK(window.get());
+  if (!window.get()) {
+    return CefRect();
+  }
+
+  // Execute
+  cef_rect_t _retval =
+      _struct->get_initial_bounds(_struct, CefWindowCppToC::Wrap(window));
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall")
+cef_show_state_t CefWindowDelegateCToCpp::GetInitialShowState(
+    CefRefPtr<CefWindow> window) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_window_delegate_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_initial_show_state)) {
+    return CEF_SHOW_STATE_NORMAL;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: window; type: refptr_diff
+  DCHECK(window.get());
+  if (!window.get()) {
+    return CEF_SHOW_STATE_NORMAL;
+  }
+
+  // Execute
+  cef_show_state_t _retval =
+      _struct->get_initial_show_state(_struct, CefWindowCppToC::Wrap(window));
+
+  // Return type: simple
+  return _retval;
+}
+
+NO_SANITIZE("cfi-icall")
 bool CefWindowDelegateCToCpp::IsFrameless(CefRefPtr<CefWindow> window) {
   shutdown_checker::AssertNotShutdown();
 
   cef_window_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_frameless))
+  if (CEF_MEMBER_MISSING(_struct, is_frameless)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: window; type: refptr_diff
   DCHECK(window.get());
-  if (!window.get())
+  if (!window.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->is_frameless(_struct, CefWindowCppToC::Wrap(window));
@@ -127,19 +307,78 @@
 }
 
 NO_SANITIZE("cfi-icall")
+bool CefWindowDelegateCToCpp::WithStandardWindowButtons(
+    CefRefPtr<CefWindow> window) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_window_delegate_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, with_standard_window_buttons)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: window; type: refptr_diff
+  DCHECK(window.get());
+  if (!window.get()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->with_standard_window_buttons(
+      _struct, CefWindowCppToC::Wrap(window));
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
+bool CefWindowDelegateCToCpp::GetTitlebarHeight(CefRefPtr<CefWindow> window,
+                                                float* titlebar_height) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_window_delegate_t* _struct = GetStruct();
+  if (CEF_MEMBER_MISSING(_struct, get_titlebar_height)) {
+    return false;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: window; type: refptr_diff
+  DCHECK(window.get());
+  if (!window.get()) {
+    return false;
+  }
+  // Verify param: titlebar_height; type: simple_byaddr
+  DCHECK(titlebar_height);
+  if (!titlebar_height) {
+    return false;
+  }
+
+  // Execute
+  int _retval = _struct->get_titlebar_height(
+      _struct, CefWindowCppToC::Wrap(window), titlebar_height);
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
 bool CefWindowDelegateCToCpp::CanResize(CefRefPtr<CefWindow> window) {
   shutdown_checker::AssertNotShutdown();
 
   cef_window_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, can_resize))
+  if (CEF_MEMBER_MISSING(_struct, can_resize)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: window; type: refptr_diff
   DCHECK(window.get());
-  if (!window.get())
+  if (!window.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->can_resize(_struct, CefWindowCppToC::Wrap(window));
@@ -153,15 +392,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, can_maximize))
+  if (CEF_MEMBER_MISSING(_struct, can_maximize)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: window; type: refptr_diff
   DCHECK(window.get());
-  if (!window.get())
+  if (!window.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->can_maximize(_struct, CefWindowCppToC::Wrap(window));
@@ -175,15 +416,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, can_minimize))
+  if (CEF_MEMBER_MISSING(_struct, can_minimize)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: window; type: refptr_diff
   DCHECK(window.get());
-  if (!window.get())
+  if (!window.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->can_minimize(_struct, CefWindowCppToC::Wrap(window));
@@ -197,15 +440,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, can_close))
+  if (CEF_MEMBER_MISSING(_struct, can_close)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: window; type: refptr_diff
   DCHECK(window.get());
-  if (!window.get())
+  if (!window.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->can_close(_struct, CefWindowCppToC::Wrap(window));
@@ -220,15 +465,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_accelerator))
+  if (CEF_MEMBER_MISSING(_struct, on_accelerator)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: window; type: refptr_diff
   DCHECK(window.get());
-  if (!window.get())
+  if (!window.get()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->on_accelerator(_struct, CefWindowCppToC::Wrap(window),
@@ -244,15 +491,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_window_delegate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, on_key_event))
+  if (CEF_MEMBER_MISSING(_struct, on_key_event)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: window; type: refptr_diff
   DCHECK(window.get());
-  if (!window.get())
+  if (!window.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -268,15 +517,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_preferred_size))
+  if (CEF_MEMBER_MISSING(_struct, get_preferred_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -292,15 +543,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_minimum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_minimum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -316,15 +569,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_maximum_size))
+  if (CEF_MEMBER_MISSING(_struct, get_maximum_size)) {
     return CefSize();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return CefSize();
+  }
 
   // Execute
   cef_size_t _retval =
@@ -341,15 +596,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, get_height_for_width))
+  if (CEF_MEMBER_MISSING(_struct, get_height_for_width)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return 0;
+  }
 
   // Execute
   int _retval =
@@ -367,19 +624,22 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_parent_view_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_parent_view_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
   // Verify param: parent; type: refptr_diff
   DCHECK(parent.get());
-  if (!parent.get())
+  if (!parent.get()) {
     return;
+  }
 
   // Execute
   _struct->on_parent_view_changed(_struct, CefViewCppToC::Wrap(view), added,
@@ -394,19 +654,22 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_child_view_changed))
+  if (CEF_MEMBER_MISSING(_struct, on_child_view_changed)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
   // Verify param: child; type: refptr_diff
   DCHECK(child.get());
-  if (!child.get())
+  if (!child.get()) {
     return;
+  }
 
   // Execute
   _struct->on_child_view_changed(_struct, CefViewCppToC::Wrap(view), added,
@@ -414,20 +677,68 @@
 }
 
 NO_SANITIZE("cfi-icall")
+void CefWindowDelegateCToCpp::OnWindowChanged(CefRefPtr<CefView> view,
+                                              bool added) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_delegate_t* _struct =
+      reinterpret_cast<cef_view_delegate_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, on_window_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: view; type: refptr_diff
+  DCHECK(view.get());
+  if (!view.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_window_changed(_struct, CefViewCppToC::Wrap(view), added);
+}
+
+NO_SANITIZE("cfi-icall")
+void CefWindowDelegateCToCpp::OnLayoutChanged(CefRefPtr<CefView> view,
+                                              const CefRect& new_bounds) {
+  shutdown_checker::AssertNotShutdown();
+
+  cef_view_delegate_t* _struct =
+      reinterpret_cast<cef_view_delegate_t*>(GetStruct());
+  if (CEF_MEMBER_MISSING(_struct, on_layout_changed)) {
+    return;
+  }
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: view; type: refptr_diff
+  DCHECK(view.get());
+  if (!view.get()) {
+    return;
+  }
+
+  // Execute
+  _struct->on_layout_changed(_struct, CefViewCppToC::Wrap(view), &new_bounds);
+}
+
+NO_SANITIZE("cfi-icall")
 void CefWindowDelegateCToCpp::OnFocus(CefRefPtr<CefView> view) {
   shutdown_checker::AssertNotShutdown();
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_focus))
+  if (CEF_MEMBER_MISSING(_struct, on_focus)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->on_focus(_struct, CefViewCppToC::Wrap(view));
@@ -439,15 +750,17 @@
 
   cef_view_delegate_t* _struct =
       reinterpret_cast<cef_view_delegate_t*>(GetStruct());
-  if (CEF_MEMBER_MISSING(_struct, on_blur))
+  if (CEF_MEMBER_MISSING(_struct, on_blur)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: view; type: refptr_diff
   DCHECK(view.get());
-  if (!view.get())
+  if (!view.get()) {
     return;
+  }
 
   // Execute
   _struct->on_blur(_struct, CefViewCppToC::Wrap(view));
@@ -469,7 +782,7 @@
     CefWindowDelegate,
     cef_window_delegate_t>::UnwrapDerived(CefWrapperType type,
                                           CefWindowDelegate* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/views/window_delegate_ctocpp.h b/src/libcef_dll/ctocpp/views/window_delegate_ctocpp.h
index 6ed7b39..fe005af 100644
--- a/src/libcef_dll/ctocpp/views/window_delegate_ctocpp.h
+++ b/src/libcef_dll/ctocpp/views/window_delegate_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=e1c4def5dc9c50b90a1a57bb7769f18763827b25$
+// $hash=e1ed42bb378f9f140e006ec582c0e908f711e7fa$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_WINDOW_DELEGATE_CTOCPP_H_
@@ -38,11 +38,24 @@
 
   // CefWindowDelegate methods.
   void OnWindowCreated(CefRefPtr<CefWindow> window) override;
+  void OnWindowClosing(CefRefPtr<CefWindow> window) override;
   void OnWindowDestroyed(CefRefPtr<CefWindow> window) override;
+  void OnWindowActivationChanged(CefRefPtr<CefWindow> window,
+                                 bool active) override;
+  void OnWindowBoundsChanged(CefRefPtr<CefWindow> window,
+                             const CefRect& new_bounds) override;
+  void OnWindowFullscreenTransition(CefRefPtr<CefWindow> window,
+                                    bool is_completed) override;
   CefRefPtr<CefWindow> GetParentWindow(CefRefPtr<CefWindow> window,
                                        bool* is_menu,
                                        bool* can_activate_menu) override;
+  bool IsWindowModalDialog(CefRefPtr<CefWindow> window) override;
+  CefRect GetInitialBounds(CefRefPtr<CefWindow> window) override;
+  cef_show_state_t GetInitialShowState(CefRefPtr<CefWindow> window) override;
   bool IsFrameless(CefRefPtr<CefWindow> window) override;
+  bool WithStandardWindowButtons(CefRefPtr<CefWindow> window) override;
+  bool GetTitlebarHeight(CefRefPtr<CefWindow> window,
+                         float* titlebar_height) override;
   bool CanResize(CefRefPtr<CefWindow> window) override;
   bool CanMaximize(CefRefPtr<CefWindow> window) override;
   bool CanMinimize(CefRefPtr<CefWindow> window) override;
@@ -64,6 +77,9 @@
   void OnChildViewChanged(CefRefPtr<CefView> view,
                           bool added,
                           CefRefPtr<CefView> child) override;
+  void OnWindowChanged(CefRefPtr<CefView> view, bool added) override;
+  void OnLayoutChanged(CefRefPtr<CefView> view,
+                       const CefRect& new_bounds) override;
   void OnFocus(CefRefPtr<CefView> view) override;
   void OnBlur(CefRefPtr<CefView> view) override;
 };
diff --git a/src/libcef_dll/ctocpp/waitable_event_ctocpp.cc b/src/libcef_dll/ctocpp/waitable_event_ctocpp.cc
index 3c98086..d784766 100644
--- a/src/libcef_dll/ctocpp/waitable_event_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/waitable_event_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=3a22edd7a71ffaa44bb7215dcb7c7c0df8dd6a23$
+// $hash=5a17c94ca2e63c936ad570de435893b55326df42$
 //
 
 #include "libcef_dll/ctocpp/waitable_event_ctocpp.h"
@@ -39,8 +39,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_waitable_event_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, reset))
+  if (CEF_MEMBER_MISSING(_struct, reset)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -52,8 +53,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_waitable_event_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, signal))
+  if (CEF_MEMBER_MISSING(_struct, signal)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -65,8 +67,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_waitable_event_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_signaled))
+  if (CEF_MEMBER_MISSING(_struct, is_signaled)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -81,8 +84,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_waitable_event_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, wait))
+  if (CEF_MEMBER_MISSING(_struct, wait)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -90,12 +94,14 @@
   _struct->wait(_struct);
 }
 
-NO_SANITIZE("cfi-icall") bool CefWaitableEventCToCpp::TimedWait(int64 max_ms) {
+NO_SANITIZE("cfi-icall")
+bool CefWaitableEventCToCpp::TimedWait(int64_t max_ms) {
   shutdown_checker::AssertNotShutdown();
 
   cef_waitable_event_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, timed_wait))
+  if (CEF_MEMBER_MISSING(_struct, timed_wait)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -122,7 +128,7 @@
                     CefWaitableEvent,
                     cef_waitable_event_t>::UnwrapDerived(CefWrapperType type,
                                                          CefWaitableEvent* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/waitable_event_ctocpp.h b/src/libcef_dll/ctocpp/waitable_event_ctocpp.h
index a735e61..331ad2d 100644
--- a/src/libcef_dll/ctocpp/waitable_event_ctocpp.h
+++ b/src/libcef_dll/ctocpp/waitable_event_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=42d88a6d0562330e918279cb11c29ab6b5a848bf$
+// $hash=587149e6f5d7d1dd1200f6ce7dd7294da82417cf$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_WAITABLE_EVENT_CTOCPP_H_
@@ -35,11 +35,11 @@
   virtual ~CefWaitableEventCToCpp();
 
   // CefWaitableEvent methods.
-  void Reset() OVERRIDE;
-  void Signal() OVERRIDE;
-  bool IsSignaled() OVERRIDE;
-  void Wait() OVERRIDE;
-  bool TimedWait(int64 max_ms) OVERRIDE;
+  void Reset() override;
+  void Signal() override;
+  bool IsSignaled() override;
+  void Wait() override;
+  bool TimedWait(int64_t max_ms) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_WAITABLE_EVENT_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/web_plugin_info_ctocpp.cc b/src/libcef_dll/ctocpp/web_plugin_info_ctocpp.cc
deleted file mode 100644
index 4c0da73..0000000
--- a/src/libcef_dll/ctocpp/web_plugin_info_ctocpp.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=8893d13d3250068c66c1a4bb82bf7c9345e95f27$
-//
-
-#include "libcef_dll/ctocpp/web_plugin_info_ctocpp.h"
-#include "libcef_dll/shutdown_checker.h"
-
-// VIRTUAL METHODS - Body may be edited by hand.
-
-NO_SANITIZE("cfi-icall") CefString CefWebPluginInfoCToCpp::GetName() {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_web_plugin_info_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_name))
-    return CefString();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  cef_string_userfree_t _retval = _struct->get_name(_struct);
-
-  // Return type: string
-  CefString _retvalStr;
-  _retvalStr.AttachToUserFree(_retval);
-  return _retvalStr;
-}
-
-NO_SANITIZE("cfi-icall") CefString CefWebPluginInfoCToCpp::GetPath() {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_web_plugin_info_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_path))
-    return CefString();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  cef_string_userfree_t _retval = _struct->get_path(_struct);
-
-  // Return type: string
-  CefString _retvalStr;
-  _retvalStr.AttachToUserFree(_retval);
-  return _retvalStr;
-}
-
-NO_SANITIZE("cfi-icall") CefString CefWebPluginInfoCToCpp::GetVersion() {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_web_plugin_info_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_version))
-    return CefString();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  cef_string_userfree_t _retval = _struct->get_version(_struct);
-
-  // Return type: string
-  CefString _retvalStr;
-  _retvalStr.AttachToUserFree(_retval);
-  return _retvalStr;
-}
-
-NO_SANITIZE("cfi-icall") CefString CefWebPluginInfoCToCpp::GetDescription() {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_web_plugin_info_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_description))
-    return CefString();
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  cef_string_userfree_t _retval = _struct->get_description(_struct);
-
-  // Return type: string
-  CefString _retvalStr;
-  _retvalStr.AttachToUserFree(_retval);
-  return _retvalStr;
-}
-
-// CONSTRUCTOR - Do not edit by hand.
-
-CefWebPluginInfoCToCpp::CefWebPluginInfoCToCpp() {}
-
-// DESTRUCTOR - Do not edit by hand.
-
-CefWebPluginInfoCToCpp::~CefWebPluginInfoCToCpp() {
-  shutdown_checker::AssertNotShutdown();
-}
-
-template <>
-cef_web_plugin_info_t*
-CefCToCppRefCounted<CefWebPluginInfoCToCpp,
-                    CefWebPluginInfo,
-                    cef_web_plugin_info_t>::UnwrapDerived(CefWrapperType type,
-                                                          CefWebPluginInfo* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
-  return nullptr;
-}
-
-template <>
-CefWrapperType CefCToCppRefCounted<CefWebPluginInfoCToCpp,
-                                   CefWebPluginInfo,
-                                   cef_web_plugin_info_t>::kWrapperType =
-    WT_WEB_PLUGIN_INFO;
diff --git a/src/libcef_dll/ctocpp/web_plugin_info_ctocpp.h b/src/libcef_dll/ctocpp/web_plugin_info_ctocpp.h
deleted file mode 100644
index a39069a..0000000
--- a/src/libcef_dll/ctocpp/web_plugin_info_ctocpp.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=0485ac1dcee7fa6707d64e312369c1eb95c1c96d$
-//
-
-#ifndef CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_INFO_CTOCPP_H_
-#define CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_INFO_CTOCPP_H_
-#pragma once
-
-#if !defined(WRAPPING_CEF_SHARED)
-#error This file can be included wrapper-side only
-#endif
-
-#include "include/capi/cef_browser_capi.h"
-#include "include/capi/cef_web_plugin_capi.h"
-#include "include/cef_browser.h"
-#include "include/cef_web_plugin.h"
-#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
-
-// Wrap a C structure with a C++ class.
-// This class may be instantiated and accessed wrapper-side only.
-class CefWebPluginInfoCToCpp
-    : public CefCToCppRefCounted<CefWebPluginInfoCToCpp,
-                                 CefWebPluginInfo,
-                                 cef_web_plugin_info_t> {
- public:
-  CefWebPluginInfoCToCpp();
-  virtual ~CefWebPluginInfoCToCpp();
-
-  // CefWebPluginInfo methods.
-  CefString GetName() OVERRIDE;
-  CefString GetPath() OVERRIDE;
-  CefString GetVersion() OVERRIDE;
-  CefString GetDescription() OVERRIDE;
-};
-
-#endif  // CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_INFO_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.cc b/src/libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.cc
deleted file mode 100644
index 14add4e..0000000
--- a/src/libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=aa1d37e0ac4dbe70fc8e0739676ef968c8ffa765$
-//
-
-#include "libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.h"
-#include "libcef_dll/cpptoc/web_plugin_info_cpptoc.h"
-#include "libcef_dll/shutdown_checker.h"
-
-// VIRTUAL METHODS - Body may be edited by hand.
-
-NO_SANITIZE("cfi-icall")
-bool CefWebPluginInfoVisitorCToCpp::Visit(CefRefPtr<CefWebPluginInfo> info,
-                                          int count,
-                                          int total) {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_web_plugin_info_visitor_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, visit))
-    return false;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: info; type: refptr_diff
-  DCHECK(info.get());
-  if (!info.get())
-    return false;
-
-  // Execute
-  int _retval =
-      _struct->visit(_struct, CefWebPluginInfoCppToC::Wrap(info), count, total);
-
-  // Return type: bool
-  return _retval ? true : false;
-}
-
-// CONSTRUCTOR - Do not edit by hand.
-
-CefWebPluginInfoVisitorCToCpp::CefWebPluginInfoVisitorCToCpp() {}
-
-// DESTRUCTOR - Do not edit by hand.
-
-CefWebPluginInfoVisitorCToCpp::~CefWebPluginInfoVisitorCToCpp() {
-  shutdown_checker::AssertNotShutdown();
-}
-
-template <>
-cef_web_plugin_info_visitor_t* CefCToCppRefCounted<
-    CefWebPluginInfoVisitorCToCpp,
-    CefWebPluginInfoVisitor,
-    cef_web_plugin_info_visitor_t>::UnwrapDerived(CefWrapperType type,
-                                                  CefWebPluginInfoVisitor* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
-  return nullptr;
-}
-
-template <>
-CefWrapperType
-    CefCToCppRefCounted<CefWebPluginInfoVisitorCToCpp,
-                        CefWebPluginInfoVisitor,
-                        cef_web_plugin_info_visitor_t>::kWrapperType =
-        WT_WEB_PLUGIN_INFO_VISITOR;
diff --git a/src/libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.h b/src/libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.h
deleted file mode 100644
index f9384e6..0000000
--- a/src/libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=b53a2be3ea825d25ee3071adc3084491649d12df$
-//
-
-#ifndef CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_INFO_VISITOR_CTOCPP_H_
-#define CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_INFO_VISITOR_CTOCPP_H_
-#pragma once
-
-#if !defined(BUILDING_CEF_SHARED)
-#error This file can be included DLL-side only
-#endif
-
-#include "include/capi/cef_browser_capi.h"
-#include "include/capi/cef_web_plugin_capi.h"
-#include "include/cef_browser.h"
-#include "include/cef_web_plugin.h"
-#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
-
-// Wrap a C structure with a C++ class.
-// This class may be instantiated and accessed DLL-side only.
-class CefWebPluginInfoVisitorCToCpp
-    : public CefCToCppRefCounted<CefWebPluginInfoVisitorCToCpp,
-                                 CefWebPluginInfoVisitor,
-                                 cef_web_plugin_info_visitor_t> {
- public:
-  CefWebPluginInfoVisitorCToCpp();
-  virtual ~CefWebPluginInfoVisitorCToCpp();
-
-  // CefWebPluginInfoVisitor methods.
-  bool Visit(CefRefPtr<CefWebPluginInfo> info, int count, int total) override;
-};
-
-#endif  // CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_INFO_VISITOR_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.cc b/src/libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.cc
deleted file mode 100644
index f5550aa..0000000
--- a/src/libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=7d4c6744f017df70be4318f1f61b140b4ee40ed5$
-//
-
-#include "libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.h"
-#include "libcef_dll/shutdown_checker.h"
-
-// VIRTUAL METHODS - Body may be edited by hand.
-
-NO_SANITIZE("cfi-icall")
-void CefWebPluginUnstableCallbackCToCpp::IsUnstable(const CefString& path,
-                                                    bool unstable) {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_web_plugin_unstable_callback_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_unstable))
-    return;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: path; type: string_byref_const
-  DCHECK(!path.empty());
-  if (path.empty())
-    return;
-
-  // Execute
-  _struct->is_unstable(_struct, path.GetStruct(), unstable);
-}
-
-// CONSTRUCTOR - Do not edit by hand.
-
-CefWebPluginUnstableCallbackCToCpp::CefWebPluginUnstableCallbackCToCpp() {}
-
-// DESTRUCTOR - Do not edit by hand.
-
-CefWebPluginUnstableCallbackCToCpp::~CefWebPluginUnstableCallbackCToCpp() {
-  shutdown_checker::AssertNotShutdown();
-}
-
-template <>
-cef_web_plugin_unstable_callback_t*
-CefCToCppRefCounted<CefWebPluginUnstableCallbackCToCpp,
-                    CefWebPluginUnstableCallback,
-                    cef_web_plugin_unstable_callback_t>::
-    UnwrapDerived(CefWrapperType type, CefWebPluginUnstableCallback* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
-  return nullptr;
-}
-
-template <>
-CefWrapperType
-    CefCToCppRefCounted<CefWebPluginUnstableCallbackCToCpp,
-                        CefWebPluginUnstableCallback,
-                        cef_web_plugin_unstable_callback_t>::kWrapperType =
-        WT_WEB_PLUGIN_UNSTABLE_CALLBACK;
diff --git a/src/libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.h b/src/libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.h
deleted file mode 100644
index 48714ea..0000000
--- a/src/libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=03d71fb933226f515bd852f98c1293b076bc9ec0$
-//
-
-#ifndef CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_UNSTABLE_CALLBACK_CTOCPP_H_
-#define CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_UNSTABLE_CALLBACK_CTOCPP_H_
-#pragma once
-
-#if !defined(BUILDING_CEF_SHARED)
-#error This file can be included DLL-side only
-#endif
-
-#include "include/capi/cef_browser_capi.h"
-#include "include/capi/cef_web_plugin_capi.h"
-#include "include/cef_browser.h"
-#include "include/cef_web_plugin.h"
-#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
-
-// Wrap a C structure with a C++ class.
-// This class may be instantiated and accessed DLL-side only.
-class CefWebPluginUnstableCallbackCToCpp
-    : public CefCToCppRefCounted<CefWebPluginUnstableCallbackCToCpp,
-                                 CefWebPluginUnstableCallback,
-                                 cef_web_plugin_unstable_callback_t> {
- public:
-  CefWebPluginUnstableCallbackCToCpp();
-  virtual ~CefWebPluginUnstableCallbackCToCpp();
-
-  // CefWebPluginUnstableCallback methods.
-  void IsUnstable(const CefString& path, bool unstable) override;
-};
-
-#endif  // CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_UNSTABLE_CALLBACK_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/write_handler_ctocpp.cc b/src/libcef_dll/ctocpp/write_handler_ctocpp.cc
index 93da3fa..0c222e3 100644
--- a/src/libcef_dll/ctocpp/write_handler_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/write_handler_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=de27cf9a29354fb3f0fd37141f1a4fe45ff73c88$
+// $hash=7e4a0a11aab2b3b4cfedb6cd6efe099b154a9063$
 //
 
 #include "libcef_dll/ctocpp/write_handler_ctocpp.h"
@@ -22,15 +22,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_write_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, write))
+  if (CEF_MEMBER_MISSING(_struct, write)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: ptr; type: simple_byaddr
   DCHECK(ptr);
-  if (!ptr)
+  if (!ptr) {
     return 0;
+  }
 
   // Execute
   size_t _retval = _struct->write(_struct, ptr, size, n);
@@ -40,12 +42,13 @@
 }
 
 NO_SANITIZE("cfi-icall")
-int CefWriteHandlerCToCpp::Seek(int64 offset, int whence) {
+int CefWriteHandlerCToCpp::Seek(int64_t offset, int whence) {
   shutdown_checker::AssertNotShutdown();
 
   cef_write_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, seek))
+  if (CEF_MEMBER_MISSING(_struct, seek)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -56,17 +59,18 @@
   return _retval;
 }
 
-NO_SANITIZE("cfi-icall") int64 CefWriteHandlerCToCpp::Tell() {
+NO_SANITIZE("cfi-icall") int64_t CefWriteHandlerCToCpp::Tell() {
   shutdown_checker::AssertNotShutdown();
 
   cef_write_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, tell))
+  if (CEF_MEMBER_MISSING(_struct, tell)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int64 _retval = _struct->tell(_struct);
+  int64_t _retval = _struct->tell(_struct);
 
   // Return type: simple
   return _retval;
@@ -76,8 +80,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_write_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, flush))
+  if (CEF_MEMBER_MISSING(_struct, flush)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -92,8 +97,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_write_handler_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, may_block))
+  if (CEF_MEMBER_MISSING(_struct, may_block)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -120,7 +126,7 @@
                     CefWriteHandler,
                     cef_write_handler_t>::UnwrapDerived(CefWrapperType type,
                                                         CefWriteHandler* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/write_handler_ctocpp.h b/src/libcef_dll/ctocpp/write_handler_ctocpp.h
index 21e2429..794eb8e 100644
--- a/src/libcef_dll/ctocpp/write_handler_ctocpp.h
+++ b/src/libcef_dll/ctocpp/write_handler_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=5dd7e1db0aefed2cc2bd78dac1cd77aabe76d064$
+// $hash=e5d33f6123dce1c11aaeb7fefe9d86eb244dda7e$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_WRITE_HANDLER_CTOCPP_H_
@@ -35,8 +35,8 @@
 
   // CefWriteHandler methods.
   size_t Write(const void* ptr, size_t size, size_t n) override;
-  int Seek(int64 offset, int whence) override;
-  int64 Tell() override;
+  int Seek(int64_t offset, int whence) override;
+  int64_t Tell() override;
   int Flush() override;
   bool MayBlock() override;
 };
diff --git a/src/libcef_dll/ctocpp/x509cert_principal_ctocpp.cc b/src/libcef_dll/ctocpp/x509cert_principal_ctocpp.cc
index 2e90645..46680dc 100644
--- a/src/libcef_dll/ctocpp/x509cert_principal_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/x509cert_principal_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=66b1884e86ab45e63bbe4f902da5934d61520d45$
+// $hash=5a5997b69936ad47fb9ab5b6f4016f33c91110c7$
 //
 
 #include "libcef_dll/ctocpp/x509cert_principal_ctocpp.h"
@@ -23,8 +23,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_x509cert_principal_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_display_name))
+  if (CEF_MEMBER_MISSING(_struct, get_display_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -41,8 +42,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_x509cert_principal_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_common_name))
+  if (CEF_MEMBER_MISSING(_struct, get_common_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -60,8 +62,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_x509cert_principal_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_locality_name))
+  if (CEF_MEMBER_MISSING(_struct, get_locality_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -79,8 +82,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_x509cert_principal_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_state_or_province_name))
+  if (CEF_MEMBER_MISSING(_struct, get_state_or_province_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -98,8 +102,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_x509cert_principal_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_country_name))
+  if (CEF_MEMBER_MISSING(_struct, get_country_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -113,49 +118,23 @@
 }
 
 NO_SANITIZE("cfi-icall")
-void CefX509CertPrincipalCToCpp::GetStreetAddresses(
-    std::vector<CefString>& addresses) {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_x509cert_principal_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_street_addresses))
-    return;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Translate param: addresses; type: string_vec_byref
-  cef_string_list_t addressesList = cef_string_list_alloc();
-  DCHECK(addressesList);
-  if (addressesList)
-    transfer_string_list_contents(addresses, addressesList);
-
-  // Execute
-  _struct->get_street_addresses(_struct, addressesList);
-
-  // Restore param:addresses; type: string_vec_byref
-  if (addressesList) {
-    addresses.clear();
-    transfer_string_list_contents(addressesList, addresses);
-    cef_string_list_free(addressesList);
-  }
-}
-
-NO_SANITIZE("cfi-icall")
 void CefX509CertPrincipalCToCpp::GetOrganizationNames(
     std::vector<CefString>& names) {
   shutdown_checker::AssertNotShutdown();
 
   cef_x509cert_principal_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_organization_names))
+  if (CEF_MEMBER_MISSING(_struct, get_organization_names)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: names; type: string_vec_byref
   cef_string_list_t namesList = cef_string_list_alloc();
   DCHECK(namesList);
-  if (namesList)
+  if (namesList) {
     transfer_string_list_contents(names, namesList);
+  }
 
   // Execute
   _struct->get_organization_names(_struct, namesList);
@@ -174,16 +153,18 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_x509cert_principal_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_organization_unit_names))
+  if (CEF_MEMBER_MISSING(_struct, get_organization_unit_names)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Translate param: names; type: string_vec_byref
   cef_string_list_t namesList = cef_string_list_alloc();
   DCHECK(namesList);
-  if (namesList)
+  if (namesList) {
     transfer_string_list_contents(names, namesList);
+  }
 
   // Execute
   _struct->get_organization_unit_names(_struct, namesList);
@@ -196,34 +177,6 @@
   }
 }
 
-NO_SANITIZE("cfi-icall")
-void CefX509CertPrincipalCToCpp::GetDomainComponents(
-    std::vector<CefString>& components) {
-  shutdown_checker::AssertNotShutdown();
-
-  cef_x509cert_principal_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_domain_components))
-    return;
-
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Translate param: components; type: string_vec_byref
-  cef_string_list_t componentsList = cef_string_list_alloc();
-  DCHECK(componentsList);
-  if (componentsList)
-    transfer_string_list_contents(components, componentsList);
-
-  // Execute
-  _struct->get_domain_components(_struct, componentsList);
-
-  // Restore param:components; type: string_vec_byref
-  if (componentsList) {
-    components.clear();
-    transfer_string_list_contents(componentsList, components);
-    cef_string_list_free(componentsList);
-  }
-}
-
 // CONSTRUCTOR - Do not edit by hand.
 
 CefX509CertPrincipalCToCpp::CefX509CertPrincipalCToCpp() {}
@@ -240,7 +193,7 @@
     CefX509CertPrincipal,
     cef_x509cert_principal_t>::UnwrapDerived(CefWrapperType type,
                                              CefX509CertPrincipal* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/x509cert_principal_ctocpp.h b/src/libcef_dll/ctocpp/x509cert_principal_ctocpp.h
index fb6fd3a..44c6486 100644
--- a/src/libcef_dll/ctocpp/x509cert_principal_ctocpp.h
+++ b/src/libcef_dll/ctocpp/x509cert_principal_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=eb6a2fc4970c9511728a65bb944720cc44c76568$
+// $hash=8baec3ed7625e735ebfb911bd92dacecbebe9cb4$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_X509CERT_PRINCIPAL_CTOCPP_H_
@@ -36,15 +36,13 @@
   virtual ~CefX509CertPrincipalCToCpp();
 
   // CefX509CertPrincipal methods.
-  CefString GetDisplayName() OVERRIDE;
-  CefString GetCommonName() OVERRIDE;
-  CefString GetLocalityName() OVERRIDE;
-  CefString GetStateOrProvinceName() OVERRIDE;
-  CefString GetCountryName() OVERRIDE;
-  void GetStreetAddresses(std::vector<CefString>& addresses) OVERRIDE;
-  void GetOrganizationNames(std::vector<CefString>& names) OVERRIDE;
-  void GetOrganizationUnitNames(std::vector<CefString>& names) OVERRIDE;
-  void GetDomainComponents(std::vector<CefString>& components) OVERRIDE;
+  CefString GetDisplayName() override;
+  CefString GetCommonName() override;
+  CefString GetLocalityName() override;
+  CefString GetStateOrProvinceName() override;
+  CefString GetCountryName() override;
+  void GetOrganizationNames(std::vector<CefString>& names) override;
+  void GetOrganizationUnitNames(std::vector<CefString>& names) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_X509CERT_PRINCIPAL_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/x509certificate_ctocpp.cc b/src/libcef_dll/ctocpp/x509certificate_ctocpp.cc
index 6f98f86..8855002 100644
--- a/src/libcef_dll/ctocpp/x509certificate_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/x509certificate_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c47209a99213feca0178f75623f6c7d1b6985f06$
+// $hash=e3ddef0c76d5f5a33d463751cb799235cad58bf4$
 //
 
 #include "libcef_dll/ctocpp/x509certificate_ctocpp.h"
@@ -25,8 +25,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_x509certificate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_subject))
+  if (CEF_MEMBER_MISSING(_struct, get_subject)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -42,8 +43,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_x509certificate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_issuer))
+  if (CEF_MEMBER_MISSING(_struct, get_issuer)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -59,8 +61,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_x509certificate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_serial_number))
+  if (CEF_MEMBER_MISSING(_struct, get_serial_number)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -71,33 +74,36 @@
   return CefBinaryValueCToCpp::Wrap(_retval);
 }
 
-NO_SANITIZE("cfi-icall") CefTime CefX509CertificateCToCpp::GetValidStart() {
+NO_SANITIZE("cfi-icall") CefBaseTime CefX509CertificateCToCpp::GetValidStart() {
   shutdown_checker::AssertNotShutdown();
 
   cef_x509certificate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_valid_start))
-    return CefTime();
+  if (CEF_MEMBER_MISSING(_struct, get_valid_start)) {
+    return CefBaseTime();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  cef_time_t _retval = _struct->get_valid_start(_struct);
+  cef_basetime_t _retval = _struct->get_valid_start(_struct);
 
   // Return type: simple
   return _retval;
 }
 
-NO_SANITIZE("cfi-icall") CefTime CefX509CertificateCToCpp::GetValidExpiry() {
+NO_SANITIZE("cfi-icall")
+CefBaseTime CefX509CertificateCToCpp::GetValidExpiry() {
   shutdown_checker::AssertNotShutdown();
 
   cef_x509certificate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_valid_expiry))
-    return CefTime();
+  if (CEF_MEMBER_MISSING(_struct, get_valid_expiry)) {
+    return CefBaseTime();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  cef_time_t _retval = _struct->get_valid_expiry(_struct);
+  cef_basetime_t _retval = _struct->get_valid_expiry(_struct);
 
   // Return type: simple
   return _retval;
@@ -108,8 +114,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_x509certificate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_derencoded))
+  if (CEF_MEMBER_MISSING(_struct, get_derencoded)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -125,8 +132,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_x509certificate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_pemencoded))
+  if (CEF_MEMBER_MISSING(_struct, get_pemencoded)) {
     return nullptr;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -141,8 +149,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_x509certificate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_issuer_chain_size))
+  if (CEF_MEMBER_MISSING(_struct, get_issuer_chain_size)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -159,8 +168,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_x509certificate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_derencoded_issuer_chain))
+  if (CEF_MEMBER_MISSING(_struct, get_derencoded_issuer_chain)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -200,8 +210,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_x509certificate_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_pemencoded_issuer_chain))
+  if (CEF_MEMBER_MISSING(_struct, get_pemencoded_issuer_chain)) {
     return;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -251,7 +262,7 @@
     CefX509Certificate,
     cef_x509certificate_t>::UnwrapDerived(CefWrapperType type,
                                           CefX509Certificate* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/x509certificate_ctocpp.h b/src/libcef_dll/ctocpp/x509certificate_ctocpp.h
index 1905ebb..721b499 100644
--- a/src/libcef_dll/ctocpp/x509certificate_ctocpp.h
+++ b/src/libcef_dll/ctocpp/x509certificate_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=76b2c3c6e5bcffc3f737f8f2ae127d9190aef91e$
+// $hash=39cb5dd7488f7035a1b52e50b48e3bffee27dba6$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_X509CERTIFICATE_CTOCPP_H_
@@ -35,16 +35,16 @@
   virtual ~CefX509CertificateCToCpp();
 
   // CefX509Certificate methods.
-  CefRefPtr<CefX509CertPrincipal> GetSubject() OVERRIDE;
-  CefRefPtr<CefX509CertPrincipal> GetIssuer() OVERRIDE;
-  CefRefPtr<CefBinaryValue> GetSerialNumber() OVERRIDE;
-  CefTime GetValidStart() OVERRIDE;
-  CefTime GetValidExpiry() OVERRIDE;
-  CefRefPtr<CefBinaryValue> GetDEREncoded() OVERRIDE;
-  CefRefPtr<CefBinaryValue> GetPEMEncoded() OVERRIDE;
-  size_t GetIssuerChainSize() OVERRIDE;
-  void GetDEREncodedIssuerChain(IssuerChainBinaryList& chain) OVERRIDE;
-  void GetPEMEncodedIssuerChain(IssuerChainBinaryList& chain) OVERRIDE;
+  CefRefPtr<CefX509CertPrincipal> GetSubject() override;
+  CefRefPtr<CefX509CertPrincipal> GetIssuer() override;
+  CefRefPtr<CefBinaryValue> GetSerialNumber() override;
+  CefBaseTime GetValidStart() override;
+  CefBaseTime GetValidExpiry() override;
+  CefRefPtr<CefBinaryValue> GetDEREncoded() override;
+  CefRefPtr<CefBinaryValue> GetPEMEncoded() override;
+  size_t GetIssuerChainSize() override;
+  void GetDEREncodedIssuerChain(IssuerChainBinaryList& chain) override;
+  void GetPEMEncodedIssuerChain(IssuerChainBinaryList& chain) override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_X509CERTIFICATE_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/xml_reader_ctocpp.cc b/src/libcef_dll/ctocpp/xml_reader_ctocpp.cc
index 83943b4..7366d79 100644
--- a/src/libcef_dll/ctocpp/xml_reader_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/xml_reader_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=480fc8b34176c75410ff4073adea11b2397e7d3e$
+// $hash=f53f587d16aeb5a66ed0cd8f5ef90a6b00833443$
 //
 
 #include "libcef_dll/ctocpp/xml_reader_ctocpp.h"
@@ -28,12 +28,14 @@
 
   // Verify param: stream; type: refptr_same
   DCHECK(stream.get());
-  if (!stream.get())
+  if (!stream.get()) {
     return nullptr;
+  }
   // Verify param: URI; type: string_byref_const
   DCHECK(!URI.empty());
-  if (URI.empty())
+  if (URI.empty()) {
     return nullptr;
+  }
 
   // Execute
   cef_xml_reader_t* _retval = cef_xml_reader_create(
@@ -49,8 +51,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, move_to_next_node))
+  if (CEF_MEMBER_MISSING(_struct, move_to_next_node)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -65,8 +68,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, close))
+  if (CEF_MEMBER_MISSING(_struct, close)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -81,8 +85,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_error))
+  if (CEF_MEMBER_MISSING(_struct, has_error)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -97,8 +102,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_error))
+  if (CEF_MEMBER_MISSING(_struct, get_error)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -115,8 +121,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_type))
+  if (CEF_MEMBER_MISSING(_struct, get_type)) {
     return XML_NODE_UNSUPPORTED;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -131,8 +138,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_depth))
+  if (CEF_MEMBER_MISSING(_struct, get_depth)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -147,8 +155,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_local_name))
+  if (CEF_MEMBER_MISSING(_struct, get_local_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -165,8 +174,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_prefix))
+  if (CEF_MEMBER_MISSING(_struct, get_prefix)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -183,8 +193,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_qualified_name))
+  if (CEF_MEMBER_MISSING(_struct, get_qualified_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -201,8 +212,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_namespace_uri))
+  if (CEF_MEMBER_MISSING(_struct, get_namespace_uri)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -219,8 +231,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_base_uri))
+  if (CEF_MEMBER_MISSING(_struct, get_base_uri)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -237,8 +250,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_xml_lang))
+  if (CEF_MEMBER_MISSING(_struct, get_xml_lang)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -255,8 +269,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, is_empty_element))
+  if (CEF_MEMBER_MISSING(_struct, is_empty_element)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -271,8 +286,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_value))
+  if (CEF_MEMBER_MISSING(_struct, has_value)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -287,8 +303,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_value))
+  if (CEF_MEMBER_MISSING(_struct, get_value)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -305,8 +322,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, has_attributes))
+  if (CEF_MEMBER_MISSING(_struct, has_attributes)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -321,8 +339,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_attribute_count))
+  if (CEF_MEMBER_MISSING(_struct, get_attribute_count)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -337,15 +356,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_attribute_byindex))
+  if (CEF_MEMBER_MISSING(_struct, get_attribute_byindex)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return CefString();
+  }
 
   // Execute
   cef_string_userfree_t _retval =
@@ -362,15 +383,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_attribute_byqname))
+  if (CEF_MEMBER_MISSING(_struct, get_attribute_byqname)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: qualifiedName; type: string_byref_const
   DCHECK(!qualifiedName.empty());
-  if (qualifiedName.empty())
+  if (qualifiedName.empty()) {
     return CefString();
+  }
 
   // Execute
   cef_string_userfree_t _retval =
@@ -388,19 +411,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_attribute_bylname))
+  if (CEF_MEMBER_MISSING(_struct, get_attribute_bylname)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: localName; type: string_byref_const
   DCHECK(!localName.empty());
-  if (localName.empty())
+  if (localName.empty()) {
     return CefString();
+  }
   // Verify param: namespaceURI; type: string_byref_const
   DCHECK(!namespaceURI.empty());
-  if (namespaceURI.empty())
+  if (namespaceURI.empty()) {
     return CefString();
+  }
 
   // Execute
   cef_string_userfree_t _retval = _struct->get_attribute_bylname(
@@ -416,8 +442,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_inner_xml))
+  if (CEF_MEMBER_MISSING(_struct, get_inner_xml)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -434,8 +461,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_outer_xml))
+  if (CEF_MEMBER_MISSING(_struct, get_outer_xml)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -452,8 +480,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_line_number))
+  if (CEF_MEMBER_MISSING(_struct, get_line_number)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -468,15 +497,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, move_to_attribute_byindex))
+  if (CEF_MEMBER_MISSING(_struct, move_to_attribute_byindex)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: index; type: simple_byval
   DCHECK_GE(index, 0);
-  if (index < 0)
+  if (index < 0) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->move_to_attribute_byindex(_struct, index);
@@ -490,15 +521,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, move_to_attribute_byqname))
+  if (CEF_MEMBER_MISSING(_struct, move_to_attribute_byqname)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: qualifiedName; type: string_byref_const
   DCHECK(!qualifiedName.empty());
-  if (qualifiedName.empty())
+  if (qualifiedName.empty()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -514,19 +547,22 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, move_to_attribute_bylname))
+  if (CEF_MEMBER_MISSING(_struct, move_to_attribute_bylname)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: localName; type: string_byref_const
   DCHECK(!localName.empty());
-  if (localName.empty())
+  if (localName.empty()) {
     return false;
+  }
   // Verify param: namespaceURI; type: string_byref_const
   DCHECK(!namespaceURI.empty());
-  if (namespaceURI.empty())
+  if (namespaceURI.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = _struct->move_to_attribute_bylname(
@@ -540,8 +576,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, move_to_first_attribute))
+  if (CEF_MEMBER_MISSING(_struct, move_to_first_attribute)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -556,8 +593,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, move_to_next_attribute))
+  if (CEF_MEMBER_MISSING(_struct, move_to_next_attribute)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -572,8 +610,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_xml_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, move_to_carrying_element))
+  if (CEF_MEMBER_MISSING(_struct, move_to_carrying_element)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -598,7 +637,7 @@
 cef_xml_reader_t*
 CefCToCppRefCounted<CefXmlReaderCToCpp, CefXmlReader, cef_xml_reader_t>::
     UnwrapDerived(CefWrapperType type, CefXmlReader* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/xml_reader_ctocpp.h b/src/libcef_dll/ctocpp/xml_reader_ctocpp.h
index 3b98826..2810186 100644
--- a/src/libcef_dll/ctocpp/xml_reader_ctocpp.h
+++ b/src/libcef_dll/ctocpp/xml_reader_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7313546898a9aecdbaf6eeda54f792c10803eb84$
+// $hash=5f87c82093a6a16e03df00673d2ff20a9f0490d5$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_XML_READER_CTOCPP_H_
@@ -34,37 +34,37 @@
   virtual ~CefXmlReaderCToCpp();
 
   // CefXmlReader methods.
-  bool MoveToNextNode() OVERRIDE;
-  bool Close() OVERRIDE;
-  bool HasError() OVERRIDE;
-  CefString GetError() OVERRIDE;
-  NodeType GetType() OVERRIDE;
-  int GetDepth() OVERRIDE;
-  CefString GetLocalName() OVERRIDE;
-  CefString GetPrefix() OVERRIDE;
-  CefString GetQualifiedName() OVERRIDE;
-  CefString GetNamespaceURI() OVERRIDE;
-  CefString GetBaseURI() OVERRIDE;
-  CefString GetXmlLang() OVERRIDE;
-  bool IsEmptyElement() OVERRIDE;
-  bool HasValue() OVERRIDE;
-  CefString GetValue() OVERRIDE;
-  bool HasAttributes() OVERRIDE;
-  size_t GetAttributeCount() OVERRIDE;
-  CefString GetAttribute(int index) OVERRIDE;
-  CefString GetAttribute(const CefString& qualifiedName) OVERRIDE;
+  bool MoveToNextNode() override;
+  bool Close() override;
+  bool HasError() override;
+  CefString GetError() override;
+  NodeType GetType() override;
+  int GetDepth() override;
+  CefString GetLocalName() override;
+  CefString GetPrefix() override;
+  CefString GetQualifiedName() override;
+  CefString GetNamespaceURI() override;
+  CefString GetBaseURI() override;
+  CefString GetXmlLang() override;
+  bool IsEmptyElement() override;
+  bool HasValue() override;
+  CefString GetValue() override;
+  bool HasAttributes() override;
+  size_t GetAttributeCount() override;
+  CefString GetAttribute(int index) override;
+  CefString GetAttribute(const CefString& qualifiedName) override;
   CefString GetAttribute(const CefString& localName,
-                         const CefString& namespaceURI) OVERRIDE;
-  CefString GetInnerXml() OVERRIDE;
-  CefString GetOuterXml() OVERRIDE;
-  int GetLineNumber() OVERRIDE;
-  bool MoveToAttribute(int index) OVERRIDE;
-  bool MoveToAttribute(const CefString& qualifiedName) OVERRIDE;
+                         const CefString& namespaceURI) override;
+  CefString GetInnerXml() override;
+  CefString GetOuterXml() override;
+  int GetLineNumber() override;
+  bool MoveToAttribute(int index) override;
+  bool MoveToAttribute(const CefString& qualifiedName) override;
   bool MoveToAttribute(const CefString& localName,
-                       const CefString& namespaceURI) OVERRIDE;
-  bool MoveToFirstAttribute() OVERRIDE;
-  bool MoveToNextAttribute() OVERRIDE;
-  bool MoveToCarryingElement() OVERRIDE;
+                       const CefString& namespaceURI) override;
+  bool MoveToFirstAttribute() override;
+  bool MoveToNextAttribute() override;
+  bool MoveToCarryingElement() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_XML_READER_CTOCPP_H_
diff --git a/src/libcef_dll/ctocpp/zip_reader_ctocpp.cc b/src/libcef_dll/ctocpp/zip_reader_ctocpp.cc
index c46f7a6..4e39ef7 100644
--- a/src/libcef_dll/ctocpp/zip_reader_ctocpp.cc
+++ b/src/libcef_dll/ctocpp/zip_reader_ctocpp.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=078dbecccef4097257adf7962e33168411375928$
+// $hash=d1ddb1f38bfc28dec90884ee9cfc9e5e79583a4e$
 //
 
 #include "libcef_dll/ctocpp/zip_reader_ctocpp.h"
@@ -27,8 +27,9 @@
 
   // Verify param: stream; type: refptr_same
   DCHECK(stream.get());
-  if (!stream.get())
+  if (!stream.get()) {
     return nullptr;
+  }
 
   // Execute
   cef_zip_reader_t* _retval =
@@ -44,8 +45,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_zip_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, move_to_first_file))
+  if (CEF_MEMBER_MISSING(_struct, move_to_first_file)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -60,8 +62,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_zip_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, move_to_next_file))
+  if (CEF_MEMBER_MISSING(_struct, move_to_next_file)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -78,15 +81,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_zip_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, move_to_file))
+  if (CEF_MEMBER_MISSING(_struct, move_to_file)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: fileName; type: string_byref_const
   DCHECK(!fileName.empty());
-  if (fileName.empty())
+  if (fileName.empty()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -100,8 +105,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_zip_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, close))
+  if (CEF_MEMBER_MISSING(_struct, close)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -116,8 +122,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_zip_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_file_name))
+  if (CEF_MEMBER_MISSING(_struct, get_file_name)) {
     return CefString();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -130,33 +137,35 @@
   return _retvalStr;
 }
 
-NO_SANITIZE("cfi-icall") int64 CefZipReaderCToCpp::GetFileSize() {
+NO_SANITIZE("cfi-icall") int64_t CefZipReaderCToCpp::GetFileSize() {
   shutdown_checker::AssertNotShutdown();
 
   cef_zip_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_file_size))
+  if (CEF_MEMBER_MISSING(_struct, get_file_size)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int64 _retval = _struct->get_file_size(_struct);
+  int64_t _retval = _struct->get_file_size(_struct);
 
   // Return type: simple
   return _retval;
 }
 
-NO_SANITIZE("cfi-icall") CefTime CefZipReaderCToCpp::GetFileLastModified() {
+NO_SANITIZE("cfi-icall") CefBaseTime CefZipReaderCToCpp::GetFileLastModified() {
   shutdown_checker::AssertNotShutdown();
 
   cef_zip_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, get_file_last_modified))
-    return CefTime();
+  if (CEF_MEMBER_MISSING(_struct, get_file_last_modified)) {
+    return CefBaseTime();
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  cef_time_t _retval = _struct->get_file_last_modified(_struct);
+  cef_basetime_t _retval = _struct->get_file_last_modified(_struct);
 
   // Return type: simple
   return _retval;
@@ -167,8 +176,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_zip_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, open_file))
+  if (CEF_MEMBER_MISSING(_struct, open_file)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -185,8 +195,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_zip_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, close_file))
+  if (CEF_MEMBER_MISSING(_struct, close_file)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -202,15 +213,17 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_zip_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, read_file))
+  if (CEF_MEMBER_MISSING(_struct, read_file)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: buffer; type: simple_byaddr
   DCHECK(buffer);
-  if (!buffer)
+  if (!buffer) {
     return 0;
+  }
 
   // Execute
   int _retval = _struct->read_file(_struct, buffer, bufferSize);
@@ -219,17 +232,18 @@
   return _retval;
 }
 
-NO_SANITIZE("cfi-icall") int64 CefZipReaderCToCpp::Tell() {
+NO_SANITIZE("cfi-icall") int64_t CefZipReaderCToCpp::Tell() {
   shutdown_checker::AssertNotShutdown();
 
   cef_zip_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, tell))
+  if (CEF_MEMBER_MISSING(_struct, tell)) {
     return 0;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int64 _retval = _struct->tell(_struct);
+  int64_t _retval = _struct->tell(_struct);
 
   // Return type: simple
   return _retval;
@@ -239,8 +253,9 @@
   shutdown_checker::AssertNotShutdown();
 
   cef_zip_reader_t* _struct = GetStruct();
-  if (CEF_MEMBER_MISSING(_struct, eof))
+  if (CEF_MEMBER_MISSING(_struct, eof)) {
     return false;
+  }
 
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -265,7 +280,7 @@
 cef_zip_reader_t*
 CefCToCppRefCounted<CefZipReaderCToCpp, CefZipReader, cef_zip_reader_t>::
     UnwrapDerived(CefWrapperType type, CefZipReader* c) {
-  NOTREACHED() << "Unexpected class type: " << type;
+  DCHECK(false) << "Unexpected class type: " << type;
   return nullptr;
 }
 
diff --git a/src/libcef_dll/ctocpp/zip_reader_ctocpp.h b/src/libcef_dll/ctocpp/zip_reader_ctocpp.h
index f960387..4f5265d 100644
--- a/src/libcef_dll/ctocpp/zip_reader_ctocpp.h
+++ b/src/libcef_dll/ctocpp/zip_reader_ctocpp.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=a2db9b88080c167747d75e9c5a68c0757d077861$
+// $hash=78a547d4bdefaadebcaefda5fed81dfe0e0124cb$
 //
 
 #ifndef CEF_LIBCEF_DLL_CTOCPP_ZIP_READER_CTOCPP_H_
@@ -34,18 +34,18 @@
   virtual ~CefZipReaderCToCpp();
 
   // CefZipReader methods.
-  bool MoveToFirstFile() OVERRIDE;
-  bool MoveToNextFile() OVERRIDE;
-  bool MoveToFile(const CefString& fileName, bool caseSensitive) OVERRIDE;
-  bool Close() OVERRIDE;
-  CefString GetFileName() OVERRIDE;
-  int64 GetFileSize() OVERRIDE;
-  CefTime GetFileLastModified() OVERRIDE;
-  bool OpenFile(const CefString& password) OVERRIDE;
-  bool CloseFile() OVERRIDE;
-  int ReadFile(void* buffer, size_t bufferSize) OVERRIDE;
-  int64 Tell() OVERRIDE;
-  bool Eof() OVERRIDE;
+  bool MoveToFirstFile() override;
+  bool MoveToNextFile() override;
+  bool MoveToFile(const CefString& fileName, bool caseSensitive) override;
+  bool Close() override;
+  CefString GetFileName() override;
+  int64_t GetFileSize() override;
+  CefBaseTime GetFileLastModified() override;
+  bool OpenFile(const CefString& password) override;
+  bool CloseFile() override;
+  int ReadFile(void* buffer, size_t bufferSize) override;
+  int64_t Tell() override;
+  bool Eof() override;
 };
 
 #endif  // CEF_LIBCEF_DLL_CTOCPP_ZIP_READER_CTOCPP_H_
diff --git a/src/libcef_dll/libcef_dll.cc b/src/libcef_dll/libcef_dll.cc
index 90df59a..b51439b 100644
--- a/src/libcef_dll/libcef_dll.cc
+++ b/src/libcef_dll/libcef_dll.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,12 +9,13 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=c42cd0225d8e4286df471fcc622f9bbf9ed977d3$
+// $hash=9d44fae857002c47910b25efb8e471ed453d2b55$
 //
 
 #include "include/capi/cef_app_capi.h"
 #include "include/capi/cef_crash_util_capi.h"
 #include "include/capi/cef_file_util_capi.h"
+#include "include/capi/cef_i18n_util_capi.h"
 #include "include/capi/cef_origin_whitelist_capi.h"
 #include "include/capi/cef_parser_capi.h"
 #include "include/capi/cef_path_util_capi.h"
@@ -24,11 +25,11 @@
 #include "include/capi/cef_task_capi.h"
 #include "include/capi/cef_trace_capi.h"
 #include "include/capi/cef_v8_capi.h"
-#include "include/capi/cef_web_plugin_capi.h"
 #include "include/capi/test/cef_test_helpers_capi.h"
 #include "include/cef_app.h"
 #include "include/cef_crash_util.h"
 #include "include/cef_file_util.h"
+#include "include/cef_i18n_util.h"
 #include "include/cef_origin_whitelist.h"
 #include "include/cef_parser.h"
 #include "include/cef_path_util.h"
@@ -38,7 +39,6 @@
 #include "include/cef_task.h"
 #include "include/cef_trace.h"
 #include "include/cef_v8.h"
-#include "include/cef_web_plugin.h"
 #include "include/test/cef_test_helpers.h"
 #include "libcef_dll/cpptoc/binary_value_cpptoc.h"
 #include "libcef_dll/cpptoc/command_line_cpptoc.h"
@@ -47,69 +47,71 @@
 #include "libcef_dll/ctocpp/app_ctocpp.h"
 #include "libcef_dll/ctocpp/completion_callback_ctocpp.h"
 #include "libcef_dll/ctocpp/end_tracing_callback_ctocpp.h"
-#include "libcef_dll/ctocpp/register_cdm_callback_ctocpp.h"
 #include "libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h"
 #include "libcef_dll/ctocpp/task_ctocpp.h"
 #include "libcef_dll/ctocpp/v8handler_ctocpp.h"
-#include "libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.h"
-#include "libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.h"
 #include "libcef_dll/shutdown_checker.h"
+#include "libcef_dll/template_util.h"
 #include "libcef_dll/transfer_util.h"
 
 // GLOBAL FUNCTIONS - Body may be edited by hand.
 
-CEF_EXPORT int cef_execute_process(const struct _cef_main_args_t* args,
+CEF_EXPORT int cef_execute_process(const cef_main_args_t* args,
                                    struct _cef_app_t* application,
                                    void* windows_sandbox_info) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
-  // Verify param: args; type: struct_byref_const
+  // Verify param: args; type: simple_byref_const
   DCHECK(args);
-  if (!args)
+  if (!args) {
     return 0;
+  }
   // Unverified params: application, windows_sandbox_info
 
-  // Translate param: args; type: struct_byref_const
-  CefMainArgs argsObj;
-  if (args)
-    argsObj.Set(*args, false);
+  // Translate param: args; type: simple_byref_const
+  CefMainArgs argsVal = args ? *args : CefMainArgs();
 
   // Execute
-  int _retval = CefExecuteProcess(argsObj, CefAppCToCpp::Wrap(application),
+  int _retval = CefExecuteProcess(argsVal, CefAppCToCpp::Wrap(application),
                                   windows_sandbox_info);
 
   // Return type: simple
   return _retval;
 }
 
-CEF_EXPORT int cef_initialize(const struct _cef_main_args_t* args,
+CEF_EXPORT int cef_initialize(const cef_main_args_t* args,
                               const struct _cef_settings_t* settings,
                               struct _cef_app_t* application,
                               void* windows_sandbox_info) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
-  // Verify param: args; type: struct_byref_const
+  // Verify param: args; type: simple_byref_const
   DCHECK(args);
-  if (!args)
+  if (!args) {
     return 0;
+  }
   // Verify param: settings; type: struct_byref_const
   DCHECK(settings);
-  if (!settings)
+  if (!settings) {
     return 0;
+  }
+  if (!template_util::has_valid_size(settings)) {
+    DCHECK(false) << "invalid settings->[base.]size";
+    return 0;
+  }
   // Unverified params: application, windows_sandbox_info
 
-  // Translate param: args; type: struct_byref_const
-  CefMainArgs argsObj;
-  if (args)
-    argsObj.Set(*args, false);
+  // Translate param: args; type: simple_byref_const
+  CefMainArgs argsVal = args ? *args : CefMainArgs();
   // Translate param: settings; type: struct_byref_const
   CefSettings settingsObj;
-  if (settings)
+  if (settings) {
     settingsObj.Set(*settings, false);
+  }
 
   // Execute
   bool _retval =
-      CefInitialize(argsObj, settingsObj, CefAppCToCpp::Wrap(application),
+      CefInitialize(argsVal, settingsObj, CefAppCToCpp::Wrap(application),
                     windows_sandbox_info);
 
   // Return type: bool
@@ -148,20 +150,6 @@
   CefQuitMessageLoop();
 }
 
-CEF_EXPORT void cef_set_osmodal_loop(int osModalLoop) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  CefSetOSModalLoop(osModalLoop ? true : false);
-}
-
-CEF_EXPORT void cef_enable_highdpi_support() {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  CefEnableHighDPISupport();
-}
-
 CEF_EXPORT int cef_crash_reporting_enabled() {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -178,8 +166,9 @@
 
   // Verify param: key; type: string_byref_const
   DCHECK(key);
-  if (!key)
+  if (!key) {
     return;
+  }
   // Unverified params: value
 
   // Execute
@@ -191,8 +180,9 @@
 
   // Verify param: full_path; type: string_byref_const
   DCHECK(full_path);
-  if (!full_path)
+  if (!full_path) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefCreateDirectory(CefString(full_path));
@@ -206,8 +196,9 @@
 
   // Verify param: temp_dir; type: string_byref
   DCHECK(temp_dir);
-  if (!temp_dir)
+  if (!temp_dir) {
     return 0;
+  }
 
   // Translate param: temp_dir; type: string_byref
   CefString temp_dirStr(temp_dir);
@@ -225,8 +216,9 @@
 
   // Verify param: new_temp_path; type: string_byref
   DCHECK(new_temp_path);
-  if (!new_temp_path)
+  if (!new_temp_path) {
     return 0;
+  }
   // Unverified params: prefix
 
   // Translate param: new_temp_path; type: string_byref
@@ -247,12 +239,14 @@
 
   // Verify param: base_dir; type: string_byref_const
   DCHECK(base_dir);
-  if (!base_dir)
+  if (!base_dir) {
     return 0;
+  }
   // Verify param: new_dir; type: string_byref
   DCHECK(new_dir);
-  if (!new_dir)
+  if (!new_dir) {
     return 0;
+  }
   // Unverified params: prefix
 
   // Translate param: new_dir; type: string_byref
@@ -271,8 +265,9 @@
 
   // Verify param: path; type: string_byref_const
   DCHECK(path);
-  if (!path)
+  if (!path) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDirectoryExists(CefString(path));
@@ -286,8 +281,9 @@
 
   // Verify param: path; type: string_byref_const
   DCHECK(path);
-  if (!path)
+  if (!path) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefDeleteFile(CefString(path), recursive ? true : false);
@@ -303,12 +299,14 @@
 
   // Verify param: src_dir; type: string_byref_const
   DCHECK(src_dir);
-  if (!src_dir)
+  if (!src_dir) {
     return 0;
+  }
   // Verify param: dest_file; type: string_byref_const
   DCHECK(dest_file);
-  if (!dest_file)
+  if (!dest_file) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefZipDirectory(CefString(src_dir), CefString(dest_file),
@@ -323,13 +321,24 @@
 
   // Verify param: path; type: string_byref_const
   DCHECK(path);
-  if (!path)
+  if (!path) {
     return;
+  }
 
   // Execute
   CefLoadCRLSetsFile(CefString(path));
 }
 
+CEF_EXPORT int cef_is_rtl() {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  bool _retval = CefIsRTL();
+
+  // Return type: bool
+  return _retval;
+}
+
 CEF_EXPORT int cef_add_cross_origin_whitelist_entry(
     const cef_string_t* source_origin,
     const cef_string_t* target_protocol,
@@ -339,12 +348,14 @@
 
   // Verify param: source_origin; type: string_byref_const
   DCHECK(source_origin);
-  if (!source_origin)
+  if (!source_origin) {
     return 0;
+  }
   // Verify param: target_protocol; type: string_byref_const
   DCHECK(target_protocol);
-  if (!target_protocol)
+  if (!target_protocol) {
     return 0;
+  }
   // Unverified params: target_domain
 
   // Execute
@@ -365,12 +376,14 @@
 
   // Verify param: source_origin; type: string_byref_const
   DCHECK(source_origin);
-  if (!source_origin)
+  if (!source_origin) {
     return 0;
+  }
   // Verify param: target_protocol; type: string_byref_const
   DCHECK(target_protocol);
-  if (!target_protocol)
+  if (!target_protocol) {
     return 0;
+  }
   // Unverified params: target_domain
 
   // Execute
@@ -392,30 +405,70 @@
   return _retval;
 }
 
+CEF_EXPORT int cef_resolve_url(const cef_string_t* base_url,
+                               const cef_string_t* relative_url,
+                               cef_string_t* resolved_url) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: base_url; type: string_byref_const
+  DCHECK(base_url);
+  if (!base_url) {
+    return 0;
+  }
+  // Verify param: relative_url; type: string_byref_const
+  DCHECK(relative_url);
+  if (!relative_url) {
+    return 0;
+  }
+  // Verify param: resolved_url; type: string_byref
+  DCHECK(resolved_url);
+  if (!resolved_url) {
+    return 0;
+  }
+
+  // Translate param: resolved_url; type: string_byref
+  CefString resolved_urlStr(resolved_url);
+
+  // Execute
+  bool _retval = CefResolveURL(CefString(base_url), CefString(relative_url),
+                               resolved_urlStr);
+
+  // Return type: bool
+  return _retval;
+}
+
 CEF_EXPORT int cef_parse_url(const cef_string_t* url,
                              struct _cef_urlparts_t* parts) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: url; type: string_byref_const
   DCHECK(url);
-  if (!url)
+  if (!url) {
     return 0;
+  }
   // Verify param: parts; type: struct_byref
   DCHECK(parts);
-  if (!parts)
+  if (!parts) {
     return 0;
+  }
+  if (!template_util::has_valid_size(parts)) {
+    DCHECK(false) << "invalid parts->[base.]size";
+    return 0;
+  }
 
   // Translate param: parts; type: struct_byref
   CefURLParts partsObj;
-  if (parts)
+  if (parts) {
     partsObj.AttachTo(*parts);
+  }
 
   // Execute
   bool _retval = CefParseURL(CefString(url), partsObj);
 
   // Restore param: parts; type: struct_byref
-  if (parts)
+  if (parts) {
     partsObj.DetachTo(*parts);
+  }
 
   // Return type: bool
   return _retval;
@@ -427,17 +480,24 @@
 
   // Verify param: parts; type: struct_byref_const
   DCHECK(parts);
-  if (!parts)
+  if (!parts) {
     return 0;
+  }
+  if (!template_util::has_valid_size(parts)) {
+    DCHECK(false) << "invalid parts->[base.]size";
+    return 0;
+  }
   // Verify param: url; type: string_byref
   DCHECK(url);
-  if (!url)
+  if (!url) {
     return 0;
+  }
 
   // Translate param: parts; type: struct_byref_const
   CefURLParts partsObj;
-  if (parts)
+  if (parts) {
     partsObj.Set(*parts, false);
+  }
   // Translate param: url; type: string_byref
   CefString urlStr(url);
 
@@ -454,8 +514,9 @@
 
   // Verify param: origin_url; type: string_byref_const
   DCHECK(origin_url);
-  if (!origin_url)
+  if (!origin_url) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefFormatUrlForSecurityDisplay(CefString(origin_url));
@@ -470,8 +531,9 @@
 
   // Verify param: extension; type: string_byref_const
   DCHECK(extension);
-  if (!extension)
+  if (!extension) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefGetMimeType(CefString(extension));
@@ -486,12 +548,14 @@
 
   // Verify param: mime_type; type: string_byref_const
   DCHECK(mime_type);
-  if (!mime_type)
+  if (!mime_type) {
     return;
+  }
   // Verify param: extensions; type: string_vec_byref
   DCHECK(extensions);
-  if (!extensions)
+  if (!extensions) {
     return;
+  }
 
   // Translate param: extensions; type: string_vec_byref
   std::vector<CefString> extensionsList;
@@ -511,8 +575,9 @@
 
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefBase64Encode(data, data_size);
@@ -527,8 +592,9 @@
 
   // Verify param: data; type: string_byref_const
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefBinaryValue> _retval = CefBase64Decode(CefString(data));
@@ -543,8 +609,9 @@
 
   // Verify param: text; type: string_byref_const
   DCHECK(text);
-  if (!text)
+  if (!text) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefURIEncode(CefString(text), use_plus ? true : false);
@@ -561,8 +628,9 @@
 
   // Verify param: text; type: string_byref_const
   DCHECK(text);
-  if (!text)
+  if (!text) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefURIDecode(
@@ -579,8 +647,9 @@
 
   // Verify param: json_string; type: string_byref_const
   DCHECK(json_string);
-  if (!json_string)
+  if (!json_string) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefValue> _retval = CefParseJSON(CefString(json_string), options);
@@ -597,8 +666,9 @@
 
   // Verify param: json; type: simple_byaddr
   DCHECK(json);
-  if (!json)
+  if (!json) {
     return NULL;
+  }
 
   // Execute
   CefRefPtr<CefValue> _retval = CefParseJSON(json, json_size, options);
@@ -610,36 +680,26 @@
 CEF_EXPORT struct _cef_value_t* cef_parse_jsonand_return_error(
     const cef_string_t* json_string,
     cef_json_parser_options_t options,
-    cef_json_parser_error_t* error_code_out,
     cef_string_t* error_msg_out) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: json_string; type: string_byref_const
   DCHECK(json_string);
-  if (!json_string)
+  if (!json_string) {
     return NULL;
-  // Verify param: error_code_out; type: simple_byref
-  DCHECK(error_code_out);
-  if (!error_code_out)
-    return NULL;
+  }
   // Verify param: error_msg_out; type: string_byref
   DCHECK(error_msg_out);
-  if (!error_msg_out)
+  if (!error_msg_out) {
     return NULL;
+  }
 
-  // Translate param: error_code_out; type: simple_byref
-  cef_json_parser_error_t error_code_outVal =
-      error_code_out ? *error_code_out : JSON_NO_ERROR;
   // Translate param: error_msg_out; type: string_byref
   CefString error_msg_outStr(error_msg_out);
 
   // Execute
   CefRefPtr<CefValue> _retval = CefParseJSONAndReturnError(
-      CefString(json_string), options, error_code_outVal, error_msg_outStr);
-
-  // Restore param: error_code_out; type: simple_byref
-  if (error_code_out)
-    *error_code_out = error_code_outVal;
+      CefString(json_string), options, error_msg_outStr);
 
   // Return type: refptr_same
   return CefValueCppToC::Wrap(_retval);
@@ -651,8 +711,9 @@
 
   // Verify param: node; type: refptr_same
   DCHECK(node);
-  if (!node)
+  if (!node) {
     return NULL;
+  }
 
   // Execute
   CefString _retval = CefWriteJSON(CefValueCppToC::Unwrap(node), options);
@@ -666,8 +727,9 @@
 
   // Verify param: path; type: string_byref
   DCHECK(path);
-  if (!path)
+  if (!path) {
     return 0;
+  }
 
   // Translate param: path; type: string_byref
   CefString pathStr(path);
@@ -684,8 +746,9 @@
 
   // Verify param: command_line; type: refptr_same
   DCHECK(command_line);
-  if (!command_line)
+  if (!command_line) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefLaunchProcess(CefCommandLineCppToC::Unwrap(command_line));
@@ -702,8 +765,9 @@
 
   // Verify param: scheme_name; type: string_byref_const
   DCHECK(scheme_name);
-  if (!scheme_name)
+  if (!scheme_name) {
     return 0;
+  }
   // Unverified params: domain_name, factory
 
   // Execute
@@ -751,8 +815,9 @@
 
   // Verify param: task; type: refptr_diff
   DCHECK(task);
-  if (!task)
+  if (!task) {
     return 0;
+  }
 
   // Execute
   bool _retval = CefPostTask(threadId, CefTaskCToCpp::Wrap(task));
@@ -763,13 +828,14 @@
 
 CEF_EXPORT int cef_post_delayed_task(cef_thread_id_t threadId,
                                      struct _cef_task_t* task,
-                                     int64 delay_ms) {
+                                     int64_t delay_ms) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: task; type: refptr_diff
   DCHECK(task);
-  if (!task)
+  if (!task) {
     return 0;
+  }
 
   // Execute
   bool _retval =
@@ -807,11 +873,11 @@
   return _retval;
 }
 
-CEF_EXPORT int64 cef_now_from_system_trace_time() {
+CEF_EXPORT int64_t cef_now_from_system_trace_time() {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int64 _retval = CefNowFromSystemTraceTime();
+  int64_t _retval = CefNowFromSystemTraceTime();
 
   // Return type: simple
   return _retval;
@@ -824,12 +890,14 @@
 
   // Verify param: extension_name; type: string_byref_const
   DCHECK(extension_name);
-  if (!extension_name)
+  if (!extension_name) {
     return 0;
+  }
   // Verify param: javascript_code; type: string_byref_const
   DCHECK(javascript_code);
-  if (!javascript_code)
+  if (!javascript_code) {
     return 0;
+  }
   // Unverified params: handler
 
   // Execute
@@ -841,85 +909,6 @@
   return _retval;
 }
 
-CEF_EXPORT void cef_visit_web_plugin_info(
-    struct _cef_web_plugin_info_visitor_t* visitor) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: visitor; type: refptr_diff
-  DCHECK(visitor);
-  if (!visitor)
-    return;
-
-  // Execute
-  CefVisitWebPluginInfo(CefWebPluginInfoVisitorCToCpp::Wrap(visitor));
-}
-
-CEF_EXPORT void cef_refresh_web_plugins() {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  CefRefreshWebPlugins();
-}
-
-CEF_EXPORT void cef_unregister_internal_web_plugin(const cef_string_t* path) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: path; type: string_byref_const
-  DCHECK(path);
-  if (!path)
-    return;
-
-  // Execute
-  CefUnregisterInternalWebPlugin(CefString(path));
-}
-
-CEF_EXPORT void cef_register_web_plugin_crash(const cef_string_t* path) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: path; type: string_byref_const
-  DCHECK(path);
-  if (!path)
-    return;
-
-  // Execute
-  CefRegisterWebPluginCrash(CefString(path));
-}
-
-CEF_EXPORT void cef_is_web_plugin_unstable(
-    const cef_string_t* path,
-    struct _cef_web_plugin_unstable_callback_t* callback) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: path; type: string_byref_const
-  DCHECK(path);
-  if (!path)
-    return;
-  // Verify param: callback; type: refptr_diff
-  DCHECK(callback);
-  if (!callback)
-    return;
-
-  // Execute
-  CefIsWebPluginUnstable(CefString(path),
-                         CefWebPluginUnstableCallbackCToCpp::Wrap(callback));
-}
-
-CEF_EXPORT void cef_register_widevine_cdm(
-    const cef_string_t* path,
-    struct _cef_register_cdm_callback_t* callback) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: path; type: string_byref_const
-  DCHECK(path);
-  if (!path)
-    return;
-  // Unverified params: callback
-
-  // Execute
-  CefRegisterWidevineCdm(CefString(path),
-                         CefRegisterCdmCallbackCToCpp::Wrap(callback));
-}
-
 CEF_EXPORT void cef_execute_java_script_with_user_gesture_for_tests(
     struct _cef_frame_t* frame,
     const cef_string_t* javascript) {
@@ -927,11 +916,25 @@
 
   // Verify param: frame; type: refptr_same
   DCHECK(frame);
-  if (!frame)
+  if (!frame) {
     return;
+  }
   // Unverified params: javascript
 
   // Execute
   CefExecuteJavaScriptWithUserGestureForTests(CefFrameCppToC::Unwrap(frame),
                                               CefString(javascript));
 }
+
+CEF_EXPORT void cef_set_data_directory_for_tests(const cef_string_t* dir) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: dir; type: string_byref_const
+  DCHECK(dir);
+  if (!dir) {
+    return;
+  }
+
+  // Execute
+  CefSetDataDirectoryForTests(CefString(dir));
+}
diff --git a/src/libcef_dll/libcef_dll2.cc b/src/libcef_dll/libcef_dll2.cc
index a240a1d..94ecd77 100644
--- a/src/libcef_dll/libcef_dll2.cc
+++ b/src/libcef_dll/libcef_dll2.cc
@@ -4,9 +4,15 @@
 //
 
 #include <cstddef>
+
+#include "include/base/cef_build.h"
 #include "include/cef_api_hash.h"
 #include "include/cef_version.h"
 
+#if defined(OS_WIN)
+#include "include/internal/cef_win.h"
+#endif
+
 CEF_EXPORT int cef_version_info(int entry) {
   switch (entry) {
     case 0:
@@ -42,3 +48,27 @@
       return NULL;
   }
 }
+
+#if defined(OS_WIN)
+
+#if defined(ARCH_CPU_32_BITS)
+CEF_EXPORT int cef_run_winmain_with_preferred_stack_size(wWinMainPtr wWinMain,
+                                                         HINSTANCE hInstance,
+                                                         LPWSTR lpCmdLine,
+                                                         int nCmdShow) {
+  return CefRunWinMainWithPreferredStackSize(wWinMain, hInstance, lpCmdLine,
+                                             nCmdShow);
+}
+
+CEF_EXPORT int cef_run_main_with_preferred_stack_size(mainPtr main,
+                                                      int argc,
+                                                      char* argv[]) {
+  return CefRunMainWithPreferredStackSize(main, argc, argv);
+}
+#endif  // defined(ARCH_CPU_32_BITS)
+
+CEF_EXPORT void cef_set_osmodal_loop(int osModalLoop) {
+  CefSetOSModalLoop(osModalLoop ? true : false);
+}
+
+#endif  // defined(OS_WIN)
diff --git a/src/libcef_dll/ptr_util.h b/src/libcef_dll/ptr_util.h
deleted file mode 100644
index 9692322..0000000
--- a/src/libcef_dll/ptr_util.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2017 The Chromium Embedded Framework 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 CEF_LIBCEF_DLL_PTR_UTIL_H_
-#define CEF_LIBCEF_DLL_PTR_UTIL_H_
-#pragma once
-
-// Helpers for CefOwnPtr<>.
-#if defined(USING_CHROMIUM_INCLUDES)
-#define OWN_PASS(p) std::move(p)
-#define OWN_RETURN_AS(p, t) (p)
-#else
-#define OWN_PASS(p) (p).Pass()
-#define OWN_RETURN_AS(p, t) (p).PassAs<t>()
-#endif
-
-#endif  // CEF_LIBCEF_DLL_PTR_UTIL_H_
diff --git a/src/libcef_dll/sandbox/sandbox_mac.mm b/src/libcef_dll/sandbox/sandbox_mac.mm
index cfdcae7..f3afaff 100644
--- a/src/libcef_dll/sandbox/sandbox_mac.mm
+++ b/src/libcef_dll/sandbox/sandbox_mac.mm
@@ -58,8 +58,9 @@
 }
 
 bool CefScopedSandboxContext::Initialize(int argc, char** argv) {
-  if (sandbox_context_)
+  if (sandbox_context_) {
     return false;
+  }
   sandbox_context_ = cef_sandbox_initialize(argc, argv);
   return !!sandbox_context_;
 }
diff --git a/src/libcef_dll/sandbox/sandbox_win.cc b/src/libcef_dll/sandbox/sandbox_win.cc
index f8cdcc9..52ef04e 100644
--- a/src/libcef_dll/sandbox/sandbox_win.cc
+++ b/src/libcef_dll/sandbox/sandbox_win.cc
@@ -2,26 +2,28 @@
 // 2011 the Chromium Authors. All rights reserved. Use of this source code is
 // governed by a BSD-style license that can be found in the LICENSE file.
 
-#include "sandbox/win/src/process_mitigations.h"
+#include "base/notreached.h"
+#include "sandbox/win/src/sandbox.h"
 #include "sandbox/win/src/sandbox_factory.h"
 
+#include "cef/libcef/features/features.h"
 #include "include/cef_sandbox_win.h"
 
 namespace {
 
-// From content/app/startup_helper_win.cc:
+// From content/app/sandbox_helper_win.cc:
 void InitializeSandboxInfo(sandbox::SandboxInterfaceInfo* info) {
   info->broker_services = sandbox::SandboxFactory::GetBrokerServices();
-  if (!info->broker_services) {
-    info->target_services = sandbox::SandboxFactory::GetTargetServices();
-  } else {
+  if (info->broker_services) {
     // Ensure the proper mitigations are enforced for the browser process.
-    sandbox::ApplyProcessMitigationsToCurrentProcess(
+    info->broker_services->RatchetDownSecurityMitigations(
         sandbox::MITIGATION_DEP | sandbox::MITIGATION_DEP_NO_ATL_THUNK |
         sandbox::MITIGATION_HARDEN_TOKEN_IL_POLICY);
     // Note: these mitigations are "post-startup".  Some mitigations that need
     // to be enabled sooner (e.g. MITIGATION_EXTENSION_POINT_DISABLE) are done
     // so in Chrome_ELF.
+  } else {
+    info->target_services = sandbox::SandboxFactory::GetTargetServices();
   }
 }
 
@@ -37,3 +39,19 @@
 void cef_sandbox_info_destroy(void* sandbox_info) {
   delete static_cast<sandbox::SandboxInterfaceInfo*>(sandbox_info);
 }
+
+#if BUILDFLAG(IS_CEF_SANDBOX_BUILD)
+
+// Avoid bringing in partition_alloc dependencies.
+namespace partition_alloc {
+bool ReleaseReservation() {
+  DCHECK(false);
+  return false;
+}
+
+void TerminateBecauseOutOfMemory(size_t size) {
+  DCHECK(false);
+}
+}  // namespace partition_alloc
+
+#endif  // BUILDFLAG(IS_CEF_SANDBOX_BUILD)
diff --git a/src/libcef_dll/shutdown_checker.cc b/src/libcef_dll/shutdown_checker.cc
index f369d03..e5646a7 100644
--- a/src/libcef_dll/shutdown_checker.cc
+++ b/src/libcef_dll/shutdown_checker.cc
@@ -4,13 +4,7 @@
 
 #include "libcef_dll/shutdown_checker.h"
 
-// For compatibility with older client compiler versions only use std::atomic
-// on the library side.
-#if defined(BUILDING_CEF_SHARED)
 #include <atomic>
-#else
-#include "include/base/cef_atomic_ref_count.h"
-#endif
 
 #include "include/base/cef_logging.h"
 
@@ -20,8 +14,6 @@
 
 namespace {
 
-#if defined(BUILDING_CEF_SHARED)
-
 std::atomic_bool g_cef_shutdown{false};
 
 bool IsCefShutdown() {
@@ -32,20 +24,6 @@
   g_cef_shutdown.store(true);
 }
 
-#else  // !defined(BUILDING_CEF_SHARED)
-
-base::AtomicRefCount g_cef_shutdown ATOMIC_DECLARATION;
-
-bool IsCefShutdown() {
-  return !base::AtomicRefCountIsZero(&g_cef_shutdown);
-}
-
-void SetCefShutdown() {
-  base::AtomicRefCountInc(&g_cef_shutdown);
-}
-
-#endif  // !defined(BUILDING_CEF_SHARED)
-
 }  // namespace
 
 void AssertNotShutdown() {
diff --git a/src/libcef_dll/template_util.h b/src/libcef_dll/template_util.h
new file mode 100644
index 0000000..4749f2c
--- /dev/null
+++ b/src/libcef_dll/template_util.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_DLL_TEMPLATE_UTIL_H_
+#define CEF_LIBCEF_DLL_TEMPLATE_UTIL_H_
+#pragma once
+
+#include <type_traits>
+
+namespace template_util {
+
+// Used to detect whether the given C struct has a size_t size field or has a
+// base field and a base field has a size field.
+template <typename T, typename = void>
+struct HasValidSize {
+  bool operator()(const T*) { return true; }
+};
+template <typename T>
+struct HasValidSize<
+    T,
+    typename std::enable_if_t<std::is_same<decltype(T::size), size_t>::value>> {
+  bool operator()(const T* s) { return s->size == sizeof(*s); }
+};
+template <typename T>
+struct HasValidSize<T, decltype(void(T::base.size))> {
+  bool operator()(const T* s) { return s->base.size == sizeof(*s); }
+};
+
+template <typename T>
+inline bool has_valid_size(const T* s) {
+  return HasValidSize<T>()(s);
+}
+
+}  // namespace template_util
+
+#endif  // CEF_LIBCEF_DLL_TEMPLATE_UTIL_H_
diff --git a/src/libcef_dll/transfer_util.cc b/src/libcef_dll/transfer_util.cc
index eb6a79c..47ad135 100644
--- a/src/libcef_dll/transfer_util.cc
+++ b/src/libcef_dll/transfer_util.cc
@@ -18,8 +18,9 @@
 void transfer_string_list_contents(const StringList& fromList,
                                    cef_string_list_t toList) {
   size_t size = fromList.size();
-  for (size_t i = 0; i < size; ++i)
+  for (size_t i = 0; i < size; ++i) {
     cef_string_list_append(toList, fromList[i].GetStruct());
+  }
 }
 
 void transfer_string_map_contents(cef_string_map_t fromMap, StringMap& toMap) {
@@ -37,8 +38,9 @@
 void transfer_string_map_contents(const StringMap& fromMap,
                                   cef_string_map_t toMap) {
   StringMap::const_iterator it = fromMap.begin();
-  for (; it != fromMap.end(); ++it)
+  for (; it != fromMap.end(); ++it) {
     cef_string_map_append(toMap, it->first.GetStruct(), it->second.GetStruct());
+  }
 }
 
 void transfer_string_multimap_contents(cef_string_multimap_t fromMap,
diff --git a/src/libcef_dll/transfer_util.h b/src/libcef_dll/transfer_util.h
index f2c3e81..6da9ae1 100644
--- a/src/libcef_dll/transfer_util.h
+++ b/src/libcef_dll/transfer_util.h
@@ -14,20 +14,20 @@
 #include "include/internal/cef_string_multimap.h"
 
 // Copy contents from one list type to another.
-typedef std::vector<CefString> StringList;
+using StringList = std::vector<CefString>;
 void transfer_string_list_contents(cef_string_list_t fromList,
                                    StringList& toList);
 void transfer_string_list_contents(const StringList& fromList,
                                    cef_string_list_t toList);
 
 // Copy contents from one map type to another.
-typedef std::map<CefString, CefString> StringMap;
+using StringMap = std::map<CefString, CefString>;
 void transfer_string_map_contents(cef_string_map_t fromMap, StringMap& toMap);
 void transfer_string_map_contents(const StringMap& fromMap,
                                   cef_string_map_t toMap);
 
 // Copy contents from one map type to another.
-typedef std::multimap<CefString, CefString> StringMultimap;
+using StringMultimap = std::multimap<CefString, CefString>;
 void transfer_string_multimap_contents(cef_string_multimap_t fromMap,
                                        StringMultimap& toMap);
 void transfer_string_multimap_contents(const StringMultimap& fromMap,
diff --git a/src/libcef_dll/views_stub.cc b/src/libcef_dll/views_stub.cc
deleted file mode 100644
index f78b3b6..0000000
--- a/src/libcef_dll/views_stub.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
-// reserved. Use of this source code is governed by a BSD-style license that
-// can be found in the LICENSE file.
-//
-// ---------------------------------------------------------------------------
-//
-// This file was generated by the CEF translator tool. If making changes by
-// hand only do so within the body of existing method and function
-// implementations. See the translator.README.txt file in the tools directory
-// for more information.
-//
-// $hash=c5439c177bd70bf3d8d52e0381c08d6276453183$
-//
-
-#include "base/logging.h"
-#include "include/views/cef_browser_view.h"
-#include "include/views/cef_display.h"
-#include "include/views/cef_label_button.h"
-#include "include/views/cef_menu_button.h"
-#include "include/views/cef_panel.h"
-#include "include/views/cef_scroll_view.h"
-#include "include/views/cef_textfield.h"
-#include "include/views/cef_window.h"
-
-// STATIC STUB METHODS - Do not edit by hand.
-
-NO_SANITIZE("cfi-icall")
-CefRefPtr<CefBrowserView> CefBrowserView::CreateBrowserView(
-    CefRefPtr<CefClient> client,
-    const CefString& url,
-    const CefBrowserSettings& settings,
-    CefRefPtr<CefDictionaryValue> extra_info,
-    CefRefPtr<CefRequestContext> request_context,
-    CefRefPtr<CefBrowserViewDelegate> delegate) {
-  NOTIMPLEMENTED();
-  return nullptr;
-}
-
-NO_SANITIZE("cfi-icall")
-CefRefPtr<CefBrowserView> CefBrowserView::GetForBrowser(
-    CefRefPtr<CefBrowser> browser) {
-  NOTIMPLEMENTED();
-  return nullptr;
-}
-
-NO_SANITIZE("cfi-icall") CefRefPtr<CefDisplay> CefDisplay::GetPrimaryDisplay() {
-  NOTIMPLEMENTED();
-  return nullptr;
-}
-
-NO_SANITIZE("cfi-icall")
-CefRefPtr<CefDisplay> CefDisplay::GetDisplayNearestPoint(
-    const CefPoint& point,
-    bool input_pixel_coords) {
-  NOTIMPLEMENTED();
-  return nullptr;
-}
-
-NO_SANITIZE("cfi-icall")
-CefRefPtr<CefDisplay> CefDisplay::GetDisplayMatchingBounds(
-    const CefRect& bounds,
-    bool input_pixel_coords) {
-  NOTIMPLEMENTED();
-  return nullptr;
-}
-
-NO_SANITIZE("cfi-icall") size_t CefDisplay::GetDisplayCount() {
-  NOTIMPLEMENTED();
-  return 0;
-}
-
-NO_SANITIZE("cfi-icall")
-void CefDisplay::GetAllDisplays(std::vector<CefRefPtr<CefDisplay>>& displays) {
-  NOTIMPLEMENTED();
-}
-
-NO_SANITIZE("cfi-icall")
-CefRefPtr<CefLabelButton> CefLabelButton::CreateLabelButton(
-    CefRefPtr<CefButtonDelegate> delegate,
-    const CefString& text) {
-  NOTIMPLEMENTED();
-  return nullptr;
-}
-
-NO_SANITIZE("cfi-icall")
-CefRefPtr<CefMenuButton> CefMenuButton::CreateMenuButton(
-    CefRefPtr<CefMenuButtonDelegate> delegate,
-    const CefString& text) {
-  NOTIMPLEMENTED();
-  return nullptr;
-}
-
-NO_SANITIZE("cfi-icall")
-CefRefPtr<CefPanel> CefPanel::CreatePanel(
-    CefRefPtr<CefPanelDelegate> delegate) {
-  NOTIMPLEMENTED();
-  return nullptr;
-}
-
-NO_SANITIZE("cfi-icall")
-CefRefPtr<CefScrollView> CefScrollView::CreateScrollView(
-    CefRefPtr<CefViewDelegate> delegate) {
-  NOTIMPLEMENTED();
-  return nullptr;
-}
-
-NO_SANITIZE("cfi-icall")
-CefRefPtr<CefTextfield> CefTextfield::CreateTextfield(
-    CefRefPtr<CefTextfieldDelegate> delegate) {
-  NOTIMPLEMENTED();
-  return nullptr;
-}
-
-NO_SANITIZE("cfi-icall")
-CefRefPtr<CefWindow> CefWindow::CreateTopLevelWindow(
-    CefRefPtr<CefWindowDelegate> delegate) {
-  NOTIMPLEMENTED();
-  return nullptr;
-}
diff --git a/src/libcef_dll/wrapper/cef_browser_info_map.h b/src/libcef_dll/wrapper/cef_browser_info_map.h
index f62c307..24459ce 100644
--- a/src/libcef_dll/wrapper/cef_browser_info_map.h
+++ b/src/libcef_dll/wrapper/cef_browser_info_map.h
@@ -9,7 +9,6 @@
 #include <map>
 
 #include "include/base/cef_logging.h"
-#include "include/base/cef_macros.h"
 
 // Default traits for CefBrowserInfoMap. Override to provide different object
 // destruction behavior.
@@ -27,8 +26,8 @@
   // Implement this interface to visit and optionally delete objects in the map.
   class Visitor {
    public:
-    typedef IdType InfoIdType;
-    typedef ObjectType InfoObjectType;
+    using InfoIdType = IdType;
+    using InfoObjectType = ObjectType;
 
     // Called once for each info object. Set |remove| to true to remove the
     // object from the map. It is safe to destruct removed objects in this
@@ -42,7 +41,10 @@
     virtual ~Visitor() {}
   };
 
-  CefBrowserInfoMap() {}
+  CefBrowserInfoMap() = default;
+
+  CefBrowserInfoMap(const CefBrowserInfoMap&) = delete;
+  CefBrowserInfoMap& operator=(const CefBrowserInfoMap&) = delete;
 
   ~CefBrowserInfoMap() { clear(); }
 
@@ -68,24 +70,28 @@
   // used to evaluate or remove the object at the same time. If the object is
   // removed using the Visitor the caller is responsible for destroying it.
   ObjectType Find(int browser_id, IdType info_id, Visitor* vistor) {
-    if (browser_info_map_.empty())
+    if (browser_info_map_.empty()) {
       return ObjectType();
+    }
 
     typename BrowserInfoMap::iterator it_browser =
         browser_info_map_.find(browser_id);
-    if (it_browser == browser_info_map_.end())
+    if (it_browser == browser_info_map_.end()) {
       return ObjectType();
+    }
 
     InfoMap* info_map = it_browser->second;
     typename InfoMap::iterator it_info = info_map->find(info_id);
-    if (it_info == info_map->end())
+    if (it_info == info_map->end()) {
       return ObjectType();
+    }
 
     ObjectType info = it_info->second;
 
     bool remove = false;
-    if (vistor)
+    if (vistor) {
       vistor->OnNextInfo(browser_id, it_info->first, info, &remove);
+    }
     if (remove) {
       info_map->erase(it_info);
 
@@ -104,8 +110,9 @@
   void FindAll(Visitor* visitor) {
     DCHECK(visitor);
 
-    if (browser_info_map_.empty())
+    if (browser_info_map_.empty()) {
       return;
+    }
 
     bool remove, keepgoing = true;
 
@@ -119,13 +126,15 @@
         keepgoing = visitor->OnNextInfo(it_browser->first, it_info->first,
                                         it_info->second, &remove);
 
-        if (remove)
+        if (remove) {
           info_map->erase(it_info++);
-        else
+        } else {
           ++it_info;
+        }
 
-        if (!keepgoing)
+        if (!keepgoing) {
           break;
+        }
       }
 
       if (info_map->empty()) {
@@ -136,8 +145,9 @@
         ++it_browser;
       }
 
-      if (!keepgoing)
+      if (!keepgoing) {
         break;
+      }
     }
   }
 
@@ -146,13 +156,15 @@
   void FindAll(int browser_id, Visitor* visitor) {
     DCHECK(visitor);
 
-    if (browser_info_map_.empty())
+    if (browser_info_map_.empty()) {
       return;
+    }
 
     typename BrowserInfoMap::iterator it_browser =
         browser_info_map_.find(browser_id);
-    if (it_browser == browser_info_map_.end())
+    if (it_browser == browser_info_map_.end()) {
       return;
+    }
 
     InfoMap* info_map = it_browser->second;
     bool remove, keepgoing;
@@ -163,13 +175,15 @@
       keepgoing = visitor->OnNextInfo(browser_id, it_info->first,
                                       it_info->second, &remove);
 
-      if (remove)
+      if (remove) {
         info_map->erase(it_info++);
-      else
+      } else {
         ++it_info;
+      }
 
-      if (!keepgoing)
+      if (!keepgoing) {
         break;
+      }
     }
 
     if (info_map->empty()) {
@@ -184,43 +198,49 @@
 
   // Returns the number of objects in the map.
   size_t size() const {
-    if (browser_info_map_.empty())
+    if (browser_info_map_.empty()) {
       return 0;
+    }
 
     size_t size = 0;
     typename BrowserInfoMap::const_iterator it_browser =
         browser_info_map_.begin();
-    for (; it_browser != browser_info_map_.end(); ++it_browser)
+    for (; it_browser != browser_info_map_.end(); ++it_browser) {
       size += it_browser->second->size();
+    }
     return size;
   }
 
   // Returns the number of objects in the map that are associated with the
   // specified browser.
   size_t size(int browser_id) const {
-    if (browser_info_map_.empty())
+    if (browser_info_map_.empty()) {
       return 0;
+    }
 
     typename BrowserInfoMap::const_iterator it_browser =
         browser_info_map_.find(browser_id);
-    if (it_browser != browser_info_map_.end())
+    if (it_browser != browser_info_map_.end()) {
       return it_browser->second->size();
+    }
 
     return 0;
   }
 
   // Remove all objects from the map. The objects will be destructed.
   void clear() {
-    if (browser_info_map_.empty())
+    if (browser_info_map_.empty()) {
       return;
+    }
 
     typename BrowserInfoMap::const_iterator it_browser =
         browser_info_map_.begin();
     for (; it_browser != browser_info_map_.end(); ++it_browser) {
       InfoMap* info_map = it_browser->second;
       typename InfoMap::const_iterator it_info = info_map->begin();
-      for (; it_info != info_map->end(); ++it_info)
+      for (; it_info != info_map->end(); ++it_info) {
         Traits::Destruct(it_info->second);
+      }
       delete info_map;
     }
     browser_info_map_.clear();
@@ -229,18 +249,21 @@
   // Remove all objects from the map that are associated with the specified
   // browser. The objects will be destructed.
   void clear(int browser_id) {
-    if (browser_info_map_.empty())
+    if (browser_info_map_.empty()) {
       return;
+    }
 
     typename BrowserInfoMap::iterator it_browser =
         browser_info_map_.find(browser_id);
-    if (it_browser == browser_info_map_.end())
+    if (it_browser == browser_info_map_.end()) {
       return;
+    }
 
     InfoMap* info_map = it_browser->second;
     typename InfoMap::const_iterator it_info = info_map->begin();
-    for (; it_info != info_map->end(); ++it_info)
+    for (; it_info != info_map->end(); ++it_info) {
       Traits::Destruct(it_info->second);
+    }
 
     browser_info_map_.erase(it_browser);
     delete info_map;
@@ -248,13 +271,11 @@
 
  private:
   // Map IdType to ObjectType instance.
-  typedef std::map<IdType, ObjectType> InfoMap;
+  using InfoMap = std::map<IdType, ObjectType>;
   // Map browser ID to InfoMap instance.
-  typedef std::map<int, InfoMap*> BrowserInfoMap;
+  using BrowserInfoMap = std::map<int, InfoMap*>;
 
   BrowserInfoMap browser_info_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefBrowserInfoMap);
 };
 
 #endif  // CEF_LIBCEF_DLL_WRAPPER_CEF_BROWSER_INFO_MAP_H_
diff --git a/src/libcef_dll/wrapper/cef_byte_read_handler.cc b/src/libcef_dll/wrapper/cef_byte_read_handler.cc
index dbb5181..a420b44 100644
--- a/src/libcef_dll/wrapper/cef_byte_read_handler.cc
+++ b/src/libcef_dll/wrapper/cef_byte_read_handler.cc
@@ -22,31 +22,34 @@
   return ret;
 }
 
-int CefByteReadHandler::Seek(int64 offset, int whence) {
+int CefByteReadHandler::Seek(int64_t offset, int whence) {
   int rv = -1L;
   base::AutoLock lock_scope(lock_);
   switch (whence) {
     case SEEK_CUR:
-      if (offset_ + offset > size_ || offset_ + offset < 0)
+      if (offset_ + offset > size_ || offset_ + offset < 0) {
         break;
+      }
       offset_ += offset;
       rv = 0;
       break;
     case SEEK_END: {
 #if defined(OS_WIN)
-      int64 offset_abs = _abs64(offset);
+      int64_t offset_abs = _abs64(offset);
 #else
-      int64 offset_abs = std::abs(offset);
+      int64_t offset_abs = std::abs(offset);
 #endif
-      if (offset_abs > size_)
+      if (offset_abs > size_) {
         break;
+      }
       offset_ = size_ - offset_abs;
       rv = 0;
       break;
     }
     case SEEK_SET:
-      if (offset > size_ || offset < 0)
+      if (offset > size_ || offset < 0) {
         break;
+      }
       offset_ = offset;
       rv = 0;
       break;
@@ -55,7 +58,7 @@
   return rv;
 }
 
-int64 CefByteReadHandler::Tell() {
+int64_t CefByteReadHandler::Tell() {
   base::AutoLock lock_scope(lock_);
   return offset_;
 }
diff --git a/src/libcef_dll/wrapper/cef_closure_task.cc b/src/libcef_dll/wrapper/cef_closure_task.cc
index 0fc7fec..860ef08 100644
--- a/src/libcef_dll/wrapper/cef_closure_task.cc
+++ b/src/libcef_dll/wrapper/cef_closure_task.cc
@@ -3,39 +3,78 @@
 // can be found in the LICENSE file.
 
 #include "include/wrapper/cef_closure_task.h"
+
+#include <memory>
+
 #include "include/base/cef_callback.h"
 
 namespace {
 
-class CefClosureTask : public CefTask {
+class CefOnceClosureTask : public CefTask {
  public:
-  explicit CefClosureTask(const base::Closure& closure) : closure_(closure) {}
+  explicit CefOnceClosureTask(base::OnceClosure closure)
+      : closure_(std::move(closure)) {}
+
+  CefOnceClosureTask(const CefOnceClosureTask&) = delete;
+  CefOnceClosureTask& operator=(const CefOnceClosureTask&) = delete;
 
   // CefTask method
-  virtual void Execute() OVERRIDE {
+  void Execute() override { std::move(closure_).Run(); }
+
+ private:
+  base::OnceClosure closure_;
+
+  IMPLEMENT_REFCOUNTING(CefOnceClosureTask);
+};
+
+class CefRepeatingClosureTask : public CefTask {
+ public:
+  explicit CefRepeatingClosureTask(const base::RepeatingClosure& closure)
+      : closure_(closure) {}
+
+  CefRepeatingClosureTask(const CefRepeatingClosureTask&) = delete;
+  CefRepeatingClosureTask& operator=(const CefRepeatingClosureTask&) = delete;
+
+  // CefTask method
+  void Execute() override {
     closure_.Run();
     closure_.Reset();
   }
 
  private:
-  base::Closure closure_;
+  base::RepeatingClosure closure_;
 
-  IMPLEMENT_REFCOUNTING(CefClosureTask);
-  DISALLOW_COPY_AND_ASSIGN(CefClosureTask);
+  IMPLEMENT_REFCOUNTING(CefRepeatingClosureTask);
 };
 
 }  // namespace
 
-CefRefPtr<CefTask> CefCreateClosureTask(const base::Closure& closure) {
-  return new CefClosureTask(closure);
+CefRefPtr<CefTask> CefCreateClosureTask(base::OnceClosure closure) {
+  return new CefOnceClosureTask(std::move(closure));
 }
 
-bool CefPostTask(CefThreadId threadId, const base::Closure& closure) {
-  return CefPostTask(threadId, new CefClosureTask(closure));
+CefRefPtr<CefTask> CefCreateClosureTask(const base::RepeatingClosure& closure) {
+  return new CefRepeatingClosureTask(closure);
+}
+
+bool CefPostTask(CefThreadId threadId, base::OnceClosure closure) {
+  return CefPostTask(threadId, new CefOnceClosureTask(std::move(closure)));
+}
+
+bool CefPostTask(CefThreadId threadId, const base::RepeatingClosure& closure) {
+  return CefPostTask(threadId, new CefRepeatingClosureTask(closure));
 }
 
 bool CefPostDelayedTask(CefThreadId threadId,
-                        const base::Closure& closure,
-                        int64 delay_ms) {
-  return CefPostDelayedTask(threadId, new CefClosureTask(closure), delay_ms);
+                        base::OnceClosure closure,
+                        int64_t delay_ms) {
+  return CefPostDelayedTask(
+      threadId, new CefOnceClosureTask(std::move(closure)), delay_ms);
+}
+
+bool CefPostDelayedTask(CefThreadId threadId,
+                        const base::RepeatingClosure& closure,
+                        int64_t delay_ms) {
+  return CefPostDelayedTask(threadId, new CefRepeatingClosureTask(closure),
+                            delay_ms);
 }
diff --git a/src/libcef_dll/wrapper/cef_message_router.cc b/src/libcef_dll/wrapper/cef_message_router.cc
index d521280..787fcf4 100644
--- a/src/libcef_dll/wrapper/cef_message_router.cc
+++ b/src/libcef_dll/wrapper/cef_message_router.cc
@@ -4,15 +4,16 @@
 
 #include "include/wrapper/cef_message_router.h"
 
+#include <limits>
 #include <map>
 #include <set>
 
-#include "include/base/cef_bind.h"
-#include "include/base/cef_macros.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_task.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "include/wrapper/cef_helpers.h"
 #include "libcef_dll/wrapper/cef_browser_info_map.h"
+#include "libcef_dll/wrapper/cef_message_router_utils.h"
 
 namespace {
 
@@ -32,6 +33,10 @@
 const int kCanceledErrorCode = -1;
 const char kCanceledErrorMessage[] = "The query has been canceled";
 
+// Value of 16KB is chosen as a result of performance tests available at
+// http://tests/ipc_performance
+constexpr size_t kResponseSizeThreshold = 16384;
+
 // Validate configuration settings.
 bool ValidateConfig(CefMessageRouterConfig& config) {
   // Must specify function names.
@@ -42,23 +47,33 @@
   return true;
 }
 
-// Helper template for generated ID values.
+namespace cmru = cef_message_router_utils;
+
+/**
+ * @brief A helper template for generating ID values.
+ *
+ * This class generates monotonically increasing ID values within the interval
+ * [kReservedId + 1, numeric_limits<T>::max()].
+ *
+ * @tparam T The data type for the ID values.
+ */
 template <typename T>
 class IdGenerator {
  public:
   IdGenerator() : next_id_(kReservedId) {}
 
+  IdGenerator(const IdGenerator&) = delete;
+  IdGenerator& operator=(const IdGenerator&) = delete;
+
   T GetNextId() {
-    T id = ++next_id_;
-    if (id == kReservedId)  // In case the integer value wraps.
-      id = ++next_id_;
-    return id;
+    if (next_id_ == std::numeric_limits<T>::max()) {
+      next_id_ = kReservedId;
+    }
+    return ++next_id_;
   }
 
  private:
   T next_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(IdGenerator);
 };
 
 // Browser-side router implementation.
@@ -69,12 +84,20 @@
    public:
     CallbackImpl(CefRefPtr<CefMessageRouterBrowserSideImpl> router,
                  int browser_id,
-                 int64 query_id,
-                 bool persistent)
+                 int64_t query_id,
+                 bool persistent,
+                 size_t message_size_threshold,
+                 const std::string& query_message_name)
         : router_(router),
           browser_id_(browser_id),
           query_id_(query_id),
-          persistent_(persistent) {}
+          persistent_(persistent),
+          message_size_threshold_(message_size_threshold),
+          query_message_name_(query_message_name) {}
+
+    CallbackImpl(const CallbackImpl&) = delete;
+    CallbackImpl& operator=(const CallbackImpl&) = delete;
+
     virtual ~CallbackImpl() {
       // Hitting this DCHECK means that you didn't call Success or Failure
       // on the Callback after returning true from Handler::OnQuery. You must
@@ -82,44 +105,37 @@
       DCHECK(!router_);
     }
 
-    void Success(const CefString& response) OVERRIDE {
-      if (!CefCurrentlyOn(TID_UI)) {
-        // Must execute on the UI thread to access member variables.
-        CefPostTask(TID_UI, base::Bind(&CallbackImpl::Success, this, response));
-        return;
-      }
+    void Success(const CefString& response) override {
+      auto builder = cmru::CreateBrowserResponseBuilder(
+          message_size_threshold_, query_message_name_, response);
 
-      if (router_) {
-        CefPostTask(
-            TID_UI,
-            base::Bind(&CefMessageRouterBrowserSideImpl::OnCallbackSuccess,
-                       router_.get(), browser_id_, query_id_, response));
-
-        if (!persistent_) {
-          // Non-persistent callbacks are only good for a single use.
-          router_ = nullptr;
-        }
-      }
+      // We need to post task here for two reasons:
+      // 1) To safely access member variables.
+      // 2) To let the router to persist the query information before
+      // the Success callback is executed.
+      CefPostTask(TID_UI,
+                  base::BindOnce(&CallbackImpl::SuccessImpl, this, builder));
     }
 
-    void Failure(int error_code, const CefString& error_message) OVERRIDE {
-      if (!CefCurrentlyOn(TID_UI)) {
-        // Must execute on the UI thread to access member variables.
-        CefPostTask(TID_UI, base::Bind(&CallbackImpl::Failure, this, error_code,
-                                       error_message));
-        return;
-      }
+    void Success(const void* data, size_t size) override {
+      auto builder = cmru::CreateBrowserResponseBuilder(
+          message_size_threshold_, query_message_name_, data, size);
 
-      if (router_) {
-        CefPostTask(
-            TID_UI,
-            base::Bind(&CefMessageRouterBrowserSideImpl::OnCallbackFailure,
-                       router_.get(), browser_id_, query_id_, error_code,
-                       error_message));
+      // We need to post task here for two reasons:
+      // 1) To safely access member variables.
+      // 2) To let the router to persist the query information before
+      // the Success callback is executed.
+      CefPostTask(TID_UI,
+                  base::BindOnce(&CallbackImpl::SuccessImpl, this, builder));
+    }
 
-        // Failure always invalidates the callback.
-        router_ = nullptr;
-      }
+    void Failure(int error_code, const CefString& error_message) override {
+      // We need to post task here for two reasons:
+      // 1) To safely access member variables.
+      // 2) To give previosly submitted tasks by the Success calls to execute
+      // before we invalidate the callback.
+      CefPostTask(TID_UI, base::BindOnce(&CallbackImpl::FailureImpl, this,
+                                         error_code, error_message));
     }
 
     void Detach() {
@@ -128,10 +144,37 @@
     }
 
    private:
+    void SuccessImpl(const CefRefPtr<cmru::BrowserResponseBuilder>& builder) {
+      if (!router_) {
+        return;
+      }
+
+      router_->OnCallbackSuccess(browser_id_, query_id_, builder);
+
+      if (!persistent_) {
+        // Non-persistent callbacks are only good for a single use.
+        router_ = nullptr;
+      }
+    }
+
+    void FailureImpl(int error_code, const CefString& error_message) {
+      if (!router_) {
+        return;
+      }
+
+      router_->OnCallbackFailure(browser_id_, query_id_, error_code,
+                                 error_message);
+
+      // Failure always invalidates the callback.
+      router_ = nullptr;
+    }
+
     CefRefPtr<CefMessageRouterBrowserSideImpl> router_;
     const int browser_id_;
-    const int64 query_id_;
+    const int64_t query_id_;
     const bool persistent_;
+    const size_t message_size_threshold_;
+    const std::string query_message_name_;
 
     IMPLEMENT_REFCOUNTING(CallbackImpl);
   };
@@ -143,12 +186,17 @@
         cancel_message_name_(config.js_cancel_function.ToString() +
                              kMessageSuffix) {}
 
+  CefMessageRouterBrowserSideImpl(const CefMessageRouterBrowserSideImpl&) =
+      delete;
+  CefMessageRouterBrowserSideImpl& operator=(
+      const CefMessageRouterBrowserSideImpl&) = delete;
+
   virtual ~CefMessageRouterBrowserSideImpl() {
     // There should be no pending queries when the router is deleted.
     DCHECK(browser_query_info_map_.empty());
   }
 
-  bool AddHandler(Handler* handler, bool first) OVERRIDE {
+  bool AddHandler(Handler* handler, bool first) override {
     CEF_REQUIRE_UI_THREAD();
     if (handler_set_.find(handler) == handler_set_.end()) {
       handler_set_.insert(first ? handler_set_.begin() : handler_set_.end(),
@@ -158,7 +206,7 @@
     return false;
   }
 
-  bool RemoveHandler(Handler* handler) OVERRIDE {
+  bool RemoveHandler(Handler* handler) override {
     CEF_REQUIRE_UI_THREAD();
     if (handler_set_.erase(handler) > 0) {
       CancelPendingFor(nullptr, handler, true);
@@ -167,16 +215,17 @@
     return false;
   }
 
-  void CancelPending(CefRefPtr<CefBrowser> browser, Handler* handler) OVERRIDE {
+  void CancelPending(CefRefPtr<CefBrowser> browser, Handler* handler) override {
     CancelPendingFor(browser, handler, true);
   }
 
   int GetPendingCount(CefRefPtr<CefBrowser> browser,
-                      Handler* handler) OVERRIDE {
+                      Handler* handler) override {
     CEF_REQUIRE_UI_THREAD();
 
-    if (browser_query_info_map_.empty())
+    if (browser_query_info_map_.empty()) {
       return 0;
+    }
 
     if (handler) {
       // Need to iterate over each QueryInfo object to test the handler.
@@ -187,9 +236,10 @@
         bool OnNextInfo(int browser_id,
                         InfoIdType info_id,
                         InfoObjectType info,
-                        bool* remove) OVERRIDE {
-          if (info->handler == handler_)
+                        bool* remove) override {
+          if (info->handler == handler_) {
             count_++;
+          }
           return true;
         }
 
@@ -214,42 +264,38 @@
     } else if (browser.get()) {
       return static_cast<int>(
           browser_query_info_map_.size(browser->GetIdentifier()));
-    } else {
-      return static_cast<int>(browser_query_info_map_.size());
     }
 
-    return 0;
+    return static_cast<int>(browser_query_info_map_.size());
   }
 
-  void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE {
+  void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
     CancelPendingFor(browser, nullptr, false);
   }
 
-  void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser) OVERRIDE {
+  void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser) override {
     CancelPendingFor(browser, nullptr, false);
   }
 
   void OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
-                      CefRefPtr<CefFrame> frame) OVERRIDE {
-    if (frame->IsMain())
+                      CefRefPtr<CefFrame> frame) override {
+    if (frame->IsMain()) {
       CancelPendingFor(browser, nullptr, false);
+    }
   }
 
   bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
                                 CefRefPtr<CefFrame> frame,
                                 CefProcessId source_process,
-                                CefRefPtr<CefProcessMessage> message) OVERRIDE {
+                                CefRefPtr<CefProcessMessage> message) override {
     CEF_REQUIRE_UI_THREAD();
 
     const std::string& message_name = message->GetName();
     if (message_name == query_message_name_) {
-      CefRefPtr<CefListValue> args = message->GetArgumentList();
-      DCHECK_EQ(args->GetSize(), 4U);
-
-      const int context_id = args->GetInt(0);
-      const int request_id = args->GetInt(1);
-      const CefString& request = args->GetString(2);
-      const bool persistent = args->GetBool(3);
+      cmru::RendererMessage content = cmru::ParseRendererMessage(message);
+      const int context_id = content.context_id;
+      const int request_id = content.request_id;
+      const bool persistent = content.is_persistent;
 
       if (handler_set_.empty()) {
         // No handlers so cancel the query.
@@ -258,41 +304,40 @@
       }
 
       const int browser_id = browser->GetIdentifier();
-      const int64 query_id = query_id_generator_.GetNextId();
+      const int64_t query_id = query_id_generator_.GetNextId();
 
-      CefRefPtr<CallbackImpl> callback(
-          new CallbackImpl(this, browser_id, query_id, persistent));
+      CefRefPtr<CallbackImpl> callback =
+          new CallbackImpl(this, browser_id, query_id, persistent,
+                           config_.message_size_threshold, query_message_name_);
 
       // Make a copy of the handler list in case the user adds or removes a
       // handler while we're iterating.
-      HandlerSet handler_set = handler_set_;
+      const HandlerSet handlers = handler_set_;
 
-      bool handled = false;
-      HandlerSet::const_iterator it_handler = handler_set.begin();
-      for (; it_handler != handler_set.end(); ++it_handler) {
-        handled = (*it_handler)
-                      ->OnQuery(browser, frame, query_id, request, persistent,
-                                callback.get());
-        if (handled)
-          break;
-      }
+      Handler* handler = std::visit(
+          [&](const auto& arg) -> CefMessageRouterBrowserSide::Handler* {
+            for (auto handler : handlers) {
+              bool handled = handler->OnQuery(browser, frame, query_id, arg,
+                                              persistent, callback.get());
+              if (handled) {
+                return handler;
+              }
+            }
+            return nullptr;
+          },
+          content.payload);
 
       // If the query isn't handled nothing should be keeping a reference to
       // the callback.
-      DCHECK(handled || callback->HasOneRef());
+      DCHECK(handler != nullptr || callback->HasOneRef());
 
-      if (handled) {
+      if (handler) {
         // Persist the query information until the callback executes.
         // It's safe to do this here because the callback will execute
         // asynchronously.
-        QueryInfo* info = new QueryInfo;
-        info->browser = browser;
-        info->frame = frame;
-        info->context_id = context_id;
-        info->request_id = request_id;
-        info->persistent = persistent;
-        info->callback = callback;
-        info->handler = *(it_handler);
+        QueryInfo* info =
+            new QueryInfo{browser,    frame,    context_id, request_id,
+                          persistent, callback, handler};
         browser_query_info_map_.Add(browser_id, query_id, info);
       } else {
         // Invalidate the callback.
@@ -348,7 +393,7 @@
   // if the query is non-persistent. If |removed| is true the caller is
   // responsible for deleting the returned QueryInfo object.
   QueryInfo* GetQueryInfo(int browser_id,
-                          int64 query_id,
+                          int64_t query_id,
                           bool always_remove,
                           bool* removed) {
     class Visitor : public BrowserQueryInfoMap::Visitor {
@@ -359,7 +404,7 @@
       bool OnNextInfo(int browser_id,
                       InfoIdType info_id,
                       InfoObjectType info,
-                      bool* remove) OVERRIDE {
+                      bool* remove) override {
         *remove = removed_ = (always_remove_ || !info->persistent);
         return true;
       }
@@ -374,29 +419,33 @@
     Visitor visitor(always_remove);
     QueryInfo* info =
         browser_query_info_map_.Find(browser_id, query_id, &visitor);
-    if (info)
+    if (info) {
       *removed = visitor.removed();
+    }
     return info;
   }
 
   // Called by CallbackImpl on success.
-  void OnCallbackSuccess(int browser_id,
-                         int64 query_id,
-                         const CefString& response) {
+  void OnCallbackSuccess(
+      int browser_id,
+      int64_t query_id,
+      const CefRefPtr<cmru::BrowserResponseBuilder>& builder) {
     CEF_REQUIRE_UI_THREAD();
 
     bool removed;
     QueryInfo* info = GetQueryInfo(browser_id, query_id, false, &removed);
     if (info) {
-      SendQuerySuccess(info, response);
-      if (removed)
+      SendQuerySuccess(info->browser, info->frame, info->context_id,
+                       info->request_id, builder);
+      if (removed) {
         delete info;
+      }
     }
   }
 
   // Called by CallbackImpl on failure.
   void OnCallbackFailure(int browser_id,
-                         int64 query_id,
+                         int64_t query_id,
                          int error_code,
                          const CefString& error_message) {
     CEF_REQUIRE_UI_THREAD();
@@ -410,24 +459,15 @@
     }
   }
 
-  void SendQuerySuccess(QueryInfo* info, const CefString& response) {
-    SendQuerySuccess(info->browser, info->frame, info->context_id,
-                     info->request_id, response);
-  }
-
-  void SendQuerySuccess(CefRefPtr<CefBrowser> browser,
-                        CefRefPtr<CefFrame> frame,
-                        int context_id,
-                        int request_id,
-                        const CefString& response) {
-    CefRefPtr<CefProcessMessage> message =
-        CefProcessMessage::Create(query_message_name_);
-    CefRefPtr<CefListValue> args = message->GetArgumentList();
-    args->SetInt(0, context_id);
-    args->SetInt(1, request_id);
-    args->SetBool(2, true);  // Indicates a success result.
-    args->SetString(3, response);
-    frame->SendProcessMessage(PID_RENDERER, message);
+  void SendQuerySuccess(
+      CefRefPtr<CefBrowser> browser,
+      CefRefPtr<CefFrame> frame,
+      int context_id,
+      int request_id,
+      const CefRefPtr<cmru::BrowserResponseBuilder>& builder) {
+    if (auto message = builder->Build(context_id, request_id)) {
+      frame->SendProcessMessage(PID_RENDERER, message);
+    }
   }
 
   void SendQueryFailure(QueryInfo* info,
@@ -464,9 +504,10 @@
   }
 
   // Cancel a query that has already been sent to a handler.
-  void CancelQuery(int64 query_id, QueryInfo* info, bool notify_renderer) {
-    if (notify_renderer)
+  void CancelQuery(int64_t query_id, QueryInfo* info, bool notify_renderer) {
+    if (notify_renderer) {
       SendQueryFailure(info, kCanceledErrorCode, kCanceledErrorMessage);
+    }
 
     info->handler->OnQueryCanceled(info->browser, info->frame, query_id);
 
@@ -482,14 +523,16 @@
                         bool notify_renderer) {
     if (!CefCurrentlyOn(TID_UI)) {
       // Must execute on the UI thread.
-      CefPostTask(TID_UI,
-                  base::Bind(&CefMessageRouterBrowserSideImpl::CancelPendingFor,
-                             this, browser, handler, notify_renderer));
+      CefPostTask(
+          TID_UI,
+          base::BindOnce(&CefMessageRouterBrowserSideImpl::CancelPendingFor,
+                         this, browser, handler, notify_renderer));
       return;
     }
 
-    if (browser_query_info_map_.empty())
+    if (browser_query_info_map_.empty()) {
       return;
+    }
 
     class Visitor : public BrowserQueryInfoMap::Visitor {
      public:
@@ -503,7 +546,7 @@
       bool OnNextInfo(int browser_id,
                       InfoIdType info_id,
                       InfoObjectType info,
-                      bool* remove) OVERRIDE {
+                      bool* remove) override {
         if (!handler_ || info->handler == handler_) {
           *remove = true;
           router_->CancelQuery(info_id, info, notify_renderer_);
@@ -542,7 +585,7 @@
       bool OnNextInfo(int browser_id,
                       InfoIdType info_id,
                       InfoObjectType info,
-                      bool* remove) OVERRIDE {
+                      bool* remove) override {
         if (info->context_id == context_id_ &&
             (request_id_ == kReservedId || info->request_id == request_id_)) {
           *remove = true;
@@ -569,21 +612,19 @@
   const std::string query_message_name_;
   const std::string cancel_message_name_;
 
-  IdGenerator<int64> query_id_generator_;
+  IdGenerator<int64_t> query_id_generator_;
 
   // Set of currently registered handlers. An entry is added when a handler is
   // registered and removed when a handler is unregistered.
-  typedef std::set<Handler*> HandlerSet;
+  using HandlerSet = std::set<Handler*>;
   HandlerSet handler_set_;
 
   // Map of query ID to QueryInfo instance. An entry is added when a Handler
   // indicates that it will handle the query and removed when either the query
   // is completed via the Callback, the query is explicitly canceled from the
   // renderer process, or the associated context is (or will be) released.
-  typedef CefBrowserInfoMap<int64, QueryInfo*> BrowserQueryInfoMap;
+  using BrowserQueryInfoMap = CefBrowserInfoMap<int64_t, QueryInfo*>;
   BrowserQueryInfoMap browser_query_info_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefMessageRouterBrowserSideImpl);
 };
 
 // Renderer-side router implementation.
@@ -595,11 +636,14 @@
                   const CefMessageRouterConfig& config)
         : router_(router), config_(config), context_id_(kReservedId) {}
 
+    V8HandlerImpl(const V8HandlerImpl&) = delete;
+    V8HandlerImpl& operator=(const V8HandlerImpl&) = delete;
+
     bool Execute(const CefString& name,
                  CefRefPtr<CefV8Value> object,
                  const CefV8ValueList& arguments,
                  CefRefPtr<CefV8Value>& retval,
-                 CefString& exception) OVERRIDE {
+                 CefString& exception) override {
       if (name == config_.js_query_function) {
         if (arguments.size() != 1 || !arguments[0]->IsObject()) {
           exception = "Invalid arguments; expecting a single object";
@@ -609,10 +653,16 @@
         CefRefPtr<CefV8Value> arg = arguments[0];
 
         CefRefPtr<CefV8Value> requestVal = arg->GetValue(kMemberRequest);
-        if (!requestVal.get() || !requestVal->IsString()) {
+        if (!requestVal.get()) {
+          exception = "Invalid arguments; object member '" +
+                      std::string(kMemberRequest) + "' is required";
+          return true;
+        }
+
+        if (!requestVal->IsString() && !requestVal->IsArrayBuffer()) {
           exception = "Invalid arguments; object member '" +
                       std::string(kMemberRequest) +
-                      "' is required and must have type string";
+                      "' must have type string or ArrayBuffer";
           return true;
         }
 
@@ -655,9 +705,11 @@
             (persistentVal.get() && persistentVal->GetBoolValue());
 
         const int request_id = router_->SendQuery(
-            context->GetBrowser(), context->GetFrame(), context_id,
-            requestVal->GetStringValue(), persistent, successVal, failureVal);
+            context->GetBrowser(), context->GetFrame(), context_id, requestVal,
+            persistent, successVal, failureVal);
+
         retval = CefV8Value::CreateInt(request_id);
+
         return true;
       } else if (name == config_.js_cancel_function) {
         if (arguments.size() != 1 || !arguments[0]->IsInt()) {
@@ -684,8 +736,9 @@
    private:
     // Don't create the context ID until it's actually needed.
     int GetIDForContext(CefRefPtr<CefV8Context> context) {
-      if (context_id_ == kReservedId)
+      if (context_id_ == kReservedId) {
         context_id_ = router_->CreateIDForContext(context);
+      }
       return context_id_;
     }
 
@@ -704,19 +757,24 @@
         cancel_message_name_(config.js_cancel_function.ToString() +
                              kMessageSuffix) {}
 
-  virtual ~CefMessageRouterRendererSideImpl() {}
+  CefMessageRouterRendererSideImpl(const CefMessageRouterRendererSideImpl&) =
+      delete;
+  CefMessageRouterRendererSideImpl& operator=(
+      const CefMessageRouterRendererSideImpl&) = delete;
 
   int GetPendingCount(CefRefPtr<CefBrowser> browser,
-                      CefRefPtr<CefV8Context> context) OVERRIDE {
+                      CefRefPtr<CefV8Context> context) override {
     CEF_REQUIRE_RENDERER_THREAD();
 
-    if (browser_request_info_map_.empty())
+    if (browser_request_info_map_.empty()) {
       return 0;
+    }
 
     if (context.get()) {
       const int context_id = GetIDForContext(context, false);
-      if (context_id == kReservedId)
+      if (context_id == kReservedId) {
         return 0;  // Nothing associated with the specified context.
+      }
 
       // Need to iterate over each RequestInfo object to test the context.
       class Visitor : public BrowserRequestInfoMap::Visitor {
@@ -726,9 +784,10 @@
         bool OnNextInfo(int browser_id,
                         InfoIdType info_id,
                         InfoObjectType info,
-                        bool* remove) OVERRIDE {
-          if (info_id.first == context_id_)
+                        bool* remove) override {
+          if (info_id.first == context_id_) {
             count_++;
+          }
           return true;
         }
 
@@ -753,16 +812,14 @@
     } else if (browser.get()) {
       return static_cast<int>(
           browser_request_info_map_.size(browser->GetIdentifier()));
-    } else {
-      return static_cast<int>(browser_request_info_map_.size());
     }
 
-    return 0;
+    return static_cast<int>(browser_request_info_map_.size());
   }
 
   void OnContextCreated(CefRefPtr<CefBrowser> browser,
                         CefRefPtr<CefFrame> frame,
-                        CefRefPtr<CefV8Context> context) OVERRIDE {
+                        CefRefPtr<CefV8Context> context) override {
     CEF_REQUIRE_RENDERER_THREAD();
 
     // Register function handlers with the 'window' object.
@@ -787,7 +844,7 @@
 
   void OnContextReleased(CefRefPtr<CefBrowser> browser,
                          CefRefPtr<CefFrame> frame,
-                         CefRefPtr<CefV8Context> context) OVERRIDE {
+                         CefRefPtr<CefV8Context> context) override {
     CEF_REQUIRE_RENDERER_THREAD();
 
     // Get the context ID and remove the context from the map.
@@ -801,42 +858,29 @@
   bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
                                 CefRefPtr<CefFrame> frame,
                                 CefProcessId source_process,
-                                CefRefPtr<CefProcessMessage> message) OVERRIDE {
+                                CefRefPtr<CefProcessMessage> message) override {
     CEF_REQUIRE_RENDERER_THREAD();
 
-    const std::string& message_name = message->GetName();
-    if (message_name == query_message_name_) {
-      CefRefPtr<CefListValue> args = message->GetArgumentList();
-      DCHECK_GT(args->GetSize(), 3U);
-
-      const int context_id = args->GetInt(0);
-      const int request_id = args->GetInt(1);
-      bool is_success = args->GetBool(2);
-
-      if (is_success) {
-        DCHECK_EQ(args->GetSize(), 4U);
-        const CefString& response = args->GetString(3);
-        CefPostTask(
-            TID_RENDERER,
-            base::Bind(
-                &CefMessageRouterRendererSideImpl::ExecuteSuccessCallback, this,
-                browser->GetIdentifier(), context_id, request_id, response));
-      } else {
-        DCHECK_EQ(args->GetSize(), 5U);
-        int error_code = args->GetInt(3);
-        const CefString& error_message = args->GetString(4);
-        CefPostTask(
-            TID_RENDERER,
-            base::Bind(
-                &CefMessageRouterRendererSideImpl::ExecuteFailureCallback, this,
-                browser->GetIdentifier(), context_id, request_id, error_code,
-                error_message));
-      }
-
-      return true;
+    if (message->GetName() != query_message_name_) {
+      return false;
     }
 
-    return false;
+    cmru::BrowserMessage content = cmru::ParseBrowserMessage(message);
+    if (content.is_success) {
+      std::visit(
+          [&](const auto& arg) {
+            ExecuteSuccessCallback(browser->GetIdentifier(), content.context_id,
+                                   content.request_id, arg);
+          },
+          content.payload);
+
+    } else {
+      ExecuteFailureCallback(browser->GetIdentifier(), content.context_id,
+                             content.request_id, content.error_code,
+                             std::get<CefString>(content.payload));
+    }
+
+    return true;
   }
 
  private:
@@ -870,7 +914,7 @@
       bool OnNextInfo(int browser_id,
                       InfoIdType info_id,
                       InfoObjectType info,
-                      bool* remove) OVERRIDE {
+                      bool* remove) override {
         *remove = removed_ = (always_remove_ || !info->persistent);
         return true;
       }
@@ -885,8 +929,9 @@
     Visitor visitor(always_remove);
     RequestInfo* info = browser_request_info_map_.Find(
         browser_id, std::make_pair(context_id, request_id), &visitor);
-    if (info)
+    if (info) {
       *removed = visitor.removed();
+    }
     return info;
   }
 
@@ -894,7 +939,7 @@
   int SendQuery(CefRefPtr<CefBrowser> browser,
                 CefRefPtr<CefFrame> frame,
                 int context_id,
-                const CefString& request,
+                CefRefPtr<CefV8Value> request,
                 bool persistent,
                 CefRefPtr<CefV8Value> success_callback,
                 CefRefPtr<CefV8Value> failure_callback) {
@@ -902,21 +947,15 @@
 
     const int request_id = request_id_generator_.GetNextId();
 
-    RequestInfo* info = new RequestInfo;
-    info->persistent = persistent;
-    info->success_callback = success_callback;
-    info->failure_callback = failure_callback;
+    auto* info =
+        new RequestInfo{persistent, success_callback, failure_callback};
+
     browser_request_info_map_.Add(browser->GetIdentifier(),
                                   std::make_pair(context_id, request_id), info);
 
-    CefRefPtr<CefProcessMessage> message =
-        CefProcessMessage::Create(query_message_name_);
-
-    CefRefPtr<CefListValue> args = message->GetArgumentList();
-    args->SetInt(0, context_id);
-    args->SetInt(1, request_id);
-    args->SetString(2, request);
-    args->SetBool(3, persistent);
+    CefRefPtr<CefProcessMessage> message = cmru::BuildRendererMsg(
+        config_.message_size_threshold, query_message_name_, context_id,
+        request_id, request, persistent);
 
     frame->SendProcessMessage(PID_BROWSER, message);
 
@@ -955,7 +994,7 @@
         bool OnNextInfo(int browser_id,
                         InfoIdType info_id,
                         InfoObjectType info,
-                        bool* remove) OVERRIDE {
+                        bool* remove) override {
           if (info_id.first == context_id_) {
             *remove = true;
             delete info;
@@ -1001,8 +1040,9 @@
     bool removed;
     RequestInfo* info =
         GetRequestInfo(browser_id, context_id, request_id, false, &removed);
-    if (!info)
+    if (!info) {
       return;
+    }
 
     CefRefPtr<CefV8Context> context = GetContextByID(context_id);
     if (context && info->success_callback) {
@@ -1012,8 +1052,44 @@
                                                          args);
     }
 
-    if (removed)
+    if (removed) {
       delete info;
+    }
+  }
+
+  // Execute the onSuccess JavaScript callback.
+  void ExecuteSuccessCallback(int browser_id,
+                              int context_id,
+                              int request_id,
+                              const CefRefPtr<CefBinaryBuffer>& response) {
+    CEF_REQUIRE_RENDERER_THREAD();
+
+    bool removed;
+    RequestInfo* info =
+        GetRequestInfo(browser_id, context_id, request_id, false, &removed);
+    if (!info) {
+      return;
+    }
+
+    CefRefPtr<CefV8Context> context = GetContextByID(context_id);
+    if (context && info->success_callback && context->Enter()) {
+      CefRefPtr<cmru::BinaryValueABRCallback> release_callback =
+          new cmru::BinaryValueABRCallback(response);
+
+      CefRefPtr<CefV8Value> value = CefV8Value::CreateArrayBuffer(
+          response->GetData(), response->GetSize(), release_callback);
+
+      context->Exit();
+
+      CefV8ValueList args;
+      args.push_back(value);
+      info->success_callback->ExecuteFunctionWithContext(context, nullptr,
+                                                         args);
+    }
+
+    if (removed) {
+      delete info;
+    }
   }
 
   // Execute the onFailure JavaScript callback.
@@ -1027,8 +1103,9 @@
     bool removed;
     RequestInfo* info =
         GetRequestInfo(browser_id, context_id, request_id, true, &removed);
-    if (!info)
+    if (!info) {
       return;
+    }
 
     CefRefPtr<CefV8Context> context = GetContextByID(context_id);
     if (context && info->failure_callback) {
@@ -1063,8 +1140,9 @@
     for (; it != context_map_.end(); ++it) {
       if (it->second->IsSame(context)) {
         int context_id = it->first;
-        if (remove)
+        if (remove) {
           context_map_.erase(it);
+        }
         return context_id;
       }
     }
@@ -1076,8 +1154,9 @@
     CEF_REQUIRE_RENDERER_THREAD();
 
     ContextMap::const_iterator it = context_map_.find(context_id);
-    if (it != context_map_.end())
+    if (it != context_map_.end()) {
       return it->second;
+    }
     return nullptr;
   }
 
@@ -1092,30 +1171,31 @@
   // entry is added when a request is initiated via the bound function and
   // removed when either the request completes, is canceled via the bound
   // function, or the associated context is released.
-  typedef CefBrowserInfoMap<std::pair<int, int>, RequestInfo*>
-      BrowserRequestInfoMap;
+  using BrowserRequestInfoMap =
+      CefBrowserInfoMap<std::pair<int, int>, RequestInfo*>;
   BrowserRequestInfoMap browser_request_info_map_;
 
   // Map of context ID to CefV8Context for existing contexts. An entry is added
   // when a bound function is executed for the first time in the context and
   // removed when the context is released.
-  typedef std::map<int, CefRefPtr<CefV8Context>> ContextMap;
+  using ContextMap = std::map<int, CefRefPtr<CefV8Context>>;
   ContextMap context_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefMessageRouterRendererSideImpl);
 };
 
 }  // namespace
 
 CefMessageRouterConfig::CefMessageRouterConfig()
-    : js_query_function("cefQuery"), js_cancel_function("cefQueryCancel") {}
+    : js_query_function("cefQuery"),
+      js_cancel_function("cefQueryCancel"),
+      message_size_threshold(kResponseSizeThreshold) {}
 
 // static
 CefRefPtr<CefMessageRouterBrowserSide> CefMessageRouterBrowserSide::Create(
     const CefMessageRouterConfig& config) {
   CefMessageRouterConfig validated_config = config;
-  if (!ValidateConfig(validated_config))
+  if (!ValidateConfig(validated_config)) {
     return nullptr;
+  }
   return new CefMessageRouterBrowserSideImpl(validated_config);
 }
 
@@ -1123,7 +1203,8 @@
 CefRefPtr<CefMessageRouterRendererSide> CefMessageRouterRendererSide::Create(
     const CefMessageRouterConfig& config) {
   CefMessageRouterConfig validated_config = config;
-  if (!ValidateConfig(validated_config))
+  if (!ValidateConfig(validated_config)) {
     return nullptr;
+  }
   return new CefMessageRouterRendererSideImpl(validated_config);
 }
diff --git a/src/libcef_dll/wrapper/cef_message_router_utils.cc b/src/libcef_dll/wrapper/cef_message_router_utils.cc
new file mode 100644
index 0000000..9fee2a0
--- /dev/null
+++ b/src/libcef_dll/wrapper/cef_message_router_utils.cc
@@ -0,0 +1,525 @@
+// Copyright (c) 2023 The Chromium Embedded Framework 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 "libcef_dll/wrapper/cef_message_router_utils.h"
+
+#include "include/cef_shared_process_message_builder.h"
+
+#include <type_traits>
+
+namespace cef_message_router_utils {
+
+namespace {
+
+constexpr int kNoError = 0;
+
+constexpr size_t kContextId = 0;
+constexpr size_t kRequestId = 1;
+constexpr size_t kRendererPayload = 2;
+constexpr size_t kIsSuccess = 2;
+constexpr size_t kBrowserPayload = 3;
+constexpr size_t kIsPersistent = 3;
+
+struct BrowserMsgHeader {
+  int context_id;
+  int request_id;
+  bool is_binary;
+};
+
+static_assert(
+    std::is_trivially_copyable_v<BrowserMsgHeader>,
+    "Copying non-trivially-copyable object across memory spaces is dangerous");
+
+struct RendererMsgHeader {
+  int context_id;
+  int request_id;
+  bool is_persistent;
+  bool is_binary;
+};
+
+static_assert(
+    std::is_trivially_copyable_v<RendererMsgHeader>,
+    "Copying non-trivially-copyable object across memory spaces is dangerous");
+
+//
+// This is a workaround for handling empty CefBinaryValues, as it's not possible
+// to create an empty one directly. We use this empty struct as a tag to invoke
+// the SetNull function within the BuildBrowserListMsg and BuildRendererListMsg
+// functions.
+//
+struct Empty {};
+
+size_t GetByteLength(const CefString& value) {
+  return value.size() * sizeof(CefString::char_type);
+}
+
+size_t GetByteLength(const CefRefPtr<CefV8Value>& value) {
+  return value->GetArrayBufferByteLength();
+}
+
+const CefString& GetListRepresentation(const CefString& value) {
+  return value;
+}
+
+CefRefPtr<CefBinaryValue> GetListRepresentation(
+    const CefRefPtr<CefV8Value>& value) {
+  return CefBinaryValue::Create(value->GetArrayBufferData(),
+                                value->GetArrayBufferByteLength());
+}
+
+template <class Header, class T>
+size_t GetMessageSize(const T& value) {
+  return sizeof(Header) + GetByteLength(value);
+}
+
+template <class Header>
+void CopyIntoMemory(void* memory, const void* data, size_t bytes) {
+  if (bytes > 0) {
+    void* dest = static_cast<uint8_t*>(memory) + sizeof(Header);
+    memcpy(dest, data, bytes);
+  }
+}
+
+template <class Header>
+void CopyIntoMemory(void* memory, const CefRefPtr<CefV8Value>& value) {
+  CopyIntoMemory<Header>(memory, value->GetArrayBufferData(),
+                         value->GetArrayBufferByteLength());
+}
+
+template <class Header>
+void CopyIntoMemory(void* memory, const CefString& value) {
+  const size_t bytes = GetByteLength(value);
+  CopyIntoMemory<Header>(memory, value.c_str(), bytes);
+}
+
+template <class Header>
+CefString GetStringFromMemory(const void* memory, size_t size) {
+  const size_t bytes = size - sizeof(Header);
+  const size_t string_len = bytes / sizeof(CefString::char_type);
+  const void* string_data =
+      static_cast<const uint8_t*>(memory) + sizeof(Header);
+  const CefString::char_type* src =
+      static_cast<const CefString::char_type*>(string_data);
+  CefString result;
+  result.FromString(src, string_len, /*copy=*/true);
+  return result;
+}
+
+template <typename T>
+constexpr bool IsCefString() {
+  return std::is_same_v<std::remove_cv_t<T>, CefString>;
+}
+
+template <typename T>
+constexpr bool IsEmpty() {
+  return std::is_same_v<std::remove_cv_t<T>, Empty>;
+}
+
+template <class ResponseType>
+CefRefPtr<CefProcessMessage> BuildBrowserListMsg(const CefString& name,
+                                                 int context_id,
+                                                 int request_id,
+                                                 const ResponseType& response) {
+  auto message = CefProcessMessage::Create(name);
+  CefRefPtr<CefListValue> args = message->GetArgumentList();
+  args->SetInt(kContextId, context_id);
+  args->SetInt(kRequestId, request_id);
+  args->SetBool(kIsSuccess, true);
+
+  if constexpr (IsCefString<ResponseType>()) {
+    args->SetString(kBrowserPayload, response);
+  } else if constexpr (IsEmpty<ResponseType>()) {
+    args->SetNull(kBrowserPayload);
+  } else {
+    args->SetBinary(kBrowserPayload, response);
+  }
+
+  return message;
+}
+
+class EmptyResponseBuilder final : public BrowserResponseBuilder {
+ public:
+  explicit EmptyResponseBuilder(const std::string& name) : name_(name) {}
+  EmptyResponseBuilder(const EmptyResponseBuilder&) = delete;
+  EmptyResponseBuilder& operator=(const EmptyResponseBuilder&) = delete;
+
+  CefRefPtr<CefProcessMessage> Build(int context_id, int request_id) override {
+    return BuildBrowserListMsg(name_, context_id, request_id, Empty{});
+  }
+
+ private:
+  const CefString name_;
+
+  IMPLEMENT_REFCOUNTING(EmptyResponseBuilder);
+};
+
+class BinaryResponseBuilder final : public BrowserResponseBuilder {
+ public:
+  BinaryResponseBuilder(const std::string& name, const void* data, size_t size)
+      : name_(name), value_(CefBinaryValue::Create(data, size)) {}
+  BinaryResponseBuilder(const BinaryResponseBuilder&) = delete;
+  BinaryResponseBuilder& operator=(const BinaryResponseBuilder&) = delete;
+
+  CefRefPtr<CefProcessMessage> Build(int context_id, int request_id) override {
+    return BuildBrowserListMsg(name_, context_id, request_id, value_);
+  }
+
+ private:
+  const CefString name_;
+  const CefRefPtr<CefBinaryValue> value_;
+
+  IMPLEMENT_REFCOUNTING(BinaryResponseBuilder);
+};
+
+class StringResponseBuilder final : public BrowserResponseBuilder {
+ public:
+  StringResponseBuilder(const std::string& name, const CefString& value)
+      : name_(name), value_(value) {}
+  StringResponseBuilder(const StringResponseBuilder&) = delete;
+  StringResponseBuilder& operator=(const StringResponseBuilder&) = delete;
+
+  CefRefPtr<CefProcessMessage> Build(int context_id, int request_id) override {
+    return BuildBrowserListMsg(name_, context_id, request_id, value_);
+  }
+
+ private:
+  const CefString name_;
+  const CefString value_;
+
+  IMPLEMENT_REFCOUNTING(StringResponseBuilder);
+};
+
+// SharedProcessMessageResponseBuilder
+class SPMResponseBuilder final : public BrowserResponseBuilder {
+ public:
+  SPMResponseBuilder(const SPMResponseBuilder&) = delete;
+  SPMResponseBuilder& operator=(const SPMResponseBuilder&) = delete;
+
+  static CefRefPtr<BrowserResponseBuilder> Create(const std::string& name,
+                                                  const void* data,
+                                                  size_t size) {
+    const size_t message_size = sizeof(BrowserMsgHeader) + size;
+    auto builder = CefSharedProcessMessageBuilder::Create(name, message_size);
+    if (!builder->IsValid()) {
+      LOG(ERROR) << "Failed to allocate shared memory region of size "
+                 << message_size;
+      return new BinaryResponseBuilder(name, data, size);
+    }
+
+    CopyIntoMemory<BrowserMsgHeader>(builder->Memory(), data, size);
+    return new SPMResponseBuilder(builder, /*is_binary=*/true);
+  }
+
+  static CefRefPtr<BrowserResponseBuilder> Create(const std::string& name,
+                                                  const CefString& value) {
+    const size_t message_size = GetMessageSize<BrowserMsgHeader>(value);
+    auto builder = CefSharedProcessMessageBuilder::Create(name, message_size);
+    if (!builder->IsValid()) {
+      LOG(ERROR) << "Failed to allocate shared memory region of size "
+                 << message_size;
+      return new StringResponseBuilder(name, value);
+    }
+
+    CopyIntoMemory<BrowserMsgHeader>(builder->Memory(), value);
+    return new SPMResponseBuilder(builder, /*is_binary=*/false);
+  }
+
+  CefRefPtr<CefProcessMessage> Build(int context_id, int request_id) override {
+    auto header = static_cast<BrowserMsgHeader*>(builder_->Memory());
+    header->context_id = context_id;
+    header->request_id = request_id;
+    header->is_binary = is_binary_;
+    return builder_->Build();
+  }
+
+ private:
+  explicit SPMResponseBuilder(
+      const CefRefPtr<CefSharedProcessMessageBuilder>& builder,
+      bool is_binary)
+      : builder_(builder), is_binary_(is_binary) {}
+
+  CefRefPtr<CefSharedProcessMessageBuilder> builder_;
+  const bool is_binary_;
+
+  IMPLEMENT_REFCOUNTING(SPMResponseBuilder);
+};
+
+class EmptyBinaryBuffer final : public CefBinaryBuffer {
+ public:
+  EmptyBinaryBuffer() = default;
+  EmptyBinaryBuffer(const EmptyBinaryBuffer&) = delete;
+  EmptyBinaryBuffer& operator=(const EmptyBinaryBuffer&) = delete;
+
+  const void* GetData() const override { return nullptr; }
+  void* GetData() override { return nullptr; }
+  size_t GetSize() const override { return 0; }
+
+ private:
+  IMPLEMENT_REFCOUNTING(EmptyBinaryBuffer);
+};
+
+class BinaryValueBuffer final : public CefBinaryBuffer {
+ public:
+  BinaryValueBuffer(CefRefPtr<CefProcessMessage> message,
+                    CefRefPtr<CefBinaryValue> value)
+      : message_(std::move(message)), value_(std::move(value)) {}
+  BinaryValueBuffer(const BinaryValueBuffer&) = delete;
+  BinaryValueBuffer& operator=(const BinaryValueBuffer&) = delete;
+
+  const void* GetData() const override { return value_->GetRawData(); }
+  void* GetData() override {
+    // This is not UB as long as underlying storage is vector<uint8_t>
+    return const_cast<void*>(value_->GetRawData());
+  }
+  size_t GetSize() const override { return value_->GetSize(); }
+
+ private:
+  const CefRefPtr<CefProcessMessage> message_;
+  const CefRefPtr<CefBinaryValue> value_;
+
+  IMPLEMENT_REFCOUNTING(BinaryValueBuffer);
+};
+
+class SharedMemoryRegionBuffer final : public CefBinaryBuffer {
+ public:
+  SharedMemoryRegionBuffer(const CefRefPtr<CefSharedMemoryRegion>& region,
+                           size_t offset)
+      : region_(region),
+        data_(static_cast<uint8_t*>(region->Memory()) + offset),
+        size_(region->Size() - offset) {}
+  SharedMemoryRegionBuffer(const SharedMemoryRegionBuffer&) = delete;
+  SharedMemoryRegionBuffer& operator=(const SharedMemoryRegionBuffer&) = delete;
+
+  const void* GetData() const override { return data_; }
+  void* GetData() override { return data_; }
+  size_t GetSize() const override { return size_; }
+
+ private:
+  const CefRefPtr<CefSharedMemoryRegion> region_;
+  void* const data_;
+  const size_t size_;
+
+  IMPLEMENT_REFCOUNTING(SharedMemoryRegionBuffer);
+};
+
+template <class RequestType>
+CefRefPtr<CefProcessMessage> BuildRendererListMsg(const std::string& name,
+                                                  int context_id,
+                                                  int request_id,
+                                                  const RequestType& request,
+                                                  bool persistent) {
+  auto message = CefProcessMessage::Create(name);
+  CefRefPtr<CefListValue> args = message->GetArgumentList();
+  args->SetInt(kContextId, context_id);
+  args->SetInt(kRequestId, request_id);
+
+  if constexpr (IsCefString<RequestType>()) {
+    args->SetString(kRendererPayload, request);
+  } else if constexpr (IsEmpty<RequestType>()) {
+    args->SetNull(kRendererPayload);
+  } else {
+    args->SetBinary(kRendererPayload, request);
+  }
+
+  args->SetBool(kIsPersistent, persistent);
+  return message;
+}
+
+template <class RequestType>
+CefRefPtr<CefProcessMessage> BuildRendererSharedMsg(const std::string& name,
+                                                    int context_id,
+                                                    int request_id,
+                                                    const RequestType& request,
+                                                    bool persistent) {
+  const size_t message_size = GetMessageSize<RendererMsgHeader>(request);
+  auto builder = CefSharedProcessMessageBuilder::Create(name, message_size);
+  if (!builder->IsValid()) {
+    LOG(ERROR) << "Failed to allocate shared memory region of size "
+               << message_size;
+    return BuildRendererListMsg(name, context_id, request_id,
+                                GetListRepresentation(request), persistent);
+  }
+
+  auto header = static_cast<RendererMsgHeader*>(builder->Memory());
+  header->context_id = context_id;
+  header->request_id = request_id;
+  header->is_persistent = persistent;
+  header->is_binary = !IsCefString<RequestType>();
+
+  CopyIntoMemory<RendererMsgHeader>(builder->Memory(), request);
+
+  return builder->Build();
+}
+
+CefRefPtr<CefProcessMessage> BuildRendererMsg(size_t threshold,
+                                              const std::string& name,
+                                              int context_id,
+                                              int request_id,
+                                              const CefString& request,
+                                              bool persistent) {
+  if (GetByteLength(request) < threshold) {
+    return BuildRendererListMsg(name, context_id, request_id, request,
+                                persistent);
+  }
+
+  return BuildRendererSharedMsg(name, context_id, request_id, request,
+                                persistent);
+}
+
+}  // namespace
+
+CefRefPtr<BrowserResponseBuilder> CreateBrowserResponseBuilder(
+    size_t threshold,
+    const std::string& name,
+    const CefString& response) {
+  if (GetByteLength(response) < threshold) {
+    return new StringResponseBuilder(name, response);
+  }
+
+  return SPMResponseBuilder::Create(name, response);
+}
+
+CefRefPtr<BrowserResponseBuilder> CreateBrowserResponseBuilder(
+    size_t threshold,
+    const std::string& name,
+    const void* data,
+    size_t size) {
+  if (size == 0) {
+    return new EmptyResponseBuilder(name);
+  }
+
+  if (size < threshold) {
+    return new BinaryResponseBuilder(name, data, size);
+  }
+
+  return SPMResponseBuilder::Create(name, data, size);
+}
+
+CefRefPtr<CefProcessMessage> BuildRendererMsg(
+    size_t threshold,
+    const std::string& name,
+    int context_id,
+    int request_id,
+    const CefRefPtr<CefV8Value>& request,
+    bool persistent) {
+  if (request->IsString()) {
+    return BuildRendererMsg(threshold, name, context_id, request_id,
+                            request->GetStringValue(), persistent);
+  }
+
+  const auto size = request->GetArrayBufferByteLength();
+  if (size == 0) {
+    return BuildRendererListMsg(name, context_id, request_id, Empty{},
+                                persistent);
+  }
+
+  if (size < threshold) {
+    return BuildRendererListMsg(name, context_id, request_id,
+                                GetListRepresentation(request), persistent);
+  }
+
+  return BuildRendererSharedMsg(name, context_id, request_id, request,
+                                persistent);
+}
+
+BrowserMessage ParseBrowserMessage(
+    const CefRefPtr<CefProcessMessage>& message) {
+  if (auto args = message->GetArgumentList()) {
+    DCHECK_GT(args->GetSize(), 3U);
+
+    const int context_id = args->GetInt(kContextId);
+    const int request_id = args->GetInt(kRequestId);
+    const bool is_success = args->GetBool(kIsSuccess);
+
+    if (is_success) {
+      DCHECK_EQ(args->GetSize(), 4U);
+      const auto payload_type = args->GetType(kBrowserPayload);
+      if (payload_type == CefValueType::VTYPE_STRING) {
+        return {context_id, request_id, is_success, kNoError,
+                args->GetString(kBrowserPayload)};
+      }
+
+      if (payload_type == CefValueType::VTYPE_BINARY) {
+        return {
+            context_id, request_id, is_success, kNoError,
+            new BinaryValueBuffer(message, args->GetBinary(kBrowserPayload))};
+      }
+
+      DCHECK(payload_type == CefValueType::VTYPE_NULL);
+      return {context_id, request_id, is_success, kNoError,
+              new EmptyBinaryBuffer()};
+    }
+
+    DCHECK_EQ(args->GetSize(), 5U);
+    return {context_id, request_id, is_success, args->GetInt(3),
+            args->GetString(4)};
+  }
+
+  const auto region = message->GetSharedMemoryRegion();
+  if (region && region->IsValid()) {
+    DCHECK_GE(region->Size(), sizeof(BrowserMsgHeader));
+    auto header = static_cast<const BrowserMsgHeader*>(region->Memory());
+
+    if (header->is_binary) {
+      return {header->context_id, header->request_id, true, kNoError,
+              new SharedMemoryRegionBuffer(region, sizeof(BrowserMsgHeader))};
+    }
+    return {header->context_id, header->request_id, true, kNoError,
+            GetStringFromMemory<BrowserMsgHeader>(region->Memory(),
+                                                  region->Size())};
+  }
+
+  NOTREACHED();
+  return {};
+}
+
+RendererMessage ParseRendererMessage(
+    const CefRefPtr<CefProcessMessage>& message) {
+  if (auto args = message->GetArgumentList()) {
+    DCHECK_EQ(args->GetSize(), 4U);
+
+    const int context_id = args->GetInt(kContextId);
+    const int request_id = args->GetInt(kRequestId);
+    const auto payload_type = args->GetType(kRendererPayload);
+    const bool persistent = args->GetBool(kIsPersistent);
+
+    if (payload_type == CefValueType::VTYPE_STRING) {
+      return {context_id, request_id, persistent,
+              args->GetString(kRendererPayload)};
+    }
+
+    if (payload_type == CefValueType::VTYPE_BINARY) {
+      return {
+          context_id, request_id, persistent,
+          new BinaryValueBuffer(message, args->GetBinary(kRendererPayload))};
+    }
+
+    DCHECK(payload_type == CefValueType::VTYPE_NULL);
+    return {context_id, request_id, persistent, new EmptyBinaryBuffer()};
+  }
+
+  const auto region = message->GetSharedMemoryRegion();
+  if (region && region->IsValid()) {
+    DCHECK_GE(region->Size(), sizeof(RendererMsgHeader));
+    auto header = static_cast<const RendererMsgHeader*>(region->Memory());
+
+    if (header->is_binary) {
+      return {header->context_id, header->request_id, header->is_persistent,
+              new SharedMemoryRegionBuffer(region, sizeof(RendererMsgHeader))};
+    }
+
+    return {
+        header->context_id,
+        header->request_id,
+        header->is_persistent,
+        GetStringFromMemory<RendererMsgHeader>(region->Memory(),
+                                               region->Size()),
+    };
+  }
+
+  NOTREACHED();
+  return {};
+}
+
+}  // namespace cef_message_router_utils
diff --git a/src/libcef_dll/wrapper/cef_message_router_utils.h b/src/libcef_dll/wrapper/cef_message_router_utils.h
new file mode 100644
index 0000000..b12a982
--- /dev/null
+++ b/src/libcef_dll/wrapper/cef_message_router_utils.h
@@ -0,0 +1,92 @@
+// Copyright (c) 2023 The Chromium Embedded Framework 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 CEF_LIBCEF_DLL_WRAPPER_CEF_MESSAGE_ROUTER_UTILS_H_
+#define CEF_LIBCEF_DLL_WRAPPER_CEF_MESSAGE_ROUTER_UTILS_H_
+#pragma once
+
+#include <variant>
+
+#include "include/wrapper/cef_message_router.h"
+
+namespace cef_message_router_utils {
+
+///
+/// This class handles the task of copying user data, such as CefString or
+/// binary values like (void*, size_t), directly to an appropriate buffer based
+/// on the user data type and size.
+///
+/// There are four specializations of this abstract class. The appropriate
+/// specialization is chosen by the `CreateBrowserResponseBuilder` function,
+/// based on the provided data type and size. For instance, for a "short"
+/// CefString, a StringResponseBuilder specialization is used, and for an empty
+/// binary value - EmptyResponseBuilder.
+///
+class BrowserResponseBuilder : public CefBaseRefCounted {
+ public:
+  ///
+  /// Creates a new CefProcessMessage from the data provided to the builder.
+  /// Returns nullptr for invalid instances. Invalidates this builder instance.
+  ///
+  virtual CefRefPtr<CefProcessMessage> Build(int context_id,
+                                             int request_id) = 0;
+};
+
+struct BrowserMessage {
+  int context_id;
+  int request_id;
+  bool is_success;
+  int error_code;
+  std::variant<CefString, CefRefPtr<CefBinaryBuffer>> payload;
+};
+
+struct RendererMessage {
+  int context_id;
+  int request_id;
+  bool is_persistent;
+  std::variant<CefString, CefRefPtr<const CefBinaryBuffer>> payload;
+};
+
+class BinaryValueABRCallback final : public CefV8ArrayBufferReleaseCallback {
+ public:
+  explicit BinaryValueABRCallback(CefRefPtr<CefBinaryBuffer> value)
+      : value_(std::move(value)) {}
+  BinaryValueABRCallback(const BinaryValueABRCallback&) = delete;
+  BinaryValueABRCallback& operator=(const BinaryValueABRCallback&) = delete;
+
+  void ReleaseBuffer(void* buffer) override {}
+
+ private:
+  const CefRefPtr<CefBinaryBuffer> value_;
+
+  IMPLEMENT_REFCOUNTING(BinaryValueABRCallback);
+};
+
+CefRefPtr<BrowserResponseBuilder> CreateBrowserResponseBuilder(
+    size_t threshold,
+    const std::string& name,
+    const CefString& response);
+
+CefRefPtr<BrowserResponseBuilder> CreateBrowserResponseBuilder(
+    size_t threshold,
+    const std::string& name,
+    const void* data,
+    size_t size);
+
+CefRefPtr<CefProcessMessage> BuildRendererMsg(
+    size_t threshold,
+    const std::string& name,
+    int context_id,
+    int request_id,
+    const CefRefPtr<CefV8Value>& request,
+    bool persistent);
+
+BrowserMessage ParseBrowserMessage(const CefRefPtr<CefProcessMessage>& message);
+
+RendererMessage ParseRendererMessage(
+    const CefRefPtr<CefProcessMessage>& message);
+
+}  // namespace cef_message_router_utils
+
+#endif  // CEF_LIBCEF_DLL_WRAPPER_CEF_MESSAGE_ROUTER_UTILS_H_
diff --git a/src/libcef_dll/wrapper/cef_resource_manager.cc b/src/libcef_dll/wrapper/cef_resource_manager.cc
index 0f5c647..1df8aeb 100644
--- a/src/libcef_dll/wrapper/cef_resource_manager.cc
+++ b/src/libcef_dll/wrapper/cef_resource_manager.cc
@@ -7,7 +7,7 @@
 #include <algorithm>
 #include <vector>
 
-#include "include/base/cef_macros.h"
+#include "include/base/cef_callback.h"
 #include "include/base/cef_weak_ptr.h"
 #include "include/cef_parser.h"
 #include "include/wrapper/cef_stream_resource_handler.h"
@@ -25,8 +25,9 @@
 std::string GetUrlWithoutQueryOrFragment(const std::string& url) {
   // Find the first instance of '?' or '#'.
   const size_t pos = std::min(url.find('?'), url.find('#'));
-  if (pos != std::string::npos)
+  if (pos != std::string::npos) {
     return url.substr(0, pos);
+  }
 
   return url;
 }
@@ -38,8 +39,9 @@
   size_t sep = url_without_query.find_last_of(".");
   if (sep != std::string::npos) {
     mime_type = CefGetMimeType(url_without_query.substr(sep + 1));
-    if (!mime_type.empty())
+    if (!mime_type.empty()) {
       return mime_type;
+    }
   }
   return "text/html";
 }
@@ -60,7 +62,10 @@
     DCHECK(!content.empty());
   }
 
-  bool OnRequest(scoped_refptr<CefResourceManager::Request> request) OVERRIDE {
+  ContentProvider(const ContentProvider&) = delete;
+  ContentProvider& operator=(const ContentProvider&) = delete;
+
+  bool OnRequest(scoped_refptr<CefResourceManager::Request> request) override {
     CEF_REQUIRE_IO_THREAD();
 
     const std::string& url = request->url();
@@ -74,8 +79,9 @@
         content_.length());
 
     // Determine the mime type a single time if it isn't already set.
-    if (mime_type_.empty())
+    if (mime_type_.empty()) {
       mime_type_ = request->mime_type_resolver().Run(url);
+    }
 
     request->Continue(new CefStreamResourceHandler(mime_type_, stream));
     return true;
@@ -85,8 +91,6 @@
   std::string url_;
   std::string content_;
   std::string mime_type_;
-
-  DISALLOW_COPY_AND_ASSIGN(ContentProvider);
 };
 
 // Provider of contents loaded from a directory on the file system.
@@ -99,13 +103,18 @@
     DCHECK(!directory_path_.empty());
 
     // Normalize the path values.
-    if (url_path_[url_path_.size() - 1] != '/')
+    if (url_path_[url_path_.size() - 1] != '/') {
       url_path_ += '/';
-    if (directory_path_[directory_path_.size() - 1] != PATH_SEP)
+    }
+    if (directory_path_[directory_path_.size() - 1] != PATH_SEP) {
       directory_path_ += PATH_SEP;
+    }
   }
 
-  bool OnRequest(scoped_refptr<CefResourceManager::Request> request) OVERRIDE {
+  DirectoryProvider(const DirectoryProvider&) = delete;
+  DirectoryProvider& operator=(const DirectoryProvider&) = delete;
+
+  bool OnRequest(scoped_refptr<CefResourceManager::Request> request) override {
     CEF_REQUIRE_IO_THREAD();
 
     const std::string& url = request->url();
@@ -116,8 +125,9 @@
     const std::string& file_path = GetFilePath(url);
 
     // Open |file_path| on the FILE thread.
-    CefPostTask(TID_FILE, base::Bind(&DirectoryProvider::OpenOnFileThread,
-                                     file_path, request));
+    CefPostTask(TID_FILE_USER_BLOCKING,
+                base::BindOnce(&DirectoryProvider::OpenOnFileThread, file_path,
+                               request));
 
     return true;
   }
@@ -134,14 +144,15 @@
   static void OpenOnFileThread(
       const std::string& file_path,
       scoped_refptr<CefResourceManager::Request> request) {
-    CEF_REQUIRE_FILE_THREAD();
+    CEF_REQUIRE_FILE_USER_BLOCKING_THREAD();
 
     CefRefPtr<CefStreamReader> stream =
         CefStreamReader::CreateForFile(file_path);
 
     // Continue loading on the IO thread.
-    CefPostTask(TID_IO, base::Bind(&DirectoryProvider::ContinueOpenOnIOThread,
-                                   request, stream));
+    CefPostTask(TID_IO,
+                base::BindOnce(&DirectoryProvider::ContinueOpenOnIOThread,
+                               request, stream));
   }
 
   static void ContinueOpenOnIOThread(
@@ -159,8 +170,6 @@
 
   std::string url_path_;
   std::string directory_path_;
-
-  DISALLOW_COPY_AND_ASSIGN(DirectoryProvider);
 };
 
 // Provider of contents loaded from an archive file.
@@ -174,16 +183,20 @@
         password_(password),
         archive_load_started_(false),
         archive_load_ended_(false),
-        ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
+        weak_ptr_factory_(this) {
     DCHECK(!url_path_.empty());
     DCHECK(!archive_path_.empty());
 
     // Normalize the path values.
-    if (url_path_[url_path_.size() - 1] != '/')
+    if (url_path_[url_path_.size() - 1] != '/') {
       url_path_ += '/';
+    }
   }
 
-  bool OnRequest(scoped_refptr<CefResourceManager::Request> request) OVERRIDE {
+  ArchiveProvider(const ArchiveProvider&) = delete;
+  ArchiveProvider& operator=(const ArchiveProvider&) = delete;
+
+  bool OnRequest(scoped_refptr<CefResourceManager::Request> request) override {
     CEF_REQUIRE_IO_THREAD();
 
     const std::string& url = request->url();
@@ -198,9 +211,10 @@
       pending_requests_.push_back(request);
 
       // Load the archive file on the FILE thread.
-      CefPostTask(TID_FILE, base::Bind(&ArchiveProvider::LoadOnFileThread,
-                                       weak_ptr_factory_.GetWeakPtr(),
-                                       archive_path_, password_));
+      CefPostTask(TID_FILE_USER_BLOCKING,
+                  base::BindOnce(&ArchiveProvider::LoadOnFileThread,
+                                 weak_ptr_factory_.GetWeakPtr(), archive_path_,
+                                 password_));
       return true;
     }
 
@@ -218,7 +232,7 @@
   static void LoadOnFileThread(base::WeakPtr<ArchiveProvider> ptr,
                                const std::string& archive_path,
                                const std::string& password) {
-    CEF_REQUIRE_FILE_THREAD();
+    CEF_REQUIRE_FILE_USER_BLOCKING_THREAD();
 
     CefRefPtr<CefZipArchive> archive;
 
@@ -234,8 +248,8 @@
       DLOG(WARNING) << "Failed to load archive file: " << archive_path;
     }
 
-    CefPostTask(TID_IO,
-                base::Bind(&ArchiveProvider::ContinueOnIOThread, ptr, archive));
+    CefPostTask(TID_IO, base::BindOnce(&ArchiveProvider::ContinueOnIOThread,
+                                       ptr, archive));
   }
 
   void ContinueOnIOThread(CefRefPtr<CefZipArchive> archive) {
@@ -247,8 +261,9 @@
     if (!pending_requests_.empty()) {
       // Continue all pending requests.
       PendingRequests::const_iterator it = pending_requests_.begin();
-      for (; it != pending_requests_.end(); ++it)
+      for (; it != pending_requests_.end(); ++it) {
         ContinueRequest(*it);
+      }
       pending_requests_.clear();
     }
   }
@@ -267,8 +282,9 @@
       }
     }
 
-    if (!handler.get())
+    if (!handler.get()) {
       return false;
+    }
 
     request->Continue(handler);
     return true;
@@ -283,14 +299,12 @@
   CefRefPtr<CefZipArchive> archive_;
 
   // List of requests that are pending while the archive is being loaded.
-  typedef std::vector<scoped_refptr<CefResourceManager::Request>>
-      PendingRequests;
+  using PendingRequests =
+      std::vector<scoped_refptr<CefResourceManager::Request>>;
   PendingRequests pending_requests_;
 
   // Must be the last member.
   base::WeakPtrFactory<ArchiveProvider> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(ArchiveProvider);
 };
 
 }  // namespace
@@ -304,7 +318,7 @@
         identifier_(identifier),
         deletion_pending_(false) {}
 
-  scoped_ptr<Provider> provider_;
+  std::unique_ptr<Provider> provider_;
   int order_;
   std::string identifier_;
 
@@ -319,8 +333,9 @@
 
 CefResourceManager::RequestState::~RequestState() {
   // Always execute the callback.
-  if (callback_.get())
-    callback_->Continue(true);
+  if (callback_.get()) {
+    callback_->Continue();
+  }
 }
 
 // CefResourceManager::Request implementation.
@@ -328,40 +343,44 @@
 void CefResourceManager::Request::Continue(
     CefRefPtr<CefResourceHandler> handler) {
   if (!CefCurrentlyOn(TID_IO)) {
-    CefPostTask(TID_IO, base::Bind(&CefResourceManager::Request::Continue, this,
-                                   handler));
+    CefPostTask(TID_IO, base::BindOnce(&CefResourceManager::Request::Continue,
+                                       this, handler));
     return;
   }
 
-  if (!state_.get())
+  if (!state_.get()) {
     return;
+  }
 
   // Disassociate |state_| immediately so that Provider::OnRequestCanceled is
   // not called unexpectedly if Provider::OnRequest calls this method and then
   // calls CefResourceManager::Remove*.
   CefPostTask(TID_IO,
-              base::Bind(&CefResourceManager::Request::ContinueOnIOThread,
-                         base::Passed(&state_), handler));
+              base::BindOnce(&CefResourceManager::Request::ContinueOnIOThread,
+                             std::move(state_), handler));
 }
 
 void CefResourceManager::Request::Stop() {
   if (!CefCurrentlyOn(TID_IO)) {
-    CefPostTask(TID_IO, base::Bind(&CefResourceManager::Request::Stop, this));
+    CefPostTask(TID_IO,
+                base::BindOnce(&CefResourceManager::Request::Stop, this));
     return;
   }
 
-  if (!state_.get())
+  if (!state_.get()) {
     return;
+  }
 
   // Disassociate |state_| immediately so that Provider::OnRequestCanceled is
   // not called unexpectedly if Provider::OnRequest calls this method and then
   // calls CefResourceManager::Remove*.
-  CefPostTask(TID_IO, base::Bind(&CefResourceManager::Request::StopOnIOThread,
-                                 base::Passed(&state_)));
+  CefPostTask(TID_IO,
+              base::BindOnce(&CefResourceManager::Request::StopOnIOThread,
+                             std::move(state_)));
 }
 
-CefResourceManager::Request::Request(scoped_ptr<RequestState> state)
-    : state_(state.Pass()), params_(state_->params_) {
+CefResourceManager::Request::Request(std::unique_ptr<RequestState> state)
+    : state_(std::move(state)), params_(state_->params_) {
   CEF_REQUIRE_IO_THREAD();
 
   ProviderEntry* entry = *(state_->current_entry_pos_);
@@ -377,13 +396,14 @@
 // handle the request. Note that |state_| may already be NULL if OnRequest
 // executes a callback before returning, in which case execution will continue
 // asynchronously in any case.
-scoped_ptr<CefResourceManager::RequestState>
+std::unique_ptr<CefResourceManager::RequestState>
 CefResourceManager::Request::SendRequest() {
   CEF_REQUIRE_IO_THREAD();
   Provider* provider = (*state_->current_entry_pos_)->provider_.get();
-  if (!provider->OnRequest(this))
-    return state_.Pass();
-  return scoped_ptr<RequestState>();
+  if (!provider->OnRequest(this)) {
+    return std::move(state_);
+  }
+  return std::unique_ptr<RequestState>();
 }
 
 bool CefResourceManager::Request::HasState() {
@@ -393,30 +413,32 @@
 
 // static
 void CefResourceManager::Request::ContinueOnIOThread(
-    scoped_ptr<RequestState> state,
+    std::unique_ptr<RequestState> state,
     CefRefPtr<CefResourceHandler> handler) {
   CEF_REQUIRE_IO_THREAD();
   // The manager may already have been deleted.
   base::WeakPtr<CefResourceManager> manager = state->manager_;
-  if (manager)
-    manager->ContinueRequest(state.Pass(), handler);
+  if (manager) {
+    manager->ContinueRequest(std::move(state), handler);
+  }
 }
 
 // static
 void CefResourceManager::Request::StopOnIOThread(
-    scoped_ptr<RequestState> state) {
+    std::unique_ptr<RequestState> state) {
   CEF_REQUIRE_IO_THREAD();
   // The manager may already have been deleted.
   base::WeakPtr<CefResourceManager> manager = state->manager_;
-  if (manager)
-    manager->StopRequest(state.Pass());
+  if (manager) {
+    manager->StopRequest(std::move(state));
+  }
 }
 
 // CefResourceManager implementation.
 
 CefResourceManager::CefResourceManager()
-    : url_filter_(base::Bind(GetFilteredUrl)),
-      mime_type_resolver_(base::Bind(GetMimeType)) {}
+    : url_filter_(base::BindRepeating(GetFilteredUrl)),
+      mime_type_resolver_(base::BindRepeating(GetMimeType)) {}
 
 CefResourceManager::~CefResourceManager() {
   CEF_REQUIRE_IO_THREAD();
@@ -426,8 +448,9 @@
   // call back into this manager due to the use of WeakPtr.
   if (!providers_.empty()) {
     ProviderEntryList::iterator it = providers_.begin();
-    for (; it != providers_.end(); ++it)
+    for (; it != providers_.end(); ++it) {
       delete *it;
+    }
     providers_.clear();
   }
 }
@@ -461,16 +484,17 @@
                                      int order,
                                      const std::string& identifier) {
   DCHECK(provider);
-  if (!provider)
-    return;
-
-  if (!CefCurrentlyOn(TID_IO)) {
-    CefPostTask(TID_IO, base::Bind(&CefResourceManager::AddProvider, this,
-                                   provider, order, identifier));
+  if (!provider) {
     return;
   }
 
-  scoped_ptr<ProviderEntry> new_entry(
+  if (!CefCurrentlyOn(TID_IO)) {
+    CefPostTask(TID_IO, base::BindOnce(&CefResourceManager::AddProvider, this,
+                                       provider, order, identifier));
+    return;
+  }
+
+  std::unique_ptr<ProviderEntry> new_entry(
       new ProviderEntry(provider, order, identifier));
 
   if (providers_.empty()) {
@@ -481,8 +505,9 @@
   // Insert before the first entry with a higher |order| value.
   ProviderEntryList::iterator it = providers_.begin();
   for (; it != providers_.end(); ++it) {
-    if ((*it)->order_ > order)
+    if ((*it)->order_ > order) {
       break;
+    }
   }
 
   providers_.insert(it, new_entry.release());
@@ -490,69 +515,75 @@
 
 void CefResourceManager::RemoveProviders(const std::string& identifier) {
   if (!CefCurrentlyOn(TID_IO)) {
-    CefPostTask(TID_IO, base::Bind(&CefResourceManager::RemoveProviders, this,
-                                   identifier));
+    CefPostTask(TID_IO, base::BindOnce(&CefResourceManager::RemoveProviders,
+                                       this, identifier));
     return;
   }
 
-  if (providers_.empty())
+  if (providers_.empty()) {
     return;
+  }
 
   ProviderEntryList::iterator it = providers_.begin();
   while (it != providers_.end()) {
-    if ((*it)->identifier_ == identifier)
+    if ((*it)->identifier_ == identifier) {
       DeleteProvider(it, false);
-    else
+    } else {
       ++it;
+    }
   }
 }
 
 void CefResourceManager::RemoveAllProviders() {
   if (!CefCurrentlyOn(TID_IO)) {
     CefPostTask(TID_IO,
-                base::Bind(&CefResourceManager::RemoveAllProviders, this));
+                base::BindOnce(&CefResourceManager::RemoveAllProviders, this));
     return;
   }
 
-  if (providers_.empty())
+  if (providers_.empty()) {
     return;
+  }
 
   ProviderEntryList::iterator it = providers_.begin();
-  while (it != providers_.end())
+  while (it != providers_.end()) {
     DeleteProvider(it, true);
+  }
 }
 
 void CefResourceManager::SetMimeTypeResolver(const MimeTypeResolver& resolver) {
   if (!CefCurrentlyOn(TID_IO)) {
-    CefPostTask(TID_IO, base::Bind(&CefResourceManager::SetMimeTypeResolver,
-                                   this, resolver));
+    CefPostTask(TID_IO, base::BindOnce(&CefResourceManager::SetMimeTypeResolver,
+                                       this, resolver));
     return;
   }
 
-  if (!resolver.is_null())
+  if (!resolver.is_null()) {
     mime_type_resolver_ = resolver;
-  else
-    mime_type_resolver_ = base::Bind(GetMimeType);
+  } else {
+    mime_type_resolver_ = base::BindRepeating(GetMimeType);
+  }
 }
 
 void CefResourceManager::SetUrlFilter(const UrlFilter& filter) {
   if (!CefCurrentlyOn(TID_IO)) {
-    CefPostTask(TID_IO,
-                base::Bind(&CefResourceManager::SetUrlFilter, this, filter));
+    CefPostTask(TID_IO, base::BindOnce(&CefResourceManager::SetUrlFilter, this,
+                                       filter));
     return;
   }
 
-  if (!filter.is_null())
+  if (!filter.is_null()) {
     url_filter_ = filter;
-  else
-    url_filter_ = base::Bind(GetFilteredUrl);
+  } else {
+    url_filter_ = base::BindRepeating(GetFilteredUrl);
+  }
 }
 
 cef_return_value_t CefResourceManager::OnBeforeResourceLoad(
     CefRefPtr<CefBrowser> browser,
     CefRefPtr<CefFrame> frame,
     CefRefPtr<CefRequest> request,
-    CefRefPtr<CefRequestCallback> callback) {
+    CefRefPtr<CefCallback> callback) {
   CEF_REQUIRE_IO_THREAD();
 
   // Find the first provider that is not pending deletion.
@@ -564,7 +595,7 @@
     return RV_CONTINUE;
   }
 
-  scoped_ptr<RequestState> state(new RequestState);
+  std::unique_ptr<RequestState> state(new RequestState);
 
   if (!weak_ptr_factory_.get()) {
     // WeakPtrFactory instances need to be created and destroyed on the same
@@ -588,7 +619,7 @@
   state->current_entry_pos_ = current_entry_pos;
 
   // If the request is potentially handled we need to continue asynchronously.
-  return SendRequest(state.Pass()) ? RV_CONTINUE_ASYNC : RV_CONTINUE;
+  return SendRequest(std::move(state)) ? RV_CONTINUE_ASYNC : RV_CONTINUE;
 }
 
 CefRefPtr<CefResourceHandler> CefResourceManager::GetResourceHandler(
@@ -597,8 +628,9 @@
     CefRefPtr<CefRequest> request) {
   CEF_REQUIRE_IO_THREAD();
 
-  if (pending_handlers_.empty())
+  if (pending_handlers_.empty()) {
     return nullptr;
+  }
 
   CefRefPtr<CefResourceHandler> handler;
 
@@ -614,21 +646,22 @@
 
 // Send the request to providers in order until one potentially handles it or we
 // run out of providers. Returns true if the request is potentially handled.
-bool CefResourceManager::SendRequest(scoped_ptr<RequestState> state) {
+bool CefResourceManager::SendRequest(std::unique_ptr<RequestState> state) {
   bool potentially_handled = false;
 
   do {
     // Should not be on the last provider entry.
     DCHECK(state->current_entry_pos_ != providers_.end());
-    scoped_refptr<Request> request = new Request(state.Pass());
+    scoped_refptr<Request> request = new Request(std::move(state));
 
     // Give the provider an opportunity to handle the request.
     state = request->SendRequest();
     if (state.get()) {
       // The provider will not handle the request. Move to the next provider if
       // any.
-      if (!IncrementProvider(state.get()))
-        StopRequest(state.Pass());
+      if (!IncrementProvider(state.get())) {
+        StopRequest(std::move(state));
+      }
     } else {
       potentially_handled = true;
     }
@@ -638,7 +671,7 @@
 }
 
 void CefResourceManager::ContinueRequest(
-    scoped_ptr<RequestState> state,
+    std::unique_ptr<RequestState> state,
     CefRefPtr<CefResourceHandler> handler) {
   CEF_REQUIRE_IO_THREAD();
 
@@ -646,17 +679,18 @@
     // The request has been handled. Associate the request ID with the handler.
     pending_handlers_.insert(
         std::make_pair(state->params_.request_->GetIdentifier(), handler));
-    StopRequest(state.Pass());
+    StopRequest(std::move(state));
   } else {
     // Move to the next provider if any.
-    if (IncrementProvider(state.get()))
-      SendRequest(state.Pass());
-    else
-      StopRequest(state.Pass());
+    if (IncrementProvider(state.get())) {
+      SendRequest(std::move(state));
+    } else {
+      StopRequest(std::move(state));
+    }
   }
 }
 
-void CefResourceManager::StopRequest(scoped_ptr<RequestState> state) {
+void CefResourceManager::StopRequest(std::unique_ptr<RequestState> state) {
   CEF_REQUIRE_IO_THREAD();
 
   // Detach from the current provider.
@@ -719,8 +753,9 @@
 
   ProviderEntry* current_entry = *(iterator);
 
-  if (current_entry->deletion_pending_)
+  if (current_entry->deletion_pending_) {
     return;
+  }
 
   if (!current_entry->pending_requests_.empty()) {
     // Don't delete the provider entry until all pending requests have cleared.
@@ -731,10 +766,11 @@
     for (; it != current_entry->pending_requests_.end(); ++it) {
       const scoped_refptr<Request>& request = *it;
       if (request->HasState()) {
-        if (stop)
+        if (stop) {
           request->Stop();
-        else
+        } else {
           request->Continue(nullptr);
+        }
         current_entry->provider_->OnRequestCanceled(request);
       }
     }
diff --git a/src/libcef_dll/wrapper/cef_scoped_temp_dir.cc b/src/libcef_dll/wrapper/cef_scoped_temp_dir.cc
index 9269aba..c131893 100644
--- a/src/libcef_dll/wrapper/cef_scoped_temp_dir.cc
+++ b/src/libcef_dll/wrapper/cef_scoped_temp_dir.cc
@@ -10,52 +10,61 @@
 CefScopedTempDir::CefScopedTempDir() {}
 
 CefScopedTempDir::~CefScopedTempDir() {
-  if (!path_.empty() && !Delete())
+  if (!path_.empty() && !Delete()) {
     DLOG(WARNING) << "Could not delete temp dir in dtor.";
+  }
 }
 
 bool CefScopedTempDir::CreateUniqueTempDir() {
-  if (!path_.empty())
+  if (!path_.empty()) {
     return false;
+  }
 
   // This "scoped_dir" prefix is only used on Windows and serves as a template
   // for the unique name.
-  if (!CefCreateNewTempDirectory("scoped_dir", path_))
+  if (!CefCreateNewTempDirectory("scoped_dir", path_)) {
     return false;
+  }
 
   return true;
 }
 
 bool CefScopedTempDir::CreateUniqueTempDirUnderPath(
     const CefString& base_path) {
-  if (!path_.empty())
+  if (!path_.empty()) {
     return false;
+  }
 
   // If |base_path| does not exist, create it.
-  if (!CefCreateDirectory(base_path))
+  if (!CefCreateDirectory(base_path)) {
     return false;
+  }
 
   // Create a new, uniquely named directory under |base_path|.
-  if (!CefCreateTempDirectoryInDirectory(base_path, "scoped_dir_", path_))
+  if (!CefCreateTempDirectoryInDirectory(base_path, "scoped_dir_", path_)) {
     return false;
+  }
 
   return true;
 }
 
 bool CefScopedTempDir::Set(const CefString& path) {
-  if (!path_.empty())
+  if (!path_.empty()) {
     return false;
+  }
 
-  if (!CefDirectoryExists(path) && !CefCreateDirectory(path))
+  if (!CefDirectoryExists(path) && !CefCreateDirectory(path)) {
     return false;
+  }
 
   path_ = path;
   return true;
 }
 
 bool CefScopedTempDir::Delete() {
-  if (path_.empty())
+  if (path_.empty()) {
     return false;
+  }
 
   bool ret = CefDeleteFile(path_, true);
   if (ret) {
diff --git a/src/libcef_dll/wrapper/cef_stream_resource_handler.cc b/src/libcef_dll/wrapper/cef_stream_resource_handler.cc
index ad5a34f..6c31e60 100644
--- a/src/libcef_dll/wrapper/cef_stream_resource_handler.cc
+++ b/src/libcef_dll/wrapper/cef_stream_resource_handler.cc
@@ -18,7 +18,6 @@
       mime_type_(mime_type),
       stream_(stream) {
   DCHECK(!mime_type_.empty());
-  DCHECK(stream_.get());
 }
 
 CefStreamResourceHandler::CefStreamResourceHandler(
@@ -33,7 +32,6 @@
       header_map_(header_map),
       stream_(stream) {
   DCHECK(!mime_type_.empty());
-  DCHECK(stream_.get());
 }
 
 bool CefStreamResourceHandler::Open(CefRefPtr<CefRequest> request,
@@ -48,7 +46,7 @@
 
 void CefStreamResourceHandler::GetResponseHeaders(
     CefRefPtr<CefResponse> response,
-    int64& response_length,
+    int64_t& response_length,
     CefString& redirectUrl) {
   CEF_REQUIRE_IO_THREAD();
 
@@ -56,10 +54,11 @@
   response->SetStatusText(status_text_);
   response->SetMimeType(mime_type_);
 
-  if (!header_map_.empty())
+  if (!header_map_.empty()) {
     response->SetHeaderMap(header_map_);
+  }
 
-  response_length = -1;
+  response_length = stream_ ? -1 : 0;
 }
 
 bool CefStreamResourceHandler::Read(
@@ -69,6 +68,7 @@
     CefRefPtr<CefResourceReadCallback> callback) {
   DCHECK(!CefCurrentlyOn(TID_UI) && !CefCurrentlyOn(TID_IO));
   DCHECK_GT(bytes_to_read, 0);
+  DCHECK(stream_);
 
   // Read until the buffer is full or until Read() returns 0 to indicate no
   // more data.
diff --git a/src/libcef_dll/wrapper/cef_xml_object.cc b/src/libcef_dll/wrapper/cef_xml_object.cc
index d6fc439..71d4f20 100644
--- a/src/libcef_dll/wrapper/cef_xml_object.cc
+++ b/src/libcef_dll/wrapper/cef_xml_object.cc
@@ -7,7 +7,6 @@
 #include <sstream>
 
 #include "include/base/cef_logging.h"
-#include "include/base/cef_macros.h"
 #include "include/cef_stream.h"
 
 namespace {
@@ -17,13 +16,17 @@
   explicit CefXmlObjectLoader(CefRefPtr<CefXmlObject> root_object)
       : root_object_(root_object) {}
 
+  CefXmlObjectLoader(const CefXmlObjectLoader&) = delete;
+  CefXmlObjectLoader& operator=(const CefXmlObjectLoader&) = delete;
+
   bool Load(CefRefPtr<CefStreamReader> stream,
             CefXmlReader::EncodingType encodingType,
             const CefString& URI) {
     CefRefPtr<CefXmlReader> reader(
         CefXmlReader::Create(stream, encodingType, URI));
-    if (!reader.get())
+    if (!reader.get()) {
       return false;
+    }
 
     bool ret = reader->MoveToNextNode();
     if (ret) {
@@ -104,7 +107,7 @@
               cur_object->GetName() != reader->GetQualifiedName()) {
             // Open tag without close tag or close tag without open tag should
             // never occur (the parser catches this error).
-            NOTREACHED();
+            DCHECK(false);
             std::stringstream ss;
             ss << "Mismatched end tag for "
                << std::string(cur_object->GetName()) << ", line "
@@ -151,8 +154,6 @@
  private:
   CefString load_error_;
   CefRefPtr<CefXmlObject> root_object_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefXmlObjectLoader);
 };
 
 }  // namespace
@@ -170,8 +171,9 @@
 
   CefXmlObjectLoader loader(this);
   if (!loader.Load(stream, encodingType, URI)) {
-    if (loadError)
+    if (loadError) {
       *loadError = loader.GetLoadError();
+    }
     return false;
   }
   return true;
@@ -194,8 +196,9 @@
     ObjectVector children;
     object->GetChildren(children);
     ObjectVector::const_iterator it = children.begin();
-    for (; it != children.end(); ++it)
+    for (; it != children.end(); ++it) {
       AddChild((*it)->Duplicate());
+    }
   }
 
   if (object->HasAttributes()) {
@@ -203,8 +206,9 @@
     object->GetAttributes(attributes);
     AttributeMap::const_iterator it = attributes.begin();
     for (; it != attributes.end(); ++it) {
-      if (overwriteAttributes || !HasAttribute(it->first))
+      if (overwriteAttributes || !HasAttribute(it->first)) {
         SetAttributeValue(it->first, it->second);
+      }
     }
   }
 }
@@ -235,8 +239,9 @@
 
 bool CefXmlObject::SetName(const CefString& name) {
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return false;
+  }
 
   base::AutoLock lock_scope(lock_);
   name_ = name;
@@ -274,8 +279,9 @@
 bool CefXmlObject::SetValue(const CefString& value) {
   base::AutoLock lock_scope(lock_);
   DCHECK(children_.empty());
-  if (!children_.empty())
+  if (!children_.empty()) {
     return false;
+  }
   value_ = value;
   return true;
 }
@@ -291,8 +297,9 @@
 }
 
 bool CefXmlObject::HasAttribute(const CefString& name) {
-  if (name.empty())
+  if (name.empty()) {
     return false;
+  }
 
   base::AutoLock lock_scope(lock_);
   AttributeMap::const_iterator it = attributes_.find(name);
@@ -305,8 +312,9 @@
   if (!name.empty()) {
     base::AutoLock lock_scope(lock_);
     AttributeMap::const_iterator it = attributes_.find(name);
-    if (it != attributes_.end())
+    if (it != attributes_.end()) {
       value = it->second;
+    }
   }
   return value;
 }
@@ -314,8 +322,9 @@
 bool CefXmlObject::SetAttributeValue(const CefString& name,
                                      const CefString& value) {
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return false;
+  }
 
   base::AutoLock lock_scope(lock_);
   AttributeMap::iterator it = attributes_.find(name);
@@ -354,21 +363,24 @@
   base::AutoLock lock_scope(lock_);
   ObjectVector::const_iterator it = children_.begin();
   for (; it != children_.end(); ++it) {
-    if ((*it).get() == child.get())
+    if ((*it).get() == child.get()) {
       return true;
+    }
   }
   return false;
 }
 
 bool CefXmlObject::AddChild(CefRefPtr<CefXmlObject> child) {
   DCHECK(child.get());
-  if (!child.get())
+  if (!child.get()) {
     return false;
+  }
 
   CefRefPtr<CefXmlObject> parent = child->GetParent();
   DCHECK(!parent);
-  if (parent)
+  if (parent) {
     return false;
+  }
 
   base::AutoLock lock_scope(lock_);
 
@@ -401,21 +413,24 @@
 void CefXmlObject::ClearChildren() {
   base::AutoLock lock_scope(lock_);
   ObjectVector::iterator it = children_.begin();
-  for (; it != children_.end(); ++it)
+  for (; it != children_.end(); ++it) {
     (*it)->SetParent(nullptr);
+  }
   children_.clear();
 }
 
 CefRefPtr<CefXmlObject> CefXmlObject::FindChild(const CefString& name) {
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return nullptr;
+  }
 
   base::AutoLock lock_scope(lock_);
   ObjectVector::const_iterator it = children_.begin();
   for (; it != children_.end(); ++it) {
-    if ((*it)->GetName() == name)
+    if ((*it)->GetName() == name) {
       return (*it);
+    }
   }
   return nullptr;
 }
@@ -423,8 +438,9 @@
 size_t CefXmlObject::FindChildren(const CefString& name,
                                   ObjectVector& children) {
   DCHECK(!name.empty());
-  if (name.empty())
+  if (name.empty()) {
     return 0;
+  }
 
   size_t ct = 0;
 
diff --git a/src/libcef_dll/wrapper/cef_zip_archive.cc b/src/libcef_dll/wrapper/cef_zip_archive.cc
index 5120d99..3ebff15 100644
--- a/src/libcef_dll/wrapper/cef_zip_archive.cc
+++ b/src/libcef_dll/wrapper/cef_zip_archive.cc
@@ -5,10 +5,9 @@
 #include "include/wrapper/cef_zip_archive.h"
 
 #include <algorithm>
+#include <memory>
 
 #include "include/base/cef_logging.h"
-#include "include/base/cef_macros.h"
-#include "include/base/cef_scoped_ptr.h"
 #include "include/cef_stream.h"
 #include "include/cef_zip_reader.h"
 #include "include/wrapper/cef_byte_read_handler.h"
@@ -30,8 +29,11 @@
  public:
   CefZipFile() : data_size_(0) {}
 
+  CefZipFile(const CefZipFile&) = delete;
+  CefZipFile& operator=(const CefZipFile&) = delete;
+
   bool Initialize(size_t data_size) {
-    data_.reset(new unsigned char[data_size]);
+    data_.reset(new (std::nothrow) unsigned char[data_size]);
     if (data_) {
       data_size_ = data_size;
       return true;
@@ -42,11 +44,11 @@
     }
   }
 
-  virtual const unsigned char* GetData() const OVERRIDE { return data_.get(); }
+  virtual const unsigned char* GetData() const override { return data_.get(); }
 
-  virtual size_t GetDataSize() const OVERRIDE { return data_size_; }
+  virtual size_t GetDataSize() const override { return data_size_; }
 
-  virtual CefRefPtr<CefStreamReader> GetStreamReader() const OVERRIDE {
+  virtual CefRefPtr<CefStreamReader> GetStreamReader() const override {
     CefRefPtr<CefReadHandler> handler(new CefByteReadHandler(
         data_.get(), data_size_, const_cast<CefZipFile*>(this)));
     return CefStreamReader::CreateForHandler(handler);
@@ -56,10 +58,9 @@
 
  private:
   size_t data_size_;
-  scoped_ptr<unsigned char[]> data_;
+  std::unique_ptr<unsigned char[]> data_;
 
   IMPLEMENT_REFCOUNTING(CefZipFile);
-  DISALLOW_COPY_AND_ASSIGN(CefZipFile);
 };
 
 }  // namespace
@@ -76,11 +77,13 @@
   base::AutoLock lock_scope(lock_);
 
   CefRefPtr<CefZipReader> reader(CefZipReader::Create(stream));
-  if (!reader.get())
+  if (!reader.get()) {
     return 0;
+  }
 
-  if (!reader->MoveToFirstFile())
+  if (!reader->MoveToFirstFile()) {
     return 0;
+  }
 
   FileMap::iterator it;
   size_t count = 0;
@@ -92,22 +95,25 @@
       continue;
     }
 
-    if (!reader->OpenFile(password))
+    if (!reader->OpenFile(password)) {
       break;
+    }
 
     const CefString& name = ToLower(reader->GetFileName());
 
     it = contents_.find(name);
     if (it != contents_.end()) {
-      if (overwriteExisting)
+      if (overwriteExisting) {
         contents_.erase(it);
-      else  // Skip files that already exist.
+      } else {  // Skip files that already exist.
         continue;
+      }
     }
 
     CefRefPtr<CefZipFile> contents = new CefZipFile();
-    if (!contents->Initialize(size))
+    if (!contents->Initialize(size)) {
       continue;
+    }
     unsigned char* data = contents->data();
     size_t offset = 0;
 
@@ -148,8 +154,9 @@
     const CefString& fileName) const {
   base::AutoLock lock_scope(lock_);
   FileMap::const_iterator it = contents_.find(ToLower(fileName));
-  if (it != contents_.end())
+  if (it != contents_.end()) {
     return it->second;
+  }
   return nullptr;
 }
 
diff --git a/src/libcef_dll/wrapper/libcef_dll_dylib.cc b/src/libcef_dll/wrapper/libcef_dll_dylib.cc
index 58a257d..21065db 100644
--- a/src/libcef_dll/wrapper/libcef_dll_dylib.cc
+++ b/src/libcef_dll/wrapper/libcef_dll_dylib.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,12 +9,13 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=66b734973339eb27399083e978844f7d5a6a6c44$
+// $hash=bcad216e5fef8b9c10a895524f8b1201608138f9$
 //
 
 #include <dlfcn.h>
 #include <stdio.h>
 
+#include "include/base/cef_compiler_specific.h"
 #include "include/capi/cef_app_capi.h"
 #include "include/capi/cef_browser_capi.h"
 #include "include/capi/cef_command_line_capi.h"
@@ -22,12 +23,14 @@
 #include "include/capi/cef_crash_util_capi.h"
 #include "include/capi/cef_drag_data_capi.h"
 #include "include/capi/cef_file_util_capi.h"
+#include "include/capi/cef_i18n_util_capi.h"
 #include "include/capi/cef_image_capi.h"
 #include "include/capi/cef_media_router_capi.h"
 #include "include/capi/cef_menu_model_capi.h"
 #include "include/capi/cef_origin_whitelist_capi.h"
 #include "include/capi/cef_parser_capi.h"
 #include "include/capi/cef_path_util_capi.h"
+#include "include/capi/cef_preference_capi.h"
 #include "include/capi/cef_print_settings_capi.h"
 #include "include/capi/cef_process_message_capi.h"
 #include "include/capi/cef_process_util_capi.h"
@@ -37,6 +40,7 @@
 #include "include/capi/cef_response_capi.h"
 #include "include/capi/cef_scheme_capi.h"
 #include "include/capi/cef_server_capi.h"
+#include "include/capi/cef_shared_process_message_builder_capi.h"
 #include "include/capi/cef_ssl_info_capi.h"
 #include "include/capi/cef_stream_capi.h"
 #include "include/capi/cef_task_capi.h"
@@ -46,10 +50,10 @@
 #include "include/capi/cef_v8_capi.h"
 #include "include/capi/cef_values_capi.h"
 #include "include/capi/cef_waitable_event_capi.h"
-#include "include/capi/cef_web_plugin_capi.h"
 #include "include/capi/cef_xml_reader_capi.h"
 #include "include/capi/cef_zip_reader_capi.h"
 #include "include/capi/test/cef_test_helpers_capi.h"
+#include "include/capi/test/cef_test_server_capi.h"
 #include "include/capi/test/cef_translator_test_capi.h"
 #include "include/capi/views/cef_browser_view_capi.h"
 #include "include/capi/views/cef_display_capi.h"
@@ -85,653 +89,249 @@
   return ptr;
 }
 
-typedef int (*cef_execute_process_ptr)(const struct _cef_main_args_t*,
-                                       struct _cef_app_t*,
-                                       void*);
-typedef int (*cef_initialize_ptr)(const struct _cef_main_args_t*,
-                                  const struct _cef_settings_t*,
-                                  struct _cef_app_t*,
-                                  void*);
-typedef void (*cef_shutdown_ptr)();
-typedef void (*cef_do_message_loop_work_ptr)();
-typedef void (*cef_run_message_loop_ptr)();
-typedef void (*cef_quit_message_loop_ptr)();
-typedef void (*cef_set_osmodal_loop_ptr)(int);
-typedef void (*cef_enable_highdpi_support_ptr)();
-typedef int (*cef_crash_reporting_enabled_ptr)();
-typedef void (*cef_set_crash_key_value_ptr)(const cef_string_t*,
-                                            const cef_string_t*);
-typedef int (*cef_create_directory_ptr)(const cef_string_t*);
-typedef int (*cef_get_temp_directory_ptr)(cef_string_t*);
-typedef int (*cef_create_new_temp_directory_ptr)(const cef_string_t*,
-                                                 cef_string_t*);
-typedef int (*cef_create_temp_directory_in_directory_ptr)(const cef_string_t*,
-                                                          const cef_string_t*,
-                                                          cef_string_t*);
-typedef int (*cef_directory_exists_ptr)(const cef_string_t*);
-typedef int (*cef_delete_file_ptr)(const cef_string_t*, int);
-typedef int (*cef_zip_directory_ptr)(const cef_string_t*,
-                                     const cef_string_t*,
-                                     int);
-typedef void (*cef_load_crlsets_file_ptr)(const cef_string_t*);
-typedef int (*cef_add_cross_origin_whitelist_entry_ptr)(const cef_string_t*,
-                                                        const cef_string_t*,
-                                                        const cef_string_t*,
-                                                        int);
-typedef int (*cef_remove_cross_origin_whitelist_entry_ptr)(const cef_string_t*,
-                                                           const cef_string_t*,
-                                                           const cef_string_t*,
-                                                           int);
-typedef int (*cef_clear_cross_origin_whitelist_ptr)();
-typedef int (*cef_parse_url_ptr)(const cef_string_t*, struct _cef_urlparts_t*);
-typedef int (*cef_create_url_ptr)(const struct _cef_urlparts_t*, cef_string_t*);
-typedef cef_string_userfree_t (*cef_format_url_for_security_display_ptr)(
-    const cef_string_t*);
-typedef cef_string_userfree_t (*cef_get_mime_type_ptr)(const cef_string_t*);
-typedef void (*cef_get_extensions_for_mime_type_ptr)(const cef_string_t*,
-                                                     cef_string_list_t);
-typedef cef_string_userfree_t (*cef_base64encode_ptr)(const void*, size_t);
-typedef struct _cef_binary_value_t* (*cef_base64decode_ptr)(
-    const cef_string_t*);
-typedef cef_string_userfree_t (*cef_uriencode_ptr)(const cef_string_t*, int);
-typedef cef_string_userfree_t (*cef_uridecode_ptr)(const cef_string_t*,
-                                                   int,
-                                                   cef_uri_unescape_rule_t);
-typedef struct _cef_value_t* (*cef_parse_json_ptr)(const cef_string_t*,
-                                                   cef_json_parser_options_t);
-typedef struct _cef_value_t* (
-    *cef_parse_json_buffer_ptr)(const void*, size_t, cef_json_parser_options_t);
-typedef struct _cef_value_t* (*cef_parse_jsonand_return_error_ptr)(
-    const cef_string_t*,
-    cef_json_parser_options_t,
-    cef_json_parser_error_t*,
-    cef_string_t*);
-typedef cef_string_userfree_t (*cef_write_json_ptr)(struct _cef_value_t*,
-                                                    cef_json_writer_options_t);
-typedef int (*cef_get_path_ptr)(cef_path_key_t, cef_string_t*);
-typedef int (*cef_launch_process_ptr)(struct _cef_command_line_t*);
-typedef int (*cef_register_scheme_handler_factory_ptr)(
-    const cef_string_t*,
-    const cef_string_t*,
-    struct _cef_scheme_handler_factory_t*);
-typedef int (*cef_clear_scheme_handler_factories_ptr)();
-typedef int (*cef_is_cert_status_error_ptr)(cef_cert_status_t);
-typedef int (*cef_currently_on_ptr)(cef_thread_id_t);
-typedef int (*cef_post_task_ptr)(cef_thread_id_t, struct _cef_task_t*);
-typedef int (*cef_post_delayed_task_ptr)(cef_thread_id_t,
-                                         struct _cef_task_t*,
-                                         int64);
-typedef int (*cef_begin_tracing_ptr)(const cef_string_t*,
-                                     struct _cef_completion_callback_t*);
-typedef int (*cef_end_tracing_ptr)(const cef_string_t*,
-                                   struct _cef_end_tracing_callback_t*);
-typedef int64 (*cef_now_from_system_trace_time_ptr)();
-typedef int (*cef_register_extension_ptr)(const cef_string_t*,
-                                          const cef_string_t*,
-                                          struct _cef_v8handler_t*);
-typedef void (*cef_visit_web_plugin_info_ptr)(
-    struct _cef_web_plugin_info_visitor_t*);
-typedef void (*cef_refresh_web_plugins_ptr)();
-typedef void (*cef_unregister_internal_web_plugin_ptr)(const cef_string_t*);
-typedef void (*cef_register_web_plugin_crash_ptr)(const cef_string_t*);
-typedef void (*cef_is_web_plugin_unstable_ptr)(
-    const cef_string_t*,
-    struct _cef_web_plugin_unstable_callback_t*);
-typedef void (*cef_register_widevine_cdm_ptr)(
-    const cef_string_t*,
-    struct _cef_register_cdm_callback_t*);
-typedef void (*cef_execute_java_script_with_user_gesture_for_tests_ptr)(
-    struct _cef_frame_t*,
-    const cef_string_t*);
-typedef int (*cef_browser_host_create_browser_ptr)(
-    const struct _cef_window_info_t*,
-    struct _cef_client_t*,
-    const cef_string_t*,
-    const struct _cef_browser_settings_t*,
-    struct _cef_dictionary_value_t*,
-    struct _cef_request_context_t*);
-typedef struct _cef_browser_t* (*cef_browser_host_create_browser_sync_ptr)(
-    const struct _cef_window_info_t*,
-    struct _cef_client_t*,
-    const cef_string_t*,
-    const struct _cef_browser_settings_t*,
-    struct _cef_dictionary_value_t*,
-    struct _cef_request_context_t*);
-typedef struct _cef_command_line_t* (*cef_command_line_create_ptr)();
-typedef struct _cef_command_line_t* (*cef_command_line_get_global_ptr)();
-typedef struct _cef_cookie_manager_t* (
-    *cef_cookie_manager_get_global_manager_ptr)(
-    struct _cef_completion_callback_t*);
-typedef struct _cef_drag_data_t* (*cef_drag_data_create_ptr)();
-typedef struct _cef_image_t* (*cef_image_create_ptr)();
-typedef struct _cef_media_router_t* (*cef_media_router_get_global_ptr)();
-typedef struct _cef_menu_model_t* (*cef_menu_model_create_ptr)(
-    struct _cef_menu_model_delegate_t*);
-typedef struct _cef_print_settings_t* (*cef_print_settings_create_ptr)();
-typedef struct _cef_process_message_t* (*cef_process_message_create_ptr)(
-    const cef_string_t*);
-typedef struct _cef_request_t* (*cef_request_create_ptr)();
-typedef struct _cef_post_data_t* (*cef_post_data_create_ptr)();
-typedef struct _cef_post_data_element_t* (*cef_post_data_element_create_ptr)();
-typedef struct _cef_request_context_t* (
-    *cef_request_context_get_global_context_ptr)();
-typedef struct _cef_request_context_t* (
-    *cef_request_context_create_context_ptr)(
-    const struct _cef_request_context_settings_t*,
-    struct _cef_request_context_handler_t*);
-typedef struct _cef_request_context_t* (*cef_create_context_shared_ptr)(
-    struct _cef_request_context_t*,
-    struct _cef_request_context_handler_t*);
-typedef struct _cef_resource_bundle_t* (*cef_resource_bundle_get_global_ptr)();
-typedef struct _cef_response_t* (*cef_response_create_ptr)();
-typedef void (*cef_server_create_ptr)(const cef_string_t*,
-                                      uint16,
-                                      int,
-                                      struct _cef_server_handler_t*);
-typedef struct _cef_stream_reader_t* (*cef_stream_reader_create_for_file_ptr)(
-    const cef_string_t*);
-typedef struct _cef_stream_reader_t* (
-    *cef_stream_reader_create_for_data_ptr)(void*, size_t);
-typedef struct _cef_stream_reader_t* (
-    *cef_stream_reader_create_for_handler_ptr)(struct _cef_read_handler_t*);
-typedef struct _cef_stream_writer_t* (*cef_stream_writer_create_for_file_ptr)(
-    const cef_string_t*);
-typedef struct _cef_stream_writer_t* (
-    *cef_stream_writer_create_for_handler_ptr)(struct _cef_write_handler_t*);
-typedef struct _cef_task_runner_t* (
-    *cef_task_runner_get_for_current_thread_ptr)();
-typedef struct _cef_task_runner_t* (*cef_task_runner_get_for_thread_ptr)(
-    cef_thread_id_t);
-typedef struct _cef_thread_t* (*cef_thread_create_ptr)(const cef_string_t*,
-                                                       cef_thread_priority_t,
-                                                       cef_message_loop_type_t,
-                                                       int,
-                                                       cef_com_init_mode_t);
-typedef struct _cef_urlrequest_t* (*cef_urlrequest_create_ptr)(
-    struct _cef_request_t*,
-    struct _cef_urlrequest_client_t*,
-    struct _cef_request_context_t*);
-typedef struct _cef_v8context_t* (*cef_v8context_get_current_context_ptr)();
-typedef struct _cef_v8context_t* (*cef_v8context_get_entered_context_ptr)();
-typedef int (*cef_v8context_in_context_ptr)();
-typedef struct _cef_v8value_t* (*cef_v8value_create_undefined_ptr)();
-typedef struct _cef_v8value_t* (*cef_v8value_create_null_ptr)();
-typedef struct _cef_v8value_t* (*cef_v8value_create_bool_ptr)(int);
-typedef struct _cef_v8value_t* (*cef_v8value_create_int_ptr)(int32);
-typedef struct _cef_v8value_t* (*cef_v8value_create_uint_ptr)(uint32);
-typedef struct _cef_v8value_t* (*cef_v8value_create_double_ptr)(double);
-typedef struct _cef_v8value_t* (*cef_v8value_create_date_ptr)(
-    const cef_time_t*);
-typedef struct _cef_v8value_t* (*cef_v8value_create_string_ptr)(
-    const cef_string_t*);
-typedef struct _cef_v8value_t* (*cef_v8value_create_object_ptr)(
-    struct _cef_v8accessor_t*,
-    struct _cef_v8interceptor_t*);
-typedef struct _cef_v8value_t* (*cef_v8value_create_array_ptr)(int);
-typedef struct _cef_v8value_t* (*cef_v8value_create_array_buffer_ptr)(
-    void*,
-    size_t,
-    struct _cef_v8array_buffer_release_callback_t*);
-typedef struct _cef_v8value_t* (*cef_v8value_create_function_ptr)(
-    const cef_string_t*,
-    struct _cef_v8handler_t*);
-typedef struct _cef_v8stack_trace_t* (*cef_v8stack_trace_get_current_ptr)(int);
-typedef struct _cef_value_t* (*cef_value_create_ptr)();
-typedef struct _cef_binary_value_t* (*cef_binary_value_create_ptr)(const void*,
-                                                                   size_t);
-typedef struct _cef_dictionary_value_t* (*cef_dictionary_value_create_ptr)();
-typedef struct _cef_list_value_t* (*cef_list_value_create_ptr)();
-typedef struct _cef_waitable_event_t* (*cef_waitable_event_create_ptr)(int,
-                                                                       int);
-typedef struct _cef_xml_reader_t* (*cef_xml_reader_create_ptr)(
-    struct _cef_stream_reader_t*,
-    cef_xml_encoding_type_t,
-    const cef_string_t*);
-typedef struct _cef_zip_reader_t* (*cef_zip_reader_create_ptr)(
-    struct _cef_stream_reader_t*);
-typedef struct _cef_translator_test_t* (*cef_translator_test_create_ptr)();
-typedef struct _cef_translator_test_ref_ptr_library_t* (
-    *cef_translator_test_ref_ptr_library_create_ptr)(int);
-typedef struct _cef_translator_test_ref_ptr_library_child_t* (
-    *cef_translator_test_ref_ptr_library_child_create_ptr)(int, int);
-typedef struct _cef_translator_test_ref_ptr_library_child_child_t* (
-    *cef_translator_test_ref_ptr_library_child_child_create_ptr)(int, int, int);
-typedef struct _cef_translator_test_scoped_library_t* (
-    *cef_translator_test_scoped_library_create_ptr)(int);
-typedef struct _cef_translator_test_scoped_library_child_t* (
-    *cef_translator_test_scoped_library_child_create_ptr)(int, int);
-typedef struct _cef_translator_test_scoped_library_child_child_t* (
-    *cef_translator_test_scoped_library_child_child_create_ptr)(int, int, int);
-typedef struct _cef_browser_view_t* (*cef_browser_view_create_ptr)(
-    struct _cef_client_t*,
-    const cef_string_t*,
-    const struct _cef_browser_settings_t*,
-    struct _cef_dictionary_value_t*,
-    struct _cef_request_context_t*,
-    struct _cef_browser_view_delegate_t*);
-typedef struct _cef_browser_view_t* (*cef_browser_view_get_for_browser_ptr)(
-    struct _cef_browser_t*);
-typedef struct _cef_display_t* (*cef_display_get_primary_ptr)();
-typedef struct _cef_display_t* (
-    *cef_display_get_nearest_point_ptr)(const cef_point_t*, int);
-typedef struct _cef_display_t* (
-    *cef_display_get_matching_bounds_ptr)(const cef_rect_t*, int);
-typedef size_t (*cef_display_get_count_ptr)();
-typedef void (*cef_display_get_alls_ptr)(size_t*, struct _cef_display_t**);
-typedef struct _cef_label_button_t* (*cef_label_button_create_ptr)(
-    struct _cef_button_delegate_t*,
-    const cef_string_t*);
-typedef struct _cef_menu_button_t* (*cef_menu_button_create_ptr)(
-    struct _cef_menu_button_delegate_t*,
-    const cef_string_t*);
-typedef struct _cef_panel_t* (*cef_panel_create_ptr)(
-    struct _cef_panel_delegate_t*);
-typedef struct _cef_scroll_view_t* (*cef_scroll_view_create_ptr)(
-    struct _cef_view_delegate_t*);
-typedef struct _cef_textfield_t* (*cef_textfield_create_ptr)(
-    struct _cef_textfield_delegate_t*);
-typedef struct _cef_window_t* (*cef_window_create_top_level_ptr)(
-    struct _cef_window_delegate_t*);
-typedef const char* (*cef_api_hash_ptr)(int);
-typedef int (*cef_version_info_ptr)(int);
-typedef int (*cef_get_min_log_level_ptr)();
-typedef int (*cef_get_vlog_level_ptr)(const char*, size_t);
-typedef void (*cef_log_ptr)(const char*, int, int, const char*);
-typedef cef_string_list_t (*cef_string_list_alloc_ptr)();
-typedef size_t (*cef_string_list_size_ptr)(cef_string_list_t);
-typedef int (*cef_string_list_value_ptr)(cef_string_list_t,
-                                         size_t,
-                                         cef_string_t*);
-typedef void (*cef_string_list_append_ptr)(cef_string_list_t,
-                                           const cef_string_t*);
-typedef void (*cef_string_list_clear_ptr)(cef_string_list_t);
-typedef void (*cef_string_list_free_ptr)(cef_string_list_t);
-typedef cef_string_list_t (*cef_string_list_copy_ptr)(cef_string_list_t);
-typedef cef_string_map_t (*cef_string_map_alloc_ptr)();
-typedef size_t (*cef_string_map_size_ptr)(cef_string_map_t);
-typedef int (*cef_string_map_find_ptr)(cef_string_map_t,
-                                       const cef_string_t*,
-                                       cef_string_t*);
-typedef int (*cef_string_map_key_ptr)(cef_string_map_t, size_t, cef_string_t*);
-typedef int (*cef_string_map_value_ptr)(cef_string_map_t,
-                                        size_t,
-                                        cef_string_t*);
-typedef int (*cef_string_map_append_ptr)(cef_string_map_t,
-                                         const cef_string_t*,
-                                         const cef_string_t*);
-typedef void (*cef_string_map_clear_ptr)(cef_string_map_t);
-typedef void (*cef_string_map_free_ptr)(cef_string_map_t);
-typedef cef_string_multimap_t (*cef_string_multimap_alloc_ptr)();
-typedef size_t (*cef_string_multimap_size_ptr)(cef_string_multimap_t);
-typedef size_t (*cef_string_multimap_find_count_ptr)(cef_string_multimap_t,
-                                                     const cef_string_t*);
-typedef int (*cef_string_multimap_enumerate_ptr)(cef_string_multimap_t,
-                                                 const cef_string_t*,
-                                                 size_t,
-                                                 cef_string_t*);
-typedef int (*cef_string_multimap_key_ptr)(cef_string_multimap_t,
-                                           size_t,
-                                           cef_string_t*);
-typedef int (*cef_string_multimap_value_ptr)(cef_string_multimap_t,
-                                             size_t,
-                                             cef_string_t*);
-typedef int (*cef_string_multimap_append_ptr)(cef_string_multimap_t,
-                                              const cef_string_t*,
-                                              const cef_string_t*);
-typedef void (*cef_string_multimap_clear_ptr)(cef_string_multimap_t);
-typedef void (*cef_string_multimap_free_ptr)(cef_string_multimap_t);
-typedef int (*cef_string_wide_set_ptr)(const wchar_t*,
-                                       size_t,
-                                       cef_string_wide_t*,
-                                       int);
-typedef int (*cef_string_utf8_set_ptr)(const char*,
-                                       size_t,
-                                       cef_string_utf8_t*,
-                                       int);
-typedef int (*cef_string_utf16_set_ptr)(const char16*,
-                                        size_t,
-                                        cef_string_utf16_t*,
-                                        int);
-typedef void (*cef_string_wide_clear_ptr)(cef_string_wide_t*);
-typedef void (*cef_string_utf8_clear_ptr)(cef_string_utf8_t*);
-typedef void (*cef_string_utf16_clear_ptr)(cef_string_utf16_t*);
-typedef int (*cef_string_wide_cmp_ptr)(const cef_string_wide_t*,
-                                       const cef_string_wide_t*);
-typedef int (*cef_string_utf8_cmp_ptr)(const cef_string_utf8_t*,
-                                       const cef_string_utf8_t*);
-typedef int (*cef_string_utf16_cmp_ptr)(const cef_string_utf16_t*,
-                                        const cef_string_utf16_t*);
-typedef int (*cef_string_wide_to_utf8_ptr)(const wchar_t*,
-                                           size_t,
-                                           cef_string_utf8_t*);
-typedef int (*cef_string_utf8_to_wide_ptr)(const char*,
-                                           size_t,
-                                           cef_string_wide_t*);
-typedef int (*cef_string_wide_to_utf16_ptr)(const wchar_t*,
-                                            size_t,
-                                            cef_string_utf16_t*);
-typedef int (*cef_string_utf16_to_wide_ptr)(const char16*,
-                                            size_t,
-                                            cef_string_wide_t*);
-typedef int (*cef_string_utf8_to_utf16_ptr)(const char*,
-                                            size_t,
-                                            cef_string_utf16_t*);
-typedef int (*cef_string_utf16_to_utf8_ptr)(const char16*,
-                                            size_t,
-                                            cef_string_utf8_t*);
-typedef int (*cef_string_ascii_to_wide_ptr)(const char*,
-                                            size_t,
-                                            cef_string_wide_t*);
-typedef int (*cef_string_ascii_to_utf16_ptr)(const char*,
-                                             size_t,
-                                             cef_string_utf16_t*);
-typedef cef_string_userfree_wide_t (*cef_string_userfree_wide_alloc_ptr)();
-typedef cef_string_userfree_utf8_t (*cef_string_userfree_utf8_alloc_ptr)();
-typedef cef_string_userfree_utf16_t (*cef_string_userfree_utf16_alloc_ptr)();
-typedef void (*cef_string_userfree_wide_free_ptr)(cef_string_userfree_wide_t);
-typedef void (*cef_string_userfree_utf8_free_ptr)(cef_string_userfree_utf8_t);
-typedef void (*cef_string_userfree_utf16_free_ptr)(cef_string_userfree_utf16_t);
-typedef int (*cef_string_utf16_to_lower_ptr)(const char16*,
-                                             size_t,
-                                             cef_string_utf16_t*);
-typedef int (*cef_string_utf16_to_upper_ptr)(const char16*,
-                                             size_t,
-                                             cef_string_utf16_t*);
-typedef cef_platform_thread_id_t (*cef_get_current_platform_thread_id_ptr)();
-typedef cef_platform_thread_handle_t (
-    *cef_get_current_platform_thread_handle_ptr)();
-typedef int (*cef_time_to_timet_ptr)(const cef_time_t*, time_t*);
-typedef int (*cef_time_from_timet_ptr)(time_t, cef_time_t*);
-typedef int (*cef_time_to_doublet_ptr)(const cef_time_t*, double*);
-typedef int (*cef_time_from_doublet_ptr)(double, cef_time_t*);
-typedef int (*cef_time_now_ptr)(cef_time_t*);
-typedef int (*cef_time_delta_ptr)(const cef_time_t*,
-                                  const cef_time_t*,
-                                  long long*);
-typedef void (*cef_trace_event_instant_ptr)(const char*,
-                                            const char*,
-                                            const char*,
-                                            uint64,
-                                            const char*,
-                                            uint64,
-                                            int);
-typedef void (*cef_trace_event_begin_ptr)(const char*,
-                                          const char*,
-                                          const char*,
-                                          uint64,
-                                          const char*,
-                                          uint64,
-                                          int);
-typedef void (*cef_trace_event_end_ptr)(const char*,
-                                        const char*,
-                                        const char*,
-                                        uint64,
-                                        const char*,
-                                        uint64,
-                                        int);
-typedef void (*cef_trace_counter_ptr)(const char*,
-                                      const char*,
-                                      const char*,
-                                      uint64,
-                                      const char*,
-                                      uint64,
-                                      int);
-typedef void (*cef_trace_counter_id_ptr)(const char*,
-                                         const char*,
-                                         uint64,
-                                         const char*,
-                                         uint64,
-                                         const char*,
-                                         uint64,
-                                         int);
-typedef void (*cef_trace_event_async_begin_ptr)(const char*,
-                                                const char*,
-                                                uint64,
-                                                const char*,
-                                                uint64,
-                                                const char*,
-                                                uint64,
-                                                int);
-typedef void (*cef_trace_event_async_step_into_ptr)(const char*,
-                                                    const char*,
-                                                    uint64,
-                                                    uint64,
-                                                    const char*,
-                                                    uint64,
-                                                    int);
-typedef void (*cef_trace_event_async_step_past_ptr)(const char*,
-                                                    const char*,
-                                                    uint64,
-                                                    uint64,
-                                                    const char*,
-                                                    uint64,
-                                                    int);
-typedef void (*cef_trace_event_async_end_ptr)(const char*,
-                                              const char*,
-                                              uint64,
-                                              const char*,
-                                              uint64,
-                                              const char*,
-                                              uint64,
-                                              int);
-
 struct libcef_pointers {
-  cef_execute_process_ptr cef_execute_process;
-  cef_initialize_ptr cef_initialize;
-  cef_shutdown_ptr cef_shutdown;
-  cef_do_message_loop_work_ptr cef_do_message_loop_work;
-  cef_run_message_loop_ptr cef_run_message_loop;
-  cef_quit_message_loop_ptr cef_quit_message_loop;
-  cef_set_osmodal_loop_ptr cef_set_osmodal_loop;
-  cef_enable_highdpi_support_ptr cef_enable_highdpi_support;
-  cef_crash_reporting_enabled_ptr cef_crash_reporting_enabled;
-  cef_set_crash_key_value_ptr cef_set_crash_key_value;
-  cef_create_directory_ptr cef_create_directory;
-  cef_get_temp_directory_ptr cef_get_temp_directory;
-  cef_create_new_temp_directory_ptr cef_create_new_temp_directory;
-  cef_create_temp_directory_in_directory_ptr
+  decltype(&cef_execute_process) cef_execute_process;
+  decltype(&cef_initialize) cef_initialize;
+  decltype(&cef_shutdown) cef_shutdown;
+  decltype(&cef_do_message_loop_work) cef_do_message_loop_work;
+  decltype(&cef_run_message_loop) cef_run_message_loop;
+  decltype(&cef_quit_message_loop) cef_quit_message_loop;
+  decltype(&cef_crash_reporting_enabled) cef_crash_reporting_enabled;
+  decltype(&cef_set_crash_key_value) cef_set_crash_key_value;
+  decltype(&cef_create_directory) cef_create_directory;
+  decltype(&cef_get_temp_directory) cef_get_temp_directory;
+  decltype(&cef_create_new_temp_directory) cef_create_new_temp_directory;
+  decltype(&cef_create_temp_directory_in_directory)
       cef_create_temp_directory_in_directory;
-  cef_directory_exists_ptr cef_directory_exists;
-  cef_delete_file_ptr cef_delete_file;
-  cef_zip_directory_ptr cef_zip_directory;
-  cef_load_crlsets_file_ptr cef_load_crlsets_file;
-  cef_add_cross_origin_whitelist_entry_ptr cef_add_cross_origin_whitelist_entry;
-  cef_remove_cross_origin_whitelist_entry_ptr
+  decltype(&cef_directory_exists) cef_directory_exists;
+  decltype(&cef_delete_file) cef_delete_file;
+  decltype(&cef_zip_directory) cef_zip_directory;
+  decltype(&cef_load_crlsets_file) cef_load_crlsets_file;
+  decltype(&cef_is_rtl) cef_is_rtl;
+  decltype(&cef_add_cross_origin_whitelist_entry)
+      cef_add_cross_origin_whitelist_entry;
+  decltype(&cef_remove_cross_origin_whitelist_entry)
       cef_remove_cross_origin_whitelist_entry;
-  cef_clear_cross_origin_whitelist_ptr cef_clear_cross_origin_whitelist;
-  cef_parse_url_ptr cef_parse_url;
-  cef_create_url_ptr cef_create_url;
-  cef_format_url_for_security_display_ptr cef_format_url_for_security_display;
-  cef_get_mime_type_ptr cef_get_mime_type;
-  cef_get_extensions_for_mime_type_ptr cef_get_extensions_for_mime_type;
-  cef_base64encode_ptr cef_base64encode;
-  cef_base64decode_ptr cef_base64decode;
-  cef_uriencode_ptr cef_uriencode;
-  cef_uridecode_ptr cef_uridecode;
-  cef_parse_json_ptr cef_parse_json;
-  cef_parse_json_buffer_ptr cef_parse_json_buffer;
-  cef_parse_jsonand_return_error_ptr cef_parse_jsonand_return_error;
-  cef_write_json_ptr cef_write_json;
-  cef_get_path_ptr cef_get_path;
-  cef_launch_process_ptr cef_launch_process;
-  cef_register_scheme_handler_factory_ptr cef_register_scheme_handler_factory;
-  cef_clear_scheme_handler_factories_ptr cef_clear_scheme_handler_factories;
-  cef_is_cert_status_error_ptr cef_is_cert_status_error;
-  cef_currently_on_ptr cef_currently_on;
-  cef_post_task_ptr cef_post_task;
-  cef_post_delayed_task_ptr cef_post_delayed_task;
-  cef_begin_tracing_ptr cef_begin_tracing;
-  cef_end_tracing_ptr cef_end_tracing;
-  cef_now_from_system_trace_time_ptr cef_now_from_system_trace_time;
-  cef_register_extension_ptr cef_register_extension;
-  cef_visit_web_plugin_info_ptr cef_visit_web_plugin_info;
-  cef_refresh_web_plugins_ptr cef_refresh_web_plugins;
-  cef_unregister_internal_web_plugin_ptr cef_unregister_internal_web_plugin;
-  cef_register_web_plugin_crash_ptr cef_register_web_plugin_crash;
-  cef_is_web_plugin_unstable_ptr cef_is_web_plugin_unstable;
-  cef_register_widevine_cdm_ptr cef_register_widevine_cdm;
-  cef_execute_java_script_with_user_gesture_for_tests_ptr
+  decltype(&cef_clear_cross_origin_whitelist) cef_clear_cross_origin_whitelist;
+  decltype(&cef_resolve_url) cef_resolve_url;
+  decltype(&cef_parse_url) cef_parse_url;
+  decltype(&cef_create_url) cef_create_url;
+  decltype(&cef_format_url_for_security_display)
+      cef_format_url_for_security_display;
+  decltype(&cef_get_mime_type) cef_get_mime_type;
+  decltype(&cef_get_extensions_for_mime_type) cef_get_extensions_for_mime_type;
+  decltype(&cef_base64encode) cef_base64encode;
+  decltype(&cef_base64decode) cef_base64decode;
+  decltype(&cef_uriencode) cef_uriencode;
+  decltype(&cef_uridecode) cef_uridecode;
+  decltype(&cef_parse_json) cef_parse_json;
+  decltype(&cef_parse_json_buffer) cef_parse_json_buffer;
+  decltype(&cef_parse_jsonand_return_error) cef_parse_jsonand_return_error;
+  decltype(&cef_write_json) cef_write_json;
+  decltype(&cef_get_path) cef_get_path;
+  decltype(&cef_launch_process) cef_launch_process;
+  decltype(&cef_register_scheme_handler_factory)
+      cef_register_scheme_handler_factory;
+  decltype(&cef_clear_scheme_handler_factories)
+      cef_clear_scheme_handler_factories;
+  decltype(&cef_is_cert_status_error) cef_is_cert_status_error;
+  decltype(&cef_currently_on) cef_currently_on;
+  decltype(&cef_post_task) cef_post_task;
+  decltype(&cef_post_delayed_task) cef_post_delayed_task;
+  decltype(&cef_begin_tracing) cef_begin_tracing;
+  decltype(&cef_end_tracing) cef_end_tracing;
+  decltype(&cef_now_from_system_trace_time) cef_now_from_system_trace_time;
+  decltype(&cef_register_extension) cef_register_extension;
+  decltype(&cef_execute_java_script_with_user_gesture_for_tests)
       cef_execute_java_script_with_user_gesture_for_tests;
-  cef_browser_host_create_browser_ptr cef_browser_host_create_browser;
-  cef_browser_host_create_browser_sync_ptr cef_browser_host_create_browser_sync;
-  cef_command_line_create_ptr cef_command_line_create;
-  cef_command_line_get_global_ptr cef_command_line_get_global;
-  cef_cookie_manager_get_global_manager_ptr
+  decltype(&cef_set_data_directory_for_tests) cef_set_data_directory_for_tests;
+  decltype(&cef_browser_host_create_browser) cef_browser_host_create_browser;
+  decltype(&cef_browser_host_create_browser_sync)
+      cef_browser_host_create_browser_sync;
+  decltype(&cef_command_line_create) cef_command_line_create;
+  decltype(&cef_command_line_get_global) cef_command_line_get_global;
+  decltype(&cef_cookie_manager_get_global_manager)
       cef_cookie_manager_get_global_manager;
-  cef_drag_data_create_ptr cef_drag_data_create;
-  cef_image_create_ptr cef_image_create;
-  cef_media_router_get_global_ptr cef_media_router_get_global;
-  cef_menu_model_create_ptr cef_menu_model_create;
-  cef_print_settings_create_ptr cef_print_settings_create;
-  cef_process_message_create_ptr cef_process_message_create;
-  cef_request_create_ptr cef_request_create;
-  cef_post_data_create_ptr cef_post_data_create;
-  cef_post_data_element_create_ptr cef_post_data_element_create;
-  cef_request_context_get_global_context_ptr
+  decltype(&cef_drag_data_create) cef_drag_data_create;
+  decltype(&cef_image_create) cef_image_create;
+  decltype(&cef_media_router_get_global) cef_media_router_get_global;
+  decltype(&cef_menu_model_create) cef_menu_model_create;
+  decltype(&cef_preference_manager_get_global)
+      cef_preference_manager_get_global;
+  decltype(&cef_print_settings_create) cef_print_settings_create;
+  decltype(&cef_process_message_create) cef_process_message_create;
+  decltype(&cef_request_create) cef_request_create;
+  decltype(&cef_post_data_create) cef_post_data_create;
+  decltype(&cef_post_data_element_create) cef_post_data_element_create;
+  decltype(&cef_request_context_get_global_context)
       cef_request_context_get_global_context;
-  cef_request_context_create_context_ptr cef_request_context_create_context;
-  cef_create_context_shared_ptr cef_create_context_shared;
-  cef_resource_bundle_get_global_ptr cef_resource_bundle_get_global;
-  cef_response_create_ptr cef_response_create;
-  cef_server_create_ptr cef_server_create;
-  cef_stream_reader_create_for_file_ptr cef_stream_reader_create_for_file;
-  cef_stream_reader_create_for_data_ptr cef_stream_reader_create_for_data;
-  cef_stream_reader_create_for_handler_ptr cef_stream_reader_create_for_handler;
-  cef_stream_writer_create_for_file_ptr cef_stream_writer_create_for_file;
-  cef_stream_writer_create_for_handler_ptr cef_stream_writer_create_for_handler;
-  cef_task_runner_get_for_current_thread_ptr
+  decltype(&cef_request_context_create_context)
+      cef_request_context_create_context;
+  decltype(&cef_create_context_shared) cef_create_context_shared;
+  decltype(&cef_resource_bundle_get_global) cef_resource_bundle_get_global;
+  decltype(&cef_response_create) cef_response_create;
+  decltype(&cef_server_create) cef_server_create;
+  decltype(&cef_shared_process_message_builder_create)
+      cef_shared_process_message_builder_create;
+  decltype(&cef_stream_reader_create_for_file)
+      cef_stream_reader_create_for_file;
+  decltype(&cef_stream_reader_create_for_data)
+      cef_stream_reader_create_for_data;
+  decltype(&cef_stream_reader_create_for_handler)
+      cef_stream_reader_create_for_handler;
+  decltype(&cef_stream_writer_create_for_file)
+      cef_stream_writer_create_for_file;
+  decltype(&cef_stream_writer_create_for_handler)
+      cef_stream_writer_create_for_handler;
+  decltype(&cef_task_runner_get_for_current_thread)
       cef_task_runner_get_for_current_thread;
-  cef_task_runner_get_for_thread_ptr cef_task_runner_get_for_thread;
-  cef_thread_create_ptr cef_thread_create;
-  cef_urlrequest_create_ptr cef_urlrequest_create;
-  cef_v8context_get_current_context_ptr cef_v8context_get_current_context;
-  cef_v8context_get_entered_context_ptr cef_v8context_get_entered_context;
-  cef_v8context_in_context_ptr cef_v8context_in_context;
-  cef_v8value_create_undefined_ptr cef_v8value_create_undefined;
-  cef_v8value_create_null_ptr cef_v8value_create_null;
-  cef_v8value_create_bool_ptr cef_v8value_create_bool;
-  cef_v8value_create_int_ptr cef_v8value_create_int;
-  cef_v8value_create_uint_ptr cef_v8value_create_uint;
-  cef_v8value_create_double_ptr cef_v8value_create_double;
-  cef_v8value_create_date_ptr cef_v8value_create_date;
-  cef_v8value_create_string_ptr cef_v8value_create_string;
-  cef_v8value_create_object_ptr cef_v8value_create_object;
-  cef_v8value_create_array_ptr cef_v8value_create_array;
-  cef_v8value_create_array_buffer_ptr cef_v8value_create_array_buffer;
-  cef_v8value_create_function_ptr cef_v8value_create_function;
-  cef_v8stack_trace_get_current_ptr cef_v8stack_trace_get_current;
-  cef_value_create_ptr cef_value_create;
-  cef_binary_value_create_ptr cef_binary_value_create;
-  cef_dictionary_value_create_ptr cef_dictionary_value_create;
-  cef_list_value_create_ptr cef_list_value_create;
-  cef_waitable_event_create_ptr cef_waitable_event_create;
-  cef_xml_reader_create_ptr cef_xml_reader_create;
-  cef_zip_reader_create_ptr cef_zip_reader_create;
-  cef_translator_test_create_ptr cef_translator_test_create;
-  cef_translator_test_ref_ptr_library_create_ptr
+  decltype(&cef_task_runner_get_for_thread) cef_task_runner_get_for_thread;
+  decltype(&cef_thread_create) cef_thread_create;
+  decltype(&cef_urlrequest_create) cef_urlrequest_create;
+  decltype(&cef_v8context_get_current_context)
+      cef_v8context_get_current_context;
+  decltype(&cef_v8context_get_entered_context)
+      cef_v8context_get_entered_context;
+  decltype(&cef_v8context_in_context) cef_v8context_in_context;
+  decltype(&cef_v8value_create_undefined) cef_v8value_create_undefined;
+  decltype(&cef_v8value_create_null) cef_v8value_create_null;
+  decltype(&cef_v8value_create_bool) cef_v8value_create_bool;
+  decltype(&cef_v8value_create_int) cef_v8value_create_int;
+  decltype(&cef_v8value_create_uint) cef_v8value_create_uint;
+  decltype(&cef_v8value_create_double) cef_v8value_create_double;
+  decltype(&cef_v8value_create_date) cef_v8value_create_date;
+  decltype(&cef_v8value_create_string) cef_v8value_create_string;
+  decltype(&cef_v8value_create_object) cef_v8value_create_object;
+  decltype(&cef_v8value_create_array) cef_v8value_create_array;
+  decltype(&cef_v8value_create_array_buffer) cef_v8value_create_array_buffer;
+  decltype(&cef_v8value_create_function) cef_v8value_create_function;
+  decltype(&cef_v8value_create_promise) cef_v8value_create_promise;
+  decltype(&cef_v8stack_trace_get_current) cef_v8stack_trace_get_current;
+  decltype(&cef_value_create) cef_value_create;
+  decltype(&cef_binary_value_create) cef_binary_value_create;
+  decltype(&cef_dictionary_value_create) cef_dictionary_value_create;
+  decltype(&cef_list_value_create) cef_list_value_create;
+  decltype(&cef_waitable_event_create) cef_waitable_event_create;
+  decltype(&cef_xml_reader_create) cef_xml_reader_create;
+  decltype(&cef_zip_reader_create) cef_zip_reader_create;
+  decltype(&cef_test_server_create_and_start) cef_test_server_create_and_start;
+  decltype(&cef_translator_test_create) cef_translator_test_create;
+  decltype(&cef_translator_test_ref_ptr_library_create)
       cef_translator_test_ref_ptr_library_create;
-  cef_translator_test_ref_ptr_library_child_create_ptr
+  decltype(&cef_translator_test_ref_ptr_library_child_create)
       cef_translator_test_ref_ptr_library_child_create;
-  cef_translator_test_ref_ptr_library_child_child_create_ptr
+  decltype(&cef_translator_test_ref_ptr_library_child_child_create)
       cef_translator_test_ref_ptr_library_child_child_create;
-  cef_translator_test_scoped_library_create_ptr
+  decltype(&cef_translator_test_scoped_library_create)
       cef_translator_test_scoped_library_create;
-  cef_translator_test_scoped_library_child_create_ptr
+  decltype(&cef_translator_test_scoped_library_child_create)
       cef_translator_test_scoped_library_child_create;
-  cef_translator_test_scoped_library_child_child_create_ptr
+  decltype(&cef_translator_test_scoped_library_child_child_create)
       cef_translator_test_scoped_library_child_child_create;
-  cef_browser_view_create_ptr cef_browser_view_create;
-  cef_browser_view_get_for_browser_ptr cef_browser_view_get_for_browser;
-  cef_display_get_primary_ptr cef_display_get_primary;
-  cef_display_get_nearest_point_ptr cef_display_get_nearest_point;
-  cef_display_get_matching_bounds_ptr cef_display_get_matching_bounds;
-  cef_display_get_count_ptr cef_display_get_count;
-  cef_display_get_alls_ptr cef_display_get_alls;
-  cef_label_button_create_ptr cef_label_button_create;
-  cef_menu_button_create_ptr cef_menu_button_create;
-  cef_panel_create_ptr cef_panel_create;
-  cef_scroll_view_create_ptr cef_scroll_view_create;
-  cef_textfield_create_ptr cef_textfield_create;
-  cef_window_create_top_level_ptr cef_window_create_top_level;
-  cef_api_hash_ptr cef_api_hash;
-  cef_version_info_ptr cef_version_info;
-  cef_get_min_log_level_ptr cef_get_min_log_level;
-  cef_get_vlog_level_ptr cef_get_vlog_level;
-  cef_log_ptr cef_log;
-  cef_string_list_alloc_ptr cef_string_list_alloc;
-  cef_string_list_size_ptr cef_string_list_size;
-  cef_string_list_value_ptr cef_string_list_value;
-  cef_string_list_append_ptr cef_string_list_append;
-  cef_string_list_clear_ptr cef_string_list_clear;
-  cef_string_list_free_ptr cef_string_list_free;
-  cef_string_list_copy_ptr cef_string_list_copy;
-  cef_string_map_alloc_ptr cef_string_map_alloc;
-  cef_string_map_size_ptr cef_string_map_size;
-  cef_string_map_find_ptr cef_string_map_find;
-  cef_string_map_key_ptr cef_string_map_key;
-  cef_string_map_value_ptr cef_string_map_value;
-  cef_string_map_append_ptr cef_string_map_append;
-  cef_string_map_clear_ptr cef_string_map_clear;
-  cef_string_map_free_ptr cef_string_map_free;
-  cef_string_multimap_alloc_ptr cef_string_multimap_alloc;
-  cef_string_multimap_size_ptr cef_string_multimap_size;
-  cef_string_multimap_find_count_ptr cef_string_multimap_find_count;
-  cef_string_multimap_enumerate_ptr cef_string_multimap_enumerate;
-  cef_string_multimap_key_ptr cef_string_multimap_key;
-  cef_string_multimap_value_ptr cef_string_multimap_value;
-  cef_string_multimap_append_ptr cef_string_multimap_append;
-  cef_string_multimap_clear_ptr cef_string_multimap_clear;
-  cef_string_multimap_free_ptr cef_string_multimap_free;
-  cef_string_wide_set_ptr cef_string_wide_set;
-  cef_string_utf8_set_ptr cef_string_utf8_set;
-  cef_string_utf16_set_ptr cef_string_utf16_set;
-  cef_string_wide_clear_ptr cef_string_wide_clear;
-  cef_string_utf8_clear_ptr cef_string_utf8_clear;
-  cef_string_utf16_clear_ptr cef_string_utf16_clear;
-  cef_string_wide_cmp_ptr cef_string_wide_cmp;
-  cef_string_utf8_cmp_ptr cef_string_utf8_cmp;
-  cef_string_utf16_cmp_ptr cef_string_utf16_cmp;
-  cef_string_wide_to_utf8_ptr cef_string_wide_to_utf8;
-  cef_string_utf8_to_wide_ptr cef_string_utf8_to_wide;
-  cef_string_wide_to_utf16_ptr cef_string_wide_to_utf16;
-  cef_string_utf16_to_wide_ptr cef_string_utf16_to_wide;
-  cef_string_utf8_to_utf16_ptr cef_string_utf8_to_utf16;
-  cef_string_utf16_to_utf8_ptr cef_string_utf16_to_utf8;
-  cef_string_ascii_to_wide_ptr cef_string_ascii_to_wide;
-  cef_string_ascii_to_utf16_ptr cef_string_ascii_to_utf16;
-  cef_string_userfree_wide_alloc_ptr cef_string_userfree_wide_alloc;
-  cef_string_userfree_utf8_alloc_ptr cef_string_userfree_utf8_alloc;
-  cef_string_userfree_utf16_alloc_ptr cef_string_userfree_utf16_alloc;
-  cef_string_userfree_wide_free_ptr cef_string_userfree_wide_free;
-  cef_string_userfree_utf8_free_ptr cef_string_userfree_utf8_free;
-  cef_string_userfree_utf16_free_ptr cef_string_userfree_utf16_free;
-  cef_string_utf16_to_lower_ptr cef_string_utf16_to_lower;
-  cef_string_utf16_to_upper_ptr cef_string_utf16_to_upper;
-  cef_get_current_platform_thread_id_ptr cef_get_current_platform_thread_id;
-  cef_get_current_platform_thread_handle_ptr
+  decltype(&cef_browser_view_create) cef_browser_view_create;
+  decltype(&cef_browser_view_get_for_browser) cef_browser_view_get_for_browser;
+  decltype(&cef_display_get_primary) cef_display_get_primary;
+  decltype(&cef_display_get_nearest_point) cef_display_get_nearest_point;
+  decltype(&cef_display_get_matching_bounds) cef_display_get_matching_bounds;
+  decltype(&cef_display_get_count) cef_display_get_count;
+  decltype(&cef_display_get_alls) cef_display_get_alls;
+  decltype(&cef_display_convert_screen_point_to_pixels)
+      cef_display_convert_screen_point_to_pixels;
+  decltype(&cef_display_convert_screen_point_from_pixels)
+      cef_display_convert_screen_point_from_pixels;
+  decltype(&cef_display_convert_screen_rect_to_pixels)
+      cef_display_convert_screen_rect_to_pixels;
+  decltype(&cef_display_convert_screen_rect_from_pixels)
+      cef_display_convert_screen_rect_from_pixels;
+  decltype(&cef_label_button_create) cef_label_button_create;
+  decltype(&cef_menu_button_create) cef_menu_button_create;
+  decltype(&cef_panel_create) cef_panel_create;
+  decltype(&cef_scroll_view_create) cef_scroll_view_create;
+  decltype(&cef_textfield_create) cef_textfield_create;
+  decltype(&cef_window_create_top_level) cef_window_create_top_level;
+  decltype(&cef_api_hash) cef_api_hash;
+  decltype(&cef_version_info) cef_version_info;
+  decltype(&cef_get_min_log_level) cef_get_min_log_level;
+  decltype(&cef_get_vlog_level) cef_get_vlog_level;
+  decltype(&cef_log) cef_log;
+  decltype(&cef_string_list_alloc) cef_string_list_alloc;
+  decltype(&cef_string_list_size) cef_string_list_size;
+  decltype(&cef_string_list_value) cef_string_list_value;
+  decltype(&cef_string_list_append) cef_string_list_append;
+  decltype(&cef_string_list_clear) cef_string_list_clear;
+  decltype(&cef_string_list_free) cef_string_list_free;
+  decltype(&cef_string_list_copy) cef_string_list_copy;
+  decltype(&cef_string_map_alloc) cef_string_map_alloc;
+  decltype(&cef_string_map_size) cef_string_map_size;
+  decltype(&cef_string_map_find) cef_string_map_find;
+  decltype(&cef_string_map_key) cef_string_map_key;
+  decltype(&cef_string_map_value) cef_string_map_value;
+  decltype(&cef_string_map_append) cef_string_map_append;
+  decltype(&cef_string_map_clear) cef_string_map_clear;
+  decltype(&cef_string_map_free) cef_string_map_free;
+  decltype(&cef_string_multimap_alloc) cef_string_multimap_alloc;
+  decltype(&cef_string_multimap_size) cef_string_multimap_size;
+  decltype(&cef_string_multimap_find_count) cef_string_multimap_find_count;
+  decltype(&cef_string_multimap_enumerate) cef_string_multimap_enumerate;
+  decltype(&cef_string_multimap_key) cef_string_multimap_key;
+  decltype(&cef_string_multimap_value) cef_string_multimap_value;
+  decltype(&cef_string_multimap_append) cef_string_multimap_append;
+  decltype(&cef_string_multimap_clear) cef_string_multimap_clear;
+  decltype(&cef_string_multimap_free) cef_string_multimap_free;
+  decltype(&cef_string_wide_set) cef_string_wide_set;
+  decltype(&cef_string_utf8_set) cef_string_utf8_set;
+  decltype(&cef_string_utf16_set) cef_string_utf16_set;
+  decltype(&cef_string_wide_clear) cef_string_wide_clear;
+  decltype(&cef_string_utf8_clear) cef_string_utf8_clear;
+  decltype(&cef_string_utf16_clear) cef_string_utf16_clear;
+  decltype(&cef_string_wide_cmp) cef_string_wide_cmp;
+  decltype(&cef_string_utf8_cmp) cef_string_utf8_cmp;
+  decltype(&cef_string_utf16_cmp) cef_string_utf16_cmp;
+  decltype(&cef_string_wide_to_utf8) cef_string_wide_to_utf8;
+  decltype(&cef_string_utf8_to_wide) cef_string_utf8_to_wide;
+  decltype(&cef_string_wide_to_utf16) cef_string_wide_to_utf16;
+  decltype(&cef_string_utf16_to_wide) cef_string_utf16_to_wide;
+  decltype(&cef_string_utf8_to_utf16) cef_string_utf8_to_utf16;
+  decltype(&cef_string_utf16_to_utf8) cef_string_utf16_to_utf8;
+  decltype(&cef_string_ascii_to_wide) cef_string_ascii_to_wide;
+  decltype(&cef_string_ascii_to_utf16) cef_string_ascii_to_utf16;
+  decltype(&cef_string_userfree_wide_alloc) cef_string_userfree_wide_alloc;
+  decltype(&cef_string_userfree_utf8_alloc) cef_string_userfree_utf8_alloc;
+  decltype(&cef_string_userfree_utf16_alloc) cef_string_userfree_utf16_alloc;
+  decltype(&cef_string_userfree_wide_free) cef_string_userfree_wide_free;
+  decltype(&cef_string_userfree_utf8_free) cef_string_userfree_utf8_free;
+  decltype(&cef_string_userfree_utf16_free) cef_string_userfree_utf16_free;
+  decltype(&cef_string_utf16_to_lower) cef_string_utf16_to_lower;
+  decltype(&cef_string_utf16_to_upper) cef_string_utf16_to_upper;
+  decltype(&cef_get_current_platform_thread_id)
+      cef_get_current_platform_thread_id;
+  decltype(&cef_get_current_platform_thread_handle)
       cef_get_current_platform_thread_handle;
-  cef_time_to_timet_ptr cef_time_to_timet;
-  cef_time_from_timet_ptr cef_time_from_timet;
-  cef_time_to_doublet_ptr cef_time_to_doublet;
-  cef_time_from_doublet_ptr cef_time_from_doublet;
-  cef_time_now_ptr cef_time_now;
-  cef_time_delta_ptr cef_time_delta;
-  cef_trace_event_instant_ptr cef_trace_event_instant;
-  cef_trace_event_begin_ptr cef_trace_event_begin;
-  cef_trace_event_end_ptr cef_trace_event_end;
-  cef_trace_counter_ptr cef_trace_counter;
-  cef_trace_counter_id_ptr cef_trace_counter_id;
-  cef_trace_event_async_begin_ptr cef_trace_event_async_begin;
-  cef_trace_event_async_step_into_ptr cef_trace_event_async_step_into;
-  cef_trace_event_async_step_past_ptr cef_trace_event_async_step_past;
-  cef_trace_event_async_end_ptr cef_trace_event_async_end;
+  decltype(&cef_time_to_timet) cef_time_to_timet;
+  decltype(&cef_time_from_timet) cef_time_from_timet;
+  decltype(&cef_time_to_doublet) cef_time_to_doublet;
+  decltype(&cef_time_from_doublet) cef_time_from_doublet;
+  decltype(&cef_time_now) cef_time_now;
+  decltype(&cef_basetime_now) cef_basetime_now;
+  decltype(&cef_time_delta) cef_time_delta;
+  decltype(&cef_time_to_basetime) cef_time_to_basetime;
+  decltype(&cef_time_from_basetime) cef_time_from_basetime;
+  decltype(&cef_trace_event_instant) cef_trace_event_instant;
+  decltype(&cef_trace_event_begin) cef_trace_event_begin;
+  decltype(&cef_trace_event_end) cef_trace_event_end;
+  decltype(&cef_trace_counter) cef_trace_counter;
+  decltype(&cef_trace_counter_id) cef_trace_counter_id;
+  decltype(&cef_trace_event_async_begin) cef_trace_event_async_begin;
+  decltype(&cef_trace_event_async_step_into) cef_trace_event_async_step_into;
+  decltype(&cef_trace_event_async_step_past) cef_trace_event_async_step_past;
+  decltype(&cef_trace_event_async_end) cef_trace_event_async_end;
 
 } g_libcef_pointers = {0};
 
-#define INIT_ENTRY(name)                                            \
-  g_libcef_pointers.name = (name##_ptr)libcef_get_ptr(path, #name); \
-  if (!g_libcef_pointers.name) {                                    \
-    return 0;                                                       \
+#define INIT_ENTRY(name)                                                 \
+  g_libcef_pointers.name = (decltype(&name))libcef_get_ptr(path, #name); \
+  if (!g_libcef_pointers.name) {                                         \
+    return 0;                                                            \
   }
 
 int libcef_init_pointers(const char* path) {
@@ -741,8 +341,6 @@
   INIT_ENTRY(cef_do_message_loop_work);
   INIT_ENTRY(cef_run_message_loop);
   INIT_ENTRY(cef_quit_message_loop);
-  INIT_ENTRY(cef_set_osmodal_loop);
-  INIT_ENTRY(cef_enable_highdpi_support);
   INIT_ENTRY(cef_crash_reporting_enabled);
   INIT_ENTRY(cef_set_crash_key_value);
   INIT_ENTRY(cef_create_directory);
@@ -753,9 +351,11 @@
   INIT_ENTRY(cef_delete_file);
   INIT_ENTRY(cef_zip_directory);
   INIT_ENTRY(cef_load_crlsets_file);
+  INIT_ENTRY(cef_is_rtl);
   INIT_ENTRY(cef_add_cross_origin_whitelist_entry);
   INIT_ENTRY(cef_remove_cross_origin_whitelist_entry);
   INIT_ENTRY(cef_clear_cross_origin_whitelist);
+  INIT_ENTRY(cef_resolve_url);
   INIT_ENTRY(cef_parse_url);
   INIT_ENTRY(cef_create_url);
   INIT_ENTRY(cef_format_url_for_security_display);
@@ -781,13 +381,8 @@
   INIT_ENTRY(cef_end_tracing);
   INIT_ENTRY(cef_now_from_system_trace_time);
   INIT_ENTRY(cef_register_extension);
-  INIT_ENTRY(cef_visit_web_plugin_info);
-  INIT_ENTRY(cef_refresh_web_plugins);
-  INIT_ENTRY(cef_unregister_internal_web_plugin);
-  INIT_ENTRY(cef_register_web_plugin_crash);
-  INIT_ENTRY(cef_is_web_plugin_unstable);
-  INIT_ENTRY(cef_register_widevine_cdm);
   INIT_ENTRY(cef_execute_java_script_with_user_gesture_for_tests);
+  INIT_ENTRY(cef_set_data_directory_for_tests);
   INIT_ENTRY(cef_browser_host_create_browser);
   INIT_ENTRY(cef_browser_host_create_browser_sync);
   INIT_ENTRY(cef_command_line_create);
@@ -797,6 +392,7 @@
   INIT_ENTRY(cef_image_create);
   INIT_ENTRY(cef_media_router_get_global);
   INIT_ENTRY(cef_menu_model_create);
+  INIT_ENTRY(cef_preference_manager_get_global);
   INIT_ENTRY(cef_print_settings_create);
   INIT_ENTRY(cef_process_message_create);
   INIT_ENTRY(cef_request_create);
@@ -808,6 +404,7 @@
   INIT_ENTRY(cef_resource_bundle_get_global);
   INIT_ENTRY(cef_response_create);
   INIT_ENTRY(cef_server_create);
+  INIT_ENTRY(cef_shared_process_message_builder_create);
   INIT_ENTRY(cef_stream_reader_create_for_file);
   INIT_ENTRY(cef_stream_reader_create_for_data);
   INIT_ENTRY(cef_stream_reader_create_for_handler);
@@ -832,6 +429,7 @@
   INIT_ENTRY(cef_v8value_create_array);
   INIT_ENTRY(cef_v8value_create_array_buffer);
   INIT_ENTRY(cef_v8value_create_function);
+  INIT_ENTRY(cef_v8value_create_promise);
   INIT_ENTRY(cef_v8stack_trace_get_current);
   INIT_ENTRY(cef_value_create);
   INIT_ENTRY(cef_binary_value_create);
@@ -840,6 +438,7 @@
   INIT_ENTRY(cef_waitable_event_create);
   INIT_ENTRY(cef_xml_reader_create);
   INIT_ENTRY(cef_zip_reader_create);
+  INIT_ENTRY(cef_test_server_create_and_start);
   INIT_ENTRY(cef_translator_test_create);
   INIT_ENTRY(cef_translator_test_ref_ptr_library_create);
   INIT_ENTRY(cef_translator_test_ref_ptr_library_child_create);
@@ -854,6 +453,10 @@
   INIT_ENTRY(cef_display_get_matching_bounds);
   INIT_ENTRY(cef_display_get_count);
   INIT_ENTRY(cef_display_get_alls);
+  INIT_ENTRY(cef_display_convert_screen_point_to_pixels);
+  INIT_ENTRY(cef_display_convert_screen_point_from_pixels);
+  INIT_ENTRY(cef_display_convert_screen_rect_to_pixels);
+  INIT_ENTRY(cef_display_convert_screen_rect_from_pixels);
   INIT_ENTRY(cef_label_button_create);
   INIT_ENTRY(cef_menu_button_create);
   INIT_ENTRY(cef_panel_create);
@@ -921,7 +524,10 @@
   INIT_ENTRY(cef_time_to_doublet);
   INIT_ENTRY(cef_time_from_doublet);
   INIT_ENTRY(cef_time_now);
+  INIT_ENTRY(cef_basetime_now);
   INIT_ENTRY(cef_time_delta);
+  INIT_ENTRY(cef_time_to_basetime);
+  INIT_ENTRY(cef_time_from_basetime);
   INIT_ENTRY(cef_trace_event_instant);
   INIT_ENTRY(cef_trace_event_begin);
   INIT_ENTRY(cef_trace_event_end);
@@ -937,8 +543,9 @@
 }  // namespace
 
 int cef_load_library(const char* path) {
-  if (g_libcef_handle)
+  if (g_libcef_handle) {
     return 0;
+  }
 
   g_libcef_handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL | RTLD_FIRST);
   if (!g_libcef_handle) {
@@ -967,7 +574,7 @@
 }
 
 NO_SANITIZE("cfi-icall")
-int cef_execute_process(const struct _cef_main_args_t* args,
+int cef_execute_process(const cef_main_args_t* args,
                         struct _cef_app_t* application,
                         void* windows_sandbox_info) {
   return g_libcef_pointers.cef_execute_process(args, application,
@@ -975,7 +582,7 @@
 }
 
 NO_SANITIZE("cfi-icall")
-int cef_initialize(const struct _cef_main_args_t* args,
+int cef_initialize(const cef_main_args_t* args,
                    const struct _cef_settings_t* settings,
                    struct _cef_app_t* application,
                    void* windows_sandbox_info) {
@@ -999,14 +606,6 @@
   g_libcef_pointers.cef_quit_message_loop();
 }
 
-NO_SANITIZE("cfi-icall") void cef_set_osmodal_loop(int osModalLoop) {
-  g_libcef_pointers.cef_set_osmodal_loop(osModalLoop);
-}
-
-NO_SANITIZE("cfi-icall") void cef_enable_highdpi_support() {
-  g_libcef_pointers.cef_enable_highdpi_support();
-}
-
 NO_SANITIZE("cfi-icall") int cef_crash_reporting_enabled() {
   return g_libcef_pointers.cef_crash_reporting_enabled();
 }
@@ -1061,6 +660,10 @@
   g_libcef_pointers.cef_load_crlsets_file(path);
 }
 
+NO_SANITIZE("cfi-icall") int cef_is_rtl() {
+  return g_libcef_pointers.cef_is_rtl();
+}
+
 NO_SANITIZE("cfi-icall")
 int cef_add_cross_origin_whitelist_entry(const cef_string_t* source_origin,
                                          const cef_string_t* target_protocol,
@@ -1084,6 +687,14 @@
 }
 
 NO_SANITIZE("cfi-icall")
+int cef_resolve_url(const cef_string_t* base_url,
+                    const cef_string_t* relative_url,
+                    cef_string_t* resolved_url) {
+  return g_libcef_pointers.cef_resolve_url(base_url, relative_url,
+                                           resolved_url);
+}
+
+NO_SANITIZE("cfi-icall")
 int cef_parse_url(const cef_string_t* url, struct _cef_urlparts_t* parts) {
   return g_libcef_pointers.cef_parse_url(url, parts);
 }
@@ -1149,10 +760,9 @@
 struct _cef_value_t* cef_parse_jsonand_return_error(
     const cef_string_t* json_string,
     cef_json_parser_options_t options,
-    cef_json_parser_error_t* error_code_out,
     cef_string_t* error_msg_out) {
-  return g_libcef_pointers.cef_parse_jsonand_return_error(
-      json_string, options, error_code_out, error_msg_out);
+  return g_libcef_pointers.cef_parse_jsonand_return_error(json_string, options,
+                                                          error_msg_out);
 }
 
 NO_SANITIZE("cfi-icall")
@@ -1201,7 +811,7 @@
 NO_SANITIZE("cfi-icall")
 int cef_post_delayed_task(cef_thread_id_t threadId,
                           struct _cef_task_t* task,
-                          int64 delay_ms) {
+                          int64_t delay_ms) {
   return g_libcef_pointers.cef_post_delayed_task(threadId, task, delay_ms);
 }
 
@@ -1217,7 +827,7 @@
   return g_libcef_pointers.cef_end_tracing(tracing_file, callback);
 }
 
-NO_SANITIZE("cfi-icall") int64 cef_now_from_system_trace_time() {
+NO_SANITIZE("cfi-icall") int64_t cef_now_from_system_trace_time() {
   return g_libcef_pointers.cef_now_from_system_trace_time();
 }
 
@@ -1230,38 +840,6 @@
 }
 
 NO_SANITIZE("cfi-icall")
-void cef_visit_web_plugin_info(struct _cef_web_plugin_info_visitor_t* visitor) {
-  g_libcef_pointers.cef_visit_web_plugin_info(visitor);
-}
-
-NO_SANITIZE("cfi-icall") void cef_refresh_web_plugins() {
-  g_libcef_pointers.cef_refresh_web_plugins();
-}
-
-NO_SANITIZE("cfi-icall")
-void cef_unregister_internal_web_plugin(const cef_string_t* path) {
-  g_libcef_pointers.cef_unregister_internal_web_plugin(path);
-}
-
-NO_SANITIZE("cfi-icall")
-void cef_register_web_plugin_crash(const cef_string_t* path) {
-  g_libcef_pointers.cef_register_web_plugin_crash(path);
-}
-
-NO_SANITIZE("cfi-icall")
-void cef_is_web_plugin_unstable(
-    const cef_string_t* path,
-    struct _cef_web_plugin_unstable_callback_t* callback) {
-  g_libcef_pointers.cef_is_web_plugin_unstable(path, callback);
-}
-
-NO_SANITIZE("cfi-icall")
-void cef_register_widevine_cdm(const cef_string_t* path,
-                               struct _cef_register_cdm_callback_t* callback) {
-  g_libcef_pointers.cef_register_widevine_cdm(path, callback);
-}
-
-NO_SANITIZE("cfi-icall")
 void cef_execute_java_script_with_user_gesture_for_tests(
     struct _cef_frame_t* frame,
     const cef_string_t* javascript) {
@@ -1270,6 +848,11 @@
 }
 
 NO_SANITIZE("cfi-icall")
+void cef_set_data_directory_for_tests(const cef_string_t* dir) {
+  g_libcef_pointers.cef_set_data_directory_for_tests(dir);
+}
+
+NO_SANITIZE("cfi-icall")
 int cef_browser_host_create_browser(
     const struct _cef_window_info_t* windowInfo,
     struct _cef_client_t* client,
@@ -1317,8 +900,9 @@
 }
 
 NO_SANITIZE("cfi-icall")
-struct _cef_media_router_t* cef_media_router_get_global() {
-  return g_libcef_pointers.cef_media_router_get_global();
+struct _cef_media_router_t* cef_media_router_get_global(
+    struct _cef_completion_callback_t* callback) {
+  return g_libcef_pointers.cef_media_router_get_global(callback);
 }
 
 NO_SANITIZE("cfi-icall")
@@ -1328,6 +912,11 @@
 }
 
 NO_SANITIZE("cfi-icall")
+struct _cef_preference_manager_t* cef_preference_manager_get_global() {
+  return g_libcef_pointers.cef_preference_manager_get_global();
+}
+
+NO_SANITIZE("cfi-icall")
 struct _cef_print_settings_t* cef_print_settings_create() {
   return g_libcef_pointers.cef_print_settings_create();
 }
@@ -1382,13 +971,21 @@
 
 NO_SANITIZE("cfi-icall")
 void cef_server_create(const cef_string_t* address,
-                       uint16 port,
+                       uint16_t port,
                        int backlog,
                        struct _cef_server_handler_t* handler) {
   g_libcef_pointers.cef_server_create(address, port, backlog, handler);
 }
 
 NO_SANITIZE("cfi-icall")
+struct _cef_shared_process_message_builder_t*
+cef_shared_process_message_builder_create(const cef_string_t* name,
+                                          size_t byte_size) {
+  return g_libcef_pointers.cef_shared_process_message_builder_create(name,
+                                                                     byte_size);
+}
+
+NO_SANITIZE("cfi-icall")
 struct _cef_stream_reader_t* cef_stream_reader_create_for_file(
     const cef_string_t* fileName) {
   return g_libcef_pointers.cef_stream_reader_create_for_file(fileName);
@@ -1477,12 +1074,12 @@
 }
 
 NO_SANITIZE("cfi-icall")
-struct _cef_v8value_t* cef_v8value_create_int(int32 value) {
+struct _cef_v8value_t* cef_v8value_create_int(int32_t value) {
   return g_libcef_pointers.cef_v8value_create_int(value);
 }
 
 NO_SANITIZE("cfi-icall")
-struct _cef_v8value_t* cef_v8value_create_uint(uint32 value) {
+struct _cef_v8value_t* cef_v8value_create_uint(uint32_t value) {
   return g_libcef_pointers.cef_v8value_create_uint(value);
 }
 
@@ -1492,7 +1089,7 @@
 }
 
 NO_SANITIZE("cfi-icall")
-struct _cef_v8value_t* cef_v8value_create_date(const cef_time_t* date) {
+struct _cef_v8value_t* cef_v8value_create_date(cef_basetime_t date) {
   return g_libcef_pointers.cef_v8value_create_date(date);
 }
 
@@ -1529,6 +1126,10 @@
   return g_libcef_pointers.cef_v8value_create_function(name, handler);
 }
 
+NO_SANITIZE("cfi-icall") struct _cef_v8value_t* cef_v8value_create_promise() {
+  return g_libcef_pointers.cef_v8value_create_promise();
+}
+
 NO_SANITIZE("cfi-icall")
 struct _cef_v8stack_trace_t* cef_v8stack_trace_get_current(int frame_limit) {
   return g_libcef_pointers.cef_v8stack_trace_get_current(frame_limit);
@@ -1576,6 +1177,16 @@
 }
 
 NO_SANITIZE("cfi-icall")
+struct _cef_test_server_t* cef_test_server_create_and_start(
+    uint16_t port,
+    int https_server,
+    cef_test_cert_type_t https_cert_type,
+    struct _cef_test_server_handler_t* handler) {
+  return g_libcef_pointers.cef_test_server_create_and_start(
+      port, https_server, https_cert_type, handler);
+}
+
+NO_SANITIZE("cfi-icall")
 struct _cef_translator_test_t* cef_translator_test_create() {
   return g_libcef_pointers.cef_translator_test_create();
 }
@@ -1673,6 +1284,28 @@
 }
 
 NO_SANITIZE("cfi-icall")
+cef_point_t cef_display_convert_screen_point_to_pixels(
+    const cef_point_t* point) {
+  return g_libcef_pointers.cef_display_convert_screen_point_to_pixels(point);
+}
+
+NO_SANITIZE("cfi-icall")
+cef_point_t cef_display_convert_screen_point_from_pixels(
+    const cef_point_t* point) {
+  return g_libcef_pointers.cef_display_convert_screen_point_from_pixels(point);
+}
+
+NO_SANITIZE("cfi-icall")
+cef_rect_t cef_display_convert_screen_rect_to_pixels(const cef_rect_t* rect) {
+  return g_libcef_pointers.cef_display_convert_screen_rect_to_pixels(rect);
+}
+
+NO_SANITIZE("cfi-icall")
+cef_rect_t cef_display_convert_screen_rect_from_pixels(const cef_rect_t* rect) {
+  return g_libcef_pointers.cef_display_convert_screen_rect_from_pixels(rect);
+}
+
+NO_SANITIZE("cfi-icall")
 struct _cef_label_button_t* cef_label_button_create(
     struct _cef_button_delegate_t* delegate,
     const cef_string_t* text) {
@@ -1878,7 +1511,7 @@
 }
 
 NO_SANITIZE("cfi-icall")
-int cef_string_utf16_set(const char16* src,
+int cef_string_utf16_set(const char16_t* src,
                          size_t src_len,
                          cef_string_utf16_t* output,
                          int copy) {
@@ -1937,7 +1570,7 @@
 }
 
 NO_SANITIZE("cfi-icall")
-int cef_string_utf16_to_wide(const char16* src,
+int cef_string_utf16_to_wide(const char16_t* src,
                              size_t src_len,
                              cef_string_wide_t* output) {
   return g_libcef_pointers.cef_string_utf16_to_wide(src, src_len, output);
@@ -1951,7 +1584,7 @@
 }
 
 NO_SANITIZE("cfi-icall")
-int cef_string_utf16_to_utf8(const char16* src,
+int cef_string_utf16_to_utf8(const char16_t* src,
                              size_t src_len,
                              cef_string_utf8_t* output) {
   return g_libcef_pointers.cef_string_utf16_to_utf8(src, src_len, output);
@@ -2002,14 +1635,14 @@
 }
 
 NO_SANITIZE("cfi-icall")
-int cef_string_utf16_to_lower(const char16* src,
+int cef_string_utf16_to_lower(const char16_t* src,
                               size_t src_len,
                               cef_string_utf16_t* output) {
   return g_libcef_pointers.cef_string_utf16_to_lower(src, src_len, output);
 }
 
 NO_SANITIZE("cfi-icall")
-int cef_string_utf16_to_upper(const char16* src,
+int cef_string_utf16_to_upper(const char16_t* src,
                               size_t src_len,
                               cef_string_utf16_t* output) {
   return g_libcef_pointers.cef_string_utf16_to_upper(src, src_len, output);
@@ -2049,6 +1682,10 @@
   return g_libcef_pointers.cef_time_now(cef_time);
 }
 
+NO_SANITIZE("cfi-icall") cef_basetime_t cef_basetime_now() {
+  return g_libcef_pointers.cef_basetime_now();
+}
+
 NO_SANITIZE("cfi-icall")
 int cef_time_delta(const cef_time_t* cef_time1,
                    const cef_time_t* cef_time2,
@@ -2057,113 +1694,113 @@
 }
 
 NO_SANITIZE("cfi-icall")
+int cef_time_to_basetime(const cef_time_t* from, cef_basetime_t* to) {
+  return g_libcef_pointers.cef_time_to_basetime(from, to);
+}
+
+NO_SANITIZE("cfi-icall")
+int cef_time_from_basetime(const cef_basetime_t from, cef_time_t* to) {
+  return g_libcef_pointers.cef_time_from_basetime(from, to);
+}
+
+NO_SANITIZE("cfi-icall")
 void cef_trace_event_instant(const char* category,
                              const char* name,
                              const char* arg1_name,
-                             uint64 arg1_val,
+                             uint64_t arg1_val,
                              const char* arg2_name,
-                             uint64 arg2_val,
-                             int copy) {
+                             uint64_t arg2_val) {
   g_libcef_pointers.cef_trace_event_instant(category, name, arg1_name, arg1_val,
-                                            arg2_name, arg2_val, copy);
+                                            arg2_name, arg2_val);
 }
 
 NO_SANITIZE("cfi-icall")
 void cef_trace_event_begin(const char* category,
                            const char* name,
                            const char* arg1_name,
-                           uint64 arg1_val,
+                           uint64_t arg1_val,
                            const char* arg2_name,
-                           uint64 arg2_val,
-                           int copy) {
+                           uint64_t arg2_val) {
   g_libcef_pointers.cef_trace_event_begin(category, name, arg1_name, arg1_val,
-                                          arg2_name, arg2_val, copy);
+                                          arg2_name, arg2_val);
 }
 
 NO_SANITIZE("cfi-icall")
 void cef_trace_event_end(const char* category,
                          const char* name,
                          const char* arg1_name,
-                         uint64 arg1_val,
+                         uint64_t arg1_val,
                          const char* arg2_name,
-                         uint64 arg2_val,
-                         int copy) {
+                         uint64_t arg2_val) {
   g_libcef_pointers.cef_trace_event_end(category, name, arg1_name, arg1_val,
-                                        arg2_name, arg2_val, copy);
+                                        arg2_name, arg2_val);
 }
 
 NO_SANITIZE("cfi-icall")
 void cef_trace_counter(const char* category,
                        const char* name,
                        const char* value1_name,
-                       uint64 value1_val,
+                       uint64_t value1_val,
                        const char* value2_name,
-                       uint64 value2_val,
-                       int copy) {
+                       uint64_t value2_val) {
   g_libcef_pointers.cef_trace_counter(category, name, value1_name, value1_val,
-                                      value2_name, value2_val, copy);
+                                      value2_name, value2_val);
 }
 
 NO_SANITIZE("cfi-icall")
 void cef_trace_counter_id(const char* category,
                           const char* name,
-                          uint64 id,
+                          uint64_t id,
                           const char* value1_name,
-                          uint64 value1_val,
+                          uint64_t value1_val,
                           const char* value2_name,
-                          uint64 value2_val,
-                          int copy) {
+                          uint64_t value2_val) {
   g_libcef_pointers.cef_trace_counter_id(category, name, id, value1_name,
-                                         value1_val, value2_name, value2_val,
-                                         copy);
+                                         value1_val, value2_name, value2_val);
 }
 
 NO_SANITIZE("cfi-icall")
 void cef_trace_event_async_begin(const char* category,
                                  const char* name,
-                                 uint64 id,
+                                 uint64_t id,
                                  const char* arg1_name,
-                                 uint64 arg1_val,
+                                 uint64_t arg1_val,
                                  const char* arg2_name,
-                                 uint64 arg2_val,
-                                 int copy) {
-  g_libcef_pointers.cef_trace_event_async_begin(
-      category, name, id, arg1_name, arg1_val, arg2_name, arg2_val, copy);
+                                 uint64_t arg2_val) {
+  g_libcef_pointers.cef_trace_event_async_begin(category, name, id, arg1_name,
+                                                arg1_val, arg2_name, arg2_val);
 }
 
 NO_SANITIZE("cfi-icall")
 void cef_trace_event_async_step_into(const char* category,
                                      const char* name,
-                                     uint64 id,
-                                     uint64 step,
+                                     uint64_t id,
+                                     uint64_t step,
                                      const char* arg1_name,
-                                     uint64 arg1_val,
-                                     int copy) {
+                                     uint64_t arg1_val) {
   g_libcef_pointers.cef_trace_event_async_step_into(category, name, id, step,
-                                                    arg1_name, arg1_val, copy);
+                                                    arg1_name, arg1_val);
 }
 
 NO_SANITIZE("cfi-icall")
 void cef_trace_event_async_step_past(const char* category,
                                      const char* name,
-                                     uint64 id,
-                                     uint64 step,
+                                     uint64_t id,
+                                     uint64_t step,
                                      const char* arg1_name,
-                                     uint64 arg1_val,
-                                     int copy) {
+                                     uint64_t arg1_val) {
   g_libcef_pointers.cef_trace_event_async_step_past(category, name, id, step,
-                                                    arg1_name, arg1_val, copy);
+                                                    arg1_name, arg1_val);
 }
 
 NO_SANITIZE("cfi-icall")
 void cef_trace_event_async_end(const char* category,
                                const char* name,
-                               uint64 id,
+                               uint64_t id,
                                const char* arg1_name,
-                               uint64 arg1_val,
+                               uint64_t arg1_val,
                                const char* arg2_name,
-                               uint64 arg2_val,
-                               int copy) {
-  g_libcef_pointers.cef_trace_event_async_end(
-      category, name, id, arg1_name, arg1_val, arg2_name, arg2_val, copy);
+                               uint64_t arg2_val) {
+  g_libcef_pointers.cef_trace_event_async_end(category, name, id, arg1_name,
+                                              arg1_val, arg2_name, arg2_val);
 }
diff --git a/src/libcef_dll/wrapper/libcef_dll_wrapper.cc b/src/libcef_dll/wrapper/libcef_dll_wrapper.cc
index 052e3a8..9928e0c 100644
--- a/src/libcef_dll/wrapper/libcef_dll_wrapper.cc
+++ b/src/libcef_dll/wrapper/libcef_dll_wrapper.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,12 +9,13 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=7db8dbe24a2510d9ae0649f1569909711017c064$
+// $hash=231eb074788457c6fa690d3c82731c5334f322b2$
 //
 
 #include "include/capi/cef_app_capi.h"
 #include "include/capi/cef_crash_util_capi.h"
 #include "include/capi/cef_file_util_capi.h"
+#include "include/capi/cef_i18n_util_capi.h"
 #include "include/capi/cef_origin_whitelist_capi.h"
 #include "include/capi/cef_parser_capi.h"
 #include "include/capi/cef_path_util_capi.h"
@@ -24,12 +25,12 @@
 #include "include/capi/cef_task_capi.h"
 #include "include/capi/cef_trace_capi.h"
 #include "include/capi/cef_v8_capi.h"
-#include "include/capi/cef_web_plugin_capi.h"
 #include "include/capi/test/cef_test_helpers_capi.h"
 #include "include/cef_api_hash.h"
 #include "include/cef_app.h"
 #include "include/cef_crash_util.h"
 #include "include/cef_file_util.h"
+#include "include/cef_i18n_util.h"
 #include "include/cef_origin_whitelist.h"
 #include "include/cef_parser.h"
 #include "include/cef_path_util.h"
@@ -39,17 +40,13 @@
 #include "include/cef_task.h"
 #include "include/cef_trace.h"
 #include "include/cef_v8.h"
-#include "include/cef_web_plugin.h"
 #include "include/test/cef_test_helpers.h"
 #include "libcef_dll/cpptoc/app_cpptoc.h"
 #include "libcef_dll/cpptoc/completion_callback_cpptoc.h"
 #include "libcef_dll/cpptoc/end_tracing_callback_cpptoc.h"
-#include "libcef_dll/cpptoc/register_cdm_callback_cpptoc.h"
 #include "libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h"
 #include "libcef_dll/cpptoc/task_cpptoc.h"
 #include "libcef_dll/cpptoc/v8handler_cpptoc.h"
-#include "libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.h"
-#include "libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.h"
 #include "libcef_dll/ctocpp/binary_value_ctocpp.h"
 #include "libcef_dll/ctocpp/command_line_ctocpp.h"
 #include "libcef_dll/ctocpp/frame_ctocpp.h"
@@ -69,7 +66,7 @@
   const char* api_hash = cef_api_hash(0);
   if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) {
     // The libcef API hash does not match the current header API hash.
-    NOTREACHED();
+    DCHECK(false);
     return 0;
   }
 
@@ -93,7 +90,7 @@
   const char* api_hash = cef_api_hash(0);
   if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) {
     // The libcef API hash does not match the current header API hash.
-    NOTREACHED();
+    DCHECK(false);
     return false;
   }
 
@@ -141,20 +138,6 @@
   cef_quit_message_loop();
 }
 
-NO_SANITIZE("cfi-icall") CEF_GLOBAL void CefSetOSModalLoop(bool osModalLoop) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  cef_set_osmodal_loop(osModalLoop);
-}
-
-NO_SANITIZE("cfi-icall") CEF_GLOBAL void CefEnableHighDPISupport() {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  cef_enable_highdpi_support();
-}
-
 NO_SANITIZE("cfi-icall") CEF_GLOBAL bool CefCrashReportingEnabled() {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
@@ -172,8 +155,9 @@
 
   // Verify param: key; type: string_byref_const
   DCHECK(!key.empty());
-  if (key.empty())
+  if (key.empty()) {
     return;
+  }
   // Unverified params: value
 
   // Execute
@@ -186,8 +170,9 @@
 
   // Verify param: full_path; type: string_byref_const
   DCHECK(!full_path.empty());
-  if (full_path.empty())
+  if (full_path.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = cef_create_directory(full_path.GetStruct());
@@ -230,8 +215,9 @@
 
   // Verify param: base_dir; type: string_byref_const
   DCHECK(!base_dir.empty());
-  if (base_dir.empty())
+  if (base_dir.empty()) {
     return false;
+  }
   // Unverified params: prefix
 
   // Execute
@@ -248,8 +234,9 @@
 
   // Verify param: path; type: string_byref_const
   DCHECK(!path.empty());
-  if (path.empty())
+  if (path.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = cef_directory_exists(path.GetStruct());
@@ -264,8 +251,9 @@
 
   // Verify param: path; type: string_byref_const
   DCHECK(!path.empty());
-  if (path.empty())
+  if (path.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = cef_delete_file(path.GetStruct(), recursive);
@@ -282,12 +270,14 @@
 
   // Verify param: src_dir; type: string_byref_const
   DCHECK(!src_dir.empty());
-  if (src_dir.empty())
+  if (src_dir.empty()) {
     return false;
+  }
   // Verify param: dest_file; type: string_byref_const
   DCHECK(!dest_file.empty());
-  if (dest_file.empty())
+  if (dest_file.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = cef_zip_directory(src_dir.GetStruct(), dest_file.GetStruct(),
@@ -303,13 +293,24 @@
 
   // Verify param: path; type: string_byref_const
   DCHECK(!path.empty());
-  if (path.empty())
+  if (path.empty()) {
     return;
+  }
 
   // Execute
   cef_load_crlsets_file(path.GetStruct());
 }
 
+NO_SANITIZE("cfi-icall") CEF_GLOBAL bool CefIsRTL() {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = cef_is_rtl();
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
 NO_SANITIZE("cfi-icall")
 CEF_GLOBAL
 bool CefAddCrossOriginWhitelistEntry(const CefString& source_origin,
@@ -320,12 +321,14 @@
 
   // Verify param: source_origin; type: string_byref_const
   DCHECK(!source_origin.empty());
-  if (source_origin.empty())
+  if (source_origin.empty()) {
     return false;
+  }
   // Verify param: target_protocol; type: string_byref_const
   DCHECK(!target_protocol.empty());
-  if (target_protocol.empty())
+  if (target_protocol.empty()) {
     return false;
+  }
   // Unverified params: target_domain
 
   // Execute
@@ -347,12 +350,14 @@
 
   // Verify param: source_origin; type: string_byref_const
   DCHECK(!source_origin.empty());
-  if (source_origin.empty())
+  if (source_origin.empty()) {
     return false;
+  }
   // Verify param: target_protocol; type: string_byref_const
   DCHECK(!target_protocol.empty());
-  if (target_protocol.empty())
+  if (target_protocol.empty()) {
     return false;
+  }
   // Unverified params: target_domain
 
   // Execute
@@ -375,13 +380,39 @@
 }
 
 NO_SANITIZE("cfi-icall")
+CEF_GLOBAL bool CefResolveURL(const CefString& base_url,
+                              const CefString& relative_url,
+                              CefString& resolved_url) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: base_url; type: string_byref_const
+  DCHECK(!base_url.empty());
+  if (base_url.empty()) {
+    return false;
+  }
+  // Verify param: relative_url; type: string_byref_const
+  DCHECK(!relative_url.empty());
+  if (relative_url.empty()) {
+    return false;
+  }
+
+  // Execute
+  int _retval = cef_resolve_url(base_url.GetStruct(), relative_url.GetStruct(),
+                                resolved_url.GetWritableStruct());
+
+  // Return type: bool
+  return _retval ? true : false;
+}
+
+NO_SANITIZE("cfi-icall")
 CEF_GLOBAL bool CefParseURL(const CefString& url, CefURLParts& parts) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: url; type: string_byref_const
   DCHECK(!url.empty());
-  if (url.empty())
+  if (url.empty()) {
     return false;
+  }
 
   // Execute
   int _retval = cef_parse_url(url.GetStruct(), &parts);
@@ -408,8 +439,9 @@
 
   // Verify param: origin_url; type: string_byref_const
   DCHECK(!origin_url.empty());
-  if (origin_url.empty())
+  if (origin_url.empty()) {
     return CefString();
+  }
 
   // Execute
   cef_string_userfree_t _retval =
@@ -427,8 +459,9 @@
 
   // Verify param: extension; type: string_byref_const
   DCHECK(!extension.empty());
-  if (extension.empty())
+  if (extension.empty()) {
     return CefString();
+  }
 
   // Execute
   cef_string_userfree_t _retval = cef_get_mime_type(extension.GetStruct());
@@ -447,14 +480,16 @@
 
   // Verify param: mime_type; type: string_byref_const
   DCHECK(!mime_type.empty());
-  if (mime_type.empty())
+  if (mime_type.empty()) {
     return;
+  }
 
   // Translate param: extensions; type: string_vec_byref
   cef_string_list_t extensionsList = cef_string_list_alloc();
   DCHECK(extensionsList);
-  if (extensionsList)
+  if (extensionsList) {
     transfer_string_list_contents(extensions, extensionsList);
+  }
 
   // Execute
   cef_get_extensions_for_mime_type(mime_type.GetStruct(), extensionsList);
@@ -473,8 +508,9 @@
 
   // Verify param: data; type: simple_byaddr
   DCHECK(data);
-  if (!data)
+  if (!data) {
     return CefString();
+  }
 
   // Execute
   cef_string_userfree_t _retval = cef_base64encode(data, data_size);
@@ -491,8 +527,9 @@
 
   // Verify param: data; type: string_byref_const
   DCHECK(!data.empty());
-  if (data.empty())
+  if (data.empty()) {
     return nullptr;
+  }
 
   // Execute
   cef_binary_value_t* _retval = cef_base64decode(data.GetStruct());
@@ -507,8 +544,9 @@
 
   // Verify param: text; type: string_byref_const
   DCHECK(!text.empty());
-  if (text.empty())
+  if (text.empty()) {
     return CefString();
+  }
 
   // Execute
   cef_string_userfree_t _retval = cef_uriencode(text.GetStruct(), use_plus);
@@ -527,8 +565,9 @@
 
   // Verify param: text; type: string_byref_const
   DCHECK(!text.empty());
-  if (text.empty())
+  if (text.empty()) {
     return CefString();
+  }
 
   // Execute
   cef_string_userfree_t _retval =
@@ -547,8 +586,9 @@
 
   // Verify param: json_string; type: string_byref_const
   DCHECK(!json_string.empty());
-  if (json_string.empty())
+  if (json_string.empty()) {
     return nullptr;
+  }
 
   // Execute
   cef_value_t* _retval = cef_parse_json(json_string.GetStruct(), options);
@@ -565,8 +605,9 @@
 
   // Verify param: json; type: simple_byaddr
   DCHECK(json);
-  if (!json)
+  if (!json) {
     return nullptr;
+  }
 
   // Execute
   cef_value_t* _retval = cef_parse_json_buffer(json, json_size, options);
@@ -579,19 +620,18 @@
 CEF_GLOBAL CefRefPtr<CefValue> CefParseJSONAndReturnError(
     const CefString& json_string,
     cef_json_parser_options_t options,
-    cef_json_parser_error_t& error_code_out,
     CefString& error_msg_out) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: json_string; type: string_byref_const
   DCHECK(!json_string.empty());
-  if (json_string.empty())
+  if (json_string.empty()) {
     return nullptr;
+  }
 
   // Execute
   cef_value_t* _retval = cef_parse_jsonand_return_error(
-      json_string.GetStruct(), options, &error_code_out,
-      error_msg_out.GetWritableStruct());
+      json_string.GetStruct(), options, error_msg_out.GetWritableStruct());
 
   // Return type: refptr_same
   return CefValueCToCpp::Wrap(_retval);
@@ -604,8 +644,9 @@
 
   // Verify param: node; type: refptr_same
   DCHECK(node.get());
-  if (!node.get())
+  if (!node.get()) {
     return CefString();
+  }
 
   // Execute
   cef_string_userfree_t _retval =
@@ -634,8 +675,9 @@
 
   // Verify param: command_line; type: refptr_same
   DCHECK(command_line.get());
-  if (!command_line.get())
+  if (!command_line.get()) {
     return false;
+  }
 
   // Execute
   int _retval = cef_launch_process(CefCommandLineCToCpp::Unwrap(command_line));
@@ -653,8 +695,9 @@
 
   // Verify param: scheme_name; type: string_byref_const
   DCHECK(!scheme_name.empty());
-  if (scheme_name.empty())
+  if (scheme_name.empty()) {
     return false;
+  }
   // Unverified params: domain_name, factory
 
   // Execute
@@ -703,8 +746,9 @@
 
   // Verify param: task; type: refptr_diff
   DCHECK(task.get());
-  if (!task.get())
+  if (!task.get()) {
     return false;
+  }
 
   // Execute
   int _retval = cef_post_task(threadId, CefTaskCppToC::Wrap(task));
@@ -716,13 +760,14 @@
 NO_SANITIZE("cfi-icall")
 CEF_GLOBAL bool CefPostDelayedTask(CefThreadId threadId,
                                    CefRefPtr<CefTask> task,
-                                   int64 delay_ms) {
+                                   int64_t delay_ms) {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Verify param: task; type: refptr_diff
   DCHECK(task.get());
-  if (!task.get())
+  if (!task.get()) {
     return false;
+  }
 
   // Execute
   int _retval =
@@ -762,11 +807,11 @@
   return _retval ? true : false;
 }
 
-NO_SANITIZE("cfi-icall") CEF_GLOBAL int64 CefNowFromSystemTraceTime() {
+NO_SANITIZE("cfi-icall") CEF_GLOBAL int64_t CefNowFromSystemTraceTime() {
   // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
 
   // Execute
-  int64 _retval = cef_now_from_system_trace_time();
+  int64_t _retval = cef_now_from_system_trace_time();
 
   // Return type: simple
   return _retval;
@@ -780,12 +825,14 @@
 
   // Verify param: extension_name; type: string_byref_const
   DCHECK(!extension_name.empty());
-  if (extension_name.empty())
+  if (extension_name.empty()) {
     return false;
+  }
   // Verify param: javascript_code; type: string_byref_const
   DCHECK(!javascript_code.empty());
-  if (javascript_code.empty())
+  if (javascript_code.empty()) {
     return false;
+  }
   // Unverified params: handler
 
   // Execute
@@ -798,90 +845,6 @@
 }
 
 NO_SANITIZE("cfi-icall")
-CEF_GLOBAL
-void CefVisitWebPluginInfo(CefRefPtr<CefWebPluginInfoVisitor> visitor) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: visitor; type: refptr_diff
-  DCHECK(visitor.get());
-  if (!visitor.get())
-    return;
-
-  // Execute
-  cef_visit_web_plugin_info(CefWebPluginInfoVisitorCppToC::Wrap(visitor));
-}
-
-NO_SANITIZE("cfi-icall") CEF_GLOBAL void CefRefreshWebPlugins() {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Execute
-  cef_refresh_web_plugins();
-}
-
-NO_SANITIZE("cfi-icall")
-CEF_GLOBAL void CefUnregisterInternalWebPlugin(const CefString& path) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: path; type: string_byref_const
-  DCHECK(!path.empty());
-  if (path.empty())
-    return;
-
-  // Execute
-  cef_unregister_internal_web_plugin(path.GetStruct());
-}
-
-NO_SANITIZE("cfi-icall")
-CEF_GLOBAL void CefRegisterWebPluginCrash(const CefString& path) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: path; type: string_byref_const
-  DCHECK(!path.empty());
-  if (path.empty())
-    return;
-
-  // Execute
-  cef_register_web_plugin_crash(path.GetStruct());
-}
-
-NO_SANITIZE("cfi-icall")
-CEF_GLOBAL void CefIsWebPluginUnstable(
-    const CefString& path,
-    CefRefPtr<CefWebPluginUnstableCallback> callback) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: path; type: string_byref_const
-  DCHECK(!path.empty());
-  if (path.empty())
-    return;
-  // Verify param: callback; type: refptr_diff
-  DCHECK(callback.get());
-  if (!callback.get())
-    return;
-
-  // Execute
-  cef_is_web_plugin_unstable(
-      path.GetStruct(), CefWebPluginUnstableCallbackCppToC::Wrap(callback));
-}
-
-NO_SANITIZE("cfi-icall")
-CEF_GLOBAL
-void CefRegisterWidevineCdm(const CefString& path,
-                            CefRefPtr<CefRegisterCdmCallback> callback) {
-  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
-
-  // Verify param: path; type: string_byref_const
-  DCHECK(!path.empty());
-  if (path.empty())
-    return;
-  // Unverified params: callback
-
-  // Execute
-  cef_register_widevine_cdm(path.GetStruct(),
-                            CefRegisterCdmCallbackCppToC::Wrap(callback));
-}
-
-NO_SANITIZE("cfi-icall")
 CEF_GLOBAL void CefExecuteJavaScriptWithUserGestureForTests(
     CefRefPtr<CefFrame> frame,
     const CefString& javascript) {
@@ -889,11 +852,26 @@
 
   // Verify param: frame; type: refptr_same
   DCHECK(frame.get());
-  if (!frame.get())
+  if (!frame.get()) {
     return;
+  }
   // Unverified params: javascript
 
   // Execute
   cef_execute_java_script_with_user_gesture_for_tests(
       CefFrameCToCpp::Unwrap(frame), javascript.GetStruct());
 }
+
+NO_SANITIZE("cfi-icall")
+CEF_GLOBAL void CefSetDataDirectoryForTests(const CefString& dir) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Verify param: dir; type: string_byref_const
+  DCHECK(!dir.empty());
+  if (dir.empty()) {
+    return;
+  }
+
+  // Execute
+  cef_set_data_directory_for_tests(dir.GetStruct());
+}
diff --git a/src/libcef_dll/wrapper/libcef_dll_wrapper2.cc b/src/libcef_dll/wrapper/libcef_dll_wrapper2.cc
index bdeef8a..4e6c48a 100644
--- a/src/libcef_dll/wrapper/libcef_dll_wrapper2.cc
+++ b/src/libcef_dll/wrapper/libcef_dll_wrapper2.cc
@@ -1,3 +1,51 @@
-// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "include/base/cef_build.h"
+
+#if defined(OS_WIN)
+
+#include "include/base/cef_compiler_specific.h"
+#include "include/base/cef_logging.h"
+#include "include/cef_api_hash.h"
+#include "include/internal/cef_win.h"
+
+#if defined(ARCH_CPU_32_BITS)
+NO_SANITIZE("cfi-icall")
+int CefRunWinMainWithPreferredStackSize(wWinMainPtr wWinMain,
+                                        HINSTANCE hInstance,
+                                        LPWSTR lpCmdLine,
+                                        int nCmdShow) {
+  CHECK(wWinMain && hInstance);
+
+  const char* api_hash = cef_api_hash(0);
+  if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) {
+    // The libcef API hash does not match the current header API hash.
+    DCHECK(false);
+    return 0;
+  }
+
+  return cef_run_winmain_with_preferred_stack_size(wWinMain, hInstance,
+                                                   lpCmdLine, nCmdShow);
+}
+
+int CefRunMainWithPreferredStackSize(mainPtr main, int argc, char* argv[]) {
+  CHECK(main);
+
+  const char* api_hash = cef_api_hash(0);
+  if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) {
+    // The libcef API hash does not match the current header API hash.
+    DCHECK(false);
+    return 0;
+  }
+
+  return cef_run_main_with_preferred_stack_size(main, argc, argv);
+}
+#endif  // defined(ARCH_CPU_32_BITS)
+
+NO_SANITIZE("cfi-icall") void CefSetOSModalLoop(bool osModalLoop) {
+  cef_set_osmodal_loop(osModalLoop);
+}
+
+#endif  // defined(OS_WIN)
diff --git a/src/libcef_dll/wrapper_types.h b/src/libcef_dll/wrapper_types.h
index 980b90d..eddb3ec 100644
--- a/src/libcef_dll/wrapper_types.h
+++ b/src/libcef_dll/wrapper_types.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
+// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 //
@@ -9,7 +9,7 @@
 // implementations. See the translator.README.txt file in the tools directory
 // for more information.
 //
-// $hash=6e7cec57ce98a10f0b0668d47c9935639963c215$
+// $hash=220cf66311a9b87b0edfadf9617138d7cf3273f8$
 //
 
 #ifndef CEF_LIBCEF_DLL_WRAPPER_TYPES_H_
@@ -35,6 +35,7 @@
   WT_BUTTON_DELEGATE,
   WT_CALLBACK,
   WT_CLIENT,
+  WT_COMMAND_HANDLER,
   WT_COMMAND_LINE,
   WT_COMPLETION_CALLBACK,
   WT_CONTEXT_MENU_HANDLER,
@@ -65,6 +66,7 @@
   WT_FIND_HANDLER,
   WT_FOCUS_HANDLER,
   WT_FRAME,
+  WT_FRAME_HANDLER,
   WT_GET_EXTENSION_RESOURCE_CALLBACK,
   WT_IMAGE,
   WT_JSDIALOG_CALLBACK,
@@ -75,6 +77,7 @@
   WT_LIFE_SPAN_HANDLER,
   WT_LIST_VALUE,
   WT_LOAD_HANDLER,
+  WT_MEDIA_ACCESS_CALLBACK,
   WT_MEDIA_OBSERVER,
   WT_MEDIA_ROUTE,
   WT_MEDIA_ROUTE_CREATE_CALLBACK,
@@ -89,23 +92,26 @@
   WT_MENU_MODEL_DELEGATE,
   WT_NAVIGATION_ENTRY,
   WT_NAVIGATION_ENTRY_VISITOR,
+  WT_OVERLAY_CONTROLLER,
   WT_PANEL,
   WT_PANEL_DELEGATE,
   WT_PDF_PRINT_CALLBACK,
+  WT_PERMISSION_HANDLER,
+  WT_PERMISSION_PROMPT_CALLBACK,
   WT_POST_DATA,
   WT_POST_DATA_ELEMENT,
+  WT_PREFERENCE_MANAGER,
+  WT_PREFERENCE_REGISTRAR,
   WT_PRINT_DIALOG_CALLBACK,
   WT_PRINT_HANDLER,
   WT_PRINT_JOB_CALLBACK,
   WT_PRINT_SETTINGS,
   WT_PROCESS_MESSAGE,
   WT_READ_HANDLER,
-  WT_REGISTER_CDM_CALLBACK,
   WT_REGISTRATION,
   WT_RENDER_HANDLER,
   WT_RENDER_PROCESS_HANDLER,
   WT_REQUEST,
-  WT_REQUEST_CALLBACK,
   WT_REQUEST_CONTEXT,
   WT_REQUEST_CONTEXT_HANDLER,
   WT_REQUEST_HANDLER,
@@ -120,6 +126,7 @@
   WT_RESPONSE_FILTER,
   WT_RUN_CONTEXT_MENU_CALLBACK,
   WT_RUN_FILE_DIALOG_CALLBACK,
+  WT_RUN_QUICK_MENU_CALLBACK,
   WT_SSLINFO,
   WT_SSLSTATUS,
   WT_SCHEME_HANDLER_FACTORY,
@@ -129,11 +136,16 @@
   WT_SERVER,
   WT_SERVER_HANDLER,
   WT_SET_COOKIE_CALLBACK,
+  WT_SHARED_MEMORY_REGION,
+  WT_SHARED_PROCESS_MESSAGE_BUILDER,
   WT_STREAM_READER,
   WT_STREAM_WRITER,
   WT_STRING_VISITOR,
   WT_TASK,
   WT_TASK_RUNNER,
+  WT_TEST_SERVER,
+  WT_TEST_SERVER_CONNECTION,
+  WT_TEST_SERVER_HANDLER,
   WT_TEXTFIELD,
   WT_TEXTFIELD_DELEGATE,
   WT_THREAD,
@@ -163,9 +175,6 @@
   WT_VIEW,
   WT_VIEW_DELEGATE,
   WT_WAITABLE_EVENT,
-  WT_WEB_PLUGIN_INFO,
-  WT_WEB_PLUGIN_INFO_VISITOR,
-  WT_WEB_PLUGIN_UNSTABLE_CALLBACK,
   WT_WINDOW,
   WT_WINDOW_DELEGATE,
   WT_WRITE_HANDLER,
diff --git a/src/patch/patch.cfg b/src/patch/patch.cfg
index fbe7a1c..0d51f0d 100644
--- a/src/patch/patch.cfg
+++ b/src/patch/patch.cfg
@@ -23,14 +23,17 @@
   {
     # Necessary for GN integration.
     #
-    # Move chrome target locales output to a chrome/ directory to avoid
-    # conflicts with the CEF configuration.
+    # Exclude the //chrome:packed_resources_locales target from the CEF build
+    # due to conflicting outputs with the //cef:repack_locales_pack target.
     #
     # Write environment.* files with the correct SDK version on Windows.
     # https://bugs.chromium.org/p/chromium/issues/detail?id=634788
     #
     # Windows: Add cc_wrapper support for sccache builds.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2432
+    # https://github.com/chromiumembedded/cef/issues/2432
+    #
+    # Windows: Add GN arg windows_sdk_version.
+    # https://bugs.chromium.org/p/chromium/issues/detail?id=1420723
     'name': 'gn_config',
   },
   {
@@ -43,11 +46,7 @@
   },
   {
     # Support component builds (GN is_component_build=true).
-    # https://bitbucket.org/chromiumembedded/cef/issues/1617
-    #
-    # Export GetUnicodeCharacterFromXKeySym and XKeySymToDomKey
-    # to fix component builds.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2587
+    # https://github.com/chromiumembedded/cef/issues/1617
     'name': 'component_build',
   },
   {
@@ -59,7 +58,7 @@
     #
     # Add MessageLoop::ReleasePump to fix crashes during shutdown with multi-
     # threaded message loop mode.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2362
+    # https://github.com/chromiumembedded/cef/issues/2362
     'name': 'message_loop',
   },
   {
@@ -68,34 +67,32 @@
     'name': 'trace_event',
   },
   {
-    # Enable popups in offscreen rendering on OS X.
-    #
-    # Allow customization of the WebView background color.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2345
+    # Enable popups in offscreen rendering on MacOS.
     'name': 'webkit_popups',
   },
   {
-    # Fix export of UnderlayOpenGLHostingWindow for 64-bit OS X builds.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1051
-    'name': 'underlay_1051',
+    # Give AlloyContentRendererClient access to protected
+    # RuntimeEnabledFeatures methods.
+    'name': 'webkit_runtime_enabled_features',
   },
   {
     # Allow specification of a parent window handle for Widget creation.
-    # https://bitbucket.org/chromiumembedded/cef/issues/180
+    # https://github.com/chromiumembedded/cef/issues/180
     #
     # Fix multiple handling of WM_MOUSEWHEEL messages on Windows.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1481
+    # https://github.com/chromiumembedded/cef/issues/1481
     #
     # Support custom RenderWidgetHostViewOSR for BrowserPluginGuest.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1565
+    # https://github.com/chromiumembedded/cef/issues/1565
     #
     # Fix focus/activation handling and keyboard input on Windows and Linux.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1677
-    # https://bitbucket.org/chromiumembedded/cef/issues/1679
-    # https://bitbucket.org/chromiumembedded/cef/issues/1700
+    # https://github.com/chromiumembedded/cef/issues/1677
+    # https://github.com/chromiumembedded/cef/issues/1679
+    # https://github.com/chromiumembedded/cef/issues/1700
+    # https://github.com/chromiumembedded/cef/issues/3316
     #
     # Support creation of captionless windows with resizable borders.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1749
+    # https://github.com/chromiumembedded/cef/issues/1749
     #
     # Windows: When |params.remove_standard_frame| is true remove WS_CAPTION
     # and WS_SYSMENU styles. Otherwise Windows 10 enforces a minimum window
@@ -103,75 +100,80 @@
     # Linux: Allow creation of activatable menu windows.
     # Linux: Support CefWindowDelegate::CanResize restriction by specifying
     # min/max Widget size values.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1947
+    # https://github.com/chromiumembedded/cef/issues/1947
     #
     # Support configuration of RWHVGuest device scale factor.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2078
-    'name': 'views_widget_180_1481_1565_1677_1749',
+    # https://github.com/chromiumembedded/cef/issues/2078
+    #
+    # Windows: Fix focus assignment when clicking WebView with external parent.
+    # https://github.com/chromiumembedded/cef/issues/3031
+    #
+    # Fix minimize & fullscreen behavior on initial Widget creation.
+    #
+    # Allow override of RWHVBase::GetNewScreenInfosForUpdate() which is now
+    # required due to https://crrev.com/96938eb36e in order to use
+    # RWHVBase::UpdateScreenInfo() with OSR.
+    #
+    # Windows: Fix incorrect DIPToScreenRect usage in DesktopWindowTreeHostWin
+    # when |has_external_parent_| is true.
+    # https://github.com/chromiumembedded/cef/issues/3359
+    #
+    # chrome: Allow override of Widget::Activate() to support activation of
+    # DevTools windows with external parent.
+    # https://github.com/chromiumembedded/cef/issues/3282
+    'name': 'views_widget',
   },
   {
     # Allow specification of a custom WebContentsView.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1257
+    # https://github.com/chromiumembedded/cef/issues/1257
     #
     # Support custom RenderWidgetHostViewOSR for BrowserPluginGuest.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1565
+    # https://github.com/chromiumembedded/cef/issues/1565
     #
     # Add WebContentsObserver::OnFrameFocused.
+    #
+    # Add WebContentsObserver::RenderWidgetCreated.
+    # https://github.com/chromiumembedded/cef/issues/3308
+    #
+    # Avoid crash in WebContentsImpl::GetWindowShowState with OSR.
     'name': 'web_contents_1257_1565',
   },
   {
     # Support custom RenderWidgetHostViewOSR for MimeHandlerViewGuest and
     # expose OnGuestAttached/Detached notifications.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1565
-    # https://bitbucket.org/chromiumembedded/cef/issues/2727
+    # https://github.com/chromiumembedded/cef/issues/1565
+    # https://github.com/chromiumembedded/cef/issues/2727
     'name': 'mime_handler_view_guest_1565_2727',
   },
   {
-    # Allow customization of the WebView background color.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1161
-    # https://codereview.chromium.org/228603007/
-    'name': 'prefs_content_1161',
-  },
-  {
     # Fix drag&drop of combined text and URL data on Linux/Aura.
     # https://codereview.chromium.org/208313009
     'name': 'ui_dragdrop_355390',
   },
   {
-    # Remove NOTREACHED() that is hit when loading Flash in incognito mode.
-    # https://bitbucket.org/chromiumembedded/cef/issue/1586
-    'name': 'content_pepper_flash_1586',
-  },
-  {
-    # Fix placement of IME window on Windows.
-    # https://bitbucket.org/chromiumembedded/cef/issue/1610
-    'name': 'ime_1610',
-  },
-  {
-    # Split service_manager::Main into the separate steps required by CEF.
+    # Split content::ContentMain into the separate steps required by CEF.
     # https://bugs.chromium.org/p/chromium/issues/detail?id=654986#c17
     #
     # Remove DCHECK on Linux when initialized CEF from a non-main thread.
-    # https://bitbucket.org/chromiumembedded/cef/issue/1639
-    'name': 'service_manager_654986',
-  },
-  {
-    # Fix missing check for defined(ENABLE_THEMES) in
-    # renderer_preferences_util.cc on Linux.
-    # https://bugs.chromium.org/p/chromium/issues/detail?id=545103
-    'name': 'renderer_preferences_util_545103',
+    # https://github.com/chromiumembedded/cef/issues/1639
+    #
+    # Fix DiscardableSharedMemoryManager crash on shutdown with multi-threaded
+    # message loop.
+    # https://github.com/chromiumembedded/cef/issues/2798
+    'name': 'content_main_654986',
   },
   {
     # Expose the FontFamilyCache UserData key.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1501
+    # https://github.com/chromiumembedded/cef/issues/1501
     'name': 'font_family_cache_1501',
   },
   {
     # Modify views::View to extend SupportsUserData.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1749
+    # https://github.com/chromiumembedded/cef/issues/1749
     #
-    # Don't add TestDesktopScreenX11 dependency on Linux.
-    # Reverts ui_controls_factory_desktop_aurax11.cc changes from
+    # Don't add TestDesktopScreenOzone dependency on Linux.
+    # Reverts ui_controls_factory_desktop_aurax11.cc (now
+    # ui_controls_factory_desktop_aura_ozone.cc) changes from
     # https://codereview.chromium.org/2327623002
     #
     # Add InkDropHostView::ink_drop_mode method.
@@ -184,19 +186,11 @@
     #
     # Expose callbacks for mouse/keyboard events that trigger menu switching.
     # Add accelerator display support to Label.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2102
-    'name': 'views_1749_2102',
-  },
-  {
-    # Expose ui::Compositor via BrowserCompositorMac for OSR.
-    'name': 'browser_compositor_mac',
-  },
-  {
-    # Fix chrome Widevine build on Linux.
+    # https://github.com/chromiumembedded/cef/issues/2102
     #
-    # Remove incorrect assertion on Windows/macOS by cherry-picking this commit:
-    # https://chromium.googlesource.com/chromium/src/+/ec992a43e7
-    'name': 'chrome_widevine',
+    # Route |parent_widget| to MenuHost for OSR context menu Widget creation.
+    # https://github.com/chromiumembedded/cef/issues/3330
+    'name': 'views_1749_2102_3330',
   },
   {
     # Support CEF changes in chrome/browser.
@@ -207,36 +201,119 @@
     'name': 'chrome_renderer',
   },
   {
-    # Don't initialize ExtensionSystemFactory when extensions are disabled.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2359
-    'name': 'chrome_browser_content_settings',
+    # Changes to support the Chrome runtime in CEF.
+    # https://github.com/chromiumembedded/cef/issues/2969
+    'name': 'chrome_runtime',
+  },
+  {
+    # Changes to support Chrome runtime integration with CEF Views.
+    # See related documentation in
+    # libcef/browser/chrome/views/chrome_browser_frame.h.
+    # https://github.com/chromiumembedded/cef/issues/2969
+    'name': 'chrome_runtime_views',
+  },
+  {
+    # Changes to support the Chrome runtime in CEF.
+    # https://github.com/chromiumembedded/cef/issues/2969
+    #
+    # Fix fatal error: 'components/printing/common/print.mojom.h' file not found
+    # From chrome/browser/ui/browser_commands.cc via
+    # chrome/browser/printing/print_view_manager_common.h
+    'name': 'chrome_browser_browser',
   },
   {
     # Don't initialize ExtensionSystemFactory when extensions are disabled.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2852
+    # https://github.com/chromiumembedded/cef/issues/2359
+    #
+    # Remove NOTREACHED() in GetContentSettingFromRulesImpl triggered by
+    # NavigationTest.LoadCrossOriginLoadURL with the chrome runtime.
+    'name': 'chrome_browser_content_settings',
+  },
+  {
+    # chrome: Support custom handling of context menus.
+    # https://github.com/chromiumembedded/cef/issues/2969
+    'name': 'chrome_browser_context_menus',
+  },
+  {
+    # Support use of chrome native dialogs with CEF runtimes.
+    # - Adds support for FileSelectHelper and SelectFileDialog interception.
+    # - Adds additional type filters for dialogs created via FileSelectHelper.
+    # - Adds support for chaining PrintingContextLinux callbacks.
+    # https://github.com/chromiumembedded/cef/issues/3314
+    'name': 'chrome_browser_dialogs_native',
+  },
+  {
+    # Support use of chrome Widget dialogs with CEF runtimes.
+    # - Add gfx::AcceleratedWidget dialog parent argument to
+    #   DialogDelegate::CreateDialogWidget for CEF windowless rendering.
+    # - Support nullptr gfx::NativeWindow/gfx::NativeView dialog parent for CEF
+    #   windowless rendering.
+    # https://github.com/chromiumembedded/cef/issues/3316
+    #
+    # Fix NativeWebContentsModalDialogManagerViews::HostChanged to not reparent
+    # between different root windows.
+    'name': 'chrome_browser_dialogs_widget',
+  },
+  {
+    # chrome: Support override of ChromeMimeHandlerViewGuestDelegate.
+    # https://github.com/chromiumembedded/cef/issues/2969
+    'name': 'chrome_browser_extensions',
+  },
+  {
+    # chrome: Expose static access to BrowserFrameMac methods.
+    # https://github.com/chromiumembedded/cef/issues/3462
+    'name': 'chrome_browser_frame_mac',
+  },
+  {
+    # alloy: Disable ProxyErrorClient callbacks when extensions are disabled.
+    # https://github.com/chromiumembedded/cef/issues/2830
+    'name': 'chrome_browser_net_proxy',
+  },
+  {
+    # Support override of CreatePermissionPrompt.
+    # https://github.com/chromiumembedded/cef/issues/3352
+    'name': 'chrome_browser_permission_prompt',
+  },
+  {
+    # Support configuration of Chrome policy management.
+    # https://github.com/chromiumembedded/cef/issues/3581
+    'name': 'chrome_browser_policy',
+  },
+  {
+    # alloy: Don't initialize ExtensionSystemFactory when extensions are
+    # disabled.
+    # https://github.com/chromiumembedded/cef/issues/2852
     'name': 'chrome_browser_themes',
   },
   {
     # Make some methods of ProfileManager virtual.
     #
-    # Don't create IdentityManager in RendererUpdater.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1917
+    # alloy: Don't create IdentityManager or BoundSessionCookieRefreshService in
+    # RendererUpdater. This avoids adding a dependency on
+    # AccountConsistencyModeManager which itself depends on browser signin.
+    # https://github.com/chromiumembedded/cef/issues/1917
+    # https://github.com/chromiumembedded/cef/issues/3401
+    #
+    # chrome: Support CEF incognito Profiles that allow Browser creation.
+    # chrome: Allow CEF to delay OffTheRecordProfileImpl initialization.
+    # https://github.com/chromiumembedded/cef/issues/2969
     'name': 'chrome_browser_profiles',
   },
   {
-    # Show the CEF Save As dialog.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2613
-    #
-    # Fix fatal error: 'components/printing/common/print.mojom.h' file not found
-    # From chrome/browser/ui/browser_commands.cc via
-    # chrome/browser/printing/print_view_manager_common.h
-    'name': 'chrome_browser_net_export',
+    # chrome: Fix assertion when clicking the incognito profile button.
+    # https://github.com/chromiumembedded/cef/issues/2969
+    'name': 'chrome_browser_profile_menu',
+  },
+  {
+    # alloy: Don't require heap profiler for utility processes.
+    # Avoids a DCHECK added in https://crrev.com/c21e9f71d1f2e
+    'name': 'chrome_utility_client',
   },
   {
     # Support override of the User-Agent product component when NetworkService
     # is enabled.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2622
-    'name': 'chrome_browser_product_override',
+    # https://github.com/chromiumembedded/cef/issues/2622
+    'name': 'embedder_product_override',
   },
   {
     # Fix Jumbo/component build dependency issue.
@@ -244,27 +321,24 @@
   },
   {
     # Allow CEF to share Chrome plugin loading code.
+    #
+    # Add BrowserPluginGuest::owner_web_contents() method.
     'name': 'chrome_plugins',
   },
   {
     # Don't create databases, blob_storage or VideoDecodeStats directories when
     # cache_path is empty.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2289
+    # https://github.com/chromiumembedded/cef/issues/2289
     'name': 'storage_incognito_2289',
   },
   {
-    # Fix plugin placeholder blocked message.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2020/
-    'name': 'webview_plugin_2020',
-  },
-  {
     # Support WebUI by removing dependency on non-NULL IOThread* object.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2037
+    # https://github.com/chromiumembedded/cef/issues/2037
     'name': 'webui_2037',
   },
   {
     # Implement breakpad/crashpad customization required by CEF.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1995
+    # https://github.com/chromiumembedded/cef/issues/1995
     'name': 'crashpad_1995',
   },
   {
@@ -277,19 +351,13 @@
   },
   {
     # Fix white flash during browser creation.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1984
+    # https://github.com/chromiumembedded/cef/issues/1984
     #
     # Windows: Fix crash during window creation.
     # https://bugs.chromium.org/p/chromium/issues/detail?id=761389
     'name': 'rwh_background_color_1984',
   },
   {
-    # Pass is_main_frame to PluginServiceFilter::IsPluginAvailable.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2015
-    #
-    # Pass the render process id to PluginServiceFilter::IsPluginAvailable.
-    # https://bugs.chromium.org/p/chromium/issues/detail?id=626728#c15
-    #
     # Expose RFH via NavigationHandle for retrieval in DidFinishNavigation on
     # network error.
     # https://groups.google.com/a/chromium.org/d/msg/chromium-dev/6iAQPx_hwh8/gaTR5f1GAQAJ
@@ -300,116 +368,110 @@
     # Add ContentRendererClient::DevToolsAgent[Attached|Detached] methods.
     #
     # Always return the Chrome product value for DevTools.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2300
+    # https://github.com/chromiumembedded/cef/issues/2300
     #
     # Add new ContentBrowserClient::HandleExternalProtocol variant for use with
     # the NetworkService.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2622
+    # https://github.com/chromiumembedded/cef/issues/2622
+    #
+    # Change ContentBrowserClient::ConfigureNetworkContextParams return type to
+    # bool to support cancellation of NetworkContext creation during shutdown.
+    # https://github.com/chromiumembedded/cef/issues/2985
     'name': 'content_2015',
   },
   {
-    # Pass is_main_frame to PluginServiceFilter::IsPluginAvailable.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2015
-    #
     # Add ContentRendererClient::DevToolsAgent[Attached|Detached] methods.
     'name': 'webkit_plugin_info_2015',
   },
   {
     # Linux: Attach routing IDs to PrintingContext.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2196
+    # https://github.com/chromiumembedded/cef/issues/2196
     'name': 'printing_context_2196',
   },
   {
-    # Linux: Fix 32-bit build fails with ld.gold: internal error in
-    # get_section_contents, at icf.cc:467
-    # https://bitbucket.org/chromiumembedded/cef/issues/2256
-    # Win: remove llvmlibthin as the combine_libs.py can't handle those
-    # https://bitbucket.org/chromiumembedded/cef/issues/2470
+    # Windows: Remove llvmlibthin as the combine_libs.py can't handle those.
+    # https://github.com/chromiumembedded/cef/issues/2470
     'name': 'build',
   },
   {
-    # Changes necessary to support for chrome extensions. Add a new
+    # Changes necessary to support chrome extensions. Add a new
     # ExtensionHost constructor that allows CEF to create the WebContents.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1947
+    # https://github.com/chromiumembedded/cef/issues/1947
     #
     # Don't initialize PrerenderContents object in StreamsPrivateAPI.
+    #
+    # Return nullptr from ExtensionsClient::Get and ExtensionRegistry::Get
+    # when extensions are disabled.
     'name': 'extensions_1947',
   },
   {
-    # Don't enable sandbox::MITIGATION_STRICT_HANDLE_CHECKS in WinRT apps.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2274
-    'name': 'win_rt_2274',
-  },
-  {
-    # Fix DCHECK running OSRTest.DragDropUpdateCursor.
-    # https://bugs.chromium.org/p/chromium/issues/detail?id=781966
-    'name': 'webkit_pointer_event_781966',
-  },
-  {
-    # macOS: Fix undesirable switch to discrete GPU during startup.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2398
-    #
-    # macOS: Rely on symlinks to find the Libraries directory.
-    # https://bugs.chromium.org/p/chromium/issues/detail?id=757974#c23
-    'name': 'mac_gpu',
-  },
-  {
     # macOS: Make the NativeEventProcessor protocol dependency optional.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2539
+    # https://github.com/chromiumembedded/cef/issues/2539
     'name': 'mac_event_observer_2539',
   },
   {
     # macOS: Fix crash when scrolling in OSR mode.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2540
+    # https://github.com/chromiumembedded/cef/issues/2540
     'name': 'mac_fling_scheduler_2540',
   },
   {
-    # Linux: Use poll instead of select to fix crash during startup.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2466
-    'name': 'linux_poll_2466',
-  },
-  {
     # Allow ResourceBundle creation/destruction on the main thread and usage on
     # the UI thread.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2398
+    # https://github.com/chromiumembedded/cef/issues/2398
     'name': 'resource_bundle_2512',
   },
   {
     # macOS: Fix crash when showing a select popup with CefDoMessageLoopWork.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2495
+    # https://github.com/chromiumembedded/cef/issues/2495
     'name': 'message_pump_mac_2495',
   },
   {
     # Linux: Load binaries from DIR_ASSETS.
-    # https://bitbucket.org/chromiumembedded/cef/issues/1936
+    # https://github.com/chromiumembedded/cef/issues/1936
     'name': 'linux_assets_path_1936',
   },
   {
+    # Linux: Fix ld.lld: error: relocation R_X86_64_TPOFF32 against
+    # blink::g_thread_specific_ cannot be used with -shared
+    # https://groups.google.com/a/chromium.org/g/blink-dev/c/wx0gZFCY3p4/m/iLBHRi0ZAQAJ
+    'name': 'linux_blink_thread_local',
+  },
+  {
+    # Linux: Avoid usage of chrome::FILE_COMPONENT_WIDEVINE_CDM_HINT.
+    # https://github.com/chromiumembedded/cef/issues/3149
+    'name': 'linux_chrome_widevine_3149',
+  },
+  {
     # Enhancements to NetworkService:
     # - Add support for calling CookieMonster::SetCookieableSchemes.
     # - Fix cache directory structure ("C:\temp\cache\cache\Cache" should be
     #   "C:\temp\cache\Cache").
-    # https://bitbucket.org/chromiumembedded/cef/issues/2622
+    # https://github.com/chromiumembedded/cef/issues/2622
+    #
+    # alloy: Avoid initialization of privacy sandbox, identity manager and
+    # first party sets policy.
+    # https://github.com/chromiumembedded/cef/issues/3434
     'name': 'services_network_2622',
   },
   {
     # Enhancements to NetworkService:
     # - Remove the non-nullptr WebContents requirement from
     #   NetworkServiceClient::OnAuthRequired.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2718
+    # https://github.com/chromiumembedded/cef/issues/2718
     #
-    # Fix shutdown crash in InitNetworkContext with multi-threaded message loop.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2703
+    # Change ContentBrowserClient::ConfigureNetworkContextParams return type to
+    # bool to support cancellation of NetworkContext creation during shutdown.
+    # https://github.com/chromiumembedded/cef/issues/2985
     #
     # Compute correct default quota when cache_path is unspecified.
     'name': 'services_network_2718',
   },
   {
-    # Windows: Remove the base::Value is_standard_layout assert which will fail
-    # for the cef_sandbox build, and which is no longer required.
-    # https://bugs.chromium.org/p/chromium/issues/detail?id=646113#c173
-    # https://chromium.googlesource.com/chromium/src/+/2f28731c17
-    'name': 'win_base_msvc_sandbox',
+    # Restore the net::LOAD_DO_NOT_SEND_COOKIES flag to support disabling of
+    # cookie load/save on a per-request basis.
+    # Partially reverts the changes from
+    # https://chromium.googlesource.com/chromium/src/+/25eaa43022
+    'name': 'net_cookie_flags',
   },
   {
     # Restore WebView::SetResizeBackgroundColor() that was removed.
@@ -417,11 +479,6 @@
     'name': 'set_resize_background_color',
   },
   {
-    # Restore WebUrlLoader Cancel method.
-    # https://chromium-review.googlesource.com/c/chromium/src/+/1617042
-    'name': 'web_url_loader_cancel_1617042',
-  },
-  {
     # Avoid a shutdown crash with multi-threaded message loop caused by
     # |g_browser_task_executor->browser_ui_thread_scheduler_| being null when
     # BrowserTaskExecutor::Shutdown is called via CefContext::FinalizeShutdown.
@@ -429,6 +486,15 @@
     'name': 'browser_scheduler',
   },
   {
+    # Restore access to WebUIControllerFactory::UnregisterFactoryForTesting
+    # which was removed in https://crrev.com/5f183d6636. We can't use
+    # ScopedWebUIControllerFactoryRegistration because it pulls in GTest
+    # dependencies.
+    #
+    # Add accessor for WebUIConfigMap::webui_controller_factory_.
+    'name': 'browser_web_ui_controller_factory',
+  },
+  {
     # Avoid a shutdown crash caused by PrefWatcher holding a reference to
     # |g_browser_process->local_state()|, and the local_state being deleted
     # before the PrefWatcher object (which is associated with a Profile).
@@ -439,7 +505,7 @@
   },
   {
     # Add support for OSR rendering with Viz.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2575
+    # https://github.com/chromiumembedded/cef/issues/2575
     'name': 'viz_osr_2575',
   },
   {
@@ -449,33 +515,43 @@
     # - Remove unsupported print preview UI options.
     # - macOS: Fix error: no member named 'kCloudPrinterHandler' in namespace
     #   'printing::features',
-    # https://bitbucket.org/chromiumembedded/cef/issues/123
+    # https://github.com/chromiumembedded/cef/issues/123
     'name': 'print_preview_123',
   },
   {
-    # Remove cef_sandbox dependency on boringssl MD5/SHA1 functions.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2743
+    # Store command-line switch names as lower-case ASCII on all platforms.
+    # https://github.com/chromiumembedded/cef/issues/1872
+    'name': 'base_command_line_1872',
+  },
+  {
+    # Remove cef_sandbox dependency on boringssl functions.
+    # https://github.com/chromiumembedded/cef/issues/2743
+    #
+    # Enable the VS 2015 Update 2 fix when building with the MSVC standard
+    # library.
+    #
+    # Avoid usage of std::atomic_flag::test() added in C++20.
+    # https://github.com/llvm/llvm-project/issues/57364
+    #
+    # Avoid usage of PartitionAlloc assertions (PA_BASE_CHECK) in raw_ptr.h.
     'name': 'base_sandbox_2743',
   },
   {
-    # Fix component build error due to ContentServiceManagerMainDelegate not
-    # being exported.
-    #
-    # Fix DiscardableSharedMemoryManager crash on shutdown with multi-threaded
-    # message loop.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2798
-    'name': 'content_app_shutdown_2798',
+    # Windows: Fix MSVC compile errors using base::MakeFixedFlatMapSorted
+    # in registry.cc when building cef_sandbox.
+    # https://github.com/chromiumembedded/cef/issues/3519
+    'name': 'base_sandbox_3519',
   },
   {
     # Add RenderWidgetHostImpl::SetCompositorForFlingScheduler to fix fling
     # scrolling in OSR mode.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2745
+    # https://github.com/chromiumembedded/cef/issues/2745
     'name': 'osr_fling_2745',
   },
   {
     # Windows: Build targets as C++17 to avoid export of std::is_integral
     # templates in cef_sandbox that should be inlined.
-    # https://bitbucket.org/chromiumembedded/cef/issues/2819
+    # https://github.com/chromiumembedded/cef/issues/2819
     'name': 'win_cpp17_msvc_sandbox_2819',
   },
   {
@@ -484,11 +560,6 @@
     'name': 'libxml_visibility',
   },
   {
-    # Fix ScreenlockMonitorDeviceSource window creation error.
-    # https://bugs.chromium.org/p/chromium/issues/detail?id=1058556
-    'name': 'win_screenlock_1058556',
-  },
-  {
     # Fix unbound AssociatedRemote error in SetBackgroundOpaque.
     # https://bugs.chromium.org/p/chromium/issues/detail?id=1070713
     'name': 'renderer_host_1070713',
@@ -497,12 +568,120 @@
     # Allow the loading of non-standard non-local WebSafe custom schemes in
     # iframes.
     # https://bugs.chromium.org/p/chromium/issues/detail?id=1081397#c9
+    #
+    # Fix crash in NavigationRequest::GetOriginForURLLoaderFactory() when
+    # navigating to an unregistered (e.g. non-standard) scheme.
+    # https://github.com/chromiumembedded/cef/issues/3105
     'name': 'browser_security_policy_1081397',
   },
   {
-    # Linux: Fix undefined symbol: ui::GtkUiDelegate::SetInstance in
-    # ChromeBrowserMainExtraPartsViewsLinux::ToolkitInitialized.
-    # https://bugs.chromium.org/p/chromium/issues/detail?id=1085806
-    'name': 'linux_chrome_views_1085806',
+    # Fix build errors with enable_background_mode=false.
+    # https://bugs.chromium.org/p/chromium/issues/detail?id=1100085
+    #
+    # Changes to support the Chrome runtime in CEF (app_controller_mac.mm).
+    # https://github.com/chromiumembedded/cef/issues/2969
+    'name': 'chrome_browser_background_mode_1100085',
+  },
+  {
+    # Linux: Fix ATK assertion error when generating ARM build config.
+    # https://bugs.chromium.org/p/chromium/issues/detail?id=1123214
+    'name': 'linux_atk_1123214',
+  },
+  {
+    # Windows: Fix crash when |sandbox_info| parameter is nullptr.
+    # https://github.com/chromiumembedded/cef/issues/3210
+    'name': 'win_sandbox_3210',
+  },
+  {
+    # Windows: Fix MSVC compile error with sandbox target.
+    # error: static assertion failed due to requirement
+    # '!is_const_v<const unsigned char>': The C++ Standard forbids
+    # containers of const elements because allocator<const T> is ill-formed.
+    'name': 'win_sandbox_policy',
+  },
+  {
+    # Windows: Always use the root window as the owner for shell dialogs.
+    # https://github.com/chromiumembedded/cef/issues/3294
+    'name': 'win_shell_dialogs_3294',
+  },
+  {
+    # Linux: Fix duplicate symbol error due to bluez/metrics_recorder.cc.
+    # https://bugs.chromium.org/p/chromium/issues/detail?id=1319006
+    'name': 'linux_bluetooth_1319006',
+  },
+  {
+    # Linux: Support chaining of PrintingContextLinux callbacks.
+    # https://github.com/chromiumembedded/cef/issues/3314
+    # Also reverts the changes from https://crrev.com/db245883e1
+    'name': 'linux_printing_context',
+  },
+  {
+    # Fix deadlock in EmbeddedTestServer::ShutdownAndWaitUntilComplete.
+    # https://chromium-review.googlesource.com/c/chromium/src/+/3798752
+    'name': 'net_test_server_3798752'
+  },
+  {
+    # Linux: Fix "error: use of result of assignment to object of volatile-
+    # qualified type 'volatile gsize' (aka 'volatile unsigned long') is
+    # deprecated [-Werror,-Wdeprecated-volatile]" when building with
+    # use_sysroot=false on Ubuntu 18.04.
+    # https://chromium-review.googlesource.com/c/chromium/src/+/3960017
+    'name': 'linux_glib_deprecated_volatile'
+  },
+  {
+    # Restore low-level attribute access from WebElement which was removed in
+    # https://chromium-review.googlesource.com/c/chromium/src/+/4200240
+    'name': 'blink_web_element_4200240'
+  },
+  {
+    # Fix ThreadChecker crash on startup with Chrome runtime + multi-threaded
+    # message loop.
+    'name': 'metrics_system_profile'
+  },
+  {
+    # macOS: Remove run-time dependency on libtest_trace_processor.dylib
+    # Reverts the changes from https://crrev.com/8b18bd125d
+    'name': 'base_test_4396276'
+  },
+  {
+    # Create top-level widget type when Widget::InitParams::child is false.
+    'name': 'ui_views_widget_type'
+  },
+  {
+    # win/linux: Fix rounding errors with Screen[Win] DIP/pixel conversions.
+    # https://bugs.chromium.org/p/chromium/issues/detail?id=1443650#c18
+    'name': 'screen_1443650'
+  },
+  {
+    # mac: Keep bubble popups on-screen.
+    # https://bugs.chromium.org/p/chromium/issues/detail?id=893292#c10
+    'name': 'mac_platform_style_bubble_893292'
+  },
+  {
+    # mac: Fix NOTREACHED with ViewsTextfieldTest.TextfieldKeyEvent.
+    # https://bugs.chromium.org/p/chromium/issues/detail?id=1467329
+    'name': 'mac_keyboard_conversion_1467329'
+  },
+  {
+    # win: Add support for "force-light-mode" command-line option.
+    # mac: Add support for "force-light-mode" and "force-dark-mode".
+    # https://github.com/chromiumembedded/cef/issues/3534
+    # https://chromium-review.googlesource.com/c/chromium/src/+/4766248
+    'name': 'light_mode_3534'
+  },
+  {
+    # Fix NOTREACHED() in RenderFrameHostImpl::CommitNavigation() with
+    # CorsTest.IframeNoneServerToCustomUnregisteredScheme.
+    # Fix bad optional access in VerifyInitiatorOrigin() with
+    # RequestHandlerTest.NotificationsCrossOriginDelayedRenderer.
+    # Partially reverts the below changes.
+    # https://chromium-review.googlesource.com/c/chromium/src/+/4829483
+    # https://bugs.chromium.org/p/chromium/issues/detail?id=1470837#c22
+    'name': 'rfh_navigation_4829483'
+  },
+  {
+    # linux: Disable compiler TLS in libxml2.
+    # https://github.com/chromiumembedded/cef/issues/3616
+    'name': 'linux_libxml_tls_3616'
   }
 ]
diff --git a/src/patch/patches/base_command_line_1872.patch b/src/patch/patches/base_command_line_1872.patch
new file mode 100644
index 0000000..40a7b12
--- /dev/null
+++ b/src/patch/patches/base_command_line_1872.patch
@@ -0,0 +1,17 @@
+diff --git base/command_line.cc base/command_line.cc
+index d762b168a9ccf..f58b4f783df16 100644
+--- base/command_line.cc
++++ base/command_line.cc
+@@ -346,11 +346,10 @@ void CommandLine::AppendSwitchNative(StringPiece switch_string,
+ #if BUILDFLAG(ENABLE_COMMANDLINE_SEQUENCE_CHECKS)
+   sequence_checker_.Check();
+ #endif
+-#if BUILDFLAG(IS_WIN)
+   const std::string switch_key = ToLowerASCII(switch_string);
++#if BUILDFLAG(IS_WIN)
+   StringType combined_switch_string(UTF8ToWide(switch_key));
+ #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
+-  StringPiece switch_key = switch_string;
+   StringType combined_switch_string(switch_key);
+ #endif
+   size_t prefix_length = GetSwitchPrefixLength(combined_switch_string);
diff --git a/src/patch/patches/base_sandbox_2743.patch b/src/patch/patches/base_sandbox_2743.patch
index 1c39edf..59b8a3f 100644
--- a/src/patch/patches/base_sandbox_2743.patch
+++ b/src/patch/patches/base_sandbox_2743.patch
@@ -1,16 +1,16 @@
 diff --git base/BUILD.gn base/BUILD.gn
-index 8df68ae89306..aa23704044be 100644
+index 55479f4187323..207b9e3a1e281 100644
 --- base/BUILD.gn
 +++ base/BUILD.gn
-@@ -33,6 +33,7 @@ import("//build/config/sysroot.gni")
- import("//build/config/ui.gni")
+@@ -40,6 +40,7 @@ import("//build/config/ui.gni")
  import("//build/nocompile.gni")
  import("//build/timestamp.gni")
+ import("//build_overrides/build.gni")
 +import("//cef/libcef/features/features.gni")
  import("//testing/libfuzzer/fuzzer_test.gni")
  import("//testing/test.gni")
- import("//third_party/icu/config.gni")
-@@ -1656,7 +1657,11 @@ jumbo_component("base") {
+ 
+@@ -1495,7 +1496,11 @@ component("base") {
      "hash/md5_constexpr_internal.h",
      "hash/sha1.h",
    ]
@@ -23,8 +23,42 @@
      sources += [
        "hash/md5_nacl.cc",
        "hash/md5_nacl.h",
+@@ -1909,6 +1914,12 @@ component("base") {
+       defines += [ "COM_INIT_CHECK_HOOK_DISABLED" ]
+     }
+ 
++    if (!use_custom_libcxx) {
++      # Enable the VS 2015 Update 2 fix when building with the MSVC standard
++      # library.
++      defines += [ "_ENABLE_ATOMIC_ALIGNMENT_FIX" ]
++    }
++
+     libs += [
+       "cfgmgr32.lib",
+       "ntdll.lib",
+diff --git base/allocator/dispatcher/dispatcher.cc base/allocator/dispatcher/dispatcher.cc
+index 616e2e89af7d3..2a2993e74d53a 100644
+--- base/allocator/dispatcher/dispatcher.cc
++++ base/allocator/dispatcher/dispatcher.cc
+@@ -10,6 +10,7 @@
+ #include "base/check.h"
+ #include "base/dcheck_is_on.h"
+ #include "base/no_destructor.h"
++#include "cef/libcef/features/features.h"
+ 
+ #if DCHECK_IS_ON()
+ #include <atomic>
+@@ -33,7 +34,7 @@ struct Dispatcher::Impl {
+   }
+ 
+   void Reset() {
+-#if DCHECK_IS_ON()
++#if DCHECK_IS_ON() && !BUILDFLAG(IS_CEF_SANDBOX_BUILD)
+     DCHECK([&]() {
+       auto const was_set = is_initialized_check_flag_.test_and_set();
+       is_initialized_check_flag_.clear();
 diff --git base/hash/md5.h base/hash/md5.h
-index 8a49f08dcb04..2f03d7a6d1b3 100644
+index aa889f350e8f7..50acac8a69225 100644
 --- base/hash/md5.h
 +++ base/hash/md5.h
 @@ -10,8 +10,9 @@
@@ -33,8 +67,167 @@
  #include "build/build_config.h"
 +#include "cef/libcef/features/features.h"
  
--#if defined(OS_NACL)
-+#if defined(OS_NACL) || BUILDFLAG(IS_CEF_SANDBOX_BUILD)
+-#if BUILDFLAG(IS_NACL)
++#if BUILDFLAG(IS_NACL) || BUILDFLAG(IS_CEF_SANDBOX_BUILD)
  #include "base/hash/md5_nacl.h"
  #else
  #include "base/hash/md5_boringssl.h"
+diff --git base/hash/sha1.h base/hash/sha1.h
+index 29626e5853c6e..2fb1c61504c5d 100644
+--- base/hash/sha1.h
++++ base/hash/sha1.h
+@@ -14,7 +14,9 @@
+ #include "base/containers/span.h"
+ #include "base/strings/string_piece.h"
+ #include "build/build_config.h"
+-#if BUILDFLAG(IS_NACL)
++#include "cef/libcef/features/features.h"
++
++#if BUILDFLAG(IS_NACL) || BUILDFLAG(IS_CEF_SANDBOX_BUILD)
+ #include "base/hash/sha1_nacl.h"
+ #else
+ #include "base/hash/sha1_boringssl.h"
+diff --git base/rand_util.h base/rand_util.h
+index c9dd1249660c1..7d68b0d893e3d 100644
+--- base/rand_util.h
++++ base/rand_util.h
+@@ -15,8 +15,9 @@
+ #include "base/compiler_specific.h"
+ #include "base/gtest_prod_util.h"
+ #include "build/build_config.h"
++#include "cef/libcef/features/features.h"
+ 
+-#if !BUILDFLAG(IS_NACL)
++#if !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_CEF_SANDBOX_BUILD)
+ #include "third_party/boringssl/src/include/openssl/rand.h"
+ #endif
+ 
+@@ -97,7 +98,7 @@ class RandomBitGenerator {
+   ~RandomBitGenerator() = default;
+ };
+ 
+-#if !BUILDFLAG(IS_NACL)
++#if !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_CEF_SANDBOX_BUILD)
+ class NonAllocatingRandomBitGenerator {
+  public:
+   using result_type = uint64_t;
+diff --git base/rand_util_win.cc base/rand_util_win.cc
+index 549f4362af8b6..f08b1b2e7f061 100644
+--- base/rand_util_win.cc
++++ base/rand_util_win.cc
+@@ -15,8 +15,12 @@
+ 
+ #include "base/check.h"
+ #include "base/feature_list.h"
++#include "cef/libcef/features/features.h"
++
++#if !BUILDFLAG(IS_CEF_SANDBOX_BUILD)
+ #include "third_party/boringssl/src/include/openssl/crypto.h"
+ #include "third_party/boringssl/src/include/openssl/rand.h"
++#endif
+ 
+ // Prototype for ProcessPrng.
+ // See: https://learn.microsoft.com/en-us/windows/win32/seccng/processprng
+@@ -28,6 +32,7 @@ namespace base {
+ 
+ namespace internal {
+ 
++#if !BUILDFLAG(IS_CEF_SANDBOX_BUILD)
+ namespace {
+ 
+ // The BoringSSl helpers are duplicated in rand_util_fuchsia.cc and
+@@ -49,6 +54,10 @@ bool UseBoringSSLForRandBytes() {
+   return g_use_boringssl.load(std::memory_order_relaxed);
+ }
+ 
++#else  // !BUILDFLAG(IS_CEF_SANDBOX_BUILD)
++void ConfigureBoringSSLBackedRandBytesFieldTrial() {}
++#endif
++
+ }  // namespace internal
+ 
+ namespace {
+@@ -66,6 +75,7 @@ decltype(&ProcessPrng) GetProcessPrng() {
+ }
+ 
+ void RandBytes(void* output, size_t output_length, bool avoid_allocation) {
++#if !BUILDFLAG(IS_CEF_SANDBOX_BUILD)
+   if (!avoid_allocation && internal::UseBoringSSLForRandBytes()) {
+     // Ensure BoringSSL is initialized so it can use things like RDRAND.
+     CRYPTO_library_init();
+@@ -73,6 +83,7 @@ void RandBytes(void* output, size_t output_length, bool avoid_allocation) {
+     (void)RAND_bytes(static_cast<uint8_t*>(output), output_length);
+     return;
+   }
++#endif  // !BUILDFLAG(IS_CEF_SANDBOX_BUILD)
+ 
+   static decltype(&ProcessPrng) process_prng_fn = GetProcessPrng();
+   BOOL success = process_prng_fn(static_cast<BYTE*>(output), output_length);
+diff --git base/unguessable_token.cc base/unguessable_token.cc
+index aa7423f88d278..1b2c7d3e3c4a0 100644
+--- base/unguessable_token.cc
++++ base/unguessable_token.cc
+@@ -10,8 +10,9 @@
+ #include "base/format_macros.h"
+ #include "base/rand_util.h"
+ #include "build/build_config.h"
++#include "cef/libcef/features/features.h"
+ 
+-#if !BUILDFLAG(IS_NACL)
++#if !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_CEF_SANDBOX_BUILD)
+ #include "third_party/boringssl/src/include/openssl/mem.h"
+ #endif
+ 
+@@ -46,7 +47,7 @@ absl::optional<UnguessableToken> UnguessableToken::Deserialize(uint64_t high,
+ }
+ 
+ bool UnguessableToken::operator==(const UnguessableToken& other) const {
+-#if BUILDFLAG(IS_NACL)
++#if BUILDFLAG(IS_NACL) || BUILDFLAG(IS_CEF_SANDBOX_BUILD)
+   // BoringSSL is unavailable for NaCl builds so it remains timing dependent.
+   return token_ == other.token_;
+ #else
+diff --git base/win/sid.cc base/win/sid.cc
+index 0f1a2ec79aa4b..7f92778a4a776 100644
+--- base/win/sid.cc
++++ base/win/sid.cc
+@@ -15,6 +15,7 @@
+ #include <utility>
+ 
+ #include "base/check.h"
++#include "base/notreached.h"
+ #include "base/no_destructor.h"
+ #include "base/rand_util.h"
+ #include "base/ranges/algorithm.h"
+@@ -22,8 +23,12 @@
+ #include "base/win/scoped_handle.h"
+ #include "base/win/scoped_localalloc.h"
+ #include "base/win/windows_version.h"
++#include "cef/libcef/features/features.h"
++
++#if !BUILDFLAG(IS_CEF_SANDBOX_BUILD)
+ #include "third_party/boringssl/src/include/openssl/crypto.h"
+ #include "third_party/boringssl/src/include/openssl/sha.h"
++#endif
+ 
+ namespace base::win {
+ 
+@@ -124,6 +129,7 @@ Sid Sid::FromNamedCapability(const std::wstring& capability_name) {
+   if (known_cap != known_capabilities->end()) {
+     return FromKnownCapability(known_cap->second);
+   }
++#if !BUILDFLAG(IS_CEF_SANDBOX_BUILD)
+   CRYPTO_library_init();
+   static_assert((SHA256_DIGEST_LENGTH / sizeof(DWORD)) ==
+                 SECURITY_APP_PACKAGE_RID_COUNT);
+@@ -136,6 +142,10 @@ Sid Sid::FromNamedCapability(const std::wstring& capability_name) {
+          reinterpret_cast<uint8_t*>(&rids[2]));
+   return FromSubAuthorities(SECURITY_APP_PACKAGE_AUTHORITY, std::size(rids),
+                             rids);
++#else
++  NOTREACHED();
++  return Sid(WellKnownSid::kNull);
++#endif
+ }
+ 
+ Sid Sid::FromKnownSid(WellKnownSid type) {
diff --git a/src/patch/patches/base_sandbox_3519.patch b/src/patch/patches/base_sandbox_3519.patch
new file mode 100644
index 0000000..e5f9cb9
--- /dev/null
+++ b/src/patch/patches/base_sandbox_3519.patch
@@ -0,0 +1,53 @@
+diff --git base/ranges/ranges.h base/ranges/ranges.h
+index 641bbaf2c7576..afdd641e38452 100644
+--- base/ranges/ranges.h
++++ base/ranges/ranges.h
+@@ -30,12 +30,14 @@ constexpr T* begin(std::array<T, N>& array, priority_tag<2> tag) {
+   return const_cast<T*>(begin(const_cast<const std::array<T, N>&>(array), tag));
+ }
+ 
++#if !defined(CEF_EXCLUDE_PROBLEMATIC_CONST_ARRAY_OVERLOADS)
+ // Overload for const std::array. Required since std::array::begin is not
+ // constexpr prior to C++17.
+ template <typename T, size_t N>
+ constexpr const T* begin(const std::array<T, N>& array, priority_tag<2>) {
+   return N != 0 ? &array[0] : nullptr;
+ }
++#endif
+ 
+ // Generic container overload.
+ template <typename Range>
+@@ -65,12 +67,14 @@ constexpr T* end(std::array<T, N>& array, priority_tag<2> tag) {
+   return const_cast<T*>(end(const_cast<const std::array<T, N>&>(array), tag));
+ }
+ 
++#if !defined(CEF_EXCLUDE_PROBLEMATIC_CONST_ARRAY_OVERLOADS)
+ // Overload for const std::array. Required since std::array::end is not
+ // constexpr prior to C++17.
+ template <typename T, size_t N>
+ constexpr const T* end(const std::array<T, N>& array, priority_tag<2>) {
+   return N != 0 ? (&array[0]) + N : nullptr;
+ }
++#endif
+ 
+ // Generic container overload.
+ template <typename Range>
+diff --git base/win/registry.cc base/win/registry.cc
+index 7b9dcb90e627e..275b60e6c2a28 100644
+--- base/win/registry.cc
++++ base/win/registry.cc
+@@ -14,6 +14,14 @@
+ #include <utility>
+ #include <vector>
+ 
++#include "cef/libcef/features/features.h"
++
++#if BUILDFLAG(IS_CEF_SANDBOX_BUILD)
++// Avoid overloads for const std::array in base/ranges/ranges.h that don't
++// compile with MSVC. See issue #3519.
++#define CEF_EXCLUDE_PROBLEMATIC_CONST_ARRAY_OVERLOADS 1
++#endif
++
+ #include "base/check_op.h"
+ #include "base/functional/callback.h"
+ #include "base/notreached.h"
diff --git a/src/patch/patches/base_test_4396276.patch b/src/patch/patches/base_test_4396276.patch
new file mode 100644
index 0000000..2fc5d8a
--- /dev/null
+++ b/src/patch/patches/base_test_4396276.patch
@@ -0,0 +1,101 @@
+diff --git base/test/BUILD.gn base/test/BUILD.gn
+index 90df027353fe7..fdfc6c6d450d9 100644
+--- base/test/BUILD.gn
++++ base/test/BUILD.gn
+@@ -189,11 +189,6 @@ static_library("test_support") {
+ 
+   if (enable_base_tracing) {
+     public_deps += [ "//third_party/perfetto:perfetto_test_support" ]
+-    public_deps += [ ":test_trace_processor" ]
+-    sources += [
+-      "test_trace_processor.cc",
+-      "test_trace_processor.h",
+-    ]
+     deps += [ ":gen_cc_chrome_track_event_descriptor" ]
+     if (is_ios) {
+       deps += [
+@@ -537,7 +532,7 @@ if (enable_base_tracing) {
+   # processor depends on dev_sqlite. The two share the same symbols but have
+   # different implementations, so we need to hide dev_sqlite in this shared
+   # library even in non-component builds to prevent duplicate symbols.
+-  _target_type = "shared_library"
++  _target_type = "component"
+   if (is_ios) {
+     _target_type = "ios_framework_bundle"
+   }
+@@ -546,6 +541,8 @@ if (enable_base_tracing) {
+     defines = [ "TEST_TRACE_PROCESSOR_IMPL" ]
+     testonly = true
+     sources = [
++      "test_trace_processor.cc",
++      "test_trace_processor.h",
+       "test_trace_processor_export.h",
+       "test_trace_processor_impl.cc",
+       "test_trace_processor_impl.h",
+@@ -563,33 +560,6 @@ if (enable_base_tracing) {
+       output_name = "TestTraceProcessor"
+       bundle_deps_filter = [ "//third_party/icu:icudata" ]
+     }
+-
+-    # Set rpath on dependent tests so that they can find the shared library
+-    # in a non-component build.
+-    if (!is_component_build) {
+-      all_dependent_configs = []
+-      if (is_linux || is_chromeos) {
+-        all_dependent_configs +=
+-            [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
+-      }
+-      if (is_mac) {
+-        # We need the lib to be in $root_out_dir/Libraries so the library is where
+-        # the linker expects it, since we set the install_name flag. We need to
+-        # set this flag so that the library can be found when it is bundled in the
+-        # Content Shell Framework (see test_trace_processor_bundle_data).
+-        output_dir = "$root_out_dir/Libraries"
+-        ldflags = [ "-Wl,-install_name,@loader_path/Libraries/libtest_trace_processor.dylib" ]
+-      }
+-    }
+-  }
+-
+-  if (!is_component_build && is_mac) {
+-    bundle_data("test_trace_processor_bundle_data") {
+-      testonly = true
+-      sources = [ "$root_out_dir/Libraries/libtest_trace_processor.dylib" ]
+-      outputs = [ "{{bundle_contents_dir}}/Libraries/{{source_file_part}}" ]
+-      public_deps = [ ":test_trace_processor" ]
+-    }
+   }
+ } else if (!is_component_build && is_mac) {
+   # Provide a dummy target in order for clients to not have to special-case
+diff --git base/test/test_trace_processor_export.h base/test/test_trace_processor_export.h
+index f5191b804bc07..aadb7d66ba4c3 100644
+--- base/test/test_trace_processor_export.h
++++ base/test/test_trace_processor_export.h
+@@ -5,6 +5,7 @@
+ #ifndef BASE_TEST_TEST_TRACE_PROCESSOR_EXPORT_H_
+ #define BASE_TEST_TEST_TRACE_PROCESSOR_EXPORT_H_
+ 
++#if defined(COMPONENT_BUILD)
+ #if defined(WIN32)
+ 
+ #if defined(TEST_TRACE_PROCESSOR_IMPL)
+@@ -23,4 +24,8 @@
+ 
+ #endif  // defined(WIN32)
+ 
++#else  // defined(COMPONENT_BUILD)
++#define TEST_TRACE_PROCESSOR_EXPORT
++#endif
++
+ #endif  // BASE_TEST_TEST_TRACE_PROCESSOR_EXPORT_H_
+diff --git content/shell/BUILD.gn content/shell/BUILD.gn
+index acc54b120738f..6a79447c20513 100644
+--- content/shell/BUILD.gn
++++ content/shell/BUILD.gn
+@@ -842,7 +842,6 @@ if (is_mac) {
+       # Specify a sensible install_name for static builds. The library is
+       # dlopen()ed so this is not used to resolve the module.
+       ldflags = [ "-Wl,-install_name,@executable_path/../Frameworks/$output_name.framework/$output_name" ]
+-      deps += [ "//base/test:test_trace_processor_bundle_data" ]
+     } else {
+       # Both the main :content_shell and :content_shell_helper_app executables
+       # need to link the framework. Because they are at different directory
diff --git a/src/patch/patches/blink_web_element_4200240.patch b/src/patch/patches/blink_web_element_4200240.patch
new file mode 100644
index 0000000..48f6e81
--- /dev/null
+++ b/src/patch/patches/blink_web_element_4200240.patch
@@ -0,0 +1,43 @@
+diff --git third_party/blink/public/web/web_element.h third_party/blink/public/web/web_element.h
+index c9a9eb2da897c..7339ae9945fc4 100644
+--- third_party/blink/public/web/web_element.h
++++ third_party/blink/public/web/web_element.h
+@@ -81,6 +81,9 @@ class BLINK_EXPORT WebElement : public WebNode {
+   void SetAttribute(const WebString& name, const WebString& value);
+   WebString TextContent() const;
+   WebString InnerHTML() const;
++  WebString AttributeLocalName(unsigned index) const;
++  WebString AttributeValue(unsigned index) const;
++  unsigned AttributeCount() const;
+ 
+   // Returns all <label> elements associated to this element.
+   WebVector<WebLabelElement> Labels() const;
+diff --git third_party/blink/renderer/core/exported/web_element.cc third_party/blink/renderer/core/exported/web_element.cc
+index 496d5181ff522..f98339358e9d4 100644
+--- third_party/blink/renderer/core/exported/web_element.cc
++++ third_party/blink/renderer/core/exported/web_element.cc
+@@ -106,6 +106,24 @@ void WebElement::SetAttribute(const WebString& attr_name,
+                                   IGNORE_EXCEPTION_FOR_TESTING);
+ }
+ 
++unsigned WebElement::AttributeCount() const {
++  if (!ConstUnwrap<Element>()->hasAttributes())
++    return 0;
++  return ConstUnwrap<Element>()->Attributes().size();
++}
++
++WebString WebElement::AttributeLocalName(unsigned index) const {
++  if (index >= AttributeCount())
++    return WebString();
++  return ConstUnwrap<Element>()->Attributes().at(index).LocalName();
++}
++
++WebString WebElement::AttributeValue(unsigned index) const {
++  if (index >= AttributeCount())
++    return WebString();
++  return ConstUnwrap<Element>()->Attributes().at(index).Value();
++}
++
+ WebString WebElement::TextContent() const {
+   return ConstUnwrap<Element>()->textContent();
+ }
diff --git a/src/patch/patches/browser_compositor_mac.patch b/src/patch/patches/browser_compositor_mac.patch
deleted file mode 100644
index 6f48449..0000000
--- a/src/patch/patches/browser_compositor_mac.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-diff --git content/browser/renderer_host/browser_compositor_view_mac.h content/browser/renderer_host/browser_compositor_view_mac.h
-index af7b3249d421..1483a48f9074 100644
---- content/browser/renderer_host/browser_compositor_view_mac.h
-+++ content/browser/renderer_host/browser_compositor_view_mac.h
-@@ -58,6 +58,8 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
- 
-   // These will not return nullptr until Destroy is called.
-   DelegatedFrameHost* GetDelegatedFrameHost();
-+  ui::Layer* GetRootLayer() { return root_layer_.get(); }
-+  ui::Compositor* GetCompositor();
- 
-   // Force a new surface id to be allocated. Returns true if the
-   // RenderWidgetHostImpl sent the resulting surface id to the renderer.
-diff --git content/browser/renderer_host/browser_compositor_view_mac.mm content/browser/renderer_host/browser_compositor_view_mac.mm
-index ac9fdebbc87d..ebb2556ad908 100644
---- content/browser/renderer_host/browser_compositor_view_mac.mm
-+++ content/browser/renderer_host/browser_compositor_view_mac.mm
-@@ -85,6 +85,12 @@ DelegatedFrameHost* BrowserCompositorMac::GetDelegatedFrameHost() {
-   return delegated_frame_host_.get();
- }
- 
-+ui::Compositor* BrowserCompositorMac::GetCompositor() {
-+  if (recyclable_compositor_)
-+    return recyclable_compositor_->compositor();
-+  return nullptr;
-+}
-+
- bool BrowserCompositorMac::ForceNewSurfaceId() {
-   dfh_local_surface_id_allocator_.GenerateId();
-   delegated_frame_host_->EmbedSurface(
diff --git a/src/patch/patches/browser_scheduler.patch b/src/patch/patches/browser_scheduler.patch
index 0f719d2..7f08060 100644
--- a/src/patch/patches/browser_scheduler.patch
+++ b/src/patch/patches/browser_scheduler.patch
@@ -1,8 +1,8 @@
 diff --git content/browser/scheduler/browser_task_executor.cc content/browser/scheduler/browser_task_executor.cc
-index 332ef34e24dc..ee866ca5f3b6 100644
+index 307d5b7ffca63..9a8f0a4d3d7bd 100644
 --- content/browser/scheduler/browser_task_executor.cc
 +++ content/browser/scheduler/browser_task_executor.cc
-@@ -244,7 +244,7 @@ void BrowserTaskExecutor::PostFeatureListSetup() {
+@@ -209,7 +209,7 @@ BrowserTaskExecutor::OnUserInputStart() {
  
  // static
  void BrowserTaskExecutor::Shutdown() {
@@ -10,4 +10,4 @@
 +  if (!g_browser_task_executor || !g_browser_task_executor->ui_thread_executor_)
      return;
  
-   DCHECK(g_browser_task_executor->ui_thread_executor_);
+   DCHECK(Get()->ui_thread_executor_);
diff --git a/src/patch/patches/browser_security_policy_1081397.patch b/src/patch/patches/browser_security_policy_1081397.patch
index 7e00f34..1a03adb 100644
--- a/src/patch/patches/browser_security_policy_1081397.patch
+++ b/src/patch/patches/browser_security_policy_1081397.patch
@@ -1,21 +1,65 @@
 diff --git content/browser/child_process_security_policy_impl.cc content/browser/child_process_security_policy_impl.cc
-index bcd42e788019..6a7a164a527a 100644
+index 401eb0cd40ee2..5e7ac0b6d9d0a 100644
 --- content/browser/child_process_security_policy_impl.cc
 +++ content/browser/child_process_security_policy_impl.cc
-@@ -1469,6 +1469,16 @@ bool ChildProcessSecurityPolicyImpl::CanAccessDataForOrigin(
-         // DeclarativeApiTest.PersistRules.
-         if (actual_process_lock.SchemeIs(url::kDataScheme))
-           return true;
+@@ -1866,6 +1866,16 @@ bool ChildProcessSecurityPolicyImpl::CanAccessDataForMaybeOpaqueOrigin(
+             // DeclarativeApiTest.PersistRules.
+             if (actual_process_lock.matches_scheme(url::kDataScheme))
+               return true;
 +
-+        // Allow other schemes that are non-standard, non-local and WebSafe.
-+        if (actual_process_lock.is_valid() &&
-+            !actual_process_lock.IsStandard() &&
-+            !base::Contains(url::GetLocalSchemes(),
-+                            actual_process_lock.scheme_piece()) &&
-+            base::Contains(schemes_okay_to_request_in_any_process_,
-+                           actual_process_lock.scheme_piece())) {
-+          return true;
-+        }
-       }
++            // Allow other schemes that are non-standard, non-local and WebSafe.
++            if (lock_url.is_valid() &&
++                !lock_url.IsStandard() &&
++                !base::Contains(url::GetLocalSchemes(),
++                                lock_url.scheme_piece()) &&
++                base::Contains(schemes_okay_to_request_in_any_process_,
++                               lock_url.scheme())) {
++              return true;
++            }
+           }
  
-       failure_reason = "lock_mismatch";
+           // Make an exception to allow most visited tiles to commit in
+diff --git content/browser/renderer_host/navigation_request.cc content/browser/renderer_host/navigation_request.cc
+index 8ba07ea436976..12baff0903754 100644
+--- content/browser/renderer_host/navigation_request.cc
++++ content/browser/renderer_host/navigation_request.cc
+@@ -7464,10 +7464,22 @@ NavigationRequest::GetOriginForURLLoaderFactoryBeforeResponseWithDebugInfo(
+   bool use_opaque_origin =
+       (sandbox_flags & network::mojom::WebSandboxFlags::kOrigin) ==
+       network::mojom::WebSandboxFlags::kOrigin;
++  if (use_opaque_origin) {
++    origin_and_debug_info.second += ", sandbox_flags";
++  }
++
++  if (!origin_and_debug_info.first.GetURL().IsStandard()) {
++    // Always return an opaque origin for non-standard URLs. Otherwise, the
++    // CanAccessDataForOrigin() check may fail for unregistered custom scheme
++    // requests in CEF.
++    use_opaque_origin = true;
++    origin_and_debug_info.second += ", cef_nonstandard";
++  }
++
+   if (use_opaque_origin) {
+     origin_and_debug_info =
+         std::make_pair(origin_and_debug_info.first.DeriveNewOpaqueOrigin(),
+-                       origin_and_debug_info.second + ", sandbox_flags");
++                       origin_and_debug_info.second);
+   }
+ 
+   return origin_and_debug_info;
+@@ -7573,6 +7585,15 @@ NavigationRequest::GetOriginForURLLoaderFactoryAfterResponseWithDebugInfo() {
+       DetermineInitiatorRelationship(initiator_rfh,
+                                      frame_tree_node_->current_frame_host()));
+ 
++  if (origin_with_debug_info.first.opaque() &&
++      origin_with_debug_info.second.find("cef_nonstandard") !=
++          std::string::npos) {
++    // Always return an opaque origin for non-standard URLs. Otherwise, the
++    // below CanAccessDataForOrigin() check may fail for unregistered custom
++    // scheme requests in CEF.
++    return origin_with_debug_info;
++  }
++
+   // MHTML documents should commit as an opaque origin. They should not be able
+   // to make network request on behalf of the real origin.
+   DCHECK(!IsMhtmlOrSubframe() || origin_with_debug_info.first.opaque());
diff --git a/src/patch/patches/browser_web_ui_controller_factory.patch b/src/patch/patches/browser_web_ui_controller_factory.patch
new file mode 100644
index 0000000..652d0d0
--- /dev/null
+++ b/src/patch/patches/browser_web_ui_controller_factory.patch
@@ -0,0 +1,29 @@
+diff --git content/public/browser/web_ui_controller_factory.h content/public/browser/web_ui_controller_factory.h
+index 9d9c17ffd6474..4eb79c65369af 100644
+--- content/public/browser/web_ui_controller_factory.h
++++ content/public/browser/web_ui_controller_factory.h
+@@ -47,9 +47,6 @@ class CONTENT_EXPORT WebUIControllerFactory {
+   virtual bool UseWebUIForURL(BrowserContext* browser_context,
+                               const GURL& url) = 0;
+ 
+- private:
+-  friend class ScopedWebUIControllerFactoryRegistration;
+-
+   static void UnregisterFactoryForTesting(WebUIControllerFactory* factory);
+ };
+ 
+diff --git content/public/browser/webui_config_map.h content/public/browser/webui_config_map.h
+index a80034506bf45..4bda477df0558 100644
+--- content/public/browser/webui_config_map.h
++++ content/public/browser/webui_config_map.h
+@@ -61,6 +61,10 @@ class CONTENT_EXPORT WebUIConfigMap {
+   // Returns the size of the map, i.e. how many WebUIConfigs are registered.
+   size_t GetSizeForTesting() { return configs_map_.size(); }
+ 
++  WebUIControllerFactory* controller_factory() const {
++    return webui_controller_factory_.get();
++  }
++
+  private:
+   void AddWebUIConfigImpl(std::unique_ptr<WebUIConfig> config);
+ 
diff --git a/src/patch/patches/build.patch b/src/patch/patches/build.patch
index 65adb12..abb212e 100644
--- a/src/patch/patches/build.patch
+++ b/src/patch/patches/build.patch
@@ -1,19 +1,10 @@
 diff --git build/config/compiler/BUILD.gn build/config/compiler/BUILD.gn
-index 4c5e6779efda..a75448436eab 100644
+index 6d05512ae3644..d67b22be8ecea 100644
 --- build/config/compiler/BUILD.gn
 +++ build/config/compiler/BUILD.gn
-@@ -172,7 +172,7 @@ declare_args() {
-             !use_clang_coverage && !(is_android && use_order_profiling) &&
-             (use_lld ||
-              (use_gold &&
--              ((!is_android && linux_use_bundled_binutils) || is_chromeos ||
-+              ((!is_android && linux_use_bundled_binutils && current_cpu != "x86") || is_chromeos ||
-                !(current_cpu == "x86" || current_cpu == "x64"))))
- }
- 
-@@ -1755,8 +1755,6 @@ config("thin_archive") {
-   # archive names to 16 characters, which is not what we want).
-   if ((is_posix && !is_nacl && !is_mac && !is_ios) || is_fuchsia) {
+@@ -2116,8 +2116,6 @@ config("thin_archive") {
+   # confuses lldb.
+   if ((is_posix && !is_nacl && !is_apple) || is_fuchsia) {
      arflags = [ "-T" ]
 -  } else if (is_win && use_lld) {
 -    arflags = [ "/llvmlibthin" ]
diff --git a/src/patch/patches/chrome_browser.patch b/src/patch/patches/chrome_browser.patch
index 0353bb7..dd760e8 100644
--- a/src/patch/patches/chrome_browser.patch
+++ b/src/patch/patches/chrome_browser.patch
@@ -1,24 +1,24 @@
 diff --git chrome/browser/BUILD.gn chrome/browser/BUILD.gn
-index b3f8ac152722..89a49bdd1e8a 100644
+index 7cb8d3fc03da2..e643e73f80930 100644
 --- chrome/browser/BUILD.gn
 +++ chrome/browser/BUILD.gn
-@@ -11,6 +11,7 @@ import("//build/config/features.gni")
- import("//build/config/jumbo.gni")
- import("//build/config/linux/gtk/gtk.gni")
+@@ -11,6 +11,7 @@ import("//build/config/compiler/pgo/pgo.gni")
+ import("//build/config/features.gni")
+ import("//build/config/python.gni")
  import("//build/config/ui.gni")
 +import("//cef/libcef/features/features.gni")
  import("//chrome/browser/buildflags.gni")
  import("//chrome/browser/downgrade/buildflags.gni")
  import("//chrome/common/features.gni")
-@@ -1988,6 +1989,7 @@ jumbo_static_library("browser") {
-     "//base/util/values:values_util",
-     "//build:branding_buildflags",
+@@ -2047,6 +2048,7 @@ static_library("browser") {
+     "//build/config/chromebox_for_meetings:buildflags",
+     "//build/config/compiler:compiler_buildflags",
      "//cc",
 +    "//cef/libcef/features",
      "//chrome:extra_resources",
      "//chrome:resources",
      "//chrome:strings",
-@@ -2314,6 +2316,10 @@ jumbo_static_library("browser") {
+@@ -2696,6 +2698,10 @@ static_library("browser") {
      ]
    }
  
@@ -28,4 +28,4 @@
 +
    if (is_android) {
      sources += [
-       "after_startup_task_utils_android.cc",
+       "accessibility/accessibility_prefs/android/accessibility_prefs_controller.cc",
diff --git a/src/patch/patches/chrome_browser_background_mode_1100085.patch b/src/patch/patches/chrome_browser_background_mode_1100085.patch
new file mode 100644
index 0000000..4775b6a
--- /dev/null
+++ b/src/patch/patches/chrome_browser_background_mode_1100085.patch
@@ -0,0 +1,72 @@
+diff --git chrome/browser/browser_process.h chrome/browser/browser_process.h
+index 25a82353eace8..bf3c1cc675688 100644
+--- chrome/browser/browser_process.h
++++ chrome/browser/browser_process.h
+@@ -203,9 +203,9 @@ class BrowserProcess {
+   virtual DownloadStatusUpdater* download_status_updater() = 0;
+   virtual DownloadRequestLimiter* download_request_limiter() = 0;
+ 
++#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
+   // Returns the object that manages background applications.
+   virtual BackgroundModeManager* background_mode_manager() = 0;
+-#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
+   virtual void set_background_mode_manager_for_test(
+       std::unique_ptr<BackgroundModeManager> manager) = 0;
+ #endif
+diff --git chrome/browser/browser_process_impl.cc chrome/browser/browser_process_impl.cc
+index 2c378853875b1..abb69e7678b8c 100644
+--- chrome/browser/browser_process_impl.cc
++++ chrome/browser/browser_process_impl.cc
+@@ -1055,18 +1055,14 @@ DownloadRequestLimiter* BrowserProcessImpl::download_request_limiter() {
+   return download_request_limiter_.get();
+ }
+ 
+-BackgroundModeManager* BrowserProcessImpl::background_mode_manager() {
+ #if BUILDFLAG(ENABLE_BACKGROUND_MODE)
++BackgroundModeManager* BrowserProcessImpl::background_mode_manager() {
+   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+   if (!background_mode_manager_)
+     CreateBackgroundModeManager();
+   return background_mode_manager_.get();
+-#else
+-  return nullptr;
+-#endif
+ }
+ 
+-#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
+ void BrowserProcessImpl::set_background_mode_manager_for_test(
+     std::unique_ptr<BackgroundModeManager> manager) {
+   background_mode_manager_ = std::move(manager);
+diff --git chrome/browser/browser_process_impl.h chrome/browser/browser_process_impl.h
+index 7cc361a82a623..041225f160f89 100644
+--- chrome/browser/browser_process_impl.h
++++ chrome/browser/browser_process_impl.h
+@@ -185,8 +185,8 @@ class BrowserProcessImpl : public BrowserProcess,
+   void SetApplicationLocale(const std::string& actual_locale) override;
+   DownloadStatusUpdater* download_status_updater() override;
+   DownloadRequestLimiter* download_request_limiter() override;
+-  BackgroundModeManager* background_mode_manager() override;
+ #if BUILDFLAG(ENABLE_BACKGROUND_MODE)
++  BackgroundModeManager* background_mode_manager() override;
+   void set_background_mode_manager_for_test(
+       std::unique_ptr<BackgroundModeManager> manager) override;
+ #endif
+diff --git chrome/browser/lifetime/browser_close_manager.cc chrome/browser/lifetime/browser_close_manager.cc
+index 1fbc225de7b84..55847e48ed0c2 100644
+--- chrome/browser/lifetime/browser_close_manager.cc
++++ chrome/browser/lifetime/browser_close_manager.cc
+@@ -157,12 +157,14 @@ void BrowserCloseManager::CloseBrowsers() {
+   // exit can restore all browsers open before exiting.
+   ProfileManager::ShutdownSessionServices();
+ #endif
++#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
+   if (!browser_shutdown::IsTryingToQuit()) {
+     BackgroundModeManager* background_mode_manager =
+         g_browser_process->background_mode_manager();
+     if (background_mode_manager)
+       background_mode_manager->SuspendBackgroundMode();
+   }
++#endif
+ 
+   // Make a copy of the BrowserList to simplify the case where we need to
+   // destroy a Browser during the loop.
diff --git a/src/patch/patches/chrome_browser_browser.patch b/src/patch/patches/chrome_browser_browser.patch
new file mode 100644
index 0000000..57c48a5
--- /dev/null
+++ b/src/patch/patches/chrome_browser_browser.patch
@@ -0,0 +1,567 @@
+diff --git chrome/browser/browser_about_handler.cc chrome/browser/browser_about_handler.cc
+index 2480282a19d12..dbd1fbf8a15b5 100644
+--- chrome/browser/browser_about_handler.cc
++++ chrome/browser/browser_about_handler.cc
+@@ -72,6 +72,9 @@ bool HandleNonNavigationAboutURL(const GURL& url) {
+         FROM_HERE, base::BindOnce(&chrome::AttemptExit));
+     return true;
+   }
++  if (base::EqualsCaseInsensitiveASCII(spec, "chrome://ignore/")) {
++    return true;
++  }
+ 
+   return false;
+ }
+diff --git chrome/browser/devtools/devtools_window.cc chrome/browser/devtools/devtools_window.cc
+index 4d99a769d6069..0ebd577182dc6 100644
+--- chrome/browser/devtools/devtools_window.cc
++++ chrome/browser/devtools/devtools_window.cc
+@@ -31,6 +31,7 @@
+ #include "chrome/browser/profiles/profile.h"
+ #include "chrome/browser/task_manager/web_contents_tags.h"
+ #include "chrome/browser/ui/browser.h"
++#include "chrome/browser/ui/browser_finder.h"
+ #include "chrome/browser/ui/browser_list.h"
+ #include "chrome/browser/ui/browser_tabstrip.h"
+ #include "chrome/browser/ui/browser_window.h"
+@@ -1162,6 +1163,13 @@ DevToolsWindow* DevToolsWindow::Create(
+         !browser->is_type_normal()) {
+       can_dock = false;
+     }
++
++#if BUILDFLAG(ENABLE_CEF)
++    if (can_dock && browser && browser->cef_delegate()) {
++      // Don't dock DevTools for CEF-managed browsers.
++      can_dock = false;
++    }
++#endif
+   }
+ 
+   // Create WebContents with devtools.
+@@ -1738,12 +1746,29 @@ void DevToolsWindow::CreateDevToolsBrowser() {
+       Browser::CreationStatus::kOk) {
+     return;
+   }
+-  browser_ =
+-      Browser::Create(Browser::CreateParams::CreateForDevTools(profile_));
+-  browser_->tab_strip_model()->AddWebContents(
+-      OwnedMainWebContents::TakeWebContents(
+-          std::move(owned_main_web_contents_)),
+-      -1, ui::PAGE_TRANSITION_AUTO_TOPLEVEL, AddTabTypes::ADD_ACTIVE);
++
++  auto opener = chrome::FindBrowserWithWebContents(GetInspectedWebContents());
++  auto devtools_contents = OwnedMainWebContents::TakeWebContents(
++      std::move(owned_main_web_contents_));
++
++#if BUILDFLAG(ENABLE_CEF)
++  if (opener && opener->cef_delegate()) {
++    // If a Browser is created, it will take ownership of |devtools_contents|.
++    browser_ = opener->cef_delegate()->CreateDevToolsBrowser(
++        profile_, opener, devtools_contents);
++  }
++#endif
++
++  if (!browser_) {
++    auto create_params = Browser::CreateParams::CreateForDevTools(profile_);
++    create_params.opener = opener;
++
++    browser_ = Browser::Create(std::move(create_params));
++    browser_->tab_strip_model()->AddWebContents(
++        std::move(devtools_contents),
++        -1, ui::PAGE_TRANSITION_AUTO_TOPLEVEL, AddTabTypes::ADD_ACTIVE);
++  }
++
+   OverrideAndSyncDevToolsRendererPrefs();
+ }
+ 
+diff --git chrome/browser/ui/BUILD.gn chrome/browser/ui/BUILD.gn
+index d5bc836ec888d..4da459c08e7af 100644
+--- chrome/browser/ui/BUILD.gn
++++ chrome/browser/ui/BUILD.gn
+@@ -9,6 +9,7 @@ import("//build/config/compiler/compiler.gni")
+ import("//build/config/features.gni")
+ import("//build/config/ozone.gni")
+ import("//build/config/ui.gni")
++import("//cef/libcef/features/features.gni")
+ import("//chrome/browser/buildflags.gni")
+ import("//chrome/common/features.gni")
+ import("//chromeos/ash/components/assistant/assistant.gni")
+@@ -374,6 +375,10 @@ static_library("ui") {
+     "//build/config/compiler:wexit_time_destructors",
+   ]
+ 
++  if (enable_cef) {
++    configs += [ "//cef/libcef/features:config" ]
++  }
++
+   # Since browser and browser_ui actually depend on each other,
+   # we must omit the dependency from browser_ui to browser.
+   # However, this means browser_ui and browser should more or less
+@@ -399,6 +404,7 @@ static_library("ui") {
+     "//build:chromeos_buildflags",
+     "//build/config/chromebox_for_meetings:buildflags",
+     "//cc/paint",
++    "//cef/libcef/features",
+     "//chrome:resources",
+     "//chrome:strings",
+     "//chrome/app:chrome_dll_resources",
+@@ -2759,6 +2765,8 @@ static_library("ui") {
+       "views/apps/app_dialog/app_block_dialog_view.h",
+       "views/apps/app_dialog/app_pause_dialog_view.cc",
+       "views/apps/app_dialog/app_pause_dialog_view.h",
++      "views/apps/app_dialog/app_uninstall_dialog_view.cc",
++      "views/apps/app_dialog/app_uninstall_dialog_view.h",
+       "views/apps/app_info_dialog/arc_app_info_links_panel.cc",
+       "views/apps/app_info_dialog/arc_app_info_links_panel.h",
+       "views/apps/chrome_app_window_client_views_chromeos.cc",
+@@ -4694,8 +4702,6 @@ static_library("ui") {
+       "views/accessibility/theme_tracking_non_accessible_image_view.h",
+       "views/apps/app_dialog/app_dialog_view.cc",
+       "views/apps/app_dialog/app_dialog_view.h",
+-      "views/apps/app_dialog/app_uninstall_dialog_view.cc",
+-      "views/apps/app_dialog/app_uninstall_dialog_view.h",
+       "views/apps/app_info_dialog/app_info_dialog_container.cc",
+       "views/apps/app_info_dialog/app_info_dialog_container.h",
+       "views/apps/app_info_dialog/app_info_dialog_views.cc",
+@@ -6393,6 +6399,7 @@ static_library("ui") {
+   if (enable_printing) {
+     deps += [
+       "//components/printing/browser",
++      "//components/printing/common:mojo_interfaces",
+       "//printing",
+     ]
+   }
+diff --git chrome/browser/ui/browser.cc chrome/browser/ui/browser.cc
+index 9ba2025634365..b6ceaa7f0b531 100644
+--- chrome/browser/ui/browser.cc
++++ chrome/browser/ui/browser.cc
+@@ -265,6 +265,25 @@
+ #include "components/captive_portal/content/captive_portal_tab_helper.h"
+ #endif
+ 
++#if BUILDFLAG(ENABLE_CEF)
++#define CALL_CEF_DELEGATE(name, ...) \
++  if (cef_browser_delegate_) { \
++    cef_browser_delegate_->name(__VA_ARGS__); \
++  }
++#define CALL_CEF_DELEGATE_RETURN(name, ...) \
++  if (cef_browser_delegate_) { \
++    return cef_browser_delegate_->name(__VA_ARGS__); \
++  }
++#define CALL_CEF_DELEGATE_RESULT(name, result, ...) \
++  if (cef_browser_delegate_) { \
++    result = cef_browser_delegate_->name(__VA_ARGS__); \
++  }
++#else  // !BUILDFLAG(ENABLE_CEF)
++#define CALL_CEF_DELEGATE(name, ...)
++#define CALL_CEF_DELEGATE_RETURN(name, ...)
++#define CALL_CEF_DELEGATE_RESULT(name, result, ...)
++#endif
++
+ #if BUILDFLAG(ENABLE_EXTENSIONS)
+ #include "chrome/browser/extensions/extension_browser_window_helper.h"
+ #endif
+@@ -460,6 +479,10 @@ Browser::Browser(const CreateParams& params)
+       type_(params.type),
+       profile_(params.profile),
+       window_(nullptr),
++#if BUILDFLAG(ENABLE_CEF)
++      cef_browser_delegate_(
++          cef::BrowserDelegate::Create(this, params.cef_params, params.opener)),
++#endif
+       tab_strip_model_delegate_(
+           std::make_unique<chrome::BrowserTabStripModelDelegate>(this)),
+       tab_strip_model_(std::make_unique<TabStripModel>(
+@@ -655,6 +678,12 @@ Browser::~Browser() {
+   // away so they don't try and call back to us.
+   if (select_file_dialog_.get())
+     select_file_dialog_->ListenerDestroyed();
++
++  // Clean up any objects attached via UserData before implicit destruction
++  // of CreateParams. Destruction of those objects may call into something
++  // (ProfileImpl, PrefService, etc) that will be destroyed when the last
++  // CefRequestContextImpl reference (held by CreateParams) is released.
++  ClearAllUserData();
+ }
+ 
+ ///////////////////////////////////////////////////////////////////////////////
+@@ -1059,6 +1088,8 @@ void Browser::WindowFullscreenStateChanged() {
+       ->WindowFullscreenStateChanged();
+   command_controller_->FullscreenStateChanged();
+   UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TOGGLE_FULLSCREEN);
++
++  CALL_CEF_DELEGATE(WindowFullscreenStateChanged);
+ }
+ 
+ void Browser::FullscreenTopUIStateChanged() {
+@@ -1398,6 +1429,14 @@ content::KeyboardEventProcessingResult Browser::PreHandleKeyboardEvent(
+   if (exclusive_access_manager_->HandleUserKeyEvent(event))
+     return content::KeyboardEventProcessingResult::HANDLED;
+ 
++#if BUILDFLAG(ENABLE_CEF)
++  if (cef_browser_delegate_) {
++    auto result = cef_browser_delegate_->PreHandleKeyboardEvent(source, event);
++    if (result != content::KeyboardEventProcessingResult::NOT_HANDLED)
++      return result;
++  }
++#endif
++
+   return window()->PreHandleKeyboardEvent(event);
+ }
+ 
+@@ -1405,8 +1444,18 @@ bool Browser::HandleKeyboardEvent(content::WebContents* source,
+                                   const NativeWebKeyboardEvent& event) {
+   DevToolsWindow* devtools_window =
+       DevToolsWindow::GetInstanceForInspectedWebContents(source);
+-  return (devtools_window && devtools_window->ForwardKeyboardEvent(event)) ||
+-         window()->HandleKeyboardEvent(event);
++  if (devtools_window && devtools_window->ForwardKeyboardEvent(event)) {
++    return true;
++  }
++
++#if BUILDFLAG(ENABLE_CEF)
++  if (cef_browser_delegate_ &&
++      cef_browser_delegate_->HandleKeyboardEvent(source, event)) {
++    return true;
++  }
++#endif
++
++  return window()->HandleKeyboardEvent(event);
+ }
+ 
+ bool Browser::TabsNeedBeforeUnloadFired() {
+@@ -1617,6 +1666,14 @@ WebContents* Browser::OpenURLFromTab(WebContents* source,
+   }
+ #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+ 
++#if BUILDFLAG(ENABLE_CEF)
++  if (cef_browser_delegate_) {
++    auto web_contents = cef_browser_delegate_->OpenURLFromTab(source, params);
++    if (!web_contents)
++      return nullptr;
++  }
++#endif
++
+   NavigateParams nav_params(this, params.url, params.transition);
+   nav_params.FillNavigateParamsFromOpenURLParams(params);
+   nav_params.source_contents = source;
+@@ -1774,6 +1831,8 @@ void Browser::LoadingStateChanged(WebContents* source,
+                                   bool should_show_loading_ui) {
+   ScheduleUIUpdate(source, content::INVALIDATE_TYPE_LOAD);
+   UpdateWindowForLoadingStateChanged(source, should_show_loading_ui);
++
++  CALL_CEF_DELEGATE(LoadingStateChanged, source, should_show_loading_ui);
+ }
+ 
+ void Browser::CloseContents(WebContents* source) {
+@@ -1802,6 +1861,8 @@ void Browser::SetContentsBounds(WebContents* source, const gfx::Rect& bounds) {
+ }
+ 
+ void Browser::UpdateTargetURL(WebContents* source, const GURL& url) {
++  CALL_CEF_DELEGATE(UpdateTargetURL, source, url);
++
+   if (!GetStatusBubble())
+     return;
+ 
+@@ -1809,6 +1870,17 @@ void Browser::UpdateTargetURL(WebContents* source, const GURL& url) {
+     GetStatusBubble()->SetURL(url);
+ }
+ 
++bool Browser::DidAddMessageToConsole(
++    content::WebContents* source,
++    blink::mojom::ConsoleMessageLevel log_level,
++    const std::u16string& message,
++    int32_t line_no,
++    const std::u16string& source_id) {
++  CALL_CEF_DELEGATE_RETURN(DidAddMessageToConsole, source, log_level, message,
++                           line_no, source_id);
++  return false;
++}
++
+ void Browser::ContentsMouseEvent(WebContents* source,
+                                  bool motion,
+                                  bool exited) {
+@@ -1833,6 +1905,19 @@ bool Browser::TakeFocus(content::WebContents* source, bool reverse) {
+   return false;
+ }
+ 
++void Browser::CanDownload(const GURL& url,
++                          const std::string& request_method,
++                          base::OnceCallback<void(bool)> callback) {
++#if BUILDFLAG(ENABLE_CEF)
++  if (cef_browser_delegate_) {
++    cef_browser_delegate_->CanDownload(url, request_method,
++                                       std::move(callback));
++    return;
++  }
++#endif
++  std::move(callback).Run(true);
++}
++
+ void Browser::BeforeUnloadFired(WebContents* web_contents,
+                                 bool proceed,
+                                 bool* proceed_to_fire_unload) {
+@@ -1925,6 +2010,10 @@ void Browser::WebContentsCreated(WebContents* source_contents,
+ 
+   // Make the tab show up in the task manager.
+   task_manager::WebContentsTags::CreateForTabContents(new_contents);
++
++  CALL_CEF_DELEGATE(WebContentsCreated, source_contents,
++                    opener_render_process_id, opener_render_frame_id,
++                    frame_name, target_url, new_contents);
+ }
+ 
+ void Browser::PortalWebContentsCreated(WebContents* portal_web_contents) {
+@@ -2046,11 +2135,15 @@ void Browser::EnterFullscreenModeForTab(
+     const blink::mojom::FullscreenOptions& options) {
+   exclusive_access_manager_->fullscreen_controller()->EnterFullscreenModeForTab(
+       requesting_frame, options.display_id);
++
++  CALL_CEF_DELEGATE(EnterFullscreenModeForTab, requesting_frame, options);
+ }
+ 
+ void Browser::ExitFullscreenModeForTab(WebContents* web_contents) {
+   exclusive_access_manager_->fullscreen_controller()->ExitFullscreenModeForTab(
+       web_contents);
++
++  CALL_CEF_DELEGATE(ExitFullscreenModeForTab, web_contents);
+ }
+ 
+ bool Browser::IsFullscreenForTabOrPending(const WebContents* web_contents) {
+@@ -2240,6 +2333,15 @@ void Browser::RequestMediaAccessPermission(
+     content::WebContents* web_contents,
+     const content::MediaStreamRequest& request,
+     content::MediaResponseCallback callback) {
++#if BUILDFLAG(ENABLE_CEF)
++  if (cef_browser_delegate_) {
++    callback = cef_browser_delegate_->RequestMediaAccessPermissionEx(
++        web_contents, request, std::move(callback));
++    if (callback.is_null())
++      return;
++  }
++#endif
++
+   const extensions::Extension* extension =
+       GetExtensionForOrigin(profile_, request.security_origin);
+   MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
+@@ -2791,9 +2893,11 @@ void Browser::RemoveScheduledUpdatesFor(WebContents* contents) {
+ // Browser, Getters for UI (private):
+ 
+ StatusBubble* Browser::GetStatusBubble() {
++  bool show_by_default = true;
++
+   // For kiosk and exclusive app mode we want to always hide the status bubble.
+   if (chrome::IsRunningInAppMode()) {
+-    return nullptr;
++    show_by_default = false;
+   }
+ 
+   // We hide the status bar for web apps windows as this matches native
+@@ -2801,6 +2905,12 @@ StatusBubble* Browser::GetStatusBubble() {
+   // mode, as the minimal browser UI includes the status bar.
+   if (web_app::AppBrowserController::IsWebApp(this) &&
+       !app_controller()->HasMinimalUiButtons()) {
++    show_by_default = false;
++  }
++
++  bool show = show_by_default;
++  CALL_CEF_DELEGATE_RESULT(ShowStatusBubble, show, show_by_default);
++  if (!show) {
+     return nullptr;
+   }
+ 
+@@ -2937,6 +3047,8 @@ void Browser::SetAsDelegate(WebContents* web_contents, bool set_delegate) {
+     BookmarkTabHelper::FromWebContents(web_contents)->RemoveObserver(this);
+     web_contents_collection_.StopObserving(web_contents);
+   }
++
++  CALL_CEF_DELEGATE(SetAsDelegate, web_contents, set_delegate);
+ }
+ 
+ void Browser::TabDetachedAtImpl(content::WebContents* contents,
+@@ -3091,6 +3203,14 @@ bool Browser::PictureInPictureBrowserSupportsWindowFeature(
+ 
+ bool Browser::SupportsWindowFeatureImpl(WindowFeature feature,
+                                         bool check_can_support) const {
++#if BUILDFLAG(ENABLE_CEF)
++  if (cef_delegate()) {
++    if (auto value = cef_delegate()->SupportsWindowFeature(feature)) {
++      return *value;
++    }
++  }
++#endif
++
+   switch (type_) {
+     case TYPE_NORMAL:
+       return NormalBrowserSupportsWindowFeature(feature, check_can_support);
+diff --git chrome/browser/ui/browser.h chrome/browser/ui/browser.h
+index db37e861d2546..ea85b9966267d 100644
+--- chrome/browser/ui/browser.h
++++ chrome/browser/ui/browser.h
+@@ -22,6 +22,7 @@
+ #include "base/timer/elapsed_timer.h"
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/tab_contents/web_contents_collection.h"
+ #include "chrome/browser/themes/theme_service_observer.h"
+ #include "chrome/browser/ui/bookmarks/bookmark_bar.h"
+@@ -48,6 +49,10 @@
+ #include "ui/gfx/geometry/rect.h"
+ #include "ui/shell_dialogs/select_file_dialog.h"
+ 
++#if BUILDFLAG(ENABLE_CEF)
++#include "cef/libcef/browser/chrome/browser_delegate.h"
++#endif
++
+ #if BUILDFLAG(IS_ANDROID)
+ #error This file should only be included on desktop.
+ #endif
+@@ -331,6 +336,15 @@ class Browser : public TabStripModelObserver,
+     // Document Picture in Picture options, specific to TYPE_PICTURE_IN_PICTURE.
+     absl::optional<blink::mojom::PictureInPictureWindowOptions> pip_options;
+ 
++#if BUILDFLAG(ENABLE_CEF)
++    // Opaque CEF-specific configuration. Will be propagated to new Browsers.
++    scoped_refptr<cef::BrowserDelegate::CreateParams> cef_params;
++
++    // Specify the Browser that is opening this popup.
++    // Currently only used with TYPE_PICTURE_IN_PICTURE and TYPE_DEVTOOLS.
++    raw_ptr<Browser, DanglingUntriaged> opener = nullptr;
++#endif
++
+    private:
+     friend class Browser;
+     friend class WindowSizerChromeOSTest;
+@@ -412,6 +426,13 @@ class Browser : public TabStripModelObserver,
+     update_ui_immediately_for_testing_ = true;
+   }
+ 
++  // Return true if CEF will expose the toolbar to the client. This value is
++  // used to selectively enable toolbar behaviors such as command processing
++  // and omnibox focus without also including the toolbar in BrowserView layout
++  // calculations.
++  void set_toolbar_overridden(bool val) { toolbar_overridden_ = val; }
++  bool toolbar_overridden() const { return toolbar_overridden_; }
++
+   // Accessors ////////////////////////////////////////////////////////////////
+ 
+   const CreateParams& create_params() const { return create_params_; }
+@@ -485,6 +506,12 @@ class Browser : public TabStripModelObserver,
+ 
+   base::WeakPtr<Browser> AsWeakPtr();
+ 
++#if BUILDFLAG(ENABLE_CEF)
++  cef::BrowserDelegate* cef_delegate() const {
++    return cef_browser_delegate_.get();
++  }
++#endif
++
+   // Get the FindBarController for this browser, creating it if it does not
+   // yet exist.
+   FindBarController* GetFindBarController();
+@@ -876,11 +903,19 @@ class Browser : public TabStripModelObserver,
+   void SetContentsBounds(content::WebContents* source,
+                          const gfx::Rect& bounds) override;
+   void UpdateTargetURL(content::WebContents* source, const GURL& url) override;
++  bool DidAddMessageToConsole(content::WebContents* source,
++                              blink::mojom::ConsoleMessageLevel log_level,
++                              const std::u16string& message,
++                              int32_t line_no,
++                              const std::u16string& source_id) override;
+   void ContentsMouseEvent(content::WebContents* source,
+                           bool motion,
+                           bool exited) override;
+   void ContentsZoomChange(bool zoom_in) override;
+   bool TakeFocus(content::WebContents* source, bool reverse) override;
++  void CanDownload(const GURL& url,
++                   const std::string& request_method,
++                   base::OnceCallback<void(bool)> callback) override;
+   void BeforeUnloadFired(content::WebContents* source,
+                          bool proceed,
+                          bool* proceed_to_fire_unload) override;
+@@ -1219,6 +1254,10 @@ class Browser : public TabStripModelObserver,
+   // This Browser's window.
+   raw_ptr<BrowserWindow, DanglingUntriaged> window_;
+ 
++#if BUILDFLAG(ENABLE_CEF)
++  std::unique_ptr<cef::BrowserDelegate> cef_browser_delegate_;
++#endif
++
+   std::unique_ptr<TabStripModelDelegate> const tab_strip_model_delegate_;
+   std::unique_ptr<TabStripModel> const tab_strip_model_;
+ 
+@@ -1288,6 +1327,8 @@ class Browser : public TabStripModelObserver,
+   const std::string initial_workspace_;
+   bool initial_visible_on_all_workspaces_state_;
+ 
++  bool toolbar_overridden_ = false;
++
+   CreationSource creation_source_ = CreationSource::kUnknown;
+ 
+   UnloadController unload_controller_;
+diff --git chrome/browser/ui/browser_navigator.cc chrome/browser/ui/browser_navigator.cc
+index e76824b5ba371..27c8e3d131238 100644
+--- chrome/browser/ui/browser_navigator.cc
++++ chrome/browser/ui/browser_navigator.cc
+@@ -288,6 +288,10 @@ std::pair<Browser*, int> GetBrowserAndTabForDisposition(
+                 : 1.0;
+         browser_params.pip_options = pip_options;
+ 
++#if BUILDFLAG(ENABLE_CEF)
++        browser_params.opener = params.browser;
++#endif
++
+         const BrowserWindow* const browser_window = params.browser->window();
+         const gfx::NativeWindow native_window =
+             browser_window ? browser_window->GetNativeWindow()
+@@ -553,6 +557,13 @@ std::unique_ptr<content::WebContents> CreateTargetContents(
+   std::unique_ptr<WebContents> target_contents =
+       WebContents::Create(create_params);
+ 
++#if BUILDFLAG(ENABLE_CEF)
++  auto cef_delegate = params.browser->cef_delegate();
++  if (cef_delegate) {
++    cef_delegate->OnWebContentsCreated(target_contents.get());
++  }
++#endif
++
+   // New tabs can have WebUI URLs that will make calls back to arbitrary
+   // tab helpers, so the entire set of tab helpers needs to be set up
+   // immediately.
+diff --git chrome/browser/ui/browser_tabstrip.cc chrome/browser/ui/browser_tabstrip.cc
+index 535d038f7023b..f861a0f37bf85 100644
+--- chrome/browser/ui/browser_tabstrip.cc
++++ chrome/browser/ui/browser_tabstrip.cc
+@@ -32,9 +32,13 @@ void AddTabAt(Browser* browser,
+   // Time new tab page creation time.  We keep track of the timing data in
+   // WebContents, but we want to include the time it takes to create the
+   // WebContents object too.
++  // For CEF use a PageTransition that matches
++  // CefFrameHostImpl::kPageTransitionExplicit.
+   base::TimeTicks new_tab_start_time = base::TimeTicks::Now();
+   NavigateParams params(browser, url.is_empty() ? browser->GetNewTabURL() : url,
+-                        ui::PAGE_TRANSITION_TYPED);
++                        static_cast<ui::PageTransition>(
++                            ui::PAGE_TRANSITION_TYPED |
++                            ui::PAGE_TRANSITION_FROM_ADDRESS_BAR));
+   params.disposition = foreground ? WindowOpenDisposition::NEW_FOREGROUND_TAB
+                                   : WindowOpenDisposition::NEW_BACKGROUND_TAB;
+   params.tabstrip_index = idx;
+@@ -70,6 +74,16 @@ void AddWebContents(Browser* browser,
+   // Can't create a new contents for the current tab - invalid case.
+   DCHECK(disposition != WindowOpenDisposition::CURRENT_TAB);
+ 
++#if BUILDFLAG(ENABLE_CEF)
++  if (browser && browser->cef_delegate() && new_contents) {
++    new_contents = browser->cef_delegate()->AddWebContents(
++        std::move(new_contents));
++    if (!new_contents) {
++      return;
++    }
++  }
++#endif
++
+   NavigateParams params(browser, std::move(new_contents));
+   params.source_contents = source_contents;
+   params.url = target_url;
diff --git a/src/patch/patches/chrome_browser_content_settings.patch b/src/patch/patches/chrome_browser_content_settings.patch
index be25854..c2e165d 100644
--- a/src/patch/patches/chrome_browser_content_settings.patch
+++ b/src/patch/patches/chrome_browser_content_settings.patch
@@ -1,55 +1,70 @@
 diff --git chrome/browser/content_settings/host_content_settings_map_factory.cc chrome/browser/content_settings/host_content_settings_map_factory.cc
-index 937b56a2e261..9e3877b06c59 100644
+index 6f842a7535a56..faaee032e82bd 100644
 --- chrome/browser/content_settings/host_content_settings_map_factory.cc
 +++ chrome/browser/content_settings/host_content_settings_map_factory.cc
-@@ -8,6 +8,7 @@
- 
+@@ -9,6 +9,7 @@
  #include "base/feature_list.h"
+ #include "build/build_config.h"
  #include "build/buildflag.h"
-+#include "cef/libcef/features/features.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/content_settings/one_time_permission_provider.h"
+ #include "chrome/browser/permissions/one_time_permissions_tracker_factory.h"
  #include "chrome/browser/profiles/off_the_record_profile_impl.h"
- #include "chrome/browser/profiles/profile.h"
- #include "chrome/browser/search_engines/template_url_service_factory.h"
-@@ -19,6 +20,10 @@
- #include "content/public/browser/browser_thread.h"
+@@ -23,6 +24,10 @@
  #include "extensions/buildflags/buildflags.h"
+ #include "ui/webui/webui_allowlist_provider.h"
  
 +#if BUILDFLAG(ENABLE_CEF)
 +#include "cef/libcef/common/extensions/extensions_util.h"
 +#endif
 +
  #if BUILDFLAG(ENABLE_EXTENSIONS)
- #include "chrome/browser/extensions/extension_service.h"
- #include "extensions/browser/extension_system.h"
-@@ -47,8 +52,14 @@ HostContentSettingsMapFactory::HostContentSettingsMapFactory()
-   DependsOn(SupervisedUserSettingsServiceFactory::GetInstance());
+ #include "base/trace_event/trace_event.h"
+ #include "extensions/browser/api/content_settings/content_settings_custom_extension_provider.h"
+@@ -68,7 +73,13 @@ HostContentSettingsMapFactory::HostContentSettingsMapFactory()
+   DependsOn(OneTimePermissionsTrackerFactory::GetInstance());
  #endif
  #if BUILDFLAG(ENABLE_EXTENSIONS)
 +#if BUILDFLAG(ENABLE_CEF)
-+  if (extensions::ExtensionsEnabled()) {
++  if (!cef::IsAlloyRuntimeEnabled() || extensions::ExtensionsEnabled()) {
 +#endif
-   DependsOn(
-       extensions::ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
+   DependsOn(extensions::ContentSettingsService::GetFactoryInstance());
 +#if BUILDFLAG(ENABLE_CEF)
 +  }
 +#endif
  #endif
- }
- 
-@@ -89,10 +100,16 @@ scoped_refptr<RefcountedKeyedService>
-           permissions::features::kPermissionDelegation)));
+   // Used by way of ShouldRestoreOldSessionCookies().
+ #if BUILDFLAG(ENABLE_SESSION_SERVICE)
+@@ -132,6 +143,9 @@ scoped_refptr<RefcountedKeyedService>
+       std::move(allowlist_provider));
  
  #if BUILDFLAG(ENABLE_EXTENSIONS)
 +#if BUILDFLAG(ENABLE_CEF)
-+  if (extensions::ExtensionsEnabled()) {
++  if (!cef::IsAlloyRuntimeEnabled() || extensions::ExtensionsEnabled()) {
 +#endif
    // These must be registered before before the HostSettings are passed over to
    // the IOThread.  Simplest to do this on construction.
-   extensions::ExtensionService::RegisterContentSettings(settings_map.get(),
-                                                         profile);
+   settings_map->RegisterProvider(
+@@ -144,6 +158,9 @@ scoped_refptr<RefcountedKeyedService>
+           // the case where profile->IsOffTheRecord() is true? And what is the
+           // interaction with profile->IsGuestSession()?
+           false));
 +#if BUILDFLAG(ENABLE_CEF)
 +  }
 +#endif
  #endif // BUILDFLAG(ENABLE_EXTENSIONS)
  #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
-   SupervisedUserSettingsService* supervised_service =
+   supervised_user::SupervisedUserSettingsService* supervised_service =
+diff --git components/content_settings/renderer/content_settings_agent_impl.cc components/content_settings/renderer/content_settings_agent_impl.cc
+index c65b17d8ee9e2..1c6e91858ba9e 100644
+--- components/content_settings/renderer/content_settings_agent_impl.cc
++++ components/content_settings/renderer/content_settings_agent_impl.cc
+@@ -144,7 +144,7 @@ ContentSetting GetContentSettingFromRules(
+       return rule.GetContentSetting();
+     }
+   }
+-  NOTREACHED();
++  // NOTREACHED();
+   return CONTENT_SETTING_DEFAULT;
+ }
+ }  // namespace
diff --git a/src/patch/patches/chrome_browser_context_menus.patch b/src/patch/patches/chrome_browser_context_menus.patch
new file mode 100644
index 0000000..13d539f
--- /dev/null
+++ b/src/patch/patches/chrome_browser_context_menus.patch
@@ -0,0 +1,194 @@
+diff --git chrome/browser/renderer_context_menu/render_view_context_menu.cc chrome/browser/renderer_context_menu/render_view_context_menu.cc
+index b4a12d129fa52..a8caaab873d3c 100644
+--- chrome/browser/renderer_context_menu/render_view_context_menu.cc
++++ chrome/browser/renderer_context_menu/render_view_context_menu.cc
+@@ -345,6 +345,13 @@ base::OnceCallback<void(RenderViewContextMenu*)>* GetMenuShownCallback() {
+   return callback.get();
+ }
+ 
++
++RenderViewContextMenu::MenuCreatedCallback* GetMenuCreatedCallback() {
++  static base::NoDestructor<RenderViewContextMenu::MenuCreatedCallback>
++      callback;
++  return callback.get();
++}
++
+ enum class UmaEnumIdLookupType {
+   GeneralEnumId,
+   ContextSpecificEnumId,
+@@ -594,6 +601,10 @@ int FindUMAEnumValueForCommand(int id, UmaEnumIdLookupType type) {
+   if (ContextMenuMatcher::IsExtensionsCustomCommandId(id))
+     return 1;
+ 
++  // Match the MENU_ID_USER_FIRST to MENU_ID_USER_LAST range from cef_types.h.
++  if (id >= 26500 && id <= 28500)
++    return 1;
++
+   id = CollapseCommandsForUMA(id);
+   const auto& map = GetIdcToUmaMap(type);
+   auto it = map.find(id);
+@@ -817,6 +828,14 @@ RenderViewContextMenu::RenderViewContextMenu(
+   pdf_ocr_submenu_model_ = std::make_unique<ui::SimpleMenuModel>(this);
+ #endif  // BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
+ 
++  auto* cb = GetMenuCreatedCallback();
++  if (!cb->is_null()) {
++    first_observer_ = cb->Run(this);
++    if (first_observer_) {
++      observers_.AddObserver(first_observer_.get());
++    }
++  }
++
+   observers_.AddObserver(&autofill_context_menu_manager_);
+ }
+ 
+@@ -1280,6 +1299,12 @@ void RenderViewContextMenu::InitMenu() {
+           autofill::PopupHidingReason::kContextMenuOpened);
+     }
+   }
++
++  if (first_observer_) {
++    // Do this last so that the observer can optionally modify previously
++    // created items.
++    first_observer_->InitMenu(params_);
++  }
+ }
+ 
+ Profile* RenderViewContextMenu::GetProfile() const {
+@@ -3315,6 +3340,12 @@ void RenderViewContextMenu::RegisterExecutePluginActionCallbackForTesting(
+   execute_plugin_action_callback_ = std::move(cb);
+ }
+ 
++// static
++void RenderViewContextMenu::RegisterMenuCreatedCallback(
++    MenuCreatedCallback cb) {
++  *GetMenuCreatedCallback() = cb;
++}
++
+ custom_handlers::ProtocolHandlerRegistry::ProtocolHandlerList
+ RenderViewContextMenu::GetHandlersForLinkUrl() {
+   custom_handlers::ProtocolHandlerRegistry::ProtocolHandlerList handlers =
+diff --git chrome/browser/renderer_context_menu/render_view_context_menu.h chrome/browser/renderer_context_menu/render_view_context_menu.h
+index 2d38d86a07d98..3f16e2bf696c1 100644
+--- chrome/browser/renderer_context_menu/render_view_context_menu.h
++++ chrome/browser/renderer_context_menu/render_view_context_menu.h
+@@ -152,6 +152,12 @@ class RenderViewContextMenu
+   }
+ #endif
+ 
++  // Registers a callback that will be called each time a context menu is
++  // created.
++  using MenuCreatedCallback = base::RepeatingCallback<
++      std::unique_ptr<RenderViewContextMenuObserver>(RenderViewContextMenu*)>;
++  static void RegisterMenuCreatedCallback(MenuCreatedCallback cb);
++
+  protected:
+   Profile* GetProfile() const;
+ 
+@@ -441,6 +447,9 @@ class RenderViewContextMenu
+   //   built.
+   bool is_protocol_submenu_valid_ = false;
+ 
++  // An observer returned via MenuCreatedCallback that will be called first.
++  std::unique_ptr<RenderViewContextMenuObserver> first_observer_;
++
+   // An observer that handles spelling suggestions, "Add to dictionary", and
+   // "Use enhanced spell check" items.
+   std::unique_ptr<SpellingMenuObserver> spelling_suggestions_menu_observer_;
+diff --git chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc
+index 18283c801689e..9838c25d6e584 100644
+--- chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc
++++ chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc
+@@ -149,6 +149,9 @@ void RenderViewContextMenuViews::RunMenuAt(views::Widget* parent,
+ bool RenderViewContextMenuViews::GetAcceleratorForCommandId(
+     int command_id,
+     ui::Accelerator* accel) const {
++  if (RenderViewContextMenu::GetAcceleratorForCommandId(command_id, accel))
++    return true;
++
+   // There are no formally defined accelerators we can query so we assume
+   // that Ctrl+C, Ctrl+V, Ctrl+X, Ctrl-A, etc do what they normally do.
+   switch (command_id) {
+diff --git components/renderer_context_menu/render_view_context_menu_base.cc components/renderer_context_menu/render_view_context_menu_base.cc
+index 965a283dea477..74c1ee8258485 100644
+--- components/renderer_context_menu/render_view_context_menu_base.cc
++++ components/renderer_context_menu/render_view_context_menu_base.cc
+@@ -382,6 +382,17 @@ bool RenderViewContextMenuBase::IsCommandIdChecked(int id) const {
+   return false;
+ }
+ 
++bool RenderViewContextMenuBase::GetAcceleratorForCommandId(
++    int id,
++    ui::Accelerator* accelerator) const {
++  for (auto& observer : observers_) {
++    if (observer.IsCommandIdSupported(id))
++      return observer.GetAccelerator(id, accelerator);
++  }
++
++  return false;
++}
++
+ void RenderViewContextMenuBase::ExecuteCommand(int id, int event_flags) {
+   command_executed_ = true;
+   RecordUsedItem(id);
+diff --git components/renderer_context_menu/render_view_context_menu_base.h components/renderer_context_menu/render_view_context_menu_base.h
+index b5995389e5107..26ef1e2ff42c7 100644
+--- components/renderer_context_menu/render_view_context_menu_base.h
++++ components/renderer_context_menu/render_view_context_menu_base.h
+@@ -87,6 +87,9 @@ class RenderViewContextMenuBase : public ui::SimpleMenuModel::Delegate,
+ 
+   const ui::SimpleMenuModel& menu_model() const { return menu_model_; }
+   const content::ContextMenuParams& params() const { return params_; }
++  content::WebContents* source_web_contents() const {
++    return source_web_contents_;
++  }
+ 
+   // Returns true if the specified command id is known and valid for
+   // this menu. If the command is known |enabled| is set to indicate
+@@ -95,6 +98,9 @@ class RenderViewContextMenuBase : public ui::SimpleMenuModel::Delegate,
+ 
+   // SimpleMenuModel::Delegate implementation.
+   bool IsCommandIdChecked(int command_id) const override;
++  bool GetAcceleratorForCommandId(
++      int command_id,
++      ui::Accelerator* accelerator) const override;
+   void ExecuteCommand(int command_id, int event_flags) override;
+   void OnMenuWillShow(ui::SimpleMenuModel* source) override;
+   void MenuClosed(ui::SimpleMenuModel* source) override;
+diff --git components/renderer_context_menu/render_view_context_menu_observer.cc components/renderer_context_menu/render_view_context_menu_observer.cc
+index 9fdda1636003d..538bd05a41296 100644
+--- components/renderer_context_menu/render_view_context_menu_observer.cc
++++ components/renderer_context_menu/render_view_context_menu_observer.cc
+@@ -15,3 +15,8 @@ bool RenderViewContextMenuObserver::IsCommandIdChecked(int command_id) {
+ bool RenderViewContextMenuObserver::IsCommandIdEnabled(int command_id) {
+   return false;
+ }
++
++bool RenderViewContextMenuObserver::GetAccelerator(int command_id,
++                                                   ui::Accelerator* accel) {
++  return false;
++}
+diff --git components/renderer_context_menu/render_view_context_menu_observer.h components/renderer_context_menu/render_view_context_menu_observer.h
+index 0527c57abd51c..70bebcbb50461 100644
+--- components/renderer_context_menu/render_view_context_menu_observer.h
++++ components/renderer_context_menu/render_view_context_menu_observer.h
+@@ -11,6 +11,10 @@ namespace content {
+ struct ContextMenuParams;
+ }
+ 
++namespace ui {
++class Accelerator;
++}
++
+ // The interface used for implementing context-menu items. The following
+ // instruction describe how to implement a context-menu item with this
+ // interface.
+@@ -100,6 +104,8 @@ class RenderViewContextMenuObserver {
+   virtual bool IsCommandIdChecked(int command_id);
+   virtual bool IsCommandIdEnabled(int command_id);
+ 
++  virtual bool GetAccelerator(int command_id, ui::Accelerator* accel);
++
+   // Called when a user selects the specified context-menu item. This is
+   // only called when the observer returns true for IsCommandIdSupported()
+   // for that |command_id|.
diff --git a/src/patch/patches/chrome_browser_dialogs_native.patch b/src/patch/patches/chrome_browser_dialogs_native.patch
new file mode 100644
index 0000000..db67cc9
--- /dev/null
+++ b/src/patch/patches/chrome_browser_dialogs_native.patch
@@ -0,0 +1,352 @@
+diff --git chrome/browser/file_select_helper.cc chrome/browser/file_select_helper.cc
+index 3f5042600416e..25c23b1a0f00d 100644
+--- chrome/browser/file_select_helper.cc
++++ chrome/browser/file_select_helper.cc
+@@ -20,6 +20,7 @@
+ #include "base/threading/hang_watcher.h"
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/browser_process.h"
+ #include "chrome/browser/enterprise/connectors/common.h"
+ #include "chrome/browser/platform_util.h"
+@@ -256,6 +257,13 @@ void FileSelectHelper::OnListFile(
+ void FileSelectHelper::LaunchConfirmationDialog(
+     const base::FilePath& path,
+     std::vector<ui::SelectedFileInfo> selected_files) {
++  if (cef::IsAlloyRuntimeEnabled() || run_from_cef_) {
++    // Don't show the upload confirmation dialog with the Alloy runtime, or
++    // when triggered via CEF (initially or recursively).
++    ConvertToFileChooserFileInfoList(selected_files);
++    return;
++  }
++
+   ShowFolderUploadConfirmationDialog(
+       path,
+       base::BindOnce(&FileSelectHelper::ConvertToFileChooserFileInfoList, this),
+@@ -340,6 +348,12 @@ void FileSelectHelper::PerformContentAnalysisIfNeeded(
+   if (AbortIfWebContentsDestroyed())
+     return;
+ 
++  // Don't trigger creation of a AccountConsistencyModeManager (see issue #3401)
++  if (cef::IsAlloyRuntimeEnabled()) {
++    NotifyListenerAndEnd(std::move(list));
++    return;
++  }
++
+ #if BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)
+   enterprise_connectors::ContentAnalysisDelegate::Data data;
+   if (enterprise_connectors::ContentAnalysisDelegate::IsEnabled(
+@@ -470,7 +484,8 @@ void FileSelectHelper::DontAbortOnMissingWebContentsForTesting() {
+ 
+ std::unique_ptr<ui::SelectFileDialog::FileTypeInfo>
+ FileSelectHelper::GetFileTypesFromAcceptType(
+-    const std::vector<std::u16string>& accept_types) {
++    const std::vector<std::u16string>& accept_types,
++    bool run_from_cef) {
+   auto base_file_type = std::make_unique<ui::SelectFileDialog::FileTypeInfo>();
+   if (accept_types.empty())
+     return base_file_type;
+@@ -483,17 +498,24 @@ FileSelectHelper::GetFileTypesFromAcceptType(
+   std::vector<base::FilePath::StringType>* extensions =
+       &file_type->extensions.back();
+ 
++  // Create individual filters for each accept type.
++  std::vector<std::vector<base::FilePath::StringType>> all_extensions;
++  std::vector<std::u16string> all_overrides;
++
+   // Find the corresponding extensions.
+   int valid_type_count = 0;
+   int description_id = 0;
+   for (const auto& accept_type : accept_types) {
++    std::vector<base::FilePath::StringType> current_extensions;
++    description_id = 0;
++
+     size_t old_extension_size = extensions->size();
+     if (accept_type[0] == '.') {
+       // If the type starts with a period it is assumed to be a file extension
+       // so we just have to add it to the list.
+       base::FilePath::StringType ext =
+           base::FilePath::FromUTF16Unsafe(accept_type).value();
+-      extensions->push_back(ext.substr(1));
++      current_extensions.push_back(ext.substr(1));
+     } else {
+       if (!base::IsStringASCII(accept_type))
+         continue;
+@@ -504,10 +526,18 @@ FileSelectHelper::GetFileTypesFromAcceptType(
+         description_id = IDS_AUDIO_FILES;
+       else if (ascii_type == "video/*")
+         description_id = IDS_VIDEO_FILES;
+-
+-      net::GetExtensionsForMimeType(ascii_type, extensions);
++      net::GetExtensionsForMimeType(ascii_type, &current_extensions);
+     }
+ 
++    if (!current_extensions.empty()) {
++      all_extensions.push_back(current_extensions);
++      all_overrides.push_back(description_id != 0 ?
++                              l10n_util::GetStringUTF16(description_id) :
++                              std::u16string());
++
++      extensions->insert(extensions->end(), current_extensions.begin(),
++                         current_extensions.end());
++    }
+     if (extensions->size() > old_extension_size)
+       valid_type_count++;
+   }
+@@ -532,6 +562,15 @@ FileSelectHelper::GetFileTypesFromAcceptType(
+         l10n_util::GetStringUTF16(description_id));
+   }
+ 
++  if (run_from_cef && all_extensions.size() > 1) {
++    // Insert filters for the specific accept types at the beginning.
++    file_type->extensions.insert(file_type->extensions.begin(),
++        all_extensions.begin(), all_extensions.end());
++    file_type->extension_description_overrides.insert(
++        file_type->extension_description_overrides.begin(),
++        all_overrides.begin(), all_overrides.end());
++  }
++
+   return file_type;
+ }
+ 
+@@ -539,7 +578,8 @@ FileSelectHelper::GetFileTypesFromAcceptType(
+ void FileSelectHelper::RunFileChooser(
+     content::RenderFrameHost* render_frame_host,
+     scoped_refptr<content::FileSelectListener> listener,
+-    const FileChooserParams& params) {
++    const FileChooserParams& params,
++    bool run_from_cef) {
+   Profile* profile = Profile::FromBrowserContext(
+       render_frame_host->GetProcess()->GetBrowserContext());
+ 
+@@ -558,6 +598,7 @@ void FileSelectHelper::RunFileChooser(
+   // message.
+   scoped_refptr<FileSelectHelper> file_select_helper(
+       new FileSelectHelper(profile));
++  file_select_helper->run_from_cef_ = run_from_cef;
+   file_select_helper->RunFileChooser(render_frame_host, std::move(listener),
+                                      params.Clone());
+ }
+@@ -609,7 +650,8 @@ void FileSelectHelper::RunFileChooser(
+ }
+ 
+ void FileSelectHelper::GetFileTypesInThreadPool(FileChooserParamsPtr params) {
+-  select_file_types_ = GetFileTypesFromAcceptType(params->accept_types);
++  select_file_types_ = GetFileTypesFromAcceptType(params->accept_types,
++                                                  run_from_cef_);
+   select_file_types_->allowed_paths =
+       params->need_local_path ? ui::SelectFileDialog::FileTypeInfo::NATIVE_PATH
+                               : ui::SelectFileDialog::FileTypeInfo::ANY_PATH;
+diff --git chrome/browser/file_select_helper.h chrome/browser/file_select_helper.h
+index 57dae0b3670ae..85eeda4cbaa5b 100644
+--- chrome/browser/file_select_helper.h
++++ chrome/browser/file_select_helper.h
+@@ -62,7 +62,8 @@ class FileSelectHelper : public base::RefCountedThreadSafe<
+   static void RunFileChooser(
+       content::RenderFrameHost* render_frame_host,
+       scoped_refptr<content::FileSelectListener> listener,
+-      const blink::mojom::FileChooserParams& params);
++      const blink::mojom::FileChooserParams& params,
++      bool run_from_cef = false);
+ 
+   // Enumerates all the files in directory.
+   static void EnumerateDirectory(
+@@ -268,7 +269,8 @@ class FileSelectHelper : public base::RefCountedThreadSafe<
+   // |accept_types| contains only valid lowercased MIME types or file extensions
+   // beginning with a period (.).
+   static std::unique_ptr<ui::SelectFileDialog::FileTypeInfo>
+-  GetFileTypesFromAcceptType(const std::vector<std::u16string>& accept_types);
++  GetFileTypesFromAcceptType(const std::vector<std::u16string>& accept_types,
++                             bool run_from_cef);
+ 
+   // Check the accept type is valid. It is expected to be all lower case with
+   // no whitespace.
+@@ -329,6 +331,9 @@ class FileSelectHelper : public base::RefCountedThreadSafe<
+   // Set to false in unit tests since there is no WebContents.
+   bool abort_on_missing_web_contents_in_tests_ = true;
+ 
++  // Set to true if this dialog was triggered via CEF.
++  bool run_from_cef_ = false;
++
+ #if BUILDFLAG(IS_CHROMEOS_ASH)
+   base::WeakPtrFactory<FileSelectHelper> weak_ptr_factory_{this};
+ #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+diff --git chrome/browser/ui/chrome_select_file_policy.h chrome/browser/ui/chrome_select_file_policy.h
+index 49272553c7c53..5ba90c9a06ecf 100644
+--- chrome/browser/ui/chrome_select_file_policy.h
++++ chrome/browser/ui/chrome_select_file_policy.h
+@@ -30,6 +30,8 @@ class ChromeSelectFilePolicy : public ui::SelectFilePolicy {
+   // Returns true if local state allows showing file pickers.
+   static bool FileSelectDialogsAllowed();
+ 
++  content::WebContents* source_contents() const { return source_contents_; }
++
+  private:
+   raw_ptr<content::WebContents, AcrossTasksDanglingUntriaged> source_contents_;
+ };
+diff --git ui/shell_dialogs/execute_select_file_win.cc ui/shell_dialogs/execute_select_file_win.cc
+index 101e91826023b..35456ffad43f3 100644
+--- ui/shell_dialogs/execute_select_file_win.cc
++++ ui/shell_dialogs/execute_select_file_win.cc
+@@ -297,9 +297,7 @@ bool ExecuteSelectSingleFile(HWND owner,
+                              const std::vector<FileFilterSpec>& filter,
+                              int* filter_index,
+                              std::vector<base::FilePath>* paths) {
+-  // Note: The title is not passed down for historical reasons.
+-  // TODO(pmonette): Figure out if it's a worthwhile improvement.
+-  return RunOpenFileDialog(owner, std::u16string(), std::u16string(),
++  return RunOpenFileDialog(owner, title, std::u16string(),
+                            default_path, filter, 0, filter_index, paths);
+ }
+ 
+@@ -311,14 +309,13 @@ bool ExecuteSelectMultipleFile(HWND owner,
+                                std::vector<base::FilePath>* paths) {
+   DWORD dialog_options = FOS_ALLOWMULTISELECT;
+ 
+-  // Note: The title is not passed down for historical reasons.
+-  // TODO(pmonette): Figure out if it's a worthwhile improvement.
+-  return RunOpenFileDialog(owner, std::u16string(), std::u16string(),
++  return RunOpenFileDialog(owner, title, std::u16string(),
+                            default_path, filter, dialog_options, filter_index,
+                            paths);
+ }
+ 
+ bool ExecuteSaveFile(HWND owner,
++                     const std::u16string& title,
+                      const base::FilePath& default_path,
+                      const std::vector<FileFilterSpec>& filter,
+                      const std::wstring& def_ext,
+@@ -331,9 +328,7 @@ bool ExecuteSaveFile(HWND owner,
+ 
+   DWORD dialog_options = FOS_OVERWRITEPROMPT;
+ 
+-  // Note: The title is not passed down for historical reasons.
+-  // TODO(pmonette): Figure out if it's a worthwhile improvement.
+-  return RunSaveFileDialog(owner, std::u16string(), default_path, filter,
++  return RunSaveFileDialog(owner, title, default_path, filter,
+                            dialog_options, def_ext, filter_index, path);
+ }
+ 
+@@ -358,7 +353,7 @@ void ExecuteSelectFile(
+       break;
+     case SelectFileDialog::SELECT_SAVEAS_FILE: {
+       base::FilePath path;
+-      if (ExecuteSaveFile(owner, default_path, filter, default_extension,
++      if (ExecuteSaveFile(owner, title, default_path, filter, default_extension,
+                           &file_type_index, &path)) {
+         paths.push_back(std::move(path));
+       }
+diff --git ui/shell_dialogs/select_file_dialog.cc ui/shell_dialogs/select_file_dialog.cc
+index e2c00b2ec1532..a2e8753766597 100644
+--- ui/shell_dialogs/select_file_dialog.cc
++++ ui/shell_dialogs/select_file_dialog.cc
+@@ -88,8 +88,10 @@ void SelectFileDialog::SetFactory(
+ // static
+ scoped_refptr<SelectFileDialog> SelectFileDialog::Create(
+     Listener* listener,
+-    std::unique_ptr<ui::SelectFilePolicy> policy) {
+-  if (dialog_factory_)
++    std::unique_ptr<ui::SelectFilePolicy> policy,
++    bool run_from_cef) {
++  // Avoid reentrancy of the CEF factory.
++  if (dialog_factory_ && (!run_from_cef || !dialog_factory_->IsCefFactory()))
+     return dialog_factory_->Create(listener, std::move(policy));
+   return CreateSelectFileDialog(listener, std::move(policy));
+ }
+diff --git ui/shell_dialogs/select_file_dialog.h ui/shell_dialogs/select_file_dialog.h
+index 65f0342389117..c4b79bc0dab91 100644
+--- ui/shell_dialogs/select_file_dialog.h
++++ ui/shell_dialogs/select_file_dialog.h
+@@ -116,7 +116,8 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
+   // is refcounted and uses a background thread.
+   static scoped_refptr<SelectFileDialog> Create(
+       Listener* listener,
+-      std::unique_ptr<SelectFilePolicy> policy);
++      std::unique_ptr<SelectFilePolicy> policy,
++      bool run_from_cef = false);
+ 
+   SelectFileDialog(const SelectFileDialog&) = delete;
+   SelectFileDialog& operator=(const SelectFileDialog&) = delete;
+@@ -213,6 +214,19 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
+                   const GURL* caller = nullptr);
+   bool HasMultipleFileTypeChoices();
+ 
++  // Match the types used by CefWindowHandle.
++#if BUILDFLAG(IS_MAC)
++  using WidgetType = void*;
++  static constexpr WidgetType kNullWidget = nullptr;
++#else
++  using WidgetType = gfx::AcceleratedWidget;
++  static constexpr WidgetType kNullWidget = gfx::kNullAcceleratedWidget;
++#endif
++
++  void set_owning_widget(WidgetType widget) {
++    owning_widget_ = widget;
++  }
++
+  protected:
+   friend class base::RefCountedThreadSafe<SelectFileDialog>;
+ 
+@@ -238,6 +252,11 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
+   // The listener to be notified of selection completion.
+   raw_ptr<Listener> listener_;
+ 
++  std::unique_ptr<SelectFilePolicy> select_file_policy_;
++
++  // Support override of the |owning_window| value.
++  WidgetType owning_widget_ = kNullWidget;
++
+  private:
+   // Tests if the file selection dialog can be displayed by
+   // testing if the AllowFileSelectionDialogs-Policy is
+@@ -250,8 +269,6 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
+ 
+   // Returns true if the dialog has multiple file type choices.
+   virtual bool HasMultipleFileTypeChoicesImpl() = 0;
+-
+-  std::unique_ptr<SelectFilePolicy> select_file_policy_;
+ };
+ 
+ SelectFileDialog* CreateSelectFileDialog(
+diff --git ui/shell_dialogs/select_file_dialog_factory.h ui/shell_dialogs/select_file_dialog_factory.h
+index c7acd9b05fbb8..3e95e4125fa24 100644
+--- ui/shell_dialogs/select_file_dialog_factory.h
++++ ui/shell_dialogs/select_file_dialog_factory.h
+@@ -24,6 +24,8 @@ class SHELL_DIALOGS_EXPORT SelectFileDialogFactory {
+   virtual SelectFileDialog* Create(
+       ui::SelectFileDialog::Listener* listener,
+       std::unique_ptr<ui::SelectFilePolicy> policy) = 0;
++
++  virtual bool IsCefFactory() const { return false; }
+ };
+ 
+ }  // namespace ui
+diff --git ui/shell_dialogs/select_file_dialog_mac.mm ui/shell_dialogs/select_file_dialog_mac.mm
+index 0b8aaa3c0e4f0..fe01d3db2eabe 100644
+--- ui/shell_dialogs/select_file_dialog_mac.mm
++++ ui/shell_dialogs/select_file_dialog_mac.mm
+@@ -102,6 +102,10 @@ void SelectFileDialogImpl::SelectFileImpl(
+     mojo_window->CreateSelectFileDialog(std::move(receiver));
+   } else {
+     NSWindow* ns_window = gfx_window.GetNativeNSWindow();
++    if (!ns_window && owning_widget_) {
++      NSView* view = ((__bridge NSView*)owning_widget_);
++      ns_window = [view window];
++    }
+     mojo::MakeSelfOwnedReceiver(
+         std::make_unique<remote_cocoa::SelectFileDialogBridge>(ns_window),
+         std::move(receiver));
+diff --git ui/shell_dialogs/select_file_dialog_win.cc ui/shell_dialogs/select_file_dialog_win.cc
+index 04aa920d91675..93ea4988839cf 100644
+--- ui/shell_dialogs/select_file_dialog_win.cc
++++ ui/shell_dialogs/select_file_dialog_win.cc
+@@ -252,6 +252,8 @@ void SelectFileDialogImpl::SelectFileImpl(
+   HWND owner = owning_window && owning_window->GetRootWindow()
+                    ? owning_window->GetHost()->GetAcceleratedWidget()
+                    : nullptr;
++  if (!owner)
++    owner = owning_widget_;
+ 
+   std::unique_ptr<RunState> run_state = BeginRun(owner);
+ 
diff --git a/src/patch/patches/chrome_browser_dialogs_widget.patch b/src/patch/patches/chrome_browser_dialogs_widget.patch
new file mode 100644
index 0000000..1ca51f7
--- /dev/null
+++ b/src/patch/patches/chrome_browser_dialogs_widget.patch
@@ -0,0 +1,227 @@
+diff --git chrome/browser/ui/views/chrome_javascript_app_modal_view_factory_views.cc chrome/browser/ui/views/chrome_javascript_app_modal_view_factory_views.cc
+index b169371e4d42f..509e4bda85b47 100644
+--- chrome/browser/ui/views/chrome_javascript_app_modal_view_factory_views.cc
++++ chrome/browser/ui/views/chrome_javascript_app_modal_view_factory_views.cc
+@@ -100,7 +100,7 @@ javascript_dialogs::AppModalDialogView* CreateViewsJavaScriptDialog(
+   gfx::NativeWindow parent_window =
+       controller->web_contents()->GetTopLevelNativeWindow();
+ #if defined(USE_AURA)
+-  if (!parent_window->GetRootWindow()) {
++  if (parent_window && !parent_window->GetRootWindow()) {
+     // When we are part of a WebContents that isn't actually being displayed
+     // on the screen, we can't actually attach to it.
+     parent_window = nullptr;
+diff --git components/constrained_window/constrained_window_views.cc components/constrained_window/constrained_window_views.cc
+index 819da6b0bff94..a8e3ecd8527bd 100644
+--- components/constrained_window/constrained_window_views.cc
++++ components/constrained_window/constrained_window_views.cc
+@@ -105,15 +105,24 @@ void UpdateModalDialogPosition(views::Widget* widget,
+   if (widget->HasCapture())
+     return;
+ 
++  // |host_view| will be nullptr with CEF windowless rendering.
++  auto host_view = dialog_host->GetHostView();
+   views::Widget* host_widget =
+-      views::Widget::GetWidgetForNativeView(dialog_host->GetHostView());
++      host_view ? views::Widget::GetWidgetForNativeView(host_view) : nullptr;
+ 
+   // If the host view is not backed by a Views::Widget, just update the widget
+   // size. This can happen on MacViews under the Cocoa browser where the window
+   // modal dialogs are displayed as sheets, and their position is managed by a
+   // ConstrainedWindowSheetController instance.
+   if (!host_widget) {
++#if BUILDFLAG(IS_MAC)
+     widget->SetSize(size);
++#elif BUILDFLAG(IS_POSIX)
++    // Set the bounds here instead of relying on the default behavior of
++    // DesktopWindowTreeHostPlatform::CenterWindow which incorrectly centers
++    // the window on the screen.
++    widget->SetBounds(gfx::Rect(dialog_host->GetDialogPosition(size), size));
++#endif
+     return;
+   }
+ 
+@@ -219,7 +228,8 @@ views::Widget* CreateWebModalDialogViews(views::WidgetDelegate* dialog,
+ 
+   views::Widget* widget = views::DialogDelegate::CreateDialogWidget(
+       dialog, nullptr,
+-      manager->delegate()->GetWebContentsModalDialogHost()->GetHostView());
++      manager->delegate()->GetWebContentsModalDialogHost()->GetHostView(),
++      manager->delegate()->GetWebContentsModalDialogHost()->GetAcceleratedWidget());
+   widget->SetNativeWindowProperty(
+       views::kWidgetIdentifierKey,
+       const_cast<void*>(kConstrainedWindowWidgetIdentifier));
+@@ -241,8 +251,13 @@ views::Widget* CreateBrowserModalDialogViews(views::DialogDelegate* dialog,
+ 
+   gfx::NativeView parent_view =
+       parent ? CurrentClient()->GetDialogHostView(parent) : nullptr;
++  // Use with CEF windowless rendering.
++  gfx::AcceleratedWidget parent_widget =
++      parent ? gfx::kNullAcceleratedWidget :
++               CurrentClient()->GetModalDialogHost(parent)->GetAcceleratedWidget();
+   views::Widget* widget =
+-      views::DialogDelegate::CreateDialogWidget(dialog, nullptr, parent_view);
++      views::DialogDelegate::CreateDialogWidget(dialog, nullptr, parent_view,
++                                                parent_widget);
+   widget->SetNativeWindowProperty(
+       views::kWidgetIdentifierKey,
+       const_cast<void*>(kConstrainedWindowWidgetIdentifier));
+@@ -258,8 +273,7 @@ views::Widget* CreateBrowserModalDialogViews(views::DialogDelegate* dialog,
+   if (!requires_positioning)
+     return widget;
+ 
+-  ModalDialogHost* host =
+-      parent ? CurrentClient()->GetModalDialogHost(parent) : nullptr;
++  ModalDialogHost* host = CurrentClient()->GetModalDialogHost(parent);
+   if (host) {
+     DCHECK_EQ(parent_view, host->GetHostView());
+     ModalDialogHostObserver* dialog_host_observer =
+diff --git components/constrained_window/native_web_contents_modal_dialog_manager_views.cc components/constrained_window/native_web_contents_modal_dialog_manager_views.cc
+index b986b7fa98c73..1000f529acc82 100644
+--- components/constrained_window/native_web_contents_modal_dialog_manager_views.cc
++++ components/constrained_window/native_web_contents_modal_dialog_manager_views.cc
+@@ -188,9 +188,20 @@ void NativeWebContentsModalDialogManagerViews::HostChanged(
+   if (host_) {
+     host_->AddObserver(this);
+ 
+-    for (auto* widget : observed_widgets_) {
+-      views::Widget::ReparentNativeView(widget->GetNativeView(),
+-                                        host_->GetHostView());
++    // |host_view| will be nullptr with CEF windowless rendering.
++    if (auto host_view = host_->GetHostView()) {
++      for (auto* widget : observed_widgets_) {
++#if defined(USE_AURA)
++        auto widget_view = widget->GetNativeView();
++        // Don't reparent between different root windows. Doing so causes
++        // issues with layout of dialogs containing Chrome browsers.
++        if (host_view->GetRootWindow() == widget_view->GetRootWindow()) {
++          views::Widget::ReparentNativeView(widget_view, host_view);
++        }
++#else
++        views::Widget::ReparentNativeView(widget->GetNativeView(), host_view);
++#endif
++      }
+     }
+ 
+     OnPositionRequiresUpdate();
+diff --git components/web_modal/modal_dialog_host.h components/web_modal/modal_dialog_host.h
+index 51ed6bcf6b540..c6e1161140655 100644
+--- components/web_modal/modal_dialog_host.h
++++ components/web_modal/modal_dialog_host.h
+@@ -34,6 +34,10 @@ class WEB_MODAL_EXPORT ModalDialogHost {
+ 
+   // Returns the view against which the dialog is positioned and parented.
+   virtual gfx::NativeView GetHostView() const = 0;
++  // Returns the widget against which the dialog is positioned and parented.
++  // Used with CEF windowless rendering.
++  virtual gfx::AcceleratedWidget GetAcceleratedWidget() const {
++      return gfx::kNullAcceleratedWidget; }
+   // Gets the position for the dialog in coordinates relative to the host view.
+   virtual gfx::Point GetDialogPosition(const gfx::Size& size) = 0;
+   // Returns whether a dialog currently about to be shown should be activated.
+diff --git ui/views/window/dialog_delegate.cc ui/views/window/dialog_delegate.cc
+index 5a69839dd683d..b217b537eba4c 100644
+--- ui/views/window/dialog_delegate.cc
++++ ui/views/window/dialog_delegate.cc
+@@ -59,10 +59,12 @@ DialogDelegate::DialogDelegate() {
+ // static
+ Widget* DialogDelegate::CreateDialogWidget(WidgetDelegate* delegate,
+                                            gfx::NativeWindow context,
+-                                           gfx::NativeView parent) {
++                                           gfx::NativeView parent,
++                                           gfx::AcceleratedWidget parent_widget) {
+   views::Widget* widget = new views::Widget;
+   views::Widget::InitParams params =
+-      GetDialogWidgetInitParams(delegate, context, parent, gfx::Rect());
++      GetDialogWidgetInitParams(delegate, context, parent, gfx::Rect(),
++                                parent_widget);
+   widget->Init(std::move(params));
+   return widget;
+ }
+@@ -71,17 +73,19 @@ Widget* DialogDelegate::CreateDialogWidget(WidgetDelegate* delegate,
+ Widget* DialogDelegate::CreateDialogWidget(
+     std::unique_ptr<WidgetDelegate> delegate,
+     gfx::NativeWindow context,
+-    gfx::NativeView parent) {
++    gfx::NativeView parent,
++    gfx::AcceleratedWidget parent_widget) {
+   DCHECK(delegate->owned_by_widget());
+-  return CreateDialogWidget(delegate.release(), context, parent);
++  return CreateDialogWidget(delegate.release(), context, parent, parent_widget);
+ }
+ 
+ // static
+-bool DialogDelegate::CanSupportCustomFrame(gfx::NativeView parent) {
++bool DialogDelegate::CanSupportCustomFrame(gfx::NativeView parent,
++                                           gfx::AcceleratedWidget parent_widget) {
+ #if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && \
+     BUILDFLAG(ENABLE_DESKTOP_AURA)
+   // The new style doesn't support unparented dialogs on Linux desktop.
+-  return parent != nullptr;
++  return parent != nullptr || parent_widget != gfx::kNullAcceleratedWidget;
+ #else
+   return true;
+ #endif
+@@ -92,14 +96,15 @@ Widget::InitParams DialogDelegate::GetDialogWidgetInitParams(
+     WidgetDelegate* delegate,
+     gfx::NativeWindow context,
+     gfx::NativeView parent,
+-    const gfx::Rect& bounds) {
++    const gfx::Rect& bounds,
++    gfx::AcceleratedWidget parent_widget) {
+   views::Widget::InitParams params;
+   params.delegate = delegate;
+   params.bounds = bounds;
+   DialogDelegate* dialog = delegate->AsDialogDelegate();
+ 
+   if (dialog)
+-    dialog->params_.custom_frame &= CanSupportCustomFrame(parent);
++    dialog->params_.custom_frame &= CanSupportCustomFrame(parent, parent_widget);
+ 
+   if (!dialog || dialog->use_custom_frame()) {
+     params.opacity = Widget::InitParams::WindowOpacity::kTranslucent;
+@@ -112,6 +117,7 @@ Widget::InitParams DialogDelegate::GetDialogWidgetInitParams(
+   }
+   params.context = context;
+   params.parent = parent;
++  params.parent_widget = parent_widget;
+ #if !BUILDFLAG(IS_APPLE)
+   // Web-modal (ui::MODAL_TYPE_CHILD) dialogs with parents are marked as child
+   // widgets to prevent top-level window behavior (independent movement, etc).
+diff --git ui/views/window/dialog_delegate.h ui/views/window/dialog_delegate.h
+index 083874eb3f0bc..2ccacfca7d413 100644
+--- ui/views/window/dialog_delegate.h
++++ ui/views/window/dialog_delegate.h
+@@ -96,13 +96,18 @@ class VIEWS_EXPORT DialogDelegate : public WidgetDelegate {
+   // your use case.
+   static Widget* CreateDialogWidget(std::unique_ptr<WidgetDelegate> delegate,
+                                     gfx::NativeWindow context,
+-                                    gfx::NativeView parent);
++                                    gfx::NativeView parent,
++                                    gfx::AcceleratedWidget parent_widget =
++                                        gfx::kNullAcceleratedWidget);
+   static Widget* CreateDialogWidget(WidgetDelegate* delegate,
+                                     gfx::NativeWindow context,
+-                                    gfx::NativeView parent);
++                                    gfx::NativeView parent,
++                                    gfx::AcceleratedWidget parent_widget =
++                                        gfx::kNullAcceleratedWidget);
+ 
+   // Whether using custom dialog frame is supported for this dialog.
+-  static bool CanSupportCustomFrame(gfx::NativeView parent);
++  static bool CanSupportCustomFrame(gfx::NativeView parent,
++                                    gfx::AcceleratedWidget parent_widget);
+ 
+   // Returns the dialog widget InitParams for a given |context| or |parent|.
+   // If |bounds| is not empty, used to initially place the dialog, otherwise
+@@ -110,7 +115,9 @@ class VIEWS_EXPORT DialogDelegate : public WidgetDelegate {
+   static Widget::InitParams GetDialogWidgetInitParams(WidgetDelegate* delegate,
+                                                       gfx::NativeWindow context,
+                                                       gfx::NativeView parent,
+-                                                      const gfx::Rect& bounds);
++                                                      const gfx::Rect& bounds,
++                                                      gfx::AcceleratedWidget parent_widget =
++                                                          gfx::kNullAcceleratedWidget);
+ 
+   // Returns a mask specifying which of the available DialogButtons are visible
+   // for the dialog.
diff --git a/src/patch/patches/chrome_browser_extensions.patch b/src/patch/patches/chrome_browser_extensions.patch
new file mode 100644
index 0000000..5590382
--- /dev/null
+++ b/src/patch/patches/chrome_browser_extensions.patch
@@ -0,0 +1,35 @@
+diff --git chrome/browser/extensions/api/chrome_extensions_api_client.cc chrome/browser/extensions/api/chrome_extensions_api_client.cc
+index 4f11c0749d725..d5d6dbbafecb1 100644
+--- chrome/browser/extensions/api/chrome_extensions_api_client.cc
++++ chrome/browser/extensions/api/chrome_extensions_api_client.cc
+@@ -14,6 +14,7 @@
+ #include "base/strings/string_util.h"
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.h"
+ #include "chrome/browser/extensions/api/chrome_device_permissions_prompt.h"
+ #include "chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.h"
+@@ -91,6 +92,10 @@
+ #include "chrome/browser/extensions/clipboard_extension_helper_chromeos.h"
+ #endif
+ 
++#if BUILDFLAG(ENABLE_CEF)
++#include "cef/libcef/browser/chrome/extensions/chrome_mime_handler_view_guest_delegate_cef.h"
++#endif
++
+ #if BUILDFLAG(ENABLE_PRINTING)
+ #include "chrome/browser/printing/printing_init.h"
+ #endif
+@@ -318,6 +323,11 @@ ChromeExtensionsAPIClient::CreateGuestViewManagerDelegate() const {
+ std::unique_ptr<MimeHandlerViewGuestDelegate>
+ ChromeExtensionsAPIClient::CreateMimeHandlerViewGuestDelegate(
+     MimeHandlerViewGuest* guest) const {
++#if BUILDFLAG(ENABLE_CEF)
++  if (cef::IsChromeRuntimeEnabled()) {
++    return std::make_unique<ChromeMimeHandlerViewGuestDelegateCef>(guest);
++  }
++#endif
+   return std::make_unique<ChromeMimeHandlerViewGuestDelegate>();
+ }
+ 
diff --git a/src/patch/patches/chrome_browser_frame_mac.patch b/src/patch/patches/chrome_browser_frame_mac.patch
new file mode 100644
index 0000000..e5ed44a
--- /dev/null
+++ b/src/patch/patches/chrome_browser_frame_mac.patch
@@ -0,0 +1,97 @@
+diff --git chrome/browser/ui/views/frame/browser_frame_mac.h chrome/browser/ui/views/frame/browser_frame_mac.h
+index a5ee05ae5f5e9..97fd2e8da450e 100644
+--- chrome/browser/ui/views/frame/browser_frame_mac.h
++++ chrome/browser/ui/views/frame/browser_frame_mac.h
+@@ -11,6 +11,7 @@
+ #include "chrome/browser/command_observer.h"
+ #include "ui/views/widget/native_widget_mac.h"
+ 
++class Browser;
+ class BrowserFrame;
+ class BrowserView;
+ @class BrowserWindowTouchBarController;
+@@ -54,6 +55,21 @@ class BrowserFrameMac : public views::NativeWidgetMac,
+   bool ShouldUseInitialVisibleOnAllWorkspaces() const override;
+   void AnnounceTextInInProcessWindow(const std::u16string& text) override;
+ 
++  static void ValidateUserInterfaceItem(
++      Browser* browser,
++      int32_t command,
++      remote_cocoa::mojom::ValidateUserInterfaceItemResult* result);
++  static bool WillExecuteCommand(
++      Browser* browser,
++      int32_t command,
++      WindowOpenDisposition window_open_disposition,
++      bool is_before_first_responder);
++  static bool ExecuteCommand(
++      Browser* browser,
++      int32_t command,
++      WindowOpenDisposition window_open_disposition,
++      bool is_before_first_responder);
++
+  protected:
+   ~BrowserFrameMac() override;
+ 
+diff --git chrome/browser/ui/views/frame/browser_frame_mac.mm chrome/browser/ui/views/frame/browser_frame_mac.mm
+index 1473ed154f906..bf861087fe292 100644
+--- chrome/browser/ui/views/frame/browser_frame_mac.mm
++++ chrome/browser/ui/views/frame/browser_frame_mac.mm
+@@ -182,7 +182,14 @@ void BrowserFrameMac::OnWindowFullscreenTransitionComplete() {
+ void BrowserFrameMac::ValidateUserInterfaceItem(
+     int32_t tag,
+     remote_cocoa::mojom::ValidateUserInterfaceItemResult* result) {
+-  Browser* browser = browser_view_->browser();
++  return ValidateUserInterfaceItem(browser_view_->browser(), tag, result);
++}
++
++// static
++void BrowserFrameMac::ValidateUserInterfaceItem(
++    Browser* browser,
++    int32_t tag,
++    remote_cocoa::mojom::ValidateUserInterfaceItemResult* result) {
+   if (!chrome::SupportsCommand(browser, tag)) {
+     result->enable = false;
+     return;
+@@ -310,8 +317,16 @@ bool BrowserFrameMac::WillExecuteCommand(
+     int32_t command,
+     WindowOpenDisposition window_open_disposition,
+     bool is_before_first_responder) {
+-  Browser* browser = browser_view_->browser();
++  return WillExecuteCommand(browser_view_->browser(), command,
++                            window_open_disposition, is_before_first_responder);
++}
+ 
++// static
++bool BrowserFrameMac::WillExecuteCommand(
++    Browser* browser,
++    int32_t command,
++    WindowOpenDisposition window_open_disposition,
++    bool is_before_first_responder) {
+   if (is_before_first_responder) {
+     // The specification for this private extensions API is incredibly vague.
+     // For now, we avoid triggering chrome commands prior to giving the
+@@ -342,11 +357,20 @@ bool BrowserFrameMac::ExecuteCommand(
+     int32_t command,
+     WindowOpenDisposition window_open_disposition,
+     bool is_before_first_responder) {
+-  if (!WillExecuteCommand(command, window_open_disposition,
+-                          is_before_first_responder))
+-    return false;
++  return ExecuteCommand(browser_view_->browser(), command,
++                        window_open_disposition, is_before_first_responder);
++}
+ 
+-  Browser* browser = browser_view_->browser();
++// static
++bool BrowserFrameMac::ExecuteCommand(
++    Browser* browser,
++    int32_t command,
++    WindowOpenDisposition window_open_disposition,
++    bool is_before_first_responder) {
++  if (!WillExecuteCommand(browser, command, window_open_disposition,
++                          is_before_first_responder)) {
++    return false;
++  }
+ 
+   chrome::ExecuteCommandWithDisposition(browser, command,
+                                         window_open_disposition);
diff --git a/src/patch/patches/chrome_browser_net_export.patch b/src/patch/patches/chrome_browser_net_export.patch
deleted file mode 100644
index b62d3d9..0000000
--- a/src/patch/patches/chrome_browser_net_export.patch
+++ /dev/null
@@ -1,253 +0,0 @@
-diff --git chrome/browser/ui/BUILD.gn chrome/browser/ui/BUILD.gn
-index dfffff81bcf2..a4518ba20aaf 100644
---- chrome/browser/ui/BUILD.gn
-+++ chrome/browser/ui/BUILD.gn
-@@ -10,6 +10,7 @@ import("//build/config/features.gni")
- import("//build/config/jumbo.gni")
- import("//build/config/linux/gtk/gtk.gni")
- import("//build/config/ui.gni")
-+import("//cef/libcef/features/features.gni")
- import("//chrome/browser/buildflags.gni")
- import("//chrome/common/features.gni")
- import("//chromeos/assistant/assistant.gni")
-@@ -362,6 +363,10 @@ jumbo_static_library("ui") {
-     "//build/config/compiler:wexit_time_destructors",
-   ]
- 
-+  if (enable_cef) {
-+    configs += [ "//cef/libcef/features:config" ]
-+  }
-+
-   # Since browser and browser_ui actually depend on each other,
-   # we must omit the dependency from browser_ui to browser.
-   # However, this means browser_ui and browser should more or less
-@@ -383,6 +388,7 @@ jumbo_static_library("ui") {
-     "//base/allocator:buildflags",
-     "//build:branding_buildflags",
-     "//cc/paint",
-+    "//cef/libcef/features",
-     "//chrome:extra_resources",
-     "//chrome:resources",
-     "//chrome:strings",
-@@ -1470,6 +1476,7 @@ jumbo_static_library("ui") {
-       "//components/keep_alive_registry",
-       "//components/network_session_configurator/common",
-       "//components/page_load_metrics/browser",
-+      "//components/printing/common:mojo_interfaces",
-       "//components/profile_metrics",
-       "//components/search_provider_logos",
-       "//components/ui_metrics",
-diff --git chrome/browser/ui/webui/net_export_ui.cc chrome/browser/ui/webui/net_export_ui.cc
-index 93bfc84f49a1..eeee229e943f 100644
---- chrome/browser/ui/webui/net_export_ui.cc
-+++ chrome/browser/ui/webui/net_export_ui.cc
-@@ -21,13 +21,12 @@
- #include "base/strings/string_util.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/values.h"
-+#include "cef/libcef/features/features.h"
- #include "chrome/browser/browser_process.h"
--#include "chrome/browser/download/download_prefs.h"
- #include "chrome/browser/net/net_export_helper.h"
- #include "chrome/browser/net/system_network_context_manager.h"
- #include "chrome/browser/platform_util.h"
- #include "chrome/browser/profiles/profile.h"
--#include "chrome/browser/ui/chrome_select_file_policy.h"
- #include "chrome/common/channel_info.h"
- #include "chrome/common/url_constants.h"
- #include "components/grit/dev_ui_components_resources.h"
-@@ -42,7 +41,14 @@
- #include "content/public/browser/web_ui_message_handler.h"
- #include "extensions/buildflags/buildflags.h"
- #include "net/log/net_log_capture_mode.h"
-+
-+#if !BUILDFLAG(ENABLE_CEF)
-+#include "chrome/browser/download/download_prefs.h"
-+#include "chrome/browser/ui/chrome_select_file_policy.h"
- #include "ui/shell_dialogs/select_file_dialog.h"
-+#else
-+#include "cef/libcef/browser/browser_host_impl.h"
-+#endif
- 
- #if defined(OS_ANDROID)
- #include "chrome/browser/android/intent_helper.h"
-@@ -68,6 +74,7 @@ content::WebUIDataSource* CreateNetExportHTMLSource() {
-   return source;
- }
- 
-+#if !BUILDFLAG(ENABLE_CEF)
- void SetIfNotNull(base::DictionaryValue* dict,
-                   const base::StringPiece& path,
-                   std::unique_ptr<base::Value> in_value) {
-@@ -75,6 +82,7 @@ void SetIfNotNull(base::DictionaryValue* dict,
-     dict->Set(path, std::move(in_value));
-   }
- }
-+#endif  // !BUILDFLAG(ENABLE_CEF)
- 
- // This class receives javascript messages from the renderer.
- // Note that the WebUI infrastructure runs on the UI thread, therefore all of
-@@ -82,7 +90,9 @@ void SetIfNotNull(base::DictionaryValue* dict,
- class NetExportMessageHandler
-     : public WebUIMessageHandler,
-       public base::SupportsWeakPtr<NetExportMessageHandler>,
-+#if !BUILDFLAG(ENABLE_CEF)
-       public ui::SelectFileDialog::Listener,
-+#endif
-       public net_log::NetExportFileWriter::StateObserver {
-  public:
-   NetExportMessageHandler();
-@@ -98,11 +108,13 @@ class NetExportMessageHandler
-   void OnSendNetLog(const base::ListValue* list);
-   void OnShowFile(const base::ListValue* list);
- 
-+#if !BUILDFLAG(ENABLE_CEF)
-   // ui::SelectFileDialog::Listener implementation.
-   void FileSelected(const base::FilePath& path,
-                     int index,
-                     void* params) override;
-   void FileSelectionCanceled(void* params) override;
-+#endif  // !BUILDFLAG(ENABLE_CEF)
- 
-   // net_log::NetExportFileWriter::StateObserver implementation.
-   void OnNewState(const base::DictionaryValue& state) override;
-@@ -132,9 +144,16 @@ class NetExportMessageHandler
-   // renderer.
-   void NotifyUIWithState(std::unique_ptr<base::DictionaryValue> state);
- 
-+#if !BUILDFLAG(ENABLE_CEF)
-   // Opens the SelectFileDialog UI with the default path to save a
-   // NetLog file.
-   void ShowSelectFileDialog(const base::FilePath& default_path);
-+#else
-+  void ShowCefSaveAsDialog(content::WebContents* web_contents);
-+  void SaveAsDialogDismissed(
-+      int selected_accept_filter,
-+      const std::vector<base::FilePath>& file_paths);
-+#endif
- 
-   // Cached pointer to SystemNetworkContextManager's NetExportFileWriter.
-   net_log::NetExportFileWriter* file_writer_;
-@@ -150,7 +169,9 @@ class NetExportMessageHandler
-   net::NetLogCaptureMode capture_mode_;
-   uint64_t max_log_file_size_;
- 
-+#if !BUILDFLAG(ENABLE_CEF)
-   scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
-+#endif
- 
-   base::WeakPtrFactory<NetExportMessageHandler> weak_ptr_factory_{this};
- 
-@@ -167,8 +188,10 @@ NetExportMessageHandler::NetExportMessageHandler()
- NetExportMessageHandler::~NetExportMessageHandler() {
-   // There may be a pending file dialog, it needs to be told that the user
-   // has gone away so that it doesn't try to call back.
-+#if !BUILDFLAG(ENABLE_CEF)
-   if (select_file_dialog_)
-     select_file_dialog_->ListenerDestroyed();
-+#endif
- 
-   file_writer_->StopNetLog(nullptr);
- }
-@@ -231,6 +254,7 @@ void NetExportMessageHandler::OnStartNetLog(const base::ListValue* list) {
-   if (UsingMobileUI()) {
-     StartNetLog(base::FilePath());
-   } else {
-+#if !BUILDFLAG(ENABLE_CEF)
-     base::FilePath initial_dir = last_save_dir.Pointer()->empty() ?
-         DownloadPrefs::FromBrowserContext(
-             web_ui()->GetWebContents()->GetBrowserContext())->DownloadPath() :
-@@ -238,6 +262,9 @@ void NetExportMessageHandler::OnStartNetLog(const base::ListValue* list) {
-     base::FilePath initial_path =
-         initial_dir.Append(FILE_PATH_LITERAL("chrome-net-export-log.json"));
-     ShowSelectFileDialog(initial_path);
-+#else  // BUILDFLAG(ENABLE_CEF)
-+    ShowCefSaveAsDialog(web_ui()->GetWebContents());
-+#endif  // BUILDFLAG(ENABLE_CEF)
-   }
- }
- 
-@@ -247,6 +274,7 @@ void NetExportMessageHandler::OnStopNetLog(const base::ListValue* list) {
-   std::unique_ptr<base::DictionaryValue> ui_thread_polled_data(
-       new base::DictionaryValue());
- 
-+#if !BUILDFLAG(ENABLE_CEF)
-   Profile* profile = Profile::FromWebUI(web_ui());
-   SetIfNotNull(ui_thread_polled_data.get(), "prerenderInfo",
-                chrome_browser_net::GetPrerenderInfo(profile));
-@@ -256,6 +284,7 @@ void NetExportMessageHandler::OnStopNetLog(const base::ListValue* list) {
-   SetIfNotNull(ui_thread_polled_data.get(), "serviceProviders",
-                chrome_browser_net::GetWindowsServiceProviders());
- #endif
-+#endif  // !BUILDFLAG(ENABLE_CEF)
- 
-   file_writer_->StopNetLog(std::move(ui_thread_polled_data));
- }
-@@ -272,6 +301,7 @@ void NetExportMessageHandler::OnShowFile(const base::ListValue* list) {
-       base::Bind(&NetExportMessageHandler::ShowFileInShell, AsWeakPtr()));
- }
- 
-+#if !BUILDFLAG(ENABLE_CEF)
- void NetExportMessageHandler::FileSelected(const base::FilePath& path,
-                                            int index,
-                                            void* params) {
-@@ -290,6 +320,7 @@ void NetExportMessageHandler::FileSelectionCanceled(void* params) {
-   DCHECK(select_file_dialog_);
-   select_file_dialog_ = nullptr;
- }
-+#endif  // !BUILDFLAG(ENABLE_CEF)
- 
- void NetExportMessageHandler::OnNewState(const base::DictionaryValue& state) {
-   NotifyUIWithState(state.CreateDeepCopy());
-@@ -354,6 +385,7 @@ void NetExportMessageHandler::NotifyUIWithState(
-                                          *state);
- }
- 
-+#if !BUILDFLAG(ENABLE_CEF)
- void NetExportMessageHandler::ShowSelectFileDialog(
-     const base::FilePath& default_path) {
-   // User may have clicked more than once before the save dialog appears.
-@@ -372,6 +404,43 @@ void NetExportMessageHandler::ShowSelectFileDialog(
-       ui::SelectFileDialog::SELECT_SAVEAS_FILE, base::string16(), default_path,
-       &file_type_info, 0, base::FilePath::StringType(), owning_window, nullptr);
- }
-+#endif  // !BUILDFLAG(ENABLE_CEF)
-+
-+#if BUILDFLAG(ENABLE_CEF)
-+
-+void NetExportMessageHandler::ShowCefSaveAsDialog(
-+    content::WebContents* web_contents) {
-+  CefRefPtr<CefBrowserHostImpl> cef_browser =
-+      CefBrowserHostImpl::GetBrowserForContents(web_contents);
-+  if (!cef_browser)
-+    return;
-+
-+  base::FilePath initial_dir;
-+  if (!last_save_dir.Pointer()->empty())
-+    initial_dir = *last_save_dir.Pointer();
-+  base::FilePath initial_path =
-+      initial_dir.Append(FILE_PATH_LITERAL("chrome-net-export-log.json"));
-+
-+  CefFileDialogRunner::FileChooserParams params;
-+  params.mode = blink::mojom::FileChooserParams::Mode::kSave;
-+  params.default_file_name = initial_path;
-+  params.accept_types.push_back(CefString(initial_path.Extension()));
-+
-+  cef_browser->RunFileChooser(
-+      params, base::Bind(&NetExportMessageHandler::SaveAsDialogDismissed,
-+                         weak_ptr_factory_.GetWeakPtr()));
-+}
-+
-+void NetExportMessageHandler::SaveAsDialogDismissed(
-+    int selected_accept_filter,
-+    const std::vector<base::FilePath>& file_paths) {
-+  if (file_paths.size() == 1) {
-+    *last_save_dir.Pointer() = file_paths[0].DirName();
-+    StartNetLog(file_paths[0]);
-+  }
-+}
-+
-+#endif  // BUILDFLAG(ENABLE_CEF)
- 
- }  // namespace
- 
diff --git a/src/patch/patches/chrome_browser_net_proxy.patch b/src/patch/patches/chrome_browser_net_proxy.patch
new file mode 100644
index 0000000..2534b11
--- /dev/null
+++ b/src/patch/patches/chrome_browser_net_proxy.patch
@@ -0,0 +1,33 @@
+diff --git chrome/browser/net/proxy_config_monitor.cc chrome/browser/net/proxy_config_monitor.cc
+index c9281f7abfbde..a1b7c77475b54 100644
+--- chrome/browser/net/proxy_config_monitor.cc
++++ chrome/browser/net/proxy_config_monitor.cc
+@@ -9,6 +9,7 @@
+ #include "base/strings/utf_string_conversions.h"
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/browser_process.h"
+ #include "chrome/browser/net/proxy_service_factory.h"
+ #include "chrome/browser/profiles/profile.h"
+@@ -21,6 +22,10 @@
+ #include "chrome/browser/ash/profiles/profile_helper.h"
+ #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+ 
++#if BUILDFLAG(ENABLE_CEF)
++#include "cef/libcef/common/extensions/extensions_util.h"
++#endif
++
+ #if BUILDFLAG(ENABLE_EXTENSIONS)
+ #include "chrome/browser/extensions/api/proxy/proxy_api.h"
+ #endif
+@@ -92,6 +97,9 @@ void ProxyConfigMonitor::AddToNetworkContextParams(
+   }
+ 
+ #if BUILDFLAG(ENABLE_EXTENSIONS)
++#if BUILDFLAG(ENABLE_CEF)
++  if (!cef::IsAlloyRuntimeEnabled() || extensions::ExtensionsEnabled())
++#endif
+   error_receiver_set_.Add(this, network_context_params->proxy_error_client
+                                     .InitWithNewPipeAndPassReceiver());
+ #endif
diff --git a/src/patch/patches/chrome_browser_permission_prompt.patch b/src/patch/patches/chrome_browser_permission_prompt.patch
new file mode 100644
index 0000000..d47d47a
--- /dev/null
+++ b/src/patch/patches/chrome_browser_permission_prompt.patch
@@ -0,0 +1,208 @@
+diff --git chrome/browser/background_fetch/background_fetch_permission_context.cc chrome/browser/background_fetch/background_fetch_permission_context.cc
+index 429739d7b8dfe..0f4bff365f62b 100644
+--- chrome/browser/background_fetch/background_fetch_permission_context.cc
++++ chrome/browser/background_fetch/background_fetch_permission_context.cc
+@@ -4,6 +4,7 @@
+ 
+ #include "chrome/browser/background_fetch/background_fetch_permission_context.h"
+ 
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/browser_process.h"
+ #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+ #include "chrome/browser/download/download_request_limiter.h"
+@@ -25,7 +26,8 @@ ContentSetting BackgroundFetchPermissionContext::GetPermissionStatusInternal(
+     const GURL& embedding_origin) const {
+   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ 
+-  if (render_frame_host && !render_frame_host->GetParent()) {
++  if (!cef::IsAlloyRuntimeEnabled() &&
++      render_frame_host && !render_frame_host->GetParent()) {
+     DownloadRequestLimiter* limiter =
+         g_browser_process->download_request_limiter();
+     DCHECK(limiter);
+diff --git chrome/browser/background_sync/periodic_background_sync_permission_context.cc chrome/browser/background_sync/periodic_background_sync_permission_context.cc
+index ea1467d09700d..5537a99500e7f 100644
+--- chrome/browser/background_sync/periodic_background_sync_permission_context.cc
++++ chrome/browser/background_sync/periodic_background_sync_permission_context.cc
+@@ -6,6 +6,7 @@
+ 
+ #include "base/feature_list.h"
+ #include "build/build_config.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+ #include "chrome/browser/installable/installable_utils.h"
+ #include "chrome/browser/profiles/profile.h"
+@@ -89,6 +90,10 @@ PeriodicBackgroundSyncPermissionContext::GetPermissionStatusInternal(
+     return CONTENT_SETTING_ALLOW;
+ #endif
+ 
++  if (cef::IsAlloyRuntimeEnabled()) {
++    return CONTENT_SETTING_BLOCK;
++  }
++
+   bool can_bypass_install_requirement =
+       base::FeatureList::IsEnabled(
+           features::kPeriodicSyncPermissionForDefaultSearchEngine) &&
+diff --git chrome/browser/permissions/chrome_permissions_client.cc chrome/browser/permissions/chrome_permissions_client.cc
+index 4d895c857260c..4dbfba9b15cae 100644
+--- chrome/browser/permissions/chrome_permissions_client.cc
++++ chrome/browser/permissions/chrome_permissions_client.cc
+@@ -14,6 +14,7 @@
+ #include "base/time/time.h"
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/bluetooth/bluetooth_chooser_context_factory.h"
+ #include "chrome/browser/content_settings/cookie_settings_factory.h"
+ #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+@@ -175,6 +176,9 @@ ChromePermissionsClient::GetPermissionDecisionAutoBlocker(
+ double ChromePermissionsClient::GetSiteEngagementScore(
+     content::BrowserContext* browser_context,
+     const GURL& origin) {
++  // No SiteEngagementService with the Alloy runtime.
++  if (cef::IsAlloyRuntimeEnabled())
++    return 0.0;
+   return site_engagement::SiteEngagementService::Get(
+              Profile::FromBrowserContext(browser_context))
+       ->GetScore(origin);
+@@ -338,8 +342,10 @@ ChromePermissionsClient::CreatePermissionUiSelectors(
+       std::make_unique<ContextualNotificationPermissionUiSelector>());
+   selectors.emplace_back(std::make_unique<PrefBasedQuietPermissionUiSelector>(
+       Profile::FromBrowserContext(browser_context)));
++  if (!cef::IsAlloyRuntimeEnabled()) {
+   selectors.emplace_back(std::make_unique<PredictionBasedPermissionUiSelector>(
+       Profile::FromBrowserContext(browser_context)));
++  }
+   return selectors;
+ }
+ 
+diff --git chrome/browser/permissions/permission_manager_factory.cc chrome/browser/permissions/permission_manager_factory.cc
+index b0374f3adafea..faf9e7102f571 100644
+--- chrome/browser/permissions/permission_manager_factory.cc
++++ chrome/browser/permissions/permission_manager_factory.cc
+@@ -6,6 +6,7 @@
+ 
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/background_fetch/background_fetch_permission_context.h"
+ #include "chrome/browser/background_sync/periodic_background_sync_permission_context.h"
+ #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+@@ -56,8 +57,10 @@ permissions::PermissionManager::PermissionContextMap CreatePermissionContexts(
+       std::make_unique<GeolocationPermissionContextDelegate>(profile);
+ #endif  // BUILDFLAG(IS_ANDROID)
+ #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS)
++  if (!cef::IsAlloyRuntimeEnabled()) {
+   delegates.geolocation_manager = device::GeolocationManager::GetInstance();
+   DCHECK(delegates.geolocation_manager);
++  }
+ #endif
+   delegates.media_stream_device_enumerator =
+       MediaCaptureDevicesDispatcher::GetInstance();
+diff --git chrome/browser/storage/durable_storage_permission_context.cc chrome/browser/storage/durable_storage_permission_context.cc
+index 9934727f31a59..765b822241e4d 100644
+--- chrome/browser/storage/durable_storage_permission_context.cc
++++ chrome/browser/storage/durable_storage_permission_context.cc
+@@ -8,6 +8,7 @@
+ 
+ #include "base/check_op.h"
+ #include "base/containers/contains.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/bookmarks/bookmark_model_factory.h"
+ #include "chrome/browser/content_settings/cookie_settings_factory.h"
+ #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+@@ -56,7 +57,10 @@ void DurableStoragePermissionContext::DecidePermission(
+ 
+   // Durable is only allowed to be granted to the top-level origin. Embedding
+   // origin is the last committed navigation origin to the web contents.
+-  if (request_data.requesting_origin != request_data.embedding_origin) {
++  // Permission depends on PWA and site engagement subsystems which are not
++  // supported by the Alloy runtime (see issue #3379).
++  if (cef::IsAlloyRuntimeEnabled() ||
++      request_data.requesting_origin != request_data.embedding_origin) {
+     NotifyPermissionSet(request_data.id, request_data.requesting_origin,
+                         request_data.embedding_origin, std::move(callback),
+                         /*persist=*/false, CONTENT_SETTING_DEFAULT,
+diff --git chrome/browser/ui/permission_bubble/permission_prompt.h chrome/browser/ui/permission_bubble/permission_prompt.h
+index fbce13c16ad10..0512b2f09937e 100644
+--- chrome/browser/ui/permission_bubble/permission_prompt.h
++++ chrome/browser/ui/permission_bubble/permission_prompt.h
+@@ -11,6 +11,13 @@ namespace content {
+ class WebContents;
+ }
+ 
++using CreatePermissionPromptFunctionPtr =
++    std::unique_ptr<permissions::PermissionPrompt> (*)(
++        content::WebContents* web_contents,
++        permissions::PermissionPrompt::Delegate* delegate,
++        bool* default_handling);
++void SetCreatePermissionPromptFunction(CreatePermissionPromptFunctionPtr);
++
+ // Factory function to create permission prompts for chrome.
+ std::unique_ptr<permissions::PermissionPrompt> CreatePermissionPrompt(
+     content::WebContents* web_contents,
+diff --git chrome/browser/ui/views/permissions/permission_prompt_factory.cc chrome/browser/ui/views/permissions/permission_prompt_factory.cc
+index 3171d0aed2cd0..dc47430ccc81e 100644
+--- chrome/browser/ui/views/permissions/permission_prompt_factory.cc
++++ chrome/browser/ui/views/permissions/permission_prompt_factory.cc
+@@ -182,11 +182,28 @@ std::unique_ptr<permissions::PermissionPrompt> CreateQuietPrompt(
+   }
+ }
+ 
++CreatePermissionPromptFunctionPtr g_create_permission_prompt_ptr = nullptr;
++
+ }  // namespace
+ 
++void SetCreatePermissionPromptFunction(
++    CreatePermissionPromptFunctionPtr ptr) {
++  g_create_permission_prompt_ptr = ptr;
++}
++
+ std::unique_ptr<permissions::PermissionPrompt> CreatePermissionPrompt(
+     content::WebContents* web_contents,
+     permissions::PermissionPrompt::Delegate* delegate) {
++  if (g_create_permission_prompt_ptr) {
++    bool default_handling = true;
++    auto prompt = g_create_permission_prompt_ptr(web_contents, delegate,
++                                                 &default_handling);
++    if (prompt)
++      return prompt;
++    if (!default_handling)
++      return nullptr;
++  }
++
+   Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
+   if (!browser) {
+     DLOG(WARNING) << "Permission prompt suppressed because the WebContents is "
+diff --git components/embedder_support/permission_context_utils.cc components/embedder_support/permission_context_utils.cc
+index 07f3c7c86b22d..110e48d59a75a 100644
+--- components/embedder_support/permission_context_utils.cc
++++ components/embedder_support/permission_context_utils.cc
+@@ -5,6 +5,7 @@
+ #include "components/embedder_support/permission_context_utils.h"
+ 
+ #include "build/build_config.h"
++#include "cef/libcef/features/runtime.h"
+ #include "components/background_sync/background_sync_permission_context.h"
+ #include "components/permissions/contexts/accessibility_permission_context.h"
+ #include "components/permissions/contexts/camera_pan_tilt_zoom_permission_context.h"
+@@ -77,12 +78,19 @@ CreateDefaultPermissionContexts(content::BrowserContext* browser_context,
+           std::move(delegates.geolocation_permission_context_delegate),
+           is_regular_profile);
+ #elif BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS)
++  if (cef::IsAlloyRuntimeEnabled()) {
++    permission_contexts[ContentSettingsType::GEOLOCATION] =
++        std::make_unique<permissions::GeolocationPermissionContext>(
++            browser_context,
++            std::move(delegates.geolocation_permission_context_delegate));
++  } else {
+   DCHECK(delegates.geolocation_manager);
+   permission_contexts[ContentSettingsType::GEOLOCATION] =
+       std::make_unique<permissions::GeolocationPermissionContextSystem>(
+           browser_context,
+           std::move(delegates.geolocation_permission_context_delegate),
+           delegates.geolocation_manager);
++  }
+ #else
+   permission_contexts[ContentSettingsType::GEOLOCATION] =
+       std::make_unique<permissions::GeolocationPermissionContext>(
diff --git a/src/patch/patches/chrome_browser_policy.patch b/src/patch/patches/chrome_browser_policy.patch
new file mode 100644
index 0000000..95134c6
--- /dev/null
+++ b/src/patch/patches/chrome_browser_policy.patch
@@ -0,0 +1,429 @@
+diff --git chrome/browser/policy/browser_dm_token_storage_linux.cc chrome/browser/policy/browser_dm_token_storage_linux.cc
+index 10085136f52ce..ec1be9babecc2 100644
+--- chrome/browser/policy/browser_dm_token_storage_linux.cc
++++ chrome/browser/policy/browser_dm_token_storage_linux.cc
+@@ -22,6 +22,7 @@
+ #include "base/task/task_traits.h"
+ #include "base/task/thread_pool.h"
+ #include "base/threading/scoped_blocking_call.h"
++#include "chrome/browser/policy/chrome_browser_policy_connector.h"
+ #include "chrome/common/chrome_paths.h"
+ 
+ namespace policy {
+@@ -116,8 +117,8 @@ std::string BrowserDMTokenStorageLinux::InitEnrollmentToken() {
+   std::string enrollment_token;
+   base::FilePath dir_policy_files_path;
+ 
+-  if (!base::PathService::Get(chrome::DIR_POLICY_FILES,
+-                              &dir_policy_files_path)) {
++  if (!ChromeBrowserPolicyConnector::GetDirPolicyFilesPath(
++          &dir_policy_files_path)) {
+     return std::string();
+   }
+ 
+@@ -147,8 +148,8 @@ bool BrowserDMTokenStorageLinux::InitEnrollmentErrorOption() {
+   std::string options;
+   base::FilePath dir_policy_files_path;
+ 
+-  if (!base::PathService::Get(chrome::DIR_POLICY_FILES,
+-                              &dir_policy_files_path)) {
++  if (!ChromeBrowserPolicyConnector::GetDirPolicyFilesPath(
++          &dir_policy_files_path)) {
+     return false;
+   }
+ 
+diff --git chrome/browser/policy/browser_dm_token_storage_mac.mm chrome/browser/policy/browser_dm_token_storage_mac.mm
+index 22fdb0efb78c7..39adc3f192ba1 100644
+--- chrome/browser/policy/browser_dm_token_storage_mac.mm
++++ chrome/browser/policy/browser_dm_token_storage_mac.mm
+@@ -26,6 +26,7 @@
+ #include "base/syslog_logging.h"
+ #include "base/task/thread_pool.h"
+ #include "base/threading/scoped_blocking_call.h"
++#include "chrome/browser/policy/chrome_browser_policy_connector.h"
+ #include "chrome/common/chrome_paths.h"
+ #include "third_party/abseil-cpp/absl/types/optional.h"
+ 
+@@ -47,11 +48,6 @@ const char kEnrollmentOptionsFilePath[] = FILE_PATH_LITERAL(
+     "/Library/Google/Chrome/CloudManagementEnrollmentOptions");
+ const char kEnrollmentMandatoryOption[] = "Mandatory";
+ 
+-// Explicitly access the "com.google.Chrome" bundle ID, no matter what this
+-// app's bundle ID actually is. All channels of Chrome should obey the same
+-// policies.
+-const CFStringRef kBundleId = CFSTR("com.google.Chrome");
+-
+ constexpr char kEnrollmentTokenMetricsName[] =
+     "Enterprise.CloudManagementEnrollmentTokenLocation.Mac";
+ 
+@@ -104,16 +100,22 @@ bool DeleteDMTokenFromAppDataDir(const std::string& client_id) {
+ // Get the enrollment token from policy file: /Library/com.google.Chrome.plist.
+ // Return true if policy is set, otherwise false.
+ bool GetEnrollmentTokenFromPolicy(std::string* enrollment_token) {
++  base::apple::ScopedCFTypeRef<CFStringRef> bundle_id(
++      ChromeBrowserPolicyConnector::GetBundleId());
++  if (!bundle_id) {
++    return false;
++  }
++
+   // Since the configuration management infrastructure is not initialized when
+   // this code runs, read the policy preference directly.
+   base::apple::ScopedCFTypeRef<CFPropertyListRef> value(
+-      CFPreferencesCopyAppValue(kEnrollmentTokenPolicyName, kBundleId));
++      CFPreferencesCopyAppValue(kEnrollmentTokenPolicyName, bundle_id));
+ 
+   // Read the enrollment token from the new location. If that fails, try the old
+   // location (which will be deprecated soon). If that also fails, bail as there
+   // is no token set.
+   if (!value ||
+-      !CFPreferencesAppValueIsForced(kEnrollmentTokenPolicyName, kBundleId)) {
++      !CFPreferencesAppValueIsForced(kEnrollmentTokenPolicyName, bundle_id)) {
+     return false;
+   }
+   CFStringRef value_string = base::apple::CFCast<CFStringRef>(value);
+@@ -138,12 +140,18 @@ bool GetEnrollmentTokenFromFile(std::string* enrollment_token) {
+ }
+ 
+ absl::optional<bool> IsEnrollmentMandatoryByPolicy() {
++  base::apple::ScopedCFTypeRef<CFStringRef> bundle_id(
++      ChromeBrowserPolicyConnector::GetBundleId());
++  if (!bundle_id) {
++    return absl::nullopt;
++  }
++
+   base::apple::ScopedCFTypeRef<CFPropertyListRef> value(
+       CFPreferencesCopyAppValue(kEnrollmentMandatoryOptionPolicyName,
+-                                kBundleId));
++                                bundle_id));
+ 
+   if (!value || !CFPreferencesAppValueIsForced(
+-                    kEnrollmentMandatoryOptionPolicyName, kBundleId)) {
++                    kEnrollmentMandatoryOptionPolicyName, bundle_id)) {
+     return absl::optional<bool>();
+   }
+ 
+diff --git chrome/browser/policy/chrome_browser_policy_connector.cc chrome/browser/policy/chrome_browser_policy_connector.cc
+index bf03f3d03991a..c36d26af6747c 100644
+--- chrome/browser/policy/chrome_browser_policy_connector.cc
++++ chrome/browser/policy/chrome_browser_policy_connector.cc
+@@ -13,11 +13,14 @@
+ #include "base/files/file_util.h"
+ #include "base/functional/bind.h"
+ #include "base/functional/callback.h"
++#include "base/no_destructor.h"
+ #include "base/path_service.h"
++#include "base/strings/utf_string_conversions.h"
+ #include "base/task/thread_pool.h"
+ #include "build/branding_buildflags.h"
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/features.h"
+ #include "chrome/browser/browser_process.h"
+ #include "chrome/browser/enterprise/browser_management/management_service_factory.h"
+ #include "chrome/browser/policy/configuration_policy_handler_list_factory.h"
+@@ -85,6 +88,11 @@
+ namespace policy {
+ namespace {
+ bool command_line_enabled_for_testing = false;
++
++std::string* PlatformPolicyId() {
++  static base::NoDestructor<std::string> id;
++  return id.get();
++}
+ }  // namespace
+ 
+ ChromeBrowserPolicyConnector::ChromeBrowserPolicyConnector()
+@@ -239,6 +247,73 @@ void ChromeBrowserPolicyConnector::EnableCommandLineSupportForTesting() {
+   command_line_enabled_for_testing = true;
+ }
+ 
++// static
++void ChromeBrowserPolicyConnector::EnablePlatformPolicySupport(
++    const std::string& id) {
++  *PlatformPolicyId() = id;
++}
++
++#if BUILDFLAG(IS_WIN)
++
++// static
++std::wstring ChromeBrowserPolicyConnector::GetPolicyKey() {
++#if BUILDFLAG(ENABLE_CEF)
++  const std::string& policy_id = *PlatformPolicyId();
++  if (!policy_id.empty()) {
++    return base::UTF8ToWide(policy_id);
++  }
++  return std::wstring();
++#else
++  return kRegistryChromePolicyKey;
++#endif
++}
++
++#elif BUILDFLAG(IS_MAC)
++
++// static
++base::apple::ScopedCFTypeRef<CFStringRef>
++ChromeBrowserPolicyConnector::GetBundleId() {
++#if BUILDFLAG(ENABLE_CEF)
++  const std::string& policy_id = *PlatformPolicyId();
++  if (policy_id.empty()) {
++    return base::apple::ScopedCFTypeRef<CFStringRef>();
++  }
++
++  return base::SysUTF8ToCFStringRef(policy_id);
++#elif BUILDFLAG(GOOGLE_CHROME_BRANDING)
++  // Explicitly access the "com.google.Chrome" bundle ID, no matter what this
++  // app's bundle ID actually is. All channels of Chrome should obey the same
++  // policies.
++  return CFSTR("com.google.Chrome");
++#else
++  return base::SysUTF8ToCFStringRef(base::apple::BaseBundleID());
++#endif
++}
++
++#elif BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID)
++
++// static
++bool ChromeBrowserPolicyConnector::GetDirPolicyFilesPath(base::FilePath* path) {
++#if BUILDFLAG(ENABLE_CEF)
++  const std::string& policy_id = *PlatformPolicyId();
++  if (policy_id.empty()) {
++    return false;
++  }
++
++  base::FilePath policy_path(policy_id);
++  if (!policy_path.IsAbsolute()) {
++    return false;
++  }
++
++  *path = policy_path;
++  return true;
++#else
++  return base::PathService::Get(chrome::DIR_POLICY_FILES, path);
++#endif
++}
++
++#endif  // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID)
++
+ base::flat_set<std::string>
+ ChromeBrowserPolicyConnector::device_affiliation_ids() const {
+ #if !BUILDFLAG(IS_CHROMEOS_ASH)
+@@ -310,22 +385,21 @@ ChromeBrowserPolicyConnector::CreatePolicyProviders() {
+ std::unique_ptr<ConfigurationPolicyProvider>
+ ChromeBrowserPolicyConnector::CreatePlatformProvider() {
+ #if BUILDFLAG(IS_WIN)
++  const std::wstring policy_key = GetPolicyKey();
++  if (policy_key.empty()) {
++    return nullptr;
++  }
+   std::unique_ptr<AsyncPolicyLoader> loader(PolicyLoaderWin::Create(
+       base::ThreadPool::CreateSequencedTaskRunner(
+           {base::MayBlock(), base::TaskPriority::BEST_EFFORT}),
+-      ManagementServiceFactory::GetForPlatform(), kRegistryChromePolicyKey));
++      ManagementServiceFactory::GetForPlatform(), policy_key));
+   return std::make_unique<AsyncPolicyProvider>(GetSchemaRegistry(),
+                                                std::move(loader));
+ #elif BUILDFLAG(IS_MAC)
+-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+-  // Explicitly watch the "com.google.Chrome" bundle ID, no matter what this
+-  // app's bundle ID actually is. All channels of Chrome should obey the same
+-  // policies.
+-  CFStringRef bundle_id = CFSTR("com.google.Chrome");
+-#else
+-  base::apple::ScopedCFTypeRef<CFStringRef> bundle_id(
+-      base::SysUTF8ToCFStringRef(base::apple::BaseBundleID()));
+-#endif
++  base::apple::ScopedCFTypeRef<CFStringRef> bundle_id(GetBundleId());
++  if (!bundle_id) {
++    return nullptr;
++  }
+   auto loader = std::make_unique<PolicyLoaderMac>(
+       base::ThreadPool::CreateSequencedTaskRunner(
+           {base::MayBlock(), base::TaskPriority::BEST_EFFORT}),
+@@ -335,7 +409,7 @@ ChromeBrowserPolicyConnector::CreatePlatformProvider() {
+                                                std::move(loader));
+ #elif BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID)
+   base::FilePath config_dir_path;
+-  if (base::PathService::Get(chrome::DIR_POLICY_FILES, &config_dir_path)) {
++  if (GetDirPolicyFilesPath(&config_dir_path)) {
+ #if BUILDFLAG(IS_CHROMEOS)
+     // If the folder containing the policy files doesn't exist, there's no need
+     // to have a provider for them. Note that in verified boot, the folder
+diff --git chrome/browser/policy/chrome_browser_policy_connector.h chrome/browser/policy/chrome_browser_policy_connector.h
+index 13b714bab7db5..f8eb85a586ce6 100644
+--- chrome/browser/policy/chrome_browser_policy_connector.h
++++ chrome/browser/policy/chrome_browser_policy_connector.h
+@@ -28,6 +28,10 @@
+ #include "components/policy/core/common/policy_loader_lacros.h"
+ #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
+ 
++#if BUILDFLAG(IS_MAC)
++#include "base/apple/scoped_cftyperef.h"
++#endif
++
+ class PrefService;
+ 
+ namespace policy {
+@@ -120,6 +124,25 @@ class ChromeBrowserPolicyConnector : public BrowserPolicyConnector {
+ 
+   static void EnableCommandLineSupportForTesting();
+ 
++  // Enable platform policy support with the specified retrieval |id|. Support
++  // is disabled by default, and if |id| is empty.
++  // On Windows, this is a registry key like "SOFTWARE\\Policies\\Google\\Chrome".
++  // On MacOS, this is a bundle ID like "com.google.Chrome".
++  // On Linux, this is a directory path like "/etc/opt/chrome/policies".
++  static void EnablePlatformPolicySupport(const std::string& id);
++
++  // Platform-specific retrieval of the policy ID value.
++#if BUILDFLAG(IS_WIN)
++  // Replaces all direct usage of kRegistryChromePolicyKey.
++  static std::wstring GetPolicyKey();
++#elif BUILDFLAG(IS_MAC)
++  // Replaces all direct usage of CFSTR("com.google.Chrome").
++  static base::apple::ScopedCFTypeRef<CFStringRef> GetBundleId();
++#elif BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID)
++  // Replaces all direct usage of chrome::DIR_POLICY_FILES.
++  static bool GetDirPolicyFilesPath(base::FilePath* path);
++#endif
++
+   virtual base::flat_set<std::string> device_affiliation_ids() const;
+ 
+ #if BUILDFLAG(IS_CHROMEOS_LACROS)
+diff --git chrome/browser/policy/policy_path_parser_mac.mm chrome/browser/policy/policy_path_parser_mac.mm
+index 44a46c9c37788..873a6469c7ab5 100644
+--- chrome/browser/policy/policy_path_parser_mac.mm
++++ chrome/browser/policy/policy_path_parser_mac.mm
+@@ -16,6 +16,7 @@
+ #include "base/logging.h"
+ #include "base/strings/sys_string_conversions.h"
+ #include "build/branding_buildflags.h"
++#include "chrome/browser/policy/chrome_browser_policy_connector.h"
+ #include "components/policy/policy_constants.h"
+ 
+ namespace policy::path_parser {
+@@ -97,15 +98,11 @@ base::FilePath::StringType ExpandPathVariables(
+ void CheckUserDataDirPolicy(base::FilePath* user_data_dir) {
+   // Since the configuration management infrastructure is not initialized when
+   // this code runs, read the policy preference directly.
+-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+-  // Explicitly access the "com.google.Chrome" bundle ID, no matter what this
+-  // app's bundle ID actually is. All channels of Chrome should obey the same
+-  // policies.
+-  CFStringRef bundle_id = CFSTR("com.google.Chrome");
+-#else
+   base::apple::ScopedCFTypeRef<CFStringRef> bundle_id(
+-      base::SysUTF8ToCFStringRef(base::apple::BaseBundleID()));
+-#endif
++      policy::ChromeBrowserPolicyConnector::GetBundleId());
++  if (!bundle_id) {
++    return;
++  }
+ 
+   base::apple::ScopedCFTypeRef<CFStringRef> key(
+       base::SysUTF8ToCFStringRef(policy::key::kUserDataDir));
+diff --git chrome/browser/policy/policy_path_parser_win.cc chrome/browser/policy/policy_path_parser_win.cc
+index 8dbf958c189dd..6eaccc6688eca 100644
+--- chrome/browser/policy/policy_path_parser_win.cc
++++ chrome/browser/policy/policy_path_parser_win.cc
+@@ -12,6 +12,7 @@
+ 
+ #include "base/strings/utf_string_conversions.h"
+ #include "base/win/registry.h"
++#include "chrome/browser/policy/chrome_browser_policy_connector.h"
+ #include "chrome/common/chrome_switches.h"
+ #include "chrome/install_static/policy_path_parser.h"
+ #include "components/policy/policy_constants.h"
+@@ -22,9 +23,15 @@ namespace {
+ bool LoadUserDataDirPolicyFromRegistry(HKEY hive,
+                                        const char* key_name_str,
+                                        base::FilePath* dir) {
++  const std::wstring policy_key =
++      policy::ChromeBrowserPolicyConnector::GetPolicyKey();
++  if (policy_key.empty()) {
++    return false;
++  }
++
+   std::wstring value;
+   std::wstring key_name(base::ASCIIToWide(key_name_str));
+-  base::win::RegKey key(hive, policy::kRegistryChromePolicyKey, KEY_READ);
++  base::win::RegKey key(hive, policy_key.c_str(), KEY_READ);
+   if (key.ReadValue(key_name.c_str(), &value) == ERROR_SUCCESS) {
+     *dir = base::FilePath(policy::path_parser::ExpandPathVariables(value));
+     return true;
+diff --git chrome/common/chrome_paths.cc chrome/common/chrome_paths.cc
+index 9c8efc76fc3f1..5ae2ec3ff1fdd 100644
+--- chrome/common/chrome_paths.cc
++++ chrome/common/chrome_paths.cc
+@@ -516,7 +516,8 @@ bool PathProvider(int key, base::FilePath* result) {
+         return false;
+       }
+       break;
+-#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_OPENBSD)
++#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_OPENBSD) && \
++    !BUILDFLAG(ENABLE_CEF)
+     case chrome::DIR_POLICY_FILES: {
+       cur = base::FilePath(policy::kPolicyPath);
+       break;
+diff --git chrome/common/chrome_paths.h chrome/common/chrome_paths.h
+index ab0301b8eb26d..3ed179ccf84bf 100644
+--- chrome/common/chrome_paths.h
++++ chrome/common/chrome_paths.h
+@@ -8,6 +8,7 @@
+ #include "build/branding_buildflags.h"
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/features.h"
+ #include "third_party/widevine/cdm/buildflags.h"
+ 
+ namespace base {
+@@ -46,7 +47,7 @@ enum {
+   DIR_INTERNAL_PLUGINS,        // Directory where internal plugins reside.
+   DIR_COMPONENTS,              // Directory where built-in implementations of
+                                // component-updated libraries or data reside.
+-#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
++#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC) && !BUILDFLAG(ENABLE_CEF)
+   DIR_POLICY_FILES,  // Directory for system-wide read-only
+                      // policy files that allow sys-admins
+                      // to set policies for chrome. This directory
+diff --git components/policy/tools/generate_policy_source.py components/policy/tools/generate_policy_source.py
+index e9d31053cb2ea..793ceac3c7772 100755
+--- components/policy/tools/generate_policy_source.py
++++ components/policy/tools/generate_policy_source.py
+@@ -500,6 +500,7 @@ def _WritePolicyConstantHeader(all_policies, policy_atomic_groups,
+ #include <cstdint>
+ #include <string>
+ 
++#include "cef/libcef/features/features.h"
+ #include "components/policy/core/common/policy_details.h"
+ #include "components/policy/core/common/policy_map.h"
+ 
+@@ -522,9 +523,11 @@ struct SchemaData;
+ ''')
+ 
+   if target_platform == 'win':
+-    f.write('// The windows registry path where Chrome policy '
++    f.write('#if !BUILDFLAG(ENABLE_CEF)\n'
++            '// The windows registry path where Chrome policy '
+             'configuration resides.\n'
+-            'extern const wchar_t kRegistryChromePolicyKey[];\n')
++            'extern const wchar_t kRegistryChromePolicyKey[];\n'
++            '#endif\n')
+ 
+   f.write('''#if BUILDFLAG(IS_CHROMEOS)
+ // Sets default profile policies values for enterprise users.
+@@ -1167,12 +1170,14 @@ namespace policy {
+     f.write('}  // namespace\n\n')
+ 
+   if target_platform == 'win':
+-    f.write('#if BUILDFLAG(GOOGLE_CHROME_BRANDING)\n'
++    f.write('#if !BUILDFLAG(ENABLE_CEF)\n'
++            '#if BUILDFLAG(GOOGLE_CHROME_BRANDING)\n'
+             'const wchar_t kRegistryChromePolicyKey[] = '
+             'L"' + CHROME_POLICY_KEY + '";\n'
+             '#else\n'
+             'const wchar_t kRegistryChromePolicyKey[] = '
+             'L"' + CHROMIUM_POLICY_KEY + '";\n'
++            '#endif\n'
+             '#endif\n\n')
+ 
+   # Setting enterprise defaults code generation.
diff --git a/src/patch/patches/chrome_browser_privacy_1119417.patch b/src/patch/patches/chrome_browser_privacy_1119417.patch
new file mode 100644
index 0000000..48aea7d
--- /dev/null
+++ b/src/patch/patches/chrome_browser_privacy_1119417.patch
@@ -0,0 +1,59 @@
+diff --git chrome/browser/privacy/BUILD.gn chrome/browser/privacy/BUILD.gn
+index cd1f57e009f50..f93721e39e559 100644
+--- chrome/browser/privacy/BUILD.gn
++++ chrome/browser/privacy/BUILD.gn
+@@ -93,11 +93,15 @@ if (is_win || is_linux) {
+     ]
+     proto_deps = [ "//components/policy:full_runtime_code_generate" ]
+     proto_out_dir = "/chrome/browser/privacy"
++    generate_cc = false
++    generate_library = false
+   }
+ 
+   proto_library("traffic_annotation_proto") {
+     sources = [ "traffic_annotation.proto" ]
+     proto_deps = [ ":chrome_settings_full_runtime" ]
+     import_dirs = [ "$root_gen_dir" + "/components/policy/proto" ]
++    generate_cc = false
++    generate_library = false
+   }
+ }
+diff --git third_party/protobuf/proto_library.gni third_party/protobuf/proto_library.gni
+index a6943f5896cba..1561a868ccef9 100644
+--- third_party/protobuf/proto_library.gni
++++ third_party/protobuf/proto_library.gni
+@@ -28,6 +28,9 @@
+ #   generate_javascript (optional, default false)
+ #       Generate Javascript protobuf stubs.
+ #
++#   generate_library (optional, default true)
++#       Generate a "static_library" target for linking with the generated code.
++#
+ #   cc_generator_options (optional)
+ #       List of extra flags passed to the protocol compiler.  If you need to
+ #       add an EXPORT macro to a protobuf's C++ header, set the
+@@ -266,14 +269,21 @@ template("proto_library") {
+   protogens_cc = []
+   protogens_js = []
+ 
++  # Whether source code bindings should be generated.
++  generate_sources = generate_cc || generate_python || generate_with_plugin ||
++                     generate_javascript
++
+   # Whether library should be generated.
+   # Library is not needed when proto_library is used to generate binary descriptor, in which case
+   # corresponding library target should be omitted entirely.
+-  generate_library = generate_cc || generate_python || generate_with_plugin ||
+-                     generate_javascript
++  if (defined(invoker.generate_library)) {
++    generate_library = invoker.generate_library
++  } else {
++    generate_library = generate_sources
++  }
+ 
+   # List output files.
+-  if (generate_library) {
++  if (generate_sources) {
+     foreach(proto, protos) {
+       proto_dir = get_path_info(proto, "dir")
+       proto_name = get_path_info(proto, "name")
diff --git a/src/patch/patches/chrome_browser_product_override.patch b/src/patch/patches/chrome_browser_product_override.patch
deleted file mode 100644
index b5e728c..0000000
--- a/src/patch/patches/chrome_browser_product_override.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-diff --git chrome/browser/chrome_content_browser_client.cc chrome/browser/chrome_content_browser_client.cc
-index b5deda2a1739..cfa14167cc89 100644
---- chrome/browser/chrome_content_browser_client.cc
-+++ chrome/browser/chrome_content_browser_client.cc
-@@ -996,10 +996,6 @@ void LaunchURL(const GURL& url,
-   }
- }
- 
--std::string GetProduct() {
--  return version_info::GetProductNameAndVersionForUserAgent();
--}
--
- void MaybeAppendSecureOriginsAllowlistSwitch(base::CommandLine* cmdline) {
-   // |allowlist| combines pref/policy + cmdline switch in the browser process.
-   // For renderer and utility (e.g. NetworkService) processes the switch is the
-@@ -1094,6 +1090,14 @@ void MaybeRecordSameSiteCookieEngagementHistogram(
- 
- }  // namespace
- 
-+std::string GetProduct() {
-+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-+  if (command_line->HasSwitch(switches::kProductVersion))
-+    return command_line->GetSwitchValueASCII(switches::kProductVersion);
-+
-+  return version_info::GetProductNameAndVersionForUserAgent();
-+}
-+
- std::string GetUserAgent() {
-   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-   if (command_line->HasSwitch(switches::kUserAgent)) {
-diff --git chrome/browser/chrome_content_browser_client.h chrome/browser/chrome_content_browser_client.h
-index ae86be8afe0f..61be54670431 100644
---- chrome/browser/chrome_content_browser_client.h
-+++ chrome/browser/chrome_content_browser_client.h
-@@ -91,7 +91,8 @@ class ChromeXrIntegrationClient;
- }
- #endif
- 
--// Returns the user agent of Chrome.
-+// Returns the product and user agent of Chrome.
-+std::string GetProduct();
- std::string GetUserAgent();
- 
- blink::UserAgentMetadata GetUserAgentMetadata();
diff --git a/src/patch/patches/chrome_browser_profile_menu.patch b/src/patch/patches/chrome_browser_profile_menu.patch
new file mode 100644
index 0000000..93bdfbd
--- /dev/null
+++ b/src/patch/patches/chrome_browser_profile_menu.patch
@@ -0,0 +1,75 @@
+diff --git chrome/browser/ui/bookmarks/bookmark_stats.cc chrome/browser/ui/bookmarks/bookmark_stats.cc
+index 7ae18c5a960b0..d48ba838efe6f 100644
+--- chrome/browser/ui/bookmarks/bookmark_stats.cc
++++ chrome/browser/ui/bookmarks/bookmark_stats.cc
+@@ -21,7 +21,9 @@ bool IsBookmarkBarLocation(BookmarkLaunchLocation location) {
+ 
+ auto GetMetricProfile(const Profile* profile) {
+   DCHECK(profile);
+-  DCHECK(profile->IsRegularProfile() || profile->IsIncognitoProfile());
++  DCHECK(profile->IsRegularProfile() || profile->IsIncognitoProfile() ||
++         (profile->IsOffTheRecord() &&
++          profile->GetOTRProfileID().IsUniqueForCEF()));
+   return profile->IsRegularProfile()
+              ? profile_metrics::BrowserProfileType::kRegular
+              : profile_metrics::BrowserProfileType::kIncognito;
+diff --git chrome/browser/ui/views/incognito_clear_browsing_data_dialog.cc chrome/browser/ui/views/incognito_clear_browsing_data_dialog.cc
+index 9f1cb38d90303..986ac5ed9bdaf 100644
+--- chrome/browser/ui/views/incognito_clear_browsing_data_dialog.cc
++++ chrome/browser/ui/views/incognito_clear_browsing_data_dialog.cc
+@@ -31,7 +31,9 @@ IncognitoClearBrowsingDataDialog::IncognitoClearBrowsingDataDialog(
+       dialog_type_(type),
+       incognito_profile_(incognito_profile) {
+   DCHECK(incognito_profile_);
+-  DCHECK(incognito_profile_->IsIncognitoProfile());
++  DCHECK(incognito_profile_->IsIncognitoProfile() ||
++         (incognito_profile_->IsOffTheRecord() &&
++          incognito_profile_->GetOTRProfileID().IsUniqueForCEF()));
+   SetButtons(ui::DIALOG_BUTTON_NONE);
+   SetShowCloseButton(true);
+ 
+diff --git chrome/browser/ui/views/incognito_clear_browsing_data_dialog_coordinator.cc chrome/browser/ui/views/incognito_clear_browsing_data_dialog_coordinator.cc
+index caa20ec03434a..2a3ca921445c1 100644
+--- chrome/browser/ui/views/incognito_clear_browsing_data_dialog_coordinator.cc
++++ chrome/browser/ui/views/incognito_clear_browsing_data_dialog_coordinator.cc
+@@ -26,6 +26,10 @@ void IncognitoClearBrowsingDataDialogCoordinator::Show(
+           ->toolbar_button_provider()
+           ->GetAvatarToolbarButton();
+ 
++  // The full toolbar may not be visible.
++  if (!avatar_toolbar_button)
++    return;
++
+   auto bubble = std::make_unique<IncognitoClearBrowsingDataDialog>(
+       avatar_toolbar_button, GetBrowser().profile(), type);
+   DCHECK_EQ(nullptr, bubble_tracker_.view());
+diff --git chrome/browser/ui/views/profiles/incognito_menu_view.cc chrome/browser/ui/views/profiles/incognito_menu_view.cc
+index f5f266328283d..672609d94d1b7 100644
+--- chrome/browser/ui/views/profiles/incognito_menu_view.cc
++++ chrome/browser/ui/views/profiles/incognito_menu_view.cc
+@@ -36,7 +36,9 @@
+ IncognitoMenuView::IncognitoMenuView(views::Button* anchor_button,
+                                      Browser* browser)
+     : ProfileMenuViewBase(anchor_button, browser) {
+-  DCHECK(browser->profile()->IsIncognitoProfile());
++  DCHECK(browser->profile()->IsIncognitoProfile() ||
++         (browser->profile()->IsOffTheRecord() &&
++          browser->profile()->GetOTRProfileID().IsUniqueForCEF()));
+   GetViewAccessibility().OverrideName(GetAccessibleWindowTitle());
+ 
+   base::RecordAction(base::UserMetricsAction("IncognitoMenu_Show"));
+diff --git chrome/browser/ui/views/profiles/profile_menu_coordinator.cc chrome/browser/ui/views/profiles/profile_menu_coordinator.cc
+index 521991e8e47ff..76f00e99336ee 100644
+--- chrome/browser/ui/views/profiles/profile_menu_coordinator.cc
++++ chrome/browser/ui/views/profiles/profile_menu_coordinator.cc
+@@ -52,7 +52,9 @@ void ProfileMenuCoordinator::Show(bool is_source_accelerator) {
+   is_incognito &= !browser.profile()->IsGuestSession();
+ #endif
+ 
+-  if (is_incognito) {
++  if (is_incognito ||
++         (browser.profile()->IsOffTheRecord() &&
++          browser.profile()->GetOTRProfileID().IsUniqueForCEF())) {
+     bubble =
+         std::make_unique<IncognitoMenuView>(avatar_toolbar_button, &browser);
+   } else {
diff --git a/src/patch/patches/chrome_browser_profiles.patch b/src/patch/patches/chrome_browser_profiles.patch
index f35b93e..4b0285a 100644
--- a/src/patch/patches/chrome_browser_profiles.patch
+++ b/src/patch/patches/chrome_browser_profiles.patch
@@ -1,30 +1,130 @@
+diff --git chrome/browser/profiles/off_the_record_profile_impl.cc chrome/browser/profiles/off_the_record_profile_impl.cc
+index 48e30b2833a05..2d848247b9bce 100644
+--- chrome/browser/profiles/off_the_record_profile_impl.cc
++++ chrome/browser/profiles/off_the_record_profile_impl.cc
+@@ -652,7 +652,9 @@ std::unique_ptr<Profile> Profile::CreateOffTheRecordProfile(
+ #endif
+   if (!profile)
+     profile = std::make_unique<OffTheRecordProfileImpl>(parent, otr_profile_id);
+-  profile->Init();
++  // With CEF we want to delay initialization.
++  if (!otr_profile_id.IsUniqueForCEF())
++    profile->Init();
+   return std::move(profile);
+ }
+ 
+diff --git chrome/browser/profiles/profile.cc chrome/browser/profiles/profile.cc
+index 6cffe941b26f9..3e6223ab0d423 100644
+--- chrome/browser/profiles/profile.cc
++++ chrome/browser/profiles/profile.cc
+@@ -84,6 +84,7 @@ base::LazyInstance<std::set<content::BrowserContext*>>::Leaky
+ 
+ namespace {
+ 
++const char kCEFOTRProfileIDPrefix[] = "CEF::BrowserContext";
+ const char kDevToolsOTRProfileIDPrefix[] = "Devtools::BrowserContext";
+ const char kMediaRouterOTRProfileIDPrefix[] = "MediaRouter::Presentation";
+ const char kTestOTRProfileIDPrefix[] = "Test::OTR";
+@@ -104,6 +105,8 @@ bool Profile::OTRProfileID::AllowsBrowserWindows() const {
+   // DevTools::BrowserContext, MediaRouter::Presentation, and
+   // CaptivePortal::Signin are exceptions to this ban.
+   if (*this == PrimaryID() ||
++      base::StartsWith(profile_id_, kCEFOTRProfileIDPrefix,
++                       base::CompareCase::SENSITIVE) ||
+       base::StartsWith(profile_id_, kDevToolsOTRProfileIDPrefix,
+                        base::CompareCase::SENSITIVE) ||
+       base::StartsWith(profile_id_, kMediaRouterOTRProfileIDPrefix,
+@@ -141,6 +144,16 @@ Profile::OTRProfileID Profile::OTRProfileID::CreateUnique(
+       base::Uuid::GenerateRandomV4().AsLowercaseString().c_str()));
+ }
+ 
++// static
++Profile::OTRProfileID Profile::OTRProfileID::CreateUniqueForCEF() {
++  return CreateUnique(kCEFOTRProfileIDPrefix);
++}
++
++bool Profile::OTRProfileID::IsUniqueForCEF() const {
++  return base::StartsWith(profile_id_, kCEFOTRProfileIDPrefix,
++                          base::CompareCase::SENSITIVE);
++}
++
+ // static
+ Profile::OTRProfileID Profile::OTRProfileID::CreateUniqueForDevTools() {
+   return CreateUnique(kDevToolsOTRProfileIDPrefix);
+diff --git chrome/browser/profiles/profile.h chrome/browser/profiles/profile.h
+index ee1675aa1ecc9..cb526d1aba30d 100644
+--- chrome/browser/profiles/profile.h
++++ chrome/browser/profiles/profile.h
+@@ -104,6 +104,10 @@ class Profile : public content::BrowserContext {
+     // be applicable to run. Please see crbug.com/1098697#c3 for more details.
+     static OTRProfileID CreateUnique(const std::string& profile_id_prefix);
+ 
++    // Creates a unique OTR profile id to be used for CEF browser contexts.
++    static OTRProfileID CreateUniqueForCEF();
++    bool IsUniqueForCEF() const;
++
+     // Creates a unique OTR profile id to be used for DevTools browser contexts.
+     static OTRProfileID CreateUniqueForDevTools();
+ 
+@@ -528,6 +532,8 @@ class Profile : public content::BrowserContext {
+     return instant_service_;
+   }
+ 
++  void NotifyOffTheRecordProfileCreated(Profile* off_the_record);
++
+  protected:
+   // Creates an OffTheRecordProfile which points to this Profile.
+   static std::unique_ptr<Profile> CreateOffTheRecordProfile(
+@@ -539,7 +545,6 @@ class Profile : public content::BrowserContext {
+   static PrefStore* CreateExtensionPrefStore(Profile*,
+                                              bool incognito_pref_store);
+ 
+-  void NotifyOffTheRecordProfileCreated(Profile* off_the_record);
+   void NotifyProfileInitializationComplete();
+ 
+   // Returns whether the user has signed in this profile to an account.
+diff --git chrome/browser/profiles/profile_impl.cc chrome/browser/profiles/profile_impl.cc
+index 90859a99248a4..26fec83939559 100644
+--- chrome/browser/profiles/profile_impl.cc
++++ chrome/browser/profiles/profile_impl.cc
+@@ -1023,7 +1023,9 @@ Profile* ProfileImpl::GetOffTheRecordProfile(const OTRProfileID& otr_profile_id,
+ 
+   otr_profiles_[otr_profile_id] = std::move(otr_profile);
+ 
+-  NotifyOffTheRecordProfileCreated(raw_otr_profile);
++  // With CEF we want to delay initialization.
++  if (!otr_profile_id.IsUniqueForCEF())
++    NotifyOffTheRecordProfileCreated(raw_otr_profile);
+ 
+   return raw_otr_profile;
+ }
 diff --git chrome/browser/profiles/profile_manager.cc chrome/browser/profiles/profile_manager.cc
-index 7a7ba226f6dc..a5c8f844344e 100644
+index d403a5b78dfbf..85620c16dbf6e 100644
 --- chrome/browser/profiles/profile_manager.cc
 +++ chrome/browser/profiles/profile_manager.cc
-@@ -364,7 +364,7 @@ ProfileManager::ProfileManager(const base::FilePath& user_data_dir)
-   registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED,
-                  content::NotificationService::AllSources());
+@@ -435,7 +435,7 @@ ProfileManager::ProfileManager(const base::FilePath& user_data_dir)
+   profile_manager_android_ = std::make_unique<ProfileManagerAndroid>(this);
+ #endif
  
 -  if (ProfileShortcutManager::IsFeatureEnabled() && !user_data_dir_.empty())
 +  if (!user_data_dir_.empty() && ProfileShortcutManager::IsFeatureEnabled())
      profile_shortcut_manager_ = ProfileShortcutManager::Create(this);
- }
  
+   zombie_metrics_timer_.Start(FROM_HERE, base::Minutes(30), this,
 diff --git chrome/browser/profiles/profile_manager.h chrome/browser/profiles/profile_manager.h
-index 3e1e28ea7d0e..b70f718c8e94 100644
+index 5f471502c07a8..6a28e9452a359 100644
 --- chrome/browser/profiles/profile_manager.h
 +++ chrome/browser/profiles/profile_manager.h
-@@ -101,7 +101,7 @@ class ProfileManager : public content::NotificationObserver,
-   // acceptable. Returns null if creation of the new profile fails.
-   // TODO(bauerb): Migrate calls from other code to GetProfileByPath(), then
+@@ -134,7 +134,7 @@ class ProfileManager : public Profile::Delegate {
+   // acceptable. Returns nullptr if loading the new profile fails.
+   // TODO(bauerb): Migrate calls from other code to `GetProfileByPath()`, then
    // make this method private.
 -  Profile* GetProfile(const base::FilePath& profile_dir);
 +  virtual Profile* GetProfile(const base::FilePath& profile_dir);
  
-   // Returns total number of profiles available on this machine.
-   size_t GetNumberOfProfiles();
-@@ -131,7 +131,7 @@ class ProfileManager : public content::NotificationObserver,
+   // Returns regular or off-the-record profile given its profile key.
+   static Profile* GetProfileFromProfileKey(ProfileKey* profile_key);
+@@ -178,7 +178,7 @@ class ProfileManager : public Profile::Delegate {
  
    // Returns true if the profile pointer is known to point to an existing
    // profile.
@@ -33,37 +133,52 @@
  
    // Returns the directory where the first created profile is stored,
    // relative to the user data directory currently in use.
-@@ -140,7 +140,7 @@ class ProfileManager : public content::NotificationObserver,
-   // Get the Profile last used (the Profile to which owns the most recently
-   // focused window) with this Chrome build. If no signed profile has been
-   // stored in Local State, hand back the Default profile.
--  Profile* GetLastUsedProfile(const base::FilePath& user_data_dir);
-+  virtual Profile* GetLastUsedProfile(const base::FilePath& user_data_dir);
- 
-   // Get the path of the last used profile, or if that's undefined, the default
-   // profile.
 diff --git chrome/browser/profiles/renderer_updater.cc chrome/browser/profiles/renderer_updater.cc
-index c1792eccd997..6c34846b7947 100644
+index 421a3a60d308a..b89123a708f79 100644
 --- chrome/browser/profiles/renderer_updater.cc
 +++ chrome/browser/profiles/renderer_updater.cc
-@@ -7,6 +7,7 @@
- #include <utility>
- 
- #include "base/bind.h"
-+#include "cef/libcef/features/features.h"
+@@ -9,6 +9,7 @@
+ #include "base/functional/bind.h"
+ #include "base/functional/callback.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/content_settings/content_settings_manager_delegate.h"
  #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
  #include "chrome/browser/profiles/profile.h"
- #include "chrome/browser/signin/identity_manager_factory.h"
-@@ -62,8 +63,12 @@ void GetGuestViewDefaultContentSettingRules(
+@@ -46,11 +47,14 @@ RendererUpdater::RendererUpdater(Profile* profile)
+ #if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS)
+       ,
+       bound_session_cookie_refresh_service_(
++          cef::IsAlloyRuntimeEnabled() ? nullptr :
+           BoundSessionCookieRefreshServiceFactory::GetForProfile(profile))
+ #endif
+ {
++  if (!cef::IsAlloyRuntimeEnabled()) {
+   identity_manager_observation_.Observe(
+       IdentityManagerFactory::GetForProfile(original_profile_));
++  }
  
- RendererUpdater::RendererUpdater(Profile* profile)
-     : profile_(profile), identity_manager_observer_(this) {
-+#if !BUILDFLAG(ENABLE_CEF)
-   identity_manager_ = IdentityManagerFactory::GetForProfile(profile);
-   identity_manager_observer_.Add(identity_manager_);
-+#else
-+  identity_manager_ = nullptr;
-+#endif
- #if defined(OS_CHROMEOS)
+ #if BUILDFLAG(IS_CHROMEOS_ASH)
    oauth2_login_manager_ =
-       chromeos::OAuth2LoginManagerFactory::GetForProfile(profile_);
+diff --git chrome/browser/profiles/renderer_updater_factory.cc chrome/browser/profiles/renderer_updater_factory.cc
+index ed5b366aa47ab..58ebe795e4636 100644
+--- chrome/browser/profiles/renderer_updater_factory.cc
++++ chrome/browser/profiles/renderer_updater_factory.cc
+@@ -4,6 +4,7 @@
+ 
+ #include "chrome/browser/profiles/renderer_updater_factory.h"
+ 
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+ #include "chrome/browser/profiles/profile.h"
+ #include "chrome/browser/profiles/renderer_updater.h"
+@@ -25,7 +26,9 @@ RendererUpdaterFactory::RendererUpdaterFactory()
+   DependsOn(IdentityManagerFactory::GetInstance());
+   DependsOn(HostContentSettingsMapFactory::GetInstance());
+ #if BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS)
++  if (!cef::IsAlloyRuntimeEnabled()) {
+   DependsOn(BoundSessionCookieRefreshServiceFactory::GetInstance());
++  }
+ #endif  // BUILDFLAG(ENABLE_BOUND_SESSION_CREDENTIALS)
+ }
+ 
diff --git a/src/patch/patches/chrome_browser_safe_browsing.patch b/src/patch/patches/chrome_browser_safe_browsing.patch
index d8734e0..b2fb1ee 100644
--- a/src/patch/patches/chrome_browser_safe_browsing.patch
+++ b/src/patch/patches/chrome_browser_safe_browsing.patch
@@ -1,12 +1,12 @@
 diff --git chrome/browser/safe_browsing/BUILD.gn chrome/browser/safe_browsing/BUILD.gn
-index 14bef91c5370..cb1faba7c23e 100644
+index 19c1eac726602..b9528268d6a9a 100644
 --- chrome/browser/safe_browsing/BUILD.gn
 +++ chrome/browser/safe_browsing/BUILD.gn
-@@ -246,6 +246,7 @@ jumbo_static_library("safe_browsing") {
-         "//chrome/common/safe_browsing:download_type_util",
-         "//chrome/services/file_util/public/cpp",
-         "//components/content_settings/core/browser",
-+        "//components/gcm_driver:gcm_buildflags",
-         "//components/language/core/common",
-         "//components/prefs",
-         "//components/safe_browsing/core:webprotect_proto",
+@@ -32,6 +32,7 @@ static_library("safe_browsing") {
+     "//components/browser_sync",
+     "//components/enterprise:enterprise",
+     "//components/enterprise/common:strings",
++    "//components/gcm_driver:gcm_buildflags",
+     "//components/keyed_service/content",
+     "//components/language/core/browser",
+     "//components/no_state_prefetch/browser",
diff --git a/src/patch/patches/chrome_browser_themes.patch b/src/patch/patches/chrome_browser_themes.patch
index ffb61d5..ecbf7f5 100644
--- a/src/patch/patches/chrome_browser_themes.patch
+++ b/src/patch/patches/chrome_browser_themes.patch
@@ -1,37 +1,82 @@
-diff --git chrome/browser/themes/theme_service_factory.cc chrome/browser/themes/theme_service_factory.cc
-index 5a0d5e736cb9..f1c9da3f73b1 100644
---- chrome/browser/themes/theme_service_factory.cc
-+++ chrome/browser/themes/theme_service_factory.cc
-@@ -7,6 +7,7 @@
- #include "base/logging.h"
- #include "base/no_destructor.h"
+diff --git chrome/browser/themes/theme_service.cc chrome/browser/themes/theme_service.cc
+index d0e1d573c1fca..65ab5fc0a6388 100644
+--- chrome/browser/themes/theme_service.cc
++++ chrome/browser/themes/theme_service.cc
+@@ -29,6 +29,7 @@
+ #include "base/task/thread_pool.h"
+ #include "base/trace_event/trace_event.h"
  #include "build/build_config.h"
-+#include "cef/libcef/features/features.h"
- #include "chrome/browser/extensions/extension_system_factory.h"
- #include "chrome/browser/profiles/incognito_helpers.h"
- #include "chrome/browser/profiles/profile.h"
-@@ -42,6 +43,10 @@ const ThemeHelper& GetThemeHelper() {
- 
- }  // namespace
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/browser_features.h"
+ #include "chrome/browser/extensions/extension_service.h"
+ #include "chrome/browser/extensions/theme_installed_infobar_delegate.h"
+@@ -70,6 +71,10 @@
+ #include "ui/color/color_provider_manager.h"
+ #include "ui/native_theme/native_theme.h"
  
 +#if BUILDFLAG(ENABLE_CEF)
 +#include "cef/libcef/common/extensions/extensions_util.h"
 +#endif
 +
- // static
- ThemeService* ThemeServiceFactory::GetForProfile(Profile* profile) {
-   return static_cast<ThemeService*>(
-@@ -71,7 +76,13 @@ ThemeServiceFactory::ThemeServiceFactory()
-           BrowserContextDependencyManager::GetInstance()) {
+ #if BUILDFLAG(ENABLE_EXTENSIONS)
+ #include "base/scoped_observation.h"
+ #include "extensions/browser/extension_registry_observer.h"
+@@ -271,11 +276,19 @@ void ThemeService::Init() {
+   // OnExtensionServiceReady. Otherwise, the ThemeObserver won't be
+   // constructed in time to observe the corresponding events.
+ #if BUILDFLAG(ENABLE_EXTENSIONS)
++#if BUILDFLAG(ENABLE_CEF)
++  const bool extensions_disabled = cef::IsAlloyRuntimeEnabled() &&
++                                   !extensions::ExtensionsEnabled();
++#else
++  const bool extensions_disabled = false;
++#endif
++  if (!extensions_disabled) {
+   theme_observer_ = std::make_unique<ThemeObserver>(this);
+ 
+   extensions::ExtensionSystem::Get(profile_)->ready().Post(
+       FROM_HERE, base::BindOnce(&ThemeService::OnExtensionServiceReady,
+                                 weak_ptr_factory_.GetWeakPtr()));
++  }
+ #endif
+   theme_syncable_service_ =
+       std::make_unique<ThemeSyncableService>(profile_, this);
+diff --git chrome/browser/themes/theme_service_factory.cc chrome/browser/themes/theme_service_factory.cc
+index 879bbeef4037b..e6cc36f388197 100644
+--- chrome/browser/themes/theme_service_factory.cc
++++ chrome/browser/themes/theme_service_factory.cc
+@@ -9,6 +9,7 @@
+ #include "base/trace_event/trace_event.h"
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/extensions/extension_system_factory.h"
+ #include "chrome/browser/profiles/profile.h"
+ #include "chrome/browser/themes/theme_service.h"
+@@ -35,6 +36,10 @@
+ #include "ui/linux/linux_ui_factory.h"
+ #endif
+ 
++#if BUILDFLAG(ENABLE_CEF)
++#include "cef/libcef/common/extensions/extensions_util.h"
++#endif
++
+ namespace {
+ 
+ const ThemeHelper& GetThemeHelper() {
+@@ -96,7 +101,15 @@ ThemeServiceFactory::ThemeServiceFactory()
+               .Build()) {
    DependsOn(extensions::ExtensionRegistryFactory::GetInstance());
    DependsOn(extensions::ExtensionPrefsFactory::GetInstance());
 +#if BUILDFLAG(ENABLE_CEF)
-+  if (extensions::ExtensionsEnabled()) {
++  const bool extensions_disabled = cef::IsAlloyRuntimeEnabled() &&
++                                   !extensions::ExtensionsEnabled();
++#else
++  const bool extensions_disabled = false;
 +#endif
++  if (!extensions_disabled) {
    DependsOn(extensions::ExtensionSystemFactory::GetInstance());
-+#if BUILDFLAG(ENABLE_CEF)
 +  }
-+#endif
  }
  
- ThemeServiceFactory::~ThemeServiceFactory() {}
+ ThemeServiceFactory::~ThemeServiceFactory() = default;
diff --git a/src/patch/patches/chrome_plugins.patch b/src/patch/patches/chrome_plugins.patch
index d930baf..e507b96 100644
--- a/src/patch/patches/chrome_plugins.patch
+++ b/src/patch/patches/chrome_plugins.patch
@@ -1,214 +1,59 @@
 diff --git chrome/browser/plugins/plugin_info_host_impl.cc chrome/browser/plugins/plugin_info_host_impl.cc
-index d49a1df73622..9a389e4383f0 100644
+index 95cd290b601a3..89e8ab892e5ea 100644
 --- chrome/browser/plugins/plugin_info_host_impl.cc
 +++ chrome/browser/plugins/plugin_info_host_impl.cc
-@@ -18,6 +18,7 @@
- #include "base/task_runner_util.h"
- #include "build/branding_buildflags.h"
- #include "build/build_config.h"
-+#include "cef/libcef/features/features.h"
- #include "chrome/browser/browser_process.h"
- #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
- #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
-@@ -54,6 +55,11 @@
- #include "url/gurl.h"
- #include "url/origin.h"
- 
-+#if BUILDFLAG(ENABLE_CEF)
-+#include "cef/libcef/browser/plugins/plugin_service_filter.h"
-+#include "cef/libcef/common/extensions/extensions_util.h"
-+#endif
-+
- #if BUILDFLAG(ENABLE_EXTENSIONS)
- #include "components/guest_view/browser/guest_view_base.h"
- #include "extensions/browser/extension_registry.h"
-@@ -100,6 +106,9 @@ bool IsPluginLoadingAccessibleResourceInWebView(
+@@ -140,6 +140,10 @@ bool IsPluginLoadingAccessibleResourceInWebView(
      extensions::ExtensionRegistry* extension_registry,
      int process_id,
      const GURL& resource) {
++  // May be nullptr if using CEF Alloy with extensions disabled.
 +  if (!extension_registry)
 +    return false;
 +
    extensions::WebViewRendererState* renderer_state =
        extensions::WebViewRendererState::GetInstance();
    std::string partition_id;
-@@ -128,9 +137,6 @@ bool IsPluginLoadingAccessibleResourceInWebView(
- 
- PluginInfoHostImpl::Context::Context(int render_process_id, Profile* profile)
-     : render_process_id_(render_process_id),
--#if BUILDFLAG(ENABLE_EXTENSIONS)
--      extension_registry_(extensions::ExtensionRegistry::Get(profile)),
--#endif
-       host_content_settings_map_(
-           HostContentSettingsMapFactory::GetForProfile(profile)),
-       plugin_prefs_(PluginPrefs::GetForProfile(profile)) {
-@@ -138,6 +144,13 @@ PluginInfoHostImpl::Context::Context(int render_process_id, Profile* profile)
-                                profile->GetPrefs());
-   run_all_flash_in_allow_mode_.Init(prefs::kRunAllFlashInAllowMode,
-                                     profile->GetPrefs());
-+
-+#if BUILDFLAG(ENABLE_EXTENSIONS)
-+#if BUILDFLAG(ENABLE_CEF)
-+  if (extensions::ExtensionsEnabled())
-+#endif
-+    extension_registry_ = extensions::ExtensionRegistry::Get(profile);
-+#endif
- }
- 
- PluginInfoHostImpl::Context::~Context() {}
-@@ -208,6 +221,7 @@ void PluginInfoHostImpl::PluginsLoaded(
-         plugin_metadata->identifier(), &output->status);
-   }
- 
-+#if !BUILDFLAG(ENABLE_CEF)
-   if (output->status == chrome::mojom::PluginStatus::kNotFound) {
-     // Check to see if the component updater can fetch an implementation.
-     std::unique_ptr<component_updater::ComponentInfo> cus_plugin_info =
-@@ -216,7 +230,9 @@ void PluginInfoHostImpl::PluginsLoaded(
-     ComponentPluginLookupDone(params, std::move(output), std::move(callback),
-                               std::move(plugin_metadata),
-                               std::move(cus_plugin_info));
--  } else {
-+  } else
-+#endif  // !BUILDFLAG(ENABLE_CEF)
-+  {
-     GetPluginInfoFinish(params, std::move(output), std::move(callback),
-                         std::move(plugin_metadata));
-   }
-@@ -229,6 +245,14 @@ void PluginInfoHostImpl::Context::DecidePluginStatus(
-     PluginMetadata::SecurityStatus security_status,
-     const std::string& plugin_identifier,
-     chrome::mojom::PluginStatus* status) const {
-+#if BUILDFLAG(ENABLE_CEF)
-+  // Don't override the user decision.
-+  if (*status == chrome::mojom::PluginStatus::kBlocked ||
-+      *status == chrome::mojom::PluginStatus::kDisabled) {
-+    return;
-+  }
-+#endif
-+
-   if (security_status == PluginMetadata::SECURITY_STATUS_FULLY_TRUSTED) {
-     *status = chrome::mojom::PluginStatus::kAllowed;
-     return;
-@@ -337,16 +361,35 @@ bool PluginInfoHostImpl::Context::FindEnabledPlugin(
-     return false;
-   }
- 
-+  const bool is_main_frame =
-+      main_frame_origin.IsSameOriginWith(url::Origin::Create(url));
-+
-+#if BUILDFLAG(ENABLE_CEF)
-+  CefPluginServiceFilter* filter = static_cast<CefPluginServiceFilter*>(
-+      PluginService::GetInstance()->GetFilter());
-+  DCHECK(filter);
-+
-+  size_t i = 0;
-+  for (; i < matching_plugins.size(); ++i) {
-+    if (filter->IsPluginAvailable(render_process_id_, render_frame_id,
-+                                  url, is_main_frame, main_frame_origin,
-+                                  &matching_plugins[i], status)) {
-+      break;
-+    }
-+  }
-+#else  // !BUILDFLAG(ENABLE_CEF)
-   content::PluginServiceFilter* filter =
-       PluginService::GetInstance()->GetFilter();
-   size_t i = 0;
-   for (; i < matching_plugins.size(); ++i) {
-     if (!filter ||
-         filter->IsPluginAvailable(render_process_id_, render_frame_id, url,
--                                  main_frame_origin, &matching_plugins[i])) {
-+                                  is_main_frame, main_frame_origin,
-+                                  &matching_plugins[i])) {
-       break;
-     }
-   }
-+#endif  // !BUILDFLAG(ENABLE_CEF)
- 
-   // If we broke out of the loop, we have found an enabled plugin.
-   bool enabled = i < matching_plugins.size();
 diff --git chrome/browser/plugins/plugin_utils.cc chrome/browser/plugins/plugin_utils.cc
-index 4e64db143b8a..71322b0261a1 100644
+index 438276b719c2f..69635e429be78 100644
 --- chrome/browser/plugins/plugin_utils.cc
 +++ chrome/browser/plugins/plugin_utils.cc
-@@ -5,6 +5,7 @@
- #include "chrome/browser/plugins/plugin_utils.h"
- 
- #include "base/values.h"
-+#include "cef/libcef/features/features.h"
- #include "chrome/browser/profiles/profile_io_data.h"
- #include "chrome/common/plugin_utils.h"
- #include "components/content_settings/core/browser/host_content_settings_map.h"
-@@ -14,6 +15,11 @@
- #include "url/gurl.h"
- #include "url/origin.h"
- 
-+#if BUILDFLAG(ENABLE_CEF)
-+#include "cef/libcef/browser/resource_context.h"
-+#include "cef/libcef/common/extensions/extensions_util.h"
-+#endif
-+
- #if BUILDFLAG(ENABLE_EXTENSIONS)
- #include "chrome/common/pref_names.h"
- #include "components/prefs/pref_service.h"
-@@ -182,6 +188,12 @@ base::flat_map<std::string, std::string>
- PluginUtils::GetMimeTypeToExtensionIdMap(
+@@ -68,6 +68,13 @@ PluginUtils::GetMimeTypeToExtensionIdMap(
      content::BrowserContext* browser_context) {
    base::flat_map<std::string, std::string> mime_type_to_extension_id_map;
-+
-+#if BUILDFLAG(ENABLE_CEF)
-+  if (!extensions::ExtensionsEnabled())
+ #if BUILDFLAG(ENABLE_EXTENSIONS)
++  // May be nullptr if using CEF Alloy with extensions disabled.
++  extensions::ExtensionRegistry* registry =
++      extensions::ExtensionRegistry::Get(browser_context);
++  if (!registry) {
 +    return mime_type_to_extension_id_map;
-+#endif
++  }
 +
- #if BUILDFLAG(ENABLE_EXTENSIONS)
    Profile* profile = Profile::FromBrowserContext(browser_context);
-   std::vector<std::string> whitelist = MimeTypesHandler::GetMIMETypeWhitelist();
-diff --git chrome/common/google_url_loader_throttle.cc chrome/common/google_url_loader_throttle.cc
-index bcb97138c321..df6792bd5317 100644
---- chrome/common/google_url_loader_throttle.cc
-+++ chrome/common/google_url_loader_throttle.cc
-@@ -5,10 +5,15 @@
- #include "chrome/common/google_url_loader_throttle.h"
- 
- #include "build/build_config.h"
-+#include "cef/libcef/features/features.h"
- #include "chrome/common/net/safe_search_util.h"
- #include "components/google/core/common/google_util.h"
- #include "services/network/public/mojom/url_response_head.mojom.h"
- 
-+#if BUILDFLAG(ENABLE_CEF)
-+#include "cef/libcef/common/extensions/extensions_util.h"
-+#endif
-+
- #if BUILDFLAG(ENABLE_EXTENSIONS)
- #include "extensions/common/extension_urls.h"
- #endif
-@@ -116,6 +121,11 @@ void GoogleURLLoaderThrottle::WillProcessResponse(
-     const GURL& response_url,
-     network::mojom::URLResponseHead* response_head,
-     bool* defer) {
-+#if BUILDFLAG(ENABLE_CEF)
-+  if (!extensions::ExtensionsEnabled())
-+    return;
-+#endif
-+
-   // Built-in additional protection for the chrome web store origin.
-   GURL webstore_url(extension_urls::GetWebstoreLaunchURL());
-   if (response_url.SchemeIsHTTPOrHTTPS() &&
+   if (extensions::ChromeContentBrowserClientExtensionsPart::
+           AreExtensionsDisabledForProfile(profile)) {
+@@ -78,9 +85,6 @@ PluginUtils::GetMimeTypeToExtensionIdMap(
+       MimeTypesHandler::GetMIMETypeAllowlist();
+   // Go through the allowed extensions and try to use them to intercept
+   // the URL request.
+-  extensions::ExtensionRegistry* registry =
+-      extensions::ExtensionRegistry::Get(browser_context);
+-  DCHECK(registry);
+   for (const std::string& extension_id : allowlist) {
+     const extensions::Extension* extension =
+         registry->enabled_extensions().GetByID(extension_id);
 diff --git chrome/renderer/chrome_content_renderer_client.cc chrome/renderer/chrome_content_renderer_client.cc
-index b96048aec4f7..edaa78c59fe8 100644
+index 8ef09f60649bb..8a4eb86233f67 100644
 --- chrome/renderer/chrome_content_renderer_client.cc
 +++ chrome/renderer/chrome_content_renderer_client.cc
-@@ -813,6 +813,7 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin(
+@@ -982,6 +982,7 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin(
  
      if ((status == chrome::mojom::PluginStatus::kUnauthorized ||
           status == chrome::mojom::PluginStatus::kBlocked) &&
-+        content_settings_agent &&
-         content_settings_agent->IsPluginTemporarilyAllowed(identifier)) {
++        content_settings_agent_delegate &&
+         content_settings_agent_delegate->IsPluginTemporarilyAllowed(
+             identifier)) {
        status = chrome::mojom::PluginStatus::kAllowed;
-     }
-@@ -1015,7 +1016,8 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin(
+@@ -1144,7 +1145,8 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin(
          render_frame->GetRemoteAssociatedInterfaces()->GetInterface(
              plugin_auth_host.BindNewEndpointAndPassReceiver());
          plugin_auth_host->BlockedUnauthorizedPlugin(group_name, identifier);
@@ -218,7 +63,7 @@
          break;
        }
        case chrome::mojom::PluginStatus::kBlocked: {
-@@ -1024,7 +1026,8 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin(
+@@ -1153,7 +1155,8 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin(
              l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name));
          placeholder->AllowLoading();
          RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Blocked"));
@@ -228,7 +73,7 @@
          break;
        }
        case chrome::mojom::PluginStatus::kBlockedByPolicy: {
-@@ -1034,7 +1037,8 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin(
+@@ -1163,7 +1166,8 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin(
                                         group_name));
          RenderThread::Get()->RecordAction(
              UserMetricsAction("Plugin_BlockedByPolicy"));
@@ -237,32 +82,60 @@
 +          content_settings_agent->DidBlockContentType(content_type);
          break;
        }
-       case chrome::mojom::PluginStatus::kBlockedNoLoading: {
-@@ -1042,7 +1046,8 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin(
-             IDR_BLOCKED_PLUGIN_HTML,
-             l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED_NO_LOADING,
-                                        group_name));
--        content_settings_agent->DidBlockContentType(content_type);
-+        if (content_settings_agent)
-+          content_settings_agent->DidBlockContentType(content_type);
-         break;
-       }
-       case chrome::mojom::PluginStatus::kComponentUpdateRequired: {
-diff --git chrome/renderer/plugins/chrome_plugin_placeholder.cc chrome/renderer/plugins/chrome_plugin_placeholder.cc
-index 8a7d7402a48c..4dde943d0222 100644
---- chrome/renderer/plugins/chrome_plugin_placeholder.cc
-+++ chrome/renderer/plugins/chrome_plugin_placeholder.cc
-@@ -359,8 +359,11 @@ void ChromePluginPlaceholder::OnBlockedContent(
+     }
+diff --git content/browser/browser_plugin/browser_plugin_embedder.h content/browser/browser_plugin/browser_plugin_embedder.h
+index ad5f1925735fd..a871f4a7792a7 100644
+--- content/browser/browser_plugin/browser_plugin_embedder.h
++++ content/browser/browser_plugin/browser_plugin_embedder.h
+@@ -15,6 +15,7 @@
+ #define CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_EMBEDDER_H_
  
-   if (status ==
-       content::RenderFrame::PeripheralContentStatus::CONTENT_STATUS_TINY) {
--    ContentSettingsAgentImpl::Get(render_frame())
--        ->DidBlockContentType(ContentSettingsType::PLUGINS);
-+      ContentSettingsAgentImpl *content_settings_agent =
-+          ContentSettingsAgentImpl::Get(render_frame());
-+      if (content_settings_agent) {
-+        content_settings_agent->DidBlockContentType(ContentSettingsType::PLUGINS);
-+      }
-   }
+ #include "base/memory/raw_ptr.h"
++#include "content/common/content_export.h"
  
-   std::string message = base::StringPrintf(
+ namespace content {
+ 
+@@ -26,7 +27,7 @@ struct NativeWebKeyboardEvent;
+ 
+ // TODO(wjmaclean): Get rid of "BrowserPlugin" in the name of this class.
+ // Perhaps "WebContentsEmbedderDelegate" would be better?
+-class BrowserPluginEmbedder {
++class CONTENT_EXPORT BrowserPluginEmbedder {
+  public:
+   BrowserPluginEmbedder(const BrowserPluginEmbedder&) = delete;
+   BrowserPluginEmbedder& operator=(const BrowserPluginEmbedder&) = delete;
+diff --git content/browser/browser_plugin/browser_plugin_guest.cc content/browser/browser_plugin/browser_plugin_guest.cc
+index f94fcfcf562db..066c66f46b7ae 100644
+--- content/browser/browser_plugin/browser_plugin_guest.cc
++++ content/browser/browser_plugin/browser_plugin_guest.cc
+@@ -49,6 +49,8 @@ std::unique_ptr<WebContentsImpl> BrowserPluginGuest::CreateNewGuestWindow(
+ }
+ 
+ void BrowserPluginGuest::InitInternal(WebContentsImpl* owner_web_contents) {
++  owner_web_contents_ = owner_web_contents;
++
+   RenderWidgetHostImpl* rwhi =
+       GetWebContents()->GetPrimaryMainFrame()->GetRenderWidgetHost();
+   DCHECK(rwhi);
+diff --git content/browser/browser_plugin/browser_plugin_guest.h content/browser/browser_plugin/browser_plugin_guest.h
+index 7f3083029d45e..94a5cbed96a10 100644
+--- content/browser/browser_plugin/browser_plugin_guest.h
++++ content/browser/browser_plugin/browser_plugin_guest.h
+@@ -70,6 +70,8 @@ class BrowserPluginGuest : public WebContentsObserver {
+   WebContentsImpl* GetWebContents() const;
+   RenderFrameHostImpl* GetProspectiveOuterDocument();
+ 
++  WebContentsImpl* owner_web_contents() const { return owner_web_contents_; }
++
+  private:
+   // BrowserPluginGuest is a WebContentsObserver of |web_contents| and
+   // |web_contents| has to stay valid for the lifetime of BrowserPluginGuest.
+@@ -80,6 +82,8 @@ class BrowserPluginGuest : public WebContentsObserver {
+ 
+   // May be null during guest destruction.
+   const base::WeakPtr<BrowserPluginGuestDelegate> delegate_;
++
++  raw_ptr<WebContentsImpl> owner_web_contents_ = nullptr;
+ };
+ 
+ }  // namespace content
diff --git a/src/patch/patches/chrome_pref_watcher.patch b/src/patch/patches/chrome_pref_watcher.patch
index 743c1d9..5a77695 100644
--- a/src/patch/patches/chrome_pref_watcher.patch
+++ b/src/patch/patches/chrome_pref_watcher.patch
@@ -1,8 +1,8 @@
 diff --git chrome/browser/ui/prefs/pref_watcher.h chrome/browser/ui/prefs/pref_watcher.h
-index a439b2ce1b32..21c7b97639f4 100644
+index 81ccdbf504726..80f44f4a87881 100644
 --- chrome/browser/ui/prefs/pref_watcher.h
 +++ chrome/browser/ui/prefs/pref_watcher.h
-@@ -29,10 +29,10 @@ class PrefWatcher : public KeyedService {
+@@ -33,10 +33,10 @@ class PrefWatcher : public KeyedService,
    void RegisterRendererPreferenceWatcher(
        mojo::PendingRemote<blink::mojom::RendererPreferenceWatcher> watcher);
  
@@ -11,6 +11,6 @@
    void Shutdown() override;
  
 + private:
+   void OnDoNotTrackEnabledChanged() override;
+ 
    void UpdateRendererPreferences();
-   void OnWebPrefChanged(const std::string& pref_name);
-   void OnLiveCaptionEnabledPrefChanged(const std::string& pref_name);
diff --git a/src/patch/patches/chrome_renderer.patch b/src/patch/patches/chrome_renderer.patch
index ebeb2e6..1518c31 100644
--- a/src/patch/patches/chrome_renderer.patch
+++ b/src/patch/patches/chrome_renderer.patch
@@ -1,24 +1,24 @@
 diff --git chrome/renderer/BUILD.gn chrome/renderer/BUILD.gn
-index 88cbad65b714..2d899f1805e2 100644
+index 18b342e66f11a..765b0634327d1 100644
 --- chrome/renderer/BUILD.gn
 +++ chrome/renderer/BUILD.gn
 @@ -5,6 +5,7 @@
  import("//build/config/buildflags_paint_preview.gni")
+ import("//build/config/chromeos/ui_mode.gni")
  import("//build/config/features.gni")
- import("//build/config/jumbo.gni")
 +import("//cef/libcef/features/features.gni")
  import("//chrome/common/features.gni")
  import("//components/nacl/features.gni")
  import("//components/offline_pages/buildflags/features.gni")
-@@ -129,6 +130,7 @@ jumbo_static_library("renderer") {
-   defines = []
- 
+@@ -136,6 +137,7 @@ static_library("renderer") {
    deps = [
+     "//base/allocator:buildflags",
+     "//build:chromeos_buildflags",
 +    "//cef/libcef/features",
      "//chrome:resources",
      "//chrome:strings",
      "//chrome/common",
-@@ -193,6 +195,10 @@ jumbo_static_library("renderer") {
+@@ -238,6 +240,10 @@ static_library("renderer") {
  
    configs += [ "//build/config/compiler:wexit_time_destructors" ]
  
@@ -27,5 +27,5 @@
 +  }
 +
    if (enable_nacl) {
-     deps += [
-       "//components/nacl/loader",
+     deps += [ "//components/nacl/renderer" ]
+ 
diff --git a/src/patch/patches/chrome_runtime.patch b/src/patch/patches/chrome_runtime.patch
new file mode 100644
index 0000000..cc1685f
--- /dev/null
+++ b/src/patch/patches/chrome_runtime.patch
@@ -0,0 +1,406 @@
+diff --git chrome/app/chrome_main_delegate.cc chrome/app/chrome_main_delegate.cc
+index 4c150b5cb007d..51e5c89714978 100644
+--- chrome/app/chrome_main_delegate.cc
++++ chrome/app/chrome_main_delegate.cc
+@@ -41,6 +41,7 @@
+ #include "base/trace_event/trace_event_impl.h"
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/buildflags.h"
+ #include "chrome/browser/chrome_content_browser_client.h"
+ #include "chrome/browser/chrome_resource_bundle_helper.h"
+@@ -569,6 +570,8 @@ struct MainFunction {
+ 
+ // Initializes the user data dir. Must be called before InitializeLocalState().
+ void InitializeUserDataDir(base::CommandLine* command_line) {
++  if (cef::IsChromeRuntimeEnabled())
++    return;
+ #if BUILDFLAG(IS_WIN)
+   // Reach out to chrome_elf for the truth on the user data directory.
+   // Note that in tests, this links to chrome_elf_test_stubs.
+@@ -741,6 +744,10 @@ ChromeMainDelegate::~ChromeMainDelegate() {
+ ChromeMainDelegate::~ChromeMainDelegate() = default;
+ #endif  // !BUILDFLAG(IS_ANDROID)
+ 
++void ChromeMainDelegate::CleanupOnUIThread() {
++  memory_system_.reset();
++}
++
+ absl::optional<int> ChromeMainDelegate::PostEarlyInitialization(
+     InvokedIn invoked_in) {
+   DCHECK(base::ThreadPoolInstance::Get());
+@@ -914,7 +921,8 @@ absl::optional<int> ChromeMainDelegate::PostEarlyInitialization(
+ 
+   if (base::FeatureList::IsEnabled(
+           features::kWriteBasicSystemProfileToPersistentHistogramsFile)) {
+-    bool record = true;
++    // Avoid CEF crash with multi-threaded-message-loop.
++    bool record = !cef::IsChromeRuntimeEnabled();
+ #if BUILDFLAG(IS_ANDROID)
+     record =
+         base::FeatureList::IsEnabled(chrome::android::kUmaBackgroundSessions);
+@@ -1358,6 +1366,7 @@ void ChromeMainDelegate::PreSandboxStartup() {
+   std::string process_type =
+       command_line.GetSwitchValueASCII(switches::kProcessType);
+ 
++  if (!cef::IsChromeRuntimeEnabled()) {
+   crash_reporter::InitializeCrashKeys();
+ 
+ #if BUILDFLAG(IS_CHROMEOS_LACROS)
+@@ -1385,6 +1394,7 @@ void ChromeMainDelegate::PreSandboxStartup() {
+   InitMacCrashReporter(command_line, process_type);
+   SetUpInstallerPreferences(command_line);
+ #endif
++  }  // !cef::IsChromeRuntimeEnabled()
+ 
+ #if BUILDFLAG(IS_WIN)
+   child_process_logging::Init();
+@@ -1589,6 +1599,7 @@ void ChromeMainDelegate::PreSandboxStartup() {
+     CHECK(!loaded_locale.empty()) << "Locale could not be found for " << locale;
+   }
+ 
++  if (!cef::IsChromeRuntimeEnabled()) {
+ #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+   // Zygote needs to call InitCrashReporter() in RunZygote().
+   if (process_type != switches::kZygoteProcess) {
+@@ -1632,6 +1643,7 @@ void ChromeMainDelegate::PreSandboxStartup() {
+   // After all the platform Breakpads have been initialized, store the command
+   // line for crash reporting.
+   crash_keys::SetCrashKeysFromCommandLine(command_line);
++  }  // !cef::IsChromeRuntimeEnabled()
+ 
+ #if BUILDFLAG(ENABLE_PDF)
+   MaybePatchGdiGetFontData();
+@@ -1750,6 +1762,7 @@ void ChromeMainDelegate::ZygoteForked() {
+     SetUpProfilingShutdownHandler();
+   }
+ 
++  if (!cef::IsChromeRuntimeEnabled()) {
+   // Needs to be called after we have chrome::DIR_USER_DATA.  BrowserMain sets
+   // this up for the browser process in a different manner.
+   const base::CommandLine* command_line =
+@@ -1772,6 +1785,7 @@ void ChromeMainDelegate::ZygoteForked() {
+ 
+   // Reset the command line for the newly spawned process.
+   crash_keys::SetCrashKeysFromCommandLine(*command_line);
++  }  // !cef::IsChromeRuntimeEnabled()
+ }
+ 
+ #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+@@ -1872,6 +1886,7 @@ void ChromeMainDelegate::InitializeMemorySystem() {
+                               channel == version_info::Channel::DEV);
+   const bool gwp_asan_boost_sampling = is_canary_dev || is_browser_process;
+ 
++  memory_system_ = std::make_unique<memory_system::MemorySystem>();
+   memory_system::Initializer()
+       .SetGwpAsanParameters(gwp_asan_boost_sampling, process_type)
+       .SetProfilingClientParameters(channel,
+@@ -1881,5 +1896,5 @@ void ChromeMainDelegate::InitializeMemorySystem() {
+                                memory_system::DispatcherParameters::
+                                    AllocationTraceRecorderInclusion::kDynamic,
+                                process_type)
+-      .Initialize(memory_system_);
++      .Initialize(*memory_system_);
+ }
+diff --git chrome/app/chrome_main_delegate.h chrome/app/chrome_main_delegate.h
+index 176b6248f18e8..1360e8c209eba 100644
+--- chrome/app/chrome_main_delegate.h
++++ chrome/app/chrome_main_delegate.h
+@@ -49,6 +49,8 @@ class ChromeMainDelegate : public content::ContentMainDelegate {
+ 
+   ~ChromeMainDelegate() override;
+ 
++  virtual void CleanupOnUIThread();
++
+  protected:
+   // content::ContentMainDelegate:
+   absl::optional<int> BasicStartupComplete() override;
+@@ -98,7 +100,7 @@ class ChromeMainDelegate : public content::ContentMainDelegate {
+ 
+   ChromeContentClient chrome_content_client_;
+ 
+-  memory_system::MemorySystem memory_system_;
++  std::unique_ptr<memory_system::MemorySystem> memory_system_;
+ 
+ #if BUILDFLAG(IS_CHROMEOS_LACROS)
+   std::unique_ptr<chromeos::LacrosService> lacros_service_;
+diff --git chrome/browser/chrome_browser_main.cc chrome/browser/chrome_browser_main.cc
+index 143a625d3bb54..cff7b898c66a9 100644
+--- chrome/browser/chrome_browser_main.cc
++++ chrome/browser/chrome_browser_main.cc
+@@ -52,6 +52,7 @@
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
+ #include "cc/base/switches.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/about_flags.h"
+ #include "chrome/browser/active_use_util.h"
+ #include "chrome/browser/after_startup_task_utils.h"
+@@ -1507,7 +1508,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
+   }
+ #endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
+ 
+-#if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
++#if BUILDFLAG(ENABLE_PROCESS_SINGLETON) && !BUILDFLAG(ENABLE_CEF)
+   // Handle special early return paths (which couldn't be processed even earlier
+   // as they require the process singleton to be held) first.
+ 
+@@ -1554,7 +1555,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
+     return content::RESULT_CODE_NORMAL_EXIT;
+ #endif  // BUILDFLAG(IS_WIN)
+   }
+-#endif  // BUILDFLAG(ENABLE_PROCESS_SINGLETON)
++#endif  // BUILDFLAG(ENABLE_PROCESS_SINGLETON) && !BUILDFLAG(ENABLE_CEF)
+ 
+ #if BUILDFLAG(IS_WIN)
+   // Check if there is any machine level Chrome installed on the current
+@@ -1608,12 +1609,14 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
+         browser_process_->local_state());
+   }
+ 
++#if !BUILDFLAG(ENABLE_CEF)
+   // Needs to be done before PostProfileInit, since login manager on CrOS is
+   // called inside PostProfileInit.
+   content::WebUIControllerFactory::RegisterFactory(
+       ChromeWebUIControllerFactory::GetInstance());
+   RegisterChromeWebUIConfigs();
+   RegisterChromeUntrustedWebUIConfigs();
++#endif
+ 
+ #if BUILDFLAG(IS_ANDROID)
+   page_info::SetPageInfoClient(new ChromePageInfoClient());
+@@ -1759,6 +1762,10 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
+   }
+ #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+ 
++  // Bypass StartupBrowserCreator and RunLoop creation with CEF.
++  // CEF with the Chrome runtime will create and manage its own RunLoop.
++#if !BUILDFLAG(ENABLE_CEF)
++
+   // This step is costly and is already measured in
+   // Startup.StartupBrowserCreator_Start.
+   // See the comment above for an explanation of |process_command_line|.
+@@ -1797,11 +1804,14 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
+ 
+     // Create the RunLoop for MainMessageLoopRun() to use and transfer
+     // ownership of the browser's lifetime to the BrowserProcess.
++    // CEF with the Chrome runtime will create and manage its own RunLoop.
+     DCHECK(!GetMainRunLoopInstance());
+     GetMainRunLoopInstance() = std::make_unique<base::RunLoop>();
+     browser_process_->SetQuitClosure(
+         GetMainRunLoopInstance()->QuitWhenIdleClosure());
+   }
++#endif  // !BUILDFLAG(ENABLE_CEF)
++
+   browser_creator_.reset();
+ #endif  // !BUILDFLAG(IS_ANDROID)
+ 
+diff --git chrome/browser/chrome_browser_main_mac.mm chrome/browser/chrome_browser_main_mac.mm
+index a509d0b37e953..0d48c4a1f1daf 100644
+--- chrome/browser/chrome_browser_main_mac.mm
++++ chrome/browser/chrome_browser_main_mac.mm
+@@ -17,6 +17,7 @@
+ #include "base/path_service.h"
+ #include "base/strings/sys_string_conversions.h"
+ #include "build/branding_buildflags.h"
++#include "cef/libcef/features/features.h"
+ #import "chrome/browser/app_controller_mac.h"
+ #include "chrome/browser/apps/app_shim/app_shim_listener.h"
+ #include "chrome/browser/browser_process.h"
+@@ -113,6 +114,7 @@ void ChromeBrowserMainPartsMac::PreCreateMainMessageLoop() {
+   }
+ #endif  // !BUILDFLAG(CHROME_FOR_TESTING)
+ 
++#if !BUILDFLAG(ENABLE_CEF)
+   // Create the app delegate by requesting the shared AppController.
+   CHECK_EQ(nil, NSApp.delegate);
+   AppController* app_controller = AppController.sharedController;
+@@ -121,6 +123,7 @@ void ChromeBrowserMainPartsMac::PreCreateMainMessageLoop() {
+   chrome::BuildMainMenu(NSApp, app_controller,
+                         l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), false);
+   [app_controller mainMenuCreated];
++#endif  // BUILDFLAG(ENABLE_CEF)
+ 
+   ui::WarmScreenCapture();
+ 
+@@ -179,5 +182,7 @@ void ChromeBrowserMainPartsMac::PostProfileInit(Profile* profile,
+ }
+ 
+ void ChromeBrowserMainPartsMac::DidEndMainMessageLoop() {
++#if !BUILDFLAG(ENABLE_CEF)
+   [AppController.sharedController didEndMainMessageLoop];
++#endif
+ }
+diff --git chrome/browser/chrome_content_browser_client.cc chrome/browser/chrome_content_browser_client.cc
+index 9b845c0e331c4..6a2128ae2b562 100644
+--- chrome/browser/chrome_content_browser_client.cc
++++ chrome/browser/chrome_content_browser_client.cc
+@@ -42,6 +42,7 @@
+ #include "base/values.h"
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/features.h"
+ #include "chrome/browser/accessibility/accessibility_labels_service.h"
+ #include "chrome/browser/accessibility/accessibility_labels_service_factory.h"
+ #include "chrome/browser/after_startup_task_utils.h"
+@@ -1550,6 +1551,8 @@ ChromeContentBrowserClient::GetPopupNavigationDelegateFactoryForTesting() {
+ }
+ 
+ ChromeContentBrowserClient::ChromeContentBrowserClient() {
++  keepalive_timer_.reset(new base::OneShotTimer());
++
+ #if BUILDFLAG(ENABLE_PLUGINS)
+   extra_parts_.push_back(
+       std::make_unique<ChromeContentBrowserClientPluginsPart>());
+@@ -1582,6 +1585,11 @@ ChromeContentBrowserClient::~ChromeContentBrowserClient() {
+   }
+ }
+ 
++void ChromeContentBrowserClient::CleanupOnUIThread() {
++  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
++  keepalive_timer_.reset();
++}
++
+ // static
+ void ChromeContentBrowserClient::RegisterLocalStatePrefs(
+     PrefRegistrySimple* registry) {
+@@ -4463,9 +4471,11 @@ void ChromeContentBrowserClient::BrowserURLHandlerCreated(
+                           &search::HandleNewTabURLReverseRewrite);
+ #endif  // BUILDFLAG(IS_ANDROID)
+ 
++#if !BUILDFLAG(ENABLE_CEF)
+   // chrome: & friends.
+   handler->AddHandlerPair(&ChromeContentBrowserClient::HandleWebUI,
+                           &ChromeContentBrowserClient::HandleWebUIReverse);
++#endif
+ }
+ 
+ base::FilePath ChromeContentBrowserClient::GetDefaultDownloadDirectory() {
+@@ -6529,7 +6539,7 @@ void ChromeContentBrowserClient::OnNetworkServiceCreated(
+ #endif
+ }
+ 
+-void ChromeContentBrowserClient::ConfigureNetworkContextParams(
++bool ChromeContentBrowserClient::ConfigureNetworkContextParams(
+     content::BrowserContext* context,
+     bool in_memory,
+     const base::FilePath& relative_partition_path,
+@@ -6547,6 +6557,8 @@ void ChromeContentBrowserClient::ConfigureNetworkContextParams(
+     network_context_params->user_agent = GetUserAgentBasedOnPolicy(context);
+     network_context_params->accept_language = GetApplicationLocale();
+   }
++
++  return true;
+ }
+ 
+ std::vector<base::FilePath>
+@@ -7653,10 +7665,10 @@ void ChromeContentBrowserClient::OnKeepaliveRequestStarted(
+   const auto now = base::TimeTicks::Now();
+   const auto timeout = GetKeepaliveTimerTimeout(context);
+   keepalive_deadline_ = std::max(keepalive_deadline_, now + timeout);
+-  if (keepalive_deadline_ > now && !keepalive_timer_.IsRunning()) {
++  if (keepalive_deadline_ > now && !keepalive_timer_->IsRunning()) {
+     DVLOG(1) << "Starting a keepalive timer(" << timeout.InSecondsF()
+              << " seconds)";
+-    keepalive_timer_.Start(
++    keepalive_timer_->Start(
+         FROM_HERE, keepalive_deadline_ - now,
+         base::BindOnce(
+             &ChromeContentBrowserClient::OnKeepaliveTimerFired,
+@@ -7675,7 +7687,8 @@ void ChromeContentBrowserClient::OnKeepaliveRequestFinished() {
+   --num_keepalive_requests_;
+   if (num_keepalive_requests_ == 0) {
+     DVLOG(1) << "Stopping the keepalive timer";
+-    keepalive_timer_.Stop();
++    if (keepalive_timer_)
++      keepalive_timer_->Stop();
+     // This deletes the keep alive handle attached to the timer function and
+     // unblock the shutdown sequence.
+   }
+@@ -7817,7 +7830,7 @@ void ChromeContentBrowserClient::OnKeepaliveTimerFired(
+   const auto now = base::TimeTicks::Now();
+   const auto then = keepalive_deadline_;
+   if (now < then) {
+-    keepalive_timer_.Start(
++    keepalive_timer_->Start(
+         FROM_HERE, then - now,
+         base::BindOnce(&ChromeContentBrowserClient::OnKeepaliveTimerFired,
+                        weak_factory_.GetWeakPtr(),
+diff --git chrome/browser/chrome_content_browser_client.h chrome/browser/chrome_content_browser_client.h
+index db4ede8eb28c8..a5ca9f6c57826 100644
+--- chrome/browser/chrome_content_browser_client.h
++++ chrome/browser/chrome_content_browser_client.h
+@@ -136,6 +136,8 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient {
+ 
+   ~ChromeContentBrowserClient() override;
+ 
++  virtual void CleanupOnUIThread();
++
+   // TODO(https://crbug.com/787567): This file is about calls from content/ out
+   // to chrome/ to get values or notify about events, but both of these
+   // functions are from chrome/ to chrome/ and don't involve content/ at all.
+@@ -654,7 +656,7 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient {
+       override;
+   void OnNetworkServiceCreated(
+       network::mojom::NetworkService* network_service) override;
+-  void ConfigureNetworkContextParams(
++  bool ConfigureNetworkContextParams(
+       content::BrowserContext* context,
+       bool in_memory,
+       const base::FilePath& relative_partition_path,
+@@ -1098,7 +1100,7 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient {
+ 
+ #if !BUILDFLAG(IS_ANDROID)
+   uint64_t num_keepalive_requests_ = 0;
+-  base::OneShotTimer keepalive_timer_;
++  std::unique_ptr<base::OneShotTimer> keepalive_timer_;
+   base::TimeTicks keepalive_deadline_;
+ #endif
+ 
+diff --git chrome/browser/prefs/browser_prefs.cc chrome/browser/prefs/browser_prefs.cc
+index fc8d276b5191a..7fbdb13fe7ff4 100644
+--- chrome/browser/prefs/browser_prefs.cc
++++ chrome/browser/prefs/browser_prefs.cc
+@@ -14,6 +14,7 @@
+ #include "build/build_config.h"
+ #include "build/chromecast_buildflags.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/features.h"
+ #include "chrome/browser/about_flags.h"
+ #include "chrome/browser/accessibility/accessibility_labels_service.h"
+ #include "chrome/browser/accessibility/accessibility_ui.h"
+@@ -189,6 +190,10 @@
+ #include "chrome/browser/background/background_mode_manager.h"
+ #endif
+ 
++#if BUILDFLAG(ENABLE_CEF)
++#include "cef/libcef/browser/prefs/browser_prefs.h"
++#endif
++
+ #if BUILDFLAG(ENABLE_EXTENSIONS)
+ #include "chrome/browser/accessibility/animation_policy_prefs.h"
+ #include "chrome/browser/apps/platform_apps/shortcut_manager.h"
+@@ -1619,6 +1624,11 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
+ 
+   // This is intentionally last.
+   RegisterLocalStatePrefsForMigration(registry);
++
++#if BUILDFLAG(ENABLE_CEF)
++  // Always call this last.
++  browser_prefs::RegisterLocalStatePrefs(registry);
++#endif
+ }
+ 
+ // Register prefs applicable to all profiles.
+@@ -2039,6 +2049,10 @@ void RegisterUserProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
+                               const std::string& locale) {
+   RegisterProfilePrefs(registry, locale);
+ 
++#if BUILDFLAG(ENABLE_CEF)
++  browser_prefs::RegisterProfilePrefs(registry);
++#endif
++
+ #if BUILDFLAG(IS_ANDROID)
+   ::android::RegisterUserProfilePrefs(registry);
+ #endif
diff --git a/src/patch/patches/chrome_runtime_views.patch b/src/patch/patches/chrome_runtime_views.patch
new file mode 100644
index 0000000..0b2eb4a
--- /dev/null
+++ b/src/patch/patches/chrome_runtime_views.patch
@@ -0,0 +1,1041 @@
+diff --git chrome/browser/ui/browser_command_controller.cc chrome/browser/ui/browser_command_controller.cc
+index 85dc58159a58a..9b582e691f6d8 100644
+--- chrome/browser/ui/browser_command_controller.cc
++++ chrome/browser/ui/browser_command_controller.cc
+@@ -402,6 +402,7 @@ bool BrowserCommandController::ExecuteCommandWithDisposition(
+   // choose to not implement CommandUpdaterDelegate inside this class and
+   // therefore command_updater_ doesn't have the delegate set).
+   if (!SupportsCommand(id) || !IsCommandEnabled(id)) {
++    LOG(WARNING) << "Invalid/disabled command " << id;
+     return false;
+   }
+ 
+@@ -418,6 +419,13 @@ bool BrowserCommandController::ExecuteCommandWithDisposition(
+   DCHECK(command_updater_.IsCommandEnabled(id))
+       << "Invalid/disabled command " << id;
+ 
++#if BUILDFLAG(ENABLE_CEF)
++  if (browser_->cef_delegate() &&
++      browser_->cef_delegate()->HandleCommand(id, disposition)) {
++    return true;
++  }
++#endif
++
+   // The order of commands in this switch statement must match the function
+   // declaration order in browser.h!
+   switch (id) {
+@@ -1152,11 +1160,13 @@ void BrowserCommandController::TabRestoreServiceLoaded(
+ // BrowserCommandController, private:
+ 
+ bool BrowserCommandController::IsShowingMainUI() {
+-  return browser_->SupportsWindowFeature(Browser::FEATURE_TABSTRIP);
++  return browser_->SupportsWindowFeature(Browser::FEATURE_TABSTRIP) ||
++         browser_->toolbar_overridden();
+ }
+ 
+ bool BrowserCommandController::IsShowingLocationBar() {
+-  return browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR);
++  return browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR) ||
++         browser_->toolbar_overridden();
+ }
+ 
+ bool BrowserCommandController::IsWebAppOrCustomTab() const {
+diff --git chrome/browser/ui/toolbar/app_menu_model.cc chrome/browser/ui/toolbar/app_menu_model.cc
+index d2b2a605cbba5..afaf26c26a6db 100644
+--- chrome/browser/ui/toolbar/app_menu_model.cc
++++ chrome/browser/ui/toolbar/app_menu_model.cc
+@@ -590,6 +590,57 @@ SaveAndShareSubMenuModel::SaveAndShareSubMenuModel(
+   }
+ }
+ 
++#if BUILDFLAG(ENABLE_CEF)
++using IsVisibleCallback = base::RepeatingCallback<bool(int)>;
++
++void FilterMenuModel(ui::SimpleMenuModel* model,
++                     const IsVisibleCallback& is_visible) {
++  absl::optional<size_t> last_separator;
++  size_t visible_ct = 0;
++  for (size_t i = 0; i < model->GetItemCount(); ++i) {
++    const auto type = model->GetTypeAt(i);
++    if (type == ui::MenuModel::TYPE_SEPARATOR) {
++      if (last_separator) {
++        // Remove multiple separators in a row. Prefer to remove a NORMAL
++        // separator if possible (as compared to zoom/edit controls which use
++        // UPPER/LOWER separators).
++        if (model->GetSeparatorTypeAt(*last_separator) ==
++            ui::NORMAL_SEPARATOR) {
++          model->RemoveItemAt(*last_separator);
++          i--;
++          last_separator = i;
++        } else {
++          model->RemoveItemAt(i);
++          i--;
++        }
++      } else if (visible_ct == 0) {
++        // Remove leading separator.
++        model->RemoveItemAt(i);
++        i--;
++      } else {
++        last_separator = i;
++      }
++      visible_ct = 0;
++    } else if (is_visible.Run(model->GetCommandIdAt(i))) {
++      last_separator = absl::nullopt;
++      visible_ct++;
++
++      if (type == ui::MenuModel::TYPE_SUBMENU) {
++        // Filter sub-menu.
++        auto sub_model =
++            static_cast<ui::SimpleMenuModel*>(model->GetSubmenuModelAt(i));
++        FilterMenuModel(sub_model, is_visible);
++      }
++    }
++  }
++
++  if (last_separator) {
++    // Remove trailing separator.
++    model->RemoveItemAt(*last_separator);
++  }
++}
++#endif  // BUILDFLAG(ENABLE_CEF)
++
+ }  // namespace
+ 
+ ////////////////////////////////////////////////////////////////////////////////
+@@ -1382,7 +1433,7 @@ bool AppMenuModel::IsCommandIdChecked(int command_id) const {
+   return false;
+ }
+ 
+-bool AppMenuModel::IsCommandIdEnabled(int command_id) const {
++bool AppMenuModel::IsCommandIdEnabledInternal(int command_id) const {
+   GlobalError* error =
+       GlobalErrorServiceFactory::GetForProfile(browser_->profile())
+           ->GetGlobalErrorByMenuItemCommandID(command_id);
+@@ -1397,6 +1448,30 @@ bool AppMenuModel::IsCommandIdEnabled(int command_id) const {
+   }
+ }
+ 
++bool AppMenuModel::IsCommandIdEnabled(int command_id) const {
++  if (!IsCommandIdEnabledInternal(command_id)) {
++    return false;
++  }
++
++#if BUILDFLAG(ENABLE_CEF)
++  if (browser_->cef_delegate()) {
++    return browser_->cef_delegate()->IsAppMenuItemEnabled(command_id);
++  }
++#endif
++
++  return true;
++}
++
++bool AppMenuModel::IsCommandIdVisible(int command_id) const {
++#if BUILDFLAG(ENABLE_CEF)
++  if (browser_->cef_delegate()) {
++    return browser_->cef_delegate()->IsAppMenuItemVisible(command_id);
++  }
++#endif
++
++  return true;
++}
++
+ bool AppMenuModel::IsCommandIdAlerted(int command_id) const {
+   if ((command_id == IDC_RECENT_TABS_MENU) ||
+       (command_id == AppMenuModel::kMinRecentTabsCommandId)) {
+@@ -1566,11 +1641,15 @@ void AppMenuModel::Build() {
+                                        kDefaultIconSize));
+   }
+ 
+-  AddSeparator(features::IsChromeRefresh2023() ? ui::NORMAL_SEPARATOR
+-                                               : ui::LOWER_SEPARATOR);
+-  CreateZoomMenu();
+-  AddSeparator(features::IsChromeRefresh2023() ? ui::NORMAL_SEPARATOR
+-                                               : ui::UPPER_SEPARATOR);
++  if (IsCommandIdVisible(IDC_ZOOM_MENU)) {
++    AddSeparator(features::IsChromeRefresh2023() ? ui::NORMAL_SEPARATOR
++                                                 : ui::LOWER_SEPARATOR);
++    CreateZoomMenu();
++    AddSeparator(features::IsChromeRefresh2023() ? ui::NORMAL_SEPARATOR
++                                                 : ui::UPPER_SEPARATOR);
++  } else {
++    AddSeparator(ui::NORMAL_SEPARATOR);
++  }
+ 
+   AddItemWithStringId(IDC_PRINT, IDS_PRINT);
+ 
+@@ -1651,9 +1730,13 @@ void AppMenuModel::Build() {
+                          kMoreToolsMenuItem);
+ 
+   if (!features::IsChromeRefresh2023()) {
+-    AddSeparator(ui::LOWER_SEPARATOR);
+-    CreateCutCopyPasteMenu();
+-    AddSeparator(ui::UPPER_SEPARATOR);
++    if (IsCommandIdVisible(IDC_EDIT_MENU)) {
++      AddSeparator(ui::LOWER_SEPARATOR);
++      CreateCutCopyPasteMenu();
++      AddSeparator(ui::UPPER_SEPARATOR);
++    } else {
++      AddSeparator(ui::NORMAL_SEPARATOR);
++    }
+   }
+ 
+   if (!features::IsChromeRefresh2023()) {
+@@ -1739,6 +1822,11 @@ void AppMenuModel::Build() {
+     SetCommandIcon(this, IDC_EXIT, kExitMenuIcon);
+   }
+ 
++#if BUILDFLAG(ENABLE_CEF)
++  FilterMenuModel(this, base::BindRepeating(&AppMenuModel::IsCommandIdVisible,
++                                            base::Unretained(this)));
++#endif
++
+   uma_action_recorded_ = false;
+ }
+ 
+diff --git chrome/browser/ui/toolbar/app_menu_model.h chrome/browser/ui/toolbar/app_menu_model.h
+index f06cf1bf08ba4..4e89b522715fc 100644
+--- chrome/browser/ui/toolbar/app_menu_model.h
++++ chrome/browser/ui/toolbar/app_menu_model.h
+@@ -204,6 +204,7 @@ class AppMenuModel : public ui::SimpleMenuModel,
+   void ExecuteCommand(int command_id, int event_flags) override;
+   bool IsCommandIdChecked(int command_id) const override;
+   bool IsCommandIdEnabled(int command_id) const override;
++  bool IsCommandIdVisible(int command_id) const override;
+   bool IsCommandIdAlerted(int command_id) const override;
+   bool GetAcceleratorForCommandId(int command_id,
+                                   ui::Accelerator* accelerator) const override;
+@@ -236,6 +237,8 @@ class AppMenuModel : public ui::SimpleMenuModel,
+   // took to select the command.
+   void LogMenuMetrics(int command_id);
+ 
++  bool IsCommandIdEnabledInternal(int command_id) const;
++
+  private:
+   // Adds actionable global error menu items to the menu.
+   // Examples: Extension permissions and sign in errors.
+diff --git chrome/browser/ui/views/find_bar_host.cc chrome/browser/ui/views/find_bar_host.cc
+index 59024587ef6b7..0c30aa71768cf 100644
+--- chrome/browser/ui/views/find_bar_host.cc
++++ chrome/browser/ui/views/find_bar_host.cc
+@@ -412,6 +412,12 @@ void FindBarHost::GetWidgetBounds(gfx::Rect* bounds) {
+   // The BrowserView does Layout for the components that we care about
+   // positioning relative to, so we ask it to tell us where we should go.
+   *bounds = browser_view()->GetFindBarBoundingBox();
++
++#if BUILDFLAG(ENABLE_CEF)
++  if (browser_view()->browser() && browser_view()->browser()->cef_delegate()) {
++    browser_view()->browser()->cef_delegate()->UpdateFindBarBoundingBox(bounds);
++  }
++#endif
+ }
+ 
+ void FindBarHost::RegisterAccelerators() {
+diff --git chrome/browser/ui/views/frame/browser_frame.cc chrome/browser/ui/views/frame/browser_frame.cc
+index bb4b3821bcfda..4014f61a7057f 100644
+--- chrome/browser/ui/views/frame/browser_frame.cc
++++ chrome/browser/ui/views/frame/browser_frame.cc
+@@ -114,15 +114,23 @@ ui::ColorProviderKey::SchemeVariant GetSchemeVariant(
+ ////////////////////////////////////////////////////////////////////////////////
+ // BrowserFrame, public:
+ 
++BrowserFrame::BrowserFrame() : BrowserFrame(nullptr) {}
++
+ BrowserFrame::BrowserFrame(BrowserView* browser_view)
+     : native_browser_frame_(nullptr),
+       root_view_(nullptr),
+       browser_frame_view_(nullptr),
+-      browser_view_(browser_view) {
+-  browser_view_->set_frame(this);
++      browser_view_(nullptr) {
+   set_is_secondary_widget(false);
+   // Don't focus anything on creation, selecting a tab will set the focus.
+   set_focus_on_creation(false);
++  if (browser_view)
++    InitBrowserView(browser_view);
++}
++
++void BrowserFrame::InitBrowserView(BrowserView* browser_view) {
++  browser_view_ = browser_view;
++  browser_view_->set_frame(this);
+ }
+ 
+ BrowserFrame::~BrowserFrame() {}
+@@ -228,10 +236,20 @@ void BrowserFrame::LayoutWebAppWindowTitle(
+ }
+ 
+ int BrowserFrame::GetTopInset() const {
++  if (!browser_frame_view_) {
++    // With CEF the browser may already be part of a larger Views layout. Zero
++    // out the adjustment in BrowserView::GetTopInsetInBrowserView() so that
++    // the browser isn't shifted to the top of the window.
++    return browser_view_->y();
++  }
+   return browser_frame_view_->GetTopInset(false);
+ }
+ 
+ void BrowserFrame::UpdateThrobber(bool running) {
++  if (!browser_frame_view_) {
++    // Not supported with CEF Views-hosted DevTools windows.
++    return;
++  }
+   browser_frame_view_->UpdateThrobber(running);
+ }
+ 
+@@ -240,6 +258,8 @@ BrowserNonClientFrameView* BrowserFrame::GetFrameView() const {
+ }
+ 
+ bool BrowserFrame::UseCustomFrame() const {
++  if (!native_browser_frame_)
++    return true;
+   return native_browser_frame_->UseCustomFrame();
+ }
+ 
+@@ -253,20 +273,30 @@ bool BrowserFrame::ShouldDrawFrameHeader() const {
+ 
+ void BrowserFrame::GetWindowPlacement(gfx::Rect* bounds,
+                                       ui::WindowShowState* show_state) const {
++  if (!native_browser_frame_) {
++    *show_state = ui::SHOW_STATE_DEFAULT;
++    return;
++  }
+   return native_browser_frame_->GetWindowPlacement(bounds, show_state);
+ }
+ 
+ content::KeyboardEventProcessingResult BrowserFrame::PreHandleKeyboardEvent(
+     const content::NativeWebKeyboardEvent& event) {
++  if (!native_browser_frame_)
++    return content::KeyboardEventProcessingResult::NOT_HANDLED;
+   return native_browser_frame_->PreHandleKeyboardEvent(event);
+ }
+ 
+ bool BrowserFrame::HandleKeyboardEvent(
+     const content::NativeWebKeyboardEvent& event) {
++  if (!native_browser_frame_)
++    return false;
+   return native_browser_frame_->HandleKeyboardEvent(event);
+ }
+ 
+ void BrowserFrame::OnBrowserViewInitViewsComplete() {
++  if (!browser_frame_view_)
++    return;
+   browser_frame_view_->OnBrowserViewInitViewsComplete();
+ }
+ 
+@@ -367,6 +397,8 @@ ui::ColorProviderKey::ThemeInitializerSupplier* BrowserFrame::GetCustomTheme()
+ }
+ 
+ void BrowserFrame::OnNativeWidgetWorkspaceChanged() {
++  if (!browser_view_)
++    return;
+   chrome::SaveWindowWorkspace(browser_view_->browser(), GetWorkspace());
+   chrome::SaveWindowVisibleOnAllWorkspaces(browser_view_->browser(),
+                                            IsVisibleOnAllWorkspaces());
+@@ -478,6 +510,8 @@ void BrowserFrame::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) {
+ 
+ ui::ColorProviderKey BrowserFrame::GetColorProviderKey() const {
+   auto key = Widget::GetColorProviderKey();
++  if (!browser_view_)
++    return key;
+ 
+   key.app_controller = browser_view_->browser()->app_controller();
+ 
+@@ -632,5 +666,8 @@ bool BrowserFrame::RegenerateFrameOnThemeChange(
+ }
+ 
+ bool BrowserFrame::IsIncognitoBrowser() const {
++  if (!browser_view_) {
++    return true;
++  }
+   return browser_view_->browser()->profile()->IsIncognitoProfile();
+ }
+diff --git chrome/browser/ui/views/frame/browser_frame.h chrome/browser/ui/views/frame/browser_frame.h
+index 0c231b6ac5b01..6b5af98e18e42 100644
+--- chrome/browser/ui/views/frame/browser_frame.h
++++ chrome/browser/ui/views/frame/browser_frame.h
+@@ -61,7 +61,9 @@ enum class TabDragKind {
+ // This is a virtual interface that allows system specific browser frames.
+ class BrowserFrame : public views::Widget, public views::ContextMenuController {
+  public:
++  BrowserFrame();
+   explicit BrowserFrame(BrowserView* browser_view);
++  void InitBrowserView(BrowserView* browser_view);
+ 
+   BrowserFrame(const BrowserFrame&) = delete;
+   BrowserFrame& operator=(const BrowserFrame&) = delete;
+diff --git chrome/browser/ui/views/frame/browser_view.cc chrome/browser/ui/views/frame/browser_view.cc
+index 41376bb2d8af1..fa9ede3614aca 100644
+--- chrome/browser/ui/views/frame/browser_view.cc
++++ chrome/browser/ui/views/frame/browser_view.cc
+@@ -343,11 +343,10 @@ using content::NativeWebKeyboardEvent;
+ using content::WebContents;
+ using web_modal::WebContentsModalDialogHost;
+ 
+-namespace {
++// static
++const char BrowserView::kBrowserViewKey[] = "__BROWSER_VIEW__";
+ 
+-// The name of a key to store on the window handle so that other code can
+-// locate this object using just the handle.
+-const char* const kBrowserViewKey = "__BROWSER_VIEW__";
++namespace {
+ 
+ #if BUILDFLAG(IS_CHROMEOS_ASH)
+ // UMA histograms that record animation smoothness for tab loading animation.
+@@ -843,12 +842,23 @@ class BrowserView::AccessibilityModeObserver : public ui::AXModeObserver {
+ ///////////////////////////////////////////////////////////////////////////////
+ // BrowserView, public:
+ 
++BrowserView::BrowserView() : BrowserView(nullptr) {}
++
+ BrowserView::BrowserView(std::unique_ptr<Browser> browser)
+     : views::ClientView(nullptr, nullptr),
+-      browser_(std::move(browser)),
+       accessibility_mode_observer_(
+-          std::make_unique<AccessibilityModeObserver>(this)),
+-      browser_actions_(*browser_) {
++          std::make_unique<AccessibilityModeObserver>(this)) {
++  if (browser)
++    InitBrowser(std::move(browser));
++}
++
++void BrowserView::InitBrowser(std::unique_ptr<Browser> browser) {
++  DCHECK(!browser_);
++  browser_ = std::move(browser);
++
++  browser_actions_ = std::make_unique<BrowserActions>(*browser_);
++  immersive_mode_controller_ = chrome::CreateImmersiveModeController(this);
++
+   SetShowIcon(
+       ::ShouldShowWindowIcon(browser_.get(), AppUsesWindowControlsOverlay()));
+ 
+@@ -897,7 +907,6 @@ BrowserView::BrowserView(std::unique_ptr<Browser> browser)
+   }
+ 
+   browser_->tab_strip_model()->AddObserver(this);
+-  immersive_mode_controller_ = chrome::CreateImmersiveModeController(this);
+ 
+   // Top container holds tab strip region and toolbar and lives at the front of
+   // the view hierarchy.
+@@ -956,8 +965,15 @@ BrowserView::BrowserView(std::unique_ptr<Browser> browser)
+   contents_container->SetLayoutManager(std::make_unique<ContentsLayoutManager>(
+       devtools_web_view_, contents_web_view_));
+ 
+-  toolbar_ = top_container_->AddChildView(
+-      std::make_unique<ToolbarView>(browser_.get(), this));
++  toolbar_ = OverrideCreateToolbar();
++  if (!toolbar_) {
++    toolbar_ = new ToolbarView(browser_.get(), this, absl::nullopt);
++  } else {
++    browser_->set_toolbar_overridden(true);
++    // Update state that depends on the above flag.
++    browser_->command_controller()->FullscreenStateChanged();
++  }
++  top_container_->AddChildView(base::WrapUnique(toolbar_.get()));
+ 
+   contents_separator_ =
+       top_container_->AddChildView(std::make_unique<ContentsSeparator>());
+@@ -1031,7 +1047,9 @@ BrowserView::~BrowserView() {
+ 
+   // All the tabs should have been destroyed already. If we were closed by the
+   // OS with some tabs than the NativeBrowserFrame should have destroyed them.
++  if (browser_) {
+   DCHECK_EQ(0, browser_->tab_strip_model()->count());
++  }
+ 
+   // Stop the animation timer explicitly here to avoid running it in a nested
+   // message loop, which may run by Browser destructor.
+@@ -1045,12 +1063,14 @@ BrowserView::~BrowserView() {
+   // child views and it is an observer for avatar toolbar button if any.
+   autofill_bubble_handler_.reset();
+ 
++  if (browser_) {
+   auto* global_registry =
+       extensions::ExtensionCommandsGlobalRegistry::Get(browser_->profile());
+   if (global_registry->registry_for_active_window() ==
+       extension_keybinding_registry_.get()) {
+     global_registry->set_registry_for_active_window(nullptr);
+   }
++  }
+ 
+   // The TabStrip attaches a listener to the model. Make sure we shut down the
+   // TabStrip first so that it can cleanly remove the listener.
+@@ -1068,7 +1088,9 @@ BrowserView::~BrowserView() {
+ 
+   // `SidePanelUI::RemoveSidePanelUIForBrowser()` deletes the
+   // SidePanelCoordinator.
++  if (browser()) {
+   SidePanelUI::RemoveSidePanelUIForBrowser(browser());
++  }
+ }
+ 
+ // static
+@@ -1939,9 +1961,14 @@ void BrowserView::OnExclusiveAccessUserInput() {
+ 
+ bool BrowserView::ShouldHideUIForFullscreen() const {
+   // Immersive mode needs UI for the slide-down top panel.
+-  if (immersive_mode_controller_->IsEnabled())
++  // Avoid callback into |immersive_mode_controller_| during construction.
++  // See CEF issue #3527.
++  if (immersive_mode_controller_ &&
++      immersive_mode_controller_->IsEnabled())
+     return false;
+ 
++  if (!frame_->GetFrameView())
++    return false;
+   return frame_->GetFrameView()->ShouldHideTopUIForFullscreen();
+ }
+ 
+@@ -2956,7 +2983,8 @@ DownloadShelf* BrowserView::GetDownloadShelf() {
+ }
+ 
+ DownloadBubbleUIController* BrowserView::GetDownloadBubbleUIController() {
+-  DCHECK(toolbar_button_provider_);
++  if (!toolbar_button_provider_)
++    return nullptr;
+   if (auto* download_button = toolbar_button_provider_->GetDownloadButton())
+     return download_button->bubble_controller();
+   return nullptr;
+@@ -3490,7 +3518,8 @@ void BrowserView::ReparentTopContainerForEndOfImmersive() {
+   if (top_container()->parent() == this)
+     return;
+ 
+-  overlay_view_->SetVisible(false);
++  if (overlay_view_)
++    overlay_view_->SetVisible(false);
+   top_container()->DestroyLayer();
+   AddChildViewAt(top_container(), 0);
+   EnsureFocusOrder();
+@@ -3948,11 +3977,38 @@ void BrowserView::GetAccessiblePanes(std::vector<views::View*>* panes) {
+ bool BrowserView::ShouldDescendIntoChildForEventHandling(
+     gfx::NativeView child,
+     const gfx::Point& location) {
++#if BUILDFLAG(ENABLE_CEF)
++  const bool frameless_pip =
++      GetIsPictureInPictureType() &&
++      !browser_->SupportsWindowFeature(Browser::FEATURE_TITLEBAR);
++  if (frameless_pip) {
++    if (auto frame_view = frame()->GetFrameView()) {
++      int result = frame_view->NonClientHitTest(location);
++      if (result == HTTOP || result == HTTOPLEFT || result == HTTOPRIGHT) {
++        // Allow resize from the top of a frameless window.
++        return false;
++      }
++    }
++  }
++#endif
++
++  absl::optional<SkRegion> draggable_region;
++
+   // Window for PWAs with window-controls-overlay display override should claim
+   // mouse events that fall within the draggable region.
+   web_app::AppBrowserController* controller = browser()->app_controller();
+-  if (AreDraggableRegionsEnabled() && controller &&
+-      controller->draggable_region().has_value()) {
++  if (AreDraggableRegionsEnabled() && controller) {
++    draggable_region = controller->draggable_region();
++  }
++
++#if BUILDFLAG(ENABLE_CEF)
++  // Match logic in PictureInPictureBrowserFrameView::NonClientHitTest.
++  if (!draggable_region.has_value() && frameless_pip) {
++    draggable_region = browser_->cef_delegate()->GetDraggableRegion();
++  }
++#endif
++
++  if (draggable_region.has_value()) {
+     // Draggable regions are defined relative to the web contents.
+     gfx::Point point_in_contents_web_view_coords(location);
+     views::View::ConvertPointToTarget(GetWidget()->GetRootView(),
+@@ -3961,7 +4017,7 @@ bool BrowserView::ShouldDescendIntoChildForEventHandling(
+ 
+     // Draggable regions should be ignored for clicks into any browser view's
+     // owned widgets, for example alerts, permission prompts or find bar.
+-    return !controller->draggable_region()->contains(
++    return !draggable_region->contains(
+                point_in_contents_web_view_coords.x(),
+                point_in_contents_web_view_coords.y()) ||
+            WidgetOwnedByAnchorContainsPoint(point_in_contents_web_view_coords);
+@@ -4069,8 +4125,10 @@ void BrowserView::Layout() {
+ 
+   // TODO(jamescook): Why was this in the middle of layout code?
+   toolbar_->location_bar()->omnibox_view()->SetFocusBehavior(
+-      IsToolbarVisible() ? FocusBehavior::ALWAYS : FocusBehavior::NEVER);
+-  frame()->GetFrameView()->UpdateMinimumSize();
++      (IsToolbarVisible() || browser_->toolbar_overridden()) ?
++          FocusBehavior::ALWAYS : FocusBehavior::NEVER);
++  if (frame()->GetFrameView())
++    frame()->GetFrameView()->UpdateMinimumSize();
+ 
+ #if BUILDFLAG(IS_CHROMEOS_ASH)
+   // In chromeOS ash we round the bottom two corners of the browser frame by
+@@ -4148,6 +4206,11 @@ void BrowserView::AddedToWidget() {
+   SetThemeProfileForWindow(GetNativeWindow(), browser_->profile());
+ #endif
+ 
++  // This browser view may already have a custom button provider set (e.g the
++  // hosted app frame).
++  if (!toolbar_button_provider_)
++    SetToolbarButtonProvider(toolbar_);
++
+   toolbar_->Init();
+ 
+   // TODO(pbos): Investigate whether the side panels should be creatable when
+@@ -4196,13 +4259,9 @@ void BrowserView::AddedToWidget() {
+ 
+   EnsureFocusOrder();
+ 
+-  // This browser view may already have a custom button provider set (e.g the
+-  // hosted app frame).
+-  if (!toolbar_button_provider_)
+-    SetToolbarButtonProvider(toolbar_);
+-
+   frame_->OnBrowserViewInitViewsComplete();
+-  frame_->GetFrameView()->UpdateMinimumSize();
++  if (frame_->GetFrameView())
++    frame_->GetFrameView()->UpdateMinimumSize();
+   using_native_frame_ = frame_->ShouldUseNativeFrame();
+ 
+   MaybeInitializeWebUITabStrip();
+@@ -4614,7 +4673,8 @@ void BrowserView::ProcessFullscreen(bool fullscreen,
+   // Undo our anti-jankiness hacks and force a re-layout.
+   in_process_fullscreen_ = false;
+   ToolbarSizeChanged(false);
+-  frame_->GetFrameView()->OnFullscreenStateChanged();
++  if (frame_->GetFrameView())
++    frame_->GetFrameView()->OnFullscreenStateChanged();
+ }
+ 
+ bool BrowserView::ShouldUseImmersiveFullscreenForUrl(const GURL& url) const {
+@@ -5003,6 +5063,8 @@ Profile* BrowserView::GetProfile() {
+ }
+ 
+ void BrowserView::UpdateUIForTabFullscreen() {
++  if (!frame_->GetFrameView())
++    return;
+   frame()->GetFrameView()->UpdateFullscreenTopUI();
+ }
+ 
+@@ -5025,6 +5087,8 @@ void BrowserView::HideDownloadShelf() {
+ }
+ 
+ bool BrowserView::CanUserExitFullscreen() const {
++  if (!frame_->GetFrameView())
++    return true;
+   return frame_->GetFrameView()->CanUserExitFullscreen();
+ }
+ 
+diff --git chrome/browser/ui/views/frame/browser_view.h chrome/browser/ui/views/frame/browser_view.h
+index f6251860d8bd3..9756332121fd8 100644
+--- chrome/browser/ui/views/frame/browser_view.h
++++ chrome/browser/ui/views/frame/browser_view.h
+@@ -140,11 +140,16 @@ class BrowserView : public BrowserWindow,
+     kUnknown
+   };
+ 
++  BrowserView();
+   explicit BrowserView(std::unique_ptr<Browser> browser);
++  void InitBrowser(std::unique_ptr<Browser> browser);
+   BrowserView(const BrowserView&) = delete;
+   BrowserView& operator=(const BrowserView&) = delete;
+   ~BrowserView() override;
+ 
++  // Key used to bind BrowserView to the Widget with which it is associated.
++  static const char kBrowserViewKey[];
++
+   void set_frame(BrowserFrame* frame) {
+     frame_ = frame;
+     paint_as_active_subscription_ =
+@@ -377,7 +382,7 @@ class BrowserView : public BrowserWindow,
+   }
+ 
+   actions::ActionItem* root_action_item() const {
+-    return browser_actions_.root_action_item();
++    return browser_actions_->root_action_item();
+   }
+ 
+   // Returns true if the view has been initialized.
+@@ -822,6 +827,9 @@ class BrowserView : public BrowserWindow,
+   // TopContainerBackground::PaintThemeCustomImage for details.
+   gfx::Point GetThemeOffsetFromBrowserView() const;
+ 
++ protected:
++  virtual ToolbarView* OverrideCreateToolbar() { return nullptr; }
++
+  private:
+   // Do not friend BrowserViewLayout. Use the BrowserViewLayoutDelegate
+   // interface to keep these two classes decoupled and testable.
+@@ -1255,7 +1263,7 @@ class BrowserView : public BrowserWindow,
+ 
+   // `browser_actions_` creates the root browser level action along with child
+   // actions.
+-  const BrowserActions browser_actions_;
++  std::unique_ptr<BrowserActions> browser_actions_;
+ 
+   std::unique_ptr<AccessibilityFocusHighlight> accessibility_focus_highlight_;
+ 
+diff --git chrome/browser/ui/views/frame/browser_view_layout.cc chrome/browser/ui/views/frame/browser_view_layout.cc
+index ab36dd2ae50e2..6dabacc9773fc 100644
+--- chrome/browser/ui/views/frame/browser_view_layout.cc
++++ chrome/browser/ui/views/frame/browser_view_layout.cc
+@@ -48,6 +48,10 @@
+ #include "ui/views/window/client_view.h"
+ #include "ui/views/window/hit_test_utils.h"
+ 
++#if BUILDFLAG(ENABLE_CEF)
++#include "cef/libcef/browser/chrome/views/chrome_views_util.h"
++#endif
++
+ using views::View;
+ using web_modal::ModalDialogHostObserver;
+ using web_modal::WebContentsModalDialogHost;
+@@ -578,6 +582,13 @@ int BrowserViewLayout::LayoutWebUITabStrip(int top) {
+ 
+ int BrowserViewLayout::LayoutToolbar(int top) {
+   TRACE_EVENT0("ui", "BrowserViewLayout::LayoutToolbar");
++#if BUILDFLAG(ENABLE_CEF)
++  if (cef::IsCefView(toolbar_)) {
++    // CEF may take ownership of the toolbar. Early exit to avoid the DCHECK
++    // in LayoutManager::SetViewVisibility().
++    return top;
++  }
++#endif
+   int browser_view_width = vertical_layout_rect_.width();
+   bool toolbar_visible = delegate_->IsToolbarVisible();
+   int height = toolbar_visible ? toolbar_->GetPreferredSize().height() : 0;
+diff --git chrome/browser/ui/views/frame/contents_web_view.cc chrome/browser/ui/views/frame/contents_web_view.cc
+index 8267a265a8e10..ee08f18e96a34 100644
+--- chrome/browser/ui/views/frame/contents_web_view.cc
++++ chrome/browser/ui/views/frame/contents_web_view.cc
+@@ -23,6 +23,11 @@
+ ContentsWebView::ContentsWebView(content::BrowserContext* browser_context)
+     : views::WebView(browser_context),
+       status_bubble_(nullptr) {
++  // Mouse events on draggable regions will not be handled by the WebView.
++  // Avoid the resulting DCHECK in NativeViewHost::OnMousePressed by
++  // configuring the NativeViewHost not to process events via the view
++  // hierarchy.
++  holder()->SetCanProcessEventsWithinSubtree(false);
+ }
+ 
+ ContentsWebView::~ContentsWebView() {
+diff --git chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc
+index b9b50af047993..70ece4c81ff04 100644
+--- chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc
++++ chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc
+@@ -573,6 +573,11 @@ PictureInPictureBrowserFrameView::PictureInPictureBrowserFrameView(
+   frame->GetNativeWindow()->SetEventTargeter(
+       std::make_unique<chromeos::InteriorResizeHandleTargeter>());
+ #endif
++
++  if (!browser_view->browser()->SupportsWindowFeature(
++          Browser::FEATURE_TITLEBAR)) {
++    top_bar_container_view_->SetVisible(false);
++  }
+ }
+ 
+ PictureInPictureBrowserFrameView::~PictureInPictureBrowserFrameView() {
+@@ -669,18 +674,42 @@ gfx::Rect PictureInPictureBrowserFrameView::GetWindowBoundsForClientBounds(
+ 
+ int PictureInPictureBrowserFrameView::NonClientHitTest(
+     const gfx::Point& point) {
+-  // Allow interacting with the buttons.
+-  if (GetLocationIconViewBounds().Contains(point) ||
+-      GetBackToTabControlsBounds().Contains(point) ||
+-      GetCloseControlsBounds().Contains(point)) {
+-    return HTCLIENT;
++  const bool frameless = !top_bar_container_view_->GetVisible();
++  if (!frameless) {
++    // Allow interacting with the buttons.
++    if (GetLocationIconViewBounds().Contains(point) ||
++        GetBackToTabControlsBounds().Contains(point) ||
++        GetCloseControlsBounds().Contains(point)) {
++      return HTCLIENT;
++    }
++
++    for (size_t i = 0; i < content_setting_views_.size(); i++) {
++      if (GetContentSettingViewBounds(i).Contains(point)) {
++        return HTCLIENT;
++      }
++    }
+   }
+ 
+-  for (size_t i = 0; i < content_setting_views_.size(); i++) {
+-    if (GetContentSettingViewBounds(i).Contains(point)) {
+-      return HTCLIENT;
++#if BUILDFLAG(ENABLE_CEF)
++  if (frameless) {
++    // Match logic in BrowserView::ShouldDescendIntoChildForEventHandling.
++    const auto draggable_region =
++        browser_view()->browser()->cef_delegate()->GetDraggableRegion();
++    if (draggable_region.has_value()) {
++      // Draggable regions are defined relative to the web contents.
++      gfx::Point point_in_contents_web_view_coords(point);
++      views::View::ConvertPointToTarget(GetWidget()->GetRootView(),
++                                        browser_view()->contents_web_view(),
++                                        &point_in_contents_web_view_coords);
++
++      if (draggable_region->contains(
++              point_in_contents_web_view_coords.x(),
++              point_in_contents_web_view_coords.y())) {
++        return HTCAPTION;
++      }
+     }
+   }
++#endif  // BUILDFLAG(ENABLE_CEF)
+ 
+   // Allow dragging and resizing the window.
+   int window_component = GetHTComponentForFrame(
+@@ -747,7 +776,8 @@ void PictureInPictureBrowserFrameView::Layout() {
+   gfx::Rect content_area = GetLocalBounds();
+   content_area.Inset(FrameBorderInsets());
+   gfx::Rect top_bar = content_area;
+-  top_bar.set_height(kTopControlsHeight);
++  top_bar.set_height(
++      top_bar_container_view_->GetVisible() ? kTopControlsHeight : 0);
+   top_bar_container_view_->SetBoundsRect(top_bar);
+ #if !BUILDFLAG(IS_ANDROID)
+   if (auto_pip_setting_overlay_) {
+@@ -1207,7 +1237,8 @@ gfx::Insets PictureInPictureBrowserFrameView::ResizeBorderInsets() const {
+ }
+ 
+ int PictureInPictureBrowserFrameView::GetTopAreaHeight() const {
+-  return FrameBorderInsets().top() + kTopControlsHeight;
++  return FrameBorderInsets().top() +
++         (top_bar_container_view_->GetVisible() ? kTopControlsHeight : 0);
+ }
+ 
+ gfx::Size PictureInPictureBrowserFrameView::GetNonClientViewAreaSize() const {
+diff --git chrome/browser/ui/views/page_action/page_action_icon_controller.cc chrome/browser/ui/views/page_action/page_action_icon_controller.cc
+index ca602db58de3a..1db448a2526a4 100644
+--- chrome/browser/ui/views/page_action/page_action_icon_controller.cc
++++ chrome/browser/ui/views/page_action/page_action_icon_controller.cc
+@@ -97,6 +97,12 @@ void PageActionIconController::Init(const PageActionIconParams& params,
+   };
+ 
+   for (PageActionIconType type : params.types_enabled) {
++#if BUILDFLAG(ENABLE_CEF)
++    if (params.browser && params.browser->cef_delegate() &&
++        !params.browser->cef_delegate()->IsPageActionIconVisible(type)) {
++      continue;
++    }
++#endif
+     switch (type) {
+       case PageActionIconType::kPaymentsOfferNotification:
+         add_page_action_icon(
+diff --git chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
+index 734c741d1f2fa..739b468cfc0d8 100644
+--- chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
++++ chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
+@@ -560,29 +560,41 @@ gfx::Range BrowserTabStripController::ListTabsInGroup(
+ }
+ 
+ bool BrowserTabStripController::IsFrameCondensed() const {
++  if (!GetFrameView())
++    return false;
+   return GetFrameView()->IsFrameCondensed();
+ }
+ 
+ bool BrowserTabStripController::HasVisibleBackgroundTabShapes() const {
++  if (!GetFrameView())
++    return false;
+   return GetFrameView()->HasVisibleBackgroundTabShapes(
+       BrowserFrameActiveState::kUseCurrent);
+ }
+ 
+ bool BrowserTabStripController::EverHasVisibleBackgroundTabShapes() const {
++  if (!GetFrameView())
++    return false;
+   return GetFrameView()->EverHasVisibleBackgroundTabShapes();
+ }
+ 
+ bool BrowserTabStripController::CanDrawStrokes() const {
++  if (!GetFrameView())
++    return false;
+   return GetFrameView()->CanDrawStrokes();
+ }
+ 
+ SkColor BrowserTabStripController::GetFrameColor(
+     BrowserFrameActiveState active_state) const {
++  if (!GetFrameView())
++    return SK_ColorWHITE;
+   return GetFrameView()->GetFrameColor(active_state);
+ }
+ 
+ absl::optional<int> BrowserTabStripController::GetCustomBackgroundId(
+     BrowserFrameActiveState active_state) const {
++  if (!GetFrameView())
++    return absl::nullopt;
+   return GetFrameView()->GetCustomBackgroundId(active_state);
+ }
+ 
+diff --git chrome/browser/ui/views/toolbar/toolbar_view.cc chrome/browser/ui/views/toolbar/toolbar_view.cc
+index 26de912e300e9..c3761d1cb060c 100644
+--- chrome/browser/ui/views/toolbar/toolbar_view.cc
++++ chrome/browser/ui/views/toolbar/toolbar_view.cc
+@@ -186,7 +186,7 @@ class TabstripLikeBackground : public views::Background {
+   void Paint(gfx::Canvas* canvas, views::View* view) const override {
+     bool painted = TopContainerBackground::PaintThemeCustomImage(canvas, view,
+                                                                  browser_view_);
+-    if (!painted) {
++    if (!painted && browser_view_->frame()->GetFrameView()) {
+       SkColor frame_color =
+           browser_view_->frame()->GetFrameView()->GetFrameColor(
+               BrowserFrameActiveState::kUseCurrent);
+@@ -215,12 +215,13 @@ END_METADATA
+ ////////////////////////////////////////////////////////////////////////////////
+ // ToolbarView, public:
+ 
+-ToolbarView::ToolbarView(Browser* browser, BrowserView* browser_view)
++ToolbarView::ToolbarView(Browser* browser, BrowserView* browser_view,
++                         absl::optional<DisplayMode> display_mode)
+     : AnimationDelegateViews(this),
+       browser_(browser),
+       browser_view_(browser_view),
+       app_menu_icon_controller_(browser->profile(), this),
+-      display_mode_(GetDisplayMode(browser)) {
++      display_mode_(display_mode ? *display_mode : GetDisplayMode(browser)) {
+   SetID(VIEW_ID_TOOLBAR);
+ 
+   container_view_ = AddChildView(std::make_unique<ContainerView>());
+@@ -245,6 +246,19 @@ ToolbarView::~ToolbarView() {
+ }
+ 
+ void ToolbarView::Init() {
++#if BUILDFLAG(ENABLE_CEF)
++  using ToolbarButtonType = cef::BrowserDelegate::ToolbarButtonType;
++  auto button_visible = [this](ToolbarButtonType type) {
++    if (this->browser_->cef_delegate()) {
++      return this->browser_->cef_delegate()->IsToolbarButtonVisible(type);
++    }
++    return true;
++  };
++  #define BUTTON_VISIBLE(type) button_visible(ToolbarButtonType::type)
++#else
++  #define BUTTON_VISIBLE(type) true
++#endif
++
+ #if defined(USE_AURA)
+   // Avoid generating too many occlusion tracking calculation events before this
+   // function returns. The occlusion status will be computed only once once this
+@@ -269,12 +283,13 @@ void ToolbarView::Init() {
+ 
+   auto location_bar = std::make_unique<LocationBarView>(
+       browser_, browser_->profile(), browser_->command_controller(), this,
+-      display_mode_ != DisplayMode::NORMAL);
++      display_mode_ != DisplayMode::NORMAL && !browser_->toolbar_overridden());
+   // Make sure the toolbar shows by default.
+   size_animation_.Reset(1);
+ 
+   std::unique_ptr<DownloadToolbarButtonView> download_button;
+-  if (download::IsDownloadBubbleEnabled(browser_->profile())) {
++  if (download::IsDownloadBubbleEnabled(browser_->profile()) &&
++      BUTTON_VISIBLE(kDownload)) {
+     download_button =
+         std::make_unique<DownloadToolbarButtonView>(browser_view_);
+   }
+@@ -356,8 +371,10 @@ void ToolbarView::Init() {
+     }
+   }
+   std::unique_ptr<media_router::CastToolbarButton> cast;
+-  if (media_router::MediaRouterEnabled(browser_->profile()))
++  if (media_router::MediaRouterEnabled(browser_->profile()) &&
++      BUTTON_VISIBLE(kCast)) {
+     cast = media_router::CastToolbarButton::Create(browser_);
++  }
+ 
+   std::unique_ptr<MediaToolbarButtonView> media_button;
+   if (base::FeatureList::IsEnabled(media::kGlobalMediaControls)) {
+@@ -367,7 +384,8 @@ void ToolbarView::Init() {
+ 
+   std::unique_ptr<send_tab_to_self::SendTabToSelfToolbarIconView>
+       send_tab_to_self_button;
+-  if (!browser_->profile()->IsOffTheRecord()) {
++  if (!browser_->profile()->IsOffTheRecord() &&
++      BUTTON_VISIBLE(kSendTabToSelf)) {
+     send_tab_to_self_button =
+         std::make_unique<send_tab_to_self::SendTabToSelfToolbarIconView>(
+             browser_view_);
+@@ -375,7 +393,7 @@ void ToolbarView::Init() {
+ 
+   std::unique_ptr<SidePanelToolbarButton> side_panel_button;
+   std::unique_ptr<SidePanelToolbarContainer> side_panel_toolbar_container;
+-  if (browser_view_->unified_side_panel()) {
++  if (browser_view_->unified_side_panel() && BUTTON_VISIBLE(kSidePanel)) {
+     if (base::FeatureList::IsEnabled(features::kSidePanelPinning)) {
+       // TODO(b:299463334): Use the new SidePanelContainer which supports
+       // ActionItems
+diff --git chrome/browser/ui/views/toolbar/toolbar_view.h chrome/browser/ui/views/toolbar/toolbar_view.h
+index 2bca1ba1b72eb..f7b0cf9d09e6e 100644
+--- chrome/browser/ui/views/toolbar/toolbar_view.h
++++ chrome/browser/ui/views/toolbar/toolbar_view.h
+@@ -91,7 +91,8 @@ class ToolbarView : public views::AccessiblePaneView,
+                 // needs to be displayed.
+   };
+ 
+-  ToolbarView(Browser* browser, BrowserView* browser_view);
++  ToolbarView(Browser* browser, BrowserView* browser_view,
++              absl::optional<DisplayMode> display_mode);
+   ToolbarView(const ToolbarView&) = delete;
+   ToolbarView& operator=(const ToolbarView&) = delete;
+   ~ToolbarView() override;
+diff --git chrome/browser/ui/web_applications/draggable_region_host_impl.cc chrome/browser/ui/web_applications/draggable_region_host_impl.cc
+index 460a2b08f964b..cb1b67d8b1213 100644
+--- chrome/browser/ui/web_applications/draggable_region_host_impl.cc
++++ chrome/browser/ui/web_applications/draggable_region_host_impl.cc
+@@ -11,6 +11,24 @@
+ #include "chrome/common/chrome_features.h"
+ #include "mojo/public/cpp/bindings/self_owned_receiver.h"
+ 
++namespace {
++
++bool IsSupported(Browser* browser) {
++  if (web_app::AppBrowserController::IsWebApp(browser))
++    return true;
++
++#if BUILDFLAG(ENABLE_CEF)
++  if (browser->cef_delegate() &&
++      browser->cef_delegate()->SupportsDraggableRegion()) {
++    return true;
++  }
++#endif
++
++  return false;
++}
++  
++}  // namespace
++
+ DraggableRegionsHostImpl::DraggableRegionsHostImpl(
+     content::RenderFrameHost& render_frame_host,
+     mojo::PendingReceiver<chrome::mojom::DraggableRegions> receiver)
+@@ -28,7 +46,7 @@ void DraggableRegionsHostImpl::CreateIfAllowed(
+   auto* browser = chrome::FindBrowserWithWebContents(web_contents);
+ 
+   // We only want to bind the receiver for PWAs.
+-  if (!web_app::AppBrowserController::IsWebApp(browser))
++  if (!IsSupported(browser))
+     return;
+ 
+   // The object is bound to the lifetime of |render_frame_host| and the mojo
+@@ -43,7 +61,7 @@ void DraggableRegionsHostImpl::UpdateDraggableRegions(
+   auto* browser = chrome::FindBrowserWithWebContents(web_contents);
+   // When a WebApp browser's WebContents is reparented to a tabbed browser, a
+   // draggable regions update may race with the reparenting logic.
+-  if (!web_app::AppBrowserController::IsWebApp(browser))
++  if (!IsSupported(browser))
+     return;
+ 
+   SkRegion sk_region;
+@@ -56,5 +74,12 @@ void DraggableRegionsHostImpl::UpdateDraggableRegions(
+   }
+ 
+   auto* app_browser_controller = browser->app_controller();
+-  app_browser_controller->UpdateDraggableRegion(sk_region);
++  if (app_browser_controller) {
++    app_browser_controller->UpdateDraggableRegion(sk_region);
++  }
++#if BUILDFLAG(ENABLE_CEF)
++  else {
++    browser->cef_delegate()->UpdateDraggableRegion(sk_region);
++  }
++#endif
+ }
diff --git a/src/patch/patches/chrome_utility_client.patch b/src/patch/patches/chrome_utility_client.patch
new file mode 100644
index 0000000..0612c60
--- /dev/null
+++ b/src/patch/patches/chrome_utility_client.patch
@@ -0,0 +1,22 @@
+diff --git chrome/utility/chrome_content_utility_client.cc chrome/utility/chrome_content_utility_client.cc
+index 6413d01cb4b41..b38eb084d8508 100644
+--- chrome/utility/chrome_content_utility_client.cc
++++ chrome/utility/chrome_content_utility_client.cc
+@@ -13,6 +13,7 @@
+ #include "base/path_service.h"
+ #include "base/task/single_thread_task_runner.h"
+ #include "build/build_config.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/common/chrome_paths.h"
+ #include "chrome/common/profiler/thread_profiler.h"
+ #include "chrome/common/profiler/thread_profiler_configuration.h"
+@@ -57,7 +58,8 @@ void ChromeContentUtilityClient::UtilityThreadStarted() {
+       command_line->GetSwitchValueASCII(switches::kProcessType);
+   // An in-process utility thread may run in other processes, only set up
+   // collector in a utility process.
+-  if (process_type == switches::kUtilityProcess) {
++  if (process_type == switches::kUtilityProcess &&
++      !cef::IsAlloyRuntimeEnabled()) {
+     // The HeapProfilerController should have been created in
+     // ChromeMainDelegate::PostEarlyInitialization.
+     using HeapProfilerController = heap_profiling::HeapProfilerController;
diff --git a/src/patch/patches/chrome_widevine.patch b/src/patch/patches/chrome_widevine.patch
deleted file mode 100644
index c99058e..0000000
--- a/src/patch/patches/chrome_widevine.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff --git third_party/widevine/cdm/BUILD.gn third_party/widevine/cdm/BUILD.gn
-index 1919784f5f93..6a8d2d5140f2 100644
---- third_party/widevine/cdm/BUILD.gn
-+++ third_party/widevine/cdm/BUILD.gn
-@@ -5,6 +5,7 @@
- import("//build/buildflag_header.gni")
- import("//build/config/chrome_build.gni")
- import("//build/config/features.gni")
-+import("//cef/libcef/features/features.gni")
- import("//media/cdm/library_cdm/cdm_paths.gni")
- import("//media/media_options.gni")
- import("//third_party/widevine/cdm/widevine.gni")
diff --git a/src/patch/patches/component_build.patch b/src/patch/patches/component_build.patch
index 3676198..34957e5 100644
--- a/src/patch/patches/component_build.patch
+++ b/src/patch/patches/component_build.patch
@@ -1,37 +1,50 @@
 diff --git content/browser/devtools/devtools_instrumentation.h content/browser/devtools/devtools_instrumentation.h
-index 35726bdf4303..e0da57f2275b 100644
+index 2d570cb3b70c7..4df17e47d3c17 100644
 --- content/browser/devtools/devtools_instrumentation.h
 +++ content/browser/devtools/devtools_instrumentation.h
-@@ -12,6 +12,7 @@
- #include <vector>
- 
- #include "base/optional.h"
-+#include "content/common/content_export.h"
- #include "content/common/navigation_params.mojom.h"
- #include "content/public/browser/certificate_request_result_type.h"
- #include "mojo/public/cpp/bindings/pending_receiver.h"
-@@ -54,7 +55,7 @@ void ApplyNetworkRequestOverrides(FrameTreeNode* frame_tree_node,
-                                   mojom::BeginNavigationParams* begin_params,
-                                   bool* report_raw_headers);
+@@ -109,7 +109,7 @@ bool ApplyUserAgentMetadataOverrides(
+     FrameTreeNode* frame_tree_node,
+     absl::optional<blink::UserAgentMetadata>* override_out);
  
 -bool WillCreateURLLoaderFactory(
 +CONTENT_EXPORT bool WillCreateURLLoaderFactory(
      RenderFrameHostImpl* rfh,
      bool is_navigation,
      bool is_download,
+diff --git content/browser/renderer_host/input/mouse_wheel_phase_handler.h content/browser/renderer_host/input/mouse_wheel_phase_handler.h
+index d69f9d4641613..e88aaf8617c52 100644
+--- content/browser/renderer_host/input/mouse_wheel_phase_handler.h
++++ content/browser/renderer_host/input/mouse_wheel_phase_handler.h
+@@ -9,6 +9,7 @@
+ #include "base/time/time.h"
+ #include "base/timer/timer.h"
+ #include "content/browser/renderer_host/render_widget_host_delegate.h"
++#include "content/common/content_export.h"
+ #include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
+ #include "third_party/blink/public/mojom/input/input_event_result.mojom-shared.h"
+ 
+@@ -51,7 +52,7 @@ enum class FirstScrollUpdateAckState {
+ // The MouseWheelPhaseHandler is responsible for adding the proper phase to
+ // wheel events. Phase information is necessary for wheel scrolling since it
+ // shows the start and end of a scrolling sequence.
+-class MouseWheelPhaseHandler {
++class CONTENT_EXPORT MouseWheelPhaseHandler {
+  public:
+   MouseWheelPhaseHandler(RenderWidgetHostViewBase* const host_view);
+ 
 diff --git content/browser/renderer_host/input/synthetic_gesture_target_base.h content/browser/renderer_host/input/synthetic_gesture_target_base.h
-index a1f57138a24f..f6dd542ab89e 100644
+index 95ce91508908e..94042da4b46bf 100644
 --- content/browser/renderer_host/input/synthetic_gesture_target_base.h
 +++ content/browser/renderer_host/input/synthetic_gesture_target_base.h
-@@ -8,6 +8,7 @@
- #include "base/macros.h"
+@@ -9,6 +9,7 @@
+ #include "base/memory/raw_ptr.h"
  #include "base/time/time.h"
  #include "content/browser/renderer_host/input/synthetic_gesture_target.h"
 +#include "content/common/content_export.h"
  #include "ui/gfx/geometry/point_f.h"
  
  namespace ui {
-@@ -25,7 +26,8 @@ namespace content {
+@@ -26,7 +27,8 @@ namespace content {
  
  class RenderWidgetHostImpl;
  
@@ -40,14 +53,14 @@
 +    public SyntheticGestureTarget {
   public:
    explicit SyntheticGestureTargetBase(RenderWidgetHostImpl* host);
-   ~SyntheticGestureTargetBase() override;
+ 
 diff --git content/common/content_switches_internal.h content/common/content_switches_internal.h
-index 886bdf0edf8f..1d714000cce5 100644
+index 97c7dc7c25000..63c42610bfd9c 100644
 --- content/common/content_switches_internal.h
 +++ content/common/content_switches_internal.h
-@@ -15,7 +15,7 @@ class CommandLine;
+@@ -17,7 +17,7 @@ namespace content {
  
- namespace content {
+ extern const char kFirstRendererProcess[];
  
 -bool IsPinchToZoomEnabled();
 +CONTENT_EXPORT bool IsPinchToZoomEnabled();
@@ -55,79 +68,57 @@
  blink::mojom::V8CacheOptions GetV8CacheOptions();
  
 diff --git third_party/blink/renderer/controller/BUILD.gn third_party/blink/renderer/controller/BUILD.gn
-index ea7f0d6dbdac..d586c2900861 100644
+index 1b0bfc81ebda9..fb5b9f1c1fc1a 100644
 --- third_party/blink/renderer/controller/BUILD.gn
 +++ third_party/blink/renderer/controller/BUILD.gn
-@@ -25,6 +25,7 @@ jumbo_component("controller") {
+@@ -35,6 +35,7 @@ component("controller") {
+   }
  
    configs += [
-     "//build/config/compiler:wexit_time_destructors",
 +    "//cef/libcef/features:config",
      "//third_party/blink/renderer:config",
      "//third_party/blink/renderer:inside_blink",
      "//third_party/blink/renderer:non_test_config",
-@@ -43,6 +44,8 @@ jumbo_component("controller") {
-     "dev_tools_frontend_impl.h",
-     "memory_usage_monitor.cc",
-     "memory_usage_monitor.h",
+@@ -60,6 +61,8 @@ component("controller") {
+     "performance_manager/v8_detailed_memory_reporter_impl.h",
+     "performance_manager/v8_worker_memory_reporter.cc",
+     "performance_manager/v8_worker_memory_reporter.h",
 +    "//cef/libcef/renderer/blink_glue.cc",
 +    "//cef/libcef/renderer/blink_glue.h",
    ]
  
-   if (is_linux) {
+   if (is_linux || is_chromeos) {
 diff --git ui/events/keycodes/BUILD.gn ui/events/keycodes/BUILD.gn
-index 772d0ef90e03..7d6d9aaf8014 100644
+index 9cdd599f0d739..23d1ff5cc30fc 100644
 --- ui/events/keycodes/BUILD.gn
 +++ ui/events/keycodes/BUILD.gn
-@@ -16,6 +16,8 @@ jumbo_source_set("xkb") {
- 
-   public_deps = [ "//ui/base:buildflags" ]
+@@ -19,6 +19,8 @@ source_set("xkb") {
+     "//ui/gfx/x/keysyms",
+   ]
  
 +  defines = [ "KEYCODES_X_IMPLEMENTATION" ]
 +
    deps = [
      "//base",
-     "//ui/events:dom_keycode_converter",
+     "//build:chromeos_buildflags",
 diff --git ui/events/keycodes/keyboard_code_conversion_xkb.h ui/events/keycodes/keyboard_code_conversion_xkb.h
-index a1f9b78704fb..c7d3558251d9 100644
+index 5693e3a1c4bc4..88c0cc6d59098 100644
 --- ui/events/keycodes/keyboard_code_conversion_xkb.h
 +++ ui/events/keycodes/keyboard_code_conversion_xkb.h
 @@ -9,6 +9,7 @@
  
- #include "base/strings/string16.h"
+ 
  #include "ui/events/keycodes/dom/dom_key.h"
 +#include "ui/events/keycodes/keycodes_x_export.h"
  #include "ui/events/keycodes/xkb_keysym.h"
  
  namespace ui {
 @@ -24,7 +25,7 @@ DomKey NonPrintableXKeySymToDomKey(xkb_keysym_t keysym);
- // base::char16 DeadXKeySymToCombiningCharacter(xkb_keysym_t keysym);
+ // char16_t DeadXKeySymToCombiningCharacter(xkb_keysym_t keysym);
  
  // Return the DomKey determined by the XKB layout result (keysym, character).
--DomKey XKeySymToDomKey(xkb_keysym_t keysym, base::char16 character);
-+KEYCODES_X_EXPORT DomKey XKeySymToDomKey(xkb_keysym_t keysym, base::char16 character);
- 
- }  // namespace ui
- 
-diff --git ui/events/keycodes/keysym_to_unicode.h ui/events/keycodes/keysym_to_unicode.h
-index a7983d179832..2bbee48e57ac 100644
---- ui/events/keycodes/keysym_to_unicode.h
-+++ ui/events/keycodes/keysym_to_unicode.h
-@@ -5,6 +5,8 @@
- #ifndef UI_EVENTS_KEYCODES_KEYSYM_TO_UNICODE_H_
- #define UI_EVENTS_KEYCODES_KEYSYM_TO_UNICODE_H_
- 
-+#include "ui/events/keycodes/keycodes_x_export.h"
-+
- #include <stdint.h>
- 
- namespace ui {
-@@ -13,7 +15,7 @@ namespace ui {
- // |keysym| doesn't represent a printable character, returns zero.  We don't
- // support characters outside the Basic Plane, and this function returns zero
- // in that case.
--uint16_t GetUnicodeCharacterFromXKeySym(unsigned long keysym);
-+KEYCODES_X_EXPORT uint16_t GetUnicodeCharacterFromXKeySym(unsigned long keysym);
+-DomKey XKeySymToDomKey(xkb_keysym_t keysym, char16_t character);
++KEYCODES_X_EXPORT DomKey XKeySymToDomKey(xkb_keysym_t keysym, char16_t character);
  
  }  // namespace ui
  
diff --git a/src/patch/patches/content_2015.patch b/src/patch/patches/content_2015.patch
index f649fac..88d0b9d 100644
--- a/src/patch/patches/content_2015.patch
+++ b/src/patch/patches/content_2015.patch
@@ -1,271 +1,82 @@
-diff --git chrome/browser/download/download_target_determiner.cc chrome/browser/download/download_target_determiner.cc
-index 1b5b71193d02..05dad7a969d5 100644
---- chrome/browser/download/download_target_determiner.cc
-+++ chrome/browser/download/download_target_determiner.cc
-@@ -657,7 +657,7 @@ void IsHandledBySafePlugin(int render_process_id,
-   content::PluginService* plugin_service =
-       content::PluginService::GetInstance();
-   bool plugin_found = plugin_service->GetPluginInfo(
--      render_process_id, routing_id, url, url::Origin(), mime_type, false,
-+      render_process_id, routing_id, url, true, url::Origin(), mime_type, false,
-       &is_stale, &plugin_info, &actual_mime_type);
-   if (is_stale && stale_plugin_action == RETRY_IF_STALE_PLUGIN_LIST) {
-     // The GetPlugins call causes the plugin list to be refreshed. Once that's
-diff --git chrome/browser/plugins/chrome_plugin_service_filter.cc chrome/browser/plugins/chrome_plugin_service_filter.cc
-index e46003ea5e4a..503876cf7725 100644
---- chrome/browser/plugins/chrome_plugin_service_filter.cc
-+++ chrome/browser/plugins/chrome_plugin_service_filter.cc
-@@ -163,6 +163,7 @@ bool ChromePluginServiceFilter::IsPluginAvailable(
-     int render_process_id,
-     int render_frame_id,
-     const GURL& plugin_content_url,
-+    bool is_main_frame,
-     const url::Origin& main_frame_origin,
-     content::WebPluginInfo* plugin) {
-   base::AutoLock auto_lock(lock_);
-diff --git chrome/browser/plugins/chrome_plugin_service_filter.h chrome/browser/plugins/chrome_plugin_service_filter.h
-index 937d3d5bc84f..ac327392dcf3 100644
---- chrome/browser/plugins/chrome_plugin_service_filter.h
-+++ chrome/browser/plugins/chrome_plugin_service_filter.h
-@@ -64,6 +64,7 @@ class ChromePluginServiceFilter : public content::PluginServiceFilter,
-   bool IsPluginAvailable(int render_process_id,
-                          int render_frame_id,
-                          const GURL& plugin_content_url,
-+                         bool is_main_frame,
-                          const url::Origin& main_frame_origin,
-                          content::WebPluginInfo* plugin) override;
- 
-diff --git chrome/browser/plugins/pdf_iframe_navigation_throttle.cc chrome/browser/plugins/pdf_iframe_navigation_throttle.cc
-index 5b780f8bf34c..a75d0da983b4 100644
---- chrome/browser/plugins/pdf_iframe_navigation_throttle.cc
-+++ chrome/browser/plugins/pdf_iframe_navigation_throttle.cc
-@@ -65,7 +65,7 @@ bool IsPDFPluginEnabled(content::NavigationHandle* navigation_handle,
- 
-   content::WebPluginInfo plugin_info;
-   return content::PluginService::GetInstance()->GetPluginInfo(
--      process_id, routing_id, navigation_handle->GetURL(),
-+      process_id, routing_id, navigation_handle->GetURL(), false,
-       web_contents->GetMainFrame()->GetLastCommittedOrigin(), kPDFMimeType,
-       false /* allow_wildcard */, is_stale, &plugin_info,
-       nullptr /* actual_mime_type */);
-diff --git chrome/browser/ui/views/frame/browser_root_view.cc chrome/browser/ui/views/frame/browser_root_view.cc
-index 2277ac1008af..db0c90677538 100644
---- chrome/browser/ui/views/frame/browser_root_view.cc
-+++ chrome/browser/ui/views/frame/browser_root_view.cc
-@@ -76,7 +76,7 @@ void OnFindURLMimeType(const GURL& url,
- #if BUILDFLAG(ENABLE_PLUGINS)
-   content::WebPluginInfo plugin;
-   result = result || content::PluginService::GetInstance()->GetPluginInfo(
--                         process_id, routing_id, url, url::Origin(), mime_type,
-+                         process_id, routing_id, url, true, url::Origin(), mime_type,
-                          false, nullptr, &plugin, nullptr);
- #endif
- 
 diff --git content/browser/devtools/devtools_http_handler.cc content/browser/devtools/devtools_http_handler.cc
-index 4956b35c1278..2f9c0621f53e 100644
+index 34cacda8ef225..e0465b8ac1185 100644
 --- content/browser/devtools/devtools_http_handler.cc
 +++ content/browser/devtools/devtools_http_handler.cc
-@@ -571,7 +571,7 @@ void DevToolsHttpHandler::OnJsonRequest(
-     version.SetString("Protocol-Version",
-                       DevToolsAgentHost::GetProtocolVersion());
-     version.SetString("WebKit-Version", GetWebKitVersion());
--    version.SetString("Browser", GetContentClient()->browser()->GetProduct());
-+    version.SetString("Browser", GetContentClient()->browser()->GetChromeProduct());
-     version.SetString("User-Agent",
-                       GetContentClient()->browser()->GetUserAgent());
-     version.SetString("V8-Version", V8_VERSION_STRING);
-diff --git content/browser/frame_host/render_frame_message_filter.cc content/browser/frame_host/render_frame_message_filter.cc
-index f6511e22ab05..0ccf811d7b22 100644
---- content/browser/frame_host/render_frame_message_filter.cc
-+++ content/browser/frame_host/render_frame_message_filter.cc
-@@ -298,6 +298,7 @@ void RenderFrameMessageFilter::OnCreateChildFrame(
- void RenderFrameMessageFilter::OnGetPluginInfo(
-     int render_frame_id,
-     const GURL& url,
-+    bool is_main_frame,
-     const url::Origin& main_frame_origin,
-     const std::string& mime_type,
-     bool* found,
-@@ -305,8 +306,9 @@ void RenderFrameMessageFilter::OnGetPluginInfo(
-     std::string* actual_mime_type) {
-   bool allow_wildcard = true;
-   *found = plugin_service_->GetPluginInfo(
--      render_process_id_, render_frame_id, url, main_frame_origin, mime_type,
--      allow_wildcard, nullptr, info, actual_mime_type);
-+      render_process_id_, render_frame_id, url, is_main_frame,
-+      main_frame_origin, mime_type, allow_wildcard, nullptr, info,
-+      actual_mime_type);
- }
- 
- void RenderFrameMessageFilter::OnOpenChannelToPepperPlugin(
-diff --git content/browser/frame_host/render_frame_message_filter.h content/browser/frame_host/render_frame_message_filter.h
-index 451bfecfa4b1..b7cddcbaca66 100644
---- content/browser/frame_host/render_frame_message_filter.h
-+++ content/browser/frame_host/render_frame_message_filter.h
-@@ -83,6 +83,7 @@ class CONTENT_EXPORT RenderFrameMessageFilter : public BrowserMessageFilter {
- #if BUILDFLAG(ENABLE_PLUGINS)
-   void OnGetPluginInfo(int render_frame_id,
-                        const GURL& url,
-+                       bool is_main_frame,
-                        const url::Origin& main_frame_origin,
-                        const std::string& mime_type,
-                        bool* found,
+@@ -588,7 +588,7 @@ void DevToolsHttpHandler::OnJsonRequest(
+     base::Value::Dict version;
+     version.Set("Protocol-Version", DevToolsAgentHost::GetProtocolVersion());
+     version.Set("WebKit-Version", GetWebKitVersion());
+-    version.Set("Browser", GetContentClient()->browser()->GetProduct());
++    version.Set("Browser", GetContentClient()->browser()->GetChromeProduct());
+     version.Set("User-Agent", GetContentClient()->browser()->GetUserAgent());
+     version.Set("V8-Version", V8_VERSION_STRING);
+     std::string host = info.GetHeaderValue("host");
 diff --git content/browser/loader/navigation_url_loader_impl.cc content/browser/loader/navigation_url_loader_impl.cc
-index 2be5d4400de9..14ece86df0e3 100644
+index 3558cbc360714..267abf8a9abd5 100644
 --- content/browser/loader/navigation_url_loader_impl.cc
 +++ content/browser/loader/navigation_url_loader_impl.cc
-@@ -722,6 +722,13 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
-             resource_request_->has_user_gesture,
-             resource_request_->request_initiator, &loader_factory);
+@@ -753,6 +753,17 @@ NavigationURLLoaderImpl::PrepareForNonInterceptedRequest() {
+           resource_request_->has_user_gesture, initiating_origin,
+           initiator_document_.AsRenderFrameHostIfValid(), &loader_factory);
  
-+        if (!handled) {
-+          handled = GetContentClient()->browser()->HandleExternalProtocol(
-+              web_contents_getter_, frame_tree_node_id_,
-+              navigation_ui_data_.get(), *resource_request_,
-+              &loader_factory);
-+        }
++      if (!handled) {
++        handled = GetContentClient()->browser()->HandleExternalProtocol(
++            web_contents_getter_, frame_tree_node_id_,
++            navigation_ui_data_.get(), request_info_->is_primary_main_frame,
++            FrameTreeNode::GloballyFindByID(frame_tree_node_id_)
++                ->IsInFencedFrameTree(),
++            request_info_->sandbox_flags,
++            *resource_request_, initiating_origin,
++            initiator_document_.AsRenderFrameHostIfValid(), &loader_factory);
++      }
 +
-         if (loader_factory) {
-           factory =
-               base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
-@@ -932,7 +939,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
-         frame_tree_node->current_frame_host()->GetProcess()->GetID();
-     int routing_id = frame_tree_node->current_frame_host()->GetRoutingID();
-     bool has_plugin = PluginService::GetInstance()->GetPluginInfo(
--        render_process_id, routing_id, resource_request_->url, url::Origin(),
-+        render_process_id, routing_id, resource_request_->url, true, url::Origin(),
-         head->mime_type, false /* allow_wildcard */, &stale, &plugin, nullptr);
- 
-     if (stale) {
-diff --git content/browser/plugin_service_impl.cc content/browser/plugin_service_impl.cc
-index 8f0f145f9760..49f0698c89f5 100644
---- content/browser/plugin_service_impl.cc
-+++ content/browser/plugin_service_impl.cc
-@@ -340,6 +340,7 @@ bool PluginServiceImpl::GetPluginInfoArray(
- bool PluginServiceImpl::GetPluginInfo(int render_process_id,
-                                       int render_frame_id,
-                                       const GURL& url,
-+                                      bool is_main_frame,
-                                       const url::Origin& main_frame_origin,
-                                       const std::string& mime_type,
-                                       bool allow_wildcard,
-@@ -357,7 +358,8 @@ bool PluginServiceImpl::GetPluginInfo(int render_process_id,
-   for (size_t i = 0; i < plugins.size(); ++i) {
-     if (!filter_ ||
-         filter_->IsPluginAvailable(render_process_id, render_frame_id, url,
--                                   main_frame_origin, &plugins[i])) {
-+                                   is_main_frame, main_frame_origin,
-+                                   &plugins[i])) {
-       *info = plugins[i];
-       if (actual_mime_type)
-         *actual_mime_type = mime_types[i];
-diff --git content/browser/plugin_service_impl.h content/browser/plugin_service_impl.h
-index 79ac3b705511..71d73d3da158 100644
---- content/browser/plugin_service_impl.h
-+++ content/browser/plugin_service_impl.h
-@@ -54,6 +54,7 @@ class CONTENT_EXPORT PluginServiceImpl : public PluginService {
-   bool GetPluginInfo(int render_process_id,
-                      int render_frame_id,
-                      const GURL& url,
-+                     bool is_main_frame,
-                      const url::Origin& main_frame_origin,
-                      const std::string& mime_type,
-                      bool allow_wildcard,
-diff --git content/browser/renderer_host/plugin_registry_impl.cc content/browser/renderer_host/plugin_registry_impl.cc
-index a6d6188fb139..7ac57de6fd55 100644
---- content/browser/renderer_host/plugin_registry_impl.cc
-+++ content/browser/renderer_host/plugin_registry_impl.cc
-@@ -29,6 +29,7 @@ void PluginRegistryImpl::Bind(
- }
- 
- void PluginRegistryImpl::GetPlugins(bool refresh,
-+                                    bool is_main_frame,
-                                     const url::Origin& main_frame_origin,
-                                     GetPluginsCallback callback) {
-   auto* plugin_service = PluginServiceImpl::GetInstance();
-@@ -50,10 +51,11 @@ void PluginRegistryImpl::GetPlugins(bool refresh,
- 
-   plugin_service->GetPlugins(base::BindOnce(
-       &PluginRegistryImpl::GetPluginsComplete, weak_factory_.GetWeakPtr(),
--      main_frame_origin, std::move(callback)));
-+      is_main_frame, main_frame_origin, std::move(callback)));
- }
- 
- void PluginRegistryImpl::GetPluginsComplete(
-+    bool is_main_frame,
-     const url::Origin& main_frame_origin,
-     GetPluginsCallback callback,
-     const std::vector<WebPluginInfo>& all_plugins) {
-@@ -76,6 +78,7 @@ void PluginRegistryImpl::GetPluginsComplete(
-     // TODO(crbug.com/621724): Pass an url::Origin instead of a GURL.
-     if (!filter || filter->IsPluginAvailable(render_process_id_, routing_id,
-                                              main_frame_origin.GetURL(),
-+                                             is_main_frame,
-                                              main_frame_origin, &plugin)) {
-       auto plugin_blink = blink::mojom::PluginInfo::New();
-       plugin_blink->name = plugin.name;
-diff --git content/browser/renderer_host/plugin_registry_impl.h content/browser/renderer_host/plugin_registry_impl.h
-index 632ae86c6fd6..55b749ec1242 100644
---- content/browser/renderer_host/plugin_registry_impl.h
-+++ content/browser/renderer_host/plugin_registry_impl.h
-@@ -24,11 +24,13 @@ class PluginRegistryImpl : public blink::mojom::PluginRegistry {
- 
-   // blink::mojom::PluginRegistry
-   void GetPlugins(bool refresh,
-+                  bool is_main_frame,
-                   const url::Origin& main_frame_origin,
-                   GetPluginsCallback callback) override;
- 
-  private:
--  void GetPluginsComplete(const url::Origin& main_frame_origin,
-+  void GetPluginsComplete(bool is_main_frame,
-+                          const url::Origin& main_frame_origin,
-                           GetPluginsCallback callback,
-                           const std::vector<WebPluginInfo>& all_plugins);
- 
-diff --git content/common/frame_messages.h content/common/frame_messages.h
-index 118765f9323f..614830e4f406 100644
---- content/common/frame_messages.h
-+++ content/common/frame_messages.h
-@@ -687,9 +687,10 @@ IPC_MESSAGE_ROUTED1(FrameHostMsg_PepperStopsPlayback,
- // type. If there is no matching plugin, |found| is false.
- // |actual_mime_type| is the actual mime type supported by the
- // found plugin.
--IPC_SYNC_MESSAGE_CONTROL4_3(FrameHostMsg_GetPluginInfo,
-+IPC_SYNC_MESSAGE_CONTROL5_3(FrameHostMsg_GetPluginInfo,
-                             int /* render_frame_id */,
-                             GURL /* url */,
-+                            bool /* is_main_frame */,
-                             url::Origin /* main_frame_origin */,
-                             std::string /* mime_type */,
-                             bool /* found */,
+       if (loader_factory) {
+         factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
+             std::move(loader_factory));
 diff --git content/public/browser/content_browser_client.cc content/public/browser/content_browser_client.cc
-index 89f33b33f8c8..30512bab9b12 100644
+index 5733e6d1ea77f..5aa0dffc85def 100644
 --- content/public/browser/content_browser_client.cc
 +++ content/public/browser/content_browser_client.cc
-@@ -9,7 +9,7 @@
- // declarations instead of including more headers. If that is infeasible, adjust
- // the limit. For more info, see
- // https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md
--#pragma clang max_tokens_here 820000
-+// #pragma clang max_tokens_here 820000
+@@ -1060,7 +1060,7 @@ ContentBrowserClient::CreateURLLoaderHandlerForServiceWorkerNavigationPreload(
+ void ContentBrowserClient::OnNetworkServiceCreated(
+     network::mojom::NetworkService* network_service) {}
  
- #include <utility>
+-void ContentBrowserClient::ConfigureNetworkContextParams(
++bool ContentBrowserClient::ConfigureNetworkContextParams(
+     BrowserContext* context,
+     bool in_memory,
+     const base::FilePath& relative_partition_path,
+@@ -1069,6 +1069,7 @@ void ContentBrowserClient::ConfigureNetworkContextParams(
+         cert_verifier_creation_params) {
+   network_context_params->user_agent = GetUserAgentBasedOnPolicy(context);
+   network_context_params->accept_language = "en-us,en";
++  return true;
+ }
  
+ std::vector<base::FilePath>
 diff --git content/public/browser/content_browser_client.h content/public/browser/content_browser_client.h
-index 26cd6d1afcb8..5ac45c794daf 100644
+index 8b4b26ed9f976..6f01db1ae5ef7 100644
 --- content/public/browser/content_browser_client.h
 +++ content/public/browser/content_browser_client.h
-@@ -26,6 +26,7 @@
- #include "content/common/content_export.h"
- #include "content/public/browser/certificate_request_result_type.h"
- #include "content/public/browser/generated_code_cache_settings.h"
+@@ -40,6 +40,7 @@
+ #include "content/public/browser/mojo_binder_policy_map.h"
+ #include "content/public/browser/privacy_sandbox_invoking_api.h"
+ #include "content/public/browser/storage_partition_config.h"
 +#include "content/public/browser/web_contents.h"
+ #include "content/public/common/alternative_error_page_override_info.mojom-forward.h"
  #include "content/public/common/page_visibility_state.h"
- #include "content/public/common/previews_state.h"
  #include "content/public/common/window_container_type.mojom-forward.h"
-@@ -1631,6 +1632,14 @@ class CONTENT_EXPORT ContentBrowserClient {
-       const base::Optional<url::Origin>& initiating_origin,
+@@ -1940,7 +1941,7 @@ class CONTENT_EXPORT ContentBrowserClient {
+   //
+   // If |relative_partition_path| is the empty string, it means this needs to
+   // create the default NetworkContext for the BrowserContext.
+-  virtual void ConfigureNetworkContextParams(
++  virtual bool ConfigureNetworkContextParams(
+       BrowserContext* context,
+       bool in_memory,
+       const base::FilePath& relative_partition_path,
+@@ -2154,6 +2155,19 @@ class CONTENT_EXPORT ContentBrowserClient {
+       RenderFrameHost* initiator_document,
        mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory);
  
 +  // Same as above, but exposing the whole ResourceRequest object.
@@ -273,13 +84,18 @@
 +      WebContents::Getter web_contents_getter,
 +      int frame_tree_node_id,
 +      NavigationUIData* navigation_data,
++      bool is_primary_main_frame,
++      bool is_in_fenced_frame_tree,
++      network::mojom::WebSandboxFlags sandbox_flags,
 +      const network::ResourceRequest& request,
++      const absl::optional<url::Origin>& initiating_origin,
++      RenderFrameHost* initiator_document,
 +      mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) { return false; }
 +
-   // Creates an OverlayWindow to be used for Picture-in-Picture. This window
-   // will house the content shown when in Picture-in-Picture mode. This will
-   // return a new OverlayWindow.
-@@ -1699,6 +1708,10 @@ class CONTENT_EXPORT ContentBrowserClient {
+   // Creates an OverlayWindow to be used for video or Picture-in-Picture.
+   // This window will house the content shown when in Picture-in-Picture mode.
+   // This will return a new OverlayWindow.
+@@ -2210,6 +2224,10 @@ class CONTENT_EXPORT ContentBrowserClient {
    // Used as part of the user agent string.
    virtual std::string GetProduct();
  
@@ -287,38 +103,14 @@
 +  // purposes with external tools like Selenium.
 +  virtual std::string GetChromeProduct() { return GetProduct(); }
 +
-   // Returns the user agent.  Content may cache this value.
+   // Returns the user agent. This can also return the reduced user agent, based
+   // on blink::features::kUserAgentReduction. Content may cache this value.
    virtual std::string GetUserAgent();
- 
-diff --git content/public/browser/plugin_service.h content/public/browser/plugin_service.h
-index dcfd3ff37186..4e822ee5f750 100644
---- content/public/browser/plugin_service.h
-+++ content/public/browser/plugin_service.h
-@@ -74,6 +74,7 @@ class CONTENT_EXPORT PluginService {
-   virtual bool GetPluginInfo(int render_process_id,
-                              int render_frame_id,
-                              const GURL& url,
-+                             bool is_main_frame,
-                              const url::Origin& main_frame_origin,
-                              const std::string& mime_type,
-                              bool allow_wildcard,
-diff --git content/public/browser/plugin_service_filter.h content/public/browser/plugin_service_filter.h
-index 98c59005599e..69752184745d 100644
---- content/public/browser/plugin_service_filter.h
-+++ content/public/browser/plugin_service_filter.h
-@@ -32,6 +32,7 @@ class PluginServiceFilter {
-   virtual bool IsPluginAvailable(int render_process_id,
-                                  int render_frame_id,
-                                  const GURL& url,
-+                                 bool is_main_frame,
-                                  const url::Origin& main_frame_origin,
-                                  WebPluginInfo* plugin) = 0;
- 
 diff --git content/public/renderer/content_renderer_client.h content/public/renderer/content_renderer_client.h
-index 764556d80f1b..7267aa6c26f6 100644
+index a4130ad4dc815..b303f6c8768b7 100644
 --- content/public/renderer/content_renderer_client.h
 +++ content/public/renderer/content_renderer_client.h
-@@ -81,6 +81,9 @@ class CONTENT_EXPORT ContentRendererClient {
+@@ -96,6 +96,9 @@ class CONTENT_EXPORT ContentRendererClient {
    // binding requests from RenderProcessHost::BindReceiver().
    virtual void ExposeInterfacesToBrowser(mojo::BinderMap* binders) {}
  
@@ -328,7 +120,7 @@
    // Notifies that a new RenderFrame has been created.
    virtual void RenderFrameCreated(RenderFrame* render_frame) {}
  
-@@ -310,6 +313,10 @@ class CONTENT_EXPORT ContentRendererClient {
+@@ -318,6 +321,10 @@ class CONTENT_EXPORT ContentRendererClient {
    // This method may invalidate the frame.
    virtual void RunScriptsAtDocumentIdle(RenderFrame* render_frame) {}
  
@@ -339,38 +131,24 @@
    // Allows subclasses to enable some runtime features before Blink has
    // started.
    virtual void SetRuntimeFeaturesDefaultsBeforeBlinkInitialization() {}
-diff --git content/renderer/render_frame_impl.cc content/renderer/render_frame_impl.cc
-index 2ab5e79b71cc..51cd9556a884 100644
---- content/renderer/render_frame_impl.cc
-+++ content/renderer/render_frame_impl.cc
-@@ -3742,7 +3742,8 @@ blink::WebPlugin* RenderFrameImpl::CreatePlugin(
-   std::string mime_type;
-   bool found = false;
-   Send(new FrameHostMsg_GetPluginInfo(
--      routing_id_, params.url, frame_->Top()->GetSecurityOrigin(),
-+      routing_id_, params.url, frame_->Parent() == nullptr,
-+      frame_->Top()->GetSecurityOrigin(),
-       params.mime_type.Utf8(), &found, &info, &mime_type));
-   if (!found)
-     return nullptr;
 diff --git content/renderer/render_thread_impl.cc content/renderer/render_thread_impl.cc
-index 76176518dfe4..b7d8dc75a23a 100644
+index 3c3ebfeec280e..b239506a39b43 100644
 --- content/renderer/render_thread_impl.cc
 +++ content/renderer/render_thread_impl.cc
-@@ -630,6 +630,8 @@ void RenderThreadImpl::Init() {
+@@ -584,6 +584,8 @@ void RenderThreadImpl::Init() {
        GetContentClient()->renderer()->CreateURLLoaderThrottleProvider(
-           URLLoaderThrottleProviderType::kFrame);
+           blink::URLLoaderThrottleProviderType::kFrame);
  
 +  GetContentClient()->renderer()->RenderThreadConnected();
 +
-   GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating(
-       &RenderThreadImpl::OnRendererInterfaceReceiver, base::Unretained(this)));
- 
+   GetAssociatedInterfaceRegistry()->AddInterface<mojom::Renderer>(
+       base::BindRepeating(&RenderThreadImpl::OnRendererInterfaceReceiver,
+                           base::Unretained(this)));
 diff --git content/renderer/renderer_blink_platform_impl.cc content/renderer/renderer_blink_platform_impl.cc
-index 8c641e6e3a6f..d2d1a7c2b6de 100644
+index 4ed1a50637e40..ce57912529596 100644
 --- content/renderer/renderer_blink_platform_impl.cc
 +++ content/renderer/renderer_blink_platform_impl.cc
-@@ -899,6 +899,15 @@ RendererBlinkPlatformImpl::GetGpuFactories() {
+@@ -941,6 +941,15 @@ SkBitmap* RendererBlinkPlatformImpl::GetSadPageBitmap() {
  
  //------------------------------------------------------------------------------
  
@@ -383,68 +161,88 @@
 +
 +//------------------------------------------------------------------------------
 +
- blink::mojom::CodeCacheHost& RendererBlinkPlatformImpl::GetCodeCacheHost() {
-   if (!code_cache_host_) {
-     code_cache_host_ = mojo::SharedRemote<blink::mojom::CodeCacheHost>(
+ std::unique_ptr<blink::WebV8ValueConverter>
+ RendererBlinkPlatformImpl::CreateWebV8ValueConverter() {
+   return std::make_unique<V8ValueConverterImpl>();
 diff --git content/renderer/renderer_blink_platform_impl.h content/renderer/renderer_blink_platform_impl.h
-index 80490f5b8d52..8c07dc87edbb 100644
+index 84c36d410a352..7904a0050e3bb 100644
 --- content/renderer/renderer_blink_platform_impl.h
 +++ content/renderer/renderer_blink_platform_impl.h
-@@ -198,6 +198,9 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
- 
-   media::GpuVideoAcceleratorFactories* GetGpuFactories() override;
+@@ -225,6 +225,9 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
+   InertAndMinimumIntervalOfUserLevelMemoryPressureSignal() override;
+ #endif  // BUILDFLAG(IS_ANDROID)
  
 +  void DevToolsAgentAttached() override;
 +  void DevToolsAgentDetached() override;
 +
-   // Returns non-null.
-   // It is invalid to call this in an incomplete env where
-   // RenderThreadImpl::current() returns nullptr (e.g. in some tests).
-diff --git content/shell/browser/shell_plugin_service_filter.cc content/shell/browser/shell_plugin_service_filter.cc
-index 427132c6920e..4809ddaf21e1 100644
---- content/shell/browser/shell_plugin_service_filter.cc
-+++ content/shell/browser/shell_plugin_service_filter.cc
-@@ -17,6 +17,7 @@ bool ShellPluginServiceFilter::IsPluginAvailable(
-     int render_process_id,
-     int render_frame_id,
-     const GURL& url,
-+    bool is_main_frame,
-     const url::Origin& main_frame_origin,
-     WebPluginInfo* plugin) {
-   return plugin->name == base::ASCIIToUTF16("Blink Test Plugin") ||
-diff --git content/shell/browser/shell_plugin_service_filter.h content/shell/browser/shell_plugin_service_filter.h
-index 337b4b0653fe..107ab4c9d8a8 100644
---- content/shell/browser/shell_plugin_service_filter.h
-+++ content/shell/browser/shell_plugin_service_filter.h
-@@ -20,6 +20,7 @@ class ShellPluginServiceFilter : public PluginServiceFilter {
-   bool IsPluginAvailable(int render_process_id,
-                          int render_frame_id,
-                          const GURL& url,
-+                         bool is_main_frame,
-                          const url::Origin& main_frame_origin,
-                          WebPluginInfo* plugin) override;
+   // Tells this platform that the renderer is locked to a site (i.e., a scheme
+   // plus eTLD+1, such as https://google.com), or to a more specific origin.
+   void SetIsLockedToSite();
+diff --git content/shell/browser/shell_content_browser_client.cc content/shell/browser/shell_content_browser_client.cc
+index 0008e3c7c9600..e639ae5373af0 100644
+--- content/shell/browser/shell_content_browser_client.cc
++++ content/shell/browser/shell_content_browser_client.cc
+@@ -685,7 +685,7 @@ void ShellContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
+ #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
+         // BUILDFLAG(IS_ANDROID)
  
-diff --git content/test/fake_plugin_service.cc content/test/fake_plugin_service.cc
-index eb280cd21c6d..b499b2536b2d 100644
---- content/test/fake_plugin_service.cc
-+++ content/test/fake_plugin_service.cc
-@@ -28,6 +28,7 @@ bool FakePluginService::GetPluginInfoArray(
- bool FakePluginService::GetPluginInfo(int render_process_id,
-                                       int render_frame_id,
-                                       const GURL& url,
-+                                      bool is_main_frame,
-                                       const url::Origin& main_frame_origin,
-                                       const std::string& mime_type,
-                                       bool allow_wildcard,
-diff --git content/test/fake_plugin_service.h content/test/fake_plugin_service.h
-index df49da7cbec0..edf526fff7f8 100644
---- content/test/fake_plugin_service.h
-+++ content/test/fake_plugin_service.h
-@@ -29,6 +29,7 @@ class FakePluginService : public PluginService {
-   bool GetPluginInfo(int render_process_id,
-                      int render_frame_id,
-                      const GURL& url,
-+                     bool is_main_frame,
-                      const url::Origin& main_frame_origin,
-                      const std::string& mime_type,
-                      bool allow_wildcard,
+-void ShellContentBrowserClient::ConfigureNetworkContextParams(
++bool ShellContentBrowserClient::ConfigureNetworkContextParams(
+     BrowserContext* context,
+     bool in_memory,
+     const base::FilePath& relative_partition_path,
+@@ -694,6 +694,7 @@ void ShellContentBrowserClient::ConfigureNetworkContextParams(
+         cert_verifier_creation_params) {
+   ConfigureNetworkContextParamsForShell(context, network_context_params,
+                                         cert_verifier_creation_params);
++  return true;
+ }
+ 
+ std::vector<base::FilePath>
+diff --git content/shell/browser/shell_content_browser_client.h content/shell/browser/shell_content_browser_client.h
+index b33300b6da3ea..fb7d4c5f7b029 100644
+--- content/shell/browser/shell_content_browser_client.h
++++ content/shell/browser/shell_content_browser_client.h
+@@ -137,7 +137,7 @@ class ShellContentBrowserClient : public ContentBrowserClient {
+ #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
+         // BUILDFLAG(IS_ANDROID)
+   device::GeolocationManager* GetGeolocationManager() override;
+-  void ConfigureNetworkContextParams(
++  bool ConfigureNetworkContextParams(
+       BrowserContext* context,
+       bool in_memory,
+       const base::FilePath& relative_partition_path,
+diff --git headless/lib/browser/headless_content_browser_client.cc headless/lib/browser/headless_content_browser_client.cc
+index 8d5fc50c9d528..7692150fb9ce0 100644
+--- headless/lib/browser/headless_content_browser_client.cc
++++ headless/lib/browser/headless_content_browser_client.cc
+@@ -294,7 +294,7 @@ bool HeadlessContentBrowserClient::IsSharedStorageSelectURLAllowed(
+   return true;
+ }
+ 
+-void HeadlessContentBrowserClient::ConfigureNetworkContextParams(
++bool HeadlessContentBrowserClient::ConfigureNetworkContextParams(
+     content::BrowserContext* context,
+     bool in_memory,
+     const base::FilePath& relative_partition_path,
+@@ -304,6 +304,7 @@ void HeadlessContentBrowserClient::ConfigureNetworkContextParams(
+   HeadlessBrowserContextImpl::From(context)->ConfigureNetworkContextParams(
+       in_memory, relative_partition_path, network_context_params,
+       cert_verifier_creation_params);
++  return true;
+ }
+ 
+ std::string HeadlessContentBrowserClient::GetProduct() {
+diff --git headless/lib/browser/headless_content_browser_client.h headless/lib/browser/headless_content_browser_client.h
+index dfdef1bdae542..af36779ca0ed6 100644
+--- headless/lib/browser/headless_content_browser_client.h
++++ headless/lib/browser/headless_content_browser_client.h
+@@ -80,7 +80,7 @@ class HeadlessContentBrowserClient : public content::ContentBrowserClient {
+       const url::Origin& top_frame_origin,
+       const url::Origin& accessing_origin) override;
+ 
+-  void ConfigureNetworkContextParams(
++  bool ConfigureNetworkContextParams(
+       content::BrowserContext* context,
+       bool in_memory,
+       const base::FilePath& relative_partition_path,
diff --git a/src/patch/patches/content_app_shutdown_2798.patch b/src/patch/patches/content_app_shutdown_2798.patch
deleted file mode 100644
index 3ed48d5..0000000
--- a/src/patch/patches/content_app_shutdown_2798.patch
+++ /dev/null
@@ -1,73 +0,0 @@
-diff --git content/app/content_main_runner_impl.cc content/app/content_main_runner_impl.cc
-index bb72915a26e2..9fbafc0643e1 100644
---- content/app/content_main_runner_impl.cc
-+++ content/app/content_main_runner_impl.cc
-@@ -44,6 +44,7 @@
- #include "base/strings/stringprintf.h"
- #include "base/task/post_task.h"
- #include "base/task/thread_pool/thread_pool_instance.h"
-+#include "base/threading/thread_restrictions.h"
- #include "base/trace_event/trace_event.h"
- #include "components/discardable_memory/service/discardable_shared_memory_manager.h"
- #include "components/download/public/common/download_task_runner.h"
-@@ -1016,6 +1017,11 @@ void ContentMainRunnerImpl::Shutdown() {
-   is_shutdown_ = true;
- }
- 
-+void ContentMainRunnerImpl::ShutdownOnUIThread() {
-+  base::ScopedAllowBaseSyncPrimitivesForTesting allow_wait;
-+  discardable_shared_memory_manager_.reset();
-+}
-+
- // static
- ContentMainRunner* ContentMainRunner::Create() {
-   return ContentMainRunnerImpl::Create();
-diff --git content/app/content_main_runner_impl.h content/app/content_main_runner_impl.h
-index 4632e35eaf65..c74d9ca750c7 100644
---- content/app/content_main_runner_impl.h
-+++ content/app/content_main_runner_impl.h
-@@ -51,6 +51,8 @@ class ContentMainRunnerImpl : public ContentMainRunner {
-   int Run(bool start_service_manager_only) override;
-   void Shutdown() override;
- 
-+  void ShutdownOnUIThread();
-+
-  private:
- #if !defined(CHROME_MULTIPLE_DLL_CHILD)
-   int RunServiceManager(MainFunctionParams& main_function_params,
-diff --git content/app/content_service_manager_main_delegate.cc content/app/content_service_manager_main_delegate.cc
-index 86d0a470a7c2..5e4b91d31e3f 100644
---- content/app/content_service_manager_main_delegate.cc
-+++ content/app/content_service_manager_main_delegate.cc
-@@ -130,4 +130,8 @@ void ContentServiceManagerMainDelegate::SetStartServiceManagerOnly(
-   start_service_manager_only_ = start_service_manager_only;
- }
- 
-+void ContentServiceManagerMainDelegate::ShutdownOnUIThread() {
-+  content_main_runner_->ShutdownOnUIThread();
-+}
-+
- }  // namespace content
-diff --git content/app/content_service_manager_main_delegate.h content/app/content_service_manager_main_delegate.h
-index 0b4042aec2ae..b8643b10a02e 100644
---- content/app/content_service_manager_main_delegate.h
-+++ content/app/content_service_manager_main_delegate.h
-@@ -18,7 +18,8 @@ namespace content {
- 
- class ContentMainRunnerImpl;
- 
--class ContentServiceManagerMainDelegate : public service_manager::MainDelegate {
-+class CONTENT_EXPORT ContentServiceManagerMainDelegate :
-+    public service_manager::MainDelegate {
-  public:
-   explicit ContentServiceManagerMainDelegate(const ContentMainParams& params);
-   ~ContentServiceManagerMainDelegate() override;
-@@ -46,6 +47,8 @@ class ContentServiceManagerMainDelegate : public service_manager::MainDelegate {
-   // full browser.
-   void SetStartServiceManagerOnly(bool start_service_manager_only);
- 
-+  void ShutdownOnUIThread();
-+
-  private:
-   ContentMainParams content_main_params_;
-   std::unique_ptr<ContentMainRunnerImpl> content_main_runner_;
diff --git a/src/patch/patches/content_main_654986.patch b/src/patch/patches/content_main_654986.patch
new file mode 100644
index 0000000..1ac4bae
--- /dev/null
+++ b/src/patch/patches/content_main_654986.patch
@@ -0,0 +1,168 @@
+diff --git content/app/content_main.cc content/app/content_main.cc
+index f70a103a45c6d..e880a7ec4b26c 100644
+--- content/app/content_main.cc
++++ content/app/content_main.cc
+@@ -174,11 +174,8 @@ ContentMainParams::~ContentMainParams() = default;
+ ContentMainParams::ContentMainParams(ContentMainParams&&) = default;
+ ContentMainParams& ContentMainParams::operator=(ContentMainParams&&) = default;
+ 
+-// This function must be marked with NO_STACK_PROTECTOR or it may crash on
+-// return, see the --change-stack-guard-on-fork command line flag.
+-int NO_STACK_PROTECTOR
+-RunContentProcess(ContentMainParams params,
+-                  ContentMainRunner* content_main_runner) {
++int ContentMainInitialize(ContentMainParams params,
++                          ContentMainRunner* content_main_runner) {
+   base::FeatureList::FailOnFeatureAccessWithoutFeatureList();
+ #if BUILDFLAG(IS_CHROMEOS_LACROS)
+   // Lacros is launched with inherited priority. Revert to normal priority
+@@ -186,9 +183,6 @@ RunContentProcess(ContentMainParams params,
+   base::PlatformThread::SetCurrentThreadType(base::ThreadType::kDefault);
+ #endif
+   int exit_code = -1;
+-#if BUILDFLAG(IS_MAC)
+-  base::apple::ScopedNSAutoreleasePool autorelease_pool;
+-#endif
+ 
+   // A flag to indicate whether Main() has been called before. On Android, we
+   // may re-run Main() without restarting the browser process. This flag
+@@ -274,14 +268,6 @@ RunContentProcess(ContentMainParams params,
+ #endif
+ 
+ #if BUILDFLAG(IS_MAC)
+-    // We need this pool for all the objects created before we get to the event
+-    // loop, but we don't want to leave them hanging around until the app quits.
+-    // Each "main" needs to flush this pool right before it goes into its main
+-    // event loop to get rid of the cruft. TODO(https://crbug.com/1424190): This
+-    // is not safe. Each main loop should create and destroy its own pool; it
+-    // should not be flushing the pool at the base of the autorelease pool
+-    // stack.
+-    params.autorelease_pool = &autorelease_pool;
+     InitializeMac();
+ #endif
+ 
+@@ -331,12 +317,46 @@ RunContentProcess(ContentMainParams params,
+ 
+   if (IsSubprocess())
+     CommonSubprocessInit();
+-  exit_code = content_main_runner->Run();
+ 
++  return exit_code;
++}
++
++// This function must be marked with NO_STACK_PROTECTOR or it may crash on
++// return, see the --change-stack-guard-on-fork command line flag.
++int NO_STACK_PROTECTOR
++ContentMainRun(ContentMainRunner* content_main_runner) {
++  return content_main_runner->Run();
++}
++
++void ContentMainShutdown(ContentMainRunner* content_main_runner) {
+ #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
+   content_main_runner->Shutdown();
+ #endif
++}
++
++// This function must be marked with NO_STACK_PROTECTOR or it may crash on
++// return, see the --change-stack-guard-on-fork command line flag.
++int NO_STACK_PROTECTOR
++RunContentProcess(ContentMainParams params,
++                  ContentMainRunner* content_main_runner) {
++#if BUILDFLAG(IS_MAC)
++  // We need this pool for all the objects created before we get to the event
++  // loop, but we don't want to leave them hanging around until the app quits.
++  // Each "main" needs to flush this pool right before it goes into its main
++  // event loop to get rid of the cruft. TODO(https://crbug.com/1424190): This
++  // is not safe. Each main loop should create and destroy its own pool; it
++  // should not be flushing the pool at the base of the autorelease pool
++  // stack.
++  base::apple::ScopedNSAutoreleasePool autorelease_pool;
++  params.autorelease_pool = &autorelease_pool;
++#endif
++
++  int exit_code = ContentMainInitialize(std::move(params), content_main_runner);
++  if (exit_code >= 0)
++    return exit_code;
++  exit_code = ContentMainRun(content_main_runner);
+ 
++  ContentMainShutdown(content_main_runner);
+   return exit_code;
+ }
+ 
+diff --git content/app/content_main_runner_impl.cc content/app/content_main_runner_impl.cc
+index 965b07bc43847..89da1178ca765 100644
+--- content/app/content_main_runner_impl.cc
++++ content/app/content_main_runner_impl.cc
+@@ -46,6 +46,7 @@
+ #include "base/task/thread_pool/thread_pool_instance.h"
+ #include "base/threading/hang_watcher.h"
+ #include "base/threading/platform_thread.h"
++#include "base/threading/thread_restrictions.h"
+ #include "base/time/time.h"
+ #include "base/trace_event/trace_event.h"
+ #include "build/build_config.h"
+@@ -1338,6 +1339,11 @@ void ContentMainRunnerImpl::Shutdown() {
+   is_shutdown_ = true;
+ }
+ 
++void ContentMainRunnerImpl::ShutdownOnUIThread() {
++  base::ScopedAllowBaseSyncPrimitivesForTesting allow_wait;
++  discardable_shared_memory_manager_.reset();
++}
++
+ // static
+ std::unique_ptr<ContentMainRunner> ContentMainRunner::Create() {
+   return ContentMainRunnerImpl::Create();
+diff --git content/app/content_main_runner_impl.h content/app/content_main_runner_impl.h
+index da60e9346b283..c36effdd7e5ee 100644
+--- content/app/content_main_runner_impl.h
++++ content/app/content_main_runner_impl.h
+@@ -27,7 +27,7 @@ class DiscardableSharedMemoryManager;
+ namespace content {
+ class MojoIpcSupport;
+ 
+-class ContentMainRunnerImpl : public ContentMainRunner {
++class CONTENT_EXPORT ContentMainRunnerImpl : public ContentMainRunner {
+  public:
+   static std::unique_ptr<ContentMainRunnerImpl> Create();
+ 
+@@ -46,6 +46,8 @@ class ContentMainRunnerImpl : public ContentMainRunner {
+   int Run() override;
+   void Shutdown() override;
+ 
++  void ShutdownOnUIThread();
++
+  private:
+   int RunBrowser(MainFunctionParams main_function_params,
+                  bool start_minimal_browser);
+diff --git content/common/set_process_title.cc content/common/set_process_title.cc
+index 283161145d792..9f3f635abdd1c 100644
+--- content/common/set_process_title.cc
++++ content/common/set_process_title.cc
+@@ -54,7 +54,7 @@ void SetProcessTitleFromCommandLine(const char** main_argv) {
+   bool have_argv0 = false;
+ 
+ #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+-  DCHECK_EQ(base::PlatformThread::CurrentId(), getpid());
++  // DCHECK_EQ(base::PlatformThread::CurrentId(), getpid());
+ 
+   if (main_argv)
+     setproctitle_init(main_argv);
+diff --git content/public/app/content_main.h content/public/app/content_main.h
+index 44d9aa44ae430..47f916f566696 100644
+--- content/public/app/content_main.h
++++ content/public/app/content_main.h
+@@ -96,6 +96,13 @@ struct CONTENT_EXPORT ContentMainParams {
+   }
+ };
+ 
++// Split RunContentProcess() into separate stages.
++CONTENT_EXPORT int ContentMainInitialize(
++    ContentMainParams params,
++    ContentMainRunner* content_main_runner);
++CONTENT_EXPORT int ContentMainRun(ContentMainRunner* content_main_runner);
++CONTENT_EXPORT void ContentMainShutdown(ContentMainRunner* content_main_runner);
++
+ CONTENT_EXPORT int RunContentProcess(ContentMainParams params,
+                                      ContentMainRunner* content_main_runner);
+ 
diff --git a/src/patch/patches/content_pepper_flash_1586.patch b/src/patch/patches/content_pepper_flash_1586.patch
deleted file mode 100644
index 3a78939..0000000
--- a/src/patch/patches/content_pepper_flash_1586.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc
-index be208ad722fa..df9c50da18ad 100644
---- content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc
-+++ content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc
-@@ -56,7 +56,7 @@ PepperFlashFileMessageFilter::PepperFlashFileMessageFilter(
-     // will construct a bad path and could provide access to the wrong files.
-     // In this case, |plugin_data_directory_| will remain unset and
-     // |ValidateAndConvertPepperFilePath| will fail.
--    NOTREACHED();
-+    //NOTREACHED();
-   } else {
-     plugin_data_directory_ = GetDataDirName(profile_data_directory).Append(
-         base::FilePath::FromUTF8Unsafe(plugin_name));
diff --git a/src/patch/patches/crashpad_1995.patch b/src/patch/patches/crashpad_1995.patch
index fb06747..48a024e 100644
--- a/src/patch/patches/crashpad_1995.patch
+++ b/src/patch/patches/crashpad_1995.patch
@@ -1,5 +1,5 @@
 diff --git chrome/chrome_elf/BUILD.gn chrome/chrome_elf/BUILD.gn
-index 9b08e23e921b..49182504ae36 100644
+index 37e2d2a50aa2c..bb6ac82cd9cb7 100644
 --- chrome/chrome_elf/BUILD.gn
 +++ chrome/chrome_elf/BUILD.gn
 @@ -7,6 +7,7 @@
@@ -10,7 +10,7 @@
  import("//chrome/process_version_rc_template.gni")
  import("//testing/test.gni")
  
-@@ -104,9 +105,6 @@ source_set("constants") {
+@@ -106,9 +107,6 @@ source_set("constants") {
  
  static_library("crash") {
    sources = [
@@ -20,7 +20,7 @@
      "crash/crash_helper.cc",
      "crash/crash_helper.h",
    ]
-@@ -114,6 +112,7 @@ static_library("crash") {
+@@ -117,6 +115,7 @@ static_library("crash") {
      ":hook_util",
      "//base",  # This needs to go.  DEP of app, crash_keys, client.
      "//base:base_static",  # pe_image
@@ -28,7 +28,7 @@
      "//chrome/install_static:install_static_util",
      "//components/crash/core/app",
      "//components/crash/core/common",  # crash_keys
-@@ -121,6 +120,17 @@ static_library("crash") {
+@@ -124,6 +123,17 @@ static_library("crash") {
      "//content/public/common:result_codes",
      "//third_party/crashpad/crashpad/client",  # DumpWithoutCrash
    ]
@@ -47,7 +47,7 @@
  
  source_set("dll_hash") {
 diff --git chrome/chrome_elf/crash/crash_helper.cc chrome/chrome_elf/crash/crash_helper.cc
-index 42a4bfcdb856..9f674625a155 100644
+index 27a803784eb9e..a8b033f475cb4 100644
 --- chrome/chrome_elf/crash/crash_helper.cc
 +++ chrome/chrome_elf/crash/crash_helper.cc
 @@ -11,12 +11,17 @@
@@ -81,41 +81,48 @@
    g_crash_helper_enabled = true;
    return true;
 diff --git chrome/common/crash_keys.cc chrome/common/crash_keys.cc
-index f9a6c6b6ae2d..3701b4423899 100644
+index 680c8ec662ecf..2c898fc6e1c70 100644
 --- chrome/common/crash_keys.cc
 +++ chrome/common/crash_keys.cc
-@@ -4,6 +4,8 @@
+@@ -6,6 +6,8 @@
  
- #include "chrome/common/crash_keys.h"
+ #include <deque>
  
 +#include <iterator>
 +
  #include "base/base_switches.h"
  #include "base/command_line.h"
- #include "base/logging.h"
-@@ -28,7 +30,7 @@
- namespace crash_keys {
+ #include "base/format_macros.h"
+@@ -100,8 +102,10 @@ void HandleEnableDisableFeatures(const base::CommandLine& command_line) {
+       "commandline-disabled-feature");
+ }
  
++}  // namespace
++
  // Return true if we DON'T want to upload this flag to the crash server.
--static bool IsBoringSwitch(const std::string& flag) {
+-bool IsBoringSwitch(const std::string& flag) {
 +bool IsBoringChromeSwitch(const std::string& flag) {
    static const char* const kIgnoreSwitches[] = {
      switches::kEnableLogging,
      switches::kFlagSwitchesBegin,
-@@ -83,7 +85,7 @@ static bool IsBoringSwitch(const std::string& flag) {
+@@ -159,11 +163,9 @@ bool IsBoringSwitch(const std::string& flag) {
+   return false;
  }
  
+-}  // namespace
+-
  void SetCrashKeysFromCommandLine(const base::CommandLine& command_line) {
--  return SetSwitchesFromCommandLine(command_line, &IsBoringSwitch);
-+  return SetSwitchesFromCommandLine(command_line, &IsBoringChromeSwitch);
+   HandleEnableDisableFeatures(command_line);
+-  SetSwitchesFromCommandLine(command_line, &IsBoringSwitch);
++  SetSwitchesFromCommandLine(command_line, &IsBoringChromeSwitch);
  }
  
  void SetActiveExtensions(const std::set<std::string>& extensions) {
 diff --git chrome/common/crash_keys.h chrome/common/crash_keys.h
-index bcf172e645a2..f879aa745adf 100644
+index d802db81c88ef..f78029680e366 100644
 --- chrome/common/crash_keys.h
 +++ chrome/common/crash_keys.h
-@@ -17,6 +17,10 @@ class CommandLine;
+@@ -16,6 +16,10 @@ class CommandLine;
  
  namespace crash_keys {
  
@@ -126,153 +133,36 @@
  // Sets the kNumSwitches key and the set of keys named using kSwitchFormat based
  // on the given |command_line|.
  void SetCrashKeysFromCommandLine(const base::CommandLine& command_line);
-diff --git components/crash/core/app/breakpad_linux.cc components/crash/core/app/breakpad_linux.cc
-index 192b0a7f137f..d53b90173ae2 100644
---- components/crash/core/app/breakpad_linux.cc
-+++ components/crash/core/app/breakpad_linux.cc
-@@ -28,6 +28,7 @@
- #include "base/base_switches.h"
- #include "base/command_line.h"
- #include "base/debug/dump_without_crashing.h"
-+#include "base/debug/leak_annotations.h"
- #include "base/files/file_path.h"
- #include "base/lazy_instance.h"
- #include "base/linux_util.h"
-@@ -104,6 +105,7 @@ namespace {
- uint64_t g_crash_loop_before_time = 0;
- #else
- const char kUploadURL[] = "https://clients2.google.com/cr/report";
-+const char* g_crash_server_url = kUploadURL;
- #endif
- 
- bool g_is_crash_reporter_enabled = false;
-@@ -717,7 +719,7 @@ bool CrashDone(const MinidumpDescriptor& minidump,
-   info.process_type_length = 7;
-   info.distro = base::g_linux_distro;
-   info.distro_length = my_strlen(base::g_linux_distro);
--  info.upload = upload;
-+  info.upload = upload && g_crash_server_url;
-   info.process_start_time = g_process_start_time;
-   info.oom_size = base::g_oom_size;
-   info.pid = g_pid;
-@@ -1404,7 +1406,7 @@ void ExecUploadProcessOrTerminate(const BreakpadInfo& info,
-     header_content_encoding,
-     header_content_type,
-     post_file,
--    kUploadURL,
-+    g_crash_server_url,
-     "--timeout=10",  // Set a timeout so we don't hang forever.
-     "--tries=1",     // Don't retry if the upload fails.
-     "-O",  // Output reply to the file descriptor path.
-@@ -1744,10 +1746,19 @@ void HandleCrashDump(const BreakpadInfo& info) {
-     GetCrashReporterClient()->GetProductNameAndVersion(&product_name, &version);
- 
-     writer.AddBoundary();
--    writer.AddPairString("prod", product_name);
-+    writer.AddPairString("product", product_name);
-+    writer.AddBoundary();
-+    writer.AddPairString("version", version);
-     writer.AddBoundary();
--    writer.AddPairString("ver", version);
-+
-+#if defined(ARCH_CPU_32_BITS)
-+    const char* platform = "linux32";
-+#elif defined(ARCH_CPU_64_BITS)
-+    const char* platform = "linux64";
-+#endif
-+    writer.AddPairString("platform", platform);
-     writer.AddBoundary();
-+
-     if (info.pid > 0) {
-       char pid_value_buf[kUint64StringSize];
-       uint64_t pid_value_len = my_uint64_len(info.pid);
-@@ -1864,6 +1875,9 @@ void HandleCrashDump(const BreakpadInfo& info) {
-         crash_reporter::internal::TransitionalCrashKeyStorage;
-     CrashKeyStorage::Iterator crash_key_iterator(*info.crash_keys);
-     const CrashKeyStorage::Entry* entry;
-+
-+    crash_reporter::CrashReporterClient::ParameterMap parameters;
-+
-     while ((entry = crash_key_iterator.Next())) {
-       if (g_use_crash_key_white_list && !IsInWhiteList(entry->key))
-         continue;
-@@ -1876,7 +1890,13 @@ void HandleCrashDump(const BreakpadInfo& info) {
-                        ? CrashKeyStorage::value_size - 1
-                        : my_strlen(entry->value);
- 
--      writer.AddPairData(entry->key, key_size, entry->value, value_size);
-+      parameters.insert(std::make_pair(std::string{entry->key, key_size}, std::string{entry->value, value_size}));
-+    }
-+    if (!parameters.empty())
-+      parameters = GetCrashReporterClient()->FilterParameters(parameters);
-+
-+    for (const auto& param : parameters) {
-+      writer.AddPairData(param.first.data(), param.first.size(), param.second.data(), param.second.size());
-       writer.AddBoundary();
-       writer.Flush();
-     }
-@@ -2088,6 +2108,17 @@ void SetChannelCrashKey(const std::string& channel) {
-   channel_key.Set(channel);
- }
- 
-+void SetCrashServerURL(const std::string& url) {
-+  if (url.empty()) {
-+    g_crash_server_url = nullptr;
-+  } else {
-+    char* new_url = new char[url.size() + 1];
-+    ANNOTATE_LEAKING_OBJECT_PTR(new_url);
-+    strcpy(new_url, url.c_str());
-+    g_crash_server_url = new_url;
-+  }
-+}
-+
- #if defined(OS_ANDROID)
- void InitNonBrowserCrashReporterForAndroid(const std::string& process_type) {
-   SanitizationInfo sanitization_info;
-diff --git components/crash/core/app/breakpad_linux.h components/crash/core/app/breakpad_linux.h
-index 9ea80370a842..3043f7d32f33 100644
---- components/crash/core/app/breakpad_linux.h
-+++ components/crash/core/app/breakpad_linux.h
-@@ -20,6 +20,9 @@ extern void InitCrashReporter(const std::string& process_type);
- // Sets the product/distribution channel crash key.
- void SetChannelCrashKey(const std::string& channel);
- 
-+// Set the crash server URL.
-+void SetCrashServerURL(const std::string& url);
-+
- #if defined(OS_ANDROID)
- extern void InitCrashKeysForTesting();
- 
 diff --git components/crash/core/app/crash_reporter_client.cc components/crash/core/app/crash_reporter_client.cc
-index e778f68af30f..d2a2a6bf1f67 100644
+index 3f3ed53d48fc4..05bbc81db0c6a 100644
 --- components/crash/core/app/crash_reporter_client.cc
 +++ components/crash/core/app/crash_reporter_client.cc
-@@ -88,7 +88,7 @@ int CrashReporterClient::GetResultCodeRespawnFailed() {
+@@ -89,7 +89,7 @@ bool CrashReporterClient::GetShouldDumpLargerDumps() {
  }
  #endif
  
--#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS)
-+#if defined(OS_POSIX) && !defined(OS_IOS)
+-#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
++#if BUILDFLAG(IS_POSIX)
  void CrashReporterClient::GetProductNameAndVersion(const char** product_name,
                                                     const char** version) {
  }
-@@ -97,6 +97,7 @@ void CrashReporterClient::GetProductNameAndVersion(std::string* product_name,
+@@ -98,6 +98,7 @@ void CrashReporterClient::GetProductNameAndVersion(std::string* product_name,
                                                     std::string* version,
                                                     std::string* channel) {}
  
-+#if !defined(OS_MACOSX)
++#if !BUILDFLAG(IS_MAC)
  base::FilePath CrashReporterClient::GetReporterLogFilename() {
    return base::FilePath();
  }
-@@ -106,6 +107,7 @@ bool CrashReporterClient::HandleCrashDump(const char* crashdump_filename,
+@@ -107,6 +108,7 @@ bool CrashReporterClient::HandleCrashDump(const char* crashdump_filename,
    return false;
  }
  #endif
 +#endif
  
- #if defined(OS_WIN)
- bool CrashReporterClient::GetCrashDumpLocation(base::string16* crash_dir) {
-@@ -148,6 +150,32 @@ bool CrashReporterClient::ReportingIsEnforcedByPolicy(bool* breakpad_enabled) {
+ #if BUILDFLAG(IS_WIN)
+ bool CrashReporterClient::GetCrashDumpLocation(std::wstring* crash_dir) {
+@@ -141,6 +143,28 @@ bool CrashReporterClient::ReportingIsEnforcedByPolicy(bool* breakpad_enabled) {
    return false;
  }
  
@@ -281,77 +171,68 @@
 +  return false;
 +}
 +
-+std::string CrashReporterClient::GetCrashServerURL() {
-+  return std::string();
-+}
-+
 +void CrashReporterClient::GetCrashOptionalArguments(
 +    std::vector<std::string>* arguments) {
 +}
 +
-+#if defined(OS_WIN)
-+base::string16 CrashReporterClient::GetCrashExternalHandler(
-+    const base::string16& exe_dir) {
++#if BUILDFLAG(IS_WIN)
++std::wstring CrashReporterClient::GetCrashExternalHandler(
++    const std::wstring& exe_dir) {
 +  return exe_dir + L"\\crashpad_handler.exe";
 +}
 +#endif
 +
-+#if defined(OS_MACOSX)
++#if BUILDFLAG(IS_MAC)
 +bool CrashReporterClient::EnableBrowserCrashForwarding() {
 +  return true;
 +}
 +#endif
 +
- #if defined(OS_ANDROID)
+ #if BUILDFLAG(IS_ANDROID)
  unsigned int CrashReporterClient::GetCrashDumpPercentage() {
    return 100;
-@@ -200,9 +228,11 @@ bool CrashReporterClient::ShouldMonitorCrashHandlerExpensively() {
+@@ -197,9 +221,4 @@ bool CrashReporterClient::ShouldMonitorCrashHandlerExpensively() {
    return false;
  }
  
 -bool CrashReporterClient::EnableBreakpadForProcess(
 -    const std::string& process_type) {
 -  return false;
-+#if defined(OS_POSIX) && !defined(OS_MACOSX)
-+CrashReporterClient::ParameterMap
-+CrashReporterClient::FilterParameters(const ParameterMap& parameters) {
-+  return parameters;
- }
-+#endif
- 
+-}
+-
  }  // namespace crash_reporter
 diff --git components/crash/core/app/crash_reporter_client.h components/crash/core/app/crash_reporter_client.h
-index 9cc78fc25840..f54cdbdf2fc4 100644
+index a604df7a5ea6a..618fbde10a65c 100644
 --- components/crash/core/app/crash_reporter_client.h
 +++ components/crash/core/app/crash_reporter_client.h
-@@ -5,7 +5,9 @@
- #ifndef COMPONENTS_CRASH_CORE_APP_CRASH_REPORTER_CLIENT_H_
- #define COMPONENTS_CRASH_CORE_APP_CRASH_REPORTER_CLIENT_H_
+@@ -7,7 +7,9 @@
+ 
+ #include <stdint.h>
  
 +#include <map>
  #include <string>
 +#include <vector>
  
- #include "base/strings/string16.h"
  #include "build/build_config.h"
-@@ -91,7 +93,7 @@ class CrashReporterClient {
-   virtual int GetResultCodeRespawnFailed();
+ 
+@@ -96,7 +98,7 @@ class CrashReporterClient {
+   virtual bool GetShouldDumpLargerDumps();
  #endif
  
--#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS)
-+#if defined(OS_POSIX) && !defined(OS_IOS)
+-#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
++#if BUILDFLAG(IS_POSIX)
    // Returns a textual description of the product type and version to include
    // in the crash report. Neither out parameter should be set to NULL.
    // TODO(jperaza): Remove the 2-parameter overload of this method once all
-@@ -102,6 +104,7 @@ class CrashReporterClient {
+@@ -107,6 +109,7 @@ class CrashReporterClient {
                                          std::string* version,
                                          std::string* channel);
  
-+#if !defined(OS_MACOSX)
++#if !BUILDFLAG(IS_MAC)
    virtual base::FilePath GetReporterLogFilename();
  
    // Custom crash minidump handler after the minidump is generated.
-@@ -111,6 +114,7 @@ class CrashReporterClient {
+@@ -116,6 +119,7 @@ class CrashReporterClient {
    // libc nor allocate memory normally.
    virtual bool HandleCrashDump(const char* crashdump_filename,
                                 uint64_t crash_pid);
@@ -359,42 +240,32 @@
  #endif
  
    // The location where minidump files should be written. Returns true if
-@@ -210,6 +214,30 @@ class CrashReporterClient {
+@@ -213,6 +217,20 @@ class CrashReporterClient {
  
    // Returns true if breakpad should run in the given process type.
    virtual bool EnableBreakpadForProcess(const std::string& process_type);
 +
-+  // Returns the URL for submitting crash reports.
-+  virtual std::string GetCrashServerURL();
-+
 +  // Populate |arguments| with additional optional arguments.
 +  virtual void GetCrashOptionalArguments(std::vector<std::string>* arguments);
 +
-+#if defined(OS_WIN)
++#if BUILDFLAG(IS_WIN)
 +  // Returns the absolute path to the external crash handler exe.
-+  virtual base::string16 GetCrashExternalHandler(const base::string16& exe_dir);
++  virtual std::wstring GetCrashExternalHandler(const std::wstring& exe_dir);
 +#endif
 +
-+#if defined(OS_MACOSX)
++#if BUILDFLAG(IS_MAC)
 +  // Returns true if forwarding of crashes to the system crash reporter is
 +  // enabled for the browser process.
 +  virtual bool EnableBrowserCrashForwarding();
 +#endif
-+
-+#if defined(OS_POSIX) && !defined(OS_MACOSX)
-+  // Provides an oportunity to modify the parameters that will be sent with a
-+  // crash upload.
-+  using ParameterMap = std::map<std::string, std::string>;
-+  virtual ParameterMap FilterParameters(const ParameterMap& parameters);
-+#endif
  };
  
  }  // namespace crash_reporter
 diff --git components/crash/core/app/crashpad.cc components/crash/core/app/crashpad.cc
-index 290b4692c16f..ef91dbdc369d 100644
+index 9ea9021f16006..cf187495ff3f0 100644
 --- components/crash/core/app/crashpad.cc
 +++ components/crash/core/app/crashpad.cc
-@@ -151,7 +151,8 @@ void InitializeCrashpadImpl(bool initial_client,
+@@ -129,7 +129,8 @@ bool InitializeCrashpadImpl(bool initial_client,
    // fallback. Forwarding is turned off for debug-mode builds even for the
    // browser process, because the system's crash reporter can take a very long
    // time to chew on symbols.
@@ -404,18 +275,90 @@
      crashpad::CrashpadInfo::GetCrashpadInfo()
          ->set_system_crash_reporter_forwarding(crashpad::TriState::kDisabled);
    }
+diff --git components/crash/core/app/crashpad_linux.cc components/crash/core/app/crashpad_linux.cc
+index 99efa6b245b99..008eb397332c2 100644
+--- components/crash/core/app/crashpad_linux.cc
++++ components/crash/core/app/crashpad_linux.cc
+@@ -23,6 +23,7 @@
+ #include "components/crash/core/app/crash_reporter_client.h"
+ #include "components/crash/core/app/crash_switches.h"
+ #include "content/public/common/content_descriptors.h"
++#include "content/public/common/content_paths.h"
+ #include "sandbox/linux/services/namespace_sandbox.h"
+ #include "third_party/crashpad/crashpad/client/crashpad_client.h"
+ #include "third_party/crashpad/crashpad/client/crashpad_info.h"
+@@ -107,11 +108,10 @@ bool PlatformCrashpadInitialization(
+     crash_reporter_client->GetCrashDumpLocation(database_path);
+     crash_reporter_client->GetCrashMetricsLocation(&metrics_path);
+ 
++    // Use the same main (default) or subprocess helper exe.
+     base::FilePath handler_path;
+-    if (!base::PathService::Get(base::DIR_EXE, &handler_path)) {
+-      return false;
+-    }
+-    handler_path = handler_path.Append("chrome_crashpad_handler");
++    base::PathService::Get(content::CHILD_PROCESS_EXE, &handler_path);
++    DCHECK(!handler_path.empty());
+ 
+     // When --use-cros-crash-reporter is set (below), the handler passes dumps
+     // to ChromeOS's /sbin/crash_reporter which in turn passes the dump to
+@@ -128,8 +128,8 @@ bool PlatformCrashpadInitialization(
+                                                     &product_version, &channel);
+ 
+     std::map<std::string, std::string> annotations;
+-    annotations["prod"] = product_name;
+-    annotations["ver"] = product_version;
++    annotations["product"] = product_name;
++    annotations["version"] = product_version;
+ 
+ #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+     // Empty means stable.
+@@ -146,7 +146,20 @@ bool PlatformCrashpadInitialization(
+       annotations["channel"] = channel;
+     }
+ 
+-    annotations["plat"] = std::string("Linux");
++#if defined(ARCH_CPU_ARM_FAMILY)
++#if defined(ARCH_CPU_32_BITS)
++    const char* platform = "linuxarm";
++#elif defined(ARCH_CPU_64_BITS)
++    const char* platform = "linuxarm64";
++#endif
++#else
++#if defined(ARCH_CPU_32_BITS)
++    const char* platform = "linux32";
++#elif defined(ARCH_CPU_64_BITS)
++    const char* platform = "linux64";
++#endif
++#endif  // defined(ARCH_CPU_ARM_FAMILY)
++    annotations["platform"] = platform;
+ 
+ #if BUILDFLAG(IS_CHROMEOS_LACROS)
+     // "build_time_millis" is used on LaCros chrome to determine when to stop
+@@ -191,6 +204,12 @@ bool PlatformCrashpadInitialization(
+     }
+ #endif
+ 
++    // Since we're using the same main or subprocess helper exe we must specify
++    // the process type.
++    arguments.push_back(std::string("--type=") + switches::kCrashpadHandler);
++
++    crash_reporter_client->GetCrashOptionalArguments(&arguments);
++
+     CHECK(client.StartHandler(handler_path, *database_path, metrics_path, url,
+                               annotations, arguments, false, false));
+   } else {
 diff --git components/crash/core/app/crashpad_mac.mm components/crash/core/app/crashpad_mac.mm
-index b579521d5586..644756cf710c 100644
+index eb5bcfe0234c3..8963b26806922 100644
 --- components/crash/core/app/crashpad_mac.mm
 +++ components/crash/core/app/crashpad_mac.mm
-@@ -16,12 +16,15 @@
- #include "base/logging.h"
- #include "base/mac/bundle_locations.h"
- #include "base/mac/foundation_util.h"
+@@ -17,11 +17,14 @@
+ #include "base/apple/foundation_util.h"
+ #include "base/check.h"
+ #include "base/files/file_path.h"
 +#include "base/path_service.h"
  #include "base/strings/string_number_conversions.h"
  #include "base/strings/string_piece.h"
- #include "base/strings/stringprintf.h"
  #include "base/strings/sys_string_conversions.h"
  #include "build/branding_buildflags.h"
  #include "components/crash/core/app/crash_reporter_client.h"
@@ -424,18 +367,10 @@
  #include "third_party/crashpad/crashpad/client/crash_report_database.h"
  #include "third_party/crashpad/crashpad/client/crashpad_client.h"
  #include "third_party/crashpad/crashpad/client/crashpad_info.h"
-@@ -37,12 +40,25 @@ namespace {
- std::map<std::string, std::string> GetProcessSimpleAnnotations() {
-   static std::map<std::string, std::string> annotations = []() -> auto {
+@@ -39,15 +42,25 @@ std::map<std::string, std::string> GetProcessSimpleAnnotations() {
      std::map<std::string, std::string> process_annotations;
-+
      @autoreleasepool {
-       NSBundle* outer_bundle = base::mac::OuterBundle();
--      NSString* product = base::mac::ObjCCast<NSString>([outer_bundle
--          objectForInfoDictionaryKey:base::mac::CFToNSCast(kCFBundleNameKey)]);
--      process_annotations["prod"] =
--          base::SysNSStringToUTF8(product).append("_Mac");
-+
+       NSBundle* outer_bundle = base::apple::OuterBundle();
 +      CrashReporterClient* crash_reporter_client = GetCrashReporterClient();
 +      const char* product_name = "";
 +      const char* product_version = "";
@@ -443,28 +378,38 @@
 +                                                      &product_version);
 +
 +      if (strlen(product_name) == 0) {
-+        NSString* product = base::mac::ObjCCast<NSString>([outer_bundle
-+            objectForInfoDictionaryKey:base::mac::CFToNSCast(
-+                kCFBundleNameKey)]);
+ #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+-      process_annotations["prod"] = "Chrome_Mac";
++        process_annotations["product"] = "Chrome_Mac";
+ #else
+-      NSString* product = base::apple::ObjCCast<NSString>(
+-          [outer_bundle objectForInfoDictionaryKey:base::apple::CFToNSPtrCast(
+-                                                       kCFBundleNameKey)]);
+-      process_annotations["prod"] =
+-          base::SysNSStringToUTF8(product).append("_Mac");
++        NSString* product = base::apple::ObjCCast<NSString>(
++            [outer_bundle objectForInfoDictionaryKey:base::apple::CFToNSPtrCast(
++                                                         kCFBundleNameKey)]);
 +        process_annotations["product"] =
 +            base::SysNSStringToUTF8(product).append("_Mac");
+ #endif
 +      } else {
 +        process_annotations["product"] = product_name;
 +      }
  
  #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
        // Empty means stable.
-@@ -58,12 +74,16 @@ std::map<std::string, std::string> GetProcessSimpleAnnotations() {
-         process_annotations["channel"] = "";
+@@ -78,12 +91,20 @@ std::map<std::string, std::string> GetProcessSimpleAnnotations() {
+         }
        }
  
 -      NSString* version =
--          base::mac::ObjCCast<NSString>([base::mac::FrameworkBundle()
+-          base::apple::ObjCCast<NSString>([base::apple::FrameworkBundle()
 -              objectForInfoDictionaryKey:@"CFBundleShortVersionString"]);
 -      process_annotations["ver"] = base::SysNSStringToUTF8(version);
 +      if (strlen(product_version) == 0) {
 +        NSString* version =
-+            base::mac::ObjCCast<NSString>([base::mac::FrameworkBundle()
++            base::apple::ObjCCast<NSString>([base::apple::FrameworkBundle()
 +                objectForInfoDictionaryKey:@"CFBundleShortVersionString"]);
 +        process_annotations["version"] = base::SysNSStringToUTF8(version);
 +      } else {
@@ -472,15 +417,19 @@
 +      }
  
 -      process_annotations["plat"] = std::string("OS X");
++#if defined(ARCH_CPU_ARM64)
++      process_annotations["platform"] = std::string("macosarm64");
++#else
 +      process_annotations["platform"] = std::string("macos");
++#endif
      }  // @autoreleasepool
      return process_annotations;
    }();
-@@ -123,10 +143,10 @@ base::FilePath PlatformCrashpadInitialization(
+@@ -143,10 +164,10 @@ bool PlatformCrashpadInitialization(
  
    if (initial_client) {
      @autoreleasepool {
--      base::FilePath framework_bundle_path = base::mac::FrameworkBundlePath();
+-      base::FilePath framework_bundle_path = base::apple::FrameworkBundlePath();
 -      base::FilePath handler_path =
 -          framework_bundle_path.Append("Helpers").Append(
 -              "chrome_crashpad_handler");
@@ -491,16 +440,7 @@
  
        // Is there a way to recover if this fails?
        CrashReporterClient* crash_reporter_client = GetCrashReporterClient();
-@@ -138,7 +158,7 @@ base::FilePath PlatformCrashpadInitialization(
-       // crash server won't have symbols for any other build types.
-       std::string url = "https://clients2.google.com/cr/report";
- #else
--      std::string url;
-+      std::string url = crash_reporter_client->GetCrashServerURL();
- #endif
- 
-       std::vector<std::string> arguments;
-@@ -161,6 +181,12 @@ base::FilePath PlatformCrashpadInitialization(
+@@ -175,6 +196,12 @@ bool PlatformCrashpadInitialization(
              "--reset-own-crash-exception-port-to-system-default");
        }
  
@@ -511,36 +451,38 @@
 +      crash_reporter_client->GetCrashOptionalArguments(&arguments);
 +
        bool result = GetCrashpadClient().StartHandler(
-           handler_path, database_path, metrics_path, url,
+           handler_path, *database_path, metrics_path, url,
            GetProcessSimpleAnnotations(), arguments, true, false);
 diff --git components/crash/core/app/crashpad_win.cc components/crash/core/app/crashpad_win.cc
-index 669f5bea844d..734163c0aad1 100644
+index 9ab5fb1c82275..740014c1119bd 100644
 --- components/crash/core/app/crashpad_win.cc
 +++ components/crash/core/app/crashpad_win.cc
 @@ -36,8 +36,8 @@ void GetPlatformCrashpadAnnotations(
-   base::string16 product_name, version, special_build, channel_name;
+   std::wstring product_name, version, special_build, channel_name;
    crash_reporter_client->GetProductNameAndVersion(
        exe_file, &product_name, &version, &special_build, &channel_name);
--  (*annotations)["prod"] = base::UTF16ToUTF8(product_name);
--  (*annotations)["ver"] = base::UTF16ToUTF8(version);
-+  (*annotations)["product"] = base::UTF16ToUTF8(product_name);
-+  (*annotations)["version"] = base::UTF16ToUTF8(version);
+-  (*annotations)["prod"] = base::WideToUTF8(product_name);
+-  (*annotations)["ver"] = base::WideToUTF8(version);
++  (*annotations)["product"] = base::WideToUTF8(product_name);
++  (*annotations)["version"] = base::WideToUTF8(version);
  #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
    // Empty means stable.
    const bool allow_empty_channel = true;
-@@ -49,9 +49,9 @@ void GetPlatformCrashpadAnnotations(
+@@ -54,9 +54,11 @@ void GetPlatformCrashpadAnnotations(
    if (!special_build.empty())
-     (*annotations)["special"] = base::UTF16ToUTF8(special_build);
+     (*annotations)["special"] = base::WideToUTF8(special_build);
  #if defined(ARCH_CPU_X86)
 -  (*annotations)["plat"] = std::string("Win32");
 +  (*annotations)["platform"] = std::string("win32");
  #elif defined(ARCH_CPU_X86_64)
 -  (*annotations)["plat"] = std::string("Win64");
 +  (*annotations)["platform"] = std::string("win64");
++#elif defined(ARCH_CPU_ARM64)
++  (*annotations)["platform"] = std::string("winarm64");
  #endif
  }
  
-@@ -66,7 +66,9 @@ base::FilePath PlatformCrashpadInitialization(
+@@ -71,7 +73,9 @@ bool PlatformCrashpadInitialization(
    base::FilePath metrics_path;  // Only valid in the browser process.
  
    const char kPipeNameVar[] = "CHROME_CRASHPAD_PIPE_NAME";
@@ -550,24 +492,19 @@
    std::unique_ptr<base::Environment> env(base::Environment::Create());
  
    CrashReporterClient* crash_reporter_client = GetCrashReporterClient();
-@@ -87,13 +89,13 @@ base::FilePath PlatformCrashpadInitialization(
+@@ -94,9 +98,11 @@ bool PlatformCrashpadInitialization(
  
- #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-     std::string url = "https://clients2.google.com/cr/report";
--#else
--    std::string url;
--#endif
+     std::string url = crash_reporter_client->GetUploadUrl();
  
++#if defined(GOOGLE_CHROME_BUILD)
      // Allow the crash server to be overridden for testing. If the variable
      // isn't present in the environment then the default URL will remain.
      env->GetVar(kServerUrlVar, &url);
-+#else
-+    std::string url = crash_reporter_client->GetCrashServerURL();
 +#endif
  
      base::FilePath exe_file(exe_path);
      if (exe_file.empty()) {
-@@ -104,13 +106,14 @@ base::FilePath PlatformCrashpadInitialization(
+@@ -107,13 +113,14 @@ bool PlatformCrashpadInitialization(
        exe_file = base::FilePath(exe_file_path);
      }
  
@@ -587,7 +524,7 @@
        if (!user_data_dir.empty()) {
          start_arguments.push_back(std::string("--user-data-dir=") +
                                    user_data_dir);
-@@ -121,9 +124,12 @@ base::FilePath PlatformCrashpadInitialization(
+@@ -124,9 +131,12 @@ bool PlatformCrashpadInitialization(
        start_arguments.push_back("/prefetch:7");
      } else {
        base::FilePath exe_dir = exe_file.DirName();
diff --git a/src/patch/patches/crashpad_tp_1995.patch b/src/patch/patches/crashpad_tp_1995.patch
index 1ece692..031e5a6 100644
--- a/src/patch/patches/crashpad_tp_1995.patch
+++ b/src/patch/patches/crashpad_tp_1995.patch
@@ -1,8 +1,8 @@
 diff --git third_party/crashpad/crashpad/client/prune_crash_reports.cc third_party/crashpad/crashpad/client/prune_crash_reports.cc
-index 8eed18d4944c..3e1fb7ac3ba5 100644
+index 077694f541d57..928a520485414 100644
 --- third_party/crashpad/crashpad/client/prune_crash_reports.cc
 +++ third_party/crashpad/crashpad/client/prune_crash_reports.cc
-@@ -72,13 +72,19 @@ size_t PruneCrashReportDatabase(CrashReportDatabase* database,
+@@ -75,13 +75,19 @@ size_t PruneCrashReportDatabase(CrashReportDatabase* database,
  }
  
  // static
@@ -26,10 +26,10 @@
  
  static const time_t kSecondsInDay = 60 * 60 * 24;
 diff --git third_party/crashpad/crashpad/client/prune_crash_reports.h third_party/crashpad/crashpad/client/prune_crash_reports.h
-index 07a70980f12a..ddf7f17325fe 100644
+index b362e0aadbadd..1588232a6e4d4 100644
 --- third_party/crashpad/crashpad/client/prune_crash_reports.h
 +++ third_party/crashpad/crashpad/client/prune_crash_reports.h
-@@ -59,7 +59,8 @@ class PruneCondition {
+@@ -58,7 +58,8 @@ class PruneCondition {
    //! of 128 MB.
    //!
    //! \return A PruneCondition for use with PruneCrashReportDatabase().
@@ -40,19 +40,19 @@
    virtual ~PruneCondition() {}
  
 diff --git third_party/crashpad/crashpad/client/settings.cc third_party/crashpad/crashpad/client/settings.cc
-index db9dface43f8..e5bdfebf8403 100644
+index 5e4119e2175c7..e66600089be04 100644
 --- third_party/crashpad/crashpad/client/settings.cc
 +++ third_party/crashpad/crashpad/client/settings.cc
-@@ -86,7 +86,7 @@ void ScopedLockedFileHandleTraits::Free(FileHandle handle) {
+@@ -117,7 +117,7 @@ void ScopedLockedFileHandleTraits::Free(FileHandle handle) {
  
  struct Settings::Data {
-   static const uint32_t kSettingsMagic = 'CPds';
--  static const uint32_t kSettingsVersion = 1;
-+  static const uint32_t kSettingsVersion = 2;
+   static constexpr uint32_t kSettingsMagic = 'CPds';
+-  static constexpr uint32_t kSettingsVersion = 1;
++  static constexpr uint32_t kSettingsVersion = 2;
  
    enum Options : uint32_t {
      kUploadsEnabled = 1 << 0,
-@@ -97,6 +97,9 @@ struct Settings::Data {
+@@ -128,6 +128,9 @@ struct Settings::Data {
             options(0),
             padding_0(0),
             last_upload_attempt_time(0),
@@ -62,7 +62,7 @@
             client_id() {}
  
    uint32_t magic;
-@@ -104,6 +107,9 @@ struct Settings::Data {
+@@ -135,6 +138,9 @@ struct Settings::Data {
    uint32_t options;
    uint32_t padding_0;
    int64_t last_upload_attempt_time;  // time_t
@@ -72,9 +72,9 @@
    UUID client_id;
  };
  
-@@ -187,6 +193,56 @@ bool Settings::SetLastUploadAttemptTime(time_t time) {
-   return WriteSettings(handle.get(), settings);
+@@ -234,6 +240,56 @@ bool Settings::IsLockExpired(const base::FilePath& file_path,
  }
+ #endif  // !CRASHPAD_FLOCK_ALWAYS_SUPPORTED
  
 +bool Settings::GetNextUploadAttemptTime(time_t* time) {
 +  DCHECK(initialized_.is_valid());
@@ -128,14 +128,14 @@
 +
  // static
  Settings::ScopedLockedFileHandle Settings::MakeScopedLockedFileHandle(
-     FileHandle file,
+     const internal::MakeScopedLockedFileHandleOptions& options,
 diff --git third_party/crashpad/crashpad/client/settings.h third_party/crashpad/crashpad/client/settings.h
-index 5761c6b965b5..aee4e6c96033 100644
+index 39b2de869d225..5a4e621c650ee 100644
 --- third_party/crashpad/crashpad/client/settings.h
 +++ third_party/crashpad/crashpad/client/settings.h
-@@ -115,6 +115,11 @@ class Settings {
-   //!     error logged.
-   bool SetLastUploadAttemptTime(time_t time);
+@@ -156,6 +156,11 @@ class Settings {
+                             time_t lockfile_ttl);
+ #endif  // !CRASHPAD_FLOCK_ALWAYS_SUPPORTED
  
 +  bool GetNextUploadAttemptTime(time_t* time);
 +  bool SetNextUploadAttemptTime(time_t time);
@@ -146,7 +146,7 @@
    struct Data;
  
 diff --git third_party/crashpad/crashpad/handler/BUILD.gn third_party/crashpad/crashpad/handler/BUILD.gn
-index ff9f5d1f2c47..c7935c4d65a7 100644
+index a2d6f7fb482a7..a5b6ae04f897b 100644
 --- third_party/crashpad/crashpad/handler/BUILD.gn
 +++ third_party/crashpad/crashpad/handler/BUILD.gn
 @@ -12,6 +12,7 @@
@@ -157,7 +157,7 @@
  import("../build/crashpad_buildconfig.gni")
  
  static_library("handler") {
-@@ -74,6 +75,17 @@ static_library("handler") {
+@@ -61,6 +62,17 @@ static_library("handler") {
      ]
    }
  
@@ -175,19 +175,19 @@
    public_configs = [ "..:crashpad_config" ]
  
    public_deps = [
-@@ -86,6 +98,7 @@ static_library("handler") {
-     "../minidump",
+@@ -76,6 +88,7 @@ static_library("handler") {
      "../snapshot",
+     "../third_party/mini_chromium:chromeos_buildflags",
      "../tools:tool_support",
 +    "//cef/libcef/features",
    ]
  
    if (crashpad_is_win) {
 diff --git third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc
-index e144bddc67d1..f3d727d0b247 100644
+index 5bd2889eda975..bf3ff4bfcf5c8 100644
 --- third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc
 +++ third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc
-@@ -262,6 +262,8 @@ CrashReportUploadThread::UploadResult CrashReportUploadThread::UploadReport(
+@@ -297,6 +297,8 @@ CrashReportUploadThread::UploadResult CrashReportUploadThread::UploadReport(
    if (minidump_process_snapshot.Initialize(reader)) {
      parameters =
          BreakpadHTTPFormParametersFromMinidump(&minidump_process_snapshot);
@@ -197,27 +197,27 @@
  
    if (!reader->SeekSet(start_offset)) {
 diff --git third_party/crashpad/crashpad/handler/crash_report_upload_thread.h third_party/crashpad/crashpad/handler/crash_report_upload_thread.h
-index 2ec1147d2620..8ff9a72e0bd7 100644
+index 22bb26e31893b..87c80604e5f7a 100644
 --- third_party/crashpad/crashpad/handler/crash_report_upload_thread.h
 +++ third_party/crashpad/crashpad/handler/crash_report_upload_thread.h
-@@ -15,6 +15,7 @@
- #ifndef CRASHPAD_HANDLER_CRASH_REPORT_UPLOAD_THREAD_H_
+@@ -16,6 +16,7 @@
  #define CRASHPAD_HANDLER_CRASH_REPORT_UPLOAD_THREAD_H_
  
+ #include <functional>
 +#include <map>
  #include <memory>
  #include <string>
- 
-@@ -103,7 +104,7 @@ class CrashReportUploadThread : public WorkerThread::Delegate,
-   //! It is expected to only be called from the same thread that called Start().
-   void Stop() override;
+ #include <unordered_map>
+@@ -128,7 +129,7 @@ class CrashReportUploadThread : public WorkerThread::Delegate,
+   //! \return `true` if the thread is running, `false` if it is not.
+   bool is_running() const { return thread_.is_running(); }
  
 - private:
 + protected:
    //! \brief The result code from UploadReport().
    enum class UploadResult {
      //! \brief The crash report was uploaded successfully.
-@@ -131,7 +132,7 @@ class CrashReportUploadThread : public WorkerThread::Delegate,
+@@ -156,7 +157,7 @@ class CrashReportUploadThread : public WorkerThread::Delegate,
    //! object was constructed with \a watch_pending_reports, it will also scan
    //! the crash report database for other pending reports, and process those as
    //! well.
@@ -226,7 +226,7 @@
  
    //! \brief Processes a single pending report from the database.
    //!
-@@ -145,7 +146,7 @@ class CrashReportUploadThread : public WorkerThread::Delegate,
+@@ -170,7 +171,7 @@ class CrashReportUploadThread : public WorkerThread::Delegate,
    //! remain in the “pending” state. If the upload fails and no more retries are
    //! desired, or report upload is disabled, it will be marked as “completed” in
    //! the database without ever having been uploaded.
@@ -235,7 +235,7 @@
  
    //! \brief Attempts to upload a crash report.
    //!
-@@ -162,6 +163,11 @@ class CrashReportUploadThread : public WorkerThread::Delegate,
+@@ -187,6 +188,11 @@ class CrashReportUploadThread : public WorkerThread::Delegate,
    UploadResult UploadReport(const CrashReportDatabase::UploadReport* report,
                              std::string* response_body);
  
@@ -248,23 +248,20 @@
    //! \brief Calls ProcessPendingReports() in response to ReportPending() having
    //!     been called on any thread, as well as periodically on a timer.
 diff --git third_party/crashpad/crashpad/handler/handler_main.cc third_party/crashpad/crashpad/handler/handler_main.cc
-index e0a262cd1f38..2949e3ac1739 100644
+index 7e908c0a305be..e35414a131f07 100644
 --- third_party/crashpad/crashpad/handler/handler_main.cc
 +++ third_party/crashpad/crashpad/handler/handler_main.cc
-@@ -36,8 +36,10 @@
- #include "base/scoped_generic.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/strings/stringprintf.h"
-+#include "base/strings/string_number_conversions.h"
+@@ -39,6 +39,7 @@
  #include "base/strings/utf_string_conversions.h"
  #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
 +#include "cef/libcef/features/features.h"
  #include "client/crash_report_database.h"
  #include "client/crashpad_client.h"
  #include "client/crashpad_info.h"
-@@ -100,6 +102,10 @@
- #include "handler/linux/exception_handler_server.h"
- #endif  // OS_MACOSX
+@@ -89,6 +90,10 @@
+ #include "util/win/session_end_watcher.h"
+ #endif  // BUILDFLAG(IS_APPLE)
  
 +#if BUILDFLAG(ENABLE_CEF)
 +#include "cef/libcef/common/cef_crash_report_upload_thread.h"
@@ -273,28 +270,28 @@
  namespace crashpad {
  
  namespace {
-@@ -215,6 +221,9 @@ struct Options {
+@@ -248,6 +253,9 @@ struct Options {
    bool periodic_tasks;
    bool rate_limit;
    bool upload_gzip;
 +  int max_uploads;
 +  int max_database_size;
 +  int max_database_age;
- #if defined(OS_CHROMEOS)
+ #if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
    bool use_cros_crash_reporter = false;
    base::FilePath minidump_dir_for_tests;
-@@ -577,6 +586,9 @@ int HandlerMain(int argc,
+@@ -622,6 +630,9 @@ int HandlerMain(int argc,
      kOptionTraceParentWithException,
  #endif
      kOptionURL,
 +    kOptionMaxUploads,
 +    kOptionMaxDatabaseSize,
 +    kOptionMaxDatabaseAge,
- #if defined(OS_CHROMEOS)
+ #if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
      kOptionUseCrosCrashReporter,
      kOptionMinidumpDirForTests,
-@@ -675,6 +687,9 @@ int HandlerMain(int argc,
- #endif  // OS_ANDROID
+@@ -722,6 +733,9 @@ int HandlerMain(int argc,
+ #endif  // BUILDFLAG(IS_ANDROID)
      {"help", no_argument, nullptr, kOptionHelp},
      {"version", no_argument, nullptr, kOptionVersion},
 +    {"max-uploads", required_argument, nullptr, kOptionMaxUploads},
@@ -303,7 +300,7 @@
      {nullptr, 0, nullptr, 0},
    };
  
-@@ -823,6 +838,27 @@ int HandlerMain(int argc,
+@@ -879,6 +893,27 @@ int HandlerMain(int argc,
          options.url = optarg;
          break;
        }
@@ -328,25 +325,31 @@
 +        }
 +        break;
 +      }
- #if defined(OS_CHROMEOS)
+ #if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
        case kOptionUseCrosCrashReporter: {
          options.use_cros_crash_reporter = true;
-@@ -972,8 +1008,14 @@ int HandlerMain(int argc,
+@@ -1028,11 +1063,20 @@ int HandlerMain(int argc,
      upload_thread_options.upload_gzip = options.upload_gzip;
      upload_thread_options.watch_pending_reports = options.periodic_tasks;
  
 +#if BUILDFLAG(ENABLE_CEF)
 +    upload_thread.Reset(new CefCrashReportUploadThread(
-+        database.get(), options.url, upload_thread_options,
++        database.get(),
++        options.url,
++        upload_thread_options,
++        CrashReportUploadThread::ProcessPendingReportsObservationCallback(),
 +        options.max_uploads));
 +#else
      upload_thread.Reset(new CrashReportUploadThread(
-         database.get(), options.url, upload_thread_options));
+         database.get(),
+         options.url,
+         upload_thread_options,
+         CrashReportUploadThread::ProcessPendingReportsObservationCallback()));
 +#endif
      upload_thread.Get()->Start();
    }
  
-@@ -1043,7 +1085,8 @@ int HandlerMain(int argc,
+@@ -1103,7 +1147,8 @@ int HandlerMain(int argc,
    ScopedStoppable prune_thread;
    if (options.periodic_tasks) {
      prune_thread.Reset(new PruneCrashReportThread(
diff --git a/src/patch/patches/embedder_product_override.patch b/src/patch/patches/embedder_product_override.patch
new file mode 100644
index 0000000..eccfbcc
--- /dev/null
+++ b/src/patch/patches/embedder_product_override.patch
@@ -0,0 +1,38 @@
+diff --git components/embedder_support/user_agent_utils.cc components/embedder_support/user_agent_utils.cc
+index c957a691efcac..127872ce6c249 100644
+--- components/embedder_support/user_agent_utils.cc
++++ components/embedder_support/user_agent_utils.cc
+@@ -18,6 +18,7 @@
+ #include "base/version.h"
+ #include "build/branding_buildflags.h"
+ #include "build/build_config.h"
++#include "cef/libcef/features/features.h"
+ #include "components/embedder_support/pref_names.h"
+ #include "components/embedder_support/switches.h"
+ #include "components/policy/core/common/policy_pref_names.h"
+@@ -38,6 +39,10 @@
+ #include "base/win/windows_version.h"
+ #endif  // BUILDFLAG(IS_WIN)
+ 
++#if BUILDFLAG(ENABLE_CEF)
++#include "cef/libcef/common/cef_switches.h"
++#endif
++
+ namespace embedder_support {
+ 
+ namespace {
+@@ -240,6 +245,14 @@ blink::UserAgentBrandList GetUserAgentBrandFullVersionList(
+ 
+ std::string GetProductAndVersion(
+     UserAgentReductionEnterprisePolicyState user_agent_reduction) {
++#if BUILDFLAG(ENABLE_CEF)
++  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
++  if (command_line->HasSwitch(switches::kUserAgentProductAndVersion)) {
++    return command_line->GetSwitchValueASCII(
++        switches::kUserAgentProductAndVersion);
++  }
++#endif
++
+   return ShouldReduceUserAgentMinorVersion(user_agent_reduction)
+              ? version_info::GetProductNameAndVersionForReducedUserAgent(
+                    blink::features::kUserAgentFrozenBuildVersion.Get())
diff --git a/src/patch/patches/extensions_1947.patch b/src/patch/patches/extensions_1947.patch
index 171e675..7ad3d36 100644
--- a/src/patch/patches/extensions_1947.patch
+++ b/src/patch/patches/extensions_1947.patch
@@ -1,54 +1,93 @@
 diff --git chrome/browser/extensions/api/streams_private/streams_private_api.cc chrome/browser/extensions/api/streams_private/streams_private_api.cc
-index bb4af725af9f..a1389be84f6e 100644
+index cead7cfa14bae..24142c2e4896f 100644
 --- chrome/browser/extensions/api/streams_private/streams_private_api.cc
 +++ chrome/browser/extensions/api/streams_private/streams_private_api.cc
 @@ -6,6 +6,7 @@
  
  #include <utility>
  
-+#include "cef/libcef/features/features.h"
++#include "cef/libcef/features/runtime.h"
  #include "chrome/browser/extensions/extension_tab_util.h"
- #include "chrome/browser/prerender/prerender_contents.h"
- #include "components/sessions/core/session_id.h"
-@@ -41,6 +42,7 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
+ #include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+ #include "components/no_state_prefetch/browser/no_state_prefetch_contents.h"
+@@ -18,6 +19,10 @@
+ #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
+ #include "extensions/common/manifest_handlers/mime_types_handler.h"
+ 
++#if BUILDFLAG(ENABLE_CEF)
++#include "cef/libcef/browser/extensions/alloy_extensions_util.h"
++#endif
++
+ namespace extensions {
+ 
+ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
+@@ -34,6 +39,7 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
    if (!web_contents)
      return;
  
-+#if !BUILDFLAG(ENABLE_CEF)
-   // If the request was for a prerender, abort the prerender and do not
-   // continue. This is because plugins cancel prerender, see
++  if (!cef::IsAlloyRuntimeEnabled()) {
+   // If the request was for NoStatePrefetch, abort the prefetcher and do not
+   // continue. This is because plugins cancel NoStatePrefetch, see
    // http://crbug.com/343590.
-@@ -50,6 +52,7 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
-     prerender_contents->Destroy(prerender::FINAL_STATUS_DOWNLOAD);
+@@ -44,6 +50,7 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
+     no_state_prefetch_contents->Destroy(prerender::FINAL_STATUS_DOWNLOAD);
      return;
    }
-+#endif  // !BUILDFLAG(ENABLE_CEF)
++  }
  
    auto* browser_context = web_contents->GetBrowserContext();
  
+@@ -70,9 +77,18 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
+   // forms of zooming won't work).
+   // TODO(1042323): Present a coherent representation of a tab id for portal
+   // contents.
+-  int tab_id = web_contents->GetOuterWebContents()
+-                   ? SessionID::InvalidValue().id()
+-                   : ExtensionTabUtil::GetTabId(web_contents);
++  int tab_id;
++  if (web_contents->GetOuterWebContents()) {
++    tab_id = SessionID::InvalidValue().id();
++  } else
++#if BUILDFLAG(ENABLE_CEF)
++  if (cef::IsAlloyRuntimeEnabled()) {
++    tab_id = alloy::GetTabIdForWebContents(web_contents);
++  } else
++#endif  // BUILDFLAG(ENABLE_CEF)
++  {
++    tab_id = ExtensionTabUtil::GetTabId(web_contents);
++  }
+ 
+   std::unique_ptr<StreamContainer> stream_container(
+       new StreamContainer(tab_id, embedded, handler_url, extension_id,
 diff --git extensions/browser/extension_host.cc extensions/browser/extension_host.cc
-index 01fbe50e48a9..3977d27e813d 100644
+index 9c44797e9e238..b61704db987b6 100644
 --- extensions/browser/extension_host.cc
 +++ extensions/browser/extension_host.cc
-@@ -66,11 +66,12 @@ ExtensionHost::ExtensionHost(const Extension* extension,
-   DCHECK(host_type == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE ||
-          host_type == VIEW_TYPE_EXTENSION_DIALOG ||
-          host_type == VIEW_TYPE_EXTENSION_POPUP);
+@@ -62,12 +62,13 @@ ExtensionHost::ExtensionHost(const Extension* extension,
+          host_type == mojom::ViewType::kExtensionDialog ||
+          host_type == mojom::ViewType::kExtensionPopup ||
+          host_type == mojom::ViewType::kExtensionSidePanel);
 -  host_contents_ = WebContents::Create(
--      WebContents::CreateParams(browser_context_, site_instance)),
--  content::WebContentsObserver::Observe(host_contents_.get());
 +  host_contents_owned_ = WebContents::Create(
-+      WebContents::CreateParams(browser_context_, site_instance));
+       WebContents::CreateParams(browser_context_, site_instance));
 +  host_contents_ = host_contents_owned_.get();
+   host_contents_->SetOwnerLocationForDebug(FROM_HERE);
+-  content::WebContentsObserver::Observe(host_contents_.get());
 +  content::WebContentsObserver::Observe(host_contents_);
    host_contents_->SetDelegate(this);
 -  SetViewType(host_contents_.get(), host_type);
 +  SetViewType(host_contents_, host_type);
+   main_frame_host_ = host_contents_->GetPrimaryMainFrame();
  
-   render_view_host_ = host_contents_->GetRenderViewHost();
+   // Listen for when an extension is unloaded from the same profile, as it may
+@@ -83,11 +84,49 @@ ExtensionHost::ExtensionHost(const Extension* extension,
+   // Create password reuse detection manager when new extension web contents are
+   // created.
+   ExtensionsBrowserClient::Get()->CreatePasswordReuseDetectionManager(
+-      host_contents_.get());
++      host_contents_);
  
-@@ -85,6 +86,48 @@ ExtensionHost::ExtensionHost(const Extension* extension,
-       dispatcher()->set_delegate(this);
+   ExtensionHostRegistry::Get(browser_context_)->ExtensionHostCreated(this);
  }
  
 +ExtensionHost::ExtensionHost(ExtensionHostDelegate* delegate,
@@ -56,16 +95,12 @@
 +                             content::BrowserContext* browser_context,
 +                             content::WebContents* host_contents,
 +                             const GURL& url,
-+                             ViewType host_type)
++                             mojom::ViewType host_type)
 +    : delegate_(delegate),
 +      extension_(extension),
 +      extension_id_(extension->id()),
 +      browser_context_(browser_context),
 +      host_contents_(host_contents),
-+      render_view_host_(nullptr),
-+      is_render_view_creation_pending_(false),
-+      has_loaded_once_(false),
-+      document_element_available_(false),
 +      initial_url_(url),
 +      extension_host_type_(host_type) {
 +  DCHECK(delegate);
@@ -73,14 +108,14 @@
 +  DCHECK(host_contents);
 +
 +  // Not used for panels, see PanelHost.
-+  DCHECK(host_type == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE ||
-+         host_type == VIEW_TYPE_EXTENSION_DIALOG ||
-+         host_type == VIEW_TYPE_EXTENSION_POPUP);
++  DCHECK(host_type == mojom::ViewType::kExtensionBackgroundPage ||
++         host_type == mojom::ViewType::kExtensionDialog ||
++         host_type == mojom::ViewType::kExtensionPopup);
 +
 +  content::WebContentsObserver::Observe(host_contents_);
 +  SetViewType(host_contents_, host_type);
 +
-+  render_view_host_ = host_contents_->GetRenderViewHost();
++  main_frame_host_ = host_contents_->GetPrimaryMainFrame();
 +
 +  // Listen for when an extension is unloaded from the same profile, as it may
 +  // be the same extension that this points to.
@@ -97,45 +132,85 @@
    ExtensionRegistry::Get(browser_context_)->RemoveObserver(this);
  
 diff --git extensions/browser/extension_host.h extensions/browser/extension_host.h
-index b5d2c7652cae..2e11775e5db3 100644
+index dda0620251895..4014bd801f727 100644
 --- extensions/browser/extension_host.h
 +++ extensions/browser/extension_host.h
-@@ -52,13 +52,19 @@ class ExtensionHost : public DeferredStartRenderHost,
-   ExtensionHost(const Extension* extension,
+@@ -62,6 +62,12 @@ class ExtensionHost : public DeferredStartRenderHost,
                  content::SiteInstance* site_instance,
-                 const GURL& url, ViewType host_type);
+                 const GURL& url,
+                 mojom::ViewType host_type);
 +  ExtensionHost(ExtensionHostDelegate* delegate,
 +                const Extension* extension,
 +                content::BrowserContext* browser_context,
 +                content::WebContents* host_contents,
 +                const GURL& url,
-+                ViewType host_type);
-   ~ExtensionHost() override;
++                mojom::ViewType host_type);
  
-   // This may be null if the extension has been or is being unloaded.
+   ExtensionHost(const ExtensionHost&) = delete;
+   ExtensionHost& operator=(const ExtensionHost&) = delete;
+@@ -72,7 +78,7 @@ class ExtensionHost : public DeferredStartRenderHost,
    const Extension* extension() const { return extension_; }
  
-   const std::string& extension_id() const { return extension_id_; }
+   const ExtensionId& extension_id() const { return extension_id_; }
 -  content::WebContents* host_contents() const { return host_contents_.get(); }
 +  content::WebContents* host_contents() const { return host_contents_; }
-   content::RenderViewHost* render_view_host() const;
+   content::RenderFrameHost* main_frame_host() const { return main_frame_host_; }
    content::RenderProcessHost* render_process_host() const;
    bool has_loaded_once() const { return has_loaded_once_; }
-@@ -176,7 +182,8 @@ class ExtensionHost : public DeferredStartRenderHost,
-   content::BrowserContext* browser_context_;
+@@ -223,7 +229,8 @@ class ExtensionHost : public DeferredStartRenderHost,
+   raw_ptr<content::BrowserContext> browser_context_;
  
    // The host for our HTML content.
 -  std::unique_ptr<content::WebContents> host_contents_;
 +  std::unique_ptr<content::WebContents> host_contents_owned_;
 +  content::WebContents* host_contents_;
  
-   // A weak pointer to the current or pending RenderViewHost. We don't access
-   // this through the host_contents because we want to deal with the pending
+   // A pointer to the current or speculative main frame in `host_contents_`. We
+   // can't access this frame through the `host_contents_` directly as it does
+diff --git extensions/browser/extension_registry.cc extensions/browser/extension_registry.cc
+index c3197eb4790fa..1e7ae767b0582 100644
+--- extensions/browser/extension_registry.cc
++++ extensions/browser/extension_registry.cc
+@@ -6,9 +6,14 @@
+ 
+ #include "base/observer_list.h"
+ #include "base/strings/string_util.h"
++#include "cef/libcef/features/runtime.h"
+ #include "extensions/browser/extension_registry_factory.h"
+ #include "extensions/browser/extension_registry_observer.h"
+ 
++#if BUILDFLAG(ENABLE_CEF)
++#include "cef/libcef/common/extensions/extensions_util.h"
++#endif
++
+ namespace extensions {
+ 
+ ExtensionRegistry::ExtensionRegistry(content::BrowserContext* browser_context)
+@@ -17,6 +22,11 @@ ExtensionRegistry::~ExtensionRegistry() = default;
+ 
+ // static
+ ExtensionRegistry* ExtensionRegistry::Get(content::BrowserContext* context) {
++#if BUILDFLAG(ENABLE_CEF)
++  if (cef::IsAlloyRuntimeEnabled() && !extensions::ExtensionsEnabled()) {
++    return nullptr;
++  }
++#endif
+   return ExtensionRegistryFactory::GetForBrowserContext(context);
+ }
+ 
 diff --git extensions/browser/extensions_browser_client.h extensions/browser/extensions_browser_client.h
-index c2d64706c1db..4d5c75dd035f 100644
+index 058367b7ab78d..99a9e901566ce 100644
 --- extensions/browser/extensions_browser_client.h
 +++ extensions/browser/extensions_browser_client.h
-@@ -56,6 +56,7 @@ class ComponentExtensionResourceManager;
+@@ -32,6 +32,7 @@
+ #include "url/gurl.h"
+ 
+ class ExtensionFunctionRegistry;
++class GURL;
+ class PrefService;
+ 
+ namespace base {
+@@ -80,6 +81,7 @@ class ComponentExtensionResourceManager;
  class Extension;
  class ExtensionCache;
  class ExtensionError;
@@ -143,7 +218,7 @@
  class ExtensionHostDelegate;
  class ExtensionSet;
  class ExtensionSystem;
-@@ -195,6 +196,14 @@ class ExtensionsBrowserClient {
+@@ -265,6 +267,14 @@ class ExtensionsBrowserClient {
    virtual std::unique_ptr<ExtensionHostDelegate>
    CreateExtensionHostDelegate() = 0;
  
@@ -159,16 +234,14 @@
    // once each time the extensions system is loaded per browser_context. The
    // implementation may wish to use the BrowserContext to record the current
 diff --git extensions/browser/process_manager.cc extensions/browser/process_manager.cc
-index bc06d55da961..64f513b54fe3 100644
+index 580df6d9b0ae7..39b2d5ccc074c 100644
 --- extensions/browser/process_manager.cc
 +++ extensions/browser/process_manager.cc
-@@ -386,9 +386,16 @@ bool ProcessManager::CreateBackgroundHost(const Extension* extension,
+@@ -380,9 +380,17 @@ bool ProcessManager::CreateBackgroundHost(const Extension* extension,
      return true;  // TODO(kalman): return false here? It might break things...
  
    DVLOG(1) << "CreateBackgroundHost " << extension->id();
 -  ExtensionHost* host =
--      new ExtensionHost(extension, GetSiteInstanceForURL(url).get(), url,
--                        VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
 +  ExtensionHost* host = nullptr;
 +  if (ExtensionsBrowserClient::Get()->CreateBackgroundExtensionHost(
 +          extension, browser_context_, url, &host) && !host) {
@@ -176,9 +249,23 @@
 +    return false;
 +  }
 +  if (!host) {
-+    host = new ExtensionHost(extension, GetSiteInstanceForURL(url).get(), url,
-+                             VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
++    host =
+       new ExtensionHost(extension, GetSiteInstanceForURL(url).get(), url,
+                         mojom::ViewType::kExtensionBackgroundPage);
 +  }
-   host->CreateRenderViewSoon();
-   OnBackgroundHostCreated(host);
-   return true;
+   host->SetCloseHandler(
+       base::BindOnce(&ProcessManager::HandleCloseExtensionHost,
+                      weak_ptr_factory_.GetWeakPtr()));
+diff --git extensions/common/extensions_client.cc extensions/common/extensions_client.cc
+index a8108350ddde2..7ae49e78b4327 100644
+--- extensions/common/extensions_client.cc
++++ extensions/common/extensions_client.cc
+@@ -23,7 +23,7 @@ ExtensionsClient* g_client = nullptr;
+ }  // namespace
+ 
+ ExtensionsClient* ExtensionsClient::Get() {
+-  DCHECK(g_client);
++  // May be nullptr if using CEF Alloy with extensions disabled.
+   return g_client;
+ }
+ 
diff --git a/src/patch/patches/font_family_cache_1501.patch b/src/patch/patches/font_family_cache_1501.patch
index ba0ff03..e5fad2c 100644
--- a/src/patch/patches/font_family_cache_1501.patch
+++ b/src/patch/patches/font_family_cache_1501.patch
@@ -1,5 +1,5 @@
 diff --git chrome/browser/font_family_cache.h chrome/browser/font_family_cache.h
-index a99372e6744c..ce40a8448868 100644
+index d4a32438bd20d..7e1d40e973333 100644
 --- chrome/browser/font_family_cache.h
 +++ chrome/browser/font_family_cache.h
 @@ -19,6 +19,8 @@ class Profile;
diff --git a/src/patch/patches/gn_config.patch b/src/patch/patches/gn_config.patch
index 4ef38c3..11af94b 100644
--- a/src/patch/patches/gn_config.patch
+++ b/src/patch/patches/gn_config.patch
@@ -1,10 +1,10 @@
 diff --git .gn .gn
-index c7296bb80f62..a64c7c42720a 100644
+index 628071cb9a464..1595a4283e134 100644
 --- .gn
 +++ .gn
-@@ -642,6 +642,8 @@ exec_script_whitelist =
- 
+@@ -144,6 +144,8 @@ exec_script_whitelist =
        "//chrome/android/webapk/shell_apk/prepare_upload_dir/BUILD.gn",
+       "//chrome/version.gni",
  
 +      "//cef/BUILD.gn",
 +
@@ -12,23 +12,41 @@
        # https://crbug.com/474506.
        "//clank/java/BUILD.gn",
 diff --git BUILD.gn BUILD.gn
-index ad58fc03312a..856991ba6096 100644
+index 64819b31d74a7..3dc461fde620f 100644
 --- BUILD.gn
 +++ BUILD.gn
-@@ -222,6 +222,7 @@ group("gn_all") {
+@@ -19,6 +19,7 @@ import("//build/config/sanitizers/sanitizers.gni")
+ import("//build/config/ui.gni")
+ import("//build/gn_logs.gni")
+ import("//build/util/generate_wrapper.gni")
++import("//cef/libcef/features/features.gni")
+ import("//chrome/browser/buildflags.gni")
+ import("//components/nacl/features.gni")
+ import("//device/vr/buildflags/buildflags.gni")
+@@ -275,6 +276,10 @@ group("gn_all") {
  
-   if (!is_ios && !is_fuchsia) {
-     deps += [
-+      "//cef",
-       "//chrome/test:telemetry_perf_unittests",
-       "//chrome/test:unit_tests",
-       "//components:components_browsertests",
+     deps += root_extra_deps
+ 
++    if (enable_cef) {
++      deps += [ "//cef" ]
++    }
++
+     if (enable_printing || enable_printing_unittests) {
+       deps += [ "//printing:printing_unittests" ]
+     }
 diff --git build/config/win/visual_studio_version.gni build/config/win/visual_studio_version.gni
-index 982fbe8d3f0d..e757be4688f1 100644
+index 1da479dd5eebc..ff9c7e467997c 100644
 --- build/config/win/visual_studio_version.gni
 +++ build/config/win/visual_studio_version.gni
-@@ -12,9 +12,8 @@ declare_args() {
-   # Currently always "2015".
+@@ -5,15 +5,14 @@
+ declare_args() {
+   # Path to Visual Studio. If empty, the default is used which is to use the
+   # automatic toolchain in depot_tools. If set, you must also set the
+-  # visual_studio_version, wdk_path and windows_sdk_version.
++  # visual_studio_version, visual_studio_runtime_dirs and windows_sdk_version.
+   visual_studio_path = ""
+ 
+   # Version of Visual Studio pointed to by the visual_studio_path.
    visual_studio_version = ""
  
 -  # Directory of the Windows driver kit. If visual_studio_path is empty, this
@@ -39,8 +57,8 @@
  
    # Full path to the Windows SDK, not including a backslash at the end.
    # This value is the default location, override if you have a different
-@@ -28,12 +27,11 @@ if (visual_studio_path == "") {
-   visual_studio_path = toolchain_data.vs_path
+@@ -31,14 +30,13 @@ if (visual_studio_path == "") {
+   windows_sdk_version = toolchain_data.sdk_version
    windows_sdk_path = toolchain_data.sdk_path
    visual_studio_version = toolchain_data.vs_version
 -  wdk_path = toolchain_data.wdk_dir
@@ -48,36 +66,106 @@
  } else {
    assert(visual_studio_version != "",
           "You must set the visual_studio_version if you set the path")
--  assert(wdk_path != "",
--         "You must set the wdk_path if you set the visual studio path")
--  visual_studio_runtime_dirs = []
 +  assert(visual_studio_runtime_dirs != "",
 +         "You must set the visual_studio_runtime_dirs if you set the visual " +
 +         "studio path")
+   assert(windows_sdk_version != "",
+          "You must set the windows_sdk_version if you set the path")
+-  assert(wdk_path != "",
+-         "You must set the wdk_path if you set the visual studio path")
+-  visual_studio_runtime_dirs = []
  }
 diff --git chrome/chrome_paks.gni chrome/chrome_paks.gni
-index ddfc4bd551d1..0e9157969deb 100644
+index d60ce9a1f8534..be1f4879542dd 100644
 --- chrome/chrome_paks.gni
 +++ chrome/chrome_paks.gni
-@@ -297,7 +297,7 @@ template("chrome_paks") {
+@@ -6,6 +6,7 @@ import("//ash/ambient/resources/resources.gni")
+ import("//build/config/chromebox_for_meetings/buildflags.gni")
+ import("//build/config/chromeos/ui_mode.gni")
+ import("//build/config/locales.gni")
++import("//cef/libcef/features/features.gni")
+ import("//chrome/browser/buildflags.gni")
+ import("//chrome/common/features.gni")
+ import("//components/signin/features.gni")
+@@ -81,6 +82,10 @@ template("chrome_repack_percent") {
+         "//ui/chromeos/resources",
+       ]
      }
++    if (enable_cef) {
++      sources += [ "$root_gen_dir/cef/cef_resources.pak" ]
++      deps += [ "//cef:cef_resources" ]
++    }
+     if (enable_extensions) {
+       sources += [ "$root_gen_dir/extensions/extensions_browser_resources_${percent}_percent.pak" ]
+       deps += [ "//extensions:extensions_browser_resources" ]
+diff --git chrome/chrome_repack_locales.gni chrome/chrome_repack_locales.gni
+index a1666413e61d3..6cac57842af85 100644
+--- chrome/chrome_repack_locales.gni
++++ chrome/chrome_repack_locales.gni
+@@ -6,6 +6,7 @@ import("//build/config/chrome_build.gni")
+ import("//build/config/chromeos/ui_mode.gni")
+ import("//build/config/features.gni")
+ import("//build/config/ui.gni")
++import("//cef/libcef/features/features.gni")
+ import("//extensions/buildflags/buildflags.gni")
+ import("//tools/grit/repack.gni")
  
-     input_locales = locales
--    output_dir = "${invoker.output_dir}/locales"
-+    output_dir = "${invoker.output_dir}/chrome/locales"
- 
-     if (is_mac) {
-       output_locales = locales_as_mac_outputs
+@@ -93,6 +94,10 @@ template("chrome_repack_locales") {
+           [ "${root_gen_dir}/chromeos/strings/chromeos_strings_" ]
+       deps += [ "//chromeos/strings" ]
+     }
++    if (enable_cef) {
++      source_patterns += [ "${root_gen_dir}/cef/cef_strings_" ]
++      deps += [ "//cef:cef_strings" ]
++    }
+     if (enable_extensions) {
+       source_patterns +=
+           [ "${root_gen_dir}/extensions/strings/extensions_strings_" ]
 diff --git chrome/installer/mini_installer/BUILD.gn chrome/installer/mini_installer/BUILD.gn
-index b2c99d4721dd..c8f870fa4a06 100644
+index 71803adcfbe02..80543d0aa58c8 100644
 --- chrome/installer/mini_installer/BUILD.gn
 +++ chrome/installer/mini_installer/BUILD.gn
-@@ -134,7 +134,7 @@ template("generate_mini_installer") {
-     inputs = [
-       "$chrome_dll_file",
-       "$root_out_dir/chrome.exe",
--      "$root_out_dir/locales/en-US.pak",
-+      "$root_out_dir/chrome/locales/en-US.pak",
-       "$root_out_dir/setup.exe",
-       "//chrome/tools/build/win/makecab.py",
-       release_file,
+@@ -6,6 +6,7 @@ import("//build/config/compiler/compiler.gni")
+ import("//build/config/features.gni")
+ import("//build/config/python.gni")
+ import("//build/config/ui.gni")
++import("//cef/libcef/features/features.gni")
+ import("//chrome/process_version_rc_template.gni")
+ import("//components/nacl/features.gni")
+ import("//third_party/dawn/scripts/dawn_features.gni")
+@@ -123,11 +124,13 @@ action("mini_installer_archive") {
+   inputs = [
+     "$root_out_dir/chrome.dll",
+     "$root_out_dir/chrome.exe",
+-    "$root_out_dir/locales/en-US.pak",
+     "$root_out_dir/setup.exe",
+     "//chrome/tools/build/win/makecab.py",
+     release_file,
+   ]
++  if (!enable_cef) {
++    inputs += [ "$root_out_dir/locales/en-US.pak" ]
++  }
+ 
+   outputs = [
+     "$root_out_dir/chrome.7z",
+diff --git tools/grit/grit_args.gni tools/grit/grit_args.gni
+index 77f1be6116d0c..6bc41416af551 100644
+--- tools/grit/grit_args.gni
++++ tools/grit/grit_args.gni
+@@ -5,6 +5,7 @@
+ import("//build/config/chrome_build.gni")
+ import("//build/config/chromeos/ui_mode.gni")
+ import("//build/config/devtools.gni")
++import("//build/config/locales.gni")
+ import("//build/config/ui.gni")
+ 
+ shared_intermediate_dir = rebase_path(root_gen_dir, root_build_dir)
+@@ -36,6 +37,8 @@ _grit_defines = [
+ 
+   # Mac and iOS want Title Case strings.
+   "use_titlecase=${is_apple}",
++
++  "enable_pseudolocales=${enable_pseudolocales}",
+ ]
+ 
+ # Must match `enable_hidpi` in ui/base/ui_features.gni.
diff --git a/src/patch/patches/gritsettings.patch b/src/patch/patches/gritsettings.patch
index 1a91508..6f269dc 100644
--- a/src/patch/patches/gritsettings.patch
+++ b/src/patch/patches/gritsettings.patch
@@ -1,12 +1,11 @@
 diff --git tools/gritsettings/resource_ids.spec tools/gritsettings/resource_ids.spec
-index 730e3209ec95..39257ae244de 100644
+index 99322038017cc..d34154ba2a374 100644
 --- tools/gritsettings/resource_ids.spec
 +++ tools/gritsettings/resource_ids.spec
-@@ -601,4 +601,13 @@
-   # Please read the header and find the right section above instead.
+@@ -1241,6 +1241,15 @@
+   # END "everything else" section.
+   # Everything but chrome/, components/, content/, and ios/
  
-   # Resource ids starting at 31000 are reserved for projects built on Chromium.
-+
 +  "cef/libcef/resources/cef_resources.grd": {
 +    "META": {"align": 31500},
 +    "includes": [31500],
@@ -15,4 +14,7 @@
 +    "META": {"align": 32000},
 +    "messages": [32000],
 +  },
++
+   # Thinking about appending to the end?
+   # Please read the header and find the right section above instead.
  }
diff --git a/src/patch/patches/ime_1610.patch b/src/patch/patches/ime_1610.patch
deleted file mode 100644
index 8dcc653..0000000
--- a/src/patch/patches/ime_1610.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-diff --git ui/base/ime/win/input_method_win_base.cc ui/base/ime/win/input_method_win_base.cc
-index 83850840d83b..3d5ffcc54f1e 100644
---- ui/base/ime/win/input_method_win_base.cc
-+++ ui/base/ime/win/input_method_win_base.cc
-@@ -263,8 +263,9 @@ bool InputMethodWinBase::IsWindowFocused(const TextInputClient* client) const {
-   // receiving keyboard input as long as it is an active window. This works well
-   // even when the |attached_window_handle| becomes active but has not received
-   // WM_FOCUS yet.
-+  // With CEF |toplevel_window_handle_| may be a child window.
-   return toplevel_window_handle_ &&
--         GetActiveWindow() == toplevel_window_handle_;
-+         GetActiveWindow() == ::GetAncestor(toplevel_window_handle_, GA_ROOT);
- }
- 
- LRESULT InputMethodWinBase::OnChar(HWND window_handle,
diff --git a/src/patch/patches/libxml_visibility.patch b/src/patch/patches/libxml_visibility.patch
index dad5e02..4d75a82 100644
--- a/src/patch/patches/libxml_visibility.patch
+++ b/src/patch/patches/libxml_visibility.patch
@@ -1,12 +1,12 @@
 diff --git third_party/libxml/BUILD.gn third_party/libxml/BUILD.gn
-index 3fe4dfd2990b..64848dfd33d7 100644
+index aab483d6b00ce..ed3c1e10a7fe7 100644
 --- third_party/libxml/BUILD.gn
 +++ third_party/libxml/BUILD.gn
-@@ -141,6 +141,7 @@ static_library("libxml") {
-     "//third_party/blink/renderer/*",
-     "//third_party/fontconfig",
-     "//third_party/libxslt",
+@@ -140,6 +140,7 @@ static_library("libxml") {
+     ":libxml_utils",
+     ":xml_reader",
+     ":xml_writer",
 +    "//cef:*",
-   ]
-   if (is_ios) {
-     foreach(tgt, ios_libxml_visibility_additions) {
+     "//chromecast/internal",
+     "//testing/libfuzzer/*",
+     "//third_party/blink/renderer/*",
diff --git a/src/patch/patches/light_mode_3534.patch b/src/patch/patches/light_mode_3534.patch
new file mode 100644
index 0000000..642b6d4
--- /dev/null
+++ b/src/patch/patches/light_mode_3534.patch
@@ -0,0 +1,116 @@
+diff --git base/win/dark_mode_support.cc base/win/dark_mode_support.cc
+index 325bc70b6ba97..d4117dbb1d4d8 100644
+--- base/win/dark_mode_support.cc
++++ base/win/dark_mode_support.cc
+@@ -6,6 +6,7 @@
+ 
+ #include <windows.h>
+ 
++#include "base/command_line.h"
+ #include "base/native_library.h"
+ #include "base/win/windows_version.h"
+ 
+@@ -85,11 +86,20 @@ const DarkModeSupport& GetDarkModeSupport() {
+   return dark_mode_support;
+ }
+ 
++bool IsForcedLightMode() {
++  static bool kIsForcedLightMode =
++      base::CommandLine::ForCurrentProcess()->HasSwitch(
++          "force-light-mode");
++  return kIsForcedLightMode;
++}
++
+ }  // namespace
+ 
+ namespace base::win {
+ 
+ bool IsDarkModeAvailable() {
++  if (IsForcedLightMode())
++    return false;
+   auto& dark_mode_support = GetDarkModeSupport();
+   return (dark_mode_support.allow_dark_mode_for_app ||
+           dark_mode_support.set_preferred_app_mode) &&
+diff --git ui/native_theme/native_theme_mac.mm ui/native_theme/native_theme_mac.mm
+index e6078b2a45d88..bf051fb8a02f4 100644
+--- ui/native_theme/native_theme_mac.mm
++++ ui/native_theme/native_theme_mac.mm
+@@ -50,6 +50,13 @@ bool InvertedColors() {
+   return NSWorkspace.sharedWorkspace.accessibilityDisplayShouldInvertColors;
+ }
+ 
++bool IsForcedLightMode() {
++  static bool kIsForcedLightMode =
++      base::CommandLine::ForCurrentProcess()->HasSwitch(
++          "force-light-mode");
++  return kIsForcedLightMode;
++}
++
+ }  // namespace
+ 
+ // Helper object to respond to light mode/dark mode changeovers.
+@@ -577,11 +584,15 @@ void NativeThemeMac::PaintSelectedMenuItem(
+ 
+ void NativeThemeMac::InitializeDarkModeStateAndObserver() {
+   __block auto theme = this;
+-  set_use_dark_colors(IsDarkMode());
++  if (!IsForcedLightMode()) {
++    set_use_dark_colors(IsForcedDarkMode() || IsDarkMode());
++  }
+   set_preferred_color_scheme(CalculatePreferredColorScheme());
+   appearance_observer_ =
+       [[NativeThemeEffectiveAppearanceObserver alloc] initWithHandler:^{
+-        theme->set_use_dark_colors(IsDarkMode());
++        if (!IsForcedLightMode()) {
++          theme->set_use_dark_colors(IsForcedDarkMode() || IsDarkMode());
++        }
+         theme->set_preferred_color_scheme(CalculatePreferredColorScheme());
+         theme->NotifyOnNativeThemeUpdated();
+       }];
+@@ -590,7 +601,9 @@ void NativeThemeMac::InitializeDarkModeStateAndObserver() {
+ void NativeThemeMac::ConfigureWebInstance() {
+   // NativeThemeAura is used as web instance so we need to initialize its state.
+   NativeTheme* web_instance = NativeTheme::GetInstanceForWeb();
+-  web_instance->set_use_dark_colors(IsDarkMode());
++  if (!IsForcedLightMode()) {
++    web_instance->set_use_dark_colors(IsForcedDarkMode() || IsDarkMode());
++  }
+   web_instance->set_preferred_color_scheme(CalculatePreferredColorScheme());
+   web_instance->SetPreferredContrast(CalculatePreferredContrast());
+   web_instance->set_prefers_reduced_transparency(PrefersReducedTransparency());
+diff --git ui/native_theme/native_theme_win.cc ui/native_theme/native_theme_win.cc
+index 50647269ec84f..c947bd2717d04 100644
+--- ui/native_theme/native_theme_win.cc
++++ ui/native_theme/native_theme_win.cc
+@@ -662,14 +662,17 @@ bool NativeThemeWin::ShouldUseDarkColors() const {
+   // Windows high contrast modes are entirely different themes,
+   // so let them take priority over dark mode.
+   // ...unless --force-dark-mode was specified in which case caveat emptor.
+-  if (InForcedColorsMode() && !IsForcedDarkMode())
++  if (supports_windows_dark_mode_ && IsForcedDarkMode()) {
++    return true;
++  }
++  if (InForcedColorsMode())
+     return false;
+   return NativeTheme::ShouldUseDarkColors();
+ }
+ 
+ NativeTheme::PreferredColorScheme
+ NativeThemeWin::CalculatePreferredColorScheme() const {
+-  if (!InForcedColorsMode())
++  if (!InForcedColorsMode() || !supports_windows_dark_mode_)
+     return NativeTheme::CalculatePreferredColorScheme();
+ 
+   // According to the spec, the preferred color scheme for web content is 'dark'
+@@ -1660,8 +1663,9 @@ void NativeThemeWin::RegisterColorFilteringRegkeyObserver() {
+ }
+ 
+ void NativeThemeWin::UpdateDarkModeStatus() {
+-  bool dark_mode_enabled = false;
+-  if (hkcu_themes_regkey_.Valid()) {
++  bool dark_mode_enabled = ShouldUseDarkColors();
++  if (supports_windows_dark_mode_ && !IsForcedDarkMode() &&
++      hkcu_themes_regkey_.Valid()) {
+     DWORD apps_use_light_theme = 1;
+     hkcu_themes_regkey_.ReadValueDW(L"AppsUseLightTheme",
+                                     &apps_use_light_theme);
diff --git a/src/patch/patches/linux_assets_path_1936.patch b/src/patch/patches/linux_assets_path_1936.patch
index 3fac280..2aa7366 100644
--- a/src/patch/patches/linux_assets_path_1936.patch
+++ b/src/patch/patches/linux_assets_path_1936.patch
@@ -1,8 +1,8 @@
 diff --git content/browser/child_process_launcher_helper_linux.cc content/browser/child_process_launcher_helper_linux.cc
-index e53e60ef146f..9b6db4a69d41 100644
+index 321faab043958..7586dc52e50ca 100644
 --- content/browser/child_process_launcher_helper_linux.cc
 +++ content/browser/child_process_launcher_helper_linux.cc
-@@ -164,7 +164,7 @@ void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
+@@ -188,7 +188,7 @@ ZygoteCommunication* ChildProcessLauncherHelper::GetZygoteForLaunch() {
  base::File OpenFileToShare(const base::FilePath& path,
                             base::MemoryMappedFile::Region* region) {
    base::FilePath exe_dir;
@@ -12,7 +12,7 @@
    base::File file(exe_dir.Append(path),
                    base::File::FLAG_OPEN | base::File::FLAG_READ);
 diff --git sandbox/linux/suid/client/setuid_sandbox_host.cc sandbox/linux/suid/client/setuid_sandbox_host.cc
-index 0aaed76c1dda..517c3d8b5772 100644
+index 84fd365da0283..88f3adf813eca 100644
 --- sandbox/linux/suid/client/setuid_sandbox_host.cc
 +++ sandbox/linux/suid/client/setuid_sandbox_host.cc
 @@ -120,7 +120,7 @@ bool SetuidSandboxHost::IsDisabledViaEnvironment() {
@@ -24,25 +24,16 @@
      base::FilePath sandbox_candidate = exe_dir.AppendASCII("chrome-sandbox");
      if (base::PathExists(sandbox_candidate))
        sandbox_binary = sandbox_candidate;
-diff --git ui/gl/init/gl_initializer_x11.cc ui/gl/init/gl_initializer_x11.cc
-index d9190a957ca2..50bb49eaf56c 100644
---- ui/gl/init/gl_initializer_x11.cc
-+++ ui/gl/init/gl_initializer_x11.cc
-@@ -86,7 +86,7 @@ bool InitializeStaticEGLInternal(GLImplementation implementation) {
-   if (implementation == kGLImplementationSwiftShaderGL) {
- #if BUILDFLAG(ENABLE_SWIFTSHADER)
+diff --git ui/ozone/common/egl_util.cc ui/ozone/common/egl_util.cc
+index 021bcad8c3084..a37406d408718 100644
+--- ui/ozone/common/egl_util.cc
++++ ui/ozone/common/egl_util.cc
+@@ -127,7 +127,7 @@ bool LoadDefaultEGLGLES2Bindings(
+   if (implementation.gl == gl::kGLImplementationEGLANGLE) {
      base::FilePath module_path;
+ #if !BUILDFLAG(IS_FUCHSIA)
 -    if (!base::PathService::Get(base::DIR_MODULE, &module_path))
 +    if (!base::PathService::Get(base::DIR_ASSETS, &module_path))
        return false;
-     module_path = module_path.Append("swiftshader/");
- 
-@@ -97,7 +97,7 @@ bool InitializeStaticEGLInternal(GLImplementation implementation) {
  #endif
-   } else if (implementation == kGLImplementationEGLANGLE) {
-     base::FilePath module_path;
--    if (!base::PathService::Get(base::DIR_MODULE, &module_path))
-+    if (!base::PathService::Get(base::DIR_ASSETS, &module_path))
-       return false;
  
-     glesv2_path = module_path.Append(kGLESv2ANGLELibraryName);
diff --git a/src/patch/patches/linux_atk_1123214.patch b/src/patch/patches/linux_atk_1123214.patch
new file mode 100644
index 0000000..3c35c15
--- /dev/null
+++ b/src/patch/patches/linux_atk_1123214.patch
@@ -0,0 +1,26 @@
+diff --git build/config/linux/atk/BUILD.gn build/config/linux/atk/BUILD.gn
+index 239c3870a149a..9f5a34fc846bd 100644
+--- build/config/linux/atk/BUILD.gn
++++ build/config/linux/atk/BUILD.gn
+@@ -11,7 +11,7 @@ import("//build/config/ui.gni")
+ assert(!is_chromeos)
+ 
+ # These packages should _only_ be expected when building for a target.
+-assert(current_toolchain == default_toolchain)
++# assert(current_toolchain == default_toolchain)
+ 
+ if (use_atk) {
+   assert(use_glib, "use_atk=true requires that use_glib=true")
+diff --git build/config/linux/atspi2/BUILD.gn build/config/linux/atspi2/BUILD.gn
+index d1629205c82a3..21de94bee534b 100644
+--- build/config/linux/atspi2/BUILD.gn
++++ build/config/linux/atspi2/BUILD.gn
+@@ -6,7 +6,7 @@ import("//build/config/linux/pkg_config.gni")
+ import("//build/config/ui.gni")
+ 
+ # These packages should _only_ be expected when building for a target.
+-assert(current_toolchain == default_toolchain)
++# assert(current_toolchain == default_toolchain)
+ 
+ if (use_atk) {
+   pkg_config("atspi2") {
diff --git a/src/patch/patches/linux_blink_thread_local.patch b/src/patch/patches/linux_blink_thread_local.patch
new file mode 100644
index 0000000..1516ff0
--- /dev/null
+++ b/src/patch/patches/linux_blink_thread_local.patch
@@ -0,0 +1,13 @@
+diff --git third_party/blink/renderer/platform/heap/thread_local.h third_party/blink/renderer/platform/heap/thread_local.h
+index e0519b0982e43..40637ce5952e3 100644
+--- third_party/blink/renderer/platform/heap/thread_local.h
++++ third_party/blink/renderer/platform/heap/thread_local.h
+@@ -36,7 +36,7 @@
+ #if BLINK_HEAP_HIDE_THREAD_LOCAL_IN_LIBRARY
+ #define BLINK_HEAP_THREAD_LOCAL_MODEL "local-dynamic"
+ #else
+-#if BUILDFLAG(IS_WIN)
++#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC))
+ #define BLINK_HEAP_THREAD_LOCAL_MODEL "initial-exec"
+ #elif BUILDFLAG(IS_ANDROID)
+ #define BLINK_HEAP_THREAD_LOCAL_MODEL "local-dynamic"
diff --git a/src/patch/patches/linux_bluetooth_1319006.patch b/src/patch/patches/linux_bluetooth_1319006.patch
new file mode 100644
index 0000000..5021761
--- /dev/null
+++ b/src/patch/patches/linux_bluetooth_1319006.patch
@@ -0,0 +1,21 @@
+diff --git device/bluetooth/BUILD.gn device/bluetooth/BUILD.gn
+index 003a2504dd681..782c83813dfc6 100644
+--- device/bluetooth/BUILD.gn
++++ device/bluetooth/BUILD.gn
+@@ -47,10 +47,12 @@ source_set("deprecated_experimental_mojo") {
+   ]
+ 
+   if (is_chromeos || is_linux) {
+-    sources += [
+-      "bluez/metrics_recorder.cc",
+-      "bluez/metrics_recorder.h",
+-    ]
++    if (is_component_build) {
++      sources += [
++        "bluez/metrics_recorder.cc",
++        "bluez/metrics_recorder.h",
++      ]
++    }
+   }
+ 
+   deps = [
diff --git a/src/patch/patches/linux_chrome_views_1085806.patch b/src/patch/patches/linux_chrome_views_1085806.patch
deleted file mode 100644
index 32e2538..0000000
--- a/src/patch/patches/linux_chrome_views_1085806.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.cc chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.cc
-index f76fb26d4780..4cc511600b3b 100644
---- chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.cc
-+++ chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.cc
-@@ -48,7 +48,7 @@ ChromeBrowserMainExtraPartsViewsLinux::
- }
- 
- void ChromeBrowserMainExtraPartsViewsLinux::ToolkitInitialized() {
--#if defined(USE_X11)
-+#if defined(USE_X11) && BUILDFLAG(USE_GTK)
-   // In Aura/X11, Gtk-based LinuxUI implementation is used, so we instantiate
-   // and inject the GtkUiDelegate before ChromeBrowserMainExtraPartsViewsLinux,
-   // so it can properly initialize GtkUi on its |ToolkitInitialized| override.
diff --git a/src/patch/patches/linux_chrome_widevine_3149.patch b/src/patch/patches/linux_chrome_widevine_3149.patch
new file mode 100644
index 0000000..3b46251
--- /dev/null
+++ b/src/patch/patches/linux_chrome_widevine_3149.patch
@@ -0,0 +1,58 @@
+diff --git chrome/common/media/component_widevine_cdm_hint_file_linux.cc chrome/common/media/component_widevine_cdm_hint_file_linux.cc
+index d529ecfb270c4..2e922ef345f04 100644
+--- chrome/common/media/component_widevine_cdm_hint_file_linux.cc
++++ chrome/common/media/component_widevine_cdm_hint_file_linux.cc
+@@ -16,6 +16,7 @@
+ #include "base/path_service.h"
+ #include "base/values.h"
+ #include "chrome/common/chrome_paths.h"
++#include "third_party/widevine/cdm/widevine_cdm_common.h"
+ 
+ namespace {
+ 
+@@ -35,14 +36,33 @@ base::FilePath GetPath(const base::Value::Dict& dict) {
+   return path;
+ }
+ 
++// On Linux the Widevine CDM is loaded into the zygote at startup. When the
++// component updater runs sometime later and finds a newer version of the
++// Widevine CDM, don't register it as the newer version can't be used. Instead,
++// save the path to the new Widevine CDM in this file. Next time at startup this
++// file will be checked, and if it references a usable Widevine CDM, use this
++// version instead of the old (potentially bundled) CDM.
++// Add this method instead of using chrome::FILE_COMPONENT_WIDEVINE_CDM_HINT
++// because only directories (not files) can be configured via
++// base::PathService::Override.
++bool GetHintFilePath(base::FilePath* hint_file_path) {
++  base::FilePath user_data_dir;
++  if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
++    return false;
++  // Match the file name in chrome/common/chrome_paths.cc
++  *hint_file_path = user_data_dir
++      .AppendASCII(kWidevineCdmBaseDirectory)
++      .Append(FILE_PATH_LITERAL("latest-component-updated-widevine-cdm"));
++  return true;
++}
++
+ }  // namespace
+ 
+ bool UpdateWidevineCdmHintFile(const base::FilePath& cdm_base_path) {
+   DCHECK(!cdm_base_path.empty());
+ 
+   base::FilePath hint_file_path;
+-  CHECK(base::PathService::Get(chrome::FILE_COMPONENT_WIDEVINE_CDM_HINT,
+-                               &hint_file_path));
++  CHECK(GetHintFilePath(&hint_file_path));
+ 
+   base::Value::Dict dict;
+   dict.Set(kPath, cdm_base_path.value());
+@@ -60,8 +80,7 @@ bool UpdateWidevineCdmHintFile(const base::FilePath& cdm_base_path) {
+ 
+ base::FilePath GetLatestComponentUpdatedWidevineCdmDirectory() {
+   base::FilePath hint_file_path;
+-  CHECK(base::PathService::Get(chrome::FILE_COMPONENT_WIDEVINE_CDM_HINT,
+-                               &hint_file_path));
++  CHECK(GetHintFilePath(&hint_file_path));
+ 
+   if (!base::PathExists(hint_file_path)) {
+     DVLOG(2) << "CDM hint file at " << hint_file_path << " does not exist.";
diff --git a/src/patch/patches/linux_glib_deprecated_volatile.patch b/src/patch/patches/linux_glib_deprecated_volatile.patch
new file mode 100644
index 0000000..8b3685c
--- /dev/null
+++ b/src/patch/patches/linux_glib_deprecated_volatile.patch
@@ -0,0 +1,28 @@
+diff --git ui/accessibility/platform/BUILD.gn ui/accessibility/platform/BUILD.gn
+index 4e23c38763184..162f8b453f4ac 100644
+--- ui/accessibility/platform/BUILD.gn
++++ ui/accessibility/platform/BUILD.gn
+@@ -287,6 +287,10 @@ component("platform") {
+       if (use_gio) {
+         configs += [ "//build/linux:gio_config" ]
+       }
++
++      if (is_clang) {
++        cflags = [ "-Wno-deprecated-volatile" ]
++      }
+     }
+   }
+ }
+diff --git ui/gtk/BUILD.gn ui/gtk/BUILD.gn
+index f4c5a2bcebbb7..5faf19980b1bd 100644
+--- ui/gtk/BUILD.gn
++++ ui/gtk/BUILD.gn
+@@ -174,4 +174,8 @@ component("gtk") {
+ 
+   # TODO: This should be removed.
+   deps += [ "//ui/ozone" ]
++
++  if (is_clang) {
++    cflags = [ "-Wno-deprecated-volatile" ]
++  }
+ }
diff --git a/src/patch/patches/linux_libxml_tls_3616.patch b/src/patch/patches/linux_libxml_tls_3616.patch
new file mode 100644
index 0000000..2e40561
--- /dev/null
+++ b/src/patch/patches/linux_libxml_tls_3616.patch
@@ -0,0 +1,13 @@
+diff --git third_party/libxml/linux/config.h third_party/libxml/linux/config.h
+index c064071ce1545..65110af9a78f5 100644
+--- third_party/libxml/linux/config.h
++++ third_party/libxml/linux/config.h
+@@ -171,7 +171,7 @@
+ /* #undef XML_SOCKLEN_T */
+ 
+ /* TLS specifier */
+-#define XML_THREAD_LOCAL _Thread_local
++/* #undef XML_THREAD_LOCAL */
+ 
+ /* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
+    <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
diff --git a/src/patch/patches/linux_poll_2466.patch b/src/patch/patches/linux_poll_2466.patch
deleted file mode 100644
index 1ffb92f..0000000
--- a/src/patch/patches/linux_poll_2466.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-diff --git base/files/file_path_watcher_linux.cc base/files/file_path_watcher_linux.cc
-index 563e08067585..3200fa658457 100644
---- base/files/file_path_watcher_linux.cc
-+++ base/files/file_path_watcher_linux.cc
-@@ -5,6 +5,7 @@
- #include "base/files/file_path_watcher.h"
- 
- #include <errno.h>
-+#include <poll.h>
- #include <stddef.h>
- #include <string.h>
- #include <sys/inotify.h>
-@@ -13,6 +14,7 @@
- #include <unistd.h>
- 
- #include <algorithm>
-+#include <array>
- #include <fstream>
- #include <map>
- #include <memory>
-@@ -263,8 +265,10 @@ void InotifyReaderThreadDelegate::ThreadMain() {
-   PlatformThread::SetName("inotify_reader");
- 
-   // Make sure the file descriptors are good for use with select().
--  CHECK_LE(0, inotify_fd_);
--  CHECK_GT(FD_SETSIZE, inotify_fd_);
-+  std::array<pollfd, 1> fdarray
-+  { {
-+      { inotify_fd_, POLLIN, 0 }
-+  } };
- 
-   while (true) {
-     fd_set rfds;
-@@ -272,10 +276,9 @@ void InotifyReaderThreadDelegate::ThreadMain() {
-     FD_SET(inotify_fd_, &rfds);
- 
-     // Wait until some inotify events are available.
--    int select_result =
--        HANDLE_EINTR(select(inotify_fd_ + 1, &rfds, nullptr, nullptr, nullptr));
--    if (select_result < 0) {
--      DPLOG(WARNING) << "select failed";
-+    int poll_result = HANDLE_EINTR(poll(fdarray.data(), fdarray.size(), -1));
-+    if (poll_result < 0) {
-+      DPLOG(WARNING) << "poll failed";
-       return;
-     }
- 
diff --git a/src/patch/patches/linux_printing_context.patch b/src/patch/patches/linux_printing_context.patch
new file mode 100644
index 0000000..e35365d
--- /dev/null
+++ b/src/patch/patches/linux_printing_context.patch
@@ -0,0 +1,136 @@
+diff --git printing/printing_context_linux.cc printing/printing_context_linux.cc
+index ab6cda8e54b37..164b3ef67445a 100644
+--- printing/printing_context_linux.cc
++++ printing/printing_context_linux.cc
+@@ -73,11 +73,11 @@ mojom::ResultCode PrintingContextLinux::UseDefaultSettings() {
+   ResetSettings();
+ 
+ #if BUILDFLAG(IS_LINUX)
+-  if (!ui::LinuxUi::instance())
++  if (!ui::PrintingContextLinuxDelegate::instance())
+     return mojom::ResultCode::kSuccess;
+ 
+   if (!print_dialog_)
+-    print_dialog_ = ui::LinuxUi::instance()->CreatePrintDialog(this);
++    print_dialog_ = ui::PrintingContextLinuxDelegate::instance()->CreatePrintDialog(this);
+ 
+   if (print_dialog_) {
+     print_dialog_->UseDefaultSettings();
+@@ -89,8 +89,8 @@ mojom::ResultCode PrintingContextLinux::UseDefaultSettings() {
+ 
+ gfx::Size PrintingContextLinux::GetPdfPaperSizeDeviceUnits() {
+ #if BUILDFLAG(IS_LINUX)
+-  if (ui::LinuxUi::instance())
+-    return ui::LinuxUi::instance()->GetPdfPaperSize(this);
++  if (ui::PrintingContextLinuxDelegate::instance())
++    return ui::PrintingContextLinuxDelegate::instance()->GetPdfPaperSize(this);
+ #endif
+ 
+   return gfx::Size();
+@@ -102,11 +102,11 @@ mojom::ResultCode PrintingContextLinux::UpdatePrinterSettings(
+   DCHECK(!in_print_job_);
+ 
+ #if BUILDFLAG(IS_LINUX)
+-  if (!ui::LinuxUi::instance())
++  if (!ui::PrintingContextLinuxDelegate::instance())
+     return mojom::ResultCode::kSuccess;
+ 
+   if (!print_dialog_)
+-    print_dialog_ = ui::LinuxUi::instance()->CreatePrintDialog(this);
++    print_dialog_ = ui::PrintingContextLinuxDelegate::instance()->CreatePrintDialog(this);
+ 
+   if (print_dialog_) {
+     // PrintDialogGtk::UpdateSettings() calls InitWithSettings() so settings_ will
+diff --git ui/linux/linux_ui.cc ui/linux/linux_ui.cc
+index 29db798e8b171..f8b9546b90321 100644
+--- ui/linux/linux_ui.cc
++++ ui/linux/linux_ui.cc
+@@ -18,11 +18,29 @@ namespace ui {
+ namespace {
+ 
+ LinuxUi* g_linux_ui = nullptr;
++static PrintingContextLinuxDelegate* g_delegate = nullptr;
+ 
+ }  // namespace
+ 
++// static
++PrintingContextLinuxDelegate* PrintingContextLinuxDelegate::SetInstance(
++    PrintingContextLinuxDelegate* delegate) {
++  auto old_delegate = g_delegate;
++  g_delegate = delegate;
++  return old_delegate;
++}
++
++// static
++PrintingContextLinuxDelegate* PrintingContextLinuxDelegate::instance() {
++  return g_delegate;
++}
++
+ // static
+ LinuxUi* LinuxUi::SetInstance(LinuxUi* instance) {
++#if BUILDFLAG(IS_LINUX) && BUILDFLAG(ENABLE_PRINTING)
++  PrintingContextLinuxDelegate::SetInstance(instance);
++#endif
++
+   return std::exchange(g_linux_ui, instance);
+ }
+ 
+diff --git ui/linux/linux_ui.h ui/linux/linux_ui.h
+index a47134d7fa672..4fef62bbec3ee 100644
+--- ui/linux/linux_ui.h
++++ ui/linux/linux_ui.h
+@@ -19,6 +19,10 @@
+ #include "printing/buildflags/buildflags.h"
+ #include "ui/gfx/geometry/rect.h"
+ 
++#if BUILDFLAG(ENABLE_PRINTING)
++#include "printing/printing_context_linux.h"  // nogncheck
++#endif
++
+ // The main entrypoint into Linux toolkit specific code. GTK/QT code should only
+ // be executed behind this interface.
+ 
+@@ -92,9 +96,27 @@ inline DisplayConfig::DisplayConfig(DisplayConfig&& other) = default;
+ inline DisplayConfig& DisplayConfig::operator=(DisplayConfig&& other) = default;
+ inline DisplayConfig::~DisplayConfig() = default;
+ 
++class COMPONENT_EXPORT(LINUX_UI) PrintingContextLinuxDelegate {
++ public:
++  virtual ~PrintingContextLinuxDelegate() = default;
++
++  virtual printing::PrintDialogLinuxInterface* CreatePrintDialog(
++      printing::PrintingContextLinux* context) = 0;
++
++  virtual gfx::Size GetPdfPaperSize(printing::PrintingContextLinux* context) = 0;
++
++  static PrintingContextLinuxDelegate* SetInstance(
++      PrintingContextLinuxDelegate* delegate);
++  static PrintingContextLinuxDelegate* instance();
++};
++
+ // Adapter class with targets to render like different toolkits. Set by any
+ // project that wants to do linux desktop native rendering.
+-class COMPONENT_EXPORT(LINUX_UI) LinuxUi {
++class COMPONENT_EXPORT(LINUX_UI) LinuxUi
++#if BUILDFLAG(ENABLE_PRINTING)
++    : public PrintingContextLinuxDelegate
++#endif
++ {
+  public:
+   // Describes the window management actions that could be taken in response to
+   // a middle click in the non client area.
+@@ -161,14 +183,6 @@ class COMPONENT_EXPORT(LINUX_UI) LinuxUi {
+   // Returns a map of KeyboardEvent code to KeyboardEvent key values.
+   virtual base::flat_map<std::string, std::string> GetKeyboardLayoutMap() = 0;
+ 
+-#if BUILDFLAG(ENABLE_PRINTING)
+-  virtual printing::PrintDialogLinuxInterface* CreatePrintDialog(
+-      printing::PrintingContextLinux* context) = 0;
+-
+-  virtual gfx::Size GetPdfPaperSize(
+-      printing::PrintingContextLinux* context) = 0;
+-#endif
+-
+   // Returns a native file selection dialog.  `listener` is of type
+   // SelectFileDialog::Listener.  TODO(thomasanderson): Move
+   // SelectFileDialog::Listener to SelectFileDialogListener so that it can be
diff --git a/src/patch/patches/mac_event_observer_2539.patch b/src/patch/patches/mac_event_observer_2539.patch
index a384086..25f5625 100644
--- a/src/patch/patches/mac_event_observer_2539.patch
+++ b/src/patch/patches/mac_event_observer_2539.patch
@@ -1,9 +1,9 @@
 diff --git content/browser/scheduler/responsiveness/native_event_observer_mac.mm content/browser/scheduler/responsiveness/native_event_observer_mac.mm
-index 7cb3238e97ed..ae800739b686 100644
+index d7f32cb53ea3a..2bab5de59657f 100644
 --- content/browser/scheduler/responsiveness/native_event_observer_mac.mm
 +++ content/browser/scheduler/responsiveness/native_event_observer_mac.mm
-@@ -12,13 +12,15 @@ namespace content {
- namespace responsiveness {
+@@ -11,13 +11,15 @@
+ namespace content::responsiveness {
  
  void NativeEventObserver::RegisterObserver() {
 -  DCHECK([NSApp conformsToProtocol:@protocol(NativeEventProcessor)]);
diff --git a/src/patch/patches/mac_fling_scheduler_2540.patch b/src/patch/patches/mac_fling_scheduler_2540.patch
index 8a7776a..fa98a94 100644
--- a/src/patch/patches/mac_fling_scheduler_2540.patch
+++ b/src/patch/patches/mac_fling_scheduler_2540.patch
@@ -1,5 +1,5 @@
 diff --git content/browser/renderer_host/input/fling_scheduler_mac.mm content/browser/renderer_host/input/fling_scheduler_mac.mm
-index f10c5d161dd1..92a751dd984e 100644
+index 50ed39df38044..7839bdaf7b7e5 100644
 --- content/browser/renderer_host/input/fling_scheduler_mac.mm
 +++ content/browser/renderer_host/input/fling_scheduler_mac.mm
 @@ -26,6 +26,10 @@ ui::Compositor* FlingSchedulerMac::GetCompositor() {
diff --git a/src/patch/patches/mac_gpu.patch b/src/patch/patches/mac_gpu.patch
deleted file mode 100644
index 8123410..0000000
--- a/src/patch/patches/mac_gpu.patch
+++ /dev/null
@@ -1,18 +0,0 @@
-diff --git ui/gl/init/gl_initializer_mac.cc ui/gl/init/gl_initializer_mac.cc
-index 0deebafe135f..fdbd9a7ecf17 100644
---- ui/gl/init/gl_initializer_mac.cc
-+++ ui/gl/init/gl_initializer_mac.cc
-@@ -46,11 +46,8 @@ bool InitializeOneOffForSandbox() {
-   // GPU-related stuff is very slow without this, probably because
-   // the sandbox prevents loading graphics drivers or some such.
-   std::vector<CGLPixelFormatAttribute> attribs;
--  if (GLContext::SwitchableGPUsSupported()) {
--    // Avoid switching to the discrete GPU just for this pixel
--    // format selection.
--    attribs.push_back(kCGLPFAAllowOfflineRenderers);
--  }
-+  // Avoid switching to the discrete GPU just for this pixel format selection.
-+  attribs.push_back(kCGLPFAAllowOfflineRenderers);
-   if (GetGLImplementation() == kGLImplementationAppleGL) {
-     attribs.push_back(kCGLPFARendererID);
-     attribs.push_back(
diff --git a/src/patch/patches/mac_keyboard_conversion_1467329.patch b/src/patch/patches/mac_keyboard_conversion_1467329.patch
new file mode 100644
index 0000000..db2260c
--- /dev/null
+++ b/src/patch/patches/mac_keyboard_conversion_1467329.patch
@@ -0,0 +1,13 @@
+diff --git ui/events/keycodes/keyboard_code_conversion_mac.mm ui/events/keycodes/keyboard_code_conversion_mac.mm
+index 593b5c2ddcd7d..f03d37b12c13d 100644
+--- ui/events/keycodes/keyboard_code_conversion_mac.mm
++++ ui/events/keycodes/keyboard_code_conversion_mac.mm
+@@ -935,7 +935,7 @@ DomKey DomKeyFromNSEvent(NSEvent* event) {
+       return DomKeyFromKeyCode(event.keyCode);
+     }
+     default:
+-      NOTREACHED_NORETURN();
++      return ui::DomKey::NONE;
+   }
+ }
+ 
diff --git a/src/patch/patches/mac_platform_style_bubble_893292.patch b/src/patch/patches/mac_platform_style_bubble_893292.patch
new file mode 100644
index 0000000..6dcd9cd
--- /dev/null
+++ b/src/patch/patches/mac_platform_style_bubble_893292.patch
@@ -0,0 +1,28 @@
+diff --git chrome/browser/ui/views/profiles/profile_menu_view_base.cc chrome/browser/ui/views/profiles/profile_menu_view_base.cc
+index 4c6746fd7340e..b93121002c27f 100644
+--- chrome/browser/ui/views/profiles/profile_menu_view_base.cc
++++ chrome/browser/ui/views/profiles/profile_menu_view_base.cc
+@@ -1022,8 +1022,8 @@ int ProfileMenuViewBase::GetMaxHeight() const {
+           ->GetDisplayNearestPoint(anchor_rect.CenterPoint())
+           .work_area();
+   int available_space = screen_space.bottom() - anchor_rect.bottom();
+-#if BUILDFLAG(IS_WIN)
+-  // On Windows the bubble can also be show to the top of the anchor.
++#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
++  // On Windows and macOS the bubble can also be show to the top of the anchor.
+   available_space =
+       std::max(available_space, anchor_rect.y() - screen_space.y());
+ #endif
+diff --git ui/views/style/platform_style_mac.mm ui/views/style/platform_style_mac.mm
+index 5036a02362c6d..54d7c9b6b58fb 100644
+--- ui/views/style/platform_style_mac.mm
++++ ui/views/style/platform_style_mac.mm
+@@ -43,7 +43,7 @@ const bool PlatformStyle::kTableViewSupportsKeyboardNavigationByCell = false;
+ const bool PlatformStyle::kTreeViewSelectionPaintsEntireRow = true;
+ const bool PlatformStyle::kUseRipples = false;
+ const bool PlatformStyle::kInactiveWidgetControlsAppearDisabled = true;
+-const bool PlatformStyle::kAdjustBubbleIfOffscreen = false;
++const bool PlatformStyle::kAdjustBubbleIfOffscreen = true;
+ const View::FocusBehavior PlatformStyle::kDefaultFocusBehavior =
+     View::FocusBehavior::ACCESSIBLE_ONLY;
+ 
diff --git a/src/patch/patches/message_loop.patch b/src/patch/patches/message_loop.patch
index dd2c938..c326151 100644
--- a/src/patch/patches/message_loop.patch
+++ b/src/patch/patches/message_loop.patch
@@ -1,39 +1,70 @@
-diff --git base/message_loop/message_loop_current.cc base/message_loop/message_loop_current.cc
-index 7688ba3d7b0d..9acaaa0d5c7f 100644
---- base/message_loop/message_loop_current.cc
-+++ base/message_loop/message_loop_current.cc
-@@ -47,6 +47,8 @@ void MessageLoopCurrent::AddDestructionObserver(
+diff --git base/message_loop/message_pump_win.cc base/message_loop/message_pump_win.cc
+index 9425ad4ba5432..20a6c1c9c74fa 100644
+--- base/message_loop/message_pump_win.cc
++++ base/message_loop/message_pump_win.cc
+@@ -2,6 +2,7 @@
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
  
- void MessageLoopCurrent::RemoveDestructionObserver(
++#include "base/task/current_thread.h"
+ #include "base/message_loop/message_pump_win.h"
+ 
+ #include <algorithm>
+@@ -496,7 +497,17 @@ bool MessagePumpForUI::ProcessNextWindowsMessage() {
+                 ctx.event()->set_chrome_message_pump();
+             msg_pump_data->set_sent_messages_in_queue(more_work_is_plausible);
+           });
+-      has_msg = ::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) != FALSE;
++ 
++      // We should not process all window messages if we are in the context of an
++      // OS modal loop, i.e. in the context of a windows API call like MessageBox.
++      // This is to ensure that these messages are peeked out by the OS modal loop.
++      if (CurrentThread::Get()->os_modal_loop()) {
++        // We only peek out WM_PAINT and WM_TIMER here for reasons mentioned above.
++        has_msg = PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) ||
++                  PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE);
++      } else {
++        has_msg = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != FALSE;
++      }
+     }
+   }
+   if (has_msg)
+diff --git base/task/current_thread.cc base/task/current_thread.cc
+index b062ee6f827b7..675a604f4b859 100644
+--- base/task/current_thread.cc
++++ base/task/current_thread.cc
+@@ -48,6 +48,8 @@ void CurrentThread::AddDestructionObserver(
+ 
+ void CurrentThread::RemoveDestructionObserver(
      DestructionObserver* destruction_observer) {
 +  if (!current_)
 +    return;
    DCHECK(current_->IsBoundToCurrentThread());
    current_->RemoveDestructionObserver(destruction_observer);
  }
-diff --git base/message_loop/message_loop_current.h base/message_loop/message_loop_current.h
-index 61b8c6fcc42d..d439b00a87bb 100644
---- base/message_loop/message_loop_current.h
-+++ base/message_loop/message_loop_current.h
-@@ -117,6 +117,12 @@ class BASE_EXPORT MessageLoopCurrent {
-   // posted tasks.
-   void SetAddQueueTimeToTasks(bool enable);
+diff --git base/task/current_thread.h base/task/current_thread.h
+index c7e113456e011..041656ff606a8 100644
+--- base/task/current_thread.h
++++ base/task/current_thread.h
+@@ -133,6 +133,12 @@ class BASE_EXPORT CurrentThread {
+   // with a null callback to clear any potentially pending callbacks.
+   void RegisterOnNextIdleCallback(OnceClosure on_next_idle_callback);
  
-+#if defined(OS_WIN)
++#if BUILDFLAG(IS_WIN)
 +  void set_os_modal_loop(bool os_modal_loop) { os_modal_loop_ = os_modal_loop; }
 +
 +  bool os_modal_loop() const { return os_modal_loop_; }
 +#endif  // OS_WIN
 +
-   // Enables or disables the recursive task processing. This happens in the case
-   // of recursive message loops. Some unwanted message loops may occur when
-   // using common controls or printer functions. By default, recursive task
-@@ -186,6 +192,13 @@ class BASE_EXPORT MessageLoopCurrent {
+   // Enables nested task processing in scope of an upcoming native message loop.
+   // Some unwanted message loops may occur when using common controls or printer
+   // functions. Hence, nested task processing is disabled by default to avoid
+@@ -197,6 +203,13 @@ class BASE_EXPORT CurrentThread {
    friend class web::WebTaskEnvironment;
  
-   sequence_manager::internal::SequenceManagerImpl* current_;
+   raw_ptr<sequence_manager::internal::SequenceManagerImpl> current_;
 +
-+#if defined(OS_WIN)
++#if BUILDFLAG(IS_WIN)
 + private:
 +  // Should be set to true before calling Windows APIs like TrackPopupMenu, etc.
 +  // which enter a modal message loop.
@@ -41,38 +72,4 @@
 +#endif
  };
  
- #if !defined(OS_NACL)
-diff --git base/message_loop/message_pump_win.cc base/message_loop/message_pump_win.cc
-index c50e34f6da1b..40dcc66ed82a 100644
---- base/message_loop/message_pump_win.cc
-+++ base/message_loop/message_pump_win.cc
-@@ -2,6 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- 
-+#include "base/message_loop/message_loop_current.h"
- #include "base/message_loop/message_pump_win.h"
- 
- #include <algorithm>
-@@ -493,10 +494,18 @@ bool MessagePumpForUI::ProcessPumpReplacementMessage() {
-   // asynchronous to this thread!!
- 
-   MSG msg;
--  const bool have_message =
--      ::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) != FALSE;
-+  bool have_message = false;
-+  // We should not process all window messages if we are in the context of an
-+  // OS modal loop, i.e. in the context of a windows API call like MessageBox.
-+  // This is to ensure that these messages are peeked out by the OS modal loop.
-+  if (MessageLoopCurrent::Get()->os_modal_loop()) {
-+    // We only peek out WM_PAINT and WM_TIMER here for reasons mentioned above.
-+    have_message = PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) ||
-+                   PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE);
-+  } else {
-+    have_message = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != FALSE;
-+  }
- 
--  // Expect no message or a message different than kMsgHaveWork.
-   DCHECK(!have_message || kMsgHaveWork != msg.message ||
-          msg.hwnd != message_window_.hwnd());
- 
+ #if !BUILDFLAG(IS_NACL)
diff --git a/src/patch/patches/message_pump_mac_2495.patch b/src/patch/patches/message_pump_mac_2495.patch
index cab8923..2f029a6 100644
--- a/src/patch/patches/message_pump_mac_2495.patch
+++ b/src/patch/patches/message_pump_mac_2495.patch
@@ -1,8 +1,8 @@
-diff --git base/message_loop/message_pump_mac.mm base/message_loop/message_pump_mac.mm
-index bb9e6d30bedd..e5ef7077c9de 100644
---- base/message_loop/message_pump_mac.mm
-+++ base/message_loop/message_pump_mac.mm
-@@ -785,7 +785,8 @@ void MessagePumpUIApplication::Detach() {
+diff --git base/message_loop/message_pump_apple.mm base/message_loop/message_pump_apple.mm
+index a79ef2f20a507..33856ab5322c2 100644
+--- base/message_loop/message_pump_apple.mm
++++ base/message_loop/message_pump_apple.mm
+@@ -762,7 +762,8 @@ void MessagePumpUIApplication::Detach() {
  #else
  
  ScopedPumpMessagesInPrivateModes::ScopedPumpMessagesInPrivateModes() {
@@ -12,7 +12,7 @@
    DCHECK_EQ(kNSApplicationModalSafeModeMask, g_app_pump->GetModeMask());
    // Pumping events in private runloop modes is known to interact badly with
    // app modal windows like NSAlert.
-@@ -797,7 +798,8 @@ ScopedPumpMessagesInPrivateModes::ScopedPumpMessagesInPrivateModes() {
+@@ -773,7 +774,8 @@ ScopedPumpMessagesInPrivateModes::ScopedPumpMessagesInPrivateModes() {
  }
  
  ScopedPumpMessagesInPrivateModes::~ScopedPumpMessagesInPrivateModes() {
@@ -20,5 +20,5 @@
 +  if (!g_app_pump)
 +    return;
    g_app_pump->SetModeMask(kNSApplicationModalSafeModeMask);
-   g_app_pump->SetTimerInvalidationAllowed(true);
  }
+ 
diff --git a/src/patch/patches/metrics_system_profile.patch b/src/patch/patches/metrics_system_profile.patch
new file mode 100644
index 0000000..9f20ed0
--- /dev/null
+++ b/src/patch/patches/metrics_system_profile.patch
@@ -0,0 +1,30 @@
+diff --git components/metrics/persistent_system_profile.cc components/metrics/persistent_system_profile.cc
+index 83c0308a977a0..9859e33d3ce7e 100644
+--- components/metrics/persistent_system_profile.cc
++++ components/metrics/persistent_system_profile.cc
+@@ -392,6 +392,10 @@ bool PersistentSystemProfile::GetSystemProfile(
+   return true;
+ }
+ 
++void PersistentSystemProfile::DetachFromCurrentThread() {
++  DETACH_FROM_THREAD(thread_checker_);
++}
++
+ // static
+ void PersistentSystemProfile::MergeUpdateRecords(
+     const base::PersistentMemoryAllocator& memory_allocator,
+diff --git components/metrics/persistent_system_profile.h components/metrics/persistent_system_profile.h
+index fc173051fb8c1..3fcc43880e89d 100644
+--- components/metrics/persistent_system_profile.h
++++ components/metrics/persistent_system_profile.h
+@@ -64,6 +64,10 @@ class PersistentSystemProfile {
+       const base::PersistentMemoryAllocator& memory_allocator,
+       SystemProfileProto* system_profile);
+ 
++  // Detaches this object from the current thread in preparation for a move to
++  // a different thread.
++  void DetachFromCurrentThread();
++
+  private:
+   friend class PersistentSystemProfileTest;
+ 
diff --git a/src/patch/patches/mime_handler_view_guest_1565_2727.patch b/src/patch/patches/mime_handler_view_guest_1565_2727.patch
index 34fe80d..6c8e5c9 100644
--- a/src/patch/patches/mime_handler_view_guest_1565_2727.patch
+++ b/src/patch/patches/mime_handler_view_guest_1565_2727.patch
@@ -1,80 +1,87 @@
 diff --git content/browser/web_contents/web_contents_view.h content/browser/web_contents/web_contents_view.h
-index c0cd19506973..956d80443c11 100644
+index dc763b0fac47b..d8b63a0f62267 100644
 --- content/browser/web_contents/web_contents_view.h
 +++ content/browser/web_contents/web_contents_view.h
-@@ -23,7 +23,7 @@ struct DropData;
- // The WebContentsView is an interface that is implemented by the platform-
- // dependent web contents views. The WebContents uses this interface to talk to
- // them.
+@@ -25,7 +25,7 @@ struct DropData;
+ // The `WebContentsView` is an interface that is implemented by the platform-
+ // dependent web contents views. The `WebContents` uses this interface to talk
+ // to them.
 -class WebContentsView {
 +class CONTENT_EXPORT WebContentsView {
   public:
-   virtual ~WebContentsView() {}
+   virtual ~WebContentsView() = default;
  
 diff --git extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
-index 068b22336fac..a970f5be0428 100644
+index 0fc4a40faf070..66b40489529e2 100644
 --- extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
 +++ extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
-@@ -207,6 +207,8 @@ void MimeHandlerViewGuest::CreateWebContents(
+@@ -202,6 +202,8 @@ void MimeHandlerViewGuest::CreateWebContents(
    WebContents::CreateParams params(browser_context(),
                                     guest_site_instance.get());
    params.guest_delegate = this;
 +  if (delegate_)
 +    delegate_->OverrideWebContentsCreateParams(&params);
-   // TODO(erikchen): Fix ownership semantics for guest views.
-   // https://crbug.com/832879.
-   std::move(callback).Run(
-@@ -217,6 +219,9 @@ void MimeHandlerViewGuest::CreateWebContents(
+   std::move(callback).Run(std::move(owned_this),
+                           WebContents::CreateWithSessionStorage(
+                               params, owner_web_contents()
+@@ -210,6 +212,10 @@ void MimeHandlerViewGuest::CreateWebContents(
  }
  
  void MimeHandlerViewGuest::DidAttachToEmbedder() {
++  is_guest_attached_ = true;
 +  if (delegate_)
 +    delegate_->OnGuestAttached();
 +
-   web_contents()->GetController().LoadURL(
-       stream_->handler_url(), content::Referrer(),
-       ui::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string());
-@@ -246,6 +251,11 @@ bool MimeHandlerViewGuest::ShouldDestroyOnDetach() const {
-   return true;
+   DCHECK(stream_->handler_url().SchemeIs(extensions::kExtensionScheme));
+   GetController().LoadURL(stream_->handler_url(), content::Referrer(),
+                           ui::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string());
+@@ -474,6 +480,14 @@ void MimeHandlerViewGuest::DidFinishNavigation(
+   }
  }
  
-+void MimeHandlerViewGuest::WillDestroy() {
-+  if (delegate_)
++void MimeHandlerViewGuest::WebContentsDestroyed() {
++  if (is_guest_attached_ && delegate_)
 +    delegate_->OnGuestDetached();
++
++  // May delete |this|.
++  GuestView<MimeHandlerViewGuest>::WebContentsDestroyed();
 +}
 +
- WebContents* MimeHandlerViewGuest::OpenURLFromTab(
-     WebContents* source,
-     const content::OpenURLParams& params) {
+ void MimeHandlerViewGuest::FuseBeforeUnloadControl(
+     mojo::PendingReceiver<mime_handler::BeforeUnloadControl> receiver) {
+   if (!pending_before_unload_control_)
 diff --git extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
-index 242db17f8f3b..80e9a5663588 100644
+index 2a2f0b6b44293..b5a5e9949138f 100644
 --- extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
 +++ extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
-@@ -130,6 +130,7 @@ class MimeHandlerViewGuest
-   void EmbedderFullscreenToggled(bool entered_fullscreen) final;
-   bool ZoomPropagatesFromEmbedderToGuest() const final;
-   bool ShouldDestroyOnDetach() const final;
-+  void WillDestroy() override;
+@@ -194,10 +194,12 @@ class MimeHandlerViewGuest
+   void ReadyToCommitNavigation(
+       content::NavigationHandle* navigation_handle) final;
+   void DidFinishNavigation(content::NavigationHandle* navigation_handle) final;
++  void WebContentsDestroyed() override;
  
-   // WebContentsDelegate implementation.
-   content::WebContents* OpenURLFromTab(
+   std::unique_ptr<MimeHandlerViewGuestDelegate> delegate_;
+   std::unique_ptr<StreamContainer> stream_;
+ 
++  bool is_guest_attached_ = false;
+   bool is_guest_fullscreen_ = false;
+   bool is_embedder_fullscreen_ = false;
+   bool plugin_can_save_ = false;
 diff --git extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest_delegate.h extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest_delegate.h
-index 98689e261460..a1b08274f455 100644
+index 7f59e7925084e..777b8a3cf103a 100644
 --- extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest_delegate.h
 +++ extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest_delegate.h
-@@ -8,9 +8,9 @@
+@@ -7,6 +7,8 @@
+ 
  #include <string>
  
- #include "base/macros.h"
 +#include "content/public/browser/web_contents.h"
- 
++
  namespace content {
--class WebContents;
+ class RenderFrameHost;
  struct ContextMenuParams;
- }  // namespace content
+@@ -25,6 +27,14 @@ class MimeHandlerViewGuestDelegate {
  
-@@ -22,6 +22,14 @@ class MimeHandlerViewGuestDelegate {
-   MimeHandlerViewGuestDelegate() {}
    virtual ~MimeHandlerViewGuestDelegate() {}
  
 +  // Provides an opportunity to supply a custom view implementation.
@@ -86,5 +93,5 @@
 +  virtual void OnGuestDetached() {}
 +
    // Handles context menu, or returns false if unhandled.
-   virtual bool HandleContextMenu(content::WebContents* web_contents,
-                                  const content::ContextMenuParams& params);
+   //
+   // The `render_frame_host` represents the frame that requests the context menu
diff --git a/src/patch/patches/net_cookie_flags.patch b/src/patch/patches/net_cookie_flags.patch
new file mode 100644
index 0000000..097dff0
--- /dev/null
+++ b/src/patch/patches/net_cookie_flags.patch
@@ -0,0 +1,39 @@
+diff --git net/base/load_flags_list.h net/base/load_flags_list.h
+index 4fc3870bcfbc8..24c6d32d4a8d8 100644
+--- net/base/load_flags_list.h
++++ net/base/load_flags_list.h
+@@ -110,3 +110,6 @@ LOAD_FLAG(CAN_USE_SHARED_DICTIONARY, 1 << 17)
+ // Indicates that CAN_USE_SHARED_DICTIONARY must be disabled after a redirect to
+ // another origin.
+ LOAD_FLAG(DISABLE_SHARED_DICTIONARY_AFTER_CROSS_ORIGIN_REDIRECT, 1 << 18)
++
++// This load will not send any cookies. For CEF usage.
++LOAD_FLAG(DO_NOT_SEND_COOKIES, 1 << 19)
+diff --git net/url_request/url_request_http_job.cc net/url_request/url_request_http_job.cc
+index db9ca10ea0f1c..48af940fa0571 100644
+--- net/url_request/url_request_http_job.cc
++++ net/url_request/url_request_http_job.cc
+@@ -1797,7 +1797,8 @@ bool URLRequestHttpJob::ShouldAddCookieHeader() const {
+   // Read cookies whenever allow_credentials() is true, even if the PrivacyMode
+   // is being overridden by NetworkDelegate and will eventually block them, as
+   // blocked cookies still need to be logged in that case.
+-  return request_->context()->cookie_store() && request_->allow_credentials();
++  return request_->context()->cookie_store() && request_->allow_credentials() &&
++         !(request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES);
+ }
+ 
+ bool URLRequestHttpJob::IsPartitionedCookiesEnabled() const {
+diff --git services/network/public/cpp/resource_request.cc services/network/public/cpp/resource_request.cc
+index 14049395fbc56..f56bfb60e693e 100644
+--- services/network/public/cpp/resource_request.cc
++++ services/network/public/cpp/resource_request.cc
+@@ -311,7 +311,8 @@ bool ResourceRequest::EqualsForTesting(const ResourceRequest& request) const {
+ }
+ 
+ bool ResourceRequest::SendsCookies() const {
+-  return credentials_mode == network::mojom::CredentialsMode::kInclude;
++  return credentials_mode == network::mojom::CredentialsMode::kInclude &&
++         !(load_flags & net::LOAD_DO_NOT_SEND_COOKIES);
+ }
+ 
+ bool ResourceRequest::SavesCookies() const {
diff --git a/src/patch/patches/net_test_server_3798752.patch b/src/patch/patches/net_test_server_3798752.patch
new file mode 100644
index 0000000..46cf56f
--- /dev/null
+++ b/src/patch/patches/net_test_server_3798752.patch
@@ -0,0 +1,22 @@
+diff --git net/test/embedded_test_server/embedded_test_server.cc net/test/embedded_test_server/embedded_test_server.cc
+index 336d1ef2ad7fc..e4abe8d2cf9fd 100644
+--- net/test/embedded_test_server/embedded_test_server.cc
++++ net/test/embedded_test_server/embedded_test_server.cc
+@@ -978,7 +978,7 @@ bool EmbeddedTestServer::PostTaskToIOThreadAndWait(base::OnceClosure closure) {
+   if (!base::CurrentThread::Get())
+     temporary_loop = std::make_unique<base::SingleThreadTaskExecutor>();
+ 
+-  base::RunLoop run_loop;
++  base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
+   if (!io_thread_->task_runner()->PostTaskAndReply(
+           FROM_HERE, std::move(closure), run_loop.QuitClosure())) {
+     return false;
+@@ -1005,7 +1005,7 @@ bool EmbeddedTestServer::PostTaskToIOThreadAndWaitWithResult(
+   if (!base::CurrentThread::Get())
+     temporary_loop = std::make_unique<base::SingleThreadTaskExecutor>();
+ 
+-  base::RunLoop run_loop;
++  base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
+   bool task_result = false;
+   if (!io_thread_->task_runner()->PostTaskAndReplyWithResult(
+           FROM_HERE, std::move(task),
diff --git a/src/patch/patches/osr_fling_2745.patch b/src/patch/patches/osr_fling_2745.patch
index 71f20a4..668b7c5 100644
--- a/src/patch/patches/osr_fling_2745.patch
+++ b/src/patch/patches/osr_fling_2745.patch
@@ -1,5 +1,5 @@
 diff --git content/browser/renderer_host/input/fling_scheduler.cc content/browser/renderer_host/input/fling_scheduler.cc
-index c7a4f1f0c3d0..7e6e3b4e56d4 100644
+index 431df5d50debe..0fcc9ea8fbb1a 100644
 --- content/browser/renderer_host/input/fling_scheduler.cc
 +++ content/browser/renderer_host/input/fling_scheduler.cc
 @@ -68,6 +68,9 @@ void FlingScheduler::ProgressFlingOnBeginFrameIfneeded(
@@ -9,11 +9,11 @@
 +  if (compositor_) {
 +    return compositor_;
 +  }
- #if defined(USE_AURA)
-   if (host_->GetView() && host_->GetView()->GetNativeView() &&
-       host_->GetView()->GetNativeView()->GetHost() &&
+   if (!host_->GetView()) {
+     return nullptr;
+   }
 diff --git content/browser/renderer_host/input/fling_scheduler_base.h content/browser/renderer_host/input/fling_scheduler_base.h
-index cc4b13a7b9c6..84f3b9ed7cf4 100644
+index afefe3cd83dee..6668463247644 100644
 --- content/browser/renderer_host/input/fling_scheduler_base.h
 +++ content/browser/renderer_host/input/fling_scheduler_base.h
 @@ -7,12 +7,23 @@
@@ -41,11 +41,11 @@
  
  }  // namespace content
 diff --git content/browser/renderer_host/render_widget_host_impl.cc content/browser/renderer_host/render_widget_host_impl.cc
-index fc06067480b0..4f313bdb1414 100644
+index d7b85d4a6adbe..6bd3035c313b3 100644
 --- content/browser/renderer_host/render_widget_host_impl.cc
 +++ content/browser/renderer_host/render_widget_host_impl.cc
-@@ -2751,6 +2751,11 @@ void RenderWidgetHostImpl::DidStartScrollingViewport() {
-     view_->set_is_currently_scrolling_viewport(true);
+@@ -3271,6 +3271,11 @@ void RenderWidgetHostImpl::OnInvalidInputEventSource() {
+       GetProcess(), bad_message::INPUT_ROUTER_INVALID_EVENT_SOURCE);
  }
  
 +void RenderWidgetHostImpl::SetCompositorForFlingScheduler(ui::Compositor* compositor)
@@ -57,10 +57,10 @@
      const WebInputEvent& event) {
    if ((base::FeatureList::IsEnabled(
 diff --git content/browser/renderer_host/render_widget_host_impl.h content/browser/renderer_host/render_widget_host_impl.h
-index 013b2165038f..28d33768143f 100644
+index 5c042eea04022..8752e45f39f1f 100644
 --- content/browser/renderer_host/render_widget_host_impl.h
 +++ content/browser/renderer_host/render_widget_host_impl.h
-@@ -731,6 +731,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
+@@ -801,6 +801,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
  
    void ProgressFlingIfNeeded(base::TimeTicks current_time);
    void StopFling();
diff --git a/src/patch/patches/prefs_content_1161.patch b/src/patch/patches/prefs_content_1161.patch
deleted file mode 100644
index 81d5775..0000000
--- a/src/patch/patches/prefs_content_1161.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-diff --git content/public/common/common_param_traits_macros.h content/public/common/common_param_traits_macros.h
-index 0e67ad3c7431..de0bb8e1a824 100644
---- content/public/common/common_param_traits_macros.h
-+++ content/public/common/common_param_traits_macros.h
-@@ -177,6 +177,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::WebPreferences)
-   IPC_STRUCT_TRAITS_MEMBER(main_frame_resizes_are_orientation_changes)
-   IPC_STRUCT_TRAITS_MEMBER(initialize_at_minimum_page_scale)
-   IPC_STRUCT_TRAITS_MEMBER(smart_insert_delete_enabled)
-+  IPC_STRUCT_TRAITS_MEMBER(base_background_color)
-   IPC_STRUCT_TRAITS_MEMBER(cookie_enabled)
-   IPC_STRUCT_TRAITS_MEMBER(navigate_on_drag_drop)
-   IPC_STRUCT_TRAITS_MEMBER(spatial_navigation_enabled)
-diff --git content/public/common/web_preferences.cc content/public/common/web_preferences.cc
-index 13999e87c780..3494c1c762cc 100644
---- content/public/common/web_preferences.cc
-+++ content/public/common/web_preferences.cc
-@@ -165,6 +165,7 @@ WebPreferences::WebPreferences()
-       spatial_navigation_enabled(false),
-       caret_browsing_enabled(false),
-       navigate_on_drag_drop(true),
-+      base_background_color(0xFFFFFFFF),  // Color::white
-       v8_cache_options(blink::mojom::V8CacheOptions::kDefault),
-       record_whole_document(false),
-       cookie_enabled(true),
-diff --git content/public/common/web_preferences.h content/public/common/web_preferences.h
-index 6c6420ec70bf..256923855837 100644
---- content/public/common/web_preferences.h
-+++ content/public/common/web_preferences.h
-@@ -181,6 +181,7 @@ struct CONTENT_EXPORT WebPreferences {
-   bool spatial_navigation_enabled;
-   bool caret_browsing_enabled;
-   bool navigate_on_drag_drop;
-+  uint32_t base_background_color;
-   blink::mojom::V8CacheOptions v8_cache_options;
-   bool record_whole_document;
- 
-diff --git content/renderer/render_view_impl.cc content/renderer/render_view_impl.cc
-index f0cb4833442b..1f80fefaa124 100644
---- content/renderer/render_view_impl.cc
-+++ content/renderer/render_view_impl.cc
-@@ -971,6 +971,8 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
- #endif
- 
-   WebRuntimeFeatures::EnableTranslateService(prefs.translate_service_available);
-+
-+  web_view->SetBaseBackgroundColor(prefs.base_background_color);
- }
- 
- /*static*/
diff --git a/src/patch/patches/print_preview_123.patch b/src/patch/patches/print_preview_123.patch
index 2712750..69f200b 100644
--- a/src/patch/patches/print_preview_123.patch
+++ b/src/patch/patches/print_preview_123.patch
@@ -1,366 +1,120 @@
 diff --git chrome/browser/download/download_prefs.cc chrome/browser/download/download_prefs.cc
-index 00d1c0fa2b00..45dcadc79fb2 100644
+index c4c7b83733167..3a22deb1cdb19 100644
 --- chrome/browser/download/download_prefs.cc
 +++ chrome/browser/download/download_prefs.cc
-@@ -22,6 +22,7 @@
- #include "base/strings/sys_string_conversions.h"
+@@ -23,6 +23,7 @@
  #include "base/strings/utf_string_conversions.h"
  #include "build/build_config.h"
-+#include "cef/libcef/features/features.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/runtime.h"
  #include "chrome/browser/download/chrome_download_manager_delegate.h"
  #include "chrome/browser/download/download_core_service_factory.h"
  #include "chrome/browser/download/download_core_service_impl.h"
-@@ -53,6 +54,10 @@
- #include "chrome/browser/ui/pdf/adobe_reader_info_win.h"
+@@ -63,6 +64,10 @@
+ #include "chrome/browser/download/bubble/download_bubble_prefs.h"
  #endif
  
 +#if BUILDFLAG(ENABLE_CEF)
-+#include "cef/libcef/browser/browser_context.h"
++#include "cef/libcef/browser/alloy/alloy_download_util.h"
 +#endif
 +
  using content::BrowserContext;
  using content::BrowserThread;
  using content::DownloadManager;
-@@ -309,7 +314,11 @@ DownloadPrefs* DownloadPrefs::FromDownloadManager(
+@@ -358,6 +363,11 @@ DownloadPrefs* DownloadPrefs::FromDownloadManager(
  // static
  DownloadPrefs* DownloadPrefs::FromBrowserContext(
      content::BrowserContext* context) {
-+#if !BUILDFLAG(ENABLE_CEF)
-   return FromDownloadManager(BrowserContext::GetDownloadManager(context));
-+#else
-+  return CefBrowserContext::GetForContext(context)->GetDownloadPrefs();
++#if BUILDFLAG(ENABLE_CEF)
++  if (cef::IsAlloyRuntimeEnabled()) {
++    return alloy::GetDownloadPrefsFromBrowserContext(context);
++  }
 +#endif
+   return FromDownloadManager(context->GetDownloadManager());
  }
  
- bool DownloadPrefs::IsFromTrustedSource(const download::DownloadItem& item) {
 diff --git chrome/browser/printing/print_preview_dialog_controller.cc chrome/browser/printing/print_preview_dialog_controller.cc
-index 84818167bce1..cdbd3f7f6f27 100644
+index c7ba18ac2081e..2d5dbe156d335 100644
 --- chrome/browser/printing/print_preview_dialog_controller.cc
 +++ chrome/browser/printing/print_preview_dialog_controller.cc
 @@ -16,6 +16,7 @@
- #include "base/strings/utf_string_conversions.h"
  #include "build/branding_buildflags.h"
  #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
 +#include "cef/libcef/features/features.h"
  #include "chrome/browser/browser_process.h"
- #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
  #include "chrome/browser/printing/print_view_manager.h"
-@@ -451,8 +452,11 @@ WebContents* PrintPreviewDialogController::CreatePrintPreviewDialog(
-   content::HostZoomMap::Get(preview_dialog->GetSiteInstance())
-       ->SetZoomLevelForHostAndScheme(print_url.scheme(), print_url.host(), 0);
-   PrintViewManager::CreateForWebContents(preview_dialog);
-+
-+#if !BUILDFLAG(ENABLE_CEF)
-   extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
-       preview_dialog);
-+#endif
- 
-   // Add an entry to the map.
-   preview_dialog_map_[preview_dialog] = initiator;
+ #include "chrome/browser/printing/print_view_manager_base.h"
 diff --git chrome/browser/resources/print_preview/ui/destination_dialog.html chrome/browser/resources/print_preview/ui/destination_dialog.html
-index 56a6a8d8ee67..5fecf7ad1780 100644
+index 5d1658999d5bb..d1b7b7288c946 100644
 --- chrome/browser/resources/print_preview/ui/destination_dialog.html
 +++ chrome/browser/resources/print_preview/ui/destination_dialog.html
-@@ -141,9 +141,7 @@
-     </print-preview-provisional-destination-resolver>
+@@ -15,10 +15,7 @@
+     </print-preview-destination-list>
    </div>
    <div slot="button-container">
--    <cr-button on-click="onOpenSettingsPrintPage_">
+-    <cr-button on-click="onManageButtonClick_">
 -      $i18n{manage}
+-      <iron-icon icon="cr:open-in-new" id="manageIcon"></iron-icon>
 -    </cr-button>
 +    <div></div>
      <cr-button class="cancel-button" on-click="onCancelButtonClick_">
        $i18n{cancel}
      </cr-button>
-diff --git chrome/browser/resources/print_preview/ui/destination_select.html chrome/browser/resources/print_preview/ui/destination_select.html
-index c93947a7634c..c60cada63ef8 100644
---- chrome/browser/resources/print_preview/ui/destination_select.html
-+++ chrome/browser/resources/print_preview/ui/destination_select.html
-@@ -31,10 +31,6 @@
-           hidden$="[[pdfPrinterDisabled]]">
-     $i18n{printToPDF}
-   </option>
--  <option value="[[getGoogleDriveDestinationKey_(activeUser)]]"
--      hidden$="[[!driveDestinationReady]]">
--    $i18n{printToGoogleDrive}
--  </option>
-   <option value="noDestinations"
-           hidden$="[[!noDestinations]]" selected$="[[noDestinations]]">
-     $i18n{noDestinationsMessage}
 diff --git chrome/browser/ui/webui/constrained_web_dialog_ui.cc chrome/browser/ui/webui/constrained_web_dialog_ui.cc
-index b59728f623e3..6fd443962836 100644
+index d5767fe27db0d..5778847a68208 100644
 --- chrome/browser/ui/webui/constrained_web_dialog_ui.cc
 +++ chrome/browser/ui/webui/constrained_web_dialog_ui.cc
-@@ -26,6 +26,8 @@
- #include "chrome/browser/extensions/tab_helper.h"
- #endif
- 
-+#include "cef/libcef/features/features.h"
-+
- using content::RenderFrameHost;
- using content::WebContents;
- using content::WebUIMessageHandler;
-@@ -55,8 +57,10 @@ class ConstrainedWebDialogDelegateUserData
+@@ -13,6 +13,7 @@
+ #include "base/memory/ptr_util.h"
+ #include "base/memory/raw_ptr.h"
+ #include "base/values.h"
++#include "cef/libcef/features/runtime.h"
+ #include "content/public/browser/notification_service.h"
+ #include "content/public/browser/render_frame_host.h"
+ #include "content/public/browser/web_contents.h"
+@@ -57,7 +58,9 @@ class ConstrainedWebDialogDelegateUserData
  ConstrainedWebDialogUI::ConstrainedWebDialogUI(content::WebUI* web_ui)
      : WebUIController(web_ui) {
  #if BUILDFLAG(ENABLE_EXTENSIONS)
-+#if !BUILDFLAG(ENABLE_CEF)
++  if (!cef::IsAlloyRuntimeEnabled()) {
    extensions::TabHelper::CreateForWebContents(web_ui->GetWebContents());
- #endif
-+#endif
- }
- 
- ConstrainedWebDialogUI::~ConstrainedWebDialogUI() {
-diff --git chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
-index 394ce8f66012..fe0e14e27fd1 100644
---- chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
-+++ chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
-@@ -178,8 +178,10 @@ PdfPrinterHandler::PdfPrinterHandler(
-       sticky_settings_(sticky_settings) {}
- 
- PdfPrinterHandler::~PdfPrinterHandler() {
-+#if !BUILDFLAG(ENABLE_CEF)
-   if (select_file_dialog_.get())
-     select_file_dialog_->ListenerDestroyed();
-+#endif
- }
- 
- void PdfPrinterHandler::Reset() {
-@@ -226,12 +228,14 @@ void PdfPrinterHandler::StartPrint(
-     return;
-   }
- 
-+#if !BUILDFLAG(ENABLE_CEF)
-   if (select_file_dialog_ &&
-       select_file_dialog_->IsRunning(
-           platform_util::GetTopLevel(preview_web_contents_->GetNativeView()))) {
-     // Dialog is already showing.
-     return;
-   }
-+#endif
- 
-   DCHECK(!print_callback_);
-   print_callback_ = std::move(callback);
-@@ -370,7 +374,11 @@ void PdfPrinterHandler::SelectFile(const base::FilePath& default_filename,
-   // If the directory is empty there is no reason to create it or use the
-   // default location.
-   if (path.empty()) {
-+#if !BUILDFLAG(ENABLE_CEF)
-     OnDirectorySelected(default_filename, path);
-+#else
-+    ShowCefSaveAsDialog(initiator, default_filename, path);
-+#endif
-     return;
-   }
- 
-@@ -380,8 +388,14 @@ void PdfPrinterHandler::SelectFile(const base::FilePath& default_filename,
-   base::ThreadPool::PostTaskAndReplyWithResult(
-       FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
-       base::BindOnce(&SelectSaveDirectory, path, default_path),
-+#if !BUILDFLAG(ENABLE_CEF)
-       base::BindOnce(&PdfPrinterHandler::OnDirectorySelected,
-                      weak_ptr_factory_.GetWeakPtr(), default_filename));
-+#else
-+      base::BindOnce(&PdfPrinterHandler::ShowCefSaveAsDialog,
-+                     weak_ptr_factory_.GetWeakPtr(), initiator,
-+                     default_filename));
-+#endif
- }
- 
- void PdfPrinterHandler::PostPrintToPdfTask() {
-@@ -397,6 +411,7 @@ void PdfPrinterHandler::OnGotUniqueFileName(const base::FilePath& path) {
-   FileSelected(path, 0, nullptr);
- }
- 
-+#if !BUILDFLAG(ENABLE_CEF)
- void PdfPrinterHandler::OnDirectorySelected(const base::FilePath& filename,
-                                             const base::FilePath& directory) {
-   base::FilePath path = directory.Append(filename);
-@@ -421,5 +436,36 @@ void PdfPrinterHandler::OnDirectorySelected(const base::FilePath& filename,
-       &file_type_info, 0, base::FilePath::StringType(),
-       platform_util::GetTopLevel(preview_web_contents_->GetNativeView()), NULL);
- }
-+#else
-+void PdfPrinterHandler::ShowCefSaveAsDialog(content::WebContents* initiator,
-+                                            const base::FilePath& filename,
-+                                            const base::FilePath& directory) {
-+  CefRefPtr<CefBrowserHostImpl> cef_browser =
-+      CefBrowserHostImpl::GetBrowserForContents(initiator);
-+  if (!cef_browser)
-+    return;
-+
-+  base::FilePath path = directory.Append(filename);
-+
-+  CefFileDialogRunner::FileChooserParams params;
-+  params.mode = blink::mojom::FileChooserParams::Mode::kSave;
-+  params.default_file_name = path;
-+  params.accept_types.push_back(CefString(path.Extension()));
-+
-+  cef_browser->RunFileChooser(
-+      params, base::Bind(&PdfPrinterHandler::SaveAsDialogDismissed,
-+                         weak_ptr_factory_.GetWeakPtr()));
-+}
-+
-+void PdfPrinterHandler::SaveAsDialogDismissed(
-+    int selected_accept_filter,
-+    const std::vector<base::FilePath>& file_paths) {
-+  if (file_paths.size() == 1) {
-+    FileSelected(file_paths[0], 0, nullptr);
-+  } else {
-+    FileSelectionCanceled(nullptr);
 +  }
-+}
-+#endif
- 
- }  // namespace printing
-diff --git chrome/browser/ui/webui/print_preview/pdf_printer_handler.h chrome/browser/ui/webui/print_preview/pdf_printer_handler.h
-index 0881b3dd9303..4df6883d4d05 100644
---- chrome/browser/ui/webui/print_preview/pdf_printer_handler.h
-+++ chrome/browser/ui/webui/print_preview/pdf_printer_handler.h
-@@ -11,9 +11,14 @@
- #include "base/memory/ref_counted.h"
- #include "base/memory/weak_ptr.h"
- #include "base/strings/string16.h"
-+#include "cef/libcef/features/features.h"
- #include "chrome/browser/ui/webui/print_preview/printer_handler.h"
- #include "ui/shell_dialogs/select_file_dialog.h"
- 
-+#if BUILDFLAG(ENABLE_CEF)
-+#include "cef/libcef/browser/browser_host_impl.h"
-+#endif
-+
- namespace base {
- class FilePath;
- class RefCountedMemory;
-@@ -76,17 +81,28 @@ class PdfPrinterHandler : public PrinterHandler,
-   // The print preview web contents. Protected so unit tests can access it.
-   content::WebContents* const preview_web_contents_;
- 
-+#if !BUILDFLAG(ENABLE_CEF)
-   // The underlying dialog object. Protected so unit tests can access it.
-   scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
-+#endif
- 
-  private:
-   void PostPrintToPdfTask();
-   void OnGotUniqueFileName(const base::FilePath& path);
- 
-+#if !BUILDFLAG(ENABLE_CEF)
-   // Prompts the user to save the file. The dialog will default to saving
-   // the file with name |filename| in |directory|.
-   void OnDirectorySelected(const base::FilePath& filename,
-                            const base::FilePath& directory);
-+#else
-+  void ShowCefSaveAsDialog(content::WebContents* initiator,
-+                           const base::FilePath& filename,
-+                           const base::FilePath& directory);
-+
-+  void SaveAsDialogDismissed(int selected_accept_filter,
-+                             const std::vector<base::FilePath>& file_paths);
-+#endif
- 
-   Profile* const profile_;
-   PrintPreviewStickySettings* const sticky_settings_;
-diff --git chrome/browser/ui/webui/print_preview/print_preview_handler.cc chrome/browser/ui/webui/print_preview/print_preview_handler.cc
-index 113d34201f90..4a75044c2bb7 100644
---- chrome/browser/ui/webui/print_preview/print_preview_handler.cc
-+++ chrome/browser/ui/webui/print_preview/print_preview_handler.cc
-@@ -27,6 +27,7 @@
- #include "base/metrics/histogram_macros.h"
- #include "base/values.h"
- #include "build/build_config.h"
-+#include "cef/libcef/features/features.h"
- #include "chrome/browser/app_mode/app_mode_utils.h"
- #include "chrome/browser/bad_message.h"
- #include "chrome/browser/browser_process.h"
-@@ -1146,7 +1147,7 @@ void PrintPreviewHandler::SendInitialSettings(
-     initial_settings.SetKey(kPolicies, std::move(policies));
- 
-   if (IsCloudPrintEnabled() &&
--      !base::FeatureList::IsEnabled(features::kCloudPrinterHandler)) {
-+      !base::FeatureList::IsEnabled(::features::kCloudPrinterHandler)) {
-     initial_settings.SetStringKey(
-         kCloudPrintURL, GURL(cloud_devices::GetCloudPrintURL()).spec());
-   }
-@@ -1403,7 +1404,7 @@ PrinterHandler* PrintPreviewHandler::GetPrinterHandler(
-     }
-     return extension_printer_handler_.get();
-   }
--#if BUILDFLAG(ENABLE_SERVICE_DISCOVERY)
-+#if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) && !BUILDFLAG(ENABLE_CEF)
-   if (printer_type == PrinterType::kPrivetPrinter) {
-     if (!privet_printer_handler_) {
-       privet_printer_handler_ =
-@@ -1411,6 +1412,9 @@ PrinterHandler* PrintPreviewHandler::GetPrinterHandler(
-     }
-     return privet_printer_handler_.get();
-   }
-+#else  // !BUILDFLAG(ENABLE_SERVICE_DISCOVERY)
-+  if (printer_type == PrinterType::kPrivetPrinter)
-+    return nullptr;
  #endif
-   if (printer_type == PrinterType::kPdfPrinter) {
-     if (!pdf_printer_handler_) {
-@@ -1430,7 +1434,7 @@ PrinterHandler* PrintPreviewHandler::GetPrinterHandler(
-   if (printer_type == PrinterType::kCloudPrinter) {
-     // This printer handler is currently experimental. Ensure it is never
-     // created unless the flag is enabled.
--    CHECK(base::FeatureList::IsEnabled(features::kCloudPrinterHandler));
-+    CHECK(base::FeatureList::IsEnabled(::features::kCloudPrinterHandler));
-     if (!cloud_printer_handler_)
-       cloud_printer_handler_ = PrinterHandler::CreateForCloudPrinters();
-     return cloud_printer_handler_.get();
-@@ -1493,6 +1497,7 @@ void PrintPreviewHandler::OnPrintResult(const std::string& callback_id,
  }
  
- void PrintPreviewHandler::RegisterForGaiaCookieChanges() {
-+#if !BUILDFLAG(ENABLE_CEF)
-   DCHECK(!identity_manager_);
-   cloud_print_enabled_ =
-       !base::Contains(printer_type_deny_list_, kCloudPrinter) &&
-@@ -1509,6 +1514,7 @@ void PrintPreviewHandler::RegisterForGaiaCookieChanges() {
- 
-   identity_manager_ = IdentityManagerFactory::GetForProfile(profile);
-   identity_manager_->AddObserver(this);
-+#endif
- }
- 
- void PrintPreviewHandler::UnregisterForGaiaCookieChanges() {
 diff --git chrome/browser/ui/webui/print_preview/print_preview_ui.cc chrome/browser/ui/webui/print_preview/print_preview_ui.cc
-index cf3c71f478da..8438a234eb8b 100644
+index 363b7f7037532..2ac23b428fbea 100644
 --- chrome/browser/ui/webui/print_preview/print_preview_ui.cc
 +++ chrome/browser/ui/webui/print_preview/print_preview_ui.cc
 @@ -24,6 +24,7 @@
- #include "base/synchronization/lock.h"
  #include "base/values.h"
  #include "build/build_config.h"
-+#include "cef/libcef/features/features.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/runtime.h"
  #include "chrome/browser/browser_process.h"
- #include "chrome/browser/browser_process_platform_part.h"
- #include "chrome/browser/printing/background_printing_manager.h"
-@@ -76,12 +77,16 @@ namespace printing {
- 
- namespace {
- 
-+#if BUILDFLAG(ENABLE_CEF)
-+const char kBasicPrintShortcut[] = "";
-+#else
- #if defined(OS_MACOSX)
- // U+0028 U+21E7 U+2318 U+0050 U+0029 in UTF8
- const char kBasicPrintShortcut[] = "\x28\xE2\x8c\xA5\xE2\x8C\x98\x50\x29";
- #elif !defined(OS_CHROMEOS)
- const char kBasicPrintShortcut[] = "(Ctrl+Shift+P)";
+ #include "chrome/browser/enterprise/browser_management/management_service_factory.h"
+ #include "chrome/browser/pdf/pdf_extension_util.h"
+@@ -106,6 +107,13 @@ const char16_t kBasicPrintShortcut[] = u"(\u2325\u2318P)";
+ const char16_t kBasicPrintShortcut[] = u"(Ctrl+Shift+P)";
  #endif
-+#endif
  
- #if !BUILDFLAG(OPTIMIZE_WEBUI)
- constexpr char kGeneratedPath[] =
-@@ -332,7 +337,7 @@ void AddPrintPreviewFlags(content::WebUIDataSource* source, Profile* profile) {
-   source->AddBoolean("isEnterpriseManaged", enterprise_managed);
++const char16_t* GetBasicPrintShortcut() {
++  if (cef::IsAlloyRuntimeEnabled()) {
++    return u"";
++  }
++  return kBasicPrintShortcut;
++}
++
+ constexpr char kInvalidArgsForDidStartPreview[] =
+     "Invalid arguments for DidStartPreview";
+ constexpr char kInvalidPageIndexForDidPreviewPage[] =
+@@ -299,7 +307,7 @@ void AddPrintPreviewStrings(content::WebUIDataSource* source) {
+   source->AddLocalizedStrings(kLocalizedStrings);
  
-   bool cloud_printer_handler_enabled =
--      base::FeatureList::IsEnabled(features::kCloudPrinterHandler);
-+      base::FeatureList::IsEnabled(::features::kCloudPrinterHandler);
-   source->AddBoolean("cloudPrinterHandlerEnabled",
-                      cloud_printer_handler_enabled);
- }
+ #if !BUILDFLAG(IS_CHROMEOS)
+-  const std::u16string shortcut_text(kBasicPrintShortcut);
++  const std::u16string shortcut_text(GetBasicPrintShortcut());
+   source->AddString("systemDialogOption",
+                     l10n_util::GetStringFUTF16(
+                         IDS_PRINT_PREVIEW_SYSTEM_DIALOG_OPTION, shortcut_text));
diff --git a/src/patch/patches/printing_context_2196.patch b/src/patch/patches/printing_context_2196.patch
index 99af9bc..5ea34ec 100644
--- a/src/patch/patches/printing_context_2196.patch
+++ b/src/patch/patches/printing_context_2196.patch
@@ -1,20 +1,20 @@
-diff --git chrome/browser/printing/print_job_worker.cc chrome/browser/printing/print_job_worker.cc
-index 33e17f0df356..04dd4798755c 100644
---- chrome/browser/printing/print_job_worker.cc
-+++ chrome/browser/printing/print_job_worker.cc
-@@ -134,6 +134,7 @@ PrintJobWorker::PrintJobWorker(int render_process_id, int render_frame_id)
-           PrintingContext::Create(printing_context_delegate_.get())),
-       thread_("Printing_Worker") {
-   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-+  printing_context_->set_render_ids(render_process_id, render_frame_id);
+diff --git chrome/browser/printing/printer_query.cc chrome/browser/printing/printer_query.cc
+index e175525a96266..7434b2f5eaa75 100644
+--- chrome/browser/printing/printer_query.cc
++++ chrome/browser/printing/printer_query.cc
+@@ -122,6 +122,7 @@ PrinterQuery::PrinterQuery(content::GlobalRenderFrameHostId rfh_id)
+       rfh_id_(rfh_id),
+       cookie_(PrintSettings::NewCookie()) {
+   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
++  printing_context_->set_render_ids(rfh_id.child_id, rfh_id.frame_routing_id);
  }
  
- PrintJobWorker::~PrintJobWorker() {
+ PrinterQuery::~PrinterQuery() {
 diff --git printing/printing_context.h printing/printing_context.h
-index 6a5a7c90ef5b..04c0535046dc 100644
+index c753f04d8b73a..7607571f78119 100644
 --- printing/printing_context.h
 +++ printing/printing_context.h
-@@ -131,6 +131,13 @@ class PRINTING_EXPORT PrintingContext {
+@@ -176,6 +176,13 @@ class COMPONENT_EXPORT(PRINTING) PrintingContext {
  
    int job_id() const { return job_id_; }
  
@@ -28,7 +28,7 @@
   protected:
    explicit PrintingContext(Delegate* delegate);
  
-@@ -155,6 +162,10 @@ class PRINTING_EXPORT PrintingContext {
+@@ -220,6 +227,10 @@ class COMPONENT_EXPORT(PRINTING) PrintingContext {
    // The job id for the current job. The value is 0 if no jobs are active.
    int job_id_;
  
@@ -37,5 +37,5 @@
 +  int render_frame_id_ = 0;
 +
   private:
-   DISALLOW_COPY_AND_ASSIGN(PrintingContext);
- };
+ #if BUILDFLAG(ENABLE_OOP_PRINTING)
+   // If this instance of PrintingContext should skip making any system calls
diff --git a/src/patch/patches/renderer_host_1070713.patch b/src/patch/patches/renderer_host_1070713.patch
index 8ad6883..dcb72a3 100644
--- a/src/patch/patches/renderer_host_1070713.patch
+++ b/src/patch/patches/renderer_host_1070713.patch
@@ -1,8 +1,8 @@
 diff --git content/browser/renderer_host/render_view_host_impl.cc content/browser/renderer_host/render_view_host_impl.cc
-index 01a4e3dc134b..cddb71886d4f 100644
+index 914e4cdd97154..13d3a939ba731 100644
 --- content/browser/renderer_host/render_view_host_impl.cc
 +++ content/browser/renderer_host/render_view_host_impl.cc
-@@ -455,6 +455,8 @@ bool RenderViewHostImpl::IsRenderViewLive() {
+@@ -713,6 +713,8 @@ bool RenderViewHostImpl::IsRenderViewLive() const {
  }
  
  void RenderViewHostImpl::SetBackgroundOpaque(bool opaque) {
diff --git a/src/patch/patches/renderer_preferences_util_545103.patch b/src/patch/patches/renderer_preferences_util_545103.patch
deleted file mode 100644
index 8d87c5b..0000000
--- a/src/patch/patches/renderer_preferences_util_545103.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-diff --git chrome/browser/renderer_preferences_util.cc chrome/browser/renderer_preferences_util.cc
-index 776c050ad31b..5107091f62b4 100644
---- chrome/browser/renderer_preferences_util.cc
-+++ chrome/browser/renderer_preferences_util.cc
-@@ -31,7 +31,8 @@
- #include "ui/base/cocoa/defaults_utils.h"
- #endif
- 
--#if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
-+#if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS) && \
-+    defined(ENABLE_THEMES)
- #include "chrome/browser/themes/theme_service.h"
- #include "chrome/browser/themes/theme_service_factory.h"
- #include "ui/views/linux_ui/linux_ui.h"
-@@ -146,7 +147,8 @@ void UpdateFromSystemSettings(blink::mojom::RendererPreferences* prefs,
-     prefs->caret_blink_interval = interval;
- #endif
- 
--#if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
-+#if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS) && \
-+    defined(ENABLE_THEMES)
-   views::LinuxUI* linux_ui = views::LinuxUI::instance();
-   if (linux_ui) {
-     if (ThemeServiceFactory::GetForProfile(profile)->UsingSystemTheme()) {
diff --git a/src/patch/patches/resource_bundle_2512.patch b/src/patch/patches/resource_bundle_2512.patch
index 594951a..7e774be 100644
--- a/src/patch/patches/resource_bundle_2512.patch
+++ b/src/patch/patches/resource_bundle_2512.patch
@@ -1,11 +1,11 @@
 diff --git ui/base/resource/resource_bundle.cc ui/base/resource/resource_bundle.cc
-index 133540ca848f..d442344715af 100644
+index bb38b0bd52767..91ff16ccc058b 100644
 --- ui/base/resource/resource_bundle.cc
 +++ ui/base/resource/resource_bundle.cc
-@@ -854,6 +854,12 @@ ResourceBundle::ResourceBundle(Delegate* delegate)
+@@ -943,6 +943,12 @@ ResourceBundle::ResourceBundle(Delegate* delegate)
      : delegate_(delegate),
        locale_resources_data_lock_(new base::Lock),
-       max_scale_factor_(SCALE_FACTOR_100P) {
+       max_scale_factor_(k100Percent) {
 +  // With CEF's multi-threaded mode the ResourceBundle may be created on the
 +  // main thread and then accessed on the UI thread. Allow the SequenceChecker
 +  // to re-bind on the UI thread when CalledOnValidSequence() is called for the
@@ -15,7 +15,7 @@
    mangle_localized_strings_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
        switches::kMangleLocalizedStrings);
  }
-@@ -863,6 +869,11 @@ ResourceBundle::~ResourceBundle() {
+@@ -952,6 +958,11 @@ ResourceBundle::~ResourceBundle() {
    UnloadLocaleResources();
  }
  
@@ -28,12 +28,12 @@
  void ResourceBundle::InitSharedInstance(Delegate* delegate) {
    DCHECK(g_shared_instance_ == nullptr) << "ResourceBundle initialized twice";
 diff --git ui/base/resource/resource_bundle.h ui/base/resource/resource_bundle.h
-index 3daa73bdc6d5..3d2f9232870d 100644
+index c24f5faf14d3f..96d4f6be11588 100644
 --- ui/base/resource/resource_bundle.h
 +++ ui/base/resource/resource_bundle.h
-@@ -158,6 +158,11 @@ class UI_BASE_EXPORT ResourceBundle {
-   // Return the global resource loader instance.
-   static ResourceBundle& GetSharedInstance();
+@@ -219,6 +219,11 @@ class COMPONENT_EXPORT(UI_BASE) ResourceBundle {
+   ResourceBundle(const ResourceBundle&) = delete;
+   ResourceBundle& operator=(const ResourceBundle&) = delete;
  
 +  // With CEF's multi-threaded mode the ResourceBundle may be created/destroyed
 +  // on the main thread but accessed on the UI thread. Call this method on the
diff --git a/src/patch/patches/rfh_navigation_4829483.patch b/src/patch/patches/rfh_navigation_4829483.patch
new file mode 100644
index 0000000..7e03c43
--- /dev/null
+++ b/src/patch/patches/rfh_navigation_4829483.patch
@@ -0,0 +1,25 @@
+diff --git content/browser/renderer_host/ipc_utils.cc content/browser/renderer_host/ipc_utils.cc
+index 5cb6e6463767d..84a9de1dfc6f0 100644
+--- content/browser/renderer_host/ipc_utils.cc
++++ content/browser/renderer_host/ipc_utils.cc
+@@ -73,7 +73,7 @@ bool VerifyInitiatorOrigin(
+           navigation_url_key,
+           navigation_url->DeprecatedGetOriginAsURL().spec());
+     }
+-    if (initiator_frame_token) {
++    if (initiator_frame_token && initiator_frame_token->has_value()) {
+       if (RenderFrameHostImpl* initiator_render_frame_host =
+               RenderFrameHostImpl::FromFrameToken(
+                   process_id, initiator_frame_token->value())) {
+diff --git content/browser/renderer_host/render_frame_host_impl.cc content/browser/renderer_host/render_frame_host_impl.cc
+index 44ab3ea5a90eb..9962e033ab103 100644
+--- content/browser/renderer_host/render_frame_host_impl.cc
++++ content/browser/renderer_host/render_frame_host_impl.cc
+@@ -10100,6 +10100,7 @@ void RenderFrameHostImpl::CommitNavigation(
+   auto browser_calc_origin_to_commit =
+       navigation_request->GetOriginToCommitWithDebugInfo();
+   if (!process_lock.is_error_page() && !is_mhtml_subframe &&
++      common_params->url.IsStandard() &&
+       !policy->CanAccessDataForOrigin(
+           GetProcess()->GetID(), browser_calc_origin_to_commit.first.value())) {
+     SCOPED_CRASH_KEY_STRING64("CommitNavigation", "lock_url",
diff --git a/src/patch/patches/runhooks.patch b/src/patch/patches/runhooks.patch
index a39c51a..e883ee5 100644
--- a/src/patch/patches/runhooks.patch
+++ b/src/patch/patches/runhooks.patch
@@ -1,11 +1,11 @@
 diff --git build/toolchain/win/setup_toolchain.py build/toolchain/win/setup_toolchain.py
-index 2ab240da4548..81e69abe1ecd 100644
+index d2f5798ce6535..64d6d388c9a27 100644
 --- build/toolchain/win/setup_toolchain.py
 +++ build/toolchain/win/setup_toolchain.py
-@@ -142,21 +142,29 @@ def _LoadToolchainEnv(cpu, sdk_dir, target_store):
-       # variable.
-       if 'VSINSTALLDIR' in os.environ:
-         del os.environ['VSINSTALLDIR']
+@@ -167,13 +167,17 @@ def _LoadToolchainEnv(cpu, toolchain_root, sdk_dir, target_store):
+           del os.environ['LIB']
+         if 'LIBPATH' in os.environ:
+           del os.environ['LIBPATH']
 -      other_path = os.path.normpath(os.path.join(
 +      script_path = os.path.normpath(os.path.join(
                                          os.environ['GYP_MSVS_OVERRIDE_PATH'],
@@ -25,25 +25,11 @@
      cpu_arg = "amd64"
      if (cpu != 'x64'):
        # x64 is default target CPU thus any other CPU requires a target set
-       cpu_arg += '_' + cpu
--    args = [script_path, cpu_arg]
-+    args = [script_path, cpu_arg, ]
-     # Store target must come before any SDK version declaration
-     if (target_store):
--      args.append(['store'])
-+      args.append('store')
-+    # Explicitly specifying the SDK version to build with to avoid accidentally
-+    # building with a new and untested SDK. This should stay in sync with the
-+    # packaged toolchain in build/vs_toolchain.py.
-+    args.append('10.0.18362.0')
-     variables = _LoadEnvFromBat(args)
-   return _ExtractImportantEnvironment(variables)
- 
 diff --git build/vs_toolchain.py build/vs_toolchain.py
-index 97600e73ba10..36773b159453 100755
+index a9cd6f03d9214..7ae775d6aca6d 100755
 --- build/vs_toolchain.py
 +++ build/vs_toolchain.py
-@@ -89,9 +89,16 @@ def SetEnvironmentAndGetRuntimeDllDirs():
+@@ -114,9 +114,16 @@ def SetEnvironmentAndGetRuntimeDllDirs():
      runtime_path = os.path.pathsep.join(vs_runtime_dll_dirs)
      os.environ['PATH'] = runtime_path + os.path.pathsep + os.environ['PATH']
    elif sys.platform == 'win32' and not depot_tools_win_toolchain:
@@ -60,7 +46,7 @@
      # When using an installed toolchain these files aren't needed in the output
      # directory in order to run binaries locally, but they are needed in order
      # to create isolates or the mini_installer. Copying them to the output
-@@ -140,6 +147,10 @@ def _RegistryGetValue(key, value):
+@@ -165,6 +172,10 @@ def _RegistryGetValue(key, value):
  def GetVisualStudioVersion():
    """Return best available version of Visual Studio.
    """
diff --git a/src/patch/patches/rwh_background_color_1984.patch b/src/patch/patches/rwh_background_color_1984.patch
index e4b3c5d..1361952 100644
--- a/src/patch/patches/rwh_background_color_1984.patch
+++ b/src/patch/patches/rwh_background_color_1984.patch
@@ -1,8 +1,16 @@
 diff --git content/browser/renderer_host/render_widget_host_view_aura.cc content/browser/renderer_host/render_widget_host_view_aura.cc
-index f7f9dafb9798..a378394c2d41 100644
+index 98746fea627ab..e00c36762eeb8 100644
 --- content/browser/renderer_host/render_widget_host_view_aura.cc
 +++ content/browser/renderer_host/render_widget_host_view_aura.cc
-@@ -745,10 +745,12 @@ gfx::Rect RenderWidgetHostViewAura::GetViewBounds() {
+@@ -6,6 +6,7 @@
+ 
+ #include <limits>
+ #include <memory>
++#include <tuple>
+ #include <set>
+ #include <utility>
+ 
+@@ -746,10 +747,12 @@ gfx::Rect RenderWidgetHostViewAura::GetViewBounds() {
  void RenderWidgetHostViewAura::UpdateBackgroundColor() {
    DCHECK(GetBackgroundColor());
  
@@ -18,19 +26,20 @@
 +  }
  }
  
- void RenderWidgetHostViewAura::WindowTitleChanged() {
-@@ -2029,6 +2031,15 @@ void RenderWidgetHostViewAura::CreateAuraWindow(aura::client::WindowType type) {
+ #if BUILDFLAG(IS_WIN)
+@@ -2384,6 +2387,16 @@ void RenderWidgetHostViewAura::CreateAuraWindow(aura::client::WindowType type) {
+   // This needs to happen only after |window_| has been initialized using
    // Init(), because it needs to have the layer.
-   if (frame_sink_id_.is_valid())
-     window_->SetEmbedFrameSinkId(frame_sink_id_);
+   window_->SetEmbedFrameSinkId(frame_sink_id_);
 +
 +  // Do this after |window_| is created to avoid crashes on Win10.
 +  // See https://crbug.com/761389.
-+  RenderViewHost* rvh = RenderViewHost::From(host_);
-+  if (rvh) {
++  auto web_contents =
++      WebContents::FromRenderViewHost(RenderViewHost::From(host_));
++  if (web_contents) {
 +    // TODO(mostynb): actually use prefs.  Landing this as a separate CL
 +    // first to rebaseline some unreliable layout tests.
-+    ignore_result(rvh->GetWebkitPreferences());
++    std::ignore = web_contents->GetOrCreateWebPreferences();
 +  }
  }
  
diff --git a/src/patch/patches/screen_1443650.patch b/src/patch/patches/screen_1443650.patch
new file mode 100644
index 0000000..bb81020
--- /dev/null
+++ b/src/patch/patches/screen_1443650.patch
@@ -0,0 +1,42 @@
+diff --git ui/display/screen.cc ui/display/screen.cc
+index 5e8e23ada050f..c11ea072109ec 100644
+--- ui/display/screen.cc
++++ ui/display/screen.cc
+@@ -107,13 +107,13 @@ base::TimeDelta Screen::CalculateIdleTime() const {
+ gfx::Rect Screen::ScreenToDIPRectInWindow(gfx::NativeWindow window,
+                                           const gfx::Rect& screen_rect) const {
+   float scale = GetDisplayNearestWindow(window).device_scale_factor();
+-  return ScaleToEnclosingRect(screen_rect, 1.0f / scale);
++  return ScaleToEnclosedRect(screen_rect, 1.0f / scale);
+ }
+ 
+ gfx::Rect Screen::DIPToScreenRectInWindow(gfx::NativeWindow window,
+                                           const gfx::Rect& dip_rect) const {
+   float scale = GetDisplayNearestWindow(window).device_scale_factor();
+-  return ScaleToEnclosingRect(dip_rect, scale);
++  return ScaleToEnclosedRect(dip_rect, scale);
+ }
+ 
+ bool Screen::GetDisplayWithDisplayId(int64_t display_id,
+diff --git ui/display/win/screen_win.cc ui/display/win/screen_win.cc
+index 773fbb8e90276..bdbda65c05dd6 100644
+--- ui/display/win/screen_win.cc
++++ ui/display/win/screen_win.cc
+@@ -535,7 +535,7 @@ gfx::Rect ScreenWin::ScreenToDIPRect(HWND hwnd, const gfx::Rect& pixel_bounds) {
+       gfx::PointF(pixel_bounds.origin()), screen_win_display));
+   const float scale_factor =
+       1.0f / screen_win_display.display().device_scale_factor();
+-  return {origin, ScaleToEnclosingRect(pixel_bounds, scale_factor).size()};
++  return {origin, ScaleToEnclosedRect(pixel_bounds, scale_factor).size()};
+ }
+ 
+ // static
+@@ -550,7 +550,7 @@ gfx::Rect ScreenWin::DIPToScreenRect(HWND hwnd, const gfx::Rect& dip_bounds) {
+   const gfx::Point origin =
+       display::win::DIPToScreenPoint(dip_bounds.origin(), screen_win_display);
+   const float scale_factor = screen_win_display.display().device_scale_factor();
+-  return {origin, ScaleToEnclosingRect(dip_bounds, scale_factor).size()};
++  return {origin, ScaleToEnclosedRect(dip_bounds, scale_factor).size()};
+ }
+ 
+ // static
diff --git a/src/patch/patches/service_manager_654986.patch b/src/patch/patches/service_manager_654986.patch
deleted file mode 100644
index 9a1e5ee..0000000
--- a/src/patch/patches/service_manager_654986.patch
+++ /dev/null
@@ -1,193 +0,0 @@
-diff --git services/service_manager/embedder/main.cc services/service_manager/embedder/main.cc
-index f9c275cdd78f..247142951d99 100644
---- services/service_manager/embedder/main.cc
-+++ services/service_manager/embedder/main.cc
-@@ -244,22 +244,36 @@ int RunService(MainDelegate* delegate) {
-   return 0;
- }
- 
-+ProcessType GetProcessType(MainDelegate* delegate,
-+                           const base::CommandLine& command_line) {
-+  ProcessType process_type = delegate->OverrideProcessType();
-+  if (process_type == ProcessType::kDefault) {
-+    const std::string& type_switch =
-+        command_line.GetSwitchValueASCII(switches::kProcessType);
-+    if (type_switch == switches::kProcessTypeServiceManager) {
-+      process_type = ProcessType::kServiceManager;
-+    } else if (type_switch == switches::kProcessTypeService) {
-+      process_type = ProcessType::kService;
-+    } else {
-+      process_type = ProcessType::kEmbedder;
-+    }
-+  }
-+  return process_type;
-+}
-+
- }  // namespace
- 
- MainParams::MainParams(MainDelegate* delegate) : delegate(delegate) {}
- 
- MainParams::~MainParams() {}
- 
--int Main(const MainParams& params) {
-+int MainInitialize(MainParams& params) {
-   MainDelegate* delegate = params.delegate;
-   DCHECK(delegate);
- 
-   int exit_code = -1;
-   base::debug::GlobalActivityTracker* tracker = nullptr;
-   ProcessType process_type = delegate->OverrideProcessType();
--#if defined(OS_MACOSX)
--  std::unique_ptr<base::mac::ScopedNSAutoreleasePool> autorelease_pool;
--#endif
- 
-   // A flag to indicate whether Main() has been called before. On Android, we
-   // may re-run Main() without restarting the browser process. This flag
-@@ -345,12 +359,7 @@ int Main(const MainParams& params) {
-     MainDelegate::InitializeParams init_params;
- 
- #if defined(OS_MACOSX)
--    // We need this pool for all the objects created before we get to the event
--    // loop, but we don't want to leave them hanging around until the app quits.
--    // Each "main" needs to flush this pool right before it goes into its main
--    // event loop to get rid of the cruft.
--    autorelease_pool = std::make_unique<base::mac::ScopedNSAutoreleasePool>();
--    init_params.autorelease_pool = autorelease_pool.get();
-+    init_params.autorelease_pool = params.autorelease_pool.get();
-     InitializeMac();
- #endif
- 
-@@ -422,18 +431,16 @@ int Main(const MainParams& params) {
-     }
-   }
- 
-+  return exit_code;
-+}
-+
-+int MainRun(MainParams& params) {
-+  MainDelegate* delegate = params.delegate;
-+  DCHECK(delegate);
-+
-+  int exit_code = 0;
-   const auto& command_line = *base::CommandLine::ForCurrentProcess();
--  if (process_type == ProcessType::kDefault) {
--    std::string type_switch =
--        command_line.GetSwitchValueASCII(switches::kProcessType);
--    if (type_switch == switches::kProcessTypeServiceManager) {
--      process_type = ProcessType::kServiceManager;
--    } else if (type_switch == switches::kProcessTypeService) {
--      process_type = ProcessType::kService;
--    } else {
--      process_type = ProcessType::kEmbedder;
--    }
--  }
-+  const ProcessType process_type = GetProcessType(delegate, command_line);
-   switch (process_type) {
-     case ProcessType::kDefault:
-       NOTREACHED();
-@@ -455,6 +462,8 @@ int Main(const MainParams& params) {
-       break;
-   }
- 
-+  base::debug::GlobalActivityTracker* tracker =
-+      base::debug::GlobalActivityTracker::Get();
-   if (tracker) {
-     if (exit_code == 0) {
-       tracker->SetProcessPhaseIfEnabled(
-@@ -466,13 +475,38 @@ int Main(const MainParams& params) {
-     }
-   }
- 
-+  return exit_code;
-+}
-+
-+void MainShutdown(MainParams& params) {
-+  MainDelegate* delegate = params.delegate;
-+  DCHECK(delegate);
-+
- #if defined(OS_MACOSX)
--  autorelease_pool.reset();
-+  params.autorelease_pool.reset();
- #endif
- 
-+  const ProcessType process_type =
-+      GetProcessType(delegate, *base::CommandLine::ForCurrentProcess());
-   if (process_type == ProcessType::kEmbedder)
-     delegate->ShutDownEmbedderProcess();
-+}
-+
-+int Main(MainParams& params) {
-+#if defined(OS_MACOSX)
-+  // We need this pool for all the objects created before we get to the event
-+  // loop, but we don't want to leave them hanging around until the app quits.
-+  // Each "main" needs to flush this pool right before it goes into its main
-+  // event loop to get rid of the cruft.
-+  params.autorelease_pool =
-+      std::make_unique<base::mac::ScopedNSAutoreleasePool>();
-+#endif
- 
-+  int exit_code = MainInitialize(params);
-+  if (exit_code >= 0)
-+    return exit_code;
-+  exit_code = MainRun(params);
-+  MainShutdown(params);
-   return exit_code;
- }
- 
-diff --git services/service_manager/embedder/main.h services/service_manager/embedder/main.h
-index 57e88aa85dfe..5ed6ec2abfda 100644
---- services/service_manager/embedder/main.h
-+++ services/service_manager/embedder/main.h
-@@ -5,9 +5,15 @@
- #ifndef SERVICES_SERVICE_MANAGER_EMBEDDER_MAIN_H_
- #define SERVICES_SERVICE_MANAGER_EMBEDDER_MAIN_H_
- 
-+#include <memory>
-+
- #include "base/component_export.h"
- #include "build/build_config.h"
- 
-+#if defined(OS_MACOSX)
-+#include "base/mac/scoped_nsautorelease_pool.h"
-+#endif  // defined(OS_MACOSX)
-+
- namespace service_manager {
- 
- class MainDelegate;
-@@ -22,11 +28,22 @@ struct COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER) MainParams {
-   int argc = 0;
-   const char** argv = nullptr;
- #endif
-+
-+#if defined(OS_MACOSX)
-+  std::unique_ptr<base::mac::ScopedNSAutoreleasePool> autorelease_pool;
-+#endif
- };
- 
-+// Split Main() into separate stages.
-+int COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER)
-+    MainInitialize(MainParams& params);
-+int COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER) MainRun(MainParams& params);
-+void COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER)
-+    MainShutdown(MainParams& params);
-+
- // Main function which should be called as early as possible by any executable
- // embedding the service manager.
--int COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER) Main(const MainParams& params);
-+int COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER) Main(MainParams& params);
- 
- }  // namespace service_manager
- 
-diff --git services/service_manager/embedder/set_process_title.cc services/service_manager/embedder/set_process_title.cc
-index 1dc53b847ef9..5432ab02a088 100644
---- services/service_manager/embedder/set_process_title.cc
-+++ services/service_manager/embedder/set_process_title.cc
-@@ -44,7 +44,7 @@ void SetProcessTitleFromCommandLine(const char** main_argv) {
-   bool have_argv0 = false;
- 
- #if defined(OS_LINUX)
--  DCHECK_EQ(base::PlatformThread::CurrentId(), getpid());
-+  //DCHECK_EQ(base::PlatformThread::CurrentId(), getpid());
- 
-   if (main_argv)
-     setproctitle_init(main_argv);
diff --git a/src/patch/patches/services_network_2622.patch b/src/patch/patches/services_network_2622.patch
index 69f778f..d8ff737 100644
--- a/src/patch/patches/services_network_2622.patch
+++ b/src/patch/patches/services_network_2622.patch
@@ -1,74 +1,180 @@
+diff --git chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc
+index 0a6c1f498b8fc..79e0cf27a7715 100644
+--- chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc
++++ chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc
+@@ -23,6 +23,7 @@
+ #include "base/strings/utf_string_conversions.h"
+ #include "base/time/time.h"
+ #include "build/build_config.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/browser_process.h"
+ #include "chrome/browser/enterprise/connectors/analysis/analysis_settings.h"
+ #include "chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.h"
+@@ -246,6 +247,9 @@ bool ContentAnalysisDelegate::IsEnabled(Profile* profile,
+                                         GURL url,
+                                         Data* data,
+                                         AnalysisConnector connector) {
++  if (cef::IsAlloyRuntimeEnabled())
++    return false;
++
+   auto* service = ConnectorsServiceFactory::GetForBrowserContext(profile);
+   // If the corresponding Connector policy isn't set, don't perform scans.
+   if (!service || !service->IsConnectorEnabled(connector))
 diff --git chrome/browser/net/profile_network_context_service.cc chrome/browser/net/profile_network_context_service.cc
-index 44ce8ba980a6..1dbbf0aa2341 100644
+index 6271f349464b9..caa45362f52cc 100644
 --- chrome/browser/net/profile_network_context_service.cc
 +++ chrome/browser/net/profile_network_context_service.cc
-@@ -18,6 +18,7 @@
- #include "base/strings/string_split.h"
- #include "base/task/post_task.h"
- #include "base/task/thread_pool.h"
-+#include "cef/libcef/features/features.h"
+@@ -22,6 +22,7 @@
+ #include "base/trace_event/trace_event.h"
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/browser_features.h"
  #include "chrome/browser/browser_process.h"
  #include "chrome/browser/content_settings/cookie_settings_factory.h"
- #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-@@ -681,9 +682,22 @@ ProfileNetworkContextService::CreateNetworkContextParams(
+@@ -320,8 +321,10 @@ ProfileNetworkContextService::ProfileNetworkContextService(Profile* profile)
+                           base::Unretained(this)));
+   cookie_settings_ = CookieSettingsFactory::GetForProfile(profile);
+   cookie_settings_observation_.Observe(cookie_settings_.get());
+-  privacy_sandbox_settings_observer_.Observe(
+-      PrivacySandboxSettingsFactory::GetForProfile(profile));
++  if (!cef::IsAlloyRuntimeEnabled()) {
++    privacy_sandbox_settings_observer_.Observe(
++        PrivacySandboxSettingsFactory::GetForProfile(profile));
++  }
+ 
+   DisableQuicIfNotAllowed();
+ 
+@@ -490,6 +493,9 @@ void ProfileNetworkContextService::OnTruncatedCookieBlockingChanged() {
+ 
+ void ProfileNetworkContextService::OnFirstPartySetsEnabledChanged(
+     bool enabled) {
++  if (cef::IsAlloyRuntimeEnabled()) {
++    return;
++  }
+   // Update all FPS Access Delegates on the FPS service to be `enabled`.
+   first_party_sets::FirstPartySetsPolicyServiceFactory::GetForBrowserContext(
+       profile_)
+@@ -881,9 +887,26 @@ void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
    network_context_params->cookie_manager_params =
        CreateCookieManagerParams(profile_, *cookie_settings_);
  
-+  network_context_params->cookieable_schemes = profile_->GetCookieableSchemes();
++  if (!in_memory) {
++    network_context_params->file_paths =
++        ::network::mojom::NetworkContextFilePaths::New();
++  }
 +
    // Configure on-disk storage for non-OTR profiles. OTR profiles just use
    // default behavior (in memory storage, default sizes).
-   if (!in_memory) {
-+#if BUILDFLAG(ENABLE_CEF)
+-  if (!in_memory) {
++  if (!in_memory && cef::IsAlloyRuntimeEnabled()) {
 +    PrefService* prefs = profile_->GetPrefs();
 +    // Configure the HTTP cache path and size.
 +    const base::FilePath& base_cache_path =
 +        prefs->GetFilePath(prefs::kDiskCacheDir);
 +    DCHECK(!base_cache_path.empty());
-+    network_context_params->http_cache_path =
++    network_context_params->file_paths->http_cache_directory =
 +        base_cache_path.Append(chrome::kCacheDirname);
 +    network_context_params->http_cache_max_size =
 +        prefs->GetInteger(prefs::kDiskCacheSize);
-+#else
++  }
++
++  if (!in_memory && !cef::IsAlloyRuntimeEnabled()) {
      PrefService* local_state = g_browser_process->local_state();
      // Configure the HTTP cache path and size.
      base::FilePath base_cache_path;
-@@ -696,6 +710,7 @@ ProfileNetworkContextService::CreateNetworkContextParams(
-         base_cache_path.Append(chrome::kCacheDirname);
-     network_context_params->http_cache_max_size =
-         local_state->GetInteger(prefs::kDiskCacheSize);
-+#endif
- 
-     // Currently this just contains HttpServerProperties, but that will likely
-     // change.
-diff --git chrome/browser/profiles/profile.h chrome/browser/profiles/profile.h
-index ee2f1e1baf51..4d53c655d723 100644
---- chrome/browser/profiles/profile.h
-+++ chrome/browser/profiles/profile.h
-@@ -375,6 +375,11 @@ class Profile : public content::BrowserContext {
-   virtual bool ShouldRestoreOldSessionCookies();
-   virtual bool ShouldPersistSessionCookies();
- 
-+  // Returns schemes that should be cookieable, if other than the defaults.
-+  virtual base::Optional<std::vector<std::string>> GetCookieableSchemes() {
-+    return base::nullopt;
+@@ -892,15 +915,14 @@ void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
+         local_state->GetFilePath(prefs::kDiskCacheDir);
+     if (!disk_cache_dir.empty())
+       base_cache_path = disk_cache_dir.Append(base_cache_path.BaseName());
++    network_context_params->file_paths->http_cache_directory =
++        base_cache_path.Append(chrome::kCacheDirname);
+     const int disk_cache_size = local_state->GetInteger(prefs::kDiskCacheSize);
+     network_context_params->http_cache_max_size = disk_cache_size;
+     network_context_params->shared_dictionary_cache_max_size = disk_cache_size;
 +  }
-+
-   // Creates NetworkContext for the specified isolated app (or for the profile
-   // itself, if |relative_path| is empty).
-   virtual mojo::Remote<network::mojom::NetworkContext> CreateNetworkContext(
+ 
+-    network_context_params->file_paths =
+-        ::network::mojom::NetworkContextFilePaths::New();
+-
+-    network_context_params->file_paths->http_cache_directory =
+-        base_cache_path.Append(chrome::kCacheDirname);
++  if (!in_memory) {
+     network_context_params->file_paths->data_directory =
+         path.Append(chrome::kNetworkDataDirname);
+     network_context_params->file_paths->unsandboxed_data_path = path;
+@@ -1053,6 +1075,7 @@ void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
+   network_context_params->block_trust_tokens =
+       anti_abuse_content_setting == CONTENT_SETTING_BLOCK;
+ 
++  if (!cef::IsAlloyRuntimeEnabled()) {
+   network_context_params->first_party_sets_access_delegate_params =
+       network::mojom::FirstPartySetsAccessDelegateParams::New();
+   network_context_params->first_party_sets_access_delegate_params->enabled =
+@@ -1069,6 +1092,7 @@ void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
+           GetForBrowserContext(profile_);
+   DCHECK(fps_service);
+   fps_service->AddRemoteAccessDelegate(std::move(fps_access_delegate_remote));
++  }
+ 
+   network_context_params->acam_preflight_spec_conformant =
+       profile_->GetPrefs()->GetBoolean(
+diff --git chrome/browser/net/profile_network_context_service_factory.cc chrome/browser/net/profile_network_context_service_factory.cc
+index 14ac2ce8b90c5..99297094beea2 100644
+--- chrome/browser/net/profile_network_context_service_factory.cc
++++ chrome/browser/net/profile_network_context_service_factory.cc
+@@ -6,6 +6,7 @@
+ 
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/first_party_sets/first_party_sets_policy_service_factory.h"
+ #include "chrome/browser/net/profile_network_context_service.h"
+ #include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h"
+@@ -53,9 +54,11 @@ ProfileNetworkContextServiceFactory::ProfileNetworkContextServiceFactory()
+ #if BUILDFLAG(IS_CHROMEOS_ASH)
+   DependsOn(chromeos::CertificateProviderServiceFactory::GetInstance());
+ #endif
++  if (!cef::IsAlloyRuntimeEnabled()) {
+   DependsOn(PrivacySandboxSettingsFactory::GetInstance());
+   DependsOn(
+       first_party_sets::FirstPartySetsPolicyServiceFactory::GetInstance());
++  }
+ }
+ 
+ ProfileNetworkContextServiceFactory::~ProfileNetworkContextServiceFactory() =
+diff --git chrome/browser/signin/identity_manager_factory.cc chrome/browser/signin/identity_manager_factory.cc
+index 77522f65b7b6e..51cc2d60d4b8d 100644
+--- chrome/browser/signin/identity_manager_factory.cc
++++ chrome/browser/signin/identity_manager_factory.cc
+@@ -11,6 +11,7 @@
+ #include "base/observer_list.h"
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/runtime.h"
+ #include "chrome/browser/browser_process.h"
+ #include "chrome/browser/image_fetcher/image_decoder_impl.h"
+ #include "chrome/browser/profiles/profile.h"
+@@ -96,6 +97,7 @@ IdentityManagerFactory::~IdentityManagerFactory() {
+ // static
+ signin::IdentityManager* IdentityManagerFactory::GetForProfile(
+     Profile* profile) {
++  DCHECK(!cef::IsAlloyRuntimeEnabled());
+   return static_cast<signin::IdentityManager*>(
+       GetInstance()->GetServiceForBrowserContext(profile, true));
+ }
 diff --git net/cookies/cookie_monster.cc net/cookies/cookie_monster.cc
-index 783485c013df..bf115fd4d63a 100644
+index 0c3ce2e289b59..7ea3744e33b60 100644
 --- net/cookies/cookie_monster.cc
 +++ net/cookies/cookie_monster.cc
-@@ -476,6 +476,25 @@ void CookieMonster::SetCookieableSchemes(
+@@ -552,6 +552,25 @@ void CookieMonster::SetCookieableSchemes(
    MaybeRunCookieCallback(std::move(callback), true);
  }
  
 +void CookieMonster::AddCookieableSchemes(
 +    const std::vector<std::string>& schemes,
 +    SetCookieableSchemesCallback callback) {
-+  DCHECK(thread_checker_.CalledOnValidThread());
++  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 +
 +  // Calls to this method will have no effect if made after a WebView or
 +  // CookieManager instance has been created.
@@ -86,25 +192,25 @@
 +
  // This function must be called before the CookieMonster is used.
  void CookieMonster::SetPersistSessionCookies(bool persist_session_cookies) {
-   DCHECK(thread_checker_.CalledOnValidThread());
+   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 diff --git net/cookies/cookie_monster.h net/cookies/cookie_monster.h
-index 431fab884a5f..eeed129b49f2 100644
+index 3ca2c691cfd00..a148193f96a0e 100644
 --- net/cookies/cookie_monster.h
 +++ net/cookies/cookie_monster.h
-@@ -180,6 +180,8 @@ class NET_EXPORT CookieMonster : public CookieStore {
+@@ -208,6 +208,8 @@ class NET_EXPORT CookieMonster : public CookieStore {
    CookieChangeDispatcher& GetChangeDispatcher() override;
    void SetCookieableSchemes(const std::vector<std::string>& schemes,
                              SetCookieableSchemesCallback callback) override;
 +  void AddCookieableSchemes(const std::vector<std::string>& schemes,
 +                            SetCookieableSchemesCallback callback) override;
- 
-   // Enables writing session cookies into the cookie database. If this this
-   // method is called, it must be called before first use of the instance
+   absl::optional<bool> SiteHasCookieInOtherPartition(
+       const net::SchemefulSite& site,
+       const absl::optional<CookiePartitionKey>& partition_key) const override;
 diff --git net/cookies/cookie_store.h net/cookies/cookie_store.h
-index 996ad7d14dfb..5c8e43c1d29c 100644
+index 61fd008fc067e..73909be088278 100644
 --- net/cookies/cookie_store.h
 +++ net/cookies/cookie_store.h
-@@ -148,6 +148,11 @@ class NET_EXPORT CookieStore {
+@@ -163,6 +163,11 @@ class NET_EXPORT CookieStore {
    // Transfer ownership of a CookieAccessDelegate.
    void SetCookieAccessDelegate(std::unique_ptr<CookieAccessDelegate> delegate);
  
@@ -113,17 +219,17 @@
 +  virtual void AddCookieableSchemes(const std::vector<std::string>& schemes,
 +                                    SetCookieableSchemesCallback callback) = 0;
 +
-   // Reports the estimate of dynamically allocated memory in bytes.
-   virtual void DumpMemoryStats(base::trace_event::ProcessMemoryDump* pmd,
-                                const std::string& parent_absolute_name) const;
+   // This may be null if no delegate has been set yet, or the delegate has been
+   // reset to null.
+   const CookieAccessDelegate* cookie_access_delegate() const {
 diff --git services/network/cookie_manager.cc services/network/cookie_manager.cc
-index d1bf7a4d1f6d..772e08ee8916 100644
+index b43998a09b981..6249ece59ae77 100644
 --- services/network/cookie_manager.cc
 +++ services/network/cookie_manager.cc
-@@ -228,14 +228,9 @@ void CookieManager::FlushCookieStore(FlushCookieStoreCallback callback) {
- void CookieManager::AllowFileSchemeCookies(
-     bool allow,
+@@ -297,14 +297,9 @@ void CookieManager::AllowFileSchemeCookies(
      AllowFileSchemeCookiesCallback callback) {
+   OnSettingsWillChange();
+ 
 -  std::vector<std::string> cookieable_schemes(
 -      net::CookieMonster::kDefaultCookieableSchemes,
 -      net::CookieMonster::kDefaultCookieableSchemes +
@@ -139,36 +245,26 @@
  
  void CookieManager::SetForceKeepSessionState() {
 diff --git services/network/network_context.cc services/network/network_context.cc
-index 5e37a45a033a..ca44461120a8 100644
+index 0a0fa8772cab9..e581302c76db1 100644
 --- services/network/network_context.cc
 +++ services/network/network_context.cc
-@@ -1795,6 +1795,7 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext() {
+@@ -2509,16 +2509,20 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext(
+         network_service_->network_quality_estimator());
    }
  
-   scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store;
-+  std::unique_ptr<net::CookieMonster> cookie_store;
-   if (params_->cookie_path) {
-     scoped_refptr<base::SequencedTaskRunner> client_task_runner =
-         base::ThreadTaskRunnerHandle::Get();
-@@ -1821,18 +1822,26 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext() {
-     session_cleanup_cookie_store =
-         base::MakeRefCounted<SessionCleanupCookieStore>(sqlite_store);
- 
+-  if (session_cleanup_cookie_store) {
 -    std::unique_ptr<net::CookieMonster> cookie_store =
-+    cookie_store =
-         std::make_unique<net::CookieMonster>(session_cleanup_cookie_store.get(),
-                                              net_log);
-     if (params_->persist_session_cookies)
-       cookie_store->SetPersistSessionCookies(true);
--
+-        std::make_unique<net::CookieMonster>(session_cleanup_cookie_store.get(),
+-                                             net_log);
+-    if (params_->persist_session_cookies)
+-      cookie_store->SetPersistSessionCookies(true);
++  std::unique_ptr<net::CookieMonster> cookie_store =
++      std::make_unique<net::CookieMonster>(session_cleanup_cookie_store.get(),
++                                           net_log);
++  if (session_cleanup_cookie_store && params_->persist_session_cookies)
++    cookie_store->SetPersistSessionCookies(true);
+ 
 -    builder.SetCookieStore(std::move(cookie_store));
-   } else {
-     DCHECK(!params_->restore_old_session_cookies);
-     DCHECK(!params_->persist_session_cookies);
-+    cookie_store =
-+        std::make_unique<net::CookieMonster>(nullptr /* store */, net_log);
-+  }
-+
 +  if (params_->cookieable_schemes.has_value()) {
 +    cookie_store->SetCookieableSchemes(
 +        *params_->cookieable_schemes,
@@ -177,14 +273,14 @@
  
 +  builder.SetCookieStore(std::move(cookie_store));
 +
-   if (base::FeatureList::IsEnabled(features::kTrustTokens)) {
+   if (base::FeatureList::IsEnabled(features::kPrivateStateTokens) ||
+       base::FeatureList::IsEnabled(features::kFledgePst)) {
      trust_token_store_ = std::make_unique<PendingTrustTokenStore>();
- 
 diff --git services/network/public/mojom/network_context.mojom services/network/public/mojom/network_context.mojom
-index 9515fe92e0b1..e659550debd2 100644
+index 3d95f8cd1adeb..8a2fa92c7eb5e 100644
 --- services/network/public/mojom/network_context.mojom
 +++ services/network/public/mojom/network_context.mojom
-@@ -219,6 +219,9 @@ struct NetworkContextParams {
+@@ -376,6 +376,9 @@ struct NetworkContextParams {
    // cookies. Otherwise it should be false.
    bool persist_session_cookies = false;
  
diff --git a/src/patch/patches/services_network_2718.patch b/src/patch/patches/services_network_2718.patch
index 3302121..ced0a31 100644
--- a/src/patch/patches/services_network_2718.patch
+++ b/src/patch/patches/services_network_2718.patch
@@ -1,52 +1,57 @@
 diff --git content/browser/storage_partition_impl.cc content/browser/storage_partition_impl.cc
-index 66a4f7c28b4f..92cb66c1dc38 100644
+index 5202b07e11c21..e0448617c9512 100644
 --- content/browser/storage_partition_impl.cc
 +++ content/browser/storage_partition_impl.cc
-@@ -797,10 +797,6 @@ class LoginHandlerDelegate {
+@@ -540,10 +540,6 @@ class LoginHandlerDelegate {
      }
  
      WebContents* web_contents = web_contents_getter_.Run();
 -    if (!web_contents) {
--      OnAuthCredentials(base::nullopt);
+-      OnAuthCredentials(absl::nullopt);
 -      return;
 -    }
  
      // WeakPtr is not strictly necessary here due to OnRequestCancelled.
      creating_login_delegate_ = true;
-@@ -857,12 +853,6 @@ void OnAuthRequiredContinuation(
-     web_contents_getter =
-         base::BindRepeating(GetWebContents, process_id, routing_id);
-   }
--  if (!web_contents_getter.Run()) {
+@@ -595,12 +591,6 @@ void OnAuthRequiredContinuation(
+     mojo::PendingRemote<network::mojom::AuthChallengeResponder>
+         auth_challenge_responder,
+     base::RepeatingCallback<WebContents*(void)> web_contents_getter) {
+-  if (!web_contents_getter || !web_contents_getter.Run()) {
 -    mojo::Remote<network::mojom::AuthChallengeResponder>
 -        auth_challenge_responder_remote(std::move(auth_challenge_responder));
--    auth_challenge_responder_remote->OnAuthCredentials(base::nullopt);
+-    auth_challenge_responder_remote->OnAuthCredentials(absl::nullopt);
 -    return;
 -  }
-   new LoginHandlerDelegate(std::move(auth_challenge_responder),
-                            std::move(web_contents_getter), auth_info,
-                            is_request_for_main_frame, process_id, routing_id,
-@@ -2603,15 +2593,21 @@ void StoragePartitionImpl::GetQuotaSettings(
+   new LoginHandlerDelegate(
+       std::move(auth_challenge_responder), std::move(web_contents_getter),
+       auth_info, is_request_for_primary_main_frame, process_id, request_id, url,
+@@ -3257,8 +3247,12 @@ void StoragePartitionImpl::GetQuotaSettings(
      return;
    }
  
 +  // CEF always returns false for IsOffTheRecord(), so also check the path.
 +  const bool is_incognito = browser_context_->IsOffTheRecord() ||
 +                            browser_context_->GetPath().empty();
++
    storage::GetNominalDynamicSettings(
 -      GetPath(), browser_context_->IsOffTheRecord(),
 +      GetPath(), is_incognito,
        storage::GetDefaultDeviceInfoHelper(), std::move(callback));
  }
  
- void StoragePartitionImpl::InitNetworkContext() {
-   network_context_ = GetContentClient()->browser()->CreateNetworkContext(
-       browser_context_, is_in_memory_, relative_partition_path_);
--  DCHECK(network_context_);
-+  if (!network_context_) {
-+    // May happen during shutdown.
+@@ -3268,9 +3262,12 @@ void StoragePartitionImpl::InitNetworkContext() {
+   cert_verifier::mojom::CertVerifierCreationParamsPtr
+       cert_verifier_creation_params =
+           cert_verifier::mojom::CertVerifierCreationParams::New();
+-  GetContentClient()->browser()->ConfigureNetworkContextParams(
++  if (!GetContentClient()->browser()->ConfigureNetworkContextParams(
+       browser_context_, is_in_memory(), relative_partition_path_,
+-      context_params.get(), cert_verifier_creation_params.get());
++      context_params.get(), cert_verifier_creation_params.get())) {
++    // Don't re-initialize the network context during shutdown.
 +    return;
 +  }
- 
-   network_context_client_receiver_.reset();
-   network_context_->SetClient(
+   // Should be initialized with existing per-profile CORS access lists.
+   DCHECK(context_params->cors_origin_access_list.empty())
+       << "NetworkContextParams::cors_origin_access_list should be populated "
diff --git a/src/patch/patches/set_resize_background_color.patch b/src/patch/patches/set_resize_background_color.patch
index f6d3fa7..2009cb2 100644
--- a/src/patch/patches/set_resize_background_color.patch
+++ b/src/patch/patches/set_resize_background_color.patch
@@ -1,63 +1,23 @@
-diff --git ui/views/controls/native/native_view_host.cc ui/views/controls/native/native_view_host.cc
-index b29553ae8f7b..c31233db9ab2 100644
---- ui/views/controls/native/native_view_host.cc
-+++ ui/views/controls/native/native_view_host.cc
-@@ -154,7 +154,7 @@ void NativeViewHost::OnPaint(gfx::Canvas* canvas) {
-   // It would be nice if this used some approximation of the page's
-   // current background color.
-   if (native_wrapper_->HasInstalledClip())
--    canvas->FillRect(GetLocalBounds(), SK_ColorWHITE);
-+    canvas->FillRect(GetLocalBounds(), resize_background_color_);
- }
- 
- void NativeViewHost::VisibilityChanged(View* starting_from, bool is_visible) {
-diff --git ui/views/controls/native/native_view_host.h ui/views/controls/native/native_view_host.h
-index f92961e9f79b..f1ff80b244ef 100644
---- ui/views/controls/native/native_view_host.h
-+++ ui/views/controls/native/native_view_host.h
-@@ -86,6 +86,12 @@ class VIEWS_EXPORT NativeViewHost : public View {
-   void set_fast_resize(bool fast_resize) { fast_resize_ = fast_resize; }
-   bool fast_resize() const { return fast_resize_; }
- 
-+  // Sets the color to paint the background during a resize that involves a
-+  // clip. This is white by default.
-+  void set_resize_background_color(SkColor resize_background_color) {
-+    resize_background_color_ = resize_background_color;
-+  }
-+
-   gfx::NativeView native_view() const { return native_view_; }
- 
-   void NativeViewDestroyed();
-@@ -132,6 +138,9 @@ class VIEWS_EXPORT NativeViewHost : public View {
-   // in the setter/accessor above.
-   bool fast_resize_ = false;
- 
-+  // Color to paint in the background while resizing.
-+  SkColor resize_background_color_ = SK_ColorWHITE;
-+
-   DISALLOW_COPY_AND_ASSIGN(NativeViewHost);
- };
- 
 diff --git ui/views/controls/webview/webview.cc ui/views/controls/webview/webview.cc
-index 7bef84b8c9ea..9b9f0a789fe9 100644
+index a2459f3137633..ad29bed6db43a 100644
 --- ui/views/controls/webview/webview.cc
 +++ ui/views/controls/webview/webview.cc
-@@ -127,6 +127,10 @@ void WebView::EnableSizingFromWebContents(const gfx::Size& min_size,
-   MaybeEnableAutoResize();
+@@ -160,6 +160,10 @@ void WebView::EnableSizingFromWebContents(const gfx::Size& min_size,
+   }
  }
  
 +void WebView::SetResizeBackgroundColor(SkColor resize_background_color) {
-+  holder_->set_resize_background_color(resize_background_color);
++  holder_->SetBackgroundColorWhenClipped(resize_background_color);
 +}
 +
  void WebView::SetCrashedOverlayView(View* crashed_overlay_view) {
-   if (crashed_overlay_view_ == crashed_overlay_view)
+   if (crashed_overlay_view_.view() == crashed_overlay_view) {
      return;
 diff --git ui/views/controls/webview/webview.h ui/views/controls/webview/webview.h
-index 84d5cd520f7a..c7a2c7644c4f 100644
+index ff8755f0cfa28..0c7d3e22b863a 100644
 --- ui/views/controls/webview/webview.h
 +++ ui/views/controls/webview/webview.h
-@@ -82,6 +82,10 @@ class WEBVIEW_EXPORT WebView : public View,
+@@ -91,6 +91,10 @@ class WEBVIEW_EXPORT WebView : public View,
    void EnableSizingFromWebContents(const gfx::Size& min_size,
                                     const gfx::Size& max_size);
  
@@ -67,4 +27,4 @@
 +
    // If provided, this View will be shown in place of the web contents
    // when the web contents is in a crashed state. This is cleared automatically
-   // if the web contents is changed.
+   // if the web contents is changed. The passed-in overlay view must be owned by
diff --git a/src/patch/patches/storage_incognito_2289.patch b/src/patch/patches/storage_incognito_2289.patch
index 96bfb4a..516680e 100644
--- a/src/patch/patches/storage_incognito_2289.patch
+++ b/src/patch/patches/storage_incognito_2289.patch
@@ -1,8 +1,8 @@
 diff --git content/browser/blob_storage/chrome_blob_storage_context.cc content/browser/blob_storage/chrome_blob_storage_context.cc
-index f90e9fce0675..33551a2874bc 100644
+index 01d2a426e2c17..c239a2f6fc786 100644
 --- content/browser/blob_storage/chrome_blob_storage_context.cc
 +++ content/browser/blob_storage/chrome_blob_storage_context.cc
-@@ -117,7 +117,8 @@ ChromeBlobStorageContext* ChromeBlobStorageContext::GetFor(
+@@ -125,7 +125,8 @@ ChromeBlobStorageContext* ChromeBlobStorageContext::GetFor(
  
      // If we're not incognito mode, schedule all of our file tasks to enable
      // disk on the storage context.
@@ -13,45 +13,60 @@
            {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
             base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 diff --git content/browser/browser_context.cc content/browser/browser_context.cc
-index 90ec29eda0e7..80cf13d79eff 100644
+index c07c16f62e3fb..25b4cd3e023e4 100644
 --- content/browser/browser_context.cc
 +++ content/browser/browser_context.cc
-@@ -59,6 +59,7 @@
- #include "content/public/common/content_switches.h"
- #include "content/public/common/service_manager_connection.h"
- #include "content/public/common/service_names.mojom.h"
-+#include "media/capabilities/in_memory_video_decode_stats_db_impl.h"
- #include "media/base/media_switches.h"
- #include "media/capabilities/in_memory_video_decode_stats_db_impl.h"
- #include "media/capabilities/video_decode_stats_db_impl.h"
-@@ -170,7 +171,7 @@ StoragePartition* GetStoragePartitionFromConfig(
-   StoragePartitionImplMap* partition_map =
-       GetStoragePartitionMap(browser_context);
+@@ -130,7 +130,7 @@ StoragePartition* BrowserContext::GetStoragePartition(
+ StoragePartition* BrowserContext::GetStoragePartition(
+     const StoragePartitionConfig& storage_partition_config,
+     bool can_create) {
+-  if (IsOffTheRecord()) {
++  if (IsOffTheRecord() || GetPath().empty()) {
+     // An off the record profile MUST only use in memory storage partitions.
+     CHECK(storage_partition_config.in_memory());
+   }
+@@ -356,7 +356,8 @@ BrowserContext::CreateVideoDecodePerfHistory() {
+   const bool kUseInMemoryDBDefault = false;
+   bool use_in_memory_db = base::GetFieldTrialParamByFeatureAsBool(
+       media::kMediaCapabilitiesWithParameters, kUseInMemoryDBParamName,
+-      kUseInMemoryDBDefault);
++      kUseInMemoryDBDefault) ||
++      GetPath().empty();
  
--  if (browser_context->IsOffTheRecord())
-+  if (browser_context->IsOffTheRecord() || browser_context->GetPath().empty())
-     in_memory = true;
+   std::unique_ptr<media::VideoDecodeStatsDB> stats_db;
+   if (use_in_memory_db) {
+diff --git content/public/browser/storage_partition_config.cc content/public/browser/storage_partition_config.cc
+index 81013d6eb993a..89abfbe7fec6c 100644
+--- content/public/browser/storage_partition_config.cc
++++ content/public/browser/storage_partition_config.cc
+@@ -7,6 +7,7 @@
+ #include <sstream>
  
-   return partition_map->Get(partition_domain, partition_name, in_memory,
-@@ -674,7 +675,7 @@ media::VideoDecodePerfHistory* BrowserContext::GetVideoDecodePerfHistory() {
-         kUseInMemoryDBDefault);
+ #include "base/check.h"
++#include "base/files/file_path.h"
+ #include "base/strings/string_number_conversions.h"
+ #include "content/public/browser/browser_context.h"
+ #include "url/gurl.h"
+@@ -22,7 +23,8 @@ StoragePartitionConfig& StoragePartitionConfig::operator=(
+ // static
+ StoragePartitionConfig StoragePartitionConfig::CreateDefault(
+     BrowserContext* browser_context) {
+-  return StoragePartitionConfig("", "", browser_context->IsOffTheRecord());
++  return StoragePartitionConfig("", "", browser_context->IsOffTheRecord() ||
++                                        browser_context->GetPath().empty());
+ }
  
-     std::unique_ptr<media::VideoDecodeStatsDB> stats_db;
--    if (use_in_memory_db) {
-+    if (use_in_memory_db || GetPath().empty()) {
-       stats_db =
-           std::make_unique<media::InMemoryVideoDecodeStatsDBImpl>(nullptr);
-     } else {
+ // static
 diff --git storage/browser/database/database_tracker.cc storage/browser/database/database_tracker.cc
-index 41dc6c9ac188..b125c1d2bcc8 100644
+index 2926db89bac41..8710578eee554 100644
 --- storage/browser/database/database_tracker.cc
 +++ storage/browser/database/database_tracker.cc
-@@ -506,7 +506,7 @@ bool DatabaseTracker::LazyInit() {
-     meta_table_.reset(new sql::MetaTable());
+@@ -569,7 +569,7 @@ bool DatabaseTracker::LazyInit() {
+     databases_table_ = std::make_unique<DatabasesTable>(db_.get());
+     meta_table_ = std::make_unique<sql::MetaTable>();
  
-     is_initialized_ =
--        base::CreateDirectory(db_dir_) &&
-+        (is_incognito_ ? true : base::CreateDirectory(db_dir_)) &&
-         (db_->is_open() ||
-          (is_incognito_ ? db_->OpenInMemory() :
-           db_->Open(kTrackerDatabaseFullPath))) &&
+-    is_initialized_ = base::CreateDirectory(db_dir_) &&
++    is_initialized_ = (is_incognito_ ? true : base::CreateDirectory(db_dir_)) &&
+                       (db_->is_open() ||
+                        (is_incognito_ ? db_->OpenInMemory()
+                                       : db_->Open(kTrackerDatabaseFullPath))) &&
diff --git a/src/patch/patches/trace_event.patch b/src/patch/patches/trace_event.patch
index 524aa47..6fb7c14 100644
--- a/src/patch/patches/trace_event.patch
+++ b/src/patch/patches/trace_event.patch
@@ -1,8 +1,8 @@
 diff --git base/trace_event/builtin_categories.h base/trace_event/builtin_categories.h
-index ac67c35bbcb0..f1ebee76b00d 100644
+index 2f9a9813f863c..f6cc9aabf8540 100644
 --- base/trace_event/builtin_categories.h
 +++ base/trace_event/builtin_categories.h
-@@ -52,6 +52,8 @@
+@@ -65,6 +65,8 @@
    X("cc")                                                                \
    X("cc.debug")                                                          \
    X("cdp.perf")                                                          \
diff --git a/src/patch/patches/ui_dragdrop_355390.patch b/src/patch/patches/ui_dragdrop_355390.patch
index 03a2c4a..1f5e08d 100644
--- a/src/patch/patches/ui_dragdrop_355390.patch
+++ b/src/patch/patches/ui_dragdrop_355390.patch
@@ -1,9 +1,9 @@
 diff --git ui/base/x/x11_os_exchange_data_provider.cc ui/base/x/x11_os_exchange_data_provider.cc
-index 41190f9f56a9..dcb869d1e2f5 100644
+index 5d169e08b509d..aff534bddfd2f 100644
 --- ui/base/x/x11_os_exchange_data_provider.cc
 +++ ui/base/x/x11_os_exchange_data_provider.cc
-@@ -127,7 +127,8 @@ void XOSExchangeDataProvider::SetURL(const GURL& url,
-     format_map_.Insert(gfx::GetAtom(kMimeTypeMozillaURL), mem);
+@@ -157,7 +157,8 @@ void XOSExchangeDataProvider::SetURL(const GURL& url,
+     format_map_.Insert(x11::GetAtom(kMimeTypeMozillaURL), mem);
  
      // Set a string fallback as well.
 -    SetString(spec);
diff --git a/src/patch/patches/ui_views_widget_type.patch b/src/patch/patches/ui_views_widget_type.patch
new file mode 100644
index 0000000..1d35923
--- /dev/null
+++ b/src/patch/patches/ui_views_widget_type.patch
@@ -0,0 +1,27 @@
+diff --git chrome/browser/ui/views/chrome_views_delegate_linux.cc chrome/browser/ui/views/chrome_views_delegate_linux.cc
+index ecc07a2a60505..82a379fa65e68 100644
+--- chrome/browser/ui/views/chrome_views_delegate_linux.cc
++++ chrome/browser/ui/views/chrome_views_delegate_linux.cc
+@@ -52,6 +52,8 @@ NativeWidgetType GetNativeWidgetTypeForInitParams(
+     return NativeWidgetType::DESKTOP_NATIVE_WIDGET_AURA;
+ 
+   return (params.parent &&
++          (params.child ||
++           params.type == views::Widget::InitParams::TYPE_BUBBLE) &&
+           params.type != views::Widget::InitParams::TYPE_MENU &&
+           params.type != views::Widget::InitParams::TYPE_TOOLTIP)
+              ? NativeWidgetType::NATIVE_WIDGET_AURA
+diff --git ui/views/test/desktop_test_views_delegate_aura.cc ui/views/test/desktop_test_views_delegate_aura.cc
+index 110eab7eec92a..2bfc96b6c439d 100644
+--- ui/views/test/desktop_test_views_delegate_aura.cc
++++ ui/views/test/desktop_test_views_delegate_aura.cc
+@@ -27,7 +27,8 @@ void DesktopTestViewsDelegate::OnBeforeWidgetInit(
+   if (params->native_widget)
+     return;
+ 
+-  if (params->parent && params->type != views::Widget::InitParams::TYPE_MENU &&
++  if (params->parent && params->child &&
++      params->type != views::Widget::InitParams::TYPE_MENU &&
+       params->type != views::Widget::InitParams::TYPE_TOOLTIP) {
+     params->native_widget = new views::NativeWidgetAura(delegate);
+   } else {
diff --git a/src/patch/patches/underlay_1051.patch b/src/patch/patches/underlay_1051.patch
deleted file mode 100644
index 330aaa6..0000000
--- a/src/patch/patches/underlay_1051.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git ui/base/cocoa/underlay_opengl_hosting_window.h ui/base/cocoa/underlay_opengl_hosting_window.h
-index d673c31a0f31..806d1341567b 100644
---- ui/base/cocoa/underlay_opengl_hosting_window.h
-+++ ui/base/cocoa/underlay_opengl_hosting_window.h
-@@ -12,7 +12,7 @@
- // Common base class for windows that host a OpenGL surface that renders under
- // the window. Previously contained methods related to hole punching, now just
- // contains common asserts.
--UI_BASE_EXPORT
-+__attribute__((visibility("default")))
- @interface UnderlayOpenGLHostingWindow : NSWindow
- @end
- 
diff --git a/src/patch/patches/views_1749_2102.patch b/src/patch/patches/views_1749_2102.patch
deleted file mode 100644
index cf38e9a..0000000
--- a/src/patch/patches/views_1749_2102.patch
+++ /dev/null
@@ -1,493 +0,0 @@
-diff --git ui/base/models/menu_model.h ui/base/models/menu_model.h
-index 5bcc6204c2b5..1bf18609d150 100644
---- ui/base/models/menu_model.h
-+++ ui/base/models/menu_model.h
-@@ -16,6 +16,7 @@
- namespace gfx {
- class FontList;
- class Image;
-+class Point;
- struct VectorIcon;
- }
- 
-@@ -125,6 +126,27 @@ class UI_BASE_EXPORT MenuModel : public base::SupportsWeakPtr<MenuModel> {
-   // |event_flags| is a bit mask of ui::EventFlags.
-   virtual void ActivatedAt(int index, int event_flags);
- 
-+  // Called when the user moves the mouse outside the menu and over the owning
-+  // window.
-+  virtual void MouseOutsideMenu(const gfx::Point& screen_point) {}
-+
-+  // Called on unhandled open/close submenu keyboard commands. |is_rtl| will be
-+  // true if the menu is displaying a right-to-left language.
-+  virtual void UnhandledOpenSubmenu(bool is_rtl) {}
-+  virtual void UnhandledCloseSubmenu(bool is_rtl) {}
-+
-+  // Override the text/background color of a given menu item dependent on the
-+  // |index| and its |is_hovered| state. |is_minor| will be true for accelerator
-+  // text. Returns true if it chooses to override the color.
-+  virtual bool GetTextColor(int index,
-+                            bool is_minor,
-+                            bool is_hovered,
-+                            SkColor* override_color) const { return false; }
-+  virtual bool GetBackgroundColor(int index,
-+                                  bool is_hovered,
-+                                  SkColor* override_color) const
-+                                  { return false; }
-+
-   // Called when the menu is about to be shown.
-   virtual void MenuWillShow() {}
- 
-diff --git ui/gfx/render_text.cc ui/gfx/render_text.cc
-index 7d5fb0c4d6e6..79e59cd87f91 100644
---- ui/gfx/render_text.cc
-+++ ui/gfx/render_text.cc
-@@ -609,6 +609,14 @@ void RenderText::SetWhitespaceElision(base::Optional<bool> whitespace_elision) {
-   }
- }
- 
-+void RenderText::SetDrawStringsFlags(int flags) {
-+  if (draw_strings_flags_ == flags)
-+    return;
-+  draw_strings_flags_ = flags;
-+  cached_bounds_and_offset_valid_ = false;
-+  OnTextAttributeChanged();
-+}
-+
- void RenderText::SetDisplayRect(const Rect& r) {
-   if (r != display_rect_) {
-     display_rect_ = r;
-@@ -1973,6 +1981,19 @@ void RenderText::OnTextAttributeChanged() {
- 
-   layout_text_up_to_date_ = false;
- 
-+  if (draw_strings_flags_ != 0) {
-+    // Compute layout size with the mnemonic character underlined since it might
-+    // be larger than with the underline hidden.
-+    int char_pos = -1;
-+    int char_span = 0;
-+    layout_text_ =
-+        gfx::RemoveAcceleratorChar(layout_text_, '&', &char_pos, &char_span);
-+    if (char_pos != -1) {
-+      gfx::Range range(char_pos, char_pos + char_span);
-+      styles_[TEXT_STYLE_UNDERLINE].ApplyValue(true, range);
-+    }
-+  }
-+
-   OnLayoutTextAttributeChanged(true);
- }
- 
-diff --git ui/gfx/render_text.h ui/gfx/render_text.h
-index 892b32910b77..0d3c4ef5cafa 100644
---- ui/gfx/render_text.h
-+++ ui/gfx/render_text.h
-@@ -324,6 +324,10 @@ class GFX_EXPORT RenderText {
-     return whitespace_elision_;
-   }
- 
-+  // Get or set the flags that control display of accelerator characters.
-+  void SetDrawStringsFlags(int flags);
-+  int draw_strings_flags() const { return draw_strings_flags_; }
-+
-   const Rect& display_rect() const { return display_rect_; }
-   void SetDisplayRect(const Rect& r);
- 
-@@ -1006,6 +1010,8 @@ class GFX_EXPORT RenderText {
-   // Tell whether or not the |layout_text_| needs an update or is up to date.
-   mutable bool layout_text_up_to_date_ = false;
- 
-+  int draw_strings_flags_ = 0;
-+
-   DISALLOW_COPY_AND_ASSIGN(RenderText);
- };
- 
-diff --git ui/views/animation/ink_drop_host_view.h ui/views/animation/ink_drop_host_view.h
-index b711c5f08f80..d0d428057e5d 100644
---- ui/views/animation/ink_drop_host_view.h
-+++ ui/views/animation/ink_drop_host_view.h
-@@ -138,6 +138,8 @@ class VIEWS_EXPORT InkDropHostView : public View {
-   // this isn't necessary anymore.
-   virtual InkDrop* GetInkDrop();
- 
-+  InkDropMode ink_drop_mode() const { return ink_drop_mode_; }
-+
-  protected:
-   // Size used for the default SquareInkDropRipple.
-   static constexpr gfx::Size kDefaultInkDropSize = gfx::Size(24, 24);
-diff --git ui/views/controls/button/label_button.cc ui/views/controls/button/label_button.cc
-index bb9105f1a18e..45ae9cdb4ab0 100644
---- ui/views/controls/button/label_button.cc
-+++ ui/views/controls/button/label_button.cc
-@@ -480,6 +480,12 @@ void LabelButton::OnThemeChanged() {
-   SchedulePaint();
- }
- 
-+void LabelButton::SetFontList(const gfx::FontList& font_list) {
-+  cached_normal_font_list_ = font_list;
-+  cached_default_button_font_list_ = font_list;
-+  label_->SetFontList(cached_normal_font_list_);
-+}
-+
- void LabelButton::StateChanged(ButtonState old_state) {
-   const gfx::Size previous_image_size(image_->GetPreferredSize());
-   UpdateImage();
-diff --git ui/views/controls/button/label_button.h ui/views/controls/button/label_button.h
-index ac348aa7dd46..88ab098daddc 100644
---- ui/views/controls/button/label_button.h
-+++ ui/views/controls/button/label_button.h
-@@ -124,6 +124,9 @@ class VIEWS_EXPORT LabelButton : public Button, public NativeThemeDelegate {
-   ui::NativeTheme::State GetForegroundThemeState(
-       ui::NativeTheme::ExtraParams* params) const override;
- 
-+  // Sets the font list used by this button.
-+  void SetFontList(const gfx::FontList& font_list);
-+
-  protected:
-   ImageView* image() const { return image_; }
-   Label* label() const { return label_; }
-diff --git ui/views/controls/label.cc ui/views/controls/label.cc
-index c15c27ae75b6..325eec4939de 100644
---- ui/views/controls/label.cc
-+++ ui/views/controls/label.cc
-@@ -53,6 +53,20 @@ bool IsOpaque(SkColor color) {
-   return SkColorGetA(color) == SK_AlphaOPAQUE;
- }
- 
-+// Strips accelerator character prefixes in |text| if needed, based on |flags|.
-+// Returns a range in |text| to underline or Range::InvalidRange() if
-+// underlining is not needed.
-+gfx::Range StripAcceleratorChars(int flags, base::string16* text) {
-+  if (flags & (gfx::Canvas::SHOW_PREFIX | gfx::Canvas::HIDE_PREFIX)) {
-+    int char_pos = -1;
-+    int char_span = 0;
-+    *text = gfx::RemoveAcceleratorChar(*text, '&', &char_pos, &char_span);
-+    if ((flags & gfx::Canvas::SHOW_PREFIX) && char_pos != -1)
-+      return gfx::Range(char_pos, char_pos + char_span);
-+  }
-+  return gfx::Range::InvalidRange();
-+}
-+
- }  // namespace
- 
- namespace views {
-@@ -308,6 +322,14 @@ base::string16 Label::GetTooltipText() const {
-   return tooltip_text_;
- }
- 
-+void Label::SetDrawStringsFlags(int flags) {
-+  if (draw_strings_flags_ == flags)
-+    return;
-+  draw_strings_flags_ = flags;
-+  full_text_->SetDrawStringsFlags(draw_strings_flags_);
-+  ResetLayout();
-+}
-+
- void Label::SetTooltipText(const base::string16& tooltip_text) {
-   DCHECK(handles_tooltips_);
-   if (tooltip_text_ == tooltip_text)
-@@ -582,7 +604,19 @@ std::unique_ptr<gfx::RenderText> Label::CreateRenderText() const {
-   render_text->SetFontList(font_list());
-   render_text->set_shadows(GetShadows());
-   render_text->SetCursorEnabled(false);
--  render_text->SetText(GetText());
-+
-+  if (draw_strings_flags_ != 0) {
-+    base::string16 text_str = GetText();
-+    gfx::Range range = StripAcceleratorChars(draw_strings_flags_, &text_str);
-+    render_text->SetText(text_str);
-+    if (range.IsValid()) {
-+      render_text->SetDisplayRect(bounds());
-+      render_text->ApplyStyle(gfx::TEXT_STYLE_UNDERLINE, true, range);
-+    }
-+  } else {
-+    render_text->SetText(GetText());
-+  }
-+
-   const bool multiline = GetMultiLine();
-   render_text->SetMultiline(multiline);
-   render_text->SetMaxLines(multiline ? GetMaxLines() : 0);
-diff --git ui/views/controls/label.h ui/views/controls/label.h
-index 4cb533caa9c7..63eac79c878c 100644
---- ui/views/controls/label.h
-+++ ui/views/controls/label.h
-@@ -177,6 +177,10 @@ class VIEWS_EXPORT Label : public View,
-   gfx::ElideBehavior GetElideBehavior() const;
-   void SetElideBehavior(gfx::ElideBehavior elide_behavior);
- 
-+  // Get or set the flags that control display of accelerator characters.
-+  void SetDrawStringsFlags(int flags);
-+  int GetDrawStringsFlags() const { return draw_strings_flags_; }
-+
-   // Gets/Sets the tooltip text.  Default behavior for a label (single-line) is
-   // to show the full text if it is wider than its bounds.  Calling this
-   // overrides the default behavior and lets you set a custom tooltip.  To
-@@ -413,6 +417,7 @@ class VIEWS_EXPORT Label : public View,
-   bool collapse_when_hidden_ = false;
-   int fixed_width_ = 0;
-   int max_width_ = 0;
-+  int draw_strings_flags_ = 0;
- 
-   std::unique_ptr<SelectionController> selection_controller_;
- 
-diff --git ui/views/controls/menu/menu_controller.cc ui/views/controls/menu/menu_controller.cc
-index d8c09129ad9a..7c28530fa7dd 100644
---- ui/views/controls/menu/menu_controller.cc
-+++ ui/views/controls/menu/menu_controller.cc
-@@ -2638,8 +2638,13 @@ MenuItemView* MenuController::FindNextSelectableMenuItem(
- 
- void MenuController::OpenSubmenuChangeSelectionIfCan() {
-   MenuItemView* item = pending_state_.item;
--  if (!item->HasSubmenu() || !item->GetEnabled())
-+  if (!item->HasSubmenu() || !item->GetEnabled() || !item->GetParentMenuItem()) {
-+    MenuItemView* submenu_item =
-+        item->GetParentMenuItem() ? item->GetParentMenuItem() : item;
-+    submenu_item->GetDelegate()->OnUnhandledOpenSubmenu(submenu_item,
-+                                                        base::i18n::IsRTL());
-     return;
-+  }
-   MenuItemView* to_select = nullptr;
-   if (!item->GetSubmenu()->GetMenuItems().empty())
-     to_select = FindInitialSelectableMenuItem(item, INCREMENT_SELECTION_DOWN);
-@@ -2658,8 +2663,10 @@ void MenuController::OpenSubmenuChangeSelectionIfCan() {
- void MenuController::CloseSubmenu() {
-   MenuItemView* item = state_.item;
-   DCHECK(item);
--  if (!item->GetParentMenuItem())
-+  if (!item->GetParentMenuItem()) {
-+    item->GetDelegate()->OnUnhandledCloseSubmenu(item, base::i18n::IsRTL());
-     return;
-+  }
-   if (item->SubmenuIsShowing())
-     SetSelection(item, SELECTION_UPDATE_IMMEDIATELY);
-   else if (item->GetParentMenuItem()->GetParentMenuItem())
-diff --git ui/views/controls/menu/menu_delegate.h ui/views/controls/menu/menu_delegate.h
-index 2a03ff43f4a6..c12d68eb212c 100644
---- ui/views/controls/menu/menu_delegate.h
-+++ ui/views/controls/menu/menu_delegate.h
-@@ -81,6 +81,22 @@ class VIEWS_EXPORT MenuDelegate {
-   // parts of |style| or leave it unmodified.
-   virtual void GetLabelStyle(int id, LabelStyle* style) const;
- 
-+  // Override the text color of a given menu item dependent on the |command_id|
-+  // and its |is_hovered| state. |is_minor| will be true for accelerator text.
-+  // Returns true if it chooses to override the color.
-+  virtual bool GetTextColor(int command_id,
-+                            bool is_minor,
-+                            bool is_hovered,
-+                            SkColor* override_color) const { return false; }
-+
-+  // Override the background color of a given menu item dependent on the
-+  // |command_id| and its |is_hovered| state. Returns true if it chooses to
-+  // override the color.
-+  virtual bool GetBackgroundColor(int command_id,
-+                                  bool is_hovered,
-+                                  SkColor* override_color) const
-+                                  { return false; }
-+
-   // The tooltip shown for the menu item. This is invoked when the user
-   // hovers over the item, and no tooltip text has been set for that item.
-   virtual base::string16 GetTooltipText(int id,
-@@ -207,6 +223,11 @@ class VIEWS_EXPORT MenuDelegate {
-                                        bool* has_mnemonics,
-                                        MenuButton** button);
- 
-+  // Called on unhandled open/close submenu keyboard commands. |is_rtl| will be
-+  // true if the menu is displaying a right-to-left language.
-+  virtual void OnUnhandledOpenSubmenu(MenuItemView* menu, bool is_rtl) {}
-+  virtual void OnUnhandledCloseSubmenu(MenuItemView* menu, bool is_rtl) {}
-+
-   // Returns the max width menus can grow to be.
-   virtual int GetMaxWidthForMenu(MenuItemView* menu);
- 
-diff --git ui/views/controls/menu/menu_item_view.cc ui/views/controls/menu/menu_item_view.cc
-index 6f45e5ac5d1c..d8a0eee3fedd 100644
---- ui/views/controls/menu/menu_item_view.cc
-+++ ui/views/controls/menu/menu_item_view.cc
-@@ -987,6 +987,15 @@ void MenuItemView::PaintBackground(gfx::Canvas* canvas,
-     spilling_rect.set_y(spilling_rect.y() - corner_radius_);
-     spilling_rect.set_height(spilling_rect.height() + corner_radius_);
-     canvas->DrawRoundRect(spilling_rect, corner_radius_, flags);
-+    return;
-+  }
-+
-+  MenuDelegate *delegate = GetDelegate();
-+  SkColor override_color;
-+  if (delegate && delegate->GetBackgroundColor(GetCommand(),
-+                                               render_selection,
-+                                               &override_color)) {
-+    canvas->DrawColor(override_color);
-   } else if (render_selection) {
-     gfx::Rect item_bounds = GetLocalBounds();
-     if (type_ == Type::kActionableSubMenu) {
-@@ -1054,6 +1063,13 @@ void MenuItemView::PaintMinorIconAndText(
- }
- 
- SkColor MenuItemView::GetTextColor(bool minor, bool render_selection) const {
-+  SkColor text_color;
-+  const MenuDelegate *delegate = GetDelegate();
-+  if (delegate && delegate->GetTextColor(GetCommand(), minor, render_selection,
-+                                         &text_color)) {
-+    return text_color;
-+  }
-+
-   style::TextContext context =
-       GetMenuController() && GetMenuController()->use_touchable_layout()
-           ? style::CONTEXT_TOUCH_MENU
-diff --git ui/views/controls/menu/menu_model_adapter.cc ui/views/controls/menu/menu_model_adapter.cc
-index 88a868cf6f98..b7c10dc5613c 100644
---- ui/views/controls/menu/menu_model_adapter.cc
-+++ ui/views/controls/menu/menu_model_adapter.cc
-@@ -230,6 +230,77 @@ bool MenuModelAdapter::IsItemChecked(int id) const {
-   return false;
- }
- 
-+MenuItemView* MenuModelAdapter::GetSiblingMenu(MenuItemView* menu,
-+                                               const gfx::Point& screen_point,
-+                                               MenuAnchorPosition* anchor,
-+                                               bool* has_mnemonics,
-+                                               MenuButton** button) {
-+  // Look up the menu model for this menu.
-+  const std::map<MenuItemView*, ui::MenuModel*>::const_iterator map_iterator =
-+      menu_map_.find(menu);
-+  if (map_iterator != menu_map_.end()) {
-+    map_iterator->second->MouseOutsideMenu(screen_point);
-+    return nullptr;
-+  }
-+
-+  NOTREACHED();
-+  return nullptr;
-+}
-+
-+void MenuModelAdapter::OnUnhandledOpenSubmenu(MenuItemView* menu,
-+                                              bool is_rtl) {
-+  // Look up the menu model for this menu.
-+  const std::map<MenuItemView*, ui::MenuModel*>::const_iterator map_iterator =
-+      menu_map_.find(menu);
-+  if (map_iterator != menu_map_.end()) {
-+    map_iterator->second->UnhandledOpenSubmenu(is_rtl);
-+    return;
-+  }
-+
-+  NOTREACHED();
-+}
-+
-+void MenuModelAdapter::OnUnhandledCloseSubmenu(MenuItemView* menu,
-+                                               bool is_rtl) {
-+  // Look up the menu model for this menu.
-+  const std::map<MenuItemView*, ui::MenuModel*>::const_iterator map_iterator =
-+      menu_map_.find(menu);
-+  if (map_iterator != menu_map_.end()) {
-+    map_iterator->second->UnhandledCloseSubmenu(is_rtl);
-+    return;
-+  }
-+
-+  NOTREACHED();
-+}
-+
-+bool MenuModelAdapter::GetTextColor(int command_id,
-+                                    bool is_minor,
-+                                    bool is_hovered,
-+                                    SkColor* override_color) const {
-+  ui::MenuModel* model = menu_model_;
-+  int index = 0;
-+  if (ui::MenuModel::GetModelAndIndexForCommandId(command_id, &model, &index))
-+    return model->GetTextColor(index, is_minor, is_hovered, override_color);
-+
-+  NOTREACHED();
-+  return false;
-+}
-+
-+bool MenuModelAdapter::GetBackgroundColor(int command_id,
-+                                          bool is_hovered,
-+                                          SkColor* override_color) const {
-+  if (command_id == -1)
-+    return menu_model_->GetBackgroundColor(-1, is_hovered, override_color);
-+
-+  ui::MenuModel* model = menu_model_;
-+  int index = 0;
-+  if (ui::MenuModel::GetModelAndIndexForCommandId(command_id, &model, &index))
-+    return model->GetBackgroundColor(index, is_hovered, override_color);
-+
-+  NOTREACHED();
-+  return false;
-+}
-+
- void MenuModelAdapter::WillShowMenu(MenuItemView* menu) {
-   // Look up the menu model for this menu.
-   const std::map<MenuItemView*, ui::MenuModel*>::const_iterator map_iterator =
-diff --git ui/views/controls/menu/menu_model_adapter.h ui/views/controls/menu/menu_model_adapter.h
-index 78f832fd3acf..cb030c991614 100644
---- ui/views/controls/menu/menu_model_adapter.h
-+++ ui/views/controls/menu/menu_model_adapter.h
-@@ -84,6 +84,20 @@ class VIEWS_EXPORT MenuModelAdapter : public MenuDelegate,
-   bool IsCommandEnabled(int id) const override;
-   bool IsCommandVisible(int id) const override;
-   bool IsItemChecked(int id) const override;
-+  MenuItemView* GetSiblingMenu(MenuItemView* menu,
-+                               const gfx::Point& screen_point,
-+                               MenuAnchorPosition* anchor,
-+                               bool* has_mnemonics,
-+                               MenuButton** button) override;
-+  void OnUnhandledOpenSubmenu(MenuItemView* menu, bool is_rtl) override;
-+  void OnUnhandledCloseSubmenu(MenuItemView* menu, bool is_rtl) override;
-+  bool GetTextColor(int command_id,
-+                    bool is_minor,
-+                    bool is_hovered,
-+                    SkColor* override_color) const override;
-+  bool GetBackgroundColor(int command_id,
-+                          bool is_hovered,
-+                          SkColor* override_color) const override;
-   void WillShowMenu(MenuItemView* menu) override;
-   void WillHideMenu(MenuItemView* menu) override;
-   void OnMenuClosed(MenuItemView* menu) override;
-diff --git ui/views/controls/menu/menu_scroll_view_container.cc ui/views/controls/menu/menu_scroll_view_container.cc
-index 7a9d15cb2066..abfe73a68ace 100644
---- ui/views/controls/menu/menu_scroll_view_container.cc
-+++ ui/views/controls/menu/menu_scroll_view_container.cc
-@@ -189,6 +189,11 @@ MenuScrollViewContainer::MenuScrollViewContainer(SubmenuView* content_view)
-   scroll_down_button_ =
-       AddChildView(std::make_unique<MenuScrollButton>(content_view, false));
- 
-+  SkColor override_color;
-+  MenuDelegate* delegate = content_view_->GetMenuItem()->GetDelegate();
-+  if (delegate && delegate->GetBackgroundColor(-1, false, &override_color))
-+    SetBackground(views::CreateSolidBackground(override_color));
-+
-   arrow_ = BubbleBorderTypeFromAnchor(
-       content_view_->GetMenuItem()->GetMenuController()->GetAnchorPosition());
- 
-diff --git ui/views/test/ui_controls_factory_desktop_aurax11.cc ui/views/test/ui_controls_factory_desktop_aurax11.cc
-index 82a2d7a7827f..082c614e57a9 100644
---- ui/views/test/ui_controls_factory_desktop_aurax11.cc
-+++ ui/views/test/ui_controls_factory_desktop_aurax11.cc
-@@ -139,10 +139,6 @@ class UIControlsDesktopX11 : public UIControlsAura {
-         aura::test::QueryLatestMousePositionRequestInHost(host);
-     host->ConvertPixelsToDIP(&root_current_location);
- 
--    auto* screen = views::test::TestDesktopScreenX11::GetInstance();
--    DCHECK_EQ(screen, display::Screen::GetScreen());
--    screen->set_cursor_screen_point(gfx::Point(screen_x, screen_y));
--
-     if (root_location != root_current_location && button_down_mask == 0) {
-       // Move the cursor because EnterNotify/LeaveNotify are generated with the
-       // current mouse position as a result of XGrabPointer()
-diff --git ui/views/view.h ui/views/view.h
-index b1dfe17e2b28..87480a766437 100644
---- ui/views/view.h
-+++ ui/views/view.h
-@@ -23,6 +23,7 @@
- #include "base/logging.h"
- #include "base/macros.h"
- #include "base/memory/ptr_util.h"
-+#include "base/supports_user_data.h"
- #include "build/build_config.h"
- #include "third_party/skia/include/core/SkPath.h"
- #include "ui/accessibility/ax_enums.mojom-forward.h"
-@@ -273,6 +274,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
-                           public ui::EventTarget,
-                           public ui::EventHandler,
-                           public ui::PropertyHandler,
-+                          public base::SupportsUserData,
-                           public views::metadata::MetaDataProvider {
-  public:
-   using Views = std::vector<View*>;
diff --git a/src/patch/patches/views_1749_2102_3330.patch b/src/patch/patches/views_1749_2102_3330.patch
new file mode 100644
index 0000000..b9b5376
--- /dev/null
+++ b/src/patch/patches/views_1749_2102_3330.patch
@@ -0,0 +1,739 @@
+diff --git ui/base/models/menu_model.h ui/base/models/menu_model.h
+index a6d70c71a1b3a..1b628f5284409 100644
+--- ui/base/models/menu_model.h
++++ ui/base/models/menu_model.h
+@@ -17,8 +17,11 @@
+ #include "ui/color/color_id.h"
+ #include "ui/gfx/native_widget_types.h"
+ 
++#include "third_party/skia/include/core/SkColor.h"
++
+ namespace gfx {
+ class FontList;
++class Point;
+ }
+ 
+ namespace ui {
+@@ -147,6 +150,27 @@ class COMPONENT_EXPORT(UI_BASE) MenuModel
+   // |event_flags| is a bit mask of ui::EventFlags.
+   virtual void ActivatedAt(size_t index, int event_flags);
+ 
++  // Called when the user moves the mouse outside the menu and over the owning
++  // window.
++  virtual void MouseOutsideMenu(const gfx::Point& screen_point) {}
++
++  // Called on unhandled open/close submenu keyboard commands. |is_rtl| will be
++  // true if the menu is displaying a right-to-left language.
++  virtual void UnhandledOpenSubmenu(bool is_rtl) {}
++  virtual void UnhandledCloseSubmenu(bool is_rtl) {}
++
++  // Override the text/background color of a given menu item dependent on the
++  // |index| and its |is_hovered| state. |is_minor| will be true for accelerator
++  // text. Returns true if it chooses to override the color.
++  virtual bool GetTextColor(size_t index,
++                            bool is_minor,
++                            bool is_hovered,
++                            SkColor* override_color) const { return false; }
++  virtual bool GetBackgroundColor(size_t index,
++                                  bool is_hovered,
++                                  SkColor* override_color) const
++                                  { return false; }
++
+   // Called when the menu is about to be shown.
+   virtual void MenuWillShow() {}
+ 
+diff --git ui/gfx/render_text.cc ui/gfx/render_text.cc
+index dab8c9be8d902..5951ec36a874e 100644
+--- ui/gfx/render_text.cc
++++ ui/gfx/render_text.cc
+@@ -670,6 +670,14 @@ void RenderText::SetWhitespaceElision(absl::optional<bool> whitespace_elision) {
+   }
+ }
+ 
++void RenderText::SetDrawStringsFlags(int flags) {
++  if (draw_strings_flags_ == flags)
++    return;
++  draw_strings_flags_ = flags;
++  cached_bounds_and_offset_valid_ = false;
++  OnTextAttributeChanged();
++}
++
+ void RenderText::SetDisplayRect(const Rect& r) {
+   if (r != display_rect_) {
+     display_rect_ = r;
+@@ -2061,6 +2069,19 @@ void RenderText::OnTextAttributeChanged() {
+ 
+   layout_text_up_to_date_ = false;
+ 
++  if (draw_strings_flags_ != 0) {
++    // Compute layout size with the mnemonic character underlined since it might
++    // be larger than with the underline hidden.
++    int char_pos = -1;
++    int char_span = 0;
++    layout_text_ =
++        gfx::LocateAndRemoveAcceleratorChar(layout_text_, &char_pos, &char_span);
++    if (char_pos != -1) {
++      gfx::Range range(char_pos, char_pos + char_span);
++      styles_[TEXT_STYLE_UNDERLINE].ApplyValue(true, range);
++    }
++  }
++
+   OnLayoutTextAttributeChanged(true);
+ }
+ 
+diff --git ui/gfx/render_text.h ui/gfx/render_text.h
+index 212c98c242ed3..26f9bb4c28400 100644
+--- ui/gfx/render_text.h
++++ ui/gfx/render_text.h
+@@ -347,6 +347,10 @@ class GFX_EXPORT RenderText {
+     return whitespace_elision_;
+   }
+ 
++  // Get or set the flags that control display of accelerator characters.
++  void SetDrawStringsFlags(int flags);
++  int draw_strings_flags() const { return draw_strings_flags_; }
++
+   const Rect& display_rect() const { return display_rect_; }
+   void SetDisplayRect(const Rect& r);
+ 
+@@ -1056,6 +1060,8 @@ class GFX_EXPORT RenderText {
+ 
+   // Tell whether or not the |layout_text_| needs an update or is up to date.
+   mutable bool layout_text_up_to_date_ = false;
++
++  int draw_strings_flags_ = 0;
+ };
+ 
+ }  // namespace gfx
+diff --git ui/views/animation/ink_drop_host.h ui/views/animation/ink_drop_host.h
+index c1c0631071a11..aa2c01ebce43e 100644
+--- ui/views/animation/ink_drop_host.h
++++ ui/views/animation/ink_drop_host.h
+@@ -194,6 +194,8 @@ class VIEWS_EXPORT InkDropHost {
+   View* host_view() { return host_view_; }
+   const View* host_view() const { return host_view_; }
+ 
++  InkDropMode ink_drop_mode() const { return ink_drop_mode_; }
++
+  private:
+   friend class test::InkDropHostTestApi;
+ 
+diff --git ui/views/controls/button/label_button.cc ui/views/controls/button/label_button.cc
+index c7b00c3852d02..be30a1995d570 100644
+--- ui/views/controls/button/label_button.cc
++++ ui/views/controls/button/label_button.cc
+@@ -566,6 +566,12 @@ void LabelButton::OnThemeChanged() {
+   SchedulePaint();
+ }
+ 
++void LabelButton::SetFontList(const gfx::FontList& font_list) {
++  cached_normal_font_list_ = font_list;
++  cached_default_button_font_list_ = font_list;
++  label_->SetFontList(cached_normal_font_list_);
++}
++
+ void LabelButton::StateChanged(ButtonState old_state) {
+   Button::StateChanged(old_state);
+   ResetLabelEnabledColor();
+diff --git ui/views/controls/button/label_button.h ui/views/controls/button/label_button.h
+index 8dbd918f09528..06fad642642c4 100644
+--- ui/views/controls/button/label_button.h
++++ ui/views/controls/button/label_button.h
+@@ -155,6 +155,9 @@ class VIEWS_EXPORT LabelButton : public Button, public NativeThemeDelegate {
+   ui::NativeTheme::State GetForegroundThemeState(
+       ui::NativeTheme::ExtraParams* params) const override;
+ 
++  // Sets the font list used by this button.
++  void SetFontList(const gfx::FontList& font_list);
++
+  protected:
+   ImageView* image() const { return image_; }
+   Label* label() const { return label_; }
+diff --git ui/views/controls/label.cc ui/views/controls/label.cc
+index a1a17ca0f4090..ad4ac7a2678e0 100644
+--- ui/views/controls/label.cc
++++ ui/views/controls/label.cc
+@@ -53,12 +53,29 @@ enum LabelPropertyKey {
+   kLabelLineHeight,
+   kLabelObscured,
+   kLabelAllowCharacterBreak,
++  kLabelDrawStringsFlags,
+ };
+ 
+ bool IsOpaque(SkColor color) {
+   return SkColorGetA(color) == SK_AlphaOPAQUE;
+ }
+ 
++// Strips accelerator character prefixes in |text| if needed, based on |flags|.
++// Returns a range in |text| to underline or Range::InvalidRange() if
++// underlining is not needed.
++gfx::Range StripAcceleratorChars(int flags, std::u16string* text) {
++  if (flags & (gfx::Canvas::SHOW_PREFIX | gfx::Canvas::HIDE_PREFIX)) {
++    int char_pos = -1;
++    int char_span = 0;
++    *text = gfx::LocateAndRemoveAcceleratorChar(*text, &char_pos, &char_span);
++    if ((flags & gfx::Canvas::SHOW_PREFIX) && char_pos != -1) {
++      return gfx::Range(static_cast<size_t>(char_pos),
++                        static_cast<size_t>(char_pos + char_span));
++    }
++  }
++  return gfx::Range::InvalidRange();
++}
++
+ }  // namespace
+ 
+ namespace views {
+@@ -474,6 +491,15 @@ void Label::SetElideBehavior(gfx::ElideBehavior elide_behavior) {
+   OnPropertyChanged(&elide_behavior_, kPropertyEffectsPreferredSizeChanged);
+ }
+ 
++void Label::SetDrawStringsFlags(int flags) {
++  if (draw_strings_flags_ == flags)
++    return;
++  draw_strings_flags_ = flags;
++  full_text_->SetDrawStringsFlags(draw_strings_flags_);
++  OnPropertyChanged(&full_text_ + kLabelDrawStringsFlags,
++                    kPropertyEffectsPreferredSizeChanged);
++}
++
+ std::u16string Label::GetTooltipText() const {
+   return tooltip_text_;
+ }
+@@ -778,6 +804,16 @@ std::unique_ptr<gfx::RenderText> Label::CreateRenderText() const {
+       render_text->SelectRange(stored_selection_range_);
+   }
+ 
++  if (draw_strings_flags_ != 0) {
++    auto text_str = GetText();
++    gfx::Range range = StripAcceleratorChars(draw_strings_flags_, &text_str);
++    render_text->SetText(text_str);
++    if (range.IsValid()) {
++      render_text->SetDisplayRect(bounds());
++      render_text->ApplyStyle(gfx::TEXT_STYLE_UNDERLINE, true, range);
++    }
++  }
++
+   return render_text;
+ }
+ 
+diff --git ui/views/controls/label.h ui/views/controls/label.h
+index 711dc633bffc2..0fa2626150de2 100644
+--- ui/views/controls/label.h
++++ ui/views/controls/label.h
+@@ -240,6 +240,10 @@ class VIEWS_EXPORT Label : public View,
+   gfx::ElideBehavior GetElideBehavior() const;
+   void SetElideBehavior(gfx::ElideBehavior elide_behavior);
+ 
++  // Get or set the flags that control display of accelerator characters.
++  void SetDrawStringsFlags(int flags);
++  int GetDrawStringsFlags() const { return draw_strings_flags_; }
++
+   // Gets/Sets the tooltip text.  Default behavior for a label (single-line) is
+   // to show the full text if it is wider than its bounds.  Calling this
+   // overrides the default behavior and lets you set a custom tooltip.  To
+@@ -504,6 +508,7 @@ class VIEWS_EXPORT Label : public View,
+   int max_width_ = 0;
+   // This is used in single-line mode.
+   int max_width_single_line_ = 0;
++  int draw_strings_flags_ = 0;
+ 
+   std::unique_ptr<SelectionController> selection_controller_;
+ 
+diff --git ui/views/controls/menu/menu_controller.cc ui/views/controls/menu/menu_controller.cc
+index b02f25526d9cb..2961ef6ba1185 100644
+--- ui/views/controls/menu/menu_controller.cc
++++ ui/views/controls/menu/menu_controller.cc
+@@ -565,7 +565,8 @@ void MenuController::Run(Widget* parent,
+                          MenuAnchorPosition position,
+                          bool context_menu,
+                          bool is_nested_drag,
+-                         gfx::NativeView native_view_for_gestures) {
++                         gfx::NativeView native_view_for_gestures,
++                         gfx::AcceleratedWidget parent_widget) {
+   exit_type_ = ExitType::kNone;
+   possible_drag_ = false;
+   drag_in_progress_ = false;
+@@ -610,6 +611,7 @@ void MenuController::Run(Widget* parent,
+       owner_->AddObserver(this);
+ 
+     native_view_for_gestures_ = native_view_for_gestures;
++    parent_widget_ = parent_widget;
+ 
+     // Only create a MenuPreTargetHandler for non-nested menus. Nested menus
+     // will use the existing one.
+@@ -2230,6 +2232,7 @@ void MenuController::OpenMenuImpl(MenuItemView* item, bool show) {
+     params.do_capture = do_capture;
+     params.native_view_for_gestures = native_view_for_gestures_;
+     params.owned_window_anchor = anchor;
++    params.parent_widget = parent_widget_;
+     if (item->GetParentMenuItem()) {
+       params.context = item->GetWidget();
+       // (crbug.com/1414232) The item to be open is a submenu. Make sure
+@@ -2915,8 +2918,13 @@ MenuItemView* MenuController::FindInitialSelectableMenuItem(
+ 
+ void MenuController::OpenSubmenuChangeSelectionIfCan() {
+   MenuItemView* item = pending_state_.item;
+-  if (!item->HasSubmenu() || !item->GetEnabled())
++  if (!item->HasSubmenu() || !item->GetEnabled() || !item->GetParentMenuItem()) {
++    MenuItemView* submenu_item =
++        item->GetParentMenuItem() ? item->GetParentMenuItem() : item;
++    submenu_item->GetDelegate()->OnUnhandledOpenSubmenu(submenu_item,
++                                                        base::i18n::IsRTL());
+     return;
++  }
+ 
+   // Show the sub-menu.
+   SetSelection(item, SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY);
+@@ -2936,8 +2944,10 @@ void MenuController::OpenSubmenuChangeSelectionIfCan() {
+ void MenuController::CloseSubmenu() {
+   MenuItemView* item = state_.item;
+   DCHECK(item);
+-  if (!item->GetParentMenuItem())
++  if (!item->GetParentMenuItem()) {
++    item->GetDelegate()->OnUnhandledCloseSubmenu(item, base::i18n::IsRTL());
+     return;
++  }
+   if (item->SubmenuIsShowing())
+     SetSelection(item, SELECTION_UPDATE_IMMEDIATELY);
+   else if (item->GetParentMenuItem()->GetParentMenuItem())
+diff --git ui/views/controls/menu/menu_controller.h ui/views/controls/menu/menu_controller.h
+index 97c1f62da483b..2c8a52f562147 100644
+--- ui/views/controls/menu/menu_controller.h
++++ ui/views/controls/menu/menu_controller.h
+@@ -138,7 +138,9 @@ class VIEWS_EXPORT MenuController
+            MenuAnchorPosition position,
+            bool context_menu,
+            bool is_nested_drag,
+-           gfx::NativeView native_view_for_gestures = gfx::NativeView());
++           gfx::NativeView native_view_for_gestures = gfx::NativeView(),
++           gfx::AcceleratedWidget parent_widget =
++               gfx::kNullAcceleratedWidget);
+ 
+   bool for_drop() const { return for_drop_; }
+ 
+@@ -722,6 +724,8 @@ class VIEWS_EXPORT MenuController
+   // RunType::SEND_GESTURE_EVENTS_TO_OWNER is set.
+   gfx::NativeView native_view_for_gestures_ = gfx::NativeView();
+ 
++  gfx::AcceleratedWidget parent_widget_ = gfx::kNullAcceleratedWidget;
++
+   // Indicates a possible drag operation.
+   bool possible_drag_ = false;
+ 
+diff --git ui/views/controls/menu/menu_delegate.h ui/views/controls/menu/menu_delegate.h
+index b8fa1c116ebcd..015f15ed72385 100644
+--- ui/views/controls/menu/menu_delegate.h
++++ ui/views/controls/menu/menu_delegate.h
+@@ -73,6 +73,22 @@ class VIEWS_EXPORT MenuDelegate {
+   virtual const gfx::FontList* GetLabelFontList(int id) const;
+   virtual absl::optional<SkColor> GetLabelColor(int id) const;
+ 
++  // Override the text color of a given menu item dependent on the |command_id|
++  // and its |is_hovered| state. |is_minor| will be true for accelerator text.
++  // Returns true if it chooses to override the color.
++  virtual bool GetTextColor(int command_id,
++                            bool is_minor,
++                            bool is_hovered,
++                            SkColor* override_color) const { return false; }
++
++  // Override the background color of a given menu item dependent on the
++  // |command_id| and its |is_hovered| state. Returns true if it chooses to
++  // override the color.
++  virtual bool GetBackgroundColor(int command_id,
++                                  bool is_hovered,
++                                  SkColor* override_color) const
++                                  { return false; }
++
+   // The tooltip shown for the menu item. This is invoked when the user
+   // hovers over the item, and no tooltip text has been set for that item.
+   virtual std::u16string GetTooltipText(int id,
+@@ -201,6 +217,11 @@ class VIEWS_EXPORT MenuDelegate {
+                                        bool* has_mnemonics,
+                                        MenuButton** button);
+ 
++  // Called on unhandled open/close submenu keyboard commands. |is_rtl| will be
++  // true if the menu is displaying a right-to-left language.
++  virtual void OnUnhandledOpenSubmenu(MenuItemView* menu, bool is_rtl) {}
++  virtual void OnUnhandledCloseSubmenu(MenuItemView* menu, bool is_rtl) {}
++
+   // Returns the max width menus can grow to be.
+   virtual int GetMaxWidthForMenu(MenuItemView* menu);
+ 
+diff --git ui/views/controls/menu/menu_host.cc ui/views/controls/menu/menu_host.cc
+index 2da9d8fb49d8d..9f344ff8180f1 100644
+--- ui/views/controls/menu/menu_host.cc
++++ ui/views/controls/menu/menu_host.cc
+@@ -141,6 +141,8 @@ void MenuHost::InitMenuHost(const InitParams& init_params) {
+                                        : gfx::NativeWindow();
+   params.bounds = init_params.bounds;
+ 
++  params.parent_widget = init_params.parent_widget;
++
+ #if defined(USE_AURA)
+   // TODO(msisov): remove kMenutype once positioning of anchored windows
+   // finally migrates to a new path.
+@@ -152,7 +154,8 @@ void MenuHost::InitMenuHost(const InitParams& init_params) {
+   // If MenuHost has no parent widget, it needs to be marked
+   // Activatable, so that calling Show in ShowMenuHost will
+   // get keyboard focus.
+-  if (init_params.parent == nullptr)
++  if (init_params.parent == nullptr &&
++      init_params.parent_widget == gfx::kNullAcceleratedWidget)
+     params.activatable = Widget::InitParams::Activatable::kYes;
+ 
+ #if BUILDFLAG(IS_WIN)
+diff --git ui/views/controls/menu/menu_host.h ui/views/controls/menu/menu_host.h
+index 10c4ecd08f76b..062f0c58bb805 100644
+--- ui/views/controls/menu/menu_host.h
++++ ui/views/controls/menu/menu_host.h
+@@ -53,6 +53,8 @@ class MenuHost : public Widget, public WidgetObserver {
+     // Additional information that helps to position anchored windows in such
+     // backends as Wayland.
+     ui::OwnedWindowAnchor owned_window_anchor;
++
++    gfx::AcceleratedWidget parent_widget = gfx::kNullAcceleratedWidget;
+   };
+ 
+   explicit MenuHost(SubmenuView* submenu);
+diff --git ui/views/controls/menu/menu_item_view.cc ui/views/controls/menu/menu_item_view.cc
+index bbb50ca16f67e..9217236ef056b 100644
+--- ui/views/controls/menu/menu_item_view.cc
++++ ui/views/controls/menu/menu_item_view.cc
+@@ -1057,6 +1057,15 @@ void MenuItemView::PaintBackground(gfx::Canvas* canvas,
+     spilling_rect.set_y(spilling_rect.y() - corner_radius_);
+     spilling_rect.set_height(spilling_rect.height() + corner_radius_);
+     canvas->DrawRoundRect(spilling_rect, corner_radius_, flags);
++    return;
++  }
++
++  MenuDelegate *delegate = GetDelegate();
++  SkColor override_color;
++  if (delegate && delegate->GetBackgroundColor(GetCommand(),
++                                               paint_as_selected,
++                                               &override_color)) {
++    canvas->DrawColor(override_color);
+   } else if (paint_as_selected) {
+     gfx::Rect item_bounds = GetLocalBounds();
+     if (type_ == Type::kActionableSubMenu) {
+@@ -1121,6 +1130,13 @@ void MenuItemView::PaintMinorIconAndText(gfx::Canvas* canvas, SkColor color) {
+ }
+ 
+ SkColor MenuItemView::GetTextColor(bool minor, bool paint_as_selected) const {
++  SkColor text_color;
++  const MenuDelegate *delegate = GetDelegate();
++  if (delegate && delegate->GetTextColor(GetCommand(), minor, paint_as_selected,
++                                         &text_color)) {
++    return text_color;
++  }
++
+   // Use a custom color if provided by the controller. If the item is selected,
+   // use the default color.
+   if (!paint_as_selected && foreground_color_id_.has_value()) {
+diff --git ui/views/controls/menu/menu_model_adapter.cc ui/views/controls/menu/menu_model_adapter.cc
+index 887f471c4db69..5d097994cbf72 100644
+--- ui/views/controls/menu/menu_model_adapter.cc
++++ ui/views/controls/menu/menu_model_adapter.cc
+@@ -4,6 +4,7 @@
+ 
+ #include "ui/views/controls/menu/menu_model_adapter.h"
+ 
++#include <limits>
+ #include <list>
+ #include <memory>
+ #include <utility>
+@@ -225,6 +226,76 @@ bool MenuModelAdapter::IsItemChecked(int id) const {
+   return model->IsItemCheckedAt(index);
+ }
+ 
++MenuItemView* MenuModelAdapter::GetSiblingMenu(MenuItemView* menu,
++                                               const gfx::Point& screen_point,
++                                               MenuAnchorPosition* anchor,
++                                               bool* has_mnemonics,
++                                               MenuButton** button) {
++  // Look up the menu model for this menu.
++  const std::map<MenuItemView*, ui::MenuModel*>::const_iterator map_iterator =
++      menu_map_.find(menu);
++  if (map_iterator != menu_map_.end()) {
++    map_iterator->second->MouseOutsideMenu(screen_point);
++    return nullptr;
++  }
++
++  NOTREACHED();
++  return nullptr;
++}
++
++void MenuModelAdapter::OnUnhandledOpenSubmenu(MenuItemView* menu,
++                                              bool is_rtl) {
++  // Look up the menu model for this menu.
++  const std::map<MenuItemView*, ui::MenuModel*>::const_iterator map_iterator =
++      menu_map_.find(menu);
++  if (map_iterator != menu_map_.end()) {
++    map_iterator->second->UnhandledOpenSubmenu(is_rtl);
++    return;
++  }
++
++  NOTREACHED();
++}
++
++void MenuModelAdapter::OnUnhandledCloseSubmenu(MenuItemView* menu,
++                                               bool is_rtl) {
++  // Look up the menu model for this menu.
++  const std::map<MenuItemView*, ui::MenuModel*>::const_iterator map_iterator =
++      menu_map_.find(menu);
++  if (map_iterator != menu_map_.end()) {
++    map_iterator->second->UnhandledCloseSubmenu(is_rtl);
++    return;
++  }
++
++  NOTREACHED();
++}
++
++bool MenuModelAdapter::GetTextColor(int command_id,
++                                    bool is_minor,
++                                    bool is_hovered,
++                                    SkColor* override_color) const {
++  ui::MenuModel* model = menu_model_;
++  size_t index = 0;
++  if (ui::MenuModel::GetModelAndIndexForCommandId(command_id, &model, &index))
++    return model->GetTextColor(index, is_minor, is_hovered, override_color);
++
++  // Return the default color.
++  return menu_model_->GetBackgroundColor(std::numeric_limits<size_t>::max(),
++                                         is_hovered, override_color);
++}
++
++bool MenuModelAdapter::GetBackgroundColor(int command_id,
++                                          bool is_hovered,
++                                          SkColor* override_color) const {
++  ui::MenuModel* model = menu_model_;
++  size_t index = 0;
++  if (ui::MenuModel::GetModelAndIndexForCommandId(command_id, &model, &index))
++    return model->GetBackgroundColor(index, is_hovered, override_color);
++
++  // Return the default color.
++  return menu_model_->GetBackgroundColor(std::numeric_limits<size_t>::max(),
++                                         is_hovered, override_color);
++}
++
+ void MenuModelAdapter::WillShowMenu(MenuItemView* menu) {
+   // Look up the menu model for this menu.
+   const std::map<MenuItemView*, ui::MenuModel*>::const_iterator map_iterator =
+diff --git ui/views/controls/menu/menu_model_adapter.h ui/views/controls/menu/menu_model_adapter.h
+index a8354c0699920..9b5deb522c29a 100644
+--- ui/views/controls/menu/menu_model_adapter.h
++++ ui/views/controls/menu/menu_model_adapter.h
+@@ -89,6 +89,20 @@ class VIEWS_EXPORT MenuModelAdapter : public MenuDelegate,
+   bool IsCommandEnabled(int id) const override;
+   bool IsCommandVisible(int id) const override;
+   bool IsItemChecked(int id) const override;
++  MenuItemView* GetSiblingMenu(MenuItemView* menu,
++                               const gfx::Point& screen_point,
++                               MenuAnchorPosition* anchor,
++                               bool* has_mnemonics,
++                               MenuButton** button) override;
++  void OnUnhandledOpenSubmenu(MenuItemView* menu, bool is_rtl) override;
++  void OnUnhandledCloseSubmenu(MenuItemView* menu, bool is_rtl) override;
++  bool GetTextColor(int command_id,
++                    bool is_minor,
++                    bool is_hovered,
++                    SkColor* override_color) const override;
++  bool GetBackgroundColor(int command_id,
++                          bool is_hovered,
++                          SkColor* override_color) const override;
+   void WillShowMenu(MenuItemView* menu) override;
+   void WillHideMenu(MenuItemView* menu) override;
+   void OnMenuClosed(MenuItemView* menu) override;
+diff --git ui/views/controls/menu/menu_runner.cc ui/views/controls/menu/menu_runner.cc
+index adb22671b94fa..59cc421e82e1b 100644
+--- ui/views/controls/menu/menu_runner.cc
++++ ui/views/controls/menu/menu_runner.cc
+@@ -36,6 +36,7 @@ void MenuRunner::RunMenuAt(Widget* parent,
+                            MenuAnchorPosition anchor,
+                            ui::MenuSourceType source_type,
+                            gfx::NativeView native_view_for_gestures,
++                           gfx::AcceleratedWidget parent_widget,
+                            absl::optional<gfx::RoundedCornersF> corners) {
+   // Do not attempt to show the menu if the application is currently shutting
+   // down. MenuDelegate::OnMenuClosed would not be called.
+@@ -82,7 +83,7 @@ void MenuRunner::RunMenuAt(Widget* parent,
+   }
+ 
+   impl_->RunMenuAt(parent, button_controller, bounds, anchor, run_types_,
+-                   native_view_for_gestures, corners);
++                   native_view_for_gestures, parent_widget, corners);
+ }
+ 
+ bool MenuRunner::IsRunning() const {
+diff --git ui/views/controls/menu/menu_runner.h ui/views/controls/menu/menu_runner.h
+index 562b67396f27f..7679dbd79e565 100644
+--- ui/views/controls/menu/menu_runner.h
++++ ui/views/controls/menu/menu_runner.h
+@@ -152,6 +152,8 @@ class VIEWS_EXPORT MenuRunner {
+                  MenuAnchorPosition anchor,
+                  ui::MenuSourceType source_type,
+                  gfx::NativeView native_view_for_gestures = gfx::NativeView(),
++                 gfx::AcceleratedWidget parent_widget =
++                     gfx::kNullAcceleratedWidget,
+                  absl::optional<gfx::RoundedCornersF> corners = absl::nullopt);
+ 
+   // Returns true if we're in a nested run loop running the menu.
+diff --git ui/views/controls/menu/menu_runner_impl.cc ui/views/controls/menu/menu_runner_impl.cc
+index e82249ad5e887..3a7429bcaf9f1 100644
+--- ui/views/controls/menu/menu_runner_impl.cc
++++ ui/views/controls/menu/menu_runner_impl.cc
+@@ -117,6 +117,7 @@ void MenuRunnerImpl::RunMenuAt(Widget* parent,
+                                MenuAnchorPosition anchor,
+                                int32_t run_types,
+                                gfx::NativeView native_view_for_gestures,
++                               gfx::AcceleratedWidget parent_widget,
+                                absl::optional<gfx::RoundedCornersF> corners) {
+   closing_event_time_ = base::TimeTicks();
+   if (running_) {
+@@ -184,7 +185,7 @@ void MenuRunnerImpl::RunMenuAt(Widget* parent,
+   controller->Run(parent, button_controller, menu_, bounds, anchor,
+                   (run_types & MenuRunner::CONTEXT_MENU) != 0,
+                   (run_types & MenuRunner::NESTED_DRAG) != 0,
+-                  native_view_for_gestures);
++                  native_view_for_gestures, parent_widget);
+ }
+ 
+ void MenuRunnerImpl::Cancel() {
+diff --git ui/views/controls/menu/menu_runner_impl.h ui/views/controls/menu/menu_runner_impl.h
+index 4d2909b5094ab..245e1a24dd810 100644
+--- ui/views/controls/menu/menu_runner_impl.h
++++ ui/views/controls/menu/menu_runner_impl.h
+@@ -53,6 +53,7 @@ class VIEWS_EXPORT MenuRunnerImpl : public MenuRunnerImplInterface,
+       MenuAnchorPosition anchor,
+       int32_t run_types,
+       gfx::NativeView native_view_for_gestures,
++      gfx::AcceleratedWidget parent_widget,
+       absl::optional<gfx::RoundedCornersF> corners = absl::nullopt) override;
+   void Cancel() override;
+   base::TimeTicks GetClosingEventTime() const override;
+diff --git ui/views/controls/menu/menu_runner_impl_adapter.cc ui/views/controls/menu/menu_runner_impl_adapter.cc
+index b6c680063889b..a1efa677a43a5 100644
+--- ui/views/controls/menu/menu_runner_impl_adapter.cc
++++ ui/views/controls/menu/menu_runner_impl_adapter.cc
+@@ -34,9 +34,10 @@ void MenuRunnerImplAdapter::RunMenuAt(
+     MenuAnchorPosition anchor,
+     int32_t types,
+     gfx::NativeView native_view_for_gestures,
++    gfx::AcceleratedWidget parent_widget,
+     absl::optional<gfx::RoundedCornersF> corners) {
+   impl_->RunMenuAt(parent, button_controller, bounds, anchor, types,
+-                   native_view_for_gestures);
++                   native_view_for_gestures, parent_widget);
+ }
+ 
+ void MenuRunnerImplAdapter::Cancel() {
+diff --git ui/views/controls/menu/menu_runner_impl_adapter.h ui/views/controls/menu/menu_runner_impl_adapter.h
+index e6587d2208a13..c2c72f7edb89c 100644
+--- ui/views/controls/menu/menu_runner_impl_adapter.h
++++ ui/views/controls/menu/menu_runner_impl_adapter.h
+@@ -44,6 +44,7 @@ class VIEWS_EXPORT MenuRunnerImplAdapter : public MenuRunnerImplInterface {
+       MenuAnchorPosition anchor,
+       int32_t types,
+       gfx::NativeView native_view_for_gestures,
++      gfx::AcceleratedWidget parent_widget,
+       absl::optional<gfx::RoundedCornersF> corners = absl::nullopt) override;
+   void Cancel() override;
+   base::TimeTicks GetClosingEventTime() const override;
+diff --git ui/views/controls/menu/menu_runner_impl_cocoa.h ui/views/controls/menu/menu_runner_impl_cocoa.h
+index 2325534ec9243..7573a54cc891c 100644
+--- ui/views/controls/menu/menu_runner_impl_cocoa.h
++++ ui/views/controls/menu/menu_runner_impl_cocoa.h
+@@ -42,6 +42,7 @@ class VIEWS_EXPORT MenuRunnerImplCocoa : public MenuRunnerImplInterface {
+       MenuAnchorPosition anchor,
+       int32_t run_types,
+       gfx::NativeView native_view_for_gestures,
++      gfx::AcceleratedWidget parent_widget,
+       absl::optional<gfx::RoundedCornersF> corners = absl::nullopt) override;
+   void Cancel() override;
+   base::TimeTicks GetClosingEventTime() const override;
+diff --git ui/views/controls/menu/menu_runner_impl_cocoa.mm ui/views/controls/menu/menu_runner_impl_cocoa.mm
+index c3c80f6becee7..5b6fc116f6255 100644
+--- ui/views/controls/menu/menu_runner_impl_cocoa.mm
++++ ui/views/controls/menu/menu_runner_impl_cocoa.mm
+@@ -190,6 +190,7 @@ void MenuRunnerImplCocoa::RunMenuAt(
+     MenuAnchorPosition anchor,
+     int32_t run_types,
+     gfx::NativeView native_view_for_gestures,
++    gfx::AcceleratedWidget /*parent_widget*/,
+     absl::optional<gfx::RoundedCornersF> corners) {
+   DCHECK(!IsRunning());
+   DCHECK(parent);
+diff --git ui/views/controls/menu/menu_runner_impl_interface.h ui/views/controls/menu/menu_runner_impl_interface.h
+index cf696fbcf0714..5c48fd7410b88 100644
+--- ui/views/controls/menu/menu_runner_impl_interface.h
++++ ui/views/controls/menu/menu_runner_impl_interface.h
+@@ -46,6 +46,8 @@ class MenuRunnerImplInterface {
+       MenuAnchorPosition anchor,
+       int32_t run_types,
+       gfx::NativeView native_view_for_gestures,
++      gfx::AcceleratedWidget parent_widget =
++          gfx::kNullAcceleratedWidget,
+       absl::optional<gfx::RoundedCornersF> corners = absl::nullopt) = 0;
+ 
+   // Hides and cancels the menu.
+diff --git ui/views/controls/menu/menu_scroll_view_container.cc ui/views/controls/menu/menu_scroll_view_container.cc
+index 8c093e002326c..3a500adcd39bb 100644
+--- ui/views/controls/menu/menu_scroll_view_container.cc
++++ ui/views/controls/menu/menu_scroll_view_container.cc
+@@ -250,6 +250,11 @@ MenuScrollViewContainer::MenuScrollViewContainer(SubmenuView* content_view)
+   scroll_down_button_ = background_view_->AddChildView(
+       std::make_unique<MenuScrollButton>(content_view, false));
+ 
++  SkColor override_color;
++  MenuDelegate* delegate = content_view_->GetMenuItem()->GetDelegate();
++  if (delegate && delegate->GetBackgroundColor(-1, false, &override_color))
++    SetBackground(views::CreateSolidBackground(override_color));
++
+   arrow_ = BubbleBorderTypeFromAnchor(
+       content_view_->GetMenuItem()->GetMenuController()->GetAnchorPosition());
+ 
+diff --git ui/views/test/ui_controls_factory_desktop_aura_ozone.cc ui/views/test/ui_controls_factory_desktop_aura_ozone.cc
+index 187e55af5d7be..3a980d26fdaae 100644
+--- ui/views/test/ui_controls_factory_desktop_aura_ozone.cc
++++ ui/views/test/ui_controls_factory_desktop_aura_ozone.cc
+@@ -15,6 +15,7 @@
+ #include "base/task/single_thread_task_runner.h"
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/features.h"
+ #include "ui/aura/client/screen_position_client.h"
+ #include "ui/aura/env.h"
+ #include "ui/aura/test/aura_test_utils.h"
+@@ -176,9 +177,11 @@ bool SendMouseMoveNotifyWhenDone(int screen_x,
+       aura::test::QueryLatestMousePositionRequestInHost(host);
+   host->ConvertPixelsToDIP(&root_current_location);
+ 
++#if !BUILDFLAG(ENABLE_CEF)
+   auto* screen = views::test::TestDesktopScreenOzone::GetInstance();
+   DCHECK_EQ(screen, display::Screen::GetScreen());
+   screen->set_cursor_screen_point(gfx::Point(screen_x, screen_y));
++#endif
+ 
+ #if !BUILDFLAG(IS_CHROMEOS_LACROS)
+   if (root_location != root_current_location &&
+diff --git ui/views/view.h ui/views/view.h
+index 80a2b76b266f5..17b85ef182b55 100644
+--- ui/views/view.h
++++ ui/views/view.h
+@@ -21,6 +21,7 @@
+ #include "base/memory/raw_ptr.h"
+ #include "base/observer_list.h"
+ #include "base/strings/string_piece.h"
++#include "base/supports_user_data.h"
+ #include "build/build_config.h"
+ #include "third_party/abseil-cpp/absl/types/optional.h"
+ #include "third_party/skia/include/core/SkPath.h"
+@@ -283,7 +284,8 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
+                           public ui::EventTarget,
+                           public ui::EventHandler,
+                           public ui::PropertyHandler,
+-                          public ui::metadata::MetaDataProvider {
++                          public ui::metadata::MetaDataProvider,
++                          public base::SupportsUserData {
+  public:
+   using Views = std::vector<View*>;
+ 
diff --git a/src/patch/patches/views_widget.patch b/src/patch/patches/views_widget.patch
new file mode 100644
index 0000000..79d8a99
--- /dev/null
+++ b/src/patch/patches/views_widget.patch
@@ -0,0 +1,502 @@
+diff --git content/browser/renderer_host/render_widget_host_view_base.cc content/browser/renderer_host/render_widget_host_view_base.cc
+index 1634c3556dc78..276a9f58e2bac 100644
+--- content/browser/renderer_host/render_widget_host_view_base.cc
++++ content/browser/renderer_host/render_widget_host_view_base.cc
+@@ -648,6 +648,14 @@ float RenderWidgetHostViewBase::GetScaleOverrideForCapture() const {
+   return scale_override_for_capture_;
+ }
+ 
++void RenderWidgetHostViewBase::SetHasExternalParent(bool val) {
++  has_external_parent_ = val;
++}
++
++bool RenderWidgetHostViewBase::HasExternalParent() const {
++  return has_external_parent_;
++}
++
+ void RenderWidgetHostViewBase::OnAutoscrollStart() {
+   if (!GetMouseWheelPhaseHandler())
+     return;
+diff --git content/browser/renderer_host/render_widget_host_view_base.h content/browser/renderer_host/render_widget_host_view_base.h
+index b010d43aaeb90..5172abec682b9 100644
+--- content/browser/renderer_host/render_widget_host_view_base.h
++++ content/browser/renderer_host/render_widget_host_view_base.h
+@@ -71,6 +71,7 @@ class CursorManager;
+ class MouseWheelPhaseHandler;
+ class RenderWidgetHostImpl;
+ class RenderWidgetHostViewBaseObserver;
++class RenderWidgetHostViewGuest;
+ class SyntheticGestureTarget;
+ class TextInputManager;
+ class TouchSelectionControllerClientManager;
+@@ -150,6 +151,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView {
+                         const gfx::Size& max_size) override;
+   void DisableAutoResize(const gfx::Size& new_size) override;
+   float GetDeviceScaleFactor() const final;
++  void SetHasExternalParent(bool val) override;
++  bool HasExternalParent() const override;
+   TouchSelectionControllerClientManager*
+   GetTouchSelectionControllerClientManager() override;
+   ui::mojom::VirtualKeyboardMode GetVirtualKeyboardMode() override;
+@@ -186,6 +189,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView {
+   // Called when screen information or native widget bounds change.
+   virtual void UpdateScreenInfo();
+ 
++  // Generates the most current set of ScreenInfos from the current set of
++  // displays in the system for use in UpdateScreenInfo.
++  virtual display::ScreenInfos GetNewScreenInfosForUpdate();
++
+   // Called by the TextInputManager to notify the view about being removed from
+   // the list of registered views, i.e., TextInputManager is no longer tracking
+   // TextInputState from this view. The RWHV should reset |text_input_manager_|
+@@ -450,6 +457,12 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView {
+                            const gfx::Rect& bounds,
+                            const gfx::Rect& anchor_rect) = 0;
+ 
++  // Perform all the initialization steps necessary for this object to represent
++  // the platform widget owned by |guest_view| and embedded in
++  // |parent_host_view|.
++  virtual void InitAsGuest(RenderWidgetHostView* parent_host_view,
++                           RenderWidgetHostViewGuest* guest_view) {}
++
+   // Sets the cursor for this view to the one specified.
+   virtual void UpdateCursor(const ui::Cursor& cursor) = 0;
+ 
+@@ -705,6 +718,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView {
+   // to all displays.
+   gfx::Size system_cursor_size_;
+ 
++  // True if the widget has a external parent view/window outside of the
++  // Chromium-controlled view/window hierarchy.
++  bool has_external_parent_ = false;
++
+  private:
+   FRIEND_TEST_ALL_PREFIXES(
+       BrowserSideFlingBrowserTest,
+@@ -726,10 +743,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView {
+ 
+   void SynchronizeVisualProperties();
+ 
+-  // Generates the most current set of ScreenInfos from the current set of
+-  // displays in the system for use in UpdateScreenInfo.
+-  display::ScreenInfos GetNewScreenInfosForUpdate();
+-
+   // Called when display properties that need to be synchronized with the
+   // renderer process changes. This method is called before notifying
+   // RenderWidgetHostImpl in order to allow the view to allocate a new
+diff --git content/browser/renderer_host/render_widget_host_view_event_handler.cc content/browser/renderer_host/render_widget_host_view_event_handler.cc
+index 401e65a8ebe6f..b83410da96f67 100644
+--- content/browser/renderer_host/render_widget_host_view_event_handler.cc
++++ content/browser/renderer_host/render_widget_host_view_event_handler.cc
+@@ -52,6 +52,10 @@ namespace {
+ // of the border area, in percentage of the corresponding dimension.
+ const int kMouseLockBorderPercentage = 15;
+ 
++#if BUILDFLAG(IS_LINUX)
++#include "ui/aura/window_tree_host.h"
++#endif
++
+ #if BUILDFLAG(IS_WIN)
+ // A callback function for EnumThreadWindows to enumerate and dismiss
+ // any owned popup windows.
+@@ -868,6 +872,14 @@ void RenderWidgetHostViewEventHandler::MoveCursorToCenter(
+     }
+     return;
+   }
++#endif
++#if BUILDFLAG(IS_LINUX)
++  if (host_view_->HasExternalParent() &&
++      window_ && window_->delegate()->CanFocus()) {
++    aura::WindowTreeHost* host = window_->GetHost();
++    if (host)
++      host->Show();
++  }
+ #endif
+   synthetic_move_position_ = center_in_screen;
+ }
+@@ -897,6 +909,17 @@ bool RenderWidgetHostViewEventHandler::MatchesSynthesizedMovePosition(
+ }
+ 
+ void RenderWidgetHostViewEventHandler::SetKeyboardFocus() {
++#if BUILDFLAG(IS_WIN)
++  if (host_view_->HasExternalParent() &&
++      window_ && window_->delegate()->CanFocus()) {
++    aura::WindowTreeHost* host = window_->GetHost();
++    if (host) {
++      gfx::AcceleratedWidget hwnd = host->GetAcceleratedWidget();
++      if (!(::GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE))
++        ::SetFocus(hwnd);
++    }
++  }
++#endif
+   // TODO(wjmaclean): can host_ ever be null?
+   if (host_ && set_focus_on_mouse_down_or_key_event_) {
+     set_focus_on_mouse_down_or_key_event_ = false;
+diff --git content/public/browser/render_widget_host_view.h content/public/browser/render_widget_host_view.h
+index d7e649d5590ab..baff410b4e0c6 100644
+--- content/public/browser/render_widget_host_view.h
++++ content/public/browser/render_widget_host_view.h
+@@ -259,6 +259,14 @@ class CONTENT_EXPORT RenderWidgetHostView {
+   // This must always return the same device scale factor as GetScreenInfo.
+   virtual float GetDeviceScaleFactor() const = 0;
+ 
++  // Set whether the widget has a external parent view/window outside of the
++  // Chromium-controlled view/window hierarchy.
++  virtual void SetHasExternalParent(bool val) = 0;
++
++  // Returns true if the widget has a external parent view/window outside of the
++  // Chromium-controlled view/window hierarchy.
++  virtual bool HasExternalParent() const = 0;
++
+ #if BUILDFLAG(IS_MAC)
+   // Set the view's active state (i.e., tint state of controls).
+   virtual void SetActive(bool active) = 0;
+diff --git ui/ozone/platform/x11/x11_window.cc ui/ozone/platform/x11/x11_window.cc
+index 91d5863a7e241..5d804395a4cf0 100644
+--- ui/ozone/platform/x11/x11_window.cc
++++ ui/ozone/platform/x11/x11_window.cc
+@@ -1802,7 +1802,8 @@ void X11Window::CreateXWindow(const PlatformWindowInitProperties& properties) {
+   req.border_pixel = 0;
+ 
+   bounds_in_pixels_ = SanitizeBounds(bounds);
+-  req.parent = x_root_window_;
++  req.parent = properties.parent_widget == gfx::kNullAcceleratedWidget ?
++      x_root_window_ : static_cast<x11::Window>(properties.parent_widget);
+   req.x = bounds_in_pixels_.x();
+   req.y = bounds_in_pixels_.y();
+   req.width = bounds_in_pixels_.width();
+diff --git ui/views/widget/desktop_aura/desktop_screen_win.cc ui/views/widget/desktop_aura/desktop_screen_win.cc
+index e4e6d3104da9e..bb372b0cd2960 100644
+--- ui/views/widget/desktop_aura/desktop_screen_win.cc
++++ ui/views/widget/desktop_aura/desktop_screen_win.cc
+@@ -23,6 +23,8 @@ DesktopScreenWin::~DesktopScreenWin() {
+ }
+ 
+ HWND DesktopScreenWin::GetHWNDFromNativeWindow(gfx::NativeWindow window) const {
++  if (!window)
++    return nullptr;
+   aura::WindowTreeHost* host = window->GetHost();
+   return host ? host->GetAcceleratedWidget() : nullptr;
+ }
+diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
+index e5c4e4d662261..15ed8c1a24557 100644
+--- ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
++++ ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
+@@ -171,6 +171,18 @@ Widget::MoveLoopResult DesktopWindowTreeHostLinux::RunMoveLoop(
+   return result;
+ }
+ 
++gfx::Rect DesktopWindowTreeHostLinux::GetWindowBoundsInScreen() const {
++  if (!screen_bounds_.IsEmpty())
++    return screen_bounds_;
++  return DesktopWindowTreeHostPlatform::GetWindowBoundsInScreen();
++}
++
++gfx::Point DesktopWindowTreeHostLinux::GetLocationOnScreenInPixels() const {
++  if (!screen_bounds_.IsEmpty())
++    return screen_bounds_.origin();
++  return DesktopWindowTreeHostPlatform::GetLocationOnScreenInPixels();
++}
++
+ void DesktopWindowTreeHostLinux::DispatchEvent(ui::Event* event) {
+   // In Windows, the native events sent to chrome are separated into client
+   // and non-client versions of events, which we record on our LocatedEvent
+@@ -294,6 +306,8 @@ void DesktopWindowTreeHostLinux::AddAdditionalInitProperties(
+ 
+   properties->wayland_app_id = params.wayland_app_id;
+ 
++  properties->parent_widget = params.parent_widget;
++
+   DCHECK(!properties->x11_extension_delegate);
+   properties->x11_extension_delegate = this;
+ }
+diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
+index ee09e16753ff0..256a24a0c6ebd 100644
+--- ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
++++ ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
+@@ -59,6 +59,8 @@ class VIEWS_EXPORT DesktopWindowTreeHostLinux
+   // Disables event listening to make |dialog| modal.
+   base::OnceClosure DisableEventListening();
+ 
++  void set_screen_bounds(const gfx::Rect& bounds) { screen_bounds_ = bounds; }
++
+  protected:
+   // Overridden from DesktopWindowTreeHost:
+   void Init(const Widget::InitParams& params) override;
+@@ -68,6 +70,8 @@ class VIEWS_EXPORT DesktopWindowTreeHostLinux
+       const gfx::Vector2d& drag_offset,
+       Widget::MoveLoopSource source,
+       Widget::MoveLoopEscapeBehavior escape_behavior) override;
++  gfx::Rect GetWindowBoundsInScreen() const override;
++  gfx::Point GetLocationOnScreenInPixels() const override;
+ 
+   // PlatformWindowDelegate:
+   void DispatchEvent(ui::Event* event) override;
+@@ -116,6 +120,9 @@ class VIEWS_EXPORT DesktopWindowTreeHostLinux
+ 
+   uint32_t modal_dialog_counter_ = 0;
+ 
++   // Override the screen bounds when the host is a child window.
++  gfx::Rect screen_bounds_;
++
+   // The display and the native X window hosting the root window.
+   base::WeakPtrFactory<DesktopWindowTreeHostLinux> weak_factory_{this};
+ };
+diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
+index 9092e91e37b7d..9d749f2508eb0 100644
+--- ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
++++ ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
+@@ -286,8 +286,8 @@ void DesktopWindowTreeHostPlatform::Init(const Widget::InitParams& params) {
+   if (properties.parent_widget) {
+     window_parent_ = DesktopWindowTreeHostPlatform::GetHostForWidget(
+         properties.parent_widget);
+-    DCHECK(window_parent_);
+-    window_parent_->window_children_.insert(this);
++    if (window_parent_)
++      window_parent_->window_children_.insert(this);
+   }
+ 
+   // Calculate initial bounds.
+diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+index 53c1d25e3f56d..377ef1e646958 100644
+--- ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
++++ ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+@@ -180,16 +180,28 @@ void DesktopWindowTreeHostWin::Init(const Widget::InitParams& params) {
+                         native_widget_delegate_.get());
+ 
+   HWND parent_hwnd = nullptr;
+-  if (params.parent && params.parent->GetHost())
++  if (params.parent_widget) {
++    parent_hwnd = params.parent_widget;
++    has_external_parent_ = true;
++  } else if (params.parent && params.parent->GetHost()) {
+     parent_hwnd = params.parent->GetHost()->GetAcceleratedWidget();
++  }
+ 
+   remove_standard_frame_ = params.remove_standard_frame;
+   has_non_client_view_ = Widget::RequiresNonClientView(params.type);
+   z_order_ = params.EffectiveZOrderLevel();
+ 
+-  // We don't have an HWND yet, so scale relative to the nearest screen.
+-  gfx::Rect pixel_bounds =
+-      display::win::ScreenWin::DIPToScreenRect(nullptr, params.bounds);
++  gfx::Rect pixel_bounds;
++  if (has_external_parent_ && params.type != Widget::InitParams::TYPE_MENU) {
++    // Scale relative to the screen that contains the parent window.
++    // Child windows always have origin (0,0).
++    pixel_bounds.set_size(display::win::ScreenWin::DIPToScreenSize(
++        parent_hwnd, params.bounds.size()));
++  } else {
++    // We don't have an HWND yet, so scale relative to the nearest screen.
++    pixel_bounds =
++        display::win::ScreenWin::DIPToScreenRect(nullptr, params.bounds);
++  }
+   message_handler_->Init(parent_hwnd, pixel_bounds, params.headless_mode);
+   CreateCompositor(params.force_software_compositing);
+   OnAcceleratedWidgetAvailable();
+@@ -1034,11 +1046,15 @@ void DesktopWindowTreeHostWin::HandleFrameChanged() {
+ }
+ 
+ void DesktopWindowTreeHostWin::HandleNativeFocus(HWND last_focused_window) {
+-  // TODO(beng): inform the native_widget_delegate_.
++  // See comments in CefBrowserPlatformDelegateNativeWin::SetFocus.
++  if (has_external_parent_ && CanActivate())
++    HandleActivationChanged(true);
+ }
+ 
+ void DesktopWindowTreeHostWin::HandleNativeBlur(HWND focused_window) {
+-  // TODO(beng): inform the native_widget_delegate_.
++  // See comments in CefBrowserPlatformDelegateNativeWin::SetFocus.
++  if (has_external_parent_ && CanActivate())
++    HandleActivationChanged(false);
+ }
+ 
+ bool DesktopWindowTreeHostWin::HandleMouseEvent(ui::MouseEvent* event) {
+@@ -1046,6 +1062,12 @@ bool DesktopWindowTreeHostWin::HandleMouseEvent(ui::MouseEvent* event) {
+   if (ui::PlatformEventSource::ShouldIgnoreNativePlatformEvents())
+     return true;
+ 
++  // See comments in CefBrowserPlatformDelegateNativeWin::SetFocus.
++  if (has_external_parent_ && CanActivate() && event->IsAnyButton() &&
++      ::GetFocus() != GetHWND()) {
++    ::SetFocus(GetHWND());
++  }
++
+   SendEventToSink(event);
+   return event->handled();
+ }
+@@ -1224,8 +1246,16 @@ void DesktopWindowTreeHostWin::SetBoundsInDIP(const gfx::Rect& bounds) {
+   // positions in variable-DPI situations. See https://crbug.com/1224715 for
+   // details.
+   aura::Window* root = nullptr;
+-  const gfx::Rect bounds_in_pixels =
++  if (has_external_parent_) {
++    // Scale relative to the screen that contains the parent window.
++    root = AsWindowTreeHost()->window();
++  }
++  gfx::Rect bounds_in_pixels =
+       display::Screen::GetScreen()->DIPToScreenRectInWindow(root, bounds);
++  if (has_external_parent_) {
++    // Child windows always have origin (0,0).
++    bounds_in_pixels.set_origin(gfx::Point(0, 0));
++  }
+   AsWindowTreeHost()->SetBoundsInPixels(bounds_in_pixels);
+ }
+ 
+diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_win.h ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
+index 2e4bacce52a45..76916c5d21cb9 100644
+--- ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
++++ ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
+@@ -322,6 +322,10 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
+   // True if the window should have the frame removed.
+   bool remove_standard_frame_;
+ 
++  // True if the widget has a external parent view/window outside of the
++  // Chromium-controlled view/window hierarchy.
++  bool has_external_parent_ = false;
++
+   // Visibility of the cursor. On Windows we can have multiple root windows and
+   // the implementation of ::ShowCursor() is based on a counter, so making this
+   // member static ensures that ::ShowCursor() is always called exactly once
+diff --git ui/views/widget/widget.cc ui/views/widget/widget.cc
+index 2f552f72074e3..3f057242d198c 100644
+--- ui/views/widget/widget.cc
++++ ui/views/widget/widget.cc
+@@ -368,7 +368,8 @@ void Widget::Init(InitParams params) {
+   }
+ 
+   params.child |= (params.type == InitParams::TYPE_CONTROL);
+-  is_top_level_ = !params.child;
++  is_top_level_ = !params.child ||
++                  params.parent_widget != gfx::kNullAcceleratedWidget;
+ 
+   if (params.opacity == views::Widget::InitParams::WindowOpacity::kInferred &&
+       params.type != views::Widget::InitParams::TYPE_WINDOW) {
+@@ -480,14 +481,22 @@ void Widget::Init(InitParams params) {
+ 
+     if (show_state == ui::SHOW_STATE_MAXIMIZED) {
+       Maximize();
++      saved_show_state_ = ui::SHOW_STATE_MAXIMIZED;
+     } else if (show_state == ui::SHOW_STATE_MINIMIZED) {
+       Minimize();
+       saved_show_state_ = ui::SHOW_STATE_MINIMIZED;
++    } else if (show_state == ui::SHOW_STATE_FULLSCREEN) {
++      SetFullscreen(true);
+     }
+   } else if (delegate) {
+     SetContentsView(delegate->TransferOwnershipOfContentsView());
+     if (should_set_initial_bounds) {
+-      SetInitialBoundsForFramelessWindow(bounds);
++      if (params.parent_widget != gfx::kNullAcceleratedWidget) {
++        // Set the bounds directly instead of applying an inset.
++        SetBounds(bounds);
++      } else {
++        SetInitialBoundsForFramelessWindow(bounds);
++      }
+     }
+   }
+ 
+@@ -1631,10 +1640,16 @@ void Widget::OnNativeWidgetParentChanged(gfx::NativeView parent) {
+ }
+ 
+ gfx::Size Widget::GetMinimumSize() const {
++  gfx::Size size;
++  if (widget_delegate_->MaybeGetMinimumSize(&size))
++    return size;
+   return non_client_view_ ? non_client_view_->GetMinimumSize() : gfx::Size();
+ }
+ 
+ gfx::Size Widget::GetMaximumSize() const {
++  gfx::Size size;
++  if (widget_delegate_->MaybeGetMaximumSize(&size))
++    return size;
+   return non_client_view_ ? non_client_view_->GetMaximumSize() : gfx::Size();
+ }
+ 
+diff --git ui/views/widget/widget.h ui/views/widget/widget.h
+index 419b75d0608b2..57bb1fca770ed 100644
+--- ui/views/widget/widget.h
++++ ui/views/widget/widget.h
+@@ -351,6 +351,8 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
+     // the concept with bubble anchoring a la BubbleDialogDelegateView.
+     gfx::NativeView parent = gfx::NativeView();
+ 
++    gfx::AcceleratedWidget parent_widget = gfx::kNullAcceleratedWidget;
++
+     // Specifies the initial bounds of the Widget. Default is empty, which means
+     // the NativeWidget may specify a default size. If the parent is specified,
+     // |bounds| is in the parent's coordinate system. If the parent is not
+@@ -742,7 +744,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
+   void ShowInactive();
+ 
+   // Activates the widget, assuming it already exists and is visible.
+-  void Activate();
++  virtual void Activate();
+ 
+   // Deactivates the widget, making the next window in the Z order the active
+   // window.
+diff --git ui/views/widget/widget_delegate.h ui/views/widget/widget_delegate.h
+index 6d87be86ae8b3..02fe7a11958d0 100644
+--- ui/views/widget/widget_delegate.h
++++ ui/views/widget/widget_delegate.h
+@@ -380,6 +380,10 @@ class VIEWS_EXPORT WidgetDelegate
+   // Returns true if the title text should be centered.
+   bool ShouldCenterWindowTitleText() const;
+ 
++  // CEF supports override of min/max size values.
++  virtual bool MaybeGetMinimumSize(gfx::Size* size) const { return false; }
++  virtual bool MaybeGetMaximumSize(gfx::Size* size) const { return false; }
++
+   bool focus_traverses_out() const { return params_.focus_traverses_out; }
+   bool enable_arrow_key_traversal() const {
+     return params_.enable_arrow_key_traversal;
+diff --git ui/views/widget/widget_hwnd_utils.cc ui/views/widget/widget_hwnd_utils.cc
+index 3b9b00b7d79ae..e759e3c1a9f34 100644
+--- ui/views/widget/widget_hwnd_utils.cc
++++ ui/views/widget/widget_hwnd_utils.cc
+@@ -63,7 +63,8 @@ void CalculateWindowStylesFromInitParams(
+       if (!widget_delegate->CanResize())
+         *style &= static_cast<DWORD>(~(WS_THICKFRAME | WS_MAXIMIZEBOX));
+       if (params.remove_standard_frame)
+-        *style &= static_cast<DWORD>(~(WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
++        *style &= static_cast<DWORD>(~(WS_MINIMIZEBOX | WS_MAXIMIZEBOX |
++                                       WS_CAPTION | WS_SYSMENU));
+ 
+       if (native_widget_delegate->IsDialogBox()) {
+         *style |= DS_MODALFRAME;
+diff --git ui/views/win/hwnd_message_handler.cc ui/views/win/hwnd_message_handler.cc
+index f43aa724b2a8e..2782c80694a70 100644
+--- ui/views/win/hwnd_message_handler.cc
++++ ui/views/win/hwnd_message_handler.cc
+@@ -955,8 +955,12 @@ bool HWNDMessageHandler::IsActive() const {
+   // In headless mode return expected activation state instead of the
+   // actual one. This ensures that onfocus/onblur notifications work
+   // as expected and no unexpected throttling occurs.
++  // This active state is checked via FocusManager::SetFocusedViewWithReason.
++  // With CEF external parent hwnd() may be a child window, whereas
++  // GetActiveWindow() will return the root window, so make sure that we always
++  // compare root windows.
+   return IsHeadless() ? headless_mode_window_->active_state
+-                      : GetActiveWindow() == hwnd();
++                      : GetActiveWindow() == GetAncestor(hwnd(), GA_ROOT);
+ }
+ 
+ bool HWNDMessageHandler::IsMinimized() const {
+@@ -3353,10 +3357,13 @@ LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message,
+   } else if (event.type() == ui::ET_MOUSEWHEEL) {
+     ui::MouseWheelEvent mouse_wheel_event(msg);
+     // Reroute the mouse wheel to the window under the pointer if applicable.
+-    return (ui::RerouteMouseWheel(hwnd(), w_param, l_param) ||
+-            delegate_->HandleMouseEvent(&mouse_wheel_event))
+-               ? 0
+-               : 1;
++    if (ui::RerouteMouseWheel(hwnd(), w_param, l_param) ||
++        delegate_->HandleMouseEvent(&mouse_wheel_event)) {
++      SetMsgHandled(TRUE);
++      return 0;
++    } else {
++      return 1;
++    }
+   }
+ 
+   // Suppress |ET_MOUSE_MOVED| and |ET_MOUSE_DRAGGED| events from WM_MOUSE*
diff --git a/src/patch/patches/views_widget_180_1481_1565_1677_1749.patch b/src/patch/patches/views_widget_180_1481_1565_1677_1749.patch
deleted file mode 100644
index 22d9b37..0000000
--- a/src/patch/patches/views_widget_180_1481_1565_1677_1749.patch
+++ /dev/null
@@ -1,438 +0,0 @@
-diff --git content/browser/renderer_host/render_widget_host_view_base.cc content/browser/renderer_host/render_widget_host_view_base.cc
-index 19c6b2e5c705..b48d5c04ae0e 100644
---- content/browser/renderer_host/render_widget_host_view_base.cc
-+++ content/browser/renderer_host/render_widget_host_view_base.cc
-@@ -568,6 +568,14 @@ float RenderWidgetHostViewBase::GetDeviceScaleFactor() {
-   return screen_info.device_scale_factor;
- }
- 
-+void RenderWidgetHostViewBase::SetHasExternalParent(bool val) {
-+  has_external_parent_ = val;
-+}
-+
-+bool RenderWidgetHostViewBase::HasExternalParent() const {
-+  return has_external_parent_;
-+}
-+
- uint32_t RenderWidgetHostViewBase::RendererFrameNumber() {
-   return renderer_frame_number_;
- }
-diff --git content/browser/renderer_host/render_widget_host_view_base.h content/browser/renderer_host/render_widget_host_view_base.h
-index 27133fd98354..2552750935af 100644
---- content/browser/renderer_host/render_widget_host_view_base.h
-+++ content/browser/renderer_host/render_widget_host_view_base.h
-@@ -65,6 +65,7 @@ class CursorManager;
- class MouseWheelPhaseHandler;
- class RenderWidgetHostImpl;
- class RenderWidgetHostViewBaseObserver;
-+class RenderWidgetHostViewGuest;
- class SyntheticGestureTarget;
- class TextInputManager;
- class TouchSelectionControllerClientManager;
-@@ -82,6 +83,9 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
-   float current_device_scale_factor() const {
-     return current_device_scale_factor_;
-   }
-+  void set_current_device_scale_factor(float scale_factor) {
-+    current_device_scale_factor_ = scale_factor;
-+  }
- 
-   // Returns the focused RenderWidgetHost inside this |view|'s RWH.
-   RenderWidgetHostImpl* GetFocusedWidget() const;
-@@ -116,6 +120,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
-   void DisableAutoResize(const gfx::Size& new_size) override;
-   bool IsScrollOffsetAtTop() override;
-   float GetDeviceScaleFactor() final;
-+  void SetHasExternalParent(bool val) override;
-+  bool HasExternalParent() const override;
-   TouchSelectionControllerClientManager*
-   GetTouchSelectionControllerClientManager() override;
-   void SetRecordContentToVisibleTimeRequest(
-@@ -444,6 +450,12 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
-   // helps to position the full screen widget on the correct monitor.
-   virtual void InitAsFullscreen(RenderWidgetHostView* reference_host_view) = 0;
- 
-+  // Perform all the initialization steps necessary for this object to represent
-+  // the platform widget owned by |guest_view| and embedded in
-+  // |parent_host_view|.
-+  virtual void InitAsGuest(RenderWidgetHostView* parent_host_view,
-+                           RenderWidgetHostViewGuest* guest_view) {}
-+
-   // Sets the cursor for this view to the one associated with the specified
-   // cursor_type.
-   virtual void UpdateCursor(const WebCursor& cursor) = 0;
-@@ -608,6 +620,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
- 
-   bool is_currently_scrolling_viewport_ = false;
- 
-+  // True if the widget has a external parent view/window outside of the
-+  // Chromium-controlled view/window hierarchy.
-+  bool has_external_parent_ = false;
-+
-  private:
-   FRIEND_TEST_ALL_PREFIXES(
-       BrowserSideFlingBrowserTest,
-diff --git content/browser/renderer_host/render_widget_host_view_event_handler.cc content/browser/renderer_host/render_widget_host_view_event_handler.cc
-index 4b2067bc7f26..3f483ff54365 100644
---- content/browser/renderer_host/render_widget_host_view_event_handler.cc
-+++ content/browser/renderer_host/render_widget_host_view_event_handler.cc
-@@ -33,6 +33,10 @@
- #include "ui/events/keycodes/dom/dom_code.h"
- #include "ui/touch_selection/touch_selection_controller.h"
- 
-+#if defined(OS_LINUX)
-+#include "ui/aura/window_tree_host.h"
-+#endif
-+
- #if defined(OS_WIN)
- #include "content/browser/frame_host/render_frame_host_impl.h"
- #include "ui/aura/window_tree_host.h"
-@@ -928,6 +932,14 @@ void RenderWidgetHostViewEventHandler::SetKeyboardFocus() {
-         ::SetFocus(hwnd);
-     }
-   }
-+#endif
-+#if defined(OS_LINUX)
-+  if (host_view_->HasExternalParent() &&
-+      window_ && window_->delegate()->CanFocus()) {
-+    aura::WindowTreeHost* host = window_->GetHost();
-+    if (host)
-+      host->Show();
-+  }
- #endif
-   // TODO(wjmaclean): can host_ ever be null?
-   if (host_ && set_focus_on_mouse_down_or_key_event_) {
-diff --git content/public/browser/render_widget_host_view.h content/public/browser/render_widget_host_view.h
-index 3e5bf09f1cf7..bc8ea335d501 100644
---- content/public/browser/render_widget_host_view.h
-+++ content/public/browser/render_widget_host_view.h
-@@ -243,6 +243,14 @@ class CONTENT_EXPORT RenderWidgetHostView {
-   // This must always return the same device scale factor as GetScreenInfo.
-   virtual float GetDeviceScaleFactor() = 0;
- 
-+  // Set whether the widget has a external parent view/window outside of the
-+  // Chromium-controlled view/window hierarchy.
-+  virtual void SetHasExternalParent(bool val) = 0;
-+
-+  // Returns true if the widget has a external parent view/window outside of the
-+  // Chromium-controlled view/window hierarchy.
-+  virtual bool HasExternalParent() const = 0;
-+
- #if defined(OS_MACOSX)
-   // Set the view's active state (i.e., tint state of controls).
-   virtual void SetActive(bool active) = 0;
-diff --git ui/base/x/x11_window.cc ui/base/x/x11_window.cc
-index f58ab14a3a07..f8388e7ac048 100644
---- ui/base/x/x11_window.cc
-+++ ui/base/x/x11_window.cc
-@@ -255,8 +255,12 @@ void XWindow::Init(const Configuration& config) {
-   attribute_mask |= CWBorderPixel;
-   swa.border_pixel = 0;
- 
-+  gfx::AcceleratedWidget parent_widget = config.parent_widget;
-+  if (parent_widget == gfx::kNullAcceleratedWidget)
-+    parent_widget = x_root_window_;
-+
-   bounds_in_pixels_ = SanitizeBounds(config.bounds);
--  xwindow_ = XCreateWindow(xdisplay_, x_root_window_, bounds_in_pixels_.x(),
-+  xwindow_ = XCreateWindow(xdisplay_, parent_widget, bounds_in_pixels_.x(),
-                            bounds_in_pixels_.y(), bounds_in_pixels_.width(),
-                            bounds_in_pixels_.height(),
-                            0,  // border width
-diff --git ui/base/x/x11_window.h ui/base/x/x11_window.h
-index d0f852b1d69d..7d3ea8779fd1 100644
---- ui/base/x/x11_window.h
-+++ ui/base/x/x11_window.h
-@@ -19,6 +19,7 @@
- #include "ui/gfx/geometry/rect.h"
- #include "ui/gfx/geometry/size.h"
- #include "ui/gfx/geometry/size_f.h"
-+#include "ui/gfx/native_widget_types.h"
- #include "ui/gfx/x/x11.h"
- #include "ui/gfx/x/x11_types.h"
- 
-@@ -86,6 +87,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow {
-     std::string wm_class_name;
-     std::string wm_class_class;
-     std::string wm_role_name;
-+    gfx::AcceleratedWidget parent_widget = gfx::kNullAcceleratedWidget;
-   };
- 
-   XWindow();
-diff --git ui/platform_window/x11/x11_window.cc ui/platform_window/x11/x11_window.cc
-index 98b442ee756d..d3ad9f8995cc 100644
---- ui/platform_window/x11/x11_window.cc
-+++ ui/platform_window/x11/x11_window.cc
-@@ -85,6 +85,7 @@ ui::XWindow::Configuration ConvertInitPropertiesToXWindowConfig(
-   config.wm_class_class = properties.wm_class_class;
-   config.wm_role_name = properties.wm_role_name;
-   config.activatable = properties.activatable;
-+  config.parent_widget = properties.parent_widget;
-   config.prefer_dark_theme = properties.prefer_dark_theme;
-   config.background_color = properties.background_color;
-   return config;
-diff --git ui/views/widget/desktop_aura/desktop_screen_win.cc ui/views/widget/desktop_aura/desktop_screen_win.cc
-index 70553b153c44..ecd99bc78373 100644
---- ui/views/widget/desktop_aura/desktop_screen_win.cc
-+++ ui/views/widget/desktop_aura/desktop_screen_win.cc
-@@ -30,6 +30,8 @@ display::Display DesktopScreenWin::GetDisplayMatching(
- }
- 
- HWND DesktopScreenWin::GetHWNDFromNativeView(gfx::NativeView window) const {
-+  if (!window)
-+    return NULL;
-   aura::WindowTreeHost* host = window->GetHost();
-   return host ? host->GetAcceleratedWidget() : nullptr;
- }
-diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
-index 91cfaf77bb31..f369314e02f4 100644
---- ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
-+++ ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
-@@ -348,6 +348,8 @@ void DesktopWindowTreeHostLinux::AddAdditionalInitProperties(
-   properties->wm_class_class = params.wm_class_class;
-   properties->wm_role_name = params.wm_role_name;
- 
-+  properties->parent_widget = params.parent_widget;
-+
-   DCHECK(!properties->x11_extension_delegate);
-   properties->x11_extension_delegate = this;
- }
-diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
-index 6f576d95707d..dacd02f13012 100644
---- ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
-+++ ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
-@@ -133,8 +133,12 @@ void DesktopWindowTreeHostWin::Init(const Widget::InitParams& params) {
-                         native_widget_delegate_);
- 
-   HWND parent_hwnd = nullptr;
--  if (params.parent && params.parent->GetHost())
-+  if (params.parent_widget) {
-+    parent_hwnd = params.parent_widget;
-+    has_external_parent_ = true;
-+  } else if (params.parent && params.parent->GetHost()) {
-     parent_hwnd = params.parent->GetHost()->GetAcceleratedWidget();
-+  }
- 
-   remove_standard_frame_ = params.remove_standard_frame;
-   has_non_client_view_ = Widget::RequiresNonClientView(params.type);
-@@ -909,11 +913,15 @@ void DesktopWindowTreeHostWin::HandleFrameChanged() {
- }
- 
- void DesktopWindowTreeHostWin::HandleNativeFocus(HWND last_focused_window) {
--  // TODO(beng): inform the native_widget_delegate_.
-+  // See comments in CefBrowserHostImpl::PlatformSetFocus.
-+  if (has_external_parent_ && CanActivate())
-+    HandleActivationChanged(true);
- }
- 
- void DesktopWindowTreeHostWin::HandleNativeBlur(HWND focused_window) {
--  // TODO(beng): inform the native_widget_delegate_.
-+  // See comments in CefBrowserHostImpl::PlatformSetFocus.
-+  if (has_external_parent_ && CanActivate())
-+    HandleActivationChanged(false);
- }
- 
- bool DesktopWindowTreeHostWin::HandleMouseEvent(ui::MouseEvent* event) {
-diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_win.h ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
-index 4b217541512c..1940da51d5c6 100644
---- ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
-+++ ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
-@@ -288,6 +288,10 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
-   // True if the window should have the frame removed.
-   bool remove_standard_frame_;
- 
-+  // True if the widget has a external parent view/window outside of the
-+  // Chromium-controlled view/window hierarchy.
-+  bool has_external_parent_ = false;
-+
-   // Owned by TooltipController, but we need to forward events to it so we keep
-   // a reference.
-   corewm::TooltipWin* tooltip_;
-diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
-index 2c94941cf273..9512335908cf 100644
---- ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
-+++ ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
-@@ -83,6 +83,9 @@ DesktopWindowTreeHostX11::~DesktopWindowTreeHostX11() {
- // DesktopWindowTreeHostX11, DesktopWindowTreeHost implementation:
- 
- void DesktopWindowTreeHostX11::Init(const Widget::InitParams& params) {
-+  if (params.parent_widget != gfx::kNullAcceleratedWidget)
-+    has_external_parent_ = true;
-+
-   DesktopWindowTreeHostLinux::Init(params);
- 
-   // Set XEventDelegate to receive selection, drag&drop and raw key events.
-@@ -134,6 +137,18 @@ void DesktopWindowTreeHostX11::EndMoveLoop() {
- ////////////////////////////////////////////////////////////////////////////////
- // DesktopWindowTreeHostX11 implementation:
- 
-+gfx::Rect DesktopWindowTreeHostX11::GetWindowBoundsInScreen() const {
-+  if (!screen_bounds_.IsEmpty())
-+    return screen_bounds_;
-+  return DesktopWindowTreeHostLinux::GetWindowBoundsInScreen();
-+}
-+
-+gfx::Point DesktopWindowTreeHostX11::GetLocationOnScreenInPixels() const {
-+  if (!screen_bounds_.IsEmpty())
-+    return screen_bounds_.origin();
-+  return DesktopWindowTreeHostLinux::GetLocationOnScreenInPixels();
-+}
-+
- void DesktopWindowTreeHostX11::OnXWindowSelectionEvent(XEvent* xev) {
-   DCHECK(xev);
-   DCHECK(drag_drop_client_);
-diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
-index 53da309c14d3..7a50560c8abc 100644
---- ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
-+++ ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
-@@ -31,6 +31,12 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 : public DesktopWindowTreeHostLinux,
-       DesktopNativeWidgetAura* desktop_native_widget_aura);
-   ~DesktopWindowTreeHostX11() override;
- 
-+  void set_screen_bounds(const gfx::Rect& bounds) { screen_bounds_ = bounds; }
-+
-+  // Returns true if the widget has a external parent view/window outside of the
-+  // Chromium-controlled view/window hierarchy.
-+  bool has_external_parent() const { return has_external_parent_; }
-+
-  protected:
-   // Overridden from DesktopWindowTreeHost:
-   void Init(const Widget::InitParams& params) override;
-@@ -42,6 +48,8 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 : public DesktopWindowTreeHostLinux,
-       Widget::MoveLoopSource source,
-       Widget::MoveLoopEscapeBehavior escape_behavior) override;
-   void EndMoveLoop() override;
-+  gfx::Rect GetWindowBoundsInScreen() const override;
-+  gfx::Point GetLocationOnScreenInPixels() const override;
- 
-  private:
-   friend class DesktopWindowTreeHostX11HighDPITest;
-@@ -56,10 +64,20 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 : public DesktopWindowTreeHostLinux,
-   // directly. See https://crbug.com/990756.
-   const ui::XWindow* GetXWindow() const;
- 
-+  // Override the screen bounds when the host is a child window.
-+  gfx::Rect screen_bounds_;
-+
-+  // True if the widget has a external parent view/window outside of the
-+  // Chromium-controlled view/window hierarchy.
-+  bool has_external_parent_ = false;
-+
-   DesktopDragDropClientAuraX11* drag_drop_client_ = nullptr;
- 
-   std::unique_ptr<X11DesktopWindowMoveClient> x11_window_move_client_;
- 
-+  // True if the xwindow has already been destroyed.
-+  bool xwindow_destroyed_ = false;
-+
-   DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostX11);
- };
- 
-diff --git ui/views/widget/widget.cc ui/views/widget/widget.cc
-index 6472b4210a0a..390758b017be 100644
---- ui/views/widget/widget.cc
-+++ ui/views/widget/widget.cc
-@@ -289,7 +289,8 @@ void Widget::Init(InitParams params) {
-     params.name = params.delegate->GetContentsView()->GetClassName();
- 
-   params.child |= (params.type == InitParams::TYPE_CONTROL);
--  is_top_level_ = !params.child;
-+  is_top_level_ = !params.child ||
-+                  params.parent_widget != gfx::kNullAcceleratedWidget;
- 
-   if (params.opacity == views::Widget::InitParams::WindowOpacity::kInferred &&
-       params.type != views::Widget::InitParams::TYPE_WINDOW) {
-@@ -371,7 +372,12 @@ void Widget::Init(InitParams params) {
-     }
-   } else if (delegate) {
-     SetContentsView(delegate->GetContentsView());
--    SetInitialBoundsForFramelessWindow(bounds);
-+    if (params.parent_widget != gfx::kNullAcceleratedWidget) {
-+      // Set the bounds directly instead of applying an inset.
-+      SetBounds(bounds);
-+    } else {
-+      SetInitialBoundsForFramelessWindow(bounds);
-+    }
-   }
- 
-   observer_manager_.Add(GetNativeTheme());
-@@ -1156,10 +1162,16 @@ void Widget::OnNativeWidgetDestroyed() {
- }
- 
- gfx::Size Widget::GetMinimumSize() const {
-+  gfx::Size size;
-+  if (widget_delegate_->MaybeGetMinimumSize(&size))
-+    return size;
-   return non_client_view_ ? non_client_view_->GetMinimumSize() : gfx::Size();
- }
- 
- gfx::Size Widget::GetMaximumSize() const {
-+  gfx::Size size;
-+  if (widget_delegate_->MaybeGetMaximumSize(&size))
-+    return size;
-   return non_client_view_ ? non_client_view_->GetMaximumSize() : gfx::Size();
- }
- 
-diff --git ui/views/widget/widget.h ui/views/widget/widget.h
-index 105fc39ed5ec..a4e227167dbd 100644
---- ui/views/widget/widget.h
-+++ ui/views/widget/widget.h
-@@ -312,6 +312,8 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
-     // the concept with bubble anchoring a la BubbleDialogDelegateView.
-     gfx::NativeView parent = nullptr;
- 
-+    gfx::AcceleratedWidget parent_widget = gfx::kNullAcceleratedWidget;
-+
-     // Specifies the initial bounds of the Widget. Default is empty, which means
-     // the NativeWidget may specify a default size. If the parent is specified,
-     // |bounds| is in the parent's coordinate system. If the parent is not
-diff --git ui/views/widget/widget_delegate.h ui/views/widget/widget_delegate.h
-index a3ec229f11cb..714f608b7b58 100644
---- ui/views/widget/widget_delegate.h
-+++ ui/views/widget/widget_delegate.h
-@@ -202,6 +202,10 @@ class VIEWS_EXPORT WidgetDelegate {
-   // be cycled through with keyboard focus.
-   virtual void GetAccessiblePanes(std::vector<View*>* panes) {}
- 
-+  // CEF supports override of min/max size values.
-+  virtual bool MaybeGetMinimumSize(gfx::Size* size) const { return false; }
-+  virtual bool MaybeGetMaximumSize(gfx::Size* size) const { return false; }
-+
-  protected:
-   virtual ~WidgetDelegate();
- 
-diff --git ui/views/widget/widget_hwnd_utils.cc ui/views/widget/widget_hwnd_utils.cc
-index 40e66a212e3e..08ee8523ab15 100644
---- ui/views/widget/widget_hwnd_utils.cc
-+++ ui/views/widget/widget_hwnd_utils.cc
-@@ -67,7 +67,7 @@ void CalculateWindowStylesFromInitParams(
-       if (!widget_delegate->CanResize())
-         *style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
-       if (params.remove_standard_frame)
--        *style &= ~(WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
-+        *style &= ~(WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU);
- 
-       if (native_widget_delegate->IsDialogBox()) {
-         *style |= DS_MODALFRAME;
-diff --git ui/views/win/hwnd_message_handler.cc ui/views/win/hwnd_message_handler.cc
-index e18afe3c8c28..3b8b21eee322 100644
---- ui/views/win/hwnd_message_handler.cc
-+++ ui/views/win/hwnd_message_handler.cc
-@@ -3005,10 +3005,13 @@ LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message,
-   } else if (event.type() == ui::ET_MOUSEWHEEL) {
-     ui::MouseWheelEvent mouse_wheel_event(msg);
-     // Reroute the mouse wheel to the window under the pointer if applicable.
--    return (ui::RerouteMouseWheel(hwnd(), w_param, l_param) ||
--            delegate_->HandleMouseEvent(&mouse_wheel_event))
--               ? 0
--               : 1;
-+    if (ui::RerouteMouseWheel(hwnd(), w_param, l_param) ||
-+        delegate_->HandleMouseEvent(&mouse_wheel_event)) {
-+      SetMsgHandled(TRUE);
-+      return 0;
-+    } else {
-+      return 1;
-+    }
-   }
- 
-   // Suppress |ET_MOUSE_MOVED| and |ET_MOUSE_DRAGGED| events from WM_MOUSE*
diff --git a/src/patch/patches/viz_osr_2575.patch b/src/patch/patches/viz_osr_2575.patch
index 7afedd6..f26ea00 100644
--- a/src/patch/patches/viz_osr_2575.patch
+++ b/src/patch/patches/viz_osr_2575.patch
@@ -1,12 +1,12 @@
 diff --git components/viz/host/host_display_client.cc components/viz/host/host_display_client.cc
-index 3547ee865c22..2215296ffadc 100644
+index 0c63e0d59b6b0..bdbac6fceb1df 100644
 --- components/viz/host/host_display_client.cc
 +++ components/viz/host/host_display_client.cc
-@@ -43,9 +43,14 @@ void HostDisplayClient::OnDisplayReceivedCALayerParams(
+@@ -48,9 +48,14 @@ void HostDisplayClient::OnDisplayReceivedCALayerParams(
  }
  #endif
  
--#if defined(OS_WIN)
+-#if BUILDFLAG(IS_WIN)
 +void HostDisplayClient::UseProxyOutputDevice(
 +    UseProxyOutputDeviceCallback callback) {
 +  std::move(callback).Run(false);
@@ -14,50 +14,50 @@
 +
  void HostDisplayClient::CreateLayeredWindowUpdater(
      mojo::PendingReceiver<mojom::LayeredWindowUpdater> receiver) {
-+#if defined(OS_WIN)
++#if BUILDFLAG(IS_WIN)
    if (!NeedsToUseLayerWindow(widget_)) {
      DLOG(ERROR) << "HWND shouldn't be using a layered window";
      return;
-@@ -53,8 +58,8 @@ void HostDisplayClient::CreateLayeredWindowUpdater(
+@@ -58,7 +63,10 @@ void HostDisplayClient::CreateLayeredWindowUpdater(
  
    layered_window_updater_ =
        std::make_unique<LayeredWindowUpdaterImpl>(widget_, std::move(receiver));
--}
- #endif
-+}
- 
- #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
- void HostDisplayClient::DidCompleteSwapWithNewSize(const gfx::Size& size) {
++#endif
+ }
++
++#if BUILDFLAG(IS_WIN)
+ void HostDisplayClient::AddChildWindowToBrowser(
+     gpu::SurfaceHandle child_window) {
+   NOTREACHED();
 diff --git components/viz/host/host_display_client.h components/viz/host/host_display_client.h
-index cedf833d2358..04456e045304 100644
+index 5eeaadec9773f..93a716decfbb9 100644
 --- components/viz/host/host_display_client.h
 +++ components/viz/host/host_display_client.h
-@@ -31,17 +31,17 @@ class VIZ_HOST_EXPORT HostDisplayClient : public mojom::DisplayClient {
-   mojo::PendingRemote<mojom::DisplayClient> GetBoundRemote(
-       scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+@@ -39,16 +39,17 @@ class VIZ_HOST_EXPORT HostDisplayClient : public mojom::DisplayClient {
+   gfx::AcceleratedWidget widget() const { return widget_; }
+ #endif
  
 - private:
-+ protected:
    // mojom::DisplayClient implementation:
 +  void UseProxyOutputDevice(UseProxyOutputDeviceCallback callback) override;
 +
- #if defined(OS_MACOSX)
+ #if BUILDFLAG(IS_APPLE)
    void OnDisplayReceivedCALayerParams(
        const gfx::CALayerParams& ca_layer_params) override;
  #endif
  
--#if defined(OS_WIN)
+-#if BUILDFLAG(IS_WIN)
    void CreateLayeredWindowUpdater(
        mojo::PendingReceiver<mojom::LayeredWindowUpdater> receiver) override;
--#endif
++#if BUILDFLAG(IS_WIN)
+   void AddChildWindowToBrowser(gpu::SurfaceHandle child_window) override;
+ #endif
  
- #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
-   void DidCompleteSwapWithNewSize(const gfx::Size& size) override;
 diff --git components/viz/host/layered_window_updater_impl.cc components/viz/host/layered_window_updater_impl.cc
-index b04f654fe820..131977a36591 100644
+index 8f726bde2cb5d..0737835d1e9d1 100644
 --- components/viz/host/layered_window_updater_impl.cc
 +++ components/viz/host/layered_window_updater_impl.cc
-@@ -44,7 +44,7 @@ void LayeredWindowUpdaterImpl::OnAllocatedSharedMemory(
+@@ -46,7 +46,7 @@ void LayeredWindowUpdaterImpl::OnAllocatedSharedMemory(
    // |region|'s handle will close when it goes out of scope.
  }
  
@@ -67,10 +67,10 @@
  
    if (!canvas_) {
 diff --git components/viz/host/layered_window_updater_impl.h components/viz/host/layered_window_updater_impl.h
-index 1026b739d283..fe562ab60ce9 100644
+index 8af69cac78b74..9f74e511c263d 100644
 --- components/viz/host/layered_window_updater_impl.h
 +++ components/viz/host/layered_window_updater_impl.h
-@@ -35,7 +35,7 @@ class VIZ_HOST_EXPORT LayeredWindowUpdaterImpl
+@@ -38,7 +38,7 @@ class VIZ_HOST_EXPORT LayeredWindowUpdaterImpl
    // mojom::LayeredWindowUpdater implementation.
    void OnAllocatedSharedMemory(const gfx::Size& pixel_size,
                                 base::UnsafeSharedMemoryRegion region) override;
@@ -80,33 +80,39 @@
   private:
    const HWND hwnd_;
 diff --git components/viz/service/BUILD.gn components/viz/service/BUILD.gn
-index eb1a0ae5ca25..846c738053b7 100644
+index d3a1ba02c0924..cf74aba62b079 100644
 --- components/viz/service/BUILD.gn
 +++ components/viz/service/BUILD.gn
-@@ -13,7 +13,10 @@ config("viz_service_implementation") {
- }
- 
- viz_component("service") {
-+  never_build_jumbo = true
-   sources = [
+@@ -230,6 +230,8 @@ viz_component("service") {
+     "transitions/transferable_resource_tracker.cc",
+     "transitions/transferable_resource_tracker.h",
+     "viz_service_export.h",
 +    "//cef/libcef/browser/osr/software_output_device_proxy.cc",
 +    "//cef/libcef/browser/osr/software_output_device_proxy.h",
-     "display/bsp_tree.cc",
-     "display/bsp_tree.h",
-     "display/bsp_walk_action.cc",
+   ]
+ 
+   defines = [ "VIZ_SERVICE_IMPLEMENTATION" ]
 diff --git components/viz/service/display_embedder/output_surface_provider_impl.cc components/viz/service/display_embedder/output_surface_provider_impl.cc
-index b4d4b1c1c597..9ce685048ab1 100644
+index 0bc450ca4faf2..bdbdca76246c6 100644
 --- components/viz/service/display_embedder/output_surface_provider_impl.cc
 +++ components/viz/service/display_embedder/output_surface_provider_impl.cc
-@@ -13,6 +13,7 @@
- #include "base/threading/thread_task_runner_handle.h"
+@@ -17,6 +17,7 @@
  #include "build/chromecast_buildflags.h"
+ #include "build/chromeos_buildflags.h"
  #include "cc/base/switches.h"
 +#include "cef/libcef/browser/osr/software_output_device_proxy.h"
  #include "components/viz/common/display/renderer_settings.h"
  #include "components/viz/common/frame_sinks/begin_frame_source.h"
- #include "components/viz/service/display_embedder/gl_output_surface.h"
-@@ -224,6 +225,20 @@ OutputSurfaceProviderImpl::CreateSoftwareOutputDeviceForPlatform(
+ #include "components/viz/service/display/display_compositor_memory_and_task_controller.h"
+@@ -29,6 +30,7 @@
+ #include "gpu/command_buffer/service/scheduler_sequence.h"
+ #include "gpu/config/gpu_finch_features.h"
+ #include "gpu/ipc/common/surface_handle.h"
++#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
+ #include "ui/base/ui_base_switches.h"
+ 
+ #if BUILDFLAG(IS_WIN)
+@@ -144,6 +146,20 @@ OutputSurfaceProviderImpl::CreateSoftwareOutputDeviceForPlatform(
    if (headless_)
      return std::make_unique<SoftwareOutputDevice>();
  
@@ -116,22 +122,22 @@
 +    bool use_proxy_output_device = false;
 +    if (display_client->UseProxyOutputDevice(&use_proxy_output_device) &&
 +        use_proxy_output_device) {
-+      mojom::LayeredWindowUpdaterPtr layered_window_updater;
++      mojo::PendingRemote<mojom::LayeredWindowUpdater> layered_window_updater;
 +      display_client->CreateLayeredWindowUpdater(
-+          mojo::MakeRequest(&layered_window_updater));
++          layered_window_updater.InitWithNewPipeAndPassReceiver());
 +      return std::make_unique<SoftwareOutputDeviceProxy>(
 +          std::move(layered_window_updater));
 +    }
 +  }
 +
- #if defined(OS_WIN)
+ #if BUILDFLAG(IS_WIN)
    return CreateSoftwareOutputDeviceWin(surface_handle, &output_device_backing_,
                                         display_client);
 diff --git components/viz/service/display_embedder/software_output_device_win.cc components/viz/service/display_embedder/software_output_device_win.cc
-index 2bb30e5318b6..535535dd6c10 100644
+index 796ae2688436e..37a3406790210 100644
 --- components/viz/service/display_embedder/software_output_device_win.cc
 +++ components/viz/service/display_embedder/software_output_device_win.cc
-@@ -188,8 +188,9 @@ void SoftwareOutputDeviceWinProxy::EndPaintDelegated(
+@@ -193,8 +193,9 @@ void SoftwareOutputDeviceWinProxy::EndPaintDelegated(
    if (!canvas_)
      return;
  
@@ -144,13 +150,13 @@
  
    TRACE_EVENT_ASYNC_BEGIN0("viz", "SoftwareOutputDeviceWinProxy::Draw", this);
 diff --git content/browser/compositor/viz_process_transport_factory.cc content/browser/compositor/viz_process_transport_factory.cc
-index 8e10af98f2b0..d39fc7ec7b4c 100644
+index c34c0854efeec..7b51180b6d8ac 100644
 --- content/browser/compositor/viz_process_transport_factory.cc
 +++ content/browser/compositor/viz_process_transport_factory.cc
-@@ -404,8 +404,13 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel(
-   compositor_data.display_private.reset();
+@@ -393,8 +393,13 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel(
+   mojo::AssociatedRemote<viz::mojom::DisplayPrivate> display_private;
    root_params->display_private =
-       compositor_data.display_private.BindNewEndpointAndPassReceiver();
+       display_private.BindNewEndpointAndPassReceiver();
 -  compositor_data.display_client =
 -      std::make_unique<HostDisplayClient>(compositor);
 +  if (compositor->delegate()) {
@@ -162,40 +168,41 @@
 +  }
    root_params->display_client =
        compositor_data.display_client->GetBoundRemote(resize_task_runner_);
- 
+   mojo::AssociatedRemote<viz::mojom::ExternalBeginFrameController>
 diff --git mojo/public/cpp/bindings/sync_call_restrictions.h mojo/public/cpp/bindings/sync_call_restrictions.h
-index 60e114920575..01f2ce164a3b 100644
+index d63ec55ae38d6..ff86831efd68b 100644
 --- mojo/public/cpp/bindings/sync_call_restrictions.h
 +++ mojo/public/cpp/bindings/sync_call_restrictions.h
-@@ -29,6 +29,7 @@ class Compositor;
+@@ -42,6 +42,7 @@ class Compositor;
+ }  // namespace ui
  
  namespace viz {
- class HostFrameSinkManager;
 +class GpuDisplayProvider;
- }
- 
- namespace mojo {
-@@ -82,6 +83,8 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) SyncCallRestrictions {
+ class GpuHostImpl;
+ class HostFrameSinkManager;
+ class HostGpuMemoryBufferManager;
+@@ -118,6 +119,8 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) SyncCallRestrictions {
    // For preventing frame swaps of wrong size during resize on Windows.
    // (https://crbug.com/811945)
    friend class ui::Compositor;
 +  // For query of whether to use SoftwareOutputDevice or not.
 +  friend class viz::GpuDisplayProvider;
-   // END ALLOWED USAGE.
- 
- #if ENABLE_SYNC_CALL_RESTRICTIONS
+   // For calling sync mojo API to get cdm origin. The service and the client are
+   // running in the same process, so it won't block anything.
+   // TODO(159346933) Remove once the origin isolation logic is moved outside of
 diff --git services/viz/privileged/mojom/compositing/display_private.mojom services/viz/privileged/mojom/compositing/display_private.mojom
-index d36f62e6ee41..e8ec62cda569 100644
+index 29936bca703b8..8ffe0f5509475 100644
 --- services/viz/privileged/mojom/compositing/display_private.mojom
 +++ services/viz/privileged/mojom/compositing/display_private.mojom
-@@ -74,12 +74,14 @@ interface DisplayPrivate {
- };
+@@ -108,13 +108,15 @@ interface DisplayPrivate {
  
+ // DisplayClient allows privileged clients to receive events from the Display.
  interface DisplayClient {
 +  [Sync]
 +  UseProxyOutputDevice() => (bool success);
 +
-   [EnableIf=is_mac]
+   // Called when new Core Animation Layer params are received.
+   [EnableIf=is_apple]
    OnDisplayReceivedCALayerParams(gfx.mojom.CALayerParams ca_layer_params);
  
    // Creates a LayeredWindowUpdater implementation to draw into a layered
@@ -203,9 +210,9 @@
 -  [EnableIf=is_win]
    CreateLayeredWindowUpdater(pending_receiver<LayeredWindowUpdater> receiver);
  
-   // Notifies that a swap has occurred and provides information about the pixel
+   // Sends the created child window to the browser process so that it can be
 diff --git services/viz/privileged/mojom/compositing/layered_window_updater.mojom services/viz/privileged/mojom/compositing/layered_window_updater.mojom
-index 6b7fbb6cf13d..e2af75168cb9 100644
+index 2f462f0deb5fc..695869b83cefa 100644
 --- services/viz/privileged/mojom/compositing/layered_window_updater.mojom
 +++ services/viz/privileged/mojom/compositing/layered_window_updater.mojom
 @@ -26,5 +26,5 @@ interface LayeredWindowUpdater {
@@ -216,20 +223,20 @@
 +  Draw(gfx.mojom.Rect damage_rect) => ();
  };
 diff --git ui/compositor/compositor.h ui/compositor/compositor.h
-index 3e2d2304faf7..f0029d34f591 100644
+index c9f14ed6547ba..f4a3da53f53ef 100644
 --- ui/compositor/compositor.h
 +++ ui/compositor/compositor.h
-@@ -23,7 +23,9 @@
- #include "cc/trees/layer_tree_host_single_thread_client.h"
+@@ -33,7 +33,9 @@
  #include "components/viz/common/frame_sinks/begin_frame_args.h"
  #include "components/viz/common/surfaces/frame_sink_id.h"
+ #include "components/viz/common/surfaces/subtree_capture_id.h"
 +#include "components/viz/host/host_display_client.h"
  #include "components/viz/host/host_frame_sink_client.h"
 +#include "components/viz/service/display/software_output_device.h"
+ #include "mojo/public/cpp/bindings/associated_remote.h"
  #include "mojo/public/cpp/bindings/pending_remote.h"
- #include "services/viz/privileged/mojom/compositing/vsync_parameter_observer.mojom-forward.h"
- #include "third_party/skia/include/core/SkColor.h"
-@@ -122,6 +124,14 @@ class COMPOSITOR_EXPORT ContextFactory {
+ #include "services/viz/privileged/mojom/compositing/display_private.mojom.h"
+@@ -145,6 +147,14 @@ class COMPOSITOR_EXPORT ContextFactory {
    virtual viz::HostFrameSinkManager* GetHostFrameSinkManager() = 0;
  };
  
@@ -244,7 +251,7 @@
  // Compositor object to take care of GPU painting.
  // A Browser compositor object is responsible for generating the final
  // displayable form of pixels comprising a single widget's contents. It draws an
-@@ -155,6 +165,9 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
+@@ -188,6 +198,9 @@ class COMPOSITOR_EXPORT Compositor : public base::PowerSuspendObserver,
    // Schedules a redraw of the layer tree associated with this compositor.
    void ScheduleDraw();
  
@@ -254,12 +261,12 @@
    // Sets the root of the layer tree drawn by this Compositor. The root layer
    // must have no parent. The compositor's root layer is reset if the root layer
    // is destroyed. NULL can be passed to reset the root layer, in which case the
-@@ -390,6 +403,8 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
+@@ -525,6 +538,8 @@ class COMPOSITOR_EXPORT Compositor : public base::PowerSuspendObserver,
  
    std::unique_ptr<PendingBeginFrameArgs> pending_begin_frame_args_;
  
 +  CompositorDelegate* delegate_ = nullptr;
 +
    // The root of the Layer tree drawn by this compositor.
-   Layer* root_layer_ = nullptr;
+   raw_ptr<Layer> root_layer_ = nullptr;
  
diff --git a/src/patch/patches/web_contents_1257_1565.patch b/src/patch/patches/web_contents_1257_1565.patch
index 828a98a..9c9376b 100644
--- a/src/patch/patches/web_contents_1257_1565.patch
+++ b/src/patch/patches/web_contents_1257_1565.patch
@@ -1,41 +1,52 @@
 diff --git content/browser/web_contents/web_contents_impl.cc content/browser/web_contents/web_contents_impl.cc
-index 0fe5a498d698..9d5379624671 100644
+index 355f0d796d3c6..d8c047d6173e3 100644
 --- content/browser/web_contents/web_contents_impl.cc
 +++ content/browser/web_contents/web_contents_impl.cc
-@@ -2069,15 +2069,22 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
-   std::string unique_name;
-   frame_tree_.root()->SetFrameName(params.main_frame_name, unique_name);
+@@ -3348,6 +3348,12 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params,
+       params.main_frame_name, GetOpener(), primary_main_frame_policy,
+       base::UnguessableToken::Create());
  
--  WebContentsViewDelegate* delegate =
--      GetContentClient()->browser()->GetWebContentsViewDelegate(this);
 +  if (params.view && params.delegate_view) {
 +    view_.reset(params.view);
 +    render_view_host_delegate_view_ = params.delegate_view;
 +  }
- 
--  if (browser_plugin_guest_) {
--    view_.reset(new WebContentsViewChildFrame(
--        this, delegate, &render_view_host_delegate_view_));
--  } else {
--    view_.reset(CreateWebContentsView(this, delegate,
--                                      &render_view_host_delegate_view_));
-+  if (!view_) {
-+    WebContentsViewDelegate* delegate =
-+        GetContentClient()->browser()->GetWebContentsViewDelegate(this);
 +
-+    if (browser_plugin_guest_) {
-+      view_.reset(new WebContentsViewChildFrame(
-+          this, delegate, &render_view_host_delegate_view_));
-+    } else {
-+      view_.reset(CreateWebContentsView(this, delegate,
-+                                        &render_view_host_delegate_view_));
-+    }
++  if (!view_) {
+   std::unique_ptr<WebContentsViewDelegate> delegate =
+       GetContentClient()->browser()->GetWebContentsViewDelegate(this);
+ 
+@@ -3358,6 +3364,7 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params,
+     view_ = CreateWebContentsView(this, std::move(delegate),
+                                   &render_view_host_delegate_view_);
    }
++  }
    CHECK(render_view_host_delegate_view_);
    CHECK(view_.get());
-@@ -2897,6 +2904,15 @@ RenderFrameHostDelegate* WebContentsImpl::CreateNewWindow(
-   // objects.
-   create_params.renderer_initiated_creation = !is_new_browsing_instance;
+ 
+@@ -3548,6 +3555,9 @@ void WebContentsImpl::RenderWidgetCreated(
+   OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::RenderWidgetCreated",
+                         "render_widget_host", render_widget_host);
+   created_widgets_.insert(render_widget_host);
++
++  observers_.NotifyObservers(
++      &WebContentsObserver::RenderWidgetCreated, render_widget_host);
+ }
+ 
+ void WebContentsImpl::RenderWidgetDeleted(
+@@ -3868,6 +3878,10 @@ void WebContentsImpl::SetWindowShowState(ui::WindowShowState state) {
+ 
+ ui::WindowShowState WebContentsImpl::GetWindowShowState() {
+   aura::Window* window = GetTopLevelNativeWindow();
++  if (!window) {
++    // |window| will be nullptr with CEF windowless rendering.
++    return ui::SHOW_STATE_DEFAULT;
++  }
+   return wm::GetWindowState(window);
+ }
+ #endif
+@@ -4335,6 +4349,15 @@ FrameTree* WebContentsImpl::CreateNewWindow(
+     create_params.picture_in_picture_options = *(params.pip_options);
+   }
  
 +  if (delegate_) {
 +    delegate_->GetCustomWebContentsView(this,
@@ -46,64 +57,52 @@
 +                                        &create_params.delegate_view);
 +  }
 +
-   std::unique_ptr<WebContentsImpl> new_contents;
-   if (!is_guest) {
-     create_params.context = view_->GetNativeView();
-@@ -6370,6 +6386,9 @@ void WebContentsImpl::SetFocusedFrame(FrameTreeNode* node,
-     // This is an outermost WebContents.
-     SetAsFocusedWebContentsIfNecessary();
+   // Check whether there is an available prerendered page for this navigation if
+   // this is not for guest. If it exists, take WebContents pre-created for
+   // hosting the prerendered page instead of creating new WebContents.
+@@ -8342,6 +8365,9 @@ void WebContentsImpl::SetFocusedFrame(FrameTreeNode* node,
    }
+ 
+   CloseListenerManager::DidChangeFocusedFrame(this);
 +
-+  for (auto& observer : observers_)
-+    observer.OnFrameFocused(node->current_frame_host());
++  observers_.NotifyObservers(&WebContentsObserver::OnFrameFocused,
++                             node->current_frame_host());
  }
  
  void WebContentsImpl::DidCallFocus() {
-diff --git content/public/browser/web_contents.cc content/public/browser/web_contents.cc
-index d1d8ff84e1d2..e7cca94f8647 100644
---- content/public/browser/web_contents.cc
-+++ content/public/browser/web_contents.cc
-@@ -28,6 +28,8 @@ WebContents::CreateParams::CreateParams(BrowserContext* context,
-       renderer_initiated_creation(false),
-       desired_renderer_state(kOkayToHaveRendererProcess),
-       starting_sandbox_flags(blink::mojom::WebSandboxFlags::kNone),
-+      view(nullptr),
-+      delegate_view(nullptr),
-       is_never_visible(false) {}
- 
- WebContents::CreateParams::CreateParams(const CreateParams& other) = default;
 diff --git content/public/browser/web_contents.h content/public/browser/web_contents.h
-index b471bd1f78c6..19fb0c70ac94 100644
+index d3d0b0aab60e9..79938331d05f1 100644
 --- content/public/browser/web_contents.h
 +++ content/public/browser/web_contents.h
-@@ -84,9 +84,11 @@ class BrowserPluginGuestDelegate;
- class InterstitialPage;
+@@ -98,10 +98,12 @@ class BrowserContext;
+ class BrowserPluginGuestDelegate;
  class RenderFrameHost;
  class RenderViewHost;
 +class RenderViewHostDelegateView;
- class RenderWidgetHost;
  class RenderWidgetHostView;
+ class ScreenOrientationDelegate;
+ class SiteInstance;
  class WebContentsDelegate;
 +class WebContentsView;
  class WebUI;
- struct CustomContextMenuContext;
  struct DropData;
-@@ -214,6 +216,10 @@ class WebContents : public PageNavigator,
-     // Sandboxing flags set on the new WebContents.
-     blink::mojom::WebSandboxFlags starting_sandbox_flags;
+ struct MHTMLGenerationParams;
+@@ -244,6 +246,10 @@ class WebContents : public PageNavigator,
+     network::mojom::WebSandboxFlags starting_sandbox_flags =
+         network::mojom::WebSandboxFlags::kNone;
  
 +    // Optionally specify the view and delegate view.
-+    content::WebContentsView* view;
-+    content::RenderViewHostDelegateView* delegate_view;
++    content::WebContentsView* view = nullptr;
++    content::RenderViewHostDelegateView* delegate_view = nullptr;
 +
      // Value used to set the last time the WebContents was made active, this is
      // the value that'll be returned by GetLastActiveTime(). If this is left
      // default initialized then the value is not passed on to the WebContents
 diff --git content/public/browser/web_contents_delegate.h content/public/browser/web_contents_delegate.h
-index d10b0f458416..84e09b266d48 100644
+index 0fa12e6a5dd2e..6461d84aa3ac9 100644
 --- content/public/browser/web_contents_delegate.h
 +++ content/public/browser/web_contents_delegate.h
-@@ -59,10 +59,12 @@ class ColorChooser;
+@@ -59,9 +59,11 @@ class EyeDropperListener;
  class FileSelectListener;
  class JavaScriptDialogManager;
  class RenderFrameHost;
@@ -111,13 +110,12 @@
  class RenderWidgetHost;
  class SessionStorageNamespace;
  class SiteInstance;
- class WebContentsImpl;
 +class WebContentsView;
  struct ContextMenuParams;
  struct DropData;
  struct MediaPlayerWatchTime;
-@@ -327,6 +329,14 @@ class CONTENT_EXPORT WebContentsDelegate {
-       const std::string& partition_id,
+@@ -344,6 +346,14 @@ class CONTENT_EXPORT WebContentsDelegate {
+       const StoragePartitionConfig& partition_config,
        SessionStorageNamespace* session_storage_namespace);
  
 +  virtual void GetCustomWebContentsView(
@@ -132,10 +130,20 @@
    // typically happens when popups are created.
    virtual void WebContentsCreated(WebContents* source_contents,
 diff --git content/public/browser/web_contents_observer.h content/public/browser/web_contents_observer.h
-index 0b9a8c72a426..1c6ca61171cd 100644
+index c3d701fc68db0..f0be70560e6ea 100644
 --- content/public/browser/web_contents_observer.h
 +++ content/public/browser/web_contents_observer.h
-@@ -582,6 +582,10 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener {
+@@ -221,6 +221,9 @@ class CONTENT_EXPORT WebContentsObserver {
+   virtual void OnCaptureHandleConfigUpdate(
+       const blink::mojom::CaptureHandleConfig& config) {}
+ 
++  // This method is invoked when a RenderWidget is created.
++  virtual void RenderWidgetCreated(RenderWidgetHost* render_widget_host) {}
++
+   // This method is invoked when the `blink::WebView` of the current
+   // RenderViewHost is ready, e.g. because we recreated it after a crash.
+   virtual void RenderViewReady() {}
+@@ -825,6 +828,10 @@ class CONTENT_EXPORT WebContentsObserver {
    // WebContents has gained/lost focus.
    virtual void OnFocusChangedInPage(FocusedNodeDetails* details) {}
  
diff --git a/src/patch/patches/web_url_loader_cancel_1617042.patch b/src/patch/patches/web_url_loader_cancel_1617042.patch
deleted file mode 100644
index 43f93a8..0000000
--- a/src/patch/patches/web_url_loader_cancel_1617042.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-diff --git content/renderer/loader/web_url_loader_impl.h content/renderer/loader/web_url_loader_impl.h
-index 7b00faa7376d..62345e79ebac 100644
---- content/renderer/loader/web_url_loader_impl.h
-+++ content/renderer/loader/web_url_loader_impl.h
-@@ -88,6 +88,7 @@ class CONTENT_EXPORT WebURLLoaderImpl : public blink::WebURLLoader {
-       bool download_to_network_cache_only,
-       bool no_mime_sniffing,
-       blink::WebURLLoaderClient* client) override;
-+  void Cancel() override;
-   void SetDefersLoading(bool value) override;
-   void DidChangePriority(blink::WebURLRequest::Priority new_priority,
-                          int intra_priority_value) override;
-@@ -98,8 +99,6 @@ class CONTENT_EXPORT WebURLLoaderImpl : public blink::WebURLLoader {
-   class RequestPeerImpl;
-   class SinkPeer;
- 
--  void Cancel();
--
-   scoped_refptr<Context> context_;
- 
-   DISALLOW_COPY_AND_ASSIGN(WebURLLoaderImpl);
-diff --git third_party/blink/public/platform/web_url_loader.h third_party/blink/public/platform/web_url_loader.h
-index 7f1b0efcdff9..24b5561d24d8 100644
---- third_party/blink/public/platform/web_url_loader.h
-+++ third_party/blink/public/platform/web_url_loader.h
-@@ -91,6 +91,10 @@ class WebURLLoader {
-       bool no_mime_sniffing,
-       WebURLLoaderClient*) = 0;
- 
-+  // Cancels an asynchronous load.  This will appear as a load error to
-+  // the client.
-+  virtual void Cancel() {}
-+
-   // Suspends/resumes an asynchronous load.
-   virtual void SetDefersLoading(bool) = 0;
- 
diff --git a/src/patch/patches/webkit_plugin_info_2015.patch b/src/patch/patches/webkit_plugin_info_2015.patch
index 97640bd..8cc1b2c 100644
--- a/src/patch/patches/webkit_plugin_info_2015.patch
+++ b/src/patch/patches/webkit_plugin_info_2015.patch
@@ -1,21 +1,10 @@
-diff --git third_party/blink/public/mojom/plugins/plugin_registry.mojom third_party/blink/public/mojom/plugins/plugin_registry.mojom
-index ff7a8ed89e94..77f44956ff22 100644
---- third_party/blink/public/mojom/plugins/plugin_registry.mojom
-+++ third_party/blink/public/mojom/plugins/plugin_registry.mojom
-@@ -36,5 +36,5 @@ interface PluginRegistry {
-   //
-   // TODO(crbug.com/850278): We shouldn't rely on the renderer to tell us the main frame origin.
-   [Sync]
--  GetPlugins(bool refresh, url.mojom.Origin main_frame_origin) => (array<PluginInfo> plugins);
-+  GetPlugins(bool refresh, bool is_main_frame, url.mojom.Origin main_frame_origin) => (array<PluginInfo> plugins);
- };
 diff --git third_party/blink/public/platform/platform.h third_party/blink/public/platform/platform.h
-index c7bc68000ad0..45798fbcf914 100644
+index cfb8b2634af81..d7c120ea753c3 100644
 --- third_party/blink/public/platform/platform.h
 +++ third_party/blink/public/platform/platform.h
-@@ -667,6 +667,11 @@ class BLINK_PLATFORM_EXPORT Platform {
-   // runs during Chromium's build step).
-   virtual bool IsTakingV8ContextSnapshot() { return false; }
+@@ -780,6 +780,11 @@ class BLINK_PLATFORM_EXPORT Platform {
+   }
+ #endif
  
 +  // DevTools ------------------------------------------------------------
 +
@@ -23,52 +12,21 @@
 +  virtual void DevToolsAgentDetached() {}
 +
   private:
-   static void InitializeCommon(Platform* platform,
-                                std::unique_ptr<Thread> main_thread);
-diff --git third_party/blink/renderer/core/dom/document_init.cc third_party/blink/renderer/core/dom/document_init.cc
-index c9c761dd34e6..75afc167a60e 100644
---- third_party/blink/renderer/core/dom/document_init.cc
-+++ third_party/blink/renderer/core/dom/document_init.cc
-@@ -200,11 +200,11 @@ DocumentInit& DocumentInit::WithTypeFrom(const String& type) {
-     if (GetFrame()->IsMainFrame()) {
-       scoped_refptr<const SecurityOrigin> origin =
-           SecurityOrigin::Create(Url());
--      plugin_data = GetFrame()->GetPage()->GetPluginData(origin.get());
-+      plugin_data = GetFrame()->GetPage()->GetPluginData(true, origin.get());
-     } else {
-       auto* top_security_origin =
-           GetFrame()->Tree().Top().GetSecurityContext()->GetSecurityOrigin();
--      plugin_data = GetFrame()->GetPage()->GetPluginData(top_security_origin);
-+      plugin_data = GetFrame()->GetPage()->GetPluginData(false, top_security_origin);
-     }
-   }
- 
-diff --git third_party/blink/renderer/core/frame/local_frame.cc third_party/blink/renderer/core/frame/local_frame.cc
-index 3c78d0089938..2f7cb6d27eea 100644
---- third_party/blink/renderer/core/frame/local_frame.cc
-+++ third_party/blink/renderer/core/frame/local_frame.cc
-@@ -1331,7 +1331,7 @@ WebContentSettingsClient* LocalFrame::GetContentSettingsClient() {
- PluginData* LocalFrame::GetPluginData() const {
-   if (!Loader().AllowPlugins(kNotAboutToInstantiatePlugin))
-     return nullptr;
--  return GetPage()->GetPluginData(
-+  return GetPage()->GetPluginData(IsMainFrame(),
-       Tree().Top().GetSecurityContext()->GetSecurityOrigin());
- }
- 
+   static void InitializeMainThreadCommon(
+       Platform* platform,
 diff --git third_party/blink/renderer/core/inspector/devtools_session.cc third_party/blink/renderer/core/inspector/devtools_session.cc
-index 4ee6a0ea5689..8b6d5b1a6e06 100644
+index 01c2f360adbb0..92ea44b41820e 100644
 --- third_party/blink/renderer/core/inspector/devtools_session.cc
 +++ third_party/blink/renderer/core/inspector/devtools_session.cc
-@@ -8,6 +8,7 @@
- #include <utility>
- #include <vector>
+@@ -10,6 +10,7 @@
  
+ #include "base/task/sequenced_task_runner.h"
+ #include "base/task/single_thread_task_runner.h"
 +#include "third_party/blink/public/platform/platform.h"
  #include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
  #include "third_party/blink/renderer/core/frame/local_frame.h"
  #include "third_party/blink/renderer/core/inspector/devtools_agent.h"
-@@ -142,6 +143,7 @@ DevToolsSession::DevToolsSession(
+@@ -165,6 +166,7 @@ DevToolsSession::DevToolsSession(
      for (wtf_size_t i = 0; i < agents_.size(); i++)
        agents_[i]->Restore();
    }
@@ -76,152 +34,11 @@
  }
  
  DevToolsSession::~DevToolsSession() {
-@@ -182,6 +184,7 @@ void DevToolsSession::Detach() {
+@@ -210,6 +212,7 @@ void DevToolsSession::Detach() {
    agents_.clear();
    v8_session_.reset();
    agent_->client_->DebuggerTaskFinished();
 +  Platform::Current()->DevToolsAgentDetached();
  }
  
- void DevToolsSession::DispatchProtocolCommand(
-diff --git third_party/blink/renderer/core/page/page.cc third_party/blink/renderer/core/page/page.cc
-index 50e76a0e0a63..e3e7dcaa5352 100644
---- third_party/blink/renderer/core/page/page.cc
-+++ third_party/blink/renderer/core/page/page.cc
-@@ -194,7 +194,8 @@ Page::Page(PageClients& page_clients)
-           MakeGarbageCollected<OverscrollController>(GetVisualViewport(),
-                                                      GetChromeClient())),
-       link_highlight_(MakeGarbageCollected<LinkHighlight>(*this)),
--      plugin_data_(nullptr),
-+      plugin_data_main_frame_(nullptr),
-+      plugin_data_sub_frame_(nullptr),
-       // TODO(pdr): Initialize |validation_message_client_| lazily.
-       validation_message_client_(
-           MakeGarbageCollected<ValidationMessageClientImpl>(*this)),
-@@ -379,21 +380,41 @@ void Page::InitialStyleChanged() {
-   }
- }
- 
--PluginData* Page::GetPluginData(const SecurityOrigin* main_frame_origin) {
--  if (!plugin_data_)
--    plugin_data_ = MakeGarbageCollected<PluginData>();
-+PluginData* Page::GetPluginData(bool is_main_frame,
-+                                const SecurityOrigin* main_frame_origin) {
-+  if (is_main_frame) {
-+    if (!plugin_data_main_frame_)
-+      plugin_data_main_frame_ = MakeGarbageCollected<PluginData>();
- 
--  if (!plugin_data_->Origin() ||
--      !main_frame_origin->IsSameOriginWith(plugin_data_->Origin()))
--    plugin_data_->UpdatePluginList(main_frame_origin);
- 
--  return plugin_data_.Get();
-+    if (!plugin_data_main_frame_->Origin() ||
-+        !main_frame_origin->IsSameOriginWith(
-+            plugin_data_main_frame_->Origin())) {
-+      plugin_data_main_frame_->UpdatePluginList(true, main_frame_origin);
-+    }
-+
-+    return plugin_data_main_frame_.Get();
-+  } else {
-+    if (!plugin_data_sub_frame_)
-+      plugin_data_sub_frame_ = MakeGarbageCollected<PluginData>();
-+
-+    if (!plugin_data_sub_frame_->Origin() ||
-+        !main_frame_origin->IsSameOriginWith(
-+            plugin_data_sub_frame_->Origin())) {
-+      plugin_data_sub_frame_->UpdatePluginList(false, main_frame_origin);
-+    }
-+
-+    return plugin_data_sub_frame_.Get();
-+  }
- }
- 
- void Page::ResetPluginData() {
-   for (Page* page : AllPages()) {
--    if (page->plugin_data_) {
--      page->plugin_data_->ResetPluginData();
-+    if (page->plugin_data_main_frame_ || page->plugin_data_sub_frame_) {
-+      if (page->plugin_data_main_frame_)
-+        page->plugin_data_main_frame_->ResetPluginData();
-+      if (page->plugin_data_sub_frame_)
-+        page->plugin_data_sub_frame_->ResetPluginData();
-       page->NotifyPluginsChanged();
-     }
-   }
-@@ -906,7 +927,8 @@ void Page::Trace(Visitor* visitor) {
-   visitor->Trace(link_highlight_);
-   visitor->Trace(spatial_navigation_controller_);
-   visitor->Trace(main_frame_);
--  visitor->Trace(plugin_data_);
-+  visitor->Trace(plugin_data_main_frame_);
-+  visitor->Trace(plugin_data_sub_frame_);
-   visitor->Trace(validation_message_client_);
-   visitor->Trace(agent_metrics_collector_);
-   visitor->Trace(plugins_changed_observers_);
-diff --git third_party/blink/renderer/core/page/page.h third_party/blink/renderer/core/page/page.h
-index 1074204dbfb6..e00ef8e7393a 100644
---- third_party/blink/renderer/core/page/page.h
-+++ third_party/blink/renderer/core/page/page.h
-@@ -144,7 +144,8 @@ class CORE_EXPORT Page final : public GarbageCollected<Page>,
-   ViewportDescription GetViewportDescription() const;
- 
-   // Returns the plugin data associated with |main_frame_origin|.
--  PluginData* GetPluginData(const SecurityOrigin* main_frame_origin);
-+  PluginData* GetPluginData(bool is_main_frame,
-+                            const SecurityOrigin* main_frame_origin);
- 
-   // Resets the plugin data for all pages in the renderer process and notifies
-   // PluginsChangedObservers.
-@@ -404,7 +405,8 @@ class CORE_EXPORT Page final : public GarbageCollected<Page>,
-   const Member<LinkHighlight> link_highlight_;
-   Member<SpatialNavigationController> spatial_navigation_controller_;
- 
--  Member<PluginData> plugin_data_;
-+  Member<PluginData> plugin_data_main_frame_;
-+  Member<PluginData> plugin_data_sub_frame_;
- 
-   Member<ValidationMessageClient> validation_message_client_;
- 
-diff --git third_party/blink/renderer/core/page/plugin_data.cc third_party/blink/renderer/core/page/plugin_data.cc
-index 9b6a945105c6..63c7c43114bc 100644
---- third_party/blink/renderer/core/page/plugin_data.cc
-+++ third_party/blink/renderer/core/page/plugin_data.cc
-@@ -91,10 +91,12 @@ void PluginData::RefreshBrowserSidePluginCache() {
-   Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
-       registry.BindNewPipeAndPassReceiver());
-   Vector<mojom::blink::PluginInfoPtr> plugins;
--  registry->GetPlugins(true, SecurityOrigin::CreateUniqueOpaque(), &plugins);
-+  registry->GetPlugins(true, true, SecurityOrigin::CreateUniqueOpaque(),
-+                       &plugins);
- }
- 
--void PluginData::UpdatePluginList(const SecurityOrigin* main_frame_origin) {
-+void PluginData::UpdatePluginList(bool is_main_frame,
-+                                  const SecurityOrigin* main_frame_origin) {
-   ResetPluginData();
-   main_frame_origin_ = main_frame_origin;
- 
-@@ -102,7 +104,7 @@ void PluginData::UpdatePluginList(const SecurityOrigin* main_frame_origin) {
-   Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
-       registry.BindNewPipeAndPassReceiver());
-   Vector<mojom::blink::PluginInfoPtr> plugins;
--  registry->GetPlugins(false, main_frame_origin_, &plugins);
-+  registry->GetPlugins(false, is_main_frame, main_frame_origin_, &plugins);
-   for (const auto& plugin : plugins) {
-     auto* plugin_info = MakeGarbageCollected<PluginInfo>(
-         plugin->name, FilePathToWebString(plugin->filename),
-diff --git third_party/blink/renderer/core/page/plugin_data.h third_party/blink/renderer/core/page/plugin_data.h
-index d0260f9f6b1b..675ba5a7c893 100644
---- third_party/blink/renderer/core/page/plugin_data.h
-+++ third_party/blink/renderer/core/page/plugin_data.h
-@@ -97,7 +97,8 @@ class CORE_EXPORT PluginData final : public GarbageCollected<PluginData> {
-   const HeapVector<Member<PluginInfo>>& Plugins() const { return plugins_; }
-   const HeapVector<Member<MimeClassInfo>>& Mimes() const { return mimes_; }
-   const SecurityOrigin* Origin() const { return main_frame_origin_.get(); }
--  void UpdatePluginList(const SecurityOrigin* main_frame_origin);
-+  void UpdatePluginList(bool is_main_frame,
-+                        const SecurityOrigin* main_frame_origin);
-   void ResetPluginData();
- 
-   bool SupportsMimeType(const String& mime_type) const;
+ void DevToolsSession::DetachFromV8() {
diff --git a/src/patch/patches/webkit_pointer_event_781966.patch b/src/patch/patches/webkit_pointer_event_781966.patch
deleted file mode 100644
index 476a576..0000000
--- a/src/patch/patches/webkit_pointer_event_781966.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git third_party/blink/renderer/core/input/pointer_event_manager.cc third_party/blink/renderer/core/input/pointer_event_manager.cc
-index 6a68b124069d..56d4a2bcad3c 100644
---- third_party/blink/renderer/core/input/pointer_event_manager.cc
-+++ third_party/blink/renderer/core/input/pointer_event_manager.cc
-@@ -310,7 +310,7 @@ void PointerEventManager::HandlePointerInterruption(
-   for (auto pointer_event : canceled_pointer_events) {
-     // If we are sending a pointercancel we have sent the pointerevent to some
-     // target before.
--    DCHECK(element_under_pointer_.Contains(pointer_event->pointerId()));
-+    // DCHECK(element_under_pointer_.Contains(pointer_event->pointerId()));
-     Element* target =
-         element_under_pointer_.at(pointer_event->pointerId()).target;
- 
diff --git a/src/patch/patches/webkit_popups.patch b/src/patch/patches/webkit_popups.patch
index 6734c86..7ecd0c5 100644
--- a/src/patch/patches/webkit_popups.patch
+++ b/src/patch/patches/webkit_popups.patch
@@ -1,20 +1,20 @@
 diff --git third_party/blink/public/web/web_view.h third_party/blink/public/web/web_view.h
-index 406c19b10b2e..28d5336e5ab6 100644
+index 8a18ecf567cd3..9697d43bbbfb9 100644
 --- third_party/blink/public/web/web_view.h
 +++ third_party/blink/public/web/web_view.h
-@@ -372,6 +372,7 @@ class WebView {
+@@ -344,6 +344,7 @@ class BLINK_EXPORT WebView {
  
    // Sets whether select popup menus should be rendered by the browser.
-   BLINK_EXPORT static void SetUseExternalPopupMenus(bool);
+   static void SetUseExternalPopupMenus(bool);
 +  virtual void SetUseExternalPopupMenusThisInstance(bool) = 0;
  
    // Cancels and hides the current popup (datetime, select...) if any.
    virtual void CancelPagePopup() = 0;
 diff --git third_party/blink/renderer/core/exported/web_view_impl.cc third_party/blink/renderer/core/exported/web_view_impl.cc
-index 43fc2bb2de69..562952a05f0c 100644
+index 866af04a935f8..0223a58e5d475 100644
 --- third_party/blink/renderer/core/exported/web_view_impl.cc
 +++ third_party/blink/renderer/core/exported/web_view_impl.cc
-@@ -216,8 +216,13 @@ void WebView::SetUseExternalPopupMenus(bool use_external_popup_menus) {
+@@ -249,8 +249,13 @@ void WebView::SetUseExternalPopupMenus(bool use_external_popup_menus) {
    g_should_use_external_popup_menus = use_external_popup_menus;
  }
  
@@ -30,19 +30,19 @@
  }
  
  namespace {
-@@ -280,6 +285,7 @@ WebViewImpl::WebViewImpl(WebViewClient* client,
+@@ -584,6 +589,7 @@ WebViewImpl::WebViewImpl(
        chrome_client_(MakeGarbageCollected<ChromeClientImpl>(this)),
        minimum_zoom_level_(PageZoomFactorToZoomLevel(kMinimumPageZoomFactor)),
        maximum_zoom_level_(PageZoomFactorToZoomLevel(kMaximumPageZoomFactor)),
 +      should_use_external_popup_menus_(g_should_use_external_popup_menus),
        does_composite_(does_composite),
        fullscreen_controller_(std::make_unique<FullscreenController>(this)),
-       receiver_(this,
+       page_base_background_color_(
 diff --git third_party/blink/renderer/core/exported/web_view_impl.h third_party/blink/renderer/core/exported/web_view_impl.h
-index 60cfa746367a..3329a3f4a9b1 100644
+index 6a180620e00c7..09d11bfd3c83f 100644
 --- third_party/blink/renderer/core/exported/web_view_impl.h
 +++ third_party/blink/renderer/core/exported/web_view_impl.h
-@@ -118,7 +118,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
+@@ -137,7 +137,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
    static HashSet<WebViewImpl*>& AllInstances();
    // Returns true if popup menus should be rendered by the browser, false if
    // they should be rendered by WebKit (which is the default).
@@ -52,20 +52,20 @@
  
    // Returns whether frames under this WebView are backed by a compositor.
    bool does_composite() const { return does_composite_; }
-@@ -628,6 +629,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
+@@ -853,6 +854,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
    float fake_page_scale_animation_page_scale_factor_ = 0.f;
    bool fake_page_scale_animation_use_anchor_ = false;
  
 +  bool should_use_external_popup_menus_;
 +
    float compositor_device_scale_factor_override_ = 0.f;
-   TransformationMatrix device_emulation_transform_;
+   gfx::Transform device_emulation_transform_;
  
 diff --git third_party/blink/renderer/core/page/chrome_client_impl.cc third_party/blink/renderer/core/page/chrome_client_impl.cc
-index 1b430137301a..ee21b1e7bf17 100644
+index 04f2127c5ebe1..0d615cccdfe69 100644
 --- third_party/blink/renderer/core/page/chrome_client_impl.cc
 +++ third_party/blink/renderer/core/page/chrome_client_impl.cc
-@@ -819,7 +819,7 @@ bool ChromeClientImpl::HasOpenedPopup() const {
+@@ -917,7 +917,7 @@ bool ChromeClientImpl::HasOpenedPopup() const {
  PopupMenu* ChromeClientImpl::OpenPopupMenu(LocalFrame& frame,
                                             HTMLSelectElement& select) {
    NotifyPopupOpeningObservers();
diff --git a/src/patch/patches/webkit_runtime_enabled_features.patch b/src/patch/patches/webkit_runtime_enabled_features.patch
new file mode 100644
index 0000000..33e7cc6
--- /dev/null
+++ b/src/patch/patches/webkit_runtime_enabled_features.patch
@@ -0,0 +1,21 @@
+diff --git third_party/blink/renderer/build/scripts/templates/runtime_enabled_features.h.tmpl third_party/blink/renderer/build/scripts/templates/runtime_enabled_features.h.tmpl
+index 32ca8183f6501..fb38785835fa0 100644
+--- third_party/blink/renderer/build/scripts/templates/runtime_enabled_features.h.tmpl
++++ third_party/blink/renderer/build/scripts/templates/runtime_enabled_features.h.tmpl
+@@ -13,6 +13,8 @@
+ #include "third_party/blink/renderer/platform/platform_export.h"
+ #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+ 
++class AlloyContentRendererClient;
++
+ #define ASSERT_ORIGIN_TRIAL(feature) \
+   static_assert(std::is_same<decltype(::blink::RuntimeEnabledFeatures::     \
+                                           feature##EnabledByRuntimeFlag()), \
+@@ -117,6 +119,7 @@ class PLATFORM_EXPORT RuntimeEnabledFeatures : public RuntimeEnabledFeaturesBase
+   // protected section of RuntimeEnabledFeaturesBase. Normally, unit tests
+   // should use the ScopedFeatureNameForTest classes defined in
+   // platform/testing/runtime_enabled_features_test_helpers.h.
++  friend class ::AlloyContentRendererClient;
+   friend class DevToolsEmulator;
+   friend class InternalRuntimeFlags;
+   friend class V8ContextSnapshotImpl;
diff --git a/src/patch/patches/webui_2037.patch b/src/patch/patches/webui_2037.patch
index 3e7f317..ed10445 100644
--- a/src/patch/patches/webui_2037.patch
+++ b/src/patch/patches/webui_2037.patch
@@ -1,50 +1,48 @@
 diff --git chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
-index 29953fdc7c55..89dd4e61f66f 100644
+index a7ab5cf0c3cd0..8a8014df43457 100644
 --- chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
 +++ chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
-@@ -21,6 +21,7 @@
+@@ -18,10 +18,12 @@
+ #include "base/strings/string_util.h"
+ #include "base/system/sys_info.h"
  #include "base/task/thread_pool.h"
++#include "base/threading/thread_restrictions.h"
+ #include "base/time/time.h"
  #include "build/branding_buildflags.h"
  #include "build/build_config.h"
-+#include "cef/libcef/features/features.h"
+ #include "build/chromeos_buildflags.h"
++#include "cef/libcef/features/runtime.h"
  #include "chrome/browser/browser_process.h"
- #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h"
- #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h"
-@@ -28,6 +29,7 @@
- #include "chrome/browser/profiles/profile_manager.h"
- #include "chrome/browser/sync/profile_sync_service_factory.h"
- #include "chrome/common/channel_info.h"
-+#include "chrome/common/chrome_switches.h"
- #include "components/prefs/pref_service.h"
- #include "components/sync/driver/about_sync_util.h"
- #include "components/sync/driver/sync_service.h"
-@@ -274,7 +276,11 @@ void ChromeInternalLogSource::Fetch(SysLogsSourceCallback callback) {
+ #include "chrome/browser/extensions/chrome_content_browser_client_extensions_part.h"
+ #include "chrome/browser/google/google_brand.h"
+@@ -422,7 +424,11 @@ void ChromeInternalLogSource::Fetch(SysLogsSourceCallback callback) {
    response->emplace(kOsVersionTag, os_version);
  #endif
  
-+#if !BUILDFLAG(ENABLE_CEF)
-+  // CEF should avoid loading ProfileSyncServiceFactory which depends on a lot
-+  // of unnecessary Chrome-specific factories.
-   PopulateSyncLogs(response.get());
-+#endif
+-  PopulateSyncLogs(response.get());
++  if (!cef::IsAlloyRuntimeEnabled()) {
++    // Avoid loading ProfileSyncServiceFactory which depends on a lot of
++    // unnecessary Chrome-specific factories.
++    PopulateSyncLogs(response.get());
++  }
    PopulateExtensionInfoLogs(response.get());
    PopulatePowerApiLogs(response.get());
-   PopulateDataReductionProxyLogs(response.get());
-@@ -364,6 +370,12 @@ void ChromeInternalLogSource::PopulateExtensionInfoLogs(
+ #if BUILDFLAG(IS_WIN)
+@@ -504,8 +510,12 @@ void ChromeInternalLogSource::PopulateExtensionInfoLogs(
    if (!profile)
      return;
  
-+  // CEF should avoid accessing ExtensionRegistry when extensions are disabled.
-+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-+      switches::kDisableExtensions)) {
-+    return;
-+  }
-+
++  // May be nullptr if using CEF Alloy with extensions disabled.
    extensions::ExtensionRegistry* extension_registry =
        extensions::ExtensionRegistry::Get(profile);
++  if (!extension_registry)
++    return;
++
    std::string extensions_list;
-@@ -453,6 +465,8 @@ void ChromeInternalLogSource::PopulateArcPolicyStatus(
- #if defined(OS_WIN)
+   for (const scoped_refptr<const extensions::Extension>& extension :
+        extension_registry->enabled_extensions()) {
+@@ -606,6 +616,8 @@ void ChromeInternalLogSource::PopulateOnboardingTime(
+ #if BUILDFLAG(IS_WIN)
  void ChromeInternalLogSource::PopulateUsbKeyboardDetected(
      SystemLogsResponse* response) {
 +  // The below call may result in some DLLs being loaded.
@@ -53,27 +51,27 @@
    bool result =
        base::win::IsKeyboardPresentOnSlate(ui::GetHiddenWindow(), &reason);
 diff --git chrome/browser/memory_details.cc chrome/browser/memory_details.cc
-index d42895d9db3f..74a6d407bbcd 100644
+index 1cf8e8840a22b..79be0f2825288 100644
 --- chrome/browser/memory_details.cc
 +++ chrome/browser/memory_details.cc
-@@ -18,6 +18,7 @@
- #include "base/task/thread_pool.h"
- #include "build/build_config.h"
- #include "chrome/browser/profiles/profile.h"
-+#include "chrome/common/chrome_switches.h"
- #include "components/nacl/common/nacl_process_type.h"
- #include "components/strings/grit/components_strings.h"
- #include "content/public/browser/browser_child_process_host_iterator.h"
-@@ -250,8 +251,11 @@ void MemoryDetails::CollectChildInfoOnUIThread() {
- 
- #if BUILDFLAG(ENABLE_EXTENSIONS)
-     // Determine if this is an extension process.
-+    // CEF should avoid accessing ExtensionRegistry when extensions are disabled.
-     bool process_is_for_extensions = false;
--    if (render_process_host) {
-+    if (render_process_host &&
-+        !base::CommandLine::ForCurrentProcess()->HasSwitch(
-+            switches::kDisableExtensions)) {
+@@ -298,9 +298,11 @@ void MemoryDetails::CollectChildInfoOnUIThread() {
+                 render_process_host->GetBrowserContext())) {
        content::BrowserContext* context =
            render_process_host->GetBrowserContext();
++
++      // May be nullptr if using CEF Alloy with extensions disabled.
        extensions::ExtensionRegistry* extension_registry =
+           extensions::ExtensionRegistry::Get(context);
+-      DCHECK(extension_registry);
++      if (extension_registry) {
+       extension_set = &extension_registry->enabled_extensions();
+       extensions::ProcessMap* process_map =
+           extensions::ProcessMap::Get(context);
+@@ -317,6 +319,7 @@ void MemoryDetails::CollectChildInfoOnUIThread() {
+           break;
+         }
+       }
++      }
+     }
+ #endif
+ 
diff --git a/src/patch/patches/webview_plugin_2020.patch b/src/patch/patches/webview_plugin_2020.patch
deleted file mode 100644
index 66d888f..0000000
--- a/src/patch/patches/webview_plugin_2020.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git chrome/app/generated_resources.grd chrome/app/generated_resources.grd
-index 288c442298f6..27e2608d1531 100644
---- chrome/app/generated_resources.grd
-+++ chrome/app/generated_resources.grd
-@@ -4973,7 +4973,7 @@ Keep your key file in a safe place. You will need it to create new versions of y
-         </message>
-       </if>
-       <message name="IDS_PLUGIN_BLOCKED_BY_POLICY" desc="The placeholder text for a plugin blocked by enterprise policy.">
--        <ph name="PLUGIN_NAME">$1<ex>Flash</ex></ph> is blocked by enterprise policy
-+        <ph name="PLUGIN_NAME">$1<ex>Flash</ex></ph> is not allowed
-       </message>
-       <message name="IDS_PLUGIN_BLOCKED_NO_LOADING" desc="The placeholder text for a blocked plugin that cannot be manually loaded by the user.">
-         <ph name="PLUGIN_NAME">$1<ex>Flash</ex></ph> is blocked
diff --git a/src/patch/patches/win_base_msvc_sandbox.patch b/src/patch/patches/win_base_msvc_sandbox.patch
deleted file mode 100644
index 7f14997..0000000
--- a/src/patch/patches/win_base_msvc_sandbox.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-diff --git base/values.cc base/values.cc
-index ecca445840a8..9cde6ece0000 100644
---- base/values.cc
-+++ base/values.cc
-@@ -24,20 +24,6 @@
- 
- namespace base {
- 
--// base::Value must be standard layout to guarantee that writing to
--// |bool_type_| then reading |type_| is defined behaviour. See:
--//
--// [class.union]:
--//   If a standard-layout union contains several standard-layout structs that
--//   share a common initial sequence (9.2), and if an object of this
--//   standard-layout union type contains one of the standard-layout structs,
--//   it is permitted to inspect the common initial sequence of any of
--//   standard-layout struct members;
--//
--static_assert(std::is_standard_layout<Value>::value,
--              "base::Value should be a standard-layout C++ class in order "
--              "to avoid undefined behaviour in its implementation!");
--
- static_assert(sizeof(Value::DoubleStorage) == sizeof(double),
-               "The double and DoubleStorage types should have the same size");
- 
diff --git a/src/patch/patches/win_cpp17_msvc_sandbox_2819.patch b/src/patch/patches/win_cpp17_msvc_sandbox_2819.patch
index b99a07a..6361d3f 100644
--- a/src/patch/patches/win_cpp17_msvc_sandbox_2819.patch
+++ b/src/patch/patches/win_cpp17_msvc_sandbox_2819.patch
@@ -1,5 +1,5 @@
 diff --git base/third_party/double_conversion/BUILD.gn base/third_party/double_conversion/BUILD.gn
-index 0083efdcd9c8..6f647c31e28a 100644
+index 8380f58d995bc..c0755bf9870b4 100644
 --- base/third_party/double_conversion/BUILD.gn
 +++ base/third_party/double_conversion/BUILD.gn
 @@ -9,6 +9,11 @@ config("config") {
@@ -15,10 +15,10 @@
  
  static_library("double_conversion") {
 diff --git base/win/BUILD.gn base/win/BUILD.gn
-index 33a38267a658..0d54f224d31c 100644
+index d915a9320750c..5661652c9b2da 100644
 --- base/win/BUILD.gn
 +++ base/win/BUILD.gn
-@@ -31,4 +31,7 @@ static_library("pe_image") {
+@@ -33,4 +33,7 @@ static_library("pe_image") {
      "pe_image.cc",
      "pe_image.h",
    ]
diff --git a/src/patch/patches/win_rt_2274.patch b/src/patch/patches/win_rt_2274.patch
deleted file mode 100644
index b4a4123..0000000
--- a/src/patch/patches/win_rt_2274.patch
+++ /dev/null
@@ -1,17 +0,0 @@
-diff --git services/service_manager/sandbox/win/sandbox_win.cc services/service_manager/sandbox/win/sandbox_win.cc
-index c369dde34758..1c2dea10764d 100644
---- services/service_manager/sandbox/win/sandbox_win.cc
-+++ services/service_manager/sandbox/win/sandbox_win.cc
-@@ -939,8 +939,11 @@ sandbox::ResultCode SandboxWin::StartSandboxedProcess(
-   }
-   // TODO(wfh): Relax strict handle checks for network process until root cause
-   // for this crash can be resolved. See https://crbug.com/939590.
--  if (sandbox_type != SandboxType::kNetwork)
-+  if (!launcher_process_command_line.HasSwitch("win-rt-app") &&
-+      sandbox_type != SandboxType::kNetwork) {
-+    // Don't enable this mitigation in WinRT apps. See issue #2274.
-     mitigations |= sandbox::MITIGATION_STRICT_HANDLE_CHECKS;
-+  }
- 
-   result = policy->SetDelayedProcessMitigations(mitigations);
-   if (result != sandbox::SBOX_ALL_OK)
diff --git a/src/patch/patches/win_sandbox_3210.patch b/src/patch/patches/win_sandbox_3210.patch
new file mode 100644
index 0000000..f6eb79a
--- /dev/null
+++ b/src/patch/patches/win_sandbox_3210.patch
@@ -0,0 +1,18 @@
+diff --git sandbox/policy/win/sandbox_win.cc sandbox/policy/win/sandbox_win.cc
+index fc31388dc3232..c0e303c816042 100644
+--- sandbox/policy/win/sandbox_win.cc
++++ sandbox/policy/win/sandbox_win.cc
+@@ -997,6 +997,13 @@ ResultCode SandboxWin::StartSandboxedProcess(
+     const base::HandlesToInheritVector& handles_to_inherit,
+     SandboxDelegate* delegate,
+     base::Process* process) {
++  // Will be nullptr if SandboxInterfaceInfo was not initialized by the CEF
++  // client, meaning that the sandbox is implicitly disabled.
++  if (!g_broker_services) {
++    return LaunchWithoutSandbox(cmd_line, handles_to_inherit, delegate,
++                                process);
++  }
++
+   const base::ElapsedTimer timer;
+ 
+   // Avoid making a policy if we won't use it.
diff --git a/src/patch/patches/win_sandbox_policy.patch b/src/patch/patches/win_sandbox_policy.patch
new file mode 100644
index 0000000..fa02b41
--- /dev/null
+++ b/src/patch/patches/win_sandbox_policy.patch
@@ -0,0 +1,94 @@
+diff --git sandbox/win/src/sandbox_policy.h sandbox/win/src/sandbox_policy.h
+index daf2af3079a2a..00197897c3c73 100644
+--- sandbox/win/src/sandbox_policy.h
++++ sandbox/win/src/sandbox_policy.h
+@@ -281,7 +281,7 @@ class [[clang::lto_visibility_public]] TargetPolicy {
+   // Adds a blob of data that will be made available in the child early in
+   // startup via sandbox::GetDelegateData(). The contents of this data should
+   // not vary between children with the same TargetConfig().
+-  virtual void AddDelegateData(base::span<const uint8_t> data) = 0;
++  virtual void AddDelegateData(base::span<uint8_t> data) = 0;
+ };
+ 
+ }  // namespace sandbox
+diff --git sandbox/win/src/sandbox_policy_base.cc sandbox/win/src/sandbox_policy_base.cc
+index 9b4f763a894bd..4ba0a7ab4de60 100644
+--- sandbox/win/src/sandbox_policy_base.cc
++++ sandbox/win/src/sandbox_policy_base.cc
+@@ -190,12 +190,12 @@ PolicyGlobal* ConfigBase::policy() {
+   return policy_;
+ }
+ 
+-absl::optional<base::span<const uint8_t>> ConfigBase::policy_span() {
++absl::optional<base::span<uint8_t>> ConfigBase::policy_span() {
+   if (policy_) {
+     // Note: this is not policy().data_size as that relates to internal data,
+     // not the entire allocated policy area.
+-    return base::span<const uint8_t>(reinterpret_cast<uint8_t*>(policy_.get()),
+-                                     kPolMemSize);
++    return base::span<uint8_t>(reinterpret_cast<uint8_t*>(policy_.get()),
++                               kPolMemSize);
+   }
+   return absl::nullopt;
+ }
+@@ -783,19 +783,19 @@ bool PolicyBase::SetupHandleCloser(TargetProcess& target) {
+   return handle_closer->InitializeTargetHandles(target);
+ }
+ 
+-absl::optional<base::span<const uint8_t>> PolicyBase::delegate_data_span() {
++absl::optional<base::span<uint8_t>> PolicyBase::delegate_data_span() {
+   if (delegate_data_) {
+     return base::make_span(*delegate_data_);
+   }
+   return absl::nullopt;
+ }
+ 
+-void PolicyBase::AddDelegateData(base::span<const uint8_t> data) {
++void PolicyBase::AddDelegateData(base::span<uint8_t> data) {
+   CHECK(data.size() > 0u);
+   // Can only set this once - as there is only one region sent to the child.
+   CHECK(!delegate_data_);
+   delegate_data_ =
+-      std::make_unique<std::vector<const uint8_t>>(data.begin(), data.end());
++      std::make_unique<std::vector<uint8_t>>(data.begin(), data.end());
+ }
+ 
+ }  // namespace sandbox
+diff --git sandbox/win/src/sandbox_policy_base.h sandbox/win/src/sandbox_policy_base.h
+index 9e6738f676d07..a3525e0cfe283 100644
+--- sandbox/win/src/sandbox_policy_base.h
++++ sandbox/win/src/sandbox_policy_base.h
+@@ -115,7 +115,7 @@ class ConfigBase final : public TargetConfig {
+ 
+   // Should only be called once the object is configured.
+   PolicyGlobal* policy();
+-  absl::optional<base::span<const uint8_t>> policy_span();
++  absl::optional<base::span<uint8_t>> policy_span();
+   std::vector<std::wstring>& blocklisted_dlls();
+   AppContainerBase* app_container();
+   IntegrityLevel integrity_level() { return integrity_level_; }
+@@ -175,7 +175,7 @@ class PolicyBase final : public TargetPolicy {
+   ResultCode SetStdoutHandle(HANDLE handle) override;
+   ResultCode SetStderrHandle(HANDLE handle) override;
+   void AddHandleToShare(HANDLE handle) override;
+-  void AddDelegateData(base::span<const uint8_t> data) override;
++  void AddDelegateData(base::span<uint8_t> data) override;
+ 
+   // Creates a Job object with the level specified in a previous call to
+   // SetJobLevel().
+@@ -237,13 +237,13 @@ class PolicyBase final : public TargetPolicy {
+   // time.
+ 
+   // Returns nullopt if no data has been set, or a view into the data.
+-  absl::optional<base::span<const uint8_t>> delegate_data_span();
++  absl::optional<base::span<uint8_t>> delegate_data_span();
+ 
+   // The user-defined global policy settings.
+   HANDLE stdout_handle_;
+   HANDLE stderr_handle_;
+   // An opaque blob of data the delegate uses to prime any pre-sandbox hooks.
+-  std::unique_ptr<std::vector<const uint8_t>> delegate_data_;
++  std::unique_ptr<std::vector<uint8_t>> delegate_data_;
+ 
+   std::unique_ptr<Dispatcher> dispatcher_;
+ 
diff --git a/src/patch/patches/win_screenlock_1058556.patch b/src/patch/patches/win_screenlock_1058556.patch
deleted file mode 100644
index b740048..0000000
--- a/src/patch/patches/win_screenlock_1058556.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git content/browser/screenlock_monitor/screenlock_monitor_device_source_win.cc content/browser/screenlock_monitor/screenlock_monitor_device_source_win.cc
-index 1cc7bf44645f..7ec28c21ec1d 100644
---- content/browser/screenlock_monitor/screenlock_monitor_device_source_win.cc
-+++ content/browser/screenlock_monitor/screenlock_monitor_device_source_win.cc
-@@ -48,7 +48,7 @@ bool ScreenlockMonitorDeviceSource::SessionMessageWindow::OnWndProc(
-   if (message == WM_WTSSESSION_CHANGE) {
-     ProcessWTSSessionLockMessage(wparam);
-   }
--  return true;
-+  return false;
- }
- 
- void ScreenlockMonitorDeviceSource::SessionMessageWindow::
diff --git a/src/patch/patches/win_shell_dialogs_3294.patch b/src/patch/patches/win_shell_dialogs_3294.patch
new file mode 100644
index 0000000..236c0f5
--- /dev/null
+++ b/src/patch/patches/win_shell_dialogs_3294.patch
@@ -0,0 +1,29 @@
+diff --git ui/shell_dialogs/base_shell_dialog_win.cc ui/shell_dialogs/base_shell_dialog_win.cc
+index 138167d4c0105..81562ffdd2162 100644
+--- ui/shell_dialogs/base_shell_dialog_win.cc
++++ ui/shell_dialogs/base_shell_dialog_win.cc
+@@ -59,11 +59,15 @@ BaseShellDialogImpl::Owners& BaseShellDialogImpl::GetOwners() {
+ 
+ // static
+ void BaseShellDialogImpl::DisableOwner(HWND owner) {
++  if (owner)
++    owner = GetAncestor(owner, GA_ROOT);
+   SetOwnerEnabled(owner, false);
+ }
+ 
+ std::unique_ptr<BaseShellDialogImpl::RunState> BaseShellDialogImpl::BeginRun(
+     HWND owner) {
++  if (owner)
++    owner = GetAncestor(owner, GA_ROOT);
+   // Cannot run a modal shell dialog if one is already running for this owner.
+   DCHECK(!IsRunningDialogForOwner(owner));
+   // The owner must be a top level window, otherwise we could end up with two
+@@ -89,6 +93,8 @@ void BaseShellDialogImpl::EndRun(std::unique_ptr<RunState> run_state) {
+ }
+ 
+ bool BaseShellDialogImpl::IsRunningDialogForOwner(HWND owner) const {
++  if (owner)
++    owner = GetAncestor(owner, GA_ROOT);
+   return (owner && GetOwners().find(owner) != GetOwners().end());
+ }
+ 
diff --git a/src/tests/cefclient/CMakeLists.txt.in b/src/tests/cefclient/CMakeLists.txt.in
index 8a9924e..8439699 100644
--- a/src/tests/cefclient/CMakeLists.txt.in
+++ b/src/tests/cefclient/CMakeLists.txt.in
@@ -49,7 +49,7 @@
 #cefclient Mac OS X sources
 {{
   'prefix': 'cefclient_macosx',
-  'set': 'CEFCLIENT_MACOSX_SRCS',
+  'set': 'CEFCLIENT_MAC_SRCS',
   'includes': [
     'shared_sources_mac',
     'cefclient_sources_mac',
@@ -59,7 +59,7 @@
 # cefclient Mac OS X helper sources.
 {{
   'prefix': 'cefclient_helper',
-  'set': 'CEFCLIENT_MACOSX_HELPER_SRCS',
+  'set': 'CEFCLIENT_MAC_HELPER_SRCS',
   'includes': [
     'shared_sources_mac_helper',
   ],
@@ -81,7 +81,7 @@
   'set': 'CEFCLIENT_RESOURCES_SRCS',
   'includes': [
     'shared_sources_resources',
-    'cefclient_bundle_resources_mac:MACOSX',
+    'cefclient_bundle_resources_mac:MAC',
     'cefclient_sources_resources',
     'cefclient_sources_resources_extensions_set_page_color',
   ],
@@ -94,7 +94,7 @@
 
 # Target executable names.
 set(CEF_TARGET "cefclient")
-if(OS_MACOSX)
+if(OS_MAC)
   set(CEF_HELPER_TARGET "cefclient_Helper")
   set(CEF_HELPER_OUTPUT_NAME "cefclient Helper")
 else()
@@ -122,19 +122,22 @@
     )
 
   # Find required libraries and update compiler/linker variables.
-  FIND_LINUX_LIBRARIES("gmodule-2.0 gtk+-2.0 gthread-2.0 gtk+-unix-print-2.0 gtkglext-1.0 xi")
+  FIND_LINUX_LIBRARIES("gmodule-2.0 gtk+-3.0 gthread-2.0 gtk+-unix-print-3.0 xi")
 
   # Executable target.
   add_executable(${CEF_TARGET} ${CEFCLIENT_SRCS})
   SET_EXECUTABLE_TARGET_PROPERTIES(${CEF_TARGET})
   add_dependencies(${CEF_TARGET} libcef_dll_wrapper)
-  target_link_libraries(${CEF_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS})
+  target_link_libraries(${CEF_TARGET} libcef_lib libcef_dll_wrapper "GL" ${CEF_STANDARD_LIBS})
 
   # Set rpath so that libraries can be placed next to the executable.
   set_target_properties(${CEF_TARGET} PROPERTIES INSTALL_RPATH "$ORIGIN")
   set_target_properties(${CEF_TARGET} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE)
   set_target_properties(${CEF_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CEF_TARGET_OUT_DIR})
 
+  # We don't call deprecated GTK functions, and they can cause build failures, so disable them.
+  add_definitions("-DGTK_DISABLE_DEPRECATED")
+
   # Copy CEF binary and resource files to the target output directory.
   COPY_FILES("${CEF_TARGET}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CEF_TARGET_OUT_DIR}")
   COPY_FILES("${CEF_TARGET}" "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CEF_TARGET_OUT_DIR}")
@@ -151,7 +154,7 @@
 # Mac OS X configuration.
 #
 
-if(OS_MACOSX)
+if(OS_MAC)
   option(OPTION_USE_ARC "Build with ARC (automatic Reference Counting) on macOS." ON)
   if(OPTION_USE_ARC)
     list(APPEND CEF_COMPILER_FLAGS
@@ -168,7 +171,7 @@
     ${CEFCLIENT_BROWSER_SRCS}
     ${CEFCLIENT_COMMON_SRCS}
     ${CEFCLIENT_RESOURCES_SRCS}
-    ${CEFCLIENT_MACOSX_SRCS}
+    ${CEFCLIENT_MAC_SRCS}
     )
 
   # All sources required by the "cefclient Helper" target. Generates an app
@@ -176,7 +179,7 @@
   set(CEFCLIENT_HELPER_SRCS
     ${CEFCLIENT_COMMON_SRCS}
     ${CEFCLIENT_RENDERER_SRCS}
-    ${CEFCLIENT_MACOSX_HELPER_SRCS}
+    ${CEFCLIENT_MAC_HELPER_SRCS}
     )
 
   # Output path for the main app bundle.
@@ -270,7 +273,7 @@
     "resources/"
     "../shared/resources/"
     )
-  COPY_MACOSX_RESOURCES("${CEFCLIENT_RESOURCES_SRCS}" "${PREFIXES}" "${CEF_TARGET}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CEF_APP}")
+  COPY_MAC_RESOURCES("${CEFCLIENT_RESOURCES_SRCS}" "${PREFIXES}" "${CEF_TARGET}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CEF_APP}")
 endif()
 
 
diff --git a/src/tests/cefclient/browser/binary_transfer_test.cc b/src/tests/cefclient/browser/binary_transfer_test.cc
new file mode 100644
index 0000000..6eb7018
--- /dev/null
+++ b/src/tests/cefclient/browser/binary_transfer_test.cc
@@ -0,0 +1,60 @@
+// Copyright (c) 2023 The Chromium Embedded Framework 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 "tests/cefclient/browser/binary_transfer_test.h"
+
+#include <algorithm>
+#include <string>
+
+namespace {
+
+const char kTestUrlPath[] = "/binary_transfer";
+
+// Handle messages in the browser process.
+class Handler final : public CefMessageRouterBrowserSide::Handler {
+ public:
+  // Called due to cefQuery execution in binary_transfer.html.
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               const CefString& request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    // Only handle messages from the test URL.
+    const std::string& url = frame->GetURL();
+    if (!client::test_runner::IsTestURL(url, kTestUrlPath)) {
+      return false;
+    }
+
+    callback->Success(request);
+    return true;
+  }
+
+  // Called due to cefQuery execution in binary_transfer.html.
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               CefRefPtr<const CefBinaryBuffer> request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    // Only handle messages from the test URL.
+    const std::string& url = frame->GetURL();
+    if (!client::test_runner::IsTestURL(url, kTestUrlPath)) {
+      return false;
+    }
+
+    callback->Success(request->GetData(), request->GetSize());
+    return true;
+  }
+};
+
+}  // namespace
+
+namespace client::binary_transfer_test {
+
+void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
+  handlers.insert(new Handler());
+}
+
+}  // namespace client::binary_transfer_test
diff --git a/src/tests/cefclient/browser/binary_transfer_test.h b/src/tests/cefclient/browser/binary_transfer_test.h
new file mode 100644
index 0000000..6690c9f
--- /dev/null
+++ b/src/tests/cefclient/browser/binary_transfer_test.h
@@ -0,0 +1,17 @@
+// Copyright (c) 2023 The Chromium Embedded Framework 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 CEF_TESTS_CEFCLIENT_BROWSER_BINARY_TRANSFER_TEST_H_
+#define CEF_TESTS_CEFCLIENT_BROWSER_BINARY_TRANSFER_TEST_H_
+#pragma once
+
+#include "tests/cefclient/browser/test_runner.h"
+
+namespace client::binary_transfer_test {
+
+void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers);
+
+}  // namespace client::binary_transfer_test
+
+#endif  // CEF_TESTS_CEFCLIENT_BROWSER_BINARY_TRANSFER_TEST_H_
diff --git a/src/tests/cefclient/browser/binding_test.cc b/src/tests/cefclient/browser/binding_test.cc
index 297ebb3..792975c 100644
--- a/src/tests/cefclient/browser/binding_test.cc
+++ b/src/tests/cefclient/browser/binding_test.cc
@@ -25,14 +25,15 @@
   // Called due to cefQuery execution in binding.html.
   virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
                        CefRefPtr<CefFrame> frame,
-                       int64 query_id,
+                       int64_t query_id,
                        const CefString& request,
                        bool persistent,
-                       CefRefPtr<Callback> callback) OVERRIDE {
+                       CefRefPtr<Callback> callback) override {
     // Only handle messages from the test URL.
     const std::string& url = frame->GetURL();
-    if (!test_runner::IsTestURL(url, kTestUrlPath))
+    if (!test_runner::IsTestURL(url, kTestUrlPath)) {
       return false;
+    }
 
     const std::string& message_name = request;
     if (message_name.find(kTestMessageName) == 0) {
diff --git a/src/tests/cefclient/browser/browser_window.cc b/src/tests/cefclient/browser/browser_window.cc
index ffe67ed..355620c 100644
--- a/src/tests/cefclient/browser/browser_window.cc
+++ b/src/tests/cefclient/browser/browser_window.cc
@@ -4,7 +4,7 @@
 
 #include "tests/cefclient/browser/browser_window.h"
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "tests/shared/browser/main_message_loop.h"
 
 namespace client {
diff --git a/src/tests/cefclient/browser/browser_window.h b/src/tests/cefclient/browser/browser_window.h
index a003ede..314ba1f 100644
--- a/src/tests/cefclient/browser/browser_window.h
+++ b/src/tests/cefclient/browser/browser_window.h
@@ -6,7 +6,8 @@
 #define CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_H_
 #pragma once
 
-#include "include/base/cef_scoped_ptr.h"
+#include <memory>
+
 #include "include/cef_browser.h"
 #include "tests/cefclient/browser/client_handler.h"
 #include "tests/cefclient/browser/client_types.h"
@@ -110,26 +111,26 @@
   bool IsClosing() const;
 
  protected:
-  // Allow deletion via scoped_ptr only.
-  friend struct base::DefaultDeleter<BrowserWindow>;
+  // Allow deletion via std::unique_ptr only.
+  friend std::default_delete<BrowserWindow>;
 
   // Constructor may be called on any thread.
   // |delegate| must outlive this object.
   explicit BrowserWindow(Delegate* delegate);
 
   // ClientHandler::Delegate methods.
-  void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void OnBrowserClosing(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void OnBrowserClosed(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void OnSetAddress(const std::string& url) OVERRIDE;
-  void OnSetTitle(const std::string& title) OVERRIDE;
-  void OnSetFullscreen(bool fullscreen) OVERRIDE;
-  void OnAutoResize(const CefSize& new_size) OVERRIDE;
+  void OnBrowserCreated(CefRefPtr<CefBrowser> browser) override;
+  void OnBrowserClosing(CefRefPtr<CefBrowser> browser) override;
+  void OnBrowserClosed(CefRefPtr<CefBrowser> browser) override;
+  void OnSetAddress(const std::string& url) override;
+  void OnSetTitle(const std::string& title) override;
+  void OnSetFullscreen(bool fullscreen) override;
+  void OnAutoResize(const CefSize& new_size) override;
   void OnSetLoadingState(bool isLoading,
                          bool canGoBack,
-                         bool canGoForward) OVERRIDE;
+                         bool canGoForward) override;
   void OnSetDraggableRegions(
-      const std::vector<CefDraggableRegion>& regions) OVERRIDE;
+      const std::vector<CefDraggableRegion>& regions) override;
 
   Delegate* delegate_;
   CefRefPtr<CefBrowser> browser_;
diff --git a/src/tests/cefclient/browser/browser_window_osr_gtk.cc b/src/tests/cefclient/browser/browser_window_osr_gtk.cc
index 242b312..db5ce52 100644
--- a/src/tests/cefclient/browser/browser_window_osr_gtk.cc
+++ b/src/tests/cefclient/browser/browser_window_osr_gtk.cc
@@ -6,18 +6,18 @@
 
 #include <GL/gl.h>
 #include <gdk/gdk.h>
-#include <gdk/gdkkeysyms.h>
+#include <gdk/gdkkeysyms-compat.h>
 #include <gdk/gdkx.h>
 #include <glib-object.h>
 #include <gtk/gtk.h>
-#include <gtk/gtkgl.h>
 
 #define XK_3270  // for XK_3270_BackTab
 #include <X11/XF86keysym.h>
 #include <X11/Xcursor/Xcursor.h>
-#include <X11/extensions/XInput2.h>
 #include <X11/keysym.h>
 
+#include <algorithm>
+
 #include "include/base/cef_logging.h"
 #include "include/base/cef_macros.h"
 #include "include/wrapper/cef_closure_task.h"
@@ -29,48 +29,34 @@
 
 namespace {
 
-// Major opcode of XInputExtension, or -1 if XInput 2.2 is not available.
-int g_xinput_extension = -1;
-
 // Static BrowserWindowOsrGtk::EventFilter needs to forward touch events
 // to correct browser, so we maintain a vector of all windows.
 std::vector<BrowserWindowOsrGtk*> g_browser_windows;
 
-bool IsTouchAvailable() {
-  return g_xinput_extension != -1;
-}
-
 int GetCefStateModifiers(guint state) {
   int modifiers = 0;
-  if (state & GDK_SHIFT_MASK)
+  if (state & GDK_SHIFT_MASK) {
     modifiers |= EVENTFLAG_SHIFT_DOWN;
-  if (state & GDK_LOCK_MASK)
-    modifiers |= EVENTFLAG_CAPS_LOCK_ON;
-  if (state & GDK_CONTROL_MASK)
-    modifiers |= EVENTFLAG_CONTROL_DOWN;
-  if (state & GDK_MOD1_MASK)
-    modifiers |= EVENTFLAG_ALT_DOWN;
-  if (state & GDK_BUTTON1_MASK)
-    modifiers |= EVENTFLAG_LEFT_MOUSE_BUTTON;
-  if (state & GDK_BUTTON2_MASK)
-    modifiers |= EVENTFLAG_MIDDLE_MOUSE_BUTTON;
-  if (state & GDK_BUTTON3_MASK)
-    modifiers |= EVENTFLAG_RIGHT_MOUSE_BUTTON;
-  return modifiers;
-}
-
-int GetCefStateModifiers(XIModifierState mods, XIButtonState buttons) {
-  guint state = mods.effective;
-  if (buttons.mask_len >= 1) {
-    if (XIMaskIsSet(buttons.mask, 1))
-      state |= GDK_BUTTON1_MASK;
-    if (XIMaskIsSet(buttons.mask, 2))
-      state |= GDK_BUTTON2_MASK;
-    if (XIMaskIsSet(buttons.mask, 3))
-      state |= GDK_BUTTON3_MASK;
   }
-
-  return GetCefStateModifiers(state);
+  if (state & GDK_LOCK_MASK) {
+    modifiers |= EVENTFLAG_CAPS_LOCK_ON;
+  }
+  if (state & GDK_CONTROL_MASK) {
+    modifiers |= EVENTFLAG_CONTROL_DOWN;
+  }
+  if (state & GDK_MOD1_MASK) {
+    modifiers |= EVENTFLAG_ALT_DOWN;
+  }
+  if (state & GDK_BUTTON1_MASK) {
+    modifiers |= EVENTFLAG_LEFT_MOUSE_BUTTON;
+  }
+  if (state & GDK_BUTTON2_MASK) {
+    modifiers |= EVENTFLAG_MIDDLE_MOUSE_BUTTON;
+  }
+  if (state & GDK_BUTTON3_MASK) {
+    modifiers |= EVENTFLAG_RIGHT_MOUSE_BUTTON;
+  }
+  return modifiers;
 }
 
 // From ui/events/keycodes/keyboard_codes_posix.h.
@@ -808,13 +794,15 @@
   // key and a caps-lock key, GTK doesn't swap their
   // |event->hardware_keycode| values but swap their |event->keyval| values.
   KeyboardCode windows_key_code = KeyboardCodeFromXKeysym(event->keyval);
-  if (windows_key_code)
+  if (windows_key_code) {
     return windows_key_code;
+  }
 
-  if (event->hardware_keycode < arraysize(kHardwareCodeToGDKKeyval)) {
+  if (event->hardware_keycode < std::size(kHardwareCodeToGDKKeyval)) {
     int keyval = kHardwareCodeToGDKKeyval[event->hardware_keycode];
-    if (keyval)
+    if (keyval) {
       return KeyboardCodeFromXKeysym(keyval);
+    }
   }
 
   // This key is one that keyboard-layout drivers cannot change.
@@ -885,62 +873,40 @@
   }
 }
 
-void GetWidgetRectInScreen(GtkWidget* widget, GdkRectangle* r) {
-  gint x, y, w, h;
-  GdkRectangle extents;
-
-  GdkWindow* window = gtk_widget_get_parent_window(widget);
-
-  // Get parent's left-top screen coordinates.
-  gdk_window_get_root_origin(window, &x, &y);
-  // Get parent's width and height.
-  gdk_drawable_get_size(window, &w, &h);
-  // Get parent's extents including decorations.
-  gdk_window_get_frame_extents(window, &extents);
-
-  // X and Y calculations assume that left, right and bottom border sizes are
-  // all the same.
-  const gint border = (extents.width - w) / 2;
-  r->x = x + border + widget->allocation.x;
-  r->y = y + (extents.height - h) - border + widget->allocation.y;
-  r->width = widget->allocation.width;
-  r->height = widget->allocation.height;
-}
-
 CefBrowserHost::DragOperationsMask GetDragOperationsMask(
     GdkDragContext* drag_context) {
   int allowed_ops = DRAG_OPERATION_NONE;
   GdkDragAction drag_action = gdk_drag_context_get_actions(drag_context);
-  if (drag_action & GDK_ACTION_COPY)
+  if (drag_action & GDK_ACTION_COPY) {
     allowed_ops |= DRAG_OPERATION_COPY;
-  if (drag_action & GDK_ACTION_MOVE)
+  }
+  if (drag_action & GDK_ACTION_MOVE) {
     allowed_ops |= DRAG_OPERATION_MOVE;
-  if (drag_action & GDK_ACTION_LINK)
+  }
+  if (drag_action & GDK_ACTION_LINK) {
     allowed_ops |= DRAG_OPERATION_LINK;
-  if (drag_action & GDK_ACTION_PRIVATE)
+  }
+  if (drag_action & GDK_ACTION_PRIVATE) {
     allowed_ops |= DRAG_OPERATION_PRIVATE;
+  }
   return static_cast<CefBrowserHost::DragOperationsMask>(allowed_ops);
 }
 
 class ScopedGLContext {
  public:
   ScopedGLContext(GtkWidget* widget, bool swap_buffers)
-      : swap_buffers_(swap_buffers) {
-    GdkGLContext* glcontext = gtk_widget_get_gl_context(widget);
-    gldrawable_ = gtk_widget_get_gl_drawable(widget);
-    is_valid_ = gdk_gl_drawable_gl_begin(gldrawable_, glcontext);
+      : swap_buffers_(swap_buffers), widget_(widget) {
+    gtk_gl_area_make_current(GTK_GL_AREA(widget));
+    is_valid_ = gtk_gl_area_get_error(GTK_GL_AREA(widget)) == nullptr;
+    if (swap_buffers_ && is_valid_) {
+      gtk_gl_area_queue_render(GTK_GL_AREA(widget_));
+      gtk_gl_area_attach_buffers(GTK_GL_AREA(widget));
+    }
   }
 
   virtual ~ScopedGLContext() {
-    if (is_valid_) {
-      gdk_gl_drawable_gl_end(gldrawable_);
-
-      if (swap_buffers_) {
-        if (gdk_gl_drawable_is_double_buffered(gldrawable_))
-          gdk_gl_drawable_swap_buffers(gldrawable_);
-        else
-          glFlush();
-      }
+    if (swap_buffers_ && is_valid_) {
+      glFlush();
     }
   }
 
@@ -948,7 +914,7 @@
 
  private:
   bool swap_buffers_;
-  GdkGLDrawable* gldrawable_;
+  GtkWidget* const widget_;
   bool is_valid_;
   ScopedGdkThreadsEnter scoped_gdk_threads_;
 };
@@ -956,6 +922,7 @@
 }  // namespace
 
 BrowserWindowOsrGtk::BrowserWindowOsrGtk(BrowserWindow::Delegate* delegate,
+                                         bool with_controls,
                                          const std::string& startup_url,
                                          const OsrRendererSettings& settings)
     : BrowserWindow(delegate),
@@ -964,16 +931,17 @@
       gl_enabled_(false),
       painting_popup_(false),
       hidden_(false),
-      glarea_(NULL),
+      glarea_(nullptr),
       drag_trigger_event_(nullptr),
       drag_data_(nullptr),
       drag_operation_(DRAG_OPERATION_NONE),
       drag_context_(nullptr),
-      drag_targets_(gtk_target_list_new(NULL, 0)),
+      drag_targets_(gtk_target_list_new(nullptr, 0)),
       drag_leave_(false),
       drag_drop_(false),
       device_scale_factor_(1.0f) {
-  client_handler_ = new ClientHandlerOsr(this, this, startup_url);
+  client_handler_ =
+      new ClientHandlerOsr(this, this, with_controls, startup_url);
   g_browser_windows.push_back(this);
 }
 
@@ -1013,11 +981,11 @@
   // Retrieve the X11 Window ID for the GTK parent window.
   GtkWidget* window =
       gtk_widget_get_ancestor(GTK_WIDGET(parent_handle), GTK_TYPE_WINDOW);
-  ::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(window));
-  DCHECK(xwindow);
+  CefWindowHandle handle = GDK_WINDOW_XID(gtk_widget_get_window(window));
+  DCHECK(handle);
 
   CefWindowInfo window_info;
-  window_info.SetAsWindowless(xwindow);
+  window_info.SetAsWindowless(handle);
 
   // Create the browser asynchronously.
   CefBrowserHost::CreateBrowser(window_info, client_handler_,
@@ -1063,17 +1031,18 @@
   }
 
   // Give focus to the browser.
-  browser_->GetHost()->SendFocusEvent(true);
+  browser_->GetHost()->SetFocus(true);
 }
 
 void BrowserWindowOsrGtk::Hide() {
   REQUIRE_MAIN_THREAD();
 
-  if (!browser_)
+  if (!browser_) {
     return;
+  }
 
   // Remove focus from the browser.
-  browser_->GetHost()->SendFocusEvent(false);
+  browser_->GetHost()->SetFocus(false);
 
   if (!hidden_) {
     // Set the browser as hidden.
@@ -1089,7 +1058,6 @@
 
 void BrowserWindowOsrGtk::SetFocus(bool focus) {
   REQUIRE_MAIN_THREAD();
-  ScopedGdkThreadsEnter scoped_gdk_threads;
   if (glarea_ && focus) {
     gtk_widget_grab_focus(glarea_);
   }
@@ -1099,12 +1067,14 @@
   REQUIRE_MAIN_THREAD();
   {
     base::AutoLock lock_scope(lock_);
-    if (device_scale_factor == device_scale_factor_)
+    if (device_scale_factor == device_scale_factor_) {
       return;
+    }
 
     // Apply some sanity checks.
-    if (device_scale_factor < 1.0f || device_scale_factor > 4.0f)
+    if (device_scale_factor < 1.0f || device_scale_factor > 4.0f) {
       return;
+    }
 
     device_scale_factor_ = device_scale_factor;
   }
@@ -1141,8 +1111,8 @@
   UnregisterDragDrop();
 
   // Disconnect all signal handlers that reference |this|.
-  g_signal_handlers_disconnect_matched(glarea_, G_SIGNAL_MATCH_DATA, 0, 0, NULL,
-                                       NULL, this);
+  g_signal_handlers_disconnect_matched(glarea_, G_SIGNAL_MATCH_DATA, 0, 0,
+                                       nullptr, nullptr, this);
 
   DisableGL();
 }
@@ -1173,13 +1143,16 @@
 
   // The simulated screen and view rectangle are the same. This is necessary
   // for popup menus to be located and sized inside the view.
-  rect.width = DeviceToLogical(glarea_->allocation.width, device_scale_factor);
-  if (rect.width == 0)
+  GtkAllocation allocation;
+  gtk_widget_get_allocation(glarea_, &allocation);
+  rect.width = DeviceToLogical(allocation.width, device_scale_factor);
+  if (rect.width == 0) {
     rect.width = 1;
-  rect.height =
-      DeviceToLogical(glarea_->allocation.height, device_scale_factor);
-  if (rect.height == 0)
+  }
+  rect.height = DeviceToLogical(allocation.height, device_scale_factor);
+  if (rect.height == 0) {
     rect.height = 1;
+  }
 }
 
 bool BrowserWindowOsrGtk::GetScreenPoint(CefRefPtr<CefBrowser> browser,
@@ -1195,10 +1168,13 @@
     device_scale_factor = device_scale_factor_;
   }
 
-  GdkRectangle screen_rect;
-  GetWidgetRectInScreen(glarea_, &screen_rect);
-  screenX = screen_rect.x + LogicalToDevice(viewX, device_scale_factor);
-  screenY = screen_rect.y + LogicalToDevice(viewY, device_scale_factor);
+  // Get the widget position in the window.
+  GtkAllocation allocation;
+  gtk_widget_get_allocation(glarea_, &allocation);
+
+  // Convert from view DIP coordinates to window (pixel) coordinates.
+  screenX = allocation.x + LogicalToDevice(viewX, device_scale_factor);
+  screenY = allocation.y + LogicalToDevice(viewY, device_scale_factor);
   return true;
 }
 
@@ -1266,12 +1242,14 @@
     return;
   }
 
-  if (!gl_enabled_)
+  if (!gl_enabled_) {
     EnableGL();
+  }
 
   ScopedGLContext scoped_gl_context(glarea_, true);
-  if (!scoped_gl_context.IsValid())
+  if (!scoped_gl_context.IsValid()) {
     return;
+  }
 
   renderer_.OnPaint(browser, type, dirtyRects, buffer, width, height);
   if (type == PET_VIEW && !renderer_.popup_rect().IsEmpty()) {
@@ -1285,7 +1263,7 @@
 void BrowserWindowOsrGtk::OnCursorChange(
     CefRefPtr<CefBrowser> browser,
     CefCursorHandle cursor,
-    CefRenderHandler::CursorType type,
+    cef_cursor_type_t type,
     const CefCursorInfo& custom_cursor_info) {
   CEF_REQUIRE_UI_THREAD();
 
@@ -1314,11 +1292,11 @@
     return false;
   }
 
+  ScopedGdkThreadsEnter scoped_gdk_threads;
+
   DragReset();
   drag_data_ = drag_data;
 
-  ScopedGdkThreadsEnter scoped_gdk_threads;
-
   // Begin drag.
   if (drag_trigger_event_) {
     LOG(ERROR) << "Dragging started, but last mouse event is missing";
@@ -1374,18 +1352,13 @@
 
   ScopedGdkThreadsEnter scoped_gdk_threads;
 
-  glarea_ = gtk_drawing_area_new();
+  glarea_ = gtk_gl_area_new();
   DCHECK(glarea_);
 
-  GdkGLConfig* glconfig =
-      gdk_gl_config_new_by_mode(static_cast<GdkGLConfigMode>(
-          GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE));
-  DCHECK(glconfig);
-
-  gtk_widget_set_gl_capability(glarea_, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
-
   gtk_widget_set_can_focus(glarea_, TRUE);
 
+  gtk_gl_area_set_auto_render(GTK_GL_AREA(glarea_), FALSE);
+
   g_signal_connect(G_OBJECT(glarea_), "size_allocate",
                    G_CALLBACK(&BrowserWindowOsrGtk::SizeAllocation), this);
 
@@ -1415,25 +1388,23 @@
                    G_CALLBACK(&BrowserWindowOsrGtk::FocusEvent), this);
   g_signal_connect(G_OBJECT(glarea_), "focus_out_event",
                    G_CALLBACK(&BrowserWindowOsrGtk::FocusEvent), this);
+  g_signal_connect(G_OBJECT(glarea_), "touch-event",
+                   G_CALLBACK(&BrowserWindowOsrGtk::TouchEvent), this);
 
   RegisterDragDrop();
 
-  gtk_container_add(GTK_CONTAINER(parent_handle), glarea_);
+  gtk_widget_set_vexpand(glarea_, TRUE);
+  gtk_grid_attach(GTK_GRID(parent_handle), glarea_, 0, 3, 1, 1);
 
   // Make the GlArea visible in the parent container.
   gtk_widget_show_all(parent_handle);
-
-  InitializeXinput(xdisplay_);
-
-  if (IsTouchAvailable())
-    RegisterTouch();
 }
 
 // static
 gint BrowserWindowOsrGtk::SizeAllocation(GtkWidget* widget,
                                          GtkAllocation* allocation,
                                          BrowserWindowOsrGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
   if (self->browser_.get()) {
     // Results in a call to GetViewRect().
     self->browser_->GetHost()->WasResized();
@@ -1445,10 +1416,11 @@
 gint BrowserWindowOsrGtk::ClickEvent(GtkWidget* widget,
                                      GdkEventButton* event,
                                      BrowserWindowOsrGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
 
-  if (!self->browser_.get())
+  if (!self->browser_.get()) {
     return TRUE;
+  }
 
   CefRefPtr<CefBrowserHost> host = self->browser_->GetHost();
 
@@ -1515,10 +1487,11 @@
 gint BrowserWindowOsrGtk::KeyEvent(GtkWidget* widget,
                                    GdkEventKey* event,
                                    BrowserWindowOsrGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
 
-  if (!self->browser_.get())
+  if (!self->browser_.get()) {
     return TRUE;
+  }
 
   CefRefPtr<CefBrowserHost> host = self->browser_->GetHost();
 
@@ -1531,10 +1504,12 @@
   key_event.native_key_code = event->hardware_keycode;
 
   key_event.modifiers = GetCefStateModifiers(event->state);
-  if (event->keyval >= GDK_KP_Space && event->keyval <= GDK_KP_9)
+  if (event->keyval >= GDK_KP_Space && event->keyval <= GDK_KP_9) {
     key_event.modifiers |= EVENTFLAG_IS_KEY_PAD;
-  if (key_event.modifiers & EVENTFLAG_ALT_DOWN)
+  }
+  if (key_event.modifiers & EVENTFLAG_ALT_DOWN) {
     key_event.is_system_key = true;
+  }
 
   if (windows_key_code == VKEY_RETURN) {
     // We need to treat the enter key as a key press of character \r.  This
@@ -1571,10 +1546,9 @@
 gint BrowserWindowOsrGtk::MoveEvent(GtkWidget* widget,
                                     GdkEventMotion* event,
                                     BrowserWindowOsrGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
-
-  if (!self->browser_.get())
+  if (!self->browser_.get()) {
     return TRUE;
+  }
 
   CefRefPtr<CefBrowserHost> host = self->browser_->GetHost();
 
@@ -1628,10 +1602,11 @@
 gint BrowserWindowOsrGtk::ScrollEvent(GtkWidget* widget,
                                       GdkEventScroll* event,
                                       BrowserWindowOsrGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
 
-  if (!self->browser_.get())
+  if (!self->browser_.get()) {
     return TRUE;
+  }
 
   CefRefPtr<CefBrowserHost> host = self->browser_->GetHost();
 
@@ -1664,6 +1639,9 @@
     case GDK_SCROLL_RIGHT:
       deltaX = -scrollbarPixelsPerGtkTick;
       break;
+    case GDK_SCROLL_SMOOTH:
+      NOTIMPLEMENTED();
+      break;
   }
 
   host->SendMouseWheelEvent(mouse_event, deltaX, deltaY);
@@ -1675,111 +1653,56 @@
                                      GdkEventFocus* event,
                                      BrowserWindowOsrGtk* self) {
   // May be called on the main thread and the UI thread.
-  if (self->browser_.get())
-    self->browser_->GetHost()->SendFocusEvent(event->in == TRUE);
+  if (self->browser_.get()) {
+    self->browser_->GetHost()->SetFocus(event->in == TRUE);
+  }
   return TRUE;
 }
 
-void BrowserWindowOsrGtk::TouchEvent(CefXIDeviceEvent event) {
-  if (!browser_.get())
-    return;
+// static
+gboolean BrowserWindowOsrGtk::TouchEvent(GtkWidget* widget,
+                                         GdkEventTouch* event,
+                                         BrowserWindowOsrGtk* self) {
+  REQUIRE_MAIN_THREAD();
 
-  XIDeviceEvent* ev = static_cast<XIDeviceEvent*>(event);
-  CefTouchEvent cef_event;
-  switch (ev->evtype) {
-    case XI_TouchBegin:
-      cef_event.type = CEF_TET_PRESSED;
+  if (!self->browser_.get()) {
+    return TRUE;
+  }
+
+  CefRefPtr<CefBrowserHost> host = self->browser_->GetHost();
+
+  float device_scale_factor;
+  {
+    base::AutoLock lock_scope(self->lock_);
+    device_scale_factor = self->device_scale_factor_;
+  }
+
+  CefTouchEvent touch_event;
+  switch (event->type) {
+    case GDK_TOUCH_BEGIN:
+      touch_event.type = CEF_TET_PRESSED;
       break;
-    case XI_TouchUpdate:
-      cef_event.type = CEF_TET_MOVED;
+    case GDK_TOUCH_UPDATE:
+      touch_event.type = CEF_TET_MOVED;
       break;
-    case XI_TouchEnd:
-      cef_event.type = CEF_TET_RELEASED;
+    case GDK_TOUCH_END:
+      touch_event.type = CEF_TET_RELEASED;
       break;
     default:
-      return;
+      return TRUE;
   }
 
-  cef_event.id = ev->detail;
-  cef_event.x = ev->event_x;
-  cef_event.y = ev->event_y;
-  cef_event.radius_x = 0;
-  cef_event.radius_y = 0;
-  cef_event.rotation_angle = 0;
-  cef_event.pressure = 0;
-  cef_event.modifiers = GetCefStateModifiers(ev->mods, ev->buttons);
+  touch_event.x = event->x;
+  touch_event.y = event->y;
+  touch_event.radius_x = 0;
+  touch_event.radius_y = 0;
+  touch_event.rotation_angle = 0;
+  touch_event.pressure = 0;
+  DeviceToLogical(touch_event, device_scale_factor);
+  touch_event.modifiers = GetCefStateModifiers(event->state);
 
-  browser_->GetHost()->SendTouchEvent(cef_event);
-}
-
-void BrowserWindowOsrGtk::RegisterTouch() {
-  GdkWindow* glwindow = gtk_widget_get_window(glarea_);
-  ::Window xwindow = GDK_WINDOW_XID(glwindow);
-  uint32_t bitMask = XI_TouchBeginMask | XI_TouchUpdateMask | XI_TouchEndMask;
-
-  XIEventMask mask;
-  mask.deviceid = XIAllMasterDevices;
-  mask.mask = reinterpret_cast<unsigned char*>(&bitMask);
-  mask.mask_len = sizeof(bitMask);
-  XISelectEvents(xdisplay_, xwindow, &mask, 1);
-}
-
-// static
-GdkFilterReturn BrowserWindowOsrGtk::EventFilter(GdkXEvent* gdk_xevent,
-                                                 GdkEvent* event,
-                                                 gpointer data) {
-  XEvent* xevent = static_cast<XEvent*>(gdk_xevent);
-  if (xevent->type == GenericEvent &&
-      xevent->xgeneric.extension == g_xinput_extension) {
-    XGetEventData(xevent->xcookie.display, &xevent->xcookie);
-    XIDeviceEvent* ev = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
-
-    if (!ev)
-      return GDK_FILTER_REMOVE;
-
-    for (BrowserWindowOsrGtk* browser_window : g_browser_windows) {
-      GtkWidget* widget = browser_window->GetWindowHandle();
-      ::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(widget));
-      if (xwindow == ev->event) {
-        browser_window->TouchEvent(ev);
-        break;
-      }
-    }
-
-    XFreeEventData(xevent->xcookie.display, &xevent->xcookie);
-    // Even if we didn't find a consumer for this event, we will make sure Gdk
-    // doesn't attempt to process the event, since it can't parse GenericEvents
-    return GDK_FILTER_REMOVE;
-  }
-
-  return GDK_FILTER_CONTINUE;
-}
-
-// static
-void BrowserWindowOsrGtk::InitializeXinput(XDisplay* xdisplay) {
-  static bool initialized = false;
-  if (initialized)
-    return;
-  initialized = true;
-
-  int firstEvent, firstError;
-  if (XQueryExtension(xdisplay, "XInputExtension", &g_xinput_extension,
-                      &firstEvent, &firstError)) {
-    int major = 2, minor = 2;
-    // X Input Extension 2.2 is needed for multitouch events.
-    if (XIQueryVersion(xdisplay, &major, &minor) == Success) {
-      // Ideally we would add an event filter for each glarea_ window
-      // separately, but unfortunately GDK can't parse X GenericEvents
-      // which have the target window stored in different way compared
-      // to other X events. That is why we add this global event filter
-      // just once, and dispatch the event to correct BrowserWindowOsrGtk
-      // manually.
-      gdk_window_add_filter(nullptr, &BrowserWindowOsrGtk::EventFilter,
-                            nullptr);
-    } else {
-      g_xinput_extension = -1;
-    }
-  }
+  host->SendTouchEvent(touch_event);
+  return TRUE;
 }
 
 bool BrowserWindowOsrGtk::IsOverPopupWidget(int x, int y) const {
@@ -1807,12 +1730,14 @@
 void BrowserWindowOsrGtk::EnableGL() {
   CEF_REQUIRE_UI_THREAD();
 
-  if (gl_enabled_)
+  if (gl_enabled_) {
     return;
+  }
 
   ScopedGLContext scoped_gl_context(glarea_, false);
-  if (!scoped_gl_context.IsValid())
+  if (!scoped_gl_context.IsValid()) {
     return;
+  }
 
   renderer_.Initialize();
 
@@ -1822,12 +1747,14 @@
 void BrowserWindowOsrGtk::DisableGL() {
   CEF_REQUIRE_UI_THREAD();
 
-  if (!gl_enabled_)
+  if (!gl_enabled_) {
     return;
+  }
 
   ScopedGLContext scoped_gl_context(glarea_, false);
-  if (!scoped_gl_context.IsValid())
+  if (!scoped_gl_context.IsValid()) {
     return;
+  }
 
   renderer_.Cleanup();
 
@@ -1863,7 +1790,8 @@
   // Default values for drag threshold are set to 8 pixels in both GTK and
   // Chromium, but doesn't work as expected.
   // --OFF--
-  // gtk_drag_source_set(glarea_, GDK_BUTTON1_MASK, NULL, 0, GDK_ACTION_COPY);
+  // gtk_drag_source_set(glarea_, GDK_BUTTON1_MASK, nullptr, 0,
+  // GDK_ACTION_COPY);
 
   // Source widget events.
   g_signal_connect(G_OBJECT(glarea_), "drag_begin",
@@ -1874,7 +1802,7 @@
                    G_CALLBACK(&BrowserWindowOsrGtk::DragEnd), this);
 
   // Destination widget and its events.
-  gtk_drag_dest_set(glarea_, (GtkDestDefaults)0, (GtkTargetEntry*)NULL, 0,
+  gtk_drag_dest_set(glarea_, (GtkDestDefaults)0, (GtkTargetEntry*)nullptr, 0,
                     (GdkDragAction)GDK_ACTION_COPY);
   g_signal_connect(G_OBJECT(glarea_), "drag_motion",
                    G_CALLBACK(&BrowserWindowOsrGtk::DragMotion), this);
@@ -1889,7 +1817,6 @@
 }
 
 void BrowserWindowOsrGtk::UnregisterDragDrop() {
-  CEF_REQUIRE_UI_THREAD();
   ScopedGdkThreadsEnter scoped_gdk_threads;
   gtk_drag_dest_unset(glarea_);
   // Drag events are unregistered in OnBeforeClose by calling
@@ -1897,7 +1824,6 @@
 }
 
 void BrowserWindowOsrGtk::DragReset() {
-  CEF_REQUIRE_UI_THREAD();
   if (drag_trigger_event_) {
     gdk_event_free(drag_trigger_event_);
     drag_trigger_event_ = nullptr;
@@ -1916,8 +1842,6 @@
 void BrowserWindowOsrGtk::DragBegin(GtkWidget* widget,
                                     GdkDragContext* drag_context,
                                     BrowserWindowOsrGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
-
   // Load drag icon.
   if (!self->drag_data_->HasImage()) {
     LOG(ERROR) << "Failed to set drag icon, drag image not available";
@@ -1940,6 +1864,8 @@
     return;
   }
 
+  ScopedGdkThreadsEnter scoped_gdk_threads;
+
   size_t image_size = image_binary->GetSize();
   guint8* image_buffer = (guint8*)malloc(image_size);  // must free
   image_binary->GetData((void*)image_buffer, image_size, 0);
@@ -1949,9 +1875,10 @@
   gboolean success = FALSE;
   loader = gdk_pixbuf_loader_new_with_type("png", &error);
   if (error == nullptr && loader) {
-    success = gdk_pixbuf_loader_write(loader, image_buffer, image_size, NULL);
+    success =
+        gdk_pixbuf_loader_write(loader, image_buffer, image_size, nullptr);
     if (success) {
-      success = gdk_pixbuf_loader_close(loader, NULL);
+      success = gdk_pixbuf_loader_close(loader, nullptr);
       if (success) {
         pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
         if (pixbuf) {
@@ -1987,7 +1914,7 @@
                                       guint info,
                                       guint time,
                                       BrowserWindowOsrGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
   // No drag targets are set so this callback is never called.
 }
 
@@ -1995,7 +1922,7 @@
 void BrowserWindowOsrGtk::DragEnd(GtkWidget* widget,
                                   GdkDragContext* drag_context,
                                   BrowserWindowOsrGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
 
   if (self->browser_) {
     // Sometimes there is DragEnd event generated without prior DragDrop.
@@ -2018,7 +1945,7 @@
                                          gint y,
                                          guint time,
                                          BrowserWindowOsrGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
 
   float device_scale_factor;
   {
@@ -2078,7 +2005,7 @@
                                     GdkDragContext* drag_context,
                                     guint time,
                                     BrowserWindowOsrGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
 
   // There is no drag-enter event in GTK. The first drag-motion event
   // after drag-leave will be a drag-enter event.
@@ -2100,7 +2027,7 @@
                                          GdkDragContext* drag_context,
                                          GtkDragResult result,
                                          BrowserWindowOsrGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
 
   // Send drag end coordinates and system drag ended event.
   if (self->browser_) {
@@ -2120,7 +2047,7 @@
                                        gint y,
                                        guint time,
                                        BrowserWindowOsrGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
 
   // Finish GTK drag.
   gtk_drag_finish(drag_context, TRUE, FALSE, time);
@@ -2164,7 +2091,7 @@
                                            guint info,
                                            guint time,
                                            BrowserWindowOsrGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
   // This callback is never called because DragDrop does not call
   // gtk_drag_get_data, as only dragging inside web view is supported.
 }
diff --git a/src/tests/cefclient/browser/browser_window_osr_gtk.h b/src/tests/cefclient/browser/browser_window_osr_gtk.h
index 33083e0..18bd380 100644
--- a/src/tests/cefclient/browser/browser_window_osr_gtk.h
+++ b/src/tests/cefclient/browser/browser_window_osr_gtk.h
@@ -25,6 +25,7 @@
   // Constructor may be called on any thread.
   // |delegate| must outlive this object.
   BrowserWindowOsrGtk(BrowserWindow::Delegate* delegate,
+                      bool with_controls,
                       const std::string& startup_url,
                       const OsrRendererSettings& settings);
 
@@ -36,61 +37,61 @@
                      const CefRect& rect,
                      const CefBrowserSettings& settings,
                      CefRefPtr<CefDictionaryValue> extra_info,
-                     CefRefPtr<CefRequestContext> request_context) OVERRIDE;
+                     CefRefPtr<CefRequestContext> request_context) override;
   void GetPopupConfig(CefWindowHandle temp_handle,
                       CefWindowInfo& windowInfo,
                       CefRefPtr<CefClient>& client,
-                      CefBrowserSettings& settings) OVERRIDE;
+                      CefBrowserSettings& settings) override;
   void ShowPopup(ClientWindowHandle parent_handle,
                  int x,
                  int y,
                  size_t width,
-                 size_t height) OVERRIDE;
-  void Show() OVERRIDE;
-  void Hide() OVERRIDE;
-  void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
-  void SetFocus(bool focus) OVERRIDE;
-  void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE;
-  float GetDeviceScaleFactor() const OVERRIDE;
-  ClientWindowHandle GetWindowHandle() const OVERRIDE;
+                 size_t height) override;
+  void Show() override;
+  void Hide() override;
+  void SetBounds(int x, int y, size_t width, size_t height) override;
+  void SetFocus(bool focus) override;
+  void SetDeviceScaleFactor(float device_scale_factor) override;
+  float GetDeviceScaleFactor() const override;
+  ClientWindowHandle GetWindowHandle() const override;
 
   // ClientHandlerOsr::OsrDelegate methods.
-  void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  bool GetRootScreenRect(CefRefPtr<CefBrowser> browser, CefRect& rect) OVERRIDE;
-  void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) OVERRIDE;
+  void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
+  void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
+  bool GetRootScreenRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override;
+  void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override;
   bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
                       int viewX,
                       int viewY,
                       int& screenX,
-                      int& screenY) OVERRIDE;
+                      int& screenY) override;
   bool GetScreenInfo(CefRefPtr<CefBrowser> browser,
-                     CefScreenInfo& screen_info) OVERRIDE;
-  void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) OVERRIDE;
-  void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect) OVERRIDE;
+                     CefScreenInfo& screen_info) override;
+  void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) override;
+  void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect) override;
   void OnPaint(CefRefPtr<CefBrowser> browser,
                CefRenderHandler::PaintElementType type,
                const CefRenderHandler::RectList& dirtyRects,
                const void* buffer,
                int width,
-               int height) OVERRIDE;
+               int height) override;
   void OnCursorChange(CefRefPtr<CefBrowser> browser,
                       CefCursorHandle cursor,
-                      CefRenderHandler::CursorType type,
-                      const CefCursorInfo& custom_cursor_info) OVERRIDE;
+                      cef_cursor_type_t type,
+                      const CefCursorInfo& custom_cursor_info) override;
   bool StartDragging(CefRefPtr<CefBrowser> browser,
                      CefRefPtr<CefDragData> drag_data,
                      CefRenderHandler::DragOperationsMask allowed_ops,
                      int x,
-                     int y) OVERRIDE;
+                     int y) override;
   void UpdateDragCursor(CefRefPtr<CefBrowser> browser,
-                        CefRenderHandler::DragOperation operation) OVERRIDE;
+                        CefRenderHandler::DragOperation operation) override;
   void OnImeCompositionRangeChanged(
       CefRefPtr<CefBrowser> browser,
       const CefRange& selection_range,
-      const CefRenderHandler::RectList& character_bounds) OVERRIDE;
-  void UpdateAccessibilityTree(CefRefPtr<CefValue> value) OVERRIDE;
-  void UpdateAccessibilityLocation(CefRefPtr<CefValue> value) OVERRIDE;
+      const CefRenderHandler::RectList& character_bounds) override;
+  void UpdateAccessibilityTree(CefRefPtr<CefValue> value) override;
+  void UpdateAccessibilityLocation(CefRefPtr<CefValue> value) override;
 
  private:
   ~BrowserWindowOsrGtk();
@@ -117,8 +118,10 @@
   static gint FocusEvent(GtkWidget* widget,
                          GdkEventFocus* event,
                          BrowserWindowOsrGtk* self);
+  static gboolean TouchEvent(GtkWidget* widget,
+                             GdkEventTouch* event,
+                             BrowserWindowOsrGtk* self);
 
-  void TouchEvent(CefXIDeviceEvent event);
   void RegisterTouch();
 
   bool IsOverPopupWidget(int x, int y) const;
@@ -176,7 +179,6 @@
   static GdkFilterReturn EventFilter(GdkXEvent* gdk_xevent,
                                      GdkEvent* event,
                                      gpointer data);
-  static void InitializeXinput(XDisplay* xdisplay);
 
   XDisplay* xdisplay_;
 
diff --git a/src/tests/cefclient/browser/browser_window_osr_mac.h b/src/tests/cefclient/browser/browser_window_osr_mac.h
index be42213..130a77c 100644
--- a/src/tests/cefclient/browser/browser_window_osr_mac.h
+++ b/src/tests/cefclient/browser/browser_window_osr_mac.h
@@ -24,6 +24,7 @@
   // Constructor may be called on any thread.
   // |delegate| must outlive this object.
   BrowserWindowOsrMac(BrowserWindow::Delegate* delegate,
+                      bool with_controls,
                       const std::string& startup_url,
                       const OsrRendererSettings& settings);
   ~BrowserWindowOsrMac();
@@ -33,65 +34,65 @@
                      const CefRect& rect,
                      const CefBrowserSettings& settings,
                      CefRefPtr<CefDictionaryValue> extra_info,
-                     CefRefPtr<CefRequestContext> request_context) OVERRIDE;
+                     CefRefPtr<CefRequestContext> request_context) override;
   void GetPopupConfig(CefWindowHandle temp_handle,
                       CefWindowInfo& windowInfo,
                       CefRefPtr<CefClient>& client,
-                      CefBrowserSettings& settings) OVERRIDE;
+                      CefBrowserSettings& settings) override;
   void ShowPopup(ClientWindowHandle parent_handle,
                  int x,
                  int y,
                  size_t width,
-                 size_t height) OVERRIDE;
-  void Show() OVERRIDE;
-  void Hide() OVERRIDE;
-  void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
-  void SetFocus(bool focus) OVERRIDE;
-  void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE;
-  float GetDeviceScaleFactor() const OVERRIDE;
-  ClientWindowHandle GetWindowHandle() const OVERRIDE;
+                 size_t height) override;
+  void Show() override;
+  void Hide() override;
+  void SetBounds(int x, int y, size_t width, size_t height) override;
+  void SetFocus(bool focus) override;
+  void SetDeviceScaleFactor(float device_scale_factor) override;
+  float GetDeviceScaleFactor() const override;
+  ClientWindowHandle GetWindowHandle() const override;
 
   // ClientHandlerOsr::OsrDelegate methods.
-  void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  bool GetRootScreenRect(CefRefPtr<CefBrowser> browser, CefRect& rect) OVERRIDE;
-  void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) OVERRIDE;
+  void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
+  void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
+  bool GetRootScreenRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override;
+  void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override;
   bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
                       int viewX,
                       int viewY,
                       int& screenX,
-                      int& screenY) OVERRIDE;
+                      int& screenY) override;
   bool GetScreenInfo(CefRefPtr<CefBrowser> browser,
-                     CefScreenInfo& screen_info) OVERRIDE;
-  void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) OVERRIDE;
-  void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect) OVERRIDE;
+                     CefScreenInfo& screen_info) override;
+  void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) override;
+  void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect) override;
   void OnPaint(CefRefPtr<CefBrowser> browser,
                CefRenderHandler::PaintElementType type,
                const CefRenderHandler::RectList& dirtyRects,
                const void* buffer,
                int width,
-               int height) OVERRIDE;
+               int height) override;
   void OnCursorChange(CefRefPtr<CefBrowser> browser,
                       CefCursorHandle cursor,
-                      CefRenderHandler::CursorType type,
-                      const CefCursorInfo& custom_cursor_info) OVERRIDE;
+                      cef_cursor_type_t type,
+                      const CefCursorInfo& custom_cursor_info) override;
   bool StartDragging(CefRefPtr<CefBrowser> browser,
                      CefRefPtr<CefDragData> drag_data,
                      CefRenderHandler::DragOperationsMask allowed_ops,
                      int x,
-                     int y) OVERRIDE;
+                     int y) override;
   void UpdateDragCursor(CefRefPtr<CefBrowser> browser,
-                        CefRenderHandler::DragOperation operation) OVERRIDE;
+                        CefRenderHandler::DragOperation operation) override;
   void OnImeCompositionRangeChanged(
       CefRefPtr<CefBrowser> browser,
       const CefRange& selection_range,
-      const CefRenderHandler::RectList& character_bounds) OVERRIDE;
+      const CefRenderHandler::RectList& character_bounds) override;
 
-  void UpdateAccessibilityTree(CefRefPtr<CefValue> value) OVERRIDE;
-  void UpdateAccessibilityLocation(CefRefPtr<CefValue> value) OVERRIDE;
+  void UpdateAccessibilityTree(CefRefPtr<CefValue> value) override;
+  void UpdateAccessibilityLocation(CefRefPtr<CefValue> value) override;
 
  private:
-  scoped_ptr<BrowserWindowOsrMacImpl> impl_;
+  std::unique_ptr<BrowserWindowOsrMacImpl> impl_;
 
   DISALLOW_COPY_AND_ASSIGN(BrowserWindowOsrMac);
 
diff --git a/src/tests/cefclient/browser/browser_window_osr_mac.mm b/src/tests/cefclient/browser/browser_window_osr_mac.mm
index da143c1..884b18d 100644
--- a/src/tests/cefclient/browser/browser_window_osr_mac.mm
+++ b/src/tests/cefclient/browser/browser_window_osr_mac.mm
@@ -21,6 +21,10 @@
 
 #import <AppKit/NSAccessibility.h>
 
+// Begin disable NSOpenGL deprecation warnings.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
 @interface BrowserOpenGLView
     : NSOpenGLView <NSDraggingSource, NSDraggingDestination, NSAccessibility> {
  @private
@@ -69,8 +73,9 @@
   }
   ~ScopedGLContext() {
     [NSOpenGLContext clearCurrentContext];
-    if (swap_buffers_)
+    if (swap_buffers_) {
       [context_ flushBuffer];
+    }
   }
 
  private:
@@ -118,15 +123,18 @@
 
     [self resetDragDrop];
 
-    NSArray* types = [NSArray
-        arrayWithObjects:kCEFDragDummyPboardType, NSStringPboardType,
-                         NSFilenamesPboardType, NSPasteboardTypeString, nil];
+    NSArray* types = [NSArray arrayWithObjects:kCEFDragDummyPboardType,
+                                               NSPasteboardTypeFileURL,
+                                               NSPasteboardTypeString, nil];
     [self registerForDraggedTypes:types];
   }
 
   return self;
 }
 
+// End disable NSOpenGL deprecation warnings.
+#pragma clang diagnostic pop
+
 - (void)dealloc {
   [[NSNotificationCenter defaultCenter]
       removeObserver:self
@@ -142,22 +150,25 @@
 }
 
 - (void)detach {
-  renderer_ = NULL;
-  browser_window_ = NULL;
-  if (text_input_client_)
+  renderer_ = nullptr;
+  browser_window_ = nullptr;
+  if (text_input_client_) {
     [text_input_client_ detach];
+  }
 }
 
 - (CefRefPtr<CefBrowser>)getBrowser {
-  if (browser_window_)
+  if (browser_window_) {
     return browser_window_->GetBrowser();
-  return NULL;
+  }
+  return nullptr;
 }
 
 - (void)setFrame:(NSRect)frameRect {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   [super setFrame:frameRect];
   browser->GetHost()->WasResized();
@@ -167,8 +178,9 @@
                 button:(CefBrowserHost::MouseButtonType)type
                   isUp:(bool)isUp {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   CefMouseEvent mouseEvent;
   [self getMouseEvent:mouseEvent forEvent:event];
@@ -189,7 +201,7 @@
   }
 
   browser->GetHost()->SendMouseClickEvent(mouseEvent, type, isUp,
-                                          [event clickCount]);
+                                          static_cast<int>([event clickCount]));
 }
 
 - (void)mouseDown:(NSEvent*)event {
@@ -197,7 +209,7 @@
 }
 
 - (void)rightMouseDown:(NSEvent*)event {
-  if ([event modifierFlags] & NSShiftKeyMask) {
+  if ([event modifierFlags] & NSEventModifierFlagShift) {
     // Start rotation effect.
     last_mouse_pos_ = cur_mouse_pos_ = [self getClickPointForEvent:event];
     rotating_ = true;
@@ -232,8 +244,9 @@
 
 - (void)mouseMoved:(NSEvent*)event {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   if (rotating_) {
     // Apply rotation effect.
@@ -270,8 +283,9 @@
 
 - (void)mouseExited:(NSEvent*)event {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   CefMouseEvent mouseEvent;
   [self getMouseEvent:mouseEvent forEvent:event];
@@ -281,10 +295,11 @@
 
 - (void)keyDown:(NSEvent*)event {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (!browser.get() || !text_input_context_osr_mac_)
+  if (!browser.get() || !text_input_context_osr_mac_) {
     return;
+  }
 
-  if ([event type] != NSFlagsChanged) {
+  if ([event type] != NSEventTypeFlagsChanged) {
     if (text_input_client_) {
       [text_input_client_ HandleKeyEventBeforeTextInputClient:event];
 
@@ -300,8 +315,9 @@
   }
 
   // Check for Caps lock and Toggle Touch Emulation
-  if (client::MainContext::Get()->TouchEventsEnabled())
+  if (client::MainContext::Get()->TouchEventsEnabled()) {
     [self toggleTouchEmulation:event];
+  }
 }
 
 // OSX does not have touch screens, so we emulate it by mapping multitouch
@@ -309,10 +325,14 @@
 // interfere with other Trackpad events, this mapping is only enabled if
 // touch-events=enabled commandline is passed and caps lock key is on.
 - (void)toggleTouchEmulation:(NSEvent*)event {
-  if ([event type] == NSFlagsChanged && [event keyCode] == 0x39) {
+  if ([event type] == NSEventTypeFlagsChanged && [event keyCode] == 0x39) {
     NSUInteger flags = [event modifierFlags];
-    BOOL touch_enabled = flags & NSAlphaShiftKeyMask ? YES : NO;
-    [self setAcceptsTouchEvents:touch_enabled];
+    BOOL touch_enabled = flags & NSEventModifierFlagCapsLock ? YES : NO;
+    if (touch_enabled) {
+      self.allowedTouchTypes |= NSTouchTypeMaskDirect;
+    } else {
+      self.allowedTouchTypes &= ~NSTouchTypeMaskDirect;
+    }
   }
 }
 
@@ -349,7 +369,7 @@
     CefTouchEvent touch_event;
 
     // NSTouch.identity is unique during the life of the touch
-    touch_event.id = touch.identity.hash;
+    touch_event.id = static_cast<int>(touch.identity.hash);
     touch_event.type = [self getTouchPhase:phase];
 
     NSPoint scaled_pos = [touch normalizedPosition];
@@ -406,8 +426,9 @@
 
 - (void)keyUp:(NSEvent*)event {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   CefKeyEvent keyEvent;
   [self getKeyEvent:keyEvent forEvent:event];
@@ -417,16 +438,18 @@
 }
 
 - (void)flagsChanged:(NSEvent*)event {
-  if ([self isKeyUpEvent:event])
+  if ([self isKeyUpEvent:event]) {
     [self keyUp:event];
-  else
+  } else {
     [self keyDown:event];
+  }
 }
 
 - (void)shortCircuitScrollWheelEvent:(NSEvent*)event {
   if ([event phase] != NSEventPhaseEnded &&
-      [event phase] != NSEventPhaseCancelled)
+      [event phase] != NSEventPhaseCancelled) {
     return;
+  }
 
   [self sendScrollWheelEvet:event];
 
@@ -443,7 +466,7 @@
   // events to the renderer.
   if ([event phase] == NSEventPhaseBegan && !endWheelMonitor_) {
     endWheelMonitor_ = [NSEvent
-        addLocalMonitorForEventsMatchingMask:NSScrollWheelMask
+        addLocalMonitorForEventsMatchingMask:NSEventMaskScrollWheel
                                      handler:^(NSEvent* blockEvent) {
                                        [self shortCircuitScrollWheelEvent:
                                                  blockEvent];
@@ -456,16 +479,17 @@
 
 - (void)sendScrollWheelEvet:(NSEvent*)event {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   CGEventRef cgEvent = [event CGEvent];
   DCHECK(cgEvent);
 
-  int deltaX =
-      CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis2);
-  int deltaY =
-      CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1);
+  int deltaX = static_cast<int>(
+      CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis2));
+  int deltaY = static_cast<int>(
+      CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1));
 
   CefMouseEvent mouseEvent;
   [self getMouseEvent:mouseEvent forEvent:event];
@@ -475,18 +499,18 @@
 
 - (BOOL)canBecomeKeyView {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  return (browser.get() != NULL);
+  return (browser.get() != nullptr);
 }
 
 - (BOOL)acceptsFirstResponder {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  return (browser.get() != NULL);
+  return (browser.get() != nullptr);
 }
 
 - (BOOL)becomeFirstResponder {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
   if (browser.get()) {
-    browser->GetHost()->SendFocusEvent(true);
+    browser->GetHost()->SetFocus(true);
     return [super becomeFirstResponder];
   }
 
@@ -496,7 +520,7 @@
 - (BOOL)resignFirstResponder {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
   if (browser.get()) {
-    browser->GetHost()->SendFocusEvent(false);
+    browser->GetHost()->SetFocus(false);
     return [super resignFirstResponder];
   }
 
@@ -505,44 +529,51 @@
 
 - (void)undo:(id)sender {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (browser.get())
+  if (browser.get()) {
     browser->GetFocusedFrame()->Undo();
+  }
 }
 
 - (void)redo:(id)sender {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (browser.get())
+  if (browser.get()) {
     browser->GetFocusedFrame()->Redo();
+  }
 }
 
 - (void)cut:(id)sender {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (browser.get())
+  if (browser.get()) {
     browser->GetFocusedFrame()->Cut();
+  }
 }
 
 - (void)copy:(id)sender {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (browser.get())
+  if (browser.get()) {
     browser->GetFocusedFrame()->Copy();
+  }
 }
 
 - (void)paste:(id)sender {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (browser.get())
+  if (browser.get()) {
     browser->GetFocusedFrame()->Paste();
+  }
 }
 
 - (void)delete:(id)sender {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (browser.get())
+  if (browser.get()) {
     browser->GetFocusedFrame()->Delete();
+  }
 }
 
 - (void)selectAll:(id)sender {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (browser.get())
+  if (browser.get()) {
     browser->GetFocusedFrame()->SelectAll();
+  }
 }
 
 - (NSPoint)getClickPointForEvent:(NSEvent*)event {
@@ -556,17 +587,19 @@
 }
 
 - (void)getKeyEvent:(CefKeyEvent&)keyEvent forEvent:(NSEvent*)event {
-  if ([event type] == NSKeyDown || [event type] == NSKeyUp) {
+  if ([event type] == NSEventTypeKeyDown || [event type] == NSEventTypeKeyUp) {
     NSString* s = [event characters];
-    if ([s length] > 0)
+    if ([s length] > 0) {
       keyEvent.character = [s characterAtIndex:0];
+    }
 
     s = [event charactersIgnoringModifiers];
-    if ([s length] > 0)
+    if ([s length] > 0) {
       keyEvent.unmodified_character = [s characterAtIndex:0];
+    }
   }
 
-  if ([event type] == NSFlagsChanged) {
+  if ([event type] == NSEventTypeFlagsChanged) {
     keyEvent.character = 0;
     keyEvent.unmodified_character = 0;
   }
@@ -602,8 +635,9 @@
 
   int device_x = point.x;
   int device_y = point.y;
-  if ([self isOverPopupWidgetX:device_x andY:device_y])
+  if ([self isOverPopupWidgetX:device_x andY:device_y]) {
     [self applyPopupOffsetToX:device_x andY:device_y];
+  }
 
   // Convert to browser view coordinates.
   mouseEvent.x = client::DeviceToLogical(device_x, device_scale_factor);
@@ -627,28 +661,34 @@
   mouseEvent.x = client::DeviceToLogical(point.x, device_scale_factor);
   mouseEvent.y = client::DeviceToLogical(point.y, device_scale_factor);
 
-  mouseEvent.modifiers = [NSEvent modifierFlags];
+  mouseEvent.modifiers = static_cast<uint32_t>([NSEvent modifierFlags]);
 }
 
 - (int)getModifiersForEvent:(NSEvent*)event {
   int modifiers = 0;
 
-  if ([event modifierFlags] & NSControlKeyMask)
+  if ([event modifierFlags] & NSEventModifierFlagControl) {
     modifiers |= EVENTFLAG_CONTROL_DOWN;
-  if ([event modifierFlags] & NSShiftKeyMask)
+  }
+  if ([event modifierFlags] & NSEventModifierFlagShift) {
     modifiers |= EVENTFLAG_SHIFT_DOWN;
-  if ([event modifierFlags] & NSAlternateKeyMask)
+  }
+  if ([event modifierFlags] & NSEventModifierFlagOption) {
     modifiers |= EVENTFLAG_ALT_DOWN;
-  if ([event modifierFlags] & NSCommandKeyMask)
+  }
+  if ([event modifierFlags] & NSEventModifierFlagCommand) {
     modifiers |= EVENTFLAG_COMMAND_DOWN;
-  if ([event modifierFlags] & NSAlphaShiftKeyMask)
+  }
+  if ([event modifierFlags] & NSEventModifierFlagCapsLock) {
     modifiers |= EVENTFLAG_CAPS_LOCK_ON;
+  }
 
-  if ([event type] == NSKeyUp || [event type] == NSKeyDown ||
-      [event type] == NSFlagsChanged) {
+  if ([event type] == NSEventTypeKeyUp || [event type] == NSEventTypeKeyDown ||
+      [event type] == NSEventTypeFlagsChanged) {
     // Only perform this check for key events
-    if ([self isKeyPadEvent:event])
+    if ([self isKeyPadEvent:event]) {
       modifiers |= EVENTFLAG_IS_KEY_PAD;
+    }
   }
 
   // OS X does not have a modifier for NumLock, so I'm not entirely sure how to
@@ -658,19 +698,19 @@
 
   // Mouse buttons
   switch ([event type]) {
-    case NSLeftMouseDragged:
-    case NSLeftMouseDown:
-    case NSLeftMouseUp:
+    case NSEventTypeLeftMouseDragged:
+    case NSEventTypeLeftMouseDown:
+    case NSEventTypeLeftMouseUp:
       modifiers |= EVENTFLAG_LEFT_MOUSE_BUTTON;
       break;
-    case NSRightMouseDragged:
-    case NSRightMouseDown:
-    case NSRightMouseUp:
+    case NSEventTypeRightMouseDragged:
+    case NSEventTypeRightMouseDown:
+    case NSEventTypeRightMouseUp:
       modifiers |= EVENTFLAG_RIGHT_MOUSE_BUTTON;
       break;
-    case NSOtherMouseDragged:
-    case NSOtherMouseDown:
-    case NSOtherMouseUp:
+    case NSEventTypeOtherMouseDragged:
+    case NSEventTypeOtherMouseDown:
+    case NSEventTypeOtherMouseUp:
       modifiers |= EVENTFLAG_MIDDLE_MOUSE_BUTTON;
       break;
     default:
@@ -681,40 +721,42 @@
 }
 
 - (BOOL)isKeyUpEvent:(NSEvent*)event {
-  if ([event type] != NSFlagsChanged)
-    return [event type] == NSKeyUp;
+  if ([event type] != NSEventTypeFlagsChanged) {
+    return [event type] == NSEventTypeKeyUp;
+  }
 
   // FIXME: This logic fails if the user presses both Shift keys at once, for
   // example: we treat releasing one of them as keyDown.
   switch ([event keyCode]) {
     case 54:  // Right Command
     case 55:  // Left Command
-      return ([event modifierFlags] & NSCommandKeyMask) == 0;
+      return ([event modifierFlags] & NSEventModifierFlagCommand) == 0;
 
     case 57:  // Capslock
-      return ([event modifierFlags] & NSAlphaShiftKeyMask) == 0;
+      return ([event modifierFlags] & NSEventModifierFlagCapsLock) == 0;
 
     case 56:  // Left Shift
     case 60:  // Right Shift
-      return ([event modifierFlags] & NSShiftKeyMask) == 0;
+      return ([event modifierFlags] & NSEventModifierFlagShift) == 0;
 
     case 58:  // Left Alt
     case 61:  // Right Alt
-      return ([event modifierFlags] & NSAlternateKeyMask) == 0;
+      return ([event modifierFlags] & NSEventModifierFlagOption) == 0;
 
     case 59:  // Left Ctrl
     case 62:  // Right Ctrl
-      return ([event modifierFlags] & NSControlKeyMask) == 0;
+      return ([event modifierFlags] & NSEventModifierFlagControl) == 0;
 
     case 63:  // Function
-      return ([event modifierFlags] & NSFunctionKeyMask) == 0;
+      return ([event modifierFlags] & NSEventModifierFlagFunction) == 0;
   }
   return false;
 }
 
 - (BOOL)isKeyPadEvent:(NSEvent*)event {
-  if ([event modifierFlags] & NSNumericPadKeyMask)
+  if ([event modifierFlags] & NSEventModifierFlagNumericPad) {
     return true;
+  }
 
   switch ([event keyCode]) {
     case 71:  // Clear
@@ -763,8 +805,9 @@
   }
 
   // The Invalidate below fixes flicker when resizing.
-  if ([self inLiveResize] && browser.get())
+  if ([self inLiveResize] && browser.get()) {
     browser->GetHost()->Invalidate(PET_VIEW);
+  }
 }
 
 // Drag and drop
@@ -787,9 +830,9 @@
   NSWindow* window = [self window];
   NSTimeInterval eventTime = [currentEvent timestamp];
 
-  NSEvent* dragEvent = [NSEvent mouseEventWithType:NSLeftMouseDragged
+  NSEvent* dragEvent = [NSEvent mouseEventWithType:NSEventTypeLeftMouseDragged
                                           location:position
-                                     modifierFlags:NSLeftMouseDraggedMask
+                                     modifierFlags:NSEventMaskLeftMouseDragged
                                          timestamp:eventTime
                                       windowNumber:[window windowNumber]
                                            context:nil
@@ -830,26 +873,31 @@
 }
 
 - (NSArray*)namesOfPromisedFilesDroppedAtDestination:(NSURL*)dropDest {
-  if (![dropDest isFileURL])
+  if (![dropDest isFileURL]) {
     return nil;
+  }
 
-  if (!current_drag_data_)
+  if (!current_drag_data_) {
     return nil;
+  }
 
-  size_t expected_size = current_drag_data_->GetFileContents(NULL);
-  if (expected_size == 0)
+  size_t expected_size = current_drag_data_->GetFileContents(nullptr);
+  if (expected_size == 0) {
     return nil;
+  }
 
   std::string path = [[dropDest path] UTF8String];
   path.append("/");
   path.append(current_drag_data_->GetFileName().ToString());
 
   CefRefPtr<CefStreamWriter> writer = CefStreamWriter::CreateForFile(path);
-  if (!writer)
+  if (!writer) {
     return nil;
+  }
 
-  if (current_drag_data_->GetFileContents(writer) != expected_size)
+  if (current_drag_data_->GetFileContents(writer) != expected_size) {
     return nil;
+  }
 
   return @[ [NSString stringWithUTF8String:path.c_str()] ];
 }
@@ -858,11 +906,13 @@
              endedAt:(NSPoint)screenPoint
            operation:(NSDragOperation)operation {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
-  if (operation == (NSDragOperationMove | NSDragOperationCopy))
+  if (operation == (NSDragOperationMove | NSDragOperationCopy)) {
     operation &= ~NSDragOperationMove;
+  }
 
   NSPoint windowPoint = [[self window] convertScreenToBase:screenPoint];
   NSPoint pt = [self flipWindowPointToView:windowPoint];
@@ -877,8 +927,9 @@
 
 - (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (!browser.get())
+  if (!browser.get()) {
     return NSDragOperationNone;
+  }
 
   CefRefPtr<CefDragData> drag_data;
   if (!current_drag_data_) {
@@ -905,8 +956,9 @@
 
 - (void)draggingExited:(id<NSDraggingInfo>)sender {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (browser.get())
+  if (browser.get()) {
     browser->GetHost()->DragTargetDragLeave();
+  }
 }
 
 - (BOOL)prepareForDragOperation:(id<NSDraggingInfo>)info {
@@ -915,8 +967,9 @@
 
 - (BOOL)performDragOperation:(id<NSDraggingInfo>)info {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (!browser.get())
+  if (!browser.get()) {
     return NO;
+  }
 
   CefMouseEvent mouseEvent;
   [self getMouseEvent:mouseEvent forDragInfo:info];
@@ -928,8 +981,9 @@
 
 - (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)info {
   CefRefPtr<CefBrowser> browser = [self getBrowser];
-  if (!browser.get())
+  if (!browser.get()) {
     return NSDragOperationNone;
+  }
 
   CefMouseEvent mouseEvent;
   [self getMouseEvent:mouseEvent forDragInfo:info];
@@ -951,7 +1005,7 @@
   }
 
   // URL.
-  if ([type isEqualToString:NSURLPboardType]) {
+  if ([type isEqualToString:NSPasteboardTypeURL]) {
     DCHECK(current_drag_data_->IsLink());
     NSString* strUrl =
         [NSString stringWithUTF8String:current_drag_data_->GetLinkURL()
@@ -969,26 +1023,26 @@
 
     // File contents.
   } else if ([type isEqualToString:fileUTI_]) {
-    size_t size = current_drag_data_->GetFileContents(NULL);
+    size_t size = current_drag_data_->GetFileContents(nullptr);
     DCHECK_GT(size, 0U);
     CefRefPtr<client::BytesWriteHandler> handler =
         new client::BytesWriteHandler(size);
     CefRefPtr<CefStreamWriter> writer =
         CefStreamWriter::CreateForHandler(handler.get());
     current_drag_data_->GetFileContents(writer);
-    DCHECK_EQ(handler->GetDataSize(), static_cast<int64>(size));
+    DCHECK_EQ(handler->GetDataSize(), static_cast<int64_t>(size));
 
     [pboard setData:[NSData dataWithBytes:handler->GetData()
                                    length:handler->GetDataSize()]
             forType:fileUTI_];
 
     // Plain text.
-  } else if ([type isEqualToString:NSStringPboardType]) {
+  } else if ([type isEqualToString:NSPasteboardTypeString]) {
     NSString* strTitle =
         [NSString stringWithUTF8String:current_drag_data_->GetFragmentText()
                                            .ToString()
                                            .c_str()];
-    [pboard setString:strTitle forType:NSStringPboardType];
+    [pboard setString:strTitle forType:NSPasteboardTypeString];
 
   } else if ([type isEqualToString:kCEFDragDummyPboardType]) {
     // The dummy type _was_ promised and someone decided to call the bluff.
@@ -998,15 +1052,17 @@
 
 // NSAccessibility Protocol implementation.
 - (BOOL)accessibilityIsIgnored {
-  if (!accessibility_helper_)
+  if (!accessibility_helper_) {
     return YES;
-  else
+  } else {
     return NO;
+  }
 }
 
 - (id)accessibilityAttributeValue:(NSString*)attribute {
-  if (!accessibility_helper_)
+  if (!accessibility_helper_) {
     return [super accessibilityAttributeValue:attribute];
+  }
   if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
     return NSAccessibilityGroupRole;
   } else if ([attribute isEqualToString:NSAccessibilityDescriptionAttribute]) {
@@ -1025,7 +1081,7 @@
     // Add Root as first Kid
     NSMutableArray* kids = [NSMutableArray arrayWithCapacity:1];
     NSObject* child = CAST_CEF_NATIVE_ACCESSIBLE_TO_NSOBJECT(
-        node->GetNativeAccessibleObject(NULL));
+        node->GetNativeAccessibleObject(nullptr));
     [kids addObject:child];
     return NSAccessibilityUnignoredChildren(kids);
   } else {
@@ -1037,7 +1093,7 @@
   if (accessibility_helper_) {
     client::OsrAXNode* node = accessibility_helper_->GetFocusedNode();
     return node ? CAST_CEF_NATIVE_ACCESSIBLE_TO_NSOBJECT(
-                      node->GetNativeAccessibleObject(NULL))
+                      node->GetNativeAccessibleObject(nullptr))
                 : nil;
   }
   return nil;
@@ -1047,7 +1103,7 @@
 - (void)resetDragDrop {
   current_drag_op_ = NSDragOperationNone;
   current_allowed_ops_ = NSDragOperationNone;
-  current_drag_data_ = NULL;
+  current_drag_data_ = nullptr;
   if (fileUTI_) {
 #if !__has_feature(objc_arc)
     [fileUTI_ release];
@@ -1064,7 +1120,7 @@
 
 - (void)fillPasteboard {
   DCHECK(!pasteboard_);
-  pasteboard_ = [NSPasteboard pasteboardWithName:NSDragPboard];
+  pasteboard_ = [NSPasteboard pasteboardWithName:NSPasteboardNameDrag];
 #if !__has_feature(objc_arc)
   [pasteboard_ retain];
 #endif  // !__has_feature(objc_arc)
@@ -1073,15 +1129,14 @@
 
   // URL (and title).
   if (current_drag_data_->IsLink()) {
-    [pasteboard_ addTypes:@[ NSURLPboardType, kNSURLTitlePboardType ]
+    [pasteboard_ addTypes:@[ NSPasteboardTypeURL, kNSURLTitlePboardType ]
                     owner:self];
   }
 
   // MIME type.
   CefString mimeType;
-  size_t contents_size = current_drag_data_->GetFileContents(NULL);
+  size_t contents_size = current_drag_data_->GetFileContents(nullptr);
   CefString download_metadata = current_drag_data_->GetLinkMetadata();
-  CefString file_name = current_drag_data_->GetFileName();
 
   // File.
   if (contents_size > 0) {
@@ -1097,13 +1152,19 @@
                                              mimeType.ToString().c_str(),
                                              kCFStringEncodingUTF8);
       fileUTI_ = (__bridge NSString*)UTTypeCreatePreferredIdentifierForTag(
-          kUTTagClassMIMEType, mimeTypeCF, NULL);
+          kUTTagClassMIMEType, mimeTypeCF, nullptr);
       CFRelease(mimeTypeCF);
       // File (HFS) promise.
       NSArray* fileUTIList = @[ fileUTI_ ];
-      [pasteboard_ addTypes:@[ NSFilesPromisePboardType ] owner:self];
+      NSString* NSPasteboardTypeFileURLPromise =
+#if __has_feature(objc_arc)
+          (__bridge NSString*)kPasteboardTypeFileURLPromise;
+#else
+          (NSString*)kPasteboardTypeFileURLPromise;
+#endif
+      [pasteboard_ addTypes:@[ NSPasteboardTypeFileURLPromise ] owner:self];
       [pasteboard_ setPropertyList:fileUTIList
-                           forType:NSFilesPromisePboardType];
+                           forType:NSPasteboardTypeFileURLPromise];
 
       [pasteboard_ addTypes:fileUTIList owner:self];
     }
@@ -1111,7 +1172,7 @@
 
   // Plain text.
   if (!current_drag_data_->GetFragmentText().empty()) {
-    [pasteboard_ addTypes:@[ NSStringPboardType ] owner:self];
+    [pasteboard_ addTypes:@[ NSPasteboardTypeString ] owner:self];
   }
 }
 
@@ -1123,14 +1184,14 @@
   NSArray* types = [pboard types];
 
   // Get plain text.
-  if ([types containsObject:NSStringPboardType]) {
+  if ([types containsObject:NSPasteboardTypeString]) {
     data->SetFragmentText(
-        [[pboard stringForType:NSStringPboardType] UTF8String]);
+        [[pboard stringForType:NSPasteboardTypeString] UTF8String]);
   }
 
   // Get files.
-  if ([types containsObject:NSFilenamesPboardType]) {
-    NSArray* files = [pboard propertyListForType:NSFilenamesPboardType];
+  if ([types containsObject:NSPasteboardTypeFileURL]) {
+    NSArray* files = [pboard propertyListForType:NSPasteboardTypeFileURL];
     if ([files isKindOfClass:[NSArray class]] && [files count]) {
       for (NSUInteger i = 0; i < [files count]; i++) {
         NSString* filename = [files objectAtIndex:i];
@@ -1154,18 +1215,21 @@
 - (void)resetDeviceScaleFactor {
   float device_scale_factor = 1.0f;
   NSWindow* window = [self window];
-  if (window)
+  if (window) {
     device_scale_factor = [window backingScaleFactor];
+  }
   [self setDeviceScaleFactor:device_scale_factor];
 }
 
 - (void)setDeviceScaleFactor:(float)device_scale_factor {
-  if (device_scale_factor == device_scale_factor_)
+  if (device_scale_factor == device_scale_factor_) {
     return;
+  }
 
   // Apply some sanity checks.
-  if (device_scale_factor < 1.0f || device_scale_factor > 4.0f)
+  if (device_scale_factor < 1.0f || device_scale_factor > 4.0f) {
     return;
+  }
 
   device_scale_factor_ = device_scale_factor;
 
@@ -1181,10 +1245,12 @@
 }
 
 - (void)viewDidChangeBackingProperties {
+  [super viewDidChangeBackingProperties];
   const CGFloat device_scale_factor = [self getDeviceScaleFactor];
 
-  if (device_scale_factor == device_scale_factor_)
+  if (device_scale_factor == device_scale_factor_) {
     return;
+  }
 
   CefRefPtr<CefBrowser> browser = [self getBrowser];
   if (browser) {
@@ -1237,8 +1303,9 @@
 
 - (void)ChangeCompositionRange:(CefRange)range
               character_bounds:(const CefRenderHandler::RectList&)bounds {
-  if (text_input_client_)
+  if (text_input_client_) {
     [text_input_client_ ChangeCompositionRange:range character_bounds:bounds];
+  }
 }
 
 - (void)UpdateAccessibilityTree:(CefRefPtr<CefValue>)value {
@@ -1323,7 +1390,7 @@
                int height);
   void OnCursorChange(CefRefPtr<CefBrowser> browser,
                       CefCursorHandle cursor,
-                      CefRenderHandler::CursorType type,
+                      cef_cursor_type_t type,
                       const CefCursorInfo& custom_cursor_info);
   bool StartDragging(CefRefPtr<CefBrowser> browser,
                      CefRefPtr<CefDragData> drag_data,
@@ -1431,17 +1498,18 @@
   }
 
   // Give focus to the browser.
-  browser_window_.browser_->GetHost()->SendFocusEvent(true);
+  browser_window_.browser_->GetHost()->SetFocus(true);
 }
 
 void BrowserWindowOsrMacImpl::Hide() {
   REQUIRE_MAIN_THREAD();
 
-  if (!browser_window_.browser_.get())
+  if (!browser_window_.browser_.get()) {
     return;
+  }
 
   // Remove focus from the browser.
-  browser_window_.browser_->GetHost()->SendFocusEvent(false);
+  browser_window_.browser_->GetHost()->SetFocus(false);
 
   if (!hidden_) {
     // Set the browser as hidden.
@@ -1460,20 +1528,23 @@
 
 void BrowserWindowOsrMacImpl::SetFocus(bool focus) {
   REQUIRE_MAIN_THREAD();
-  if (native_browser_view_)
+  if (native_browser_view_) {
     [native_browser_view_.window makeFirstResponder:native_browser_view_];
+  }
 }
 
 void BrowserWindowOsrMacImpl::SetDeviceScaleFactor(float device_scale_factor) {
   REQUIRE_MAIN_THREAD();
-  if (native_browser_view_)
+  if (native_browser_view_) {
     [native_browser_view_ setDeviceScaleFactor:device_scale_factor];
+  }
 }
 
 float BrowserWindowOsrMacImpl::GetDeviceScaleFactor() const {
   REQUIRE_MAIN_THREAD();
-  if (native_browser_view_)
+  if (native_browser_view_) {
     return [native_browser_view_ getDeviceScaleFactor];
+  }
   return 1.0f;
 }
 
@@ -1524,11 +1595,13 @@
 
   // Convert to browser view coordinates.
   rect.width = DeviceToLogical(bounds.size.width, device_scale_factor);
-  if (rect.width == 0)
+  if (rect.width == 0) {
     rect.width = 1;
+  }
   rect.height = DeviceToLogical(bounds.size.height, device_scale_factor);
-  if (rect.height == 0)
+  if (rect.height == 0) {
     rect.height = 1;
+  }
 }
 
 bool BrowserWindowOsrMacImpl::GetScreenPoint(CefRefPtr<CefBrowser> browser,
@@ -1539,8 +1612,9 @@
   CEF_REQUIRE_UI_THREAD();
   REQUIRE_MAIN_THREAD();
 
-  if (!native_browser_view_)
+  if (!native_browser_view_) {
     return false;
+  }
 
   const float device_scale_factor = [native_browser_view_ getDeviceScaleFactor];
 
@@ -1571,8 +1645,9 @@
   CEF_REQUIRE_UI_THREAD();
   REQUIRE_MAIN_THREAD();
 
-  if (!native_browser_view_)
+  if (!native_browser_view_) {
     return false;
+  }
 
   CefRect view_rect;
   GetViewRect(browser, view_rect);
@@ -1592,8 +1667,9 @@
   CEF_REQUIRE_UI_THREAD();
   REQUIRE_MAIN_THREAD();
 
-  if (!native_browser_view_)
+  if (!native_browser_view_) {
     return;
+  }
 
   if (!show) {
     renderer_.ClearPopupRects();
@@ -1607,8 +1683,9 @@
   CEF_REQUIRE_UI_THREAD();
   REQUIRE_MAIN_THREAD();
 
-  if (!native_browser_view_)
+  if (!native_browser_view_) {
     return;
+  }
 
   const float device_scale_factor = [native_browser_view_ getDeviceScaleFactor];
 
@@ -1628,8 +1705,9 @@
   CEF_REQUIRE_UI_THREAD();
   REQUIRE_MAIN_THREAD();
 
-  if (!native_browser_view_)
+  if (!native_browser_view_) {
     return;
+  }
 
   if (width <= 2 && height <= 2) {
     // Ignore really small buffer sizes while the widget is starting up.
@@ -1655,7 +1733,7 @@
 void BrowserWindowOsrMacImpl::OnCursorChange(
     CefRefPtr<CefBrowser> browser,
     CefCursorHandle cursor,
-    CefRenderHandler::CursorType type,
+    cef_cursor_type_t type,
     const CefCursorInfo& custom_cursor_info) {
   CEF_REQUIRE_UI_THREAD();
   REQUIRE_MAIN_THREAD();
@@ -1672,8 +1750,9 @@
   CEF_REQUIRE_UI_THREAD();
   REQUIRE_MAIN_THREAD();
 
-  if (!native_browser_view_)
+  if (!native_browser_view_) {
     return false;
+  }
 
   static float device_scale_factor =
       [native_browser_view_ getDeviceScaleFactor];
@@ -1700,8 +1779,9 @@
   CEF_REQUIRE_UI_THREAD();
   REQUIRE_MAIN_THREAD();
 
-  if (native_browser_view_)
+  if (native_browser_view_) {
     [native_browser_view_ setCurrentDragOp:operation];
+  }
 }
 
 void BrowserWindowOsrMacImpl::OnImeCompositionRangeChanged(
@@ -1761,10 +1841,12 @@
 }
 
 BrowserWindowOsrMac::BrowserWindowOsrMac(BrowserWindow::Delegate* delegate,
+                                         bool with_controls,
                                          const std::string& startup_url,
                                          const OsrRendererSettings& settings)
     : BrowserWindow(delegate) {
-  client_handler_ = new ClientHandlerOsr(this, this, startup_url);
+  client_handler_ =
+      new ClientHandlerOsr(this, this, with_controls, startup_url);
   impl_.reset(
       new BrowserWindowOsrMacImpl(delegate, startup_url, settings, *this));
 }
@@ -1877,7 +1959,7 @@
 void BrowserWindowOsrMac::OnCursorChange(
     CefRefPtr<CefBrowser> browser,
     CefCursorHandle cursor,
-    CefRenderHandler::CursorType type,
+    cef_cursor_type_t type,
     const CefCursorInfo& custom_cursor_info) {
   impl_->OnCursorChange(browser, cursor, type, custom_cursor_info);
 }
diff --git a/src/tests/cefclient/browser/browser_window_osr_win.cc b/src/tests/cefclient/browser/browser_window_osr_win.cc
index 053c655..3a9e3c6 100644
--- a/src/tests/cefclient/browser/browser_window_osr_win.cc
+++ b/src/tests/cefclient/browser/browser_window_osr_win.cc
@@ -9,11 +9,13 @@
 namespace client {
 
 BrowserWindowOsrWin::BrowserWindowOsrWin(BrowserWindow::Delegate* delegate,
+                                         bool with_controls,
                                          const std::string& startup_url,
                                          const OsrRendererSettings& settings)
-    : BrowserWindow(delegate), osr_hwnd_(NULL), device_scale_factor_(0) {
+    : BrowserWindow(delegate), osr_hwnd_(nullptr), device_scale_factor_(0) {
   osr_window_ = new OsrWindowWin(this, settings);
-  client_handler_ = new ClientHandlerOsr(this, osr_window_.get(), startup_url);
+  client_handler_ =
+      new ClientHandlerOsr(this, osr_window_.get(), with_controls, startup_url);
 }
 
 void BrowserWindowOsrWin::CreateBrowser(
@@ -55,46 +57,54 @@
                                     size_t width,
                                     size_t height) {
   REQUIRE_MAIN_THREAD();
-  if (osr_window_)
+  if (osr_window_) {
     osr_window_->ShowPopup(parent_handle, x, y, width, height);
+  }
 }
 
 void BrowserWindowOsrWin::Show() {
   REQUIRE_MAIN_THREAD();
-  if (osr_window_)
+  if (osr_window_) {
     osr_window_->Show();
+  }
 }
 
 void BrowserWindowOsrWin::Hide() {
   REQUIRE_MAIN_THREAD();
-  if (osr_window_)
+  if (osr_window_) {
     osr_window_->Hide();
+  }
 }
 
 void BrowserWindowOsrWin::SetBounds(int x, int y, size_t width, size_t height) {
   REQUIRE_MAIN_THREAD();
-  if (osr_window_)
+  if (osr_window_) {
     osr_window_->SetBounds(x, y, width, height);
+  }
 }
 
 void BrowserWindowOsrWin::SetFocus(bool focus) {
   REQUIRE_MAIN_THREAD();
-  if (osr_window_ && focus)
+  if (osr_window_ && focus) {
     osr_window_->SetFocus();
+  }
 }
 
 void BrowserWindowOsrWin::SetDeviceScaleFactor(float device_scale_factor) {
   REQUIRE_MAIN_THREAD();
-  if (device_scale_factor == device_scale_factor_)
+  if (device_scale_factor == device_scale_factor_) {
     return;
+  }
 
   // Apply some sanity checks.
-  if (device_scale_factor < 1.0f || device_scale_factor > 4.0f)
+  if (device_scale_factor < 1.0f || device_scale_factor > 4.0f) {
     return;
+  }
 
   device_scale_factor_ = device_scale_factor;
-  if (osr_window_)
+  if (osr_window_) {
     osr_window_->SetDeviceScaleFactor(device_scale_factor);
+  }
 }
 
 float BrowserWindowOsrWin::GetDeviceScaleFactor() const {
diff --git a/src/tests/cefclient/browser/browser_window_osr_win.h b/src/tests/cefclient/browser/browser_window_osr_win.h
index 9cf3027..e8caf71 100644
--- a/src/tests/cefclient/browser/browser_window_osr_win.h
+++ b/src/tests/cefclient/browser/browser_window_osr_win.h
@@ -20,6 +20,7 @@
   // Constructor may be called on any thread.
   // |delegate| must outlive this object.
   BrowserWindowOsrWin(BrowserWindow::Delegate* delegate,
+                      bool with_controls,
                       const std::string& startup_url,
                       const OsrRendererSettings& settings);
 
@@ -28,30 +29,30 @@
                      const CefRect& rect,
                      const CefBrowserSettings& settings,
                      CefRefPtr<CefDictionaryValue> extra_info,
-                     CefRefPtr<CefRequestContext> request_context) OVERRIDE;
+                     CefRefPtr<CefRequestContext> request_context) override;
   void GetPopupConfig(CefWindowHandle temp_handle,
                       CefWindowInfo& windowInfo,
                       CefRefPtr<CefClient>& client,
-                      CefBrowserSettings& settings) OVERRIDE;
+                      CefBrowserSettings& settings) override;
   void ShowPopup(ClientWindowHandle parent_handle,
                  int x,
                  int y,
                  size_t width,
-                 size_t height) OVERRIDE;
-  void Show() OVERRIDE;
-  void Hide() OVERRIDE;
-  void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
-  void SetFocus(bool focus) OVERRIDE;
-  void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE;
-  float GetDeviceScaleFactor() const OVERRIDE;
-  ClientWindowHandle GetWindowHandle() const OVERRIDE;
+                 size_t height) override;
+  void Show() override;
+  void Hide() override;
+  void SetBounds(int x, int y, size_t width, size_t height) override;
+  void SetFocus(bool focus) override;
+  void SetDeviceScaleFactor(float device_scale_factor) override;
+  float GetDeviceScaleFactor() const override;
+  ClientWindowHandle GetWindowHandle() const override;
 
  private:
   // ClienHandler::Delegate methods.
-  void OnBrowserClosed(CefRefPtr<CefBrowser> browser) OVERRIDE;
+  void OnBrowserClosed(CefRefPtr<CefBrowser> browser) override;
 
   // OsrWindowWin::Delegate methods.
-  void OnOsrNativeWindowCreated(HWND hwnd) OVERRIDE;
+  void OnOsrNativeWindowCreated(HWND hwnd) override;
 
   // The below members are only accessed on the main thread.
   scoped_refptr<OsrWindowWin> osr_window_;
diff --git a/src/tests/cefclient/browser/browser_window_std_gtk.cc b/src/tests/cefclient/browser/browser_window_std_gtk.cc
index 4810f52..8d4bd57 100644
--- a/src/tests/cefclient/browser/browser_window_std_gtk.cc
+++ b/src/tests/cefclient/browser/browser_window_std_gtk.cc
@@ -38,12 +38,13 @@
   Atom atoms[3];
   int result =
       XInternAtoms(xdisplay, const_cast<char**>(kAtoms), 3, false, atoms);
-  if (!result)
+  if (!result) {
     NOTREACHED();
+  }
 
   if (!visible) {
     // Set the hidden property state value.
-    scoped_ptr<Atom[]> data(new Atom[1]);
+    std::unique_ptr<Atom[]> data(new Atom[1]);
     data[0] = atoms[2];
 
     XChangeProperty(xdisplay, xwindow,
@@ -59,7 +60,7 @@
                     atoms[0],  // name
                     atoms[1],  // type
                     32,        // size in bits of items in 'value'
-                    PropModeReplace, NULL,
+                    PropModeReplace, nullptr,
                     0);  // num items
   }
 }
@@ -82,9 +83,10 @@
 }  // namespace
 
 BrowserWindowStdGtk::BrowserWindowStdGtk(Delegate* delegate,
+                                         bool with_controls,
                                          const std::string& startup_url)
     : BrowserWindow(delegate), xdisplay_(nullptr) {
-  client_handler_ = new ClientHandlerStd(this, startup_url);
+  client_handler_ = new ClientHandlerStd(this, with_controls, startup_url);
 }
 
 void BrowserWindowStdGtk::set_xdisplay(XDisplay* xdisplay) {
@@ -173,8 +175,9 @@
 void BrowserWindowStdGtk::SetFocus(bool focus) {
   REQUIRE_MAIN_THREAD();
 
-  if (browser_)
+  if (browser_) {
     browser_->GetHost()->SetFocus(focus);
+  }
 }
 
 ClientWindowHandle BrowserWindowStdGtk::GetWindowHandle() const {
@@ -182,7 +185,7 @@
 
   // There is no GtkWidget* representation of this object.
   NOTREACHED();
-  return NULL;
+  return nullptr;
 }
 
 }  // namespace client
diff --git a/src/tests/cefclient/browser/browser_window_std_gtk.h b/src/tests/cefclient/browser/browser_window_std_gtk.h
index 300f37f..28d5078 100644
--- a/src/tests/cefclient/browser/browser_window_std_gtk.h
+++ b/src/tests/cefclient/browser/browser_window_std_gtk.h
@@ -17,7 +17,9 @@
  public:
   // Constructor may be called on any thread.
   // |delegate| must outlive this object.
-  BrowserWindowStdGtk(Delegate* delegate, const std::string& startup_url);
+  BrowserWindowStdGtk(Delegate* delegate,
+                      bool with_controls,
+                      const std::string& startup_url);
 
   // Called from RootWindowGtk::CreateRootWindow before CreateBrowser.
   void set_xdisplay(XDisplay* xdisplay);
@@ -27,21 +29,21 @@
                      const CefRect& rect,
                      const CefBrowserSettings& settings,
                      CefRefPtr<CefDictionaryValue> extra_info,
-                     CefRefPtr<CefRequestContext> request_context) OVERRIDE;
+                     CefRefPtr<CefRequestContext> request_context) override;
   void GetPopupConfig(CefWindowHandle temp_handle,
                       CefWindowInfo& windowInfo,
                       CefRefPtr<CefClient>& client,
-                      CefBrowserSettings& settings) OVERRIDE;
+                      CefBrowserSettings& settings) override;
   void ShowPopup(ClientWindowHandle parent_handle,
                  int x,
                  int y,
                  size_t width,
-                 size_t height) OVERRIDE;
-  void Show() OVERRIDE;
-  void Hide() OVERRIDE;
-  void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
-  void SetFocus(bool focus) OVERRIDE;
-  ClientWindowHandle GetWindowHandle() const OVERRIDE;
+                 size_t height) override;
+  void Show() override;
+  void Hide() override;
+  void SetBounds(int x, int y, size_t width, size_t height) override;
+  void SetFocus(bool focus) override;
+  ClientWindowHandle GetWindowHandle() const override;
 
  private:
   XDisplay* xdisplay_;
diff --git a/src/tests/cefclient/browser/browser_window_std_mac.h b/src/tests/cefclient/browser/browser_window_std_mac.h
index 853b616..8a91d8d 100644
--- a/src/tests/cefclient/browser/browser_window_std_mac.h
+++ b/src/tests/cefclient/browser/browser_window_std_mac.h
@@ -17,28 +17,30 @@
  public:
   // Constructor may be called on any thread.
   // |delegate| must outlive this object.
-  BrowserWindowStdMac(Delegate* delegate, const std::string& startup_url);
+  BrowserWindowStdMac(Delegate* delegate,
+                      bool with_controls,
+                      const std::string& startup_url);
 
   // BrowserWindow methods.
   void CreateBrowser(ClientWindowHandle parent_handle,
                      const CefRect& rect,
                      const CefBrowserSettings& settings,
                      CefRefPtr<CefDictionaryValue> extra_info,
-                     CefRefPtr<CefRequestContext> request_context) OVERRIDE;
+                     CefRefPtr<CefRequestContext> request_context) override;
   void GetPopupConfig(CefWindowHandle temp_handle,
                       CefWindowInfo& windowInfo,
                       CefRefPtr<CefClient>& client,
-                      CefBrowserSettings& settings) OVERRIDE;
+                      CefBrowserSettings& settings) override;
   void ShowPopup(ClientWindowHandle parent_handle,
                  int x,
                  int y,
                  size_t width,
-                 size_t height) OVERRIDE;
-  void Show() OVERRIDE;
-  void Hide() OVERRIDE;
-  void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
-  void SetFocus(bool focus) OVERRIDE;
-  ClientWindowHandle GetWindowHandle() const OVERRIDE;
+                 size_t height) override;
+  void Show() override;
+  void Hide() override;
+  void SetBounds(int x, int y, size_t width, size_t height) override;
+  void SetFocus(bool focus) override;
+  ClientWindowHandle GetWindowHandle() const override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(BrowserWindowStdMac);
diff --git a/src/tests/cefclient/browser/browser_window_std_mac.mm b/src/tests/cefclient/browser/browser_window_std_mac.mm
index c02bb32..17ebc8f 100644
--- a/src/tests/cefclient/browser/browser_window_std_mac.mm
+++ b/src/tests/cefclient/browser/browser_window_std_mac.mm
@@ -13,9 +13,10 @@
 namespace client {
 
 BrowserWindowStdMac::BrowserWindowStdMac(Delegate* delegate,
+                                         bool with_controls,
                                          const std::string& startup_url)
     : BrowserWindow(delegate) {
-  client_handler_ = new ClientHandlerStd(this, startup_url);
+  client_handler_ = new ClientHandlerStd(this, with_controls, startup_url);
 }
 
 void BrowserWindowStdMac::CreateBrowser(
@@ -27,8 +28,7 @@
   REQUIRE_MAIN_THREAD();
 
   CefWindowInfo window_info;
-  window_info.SetAsChild(parent_handle, rect.x, rect.y, rect.width,
-                         rect.height);
+  window_info.SetAsChild(parent_handle, rect);
 
   CefBrowserHost::CreateBrowser(window_info, client_handler_,
                                 client_handler_->startup_url(), settings,
@@ -42,7 +42,7 @@
   CEF_REQUIRE_UI_THREAD();
 
   // The window will be properly sized after the browser is created.
-  windowInfo.SetAsChild(temp_handle, 0, 0, 0, 0);
+  windowInfo.SetAsChild(temp_handle, CefRect());
   client = client_handler_;
 }
 
@@ -86,9 +86,10 @@
 ClientWindowHandle BrowserWindowStdMac::GetWindowHandle() const {
   REQUIRE_MAIN_THREAD();
 
-  if (browser_)
+  if (browser_) {
     return browser_->GetHost()->GetWindowHandle();
-  return NULL;
+  }
+  return nullptr;
 }
 
 }  // namespace client
diff --git a/src/tests/cefclient/browser/browser_window_std_win.cc b/src/tests/cefclient/browser/browser_window_std_win.cc
index f1e53d6..d363377 100644
--- a/src/tests/cefclient/browser/browser_window_std_win.cc
+++ b/src/tests/cefclient/browser/browser_window_std_win.cc
@@ -10,9 +10,10 @@
 namespace client {
 
 BrowserWindowStdWin::BrowserWindowStdWin(Delegate* delegate,
+                                         bool with_controls,
                                          const std::string& startup_url)
     : BrowserWindow(delegate) {
-  client_handler_ = new ClientHandlerStd(this, startup_url);
+  client_handler_ = new ClientHandlerStd(this, with_controls, startup_url);
 }
 
 void BrowserWindowStdWin::CreateBrowser(
@@ -24,8 +25,7 @@
   REQUIRE_MAIN_THREAD();
 
   CefWindowInfo window_info;
-  RECT wnd_rect = {rect.x, rect.y, rect.x + rect.width, rect.y + rect.height};
-  window_info.SetAsChild(parent_handle, wnd_rect);
+  window_info.SetAsChild(parent_handle, rect);
 
   if (GetWindowLongPtr(parent_handle, GWL_EXSTYLE) & WS_EX_NOACTIVATE) {
     // Don't activate the browser window on creation.
@@ -44,7 +44,7 @@
   CEF_REQUIRE_UI_THREAD();
 
   // The window will be properly sized after the browser is created.
-  windowInfo.SetAsChild(temp_handle, RECT());
+  windowInfo.SetAsChild(temp_handle, CefRect());
 
   // Don't activate the hidden browser window on creation.
   windowInfo.ex_style |= WS_EX_NOACTIVATE;
@@ -62,7 +62,7 @@
   HWND hwnd = GetWindowHandle();
   if (hwnd) {
     SetParent(hwnd, parent_handle);
-    SetWindowPos(hwnd, NULL, x, y, static_cast<int>(width),
+    SetWindowPos(hwnd, nullptr, x, y, static_cast<int>(width),
                  static_cast<int>(height), SWP_NOZORDER | SWP_NOACTIVATE);
 
     const bool no_activate =
@@ -75,8 +75,9 @@
   REQUIRE_MAIN_THREAD();
 
   HWND hwnd = GetWindowHandle();
-  if (hwnd && !::IsWindowVisible(hwnd))
+  if (hwnd && !::IsWindowVisible(hwnd)) {
     ShowWindow(hwnd, SW_SHOW);
+  }
 }
 
 void BrowserWindowStdWin::Hide() {
@@ -86,7 +87,7 @@
   if (hwnd) {
     // When the frame window is minimized set the browser window size to 0x0 to
     // reduce resource usage.
-    SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
+    SetWindowPos(hwnd, nullptr, 0, 0, 0, 0,
                  SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
   }
 }
@@ -97,7 +98,7 @@
   HWND hwnd = GetWindowHandle();
   if (hwnd) {
     // Set the browser window bounds.
-    SetWindowPos(hwnd, NULL, x, y, static_cast<int>(width),
+    SetWindowPos(hwnd, nullptr, x, y, static_cast<int>(width),
                  static_cast<int>(height), SWP_NOZORDER);
   }
 }
@@ -105,16 +106,18 @@
 void BrowserWindowStdWin::SetFocus(bool focus) {
   REQUIRE_MAIN_THREAD();
 
-  if (browser_)
+  if (browser_) {
     browser_->GetHost()->SetFocus(focus);
+  }
 }
 
 ClientWindowHandle BrowserWindowStdWin::GetWindowHandle() const {
   REQUIRE_MAIN_THREAD();
 
-  if (browser_)
+  if (browser_) {
     return browser_->GetHost()->GetWindowHandle();
-  return NULL;
+  }
+  return nullptr;
 }
 
 }  // namespace client
diff --git a/src/tests/cefclient/browser/browser_window_std_win.h b/src/tests/cefclient/browser/browser_window_std_win.h
index 8c8bef2..5a7ee2a 100644
--- a/src/tests/cefclient/browser/browser_window_std_win.h
+++ b/src/tests/cefclient/browser/browser_window_std_win.h
@@ -17,28 +17,30 @@
  public:
   // Constructor may be called on any thread.
   // |delegate| must outlive this object.
-  BrowserWindowStdWin(Delegate* delegate, const std::string& startup_url);
+  BrowserWindowStdWin(Delegate* delegate,
+                      bool with_controls,
+                      const std::string& startup_url);
 
   // BrowserWindow methods.
   void CreateBrowser(ClientWindowHandle parent_handle,
                      const CefRect& rect,
                      const CefBrowserSettings& settings,
                      CefRefPtr<CefDictionaryValue> extra_info,
-                     CefRefPtr<CefRequestContext> request_context) OVERRIDE;
+                     CefRefPtr<CefRequestContext> request_context) override;
   void GetPopupConfig(CefWindowHandle temp_handle,
                       CefWindowInfo& windowInfo,
                       CefRefPtr<CefClient>& client,
-                      CefBrowserSettings& settings) OVERRIDE;
+                      CefBrowserSettings& settings) override;
   void ShowPopup(ClientWindowHandle parent_handle,
                  int x,
                  int y,
                  size_t width,
-                 size_t height) OVERRIDE;
-  void Show() OVERRIDE;
-  void Hide() OVERRIDE;
-  void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
-  void SetFocus(bool focus) OVERRIDE;
-  ClientWindowHandle GetWindowHandle() const OVERRIDE;
+                 size_t height) override;
+  void Show() override;
+  void Hide() override;
+  void SetBounds(int x, int y, size_t width, size_t height) override;
+  void SetFocus(bool focus) override;
+  ClientWindowHandle GetWindowHandle() const override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(BrowserWindowStdWin);
diff --git a/src/tests/cefclient/browser/bytes_write_handler.cc b/src/tests/cefclient/browser/bytes_write_handler.cc
index 25f17fa..d53b61a 100644
--- a/src/tests/cefclient/browser/bytes_write_handler.cc
+++ b/src/tests/cefclient/browser/bytes_write_handler.cc
@@ -19,14 +19,15 @@
 }
 
 BytesWriteHandler::~BytesWriteHandler() {
-  if (data_)
+  if (data_) {
     free(data_);
+  }
 }
 
 size_t BytesWriteHandler::Write(const void* ptr, size_t size, size_t n) {
   base::AutoLock lock_scope(lock_);
   size_t rv;
-  if (offset_ + static_cast<int64>(size * n) >= datasize_ &&
+  if (offset_ + static_cast<int64_t>(size * n) >= datasize_ &&
       Grow(size * n) == 0) {
     rv = 0;
   } else {
@@ -38,27 +39,30 @@
   return rv;
 }
 
-int BytesWriteHandler::Seek(int64 offset, int whence) {
+int BytesWriteHandler::Seek(int64_t offset, int whence) {
   int rv = -1L;
   base::AutoLock lock_scope(lock_);
   switch (whence) {
     case SEEK_CUR:
-      if (offset_ + offset > datasize_ || offset_ + offset < 0)
+      if (offset_ + offset > datasize_ || offset_ + offset < 0) {
         break;
+      }
       offset_ += offset;
       rv = 0;
       break;
     case SEEK_END: {
-      int64 offset_abs = std::abs(offset);
-      if (offset_abs > datasize_)
+      int64_t offset_abs = std::abs(offset);
+      if (offset_abs > datasize_) {
         break;
+      }
       offset_ = datasize_ - offset_abs;
       rv = 0;
       break;
     }
     case SEEK_SET:
-      if (offset > datasize_ || offset < 0)
+      if (offset > datasize_ || offset < 0) {
         break;
+      }
       offset_ = offset;
       rv = 0;
       break;
@@ -67,7 +71,7 @@
   return rv;
 }
 
-int64 BytesWriteHandler::Tell() {
+int64_t BytesWriteHandler::Tell() {
   base::AutoLock lock_scope(lock_);
   return offset_;
 }
diff --git a/src/tests/cefclient/browser/bytes_write_handler.h b/src/tests/cefclient/browser/bytes_write_handler.h
index 26f9c7b..b71d8fb 100644
--- a/src/tests/cefclient/browser/bytes_write_handler.h
+++ b/src/tests/cefclient/browser/bytes_write_handler.h
@@ -16,22 +16,22 @@
   explicit BytesWriteHandler(size_t grow);
   ~BytesWriteHandler();
 
-  size_t Write(const void* ptr, size_t size, size_t n) OVERRIDE;
-  int Seek(int64 offset, int whence) OVERRIDE;
-  int64 Tell() OVERRIDE;
-  int Flush() OVERRIDE;
-  bool MayBlock() OVERRIDE { return false; }
+  size_t Write(const void* ptr, size_t size, size_t n) override;
+  int Seek(int64_t offset, int whence) override;
+  int64_t Tell() override;
+  int Flush() override;
+  bool MayBlock() override { return false; }
 
   void* GetData() { return data_; }
-  int64 GetDataSize() { return offset_; }
+  int64_t GetDataSize() { return offset_; }
 
  private:
   size_t Grow(size_t size);
 
   size_t grow_;
   void* data_;
-  int64 datasize_;
-  int64 offset_;
+  int64_t datasize_;
+  int64_t offset_;
 
   base::Lock lock_;
 
diff --git a/src/tests/cefclient/browser/client_app_delegates_browser.cc b/src/tests/cefclient/browser/client_app_delegates_browser.cc
index 4594818..2d6fc64 100644
--- a/src/tests/cefclient/browser/client_app_delegates_browser.cc
+++ b/src/tests/cefclient/browser/client_app_delegates_browser.cc
@@ -6,24 +6,15 @@
 
 #include "tests/cefclient/browser/client_browser.h"
 
-#if defined(OS_LINUX)
-#include "tests/cefclient/browser/print_handler_gtk.h"
-#endif
-
 namespace client {
 
 // static
+void ClientAppBrowser::RegisterCookieableSchemes(
+    std::vector<std::string>& cookieable_schemes) {}
+
+// static
 void ClientAppBrowser::CreateDelegates(DelegateSet& delegates) {
   browser::CreateDelegates(delegates);
 }
 
-// static
-CefRefPtr<CefPrintHandler> ClientAppBrowser::CreatePrintHandler() {
-#if defined(OS_LINUX)
-  return new ClientPrintHandlerGtk();
-#else
-  return nullptr;
-#endif
-}
-
 }  // namespace client
diff --git a/src/tests/cefclient/browser/client_browser.cc b/src/tests/cefclient/browser/client_browser.cc
index cffb1dc..fd1561c 100644
--- a/src/tests/cefclient/browser/client_browser.cc
+++ b/src/tests/cefclient/browser/client_browser.cc
@@ -5,9 +5,12 @@
 #include "tests/cefclient/browser/client_browser.h"
 #include "tests/cefclient/browser/main_context.h"
 
+#include "include/base/cef_logging.h"
 #include "include/cef_command_line.h"
 #include "include/cef_crash_util.h"
 #include "include/cef_file_util.h"
+#include "tests/cefclient/browser/client_prefs.h"
+#include "tests/cefclient/browser/default_client_handler.h"
 #include "tests/shared/common/client_switches.h"
 
 namespace client {
@@ -19,7 +22,17 @@
  public:
   ClientBrowserDelegate() {}
 
-  void OnContextInitialized(CefRefPtr<ClientAppBrowser> app) OVERRIDE {
+  void OnRegisterCustomPreferences(
+      CefRefPtr<client::ClientAppBrowser> app,
+      cef_preferences_type_t type,
+      CefRawPtr<CefPreferenceRegistrar> registrar) override {
+    if (type == CEF_PREFERENCES_TYPE_GLOBAL) {
+      // Register global preferences with default values.
+      prefs::RegisterGlobalPreferences(registrar);
+    }
+  }
+
+  void OnContextInitialized(CefRefPtr<ClientAppBrowser> app) override {
     if (CefCrashReportingEnabled()) {
       // Set some crash keys for testing purposes. Keys must be defined in the
       // "crash_reporter.cfg" file. See cef_crash_util.h for details.
@@ -42,10 +55,19 @@
 
   void OnBeforeCommandLineProcessing(
       CefRefPtr<ClientAppBrowser> app,
-      CefRefPtr<CefCommandLine> command_line) OVERRIDE {
+      CefRefPtr<CefCommandLine> command_line) override {
     // Append Chromium command line parameters if touch events are enabled
-    if (client::MainContext::Get()->TouchEventsEnabled())
+    if (client::MainContext::Get()->TouchEventsEnabled()) {
       command_line->AppendSwitchWithValue("touch-events", "enabled");
+    }
+  }
+
+  CefRefPtr<CefClient> GetDefaultClient(
+      CefRefPtr<ClientAppBrowser> app) override {
+    // Default client handler for unmanaged browser windows. Used with the
+    // Chrome runtime only.
+    LOG(INFO) << "Creating a chrome browser with the default client";
+    return new DefaultClientHandler();
   }
 
  private:
diff --git a/src/tests/cefclient/browser/client_handler.cc b/src/tests/cefclient/browser/client_handler.cc
index dc2bb5f..dc24336 100644
--- a/src/tests/cefclient/browser/client_handler.cc
+++ b/src/tests/cefclient/browser/client_handler.cc
@@ -10,10 +10,12 @@
 #include <sstream>
 #include <string>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_browser.h"
+#include "include/cef_command_ids.h"
 #include "include/cef_frame.h"
 #include "include/cef_parser.h"
+#include "include/cef_shared_process_message_builder.h"
 #include "include/cef_ssl_status.h"
 #include "include/cef_x509_certificate.h"
 #include "include/wrapper/cef_closure_task.h"
@@ -22,7 +24,9 @@
 #include "tests/cefclient/browser/test_runner.h"
 #include "tests/shared/browser/extension_util.h"
 #include "tests/shared/browser/resource_util.h"
+#include "tests/shared/common/binary_value_utils.h"
 #include "tests/shared/common/client_switches.h"
+#include "tests/shared/common/string_util.h"
 
 namespace client {
 
@@ -40,6 +44,8 @@
   CLIENT_ID_CLOSE_DEVTOOLS,
   CLIENT_ID_INSPECT_ELEMENT,
   CLIENT_ID_SHOW_SSL_INFO,
+  CLIENT_ID_CURSOR_CHANGE_DISABLED,
+  CLIENT_ID_MEDIA_HANDLING_DISABLED,
   CLIENT_ID_OFFLINE,
   CLIENT_ID_TESTMENU_SUBMENU,
   CLIENT_ID_TESTMENU_CHECKITEM,
@@ -48,21 +54,23 @@
   CLIENT_ID_TESTMENU_RADIOITEM3,
 };
 
-// Musr match the value in client_renderer.cc.
+// Must match the value in client_renderer.cc.
 const char kFocusedNodeChangedMessage[] = "ClientRenderer.FocusedNodeChanged";
 
 std::string GetTimeString(const CefTime& value) {
-  if (value.GetTimeT() == 0)
+  if (value.GetTimeT() == 0) {
     return "Unspecified";
+  }
 
   static const char* kMonths[] = {
       "January", "February", "March",     "April",   "May",      "June",
       "July",    "August",   "September", "October", "November", "December"};
   std::string month;
-  if (value.month >= 1 && value.month <= 12)
+  if (value.month >= 1 && value.month <= 12) {
     month = kMonths[value.month - 1];
-  else
+  } else {
     month = "Invalid";
+  }
 
   std::stringstream ss;
   ss << month << " " << value.day_of_month << ", " << value.year << " "
@@ -72,9 +80,19 @@
   return ss.str();
 }
 
+std::string GetTimeString(const CefBaseTime& value) {
+  CefTime time;
+  if (cef_time_from_basetime(value, &time)) {
+    return GetTimeString(time);
+  } else {
+    return "Invalid";
+  }
+}
+
 std::string GetBinaryString(CefRefPtr<CefBinaryValue> value) {
-  if (!value.get())
+  if (!value.get()) {
     return "&nbsp;";
+  }
 
   // Retrieve the value.
   const size_t size = value->GetSize();
@@ -117,8 +135,9 @@
   FLAG(CERT_STATUS_SHA1_SIGNATURE_PRESENT);
   FLAG(CERT_STATUS_CT_COMPLIANCE_FAILED);
 
-  if (result.empty())
+  if (result.empty()) {
     return "&nbsp;";
+  }
   return result;
 }
 
@@ -141,8 +160,9 @@
   FLAG(SSL_CONTENT_DISPLAYED_INSECURE_CONTENT);
   FLAG(SSL_CONTENT_RAN_INSECURE_CONTENT);
 
-  if (result.empty())
+  if (result.empty()) {
     return "&nbsp;";
+  }
   return result;
 }
 
@@ -160,8 +180,9 @@
      << "</a><br/>Error: " << test_runner::GetErrorString(error_code) << " ("
      << error_code << ")";
 
-  if (!other_info.empty())
+  if (!other_info.empty()) {
     ss << "<br/>" << other_info;
+  }
 
   ss << "</body></html>";
   frame->LoadURL(test_runner::GetDataURI(ss.str(), "text/html"));
@@ -220,6 +241,195 @@
   return ss.str();
 }
 
+void OnTestProcessMessageReceived(
+    const CefRefPtr<CefFrame>& frame,
+    const CefRefPtr<CefProcessMessage>& process_message,
+    const bv_utils::TimePoint& finish_time) {
+  DCHECK(process_message->IsValid());
+
+  CefRefPtr<CefListValue> input_args = process_message->GetArgumentList();
+  DCHECK_EQ(input_args->GetSize(), 1U);
+
+  const auto renderer_msg =
+      bv_utils::GetRendererMsgFromBinary(input_args->GetBinary(0));
+
+  CefRefPtr<CefProcessMessage> response =
+      CefProcessMessage::Create(bv_utils::kTestSendProcessMessage);
+  CefRefPtr<CefListValue> args = response->GetArgumentList();
+
+  const auto message_size = std::max(input_args->GetBinary(0)->GetSize(),
+                                     sizeof(bv_utils::BrowserMessage));
+  std::vector<uint8_t> data(message_size);
+
+  const auto browser_msg =
+      reinterpret_cast<bv_utils::BrowserMessage*>(data.data());
+  browser_msg->test_id = renderer_msg.test_id;
+  browser_msg->duration = finish_time - renderer_msg.start_time;
+  browser_msg->start_time = bv_utils::Now();
+
+  args->SetBinary(0, bv_utils::CreateCefBinaryValue(data));
+  frame->SendProcessMessage(PID_RENDERER, response);
+}
+
+void OnTestSMRProcessMessageReceived(
+    const CefRefPtr<CefFrame>& frame,
+    const CefRefPtr<CefProcessMessage>& process_message,
+    const bv_utils::TimePoint& finish_time) {
+  DCHECK(process_message->IsValid());
+
+  CefRefPtr<CefSharedMemoryRegion> region =
+      process_message->GetSharedMemoryRegion();
+  DCHECK_GE(region->Size(), sizeof(bv_utils::RendererMessage));
+
+  const auto renderer_msg =
+      static_cast<const bv_utils::RendererMessage*>(region->Memory());
+  const auto message_size =
+      std::max(region->Size(), sizeof(bv_utils::BrowserMessage));
+
+  std::vector<uint8_t> data(message_size);
+  const auto browser_msg =
+      reinterpret_cast<bv_utils::BrowserMessage*>(data.data());
+  browser_msg->test_id = renderer_msg->test_id;
+  browser_msg->duration = finish_time - renderer_msg->start_time;
+  browser_msg->start_time = bv_utils::Now();
+
+  auto builder = CefSharedProcessMessageBuilder::Create(
+      bv_utils::kTestSendSMRProcessMessage, message_size);
+
+  bv_utils::CopyDataIntoMemory(data, builder->Memory());
+
+  frame->SendProcessMessage(PID_RENDERER, builder->Build());
+}
+
+bool IsAllowedPageActionIcon(cef_chrome_page_action_icon_type_t icon_type) {
+  // Only the specified icons will be allowed.
+  switch (icon_type) {
+    case CEF_CPAIT_FIND:
+    case CEF_CPAIT_ZOOM:
+      return true;
+    default:
+      break;
+  }
+  return false;
+}
+
+bool IsAllowedToolbarButton(cef_chrome_toolbar_button_type_t button_type) {
+  // All configurable buttons will be disabled.
+  return false;
+}
+
+bool IsAllowedAppMenuCommandId(int command_id) {
+  // Only the commands in this array will be allowed.
+  static const int kAllowedCommandIds[] = {
+      IDC_NEW_WINDOW,
+      IDC_NEW_INCOGNITO_WINDOW,
+
+      // Zoom buttons.
+      IDC_ZOOM_MENU,
+      IDC_ZOOM_PLUS,
+      IDC_ZOOM_NORMAL,
+      IDC_ZOOM_MINUS,
+      IDC_FULLSCREEN,
+
+      IDC_PRINT,
+      IDC_FIND,
+      IDC_FIND_NEXT,
+      IDC_FIND_PREVIOUS,
+
+      // "More tools" sub-menu and contents.
+      IDC_MORE_TOOLS_MENU,
+      IDC_CLEAR_BROWSING_DATA,
+      IDC_MANAGE_EXTENSIONS,
+      IDC_PERFORMANCE,
+      IDC_TASK_MANAGER,
+      IDC_DEV_TOOLS,
+
+      // Edit buttons.
+      IDC_EDIT_MENU,
+      IDC_CUT,
+      IDC_COPY,
+      IDC_PASTE,
+
+      IDC_OPTIONS,
+      IDC_EXIT,
+  };
+  for (size_t i = 0; i < std::size(kAllowedCommandIds); ++i) {
+    if (command_id == kAllowedCommandIds[i]) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool IsAllowedContextMenuCommandId(int command_id) {
+  // Allow commands added by web content.
+  if (command_id >= IDC_CONTENT_CONTEXT_CUSTOM_FIRST &&
+      command_id <= IDC_CONTENT_CONTEXT_CUSTOM_LAST) {
+    return true;
+  }
+
+  // Allow commands added by extensions.
+  if (command_id >= IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST &&
+      command_id <= IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST) {
+    return true;
+  }
+
+  // Only the commands in this array will be allowed.
+  static const int kAllowedCommandIds[] = {
+      // Page navigation.
+      IDC_BACK,
+      IDC_FORWARD,
+      IDC_RELOAD,
+      IDC_RELOAD_BYPASSING_CACHE,
+      IDC_RELOAD_CLEARING_CACHE,
+      IDC_STOP,
+
+      // Printing.
+      IDC_PRINT,
+
+      // Edit controls.
+      IDC_CONTENT_CONTEXT_CUT,
+      IDC_CONTENT_CONTEXT_COPY,
+      IDC_CONTENT_CONTEXT_PASTE,
+      IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE,
+      IDC_CONTENT_CONTEXT_DELETE,
+      IDC_CONTENT_CONTEXT_SELECTALL,
+      IDC_CONTENT_CONTEXT_UNDO,
+      IDC_CONTENT_CONTEXT_REDO,
+  };
+  for (size_t i = 0; i < std::size(kAllowedCommandIds); ++i) {
+    if (command_id == kAllowedCommandIds[i]) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void FilterContextMenuModel(CefRefPtr<CefMenuModel> model) {
+  // Evaluate from the bottom to the top because we'll be removing menu items.
+  for (size_t x = model->GetCount(); x > 0; --x) {
+    const auto i = x - 1;
+    const auto type = model->GetTypeAt(i);
+    if (type == MENUITEMTYPE_SUBMENU) {
+      // Filter sub-menu and remove if empty.
+      auto sub_model = model->GetSubMenuAt(i);
+      FilterContextMenuModel(sub_model);
+      if (sub_model->GetCount() == 0) {
+        model->RemoveAt(i);
+      }
+    } else if (type == MENUITEMTYPE_SEPARATOR) {
+      // A separator shouldn't be the first or last element in the menu, and
+      // there shouldn't be multiple in a row.
+      if (i == 0 || i == model->GetCount() - 1 ||
+          model->GetTypeAt(i + 1) == MENUITEMTYPE_SEPARATOR) {
+        model->RemoveAt(i);
+      }
+    } else if (!IsAllowedContextMenuCommandId(model->GetCommandIdAt(i))) {
+      model->RemoveAt(i);
+    }
+  }
+}
+
 }  // namespace
 
 class ClientDownloadImageCallback : public CefDownloadImageCallback {
@@ -229,9 +439,10 @@
 
   void OnDownloadImageFinished(const CefString& image_url,
                                int http_status_code,
-                               CefRefPtr<CefImage> image) OVERRIDE {
-    if (image)
+                               CefRefPtr<CefImage> image) override {
+    if (image) {
       client_handler_->NotifyFavicon(image);
+    }
   }
 
  private:
@@ -243,23 +454,15 @@
 
 ClientHandler::ClientHandler(Delegate* delegate,
                              bool is_osr,
+                             bool with_controls,
                              const std::string& startup_url)
     : is_osr_(is_osr),
+      with_controls_(with_controls),
       startup_url_(startup_url),
-      download_favicon_images_(false),
       delegate_(delegate),
-      browser_count_(0),
-      console_log_file_(MainContext::Get()->GetConsoleLogPath()),
-      first_console_message_(true),
-      focus_on_editable_field_(false),
-      initial_navigation_(true) {
+      console_log_file_(MainContext::Get()->GetConsoleLogPath()) {
   DCHECK(!console_log_file_.empty());
 
-#if defined(OS_LINUX)
-  // Provide the GTK-based dialog implementation on Linux.
-  dialog_handler_ = new ClientDialogHandlerGtk();
-#endif
-
   resource_manager_ = new CefResourceManager();
   test_runner::SetupResourceManager(resource_manager_, &string_resource_map_);
 
@@ -269,12 +472,56 @@
   mouse_cursor_change_disabled_ =
       command_line->HasSwitch(switches::kMouseCursorChangeDisabled);
   offline_ = command_line->HasSwitch(switches::kOffline);
+  filter_chrome_commands_ =
+      command_line->HasSwitch(switches::kFilterChromeCommands);
+
+#if defined(OS_LINUX)
+  // Optionally use the client-provided GTK dialogs.
+  const bool use_client_dialogs =
+      command_line->HasSwitch(switches::kUseClientDialogs);
+
+  // Determine if the client-provided GTK dialogs can/should be used.
+  bool require_client_dialogs = false;
+  bool support_client_dialogs = true;
+
+  if (command_line->HasSwitch(switches::kMultiThreadedMessageLoop)) {
+    // Default/internal GTK dialogs are not supported in combination with
+    // multi-threaded-message-loop because Chromium doesn't support GDK threads.
+    // This does not apply to the JS dialogs which use Views instead of GTK.
+    if (!use_client_dialogs) {
+      LOG(WARNING) << "Client dialogs must be used in combination with "
+                      "multi-threaded-message-loop.";
+    }
+    require_client_dialogs = true;
+  }
+
+  if (MainContext::Get()->UseViews()) {
+    // Client-provided GTK dialogs cannot be used in combination with Views
+    // because the implementation of ClientDialogHandlerGtk requires a top-level
+    // GtkWindow.
+    if (use_client_dialogs) {
+      LOG(ERROR) << "Client dialogs cannot be used in combination with Views.";
+    }
+    support_client_dialogs = false;
+  }
+
+  if (support_client_dialogs) {
+    if (use_client_dialogs) {
+      js_dialog_handler_ = new ClientDialogHandlerGtk();
+    }
+    if (use_client_dialogs || require_client_dialogs) {
+      file_dialog_handler_ = js_dialog_handler_ ? js_dialog_handler_
+                                                : new ClientDialogHandlerGtk();
+      print_handler_ = new ClientPrintHandlerGtk();
+    }
+  }
+#endif  // defined(OS_LINUX)
 }
 
 void ClientHandler::DetachDelegate() {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
-    MAIN_POST_CLOSURE(base::Bind(&ClientHandler::DetachDelegate, this));
+    MAIN_POST_CLOSURE(base::BindOnce(&ClientHandler::DetachDelegate, this));
     return;
   }
 
@@ -289,13 +536,15 @@
     CefRefPtr<CefProcessMessage> message) {
   CEF_REQUIRE_UI_THREAD();
 
+  const auto finish_time = bv_utils::Now();
+
   if (message_router_->OnProcessMessageReceived(browser, frame, source_process,
                                                 message)) {
     return true;
   }
 
   // Check for messages from the client renderer.
-  std::string message_name = message->GetName();
+  const std::string& message_name = message->GetName();
   if (message_name == kFocusedNodeChangedMessage) {
     // A message is sent from ClientRenderDelegate to tell us whether the
     // currently focused DOM node is editable. Use of |focus_on_editable_field_|
@@ -305,42 +554,141 @@
     return true;
   }
 
+  if (message_name == bv_utils::kTestSendProcessMessage) {
+    OnTestProcessMessageReceived(frame, message, finish_time);
+    return true;
+  }
+
+  if (message_name == bv_utils::kTestSendSMRProcessMessage) {
+    OnTestSMRProcessMessageReceived(frame, message, finish_time);
+    return true;
+  }
+
   return false;
 }
 
+bool ClientHandler::OnChromeCommand(CefRefPtr<CefBrowser> browser,
+                                    int command_id,
+                                    cef_window_open_disposition_t disposition) {
+  CEF_REQUIRE_UI_THREAD();
+  DCHECK(MainContext::Get()->UseChromeRuntime());
+
+  const bool allowed = IsAllowedAppMenuCommandId(command_id) ||
+                       IsAllowedContextMenuCommandId(command_id);
+
+  bool block = false;
+  if (filter_chrome_commands_) {
+    // Block all commands that aren't specifically allowed.
+    block = !allowed;
+  } else if (!with_controls_) {
+    // If controls are hidden, block all commands that don't target the current
+    // tab or aren't specifically allowed.
+    block = disposition != CEF_WOD_CURRENT_TAB || !allowed;
+  }
+
+  if (block) {
+    LOG(INFO) << "Blocking command " << command_id << " with disposition "
+              << disposition;
+    return true;
+  }
+
+  // Default handling.
+  return false;
+}
+
+bool ClientHandler::IsChromeAppMenuItemVisible(CefRefPtr<CefBrowser> browser,
+                                               int command_id) {
+  CEF_REQUIRE_UI_THREAD();
+  DCHECK(MainContext::Get()->UseChromeRuntime());
+  if (!filter_chrome_commands_) {
+    return true;
+  }
+  return IsAllowedAppMenuCommandId(command_id);
+}
+
+bool ClientHandler::IsChromePageActionIconVisible(
+    cef_chrome_page_action_icon_type_t icon_type) {
+  CEF_REQUIRE_UI_THREAD();
+  DCHECK(MainContext::Get()->UseChromeRuntime());
+  if (!filter_chrome_commands_) {
+    return true;
+  }
+  return IsAllowedPageActionIcon(icon_type);
+}
+
+bool ClientHandler::IsChromeToolbarButtonVisible(
+    cef_chrome_toolbar_button_type_t button_type) {
+  CEF_REQUIRE_UI_THREAD();
+  DCHECK(MainContext::Get()->UseChromeRuntime());
+  if (!filter_chrome_commands_) {
+    return true;
+  }
+  return IsAllowedToolbarButton(button_type);
+}
+
 void ClientHandler::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
                                         CefRefPtr<CefFrame> frame,
                                         CefRefPtr<CefContextMenuParams> params,
                                         CefRefPtr<CefMenuModel> model) {
   CEF_REQUIRE_UI_THREAD();
 
+  const bool use_chrome_runtime = MainContext::Get()->UseChromeRuntime();
+  if (use_chrome_runtime && (!with_controls_ || filter_chrome_commands_)) {
+    // Remove all disallowed menu items.
+    FilterContextMenuModel(model);
+  }
+
   if ((params->GetTypeFlags() & (CM_TYPEFLAG_PAGE | CM_TYPEFLAG_FRAME)) != 0) {
     // Add a separator if the menu already has items.
-    if (model->GetCount() > 0)
+    if (model->GetCount() > 0) {
       model->AddSeparator();
+    }
 
     // Add DevTools items to all context menus.
     model->AddItem(CLIENT_ID_SHOW_DEVTOOLS, "&Show DevTools");
     model->AddItem(CLIENT_ID_CLOSE_DEVTOOLS, "Close DevTools");
-    model->AddSeparator();
-    model->AddItem(CLIENT_ID_INSPECT_ELEMENT, "Inspect Element");
+
+    if (!use_chrome_runtime) {
+      // Chrome runtime already gives us an "Inspect" menu item.
+      model->AddSeparator();
+      model->AddItem(CLIENT_ID_INSPECT_ELEMENT, "Inspect Element");
+    }
 
     if (HasSSLInformation(browser)) {
       model->AddSeparator();
       model->AddItem(CLIENT_ID_SHOW_SSL_INFO, "Show SSL information");
     }
 
+    if (!use_chrome_runtime) {
+      // TODO(chrome-runtime): Add support for this.
+      model->AddSeparator();
+      model->AddCheckItem(CLIENT_ID_CURSOR_CHANGE_DISABLED,
+                          "Cursor change disabled");
+      if (mouse_cursor_change_disabled_) {
+        model->SetChecked(CLIENT_ID_CURSOR_CHANGE_DISABLED, true);
+      }
+
+      model->AddSeparator();
+      model->AddCheckItem(CLIENT_ID_MEDIA_HANDLING_DISABLED,
+                          "Media handling disabled");
+      if (media_handling_disabled_) {
+        model->SetChecked(CLIENT_ID_MEDIA_HANDLING_DISABLED, true);
+      }
+    }
+
     model->AddSeparator();
-    model->AddItem(CLIENT_ID_OFFLINE, "Offline mode");
-    if (offline_)
+    model->AddCheckItem(CLIENT_ID_OFFLINE, "Offline mode");
+    if (offline_) {
       model->SetChecked(CLIENT_ID_OFFLINE, true);
+    }
 
     // Test context menu features.
     BuildTestMenu(model);
   }
 
-  if (delegate_)
+  if (delegate_) {
     delegate_->OnBeforeContextMenu(model);
+  }
 }
 
 bool ClientHandler::OnContextMenuCommand(CefRefPtr<CefBrowser> browser,
@@ -363,6 +711,12 @@
     case CLIENT_ID_SHOW_SSL_INFO:
       ShowSSLInformation(browser);
       return true;
+    case CLIENT_ID_CURSOR_CHANGE_DISABLED:
+      mouse_cursor_change_disabled_ = !mouse_cursor_change_disabled_;
+      return true;
+    case CLIENT_ID_MEDIA_HANDLING_DISABLED:
+      media_handling_disabled_ = !media_handling_disabled_;
+      return true;
     case CLIENT_ID_OFFLINE:
       offline_ = !offline_;
       SetOfflineState(browser, offline_);
@@ -378,8 +732,9 @@
   CEF_REQUIRE_UI_THREAD();
 
   // Only update the address for the main (top-level) frame.
-  if (frame->IsMain())
+  if (frame->IsMain()) {
     NotifyAddress(url);
+  }
 }
 
 void ClientHandler::OnTitleChange(CefRefPtr<CefBrowser> browser,
@@ -440,12 +795,6 @@
        << NEWLINE << "-----------------------" << NEWLINE;
     fputs(ss.str().c_str(), file);
     fclose(file);
-
-    if (first_console_message_) {
-      test_runner::Alert(
-          browser, "Console messages written to \"" + console_log_file_ + "\"");
-      first_console_message_ = false;
-    }
   }
 
   return false;
@@ -459,6 +808,31 @@
   return true;
 }
 
+bool ClientHandler::OnCursorChange(CefRefPtr<CefBrowser> browser,
+                                   CefCursorHandle cursor,
+                                   cef_cursor_type_t type,
+                                   const CefCursorInfo& custom_cursor_info) {
+  CEF_REQUIRE_UI_THREAD();
+
+  // Return true to disable default handling of cursor changes.
+  return mouse_cursor_change_disabled_;
+}
+
+bool ClientHandler::CanDownload(CefRefPtr<CefBrowser> browser,
+                                const CefString& url,
+                                const CefString& request_method) {
+  CEF_REQUIRE_UI_THREAD();
+
+  if (!with_controls_) {
+    // Block the download.
+    LOG(INFO) << "Blocking download";
+    return false;
+  }
+
+  // Allow the download.
+  return true;
+}
+
 void ClientHandler::OnBeforeDownload(
     CefRefPtr<CefBrowser> browser,
     CefRefPtr<CefDownloadItem> download_item,
@@ -534,6 +908,7 @@
                                   bool* is_keyboard_shortcut) {
   CEF_REQUIRE_UI_THREAD();
 
+  /*
   if (!event.focus_on_editable_field && event.windows_key_code == 0x20) {
     // Special handling for the space character when an input element does not
     // have focus. Handling the event in OnPreKeyEvent() keeps the event from
@@ -544,6 +919,7 @@
       test_runner::Alert(browser, "You pressed the space bar!");
     return true;
   }
+  */
 
   return false;
 }
@@ -563,9 +939,36 @@
     bool* no_javascript_access) {
   CEF_REQUIRE_UI_THREAD();
 
-  // Return true to cancel the popup window.
-  return !CreatePopupWindow(browser, false, popupFeatures, windowInfo, client,
-                            settings);
+  if (target_disposition == CEF_WOD_NEW_PICTURE_IN_PICTURE) {
+    // Use default handling for document picture-in-picture popups.
+    client = nullptr;
+    return false;
+  }
+
+  // Potentially create a new RootWindow for the popup browser that will be
+  // created asynchronously.
+  CreatePopupWindow(browser, /*is_devtools=*/false, popupFeatures, windowInfo,
+                    client, settings);
+
+  // Allow popup creation.
+  return false;
+}
+
+void ClientHandler::OnBeforeDevToolsPopup(
+    CefRefPtr<CefBrowser> browser,
+    CefWindowInfo& windowInfo,
+    CefRefPtr<CefClient>& client,
+    CefBrowserSettings& settings,
+    CefRefPtr<CefDictionaryValue>& extra_info,
+    bool* use_default_window) {
+  CEF_REQUIRE_UI_THREAD();
+
+  // Potentially create a new RootWindow for the DevTools popup browser that
+  // will be created immediately after this method returns.
+  if (!CreatePopupWindow(browser, /*is_devtools=*/true, CefPopupFeatures(),
+                         windowInfo, client, settings)) {
+    *use_default_window = true;
+  }
 }
 
 void ClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
@@ -581,17 +984,15 @@
     // Register handlers with the router.
     test_runner::CreateMessageHandlers(message_handler_set_);
     MessageHandlerSet::const_iterator it = message_handler_set_.begin();
-    for (; it != message_handler_set_.end(); ++it)
+    for (; it != message_handler_set_.end(); ++it) {
       message_router_->AddHandler(*(it), false);
+    }
   }
 
-  // Disable mouse cursor change if requested via the command-line flag.
-  if (mouse_cursor_change_disabled_)
-    browser->GetHost()->SetMouseCursorChangeDisabled(true);
-
   // Set offline mode if requested via the command-line flag.
-  if (offline_)
+  if (offline_) {
     SetOfflineState(browser, true);
+  }
 
   if (browser->GetHost()->GetExtension()) {
     // Browsers hosting extension apps should auto-resize.
@@ -657,21 +1058,34 @@
   CEF_REQUIRE_UI_THREAD();
 
   // Don't display an error for downloaded files.
-  if (errorCode == ERR_ABORTED)
+  if (errorCode == ERR_ABORTED) {
     return;
+  }
 
   // Don't display an error for external protocols that we allow the OS to
   // handle. See OnProtocolExecution().
   if (errorCode == ERR_UNKNOWN_URL_SCHEME) {
     std::string urlStr = frame->GetURL();
-    if (urlStr.find("spotify:") == 0)
+    if (urlStr.find("spotify:") == 0) {
       return;
+    }
   }
 
   // Load the error page.
   LoadErrorPage(frame, failedUrl, errorCode, errorText);
 }
 
+bool ClientHandler::OnRequestMediaAccessPermission(
+    CefRefPtr<CefBrowser> browser,
+    CefRefPtr<CefFrame> frame,
+    const CefString& requesting_origin,
+    uint32_t requested_permissions,
+    CefRefPtr<CefMediaAccessCallback> callback) {
+  callback->Continue(media_handling_disabled_ ? CEF_MEDIA_PERMISSION_NONE
+                                              : requested_permissions);
+  return true;
+}
+
 bool ClientHandler::OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
                                    CefRefPtr<CefFrame> frame,
                                    CefRefPtr<CefRequest> request,
@@ -689,15 +1103,16 @@
     const CefString& target_url,
     CefRequestHandler::WindowOpenDisposition target_disposition,
     bool user_gesture) {
-  if (target_disposition == WOD_NEW_BACKGROUND_TAB ||
-      target_disposition == WOD_NEW_FOREGROUND_TAB) {
+  if (target_disposition == CEF_WOD_NEW_BACKGROUND_TAB ||
+      target_disposition == CEF_WOD_NEW_FOREGROUND_TAB) {
     // Handle middle-click and ctrl + left-click by opening the URL in a new
     // browser window.
-    RootWindowConfig config;
-    config.with_controls = true;
-    config.with_osr = is_osr();
-    config.url = target_url;
-    MainContext::Get()->GetRootWindowManager()->CreateRootWindow(config);
+    auto config = std::make_unique<RootWindowConfig>();
+    config->with_controls = with_controls_;
+    config->with_osr = is_osr_;
+    config->url = target_url;
+    MainContext::Get()->GetRootWindowManager()->CreateRootWindow(
+        std::move(config));
     return true;
   }
 
@@ -743,30 +1158,18 @@
   return false;
 }
 
-bool ClientHandler::OnQuotaRequest(CefRefPtr<CefBrowser> browser,
-                                   const CefString& origin_url,
-                                   int64 new_size,
-                                   CefRefPtr<CefRequestCallback> callback) {
-  CEF_REQUIRE_IO_THREAD();
-
-  static const int64 max_size = 1024 * 1024 * 20;  // 20mb.
-
-  // Grant the quota request if the size is reasonable.
-  callback->Continue(new_size <= max_size);
-  return true;
-}
-
 bool ClientHandler::OnCertificateError(CefRefPtr<CefBrowser> browser,
                                        ErrorCode cert_error,
                                        const CefString& request_url,
                                        CefRefPtr<CefSSLInfo> ssl_info,
-                                       CefRefPtr<CefRequestCallback> callback) {
+                                       CefRefPtr<CefCallback> callback) {
   CEF_REQUIRE_UI_THREAD();
 
-  if (cert_error == ERR_CERT_AUTHORITY_INVALID &&
-      request_url.ToString().find("https://www.magpcss.org/") == 0U) {
-    // Allow the CEF Forum to load. It has a self-signed certificate.
-    callback->Continue(true);
+  if (cert_error == ERR_CERT_COMMON_NAME_INVALID &&
+      request_url.ToString().find("https://www.magpcss.com/") == 0U) {
+    // Allow magpcss.com to load despite having a certificate common name of
+    // magpcss.org.
+    callback->Continue();
     return true;
   }
 
@@ -823,27 +1226,27 @@
   message_router_->OnRenderProcessTerminated(browser);
 
   // Don't reload if there's no start URL, or if the crash URL was specified.
-  if (startup_url_.empty() || startup_url_ == "chrome://crash")
+  if (startup_url_.empty() || startup_url_ == "chrome://crash") {
     return;
+  }
 
   CefRefPtr<CefFrame> frame = browser->GetMainFrame();
   std::string url = frame->GetURL();
 
   // Don't reload if the termination occurred before any URL had successfully
   // loaded.
-  if (url.empty())
+  if (url.empty()) {
     return;
-
-  std::string start_url = startup_url_;
+  }
 
   // Convert URLs to lowercase for easier comparison.
-  std::transform(url.begin(), url.end(), url.begin(), tolower);
-  std::transform(start_url.begin(), start_url.end(), start_url.begin(),
-                 tolower);
+  url = AsciiStrToLower(url);
+  const std::string& start_url = AsciiStrToLower(startup_url_);
 
   // Don't reload the URL that just resulted in termination.
-  if (url.find(start_url) == 0)
+  if (url.find(start_url) == 0) {
     return;
+  }
 
   frame->LoadURL(startup_url_);
 }
@@ -854,15 +1257,16 @@
 
   // Restore offline mode after main frame navigation. Otherwise, offline state
   // (e.g. `navigator.onLine`) might be wrong in the renderer process.
-  if (offline_)
+  if (offline_) {
     SetOfflineState(browser, true);
+  }
 }
 
 cef_return_value_t ClientHandler::OnBeforeResourceLoad(
     CefRefPtr<CefBrowser> browser,
     CefRefPtr<CefFrame> frame,
     CefRefPtr<CefRequest> request,
-    CefRefPtr<CefRequestCallback> callback) {
+    CefRefPtr<CefCallback> callback) {
   CEF_REQUIRE_IO_THREAD();
 
   return resource_manager_->OnBeforeResourceLoad(browser, frame, request,
@@ -898,8 +1302,9 @@
   std::string urlStr = request->GetURL();
 
   // Allow OS execution of Spotify URIs.
-  if (urlStr.find("spotify:") == 0)
+  if (urlStr.find("spotify:") == 0) {
     allow_os_execution = true;
+  }
 }
 
 int ClientHandler::GetBrowserCount() const {
@@ -911,8 +1316,8 @@
                                  const CefPoint& inspect_element_at) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&ClientHandler::ShowDevTools, this, browser,
-                                   inspect_element_at));
+    CefPostTask(TID_UI, base::BindOnce(&ClientHandler::ShowDevTools, this,
+                                       browser, inspect_element_at));
     return;
   }
 
@@ -920,25 +1325,21 @@
   CefRefPtr<CefClient> client;
   CefBrowserSettings settings;
 
-  MainContext::Get()->PopulateBrowserSettings(&settings);
-
   CefRefPtr<CefBrowserHost> host = browser->GetHost();
 
   // Test if the DevTools browser already exists.
-  bool has_devtools = host->HasDevTools();
-  if (!has_devtools) {
-    // Create a new RootWindow for the DevTools browser that will be created
-    // by ShowDevTools().
-    has_devtools = CreatePopupWindow(browser, true, CefPopupFeatures(),
-                                     windowInfo, client, settings);
+  if (!MainContext::Get()->UseChromeRuntime() && !host->HasDevTools()) {
+    // Potentially create a new RootWindow for the DevTools browser that will be
+    // created by ShowDevTools(). For Chrome runtime this occurs in
+    // OnBeforeDevToolsPopup instead.
+    CreatePopupWindow(browser, /*is_devtools=*/true, CefPopupFeatures(),
+                      windowInfo, client, settings);
   }
 
-  if (has_devtools) {
-    // Create the DevTools browser if it doesn't already exist.
-    // Otherwise, focus the existing DevTools browser and inspect the element
-    // at |inspect_element_at| if non-empty.
-    host->ShowDevTools(windowInfo, client, settings, inspect_element_at);
-  }
+  // Create the DevTools browser if it doesn't already exist.
+  // Otherwise, focus the existing DevTools browser and inspect the element
+  // at |inspect_element_at| if non-empty.
+  host->ShowDevTools(windowInfo, client, settings, inspect_element_at);
 }
 
 void ClientHandler::CloseDevTools(CefRefPtr<CefBrowser> browser) {
@@ -957,12 +1358,14 @@
   std::stringstream ss;
   CefRefPtr<CefNavigationEntry> nav =
       browser->GetHost()->GetVisibleNavigationEntry();
-  if (!nav)
+  if (!nav) {
     return;
+  }
 
   CefRefPtr<CefSSLStatus> ssl = nav->GetSSLStatus();
-  if (!ssl)
+  if (!ssl) {
     return;
+  }
 
   ss << "<html><head><title>SSL Information</title></head>"
         "<body bgcolor=\"white\">"
@@ -973,8 +1376,9 @@
   if (CefParseURL(nav->GetURL(), urlparts)) {
     CefString port(&urlparts.port);
     ss << "<tr><td>Server</td><td>" << CefString(&urlparts.host).ToString();
-    if (!port.empty())
+    if (!port.empty()) {
       ss << ":" << port.ToString();
+    }
     ss << "</td></tr>";
   }
 
@@ -986,23 +1390,25 @@
   ss << "</table>";
 
   CefRefPtr<CefX509Certificate> cert = ssl->GetX509Certificate();
-  if (cert.get())
+  if (cert.get()) {
     ss << GetCertificateInformation(cert, ssl->GetCertStatus());
+  }
 
   ss << "</body></html>";
 
-  RootWindowConfig config;
-  config.with_controls = false;
-  config.with_osr = is_osr();
-  config.url = test_runner::GetDataURI(ss.str(), "text/html");
-  MainContext::Get()->GetRootWindowManager()->CreateRootWindow(config);
+  auto config = std::make_unique<RootWindowConfig>();
+  config->with_controls = false;
+  config->with_osr = is_osr_;
+  config->url = test_runner::GetDataURI(ss.str(), "text/html");
+  MainContext::Get()->GetRootWindowManager()->CreateRootWindow(
+      std::move(config));
 }
 
 void ClientHandler::SetStringResource(const std::string& page,
                                       const std::string& data) {
   if (!CefCurrentlyOn(TID_IO)) {
-    CefPostTask(TID_IO, base::Bind(&ClientHandler::SetStringResource, this,
-                                   page, data));
+    CefPostTask(TID_IO, base::BindOnce(&ClientHandler::SetStringResource, this,
+                                       page, data));
     return;
   }
 
@@ -1019,103 +1425,112 @@
 
   // The popup browser will be parented to a new native window.
   // Don't show URL bar and navigation buttons on DevTools windows.
-  MainContext::Get()->GetRootWindowManager()->CreateRootWindowAsPopup(
-      !is_devtools, is_osr(), popupFeatures, windowInfo, client, settings);
-
-  return true;
+  // May return nullptr if UseDefaultPopup() returns true.
+  return !!MainContext::Get()->GetRootWindowManager()->CreateRootWindowAsPopup(
+      with_controls_ && !is_devtools, is_osr_, popupFeatures, windowInfo,
+      client, settings);
 }
 
 void ClientHandler::NotifyBrowserCreated(CefRefPtr<CefBrowser> browser) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
     MAIN_POST_CLOSURE(
-        base::Bind(&ClientHandler::NotifyBrowserCreated, this, browser));
+        base::BindOnce(&ClientHandler::NotifyBrowserCreated, this, browser));
     return;
   }
 
-  if (delegate_)
+  if (delegate_) {
     delegate_->OnBrowserCreated(browser);
+  }
 }
 
 void ClientHandler::NotifyBrowserClosing(CefRefPtr<CefBrowser> browser) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
     MAIN_POST_CLOSURE(
-        base::Bind(&ClientHandler::NotifyBrowserClosing, this, browser));
+        base::BindOnce(&ClientHandler::NotifyBrowserClosing, this, browser));
     return;
   }
 
-  if (delegate_)
+  if (delegate_) {
     delegate_->OnBrowserClosing(browser);
+  }
 }
 
 void ClientHandler::NotifyBrowserClosed(CefRefPtr<CefBrowser> browser) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
     MAIN_POST_CLOSURE(
-        base::Bind(&ClientHandler::NotifyBrowserClosed, this, browser));
+        base::BindOnce(&ClientHandler::NotifyBrowserClosed, this, browser));
     return;
   }
 
-  if (delegate_)
+  if (delegate_) {
     delegate_->OnBrowserClosed(browser);
+  }
 }
 
 void ClientHandler::NotifyAddress(const CefString& url) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
-    MAIN_POST_CLOSURE(base::Bind(&ClientHandler::NotifyAddress, this, url));
+    MAIN_POST_CLOSURE(base::BindOnce(&ClientHandler::NotifyAddress, this, url));
     return;
   }
 
-  if (delegate_)
+  if (delegate_) {
     delegate_->OnSetAddress(url);
+  }
 }
 
 void ClientHandler::NotifyTitle(const CefString& title) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
-    MAIN_POST_CLOSURE(base::Bind(&ClientHandler::NotifyTitle, this, title));
+    MAIN_POST_CLOSURE(base::BindOnce(&ClientHandler::NotifyTitle, this, title));
     return;
   }
 
-  if (delegate_)
+  if (delegate_) {
     delegate_->OnSetTitle(title);
+  }
 }
 
 void ClientHandler::NotifyFavicon(CefRefPtr<CefImage> image) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
-    MAIN_POST_CLOSURE(base::Bind(&ClientHandler::NotifyFavicon, this, image));
+    MAIN_POST_CLOSURE(
+        base::BindOnce(&ClientHandler::NotifyFavicon, this, image));
     return;
   }
 
-  if (delegate_)
+  if (delegate_) {
     delegate_->OnSetFavicon(image);
+  }
 }
 
 void ClientHandler::NotifyFullscreen(bool fullscreen) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
     MAIN_POST_CLOSURE(
-        base::Bind(&ClientHandler::NotifyFullscreen, this, fullscreen));
+        base::BindOnce(&ClientHandler::NotifyFullscreen, this, fullscreen));
     return;
   }
 
-  if (delegate_)
+  if (delegate_) {
     delegate_->OnSetFullscreen(fullscreen);
+  }
 }
 
 void ClientHandler::NotifyAutoResize(const CefSize& new_size) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
     MAIN_POST_CLOSURE(
-        base::Bind(&ClientHandler::NotifyAutoResize, this, new_size));
+        base::BindOnce(&ClientHandler::NotifyAutoResize, this, new_size));
     return;
   }
 
-  if (delegate_)
+  if (delegate_) {
     delegate_->OnAutoResize(new_size);
+  }
 }
 
 void ClientHandler::NotifyLoadingState(bool isLoading,
@@ -1123,13 +1538,14 @@
                                        bool canGoForward) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
-    MAIN_POST_CLOSURE(base::Bind(&ClientHandler::NotifyLoadingState, this,
-                                 isLoading, canGoBack, canGoForward));
+    MAIN_POST_CLOSURE(base::BindOnce(&ClientHandler::NotifyLoadingState, this,
+                                     isLoading, canGoBack, canGoForward));
     return;
   }
 
-  if (delegate_)
+  if (delegate_) {
     delegate_->OnSetLoadingState(isLoading, canGoBack, canGoForward);
+  }
 }
 
 void ClientHandler::NotifyDraggableRegions(
@@ -1137,28 +1553,32 @@
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
     MAIN_POST_CLOSURE(
-        base::Bind(&ClientHandler::NotifyDraggableRegions, this, regions));
+        base::BindOnce(&ClientHandler::NotifyDraggableRegions, this, regions));
     return;
   }
 
-  if (delegate_)
+  if (delegate_) {
     delegate_->OnSetDraggableRegions(regions);
+  }
 }
 
 void ClientHandler::NotifyTakeFocus(bool next) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
-    MAIN_POST_CLOSURE(base::Bind(&ClientHandler::NotifyTakeFocus, this, next));
+    MAIN_POST_CLOSURE(
+        base::BindOnce(&ClientHandler::NotifyTakeFocus, this, next));
     return;
   }
 
-  if (delegate_)
+  if (delegate_) {
     delegate_->OnTakeFocus(next);
+  }
 }
 
 void ClientHandler::BuildTestMenu(CefRefPtr<CefMenuModel> model) {
-  if (model->GetCount() > 0)
+  if (model->GetCount() > 0) {
     model->AddSeparator();
+  }
 
   // Build the sub menu.
   CefRefPtr<CefMenuModel> submenu =
@@ -1169,8 +1589,9 @@
   submenu->AddRadioItem(CLIENT_ID_TESTMENU_RADIOITEM3, "Radio Item 3", 0);
 
   // Check the check item.
-  if (test_menu_state_.check_item)
+  if (test_menu_state_.check_item) {
     submenu->SetChecked(CLIENT_ID_TESTMENU_CHECKITEM, true);
+  }
 
   // Check the selected radio item.
   submenu->SetChecked(
diff --git a/src/tests/cefclient/browser/client_handler.h b/src/tests/cefclient/browser/client_handler.h
index 599ef7f..f1f9fe1 100644
--- a/src/tests/cefclient/browser/client_handler.h
+++ b/src/tests/cefclient/browser/client_handler.h
@@ -18,6 +18,7 @@
 
 #if defined(OS_LINUX)
 #include "tests/cefclient/browser/dialog_handler_gtk.h"
+#include "tests/cefclient/browser/print_handler_gtk.h"
 #endif
 
 namespace client {
@@ -27,6 +28,7 @@
 // Client handler abstract base class. Provides common functionality shared by
 // all concrete client handler implementations.
 class ClientHandler : public CefClient,
+                      public CefCommandHandler,
                       public CefContextMenuHandler,
                       public CefDisplayHandler,
                       public CefDownloadHandler,
@@ -35,6 +37,7 @@
                       public CefKeyboardHandler,
                       public CefLifeSpanHandler,
                       public CefLoadHandler,
+                      public CefPermissionHandler,
                       public CefRequestHandler,
                       public CefResourceRequestHandler {
  public:
@@ -92,6 +95,7 @@
   // |delegate| must outlive this object or DetachDelegate() must be called.
   ClientHandler(Delegate* delegate,
                 bool is_osr,
+                bool with_controls,
                 const std::string& startup_url);
 
   // This object may outlive the Delegate object so it's necessary for the
@@ -99,87 +103,112 @@
   void DetachDelegate();
 
   // CefClient methods
-  CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() OVERRIDE {
+  CefRefPtr<CefCommandHandler> GetCommandHandler() override { return this; }
+  CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() override {
     return this;
   }
-  CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE { return this; }
-  CefRefPtr<CefDownloadHandler> GetDownloadHandler() OVERRIDE { return this; }
-  CefRefPtr<CefDragHandler> GetDragHandler() OVERRIDE { return this; }
-  CefRefPtr<CefFocusHandler> GetFocusHandler() OVERRIDE { return this; }
-  CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() OVERRIDE { return this; }
-  CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE { return this; }
-  CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE { return this; }
-  CefRefPtr<CefRequestHandler> GetRequestHandler() OVERRIDE { return this; }
+  CefRefPtr<CefDisplayHandler> GetDisplayHandler() override { return this; }
+  CefRefPtr<CefDownloadHandler> GetDownloadHandler() override { return this; }
+  CefRefPtr<CefDragHandler> GetDragHandler() override { return this; }
+  CefRefPtr<CefFocusHandler> GetFocusHandler() override { return this; }
+  CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() override { return this; }
+  CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }
+  CefRefPtr<CefLoadHandler> GetLoadHandler() override { return this; }
+  CefRefPtr<CefRequestHandler> GetRequestHandler() override { return this; }
+  CefRefPtr<CefPermissionHandler> GetPermissionHandler() override {
+    return this;
+  }
   bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
                                 CefRefPtr<CefFrame> frame,
                                 CefProcessId source_process,
-                                CefRefPtr<CefProcessMessage> message) OVERRIDE;
+                                CefRefPtr<CefProcessMessage> message) override;
 
 #if defined(OS_LINUX)
-  CefRefPtr<CefDialogHandler> GetDialogHandler() OVERRIDE {
-    return dialog_handler_;
+  CefRefPtr<CefDialogHandler> GetDialogHandler() override {
+    return file_dialog_handler_;
   }
-  CefRefPtr<CefJSDialogHandler> GetJSDialogHandler() OVERRIDE {
-    return dialog_handler_;
+  CefRefPtr<CefJSDialogHandler> GetJSDialogHandler() override {
+    return js_dialog_handler_;
+  }
+  CefRefPtr<CefPrintHandler> GetPrintHandler() override {
+    return print_handler_;
   }
 #endif
 
+  // CefCommandHandler methods
+  bool OnChromeCommand(CefRefPtr<CefBrowser> browser,
+                       int command_id,
+                       cef_window_open_disposition_t disposition) override;
+  bool IsChromeAppMenuItemVisible(CefRefPtr<CefBrowser> browser,
+                                  int command_id) override;
+  bool IsChromePageActionIconVisible(
+      cef_chrome_page_action_icon_type_t icon_type) override;
+  bool IsChromeToolbarButtonVisible(
+      cef_chrome_toolbar_button_type_t button_type) override;
+
   // CefContextMenuHandler methods
   void OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
                            CefRefPtr<CefFrame> frame,
                            CefRefPtr<CefContextMenuParams> params,
-                           CefRefPtr<CefMenuModel> model) OVERRIDE;
+                           CefRefPtr<CefMenuModel> model) override;
   bool OnContextMenuCommand(CefRefPtr<CefBrowser> browser,
                             CefRefPtr<CefFrame> frame,
                             CefRefPtr<CefContextMenuParams> params,
                             int command_id,
-                            EventFlags event_flags) OVERRIDE;
+                            EventFlags event_flags) override;
 
   // CefDisplayHandler methods
   void OnAddressChange(CefRefPtr<CefBrowser> browser,
                        CefRefPtr<CefFrame> frame,
-                       const CefString& url) OVERRIDE;
+                       const CefString& url) override;
   void OnTitleChange(CefRefPtr<CefBrowser> browser,
-                     const CefString& title) OVERRIDE;
+                     const CefString& title) override;
   void OnFaviconURLChange(CefRefPtr<CefBrowser> browser,
-                          const std::vector<CefString>& icon_urls) OVERRIDE;
+                          const std::vector<CefString>& icon_urls) override;
   void OnFullscreenModeChange(CefRefPtr<CefBrowser> browser,
-                              bool fullscreen) OVERRIDE;
+                              bool fullscreen) override;
   bool OnConsoleMessage(CefRefPtr<CefBrowser> browser,
                         cef_log_severity_t level,
                         const CefString& message,
                         const CefString& source,
-                        int line) OVERRIDE;
+                        int line) override;
   bool OnAutoResize(CefRefPtr<CefBrowser> browser,
-                    const CefSize& new_size) OVERRIDE;
+                    const CefSize& new_size) override;
+  bool OnCursorChange(CefRefPtr<CefBrowser> browser,
+                      CefCursorHandle cursor,
+                      cef_cursor_type_t type,
+                      const CefCursorInfo& custom_cursor_info) override;
 
   // CefDownloadHandler methods
+  bool CanDownload(CefRefPtr<CefBrowser> browser,
+                   const CefString& url,
+                   const CefString& request_method) override;
   void OnBeforeDownload(CefRefPtr<CefBrowser> browser,
                         CefRefPtr<CefDownloadItem> download_item,
                         const CefString& suggested_name,
-                        CefRefPtr<CefBeforeDownloadCallback> callback) OVERRIDE;
+                        CefRefPtr<CefBeforeDownloadCallback> callback) override;
   void OnDownloadUpdated(CefRefPtr<CefBrowser> browser,
                          CefRefPtr<CefDownloadItem> download_item,
-                         CefRefPtr<CefDownloadItemCallback> callback) OVERRIDE;
+                         CefRefPtr<CefDownloadItemCallback> callback) override;
 
   // CefDragHandler methods
   bool OnDragEnter(CefRefPtr<CefBrowser> browser,
                    CefRefPtr<CefDragData> dragData,
-                   CefDragHandler::DragOperationsMask mask) OVERRIDE;
+                   CefDragHandler::DragOperationsMask mask) override;
   void OnDraggableRegionsChanged(
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
-      const std::vector<CefDraggableRegion>& regions) OVERRIDE;
+      const std::vector<CefDraggableRegion>& regions) override;
 
   // CefFocusHandler methods
-  void OnTakeFocus(CefRefPtr<CefBrowser> browser, bool next) OVERRIDE;
-  bool OnSetFocus(CefRefPtr<CefBrowser> browser, FocusSource source) OVERRIDE;
+  void OnTakeFocus(CefRefPtr<CefBrowser> browser, bool next) override;
+  bool OnSetFocus(CefRefPtr<CefBrowser> browser, FocusSource source) override;
 
   // CefKeyboardHandler methods
   bool OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
                      const CefKeyEvent& event,
                      CefEventHandle os_event,
-                     bool* is_keyboard_shortcut) OVERRIDE;
+                     bool* is_keyboard_shortcut) override;
 
   // CefLifeSpanHandler methods
   bool OnBeforePopup(
@@ -194,34 +223,48 @@
       CefRefPtr<CefClient>& client,
       CefBrowserSettings& settings,
       CefRefPtr<CefDictionaryValue>& extra_info,
-      bool* no_javascript_access) OVERRIDE;
-  void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
+      bool* no_javascript_access) override;
+  void OnBeforeDevToolsPopup(CefRefPtr<CefBrowser> browser,
+                             CefWindowInfo& windowInfo,
+                             CefRefPtr<CefClient>& client,
+                             CefBrowserSettings& settings,
+                             CefRefPtr<CefDictionaryValue>& extra_info,
+                             bool* use_default_window) override;
+  void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
+  bool DoClose(CefRefPtr<CefBrowser> browser) override;
+  void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
 
   // CefLoadHandler methods
   void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
                             bool isLoading,
                             bool canGoBack,
-                            bool canGoForward) OVERRIDE;
+                            bool canGoForward) override;
   void OnLoadError(CefRefPtr<CefBrowser> browser,
                    CefRefPtr<CefFrame> frame,
                    ErrorCode errorCode,
                    const CefString& errorText,
-                   const CefString& failedUrl) OVERRIDE;
+                   const CefString& failedUrl) override;
+
+  // CefPermissionHandler methods
+  bool OnRequestMediaAccessPermission(
+      CefRefPtr<CefBrowser> browser,
+      CefRefPtr<CefFrame> frame,
+      const CefString& requesting_origin,
+      uint32_t requested_permissions,
+      CefRefPtr<CefMediaAccessCallback> callback) override;
 
   // CefRequestHandler methods
   bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
                       CefRefPtr<CefFrame> frame,
                       CefRefPtr<CefRequest> request,
                       bool user_gesture,
-                      bool is_redirect) OVERRIDE;
+                      bool is_redirect) override;
   bool OnOpenURLFromTab(
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       const CefString& target_url,
       CefRequestHandler::WindowOpenDisposition target_disposition,
-      bool user_gesture) OVERRIDE;
+      bool user_gesture) override;
   CefRefPtr<CefResourceRequestHandler> GetResourceRequestHandler(
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
@@ -229,7 +272,7 @@
       bool is_navigation,
       bool is_download,
       const CefString& request_initiator,
-      bool& disable_default_handling) OVERRIDE;
+      bool& disable_default_handling) override;
   bool GetAuthCredentials(CefRefPtr<CefBrowser> browser,
                           const CefString& origin_url,
                           bool isProxy,
@@ -237,46 +280,42 @@
                           int port,
                           const CefString& realm,
                           const CefString& scheme,
-                          CefRefPtr<CefAuthCallback> callback) OVERRIDE;
-  bool OnQuotaRequest(CefRefPtr<CefBrowser> browser,
-                      const CefString& origin_url,
-                      int64 new_size,
-                      CefRefPtr<CefRequestCallback> callback) OVERRIDE;
+                          CefRefPtr<CefAuthCallback> callback) override;
   bool OnCertificateError(CefRefPtr<CefBrowser> browser,
                           ErrorCode cert_error,
                           const CefString& request_url,
                           CefRefPtr<CefSSLInfo> ssl_info,
-                          CefRefPtr<CefRequestCallback> callback) OVERRIDE;
+                          CefRefPtr<CefCallback> callback) override;
   bool OnSelectClientCertificate(
       CefRefPtr<CefBrowser> browser,
       bool isProxy,
       const CefString& host,
       int port,
       const X509CertificateList& certificates,
-      CefRefPtr<CefSelectClientCertificateCallback> callback) OVERRIDE;
+      CefRefPtr<CefSelectClientCertificateCallback> callback) override;
   void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
-                                 TerminationStatus status) OVERRIDE;
-  void OnDocumentAvailableInMainFrame(CefRefPtr<CefBrowser> browser) OVERRIDE;
+                                 TerminationStatus status) override;
+  void OnDocumentAvailableInMainFrame(CefRefPtr<CefBrowser> browser) override;
 
   // CefResourceRequestHandler methods
   cef_return_value_t OnBeforeResourceLoad(
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) OVERRIDE;
+      CefRefPtr<CefCallback> callback) override;
   CefRefPtr<CefResourceHandler> GetResourceHandler(
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
-      CefRefPtr<CefRequest> request) OVERRIDE;
+      CefRefPtr<CefRequest> request) override;
   CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request,
-      CefRefPtr<CefResponse> response) OVERRIDE;
+      CefRefPtr<CefResponse> response) override;
   void OnProtocolExecution(CefRefPtr<CefBrowser> browser,
                            CefRefPtr<CefFrame> frame,
                            CefRefPtr<CefRequest> request,
-                           bool& allow_os_execution) OVERRIDE;
+                           bool& allow_os_execution) override;
 
   // Returns the number of browsers currently using this handler. Can only be
   // called on the CEF UI thread.
@@ -304,9 +343,6 @@
   // Returns the startup URL.
   std::string startup_url() const { return startup_url_; }
 
-  // Returns true if this handler uses off-screen rendering.
-  bool is_osr() const { return is_osr_; }
-
   // Set/get whether the client should download favicon images. Only safe to
   // call immediately after client creation or on the browser process UI thread.
   bool download_favicon_images() const { return download_favicon_images_; }
@@ -318,9 +354,8 @@
   friend class ClientDownloadImageCallback;
 
   // Create a new popup window using the specified information. |is_devtools|
-  // will be true if the window will be used for DevTools. Return true to
-  // proceed with popup browser creation or false to cancel the popup browser.
-  // May be called on any thead.
+  // will be true if the window will be used for DevTools. Returns true if a
+  // RootWindow was created for the popup.
   bool CreatePopupWindow(CefRefPtr<CefBrowser> browser,
                          bool is_devtools,
                          const CefPopupFeatures& popupFeatures,
@@ -353,21 +388,32 @@
   // True if this handler uses off-screen rendering.
   const bool is_osr_;
 
+  // True if this handler shows controls.
+  const bool with_controls_;
+
   // The startup URL.
   const std::string startup_url_;
 
   // True if mouse cursor change is disabled.
   bool mouse_cursor_change_disabled_;
 
+  // True if media handling is disabled.
+  bool media_handling_disabled_ = true;
+
   // True if the browser is currently offline.
   bool offline_;
 
+  // True if the Chrome toolbar and menu contents/commands should be filtered.
+  bool filter_chrome_commands_;
+
   // True if Favicon images should be downloaded.
-  bool download_favicon_images_;
+  bool download_favicon_images_ = false;
 
 #if defined(OS_LINUX)
-  // Custom dialog handler for GTK.
-  CefRefPtr<ClientDialogHandlerGtk> dialog_handler_;
+  // Custom dialog handlers for GTK.
+  CefRefPtr<ClientDialogHandlerGtk> file_dialog_handler_;
+  CefRefPtr<ClientDialogHandlerGtk> js_dialog_handler_;
+  CefRefPtr<ClientPrintHandlerGtk> print_handler_;
 #endif
 
   // Handles the browser side of query routing. The renderer side is handled
@@ -399,17 +445,16 @@
   } test_menu_state_;
 
   // The current number of browsers using this handler.
-  int browser_count_;
+  int browser_count_ = 0;
 
   // Console logging state.
   const std::string console_log_file_;
-  bool first_console_message_;
 
   // True if an editable field currently has focus.
-  bool focus_on_editable_field_;
+  bool focus_on_editable_field_ = false;
 
   // True for the initial navigation after browser creation.
-  bool initial_navigation_;
+  bool initial_navigation_ = true;
 
   // Set of Handlers registered with the message router.
   MessageHandlerSet message_handler_set_;
diff --git a/src/tests/cefclient/browser/client_handler_osr.cc b/src/tests/cefclient/browser/client_handler_osr.cc
index a5873da..2f36af9 100644
--- a/src/tests/cefclient/browser/client_handler_osr.cc
+++ b/src/tests/cefclient/browser/client_handler_osr.cc
@@ -4,7 +4,7 @@
 
 #include "tests/cefclient/browser/client_handler_osr.h"
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "include/wrapper/cef_helpers.h"
 
@@ -12,15 +12,18 @@
 
 ClientHandlerOsr::ClientHandlerOsr(Delegate* delegate,
                                    OsrDelegate* osr_delegate,
+                                   bool with_controls,
                                    const std::string& startup_url)
-    : ClientHandler(delegate, true, startup_url), osr_delegate_(osr_delegate) {
+    : ClientHandler(delegate, /*is_osr=*/true, with_controls, startup_url),
+      osr_delegate_(osr_delegate) {
   DCHECK(osr_delegate_);
 }
 
 void ClientHandlerOsr::DetachOsrDelegate() {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&ClientHandlerOsr::DetachOsrDelegate, this));
+    CefPostTask(TID_UI,
+                base::BindOnce(&ClientHandlerOsr::DetachOsrDelegate, this));
     return;
   }
 
@@ -30,23 +33,26 @@
 
 void ClientHandlerOsr::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
   CEF_REQUIRE_UI_THREAD();
-  if (osr_delegate_)
+  if (osr_delegate_) {
     osr_delegate_->OnAfterCreated(browser);
+  }
   ClientHandler::OnAfterCreated(browser);
 }
 
 void ClientHandlerOsr::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
   CEF_REQUIRE_UI_THREAD();
-  if (osr_delegate_)
+  if (osr_delegate_) {
     osr_delegate_->OnBeforeClose(browser);
+  }
   ClientHandler::OnBeforeClose(browser);
 }
 
 bool ClientHandlerOsr::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
                                          CefRect& rect) {
   CEF_REQUIRE_UI_THREAD();
-  if (!osr_delegate_)
+  if (!osr_delegate_) {
     return false;
+  }
   return osr_delegate_->GetRootScreenRect(browser, rect);
 }
 
@@ -67,31 +73,35 @@
                                       int& screenX,
                                       int& screenY) {
   CEF_REQUIRE_UI_THREAD();
-  if (!osr_delegate_)
+  if (!osr_delegate_) {
     return false;
+  }
   return osr_delegate_->GetScreenPoint(browser, viewX, viewY, screenX, screenY);
 }
 
 bool ClientHandlerOsr::GetScreenInfo(CefRefPtr<CefBrowser> browser,
                                      CefScreenInfo& screen_info) {
   CEF_REQUIRE_UI_THREAD();
-  if (!osr_delegate_)
+  if (!osr_delegate_) {
     return false;
+  }
   return osr_delegate_->GetScreenInfo(browser, screen_info);
 }
 
 void ClientHandlerOsr::OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) {
   CEF_REQUIRE_UI_THREAD();
-  if (!osr_delegate_)
+  if (!osr_delegate_) {
     return;
+  }
   return osr_delegate_->OnPopupShow(browser, show);
 }
 
 void ClientHandlerOsr::OnPopupSize(CefRefPtr<CefBrowser> browser,
                                    const CefRect& rect) {
   CEF_REQUIRE_UI_THREAD();
-  if (!osr_delegate_)
+  if (!osr_delegate_) {
     return;
+  }
   return osr_delegate_->OnPopupSize(browser, rect);
 }
 
@@ -102,8 +112,9 @@
                                int width,
                                int height) {
   CEF_REQUIRE_UI_THREAD();
-  if (!osr_delegate_)
+  if (!osr_delegate_) {
     return;
+  }
   osr_delegate_->OnPaint(browser, type, dirtyRects, buffer, width, height);
 }
 
@@ -113,21 +124,12 @@
     const CefRenderHandler::RectList& dirtyRects,
     void* share_handle) {
   CEF_REQUIRE_UI_THREAD();
-  if (!osr_delegate_)
+  if (!osr_delegate_) {
     return;
+  }
   osr_delegate_->OnAcceleratedPaint(browser, type, dirtyRects, share_handle);
 }
 
-void ClientHandlerOsr::OnCursorChange(CefRefPtr<CefBrowser> browser,
-                                      CefCursorHandle cursor,
-                                      CursorType type,
-                                      const CefCursorInfo& custom_cursor_info) {
-  CEF_REQUIRE_UI_THREAD();
-  if (!osr_delegate_)
-    return;
-  osr_delegate_->OnCursorChange(browser, cursor, type, custom_cursor_info);
-}
-
 bool ClientHandlerOsr::StartDragging(
     CefRefPtr<CefBrowser> browser,
     CefRefPtr<CefDragData> drag_data,
@@ -135,8 +137,9 @@
     int x,
     int y) {
   CEF_REQUIRE_UI_THREAD();
-  if (!osr_delegate_)
+  if (!osr_delegate_) {
     return false;
+  }
   return osr_delegate_->StartDragging(browser, drag_data, allowed_ops, x, y);
 }
 
@@ -144,8 +147,9 @@
     CefRefPtr<CefBrowser> browser,
     CefRenderHandler::DragOperation operation) {
   CEF_REQUIRE_UI_THREAD();
-  if (!osr_delegate_)
+  if (!osr_delegate_) {
     return;
+  }
   osr_delegate_->UpdateDragCursor(browser, operation);
 }
 
@@ -154,24 +158,42 @@
     const CefRange& selection_range,
     const CefRenderHandler::RectList& character_bounds) {
   CEF_REQUIRE_UI_THREAD();
-  if (!osr_delegate_)
+  if (!osr_delegate_) {
     return;
+  }
   osr_delegate_->OnImeCompositionRangeChanged(browser, selection_range,
                                               character_bounds);
 }
 
 void ClientHandlerOsr::OnAccessibilityTreeChange(CefRefPtr<CefValue> value) {
   CEF_REQUIRE_UI_THREAD();
-  if (!osr_delegate_)
+  if (!osr_delegate_) {
     return;
+  }
   osr_delegate_->UpdateAccessibilityTree(value);
 }
 
+bool ClientHandlerOsr::OnCursorChange(CefRefPtr<CefBrowser> browser,
+                                      CefCursorHandle cursor,
+                                      cef_cursor_type_t type,
+                                      const CefCursorInfo& custom_cursor_info) {
+  CEF_REQUIRE_UI_THREAD();
+  if (ClientHandler::OnCursorChange(browser, cursor, type,
+                                    custom_cursor_info)) {
+    return true;
+  }
+  if (osr_delegate_) {
+    osr_delegate_->OnCursorChange(browser, cursor, type, custom_cursor_info);
+  }
+  return true;
+}
+
 void ClientHandlerOsr::OnAccessibilityLocationChange(
     CefRefPtr<CefValue> value) {
   CEF_REQUIRE_UI_THREAD();
-  if (!osr_delegate_)
+  if (!osr_delegate_) {
     return;
+  }
   osr_delegate_->UpdateAccessibilityLocation(value);
 }
 
diff --git a/src/tests/cefclient/browser/client_handler_osr.h b/src/tests/cefclient/browser/client_handler_osr.h
index 1a2c200..1fe247e 100644
--- a/src/tests/cefclient/browser/client_handler_osr.h
+++ b/src/tests/cefclient/browser/client_handler_osr.h
@@ -49,10 +49,6 @@
         CefRenderHandler::PaintElementType type,
         const CefRenderHandler::RectList& dirtyRects,
         void* share_handle) {}
-    virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
-                                CefCursorHandle cursor,
-                                CefRenderHandler::CursorType type,
-                                const CefCursorInfo& custom_cursor_info) = 0;
     virtual bool StartDragging(CefRefPtr<CefBrowser> browser,
                                CefRefPtr<CefDragData> drag_data,
                                CefRenderHandler::DragOperationsMask allowed_ops,
@@ -66,8 +62,13 @@
         const CefRange& selection_range,
         const CefRenderHandler::RectList& character_bounds) = 0;
 
-    virtual void UpdateAccessibilityTree(CefRefPtr<CefValue> value) = 0;
+    // These methods match the CefDisplayHandler interface.
+    virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
+                                CefCursorHandle cursor,
+                                cef_cursor_type_t type,
+                                const CefCursorInfo& custom_cursor_info) = 0;
 
+    virtual void UpdateAccessibilityTree(CefRefPtr<CefValue> value) = 0;
     virtual void UpdateAccessibilityLocation(CefRefPtr<CefValue> value) = 0;
 
    protected:
@@ -76,6 +77,7 @@
 
   ClientHandlerOsr(Delegate* delegate,
                    OsrDelegate* osr_delegate,
+                   bool with_controls,
                    const std::string& startup_url);
 
   // This object may outlive the OsrDelegate object so it's necessary for the
@@ -83,56 +85,58 @@
   void DetachOsrDelegate();
 
   // CefClient methods.
-  CefRefPtr<CefRenderHandler> GetRenderHandler() OVERRIDE { return this; }
-  CefRefPtr<CefAccessibilityHandler> GetAccessibilityHandler() OVERRIDE {
+  CefRefPtr<CefRenderHandler> GetRenderHandler() override { return this; }
+  CefRefPtr<CefAccessibilityHandler> GetAccessibilityHandler() override {
     return this;
   }
 
   // CefLifeSpanHandler methods.
-  void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
+  void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
+  void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
 
   // CefRenderHandler methods.
-  bool GetRootScreenRect(CefRefPtr<CefBrowser> browser, CefRect& rect) OVERRIDE;
-  void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) OVERRIDE;
+  bool GetRootScreenRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override;
+  void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override;
   bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
                       int viewX,
                       int viewY,
                       int& screenX,
-                      int& screenY) OVERRIDE;
+                      int& screenY) override;
   bool GetScreenInfo(CefRefPtr<CefBrowser> browser,
-                     CefScreenInfo& screen_info) OVERRIDE;
-  void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) OVERRIDE;
-  void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect) OVERRIDE;
+                     CefScreenInfo& screen_info) override;
+  void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) override;
+  void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect) override;
   void OnPaint(CefRefPtr<CefBrowser> browser,
                CefRenderHandler::PaintElementType type,
                const CefRenderHandler::RectList& dirtyRects,
                const void* buffer,
                int width,
-               int height) OVERRIDE;
+               int height) override;
   void OnAcceleratedPaint(CefRefPtr<CefBrowser> browser,
                           CefRenderHandler::PaintElementType type,
                           const CefRenderHandler::RectList& dirtyRects,
-                          void* share_handle) OVERRIDE;
-  void OnCursorChange(CefRefPtr<CefBrowser> browser,
-                      CefCursorHandle cursor,
-                      CursorType type,
-                      const CefCursorInfo& custom_cursor_info) OVERRIDE;
+                          void* share_handle) override;
   bool StartDragging(CefRefPtr<CefBrowser> browser,
                      CefRefPtr<CefDragData> drag_data,
                      CefRenderHandler::DragOperationsMask allowed_ops,
                      int x,
-                     int y) OVERRIDE;
+                     int y) override;
   void UpdateDragCursor(CefRefPtr<CefBrowser> browser,
-                        CefRenderHandler::DragOperation operation) OVERRIDE;
+                        CefRenderHandler::DragOperation operation) override;
   void OnImeCompositionRangeChanged(
       CefRefPtr<CefBrowser> browser,
       const CefRange& selection_range,
-      const CefRenderHandler::RectList& character_bounds) OVERRIDE;
+      const CefRenderHandler::RectList& character_bounds) override;
+
+  // CefDisplayHandler methods.
+  bool OnCursorChange(CefRefPtr<CefBrowser> browser,
+                      CefCursorHandle cursor,
+                      cef_cursor_type_t type,
+                      const CefCursorInfo& custom_cursor_info) override;
 
   // CefAccessibilityHandler methods.
-  void OnAccessibilityTreeChange(CefRefPtr<CefValue> value) OVERRIDE;
-  void OnAccessibilityLocationChange(CefRefPtr<CefValue> value) OVERRIDE;
+  void OnAccessibilityTreeChange(CefRefPtr<CefValue> value) override;
+  void OnAccessibilityLocationChange(CefRefPtr<CefValue> value) override;
 
  private:
   // Only accessed on the UI thread.
diff --git a/src/tests/cefclient/browser/client_handler_std.cc b/src/tests/cefclient/browser/client_handler_std.cc
index 803028f..e78166d 100644
--- a/src/tests/cefclient/browser/client_handler_std.cc
+++ b/src/tests/cefclient/browser/client_handler_std.cc
@@ -7,7 +7,8 @@
 namespace client {
 
 ClientHandlerStd::ClientHandlerStd(Delegate* delegate,
+                                   bool with_controls,
                                    const std::string& startup_url)
-    : ClientHandler(delegate, false, startup_url) {}
+    : ClientHandler(delegate, /*is_osr=*/false, with_controls, startup_url) {}
 
 }  // namespace client
diff --git a/src/tests/cefclient/browser/client_handler_std.h b/src/tests/cefclient/browser/client_handler_std.h
index 5a73a3e..02aa747 100644
--- a/src/tests/cefclient/browser/client_handler_std.h
+++ b/src/tests/cefclient/browser/client_handler_std.h
@@ -14,7 +14,9 @@
 // one browser per handler instance.
 class ClientHandlerStd : public ClientHandler {
  public:
-  ClientHandlerStd(Delegate* delegate, const std::string& startup_url);
+  ClientHandlerStd(Delegate* delegate,
+                   bool with_controls,
+                   const std::string& startup_url);
 
  private:
   // Include the default reference counting implementation.
diff --git a/src/tests/cefclient/browser/client_prefs.cc b/src/tests/cefclient/browser/client_prefs.cc
new file mode 100644
index 0000000..e64a1de
--- /dev/null
+++ b/src/tests/cefclient/browser/client_prefs.cc
@@ -0,0 +1,206 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "tests/cefclient/browser/client_prefs.h"
+
+#include <memory>
+
+#include "include/base/cef_logging.h"
+#include "include/cef_command_line.h"
+#include "include/cef_preference.h"
+#include "include/cef_values.h"
+#include "include/views/cef_display.h"
+#include "include/wrapper/cef_helpers.h"
+#include "tests/shared/common/client_switches.h"
+#include "tests/shared/common/string_util.h"
+
+namespace client {
+namespace prefs {
+
+namespace {
+
+constexpr char kPrefWindowRestore[] = "cefclient.window_restore";
+
+constexpr char kWindowRestoreStateKey[] = "state";
+constexpr char kWindowRestoreBoundsKey[] = "bounds";
+constexpr char kWindowRestoreBoundsKey_X[] = "x";
+constexpr char kWindowRestoreBoundsKey_Y[] = "y";
+constexpr char kWindowRestoreBoundsKey_W[] = "w";
+constexpr char kWindowRestoreBoundsKey_H[] = "h";
+
+static struct {
+  const char* str;
+  cef_show_state_t state;
+} const kWindowRestoreStateValueMap[] = {
+    {"normal", CEF_SHOW_STATE_NORMAL},
+    {"minimized", CEF_SHOW_STATE_MINIMIZED},
+    {"maximized", CEF_SHOW_STATE_MAXIMIZED},
+    {"fullscreen", CEF_SHOW_STATE_FULLSCREEN},
+};
+
+std::optional<cef_show_state_t> ShowStateFromString(const std::string& str) {
+  const auto strLower = AsciiStrToLower(str);
+  for (size_t i = 0; i < std::size(kWindowRestoreStateValueMap); ++i) {
+    if (strLower == kWindowRestoreStateValueMap[i].str) {
+      return kWindowRestoreStateValueMap[i].state;
+    }
+  }
+  return std::nullopt;
+}
+
+const char* ShowStateToString(cef_show_state_t show_state) {
+  for (size_t i = 0; i < std::size(kWindowRestoreStateValueMap); ++i) {
+    if (show_state == kWindowRestoreStateValueMap[i].state) {
+      return kWindowRestoreStateValueMap[i].str;
+    }
+  }
+  NOTREACHED();
+  return nullptr;
+}
+
+// Create the CefValue representation that will be stored in preferences.
+CefRefPtr<CefValue> CreateWindowRestoreValue(
+    cef_show_state_t show_state,
+    std::optional<CefRect> dip_bounds) {
+  auto dict = CefDictionaryValue::Create();
+
+  // Show state is required.
+  dict->SetString(kWindowRestoreStateKey, ShowStateToString(show_state));
+
+  // Bounds is optional.
+  if (dip_bounds) {
+    auto bounds_dict = CefDictionaryValue::Create();
+    bounds_dict->SetInt(kWindowRestoreBoundsKey_X, dip_bounds->x);
+    bounds_dict->SetInt(kWindowRestoreBoundsKey_Y, dip_bounds->y);
+    bounds_dict->SetInt(kWindowRestoreBoundsKey_W, dip_bounds->width);
+    bounds_dict->SetInt(kWindowRestoreBoundsKey_H, dip_bounds->height);
+    dict->SetDictionary(kWindowRestoreBoundsKey, bounds_dict);
+  }
+
+  auto value = CefValue::Create();
+  value->SetDictionary(dict);
+  return value;
+}
+
+CefRefPtr<CefValue> CreateDefaultWindowRestoreValue() {
+  return CreateWindowRestoreValue(CEF_SHOW_STATE_NORMAL, std::nullopt);
+}
+
+// Parse the CefValue representation that was stored in preferences.
+bool ParseWindowRestoreValue(CefRefPtr<CefValue> value,
+                             cef_show_state_t& show_state,
+                             std::optional<CefRect>& dip_bounds) {
+  if (!value || value->GetType() != VTYPE_DICTIONARY) {
+    return false;
+  }
+
+  auto dict = value->GetDictionary();
+
+  bool has_state = false;
+
+  // Show state is required.
+  if (dict->GetType(kWindowRestoreStateKey) == VTYPE_STRING) {
+    auto result = ShowStateFromString(dict->GetString(kWindowRestoreStateKey));
+    if (result) {
+      show_state = *result;
+      has_state = true;
+    }
+  }
+
+  // Bounds is optional.
+  if (has_state && dict->GetType(kWindowRestoreBoundsKey) == VTYPE_DICTIONARY) {
+    auto bounds_dict = dict->GetDictionary(kWindowRestoreBoundsKey);
+    if (bounds_dict->GetType(kWindowRestoreBoundsKey_X) == VTYPE_INT &&
+        bounds_dict->GetType(kWindowRestoreBoundsKey_Y) == VTYPE_INT &&
+        bounds_dict->GetType(kWindowRestoreBoundsKey_W) == VTYPE_INT &&
+        bounds_dict->GetType(kWindowRestoreBoundsKey_H) == VTYPE_INT) {
+      dip_bounds = CefRect(bounds_dict->GetInt(kWindowRestoreBoundsKey_X),
+                           bounds_dict->GetInt(kWindowRestoreBoundsKey_Y),
+                           bounds_dict->GetInt(kWindowRestoreBoundsKey_W),
+                           bounds_dict->GetInt(kWindowRestoreBoundsKey_H));
+    }
+  }
+
+  return has_state;
+}
+
+// Keep the bounds inside the closest display work area.
+CefRect ClampBoundsToDisplay(const CefRect& dip_bounds) {
+  auto display = CefDisplay::GetDisplayMatchingBounds(
+      dip_bounds, /*input_pixel_coords=*/false);
+  const auto work_area = display->GetWorkArea();
+
+  CefRect bounds = dip_bounds;
+
+  if (bounds.width > work_area.width) {
+    bounds.width = work_area.width;
+  }
+  if (bounds.height > work_area.height) {
+    bounds.height = work_area.height;
+  }
+
+  if (bounds.x < work_area.x) {
+    bounds.x = work_area.x;
+  } else if (bounds.x + bounds.width >= work_area.x + work_area.width) {
+    bounds.x = work_area.x + work_area.width - bounds.width;
+  }
+
+  if (bounds.y < work_area.y) {
+    bounds.y = work_area.y;
+  } else if (bounds.y + bounds.height >= work_area.y + work_area.height) {
+    bounds.y = work_area.y + work_area.height - bounds.height;
+  }
+
+  return bounds;
+}
+
+}  // namespace
+
+void RegisterGlobalPreferences(CefRawPtr<CefPreferenceRegistrar> registrar) {
+  registrar->AddPreference(kPrefWindowRestore,
+                           CreateDefaultWindowRestoreValue());
+}
+
+bool LoadWindowRestorePreferences(cef_show_state_t& show_state,
+                                  std::optional<CefRect>& dip_bounds) {
+  CEF_REQUIRE_UI_THREAD();
+
+  // Check if show state was specified on the command-line.
+  auto command_line = CefCommandLine::GetGlobalCommandLine();
+  if (command_line->HasSwitch(switches::kInitialShowState)) {
+    auto result = ShowStateFromString(
+        command_line->GetSwitchValue(switches::kInitialShowState));
+    if (result) {
+      show_state = *result;
+      return true;
+    }
+  }
+
+  // Check if show state was saved in global preferences.
+  auto manager = CefPreferenceManager::GetGlobalPreferenceManager();
+  if (ParseWindowRestoreValue(manager->GetPreference(kPrefWindowRestore),
+                              show_state, dip_bounds)) {
+    if (dip_bounds) {
+      // Keep the bounds inside the closest display.
+      dip_bounds = ClampBoundsToDisplay(*dip_bounds);
+    }
+    return true;
+  }
+
+  return false;
+}
+
+bool SaveWindowRestorePreferences(cef_show_state_t show_state,
+                                  std::optional<CefRect> dip_bounds) {
+  CEF_REQUIRE_UI_THREAD();
+  auto manager = CefPreferenceManager::GetGlobalPreferenceManager();
+
+  CefString error;
+  return manager->SetPreference(
+      kPrefWindowRestore, CreateWindowRestoreValue(show_state, dip_bounds),
+      error);
+}
+
+}  // namespace prefs
+}  // namespace client
diff --git a/src/tests/cefclient/browser/client_prefs.h b/src/tests/cefclient/browser/client_prefs.h
new file mode 100644
index 0000000..577290d
--- /dev/null
+++ b/src/tests/cefclient/browser/client_prefs.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_PREFS_H_
+#define CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_PREFS_H_
+#pragma once
+
+#include <optional>
+
+#include "include/cef_base.h"
+#include "include/cef_preference.h"
+
+namespace client {
+namespace prefs {
+
+// Register global preferences with default values.
+void RegisterGlobalPreferences(CefRawPtr<CefPreferenceRegistrar> registrar);
+
+// Load/save window restore info.
+bool LoadWindowRestorePreferences(cef_show_state_t& show_state,
+                                  std::optional<CefRect>& dip_bounds);
+bool SaveWindowRestorePreferences(cef_show_state_t show_state,
+                                  std::optional<CefRect> dip_bounds);
+
+}  // namespace prefs
+}  // namespace client
+
+#endif  // CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_PREFS_H_
diff --git a/src/tests/cefclient/browser/client_types.h b/src/tests/cefclient/browser/client_types.h
index 2eefd19..092c711 100644
--- a/src/tests/cefclient/browser/client_types.h
+++ b/src/tests/cefclient/browser/client_types.h
@@ -17,13 +17,13 @@
 #define ClientWindowHandle CefWindowHandle
 #endif
 
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
 #define ClientNativeMacWindow void*
 #ifdef __OBJC__
 #define CAST_CLIENT_NATIVE_MAC_WINDOW_TO_NSWINDOW(native) \
   (__bridge NSWindow*)native
 #define CAST_NSWINDOW_TO_CLIENT_NATIVE_MAC_WINDOW(window) (__bridge void*)window
 #endif  // __OBJC__
-#endif  // defined OS_MACOSX
+#endif  // defined OS_MAC
 
 #endif  // CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_TYPES_H_
diff --git a/src/tests/cefclient/browser/default_client_handler.cc b/src/tests/cefclient/browser/default_client_handler.cc
new file mode 100644
index 0000000..d42f32a
--- /dev/null
+++ b/src/tests/cefclient/browser/default_client_handler.cc
@@ -0,0 +1,60 @@
+// Copyright (c) 2023 The Chromium Embedded Framework 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 "tests/cefclient/browser/default_client_handler.h"
+
+#include "tests/cefclient/browser/test_runner.h"
+
+namespace client {
+
+DefaultClientHandler::DefaultClientHandler() {
+  resource_manager_ = new CefResourceManager();
+  test_runner::SetupResourceManager(resource_manager_, nullptr);
+}
+
+CefRefPtr<CefResourceRequestHandler>
+DefaultClientHandler::GetResourceRequestHandler(
+    CefRefPtr<CefBrowser> browser,
+    CefRefPtr<CefFrame> frame,
+    CefRefPtr<CefRequest> request,
+    bool is_navigation,
+    bool is_download,
+    const CefString& request_initiator,
+    bool& disable_default_handling) {
+  CEF_REQUIRE_IO_THREAD();
+  return this;
+}
+
+cef_return_value_t DefaultClientHandler::OnBeforeResourceLoad(
+    CefRefPtr<CefBrowser> browser,
+    CefRefPtr<CefFrame> frame,
+    CefRefPtr<CefRequest> request,
+    CefRefPtr<CefCallback> callback) {
+  CEF_REQUIRE_IO_THREAD();
+
+  return resource_manager_->OnBeforeResourceLoad(browser, frame, request,
+                                                 callback);
+}
+
+CefRefPtr<CefResourceHandler> DefaultClientHandler::GetResourceHandler(
+    CefRefPtr<CefBrowser> browser,
+    CefRefPtr<CefFrame> frame,
+    CefRefPtr<CefRequest> request) {
+  CEF_REQUIRE_IO_THREAD();
+
+  return resource_manager_->GetResourceHandler(browser, frame, request);
+}
+
+CefRefPtr<CefResponseFilter> DefaultClientHandler::GetResourceResponseFilter(
+    CefRefPtr<CefBrowser> browser,
+    CefRefPtr<CefFrame> frame,
+    CefRefPtr<CefRequest> request,
+    CefRefPtr<CefResponse> response) {
+  CEF_REQUIRE_IO_THREAD();
+
+  return test_runner::GetResourceResponseFilter(browser, frame, request,
+                                                response);
+}
+
+}  // namespace client
diff --git a/src/tests/cefclient/browser/default_client_handler.h b/src/tests/cefclient/browser/default_client_handler.h
new file mode 100644
index 0000000..6970d4c
--- /dev/null
+++ b/src/tests/cefclient/browser/default_client_handler.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2023 The Chromium Embedded Framework 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 CEF_TESTS_CEFCLIENT_BROWSER_DEFAULT_CLIENT_HANDLER_H_
+#define CEF_TESTS_CEFCLIENT_BROWSER_DEFAULT_CLIENT_HANDLER_H_
+#pragma once
+
+#include "include/cef_client.h"
+#include "include/wrapper/cef_resource_manager.h"
+
+namespace client {
+
+// Default client handler for unmanaged browser windows. Used with the Chrome
+// runtime only.
+class DefaultClientHandler : public CefClient,
+                             public CefRequestHandler,
+                             public CefResourceRequestHandler {
+ public:
+  DefaultClientHandler();
+
+  // CefClient methods
+  CefRefPtr<CefRequestHandler> GetRequestHandler() override { return this; }
+
+  // CefRequestHandler methods
+  CefRefPtr<CefResourceRequestHandler> GetResourceRequestHandler(
+      CefRefPtr<CefBrowser> browser,
+      CefRefPtr<CefFrame> frame,
+      CefRefPtr<CefRequest> request,
+      bool is_navigation,
+      bool is_download,
+      const CefString& request_initiator,
+      bool& disable_default_handling) override;
+
+  // CefResourceRequestHandler methods
+  cef_return_value_t OnBeforeResourceLoad(
+      CefRefPtr<CefBrowser> browser,
+      CefRefPtr<CefFrame> frame,
+      CefRefPtr<CefRequest> request,
+      CefRefPtr<CefCallback> callback) override;
+  CefRefPtr<CefResourceHandler> GetResourceHandler(
+      CefRefPtr<CefBrowser> browser,
+      CefRefPtr<CefFrame> frame,
+      CefRefPtr<CefRequest> request) override;
+  CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
+      CefRefPtr<CefBrowser> browser,
+      CefRefPtr<CefFrame> frame,
+      CefRefPtr<CefRequest> request,
+      CefRefPtr<CefResponse> response) override;
+
+ private:
+  // Manages the registration and delivery of resources.
+  CefRefPtr<CefResourceManager> resource_manager_;
+
+  IMPLEMENT_REFCOUNTING(DefaultClientHandler);
+  DISALLOW_COPY_AND_ASSIGN(DefaultClientHandler);
+};
+
+}  // namespace client
+
+#endif  // CEF_TESTS_CEFCLIENT_BROWSER_DEFAULT_CLIENT_HANDLER_H_
diff --git a/src/tests/cefclient/browser/dialog_handler_gtk.cc b/src/tests/cefclient/browser/dialog_handler_gtk.cc
index 1958a52..33e687b 100644
--- a/src/tests/cefclient/browser/dialog_handler_gtk.cc
+++ b/src/tests/cefclient/browser/dialog_handler_gtk.cc
@@ -24,8 +24,9 @@
 std::string GetPromptText(GtkDialog* dialog) {
   GtkWidget* widget = static_cast<GtkWidget*>(
       g_object_get_data(G_OBJECT(dialog), kPromptTextId));
-  if (widget)
+  if (widget) {
     return gtk_entry_get_text(GTK_ENTRY(widget));
+  }
   return std::string();
 }
 
@@ -43,8 +44,9 @@
 
   for (size_t i = 0;
        i < sizeof(kWildCardMimeTypes) / sizeof(kWildCardMimeTypes[0]); ++i) {
-    if (mime_type == std::string(kWildCardMimeTypes[i].mime_type) + "/*")
+    if (mime_type == std::string(kWildCardMimeTypes[i].mime_type) + "/*") {
       return std::string(kWildCardMimeTypes[i].label);
+    }
   }
 
   return std::string();
@@ -56,10 +58,11 @@
                 std::vector<GtkFileFilter*>* filters) {
   bool has_filter = false;
 
-  for (size_t i = 0; i < accept_filters.size(); ++i) {
-    const std::string& filter = accept_filters[i];
-    if (filter.empty())
+  for (size_t j = 0; j < accept_filters.size(); ++j) {
+    const std::string& filter = accept_filters[j];
+    if (filter.empty()) {
       continue;
+    }
 
     std::vector<std::string> extensions;
     std::string description;
@@ -75,8 +78,9 @@
       for (size_t i = 0; i <= size; ++i) {
         if (i == size || exts[i] == ';') {
           std::string ext(exts, last, i - last);
-          if (!ext.empty() && ext[0] == '.')
+          if (!ext.empty() && ext[0] == '.') {
             extensions.push_back(ext);
+          }
           last = i + 1;
         }
       }
@@ -89,33 +93,38 @@
 
       std::vector<CefString> ext;
       CefGetExtensionsForMimeType(filter, ext);
-      for (size_t x = 0; x < ext.size(); ++x)
+      for (size_t x = 0; x < ext.size(); ++x) {
         extensions.push_back("." + ext[x].ToString());
+      }
     }
 
-    if (extensions.empty())
+    if (extensions.empty()) {
       continue;
+    }
 
     GtkFileFilter* gtk_filter = gtk_file_filter_new();
 
     std::string ext_str;
     for (size_t x = 0; x < extensions.size(); ++x) {
       const std::string& pattern = "*" + extensions[x];
-      if (x != 0)
+      if (x != 0) {
         ext_str += ";";
+      }
       ext_str += pattern;
       gtk_file_filter_add_pattern(gtk_filter, pattern.c_str());
     }
 
-    if (description.empty())
+    if (description.empty()) {
       description = ext_str;
-    else
+    } else {
       description += " (" + ext_str + ")";
+    }
 
     gtk_file_filter_set_name(gtk_filter, description.c_str());
     gtk_file_chooser_add_filter(chooser, gtk_filter);
-    if (!has_filter)
+    if (!has_filter) {
       has_filter = true;
+    }
 
     filters->push_back(gtk_filter);
   }
@@ -135,18 +144,16 @@
   scoped_refptr<RootWindow> root_window =
       RootWindow::GetForBrowser(browser->GetIdentifier());
   if (root_window) {
-    GtkWindow* window = GTK_WINDOW(root_window->GetWindowHandle());
-    if (!window)
+    GtkWidget* window = root_window->GetWindowHandle();
+    DCHECK(window);
+    if (!window) {
       LOG(ERROR) << "No GtkWindow for browser";
-    return window;
+    }
+    return GTK_WINDOW(window);
   }
   return nullptr;
 }
 
-void RunCallback(base::Callback<void(GtkWindow*)> callback, GtkWindow* window) {
-  callback.Run(window);
-}
-
 }  // namespace
 
 ClientDialogHandlerGtk::ClientDialogHandlerGtk() : gtk_dialog_(nullptr) {}
@@ -157,7 +164,6 @@
     const CefString& title,
     const CefString& default_file_path,
     const std::vector<CefString>& accept_filters,
-    int selected_accept_filter,
     CefRefPtr<CefFileDialogCallback> callback) {
   CEF_REQUIRE_UI_THREAD();
 
@@ -167,12 +173,11 @@
   params.title = title;
   params.default_file_path = default_file_path;
   params.accept_filters = accept_filters;
-  params.selected_accept_filter = selected_accept_filter;
   params.callback = callback;
 
   GetWindowAndContinue(
-      browser,
-      base::Bind(&ClientDialogHandlerGtk::OnFileDialogContinue, this, params));
+      browser, base::BindOnce(&ClientDialogHandlerGtk::OnFileDialogContinue,
+                              this, params));
   return true;
 }
 
@@ -194,8 +199,8 @@
   params.callback = callback;
 
   GetWindowAndContinue(
-      browser,
-      base::Bind(&ClientDialogHandlerGtk::OnJSDialogContinue, this, params));
+      browser, base::BindOnce(&ClientDialogHandlerGtk::OnJSDialogContinue, this,
+                              params));
   return true;
 }
 
@@ -217,17 +222,19 @@
 void ClientDialogHandlerGtk::OnResetDialogState(CefRefPtr<CefBrowser> browser) {
   CEF_REQUIRE_UI_THREAD();
 
-  if (!gtk_dialog_)
+  if (!gtk_dialog_) {
     return;
+  }
 
   gtk_widget_destroy(gtk_dialog_);
   gtk_dialog_ = nullptr;
   js_dialog_callback_ = nullptr;
 }
 
-void ClientDialogHandlerGtk::OnFileDialogContinue(OnFileDialogParams params,
-                                                  GtkWindow* window) {
-  CEF_REQUIRE_UI_THREAD();
+void ClientDialogHandlerGtk::OnFileDialogContinue(
+    const OnFileDialogParams& params,
+    GtkWindow* window) {
+  REQUIRE_MAIN_THREAD();
 
   ScopedGdkThreadsEnter scoped_gdk_threads;
 
@@ -236,19 +243,16 @@
   GtkFileChooserAction action;
   const gchar* accept_button;
 
-  // Remove any modifier flags.
-  FileDialogMode mode_type =
-      static_cast<FileDialogMode>(params.mode & FILE_DIALOG_TYPE_MASK);
-
-  if (mode_type == FILE_DIALOG_OPEN || mode_type == FILE_DIALOG_OPEN_MULTIPLE) {
+  if (params.mode == FILE_DIALOG_OPEN ||
+      params.mode == FILE_DIALOG_OPEN_MULTIPLE) {
     action = GTK_FILE_CHOOSER_ACTION_OPEN;
-    accept_button = GTK_STOCK_OPEN;
-  } else if (mode_type == FILE_DIALOG_OPEN_FOLDER) {
+    accept_button = "_Open";
+  } else if (params.mode == FILE_DIALOG_OPEN_FOLDER) {
     action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
-    accept_button = GTK_STOCK_OPEN;
-  } else if (mode_type == FILE_DIALOG_SAVE) {
+    accept_button = "_Open";
+  } else if (params.mode == FILE_DIALOG_SAVE) {
     action = GTK_FILE_CHOOSER_ACTION_SAVE;
-    accept_button = GTK_STOCK_SAVE;
+    accept_button = "_Save";
   } else {
     NOTREACHED();
     params.callback->Cancel();
@@ -259,7 +263,7 @@
   if (!params.title.empty()) {
     title_str = params.title;
   } else {
-    switch (mode_type) {
+    switch (params.mode) {
       case FILE_DIALOG_OPEN:
         title_str = "Open File";
         break;
@@ -278,22 +282,14 @@
   }
 
   GtkWidget* dialog = gtk_file_chooser_dialog_new(
-      title_str.c_str(), GTK_WINDOW(window), action, GTK_STOCK_CANCEL,
-      GTK_RESPONSE_CANCEL, accept_button, GTK_RESPONSE_ACCEPT, NULL);
+      title_str.c_str(), GTK_WINDOW(window), action, "_Cancel",
+      GTK_RESPONSE_CANCEL, accept_button, GTK_RESPONSE_ACCEPT, nullptr);
 
-  if (mode_type == FILE_DIALOG_OPEN_MULTIPLE)
+  if (params.mode == FILE_DIALOG_OPEN_MULTIPLE) {
     gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
-
-  if (mode_type == FILE_DIALOG_SAVE) {
-    gtk_file_chooser_set_do_overwrite_confirmation(
-        GTK_FILE_CHOOSER(dialog),
-        !!(params.mode & FILE_DIALOG_OVERWRITEPROMPT_FLAG));
   }
 
-  gtk_file_chooser_set_show_hidden(
-      GTK_FILE_CHOOSER(dialog), !(params.mode & FILE_DIALOG_HIDEREADONLY_FLAG));
-
-  if (!params.default_file_path.empty() && mode_type == FILE_DIALOG_SAVE) {
+  if (!params.default_file_path.empty() && params.mode == FILE_DIALOG_SAVE) {
     const std::string& file_path = params.default_file_path;
     bool exists = false;
 
@@ -314,20 +310,17 @@
 
   std::vector<GtkFileFilter*> filters;
   AddFilters(GTK_FILE_CHOOSER(dialog), params.accept_filters, true, &filters);
-  if (params.selected_accept_filter < static_cast<int>(filters.size())) {
-    gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog),
-                                filters[params.selected_accept_filter]);
-  }
 
   bool success = false;
 
   if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
-    if (mode_type == FILE_DIALOG_OPEN || mode_type == FILE_DIALOG_OPEN_FOLDER ||
-        mode_type == FILE_DIALOG_SAVE) {
+    if (params.mode == FILE_DIALOG_OPEN ||
+        params.mode == FILE_DIALOG_OPEN_FOLDER ||
+        params.mode == FILE_DIALOG_SAVE) {
       char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
       files.push_back(std::string(filename));
       success = true;
-    } else if (mode_type == FILE_DIALOG_OPEN_MULTIPLE) {
+    } else if (params.mode == FILE_DIALOG_OPEN_MULTIPLE) {
       GSList* filenames =
           gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
       if (filenames) {
@@ -343,31 +336,18 @@
     }
   }
 
-  int filter_index = params.selected_accept_filter;
-  if (success) {
-    GtkFileFilter* selected_filter =
-        gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog));
-    if (selected_filter != nullptr) {
-      for (size_t x = 0; x < filters.size(); ++x) {
-        if (filters[x] == selected_filter) {
-          filter_index = x;
-          break;
-        }
-      }
-    }
-  }
-
   gtk_widget_destroy(dialog);
 
-  if (success)
-    params.callback->Continue(filter_index, files);
-  else
+  if (success) {
+    params.callback->Continue(files);
+  } else {
     params.callback->Cancel();
+  }
 }
 
-void ClientDialogHandlerGtk::OnJSDialogContinue(OnJSDialogParams params,
+void ClientDialogHandlerGtk::OnJSDialogContinue(const OnJSDialogParams& params,
                                                 GtkWindow* window) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
 
   ScopedGdkThreadsEnter scoped_gdk_threads;
 
@@ -406,15 +386,16 @@
                                        gtk_message_type, buttons, "%s",
                                        params.message_text.ToString().c_str());
   g_signal_connect(gtk_dialog_, "delete-event",
-                   G_CALLBACK(gtk_widget_hide_on_delete), NULL);
+                   G_CALLBACK(gtk_widget_hide_on_delete), nullptr);
 
   gtk_window_set_title(GTK_WINDOW(gtk_dialog_), title.c_str());
 
-  GtkWidget* ok_button = gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_),
-                                               GTK_STOCK_OK, GTK_RESPONSE_OK);
+  GtkWidget* ok_button =
+      gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_), "_OK", GTK_RESPONSE_OK);
 
-  if (params.dialog_type != JSDIALOGTYPE_PROMPT)
+  if (params.dialog_type != JSDIALOGTYPE_PROMPT) {
     gtk_widget_grab_focus(ok_button);
+  }
 
   if (params.dialog_type == JSDIALOGTYPE_PROMPT) {
     GtkWidget* content_area =
@@ -434,16 +415,17 @@
 
 void ClientDialogHandlerGtk::GetWindowAndContinue(
     CefRefPtr<CefBrowser> browser,
-    base::Callback<void(GtkWindow*)> callback) {
+    base::OnceCallback<void(GtkWindow*)> callback) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
-    MAIN_POST_CLOSURE(base::Bind(&ClientDialogHandlerGtk::GetWindowAndContinue,
-                                 this, browser, callback));
+    MAIN_POST_CLOSURE(
+        base::BindOnce(&ClientDialogHandlerGtk::GetWindowAndContinue, this,
+                       browser, std::move(callback)));
     return;
   }
 
   GtkWindow* window = GetWindow(browser);
   if (window) {
-    CefPostTask(TID_UI, base::Bind(RunCallback, callback, window));
+    std::move(callback).Run(window);
   }
 }
 
@@ -451,7 +433,7 @@
 void ClientDialogHandlerGtk::OnDialogResponse(GtkDialog* dialog,
                                               gint response_id,
                                               ClientDialogHandlerGtk* handler) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
 
   DCHECK_EQ(dialog, GTK_DIALOG(handler->gtk_dialog_));
   switch (response_id) {
@@ -466,7 +448,9 @@
       NOTREACHED();
   }
 
-  handler->OnResetDialogState(nullptr);
+  CefPostTask(TID_UI,
+              base::BindOnce(&ClientDialogHandlerGtk::OnResetDialogState,
+                             handler, nullptr));
 }
 
 }  // namespace client
diff --git a/src/tests/cefclient/browser/dialog_handler_gtk.h b/src/tests/cefclient/browser/dialog_handler_gtk.h
index c29d9f0..1ad9671 100644
--- a/src/tests/cefclient/browser/dialog_handler_gtk.h
+++ b/src/tests/cefclient/browser/dialog_handler_gtk.h
@@ -25,8 +25,7 @@
                     const CefString& title,
                     const CefString& default_file_path,
                     const std::vector<CefString>& accept_filters,
-                    int selected_accept_filter,
-                    CefRefPtr<CefFileDialogCallback> callback) OVERRIDE;
+                    CefRefPtr<CefFileDialogCallback> callback) override;
 
   // CefJSDialogHandler methods.
   bool OnJSDialog(CefRefPtr<CefBrowser> browser,
@@ -35,12 +34,12 @@
                   const CefString& message_text,
                   const CefString& default_prompt_text,
                   CefRefPtr<CefJSDialogCallback> callback,
-                  bool& suppress_message) OVERRIDE;
+                  bool& suppress_message) override;
   bool OnBeforeUnloadDialog(CefRefPtr<CefBrowser> browser,
                             const CefString& message_text,
                             bool is_reload,
-                            CefRefPtr<CefJSDialogCallback> callback) OVERRIDE;
-  void OnResetDialogState(CefRefPtr<CefBrowser> browser) OVERRIDE;
+                            CefRefPtr<CefJSDialogCallback> callback) override;
+  void OnResetDialogState(CefRefPtr<CefBrowser> browser) override;
 
  private:
   struct OnFileDialogParams {
@@ -49,10 +48,10 @@
     CefString title;
     CefString default_file_path;
     std::vector<CefString> accept_filters;
-    int selected_accept_filter;
     CefRefPtr<CefFileDialogCallback> callback;
   };
-  void OnFileDialogContinue(OnFileDialogParams params, GtkWindow* window);
+  void OnFileDialogContinue(const OnFileDialogParams& params,
+                            GtkWindow* window);
 
   struct OnJSDialogParams {
     CefRefPtr<CefBrowser> browser;
@@ -62,10 +61,10 @@
     CefString default_prompt_text;
     CefRefPtr<CefJSDialogCallback> callback;
   };
-  void OnJSDialogContinue(OnJSDialogParams params, GtkWindow* window);
+  void OnJSDialogContinue(const OnJSDialogParams& params, GtkWindow* window);
 
   void GetWindowAndContinue(CefRefPtr<CefBrowser> browser,
-                            base::Callback<void(GtkWindow*)> callback);
+                            base::OnceCallback<void(GtkWindow*)> callback);
 
   static void OnDialogResponse(GtkDialog* dialog,
                                gint response_id,
diff --git a/src/tests/cefclient/browser/dialog_test.cc b/src/tests/cefclient/browser/dialog_test.cc
index 030cedc..7fbc814 100644
--- a/src/tests/cefclient/browser/dialog_test.cc
+++ b/src/tests/cefclient/browser/dialog_test.cc
@@ -17,7 +17,8 @@
 namespace {
 
 const char kTestUrlPath[] = "/dialogs";
-const char kFileOpenMessageName[] = "DialogTest.FileOpen";
+const char kFileOpenPngMessageName[] = "DialogTest.FileOpenPng";
+const char kFileOpenImageMessageName[] = "DialogTest.FileOpenImage";
 const char kFileOpenMultipleMessageName[] = "DialogTest.FileOpenMultiple";
 const char kFileOpenFolderMessageName[] = "DialogTest.FileOpenFolder";
 const char kFileSaveMessageName[] = "DialogTest.FileSave";
@@ -25,11 +26,9 @@
 // Store persistent dialog state information.
 class DialogState : public base::RefCountedThreadSafe<DialogState> {
  public:
-  DialogState()
-      : mode_(FILE_DIALOG_OPEN), last_selected_filter_(0), pending_(false) {}
+  DialogState() : mode_(FILE_DIALOG_OPEN), pending_(false) {}
 
   cef_file_dialog_mode_t mode_;
-  int last_selected_filter_;
   CefString last_file_;
   bool pending_;
 
@@ -45,15 +44,11 @@
       : router_callback_(router_callback), dialog_state_(dialog_state) {}
 
   virtual void OnFileDialogDismissed(
-      int last_selected_filter,
-      const std::vector<CefString>& file_paths) OVERRIDE {
+      const std::vector<CefString>& file_paths) override {
     CEF_REQUIRE_UI_THREAD();
     DCHECK(dialog_state_->pending_);
 
     if (!file_paths.empty()) {
-      if (dialog_state_->mode_ != FILE_DIALOG_OPEN_FOLDER)
-        dialog_state_->last_selected_filter_ = last_selected_filter;
-
       dialog_state_->last_file_ = file_paths[0];
       if (dialog_state_->mode_ == FILE_DIALOG_OPEN_FOLDER) {
         std::string last_file = dialog_state_->last_file_;
@@ -69,8 +64,9 @@
     // Send a message back to the render process with the list of file paths.
     std::string response;
     for (int i = 0; i < static_cast<int>(file_paths.size()); ++i) {
-      if (!response.empty())
+      if (!response.empty()) {
         response += "|";  // Use a delimiter disallowed in file paths.
+      }
       response += file_paths[i];
     }
 
@@ -97,19 +93,21 @@
   // Called due to cefQuery execution in dialogs.html.
   virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
                        CefRefPtr<CefFrame> frame,
-                       int64 query_id,
+                       int64_t query_id,
                        const CefString& request,
                        bool persistent,
-                       CefRefPtr<Callback> callback) OVERRIDE {
+                       CefRefPtr<Callback> callback) override {
     CEF_REQUIRE_UI_THREAD();
 
     // Only handle messages from the test URL.
     const std::string& url = frame->GetURL();
-    if (!test_runner::IsTestURL(url, kTestUrlPath))
+    if (!test_runner::IsTestURL(url, kTestUrlPath)) {
       return false;
+    }
 
-    if (!dialog_state_.get())
+    if (!dialog_state_.get()) {
       dialog_state_ = new DialogState;
+    }
 
     // Make sure we're only running one dialog at a time.
     DCHECK(!dialog_state_->pending_);
@@ -118,25 +116,30 @@
     std::string title;
 
     const std::string& message_name = request;
-    if (message_name == kFileOpenMessageName) {
+    if (message_name == kFileOpenPngMessageName) {
       dialog_state_->mode_ = FILE_DIALOG_OPEN;
-      title = "My Open Dialog";
+      title = "My Open PNG Dialog";
+      accept_filters.push_back(".png");
+    } else if (message_name == kFileOpenImageMessageName) {
+      dialog_state_->mode_ = FILE_DIALOG_OPEN;
+      title = "My Open Image Dialog";
+      accept_filters.push_back("image/*");
     } else if (message_name == kFileOpenMultipleMessageName) {
       dialog_state_->mode_ = FILE_DIALOG_OPEN_MULTIPLE;
-      title = "My Open Multiple Dialog";
+      title = "My Open MultiType Dialog";
     } else if (message_name == kFileOpenFolderMessageName) {
       dialog_state_->mode_ = FILE_DIALOG_OPEN_FOLDER;
       title = "My Open Folder Dialog";
     } else if (message_name == kFileSaveMessageName) {
-      dialog_state_->mode_ = static_cast<cef_file_dialog_mode_t>(
-          FILE_DIALOG_SAVE | FILE_DIALOG_OVERWRITEPROMPT_FLAG);
+      dialog_state_->mode_ = FILE_DIALOG_SAVE;
       title = "My Save Dialog";
     } else {
       NOTREACHED();
       return true;
     }
 
-    if (dialog_state_->mode_ != FILE_DIALOG_OPEN_FOLDER) {
+    if (accept_filters.empty() &&
+        dialog_state_->mode_ != FILE_DIALOG_OPEN_FOLDER) {
       // Build filters based on mime time.
       accept_filters.push_back("text/*");
 
@@ -154,7 +157,6 @@
 
     browser->GetHost()->RunFileDialog(
         dialog_state_->mode_, title, dialog_state_->last_file_, accept_filters,
-        dialog_state_->last_selected_filter_,
         new DialogCallback(callback, dialog_state_));
 
     return true;
diff --git a/src/tests/cefclient/browser/drm_test.cc b/src/tests/cefclient/browser/drm_test.cc
deleted file mode 100644
index 75632bd..0000000
--- a/src/tests/cefclient/browser/drm_test.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (c) 2016 The Chromium Embedded Framework 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 "tests/cefclient/browser/drm_test.h"
-
-#include <algorithm>
-#include <string>
-
-#include "include/cef_parser.h"
-#include "include/cef_web_plugin.h"
-#include "tests/cefclient/browser/test_runner.h"
-
-namespace client {
-namespace drm_test {
-
-namespace {
-
-// Application-specific error codes.
-const int kMessageFormatError = 1;
-const int kCdmLoadError = 2;
-
-const char kTestUrlPath[] = "/drm";
-const char kWidevineCdmPathKey[] = "widevine_cdm_path";
-
-// Callback executed once CDM registration is complete.
-class CdmCallback : public CefRegisterCdmCallback {
- public:
-  CdmCallback(CefRefPtr<CefMessageRouterBrowserSide::Callback> callback)
-      : callback_(callback) {}
-
-  void OnCdmRegistrationComplete(cef_cdm_registration_error_t result,
-                                 const CefString& error_message) OVERRIDE {
-    if (result == CEF_CDM_REGISTRATION_ERROR_NONE)
-      callback_->Success("");
-    else
-      callback_->Failure(kCdmLoadError, error_message);
-    callback_ = nullptr;
-  }
-
- private:
-  CefRefPtr<CefMessageRouterBrowserSide::Callback> callback_;
-
-  IMPLEMENT_REFCOUNTING(CdmCallback);
-  DISALLOW_COPY_AND_ASSIGN(CdmCallback);
-};
-
-// Handle messages in the browser process.
-class Handler : public CefMessageRouterBrowserSide::Handler {
- public:
-  Handler() {}
-
-  // Called due to cefQuery execution in drm.html.
-  virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
-                       CefRefPtr<CefFrame> frame,
-                       int64 query_id,
-                       const CefString& request,
-                       bool persistent,
-                       CefRefPtr<Callback> callback) OVERRIDE {
-    // Only handle messages from the test URL.
-    const std::string& url = frame->GetURL();
-    if (!test_runner::IsTestURL(url, kTestUrlPath))
-      return false;
-
-    // Parse |request| as a JSON dictionary.
-    CefRefPtr<CefDictionaryValue> request_dict = ParseJSON(request);
-    if (!request_dict) {
-      callback->Failure(kMessageFormatError, "Incorrect message format");
-      return true;
-    }
-
-    // Verify the "widevine_cdm_path" key.
-    if (!VerifyKey(request_dict, kWidevineCdmPathKey, VTYPE_STRING, callback))
-      return true;
-
-    const std::string& widevine_cdm_path =
-        request_dict->GetString(kWidevineCdmPathKey);
-    if (widevine_cdm_path.empty()) {
-      callback->Failure(kMessageFormatError, "Empty widevine CDM path");
-      return true;
-    }
-
-    // Register the Widvine CDM.
-    CefRegisterWidevineCdm(widevine_cdm_path, new CdmCallback(callback));
-    return true;
-  }
-
- private:
-  // Convert a JSON string to a dictionary value.
-  static CefRefPtr<CefDictionaryValue> ParseJSON(const CefString& string) {
-    CefRefPtr<CefValue> value = CefParseJSON(string, JSON_PARSER_RFC);
-    if (value.get() && value->GetType() == VTYPE_DICTIONARY)
-      return value->GetDictionary();
-    return nullptr;
-  }
-
-  // Verify that |key| exists in |dictionary| and has type |value_type|. Fails
-  // |callback| and returns false on failure.
-  static bool VerifyKey(CefRefPtr<CefDictionaryValue> dictionary,
-                        const char* key,
-                        cef_value_type_t value_type,
-                        CefRefPtr<Callback> callback) {
-    if (!dictionary->HasKey(key) || dictionary->GetType(key) != value_type) {
-      callback->Failure(
-          kMessageFormatError,
-          "Missing or incorrectly formatted message key: " + std::string(key));
-      return false;
-    }
-    return true;
-  }
-};
-
-}  // namespace
-
-void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
-  handlers.insert(new Handler());
-}
-
-}  // namespace drm_test
-}  // namespace client
diff --git a/src/tests/cefclient/browser/drm_test.h b/src/tests/cefclient/browser/drm_test.h
deleted file mode 100644
index e8afa3f..0000000
--- a/src/tests/cefclient/browser/drm_test.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2016 The Chromium Embedded Framework 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 CEF_TESTS_CEFCLIENT_BROWSER_DRM_TEST_H_
-#define CEF_TESTS_CEFCLIENT_BROWSER_DRM_TEST_H_
-#pragma once
-
-#include "tests/cefclient/browser/test_runner.h"
-
-namespace client {
-namespace drm_test {
-
-// Create message handlers. Called from test_runner.cc.
-void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers);
-
-}  // namespace drm_test
-}  // namespace client
-
-#endif  // CEF_TESTS_CEFCLIENT_BROWSER_DRM_TEST_H_
diff --git a/src/tests/cefclient/browser/image_cache.cc b/src/tests/cefclient/browser/image_cache.cc
index c2c4105..2164593 100644
--- a/src/tests/cefclient/browser/image_cache.cc
+++ b/src/tests/cefclient/browser/image_cache.cc
@@ -4,8 +4,11 @@
 
 #include "tests/cefclient/browser/image_cache.h"
 
+#include <algorithm>
+
 #include "tests/shared/browser/file_util.h"
 #include "tests/shared/browser/resource_util.h"
+#include "tests/shared/common/string_util.h"
 
 namespace client {
 
@@ -34,8 +37,9 @@
     : id_(id), reps_(reps), internal_(internal), force_reload_(force_reload) {
 #ifndef NDEBUG
   DCHECK(!id_.empty());
-  if (id_ != kEmptyId)
+  if (id_ != kEmptyId) {
     DCHECK(!reps_.empty());
+  }
 #endif
 }
 
@@ -89,13 +93,13 @@
 };
 
 void ImageCache::LoadImages(const ImageInfoSet& image_info,
-                            const LoadImagesCallback& callback) {
+                            LoadImagesCallback callback) {
   DCHECK(!image_info.empty());
   DCHECK(!callback.is_null());
 
   if (!CefCurrentlyOn(TID_UI)) {
-    CefPostTask(TID_UI, base::Bind(&ImageCache::LoadImages, this, image_info,
-                                   callback));
+    CefPostTask(TID_UI, base::BindOnce(&ImageCache::LoadImages, this,
+                                       image_info, std::move(callback)));
     return;
   }
 
@@ -126,15 +130,17 @@
 
     // Load the image.
     images.push_back(nullptr);
-    if (!missing_images)
+    if (!missing_images) {
       missing_images = true;
+    }
   }
 
   if (missing_images) {
-    CefPostTask(TID_FILE, base::Bind(&ImageCache::LoadMissing, this, image_info,
-                                     images, callback));
+    CefPostTask(TID_FILE_USER_BLOCKING,
+                base::BindOnce(&ImageCache::LoadMissing, this, image_info,
+                               images, std::move(callback)));
   } else {
-    callback.Run(images);
+    std::move(callback).Run(images);
   }
 }
 
@@ -143,8 +149,9 @@
   DCHECK(!image_id.empty());
 
   ImageMap::const_iterator it = image_map_.find(image_id);
-  if (it != image_map_.end())
+  if (it != image_map_.end()) {
     return it->second;
+  }
 
   return nullptr;
 }
@@ -152,22 +159,25 @@
 // static
 ImageCache::ImageType ImageCache::GetImageType(const std::string& path) {
   std::string ext = file_util::GetFileExtension(path);
-  if (ext.empty())
+  if (ext.empty()) {
     return TYPE_NONE;
+  }
 
-  std::transform(ext.begin(), ext.end(), ext.begin(), tolower);
-  if (ext == "png")
+  ext = AsciiStrToLower(ext);
+  if (ext == "png") {
     return TYPE_PNG;
-  if (ext == "jpg" || ext == "jpeg")
+  }
+  if (ext == "jpg" || ext == "jpeg") {
     return TYPE_JPEG;
+  }
 
   return TYPE_NONE;
 }
 
 void ImageCache::LoadMissing(const ImageInfoSet& image_info,
                              const ImageSet& images,
-                             const LoadImagesCallback& callback) {
-  CEF_REQUIRE_FILE_THREAD();
+                             LoadImagesCallback callback) {
+  CEF_REQUIRE_FILE_USER_BLOCKING_THREAD();
 
   DCHECK_EQ(image_info.size(), images.size());
 
@@ -187,14 +197,14 @@
     contents.push_back(content);
   }
 
-  CefPostTask(TID_UI, base::Bind(&ImageCache::UpdateCache, this, image_info,
-                                 contents, callback));
+  CefPostTask(TID_UI, base::BindOnce(&ImageCache::UpdateCache, this, image_info,
+                                     contents, std::move(callback)));
 }
 
 // static
 bool ImageCache::LoadImageContents(const ImageInfo& info,
                                    ImageContent* content) {
-  CEF_REQUIRE_FILE_THREAD();
+  CEF_REQUIRE_FILE_USER_BLOCKING_THREAD();
 
   ImageRepSet::const_iterator it = info.reps_.begin();
   for (; it != info.reps_.end(); ++it) {
@@ -219,15 +229,17 @@
                                    bool internal,
                                    ImageType* type,
                                    std::string* contents) {
-  CEF_REQUIRE_FILE_THREAD();
+  CEF_REQUIRE_FILE_USER_BLOCKING_THREAD();
 
   *type = GetImageType(path);
-  if (*type == TYPE_NONE)
+  if (*type == TYPE_NONE) {
     return false;
+  }
 
   if (internal) {
-    if (!LoadBinaryResource(path.c_str(), *contents))
+    if (!LoadBinaryResource(path.c_str(), *contents)) {
       return false;
+    }
   } else if (!file_util::ReadFileToString(path, contents)) {
     return false;
   }
@@ -237,7 +249,7 @@
 
 void ImageCache::UpdateCache(const ImageInfoSet& image_info,
                              const ImageContentSet& contents,
-                             const LoadImagesCallback& callback) {
+                             LoadImagesCallback callback) {
   CEF_REQUIRE_UI_THREAD();
 
   DCHECK_EQ(image_info.size(), contents.size());
@@ -261,7 +273,7 @@
     }
   }
 
-  callback.Run(images);
+  std::move(callback).Run(images);
 }
 
 // static
@@ -272,8 +284,9 @@
   // Shouldn't be creating an image if one already exists.
   DCHECK(!content.image_);
 
-  if (content.contents_.empty())
+  if (content.contents_.empty()) {
     return nullptr;
+  }
 
   CefRefPtr<CefImage> image = CefImage::CreateImage();
 
diff --git a/src/tests/cefclient/browser/image_cache.h b/src/tests/cefclient/browser/image_cache.h
index fa43c8d..4214672 100644
--- a/src/tests/cefclient/browser/image_cache.h
+++ b/src/tests/cefclient/browser/image_cache.h
@@ -9,7 +9,7 @@
 #include <map>
 #include <vector>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/base/cef_ref_counted.h"
 #include "include/cef_image.h"
 #include "include/wrapper/cef_closure_task.h"
@@ -33,7 +33,7 @@
     // Image scale factor (usually 1.0f or 2.0f).
     float scale_factor_;
   };
-  typedef std::vector<ImageRep> ImageRepSet;
+  using ImageRepSet = std::vector<ImageRep>;
 
   // Unique image that may have multiple representations.
   struct ImageInfo {
@@ -67,16 +67,16 @@
     // True to force reload.
     bool force_reload_;
   };
-  typedef std::vector<ImageInfo> ImageInfoSet;
+  using ImageInfoSet = std::vector<ImageInfo>;
 
-  typedef std::vector<CefRefPtr<CefImage>> ImageSet;
+  using ImageSet = std::vector<CefRefPtr<CefImage>>;
 
-  typedef base::Callback<void(const ImageSet& /*images*/)> LoadImagesCallback;
+  using LoadImagesCallback =
+      base::OnceCallback<void(const ImageSet& /*images*/)>;
 
   // Loads the images represented by |image_info|. Executes |callback|
   // either synchronously or asychronously on the UI thread after completion.
-  void LoadImages(const ImageInfoSet& image_info,
-                  const LoadImagesCallback& callback);
+  void LoadImages(const ImageInfoSet& image_info, LoadImagesCallback callback);
 
   // Returns an image that has already been cached. Must be called on the
   // UI thread.
@@ -98,12 +98,12 @@
   static ImageType GetImageType(const std::string& path);
 
   struct ImageContent;
-  typedef std::vector<ImageContent> ImageContentSet;
+  using ImageContentSet = std::vector<ImageContent>;
 
   // Load missing image contents on the FILE thread.
   void LoadMissing(const ImageInfoSet& image_info,
                    const ImageSet& images,
-                   const LoadImagesCallback& callback);
+                   LoadImagesCallback callback);
   static bool LoadImageContents(const ImageInfo& info, ImageContent* content);
   static bool LoadImageContents(const std::string& path,
                                 bool internal,
@@ -113,12 +113,12 @@
   // Create missing CefImage representations on the UI thread.
   void UpdateCache(const ImageInfoSet& image_info,
                    const ImageContentSet& contents,
-                   const LoadImagesCallback& callback);
+                   LoadImagesCallback callback);
   static CefRefPtr<CefImage> CreateImage(const std::string& image_id,
                                          const ImageContent& content);
 
   // Map image ID to image representation. Only accessed on the UI thread.
-  typedef std::map<std::string, CefRefPtr<CefImage>> ImageMap;
+  using ImageMap = std::map<std::string, CefRefPtr<CefImage>>;
   ImageMap image_map_;
 };
 
diff --git a/src/tests/cefclient/browser/main_context.h b/src/tests/cefclient/browser/main_context.h
index 780bf1e..c1bfaca 100644
--- a/src/tests/cefclient/browser/main_context.h
+++ b/src/tests/cefclient/browser/main_context.h
@@ -8,6 +8,7 @@
 
 #include <string>
 
+#include "include/base/cef_macros.h"
 #include "include/base/cef_ref_counted.h"
 #include "include/internal/cef_types_wrappers.h"
 #include "tests/cefclient/browser/osr_renderer_settings.h"
@@ -38,6 +39,13 @@
   // Returns the background color.
   virtual cef_color_t GetBackgroundColor() = 0;
 
+  // Returns true if the Chrome runtime will be used.
+  virtual bool UseChromeRuntime() = 0;
+
+  // Returns true if a native parent window is being used with the Chrome
+  // runtime.
+  virtual bool UseChromeRuntimeNative() = 0;
+
   // Returns true if the Views framework will be used.
   virtual bool UseViews() = 0;
 
@@ -47,6 +55,9 @@
   // Returns true if touch events are enabled.
   virtual bool TouchEventsEnabled() = 0;
 
+  // Returns true if the default popup implementation should be used.
+  virtual bool UseDefaultPopup() = 0;
+
   // Populate |settings| based on command-line arguments.
   virtual void PopulateSettings(CefSettings* settings) = 0;
   virtual void PopulateBrowserSettings(CefBrowserSettings* settings) = 0;
diff --git a/src/tests/cefclient/browser/main_context_impl.cc b/src/tests/cefclient/browser/main_context_impl.cc
index ef293bf..1e85ed9 100644
--- a/src/tests/cefclient/browser/main_context_impl.cc
+++ b/src/tests/cefclient/browser/main_context_impl.cc
@@ -4,33 +4,35 @@
 
 #include "tests/cefclient/browser/main_context_impl.h"
 
+#include <algorithm>
+
 #include "include/cef_parser.h"
-#include "include/cef_web_plugin.h"
+#include "tests/cefclient/browser/test_runner.h"
+#include "tests/shared/browser/client_app_browser.h"
 #include "tests/shared/common/client_switches.h"
+#include "tests/shared/common/string_util.h"
 
 namespace client {
 
 namespace {
 
 // The default URL to load in a browser window.
-const char kDefaultUrl[] = "http://www.google.com";
+const char kDefaultUrl[] = "https://www.google.com";
 
 // Returns the ARGB value for |color|.
 cef_color_t ParseColor(const std::string& color) {
-  std::string colorToLower;
-  colorToLower.resize(color.size());
-  std::transform(color.begin(), color.end(), colorToLower.begin(), ::tolower);
-
-  if (colorToLower == "black")
+  const std::string& colorToLower = AsciiStrToLower(color);
+  if (colorToLower == "black") {
     return CefColorSetARGB(255, 0, 0, 0);
-  else if (colorToLower == "blue")
+  } else if (colorToLower == "blue") {
     return CefColorSetARGB(255, 0, 0, 255);
-  else if (colorToLower == "green")
+  } else if (colorToLower == "green") {
     return CefColorSetARGB(255, 0, 255, 0);
-  else if (colorToLower == "red")
+  } else if (colorToLower == "red") {
     return CefColorSetARGB(255, 255, 0, 0);
-  else if (colorToLower == "white")
+  } else if (colorToLower == "white") {
     return CefColorSetARGB(255, 255, 255, 255);
+  }
 
   // Use the default color.
   return 0;
@@ -41,20 +43,16 @@
 MainContextImpl::MainContextImpl(CefRefPtr<CefCommandLine> command_line,
                                  bool terminate_when_all_windows_closed)
     : command_line_(command_line),
-      terminate_when_all_windows_closed_(terminate_when_all_windows_closed),
-      initialized_(false),
-      shutdown_(false),
-      background_color_(0),
-      browser_background_color_(0),
-      windowless_frame_rate_(0),
-      use_views_(false) {
+      terminate_when_all_windows_closed_(terminate_when_all_windows_closed) {
   DCHECK(command_line_.get());
 
   // Set the main URL.
-  if (command_line_->HasSwitch(switches::kUrl))
+  if (command_line_->HasSwitch(switches::kUrl)) {
     main_url_ = command_line_->GetSwitchValue(switches::kUrl);
-  if (main_url_.empty())
+  }
+  if (main_url_.empty()) {
     main_url_ = kDefaultUrl;
+  }
 
   // Whether windowless (off-screen) rendering will be used.
   use_windowless_rendering_ =
@@ -93,7 +91,16 @@
 #endif
   }
 
-#if defined(OS_WIN) || defined(OS_LINUX)
+  // Enable experimental Chrome runtime. See issue #2969 for details.
+  use_chrome_runtime_ =
+      command_line_->HasSwitch(switches::kEnableChromeRuntime);
+
+  if (use_windowless_rendering_ && use_chrome_runtime_) {
+    LOG(ERROR)
+        << "Windowless rendering is not supported with the Chrome runtime.";
+    use_chrome_runtime_ = false;
+  }
+
   // Whether the Views framework will be used.
   use_views_ = command_line_->HasSwitch(switches::kUseViews);
 
@@ -103,17 +110,36 @@
     use_views_ = false;
   }
 
+#if defined(OS_WIN) || defined(OS_LINUX)
+  use_chrome_runtime_native_ =
+      use_chrome_runtime_ && command_line->HasSwitch(switches::kUseNative);
+  if (use_chrome_runtime_ && !use_views_ && !use_chrome_runtime_native_) {
+    LOG(WARNING) << "Chrome runtime defaults to the Views framework.";
+    use_views_ = true;
+  }
+#else   // !(defined(OS_WIN) || defined(OS_LINUX))
+  if (use_chrome_runtime_ && !use_views_) {
+    // TODO(chrome): Add support for this runtime configuration (e.g. a fully
+    // styled Chrome window with cefclient menu customizations). In the mean
+    // time this can be demo'd with "cefsimple --enable-chrome-runtime".
+    LOG(WARNING) << "Chrome runtime requires the Views framework.";
+    use_views_ = true;
+  }
+#endif  // !(defined(OS_WIN) || defined(OS_LINUX))
+
   if (use_views_ && command_line->HasSwitch(switches::kHideFrame) &&
       !command_line_->HasSwitch(switches::kUrl)) {
     // Use the draggable regions test as the default URL for frameless windows.
-    main_url_ = "http://tests/draggable";
+    main_url_ = test_runner::GetTestURL("draggable");
   }
-#endif  // defined(OS_WIN) || defined(OS_LINUX)
 
   if (command_line_->HasSwitch(switches::kBackgroundColor)) {
     // Parse the background color value.
     background_color_ =
         ParseColor(command_line_->GetSwitchValue(switches::kBackgroundColor));
+  } else if (command_line_->HasSwitch("force-dark-mode")) {
+    // Use black background color by default with dark mode.
+    background_color_ = ParseColor("black");
   }
 
   if (background_color_ == 0 && !use_views_) {
@@ -125,16 +151,6 @@
   if (!use_transparent_painting) {
     browser_background_color_ = background_color_;
   }
-
-  const std::string& cdm_path =
-      command_line_->GetSwitchValue(switches::kWidevineCdmPath);
-  if (!cdm_path.empty()) {
-    // Register the Widevine CDM at the specified path. See comments in
-    // cef_web_plugin.h for details. It's safe to call this method before
-    // CefInitialize(), and calling it before CefInitialize() is required on
-    // Linux.
-    CefRegisterWidevineCdm(cdm_path, nullptr);
-  }
 }
 
 MainContextImpl::~MainContextImpl() {
@@ -155,6 +171,14 @@
   return background_color_;
 }
 
+bool MainContextImpl::UseChromeRuntime() {
+  return use_chrome_runtime_;
+}
+
+bool MainContextImpl::UseChromeRuntimeNative() {
+  return use_chrome_runtime_native_;
+}
+
 bool MainContextImpl::UseViews() {
   return use_views_;
 }
@@ -167,32 +191,65 @@
   return command_line_->GetSwitchValue("touch-events") == "enabled";
 }
 
-void MainContextImpl::PopulateSettings(CefSettings* settings) {
-#if defined(OS_WIN) || defined(OS_LINUX)
-  settings->multi_threaded_message_loop =
-      command_line_->HasSwitch(switches::kMultiThreadedMessageLoop);
-#endif
+bool MainContextImpl::UseDefaultPopup() {
+  return !use_windowless_rendering_ &&
+         command_line_->HasSwitch(switches::kUseDefaultPopup);
+}
 
-  if (!settings->multi_threaded_message_loop) {
-    settings->external_message_pump =
-        command_line_->HasSwitch(switches::kExternalMessagePump);
+void MainContextImpl::PopulateSettings(CefSettings* settings) {
+  client::ClientAppBrowser::PopulateSettings(command_line_, *settings);
+
+  if (use_chrome_runtime_) {
+    settings->chrome_runtime = true;
   }
 
   CefString(&settings->cache_path) =
       command_line_->GetSwitchValue(switches::kCachePath);
 
-  if (use_windowless_rendering_)
+  if (use_windowless_rendering_) {
     settings->windowless_rendering_enabled = true;
+  }
 
-  if (browser_background_color_ != 0)
+  if (browser_background_color_ != 0) {
     settings->background_color = browser_background_color_;
+  }
+
+  if (command_line_->HasSwitch("lang")) {
+    // Use the same locale for the Accept-Language HTTP request header.
+    CefString(&settings->accept_language_list) =
+        command_line_->GetSwitchValue("lang");
+  }
+
+  if (command_line_->HasSwitch("enable-chrome-policy")) {
+    // Enable Chrome policy management via Platform and OS-user policies.
+    // Use the same configuration ID as Google Chrome for testing purposes.
+    // If Google Chrome is managed on this machine we'll show the same
+    // configured policies in chrome://policy/.
+    CefString(&settings->chrome_policy_id) =
+#if defined(OS_WIN)
+        "SOFTWARE\\Policies\\Google\\Chrome";
+#elif defined(OS_MAC)
+        "com.google.Chrome";
+#elif defined(OS_LINUX)
+        "/etc/opt/chrome/policies";
+#else
+        "";
+#endif
+  }
 }
 
 void MainContextImpl::PopulateBrowserSettings(CefBrowserSettings* settings) {
   settings->windowless_frame_rate = windowless_frame_rate_;
 
-  if (browser_background_color_ != 0)
+  if (browser_background_color_ != 0) {
     settings->background_color = browser_background_color_;
+  }
+
+  if (use_chrome_runtime_ &&
+      command_line_->HasSwitch(switches::kHideChromeBubbles)) {
+    settings->chrome_status_bubble = STATE_DISABLED;
+    settings->chrome_zoom_bubble = STATE_DISABLED;
+  }
 }
 
 void MainContextImpl::PopulateOsrSettings(OsrRendererSettings* settings) {
@@ -205,8 +262,9 @@
   settings->external_begin_frame_enabled = external_begin_frame_enabled_;
   settings->begin_frame_rate = windowless_frame_rate_;
 
-  if (browser_background_color_ != 0)
+  if (browser_background_color_ != 0) {
     settings->background_color = browser_background_color_;
+  }
 }
 
 RootWindowManager* MainContextImpl::GetRootWindowManager() {
@@ -222,8 +280,9 @@
   DCHECK(!initialized_);
   DCHECK(!shutdown_);
 
-  if (!CefInitialize(args, settings, application, windows_sandbox_info))
+  if (!CefInitialize(args, settings, application, windows_sandbox_info)) {
     return false;
+  }
 
   // Need to create the RootWindowManager after calling CefInitialize because
   // TempWindowX11 uses cef_get_xdisplay().
diff --git a/src/tests/cefclient/browser/main_context_impl.h b/src/tests/cefclient/browser/main_context_impl.h
index 4c267f3..876804e 100644
--- a/src/tests/cefclient/browser/main_context_impl.h
+++ b/src/tests/cefclient/browser/main_context_impl.h
@@ -6,7 +6,8 @@
 #define CEF_TESTS_CEFCLIENT_BROWSER_MAIN_CONTEXT_IMPL_H_
 #pragma once
 
-#include "include/base/cef_scoped_ptr.h"
+#include <memory>
+
 #include "include/base/cef_thread_checker.h"
 #include "include/cef_app.h"
 #include "include/cef_command_line.h"
@@ -22,18 +23,21 @@
                   bool terminate_when_all_windows_closed);
 
   // MainContext members.
-  std::string GetConsoleLogPath() OVERRIDE;
-  std::string GetDownloadPath(const std::string& file_name) OVERRIDE;
-  std::string GetAppWorkingDirectory() OVERRIDE;
-  std::string GetMainURL() OVERRIDE;
-  cef_color_t GetBackgroundColor() OVERRIDE;
-  bool UseViews() OVERRIDE;
-  bool UseWindowlessRendering() OVERRIDE;
-  bool TouchEventsEnabled() OVERRIDE;
-  void PopulateSettings(CefSettings* settings) OVERRIDE;
-  void PopulateBrowserSettings(CefBrowserSettings* settings) OVERRIDE;
-  void PopulateOsrSettings(OsrRendererSettings* settings) OVERRIDE;
-  RootWindowManager* GetRootWindowManager() OVERRIDE;
+  std::string GetConsoleLogPath() override;
+  std::string GetDownloadPath(const std::string& file_name) override;
+  std::string GetAppWorkingDirectory() override;
+  std::string GetMainURL() override;
+  cef_color_t GetBackgroundColor() override;
+  bool UseChromeRuntime() override;
+  bool UseChromeRuntimeNative() override;
+  bool UseViews() override;
+  bool UseWindowlessRendering() override;
+  bool TouchEventsEnabled() override;
+  bool UseDefaultPopup() override;
+  void PopulateSettings(CefSettings* settings) override;
+  void PopulateBrowserSettings(CefBrowserSettings* settings) override;
+  void PopulateOsrSettings(OsrRendererSettings* settings) override;
+  RootWindowManager* GetRootWindowManager() override;
 
   // Initialize CEF and associated main context state. This method must be
   // called on the same thread that created this object.
@@ -47,8 +51,8 @@
   void Shutdown();
 
  private:
-  // Allow deletion via scoped_ptr only.
-  friend struct base::DefaultDeleter<MainContextImpl>;
+  // Allow deletion via std::unique_ptr only.
+  friend std::default_delete<MainContextImpl>;
 
   ~MainContextImpl();
 
@@ -62,18 +66,19 @@
   // Track context state. Accessing these variables from multiple threads is
   // safe because only a single thread will exist at the time that they're set
   // (during context initialization and shutdown).
-  bool initialized_;
-  bool shutdown_;
+  bool initialized_ = false;
+  bool shutdown_ = false;
 
   std::string main_url_;
-  cef_color_t background_color_;
-  cef_color_t browser_background_color_;
+  cef_color_t background_color_ = 0;
+  cef_color_t browser_background_color_ = 0;
   bool use_windowless_rendering_;
-  int windowless_frame_rate_;
+  int windowless_frame_rate_ = 0;
+  bool use_chrome_runtime_;
+  bool use_chrome_runtime_native_ = false;
   bool use_views_;
-  bool touch_events_enabled_;
 
-  scoped_ptr<RootWindowManager> root_window_manager_;
+  std::unique_ptr<RootWindowManager> root_window_manager_;
 
 #if defined(OS_WIN)
   bool shared_texture_enabled_;
diff --git a/src/tests/cefclient/browser/main_context_impl_win.cc b/src/tests/cefclient/browser/main_context_impl_win.cc
index 0bbfbf2..d85c6e9 100644
--- a/src/tests/cefclient/browser/main_context_impl_win.cc
+++ b/src/tests/cefclient/browser/main_context_impl_win.cc
@@ -14,8 +14,8 @@
   std::string path;
 
   // Save the file in the user's "My Documents" folder.
-  if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL,
-                                0, szFolderPath))) {
+  if (SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_PERSONAL | CSIDL_FLAG_CREATE,
+                                nullptr, 0, szFolderPath))) {
     path = CefString(szFolderPath);
     path += "\\" + file_name;
   }
diff --git a/src/tests/cefclient/browser/main_message_loop_multithreaded_gtk.cc b/src/tests/cefclient/browser/main_message_loop_multithreaded_gtk.cc
index d4a0443..736a106 100644
--- a/src/tests/cefclient/browser/main_message_loop_multithreaded_gtk.cc
+++ b/src/tests/cefclient/browser/main_message_loop_multithreaded_gtk.cc
@@ -5,9 +5,9 @@
 #include "tests/cefclient/browser/main_message_loop_multithreaded_gtk.h"
 
 #include <X11/Xlib.h>
-#include <gtk/gtkmain.h>
+#include <gtk/gtk.h>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/base/cef_logging.h"
 #include "include/wrapper/cef_closure_task.h"
 
@@ -78,10 +78,9 @@
 int MainMessageLoopMultithreadedGtk::Run() {
   DCHECK(RunsTasksOnCurrentThread());
 
-  // Chromium uses the default GLib context so we create our own context and
-  // make it the default for this thread.
-  main_context_ = g_main_context_new();
-  g_main_context_push_thread_default(main_context_);
+  // We use the default Glib context and Chromium creates its own context in
+  // MessagePumpGlib (starting in M86).
+  main_context_ = g_main_context_default();
 
   main_loop_ = g_main_loop_new(main_context_, TRUE);
 
@@ -100,15 +99,13 @@
   g_main_loop_unref(main_loop_);
   main_loop_ = nullptr;
 
-  g_main_context_pop_thread_default(main_context_);
-  g_main_context_unref(main_context_);
   main_context_ = nullptr;
 
   return 0;
 }
 
 void MainMessageLoopMultithreadedGtk::Quit() {
-  PostTask(CefCreateClosureTask(base::Bind(
+  PostTask(CefCreateClosureTask(base::BindOnce(
       &MainMessageLoopMultithreadedGtk::DoQuit, base::Unretained(this))));
 }
 
diff --git a/src/tests/cefclient/browser/main_message_loop_multithreaded_gtk.h b/src/tests/cefclient/browser/main_message_loop_multithreaded_gtk.h
index 51087fa..7fbeaf8 100644
--- a/src/tests/cefclient/browser/main_message_loop_multithreaded_gtk.h
+++ b/src/tests/cefclient/browser/main_message_loop_multithreaded_gtk.h
@@ -26,10 +26,10 @@
   ~MainMessageLoopMultithreadedGtk();
 
   // MainMessageLoop methods.
-  int Run() OVERRIDE;
-  void Quit() OVERRIDE;
-  void PostTask(CefRefPtr<CefTask> task) OVERRIDE;
-  bool RunsTasksOnCurrentThread() const OVERRIDE;
+  int Run() override;
+  void Quit() override;
+  void PostTask(CefRefPtr<CefTask> task) override;
+  bool RunsTasksOnCurrentThread() const override;
 
  private:
   static int TriggerRunTasks(void* self);
diff --git a/src/tests/cefclient/browser/main_message_loop_multithreaded_win.cc b/src/tests/cefclient/browser/main_message_loop_multithreaded_win.cc
index 39912ce..156cd3e 100644
--- a/src/tests/cefclient/browser/main_message_loop_multithreaded_win.cc
+++ b/src/tests/cefclient/browser/main_message_loop_multithreaded_win.cc
@@ -4,7 +4,7 @@
 
 #include "tests/cefclient/browser/main_message_loop_multithreaded_win.h"
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/base/cef_logging.h"
 #include "include/cef_app.h"
 #include "tests/cefclient/browser/resource.h"
@@ -22,8 +22,8 @@
 MainMessageLoopMultithreadedWin::MainMessageLoopMultithreadedWin()
     : thread_id_(base::PlatformThread::CurrentId()),
       task_message_id_(RegisterWindowMessage(kTaskMessageName)),
-      dialog_hwnd_(NULL),
-      message_hwnd_(NULL) {}
+      dialog_hwnd_(nullptr),
+      message_hwnd_(nullptr) {}
 
 MainMessageLoopMultithreadedWin::~MainMessageLoopMultithreadedWin() {
   DCHECK(RunsTasksOnCurrentThread());
@@ -34,7 +34,7 @@
 int MainMessageLoopMultithreadedWin::Run() {
   DCHECK(RunsTasksOnCurrentThread());
 
-  HINSTANCE hInstance = ::GetModuleHandle(NULL);
+  HINSTANCE hInstance = ::GetModuleHandle(nullptr);
 
   {
     base::AutoLock lock_scope(lock_);
@@ -59,10 +59,11 @@
   MSG msg;
 
   // Run the application message loop.
-  while (GetMessage(&msg, NULL, 0, 0)) {
+  while (GetMessage(&msg, nullptr, 0, 0)) {
     // Allow processing of dialog messages.
-    if (dialog_hwnd_ && IsDialogMessage(dialog_hwnd_, &msg))
+    if (dialog_hwnd_ && IsDialogMessage(dialog_hwnd_, &msg)) {
       continue;
+    }
 
     if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
       TranslateMessage(&msg);
@@ -75,7 +76,7 @@
 
     // Destroy the message window.
     DestroyWindow(message_hwnd_);
-    message_hwnd_ = NULL;
+    message_hwnd_ = nullptr;
   }
 
   return static_cast<int>(msg.wParam);
@@ -83,7 +84,7 @@
 
 void MainMessageLoopMultithreadedWin::Quit() {
   // Execute PostQuitMessage(0) on the main thread.
-  PostClosure(base::Bind(::PostQuitMessage, 0));
+  PostClosure(base::BindOnce(::PostQuitMessage, 0));
 }
 
 void MainMessageLoopMultithreadedWin::PostTask(CefRefPtr<CefTask> task) {
@@ -142,7 +143,7 @@
     switch (message) {
       case WM_NCDESTROY:
         // Clear the reference to |self|.
-        SetUserDataPtr(hWnd, NULL);
+        SetUserDataPtr(hWnd, nullptr);
         break;
     }
   }
diff --git a/src/tests/cefclient/browser/main_message_loop_multithreaded_win.h b/src/tests/cefclient/browser/main_message_loop_multithreaded_win.h
index 7f04555..6115106 100644
--- a/src/tests/cefclient/browser/main_message_loop_multithreaded_win.h
+++ b/src/tests/cefclient/browser/main_message_loop_multithreaded_win.h
@@ -25,11 +25,11 @@
   ~MainMessageLoopMultithreadedWin();
 
   // MainMessageLoop methods.
-  int Run() OVERRIDE;
-  void Quit() OVERRIDE;
-  void PostTask(CefRefPtr<CefTask> task) OVERRIDE;
-  bool RunsTasksOnCurrentThread() const OVERRIDE;
-  void SetCurrentModelessDialog(HWND hWndDialog) OVERRIDE;
+  int Run() override;
+  void Quit() override;
+  void PostTask(CefRefPtr<CefTask> task) override;
+  bool RunsTasksOnCurrentThread() const override;
+  void SetCurrentModelessDialog(HWND hWndDialog) override;
 
  private:
   // Create the message window.
diff --git a/src/tests/cefclient/browser/media_router_test.cc b/src/tests/cefclient/browser/media_router_test.cc
index 8fdfe1c..36cbe92 100644
--- a/src/tests/cefclient/browser/media_router_test.cc
+++ b/src/tests/cefclient/browser/media_router_test.cc
@@ -65,7 +65,7 @@
   // CefMediaRouteCreateCallback method:
   void OnMediaRouteCreateFinished(RouteCreateResult result,
                                   const CefString& error,
-                                  CefRefPtr<CefMediaRoute> route) OVERRIDE {
+                                  CefRefPtr<CefMediaRoute> route) override {
     CEF_REQUIRE_UI_THREAD();
     if (result == CEF_MRCR_OK) {
       CefRefPtr<CefDictionaryValue> dict = CefDictionaryValue::Create();
@@ -74,7 +74,7 @@
     } else {
       SendFailure(create_callback_, kRequestFailedError + result, error);
     }
-    create_callback_ = NULL;
+    create_callback_ = nullptr;
   }
 
  private:
@@ -98,7 +98,7 @@
         pending_sink_query_id_(-1),
         pending_sink_callbacks_(0U) {}
 
-  ~MediaObserver() OVERRIDE { ClearSinkInfoMap(); }
+  ~MediaObserver() override { ClearSinkInfoMap(); }
 
   bool CreateRoute(const std::string& source_urn,
                    const std::string& sink_id,
@@ -149,18 +149,17 @@
   class DeviceInfoCallback : public CefMediaSinkDeviceInfoCallback {
    public:
     // Callback to be executed when the device info is available.
-    typedef base::Callback<void(const std::string& sink_id,
-                                const CefMediaSinkDeviceInfo& device_info)>
-        CallbackType;
+    using CallbackType =
+        base::OnceCallback<void(const std::string& sink_id,
+                                const CefMediaSinkDeviceInfo& device_info)>;
 
-    DeviceInfoCallback(const std::string& sink_id, const CallbackType& callback)
-        : sink_id_(sink_id), callback_(callback) {}
+    DeviceInfoCallback(const std::string& sink_id, CallbackType callback)
+        : sink_id_(sink_id), callback_(std::move(callback)) {}
 
     void OnMediaSinkDeviceInfo(
-        const CefMediaSinkDeviceInfo& device_info) OVERRIDE {
+        const CefMediaSinkDeviceInfo& device_info) override {
       CEF_REQUIRE_UI_THREAD();
-      callback_.Run(sink_id_, device_info);
-      callback_.Reset();
+      std::move(callback_).Run(sink_id_, device_info);
     }
 
    private:
@@ -172,7 +171,7 @@
   };
 
   // CefMediaObserver methods:
-  void OnSinks(const MediaSinkVector& sinks) OVERRIDE {
+  void OnSinks(const MediaSinkVector& sinks) override {
     CEF_REQUIRE_UI_THREAD();
 
     ClearSinkInfoMap();
@@ -187,9 +186,6 @@
       return;
     }
 
-    DeviceInfoCallback::CallbackType callback = base::Bind(
-        &MediaObserver::OnSinkDeviceInfo, this, pending_sink_query_id_);
-
     MediaSinkVector::const_iterator it = sinks.begin();
     for (size_t idx = 0; it != sinks.end(); ++it, ++idx) {
       CefRefPtr<CefMediaSink> sink = *it;
@@ -200,11 +196,13 @@
 
       // Request the device info asynchronously. Send the response once all
       // callbacks have executed.
-      sink->GetDeviceInfo(new DeviceInfoCallback(sink_id, callback));
+      auto callback = base::BindOnce(&MediaObserver::OnSinkDeviceInfo, this,
+                                     pending_sink_query_id_);
+      sink->GetDeviceInfo(new DeviceInfoCallback(sink_id, std::move(callback)));
     }
   }
 
-  void OnRoutes(const MediaRouteVector& routes) OVERRIDE {
+  void OnRoutes(const MediaRouteVector& routes) override {
     CEF_REQUIRE_UI_THREAD();
 
     route_map_.clear();
@@ -231,7 +229,7 @@
   }
 
   void OnRouteStateChanged(CefRefPtr<CefMediaRoute> route,
-                           ConnectionState state) OVERRIDE {
+                           ConnectionState state) override {
     CEF_REQUIRE_UI_THREAD();
 
     CefRefPtr<CefDictionaryValue> payload = CefDictionaryValue::Create();
@@ -242,7 +240,7 @@
 
   void OnRouteMessageReceived(CefRefPtr<CefMediaRoute> route,
                               const void* message,
-                              size_t message_size) OVERRIDE {
+                              size_t message_size) override {
     CEF_REQUIRE_UI_THREAD();
 
     std::string message_str(static_cast<const char*>(message), message_size);
@@ -256,16 +254,18 @@
  private:
   CefRefPtr<CefMediaSource> GetSource(const std::string& source_urn) {
     CefRefPtr<CefMediaSource> source = media_router_->GetSource(source_urn);
-    if (!source || !source->IsValid())
-      return NULL;
+    if (!source) {
+      return nullptr;
+    }
     return source;
   }
 
   CefRefPtr<CefMediaSink> GetSink(const std::string& sink_id) {
     SinkInfoMap::const_iterator it = sink_info_map_.find(sink_id);
-    if (it != sink_info_map_.end())
+    if (it != sink_info_map_.end()) {
       return it->second->sink;
-    return NULL;
+    }
+    return nullptr;
   }
 
   void ClearSinkInfoMap() {
@@ -280,8 +280,9 @@
                         const std::string& sink_id,
                         const CefMediaSinkDeviceInfo& device_info) {
     // Discard callbacks that arrive after a new call to OnSinks().
-    if (sink_query_id != pending_sink_query_id_)
+    if (sink_query_id != pending_sink_query_id_) {
       return;
+    }
 
     SinkInfoMap::const_iterator it = sink_info_map_.find(sink_id);
     if (it != sink_info_map_.end()) {
@@ -297,9 +298,10 @@
 
   CefRefPtr<CefMediaRoute> GetRoute(const std::string& route_id) {
     RouteMap::const_iterator it = route_map_.find(route_id);
-    if (it != route_map_.end())
+    if (it != route_map_.end()) {
       return it->second;
-    return NULL;
+    }
+    return nullptr;
   }
 
   void SendResponse(const std::string& name,
@@ -322,17 +324,15 @@
       CefRefPtr<CefDictionaryValue> sink_dict = CefDictionaryValue::Create();
       sink_dict->SetString("id", it->first);
       sink_dict->SetString("name", info->sink->GetName());
-      sink_dict->SetString("desc", info->sink->GetDescription());
       sink_dict->SetInt("icon", info->sink->GetIconType());
       sink_dict->SetString("ip_address",
                            CefString(&info->device_info.ip_address));
       sink_dict->SetInt("port", info->device_info.port);
       sink_dict->SetString("model_name",
                            CefString(&info->device_info.model_name));
-      sink_dict->SetString("type",
-                           info->sink->IsCastSink()
-                               ? "cast"
-                               : info->sink->IsDialSink() ? "dial" : "unknown");
+      sink_dict->SetString("type", info->sink->IsCastSink()   ? "cast"
+                                   : info->sink->IsDialSink() ? "dial"
+                                                              : "unknown");
       sinks_list->SetDictionary(idx, sink_dict);
     }
 
@@ -383,16 +383,17 @@
   // Called due to cefQuery execution in media_router.html.
   bool OnQuery(CefRefPtr<CefBrowser> browser,
                CefRefPtr<CefFrame> frame,
-               int64 query_id,
+               int64_t query_id,
                const CefString& request,
                bool persistent,
-               CefRefPtr<Callback> callback) OVERRIDE {
+               CefRefPtr<Callback> callback) override {
     CEF_REQUIRE_UI_THREAD();
 
     // Only handle messages from the test URL.
     const std::string& url = frame->GetURL();
-    if (!test_runner::IsTestURL(url, kTestUrlPath))
+    if (!test_runner::IsTestURL(url, kTestUrlPath)) {
       return false;
+    }
 
     // Parse |request| as a JSON dictionary.
     CefRefPtr<CefDictionaryValue> request_dict = ParseJSON(request);
@@ -402,8 +403,9 @@
     }
 
     // Verify the "name" key.
-    if (!VerifyKey(request_dict, kNameKey, VTYPE_STRING, callback))
+    if (!VerifyKey(request_dict, kNameKey, VTYPE_STRING, callback)) {
       return true;
+    }
 
     const std::string& message_name = request_dict->GetString(kNameKey);
     if (message_name == kNameValueSubscribe) {
@@ -434,11 +436,13 @@
       // Create a new route.
 
       // Verify the "source_urn" key.
-      if (!VerifyKey(request_dict, kSourceKey, VTYPE_STRING, callback))
+      if (!VerifyKey(request_dict, kSourceKey, VTYPE_STRING, callback)) {
         return true;
+      }
       // Verify the "sink_id" key.
-      if (!VerifyKey(request_dict, kSinkKey, VTYPE_STRING, callback))
+      if (!VerifyKey(request_dict, kSinkKey, VTYPE_STRING, callback)) {
         return true;
+      }
 
       const std::string& source_urn = request_dict->GetString(kSourceKey);
       const std::string& sink_id = request_dict->GetString(kSinkKey);
@@ -453,8 +457,9 @@
       // Terminate an existing route.
 
       // Verify the "route" key.
-      if (!VerifyKey(request_dict, kRouteKey, VTYPE_STRING, callback))
+      if (!VerifyKey(request_dict, kRouteKey, VTYPE_STRING, callback)) {
         return true;
+      }
 
       const std::string& route_id = request_dict->GetString(kRouteKey);
       std::string error;
@@ -468,11 +473,13 @@
       // Send a route message.
 
       // Verify the "route_id" key.
-      if (!VerifyKey(request_dict, kRouteKey, VTYPE_STRING, callback))
+      if (!VerifyKey(request_dict, kRouteKey, VTYPE_STRING, callback)) {
         return true;
+      }
       // Verify the "message" key.
-      if (!VerifyKey(request_dict, kMessageKey, VTYPE_STRING, callback))
+      if (!VerifyKey(request_dict, kMessageKey, VTYPE_STRING, callback)) {
         return true;
+      }
 
       const std::string& route_id = request_dict->GetString(kRouteKey);
       const std::string& message = request_dict->GetString(kMessageKey);
@@ -490,7 +497,7 @@
 
   void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
                        CefRefPtr<CefFrame> frame,
-                       int64 query_id) OVERRIDE {
+                       int64_t query_id) override {
     CEF_REQUIRE_UI_THREAD();
     RemoveSubscription(browser->GetIdentifier(), query_id);
   }
@@ -505,8 +512,9 @@
   // Convert a JSON string to a dictionary value.
   static CefRefPtr<CefDictionaryValue> ParseJSON(const CefString& string) {
     CefRefPtr<CefValue> value = CefParseJSON(string, JSON_PARSER_RFC);
-    if (value.get() && value->GetType() == VTYPE_DICTIONARY)
+    if (value.get() && value->GetType() == VTYPE_DICTIONARY) {
       return value->GetDictionary();
+    }
     return nullptr;
   }
 
@@ -527,13 +535,13 @@
 
   // Subscription state associated with a single browser.
   struct SubscriptionState {
-    int64 query_id;
+    int64_t query_id;
     CefRefPtr<MediaObserver> observer;
     CefRefPtr<CefRegistration> registration;
   };
 
   bool CreateSubscription(CefRefPtr<CefBrowser> browser,
-                          int64 query_id,
+                          int64_t query_id,
                           CefRefPtr<Callback> callback) {
     const int browser_id = browser->GetIdentifier();
     if (subscription_state_map_.find(browser_id) !=
@@ -543,7 +551,7 @@
     }
 
     CefRefPtr<CefMediaRouter> media_router =
-        browser->GetHost()->GetRequestContext()->GetMediaRouter();
+        browser->GetHost()->GetRequestContext()->GetMediaRouter(nullptr);
 
     SubscriptionState* state = new SubscriptionState();
     state->query_id = query_id;
@@ -558,7 +566,7 @@
     return true;
   }
 
-  void RemoveSubscription(int browser_id, int64 query_id) {
+  void RemoveSubscription(int browser_id, int64_t query_id) {
     SubscriptionStateMap::iterator it =
         subscription_state_map_.find(browser_id);
     if (it != subscription_state_map_.end() &&
@@ -574,7 +582,7 @@
     if (it != subscription_state_map_.end()) {
       return it->second->observer;
     }
-    return NULL;
+    return nullptr;
   }
 
   // Map of browser ID to SubscriptionState object.
diff --git a/src/tests/cefclient/browser/osr_accessibility_helper.cc b/src/tests/cefclient/browser/osr_accessibility_helper.cc
index 01fafc0..caf3796 100644
--- a/src/tests/cefclient/browser/osr_accessibility_helper.cc
+++ b/src/tests/cefclient/browser/osr_accessibility_helper.cc
@@ -38,8 +38,7 @@
 
 OsrAccessibilityHelper::OsrAccessibilityHelper(CefRefPtr<CefValue> value,
                                                CefRefPtr<CefBrowser> browser)
-    : focused_node_id_(-1),
-      browser_(browser) {
+    : focused_node_id_(-1), browser_(browser) {
   UpdateAccessibilityTree(value);
 }
 
diff --git a/src/tests/cefclient/browser/osr_accessibility_node.cc b/src/tests/cefclient/browser/osr_accessibility_node.cc
index befa25f..648d50a 100644
--- a/src/tests/cefclient/browser/osr_accessibility_node.cc
+++ b/src/tests/cefclient/browser/osr_accessibility_node.cc
@@ -41,16 +41,18 @@
 }
 
 void OsrAXNode::UpdateValue(CefRefPtr<CefDictionaryValue> value) {
-  if (value->HasKey("role"))
+  if (value->HasKey("role")) {
     role_ = value->GetString("role");
+  }
 
   if (value->HasKey("child_ids")) {
     CefRefPtr<CefListValue> childs = value->GetList("child_ids");
     // Reset child Ids
     child_ids_.clear();
-    for (size_t idx = 0; idx < childs->GetSize(); idx++)
+    for (size_t idx = 0; idx < childs->GetSize(); idx++) {
       child_ids_.push_back(
           OsrAccessibilityHelper::CastToInt(childs->GetValue(idx)));
+    }
   }
   // Update Location
   if (value->HasKey("location")) {
@@ -85,24 +87,29 @@
     if (attributes_ && attributes_->HasKey("childTreeId")) {
       child_tree_id_ = attributes_->GetString("childTreeId");
     }
-    if (attributes_ && attributes_->HasKey("name"))
+    if (attributes_ && attributes_->HasKey("name")) {
       name_ = attributes_->GetString("name");
-    if (attributes_ && attributes_->HasKey("value"))
+    }
+    if (attributes_ && attributes_->HasKey("value")) {
       value_ = attributes_->GetString("value");
-    if (attributes_ && attributes_->HasKey("description"))
+    }
+    if (attributes_ && attributes_->HasKey("description")) {
       description_ = attributes_->GetString("description");
+    }
   }
 }
 
 CefWindowHandle OsrAXNode::GetWindowHandle() const {
-  if (accessibility_helper_)
+  if (accessibility_helper_) {
     return accessibility_helper_->GetWindowHandle();
-  return NULL;
+  }
+  return nullptr;
 }
 
 CefRefPtr<CefBrowser> OsrAXNode::GetBrowser() const {
-  if (accessibility_helper_)
+  if (accessibility_helper_) {
     return accessibility_helper_->GetBrowser();
+  }
   return nullptr;
 }
 
@@ -149,8 +156,9 @@
 
 OsrAXNode* OsrAXNode::ChildAtIndex(int index) const {
   int count = static_cast<int>(child_ids_.size());
-  if (index < count)
+  if (index < count) {
     return accessibility_helper_->GetNode(OsrAXTreeId(), child_ids_[index]);
+  }
   if ((index == count) && (!child_tree_id_.empty())) {
     OsrAXNode* childTreeRootNode =
         accessibility_helper_->GetTreeRootNode(child_tree_id_);
diff --git a/src/tests/cefclient/browser/osr_accessibility_node.h b/src/tests/cefclient/browser/osr_accessibility_node.h
index ece83c0..ab88819 100644
--- a/src/tests/cefclient/browser/osr_accessibility_node.h
+++ b/src/tests/cefclient/browser/osr_accessibility_node.h
@@ -10,7 +10,7 @@
 
 #include "include/cef_browser.h"
 
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
 typedef void CefNativeAccessible;
 #if __OBJC__
 #if __has_feature(objc_arc)
diff --git a/src/tests/cefclient/browser/osr_accessibility_node_mac.mm b/src/tests/cefclient/browser/osr_accessibility_node_mac.mm
index 2fbb8da..b5d5c38 100644
--- a/src/tests/cefclient/browser/osr_accessibility_node_mac.mm
+++ b/src/tests/cefclient/browser/osr_accessibility_node_mac.mm
@@ -15,220 +15,327 @@
 namespace {
 
 NSString* AxRoleToNSAxRole(const std::string& role_string) {
-  if (role_string == "abbr")
+  if (role_string == "abbr") {
     return NSAccessibilityGroupRole;
-  if (role_string == "alertDialog")
+  }
+  if (role_string == "alertDialog") {
     return NSAccessibilityGroupRole;
-  if (role_string == "alert")
+  }
+  if (role_string == "alert") {
     return NSAccessibilityGroupRole;
-  if (role_string == "annotation")
+  }
+  if (role_string == "annotation") {
     return NSAccessibilityUnknownRole;
-  if (role_string == "application")
+  }
+  if (role_string == "application") {
     return NSAccessibilityGroupRole;
-  if (role_string == "article")
+  }
+  if (role_string == "article") {
     return NSAccessibilityGroupRole;
-  if (role_string == "audio")
+  }
+  if (role_string == "audio") {
     return NSAccessibilityGroupRole;
-  if (role_string == "banner")
+  }
+  if (role_string == "banner") {
     return NSAccessibilityGroupRole;
-  if (role_string == "blockquote")
+  }
+  if (role_string == "blockquote") {
     return NSAccessibilityGroupRole;
-  if (role_string == "busyIndicator")
+  }
+  if (role_string == "busyIndicator") {
     return NSAccessibilityBusyIndicatorRole;
-  if (role_string == "button")
+  }
+  if (role_string == "button") {
     return NSAccessibilityButtonRole;
-  if (role_string == "buttonDropDown")
+  }
+  if (role_string == "buttonDropDown") {
     return NSAccessibilityButtonRole;
-  if (role_string == "canvas")
+  }
+  if (role_string == "canvas") {
     return NSAccessibilityImageRole;
-  if (role_string == "caption")
+  }
+  if (role_string == "caption") {
     return NSAccessibilityGroupRole;
-  if (role_string == "checkBox")
+  }
+  if (role_string == "checkBox") {
     return NSAccessibilityCheckBoxRole;
-  if (role_string == "colorWell")
+  }
+  if (role_string == "colorWell") {
     return NSAccessibilityColorWellRole;
-  if (role_string == "column")
+  }
+  if (role_string == "column") {
     return NSAccessibilityColumnRole;
-  if (role_string == "comboBox")
+  }
+  if (role_string == "comboBox") {
     return NSAccessibilityComboBoxRole;
-  if (role_string == "complementary")
+  }
+  if (role_string == "complementary") {
     return NSAccessibilityGroupRole;
-  if (role_string == "contentInfo")
+  }
+  if (role_string == "contentInfo") {
     return NSAccessibilityGroupRole;
-  if (role_string == "definition")
+  }
+  if (role_string == "definition") {
     return NSAccessibilityGroupRole;
-  if (role_string == "descriptionListDetail")
+  }
+  if (role_string == "descriptionListDetail") {
     return NSAccessibilityGroupRole;
-  if (role_string == "descriptionList")
+  }
+  if (role_string == "descriptionList") {
     return NSAccessibilityListRole;
-  if (role_string == "descriptionListTerm")
+  }
+  if (role_string == "descriptionListTerm") {
     return NSAccessibilityGroupRole;
-  if (role_string == "details")
+  }
+  if (role_string == "details") {
     return NSAccessibilityGroupRole;
-  if (role_string == "dialog")
+  }
+  if (role_string == "dialog") {
     return NSAccessibilityGroupRole;
-  if (role_string == "directory")
+  }
+  if (role_string == "directory") {
     return NSAccessibilityListRole;
-  if (role_string == "disclosureTriangle")
+  }
+  if (role_string == "disclosureTriangle") {
     return NSAccessibilityDisclosureTriangleRole;
-  if (role_string == "div")
+  }
+  if (role_string == "div") {
     return NSAccessibilityGroupRole;
-  if (role_string == "document")
+  }
+  if (role_string == "document") {
     return NSAccessibilityGroupRole;
-  if (role_string == "embeddedObject")
+  }
+  if (role_string == "embeddedObject") {
     return NSAccessibilityGroupRole;
-  if (role_string == "figcaption")
+  }
+  if (role_string == "figcaption") {
     return NSAccessibilityGroupRole;
-  if (role_string == "figure")
+  }
+  if (role_string == "figure") {
     return NSAccessibilityGroupRole;
-  if (role_string == "footer")
+  }
+  if (role_string == "footer") {
     return NSAccessibilityGroupRole;
-  if (role_string == "form")
+  }
+  if (role_string == "form") {
     return NSAccessibilityGroupRole;
-  if (role_string == "genericContainer")
+  }
+  if (role_string == "genericContainer") {
     return NSAccessibilityGroupRole;
-  if (role_string == "grid")
+  }
+  if (role_string == "grid") {
     return NSAccessibilityGroupRole;
-  if (role_string == "group")
+  }
+  if (role_string == "group") {
     return NSAccessibilityGroupRole;
-  if (role_string == "iframe")
+  }
+  if (role_string == "iframe") {
     return NSAccessibilityGroupRole;
-  if (role_string == "iframePresentational")
+  }
+  if (role_string == "iframePresentational") {
     return NSAccessibilityGroupRole;
-  if (role_string == "ignored")
+  }
+  if (role_string == "ignored") {
     return NSAccessibilityUnknownRole;
-  if (role_string == "imageMapLink")
+  }
+  if (role_string == "imageMapLink") {
     return NSAccessibilityLinkRole;
-  if (role_string == "imageMap")
+  }
+  if (role_string == "imageMap") {
     return NSAccessibilityGroupRole;
-  if (role_string == "image")
+  }
+  if (role_string == "image") {
     return NSAccessibilityImageRole;
-  if (role_string == "labelText")
+  }
+  if (role_string == "labelText") {
     return NSAccessibilityGroupRole;
-  if (role_string == "legend")
+  }
+  if (role_string == "legend") {
     return NSAccessibilityGroupRole;
-  if (role_string == "link")
+  }
+  if (role_string == "link") {
     return NSAccessibilityLinkRole;
-  if (role_string == "listBoxOption")
+  }
+  if (role_string == "listBoxOption") {
     return NSAccessibilityStaticTextRole;
-  if (role_string == "listBox")
+  }
+  if (role_string == "listBox") {
     return NSAccessibilityListRole;
-  if (role_string == "listItem")
+  }
+  if (role_string == "listItem") {
     return NSAccessibilityGroupRole;
-  if (role_string == "list")
+  }
+  if (role_string == "list") {
     return NSAccessibilityListRole;
-  if (role_string == "log")
+  }
+  if (role_string == "log") {
     return NSAccessibilityGroupRole;
-  if (role_string == "main")
+  }
+  if (role_string == "main") {
     return NSAccessibilityGroupRole;
-  if (role_string == "mark")
+  }
+  if (role_string == "mark") {
     return NSAccessibilityGroupRole;
-  if (role_string == "marquee")
+  }
+  if (role_string == "marquee") {
     return NSAccessibilityGroupRole;
-  if (role_string == "math")
+  }
+  if (role_string == "math") {
     return NSAccessibilityGroupRole;
-  if (role_string == "menu")
+  }
+  if (role_string == "menu") {
     return NSAccessibilityMenuRole;
-  if (role_string == "menuBar")
+  }
+  if (role_string == "menuBar") {
     return NSAccessibilityMenuBarRole;
-  if (role_string == "menuButton")
+  }
+  if (role_string == "menuButton") {
     return NSAccessibilityButtonRole;
-  if (role_string == "menuItem")
+  }
+  if (role_string == "menuItem") {
     return NSAccessibilityMenuItemRole;
-  if (role_string == "menuItemCheckBox")
+  }
+  if (role_string == "menuItemCheckBox") {
     return NSAccessibilityMenuItemRole;
-  if (role_string == "menuItemRadio")
+  }
+  if (role_string == "menuItemRadio") {
     return NSAccessibilityMenuItemRole;
-  if (role_string == "menuListOption")
+  }
+  if (role_string == "menuListOption") {
     return NSAccessibilityMenuItemRole;
-  if (role_string == "menuListPopup")
+  }
+  if (role_string == "menuListPopup") {
     return NSAccessibilityUnknownRole;
-  if (role_string == "meter")
+  }
+  if (role_string == "meter") {
     return NSAccessibilityProgressIndicatorRole;
-  if (role_string == "navigation")
+  }
+  if (role_string == "navigation") {
     return NSAccessibilityGroupRole;
-  if (role_string == "note")
+  }
+  if (role_string == "note") {
     return NSAccessibilityGroupRole;
-  if (role_string == "outline")
+  }
+  if (role_string == "outline") {
     return NSAccessibilityOutlineRole;
-  if (role_string == "paragraph")
+  }
+  if (role_string == "paragraph") {
     return NSAccessibilityGroupRole;
-  if (role_string == "popUpButton")
+  }
+  if (role_string == "popUpButton") {
     return NSAccessibilityPopUpButtonRole;
-  if (role_string == "pre")
+  }
+  if (role_string == "pre") {
     return NSAccessibilityGroupRole;
-  if (role_string == "presentational")
+  }
+  if (role_string == "presentational") {
     return NSAccessibilityGroupRole;
-  if (role_string == "progressIndicator")
+  }
+  if (role_string == "progressIndicator") {
     return NSAccessibilityProgressIndicatorRole;
-  if (role_string == "radioButton")
+  }
+  if (role_string == "radioButton") {
     return NSAccessibilityRadioButtonRole;
-  if (role_string == "radioGroup")
+  }
+  if (role_string == "radioGroup") {
     return NSAccessibilityRadioGroupRole;
-  if (role_string == "region")
+  }
+  if (role_string == "region") {
     return NSAccessibilityGroupRole;
-  if (role_string == "row")
+  }
+  if (role_string == "row") {
     return NSAccessibilityRowRole;
-  if (role_string == "ruler")
+  }
+  if (role_string == "ruler") {
     return NSAccessibilityRulerRole;
-  if (role_string == "scrollBar")
+  }
+  if (role_string == "scrollBar") {
     return NSAccessibilityScrollBarRole;
-  if (role_string == "search")
+  }
+  if (role_string == "search") {
     return NSAccessibilityGroupRole;
-  if (role_string == "searchBox")
+  }
+  if (role_string == "searchBox") {
     return NSAccessibilityTextFieldRole;
-  if (role_string == "slider")
+  }
+  if (role_string == "slider") {
     return NSAccessibilitySliderRole;
-  if (role_string == "sliderThumb")
+  }
+  if (role_string == "sliderThumb") {
     return NSAccessibilityValueIndicatorRole;
-  if (role_string == "spinButton")
+  }
+  if (role_string == "spinButton") {
     return NSAccessibilityIncrementorRole;
-  if (role_string == "splitter")
+  }
+  if (role_string == "splitter") {
     return NSAccessibilitySplitterRole;
-  if (role_string == "staticText")
+  }
+  if (role_string == "staticText") {
     return NSAccessibilityStaticTextRole;
-  if (role_string == "status")
+  }
+  if (role_string == "status") {
     return NSAccessibilityGroupRole;
-  if (role_string == "svgRoot")
+  }
+  if (role_string == "svgRoot") {
     return NSAccessibilityGroupRole;
-  if (role_string == "switch")
+  }
+  if (role_string == "switch") {
     return NSAccessibilityCheckBoxRole;
-  if (role_string == "tabGroup")
+  }
+  if (role_string == "tabGroup") {
     return NSAccessibilityTabGroupRole;
-  if (role_string == "tabList")
+  }
+  if (role_string == "tabList") {
     return NSAccessibilityTabGroupRole;
-  if (role_string == "tabPanel")
+  }
+  if (role_string == "tabPanel") {
     return NSAccessibilityGroupRole;
-  if (role_string == "tab")
+  }
+  if (role_string == "tab") {
     return NSAccessibilityRadioButtonRole;
-  if (role_string == "tableHeaderContainer")
+  }
+  if (role_string == "tableHeaderContainer") {
     return NSAccessibilityGroupRole;
-  if (role_string == "table")
+  }
+  if (role_string == "table") {
     return NSAccessibilityTableRole;
-  if (role_string == "textField")
+  }
+  if (role_string == "textField") {
     return NSAccessibilityTextFieldRole;
-  if (role_string == "time")
+  }
+  if (role_string == "time") {
     return NSAccessibilityGroupRole;
-  if (role_string == "timer")
+  }
+  if (role_string == "timer") {
     return NSAccessibilityGroupRole;
-  if (role_string == "toggleButton")
+  }
+  if (role_string == "toggleButton") {
     return NSAccessibilityCheckBoxRole;
-  if (role_string == "toolbar")
+  }
+  if (role_string == "toolbar") {
     return NSAccessibilityToolbarRole;
-  if (role_string == "treeGrid")
+  }
+  if (role_string == "treeGrid") {
     return NSAccessibilityTableRole;
-  if (role_string == "treeItem")
+  }
+  if (role_string == "treeItem") {
     return NSAccessibilityRowRole;
-  if (role_string == "tree")
+  }
+  if (role_string == "tree") {
     return NSAccessibilityOutlineRole;
-  if (role_string == "unknown")
+  }
+  if (role_string == "unknown") {
     return NSAccessibilityUnknownRole;
-  if (role_string == "tooltip")
+  }
+  if (role_string == "tooltip") {
     return NSAccessibilityGroupRole;
-  if (role_string == "video")
+  }
+  if (role_string == "video") {
     return NSAccessibilityGroupRole;
-  if (role_string == "window")
+  }
+  if (role_string == "window") {
     return NSAccessibilityWindowRole;
+  }
   return [NSString stringWithUTF8String:role_string.c_str()];
 }
 
@@ -387,8 +494,9 @@
 
 - (id)accessibilityAttributeValue:(NSString*)attribute {
   NSObject* typed_parent = CAST_CEF_NATIVE_ACCESSIBLE_TO_NSOBJECT(parent_);
-  if (!node_)
+  if (!node_) {
     return nil;
+  }
   if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
     return [self axRole];
   } else if ([attribute
diff --git a/src/tests/cefclient/browser/osr_accessibility_node_win.cc b/src/tests/cefclient/browser/osr_accessibility_node_win.cc
index a96889a..5c5e64f 100644
--- a/src/tests/cefclient/browser/osr_accessibility_node_win.cc
+++ b/src/tests/cefclient/browser/osr_accessibility_node_win.cc
@@ -40,72 +40,105 @@
 
 // Helper function to convert to MSAARole
 int AxRoleToMSAARole(const std::string& role_string) {
-  if (role_string == "alert")
+  if (role_string == "alert") {
     return ROLE_SYSTEM_ALERT;
-  if (role_string == "application")
+  }
+  if (role_string == "application") {
     return ROLE_SYSTEM_APPLICATION;
-  if (role_string == "buttonDropDown")
+  }
+  if (role_string == "buttonDropDown") {
     return ROLE_SYSTEM_BUTTONDROPDOWN;
-  if (role_string == "popUpButton")
+  }
+  if (role_string == "popUpButton") {
     return ROLE_SYSTEM_BUTTONMENU;
-  if (role_string == "checkBox")
+  }
+  if (role_string == "checkBox") {
     return ROLE_SYSTEM_CHECKBUTTON;
-  if (role_string == "comboBox")
+  }
+  if (role_string == "comboBox") {
     return ROLE_SYSTEM_COMBOBOX;
-  if (role_string == "dialog")
+  }
+  if (role_string == "dialog") {
     return ROLE_SYSTEM_DIALOG;
-  if (role_string == "genericContainer")
+  }
+  if (role_string == "genericContainer") {
     return ROLE_SYSTEM_GROUPING;
-  if (role_string == "group")
+  }
+  if (role_string == "group") {
     return ROLE_SYSTEM_GROUPING;
-  if (role_string == "image")
+  }
+  if (role_string == "image") {
     return ROLE_SYSTEM_GRAPHIC;
-  if (role_string == "link")
+  }
+  if (role_string == "link") {
     return ROLE_SYSTEM_LINK;
-  if (role_string == "locationBar")
+  }
+  if (role_string == "locationBar") {
     return ROLE_SYSTEM_GROUPING;
-  if (role_string == "menuBar")
+  }
+  if (role_string == "menuBar") {
     return ROLE_SYSTEM_MENUBAR;
-  if (role_string == "menuItem")
+  }
+  if (role_string == "menuItem") {
     return ROLE_SYSTEM_MENUITEM;
-  if (role_string == "menuListPopup")
+  }
+  if (role_string == "menuListPopup") {
     return ROLE_SYSTEM_MENUPOPUP;
-  if (role_string == "tree")
+  }
+  if (role_string == "tree") {
     return ROLE_SYSTEM_OUTLINE;
-  if (role_string == "treeItem")
+  }
+  if (role_string == "treeItem") {
     return ROLE_SYSTEM_OUTLINEITEM;
-  if (role_string == "tab")
+  }
+  if (role_string == "tab") {
     return ROLE_SYSTEM_PAGETAB;
-  if (role_string == "tabList")
+  }
+  if (role_string == "tabList") {
     return ROLE_SYSTEM_PAGETABLIST;
-  if (role_string == "pane")
+  }
+  if (role_string == "pane") {
     return ROLE_SYSTEM_PANE;
-  if (role_string == "progressIndicator")
+  }
+  if (role_string == "progressIndicator") {
     return ROLE_SYSTEM_PROGRESSBAR;
-  if (role_string == "button")
+  }
+  if (role_string == "button") {
     return ROLE_SYSTEM_PUSHBUTTON;
-  if (role_string == "radioButton")
+  }
+  if (role_string == "radioButton") {
     return ROLE_SYSTEM_RADIOBUTTON;
-  if (role_string == "scrollBar")
+  }
+  if (role_string == "scrollBar") {
     return ROLE_SYSTEM_SCROLLBAR;
-  if (role_string == "splitter")
+  }
+  if (role_string == "splitter") {
     return ROLE_SYSTEM_SEPARATOR;
-  if (role_string == "slider")
+  }
+  if (role_string == "slider") {
     return ROLE_SYSTEM_SLIDER;
-  if (role_string == "staticText")
+  }
+  if (role_string == "staticText") {
     return ROLE_SYSTEM_STATICTEXT;
-  if (role_string == "textField")
+  }
+  if (role_string == "textField") {
     return ROLE_SYSTEM_TEXT;
-  if (role_string == "titleBar")
+  }
+  if (role_string == "titleBar") {
     return ROLE_SYSTEM_TITLEBAR;
-  if (role_string == "toolbar")
+  }
+  if (role_string == "toolbar") {
     return ROLE_SYSTEM_TOOLBAR;
-  if (role_string == "webView")
+  }
+  if (role_string == "webView") {
     return ROLE_SYSTEM_GROUPING;
-  if (role_string == "window")
+  }
+  if (role_string == "window") {
     return ROLE_SYSTEM_WINDOW;
-  if (role_string == "client")
+  }
+  if (role_string == "client") {
     return ROLE_SYSTEM_CLIENT;
+  }
   // This is the default role for MSAA.
   return ROLE_SYSTEM_CLIENT;
 }
@@ -235,17 +268,19 @@
 // Handles ref counting and querying for other supported interfaces.
 // We only support, IUnknown, IDispatch and IAccessible.
 STDMETHODIMP CefIAccessible::QueryInterface(REFIID riid, void** ppvObject) {
-  if (riid == IID_IAccessible)
+  if (riid == IID_IAccessible) {
     *ppvObject = static_cast<IAccessible*>(this);
-  else if (riid == IID_IDispatch)
+  } else if (riid == IID_IDispatch) {
     *ppvObject = static_cast<IDispatch*>(this);
-  else if (riid == IID_IUnknown)
+  } else if (riid == IID_IUnknown) {
     *ppvObject = static_cast<IUnknown*>(this);
-  else
+  } else {
     *ppvObject = nullptr;
+  }
 
-  if (*ppvObject)
+  if (*ppvObject) {
     reinterpret_cast<IUnknown*>(*ppvObject)->AddRef();
+  }
 
   return (*ppvObject) ? S_OK : E_NOINTERFACE;
 }
@@ -259,8 +294,9 @@
   ULONG ulRefCnt = InterlockedDecrement((LONG volatile*)&ref_count_);
   if (ulRefCnt == 0) {
     // Remove reference from OsrAXNode
-    if (node_)
+    if (node_) {
       node_->Destroy();
+    }
     delete this;
   }
 
@@ -286,8 +322,9 @@
         }
       }
 
-      if (parent)
+      if (parent) {
         parent->AddRef();
+      }
       *ppdispParent = parent;
       retCode = (*ppdispParent) ? S_OK : S_FALSE;
     }
@@ -327,15 +364,17 @@
           // Convert to 0 based index and get Child Node.
           OsrAXNode* child = node_->ChildAtIndex(varChild.lVal - 1);
           // Fallback to focused node
-          if (!child)
+          if (!child) {
             child = node_->GetAccessibilityHelper()->GetFocusedNode();
+          }
 
           *ppdispChild = child->GetNativeAccessibleObject(node_);
         }
-        if (*ppdispChild == nullptr)
+        if (*ppdispChild == nullptr) {
           retCode = S_FALSE;
-        else
+        } else {
           (*ppdispChild)->AddRef();
+        }
       }
     }
   }
@@ -436,10 +475,11 @@
     BSTR* pszKeyboardShortcut) {
   HRESULT retCode = DATACHECK(node_);
   if (SUCCEEDED(retCode)) {
-    if (pszKeyboardShortcut && VALID_CHILDID(varChild))
+    if (pszKeyboardShortcut && VALID_CHILDID(varChild)) {
       *pszKeyboardShortcut = ::SysAllocString(L"None");
-    else
+    } else {
       retCode = E_INVALIDARG;
+    }
   }
   return retCode;
 }
@@ -450,8 +490,9 @@
   if (SUCCEEDED(retCode)) {
     OsrAXNode* focusedNode = node_->GetAccessibilityHelper()->GetFocusedNode();
     CefNativeAccessible* nativeObj = nullptr;
-    if (focusedNode)
+    if (focusedNode) {
       nativeObj = focusedNode->GetNativeAccessibleObject(nullptr);
+    }
 
     if (nativeObj) {
       if (nativeObj == this) {
@@ -473,10 +514,11 @@
 STDMETHODIMP CefIAccessible::get_accSelection(VARIANT* pvarChildren) {
   HRESULT retCode = DATACHECK(node_);
   if (SUCCEEDED(retCode)) {
-    if (pvarChildren)
+    if (pvarChildren) {
       pvarChildren->vt = VT_EMPTY;
-    else
+    } else {
       retCode = E_INVALIDARG;
+    }
   }
   return retCode;
 }
@@ -486,10 +528,11 @@
                                                   BSTR* pszDefaultAction) {
   HRESULT retCode = DATACHECK(node_);
   if (SUCCEEDED(retCode)) {
-    if (pszDefaultAction && VALID_CHILDID(varChild))
+    if (pszDefaultAction && VALID_CHILDID(varChild)) {
       *pszDefaultAction = ::SysAllocString(L"Push");
-    else
+    } else {
       retCode = E_INVALIDARG;
+    }
   }
   return retCode;
 }
@@ -661,8 +704,9 @@
 
 void OsrAXNode::Destroy() {
   CefIAccessible* ptr = static_cast<CefIAccessible*>(platform_accessibility_);
-  if (ptr)
+  if (ptr) {
     ptr->MarkDestroyed();
+  }
   platform_accessibility_ = nullptr;
 }
 
diff --git a/src/tests/cefclient/browser/osr_d3d11_win.cc b/src/tests/cefclient/browser/osr_d3d11_win.cc
deleted file mode 100644
index ca23d07..0000000
--- a/src/tests/cefclient/browser/osr_d3d11_win.cc
+++ /dev/null
@@ -1,934 +0,0 @@
-// Copyright 2018 The Chromium Embedded Framework Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be found
-// in the LICENSE file.
-//
-// Portions Copyright (c) 2018 Daktronics with the following MIT License:
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-
-#include "tests/cefclient/browser/osr_d3d11_win.h"
-
-#include <iomanip>  // For std::setw.
-
-#if OS_WIN && ARCH_CPU_ARM_FAMILY
-#define __prefetch(x) x
-#endif
-#include <d3dcompiler.h>
-#include <directxmath.h>
-
-#include "include/base/cef_logging.h"
-#include "include/internal/cef_string.h"
-#include "tests/shared/browser/util_win.h"
-
-namespace client {
-namespace d3d11 {
-
-namespace {
-
-// Wrap a raw COM pointer in a shared_ptr for auto Release().
-template <class T>
-std::shared_ptr<T> to_com_ptr(T* obj) {
-  return std::shared_ptr<T>(obj, [](T* p) {
-    if (p)
-      p->Release();
-  });
-}
-
-}  // namespace
-
-struct SimpleVertex {
-  DirectX::XMFLOAT3 pos;
-  DirectX::XMFLOAT2 tex;
-};
-
-Context::Context(ID3D11DeviceContext* ctx) : ctx_(to_com_ptr(ctx)) {}
-
-void Context::flush() {
-  ctx_->Flush();
-}
-
-SwapChain::SwapChain(IDXGISwapChain* swapchain,
-                     ID3D11RenderTargetView* rtv,
-                     ID3D11SamplerState* sampler,
-                     ID3D11BlendState* blender)
-    : sampler_(to_com_ptr(sampler)),
-      blender_(to_com_ptr(blender)),
-      swapchain_(to_com_ptr(swapchain)),
-      rtv_(to_com_ptr(rtv)),
-      width_(0),
-      height_(0) {}
-
-void SwapChain::bind(const std::shared_ptr<Context>& ctx) {
-  ctx_ = ctx;
-  ID3D11DeviceContext* d3d11_ctx = (ID3D11DeviceContext*)(*ctx_);
-
-  ID3D11RenderTargetView* rtv[1] = {rtv_.get()};
-  d3d11_ctx->OMSetRenderTargets(1, rtv, nullptr);
-
-  // Set default blending state.
-  if (blender_) {
-    float factor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
-    d3d11_ctx->OMSetBlendState(blender_.get(), factor, 0xffffffff);
-  }
-
-  // Set default sampler state.
-  if (sampler_) {
-    ID3D11SamplerState* samplers[1] = {sampler_.get()};
-    d3d11_ctx->PSSetSamplers(0, 1, samplers);
-  }
-}
-
-void SwapChain::unbind() {
-  ctx_.reset();
-}
-
-void SwapChain::clear(float red, float green, float blue, float alpha) {
-  ID3D11DeviceContext* d3d11_ctx = (ID3D11DeviceContext*)(*ctx_);
-  CHECK(d3d11_ctx);
-
-  FLOAT color[4] = {red, green, blue, alpha};
-  d3d11_ctx->ClearRenderTargetView(rtv_.get(), color);
-}
-
-void SwapChain::present(int sync_interval) {
-  swapchain_->Present(sync_interval, 0);
-}
-
-void SwapChain::resize(int width, int height) {
-  if (width <= 0 || height <= 0 || width == width_ || height == height_) {
-    return;
-  }
-  width_ = width;
-  height_ = height;
-
-  ID3D11DeviceContext* d3d11_ctx = (ID3D11DeviceContext*)(*ctx_);
-  CHECK(d3d11_ctx);
-
-  d3d11_ctx->OMSetRenderTargets(0, 0, 0);
-  rtv_.reset();
-
-  DXGI_SWAP_CHAIN_DESC desc;
-  swapchain_->GetDesc(&desc);
-  auto hr = swapchain_->ResizeBuffers(0, width, height, desc.BufferDesc.Format,
-                                      desc.Flags);
-  if (FAILED(hr)) {
-    LOG(ERROR) << "d3d11: Failed to resize swapchain (" << width << "x"
-               << height << ")";
-    return;
-  }
-
-  ID3D11Texture2D* buffer = nullptr;
-  hr = swapchain_->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&buffer);
-  if (FAILED(hr)) {
-    LOG(ERROR) << "d3d11: Failed to resize swapchain (" << width << "x"
-               << height << ")";
-    return;
-  }
-
-  ID3D11Device* dev = nullptr;
-  d3d11_ctx->GetDevice(&dev);
-  if (dev) {
-    D3D11_RENDER_TARGET_VIEW_DESC vdesc = {};
-    vdesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
-    vdesc.Texture2D.MipSlice = 0;
-    vdesc.Format = desc.BufferDesc.Format;
-
-    ID3D11RenderTargetView* view = nullptr;
-    hr = dev->CreateRenderTargetView(buffer, &vdesc, &view);
-    if (SUCCEEDED(hr)) {
-      rtv_ = to_com_ptr(view);
-      d3d11_ctx->OMSetRenderTargets(1, &view, nullptr);
-    }
-    dev->Release();
-  }
-  buffer->Release();
-
-  D3D11_VIEWPORT vp;
-  vp.Width = static_cast<float>(width);
-  vp.Height = static_cast<float>(height);
-  vp.MinDepth = D3D11_MIN_DEPTH;
-  vp.MaxDepth = D3D11_MAX_DEPTH;
-  vp.TopLeftX = 0;
-  vp.TopLeftY = 0;
-  d3d11_ctx->RSSetViewports(1, &vp);
-}
-
-Effect::Effect(ID3D11VertexShader* vsh,
-               ID3D11PixelShader* psh,
-               ID3D11InputLayout* layout)
-    : vsh_(to_com_ptr(vsh)),
-      psh_(to_com_ptr(psh)),
-      layout_(to_com_ptr(layout)) {}
-
-void Effect::bind(const std::shared_ptr<Context>& ctx) {
-  ctx_ = ctx;
-  ID3D11DeviceContext* d3d11_ctx = (ID3D11DeviceContext*)(*ctx_);
-
-  d3d11_ctx->IASetInputLayout(layout_.get());
-  d3d11_ctx->VSSetShader(vsh_.get(), nullptr, 0);
-  d3d11_ctx->PSSetShader(psh_.get(), nullptr, 0);
-}
-
-void Effect::unbind() {}
-
-Geometry::Geometry(D3D_PRIMITIVE_TOPOLOGY primitive,
-                   uint32_t vertices,
-                   uint32_t stride,
-                   ID3D11Buffer* buffer)
-    : primitive_(primitive),
-      vertices_(vertices),
-      stride_(stride),
-      buffer_(to_com_ptr(buffer)) {}
-
-void Geometry::bind(const std::shared_ptr<Context>& ctx) {
-  ctx_ = ctx;
-  ID3D11DeviceContext* d3d11_ctx = (ID3D11DeviceContext*)(*ctx_);
-
-  // TODO: Handle offset.
-  uint32_t offset = 0;
-
-  ID3D11Buffer* buffers[1] = {buffer_.get()};
-  d3d11_ctx->IASetVertexBuffers(0, 1, buffers, &stride_, &offset);
-  d3d11_ctx->IASetPrimitiveTopology(primitive_);
-}
-
-void Geometry::unbind() {}
-
-void Geometry::draw() {
-  ID3D11DeviceContext* d3d11_ctx = (ID3D11DeviceContext*)(*ctx_);
-  CHECK(d3d11_ctx);
-
-  // TODO: Handle offset.
-  d3d11_ctx->Draw(vertices_, 0);
-}
-
-Texture2D::Texture2D(ID3D11Texture2D* tex, ID3D11ShaderResourceView* srv)
-    : texture_(to_com_ptr(tex)), srv_(to_com_ptr(srv)) {
-  share_handle_ = nullptr;
-
-  IDXGIResource* res = nullptr;
-  if (SUCCEEDED(texture_->QueryInterface(__uuidof(IDXGIResource),
-                                         reinterpret_cast<void**>(&res)))) {
-    res->GetSharedHandle(&share_handle_);
-    res->Release();
-  }
-
-  // Are we using a keyed mutex?
-  IDXGIKeyedMutex* mutex = nullptr;
-  if (SUCCEEDED(texture_->QueryInterface(__uuidof(IDXGIKeyedMutex),
-                                         (void**)&mutex))) {
-    keyed_mutex_ = to_com_ptr(mutex);
-  }
-}
-
-uint32_t Texture2D::width() const {
-  D3D11_TEXTURE2D_DESC desc;
-  texture_->GetDesc(&desc);
-  return desc.Width;
-}
-
-uint32_t Texture2D::height() const {
-  D3D11_TEXTURE2D_DESC desc;
-  texture_->GetDesc(&desc);
-  return desc.Height;
-}
-
-DXGI_FORMAT Texture2D::format() const {
-  D3D11_TEXTURE2D_DESC desc;
-  texture_->GetDesc(&desc);
-  return desc.Format;
-}
-
-bool Texture2D::has_mutex() const {
-  return (keyed_mutex_.get() != nullptr);
-}
-
-bool Texture2D::lock_key(uint64_t key, uint32_t timeout_ms) {
-  if (keyed_mutex_) {
-    const auto hr = keyed_mutex_->AcquireSync(key, timeout_ms);
-    return (hr == S_OK);
-  }
-  return true;
-}
-
-void Texture2D::unlock_key(uint64_t key) {
-  if (keyed_mutex_) {
-    keyed_mutex_->ReleaseSync(key);
-  }
-}
-
-void Texture2D::bind(const std::shared_ptr<Context>& ctx) {
-  ctx_ = ctx;
-  ID3D11DeviceContext* d3d11_ctx = (ID3D11DeviceContext*)(*ctx_);
-  if (srv_) {
-    ID3D11ShaderResourceView* views[1] = {srv_.get()};
-    d3d11_ctx->PSSetShaderResources(0, 1, views);
-  }
-}
-
-void Texture2D::unbind() {}
-
-void* Texture2D::share_handle() const {
-  return share_handle_;
-}
-
-void Texture2D::copy_from(const std::shared_ptr<Texture2D>& other) {
-  ID3D11DeviceContext* d3d11_ctx = (ID3D11DeviceContext*)(*ctx_);
-  CHECK(d3d11_ctx);
-  if (other) {
-    d3d11_ctx->CopyResource(texture_.get(), other->texture_.get());
-  }
-}
-
-Device::Device(ID3D11Device* pdev, ID3D11DeviceContext* pctx)
-    : device_(to_com_ptr(pdev)), ctx_(std::make_shared<Context>(pctx)) {
-  lib_compiler_ = LoadLibrary(L"d3dcompiler_47.dll");
-}
-
-// static
-std::shared_ptr<Device> Device::create() {
-  UINT flags = 0;
-#ifdef _DEBUG
-  flags |= D3D11_CREATE_DEVICE_DEBUG;
-#endif
-
-  D3D_FEATURE_LEVEL feature_levels[] = {
-      D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1,
-      D3D_FEATURE_LEVEL_10_0,
-      // D3D_FEATURE_LEVEL_9_3,
-  };
-  UINT num_feature_levels = sizeof(feature_levels) / sizeof(feature_levels[0]);
-
-  ID3D11Device* pdev = nullptr;
-  ID3D11DeviceContext* pctx = nullptr;
-
-  D3D_FEATURE_LEVEL selected_level;
-  HRESULT hr = D3D11CreateDevice(
-      nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, flags, feature_levels,
-      num_feature_levels, D3D11_SDK_VERSION, &pdev, &selected_level, &pctx);
-
-  if (hr == E_INVALIDARG) {
-    // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1
-    // so we need to retry without it.
-    hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, flags,
-                           &feature_levels[1], num_feature_levels - 1,
-                           D3D11_SDK_VERSION, &pdev, &selected_level, &pctx);
-  }
-
-  if (SUCCEEDED(hr)) {
-    const auto dev = std::make_shared<Device>(pdev, pctx);
-
-    LOG(INFO) << "d3d11: Selected adapter " << dev->adapter_name()
-              << " and feature level 0x" << std::setw(4) << std::hex
-              << selected_level;
-
-    return dev;
-  }
-
-  return nullptr;
-}
-
-std::string Device::adapter_name() const {
-  IDXGIDevice* dxgi_dev = nullptr;
-  auto hr = device_->QueryInterface(__uuidof(dxgi_dev), (void**)&dxgi_dev);
-  if (SUCCEEDED(hr)) {
-    IDXGIAdapter* dxgi_adapt = nullptr;
-    hr = dxgi_dev->GetAdapter(&dxgi_adapt);
-    dxgi_dev->Release();
-    if (SUCCEEDED(hr)) {
-      DXGI_ADAPTER_DESC desc;
-      hr = dxgi_adapt->GetDesc(&desc);
-      dxgi_adapt->Release();
-      if (SUCCEEDED(hr)) {
-        return CefString(desc.Description);
-      }
-    }
-  }
-
-  return "n/a";
-}
-
-std::shared_ptr<Context> Device::immedidate_context() {
-  return ctx_;
-}
-
-std::shared_ptr<SwapChain> Device::create_swapchain(HWND window,
-                                                    int width,
-                                                    int height) {
-  HRESULT hr;
-  IDXGIFactory1* dxgi_factory = nullptr;
-
-  // Default size to the window size unless specified.
-  RECT rc_bounds;
-  GetClientRect(window, &rc_bounds);
-  if (width <= 0) {
-    width = rc_bounds.right - rc_bounds.left;
-  }
-  if (height <= 0) {
-    height = rc_bounds.bottom - rc_bounds.top;
-  }
-
-  {
-    IDXGIDevice* dxgi_dev = nullptr;
-    hr = device_->QueryInterface(__uuidof(IDXGIDevice),
-                                 reinterpret_cast<void**>(&dxgi_dev));
-    if (FAILED(hr)) {
-      return nullptr;
-    }
-
-    IDXGIAdapter* adapter = nullptr;
-    hr = dxgi_dev->GetAdapter(&adapter);
-    dxgi_dev->Release();
-    if (FAILED(hr)) {
-      return nullptr;
-    }
-
-    hr = adapter->GetParent(__uuidof(IDXGIFactory1),
-                            reinterpret_cast<void**>(&dxgi_factory));
-    adapter->Release();
-  }
-
-  if (!dxgi_factory) {
-    return nullptr;
-  }
-
-  IDXGISwapChain* swapchain = nullptr;
-
-  // Create swap chain.
-  IDXGIFactory2* dxgi_factory2 = nullptr;
-  hr = dxgi_factory->QueryInterface(__uuidof(IDXGIFactory2),
-                                    reinterpret_cast<void**>(&dxgi_factory2));
-  if (dxgi_factory2) {
-    DXGI_SWAP_CHAIN_DESC1 sd;
-    ZeroMemory(&sd, sizeof(sd));
-    sd.Width = width;
-    sd.Height = height;
-    sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
-    sd.SampleDesc.Count = 1;
-    sd.SampleDesc.Quality = 0;
-    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-    sd.BufferCount = 1;
-
-    IDXGISwapChain1* swapchain1 = nullptr;
-    hr = dxgi_factory2->CreateSwapChainForHwnd(device_.get(), window, &sd,
-                                               nullptr, nullptr, &swapchain1);
-    if (SUCCEEDED(hr)) {
-      hr = swapchain1->QueryInterface(__uuidof(IDXGISwapChain),
-                                      reinterpret_cast<void**>(&swapchain));
-      swapchain1->Release();
-    }
-
-    dxgi_factory2->Release();
-  } else {
-    // DirectX 11.0 systems.
-    DXGI_SWAP_CHAIN_DESC sd;
-    ZeroMemory(&sd, sizeof(sd));
-    sd.BufferCount = 1;
-    sd.BufferDesc.Width = width;
-    sd.BufferDesc.Height = height;
-    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
-    sd.BufferDesc.RefreshRate.Numerator = 60;
-    sd.BufferDesc.RefreshRate.Denominator = 1;
-    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-    sd.OutputWindow = window;
-    sd.SampleDesc.Count = 1;
-    sd.SampleDesc.Quality = 0;
-    sd.Windowed = TRUE;
-
-    hr = dxgi_factory->CreateSwapChain(device_.get(), &sd, &swapchain);
-  }
-
-  // We don't handle full-screen swapchains so we block the ALT+ENTER shortcut.
-  dxgi_factory->MakeWindowAssociation(window, DXGI_MWA_NO_ALT_ENTER);
-  dxgi_factory->Release();
-
-  if (!swapchain) {
-    return nullptr;
-  }
-
-  ID3D11Texture2D* back_buffer = nullptr;
-  hr = swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D),
-                            reinterpret_cast<void**>(&back_buffer));
-  if (FAILED(hr)) {
-    swapchain->Release();
-    return nullptr;
-  }
-
-  ID3D11RenderTargetView* rtv = nullptr;
-  hr = device_->CreateRenderTargetView(back_buffer, nullptr, &rtv);
-  back_buffer->Release();
-  if (FAILED(hr)) {
-    swapchain->Release();
-    return nullptr;
-  }
-
-  const auto ctx = (ID3D11DeviceContext*)(*ctx_);
-
-  ctx->OMSetRenderTargets(1, &rtv, nullptr);
-
-  // Setup the viewport.
-  D3D11_VIEWPORT vp;
-  vp.Width = (FLOAT)width;
-  vp.Height = (FLOAT)height;
-  vp.MinDepth = 0.0f;
-  vp.MaxDepth = 1.0f;
-  vp.TopLeftX = 0;
-  vp.TopLeftY = 0;
-  ctx->RSSetViewports(1, &vp);
-
-  // Create a default sampler to use.
-  ID3D11SamplerState* sampler = nullptr;
-  {
-    D3D11_SAMPLER_DESC desc = {};
-    desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
-    desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
-    desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
-    desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
-    desc.MinLOD = 0.0f;
-    desc.MaxLOD = D3D11_FLOAT32_MAX;
-    desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
-    device_->CreateSamplerState(&desc, &sampler);
-  }
-
-  // Create a default blend state to use (pre-multiplied alpha).
-  ID3D11BlendState* blender = nullptr;
-  {
-    D3D11_BLEND_DESC desc;
-    desc.AlphaToCoverageEnable = FALSE;
-    desc.IndependentBlendEnable = FALSE;
-    const auto count = sizeof(desc.RenderTarget) / sizeof(desc.RenderTarget[0]);
-    for (size_t n = 0; n < count; ++n) {
-      desc.RenderTarget[n].BlendEnable = TRUE;
-      desc.RenderTarget[n].SrcBlend = D3D11_BLEND_ONE;
-      desc.RenderTarget[n].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
-      desc.RenderTarget[n].SrcBlendAlpha = D3D11_BLEND_ONE;
-      desc.RenderTarget[n].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
-      desc.RenderTarget[n].BlendOp = D3D11_BLEND_OP_ADD;
-      desc.RenderTarget[n].BlendOpAlpha = D3D11_BLEND_OP_ADD;
-      desc.RenderTarget[n].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
-    }
-    device_->CreateBlendState(&desc, &blender);
-  }
-
-  return std::make_shared<SwapChain>(swapchain, rtv, sampler, blender);
-}
-
-std::shared_ptr<Geometry> Device::create_quad(float x,
-                                              float y,
-                                              float width,
-                                              float height,
-                                              bool flip) {
-  x = (x * 2.0f) - 1.0f;
-  y = 1.0f - (y * 2.0f);
-  width = width * 2.0f;
-  height = height * 2.0f;
-  float z = 1.0f;
-
-  SimpleVertex vertices[] = {
-
-      {DirectX::XMFLOAT3(x, y, z), DirectX::XMFLOAT2(0.0f, 0.0f)},
-      {DirectX::XMFLOAT3(x + width, y, z), DirectX::XMFLOAT2(1.0f, 0.0f)},
-      {DirectX::XMFLOAT3(x, y - height, z), DirectX::XMFLOAT2(0.0f, 1.0f)},
-      {DirectX::XMFLOAT3(x + width, y - height, z),
-       DirectX::XMFLOAT2(1.0f, 1.0f)}};
-
-  if (flip) {
-    DirectX::XMFLOAT2 tmp(vertices[2].tex);
-    vertices[2].tex = vertices[0].tex;
-    vertices[0].tex = tmp;
-
-    tmp = vertices[3].tex;
-    vertices[3].tex = vertices[1].tex;
-    vertices[1].tex = tmp;
-  }
-
-  D3D11_BUFFER_DESC desc = {};
-  desc.Usage = D3D11_USAGE_DEFAULT;
-  desc.ByteWidth = sizeof(SimpleVertex) * 4;
-  desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
-  desc.CPUAccessFlags = 0;
-
-  D3D11_SUBRESOURCE_DATA srd = {};
-  srd.pSysMem = vertices;
-
-  ID3D11Buffer* buffer = nullptr;
-  const auto hr = device_->CreateBuffer(&desc, &srd, &buffer);
-  if (SUCCEEDED(hr)) {
-    return std::make_shared<Geometry>(
-        D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, 4,
-        static_cast<uint32_t>(sizeof(SimpleVertex)), buffer);
-  }
-
-  return nullptr;
-}
-
-std::shared_ptr<Texture2D> Device::open_shared_texture(void* handle) {
-  ID3D11Texture2D* tex = nullptr;
-  auto hr = device_->OpenSharedResource(handle, __uuidof(ID3D11Texture2D),
-                                        (void**)(&tex));
-  if (FAILED(hr)) {
-    return nullptr;
-  }
-
-  D3D11_TEXTURE2D_DESC td;
-  tex->GetDesc(&td);
-
-  ID3D11ShaderResourceView* srv = nullptr;
-
-  if (td.BindFlags & D3D11_BIND_SHADER_RESOURCE) {
-    D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc;
-    srv_desc.Format = td.Format;
-    srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
-    srv_desc.Texture2D.MostDetailedMip = 0;
-    srv_desc.Texture2D.MipLevels = 1;
-
-    hr = device_->CreateShaderResourceView(tex, &srv_desc, &srv);
-    if (FAILED(hr)) {
-      tex->Release();
-      return nullptr;
-    }
-  }
-
-  return std::make_shared<Texture2D>(tex, srv);
-}
-
-std::shared_ptr<Texture2D> Device::create_texture(int width,
-                                                  int height,
-                                                  DXGI_FORMAT format,
-                                                  const void* data,
-                                                  size_t row_stride) {
-  D3D11_TEXTURE2D_DESC td;
-  td.ArraySize = 1;
-  td.BindFlags = D3D11_BIND_SHADER_RESOURCE;
-  td.CPUAccessFlags = 0;
-  td.Format = format;
-  td.Width = width;
-  td.Height = height;
-  td.MipLevels = 1;
-  td.MiscFlags = 0;
-  td.SampleDesc.Count = 1;
-  td.SampleDesc.Quality = 0;
-  td.Usage = D3D11_USAGE_DEFAULT;
-
-  D3D11_SUBRESOURCE_DATA srd;
-  srd.pSysMem = data;
-  srd.SysMemPitch = static_cast<uint32_t>(row_stride);
-  srd.SysMemSlicePitch = 0;
-
-  ID3D11Texture2D* tex = nullptr;
-  auto hr = device_->CreateTexture2D(&td, data ? &srd : nullptr, &tex);
-  if (FAILED(hr)) {
-    return nullptr;
-  }
-
-  D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc;
-  srv_desc.Format = td.Format;
-  srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
-  srv_desc.Texture2D.MostDetailedMip = 0;
-  srv_desc.Texture2D.MipLevels = 1;
-
-  ID3D11ShaderResourceView* srv = nullptr;
-  hr = device_->CreateShaderResourceView(tex, &srv_desc, &srv);
-  if (FAILED(hr)) {
-    tex->Release();
-    return nullptr;
-  }
-
-  return std::make_shared<Texture2D>(tex, srv);
-}
-
-std::shared_ptr<ID3DBlob> Device::compile_shader(const std::string& source_code,
-                                                 const std::string& entry_point,
-                                                 const std::string& model) {
-  if (!lib_compiler_) {
-    return nullptr;
-  }
-
-  typedef HRESULT(WINAPI * PFN_D3DCOMPILE)(
-      LPCVOID, SIZE_T, LPCSTR, const D3D_SHADER_MACRO*, ID3DInclude*, LPCSTR,
-      LPCSTR, UINT, UINT, ID3DBlob**, ID3DBlob**);
-
-  const auto fnc_compile = reinterpret_cast<PFN_D3DCOMPILE>(
-      GetProcAddress(lib_compiler_, "D3DCompile"));
-  if (!fnc_compile) {
-    return nullptr;
-  }
-
-  DWORD flags = D3DCOMPILE_ENABLE_STRICTNESS;
-
-#if defined(NDEBUG)
-// flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;
-// flags |= D3DCOMPILE_AVOID_FLOW_CONTROL;
-#else
-  flags |= D3DCOMPILE_DEBUG;
-  flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
-#endif
-
-  ID3DBlob* blob = nullptr;
-  ID3DBlob* blob_err = nullptr;
-
-  const auto psrc = source_code.c_str();
-  const auto len = source_code.size() + 1;
-
-  const auto hr =
-      fnc_compile(psrc, len, nullptr, nullptr, nullptr, entry_point.c_str(),
-                  model.c_str(), flags, 0, &blob, &blob_err);
-
-  if (FAILED(hr)) {
-    if (blob_err) {
-      // TODO: Log the error.
-      blob_err->Release();
-    }
-    return nullptr;
-  }
-
-  if (blob_err) {
-    blob_err->Release();
-  }
-
-  return std::shared_ptr<ID3DBlob>(blob, [](ID3DBlob* p) {
-    if (p)
-      p->Release();
-  });
-}
-
-std::shared_ptr<Effect> Device::create_default_effect() {
-  const auto vsh =
-      R"--(struct VS_INPUT
-{
-	float4 pos : POSITION;
-	float2 tex : TEXCOORD0;
-};
-
-struct VS_OUTPUT
-{
-	float4 pos : SV_POSITION;
-	float2 tex : TEXCOORD0;
-};
-
-VS_OUTPUT main(VS_INPUT input)
-{
-	VS_OUTPUT output;
-	output.pos = input.pos;
-	output.tex = input.tex;
-	return output;
-})--";
-
-  const auto psh =
-      R"--(Texture2D tex0 : register(t0);
-SamplerState samp0 : register(s0);
-
-struct VS_OUTPUT
-{
-	float4 pos : SV_POSITION;
-	float2 tex : TEXCOORD0;
-};
-
-float4 main(VS_OUTPUT input) : SV_Target
-{
-	return tex0.Sample(samp0, input.tex);
-})--";
-
-  return create_effect(vsh, "main", "vs_4_0", psh, "main", "ps_4_0");
-}
-
-std::shared_ptr<Effect> Device::create_effect(const std::string& vertex_code,
-                                              const std::string& vertex_entry,
-                                              const std::string& vertex_model,
-                                              const std::string& pixel_code,
-                                              const std::string& pixel_entry,
-                                              const std::string& pixel_model) {
-  const auto vs_blob = compile_shader(vertex_code, vertex_entry, vertex_model);
-
-  ID3D11VertexShader* vshdr = nullptr;
-  ID3D11InputLayout* layout = nullptr;
-
-  if (vs_blob) {
-    device_->CreateVertexShader(vs_blob->GetBufferPointer(),
-                                vs_blob->GetBufferSize(), nullptr, &vshdr);
-
-    D3D11_INPUT_ELEMENT_DESC layout_desc[] = {
-        {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
-         D3D11_INPUT_PER_VERTEX_DATA, 0},
-        {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12,
-         D3D11_INPUT_PER_VERTEX_DATA, 0},
-    };
-
-    UINT elements = ARRAYSIZE(layout_desc);
-
-    // Create the input layout.
-    device_->CreateInputLayout(layout_desc, elements,
-                               vs_blob->GetBufferPointer(),
-                               vs_blob->GetBufferSize(), &layout);
-  }
-
-  const auto ps_blob = compile_shader(pixel_code, pixel_entry, pixel_model);
-  ID3D11PixelShader* pshdr = nullptr;
-  if (ps_blob) {
-    device_->CreatePixelShader(ps_blob->GetBufferPointer(),
-                               ps_blob->GetBufferSize(), nullptr, &pshdr);
-  }
-
-  return std::make_shared<Effect>(vshdr, pshdr, layout);
-}
-
-Layer::Layer(const std::shared_ptr<Device>& device, bool flip)
-    : device_(device), flip_(flip) {
-  bounds_.x = bounds_.y = bounds_.width = bounds_.height = 0.0f;
-}
-
-Layer::~Layer() {}
-
-void Layer::attach(const std::shared_ptr<Composition>& parent) {
-  composition_ = parent;
-}
-
-std::shared_ptr<Composition> Layer::composition() const {
-  return composition_.lock();
-}
-
-Rect Layer::bounds() const {
-  return bounds_;
-}
-
-void Layer::move(float x, float y, float width, float height) {
-  bounds_.x = x;
-  bounds_.y = y;
-  bounds_.width = width;
-  bounds_.height = height;
-
-  // It's not efficient to create the quad everytime we move, but for now we're
-  // just trying to get something on-screen.
-  geometry_.reset();
-}
-
-void Layer::tick(double) {
-  // Nothing to update in the base class.
-}
-
-void Layer::render_texture(const std::shared_ptr<Context>& ctx,
-                           const std::shared_ptr<Texture2D>& texture) {
-  if (!geometry_) {
-    geometry_ = device_->create_quad(bounds_.x, bounds_.y, bounds_.width,
-                                     bounds_.height, flip_);
-  }
-
-  if (geometry_ && texture) {
-    // We need a shader.
-    if (!effect_) {
-      effect_ = device_->create_default_effect();
-    }
-
-    // Bind our states/resource to the pipeline.
-    ScopedBinder<Geometry> quad_binder(ctx, geometry_);
-    ScopedBinder<Effect> fx_binder(ctx, effect_);
-    ScopedBinder<Texture2D> tex_binder(ctx, texture);
-
-    // Draw the quad.
-    geometry_->draw();
-  }
-}
-
-Composition::Composition(const std::shared_ptr<Device>& device,
-                         int width,
-                         int height)
-    : width_(width), height_(height), vsync_(true), device_(device) {
-  fps_ = 0.0;
-  time_ = 0.0;
-  frame_ = 0;
-  fps_start_ = GetTimeNow();
-}
-
-bool Composition::is_vsync() const {
-  return vsync_;
-}
-
-double Composition::time() const {
-  return time_;
-}
-
-double Composition::fps() const {
-  return fps_;
-}
-
-void Composition::add_layer(const std::shared_ptr<Layer>& layer) {
-  if (layer) {
-    layers_.push_back(layer);
-
-    // Attach ourselves as the parent.
-    layer->attach(shared_from_this());
-  }
-}
-
-bool Composition::remove_layer(const std::shared_ptr<Layer>& layer) {
-  size_t match = 0;
-  if (layer) {
-    for (auto i = layers_.begin(); i != layers_.end();) {
-      if ((*i).get() == layer.get()) {
-        i = layers_.erase(i);
-        match++;
-      } else {
-        i++;
-      }
-    }
-  }
-  return (match > 0);
-}
-
-void Composition::resize(bool vsync, int width, int height) {
-  vsync_ = vsync;
-  width_ = width;
-  height_ = height;
-}
-
-void Composition::tick(double t) {
-  time_ = t;
-  for (const auto& layer : layers_) {
-    layer->tick(t);
-  }
-}
-
-void Composition::render(const std::shared_ptr<Context>& ctx) {
-  // Use painter's algorithm and render our layers in order (not doing any dept
-  // or 3D here).
-  for (const auto& layer : layers_) {
-    layer->render(ctx);
-  }
-
-  frame_++;
-  const auto now = GetTimeNow();
-  if ((now - fps_start_) > 1000000) {
-    fps_ = frame_ / double((now - fps_start_) / 1000000.0);
-    frame_ = 0;
-    fps_start_ = now;
-  }
-}
-
-FrameBuffer::FrameBuffer(const std::shared_ptr<Device>& device)
-    : device_(device) {}
-
-void FrameBuffer::on_paint(void* shared_handle) {
-  // Did the shared texture change?
-  if (shared_buffer_ && shared_handle != shared_buffer_->share_handle()) {
-    shared_buffer_.reset();
-  }
-
-  // Open the shared texture.
-  if (!shared_buffer_) {
-    shared_buffer_ = device_->open_shared_texture((void*)shared_handle);
-    if (!shared_buffer_) {
-      LOG(ERROR) << "d3d11: Could not open shared texture!";
-    }
-  }
-}
-
-}  // namespace d3d11
-}  // namespace client
diff --git a/src/tests/cefclient/browser/osr_d3d11_win.h b/src/tests/cefclient/browser/osr_d3d11_win.h
deleted file mode 100644
index f1190e3..0000000
--- a/src/tests/cefclient/browser/osr_d3d11_win.h
+++ /dev/null
@@ -1,330 +0,0 @@
-// Copyright 2018 The Chromium Embedded Framework Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be found
-// in the LICENSE file.
-//
-// Portions Copyright (c) 2018 Daktronics with the following MIT License:
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-
-#ifndef CEF_TESTS_CEFCLIENT_BROWSER_OSR_D3D11_WIN_H_
-#define CEF_TESTS_CEFCLIENT_BROWSER_OSR_D3D11_WIN_H_
-#pragma once
-
-#include <d3d11_1.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "include/base/cef_macros.h"
-
-namespace client {
-namespace d3d11 {
-
-class Composition;
-class Context;
-class Effect;
-class Geometry;
-class SwapChain;
-class Texture2D;
-
-// Basic rect for floats.
-struct Rect {
-  float x;
-  float y;
-  float width;
-  float height;
-};
-
-template <class T>
-class ScopedBinder {
- public:
-  ScopedBinder(const std::shared_ptr<Context>& ctx,
-               const std::shared_ptr<T>& target)
-      : target_(target) {
-    if (target_) {
-      target_->bind(ctx);
-    }
-  }
-  ~ScopedBinder() {
-    if (target_) {
-      target_->unbind();
-    }
-  }
-
- private:
-  const std::shared_ptr<T> target_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedBinder);
-};
-
-class Context {
- public:
-  Context(ID3D11DeviceContext*);
-
-  void flush();
-
-  operator ID3D11DeviceContext*() { return ctx_.get(); }
-
- private:
-  const std::shared_ptr<ID3D11DeviceContext> ctx_;
-};
-
-// Encapsulate a D3D11 Device object.
-class Device {
- public:
-  Device(ID3D11Device*, ID3D11DeviceContext*);
-
-  static std::shared_ptr<Device> create();
-
-  std::string adapter_name() const;
-
-  operator ID3D11Device*() { return device_.get(); }
-
-  std::shared_ptr<Context> immedidate_context();
-
-  std::shared_ptr<SwapChain> create_swapchain(HWND,
-                                              int width = 0,
-                                              int height = 0);
-
-  std::shared_ptr<Geometry> create_quad(float x,
-                                        float y,
-                                        float width,
-                                        float height,
-                                        bool flip = false);
-
-  std::shared_ptr<Texture2D> create_texture(int width,
-                                            int height,
-                                            DXGI_FORMAT format,
-                                            const void* data,
-                                            size_t row_stride);
-
-  std::shared_ptr<Texture2D> open_shared_texture(void*);
-
-  // Create some basic shaders so we can draw a textured-quad.
-  std::shared_ptr<Effect> create_default_effect();
-
-  std::shared_ptr<Effect> create_effect(const std::string& vertex_code,
-                                        const std::string& vertex_entry,
-                                        const std::string& vertex_model,
-                                        const std::string& pixel_code,
-                                        const std::string& pixel_entry,
-                                        const std::string& pixel_model);
-
- private:
-  std::shared_ptr<ID3DBlob> compile_shader(const std::string& source_code,
-                                           const std::string& entry_point,
-                                           const std::string& model);
-
-  HMODULE lib_compiler_;
-
-  const std::shared_ptr<ID3D11Device> device_;
-  const std::shared_ptr<Context> ctx_;
-
-  DISALLOW_COPY_AND_ASSIGN(Device);
-};
-
-// Encapsulate a DXGI swapchain for a window.
-class SwapChain {
- public:
-  SwapChain(IDXGISwapChain*,
-            ID3D11RenderTargetView*,
-            ID3D11SamplerState*,
-            ID3D11BlendState*);
-
-  void bind(const std::shared_ptr<Context>& ctx);
-  void unbind();
-
-  void clear(float red, float green, float blue, float alpha);
-
-  void present(int sync_interval);
-  void resize(int width, int height);
-
-  int width() const { return width_; }
-  int height() const { return height_; }
-
- private:
-  const std::shared_ptr<ID3D11SamplerState> sampler_;
-  const std::shared_ptr<ID3D11BlendState> blender_;
-  const std::shared_ptr<IDXGISwapChain> swapchain_;
-  std::shared_ptr<ID3D11RenderTargetView> rtv_;
-  std::shared_ptr<Context> ctx_;
-  int width_;
-  int height_;
-
-  DISALLOW_COPY_AND_ASSIGN(SwapChain);
-};
-
-class Texture2D {
- public:
-  Texture2D(ID3D11Texture2D* tex, ID3D11ShaderResourceView* srv);
-
-  void bind(std::shared_ptr<Context> const& ctx);
-  void unbind();
-
-  uint32_t width() const;
-  uint32_t height() const;
-  DXGI_FORMAT format() const;
-
-  bool has_mutex() const;
-
-  bool lock_key(uint64_t key, uint32_t timeout_ms);
-  void unlock_key(uint64_t key);
-
-  void* share_handle() const;
-
-  void copy_from(const std::shared_ptr<Texture2D>&);
-
- private:
-  HANDLE share_handle_;
-
-  const std::shared_ptr<ID3D11Texture2D> texture_;
-  const std::shared_ptr<ID3D11ShaderResourceView> srv_;
-  std::shared_ptr<IDXGIKeyedMutex> keyed_mutex_;
-  std::shared_ptr<Context> ctx_;
-
-  DISALLOW_COPY_AND_ASSIGN(Texture2D);
-};
-
-class Effect {
- public:
-  Effect(ID3D11VertexShader* vsh,
-         ID3D11PixelShader* psh,
-         ID3D11InputLayout* layout);
-
-  void bind(const std::shared_ptr<Context>& ctx);
-  void unbind();
-
- private:
-  const std::shared_ptr<ID3D11VertexShader> vsh_;
-  const std::shared_ptr<ID3D11PixelShader> psh_;
-  const std::shared_ptr<ID3D11InputLayout> layout_;
-  std::shared_ptr<Context> ctx_;
-
-  DISALLOW_COPY_AND_ASSIGN(Effect);
-};
-
-class Geometry {
- public:
-  Geometry(D3D_PRIMITIVE_TOPOLOGY primitive,
-           uint32_t vertices,
-           uint32_t stride,
-           ID3D11Buffer*);
-
-  void bind(const std::shared_ptr<Context>& ctx);
-  void unbind();
-
-  void draw();
-
- private:
-  D3D_PRIMITIVE_TOPOLOGY primitive_;
-  uint32_t vertices_;
-  uint32_t stride_;
-  const std::shared_ptr<ID3D11Buffer> buffer_;
-  std::shared_ptr<Context> ctx_;
-
-  DISALLOW_COPY_AND_ASSIGN(Geometry);
-};
-
-// Abstraction for a 2D layer within a composition.
-class Layer {
- public:
-  Layer(const std::shared_ptr<Device>& device, bool flip);
-  virtual ~Layer();
-
-  void attach(const std::shared_ptr<Composition>&);
-
-  // Uses normalized 0-1.0 coordinates.
-  virtual void move(float x, float y, float width, float height);
-
-  virtual void tick(double t);
-  virtual void render(const std::shared_ptr<Context>& ctx) = 0;
-
-  Rect bounds() const;
-
-  std::shared_ptr<Composition> composition() const;
-
- protected:
-  // Helper method for derived classes to draw a textured-quad.
-  void render_texture(const std::shared_ptr<Context>& ctx,
-                      const std::shared_ptr<Texture2D>& texture);
-
-  const std::shared_ptr<Device> device_;
-  const bool flip_;
-
-  Rect bounds_;
-  std::shared_ptr<Geometry> geometry_;
-  std::shared_ptr<Effect> effect_;
-
- private:
-  std::weak_ptr<Composition> composition_;
-
-  DISALLOW_COPY_AND_ASSIGN(Layer);
-};
-
-// A collection of layers. Will render 1-N layers to a D3D11 device.
-class Composition : public std::enable_shared_from_this<Composition> {
- public:
-  Composition(const std::shared_ptr<Device>& device,
-              int width = 0,
-              int height = 0);
-
-  int width() const { return width_; }
-  int height() const { return height_; }
-
-  double fps() const;
-  double time() const;
-
-  bool is_vsync() const;
-
-  void tick(double);
-  void render(const std::shared_ptr<Context>&);
-
-  void add_layer(const std::shared_ptr<Layer>& layer);
-  bool remove_layer(const std::shared_ptr<Layer>& layer);
-  void resize(bool vsync, int width, int height);
-
- private:
-  int width_;
-  int height_;
-  uint32_t frame_;
-  int64_t fps_start_;
-  double fps_;
-  double time_;
-  bool vsync_;
-
-  const std::shared_ptr<Device> device_;
-  std::vector<std::shared_ptr<Layer>> layers_;
-
-  DISALLOW_COPY_AND_ASSIGN(Composition);
-};
-
-class FrameBuffer {
- public:
-  explicit FrameBuffer(const std::shared_ptr<Device>& device);
-
-  // Called in response to CEF's OnAcceleratedPaint notification.
-  void on_paint(void* shared_handle);
-
-  // Returns what should be considered the front buffer.
-  std::shared_ptr<Texture2D> texture() const { return shared_buffer_; }
-
- private:
-  const std::shared_ptr<Device> device_;
-  std::shared_ptr<Texture2D> shared_buffer_;
-
-  DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
-};
-
-}  // namespace d3d11
-}  // namespace client
-
-#endif  // CEF_TESTS_CEFCLIENT_BROWSER_OSR_D3D11_WIN_H_
diff --git a/src/tests/cefclient/browser/osr_dragdrop_win.cc b/src/tests/cefclient/browser/osr_dragdrop_win.cc
index cdd95b8..512134f 100644
--- a/src/tests/cefclient/browser/osr_dragdrop_win.cc
+++ b/src/tests/cefclient/browser/osr_dragdrop_win.cc
@@ -24,23 +24,29 @@
 
 DWORD DragOperationToDropEffect(CefRenderHandler::DragOperation allowed_ops) {
   DWORD effect = DROPEFFECT_NONE;
-  if (allowed_ops & DRAG_OPERATION_COPY)
+  if (allowed_ops & DRAG_OPERATION_COPY) {
     effect |= DROPEFFECT_COPY;
-  if (allowed_ops & DRAG_OPERATION_LINK)
+  }
+  if (allowed_ops & DRAG_OPERATION_LINK) {
     effect |= DROPEFFECT_LINK;
-  if (allowed_ops & DRAG_OPERATION_MOVE)
+  }
+  if (allowed_ops & DRAG_OPERATION_MOVE) {
     effect |= DROPEFFECT_MOVE;
+  }
   return effect;
 }
 
 CefRenderHandler::DragOperationsMask DropEffectToDragOperation(DWORD effect) {
   DWORD operation = DRAG_OPERATION_NONE;
-  if (effect & DROPEFFECT_COPY)
+  if (effect & DROPEFFECT_COPY) {
     operation |= DRAG_OPERATION_COPY;
-  if (effect & DROPEFFECT_LINK)
+  }
+  if (effect & DROPEFFECT_LINK) {
     operation |= DRAG_OPERATION_LINK;
-  if (effect & DROPEFFECT_MOVE)
+  }
+  if (effect & DROPEFFECT_MOVE) {
     operation |= DRAG_OPERATION_MOVE;
+  }
   return static_cast<CefRenderHandler::DragOperationsMask>(operation);
 }
 
@@ -62,7 +68,7 @@
 
   storage->hGlobal = handle;
   storage->tymed = TYMED_HGLOBAL;
-  storage->pUnkForRelease = NULL;
+  storage->pUnkForRelease = nullptr;
 }
 
 template <typename T>
@@ -86,15 +92,16 @@
 
   storage->tymed = TYMED_HGLOBAL;
   storage->hGlobal = hdata;
-  storage->pUnkForRelease = NULL;
+  storage->pUnkForRelease = nullptr;
 }
 
 // Helper method for converting from text/html to MS CF_HTML.
 // Documentation for the CF_HTML format is available at
 // http://msdn.microsoft.com/en-us/library/aa767917(VS.85).aspx
 std::string HtmlToCFHtml(const std::string& html, const std::string& base_url) {
-  if (html.empty())
+  if (html.empty()) {
     return std::string();
+  }
 
 #define MAX_DIGITS 10
 #define MAKE_NUMBER_FORMAT_1(digits) MAKE_NUMBER_FORMAT_2(digits)
@@ -202,7 +209,7 @@
   size_t frag_start = std::string::npos;
   size_t frag_end = std::string::npos;
 
-  CFHtmlExtractMetadata(cf_html, base_url, NULL, &frag_start, &frag_end);
+  CFHtmlExtractMetadata(cf_html, base_url, nullptr, &frag_start, &frag_end);
 
   if (html && frag_start != std::string::npos &&
       frag_end != std::string::npos) {
@@ -221,7 +228,7 @@
   const int kMaxDataObjects = 10;
   FORMATETC fmtetcs[kMaxDataObjects];
   STGMEDIUM stgmeds[kMaxDataObjects];
-  FORMATETC fmtetc = {0, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
+  FORMATETC fmtetc = {0, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
   int curr_index = 0;
   CefString text = drag_data->GetFragmentText();
   if (!text.empty()) {
@@ -249,13 +256,13 @@
     curr_index++;
   }
 
-  size_t bufferSize = drag_data->GetFileContents(NULL);
+  size_t bufferSize = drag_data->GetFileContents(nullptr);
   if (bufferSize) {
     CefRefPtr<BytesWriteHandler> handler = new BytesWriteHandler(bufferSize);
     CefRefPtr<CefStreamWriter> writer =
         CefStreamWriter::CreateForHandler(handler.get());
     drag_data->GetFileContents(writer);
-    DCHECK_EQ(handler->GetDataSize(), static_cast<int64>(bufferSize));
+    DCHECK_EQ(handler->GetDataSize(), static_cast<int64_t>(bufferSize));
     CefString fileName = drag_data->GetFileName();
     GetStorageForFileDescriptor(&stgmeds[curr_index], fileName.ToWString());
     fmtetc.cfFormat = file_desc_format;
@@ -279,8 +286,9 @@
   CefRefPtr<CefDragData> drag_data = CefDragData::Create();
   IEnumFORMATETC* enumFormats = nullptr;
   HRESULT res = data_object->EnumFormatEtc(DATADIR_GET, &enumFormats);
-  if (res != S_OK)
+  if (res != S_OK) {
     return drag_data;
+  }
   enumFormats->Reset();
   const int kCelt = 10;
 
@@ -294,8 +302,9 @@
       if (!(format == CF_UNICODETEXT || format == CF_TEXT ||
             format == moz_url_format || format == html_format ||
             format == CF_HDROP) ||
-          rgelt[i].tymed != TYMED_HGLOBAL)
+          rgelt[i].tymed != TYMED_HGLOBAL) {
         continue;
+      }
       STGMEDIUM medium;
       if (data_object->GetData(&rgelt[i], &medium) == S_OK) {
         if (!medium.hGlobal) {
@@ -336,18 +345,21 @@
           const unsigned num_files = DragQueryFileW(hdrop, 0xffffffff, 0, 0);
           for (unsigned int x = 0; x < num_files; ++x) {
             wchar_t filename[kMaxFilenameLen];
-            if (!DragQueryFileW(hdrop, x, filename, kMaxFilenameLen))
+            if (!DragQueryFileW(hdrop, x, filename, kMaxFilenameLen)) {
               continue;
+            }
             WCHAR* name = wcsrchr(filename, '\\');
             drag_data->AddFile(filename, (name ? name + 1 : filename));
           }
         }
-        if (medium.hGlobal)
+        if (medium.hGlobal) {
           GlobalUnlock(medium.hGlobal);
-        if (format == CF_HDROP)
+        }
+        if (format == CF_HDROP) {
           DragFinish((HDROP)hGlobal);
-        else
+        } else {
           ReleaseStgMedium(&medium);
+        }
       }
     }
   } while (res == S_OK);
@@ -366,8 +378,9 @@
                                  DWORD key_state,
                                  POINTL cursor_position,
                                  DWORD* effect) {
-  if (!callback_)
+  if (!callback_) {
     return E_UNEXPECTED;
+  }
 
   CefRefPtr<CefDragData> drag_data = current_drag_data_;
   if (!drag_data) {
@@ -394,8 +407,9 @@
     current_drag_data_ = drag_data->Clone();
     current_drag_data_->ResetFileContents();
     HRESULT res = DoDragDrop(dataObject, dropSource, effect, &resEffect);
-    if (res != DRAGDROP_S_DROP)
+    if (res != DRAGDROP_S_DROP) {
       resEffect = DROPEFFECT_NONE;
+    }
     current_drag_data_ = nullptr;
   }
   return DropEffectToDragOperation(resEffect);
@@ -404,8 +418,9 @@
 HRESULT DropTargetWin::DragOver(DWORD key_state,
                                 POINTL cursor_position,
                                 DWORD* effect) {
-  if (!callback_)
+  if (!callback_) {
     return E_UNEXPECTED;
+  }
   CefMouseEvent ev = ToMouseEvent(cursor_position, key_state, hWnd_);
   CefBrowserHost::DragOperationsMask mask = DropEffectToDragOperation(*effect);
   mask = callback_->OnDragOver(ev, mask);
@@ -414,8 +429,9 @@
 }
 
 HRESULT DropTargetWin::DragLeave() {
-  if (!callback_)
+  if (!callback_) {
     return E_UNEXPECTED;
+  }
   callback_->OnDragLeave();
   return S_OK;
 }
@@ -424,8 +440,9 @@
                             DWORD key_state,
                             POINTL cursor_position,
                             DWORD* effect) {
-  if (!callback_)
+  if (!callback_) {
     return E_UNEXPECTED;
+  }
   CefMouseEvent ev = ToMouseEvent(cursor_position, key_state, hWnd_);
   CefBrowserHost::DragOperationsMask mask = DropEffectToDragOperation(*effect);
   mask = callback_->OnDrop(ev, mask);
@@ -458,8 +475,9 @@
     UINT cfmt,
     FORMATETC* afmt,
     IEnumFORMATETC** ppEnumFormatEtc) {
-  if (cfmt == 0 || afmt == 0 || ppEnumFormatEtc == 0)
+  if (cfmt == 0 || afmt == 0 || ppEnumFormatEtc == 0) {
     return E_INVALIDARG;
+  }
 
   *ppEnumFormatEtc = new DragEnumFormatEtc(afmt, cfmt);
 
@@ -479,8 +497,9 @@
   }
 
   // store result
-  if (pceltFetched != 0)
+  if (pceltFetched != 0) {
     *pceltFetched = copied;
+  }
 
   // did we copy all that was requested?
   return (copied == celt) ? S_OK : S_FALSE;
@@ -522,8 +541,9 @@
 DragEnumFormatEtc::~DragEnumFormatEtc() {
   // first free any DVTARGETDEVICE structures
   for (ULONG i = 0; i < m_nNumFormats; i++) {
-    if (m_pFormatEtc[i].ptd)
+    if (m_pFormatEtc[i].ptd) {
       CoTaskMemFree(m_pFormatEtc[i].ptd);
+    }
   }
 
   // now free the main array
@@ -559,7 +579,7 @@
 
 HRESULT DataObjectWin::GetCanonicalFormatEtc(FORMATETC* pFormatEct,
                                              FORMATETC* pFormatEtcOut) {
-  pFormatEtcOut->ptd = NULL;
+  pFormatEtcOut->ptd = nullptr;
   return E_NOTIMPL;
 }
 
@@ -594,8 +614,9 @@
   int idx;
 
   // try to match the specified FORMATETC with one of our supported formats
-  if ((idx = LookupFormatEtc(pFormatEtc)) == -1)
+  if ((idx = LookupFormatEtc(pFormatEtc)) == -1) {
     return DV_E_FORMATETC;
+  }
 
   // found a match - transfer data into supplied storage medium
   pMedium->tymed = m_pFormatEtc[idx].tymed;
diff --git a/src/tests/cefclient/browser/osr_dragdrop_win.h b/src/tests/cefclient/browser/osr_dragdrop_win.h
index caf9613..29ef260 100644
--- a/src/tests/cefclient/browser/osr_dragdrop_win.h
+++ b/src/tests/cefclient/browser/osr_dragdrop_win.h
@@ -37,17 +37,19 @@
     AddRef();                                                       \
     return S_OK;                                                    \
   }
-#define IUNKNOWN_IMPLEMENTATION                     \
-  ULONG __stdcall AddRef() { return ++ref_count_; } \
-  ULONG __stdcall Release() {                       \
-    if (--ref_count_ == 0) {                        \
-      delete this;                                  \
-      return 0U;                                    \
-    }                                               \
-    return ref_count_;                              \
-  }                                                 \
-                                                    \
- protected:                                         \
+#define IUNKNOWN_IMPLEMENTATION \
+  ULONG __stdcall AddRef() {    \
+    return ++ref_count_;        \
+  }                             \
+  ULONG __stdcall Release() {   \
+    if (--ref_count_ == 0) {    \
+      delete this;              \
+      return 0U;                \
+    }                           \
+    return ref_count_;          \
+  }                             \
+                                \
+ protected:                     \
   ULONG ref_count_;
 
 class DropTargetWin : public IDropTarget {
diff --git a/src/tests/cefclient/browser/osr_ime_handler_win.cc b/src/tests/cefclient/browser/osr_ime_handler_win.cc
index aac4d3d..115c2fe 100644
--- a/src/tests/cefclient/browser/osr_ime_handler_win.cc
+++ b/src/tests/cefclient/browser/osr_ime_handler_win.cc
@@ -14,10 +14,12 @@
 #include "tests/shared/browser/main_message_loop.h"
 #include "tests/shared/browser/util_win.h"
 
-#define ColorUNDERLINE 0xFF000000  // Black SkColor value for underline,
-                                   // same as Blink.
-#define ColorBKCOLOR 0x00000000    // White SkColor value for background,
-                                   // same as Blink.
+#define ColorUNDERLINE \
+  0xFF000000  // Black SkColor value for underline,
+              // same as Blink.
+#define ColorBKCOLOR \
+  0x00000000  // White SkColor value for background,
+              // same as Blink.
 
 namespace client {
 
@@ -33,23 +35,26 @@
 // to get the target range that's selected by the user in the current
 // composition string.
 void GetCompositionSelectionRange(HIMC imc,
-                                  int* target_start,
-                                  int* target_end) {
-  int attribute_size = ::ImmGetCompositionString(imc, GCS_COMPATTR, NULL, 0);
+                                  uint32_t* target_start,
+                                  uint32_t* target_end) {
+  uint32_t attribute_size =
+      ::ImmGetCompositionString(imc, GCS_COMPATTR, nullptr, 0);
   if (attribute_size > 0) {
-    int start = 0;
-    int end = 0;
+    uint32_t start = 0;
+    uint32_t end = 0;
     std::vector<char> attribute_data(attribute_size);
 
     ::ImmGetCompositionString(imc, GCS_COMPATTR, &attribute_data[0],
                               attribute_size);
     for (start = 0; start < attribute_size; ++start) {
-      if (IsSelectionAttribute(attribute_data[start]))
+      if (IsSelectionAttribute(attribute_data[start])) {
         break;
+      }
     }
     for (end = start; end < attribute_size; ++end) {
-      if (!IsSelectionAttribute(attribute_data[end]))
+      if (!IsSelectionAttribute(attribute_data[end])) {
         break;
+      }
     }
 
     *target_start = start;
@@ -61,18 +66,18 @@
 // underlines information of the current composition string.
 void GetCompositionUnderlines(
     HIMC imc,
-    int target_start,
-    int target_end,
+    uint32_t target_start,
+    uint32_t target_end,
     std::vector<CefCompositionUnderline>& underlines) {
-  int clause_size = ::ImmGetCompositionString(imc, GCS_COMPCLAUSE, NULL, 0);
-  int clause_length = clause_size / sizeof(uint32);
+  int clause_size = ::ImmGetCompositionString(imc, GCS_COMPCLAUSE, nullptr, 0);
+  int clause_length = clause_size / sizeof(uint32_t);
   if (clause_length) {
-    std::vector<uint32> clause_data(clause_length);
+    std::vector<uint32_t> clause_data(clause_length);
 
     ::ImmGetCompositionString(imc, GCS_COMPCLAUSE, &clause_data[0],
                               clause_size);
     for (int i = 0; i < clause_length - 1; ++i) {
-      cef_composition_underline_t underline;
+      cef_composition_underline_t underline = {};
       underline.range.from = clause_data[i];
       underline.range.to = clause_data[i + 1];
       underline.color = ColorUNDERLINE;
@@ -95,7 +100,7 @@
     : is_composing_(false),
       input_language_id_(LANG_USER_DEFAULT),
       system_caret_(false),
-      cursor_index_(-1),
+      cursor_index_(std::numeric_limits<uint32_t>::max()),
       hwnd_(hwnd) {
   ime_rect_ = {-1, -1, 0, 0};
 }
@@ -131,8 +136,9 @@
   if (PRIMARYLANGID(input_language_id_) == LANG_CHINESE ||
       PRIMARYLANGID(input_language_id_) == LANG_JAPANESE) {
     if (!system_caret_) {
-      if (::CreateCaret(hwnd_, NULL, 1, 1))
+      if (::CreateCaret(hwnd_, nullptr, 1, 1)) {
         system_caret_ = true;
+      }
     }
   }
 }
@@ -147,24 +153,28 @@
 
 void OsrImeHandlerWin::MoveImeWindow() {
   // Does nothing when the target window has no input focus.
-  if (GetFocus() != hwnd_)
+  if (GetFocus() != hwnd_) {
     return;
+  }
 
   CefRect rc = ime_rect_;
-  int location = cursor_index_;
+  uint32_t location = cursor_index_;
 
   // If location is not specified fall back to the composition range start.
-  if (location == -1)
+  if (location == std::numeric_limits<uint32_t>::max()) {
     location = composition_range_.from;
+  }
 
   // Offset location by the composition range start if required.
-  if (location >= composition_range_.from)
+  if (location >= composition_range_.from) {
     location -= composition_range_.from;
+  }
 
-  if (location < static_cast<int>(composition_bounds_.size()))
+  if (location < composition_bounds_.size()) {
     rc = composition_bounds_[location];
-  else
+  } else {
     return;
+  }
 
   HIMC imc = ::ImmGetContext(hwnd_);
   if (imc) {
@@ -231,7 +241,7 @@
 void OsrImeHandlerWin::ResetComposition() {
   // Reset the composition status.
   is_composing_ = false;
-  cursor_index_ = -1;
+  cursor_index_ = std::numeric_limits<uint32_t>::max();
 }
 
 void OsrImeHandlerWin::GetCompositionInfo(
@@ -244,13 +254,14 @@
   // convert them into underlines and selection range respectively.
   underlines.clear();
 
-  int length = static_cast<int>(composition_text.length());
+  uint32_t length = static_cast<uint32_t>(composition_text.length());
 
   // Find out the range selected by the user.
-  int target_start = length;
-  int target_end = length;
-  if (lparam & GCS_COMPATTR)
+  uint32_t target_start = length;
+  uint32_t target_end = length;
+  if (lparam & GCS_COMPATTR) {
     GetCompositionSelectionRange(imc, &target_start, &target_end);
+  }
 
   // Retrieve the selection range information. If CS_NOMOVECARET is specified
   // it means the cursor should not be moved and we therefore place the caret at
@@ -262,15 +273,16 @@
   if (!(lparam & CS_NOMOVECARET) && (lparam & GCS_CURSORPOS)) {
     // IMM32 does not support non-zero-width selection in a composition. So
     // always use the caret position as selection range.
-    int cursor = ::ImmGetCompositionString(imc, GCS_CURSORPOS, NULL, 0);
+    int cursor = ::ImmGetCompositionString(imc, GCS_CURSORPOS, nullptr, 0);
     composition_start = cursor;
   } else {
     composition_start = 0;
   }
 
   // Retrieve the clause segmentations and convert them to underlines.
-  if (lparam & GCS_COMPCLAUSE)
+  if (lparam & GCS_COMPCLAUSE) {
     GetCompositionUnderlines(imc, target_start, target_end, underlines);
+  }
 
   // Set default underlines in case there is no clause information.
   if (!underlines.size()) {
@@ -302,13 +314,15 @@
                                  WPARAM lparam,
                                  int type,
                                  CefString& result) {
-  if (!(lparam & type))
+  if (!(lparam & type)) {
     return false;
-  LONG string_size = ::ImmGetCompositionString(imc, type, NULL, 0);
-  if (string_size <= 0)
+  }
+  LONG string_size = ::ImmGetCompositionString(imc, type, nullptr, 0);
+  if (string_size <= 0) {
     return false;
+  }
 
-  // For trailing NULL - ImmGetCompositionString excludes that.
+  // For trailing nullptr - ImmGetCompositionString excludes that.
   string_size += sizeof(WCHAR);
 
   std::vector<wchar_t> buffer(string_size);
@@ -354,7 +368,7 @@
 
 void OsrImeHandlerWin::DisableIME() {
   CleanupComposition();
-  ::ImmAssociateContextEx(hwnd_, NULL, 0);
+  ::ImmAssociateContextEx(hwnd_, nullptr, 0);
 }
 
 void OsrImeHandlerWin::CancelIME() {
@@ -370,10 +384,10 @@
 
 void OsrImeHandlerWin::EnableIME() {
   // Load the default IME context.
-  ::ImmAssociateContextEx(hwnd_, NULL, IACE_DEFAULT);
+  ::ImmAssociateContextEx(hwnd_, nullptr, IACE_DEFAULT);
 }
 
-void OsrImeHandlerWin::UpdateCaretPosition(int index) {
+void OsrImeHandlerWin::UpdateCaretPosition(uint32_t index) {
   // Save the caret position.
   cursor_index_ = index;
   // Move the IME window.
diff --git a/src/tests/cefclient/browser/osr_ime_handler_win.h b/src/tests/cefclient/browser/osr_ime_handler_win.h
index 8758985..de5b92f 100644
--- a/src/tests/cefclient/browser/osr_ime_handler_win.h
+++ b/src/tests/cefclient/browser/osr_ime_handler_win.h
@@ -60,7 +60,7 @@
   virtual void CancelIME();
 
   // Updates the IME caret position of the given window.
-  void UpdateCaretPosition(int index);
+  void UpdateCaretPosition(uint32_t index);
 
   // Updates the composition range. |selected_range| is the range of characters
   // that have been selected. |character_bounds| is the bounds of each character
@@ -100,7 +100,7 @@
   CefRect ime_rect_;
 
   // The current cursor index in composition string.
-  int cursor_index_;
+  uint32_t cursor_index_;
 
   // The composition range in the string. This may be used to determine the
   // offset in composition bounds.
diff --git a/src/tests/cefclient/browser/osr_render_handler_win.cc b/src/tests/cefclient/browser/osr_render_handler_win.cc
index 8fa9b16..525b7a2 100644
--- a/src/tests/cefclient/browser/osr_render_handler_win.cc
+++ b/src/tests/cefclient/browser/osr_render_handler_win.cc
@@ -4,7 +4,7 @@
 
 #include "tests/cefclient/browser/osr_render_handler_win.h"
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "include/wrapper/cef_helpers.h"
 #include "tests/shared/browser/util_win.h"
@@ -69,9 +69,9 @@
 
   // Trigger again after the necessary delay to maintain the desired frame rate.
   CefPostDelayedTask(TID_UI,
-                     base::Bind(&OsrRenderHandlerWin::TriggerBeginFrame,
-                                weak_factory_.GetWeakPtr(), now, delay_us),
-                     int64(offset / 1000.0));
+                     base::BindOnce(&OsrRenderHandlerWin::TriggerBeginFrame,
+                                    weak_factory_.GetWeakPtr(), now, delay_us),
+                     static_cast<int64_t>(offset / 1000.0));
 
   if (settings_.external_begin_frame_enabled && browser_) {
     // We're running the BeginFrame timer. Trigger rendering via
diff --git a/src/tests/cefclient/browser/osr_render_handler_win_d3d11.cc b/src/tests/cefclient/browser/osr_render_handler_win_d3d11.cc
index 67f4d90..93de15a 100644
--- a/src/tests/cefclient/browser/osr_render_handler_win_d3d11.cc
+++ b/src/tests/cefclient/browser/osr_render_handler_win_d3d11.cc
@@ -4,7 +4,7 @@
 
 #include "tests/cefclient/browser/osr_render_handler_win_d3d11.h"
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "include/wrapper/cef_helpers.h"
 #include "tests/shared/browser/util_win.h"
@@ -35,32 +35,40 @@
 
 void PopupLayer::set_bounds(const CefRect& bounds) {
   const auto comp = composition();
-  if (!comp)
+  if (!comp) {
     return;
+  }
 
   const auto outer_width = comp->width();
   const auto outer_height = comp->height();
-  if (outer_width == 0 || outer_height == 0)
+  if (outer_width == 0 || outer_height == 0) {
     return;
+  }
 
   original_bounds_ = bounds;
   bounds_ = bounds;
 
   // If x or y are negative, move them to 0.
-  if (bounds_.x < 0)
+  if (bounds_.x < 0) {
     bounds_.x = 0;
-  if (bounds_.y < 0)
+  }
+  if (bounds_.y < 0) {
     bounds_.y = 0;
+  }
   // If popup goes outside the view, try to reposition origin
-  if (bounds_.x + bounds_.width > outer_width)
+  if (bounds_.x + bounds_.width > outer_width) {
     bounds_.x = outer_width - bounds_.width;
-  if (bounds_.y + bounds_.height > outer_height)
+  }
+  if (bounds_.y + bounds_.height > outer_height) {
     bounds_.y = outer_height - bounds_.height;
+  }
   // If x or y became negative, move them to 0 again.
-  if (bounds_.x < 0)
+  if (bounds_.x < 0) {
     bounds_.x = 0;
-  if (bounds_.y < 0)
+  }
+  if (bounds_.y < 0) {
     bounds_.y = 0;
+  }
 
   const auto x = bounds_.x / float(outer_width);
   const auto y = bounds_.y / float(outer_height);
@@ -82,14 +90,16 @@
   // Create a D3D11 device instance.
   device_ = d3d11::Device::create();
   DCHECK(device_);
-  if (!device_)
+  if (!device_) {
     return false;
+  }
 
   // Create a D3D11 swapchain for the window.
   swap_chain_ = device_->create_swapchain(hwnd());
   DCHECK(swap_chain_);
-  if (!swap_chain_)
+  if (!swap_chain_) {
     return false;
+  }
 
   // Create the browser layer.
   browser_layer_ = std::make_shared<BrowserLayer>(device_);
@@ -124,15 +134,17 @@
 
 int OsrRenderHandlerWinD3D11::GetPopupXOffset() const {
   CEF_REQUIRE_UI_THREAD();
-  if (popup_layer_)
+  if (popup_layer_) {
     return popup_layer_->xoffset();
+  }
   return 0;
 }
 
 int OsrRenderHandlerWinD3D11::GetPopupYOffset() const {
   CEF_REQUIRE_UI_THREAD();
-  if (popup_layer_)
+  if (popup_layer_) {
     return popup_layer_->yoffset();
+  }
   return 0;
 }
 
diff --git a/src/tests/cefclient/browser/osr_render_handler_win_d3d11.h b/src/tests/cefclient/browser/osr_render_handler_win_d3d11.h
index a72b1dd..cd0b8d5 100644
--- a/src/tests/cefclient/browser/osr_render_handler_win_d3d11.h
+++ b/src/tests/cefclient/browser/osr_render_handler_win_d3d11.h
@@ -16,7 +16,7 @@
  public:
   explicit BrowserLayer(const std::shared_ptr<d3d11::Device>& device);
 
-  void render(const std::shared_ptr<d3d11::Context>& ctx) OVERRIDE;
+  void render(const std::shared_ptr<d3d11::Context>& ctx) override;
 
   void on_paint(void* share_handle);
 
@@ -54,26 +54,26 @@
   // May fail if D3D11 cannot be initialized.
   bool Initialize(CefRefPtr<CefBrowser> browser, int width, int height);
 
-  void SetSpin(float spinX, float spinY) OVERRIDE;
-  void IncrementSpin(float spinDX, float spinDY) OVERRIDE;
-  bool IsOverPopupWidget(int x, int y) const OVERRIDE;
-  int GetPopupXOffset() const OVERRIDE;
-  int GetPopupYOffset() const OVERRIDE;
-  void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) OVERRIDE;
-  void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect) OVERRIDE;
+  void SetSpin(float spinX, float spinY) override;
+  void IncrementSpin(float spinDX, float spinDY) override;
+  bool IsOverPopupWidget(int x, int y) const override;
+  int GetPopupXOffset() const override;
+  int GetPopupYOffset() const override;
+  void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) override;
+  void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect) override;
   void OnPaint(CefRefPtr<CefBrowser> browser,
                CefRenderHandler::PaintElementType type,
                const CefRenderHandler::RectList& dirtyRects,
                const void* buffer,
                int width,
-               int height) OVERRIDE;
+               int height) override;
   void OnAcceleratedPaint(CefRefPtr<CefBrowser> browser,
                           CefRenderHandler::PaintElementType type,
                           const CefRenderHandler::RectList& dirtyRects,
-                          void* share_handle) OVERRIDE;
+                          void* share_handle) override;
 
  private:
-  void Render() OVERRIDE;
+  void Render() override;
 
   uint64_t start_time_;
   std::shared_ptr<d3d11::Device> device_;
diff --git a/src/tests/cefclient/browser/osr_render_handler_win_gl.cc b/src/tests/cefclient/browser/osr_render_handler_win_gl.cc
index 6bfe1ea..506214b 100644
--- a/src/tests/cefclient/browser/osr_render_handler_win_gl.cc
+++ b/src/tests/cefclient/browser/osr_render_handler_win_gl.cc
@@ -4,7 +4,7 @@
 
 #include "tests/cefclient/browser/osr_render_handler_win_gl.h"
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "include/wrapper/cef_helpers.h"
 #include "tests/shared/browser/util_win.h"
@@ -18,12 +18,11 @@
  public:
   ScopedGLContext(HDC hdc, HGLRC hglrc, bool swap_buffers)
       : hdc_(hdc), swap_buffers_(swap_buffers) {
-    BOOL result = wglMakeCurrent(hdc, hglrc);
-    ALLOW_UNUSED_LOCAL(result);
+    [[maybe_unused]] BOOL result = wglMakeCurrent(hdc, hglrc);
     DCHECK(result);
   }
   ~ScopedGLContext() {
-    BOOL result = wglMakeCurrent(NULL, NULL);
+    BOOL result = wglMakeCurrent(nullptr, nullptr);
     DCHECK(result);
     if (swap_buffers_) {
       result = SwapBuffers(hdc_);
@@ -43,8 +42,8 @@
     HWND hwnd)
     : OsrRenderHandlerWin(settings, hwnd),
       renderer_(settings),
-      hdc_(NULL),
-      hrc_(NULL),
+      hdc_(nullptr),
+      hrc_(nullptr),
       painting_popup_(false) {}
 
 void OsrRenderHandlerWinGL::Initialize(CefRefPtr<CefBrowser> browser) {
@@ -188,14 +187,13 @@
 
   if (IsWindow(hwnd())) {
     // wglDeleteContext will make the context not current before deleting it.
-    BOOL result = wglDeleteContext(hrc_);
-    ALLOW_UNUSED_LOCAL(result);
+    [[maybe_unused]] BOOL result = wglDeleteContext(hrc_);
     DCHECK(result);
     ReleaseDC(hwnd(), hdc_);
   }
 
-  hdc_ = NULL;
-  hrc_ = NULL;
+  hdc_ = nullptr;
+  hrc_ = nullptr;
 }
 
 }  // namespace client
diff --git a/src/tests/cefclient/browser/osr_render_handler_win_gl.h b/src/tests/cefclient/browser/osr_render_handler_win_gl.h
index 606bc70..88ff092 100644
--- a/src/tests/cefclient/browser/osr_render_handler_win_gl.h
+++ b/src/tests/cefclient/browser/osr_render_handler_win_gl.h
@@ -19,26 +19,26 @@
   // Must be called immediately after object creation.
   void Initialize(CefRefPtr<CefBrowser> browser);
 
-  void SetSpin(float spinX, float spinY) OVERRIDE;
-  void IncrementSpin(float spinDX, float spinDY) OVERRIDE;
-  bool IsOverPopupWidget(int x, int y) const OVERRIDE;
-  int GetPopupXOffset() const OVERRIDE;
-  int GetPopupYOffset() const OVERRIDE;
-  void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) OVERRIDE;
-  void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect) OVERRIDE;
+  void SetSpin(float spinX, float spinY) override;
+  void IncrementSpin(float spinDX, float spinDY) override;
+  bool IsOverPopupWidget(int x, int y) const override;
+  int GetPopupXOffset() const override;
+  int GetPopupYOffset() const override;
+  void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) override;
+  void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect) override;
   void OnPaint(CefRefPtr<CefBrowser> browser,
                CefRenderHandler::PaintElementType type,
                const CefRenderHandler::RectList& dirtyRects,
                const void* buffer,
                int width,
-               int height) OVERRIDE;
+               int height) override;
   void OnAcceleratedPaint(CefRefPtr<CefBrowser> browser,
                           CefRenderHandler::PaintElementType type,
                           const CefRenderHandler::RectList& dirtyRects,
-                          void* share_handle) OVERRIDE;
+                          void* share_handle) override;
 
  private:
-  void Render() OVERRIDE;
+  void Render() override;
 
   void EnableGL();
   void DisableGL();
diff --git a/src/tests/cefclient/browser/osr_renderer.cc b/src/tests/cefclient/browser/osr_renderer.cc
index de2473a..ef08804 100644
--- a/src/tests/cefclient/browser/osr_renderer.cc
+++ b/src/tests/cefclient/browser/osr_renderer.cc
@@ -6,7 +6,8 @@
 
 #if defined(OS_WIN)
 #include <gl/gl.h>
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
+#define GL_SILENCE_DEPRECATION
 #include <OpenGL/gl.h>
 #elif defined(OS_LINUX)
 #include <GL/gl.h>
@@ -54,8 +55,9 @@
 }
 
 void OsrRenderer::Initialize() {
-  if (initialized_)
+  if (initialized_) {
     return;
+  }
 
   glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
   VERIFY_NO_ERROR;
@@ -94,13 +96,15 @@
 }
 
 void OsrRenderer::Cleanup() {
-  if (texture_id_ != 0)
+  if (texture_id_ != 0) {
     glDeleteTextures(1, &texture_id_);
+  }
 }
 
 void OsrRenderer::Render() {
-  if (view_width_ == 0 || view_height_ == 0)
+  if (view_width_ == 0 || view_height_ == 0) {
     return;
+  }
 
   DCHECK(initialized_);
 
@@ -246,8 +250,9 @@
 
 void OsrRenderer::OnPopupSize(CefRefPtr<CefBrowser> browser,
                               const CefRect& rect) {
-  if (rect.width <= 0 || rect.height <= 0)
+  if (rect.width <= 0 || rect.height <= 0) {
     return;
+  }
   original_popup_rect_ = rect;
   popup_rect_ = GetPopupRectInWebView(original_popup_rect_);
 }
@@ -255,20 +260,26 @@
 CefRect OsrRenderer::GetPopupRectInWebView(const CefRect& original_rect) {
   CefRect rc(original_rect);
   // if x or y are negative, move them to 0.
-  if (rc.x < 0)
+  if (rc.x < 0) {
     rc.x = 0;
-  if (rc.y < 0)
+  }
+  if (rc.y < 0) {
     rc.y = 0;
+  }
   // if popup goes outside the view, try to reposition origin
-  if (rc.x + rc.width > view_width_)
+  if (rc.x + rc.width > view_width_) {
     rc.x = view_width_ - rc.width;
-  if (rc.y + rc.height > view_height_)
+  }
+  if (rc.y + rc.height > view_height_) {
     rc.y = view_height_ - rc.height;
+  }
   // if x or y became negative, move them to 0 again.
-  if (rc.x < 0)
+  if (rc.x < 0) {
     rc.x = 0;
-  if (rc.y < 0)
+  }
+  if (rc.y < 0) {
     rc.y = 0;
+  }
   return rc;
 }
 
@@ -283,8 +294,9 @@
                           const void* buffer,
                           int width,
                           int height) {
-  if (!initialized_)
+  if (!initialized_) {
     Initialize();
+  }
 
   if (IsTransparent()) {
     // Enable alpha blending.
@@ -307,8 +319,9 @@
     view_width_ = width;
     view_height_ = height;
 
-    if (settings_.show_update_rect)
+    if (settings_.show_update_rect) {
       update_rect_ = dirtyRects[0];
+    }
 
     glPixelStorei(GL_UNPACK_ROW_LENGTH, view_width_);
     VERIFY_NO_ERROR;
@@ -357,10 +370,12 @@
       skip_rows = -y;
       y = 0;
     }
-    if (x + w > view_width_)
+    if (x + w > view_width_) {
       w -= x + w - view_width_;
-    if (y + h > view_height_)
+    }
+    if (y + h > view_height_) {
       h -= y + h - view_height_;
+    }
 
     // Update the popup rectangle.
     glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
diff --git a/src/tests/cefclient/browser/osr_renderer_settings.h b/src/tests/cefclient/browser/osr_renderer_settings.h
index 535b10a..cbd560b 100644
--- a/src/tests/cefclient/browser/osr_renderer_settings.h
+++ b/src/tests/cefclient/browser/osr_renderer_settings.h
@@ -13,7 +13,7 @@
 struct OsrRendererSettings {
   OsrRendererSettings()
       : show_update_rect(false),
-        background_color(CefColorSetARGB(255, 255, 255, 255)),
+        background_color(0),
         shared_texture_enabled(false),
         external_begin_frame_enabled(false),
         begin_frame_rate(0) {}
diff --git a/src/tests/cefclient/browser/osr_window_win.cc b/src/tests/cefclient/browser/osr_window_win.cc
index 66b220d..ed80052 100644
--- a/src/tests/cefclient/browser/osr_window_win.cc
+++ b/src/tests/cefclient/browser/osr_window_win.cc
@@ -85,7 +85,7 @@
                            const OsrRendererSettings& settings)
     : delegate_(delegate),
       settings_(settings),
-      hwnd_(NULL),
+      hwnd_(nullptr),
       device_scale_factor_(0),
       hidden_(false),
       last_mouse_pos_(),
@@ -127,7 +127,7 @@
     CreateBrowserHelper* helper =
         new CreateBrowserHelper(parent_hwnd, rect, handler, startup_url,
                                 settings, extra_info, request_context, this);
-    CefPostTask(TID_UI, base::Bind(CreateBrowserWithHelper, helper));
+    CefPostTask(TID_UI, base::BindOnce(CreateBrowserWithHelper, helper));
     return;
   }
 
@@ -158,8 +158,8 @@
                              size_t height) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&OsrWindowWin::ShowPopup, this, parent_hwnd,
-                                   x, y, width, height));
+    CefPostTask(TID_UI, base::BindOnce(&OsrWindowWin::ShowPopup, this,
+                                       parent_hwnd, x, y, width, height));
     return;
   }
 
@@ -184,16 +184,18 @@
 void OsrWindowWin::Show() {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&OsrWindowWin::Show, this));
+    CefPostTask(TID_UI, base::BindOnce(&OsrWindowWin::Show, this));
     return;
   }
 
-  if (!browser_)
+  if (!browser_) {
     return;
+  }
 
   // Show the native window if not currently visible.
-  if (hwnd_ && !::IsWindowVisible(hwnd_))
+  if (hwnd_ && !::IsWindowVisible(hwnd_)) {
     ShowWindow(hwnd_, SW_SHOW);
+  }
 
   if (hidden_) {
     // Set the browser as visible.
@@ -202,21 +204,22 @@
   }
 
   // Give focus to the browser.
-  browser_->GetHost()->SendFocusEvent(true);
+  browser_->GetHost()->SetFocus(true);
 }
 
 void OsrWindowWin::Hide() {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&OsrWindowWin::Hide, this));
+    CefPostTask(TID_UI, base::BindOnce(&OsrWindowWin::Hide, this));
     return;
   }
 
-  if (!browser_)
+  if (!browser_) {
     return;
+  }
 
   // Remove focus from the browser.
-  browser_->GetHost()->SendFocusEvent(false);
+  browser_->GetHost()->SetFocus(false);
 
   if (!hidden_) {
     // Set the browser as hidden.
@@ -228,14 +231,14 @@
 void OsrWindowWin::SetBounds(int x, int y, size_t width, size_t height) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&OsrWindowWin::SetBounds, this, x, y, width,
-                                   height));
+    CefPostTask(TID_UI, base::BindOnce(&OsrWindowWin::SetBounds, this, x, y,
+                                       width, height));
     return;
   }
 
   if (hwnd_) {
     // Set the browser window bounds.
-    ::SetWindowPos(hwnd_, NULL, x, y, static_cast<int>(width),
+    ::SetWindowPos(hwnd_, nullptr, x, y, static_cast<int>(width),
                    static_cast<int>(height), SWP_NOZORDER);
   }
 }
@@ -243,7 +246,7 @@
 void OsrWindowWin::SetFocus() {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&OsrWindowWin::SetFocus, this));
+    CefPostTask(TID_UI, base::BindOnce(&OsrWindowWin::SetFocus, this));
     return;
   }
 
@@ -256,13 +259,14 @@
 void OsrWindowWin::SetDeviceScaleFactor(float device_scale_factor) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&OsrWindowWin::SetDeviceScaleFactor, this,
-                                   device_scale_factor));
+    CefPostTask(TID_UI, base::BindOnce(&OsrWindowWin::SetDeviceScaleFactor,
+                                       this, device_scale_factor));
     return;
   }
 
-  if (device_scale_factor == device_scale_factor_)
+  if (device_scale_factor == device_scale_factor_) {
     return;
+  }
 
   device_scale_factor_ = device_scale_factor;
   if (browser_) {
@@ -277,7 +281,7 @@
   DCHECK(parent_hwnd);
   DCHECK(!::IsRectEmpty(&rect));
 
-  HINSTANCE hInst = ::GetModuleHandle(NULL);
+  HINSTANCE hInst = ::GetModuleHandle(nullptr);
 
   const cef_color_t background_color = MainContext::Get()->GetBackgroundColor();
   const HBRUSH background_brush = CreateSolidBrush(
@@ -318,8 +322,9 @@
   ime_handler_.reset(new OsrImeHandlerWin(hwnd_));
 
   // Enable Touch Events if requested
-  if (client::MainContext::Get()->TouchEventsEnabled())
+  if (client::MainContext::Get()->TouchEventsEnabled()) {
     RegisterTouchWindow(hwnd_, 0);
+  }
 
   // Notify the window owner.
   NotifyNativeWindowCreated(hwnd_);
@@ -327,7 +332,7 @@
 
 void OsrWindowWin::Destroy() {
   CEF_REQUIRE_UI_THREAD();
-  DCHECK(hwnd_ != NULL);
+  DCHECK(hwnd_ != nullptr);
 
 #if defined(CEF_USE_ATL)
   // Revoke/delete the drag&drop handler.
@@ -340,14 +345,14 @@
   // Destroy the native window.
   ::DestroyWindow(hwnd_);
   ime_handler_.reset();
-  hwnd_ = NULL;
+  hwnd_ = nullptr;
 }
 
 void OsrWindowWin::NotifyNativeWindowCreated(HWND hwnd) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
     MAIN_POST_CLOSURE(
-        base::Bind(&OsrWindowWin::NotifyNativeWindowCreated, this, hwnd));
+        base::BindOnce(&OsrWindowWin::NotifyNativeWindowCreated, this, hwnd));
     return;
   }
 
@@ -359,8 +364,9 @@
                                     HBRUSH background_brush) {
   // Only register the class one time.
   static bool class_registered = false;
-  if (class_registered)
+  if (class_registered) {
     return;
+  }
   class_registered = true;
 
   WNDCLASSEX wcex;
@@ -371,10 +377,10 @@
   wcex.cbClsExtra = 0;
   wcex.cbWndExtra = 0;
   wcex.hInstance = hInstance;
-  wcex.hIcon = NULL;
-  wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
+  wcex.hIcon = nullptr;
+  wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
   wcex.hbrBackground = background_brush;
-  wcex.lpszMenuName = NULL;
+  wcex.lpszMenuName = nullptr;
   wcex.lpszClassName = kWndClass;
   wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
 
@@ -412,8 +418,7 @@
       // Send the text to the browser. The |replacement_range| and
       // |relative_cursor_pos| params are not used on Windows, so provide
       // default invalid values.
-      browser_->GetHost()->ImeCommitText(cTextStr,
-                                         CefRange(UINT32_MAX, UINT32_MAX), 0);
+      browser_->GetHost()->ImeCommitText(cTextStr, CefRange::InvalidRange(), 0);
       ime_handler_->ResetComposition();
       // Continue reading the composition string - Japanese IMEs send both
       // GCS_RESULTSTR and GCS_COMPSTR.
@@ -427,7 +432,7 @@
       // Send the composition string to the browser. The |replacement_range|
       // param is not used on Windows, so provide a default invalid value.
       browser_->GetHost()->ImeSetComposition(
-          cTextStr, underlines, CefRange(UINT32_MAX, UINT32_MAX),
+          cTextStr, underlines, CefRange::InvalidRange(),
           CefRange(composition_start,
                    static_cast<int>(composition_start + cTextStr.length())));
 
@@ -458,8 +463,9 @@
   CEF_REQUIRE_UI_THREAD();
 
   OsrWindowWin* self = GetUserDataPtr<OsrWindowWin*>(hWnd);
-  if (!self)
+  if (!self) {
     return DefWindowProc(hWnd, message, wParam, lParam);
+  }
 
   // We want to handle IME events before the OS does any default handling.
   switch (message) {
@@ -490,8 +496,9 @@
               static_cast<IAccessible*>(self->accessibility_root_));
         } else {
           // Notify the renderer to enable accessibility.
-          if (self->browser_ && self->browser_->GetHost())
+          if (self->browser_ && self->browser_->GetHost()) {
             self->browser_->GetHost()->SetAccessibilityState(STATE_ENABLED);
+          }
         }
       }
     } break;
@@ -536,8 +543,9 @@
       return 0;
 
     case WM_ERASEBKGND:
-      if (self->OnEraseBkgnd())
+      if (self->OnEraseBkgnd()) {
         break;
+      }
       // Don't erase the background.
       return 0;
 
@@ -546,14 +554,15 @@
     // intutive, complete and simpler to code.
     // https://msdn.microsoft.com/en-us/library/hh454903(v=vs.85).aspx
     case WM_TOUCH:
-      if (self->OnTouchEvent(message, wParam, lParam))
+      if (self->OnTouchEvent(message, wParam, lParam)) {
         return 0;
+      }
       break;
 
     case WM_NCDESTROY:
       // Clear the reference to |self|.
-      SetUserDataPtr(hWnd, NULL);
-      self->hwnd_ = NULL;
+      SetUserDataPtr(hWnd, nullptr);
+      self->hwnd_ = nullptr;
       break;
   }
 
@@ -561,12 +570,14 @@
 }
 
 void OsrWindowWin::OnMouseEvent(UINT message, WPARAM wParam, LPARAM lParam) {
-  if (IsMouseEventFromTouch(message))
+  if (IsMouseEventFromTouch(message)) {
     return;
+  }
 
   CefRefPtr<CefBrowserHost> browser_host;
-  if (browser_)
+  if (browser_) {
     browser_host = browser_->GetHost();
+  }
 
   LONG currentTime = 0;
   bool cancelPreviousClick = false;
@@ -635,8 +646,9 @@
     case WM_LBUTTONUP:
     case WM_RBUTTONUP:
     case WM_MBUTTONUP:
-      if (GetCapture() == hwnd_)
+      if (GetCapture() == hwnd_) {
         ReleaseCapture();
+      }
       if (mouse_rotation_) {
         // End rotation effect.
         mouse_rotation_ = false;
@@ -732,8 +744,9 @@
       if (browser_host) {
         POINT screen_point = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
         HWND scrolled_wnd = ::WindowFromPoint(screen_point);
-        if (scrolled_wnd != hwnd_)
+        if (scrolled_wnd != hwnd_) {
           break;
+        }
 
         ScreenToClient(hwnd_, &screen_point);
         int delta = GET_WHEEL_DELTA_WPARAM(wParam);
@@ -756,26 +769,31 @@
   // Keep |client_rect_| up to date.
   ::GetClientRect(hwnd_, &client_rect_);
 
-  if (browser_)
+  if (browser_) {
     browser_->GetHost()->WasResized();
+  }
 }
 
 void OsrWindowWin::OnFocus(bool setFocus) {
-  if (browser_)
-    browser_->GetHost()->SendFocusEvent(setFocus);
+  if (browser_) {
+    browser_->GetHost()->SetFocus(setFocus);
+  }
 }
 
 void OsrWindowWin::OnCaptureLost() {
-  if (mouse_rotation_)
+  if (mouse_rotation_) {
     return;
+  }
 
-  if (browser_)
+  if (browser_) {
     browser_->GetHost()->SendCaptureLostEvent();
+  }
 }
 
 void OsrWindowWin::OnKeyEvent(UINT message, WPARAM wParam, LPARAM lParam) {
-  if (!browser_)
+  if (!browser_) {
     return;
+  }
 
   CefKeyEvent event;
   event.windows_key_code = wParam;
@@ -783,12 +801,13 @@
   event.is_system_key = message == WM_SYSCHAR || message == WM_SYSKEYDOWN ||
                         message == WM_SYSKEYUP;
 
-  if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
+  if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN) {
     event.type = KEYEVENT_RAWKEYDOWN;
-  else if (message == WM_KEYUP || message == WM_SYSKEYUP)
+  } else if (message == WM_KEYUP || message == WM_SYSKEYUP) {
     event.type = KEYEVENT_KEYUP;
-  else
+  } else {
     event.type = KEYEVENT_CHAR;
+  }
   event.modifiers = GetCefKeyboardModifiers(wParam, lParam);
 
   // mimic alt-gr check behaviour from
@@ -801,10 +820,12 @@
     // https://docs.microsoft.com/en-gb/windows/win32/api/winuser/nf-winuser-vkkeyscanexw
     // ... high-order byte contains the shift state,
     // which can be a combination of the following flag bits.
+    // 1 Either SHIFT key is pressed.
     // 2 Either CTRL key is pressed.
     // 4 Either ALT key is pressed.
     SHORT scan_res = ::VkKeyScanExW(wParam, current_layout);
-    if (((scan_res >> 8) & 0xFF) == (2 | 4)) {  // ctrl-alt pressed
+    constexpr auto ctrlAlt = (2 | 4);
+    if (((scan_res >> 8) & ctrlAlt) == ctrlAlt) {  // ctrl-alt pressed
       event.modifiers &= ~(EVENTFLAG_CONTROL_DOWN | EVENTFLAG_ALT_DOWN);
       event.modifiers |= EVENTFLAG_ALTGR_DOWN;
     }
@@ -820,8 +841,9 @@
   BeginPaint(hwnd_, &ps);
   EndPaint(hwnd_, &ps);
 
-  if (browser_)
+  if (browser_) {
     browser_->GetHost()->Invalidate(PET_VIEW);
+  }
 }
 
 bool OsrWindowWin::OnEraseBkgnd() {
@@ -833,8 +855,9 @@
   // Handle touch events on Windows.
   int num_points = LOWORD(wParam);
   // Chromium only supports upto 16 touch points.
-  if (num_points < 0 || num_points > 16)
+  if (num_points < 0 || num_points > 16) {
     return false;
+  }
   std::unique_ptr<TOUCHINPUT[]> input(new TOUCHINPUT[num_points]);
   if (GetTouchInputInfo(reinterpret_cast<HTOUCHINPUT>(lParam), num_points,
                         input.get(), sizeof(TOUCHINPUT))) {
@@ -850,8 +873,9 @@
         // ignore touch events in the non-client area.
         LPARAM l_param_ht = MAKELPARAM(point.x, point.y);
         LRESULT hittest = SendMessage(hwnd_, WM_NCHITTEST, 0, l_param_ht);
-        if (hittest != HTCLIENT)
+        if (hittest != HTCLIENT) {
           return false;
+        }
       }
 
       ScreenToClient(hwnd_, &point);
@@ -876,8 +900,9 @@
       touch_event.modifiers = 0;
 
       // Notify the browser of touch event
-      if (browser_)
+      if (browser_) {
         browser_->GetHost()->SendTouchEvent(touch_event);
+      }
     }
     CloseTouchInputHandle(reinterpret_cast<HTOUCHINPUT>(lParam));
     return true;
@@ -887,8 +912,9 @@
 }
 
 bool OsrWindowWin::IsOverPopupWidget(int x, int y) const {
-  if (!render_handler_)
+  if (!render_handler_) {
     return false;
+  }
   return render_handler_->IsOverPopupWidget(x, y);
 }
 
@@ -921,7 +947,7 @@
   if (hwnd_) {
     // Show the browser window. Called asynchronously so that the browser has
     // time to create associated internal objects.
-    CefPostTask(TID_UI, base::Bind(&OsrWindowWin::Show, this));
+    CefPostTask(TID_UI, base::BindOnce(&OsrWindowWin::Show, this));
   }
 }
 
@@ -948,12 +974,14 @@
   rect.x = rect.y = 0;
   rect.width = DeviceToLogical(client_rect_.right - client_rect_.left,
                                device_scale_factor_);
-  if (rect.width == 0)
+  if (rect.width == 0) {
     rect.width = 1;
+  }
   rect.height = DeviceToLogical(client_rect_.bottom - client_rect_.top,
                                 device_scale_factor_);
-  if (rect.height == 0)
+  if (rect.height == 0) {
     rect.height = 1;
+  }
 }
 
 bool OsrWindowWin::GetScreenPoint(CefRefPtr<CefBrowser> browser,
@@ -964,10 +992,11 @@
   CEF_REQUIRE_UI_THREAD();
   DCHECK_GT(device_scale_factor_, 0);
 
-  if (!::IsWindow(hwnd_))
+  if (!::IsWindow(hwnd_)) {
     return false;
+  }
 
-  // Convert the point from view coordinates to actual screen coordinates.
+  // Convert from view DIP coordinates to screen device (pixel) coordinates.
   POINT screen_pt = {LogicalToDevice(viewX, device_scale_factor_),
                      LogicalToDevice(viewY, device_scale_factor_)};
   ClientToScreen(hwnd_, &screen_pt);
@@ -981,8 +1010,9 @@
   CEF_REQUIRE_UI_THREAD();
   DCHECK_GT(device_scale_factor_, 0);
 
-  if (!::IsWindow(hwnd_))
+  if (!::IsWindow(hwnd_)) {
     return false;
+  }
 
   CefRect view_rect;
   GetViewRect(browser, view_rect);
@@ -1027,14 +1057,15 @@
 
 void OsrWindowWin::OnCursorChange(CefRefPtr<CefBrowser> browser,
                                   CefCursorHandle cursor,
-                                  CefRenderHandler::CursorType type,
+                                  cef_cursor_type_t type,
                                   const CefCursorInfo& custom_cursor_info) {
   CEF_REQUIRE_UI_THREAD();
 
-  if (!::IsWindow(hwnd_))
+  if (!::IsWindow(hwnd_)) {
     return;
+  }
 
-  // Change the plugin window's cursor.
+  // Change the window's cursor.
   SetClassLongPtr(hwnd_, GCLP_HCURSOR,
                   static_cast<LONG>(reinterpret_cast<LONG_PTR>(cursor)));
   SetCursor(cursor);
@@ -1049,8 +1080,9 @@
   CEF_REQUIRE_UI_THREAD();
 
 #if defined(CEF_USE_ATL)
-  if (!drop_target_)
+  if (!drop_target_) {
     return false;
+  }
 
   current_drag_op_ = DRAG_OPERATION_NONE;
   CefBrowserHost::DragOperationsMask result =
@@ -1151,8 +1183,9 @@
 }
 
 void OsrWindowWin::OnDragLeave() {
-  if (browser_)
+  if (browser_) {
     browser_->GetHost()->DragTargetDragLeave();
+  }
 }
 
 CefBrowserHost::DragOperationsMask OsrWindowWin::OnDrop(
diff --git a/src/tests/cefclient/browser/osr_window_win.h b/src/tests/cefclient/browser/osr_window_win.h
index 0955ebc..fea8ec4 100644
--- a/src/tests/cefclient/browser/osr_window_win.h
+++ b/src/tests/cefclient/browser/osr_window_win.h
@@ -6,7 +6,7 @@
 #define CEF_TESTS_CEFCLIENT_BROWSER_OSR_WINDOW_WIN_H_
 #pragma once
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/base/cef_ref_counted.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "include/wrapper/cef_helpers.h"
@@ -108,62 +108,62 @@
   void ApplyPopupOffset(int& x, int& y) const;
 
   // ClientHandlerOsr::OsrDelegate methods.
-  void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  bool GetRootScreenRect(CefRefPtr<CefBrowser> browser, CefRect& rect) OVERRIDE;
-  void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) OVERRIDE;
+  void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
+  void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
+  bool GetRootScreenRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override;
+  void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override;
   bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
                       int viewX,
                       int viewY,
                       int& screenX,
-                      int& screenY) OVERRIDE;
+                      int& screenY) override;
   bool GetScreenInfo(CefRefPtr<CefBrowser> browser,
-                     CefScreenInfo& screen_info) OVERRIDE;
-  void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) OVERRIDE;
-  void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect) OVERRIDE;
+                     CefScreenInfo& screen_info) override;
+  void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) override;
+  void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect) override;
   void OnPaint(CefRefPtr<CefBrowser> browser,
                CefRenderHandler::PaintElementType type,
                const CefRenderHandler::RectList& dirtyRects,
                const void* buffer,
                int width,
-               int height) OVERRIDE;
+               int height) override;
   void OnAcceleratedPaint(CefRefPtr<CefBrowser> browser,
                           CefRenderHandler::PaintElementType type,
                           const CefRenderHandler::RectList& dirtyRects,
-                          void* share_handle) OVERRIDE;
+                          void* share_handle) override;
   void OnCursorChange(CefRefPtr<CefBrowser> browser,
                       CefCursorHandle cursor,
-                      CefRenderHandler::CursorType type,
-                      const CefCursorInfo& custom_cursor_info) OVERRIDE;
+                      cef_cursor_type_t type,
+                      const CefCursorInfo& custom_cursor_info) override;
   bool StartDragging(CefRefPtr<CefBrowser> browser,
                      CefRefPtr<CefDragData> drag_data,
                      CefRenderHandler::DragOperationsMask allowed_ops,
                      int x,
-                     int y) OVERRIDE;
+                     int y) override;
   void UpdateDragCursor(CefRefPtr<CefBrowser> browser,
-                        CefRenderHandler::DragOperation operation) OVERRIDE;
+                        CefRenderHandler::DragOperation operation) override;
   void OnImeCompositionRangeChanged(
       CefRefPtr<CefBrowser> browser,
       const CefRange& selection_range,
-      const CefRenderHandler::RectList& character_bounds) OVERRIDE;
+      const CefRenderHandler::RectList& character_bounds) override;
 
-  void UpdateAccessibilityTree(CefRefPtr<CefValue> value) OVERRIDE;
+  void UpdateAccessibilityTree(CefRefPtr<CefValue> value) override;
 
-  void UpdateAccessibilityLocation(CefRefPtr<CefValue> value) OVERRIDE;
+  void UpdateAccessibilityLocation(CefRefPtr<CefValue> value) override;
 
 #if defined(CEF_USE_ATL)
   // OsrDragEvents methods.
   CefBrowserHost::DragOperationsMask OnDragEnter(
       CefRefPtr<CefDragData> drag_data,
       CefMouseEvent ev,
-      CefBrowserHost::DragOperationsMask effect) OVERRIDE;
+      CefBrowserHost::DragOperationsMask effect) override;
   CefBrowserHost::DragOperationsMask OnDragOver(
       CefMouseEvent ev,
-      CefBrowserHost::DragOperationsMask effect) OVERRIDE;
-  void OnDragLeave() OVERRIDE;
+      CefBrowserHost::DragOperationsMask effect) override;
+  void OnDragLeave() override;
   CefBrowserHost::DragOperationsMask OnDrop(
       CefMouseEvent ev,
-      CefBrowserHost::DragOperationsMask effect) OVERRIDE;
+      CefBrowserHost::DragOperationsMask effect) override;
 #endif  // defined(CEF_USE_ATL)
 
   void EnsureRenderHandler();
@@ -173,10 +173,10 @@
 
   const OsrRendererSettings settings_;
   HWND hwnd_;
-  scoped_ptr<OsrRenderHandlerWin> render_handler_;
+  std::unique_ptr<OsrRenderHandlerWin> render_handler_;
 
   // Class that encapsulates IMM32 APIs and controls IMEs attached to a window.
-  scoped_ptr<OsrImeHandlerWin> ime_handler_;
+  std::unique_ptr<OsrImeHandlerWin> ime_handler_;
 
   RECT client_rect_;
   float device_scale_factor_;
@@ -189,7 +189,7 @@
 
   // Class that abstracts the accessibility information received from the
   // renderer.
-  scoped_ptr<OsrAccessibilityHelper> accessibility_handler_;
+  std::unique_ptr<OsrAccessibilityHelper> accessibility_handler_;
   IAccessible* accessibility_root_;
 #endif
 
diff --git a/src/tests/cefclient/browser/preferences_test.cc b/src/tests/cefclient/browser/preferences_test.cc
index 5659a81..f3b69ba 100644
--- a/src/tests/cefclient/browser/preferences_test.cc
+++ b/src/tests/cefclient/browser/preferences_test.cc
@@ -46,16 +46,17 @@
   // Called due to cefQuery execution in preferences.html.
   bool OnQuery(CefRefPtr<CefBrowser> browser,
                CefRefPtr<CefFrame> frame,
-               int64 query_id,
+               int64_t query_id,
                const CefString& request,
                bool persistent,
-               CefRefPtr<Callback> callback) OVERRIDE {
+               CefRefPtr<Callback> callback) override {
     CEF_REQUIRE_UI_THREAD();
 
     // Only handle messages from the test URL.
     const std::string& url = frame->GetURL();
-    if (!test_runner::IsTestURL(url, kTestUrlPath))
+    if (!test_runner::IsTestURL(url, kTestUrlPath)) {
       return false;
+    }
 
     // Parse |request| as a JSON dictionary.
     CefRefPtr<CefDictionaryValue> request_dict = ParseJSON(request);
@@ -65,16 +66,18 @@
     }
 
     // Verify the "name" key.
-    if (!VerifyKey(request_dict, kNameKey, VTYPE_STRING, callback))
+    if (!VerifyKey(request_dict, kNameKey, VTYPE_STRING, callback)) {
       return true;
+    }
 
     const std::string& message_name = request_dict->GetString(kNameKey);
     if (message_name == kNameValueGet) {
       // JavaScript is requesting a JSON representation of the preferences tree.
 
       // Verify the "include_defaults" key.
-      if (!VerifyKey(request_dict, kIncludeDefaultsKey, VTYPE_BOOL, callback))
+      if (!VerifyKey(request_dict, kIncludeDefaultsKey, VTYPE_BOOL, callback)) {
         return true;
+      }
 
       const bool include_defaults = request_dict->GetBool(kIncludeDefaultsKey);
 
@@ -86,8 +89,10 @@
       // specified JSON representation.
 
       // Verify the "preferences" key.
-      if (!VerifyKey(request_dict, kPreferencesKey, VTYPE_DICTIONARY, callback))
+      if (!VerifyKey(request_dict, kPreferencesKey, VTYPE_DICTIONARY,
+                     callback)) {
         return true;
+      }
 
       CefRefPtr<CefDictionaryValue> preferences =
           request_dict->GetDictionary(kPreferencesKey);
@@ -147,30 +152,34 @@
       ss << "Successfully changed " << changed_names.size() << " preferences; ";
       for (size_t i = 0; i < changed_names.size(); ++i) {
         ss << changed_names[i];
-        if (i < changed_names.size() - 1)
+        if (i < changed_names.size() - 1) {
           ss << ", ";
+        }
       }
       message = ss.str();
     }
 
     if (!success) {
       DCHECK(!error.empty());
-      if (!message.empty())
+      if (!message.empty()) {
         message += "\n";
+      }
       message += error;
     }
 
     if (changed_names.empty()) {
-      if (!message.empty())
+      if (!message.empty()) {
         message += "\n";
+      }
       message += "No preferences changed.";
     }
 
     // Return the message to the JavaScript caller.
-    if (success)
+    if (success) {
       callback->Success(message);
-    else
+    } else {
       callback->Failure(kPreferenceApplicationError, message);
+    }
   }
 
   // Execute |callback| with the global state dictionary as a JSON string.
@@ -206,8 +215,9 @@
   // Convert a JSON string to a dictionary value.
   static CefRefPtr<CefDictionaryValue> ParseJSON(const CefString& string) {
     CefRefPtr<CefValue> value = CefParseJSON(string, JSON_PARSER_RFC);
-    if (value.get() && value->GetType() == VTYPE_DICTIONARY)
+    if (value.get() && value->GetType() == VTYPE_DICTIONARY) {
       return value->GetDictionary();
+    }
     return nullptr;
   }
 
@@ -288,10 +298,11 @@
       const std::string& string_val = value->GetString();
       switch (existing_value->GetType()) {
         case VTYPE_BOOL:
-          if (string_val == "true" || string_val == "1")
+          if (string_val == "true" || string_val == "1") {
             value->SetBool(true);
-          else if (string_val == "false" || string_val == "0")
+          } else if (string_val == "false" || string_val == "0") {
             value->SetBool(false);
+          }
           break;
         case VTYPE_INT:
           value->SetInt(atoi(string_val.c_str()));
@@ -306,8 +317,9 @@
     }
 
     // Nothing to do if the value hasn't changed.
-    if (existing_value->IsEqual(value))
+    if (existing_value->IsEqual(value)) {
       return true;
+    }
 
     // Attempt to set the preference.
     CefString error_str;
diff --git a/src/tests/cefclient/browser/print_handler_gtk.cc b/src/tests/cefclient/browser/print_handler_gtk.cc
index 922c85b..bd924c9 100644
--- a/src/tests/cefclient/browser/print_handler_gtk.cc
+++ b/src/tests/cefclient/browser/print_handler_gtk.cc
@@ -5,12 +5,13 @@
 
 #include "tests/cefclient/browser/print_handler_gtk.h"
 
+#include <memory>
 #include <vector>
 
 #include <gtk/gtk.h>
 #include <gtk/gtkunixprint.h>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/base/cef_logging.h"
 #include "include/base/cef_macros.h"
 #include "include/wrapper/cef_helpers.h"
@@ -86,8 +87,9 @@
 // Lazily initialize the singleton instance.
 StickyPrintSettingGtk* GetLastUsedSettings() {
   static StickyPrintSettingGtk* settings = nullptr;
-  if (!settings)
+  if (!settings) {
     settings = new StickyPrintSettingGtk();
+  }
   return settings;
 }
 
@@ -95,7 +97,7 @@
 class GtkPrinterList {
  public:
   GtkPrinterList() : default_printer_(nullptr) {
-    gtk_enumerate_printers(SetPrinter, this, NULL, TRUE);
+    gtk_enumerate_printers(SetPrinter, this, nullptr, TRUE);
   }
 
   ~GtkPrinterList() {
@@ -105,16 +107,17 @@
     }
   }
 
-  // Can return NULL if there's no default printer. E.g. Printer on a laptop
+  // Can return nullptr if there's no default printer. E.g. Printer on a laptop
   // is "home_printer", but the laptop is at work.
   GtkPrinter* default_printer() { return default_printer_; }
 
-  // Can return NULL if the printer cannot be found due to:
+  // Can return nullptr if the printer cannot be found due to:
   // - Printer list out of sync with printer dialog UI.
   // - Querying for non-existant printers like 'Print to PDF'.
   GtkPrinter* GetPrinterWithName(const std::string& name) {
-    if (name.empty())
+    if (name.empty()) {
       return nullptr;
+    }
 
     for (std::vector<GtkPrinter*>::iterator it = printers_.begin();
          it < printers_.end(); ++it) {
@@ -130,8 +133,9 @@
   // Callback function used by gtk_enumerate_printers() to get all printer.
   static gboolean SetPrinter(GtkPrinter* printer, gpointer data) {
     GtkPrinterList* printer_list = reinterpret_cast<GtkPrinterList*>(data);
-    if (gtk_printer_is_default(printer))
+    if (gtk_printer_is_default(printer)) {
       printer_list->default_printer_ = printer;
+    }
 
     g_object_ref(printer);
     printer_list->printers_.push_back(printer);
@@ -225,8 +229,9 @@
 
   std::string device_name;
   const gchar* name = gtk_print_settings_get_printer(settings);
-  if (name)
+  if (name) {
     device_name = name;
+  }
   print_settings->SetDeviceName(device_name);
 
   CefSize physical_size_device_units;
@@ -272,30 +277,28 @@
                                           printable_area_device_units, true);
 }
 
-// Returns the GtkWindow* for the browser. Will return NULL when using the Views
-// framework.
+// Returns the GtkWindow* for the browser. Will return nullptr when using the
+// Views framework.
 GtkWindow* GetWindow(CefRefPtr<CefBrowser> browser) {
   scoped_refptr<RootWindow> root_window =
       RootWindow::GetForBrowser(browser->GetIdentifier());
-  if (root_window)
+  if (root_window) {
     return GTK_WINDOW(root_window->GetWindowHandle());
+  }
   return nullptr;
 }
 
-void RunCallback(base::Callback<void(GtkWindow*)> callback, GtkWindow* window) {
-  callback.Run(window);
-}
-
 void GetWindowAndContinue(CefRefPtr<CefBrowser> browser,
-                          base::Callback<void(GtkWindow*)> callback) {
+                          base::OnceCallback<void(GtkWindow*)> callback) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
-    MAIN_POST_CLOSURE(base::Bind(GetWindowAndContinue, browser, callback));
+    MAIN_POST_CLOSURE(
+        base::BindOnce(GetWindowAndContinue, browser, std::move(callback)));
     return;
   }
 
   GtkWindow* window = GetWindow(browser);
   if (window) {
-    CefPostTask(TID_UI, base::Bind(RunCallback, callback, window));
+    CefPostTask(TID_UI, base::BindOnce(std::move(callback), window));
   }
 }
 
@@ -388,8 +391,9 @@
         gtk_print_settings_set(gtk_settings_, kCUPSDuplex, cups_duplex_mode);
       }
 
-      if (!page_setup_)
+      if (!page_setup_) {
         page_setup_ = gtk_page_setup_new();
+      }
 
       gtk_print_settings_set_orientation(gtk_settings_,
                                          settings->IsLandscape()
@@ -410,9 +414,9 @@
     ScopedGdkThreadsEnter scoped_gdk_threads;
 
     // TODO(estade): We need a window title here.
-    dialog_ = gtk_print_unix_dialog_new(NULL, parent);
+    dialog_ = gtk_print_unix_dialog_new(nullptr, parent);
     g_signal_connect(dialog_, "delete-event",
-                     G_CALLBACK(gtk_widget_hide_on_delete), NULL);
+                     G_CALLBACK(gtk_widget_hide_on_delete), nullptr);
 
     // Set modal so user cannot focus the same tab and press print again.
     gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);
@@ -441,10 +445,11 @@
   bool OnPrintJob(const CefString& document_name,
                   const CefString& pdf_file_path,
                   CefRefPtr<CefPrintJobCallback> callback) {
-    // If |printer_| is NULL then somehow the GTK printer list changed out under
-    // us. In which case, just bail out.
-    if (!printer_)
+    // If |printer_| is nullptr then somehow the GTK printer list changed out
+    // under us. In which case, just bail out.
+    if (!printer_) {
       return false;
+    }
 
     ScopedGdkThreadsEnter scoped_gdk_threads;
 
@@ -456,8 +461,8 @@
     GtkPrintJob* print_job = gtk_print_job_new(
         document_name.ToString().c_str(), printer_, gtk_settings_, page_setup_);
     gtk_print_job_set_source_file(print_job, pdf_file_path.ToString().c_str(),
-                                  NULL);
-    gtk_print_job_send(print_job, OnJobCompletedThunk, this, NULL);
+                                  nullptr);
+    gtk_print_job_send(print_job, OnJobCompletedThunk, this, nullptr);
 
     return true;
   }
@@ -472,19 +477,22 @@
 
     switch (response_id) {
       case GTK_RESPONSE_OK: {
-        if (gtk_settings_)
+        if (gtk_settings_) {
           g_object_unref(gtk_settings_);
+        }
         gtk_settings_ =
             gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog_));
 
-        if (printer_)
+        if (printer_) {
           g_object_unref(printer_);
+        }
         printer_ = gtk_print_unix_dialog_get_selected_printer(
             GTK_PRINT_UNIX_DIALOG(dialog_));
         g_object_ref(printer_);
 
-        if (page_setup_)
+        if (page_setup_) {
           g_object_unref(page_setup_);
+        }
         page_setup_ = gtk_print_unix_dialog_get_page_setup(
             GTK_PRINT_UNIX_DIALOG(dialog_));
         g_object_ref(page_setup_);
@@ -539,12 +547,12 @@
     }
   }
 
-  void OnJobCompleted(GtkPrintJob* print_job, GError* error) {
+  void OnJobCompleted(GtkPrintJob* print_job, const GError* error) {
     // Continue() will result in a call to ClientPrintHandlerGtk::OnPrintReset
     // which deletes |this|. Execute it asnychronously so the call stack has a
     // chance to unwind.
-    CefPostTask(TID_UI, base::Bind(&CefPrintJobCallback::Continue,
-                                   job_callback_.get()));
+    CefPostTask(TID_UI, base::BindOnce(&CefPrintJobCallback::Continue,
+                                       job_callback_.get()));
     job_callback_ = nullptr;
   }
 
@@ -556,7 +564,7 @@
 
   static void OnJobCompletedThunk(GtkPrintJob* print_job,
                                   void* handler,
-                                  GError* error) {
+                                  const GError* error) {
     static_cast<PrintHandler*>(handler)->OnJobCompleted(print_job, error);
   }
 
@@ -574,23 +582,13 @@
 ClientPrintHandlerGtk::ClientPrintHandlerGtk() {}
 
 ClientPrintHandlerGtk::~ClientPrintHandlerGtk() {
-  DCHECK(print_handler_map_.empty());
+  DCHECK(!print_handler_);
 }
 
 void ClientPrintHandlerGtk::OnPrintStart(CefRefPtr<CefBrowser> browser) {
   CEF_REQUIRE_UI_THREAD();
-
-  const int browser_id = browser->GetIdentifier();
-
-#ifndef _NDEBUG
-  // Print handler should not already exist for the browser.
-  PrintHandlerMap::const_iterator it = print_handler_map_.find(browser_id);
-  DCHECK(it == print_handler_map_.end());
-#endif
-
-  // Create a new print handler.
-  PrintHandler* ph = new PrintHandler(browser);
-  print_handler_map_.insert(std::make_pair(browser_id, ph));
+  DCHECK(!print_handler_);
+  print_handler_.reset(new PrintHandler(browser));
 }
 
 void ClientPrintHandlerGtk::OnPrintSettings(
@@ -599,7 +597,7 @@
     bool get_defaults) {
   CEF_REQUIRE_UI_THREAD();
 
-  GetPrintHandler(browser)->OnPrintSettings(settings, get_defaults);
+  print_handler_->OnPrintSettings(settings, get_defaults);
 }
 
 bool ClientPrintHandlerGtk::OnPrintDialog(
@@ -608,10 +606,10 @@
     CefRefPtr<CefPrintDialogCallback> callback) {
   CEF_REQUIRE_UI_THREAD();
 
-  PrintHandler* print_handler = GetPrintHandler(browser);
-  GetWindowAndContinue(browser, base::Bind(&PrintHandler::OnPrintDialog,
-                                           base::Unretained(print_handler),
-                                           has_selection, callback));
+  GetWindowAndContinue(browser,
+                       base::BindOnce(&PrintHandler::OnPrintDialog,
+                                      base::Unretained(print_handler_.get()),
+                                      has_selection, callback));
   return true;
 }
 
@@ -622,22 +620,18 @@
     CefRefPtr<CefPrintJobCallback> callback) {
   CEF_REQUIRE_UI_THREAD();
 
-  return GetPrintHandler(browser)->OnPrintJob(document_name, pdf_file_path,
-                                              callback);
+  return print_handler_->OnPrintJob(document_name, pdf_file_path, callback);
 }
 
 void ClientPrintHandlerGtk::OnPrintReset(CefRefPtr<CefBrowser> browser) {
   CEF_REQUIRE_UI_THREAD();
 
   // Delete the print handler.
-  PrintHandlerMap::iterator it =
-      print_handler_map_.find(browser->GetIdentifier());
-  DCHECK(it != print_handler_map_.end());
-  delete it->second;
-  print_handler_map_.erase(it);
+  print_handler_.reset();
 }
 
-CefSize ClientPrintHandlerGtk::GetPdfPaperSize(int device_units_per_inch) {
+CefSize ClientPrintHandlerGtk::GetPdfPaperSize(CefRefPtr<CefBrowser> browser,
+                                               int device_units_per_inch) {
   CEF_REQUIRE_UI_THREAD();
 
   ScopedGdkThreadsEnter scoped_gdk_threads;
@@ -652,12 +646,4 @@
   return CefSize(width * device_units_per_inch, height * device_units_per_inch);
 }
 
-ClientPrintHandlerGtk::PrintHandler* ClientPrintHandlerGtk::GetPrintHandler(
-    CefRefPtr<CefBrowser> browser) {
-  PrintHandlerMap::const_iterator it =
-      print_handler_map_.find(browser->GetIdentifier());
-  DCHECK(it != print_handler_map_.end());
-  return it->second;
-}
-
 }  // namespace client
diff --git a/src/tests/cefclient/browser/print_handler_gtk.h b/src/tests/cefclient/browser/print_handler_gtk.h
index 857b8c7..6c38381 100644
--- a/src/tests/cefclient/browser/print_handler_gtk.h
+++ b/src/tests/cefclient/browser/print_handler_gtk.h
@@ -7,7 +7,7 @@
 #define CEF_TESTS_CEFCLIENT_BROWSER_PRINT_HANDLER_GTK_H_
 #pragma once
 
-#include <map>
+#include <memory>
 
 #include "include/cef_print_handler.h"
 
@@ -19,28 +19,25 @@
   virtual ~ClientPrintHandlerGtk();
 
   // CefPrintHandler methods.
-  void OnPrintStart(CefRefPtr<CefBrowser> browser) OVERRIDE;
+  void OnPrintStart(CefRefPtr<CefBrowser> browser) override;
   void OnPrintSettings(CefRefPtr<CefBrowser> browser,
                        CefRefPtr<CefPrintSettings> settings,
-                       bool get_defaults) OVERRIDE;
+                       bool get_defaults) override;
   bool OnPrintDialog(CefRefPtr<CefBrowser> browser,
                      bool has_selection,
-                     CefRefPtr<CefPrintDialogCallback> callback) OVERRIDE;
+                     CefRefPtr<CefPrintDialogCallback> callback) override;
   bool OnPrintJob(CefRefPtr<CefBrowser> browser,
                   const CefString& document_name,
                   const CefString& pdf_file_path,
-                  CefRefPtr<CefPrintJobCallback> callback) OVERRIDE;
-  void OnPrintReset(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  CefSize GetPdfPaperSize(int device_units_per_inch) OVERRIDE;
+                  CefRefPtr<CefPrintJobCallback> callback) override;
+  void OnPrintReset(CefRefPtr<CefBrowser> browser) override;
+  CefSize GetPdfPaperSize(CefRefPtr<CefBrowser> browser,
+                          int device_units_per_inch) override;
 
  private:
   // Print handler.
   struct PrintHandler;
-  PrintHandler* GetPrintHandler(CefRefPtr<CefBrowser> browser);
-
-  // Map of browser ID to print handler.
-  typedef std::map<int, PrintHandler*> PrintHandlerMap;
-  PrintHandlerMap print_handler_map_;
+  std::unique_ptr<PrintHandler> print_handler_;
 
   IMPLEMENT_REFCOUNTING(ClientPrintHandlerGtk);
   DISALLOW_COPY_AND_ASSIGN(ClientPrintHandlerGtk);
diff --git a/src/tests/cefclient/browser/resource.h b/src/tests/cefclient/browser/resource.h
index 6003d12..b32f3e3 100644
--- a/src/tests/cefclient/browser/resource.h
+++ b/src/tests/cefclient/browser/resource.h
@@ -27,9 +27,9 @@
 #define ID_TESTS_GETSOURCE 32700
 #define ID_TESTS_GETTEXT 32701
 #define ID_TESTS_OTHER_TESTS 32702
-#define ID_TESTS_PLUGIN_INFO 32703
-#define ID_TESTS_WINDOW_NEW 32704
-#define ID_TESTS_WINDOW_POPUP 32705
+#define ID_TESTS_WINDOW_NEW 32703
+#define ID_TESTS_WINDOW_POPUP 32704
+#define ID_TESTS_WINDOW_DIALOG 32705
 #define ID_TESTS_PRINT 32706
 #define ID_TESTS_REQUEST 32707
 #define ID_TESTS_TRACING_BEGIN 32708
@@ -44,31 +44,32 @@
 #define ID_TESTS_UNMUTE_AUDIO 32717
 #define ID_TESTS_LAST 32717
 #define IDC_STATIC -1
-#define IDS_BINDING_HTML 1000
-#define IDS_DIALOGS_HTML 1001
-#define IDS_DRAGGABLE_HTML 1002
-#define IDS_DRM_HTML 1003
-#define IDS_LOCALSTORAGE_HTML 1004
-#define IDS_LOGO_PNG 1005
-#define IDS_MEDIA_ROUTER_HTML 1006
-#define IDS_MENU_ICON_1X_PNG 1007
-#define IDS_MENU_ICON_2X_PNG 1008
-#define IDS_OSRTEST_HTML 1009
-#define IDS_OTHER_TESTS_HTML 1010
-#define IDS_PDF_HTML 1011
-#define IDS_PDF_PDF 1012
-#define IDS_PERFORMANCE_HTML 1013
-#define IDS_PERFORMANCE2_HTML 1014
-#define IDS_PREFERENCES_HTML 1015
-#define IDS_RESPONSE_FILTER_HTML 1016
-#define IDS_SERVER_HTML 1017
-#define IDS_TRANSPARENCY_HTML 1018
-#define IDS_URLREQUEST_HTML 1019
-#define IDS_WEBSOCKET_HTML 1020
-#define IDS_WINDOW_HTML 1021
-#define IDS_WINDOW_ICON_1X_PNG 1022
-#define IDS_WINDOW_ICON_2X_PNG 1023
-#define IDS_XMLHTTPREQUEST_HTML 1024
+#define IDS_BINARY_TRANSFER_HTML 1000
+#define IDS_BINDING_HTML 1001
+#define IDS_DIALOGS_HTML 1002
+#define IDS_DRAGGABLE_HTML 1003
+#define IDS_IPC_PERFORMANCE_HTML 1004
+#define IDS_LOCALSTORAGE_HTML 1005
+#define IDS_LOGO_PNG 1006
+#define IDS_MEDIA_ROUTER_HTML 1007
+#define IDS_MENU_ICON_1X_PNG 1008
+#define IDS_MENU_ICON_2X_PNG 1009
+#define IDS_OSRTEST_HTML 1010
+#define IDS_OTHER_TESTS_HTML 1011
+#define IDS_PDF_HTML 1012
+#define IDS_PDF_PDF 1013
+#define IDS_PERFORMANCE_HTML 1014
+#define IDS_PERFORMANCE2_HTML 1015
+#define IDS_PREFERENCES_HTML 1016
+#define IDS_RESPONSE_FILTER_HTML 1017
+#define IDS_SERVER_HTML 1018
+#define IDS_TRANSPARENCY_HTML 1019
+#define IDS_URLREQUEST_HTML 1020
+#define IDS_WEBSOCKET_HTML 1021
+#define IDS_WINDOW_HTML 1022
+#define IDS_WINDOW_ICON_1X_PNG 1023
+#define IDS_WINDOW_ICON_2X_PNG 1024
+#define IDS_XMLHTTPREQUEST_HTML 1025
 
 #define IDS_EXTENSIONS_SET_PAGE_COLOR_ICON_PNG 1030
 #define IDS_EXTENSIONS_SET_PAGE_COLOR_MANIFEST_JSON 1031
diff --git a/src/tests/cefclient/browser/resource_util_linux.cc b/src/tests/cefclient/browser/resource_util_linux.cc
index a7aa555..0acdd09 100644
--- a/src/tests/cefclient/browser/resource_util_linux.cc
+++ b/src/tests/cefclient/browser/resource_util_linux.cc
@@ -16,15 +16,17 @@
 
   // Retrieve the executable path.
   ssize_t len = readlink("/proc/self/exe", buff, sizeof(buff) - 1);
-  if (len == -1)
+  if (len == -1) {
     return false;
+  }
 
   buff[len] = 0;
 
   // Remove the executable name from the path.
   char* pos = strrchr(buff, '/');
-  if (!pos)
+  if (!pos) {
     return false;
+  }
 
   // Add "cefclient_files" to the path.
   strcpy(pos + 1, "cefclient_files");
diff --git a/src/tests/cefclient/browser/resource_util_win_idmap.cc b/src/tests/cefclient/browser/resource_util_win_idmap.cc
index 545ce49..17bb874 100644
--- a/src/tests/cefclient/browser/resource_util_win_idmap.cc
+++ b/src/tests/cefclient/browser/resource_util_win_idmap.cc
@@ -13,45 +13,46 @@
   static struct _resource_map {
     const char* name;
     int id;
-  } resource_map[] = {
-      {"binding.html", IDS_BINDING_HTML},
-      {"dialogs.html", IDS_DIALOGS_HTML},
-      {"draggable.html", IDS_DRAGGABLE_HTML},
-      {"drm.html", IDS_DRM_HTML},
-      {"extensions/set_page_color/icon.png",
-       IDS_EXTENSIONS_SET_PAGE_COLOR_ICON_PNG},
-      {"extensions/set_page_color/manifest.json",
-       IDS_EXTENSIONS_SET_PAGE_COLOR_MANIFEST_JSON},
-      {"extensions/set_page_color/popup.html",
-       IDS_EXTENSIONS_SET_PAGE_COLOR_POPUP_HTML},
-      {"extensions/set_page_color/popup.js",
-       IDS_EXTENSIONS_SET_PAGE_COLOR_POPUP_JS},
-      {"localstorage.html", IDS_LOCALSTORAGE_HTML},
-      {"logo.png", IDS_LOGO_PNG},
-      {"media_router.html", IDS_MEDIA_ROUTER_HTML},
-      {"menu_icon.1x.png", IDS_MENU_ICON_1X_PNG},
-      {"menu_icon.2x.png", IDS_MENU_ICON_2X_PNG},
-      {"osr_test.html", IDS_OSRTEST_HTML},
-      {"other_tests.html", IDS_OTHER_TESTS_HTML},
-      {"pdf.html", IDS_PDF_HTML},
-      {"pdf.pdf", IDS_PDF_PDF},
-      {"performance.html", IDS_PERFORMANCE_HTML},
-      {"performance2.html", IDS_PERFORMANCE2_HTML},
-      {"preferences.html", IDS_PREFERENCES_HTML},
-      {"response_filter.html", IDS_RESPONSE_FILTER_HTML},
-      {"server.html", IDS_SERVER_HTML},
-      {"transparency.html", IDS_TRANSPARENCY_HTML},
-      {"urlrequest.html", IDS_URLREQUEST_HTML},
-      {"websocket.html", IDS_WEBSOCKET_HTML},
-      {"window.html", IDS_WINDOW_HTML},
-      {"window_icon.1x.png", IDS_WINDOW_ICON_1X_PNG},
-      {"window_icon.2x.png", IDS_WINDOW_ICON_2X_PNG},
-      {"xmlhttprequest.html", IDS_XMLHTTPREQUEST_HTML},
-  };
+  } resource_map[] = {{"binary_transfer.html", IDS_BINARY_TRANSFER_HTML},
+                      {"binding.html", IDS_BINDING_HTML},
+                      {"dialogs.html", IDS_DIALOGS_HTML},
+                      {"draggable.html", IDS_DRAGGABLE_HTML},
+                      {"extensions/set_page_color/icon.png",
+                       IDS_EXTENSIONS_SET_PAGE_COLOR_ICON_PNG},
+                      {"extensions/set_page_color/manifest.json",
+                       IDS_EXTENSIONS_SET_PAGE_COLOR_MANIFEST_JSON},
+                      {"extensions/set_page_color/popup.html",
+                       IDS_EXTENSIONS_SET_PAGE_COLOR_POPUP_HTML},
+                      {"extensions/set_page_color/popup.js",
+                       IDS_EXTENSIONS_SET_PAGE_COLOR_POPUP_JS},
+                      {"ipc_performance.html", IDS_IPC_PERFORMANCE_HTML},
+                      {"localstorage.html", IDS_LOCALSTORAGE_HTML},
+                      {"logo.png", IDS_LOGO_PNG},
+                      {"media_router.html", IDS_MEDIA_ROUTER_HTML},
+                      {"menu_icon.1x.png", IDS_MENU_ICON_1X_PNG},
+                      {"menu_icon.2x.png", IDS_MENU_ICON_2X_PNG},
+                      {"osr_test.html", IDS_OSRTEST_HTML},
+                      {"other_tests.html", IDS_OTHER_TESTS_HTML},
+                      {"pdf.html", IDS_PDF_HTML},
+                      {"pdf.pdf", IDS_PDF_PDF},
+                      {"performance.html", IDS_PERFORMANCE_HTML},
+                      {"performance2.html", IDS_PERFORMANCE2_HTML},
+                      {"preferences.html", IDS_PREFERENCES_HTML},
+                      {"response_filter.html", IDS_RESPONSE_FILTER_HTML},
+                      {"server.html", IDS_SERVER_HTML},
+                      {"transparency.html", IDS_TRANSPARENCY_HTML},
+                      {"urlrequest.html", IDS_URLREQUEST_HTML},
+                      {"websocket.html", IDS_WEBSOCKET_HTML},
+                      {"window.html", IDS_WINDOW_HTML},
+                      {"window_icon.1x.png", IDS_WINDOW_ICON_1X_PNG},
+                      {"window_icon.2x.png", IDS_WINDOW_ICON_2X_PNG},
+                      {"xmlhttprequest.html", IDS_XMLHTTPREQUEST_HTML},
+                      {"xmlhttprequest.html", IDS_XMLHTTPREQUEST_HTML}};
 
   for (size_t i = 0; i < sizeof(resource_map) / sizeof(_resource_map); ++i) {
-    if (!strcmp(resource_map[i].name, resource_name))
+    if (!strcmp(resource_map[i].name, resource_name)) {
       return resource_map[i].id;
+    }
   }
 
   return 0;
diff --git a/src/tests/cefclient/browser/response_filter_test.cc b/src/tests/cefclient/browser/response_filter_test.cc
index 1832504..4e2e243 100644
--- a/src/tests/cefclient/browser/response_filter_test.cc
+++ b/src/tests/cefclient/browser/response_filter_test.cc
@@ -36,15 +36,16 @@
         replace_overflow_size_(0U),
         replace_count_(0U) {}
 
-  bool InitFilter() OVERRIDE {
+  bool InitFilter() override {
     const size_t find_size = sizeof(kFindString) - 1;
     const size_t replace_size = sizeof(kReplaceString) - 1;
 
     // Determine a reasonable amount of space for find/replace overflow. For
     // example, the amount of space required if the search string is
     // found/replaced 10 times (plus space for the count).
-    if (replace_size > find_size)
+    if (replace_size > find_size) {
       replace_overflow_size_ = (replace_size - find_size + 3) * 10;
+    }
 
     return true;
   }
@@ -54,7 +55,7 @@
                       size_t& data_in_read,
                       void* data_out,
                       size_t data_out_size,
-                      size_t& data_out_written) OVERRIDE {
+                      size_t& data_out_written) override {
     DCHECK((data_in_size == 0U && !data_in) || (data_in_size > 0U && data_in));
     DCHECK_EQ(data_in_read, 0U);
     DCHECK(data_out);
@@ -176,27 +177,29 @@
  public:
   PassThruResponseFilter() {}
 
-  bool InitFilter() OVERRIDE { return true; }
+  bool InitFilter() override { return true; }
 
   FilterStatus Filter(void* data_in,
                       size_t data_in_size,
                       size_t& data_in_read,
                       void* data_out,
                       size_t data_out_size,
-                      size_t& data_out_written) OVERRIDE {
+                      size_t& data_out_written) override {
     DCHECK((data_in_size == 0U && !data_in) || (data_in_size > 0U && data_in));
     DCHECK_EQ(data_in_read, 0U);
     DCHECK(data_out);
     DCHECK_GT(data_out_size, 0U);
     DCHECK_EQ(data_out_written, 0U);
 
-    // All data will be read.
-    data_in_read = data_in_size;
-
     // Write out the contents unchanged.
-    data_out_written = std::min(data_in_read, data_out_size);
-    if (data_out_written > 0)
+    data_out_written = std::min(data_in_size, data_out_size);
+
+    // All data will be read.
+    data_in_read = data_out_written;
+
+    if (data_out_written > 0) {
       memcpy(data_out, data_in, data_out_written);
+    }
 
     return RESPONSE_FILTER_DONE;
   }
@@ -228,11 +231,13 @@
   // Use the find/replace filter on the test URL.
   const std::string& url = request->GetURL();
 
-  if (test_runner::IsTestURL(url, kTestUrlPath))
+  if (test_runner::IsTestURL(url, kTestUrlPath)) {
     return new FindReplaceResponseFilter();
+  }
 
-  if (MatchesFilterURL(url))
+  if (MatchesFilterURL(url)) {
     return new PassThruResponseFilter();
+  }
 
   return nullptr;
 }
diff --git a/src/tests/cefclient/browser/root_window.cc b/src/tests/cefclient/browser/root_window.cc
index 45ae809..f2fb4e0 100644
--- a/src/tests/cefclient/browser/root_window.cc
+++ b/src/tests/cefclient/browser/root_window.cc
@@ -4,18 +4,14 @@
 
 #include "tests/cefclient/browser/root_window.h"
 
+#include "include/base/cef_callback_helpers.h"
+
 #include "tests/cefclient/browser/main_context.h"
 #include "tests/cefclient/browser/root_window_manager.h"
 
 namespace client {
 
-RootWindowConfig::RootWindowConfig()
-    : always_on_top(false),
-      with_controls(true),
-      with_osr(false),
-      with_extension(false),
-      initially_hidden(false),
-      url(MainContext::Get()->GetMainURL()) {}
+RootWindowConfig::RootWindowConfig() : url(MainContext::Get()->GetMainURL()) {}
 
 RootWindow::RootWindow() : delegate_(nullptr) {}
 
@@ -32,12 +28,13 @@
   DCHECK(delegate_);
   DCHECK(!WithExtension());
 
-  if (extensions.empty())
+  if (extensions.empty()) {
     return;
+  }
 
   ExtensionSet::const_iterator it = extensions.begin();
   for (; it != extensions.end(); ++it) {
-    delegate_->CreateExtensionWindow(*it, CefRect(), nullptr, base::Closure(),
+    delegate_->CreateExtensionWindow(*it, CefRect(), nullptr, base::DoNothing(),
                                      WithWindowlessRendering());
   }
 }
diff --git a/src/tests/cefclient/browser/root_window.h b/src/tests/cefclient/browser/root_window.h
index b73fc51..6883602 100644
--- a/src/tests/cefclient/browser/root_window.h
+++ b/src/tests/cefclient/browser/root_window.h
@@ -6,6 +6,7 @@
 #define CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_H_
 #pragma once
 
+#include <memory>
 #include <set>
 #include <string>
 
@@ -17,30 +18,39 @@
 #include "tests/cefclient/browser/image_cache.h"
 #include "tests/shared/browser/main_message_loop.h"
 
-#if defined(OS_MACOSX) && __OBJC__
-@class NSWindow;
-#endif  // defined(OS_MACOSX) && __OBJC__
-
 namespace client {
 
+enum class WindowType {
+  NORMAL,
+
+  // The window is hosting an extension app.
+  EXTENSION,
+
+  // The window is a modal dialog.
+  DIALOG,
+
+  // The window is a DevTools popup.
+  DEVTOOLS,
+};
+
 // Used to configure how a RootWindow is created.
 struct RootWindowConfig {
   RootWindowConfig();
 
+  // Configure the window type.
+  WindowType window_type = WindowType::NORMAL;
+
   // If true the window will always display above other windows.
-  bool always_on_top;
+  bool always_on_top = false;
 
   // If true the window will show controls.
-  bool with_controls;
+  bool with_controls = true;
 
   // If true the window will use off-screen rendering.
-  bool with_osr;
-
-  // If true the window is hosting an extension app.
-  bool with_extension;
+  bool with_osr = false;
 
   // If true the window will be created initially hidden.
-  bool initially_hidden;
+  bool initially_hidden = false;
 
   // Requested window position. If |bounds| and |source_bounds| are empty the
   // default window size and location will be used.
@@ -52,12 +62,16 @@
   // based windows when |initially_hidden| is also true.
   CefRect source_bounds;
 
+  // Requested window show state. Only used when |bounds| is non-empty and
+  // |initially_hidden| is false.
+  cef_show_state_t show_state = CEF_SHOW_STATE_NORMAL;
+
   // Parent window. Only used for Views-based windows.
   CefRefPtr<CefWindow> parent_window;
 
   // Callback to be executed when the window is closed. Will be executed on the
   // main thread. This is currently only implemented for Views-based windows.
-  base::Closure close_callback;
+  base::OnceClosure close_callback;
 
   // Initial URL to load.
   std::string url;
@@ -76,7 +90,7 @@
   class Delegate {
    public:
     // Called to retrieve the CefRequestContext for browser. Only called for
-    // non-popup browsers. May return NULL.
+    // non-popup browsers. May return nullptr.
     virtual CefRefPtr<CefRequestContext> GetRequestContext(
         RootWindow* root_window) = 0;
 
@@ -104,7 +118,7 @@
     virtual void CreateExtensionWindow(CefRefPtr<CefExtension> extension,
                                        const CefRect& source_bounds,
                                        CefRefPtr<CefWindow> parent_window,
-                                       const base::Closure& close_callback,
+                                       base::OnceClosure close_callback,
                                        bool with_osr) = 0;
 
    protected:
@@ -121,27 +135,21 @@
   // called on the main thread.
   static scoped_refptr<RootWindow> GetForBrowser(int browser_id);
 
-#if defined(OS_MACOSX) && __OBJC__
-  // Returns the RootWindow associated with the specified |window|. Must be
-  // called on the main thread.
-  static scoped_refptr<RootWindow> GetForNSWindow(NSWindow* window);
-#endif
-
   // Initialize as a normal window. This will create and show a native window
   // hosting a single browser instance. This method may be called on any thread.
-  // |delegate| must be non-NULL and outlive this object.
+  // |delegate| must be non-nullptr and outlive this object.
   // Use RootWindowManager::CreateRootWindow() instead of calling this method
   // directly.
   virtual void Init(RootWindow::Delegate* delegate,
-                    const RootWindowConfig& config,
+                    std::unique_ptr<RootWindowConfig> config,
                     const CefBrowserSettings& settings) = 0;
 
   // Initialize as a popup window. This is used to attach a new native window to
   // a single browser instance that will be created later. The native window
   // will be created and shown once the browser is available. This method may be
-  // called on any thread. |delegate| must be non-NULL and outlive this object.
-  // Use RootWindowManager::CreateRootWindowAsPopup() instead of calling this
-  // method directly. Called on the UI thread.
+  // called on any thread. |delegate| must be non-nullptr and outlive this
+  // object. Use RootWindowManager::CreateRootWindowAsPopup() instead of calling
+  // this method directly. Called on the UI thread.
   virtual void InitAsPopup(RootWindow::Delegate* delegate,
                            bool with_controls,
                            bool with_osr,
diff --git a/src/tests/cefclient/browser/root_window_create.cc b/src/tests/cefclient/browser/root_window_create.cc
index 04e347c..2ad06cf 100644
--- a/src/tests/cefclient/browser/root_window_create.cc
+++ b/src/tests/cefclient/browser/root_window_create.cc
@@ -4,15 +4,13 @@
 
 #include "tests/cefclient/browser/root_window.h"
 
-#if defined(OS_WIN) || defined(OS_LINUX)
 #include "tests/cefclient/browser/root_window_views.h"
-#endif
 
 #if defined(OS_WIN)
 #include "tests/cefclient/browser/root_window_win.h"
 #elif defined(OS_LINUX)
 #include "tests/cefclient/browser/root_window_gtk.h"
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
 #include "tests/cefclient/browser/root_window_mac.h"
 #endif
 
@@ -21,22 +19,18 @@
 // static
 scoped_refptr<RootWindow> RootWindow::Create(bool use_views) {
   if (use_views) {
-#if defined(OS_WIN) || defined(OS_LINUX)
     return new RootWindowViews();
-#else
-    LOG(FATAL) << "Views framework is not supported on this platform.";
-#endif
   }
 
 #if defined(OS_WIN)
   return new RootWindowWin();
 #elif defined(OS_LINUX)
   return new RootWindowGtk();
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
   return new RootWindowMac();
+#else
+#error Unsupported platform
 #endif
-
-  return nullptr;
 }
 
 }  // namespace client
diff --git a/src/tests/cefclient/browser/root_window_gtk.cc b/src/tests/cefclient/browser/root_window_gtk.cc
index ba48589..420bc87 100644
--- a/src/tests/cefclient/browser/root_window_gtk.cc
+++ b/src/tests/cefclient/browser/root_window_gtk.cc
@@ -11,7 +11,7 @@
 #undef Success     // Definition conflicts with cef_message_router.h
 #undef RootWindow  // Definition conflicts with root_window.h
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_app.h"
 #include "tests/cefclient/browser/browser_window_osr_gtk.h"
 #include "tests/cefclient/browser/browser_window_std_gtk.h"
@@ -29,6 +29,37 @@
 
 const char kMenuIdKey[] = "menu_id";
 
+void UseDefaultX11VisualForGtk(GtkWidget* widget) {
+#if GTK_CHECK_VERSION(3, 15, 1)
+  // GTK+ > 3.15.1 uses an X11 visual optimized for GTK+'s OpenGL stuff
+  // since revid dae447728d: https://github.com/GNOME/gtk/commit/dae447728d
+  // However, it breaks CEF: https://github.com/cztomczak/cefcapi/issues/9
+  // Let's use the default X11 visual instead of the GTK's blessed one.
+  // Copied from: https://github.com/cztomczak/cefcapi.
+  GdkScreen* screen = gdk_screen_get_default();
+  GList* visuals = gdk_screen_list_visuals(screen);
+
+  GdkX11Screen* x11_screen = GDK_X11_SCREEN(screen);
+  if (x11_screen == nullptr) {
+    return;
+  }
+
+  Visual* default_xvisual = DefaultVisual(GDK_SCREEN_XDISPLAY(x11_screen),
+                                          GDK_SCREEN_XNUMBER(x11_screen));
+  GList* cursor = visuals;
+  while (cursor != nullptr) {
+    GdkVisual* visual = GDK_X11_VISUAL(cursor->data);
+    if (default_xvisual->visualid ==
+        gdk_x11_visual_get_xvisual(visual)->visualid) {
+      gtk_widget_set_visual(widget, visual);
+      break;
+    }
+    cursor = cursor->next;
+  }
+  g_list_free(visuals);
+#endif
+}
+
 bool IsWindowMaximized(GtkWindow* window) {
   GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
   gint state = gdk_window_get_state(gdk_window);
@@ -37,8 +68,9 @@
 
 void MinimizeWindow(GtkWindow* window) {
   // Unmaximize the window before minimizing so restore behaves correctly.
-  if (IsWindowMaximized(window))
+  if (IsWindowMaximized(window)) {
     gtk_window_unmaximize(window);
+  }
 
   gtk_window_iconify(window);
 }
@@ -78,29 +110,25 @@
 }
 
 void RootWindowGtk::Init(RootWindow::Delegate* delegate,
-                         const RootWindowConfig& config,
+                         std::unique_ptr<RootWindowConfig> config,
                          const CefBrowserSettings& settings) {
   DCHECK(delegate);
   DCHECK(!initialized_);
 
   delegate_ = delegate;
-  with_controls_ = config.with_controls;
-  always_on_top_ = config.always_on_top;
-  with_osr_ = config.with_osr;
-  with_extension_ = config.with_extension;
-  start_rect_ = config.bounds;
+  with_controls_ = config->with_controls;
+  always_on_top_ = config->always_on_top;
+  with_osr_ = config->with_osr;
+  with_extension_ = config->window_type == WindowType::EXTENSION;
+  start_rect_ = config->bounds;
 
-  CreateBrowserWindow(config.url);
+  CreateBrowserWindow(config->url);
 
   initialized_ = true;
 
-  // Create the native root window on the main thread.
-  if (CURRENTLY_ON_MAIN_THREAD()) {
-    CreateRootWindow(settings, config.initially_hidden);
-  } else {
-    MAIN_POST_CLOSURE(base::Bind(&RootWindowGtk::CreateRootWindow, this,
-                                 settings, config.initially_hidden));
-  }
+  // Always post asynchronously to avoid reentrancy of the GDK lock.
+  MAIN_POST_CLOSURE(base::BindOnce(&RootWindowGtk::CreateRootWindow, this,
+                                   settings, config->initially_hidden));
 }
 
 void RootWindowGtk::InitAsPopup(RootWindow::Delegate* delegate,
@@ -118,14 +146,18 @@
   with_osr_ = with_osr;
   is_popup_ = true;
 
-  if (popupFeatures.xSet)
+  if (popupFeatures.xSet) {
     start_rect_.x = popupFeatures.x;
-  if (popupFeatures.ySet)
+  }
+  if (popupFeatures.ySet) {
     start_rect_.y = popupFeatures.y;
-  if (popupFeatures.widthSet)
+  }
+  if (popupFeatures.widthSet) {
     start_rect_.width = popupFeatures.width;
-  if (popupFeatures.heightSet)
+  }
+  if (popupFeatures.heightSet) {
     start_rect_.height = popupFeatures.height;
+  }
 
   CreateBrowserWindow(std::string());
 
@@ -141,18 +173,21 @@
 void RootWindowGtk::Show(ShowMode mode) {
   REQUIRE_MAIN_THREAD();
 
-  if (!window_)
+  if (!window_) {
     return;
+  }
 
   ScopedGdkThreadsEnter scoped_gdk_threads;
 
   // Show the GTK window.
+  UseDefaultX11VisualForGtk(GTK_WIDGET(window_));
   gtk_widget_show_all(window_);
 
-  if (mode == ShowMinimized)
+  if (mode == ShowMinimized) {
     MinimizeWindow(GTK_WINDOW(window_));
-  else if (mode == ShowMaximized)
+  } else if (mode == ShowMaximized) {
     MaximizeWindow(GTK_WINDOW(window_));
+  }
 
   // Flush the display to make sure the underlying X11 window gets created
   // immediately.
@@ -166,15 +201,17 @@
 
   ScopedGdkThreadsEnter scoped_gdk_threads;
 
-  if (window_)
+  if (window_) {
     gtk_widget_hide(window_);
+  }
 }
 
 void RootWindowGtk::SetBounds(int x, int y, size_t width, size_t height) {
   REQUIRE_MAIN_THREAD();
 
-  if (!window_)
+  if (!window_) {
     return;
+  }
 
   ScopedGdkThreadsEnter scoped_gdk_threads;
 
@@ -182,10 +219,11 @@
   GdkWindow* gdk_window = gtk_widget_get_window(window_);
 
   // Make sure the window isn't minimized or maximized.
-  if (IsWindowMaximized(window))
+  if (IsWindowMaximized(window)) {
     gtk_window_unmaximize(window);
-  else
+  } else {
     gtk_window_present(window);
+  }
 
   gdk_window_move_resize(gdk_window, x, y, width, height);
 }
@@ -206,15 +244,17 @@
 void RootWindowGtk::SetDeviceScaleFactor(float device_scale_factor) {
   REQUIRE_MAIN_THREAD();
 
-  if (browser_window_ && with_osr_)
+  if (browser_window_ && with_osr_) {
     browser_window_->SetDeviceScaleFactor(device_scale_factor);
+  }
 }
 
 float RootWindowGtk::GetDeviceScaleFactor() const {
   REQUIRE_MAIN_THREAD();
 
-  if (browser_window_ && with_osr_)
+  if (browser_window_ && with_osr_) {
     return browser_window_->GetDeviceScaleFactor();
+  }
 
   NOTREACHED();
   return 0.0f;
@@ -223,8 +263,9 @@
 CefRefPtr<CefBrowser> RootWindowGtk::GetBrowser() const {
   REQUIRE_MAIN_THREAD();
 
-  if (browser_window_)
+  if (browser_window_) {
     return browser_window_->GetBrowser();
+  }
   return nullptr;
 }
 
@@ -247,9 +288,11 @@
   if (with_osr_) {
     OsrRendererSettings settings = {};
     MainContext::Get()->PopulateOsrSettings(&settings);
-    browser_window_.reset(new BrowserWindowOsrGtk(this, startup_url, settings));
+    browser_window_.reset(
+        new BrowserWindowOsrGtk(this, with_controls_, startup_url, settings));
   } else {
-    browser_window_.reset(new BrowserWindowStdGtk(this, startup_url));
+    browser_window_.reset(
+        new BrowserWindowStdGtk(this, with_controls_, startup_url));
   }
 }
 
@@ -294,23 +337,34 @@
                    G_CALLBACK(&RootWindowGtk::WindowDelete), this);
 
   const cef_color_t background_color = MainContext::Get()->GetBackgroundColor();
-  GdkColor color = {0};
-  color.red = CefColorGetR(background_color) * 65535 / 255;
-  color.green = CefColorGetG(background_color) * 65535 / 255;
-  color.blue = CefColorGetB(background_color) * 65535 / 255;
-  gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &color);
+  GdkRGBA rgba = {0};
+  rgba.red = CefColorGetR(background_color) * 65535 / 255;
+  rgba.green = CefColorGetG(background_color) * 65535 / 255;
+  rgba.blue = CefColorGetB(background_color) * 65535 / 255;
+  rgba.alpha = 1;
 
-  GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
-  g_signal_connect(vbox, "size-allocate",
-                   G_CALLBACK(&RootWindowGtk::VboxSizeAllocated), this);
-  gtk_container_add(GTK_CONTAINER(window_), vbox);
+  gchar* css = g_strdup_printf("#* { background-color: %s; }",
+                               gdk_rgba_to_string(&rgba));
+  GtkCssProvider* provider = gtk_css_provider_new();
+  gtk_css_provider_load_from_data(provider, css, -1, nullptr);
+  g_free(css);
+  gtk_style_context_add_provider(gtk_widget_get_style_context(window_),
+                                 GTK_STYLE_PROVIDER(provider),
+                                 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+  g_object_unref(provider);
+
+  GtkWidget* grid = gtk_grid_new();
+  gtk_grid_set_column_homogeneous(GTK_GRID(grid), TRUE);
+  g_signal_connect(grid, "size-allocate",
+                   G_CALLBACK(&RootWindowGtk::GridSizeAllocated), this);
+  gtk_container_add(GTK_CONTAINER(window_), grid);
 
   if (with_controls_) {
     GtkWidget* menu_bar = CreateMenuBar();
     g_signal_connect(menu_bar, "size-allocate",
                      G_CALLBACK(&RootWindowGtk::MenubarSizeAllocated), this);
 
-    gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 0);
+    gtk_grid_attach(GTK_GRID(grid), menu_bar, 0, 0, 1, 1);
 
     GtkWidget* toolbar = gtk_toolbar_new();
     // Turn off the labels on the toolbar buttons.
@@ -318,22 +372,29 @@
     g_signal_connect(toolbar, "size-allocate",
                      G_CALLBACK(&RootWindowGtk::ToolbarSizeAllocated), this);
 
-    back_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_GO_BACK);
+    back_button_ = gtk_tool_button_new(
+        gtk_image_new_from_icon_name("go-previous", GTK_ICON_SIZE_MENU),
+        nullptr);
     g_signal_connect(back_button_, "clicked",
                      G_CALLBACK(&RootWindowGtk::BackButtonClicked), this);
     gtk_toolbar_insert(GTK_TOOLBAR(toolbar), back_button_, -1 /* append */);
 
-    forward_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_GO_FORWARD);
+    forward_button_ = gtk_tool_button_new(
+        gtk_image_new_from_icon_name("go-next", GTK_ICON_SIZE_MENU), nullptr);
     g_signal_connect(forward_button_, "clicked",
                      G_CALLBACK(&RootWindowGtk::ForwardButtonClicked), this);
     gtk_toolbar_insert(GTK_TOOLBAR(toolbar), forward_button_, -1 /* append */);
 
-    reload_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_REFRESH);
+    reload_button_ = gtk_tool_button_new(
+        gtk_image_new_from_icon_name("view-refresh", GTK_ICON_SIZE_MENU),
+        nullptr);
     g_signal_connect(reload_button_, "clicked",
                      G_CALLBACK(&RootWindowGtk::ReloadButtonClicked), this);
     gtk_toolbar_insert(GTK_TOOLBAR(toolbar), reload_button_, -1 /* append */);
 
-    stop_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_STOP);
+    stop_button_ = gtk_tool_button_new(
+        gtk_image_new_from_icon_name("process-stop", GTK_ICON_SIZE_MENU),
+        nullptr);
     g_signal_connect(stop_button_, "clicked",
                      G_CALLBACK(&RootWindowGtk::StopButtonClicked), this);
     gtk_toolbar_insert(GTK_TOOLBAR(toolbar), stop_button_, -1 /* append */);
@@ -349,7 +410,8 @@
     gtk_tool_item_set_expand(tool_item, TRUE);
     gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_item, -1);  // append
 
-    gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
+    gtk_grid_attach_next_to(GTK_GRID(grid), toolbar, menu_bar, GTK_POS_BOTTOM,
+                            1, 1);
   }
 
   // Realize (show) the GTK widget. This must be done before the browser is
@@ -364,8 +426,8 @@
 
   // Windowed browsers are parented to the X11 Window underlying the GtkWindow*
   // and must be sized manually. The OSR GTK widget, on the other hand, can be
-  // added to the Vbox container for automatic layout-based sizing.
-  GtkWidget* parent = with_osr_ ? vbox : window_;
+  // added to the grid container for automatic layout-based sizing.
+  GtkWidget* parent = with_osr_ ? grid : window_;
 
   // Set the Display associated with the browser.
   ::Display* xdisplay = GDK_WINDOW_XDISPLAY(gtk_widget_get_window(window_));
@@ -395,8 +457,9 @@
 
   // For popup browsers create the root window once the browser has been
   // created.
-  if (is_popup_)
+  if (is_popup_) {
     CreateRootWindow(CefBrowserSettings(), false);
+  }
 
   delegate_->OnBrowserCreated(this, browser);
 }
@@ -404,7 +467,7 @@
 void RootWindowGtk::OnBrowserWindowClosing() {
   if (!CefCurrentlyOn(TID_UI)) {
     CefPostTask(TID_UI,
-                base::Bind(&RootWindowGtk::OnBrowserWindowClosing, this));
+                base::BindOnce(&RootWindowGtk::OnBrowserWindowClosing, this));
     return;
   }
 
@@ -453,20 +516,22 @@
 
   CefRefPtr<CefBrowser> browser = GetBrowser();
   if (browser) {
-    scoped_ptr<window_test::WindowTestRunnerGtk> test_runner(
+    std::unique_ptr<window_test::WindowTestRunnerGtk> test_runner(
         new window_test::WindowTestRunnerGtk());
-    if (fullscreen)
+    if (fullscreen) {
       test_runner->Maximize(browser);
-    else
+    } else {
       test_runner->Restore(browser);
+    }
   }
 }
 
 void RootWindowGtk::OnAutoResize(const CefSize& new_size) {
   REQUIRE_MAIN_THREAD();
 
-  if (!window_)
+  if (!window_) {
     return;
+  }
 
   ScopedGdkThreadsEnter scoped_gdk_threads;
 
@@ -474,10 +539,11 @@
   GdkWindow* gdk_window = gtk_widget_get_window(window_);
 
   // Make sure the window isn't minimized or maximized.
-  if (IsWindowMaximized(window))
+  if (IsWindowMaximized(window)) {
     gtk_window_unmaximize(window);
-  else
+  } else {
     gtk_window_present(window);
+  }
 
   gdk_window_resize(gdk_window, new_size.width, new_size.height);
 }
@@ -506,7 +572,7 @@
 void RootWindowGtk::NotifyMoveOrResizeStarted() {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     MAIN_POST_CLOSURE(
-        base::Bind(&RootWindowGtk::NotifyMoveOrResizeStarted, this));
+        base::BindOnce(&RootWindowGtk::NotifyMoveOrResizeStarted, this));
     return;
   }
 
@@ -523,12 +589,13 @@
 
 void RootWindowGtk::NotifySetFocus() {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
-    MAIN_POST_CLOSURE(base::Bind(&RootWindowGtk::NotifySetFocus, this));
+    MAIN_POST_CLOSURE(base::BindOnce(&RootWindowGtk::NotifySetFocus, this));
     return;
   }
 
-  if (!browser_window_.get())
+  if (!browser_window_.get()) {
     return;
+  }
 
   browser_window_->SetFocus(true);
   delegate_->OnRootWindowActivated(this);
@@ -537,23 +604,25 @@
 void RootWindowGtk::NotifyVisibilityChange(bool show) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     MAIN_POST_CLOSURE(
-        base::Bind(&RootWindowGtk::NotifyVisibilityChange, this, show));
+        base::BindOnce(&RootWindowGtk::NotifyVisibilityChange, this, show));
     return;
   }
 
-  if (!browser_window_.get())
+  if (!browser_window_.get()) {
     return;
+  }
 
-  if (show)
+  if (show) {
     browser_window_->Show();
-  else
+  } else {
     browser_window_->Hide();
+  }
 }
 
 void RootWindowGtk::NotifyMenuBarHeight(int height) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     MAIN_POST_CLOSURE(
-        base::Bind(&RootWindowGtk::NotifyMenuBarHeight, this, height));
+        base::BindOnce(&RootWindowGtk::NotifyMenuBarHeight, this, height));
     return;
   }
 
@@ -562,8 +631,8 @@
 
 void RootWindowGtk::NotifyContentBounds(int x, int y, int width, int height) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
-    MAIN_POST_CLOSURE(base::Bind(&RootWindowGtk::NotifyContentBounds, this, x,
-                                 y, width, height));
+    MAIN_POST_CLOSURE(base::BindOnce(&RootWindowGtk::NotifyContentBounds, this,
+                                     x, y, width, height));
     return;
   }
 
@@ -586,7 +655,7 @@
 
 void RootWindowGtk::NotifyLoadURL(const std::string& url) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
-    MAIN_POST_CLOSURE(base::Bind(&RootWindowGtk::NotifyLoadURL, this, url));
+    MAIN_POST_CLOSURE(base::BindOnce(&RootWindowGtk::NotifyLoadURL, this, url));
     return;
   }
 
@@ -599,13 +668,14 @@
 void RootWindowGtk::NotifyButtonClicked(int id) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     MAIN_POST_CLOSURE(
-        base::Bind(&RootWindowGtk::NotifyButtonClicked, this, id));
+        base::BindOnce(&RootWindowGtk::NotifyButtonClicked, this, id));
     return;
   }
 
   CefRefPtr<CefBrowser> browser = GetBrowser();
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   switch (id) {
     case IDC_NAV_BACK:
@@ -627,18 +697,19 @@
 
 void RootWindowGtk::NotifyMenuItem(int id) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
-    MAIN_POST_CLOSURE(base::Bind(&RootWindowGtk::NotifyMenuItem, this, id));
+    MAIN_POST_CLOSURE(base::BindOnce(&RootWindowGtk::NotifyMenuItem, this, id));
     return;
   }
 
   // Run the test.
-  if (delegate_)
+  if (delegate_) {
     delegate_->OnTest(this, id);
+  }
 }
 
 void RootWindowGtk::NotifyForceClose() {
   if (!CefCurrentlyOn(TID_UI)) {
-    CefPostTask(TID_UI, base::Bind(&RootWindowGtk::NotifyForceClose, this));
+    CefPostTask(TID_UI, base::BindOnce(&RootWindowGtk::NotifyForceClose, this));
     return;
   }
 
@@ -647,7 +718,7 @@
 
 void RootWindowGtk::NotifyCloseBrowser() {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
-    MAIN_POST_CLOSURE(base::Bind(&RootWindowGtk::NotifyCloseBrowser, this));
+    MAIN_POST_CLOSURE(base::BindOnce(&RootWindowGtk::NotifyCloseBrowser, this));
     return;
   }
 
@@ -663,26 +734,30 @@
   DCHECK_EQ(1, window_destroyed + browser_destroyed);
 
   if (!CURRENTLY_ON_MAIN_THREAD()) {
-    MAIN_POST_CLOSURE(base::Bind(&RootWindowGtk::NotifyDestroyedIfDone, this,
-                                 window_destroyed, browser_destroyed));
+    MAIN_POST_CLOSURE(base::BindOnce(&RootWindowGtk::NotifyDestroyedIfDone,
+                                     this, window_destroyed,
+                                     browser_destroyed));
     return;
   }
 
-  if (window_destroyed)
+  if (window_destroyed) {
     window_destroyed_ = true;
-  if (browser_destroyed)
+  }
+  if (browser_destroyed) {
     browser_destroyed_ = true;
+  }
 
   // Notify once both the window and the browser have been destroyed.
-  if (window_destroyed_ && browser_destroyed_)
+  if (window_destroyed_ && browser_destroyed_) {
     delegate_->OnRootWindowDestroyed(this);
+  }
 }
 
 // static
 gboolean RootWindowGtk::WindowFocusIn(GtkWidget* widget,
                                       GdkEventFocus* event,
                                       RootWindowGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
 
   if (event->in) {
     self->NotifySetFocus();
@@ -698,7 +773,7 @@
 gboolean RootWindowGtk::WindowState(GtkWidget* widget,
                                     GdkEventWindowState* event,
                                     RootWindowGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
 
   // Called when the root window is iconified or restored. Hide the browser
   // window when the root window is iconified to reduce resource usage.
@@ -714,7 +789,7 @@
 gboolean RootWindowGtk::WindowConfigure(GtkWindow* window,
                                         GdkEvent* event,
                                         RootWindowGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
   self->NotifyMoveOrResizeStarted();
   return FALSE;  // Don't stop this message.
 }
@@ -729,11 +804,12 @@
 gboolean RootWindowGtk::WindowDelete(GtkWidget* widget,
                                      GdkEvent* event,
                                      RootWindowGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
 
   // Called to query whether the root window should be closed.
-  if (self->force_close_)
+  if (self->force_close_) {
     return FALSE;  // Allow the close.
+  }
 
   if (!self->is_closing_) {
     // Notify the browser window that we would like to close it. This
@@ -750,7 +826,7 @@
 }
 
 // static
-void RootWindowGtk::VboxSizeAllocated(GtkWidget* widget,
+void RootWindowGtk::GridSizeAllocated(GtkWidget* widget,
                                       GtkAllocation* allocation,
                                       RootWindowGtk* self) {
   // May be called on the main thread and the UI thread.
@@ -769,7 +845,7 @@
 // static
 gboolean RootWindowGtk::MenuItemActivated(GtkWidget* widget,
                                           RootWindowGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
 
   // Retrieve the menu ID set in AddMenuEntry.
   int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), kMenuIdKey));
@@ -787,33 +863,33 @@
 
 // static
 void RootWindowGtk::BackButtonClicked(GtkButton* button, RootWindowGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
   self->NotifyButtonClicked(IDC_NAV_BACK);
 }
 
 // static
 void RootWindowGtk::ForwardButtonClicked(GtkButton* button,
                                          RootWindowGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
   self->NotifyButtonClicked(IDC_NAV_FORWARD);
 }
 
 // static
 void RootWindowGtk::StopButtonClicked(GtkButton* button, RootWindowGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
   self->NotifyButtonClicked(IDC_NAV_STOP);
 }
 
 // static
 void RootWindowGtk::ReloadButtonClicked(GtkButton* button,
                                         RootWindowGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
   self->NotifyButtonClicked(IDC_NAV_RELOAD);
 }
 
 // static
 void RootWindowGtk::URLEntryActivate(GtkEntry* entry, RootWindowGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
   const gchar* url = gtk_entry_get_text(entry);
   self->NotifyLoadURL(std::string(url));
 }
@@ -822,7 +898,7 @@
 gboolean RootWindowGtk::URLEntryButtonPress(GtkWidget* widget,
                                             GdkEventButton* event,
                                             RootWindowGtk* self) {
-  CEF_REQUIRE_UI_THREAD();
+  REQUIRE_MAIN_THREAD();
 
   // Give focus to the GTK window. This is a work-around for bad focus-related
   // interaction between the root window managed by GTK and the browser managed
@@ -837,8 +913,9 @@
   Atom atoms[2];
   int result =
       XInternAtoms(xdisplay, const_cast<char**>(kAtoms), 2, false, atoms);
-  if (!result)
+  if (!result) {
     NOTREACHED();
+  }
 
   XEvent e;
   e.type = ClientMessage;
@@ -867,7 +944,6 @@
   AddMenuEntry(test_menu, "New Window", ID_TESTS_WINDOW_NEW);
   AddMenuEntry(test_menu, "Popup Window", ID_TESTS_WINDOW_POPUP);
   AddMenuEntry(test_menu, "Request", ID_TESTS_REQUEST);
-  AddMenuEntry(test_menu, "Plugin Info", ID_TESTS_PLUGIN_INFO);
   AddMenuEntry(test_menu, "Zoom In", ID_TESTS_ZOOM_IN);
   AddMenuEntry(test_menu, "Zoom Out", ID_TESTS_ZOOM_OUT);
   AddMenuEntry(test_menu, "Zoom Reset", ID_TESTS_ZOOM_RESET);
diff --git a/src/tests/cefclient/browser/root_window_gtk.h b/src/tests/cefclient/browser/root_window_gtk.h
index 9982c14..6af0c48 100644
--- a/src/tests/cefclient/browser/root_window_gtk.h
+++ b/src/tests/cefclient/browser/root_window_gtk.h
@@ -7,9 +7,9 @@
 #pragma once
 
 #include <gtk/gtk.h>
+#include <memory>
 #include <string>
 
-#include "include/base/cef_scoped_ptr.h"
 #include "tests/cefclient/browser/browser_window.h"
 #include "tests/cefclient/browser/root_window.h"
 
@@ -26,25 +26,25 @@
 
   // RootWindow methods.
   void Init(RootWindow::Delegate* delegate,
-            const RootWindowConfig& config,
-            const CefBrowserSettings& settings) OVERRIDE;
+            std::unique_ptr<RootWindowConfig> config,
+            const CefBrowserSettings& settings) override;
   void InitAsPopup(RootWindow::Delegate* delegate,
                    bool with_controls,
                    bool with_osr,
                    const CefPopupFeatures& popupFeatures,
                    CefWindowInfo& windowInfo,
                    CefRefPtr<CefClient>& client,
-                   CefBrowserSettings& settings) OVERRIDE;
-  void Show(ShowMode mode) OVERRIDE;
-  void Hide() OVERRIDE;
-  void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
-  void Close(bool force) OVERRIDE;
-  void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE;
-  float GetDeviceScaleFactor() const OVERRIDE;
-  CefRefPtr<CefBrowser> GetBrowser() const OVERRIDE;
-  ClientWindowHandle GetWindowHandle() const OVERRIDE;
-  bool WithWindowlessRendering() const OVERRIDE;
-  bool WithExtension() const OVERRIDE;
+                   CefBrowserSettings& settings) override;
+  void Show(ShowMode mode) override;
+  void Hide() override;
+  void SetBounds(int x, int y, size_t width, size_t height) override;
+  void Close(bool force) override;
+  void SetDeviceScaleFactor(float device_scale_factor) override;
+  float GetDeviceScaleFactor() const override;
+  CefRefPtr<CefBrowser> GetBrowser() const override;
+  ClientWindowHandle GetWindowHandle() const override;
+  bool WithWindowlessRendering() const override;
+  bool WithExtension() const override;
 
  private:
   void CreateBrowserWindow(const std::string& startup_url);
@@ -52,18 +52,18 @@
                         bool initially_hidden);
 
   // BrowserWindow::Delegate methods.
-  void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void OnBrowserWindowClosing() OVERRIDE;
-  void OnBrowserWindowDestroyed() OVERRIDE;
-  void OnSetAddress(const std::string& url) OVERRIDE;
-  void OnSetTitle(const std::string& title) OVERRIDE;
-  void OnSetFullscreen(bool fullscreen) OVERRIDE;
-  void OnAutoResize(const CefSize& new_size) OVERRIDE;
+  void OnBrowserCreated(CefRefPtr<CefBrowser> browser) override;
+  void OnBrowserWindowClosing() override;
+  void OnBrowserWindowDestroyed() override;
+  void OnSetAddress(const std::string& url) override;
+  void OnSetTitle(const std::string& title) override;
+  void OnSetFullscreen(bool fullscreen) override;
+  void OnAutoResize(const CefSize& new_size) override;
   void OnSetLoadingState(bool isLoading,
                          bool canGoBack,
-                         bool canGoForward) OVERRIDE;
+                         bool canGoForward) override;
   void OnSetDraggableRegions(
-      const std::vector<CefDraggableRegion>& regions) OVERRIDE;
+      const std::vector<CefDraggableRegion>& regions) override;
 
   void NotifyMoveOrResizeStarted();
   void NotifySetFocus();
@@ -97,7 +97,7 @@
                                RootWindowGtk* self);
 
   // Signal handlers for the GTK Vbox containing all UX elements.
-  static void VboxSizeAllocated(GtkWidget* widget,
+  static void GridSizeAllocated(GtkWidget* widget,
                                 GtkAllocation* allocation,
                                 RootWindowGtk* self);
 
@@ -130,7 +130,7 @@
   bool with_extension_;
   bool is_popup_;
   CefRect start_rect_;
-  scoped_ptr<BrowserWindow> browser_window_;
+  std::unique_ptr<BrowserWindow> browser_window_;
   bool initialized_;
 
   // Main window.
diff --git a/src/tests/cefclient/browser/root_window_mac.h b/src/tests/cefclient/browser/root_window_mac.h
index ddd76ba..7a5d435 100644
--- a/src/tests/cefclient/browser/root_window_mac.h
+++ b/src/tests/cefclient/browser/root_window_mac.h
@@ -6,9 +6,9 @@
 #define CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_MAC_H_
 #pragma once
 
+#include <memory>
 #include <string>
 
-#include "include/base/cef_scoped_ptr.h"
 #include "tests/cefclient/browser/browser_window.h"
 #include "tests/cefclient/browser/root_window.h"
 
@@ -30,38 +30,38 @@
 
   // RootWindow methods.
   void Init(RootWindow::Delegate* delegate,
-            const RootWindowConfig& config,
-            const CefBrowserSettings& settings) OVERRIDE;
+            std::unique_ptr<RootWindowConfig> config,
+            const CefBrowserSettings& settings) override;
   void InitAsPopup(RootWindow::Delegate* delegate,
                    bool with_controls,
                    bool with_osr,
                    const CefPopupFeatures& popupFeatures,
                    CefWindowInfo& windowInfo,
                    CefRefPtr<CefClient>& client,
-                   CefBrowserSettings& settings) OVERRIDE;
-  void Show(ShowMode mode) OVERRIDE;
-  void Hide() OVERRIDE;
-  void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
-  void Close(bool force) OVERRIDE;
-  void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE;
-  float GetDeviceScaleFactor() const OVERRIDE;
-  CefRefPtr<CefBrowser> GetBrowser() const OVERRIDE;
-  ClientWindowHandle GetWindowHandle() const OVERRIDE;
-  bool WithWindowlessRendering() const OVERRIDE;
-  bool WithExtension() const OVERRIDE;
+                   CefBrowserSettings& settings) override;
+  void Show(ShowMode mode) override;
+  void Hide() override;
+  void SetBounds(int x, int y, size_t width, size_t height) override;
+  void Close(bool force) override;
+  void SetDeviceScaleFactor(float device_scale_factor) override;
+  float GetDeviceScaleFactor() const override;
+  CefRefPtr<CefBrowser> GetBrowser() const override;
+  ClientWindowHandle GetWindowHandle() const override;
+  bool WithWindowlessRendering() const override;
+  bool WithExtension() const override;
 
   // BrowserWindow::Delegate methods.
-  void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void OnBrowserWindowDestroyed() OVERRIDE;
-  void OnSetAddress(const std::string& url) OVERRIDE;
-  void OnSetTitle(const std::string& title) OVERRIDE;
-  void OnSetFullscreen(bool fullscreen) OVERRIDE;
-  void OnAutoResize(const CefSize& new_size) OVERRIDE;
+  void OnBrowserCreated(CefRefPtr<CefBrowser> browser) override;
+  void OnBrowserWindowDestroyed() override;
+  void OnSetAddress(const std::string& url) override;
+  void OnSetTitle(const std::string& title) override;
+  void OnSetFullscreen(bool fullscreen) override;
+  void OnAutoResize(const CefSize& new_size) override;
   void OnSetLoadingState(bool isLoading,
                          bool canGoBack,
-                         bool canGoForward) OVERRIDE;
+                         bool canGoForward) override;
   void OnSetDraggableRegions(
-      const std::vector<CefDraggableRegion>& regions) OVERRIDE;
+      const std::vector<CefDraggableRegion>& regions) override;
 
   void OnNativeWindowClosed();
 
diff --git a/src/tests/cefclient/browser/root_window_mac.mm b/src/tests/cefclient/browser/root_window_mac.mm
index 6595407..072566f 100644
--- a/src/tests/cefclient/browser/root_window_mac.mm
+++ b/src/tests/cefclient/browser/root_window_mac.mm
@@ -6,11 +6,13 @@
 
 #include <Cocoa/Cocoa.h>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_app.h"
 #include "include/cef_application_mac.h"
+#include "include/views/cef_display.h"
 #include "tests/cefclient/browser/browser_window_osr_mac.h"
 #include "tests/cefclient/browser/browser_window_std_mac.h"
+#include "tests/cefclient/browser/client_prefs.h"
 #include "tests/cefclient/browser/main_context.h"
 #include "tests/cefclient/browser/temp_window.h"
 #include "tests/cefclient/browser/window_test_runner_mac.h"
@@ -23,10 +25,12 @@
  @private
   NSWindow* window_;
   client::RootWindowMac* root_window_;
+  std::optional<CefRect> last_visible_bounds_;
   bool force_close_;
 }
 
 @property(nonatomic, readonly) client::RootWindowMac* root_window;
+@property(nonatomic, readwrite) std::optional<CefRect> last_visible_bounds;
 @property(nonatomic, readwrite) bool force_close;
 
 - (id)initWithWindow:(NSWindow*)window
@@ -54,18 +58,128 @@
   [button autorelease];
 #endif  // !__has_feature(objc_arc)
   [button setTitle:title];
-  [button setBezelStyle:NSSmallSquareBezelStyle];
+  [button setBezelStyle:NSBezelStyleSmallSquare];
   [button setAutoresizingMask:(NSViewMaxXMargin | NSViewMinYMargin)];
   [parent addSubview:button];
   rect->origin.x += BUTTON_WIDTH;
   return button;
 }
 
-NSRect GetScreenRectForWindow(NSWindow* window) {
-  NSScreen* screen = [window screen];
-  if (screen == nil)
+// Returns the current DIP screen bounds for a visible window in the
+// restored position, or nullopt if the window is currently minimized or
+// fullscreen.
+std::optional<CefRect> GetWindowBoundsInScreen(NSWindow* window) {
+  if ([window isMiniaturized] or [window isZoomed]) {
+    return std::nullopt;
+  }
+
+  auto screen = [window screen];
+  if (screen == nil) {
     screen = [NSScreen mainScreen];
-  return [screen visibleFrame];
+  }
+
+  const auto bounds = [window frame];
+  const auto screen_bounds = [screen frame];
+
+  if (NSEqualRects(bounds, screen_bounds)) {
+    // Don't include windows that are transitioning to fullscreen.
+    return std::nullopt;
+  }
+
+  CefRect dip_bounds{static_cast<int>(bounds.origin.x),
+                     static_cast<int>(bounds.origin.y),
+                     static_cast<int>(bounds.size.width),
+                     static_cast<int>(bounds.size.height)};
+
+  // Convert from macOS coordinates (bottom-left origin) to DIP coordinates
+  // (top-left origin).
+  dip_bounds.y = static_cast<int>(screen_bounds.size.height) -
+                 dip_bounds.height - dip_bounds.y;
+
+  return dip_bounds;
+}
+
+// Keep the frame bounds inside the display work area.
+NSRect ClampNSBoundsToWorkArea(const NSRect& frame_bounds,
+                               const CefRect& display_bounds,
+                               const CefRect& work_area) {
+  NSRect bounds = frame_bounds;
+
+  // Convert from DIP coordinates (top-left origin) to macOS coordinates
+  // (bottom-left origin).
+  const int work_area_y =
+      display_bounds.height - work_area.height - work_area.y;
+
+  if (bounds.size.width > work_area.width) {
+    bounds.size.width = work_area.width;
+  }
+  if (bounds.size.height > work_area.height) {
+    bounds.size.height = work_area.height;
+  }
+
+  if (bounds.origin.x < work_area.x) {
+    bounds.origin.x = work_area.x;
+  } else if (bounds.origin.x + bounds.size.width >=
+             work_area.x + work_area.width) {
+    bounds.origin.x = work_area.x + work_area.width - bounds.size.width;
+  }
+
+  if (bounds.origin.y < work_area_y) {
+    bounds.origin.y = work_area_y;
+  } else if (bounds.origin.y + bounds.size.height >=
+             work_area_y + work_area.height) {
+    bounds.origin.y = work_area_y + work_area.height - bounds.size.height;
+  }
+
+  return bounds;
+}
+
+// Get frame and content area rects matching the input DIP screen bounds. The
+// resulting window frame will be kept inside the closest display work area. If
+// |input_content_bounds| is true the input size is used for the content area
+// and the input origin is used for the frame. Otherwise, both input size and
+// origin are used for the frame.
+void GetNSBoundsInDisplay(const CefRect& dip_bounds,
+                          bool input_content_bounds,
+                          NSWindowStyleMask style_mask,
+                          NSRect& frame_rect,
+                          NSRect& content_rect) {
+  // Identify the closest display.
+  auto display =
+      CefDisplay::GetDisplayMatchingBounds(dip_bounds,
+                                           /*input_pixel_coords=*/false);
+  const auto display_bounds = display->GetBounds();
+  const auto display_work_area = display->GetWorkArea();
+
+  // Convert from DIP coordinates (top-left origin) to macOS coordinates
+  // (bottom-left origin).
+  NSRect requested_rect = NSMakeRect(dip_bounds.x, dip_bounds.y,
+                                     dip_bounds.width, dip_bounds.height);
+  requested_rect.origin.y = display_bounds.height - requested_rect.size.height -
+                            requested_rect.origin.y;
+
+  // Calculate the equivalent frame and content bounds.
+  if (input_content_bounds) {
+    // Compute frame rect from content rect. Keep the requested origin.
+    content_rect = requested_rect;
+    frame_rect = [NSWindow frameRectForContentRect:content_rect
+                                         styleMask:style_mask];
+    frame_rect.origin = requested_rect.origin;
+  } else {
+    // Compute content rect from frame rect.
+    frame_rect = requested_rect;
+    content_rect = [NSWindow contentRectForFrameRect:frame_rect
+                                           styleMask:style_mask];
+  }
+
+  // Keep the frame inside the display work area.
+  const NSRect new_frame_rect =
+      ClampNSBoundsToWorkArea(frame_rect, display_bounds, display_work_area);
+  if (!NSEqualRects(frame_rect, new_frame_rect)) {
+    frame_rect = new_frame_rect;
+    content_rect = [NSWindow contentRectForFrameRect:frame_rect
+                                           styleMask:style_mask];
+  }
 }
 
 }  // namespace
@@ -86,7 +200,7 @@
 
   // RootWindow methods.
   void Init(RootWindow::Delegate* delegate,
-            const RootWindowConfig& config,
+            std::unique_ptr<RootWindowConfig> config,
             const CefBrowserSettings& settings);
   void InitAsPopup(RootWindow::Delegate* delegate,
                    bool with_controls,
@@ -121,45 +235,34 @@
   // After initialization all members are only accessed on the main thread.
   // Members set during initialization.
   RootWindowMac& root_window_;
-  bool with_controls_;
-  bool with_osr_;
-  bool with_extension_;
-  bool is_popup_;
-  CefRect start_rect_;
-  scoped_ptr<BrowserWindow> browser_window_;
-  bool initialized_;
+  bool with_controls_ = false;
+  bool with_osr_ = false;
+  bool with_extension_ = false;
+  bool is_popup_ = false;
+  CefRect initial_bounds_;
+  cef_show_state_t initial_show_state_ = CEF_SHOW_STATE_NORMAL;
+  std::unique_ptr<BrowserWindow> browser_window_;
+  bool initialized_ = false;
 
   // Main window.
-  NSWindow* window_;
-  RootWindowDelegate* window_delegate_;
+  NSWindow* window_ = nil;
+  RootWindowDelegate* window_delegate_ = nil;
 
   // Buttons.
-  NSButton* back_button_;
-  NSButton* forward_button_;
-  NSButton* reload_button_;
-  NSButton* stop_button_;
+  NSButton* back_button_ = nil;
+  NSButton* forward_button_ = nil;
+  NSButton* reload_button_ = nil;
+  NSButton* stop_button_ = nil;
 
   // URL text field.
-  NSTextField* url_textfield_;
+  NSTextField* url_textfield_ = nil;
 
-  bool window_destroyed_;
-  bool browser_destroyed_;
+  bool window_destroyed_ = false;
+  bool browser_destroyed_ = false;
 };
 
 RootWindowMacImpl::RootWindowMacImpl(RootWindowMac& root_window)
-    : root_window_(root_window),
-      with_controls_(false),
-      with_osr_(false),
-      is_popup_(false),
-      initialized_(false),
-      window_(nil),
-      back_button_(nil),
-      forward_button_(nil),
-      reload_button_(nil),
-      stop_button_(nil),
-      url_textfield_(nil),
-      window_destroyed_(false),
-      browser_destroyed_(false) {}
+    : root_window_(root_window) {}
 
 RootWindowMacImpl::~RootWindowMacImpl() {
   REQUIRE_MAIN_THREAD();
@@ -170,26 +273,33 @@
 }
 
 void RootWindowMacImpl::Init(RootWindow::Delegate* delegate,
-                             const RootWindowConfig& config,
+                             std::unique_ptr<RootWindowConfig> config,
                              const CefBrowserSettings& settings) {
   DCHECK(!initialized_);
 
-  with_controls_ = config.with_controls;
-  with_osr_ = config.with_osr;
-  with_extension_ = config.with_extension;
-  start_rect_ = config.bounds;
+  with_controls_ = config->with_controls;
+  with_osr_ = config->with_osr;
+  with_extension_ = config->window_type == WindowType::EXTENSION;
 
-  CreateBrowserWindow(config.url);
+  if (!config->bounds.IsEmpty()) {
+    // Initial state was specified via the config object.
+    initial_bounds_ = config->bounds;
+    initial_show_state_ = config->show_state;
+  } else {
+    // Initial state may be specified via the command-line or global
+    // preferences.
+    std::optional<CefRect> bounds;
+    if (prefs::LoadWindowRestorePreferences(initial_show_state_, bounds) &&
+        bounds) {
+      initial_bounds_ = *bounds;
+    }
+  }
+
+  CreateBrowserWindow(config->url);
 
   initialized_ = true;
 
-  // Create the native root window on the main thread.
-  if (CURRENTLY_ON_MAIN_THREAD()) {
-    CreateRootWindow(settings, config.initially_hidden);
-  } else {
-    MAIN_POST_CLOSURE(base::Bind(&RootWindowMacImpl::CreateRootWindow, this,
-                                 settings, config.initially_hidden));
-  }
+  CreateRootWindow(settings, config->initially_hidden);
 }
 
 void RootWindowMacImpl::InitAsPopup(RootWindow::Delegate* delegate,
@@ -206,14 +316,18 @@
   with_osr_ = with_osr;
   is_popup_ = true;
 
-  if (popupFeatures.xSet)
-    start_rect_.x = popupFeatures.x;
-  if (popupFeatures.ySet)
-    start_rect_.y = popupFeatures.y;
-  if (popupFeatures.widthSet)
-    start_rect_.width = popupFeatures.width;
-  if (popupFeatures.heightSet)
-    start_rect_.height = popupFeatures.height;
+  if (popupFeatures.xSet) {
+    initial_bounds_.x = popupFeatures.x;
+  }
+  if (popupFeatures.ySet) {
+    initial_bounds_.y = popupFeatures.y;
+  }
+  if (popupFeatures.widthSet) {
+    initial_bounds_.width = popupFeatures.width;
+  }
+  if (popupFeatures.heightSet) {
+    initial_bounds_.height = popupFeatures.height;
+  }
 
   CreateBrowserWindow(std::string());
 
@@ -229,8 +343,9 @@
 void RootWindowMacImpl::Show(RootWindow::ShowMode mode) {
   REQUIRE_MAIN_THREAD();
 
-  if (!window_)
+  if (!window_) {
     return;
+  }
 
   const bool is_visible = [window_ isVisible];
   const bool is_minimized = [window_ isMiniaturized];
@@ -244,31 +359,36 @@
   }
 
   // Undo the previous state since it's not the desired state.
-  if (is_minimized)
+  if (is_minimized) {
     [window_ deminiaturize:nil];
-  else if (is_maximized)
+  } else if (is_maximized) {
     [window_ performZoom:nil];
+  }
 
   // Window visibility may change after (for example) deminiaturizing the
   // window.
-  if (![window_ isVisible])
+  if (![window_ isVisible]) {
     [window_ makeKeyAndOrderFront:nil];
+  }
 
-  if (mode == RootWindow::ShowMinimized)
+  if (mode == RootWindow::ShowMinimized) {
     [window_ performMiniaturize:nil];
-  else if (mode == RootWindow::ShowMaximized)
+  } else if (mode == RootWindow::ShowMaximized) {
     [window_ performZoom:nil];
+  }
 }
 
 void RootWindowMacImpl::Hide() {
   REQUIRE_MAIN_THREAD();
 
-  if (!window_)
+  if (!window_) {
     return;
+  }
 
   // Undo miniaturization, if any, so the window will actually be hidden.
-  if ([window_ isMiniaturized])
+  if ([window_ isMiniaturized]) {
     [window_ deminiaturize:nil];
+  }
 
   // Hide the window.
   [window_ orderOut:nil];
@@ -277,21 +397,17 @@
 void RootWindowMacImpl::SetBounds(int x, int y, size_t width, size_t height) {
   REQUIRE_MAIN_THREAD();
 
-  if (!window_)
+  if (!window_) {
     return;
+  }
 
-  NSRect screen_rect = GetScreenRectForWindow(window_);
+  const CefRect dip_bounds(x, y, static_cast<int>(width),
+                           static_cast<int>(height));
 
-  // Desired content rectangle.
-  NSRect content_rect;
-  content_rect.size.width = static_cast<int>(width);
-  content_rect.size.height =
-      static_cast<int>(height) + (with_controls_ ? URLBAR_HEIGHT : 0);
-
-  // Convert to a frame rectangle.
-  NSRect frame_rect = [window_ frameRectForContentRect:content_rect];
-  frame_rect.origin.x = x;
-  frame_rect.origin.y = screen_rect.size.height - y;
+  // Calculate the equivalent frame and content area bounds.
+  NSRect frame_rect, content_rect;
+  GetNSBoundsInDisplay(dip_bounds, /*input_content_bounds=*/true,
+                       [window_ styleMask], frame_rect, content_rect);
 
   [window_ setFrame:frame_rect display:YES];
 }
@@ -309,15 +425,17 @@
 void RootWindowMacImpl::SetDeviceScaleFactor(float device_scale_factor) {
   REQUIRE_MAIN_THREAD();
 
-  if (browser_window_ && with_osr_)
+  if (browser_window_ && with_osr_) {
     browser_window_->SetDeviceScaleFactor(device_scale_factor);
+  }
 }
 
 float RootWindowMacImpl::GetDeviceScaleFactor() const {
   REQUIRE_MAIN_THREAD();
 
-  if (browser_window_ && with_osr_)
+  if (browser_window_ && with_osr_) {
     return browser_window_->GetDeviceScaleFactor();
+  }
 
   NOTREACHED();
   return 0.0f;
@@ -326,9 +444,10 @@
 CefRefPtr<CefBrowser> RootWindowMacImpl::GetBrowser() const {
   REQUIRE_MAIN_THREAD();
 
-  if (browser_window_)
+  if (browser_window_) {
     return browser_window_->GetBrowser();
-  return NULL;
+  }
+  return nullptr;
 }
 
 ClientWindowHandle RootWindowMacImpl::GetWindowHandle() const {
@@ -356,10 +475,11 @@
   if (with_osr_) {
     OsrRendererSettings settings = {};
     MainContext::Get()->PopulateOsrSettings(&settings);
-    browser_window_.reset(
-        new BrowserWindowOsrMac(&root_window_, startup_url, settings));
+    browser_window_.reset(new BrowserWindowOsrMac(&root_window_, with_controls_,
+                                                  startup_url, settings));
   } else {
-    browser_window_.reset(new BrowserWindowStdMac(&root_window_, startup_url));
+    browser_window_.reset(
+        new BrowserWindowStdMac(&root_window_, with_controls_, startup_url));
   }
 }
 
@@ -370,35 +490,36 @@
 
   // TODO(port): If no x,y position is specified the window will always appear
   // in the upper-left corner. Maybe there's a better default place to put it?
-  int x = start_rect_.x;
-  int y = start_rect_.y;
-  int width, height;
-  if (start_rect_.IsEmpty()) {
-    // TODO(port): Also, maybe there's a better way to choose the default size.
-    width = 800;
-    height = 600;
-  } else {
-    width = start_rect_.width;
-    height = start_rect_.height;
+  CefRect dip_bounds = initial_bounds_;
+
+  // TODO(port): Also, maybe there's a better way to choose the default size.
+  if (dip_bounds.width <= 0) {
+    dip_bounds.width = 800;
+  }
+  if (dip_bounds.height <= 0) {
+    dip_bounds.height = 600;
   }
 
+  // For popups, the requested bounds are for the content area and the requested
+  // origin is for the window.
+  if (is_popup_ && with_controls_) {
+    dip_bounds.height += URLBAR_HEIGHT;
+  }
+
+  const NSWindowStyleMask style_mask =
+      (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
+       NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable);
+
+  // Calculate the equivalent frame and content area bounds.
+  NSRect frame_rect, content_rect;
+  GetNSBoundsInDisplay(dip_bounds, /*input_content_bounds=*/is_popup_,
+                       style_mask, frame_rect, content_rect);
+
   // Create the main window.
-  NSRect screen_rect = [[NSScreen mainScreen] visibleFrame];
-  NSRect window_rect =
-      NSMakeRect(x, screen_rect.size.height - y, width, height);
-
-  // The CEF framework library is loaded at runtime so we need to use this
-  // mechanism for retrieving the class.
-  Class window_class = NSClassFromString(@"UnderlayOpenGLHostingWindow");
-  CHECK(window_class);
-
-  window_ = [[window_class alloc]
-      initWithContentRect:window_rect
-                styleMask:(NSTitledWindowMask | NSClosableWindowMask |
-                           NSMiniaturizableWindowMask | NSResizableWindowMask |
-                           NSUnifiedTitleAndToolbarWindowMask)
-                  backing:NSBackingStoreBuffered
-                    defer:NO];
+  window_ = [[NSWindow alloc] initWithContentRect:content_rect
+                                        styleMask:style_mask
+                                          backing:NSBackingStoreBuffered
+                                            defer:NO];
   [window_ setTitle:@"cefclient"];
   // No dark mode, please
   window_.appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua];
@@ -407,6 +528,12 @@
   window_delegate_ = [[RootWindowDelegate alloc] initWithWindow:window_
                                                   andRootWindow:&root_window_];
 
+  if (!initial_bounds_.IsEmpty()) {
+    // Remember the bounds from the previous application run in case the user
+    // does not move or resize the window during this application run.
+    window_delegate_.last_visible_bounds = initial_bounds_;
+  }
+
   // Rely on the window delegate to clean us up rather than immediately
   // releasing when the window gets closed. We use the delegate to do
   // everything from the autorelease pool so the window isn't on the stack
@@ -438,16 +565,17 @@
   }
 
   if (with_controls_) {
+    // Reduce the browser height by the URL bar height.
+    contentBounds.size.height -= URLBAR_HEIGHT;
+
     // Create the buttons.
     NSRect button_rect = contentBounds;
-    button_rect.origin.y = window_rect.size.height - URLBAR_HEIGHT +
-                           (URLBAR_HEIGHT - BUTTON_HEIGHT) / 2;
+    button_rect.origin.y =
+        contentBounds.size.height + (URLBAR_HEIGHT - BUTTON_HEIGHT) / 2;
     button_rect.size.height = BUTTON_HEIGHT;
     button_rect.origin.x += BUTTON_MARGIN;
     button_rect.size.width = BUTTON_WIDTH;
 
-    contentBounds.size.height -= URLBAR_HEIGHT;
-
     back_button_ = MakeButton(&button_rect, @"Back", contentView);
     [back_button_ setTarget:window_delegate_];
     [back_button_ setAction:@selector(goBack:)];
@@ -483,11 +611,16 @@
     [[url_textfield_ cell] setScrollable:YES];
   }
 
+  // Place the window at the target point. This is required for proper placement
+  // if the point is on a secondary display.
+  [window_ setFrameOrigin:frame_rect.origin];
+
   if (!is_popup_) {
     // Create the browser window.
     browser_window_->CreateBrowser(
         CAST_NSVIEW_TO_CEF_WINDOW_HANDLE(contentView),
-        CefRect(0, 0, width, height), settings, NULL,
+        CefRect(0, 0, contentBounds.size.width, contentBounds.size.height),
+        settings, nullptr,
         root_window_.delegate_->GetRequestContext(&root_window_));
   } else {
     // With popups we already have a browser window. Parent the browser window
@@ -498,11 +631,15 @@
   }
 
   if (!initially_hidden) {
-    // Show the window.
-    Show(RootWindow::ShowNormal);
+    auto mode = RootWindow::ShowNormal;
+    if (initial_show_state_ == CEF_SHOW_STATE_MAXIMIZED) {
+      mode = RootWindow::ShowMaximized;
+    } else if (initial_show_state_ == CEF_SHOW_STATE_MINIMIZED) {
+      mode = RootWindow::ShowMinimized;
+    }
 
-    // Size the window.
-    SetBounds(x, y, width, height);
+    // Show the window.
+    Show(mode);
   }
 }
 
@@ -511,8 +648,9 @@
 
   // For popup browsers create the root window once the browser has been
   // created.
-  if (is_popup_)
+  if (is_popup_) {
     CreateRootWindow(CefBrowserSettings(), false);
+  }
 
   root_window_.delegate_->OnBrowserCreated(&root_window_, browser);
 }
@@ -564,20 +702,22 @@
 
   CefRefPtr<CefBrowser> browser = GetBrowser();
   if (browser) {
-    scoped_ptr<window_test::WindowTestRunnerMac> test_runner(
+    std::unique_ptr<window_test::WindowTestRunnerMac> test_runner(
         new window_test::WindowTestRunnerMac());
-    if (fullscreen)
+    if (fullscreen) {
       test_runner->Maximize(browser);
-    else
+    } else {
       test_runner->Restore(browser);
+    }
   }
 }
 
 void RootWindowMacImpl::OnAutoResize(const CefSize& new_size) {
   REQUIRE_MAIN_THREAD();
 
-  if (!window_)
+  if (!window_) {
     return;
+  }
 
   // Desired content rectangle.
   NSRect content_rect;
@@ -625,8 +765,9 @@
 
 void RootWindowMacImpl::NotifyDestroyedIfDone() {
   // Notify once both the window and the browser have been destroyed.
-  if (window_destroyed_ && browser_destroyed_)
+  if (window_destroyed_ && browser_destroyed_) {
     root_window_.delegate_->OnRootWindowDestroyed(&root_window_);
+  }
 }
 
 RootWindowMac::RootWindowMac() {
@@ -644,11 +785,11 @@
 }
 
 void RootWindowMac::Init(RootWindow::Delegate* delegate,
-                         const RootWindowConfig& config,
+                         std::unique_ptr<RootWindowConfig> config,
                          const CefBrowserSettings& settings) {
   DCHECK(delegate);
   delegate_ = delegate;
-  impl_->Init(delegate, config, settings);
+  impl_->Init(delegate, std::move(config), settings);
 }
 
 void RootWindowMac::InitAsPopup(RootWindow::Delegate* delegate,
@@ -743,18 +884,12 @@
   impl_->OnNativeWindowClosed();
 }
 
-// static
-scoped_refptr<RootWindow> RootWindow::GetForNSWindow(NSWindow* window) {
-  RootWindowDelegate* delegate =
-      static_cast<RootWindowDelegate*>([window delegate]);
-  return [delegate root_window];
-}
-
 }  // namespace client
 
 @implementation RootWindowDelegate
 
 @synthesize root_window = root_window_;
+@synthesize last_visible_bounds = last_visible_bounds_;
 @synthesize force_close = force_close_;
 
 - (id)initWithWindow:(NSWindow*)window
@@ -789,40 +924,46 @@
 
 - (IBAction)goBack:(id)sender {
   CefRefPtr<CefBrowser> browser = root_window_->GetBrowser();
-  if (browser.get())
+  if (browser.get()) {
     browser->GoBack();
+  }
 }
 
 - (IBAction)goForward:(id)sender {
   CefRefPtr<CefBrowser> browser = root_window_->GetBrowser();
-  if (browser.get())
+  if (browser.get()) {
     browser->GoForward();
+  }
 }
 
 - (IBAction)reload:(id)sender {
   CefRefPtr<CefBrowser> browser = root_window_->GetBrowser();
-  if (browser.get())
+  if (browser.get()) {
     browser->Reload();
+  }
 }
 
 - (IBAction)stopLoading:(id)sender {
   CefRefPtr<CefBrowser> browser = root_window_->GetBrowser();
-  if (browser.get())
+  if (browser.get()) {
     browser->StopLoad();
+  }
 }
 
 - (IBAction)takeURLStringValueFrom:(NSTextField*)sender {
   CefRefPtr<CefBrowser> browser = root_window_->GetBrowser();
-  if (!browser.get())
+  if (!browser.get()) {
     return;
+  }
 
   NSString* url = [sender stringValue];
 
   // if it doesn't already have a prefix, add http. If we can't parse it,
   // just don't bother rather than making things worse.
   NSURL* tempUrl = [NSURL URLWithString:url];
-  if (tempUrl && ![tempUrl scheme])
+  if (tempUrl && ![tempUrl scheme]) {
     url = [@"http://" stringByAppendingString:url];
+  }
 
   std::string urlStr = [url UTF8String];
   browser->GetMainFrame()->LoadURL(urlStr);
@@ -831,30 +972,52 @@
 // Called when we are activated (when we gain focus).
 - (void)windowDidBecomeKey:(NSNotification*)notification {
   client::BrowserWindow* browser_window = root_window_->browser_window();
-  if (browser_window)
+  if (browser_window) {
     browser_window->SetFocus(true);
+  }
   root_window_->delegate()->OnRootWindowActivated(root_window_);
 }
 
 // Called when we are deactivated (when we lose focus).
 - (void)windowDidResignKey:(NSNotification*)notification {
   client::BrowserWindow* browser_window = root_window_->browser_window();
-  if (browser_window)
+  if (browser_window) {
     browser_window->SetFocus(false);
+  }
 }
 
 // Called when we have been minimized.
 - (void)windowDidMiniaturize:(NSNotification*)notification {
   client::BrowserWindow* browser_window = root_window_->browser_window();
-  if (browser_window)
+  if (browser_window) {
     browser_window->Hide();
+  }
 }
 
 // Called when we have been unminimized.
 - (void)windowDidDeminiaturize:(NSNotification*)notification {
   client::BrowserWindow* browser_window = root_window_->browser_window();
-  if (browser_window)
+  if (browser_window) {
     browser_window->Show();
+  }
+}
+
+// Called when we have been resized.
+- (void)windowDidResize:(NSNotification*)notification {
+  // Track the last visible bounds for window restore purposes.
+  const auto dip_bounds = client::GetWindowBoundsInScreen(window_);
+  if (dip_bounds) {
+    last_visible_bounds_ = dip_bounds;
+  }
+}
+
+// Called when we have been moved.
+- (void)windowDidMove:(NSNotification*)notification {
+  // Track the last visible bounds for window restore purposes.
+  const auto dip_bounds = client::GetWindowBoundsInScreen(window_);
+  if (dip_bounds) {
+    last_visible_bounds_ = dip_bounds;
+  }
 }
 
 // Called when the application has been hidden.
@@ -862,8 +1025,9 @@
   // If the window is miniaturized then nothing has really changed.
   if (![window_ isMiniaturized]) {
     client::BrowserWindow* browser_window = root_window_->browser_window();
-    if (browser_window)
+    if (browser_window) {
       browser_window->Hide();
+    }
   }
 }
 
@@ -872,8 +1036,9 @@
   // If the window is miniaturized then nothing has really changed.
   if (![window_ isMiniaturized]) {
     client::BrowserWindow* browser_window = root_window_->browser_window();
-    if (browser_window)
+    if (browser_window) {
       browser_window->Show();
+    }
   }
 }
 
@@ -897,13 +1062,22 @@
     }
   }
 
-  // Don't want any more delegate callbacks after we destroy ourselves.
-  window_.delegate = nil;
-  // Delete the window.
-#if !__has_feature(objc_arc)
-  [window autorelease];
-#endif  // !__has_feature(objc_arc)
-  window_ = nil;
+  // Save window restore position.
+  std::optional<CefRect> dip_bounds;
+  cef_show_state_t show_state = CEF_SHOW_STATE_NORMAL;
+  if ([window_ isMiniaturized]) {
+    show_state = CEF_SHOW_STATE_MINIMIZED;
+  } else if ([window_ isZoomed]) {
+    show_state = CEF_SHOW_STATE_MAXIMIZED;
+  } else {
+    dip_bounds = client::GetWindowBoundsInScreen(window_);
+  }
+
+  if (!dip_bounds) {
+    dip_bounds = last_visible_bounds_;
+  }
+
+  client::prefs::SaveWindowRestorePreferences(show_state, dip_bounds);
 
   // Clean ourselves up after clearing the stack of anything that might have the
   // window on it.
diff --git a/src/tests/cefclient/browser/root_window_manager.cc b/src/tests/cefclient/browser/root_window_manager.cc
index f0ad7a5..d256d74 100644
--- a/src/tests/cefclient/browser/root_window_manager.cc
+++ b/src/tests/cefclient/browser/root_window_manager.cc
@@ -6,9 +6,10 @@
 
 #include <sstream>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/base/cef_logging.h"
 #include "include/wrapper/cef_helpers.h"
+#include "tests/cefclient/browser/client_handler_std.h"
 #include "tests/cefclient/browser/main_context.h"
 #include "tests/cefclient/browser/test_runner.h"
 #include "tests/shared/browser/extension_util.h"
@@ -26,24 +27,8 @@
   ClientRequestContextHandler() {}
 
   // CefRequestContextHandler methods:
-  bool OnBeforePluginLoad(const CefString& mime_type,
-                          const CefString& plugin_url,
-                          bool is_main_frame,
-                          const CefString& top_origin_url,
-                          CefRefPtr<CefWebPluginInfo> plugin_info,
-                          PluginPolicy* plugin_policy) OVERRIDE {
-    // Always allow the PDF plugin to load.
-    if (*plugin_policy != PLUGIN_POLICY_ALLOW &&
-        mime_type == "application/pdf") {
-      *plugin_policy = PLUGIN_POLICY_ALLOW;
-      return true;
-    }
-
-    return false;
-  }
-
   void OnRequestContextInitialized(
-      CefRefPtr<CefRequestContext> request_context) OVERRIDE {
+      CefRefPtr<CefRequestContext> request_context) override {
     CEF_REQUIRE_UI_THREAD();
 
     CefRefPtr<CefCommandLine> command_line =
@@ -67,22 +52,31 @@
         std::string part;
         std::istringstream f(extension_path);
         while (getline(f, part, ';')) {
-          if (!part.empty())
+          if (!part.empty()) {
             extension_util::LoadExtension(request_context, part, this);
+          }
         }
       }
     }
+
+    // Allow the startup URL to create popups that bypass the popup blocker.
+    // For example, via Tests > New Popup from the top menu. This applies for
+    // for the Chrome runtime only.
+    const auto& startup_url = MainContext::Get()->GetMainURL();
+    request_context->SetContentSetting(startup_url, startup_url,
+                                       CEF_CONTENT_SETTING_TYPE_POPUPS,
+                                       CEF_CONTENT_SETTING_VALUE_ALLOW);
   }
 
   // CefExtensionHandler methods:
-  void OnExtensionLoaded(CefRefPtr<CefExtension> extension) OVERRIDE {
+  void OnExtensionLoaded(CefRefPtr<CefExtension> extension) override {
     CEF_REQUIRE_UI_THREAD();
     MainContext::Get()->GetRootWindowManager()->AddExtension(extension);
   }
 
   CefRefPtr<CefBrowser> GetActiveBrowser(CefRefPtr<CefExtension> extension,
                                          CefRefPtr<CefBrowser> browser,
-                                         bool include_incognito) OVERRIDE {
+                                         bool include_incognito) override {
     CEF_REQUIRE_UI_THREAD();
 
     // Return the browser for the active/foreground window.
@@ -123,13 +117,13 @@
 }
 
 scoped_refptr<RootWindow> RootWindowManager::CreateRootWindow(
-    const RootWindowConfig& config) {
+    std::unique_ptr<RootWindowConfig> config) {
   CefBrowserSettings settings;
   MainContext::Get()->PopulateBrowserSettings(&settings);
 
   scoped_refptr<RootWindow> root_window =
       RootWindow::Create(MainContext::Get()->UseViews());
-  root_window->Init(this, config, settings);
+  root_window->Init(this, std::move(config), settings);
 
   // Store a reference to the root window on the main thread.
   OnRootWindowCreated(root_window);
@@ -146,13 +140,21 @@
     CefBrowserSettings& settings) {
   CEF_REQUIRE_UI_THREAD();
 
+  MainContext::Get()->PopulateBrowserSettings(&settings);
+
+  if (MainContext::Get()->UseDefaultPopup()) {
+    // Use default window creation for the popup. A new |client| instance is
+    // still required by cefclient architecture.
+    client = new ClientHandlerStd(/*delegate=*/nullptr, with_controls,
+                                  /*startup_url=*/CefString());
+    return nullptr;
+  }
+
   if (!temp_window_) {
     // TempWindow must be created on the UI thread.
     temp_window_.reset(new TempWindow());
   }
 
-  MainContext::Get()->PopulateBrowserSettings(&settings);
-
   scoped_refptr<RootWindow> root_window =
       RootWindow::Create(MainContext::Get()->UseViews());
   root_window->InitAsPopup(this, with_controls, with_osr, popupFeatures,
@@ -168,7 +170,7 @@
     CefRefPtr<CefExtension> extension,
     const CefRect& source_bounds,
     CefRefPtr<CefWindow> parent_window,
-    const base::Closure& close_callback,
+    base::OnceClosure close_callback,
     bool with_controls,
     bool with_osr) {
   const std::string& extension_url = extension_util::GetExtensionURL(extension);
@@ -180,37 +182,38 @@
   // Create an initially hidden browser window that loads the extension URL.
   // We'll show the window when the desired size becomes available via
   // ClientHandler::OnAutoResize.
-  RootWindowConfig config;
-  config.with_controls = with_controls;
-  config.with_osr = with_osr;
-  config.with_extension = true;
-  config.initially_hidden = true;
-  config.source_bounds = source_bounds;
-  config.parent_window = parent_window;
-  config.close_callback = close_callback;
-  config.url = extension_url;
-  return CreateRootWindow(config);
+  auto config = std::make_unique<RootWindowConfig>();
+  config->window_type = WindowType::EXTENSION;
+  config->with_controls = with_controls;
+  config->with_osr = with_osr;
+  config->initially_hidden = true;
+  config->source_bounds = source_bounds;
+  config->parent_window = parent_window;
+  config->close_callback = std::move(close_callback);
+  config->url = extension_url;
+  return CreateRootWindow(std::move(config));
 }
 
 bool RootWindowManager::HasRootWindowAsExtension(
     CefRefPtr<CefExtension> extension) {
   REQUIRE_MAIN_THREAD();
 
-  RootWindowSet::const_iterator it = root_windows_.begin();
-  for (; it != root_windows_.end(); ++it) {
-    const RootWindow* root_window = (*it);
-    if (!root_window->WithExtension())
+  for (auto root_window : root_windows_) {
+    if (!root_window->WithExtension()) {
       continue;
+    }
 
     CefRefPtr<CefBrowser> browser = root_window->GetBrowser();
-    if (!browser)
+    if (!browser) {
       continue;
+    }
 
     CefRefPtr<CefExtension> browser_extension =
         browser->GetHost()->GetExtension();
     DCHECK(browser_extension);
-    if (browser_extension->GetIdentifier() == extension->GetIdentifier())
+    if (browser_extension->GetIdentifier() == extension->GetIdentifier()) {
       return true;
+    }
   }
 
   return false;
@@ -220,11 +223,11 @@
     int browser_id) const {
   REQUIRE_MAIN_THREAD();
 
-  RootWindowSet::const_iterator it = root_windows_.begin();
-  for (; it != root_windows_.end(); ++it) {
-    CefRefPtr<CefBrowser> browser = (*it)->GetBrowser();
-    if (browser.get() && browser->GetIdentifier() == browser_id)
-      return *it;
+  for (auto root_window : root_windows_) {
+    CefRefPtr<CefBrowser> browser = root_window->GetBrowser();
+    if (browser.get() && browser->GetIdentifier() == browser_id) {
+      return root_window;
+    }
   }
   return nullptr;
 }
@@ -242,40 +245,43 @@
 void RootWindowManager::CloseAllWindows(bool force) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
-    MAIN_POST_CLOSURE(base::Bind(&RootWindowManager::CloseAllWindows,
-                                 base::Unretained(this), force));
+    MAIN_POST_CLOSURE(base::BindOnce(&RootWindowManager::CloseAllWindows,
+                                     base::Unretained(this), force));
     return;
   }
 
-  if (root_windows_.empty())
+  if (root_windows_.empty()) {
     return;
+  }
 
   // Use a copy of |root_windows_| because the original set may be modified
   // in OnRootWindowDestroyed while iterating.
   RootWindowSet root_windows = root_windows_;
 
-  RootWindowSet::const_iterator it = root_windows.begin();
-  for (; it != root_windows.end(); ++it)
-    (*it)->Close(force);
+  for (auto root_window : root_windows) {
+    root_window->Close(force);
+  }
 }
 
 void RootWindowManager::AddExtension(CefRefPtr<CefExtension> extension) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
-    MAIN_POST_CLOSURE(base::Bind(&RootWindowManager::AddExtension,
-                                 base::Unretained(this), extension));
+    MAIN_POST_CLOSURE(base::BindOnce(&RootWindowManager::AddExtension,
+                                     base::Unretained(this), extension));
     return;
   }
 
   // Don't track extensions that can't be loaded directly.
-  if (extension_util::GetExtensionURL(extension).empty())
+  if (extension_util::GetExtensionURL(extension).empty()) {
     return;
+  }
 
   // Don't add the same extension multiple times.
   ExtensionSet::const_iterator it = extensions_.begin();
   for (; it != extensions_.end(); ++it) {
-    if ((*it)->GetIdentifier() == extension->GetIdentifier())
+    if ((*it)->GetIdentifier() == extension->GetIdentifier()) {
       return;
+    }
   }
 
   extensions_.insert(extension);
@@ -286,8 +292,8 @@
     scoped_refptr<RootWindow> root_window) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
-    MAIN_POST_CLOSURE(base::Bind(&RootWindowManager::OnRootWindowCreated,
-                                 base::Unretained(this), root_window));
+    MAIN_POST_CLOSURE(base::BindOnce(&RootWindowManager::OnRootWindowCreated,
+                                     base::Unretained(this), root_window));
     return;
   }
 
@@ -298,7 +304,7 @@
     if (root_windows_.size() == 1U) {
       // The first non-extension root window should be considered the active
       // window.
-      OnRootWindowActivated(root_window);
+      OnRootWindowActivated(root_window.get());
     }
   }
 }
@@ -306,11 +312,10 @@
 void RootWindowManager::NotifyExtensionsChanged() {
   REQUIRE_MAIN_THREAD();
 
-  RootWindowSet::const_iterator it = root_windows_.begin();
-  for (; it != root_windows_.end(); ++it) {
-    RootWindow* root_window = *it;
-    if (!root_window->WithExtension())
+  for (auto root_window : root_windows_) {
+    if (!root_window->WithExtension()) {
       root_window->OnExtensionsChanged(extensions_);
+    }
   }
 }
 
@@ -335,7 +340,7 @@
         // isolated context objects.
         std::stringstream ss;
         ss << command_line->GetSwitchValue(switches::kCachePath).ToString()
-           << file_util::kPathSep << time(NULL);
+           << file_util::kPathSep << time(nullptr);
         CefString(&settings.cache_path) = ss.str();
       }
     }
@@ -378,8 +383,9 @@
 
   RootWindowSet::iterator it = root_windows_.find(root_window);
   DCHECK(it != root_windows_.end());
-  if (it != root_windows_.end())
+  if (it != root_windows_.end()) {
     root_windows_.erase(it);
+  }
 
   if (root_window == active_root_window_) {
     active_root_window_ = nullptr;
@@ -390,8 +396,8 @@
 
   if (terminate_when_all_windows_closed_ && root_windows_.empty()) {
     // All windows have closed. Clean up on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&RootWindowManager::CleanupOnUIThread,
-                                   base::Unretained(this)));
+    CefPostTask(TID_UI, base::BindOnce(&RootWindowManager::CleanupOnUIThread,
+                                       base::Unretained(this)));
   }
 }
 
@@ -403,14 +409,15 @@
     return;
   }
 
-  if (root_window == active_root_window_)
+  if (root_window == active_root_window_) {
     return;
+  }
 
   active_root_window_ = root_window;
 
   {
     base::AutoLock lock_scope(active_browser_lock_);
-    // May be NULL at this point, in which case we'll make the association in
+    // May be nullptr at this point, in which case we'll make the association in
     // OnBrowserCreated.
     active_browser_ = active_root_window_->GetBrowser();
   }
@@ -430,13 +437,13 @@
     CefRefPtr<CefExtension> extension,
     const CefRect& source_bounds,
     CefRefPtr<CefWindow> parent_window,
-    const base::Closure& close_callback,
+    base::OnceClosure close_callback,
     bool with_osr) {
   REQUIRE_MAIN_THREAD();
 
   if (!HasRootWindowAsExtension(extension)) {
     CreateRootWindowAsExtension(extension, source_bounds, parent_window,
-                                close_callback, false, with_osr);
+                                std::move(close_callback), false, with_osr);
   }
 }
 
diff --git a/src/tests/cefclient/browser/root_window_manager.h b/src/tests/cefclient/browser/root_window_manager.h
index 18cf8dd..82f4e17 100644
--- a/src/tests/cefclient/browser/root_window_manager.h
+++ b/src/tests/cefclient/browser/root_window_manager.h
@@ -6,9 +6,9 @@
 #define CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_MANAGER_H_
 #pragma once
 
+#include <memory>
 #include <set>
 
-#include "include/base/cef_scoped_ptr.h"
 #include "include/cef_command_line.h"
 #include "include/cef_request_context_handler.h"
 #include "tests/cefclient/browser/image_cache.h"
@@ -27,7 +27,8 @@
 
   // Create a new top-level native window. This method can be called from
   // anywhere.
-  scoped_refptr<RootWindow> CreateRootWindow(const RootWindowConfig& config);
+  scoped_refptr<RootWindow> CreateRootWindow(
+      std::unique_ptr<RootWindowConfig> config);
 
   // Create a new native popup window.
   // If |with_controls| is true the window will show controls.
@@ -50,7 +51,7 @@
       CefRefPtr<CefExtension> extension,
       const CefRect& source_bounds,
       CefRefPtr<CefWindow> parent_window,
-      const base::Closure& close_callback,
+      base::OnceClosure close_callback,
       bool with_controls,
       bool with_osr);
 
@@ -62,12 +63,12 @@
   // called on the main thread.
   scoped_refptr<RootWindow> GetWindowForBrowser(int browser_id) const;
 
-  // Returns the currently active/foreground RootWindow. May return NULL. Must
-  // be called on the main thread.
+  // Returns the currently active/foreground RootWindow. May return nullptr.
+  // Must be called on the main thread.
   scoped_refptr<RootWindow> GetActiveRootWindow() const;
 
-  // Returns the currently active/foreground browser. May return NULL. Safe to
-  // call from any thread.
+  // Returns the currently active/foreground browser. May return nullptr. Safe
+  // to call from any thread.
   CefRefPtr<CefBrowser> GetActiveBrowser() const;
 
   // Close all existing windows. If |force| is true onunload handlers will not
@@ -83,8 +84,8 @@
   }
 
  private:
-  // Allow deletion via scoped_ptr only.
-  friend struct base::DefaultDeleter<RootWindowManager>;
+  // Allow deletion via std::unique_ptr only.
+  friend std::default_delete<RootWindowManager>;
 
   ~RootWindowManager();
 
@@ -93,19 +94,19 @@
 
   // RootWindow::Delegate methods.
   CefRefPtr<CefRequestContext> GetRequestContext(
-      RootWindow* root_window) OVERRIDE;
-  scoped_refptr<ImageCache> GetImageCache() OVERRIDE;
-  void OnTest(RootWindow* root_window, int test_id) OVERRIDE;
-  void OnExit(RootWindow* root_window) OVERRIDE;
-  void OnRootWindowDestroyed(RootWindow* root_window) OVERRIDE;
-  void OnRootWindowActivated(RootWindow* root_window) OVERRIDE;
+      RootWindow* root_window) override;
+  scoped_refptr<ImageCache> GetImageCache() override;
+  void OnTest(RootWindow* root_window, int test_id) override;
+  void OnExit(RootWindow* root_window) override;
+  void OnRootWindowDestroyed(RootWindow* root_window) override;
+  void OnRootWindowActivated(RootWindow* root_window) override;
   void OnBrowserCreated(RootWindow* root_window,
-                        CefRefPtr<CefBrowser> browser) OVERRIDE;
+                        CefRefPtr<CefBrowser> browser) override;
   void CreateExtensionWindow(CefRefPtr<CefExtension> extension,
                              const CefRect& source_bounds,
                              CefRefPtr<CefWindow> parent_window,
-                             const base::Closure& close_callback,
-                             bool with_osr) OVERRIDE;
+                             base::OnceClosure close_callback,
+                             bool with_osr) override;
 
   void CleanupOnUIThread();
 
@@ -127,7 +128,7 @@
   CefRefPtr<CefBrowser> active_browser_;
 
   // Singleton window used as the temporary parent for popup browsers.
-  scoped_ptr<TempWindow> temp_window_;
+  std::unique_ptr<TempWindow> temp_window_;
 
   CefRefPtr<CefRequestContext> shared_request_context_;
 
diff --git a/src/tests/cefclient/browser/root_window_views.cc b/src/tests/cefclient/browser/root_window_views.cc
index 0165a9c..f5f0ff2 100644
--- a/src/tests/cefclient/browser/root_window_views.cc
+++ b/src/tests/cefclient/browser/root_window_views.cc
@@ -4,11 +4,14 @@
 
 #include "tests/cefclient/browser/root_window_views.h"
 
-#include "include/base/cef_bind.h"
+#include <memory>
+
 #include "include/base/cef_build.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_app.h"
 #include "include/wrapper/cef_helpers.h"
 #include "tests/cefclient/browser/client_handler_std.h"
+#include "tests/cefclient/browser/client_prefs.h"
 
 namespace client {
 
@@ -19,48 +22,33 @@
 
 }  // namespace
 
-RootWindowViews::RootWindowViews()
-    : with_controls_(false),
-      always_on_top_(false),
-      with_extension_(false),
-      initially_hidden_(false),
-      is_popup_(false),
-      position_on_resize_(false),
-      initialized_(false),
-      window_destroyed_(false),
-      browser_destroyed_(false) {}
+RootWindowViews::RootWindowViews() = default;
 
 RootWindowViews::~RootWindowViews() {
   REQUIRE_MAIN_THREAD();
 }
 
+void RootWindowViews::SetTitlebarHeight(const std::optional<float>& height) {
+  if (window_) {
+    window_->SetTitlebarHeight(height);
+  }
+}
+
 void RootWindowViews::Init(RootWindow::Delegate* delegate,
-                           const RootWindowConfig& config,
+                           std::unique_ptr<RootWindowConfig> config,
                            const CefBrowserSettings& settings) {
   DCHECK(delegate);
-  DCHECK(!config.with_osr);  // Windowless rendering is not supported.
+  DCHECK(!config->with_osr);  // Windowless rendering is not supported.
   DCHECK(!initialized_);
 
   delegate_ = delegate;
-  with_controls_ = config.with_controls;
-  always_on_top_ = config.always_on_top;
-  with_extension_ = config.with_extension;
-  initially_hidden_ = config.initially_hidden;
-  if (initially_hidden_ && !config.source_bounds.IsEmpty()) {
-    // The window will be sized and positioned in OnAutoResize().
-    initial_bounds_ = config.source_bounds;
-    position_on_resize_ = true;
-  } else {
-    initial_bounds_ = config.bounds;
-  }
-  parent_window_ = config.parent_window;
-  close_callback_ = config.close_callback;
+  config_ = std::move(config);
 
-  CreateClientHandler(config.url);
+  CreateClientHandler(config_->url);
   initialized_ = true;
 
   // Continue initialization on the UI thread.
-  InitOnUIThread(settings, config.url, delegate_->GetRequestContext(this));
+  InitOnUIThread(settings, delegate_->GetRequestContext(this));
 }
 
 void RootWindowViews::InitAsPopup(RootWindow::Delegate* delegate,
@@ -77,17 +65,21 @@
   DCHECK(!initialized_);
 
   delegate_ = delegate;
-  with_controls_ = with_controls;
-  is_popup_ = true;
+  config_ = std::make_unique<RootWindowConfig>();
+  config_->with_controls = with_controls;
 
-  if (popupFeatures.xSet)
+  if (popupFeatures.xSet) {
     initial_bounds_.x = popupFeatures.x;
-  if (popupFeatures.ySet)
+  }
+  if (popupFeatures.ySet) {
     initial_bounds_.y = popupFeatures.y;
-  if (popupFeatures.widthSet)
+  }
+  if (popupFeatures.widthSet) {
     initial_bounds_.width = popupFeatures.width;
-  if (popupFeatures.heightSet)
+  }
+  if (popupFeatures.heightSet) {
     initial_bounds_.height = popupFeatures.height;
+  }
 
   CreateClientHandler(std::string());
   initialized_ = true;
@@ -99,12 +91,13 @@
 void RootWindowViews::Show(ShowMode mode) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&RootWindowViews::Show, this, mode));
+    CefPostTask(TID_UI, base::BindOnce(&RootWindowViews::Show, this, mode));
     return;
   }
 
-  if (!window_)
+  if (!window_) {
     return;
+  }
 
   window_->Show();
 
@@ -123,19 +116,20 @@
 void RootWindowViews::Hide() {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&RootWindowViews::Hide, this));
+    CefPostTask(TID_UI, base::BindOnce(&RootWindowViews::Hide, this));
     return;
   }
 
-  if (window_)
+  if (window_) {
     window_->Hide();
+  }
 }
 
 void RootWindowViews::SetBounds(int x, int y, size_t width, size_t height) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&RootWindowViews::SetBounds, this, x, y,
-                                   width, height));
+    CefPostTask(TID_UI, base::BindOnce(&RootWindowViews::SetBounds, this, x, y,
+                                       width, height));
     return;
   }
 
@@ -148,12 +142,13 @@
 void RootWindowViews::Close(bool force) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&RootWindowViews::Close, this, force));
+    CefPostTask(TID_UI, base::BindOnce(&RootWindowViews::Close, this, force));
     return;
   }
 
-  if (window_)
+  if (window_) {
     window_->Close(force);
+  }
 }
 
 void RootWindowViews::SetDeviceScaleFactor(float device_scale_factor) {
@@ -178,34 +173,30 @@
   REQUIRE_MAIN_THREAD();
 #if defined(OS_LINUX)
   // ClientWindowHandle is a GtkWidget* on Linux and we don't have one of those.
-  return NULL;
+  return nullptr;
 #else
-  if (browser_)
+  if (browser_) {
     return browser_->GetHost()->GetWindowHandle();
+  }
   return kNullWindowHandle;
 #endif
 }
 
 bool RootWindowViews::WithExtension() const {
   DCHECK(initialized_);
-  return with_extension_;
+  return config_->window_type == WindowType::EXTENSION;
 }
 
 bool RootWindowViews::WithControls() {
   DCHECK(initialized_);
-  return with_controls_;
-}
-
-bool RootWindowViews::WithExtension() {
-  DCHECK(initialized_);
-  return with_extension_;
+  return config_->with_controls;
 }
 
 void RootWindowViews::OnExtensionsChanged(const ExtensionSet& extensions) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&RootWindowViews::OnExtensionsChanged, this,
-                                   extensions));
+    CefPostTask(TID_UI, base::BindOnce(&RootWindowViews::OnExtensionsChanged,
+                                       this, extensions));
     return;
   }
 
@@ -219,19 +210,24 @@
 
 bool RootWindowViews::InitiallyHidden() {
   CEF_REQUIRE_UI_THREAD();
-  return initially_hidden_;
+  return config_->initially_hidden;
 }
 
 CefRefPtr<CefWindow> RootWindowViews::GetParentWindow() {
   CEF_REQUIRE_UI_THREAD();
-  return parent_window_;
+  return config_->parent_window;
 }
 
-CefRect RootWindowViews::GetWindowBounds() {
+CefRect RootWindowViews::GetInitialBounds() {
   CEF_REQUIRE_UI_THREAD();
   return initial_bounds_;
 }
 
+cef_show_state_t RootWindowViews::GetInitialShowState() {
+  CEF_REQUIRE_UI_THREAD();
+  return initial_show_state_;
+}
+
 scoped_refptr<ImageCache> RootWindowViews::GetImageCache() {
   CEF_REQUIRE_UI_THREAD();
   return image_cache_;
@@ -241,7 +237,7 @@
   CEF_REQUIRE_UI_THREAD();
   DCHECK(!window_);
   window_ = window;
-  window_->SetAlwaysOnTop(always_on_top_);
+  window_->SetAlwaysOnTop(config_->always_on_top);
 
   if (!pending_extensions_.empty()) {
     window_->OnExtensionsChanged(pending_extensions_);
@@ -249,13 +245,28 @@
   }
 }
 
+void RootWindowViews::OnViewsWindowClosing(CefRefPtr<ViewsWindow> window) {
+  CEF_REQUIRE_UI_THREAD();
+  DCHECK(window_);
+
+  if (!window_->SupportsWindowRestore()) {
+    return;
+  }
+
+  cef_show_state_t show_state;
+  std::optional<CefRect> dip_bounds;
+  if (window_->GetWindowRestorePreferences(show_state, dip_bounds)) {
+    prefs::SaveWindowRestorePreferences(show_state, dip_bounds);
+  }
+}
+
 void RootWindowViews::OnViewsWindowDestroyed(CefRefPtr<ViewsWindow> window) {
   CEF_REQUIRE_UI_THREAD();
   window_ = nullptr;
 
   // Continue on the main thread.
   MAIN_POST_CLOSURE(
-      base::Bind(&RootWindowViews::NotifyViewsWindowDestroyed, this));
+      base::BindOnce(&RootWindowViews::NotifyViewsWindowDestroyed, this));
 }
 
 void RootWindowViews::OnViewsWindowActivated(CefRefPtr<ViewsWindow> window) {
@@ -263,7 +274,7 @@
 
   // Continue on the main thread.
   MAIN_POST_CLOSURE(
-      base::Bind(&RootWindowViews::NotifyViewsWindowActivated, this));
+      base::BindOnce(&RootWindowViews::NotifyViewsWindowActivated, this));
 }
 
 ViewsWindow::Delegate* RootWindowViews::GetDelegateForPopup(
@@ -274,33 +285,35 @@
   RootWindowViews* root_window =
       static_cast<RootWindowViews*>(handler->delegate());
 
-  // Transfer some state to the child RootWindowViews.
-  root_window->image_cache_ = image_cache_;
+  // May be nullptr when using the default popup behavior.
+  if (root_window) {
+    // Transfer some state to the child RootWindowViews.
+    root_window->image_cache_ = image_cache_;
+  }
 
   return root_window;
 }
 
-void RootWindowViews::CreateExtensionWindow(
-    CefRefPtr<CefExtension> extension,
-    const CefRect& source_bounds,
-    CefRefPtr<CefWindow> parent_window,
-    const base::Closure& close_callback) {
+void RootWindowViews::CreateExtensionWindow(CefRefPtr<CefExtension> extension,
+                                            const CefRect& source_bounds,
+                                            CefRefPtr<CefWindow> parent_window,
+                                            base::OnceClosure close_callback) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
-    MAIN_POST_CLOSURE(base::Bind(&RootWindowViews::CreateExtensionWindow, this,
-                                 extension, source_bounds, parent_window,
-                                 close_callback));
+    MAIN_POST_CLOSURE(base::BindOnce(&RootWindowViews::CreateExtensionWindow,
+                                     this, extension, source_bounds,
+                                     parent_window, std::move(close_callback)));
     return;
   }
 
   delegate_->CreateExtensionWindow(extension, source_bounds, parent_window,
-                                   close_callback, false);
+                                   std::move(close_callback), false);
 }
 
 void RootWindowViews::OnTest(int test_id) {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
-    MAIN_POST_CLOSURE(base::Bind(&RootWindowViews::OnTest, this, test_id));
+    MAIN_POST_CLOSURE(base::BindOnce(&RootWindowViews::OnTest, this, test_id));
     return;
   }
 
@@ -310,7 +323,7 @@
 void RootWindowViews::OnExit() {
   if (!CURRENTLY_ON_MAIN_THREAD()) {
     // Execute this method on the main thread.
-    MAIN_POST_CLOSURE(base::Bind(&RootWindowViews::OnExit, this));
+    MAIN_POST_CLOSURE(base::BindOnce(&RootWindowViews::OnExit, this));
     return;
   }
 
@@ -346,54 +359,60 @@
 void RootWindowViews::OnSetAddress(const std::string& url) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&RootWindowViews::OnSetAddress, this, url));
+    CefPostTask(TID_UI,
+                base::BindOnce(&RootWindowViews::OnSetAddress, this, url));
     return;
   }
 
-  if (window_ && with_controls_)
+  if (window_) {
     window_->SetAddress(url);
+  }
 }
 
 void RootWindowViews::OnSetTitle(const std::string& title) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&RootWindowViews::OnSetTitle, this, title));
+    CefPostTask(TID_UI,
+                base::BindOnce(&RootWindowViews::OnSetTitle, this, title));
     return;
   }
 
-  if (window_)
+  if (window_) {
     window_->SetTitle(title);
+  }
 }
 
 void RootWindowViews::OnSetFavicon(CefRefPtr<CefImage> image) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
     CefPostTask(TID_UI,
-                base::Bind(&RootWindowViews::OnSetFavicon, this, image));
+                base::BindOnce(&RootWindowViews::OnSetFavicon, this, image));
     return;
   }
 
-  if (window_)
+  if (window_) {
     window_->SetFavicon(image);
+  }
 }
 
 void RootWindowViews::OnSetFullscreen(bool fullscreen) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&RootWindowViews::OnSetFullscreen, this,
-                                   fullscreen));
+    CefPostTask(TID_UI, base::BindOnce(&RootWindowViews::OnSetFullscreen, this,
+                                       fullscreen));
     return;
   }
 
-  if (window_)
+  if (window_) {
     window_->SetFullscreen(fullscreen);
+  }
 }
 
 void RootWindowViews::OnAutoResize(const CefSize& new_size) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
     CefPostTask(TID_UI,
-                base::Bind(&RootWindowViews::OnAutoResize, this, new_size));
+                base::BindOnce(&RootWindowViews::OnAutoResize, this, new_size));
     return;
   }
 
@@ -421,14 +440,14 @@
                                         bool canGoForward) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&RootWindowViews::OnSetLoadingState, this,
-                                   isLoading, canGoBack, canGoForward));
+    CefPostTask(TID_UI,
+                base::BindOnce(&RootWindowViews::OnSetLoadingState, this,
+                               isLoading, canGoBack, canGoForward));
     return;
   }
 
   if (window_) {
-    if (with_controls_)
-      window_->SetLoadingState(isLoading, canGoBack, canGoForward);
+    window_->SetLoadingState(isLoading, canGoBack, canGoForward);
 
     if (isLoading) {
       // Reset to the default window icon when loading begins.
@@ -442,65 +461,86 @@
     const std::vector<CefDraggableRegion>& regions) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&RootWindowViews::OnSetDraggableRegions,
-                                   this, regions));
+    CefPostTask(TID_UI, base::BindOnce(&RootWindowViews::OnSetDraggableRegions,
+                                       this, regions));
     return;
   }
 
-  if (window_)
+  if (window_) {
     window_->SetDraggableRegions(regions);
+  }
 }
 
 void RootWindowViews::OnTakeFocus(bool next) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&RootWindowViews::OnTakeFocus, this, next));
+    CefPostTask(TID_UI,
+                base::BindOnce(&RootWindowViews::OnTakeFocus, this, next));
     return;
   }
 
-  if (window_)
+  if (window_) {
     window_->TakeFocus(next);
+  }
 }
 
 void RootWindowViews::OnBeforeContextMenu(CefRefPtr<CefMenuModel> model) {
   CEF_REQUIRE_UI_THREAD();
-  if (window_)
+  if (window_) {
     window_->OnBeforeContextMenu(model);
+  }
 }
 
 void RootWindowViews::CreateClientHandler(const std::string& url) {
   DCHECK(!client_handler_);
 
-  client_handler_ = new ClientHandlerStd(this, url);
+  client_handler_ = new ClientHandlerStd(this, config_->with_controls, url);
   client_handler_->set_download_favicon_images(true);
 }
 
 void RootWindowViews::InitOnUIThread(
     const CefBrowserSettings& settings,
-    const std::string& startup_url,
     CefRefPtr<CefRequestContext> request_context) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&RootWindowViews::InitOnUIThread, this,
-                                   settings, startup_url, request_context));
+    CefPostTask(TID_UI, base::BindOnce(&RootWindowViews::InitOnUIThread, this,
+                                       settings, request_context));
     return;
   }
 
+  if (config_->initially_hidden && !config_->source_bounds.IsEmpty()) {
+    // The window will be sized and positioned in OnAutoResize().
+    initial_bounds_ = config_->source_bounds;
+    position_on_resize_ = true;
+  } else if (!config_->bounds.IsEmpty()) {
+    // Initial state was specified via the config object.
+    initial_bounds_ = config_->bounds;
+    initial_show_state_ = config_->show_state;
+  } else if (ViewsWindow::SupportsWindowRestore(config_->window_type)) {
+    // Initial state may be specified via the command-line or global
+    // preferences.
+    std::optional<CefRect> bounds;
+    if (prefs::LoadWindowRestorePreferences(initial_show_state_, bounds) &&
+        bounds) {
+      initial_bounds_ = *bounds;
+    }
+  }
+
   image_cache_ = delegate_->GetImageCache();
 
   // Populate the default image cache.
   ImageCache::ImageInfoSet image_set;
-  for (size_t i = 0U; i < arraysize(kDefaultImageCache); ++i)
+  for (size_t i = 0U; i < std::size(kDefaultImageCache); ++i) {
     image_set.push_back(ImageCache::ImageInfo::Create2x(kDefaultImageCache[i]));
+  }
 
   image_cache_->LoadImages(
-      image_set, base::Bind(&RootWindowViews::CreateViewsWindow, this, settings,
-                            startup_url, request_context));
+      image_set, base::BindOnce(&RootWindowViews::CreateViewsWindow, this,
+                                settings, request_context));
 }
 
 void RootWindowViews::CreateViewsWindow(
     const CefBrowserSettings& settings,
-    const std::string& startup_url,
     CefRefPtr<CefRequestContext> request_context,
     const ImageCache::ImageSet& images) {
   CEF_REQUIRE_UI_THREAD();
@@ -508,15 +548,15 @@
 
 #ifndef NDEBUG
   // Make sure the default images loaded successfully.
-  DCHECK_EQ(images.size(), arraysize(kDefaultImageCache));
-  for (size_t i = 0U; i < arraysize(kDefaultImageCache); ++i) {
+  DCHECK_EQ(images.size(), std::size(kDefaultImageCache));
+  for (size_t i = 0U; i < std::size(kDefaultImageCache); ++i) {
     DCHECK(images[i]) << "Default image " << i << " failed to load";
   }
 #endif
 
   // Create the ViewsWindow. It will show itself after creation.
-  ViewsWindow::Create(this, client_handler_, startup_url, settings,
-                      request_context);
+  ViewsWindow::Create(config_->window_type, this, client_handler_, config_->url,
+                      settings, request_context);
 }
 
 void RootWindowViews::NotifyViewsWindowDestroyed() {
@@ -533,9 +573,14 @@
 void RootWindowViews::NotifyDestroyedIfDone() {
   // Notify once both the window and the browser have been destroyed.
   if (window_destroyed_ && browser_destroyed_) {
+    // The delegate may be holding the last reference to |this|, so take a
+    // reference here to keep |this| alive until after the method completes.
+    scoped_refptr<RootWindow> self = this;
+
     delegate_->OnRootWindowDestroyed(this);
-    if (!close_callback_.is_null())
-      close_callback_.Run();
+    if (!config_->close_callback.is_null()) {
+      std::move(config_->close_callback).Run();
+    }
   }
 }
 
diff --git a/src/tests/cefclient/browser/root_window_views.h b/src/tests/cefclient/browser/root_window_views.h
index 1c719c4..c6ce556 100644
--- a/src/tests/cefclient/browser/root_window_views.h
+++ b/src/tests/cefclient/browser/root_window_views.h
@@ -6,9 +6,9 @@
 #define CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_VIEWS_H_
 #pragma once
 
+#include <memory>
 #include <string>
 
-#include "include/base/cef_scoped_ptr.h"
 #include "tests/cefclient/browser/client_handler.h"
 #include "tests/cefclient/browser/root_window.h"
 #include "tests/cefclient/browser/views_window.h"
@@ -26,74 +26,75 @@
   RootWindowViews();
   ~RootWindowViews();
 
+  void SetTitlebarHeight(const std::optional<float>& height);
+
   // RootWindow methods:
   void Init(RootWindow::Delegate* delegate,
-            const RootWindowConfig& config,
-            const CefBrowserSettings& settings) OVERRIDE;
+            std::unique_ptr<RootWindowConfig> config,
+            const CefBrowserSettings& settings) override;
   void InitAsPopup(RootWindow::Delegate* delegate,
                    bool with_controls,
                    bool with_osr,
                    const CefPopupFeatures& popupFeatures,
                    CefWindowInfo& windowInfo,
                    CefRefPtr<CefClient>& client,
-                   CefBrowserSettings& settings) OVERRIDE;
-  void Show(ShowMode mode) OVERRIDE;
-  void Hide() OVERRIDE;
-  void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
-  void Close(bool force) OVERRIDE;
-  void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE;
-  float GetDeviceScaleFactor() const OVERRIDE;
-  CefRefPtr<CefBrowser> GetBrowser() const OVERRIDE;
-  ClientWindowHandle GetWindowHandle() const OVERRIDE;
-  bool WithWindowlessRendering() const OVERRIDE { return false; }
-  bool WithExtension() const OVERRIDE;
-  void OnExtensionsChanged(const ExtensionSet& extensions) OVERRIDE;
+                   CefBrowserSettings& settings) override;
+  void Show(ShowMode mode) override;
+  void Hide() override;
+  void SetBounds(int x, int y, size_t width, size_t height) override;
+  void Close(bool force) override;
+  void SetDeviceScaleFactor(float device_scale_factor) override;
+  float GetDeviceScaleFactor() const override;
+  CefRefPtr<CefBrowser> GetBrowser() const override;
+  ClientWindowHandle GetWindowHandle() const override;
+  bool WithWindowlessRendering() const override { return false; }
+  bool WithExtension() const override;
+  void OnExtensionsChanged(const ExtensionSet& extensions) override;
 
   // ViewsWindow::Delegate methods:
-  bool WithControls() OVERRIDE;
-  bool WithExtension() OVERRIDE;
-  bool InitiallyHidden() OVERRIDE;
-  CefRefPtr<CefWindow> GetParentWindow() OVERRIDE;
-  CefRect GetWindowBounds() OVERRIDE;
-  scoped_refptr<ImageCache> GetImageCache() OVERRIDE;
-  void OnViewsWindowCreated(CefRefPtr<ViewsWindow> window) OVERRIDE;
-  void OnViewsWindowDestroyed(CefRefPtr<ViewsWindow> window) OVERRIDE;
-  void OnViewsWindowActivated(CefRefPtr<ViewsWindow> window) OVERRIDE;
+  bool WithControls() override;
+  bool InitiallyHidden() override;
+  CefRefPtr<CefWindow> GetParentWindow() override;
+  CefRect GetInitialBounds() override;
+  cef_show_state_t GetInitialShowState() override;
+  scoped_refptr<ImageCache> GetImageCache() override;
+  void OnViewsWindowCreated(CefRefPtr<ViewsWindow> window) override;
+  void OnViewsWindowClosing(CefRefPtr<ViewsWindow> window) override;
+  void OnViewsWindowDestroyed(CefRefPtr<ViewsWindow> window) override;
+  void OnViewsWindowActivated(CefRefPtr<ViewsWindow> window) override;
   ViewsWindow::Delegate* GetDelegateForPopup(
-      CefRefPtr<CefClient> client) OVERRIDE;
+      CefRefPtr<CefClient> client) override;
   void CreateExtensionWindow(CefRefPtr<CefExtension> extension,
                              const CefRect& source_bounds,
                              CefRefPtr<CefWindow> parent_window,
-                             const base::Closure& close_callback) OVERRIDE;
-  void OnTest(int test_id) OVERRIDE;
-  void OnExit() OVERRIDE;
+                             base::OnceClosure close_callback) override;
+  void OnTest(int test_id) override;
+  void OnExit() override;
 
  protected:
   // ClientHandler::Delegate methods:
-  void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void OnBrowserClosing(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void OnBrowserClosed(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void OnSetAddress(const std::string& url) OVERRIDE;
-  void OnSetTitle(const std::string& title) OVERRIDE;
-  void OnSetFavicon(CefRefPtr<CefImage> image) OVERRIDE;
-  void OnSetFullscreen(bool fullscreen) OVERRIDE;
-  void OnAutoResize(const CefSize& new_size) OVERRIDE;
+  void OnBrowserCreated(CefRefPtr<CefBrowser> browser) override;
+  void OnBrowserClosing(CefRefPtr<CefBrowser> browser) override;
+  void OnBrowserClosed(CefRefPtr<CefBrowser> browser) override;
+  void OnSetAddress(const std::string& url) override;
+  void OnSetTitle(const std::string& title) override;
+  void OnSetFavicon(CefRefPtr<CefImage> image) override;
+  void OnSetFullscreen(bool fullscreen) override;
+  void OnAutoResize(const CefSize& new_size) override;
   void OnSetLoadingState(bool isLoading,
                          bool canGoBack,
-                         bool canGoForward) OVERRIDE;
+                         bool canGoForward) override;
   void OnSetDraggableRegions(
-      const std::vector<CefDraggableRegion>& regions) OVERRIDE;
-  void OnTakeFocus(bool next) OVERRIDE;
-  void OnBeforeContextMenu(CefRefPtr<CefMenuModel> model) OVERRIDE;
+      const std::vector<CefDraggableRegion>& regions) override;
+  void OnTakeFocus(bool next) override;
+  void OnBeforeContextMenu(CefRefPtr<CefMenuModel> model) override;
 
  private:
   void CreateClientHandler(const std::string& url);
 
   void InitOnUIThread(const CefBrowserSettings& settings,
-                      const std::string& startup_url,
                       CefRefPtr<CefRequestContext> request_context);
   void CreateViewsWindow(const CefBrowserSettings& settings,
-                         const std::string& startup_url,
                          CefRefPtr<CefRequestContext> request_context,
                          const ImageCache::ImageSet& images);
 
@@ -101,27 +102,20 @@
   void NotifyViewsWindowActivated();
   void NotifyDestroyedIfDone();
 
-  // After initialization all members are only accessed on the main thread
-  // unless otherwise indicated.
-  // Members set during initialization.
-  bool with_controls_;
-  bool always_on_top_;
-  bool with_extension_;
-  bool initially_hidden_;
-  CefRefPtr<CefWindow> parent_window_;
-  bool is_popup_;
-  CefRect initial_bounds_;
-  base::Closure close_callback_;
-  bool position_on_resize_;
+  // Members set during initialization. Safe to access from any thread.
+  std::unique_ptr<RootWindowConfig> config_;
   CefRefPtr<ClientHandler> client_handler_;
+  bool initialized_ = false;
 
-  bool initialized_;
-  bool window_destroyed_;
-  bool browser_destroyed_;
-
+  // Only accessed on the main thread.
   CefRefPtr<CefBrowser> browser_;
+  bool window_destroyed_ = false;
+  bool browser_destroyed_ = false;
 
   // Only accessed on the browser process UI thread.
+  CefRect initial_bounds_;
+  cef_show_state_t initial_show_state_ = CEF_SHOW_STATE_NORMAL;
+  bool position_on_resize_ = false;
   CefRefPtr<ViewsWindow> window_;
   ExtensionSet pending_extensions_;
   scoped_refptr<ImageCache> image_cache_;
diff --git a/src/tests/cefclient/browser/root_window_win.cc b/src/tests/cefclient/browser/root_window_win.cc
index dd208db..19b489b 100644
--- a/src/tests/cefclient/browser/root_window_win.cc
+++ b/src/tests/cefclient/browser/root_window_win.cc
@@ -6,11 +6,15 @@
 
 #include <shellscalingapi.h>
 
-#include "include/base/cef_bind.h"
+#include <optional>
+
 #include "include/base/cef_build.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_app.h"
+#include "include/views/cef_display.h"
 #include "tests/cefclient/browser/browser_window_osr_win.h"
 #include "tests/cefclient/browser/browser_window_std_win.h"
+#include "tests/cefclient/browser/client_prefs.h"
 #include "tests/cefclient/browser/main_context.h"
 #include "tests/cefclient/browser/resource.h"
 #include "tests/cefclient/browser/temp_window.h"
@@ -68,8 +72,9 @@
       if (func_ptr) {
         PROCESS_DPI_AWARENESS awareness;
         if (SUCCEEDED(func_ptr(nullptr, &awareness)) &&
-            awareness == PROCESS_PER_MONITOR_DPI_AWARE)
+            awareness == PROCESS_PER_MONITOR_DPI_AWARE) {
           per_monitor_dpi_aware = PerMonitorDpiAware::PER_MONITOR_DPI_AWARE;
+        }
       }
     }
   }
@@ -84,8 +89,9 @@
     typedef UINT(WINAPI * GetDpiForWindowPtr)(HWND);
     static GetDpiForWindowPtr func_ptr = reinterpret_cast<GetDpiForWindowPtr>(
         GetProcAddress(GetModuleHandle(L"user32.dll"), "GetDpiForWindow"));
-    if (func_ptr)
+    if (func_ptr) {
       return static_cast<float>(func_ptr(hwnd)) / DPI_1X;
+    }
   }
 
   return client::GetDeviceScaleFactor();
@@ -101,35 +107,7 @@
 
 }  // namespace
 
-RootWindowWin::RootWindowWin()
-    : with_controls_(false),
-      always_on_top_(false),
-      with_osr_(false),
-      with_extension_(false),
-      is_popup_(false),
-      start_rect_(),
-      initialized_(false),
-      hwnd_(NULL),
-      draggable_region_(NULL),
-      font_(NULL),
-      font_height_(0),
-      back_hwnd_(NULL),
-      forward_hwnd_(NULL),
-      reload_hwnd_(NULL),
-      stop_hwnd_(NULL),
-      edit_hwnd_(NULL),
-      edit_wndproc_old_(NULL),
-      find_hwnd_(NULL),
-      find_message_id_(0),
-      find_wndproc_old_(NULL),
-      find_state_(),
-      find_next_(false),
-      find_match_case_last_(false),
-      window_destroyed_(false),
-      browser_destroyed_(false),
-      called_enable_non_client_dpi_scaling_(false) {
-  find_buff_[0] = 0;
-
+RootWindowWin::RootWindowWin() {
   // Create a HRGN representing the draggable window area.
   draggable_region_ = ::CreateRectRgn(0, 0, 0, 0);
 }
@@ -146,33 +124,58 @@
 }
 
 void RootWindowWin::Init(RootWindow::Delegate* delegate,
-                         const RootWindowConfig& config,
+                         std::unique_ptr<RootWindowConfig> config,
                          const CefBrowserSettings& settings) {
   DCHECK(delegate);
   DCHECK(!initialized_);
 
   delegate_ = delegate;
-  with_controls_ = config.with_controls;
-  always_on_top_ = config.always_on_top;
-  with_osr_ = config.with_osr;
-  with_extension_ = config.with_extension;
+  with_controls_ = config->with_controls;
+  always_on_top_ = config->always_on_top;
+  with_osr_ = config->with_osr;
+  with_extension_ = config->window_type == WindowType::EXTENSION;
 
-  start_rect_.left = config.bounds.x;
-  start_rect_.top = config.bounds.y;
-  start_rect_.right = config.bounds.x + config.bounds.width;
-  start_rect_.bottom = config.bounds.y + config.bounds.height;
+  CreateBrowserWindow(config->url);
 
-  CreateBrowserWindow(config.url);
+  if (CefCurrentlyOn(TID_UI)) {
+    ContinueInitOnUIThread(std::move(config), settings);
+  } else {
+    CefPostTask(TID_UI, base::BindOnce(&RootWindowWin::ContinueInitOnUIThread,
+                                       this, std::move(config), settings));
+  }
+}
+
+void RootWindowWin::ContinueInitOnUIThread(
+    std::unique_ptr<RootWindowConfig> config,
+    const CefBrowserSettings& settings) {
+  CEF_REQUIRE_UI_THREAD();
+
+  if (!config->bounds.IsEmpty()) {
+    // Initial state was specified via the config object.
+    initial_bounds_ = config->bounds;
+    initial_show_state_ = config->show_state;
+  } else {
+    // Initial state may be specified via the command-line or global
+    // preferences.
+    std::optional<CefRect> bounds;
+    if (prefs::LoadWindowRestorePreferences(initial_show_state_, bounds) &&
+        bounds) {
+      initial_bounds_ = CefDisplay::ConvertScreenRectToPixels(*bounds);
+    }
+  }
+
+  MAIN_POST_CLOSURE(base::BindOnce(&RootWindowWin::ContinueInitOnMainThread,
+                                   this, std::move(config), settings));
+}
+
+void RootWindowWin::ContinueInitOnMainThread(
+    std::unique_ptr<RootWindowConfig> config,
+    const CefBrowserSettings& settings) {
+  REQUIRE_MAIN_THREAD();
 
   initialized_ = true;
 
-  // Create the native root window on the main thread.
-  if (CURRENTLY_ON_MAIN_THREAD()) {
-    CreateRootWindow(settings, config.initially_hidden);
-  } else {
-    MAIN_POST_CLOSURE(base::Bind(&RootWindowWin::CreateRootWindow, this,
-                                 settings, config.initially_hidden));
-  }
+  CreateRootWindow(settings, config->initially_hidden);
 }
 
 void RootWindowWin::InitAsPopup(RootWindow::Delegate* delegate,
@@ -192,14 +195,18 @@
   with_osr_ = with_osr;
   is_popup_ = true;
 
-  if (popupFeatures.xSet)
-    start_rect_.left = popupFeatures.x;
-  if (popupFeatures.ySet)
-    start_rect_.top = popupFeatures.y;
-  if (popupFeatures.widthSet)
-    start_rect_.right = start_rect_.left + popupFeatures.width;
-  if (popupFeatures.heightSet)
-    start_rect_.bottom = start_rect_.top + popupFeatures.height;
+  if (popupFeatures.xSet) {
+    initial_bounds_.x = popupFeatures.x;
+  }
+  if (popupFeatures.ySet) {
+    initial_bounds_.y = popupFeatures.y;
+  }
+  if (popupFeatures.widthSet) {
+    initial_bounds_.width = popupFeatures.width;
+  }
+  if (popupFeatures.heightSet) {
+    initial_bounds_.height = popupFeatures.height;
+  }
 
   CreateBrowserWindow(std::string());
 
@@ -215,8 +222,9 @@
 void RootWindowWin::Show(ShowMode mode) {
   REQUIRE_MAIN_THREAD();
 
-  if (!hwnd_)
+  if (!hwnd_) {
     return;
+  }
 
   int nCmdShow = SW_SHOWNORMAL;
   switch (mode) {
@@ -234,21 +242,24 @@
   }
 
   ShowWindow(hwnd_, nCmdShow);
-  UpdateWindow(hwnd_);
+  if (mode != ShowMinimized) {
+    UpdateWindow(hwnd_);
+  }
 }
 
 void RootWindowWin::Hide() {
   REQUIRE_MAIN_THREAD();
 
-  if (hwnd_)
+  if (hwnd_) {
     ShowWindow(hwnd_, SW_HIDE);
+  }
 }
 
 void RootWindowWin::SetBounds(int x, int y, size_t width, size_t height) {
   REQUIRE_MAIN_THREAD();
 
   if (hwnd_) {
-    SetWindowPos(hwnd_, NULL, x, y, static_cast<int>(width),
+    SetWindowPos(hwnd_, nullptr, x, y, static_cast<int>(width),
                  static_cast<int>(height), SWP_NOZORDER);
   }
 }
@@ -257,25 +268,28 @@
   REQUIRE_MAIN_THREAD();
 
   if (hwnd_) {
-    if (force)
+    if (force) {
       DestroyWindow(hwnd_);
-    else
+    } else {
       PostMessage(hwnd_, WM_CLOSE, 0, 0);
+    }
   }
 }
 
 void RootWindowWin::SetDeviceScaleFactor(float device_scale_factor) {
   REQUIRE_MAIN_THREAD();
 
-  if (browser_window_ && with_osr_)
+  if (browser_window_ && with_osr_) {
     browser_window_->SetDeviceScaleFactor(device_scale_factor);
+  }
 }
 
 float RootWindowWin::GetDeviceScaleFactor() const {
   REQUIRE_MAIN_THREAD();
 
-  if (browser_window_ && with_osr_)
+  if (browser_window_ && with_osr_) {
     return browser_window_->GetDeviceScaleFactor();
+  }
 
   NOTREACHED();
   return 0.0f;
@@ -284,8 +298,9 @@
 CefRefPtr<CefBrowser> RootWindowWin::GetBrowser() const {
   REQUIRE_MAIN_THREAD();
 
-  if (browser_window_)
+  if (browser_window_) {
     return browser_window_->GetBrowser();
+  }
   return nullptr;
 }
 
@@ -308,9 +323,11 @@
   if (with_osr_) {
     OsrRendererSettings settings = {};
     MainContext::Get()->PopulateOsrSettings(&settings);
-    browser_window_.reset(new BrowserWindowOsrWin(this, startup_url, settings));
+    browser_window_.reset(
+        new BrowserWindowOsrWin(this, with_controls_, startup_url, settings));
   } else {
-    browser_window_.reset(new BrowserWindowStdWin(this, startup_url));
+    browser_window_.reset(
+        new BrowserWindowStdWin(this, with_controls_, startup_url));
   }
 }
 
@@ -319,7 +336,7 @@
   REQUIRE_MAIN_THREAD();
   DCHECK(!hwnd_);
 
-  HINSTANCE hInstance = GetModuleHandle(NULL);
+  HINSTANCE hInstance = GetModuleHandle(nullptr);
 
   // Load strings from the resource file.
   const std::wstring& window_title = GetResourceString(IDS_APP_TITLE);
@@ -341,33 +358,44 @@
       CefCommandLine::GetGlobalCommandLine();
   const bool no_activate = command_line->HasSwitch(switches::kNoActivate);
 
-  const DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
+  DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
   DWORD dwExStyle = always_on_top_ ? WS_EX_TOPMOST : 0;
   if (no_activate) {
     // Don't activate the browser window on creation.
     dwExStyle |= WS_EX_NOACTIVATE;
   }
 
+  if (initial_show_state_ == CEF_SHOW_STATE_MAXIMIZED) {
+    dwStyle |= WS_MAXIMIZE;
+  } else if (initial_show_state_ == CEF_SHOW_STATE_MINIMIZED) {
+    dwStyle |= WS_MINIMIZE;
+  }
+
   int x, y, width, height;
-  if (::IsRectEmpty(&start_rect_)) {
+  if (initial_bounds_.IsEmpty()) {
     // Use the default window position/size.
     x = y = width = height = CW_USEDEFAULT;
   } else {
-    // Adjust the window size to account for window frame and controls.
-    RECT window_rect = start_rect_;
-    ::AdjustWindowRectEx(&window_rect, dwStyle, with_controls_, dwExStyle);
+    x = initial_bounds_.x;
+    y = initial_bounds_.y;
+    width = initial_bounds_.width;
+    height = initial_bounds_.height;
 
-    x = start_rect_.left;
-    y = start_rect_.top;
-    width = window_rect.right - window_rect.left;
-    height = window_rect.bottom - window_rect.top;
+    if (is_popup_) {
+      // Adjust the window size to account for window frame and controls. Keep
+      // the origin unchanged.
+      RECT window_rect = {x, y, x + width, y + height};
+      ::AdjustWindowRectEx(&window_rect, dwStyle, with_controls_, dwExStyle);
+      width = window_rect.right - window_rect.left;
+      height = window_rect.bottom - window_rect.top;
+    }
   }
 
   browser_settings_ = settings;
 
   // Create the main window initially hidden.
   CreateWindowEx(dwExStyle, window_class.c_str(), window_title.c_str(), dwStyle,
-                 x, y, width, height, NULL, NULL, hInstance, this);
+                 x, y, width, height, nullptr, nullptr, hInstance, this);
   CHECK(hwnd_);
 
   if (!called_enable_non_client_dpi_scaling_ && IsProcessPerMonitorDpiAware()) {
@@ -378,13 +406,23 @@
     static EnableChildWindowDpiMessagePtr func_ptr =
         reinterpret_cast<EnableChildWindowDpiMessagePtr>(GetProcAddress(
             GetModuleHandle(L"user32.dll"), "EnableChildWindowDpiMessage"));
-    if (func_ptr)
+    if (func_ptr) {
       func_ptr(hwnd_, TRUE);
+    }
   }
 
   if (!initially_hidden) {
+    ShowMode mode = ShowNormal;
+    if (no_activate) {
+      mode = ShowNoActivate;
+    } else if (initial_show_state_ == CEF_SHOW_STATE_MAXIMIZED) {
+      mode = ShowMaximized;
+    } else if (initial_show_state_ == CEF_SHOW_STATE_MINIMIZED) {
+      mode = ShowMinimized;
+    }
+
     // Show this window.
-    Show(no_activate ? ShowNoActivate : ShowNormal);
+    Show(mode);
   }
 }
 
@@ -394,8 +432,9 @@
                                       HBRUSH background_brush) {
   // Only register the class one time.
   static bool class_registered = false;
-  if (class_registered)
+  if (class_registered) {
     return;
+  }
   class_registered = true;
 
   WNDCLASSEX wcex;
@@ -408,7 +447,7 @@
   wcex.cbWndExtra = 0;
   wcex.hInstance = hInstance;
   wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CEFCLIENT));
-  wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
+  wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
   wcex.hbrBackground = background_brush;
   wcex.lpszMenuName = MAKEINTRESOURCE(IDC_CEFCLIENT);
   wcex.lpszClassName = window_class.c_str();
@@ -447,8 +486,8 @@
       break;
     case WM_NCDESTROY:
       // Clear the reference to |self|.
-      SetUserDataPtr(hWnd, NULL);
-      self->edit_hwnd_ = NULL;
+      SetUserDataPtr(hWnd, nullptr);
+      self->edit_hwnd_ = nullptr;
       break;
   }
 
@@ -469,13 +508,13 @@
   switch (message) {
     case WM_ACTIVATE:
       // Set this dialog as current when activated.
-      MainMessageLoop::Get()->SetCurrentModelessDialog(wParam == 0 ? NULL
+      MainMessageLoop::Get()->SetCurrentModelessDialog(wParam == 0 ? nullptr
                                                                    : hWnd);
       return FALSE;
     case WM_NCDESTROY:
       // Clear the reference to |self|.
-      SetUserDataPtr(hWnd, NULL);
-      self->find_hwnd_ = NULL;
+      SetUserDataPtr(hWnd, nullptr);
+      self->find_hwnd_ = nullptr;
       break;
   }
 
@@ -492,8 +531,9 @@
   RootWindowWin* self = nullptr;
   if (message != WM_NCCREATE) {
     self = GetUserDataPtr<RootWindowWin*>(hWnd);
-    if (!self)
+    if (!self) {
       return DefWindowProc(hWnd, message, wParam, lParam);
+    }
     DCHECK_EQ(hWnd, self->hwnd_);
   }
 
@@ -508,8 +548,9 @@
   // Callback for the main window
   switch (message) {
     case WM_COMMAND:
-      if (self->OnCommand(LOWORD(wParam)))
+      if (self->OnCommand(LOWORD(wParam))) {
         return 0;
+      }
       break;
 
     case WM_GETOBJECT: {
@@ -519,8 +560,9 @@
 
       // Accessibility readers will send an OBJID_CLIENT message.
       if (static_cast<DWORD>(OBJID_CLIENT) == obj_id) {
-        if (self->GetBrowser() && self->GetBrowser()->GetHost())
+        if (self->GetBrowser() && self->GetBrowser()->GetHost()) {
           self->GetBrowser()->GetHost()->SetAccessibilityState(STATE_ENABLED);
+        }
       }
     } break;
 
@@ -537,6 +579,15 @@
       self->OnFocus();
       return 0;
 
+    case WM_ENABLE:
+      if (wParam == TRUE) {
+        // Give focus to the browser after EnableWindow enables this window
+        // (e.g. after a modal dialog is dismissed).
+        self->OnFocus();
+        return 0;
+      }
+      break;
+
     case WM_SIZE:
       self->OnSize(wParam == SIZE_MINIMIZED);
       break;
@@ -551,8 +602,9 @@
       break;
 
     case WM_ERASEBKGND:
-      if (self->OnEraseBkgnd())
+      if (self->OnEraseBkgnd()) {
         break;
+      }
       // Don't erase the background.
       return 0;
 
@@ -571,8 +623,9 @@
       break;
 
     case WM_CLOSE:
-      if (self->OnClose())
+      if (self->OnClose()) {
         return 0;  // Cancel the close.
+      }
       break;
 
     case WM_NCHITTEST: {
@@ -607,8 +660,8 @@
 
     case WM_NCDESTROY:
       // Clear the reference to |self|.
-      SetUserDataPtr(hWnd, NULL);
-      self->hwnd_ = NULL;
+      SetUserDataPtr(hWnd, nullptr);
+      self->hwnd_ = nullptr;
       self->OnDestroyed();
       break;
   }
@@ -626,25 +679,29 @@
   // Selecting "Close window" from the task bar menu may send a focus
   // notification even though the window is currently disabled (e.g. while a
   // modal JS dialog is displayed).
-  if (browser_window_ && ::IsWindowEnabled(hwnd_))
+  if (browser_window_ && ::IsWindowEnabled(hwnd_)) {
     browser_window_->SetFocus(true);
+  }
 }
 
 void RootWindowWin::OnActivate(bool active) {
-  if (active)
+  if (active) {
     delegate_->OnRootWindowActivated(this);
+  }
 }
 
 void RootWindowWin::OnSize(bool minimized) {
   if (minimized) {
     // Notify the browser window that it was hidden and do nothing further.
-    if (browser_window_)
+    if (browser_window_) {
       browser_window_->Hide();
+    }
     return;
   }
 
-  if (browser_window_)
+  if (browser_window_) {
     browser_window_->Show();
+  }
 
   RECT rect;
   GetClientRect(hwnd_, &rect);
@@ -683,36 +740,36 @@
 
     int x_offset = rect.left;
 
-    // |browser_hwnd| may be NULL if the browser has not yet been created.
-    HWND browser_hwnd = NULL;
-    if (browser_window_)
+    // |browser_hwnd| may be nullptr if the browser has not yet been created.
+    HWND browser_hwnd = nullptr;
+    if (browser_window_) {
       browser_hwnd = browser_window_->GetWindowHandle();
+    }
 
     // Resize all controls.
     HDWP hdwp = BeginDeferWindowPos(browser_hwnd ? 6 : 5);
-    hdwp = DeferWindowPos(hdwp, back_hwnd_, NULL, x_offset, 0, button_width,
+    hdwp = DeferWindowPos(hdwp, back_hwnd_, nullptr, x_offset, 0, button_width,
                           urlbar_height, SWP_NOZORDER);
     x_offset += button_width;
-    hdwp = DeferWindowPos(hdwp, forward_hwnd_, NULL, x_offset, 0, button_width,
+    hdwp = DeferWindowPos(hdwp, forward_hwnd_, nullptr, x_offset, 0,
+                          button_width, urlbar_height, SWP_NOZORDER);
+    x_offset += button_width;
+    hdwp = DeferWindowPos(hdwp, reload_hwnd_, nullptr, x_offset, 0,
+                          button_width, urlbar_height, SWP_NOZORDER);
+    x_offset += button_width;
+    hdwp = DeferWindowPos(hdwp, stop_hwnd_, nullptr, x_offset, 0, button_width,
                           urlbar_height, SWP_NOZORDER);
     x_offset += button_width;
-    hdwp = DeferWindowPos(hdwp, reload_hwnd_, NULL, x_offset, 0, button_width,
-                          urlbar_height, SWP_NOZORDER);
-    x_offset += button_width;
-    hdwp = DeferWindowPos(hdwp, stop_hwnd_, NULL, x_offset, 0, button_width,
-                          urlbar_height, SWP_NOZORDER);
-    x_offset += button_width;
-    hdwp = DeferWindowPos(hdwp, edit_hwnd_, NULL, x_offset, 0,
+    hdwp = DeferWindowPos(hdwp, edit_hwnd_, nullptr, x_offset, 0,
                           rect.right - x_offset, urlbar_height, SWP_NOZORDER);
 
     if (browser_hwnd) {
-      hdwp = DeferWindowPos(hdwp, browser_hwnd, NULL, rect.left, rect.top,
+      hdwp = DeferWindowPos(hdwp, browser_hwnd, nullptr, rect.left, rect.top,
                             rect.right - rect.left, rect.bottom - rect.top,
                             SWP_NOZORDER);
     }
 
-    BOOL result = EndDeferWindowPos(hdwp);
-    ALLOW_UNUSED_LOCAL(result);
+    [[maybe_unused]] BOOL result = EndDeferWindowPos(hdwp);
     DCHECK(result);
   } else if (browser_window_) {
     // Size the browser window to the whole client area.
@@ -724,8 +781,9 @@
   // Notify the browser of move events so that popup windows are displayed
   // in the correct location and dismissed when the window moves.
   CefRefPtr<CefBrowser> browser = GetBrowser();
-  if (browser)
+  if (browser) {
     browser->GetHost()->NotifyMoveOrResizeStarted();
+  }
 }
 
 void RootWindowWin::OnDpiChanged(WPARAM wParam, LPARAM lParam) {
@@ -769,20 +827,24 @@
       OnFind();
       return true;
     case IDC_NAV_BACK:  // Back button
-      if (CefRefPtr<CefBrowser> browser = GetBrowser())
+      if (CefRefPtr<CefBrowser> browser = GetBrowser()) {
         browser->GoBack();
+      }
       return true;
     case IDC_NAV_FORWARD:  // Forward button
-      if (CefRefPtr<CefBrowser> browser = GetBrowser())
+      if (CefRefPtr<CefBrowser> browser = GetBrowser()) {
         browser->GoForward();
+      }
       return true;
     case IDC_NAV_RELOAD:  // Reload button
-      if (CefRefPtr<CefBrowser> browser = GetBrowser())
+      if (CefRefPtr<CefBrowser> browser = GetBrowser()) {
         browser->Reload();
+      }
       return true;
     case IDC_NAV_STOP:  // Stop button
-      if (CefRefPtr<CefBrowser> browser = GetBrowser())
+      if (CefRefPtr<CefBrowser> browser = GetBrowser()) {
         browser->StopLoad();
+      }
       return true;
   }
 
@@ -839,17 +901,18 @@
       find_what_last_ = find_buff_;
     }
 
-    browser->GetHost()->Find(0, find_what,
+    browser->GetHost()->Find(find_what,
                              (find_state_.Flags & FR_DOWN) ? true : false,
                              match_case, find_next_);
-    if (!find_next_)
+    if (!find_next_) {
       find_next_ = true;
+    }
   }
 }
 
 void RootWindowWin::OnAbout() {
   // Show the about box.
-  DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd_,
+  DialogBox(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd_,
             AboutWndProc);
 }
 
@@ -936,7 +999,7 @@
     }
   } else {
     // No controls so also remove the default menu.
-    ::SetMenu(hwnd_, NULL);
+    ::SetMenu(hwnd_, nullptr);
   }
 
   const float device_scale_factor = GetWindowScaleFactor(hwnd_);
@@ -973,6 +1036,18 @@
     }
   }
 
+  // Retrieve current window placement information.
+  WINDOWPLACEMENT placement;
+  ::GetWindowPlacement(hwnd_, &placement);
+
+  if (CefCurrentlyOn(TID_UI)) {
+    SaveWindowRestoreOnUIThread(placement);
+  } else {
+    CefPostTask(
+        TID_UI,
+        base::BindOnce(&RootWindowWin::SaveWindowRestoreOnUIThread, placement));
+  }
+
   // Allow the close.
   return false;
 }
@@ -1016,15 +1091,17 @@
 void RootWindowWin::OnSetAddress(const std::string& url) {
   REQUIRE_MAIN_THREAD();
 
-  if (edit_hwnd_)
+  if (edit_hwnd_) {
     SetWindowText(edit_hwnd_, CefString(url).ToWString().c_str());
+  }
 }
 
 void RootWindowWin::OnSetTitle(const std::string& title) {
   REQUIRE_MAIN_THREAD();
 
-  if (hwnd_)
+  if (hwnd_) {
     SetWindowText(hwnd_, CefString(title).ToWString().c_str());
+  }
 }
 
 void RootWindowWin::OnSetFullscreen(bool fullscreen) {
@@ -1032,33 +1109,36 @@
 
   CefRefPtr<CefBrowser> browser = GetBrowser();
   if (browser) {
-    scoped_ptr<window_test::WindowTestRunnerWin> test_runner(
+    std::unique_ptr<window_test::WindowTestRunnerWin> test_runner(
         new window_test::WindowTestRunnerWin());
-    if (fullscreen)
+    if (fullscreen) {
       test_runner->Maximize(browser);
-    else
+    } else {
       test_runner->Restore(browser);
+    }
   }
 }
 
 void RootWindowWin::OnAutoResize(const CefSize& new_size) {
   REQUIRE_MAIN_THREAD();
 
-  if (!hwnd_)
+  if (!hwnd_) {
     return;
+  }
 
   int new_width = new_size.width;
 
   // Make the window wide enough to drag by the top menu bar.
-  if (new_width < 200)
+  if (new_width < 200) {
     new_width = 200;
+  }
 
   const float device_scale_factor = GetWindowScaleFactor(hwnd_);
   RECT rect = {0, 0, LogicalToDevice(new_width, device_scale_factor),
                LogicalToDevice(new_size.height, device_scale_factor)};
   DWORD style = GetWindowLong(hwnd_, GWL_STYLE);
   DWORD ex_style = GetWindowLong(hwnd_, GWL_EXSTYLE);
-  bool has_menu = !(style & WS_CHILD) && (GetMenu(hwnd_) != NULL);
+  bool has_menu = !(style & WS_CHILD) && (GetMenu(hwnd_) != nullptr);
 
   // The size value is for the client area. Calculate the whole window size
   // based on the current style.
@@ -1066,7 +1146,7 @@
 
   // Size the window. The left/top values may be negative.
   // Also show the window if it's not currently visible.
-  SetWindowPos(hwnd_, NULL, 0, 0, rect.right - rect.left,
+  SetWindowPos(hwnd_, nullptr, 0, 0, rect.right - rect.left,
                rect.bottom - rect.top,
                SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE | SWP_SHOWWINDOW);
 }
@@ -1153,9 +1233,8 @@
   LONG_PTR hParentWndProc =
       reinterpret_cast<LONG_PTR>(::GetPropW(hWnd, kParentWndProc));
   if (hParentWndProc) {
-    LONG_PTR hPreviousWndProc =
+    [[maybe_unused]] LONG_PTR hPreviousWndProc =
         SetWindowLongPtr(hWnd, GWLP_WNDPROC, hParentWndProc);
-    ALLOW_UNUSED_LOCAL(hPreviousWndProc);
     DCHECK_EQ(hPreviousWndProc,
               reinterpret_cast<LONG_PTR>(SubclassedWindowProc));
   }
@@ -1206,8 +1285,30 @@
 
 void RootWindowWin::NotifyDestroyedIfDone() {
   // Notify once both the window and the browser have been destroyed.
-  if (window_destroyed_ && browser_destroyed_)
+  if (window_destroyed_ && browser_destroyed_) {
     delegate_->OnRootWindowDestroyed(this);
+  }
+}
+
+// static
+void RootWindowWin::SaveWindowRestoreOnUIThread(
+    const WINDOWPLACEMENT& placement) {
+  CEF_REQUIRE_UI_THREAD();
+
+  cef_show_state_t show_state = CEF_SHOW_STATE_NORMAL;
+  if (placement.showCmd == SW_SHOWMINIMIZED) {
+    show_state = CEF_SHOW_STATE_MINIMIZED;
+  } else if (placement.showCmd == SW_SHOWMAXIMIZED) {
+    show_state = CEF_SHOW_STATE_MAXIMIZED;
+  }
+
+  // Coordinates when the window is in the restored position.
+  const auto rect = placement.rcNormalPosition;
+  CefRect pixel_bounds(rect.left, rect.top, rect.right - rect.left,
+                       rect.bottom - rect.top);
+  const auto dip_bounds = CefDisplay::ConvertScreenRectFromPixels(pixel_bounds);
+
+  prefs::SaveWindowRestorePreferences(show_state, dip_bounds);
 }
 
 }  // namespace client
diff --git a/src/tests/cefclient/browser/root_window_win.h b/src/tests/cefclient/browser/root_window_win.h
index 153c38e..f36b2ce 100644
--- a/src/tests/cefclient/browser/root_window_win.h
+++ b/src/tests/cefclient/browser/root_window_win.h
@@ -10,9 +10,9 @@
 
 #include <commdlg.h>
 
+#include <memory>
 #include <string>
 
-#include "include/base/cef_scoped_ptr.h"
 #include "tests/cefclient/browser/browser_window.h"
 #include "tests/cefclient/browser/root_window.h"
 
@@ -29,27 +29,32 @@
 
   // RootWindow methods.
   void Init(RootWindow::Delegate* delegate,
-            const RootWindowConfig& config,
-            const CefBrowserSettings& settings) OVERRIDE;
+            std::unique_ptr<RootWindowConfig> config,
+            const CefBrowserSettings& settings) override;
   void InitAsPopup(RootWindow::Delegate* delegate,
                    bool with_controls,
                    bool with_osr,
                    const CefPopupFeatures& popupFeatures,
                    CefWindowInfo& windowInfo,
                    CefRefPtr<CefClient>& client,
-                   CefBrowserSettings& settings) OVERRIDE;
-  void Show(ShowMode mode) OVERRIDE;
-  void Hide() OVERRIDE;
-  void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
-  void Close(bool force) OVERRIDE;
-  void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE;
-  float GetDeviceScaleFactor() const OVERRIDE;
-  CefRefPtr<CefBrowser> GetBrowser() const OVERRIDE;
-  ClientWindowHandle GetWindowHandle() const OVERRIDE;
-  bool WithWindowlessRendering() const OVERRIDE;
-  bool WithExtension() const OVERRIDE;
+                   CefBrowserSettings& settings) override;
+  void Show(ShowMode mode) override;
+  void Hide() override;
+  void SetBounds(int x, int y, size_t width, size_t height) override;
+  void Close(bool force) override;
+  void SetDeviceScaleFactor(float device_scale_factor) override;
+  float GetDeviceScaleFactor() const override;
+  CefRefPtr<CefBrowser> GetBrowser() const override;
+  ClientWindowHandle GetWindowHandle() const override;
+  bool WithWindowlessRendering() const override;
+  bool WithExtension() const override;
 
  private:
+  void ContinueInitOnUIThread(std::unique_ptr<RootWindowConfig> config,
+                              const CefBrowserSettings& settings);
+  void ContinueInitOnMainThread(std::unique_ptr<RootWindowConfig> config,
+                                const CefBrowserSettings& settings);
+
   void CreateBrowserWindow(const std::string& startup_url);
   void CreateRootWindow(const CefBrowserSettings& settings,
                         bool initially_hidden);
@@ -95,68 +100,71 @@
   void OnDestroyed();
 
   // BrowserWindow::Delegate methods.
-  void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void OnBrowserWindowDestroyed() OVERRIDE;
-  void OnSetAddress(const std::string& url) OVERRIDE;
-  void OnSetTitle(const std::string& title) OVERRIDE;
-  void OnSetFullscreen(bool fullscreen) OVERRIDE;
-  void OnAutoResize(const CefSize& new_size) OVERRIDE;
+  void OnBrowserCreated(CefRefPtr<CefBrowser> browser) override;
+  void OnBrowserWindowDestroyed() override;
+  void OnSetAddress(const std::string& url) override;
+  void OnSetTitle(const std::string& title) override;
+  void OnSetFullscreen(bool fullscreen) override;
+  void OnAutoResize(const CefSize& new_size) override;
   void OnSetLoadingState(bool isLoading,
                          bool canGoBack,
-                         bool canGoForward) OVERRIDE;
+                         bool canGoForward) override;
   void OnSetDraggableRegions(
-      const std::vector<CefDraggableRegion>& regions) OVERRIDE;
+      const std::vector<CefDraggableRegion>& regions) override;
 
   void NotifyDestroyedIfDone();
 
+  static void SaveWindowRestoreOnUIThread(const WINDOWPLACEMENT& placement);
+
   // After initialization all members are only accessed on the main thread.
   // Members set during initialization.
-  bool with_controls_;
-  bool always_on_top_;
-  bool with_osr_;
-  bool with_extension_;
-  bool is_popup_;
-  RECT start_rect_;
-  scoped_ptr<BrowserWindow> browser_window_;
+  bool with_controls_ = false;
+  bool always_on_top_ = false;
+  bool with_osr_ = false;
+  bool with_extension_ = false;
+  bool is_popup_ = false;
+  CefRect initial_bounds_;
+  cef_show_state_t initial_show_state_ = CEF_SHOW_STATE_NORMAL;
+  std::unique_ptr<BrowserWindow> browser_window_;
   CefBrowserSettings browser_settings_;
-  bool initialized_;
+  bool initialized_ = false;
 
   // Main window.
-  HWND hwnd_;
+  HWND hwnd_ = nullptr;
 
   // Draggable region.
-  HRGN draggable_region_;
+  HRGN draggable_region_ = nullptr;
 
   // Font for buttons and text fields.
-  HFONT font_;
-  int font_height_;
+  HFONT font_ = nullptr;
+  int font_height_ = 0;
 
   // Buttons.
-  HWND back_hwnd_;
-  HWND forward_hwnd_;
-  HWND reload_hwnd_;
-  HWND stop_hwnd_;
+  HWND back_hwnd_ = nullptr;
+  HWND forward_hwnd_ = nullptr;
+  HWND reload_hwnd_ = nullptr;
+  HWND stop_hwnd_ = nullptr;
 
   // URL text field.
-  HWND edit_hwnd_;
-  WNDPROC edit_wndproc_old_;
+  HWND edit_hwnd_ = nullptr;
+  WNDPROC edit_wndproc_old_ = nullptr;
 
   // Find dialog.
-  HWND find_hwnd_;
-  UINT find_message_id_;
-  WNDPROC find_wndproc_old_;
+  HWND find_hwnd_ = nullptr;
+  UINT find_message_id_ = 0;
+  WNDPROC find_wndproc_old_ = nullptr;
 
   // Find dialog state.
-  FINDREPLACE find_state_;
-  WCHAR find_buff_[80];
+  FINDREPLACE find_state_ = {0};
+  WCHAR find_buff_[80] = {0};
   std::wstring find_what_last_;
-  bool find_next_;
-  bool find_match_case_last_;
+  bool find_next_ = false;
+  bool find_match_case_last_ = false;
 
-  bool window_destroyed_;
-  bool browser_destroyed_;
+  bool window_destroyed_ = false;
+  bool browser_destroyed_ = false;
 
-  bool called_enable_non_client_dpi_scaling_;
+  bool called_enable_non_client_dpi_scaling_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(RootWindowWin);
 };
diff --git a/src/tests/cefclient/browser/scheme_test.cc b/src/tests/cefclient/browser/scheme_test.cc
index c19806b..8233130 100644
--- a/src/tests/cefclient/browser/scheme_test.cc
+++ b/src/tests/cefclient/browser/scheme_test.cc
@@ -30,7 +30,7 @@
 
   bool Open(CefRefPtr<CefRequest> request,
             bool& handle_request,
-            CefRefPtr<CefCallback> callback) OVERRIDE {
+            CefRefPtr<CefCallback> callback) override {
     DCHECK(!CefCurrentlyOn(TID_UI) && !CefCurrentlyOn(TID_IO));
 
     // The request will be continued or canceled based on the return value.
@@ -78,8 +78,8 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
-                          CefString& redirectUrl) OVERRIDE {
+                          int64_t& response_length,
+                          CefString& redirectUrl) override {
     CEF_REQUIRE_IO_THREAD();
 
     DCHECK(!data_.empty());
@@ -91,12 +91,12 @@
     response_length = data_.length();
   }
 
-  void Cancel() OVERRIDE { CEF_REQUIRE_IO_THREAD(); }
+  void Cancel() override { CEF_REQUIRE_IO_THREAD(); }
 
   bool Read(void* data_out,
             int bytes_to_read,
             int& bytes_read,
-            CefRefPtr<CefResourceReadCallback> callback) OVERRIDE {
+            CefRefPtr<CefResourceReadCallback> callback) override {
     DCHECK(!CefCurrentlyOn(TID_UI) && !CefCurrentlyOn(TID_IO));
 
     bool has_data = false;
@@ -134,7 +134,7 @@
   CefRefPtr<CefResourceHandler> Create(CefRefPtr<CefBrowser> browser,
                                        CefRefPtr<CefFrame> frame,
                                        const CefString& scheme_name,
-                                       CefRefPtr<CefRequest> request) OVERRIDE {
+                                       CefRefPtr<CefRequest> request) override {
     CEF_REQUIRE_IO_THREAD();
     return new ClientSchemeHandler();
   }
diff --git a/src/tests/cefclient/browser/server_test.cc b/src/tests/cefclient/browser/server_test.cc
index ee3b922..6101c3b 100644
--- a/src/tests/cefclient/browser/server_test.cc
+++ b/src/tests/cefclient/browser/server_test.cc
@@ -5,9 +5,10 @@
 #include "tests/cefclient/browser/server_test.h"
 
 #include <algorithm>
+#include <memory>
 #include <string>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/base/cef_weak_ptr.h"
 #include "include/cef_parser.h"
 #include "include/cef_server.h"
@@ -30,9 +31,6 @@
 const char kStatusKey[] = "status";
 const char kMessageKey[] = "message";
 
-// Required URL for cefQuery execution.
-const char kTestUrl[] = "http://tests/server";
-
 // Server default values.
 const char kServerAddress[] = "127.0.0.1";
 const int kServerPortDefault = 8099;
@@ -42,25 +40,25 @@
 // Handles the HTTP/WebSocket server.
 class ServerHandler : public CefServerHandler {
  public:
-  typedef base::Callback<void(bool /* success */)> CompleteCallback;
+  using CompleteCallback = base::OnceCallback<void(bool /* success */)>;
 
   ServerHandler() {}
 
   // |complete_callback| will be executed on the UI thread after completion.
-  void StartServer(int port, const CompleteCallback& complete_callback) {
+  void StartServer(int port, CompleteCallback complete_callback) {
     CEF_REQUIRE_UI_THREAD();
     DCHECK(!server_);
     DCHECK(port >= 1025 && port <= 65535);
     port_ = port;
-    complete_callback_ = complete_callback;
+    complete_callback_ = std::move(complete_callback);
     CefServer::CreateServer(kServerAddress, port, kServerBacklog, this);
   }
 
   // |complete_callback| will be executed on the UI thread after completion.
-  void StopServer(const CompleteCallback& complete_callback) {
+  void StopServer(CompleteCallback complete_callback) {
     CEF_REQUIRE_UI_THREAD();
     DCHECK(server_);
-    complete_callback_ = complete_callback;
+    complete_callback_ = std::move(complete_callback);
     server_->Shutdown();
   }
 
@@ -92,11 +90,13 @@
     CefURLParts url_parts;
     CefParseURL(request->GetURL(), url_parts);
     std::string path = CefString(&url_parts.path);
-    if (!path.empty() && path[0] == '/')
+    if (!path.empty() && path[0] == '/') {
       path = path.substr(1);
+    }
 
-    if (path.empty())
+    if (path.empty()) {
       path = kDefaultPath;
+    }
 
     std::string mime_type;
     const size_t sep = path.find_last_of(".");
@@ -107,8 +107,9 @@
       // No extension. Assume html.
       path += ".html";
     }
-    if (mime_type.empty())
+    if (mime_type.empty()) {
       mime_type = "text/html";
+    }
 
     CefRefPtr<CefStreamReader> stream;
     CefResponse::HeaderMap extra_headers;
@@ -159,14 +160,13 @@
  private:
   void RunCompleteCallback(bool success) {
     if (!CefCurrentlyOn(TID_UI)) {
-      CefPostTask(TID_UI, base::Bind(&ServerHandler::RunCompleteCallback, this,
-                                     success));
+      CefPostTask(TID_UI, base::BindOnce(&ServerHandler::RunCompleteCallback,
+                                         this, success));
       return;
     }
 
     if (!complete_callback_.is_null()) {
-      complete_callback_.Run(success);
-      complete_callback_.Reset();
+      std::move(complete_callback_).Run(success);
     }
   }
 
@@ -177,7 +177,7 @@
                                      CefResponse::HeaderMap extra_headers) {
     // Determine the stream size.
     stream->Seek(0, SEEK_END);
-    int64 content_length = stream->Tell();
+    int64_t content_length = stream->Tell();
     stream->Seek(0, SEEK_SET);
 
     // Send response headers.
@@ -189,8 +189,9 @@
     size_t read;
     do {
       read = stream->Read(buffer, 1, sizeof(buffer));
-      if (read > 0)
+      if (read > 0) {
         server->SendRawData(connection_id, buffer, read);
+      }
     } while (!stream->Eof() && read != 0);
 
     // Close the connection.
@@ -222,16 +223,17 @@
   // Called due to cefQuery execution in server.html.
   virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
                        CefRefPtr<CefFrame> frame,
-                       int64 query_id,
+                       int64_t query_id,
                        const CefString& request,
                        bool persistent,
-                       CefRefPtr<Callback> callback) OVERRIDE {
+                       CefRefPtr<Callback> callback) override {
     CEF_REQUIRE_UI_THREAD();
 
     // Only handle messages from the test URL.
     const std::string& url = frame->GetURL();
-    if (url.find(kTestUrl) != 0)
+    if (url.find(test_runner::GetTestURL("server")) != 0) {
       return false;
+    }
 
     // Parse |request| as a JSON dictionary.
     CefRefPtr<CefDictionaryValue> request_dict = ParseJSON(request);
@@ -240,8 +242,9 @@
       return true;
     }
 
-    if (!VerifyKey(request_dict, kActionKey, VTYPE_STRING, callback))
+    if (!VerifyKey(request_dict, kActionKey, VTYPE_STRING, callback)) {
       return true;
+    }
 
     const std::string& action = request_dict->GetString(kActionKey);
     if (action == "query") {
@@ -280,8 +283,9 @@
       return;
     }
 
-    if (!VerifyKey(request_dict, kPortKey, VTYPE_INT, callback))
+    if (!VerifyKey(request_dict, kPortKey, VTYPE_INT, callback)) {
       return;
+    }
 
     const int port = request_dict->GetInt(kPortKey);
     if (port < 8000 || port > 65535) {
@@ -292,9 +296,9 @@
     handler_ = new ServerHandler();
 
     // Start the server. OnComplete will be executed upon completion.
-    handler_->StartServer(port,
-                          base::Bind(&Handler::OnStartComplete,
-                                     weak_ptr_factory_.GetWeakPtr(), callback));
+    handler_->StartServer(
+        port, base::BindOnce(&Handler::OnStartComplete,
+                             weak_ptr_factory_.GetWeakPtr(), callback));
   }
 
   // Stop the server.
@@ -306,8 +310,8 @@
     }
 
     // Stop the server. OnComplete will be executed upon completion.
-    handler_->StopServer(base::Bind(&Handler::OnStopComplete,
-                                    weak_ptr_factory_.GetWeakPtr(), callback));
+    handler_->StopServer(base::BindOnce(
+        &Handler::OnStopComplete, weak_ptr_factory_.GetWeakPtr(), callback));
 
     handler_ = nullptr;
   }
@@ -350,8 +354,9 @@
   // Convert a JSON string to a dictionary value.
   static CefRefPtr<CefDictionaryValue> ParseJSON(const CefString& string) {
     CefRefPtr<CefValue> value = CefParseJSON(string, JSON_PARSER_RFC);
-    if (value.get() && value->GetType() == VTYPE_DICTIONARY)
+    if (value.get() && value->GetType() == VTYPE_DICTIONARY) {
       return value->GetDictionary();
+    }
     return nullptr;
   }
 
diff --git a/src/tests/cefclient/browser/temp_window.h b/src/tests/cefclient/browser/temp_window.h
index 499c80a..391bba4 100644
--- a/src/tests/cefclient/browser/temp_window.h
+++ b/src/tests/cefclient/browser/temp_window.h
@@ -12,7 +12,7 @@
 #include "tests/cefclient/browser/temp_window_win.h"
 #elif defined(OS_LINUX)
 #include "tests/cefclient/browser/temp_window_x11.h"
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
 #include "tests/cefclient/browser/temp_window_mac.h"
 #endif
 
@@ -22,7 +22,7 @@
 typedef TempWindowWin TempWindow;
 #elif defined(OS_LINUX)
 typedef TempWindowX11 TempWindow;
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
 typedef TempWindowMac TempWindow;
 #endif
 
diff --git a/src/tests/cefclient/browser/temp_window_mac.h b/src/tests/cefclient/browser/temp_window_mac.h
index c64062f..feded5c 100644
--- a/src/tests/cefclient/browser/temp_window_mac.h
+++ b/src/tests/cefclient/browser/temp_window_mac.h
@@ -22,13 +22,13 @@
  private:
   // A single instance will be created/owned by RootWindowManager.
   friend class RootWindowManager;
-  // Allow deletion via scoped_ptr only.
-  friend struct base::DefaultDeleter<TempWindowMac>;
+  // Allow deletion via std::unique_ptr only.
+  friend std::default_delete<TempWindowMac>;
 
   TempWindowMac();
   ~TempWindowMac();
 
-  scoped_ptr<TempWindowMacImpl> impl_;
+  std::unique_ptr<TempWindowMacImpl> impl_;
 
   DISALLOW_COPY_AND_ASSIGN(TempWindowMac);
 };
diff --git a/src/tests/cefclient/browser/temp_window_mac.mm b/src/tests/cefclient/browser/temp_window_mac.mm
index 6aff01c..c230445 100644
--- a/src/tests/cefclient/browser/temp_window_mac.mm
+++ b/src/tests/cefclient/browser/temp_window_mac.mm
@@ -13,7 +13,7 @@
 
 namespace {
 
-TempWindowMac* g_temp_window = NULL;
+TempWindowMac* g_temp_window = nullptr;
 
 }  // namespace
 
@@ -22,7 +22,7 @@
   TempWindowMacImpl() {
     // Create a borderless non-visible 1x1 window.
     window_ = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1)
-                                          styleMask:NSBorderlessWindowMask
+                                          styleMask:NSWindowStyleMaskBorderless
                                             backing:NSBackingStoreBuffered
                                               defer:NO];
     CHECK(window_);
@@ -46,7 +46,7 @@
 
 TempWindowMac::~TempWindowMac() {
   impl_.reset();
-  g_temp_window = NULL;
+  g_temp_window = nullptr;
 }
 
 // static
diff --git a/src/tests/cefclient/browser/temp_window_win.cc b/src/tests/cefclient/browser/temp_window_win.cc
index af5cdf9..2bd7461 100644
--- a/src/tests/cefclient/browser/temp_window_win.cc
+++ b/src/tests/cefclient/browser/temp_window_win.cc
@@ -16,7 +16,7 @@
 
 // Create the temp window.
 HWND CreateTempWindow() {
-  HINSTANCE hInstance = ::GetModuleHandle(NULL);
+  HINSTANCE hInstance = ::GetModuleHandle(nullptr);
 
   WNDCLASSEX wc = {0};
   wc.cbSize = sizeof(wc);
@@ -27,14 +27,14 @@
 
   // Create a 1x1 pixel hidden window.
   return CreateWindow(kWndClass, 0, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, 0, 0,
-                      1, 1, NULL, NULL, hInstance, NULL);
+                      1, 1, nullptr, nullptr, hInstance, nullptr);
 }
 
 TempWindowWin* g_temp_window = nullptr;
 
 }  // namespace
 
-TempWindowWin::TempWindowWin() : hwnd_(NULL) {
+TempWindowWin::TempWindowWin() : hwnd_(nullptr) {
   DCHECK(!g_temp_window);
   g_temp_window = this;
 
diff --git a/src/tests/cefclient/browser/temp_window_win.h b/src/tests/cefclient/browser/temp_window_win.h
index b5f312e..2716a38 100644
--- a/src/tests/cefclient/browser/temp_window_win.h
+++ b/src/tests/cefclient/browser/temp_window_win.h
@@ -20,8 +20,8 @@
  private:
   // A single instance will be created/owned by RootWindowManager.
   friend class RootWindowManager;
-  // Allow deletion via scoped_ptr only.
-  friend struct base::DefaultDeleter<TempWindowWin>;
+  // Allow deletion via std::unique_ptr only.
+  friend std::default_delete<TempWindowWin>;
 
   TempWindowWin();
   ~TempWindowWin();
diff --git a/src/tests/cefclient/browser/temp_window_x11.h b/src/tests/cefclient/browser/temp_window_x11.h
index 08e452e..849d02f 100644
--- a/src/tests/cefclient/browser/temp_window_x11.h
+++ b/src/tests/cefclient/browser/temp_window_x11.h
@@ -20,8 +20,8 @@
  private:
   // A single instance will be created/owned by RootWindowManager.
   friend class RootWindowManager;
-  // Allow deletion via scoped_ptr only.
-  friend struct base::DefaultDeleter<TempWindowX11>;
+  // Allow deletion via std::unique_ptr only.
+  friend std::default_delete<TempWindowX11>;
 
   TempWindowX11();
   ~TempWindowX11();
diff --git a/src/tests/cefclient/browser/test_runner.cc b/src/tests/cefclient/browser/test_runner.cc
index 68805e9..fe0becf 100644
--- a/src/tests/cefclient/browser/test_runner.cc
+++ b/src/tests/cefclient/browser/test_runner.cc
@@ -4,21 +4,22 @@
 
 #include "tests/cefclient/browser/test_runner.h"
 
+#include <algorithm>
 #include <map>
 #include <set>
 #include <sstream>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_parser.h"
 #include "include/cef_task.h"
 #include "include/cef_trace.h"
-#include "include/cef_web_plugin.h"
+#include "include/views/cef_browser_view.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "include/wrapper/cef_stream_resource_handler.h"
+#include "tests/cefclient/browser/binary_transfer_test.h"
 #include "tests/cefclient/browser/binding_test.h"
 #include "tests/cefclient/browser/client_handler.h"
 #include "tests/cefclient/browser/dialog_test.h"
-#include "tests/cefclient/browser/drm_test.h"
 #include "tests/cefclient/browser/main_context.h"
 #include "tests/cefclient/browser/media_router_test.h"
 #include "tests/cefclient/browser/preferences_test.h"
@@ -30,6 +31,7 @@
 #include "tests/cefclient/browser/urlrequest_test.h"
 #include "tests/cefclient/browser/window_test.h"
 #include "tests/shared/browser/resource_util.h"
+#include "tests/shared/common/string_util.h"
 
 namespace client {
 namespace test_runner {
@@ -38,12 +40,11 @@
 
 const char kTestHost[] = "tests";
 const char kLocalHost[] = "localhost";
-const char kTestOrigin[] = "http://tests/";
+const char kTestOrigin[] = "https://tests/";
 
 // Pages handled via StringResourceProvider.
 const char kTestGetSourcePage[] = "get_source.html";
 const char kTestGetTextPage[] = "get_text.html";
-const char kTestPluginInfoPage[] = "plugin_info.html";
 
 // Set page data and navigate the browser. Used in combination with
 // StringResourceProvider.
@@ -56,31 +57,13 @@
   browser->GetMainFrame()->LoadURL(kTestOrigin + page);
 }
 
-// Replace all instances of |from| with |to| in |str|.
-std::string StringReplace(const std::string& str,
-                          const std::string& from,
-                          const std::string& to) {
-  std::string result = str;
-  std::string::size_type pos = 0;
-  std::string::size_type from_len = from.length();
-  std::string::size_type to_len = to.length();
-  do {
-    pos = result.find(from, pos);
-    if (pos != std::string::npos) {
-      result.replace(pos, from_len, to);
-      pos += to_len;
-    }
-  } while (pos != std::string::npos);
-  return result;
-}
-
 void RunGetSourceTest(CefRefPtr<CefBrowser> browser) {
   class Visitor : public CefStringVisitor {
    public:
     explicit Visitor(CefRefPtr<CefBrowser> browser) : browser_(browser) {}
-    virtual void Visit(const CefString& string) OVERRIDE {
-      std::string source = StringReplace(string, "<", "&lt;");
-      source = StringReplace(source, ">", "&gt;");
+    virtual void Visit(const CefString& string) override {
+      std::string source = AsciiStrReplace(string, "<", "&lt;");
+      source = AsciiStrReplace(source, ">", "&gt;");
       std::stringstream ss;
       ss << "<html><body bgcolor=\"white\">Source:<pre>" << source
          << "</pre></body></html>";
@@ -99,9 +82,9 @@
   class Visitor : public CefStringVisitor {
    public:
     explicit Visitor(CefRefPtr<CefBrowser> browser) : browser_(browser) {}
-    virtual void Visit(const CefString& string) OVERRIDE {
-      std::string text = StringReplace(string, "<", "&lt;");
-      text = StringReplace(text, ">", "&gt;");
+    virtual void Visit(const CefString& string) override {
+      std::string text = AsciiStrReplace(string, "<", "&lt;");
+      text = AsciiStrReplace(text, ">", "&gt;");
       std::stringstream ss;
       ss << "<html><body bgcolor=\"white\">Text:<pre>" << text
          << "</pre></body></html>";
@@ -120,18 +103,18 @@
   // Create a new request
   CefRefPtr<CefRequest> request(CefRequest::Create());
 
-  if (browser->GetMainFrame()->GetURL().ToString().find("http://tests/") != 0) {
+  if (browser->GetMainFrame()->GetURL().ToString().find(kTestOrigin) != 0) {
     // The LoadRequest method will fail with "bad IPC message" reason
     // INVALID_INITIATOR_ORIGIN (213) unless you first navigate to the
     // request origin using some other mechanism (LoadURL, link click, etc).
-    Alert(browser,
-          "Please first navigate to a http://tests/ URL. "
-          "For example, first load Tests > Other Tests.");
+    Alert(browser, "Please first navigate to a " + std::string(kTestOrigin) +
+                       " URL. "
+                       "For example, first load Tests > Other Tests.");
     return;
   }
 
   // Set the request URL
-  request->SetURL("http://tests/request");
+  request->SetURL(GetTestURL("request"));
 
   // Add post data to the request.  The correct method and content-
   // type headers will be set by CEF.
@@ -152,60 +135,30 @@
 }
 
 void RunNewWindowTest(CefRefPtr<CefBrowser> browser) {
-  RootWindowConfig config;
-  config.with_controls = true;
-  config.with_osr = browser->GetHost()->IsWindowRenderingDisabled();
-  MainContext::Get()->GetRootWindowManager()->CreateRootWindow(config);
+  auto config = std::make_unique<RootWindowConfig>();
+  config->with_controls = true;
+  config->with_osr = browser->GetHost()->IsWindowRenderingDisabled();
+  MainContext::Get()->GetRootWindowManager()->CreateRootWindow(
+      std::move(config));
 }
 
 void RunPopupWindowTest(CefRefPtr<CefBrowser> browser) {
   browser->GetMainFrame()->ExecuteJavaScript(
-      "window.open('http://www.google.com');", "about:blank", 0);
+      "window.open('https://www.google.com');", "about:blank", 0);
 }
 
-void RunPluginInfoTest(CefRefPtr<CefBrowser> browser) {
-  class Visitor : public CefWebPluginInfoVisitor {
-   public:
-    explicit Visitor(CefRefPtr<CefBrowser> browser) : browser_(browser) {
-      html_ =
-          "<html><head><title>Plugin Info Test</title></head>"
-          "<body bgcolor=\"white\">"
-          "\n<b>Installed plugins:</b>";
-    }
-    ~Visitor() {
-      html_ += "\n</body></html>";
-
-      // Load the html in the browser.
-      LoadStringResourcePage(browser_, kTestPluginInfoPage, html_);
-    }
-
-    virtual bool Visit(CefRefPtr<CefWebPluginInfo> info,
-                       int count,
-                       int total) OVERRIDE {
-      html_ += "\n<br/><br/>Name: " + info->GetName().ToString() +
-               "\n<br/>Description: " + info->GetDescription().ToString() +
-               "\n<br/>Version: " + info->GetVersion().ToString() +
-               "\n<br/>Path: " + info->GetPath().ToString();
-      return true;
-    }
-
-   private:
-    std::string html_;
-    CefRefPtr<CefBrowser> browser_;
-    IMPLEMENT_REFCOUNTING(Visitor);
-  };
-
-  CefVisitWebPluginInfo(new Visitor(browser));
-}
-
-void ModifyZoom(CefRefPtr<CefBrowser> browser, double delta) {
-  if (!CefCurrentlyOn(TID_UI)) {
-    // Execute on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&ModifyZoom, browser, delta));
+void RunDialogWindowTest(CefRefPtr<CefBrowser> browser) {
+  auto browser_view = CefBrowserView::GetForBrowser(browser);
+  if (!browser_view) {
+    LOG(ERROR) << "Dialog windows require Views";
     return;
   }
 
-  browser->GetHost()->SetZoomLevel(browser->GetHost()->GetZoomLevel() + delta);
+  auto config = std::make_unique<RootWindowConfig>();
+  config->window_type = WindowType::DIALOG;
+  config->parent_window = browser_view->GetWindow();
+  MainContext::Get()->GetRootWindowManager()->CreateRootWindow(
+      std::move(config));
 }
 
 const char kPrompt[] = "Prompt.";
@@ -220,29 +173,32 @@
   // Called due to cefQuery execution.
   virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
                        CefRefPtr<CefFrame> frame,
-                       int64 query_id,
+                       int64_t query_id,
                        const CefString& request,
                        bool persistent,
-                       CefRefPtr<Callback> callback) OVERRIDE {
+                       CefRefPtr<Callback> callback) override {
     // Parse |request| which takes the form "Prompt.[type]:[value]".
     const std::string& request_str = request;
-    if (request_str.find(kPrompt) != 0)
+    if (request_str.find(kPrompt) != 0) {
       return false;
+    }
 
     std::string type = request_str.substr(sizeof(kPrompt) - 1);
     size_t delim = type.find(':');
-    if (delim == std::string::npos)
+    if (delim == std::string::npos) {
       return false;
+    }
 
     const std::string& value = type.substr(delim + 1);
     type = type.substr(0, delim);
 
     // Canceling the prompt dialog returns a value of "null".
     if (value != "null") {
-      if (type == kPromptFPS)
+      if (type == kPromptFPS) {
         SetFPS(browser, atoi(value.c_str()));
-      else if (type == kPromptDSF)
+      } else if (type == kPromptDSF) {
         SetDSF(browser, static_cast<float>(atof(value.c_str())));
+      }
     }
 
     // Nothing is done with the response.
@@ -264,7 +220,7 @@
 
   void SetDSF(CefRefPtr<CefBrowser> browser, float dsf) {
     MainMessageLoop::Get()->PostClosure(
-        base::Bind(&PromptHandler::SetDSFOnMainThread, browser, dsf));
+        base::BindOnce(&PromptHandler::SetDSFOnMainThread, browser, dsf));
   }
 
   static void SetDSFOnMainThread(CefRefPtr<CefBrowser> browser, float dsf) {
@@ -291,7 +247,7 @@
 void PromptFPS(CefRefPtr<CefBrowser> browser) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&PromptFPS, browser));
+    CefPostTask(TID_UI, base::BindOnce(&PromptFPS, browser));
     return;
   }
 
@@ -305,7 +261,7 @@
 void PromptDSF(CefRefPtr<CefBrowser> browser) {
   if (!MainMessageLoop::Get()->RunsTasksOnCurrentThread()) {
     // Execute on the main thread.
-    MainMessageLoop::Get()->PostClosure(base::Bind(&PromptDSF, browser));
+    MainMessageLoop::Get()->PostClosure(base::BindOnce(&PromptDSF, browser));
     return;
   }
 
@@ -320,7 +276,7 @@
 void BeginTracing() {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&BeginTracing));
+    CefPostTask(TID_UI, base::BindOnce(&BeginTracing));
     return;
   }
 
@@ -330,7 +286,7 @@
 void EndTracing(CefRefPtr<CefBrowser> browser) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&EndTracing, browser));
+    CefPostTask(TID_UI, base::BindOnce(&EndTracing, browser));
     return;
   }
 
@@ -343,23 +299,19 @@
     void RunDialog() {
       static const char kDefaultFileName[] = "trace.txt";
       std::string path = MainContext::Get()->GetDownloadPath(kDefaultFileName);
-      if (path.empty())
+      if (path.empty()) {
         path = kDefaultFileName;
+      }
 
       // Results in a call to OnFileDialogDismissed.
       browser_->GetHost()->RunFileDialog(
-          static_cast<cef_file_dialog_mode_t>(FILE_DIALOG_SAVE |
-                                              FILE_DIALOG_OVERWRITEPROMPT_FLAG),
-          CefString(),  // title
-          path,
-          std::vector<CefString>(),  // accept_filters
-          0,                         // selected_accept_filter
-          this);
+          FILE_DIALOG_SAVE,
+          /*title=*/CefString(), path,
+          /*accept_filters=*/std::vector<CefString>(), this);
     }
 
     void OnFileDialogDismissed(
-        int selected_accept_filter,
-        const std::vector<CefString>& file_paths) OVERRIDE {
+        const std::vector<CefString>& file_paths) override {
       if (!file_paths.empty()) {
         // File selected. Results in a call to OnEndTracingComplete.
         CefEndTracing(file_paths.front(), this);
@@ -369,7 +321,7 @@
       }
     }
 
-    void OnEndTracingComplete(const CefString& tracing_file) OVERRIDE {
+    void OnEndTracingComplete(const CefString& tracing_file) override {
       Alert(browser_,
             "File \"" + tracing_file.ToString() + "\" saved successfully.");
     }
@@ -386,7 +338,7 @@
 void PrintToPDF(CefRefPtr<CefBrowser> browser) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&PrintToPDF, browser));
+    CefPostTask(TID_UI, base::BindOnce(&PrintToPDF, browser));
     return;
   }
 
@@ -399,39 +351,46 @@
     void RunDialog() {
       static const char kDefaultFileName[] = "output.pdf";
       std::string path = MainContext::Get()->GetDownloadPath(kDefaultFileName);
-      if (path.empty())
+      if (path.empty()) {
         path = kDefaultFileName;
+      }
 
       std::vector<CefString> accept_filters;
       accept_filters.push_back(".pdf");
 
       // Results in a call to OnFileDialogDismissed.
-      browser_->GetHost()->RunFileDialog(
-          static_cast<cef_file_dialog_mode_t>(FILE_DIALOG_SAVE |
-                                              FILE_DIALOG_OVERWRITEPROMPT_FLAG),
-          CefString(),  // title
-          path, accept_filters,
-          0,  // selected_accept_filter
-          this);
+      browser_->GetHost()->RunFileDialog(FILE_DIALOG_SAVE,
+                                         /*title=*/CefString(), path,
+                                         accept_filters, this);
     }
 
     void OnFileDialogDismissed(
-        int selected_accept_filter,
-        const std::vector<CefString>& file_paths) OVERRIDE {
+        const std::vector<CefString>& file_paths) override {
       if (!file_paths.empty()) {
         CefPdfPrintSettings settings;
 
-        // Show the URL in the footer.
-        settings.header_footer_enabled = true;
-        CefString(&settings.header_footer_url) =
-            browser_->GetMainFrame()->GetURL();
+        // Display a header and footer.
+        settings.display_header_footer = true;
+        CefString(&settings.header_template) =
+            "<div style=\"width: 100%; font-size: 9px; position: relative;\">"
+            "<div style=\"position: absolute; left: 5px;\">"
+            "<span class=\"title\"></span></div>"
+            "</div>";
+        CefString(&settings.footer_template) =
+            "<div style=\"width: 100%; font-size: 9px; position: relative;\">"
+            "<div style=\"position: absolute; left: 5px;\">"
+            "<span class=\"date\"></span></div>"
+            "<div style=\"position: absolute; right: 5px;\">"
+            "<span class=\"pageNumber\"></span>/"
+            "<span class=\"totalPages\"></span></div>"
+            "</div>";
 
         // Print to the selected PDF file.
         browser_->GetHost()->PrintToPDF(file_paths[0], settings, this);
       }
     }
 
-    void OnPdfPrintFinished(const CefString& path, bool ok) OVERRIDE {
+    void OnPdfPrintFinished(const CefString& path, bool ok) override {
       Alert(browser_, "File \"" + path.ToString() + "\" " +
                           (ok ? "saved successfully." : "failed to save."));
     }
@@ -451,7 +410,7 @@
 }
 
 void RunOtherTests(CefRefPtr<CefBrowser> browser) {
-  browser->GetMainFrame()->LoadURL("http://tests/other_tests");
+  browser->GetMainFrame()->LoadURL(GetTestURL("other_tests"));
 }
 
 // Provider that dumps the request contents.
@@ -461,7 +420,7 @@
     DCHECK(!url.empty());
   }
 
-  bool OnRequest(scoped_refptr<CefResourceManager::Request> request) OVERRIDE {
+  bool OnRequest(scoped_refptr<CefResourceManager::Request> request) override {
     CEF_REQUIRE_IO_THREAD();
 
     const std::string& url = request->url();
@@ -495,7 +454,7 @@
     DCHECK(!pages.empty());
   }
 
-  bool OnRequest(scoped_refptr<CefResourceManager::Request> request) OVERRIDE {
+  bool OnRequest(scoped_refptr<CefResourceManager::Request> request) override {
     CEF_REQUIRE_IO_THREAD();
 
     const std::string& url = request->url();
@@ -544,8 +503,9 @@
 
   // Identify where the query or fragment component, if any, begins.
   size_t suffix_pos = url.find('?');
-  if (suffix_pos == std::string::npos)
+  if (suffix_pos == std::string::npos) {
     suffix_pos = url.find('#');
+  }
 
   std::string url_base, url_suffix;
   if (suffix_pos == std::string::npos) {
@@ -557,15 +517,17 @@
 
   // Identify the last path component.
   size_t path_pos = url_base.rfind('/');
-  if (path_pos == std::string::npos)
+  if (path_pos == std::string::npos) {
     return url;
+  }
 
   const std::string& path_component = url_base.substr(path_pos);
 
   // Identify if a file extension is currently specified.
   size_t ext_pos = path_component.rfind(".");
-  if (ext_pos != std::string::npos)
+  if (ext_pos != std::string::npos) {
     return url;
+  }
 
   // Rebuild the URL with a file extension.
   return url_base + ".html" + url_suffix;
@@ -574,8 +536,9 @@
 }  // namespace
 
 void RunTest(CefRefPtr<CefBrowser> browser, int id) {
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   switch (id) {
     case ID_TESTS_GETSOURCE:
@@ -590,20 +553,20 @@
     case ID_TESTS_WINDOW_POPUP:
       RunPopupWindowTest(browser);
       break;
+    case ID_TESTS_WINDOW_DIALOG:
+      RunDialogWindowTest(browser);
+      break;
     case ID_TESTS_REQUEST:
       RunRequestTest(browser);
       break;
-    case ID_TESTS_PLUGIN_INFO:
-      RunPluginInfoTest(browser);
-      break;
     case ID_TESTS_ZOOM_IN:
-      ModifyZoom(browser, 0.5);
+      browser->GetHost()->Zoom(CEF_ZOOM_COMMAND_IN);
       break;
     case ID_TESTS_ZOOM_OUT:
-      ModifyZoom(browser, -0.5);
+      browser->GetHost()->Zoom(CEF_ZOOM_COMMAND_OUT);
       break;
     case ID_TESTS_ZOOM_RESET:
-      browser->GetHost()->SetZoomLevel(0.0);
+      browser->GetHost()->Zoom(CEF_ZOOM_COMMAND_RESET);
       break;
     case ID_TESTS_OSR_FPS:
       PromptFPS(browser);
@@ -698,8 +661,7 @@
 
     CefRequest::HeaderMap::const_iterator it = requestMap.begin();
     for (; it != requestMap.end(); ++it) {
-      std::string key = it->first;
-      std::transform(key.begin(), key.end(), key.begin(), ::tolower);
+      const std::string& key = AsciiStrToLower(it->first);
       if (key == "origin") {
         origin = it->second;
         break;
@@ -708,7 +670,7 @@
   }
 
   if (!origin.empty() &&
-      (origin.find("http://" + std::string(kTestHost)) == 0 ||
+      (origin.find("https://" + std::string(kTestHost)) == 0 ||
        origin.find("http://" + std::string(kLocalHost)) == 0)) {
     // Allow cross-origin XMLHttpRequests from test origins.
     response_headers.insert(
@@ -799,15 +761,15 @@
                           StringResourceMap* string_resource_map) {
   if (!CefCurrentlyOn(TID_IO)) {
     // Execute on the browser IO thread.
-    CefPostTask(TID_IO, base::Bind(SetupResourceManager, resource_manager,
-                                   string_resource_map));
+    CefPostTask(TID_IO, base::BindOnce(SetupResourceManager, resource_manager,
+                                       string_resource_map));
     return;
   }
 
   const std::string& test_origin = kTestOrigin;
 
   // Add the URL filter.
-  resource_manager->SetUrlFilter(base::Bind(RequestUrlFilter));
+  resource_manager->SetUrlFilter(base::BindRepeating(RequestUrlFilter));
 
   // Add provider for resource dumps.
   resource_manager->AddProvider(
@@ -818,12 +780,13 @@
   std::set<std::string> string_pages;
   string_pages.insert(kTestGetSourcePage);
   string_pages.insert(kTestGetTextPage);
-  string_pages.insert(kTestPluginInfoPage);
 
-  // Add provider for string resources.
-  resource_manager->AddProvider(
-      new StringResourceProvider(string_pages, string_resource_map), 0,
-      std::string());
+  if (string_resource_map) {
+    // Add provider for string resources.
+    resource_manager->AddProvider(
+        new StringResourceProvider(string_pages, string_resource_map), 0,
+        std::string());
+  }
 
 // Add provider for bundled resource files.
 #if defined(OS_WIN)
@@ -846,26 +809,32 @@
     // Alerts originating from extension hosts should instead be displayed in
     // the active browser.
     browser = MainContext::Get()->GetRootWindowManager()->GetActiveBrowser();
-    if (!browser)
+    if (!browser) {
       return;
+    }
   }
 
   // Escape special characters in the message.
-  std::string msg = StringReplace(message, "\\", "\\\\");
-  msg = StringReplace(msg, "'", "\\'");
+  std::string msg = AsciiStrReplace(message, "\\", "\\\\");
+  msg = AsciiStrReplace(msg, "'", "\\'");
 
   // Execute a JavaScript alert().
   CefRefPtr<CefFrame> frame = browser->GetMainFrame();
   frame->ExecuteJavaScript("alert('" + msg + "');", frame->GetURL(), 0);
 }
 
+std::string GetTestURL(const std::string& path) {
+  return kTestOrigin + path;
+}
+
 bool IsTestURL(const std::string& url, const std::string& path) {
   CefURLParts parts;
   CefParseURL(url, parts);
 
   const std::string& url_host = CefString(&parts.host);
-  if (url_host != kTestHost && url_host != kLocalHost)
+  if (url_host != kTestHost && url_host != kLocalHost) {
     return false;
+  }
 
   const std::string& url_path = CefString(&parts.path);
   return url_path.find(path) == 0;
@@ -874,15 +843,15 @@
 void CreateMessageHandlers(MessageHandlerSet& handlers) {
   handlers.insert(new PromptHandler);
 
+  // Create the binary trasfer test handlers.
+  binary_transfer_test::CreateMessageHandlers(handlers);
+
   // Create the binding test handlers.
   binding_test::CreateMessageHandlers(handlers);
 
   // Create the dialog test handlers.
   dialog_test::CreateMessageHandlers(handlers);
 
-  // Create the drm test handlers.
-  drm_test::CreateMessageHandlers(handlers);
-
   // Create the media router test handlers.
   media_router_test::CreateMessageHandlers(handlers);
 
diff --git a/src/tests/cefclient/browser/test_runner.h b/src/tests/cefclient/browser/test_runner.h
index ed0172d..5b6f010 100644
--- a/src/tests/cefclient/browser/test_runner.h
+++ b/src/tests/cefclient/browser/test_runner.h
@@ -44,8 +44,11 @@
 // Show a JS alert message.
 void Alert(CefRefPtr<CefBrowser> browser, const std::string& message);
 
+// Returns "https://tests/<path>".
+std::string GetTestURL(const std::string& path);
+
 // Returns true if |url| is a test URL with the specified |path|. This matches
-// both http://tests/<path> and http://localhost:xxxx/<path>.
+// both "https://tests/<path>" and "http://localhost:xxxx/<path>".
 bool IsTestURL(const std::string& url, const std::string& path);
 
 // Create all CefMessageRouterBrowserSide::Handler objects. They will be
diff --git a/src/tests/cefclient/browser/text_input_client_osr_mac.h b/src/tests/cefclient/browser/text_input_client_osr_mac.h
index 9f6cbca..def6d55 100644
--- a/src/tests/cefclient/browser/text_input_client_osr_mac.h
+++ b/src/tests/cefclient/browser/text_input_client_osr_mac.h
@@ -16,7 +16,7 @@
 // Implementation for the NSTextInputClient protocol used for enabling IME on
 // mac when window rendering is disabled.
 
-@interface CefTextInputClientOSRMac : NSObject<NSTextInputClient> {
+@interface CefTextInputClientOSRMac : NSObject <NSTextInputClient> {
  @private
 
   // The range of current marked text inside the whole content of the DOM node
diff --git a/src/tests/cefclient/browser/text_input_client_osr_mac.mm b/src/tests/cefclient/browser/text_input_client_osr_mac.mm
index 8532708..1695b76 100644
--- a/src/tests/cefclient/browser/text_input_client_osr_mac.mm
+++ b/src/tests/cefclient/browser/text_input_client_osr_mac.mm
@@ -30,7 +30,7 @@
 // third_party/WebKit/Source/WebKit/mac/WebView/WebHTMLView.mm
 void ExtractUnderlines(NSAttributedString* string,
                        std::vector<CefCompositionUnderline>* underlines) {
-  int length = [[string string] length];
+  int length = static_cast<int>([[string string] length]);
   int i = 0;
   while (i < length) {
     NSRange range;
@@ -43,13 +43,17 @@
       if (NSColor* colorAttr =
               [attrs objectForKey:NSUnderlineColorAttributeName]) {
         color = CefColorFromNSColor(
-            [colorAttr colorUsingColorSpaceName:NSDeviceRGBColorSpace]);
+            [colorAttr colorUsingColorSpace:NSColorSpace.deviceRGBColorSpace]);
       }
       cef_composition_underline_t line = {
-          {range.location, NSMaxRange(range)}, color, 0, [style intValue] > 1};
+          {static_cast<uint32_t>(range.location),
+           static_cast<uint32_t>(NSMaxRange(range))},
+          color,
+          0,
+          [style intValue] > 1};
       underlines->push_back(line);
     }
-    i = range.location + range.length;
+    i = static_cast<int>(range.location + range.length);
   }
 }
 
@@ -71,7 +75,7 @@
 }
 
 - (void)detach {
-  browser_ = NULL;
+  browser_ = nullptr;
 }
 
 - (NSArray*)validAttributesForMarkedText {
@@ -86,8 +90,9 @@
 }
 
 - (NSRange)selectedRange {
-  if (selectedRange_.location == NSNotFound || selectedRange_.length == 0)
+  if (selectedRange_.location == NSNotFound || selectedRange_.length == 0) {
     return NSMakeRange(NSNotFound, 0);
+  }
   return selectedRange_;
 }
 
@@ -105,8 +110,8 @@
   if (handlingKeyDown_) {
     textToBeInserted_.append([im_text UTF8String]);
   } else {
-    cef_range_t range = {replacementRange.location,
-                         NSMaxRange(replacementRange)};
+    cef_range_t range = {static_cast<uint32_t>(replacementRange.location),
+                         static_cast<uint32_t>(NSMaxRange(replacementRange))};
     browser_->GetHost()->ImeCommitText([im_text UTF8String], range, 0);
   }
 
@@ -127,7 +132,7 @@
 
   BOOL isAttributedString = [aString isKindOfClass:[NSAttributedString class]];
   NSString* im_text = isAttributedString ? [aString string] : aString;
-  int length = [im_text length];
+  uint32_t length = static_cast<uint32_t>([im_text length]);
 
   // |markedRange_| will get set in a callback from ImeSetComposition().
   selectedRange_ = newSelRange;
@@ -149,12 +154,15 @@
   // ongoing composition. Our input method backend will automatically cancel an
   // ongoing composition when we send empty text.
   if (handlingKeyDown_) {
-    setMarkedTextReplacementRange_ = {replacementRange.location,
-                                      NSMaxRange(replacementRange)};
+    setMarkedTextReplacementRange_ = {
+        static_cast<uint32_t>(replacementRange.location),
+        static_cast<uint32_t>(NSMaxRange(replacementRange))};
   } else if (!handlingKeyDown_) {
-    CefRange replacement_range(replacementRange.location,
-                               NSMaxRange(replacementRange));
-    CefRange selection_range(newSelRange.location, NSMaxRange(newSelRange));
+    CefRange replacement_range(
+        static_cast<uint32_t>(replacementRange.location),
+        static_cast<uint32_t>(NSMaxRange(replacementRange)));
+    CefRange selection_range(static_cast<uint32_t>(newSelRange.location),
+                             static_cast<uint32_t>(NSMaxRange(newSelRange)));
 
     browser_->GetHost()->ImeSetComposition(markedText_, underlines_,
                                            replacement_range, selection_range);
@@ -173,10 +181,11 @@
 
   // If we are handling a key down event then ImeFinishComposingText() will be
   // called from the keyEvent: method.
-  if (!handlingKeyDown_)
+  if (!handlingKeyDown_) {
     browser_->GetHost()->ImeFinishComposingText(false);
-  else
+  } else {
     unmarkTextCalled_ = YES;
+  }
 }
 
 - (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range
@@ -194,20 +203,23 @@
   NSUInteger location = theRange.location;
 
   // If location is not specified fall back to the composition range start.
-  if (location == NSNotFound)
+  if (location == NSNotFound) {
     location = markedRange_.location;
+  }
 
   // Offset location by the composition range start if required.
-  if (location >= markedRange_.location)
+  if (location >= markedRange_.location) {
     location -= markedRange_.location;
+  }
 
   if (location < composition_bounds_.size()) {
     const CefRect& rc = composition_bounds_[location];
     rect = NSMakeRect(rc.x, rc.y, rc.width, rc.height);
   }
 
-  if (actualRange)
+  if (actualRange) {
     *actualRange = NSMakeRange(location, theRange.length);
+  }
 
   return rect;
 }
@@ -226,16 +238,17 @@
 
 - (NSRect)firstRectForCharacterRange:(NSRange)theRange
                          actualRange:(NSRangePointer)actualRange {
-  NSRect rect =
-      [self firstViewRectForCharacterRange:theRange actualRange:actualRange];
+  NSRect rect = [self firstViewRectForCharacterRange:theRange
+                                         actualRange:actualRange];
 
   // Convert into screen coordinates for return.
   rect = [self screenRectFromViewRect:rect];
 
-  if (rect.origin.y >= rect.size.height)
+  if (rect.origin.y >= rect.size.height) {
     rect.origin.y -= rect.size.height;
-  else
+  } else {
     rect.origin.y = 0;
+  }
 
   return rect;
 }
@@ -245,7 +258,7 @@
 }
 
 - (void)HandleKeyEventBeforeTextInputClient:(NSEvent*)keyEvent {
-  DCHECK([keyEvent type] == NSKeyDown);
+  DCHECK([keyEvent type] == NSEventTypeKeyDown);
   // Don't call this method recursively.
   DCHECK(!handlingKeyDown_);
 
@@ -257,7 +270,7 @@
   textToBeInserted_.clear();
   markedText_.clear();
   underlines_.clear();
-  setMarkedTextReplacementRange_ = CefRange(UINT32_MAX, UINT32_MAX);
+  setMarkedTextReplacementRange_ = CefRange::InvalidRange();
   unmarkTextCalled_ = NO;
 }
 
@@ -280,8 +293,9 @@
     // Don't send a CHAR event for non-char keys like arrows, function keys and
     // clear.
     if (keyEvent.modifiers & (EVENTFLAG_IS_KEY_PAD)) {
-      if (keyEvent.native_key_code == 71)
+      if (keyEvent.native_key_code == 71) {
         return;
+      }
     }
 
     keyEvent.type = KEYEVENT_CHAR;
@@ -294,7 +308,7 @@
   if (textToBeInserted_.length() >
       ((hasMarkedText_ || oldHasMarkedText_) ? 0u : 1u)) {
     browser_->GetHost()->ImeCommitText(textToBeInserted_,
-                                       CefRange(UINT32_MAX, UINT32_MAX), 0);
+                                       CefRange::InvalidRange(), 0);
     textToBeInserted_.clear();
   }
 
@@ -305,17 +319,19 @@
     // |selectedRange_| is the range being selected inside the marked text.
     browser_->GetHost()->ImeSetComposition(
         markedText_, underlines_, setMarkedTextReplacementRange_,
-        CefRange(selectedRange_.location, NSMaxRange(selectedRange_)));
+        CefRange(static_cast<uint32_t>(selectedRange_.location),
+                 static_cast<uint32_t>(NSMaxRange(selectedRange_))));
   } else if (oldHasMarkedText_ && !hasMarkedText_ && !textInserted) {
     // There was no marked text or inserted text. Complete or cancel the
     // composition.
-    if (unmarkTextCalled_)
+    if (unmarkTextCalled_) {
       browser_->GetHost()->ImeFinishComposingText(false);
-    else
+    } else {
       browser_->GetHost()->ImeCancelComposition();
+    }
   }
 
-  setMarkedTextReplacementRange_ = CefRange(UINT32_MAX, UINT32_MAX);
+  setMarkedTextReplacementRange_ = CefRange::InvalidRange();
 }
 
 - (void)ChangeCompositionRange:(CefRange)range
@@ -326,8 +342,9 @@
 }
 
 - (void)cancelComposition {
-  if (!hasMarkedText_)
+  if (!hasMarkedText_) {
     return;
+  }
 
 // Cancel the ongoing composition. [NSInputManager markedTextAbandoned:]
 // doesn't call any NSTextInput functions, such as setMarkedText or
diff --git a/src/tests/cefclient/browser/urlrequest_test.cc b/src/tests/cefclient/browser/urlrequest_test.cc
index 7e39613..135d57b 100644
--- a/src/tests/cefclient/browser/urlrequest_test.cc
+++ b/src/tests/cefclient/browser/urlrequest_test.cc
@@ -4,9 +4,9 @@
 
 #include "tests/cefclient/browser/urlrequest_test.h"
 
+#include <memory>
 #include <string>
 
-#include "include/base/cef_bind.h"
 #include "include/base/cef_callback.h"
 #include "include/base/cef_logging.h"
 #include "include/cef_urlrequest.h"
@@ -26,40 +26,40 @@
 class RequestClient : public CefURLRequestClient {
  public:
   // Callback to be executed on request completion.
-  typedef base::Callback<void(CefURLRequest::ErrorCode /*error_code*/,
-                              const std::string& /*download_data*/)>
-      Callback;
+  using Callback =
+      base::OnceCallback<void(CefURLRequest::ErrorCode /*error_code*/,
+                              const std::string& /*download_data*/)>;
 
-  explicit RequestClient(const Callback& callback) : callback_(callback) {
+  explicit RequestClient(Callback callback) : callback_(std::move(callback)) {
     CEF_REQUIRE_UI_THREAD();
     DCHECK(!callback_.is_null());
   }
 
   void Detach() {
     CEF_REQUIRE_UI_THREAD();
-    if (!callback_.is_null())
-      callback_.Reset();
-  }
-
-  void OnRequestComplete(CefRefPtr<CefURLRequest> request) OVERRIDE {
-    CEF_REQUIRE_UI_THREAD();
     if (!callback_.is_null()) {
-      callback_.Run(request->GetRequestError(), download_data_);
       callback_.Reset();
     }
   }
 
+  void OnRequestComplete(CefRefPtr<CefURLRequest> request) override {
+    CEF_REQUIRE_UI_THREAD();
+    if (!callback_.is_null()) {
+      std::move(callback_).Run(request->GetRequestError(), download_data_);
+    }
+  }
+
   void OnUploadProgress(CefRefPtr<CefURLRequest> request,
-                        int64 current,
-                        int64 total) OVERRIDE {}
+                        int64_t current,
+                        int64_t total) override {}
 
   void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
-                          int64 current,
-                          int64 total) OVERRIDE {}
+                          int64_t current,
+                          int64_t total) override {}
 
   void OnDownloadData(CefRefPtr<CefURLRequest> request,
                       const void* data,
-                      size_t data_length) OVERRIDE {
+                      size_t data_length) override {
     CEF_REQUIRE_UI_THREAD();
     download_data_ += std::string(static_cast<const char*>(data), data_length);
   }
@@ -69,7 +69,7 @@
                           int port,
                           const CefString& realm,
                           const CefString& scheme,
-                          CefRefPtr<CefAuthCallback> callback) OVERRIDE {
+                          CefRefPtr<CefAuthCallback> callback) override {
     return false;
   }
 
@@ -91,16 +91,17 @@
   // Called due to cefQuery execution in urlrequest.html.
   bool OnQuery(CefRefPtr<CefBrowser> browser,
                CefRefPtr<CefFrame> frame,
-               int64 query_id,
+               int64_t query_id,
                const CefString& request,
                bool persistent,
-               CefRefPtr<Callback> callback) OVERRIDE {
+               CefRefPtr<Callback> callback) override {
     CEF_REQUIRE_UI_THREAD();
 
     // Only handle messages from the test URL.
     const std::string& url = frame->GetURL();
-    if (!test_runner::IsTestURL(url, kTestUrlPath))
+    if (!test_runner::IsTestURL(url, kTestUrlPath)) {
       return false;
+    }
 
     const std::string& message_name = request;
     if (message_name.find(kTestMessageName) == 0) {
@@ -123,13 +124,13 @@
       // It's safe to use base::Unretained() here because there is only one
       // RequestClient pending at any given time and we explicitly detach the
       // callback in the Handler destructor.
-      const RequestClient::Callback& request_callback =
-          base::Bind(&Handler::OnRequestComplete, base::Unretained(this));
+      auto request_callback =
+          base::BindOnce(&Handler::OnRequestComplete, base::Unretained(this));
 
       // Create and start a new CefURLRequest associated with the frame, so
       // that it shares authentication with ClientHandler::GetAuthCredentials.
       urlrequest_ = frame->CreateURLRequest(
-          cef_request, new RequestClient(request_callback));
+          cef_request, new RequestClient(std::move(request_callback)));
 
       return true;
     }
@@ -161,10 +162,11 @@
                          const std::string& download_data) {
     CEF_REQUIRE_UI_THREAD();
 
-    if (error_code == ERR_NONE)
+    if (error_code == ERR_NONE) {
       callback_->Success(download_data);
-    else
+    } else {
       callback_->Failure(error_code, test_runner::GetErrorString(error_code));
+    }
 
     callback_ = nullptr;
     urlrequest_ = nullptr;
diff --git a/src/tests/cefclient/browser/views_menu_bar.cc b/src/tests/cefclient/browser/views_menu_bar.cc
index a7b4b4f..6f04714 100644
--- a/src/tests/cefclient/browser/views_menu_bar.cc
+++ b/src/tests/cefclient/browser/views_menu_bar.cc
@@ -4,6 +4,7 @@
 
 #include "tests/cefclient/browser/views_menu_bar.h"
 
+#include "include/cef_i18n_util.h"
 #include "include/views/cef_box_layout.h"
 #include "include/views/cef_window.h"
 #include "tests/cefclient/browser/views_style.h"
@@ -19,7 +20,7 @@
 // If the mnemonic is capital I and the UI language is Turkish, lowercasing it
 // results in 'small dotless i', which is different from a 'dotted i'. Similar
 // issues may exist for az and lt locales.
-base::char16 ToLower(base::char16 c) {
+char16_t ToLower(char16_t c) {
   CefStringUTF16 str16;
   cef_string_utf16_to_lower(&c, 1, str16.GetWritableStruct());
   return str16.length() > 0 ? str16.c_str()[0] : 0;
@@ -27,24 +28,28 @@
 
 // Extract the mnemonic character from |title|. For example, if |title| is
 // "&Test" then the mnemonic character is 'T'.
-base::char16 GetMnemonic(const base::string16& title) {
+char16_t GetMnemonic(const std::u16string& title) {
   size_t index = 0;
   do {
     index = title.find('&', index);
-    if (index != base::string16::npos) {
-      if (index + 1 != title.size() && title[index + 1] != '&')
+    if (index != std::u16string::npos) {
+      if (index + 1 != title.size() && title[index + 1] != '&') {
         return ToLower(title[index + 1]);
+      }
       index++;
     }
-  } while (index != base::string16::npos);
+  } while (index != std::u16string::npos);
   return 0;
 }
 
 }  // namespace
 
-ViewsMenuBar::ViewsMenuBar(Delegate* delegate, int menu_id_start)
+ViewsMenuBar::ViewsMenuBar(Delegate* delegate,
+                           int menu_id_start,
+                           bool use_bottom_controls)
     : delegate_(delegate),
       id_start_(menu_id_start),
+      use_bottom_controls_(use_bottom_controls),
       id_next_(menu_id_start),
       last_nav_with_keyboard_(false) {
   DCHECK(delegate_);
@@ -66,8 +71,9 @@
 
   // Assign the new menu ID.
   const int new_menu_id = id_next_++;
-  if (menu_id)
+  if (menu_id) {
     *menu_id = new_menu_id;
+  }
 
   // Create the new MenuModel.
   CefRefPtr<CefMenuModel> model = CefMenuModel::CreateMenuModel(this);
@@ -89,25 +95,29 @@
   panel_->AddChildView(button);
 
   // Extract the mnemonic that triggers the menu, if any.
-  base::char16 mnemonic = GetMnemonic(label);
-  if (mnemonic != 0)
+  char16_t mnemonic = GetMnemonic(label);
+  if (mnemonic != 0) {
     mnemonics_.insert(std::make_pair(mnemonic, new_menu_id));
+  }
 
   return model;
 }
 
 CefRefPtr<CefMenuModel> ViewsMenuBar::GetMenuModel(int menu_id) const {
-  if (HasMenuId(menu_id))
+  if (HasMenuId(menu_id)) {
     return models_[menu_id - id_start_];
+  }
   return nullptr;
 }
 
 void ViewsMenuBar::SetMenuFocusable(bool focusable) {
-  if (!panel_)
+  if (!panel_) {
     return;
+  }
 
-  for (int id = id_start_; id < id_next_; ++id)
+  for (int id = id_start_; id < id_next_; ++id) {
     panel_->GetViewForID(id)->SetFocusable(focusable);
+  }
 
   if (focusable) {
     // Give focus to the first MenuButton.
@@ -116,20 +126,24 @@
 }
 
 bool ViewsMenuBar::OnKeyEvent(const CefKeyEvent& event) {
-  if (!panel_)
+  if (!panel_) {
     return false;
+  }
 
-  if (event.type != KEYEVENT_RAWKEYDOWN)
+  if (event.type != KEYEVENT_RAWKEYDOWN) {
     return false;
+  }
 
   // Do not check mnemonics if the Alt or Ctrl modifiers are pressed. For
   // example Ctrl+<T> is an accelerator, but <T> only is a mnemonic.
-  if (event.modifiers & (EVENTFLAG_ALT_DOWN | EVENTFLAG_CONTROL_DOWN))
+  if (event.modifiers & (EVENTFLAG_ALT_DOWN | EVENTFLAG_CONTROL_DOWN)) {
     return false;
+  }
 
   MnemonicMap::const_iterator it = mnemonics_.find(ToLower(event.character));
-  if (it == mnemonics_.end())
+  if (it == mnemonics_.end()) {
     return false;
+  }
 
   // Set status indicating that we navigated using the keyboard.
   last_nav_with_keyboard_ = true;
@@ -153,9 +167,30 @@
     CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock) {
   CefRefPtr<CefMenuModel> menu_model = GetMenuModel(menu_button->GetID());
 
-  // Adjust menu position left by button width.
+  const auto button_bounds = menu_button->GetBoundsInScreen();
+
+  // Adjust menu position to align with the button.
   CefPoint point = screen_point;
-  point.x -= menu_button->GetBounds().width - 4;
+  if (CefIsRTL()) {
+    point.x += button_bounds.width - 4;
+  } else {
+    point.x -= button_bounds.width - 4;
+  }
+
+  if (use_bottom_controls_) {
+    const auto display_bounds =
+        menu_button->GetWindow()->GetDisplay()->GetWorkArea();
+    const int available_height = display_bounds.y + display_bounds.height -
+                                 button_bounds.y - button_bounds.height;
+
+    // Approximation of the menu height.
+    const int menu_height =
+        static_cast<int>(menu_model->GetCount()) * button_bounds.height;
+    if (menu_height > available_height) {
+      // The menu will go upwards, so place it above the button.
+      point.y -= button_bounds.height - 8;
+    }
+  }
 
   // Keep track of the current |last_nav_with_keyboard_| status and restore it
   // after displaying the new menu.
@@ -184,33 +219,46 @@
 
   // Convert the point from screen to window coordinates.
   CefPoint window_point = screen_point;
-  if (!window->ConvertPointFromScreen(window_point))
+  if (!window->ConvertPointFromScreen(window_point)) {
     return;
+  }
 
   CefRect panel_bounds = panel_->GetBounds();
 
   if (last_nav_with_keyboard_) {
     // The user navigated last using the keyboard. Don't change menus using
     // mouse movements until the mouse exits and re-enters the Panel.
-    if (panel_bounds.Contains(window_point))
+    if (panel_bounds.Contains(window_point)) {
       return;
+    }
     last_nav_with_keyboard_ = false;
   }
 
   // Check that the point is inside the Panel.
-  if (!panel_bounds.Contains(window_point))
+  if (!panel_bounds.Contains(window_point)) {
     return;
+  }
 
   const int active_menu_id = GetActiveMenuId();
 
   // Determine which MenuButton is under the specified point.
   for (int id = id_start_; id < id_next_; ++id) {
     // Skip the currently active MenuButton.
-    if (id == active_menu_id)
+    if (id == active_menu_id) {
       continue;
+    }
 
     CefRefPtr<CefView> button = panel_->GetViewForID(id);
     CefRect button_bounds = button->GetBounds();
+
+    // Adjust for window coordinates.
+    button_bounds.y += panel_bounds.y;
+
+    if (CefIsRTL()) {
+      // Adjust for right-to-left button layout.
+      button_bounds.x =
+          panel_bounds.width - button_bounds.x - button_bounds.width;
+    }
     if (button_bounds.Contains(window_point)) {
       // Trigger the hovered MenuButton.
       TriggerMenuButton(button);
@@ -231,13 +279,15 @@
 
 void ViewsMenuBar::MenuClosed(CefRefPtr<CefMenuModel> menu_model) {
   // Reset |last_nav_with_keyboard_| status whenever the main menu closes.
-  if (!menu_model->IsSubMenu() && last_nav_with_keyboard_)
+  if (!menu_model->IsSubMenu() && last_nav_with_keyboard_) {
     last_nav_with_keyboard_ = false;
+  }
 }
 
 void ViewsMenuBar::EnsureMenuPanel() {
-  if (panel_)
+  if (panel_) {
     return;
+  }
 
   panel_ = CefPanel::CreatePanel(nullptr);
   views_style::ApplyTo(panel_);
@@ -253,8 +303,9 @@
 
   for (int id = id_start_; id < id_next_; ++id) {
     CefRefPtr<CefButton> button = panel_->GetViewForID(id)->AsButton();
-    if (button->GetState() == CEF_BUTTON_STATE_PRESSED)
+    if (button->GetState() == CEF_BUTTON_STATE_PRESSED) {
       return id;
+    }
   }
 
   return -1;
@@ -269,8 +320,9 @@
 
   // Compute the modulus to avoid negative values.
   int next_menu_index = (active_menu_index + offset) % menu_count;
-  if (next_menu_index < 0)
+  if (next_menu_index < 0) {
     next_menu_index += menu_count;
+  }
 
   // Cancel the existing menu. MenuClosed may be called.
   panel_->GetWindow()->CancelMenu();
@@ -285,8 +337,9 @@
 void ViewsMenuBar::TriggerMenuButton(CefRefPtr<CefView> button) {
   CefRefPtr<CefMenuButton> menu_button =
       button->AsButton()->AsLabelButton()->AsMenuButton();
-  if (menu_button->IsFocusable())
+  if (menu_button->IsFocusable()) {
     menu_button->RequestFocus();
+  }
   menu_button->TriggerMenu();
 }
 
diff --git a/src/tests/cefclient/browser/views_menu_bar.h b/src/tests/cefclient/browser/views_menu_bar.h
index 0bf1b2d..e1f6ec6 100644
--- a/src/tests/cefclient/browser/views_menu_bar.h
+++ b/src/tests/cefclient/browser/views_menu_bar.h
@@ -39,7 +39,7 @@
   // |menu_id_start| is the ID for the first CefMenuButton in the bar. An ID
   // range starting with |menu_id_start| and extending for a reasonable distance
   // should be reserved in the client for MenuBar usage.
-  ViewsMenuBar(Delegate* delegate, int menu_id_start);
+  ViewsMenuBar(Delegate* delegate, int menu_id_start, bool use_bottom_controls);
 
   // Returns true if |menu_id| exists in the menu bar.
   bool HasMenuId(int menu_id) const;
@@ -47,11 +47,11 @@
   // Returns the CefPanel that represents the menu bar.
   CefRefPtr<CefPanel> GetMenuPanel();
 
-  // Create a new menu with the specified |label|. If |menu_id| is non-NULL it
-  // will be populated with the new menu ID.
+  // Create a new menu with the specified |label|. If |menu_id| is non-nullptr
+  // it will be populated with the new menu ID.
   CefRefPtr<CefMenuModel> CreateMenuModel(const CefString& label, int* menu_id);
 
-  // Returns the menu with the specified |menu_id|, or NULL if no such menu
+  // Returns the menu with the specified |menu_id|, or nullptr if no such menu
   // exists.
   CefRefPtr<CefMenuModel> GetMenuModel(int menu_id) const;
 
@@ -70,25 +70,25 @@
 
  protected:
   // CefButtonDelegate methods:
-  void OnButtonPressed(CefRefPtr<CefButton> button) OVERRIDE {}
+  void OnButtonPressed(CefRefPtr<CefButton> button) override {}
 
   // CefMenuButtonDelegate methods:
   void OnMenuButtonPressed(
       CefRefPtr<CefMenuButton> menu_button,
       const CefPoint& screen_point,
-      CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock) OVERRIDE;
+      CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock) override;
 
   // CefMenuModelDelegate methods:
   void ExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
                       int command_id,
-                      cef_event_flags_t event_flags) OVERRIDE;
+                      cef_event_flags_t event_flags) override;
   void MouseOutsideMenu(CefRefPtr<CefMenuModel> menu_model,
-                        const CefPoint& screen_point) OVERRIDE;
+                        const CefPoint& screen_point) override;
   void UnhandledOpenSubmenu(CefRefPtr<CefMenuModel> menu_model,
-                            bool is_rtl) OVERRIDE;
+                            bool is_rtl) override;
   void UnhandledCloseSubmenu(CefRefPtr<CefMenuModel> menu_model,
-                             bool is_rtl) OVERRIDE;
-  void MenuClosed(CefRefPtr<CefMenuModel> menu_model) OVERRIDE;
+                             bool is_rtl) override;
+  void MenuClosed(CefRefPtr<CefMenuModel> menu_model) override;
 
  private:
   // Creates the menu panel if it doesn't already exist.
@@ -106,13 +106,14 @@
 
   Delegate* delegate_;  // Not owned by this object.
   const int id_start_;
+  const bool use_bottom_controls_;
   int id_next_;
   CefRefPtr<CefPanel> panel_;
   std::vector<CefRefPtr<CefMenuModel>> models_;
   bool last_nav_with_keyboard_;
 
   // Map of mnemonic to MenuButton ID.
-  typedef std::map<base::char16, int> MnemonicMap;
+  typedef std::map<char16_t, int> MnemonicMap;
   MnemonicMap mnemonics_;
 
   IMPLEMENT_REFCOUNTING(ViewsMenuBar);
diff --git a/src/tests/cefclient/browser/views_overlay_controls.cc b/src/tests/cefclient/browser/views_overlay_controls.cc
new file mode 100644
index 0000000..582f0e1
--- /dev/null
+++ b/src/tests/cefclient/browser/views_overlay_controls.cc
@@ -0,0 +1,253 @@
+// Copyright (c) 2021 The Chromium Embedded Framework 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 "tests/cefclient/browser/views_overlay_controls.h"
+
+#include <algorithm>
+#include <array>
+#include <string>
+
+#include "include/views/cef_box_layout.h"
+#include "include/views/cef_window.h"
+#include "tests/cefclient/browser/views_style.h"
+
+namespace client {
+
+namespace {
+
+constexpr int kInsets = 4;
+constexpr int kLocationBarPadding = 100;
+
+// White with 80% opacity.
+constexpr auto kBackgroundColor = CefColorSetARGB(255 * .80, 255, 255, 255);
+
+std::string GetLabel(ViewsOverlayControls::Command command, bool maximized) {
+  switch (command) {
+    case ViewsOverlayControls::Command::kMinimize:
+      return "-";
+    case ViewsOverlayControls::Command::kMaximize:
+      return maximized ? "O" : "o";
+    case ViewsOverlayControls::Command::kClose:
+      return "X";
+  }
+  NOTREACHED();
+  return std::string();
+}
+
+std::array<ViewsOverlayControls::Command, 3> GetButtons() {
+#if defined(OS_MAC)
+  return {ViewsOverlayControls::Command::kClose,
+          ViewsOverlayControls::Command::kMaximize,
+          ViewsOverlayControls::Command::kMinimize};
+#else
+  return {ViewsOverlayControls::Command::kMinimize,
+          ViewsOverlayControls::Command::kMaximize,
+          ViewsOverlayControls::Command::kClose};
+#endif
+}
+
+cef_docking_mode_t GetPanelDockingMode(bool use_bottom_controls) {
+#if defined(OS_MAC)
+  return use_bottom_controls ? CEF_DOCKING_MODE_BOTTOM_LEFT
+                             : CEF_DOCKING_MODE_TOP_LEFT;
+#else
+  return use_bottom_controls ? CEF_DOCKING_MODE_BOTTOM_RIGHT
+                             : CEF_DOCKING_MODE_TOP_RIGHT;
+#endif
+}
+cef_docking_mode_t GetMenuDockingMode(bool use_bottom_controls) {
+#if defined(OS_MAC)
+  return use_bottom_controls ? CEF_DOCKING_MODE_BOTTOM_RIGHT
+                             : CEF_DOCKING_MODE_TOP_RIGHT;
+#else
+  return use_bottom_controls ? CEF_DOCKING_MODE_BOTTOM_LEFT
+                             : CEF_DOCKING_MODE_TOP_LEFT;
+#endif
+}
+
+}  // namespace
+
+ViewsOverlayControls::ViewsOverlayControls(bool with_window_buttons,
+                                           bool use_bottom_controls)
+    : with_window_buttons_(with_window_buttons),
+      use_bottom_controls_(use_bottom_controls) {}
+
+void ViewsOverlayControls::Initialize(CefRefPtr<CefWindow> window,
+                                      CefRefPtr<CefMenuButton> menu_button,
+                                      CefRefPtr<CefView> location_bar,
+                                      bool is_chrome_toolbar) {
+  DCHECK(!window_);
+  DCHECK(menu_button);
+  DCHECK(location_bar);
+
+  window_ = window;
+  window_maximized_ = window_->IsMaximized();
+
+  CefInsets insets;
+  if (use_bottom_controls_) {
+    insets.Set(0, kInsets, kInsets, kInsets);
+  } else {
+    insets.Set(kInsets, kInsets, 0, kInsets);
+  }
+
+  if (with_window_buttons_) {
+    // Window control buttons. These controls are currently text which means
+    // that we can't use a transparent background because subpixel text
+    // rendering will break.
+    // See comments on the related DCHECK in Label::PaintText.
+    panel_ = CefPanel::CreatePanel(nullptr);
+    views_style::ApplyTo(panel_);
+
+    // Use a horizontal box layout.
+    CefBoxLayoutSettings panel_layout_settings;
+    panel_layout_settings.horizontal = true;
+    panel_->SetToBoxLayout(panel_layout_settings);
+
+    for (auto button : GetButtons()) {
+      panel_->AddChildView(CreateButton(button));
+    }
+    panel_controller_ = window->AddOverlayView(
+        panel_, GetPanelDockingMode(use_bottom_controls_));
+    panel_controller_->SetInsets(insets);
+    panel_controller_->SetVisible(true);
+  }
+
+  // Menu button.
+  menu_button->SetBackgroundColor(kBackgroundColor);
+  menu_controller_ = window_->AddOverlayView(
+      menu_button, GetMenuDockingMode(use_bottom_controls_));
+  menu_controller_->SetInsets(insets);
+  menu_controller_->SetVisible(true);
+
+  // Location bar. Will be made visible in UpdateControls().
+  location_bar_ = location_bar;
+  is_chrome_toolbar_ = is_chrome_toolbar;
+  // Use a 100% transparent background for the Chrome toolbar.
+  location_bar_->SetBackgroundColor(is_chrome_toolbar_ ? 0 : kBackgroundColor);
+  location_controller_ =
+      window_->AddOverlayView(location_bar_, CEF_DOCKING_MODE_CUSTOM);
+}
+
+void ViewsOverlayControls::Destroy() {
+  window_ = nullptr;
+  panel_ = nullptr;
+  if (panel_controller_) {
+    panel_controller_->Destroy();
+    panel_controller_ = nullptr;
+  }
+  menu_controller_->Destroy();
+  menu_controller_ = nullptr;
+  location_bar_ = nullptr;
+  location_controller_->Destroy();
+  location_controller_ = nullptr;
+}
+
+void ViewsOverlayControls::UpdateControls() {
+  // Update location bar size, position and visibility.
+  const auto window_bounds = window_->GetBounds();
+  auto bounds = window_bounds;
+  bounds.x = kLocationBarPadding;
+  bounds.width -= kLocationBarPadding * 2;
+
+  if (is_chrome_toolbar_) {
+    // Fit the standard Chrome toolbar.
+    const auto preferred_size = location_bar_->GetPreferredSize();
+    bounds.height =
+        std::max(menu_controller_->GetSize().height, preferred_size.height);
+  } else {
+    bounds.height = menu_controller_->GetSize().height;
+  }
+
+  if (use_bottom_controls_) {
+    bounds.y = window_bounds.height - bounds.height - kInsets;
+  } else {
+    bounds.y = kInsets;
+  }
+
+  if (bounds.width < kLocationBarPadding * 2) {
+    // Not enough space.
+    location_controller_->SetVisible(false);
+  } else {
+    location_bar_->SetSize(CefSize(bounds.width, bounds.height));
+    location_controller_->SetBounds(bounds);
+    location_controller_->SetVisible(true);
+  }
+
+  MaybeUpdateMaximizeButton();
+}
+
+void ViewsOverlayControls::UpdateDraggableRegions(
+    std::vector<CefDraggableRegion>& window_regions) {
+  if (panel_controller_ && panel_controller_->IsVisible()) {
+    window_regions.push_back(CefDraggableRegion(panel_controller_->GetBounds(),
+                                                /*draggable=*/false));
+  }
+
+  if (menu_controller_ && menu_controller_->IsVisible()) {
+    window_regions.push_back(
+        CefDraggableRegion(menu_controller_->GetBounds(), /*draggable=*/false));
+  }
+
+  if (location_controller_ && location_controller_->IsVisible()) {
+    window_regions.push_back(CefDraggableRegion(
+        location_controller_->GetBounds(), /*draggable=*/false));
+  }
+}
+
+void ViewsOverlayControls::OnButtonPressed(CefRefPtr<CefButton> button) {
+  auto command = static_cast<Command>(button->GetID());
+  switch (command) {
+    case ViewsOverlayControls::Command::kMinimize:
+      window_->Minimize();
+      break;
+    case ViewsOverlayControls::Command::kMaximize:
+      if (window_->IsMaximized()) {
+        window_->Restore();
+      } else {
+        window_->Maximize();
+      }
+      break;
+    case ViewsOverlayControls::Command::kClose:
+      window_->Close();
+      return;
+  }
+
+  // Explicitly reset button state because the button may have moved and it
+  // won't receive the corresponding mouse move events.
+  button->SetState(CEF_BUTTON_STATE_NORMAL);
+  button->SetInkDropEnabled(false);
+  button->SetInkDropEnabled(true);
+
+  if (command == Command::kMaximize) {
+    MaybeUpdateMaximizeButton();
+  }
+}
+
+CefRefPtr<CefLabelButton> ViewsOverlayControls::CreateButton(Command command) {
+  CefRefPtr<CefLabelButton> button = CefLabelButton::CreateLabelButton(
+      this, GetLabel(command, window_maximized_));
+  button->SetID(static_cast<int>(command));
+  views_style::ApplyTo(button);
+  button->SetInkDropEnabled(true);
+  button->SetFocusable(false);  // Don't give focus to the button.
+  return button;
+}
+
+void ViewsOverlayControls::MaybeUpdateMaximizeButton() {
+  if (!with_window_buttons_ || window_->IsMaximized() == window_maximized_) {
+    return;
+  }
+  window_maximized_ = !window_maximized_;
+
+  auto max_button = panel_->GetChildViewAt(1);
+  auto command = static_cast<Command>(max_button->GetID());
+  DCHECK(command == Command::kMaximize);
+  max_button->AsButton()->AsLabelButton()->SetText(
+      GetLabel(command, window_maximized_));
+
+  // Adjust overlay size and placement due to layout changing.
+  panel_controller_->SizeToPreferredSize();
+}
+
+}  // namespace client
diff --git a/src/tests/cefclient/browser/views_overlay_controls.h b/src/tests/cefclient/browser/views_overlay_controls.h
new file mode 100644
index 0000000..0a79424
--- /dev/null
+++ b/src/tests/cefclient/browser/views_overlay_controls.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2021 The Chromium Embedded Framework 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 CEF_TESTS_CEFCLIENT_BROWSER_VIEWS_OVERLAY_CONTROLS_H_
+#define CEF_TESTS_CEFCLIENT_BROWSER_VIEWS_OVERLAY_CONTROLS_H_
+#pragma once
+
+#include "include/views/cef_button_delegate.h"
+#include "include/views/cef_label_button.h"
+#include "include/views/cef_menu_button.h"
+#include "include/views/cef_overlay_controller.h"
+#include "include/views/cef_panel.h"
+
+namespace client {
+
+// Implements window overlay controls that receive absolute positioning on top
+// of the browser view. All methods must be called on the browser process UI
+// thread.
+class ViewsOverlayControls : public CefButtonDelegate {
+ public:
+  enum class Command {
+    kMinimize = 1,
+    kMaximize,
+    kClose,
+  };
+
+  ViewsOverlayControls(bool with_window_buttons, bool use_bottom_controls);
+
+  void Initialize(CefRefPtr<CefWindow> window,
+                  CefRefPtr<CefMenuButton> menu_button,
+                  CefRefPtr<CefView> location_bar,
+                  bool is_chrome_toolbar);
+  void Destroy();
+
+  // Update window control button state and location bar bounds.
+  void UpdateControls();
+
+  // Exclude all regions obscured by overlays.
+  void UpdateDraggableRegions(std::vector<CefDraggableRegion>& window_regions);
+
+ private:
+  // CefButtonDelegate methods:
+  void OnButtonPressed(CefRefPtr<CefButton> button) override;
+
+  CefRefPtr<CefLabelButton> CreateButton(Command command);
+
+  void MaybeUpdateMaximizeButton();
+
+  CefRefPtr<CefWindow> window_;
+  bool window_maximized_;
+
+  // Window control buttons.
+  CefRefPtr<CefPanel> panel_;
+  CefRefPtr<CefOverlayController> panel_controller_;
+  const bool with_window_buttons_;
+  const bool use_bottom_controls_;
+
+  // Location bar.
+  CefRefPtr<CefView> location_bar_;
+  bool is_chrome_toolbar_;
+  CefRefPtr<CefOverlayController> location_controller_;
+
+  // Menu button.
+  CefRefPtr<CefOverlayController> menu_controller_;
+
+  IMPLEMENT_REFCOUNTING(ViewsOverlayControls);
+  DISALLOW_COPY_AND_ASSIGN(ViewsOverlayControls);
+};
+
+}  // namespace client
+
+#endif  // CEF_TESTS_CEFCLIENT_BROWSER_VIEWS_OVERLAY_CONTROLS_H_
diff --git a/src/tests/cefclient/browser/views_style.cc b/src/tests/cefclient/browser/views_style.cc
index 830b7ce..4021ebd 100644
--- a/src/tests/cefclient/browser/views_style.cc
+++ b/src/tests/cefclient/browser/views_style.cc
@@ -22,8 +22,9 @@
 
 void MaybeInitialize() {
   static bool initialized = false;
-  if (initialized)
+  if (initialized) {
     return;
+  }
 
   g_background_color = MainContext::Get()->GetBackgroundColor();
   if (g_background_color != 0) {
@@ -49,16 +50,26 @@
   return g_background_color != 0;
 }
 
-void ApplyTo(CefRefPtr<CefPanel> panel) {
-  if (!IsSet())
+void ApplyBackgroundTo(CefRefPtr<CefView> view) {
+  if (!IsSet()) {
     return;
+  }
+
+  view->SetBackgroundColor(g_background_color);
+}
+
+void ApplyTo(CefRefPtr<CefPanel> panel) {
+  if (!IsSet()) {
+    return;
+  }
 
   panel->SetBackgroundColor(g_background_color);
 }
 
 void ApplyTo(CefRefPtr<CefLabelButton> label_button) {
-  if (!IsSet())
+  if (!IsSet()) {
     return;
+  }
 
   // All text except disabled gets the same color.
   label_button->SetEnabledTextColors(g_text_color);
@@ -69,16 +80,18 @@
 }
 
 void ApplyTo(CefRefPtr<CefTextfield> textfield) {
-  if (!IsSet())
+  if (!IsSet()) {
     return;
+  }
 
   textfield->SetBackgroundColor(g_background_color);
   textfield->SetTextColor(g_text_color);
 }
 
 void ApplyTo(CefRefPtr<CefMenuModel> menu_model) {
-  if (!IsSet())
+  if (!IsSet()) {
     return;
+  }
 
   // All text except non-hovered accelerator gets the same color.
   menu_model->SetColorAt(-1, CEF_MENU_COLOR_TEXT, g_text_color);
@@ -93,9 +106,10 @@
                          g_background_hover_color);
 
   // Recursively color sub-menus.
-  for (int i = 0; i < menu_model->GetCount(); ++i) {
-    if (menu_model->GetTypeAt(i) == MENUITEMTYPE_SUBMENU)
+  for (size_t i = 0; i < menu_model->GetCount(); ++i) {
+    if (menu_model->GetTypeAt(i) == MENUITEMTYPE_SUBMENU) {
       ApplyTo(menu_model->GetSubMenuAt(i));
+    }
   }
 }
 
diff --git a/src/tests/cefclient/browser/views_style.h b/src/tests/cefclient/browser/views_style.h
index 0d32f2c..f9b7c97 100644
--- a/src/tests/cefclient/browser/views_style.h
+++ b/src/tests/cefclient/browser/views_style.h
@@ -19,6 +19,7 @@
 bool IsSet();
 
 // Apply style to views objects.
+void ApplyBackgroundTo(CefRefPtr<CefView> view);
 void ApplyTo(CefRefPtr<CefPanel> panel);
 void ApplyTo(CefRefPtr<CefLabelButton> label_button);
 void ApplyTo(CefRefPtr<CefTextfield> textfield);
diff --git a/src/tests/cefclient/browser/views_window.cc b/src/tests/cefclient/browser/views_window.cc
index 230e6de..65abb6d 100644
--- a/src/tests/cefclient/browser/views_window.cc
+++ b/src/tests/cefclient/browser/views_window.cc
@@ -6,11 +6,13 @@
 
 #include <algorithm>
 
-#include "include/base/cef_bind.h"
 #include "include/base/cef_build.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_app.h"
+#include "include/cef_i18n_util.h"
 #include "include/views/cef_box_layout.h"
 #include "include/wrapper/cef_helpers.h"
+#include "tests/cefclient/browser/main_context.h"
 #include "tests/cefclient/browser/resource.h"
 #include "tests/cefclient/browser/views_style.h"
 #include "tests/shared/browser/extension_util.h"
@@ -28,6 +30,15 @@
 
 const char kDefaultExtensionIcon[] = "window_icon";
 
+// Default window size.
+constexpr int kDefaultWidth = 800;
+constexpr int kDefaultHeight = 600;
+
+#if defined(OS_MAC)
+constexpr int kTitleBarHeight = 35;
+constexpr int kWindowButtonsWidth = 80;
+#endif
+
 // Control IDs for Views in the top-level Window.
 enum ControlIds {
   ID_WINDOW = 1,
@@ -57,10 +68,12 @@
   // Determine the largest button size.
   for (size_t i = 0U; i < buttons.size(); ++i) {
     const CefSize& button_size = buttons[i]->GetPreferredSize();
-    if (size.width < button_size.width)
+    if (size.width < button_size.width) {
       size.width = button_size.width;
-    if (size.height < button_size.height)
+    }
+    if (size.height < button_size.height) {
       size.height = button_size.height;
+    }
   }
 
   for (size_t i = 0U; i < buttons.size(); ++i) {
@@ -77,8 +90,8 @@
   test_menu->AddItem(ID_TESTS_GETTEXT, "Get Text");
   test_menu->AddItem(ID_TESTS_WINDOW_NEW, "New Window");
   test_menu->AddItem(ID_TESTS_WINDOW_POPUP, "Popup Window");
+  test_menu->AddItem(ID_TESTS_WINDOW_DIALOG, "Dialog Window");
   test_menu->AddItem(ID_TESTS_REQUEST, "Request");
-  test_menu->AddItem(ID_TESTS_PLUGIN_INFO, "Plugin Info");
   test_menu->AddItem(ID_TESTS_ZOOM_IN, "Zoom In");
   test_menu->AddItem(ID_TESTS_ZOOM_OUT, "Zoom Out");
   test_menu->AddItem(ID_TESTS_ZOOM_RESET, "Zoom Reset");
@@ -99,10 +112,27 @@
                               true);
 }
 
+CefBrowserViewDelegate::ChromeToolbarType CalculateChromeToolbarType(
+    const std::string& toolbar_type,
+    bool hide_toolbar,
+    bool with_overlay_controls) {
+  if (!MainContext::Get()->UseChromeRuntime() || toolbar_type == "none" ||
+      hide_toolbar) {
+    return CEF_CTT_NONE;
+  }
+
+  if (toolbar_type == "location") {
+    return CEF_CTT_LOCATION;
+  }
+
+  return with_overlay_controls ? CEF_CTT_LOCATION : CEF_CTT_NORMAL;
+}
+
 }  // namespace
 
 // static
 CefRefPtr<ViewsWindow> ViewsWindow::Create(
+    WindowType type,
     Delegate* delegate,
     CefRefPtr<CefClient> client,
     const CefString& url,
@@ -112,7 +142,8 @@
   DCHECK(delegate);
 
   // Create a new ViewsWindow.
-  CefRefPtr<ViewsWindow> views_window = new ViewsWindow(delegate, nullptr);
+  CefRefPtr<ViewsWindow> views_window =
+      new ViewsWindow(type, delegate, nullptr);
 
   // Create a new BrowserView.
   CefRefPtr<CefBrowserView> browser_view = CefBrowserView::CreateBrowserView(
@@ -129,9 +160,29 @@
 
 void ViewsWindow::Show() {
   CEF_REQUIRE_UI_THREAD();
-  if (window_)
-    window_->Show();
-  if (browser_view_) {
+  if (window_) {
+    if (type_ == WindowType::DIALOG) {
+      if (use_window_modal_dialog_) {
+        // Show as a window modal dialog (IsWindowModalDialog() will return
+        // true).
+        window_->Show();
+      } else {
+        CefRefPtr<CefBrowserView> browser_view;
+        if (auto parent_window = delegate_->GetParentWindow()) {
+          if (auto view = parent_window->GetViewForID(ID_BROWSER_VIEW)) {
+            browser_view = view->AsBrowserView();
+          }
+        }
+        CHECK(browser_view);
+
+        // Show as a browser modal dialog (relative to |browser_view|).
+        window_->ShowAsBrowserModalDialog(browser_view);
+      }
+    } else {
+      window_->Show();
+    }
+  }
+  if (browser_view_ && !window_->IsMinimized()) {
     // Give keyboard focus to the BrowserView.
     browser_view_->RequestFocus();
   }
@@ -139,45 +190,52 @@
 
 void ViewsWindow::Hide() {
   CEF_REQUIRE_UI_THREAD();
-  if (window_)
+  if (window_) {
     window_->Hide();
+  }
 }
 
 void ViewsWindow::Minimize() {
   CEF_REQUIRE_UI_THREAD();
-  if (window_)
+  if (window_) {
     window_->Minimize();
+  }
 }
 
 void ViewsWindow::Maximize() {
   CEF_REQUIRE_UI_THREAD();
-  if (window_)
+  if (window_) {
     window_->Maximize();
+  }
 }
 
 void ViewsWindow::SetBounds(const CefRect& bounds) {
   CEF_REQUIRE_UI_THREAD();
-  if (window_)
+  if (window_) {
     window_->SetBounds(bounds);
+  }
 }
 
 void ViewsWindow::SetBrowserSize(const CefSize& size,
                                  bool has_position,
                                  const CefPoint& position) {
   CEF_REQUIRE_UI_THREAD();
-  if (browser_view_)
+  if (browser_view_) {
     browser_view_->SetSize(size);
+  }
   if (window_) {
     window_->SizeToPreferredSize();
-    if (has_position)
+    if (has_position) {
       window_->SetPosition(position);
+    }
   }
 }
 
 void ViewsWindow::Close(bool force) {
   CEF_REQUIRE_UI_THREAD();
-  if (!browser_view_)
+  if (!browser_view_) {
     return;
+  }
 
   CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
   if (browser) {
@@ -189,18 +247,21 @@
 
 void ViewsWindow::SetAddress(const std::string& url) {
   CEF_REQUIRE_UI_THREAD();
-  if (!window_ || !with_controls_)
+  if (!window_) {
     return;
+  }
 
-  CefRefPtr<CefView> view = window_->GetViewForID(ID_URL_TEXTFIELD);
-  if (view && view->AsTextfield())
-    view->AsTextfield()->SetText(url);
+  // |location_bar_| may instead be a Chrome toolbar.
+  if (location_bar_ && location_bar_->AsTextfield()) {
+    location_bar_->AsTextfield()->SetText(url);
+  }
 }
 
 void ViewsWindow::SetTitle(const std::string& title) {
   CEF_REQUIRE_UI_THREAD();
-  if (window_)
+  if (window_) {
     window_->SetTitle(title);
+  }
 }
 
 void ViewsWindow::SetFavicon(CefRefPtr<CefImage> image) {
@@ -209,17 +270,25 @@
   // Window icons should be 16 DIP in size.
   DCHECK_EQ(std::max(image->GetWidth(), image->GetHeight()), 16U);
 
-  if (window_)
+  if (window_) {
     window_->SetWindowIcon(image);
+  }
 }
 
 void ViewsWindow::SetFullscreen(bool fullscreen) {
   CEF_REQUIRE_UI_THREAD();
-  if (window_) {
-    // Hide the top controls while in full-screen mode.
-    if (with_controls_)
-      ShowTopControls(!fullscreen);
 
+  // For Chrome runtime we ignore this notification from
+  // ClientHandler::OnFullscreenModeChange(). Chrome runtime will trigger
+  // the fullscreen change internally and then call
+  // OnWindowFullscreenTransition().
+  if (MainContext::Get()->UseChromeRuntime()) {
+    return;
+  }
+
+  // For Alloy runtime we need to explicitly trigger the fullscreen change.
+  if (window_) {
+    // Results in a call to OnWindowFullscreenTransition().
     window_->SetFullscreen(fullscreen);
   }
 }
@@ -235,34 +304,41 @@
                                   bool canGoBack,
                                   bool canGoForward) {
   CEF_REQUIRE_UI_THREAD();
-  if (!window_ || !with_controls_)
+  if (!window_ || chrome_toolbar_type_ == CEF_CTT_NORMAL) {
     return;
+  }
 
-  EnableView(ID_BACK_BUTTON, canGoBack);
-  EnableView(ID_FORWARD_BUTTON, canGoForward);
-  EnableView(ID_RELOAD_BUTTON, !isLoading);
-  EnableView(ID_STOP_BUTTON, isLoading);
-  EnableView(ID_URL_TEXTFIELD, true);
+  if (with_controls_) {
+    EnableView(ID_BACK_BUTTON, canGoBack);
+    EnableView(ID_FORWARD_BUTTON, canGoForward);
+    EnableView(ID_RELOAD_BUTTON, !isLoading);
+    EnableView(ID_STOP_BUTTON, isLoading);
+  }
+  if (location_bar_) {
+    EnableView(ID_URL_TEXTFIELD, true);
+  }
 }
 
 void ViewsWindow::SetDraggableRegions(
     const std::vector<CefDraggableRegion>& regions) {
   CEF_REQUIRE_UI_THREAD();
 
-  if (!window_ || !browser_view_)
+  if (!window_ || !browser_view_) {
     return;
-
-  std::vector<CefDraggableRegion> window_regions;
+  }
 
   // Convert the regions from BrowserView to Window coordinates.
-  std::vector<CefDraggableRegion>::const_iterator it = regions.begin();
-  for (; it != regions.end(); ++it) {
-    CefDraggableRegion region = *it;
+  std::vector<CefDraggableRegion> window_regions = regions;
+  for (auto& region : window_regions) {
     CefPoint origin = CefPoint(region.bounds.x, region.bounds.y);
     browser_view_->ConvertPointToWindow(origin);
     region.bounds.x = origin.x;
     region.bounds.y = origin.y;
-    window_regions.push_back(region);
+  }
+
+  if (overlay_controls_) {
+    // Exclude all regions obscured by overlays.
+    overlay_controls_->UpdateDraggableRegions(window_regions);
   }
 
   window_->SetDraggableRegions(window_regions);
@@ -271,11 +347,16 @@
 void ViewsWindow::TakeFocus(bool next) {
   CEF_REQUIRE_UI_THREAD();
 
-  if (!window_ || !with_controls_)
+  if (!window_) {
     return;
+  }
 
-  // Give focus to the URL textfield.
-  window_->GetViewForID(ID_URL_TEXTFIELD)->RequestFocus();
+  if (chrome_toolbar_type_ == CEF_CTT_NORMAL) {
+    toolbar_->RequestFocus();
+  } else if (location_bar_) {
+    // Give focus to the location bar.
+    location_bar_->RequestFocus();
+  }
 }
 
 void ViewsWindow::OnBeforeContextMenu(CefRefPtr<CefMenuModel> model) {
@@ -308,14 +389,65 @@
       image_set.push_back(
           ImageCache::ImageInfo::Create1x(icon_path, icon_path, internal));
     } else {
-      // Get a NULL image and use the default icon.
+      // Get a nullptr image and use the default icon.
       image_set.push_back(ImageCache::ImageInfo::Empty());
     }
   }
 
   delegate_->GetImageCache()->LoadImages(
       image_set,
-      base::Bind(&ViewsWindow::OnExtensionIconsLoaded, this, extensions));
+      base::BindOnce(&ViewsWindow::OnExtensionIconsLoaded, this, extensions));
+}
+
+// static
+bool ViewsWindow::SupportsWindowRestore(WindowType type) {
+  // Only support window restore with normal windows.
+  return type == WindowType::NORMAL;
+}
+
+bool ViewsWindow::SupportsWindowRestore() const {
+  return SupportsWindowRestore(type_);
+}
+
+bool ViewsWindow::GetWindowRestorePreferences(
+    cef_show_state_t& show_state,
+    std::optional<CefRect>& dip_bounds) {
+  CEF_REQUIRE_UI_THREAD();
+  DCHECK(SupportsWindowRestore());
+  if (!window_) {
+    return false;
+  }
+
+  show_state = CEF_SHOW_STATE_NORMAL;
+  if (window_->IsMinimized()) {
+    show_state = CEF_SHOW_STATE_MINIMIZED;
+  } else if (window_->IsFullscreen()) {
+    // On MacOS, IsMaximized() will also return true for fullscreen, so check
+    // IsFullscreen() first.
+    show_state = CEF_SHOW_STATE_FULLSCREEN;
+  } else if (window_->IsMaximized()) {
+    show_state = CEF_SHOW_STATE_MAXIMIZED;
+  }
+
+  if (show_state == CEF_SHOW_STATE_NORMAL) {
+    // Use the current visible bounds.
+    dip_bounds = window_->GetBoundsInScreen();
+  } else {
+    // Use the last known visible bounds.
+    dip_bounds = last_visible_bounds_;
+  }
+
+  return true;
+}
+
+void ViewsWindow::SetTitlebarHeight(const std::optional<float>& height) {
+  CEF_REQUIRE_UI_THREAD();
+  if (height.has_value()) {
+    override_titlebar_height_ = height;
+  } else {
+    override_titlebar_height_ = default_titlebar_height_;
+  }
+  NudgeWindow();
 }
 
 CefRefPtr<CefBrowserViewDelegate> ViewsWindow::GetDelegateForPopupBrowserView(
@@ -330,11 +462,18 @@
   // knows the association between |client| and itself.
   Delegate* popup_delegate = delegate_->GetDelegateForPopup(client);
 
+  // May be nullptr when using the default popup behavior.
+  if (!popup_delegate) {
+    return nullptr;
+  }
+
   // Should not be the same RootWindowViews that owns |this|.
-  DCHECK(popup_delegate && popup_delegate != delegate_);
+  DCHECK(popup_delegate != delegate_);
 
   // Create a new ViewsWindow for the popup BrowserView.
-  return new ViewsWindow(popup_delegate, nullptr);
+  return new ViewsWindow(
+      is_devtools ? WindowType::DEVTOOLS : WindowType::NORMAL, popup_delegate,
+      nullptr);
 }
 
 bool ViewsWindow::OnPopupBrowserViewCreated(
@@ -348,8 +487,13 @@
       static_cast<ViewsWindow*>(static_cast<CefBrowserViewDelegate*>(
           popup_browser_view->GetDelegate().get()));
 
+  // May be nullptr when using the default popup behavior.
+  if (!popup_window) {
+    return false;
+  }
+
   // Should not be the same ViewsWindow as |this|.
-  DCHECK(popup_window && popup_window != this);
+  DCHECK(popup_window != this);
 
   // Associate the ViewsWindow with the new popup browser.
   popup_window->SetBrowserView(popup_browser_view);
@@ -362,16 +506,28 @@
   return true;
 }
 
+CefBrowserViewDelegate::ChromeToolbarType ViewsWindow::GetChromeToolbarType(
+    CefRefPtr<CefBrowserView> browser_view) {
+  return chrome_toolbar_type_;
+}
+
+bool ViewsWindow::UseFramelessWindowForPictureInPicture(
+    CefRefPtr<CefBrowserView> browser_view) {
+  return hide_pip_frame_;
+}
+
 void ViewsWindow::OnButtonPressed(CefRefPtr<CefButton> button) {
   CEF_REQUIRE_UI_THREAD();
   DCHECK(with_controls_);
 
-  if (!browser_view_)
+  if (!browser_view_) {
     return;
+  }
 
   CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
-  if (!browser)
+  if (!browser) {
     return;
+  }
 
   switch (button->GetID()) {
     case ID_BACK_BUTTON:
@@ -414,22 +570,50 @@
     // Create a window for the extension.
     delegate_->CreateExtensionWindow(
         extensions_[extension_idx].extension_, menu_button->GetBoundsInScreen(),
-        window_, base::Bind(&ViewsWindow::OnExtensionWindowClosed, this));
+        window_, base::BindOnce(&ViewsWindow::OnExtensionWindowClosed, this));
     return;
   }
 
-  DCHECK(with_controls_);
+  DCHECK(with_controls_ || with_overlay_controls_);
   DCHECK_EQ(ID_MENU_BUTTON, id);
 
-  menu_button->ShowMenu(button_menu_model_, screen_point,
-                        CEF_MENU_ANCHOR_TOPRIGHT);
+  const auto button_bounds = menu_button->GetBoundsInScreen();
+
+  auto point = screen_point;
+  if (with_overlay_controls_) {
+    // Align the menu correctly under the button.
+    if (CefIsRTL()) {
+      point.x += button_bounds.width - 4;
+    } else {
+      point.x -= button_bounds.width - 4;
+    }
+  }
+
+  if (use_bottom_controls_) {
+    const auto display_bounds =
+        menu_button->GetWindow()->GetDisplay()->GetWorkArea();
+    const int available_height = display_bounds.y + display_bounds.height -
+                                 button_bounds.y - button_bounds.height;
+
+    // Approximation of the menu height.
+    const int menu_height =
+        static_cast<int>(button_menu_model_->GetCount()) * button_bounds.height;
+    if (menu_height > available_height) {
+      // The menu will go upwards, so place it above the button.
+      point.y -= button_bounds.height - 8;
+    }
+  }
+
+  menu_button->ShowMenu(button_menu_model_, point,
+                        with_overlay_controls_ ? CEF_MENU_ANCHOR_TOPLEFT
+                                               : CEF_MENU_ANCHOR_TOPRIGHT);
 }
 
 void ViewsWindow::ExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
                                  int command_id,
                                  cef_event_flags_t event_flags) {
   CEF_REQUIRE_UI_THREAD();
-  DCHECK(with_controls_);
+  DCHECK(with_controls_ || with_overlay_controls_);
 
   if (command_id == ID_QUIT) {
     delegate_->OnExit();
@@ -443,7 +627,6 @@
 bool ViewsWindow::OnKeyEvent(CefRefPtr<CefTextfield> textfield,
                              const CefKeyEvent& event) {
   CEF_REQUIRE_UI_THREAD();
-  DCHECK(with_controls_);
   DCHECK_EQ(ID_URL_TEXTFIELD, textfield->GetID());
 
   // Trigger when the return key is pressed.
@@ -451,11 +634,9 @@
       event.windows_key_code == VK_RETURN) {
     CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
     if (browser) {
-      CefRefPtr<CefView> view = window_->GetViewForID(ID_URL_TEXTFIELD);
-      if (view && view->AsTextfield()) {
-        const CefString& url = view->AsTextfield()->GetText();
-        if (!url.empty())
-          browser->GetMainFrame()->LoadURL(url);
+      const CefString& url = textfield->GetText();
+      if (!url.empty()) {
+        browser->GetMainFrame()->LoadURL(url);
       }
     }
 
@@ -466,6 +647,37 @@
   return false;
 }
 
+void ViewsWindow::OnWindowFullscreenTransition(CefRefPtr<CefWindow> window,
+                                               bool is_completed) {
+#if defined(OS_MAC)
+  // On MacOS we get two asynchronous callbacks, and we want to change the UI on
+  // |is_completed=false| (e.g. when the fullscreen transition begins).
+  const bool should_change = !is_completed;
+#else
+  // On other platforms we only get a single synchronous callback with
+  // |is_completed=true|.
+  DCHECK(is_completed);
+  const bool should_change = true;
+#endif
+
+  // Hide the top controls while in fullscreen mode.
+  if (should_change && with_controls_) {
+    ShowTopControls(!window->IsFullscreen());
+  }
+
+  // With Alloy runtime we need to explicitly exit browser fullscreen when
+  // exiting window fullscreen. Chrome runtime handles this internally.
+  if (!MainContext::Get()->UseChromeRuntime() && should_change &&
+      !window->IsFullscreen()) {
+    CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
+    if (browser && browser->GetHost()->IsFullscreen()) {
+      // Will not cause a resize because the fullscreen transition has already
+      // begun.
+      browser->GetHost()->ExitFullscreen(/*will_cause_resize=*/false);
+    }
+  }
+}
+
 void ViewsWindow::OnWindowCreated(CefRefPtr<CefWindow> window) {
   CEF_REQUIRE_UI_THREAD();
   DCHECK(browser_view_);
@@ -475,39 +687,44 @@
   window_ = window;
   window_->SetID(ID_WINDOW);
 
-  with_controls_ = delegate_->WithControls();
-
   delegate_->OnViewsWindowCreated(this);
 
-  CefRect bounds = delegate_->GetWindowBounds();
-  if (bounds.IsEmpty()) {
-    // Use the default size.
-    bounds.width = 800;
-    bounds.height = 600;
-  }
-
-  if (bounds.x == 0 && bounds.y == 0) {
-    // Size the Window and center it.
-    window_->CenterWindow(CefSize(bounds.width, bounds.height));
-  } else {
-    // Set the Window bounds as specified.
-    window_->SetBounds(bounds);
+  if (type_ == WindowType::NORMAL || type_ == WindowType::DEVTOOLS) {
+    const CefRect bounds = delegate_->GetInitialBounds();
+    if (bounds.IsEmpty()) {
+      // Size the Window and center it at the default size.
+      window_->CenterWindow(CefSize(kDefaultWidth, kDefaultHeight));
+    } else if (SupportsWindowRestore()) {
+      // Remember the bounds from the previous application run in case the user
+      // does not move or resize the window during this application run.
+      last_visible_bounds_ = bounds;
+    }
   }
 
   // Set the background color for regions that are not obscured by other Views.
   views_style::ApplyTo(window_.get());
 
+  if (with_controls_ || with_overlay_controls_) {
+    // Create the MenuModel that will be displayed via the menu button.
+    CreateMenuModel();
+  }
+
   if (with_controls_) {
     // Add the BrowserView and other controls to the Window.
-    AddControls();
+    AddBrowserView();
 
     // Add keyboard accelerators to the Window.
     AddAccelerators();
+
+    // Hide the top controls while in full-screen mode.
+    if (delegate_->GetInitialShowState() == CEF_SHOW_STATE_FULLSCREEN) {
+      ShowTopControls(false);
+    }
   } else {
     // Add the BrowserView as the only child of the Window.
     window_->AddChildView(browser_view_);
 
-    if (!delegate_->WithExtension()) {
+    if (type_ != WindowType::EXTENSION) {
       // Choose a reasonable minimum window size.
       minimum_window_size_ = CefSize(100, 100);
     }
@@ -519,6 +736,13 @@
   }
 }
 
+void ViewsWindow::OnWindowClosing(CefRefPtr<CefWindow> window) {
+  CEF_REQUIRE_UI_THREAD();
+  DCHECK(window_);
+
+  delegate_->OnViewsWindowClosing(this);
+}
+
 void ViewsWindow::OnWindowDestroyed(CefRefPtr<CefWindow> window) {
   CEF_REQUIRE_UI_THREAD();
   DCHECK(window_);
@@ -527,21 +751,49 @@
 
   browser_view_ = nullptr;
   button_menu_model_ = nullptr;
-  if (top_menu_bar_) {
-    top_menu_bar_->Reset();
-    top_menu_bar_ = nullptr;
+  if (menu_bar_) {
+    menu_bar_->Reset();
+    menu_bar_ = nullptr;
   }
   extensions_panel_ = nullptr;
+  menu_button_ = nullptr;
   window_ = nullptr;
 }
 
+void ViewsWindow::OnWindowActivationChanged(CefRefPtr<CefWindow> window,
+                                            bool active) {
+  if (!active) {
+    return;
+  }
+
+  delegate_->OnViewsWindowActivated(this);
+}
+
+void ViewsWindow::OnWindowBoundsChanged(CefRefPtr<CefWindow> window,
+                                        const CefRect& new_bounds) {
+  if (SupportsWindowRestore() && !window->IsMinimized() &&
+      !window->IsMaximized() && !window->IsFullscreen()) {
+    // Track the last visible bounds for window restore purposes.
+    last_visible_bounds_ = new_bounds;
+  }
+
+#if defined(OS_MAC)
+  if (frameless_ && with_standard_buttons_ && toolbar_) {
+    auto insets = toolbar_->GetInsets();
+    insets.left = window->IsFullscreen() ? 0 : kWindowButtonsWidth;
+    toolbar_->SetInsets(insets);
+  }
+#endif
+}
+
 bool ViewsWindow::CanClose(CefRefPtr<CefWindow> window) {
   CEF_REQUIRE_UI_THREAD();
 
   // Allow the window to close if the browser says it's OK.
   CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
-  if (browser)
+  if (browser) {
     return browser->GetHost()->TryCloseBrowser();
+  }
   return true;
 }
 
@@ -551,24 +803,73 @@
   CEF_REQUIRE_UI_THREAD();
   CefRefPtr<CefWindow> parent_window = delegate_->GetParentWindow();
   if (parent_window) {
-    // Should be an extension window, in which case we want it to behave as a
-    // menu and allow activation.
-    DCHECK(delegate_->WithExtension());
-    *is_menu = true;
-    *can_activate_menu = true;
+    // Extension windows behave as a menu and allow activation.
+    if (type_ == WindowType::EXTENSION) {
+      *is_menu = true;
+      *can_activate_menu = true;
+    }
   }
   return parent_window;
 }
 
+bool ViewsWindow::IsWindowModalDialog(CefRefPtr<CefWindow> window) {
+  CEF_REQUIRE_UI_THREAD();
+  DCHECK(delegate_->GetParentWindow());
+  return use_window_modal_dialog_;
+}
+
+CefRect ViewsWindow::GetInitialBounds(CefRefPtr<CefWindow> window) {
+  CEF_REQUIRE_UI_THREAD();
+  const CefRect bounds = delegate_->GetInitialBounds();
+  if (frameless_ && bounds.IsEmpty()) {
+    // Need to provide a size for frameless windows that will be centered.
+    return CefRect(0, 0, kDefaultWidth, kDefaultHeight);
+  }
+  return bounds;
+}
+
+cef_show_state_t ViewsWindow::GetInitialShowState(CefRefPtr<CefWindow> window) {
+  CEF_REQUIRE_UI_THREAD();
+  return delegate_->GetInitialShowState();
+}
+
 bool ViewsWindow::IsFrameless(CefRefPtr<CefWindow> window) {
   CEF_REQUIRE_UI_THREAD();
   return frameless_;
 }
 
+bool ViewsWindow::WithStandardWindowButtons(CefRefPtr<CefWindow> window) {
+  CEF_REQUIRE_UI_THREAD();
+  return with_standard_buttons_;
+}
+
+bool ViewsWindow::GetTitlebarHeight(CefRefPtr<CefWindow> window,
+                                    float* titlebar_height) {
+  CEF_REQUIRE_UI_THREAD();
+#if defined(OS_MAC)
+  if (override_titlebar_height_.has_value()) {
+    *titlebar_height = override_titlebar_height_.value();
+    return true;
+  }
+#endif
+
+  return false;
+}
+
 bool ViewsWindow::CanResize(CefRefPtr<CefWindow> window) {
   CEF_REQUIRE_UI_THREAD();
-  // Don't allow windows hosting extensions to resize.
-  return !delegate_->WithExtension();
+  // Only allow resize of normal and DevTools windows.
+  return type_ == WindowType::NORMAL || type_ == WindowType::DEVTOOLS;
+}
+
+bool ViewsWindow::CanMaximize(CefRefPtr<CefWindow> window) {
+  CEF_REQUIRE_UI_THREAD();
+  return CanResize(window);
+}
+
+bool ViewsWindow::CanMinimize(CefRefPtr<CefWindow> window) {
+  CEF_REQUIRE_UI_THREAD();
+  return CanResize(window);
 }
 
 bool ViewsWindow::OnAccelerator(CefRefPtr<CefWindow> window, int command_id) {
@@ -586,18 +887,20 @@
                              const CefKeyEvent& event) {
   CEF_REQUIRE_UI_THREAD();
 
-  if (!window_)
+  if (!window_) {
     return false;
+  }
 
-  if (delegate_->WithExtension() && event.type == KEYEVENT_RAWKEYDOWN &&
+  if (type_ == WindowType::EXTENSION && event.type == KEYEVENT_RAWKEYDOWN &&
       event.windows_key_code == VK_ESCAPE) {
     // Close the extension window on escape.
     Close(false);
     return true;
   }
 
-  if (!with_controls_)
+  if (!with_controls_) {
     return false;
+  }
 
   if (event.type == KEYEVENT_RAWKEYDOWN && event.windows_key_code == VK_MENU) {
     // ALT key is pressed.
@@ -615,17 +918,31 @@
     return true;
   }
 
-  if (menu_has_focus_ && top_menu_bar_)
-    return top_menu_bar_->OnKeyEvent(event);
+  if (menu_has_focus_ && menu_bar_) {
+    return menu_bar_->OnKeyEvent(event);
+  }
 
   return false;
 }
 
+CefSize ViewsWindow::GetPreferredSize(CefRefPtr<CefView> view) {
+  CEF_REQUIRE_UI_THREAD();
+
+  if (view->GetID() == ID_WINDOW && type_ == WindowType::DIALOG) {
+    // Preferred size for a browser modal dialog. The dialog will be shrunk to
+    // fit inside the parent browser view if necessary.
+    return CefSize(kDefaultWidth, kDefaultHeight);
+  }
+
+  return CefSize();
+}
+
 CefSize ViewsWindow::GetMinimumSize(CefRefPtr<CefView> view) {
   CEF_REQUIRE_UI_THREAD();
 
-  if (view->GetID() == ID_WINDOW)
+  if (view->GetID() == ID_WINDOW) {
     return minimum_window_size_;
+  }
 
   return CefSize();
 }
@@ -637,58 +954,147 @@
 
   // Keep track of the non-menu view that was last focused.
   if (last_focused_view_ != view_id &&
-      (!top_menu_bar_ || !top_menu_bar_->HasMenuId(view_id))) {
+      (!menu_bar_ || !menu_bar_->HasMenuId(view_id))) {
     last_focused_view_ = view_id;
   }
 
   // When focus leaves the menu buttons make them unfocusable.
   if (menu_has_focus_) {
-    if (top_menu_bar_) {
-      if (!top_menu_bar_->HasMenuId(view_id))
+    if (menu_bar_) {
+      if (!menu_bar_->HasMenuId(view_id)) {
         SetMenuFocusable(false);
+      }
     } else if (view_id != ID_MENU_BUTTON) {
       SetMenuFocusable(false);
     }
   }
-
-  if (view_id == ID_BROWSER_VIEW)
-    delegate_->OnViewsWindowActivated(this);
 }
 
 void ViewsWindow::OnBlur(CefRefPtr<CefView> view) {
   CEF_REQUIRE_UI_THREAD();
 
   const int view_id = view->GetID();
-  if (view_id == ID_BROWSER_VIEW && delegate_->WithExtension()) {
+  if (view_id == ID_BROWSER_VIEW && type_ == WindowType::EXTENSION) {
     // Close windows hosting extensions when the browser loses focus.
     Close(false);
   }
 }
 
+void ViewsWindow::OnWindowChanged(CefRefPtr<CefView> view, bool added) {
+  const int view_id = view->GetID();
+  if (view_id != ID_BROWSER_VIEW) {
+    return;
+  }
+
+  if (added) {
+    if (with_controls_) {
+      AddControls();
+    }
+
+    if (with_overlay_controls_) {
+      // Add window buttons if we don't have standard ones
+      const bool with_window_buttons = !with_standard_buttons_;
+      overlay_controls_ =
+          new ViewsOverlayControls(with_window_buttons, use_bottom_controls_);
+      overlay_controls_->Initialize(window_, CreateMenuButton(),
+                                    CreateLocationBar(),
+                                    chrome_toolbar_type_ != CEF_CTT_NONE);
+    }
+  } else {
+    // Remove any controls that may include the Chrome toolbar before removing
+    // the BrowserView.
+    if (overlay_controls_) {
+      overlay_controls_->Destroy();
+      overlay_controls_ = nullptr;
+      location_bar_ = nullptr;
+    } else if (use_bottom_controls_) {
+      if (toolbar_) {
+        window_->RemoveChildView(toolbar_);
+        toolbar_ = nullptr;
+        location_bar_ = nullptr;
+      }
+    }
+  }
+}
+
+void ViewsWindow::OnLayoutChanged(CefRefPtr<CefView> view,
+                                  const CefRect& new_bounds) {
+  const int view_id = view->GetID();
+  if (view_id != ID_BROWSER_VIEW) {
+    return;
+  }
+
+  if (overlay_controls_) {
+    overlay_controls_->UpdateControls();
+  }
+}
+
 void ViewsWindow::MenuBarExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
                                         int command_id,
                                         cef_event_flags_t event_flags) {
   ExecuteCommand(menu_model, command_id, event_flags);
 }
 
-ViewsWindow::ViewsWindow(Delegate* delegate,
+ViewsWindow::ViewsWindow(WindowType type,
+                         Delegate* delegate,
                          CefRefPtr<CefBrowserView> browser_view)
-    : delegate_(delegate),
-      with_controls_(false),
+    : type_(type),
+      delegate_(delegate),
       menu_has_focus_(false),
       last_focused_view_(false) {
   DCHECK(delegate_);
-  if (browser_view)
+  if (browser_view) {
     SetBrowserView(browser_view);
+  }
 
   CefRefPtr<CefCommandLine> command_line =
       CefCommandLine::GetGlobalCommandLine();
-  frameless_ = command_line->HasSwitch(switches::kHideFrame) ||
-               delegate_->WithExtension();
 
-  if (!command_line->HasSwitch(switches::kHideTopMenu)) {
-    top_menu_bar_ = new ViewsMenuBar(this, ID_TOP_MENU_FIRST);
+  const bool is_normal_type = type_ == WindowType::NORMAL;
+
+  with_controls_ = is_normal_type && delegate_->WithControls();
+
+  const bool hide_frame = command_line->HasSwitch(switches::kHideFrame);
+  const bool hide_overlays =
+      !is_normal_type || command_line->HasSwitch(switches::kHideOverlays);
+  const bool hide_toolbar = hide_overlays && !with_controls_;
+  const bool show_window_buttons =
+      command_line->HasSwitch(switches::kShowWindowButtons);
+
+  // Without a window frame.
+  frameless_ = hide_frame || type_ == WindowType::EXTENSION;
+
+  // With an overlay that mimics window controls.
+  with_overlay_controls_ = hide_frame && !hide_overlays && !with_controls_;
+
+  // If window has frame or flag passed explicitly
+  with_standard_buttons_ = !frameless_ || show_window_buttons;
+
+#if defined(OS_MAC)
+  if (frameless_ && with_standard_buttons_) {
+    default_titlebar_height_ = kTitleBarHeight;
+    override_titlebar_height_ = kTitleBarHeight;
   }
+#endif
+
+  const std::string& toolbar_type =
+      command_line->GetSwitchValue(switches::kShowChromeToolbar);
+  chrome_toolbar_type_ = CalculateChromeToolbarType(toolbar_type, hide_toolbar,
+                                                    with_overlay_controls_);
+
+  use_bottom_controls_ = command_line->HasSwitch(switches::kUseBottomControls);
+
+#if !defined(OS_MAC)
+  // On Mac we don't show a top menu on the window. The options are available in
+  // the app menu instead.
+  if (!command_line->HasSwitch(switches::kHideTopMenu)) {
+    menu_bar_ = new ViewsMenuBar(this, ID_TOP_MENU_FIRST, use_bottom_controls_);
+  }
+#endif
+
+  use_window_modal_dialog_ =
+      command_line->HasSwitch(switches::kUseWindowModalDialog);
+  hide_pip_frame_ = command_line->HasSwitch(switches::kHidePipFrame);
 }
 
 void ViewsWindow::SetBrowserView(CefRefPtr<CefBrowserView> browser_view) {
@@ -709,10 +1115,10 @@
   AddTestMenuItems(test_menu);
   AddFileMenuItems(button_menu_model_);
 
-  if (top_menu_bar_) {
+  if (menu_bar_) {
     // Add the menus to the top menu bar.
-    AddFileMenuItems(top_menu_bar_->CreateMenuModel("&File", nullptr));
-    AddTestMenuItems(top_menu_bar_->CreateMenuModel("&Tests", nullptr));
+    AddFileMenuItems(menu_bar_->CreateMenuModel("&File", nullptr));
+    AddTestMenuItems(menu_bar_->CreateMenuModel("&Tests", nullptr));
   }
 }
 
@@ -722,69 +1128,49 @@
   CefRefPtr<CefLabelButton> button =
       CefLabelButton::CreateLabelButton(this, label);
   button->SetID(id);
+  views_style::ApplyTo(button.get());
+  button->SetInkDropEnabled(true);
   button->SetEnabled(false);    // Disabled by default.
   button->SetFocusable(false);  // Don't give focus to the button.
 
   return button;
 }
 
-void ViewsWindow::AddControls() {
-  // Create the MenuModel that will be displayed via the menu button.
-  CreateMenuModel();
-
-  CefRefPtr<CefPanel> top_menu_panel;
-  if (top_menu_bar_)
-    top_menu_panel = top_menu_bar_->GetMenuPanel();
-
-  // Create the browse buttons.
-  LabelButtons browse_buttons;
-  browse_buttons.push_back(CreateBrowseButton("Back", ID_BACK_BUTTON));
-  browse_buttons.push_back(CreateBrowseButton("Forward", ID_FORWARD_BUTTON));
-  browse_buttons.push_back(CreateBrowseButton("Reload", ID_RELOAD_BUTTON));
-  browse_buttons.push_back(CreateBrowseButton("Stop", ID_STOP_BUTTON));
-
-  // Create the URL textfield.
-  CefRefPtr<CefTextfield> url_textfield = CefTextfield::CreateTextfield(this);
-  url_textfield->SetID(ID_URL_TEXTFIELD);
-  url_textfield->SetEnabled(false);  // Disabled by default.
-  views_style::ApplyTo(url_textfield);
-
+CefRefPtr<CefMenuButton> ViewsWindow::CreateMenuButton() {
   // Create the menu button.
-  CefRefPtr<CefMenuButton> menu_button =
-      CefMenuButton::CreateMenuButton(this, CefString());
-  menu_button->SetID(ID_MENU_BUTTON);
-  menu_button->SetImage(
+  DCHECK(!menu_button_);
+  menu_button_ = CefMenuButton::CreateMenuButton(this, CefString());
+  menu_button_->SetID(ID_MENU_BUTTON);
+  menu_button_->SetImage(
       CEF_BUTTON_STATE_NORMAL,
       delegate_->GetImageCache()->GetCachedImage("menu_icon"));
-  views_style::ApplyTo(menu_button.get());
-  menu_button->SetInkDropEnabled(true);
+  views_style::ApplyTo(menu_button_.get());
+  menu_button_->SetInkDropEnabled(true);
   // Override the default minimum size.
-  menu_button->SetMinimumSize(CefSize(0, 0));
+  menu_button_->SetMinimumSize(CefSize(0, 0));
+  return menu_button_;
+}
 
-  // Create the top panel.
-  CefRefPtr<CefPanel> top_panel = CefPanel::CreatePanel(nullptr);
+CefRefPtr<CefView> ViewsWindow::CreateLocationBar() {
+  DCHECK(!location_bar_);
+  if (chrome_toolbar_type_ == CEF_CTT_LOCATION) {
+    // Chrome will provide a minimal location bar.
+    location_bar_ = browser_view_->GetChromeToolbar();
+    DCHECK(location_bar_);
+    views_style::ApplyBackgroundTo(location_bar_);
+  }
+  if (!location_bar_) {
+    // Create the URL textfield.
+    CefRefPtr<CefTextfield> url_textfield = CefTextfield::CreateTextfield(this);
+    url_textfield->SetID(ID_URL_TEXTFIELD);
+    url_textfield->SetEnabled(false);  // Disabled by default.
+    views_style::ApplyTo(url_textfield);
+    location_bar_ = url_textfield;
+  }
+  return location_bar_;
+}
 
-  // Use a horizontal box layout for |top_panel|.
-  CefBoxLayoutSettings top_panel_layout_settings;
-  top_panel_layout_settings.horizontal = true;
-  CefRefPtr<CefBoxLayout> top_panel_layout =
-      top_panel->SetToBoxLayout(top_panel_layout_settings);
-
-  // Add the buttons and URL textfield to |top_panel|.
-  for (size_t i = 0U; i < browse_buttons.size(); ++i)
-    top_panel->AddChildView(browse_buttons[i]);
-  top_panel->AddChildView(url_textfield);
-
-  UpdateExtensionControls();
-  DCHECK(extensions_panel_);
-  top_panel->AddChildView(extensions_panel_);
-
-  top_panel->AddChildView(menu_button);
-  views_style::ApplyTo(top_panel);
-
-  // Allow |url_textfield| to grow and fill any remaining space.
-  top_panel_layout->SetFlexForView(url_textfield, 1);
-
+void ViewsWindow::AddBrowserView() {
   // Use a vertical box layout for |window|.
   CefBoxLayoutSettings window_layout_settings;
   window_layout_settings.horizontal = false;
@@ -792,50 +1178,136 @@
   CefRefPtr<CefBoxLayout> window_layout =
       window_->SetToBoxLayout(window_layout_settings);
 
-  // Add the top panel and browser view to |window|.
-  if (top_menu_panel)
-    window_->AddChildView(top_menu_panel);
-  window_->AddChildView(top_panel);
   window_->AddChildView(browser_view_);
 
   // Allow |browser_view_| to grow and fill any remaining space.
   window_layout->SetFlexForView(browser_view_, 1);
 
+  // Remaining setup will be performed in OnWindowChanged after the BrowserView
+  // is added to the CefWindow. This is necessary because Chrome toolbars are
+  // only available after the BrowserView is added.
+}
+
+void ViewsWindow::AddControls() {
+  // Build the remainder of the UI now that the BrowserView has been added to
+  // the CefWindow. This is a requirement to use Chrome toolbars.
+
+  CefRefPtr<CefPanel> menu_panel;
+  if (menu_bar_) {
+    menu_panel = menu_bar_->GetMenuPanel();
+  }
+
+  LabelButtons browse_buttons;
+
+  if (chrome_toolbar_type_ == CEF_CTT_NORMAL) {
+    // Chrome will provide a normal toolbar with location, menu, etc.
+    toolbar_ = browser_view_->GetChromeToolbar();
+    DCHECK(toolbar_);
+  }
+
+  if (!toolbar_) {
+    // Create the browse buttons.
+    browse_buttons.push_back(CreateBrowseButton("Back", ID_BACK_BUTTON));
+    browse_buttons.push_back(CreateBrowseButton("Forward", ID_FORWARD_BUTTON));
+    browse_buttons.push_back(CreateBrowseButton("Reload", ID_RELOAD_BUTTON));
+    browse_buttons.push_back(CreateBrowseButton("Stop", ID_STOP_BUTTON));
+
+    CreateLocationBar();
+    CreateMenuButton();
+
+    // Create the toolbar panel.
+    CefRefPtr<CefPanel> panel = CefPanel::CreatePanel(nullptr);
+
+    // Use a horizontal box layout for |panel|.
+    CefBoxLayoutSettings panel_layout_settings;
+    panel_layout_settings.horizontal = true;
+    CefRefPtr<CefBoxLayout> panel_layout =
+        panel->SetToBoxLayout(panel_layout_settings);
+
+    // Add the buttons and URL textfield to |panel|.
+    for (auto& browse_button : browse_buttons) {
+      panel->AddChildView(browse_button);
+    }
+    panel->AddChildView(location_bar_);
+
+    UpdateExtensionControls();
+    DCHECK(extensions_panel_);
+    panel->AddChildView(extensions_panel_);
+
+    panel->AddChildView(menu_button_);
+    views_style::ApplyTo(panel);
+
+    // Allow |location| to grow and fill any remaining space.
+    panel_layout->SetFlexForView(location_bar_, 1);
+
+    toolbar_ = panel;
+  }
+
+#if defined(OS_MAC)
+  if (frameless_ && with_standard_buttons_) {
+    auto insets = toolbar_->GetInsets();
+    insets.left = kWindowButtonsWidth;
+    toolbar_->SetInsets(insets);
+  }
+#endif
+
+  if (use_bottom_controls_) {
+    // Add the panel at the bottom of |window|.
+    window_->AddChildView(toolbar_);
+    if (menu_panel) {
+      window_->AddChildView(menu_panel);
+    }
+  } else {
+    // Add the panel at the top of |window|.
+    int index = 0;
+    if (menu_panel) {
+      window_->AddChildViewAt(menu_panel, index++);
+    }
+    window_->AddChildViewAt(toolbar_, index);
+  }
+
   // Lay out |window| so we can get the default button sizes.
   window_->Layout();
 
-  // Make all browse buttons the same size.
-  MakeButtonsSameSize(browse_buttons);
+  int min_width = 200;
+  if (!browse_buttons.empty()) {
+    // Make all browse buttons the same size.
+    MakeButtonsSameSize(browse_buttons);
 
-  // Lay out |window| again with the new button sizes.
-  window_->Layout();
+    // Lay out |window| again with the new button sizes.
+    window_->Layout();
 
-  // Minimum window width is the size of all buttons plus some extra.
-  const int min_width = browse_buttons[0]->GetBounds().width * 4 +
-                        menu_button->GetBounds().width + 100;
-  // Minimum window height is the hight of the top toolbar plus some extra.
-  int min_height = top_panel->GetBounds().height + 100;
-  if (top_menu_panel)
-    min_height += top_menu_panel->GetBounds().height;
+    const int buttons_number = static_cast<int>(browse_buttons.size());
+
+    // Minimum window width is the size of all buttons plus some extra.
+    min_width = browse_buttons[0]->GetBounds().width * buttons_number +
+                menu_button_->GetBounds().width + 100;
+  }
+
+  // Minimum window height is the hight of the toolbar plus some extra.
+  int min_height = toolbar_->GetBounds().height + 100;
+  if (menu_panel) {
+    min_height += menu_panel->GetBounds().height;
+  }
 
   minimum_window_size_ = CefSize(min_width, min_height);
 }
 
 void ViewsWindow::AddAccelerators() {
-  // Trigger accelerators without first forwarding to web content.
-  browser_view_->SetPreferAccelerators(true);
-
   // Specify the accelerators to handle. OnAccelerator will be called when the
   // accelerator is triggered.
-  window_->SetAccelerator(ID_QUIT, 'X', false, false, true);
+  window_->SetAccelerator(ID_QUIT, 'X', /*shift_pressed=*/false,
+                          /*ctrl_pressed=*/false, /*alt_pressed=*/true,
+                          /*high_priority=*/true);
 }
 
 void ViewsWindow::SetMenuFocusable(bool focusable) {
-  if (!window_ || !with_controls_)
+  if (!window_ || !with_controls_) {
     return;
+  }
 
-  if (top_menu_bar_) {
-    top_menu_bar_->SetMenuFocusable(focusable);
+  if (menu_bar_) {
+    menu_bar_->SetMenuFocusable(focusable);
   } else {
     window_->GetViewForID(ID_MENU_BUTTON)->SetFocusable(focusable);
 
@@ -849,40 +1321,45 @@
 }
 
 void ViewsWindow::EnableView(int id, bool enable) {
-  if (!window_)
+  if (!window_) {
     return;
-  CefRefPtr<CefView> view = window_->GetViewForID(id);
-  if (view)
+  }
+  // Special handling for |location_bar_| which may be an overlay (e.g. not a
+  // child of this view).
+  CefRefPtr<CefView> view =
+      id == ID_URL_TEXTFIELD ? location_bar_ : window_->GetViewForID(id);
+  if (view) {
     view->SetEnabled(enable);
+  }
 }
 
 void ViewsWindow::ShowTopControls(bool show) {
-  if (!window_ || !with_controls_)
+  if (!window_ || !with_controls_) {
     return;
+  }
 
-  // Change the visibility of the panel that contains the buttons.
-  CefRefPtr<CefView> parent_view =
-      window_->GetViewForID(ID_BACK_BUTTON)->GetParentView();
-  if (parent_view->IsVisible() != show) {
-    parent_view->SetVisible(show);
-    parent_view->InvalidateLayout();
+  // Change the visibility of the toolbar.
+  if (toolbar_->IsVisible() != show) {
+    toolbar_->SetVisible(show);
+    toolbar_->InvalidateLayout();
   }
 }
 
 void ViewsWindow::UpdateExtensionControls() {
   CEF_REQUIRE_UI_THREAD();
 
-  if (!window_ || !with_controls_)
+  if (!window_ || !with_controls_) {
     return;
+  }
 
   if (!extensions_panel_) {
     extensions_panel_ = CefPanel::CreatePanel(nullptr);
 
-    // Use a horizontal box layout for |top_panel|.
-    CefBoxLayoutSettings top_panel_layout_settings;
-    top_panel_layout_settings.horizontal = true;
-    CefRefPtr<CefBoxLayout> top_panel_layout =
-        extensions_panel_->SetToBoxLayout(top_panel_layout_settings);
+    // Use a horizontal box layout for |panel|.
+    CefBoxLayoutSettings panel_layout_settings;
+    panel_layout_settings.horizontal = true;
+    CefRefPtr<CefBoxLayout> panel_layout =
+        extensions_panel_->SetToBoxLayout(panel_layout_settings);
   } else {
     extensions_panel_->RemoveAllChildViews();
   }
@@ -908,16 +1385,17 @@
   }
 
   CefRefPtr<CefView> parent_view = extensions_panel_->GetParentView();
-  if (parent_view)
+  if (parent_view) {
     parent_view->InvalidateLayout();
+  }
 }
 
 void ViewsWindow::OnExtensionIconsLoaded(const ExtensionSet& extensions,
                                          const ImageCache::ImageSet& images) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&ViewsWindow::OnExtensionIconsLoaded, this,
-                                   extensions, images));
+    CefPostTask(TID_UI, base::BindOnce(&ViewsWindow::OnExtensionIconsLoaded,
+                                       this, extensions, images));
     return;
   }
 
@@ -929,8 +1407,9 @@
   ImageCache::ImageSet::const_iterator it2 = images.begin();
   for (; it1 != extensions.end() && it2 != images.end(); ++it1, ++it2) {
     CefRefPtr<CefImage> icon = *it2;
-    if (!icon)
+    if (!icon) {
       icon = delegate_->GetImageCache()->GetCachedImage(kDefaultExtensionIcon);
+    }
     extensions_.push_back(ExtensionInfo(*it1, icon));
   }
 
@@ -941,7 +1420,7 @@
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute this method on the UI thread.
     CefPostTask(TID_UI,
-                base::Bind(&ViewsWindow::OnExtensionWindowClosed, this));
+                base::BindOnce(&ViewsWindow::OnExtensionWindowClosed, this));
     return;
   }
 
@@ -949,4 +1428,10 @@
   extension_button_pressed_lock_ = nullptr;
 }
 
+#if !defined(OS_MAC)
+void ViewsWindow::NudgeWindow() {
+  NOTIMPLEMENTED();
+}
+#endif
+
 }  // namespace client
diff --git a/src/tests/cefclient/browser/views_window.h b/src/tests/cefclient/browser/views_window.h
index 62739ac..628a091 100644
--- a/src/tests/cefclient/browser/views_window.h
+++ b/src/tests/cefclient/browser/views_window.h
@@ -6,6 +6,7 @@
 #define CEF_TESTS_CEFCLIENT_BROWSER_VIEWS_WINDOW_H_
 #pragma once
 
+#include <optional>
 #include <set>
 #include <string>
 #include <vector>
@@ -18,12 +19,15 @@
 #include "include/views/cef_label_button.h"
 #include "include/views/cef_menu_button.h"
 #include "include/views/cef_menu_button_delegate.h"
+#include "include/views/cef_overlay_controller.h"
 #include "include/views/cef_textfield.h"
 #include "include/views/cef_textfield_delegate.h"
 #include "include/views/cef_window.h"
 #include "include/views/cef_window_delegate.h"
 #include "tests/cefclient/browser/image_cache.h"
+#include "tests/cefclient/browser/root_window.h"
 #include "tests/cefclient/browser/views_menu_bar.h"
+#include "tests/cefclient/browser/views_overlay_controls.h"
 
 namespace client {
 
@@ -45,9 +49,6 @@
     // Return true if the window should show controls.
     virtual bool WithControls() = 0;
 
-    // Return true if the window is hosting an extension.
-    virtual bool WithExtension() = 0;
-
     // Return true if the window should be created initially hidden.
     virtual bool InitiallyHidden() = 0;
 
@@ -55,7 +56,10 @@
     virtual CefRefPtr<CefWindow> GetParentWindow() = 0;
 
     // Return the initial window bounds.
-    virtual CefRect GetWindowBounds() = 0;
+    virtual CefRect GetInitialBounds() = 0;
+
+    // Return the initial window show state.
+    virtual cef_show_state_t GetInitialShowState() = 0;
 
     // Returns the ImageCache.
     virtual scoped_refptr<ImageCache> GetImageCache() = 0;
@@ -63,6 +67,9 @@
     // Called when the ViewsWindow is created.
     virtual void OnViewsWindowCreated(CefRefPtr<ViewsWindow> window) = 0;
 
+    // Called when the ViewsWindow is closing.
+    virtual void OnViewsWindowClosing(CefRefPtr<ViewsWindow> window) = 0;
+
     // Called when the ViewsWindow is destroyed. All references to |window|
     // should be released in this callback.
     virtual void OnViewsWindowDestroyed(CefRefPtr<ViewsWindow> window) = 0;
@@ -78,7 +85,7 @@
     virtual void CreateExtensionWindow(CefRefPtr<CefExtension> extension,
                                        const CefRect& source_bounds,
                                        CefRefPtr<CefWindow> parent_window,
-                                       const base::Closure& close_callback) = 0;
+                                       base::OnceClosure close_callback) = 0;
 
     // Called to execute a test. See resource.h for |test_id| values.
     virtual void OnTest(int test_id) = 0;
@@ -93,6 +100,7 @@
   // Create a new top-level ViewsWindow hosting a browser with the specified
   // configuration.
   static CefRefPtr<ViewsWindow> Create(
+      WindowType type,
       Delegate* delegate,
       CefRefPtr<CefClient> client,
       const CefString& url,
@@ -119,61 +127,93 @@
   void OnBeforeContextMenu(CefRefPtr<CefMenuModel> model);
   void OnExtensionsChanged(const ExtensionSet& extensions);
 
+  static bool SupportsWindowRestore(WindowType type);
+  bool SupportsWindowRestore() const;
+  bool GetWindowRestorePreferences(cef_show_state_t& show_state,
+                                   std::optional<CefRect>& dip_bounds);
+  void SetTitlebarHeight(const std::optional<float>& height);
+
   // CefBrowserViewDelegate methods:
   CefRefPtr<CefBrowserViewDelegate> GetDelegateForPopupBrowserView(
       CefRefPtr<CefBrowserView> browser_view,
       const CefBrowserSettings& settings,
       CefRefPtr<CefClient> client,
-      bool is_devtools) OVERRIDE;
+      bool is_devtools) override;
   bool OnPopupBrowserViewCreated(CefRefPtr<CefBrowserView> browser_view,
                                  CefRefPtr<CefBrowserView> popup_browser_view,
-                                 bool is_devtools) OVERRIDE;
+                                 bool is_devtools) override;
+  ChromeToolbarType GetChromeToolbarType(
+      CefRefPtr<CefBrowserView> browser_view) override;
+  bool UseFramelessWindowForPictureInPicture(
+      CefRefPtr<CefBrowserView> browser_view) override;
 
   // CefButtonDelegate methods:
-  void OnButtonPressed(CefRefPtr<CefButton> button) OVERRIDE;
+  void OnButtonPressed(CefRefPtr<CefButton> button) override;
 
   // CefMenuButtonDelegate methods:
   void OnMenuButtonPressed(
       CefRefPtr<CefMenuButton> menu_button,
       const CefPoint& screen_point,
-      CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock) OVERRIDE;
+      CefRefPtr<CefMenuButtonPressedLock> button_pressed_lock) override;
 
   // CefMenuModelDelegate methods:
   void ExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
                       int command_id,
-                      cef_event_flags_t event_flags) OVERRIDE;
+                      cef_event_flags_t event_flags) override;
 
   // CefTextfieldDelegate methods:
   bool OnKeyEvent(CefRefPtr<CefTextfield> textfield,
-                  const CefKeyEvent& event) OVERRIDE;
+                  const CefKeyEvent& event) override;
 
   // CefWindowDelegate methods:
-  void OnWindowCreated(CefRefPtr<CefWindow> window) OVERRIDE;
-  void OnWindowDestroyed(CefRefPtr<CefWindow> window) OVERRIDE;
+  void OnWindowCreated(CefRefPtr<CefWindow> window) override;
+  void OnWindowClosing(CefRefPtr<CefWindow> window) override;
+  void OnWindowDestroyed(CefRefPtr<CefWindow> window) override;
+  void OnWindowActivationChanged(CefRefPtr<CefWindow> window,
+                                 bool active) override;
+  void OnWindowBoundsChanged(CefRefPtr<CefWindow> window,
+                             const CefRect& new_bounds) override;
   CefRefPtr<CefWindow> GetParentWindow(CefRefPtr<CefWindow> window,
                                        bool* is_menu,
-                                       bool* can_activate_menu) OVERRIDE;
-  bool IsFrameless(CefRefPtr<CefWindow> window) OVERRIDE;
-  bool CanResize(CefRefPtr<CefWindow> window) OVERRIDE;
-  bool CanClose(CefRefPtr<CefWindow> window) OVERRIDE;
-  bool OnAccelerator(CefRefPtr<CefWindow> window, int command_id) OVERRIDE;
+                                       bool* can_activate_menu) override;
+  bool IsWindowModalDialog(CefRefPtr<CefWindow> window) override;
+  CefRect GetInitialBounds(CefRefPtr<CefWindow> window) override;
+  cef_show_state_t GetInitialShowState(CefRefPtr<CefWindow> window) override;
+  bool IsFrameless(CefRefPtr<CefWindow> window) override;
+  bool WithStandardWindowButtons(CefRefPtr<CefWindow> window) override;
+  bool GetTitlebarHeight(CefRefPtr<CefWindow> window,
+                         float* titlebar_height) override;
+  bool CanResize(CefRefPtr<CefWindow> window) override;
+  bool CanMaximize(CefRefPtr<CefWindow> window) override;
+  bool CanMinimize(CefRefPtr<CefWindow> window) override;
+  bool CanClose(CefRefPtr<CefWindow> window) override;
+  bool OnAccelerator(CefRefPtr<CefWindow> window, int command_id) override;
   bool OnKeyEvent(CefRefPtr<CefWindow> window,
-                  const CefKeyEvent& event) OVERRIDE;
+                  const CefKeyEvent& event) override;
+  void OnWindowFullscreenTransition(CefRefPtr<CefWindow> window,
+                                    bool is_completed) override;
 
   // CefViewDelegate methods:
-  CefSize GetMinimumSize(CefRefPtr<CefView> view) OVERRIDE;
-  void OnFocus(CefRefPtr<CefView> view) OVERRIDE;
-  void OnBlur(CefRefPtr<CefView> view) OVERRIDE;
+  CefSize GetPreferredSize(CefRefPtr<CefView> view) override;
+  CefSize GetMinimumSize(CefRefPtr<CefView> view) override;
+  void OnFocus(CefRefPtr<CefView> view) override;
+  void OnBlur(CefRefPtr<CefView> view) override;
+  void OnWindowChanged(CefRefPtr<CefView> view, bool added) override;
+  void OnLayoutChanged(CefRefPtr<CefView> view,
+                       const CefRect& new_bounds) override;
 
   // ViewsMenuBar::Delegate methods:
   void MenuBarExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
                              int command_id,
-                             cef_event_flags_t event_flags) OVERRIDE;
+                             cef_event_flags_t event_flags) override;
 
  private:
   // |delegate| is guaranteed to outlive this object.
-  // |browser_view| may be NULL, in which case SetBrowserView() will be called.
-  ViewsWindow(Delegate* delegate, CefRefPtr<CefBrowserView> browser_view);
+  // |browser_view| may be nullptr, in which case SetBrowserView() will be
+  // called.
+  ViewsWindow(WindowType type,
+              Delegate* delegate,
+              CefRefPtr<CefBrowserView> browser_view);
 
   void SetBrowserView(CefRefPtr<CefBrowserView> browser_view);
 
@@ -181,8 +221,13 @@
   void CreateMenuModel();
   CefRefPtr<CefLabelButton> CreateBrowseButton(const std::string& label,
                                                int id);
+  CefRefPtr<CefMenuButton> CreateMenuButton();
+  CefRefPtr<CefView> CreateLocationBar();
 
-  // Add controls to the Window.
+  // Add the BrowserView to the Window.
+  void AddBrowserView();
+
+  // Add other controls to the Window.
   void AddControls();
 
   // Add keyboard accelerators to the Window.
@@ -204,19 +249,37 @@
                               const ImageCache::ImageSet& images);
   void OnExtensionWindowClosed();
 
+  void NudgeWindow();
+
+  const WindowType type_;
   Delegate* delegate_;  // Not owned by this object.
   CefRefPtr<CefBrowserView> browser_view_;
   bool frameless_;
   bool with_controls_;
+  bool with_overlay_controls_;
+  bool with_standard_buttons_;
+  ChromeToolbarType chrome_toolbar_type_;
+  bool use_window_modal_dialog_;
+  bool use_bottom_controls_;
+  bool hide_pip_frame_;
   CefRefPtr<CefWindow> window_;
 
   CefRefPtr<CefMenuModel> button_menu_model_;
-  CefRefPtr<ViewsMenuBar> top_menu_bar_;
+  CefRefPtr<ViewsMenuBar> menu_bar_;
+  CefRefPtr<CefView> toolbar_;
+  CefRefPtr<CefMenuButton> menu_button_;
+  CefRefPtr<CefView> location_bar_;
   bool menu_has_focus_;
   int last_focused_view_;
+  std::optional<CefRect> last_visible_bounds_;
 
   CefSize minimum_window_size_;
 
+  CefRefPtr<ViewsOverlayControls> overlay_controls_;
+
+  std::optional<float> default_titlebar_height_;
+  std::optional<float> override_titlebar_height_;
+
   // Structure representing an extension.
   struct ExtensionInfo {
     ExtensionInfo(CefRefPtr<CefExtension> extension, CefRefPtr<CefImage> image)
diff --git a/src/tests/cefclient/browser/views_window_mac.mm b/src/tests/cefclient/browser/views_window_mac.mm
new file mode 100644
index 0000000..936a85c
--- /dev/null
+++ b/src/tests/cefclient/browser/views_window_mac.mm
@@ -0,0 +1,24 @@
+// Copyright (c) 2023 The Chromium Embedded Framework 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 "tests/cefclient/browser/views_window.h"
+
+#include <Cocoa/Cocoa.h>
+
+namespace client {
+
+void ViewsWindow::NudgeWindow() {
+  if (window_) {
+    auto view = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(window_->GetWindowHandle());
+    NSWindow* main_window = view.window;
+
+    auto theme_frame = main_window.contentView.superview;
+    // Nudge view frame a little to force an update.
+    NSSize size = theme_frame.frame.size;
+    [theme_frame setFrameSize:NSMakeSize(size.width - 1, size.height)];
+    [theme_frame setFrameSize:size];
+  }
+}
+
+}
diff --git a/src/tests/cefclient/browser/window_test.cc b/src/tests/cefclient/browser/window_test.cc
index 4cb0461..68c27fb 100644
--- a/src/tests/cefclient/browser/window_test.cc
+++ b/src/tests/cefclient/browser/window_test.cc
@@ -9,21 +9,19 @@
 #include <string>
 #include <vector>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/wrapper/cef_stream_resource_handler.h"
 #include "tests/cefclient/browser/main_context.h"
 #include "tests/cefclient/browser/test_runner.h"
 #include "tests/cefclient/browser/window_test_runner.h"
 
-#if defined(OS_WIN) || defined(OS_LINUX)
 #include "tests/cefclient/browser/window_test_runner_views.h"
-#endif
 
 #if defined(OS_WIN)
 #include "tests/cefclient/browser/window_test_runner_win.h"
 #elif defined(OS_LINUX)
 #include "tests/cefclient/browser/window_test_runner_gtk.h"
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
 #include "tests/cefclient/browser/window_test_runner_mac.h"
 #endif
 
@@ -37,25 +35,51 @@
 const char kMessageMinimizeName[] = "WindowTest.Minimize";
 const char kMessageMaximizeName[] = "WindowTest.Maximize";
 const char kMessageRestoreName[] = "WindowTest.Restore";
+const char kMessageFullscreenName[] = "WindowTest.Fullscreen";
+const char kMessageTitlebarHeightName[] = "WindowTest.TitlebarHeight";
 
 // Create the appropriate platform test runner object.
-scoped_ptr<WindowTestRunner> CreateWindowTestRunner() {
-#if defined(OS_WIN) || defined(OS_LINUX)
-  if (MainContext::Get()->UseViews())
-    return scoped_ptr<WindowTestRunner>(new WindowTestRunnerViews());
-#endif
+std::unique_ptr<WindowTestRunner> CreateWindowTestRunner() {
+  if (MainContext::Get()->UseViews()) {
+    return std::make_unique<WindowTestRunnerViews>();
+  }
 
 #if defined(OS_WIN)
-  return scoped_ptr<WindowTestRunner>(new WindowTestRunnerWin());
+  return std::make_unique<WindowTestRunnerWin>();
 #elif defined(OS_LINUX)
-  return scoped_ptr<WindowTestRunner>(new WindowTestRunnerGtk());
-#elif defined(OS_MACOSX)
-  return scoped_ptr<WindowTestRunner>(new WindowTestRunnerMac());
+  return std::make_unique<WindowTestRunnerGtk>();
+#elif defined(OS_MAC)
+  return std::make_unique<WindowTestRunnerMac>();
 #else
 #error "No implementation available for your platform."
 #endif
 }
 
+// Parse the comma-delimited list of integer values.
+std::vector<int> ParsePosition(const std::string& message_name) {
+  std::vector<int> vec;
+  const std::string& vals = message_name.substr(sizeof(kMessagePositionName));
+  std::stringstream ss(vals);
+  int i;
+  while (ss >> i) {
+    vec.push_back(i);
+    if (ss.peek() == ',') {
+      ss.ignore();
+    }
+  }
+
+  return vec;
+}
+
+std::optional<float> ParseHeight(const std::string& message) {
+  if (message.size() > sizeof(kMessageTitlebarHeightName)) {
+    const std::string& val = message.substr(sizeof(kMessageTitlebarHeightName));
+    return std::stof(val);
+  } else {
+    return std::nullopt;
+  }
+}
+
 // Handle messages in the browser process.
 class Handler : public CefMessageRouterBrowserSide::Handler {
  public:
@@ -64,42 +88,33 @@
   // Called due to cefBroadcast execution in window.html.
   virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
                        CefRefPtr<CefFrame> frame,
-                       int64 query_id,
+                       int64_t query_id,
                        const CefString& request,
                        bool persistent,
-                       CefRefPtr<Callback> callback) OVERRIDE {
+                       CefRefPtr<Callback> callback) override {
     // Only handle messages from the test URL.
     const std::string& url = frame->GetURL();
-    if (!test_runner::IsTestURL(url, kTestUrlPath))
+    if (!test_runner::IsTestURL(url, kTestUrlPath)) {
       return false;
+    }
 
     const std::string& message_name = request;
     if (message_name.find(kMessagePositionName) == 0) {
-      // Parse the comma-delimited list of integer values.
-      std::vector<int> vec;
-      const std::string& vals =
-          message_name.substr(sizeof(kMessagePositionName));
-      std::stringstream ss(vals);
-      int i;
-      while (ss >> i) {
-        vec.push_back(i);
-        if (ss.peek() == ',')
-          ss.ignore();
-      }
-
+      const auto vec = ParsePosition(message_name);
       if (vec.size() == 4) {
-        // Execute SetPos() on the main thread.
         runner_->SetPos(browser, vec[0], vec[1], vec[2], vec[3]);
       }
     } else if (message_name == kMessageMinimizeName) {
-      // Execute Minimize() on the main thread.
       runner_->Minimize(browser);
     } else if (message_name == kMessageMaximizeName) {
-      // Execute Maximize() on the main thread.
       runner_->Maximize(browser);
     } else if (message_name == kMessageRestoreName) {
-      // Execute Restore() on the main thread.
       runner_->Restore(browser);
+    } else if (message_name == kMessageFullscreenName) {
+      runner_->Fullscreen(browser);
+    } else if (message_name.find(kMessageTitlebarHeightName) == 0) {
+      const auto height = ParseHeight(message_name);
+      runner_->SetTitleBarHeight(browser, height);
     } else {
       NOTREACHED();
     }
@@ -109,7 +124,7 @@
   }
 
  private:
-  scoped_ptr<WindowTestRunner> runner_;
+  std::unique_ptr<WindowTestRunner> runner_;
 };
 
 }  // namespace
diff --git a/src/tests/cefclient/browser/window_test_runner.cc b/src/tests/cefclient/browser/window_test_runner.cc
index 05f1ac5..c81810b 100644
--- a/src/tests/cefclient/browser/window_test_runner.cc
+++ b/src/tests/cefclient/browser/window_test_runner.cc
@@ -12,22 +12,37 @@
   window.x += display.x;
   window.y += display.y;
 
-  if (window.x < display.x)
+  if (window.x < display.x) {
     window.x = display.x;
-  if (window.y < display.y)
+  }
+  if (window.y < display.y) {
     window.y = display.y;
-  if (window.width < 100)
+  }
+  if (window.width < 100) {
     window.width = 100;
-  else if (window.width >= display.width)
+  } else if (window.width >= display.width) {
     window.width = display.width;
-  if (window.height < 100)
+  }
+  if (window.height < 100) {
     window.height = 100;
-  else if (window.height >= display.height)
+  } else if (window.height >= display.height) {
     window.height = display.height;
-  if (window.x + window.width >= display.x + display.width)
+  }
+  if (window.x + window.width >= display.x + display.width) {
     window.x = display.x + display.width - window.width;
-  if (window.y + window.height >= display.y + display.height)
+  }
+  if (window.y + window.height >= display.y + display.height) {
     window.y = display.y + display.height - window.height;
+  }
+}
+
+void WindowTestRunner::Fullscreen(CefRefPtr<CefBrowser> browser) {
+  NOTIMPLEMENTED();
+}
+
+void WindowTestRunner::SetTitleBarHeight(CefRefPtr<CefBrowser> browser,
+                                         const std::optional<float>& height) {
+  NOTIMPLEMENTED();
 }
 
 }  // namespace window_test
diff --git a/src/tests/cefclient/browser/window_test_runner.h b/src/tests/cefclient/browser/window_test_runner.h
index 26a5324..8378d4c 100644
--- a/src/tests/cefclient/browser/window_test_runner.h
+++ b/src/tests/cefclient/browser/window_test_runner.h
@@ -8,6 +8,8 @@
 
 #include "include/cef_browser.h"
 
+#include <optional>
+
 namespace client {
 namespace window_test {
 
@@ -15,6 +17,8 @@
 // the browser process UI thread unless otherwise indicated.
 class WindowTestRunner {
  public:
+  virtual ~WindowTestRunner() = default;
+
   virtual void SetPos(CefRefPtr<CefBrowser> browser,
                       int x,
                       int y,
@@ -23,12 +27,14 @@
   virtual void Minimize(CefRefPtr<CefBrowser> browser) = 0;
   virtual void Maximize(CefRefPtr<CefBrowser> browser) = 0;
   virtual void Restore(CefRefPtr<CefBrowser> browser) = 0;
+  virtual void Fullscreen(CefRefPtr<CefBrowser> browser);
 
   // Fit |window| inside |display|. Coordinates are relative to the upper-left
   // corner of the display.
   static void ModifyBounds(const CefRect& display, CefRect& window);
 
-  virtual ~WindowTestRunner() {}
+  virtual void SetTitleBarHeight(CefRefPtr<CefBrowser> browser,
+                                 const std::optional<float>& height);
 };
 
 }  // namespace window_test
diff --git a/src/tests/cefclient/browser/window_test_runner_gtk.cc b/src/tests/cefclient/browser/window_test_runner_gtk.cc
index ff79991..a5093f1 100644
--- a/src/tests/cefclient/browser/window_test_runner_gtk.cc
+++ b/src/tests/cefclient/browser/window_test_runner_gtk.cc
@@ -21,8 +21,9 @@
       RootWindow::GetForBrowser(browser->GetIdentifier());
   if (root_window) {
     GtkWindow* window = GTK_WINDOW(root_window->GetWindowHandle());
-    if (!window)
+    if (!window) {
       LOG(ERROR) << "No GtkWindow for browser";
+    }
     return window;
   }
   return nullptr;
@@ -43,15 +44,17 @@
   ScopedGdkThreadsEnter scoped_gdk_threads;
 
   GtkWindow* window = GetWindow(browser);
-  if (!window)
+  if (!window) {
     return;
+  }
   GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
 
   // Make sure the window isn't minimized or maximized.
-  if (IsMaximized(window))
+  if (IsMaximized(window)) {
     gtk_window_unmaximize(window);
-  else
+  } else {
     gtk_window_present(window);
+  }
 
   // Retrieve information about the display that contains the window.
   GdkScreen* screen = gdk_screen_get_default();
@@ -73,12 +76,14 @@
   ScopedGdkThreadsEnter scoped_gdk_threads;
 
   GtkWindow* window = GetWindow(browser);
-  if (!window)
+  if (!window) {
     return;
+  }
 
   // Unmaximize the window before minimizing so restore behaves correctly.
-  if (IsMaximized(window))
+  if (IsMaximized(window)) {
     gtk_window_unmaximize(window);
+  }
 
   gtk_window_iconify(window);
 }
@@ -88,8 +93,9 @@
   ScopedGdkThreadsEnter scoped_gdk_threads;
 
   GtkWindow* window = GetWindow(browser);
-  if (!window)
+  if (!window) {
     return;
+  }
   gtk_window_maximize(window);
 }
 
@@ -98,12 +104,14 @@
   ScopedGdkThreadsEnter scoped_gdk_threads;
 
   GtkWindow* window = GetWindow(browser);
-  if (!window)
+  if (!window) {
     return;
-  if (IsMaximized(window))
+  }
+  if (IsMaximized(window)) {
     gtk_window_unmaximize(window);
-  else
+  } else {
     gtk_window_present(window);
+  }
 }
 
 }  // namespace
@@ -115,19 +123,19 @@
                                  int y,
                                  int width,
                                  int height) {
-  MAIN_POST_CLOSURE(base::Bind(SetPosImpl, browser, x, y, width, height));
+  MAIN_POST_CLOSURE(base::BindOnce(SetPosImpl, browser, x, y, width, height));
 }
 
 void WindowTestRunnerGtk::Minimize(CefRefPtr<CefBrowser> browser) {
-  MAIN_POST_CLOSURE(base::Bind(MinimizeImpl, browser));
+  MAIN_POST_CLOSURE(base::BindOnce(MinimizeImpl, browser));
 }
 
 void WindowTestRunnerGtk::Maximize(CefRefPtr<CefBrowser> browser) {
-  MAIN_POST_CLOSURE(base::Bind(MaximizeImpl, browser));
+  MAIN_POST_CLOSURE(base::BindOnce(MaximizeImpl, browser));
 }
 
 void WindowTestRunnerGtk::Restore(CefRefPtr<CefBrowser> browser) {
-  MAIN_POST_CLOSURE(base::Bind(RestoreImpl, browser));
+  MAIN_POST_CLOSURE(base::BindOnce(RestoreImpl, browser));
 }
 
 }  // namespace window_test
diff --git a/src/tests/cefclient/browser/window_test_runner_gtk.h b/src/tests/cefclient/browser/window_test_runner_gtk.h
index c920fdb..c699039 100644
--- a/src/tests/cefclient/browser/window_test_runner_gtk.h
+++ b/src/tests/cefclient/browser/window_test_runner_gtk.h
@@ -20,10 +20,10 @@
               int x,
               int y,
               int width,
-              int height) OVERRIDE;
-  void Minimize(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void Maximize(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void Restore(CefRefPtr<CefBrowser> browser) OVERRIDE;
+              int height) override;
+  void Minimize(CefRefPtr<CefBrowser> browser) override;
+  void Maximize(CefRefPtr<CefBrowser> browser) override;
+  void Restore(CefRefPtr<CefBrowser> browser) override;
 };
 
 }  // namespace window_test
diff --git a/src/tests/cefclient/browser/window_test_runner_mac.h b/src/tests/cefclient/browser/window_test_runner_mac.h
index 199d04a..aebae0e 100644
--- a/src/tests/cefclient/browser/window_test_runner_mac.h
+++ b/src/tests/cefclient/browser/window_test_runner_mac.h
@@ -20,10 +20,10 @@
               int x,
               int y,
               int width,
-              int height) OVERRIDE;
-  void Minimize(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void Maximize(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void Restore(CefRefPtr<CefBrowser> browser) OVERRIDE;
+              int height) override;
+  void Minimize(CefRefPtr<CefBrowser> browser) override;
+  void Maximize(CefRefPtr<CefBrowser> browser) override;
+  void Restore(CefRefPtr<CefBrowser> browser) override;
 };
 
 }  // namespace window_test
diff --git a/src/tests/cefclient/browser/window_test_runner_mac.mm b/src/tests/cefclient/browser/window_test_runner_mac.mm
index 2a04d09..1f18144 100644
--- a/src/tests/cefclient/browser/window_test_runner_mac.mm
+++ b/src/tests/cefclient/browser/window_test_runner_mac.mm
@@ -35,15 +35,17 @@
   NSWindow* window = GetWindow(browser);
 
   // Make sure the window isn't minimized or maximized.
-  if ([window isMiniaturized])
+  if ([window isMiniaturized]) {
     [window deminiaturize:nil];
-  else if ([window isZoomed])
+  } else if ([window isZoomed]) {
     [window performZoom:nil];
+  }
 
   // Retrieve information for the display that contains the window.
   NSScreen* screen = [window screen];
-  if (screen == nil)
+  if (screen == nil) {
     screen = [NSScreen mainScreen];
+  }
   NSRect frame = [screen frame];
   NSRect visibleFrame = [screen visibleFrame];
 
@@ -82,10 +84,11 @@
   REQUIRE_MAIN_THREAD();
 
   NSWindow* window = GetWindow(browser);
-  if ([window isMiniaturized])
+  if ([window isMiniaturized]) {
     [window deminiaturize:nil];
-  else if ([window isZoomed])
+  } else if ([window isZoomed]) {
     [window performZoom:nil];
+  }
 }
 
 }  // namespace window_test
diff --git a/src/tests/cefclient/browser/window_test_runner_views.cc b/src/tests/cefclient/browser/window_test_runner_views.cc
index 03aecf4..9508ca7 100644
--- a/src/tests/cefclient/browser/window_test_runner_views.cc
+++ b/src/tests/cefclient/browser/window_test_runner_views.cc
@@ -9,12 +9,15 @@
 #include "include/views/cef_window.h"
 #include "include/wrapper/cef_helpers.h"
 
+#include "tests/cefclient/browser/root_window_views.h"
+#include "tests/cefclient/browser/views_window.h"
+
 namespace client {
 namespace window_test {
 
 namespace {
 
-CefRefPtr<CefWindow> GetWindow(CefRefPtr<CefBrowser> browser) {
+CefRefPtr<CefWindow> GetWindow(const CefRefPtr<CefBrowser>& browser) {
   CEF_REQUIRE_UI_THREAD();
   DCHECK(browser->GetHost()->HasView());
 
@@ -27,6 +30,16 @@
   return window;
 }
 
+void SetTitlebarHeight(const CefRefPtr<CefBrowser>& browser,
+                       const std::optional<float>& height) {
+  CEF_REQUIRE_UI_THREAD();
+  auto root_window = RootWindow::GetForBrowser(browser->GetIdentifier());
+  DCHECK(root_window.get());
+
+  auto root_window_views = static_cast<RootWindowViews*>(root_window.get());
+  root_window_views->SetTitlebarHeight(height);
+}
+
 }  // namespace
 
 WindowTestRunnerViews::WindowTestRunnerViews() {}
@@ -56,5 +69,22 @@
   GetWindow(browser)->Restore();
 }
 
+void WindowTestRunnerViews::Fullscreen(CefRefPtr<CefBrowser> browser) {
+  auto window = GetWindow(browser);
+
+  // Results in a call to ViewsWindow::OnWindowFullscreenTransition().
+  if (window->IsFullscreen()) {
+    window->SetFullscreen(false);
+  } else {
+    window->SetFullscreen(true);
+  }
+}
+
+void WindowTestRunnerViews::SetTitleBarHeight(
+    CefRefPtr<CefBrowser> browser,
+    const std::optional<float>& height) {
+  SetTitlebarHeight(browser, height);
+}
+
 }  // namespace window_test
 }  // namespace client
diff --git a/src/tests/cefclient/browser/window_test_runner_views.h b/src/tests/cefclient/browser/window_test_runner_views.h
index 81334e4..d8b0bde 100644
--- a/src/tests/cefclient/browser/window_test_runner_views.h
+++ b/src/tests/cefclient/browser/window_test_runner_views.h
@@ -20,10 +20,13 @@
               int x,
               int y,
               int width,
-              int height) OVERRIDE;
-  void Minimize(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void Maximize(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void Restore(CefRefPtr<CefBrowser> browser) OVERRIDE;
+              int height) override;
+  void Minimize(CefRefPtr<CefBrowser> browser) override;
+  void Maximize(CefRefPtr<CefBrowser> browser) override;
+  void Restore(CefRefPtr<CefBrowser> browser) override;
+  void Fullscreen(CefRefPtr<CefBrowser> browser) override;
+  void SetTitleBarHeight(CefRefPtr<CefBrowser> browser,
+                         const std::optional<float>& height) override;
 };
 
 }  // namespace window_test
diff --git a/src/tests/cefclient/browser/window_test_runner_win.cc b/src/tests/cefclient/browser/window_test_runner_win.cc
index de03c96..d94e898 100644
--- a/src/tests/cefclient/browser/window_test_runner_win.cc
+++ b/src/tests/cefclient/browser/window_test_runner_win.cc
@@ -21,10 +21,11 @@
   WINDOWPLACEMENT placement;
   ::GetWindowPlacement(root_hwnd, &placement);
 
-  if (placement.showCmd == nCmdShow)
+  if (placement.showCmd == nCmdShow) {
     ::ShowWindow(root_hwnd, SW_RESTORE);
-  else
+  } else {
     ::ShowWindow(root_hwnd, nCmdShow);
+  }
 }
 
 void SetPosImpl(CefRefPtr<CefBrowser> browser,
@@ -33,8 +34,9 @@
                 int width,
                 int height) {
   HWND root_hwnd = GetRootHwnd(browser);
-  if (!root_hwnd)
+  if (!root_hwnd) {
     return;
+  }
 
   // Retrieve current window placement information.
   WINDOWPLACEMENT placement;
@@ -54,7 +56,8 @@
   CefRect window_rect(x, y, width, height);
   WindowTestRunner::ModifyBounds(display_rect, window_rect);
 
-  if (placement.showCmd == SW_MINIMIZE || placement.showCmd == SW_MAXIMIZE) {
+  if (placement.showCmd == SW_SHOWMINIMIZED ||
+      placement.showCmd == SW_SHOWMAXIMIZED) {
     // The window is currently minimized or maximized. Restore it to the desired
     // position.
     placement.rcNormalPosition.left = window_rect.x;
@@ -65,29 +68,32 @@
     ::ShowWindow(root_hwnd, SW_RESTORE);
   } else {
     // Set the window position.
-    ::SetWindowPos(root_hwnd, NULL, window_rect.x, window_rect.y,
+    ::SetWindowPos(root_hwnd, nullptr, window_rect.x, window_rect.y,
                    window_rect.width, window_rect.height, SWP_NOZORDER);
   }
 }
 
 void MinimizeImpl(CefRefPtr<CefBrowser> browser) {
   HWND root_hwnd = GetRootHwnd(browser);
-  if (!root_hwnd)
+  if (!root_hwnd) {
     return;
+  }
   Toggle(root_hwnd, SW_MINIMIZE);
 }
 
 void MaximizeImpl(CefRefPtr<CefBrowser> browser) {
   HWND root_hwnd = GetRootHwnd(browser);
-  if (!root_hwnd)
+  if (!root_hwnd) {
     return;
+  }
   Toggle(root_hwnd, SW_MAXIMIZE);
 }
 
 void RestoreImpl(CefRefPtr<CefBrowser> browser) {
   HWND root_hwnd = GetRootHwnd(browser);
-  if (!root_hwnd)
+  if (!root_hwnd) {
     return;
+  }
   ::ShowWindow(root_hwnd, SW_RESTORE);
 }
 
@@ -104,7 +110,7 @@
     SetPosImpl(browser, x, y, width, height);
   } else {
     // Execute on the main application thread.
-    MAIN_POST_CLOSURE(base::Bind(SetPosImpl, browser, x, y, width, height));
+    MAIN_POST_CLOSURE(base::BindOnce(SetPosImpl, browser, x, y, width, height));
   }
 }
 
@@ -113,7 +119,7 @@
     MinimizeImpl(browser);
   } else {
     // Execute on the main application thread.
-    MAIN_POST_CLOSURE(base::Bind(MinimizeImpl, browser));
+    MAIN_POST_CLOSURE(base::BindOnce(MinimizeImpl, browser));
   }
 }
 
@@ -122,7 +128,7 @@
     MaximizeImpl(browser);
   } else {
     // Execute on the main application thread.
-    MAIN_POST_CLOSURE(base::Bind(MaximizeImpl, browser));
+    MAIN_POST_CLOSURE(base::BindOnce(MaximizeImpl, browser));
   }
 }
 
@@ -131,7 +137,7 @@
     RestoreImpl(browser);
   } else {
     // Execute on the main application thread.
-    MAIN_POST_CLOSURE(base::Bind(RestoreImpl, browser));
+    MAIN_POST_CLOSURE(base::BindOnce(RestoreImpl, browser));
   }
 }
 
diff --git a/src/tests/cefclient/browser/window_test_runner_win.h b/src/tests/cefclient/browser/window_test_runner_win.h
index 14ff9f7..d6e38ef 100644
--- a/src/tests/cefclient/browser/window_test_runner_win.h
+++ b/src/tests/cefclient/browser/window_test_runner_win.h
@@ -21,10 +21,10 @@
               int x,
               int y,
               int width,
-              int height) OVERRIDE;
-  void Minimize(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void Maximize(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  void Restore(CefRefPtr<CefBrowser> browser) OVERRIDE;
+              int height) override;
+  void Minimize(CefRefPtr<CefBrowser> browser) override;
+  void Maximize(CefRefPtr<CefBrowser> browser) override;
+  void Restore(CefRefPtr<CefBrowser> browser) override;
 };
 
 }  // namespace window_test
diff --git a/src/tests/cefclient/cefclient_gtk.cc b/src/tests/cefclient/cefclient_gtk.cc
index 02ae571..f0237a5 100644
--- a/src/tests/cefclient/cefclient_gtk.cc
+++ b/src/tests/cefclient/cefclient_gtk.cc
@@ -3,7 +3,6 @@
 // can be found in the LICENSE file.
 
 #include <gtk/gtk.h>
-#include <gtk/gtkgl.h>
 
 #include <X11/Xlib.h>
 #undef Success     // Definition conflicts with cef_message_router.h
@@ -11,10 +10,10 @@
 
 #include <stdlib.h>
 #include <unistd.h>
+#include <memory>
 #include <string>
 
 #include "include/base/cef_logging.h"
-#include "include/base/cef_scoped_ptr.h"
 #include "include/cef_app.h"
 #include "include/cef_command_line.h"
 #include "include/wrapper/cef_helpers.h"
@@ -80,11 +79,12 @@
 
   // Execute the secondary process, if any.
   int exit_code = CefExecuteProcess(main_args, app, nullptr);
-  if (exit_code >= 0)
+  if (exit_code >= 0) {
     return exit_code;
+  }
 
   // Create the main context object.
-  scoped_ptr<MainContextImpl> context(new MainContextImpl(command_line, true));
+  auto context = std::make_unique<MainContextImpl>(command_line, true);
 
   CefSettings settings;
 
@@ -98,25 +98,33 @@
   // Populate the settings based on command line arguments.
   context->PopulateSettings(&settings);
 
+  if (settings.windowless_rendering_enabled) {
+    // Force the app to use OpenGL <= 3.1 when off-screen rendering is enabled.
+    // TODO(cefclient): Rewrite OSRRenderer to use shaders instead of the
+    // fixed-function pipeline which was removed in OpenGL 3.2 (back in 2009).
+    setenv("MESA_GL_VERSION_OVERRIDE", "3.1", /*overwrite=*/0);
+  }
+
   // Create the main message loop object.
-  scoped_ptr<MainMessageLoop> message_loop;
-  if (settings.multi_threaded_message_loop)
+  std::unique_ptr<MainMessageLoop> message_loop;
+  if (settings.multi_threaded_message_loop) {
     message_loop.reset(new MainMessageLoopMultithreadedGtk);
-  else if (settings.external_message_pump)
+  } else if (settings.external_message_pump) {
     message_loop = MainMessageLoopExternalPump::Create();
-  else
+  } else {
     message_loop.reset(new MainMessageLoopStd);
+  }
 
   // Initialize CEF.
   context->Initialize(main_args, settings, app, nullptr);
 
+  // Force Gtk to use Xwayland (in case a Wayland compositor is being used).
+  gdk_set_allowed_backends("x11");
+
   // The Chromium sandbox requires that there only be a single thread during
   // initialization. Therefore initialize GTK after CEF.
   gtk_init(&argc, &argv_copy);
 
-  // Perform gtkglext initialization required by the OSR example.
-  gtk_gl_init(&argc, &argv_copy);
-
   // Install xlib error handlers so that the application won't be terminated
   // on non-fatal errors. Must be done after initializing GTK.
   XSetErrorHandler(XErrorHandlerImpl);
@@ -129,14 +137,16 @@
   // Register scheme handlers.
   test_runner::RegisterSchemeHandlers();
 
-  RootWindowConfig window_config;
-  window_config.always_on_top = command_line->HasSwitch(switches::kAlwaysOnTop);
-  window_config.with_controls =
+  auto window_config = std::make_unique<RootWindowConfig>();
+  window_config->always_on_top =
+      command_line->HasSwitch(switches::kAlwaysOnTop);
+  window_config->with_controls =
       !command_line->HasSwitch(switches::kHideControls);
-  window_config.with_osr = settings.windowless_rendering_enabled ? true : false;
+  window_config->with_osr =
+      settings.windowless_rendering_enabled ? true : false;
 
   // Create the first window.
-  context->GetRootWindowManager()->CreateRootWindow(window_config);
+  context->GetRootWindowManager()->CreateRootWindow(std::move(window_config));
 
   // Run the message loop. This will block until Quit() is called.
   int result = message_loop->Run();
diff --git a/src/tests/cefclient/cefclient_mac.mm b/src/tests/cefclient/cefclient_mac.mm
index e7bd659..32c4c75 100644
--- a/src/tests/cefclient/cefclient_mac.mm
+++ b/src/tests/cefclient/cefclient_mac.mm
@@ -6,6 +6,7 @@
 #import <Cocoa/Cocoa.h>
 #include "include/cef_app.h"
 #import "include/cef_application_mac.h"
+#include "include/cef_command_ids.h"
 #import "include/wrapper/cef_library_loader.h"
 #include "tests/cefclient/browser/main_context_impl.h"
 #include "tests/cefclient/browser/resource.h"
@@ -22,8 +23,9 @@
 NSMenuItem* GetMenuBarMenuWithTag(NSInteger tag) {
   NSMenu* main_menu = [[NSApplication sharedApplication] mainMenu];
   NSInteger found_index = [main_menu indexOfItemWithTag:tag];
-  if (found_index >= 0)
+  if (found_index >= 0) {
     return [main_menu itemAtIndex:found_index];
+  }
   return nil;
 }
 
@@ -31,12 +33,20 @@
 NSMenuItem* GetMenuItemWithAction(NSMenu* menu, SEL action_selector) {
   for (NSInteger i = 0; i < menu.numberOfItems; ++i) {
     NSMenuItem* item = [menu itemAtIndex:i];
-    if (item.action == action_selector)
+    if (item.action == action_selector) {
       return item;
+    }
   }
   return nil;
 }
 
+void RemoveMenuItem(NSMenu* menu, SEL action_selector) {
+  NSMenuItem* item = GetMenuItemWithAction(menu, action_selector);
+  if (item) {
+    [menu removeItem:item];
+  }
+}
+
 }  // namespace
 
 // Receives notifications from the application. Will delete itself when done.
@@ -54,8 +64,8 @@
 - (IBAction)menuTestsGetSource:(id)sender;
 - (IBAction)menuTestsWindowNew:(id)sender;
 - (IBAction)menuTestsWindowPopup:(id)sender;
+- (IBAction)menuTestsWindowDialog:(id)sender;
 - (IBAction)menuTestsRequest:(id)sender;
-- (IBAction)menuTestsPluginInfo:(id)sender;
 - (IBAction)menuTestsZoomIn:(id)sender;
 - (IBAction)menuTestsZoomOut:(id)sender;
 - (IBAction)menuTestsZoomReset:(id)sender;
@@ -204,28 +214,28 @@
   // Set the delegate for application events.
   [application setDelegate:self];
 
-  if (!with_osr_) {
-    // Remove the OSR-related menu items when OSR is disabled.
-    NSMenuItem* tests_menu = GetMenuBarMenuWithTag(8);
-    if (tests_menu) {
-      NSMenuItem* set_fps_item = GetMenuItemWithAction(
-          tests_menu.submenu, @selector(menuTestsSetFPS:));
-      if (set_fps_item)
-        [tests_menu.submenu removeItem:set_fps_item];
-      NSMenuItem* set_scale_factor_item = GetMenuItemWithAction(
-          tests_menu.submenu, @selector(menuTestsSetScaleFactor:));
-      if (set_scale_factor_item)
-        [tests_menu.submenu removeItem:set_scale_factor_item];
+  auto* main_context = client::MainContext::Get();
+
+  NSMenuItem* tests_menu = GetMenuBarMenuWithTag(8);
+  if (tests_menu) {
+    if (!with_osr_) {
+      // Remove the OSR-related menu items when not using OSR.
+      RemoveMenuItem(tests_menu.submenu, @selector(menuTestsSetFPS:));
+      RemoveMenuItem(tests_menu.submenu, @selector(menuTestsSetScaleFactor:));
+    }
+    if (!main_context->UseViews()) {
+      // Remove the Views-related menu items when not using Views.
+      RemoveMenuItem(tests_menu.submenu, @selector(menuTestsWindowDialog:));
     }
   }
 
-  client::RootWindowConfig window_config;
-  window_config.with_controls = with_controls_;
-  window_config.with_osr = with_osr_;
+  auto window_config = std::make_unique<client::RootWindowConfig>();
+  window_config->with_controls = with_controls_;
+  window_config->with_osr = with_osr_;
 
   // Create the first window.
-  client::MainContext::Get()->GetRootWindowManager()->CreateRootWindow(
-      window_config);
+  main_context->GetRootWindowManager()->CreateRootWindow(
+      std::move(window_config));
 }
 
 - (void)tryToTerminateApplication:(NSApplication*)app {
@@ -237,17 +247,9 @@
 }
 
 - (void)testsItemSelected:(int)command_id {
-  // Retrieve the active RootWindow.
-  NSWindow* key_window = [[NSApplication sharedApplication] keyWindow];
-  if (!key_window)
-    return;
-
-  scoped_refptr<client::RootWindow> root_window =
-      client::RootWindow::GetForNSWindow(key_window);
-
-  CefRefPtr<CefBrowser> browser = root_window->GetBrowser();
-  if (browser.get())
+  if (auto browser = [self getActiveBrowser]) {
     client::test_runner::RunTest(browser, command_id);
+  }
 }
 
 - (IBAction)menuTestsGetText:(id)sender {
@@ -266,12 +268,12 @@
   [self testsItemSelected:ID_TESTS_WINDOW_POPUP];
 }
 
-- (IBAction)menuTestsRequest:(id)sender {
-  [self testsItemSelected:ID_TESTS_REQUEST];
+- (IBAction)menuTestsWindowDialog:(id)sender {
+  [self testsItemSelected:ID_TESTS_WINDOW_DIALOG];
 }
 
-- (IBAction)menuTestsPluginInfo:(id)sender {
-  [self testsItemSelected:ID_TESTS_PLUGIN_INFO];
+- (IBAction)menuTestsRequest:(id)sender {
+  [self testsItemSelected:ID_TESTS_REQUEST];
 }
 
 - (IBAction)menuTestsZoomIn:(id)sender {
@@ -322,17 +324,28 @@
   [self testsItemSelected:ID_TESTS_OTHER_TESTS];
 }
 
+- (CefRefPtr<CefBrowser>)getActiveBrowser {
+  auto root_window =
+      client::MainContext::Get()->GetRootWindowManager()->GetActiveRootWindow();
+  if (root_window) {
+    return root_window->GetBrowser();
+  }
+
+  return nullptr;
+}
+
+- (NSWindow*)getActiveBrowserNSWindow {
+  if (auto browser = [self getActiveBrowser]) {
+    if (auto view = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(
+            browser->GetHost()->GetWindowHandle())) {
+      return [view window];
+    }
+  }
+  return nil;
+}
+
 - (void)enableAccessibility:(bool)bEnable {
-  // Retrieve the active RootWindow.
-  NSWindow* key_window = [[NSApplication sharedApplication] keyWindow];
-  if (!key_window)
-    return;
-
-  scoped_refptr<client::RootWindow> root_window =
-      client::RootWindow::GetForNSWindow(key_window);
-
-  CefRefPtr<CefBrowser> browser = root_window->GetBrowser();
-  if (browser.get()) {
+  if (auto browser = [self getActiveBrowser]) {
     browser->GetHost()->SetAccessibilityState(bEnable ? STATE_ENABLED
                                                       : STATE_DISABLED);
   }
@@ -343,6 +356,157 @@
   return NSTerminateNow;
 }
 
+// Returns true if there is a modal window (either window- or application-
+// modal) blocking the active browser. Note that tab modal dialogs (HTTP auth
+// sheets) will not count as blocking the browser. But things like open/save
+// dialogs that are window modal will block the browser.
+- (BOOL)keyWindowIsModal {
+  if ([NSApp modalWindow]) {
+    return YES;
+  }
+
+  if (auto window = [self getActiveBrowserNSWindow]) {
+    return [[window attachedSheet] isKindOfClass:[NSWindow class]];
+  }
+
+  return NO;
+}
+
+// AppKit will call -[NSUserInterfaceValidations validateUserInterfaceItem:] to
+// validate UI items. Any item whose target is FirstResponder, or nil, will
+// traverse the responder chain looking for a responder that implements the
+// item's selector. The top menu (configured in MainMenu.xib) can contain menu
+// items with selectors that are implemented by Chromium's
+// RenderWidgetHostViewCocoa or NativeWidgetMacNSWindow classes. These classes
+// live in the Cocoa view hierarchy and will be triggered only if the browser
+// window is focused. When the browser window is not focused these selectors
+// will be forwarded (by Chromium's CommandDispatcher class) to `[NSApp
+// delegate]` (this class). The particular selectors of interest here are
+// |-commandDispatch:| and |-commandDispatchUsingKeyModifiers:| which will have
+// a tag value from include/cef_command_ids.h. For example, 37000 is IDC_FIND
+// and can be triggered via the "Find..." menu item or the Cmd+g keyboard
+// shortcut:
+//
+//   <menuItem title="Find..." tag="37000" keyEquivalent="g" id="209">
+//        <connections>
+//            <action selector="commandDispatch:" target="-1" id="241"/>
+//        </connections>
+//   </menuItem>
+//
+// If |-validateUserInterfaceItem:| returns YES then the menu item will be
+// enabled and execution will trigger the associated selector.
+//
+// This implementation is based on Chromium's AppController class.
+- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
+  SEL action = [item action];
+  BOOL enable = NO;
+  // Whether opening a new browser window is allowed.
+  BOOL canOpenNewBrowser = YES;
+
+  // Commands from the menu bar are only handled by commandDispatch: if there is
+  // no key window.
+  if (action == @selector(commandDispatch:) ||
+      action == @selector(commandDispatchUsingKeyModifiers:)) {
+    switch ([item tag]) {
+      // Browser-level items that open in new tabs or perform an action in a
+      // current tab should not open if there's a window- or app-modal dialog.
+      case IDC_OPEN_FILE:
+      case IDC_NEW_TAB:
+      case IDC_FOCUS_LOCATION:
+      case IDC_FOCUS_SEARCH:
+      case IDC_SHOW_HISTORY:
+      case IDC_SHOW_BOOKMARK_MANAGER:
+      case IDC_CLEAR_BROWSING_DATA:
+      case IDC_SHOW_DOWNLOADS:
+      case IDC_IMPORT_SETTINGS:
+      case IDC_MANAGE_EXTENSIONS:
+      case IDC_HELP_PAGE_VIA_MENU:
+      case IDC_OPTIONS:
+        enable = canOpenNewBrowser && ![self keyWindowIsModal];
+        break;
+      // Browser-level items that open in new windows: allow the user to open
+      // a new window even if there's a window-modal dialog.
+      case IDC_NEW_WINDOW:
+        enable = canOpenNewBrowser;
+        break;
+      case IDC_TASK_MANAGER:
+        enable = YES;
+        break;
+      case IDC_NEW_INCOGNITO_WINDOW:
+        enable = canOpenNewBrowser;
+        break;
+      default:
+        enable = ![self keyWindowIsModal];
+        break;
+    }
+  } else if ([self respondsToSelector:action]) {
+    // All other selectors that this class implements.
+    enable = YES;
+  }
+
+  return enable;
+}
+
+// This will get called in the case where the frontmost window is not a browser
+// window, and the user has command-clicked a button in a background browser
+// window whose action is |-commandDispatch:|
+- (void)commandDispatch:(id)sender {
+  // Handle the case where we're dispatching a command from a sender that's in a
+  // browser window. This means that the command came from a background window
+  // and is getting here because the foreground window is not a browser window.
+  DCHECK(sender);
+  if ([sender respondsToSelector:@selector(window)]) {
+    id delegate = [[sender window] windowController];
+    if ([delegate respondsToSelector:@selector(commandDispatch:)]) {
+      [delegate commandDispatch:sender];
+      return;
+    }
+  }
+
+  // Handle specific commands where we want to make the last active browser
+  // frontmost and then re-execute the command.
+  switch ([sender tag]) {
+    case IDC_FIND:
+    case IDC_FIND_NEXT:
+    case IDC_FIND_PREVIOUS:
+      if (id window = [self getActiveBrowserNSWindow]) {
+        [window makeKeyAndOrderFront:nil];
+        if ([window respondsToSelector:@selector(commandDispatch:)]) {
+          [window commandDispatch:sender];
+          return;
+        }
+      }
+      break;
+    default:
+      break;
+  }
+
+  LOG(INFO) << "Unhandled commandDispatch: for tag " << [sender tag];
+}
+
+// Same as |-commandDispatch:|, but executes commands using a disposition
+// determined by the key flags. This will get called in the case where the
+// frontmost window is not a browser window, and the user has command-clicked
+// a button in a background browser window whose action is
+// |-commandDispatchUsingKeyModifiers:|
+- (void)commandDispatchUsingKeyModifiers:(id)sender {
+  // Handle the case where we're dispatching a command from a sender that's in a
+  // browser window. This means that the command came from a background window
+  // and is getting here because the foreground window is not a browser window.
+  DCHECK(sender);
+  if ([sender respondsToSelector:@selector(window)]) {
+    id delegate = [[sender window] windowController];
+    if ([delegate
+            respondsToSelector:@selector(commandDispatchUsingKeyModifiers:)]) {
+      [delegate commandDispatchUsingKeyModifiers:sender];
+      return;
+    }
+  }
+
+  LOG(INFO) << "Unhandled commandDispatchUsingKeyModifiers: for tag "
+            << [sender tag];
+}
+
 @end
 
 namespace client {
@@ -352,8 +516,9 @@
   // Load the CEF framework library at runtime instead of linking directly
   // as required by the macOS sandbox implementation.
   CefScopedLibraryLoader library_loader;
-  if (!library_loader.LoadInMain())
+  if (!library_loader.LoadInMain()) {
     return 1;
+  }
 
   int result = -1;
 
@@ -363,6 +528,11 @@
     // Initialize the ClientApplication instance.
     [ClientApplication sharedApplication];
 
+    // If there was an invocation to NSApp prior to this method, then the NSApp
+    // will not be a ClientApplication, but will instead be an NSApplication.
+    // This is undesirable and we must enforce that this doesn't happen.
+    CHECK([NSApp isKindOfClass:[ClientApplication class]]);
+
     // Parse command-line arguments.
     CefRefPtr<CefCommandLine> command_line =
         CefCommandLine::CreateCommandLine();
@@ -372,11 +542,12 @@
     CefRefPtr<CefApp> app;
     ClientApp::ProcessType process_type =
         ClientApp::GetProcessType(command_line);
-    if (process_type == ClientApp::BrowserProcess)
+    if (process_type == ClientApp::BrowserProcess) {
       app = new ClientAppBrowser();
+    }
 
     // Create the main context object.
-    scoped_ptr<MainContextImpl> context(
+    std::unique_ptr<MainContextImpl> context(
         new MainContextImpl(command_line, true));
 
     CefSettings settings;
@@ -392,14 +563,15 @@
     context->PopulateSettings(&settings);
 
     // Create the main message loop object.
-    scoped_ptr<MainMessageLoop> message_loop;
-    if (settings.external_message_pump)
+    std::unique_ptr<MainMessageLoop> message_loop;
+    if (settings.external_message_pump) {
       message_loop = MainMessageLoopExternalPump::Create();
-    else
+    } else {
       message_loop.reset(new MainMessageLoopStd);
+    }
 
     // Initialize CEF.
-    context->Initialize(main_args, settings, app, NULL);
+    context->Initialize(main_args, settings, app, nullptr);
 
     // Register scheme handlers.
     test_runner::RegisterSchemeHandlers();
diff --git a/src/tests/cefclient/cefclient_win.cc b/src/tests/cefclient/cefclient_win.cc
index 74166bb..e4d4b34 100644
--- a/src/tests/cefclient/cefclient_win.cc
+++ b/src/tests/cefclient/cefclient_win.cc
@@ -4,7 +4,8 @@
 
 #include <windows.h>
 
-#include "include/base/cef_scoped_ptr.h"
+#include <memory>
+
 #include "include/cef_command_line.h"
 #include "include/cef_sandbox_win.h"
 #include "tests/cefclient/browser/main_context_impl.h"
@@ -34,9 +35,6 @@
 namespace {
 
 int RunMain(HINSTANCE hInstance, int nCmdShow) {
-  // Enable High-DPI support on Windows 7 or newer.
-  CefEnableHighDPISupport();
-
   CefMainArgs main_args(hInstance);
 
   void* sandbox_info = nullptr;
@@ -55,20 +53,22 @@
   // Create a ClientApp of the correct type.
   CefRefPtr<CefApp> app;
   ClientApp::ProcessType process_type = ClientApp::GetProcessType(command_line);
-  if (process_type == ClientApp::BrowserProcess)
+  if (process_type == ClientApp::BrowserProcess) {
     app = new ClientAppBrowser();
-  else if (process_type == ClientApp::RendererProcess)
+  } else if (process_type == ClientApp::RendererProcess) {
     app = new ClientAppRenderer();
-  else if (process_type == ClientApp::OtherProcess)
+  } else if (process_type == ClientApp::OtherProcess) {
     app = new ClientAppOther();
+  }
 
   // Execute the secondary process, if any.
   int exit_code = CefExecuteProcess(main_args, app, sandbox_info);
-  if (exit_code >= 0)
+  if (exit_code >= 0) {
     return exit_code;
+  }
 
   // Create the main context object.
-  scoped_ptr<MainContextImpl> context(new MainContextImpl(command_line, true));
+  auto context = std::make_unique<MainContextImpl>(command_line, true);
 
   CefSettings settings;
 
@@ -76,21 +76,18 @@
   settings.no_sandbox = true;
 #endif
 
-  // Applications should specify a unique GUID here to enable trusted downloads.
-  CefString(&settings.application_client_id_for_file_scanning)
-      .FromString("9A8DE24D-B822-4C6C-8259-5A848FEA1E68");
-
   // Populate the settings based on command line arguments.
   context->PopulateSettings(&settings);
 
   // Create the main message loop object.
-  scoped_ptr<MainMessageLoop> message_loop;
-  if (settings.multi_threaded_message_loop)
+  std::unique_ptr<MainMessageLoop> message_loop;
+  if (settings.multi_threaded_message_loop) {
     message_loop.reset(new MainMessageLoopMultithreadedWin);
-  else if (settings.external_message_pump)
+  } else if (settings.external_message_pump) {
     message_loop = MainMessageLoopExternalPump::Create();
-  else
+  } else {
     message_loop.reset(new MainMessageLoopStd);
+  }
 
   // Initialize CEF.
   context->Initialize(main_args, settings, app, sandbox_info);
@@ -98,14 +95,16 @@
   // Register scheme handlers.
   test_runner::RegisterSchemeHandlers();
 
-  RootWindowConfig window_config;
-  window_config.always_on_top = command_line->HasSwitch(switches::kAlwaysOnTop);
-  window_config.with_controls =
+  auto window_config = std::make_unique<RootWindowConfig>();
+  window_config->always_on_top =
+      command_line->HasSwitch(switches::kAlwaysOnTop);
+  window_config->with_controls =
       !command_line->HasSwitch(switches::kHideControls);
-  window_config.with_osr = settings.windowless_rendering_enabled ? true : false;
+  window_config->with_osr =
+      settings.windowless_rendering_enabled ? true : false;
 
   // Create the first window.
-  context->GetRootWindowManager()->CreateRootWindow(window_config);
+  context->GetRootWindowManager()->CreateRootWindow(std::move(window_config));
 
   // Run the message loop. This will block until Quit() is called by the
   // RootWindowManager after all windows have been destroyed.
@@ -131,5 +130,22 @@
                       int nCmdShow) {
   UNREFERENCED_PARAMETER(hPrevInstance);
   UNREFERENCED_PARAMETER(lpCmdLine);
+
+#if defined(ARCH_CPU_32_BITS)
+  // Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
+  // stack size. This function must be called at the top of the executable entry
+  // point function (`main()` or `wWinMain()`). It is used in combination with
+  // the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
+  // flag on executable targets. This saves significant memory on threads (like
+  // those in the Windows thread pool, and others) whose stack size can only be
+  // controlled via the linker flag.
+  int exit_code = CefRunWinMainWithPreferredStackSize(wWinMain, hInstance,
+                                                      lpCmdLine, nCmdShow);
+  if (exit_code >= 0) {
+    // The fiber has completed so return here.
+    return exit_code;
+  }
+#endif
+
   return client::RunMain(hInstance, nCmdShow);
 }
diff --git a/src/tests/cefclient/common/client_app_delegates_common.cc b/src/tests/cefclient/common/client_app_delegates_common.cc
index 99c3b86..493f3e1 100644
--- a/src/tests/cefclient/common/client_app_delegates_common.cc
+++ b/src/tests/cefclient/common/client_app_delegates_common.cc
@@ -8,10 +8,8 @@
 namespace client {
 
 // static
-void ClientApp::RegisterCustomSchemes(
-    CefRawPtr<CefSchemeRegistrar> registrar,
-    std::vector<CefString>& cookiable_schemes) {
-  scheme_test::RegisterCustomSchemes(registrar, cookiable_schemes);
+void ClientApp::RegisterCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar) {
+  scheme_test::RegisterCustomSchemes(registrar);
 }
 
 }  // namespace client
diff --git a/src/tests/cefclient/common/scheme_test_common.cc b/src/tests/cefclient/common/scheme_test_common.cc
index 4cf337a..7eb1eb6 100644
--- a/src/tests/cefclient/common/scheme_test_common.cc
+++ b/src/tests/cefclient/common/scheme_test_common.cc
@@ -9,8 +9,7 @@
 namespace client {
 namespace scheme_test {
 
-void RegisterCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar,
-                           std::vector<CefString>& cookiable_schemes) {
+void RegisterCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar) {
   registrar->AddCustomScheme(
       "client", CEF_SCHEME_OPTION_STANDARD | CEF_SCHEME_OPTION_CORS_ENABLED);
 }
diff --git a/src/tests/cefclient/common/scheme_test_common.h b/src/tests/cefclient/common/scheme_test_common.h
index 859623d..7eb2821 100644
--- a/src/tests/cefclient/common/scheme_test_common.h
+++ b/src/tests/cefclient/common/scheme_test_common.h
@@ -17,8 +17,7 @@
 // See browser/scheme_test.h for creation/registration of the custom scheme
 // handler which only occurs in the browser process. Called from
 // client_app_delegates_common.cc.
-void RegisterCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar,
-                           std::vector<CefString>& cookiable_schemes);
+void RegisterCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar);
 
 }  // namespace scheme_test
 }  // namespace client
diff --git a/src/tests/cefclient/renderer/client_app_delegates_renderer.cc b/src/tests/cefclient/renderer/client_app_delegates_renderer.cc
index bae180d..930c712 100644
--- a/src/tests/cefclient/renderer/client_app_delegates_renderer.cc
+++ b/src/tests/cefclient/renderer/client_app_delegates_renderer.cc
@@ -3,6 +3,7 @@
 // can be found in the LICENSE file.
 
 #include "tests/cefclient/renderer/client_renderer.h"
+#include "tests/cefclient/renderer/ipc_performance_test.h"
 #include "tests/cefclient/renderer/performance_test.h"
 #include "tests/shared/renderer/client_app_renderer.h"
 
@@ -12,6 +13,7 @@
 void ClientAppRenderer::CreateDelegates(DelegateSet& delegates) {
   renderer::CreateDelegates(delegates);
   performance_test::CreateDelegates(delegates);
+  ipc_performance_test::CreateDelegates(delegates);
 }
 
 }  // namespace client
diff --git a/src/tests/cefclient/renderer/client_renderer.cc b/src/tests/cefclient/renderer/client_renderer.cc
index 100fe2c..106a612 100644
--- a/src/tests/cefclient/renderer/client_renderer.cc
+++ b/src/tests/cefclient/renderer/client_renderer.cc
@@ -24,8 +24,7 @@
  public:
   ClientRenderDelegate() : last_node_is_editable_(false) {}
 
-  void OnRenderThreadCreated(CefRefPtr<ClientAppRenderer> app,
-                             CefRefPtr<CefListValue> extra_info) OVERRIDE {
+  void OnWebKitInitialized(CefRefPtr<ClientAppRenderer> app) override {
     if (CefCrashReportingEnabled()) {
       // Set some crash keys for testing purposes. Keys must be defined in the
       // "crash_reporter.cfg" file. See cef_crash_util.h for details.
@@ -36,9 +35,7 @@
       CefSetCrashKeyValue("testkey_large1", "value1_large_renderer");
       CefSetCrashKeyValue("testkey_large2", "value2_large_renderer");
     }
-  }
 
-  void OnWebKitInitialized(CefRefPtr<ClientAppRenderer> app) OVERRIDE {
     // Create the renderer-side router for query handling.
     CefMessageRouterConfig config;
     message_router_ = CefMessageRouterRendererSide::Create(config);
@@ -47,21 +44,21 @@
   void OnContextCreated(CefRefPtr<ClientAppRenderer> app,
                         CefRefPtr<CefBrowser> browser,
                         CefRefPtr<CefFrame> frame,
-                        CefRefPtr<CefV8Context> context) OVERRIDE {
+                        CefRefPtr<CefV8Context> context) override {
     message_router_->OnContextCreated(browser, frame, context);
   }
 
   void OnContextReleased(CefRefPtr<ClientAppRenderer> app,
                          CefRefPtr<CefBrowser> browser,
                          CefRefPtr<CefFrame> frame,
-                         CefRefPtr<CefV8Context> context) OVERRIDE {
+                         CefRefPtr<CefV8Context> context) override {
     message_router_->OnContextReleased(browser, frame, context);
   }
 
   void OnFocusedNodeChanged(CefRefPtr<ClientAppRenderer> app,
                             CefRefPtr<CefBrowser> browser,
                             CefRefPtr<CefFrame> frame,
-                            CefRefPtr<CefDOMNode> node) OVERRIDE {
+                            CefRefPtr<CefDOMNode> node) override {
     bool is_editable = (node.get() && node->IsEditable());
     if (is_editable != last_node_is_editable_) {
       // Notify the browser of the change in focused element type.
@@ -77,7 +74,7 @@
                                 CefRefPtr<CefBrowser> browser,
                                 CefRefPtr<CefFrame> frame,
                                 CefProcessId source_process,
-                                CefRefPtr<CefProcessMessage> message) OVERRIDE {
+                                CefRefPtr<CefProcessMessage> message) override {
     return message_router_->OnProcessMessageReceived(browser, frame,
                                                      source_process, message);
   }
diff --git a/src/tests/cefclient/renderer/ipc_performance_test.cc b/src/tests/cefclient/renderer/ipc_performance_test.cc
new file mode 100644
index 0000000..c8b570a
--- /dev/null
+++ b/src/tests/cefclient/renderer/ipc_performance_test.cc
@@ -0,0 +1,251 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "tests/cefclient/renderer/ipc_performance_test.h"
+
+#include "include/cef_shared_process_message_builder.h"
+#include "include/wrapper/cef_helpers.h"
+#include "tests/shared/common/binary_value_utils.h"
+
+namespace {
+
+// JS object member names.
+constexpr char kMessageSize[] = "size";
+constexpr char kTestId[] = "testId";
+constexpr CefV8Value::PropertyAttribute kAttributes =
+    static_cast<CefV8Value::PropertyAttribute>(
+        V8_PROPERTY_ATTRIBUTE_READONLY | V8_PROPERTY_ATTRIBUTE_DONTENUM |
+        V8_PROPERTY_ATTRIBUTE_DONTDELETE);
+
+struct TestInfo {
+  size_t message_size = 0;
+  int id = 0;
+  bool is_valid = false;
+};
+
+TestInfo GetTest(const CefV8ValueList& arguments, CefString& exception) {
+  TestInfo info{};
+
+  if (arguments.size() != 1 || !arguments[0]->IsObject()) {
+    exception = "Invalid arguments; expecting a single object";
+    return info;
+  }
+
+  CefRefPtr<CefV8Value> arg = arguments[0];
+  CefRefPtr<CefV8Value> message_size = arg->GetValue(kMessageSize);
+  if (!message_size.get() || !message_size->IsInt()) {
+    exception =
+        "Invalid arguments; object member 'size' is required and must have "
+        "integer type";
+    return info;
+  }
+
+  if (message_size->GetIntValue() < 1) {
+    exception =
+        "Invalid arguments; object member 'size' must be "
+        "positive";
+    return info;
+  }
+
+  CefRefPtr<CefV8Value> test_id = arg->GetValue(kTestId);
+  if (!message_size.get() || !message_size->IsInt()) {
+    exception =
+        "Invalid arguments; object member 'testId' is required and must "
+        "have integer type";
+    return info;
+  }
+
+  info.message_size = static_cast<size_t>(message_size->GetIntValue());
+  info.id = test_id->GetIntValue();
+  info.is_valid = true;
+
+  return info;
+}
+
+// Handle bindings in the render process.
+class IpcDelegate final : public client::ClientAppRenderer::Delegate {
+ public:
+  class V8HandlerImpl final : public CefV8Handler {
+   public:
+    explicit V8HandlerImpl(const CefRefPtr<IpcDelegate>& delegate)
+        : delegate_(delegate) {}
+    V8HandlerImpl(const V8HandlerImpl&) = delete;
+    V8HandlerImpl& operator=(const V8HandlerImpl&) = delete;
+
+    bool Execute(const CefString& name,
+                 CefRefPtr<CefV8Value> object,
+                 const CefV8ValueList& arguments,
+                 CefRefPtr<CefV8Value>& retval,
+                 CefString& exception) override {
+      if (name == bv_utils::kTestSendProcessMessage) {
+        const auto test = GetTest(arguments, exception);
+        if (test.is_valid) {
+          SendTestProcessMessage(test.message_size, test.id);
+        }
+        return true;
+      }
+
+      if (name == bv_utils::kTestSendSMRProcessMessage) {
+        const auto test = GetTest(arguments, exception);
+        if (test.is_valid) {
+          SendTestSMRProcessMessage(test.message_size, test.id);
+        }
+        return true;
+      }
+
+      return false;
+    }
+
+   private:
+    void SendTestProcessMessage(size_t message_size, int test_id) {
+      auto context = CefV8Context::GetCurrentContext();
+      delegate_->SendTestProcessMessage(context->GetFrame(), message_size,
+                                        test_id);
+    }
+
+    void SendTestSMRProcessMessage(size_t message_size, int test_id) {
+      auto context = CefV8Context::GetCurrentContext();
+      delegate_->SendTestSMRProcessMessage(context->GetFrame(), message_size,
+                                           test_id);
+    }
+
+    CefRefPtr<IpcDelegate> delegate_;
+    IMPLEMENT_REFCOUNTING(V8HandlerImpl);
+  };
+
+  IpcDelegate() = default;
+  IpcDelegate(const IpcDelegate&) = delete;
+  IpcDelegate& operator=(const IpcDelegate&) = delete;
+
+  void OnContextCreated(CefRefPtr<client::ClientAppRenderer> app,
+                        CefRefPtr<CefBrowser> browser,
+                        CefRefPtr<CefFrame> frame,
+                        CefRefPtr<CefV8Context> context) override {
+    CEF_REQUIRE_RENDERER_THREAD();
+
+    CefRefPtr<CefV8Handler> handler = new V8HandlerImpl(this);
+
+    // Register function handlers with the 'window' object.
+    auto window = context->GetGlobal();
+    window->SetValue(
+        bv_utils::kTestSendProcessMessage,
+        CefV8Value::CreateFunction(bv_utils::kTestSendProcessMessage, handler),
+        kAttributes);
+
+    window->SetValue(bv_utils::kTestSendSMRProcessMessage,
+                     CefV8Value::CreateFunction(
+                         bv_utils::kTestSendSMRProcessMessage, handler),
+                     kAttributes);
+  }
+
+  bool OnProcessMessageReceived(CefRefPtr<client::ClientAppRenderer> app,
+                                CefRefPtr<CefBrowser> browser,
+                                CefRefPtr<CefFrame> frame,
+                                CefProcessId source_process,
+                                CefRefPtr<CefProcessMessage> message) override {
+    CEF_REQUIRE_RENDERER_THREAD();
+    const auto finish_time = bv_utils::Now();
+
+    if (message->GetName() == bv_utils::kTestSendProcessMessage) {
+      auto args = message->GetArgumentList();
+      DCHECK_EQ(args->GetSize(), 1U);
+
+      const auto browser_msg =
+          bv_utils::GetBrowserMsgFromBinary(args->GetBinary(0));
+      PassTestResultToJs(frame, finish_time, browser_msg);
+
+      return true;
+    }
+
+    if (message->GetName() == bv_utils::kTestSendSMRProcessMessage) {
+      const auto region = message->GetSharedMemoryRegion();
+      DCHECK(region->IsValid());
+      DCHECK_GE(region->Size(), sizeof(bv_utils::BrowserMessage));
+
+      const auto browser_msg =
+          static_cast<const bv_utils::BrowserMessage*>(region->Memory());
+
+      PassTestResultToJs(frame, finish_time, *browser_msg);
+
+      return true;
+    }
+
+    return false;
+  }
+
+ private:
+  IMPLEMENT_REFCOUNTING(IpcDelegate);
+
+  void SendTestProcessMessage(CefRefPtr<CefFrame> frame,
+                              size_t message_size,
+                              int test_id) {
+    CEF_REQUIRE_RENDERER_THREAD();
+
+    auto process_message =
+        CefProcessMessage::Create(bv_utils::kTestSendProcessMessage);
+    auto args = process_message->GetArgumentList();
+
+    const auto buffer_size =
+        std::max(message_size, sizeof(bv_utils::RendererMessage));
+    std::vector<uint8_t> buffer(buffer_size);
+
+    const auto renderer_msg =
+        reinterpret_cast<bv_utils::RendererMessage*>(buffer.data());
+
+    renderer_msg->test_id = test_id;
+    renderer_msg->start_time = bv_utils::Now();
+
+    args->SetBinary(0, bv_utils::CreateCefBinaryValue(buffer));
+    frame->SendProcessMessage(PID_BROWSER, process_message);
+  }
+
+  void SendTestSMRProcessMessage(CefRefPtr<CefFrame> frame,
+                                 size_t message_size,
+                                 int test_id) {
+    CEF_REQUIRE_RENDERER_THREAD();
+
+    const auto buffer_size =
+        std::max(message_size, sizeof(bv_utils::RendererMessage));
+
+    std::vector<uint8_t> buffer(buffer_size);
+    const auto renderer_msg =
+        reinterpret_cast<bv_utils::RendererMessage*>(buffer.data());
+    renderer_msg->test_id = test_id;
+    renderer_msg->start_time = bv_utils::Now();
+
+    auto builder = CefSharedProcessMessageBuilder::Create(
+        bv_utils::kTestSendSMRProcessMessage, buffer_size);
+
+    bv_utils::CopyDataIntoMemory(buffer, builder->Memory());
+
+    frame->SendProcessMessage(PID_BROWSER, builder->Build());
+  }
+
+  // Execute the onSuccess JavaScript callback.
+  void PassTestResultToJs(CefRefPtr<CefFrame> frame,
+                          const bv_utils::TimePoint& finish_time,
+                          const bv_utils::BrowserMessage& msg) {
+    const auto rendered_to_browser = msg.duration;
+    const auto browser_to_rendered = finish_time - msg.start_time;
+
+    CefString code = "testSendProcessMessageResult(" +
+                     std::to_string(msg.test_id) + ", " +
+                     bv_utils::ToMicroSecString(rendered_to_browser) + ", " +
+                     bv_utils::ToMicroSecString(browser_to_rendered) + ");";
+
+    frame->ExecuteJavaScript(code, frame->GetURL(), 0);
+  }
+};
+
+}  // namespace
+
+namespace client {
+namespace ipc_performance_test {
+
+void CreateDelegates(ClientAppRenderer::DelegateSet& delegates) {
+  delegates.insert(new IpcDelegate());
+}
+
+}  // namespace ipc_performance_test
+}  // namespace client
diff --git a/src/tests/cefclient/renderer/ipc_performance_test.h b/src/tests/cefclient/renderer/ipc_performance_test.h
new file mode 100644
index 0000000..1ba2727
--- /dev/null
+++ b/src/tests/cefclient/renderer/ipc_performance_test.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 CEF_TESTS_CEFCLIENT_RENDERER_IPC_PERFORMANCE_TEST_H_
+#define CEF_TESTS_CEFCLIENT_RENDERER_IPC_PERFORMANCE_TEST_H_
+#pragma once
+
+#include "tests/shared/renderer/client_app_renderer.h"
+
+namespace client {
+namespace ipc_performance_test {
+
+void CreateDelegates(ClientAppRenderer::DelegateSet& delegates);
+
+}  // namespace ipc_performance_test
+}  // namespace client
+
+#endif  // CEF_TESTS_CEFCLIENT_RENDERER_IPC_PERFORMANCE_TEST_H_
diff --git a/src/tests/cefclient/renderer/performance_test.cc b/src/tests/cefclient/renderer/performance_test.cc
index 64fcaaa..8904191 100644
--- a/src/tests/cefclient/renderer/performance_test.cc
+++ b/src/tests/cefclient/renderer/performance_test.cc
@@ -35,7 +35,7 @@
                        CefRefPtr<CefV8Value> object,
                        const CefV8ValueList& arguments,
                        CefRefPtr<CefV8Value>& retval,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
     if (name == kRunPerfTest) {
       if (arguments.size() == 1 && arguments[0]->IsString()) {
         // Run the specified perf test.
@@ -45,9 +45,9 @@
         for (int i = 0; i < kPerfTestsCount; ++i) {
           if (test == kPerfTests[i].name) {
             // Execute the test.
-            int64 delta = kPerfTests[i].test(kPerfTests[i].iterations);
+            int64_t delta = kPerfTests[i].test(kPerfTests[i].iterations);
 
-            retval = CefV8Value::CreateInt(delta);
+            retval = CefV8Value::CreateInt(static_cast<int32_t>(delta));
             found = true;
             break;
           }
@@ -74,8 +74,7 @@
       if (arguments.size() == 0) {
         retval = CefV8Value::CreateInt(1);
       } else if (arguments.size() == 1 && arguments[0]->IsInt()) {
-        int32 type = arguments[0]->GetIntValue();
-        CefTime date;
+        int32_t type = arguments[0]->GetIntValue();
         switch (type) {
           case 0:
             retval = CefV8Value::CreateUndefined();
@@ -96,8 +95,7 @@
             retval = CefV8Value::CreateDouble(1.234);
             break;
           case 6:
-            date.Now();
-            retval = CefV8Value::CreateDate(date);
+            retval = CefV8Value::CreateDate(CefBaseTime::Now());
             break;
           case 7:
             retval = CefV8Value::CreateString("Hello, world!");
@@ -133,7 +131,7 @@
   virtual void OnContextCreated(CefRefPtr<ClientAppRenderer> app,
                                 CefRefPtr<CefBrowser> browser,
                                 CefRefPtr<CefFrame> frame,
-                                CefRefPtr<CefV8Context> context) OVERRIDE {
+                                CefRefPtr<CefV8Context> context) override {
     CefRefPtr<CefV8Value> object = context->GetGlobal();
 
     CefRefPtr<CefV8Handler> handler = new V8Handler();
diff --git a/src/tests/cefclient/renderer/performance_test_setup.h b/src/tests/cefclient/renderer/performance_test_setup.h
index 7427a55..5ed34b3 100644
--- a/src/tests/cefclient/renderer/performance_test_setup.h
+++ b/src/tests/cefclient/renderer/performance_test_setup.h
@@ -24,7 +24,7 @@
 #define PERF_TEST_ENTRY(name) PERF_TEST_ENTRY_EX(name, kDefaultIterations)
 
 // Test function declaration.
-#define PERF_TEST_RESULT int64
+#define PERF_TEST_RESULT int64_t
 #define PERF_TEST_PARAM_ITERATIONS iterations
 #define PERF_TEST_PARAMS int PERF_TEST_PARAM_ITERATIONS
 #define PERF_TEST_FUNC(name) \
@@ -51,7 +51,7 @@
     running_ = false;
   }
 
-  int64 Delta() {
+  int64_t Delta() {
     DCHECK(!running_);
     return start_.Delta(stop_);
   }
@@ -78,7 +78,7 @@
 
 // Perform test iterations and return the timing result.
 #define PERF_ITERATIONS_START() \
-  int64 _result = 0;            \
+  int64_t _result = 0;          \
   PERF_ITERATIONS_START_EX()
 
 #define PERF_ITERATIONS_END()     \
diff --git a/src/tests/cefclient/renderer/performance_test_tests.cc b/src/tests/cefclient/renderer/performance_test_tests.cc
index 010fcf9..b94df36 100644
--- a/src/tests/cefclient/renderer/performance_test_tests.cc
+++ b/src/tests/cefclient/renderer/performance_test_tests.cc
@@ -44,7 +44,11 @@
 }
 
 PERF_TEST_FUNC(V8DateCreate) {
-  static cef_time_t time = {2012, 1, 0, 1};
+  static cef_time_t time_exploded = {2012, 1, 0, 1};
+
+  cef_basetime_t basetime;
+  cef_time_to_basetime(&time_exploded, &basetime);
+  CefBaseTime time(basetime);
 
   PERF_ITERATIONS_START()
   CefRefPtr<CefV8Value> value = CefV8Value::CreateDate(time);
@@ -93,7 +97,7 @@
                          CefRefPtr<CefV8Value> object,
                          const CefV8ValueList& arguments,
                          CefRefPtr<CefV8Value>& retval,
-                         CefString& exception) OVERRIDE {
+                         CefString& exception) override {
       return false;
     }
     IMPLEMENT_REFCOUNTING(Handler);
@@ -115,7 +119,7 @@
                          CefRefPtr<CefV8Value> object,
                          const CefV8ValueList& arguments,
                          CefRefPtr<CefV8Value>& retval,
-                         CefString& exception) OVERRIDE {
+                         CefString& exception) override {
       return true;
     }
     IMPLEMENT_REFCOUNTING(Handler);
@@ -140,7 +144,7 @@
                          CefRefPtr<CefV8Value> object,
                          const CefV8ValueList& arguments,
                          CefRefPtr<CefV8Value>& retval,
-                         CefString& exception) OVERRIDE {
+                         CefString& exception) override {
       return true;
     }
     IMPLEMENT_REFCOUNTING(Handler);
@@ -171,13 +175,13 @@
     virtual bool Get(const CefString& name,
                      const CefRefPtr<CefV8Value> object,
                      CefRefPtr<CefV8Value>& retval,
-                     CefString& exception) OVERRIDE {
+                     CefString& exception) override {
       return true;
     }
     virtual bool Set(const CefString& name,
                      const CefRefPtr<CefV8Value> object,
                      const CefRefPtr<CefV8Value> value,
-                     CefString& exception) OVERRIDE {
+                     CefString& exception) override {
       return true;
     }
     IMPLEMENT_REFCOUNTING(Accessor);
@@ -197,25 +201,25 @@
     virtual bool Get(const CefString& name,
                      const CefRefPtr<CefV8Value> object,
                      CefRefPtr<CefV8Value>& retval,
-                     CefString& exception) OVERRIDE {
+                     CefString& exception) override {
       return true;
     }
     virtual bool Get(int index,
                      const CefRefPtr<CefV8Value> object,
                      CefRefPtr<CefV8Value>& retval,
-                     CefString& exception) OVERRIDE {
+                     CefString& exception) override {
       return true;
     }
     virtual bool Set(const CefString& name,
                      const CefRefPtr<CefV8Value> object,
                      const CefRefPtr<CefV8Value> value,
-                     CefString& exception) OVERRIDE {
+                     CefString& exception) override {
       return true;
     }
     virtual bool Set(int index,
                      const CefRefPtr<CefV8Value> object,
                      const CefRefPtr<CefV8Value> value,
-                     CefString& exception) OVERRIDE {
+                     CefString& exception) override {
       return true;
     }
     IMPLEMENT_REFCOUNTING(Interceptor);
@@ -257,13 +261,13 @@
     virtual bool Get(const CefString& name,
                      const CefRefPtr<CefV8Value> object,
                      CefRefPtr<CefV8Value>& retval,
-                     CefString& exception) OVERRIDE {
+                     CefString& exception) override {
       return true;
     }
     virtual bool Set(const CefString& name,
                      const CefRefPtr<CefV8Value> object,
                      const CefRefPtr<CefV8Value> value,
-                     CefString& exception) OVERRIDE {
+                     CefString& exception) override {
       val_ = value;
       return true;
     }
@@ -291,14 +295,14 @@
     virtual bool Get(const CefString& name,
                      const CefRefPtr<CefV8Value> object,
                      CefRefPtr<CefV8Value>& retval,
-                     CefString& exception) OVERRIDE {
+                     CefString& exception) override {
       retval = val_;
       return true;
     }
     virtual bool Set(const CefString& name,
                      const CefRefPtr<CefV8Value> object,
                      const CefRefPtr<CefV8Value> value,
-                     CefString& exception) OVERRIDE {
+                     CefString& exception) override {
       return true;
     }
     CefRefPtr<CefV8Value> val_;
diff --git a/src/tests/cefclient/resources/binary_transfer.html b/src/tests/cefclient/resources/binary_transfer.html
new file mode 100644
index 0000000..947769e
--- /dev/null
+++ b/src/tests/cefclient/resources/binary_transfer.html
@@ -0,0 +1,498 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8" />
+    <title>Binary vs String Transfer Benchmark</title>
+    <script src="https://cdn.plot.ly/plotly-2.26.0.min.js"></script>
+    <style>
+      body {
+        font-family: Tahoma, Serif;
+        font-size: 10pt;
+      }
+      .info {
+        font-size: 12pt;
+      }
+      .left {
+        text-align: left;
+      }
+      .right {
+        text-align: right;
+      }
+      .positive {
+        color: green;
+        font-weight: bold;
+      }
+      .negative {
+        color: red;
+        font-weight: bold;
+      }
+      .center {
+        text-align: center;
+      }
+      table.resultTable {
+        border: 1px solid black;
+        border-collapse: collapse;
+        empty-cells: show;
+        width: 100%;
+      }
+      table.resultTable td {
+        padding: 2px 4px;
+        border: 1px solid black;
+      }
+      table.resultTable > thead > tr {
+        font-weight: bold;
+        background: lightblue;
+      }
+      table.resultTable > tbody > tr:nth-child(odd) {
+        background: white;
+      }
+      table.resultTable > tbody > tr:nth-child(even) {
+        background: lightgray;
+      }
+      .hide {
+        display: none;
+      }
+    </style>
+  </head>
+
+  <body background-color="white">
+    <h1>Binary vs String Transfer Benchmark</h1>
+
+    <table>
+      <tr>
+        <td>
+          <p class="info">
+            This benchmark evaluates the message transfer speed between the
+            renderer process and the browser process. <br />It compares the
+            performance of binary and string message transfer.
+          </p>
+          <p class="info">
+            <b>Note:</b> There is no progress indication of the tests because it
+            significantly influences measurements. <br />It usually takes 30
+            seconds (for 300 samples) to complete the tests.
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td>
+          Samples:
+          <input
+            id="sSamples"
+            type="text"
+            value="300"
+            required
+            pattern="[0-9]+"
+          />
+          <button id="sRun" autofocus onclick="runTestSuite()">Run</button>
+        </td>
+      </tr>
+    </table>
+
+    <div style="padding-top: 10px; padding-bottom: 10px">
+      <table id="resultTable" class="resultTable">
+        <thead>
+          <tr>
+            <td class="center" style="width: 8%">Message Size</td>
+            <td class="center" style="width: 8%">
+              String Round Trip Avg,&nbsp;ms
+            </td>
+            <td class="center" style="width: 8%">
+              Binary Round Trip Avg,&nbsp;ms
+            </td>
+            <td class="center" style="width: 10%">Relative Trip Difference</td>
+            <td class="center" style="width: 8%">String Speed,&nbsp;MB/s</td>
+            <td class="center" style="width: 8%">Binary Speed,&nbsp;MB/s</td>
+            <td class="center" style="width: 10%">Relative Speed Difference</td>
+            <td class="center" style="width: 8%">String Standard Deviation</td>
+            <td class="center" style="width: 8%">Binary Standard Deviation</td>
+          </tr>
+        </thead>
+        <tbody>
+          <!-- result rows here -->
+        </tbody>
+      </table>
+    </div>
+
+    <div id="round_trip_avg_chart">
+      <!-- Average round trip linear chart will be drawn inside this DIV -->
+    </div>
+
+    <div id="box_plot_chart">
+      <!-- Box plot of round trip time will be drawn inside this DIV -->
+    </div>
+
+    <script type="text/javascript">
+      let tests = [];
+      let box_plot_test_data = [];
+      let round_trip_avg_plot_data = [];
+
+      function nextTestSuite(testIndex) {
+        const nextTestIndex = testIndex + 1;
+        setTimeout(execTestSuite, 0, nextTestIndex);
+      }
+
+      function generateRandomString(size) {
+        // Symbols that will be encoded as two bytes in UTF-8
+        // so we compare transfer of the same amount of bytes
+        const characters =
+          "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя";
+        let randomString = "";
+        for (let i = 0; i < size; i++) {
+          const randomIndex = Math.floor(Math.random() * characters.length);
+          randomString += characters.charAt(randomIndex);
+        }
+        return randomString;
+      }
+
+      function generateRandomArrayBuffer(size) {
+        const buffer = new ArrayBuffer(size);
+        const uint8Array = new Uint8Array(buffer);
+        for (let i = 0; i < uint8Array.length; i++) {
+          uint8Array[i] = Math.floor(Math.random() * 256);
+        }
+        return buffer;
+      }
+
+      function reportError(errorCode, errorMessage) {
+        console.error(`ErrorCode:${errorCode} Message:${errorMessage}`);
+      }
+
+      function sendString(size, testIndex) {
+        const request = generateRandomString(size);
+        const startTime = performance.now();
+        const onSuccess = (response) => {
+          const roundTrip = performance.now() - startTime;
+          const test = tests[testIndex];
+          test.totalRoundTrip += roundTrip;
+          test.sample++;
+          box_plot_test_data[testIndex].x.push(roundTrip);
+          setTimeout(execTest, 0, testIndex);
+        };
+
+        window.cefQuery({
+          request: request,
+          onSuccess: onSuccess,
+          onFailure: reportError,
+        });
+      }
+
+      function sendArrayBuffer(size, testIndex) {
+        const request = generateRandomArrayBuffer(size);
+        const startTime = performance.now();
+        const onSuccess = (response) => {
+          const roundTrip = performance.now() - startTime;
+          const test = tests[testIndex];
+          test.totalRoundTrip += roundTrip;
+          test.sample++;
+          box_plot_test_data[testIndex].x.push(roundTrip);
+          setTimeout(execTest, 0, testIndex);
+        };
+
+        window.cefQuery({
+          request: request,
+          onSuccess: onSuccess,
+          onFailure: reportError,
+        });
+      }
+
+      function getStandardDeviation(array, mean) {
+        const n = array.length;
+        if (n < 5) return null;
+        return Math.sqrt(
+          array.map((x) => Math.pow(x - mean, 2)).reduce((a, b) => a + b) /
+            (n - 1)
+        );
+      }
+
+      function execTest(testIndex) {
+        const test = tests[testIndex];
+        if (test.sample >= test.totalSamples) {
+          return nextTestSuite(testIndex);
+        }
+        test.func(test.length, test.index);
+      }
+
+      function column(prepared, value) {
+        return (
+          "<td class='right'>" + (!prepared ? "-" : value.toFixed(3)) + "</td>"
+        );
+      }
+
+      function relativeDiffColumn(prepared, value, isBiggerBetter) {
+        if (!prepared) return "<td class='right'>-</td>";
+
+        const isPositive = value >= 0 == isBiggerBetter;
+        return [
+          "<td class='right ",
+          isPositive ? "positive" : "negative",
+          "'>",
+          value > 0 ? "+" : "",
+          value.toFixed(2),
+          "%</td>",
+        ].join("");
+      }
+
+      function displayResult(test) {
+        const id = "testResultRow_" + test.index;
+
+        const markup = [
+          "<tr id='",
+          id,
+          "'>",
+          "<td class='left'>",
+          test.name,
+          "</td>",
+          column(test.prepared, test.avgRoundTrip),
+          column(test.prepared, test.avgRoundTripBin),
+          relativeDiffColumn(test.prepared, test.relativeTripDiff, false),
+          column(test.prepared, test.speed),
+          column(test.prepared, test.speedBinary),
+          relativeDiffColumn(test.prepared, test.relativeSpeedDiff, true),
+          "<td class='right'>",
+          !test.prepared || test.stdDeviation == null
+            ? "-"
+            : test.stdDeviation.toFixed(3),
+          "</td>",
+          "<td class='right'>",
+          !test.prepared || test.stdDeviationBinary == null
+            ? "-"
+            : test.stdDeviationBinary.toFixed(3),
+          "</td>",
+          "</tr>",
+        ].join("");
+
+        const row = document.getElementById(id);
+        if (row) {
+          row.outerHTML = markup;
+        } else {
+          const tbody = document.getElementById("resultTable").tBodies[0];
+          tbody.insertAdjacentHTML("beforeEnd", markup);
+        }
+      }
+      function relativeDiff(left, right) {
+        if (right != 0) {
+          return ((left - right) / right) * 100;
+        }
+        return 0;
+      }
+
+      function buildTestResults(tests) {
+        testResults = [];
+
+        let oldRoundTrip = {
+          x: [],
+          y: [],
+          type: "scatter",
+          name: "String",
+        };
+
+        let newRoundTrip = {
+          x: [],
+          y: [],
+          type: "scatter",
+          name: "Binary",
+        };
+
+        for (let i = 0; i < tests.length / 2; i++) {
+          const index = testResults.length;
+
+          // Tests are in pairs - String and Binary
+          const test = tests[i * 2];
+          const testBin = tests[i * 2 + 1];
+
+          const avgRoundTrip = test.totalRoundTrip / test.totalSamples;
+          const avgRoundTripBin = testBin.totalRoundTrip / testBin.totalSamples;
+          const relativeTripDiff = relativeDiff(avgRoundTripBin, avgRoundTrip);
+
+          // In MB/s
+          const speed = test.byteSize / (avgRoundTrip * 1000);
+          const speedBinary = testBin.byteSize / (avgRoundTripBin * 1000);
+          const relativeSpeedDiff = relativeDiff(speedBinary, speed);
+
+          const stdDeviation = getStandardDeviation(
+            box_plot_test_data[test.index].x,
+            avgRoundTrip
+          );
+          const stdDeviationBinary = getStandardDeviation(
+            box_plot_test_data[testBin.index].x,
+            avgRoundTripBin
+          );
+
+          testResults.push({
+            name: humanFileSize(test.byteSize),
+            index: index,
+            prepared: true,
+            avgRoundTrip: avgRoundTrip,
+            avgRoundTripBin: avgRoundTripBin,
+            relativeTripDiff: relativeTripDiff,
+            speed: speed,
+            speedBinary: speedBinary,
+            relativeSpeedDiff: relativeSpeedDiff,
+            stdDeviation: stdDeviation,
+            stdDeviationBinary: stdDeviationBinary,
+          });
+
+          oldRoundTrip.x.push(test.byteSize);
+          newRoundTrip.x.push(test.byteSize);
+          oldRoundTrip.y.push(avgRoundTrip);
+          newRoundTrip.y.push(avgRoundTripBin);
+        }
+
+        round_trip_avg_plot_data = [oldRoundTrip, newRoundTrip];
+        return testResults;
+      }
+
+      function buildEmptyTestResults(tests) {
+        testResults = [];
+        for (let i = 0; i < tests.length / 2; i++) {
+          const index = testResults.length;
+          const test = tests[i * 2];
+
+          testResults.push({
+            name: humanFileSize(test.byteSize),
+            index: index,
+            prepared: false,
+          });
+        }
+        return testResults;
+      }
+
+      function resetTestsResults(totalSamples) {
+        if (totalSamples <= 0) totalSamples = 1;
+
+        // Reset tests results
+        tests.forEach((test) => {
+          test.sample = 0;
+          test.totalRoundTrip = 0;
+          test.totalSamples = totalSamples;
+        });
+
+        testResults = buildEmptyTestResults(tests);
+        testResults.forEach((result) => displayResult(result));
+
+        round_trip_avg_plot_data = [];
+        box_plot_test_data.forEach((data) => {
+          data.x = [];
+        });
+      }
+
+      function queueTest(name, byteSize, length, testFunc) {
+        const testIndex = tests.length;
+        test = {
+          name: name,
+          byteSize: byteSize,
+          length: length,
+          index: testIndex,
+          sample: 0,
+          totalRoundTrip: 0,
+          func: testFunc,
+        };
+        tests.push(test);
+
+        box_plot_test_data.push({
+          x: [],
+          type: "box",
+          boxpoints: "all",
+          name: name,
+          jitter: 0.3,
+          pointpos: -1.8,
+        });
+      }
+
+      function execTestSuite(testIndex) {
+        if (testIndex < tests.length) {
+          execTest(testIndex);
+        } else {
+          testsRunFinished();
+        }
+      }
+
+      function startTests() {
+        // Let the updated table render before starting the tests
+        setTimeout(execTestSuite, 200, 0);
+      }
+
+      function execQueuedTests(totalSamples) {
+        resetTestsResults(totalSamples);
+        startTests();
+      }
+
+      function setSettingsState(disabled) {
+        document.getElementById("sSamples").disabled = disabled;
+        document.getElementById("sRun").disabled = disabled;
+      }
+
+      function testsRunFinished() {
+        testResults = buildTestResults(tests);
+        testResults.forEach((result) => displayResult(result));
+
+        const round_trip_layout = {
+          title: "Average round trip, μs (Smaller Better)",
+        };
+        Plotly.newPlot(
+          "round_trip_avg_chart",
+          round_trip_avg_plot_data,
+          round_trip_layout
+        );
+
+        const box_plot_layout = {
+          title: "Round Trip Time, μs",
+        };
+        Plotly.newPlot("box_plot_chart", box_plot_test_data, box_plot_layout);
+        setSettingsState(false);
+      }
+
+      function humanFileSize(bytes) {
+        const step = 1024;
+        const originalBytes = bytes;
+
+        if (Math.abs(bytes) < step) {
+          return bytes + " B";
+        }
+
+        const units = [" KB", " MB", " GB"];
+        let u = -1;
+        let count = 0;
+
+        do {
+          bytes /= step;
+          u += 1;
+          count += 1;
+        } while (Math.abs(bytes) >= step && u < units.length - 1);
+
+        return bytes.toString() + units[u];
+      }
+
+      window.runTestSuite = () => {
+        Plotly.purge("round_trip_avg_chart");
+        Plotly.purge("box_plot_chart");
+        setSettingsState(true);
+        const totalSamples = parseInt(
+          document.getElementById("sSamples").value
+        );
+        execQueuedTests(totalSamples);
+      };
+
+      const totalSamples = parseInt(document.getElementById("sSamples").value);
+      queueTest("Empty String", 0, 0, sendString);
+      queueTest("Empty Binary", 0, 0, sendArrayBuffer);
+      for (let byteSize = 8; byteSize <= 512 * 1024; byteSize *= 2) {
+        // Byte size of a string is twice its length because of UTF-16 encoding
+        const stringLen = byteSize / 2;
+        queueTest(
+          humanFileSize(byteSize) + " String",
+          byteSize,
+          stringLen,
+          sendString
+        );
+        queueTest(
+          humanFileSize(byteSize) + " Binary",
+          byteSize,
+          byteSize,
+          sendArrayBuffer
+        );
+      }
+      resetTestsResults(totalSamples);
+    </script>
+  </body>
+</html>
diff --git a/src/tests/cefclient/resources/dialogs.html b/src/tests/cefclient/resources/dialogs.html
index fb1321c..537011a 100644
--- a/src/tests/cefclient/resources/dialogs.html
+++ b/src/tests/cefclient/resources/dialogs.html
@@ -65,10 +65,13 @@
 <br/><input type="button" onclick="show_alert();" value="Show Alert">
 <br/><input type="button" onclick="show_confirm();" value="Show Confirm"> <span id="cm"></span>
 <br/><input type="button" onclick="show_prompt();" value="Show Prompt"> <span id="pm"></span>
-<br/>input type="file": <input type="file" name="pic" accept="text/*,.js,.css,image/*">
+<br/>input type="file" (.png): <input type="file" name="pic" accept=".png">
+<br/>input type="file" (image/*): <input type="file" name="pic" accept="image/*">
+<br/>input type="file" (multiple types): <input type="file" name="pic" accept="text/*,.js,.css,image/*">
 <br/>input type="file" (directory): <input type="file" webkitdirectory  accept="text/*,.js,.css,image/*">
-<br/><input type="button" onclick="show_file_dialog('fo', 'FileOpen');" value="Show File Open" disabled="true"> <span id="fo"></span>
-<br/><input type="button" onclick="show_file_dialog('fom', 'FileOpenMultiple');" value="Show File Open Multiple" disabled="true"> <span id="fom"></span>
+<br/><input type="button" onclick="show_file_dialog('fop', 'FileOpenPng');" value="Show File Open (.png)" disabled="true"> <span id="fop"></span>
+<br/><input type="button" onclick="show_file_dialog('foi', 'FileOpenImage');" value="Show File Open (image/*)" disabled="true"> <span id="foi"></span>
+<br/><input type="button" onclick="show_file_dialog('fom', 'FileOpenMultiple');" value="Show File Open (multiple types/files)" disabled="true"> <span id="fom"></span>
 <br/><input type="button" onclick="show_file_dialog('fof', 'FileOpenFolder');" value="Show File Open Folder" disabled="true"> <span id="fof"></span>
 <br/><input type="button" onclick="show_file_dialog('fs', 'FileSave');" value="Show File Save" disabled="true"> <span id="fs"></span>
 <p id="time"></p>
diff --git a/src/tests/cefclient/resources/draggable.html b/src/tests/cefclient/resources/draggable.html
index 6b1ecf0..354ed57 100644
--- a/src/tests/cefclient/resources/draggable.html
+++ b/src/tests/cefclient/resources/draggable.html
@@ -2,6 +2,24 @@
 <head>
 <title>Draggable Regions Test</title>
 <style>
+html, body {
+  height: 100%;
+  overflow: hidden;
+}
+.draggable-title {
+  -webkit-app-region: drag;
+  position: absolute;
+  top: 0px;
+  left: 0px;
+  width: 100%;
+  height: 34px;
+  background-color: white;
+  opacity: .5;
+}
+.content {
+  margin-top: 34px;
+  background-color: white;
+}
 .draggable {
   -webkit-app-region: drag;
   position: absolute;
@@ -23,10 +41,13 @@
 }
 </style>
 </head>
-<body bgcolor="white">
+<body>
+  <div class="draggable-title"></div>
+  <div class="content">
   Draggable regions can be defined using the -webkit-app-region CSS property.
   <br/>In the below example the red region is draggable and the blue sub-region is non-draggable.
   <br/>Windows can be resized by default and closed using JavaScript <a href="#" onClick="window.close(); return false;">window.close()</a>.
+  </div>
   <div class="draggable">
     <div class="nondraggable"></div>
   </div>
diff --git a/src/tests/cefclient/resources/drm.html b/src/tests/cefclient/resources/drm.html
deleted file mode 100644
index cfb1cc0..0000000
--- a/src/tests/cefclient/resources/drm.html
+++ /dev/null
@@ -1,141 +0,0 @@
-<html>
-<head>
-<title>DRM Test</title>
-<script language="JavaScript">
-
-function setup() {
-  if (location.hostname == 'tests' || location.hostname == 'localhost')
-    return;
-
-  alert('This page can only be run from tests or localhost.');
-
-  // Disable all elements.
-  var elements = document.getElementById("form").elements;
-  for (var i = 0, element; element = elements[i++]; ) {
-    element.disabled = true;
-  }
-
-  doTest();
-}
-
-// Based on DRM detection code from https://github.com/google/shaka-player
-function probeSupport() {
-  var tests = [];
-  var testKeySystems = [
-    'org.w3.clearkey',
-    'com.widevine.alpha',
-  ];
-
-  var basicVideoCapabilities = [
-    { contentType: 'video/mp4; codecs="avc1.42E01E"' },
-    { contentType: 'video/webm; codecs="vp9"' }
-  ];
-
-  var basicConfig = {
-    videoCapabilities: basicVideoCapabilities
-  };
-  var offlineConfig = {
-    videoCapabilities: basicVideoCapabilities,
-    persistentState: 'required',
-    sessionTypes: ['persistent-license']
-  };
-
-  // Try the offline config first, then fall back to the basic config.
-  var configs = [offlineConfig, basicConfig];
-
-  var support = {};
-  testKeySystems.forEach(function(keySystem) {
-    var p = navigator.requestMediaKeySystemAccess(keySystem, configs)
-        .then(function(access) {
-          // We can't (yet) trust every browser to report the session types they
-          // support in access.getConfiguration().  Therefore, we create a
-          // MediaKeys object and try to create an offline session.
-          // https://goo.gl/gtYT3z, https://goo.gl/rvnB1g, https://goo.gl/z0URJ0
-          var mediaKeys = access.createMediaKeys();
-          var persistentState = false;
-          try {
-            // This will throw if persistent licenses are not supported.
-            mediaKeys.createSession('persistent-license');
-            persistentState = true;
-          } catch (e) {}
-
-          support[keySystem] = {persistentState: persistentState};
-        }, function() {
-          support[keySystem] = null;
-        });
-    tests.push(p);
-  });
-
-  return Promise.all(tests).then(function() {
-    return support;
-  });
-}
-
-function getWidevineCdmInfo() {
-  if (!('Widevine Content Decryption Module' in navigator.plugins)) {
-    return "Widevine CDM plugin not loaded.";
-  }
-
-  var plugin = navigator.plugins['Widevine Content Decryption Module'];
-  return "Widevine CDM plugin:\n" + JSON.stringify({
-    "name": plugin.name,
-    "filename": plugin.filename,
-    "description": plugin.description,
-  }, null, '  ')
-}
-
-function printSupport(support) {
-  var output = document.getElementById('output');
-  output.textContent = getWidevineCdmInfo() + "\n\nDRM Support:\n" + support;
-}
-
-function doTest() {
-  probeSupport().then(function(support) {
-    printSupport(JSON.stringify(support, null, '  '));
-  });
-}
-
-// Send a message to the browser process.
-function sendMessage() {
-  // Create the request object.
-  var request = {};
-  request.widevine_cdm_path =
-      document.getElementById("widevine_cdm_path").value;
-
-  // Results in a call to the OnQuery method in drm_test.cc
-  window.cefQuery({
-    request: JSON.stringify(request),
-    onSuccess: function(response) {
-      alert('Widevine CDM plugin loaded successfully!');
-      // Registration succeeded so test again.
-      doTest();
-    },
-    onFailure: function(error_code, error_message) {
-      alert(error_message + ' (' + error_code + ')');
-    }
-  });
-}
-
-</script>
-
-</head>
-<body bgcolor="white" onload="setup()">
-Important notes:
-<ul>
-<li>Clearkey support is built in and should always be enabled.</li>
-<li>Widevine support requires CDM binaries that must be downloaded from Google. Contact Google <a href="https://www.widevine.com/contact.html">here</a> for details.</li>
-<li>Widevine support is enabled by calling the CefRegisterWidevineCdm() function. See comments in cef_web_plugin.h for usage.</li>
-<li>The CefRegisterWidevineCdm() function can be called during runtime on Windows and OS X to register Widevine binaries. Use the below form to test this capability.</li>
-<li>Calling CefRegisterWidevineCdm() before CefInitialize() is required on Linux.</li>
-<li>Cefclient will call CefRegisterWidevineCdm() before CefInitialize() if "--widevine-cdm-path=&lt;path&gt;" is specified on the command-line.</li>
-<li>View extended media support information <a href="https://shaka-player-demo.appspot.com/support.html">here</a>.</li>
-<li>Test DRM video playback <a href="https://shaka-player-demo.appspot.com/demo/">here</a>. Select an "asset" that includes Clearkey or Widevine in the name.</li>
-</ul>
-
-<form id="form">
-Widevine CDM Path: <input type="text" id="widevine_cdm_path" value="" size="40">
-<input type="button" onclick="sendMessage();" value="Load CDM">
-</form>
-<pre id="output"></pre>
-</body>
-</html>
diff --git a/src/tests/cefclient/resources/ipc_performance.html b/src/tests/cefclient/resources/ipc_performance.html
new file mode 100644
index 0000000..35e42b8
--- /dev/null
+++ b/src/tests/cefclient/resources/ipc_performance.html
@@ -0,0 +1,434 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8" />
+    <title>IPC Performance Tests</title>
+    <script src="https://cdn.plot.ly/plotly-2.26.0.min.js"></script>
+    <style>
+      body {
+        font-family: Tahoma, Serif;
+        font-size: 10pt;
+      }
+
+      .left {
+        text-align: left;
+      }
+
+      .right {
+        text-align: right;
+      }
+
+      .positive {
+        color: green;
+        font-weight: bold;
+      }
+
+      .negative {
+        color: red;
+        font-weight: bold;
+      }
+
+      .center {
+        text-align: center;
+      }
+
+      table.resultTable {
+        border: 1px solid black;
+        border-collapse: collapse;
+        empty-cells: show;
+        width: 100%;
+      }
+
+      table.resultTable td {
+        padding: 2px 4px;
+        border: 1px solid black;
+      }
+
+      table.resultTable > thead > tr {
+        font-weight: bold;
+        background: lightblue;
+      }
+
+      table.resultTable > tbody > tr:nth-child(odd) {
+        background: white;
+      }
+
+      table.resultTable > tbody > tr:nth-child(even) {
+        background: lightgray;
+      }
+
+      .hide {
+        display: none;
+      }
+    </style>
+  </head>
+
+  <body background-color="white">
+    <h1>IPC Performance Tests</h1>
+
+    <table>
+      <tr>
+        <td>
+          <p>
+            There is no progress indication of the tests because it
+            significantly influences measurements. <br />It usually takes 15
+            seconds (for 1000 samples) to complete the tests. <br /><b>AL</b> -
+            ArgumentList-based process messages. <b>SM</b> -
+            SharedMemoryRegion-based process messages.
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td>
+          Samples:
+          <input
+            id="sSamples"
+            type="text"
+            value="1000"
+            required
+            pattern="[0-9]+"
+          />
+          <button id="sRun" autofocus onclick="runTestSuite()">Run</button>
+        </td>
+      </tr>
+    </table>
+
+    <div style="padding-top: 10px; padding-bottom: 10px">
+      <table id="resultTable" class="resultTable">
+        <thead>
+          <tr>
+            <td class="center" style="width: 8%">Message Size</td>
+            <td class="center" style="width: 8%">AL Round Trip Avg,&nbsp;μs</td>
+            <td class="center" style="width: 8%">SM Round Trip Avg,&nbsp;μs</td>
+            <td class="center" style="width: 10%">Relative Trip Difference</td>
+            <td class="center" style="width: 8%">AL Speed,&nbsp;MB/s</td>
+            <td class="center" style="width: 8%">SM Speed,&nbsp;MB/s</td>
+            <td class="center" style="width: 10%">Relative Speed Difference</td>
+            <td class="center" style="width: 8%">AL Standard Deviation</td>
+            <td class="center" style="width: 8%">SM Standard Deviation</td>
+          </tr>
+        </thead>
+        <tbody>
+          <!-- result rows here -->
+        </tbody>
+      </table>
+    </div>
+
+    <div id="round_trip_avg_chart">
+      <!-- Average round trip linear chart will be drawn inside this DIV -->
+    </div>
+
+    <div id="box_plot_chart">
+      <!-- Box plot of round trip time will be drawn inside this DIV -->
+    </div>
+
+    <script type="text/javascript">
+      let tests = [];
+      let box_plot_test_data = [];
+      let round_trip_avg_plot_data = [];
+
+      function testSendProcessMessageResult(
+        testIndex,
+        fromRendererToBrowser,
+        fromBrowserToRenderer
+      ) {
+        const test = tests[testIndex];
+        const roundTrip = fromRendererToBrowser + fromBrowserToRenderer;
+        test.totalRoundTrip += roundTrip;
+        test.sample++;
+        box_plot_test_data[testIndex].x.push(roundTrip);
+
+        setTimeout(execTest, 0, testIndex);
+      }
+
+      function sendRequest(size, testIndex) {
+        window.testSendProcessMessage({
+          size: size,
+          testId: testIndex,
+        });
+      }
+
+      function sendSMRRequest(size, testIndex) {
+        window.testSendSMRProcessMessage({
+          size: size,
+          testId: testIndex,
+        });
+      }
+
+      function getStandardDeviation(array, mean) {
+        const n = array.length;
+        if (n < 5) return null;
+        return Math.sqrt(
+          array.map((x) => Math.pow(x - mean, 2)).reduce((a, b) => a + b) /
+            (n - 1)
+        );
+      }
+
+      function execTest(testIndex) {
+        const test = tests[testIndex];
+
+        if (test.sample >= test.totalSamples) {
+          setTimeout(execNextTest, 0, testIndex);
+        } else {
+          test.func(test.messageSize, test.index);
+        }
+      }
+
+      function column(prepared, value) {
+        return (
+          "<td class='right'>" + (!prepared ? "-" : value.toFixed(2)) + "</td>"
+        );
+      }
+
+      function relativeDiffColumn(prepared, value, isBiggerBetter) {
+        if (!prepared) return "<td class='right'>-</td>";
+
+        const isPositive = value > 0 == isBiggerBetter;
+        return [
+          "<td class='right ",
+          isPositive ? "positive" : "negative",
+          "'>",
+          value > 0 ? "+" : "",
+          value.toFixed(2),
+          "%</td>",
+        ].join("");
+      }
+
+      function displayResult(test) {
+        const id = "testResultRow_" + test.index;
+
+        const markup = [
+          "<tr id='",
+          id,
+          "'>",
+          "<td class='left'>",
+          test.name,
+          "</td>",
+          column(test.prepared, test.avgRoundTrip),
+          column(test.prepared, test.avgRoundTripSMR),
+          relativeDiffColumn(test.prepared, test.relativeTripDiff, false),
+          column(test.prepared, test.speed),
+          column(test.prepared, test.speedSMR),
+          relativeDiffColumn(test.prepared, test.relativeSpeedDiff, true),
+          "<td class='right'>",
+          !test.prepared || test.stdDeviation == null
+            ? "-"
+            : test.stdDeviation.toFixed(2),
+          "</td>",
+          "<td class='right'>",
+          !test.prepared || test.stdDeviationSMR == null
+            ? "-"
+            : test.stdDeviationSMR.toFixed(2),
+          "</td>",
+          "</tr>",
+        ].join("");
+
+        const row = document.getElementById(id);
+        if (row) {
+          row.outerHTML = markup;
+        } else {
+          const tbody = document.getElementById("resultTable").tBodies[0];
+          tbody.insertAdjacentHTML("beforeEnd", markup);
+        }
+      }
+
+      function buildTestResults(tests) {
+        testResults = [];
+
+        let oldRoundTrip = {
+          x: [],
+          y: [],
+          type: "scatter",
+          name: "ArgumentList",
+        };
+
+        let newRoundTrip = {
+          x: [],
+          y: [],
+          type: "scatter",
+          name: "SharedMemoryRegion",
+        };
+
+        for (let i = 0; i < tests.length / 2; i++) {
+          const index = testResults.length;
+
+          const test = tests[i * 2];
+          const testSMR = tests[i * 2 + 1];
+
+          const avgRoundTrip = test.totalRoundTrip / test.totalSamples;
+          const avgRoundTripSMR = testSMR.totalRoundTrip / testSMR.totalSamples;
+          const relativeTripDiff =
+            ((avgRoundTripSMR - avgRoundTrip) / avgRoundTrip) * 100;
+
+          // In MB/s
+          const speed = test.messageSize / avgRoundTrip;
+          const speedSMR = testSMR.messageSize / avgRoundTripSMR;
+          const relativeSpeedDiff = ((speedSMR - speed) / speed) * 100;
+
+          const stdDeviation = getStandardDeviation(
+            box_plot_test_data[test.index].x,
+            avgRoundTrip
+          );
+          const stdDeviationSMR = getStandardDeviation(
+            box_plot_test_data[testSMR.index].x,
+            avgRoundTripSMR
+          );
+
+          testResults.push({
+            name: humanFileSize(test.messageSize),
+            index: index,
+            prepared: true,
+            avgRoundTrip: avgRoundTrip,
+            avgRoundTripSMR: avgRoundTripSMR,
+            relativeTripDiff: relativeTripDiff,
+            speed: speed,
+            speedSMR: speedSMR,
+            relativeSpeedDiff: relativeSpeedDiff,
+            stdDeviation: stdDeviation,
+            stdDeviationSMR: stdDeviationSMR,
+          });
+
+          oldRoundTrip.x.push(test.messageSize);
+          newRoundTrip.x.push(test.messageSize);
+          oldRoundTrip.y.push(avgRoundTrip);
+          newRoundTrip.y.push(avgRoundTripSMR);
+        }
+
+        round_trip_avg_plot_data = [oldRoundTrip, newRoundTrip];
+        return testResults;
+      }
+
+      function buildEmptyTestResults(tests) {
+        testResults = [];
+        for (let i = 0; i < tests.length / 2; i++) {
+          const index = testResults.length;
+          const test = tests[i * 2];
+
+          testResults.push({
+            name: humanFileSize(test.messageSize),
+            index: index,
+            prepared: false,
+          });
+        }
+        return testResults;
+      }
+
+      function prepareQueuedTests(totalSamples) {
+        if (totalSamples <= 0) totalSamples = 1;
+
+        tests.forEach((test) => {
+          test.sample = 0;
+          test.totalRoundTrip = 0;
+          test.totalSamples = totalSamples;
+        });
+
+        testResults = buildEmptyTestResults(tests);
+        testResults.forEach((result) => displayResult(result));
+
+        round_trip_avg_plot_data = [];
+        box_plot_test_data.forEach((data) => {
+          data.x = [];
+        });
+      }
+
+      function queueTest(name, messageSize, testFunc) {
+        const testIndex = tests.length;
+        test = {
+          name: name,
+          messageSize: messageSize,
+          index: testIndex,
+          func: testFunc,
+        };
+        tests.push(test);
+
+        box_plot_test_data.push({
+          x: [],
+          type: "box",
+          boxpoints: "all",
+          name: name,
+          jitter: 0.3,
+          pointpos: -1.8,
+        });
+      }
+
+      function execNextTest(testIndex) {
+        testIndex++;
+        if (tests.length <= testIndex) {
+          testSuiteFinished();
+        } else {
+          execTest(testIndex);
+        }
+      }
+
+      function execQueuedTests(totalSamples) {
+        prepareQueuedTests(totalSamples);
+        // Let the updated table render before starting the tests
+        setTimeout(execNextTest, 200, -1);
+      }
+
+      function setSettingsState(disabled) {
+        document.getElementById("sSamples").disabled = disabled;
+        document.getElementById("sRun").disabled = disabled;
+      }
+
+      function testSuiteFinished() {
+        testResults = buildTestResults(tests);
+        testResults.forEach((result) => displayResult(result));
+
+        const round_trip_layout = {
+          title: "Average round trip, ms (Smaller Better)",
+        };
+        Plotly.newPlot(
+          "round_trip_avg_chart",
+          round_trip_avg_plot_data,
+          round_trip_layout
+        );
+
+        const box_plot_layout = {
+          title: "Round Trip Time, ms",
+        };
+        Plotly.newPlot("box_plot_chart", box_plot_test_data, box_plot_layout);
+        setSettingsState(false);
+      }
+
+      function humanFileSize(bytes) {
+        const step = 1024;
+
+        if (Math.abs(bytes) < step) {
+          return bytes + " B";
+        }
+
+        const units = [" KB", " MB", " GB"];
+        let u = -1;
+        let count = 0;
+
+        do {
+          bytes /= step;
+          u += 1;
+          count += 1;
+        } while (Math.abs(bytes) >= step && u < units.length - 1);
+
+        return bytes.toString() + units[u];
+      }
+
+      window.runTestSuite = () => {
+        Plotly.purge("round_trip_avg_chart");
+        Plotly.purge("box_plot_chart");
+        setSettingsState(true);
+        const totalSamples = parseInt(
+          document.getElementById("sSamples").value
+        );
+        execQueuedTests(totalSamples);
+        return false;
+      };
+
+      for (let size = 512; size <= 512 * 1024; size = size * 2) {
+        queueTest(humanFileSize(size) + " AL", size, sendRequest);
+        queueTest(humanFileSize(size) + " SM", size, sendSMRRequest);
+      }
+
+      const totalSamples = parseInt(document.getElementById("sSamples").value);
+      prepareQueuedTests(totalSamples);
+    </script>
+  </body>
+</html>
diff --git a/src/tests/cefclient/resources/mac/English.lproj/MainMenu.xib b/src/tests/cefclient/resources/mac/English.lproj/MainMenu.xib
index d54bff2..e751d4e 100644
--- a/src/tests/cefclient/resources/mac/English.lproj/MainMenu.xib
+++ b/src/tests/cefclient/resources/mac/English.lproj/MainMenu.xib
@@ -173,16 +173,27 @@
                             <menuItem title="Find" id="218">
                                 <menu key="submenu" title="Find" id="220">
                                     <items>
-                                        <menuItem title="Find…" tag="1" keyEquivalent="f" id="209">
+                                        <menuItem title="Find…" tag="37000" keyEquivalent="f" id="209">
                                             <connections>
-                                                <action selector="performFindPanelAction:" target="-1" id="241"/>
+                                                <action selector="commandDispatch:" target="-1" id="241"/>
                                             </connections>
                                         </menuItem>
-                                        <menuItem title="Find Next" tag="2" keyEquivalent="g" id="208"/>
-                                        <menuItem title="Find Previous" tag="3" keyEquivalent="G" id="213">
-                                            <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
+                                        <menuItem title="Find Next" tag="37001" keyEquivalent="g" id="208">
+                                            <connections>
+                                                <action selector="commandDispatch:" target="-1" id="242"/>
+                                            </connections>
                                         </menuItem>
-                                        <menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221"/>
+                                        <menuItem title="Find Previous" tag="37002" keyEquivalent="G" id="213">
+                                            <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
+                                            <connections>
+                                                <action selector="commandDispatch:" target="-1" id="243"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Use Selection for Find" keyEquivalent="e" id="221">
+                                            <connections>
+                                                <action selector="copyToFindPboard:" target="-1" id="244"/>
+                                            </connections>
+                                        </menuItem>
                                         <menuItem title="Jump to Selection" keyEquivalent="j" id="210">
                                             <connections>
                                                 <action selector="centerSelectionInVisibleArea:" target="-1" id="245"/>
@@ -351,18 +362,18 @@
                                     <action selector="menuTestsWindowPopup:" target="-2" id="8GQ-Ph-2iP"/>
                                 </connections>
                             </menuItem>
+                            <menuItem title="Dialog Window" id="a52-WG-ltZ">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <connections>
+                                    <action selector="menuTestsWindowDialog:" target="-2" id="8GQ-Ph-2iQ"/>
+                                </connections>
+                            </menuItem>
                             <menuItem title="Request" id="Ymm-D1-9xh">
                                 <modifierMask key="keyEquivalentModifierMask"/>
                                 <connections>
                                     <action selector="menuTestsRequest:" target="-2" id="bT6-It-UE3"/>
                                 </connections>
                             </menuItem>
-                            <menuItem title="Plugin Info" id="DgT-RO-YAr">
-                                <modifierMask key="keyEquivalentModifierMask"/>
-                                <connections>
-                                    <action selector="menuTestsPluginInfo:" target="-2" id="xIV-r7-IGH"/>
-                                </connections>
-                            </menuItem>
                             <menuItem title="Zoom In" id="l8B-JC-657">
                                 <modifierMask key="keyEquivalentModifierMask"/>
                                 <connections>
diff --git a/src/tests/cefclient/resources/mac/Info.plist b/src/tests/cefclient/resources/mac/Info.plist
index 3730aeb..5e7e36d 100644
--- a/src/tests/cefclient/resources/mac/Info.plist
+++ b/src/tests/cefclient/resources/mac/Info.plist
@@ -28,7 +28,7 @@
 		<string>0</string>
 	</dict>
 	<key>LSMinimumSystemVersion</key>
-	<string>10.9.0</string>
+	<string>10.13.0</string>
 	<key>NSMainNibFile</key>
 	<string>MainMenu</string>
 	<key>NSPrincipalClass</key>
diff --git a/src/tests/cefclient/resources/mac/helper-Info.plist b/src/tests/cefclient/resources/mac/helper-Info.plist
index 43fb556..bee1aa4 100644
--- a/src/tests/cefclient/resources/mac/helper-Info.plist
+++ b/src/tests/cefclient/resources/mac/helper-Info.plist
@@ -28,7 +28,7 @@
 	<key>LSFileQuarantineEnabled</key>
 	<true/>
 	<key>LSMinimumSystemVersion</key>
-	<string>10.9.0</string>
+	<string>10.13.0</string>
 	<key>LSUIElement</key>
 	<string>1</string>
 	<key>NSSupportsAutomaticGraphicsSwitching</key>
diff --git a/src/tests/cefclient/resources/media_router.html b/src/tests/cefclient/resources/media_router.html
index 54f8b74..0e874ff 100644
--- a/src/tests/cefclient/resources/media_router.html
+++ b/src/tests/cefclient/resources/media_router.html
@@ -240,7 +240,6 @@
       name: string,
       type: string ('cast' or 'dial'),
       id: string,
-      desc: string,
       icon: int
     }, ...
   ]
@@ -506,14 +505,12 @@
       name: 'Sink 1',
       type: 'cast',
       id: 'sink1',
-      desc: 'My cast device',
       icon: CEF_MSIT_CAST
     },
     {
       name: 'Sink 2',
       type: 'dial',
       id: 'sink2',
-      desc: 'My dial device',
       icon: CEF_MSIT_GENERIC
     }
   ];
@@ -571,7 +568,7 @@
       Status information and messages will be displayed in the center of the screen.
       After creating a route you can send messages to the receiver app using the textarea at the bottom of the screen.
       Messages are usually in JSON format with a example of Cast communication to be found
-      <a href="https://bitbucket.org/chromiumembedded/cef/issues/2900/add-mediarouter-support-for-cast-receiver#comment-56680326" target="_blank">here</a>.
+      <a href="https://github.com/chromiumembedded/cef/issues/2900#issuecomment-1465022620" target="_blank">here</a>.
     </p>
   </div>
   <div class="route_controls">
diff --git a/src/tests/cefclient/resources/other_tests.html b/src/tests/cefclient/resources/other_tests.html
index a92b849..7c094c2 100644
--- a/src/tests/cefclient/resources/other_tests.html
+++ b/src/tests/cefclient/resources/other_tests.html
@@ -9,15 +9,16 @@
 <li><a href="http://webkit.org/blog-files/3d-transforms/poster-circle.html">Accelerated Layers</a></li>
 <li><a href="https://jigsaw.w3.org/HTTP/Basic/">Authentication (Basic)</a> - credentials returned via GetAuthCredentials</li>
 <li><a href="https://jigsaw.w3.org/HTTP/Digest/">Authentication (Digest)</a> - credentials returned via GetAuthCredentials</li>
+<li><a href="binary_transfer">Binary vs String Transfer Benchmark</a></li>
 <li><a href="http://html5advent2011.digitpaint.nl/3/index.html">Cursors</a></li>
 <li><a href="dialogs">Dialogs</a></li>
 <li><a href="http://html5demos.com/drag">Drag & Drop</a></li>
 <li><a href="draggable">Draggable Regions</a></li>
-<li><a href="drm">DRM (Clearkey, Widevine)</a> - Widevine requires setup as described in cef_web_plugin.h</li>
-<li><a href="http://www.adobe.com/software/flash/about/">Flash Plugin</a> - requires "enable-system-flash" flag on Win/Mac and "ppapi-flash-path", "ppapi-flash-version" flags on Linux</li>
+<li>DRM (Clearkey, Widevine) <a href="https://shaka-player-demo.appspot.com/support.html">Codecs support</a>, <a href="https://shaka-player-demo.appspot.com/demo/">Video player demo</a></li>
 <li><a href="http://www.html5test.com">HTML5 Feature Test</a></li>
 <li><a href="http://html5-demos.appspot.com/static/filesystem/filer.js/demos/index.html">HTML5 Filesystem</a> - requires "cache-path" flag</li>
 <li><a href="http://www.youtube.com/watch?v=siOHh0uzcuY&html5=True">HTML5 Video</a></li>
+<li><a href="ipc_performance">IPC Performance Tests</a></li>
 <li><a href="binding">JavaScript Binding</a></li>
 <li><a href="performance">JavaScript Performance Tests</a></li>
 <li><a href="performance2">JavaScript Performance (2) Tests</a></li>
diff --git a/src/tests/cefclient/resources/server.html b/src/tests/cefclient/resources/server.html
index 9e49e06..6762789 100644
--- a/src/tests/cefclient/resources/server.html
+++ b/src/tests/cefclient/resources/server.html
@@ -24,7 +24,7 @@
 }
 
 function setup() {
-  if (location.origin != 'http://tests') {
+  if (location.origin != 'https://tests') {
     document.getElementById('warning').style.display = 'block';
     return;
   }
@@ -84,7 +84,7 @@
 </head>
 <body bgcolor="white" onload="setup()">
 <div id="warning" style="display:none;color:red;font-weight:bold;">
-This page can only be run from the http://tests origin.
+This page can only be run from the https://tests origin.
 </div>
 <p>
 This page starts an HTTP/WebSocket server on localhost with the specified port number.
diff --git a/src/tests/cefclient/resources/urlrequest.html b/src/tests/cefclient/resources/urlrequest.html
index fc7484d..873dbd4 100644
--- a/src/tests/cefclient/resources/urlrequest.html
+++ b/src/tests/cefclient/resources/urlrequest.html
@@ -34,7 +34,7 @@
 </head>
 <body bgcolor="white" onload="setup()">
 <form id="form">
-URL: <input type="text" id="url" value="http://www.google.com">
+URL: <input type="text" id="url" value="https://www.google.com">
 <br/><input type="button" onclick="execURLRequest();" value="Execute CefURLRequest">
 <br/><textarea rows="10" cols="40" id="ta"></textarea>
 </form>
diff --git a/src/tests/cefclient/resources/websocket.html b/src/tests/cefclient/resources/websocket.html
index e13abc0..91f35f2 100644
--- a/src/tests/cefclient/resources/websocket.html
+++ b/src/tests/cefclient/resources/websocket.html
@@ -87,7 +87,7 @@
 <body bgcolor="white" onload="setup()">
 <div id="warning" style="display:none;color:red;font-weight:bold;">
 This page is most useful when loaded from localhost.
-You should first create a server using the <a href="http://tests/server">HTTP/WebSocket Server test</a>.
+You should first create a server using the <a href="https://tests/server">HTTP/WebSocket Server test</a>.
 </div>
 <p>
 This page tests a WebSocket connection.
diff --git a/src/tests/cefclient/resources/win/cefclient.rc b/src/tests/cefclient/resources/win/cefclient.rc
index 77bf9df..edd7e1b 100644
--- a/src/tests/cefclient/resources/win/cefclient.rc
+++ b/src/tests/cefclient/resources/win/cefclient.rc
@@ -29,10 +29,11 @@
 // Binary

 //

 

+IDS_BINARY_TRANSFER_HTML BINARY "..\\binary_transfer.html"

 IDS_BINDING_HTML BINARY "..\\binding.html"

 IDS_DIALOGS_HTML BINARY "..\\dialogs.html"

 IDS_DRAGGABLE_HTML BINARY "..\\draggable.html"

-IDS_DRM_HTML BINARY "..\\drm.html"

+IDS_IPC_PERFORMANCE_HTML BINARY "..\\ipc_performance.html"

 IDS_LOCALSTORAGE_HTML BINARY "..\\localstorage.html"

 IDS_LOGO_PNG BINARY "..\\logo.png"

 IDS_MEDIA_ROUTER_HTML BINARY "..\\media_router.html"

@@ -94,7 +95,6 @@
         MENUITEM "New Window",                  ID_TESTS_WINDOW_NEW

         MENUITEM "Popup Window",                ID_TESTS_WINDOW_POPUP

         MENUITEM "Request",                     ID_TESTS_REQUEST

-        MENUITEM "Plugin Info",                 ID_TESTS_PLUGIN_INFO

         MENUITEM "Zoom In",                     ID_TESTS_ZOOM_IN

         MENUITEM "Zoom Out",                    ID_TESTS_ZOOM_OUT

         MENUITEM "Zoom Reset",                  ID_TESTS_ZOOM_RESET

@@ -229,4 +229,3 @@
 

 /////////////////////////////////////////////////////////////////////////////

 #endif    // not APSTUDIO_INVOKED

-

diff --git a/src/tests/cefclient/resources/window.html b/src/tests/cefclient/resources/window.html
index 7703d0d..17f53d2 100644
--- a/src/tests/cefclient/resources/window.html
+++ b/src/tests/cefclient/resources/window.html
@@ -1,6 +1,13 @@
-<html>
+<!DOCTYPE html>
+<html lang="en-US">
 <head>
 <title>Window Test</title>
+<style>
+/* Background becomes pink in fullscreen mode. */
+:fullscreen {
+  background: pink;
+}
+</style>
 <script>
 function setup() {
   if (location.hostname == 'tests' || location.hostname == 'localhost')
@@ -37,6 +44,18 @@
   setTimeout(function() { send_message('Restore'); }, 1000);
 }
 
+function fullscreenWindow() {
+  send_message('Fullscreen');
+}
+
+function fullscreenBrowser() {
+  if (document.fullscreenElement) {
+    document.exitFullscreen();
+  } else {
+    document.getElementById('form').requestFullscreen();
+  }
+}
+
 function position() {
   var x = parseInt(document.getElementById('x').value);
   var y = parseInt(document.getElementById('y').value);
@@ -47,6 +66,14 @@
   else
     send_message('Position', x + ',' + y + ',' + width + ',' + height);
 }
+
+function setTitlebarHeight() {
+  const height = parseFloat(document.getElementById('title_bar_height').value);
+  if (isNaN(height))
+    send_message('TitlebarHeight');
+  else
+    send_message('TitlebarHeight', height);
+}
 </script>
 </head>
 <body bgcolor="white" onload="setup()">
@@ -55,11 +82,15 @@
 <br/><input type="button" onclick="minimize();" value="Minimize">
 <br/><input type="button" onclick="maximize();" value="Maximize">
 <br/><input type="button" onclick="restore();" value="Restore"> (minimizes and then restores the window as topmost)
+<br/><input type="button" onclick="fullscreenWindow();" value="Toggle Window Fullscreen"> (works with Views)
+<br/><input type="button" onclick="fullscreenBrowser();" value="Toggle Browser Fullscreen"> (uses <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API" target="_new">Fullscreen API</a>; background turns pink)
 <br/><input type="button" onclick="position();" value="Set Position">
 X: <input type="text" size="4" id="x" value="200">
 Y: <input type="text" size="4" id="y" value="100">
 Width: <input type="text" size="4" id="width" value="800">
 Height: <input type="text" size="4" id="height" value="600">
+<br/><input type="button" onclick="setTitlebarHeight();" value="Set Titlebar Height">
+<input type="number" min="0" max="100" id="title_bar_height" value="50"> (works on macOS with Views)
 </form>
 </body>
 </html>
diff --git a/src/tests/cefclient/resources/xmlhttprequest.html b/src/tests/cefclient/resources/xmlhttprequest.html
index 8da20f3..655f48a 100644
--- a/src/tests/cefclient/resources/xmlhttprequest.html
+++ b/src/tests/cefclient/resources/xmlhttprequest.html
@@ -30,7 +30,7 @@
 }
 </script>
 <form>
-URL: <input type="text" id="url" value="http://tests/request">
+URL: <input type="text" id="url" value="https://tests/request">
 <br/><input type="button" onclick="execXMLHttpRequest();" value="Execute XMLHttpRequest">
 <br/><textarea rows="10" cols="40" id="ta"></textarea>
 </form>
diff --git a/src/tests/cefsimple/CMakeLists.txt.in b/src/tests/cefsimple/CMakeLists.txt.in
index 12b1c84..9eb0824 100644
--- a/src/tests/cefsimple/CMakeLists.txt.in
+++ b/src/tests/cefsimple/CMakeLists.txt.in
@@ -13,7 +13,7 @@
   'includes': [
     'cefsimple_sources_common',
     'cefsimple_sources_win:WINDOWS',
-    'cefsimple_sources_mac:MACOSX',
+    'cefsimple_sources_mac:MAC',
     'cefsimple_sources_linux:LINUX',
   ],
 }}
@@ -22,7 +22,7 @@
 {{
   'prefix': 'cefsimple_helper',
   'includes': [
-    'cefsimple_sources_mac_helper:MACOSX',
+    'cefsimple_sources_mac_helper:MAC',
   ],
 }}
 
@@ -31,7 +31,7 @@
   'prefix': 'cefsimple_resources',
   'set': 'CEFSIMPLE_RESOURCES_SRCS',
   'includes': [
-    'cefsimple_bundle_resources_mac:MACOSX',
+    'cefsimple_bundle_resources_mac:MAC',
   ],
 }}
 
@@ -42,7 +42,7 @@
 
 # Target executable names.
 set(CEF_TARGET "cefsimple")
-if(OS_MACOSX)
+if(OS_MAC)
   set(CEF_HELPER_TARGET "cefsimple_Helper")
   set(CEF_HELPER_OUTPUT_NAME "cefsimple Helper")
 else()
@@ -86,7 +86,7 @@
 # Mac OS X configuration.
 #
 
-if(OS_MACOSX)
+if(OS_MAC)
   option(OPTION_USE_ARC "Build with ARC (automatic Reference Counting) on macOS." ON)
   if(OPTION_USE_ARC)
     list(APPEND CEF_COMPILER_FLAGS
@@ -184,7 +184,7 @@
   # directive but that doesn't properly handle nested resource directories.
   # Remove these prefixes from input file paths.
   set(PREFIXES "mac/")
-  COPY_MACOSX_RESOURCES("${CEFSIMPLE_RESOURCES_SRCS}" "${PREFIXES}" "${CEF_TARGET}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CEF_APP}")
+  COPY_MAC_RESOURCES("${CEFSIMPLE_RESOURCES_SRCS}" "${PREFIXES}" "${CEF_TARGET}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CEF_APP}")
 endif()
 
 
diff --git a/src/tests/cefsimple/cefsimple_linux.cc b/src/tests/cefsimple/cefsimple_linux.cc
index 87efbb7..26b3c7b 100644
--- a/src/tests/cefsimple/cefsimple_linux.cc
+++ b/src/tests/cefsimple/cefsimple_linux.cc
@@ -9,6 +9,7 @@
 #endif
 
 #include "include/base/cef_logging.h"
+#include "include/cef_command_line.h"
 
 #if defined(CEF_X11)
 namespace {
@@ -36,9 +37,9 @@
   // Provide CEF with command-line arguments.
   CefMainArgs main_args(argc, argv);
 
-  // CEF applications have multiple sub-processes (render, plugin, GPU, etc)
-  // that share the same executable. This function checks the command-line and,
-  // if this is a sub-process, executes the appropriate logic.
+  // CEF applications have multiple sub-processes (render, GPU, etc) that share
+  // the same executable. This function checks the command-line and, if this is
+  // a sub-process, executes the appropriate logic.
   int exit_code = CefExecuteProcess(main_args, nullptr, nullptr);
   if (exit_code >= 0) {
     // The sub-process has completed so return here.
@@ -52,9 +53,18 @@
   XSetIOErrorHandler(XIOErrorHandlerImpl);
 #endif
 
+  // Parse command-line arguments for use in this method.
+  CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
+  command_line->InitFromArgv(argc, argv);
+
   // Specify CEF global settings here.
   CefSettings settings;
 
+  if (command_line->HasSwitch("enable-chrome-runtime")) {
+    // Enable experimental Chrome runtime. See issue #2969 for details.
+    settings.chrome_runtime = true;
+  }
+
 // When generating projects with CMake the CEF_USE_SANDBOX value will be defined
 // automatically. Pass -DUSE_SANDBOX=OFF to the CMake command-line to disable
 // use of the sandbox.
diff --git a/src/tests/cefsimple/cefsimple_mac.mm b/src/tests/cefsimple/cefsimple_mac.mm
index e5301b4..6d2c9ed 100644
--- a/src/tests/cefsimple/cefsimple_mac.mm
+++ b/src/tests/cefsimple/cefsimple_mac.mm
@@ -6,6 +6,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "include/cef_application_mac.h"
+#include "include/cef_command_line.h"
 #include "include/wrapper/cef_helpers.h"
 #include "include/wrapper/cef_library_loader.h"
 #include "tests/cefsimple/simple_app.h"
@@ -13,6 +14,7 @@
 
 // Receives notifications from the application.
 @interface SimpleAppDelegate : NSObject <NSApplicationDelegate>
+
 - (void)createApplication:(id)object;
 - (void)tryToTerminateApplication:(NSApplication*)app;
 @end
@@ -87,7 +89,6 @@
 
 // Create the application on the UI thread.
 - (void)createApplication:(id)object {
-  [NSApplication sharedApplication];
   [[NSBundle mainBundle] loadNibNamed:@"MainMenu"
                                 owner:NSApp
                       topLevelObjects:nil];
@@ -98,8 +99,9 @@
 
 - (void)tryToTerminateApplication:(NSApplication*)app {
   SimpleHandler* handler = SimpleHandler::GetInstance();
-  if (handler && !handler->IsClosing())
+  if (handler && !handler->IsClosing()) {
     handler->CloseAllBrowsers(false);
+  }
 }
 
 - (NSApplicationTerminateReply)applicationShouldTerminate:
@@ -113,8 +115,9 @@
   // Load the CEF framework library at runtime instead of linking directly
   // as required by the macOS sandbox implementation.
   CefScopedLibraryLoader library_loader;
-  if (!library_loader.LoadInMain())
+  if (!library_loader.LoadInMain()) {
     return 1;
+  }
 
   // Provide CEF with command-line arguments.
   CefMainArgs main_args(argc, argv);
@@ -123,9 +126,27 @@
     // Initialize the SimpleApplication instance.
     [SimpleApplication sharedApplication];
 
+    // If there was an invocation to NSApp prior to this method, then the NSApp
+    // will not be a SimpleApplication, but will instead be an NSApplication.
+    // This is undesirable and we must enforce that this doesn't happen.
+    CHECK([NSApp isKindOfClass:[SimpleApplication class]]);
+
+    // Parse command-line arguments for use in this method.
+    CefRefPtr<CefCommandLine> command_line =
+        CefCommandLine::CreateCommandLine();
+    command_line->InitFromArgv(argc, argv);
+
     // Specify CEF global settings here.
     CefSettings settings;
 
+    const bool with_chrome_runtime =
+        command_line->HasSwitch("enable-chrome-runtime");
+
+    if (with_chrome_runtime) {
+      // Enable experimental Chrome runtime. See issue #2969 for details.
+      settings.chrome_runtime = true;
+    }
+
     // When generating projects with CMake the CEF_USE_SANDBOX value will be
     // defined automatically. Pass -DUSE_SANDBOX=OFF to the CMake command-line
     // to disable use of the sandbox.
@@ -139,7 +160,7 @@
     CefRefPtr<SimpleApp> app(new SimpleApp);
 
     // Initialize CEF for the browser process.
-    CefInitialize(main_args, settings, app.get(), NULL);
+    CefInitialize(main_args, settings, app.get(), nullptr);
 
     // Create the application delegate.
     NSObject* delegate = [[SimpleAppDelegate alloc] init];
diff --git a/src/tests/cefsimple/cefsimple_win.cc b/src/tests/cefsimple/cefsimple_win.cc
index 14fe5e1..e443116 100644
--- a/src/tests/cefsimple/cefsimple_win.cc
+++ b/src/tests/cefsimple/cefsimple_win.cc
@@ -4,6 +4,7 @@
 
 #include <windows.h>
 
+#include "include/cef_command_line.h"
 #include "include/cef_sandbox_win.h"
 #include "tests/cefsimple/simple_app.h"
 
@@ -27,8 +28,23 @@
   UNREFERENCED_PARAMETER(hPrevInstance);
   UNREFERENCED_PARAMETER(lpCmdLine);
 
-  // Enable High-DPI support on Windows 7 or newer.
-  CefEnableHighDPISupport();
+  int exit_code;
+
+#if defined(ARCH_CPU_32_BITS)
+  // Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
+  // stack size. This function must be called at the top of the executable entry
+  // point function (`main()` or `wWinMain()`). It is used in combination with
+  // the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
+  // flag on executable targets. This saves significant memory on threads (like
+  // those in the Windows thread pool, and others) whose stack size can only be
+  // controlled via the linker flag.
+  exit_code = CefRunWinMainWithPreferredStackSize(wWinMain, hInstance,
+                                                  lpCmdLine, nCmdShow);
+  if (exit_code >= 0) {
+    // The fiber has completed so return here.
+    return exit_code;
+  }
+#endif
 
   void* sandbox_info = nullptr;
 
@@ -42,18 +58,27 @@
   // Provide CEF with command-line arguments.
   CefMainArgs main_args(hInstance);
 
-  // CEF applications have multiple sub-processes (render, plugin, GPU, etc)
-  // that share the same executable. This function checks the command-line and,
-  // if this is a sub-process, executes the appropriate logic.
-  int exit_code = CefExecuteProcess(main_args, nullptr, sandbox_info);
+  // CEF applications have multiple sub-processes (render, GPU, etc) that share
+  // the same executable. This function checks the command-line and, if this is
+  // a sub-process, executes the appropriate logic.
+  exit_code = CefExecuteProcess(main_args, nullptr, sandbox_info);
   if (exit_code >= 0) {
     // The sub-process has completed so return here.
     return exit_code;
   }
 
+  // Parse command-line arguments for use in this method.
+  CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
+  command_line->InitFromString(::GetCommandLineW());
+
   // Specify CEF global settings here.
   CefSettings settings;
 
+  if (command_line->HasSwitch("enable-chrome-runtime")) {
+    // Enable experimental Chrome runtime. See issue #2969 for details.
+    settings.chrome_runtime = true;
+  }
+
 #if !defined(CEF_USE_SANDBOX)
   settings.no_sandbox = true;
 #endif
diff --git a/src/tests/cefsimple/mac/Info.plist b/src/tests/cefsimple/mac/Info.plist
index 102c9b5..c83d7c1 100644
--- a/src/tests/cefsimple/mac/Info.plist
+++ b/src/tests/cefsimple/mac/Info.plist
@@ -26,7 +26,7 @@
 		<string>0</string>
 	</dict>
 	<key>LSMinimumSystemVersion</key>
-	<string>10.9.0</string>
+	<string>10.13.0</string>
 	<key>NSMainNibFile</key>
 	<string>MainMenu</string>
 	<key>NSPrincipalClass</key>
diff --git a/src/tests/cefsimple/mac/helper-Info.plist b/src/tests/cefsimple/mac/helper-Info.plist
index 46c1e2b..17842e2 100644
--- a/src/tests/cefsimple/mac/helper-Info.plist
+++ b/src/tests/cefsimple/mac/helper-Info.plist
@@ -26,7 +26,7 @@
 	<key>LSFileQuarantineEnabled</key>
 	<true/>
 	<key>LSMinimumSystemVersion</key>
-	<string>10.9.0</string>
+	<string>10.13.0</string>
 	<key>LSUIElement</key>
 	<string>1</string>
 	<key>NSSupportsAutomaticGraphicsSwitching</key>
diff --git a/src/tests/cefsimple/process_helper_mac.cc b/src/tests/cefsimple/process_helper_mac.cc
index 224593d..bc6d83c 100644
--- a/src/tests/cefsimple/process_helper_mac.cc
+++ b/src/tests/cefsimple/process_helper_mac.cc
@@ -17,15 +17,17 @@
 #if defined(CEF_USE_SANDBOX)
   // Initialize the macOS sandbox for this helper process.
   CefScopedSandboxContext sandbox_context;
-  if (!sandbox_context.Initialize(argc, argv))
+  if (!sandbox_context.Initialize(argc, argv)) {
     return 1;
+  }
 #endif
 
   // Load the CEF framework library at runtime instead of linking directly
   // as required by the macOS sandbox implementation.
   CefScopedLibraryLoader library_loader;
-  if (!library_loader.LoadInHelper())
+  if (!library_loader.LoadInHelper()) {
     return 1;
+  }
 
   // Provide CEF with command-line arguments.
   CefMainArgs main_args(argc, argv);
diff --git a/src/tests/cefsimple/simple_app.cc b/src/tests/cefsimple/simple_app.cc
index baa20d1..72556cf 100644
--- a/src/tests/cefsimple/simple_app.cc
+++ b/src/tests/cefsimple/simple_app.cc
@@ -22,7 +22,7 @@
   explicit SimpleWindowDelegate(CefRefPtr<CefBrowserView> browser_view)
       : browser_view_(browser_view) {}
 
-  void OnWindowCreated(CefRefPtr<CefWindow> window) OVERRIDE {
+  void OnWindowCreated(CefRefPtr<CefWindow> window) override {
     // Add the browser view and show the window.
     window->AddChildView(browser_view_);
     window->Show();
@@ -31,19 +31,20 @@
     browser_view_->RequestFocus();
   }
 
-  void OnWindowDestroyed(CefRefPtr<CefWindow> window) OVERRIDE {
+  void OnWindowDestroyed(CefRefPtr<CefWindow> window) override {
     browser_view_ = nullptr;
   }
 
-  bool CanClose(CefRefPtr<CefWindow> window) OVERRIDE {
+  bool CanClose(CefRefPtr<CefWindow> window) override {
     // Allow the window to close if the browser says it's OK.
     CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
-    if (browser)
+    if (browser) {
       return browser->GetHost()->TryCloseBrowser();
+    }
     return true;
   }
 
-  CefSize GetPreferredSize(CefRefPtr<CefView> view) OVERRIDE {
+  CefSize GetPreferredSize(CefRefPtr<CefView> view) override {
     return CefSize(800, 600);
   }
 
@@ -60,7 +61,7 @@
 
   bool OnPopupBrowserViewCreated(CefRefPtr<CefBrowserView> browser_view,
                                  CefRefPtr<CefBrowserView> popup_browser_view,
-                                 bool is_devtools) OVERRIDE {
+                                 bool is_devtools) override {
     // Create a new top-level Window for the popup. It will show itself after
     // creation.
     CefWindow::CreateTopLevelWindow(
@@ -85,15 +86,10 @@
   CefRefPtr<CefCommandLine> command_line =
       CefCommandLine::GetGlobalCommandLine();
 
-#if defined(OS_WIN) || defined(OS_LINUX)
   // Create the browser using the Views framework if "--use-views" is specified
   // via the command-line. Otherwise, create the browser using the native
-  // platform framework. The Views framework is currently only supported on
-  // Windows and Linux.
+  // platform framework.
   const bool use_views = command_line->HasSwitch("use-views");
-#else
-  const bool use_views = false;
-#endif
 
   // SimpleHandler implements browser-level callbacks.
   CefRefPtr<SimpleHandler> handler(new SimpleHandler(use_views));
@@ -106,8 +102,9 @@
   // Check if a "--url=" value was provided via the command-line. If so, use
   // that instead of the default URL.
   url = command_line->GetSwitchValue("url");
-  if (url.empty())
+  if (url.empty()) {
     url = "http://www.google.com";
+  }
 
   if (use_views) {
     // Create the BrowserView.
@@ -124,7 +121,7 @@
 #if defined(OS_WIN)
     // On Windows we need to specify certain flags that will be passed to
     // CreateWindowEx().
-    window_info.SetAsPopup(NULL, "cefsimple");
+    window_info.SetAsPopup(nullptr, "cefsimple");
 #endif
 
     // Create the first browser window.
@@ -132,3 +129,8 @@
                                   nullptr, nullptr);
   }
 }
+
+CefRefPtr<CefClient> SimpleApp::GetDefaultClient() {
+  // Called when a new browser window is created via the Chrome runtime UI.
+  return SimpleHandler::GetInstance();
+}
diff --git a/src/tests/cefsimple/simple_app.h b/src/tests/cefsimple/simple_app.h
index 8ed9969..81afd54 100644
--- a/src/tests/cefsimple/simple_app.h
+++ b/src/tests/cefsimple/simple_app.h
@@ -13,13 +13,13 @@
   SimpleApp();
 
   // CefApp methods:
-  virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()
-      OVERRIDE {
+  CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() override {
     return this;
   }
 
   // CefBrowserProcessHandler methods:
-  virtual void OnContextInitialized() OVERRIDE;
+  void OnContextInitialized() override;
+  CefRefPtr<CefClient> GetDefaultClient() override;
 
  private:
   // Include the default reference counting implementation.
diff --git a/src/tests/cefsimple/simple_handler.cc b/src/tests/cefsimple/simple_handler.cc
index fafedc8..e7d977f 100644
--- a/src/tests/cefsimple/simple_handler.cc
+++ b/src/tests/cefsimple/simple_handler.cc
@@ -7,7 +7,7 @@
 #include <sstream>
 #include <string>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_app.h"
 #include "include/cef_parser.h"
 #include "include/views/cef_browser_view.h"
@@ -53,10 +53,11 @@
         CefBrowserView::GetForBrowser(browser);
     if (browser_view) {
       CefRefPtr<CefWindow> window = browser_view->GetWindow();
-      if (window)
+      if (window) {
         window->SetTitle(title);
+      }
     }
-  } else {
+  } else if (!IsChromeRuntimeEnabled()) {
     // Set the title of the window using platform APIs.
     PlatformTitleChange(browser, title);
   }
@@ -110,9 +111,15 @@
                                 const CefString& failedUrl) {
   CEF_REQUIRE_UI_THREAD();
 
-  // Don't display an error for downloaded files.
-  if (errorCode == ERR_ABORTED)
+  // Allow Chrome to show the error page.
+  if (IsChromeRuntimeEnabled()) {
     return;
+  }
+
+  // Don't display an error for downloaded files.
+  if (errorCode == ERR_ABORTED) {
+    return;
+  }
 
   // Display a load error message using a data: URI.
   std::stringstream ss;
@@ -127,15 +134,28 @@
 void SimpleHandler::CloseAllBrowsers(bool force_close) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&SimpleHandler::CloseAllBrowsers, this,
-                                   force_close));
+    CefPostTask(TID_UI, base::BindOnce(&SimpleHandler::CloseAllBrowsers, this,
+                                       force_close));
     return;
   }
 
-  if (browser_list_.empty())
+  if (browser_list_.empty()) {
     return;
+  }
 
   BrowserList::const_iterator it = browser_list_.begin();
-  for (; it != browser_list_.end(); ++it)
+  for (; it != browser_list_.end(); ++it) {
     (*it)->GetHost()->CloseBrowser(force_close);
+  }
+}
+
+// static
+bool SimpleHandler::IsChromeRuntimeEnabled() {
+  static int value = -1;
+  if (value == -1) {
+    CefRefPtr<CefCommandLine> command_line =
+        CefCommandLine::GetGlobalCommandLine();
+    value = command_line->HasSwitch("enable-chrome-runtime") ? 1 : 0;
+  }
+  return value == 1;
 }
diff --git a/src/tests/cefsimple/simple_handler.h b/src/tests/cefsimple/simple_handler.h
index 10194f0..c53421e 100644
--- a/src/tests/cefsimple/simple_handler.h
+++ b/src/tests/cefsimple/simple_handler.h
@@ -21,35 +21,38 @@
   static SimpleHandler* GetInstance();
 
   // CefClient methods:
-  virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
+  virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() override {
     return this;
   }
-  virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
+  virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override {
     return this;
   }
-  virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE { return this; }
+  virtual CefRefPtr<CefLoadHandler> GetLoadHandler() override { return this; }
 
   // CefDisplayHandler methods:
   virtual void OnTitleChange(CefRefPtr<CefBrowser> browser,
-                             const CefString& title) OVERRIDE;
+                             const CefString& title) override;
 
   // CefLifeSpanHandler methods:
-  virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  virtual bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
+  virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
+  virtual bool DoClose(CefRefPtr<CefBrowser> browser) override;
+  virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
 
   // CefLoadHandler methods:
   virtual void OnLoadError(CefRefPtr<CefBrowser> browser,
                            CefRefPtr<CefFrame> frame,
                            ErrorCode errorCode,
                            const CefString& errorText,
-                           const CefString& failedUrl) OVERRIDE;
+                           const CefString& failedUrl) override;
 
   // Request that all existing browser windows close.
   void CloseAllBrowsers(bool force_close);
 
   bool IsClosing() const { return is_closing_; }
 
+  // Returns true if the Chrome runtime is enabled.
+  static bool IsChromeRuntimeEnabled();
+
  private:
   // Platform-specific implementation.
   void PlatformTitleChange(CefRefPtr<CefBrowser> browser,
diff --git a/src/tests/cefsimple/simple_handler_linux.cc b/src/tests/cefsimple/simple_handler_linux.cc
index 239791c..92d9a16 100644
--- a/src/tests/cefsimple/simple_handler_linux.cc
+++ b/src/tests/cefsimple/simple_handler_linux.cc
@@ -25,15 +25,18 @@
 
   // Retrieve the X11 window handle for the browser.
   ::Window window = browser->GetHost()->GetWindowHandle();
-  DCHECK(window != kNullWindowHandle);
+  if (window == kNullWindowHandle) {
+    return;
+  }
 
   // Retrieve the atoms required by the below XChangeProperty call.
   const char* kAtoms[] = {"_NET_WM_NAME", "UTF8_STRING"};
   Atom atoms[2];
   int result =
       XInternAtoms(display, const_cast<char**>(kAtoms), 2, false, atoms);
-  if (!result)
+  if (!result) {
     NOTREACHED();
+  }
 
   // Set the window title.
   XChangeProperty(display, window, atoms[0], atoms[1], 8, PropModeReplace,
diff --git a/src/tests/cefsimple/simple_handler_win.cc b/src/tests/cefsimple/simple_handler_win.cc
index 23f0533..3811c67 100644
--- a/src/tests/cefsimple/simple_handler_win.cc
+++ b/src/tests/cefsimple/simple_handler_win.cc
@@ -12,5 +12,7 @@
 void SimpleHandler::PlatformTitleChange(CefRefPtr<CefBrowser> browser,
                                         const CefString& title) {
   CefWindowHandle hwnd = browser->GetHost()->GetWindowHandle();
-  SetWindowText(hwnd, std::wstring(title).c_str());
+  if (hwnd) {
+    SetWindowText(hwnd, std::wstring(title).c_str());
+  }
 }
diff --git a/src/tests/ceftests/CMakeLists.txt.in b/src/tests/ceftests/CMakeLists.txt.in
index cdda2b7..3d87035 100644
--- a/src/tests/ceftests/CMakeLists.txt.in
+++ b/src/tests/ceftests/CMakeLists.txt.in
@@ -14,15 +14,13 @@
     'shared_sources_browser',
     'shared_sources_common',
     'shared_sources_linux:LINUX',
-    'shared_sources_mac:MACOSX',
+    'shared_sources_mac:MAC',
     'shared_sources_renderer:WINDOWS',
     'shared_sources_renderer:LINUX',
     'shared_sources_win:WINDOWS',
     'ceftests_sources_common',
     'ceftests_sources_linux:LINUX',
-    'ceftests_sources_mac:MACOSX',
-    'ceftests_sources_views:WINDOWS',
-    'ceftests_sources_views:LINUX',
+    'ceftests_sources_mac:MAC',
     'ceftests_sources_win:WINDOWS',
   ],
 }}
@@ -33,9 +31,9 @@
   'set': 'UNITTESTS_HELPER_SRCS',
   'includes': [
     'shared_sources_common',
-    'shared_sources_mac_helper:MACOSX',
+    'shared_sources_mac_helper:MAC',
     'shared_sources_renderer',
-    'ceftests_sources_mac_helper:MACOSX',
+    'ceftests_sources_mac_helper:MAC',
   ],
 }}
 
@@ -45,10 +43,18 @@
   'set': 'UNITTESTS_RESOURCES_SRCS',
   'includes': [
     'shared_sources_resources',
-    'ceftests_bundle_resources_mac:MACOSX',
+    'ceftests_bundle_resources_mac:MAC',
   ],
 }}
 
+# ceftests data resources.
+{{
+  'prefix': 'ceftests_data_resources',
+  'set': 'UNITTESTS_DATA_RESOURCES_SRCS',
+  'includes': [
+    'ceftests_data_resources',
+  ],
+}}
 
 #
 # Shared configuration.
@@ -56,7 +62,7 @@
 
 # Target executable names.
 set(CEF_TARGET "ceftests")
-if(OS_MACOSX)
+if(OS_MAC)
   set(CEF_HELPER_TARGET "ceftests_Helper")
   set(CEF_HELPER_OUTPUT_NAME "ceftests Helper")
 else()
@@ -94,6 +100,13 @@
   # Copy ceftests resource files to the target output directory.
   COPY_FILES("${CEF_TARGET}" "${UNITTESTS_RESOURCES_SRCS}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CEF_TARGET_OUT_DIR}/ceftests_files")
 
+  # Copy ceftests data resource files to the target output directory.
+  # Remove these prefixes from input file paths.
+  set(PREFIXES
+    "resources/"
+    )
+  COPY_RESOURCES("${CEF_TARGET}" "${UNITTESTS_DATA_RESOURCES_SRCS}" "${PREFIXES}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CEF_TARGET_OUT_DIR}/ceftests_files")
+
   # Set SUID permissions on the chrome-sandbox target.
   SET_LINUX_SUID_PERMISSIONS("${CEF_TARGET}" "${CEF_TARGET_OUT_DIR}/chrome-sandbox")
 endif()
@@ -103,7 +116,17 @@
 # Mac OS X configuration.
 #
 
-if(OS_MACOSX)
+if(OS_MAC)
+  option(OPTION_USE_ARC "Build with ARC (automatic Reference Counting) on macOS." ON)
+  if(OPTION_USE_ARC)
+    list(APPEND CEF_COMPILER_FLAGS
+      -fobjc-arc
+      )
+    set_target_properties(${target} PROPERTIES
+      CLANG_ENABLE_OBJC_ARC "YES"
+      )
+  endif()
+
   # Output path for the main app bundle.
   set(CEF_APP "${CEF_TARGET_OUT_DIR}/${CEF_TARGET}.app")
 
@@ -192,9 +215,11 @@
   # Remove these prefixes from input file paths.
   set(PREFIXES
     "resources/mac/"
+    "resources/"
     "../shared/resources/"
     )
-  COPY_MACOSX_RESOURCES("${UNITTESTS_RESOURCES_SRCS}" "${PREFIXES}" "${CEF_TARGET}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CEF_APP}")
+  set(RESOURCES ${UNITTESTS_RESOURCES_SRCS} ${UNITTESTS_DATA_RESOURCES_SRCS})
+  COPY_MAC_RESOURCES("${RESOURCES}" "${PREFIXES}" "${CEF_TARGET}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CEF_APP}")
 endif()
 
 
@@ -226,5 +251,11 @@
   # Copy CEF binary and resource files to the target output directory.
   COPY_FILES("${CEF_TARGET}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CEF_TARGET_OUT_DIR}")
   COPY_FILES("${CEF_TARGET}" "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CEF_TARGET_OUT_DIR}")
-endif()
 
+  # Copy ceftests data resource files to the target output directory.
+  # Remove these prefixes from input file paths.
+  set(PREFIXES
+    "resources/"
+    )
+  COPY_RESOURCES("${CEF_TARGET}" "${UNITTESTS_DATA_RESOURCES_SRCS}" "${PREFIXES}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CEF_TARGET_OUT_DIR}/ceftests_files")
+endif()
diff --git a/src/tests/ceftests/audio_output_unittest.cc b/src/tests/ceftests/audio_output_unittest.cc
index 8d134b6..3bd5797 100644
--- a/src/tests/ceftests/audio_output_unittest.cc
+++ b/src/tests/ceftests/audio_output_unittest.cc
@@ -2,7 +2,7 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "tests/ceftests/test_handler.h"
 #include "tests/gtest/include/gtest/gtest.h"
@@ -11,7 +11,7 @@
 using client::ClientAppBrowser;
 
 // Taken from:
-// http://www.iandevlin.com/blog/2012/09/html5/html5-media-and-data-uri/
+// https://www.iandevlin.com/blog/2012/09/html5/html5-media-and-data-uri/
 #define AUDIO_DATA                                                             \
   "data:audio/"                                                                \
   "ogg;base64,T2dnUwACAAAAAAAAAAA+"                                            \
@@ -801,10 +801,10 @@
 const int kFramesPerBuffer = 882;  // 10ms
 const CefAudioHandler::ChannelLayout kChannelLayout = CEF_CHANNEL_LAYOUT_STEREO;
 
-const char kAudioOutputTestUrl[] = "http://tests/audiooutputtest";
-const char kAudioCloseBrowserTestUrl[] = "http://tests/audioclosebrowsertest";
+const char kAudioOutputTestUrl[] = "https://tests/audiooutputtest";
+const char kAudioCloseBrowserTestUrl[] = "https://tests/audioclosebrowsertest";
 const char kAudioTogglePlaybackTestUrl[] =
-    "http://tests/audiotoggleplaybacktest";
+    "https://tests/audiotoggleplaybacktest";
 
 const char kTestHtml[] =
     "<!DOCTYPE html><html><head><meta "
@@ -814,22 +814,43 @@
     "style=\"display:none\"></audio></body></html>";
 
 const char kToggleTestHtml[] =
-    "<!DOCTYPE html><html><head><meta "
-    "charset=\"utf-8\"/><script type=\"text/javascript\">var timeouts = [ "
-    "1950, 150, 2000, 150, 2050, 150, 2100, 150, 2200, 150 "
-    "]; function togglePlayback(el, playing, count) { if (count < 10) { var "
-    "timeout = "
-    "timeouts[count]; if (playing) { el.pause(); } else { el.play(); } "
-    "setTimeout(togglePlayback, timeout, el, !playing, ++count); } } function "
-    "loadHandler() { var audioStarted = false; var el = "
-    "document.getElementById(\"audio_output_frame\"); el.onplay = (event) => "
-    "{ if (audioStarted) { return; } audioStarted = true; "
-    "setTimeout(togglePlayback, 150, el, audioStarted, 0); "
-    "}; }</script></head><body "
-    "onload=\"loadHandler()\"><p>TEST</p><audio "
-    "id=\"audio_output_frame\" src=\"" AUDIO_DATA
-    "\" autoplay "
-    "style=\"display:none\"></audio></body></html>";
+    "<!DOCTYPE html><html><head><meta charset=\"utf-8\"/>"
+    "<script type=\"text/javascript\">"
+    "var timeouts = [150, 1950, 150, 2000, 150, 2050, 150, 2100, 150, 2200, "
+    "150];"
+    "var count = 0;"
+    "function togglePlayback(el, playing, count) {"
+    "  if (playing) {"
+    // "    console.log('togglePlayback pause (' + count + ')');"
+    "    el.pause();"
+    "  } else {"
+    // "    console.log('togglePlayback play (' + count + ')');"
+    "    el.play();"
+    "  }"
+    "}"
+    "function loadHandler() {"
+    "  var el = document.getElementById(\"audio_output_frame\");"
+    "  el.onplay = (event) => {"
+    "    var timeout = timeouts[count];"
+    // "    console.log('loadHandler onplay (' + count + ') wait ' + timeout);"
+    "    if (count < timeouts.length) {"
+    "      setTimeout(togglePlayback, timeout, el, true, count);"
+    "      count++;"
+    "    }"
+    "  };"
+    "  el.onpause = (event) => {"
+    "    var timeout = timeouts[count];"
+    // "    console.log('loadHandler onpause (' + count + ') wait ' + timeout);"
+    "    if (count < timeouts.length) {"
+    "      setTimeout(togglePlayback, timeout, el, false, count);"
+    "      count++;"
+    "    }"
+    "  };"
+    "}"
+    "</script></head>"
+    "<body onload=\"loadHandler()\"><p>TEST</p>"
+    "<audio id=\"audio_output_frame\" src=\"" AUDIO_DATA
+    "\" autoplay style=\"display:none\"></audio></body></html>";
 
 class AudioOutputTest : public ClientAppBrowser::Delegate {
  public:
@@ -895,7 +916,7 @@
   void OnAudioStreamPacket(CefRefPtr<CefBrowser> browser,
                            const float** data,
                            int frames,
-                           int64 pts) override {
+                           int64_t pts) override {
     EXPECT_TRUE(got_on_audio_stream_started_);
     EXPECT_TRUE(browser_->IsSame(browser));
     EXPECT_EQ(frames, kFramesPerBuffer);
@@ -950,7 +971,7 @@
   void OnAudioStreamPacket(CefRefPtr<CefBrowser> browser,
                            const float** data,
                            int frames,
-                           int64 pts) override {
+                           int64_t pts) override {
     if (!got_on_audio_stream_packet_.isSet()) {
       browser->GetMainFrame()->ExecuteJavaScript(
           "var ifr = document.getElementById(\"audio_output_frame\"); "
@@ -981,7 +1002,7 @@
   void OnAudioStreamPacket(CefRefPtr<CefBrowser> browser,
                            const float** data,
                            int frames,
-                           int64 pts) override {
+                           int64_t pts) override {
     if (!got_on_audio_stream_packet_.isSet()) {
       CloseBrowser(browser, true);
     }
@@ -1034,8 +1055,9 @@
 
   void OnAudioStreamStopped(CefRefPtr<CefBrowser> browser) override {
     EXPECT_EQ(start_count_, ++stop_count_);
-    if (stop_count_ == kToggleCount)
+    if (stop_count_ == kToggleCount) {
       AudioTestHandler::OnAudioStreamStopped(browser);
+    }
   }
 
  protected:
diff --git a/src/tests/ceftests/certificate_error_unittest.cc b/src/tests/ceftests/certificate_error_unittest.cc
new file mode 100644
index 0000000..927c6c1
--- /dev/null
+++ b/src/tests/ceftests/certificate_error_unittest.cc
@@ -0,0 +1,526 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "include/base/cef_callback.h"
+#include "include/test/cef_test_server.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "include/wrapper/cef_stream_resource_handler.h"
+#include "tests/ceftests/test_handler.h"
+#include "tests/ceftests/test_server_observer.h"
+#include "tests/ceftests/test_util.h"
+#include "tests/gtest/include/gtest/gtest.h"
+#include "tests/shared/common/string_util.h"
+
+namespace {
+
+// Used to observe HTTP and HTTPS server requests.
+class OtherServerObserver : public test_server::ObserverHelper {
+ public:
+  using ReadyCallback = base::OnceCallback<void(const std::string& url)>;
+  using RequestCallback =
+      base::RepeatingCallback<bool(CefRefPtr<CefRequest> request,
+                                   const ResponseCallback& response_callback)>;
+
+  OtherServerObserver(bool https_server,
+                      ReadyCallback ready_callback,
+                      base::OnceClosure done_callback,
+                      const RequestCallback& request_callback)
+      : ready_callback_(std::move(ready_callback)),
+        done_callback_(std::move(done_callback)),
+        request_callback_(request_callback) {
+    EXPECT_TRUE(ready_callback_);
+    EXPECT_TRUE(done_callback_);
+    EXPECT_TRUE(request_callback_);
+    Initialize(https_server);
+  }
+
+  void OnInitialized(const std::string& server_origin) override {
+    EXPECT_UI_THREAD();
+    std::move(ready_callback_).Run(server_origin);
+  }
+
+  void OnShutdown() override {
+    EXPECT_UI_THREAD();
+    std::move(done_callback_).Run();
+    delete this;
+  }
+
+  bool OnTestServerRequest(CefRefPtr<CefRequest> request,
+                           const ResponseCallback& response_callback) override {
+    EXPECT_UI_THREAD();
+    return request_callback_.Run(request, response_callback);
+  }
+
+ private:
+  ReadyCallback ready_callback_;
+  base::OnceClosure done_callback_;
+  RequestCallback request_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(OtherServerObserver);
+};
+
+class CertificateErrorTest : public TestHandler, public CefTestServerHandler {
+ public:
+  using ResponseCallback = test_server::ObserverHelper::ResponseCallback;
+
+  enum class OtherServerType {
+    NONE,
+    HTTP,
+    HTTPS,
+  };
+
+  CertificateErrorTest(
+      cef_test_cert_type_t cert_type,
+      bool expect_load_success,
+      bool expect_certificate_error,
+      OtherServerType other_server_type = OtherServerType::NONE)
+      : cert_type_(cert_type),
+        expect_load_success_(expect_load_success),
+        expect_certificate_error_(expect_certificate_error),
+        other_server_type_(other_server_type) {}
+
+  void RunTest() override {
+    SetTestTimeout();
+    CefPostTask(TID_UI,
+                base::BindOnce(&CertificateErrorTest::StartHttpsServer, this));
+  }
+
+  bool OnTestServerRequest(
+      CefRefPtr<CefTestServer> server,
+      CefRefPtr<CefRequest> request,
+      CefRefPtr<CefTestServerConnection> connection) override {
+    CefPostTask(TID_UI,
+                base::BindOnce(&CertificateErrorTest::HandleHttpsRequest, this,
+                               request, connection));
+    return true;
+  }
+
+  bool OnOtherServerRequest(CefRefPtr<CefRequest> request,
+                            const ResponseCallback& response_callback) {
+    EXPECT_UI_THREAD();
+    HandleOtherServerRequest(request, response_callback);
+    return true;
+  }
+
+  bool OnCertificateError(CefRefPtr<CefBrowser> browser,
+                          cef_errorcode_t cert_error,
+                          const CefString& request_url,
+                          CefRefPtr<CefSSLInfo> ssl_info,
+                          CefRefPtr<CefCallback> callback) override {
+    EXPECT_UI_THREAD();
+    got_certificate_error_.yes();
+
+    EXPECT_STREQ(GetEndURL().c_str(), request_url.ToString().c_str());
+
+    if (expect_load_success_) {
+      // Continue the load.
+      callback->Continue();
+      return true;
+    }
+
+    // Cancel the load.
+    return false;
+  }
+
+  void OnLoadEnd(CefRefPtr<CefBrowser> browser,
+                 CefRefPtr<CefFrame> frame,
+                 int httpStatusCode) override {
+    EXPECT_UI_THREAD();
+
+    TestHandler::OnLoadEnd(browser, frame, httpStatusCode);
+
+    const std::string& url = frame->GetURL();
+    if (url == GetEndURL()) {
+      got_load_end_.yes();
+      MaybeEndTest();
+    }
+  }
+
+  void OnLoadError(CefRefPtr<CefBrowser> browser,
+                   CefRefPtr<CefFrame> frame,
+                   ErrorCode errorCode,
+                   const CefString& errorText,
+                   const CefString& failedUrl) override {
+    EXPECT_UI_THREAD();
+
+    const std::string& url = frame->GetURL();
+    if (url == GetEndURL()) {
+      got_load_error_.yes();
+      MaybeEndTest();
+    }
+  }
+
+  void DestroyTest() override {
+    EXPECT_FALSE(server_);
+    EXPECT_FALSE(other_server_);
+
+    EXPECT_TRUE(got_load_end_);
+
+    if (expect_load_success_) {
+      EXPECT_TRUE(got_request_);
+      EXPECT_FALSE(got_load_error_);
+    } else {
+      EXPECT_FALSE(got_request_);
+      EXPECT_TRUE(got_load_error_);
+    }
+
+    EXPECT_EQ(expect_certificate_error_, got_certificate_error_);
+
+    TestHandler::DestroyTest();
+  }
+
+ protected:
+  virtual std::string GetStartURL() const {
+    return server_origin() + "/index.html";
+  }
+  virtual std::string GetEndURL() const { return GetStartURL(); }
+
+  const std::string& server_origin() const { return server_origin_; }
+  const std::string& other_origin() const { return other_origin_; }
+
+  virtual void HandleOtherServerRequest(
+      CefRefPtr<CefRequest> request,
+      const ResponseCallback& response_callback) {}
+
+ private:
+  void HandleHttpsRequest(CefRefPtr<CefRequest> request,
+                          CefRefPtr<CefTestServerConnection> connection) {
+    EXPECT_UI_THREAD();
+    got_request_.yes();
+
+    const std::string response = "<html><body>Certificate Test</body></html>";
+    connection->SendHttp200Response("text/html", response.c_str(),
+                                    response.size());
+
+    MaybeEndTest();
+  }
+
+  void MaybeEndTest() {
+    EXPECT_UI_THREAD();
+
+    bool end_test;
+    if (expect_load_success_) {
+      end_test = got_load_end_ && got_request_;
+    } else {
+      end_test = got_load_end_ && got_load_error_;
+    }
+
+    if (end_test) {
+      StopHttpsServer();
+    }
+  }
+
+  void StartHttpsServer() {
+    EXPECT_UI_THREAD();
+
+    server_ = CefTestServer::CreateAndStart(/*port=*/0, /*https_server=*/true,
+                                            cert_type_, this);
+    server_origin_ = server_->GetOrigin();
+
+    if (other_server_type_ != OtherServerType::NONE) {
+      StartOtherServer();
+    } else {
+      DoCreateBrowser();
+    }
+  }
+
+  void StartOtherServer() {
+    EXPECT_UI_THREAD();
+    EXPECT_NE(other_server_type_, OtherServerType::NONE);
+
+    // Will delete itself after the server stops.
+    other_server_ = new OtherServerObserver(
+        other_server_type_ == OtherServerType::HTTPS,
+        base::BindOnce(&CertificateErrorTest::StartedOtherServer, this),
+        base::BindOnce(&CertificateErrorTest::StoppedOtherServer, this),
+        base::BindRepeating(&CertificateErrorTest::OnOtherServerRequest, this));
+  }
+
+  void StartedOtherServer(const std::string& other_origin) {
+    EXPECT_UI_THREAD();
+    EXPECT_NE(other_server_type_, OtherServerType::NONE);
+
+    other_origin_ = other_origin;
+    DoCreateBrowser();
+  }
+
+  void DoCreateBrowser() {
+    EXPECT_UI_THREAD();
+
+    // Create a new in-memory context so certificate decisions aren't cached.
+    CreateTestRequestContext(
+        TEST_RC_MODE_CUSTOM_WITH_HANDLER, /*cache_path=*/std::string(),
+        base::BindOnce(&CertificateErrorTest::DoCreateBrowserContinue, this));
+  }
+
+  void DoCreateBrowserContinue(CefRefPtr<CefRequestContext> request_context) {
+    EXPECT_UI_THREAD();
+
+    CreateBrowser(GetStartURL(), request_context);
+  }
+
+  void StopHttpsServer() {
+    EXPECT_UI_THREAD();
+
+    server_->Stop();
+    server_ = nullptr;
+
+    if (other_server_type_ != OtherServerType::NONE) {
+      // Stop the other server. Results in a call to StoppedOtherServer().
+      other_server_->Shutdown();
+    } else {
+      DestroyTest();
+    }
+  }
+
+  void StoppedOtherServer() {
+    EXPECT_UI_THREAD();
+    EXPECT_NE(other_server_type_, OtherServerType::NONE);
+
+    other_server_ = nullptr;
+    DestroyTest();
+  }
+
+  const cef_test_cert_type_t cert_type_;
+  const bool expect_load_success_;
+  const bool expect_certificate_error_;
+  const OtherServerType other_server_type_;
+
+  CefRefPtr<CefTestServer> server_;
+  std::string server_origin_;
+
+  OtherServerObserver* other_server_ = nullptr;
+  std::string other_origin_;
+
+  TrackCallback got_request_;
+  TrackCallback got_certificate_error_;
+  TrackCallback got_load_end_;
+  TrackCallback got_load_error_;
+
+  IMPLEMENT_REFCOUNTING(CertificateErrorTest);
+};
+
+}  // namespace
+
+TEST(CertificateErrorTest, DirectNoError) {
+  CefRefPtr<CertificateErrorTest> handler = new CertificateErrorTest(
+      /*cert_type=*/CEF_TEST_CERT_OK_DOMAIN, /*expect_load_success=*/true,
+      /*expect_certificate_error=*/false);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(CertificateErrorTest, DirectExpired) {
+  CefRefPtr<CertificateErrorTest> handler = new CertificateErrorTest(
+      /*cert_type=*/CEF_TEST_CERT_EXPIRED, /*expect_load_success=*/false,
+      /*expect_certificate_error=*/true);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+namespace {
+
+class DirectMismatchedTest : public CertificateErrorTest {
+ public:
+  DirectMismatchedTest(bool continue_invalid_certificate)
+      : CertificateErrorTest(
+            /*cert_type=*/CEF_TEST_CERT_OK_DOMAIN,
+            /*expect_load_success=*/continue_invalid_certificate,
+            /*expect_certificate_error=*/true) {}
+
+ protected:
+  std::string GetStartURL() const {
+    // Load by IP address when the certificate expects a domain.
+    return client::AsciiStrReplace(server_origin(), "localhost", "127.0.0.1") +
+           "/index.html";
+  }
+};
+
+}  // namespace
+
+TEST(CertificateErrorTest, DirectMismatchedCancel) {
+  CefRefPtr<DirectMismatchedTest> handler =
+      new DirectMismatchedTest(/*continue_invalid_certificate=*/false);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(CertificateErrorTest, DirectMismatchedContinue) {
+  CefRefPtr<DirectMismatchedTest> handler =
+      new DirectMismatchedTest(/*continue_invalid_certificate=*/true);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+namespace {
+
+class RedirectMismatchedFromHandlerTest : public CertificateErrorTest {
+ public:
+  RedirectMismatchedFromHandlerTest(bool continue_invalid_certificate,
+                                    bool redirect_from_https)
+      : CertificateErrorTest(
+            /*cert_type=*/CEF_TEST_CERT_OK_DOMAIN,
+            /*expect_load_success=*/continue_invalid_certificate,
+            /*expect_certificate_error=*/true),
+        redirect_from_https_(redirect_from_https) {}
+
+  CefRefPtr<CefResourceHandler> GetResourceHandler(
+      CefRefPtr<CefBrowser> browser,
+      CefRefPtr<CefFrame> frame,
+      CefRefPtr<CefRequest> request) override {
+    EXPECT_IO_THREAD();
+
+    const std::string& url = request->GetURL();
+    if (url == GetStartURL()) {
+      // Redirect to the end URL.
+      return new CefStreamResourceHandler(
+          301, "Permanent Redirect", "text/html", {{"Location", GetEndURL()}},
+          /*stream=*/nullptr);
+    }
+
+    return TestHandler::GetResourceHandler(browser, frame, request);
+  }
+
+ protected:
+  std::string GetStartURL() const override {
+    return redirect_from_https_ ? "https://certificate-test.com/index.html"
+                                : "http://certificate-test.com/index.html";
+  }
+
+  std::string GetEndURL() const override {
+    // Load by IP address when the certificate expects a domain.
+    return client::AsciiStrReplace(server_origin(), "localhost", "127.0.0.1") +
+           "/index.html";
+  }
+
+ private:
+  const bool redirect_from_https_;
+};
+
+}  // namespace
+
+TEST(CertificateErrorTest, RedirectMismatchedFromHttpsResourceCancel) {
+  CefRefPtr<RedirectMismatchedFromHandlerTest> handler =
+      new RedirectMismatchedFromHandlerTest(
+          /*continue_invalid_certificate=*/false,
+          /*redirect_from_https=*/true);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(CertificateErrorTest, RedirectMismatchedFromHttpsResourceContinue) {
+  CefRefPtr<RedirectMismatchedFromHandlerTest> handler =
+      new RedirectMismatchedFromHandlerTest(
+          /*continue_invalid_certificate=*/true,
+          /*redirect_from_https=*/true);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(CertificateErrorTest, RedirectMismatchedFromHttpResourceCancel) {
+  CefRefPtr<RedirectMismatchedFromHandlerTest> handler =
+      new RedirectMismatchedFromHandlerTest(
+          /*continue_invalid_certificate=*/false,
+          /*redirect_from_https=*/false);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(CertificateErrorTest, RedirectMismatchedFromHttpResourceContinue) {
+  CefRefPtr<RedirectMismatchedFromHandlerTest> handler =
+      new RedirectMismatchedFromHandlerTest(
+          /*continue_invalid_certificate=*/true,
+          /*redirect_from_https=*/false);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+namespace {
+
+class RedirectMismatchedFromServerTest : public CertificateErrorTest {
+ public:
+  RedirectMismatchedFromServerTest(bool continue_invalid_certificate,
+                                   bool redirect_from_https)
+      : CertificateErrorTest(
+            /*cert_type=*/CEF_TEST_CERT_OK_DOMAIN,
+            /*expect_load_success=*/continue_invalid_certificate,
+            /*expect_certificate_error=*/true,
+            redirect_from_https ? OtherServerType::HTTPS
+                                : OtherServerType::HTTP) {}
+
+  void HandleOtherServerRequest(
+      CefRefPtr<CefRequest> request,
+      const ResponseCallback& response_callback) override {
+    EXPECT_UI_THREAD();
+
+    EXPECT_FALSE(got_other_request_);
+    got_other_request_.yes();
+
+    const std::string& url = request->GetURL();
+    EXPECT_STREQ(GetStartURL().c_str(), url.c_str());
+
+    // Redirect to the end URL.
+    auto response = CefResponse::Create();
+    response->SetMimeType("text/html");
+    response->SetStatus(301);  // Permanent Redirect
+    response->SetHeaderByName("Location", GetEndURL(),
+                              /*overwrite=*/true);
+
+    response_callback.Run(response, /*response_body=*/std::string());
+  }
+
+  void DestroyTest() override {
+    EXPECT_TRUE(got_other_request_);
+    CertificateErrorTest::DestroyTest();
+  }
+
+ protected:
+  std::string GetStartURL() const override {
+    return other_origin() + "/index.html";
+  }
+
+  std::string GetEndURL() const override {
+    // Load by IP address when the certificate expects a domain.
+    return client::AsciiStrReplace(server_origin(), "localhost", "127.0.0.1") +
+           "/index.html";
+  }
+
+ private:
+  TrackCallback got_other_request_;
+};
+
+}  // namespace
+
+TEST(CertificateErrorTest, RedirectMismatchedFromHttpsServerCancel) {
+  CefRefPtr<RedirectMismatchedFromServerTest> handler =
+      new RedirectMismatchedFromServerTest(
+          /*continue_invalid_certificate=*/false, /*redirect_from_https=*/true);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(CertificateErrorTest, RedirectMismatchedFromHttpsServerContinue) {
+  CefRefPtr<RedirectMismatchedFromServerTest> handler =
+      new RedirectMismatchedFromServerTest(
+          /*continue_invalid_certificate=*/true, /*redirect_from_https=*/true);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(CertificateErrorTest, RedirectMismatchedFromHttpServerCancel) {
+  CefRefPtr<RedirectMismatchedFromServerTest> handler =
+      new RedirectMismatchedFromServerTest(
+          /*continue_invalid_certificate=*/false,
+          /*redirect_from_https=*/false);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(CertificateErrorTest, RedirectMismatchedFromHttpServerContinue) {
+  CefRefPtr<RedirectMismatchedFromServerTest> handler =
+      new RedirectMismatchedFromServerTest(
+          /*continue_invalid_certificate=*/true, /*redirect_from_https=*/false);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
diff --git a/src/tests/ceftests/client_app_delegates.cc b/src/tests/ceftests/client_app_delegates.cc
index a577a53..10efbfc 100644
--- a/src/tests/ceftests/client_app_delegates.cc
+++ b/src/tests/ceftests/client_app_delegates.cc
@@ -13,20 +13,24 @@
   extern void CreateAudioOutputTests(ClientAppBrowser::DelegateSet & delegates);
   CreateAudioOutputTests(delegates);
 
-  // Bring in the Navigation tests.
-  extern void CreateNavigationBrowserTests(ClientAppBrowser::DelegateSet &
-                                           delegates);
-  CreateNavigationBrowserTests(delegates);
-
-  // Bring in the plugin tests.
-  extern void CreatePluginBrowserTests(ClientAppBrowser::DelegateSet &
-                                       delegates);
-  CreatePluginBrowserTests(delegates);
+  // Bring in the CORS tests.
+  extern void CreateCorsBrowserTests(ClientAppBrowser::DelegateSet & delegates);
+  CreateCorsBrowserTests(delegates);
 
   // Bring in the preference tests.
   extern void CreatePreferenceBrowserTests(ClientAppBrowser::DelegateSet &
                                            delegates);
   CreatePreferenceBrowserTests(delegates);
+
+  // Bring in the media access tests.
+  extern void CreateMediaAccessBrowserTests(ClientAppBrowser::DelegateSet &
+                                            delegates);
+  CreateMediaAccessBrowserTests(delegates);
+
+  // Bring in URLRequest tests.
+  extern void CreateURLRequestBrowserTests(ClientAppBrowser::DelegateSet &
+                                           delegates);
+  CreateURLRequestBrowserTests(delegates);
 }
 
 void CreateRenderDelegates(ClientAppRenderer::DelegateSet& delegates) {
@@ -55,6 +59,11 @@
                                                 delegates);
   CreateProcessMessageRendererTests(delegates);
 
+  // Bring in the shared process message tests.
+  extern void CreateSharedProcessMessageTests(ClientAppRenderer::DelegateSet &
+                                              delegates);
+  CreateSharedProcessMessageTests(delegates);
+
   // Bring in the RequestHandler tests.
   extern void CreateRequestHandlerRendererTests(ClientAppRenderer::DelegateSet &
                                                 delegates);
@@ -70,41 +79,48 @@
                                         delegates);
   CreateThreadRendererTests(delegates);
 
-  // Bring in the URLRequest tests.
-  extern void CreateURLRequestRendererTests(ClientAppRenderer::DelegateSet &
-                                            delegates);
-  CreateURLRequestRendererTests(delegates);
-
   // Bring in the V8 tests.
   extern void CreateV8RendererTests(ClientAppRenderer::DelegateSet & delegates);
   CreateV8RendererTests(delegates);
 }
 
-void RegisterCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar,
-                           std::vector<CefString>& cookiable_schemes) {
+void RegisterCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar) {
   // Bring in the scheme handler tests.
   extern void RegisterSchemeHandlerCustomSchemes(
-      CefRawPtr<CefSchemeRegistrar> registrar,
-      std::vector<CefString> & cookiable_schemes);
-  RegisterSchemeHandlerCustomSchemes(registrar, cookiable_schemes);
+      CefRawPtr<CefSchemeRegistrar> registrar);
+  RegisterSchemeHandlerCustomSchemes(registrar);
 
   // Bring in the cookie tests.
   extern void RegisterCookieCustomSchemes(
-      CefRawPtr<CefSchemeRegistrar> registrar,
-      std::vector<CefString> & cookiable_schemes);
-  RegisterCookieCustomSchemes(registrar, cookiable_schemes);
+      CefRawPtr<CefSchemeRegistrar> registrar);
+  RegisterCookieCustomSchemes(registrar);
 
   // Bring in the URLRequest tests.
   extern void RegisterURLRequestCustomSchemes(
-      CefRawPtr<CefSchemeRegistrar> registrar,
-      std::vector<CefString> & cookiable_schemes);
-  RegisterURLRequestCustomSchemes(registrar, cookiable_schemes);
+      CefRawPtr<CefSchemeRegistrar> registrar);
+  RegisterURLRequestCustomSchemes(registrar);
 
   // Bring in the resource request handler tests.
   extern void RegisterResourceRequestHandlerCustomSchemes(
-      CefRawPtr<CefSchemeRegistrar> registrar,
-      std::vector<CefString> & cookiable_schemes);
-  RegisterResourceRequestHandlerCustomSchemes(registrar, cookiable_schemes);
+      CefRawPtr<CefSchemeRegistrar> registrar);
+  RegisterResourceRequestHandlerCustomSchemes(registrar);
+}
+
+void RegisterCookieableSchemes(std::vector<std::string>& cookieable_schemes) {
+  // Bring in the scheme handler tests.
+  extern void RegisterSchemeHandlerCookieableSchemes(std::vector<std::string> &
+                                                     cookieable_schemes);
+  RegisterSchemeHandlerCookieableSchemes(cookieable_schemes);
+
+  // Bring in the cookie tests.
+  extern void RegisterCookieCookieableSchemes(std::vector<std::string> &
+                                              cookieable_schemes);
+  RegisterCookieCookieableSchemes(cookieable_schemes);
+
+  // Bring in the URLRequest tests.
+  extern void RegisterURLRequestCookieableSchemes(std::vector<std::string> &
+                                                  cookieable_schemes);
+  RegisterURLRequestCookieableSchemes(cookieable_schemes);
 }
 
 namespace client {
@@ -115,20 +131,19 @@
 }
 
 // static
-CefRefPtr<CefPrintHandler> ClientAppBrowser::CreatePrintHandler() {
-  return nullptr;
-}
-
-// static
 void ClientAppRenderer::CreateDelegates(DelegateSet& delegates) {
   ::CreateRenderDelegates(delegates);
 }
 
 // static
-void ClientApp::RegisterCustomSchemes(
-    CefRawPtr<CefSchemeRegistrar> registrar,
-    std::vector<CefString>& cookiable_schemes) {
-  ::RegisterCustomSchemes(registrar, cookiable_schemes);
+void ClientApp::RegisterCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar) {
+  ::RegisterCustomSchemes(registrar);
+}
+
+// static
+void ClientAppBrowser::RegisterCookieableSchemes(
+    std::vector<std::string>& cookieable_schemes) {
+  ::RegisterCookieableSchemes(cookieable_schemes);
 }
 
 }  // namespace client
diff --git a/src/tests/ceftests/command_line_unittest.cc b/src/tests/ceftests/command_line_unittest.cc
index abb71c4..978ff1f 100644
--- a/src/tests/ceftests/command_line_unittest.cc
+++ b/src/tests/ceftests/command_line_unittest.cc
@@ -18,9 +18,10 @@
   EXPECT_TRUE(command_line->HasSwitch("switch1"));
   std::string switch1 = command_line->GetSwitchValue("switch1");
   EXPECT_EQ("", switch1);
-  EXPECT_TRUE(command_line->HasSwitch("switch2"));
-  std::string switch2 = command_line->GetSwitchValue("switch2");
-  EXPECT_EQ("val2", switch2);
+  // Switch names are converted to lowercase but values are left unchanged.
+  EXPECT_TRUE(command_line->HasSwitch("SWITCH2"));
+  std::string switch2 = command_line->GetSwitchValue("SWITCH2");
+  EXPECT_EQ("VAL2", switch2);
   EXPECT_TRUE(command_line->HasSwitch("switch3"));
   std::string switch3 = command_line->GetSwitchValue("switch3");
   EXPECT_EQ("val3", switch3);
@@ -45,7 +46,7 @@
       EXPECT_EQ("", val);
     } else if (name == "switch2") {
       has2 = true;
-      EXPECT_EQ("val2", val);
+      EXPECT_EQ("VAL2", val);
     } else if (name == "switch3") {
       has3 = true;
       EXPECT_EQ("val3", val);
@@ -86,10 +87,10 @@
 
 #if defined(OS_WIN)
   command_line->InitFromString(
-      "test.exe --switch1 -switch2=val2 /switch3=val3 "
+      "test.exe --switch1 -switch2=VAL2 /switch3=val3 "
       "-switch4=\"val 4\" arg1 \"arg 2\"");
 #else
-  const char* args[] = {"test.exe",      "--switch1",      "-switch2=val2",
+  const char* args[] = {"test.exe",      "--switch1",      "-switch2=VAL2",
                         "-switch3=val3", "-switch4=val 4", "arg1",
                         "arg 2"};
   command_line->InitFromArgv(sizeof(args) / sizeof(char*), args);
@@ -105,7 +106,7 @@
 
   command_line->SetProgram("test.exe");
   command_line->AppendSwitch("switch1");
-  command_line->AppendSwitchWithValue("switch2", "val2");
+  command_line->AppendSwitchWithValue("switch2", "VAL2");
   command_line->AppendSwitchWithValue("switch3", "val3");
   command_line->AppendSwitchWithValue("switch4", "val 4");
   command_line->AppendArgument("arg1");
@@ -121,7 +122,7 @@
 
   command_line->SetProgram("test.exe");
   command_line->AppendSwitch("-switch1");
-  command_line->AppendSwitchWithValue("--switch2", "val2");
+  command_line->AppendSwitchWithValue("--switch2", "VAL2");
   command_line->AppendSwitchWithValue("-switch3", "val3");
   command_line->AppendSwitchWithValue("-switch4", "val 4");
 
@@ -133,3 +134,19 @@
 
   VerifyCommandLine(command_line, arg1, arg2);
 }
+
+// Test that command line switch names are converted to lowercase ASCII.
+TEST(CommandLineTest, IgnoreCase) {
+  CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
+  EXPECT_TRUE(command_line.get() != nullptr);
+
+  command_line->SetProgram("test.exe");
+  command_line->AppendSwitch("-Switch1");
+  command_line->AppendSwitchWithValue("-SWITCH2", "VAL2");
+  command_line->AppendSwitchWithValue("-switch3", "val3");
+  command_line->AppendSwitchWithValue("-switch4", "val 4");
+  command_line->AppendArgument("arg1");
+  command_line->AppendArgument("arg 2");
+
+  VerifyCommandLine(command_line);
+}
diff --git a/src/tests/ceftests/cookie_unittest.cc b/src/tests/ceftests/cookie_unittest.cc
index e4672a1..235e013 100644
--- a/src/tests/ceftests/cookie_unittest.cc
+++ b/src/tests/ceftests/cookie_unittest.cc
@@ -2,9 +2,11 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
+#include <algorithm>
+#include <chrono>
 #include <vector>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/base/cef_logging.h"
 #include "include/base/cef_ref_counted.h"
 #include "include/cef_cookie.h"
@@ -15,13 +17,15 @@
 #include "include/wrapper/cef_closure_task.h"
 #include "tests/ceftests/routing_test_handler.h"
 #include "tests/ceftests/test_handler.h"
+#include "tests/ceftests/test_server_observer.h"
 #include "tests/ceftests/test_suite.h"
 #include "tests/ceftests/test_util.h"
 #include "tests/gtest/include/gtest/gtest.h"
+#include "tests/shared/common/string_util.h"
 
 namespace {
 
-const char* kTestUrl = "http://www.test.com/path/to/cookietest/foo.html";
+const char* kTestUrl = "https://www.test.com/path/to/cookietest/foo.html";
 const char* kTestDomain = "www.test.com";
 const char* kTestPath = "/path/to/cookietest";
 
@@ -92,12 +96,14 @@
  public:
   TestVisitor(CookieVector* cookies,
               bool deleteCookies,
-              const base::Closure& callback)
-      : cookies_(cookies), delete_cookies_(deleteCookies), callback_(callback) {
+              base::OnceClosure callback)
+      : cookies_(cookies),
+        delete_cookies_(deleteCookies),
+        callback_(std::move(callback)) {
     EXPECT_TRUE(cookies_);
     EXPECT_FALSE(callback_.is_null());
   }
-  ~TestVisitor() override { callback_.Run(); }
+  ~TestVisitor() override { std::move(callback_).Run(); }
 
   bool Visit(const CefCookie& cookie,
              int count,
@@ -105,15 +111,16 @@
              bool& deleteCookie) override {
     EXPECT_TRUE(CefCurrentlyOn(TID_UI));
     cookies_->push_back(cookie);
-    if (delete_cookies_)
+    if (delete_cookies_) {
       deleteCookie = true;
+    }
     return true;
   }
 
  private:
   CookieVector* cookies_;
   bool delete_cookies_;
-  base::Closure callback_;
+  base::OnceClosure callback_;
 
   IMPLEMENT_REFCOUNTING(TestVisitor);
 };
@@ -144,6 +151,14 @@
   event->Wait();
 }
 
+time_t GetExpiryDate() {
+  static time_t expiry_time = [] {
+    return std::chrono::system_clock::to_time_t(
+        std::chrono::system_clock::now() + std::chrono::hours(1));
+  }();
+  return expiry_time;
+}
+
 // Create a test cookie. If |withDomain| is true a domain cookie will be
 // created, otherwise a host cookie will be created.
 void CreateCookie(CefRefPtr<CefCookieManager> manager,
@@ -153,15 +168,17 @@
                   CefRefPtr<CefWaitableEvent> event) {
   CefString(&cookie.name).FromASCII("my_cookie");
   CefString(&cookie.value).FromASCII("My Value");
-  if (withDomain)
+  if (withDomain) {
     CefString(&cookie.domain).FromASCII(kTestDomain);
+  }
   CefString(&cookie.path).FromASCII(kTestPath);
   if (!sessionCookie) {
     cookie.has_expires = true;
-    cookie.expires.year = 2200;
-    cookie.expires.month = 4;
-    cookie.expires.day_of_week = 5;
-    cookie.expires.day_of_month = 11;
+    // Must choose the expiry date dynamically due to the
+    // "ClampCookieExpiryTo400Days" feature enabled in M104.
+    cef_time_t expiry_time;
+    EXPECT_TRUE(cef_time_from_timet(GetExpiryDate(), &expiry_time));
+    EXPECT_TRUE(cef_time_to_basetime(&expiry_time, &cookie.expires));
   }
 
   CookieVector cookies;
@@ -176,10 +193,10 @@
                      bool includeHttpOnly,
                      CookieVector& cookies,
                      bool deleteCookies,
-                     const base::Closure& callback) {
+                     base::OnceClosure callback) {
   EXPECT_TRUE(manager->VisitUrlCookies(
       url, includeHttpOnly,
-      new TestVisitor(&cookies, deleteCookies, callback)));
+      new TestVisitor(&cookies, deleteCookies, std::move(callback))));
 }
 
 // Visit URL cookies. Block on |event|.
@@ -190,7 +207,7 @@
                      bool deleteCookies,
                      CefRefPtr<CefWaitableEvent> event) {
   VisitUrlCookies(manager, url, includeHttpOnly, cookies, deleteCookies,
-                  base::Bind(&CefWaitableEvent::Signal, event));
+                  base::BindOnce(&CefWaitableEvent::Signal, event));
   event->Wait();
 }
 
@@ -198,9 +215,9 @@
 void VisitAllCookies(CefRefPtr<CefCookieManager> manager,
                      CookieVector& cookies,
                      bool deleteCookies,
-                     const base::Closure& callback) {
+                     base::OnceClosure callback) {
   EXPECT_TRUE(manager->VisitAllCookies(
-      new TestVisitor(&cookies, deleteCookies, callback)));
+      new TestVisitor(&cookies, deleteCookies, std::move(callback))));
 }
 
 // Visit all cookies. Block on |event|.
@@ -209,7 +226,7 @@
                      bool deleteCookies,
                      CefRefPtr<CefWaitableEvent> event) {
   VisitAllCookies(manager, cookies, deleteCookies,
-                  base::Bind(&CefWaitableEvent::Signal, event));
+                  base::BindOnce(&CefWaitableEvent::Signal, event));
   event->Wait();
 }
 
@@ -227,26 +244,21 @@
   VisitUrlCookies(manager, kTestUrl, false, cookies, deleteCookies, event);
 
   EXPECT_EQ(1U, cookies.size());
-  if (cookies.size() != 1U)
+  if (cookies.size() != 1U) {
     return;
+  }
 
   const CefCookie& cookie_read = cookies[0];
   EXPECT_EQ(CefString(&cookie_read.name), "my_cookie");
   EXPECT_EQ(CefString(&cookie_read.value), "My Value");
-  if (withDomain)
+  if (withDomain) {
     EXPECT_EQ(CefString(&cookie_read.domain), ".www.test.com");
-  else
+  } else {
     EXPECT_EQ(CefString(&cookie_read.domain), kTestDomain);
+  }
   EXPECT_EQ(CefString(&cookie_read.path), kTestPath);
   EXPECT_EQ(cookie.has_expires, cookie_read.has_expires);
-  EXPECT_EQ(cookie.expires.year, cookie_read.expires.year);
-  EXPECT_EQ(cookie.expires.month, cookie_read.expires.month);
-  EXPECT_EQ(cookie.expires.day_of_week, cookie_read.expires.day_of_week);
-  EXPECT_EQ(cookie.expires.day_of_month, cookie_read.expires.day_of_month);
-  EXPECT_EQ(cookie.expires.hour, cookie_read.expires.hour);
-  EXPECT_EQ(cookie.expires.minute, cookie_read.expires.minute);
-  EXPECT_EQ(cookie.expires.second, cookie_read.expires.second);
-  EXPECT_EQ(cookie.expires.millisecond, cookie_read.expires.millisecond);
+  EXPECT_EQ(cookie.expires.val, cookie_read.expires.val);
   EXPECT_EQ(cookie.same_site, cookie_read.same_site);
   EXPECT_EQ(cookie.priority, cookie_read.priority);
 }
@@ -307,7 +319,7 @@
   CookieVector cookies;
 
   CefCookie cookie;
-  const char* kUrl = "http://www.xyz.com";
+  const char* kUrl = "https://www.xyz.com";
   CefString(&cookie.name).FromASCII("invalid1");
   CefString(&cookie.value).FromASCII("invalid1");
   CefString(&cookie.domain).FromASCII(".zyx.com");  // domain mismatch
@@ -371,8 +383,9 @@
   VisitUrlCookies(manager, kTestUrl, false, cookies, false, event);
 
   EXPECT_EQ(3U, cookies.size());
-  if (cookies.size() != 3U)
+  if (cookies.size() != 3U) {
     return;
+  }
 
   EXPECT_EQ(CefString(&cookies[0].name), "my_cookie0");
   EXPECT_EQ(CefString(&cookies[1].name), "my_cookie2");
@@ -428,7 +441,7 @@
 
   // Create cookies with 2 separate hosts.
   CefCookie cookie1;
-  const char* kUrl1 = "http://www.foo.com";
+  const char* kUrl1 = "https://www.foo.com";
   CefString(&cookie1.name).FromASCII("my_cookie1");
   CefString(&cookie1.value).FromASCII("My Value 1");
 
@@ -437,7 +450,7 @@
   cookies.clear();
 
   CefCookie cookie2;
-  const char* kUrl2 = "http://www.bar.com";
+  const char* kUrl2 = "https://www.bar.com";
   CefString(&cookie2.name).FromASCII("my_cookie2");
   CefString(&cookie2.value).FromASCII("My Value 2");
 
@@ -449,8 +462,9 @@
   VisitAllCookies(manager, cookies, false, event);
 
   EXPECT_EQ(2U, cookies.size());
-  if (cookies.size() != 2U)
+  if (cookies.size() != 2U) {
     return;
+  }
 
   EXPECT_EQ(CefString(&cookies[0].name), "my_cookie1");
   EXPECT_EQ(CefString(&cookies[0].value), "My Value 1");
@@ -464,8 +478,9 @@
   VisitUrlCookies(manager, kUrl1, false, cookies, false, event);
 
   EXPECT_EQ(1U, cookies.size());
-  if (cookies.size() != 1U)
+  if (cookies.size() != 1U) {
     return;
+  }
 
   EXPECT_EQ(CefString(&cookies[0].name), "my_cookie1");
   EXPECT_EQ(CefString(&cookies[0].value), "My Value 1");
@@ -475,8 +490,9 @@
   VisitUrlCookies(manager, kUrl2, false, cookies, false, event);
 
   EXPECT_EQ(1U, cookies.size());
-  if (cookies.size() != 1U)
+  if (cookies.size() != 1U) {
     return;
+  }
 
   EXPECT_EQ(CefString(&cookies[0].name), "my_cookie2");
   EXPECT_EQ(CefString(&cookies[0].value), "My Value 2");
@@ -558,8 +574,8 @@
 
 namespace {
 
-const char* kCookieJSUrl1 = "http://tests/cookie1.html";
-const char* kCookieJSUrl2 = "http://tests/cookie2.html";
+const char* kCookieJSUrl1 = "https://tests/cookie1.html";
+const char* kCookieJSUrl2 = "https://tests/cookie2.html";
 
 class CookieTestJSHandler : public TestHandler {
  public:
@@ -600,8 +616,8 @@
   // Go to the next URL.
   void LoadNextURL(CefRefPtr<CefFrame> frame) {
     if (!CefCurrentlyOn(TID_UI)) {
-      CefPostTask(TID_UI,
-                  base::Bind(&CookieTestJSHandler::LoadNextURL, this, frame));
+      CefPostTask(TID_UI, base::BindOnce(&CookieTestJSHandler::LoadNextURL,
+                                         this, frame));
       return;
     }
 
@@ -610,7 +626,8 @@
 
   void CompleteTest() {
     if (!CefCurrentlyOn(TID_UI)) {
-      CefPostTask(TID_UI, base::Bind(&CookieTestJSHandler::CompleteTest, this));
+      CefPostTask(TID_UI,
+                  base::BindOnce(&CookieTestJSHandler::CompleteTest, this));
       return;
     }
 
@@ -623,12 +640,13 @@
     std::string url = frame->GetURL();
     if (url == kCookieJSUrl1) {
       got_load_end1_.yes();
-      VerifyCookie(manager_, url, "name1", "value1", true, &got_cookie1_,
-                   base::Bind(&CookieTestJSHandler::LoadNextURL, this, frame));
+      VerifyCookie(
+          manager_, url, "name1", "value1", true, &got_cookie1_,
+          base::BindOnce(&CookieTestJSHandler::LoadNextURL, this, frame));
     } else {
       got_load_end2_.yes();
       VerifyCookie(manager_, url, "name2", "value2", true, &got_cookie2_,
-                   base::Bind(&CookieTestJSHandler::CompleteTest, this));
+                   base::BindOnce(&CookieTestJSHandler::CompleteTest, this));
     }
   }
 
@@ -639,25 +657,26 @@
                     const std::string& value,
                     bool deleteCookie,
                     TrackCallback* callback,
-                    const base::Closure& continue_callback) {
+                    base::OnceClosure continue_callback) {
     // Get the cookie.
     EXPECT_TRUE(cookies_.empty());
-    VisitUrlCookies(manager, url, false, cookies_, deleteCookie,
-                    base::Bind(&CookieTestJSHandler::VerifyCookieComplete, this,
-                               name, value, callback, continue_callback));
+    VisitUrlCookies(
+        manager, url, false, cookies_, deleteCookie,
+        base::BindOnce(&CookieTestJSHandler::VerifyCookieComplete, this, name,
+                       value, callback, std::move(continue_callback)));
   }
 
   void VerifyCookieComplete(const std::string& name,
                             const std::string& value,
                             TrackCallback* callback,
-                            const base::Closure& continue_callback) {
+                            base::OnceClosure continue_callback) {
     if (cookies_.size() == 1U && CefString(&cookies_[0].name) == name &&
         CefString(&cookies_[0].value) == value) {
       callback->yes();
     }
 
     cookies_.clear();
-    continue_callback.Run();
+    std::move(continue_callback).Run();
   }
 
   CefRefPtr<CefCookieManager> manager_;
@@ -693,16 +712,13 @@
 
 class CompletionCallback : public CefCompletionCallback {
  public:
-  explicit CompletionCallback(const base::Closure& callback)
-      : callback_(callback) {}
+  explicit CompletionCallback(base::OnceClosure callback)
+      : callback_(std::move(callback)) {}
 
-  void OnComplete() override {
-    callback_.Run();
-    callback_.Reset();
-  }
+  void OnComplete() override { std::move(callback_).Run(); }
 
  private:
-  base::Closure callback_;
+  base::OnceClosure callback_;
   IMPLEMENT_REFCOUNTING(CompletionCallback);
 };
 
@@ -735,8 +751,9 @@
         CefRequest::HeaderMap headerMap;
         request->GetHeaderMap(headerMap);
         CefRequest::HeaderMap::iterator it = headerMap.find("Cookie");
-        if (it != headerMap.end() && it->second == "name2=value2")
+        if (it != headerMap.end() && it->second == "name2=value2") {
           handler_->got_process_request_cookie_.yes();
+        }
       }
 
       // Continue immediately.
@@ -745,7 +762,7 @@
     }
 
     void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                            int64& response_length,
+                            int64_t& response_length,
                             CefString& redirectUrl) override {
       response_length = content_.size();
 
@@ -811,8 +828,9 @@
         CefRequest::HeaderMap headerMap;
         request->GetHeaderMap(headerMap);
         CefRequest::HeaderMap::iterator it = headerMap.find("Cookie");
-        if (it != headerMap.end() && it->second == "name2=value2")
+        if (it != headerMap.end() && it->second == "name2=value2") {
           handler_->got_create_cookie_.yes();
+        }
       }
 
       return new SchemeHandler(handler_);
@@ -842,41 +860,36 @@
     } else {
       // Create the request context that will use an in-memory cache.
       CefRequestContextSettings settings;
+
+      if (scheme_ == kCustomCookieScheme || block_cookies_) {
+        if (!block_cookies_) {
+          CefString(&settings.cookieable_schemes_list) = kCustomCookieScheme;
+        } else {
+          settings.cookieable_schemes_exclude_defaults = true;
+        }
+      }
+
       request_context_ = CefRequestContext::CreateContext(settings, nullptr);
     }
 
     // Register the scheme handler.
     request_context_->RegisterSchemeHandlerFactory(
         scheme_, "cookie-tests", new SchemeHandlerFactory(this));
-    manager_ = request_context_->GetCookieManager(nullptr);
-    if (!use_global_ && (scheme_ == kCustomCookieScheme || block_cookies_)) {
-      std::vector<CefString> schemes;
-      if (!block_cookies_)
-        schemes.push_back(kCustomCookieScheme);
 
-      // Need to wait for completion before creating the browser.
-      manager_->SetSupportedSchemes(
-          schemes, !block_cookies_ /* include_defaults */,
-          new CompletionCallback(base::Bind(
-              &CookieTestSchemeHandler::CreateBrowserContinue, this)));
-    } else {
-      CreateBrowserContinue();
-    }
+    manager_ = request_context_->GetCookieManager(nullptr);
+
+    // Create the browser.
+    CreateBrowser(url1_, request_context_);
 
     // Time out the test after a reasonable period of time.
     SetTestTimeout();
   }
 
-  void CreateBrowserContinue() {
-    // Create the browser.
-    CreateBrowser(url1_, request_context_);
-  }
-
   // Go to the next URL.
   void LoadNextURL(CefRefPtr<CefFrame> frame, const std::string& url) {
     if (!CefCurrentlyOn(TID_UI)) {
-      CefPostTask(TID_UI, base::Bind(&CookieTestSchemeHandler::LoadNextURL,
-                                     this, frame, url));
+      CefPostTask(TID_UI, base::BindOnce(&CookieTestSchemeHandler::LoadNextURL,
+                                         this, frame, url));
       return;
     }
 
@@ -885,8 +898,8 @@
 
   void CompleteTest(CefRefPtr<CefBrowser> browser) {
     if (!CefCurrentlyOn(TID_UI)) {
-      CefPostTask(TID_UI, base::Bind(&CookieTestSchemeHandler::CompleteTest,
-                                     this, browser));
+      CefPostTask(TID_UI, base::BindOnce(&CookieTestSchemeHandler::CompleteTest,
+                                         this, browser));
       return;
     }
 
@@ -904,18 +917,18 @@
     if (url == url1_) {
       got_load_end1_.yes();
       VerifyCookie(manager_, url, "name1", "value1", true, &got_cookie1_,
-                   base::Bind(&CookieTestSchemeHandler::LoadNextURL, this,
-                              frame, url2_));
+                   base::BindOnce(&CookieTestSchemeHandler::LoadNextURL, this,
+                                  frame, url2_));
     } else if (url == url2_) {
       got_load_end2_.yes();
       VerifyCookie(manager_, url, "name2", "value2", false, &got_cookie2_,
-                   base::Bind(&CookieTestSchemeHandler::LoadNextURL, this,
-                              frame, url3_));
+                   base::BindOnce(&CookieTestSchemeHandler::LoadNextURL, this,
+                                  frame, url3_));
     } else {
       got_load_end3_.yes();
-      VerifyCookie(
-          manager_, url, "name2", "value2", true, &got_cookie3_,
-          base::Bind(&CookieTestSchemeHandler::CompleteTest, this, browser));
+      VerifyCookie(manager_, url, "name2", "value2", true, &got_cookie3_,
+                   base::BindOnce(&CookieTestSchemeHandler::CompleteTest, this,
+                                  browser));
     }
   }
 
@@ -956,25 +969,26 @@
                     const std::string& value,
                     bool deleteCookie,
                     TrackCallback* callback,
-                    const base::Closure& continue_callback) {
+                    base::OnceClosure continue_callback) {
     // Get the cookie.
     EXPECT_TRUE(cookies_.empty());
-    VisitUrlCookies(manager, url, false, cookies_, deleteCookie,
-                    base::Bind(&CookieTestSchemeHandler::VerifyCookieComplete,
-                               this, name, value, callback, continue_callback));
+    VisitUrlCookies(
+        manager, url, false, cookies_, deleteCookie,
+        base::BindOnce(&CookieTestSchemeHandler::VerifyCookieComplete, this,
+                       name, value, callback, std::move(continue_callback)));
   }
 
   void VerifyCookieComplete(const std::string& name,
                             const std::string& value,
                             TrackCallback* callback,
-                            const base::Closure& continue_callback) {
+                            base::OnceClosure continue_callback) {
     if (cookies_.size() == 1U && CefString(&cookies_[0].name) == name &&
         CefString(&cookies_[0].value) == value) {
       callback->yes();
     }
 
     cookies_.clear();
-    continue_callback.Run();
+    std::move(continue_callback).Run();
   }
 
   const std::string scheme_;
@@ -1009,7 +1023,7 @@
 // Verify use of the global cookie manager with HTTP.
 TEST(CookieTest, GetCookieManagerHttpGlobal) {
   CefRefPtr<CookieTestSchemeHandler> handler =
-      new CookieTestSchemeHandler("http", true);
+      new CookieTestSchemeHandler("https", true);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 }
@@ -1017,7 +1031,7 @@
 // Verify use of an in-memory cookie manager with HTTP.
 TEST(CookieTest, GetCookieManagerHttpInMemory) {
   CefRefPtr<CookieTestSchemeHandler> handler =
-      new CookieTestSchemeHandler("http", false);
+      new CookieTestSchemeHandler("https", false);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 }
@@ -1025,7 +1039,7 @@
 // Verify use of an in-memory cookie manager with HTTP to block all cookies.
 TEST(CookieTest, GetCookieManagerHttpInMemoryBlocked) {
   CefRefPtr<CookieTestSchemeHandler> handler =
-      new CookieTestSchemeHandler("http", false, true);
+      new CookieTestSchemeHandler("https", false, true);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 }
@@ -1048,32 +1062,34 @@
 
 namespace {
 
-const char kCookieAccessScheme[] = "http";
+constexpr bool kUseHttpsServerScheme = false;
+
 const char kCookieAccessDomain[] = "test-cookies.com";
-const char kCookieAccessServerIP[] = "127.0.0.1";
-const uint16 kCookieAccessServerPort = 8099;
+
+std::string GetCookieAccessScheme() {
+  return test_server::GetScheme(kUseHttpsServerScheme);
+}
 
 std::string GetCookieAccessOrigin(const std::string& scheme,
                                   bool server_backend) {
-  std::stringstream ss;
   if (server_backend) {
-    ss << scheme << "://" << kCookieAccessServerIP << ":"
-       << kCookieAccessServerPort;
-  } else {
-    ss << scheme << "://" << kCookieAccessDomain;
+    EXPECT_STREQ(GetCookieAccessScheme().c_str(), scheme.c_str());
+    return test_server::GetOrigin(kUseHttpsServerScheme);
   }
-  ss << "/";
+
+  std::stringstream ss;
+  ss << scheme << "://" << kCookieAccessDomain;
   return ss.str();
 }
 
 std::string GetCookieAccessUrl1(const std::string& scheme,
                                 bool server_backend) {
-  return GetCookieAccessOrigin(scheme, server_backend) + "cookie1.html";
+  return GetCookieAccessOrigin(scheme, server_backend) + "/cookie1.html";
 }
 
 std::string GetCookieAccessUrl2(const std::string& scheme,
                                 bool server_backend) {
-  return GetCookieAccessOrigin(scheme, server_backend) + "cookie2.html";
+  return GetCookieAccessOrigin(scheme, server_backend) + "/cookie2.html";
 }
 
 void TestCookieString(const std::string& cookie_str,
@@ -1106,10 +1122,12 @@
 };
 
 std::string GetHeaderValue(const CefServer::HeaderMap& header_map,
-                           const std::string& header_name) {
-  CefServer::HeaderMap::const_iterator it = header_map.find(header_name);
-  if (it != header_map.end())
-    return it->second;
+                           const std::string& header_name_lower) {
+  for (const auto& [name, value] : header_map) {
+    if (client::AsciiStrToLower(name) == header_name_lower) {
+      return value;
+    }
+  }
   return std::string();
 }
 
@@ -1126,7 +1144,7 @@
 
     CefRequest::HeaderMap headerMap;
     request->GetHeaderMap(headerMap);
-    const std::string& cookie_str = GetHeaderValue(headerMap, "Cookie");
+    const std::string& cookie_str = GetHeaderValue(headerMap, "cookie");
     TestCookieString(cookie_str, data_->cookie_js_ct_, data_->cookie_net_ct_);
 
     // Continue immediately.
@@ -1135,7 +1153,7 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
     EXPECT_IO_THREAD();
 
@@ -1220,7 +1238,9 @@
     }
 
     // Unknown test.
-    ADD_FAILURE() << "Unexpected url: " << url;
+    if (!IgnoreURL(url)) {
+      ADD_FAILURE() << "Unexpected url: " << url;
+    }
     return nullptr;
   }
 
@@ -1228,15 +1248,13 @@
     data_map_.insert(std::make_pair(url, data));
   }
 
-  void Shutdown(const base::Closure& complete_callback) {
+  void Shutdown(base::OnceClosure complete_callback) {
     if (!CefCurrentlyOn(TID_IO)) {
-      CefPostTask(TID_IO,
-                  base::Bind(&CookieAccessSchemeHandlerFactory::Shutdown, this,
-                             complete_callback));
+      CefPostTask(TID_IO, base::BindOnce(std::move(complete_callback)));
       return;
     }
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
  private:
@@ -1248,13 +1266,11 @@
 };
 
 // HTTP server handler.
-class CookieAccessServerHandler : public CefServerHandler,
+class CookieAccessServerHandler : public test_server::ObserverHelper,
                                   public CookieAccessResponseHandler {
  public:
   CookieAccessServerHandler()
       : initialized_(false),
-        expected_connection_ct_(-1),
-        actual_connection_ct_(0),
         expected_http_request_ct_(-1),
         actual_http_request_ct_(0) {}
 
@@ -1262,177 +1278,70 @@
 
   // Must be called before CreateServer().
   void AddResponse(const std::string& url, CookieAccessData* data) override {
-    EXPECT_FALSE(initialized_);
     data_map_.insert(std::make_pair(url, data));
   }
 
   // Must be called before CreateServer().
-  void SetExpectedRequestCount(int count) {
-    EXPECT_FALSE(initialized_);
-    expected_connection_ct_ = expected_http_request_ct_ = count;
-  }
+  void SetExpectedRequestCount(int count) { expected_http_request_ct_ = count; }
 
   // |complete_callback| will be executed on the UI thread after the server is
   // started.
-  void CreateServer(const base::Closure& complete_callback) {
+  void CreateServer(base::OnceClosure complete_callback) {
     EXPECT_UI_THREAD();
 
-    if (expected_connection_ct_ < 0) {
-      // Default to the assumption of one request per registered URL.
-      SetExpectedRequestCount(static_cast<int>(data_map_.size()));
-    }
-
     EXPECT_FALSE(initialized_);
     initialized_ = true;
 
     EXPECT_TRUE(complete_callback_.is_null());
-    complete_callback_ = complete_callback;
+    complete_callback_ = std::move(complete_callback);
 
-    CefServer::CreateServer(kCookieAccessServerIP, kCookieAccessServerPort, 10,
-                            this);
+    Initialize(kUseHttpsServerScheme);
   }
 
   // Results in a call to VerifyResults() and eventual execution of the
   // |complete_callback| on the UI thread via CookieAccessServerHandler
   // destruction.
-  void ShutdownServer(const base::Closure& complete_callback) {
+  void ShutdownServer(base::OnceClosure complete_callback) {
     EXPECT_UI_THREAD();
 
     EXPECT_TRUE(complete_callback_.is_null());
-    complete_callback_ = complete_callback;
+    complete_callback_ = std::move(complete_callback);
 
-    EXPECT_TRUE(server_);
-    if (server_)
-      server_->Shutdown();
+    Shutdown();
   }
 
-  void OnServerCreated(CefRefPtr<CefServer> server) override {
-    EXPECT_TRUE(server);
-    EXPECT_TRUE(server->IsRunning());
-    EXPECT_FALSE(server->HasConnection());
+  void OnInitialized(const std::string& server_origin) override {
+    EXPECT_UI_THREAD();
+    EXPECT_STREQ(server_origin.c_str(),
+                 GetCookieAccessOrigin(GetCookieAccessScheme(), true).c_str());
 
     EXPECT_FALSE(got_server_created_);
     got_server_created_.yes();
 
-    EXPECT_FALSE(server_);
-    server_ = server;
-
-    EXPECT_FALSE(server_runner_);
-    server_runner_ = server_->GetTaskRunner();
-    EXPECT_TRUE(server_runner_);
-    EXPECT_TRUE(server_runner_->BelongsToCurrentThread());
-
-    CefPostTask(
-        TID_UI,
-        base::Bind(&CookieAccessServerHandler::RunCompleteCallback, this));
+    RunCompleteCallback();
   }
 
-  void OnServerDestroyed(CefRefPtr<CefServer> server) override {
-    EXPECT_TRUE(VerifyServer(server));
-    EXPECT_FALSE(server->IsRunning());
-    EXPECT_FALSE(server->HasConnection());
+  void OnShutdown() override {
+    EXPECT_UI_THREAD();
 
     EXPECT_FALSE(got_server_destroyed_);
     got_server_destroyed_.yes();
 
-    server_ = nullptr;
-
     VerifyResults();
+
+    delete this;
   }
 
-  void OnClientConnected(CefRefPtr<CefServer> server,
-                         int connection_id) override {
-    EXPECT_TRUE(VerifyServer(server));
-    EXPECT_TRUE(server->HasConnection());
-    EXPECT_TRUE(server->IsValidConnection(connection_id));
-
-    EXPECT_TRUE(connection_id_set_.find(connection_id) ==
-                connection_id_set_.end());
-    connection_id_set_.insert(connection_id);
-
-    actual_connection_ct_++;
-  }
-
-  void OnClientDisconnected(CefRefPtr<CefServer> server,
-                            int connection_id) override {
-    EXPECT_TRUE(VerifyServer(server));
-    EXPECT_FALSE(server->IsValidConnection(connection_id));
-
-    ConnectionIdSet::iterator it = connection_id_set_.find(connection_id);
-    EXPECT_TRUE(it != connection_id_set_.end());
-    connection_id_set_.erase(it);
-  }
-
-  void OnHttpRequest(CefRefPtr<CefServer> server,
-                     int connection_id,
-                     const CefString& client_address,
-                     CefRefPtr<CefRequest> request) override {
-    EXPECT_TRUE(VerifyServer(server));
-    EXPECT_TRUE(VerifyConnection(connection_id));
-    EXPECT_FALSE(client_address.empty());
+  bool OnTestServerRequest(CefRefPtr<CefRequest> request,
+                           const ResponseCallback& response_callback) override {
+    EXPECT_UI_THREAD();
 
     // Log the requests for better error reporting.
     request_log_ += request->GetMethod().ToString() + " " +
                     request->GetURL().ToString() + "\n";
 
-    HandleRequest(server, connection_id, request);
-
     actual_http_request_ct_++;
-  }
 
-  void OnWebSocketRequest(CefRefPtr<CefServer> server,
-                          int connection_id,
-                          const CefString& client_address,
-                          CefRefPtr<CefRequest> request,
-                          CefRefPtr<CefCallback> callback) override {
-    NOTREACHED();
-  }
-
-  void OnWebSocketConnected(CefRefPtr<CefServer> server,
-                            int connection_id) override {
-    NOTREACHED();
-  }
-
-  void OnWebSocketMessage(CefRefPtr<CefServer> server,
-                          int connection_id,
-                          const void* data,
-                          size_t data_size) override {
-    NOTREACHED();
-  }
-
- private:
-  bool RunningOnServerThread() {
-    return server_runner_ && server_runner_->BelongsToCurrentThread();
-  }
-
-  bool VerifyServer(CefRefPtr<CefServer> server) {
-    V_DECLARE();
-    V_EXPECT_TRUE(RunningOnServerThread());
-    V_EXPECT_TRUE(server);
-    V_EXPECT_TRUE(server_);
-    V_EXPECT_TRUE(server->GetAddress().ToString() ==
-                  server_->GetAddress().ToString());
-    V_RETURN();
-  }
-
-  bool VerifyConnection(int connection_id) {
-    return connection_id_set_.find(connection_id) != connection_id_set_.end();
-  }
-
-  void VerifyResults() {
-    EXPECT_TRUE(RunningOnServerThread());
-
-    EXPECT_TRUE(got_server_created_);
-    EXPECT_TRUE(got_server_destroyed_);
-    EXPECT_TRUE(connection_id_set_.empty());
-    EXPECT_EQ(expected_connection_ct_, actual_connection_ct_) << request_log_;
-    EXPECT_EQ(expected_http_request_ct_, actual_http_request_ct_)
-        << request_log_;
-  }
-
-  void HandleRequest(CefRefPtr<CefServer> server,
-                     int connection_id,
-                     CefRefPtr<CefRequest> request) {
     const std::string& url = request->GetURL();
     ResponseDataMap::const_iterator it = data_map_.find(url);
     if (it != data_map_.end()) {
@@ -1444,57 +1353,38 @@
       TestCookieString(cookie_str, it->second->cookie_js_ct_,
                        it->second->cookie_net_ct_);
 
-      SendResponse(server, connection_id, it->second->response,
-                   it->second->response_data);
-    } else {
+      response_callback.Run(it->second->response, it->second->response_data);
+      return true;
+    } else if (!IgnoreURL(url)) {
       // Unknown test.
       ADD_FAILURE() << "Unexpected url: " << url;
-      server->SendHttp500Response(connection_id, "Unknown test");
     }
+    return false;
   }
 
-  void SendResponse(CefRefPtr<CefServer> server,
-                    int connection_id,
-                    CefRefPtr<CefResponse> response,
-                    const std::string& response_data) {
-    int response_code = response->GetStatus();
-    const CefString& content_type = response->GetMimeType();
-    int64 content_length = static_cast<int64>(response_data.size());
-
-    CefResponse::HeaderMap extra_headers;
-    response->GetHeaderMap(extra_headers);
-
-    server->SendHttpResponse(connection_id, response_code, content_type,
-                             content_length, extra_headers);
-
-    if (content_length != 0) {
-      server->SendRawData(connection_id, response_data.data(),
-                          response_data.size());
-      server->CloseConnection(connection_id);
-    }
-
-    // The connection should be closed.
-    EXPECT_FALSE(server->IsValidConnection(connection_id));
+ private:
+  void VerifyResults() {
+    EXPECT_TRUE(got_server_created_);
+    EXPECT_TRUE(got_server_destroyed_);
+    EXPECT_EQ(expected_http_request_ct_, actual_http_request_ct_)
+        << request_log_;
   }
 
   void RunCompleteCallback() {
     EXPECT_UI_THREAD();
 
     EXPECT_FALSE(complete_callback_.is_null());
-    complete_callback_.Run();
-    complete_callback_.Reset();
+    std::move(complete_callback_).Run();
   }
 
   // Map of URL to Data.
   typedef std::map<std::string, CookieAccessData*> ResponseDataMap;
   ResponseDataMap data_map_;
 
-  CefRefPtr<CefServer> server_;
-  CefRefPtr<CefTaskRunner> server_runner_;
   bool initialized_;
 
   // Only accessed on the UI thread.
-  base::Closure complete_callback_;
+  base::OnceClosure complete_callback_;
 
   // After initialization the below members are only accessed on the server
   // thread.
@@ -1502,17 +1392,11 @@
   TrackCallback got_server_created_;
   TrackCallback got_server_destroyed_;
 
-  typedef std::set<int> ConnectionIdSet;
-  ConnectionIdSet connection_id_set_;
-
-  int expected_connection_ct_;
-  int actual_connection_ct_;
   int expected_http_request_ct_;
   int actual_http_request_ct_;
 
   std::string request_log_;
 
-  IMPLEMENT_REFCOUNTING(CookieAccessServerHandler);
   DISALLOW_COPY_AND_ASSIGN(CookieAccessServerHandler);
 };
 
@@ -1526,9 +1410,9 @@
     BLOCK_READ_WRITE = BLOCK_READ | BLOCK_WRITE,
     ALLOW_NO_FILTER = 1 << 2,
 
-    // Block all cookies using SetSupportedSchemes. Can only be used with a
-    // non-global request context because it's too late (during test execution)
-    // to call this method on the global context.
+    // Block all cookies using CefRequestContextSettings. Can only be used with
+    // a non-global request context because it's too late (during test
+    // execution) to call this method on the global context.
     BLOCK_ALL_COOKIES = 1 << 3,
 
     // Return nullptr from GetResourceRequestHandler. Can only be used in
@@ -1554,14 +1438,16 @@
                           bool use_global)
       : test_mode_(test_mode),
         test_backend_(test_backend),
-        scheme_(custom_scheme ? kCustomCookieScheme : kCookieAccessScheme),
+        scheme_(custom_scheme ? kCustomCookieScheme : GetCookieAccessScheme()),
         use_global_(use_global) {
-    if (test_mode_ == BLOCK_ALL_COOKIES)
+    if (test_mode_ == BLOCK_ALL_COOKIES) {
       CHECK(!use_global_);
-    else if (test_mode_ == ALLOW_NO_HANDLER)
+    } else if (test_mode_ == ALLOW_NO_HANDLER) {
       CHECK_NE(RESOURCE_HANDLER, test_backend_);
-    if (test_backend_ == SERVER)
+    }
+    if (test_backend_ == SERVER) {
       CHECK(!custom_scheme);
+    }
   }
 
   void RunTest() override {
@@ -1570,33 +1456,29 @@
     } else {
       // Create the request context that will use an in-memory cache.
       CefRequestContextSettings settings;
+
+      const bool block_cookies = (test_mode_ == BLOCK_ALL_COOKIES);
+      if (scheme_ == kCustomCookieScheme || block_cookies) {
+        if (!block_cookies) {
+          CefString(&settings.cookieable_schemes_list) = kCustomCookieScheme;
+        } else {
+          settings.cookieable_schemes_exclude_defaults = true;
+        }
+      }
+
       context_ = CefRequestContext::CreateContext(settings, nullptr);
     }
 
-    cookie_manager_ = context_->GetCookieManager(nullptr);
-
     SetTestTimeout();
 
-    const bool block_cookies = (test_mode_ == BLOCK_ALL_COOKIES);
-    if (!use_global_ && (scheme_ == kCustomCookieScheme || block_cookies)) {
-      std::vector<CefString> schemes;
-      if (!block_cookies)
-        schemes.push_back(kCustomCookieScheme);
-
-      // Need to wait for completion before creating the browser.
-      cookie_manager_->SetSupportedSchemes(
-          schemes, !block_cookies /* include_defaults */,
-          new CompletionCallback(base::Bind(
-              &CookieAccessTestHandler::RunTestSetupContinue, this)));
-    } else {
-      RunTestSetupContinue();
-    }
+    cookie_manager_ = context_->GetCookieManager(nullptr);
+    RunTestSetupContinue();
   }
 
   void DestroyTest() override {
     if (!CefCurrentlyOn(TID_UI)) {
       CefPostTask(TID_UI,
-                  base::Bind(&CookieAccessTestHandler::DestroyTest, this));
+                  base::BindOnce(&CookieAccessTestHandler::DestroyTest, this));
       return;
     }
 
@@ -1611,20 +1493,24 @@
       EXPECT_EQ(0, can_save_cookie1_ct_);
       EXPECT_EQ(0, can_send_cookie2_ct_);
     } else {
-      // Get 1 call to CanSaveCookie for the 1st network request due to the
-      // network cookie.
-      EXPECT_EQ(1, can_save_cookie1_ct_);
       if (test_mode_ == BLOCK_ALL_COOKIES) {
         // Never send any cookies.
         EXPECT_EQ(0, can_send_cookie2_ct_);
+        EXPECT_EQ(0, can_save_cookie1_ct_);
       } else if (test_mode_ & BLOCK_WRITE) {
         // Get 1 calls to CanSendCookie for the 2nd network request due to the
         // JS cookie (network cookie is blocked).
         EXPECT_EQ(1, can_send_cookie2_ct_);
+        // Get 1 call to CanSaveCookie for the 1st network request due to the
+        // network cookie.
+        EXPECT_EQ(1, can_save_cookie1_ct_);
       } else {
         // Get 2 calls to CanSendCookie for the 2nd network request due to the
         // network cookie + JS cookie.
         EXPECT_EQ(2, can_send_cookie2_ct_);
+        // Get 1 call to CanSaveCookie for the 1st network request due to the
+        // network cookie.
+        EXPECT_EQ(1, can_save_cookie1_ct_);
       }
     }
 
@@ -1679,8 +1565,9 @@
       CefRefPtr<CefRequest> request) override {
     EXPECT_IO_THREAD();
 
-    if (test_mode_ == ALLOW_NO_FILTER)
+    if (test_mode_ == ALLOW_NO_FILTER) {
       return nullptr;
+    }
 
     return this;
   }
@@ -1693,8 +1580,9 @@
       bool is_download,
       const CefString& request_initiator,
       bool& disable_default_handling) override {
-    if (test_mode_ == ALLOW_NO_HANDLER)
+    if (test_mode_ == ALLOW_NO_HANDLER) {
       return nullptr;
+    }
 
     return this;
   }
@@ -1703,7 +1591,7 @@
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request) override {
-    if (test_backend_ == RESOURCE_HANDLER) {
+    if (test_backend_ == RESOURCE_HANDLER && scheme_factory_) {
       return scheme_factory_->Create(browser, frame, scheme_, request);
     }
 
@@ -1719,7 +1607,7 @@
     const std::string& url = request->GetURL();
     if (url == GetCookieAccessUrl2(scheme_, test_backend_ == SERVER)) {
       can_send_cookie2_ct_++;
-    } else {
+    } else if (!IgnoreURL(url)) {
       ADD_FAILURE() << "Unexpected url: " << url;
     }
 
@@ -1740,7 +1628,7 @@
     const std::string& url = request->GetURL();
     if (url == GetCookieAccessUrl1(scheme_, test_backend_ == SERVER)) {
       can_save_cookie1_ct_++;
-    } else {
+    } else if (!IgnoreURL(url)) {
       ADD_FAILURE() << "Unexpected url: " << url;
     }
 
@@ -1749,7 +1637,7 @@
 
   bool OnQuery(CefRefPtr<CefBrowser> browser,
                CefRefPtr<CefFrame> frame,
-               int64 query_id,
+               int64_t query_id,
                const CefString& request,
                bool persistent,
                CefRefPtr<Callback> callback) override {
@@ -1815,47 +1703,55 @@
   }
 
   void RunTestSetupContinue() {
-    CefPostTask(TID_UI,
-                base::Bind(&CookieAccessTestHandler::StartBackend, this,
-                           base::Bind(&CookieAccessTestHandler::RunTestContinue,
-                                      this)));
+    CefPostTask(
+        TID_UI,
+        base::BindOnce(
+            &CookieAccessTestHandler::StartBackend, this,
+            base::BindOnce(&CookieAccessTestHandler::RunTestContinue, this)));
   }
 
-  void StartBackend(const base::Closure& complete_callback) {
+  void StartBackend(base::OnceClosure complete_callback) {
     if (test_backend_ == SERVER) {
-      StartServer(complete_callback);
+      StartServer(std::move(complete_callback));
     } else {
-      StartSchemeHandler(complete_callback);
+      StartSchemeHandler(std::move(complete_callback));
     }
   }
 
-  void StartServer(const base::Closure& complete_callback) {
+  void StartServer(base::OnceClosure complete_callback) {
     EXPECT_FALSE(server_handler_);
 
     server_handler_ = new CookieAccessServerHandler();
-    AddResponses(server_handler_.get());
-    server_handler_->CreateServer(complete_callback);
+    server_handler_->CreateServer(std::move(complete_callback));
   }
 
-  void StartSchemeHandler(const base::Closure& complete_callback) {
+  void StartSchemeHandler(base::OnceClosure complete_callback) {
     // Add the factory registration.
     scheme_factory_ = new CookieAccessSchemeHandlerFactory();
-    AddResponses(scheme_factory_.get());
     if (test_backend_ == SCHEME_HANDLER) {
       context_->RegisterSchemeHandlerFactory(scheme_, kCookieAccessDomain,
                                              scheme_factory_.get());
     }
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
   void RunTestContinue() {
     if (!CefCurrentlyOn(TID_UI)) {
-      CefPostTask(TID_UI,
-                  base::Bind(&CookieAccessTestHandler::RunTestContinue, this));
+      CefPostTask(TID_UI, base::BindOnce(
+                              &CookieAccessTestHandler::RunTestContinue, this));
       return;
     }
 
+    if (test_backend_ == SERVER) {
+      AddResponses(server_handler_);
+
+      // 1 request for each URL.
+      server_handler_->SetExpectedRequestCount(2);
+    } else {
+      AddResponses(scheme_factory_.get());
+    }
+
     CreateBrowser(GetCookieAccessUrl1(scheme_, test_backend_ == SERVER),
                   context_);
   }
@@ -1870,9 +1766,9 @@
         // Destroy the test.
         CefPostTask(
             TID_UI,
-            base::Bind(
-                &CookieAccessTestHandler::ShutdownBackend, handler_,
-                base::Bind(&CookieAccessTestHandler::DestroyTest, handler_)));
+            base::BindOnce(&CookieAccessTestHandler::ShutdownBackend, handler_,
+                           base::BindOnce(&CookieAccessTestHandler::DestroyTest,
+                                          handler_)));
       }
 
       bool Visit(const CefCookie& cookie,
@@ -1881,10 +1777,11 @@
                  bool& deleteCookie) override {
         const std::string& name = CefString(&cookie.name);
         const std::string& value = CefString(&cookie.value);
-        if (name == "name_js" && value == "value_js")
+        if (name == "name_js" && value == "value_js") {
           handler_->cookie_js3_ct_++;
-        else if (name == "name_net" && value == "value_net")
+        } else if (name == "name_net" && value == "value_net") {
           handler_->cookie_net3_ct_++;
+        }
 
         // Clean up the cookies.
         deleteCookie = true;
@@ -1900,29 +1797,30 @@
     cookie_manager_->VisitAllCookies(new TestVisitor(this));
   }
 
-  void ShutdownBackend(const base::Closure& complete_callback) {
+  void ShutdownBackend(base::OnceClosure complete_callback) {
     if (test_backend_ == SERVER) {
-      ShutdownServer(complete_callback);
+      ShutdownServer(std::move(complete_callback));
     } else {
-      ShutdownSchemeHandler(complete_callback);
+      ShutdownSchemeHandler(std::move(complete_callback));
     }
   }
 
-  void ShutdownServer(const base::Closure& complete_callback) {
+  void ShutdownServer(base::OnceClosure complete_callback) {
     EXPECT_TRUE(server_handler_);
 
-    server_handler_->ShutdownServer(complete_callback);
+    // |server_handler_| will delete itself after shutdown.
+    server_handler_->ShutdownServer(std::move(complete_callback));
     server_handler_ = nullptr;
   }
 
-  void ShutdownSchemeHandler(const base::Closure& complete_callback) {
+  void ShutdownSchemeHandler(base::OnceClosure complete_callback) {
     EXPECT_TRUE(scheme_factory_);
 
     if (test_backend_ == SCHEME_HANDLER) {
       context_->RegisterSchemeHandlerFactory(scheme_, kCookieAccessDomain,
                                              nullptr);
     }
-    scheme_factory_->Shutdown(complete_callback);
+    scheme_factory_->Shutdown(std::move(complete_callback));
     scheme_factory_ = nullptr;
   }
 
@@ -1933,7 +1831,7 @@
   CefRefPtr<CefRequestContext> context_;
   CefRefPtr<CefCookieManager> cookie_manager_;
 
-  CefRefPtr<CookieAccessServerHandler> server_handler_;
+  CookieAccessServerHandler* server_handler_ = nullptr;
   CefRefPtr<CookieAccessSchemeHandlerFactory> scheme_factory_;
 
   CookieAccessData data1_;
@@ -2028,7 +1926,7 @@
                                  public CefCookieAccessFilter {
  public:
   explicit CookieRestartTestHandler(bool use_global)
-      : scheme_(kCookieAccessScheme), use_global_(use_global) {}
+      : scheme_(GetCookieAccessScheme()), use_global_(use_global) {}
 
   void RunTest() override {
     if (use_global_) {
@@ -2048,7 +1946,7 @@
   void DestroyTest() override {
     if (!CefCurrentlyOn(TID_UI)) {
       CefPostTask(TID_UI,
-                  base::Bind(&CookieRestartTestHandler::DestroyTest, this));
+                  base::BindOnce(&CookieRestartTestHandler::DestroyTest, this));
       return;
     }
 
@@ -2158,7 +2056,7 @@
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) override {
+      CefRefPtr<CefCallback> callback) override {
     EXPECT_IO_THREAD();
     before_resource_load_ct_++;
 
@@ -2216,7 +2114,7 @@
 
   bool OnQuery(CefRefPtr<CefBrowser> browser,
                CefRefPtr<CefFrame> frame,
-               int64 query_id,
+               int64_t query_id,
                const CefString& request,
                bool persistent,
                CefRefPtr<Callback> callback) override {
@@ -2283,28 +2181,31 @@
   void RunTestSetupContinue() {
     CefPostTask(
         TID_UI,
-        base::Bind(
+        base::BindOnce(
             &CookieRestartTestHandler::StartServer, this,
-            base::Bind(&CookieRestartTestHandler::RunTestContinue, this)));
+            base::BindOnce(&CookieRestartTestHandler::RunTestContinue, this)));
   }
 
-  void StartServer(const base::Closure& complete_callback) {
+  void StartServer(base::OnceClosure complete_callback) {
     EXPECT_FALSE(server_handler_);
 
     server_handler_ = new CookieAccessServerHandler();
-    AddResponses(server_handler_.get());
-    // 2 requests for each URL.
-    server_handler_->SetExpectedRequestCount(4);
-    server_handler_->CreateServer(complete_callback);
+    server_handler_->CreateServer(std::move(complete_callback));
   }
 
   void RunTestContinue() {
     if (!CefCurrentlyOn(TID_UI)) {
-      CefPostTask(TID_UI,
-                  base::Bind(&CookieRestartTestHandler::RunTestContinue, this));
+      CefPostTask(
+          TID_UI,
+          base::BindOnce(&CookieRestartTestHandler::RunTestContinue, this));
       return;
     }
 
+    AddResponses(server_handler_);
+
+    // 2 requests for each URL.
+    server_handler_->SetExpectedRequestCount(4);
+
     CreateBrowser(GetCookieAccessUrl1(scheme_, true), context_);
   }
 
@@ -2316,11 +2217,11 @@
           : handler_(handler) {}
       ~TestVisitor() override {
         // Destroy the test.
-        CefPostTask(
-            TID_UI,
-            base::Bind(
-                &CookieRestartTestHandler::ShutdownServer, handler_,
-                base::Bind(&CookieRestartTestHandler::DestroyTest, handler_)));
+        CefPostTask(TID_UI,
+                    base::BindOnce(
+                        &CookieRestartTestHandler::ShutdownServer, handler_,
+                        base::BindOnce(&CookieRestartTestHandler::DestroyTest,
+                                       handler_)));
       }
 
       bool Visit(const CefCookie& cookie,
@@ -2329,10 +2230,11 @@
                  bool& deleteCookie) override {
         const std::string& name = CefString(&cookie.name);
         const std::string& value = CefString(&cookie.value);
-        if (name == "name_js" && value == "value_js")
+        if (name == "name_js" && value == "value_js") {
           handler_->cookie_manager_js_ct_++;
-        else if (name == "name_net" && value == "value_net")
+        } else if (name == "name_net" && value == "value_net") {
           handler_->cookie_manager_net_ct_++;
+        }
 
         // Clean up the cookies.
         deleteCookie = true;
@@ -2348,10 +2250,11 @@
     cookie_manager_->VisitAllCookies(new TestVisitor(this));
   }
 
-  void ShutdownServer(const base::Closure& complete_callback) {
+  void ShutdownServer(base::OnceClosure complete_callback) {
     EXPECT_TRUE(server_handler_);
 
-    server_handler_->ShutdownServer(complete_callback);
+    // |server_handler_| will delete itself after shutdown.
+    server_handler_->ShutdownServer(std::move(complete_callback));
     server_handler_ = nullptr;
   }
 
@@ -2360,7 +2263,7 @@
   CefRefPtr<CefRequestContext> context_;
   CefRefPtr<CefCookieManager> cookie_manager_;
 
-  CefRefPtr<CookieAccessServerHandler> server_handler_;
+  CookieAccessServerHandler* server_handler_ = nullptr;
 
   CookieAccessData data1_;
   CookieAccessData data2_;
@@ -2403,11 +2306,17 @@
 
 // Entry point for registering custom schemes.
 // Called from client_app_delegates.cc.
-void RegisterCookieCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar,
-                                 std::vector<CefString>& cookiable_schemes) {
+void RegisterCookieCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar) {
   // Used by GetCookieManagerCustom* tests.
   registrar->AddCustomScheme(
       kCustomCookieScheme,
       CEF_SCHEME_OPTION_STANDARD | CEF_SCHEME_OPTION_CORS_ENABLED);
-  cookiable_schemes.push_back(kCustomCookieScheme);
+}
+
+// Entry point for registering cookieable schemes.
+// Called from client_app_delegates.cc.
+void RegisterCookieCookieableSchemes(
+    std::vector<std::string>& cookieable_schemes) {
+  // Used by GetCookieManagerCustom* tests.
+  cookieable_schemes.push_back(kCustomCookieScheme);
 }
diff --git a/src/tests/ceftests/cors_unittest.cc b/src/tests/ceftests/cors_unittest.cc
new file mode 100644
index 0000000..515f2f7
--- /dev/null
+++ b/src/tests/ceftests/cors_unittest.cc
@@ -0,0 +1,1855 @@
+// Copyright (c) 2020 The Chromium Embedded Framework 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 <algorithm>
+#include <set>
+#include <vector>
+
+#include "include/base/cef_callback.h"
+#include "include/cef_callback.h"
+#include "include/cef_origin_whitelist.h"
+#include "include/cef_scheme.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "tests/ceftests/routing_test_handler.h"
+#include "tests/ceftests/test_request.h"
+#include "tests/ceftests/test_server_observer.h"
+#include "tests/ceftests/test_util.h"
+#include "tests/shared/browser/client_app_browser.h"
+
+namespace {
+
+// Browser-side app delegate.
+class CorsBrowserTest : public client::ClientAppBrowser::Delegate {
+ public:
+  CorsBrowserTest() {}
+
+  void OnContextInitialized(CefRefPtr<client::ClientAppBrowser> app) override {
+    if (IsChromeRuntimeEnabled()) {
+      // Disable InsecureFormNavigationThrottle which blocks 307 redirect of
+      // POST requests from HTTPS to custom non-standard scheme causing the
+      // CorsTest.RedirectPost307HttpSchemeToCustomNonStandardScheme test to
+      // fail.
+      CefRefPtr<CefValue> value = CefValue::Create();
+      value->SetBool(false);
+      CefString error;
+      bool result = CefRequestContext::GetGlobalContext()->SetPreference(
+          "profile.mixed_forms_warnings", value, error);
+      CHECK(result) << error.ToString();
+    }
+  }
+
+ private:
+  IMPLEMENT_REFCOUNTING(CorsBrowserTest);
+};
+
+constexpr bool kUseHttpsServerScheme = false;
+
+const char kMimeTypeHtml[] = "text/html";
+const char kMimeTypeText[] = "text/plain";
+
+const char kDefaultHtml[] = "<html><body>TEST</body></html>";
+const char kDefaultText[] = "TEST";
+const char kDefaultCookie[] = "testCookie=testVal";
+
+const char kSuccessMsg[] = "CorsTestHandler.Success";
+const char kFailureMsg[] = "CorsTestHandler.Failure";
+
+// Source that will handle the request.
+enum class HandlerType {
+  SERVER,
+  HTTP_SCHEME,
+  CUSTOM_STANDARD_SCHEME,
+  CUSTOM_NONSTANDARD_SCHEME,
+  CUSTOM_UNREGISTERED_SCHEME,
+};
+
+std::string GetOrigin(HandlerType handler) {
+  switch (handler) {
+    case HandlerType::SERVER:
+      return test_server::GetOrigin(kUseHttpsServerScheme);
+    case HandlerType::HTTP_SCHEME:
+      // Use HTTPS because requests from HTTP to the loopback address will be
+      // blocked by https://chromestatus.com/feature/5436853517811712.
+      return "https://corstest.com";
+    case HandlerType::CUSTOM_STANDARD_SCHEME:
+      // Standard scheme that's registered as CORS and fetch enabled.
+      // Registered in scheme_handler_unittest.cc.
+      return "customstdfetch://corstest";
+    case HandlerType::CUSTOM_NONSTANDARD_SCHEME:
+      // Non-standard schemes are not CORS or fetch enabled.
+      // Registered in scheme_handler_unittest.cc.
+      return "customnonstd:corstest";
+    case HandlerType::CUSTOM_UNREGISTERED_SCHEME:
+      // A scheme that isn't registered anywhere is treated as a non-standard
+      // scheme.
+      return "customstdunregistered://corstest";
+  }
+  NOTREACHED();
+  return std::string();
+}
+
+std::string GetScheme(HandlerType handler) {
+  switch (handler) {
+    case HandlerType::SERVER:
+      return test_server::GetScheme(kUseHttpsServerScheme);
+    case HandlerType::HTTP_SCHEME:
+      return "https";
+    case HandlerType::CUSTOM_STANDARD_SCHEME:
+      return "customstdfetch";
+    case HandlerType::CUSTOM_NONSTANDARD_SCHEME:
+      return "customnonstd";
+    case HandlerType::CUSTOM_UNREGISTERED_SCHEME:
+      return "customstdunregistered";
+  }
+  NOTREACHED();
+  return std::string();
+}
+
+bool IsNonStandardType(HandlerType handler) {
+  return handler == HandlerType::CUSTOM_NONSTANDARD_SCHEME ||
+         handler == HandlerType::CUSTOM_UNREGISTERED_SCHEME;
+}
+
+bool IsStandardType(HandlerType handler) {
+  return !IsNonStandardType(handler);
+}
+
+std::string GetPathURL(HandlerType handler, const std::string& path) {
+  return GetOrigin(handler) + path;
+}
+
+struct Resource {
+  // Uniquely identifies the resource.
+  HandlerType handler = HandlerType::SERVER;
+  std::string path;
+  // If non-empty the method value must match.
+  std::string method;
+
+  // Response information that will be returned.
+  CefRefPtr<CefResponse> response;
+  std::string response_data;
+
+  // Expected error code in OnLoadError.
+  cef_errorcode_t expected_error_code = ERR_NONE;
+
+  // Expected number of responses.
+  int expected_response_ct = 1;
+
+  // Expected number of OnQuery calls.
+  int expected_success_query_ct = 0;
+  int expected_failure_query_ct = 0;
+
+  // Actual number of responses.
+  int response_ct = 0;
+
+  // Actual number of OnQuery calls.
+  int success_query_ct = 0;
+  int failure_query_ct = 0;
+
+  Resource() {}
+  Resource(HandlerType request_handler,
+           const std::string& request_path,
+           const std::string& mime_type = kMimeTypeHtml,
+           const std::string& data = kDefaultHtml,
+           int status = 200) {
+    Init(request_handler, request_path, mime_type, data, status);
+  }
+
+  // Perform basic initialization.
+  void Init(HandlerType request_handler,
+            const std::string& request_path,
+            const std::string& mime_type = kMimeTypeHtml,
+            const std::string& data = kDefaultHtml,
+            int status = 200) {
+    handler = request_handler;
+    path = request_path;
+    response_data = data;
+    response = CefResponse::Create();
+    response->SetMimeType(mime_type);
+    response->SetStatus(status);
+  }
+
+  // Validate expected initial state.
+  void Validate() const {
+    DCHECK(!path.empty());
+    DCHECK(response);
+    DCHECK(!response->GetMimeType().empty());
+    DCHECK_EQ(0, response_ct);
+    DCHECK_GE(expected_response_ct, 0);
+  }
+
+  std::string GetPathURL() const { return ::GetPathURL(handler, path); }
+
+  // Returns true if all expectations have been met.
+  bool IsDone() const {
+    return response_ct == expected_response_ct &&
+           success_query_ct == expected_success_query_ct &&
+           failure_query_ct == expected_failure_query_ct;
+  }
+
+  void AssertDone() const {
+    EXPECT_EQ(expected_response_ct, response_ct) << GetPathURL();
+    EXPECT_EQ(expected_success_query_ct, success_query_ct) << GetPathURL();
+    EXPECT_EQ(expected_failure_query_ct, failure_query_ct) << GetPathURL();
+  }
+
+  // Optionally override to verify request contents.
+  virtual bool VerifyRequest(CefRefPtr<CefRequest> request) const {
+    return true;
+  }
+};
+
+struct TestSetup {
+  // Available resources.
+  typedef std::vector<Resource*> ResourceList;
+  ResourceList resources;
+
+  struct ConsoleMessage {
+    std::string message;
+
+    // Number of times the message was received. All registered messages are
+    // expected at least one time.
+    size_t count = 0;
+  };
+
+  // Used for testing received console messages.
+  std::vector<ConsoleMessage> console_messages;
+
+  // If true cookies will be cleared after every test run.
+  bool clear_cookies = false;
+
+  void AddResource(Resource* resource) {
+    DCHECK(resource);
+    resource->Validate();
+    resources.push_back(resource);
+  }
+
+  void AddConsoleMessage(const std::string& message) {
+    DCHECK(!message.empty());
+    console_messages.push_back({message, 0U});
+  }
+
+  Resource* GetResource(const std::string& url,
+                        const std::string& method = std::string()) const {
+    if (resources.empty()) {
+      return nullptr;
+    }
+
+    std::set<std::string> matching_methods;
+    if (method.empty()) {
+      // Match standard HTTP methods.
+      matching_methods.insert("GET");
+      matching_methods.insert("POST");
+    } else {
+      matching_methods.insert(method);
+    }
+
+    const std::string& path_url = test_request::GetPathURL(url);
+    ResourceList::const_iterator it = resources.begin();
+    for (; it != resources.end(); ++it) {
+      Resource* resource = *it;
+      if (resource->GetPathURL() == path_url &&
+          (resource->method.empty() ||
+           matching_methods.find(resource->method) != matching_methods.end())) {
+        return resource;
+      }
+    }
+    return nullptr;
+  }
+
+  Resource* GetResource(CefRefPtr<CefRequest> request) const {
+    return GetResource(request->GetURL(), request->GetMethod());
+  }
+
+  // Optional initialization after the test server is started.
+  virtual void Initialize() {}
+
+  // Validate expected initial state.
+  void Validate() const { DCHECK(!resources.empty()); }
+
+  std::string GetMainURL() const { return resources.front()->GetPathURL(); }
+
+  // Returns true if the server will be used.
+  virtual bool NeedsServer() const {
+    ResourceList::const_iterator it = resources.begin();
+    for (; it != resources.end(); ++it) {
+      Resource* resource = *it;
+      if (resource->handler == HandlerType::SERVER) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  // Returns true if all expectations have been met.
+  bool IsDone() const {
+    ResourceList::const_iterator it = resources.begin();
+    for (; it != resources.end(); ++it) {
+      Resource* resource = *it;
+      if (!resource->IsDone()) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  void AssertDone() const {
+    ResourceList::const_iterator it = resources.begin();
+    for (; it != resources.end(); ++it) {
+      (*it)->AssertDone();
+    }
+  }
+
+  // Optionally override to verify cleared cookie contents.
+  virtual bool VerifyClearedCookies(
+      const test_request::CookieVector& cookies) const {
+    return true;
+  }
+};
+
+class TestServerObserver : public test_server::ObserverHelper {
+ public:
+  TestServerObserver(TestSetup* setup,
+                     base::OnceClosure ready_callback,
+                     base::OnceClosure done_callback)
+      : setup_(setup),
+        ready_callback_(std::move(ready_callback)),
+        done_callback_(std::move(done_callback)) {
+    DCHECK(setup);
+    Initialize(kUseHttpsServerScheme);
+  }
+
+  ~TestServerObserver() override { std::move(done_callback_).Run(); }
+
+  void OnInitialized(const std::string& server_origin) override {
+    CEF_REQUIRE_UI_THREAD();
+    std::move(ready_callback_).Run();
+  }
+
+  bool OnTestServerRequest(CefRefPtr<CefRequest> request,
+                           const ResponseCallback& response_callback) override {
+    CEF_REQUIRE_UI_THREAD();
+    Resource* resource = setup_->GetResource(request);
+    if (!resource) {
+      // Not a request we handle.
+      return false;
+    }
+
+    resource->response_ct++;
+    EXPECT_TRUE(resource->VerifyRequest(request))
+        << request->GetURL().ToString();
+    response_callback.Run(resource->response, resource->response_data);
+
+    // Stop propagating the callback.
+    return true;
+  }
+
+  void OnShutdown() override {
+    CEF_REQUIRE_UI_THREAD();
+    delete this;
+  }
+
+ private:
+  TestSetup* const setup_;
+  base::OnceClosure ready_callback_;
+  base::OnceClosure done_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestServerObserver);
+};
+
+class CorsTestHandler : public RoutingTestHandler {
+ public:
+  explicit CorsTestHandler(TestSetup* setup) : setup_(setup) {}
+
+  void RunTest() override {
+    StartServer(base::BindOnce(&CorsTestHandler::TriggerCreateBrowser, this));
+
+    // Time out the test after a reasonable period of time.
+    SetTestTimeout();
+  }
+
+  // Necessary to make the method public in order to destroy the test from
+  // ClientSchemeHandlerType::ProcessRequest().
+  void DestroyTest() override {
+    EXPECT_TRUE(shutting_down_);
+
+    if (setup_->NeedsServer()) {
+      EXPECT_TRUE(got_stopped_server_);
+    } else {
+      EXPECT_FALSE(got_stopped_server_);
+    }
+
+    if (setup_->clear_cookies) {
+      EXPECT_TRUE(got_cleared_cookies_);
+    } else {
+      EXPECT_FALSE(got_cleared_cookies_);
+    }
+
+    setup_->AssertDone();
+    for (const auto& cm : setup_->console_messages) {
+      EXPECT_GT(cm.count, 0U)
+          << "Did not receive expected console message: " << cm.message;
+    }
+
+    RoutingTestHandler::DestroyTest();
+  }
+
+  CefRefPtr<CefResourceHandler> GetResourceHandler(
+      CefRefPtr<CefBrowser> browser,
+      CefRefPtr<CefFrame> frame,
+      CefRefPtr<CefRequest> request) override {
+    CEF_REQUIRE_IO_THREAD();
+    const std::string& url = request->GetURL();
+    const std::string& method = request->GetMethod();
+    if (method == "OPTIONS") {
+      // We should never see the CORS preflight request.
+      ADD_FAILURE() << "Unexpected CORS preflight for " << url;
+    }
+
+    Resource* resource = setup_->GetResource(request);
+    if (resource && resource->handler != HandlerType::SERVER) {
+      resource->response_ct++;
+      EXPECT_TRUE(resource->VerifyRequest(request)) << url;
+      return test_request::CreateResourceHandler(resource->response,
+                                                 resource->response_data);
+    }
+    return RoutingTestHandler::GetResourceHandler(browser, frame, request);
+  }
+
+  void OnLoadEnd(CefRefPtr<CefBrowser> browser,
+                 CefRefPtr<CefFrame> frame,
+                 int httpStatusCode) override {
+    const std::string& url = frame->GetURL();
+    Resource* resource = GetResource(url);
+    if (!resource) {
+      return;
+    }
+
+    const int expected_status = resource->response->GetStatus();
+    if (url == main_url_ || expected_status != 200) {
+      // Test that the status code is correct.
+      EXPECT_EQ(expected_status, httpStatusCode) << url;
+    }
+
+    TriggerDestroyTestIfDone();
+  }
+
+  void OnLoadError(CefRefPtr<CefBrowser> browser,
+                   CefRefPtr<CefFrame> frame,
+                   ErrorCode errorCode,
+                   const CefString& errorText,
+                   const CefString& failedUrl) override {
+    Resource* resource = GetResource(failedUrl);
+    if (!resource) {
+      return;
+    }
+
+    const cef_errorcode_t expected_error = resource->response->GetError();
+
+    // Tests sometimes also fail with ERR_ABORTED.
+    if (!(expected_error == ERR_NONE && errorCode == ERR_ABORTED)) {
+      EXPECT_EQ(expected_error, errorCode) << failedUrl.ToString();
+    }
+
+    TriggerDestroyTestIfDone();
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               const CefString& request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    Resource* resource = GetResource(frame->GetURL());
+    if (!resource) {
+      return false;
+    }
+
+    if (request.ToString() == kSuccessMsg ||
+        request.ToString() == kFailureMsg) {
+      callback->Success("");
+      if (request.ToString() == kSuccessMsg) {
+        resource->success_query_ct++;
+      } else {
+        resource->failure_query_ct++;
+      }
+      TriggerDestroyTestIfDone();
+      return true;
+    }
+    return false;
+  }
+
+  bool OnConsoleMessage(CefRefPtr<CefBrowser> browser,
+                        cef_log_severity_t level,
+                        const CefString& message,
+                        const CefString& source,
+                        int line) override {
+    bool expected = false;
+    if (!setup_->console_messages.empty()) {
+      const std::string& actual = message.ToString();
+      for (auto& cm : setup_->console_messages) {
+        if (actual.find(cm.message) == 0U) {
+          expected = true;
+          cm.count++;
+          break;
+        }
+      }
+    }
+
+    EXPECT_TRUE(expected) << "Unexpected console message: "
+                          << message.ToString();
+    return false;
+  }
+
+ protected:
+  void TriggerCreateBrowser() {
+    setup_->Initialize();
+    setup_->Validate();
+
+    main_url_ = setup_->GetMainURL();
+    CreateBrowser(main_url_);
+  }
+
+  void TriggerDestroyTestIfDone() {
+    CefPostTask(TID_UI,
+                base::BindOnce(&CorsTestHandler::DestroyTestIfDone, this));
+  }
+
+  void DestroyTestIfDone() {
+    CEF_REQUIRE_UI_THREAD();
+    if (shutting_down_) {
+      return;
+    }
+
+    if (setup_->IsDone()) {
+      shutting_down_ = true;
+      StopServer();
+    }
+  }
+
+  void StartServer(base::OnceClosure next_step) {
+    if (!CefCurrentlyOn(TID_UI)) {
+      CefPostTask(TID_UI, base::BindOnce(&CorsTestHandler::StartServer, this,
+                                         std::move(next_step)));
+      return;
+    }
+
+    if (!setup_->NeedsServer()) {
+      std::move(next_step).Run();
+      return;
+    }
+
+    // Will delete itself after the server stops.
+    server_ = new TestServerObserver(
+        setup_, std::move(next_step),
+        base::BindOnce(&CorsTestHandler::StoppedServer, this));
+  }
+
+  void StopServer() {
+    CEF_REQUIRE_UI_THREAD();
+    if (!server_) {
+      DCHECK(!setup_->NeedsServer());
+      AfterStoppedServer();
+      return;
+    }
+
+    // Results in a call to StoppedServer().
+    server_->Shutdown();
+  }
+
+  void StoppedServer() {
+    CEF_REQUIRE_UI_THREAD();
+    got_stopped_server_.yes();
+    server_ = nullptr;
+    AfterStoppedServer();
+  }
+
+  void AfterStoppedServer() {
+    CEF_REQUIRE_UI_THREAD();
+    if (setup_->clear_cookies) {
+      ClearCookies();
+    } else {
+      DestroyTest();
+    }
+  }
+
+  void ClearCookies() {
+    CEF_REQUIRE_UI_THREAD();
+    DCHECK(setup_->clear_cookies);
+    test_request::GetAllCookies(
+        CefCookieManager::GetGlobalManager(nullptr), /*delete_cookies=*/true,
+        base::BindOnce(&CorsTestHandler::ClearedCookies, this));
+  }
+
+  void ClearedCookies(const test_request::CookieVector& cookies) {
+    CEF_REQUIRE_UI_THREAD();
+    got_cleared_cookies_.yes();
+    EXPECT_TRUE(setup_->VerifyClearedCookies(cookies));
+    DestroyTest();
+  }
+
+  Resource* GetResource(const std::string& url) const {
+    Resource* resource = setup_->GetResource(url);
+    EXPECT_TRUE(resource) << url;
+    return resource;
+  }
+
+  TestSetup* setup_;
+  std::string main_url_;
+  TestServerObserver* server_ = nullptr;
+  bool shutting_down_ = false;
+
+  TrackCallback got_stopped_server_;
+  TrackCallback got_cleared_cookies_;
+
+  IMPLEMENT_REFCOUNTING(CorsTestHandler);
+  DISALLOW_COPY_AND_ASSIGN(CorsTestHandler);
+};
+
+// JS that results in a call to CorsTestHandler::OnQuery.
+std::string GetMsgJS(const std::string& msg) {
+  return "window.testQuery({request:'" + msg + "'});";
+}
+
+std::string GetSuccessMsgJS() {
+  return GetMsgJS(kSuccessMsg);
+}
+std::string GetFailureMsgJS() {
+  return GetMsgJS(kFailureMsg);
+}
+
+std::string GetDefaultSuccessMsgHtml() {
+  return "<html><body>TEST<script>" + GetSuccessMsgJS() +
+         "</script></body></html>";
+}
+
+}  // namespace
+
+// Verify the test harness for server requests.
+TEST(CorsTest, BasicServer) {
+  TestSetup setup;
+  Resource resource(HandlerType::SERVER, "/CorsTest.BasicServer");
+  setup.AddResource(&resource);
+
+  CefRefPtr<CorsTestHandler> handler = new CorsTestHandler(&setup);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Like above, but also send a query JS message.
+TEST(CorsTest, BasicServerWithQuery) {
+  TestSetup setup;
+  Resource resource(HandlerType::SERVER, "/CorsTest.BasicServerWithQuery",
+                    kMimeTypeHtml, GetDefaultSuccessMsgHtml());
+  resource.expected_success_query_ct = 1;
+  setup.AddResource(&resource);
+
+  CefRefPtr<CorsTestHandler> handler = new CorsTestHandler(&setup);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Verify the test harness for http scheme requests.
+TEST(CorsTest, BasicHttpScheme) {
+  TestSetup setup;
+  Resource resource(HandlerType::HTTP_SCHEME, "/CorsTest.BasicHttpScheme");
+  setup.AddResource(&resource);
+
+  CefRefPtr<CorsTestHandler> handler = new CorsTestHandler(&setup);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Like above, but also send a query JS message.
+TEST(CorsTest, BasicHttpSchemeWithQuery) {
+  TestSetup setup;
+  Resource resource(HandlerType::HTTP_SCHEME,
+                    "/CorsTest.BasicHttpSchemeWithQuery", kMimeTypeHtml,
+                    GetDefaultSuccessMsgHtml());
+  resource.expected_success_query_ct = 1;
+  setup.AddResource(&resource);
+
+  CefRefPtr<CorsTestHandler> handler = new CorsTestHandler(&setup);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Verify the test harness for custom standard scheme requests.
+TEST(CorsTest, BasicCustomStandardScheme) {
+  TestSetup setup;
+  Resource resource(HandlerType::CUSTOM_STANDARD_SCHEME,
+                    "/CorsTest.BasicCustomStandardScheme");
+  setup.AddResource(&resource);
+
+  CefRefPtr<CorsTestHandler> handler = new CorsTestHandler(&setup);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Like above, but also send a query JS message.
+TEST(CorsTest, BasicCustomStandardSchemeWithQuery) {
+  TestSetup setup;
+  Resource resource(HandlerType::CUSTOM_STANDARD_SCHEME,
+                    "/CorsTest.BasicCustomStandardSchemeWithQuery",
+                    kMimeTypeHtml, GetDefaultSuccessMsgHtml());
+  resource.expected_success_query_ct = 1;
+  setup.AddResource(&resource);
+
+  CefRefPtr<CorsTestHandler> handler = new CorsTestHandler(&setup);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+namespace {
+
+struct CookieTestSetup : TestSetup {
+  CookieTestSetup() {}
+
+  bool expect_cookie = false;
+
+  bool VerifyClearedCookies(
+      const test_request::CookieVector& cookies) const override {
+    if (!expect_cookie) {
+      EXPECT_TRUE(cookies.empty());
+      return cookies.empty();
+    }
+
+    EXPECT_EQ(1U, cookies.size());
+    const std::string& cookie = CefString(&cookies[0].name).ToString() + "=" +
+                                CefString(&cookies[0].value).ToString();
+    EXPECT_STREQ(kDefaultCookie, cookie.c_str());
+    return cookie == kDefaultCookie;
+  }
+};
+
+struct CookieResource : Resource {
+  CookieResource() {}
+
+  bool expect_cookie = false;
+
+  void InitSetCookie() {
+    response->SetHeaderByName("Set-Cookie", kDefaultCookie,
+                              /*override=*/true);
+  }
+
+  bool VerifyRequest(CefRefPtr<CefRequest> request) const override {
+    const std::string& cookie = request->GetHeaderByName("Cookie");
+    const std::string& expected_cookie =
+        expect_cookie ? kDefaultCookie : std::string();
+    EXPECT_STREQ(expected_cookie.c_str(), cookie.c_str()) << GetPathURL();
+    return expected_cookie == cookie;
+  }
+};
+
+void SetupCookieExpectations(CookieTestSetup* setup,
+                             CookieResource* main_resource,
+                             CookieResource* sub_resource) {
+  // All schemes except custom non-standard support cookies.
+  const bool supports_cookies = IsStandardType(main_resource->handler);
+
+  // The main resource may set the cookie (if cookies are supported), but should
+  // not receive one.
+  main_resource->InitSetCookie();
+  main_resource->expect_cookie = false;
+
+  // A cookie will be set only for schemes that support cookies.
+  setup->expect_cookie = supports_cookies;
+  // Always clear cookies so we can verify that one wasn't set unexpectedly.
+  setup->clear_cookies = true;
+
+  // Expect the sub-resource to receive the cookie for same-origin requests
+  // only.
+  sub_resource->expect_cookie =
+      supports_cookies && main_resource->handler == sub_resource->handler;
+}
+
+std::string GetIframeMainHtml(const std::string& iframe_url,
+                              const std::string& sandbox_attribs) {
+  return "<html><body>TEST<iframe src=\"" + iframe_url + "\" sandbox=\"" +
+         sandbox_attribs + "\"></iframe></body></html>";
+}
+
+std::string GetIframeSubHtml() {
+  // Try to script the parent frame, then send the SuccessMsg.
+  return "<html><body>TEST<script>try { parent.document.body; } catch "
+         "(exception) { console.log(exception.toString()); }" +
+         GetSuccessMsgJS() + "</script></body></html>";
+}
+
+bool HasSandboxAttrib(const std::string& sandbox_attribs,
+                      const std::string& attrib) {
+  return sandbox_attribs.find(attrib) != std::string::npos;
+}
+
+void SetupIframeRequest(CookieTestSetup* setup,
+                        const std::string& test_name,
+                        HandlerType main_handler,
+                        CookieResource* main_resource,
+                        HandlerType iframe_handler,
+                        CookieResource* iframe_resource,
+                        const std::string& sandbox_attribs) {
+  const std::string& base_path = "/" + test_name;
+
+  // Expect a single iframe request.
+  iframe_resource->Init(iframe_handler, base_path + ".iframe.html",
+                        kMimeTypeHtml, GetIframeSubHtml());
+
+  // Expect a single main frame request.
+  const std::string& iframe_url = iframe_resource->GetPathURL();
+  main_resource->Init(main_handler, base_path, kMimeTypeHtml,
+                      GetIframeMainHtml(iframe_url, sandbox_attribs));
+
+  SetupCookieExpectations(setup, main_resource, iframe_resource);
+
+  if (HasSandboxAttrib(sandbox_attribs, "allow-scripts")) {
+    // Expect the iframe to load successfully and send the SuccessMsg.
+    iframe_resource->expected_success_query_ct = 1;
+
+    const bool has_same_origin =
+        HasSandboxAttrib(sandbox_attribs, "allow-same-origin");
+    if (!has_same_origin ||
+        (has_same_origin &&
+         (IsNonStandardType(main_handler) || main_handler != iframe_handler))) {
+      // Expect parent frame scripting to fail if:
+      // - "allow-same-origin" is not specified;
+      // - the main frame is a non-standard scheme (e.g. CORS disabled);
+      // - the main frame and iframe origins don't match.
+      // The reported origin will be "null" if "allow-same-origin" is not
+      // specified, or if the iframe is hosted on a non-standard scheme.
+      const std::string& origin =
+          !has_same_origin || IsNonStandardType(iframe_handler)
+              ? "null"
+              : GetOrigin(iframe_handler);
+      setup->AddConsoleMessage(
+          "SecurityError: Failed to read a named property 'document' from "
+          "'Window': Blocked a frame with origin \"" +
+          origin + "\" from accessing a cross-origin frame.");
+    }
+
+    if (has_same_origin && main_handler == iframe_handler &&
+        IsStandardType(main_handler)) {
+      setup->AddConsoleMessage(
+          "An iframe which has both allow-scripts and allow-same-origin for "
+          "its sandbox attribute can escape its sandboxing.");
+    }
+  } else {
+    // Expect JavaScript execution to fail.
+    setup->AddConsoleMessage("Blocked script execution in '" + iframe_url +
+                             "' because the document's frame is sandboxed and "
+                             "the 'allow-scripts' permission is not set.");
+  }
+
+  setup->AddResource(main_resource);
+  setup->AddResource(iframe_resource);
+}
+
+struct IframeTestSetup : CookieTestSetup {
+  IframeTestSetup(const std::string& test_name,
+                  HandlerType main_handler,
+                  HandlerType iframe_handler,
+                  const std::string& sandbox_attribs)
+      : test_name_(test_name),
+        main_handler_(main_handler),
+        iframe_handler_(iframe_handler),
+        sandbox_attribs_(sandbox_attribs) {}
+
+  bool NeedsServer() const override {
+    return main_handler_ == HandlerType::SERVER ||
+           iframe_handler_ == HandlerType::SERVER;
+  }
+
+  void Initialize() override {
+    SetupIframeRequest(this, test_name_, main_handler_, &resource_main_,
+                       iframe_handler_, &resource_iframe_, sandbox_attribs_);
+  }
+
+ private:
+  const std::string test_name_;
+  const HandlerType main_handler_;
+  const HandlerType iframe_handler_;
+  const std::string sandbox_attribs_;
+
+  CookieResource resource_main_;
+  CookieResource resource_iframe_;
+};
+
+}  // namespace
+
+// Test iframe sandbox attributes with different origin combinations.
+#define CORS_TEST_IFRAME(test_name, handler_main, handler_iframe,        \
+                         sandbox_attribs)                                \
+  TEST(CorsTest, Iframe##test_name) {                                    \
+    IframeTestSetup setup("CorsTest.Iframe" #test_name,                  \
+                          HandlerType::handler_main,                     \
+                          HandlerType::handler_iframe, sandbox_attribs); \
+    CefRefPtr<CorsTestHandler> handler = new CorsTestHandler(&setup);    \
+    handler->ExecuteTest();                                              \
+    ReleaseAndWaitForDestructor(handler);                                \
+  }
+
+// Test all origin combinations (same and cross-origin).
+#define CORS_TEST_IFRAME_ALL(name, sandbox_attribs)                            \
+  CORS_TEST_IFRAME(name##ServerToServer, SERVER, SERVER, sandbox_attribs)      \
+  CORS_TEST_IFRAME(name##ServerToHttpScheme, SERVER, HTTP_SCHEME,              \
+                   sandbox_attribs)                                            \
+  CORS_TEST_IFRAME(name##ServerToCustomStandardScheme, SERVER,                 \
+                   CUSTOM_STANDARD_SCHEME, sandbox_attribs)                    \
+  CORS_TEST_IFRAME(name##ServerToCustomNonStandardScheme, SERVER,              \
+                   CUSTOM_NONSTANDARD_SCHEME, sandbox_attribs)                 \
+  CORS_TEST_IFRAME(name##ServerToCustomUnregisteredScheme, SERVER,             \
+                   CUSTOM_UNREGISTERED_SCHEME, sandbox_attribs)                \
+  CORS_TEST_IFRAME(name##HttpSchemeToServer, HTTP_SCHEME, SERVER,              \
+                   sandbox_attribs)                                            \
+  CORS_TEST_IFRAME(name##HttpSchemeToHttpScheme, HTTP_SCHEME, HTTP_SCHEME,     \
+                   sandbox_attribs)                                            \
+  CORS_TEST_IFRAME(name##HttpSchemeToCustomStandardScheme, HTTP_SCHEME,        \
+                   CUSTOM_STANDARD_SCHEME, sandbox_attribs)                    \
+  CORS_TEST_IFRAME(name##HttpSchemeToCustomNonStandardScheme, HTTP_SCHEME,     \
+                   CUSTOM_NONSTANDARD_SCHEME, sandbox_attribs)                 \
+  CORS_TEST_IFRAME(name##HttpSchemeToCustomUnregisteredScheme, HTTP_SCHEME,    \
+                   CUSTOM_UNREGISTERED_SCHEME, sandbox_attribs)                \
+  CORS_TEST_IFRAME(name##CustomStandardSchemeToServer, CUSTOM_STANDARD_SCHEME, \
+                   SERVER, sandbox_attribs)                                    \
+  CORS_TEST_IFRAME(name##CustomStandardSchemeToHttpScheme,                     \
+                   CUSTOM_STANDARD_SCHEME, HTTP_SCHEME, sandbox_attribs)       \
+  CORS_TEST_IFRAME(name##CustomStandardSchemeToCustomStandardScheme,           \
+                   CUSTOM_STANDARD_SCHEME, CUSTOM_STANDARD_SCHEME,             \
+                   sandbox_attribs)                                            \
+  CORS_TEST_IFRAME(name##CustomStandardSchemeToCustomNonStandardScheme,        \
+                   CUSTOM_STANDARD_SCHEME, CUSTOM_NONSTANDARD_SCHEME,          \
+                   sandbox_attribs)                                            \
+  CORS_TEST_IFRAME(name##CustomStandardSchemeToCustomUnregisteredScheme,       \
+                   CUSTOM_STANDARD_SCHEME, CUSTOM_UNREGISTERED_SCHEME,         \
+                   sandbox_attribs)                                            \
+  CORS_TEST_IFRAME(name##CustomNonStandardSchemeToServer,                      \
+                   CUSTOM_NONSTANDARD_SCHEME, SERVER, sandbox_attribs)         \
+  CORS_TEST_IFRAME(name##CustomNonStandardSchemeToHttpScheme,                  \
+                   CUSTOM_NONSTANDARD_SCHEME, HTTP_SCHEME, sandbox_attribs)    \
+  CORS_TEST_IFRAME(name##CustomNonStandardSchemeToCustomStandardScheme,        \
+                   CUSTOM_NONSTANDARD_SCHEME, CUSTOM_STANDARD_SCHEME,          \
+                   sandbox_attribs)                                            \
+  CORS_TEST_IFRAME(name##CustomNonStandardSchemeToCustomNonStandardScheme,     \
+                   CUSTOM_NONSTANDARD_SCHEME, CUSTOM_NONSTANDARD_SCHEME,       \
+                   sandbox_attribs)                                            \
+  CORS_TEST_IFRAME(name##CustomNonStandardSchemeToCustomUnregisteredScheme,    \
+                   CUSTOM_NONSTANDARD_SCHEME, CUSTOM_UNREGISTERED_SCHEME,      \
+                   sandbox_attribs)                                            \
+  CORS_TEST_IFRAME(name##CustomUnregisteredSchemeToServer,                     \
+                   CUSTOM_UNREGISTERED_SCHEME, SERVER, sandbox_attribs)        \
+  CORS_TEST_IFRAME(name##CustomUnregisteredSchemeToHttpScheme,                 \
+                   CUSTOM_UNREGISTERED_SCHEME, HTTP_SCHEME, sandbox_attribs)   \
+  CORS_TEST_IFRAME(name##CustomUnregisteredSchemeToCustomStandardScheme,       \
+                   CUSTOM_UNREGISTERED_SCHEME, CUSTOM_STANDARD_SCHEME,         \
+                   sandbox_attribs)                                            \
+  CORS_TEST_IFRAME(name##CustomUnregisteredSchemeToCustomNonStandardScheme,    \
+                   CUSTOM_UNREGISTERED_SCHEME, CUSTOM_NONSTANDARD_SCHEME,      \
+                   sandbox_attribs)                                            \
+  CORS_TEST_IFRAME(name##CustomUnregisteredSchemeToCustomUnregisteredScheme,   \
+                   CUSTOM_UNREGISTERED_SCHEME, CUSTOM_UNREGISTERED_SCHEME,     \
+                   sandbox_attribs)
+
+// Everything is blocked.
+CORS_TEST_IFRAME_ALL(None, "")
+
+// JavaScript execution is allowed.
+CORS_TEST_IFRAME_ALL(AllowScripts, "allow-scripts")
+
+// JavaScript execution is allowed and scripting the parent is allowed for
+// same-origin only.
+CORS_TEST_IFRAME_ALL(AllowScriptsAndSameOrigin,
+                     "allow-scripts allow-same-origin")
+
+namespace {
+
+const char kSubRequestMethod[] = "GET";
+const char kSubUnsafeHeaderName[] = "x-unsafe-header";
+const char kSubUnsafeHeaderValue[] = "not-safe";
+
+struct SubResource : CookieResource {
+  SubResource() {}
+
+  std::string main_origin;
+  bool supports_cors = false;
+  bool is_cross_origin = false;
+
+  void InitCors(HandlerType main_handler, bool add_header) {
+    // Must specify the method to differentiate from the preflight request.
+    method = kSubRequestMethod;
+
+    // Origin is always "null" for non-standard schemes.
+    main_origin =
+        IsNonStandardType(main_handler) ? "null" : GetOrigin(main_handler);
+
+    // True if cross-origin requests are allowed. XHR requests to non-standard
+    // schemes are not allowed (due to the "null" origin).
+    supports_cors = IsStandardType(handler);
+    if (!supports_cors) {
+      // Don't expect the xhr request.
+      expected_response_ct = 0;
+    }
+
+    // True if the request is considered cross-origin. Any requests between
+    // non-standard schemes are considered cross-origin (due to the "null"
+    // origin).
+    is_cross_origin =
+        main_handler != handler ||
+        (IsNonStandardType(main_handler) && handler == main_handler);
+
+    if (is_cross_origin && add_header) {
+      response->SetHeaderByName("Access-Control-Allow-Origin", main_origin,
+                                false);
+    }
+  }
+
+  bool VerifyRequest(CefRefPtr<CefRequest> request) const override {
+    if (!CookieResource::VerifyRequest(request)) {
+      return false;
+    }
+
+    const std::string& request_method = request->GetMethod();
+    EXPECT_STREQ(method.c_str(), request_method.c_str()) << GetPathURL();
+    if (request_method != method) {
+      return false;
+    }
+
+    // Verify that the "Origin" header contains the expected value.
+    const std::string& origin = request->GetHeaderByName("Origin");
+    const std::string& expected_origin =
+        is_cross_origin ? main_origin : std::string();
+    EXPECT_STREQ(expected_origin.c_str(), origin.c_str()) << GetPathURL();
+    if (expected_origin != origin) {
+      return false;
+    }
+
+    // Verify that the "X-Unsafe-Header" header contains the expected value.
+    const std::string& unsafe_header =
+        request->GetHeaderByName(kSubUnsafeHeaderName);
+    EXPECT_STREQ(kSubUnsafeHeaderValue, unsafe_header.c_str()) << GetPathURL();
+    return unsafe_header == kSubUnsafeHeaderValue;
+  }
+};
+
+// See https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
+// for details of CORS preflight behavior.
+struct PreflightResource : Resource {
+  std::string main_origin;
+
+  void InitPreflight(HandlerType main_handler) {
+    // CORS preflight requests originate from PreflightController in the network
+    // process, so we only expect them for server requests.
+    EXPECT_EQ(HandlerType::SERVER, handler);
+
+    // Origin is always "null" for non-standard schemes.
+    main_origin =
+        IsNonStandardType(main_handler) ? "null" : GetOrigin(main_handler);
+
+    method = "OPTIONS";
+    response->SetHeaderByName("Access-Control-Allow-Methods",
+                              "GET,HEAD,OPTIONS,POST", false);
+    response->SetHeaderByName("Access-Control-Allow-Headers",
+                              kSubUnsafeHeaderName, false);
+    response->SetHeaderByName("Access-Control-Allow-Origin", main_origin,
+                              false);
+  }
+
+  bool VerifyRequest(CefRefPtr<CefRequest> request) const override {
+    const std::string& request_method = request->GetMethod();
+    EXPECT_STREQ(method.c_str(), request_method.c_str()) << GetPathURL();
+    if (request_method != method) {
+      return false;
+    }
+
+    const std::string& origin = request->GetHeaderByName("Origin");
+    EXPECT_STREQ(main_origin.c_str(), origin.c_str()) << GetPathURL();
+    if (main_origin != origin) {
+      return false;
+    }
+
+    const std::string& ac_request_method =
+        request->GetHeaderByName("Access-Control-Request-Method");
+    EXPECT_STREQ(kSubRequestMethod, ac_request_method.c_str()) << GetPathURL();
+    if (ac_request_method != kSubRequestMethod) {
+      return false;
+    }
+
+    const std::string& ac_request_headers =
+        request->GetHeaderByName("Access-Control-Request-Headers");
+    EXPECT_STREQ(kSubUnsafeHeaderName, ac_request_headers.c_str())
+        << GetPathURL();
+    if (ac_request_headers != kSubUnsafeHeaderName) {
+      return false;
+    }
+
+    return true;
+  }
+};
+
+enum class ExecMode {
+  XHR,
+  FETCH,
+};
+
+std::string GetXhrExecJS(const std::string& sub_url) {
+  // Inclusion of an unsafe header triggers CORS preflight for cross-origin
+  // requests to the server.
+  return "xhr = new XMLHttpRequest();\n"
+         "xhr.open(\"GET\", \"" +
+         sub_url +
+         "\", true)\n;"
+         "xhr.setRequestHeader('" +
+         kSubUnsafeHeaderName + "', '" + kSubUnsafeHeaderValue +
+         "');\n"
+         "xhr.onload = function(e) {\n"
+         "  if (xhr.readyState === 4) {\n"
+         "    if (xhr.status === 200) {\n"
+         "      onResult(xhr.responseText);\n"
+         "    } else {\n"
+         "      console.log('XMLHttpRequest failed with status ' + "
+         "xhr.status);\n"
+         "      onResult('FAILURE');\n"
+         "    }\n"
+         "  }\n"
+         "};\n"
+         "xhr.onerror = function(e) {\n"
+         "  onResult('FAILURE');\n"
+         "};\n"
+         "xhr.send();\n";
+}
+
+std::string GetFetchExecJS(const std::string& sub_url) {
+  // Inclusion of an unsafe header triggers CORS preflight for cross-origin
+  // requests to the server.
+  return std::string() +
+         "let h = new Headers();\n"
+         "h.append('" +
+         kSubUnsafeHeaderName + "', '" + kSubUnsafeHeaderValue +
+         "');\n"
+         "fetch('" +
+         sub_url +
+         "', {headers: h})\n"
+         ".then(function(response) {\n"
+         "  if (response.status === 200) {\n"
+         "      response.text().then(function(text) {\n"
+         "          onResult(text);\n"
+         "      }).catch(function(e) {\n"
+         "          onResult('FAILURE')\n;        "
+         "      })\n;"
+         "  } else {\n"
+         "      onResult('FAILURE');\n"
+         "  }\n"
+         "}).catch(function(e) {\n"
+         "  onResult('FAILURE');\n"
+         "});\n";
+}
+
+std::string GetExecMainHtml(ExecMode mode, const std::string& sub_url) {
+  return std::string() +
+         "<html><head>\n"
+         "<script language=\"JavaScript\">\n" +
+         "function onResult(val) {\n"
+         "  if (val === '" +
+         kDefaultText + "') {" + GetSuccessMsgJS() + "} else {" +
+         GetFailureMsgJS() +
+         "}\n}\n"
+         "function execRequest() {\n" +
+         (mode == ExecMode::XHR ? GetXhrExecJS(sub_url)
+                                : GetFetchExecJS(sub_url)) +
+         "}\n</script>\n"
+         "</head><body onload=\"execRequest();\">"
+         "Running execRequest..."
+         "</body></html>";
+}
+
+// XHR and fetch requests behave the same, except for console message contents.
+// In addition to basic CORS header behaviors and request blocking, this test
+// verifies that CORS preflight requests are sent and received when expected.
+// Since preflight behavior is implemented in the network process we expect it
+// to already have substantial test coverage in Chromium.
+void SetupExecRequest(ExecMode mode,
+                      CookieTestSetup* setup,
+                      const std::string& test_name,
+                      HandlerType main_handler,
+                      CookieResource* main_resource,
+                      HandlerType sub_handler,
+                      SubResource* sub_resource,
+                      PreflightResource* preflight_resource,
+                      bool add_header) {
+  const std::string& base_path = "/" + test_name;
+
+  // Expect a single xhr request.
+  const std::string& sub_path = base_path + ".sub.txt";
+  sub_resource->Init(sub_handler, sub_path, kMimeTypeText, kDefaultText);
+  sub_resource->InitCors(main_handler, add_header);
+
+  // Expect a single main frame request.
+  const std::string& sub_url = sub_resource->GetPathURL();
+  main_resource->Init(main_handler, base_path, kMimeTypeHtml,
+                      GetExecMainHtml(mode, sub_url));
+
+  SetupCookieExpectations(setup, main_resource, sub_resource);
+
+  // Cross-origin requests to a server sub-resource will receive a CORS
+  // preflight request because we add an unsafe header.
+  const bool expect_cors_preflight =
+      sub_resource->is_cross_origin && sub_handler == HandlerType::SERVER;
+
+  if (sub_resource->is_cross_origin &&
+      (!sub_resource->supports_cors || !add_header)) {
+    // Expect the cross-origin XHR to be blocked.
+    main_resource->expected_failure_query_ct = 1;
+
+    if (sub_resource->supports_cors && !add_header) {
+      // The request supports CORS, but we didn't add the
+      // "Access-Control-Allow-Origin" header.
+      if (!expect_cors_preflight || preflight_resource != nullptr) {
+        // This is the error message when not expecting a CORS preflight
+        // request, or when the preflight request is handled by the server.
+        // Unhandled preflight requests will output a different error message
+        // (see below).
+        if (mode == ExecMode::XHR) {
+          setup->AddConsoleMessage(
+              "Access to XMLHttpRequest at '" + sub_url + "' from origin '" +
+              sub_resource->main_origin +
+              "' has been blocked by CORS policy: No "
+              "'Access-Control-Allow-Origin' "
+              "header is present on the requested resource.");
+        } else {
+          setup->AddConsoleMessage(
+              "Access to fetch at '" + sub_url + "' from origin '" +
+              sub_resource->main_origin +
+              "' has been blocked by CORS policy: No "
+              "'Access-Control-Allow-Origin' header is present on the "
+              "requested "
+              "resource. If an opaque response serves your needs, set the "
+              "request's mode to 'no-cors' to fetch the resource with CORS "
+              "disabled.");
+        }
+      }
+    } else if (mode == ExecMode::XHR) {
+      setup->AddConsoleMessage(
+          "Access to XMLHttpRequest at '" + sub_url + "' from origin '" +
+          sub_resource->main_origin +
+          "' has been blocked by CORS policy: Cross origin requests are only "
+          "supported for protocol schemes:");
+    } else {
+      setup->AddConsoleMessage("Fetch API cannot load " + sub_url +
+                               ". URL scheme \"" + GetScheme(sub_handler) +
+                               "\" is not supported.");
+    }
+  } else {
+    // Expect the (possibly cross-origin) XHR to be allowed.
+    main_resource->expected_success_query_ct = 1;
+  }
+
+  setup->AddResource(main_resource);
+  setup->AddResource(sub_resource);
+
+  if (expect_cors_preflight) {
+    // Expect a CORS preflight request.
+    if (preflight_resource) {
+      // The server will handle the preflight request. The cross-origin XHR may
+      // still be blocked if the "Access-Control-Allow-Origin" header is missing
+      // (see above).
+      preflight_resource->Init(sub_handler, sub_path, kMimeTypeText,
+                               std::string());
+      preflight_resource->InitPreflight(main_handler);
+      setup->AddResource(preflight_resource);
+    } else {
+      // The server will not handle the preflight request. Expect the
+      // cross-origin XHR to be blocked.
+      main_resource->expected_failure_query_ct = 1;
+      main_resource->expected_success_query_ct = 0;
+      sub_resource->expected_response_ct = 0;
+
+      if (mode == ExecMode::XHR) {
+        setup->AddConsoleMessage(
+            "Access to XMLHttpRequest at '" + sub_url + "' from origin '" +
+            sub_resource->main_origin +
+            "' has been blocked by CORS policy: Response to preflight request "
+            "doesn't pass access control check: No "
+            "'Access-Control-Allow-Origin' header is present on the requested "
+            "resource.");
+      } else {
+        setup->AddConsoleMessage(
+            "Access to fetch at '" + sub_url + "' from origin '" +
+            sub_resource->main_origin +
+            "' has been blocked by CORS policy: Response to preflight request "
+            "doesn't pass access control check: No "
+            "'Access-Control-Allow-Origin' header is present on the requested "
+            "resource. If an opaque response serves your needs, set the "
+            "request's mode to 'no-cors' to fetch the resource with CORS "
+            "disabled.");
+      }
+    }
+  }
+}
+
+}  // namespace
+
+// Test XHR requests with different origin combinations.
+#define CORS_TEST_XHR(test_name, handler_main, handler_sub, add_header) \
+  TEST(CorsTest, Xhr##test_name) {                                      \
+    CookieTestSetup setup;                                              \
+    CookieResource resource_main;                                       \
+    SubResource resource_sub;                                           \
+    PreflightResource resource_preflight;                               \
+    SetupExecRequest(ExecMode::XHR, &setup, "CorsTest.Xhr" #test_name,  \
+                     HandlerType::handler_main, &resource_main,         \
+                     HandlerType::handler_sub, &resource_sub,           \
+                     &resource_preflight, add_header);                  \
+    CefRefPtr<CorsTestHandler> handler = new CorsTestHandler(&setup);   \
+    handler->ExecuteTest();                                             \
+    ReleaseAndWaitForDestructor(handler);                               \
+  }
+
+// Test all origin combinations (same and cross-origin).
+#define CORS_TEST_XHR_ALL(name, add_header)                                    \
+  CORS_TEST_XHR(name##ServerToServer, SERVER, SERVER, add_header)              \
+  CORS_TEST_XHR(name##ServerToHttpScheme, SERVER, HTTP_SCHEME, add_header)     \
+  CORS_TEST_XHR(name##ServerToCustomStandardScheme, SERVER,                    \
+                CUSTOM_STANDARD_SCHEME, add_header)                            \
+  CORS_TEST_XHR(name##ServerToCustomNonStandardScheme, SERVER,                 \
+                CUSTOM_NONSTANDARD_SCHEME, add_header)                         \
+  CORS_TEST_XHR(name##ServerToCustomUnregisteredScheme, SERVER,                \
+                CUSTOM_UNREGISTERED_SCHEME, add_header)                        \
+  CORS_TEST_XHR(name##HttpSchemeToServer, HTTP_SCHEME, SERVER, add_header)     \
+  CORS_TEST_XHR(name##HttpSchemeToHttpScheme, HTTP_SCHEME, HTTP_SCHEME,        \
+                add_header)                                                    \
+  CORS_TEST_XHR(name##HttpSchemeToCustomStandardScheme, HTTP_SCHEME,           \
+                CUSTOM_STANDARD_SCHEME, add_header)                            \
+  CORS_TEST_XHR(name##HttpSchemeToCustomNonStandardScheme, HTTP_SCHEME,        \
+                CUSTOM_NONSTANDARD_SCHEME, add_header)                         \
+  CORS_TEST_XHR(name##HttpSchemeToCustomUnregisteredScheme, HTTP_SCHEME,       \
+                CUSTOM_UNREGISTERED_SCHEME, add_header)                        \
+  CORS_TEST_XHR(name##CustomStandardSchemeToServer, CUSTOM_STANDARD_SCHEME,    \
+                SERVER, add_header)                                            \
+  CORS_TEST_XHR(name##CustomStandardSchemeToHttpScheme,                        \
+                CUSTOM_STANDARD_SCHEME, HTTP_SCHEME, add_header)               \
+  CORS_TEST_XHR(name##CustomStandardSchemeToCustomStandardScheme,              \
+                CUSTOM_STANDARD_SCHEME, CUSTOM_STANDARD_SCHEME, add_header)    \
+  CORS_TEST_XHR(name##CustomStandardSchemeToCustomNonStandardScheme,           \
+                CUSTOM_STANDARD_SCHEME, CUSTOM_NONSTANDARD_SCHEME, add_header) \
+  CORS_TEST_XHR(name##CustomStandardSchemeToCustomUnregisteredScheme,          \
+                CUSTOM_STANDARD_SCHEME, CUSTOM_UNREGISTERED_SCHEME,            \
+                add_header)                                                    \
+  CORS_TEST_XHR(name##CustomNonStandardSchemeToServer,                         \
+                CUSTOM_NONSTANDARD_SCHEME, SERVER, add_header)                 \
+  CORS_TEST_XHR(name##CustomNonStandardSchemeToHttpScheme,                     \
+                CUSTOM_NONSTANDARD_SCHEME, HTTP_SCHEME, add_header)            \
+  CORS_TEST_XHR(name##CustomNonStandardSchemeToCustomStandardScheme,           \
+                CUSTOM_NONSTANDARD_SCHEME, CUSTOM_STANDARD_SCHEME, add_header) \
+  CORS_TEST_XHR(name##CustomNonStandardSchemeToCustomNonStandardScheme,        \
+                CUSTOM_NONSTANDARD_SCHEME, CUSTOM_NONSTANDARD_SCHEME,          \
+                add_header)                                                    \
+  CORS_TEST_XHR(name##CustomNonStandardSchemeToCustomUnregisteredScheme,       \
+                CUSTOM_NONSTANDARD_SCHEME, CUSTOM_UNREGISTERED_SCHEME,         \
+                add_header)                                                    \
+  CORS_TEST_XHR(name##CustomUnregisteredSchemeToServer,                        \
+                CUSTOM_UNREGISTERED_SCHEME, SERVER, add_header)                \
+  CORS_TEST_XHR(name##CustomUnregisteredSchemeToHttpScheme,                    \
+                CUSTOM_UNREGISTERED_SCHEME, HTTP_SCHEME, add_header)           \
+  CORS_TEST_XHR(name##CustomUnregisteredSchemeToCustomStandardScheme,          \
+                CUSTOM_UNREGISTERED_SCHEME, CUSTOM_STANDARD_SCHEME,            \
+                add_header)                                                    \
+  CORS_TEST_XHR(name##CustomUnregisteredSchemeToCustomNonStandardScheme,       \
+                CUSTOM_UNREGISTERED_SCHEME, CUSTOM_NONSTANDARD_SCHEME,         \
+                add_header)                                                    \
+  CORS_TEST_XHR(name##CustomUnregisteredSchemeToCustomUnregisteredScheme,      \
+                CUSTOM_UNREGISTERED_SCHEME, CUSTOM_UNREGISTERED_SCHEME,        \
+                add_header)
+
+// XHR requests without the "Access-Control-Allow-Origin" header.
+CORS_TEST_XHR_ALL(NoHeader, false)
+
+// XHR requests with the "Access-Control-Allow-Origin" header.
+CORS_TEST_XHR_ALL(WithHeader, true)
+
+// Like above, but without handling CORS preflight requests.
+#define CORS_TEST_XHR_NO_PREFLIGHT(test_name, handler_main, handler_sub, \
+                                   add_header)                           \
+  TEST(CorsTest, Xhr##test_name) {                                       \
+    CookieTestSetup setup;                                               \
+    CookieResource resource_main;                                        \
+    SubResource resource_sub;                                            \
+    SetupExecRequest(ExecMode::XHR, &setup, "CorsTest.Xhr" #test_name,   \
+                     HandlerType::handler_main, &resource_main,          \
+                     HandlerType::handler_sub, &resource_sub, nullptr,   \
+                     add_header);                                        \
+    CefRefPtr<CorsTestHandler> handler = new CorsTestHandler(&setup);    \
+    handler->ExecuteTest();                                              \
+    ReleaseAndWaitForDestructor(handler);                                \
+  }
+
+#define CORS_TEST_XHR_NO_PREFLIGHT_SERVER(name, add_header)                    \
+  CORS_TEST_XHR_NO_PREFLIGHT(name##ServerToServer, SERVER, SERVER, add_header) \
+  CORS_TEST_XHR_NO_PREFLIGHT(name##HttpSchemeToServer, HTTP_SCHEME, SERVER,    \
+                             add_header)                                       \
+  CORS_TEST_XHR_NO_PREFLIGHT(name##CustomStandardSchemeToServer,               \
+                             CUSTOM_STANDARD_SCHEME, SERVER, add_header)       \
+  CORS_TEST_XHR_NO_PREFLIGHT(name##CustomNonStandardSchemeToServer,            \
+                             CUSTOM_NONSTANDARD_SCHEME, SERVER, add_header)
+
+// XHR requests without the "Access-Control-Allow-Origin" header.
+CORS_TEST_XHR_NO_PREFLIGHT_SERVER(NoHeaderNoPreflight, false)
+
+// XHR requests with the "Access-Control-Allow-Origin" header.
+CORS_TEST_XHR_NO_PREFLIGHT_SERVER(WithHeaderNoPreflight, true)
+
+// Test fetch requests with different origin combinations.
+#define CORS_TEST_FETCH(test_name, handler_main, handler_sub, add_header)  \
+  TEST(CorsTest, Fetch##test_name) {                                       \
+    CookieTestSetup setup;                                                 \
+    CookieResource resource_main;                                          \
+    SubResource resource_sub;                                              \
+    PreflightResource resource_preflight;                                  \
+    SetupExecRequest(ExecMode::FETCH, &setup, "CorsTest.Fetch" #test_name, \
+                     HandlerType::handler_main, &resource_main,            \
+                     HandlerType::handler_sub, &resource_sub,              \
+                     &resource_preflight, add_header);                     \
+    CefRefPtr<CorsTestHandler> handler = new CorsTestHandler(&setup);      \
+    handler->ExecuteTest();                                                \
+    ReleaseAndWaitForDestructor(handler);                                  \
+  }
+
+// Test all origin combinations (same and cross-origin).
+#define CORS_TEST_FETCH_ALL(name, add_header)                                 \
+  CORS_TEST_FETCH(name##ServerToServer, SERVER, SERVER, add_header)           \
+  CORS_TEST_FETCH(name##ServerToHttpScheme, SERVER, HTTP_SCHEME, add_header)  \
+  CORS_TEST_FETCH(name##ServerToCustomStandardScheme, SERVER,                 \
+                  CUSTOM_STANDARD_SCHEME, add_header)                         \
+  CORS_TEST_FETCH(name##ServerToCustomNonStandardScheme, SERVER,              \
+                  CUSTOM_NONSTANDARD_SCHEME, add_header)                      \
+  CORS_TEST_FETCH(name##ServerToCustomUnregisteredScheme, SERVER,             \
+                  CUSTOM_UNREGISTERED_SCHEME, add_header)                     \
+  CORS_TEST_FETCH(name##HttpSchemeToServer, HTTP_SCHEME, SERVER, add_header)  \
+  CORS_TEST_FETCH(name##HttpSchemeToHttpScheme, HTTP_SCHEME, HTTP_SCHEME,     \
+                  add_header)                                                 \
+  CORS_TEST_FETCH(name##HttpSchemeToCustomStandardScheme, HTTP_SCHEME,        \
+                  CUSTOM_STANDARD_SCHEME, add_header)                         \
+  CORS_TEST_FETCH(name##HttpSchemeToCustomNonStandardScheme, HTTP_SCHEME,     \
+                  CUSTOM_NONSTANDARD_SCHEME, add_header)                      \
+  CORS_TEST_FETCH(name##HttpSchemeToCustomUnregisteredScheme, HTTP_SCHEME,    \
+                  CUSTOM_UNREGISTERED_SCHEME, add_header)                     \
+  CORS_TEST_FETCH(name##CustomStandardSchemeToServer, CUSTOM_STANDARD_SCHEME, \
+                  SERVER, add_header)                                         \
+  CORS_TEST_FETCH(name##CustomStandardSchemeToHttpScheme,                     \
+                  CUSTOM_STANDARD_SCHEME, HTTP_SCHEME, add_header)            \
+  CORS_TEST_FETCH(name##CustomStandardSchemeToCustomStandardScheme,           \
+                  CUSTOM_STANDARD_SCHEME, CUSTOM_STANDARD_SCHEME, add_header) \
+  CORS_TEST_FETCH(name##CustomStandardSchemeToCustomNonStandardScheme,        \
+                  CUSTOM_STANDARD_SCHEME, CUSTOM_NONSTANDARD_SCHEME,          \
+                  add_header)                                                 \
+  CORS_TEST_FETCH(name##CustomStandardSchemeToCustomUnregisteredScheme,       \
+                  CUSTOM_STANDARD_SCHEME, CUSTOM_UNREGISTERED_SCHEME,         \
+                  add_header)                                                 \
+  CORS_TEST_FETCH(name##CustomNonStandardSchemeToServer,                      \
+                  CUSTOM_NONSTANDARD_SCHEME, SERVER, add_header)              \
+  CORS_TEST_FETCH(name##CustomNonStandardSchemeToHttpScheme,                  \
+                  CUSTOM_NONSTANDARD_SCHEME, HTTP_SCHEME, add_header)         \
+  CORS_TEST_FETCH(name##CustomNonStandardSchemeToCustomStandardScheme,        \
+                  CUSTOM_NONSTANDARD_SCHEME, CUSTOM_STANDARD_SCHEME,          \
+                  add_header)                                                 \
+  CORS_TEST_FETCH(name##CustomNonStandardSchemeToCustomNonStandardScheme,     \
+                  CUSTOM_NONSTANDARD_SCHEME, CUSTOM_NONSTANDARD_SCHEME,       \
+                  add_header)                                                 \
+  CORS_TEST_FETCH(name##CustomNonStandardSchemeToCustomUnregisteredScheme,    \
+                  CUSTOM_NONSTANDARD_SCHEME, CUSTOM_UNREGISTERED_SCHEME,      \
+                  add_header)                                                 \
+  CORS_TEST_FETCH(name##CustomUnregisteredSchemeToServer,                     \
+                  CUSTOM_UNREGISTERED_SCHEME, SERVER, add_header)             \
+  CORS_TEST_FETCH(name##CustomUnregisteredSchemeToHttpScheme,                 \
+                  CUSTOM_UNREGISTERED_SCHEME, HTTP_SCHEME, add_header)        \
+  CORS_TEST_FETCH(name##CustomUnregisteredSchemeToCustomStandardScheme,       \
+                  CUSTOM_UNREGISTERED_SCHEME, CUSTOM_STANDARD_SCHEME,         \
+                  add_header)                                                 \
+  CORS_TEST_FETCH(name##CustomUnregisteredSchemeToCustomNonStandardScheme,    \
+                  CUSTOM_UNREGISTERED_SCHEME, CUSTOM_NONSTANDARD_SCHEME,      \
+                  add_header)                                                 \
+  CORS_TEST_FETCH(name##CustomUnregisteredSchemeToCustomUnregisteredScheme,   \
+                  CUSTOM_UNREGISTERED_SCHEME, CUSTOM_UNREGISTERED_SCHEME,     \
+                  add_header)
+
+// Fetch requests without the "Access-Control-Allow-Origin" header.
+CORS_TEST_FETCH_ALL(NoHeader, false)
+
+// Fetch requests with the "Access-Control-Allow-Origin" header.
+CORS_TEST_FETCH_ALL(WithHeader, true)
+
+// Like above, but without handling CORS preflight requests.
+#define CORS_TEST_FETCH_NO_PREFLIGHT(test_name, handler_main, handler_sub, \
+                                     add_header)                           \
+  TEST(CorsTest, Fetch##test_name) {                                       \
+    CookieTestSetup setup;                                                 \
+    CookieResource resource_main;                                          \
+    SubResource resource_sub;                                              \
+    SetupExecRequest(ExecMode::FETCH, &setup, "CorsTest.Fetch" #test_name, \
+                     HandlerType::handler_main, &resource_main,            \
+                     HandlerType::handler_sub, &resource_sub, nullptr,     \
+                     add_header);                                          \
+    CefRefPtr<CorsTestHandler> handler = new CorsTestHandler(&setup);      \
+    handler->ExecuteTest();                                                \
+    ReleaseAndWaitForDestructor(handler);                                  \
+  }
+
+#define CORS_TEST_FETCH_NO_PREFLIGHT_SERVER(name, add_header)                 \
+  CORS_TEST_FETCH_NO_PREFLIGHT(name##ServerToServer, SERVER, SERVER,          \
+                               add_header)                                    \
+  CORS_TEST_FETCH_NO_PREFLIGHT(name##HttpSchemeToServer, HTTP_SCHEME, SERVER, \
+                               add_header)                                    \
+  CORS_TEST_FETCH_NO_PREFLIGHT(name##CustomStandardSchemeToServer,            \
+                               CUSTOM_STANDARD_SCHEME, SERVER, add_header)    \
+  CORS_TEST_FETCH_NO_PREFLIGHT(name##CustomNonStandardSchemeToServer,         \
+                               CUSTOM_NONSTANDARD_SCHEME, SERVER, add_header)
+
+// Fetch requests without the "Access-Control-Allow-Origin" header.
+CORS_TEST_FETCH_NO_PREFLIGHT_SERVER(NoHeaderNoPreflight, false)
+
+// Fetch requests with the "Access-Control-Allow-Origin" header.
+CORS_TEST_FETCH_NO_PREFLIGHT_SERVER(WithHeaderNoPreflight, true)
+
+namespace {
+
+enum class RedirectMode {
+  MODE_302,
+  MODE_307,
+};
+
+struct RedirectGetResource : CookieResource {
+  RedirectGetResource() {}
+
+  bool VerifyRequest(CefRefPtr<CefRequest> request) const override {
+    if (!CookieResource::VerifyRequest(request)) {
+      return false;
+    }
+
+    // The "Origin" header should never be present for a redirect.
+    const std::string& origin = request->GetHeaderByName("Origin");
+    EXPECT_TRUE(origin.empty()) << GetPathURL();
+    return origin.empty();
+  }
+};
+
+void SetupRedirectResponse(RedirectMode mode,
+                           const std::string& redirect_url,
+                           CefRefPtr<CefResponse> response) {
+  if (mode == RedirectMode::MODE_302) {
+    response->SetStatus(302);
+  } else if (mode == RedirectMode::MODE_307) {
+    response->SetStatus(307);
+  } else {
+    NOTREACHED();
+  }
+
+  response->SetHeaderByName("Location", redirect_url,
+                            /*override=*/false);
+}
+
+// Test redirect requests.
+void SetupRedirectGetRequest(RedirectMode mode,
+                             CookieTestSetup* setup,
+                             const std::string& test_name,
+                             HandlerType main_handler,
+                             CookieResource* main_resource,
+                             HandlerType redirect_handler,
+                             RedirectGetResource* redirect_resource) {
+  const std::string& base_path = "/" + test_name;
+
+  // Expect a single redirect request that sends SuccessMsg.
+  redirect_resource->Init(redirect_handler, base_path + ".redirect.html",
+                          kMimeTypeHtml, GetDefaultSuccessMsgHtml());
+  redirect_resource->expected_success_query_ct = 1;
+
+  // Expect a single main request that results in a redirect.
+  const std::string& redirect_url = redirect_resource->GetPathURL();
+  main_resource->Init(main_handler, base_path, kMimeTypeHtml, std::string());
+  SetupRedirectResponse(mode, redirect_url, main_resource->response);
+
+  SetupCookieExpectations(setup, main_resource, redirect_resource);
+
+  setup->AddResource(main_resource);
+  setup->AddResource(redirect_resource);
+}
+
+}  // namespace
+
+// Test redirect GET requests with different origin combinations.
+#define CORS_TEST_REDIRECT_GET(test_name, mode, handler_main,          \
+                               handler_redirect)                       \
+  TEST(CorsTest, RedirectGet##test_name) {                             \
+    CookieTestSetup setup;                                             \
+    CookieResource resource_main;                                      \
+    RedirectGetResource resource_redirect;                             \
+    SetupRedirectGetRequest(                                           \
+        RedirectMode::mode, &setup, "CorsTest.RedirectGet" #test_name, \
+        HandlerType::handler_main, &resource_main,                     \
+        HandlerType::handler_redirect, &resource_redirect);            \
+    CefRefPtr<CorsTestHandler> handler = new CorsTestHandler(&setup);  \
+    handler->ExecuteTest();                                            \
+    ReleaseAndWaitForDestructor(handler);                              \
+  }
+
+// Test all redirect GET combinations (same and cross-origin).
+#define CORS_TEST_REDIRECT_GET_ALL(name, mode)                                 \
+  CORS_TEST_REDIRECT_GET(name##ServerToServer, mode, SERVER, SERVER)           \
+  CORS_TEST_REDIRECT_GET(name##ServerToHttpScheme, mode, SERVER, HTTP_SCHEME)  \
+  CORS_TEST_REDIRECT_GET(name##ServerToCustomStandardScheme, mode, SERVER,     \
+                         CUSTOM_STANDARD_SCHEME)                               \
+  CORS_TEST_REDIRECT_GET(name##ServerToCustomNonStandardScheme, mode, SERVER,  \
+                         CUSTOM_NONSTANDARD_SCHEME)                            \
+  CORS_TEST_REDIRECT_GET(name##ServerToCustomUnregisteredScheme, mode, SERVER, \
+                         CUSTOM_UNREGISTERED_SCHEME)                           \
+  CORS_TEST_REDIRECT_GET(name##HttpSchemeToServer, mode, HTTP_SCHEME, SERVER)  \
+  CORS_TEST_REDIRECT_GET(name##HttpSchemeToHttpScheme, mode, HTTP_SCHEME,      \
+                         HTTP_SCHEME)                                          \
+  CORS_TEST_REDIRECT_GET(name##HttpSchemeToCustomStandardScheme, mode,         \
+                         HTTP_SCHEME, CUSTOM_STANDARD_SCHEME)                  \
+  CORS_TEST_REDIRECT_GET(name##HttpSchemeToCustomNonStandardScheme, mode,      \
+                         HTTP_SCHEME, CUSTOM_NONSTANDARD_SCHEME)               \
+  CORS_TEST_REDIRECT_GET(name##HttpSchemeToCustomUnregisteredScheme, mode,     \
+                         HTTP_SCHEME, CUSTOM_UNREGISTERED_SCHEME)              \
+  CORS_TEST_REDIRECT_GET(name##CustomStandardSchemeToServer, mode,             \
+                         CUSTOM_STANDARD_SCHEME, SERVER)                       \
+  CORS_TEST_REDIRECT_GET(name##CustomStandardSchemeToHttpScheme, mode,         \
+                         CUSTOM_STANDARD_SCHEME, HTTP_SCHEME)                  \
+  CORS_TEST_REDIRECT_GET(name##CustomStandardSchemeToCustomStandardScheme,     \
+                         mode, CUSTOM_STANDARD_SCHEME, CUSTOM_STANDARD_SCHEME) \
+  CORS_TEST_REDIRECT_GET(name##CustomStandardSchemeToCustomNonStandardScheme,  \
+                         mode, CUSTOM_STANDARD_SCHEME,                         \
+                         CUSTOM_NONSTANDARD_SCHEME)                            \
+  CORS_TEST_REDIRECT_GET(name##CustomStandardSchemeToCustomUnregisteredScheme, \
+                         mode, CUSTOM_STANDARD_SCHEME,                         \
+                         CUSTOM_UNREGISTERED_SCHEME)                           \
+  CORS_TEST_REDIRECT_GET(name##CustomNonStandardSchemeToServer, mode,          \
+                         CUSTOM_NONSTANDARD_SCHEME, SERVER)                    \
+  CORS_TEST_REDIRECT_GET(name##CustomNonStandardSchemeToHttpScheme, mode,      \
+                         CUSTOM_NONSTANDARD_SCHEME, HTTP_SCHEME)               \
+  CORS_TEST_REDIRECT_GET(name##CustomNonStandardSchemeToCustomStandardScheme,  \
+                         mode, CUSTOM_NONSTANDARD_SCHEME,                      \
+                         CUSTOM_STANDARD_SCHEME)                               \
+  CORS_TEST_REDIRECT_GET(                                                      \
+      name##CustomNonStandardSchemeToCustomNonStandardScheme, mode,            \
+      CUSTOM_NONSTANDARD_SCHEME, CUSTOM_NONSTANDARD_SCHEME)                    \
+  CORS_TEST_REDIRECT_GET(                                                      \
+      name##CustomNonStandardSchemeToCustomUnregisteredScheme, mode,           \
+      CUSTOM_NONSTANDARD_SCHEME, CUSTOM_UNREGISTERED_SCHEME)                   \
+  CORS_TEST_REDIRECT_GET(name##CustomUnregisteredSchemeToServer, mode,         \
+                         CUSTOM_UNREGISTERED_SCHEME, SERVER)                   \
+  CORS_TEST_REDIRECT_GET(name##CustomUnregisteredSchemeToHttpScheme, mode,     \
+                         CUSTOM_UNREGISTERED_SCHEME, HTTP_SCHEME)              \
+  CORS_TEST_REDIRECT_GET(name##CustomUnregisteredSchemeToCustomStandardScheme, \
+                         mode, CUSTOM_UNREGISTERED_SCHEME,                     \
+                         CUSTOM_STANDARD_SCHEME)                               \
+  CORS_TEST_REDIRECT_GET(                                                      \
+      name##CustomUnregisteredSchemeToCustomNonStandardScheme, mode,           \
+      CUSTOM_UNREGISTERED_SCHEME, CUSTOM_NONSTANDARD_SCHEME)                   \
+  CORS_TEST_REDIRECT_GET(                                                      \
+      name##CustomUnregisteredSchemeToCustomUnregisteredScheme, mode,          \
+      CUSTOM_UNREGISTERED_SCHEME, CUSTOM_UNREGISTERED_SCHEME)
+
+// Redirect GET requests.
+CORS_TEST_REDIRECT_GET_ALL(302, MODE_302)
+CORS_TEST_REDIRECT_GET_ALL(307, MODE_307)
+
+namespace {
+
+struct PostResource : CookieResource {
+  PostResource() {}
+
+  bool expect_downgrade_to_get = false;
+  bool was_redirected = false;
+
+  std::string main_origin;
+  bool is_cross_origin;
+
+  void InitOrigin(HandlerType main_handler) {
+    // Origin is always "null" for non-HTTP(S) schemes.
+    // This should only be "null" for non-standard schemes, but Blink is likely
+    // using SchemeIsHTTPOrHTTPS() when submitting the form request.
+    main_origin = IsNonStandardType(main_handler) ||
+                          main_handler == HandlerType::CUSTOM_STANDARD_SCHEME
+                      ? "null"
+                      : GetOrigin(main_handler);
+
+    // True if the request is considered cross-origin. Any requests between
+    // non-standard schemes are considered cross-origin (due to the "null"
+    // origin).
+    is_cross_origin =
+        main_handler != handler ||
+        (IsNonStandardType(main_handler) && handler == main_handler);
+  }
+
+  bool VerifyRequest(CefRefPtr<CefRequest> request) const override {
+    if (!CookieResource::VerifyRequest(request)) {
+      return false;
+    }
+
+    // The "Origin" header should be present if the request is POST, and was not
+    // redirected cross-origin.
+    std::string expected_origin;
+    if (!expect_downgrade_to_get) {
+      if (was_redirected && is_cross_origin) {
+        // Always "null" for cross-origin redirects.
+        expected_origin = "null";
+      } else {
+        expected_origin = main_origin;
+      }
+    }
+
+    const std::string& origin = request->GetHeaderByName("Origin");
+    EXPECT_STREQ(expected_origin.c_str(), origin.c_str()) << GetPathURL();
+    if (expected_origin != origin) {
+      return false;
+    }
+
+    const std::string& req_method = request->GetMethod();
+    const bool has_post_data = request->GetPostData() != nullptr;
+    if (expect_downgrade_to_get) {
+      EXPECT_FALSE(has_post_data) << GetPathURL();
+      EXPECT_STREQ("GET", req_method.c_str()) << GetPathURL();
+      return !has_post_data && req_method == "GET";
+    } else {
+      EXPECT_TRUE(has_post_data) << GetPathURL();
+      EXPECT_STREQ("POST", req_method.c_str()) << GetPathURL();
+      return has_post_data && req_method == "POST";
+    }
+  }
+};
+
+std::string GetPostFormHtml(const std::string& submit_url) {
+  return "<html><body>"
+         "<form id=\"f\" action=\"" +
+         submit_url +
+         "\" method=\"post\">"
+         "<input type=\"hidden\" name=\"n\" value=\"v\"></form>"
+         "<script>document.getElementById('f').submit();</script>"
+         "</body></html>";
+}
+
+// Test redirect requests.
+void SetupRedirectPostRequest(RedirectMode mode,
+                              CookieTestSetup* setup,
+                              const std::string& test_name,
+                              HandlerType main_handler,
+                              CookieResource* main_resource,
+                              PostResource* submit_resource,
+                              HandlerType redirect_handler,
+                              PostResource* redirect_resource) {
+  const std::string& base_path = "/" + test_name;
+
+  // Expect a single redirect request that sends SuccessMsg.
+  redirect_resource->Init(redirect_handler, base_path + ".redirect.html",
+                          kMimeTypeHtml, GetDefaultSuccessMsgHtml());
+  redirect_resource->InitOrigin(main_handler);
+  redirect_resource->expected_success_query_ct = 1;
+
+  // 302 redirects will downgrade POST requests to GET.
+  redirect_resource->expect_downgrade_to_get = mode == RedirectMode::MODE_302;
+  redirect_resource->was_redirected = true;
+
+  // Expect a single submit request that redirects the response.
+  const std::string& redirect_url = redirect_resource->GetPathURL();
+  submit_resource->Init(main_handler, base_path + ".submit.html", kMimeTypeHtml,
+                        std::string());
+  submit_resource->InitOrigin(main_handler);
+  SetupRedirectResponse(mode, redirect_url, submit_resource->response);
+
+  // Expect a single main request that submits the form.
+  const std::string& submit_url = submit_resource->GetPathURL();
+  main_resource->Init(main_handler, base_path, kMimeTypeHtml,
+                      GetPostFormHtml(submit_url));
+
+  SetupCookieExpectations(setup, main_resource, submit_resource);
+  SetupCookieExpectations(setup, main_resource, redirect_resource);
+
+  setup->AddResource(main_resource);
+  setup->AddResource(submit_resource);
+  setup->AddResource(redirect_resource);
+}
+
+}  // namespace
+
+// Test redirect GET requests with different origin combinations.
+#define CORS_TEST_REDIRECT_POST(test_name, mode, handler_main,          \
+                                handler_redirect)                       \
+  TEST(CorsTest, RedirectPost##test_name) {                             \
+    CookieTestSetup setup;                                              \
+    CookieResource resource_main;                                       \
+    PostResource resource_submit, resource_redirect;                    \
+    SetupRedirectPostRequest(                                           \
+        RedirectMode::mode, &setup, "CorsTest.RedirectPost" #test_name, \
+        HandlerType::handler_main, &resource_main, &resource_submit,    \
+        HandlerType::handler_redirect, &resource_redirect);             \
+    CefRefPtr<CorsTestHandler> handler = new CorsTestHandler(&setup);   \
+    handler->ExecuteTest();                                             \
+    ReleaseAndWaitForDestructor(handler);                               \
+  }
+
+// Test all redirect GET combinations (same and cross-origin).
+#define CORS_TEST_REDIRECT_POST_ALL(name, mode)                                \
+  CORS_TEST_REDIRECT_POST(name##ServerToServer, mode, SERVER, SERVER)          \
+  CORS_TEST_REDIRECT_POST(name##ServerToHttpScheme, mode, SERVER, HTTP_SCHEME) \
+  CORS_TEST_REDIRECT_POST(name##ServerToCustomStandardScheme, mode, SERVER,    \
+                          CUSTOM_STANDARD_SCHEME)                              \
+  CORS_TEST_REDIRECT_POST(name##ServerToCustomNonStandardScheme, mode, SERVER, \
+                          CUSTOM_NONSTANDARD_SCHEME)                           \
+  CORS_TEST_REDIRECT_POST(name##ServerToCustomUnregisteredScheme, mode,        \
+                          SERVER, CUSTOM_UNREGISTERED_SCHEME)                  \
+  CORS_TEST_REDIRECT_POST(name##HttpSchemeToServer, mode, HTTP_SCHEME, SERVER) \
+  CORS_TEST_REDIRECT_POST(name##HttpSchemeToHttpScheme, mode, HTTP_SCHEME,     \
+                          HTTP_SCHEME)                                         \
+  CORS_TEST_REDIRECT_POST(name##HttpSchemeToCustomStandardScheme, mode,        \
+                          HTTP_SCHEME, CUSTOM_STANDARD_SCHEME)                 \
+  CORS_TEST_REDIRECT_POST(name##HttpSchemeToCustomNonStandardScheme, mode,     \
+                          HTTP_SCHEME, CUSTOM_NONSTANDARD_SCHEME)              \
+  CORS_TEST_REDIRECT_POST(name##HttpSchemeToCustomUnregisteredScheme, mode,    \
+                          HTTP_SCHEME, CUSTOM_UNREGISTERED_SCHEME)             \
+  CORS_TEST_REDIRECT_POST(name##CustomStandardSchemeToServer, mode,            \
+                          CUSTOM_STANDARD_SCHEME, SERVER)                      \
+  CORS_TEST_REDIRECT_POST(name##CustomStandardSchemeToHttpScheme, mode,        \
+                          CUSTOM_STANDARD_SCHEME, HTTP_SCHEME)                 \
+  CORS_TEST_REDIRECT_POST(name##CustomStandardSchemeToCustomStandardScheme,    \
+                          mode, CUSTOM_STANDARD_SCHEME,                        \
+                          CUSTOM_STANDARD_SCHEME)                              \
+  CORS_TEST_REDIRECT_POST(name##CustomStandardSchemeToCustomNonStandardScheme, \
+                          mode, CUSTOM_STANDARD_SCHEME,                        \
+                          CUSTOM_NONSTANDARD_SCHEME)                           \
+  CORS_TEST_REDIRECT_POST(                                                     \
+      name##CustomStandardSchemeToCustomUnregisteredScheme, mode,              \
+      CUSTOM_STANDARD_SCHEME, CUSTOM_UNREGISTERED_SCHEME)                      \
+  CORS_TEST_REDIRECT_POST(name##CustomNonStandardSchemeToServer, mode,         \
+                          CUSTOM_NONSTANDARD_SCHEME, SERVER)                   \
+  CORS_TEST_REDIRECT_POST(name##CustomNonStandardSchemeToHttpScheme, mode,     \
+                          CUSTOM_NONSTANDARD_SCHEME, HTTP_SCHEME)              \
+  CORS_TEST_REDIRECT_POST(name##CustomNonStandardSchemeToCustomStandardScheme, \
+                          mode, CUSTOM_NONSTANDARD_SCHEME,                     \
+                          CUSTOM_STANDARD_SCHEME)                              \
+  CORS_TEST_REDIRECT_POST(                                                     \
+      name##CustomNonStandardSchemeToCustomNonStandardScheme, mode,            \
+      CUSTOM_NONSTANDARD_SCHEME, CUSTOM_NONSTANDARD_SCHEME)                    \
+  CORS_TEST_REDIRECT_POST(                                                     \
+      name##CustomNonStandardSchemeToCustomUnregisteredScheme, mode,           \
+      CUSTOM_NONSTANDARD_SCHEME, CUSTOM_UNREGISTERED_SCHEME)                   \
+  CORS_TEST_REDIRECT_POST(name##CustomUnregisteredSchemeToServer, mode,        \
+                          CUSTOM_UNREGISTERED_SCHEME, SERVER)                  \
+  CORS_TEST_REDIRECT_POST(name##CustomUnregisteredSchemeToHttpScheme, mode,    \
+                          CUSTOM_UNREGISTERED_SCHEME, HTTP_SCHEME)             \
+  CORS_TEST_REDIRECT_POST(                                                     \
+      name##CustomUnregisteredSchemeToCustomStandardScheme, mode,              \
+      CUSTOM_UNREGISTERED_SCHEME, CUSTOM_STANDARD_SCHEME)                      \
+  CORS_TEST_REDIRECT_POST(                                                     \
+      name##CustomUnregisteredSchemeToCustomNonStandardScheme, mode,           \
+      CUSTOM_UNREGISTERED_SCHEME, CUSTOM_NONSTANDARD_SCHEME)                   \
+  CORS_TEST_REDIRECT_POST(                                                     \
+      name##CustomUnregisteredSchemeToCustomUnregisteredScheme, mode,          \
+      CUSTOM_UNREGISTERED_SCHEME, CUSTOM_UNREGISTERED_SCHEME)
+
+// Redirect GET requests.
+CORS_TEST_REDIRECT_POST_ALL(302, MODE_302)
+CORS_TEST_REDIRECT_POST_ALL(307, MODE_307)
+
+// Entry point for creating CORS browser test objects.
+// Called from client_app_delegates.cc.
+void CreateCorsBrowserTests(client::ClientAppBrowser::DelegateSet& delegates) {
+  delegates.insert(new CorsBrowserTest);
+}
diff --git a/src/tests/ceftests/devtools_message_unittest.cc b/src/tests/ceftests/devtools_message_unittest.cc
index 13f070e..c695ae1 100644
--- a/src/tests/ceftests/devtools_message_unittest.cc
+++ b/src/tests/ceftests/devtools_message_unittest.cc
@@ -5,7 +5,8 @@
 #include <algorithm>
 #include <sstream>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
+#include "include/base/cef_callback_helpers.h"
 #include "include/cef_callback.h"
 #include "include/cef_devtools_message_observer.h"
 #include "include/cef_parser.h"
@@ -16,8 +17,8 @@
 
 namespace {
 
-const char kTestUrl1[] = "http://tests/DevToolsMessage1";
-const char kTestUrl2[] = "http://tests/DevToolsMessage2";
+const char kTestUrl1[] = "https://tests/DevToolsMessage1";
+const char kTestUrl2[] = "https://tests/DevToolsMessage2";
 
 class DevToolsMessageTestHandler : public TestHandler {
  public:
@@ -53,8 +54,9 @@
       if (load_ct_ == 1) {
         // STEP 2: 1st load has completed. Now enable page domain notifications
         // and wait for the method result.
-        ExecuteMethod("Page.enable", "",
-                      base::Bind(&DevToolsMessageTestHandler::Navigate, this));
+        ExecuteMethod(
+            "Page.enable", "",
+            base::BindOnce(&DevToolsMessageTestHandler::Navigate, this));
       } else if (load_ct_ == 2) {
         MaybeDestroyTest();
       }
@@ -184,7 +186,7 @@
   // |expected_result| can be a fragment that the result should start with.
   void ExecuteMethod(const std::string& method,
                      const std::string& params,
-                     const base::Closure& next_step,
+                     base::OnceClosure next_step,
                      const std::string& expected_result = "{}",
                      bool expected_success = true) {
     CHECK(!method.empty());
@@ -201,7 +203,7 @@
 
     // Set expected result state.
     pending_message_ = message.str();
-    pending_result_next_ = next_step;
+    pending_result_next_ = std::move(next_step);
     pending_result_ = {message_id, expected_success, expected_result};
 
     if (message_id % 2 == 0) {
@@ -231,8 +233,9 @@
   void OnMethodResult(const MethodResult& result) {
     EXPECT_EQ(pending_result_.message_id, result.message_id)
         << "with message=" << pending_message_;
-    if (result.message_id != pending_result_.message_id)
+    if (result.message_id != pending_result_.message_id) {
       return;
+    }
 
     EXPECT_EQ(pending_result_.success, result.success)
         << "with message=" << pending_message_;
@@ -245,17 +248,17 @@
     last_result_id_ = result.message_id;
 
     // Continue asynchronously to allow the callstack to unwind.
-    CefPostTask(TID_UI, pending_result_next_);
+    CefPostTask(TID_UI, std::move(pending_result_next_));
 
     // Clear expected result state.
     pending_message_.clear();
-    pending_result_next_.Reset();
     pending_result_ = {};
   }
 
   void OnEvent(const Event& event) {
-    if (event.method != pending_event_.method)
+    if (event.method != pending_event_.method) {
       return;
+    }
 
     EXPECT_TRUE(event.params.find(pending_event_.params) == 0)
         << "with method=" << event.method
@@ -263,17 +266,16 @@
         << "\nand expected params=" << pending_event_.params;
 
     // Continue asynchronously to allow the callstack to unwind.
-    CefPostTask(TID_UI, pending_event_next_);
+    CefPostTask(TID_UI, std::move(pending_event_next_));
 
     // Clear expected result state.
     pending_event_ = {};
-    pending_event_next_.Reset();
   }
 
   void Navigate() {
     pending_event_ = {"Page.frameNavigated", "{\"frame\":"};
     pending_event_next_ =
-        base::Bind(&DevToolsMessageTestHandler::AfterNavigate, this);
+        base::BindOnce(&DevToolsMessageTestHandler::AfterNavigate, this);
 
     std::stringstream params;
     params << "{\"url\":\"" << kTestUrl2 << "\"}";
@@ -281,7 +283,7 @@
     // STEP 3: Page domain notifications are enabled. Now start a new
     // navigation (but do nothing on method result) and wait for the
     // "Page.frameNavigated" event.
-    ExecuteMethod("Page.navigate", params.str(), base::Bind(base::DoNothing),
+    ExecuteMethod("Page.navigate", params.str(), base::DoNothing(),
                   /*expected_result=*/"{\"frameId\":");
   }
 
@@ -290,7 +292,7 @@
     // notifications.
     ExecuteMethod(
         "Page.disable", "",
-        base::Bind(&DevToolsMessageTestHandler::AfterPageDisabled, this));
+        base::BindOnce(&DevToolsMessageTestHandler::AfterPageDisabled, this));
   }
 
   void AfterPageDisabled() {
@@ -298,7 +300,7 @@
     // method to verify an error result, and then destroy the test when done.
     ExecuteMethod(
         "Foo.doesNotExist", "",
-        base::Bind(&DevToolsMessageTestHandler::MaybeDestroyTest, this),
+        base::BindOnce(&DevToolsMessageTestHandler::MaybeDestroyTest, this),
         /*expected_result=*/
         "{\"code\":-32601,\"message\":\"'Foo.doesNotExist' wasn't found\"}",
         /*expected_success=*/false);
@@ -335,13 +337,13 @@
   //   Tracks the last message ID received.
   int last_result_id_ = -1;
   //   When received, execute this callback.
-  base::Closure pending_result_next_;
+  base::OnceClosure pending_result_next_;
 
   // Wait for |pending_event_.method| in OnEvent.
   // The params should start with the |pending_event_.params| fragment.
   Event pending_event_;
   //   When received, execute this callback.
-  base::Closure pending_event_next_;
+  base::OnceClosure pending_event_next_;
 
   CefRefPtr<CefRegistration> registration_;
 
diff --git a/src/tests/ceftests/dialog_unittest.cc b/src/tests/ceftests/dialog_unittest.cc
index 800dc1c..3ee680c 100644
--- a/src/tests/ceftests/dialog_unittest.cc
+++ b/src/tests/ceftests/dialog_unittest.cc
@@ -2,7 +2,7 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "tests/ceftests/test_handler.h"
 #include "tests/ceftests/test_util.h"
@@ -10,7 +10,7 @@
 
 namespace {
 
-const char* kTestUrl = "http://tests/DialogTestHandler";
+const char* kTestUrl = "https://tests/DialogTestHandler";
 
 class DialogTestHandler : public TestHandler {
  public:
@@ -19,7 +19,6 @@
         : mode(dialog_mode),
           title("Test Title"),
           default_file_name("Test File Name"),
-          selected_accept_filter(1),  // Something other than 0 for testing.
           callback_async(false),
           callback_cancel(false) {
       accept_types.push_back("text/*");
@@ -31,7 +30,6 @@
     CefString title;
     CefString default_file_name;
     std::vector<CefString> accept_types;
-    int selected_accept_filter;
 
     bool callback_async;  // True if the callback should execute asynchronously.
     bool callback_cancel;  // True if the callback should cancel.
@@ -43,16 +41,12 @@
     explicit Callback(DialogTestHandler* handler) : handler_(handler) {}
 
     void OnFileDialogDismissed(
-        int selected_accept_filter,
         const std::vector<CefString>& file_paths) override {
       handler_->got_onfiledialogdismissed_.yes();
 
       if (handler_->config_.callback_cancel) {
-        EXPECT_EQ(0, selected_accept_filter);
         EXPECT_TRUE(file_paths.empty());
       } else {
-        EXPECT_EQ(handler_->config_.selected_accept_filter,
-                  selected_accept_filter);
         TestStringVectorEqual(handler_->config_.callback_paths, file_paths);
       }
 
@@ -81,18 +75,17 @@
   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
                  CefRefPtr<CefFrame> frame,
                  int httpStatusCode) override {
-    browser->GetHost()->RunFileDialog(
-        config_.mode, config_.title, config_.default_file_name,
-        config_.accept_types, config_.selected_accept_filter,
-        new Callback(this));
+    browser->GetHost()->RunFileDialog(config_.mode, config_.title,
+                                      config_.default_file_name,
+                                      config_.accept_types, new Callback(this));
   }
 
   void ExecuteCallback(CefRefPtr<CefFileDialogCallback> callback) {
-    if (config_.callback_cancel)
+    if (config_.callback_cancel) {
       callback->Cancel();
-    else
-      callback->Continue(config_.selected_accept_filter,
-                         config_.callback_paths);
+    } else {
+      callback->Continue(config_.callback_paths);
+    }
   }
 
   // CefDialogHandler
@@ -101,7 +94,6 @@
                     const CefString& title,
                     const CefString& default_file_name,
                     const std::vector<CefString>& accept_types,
-                    int selected_accept_filter,
                     CefRefPtr<CefFileDialogCallback> callback) override {
     got_onfiledialog_.yes();
 
@@ -115,8 +107,8 @@
     TestStringVectorEqual(config_.accept_types, accept_types);
 
     if (config_.callback_async) {
-      CefPostTask(TID_UI, base::Bind(&DialogTestHandler::ExecuteCallback, this,
-                                     callback));
+      CefPostTask(TID_UI, base::BindOnce(&DialogTestHandler::ExecuteCallback,
+                                         this, callback));
     } else {
       ExecuteCallback(callback);
     }
@@ -155,21 +147,6 @@
   ReleaseAndWaitForDestructor(handler);
 }
 
-TEST(DialogTest, FileAdditionalFlags) {
-  DialogTestHandler::TestConfig config(static_cast<cef_file_dialog_mode_t>(
-      FILE_DIALOG_OPEN | FILE_DIALOG_HIDEREADONLY_FLAG |
-      FILE_DIALOG_OVERWRITEPROMPT_FLAG));
-  config.title.clear();
-  config.default_file_name.clear();
-  config.accept_types.clear();
-  config.callback_async = false;
-  config.callback_cancel = false;
-
-  CefRefPtr<DialogTestHandler> handler = new DialogTestHandler(config);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
 TEST(DialogTest, FileOpen) {
   DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN);
   config.callback_async = false;
diff --git a/src/tests/ceftests/display_unittest.cc b/src/tests/ceftests/display_unittest.cc
index 06ba211..e867d3c 100644
--- a/src/tests/ceftests/display_unittest.cc
+++ b/src/tests/ceftests/display_unittest.cc
@@ -4,7 +4,7 @@
 
 #include <list>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "tests/ceftests/routing_test_handler.h"
 #include "tests/ceftests/test_handler.h"
@@ -19,8 +19,8 @@
 // 4. History forward to kTitleUrl2 (title should be kTitleStr2)
 // 5. Set title via JavaScript (title should be kTitleStr3)
 
-const char kTitleUrl1[] = "http://tests-title/nav1.html";
-const char kTitleUrl2[] = "http://tests-title/nav2.html";
+const char kTitleUrl1[] = "https://tests-title/nav1.html";
+const char kTitleUrl2[] = "https://tests-title/nav2.html";
 const char kTitleStr1[] = "Title 1";
 const char kTitleStr2[] = "Title 2";
 const char kTitleStr3[] = "Title 3";
@@ -55,8 +55,9 @@
                      const CefString& title) override {
     // Ignore the 2nd OnTitleChange call which arrives after navigation
     // completion.
-    if (got_title_change_)
+    if (got_title_change_) {
       return;
+    }
 
     std::string title_str = title;
     if (step_ == 0 || step_ == 2) {
@@ -81,8 +82,9 @@
                             bool isLoading,
                             bool canGoBack,
                             bool canGoForward) override {
-    if (isLoading)
+    if (isLoading) {
       return;
+    }
 
     // Call NextIfReady asynchronously because an additional call to
     // OnTitleChange will be triggered later in the current call stack due to
@@ -90,13 +92,14 @@
     // NextIfReady.
     got_loading_state_change_ = true;
     CefPostTask(TID_UI,
-                base::Bind(&TitleTestHandler::NextIfReady, this, browser));
+                base::BindOnce(&TitleTestHandler::NextIfReady, this, browser));
   }
 
  private:
   void NextIfReady(CefRefPtr<CefBrowser> browser) {
-    if (!got_title_change_ || !got_loading_state_change_)
+    if (!got_title_change_ || !got_loading_state_change_) {
       return;
+    }
 
     got_title_change_ = false;
     got_loading_state_change_ = false;
@@ -120,8 +123,9 @@
   }
 
   void DestroyTest() override {
-    for (int i = 0; i < 5; ++i)
+    for (int i = 0; i < 5; ++i) {
       EXPECT_TRUE(got_title_[i]) << "step " << i;
+    }
 
     TestHandler::DestroyTest();
   }
@@ -147,7 +151,7 @@
 
 namespace {
 
-const char kAutoResizeUrl[] = "http://tests-display/auto-resize.html";
+const char kAutoResizeUrl[] = "https://tests-display/auto-resize.html";
 
 class AutoResizeTestHandler : public RoutingTestHandler {
  public:
@@ -190,7 +194,7 @@
     } else if (!got_auto_resize2_) {
       got_auto_resize2_.yes();
       EXPECT_EQ(50, new_size.width);
-      EXPECT_EQ(36, new_size.height);
+      EXPECT_EQ(37, new_size.height);
 
       // Disable resize notifications.
       browser->GetHost()->SetAutoResizeEnabled(false, CefSize(), CefSize());
@@ -210,7 +214,7 @@
 
   bool OnQuery(CefRefPtr<CefBrowser> browser,
                CefRefPtr<CefFrame> frame,
-               int64 query_id,
+               int64_t query_id,
                const CefString& request,
                bool persistent,
                CefRefPtr<Callback> callback) override {
@@ -256,7 +260,7 @@
         : level(message_level),
           message("'Test Message'"),
           expected_message("Test Message"),
-          source("http://tests-console-message/level.html"),
+          source("https://tests-console-message/level.html"),
           line(42) {}
 
     cef_log_severity_t level;
@@ -287,8 +291,9 @@
                             bool isLoading,
                             bool canGoBack,
                             bool canGoForward) override {
-    if (isLoading)
+    if (isLoading) {
       return;
+    }
 
     // Print console message after loading.
     browser->GetMainFrame()->ExecuteJavaScript("printMessage()", config_.source,
@@ -459,7 +464,7 @@
 
 namespace {
 
-const char kLoadinProgressUrl[] = "http://tests-display/loading-progress.html";
+const char kLoadinProgressUrl[] = "https://tests-display/loading-progress.html";
 
 // Browser side.
 class LoadingProgressTestHandler : public TestHandler {
@@ -485,8 +490,9 @@
                             bool isLoading,
                             bool canGoBack,
                             bool canGoForward) override {
-    if (isLoading)
+    if (isLoading) {
       return;
+    }
 
     DestroyTest();
   }
diff --git a/src/tests/ceftests/dom_unittest.cc b/src/tests/ceftests/dom_unittest.cc
index 1b26252..a831b4b 100644
--- a/src/tests/ceftests/dom_unittest.cc
+++ b/src/tests/ceftests/dom_unittest.cc
@@ -11,7 +11,7 @@
 
 namespace {
 
-const char* kTestUrl = "http://tests/DOMTest.Test";
+const char* kTestUrl = "https://tests/DOMTest.Test";
 const char* kTestMessage = "DOMTest.Message";
 
 enum DOMTestType {
@@ -59,7 +59,8 @@
     EXPECT_FALSE(textNode->HasChildren());
   }
 
-  void TestBodyNodeStructure(CefRefPtr<CefDOMNode> bodyNode) {
+  void TestBodyNodeStructure(CefRefPtr<CefDOMNode> bodyNode,
+                             float devicePixelRatio) {
     EXPECT_TRUE(bodyNode.get());
     EXPECT_TRUE(bodyNode->IsElement());
     EXPECT_FALSE(bodyNode->IsText());
@@ -133,11 +134,14 @@
     EXPECT_TRUE(divNode.get());
     EXPECT_TRUE(divNode->IsElement());
     EXPECT_FALSE(divNode->IsText());
+
+    // Returned bounds are in device pixels.
     CefRect divRect = divNode->GetElementBounds();
-    EXPECT_EQ(divRect.width, 50);
-    EXPECT_EQ(divRect.height, 25);
-    EXPECT_EQ(divRect.x, 150);
-    EXPECT_EQ(divRect.y, 100);
+    EXPECT_NEAR(divRect.width, 50.0 * devicePixelRatio, 1);
+    EXPECT_NEAR(divRect.height, 25.0 * devicePixelRatio, 1);
+    EXPECT_NEAR(divRect.x, 150.0 * devicePixelRatio, 1);
+    EXPECT_NEAR(divRect.y, 100.0 * devicePixelRatio, 1);
+
     EXPECT_FALSE(divNode->GetNextSibling().get());
   }
 
@@ -145,7 +149,7 @@
   void TestStructure(CefRefPtr<CefDOMDocument> document) {
     EXPECT_EQ(document->GetTitle(), "The Title");
     EXPECT_EQ(document->GetBaseURL(), kTestUrl);
-    EXPECT_EQ(document->GetCompleteURL("foo.html"), "http://tests/foo.html");
+    EXPECT_EQ(document->GetCompleteURL("foo.html"), "https://tests/foo.html");
 
     // Navigate the complete document structure.
     CefRefPtr<CefDOMNode> docNode = document->GetDocument();
@@ -166,8 +170,10 @@
     CefRefPtr<CefDOMNode> headNode = htmlNode->GetFirstChild();
     TestHeadNodeStructure(headNode);
 
+    const float devicePixelRatio = GetDevicePixelRatio();
+
     CefRefPtr<CefDOMNode> bodyNode = headNode->GetNextSibling();
-    TestBodyNodeStructure(bodyNode);
+    TestBodyNodeStructure(bodyNode, devicePixelRatio);
 
     // Retrieve the head node directly.
     headNode = document->GetHead();
@@ -175,7 +181,7 @@
 
     // Retrieve the body node directly.
     bodyNode = document->GetBody();
-    TestBodyNodeStructure(bodyNode);
+    TestBodyNodeStructure(bodyNode, devicePixelRatio);
   }
 
   // Test document modification by changing the H1 tag.
@@ -205,10 +211,11 @@
   }
 
   void Visit(CefRefPtr<CefDOMDocument> document) override {
-    if (test_type_ == DOM_TEST_STRUCTURE)
+    if (test_type_ == DOM_TEST_STRUCTURE) {
       TestStructure(document);
-    else if (test_type_ == DOM_TEST_MODIFY)
+    } else if (test_type_ == DOM_TEST_MODIFY) {
       TestModify(document);
+    }
 
     DestroyTest();
   }
@@ -226,6 +233,28 @@
     browser_->GetMainFrame()->SendProcessMessage(PID_BROWSER, return_msg);
   }
 
+  // Used to convert between device pixels and CSS pixels.
+  float GetDevicePixelRatio() {
+    auto context = browser_->GetMainFrame()->GetV8Context();
+    EXPECT_TRUE(context);
+
+    CefRefPtr<CefV8Value> retval;
+    CefRefPtr<CefV8Exception> exception;
+    EXPECT_TRUE(context->Eval("window.devicePixelRatio", CefString(), 0, retval,
+                              exception));
+    if (exception) {
+      ADD_FAILURE() << exception->GetMessage().c_str();
+      return 1.0;
+    }
+
+    if (retval->IsValid() && retval->IsDouble()) {
+      return static_cast<float>(retval->GetDoubleValue());
+    }
+
+    ADD_FAILURE() << "Failed to retrieve devicePixelRatio";
+    return 1.0;
+  }
+
   CefRefPtr<CefBrowser> browser_;
   DOMTestType test_type_;
 
@@ -263,6 +292,7 @@
   explicit TestDOMHandler(DOMTestType test) : test_type_(test) {}
 
   void RunTest() override {
+    // Specified values are in CSS pixels.
     std::stringstream mainHtml;
     mainHtml << "<html>"
                 "<head><title>The Title</title></head>"
@@ -301,8 +331,9 @@
 
     got_message_.yes();
 
-    if (message->GetArgumentList()->GetBool(0))
+    if (message->GetArgumentList()->GetBool(0)) {
       got_success_.yes();
+    }
 
     // Test is complete.
     DestroyTest();
diff --git a/src/tests/ceftests/download_unittest.cc b/src/tests/ceftests/download_unittest.cc
index 6408f6f..768906e 100644
--- a/src/tests/ceftests/download_unittest.cc
+++ b/src/tests/ceftests/download_unittest.cc
@@ -2,6 +2,11 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
+#include <algorithm>
+#include <memory>
+
+#include "include/base/cef_callback.h"
+#include "include/base/cef_callback_helpers.h"
 #include "include/cef_scheme.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "include/wrapper/cef_scoped_temp_dir.h"
@@ -13,22 +18,22 @@
 namespace {
 
 const char kTestDomain[] = "test-download.com";
-const char kTestStartUrl[] = "http://test-download.com/test.html";
-const char kTestDownloadUrl[] = "http://test-download.com/download.txt";
-const char kTestNavUrl[] = "http://test-download-nav.com/nav.html";
+const char kTestStartUrl[] = "https://test-download.com/test.html";
+const char kTestDownloadUrl[] = "https://test-download.com/download.txt";
+const char kTestNavUrl[] = "https://test-download-nav.com/nav.html";
 const char kTestFileName[] = "download_test.txt";
 const char kTestContentDisposition[] =
     "attachment; filename=\"download_test.txt\"";
 const char kTestMimeType[] = "text/plain";
 const char kTestContent[] = "Download test text";
 
-typedef base::Callback<void(const base::Closure& /*callback*/)> DelayCallback;
+using DelayCallback = base::OnceCallback<void(base::OnceClosure /*callback*/)>;
 
 class DownloadSchemeHandler : public CefResourceHandler {
  public:
-  DownloadSchemeHandler(const DelayCallback& delay_callback,
+  DownloadSchemeHandler(DelayCallback delay_callback,
                         TrackCallback* got_download_request)
-      : delay_callback_(delay_callback),
+      : delay_callback_(std::move(delay_callback)),
         got_download_request_(got_download_request),
         should_delay_(false),
         offset_(0) {}
@@ -59,7 +64,7 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
     response_length = content_.size();
 
@@ -85,9 +90,9 @@
 
     if (should_delay_ && !delay_callback_.is_null()) {
       // Delay the download response a single time.
-      delay_callback_.Run(base::Bind(&DownloadSchemeHandler::ContinueRead, this,
-                                     data_out, bytes_to_read, callback));
-      delay_callback_.Reset();
+      std::move(delay_callback_)
+          .Run(base::BindOnce(&DownloadSchemeHandler::ContinueRead, this,
+                              data_out, bytes_to_read, callback));
       return true;
     }
 
@@ -134,22 +139,27 @@
   DISALLOW_COPY_AND_ASSIGN(DownloadSchemeHandler);
 };
 
+using DelayCallbackVendor = base::RepeatingCallback<DelayCallback(void)>;
+
 class DownloadSchemeHandlerFactory : public CefSchemeHandlerFactory {
  public:
-  DownloadSchemeHandlerFactory(const DelayCallback& delay_callback,
+  DownloadSchemeHandlerFactory(const DelayCallbackVendor& delay_callback_vendor,
                                TrackCallback* got_download_request)
-      : delay_callback_(delay_callback),
+      : delay_callback_vendor_(delay_callback_vendor),
         got_download_request_(got_download_request) {}
 
   CefRefPtr<CefResourceHandler> Create(CefRefPtr<CefBrowser> browser,
                                        CefRefPtr<CefFrame> frame,
                                        const CefString& scheme_name,
                                        CefRefPtr<CefRequest> request) override {
-    return new DownloadSchemeHandler(delay_callback_, got_download_request_);
+    return new DownloadSchemeHandler(delay_callback_vendor_.is_null()
+                                         ? base::NullCallback()
+                                         : delay_callback_vendor_.Run(),
+                                     got_download_request_);
   }
 
  private:
-  DelayCallback delay_callback_;
+  DelayCallbackVendor delay_callback_vendor_;
   TrackCallback* got_download_request_;
 
   IMPLEMENT_REFCOUNTING(DownloadSchemeHandlerFactory);
@@ -159,11 +169,12 @@
 class DownloadTestHandler : public TestHandler {
  public:
   enum TestMode {
-    PROGAMMATIC,
+    PROGRAMMATIC,
     NAVIGATED,
     PENDING,
     CLICKED,
-    CLICKED_REJECTED,
+    CLICKED_INVALID,
+    CLICKED_BLOCKED,
   };
 
   DownloadTestHandler(TestMode test_mode,
@@ -176,34 +187,56 @@
         verified_results_(false) {}
 
   bool is_clicked() const {
-    return test_mode_ == CLICKED || test_mode_ == CLICKED_REJECTED;
+    return test_mode_ == CLICKED || test_mode_ == CLICKED_INVALID ||
+           test_mode_ == CLICKED_BLOCKED;
+  }
+
+  bool is_clicked_and_downloaded() const { return test_mode_ == CLICKED; }
+
+  bool is_downloaded() const {
+    return test_mode_ == PROGRAMMATIC || test_mode_ == NAVIGATED ||
+           is_clicked_and_downloaded();
   }
 
   void RunTest() override {
-    DelayCallback delay_callback;
-    if (test_mode_ == NAVIGATED || test_mode_ == PENDING)
-      delay_callback = base::Bind(&DownloadTestHandler::OnDelayCallback, this);
-
-    CefRefPtr<CefSchemeHandlerFactory> scheme_factory =
-        new DownloadSchemeHandlerFactory(delay_callback,
-                                         &got_download_request_);
-
-    CefRefPtr<CefRequestContext> request_context =
-        CreateTestRequestContext(rc_mode_, rc_cache_path_);
-    if (request_context) {
-      request_context->RegisterSchemeHandlerFactory("http", kTestDomain,
-                                                    scheme_factory);
-    } else {
-      CefRegisterSchemeHandlerFactory("http", kTestDomain, scheme_factory);
-    }
-
-    if (test_mode_ != CLICKED_REJECTED) {
+    if (!is_clicked() || is_clicked_and_downloaded()) {
       // Create a new temporary directory.
       EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
       test_path_ =
           client::file_util::JoinPath(temp_dir_.GetPath(), kTestFileName);
     }
 
+    CreateTestRequestContext(
+        rc_mode_, rc_cache_path_,
+        base::BindOnce(&DownloadTestHandler::RunTestContinue, this));
+
+    // Time out the test after a reasonable period of time.
+    SetTestTimeout();
+  }
+
+  void RunTestContinue(CefRefPtr<CefRequestContext> request_context) {
+    EXPECT_UI_THREAD();
+
+    DelayCallbackVendor delay_callback_vendor;
+    if (test_mode_ == NAVIGATED || test_mode_ == PENDING) {
+      delay_callback_vendor = base::BindRepeating(
+          [](CefRefPtr<DownloadTestHandler> self) {
+            return base::BindOnce(&DownloadTestHandler::OnDelayCallback, self);
+          },
+          CefRefPtr<DownloadTestHandler>(this));
+    }
+
+    CefRefPtr<CefSchemeHandlerFactory> scheme_factory =
+        new DownloadSchemeHandlerFactory(delay_callback_vendor,
+                                         &got_download_request_);
+
+    if (request_context) {
+      request_context->RegisterSchemeHandlerFactory("https", kTestDomain,
+                                                    scheme_factory);
+    } else {
+      CefRegisterSchemeHandlerFactory("https", kTestDomain, scheme_factory);
+    }
+
     if (test_mode_ == NAVIGATED) {
       // Add the resource that we'll navigate to.
       AddResource(kTestNavUrl, "<html><body>Navigated</body></html>",
@@ -211,28 +244,25 @@
     }
 
     if (is_clicked()) {
-      std::string url;
-      if (test_mode_ == CLICKED) {
-        url = kTestDownloadUrl;
-      } else if (test_mode_ == CLICKED_REJECTED) {
-        url = "invalid:foo@example.com";
+      if (test_mode_ == CLICKED || test_mode_ == CLICKED_BLOCKED) {
+        download_url_ = kTestDownloadUrl;
+      } else if (test_mode_ == CLICKED_INVALID) {
+        download_url_ = "invalid:foo@example.com";
       } else {
         EXPECT_TRUE(false);  // Not reached.
       }
-      AddResource(
-          kTestStartUrl,
-          "<html><body><a href=\"" + url + "\">CLICK ME</a></body></html>",
-          "text/html");
+      AddResource(kTestStartUrl,
+                  "<html><body><a href=\"" + download_url_ +
+                      "\">CLICK ME</a></body></html>",
+                  "text/html");
     } else {
+      download_url_ = kTestStartUrl;
       AddResource(kTestStartUrl, "<html><body>Download Test</body></html>",
                   "text/html");
     }
 
     // Create the browser
     CreateBrowser(kTestStartUrl, request_context);
-
-    // Time out the test after a reasonable period of time.
-    SetTestTimeout();
   }
 
   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
@@ -249,14 +279,7 @@
       // Begin the download by clicking a link.
       // ALT key will trigger download of custom protocol links.
       SendClick(browser,
-                test_mode_ == CLICKED_REJECTED ? EVENTFLAG_ALT_DOWN : 0);
-
-      if (test_mode_ == CLICKED_REJECTED) {
-        // Destroy the test after a bit because there will be no further
-        // callbacks.
-        CefPostDelayedTask(
-            TID_UI, base::Bind(&DownloadTestHandler::DestroyTest, this), 200);
-      }
+                test_mode_ == CLICKED_INVALID ? EVENTFLAG_ALT_DOWN : 0);
     } else {
       // Begin the download progammatically.
       browser->GetHost()->StartDownload(kTestDownloadUrl);
@@ -264,17 +287,17 @@
   }
 
   // Callback from the scheme handler when the download request is delayed.
-  void OnDelayCallback(const base::Closure& callback) {
+  void OnDelayCallback(base::OnceClosure callback) {
     if (!CefCurrentlyOn(TID_UI)) {
-      CefPostTask(TID_UI, base::Bind(&DownloadTestHandler::OnDelayCallback,
-                                     this, callback));
+      CefPostTask(TID_UI, base::BindOnce(&DownloadTestHandler::OnDelayCallback,
+                                         this, std::move(callback)));
       return;
     }
 
     got_delay_callback_.yes();
 
     if (test_mode_ == NAVIGATED) {
-      delay_callback_ = callback;
+      delay_callback_ = std::move(callback);
       ContinueNavigatedIfReady();
     } else if (test_mode_ == PENDING) {
       ContinuePendingIfReady();
@@ -287,8 +310,7 @@
     EXPECT_EQ(test_mode_, NAVIGATED);
     if (got_delay_callback_ && got_nav_load_) {
       EXPECT_FALSE(delay_callback_.is_null());
-      delay_callback_.Run();
-      delay_callback_.Reset();
+      std::move(delay_callback_).Run();
     }
   }
 
@@ -301,6 +323,30 @@
     }
   }
 
+  bool CanDownload(CefRefPtr<CefBrowser> browser,
+                   const CefString& url,
+                   const CefString& request_method) override {
+    EXPECT_TRUE(CefCurrentlyOn(TID_UI));
+    EXPECT_FALSE(got_can_download_);
+    EXPECT_FALSE(got_on_before_download_);
+    EXPECT_TRUE(is_clicked());
+
+    got_can_download_.yes();
+
+    EXPECT_TRUE(browser->IsSame(GetBrowser()));
+    EXPECT_STREQ(download_url_.c_str(), url.ToString().c_str());
+    EXPECT_STREQ("GET", request_method.ToString().c_str());
+
+    if (is_clicked() && !is_clicked_and_downloaded()) {
+      // Destroy the test after a bit because there will be no further
+      // callbacks.
+      CefPostDelayedTask(
+          TID_UI, base::BindOnce(&DownloadTestHandler::DestroyTest, this), 200);
+    }
+
+    return test_mode_ != CLICKED_BLOCKED;
+  }
+
   void OnBeforeDownload(
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefDownloadItem> download_item,
@@ -309,6 +355,12 @@
     EXPECT_TRUE(CefCurrentlyOn(TID_UI));
     EXPECT_FALSE(got_on_before_download_);
 
+    if (is_clicked()) {
+      EXPECT_TRUE(got_can_download_);
+    } else {
+      EXPECT_FALSE(got_can_download_);
+    }
+
     got_on_before_download_.yes();
 
     EXPECT_TRUE(browser->IsSame(GetBrowser()));
@@ -323,7 +375,10 @@
     EXPECT_TRUE(download_item->IsInProgress());
     EXPECT_FALSE(download_item->IsComplete());
     EXPECT_FALSE(download_item->IsCanceled());
-    EXPECT_EQ(static_cast<int64>(sizeof(kTestContent) - 1),
+    EXPECT_FALSE(download_item->IsInterrupted());
+    EXPECT_EQ(CEF_DOWNLOAD_INTERRUPT_REASON_NONE,
+              download_item->GetInterruptReason());
+    EXPECT_EQ(static_cast<int64_t>(sizeof(kTestContent) - 1),
               download_item->GetTotalBytes());
     EXPECT_EQ(0UL, download_item->GetFullPath().length());
     EXPECT_STREQ(kTestDownloadUrl, download_item->GetURL().ToString().c_str());
@@ -349,8 +404,9 @@
                          CefRefPtr<CefDownloadItemCallback> callback) override {
     EXPECT_TRUE(CefCurrentlyOn(TID_UI));
 
-    if (destroyed_)
+    if (destroyed_) {
       return;
+    }
 
     got_on_download_updated_.yes();
 
@@ -367,6 +423,9 @@
 
     EXPECT_TRUE(download_item->IsValid());
     EXPECT_FALSE(download_item->IsCanceled());
+    EXPECT_FALSE(download_item->IsInterrupted());
+    EXPECT_EQ(CEF_DOWNLOAD_INTERRUPT_REASON_NONE,
+              download_item->GetInterruptReason());
     EXPECT_STREQ(kTestDownloadUrl, download_item->GetURL().ToString().c_str());
     EXPECT_STREQ(kTestContentDisposition,
                  download_item->GetContentDisposition().ToString().c_str());
@@ -384,9 +443,9 @@
 
       EXPECT_FALSE(download_item->IsInProgress());
       EXPECT_EQ(100, download_item->GetPercentComplete());
-      EXPECT_EQ(static_cast<int64>(sizeof(kTestContent) - 1),
+      EXPECT_EQ(static_cast<int64_t>(sizeof(kTestContent) - 1),
                 download_item->GetReceivedBytes());
-      EXPECT_EQ(static_cast<int64>(sizeof(kTestContent) - 1),
+      EXPECT_EQ(static_cast<int64_t>(sizeof(kTestContent) - 1),
                 download_item->GetTotalBytes());
 
       DestroyTest();
@@ -402,7 +461,7 @@
   }
 
   void VerifyResultsOnFileThread() {
-    EXPECT_TRUE(CefCurrentlyOn(TID_FILE));
+    EXPECT_TRUE(CefCurrentlyOn(TID_FILE_USER_VISIBLE));
 
     if (test_mode_ != PENDING) {
       // Verify the file contents.
@@ -414,7 +473,8 @@
     EXPECT_TRUE(temp_dir_.Delete());
     EXPECT_TRUE(temp_dir_.IsEmpty());
 
-    CefPostTask(TID_UI, base::Bind(&DownloadTestHandler::DestroyTest, this));
+    CefPostTask(TID_UI,
+                base::BindOnce(&DownloadTestHandler::DestroyTest, this));
   }
 
   void DestroyTest() override {
@@ -422,9 +482,9 @@
       // Avoid an endless failure loop.
       verified_results_ = true;
       // Clean up temp_dir_ on the FILE thread before destroying the test.
-      CefPostTask(
-          TID_FILE,
-          base::Bind(&DownloadTestHandler::VerifyResultsOnFileThread, this));
+      CefPostTask(TID_FILE_USER_VISIBLE,
+                  base::BindOnce(
+                      &DownloadTestHandler::VerifyResultsOnFileThread, this));
       return;
     }
 
@@ -437,29 +497,43 @@
     }
 
     if (request_context_) {
-      request_context_->RegisterSchemeHandlerFactory("http", kTestDomain,
+      request_context_->RegisterSchemeHandlerFactory("https", kTestDomain,
                                                      nullptr);
       request_context_ = nullptr;
     } else {
-      CefRegisterSchemeHandlerFactory("http", kTestDomain, nullptr);
+      CefRegisterSchemeHandlerFactory("https", kTestDomain, nullptr);
     }
 
-    if (test_mode_ == CLICKED_REJECTED) {
+    if (is_clicked()) {
+      EXPECT_TRUE(got_can_download_);
+    } else {
+      EXPECT_FALSE(got_can_download_);
+    }
+
+    if (test_mode_ == CLICKED_INVALID) {
+      // The invalid protocol request is not handled.
       EXPECT_FALSE(got_download_request_);
+    } else {
+      EXPECT_TRUE(got_download_request_);
+    }
+
+    if (is_clicked() && !is_clicked_and_downloaded()) {
+      // The download never proceeds.
       EXPECT_FALSE(got_on_before_download_);
       EXPECT_FALSE(got_on_download_updated_);
     } else {
-      EXPECT_TRUE(got_download_request_);
       EXPECT_TRUE(got_on_before_download_);
       EXPECT_TRUE(got_on_download_updated_);
     }
 
-    if (test_mode_ == NAVIGATED)
+    if (test_mode_ == NAVIGATED) {
       EXPECT_TRUE(got_nav_load_);
-    else
+    } else {
       EXPECT_FALSE(got_nav_load_);
+    }
 
-    if (test_mode_ == PENDING || test_mode_ == CLICKED_REJECTED) {
+    if (!is_downloaded()) {
+      // The download never completes.
       EXPECT_FALSE(got_download_complete_);
       EXPECT_FALSE(got_full_path_);
     } else {
@@ -477,8 +551,7 @@
     mouse_event.x = 20;
     mouse_event.y = 20;
     mouse_event.modifiers = modifiers;
-    browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1);
-    browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true, 1);
+    SendMouseClickEvent(browser, mouse_event);
   }
 
   const TestMode test_mode_;
@@ -488,18 +561,20 @@
   CefRefPtr<CefRequestContext> request_context_;
 
   // Used with NAVIGATED and PENDING test modes.
-  base::Closure delay_callback_;
+  base::OnceClosure delay_callback_;
 
   // Used with PENDING test mode.
   CefRefPtr<CefDownloadItemCallback> download_item_callback_;
 
+  std::string download_url_;
   CefScopedTempDir temp_dir_;
   std::string test_path_;
-  uint32 download_id_;
+  uint32_t download_id_;
   bool verified_results_;
   bool destroyed_ = false;
 
   TrackCallback got_download_request_;
+  TrackCallback got_can_download_;
   TrackCallback got_on_before_download_;
   TrackCallback got_on_download_updated_;
   TrackCallback got_full_path_;
@@ -516,14 +591,18 @@
   RC_TEST_GROUP_ALL(DownloadTest, test_name, DownloadTestHandler, test_mode)
 
 // Test a programmatic download.
-DOWNLOAD_TEST_GROUP(Programmatic, PROGAMMATIC)
+DOWNLOAD_TEST_GROUP(Programmatic, PROGRAMMATIC)
 
 // Test a clicked download.
 DOWNLOAD_TEST_GROUP(Clicked, CLICKED)
 
 // Test a clicked download where the protocol is invalid and therefore rejected.
 // There will be no resulting CefDownloadHandler callbacks.
-DOWNLOAD_TEST_GROUP(ClickedRejected, CLICKED_REJECTED)
+DOWNLOAD_TEST_GROUP(ClickedInvalid, CLICKED_INVALID)
+
+// Test a clicked download where CanDownload returns false.
+// There will be no resulting CefDownloadHandler callbacks.
+DOWNLOAD_TEST_GROUP(ClickedBlocked, CLICKED_BLOCKED)
 
 // Test where the download completes after cross-origin navigation.
 DOWNLOAD_TEST_GROUP(Navigated, NAVIGATED)
diff --git a/src/tests/ceftests/draggable_regions_unittest.cc b/src/tests/ceftests/draggable_regions_unittest.cc
index fea4fc0..46704c1 100644
--- a/src/tests/ceftests/draggable_regions_unittest.cc
+++ b/src/tests/ceftests/draggable_regions_unittest.cc
@@ -2,13 +2,16 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
+#include "include/base/cef_callback.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "tests/ceftests/test_handler.h"
 #include "tests/gtest/include/gtest/gtest.h"
 
+// Set to 1 to enable verbose debugging info logging.
+#define VERBOSE_DEBUGGING 0
+
 namespace {
 
-const char kTestURLWithRegions[] = "http://test.com/regions";
 const char kTestHTMLWithRegions[] =
     "<html>"
     "  <body>"
@@ -22,10 +25,8 @@
     "  </body>"
     "</html>";
 
-const char kTestURLWithoutRegions[] = "http://test.com/no-regions";
 const char kTestHTMLWithoutRegions[] = "<html><body>Hello World!</body></html>";
 
-const char kTestURLWithChangingRegions[] = "http://test.com/changing-regions";
 const char kTestHTMLWithChangingRegions[] =
     "<html>"
     "  <body>"
@@ -47,75 +48,139 @@
     "  </body>"
     "</html>";
 
-class DraggableRegionsTestHandler : public TestHandler, public CefDragHandler {
+class DraggableRegionsTestHandler : public TestHandler,
+                                    public CefDragHandler,
+                                    public CefFrameHandler {
  public:
-  DraggableRegionsTestHandler() : step_(kStepWithRegions) {}
+  // Test steps executed in order.
+  enum Step {
+    // Nav 1: Two regions (get notification).
+    kStepWithRegions = 1,
+    // Nav 2: Starts with the same region as Nav 1 (no notification),
+    // then a changed region (get notification).
+    kStepWithChangingRegions,
+    // Nav 3: No regions (get notification).
+    kStepWithoutRegions,
+    // GoBack: Two regions (get notification), then a changed region (get
+    // notification). Note the first notification is not sent if
+    // BackForwardCache is enabled.
+    kStepWithChangingRegions2,
+    kStepWithChangingRegions3,
+    // GoForward: No regions (get notification).
+    kStepWithoutRegions2,
+
+    kStepMax = kStepWithoutRegions2,
+  };
+
+  explicit DraggableRegionsTestHandler(bool same_origin)
+      : same_origin_(same_origin) {}
 
   void RunTest() override {
     // Add HTML documents with and without draggable regions.
-    AddResource(kTestURLWithRegions, kTestHTMLWithRegions, "text/html");
-    AddResource(kTestURLWithoutRegions, kTestHTMLWithoutRegions, "text/html");
-    AddResource(kTestURLWithChangingRegions, kTestHTMLWithChangingRegions,
+    AddResource(GetURL(kStepWithRegions), kTestHTMLWithRegions, "text/html");
+    AddResource(GetURL(kStepWithChangingRegions), kTestHTMLWithChangingRegions,
+                "text/html");
+    AddResource(GetURL(kStepWithoutRegions), kTestHTMLWithoutRegions,
                 "text/html");
 
     // Create the browser
-    CreateBrowser(kTestURLWithRegions);
+    CreateBrowser(GetURL(kStepWithRegions));
 
     // Time out the test after a reasonable period of time.
     SetTestTimeout();
   }
 
   CefRefPtr<CefDragHandler> GetDragHandler() override { return this; }
+  CefRefPtr<CefFrameHandler> GetFrameHandler() override { return this; }
 
   void OnDraggableRegionsChanged(
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       const std::vector<CefDraggableRegion>& regions) override {
-    EXPECT_TRUE(CefCurrentlyOn(TID_UI));
+    EXPECT_UI_THREAD();
     EXPECT_TRUE(browser->IsSame(GetBrowser()));
     EXPECT_TRUE(frame->IsMain());
 
-    did_call_on_draggable_regions_changed_.yes();
+    draggable_regions_changed_ct_++;
+
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "step " << step_ << " regions.size " << regions.size()
+              << " url " << frame->GetURL().ToString();
+    if (regions.size() == 2) {
+      LOG(INFO) << "  region[0] x " << regions[0].bounds.x << " y "
+                << regions[0].bounds.y << " width " << regions[0].bounds.width
+                << " height " << regions[0].bounds.height;
+      LOG(INFO) << "  region[1] x " << regions[1].bounds.x << " y "
+                << regions[1].bounds.y << " width " << regions[1].bounds.width
+                << " height " << regions[1].bounds.height;
+    }
+#endif  // VERBOSE_DEBUGGING
 
     switch (step_) {
       case kStepWithRegions:
-      case kStepWithChangingRegions1:
-        EXPECT_EQ(2U, regions.size());
-        EXPECT_EQ(50, regions[0].bounds.x);
-        EXPECT_EQ(50, regions[0].bounds.y);
-        EXPECT_EQ(200, regions[0].bounds.width);
-        EXPECT_EQ(200, regions[0].bounds.height);
+      case kStepWithChangingRegions2:
+        EXPECT_EQ(2U, regions.size()) << step_;
+        if (regions.size() != 2U) {
+          break;
+        }
+        EXPECT_NEAR(50, regions[0].bounds.x, 1);
+        EXPECT_NEAR(50, regions[0].bounds.y, 1);
+        EXPECT_NEAR(200, regions[0].bounds.width, 1);
+        EXPECT_NEAR(200, regions[0].bounds.height, 1);
         EXPECT_EQ(1, regions[0].draggable);
-        EXPECT_EQ(125, regions[1].bounds.x);
-        EXPECT_EQ(125, regions[1].bounds.y);
-        EXPECT_EQ(50, regions[1].bounds.width);
-        EXPECT_EQ(50, regions[1].bounds.height);
+        EXPECT_NEAR(125, regions[1].bounds.x, 1);
+        EXPECT_NEAR(125, regions[1].bounds.y, 1);
+        EXPECT_NEAR(50, regions[1].bounds.width, 1);
+        EXPECT_NEAR(50, regions[1].bounds.height, 1);
         EXPECT_EQ(0, regions[1].draggable);
         break;
-      case kStepWithChangingRegions2:
-        EXPECT_EQ(2U, regions.size());
+      case kStepWithChangingRegions:
+      case kStepWithChangingRegions3:
+        EXPECT_EQ(2U, regions.size()) << step_;
+        if (regions.size() != 2U) {
+          break;
+        }
         EXPECT_EQ(0, regions[0].bounds.x);
         EXPECT_EQ(0, regions[0].bounds.y);
-        EXPECT_EQ(200, regions[0].bounds.width);
-        EXPECT_EQ(200, regions[0].bounds.height);
+        EXPECT_NEAR(200, regions[0].bounds.width, 1);
+        EXPECT_NEAR(200, regions[0].bounds.height, 1);
         EXPECT_EQ(1, regions[0].draggable);
-        EXPECT_EQ(75, regions[1].bounds.x);
-        EXPECT_EQ(75, regions[1].bounds.y);
-        EXPECT_EQ(50, regions[1].bounds.width);
-        EXPECT_EQ(50, regions[1].bounds.height);
+        EXPECT_NEAR(75, regions[1].bounds.x, 1);
+        EXPECT_NEAR(75, regions[1].bounds.y, 1);
+        EXPECT_NEAR(50, regions[1].bounds.width, 2);
+        EXPECT_NEAR(50, regions[1].bounds.height, 2);
         EXPECT_EQ(0, regions[1].draggable);
         break;
       case kStepWithoutRegions:
-        // Should not be reached.
-        EXPECT_TRUE(false);
+      case kStepWithoutRegions2:
+        EXPECT_TRUE(regions.empty()) << step_;
         break;
     }
 
     NextTest(browser);
   }
 
+  void OnFrameAttached(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame,
+                       bool reattached) override {
+    EXPECT_UI_THREAD();
+    EXPECT_TRUE(browser->IsSame(GetBrowser()));
+    EXPECT_TRUE(frame->IsMain());
+
+    if (reattached) {
+      // When BackForwardCache is enabled and we go back to
+      // kTestHTMLWithChangingRegions, draggable regions will already be in the
+      // final position because the page content is not reloaded.
+      if (step_ == kStepWithChangingRegions2) {
+        step_ = kStepWithChangingRegions3;
+        expected_draggable_regions_changed_ct_--;
+      }
+    }
+  }
+
   void DestroyTest() override {
-    EXPECT_FALSE(did_call_on_draggable_regions_changed_);
+    EXPECT_EQ(expected_draggable_regions_changed_ct_,
+              draggable_regions_changed_ct_);
 
     TestHandler::DestroyTest();
   }
@@ -124,50 +189,79 @@
   void NextTest(CefRefPtr<CefBrowser> browser) {
     CefRefPtr<CefFrame> frame(browser->GetMainFrame());
 
-    did_call_on_draggable_regions_changed_.reset();
-
     switch (step_) {
       case kStepWithRegions:
-        step_ = kStepWithChangingRegions1;
-        frame->LoadURL(kTestURLWithChangingRegions);
+        step_ = kStepWithChangingRegions;
+        frame->LoadURL(GetURL(kStepWithChangingRegions));
         break;
-      case kStepWithChangingRegions1:
-        step_ = kStepWithChangingRegions2;
-        break;
-      case kStepWithChangingRegions2:
+      case kStepWithChangingRegions:
         step_ = kStepWithoutRegions;
-        frame->LoadURL(kTestURLWithoutRegions);
-        // Needed because this test doesn't call OnDraggableRegionsChanged.
-        CefPostDelayedTask(
-            TID_UI, base::Bind(&DraggableRegionsTestHandler::DestroyTest, this),
-            500);
+        frame->LoadURL(GetURL(kStepWithoutRegions));
         break;
       case kStepWithoutRegions: {
-        // Should not be reached.
-        EXPECT_TRUE(false);
+        step_ = kStepWithChangingRegions2;
+        browser->GoBack();
+        break;
+      }
+      case kStepWithChangingRegions2: {
+        step_ = kStepWithChangingRegions3;
+        break;
+      }
+      case kStepWithChangingRegions3: {
+        step_ = kStepWithoutRegions2;
+        browser->GoForward();
+        break;
+      }
+      case kStepWithoutRegions2: {
+        DestroyTest();
         break;
       }
     }
   }
 
-  enum Step {
-    kStepWithRegions,
-    kStepWithChangingRegions1,
-    kStepWithChangingRegions2,
-    kStepWithoutRegions,
-  } step_;
+  std::string GetURL(Step step) const {
+    // When |same_origin_| is true every other URL gets a different origin.
+    switch (step) {
+      case kStepWithRegions:
+        return same_origin_ ? "https://test.com/regions"
+                            : "https://test2.com/regions";
+      case kStepWithChangingRegions:
+      case kStepWithChangingRegions2:
+      case kStepWithChangingRegions3:
+        return "https://test.com/changing-regions";
+      case kStepWithoutRegions:
+      case kStepWithoutRegions2:
+        return same_origin_ ? "https://test.com/no-regions"
+                            : "https://test2.com/no-regions";
+    }
 
-  TrackCallback did_call_on_draggable_regions_changed_;
+    NOTREACHED();
+    return "";
+  }
+
+  const bool same_origin_;
+
+  Step step_ = kStepWithRegions;
+  int draggable_regions_changed_ct_ = 0;
+  int expected_draggable_regions_changed_ct_ = kStepMax;
 
   IMPLEMENT_REFCOUNTING(DraggableRegionsTestHandler);
 };
 
 }  // namespace
 
-// Verify that draggable regions work.
-TEST(DraggableRegionsTest, DraggableRegions) {
+// Verify that draggable regions work in the same origin.
+TEST(DraggableRegionsTest, DraggableRegionsSameOrigin) {
   CefRefPtr<DraggableRegionsTestHandler> handler =
-      new DraggableRegionsTestHandler();
+      new DraggableRegionsTestHandler(/*same_origin=*/true);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Verify that draggable regions work cross-origin.
+TEST(DraggableRegionsTest, DraggableRegionsCrossOrigin) {
+  CefRefPtr<DraggableRegionsTestHandler> handler =
+      new DraggableRegionsTestHandler(/*same_origin=*/false);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 }
diff --git a/src/tests/ceftests/extensions/background_unittest.cc b/src/tests/ceftests/extensions/background_unittest.cc
index b7961d2..a043f16 100644
--- a/src/tests/ceftests/extensions/background_unittest.cc
+++ b/src/tests/ceftests/extensions/background_unittest.cc
@@ -64,11 +64,13 @@
     EXPECT_TRUE(extension_->IsSame(extension));
 
     // The extension should no longer be registered with the context.
-    if (loader_request_context())
+    if (loader_request_context()) {
       VerifyExtensionInContext(extension, loader_request_context(), false,
                                true);
-    if (request_context() && !request_context_same_loader())
+    }
+    if (request_context() && !request_context_same_loader()) {
       VerifyExtensionInContext(extension, request_context(), false, false);
+    }
 
     extension_ = nullptr;
 
@@ -76,7 +78,7 @@
     // Will close the browser windows.
     CefPostTask(
         TID_UI,
-        base::Bind(&BackgroundLoadUnloadTestHandler::DestroyTest, this));
+        base::BindOnce(&BackgroundLoadUnloadTestHandler::DestroyTest, this));
   }
 
   bool OnBeforeBackgroundBrowser(CefRefPtr<CefExtension> extension,
@@ -169,8 +171,9 @@
     TestDictionaryEqual(expected_manifest, extension->GetManifest());
 
     VerifyExtensionInContext(extension, loader_request_context(), true, true);
-    if (!request_context_same_loader())
+    if (!request_context_same_loader()) {
       VerifyExtensionInContext(extension, request_context(), true, false);
+    }
   }
 
   std::string GetExtensionURL(CefRefPtr<CefExtension> extension,
@@ -239,9 +242,9 @@
 
   virtual void TriggerDestroyTest() {
     // Execute asynchronously so call stacks have a chance to unwind.
-    CefPostTask(TID_UI,
-                base::Bind(&BackgroundLoadUnloadTestHandler::UnloadExtension,
-                           this, extension_));
+    CefPostTask(TID_UI, base::BindOnce(
+                            &BackgroundLoadUnloadTestHandler::UnloadExtension,
+                            this, extension_));
   }
 
   CefRefPtr<CefExtension> extension_;
diff --git a/src/tests/ceftests/extensions/chrome_alarms_unittest.cc b/src/tests/ceftests/extensions/chrome_alarms_unittest.cc
index a4abc86..25809a4 100644
--- a/src/tests/ceftests/extensions/chrome_alarms_unittest.cc
+++ b/src/tests/ceftests/extensions/chrome_alarms_unittest.cc
@@ -56,7 +56,7 @@
 
     // Execute asynchronously so call stacks have a chance to unwind.
     // Will close the browser windows.
-    CefPostTask(TID_UI, base::Bind(&AlarmsTestHandler::DestroyTest, this));
+    CefPostTask(TID_UI, base::BindOnce(&AlarmsTestHandler::DestroyTest, this));
   }
 
   // CefLoadHandler methods:
@@ -167,8 +167,8 @@
 
   virtual void TriggerDestroyTest() {
     // Execute asynchronously so call stacks have a chance to unwind.
-    CefPostTask(TID_UI, base::Bind(&AlarmsTestHandler::UnloadExtension, this,
-                                   extension_));
+    CefPostTask(TID_UI, base::BindOnce(&AlarmsTestHandler::UnloadExtension,
+                                       this, extension_));
   }
 
   CefRefPtr<CefExtension> extension() const { return extension_; }
diff --git a/src/tests/ceftests/extensions/chrome_storage_unittest.cc b/src/tests/ceftests/extensions/chrome_storage_unittest.cc
index f71d6d8..28fe1c3 100644
--- a/src/tests/ceftests/extensions/chrome_storage_unittest.cc
+++ b/src/tests/ceftests/extensions/chrome_storage_unittest.cc
@@ -56,7 +56,7 @@
 
     // Execute asynchronously so call stacks have a chance to unwind.
     // Will close the browser windows.
-    CefPostTask(TID_UI, base::Bind(&StorageTestHandler::DestroyTest, this));
+    CefPostTask(TID_UI, base::BindOnce(&StorageTestHandler::DestroyTest, this));
   }
 
   // CefLoadHandler methods:
@@ -167,8 +167,8 @@
 
   virtual void TriggerDestroyTest() {
     // Execute asynchronously so call stacks have a chance to unwind.
-    CefPostTask(TID_UI, base::Bind(&StorageTestHandler::UnloadExtension, this,
-                                   extension_));
+    CefPostTask(TID_UI, base::BindOnce(&StorageTestHandler::UnloadExtension,
+                                       this, extension_));
   }
 
   CefRefPtr<CefExtension> extension() const { return extension_; }
diff --git a/src/tests/ceftests/extensions/chrome_tabs_unittest.cc b/src/tests/ceftests/extensions/chrome_tabs_unittest.cc
index ae0306e..c40043e 100644
--- a/src/tests/ceftests/extensions/chrome_tabs_unittest.cc
+++ b/src/tests/ceftests/extensions/chrome_tabs_unittest.cc
@@ -52,10 +52,11 @@
     EXPECT_FALSE(extension_);
     extension_ = extension;
 
-    if (create_main_browser_first_)
+    if (create_main_browser_first_) {
       CreateBrowserForExtensionIfReady();
-    else
+    } else {
       CreateBrowserForExtension();
+    }
   }
 
   void OnExtensionUnloaded(CefRefPtr<CefExtension> extension) override {
@@ -68,7 +69,7 @@
 
     // Execute asynchronously so call stacks have a chance to unwind.
     // Will close the browser windows.
-    CefPostTask(TID_UI, base::Bind(&TabsTestHandler::DestroyTest, this));
+    CefPostTask(TID_UI, base::BindOnce(&TabsTestHandler::DestroyTest, this));
   }
 
   CefRefPtr<CefBrowser> GetActiveBrowser(CefRefPtr<CefExtension> extension,
@@ -168,8 +169,9 @@
       EXPECT_TRUE(browser->IsSame(main_browser_));
       EXPECT_FALSE(got_main_body_onload_);
       got_main_body_onload_.yes();
-      if (create_main_browser_first_)
+      if (create_main_browser_first_) {
         CreateBrowserForExtensionIfReady();
+      }
       TriggerTabsApiJSFunctionIfReady();
       return true;
     }
@@ -272,8 +274,8 @@
 
   virtual void TriggerDestroyTest() {
     // Execute asynchronously so call stacks have a chance to unwind.
-    CefPostTask(TID_UI, base::Bind(&TabsTestHandler::UnloadExtension, this,
-                                   extension_));
+    CefPostTask(TID_UI, base::BindOnce(&TabsTestHandler::UnloadExtension, this,
+                                       extension_));
   }
 
   CefRefPtr<CefExtension> extension() const { return extension_; }
@@ -298,8 +300,9 @@
  private:
   void CreateBrowserForExtensionIfReady() {
     DCHECK(create_main_browser_first_);
-    if (extension_ && main_browser_)
+    if (extension_ && main_browser_) {
       CreateBrowserForExtension();
+    }
   }
 
   void CreateBrowserForExtension() {
@@ -317,8 +320,9 @@
   }
 
   void TriggerTabsApiJSFunctionIfReady() {
-    if (got_main_body_onload_ && got_extension_body_onload_)
+    if (got_main_body_onload_ && got_extension_body_onload_) {
       TriggerTabsApiJSFunction();
+    }
   }
 
   void TriggerTabsApiJSFunction() {
@@ -513,8 +517,9 @@
   }
 
   void TriggerDestroyTestIfReady() {
-    if (got_tab_callback_message_ && got_success_message())
+    if (got_tab_callback_message_ && got_success_message()) {
       TriggerDestroyTest();
+    }
   }
 
   CefRefPtr<CefBrowser> created_browser_;
diff --git a/src/tests/ceftests/extensions/extension_test_handler.cc b/src/tests/ceftests/extensions/extension_test_handler.cc
index b47c230..0aaef51 100644
--- a/src/tests/ceftests/extensions/extension_test_handler.cc
+++ b/src/tests/ceftests/extensions/extension_test_handler.cc
@@ -26,15 +26,15 @@
 
 ExtensionTestHandler::~ExtensionTestHandler() {
   if (!request_context_temp_dir_.IsEmpty()) {
-    // Delete temporary directories on shutdown.
-    CefTestSuite::GetInstance()->RegisterTempDirectory(
-        request_context_temp_dir_.Take());
+    // Temporary directory will be deleted on shutdown.
+    request_context_temp_dir_.Take();
   }
 }
 
 void ExtensionTestHandler::RunTest() {
-  if (create_main_browser_)
+  if (create_main_browser_) {
     OnAddMainBrowserResources();
+  }
 
   CefRefPtr<CefRequestContextHandler> rc_handler;
   if (request_context_with_handler()) {
@@ -65,7 +65,8 @@
 
     if (request_context_on_disk()) {
       // Create a new temporary directory.
-      EXPECT_TRUE(request_context_temp_dir_.CreateUniqueTempDir());
+      EXPECT_TRUE(request_context_temp_dir_.CreateUniqueTempDirUnderPath(
+          CefTestSuite::GetInstance()->root_cache_path()));
       CefString(&settings.cache_path) = request_context_temp_dir_.GetPath();
     }
 
@@ -130,12 +131,13 @@
 // CefMessageRouterBrowserSide::Handler methods:
 bool ExtensionTestHandler::OnQuery(CefRefPtr<CefBrowser> browser,
                                    CefRefPtr<CefFrame> frame,
-                                   int64 query_id,
+                                   int64_t query_id,
                                    const CefString& request,
                                    bool persistent,
                                    CefRefPtr<Callback> callback) {
-  if (OnMessage(browser, request))
+  if (OnMessage(browser, request)) {
     return true;
+  }
 
   EXPECT_FALSE(true) << "Unexpected message: " << request.ToString();
   return false;
@@ -153,8 +155,9 @@
   CefRefPtr<CefListValue> permissions = CefListValue::Create();
   permissions->SetSize(api_permissions.size() + 2);
   size_t idx = 0;
-  for (; idx < api_permissions.size(); ++idx)
+  for (; idx < api_permissions.size(); ++idx) {
     permissions->SetString(idx, api_permissions[idx]);
+  }
 
   // Allow access to all http/https origins.
   permissions->SetString(idx++, "http://*/*");
diff --git a/src/tests/ceftests/extensions/extension_test_handler.h b/src/tests/ceftests/extensions/extension_test_handler.h
index a2a87e3..3e3eeb3 100644
--- a/src/tests/ceftests/extensions/extension_test_handler.h
+++ b/src/tests/ceftests/extensions/extension_test_handler.h
@@ -2,8 +2,8 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#ifndef CEF_TESTS_UNITTESTS_EXTENSIONS_EXTENSION_TEST_HANDLER_H_
-#define CEF_TESTS_UNITTESTS_EXTENSIONS_EXTENSION_TEST_HANDLER_H_
+#ifndef CEF_TESTS_CEFTESTS_EXTENSIONS_EXTENSION_TEST_HANDLER_H_
+#define CEF_TESTS_CEFTESTS_EXTENSIONS_EXTENSION_TEST_HANDLER_H_
 #pragma once
 
 #include <vector>
@@ -56,7 +56,7 @@
   // CefMessageRouterBrowserSide::Handler methods:
   bool OnQuery(CefRefPtr<CefBrowser> browser,
                CefRefPtr<CefFrame> frame,
-               int64 query_id,
+               int64_t query_id,
                const CefString& request,
                bool persistent,
                CefRefPtr<Callback> callback) override;
@@ -235,4 +235,4 @@
   EXTENSION_TEST_GROUP_MINIMAL_GLOBAL(name, test_class) \
   EXTENSION_TEST_GROUP_MINIMAL_CUSTOM(name, test_class)
 
-#endif  // CEF_TESTS_UNITTESTS_EXTENSIONS_EXTENSION_TEST_HANDLER_H_
+#endif  // CEF_TESTS_CEFTESTS_EXTENSIONS_EXTENSION_TEST_HANDLER_H_
diff --git a/src/tests/ceftests/extensions/view_unittest.cc b/src/tests/ceftests/extensions/view_unittest.cc
index 444ed1e..4d9c03c 100644
--- a/src/tests/ceftests/extensions/view_unittest.cc
+++ b/src/tests/ceftests/extensions/view_unittest.cc
@@ -52,18 +52,20 @@
     EXPECT_TRUE(extension_->IsSame(extension));
 
     // The extension should no longer be registered with the context.
-    if (loader_request_context())
+    if (loader_request_context()) {
       VerifyExtensionInContext(extension, loader_request_context(), false,
                                true);
-    if (request_context() && !request_context_same_loader())
+    }
+    if (request_context() && !request_context_same_loader()) {
       VerifyExtensionInContext(extension, request_context(), false, false);
+    }
 
     extension_ = nullptr;
 
     // Execute asynchronously so call stacks have a chance to unwind.
     // Will close the browser windows.
     CefPostTask(TID_UI,
-                base::Bind(&ViewLoadUnloadTestHandler::DestroyTest, this));
+                base::BindOnce(&ViewLoadUnloadTestHandler::DestroyTest, this));
   }
 
   // CefLoadHandler methods:
@@ -164,8 +166,9 @@
     TestDictionaryEqual(expected_manifest, extension->GetManifest());
 
     VerifyExtensionInContext(extension, loader_request_context(), true, true);
-    if (!request_context_same_loader())
+    if (!request_context_same_loader()) {
       VerifyExtensionInContext(extension, request_context(), true, false);
+    }
   }
 
   void CreateBrowserForExtension() {
@@ -194,8 +197,9 @@
 
   virtual void TriggerDestroyTest() {
     // Execute asynchronously so call stacks have a chance to unwind.
-    CefPostTask(TID_UI, base::Bind(&ViewLoadUnloadTestHandler::UnloadExtension,
-                                   this, extension_));
+    CefPostTask(TID_UI,
+                base::BindOnce(&ViewLoadUnloadTestHandler::UnloadExtension,
+                               this, extension_));
   }
 
   CefRefPtr<CefExtension> extension_;
diff --git a/src/tests/ceftests/frame_handler_unittest.cc b/src/tests/ceftests/frame_handler_unittest.cc
new file mode 100644
index 0000000..42ee79d
--- /dev/null
+++ b/src/tests/ceftests/frame_handler_unittest.cc
@@ -0,0 +1,1724 @@
+// Copyright 2021 The Chromium Embedded Framework 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 <limits>
+#include <map>
+#include <memory>
+#include <queue>
+#include <sstream>
+#include <string>
+
+#include "include/base/cef_callback.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "tests/ceftests/routing_test_handler.h"
+#include "tests/ceftests/test_handler.h"
+#include "tests/ceftests/test_util.h"
+#include "tests/gtest/include/gtest/gtest.h"
+
+// Set to 1 to enable verbose debugging info logging.
+#define VERBOSE_DEBUGGING 0
+
+namespace {
+
+// Must match CefFrameHostImpl::kInvalidFrameId.
+const int kInvalidFrameId = -4;
+
+// Tracks callback status for a single frame object.
+struct FrameStatus {
+  // Callbacks in expected order. Not all callbacks are executed in all cases
+  // (see IsExpectedCallback).
+  enum CallbackType {
+    FRAME_CREATED,
+    MAIN_FRAME_INITIAL_ASSIGNED,
+    AFTER_CREATED,
+    FRAME_ATTACHED,
+    MAIN_FRAME_CHANGED_ASSIGNED,
+    LOAD_START,
+    LOAD_END,
+    BEFORE_CLOSE,
+    FRAME_DETACHED,
+    MAIN_FRAME_CHANGED_REMOVED,
+    MAIN_FRAME_FINAL_REMOVED,
+
+    CALLBACK_LAST = MAIN_FRAME_FINAL_REMOVED,
+  };
+
+  static const char* GetCallbackName(int type) {
+    switch (type) {
+      case FRAME_CREATED:
+        return "OnFrameCreated";
+      case MAIN_FRAME_INITIAL_ASSIGNED:
+        return "OnMainFrameChanged(initial_assigned)";
+      case AFTER_CREATED:
+        return "OnAfterCreated";
+      case FRAME_ATTACHED:
+        return "OnFrameAttached";
+      case MAIN_FRAME_CHANGED_ASSIGNED:
+        return "OnMainFrameChanged(changed_assigned)";
+      case LOAD_START:
+        return "OnLoadStart";
+      case LOAD_END:
+        return "OnLoadEnd";
+      case BEFORE_CLOSE:
+        return "OnBeforeClose";
+      case FRAME_DETACHED:
+        return "OnFrameDetached";
+      case MAIN_FRAME_CHANGED_REMOVED:
+        return "OnMainFrameChanged(changed_removed)";
+      case MAIN_FRAME_FINAL_REMOVED:
+        return "OnMainFrameChanged(final_removed)";
+    }
+    NOTREACHED();
+    return "Unknown";
+  }
+
+  // Returns true for callbacks that should only execute for main frames.
+  static bool IsMainFrameOnlyCallback(int type) {
+    return (type == MAIN_FRAME_INITIAL_ASSIGNED || type == AFTER_CREATED ||
+            type == MAIN_FRAME_CHANGED_ASSIGNED || type == BEFORE_CLOSE ||
+            type == MAIN_FRAME_CHANGED_REMOVED ||
+            type == MAIN_FRAME_FINAL_REMOVED);
+  }
+
+  static std::string GetFrameDebugString(CefRefPtr<CefFrame> frame) {
+    // Match the logic in frame_util::GetFrameDebugString.
+    // Specific formulation of the frame ID is an implementation detail that
+    // should generally not be relied upon, but this decomposed format makes the
+    // debug logging easier to follow.
+    uint64_t frame_id = frame->GetIdentifier();
+    uint32_t process_id = frame_id >> 32;
+    uint32_t routing_id = std::numeric_limits<uint32_t>::max() & frame_id;
+    std::stringstream ss;
+    ss << (frame->IsMain() ? "main" : " sub") << "[" << process_id << ","
+       << routing_id << "]";
+    return ss.str();
+  }
+
+  FrameStatus(CefRefPtr<CefFrame> frame)
+      : frame_id_(frame->GetIdentifier()),
+        is_main_(frame->IsMain()),
+        ident_str_(GetFrameDebugString(frame)) {}
+
+  int64_t frame_id() const { return frame_id_; }
+  bool is_main() const { return is_main_; }
+
+  bool AllQueriesDelivered(std::string* msg = nullptr) const {
+    EXPECT_UI_THREAD();
+    const int expected_ct = is_temporary_ ? 0 : expected_query_ct_;
+#if VERBOSE_DEBUGGING
+    if (msg) {
+      std::stringstream ss;
+      ss << ident_str_ << "(expected=" << expected_ct
+         << " delivered=" << delivered_query_ct_ << ")";
+      *msg += ss.str();
+    }
+#endif
+    return delivered_query_ct_ == expected_ct;
+  }
+  int QueriesDeliveredCount() const {
+    EXPECT_UI_THREAD();
+    return delivered_query_ct_;
+  }
+
+  bool IsSame(CefRefPtr<CefFrame> frame) const {
+    return frame->GetIdentifier() == frame_id();
+  }
+
+  bool IsLoaded(std::string* msg = nullptr) const {
+#if VERBOSE_DEBUGGING
+    if (msg) {
+      std::stringstream ss;
+      ss << ident_str_ << "(";
+      for (int i = 0; i <= LOAD_END; ++i) {
+        ss << GetCallbackName(i) << "=" << got_callback_[i];
+        if (i < LOAD_END) {
+          ss << " ";
+        }
+      }
+      ss << ")";
+      *msg += ss.str();
+    }
+#endif
+    return got_callback_[LOAD_END];
+  }
+  bool IsDetached() const { return got_callback_[FRAME_DETACHED]; }
+
+  void SetIsFirstMain(bool val) {
+    EXPECT_TRUE(is_main_);
+    is_first_main_ = val;
+    if (is_first_main_) {
+      // Also expect OnAfterCreated
+      expected_query_ct_++;
+    }
+  }
+  void SetIsLastMain(bool val) {
+    EXPECT_TRUE(is_main_);
+    is_last_main_ = val;
+  }
+
+  void SetIsTemporary(bool val) {
+    EXPECT_FALSE(is_main_);
+    is_temporary_ = val;
+  }
+  bool IsTemporary() const { return is_temporary_; }
+
+  void SetAdditionalDebugInfo(const std::string& debug_info) {
+    debug_info_ = debug_info;
+  }
+
+  std::string GetDebugString() const { return debug_info_ + ident_str_; }
+
+  // The main frame will be reused for same-origin navigations.
+  void ResetMainLoadStatus() {
+    EXPECT_TRUE(is_main_);
+
+    ResetCallbackStatus(LOAD_START, /*expect_query=*/true);
+    ResetCallbackStatus(LOAD_END, /*expect_query=*/true);
+  }
+
+  void OnFrameCreated(CefRefPtr<CefBrowser> browser,
+                      CefRefPtr<CefFrame> frame) {
+    EXPECT_UI_THREAD();
+    VerifyBrowser(__FUNCTION__, browser);
+    VerifyFrame(__FUNCTION__, frame);
+
+    GotCallback(__FUNCTION__, FRAME_CREATED);
+
+    // Test delivery of messages using a frame that isn't connected yet.
+    // This tests queuing of messages in the browser process and possibly the
+    // renderer process.
+    ExecuteQuery(frame, FRAME_CREATED);
+  }
+
+  void OnFrameAttached(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame) {
+    EXPECT_UI_THREAD();
+    VerifyBrowser(__FUNCTION__, browser);
+    VerifyFrame(__FUNCTION__, frame);
+
+    GotCallback(__FUNCTION__, FRAME_ATTACHED);
+
+    // Test delivery of messages using a frame that just connected.
+    // This tests queuing of messages in the browser process and possibly the
+    // renderer process.
+    ExecuteQuery(frame, FRAME_ATTACHED);
+  }
+
+  void OnFrameDetached(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame) {
+    EXPECT_UI_THREAD();
+    VerifyBrowser(__FUNCTION__, browser);
+    // A frame is never valid after it's detached.
+    VerifyFrame(__FUNCTION__, frame, /*expect_valid=*/false);
+
+    GotCallback(__FUNCTION__, FRAME_DETACHED);
+  }
+
+  void OnMainFrameChanged(CefRefPtr<CefBrowser> browser,
+                          CefRefPtr<CefFrame> old_frame,
+                          CefRefPtr<CefFrame> new_frame) {
+    EXPECT_UI_THREAD();
+    EXPECT_TRUE(is_main_);
+    VerifyBrowser(__FUNCTION__, browser);
+
+    bool got_match = false;
+
+    if (old_frame && new_frame) {
+      EXPECT_NE(old_frame->GetIdentifier(), new_frame->GetIdentifier());
+    }
+
+    if (old_frame && IsSame(old_frame)) {
+      got_match = true;
+      // A frame is never valid after it's detached.
+      VerifyFrame(__FUNCTION__, old_frame, /*expect_valid=*/false);
+      GotCallback(__FUNCTION__, new_frame ? MAIN_FRAME_CHANGED_REMOVED
+                                          : MAIN_FRAME_FINAL_REMOVED);
+      if (is_last_main_) {
+        EXPECT_FALSE(new_frame);
+      }
+    }
+
+    if (new_frame && IsSame(new_frame)) {
+      got_match = true;
+      VerifyFrame(__FUNCTION__, new_frame);
+      GotCallback(__FUNCTION__, old_frame ? MAIN_FRAME_CHANGED_ASSIGNED
+                                          : MAIN_FRAME_INITIAL_ASSIGNED);
+      if (is_first_main_) {
+        EXPECT_FALSE(old_frame);
+      }
+    }
+
+    EXPECT_TRUE(got_match);
+  }
+
+  void OnAfterCreated(CefRefPtr<CefBrowser> browser) {
+    EXPECT_UI_THREAD();
+    VerifyBrowser(__FUNCTION__, browser);
+
+    auto frame = browser->GetMainFrame();
+    VerifyFrame(__FUNCTION__, frame);
+
+    GotCallback(__FUNCTION__, AFTER_CREATED);
+    ExecuteQuery(frame, AFTER_CREATED);
+  }
+
+  // Called for all existing frames, not just the target frame.
+  // We need to track this status to know if the browser should be valid in
+  // following calls to OnFrameDetached.
+  void OnBeforeClose(CefRefPtr<CefBrowser> browser) {
+    EXPECT_UI_THREAD();
+    VerifyBrowser(__FUNCTION__, browser);
+
+    auto frame = browser->GetMainFrame();
+    EXPECT_TRUE(frame->IsValid());
+
+    got_before_close_ = true;
+    if (IsSame(frame)) {
+      VerifyFrame(__FUNCTION__, frame);
+      GotCallback(__FUNCTION__, BEFORE_CLOSE);
+    }
+  }
+
+  void OnLoadStart(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame) {
+    EXPECT_UI_THREAD();
+    VerifyBrowser(__FUNCTION__, browser);
+    VerifyFrame(__FUNCTION__, frame);
+
+    GotCallback(__FUNCTION__, LOAD_START);
+    ExecuteQuery(frame, LOAD_START);
+  }
+
+  void OnLoadEnd(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame) {
+    EXPECT_UI_THREAD();
+    VerifyBrowser(__FUNCTION__, browser);
+    VerifyFrame(__FUNCTION__, frame);
+
+    GotCallback(__FUNCTION__, LOAD_END);
+    ExecuteQuery(frame, LOAD_END);
+  }
+
+  void OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               const CefString& request) {
+    EXPECT_UI_THREAD();
+
+    const std::string& received_query = request;
+
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << GetDebugString() << " recv query " << received_query << " ("
+              << (delivered_query_ct_ + 1) << " of " << expected_query_ct_
+              << ")";
+#endif
+
+    VerifyBrowser(__FUNCTION__, browser);
+    VerifyFrame(__FUNCTION__, frame);
+
+    EXPECT_GE(pending_queries_.size(), 1U);
+    const std::string& expected_query = pending_queries_.front();
+    EXPECT_STREQ(expected_query.c_str(), received_query.c_str());
+    if (expected_query == received_query) {
+      pending_queries_.pop();
+    }
+
+    EXPECT_LT(delivered_query_ct_, expected_query_ct_);
+    delivered_query_ct_++;
+  }
+
+  void VerifyTestResults() {
+    EXPECT_UI_THREAD();
+
+    // Verify that all expected callbacks have executed.
+    VerifyCallbackStatus(__FUNCTION__, CALLBACK_LAST + 1);
+
+    if (is_temporary_) {
+      // Should not receive any queries.
+      EXPECT_FALSE(is_main_);
+      EXPECT_EQ(0, delivered_query_ct_);
+    } else {
+      // Verify that all expected messages have been sent and received.
+      EXPECT_EQ(expected_query_ct_, delivered_query_ct_);
+      EXPECT_EQ(0U, pending_queries_.size());
+      while (!pending_queries_.empty()) {
+        ADD_FAILURE() << "Query sent but not received: "
+                      << pending_queries_.front();
+        pending_queries_.pop();
+      }
+    }
+  }
+
+  bool DidGetCallback(int callback) const { return got_callback_[callback]; }
+
+ private:
+  void GotCallback(const std::string& func, int callback) {
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << GetDebugString() << " callback " << GetCallbackName(callback);
+#endif
+
+    EXPECT_TRUE(IsExpectedCallback(callback)) << func;
+    VerifyCallbackStatus(func, callback);
+    got_callback_[callback].yes();
+  }
+
+  bool IsExpectedCallback(int callback) const {
+    if (!is_main_ && IsMainFrameOnlyCallback(callback)) {
+      return false;
+    }
+
+    if (is_main_) {
+      if ((callback == MAIN_FRAME_INITIAL_ASSIGNED ||
+           callback == AFTER_CREATED) &&
+          !is_first_main_) {
+        return false;
+      }
+      if ((callback == BEFORE_CLOSE || callback == MAIN_FRAME_FINAL_REMOVED) &&
+          !is_last_main_) {
+        return false;
+      }
+      if (callback == MAIN_FRAME_CHANGED_ASSIGNED && is_first_main_) {
+        return false;
+      }
+      if (callback == MAIN_FRAME_CHANGED_REMOVED && is_last_main_) {
+        return false;
+      }
+    } else if (is_temporary_) {
+      // For cross-process sub-frame navigation a sub-frame is first created in
+      // the parent's renderer process. That sub-frame is then discarded after
+      // the real cross-origin sub-frame is created in a different renderer
+      // process. These discarded sub-frames will get OnFrameCreated/
+      // OnFrameAttached immediately followed by OnFrameDetached.
+      return callback == FRAME_CREATED || callback == FRAME_ATTACHED ||
+             callback == FRAME_DETACHED;
+    }
+
+    return true;
+  }
+
+  void VerifyCallbackStatus(const std::string& func,
+                            int current_callback) const {
+    EXPECT_UI_THREAD();
+
+    for (int i = 0; i <= CALLBACK_LAST; ++i) {
+      if (i < current_callback && IsExpectedCallback(i)) {
+        EXPECT_TRUE(got_callback_[i])
+            << "inside " << func << " should already have gotten "
+            << GetCallbackName(i);
+      } else {
+        EXPECT_FALSE(got_callback_[i])
+            << "inside " << func << " should not already have gotten "
+            << GetCallbackName(i);
+      }
+    }
+  }
+
+  void VerifyBrowser(const std::string& func,
+                     CefRefPtr<CefBrowser> browser) const {
+    const bool expect_valid = !got_before_close_;
+    if (expect_valid) {
+      EXPECT_TRUE(browser->IsValid()) << func;
+    } else {
+      EXPECT_FALSE(browser->IsValid()) << func;
+    }
+
+    // Note that this might not be the same main frame as us when navigating
+    // cross-origin, because the new main frame object is assigned to the
+    // browser before the CefFrameHandler callbacks related to main frame change
+    // have executed. This started out as an implementation detail but it fits
+    // nicely with the concept that "GetMainFrame() always returns a frame that
+    // can be used", which wouldn't be the case if we returned the old frame
+    // when calling GetMainFrame() from inside OnFrameCreated (for the new
+    // frame), OnFrameDetached (for the old frame) or OnMainFrameChanged.
+    auto main_frame = browser->GetMainFrame();
+    if (expect_valid) {
+      EXPECT_TRUE(main_frame) << func;
+      EXPECT_TRUE(main_frame->IsValid()) << func;
+      EXPECT_TRUE(main_frame->IsMain()) << func;
+    } else {
+      // GetMainFrame() returns nullptr after OnBeforeClose.
+      EXPECT_FALSE(main_frame) << func;
+    }
+  }
+
+  void VerifyFrame(const std::string& func,
+                   CefRefPtr<CefFrame> frame,
+                   bool expect_valid = true) const {
+    if (expect_valid) {
+      EXPECT_TRUE(frame->IsValid()) << func;
+    } else {
+      EXPECT_FALSE(frame->IsValid()) << func;
+    }
+
+    // |frame| should be us. This checks the frame type and ID.
+    EXPECT_STREQ(ident_str_.c_str(), GetFrameDebugString(frame).c_str())
+        << func;
+  }
+
+  void ExecuteQuery(CefRefPtr<CefFrame> frame, int callback) {
+    EXPECT_UI_THREAD();
+    const std::string& value = GetCallbackName(callback);
+
+    std::string js_string;
+
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << GetDebugString() << " sent query " << value;
+    js_string +=
+        "console.log('" + GetDebugString() + " exec query " + value + "');";
+#endif
+
+    js_string += "window.testQuery({request:'" + value + "'});";
+
+    pending_queries_.push(value);
+
+    // GetURL() will return an empty string for early callbacks, but that
+    // doesn't appear to cause any issues.
+    frame->ExecuteJavaScript(js_string, frame->GetURL(), 0);
+  }
+
+  // Reset state so we can get the same callback again.
+  void ResetCallbackStatus(int callback, bool expect_query) {
+    EXPECT_UI_THREAD();
+
+    EXPECT_TRUE(got_callback_[callback]) << GetCallbackName(callback);
+    got_callback_[callback].reset();
+
+    if (expect_query) {
+      delivered_query_ct_--;
+    }
+  }
+
+  const int64_t frame_id_;
+  const bool is_main_;
+  const std::string ident_str_;
+
+  bool is_first_main_ = false;
+  bool is_last_main_ = false;
+  bool is_temporary_ = false;
+  std::string debug_info_;
+
+  bool got_before_close_ = false;
+
+  TrackCallback got_callback_[CALLBACK_LAST + 1];
+
+  std::queue<std::string> pending_queries_;
+
+  // Expect OnCreated, OnAttached, OnLoadStart, OnLoadEnd.
+  int expected_query_ct_ = 4;
+  int delivered_query_ct_ = 0;
+};
+
+const char kOrderMainUrl[] = "https://tests-frame-handler/main-order.html";
+
+class OrderMainTestHandler : public RoutingTestHandler, public CefFrameHandler {
+ public:
+  OrderMainTestHandler(CompletionState* completion_state = nullptr)
+      : RoutingTestHandler(completion_state) {}
+
+  CefRefPtr<CefFrameHandler> GetFrameHandler() override {
+    get_frame_handler_ct_++;
+    return this;
+  }
+
+  void RunTest() override {
+    // Add the main resource that we will navigate to/from.
+    AddResource(GetMainURL(), GetMainHtml(), "text/html");
+
+    // Create the browser.
+    CreateBrowser(GetMainURL());
+
+    // Time out the test after a reasonable period of time.
+    SetTestTimeout();
+  }
+
+  void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
+    EXPECT_UI_THREAD();
+    RoutingTestHandler::OnAfterCreated(browser);
+
+    EXPECT_FALSE(got_after_created_);
+    got_after_created_ = true;
+
+    EXPECT_TRUE(current_main_frame_);
+    current_main_frame_->OnAfterCreated(browser);
+  }
+
+  void OnLoadStart(CefRefPtr<CefBrowser> browser,
+                   CefRefPtr<CefFrame> frame,
+                   TransitionType transition_type) override {
+    EXPECT_UI_THREAD();
+    RoutingTestHandler::OnLoadStart(browser, frame, transition_type);
+
+    EXPECT_TRUE(current_main_frame_);
+    current_main_frame_->OnLoadStart(browser, frame);
+  }
+
+  void OnLoadEnd(CefRefPtr<CefBrowser> browser,
+                 CefRefPtr<CefFrame> frame,
+                 int httpStatusCode) override {
+    EXPECT_UI_THREAD();
+    RoutingTestHandler::OnLoadEnd(browser, frame, httpStatusCode);
+
+    EXPECT_TRUE(current_main_frame_);
+    current_main_frame_->OnLoadEnd(browser, frame);
+
+    MaybeDestroyTest();
+  }
+
+  void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
+    EXPECT_UI_THREAD();
+
+    EXPECT_FALSE(got_before_close_);
+    got_before_close_ = true;
+
+    EXPECT_TRUE(current_main_frame_);
+    current_main_frame_->OnBeforeClose(browser);
+
+    RoutingTestHandler::OnBeforeClose(browser);
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               const CefString& request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    EXPECT_UI_THREAD();
+
+    // Messages for the old and new frames are interleaved during cross-origin
+    // navigation.
+    if (pending_main_frame_) {
+      EXPECT_TRUE(IsCrossOriginOrSameSiteBFCacheEnabled());
+      pending_main_frame_->OnQuery(browser, frame, request);
+    } else {
+      EXPECT_TRUE(current_main_frame_);
+      current_main_frame_->OnQuery(browser, frame, request);
+    }
+
+    MaybeDestroyTest();
+    return true;
+  }
+
+  void OnFrameCreated(CefRefPtr<CefBrowser> browser,
+                      CefRefPtr<CefFrame> frame) override {
+    EXPECT_UI_THREAD();
+
+    EXPECT_TRUE(frame->IsMain());
+    EXPECT_FALSE(pending_main_frame_);
+
+    // First callback referencing the new frame.
+    pending_main_frame_ = new FrameStatus(frame);
+    pending_main_frame_->SetAdditionalDebugInfo(GetAdditionalDebugInfo());
+    pending_main_frame_->SetIsFirstMain(!got_after_created_);
+    pending_main_frame_->SetIsLastMain(
+        !IsCrossOriginOrSameSiteBFCacheEnabled() || IsLastNavigation());
+    pending_main_frame_->OnFrameCreated(browser, frame);
+  }
+
+  void OnFrameAttached(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame,
+                       bool reattached) override {
+    EXPECT_UI_THREAD();
+
+    // May arrive before or after OnMainFrameChanged switches the frame (after
+    // on initial browser creation, before on cross-origin navigation).
+    if (pending_main_frame_) {
+      EXPECT_TRUE(IsCrossOriginOrSameSiteBFCacheEnabled());
+      pending_main_frame_->OnFrameAttached(browser, frame);
+    } else {
+      EXPECT_TRUE(current_main_frame_);
+      current_main_frame_->OnFrameAttached(browser, frame);
+    }
+  }
+
+  void OnFrameDetached(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame) override {
+    EXPECT_UI_THREAD();
+    EXPECT_TRUE(current_main_frame_);
+    current_main_frame_->OnFrameDetached(browser, frame);
+  }
+
+  void OnMainFrameChanged(CefRefPtr<CefBrowser> browser,
+                          CefRefPtr<CefFrame> old_frame,
+                          CefRefPtr<CefFrame> new_frame) override {
+    EXPECT_UI_THREAD();
+    EXPECT_TRUE(old_frame || new_frame);
+    if (old_frame) {
+      EXPECT_FALSE(old_frame->IsValid());
+      EXPECT_TRUE(old_frame->IsMain());
+
+      // May be nullptr with PopupOrderMainTestHandler.
+      if (current_main_frame_) {
+        // Last callback referencing the old frame.
+        EXPECT_TRUE(current_main_frame_);
+        current_main_frame_->OnMainFrameChanged(browser, old_frame, new_frame);
+        current_main_frame_->VerifyTestResults();
+        delete current_main_frame_;
+        current_main_frame_ = nullptr;
+      }
+    }
+    if (new_frame) {
+      EXPECT_TRUE(new_frame->IsValid());
+      EXPECT_TRUE(new_frame->IsMain());
+
+      // Always called after OnFrameCreated. See also comments in
+      // OnFrameAttached.
+      EXPECT_TRUE(pending_main_frame_);
+      pending_main_frame_->OnMainFrameChanged(browser, old_frame, new_frame);
+
+      // The pending frame becomes the current frame.
+      EXPECT_FALSE(current_main_frame_);
+      current_main_frame_ = pending_main_frame_;
+      pending_main_frame_ = nullptr;
+    }
+
+    if (old_frame && new_frame) {
+      // Main frame changed due to cross-origin navigation.
+      EXPECT_TRUE(IsCrossOriginOrSameSiteBFCacheEnabled());
+      main_frame_changed_ct_++;
+    }
+
+    if (old_frame && !new_frame) {
+      // Very last callback.
+      VerifyTestResults();
+    }
+  }
+
+ protected:
+  virtual std::string GetMainURL() const { return kOrderMainUrl; }
+
+  virtual std::string GetMainHtml() const {
+    return "<html><body>TEST</body></html>";
+  }
+
+  virtual std::string GetNextMainURL() { return std::string(); }
+  virtual bool IsFirstNavigation() const { return true; }
+  virtual bool IsLastNavigation() const { return true; }
+  virtual bool IsCrossOrigin() const { return false; }
+
+  bool IsCrossOriginOrSameSiteBFCacheEnabled() const {
+    return IsCrossOrigin() || IsSameSiteBFCacheEnabled();
+  }
+
+  virtual std::string GetAdditionalDebugInfo() const { return std::string(); }
+
+  virtual bool AllQueriesDelivered(std::string* msg = nullptr) const {
+    EXPECT_UI_THREAD();
+    if (pending_main_frame_) {
+      return false;
+    }
+    return current_main_frame_->AllQueriesDelivered(msg);
+  }
+
+  virtual bool AllFramesLoaded(std::string* msg = nullptr) const {
+    EXPECT_UI_THREAD();
+    if (pending_main_frame_) {
+      return false;
+    }
+    return current_main_frame_->IsLoaded(msg);
+  }
+
+  void MaybeDestroyTest() {
+#if VERBOSE_DEBUGGING
+    std::string delivered_msg, loaded_msg;
+    const bool all_queries_delivered = AllQueriesDelivered(&delivered_msg);
+    const bool all_frames_loaded = AllFramesLoaded(&loaded_msg);
+    LOG(INFO) << (current_main_frame_ ? current_main_frame_->GetDebugString()
+                                      : "")
+              << " AllQueriesDelivered=" << all_queries_delivered << " {"
+              << delivered_msg << "}"
+              << " AllFramesLoaded=" << all_frames_loaded << " {" << loaded_msg
+              << "}";
+    if (all_queries_delivered && all_frames_loaded) {
+#else
+    if (AllQueriesDelivered() && AllFramesLoaded()) {
+#endif
+      const std::string& next_url = GetNextMainURL();
+      if (!next_url.empty()) {
+        if (!IsCrossOriginOrSameSiteBFCacheEnabled()) {
+          // Reusing the same main frame for same origin nav.
+          current_main_frame_->ResetMainLoadStatus();
+        }
+
+#if VERBOSE_DEBUGGING
+        LOG(INFO) << current_main_frame_->GetDebugString()
+                  << "--> Navigating to " << next_url;
+#endif
+        GetBrowser()->GetMainFrame()->LoadURL(next_url);
+      } else {
+#if VERBOSE_DEBUGGING
+        LOG(INFO) << "--> Destroy test";
+#endif
+        DestroyTest();
+      }
+    }
+  }
+
+  virtual void VerifyTestResults() {
+    EXPECT_UI_THREAD();
+
+    // OnMainFrameChanged should have cleaned up.
+    EXPECT_FALSE(pending_main_frame_);
+    EXPECT_FALSE(current_main_frame_);
+
+    EXPECT_TRUE(got_after_created_);
+    EXPECT_TRUE(got_before_close_);
+
+    // We document GetFrameHandler() as only being called a single time.
+    EXPECT_EQ(1, get_frame_handler_ct_);
+
+    // Make sure we get the expected number OnMainFrameChanged callbacks for the
+    // main frame.
+    EXPECT_EQ(expected_main_frame_changed_ct_, main_frame_changed_ct_);
+  }
+
+  // Number of times we expect the main frame to change (e.g. once per
+  // cross-origin navigation).
+  int expected_main_frame_changed_ct_ = 0;
+
+  bool got_after_created_ = false;
+  bool got_before_close_ = false;
+
+ private:
+  int get_frame_handler_ct_ = 0;
+  int main_frame_changed_ct_ = 0;
+
+  FrameStatus* current_main_frame_ = nullptr;
+  FrameStatus* pending_main_frame_ = nullptr;
+
+  IMPLEMENT_REFCOUNTING(OrderMainTestHandler);
+};
+
+}  // namespace
+
+// Test the ordering and behavior of main frame callbacks.
+TEST(FrameHandlerTest, OrderMain) {
+  CefRefPtr<OrderMainTestHandler> handler = new OrderMainTestHandler();
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+namespace {
+
+const char kOrderMainUrlPrefix[] = "https://tests-frame-handler";
+
+class NavigateOrderMainTestHandler : public OrderMainTestHandler {
+ public:
+  NavigateOrderMainTestHandler(bool cross_origin, int additional_nav_ct = 2)
+      : cross_origin_(cross_origin), additional_nav_ct_(additional_nav_ct) {}
+
+  void RunTest() override {
+    // Once for each cross-origin LoadURL call.
+    expected_main_frame_changed_ct_ =
+        IsCrossOriginOrSameSiteBFCacheEnabled() ? additional_nav_ct_ : 0;
+
+    // Resources for the 2nd+ navigation.
+    for (int i = 1; i <= additional_nav_ct_; i++) {
+      AddResource(GetURLForNav(i), GetMainHtmlForNav(i), "text/html");
+    }
+
+    OrderMainTestHandler::RunTest();
+  }
+
+ protected:
+  // Loaded when the browser is created.
+  std::string GetMainURL() const override { return GetURLForNav(0); }
+  std::string GetMainHtml() const override { return GetMainHtmlForNav(0); }
+
+  std::string GetNextMainURL() override {
+    if (current_nav_ct_ == additional_nav_ct_) {
+      // No more navigations.
+      return std::string();
+    }
+    return GetURLForNav(++current_nav_ct_);
+  }
+
+  bool IsFirstNavigation() const override { return current_nav_ct_ == 0U; }
+  bool IsLastNavigation() const override {
+    return current_nav_ct_ == additional_nav_ct_;
+  }
+  bool IsCrossOrigin() const override { return cross_origin_; }
+  int additional_nav_ct() const { return additional_nav_ct_; }
+
+  void VerifyTestResults() override {
+    OrderMainTestHandler::VerifyTestResults();
+    EXPECT_TRUE(IsLastNavigation());
+  }
+
+  virtual std::string GetMainHtmlForNav(int nav) const {
+    return "<html><body>TEST " + std::to_string(nav) + "</body></html>";
+  }
+
+  std::string GetURLForNav(int nav, const std::string& suffix = "") const {
+    std::stringstream ss;
+    if (cross_origin_) {
+      ss << kOrderMainUrlPrefix << nav << "/cross-origin" << suffix << ".html";
+    } else {
+      ss << kOrderMainUrlPrefix << "/" << nav << "same-origin" << suffix
+         << ".html";
+    }
+    return ss.str();
+  }
+
+ private:
+  const bool cross_origin_;
+  const int additional_nav_ct_;
+
+  int current_nav_ct_ = 0;
+};
+
+}  // namespace
+
+// Main frame navigating to different URLs with the same origin.
+TEST(FrameHandlerTest, OrderMainNavSameOrigin) {
+  CefRefPtr<NavigateOrderMainTestHandler> handler =
+      new NavigateOrderMainTestHandler(/*cross_origin=*/false);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Main frame navigating cross-origin.
+TEST(FrameHandlerTest, OrderMainNavCrossOrigin) {
+  CefRefPtr<NavigateOrderMainTestHandler> handler =
+      new NavigateOrderMainTestHandler(/*cross_origin=*/true);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+namespace {
+
+// Tracks sub-frames for a single main frame load.
+class FrameStatusMap {
+ public:
+  explicit FrameStatusMap(size_t expected_frame_ct)
+      : expected_frame_ct_(expected_frame_ct) {}
+  ~FrameStatusMap() { EXPECT_TRUE(frame_map_.empty()); }
+
+  bool Contains(CefRefPtr<CefFrame> frame) const {
+    return frame_map_.find(frame->GetIdentifier()) != frame_map_.end();
+  }
+
+  FrameStatus* CreateFrameStatus(CefRefPtr<CefFrame> frame) {
+    EXPECT_UI_THREAD();
+
+    EXPECT_LT(size(), expected_frame_ct_);
+
+    const int64_t id = frame->GetIdentifier();
+    EXPECT_NE(kInvalidFrameId, id);
+    EXPECT_EQ(frame_map_.find(id), frame_map_.end());
+
+    FrameStatus* status = new FrameStatus(frame);
+    frame_map_.insert(std::make_pair(id, status));
+    return status;
+  }
+
+  FrameStatus* GetFrameStatus(CefRefPtr<CefFrame> frame) const {
+    EXPECT_UI_THREAD();
+
+    const int64_t id = frame->GetIdentifier();
+    EXPECT_NE(kInvalidFrameId, id);
+    Map::const_iterator it = frame_map_.find(id);
+    EXPECT_NE(it, frame_map_.end());
+    return it->second;
+  }
+
+  void RemoveFrameStatus(CefRefPtr<CefFrame> frame) {
+    const int64_t id = frame->GetIdentifier();
+    Map::iterator it = frame_map_.find(id);
+    EXPECT_NE(it, frame_map_.end());
+    frame_map_.erase(it);
+  }
+
+  void OnBeforeClose(CefRefPtr<CefBrowser> browser) {
+    Map::const_iterator it = frame_map_.begin();
+    for (; it != frame_map_.end(); ++it) {
+      it->second->OnBeforeClose(browser);
+    }
+  }
+
+  bool AllQueriesDelivered(std::string* msg = nullptr) const {
+    if (size() != expected_frame_ct_) {
+#if VERBOSE_DEBUGGING
+      if (msg) {
+        std::stringstream ss;
+        ss << " SUB COUNT MISMATCH! size=" << size()
+           << " expected=" << expected_frame_ct_;
+        *msg += ss.str();
+      }
+#endif
+      return false;
+    }
+
+    Map::const_iterator it = frame_map_.begin();
+    for (; it != frame_map_.end(); ++it) {
+      if (!it->second->AllQueriesDelivered(msg)) {
+#if VERBOSE_DEBUGGING
+        if (msg) {
+          *msg += " " + it->second->GetDebugString() + " PENDING";
+        }
+#endif
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  bool AllFramesLoaded(std::string* msg = nullptr) const {
+    if (size() != expected_frame_ct_) {
+#if VERBOSE_DEBUGGING
+      if (msg) {
+        std::stringstream ss;
+        ss << " SUB COUNT MISMATCH! size=" << size()
+           << " expected=" << expected_frame_ct_;
+        *msg += ss.str();
+      }
+#endif
+      return false;
+    }
+
+    Map::const_iterator it = frame_map_.begin();
+    for (; it != frame_map_.end(); ++it) {
+      if (!it->second->IsTemporary() && !it->second->IsLoaded(msg)) {
+#if VERBOSE_DEBUGGING
+        if (msg) {
+          *msg += " " + it->second->GetDebugString() + " PENDING";
+        }
+#endif
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  bool AllFramesDetached() const {
+    if (size() != expected_frame_ct_) {
+      return false;
+    }
+
+    Map::const_iterator it = frame_map_.begin();
+    for (; it != frame_map_.end(); ++it) {
+      if (!it->second->IsDetached()) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  void VerifyAndClearTestResults() {
+    EXPECT_EQ(expected_frame_ct_, size());
+    Map::const_iterator it = frame_map_.begin();
+    for (; it != frame_map_.end(); ++it) {
+      it->second->VerifyTestResults();
+      delete it->second;
+    }
+    frame_map_.clear();
+  }
+
+  size_t size() const { return frame_map_.size(); }
+
+ private:
+  using Map = std::map<int64_t, FrameStatus*>;
+  Map frame_map_;
+
+  // The expected number of sub-frames.
+  const size_t expected_frame_ct_;
+};
+
+class OrderSubTestHandler : public NavigateOrderMainTestHandler {
+ public:
+  enum TestMode {
+    // Two sub-frames at the same level.
+    SUBFRAME_PEERS,
+
+    // One sub-frame inside the other.
+    SUBFRAME_CHILDREN,
+  };
+
+  OrderSubTestHandler(bool cross_origin,
+                      int additional_nav_ct,
+                      TestMode mode,
+                      size_t expected_frame_ct = 2U)
+      : NavigateOrderMainTestHandler(cross_origin, additional_nav_ct),
+        test_mode_(mode),
+        expected_frame_ct_(expected_frame_ct) {}
+  ~OrderSubTestHandler() override { EXPECT_TRUE(frame_maps_.empty()); }
+
+  void RunTest() override {
+    for (int i = 0; i <= additional_nav_ct(); i++) {
+      AddResource(GetSubURL1ForNav(i), GetSubFrameHtml1ForNav(i), "text/html");
+      AddResource(GetSubURL2ForNav(i), GetSubFrameHtml2ForNav(i), "text/html");
+    }
+
+    NavigateOrderMainTestHandler::RunTest();
+  }
+
+  void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
+    NavigateOrderMainTestHandler::OnBeforeClose(browser);
+
+    for (auto& map : frame_maps_) {
+      // Also need to notify any sub-frames.
+      map->OnBeforeClose(browser);
+    }
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               const CefString& request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    if (!frame->IsMain()) {
+      auto map = GetFrameMap(frame);
+      auto status = map->GetFrameStatus(frame);
+      status->OnQuery(browser, frame, request);
+      if (status->AllQueriesDelivered()) {
+        MaybeDestroyTest();
+      }
+      return true;
+    }
+
+    return NavigateOrderMainTestHandler::OnQuery(browser, frame, query_id,
+                                                 request, persistent, callback);
+  }
+
+  void OnFrameCreated(CefRefPtr<CefBrowser> browser,
+                      CefRefPtr<CefFrame> frame) override {
+    if (!frame->IsMain()) {
+      // Potentially the first notification of a new sub-frame after navigation.
+      auto map = GetOrCreateFrameMap(frame);
+      auto status = map->CreateFrameStatus(frame);
+      status->SetAdditionalDebugInfo(GetAdditionalDebugInfo());
+      status->OnFrameCreated(browser, frame);
+      return;
+    }
+
+    NavigateOrderMainTestHandler::OnFrameCreated(browser, frame);
+  }
+
+  void OnFrameAttached(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame,
+                       bool reattached) override {
+    if (!frame->IsMain()) {
+      auto map = GetFrameMap(frame);
+      auto status = map->GetFrameStatus(frame);
+      status->OnFrameAttached(browser, frame);
+      return;
+    }
+
+    NavigateOrderMainTestHandler::OnFrameAttached(browser, frame, reattached);
+  }
+
+  void OnFrameDetached(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame) override {
+    if (!frame->IsMain()) {
+      // Potentially the last notification for an old sub-frame after
+      // navigation.
+      auto map = GetFrameMap(frame);
+      auto status = map->GetFrameStatus(frame);
+      status->OnFrameDetached(browser, frame);
+
+      if (map->AllFramesDetached()) {
+        // Verify results from the previous navigation.
+        VerifyAndClearSubFrameTestResults(map);
+      }
+      return;
+    }
+
+    NavigateOrderMainTestHandler::OnFrameDetached(browser, frame);
+  }
+
+  void OnLoadStart(CefRefPtr<CefBrowser> browser,
+                   CefRefPtr<CefFrame> frame,
+                   TransitionType transition_type) override {
+    if (!frame->IsMain()) {
+      auto map = GetFrameMap(frame);
+      auto status = map->GetFrameStatus(frame);
+      status->OnLoadStart(browser, frame);
+      return;
+    }
+
+    NavigateOrderMainTestHandler::OnLoadStart(browser, frame, transition_type);
+  }
+
+  void OnLoadEnd(CefRefPtr<CefBrowser> browser,
+                 CefRefPtr<CefFrame> frame,
+                 int httpStatusCode) override {
+    if (!frame->IsMain()) {
+      auto map = GetFrameMap(frame);
+      auto status = map->GetFrameStatus(frame);
+      status->OnLoadEnd(browser, frame);
+      return;
+    }
+
+    NavigateOrderMainTestHandler::OnLoadEnd(browser, frame, httpStatusCode);
+  }
+
+ protected:
+  virtual std::string GetSubURL1ForNav(int nav) const {
+    return GetURLForNav(nav, "sub1");
+  }
+
+  std::string GetSubFrameHtml1ForNav(int nav) const {
+    if (test_mode_ == SUBFRAME_CHILDREN) {
+      return "<iframe src=\"" + GetSubURL2ForNav(nav) + "\">";
+    }
+    return "<html><body>Sub1</body></html>";
+  }
+
+  virtual std::string GetSubURL2ForNav(int nav) const {
+    return GetURLForNav(nav, "sub2");
+  }
+
+  std::string GetSubFrameHtml2ForNav(int nav) const {
+    return "<html><body>Sub2</body></html>";
+  }
+
+  std::string GetMainHtmlForNav(int nav) const override {
+    if (test_mode_ == SUBFRAME_PEERS) {
+      return "<html><body><iframe src=\"" + GetSubURL1ForNav(nav) +
+             "\"></iframe><iframe src=\"" + GetSubURL2ForNav(nav) +
+             "\"></iframe></body></html>";
+    } else if (test_mode_ == SUBFRAME_CHILDREN) {
+      return "<html><body><iframe src=\"" + GetSubURL1ForNav(nav) +
+             "\"></iframe></iframe></body></html>";
+    }
+    NOTREACHED();
+    return std::string();
+  }
+
+  bool AllQueriesDelivered(std::string* msg = nullptr) const override {
+    if (!NavigateOrderMainTestHandler::AllQueriesDelivered(msg)) {
+#if VERBOSE_DEBUGGING
+      if (msg) {
+        *msg += " MAIN PENDING";
+      }
+#endif
+      return false;
+    }
+
+    if (frame_maps_.empty()) {
+#if VERBOSE_DEBUGGING
+      if (msg) {
+        *msg += " NO SUBS";
+      }
+#endif
+      return false;
+    }
+
+    if (!frame_maps_.back()->AllQueriesDelivered(msg)) {
+#if VERBOSE_DEBUGGING
+      if (msg) {
+        *msg += " SUBS PENDING";
+      }
+#endif
+      return false;
+    }
+    return true;
+  }
+
+  bool AllFramesLoaded(std::string* msg = nullptr) const override {
+    if (!NavigateOrderMainTestHandler::AllFramesLoaded(msg)) {
+#if VERBOSE_DEBUGGING
+      if (msg) {
+        *msg += " MAIN PENDING";
+      }
+#endif
+      return false;
+    }
+
+    if (frame_maps_.empty()) {
+#if VERBOSE_DEBUGGING
+      if (msg) {
+        *msg += " NO SUBS";
+      }
+#endif
+      return false;
+    }
+
+    if (!frame_maps_.back()->AllFramesLoaded(msg)) {
+#if VERBOSE_DEBUGGING
+      if (msg) {
+        *msg += " SUBS PENDING";
+      }
+#endif
+      return false;
+    }
+    return true;
+  }
+
+  void VerifyTestResults() override {
+    NavigateOrderMainTestHandler::VerifyTestResults();
+    EXPECT_TRUE(frame_maps_.empty());
+  }
+
+  size_t expected_frame_ct() const { return expected_frame_ct_; }
+
+  FrameStatusMap* GetFrameMap(CefRefPtr<CefFrame> frame) const {
+    for (auto& map : frame_maps_) {
+      if (map->Contains(frame)) {
+        return map.get();
+      }
+    }
+    return nullptr;
+  }
+
+ private:
+  // All sub-frame objects should already have received all callbacks.
+  void VerifyAndClearSubFrameTestResults(FrameStatusMap* map) {
+    map->VerifyAndClearTestResults();
+
+    bool found = false;
+    FrameStatusMapVector::iterator it = frame_maps_.begin();
+    for (; it != frame_maps_.end(); ++it) {
+      if ((*it).get() == map) {
+        frame_maps_.erase(it);
+        found = true;
+        break;
+      }
+    }
+
+    EXPECT_TRUE(found);
+  }
+
+  FrameStatusMap* GetOrCreateFrameMap(CefRefPtr<CefFrame> frame) {
+    if (auto map = GetFrameMap(frame)) {
+      return map;
+    }
+
+    if (frame_maps_.empty() ||
+        frame_maps_.back()->size() >= expected_frame_ct_) {
+      // Start a new frame map.
+      auto map = std::make_unique<FrameStatusMap>(expected_frame_ct_);
+      frame_maps_.push_back(std::move(map));
+    }
+
+    return frame_maps_.back().get();
+  }
+
+  const TestMode test_mode_;
+
+  // The expected number of sub-frames.
+  const size_t expected_frame_ct_;
+
+  using FrameStatusMapVector = std::vector<std::unique_ptr<FrameStatusMap>>;
+  FrameStatusMapVector frame_maps_;
+};
+
+}  // namespace
+
+// Main frame loads two sub-frames that are peers in the same origin.
+TEST(FrameHandlerTest, OrderSubSameOriginPeers) {
+  CefRefPtr<OrderSubTestHandler> handler =
+      new OrderSubTestHandler(/*cross_origin=*/false, /*additional_nav_ct=*/0,
+                              OrderSubTestHandler::SUBFRAME_PEERS);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Main frame loads two sub-frames that are peers in the same origin, then
+// navigates in the same origin and does it again twice.
+TEST(FrameHandlerTest, OrderSubSameOriginPeersNavSameOrigin) {
+  CefRefPtr<OrderSubTestHandler> handler =
+      new OrderSubTestHandler(/*cross_origin=*/false, /*additional_nav_ct=*/2,
+                              OrderSubTestHandler::SUBFRAME_PEERS);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Main frame loads two sub-frames that are peers in the same origin, then
+// navigates cross-origin and does it again twice.
+TEST(FrameHandlerTest, OrderSubSameOriginPeersNavCrossOrigin) {
+  CefRefPtr<OrderSubTestHandler> handler =
+      new OrderSubTestHandler(/*cross_origin=*/true, /*additional_nav_ct=*/2,
+                              OrderSubTestHandler::SUBFRAME_PEERS);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Main frame loads a sub-frame that then has it's own sub-frame.
+TEST(FrameHandlerTest, OrderSubSameOriginChildren) {
+  CefRefPtr<OrderSubTestHandler> handler =
+      new OrderSubTestHandler(/*cross_origin=*/false, /*additional_nav_ct=*/0,
+                              OrderSubTestHandler::SUBFRAME_CHILDREN);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Main frame loads a sub-frame that then has it's own sub-frame, then navigates
+// in the same origin and does it again twice.
+TEST(FrameHandlerTest, OrderSubSameOriginChildrenNavSameOrigin) {
+  CefRefPtr<OrderSubTestHandler> handler =
+      new OrderSubTestHandler(/*cross_origin=*/false, /*additional_nav_ct=*/2,
+                              OrderSubTestHandler::SUBFRAME_CHILDREN);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Main frame loads a sub-frame that then has it's own sub-frame, then navigates
+// cross-origin and does it again twice.
+TEST(FrameHandlerTest, OrderSubSameOriginChildrenNavCrossOrigin) {
+  CefRefPtr<OrderSubTestHandler> handler =
+      new OrderSubTestHandler(/*cross_origin=*/true, /*additional_nav_ct=*/2,
+                              OrderSubTestHandler::SUBFRAME_CHILDREN);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+namespace {
+
+// Like above, but also navigating the sub-frames cross-origin.
+class CrossOriginOrderSubTestHandler : public OrderSubTestHandler {
+ public:
+  CrossOriginOrderSubTestHandler(int additional_nav_ct, TestMode mode)
+      : OrderSubTestHandler(/*cross_origin=*/true,
+                            additional_nav_ct,
+                            mode,
+                            /*expected_frame_ct=*/4U) {}
+
+  void OnFrameDetached(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame) override {
+    // A sub-frame is first created in the parent's renderer process. That
+    // sub-frame is then discarded after the real cross-origin sub-frame is
+    // created in a different renderer process. These discarded sub-frames will
+    // get OnFrameCreated/OnFrameAttached immediately followed by
+    // OnFrameDetached.
+    if (!frame->IsMain()) {
+      auto map = GetFrameMap(frame);
+      auto status = map->GetFrameStatus(frame);
+      if (status && !status->DidGetCallback(FrameStatus::LOAD_START)) {
+        status->SetIsTemporary(true);
+        temp_frame_detached_ct_++;
+      }
+    }
+
+    OrderSubTestHandler::OnFrameDetached(browser, frame);
+  }
+
+ protected:
+  std::string GetSubURL1ForNav(int nav) const override {
+    std::stringstream ss;
+    ss << kOrderMainUrlPrefix << nav << "-sub1/sub-cross-origin.html";
+    return ss.str();
+  }
+
+  std::string GetSubURL2ForNav(int nav) const override {
+    std::stringstream ss;
+    ss << kOrderMainUrlPrefix << nav << "-sub2/sub-cross-origin.html";
+    return ss.str();
+  }
+
+  void VerifyTestResults() override {
+    OrderSubTestHandler::VerifyTestResults();
+
+    const size_t expected_temp_ct =
+        (expected_frame_ct() / 2U) * (1U + additional_nav_ct());
+    EXPECT_EQ(expected_temp_ct, temp_frame_detached_ct_);
+  }
+
+ private:
+  size_t temp_frame_detached_ct_ = 0U;
+};
+
+}  // namespace
+
+// Main frame loads two sub-frames that are peers in a different origin.
+TEST(FrameHandlerTest, OrderSubCrossOriginPeers) {
+  CefRefPtr<CrossOriginOrderSubTestHandler> handler =
+      new CrossOriginOrderSubTestHandler(
+          /*additional_nav_ct=*/0,
+          CrossOriginOrderSubTestHandler::SUBFRAME_PEERS);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Main frame loads two sub-frames that are peers in a different origin, then
+// navigates cross-origin and does it again twice.
+TEST(FrameHandlerTest, OrderSubCrossOriginPeersNavCrossOrigin) {
+  CefRefPtr<CrossOriginOrderSubTestHandler> handler =
+      new CrossOriginOrderSubTestHandler(
+          /*additional_nav_ct=*/2,
+          CrossOriginOrderSubTestHandler::SUBFRAME_PEERS);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Main frame loads a sub-frame in a different origin that then has it's own
+// sub-frame in a different origin.
+TEST(FrameHandlerTest, OrderSubCrossOriginChildren) {
+  CefRefPtr<CrossOriginOrderSubTestHandler> handler =
+      new CrossOriginOrderSubTestHandler(
+          /*additional_nav_ct=*/0,
+          CrossOriginOrderSubTestHandler::SUBFRAME_CHILDREN);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Main frame loads a sub-frame in a different origin that then has it's own
+// sub-frame in a different origin, then navigates cross-origin and does it
+// again twice.
+TEST(FrameHandlerTest, OrderSubCrossOriginChildrenNavCrossOrigin) {
+  CefRefPtr<CrossOriginOrderSubTestHandler> handler =
+      new CrossOriginOrderSubTestHandler(
+          /*additional_nav_ct=*/2,
+          CrossOriginOrderSubTestHandler::SUBFRAME_CHILDREN);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+namespace {
+
+const char kOrderMainCrossUrl[] =
+    "https://tests-frame-handler-cross/main-order.html";
+
+// Will be assigned as popup handler via
+// ParentOrderMainTestHandler::OnBeforePopup.
+class PopupOrderMainTestHandler : public OrderMainTestHandler {
+ public:
+  PopupOrderMainTestHandler(CompletionState* completion_state,
+                            bool cross_origin)
+      : OrderMainTestHandler(completion_state), cross_origin_(cross_origin) {
+    expected_main_frame_changed_ct_ = cross_origin_ ? 1 : 0;
+  }
+
+  void SetupTest() override {
+    // Proceed to RunTest().
+    SetupComplete();
+  }
+
+  void RunTest() override {
+    // Add the main resource that we will navigate to/from.
+    AddResource(GetMainURL(), GetMainHtml(), "text/html");
+
+    // Time out the test after a reasonable period of time.
+    SetTestTimeout();
+  }
+
+  void OnFrameCreated(CefRefPtr<CefBrowser> browser,
+                      CefRefPtr<CefFrame> frame) override {
+    EXPECT_UI_THREAD();
+
+    EXPECT_TRUE(frame->IsMain());
+    if (cross_origin_ && !temp_main_frame_) {
+      // The first main frame in the popup will be created in the parent
+      // process.
+      EXPECT_FALSE(got_temp_created_);
+      got_temp_created_.yes();
+
+      temp_main_frame_ = new FrameStatus(frame);
+      temp_main_frame_->SetAdditionalDebugInfo(GetAdditionalDebugInfo() +
+                                               "temp ");
+      temp_main_frame_->SetIsFirstMain(true);
+      temp_main_frame_->OnFrameCreated(browser, frame);
+      return;
+    }
+
+    OrderMainTestHandler::OnFrameCreated(browser, frame);
+  }
+
+  void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
+    if (temp_main_frame_ && temp_main_frame_->IsSame(browser->GetMainFrame())) {
+      EXPECT_FALSE(got_after_created_);
+      got_after_created_ = true;
+
+      EXPECT_TRUE(cross_origin_);
+      temp_main_frame_->OnAfterCreated(browser);
+
+      // Intentionally skipping the immediate parent class method.
+      RoutingTestHandler::OnAfterCreated(browser);
+      return;
+    }
+
+    OrderMainTestHandler::OnAfterCreated(browser);
+  }
+
+  void OnFrameAttached(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame,
+                       bool reattached) override {
+    if (temp_main_frame_ && temp_main_frame_->IsSame(frame)) {
+      EXPECT_TRUE(cross_origin_);
+      temp_main_frame_->OnFrameAttached(browser, frame);
+      return;
+    }
+
+    OrderMainTestHandler::OnFrameAttached(browser, frame, reattached);
+  }
+
+  void OnMainFrameChanged(CefRefPtr<CefBrowser> browser,
+                          CefRefPtr<CefFrame> old_frame,
+                          CefRefPtr<CefFrame> new_frame) override {
+    if (temp_main_frame_ && temp_main_frame_->IsSame(new_frame)) {
+      EXPECT_TRUE(cross_origin_);
+      temp_main_frame_->OnMainFrameChanged(browser, old_frame, new_frame);
+      return;
+    }
+
+    OrderMainTestHandler::OnMainFrameChanged(browser, old_frame, new_frame);
+  }
+
+  void OnFrameDetached(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame) override {
+    if (temp_main_frame_ && temp_main_frame_->IsSame(frame)) {
+      EXPECT_TRUE(cross_origin_);
+      EXPECT_FALSE(got_temp_destroyed_);
+      got_temp_destroyed_.yes();
+
+#if VERBOSE_DEBUGGING
+      LOG(INFO) << temp_main_frame_->GetDebugString()
+                << " callback OnFrameDetached(discarded)";
+#endif
+
+      // All of the initial main frame callbacks go to the proxy.
+      EXPECT_TRUE(temp_main_frame_->DidGetCallback(FrameStatus::AFTER_CREATED));
+      EXPECT_TRUE(temp_main_frame_->DidGetCallback(
+          FrameStatus::MAIN_FRAME_INITIAL_ASSIGNED));
+      EXPECT_TRUE(!temp_main_frame_->DidGetCallback(FrameStatus::LOAD_START));
+      EXPECT_TRUE(temp_main_frame_->DidGetCallback(FrameStatus::FRAME_CREATED));
+      EXPECT_TRUE(
+          temp_main_frame_->DidGetCallback(FrameStatus::FRAME_ATTACHED));
+
+      // Should receive queries for OnFrameCreated, OnAfterCreated,
+      // OnFrameAttached.
+      EXPECT_EQ(temp_main_frame_->QueriesDeliveredCount(), 3);
+
+      delete temp_main_frame_;
+      temp_main_frame_ = nullptr;
+      return;
+    }
+
+    OrderMainTestHandler::OnFrameDetached(browser, frame);
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               const CefString& request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    if (temp_main_frame_ && temp_main_frame_->IsSame(frame)) {
+      EXPECT_TRUE(cross_origin_);
+      temp_main_frame_->OnQuery(browser, frame, request);
+      return true;
+    }
+
+    return OrderMainTestHandler::OnQuery(browser, frame, query_id, request,
+                                         persistent, callback);
+  }
+
+  std::string GetMainURL() const override {
+    return cross_origin_ ? kOrderMainCrossUrl : kOrderMainUrl;
+  }
+
+ protected:
+  bool IsCrossOrigin() const override { return cross_origin_; }
+
+  void VerifyTestResults() override {
+    OrderMainTestHandler::VerifyTestResults();
+
+    if (cross_origin_) {
+      EXPECT_TRUE(got_temp_created_);
+      EXPECT_TRUE(got_temp_destroyed_);
+    } else {
+      EXPECT_FALSE(got_temp_created_);
+      EXPECT_FALSE(got_temp_destroyed_);
+    }
+    EXPECT_FALSE(temp_main_frame_);
+  }
+
+ private:
+  std::string GetAdditionalDebugInfo() const override { return " popup: "; }
+
+  const bool cross_origin_;
+
+  TrackCallback got_temp_created_;
+  TrackCallback got_temp_destroyed_;
+  FrameStatus* temp_main_frame_ = nullptr;
+};
+
+class ParentOrderMainTestHandler : public OrderMainTestHandler {
+ public:
+  ParentOrderMainTestHandler(CompletionState* completion_state,
+                             CefRefPtr<PopupOrderMainTestHandler> popup_handler)
+      : OrderMainTestHandler(completion_state), popup_handler_(popup_handler) {}
+
+  bool OnBeforePopup(
+      CefRefPtr<CefBrowser> browser,
+      CefRefPtr<CefFrame> frame,
+      const CefString& target_url,
+      const CefString& target_frame_name,
+      CefLifeSpanHandler::WindowOpenDisposition target_disposition,
+      bool user_gesture,
+      const CefPopupFeatures& popupFeatures,
+      CefWindowInfo& windowInfo,
+      CefRefPtr<CefClient>& client,
+      CefBrowserSettings& settings,
+      CefRefPtr<CefDictionaryValue>& extra_info,
+      bool* no_javascript_access) override {
+    // Intentionally not calling the parent class method.
+    EXPECT_FALSE(got_on_before_popup_);
+    got_on_before_popup_.yes();
+
+    client = popup_handler_;
+    popup_handler_ = nullptr;
+
+    // Proceed with popup creation.
+    return false;
+  }
+
+  void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
+    OrderMainTestHandler::OnAfterCreated(browser);
+
+    GrantPopupPermission(browser->GetHost()->GetRequestContext(), GetMainURL());
+
+    // Create the popup ASAP.
+    browser->GetMainFrame()->ExecuteJavaScript(
+        "window.open('" + popup_handler_->GetMainURL() + "');", CefString(), 0);
+  }
+
+  void SetupTest() override {
+    // Proceed to RunTest().
+    SetupComplete();
+  }
+
+  void DestroyTest() override {
+    EXPECT_TRUE(got_on_before_popup_);
+    OrderMainTestHandler::DestroyTest();
+  }
+
+ private:
+  std::string GetAdditionalDebugInfo() const override { return "parent: "; }
+
+  CefRefPtr<PopupOrderMainTestHandler> popup_handler_;
+
+  TrackCallback got_on_before_popup_;
+};
+
+void RunOrderMainPopupTest(bool cross_origin) {
+  TestHandler::CompletionState completion_state(/*count=*/2);
+  TestHandler::Collection collection(&completion_state);
+
+  CefRefPtr<PopupOrderMainTestHandler> popup_handler =
+      new PopupOrderMainTestHandler(&completion_state, cross_origin);
+  CefRefPtr<ParentOrderMainTestHandler> parent_handler =
+      new ParentOrderMainTestHandler(&completion_state, popup_handler);
+
+  collection.AddTestHandler(popup_handler.get());
+  collection.AddTestHandler(parent_handler.get());
+  collection.ExecuteTests();
+
+  ReleaseAndWaitForDestructor(parent_handler);
+  ReleaseAndWaitForDestructor(popup_handler);
+}
+
+}  // namespace
+
+// Test the ordering and behavior of main frame callbacks in a popup with the
+// same origin.
+TEST(FrameHandlerTest, OrderMainPopupSameOrigin) {
+  RunOrderMainPopupTest(/*cross_origin=*/false);
+}
+
+// Test the ordering and behavior of main frame callbacks in a popup with a
+// different origin.
+TEST(FrameHandlerTest, OrderMainPopupCrossOrigin) {
+  RunOrderMainPopupTest(/*cross_origin=*/true);
+}
diff --git a/src/tests/ceftests/frame_unittest.cc b/src/tests/ceftests/frame_unittest.cc
index 1498a32..3513d2a 100644
--- a/src/tests/ceftests/frame_unittest.cc
+++ b/src/tests/ceftests/frame_unittest.cc
@@ -2,8 +2,9 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
-#include "include/base/cef_scoped_ptr.h"
+#include <memory>
+
+#include "include/base/cef_callback.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "include/wrapper/cef_stream_resource_handler.h"
 #include "tests/ceftests/test_handler.h"
@@ -92,10 +93,10 @@
 const char kFrameNavTestCmdKey[] = "frame-nav-test";
 
 // Origins used in tests.
-const char kFrameNavOrigin0[] = "http://tests-framenav0.com/";
-const char kFrameNavOrigin1[] = "http://tests-framenav1.com/";
-const char kFrameNavOrigin2[] = "http://tests-framenav2.com/";
-const char kFrameNavOrigin3[] = "http://tests-framenav3.com/";
+const char kFrameNavOrigin0[] = "https://tests-framenav0.com/";
+const char kFrameNavOrigin1[] = "https://tests-framenav1.com/";
+const char kFrameNavOrigin2[] = "https://tests-framenav2.com/";
+const char kFrameNavOrigin3[] = "https://tests-framenav3.com/";
 
 // Maximum number of navigations. Should be kept synchronized with the number
 // of kFrameNavOrigin* values. Don't modify this value without checking the
@@ -105,7 +106,7 @@
 // Abstract base class representing expectations that result from a navigation.
 class FrameNavExpectations {
  public:
-  typedef base::Callback<void(CefRefPtr<CefBrowser>, CefRefPtr<CefFrame>)>
+  typedef base::OnceCallback<void(CefRefPtr<CefBrowser>, CefRefPtr<CefFrame>)>
       CompletionCallback;
 
   FrameNavExpectations(int nav, bool renderer)
@@ -136,9 +137,9 @@
     if (!completion_callback_.is_null()) {
       // Execute the callback asynchronously to avoid any issues with what's
       // currently on the stack.
-      CefPostTask((renderer_ ? TID_RENDERER : TID_UI),
-                  base::Bind(completion_callback_, browser, frame));
-      completion_callback_.Reset();
+      CefPostTask(
+          (renderer_ ? TID_RENDERER : TID_UI),
+          base::BindOnce(std::move(completion_callback_), browser, frame));
     }
   }
 
@@ -152,8 +153,8 @@
   // Returns true if this is a renderer-side expectation object.
   bool renderer() const { return renderer_; }
 
-  void set_completion_callback(const CompletionCallback& completion_callback) {
-    completion_callback_ = completion_callback;
+  void set_completion_callback(CompletionCallback completion_callback) {
+    completion_callback_ = std::move(completion_callback);
   }
 
  private:
@@ -222,7 +223,7 @@
   FrameNavExpectationsFactoryBrowser() {}
 
   // Create a new factory instance of the specified type.
-  static scoped_ptr<FrameNavExpectationsFactoryBrowser> FromID(
+  static std::unique_ptr<FrameNavExpectationsFactoryBrowser> FromID(
       FrameNavFactoryId id);
 
   // Returns true if there will be more navigations in the browser process
@@ -232,18 +233,17 @@
   // Verify final expectations results.
   virtual bool Finalize() = 0;
 
-  scoped_ptr<FrameNavExpectationsBrowser> Create(
+  std::unique_ptr<FrameNavExpectationsBrowser> Create(
       int nav,
-      const FrameNavExpectations::CompletionCallback& completion_callback) {
-    scoped_ptr<FrameNavExpectationsBrowser> expectations;
-    expectations = Create(nav);
-    expectations->set_completion_callback(completion_callback);
-    return expectations.Pass();
+      FrameNavExpectations::CompletionCallback completion_callback) {
+    auto expectations = Create(nav);
+    expectations->set_completion_callback(std::move(completion_callback));
+    return expectations;
   }
 
  protected:
   // Implement in the test-specific factory instance.
-  virtual scoped_ptr<FrameNavExpectationsBrowser> Create(int nav) = 0;
+  virtual std::unique_ptr<FrameNavExpectationsBrowser> Create(int nav) = 0;
 };
 
 // Renderer process expectations factory abstact base class.
@@ -252,21 +252,20 @@
   FrameNavExpectationsFactoryRenderer() {}
 
   // Create a new factory instance of the specified type.
-  static scoped_ptr<FrameNavExpectationsFactoryRenderer> FromID(
+  static std::unique_ptr<FrameNavExpectationsFactoryRenderer> FromID(
       FrameNavFactoryId id);
 
-  scoped_ptr<FrameNavExpectationsRenderer> Create(
+  std::unique_ptr<FrameNavExpectationsRenderer> Create(
       int nav,
-      const FrameNavExpectations::CompletionCallback& completion_callback) {
-    scoped_ptr<FrameNavExpectationsRenderer> expectations;
-    expectations = Create(nav);
-    expectations->set_completion_callback(completion_callback);
-    return expectations.Pass();
+      FrameNavExpectations::CompletionCallback completion_callback) {
+    auto expectations = Create(nav);
+    expectations->set_completion_callback(std::move(completion_callback));
+    return expectations;
   }
 
  protected:
   // Implement in the test-specific factory instance.
-  virtual scoped_ptr<FrameNavExpectationsRenderer> Create(int nav) = 0;
+  virtual std::unique_ptr<FrameNavExpectationsRenderer> Create(int nav) = 0;
 };
 
 // Renderer side handler.
@@ -278,22 +277,25 @@
   void OnBrowserCreated(CefRefPtr<ClientAppRenderer> app,
                         CefRefPtr<CefBrowser> browser,
                         CefRefPtr<CefDictionaryValue> extra_info) override {
-    if (!extra_info->HasKey(kFrameNavTestCmdKey))
+    if (!extra_info || !extra_info->HasKey(kFrameNavTestCmdKey)) {
       return;
+    }
 
     FrameNavFactoryId factory_id =
         static_cast<FrameNavFactoryId>(extra_info->GetInt(kFrameNavTestCmdKey));
     run_test_ = factory_id != FNF_ID_INVALID;
-    if (!run_test_)
+    if (!run_test_) {
       return;
+    }
 
     factory_ = FrameNavExpectationsFactoryRenderer::FromID(factory_id);
   }
 
   CefRefPtr<CefLoadHandler> GetLoadHandler(
       CefRefPtr<ClientAppRenderer> app) override {
-    if (!run_test_)
+    if (!run_test_) {
       return nullptr;
+    }
 
     return this;
   }
@@ -325,10 +327,11 @@
   // Create a new expectations object if one does not already exist for the
   // current navigation.
   void CreateExpectationsIfNecessary() {
-    if (expectations_)
+    if (expectations_) {
       return;
+    }
     expectations_ = factory_->Create(
-        nav_, base::Bind(&FrameNavRendererTest::SendTestResults, this));
+        nav_, base::BindOnce(&FrameNavRendererTest::SendTestResults, this));
   }
 
   // Send the test results.
@@ -350,7 +353,7 @@
     EXPECT_TRUE(args->SetInt(0, nav_));
     EXPECT_TRUE(args->SetBool(1, result));
 
-    const int64 frame_id = frame->GetIdentifier();
+    const int64_t frame_id = frame->GetIdentifier();
     EXPECT_TRUE(args->SetInt(2, CefInt64GetLow(frame_id)));
     EXPECT_TRUE(args->SetInt(3, CefInt64GetHigh(frame_id)));
 
@@ -361,8 +364,8 @@
 
   bool run_test_;
   int nav_;
-  scoped_ptr<FrameNavExpectationsFactoryRenderer> factory_;
-  scoped_ptr<FrameNavExpectationsRenderer> expectations_;
+  std::unique_ptr<FrameNavExpectationsFactoryRenderer> factory_;
+  std::unique_ptr<FrameNavExpectationsRenderer> expectations_;
 
   IMPLEMENT_REFCOUNTING(FrameNavRendererTest);
 };
@@ -379,7 +382,7 @@
   void RunTest() override {
     // Create the first expectations object.
     expectations_ = factory_->Create(
-        nav_, base::Bind(&FrameNavTestHandler::RunNextNav, this));
+        nav_, base::BindOnce(&FrameNavTestHandler::RunNextNav, this));
 
     CefRefPtr<CefDictionaryValue> extra_info = CefDictionaryValue::Create();
     extra_info->SetInt(kFrameNavTestCmdKey, factory_->GetID());
@@ -408,7 +411,7 @@
 
     // Create the next expectations object.
     expectations_ = factory_->Create(
-        nav_, base::Bind(&FrameNavTestHandler::RunNextNav, this));
+        nav_, base::BindOnce(&FrameNavTestHandler::RunNextNav, this));
 
     // Load the main URL.
     browser->GetMainFrame()->LoadURL(expectations_->GetMainURL());
@@ -424,10 +427,14 @@
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request) override {
+    const std::string& url = request->GetURL();
+    if (IgnoreURL(url)) {
+      return nullptr;
+    }
+
     EXPECT_TRUE(expectations_->GetResourceHandler(browser, frame))
         << "nav = " << nav_;
 
-    const std::string& url = request->GetURL();
     const std::string& content = expectations_->GetContentForURL(url);
     EXPECT_TRUE(!content.empty()) << "nav = " << nav_;
 
@@ -484,7 +491,7 @@
           << "nav = " << nav_;
 
       // Test that browser and render process frame IDs match.
-      const int64 frame_id = CefInt64Set(args->GetInt(2), args->GetInt(3));
+      const int64_t frame_id = CefInt64Set(args->GetInt(2), args->GetInt(3));
       EXPECT_EQ(frame->GetIdentifier(), frame_id);
 
       return true;
@@ -495,8 +502,9 @@
   }
 
   void DestroyTest() override {
-    if (got_destroyed_)
+    if (got_destroyed_) {
       return;
+    }
 
     got_destroyed_.yes();
 
@@ -511,8 +519,8 @@
 
   int nav_;
   TrackCallback got_destroyed_;
-  scoped_ptr<FrameNavExpectationsFactoryBrowser> factory_;
-  scoped_ptr<FrameNavExpectationsBrowser> expectations_;
+  std::unique_ptr<FrameNavExpectationsFactoryBrowser> factory_;
+  std::unique_ptr<FrameNavExpectationsBrowser> expectations_;
 
   IMPLEMENT_REFCOUNTING(FrameNavTestHandler);
 };
@@ -618,8 +626,9 @@
  private:
   void SignalCompleteIfDone(CefRefPtr<CefBrowser> browser,
                             CefRefPtr<CefFrame> frame) {
-    if (got_renderer_done_ && got_load_end_ && got_loading_state_change_end_)
+    if (got_renderer_done_ && got_load_end_ && got_loading_state_change_end_) {
       SignalComplete(browser, frame);
+    }
   }
 
   TrackCallback got_load_start_;
@@ -688,8 +697,9 @@
  private:
   void SignalCompleteIfDone(CefRefPtr<CefBrowser> browser,
                             CefRefPtr<CefFrame> frame) {
-    if (got_load_end_ && got_loading_state_change_end_)
+    if (got_load_end_ && got_loading_state_change_end_) {
       SignalComplete(browser, frame);
+    }
   }
 
   TrackCallback got_load_start_;
@@ -792,11 +802,11 @@
   }
 
  protected:
-  scoped_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
+  std::unique_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
     EXPECT_FALSE(got_create_);
     got_create_.yes();
-    return scoped_ptr<FrameNavExpectationsBrowser>(
-        new FrameNavExpectationsBrowserTestSingleNavHarness(nav));
+    return std::make_unique<FrameNavExpectationsBrowserTestSingleNavHarness>(
+        nav);
   }
 
  private:
@@ -813,9 +823,9 @@
   FrameNavFactoryId GetID() const override { return FNF_ID_SINGLE_NAV_HARNESS; }
 
  protected:
-  scoped_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
-    return scoped_ptr<FrameNavExpectationsRenderer>(
-        new FrameNavExpectationsRendererTestSingleNavHarness(nav));
+  std::unique_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
+    return std::make_unique<FrameNavExpectationsRendererTestSingleNavHarness>(
+        nav);
   }
 };
 
@@ -832,7 +842,7 @@
   V_DECLARE();
   V_EXPECT_TRUE(frame.get());
   V_EXPECT_TRUE(frame->IsValid());
-  const int64 frame_id = frame->GetIdentifier();
+  const int64_t frame_id = frame->GetIdentifier();
   V_EXPECT_TRUE(frame_id > 0) << frame_id;
   V_EXPECT_TRUE(frame->IsValid());
   V_EXPECT_TRUE(frame->IsMain());
@@ -869,7 +879,7 @@
   size_t frame_count = browser->GetFrameCount();
   V_EXPECT_TRUE(frame_count == 1U);
 
-  std::vector<int64> identifiers;
+  std::vector<int64_t> identifiers;
   browser->GetFrameIdentifiers(identifiers);
   V_EXPECT_TRUE(identifiers.size() == 1U);
   if (identifiers.size() == 1U) {
@@ -1011,9 +1021,8 @@
   bool Finalize() override { return true; }
 
  protected:
-  scoped_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
-    return scoped_ptr<FrameNavExpectationsBrowser>(
-        new FrameNavExpectationsBrowserTestSingleNav(nav));
+  std::unique_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
+    return std::make_unique<FrameNavExpectationsBrowserTestSingleNav>(nav);
   }
 };
 
@@ -1025,9 +1034,8 @@
   FrameNavFactoryId GetID() const override { return FNF_ID_SINGLE_NAV; }
 
  protected:
-  scoped_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
-    return scoped_ptr<FrameNavExpectationsRenderer>(
-        new FrameNavExpectationsRendererTestSingleNav(nav));
+  std::unique_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
+    return std::make_unique<FrameNavExpectationsRendererTestSingleNav>(nav);
   }
 };
 
@@ -1053,8 +1061,9 @@
 
   bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
                             bool isLoading) override {
-    if (!isLoading)
+    if (!isLoading) {
       SignalCompleteIfDone(browser, browser->GetMainFrame());
+    }
     return true;
   }
 
@@ -1085,8 +1094,9 @@
  private:
   void SignalCompleteIfDone(CefRefPtr<CefBrowser> browser,
                             CefRefPtr<CefFrame> frame) {
-    if (IsNavigationDone())
+    if (IsNavigationDone()) {
       SignalComplete(browser, frame);
+    }
   }
 
   TrackCallback got_finalize_;
@@ -1108,8 +1118,9 @@
 
   bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
                             bool isLoading) override {
-    if (!isLoading)
+    if (!isLoading) {
       SignalCompleteIfDone(browser, browser->GetMainFrame());
+    }
     return true;
   }
 
@@ -1131,8 +1142,9 @@
  private:
   void SignalCompleteIfDone(CefRefPtr<CefBrowser> browser,
                             CefRefPtr<CefFrame> frame) {
-    if (IsNavigationDone())
+    if (IsNavigationDone()) {
       SignalComplete(browser, frame);
+    }
   }
 
   TrackCallback got_finalize_;
@@ -1337,10 +1349,10 @@
   }
 
  protected:
-  scoped_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
+  std::unique_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
     create_count_++;
-    return scoped_ptr<FrameNavExpectationsBrowser>(
-        new FrameNavExpectationsBrowserTestMultiNavHarness(nav));
+    return std::make_unique<FrameNavExpectationsBrowserTestMultiNavHarness>(
+        nav);
   }
 
  private:
@@ -1357,9 +1369,9 @@
   FrameNavFactoryId GetID() const override { return FNF_ID_MULTI_NAV_HARNESS; }
 
  protected:
-  scoped_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
-    return scoped_ptr<FrameNavExpectationsRenderer>(
-        new FrameNavExpectationsRendererTestMultiNavHarness(nav));
+  std::unique_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
+    return std::make_unique<FrameNavExpectationsRendererTestMultiNavHarness>(
+        nav);
   }
 };
 
@@ -1393,8 +1405,9 @@
 
   bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
                             bool isLoading) override {
-    if (!isLoading)
+    if (!isLoading) {
       got_load_state_change_done_.yes();
+    }
     V_DECLARE();
     if (isLoading && nav() == 0) {
       V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, nullptr, std::string()));
@@ -1438,8 +1451,9 @@
                       const std::string& url) override {
     V_DECLARE();
     std::string expected_url;
-    if (nav() > 0)
+    if (nav() > 0) {
       expected_url = GetPreviousMainURL();
+    }
     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, expected_url));
     V_EXPECT_TRUE(parent::OnBeforeBrowse(browser, frame, url));
     V_RETURN();
@@ -1449,8 +1463,9 @@
                           CefRefPtr<CefFrame> frame) override {
     V_DECLARE();
     std::string expected_url;
-    if (nav() > 0)
+    if (nav() > 0) {
       expected_url = GetPreviousMainURL();
+    }
     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, expected_url));
     V_EXPECT_TRUE(parent::GetResourceHandler(browser, frame));
     V_RETURN();
@@ -1502,8 +1517,9 @@
 
   bool OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
                             bool isLoading) override {
-    if (!isLoading)
+    if (!isLoading) {
       got_load_state_change_done_.yes();
+    }
     V_DECLARE();
     V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, nullptr, GetMainURL()));
     V_EXPECT_TRUE(parent::OnLoadingStateChange(browser, isLoading));
@@ -1567,10 +1583,9 @@
   }
 
  protected:
-  scoped_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
+  std::unique_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
     nav_count_++;
-    return scoped_ptr<FrameNavExpectationsBrowser>(
-        new FrameNavExpectationsBrowserTestMultiNav(nav));
+    return std::make_unique<FrameNavExpectationsBrowserTestMultiNav>(nav);
   }
 
  private:
@@ -1585,9 +1600,8 @@
   FrameNavFactoryId GetID() const override { return FNF_ID_MULTI_NAV; }
 
  protected:
-  scoped_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
-    return scoped_ptr<FrameNavExpectationsRenderer>(
-        new FrameNavExpectationsRendererTestMultiNav(nav));
+  std::unique_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
+    return std::make_unique<FrameNavExpectationsRendererTestMultiNav>(nav);
   }
 };
 
@@ -1612,7 +1626,7 @@
   // frame0 contains frame1 contains frame2, contains frame3.
   CefRefPtr<CefFrame> frame0, frame1, frame2, frame3;
   CefRefPtr<CefFrame> frame0b, frame1b, frame2b, frame3b;
-  int64 frame0id, frame1id, frame2id, frame3id;
+  int64_t frame0id, frame1id, frame2id, frame3id;
   std::string frame0url, frame1url, frame2url, frame3url;
 
   // Verify the GetFrameNames result.
@@ -1629,8 +1643,9 @@
     auto it = expected_names.find(nameStr);
     V_EXPECT_FALSE(it == expected_names.end())
         << "Unexpected name: \"" << nameStr << "\"";
-    if (it != expected_names.end())
+    if (it != expected_names.end()) {
       expected_names.erase(it);
+    }
   }
 
   for (const auto& name : expected_names) {
@@ -1736,9 +1751,9 @@
   V_EXPECT_TRUE(frame_count == 4U) << " actual: " << frame_count;
 
   // Verify the GetFrameIdentifiers result.
-  std::set<int64> expected_idents = {frame0id, frame1id, frame2id, frame3id};
+  std::set<int64_t> expected_idents = {frame0id, frame1id, frame2id, frame3id};
 
-  std::vector<int64> idents;
+  std::vector<int64_t> idents;
   browser->GetFrameIdentifiers(idents);
   V_EXPECT_TRUE(idents.size() == expected_idents.size())
       << "expected: " << expected_idents.size() << " actual: " << idents.size();
@@ -1746,8 +1761,9 @@
   for (const auto& ident : idents) {
     auto it = expected_idents.find(ident);
     V_EXPECT_FALSE(it == expected_idents.end()) << "Unexpected id: " << ident;
-    if (it != expected_idents.end())
+    if (it != expected_idents.end()) {
       expected_idents.erase(it);
+    }
   }
 
   for (const auto& ident : expected_idents) {
@@ -2001,8 +2017,9 @@
 
   FrameNavExpectationsRendererTestNestedIframes(int nav, bool same_origin)
       : parent(nav) {
-    if (same_origin)
+    if (same_origin) {
       origin_ = kFrameNavOrigin0;
+    }
   }
 
   bool IsNavigationDone() const override {
@@ -2143,10 +2160,10 @@
   }
 
  protected:
-  scoped_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
+  std::unique_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
     create_count_++;
-    return scoped_ptr<FrameNavExpectationsBrowser>(
-        new FrameNavExpectationsBrowserTestNestedIframes(nav, true));
+    return std::make_unique<FrameNavExpectationsBrowserTestNestedIframes>(nav,
+                                                                          true);
   }
 
  private:
@@ -2163,9 +2180,9 @@
   }
 
  protected:
-  scoped_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
-    return scoped_ptr<FrameNavExpectationsRenderer>(
-        new FrameNavExpectationsRendererTestNestedIframes(nav, true));
+  std::unique_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
+    return std::make_unique<FrameNavExpectationsRendererTestNestedIframes>(
+        nav, true);
   }
 };
 
@@ -2197,10 +2214,10 @@
   }
 
  protected:
-  scoped_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
+  std::unique_ptr<FrameNavExpectationsBrowser> Create(int nav) override {
     create_count_++;
-    return scoped_ptr<FrameNavExpectationsBrowser>(
-        new FrameNavExpectationsBrowserTestNestedIframes(nav, false));
+    return std::make_unique<FrameNavExpectationsBrowserTestNestedIframes>(
+        nav, false);
   }
 
  private:
@@ -2217,9 +2234,9 @@
   }
 
  protected:
-  scoped_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
-    return scoped_ptr<FrameNavExpectationsRenderer>(
-        new FrameNavExpectationsRendererTestNestedIframes(nav, false));
+  std::unique_ptr<FrameNavExpectationsRenderer> Create(int nav) override {
+    return std::make_unique<FrameNavExpectationsRendererTestNestedIframes>(
+        nav, false);
   }
 };
 
@@ -2234,9 +2251,9 @@
 // must be listed here.
 
 // static
-scoped_ptr<FrameNavExpectationsFactoryBrowser>
+std::unique_ptr<FrameNavExpectationsFactoryBrowser>
 FrameNavExpectationsFactoryBrowser::FromID(FrameNavFactoryId id) {
-  scoped_ptr<FrameNavExpectationsFactoryBrowser> factory;
+  std::unique_ptr<FrameNavExpectationsFactoryBrowser> factory;
   switch (id) {
     case FNF_ID_SINGLE_NAV_HARNESS:
       factory.reset(new FrameNavExpectationsFactoryBrowserTestSingleNavHarness);
@@ -2263,13 +2280,13 @@
   }
   EXPECT_TRUE(factory);
   EXPECT_EQ(id, factory->GetID());
-  return factory.Pass();
+  return factory;
 }
 
 // static
-scoped_ptr<FrameNavExpectationsFactoryRenderer>
+std::unique_ptr<FrameNavExpectationsFactoryRenderer>
 FrameNavExpectationsFactoryRenderer::FromID(FrameNavFactoryId id) {
-  scoped_ptr<FrameNavExpectationsFactoryRenderer> factory;
+  std::unique_ptr<FrameNavExpectationsFactoryRenderer> factory;
   switch (id) {
     case FNF_ID_SINGLE_NAV_HARNESS:
       factory.reset(
@@ -2297,7 +2314,7 @@
   }
   EXPECT_TRUE(factory);
   EXPECT_EQ(id, factory->GetID());
-  return factory.Pass();
+  return factory;
 }
 
 }  // namespace
diff --git a/src/tests/ceftests/hsts_redirect_unittest.cc b/src/tests/ceftests/hsts_redirect_unittest.cc
new file mode 100644
index 0000000..1666eaa
--- /dev/null
+++ b/src/tests/ceftests/hsts_redirect_unittest.cc
@@ -0,0 +1,323 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "include/base/cef_callback.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "tests/ceftests/test_handler.h"
+#include "tests/ceftests/test_server.h"
+#include "tests/ceftests/test_server_observer.h"
+#include "tests/ceftests/test_util.h"
+#include "tests/gtest/include/gtest/gtest.h"
+#include "tests/shared/common/string_util.h"
+
+namespace {
+
+// Set the "Strict-Transport-Security" header on an HTTPS response to enable
+// HSTS redirects for follow-up HTTP requests to the same origin. See
+// https://www.chromium.org/hsts/.
+//
+// HSTS is implemented in the network service so real servers are required to
+// test the redirect behavior. It also requires a "localhost" domain certificate
+// instead of IP address (see https://crbug.com/456712). See additional comments
+// in OnResourceRedirect about redirect behavior with non-standard port numbers.
+//
+// The test works as follows:
+// 1. Start HTTP and HTTPS servers.
+// 2. Load an HTTP URL that redirects to an HTTPS URL.
+// 3. Set the "Strict-Transport-Security" header in response to the first HTTPS
+//    request.
+// 4. Load the same HTTP URL additional times to trigger the internal HTTP to
+//    HTTPS redirect.
+
+// Number of times to load the same HTTP URL. Must be > 1.
+constexpr size_t kHSTSLoadCount = 3;
+
+constexpr char kHSTSURLPath[] = "/index.html";
+
+// Used to observe HTTP and HTTPS server requests.
+class HSTSTestServerObserver : public test_server::ObserverHelper {
+ public:
+  using ReadyCallback = base::OnceCallback<void(const std::string& url)>;
+
+  HSTSTestServerObserver(bool https_server,
+                         size_t& nav_ct,
+                         TrackCallback (&got_request)[kHSTSLoadCount],
+                         ReadyCallback ready_callback,
+                         base::OnceClosure done_callback)
+      : https_server_(https_server),
+        nav_ct_(nav_ct),
+        got_request_(got_request),
+        ready_callback_(std::move(ready_callback)),
+        done_callback_(std::move(done_callback)) {
+    Initialize(https_server);
+  }
+
+  void OnInitialized(const std::string& server_origin) override {
+    EXPECT_UI_THREAD();
+
+    origin_ = ToLocalhostOrigin(server_origin);
+    url_ = origin_ + kHSTSURLPath;
+
+    std::move(ready_callback_).Run(url_);
+  }
+
+  void OnShutdown() override {
+    EXPECT_UI_THREAD();
+    std::move(done_callback_).Run();
+    delete this;
+  }
+
+  bool OnTestServerRequest(CefRefPtr<CefRequest> request,
+                           const ResponseCallback& response_callback) override {
+    EXPECT_UI_THREAD();
+
+    // At most 1 request per load.
+    EXPECT_FALSE(got_request_[nav_ct_]) << nav_ct_;
+    got_request_[nav_ct_].yes();
+
+    const std::string& url = ToLocalhostOrigin(request->GetURL());
+
+    auto response = CefResponse::Create();
+    response->SetMimeType("text/html");
+    std::string response_body;
+
+    if (!https_server_) {
+      // Redirect to the HTTPS URL.
+      EXPECT_STREQ(url_.c_str(), url.c_str()) << nav_ct_;
+      response->SetStatus(301);  // Permanent Redirect
+      response->SetHeaderByName("Location",
+                                GetLocalhostURL(/*https_server=*/true),
+                                /*overwrite=*/true);
+    } else {
+      // Normal response after an HTTP to HTTPS redirect.
+      EXPECT_STREQ(url_.c_str(), url.c_str()) << nav_ct_;
+      response->SetStatus(200);
+
+      if (nav_ct_ == 0) {
+        // Set the "Strict-Transport-Security" header in response to the first
+        // HTTPS request.
+        response->SetHeaderByName("Strict-Transport-Security",
+                                  "max-age=16070400",
+                                  /*overwrite=*/true);
+      }
+
+      // Don't cache the HTTPS response (so we see all the requests).
+      response->SetHeaderByName("Cache-Control", "no-cache",
+                                /*overwrite=*/true);
+
+      response_body = "<html><body>Test1</body></html>";
+    }
+
+    response_callback.Run(response, response_body);
+
+    // Stop propagating the callback.
+    return true;
+  }
+
+ private:
+  static std::string ToLocalhostOrigin(const std::string& origin) {
+    // Need to explicitly use the "localhost" domain instead of the IP address.
+    // HTTPS URLs will already be using "localhost".
+    return client::AsciiStrReplace(origin, "127.0.0.1", "localhost");
+  }
+
+  static std::string GetLocalhostOrigin(bool https_server) {
+    return ToLocalhostOrigin(test_server::GetOrigin(https_server));
+  }
+
+  static std::string GetLocalhostURL(bool https_server) {
+    return GetLocalhostOrigin(/*https_server=*/true) + kHSTSURLPath;
+  }
+
+  const bool https_server_;
+
+  size_t& nav_ct_;
+  TrackCallback (&got_request_)[kHSTSLoadCount];
+  ReadyCallback ready_callback_;
+  base::OnceClosure done_callback_;
+
+  std::string origin_;
+  std::string url_;
+
+  DISALLOW_COPY_AND_ASSIGN(HSTSTestServerObserver);
+};
+
+class HSTSRedirectTest : public TestHandler {
+ public:
+  HSTSRedirectTest() = default;
+
+  void RunTest() override {
+    SetTestTimeout();
+    CefPostTask(TID_UI,
+                base::BindOnce(&HSTSRedirectTest::StartHttpServer, this));
+  }
+
+  void OnResourceRedirect(CefRefPtr<CefBrowser> browser,
+                          CefRefPtr<CefFrame> frame,
+                          CefRefPtr<CefRequest> request,
+                          CefRefPtr<CefResponse> response,
+                          CefString& new_url) override {
+    EXPECT_IO_THREAD();
+
+    EXPECT_FALSE(got_redirect_[nav_ct_]) << nav_ct_;
+    got_redirect_[nav_ct_].yes();
+
+    EXPECT_STREQ(http_url_.c_str(), request->GetURL().ToString().c_str())
+        << nav_ct_;
+
+    if (nav_ct_ == 0) {
+      // Initial HTTP to HTTPS redirect.
+      EXPECT_STREQ(https_url_.c_str(), new_url.ToString().c_str()) << nav_ct_;
+    } else {
+      // HSTS HTTP to HTTPS redirect. This will use the wrong "localhost" port
+      // number, per spec. From RFC 6797:
+      //   The UA MUST replace the URI scheme with "https" [RFC2818], and if the
+      //   URI contains an explicit port component of "80", then the UA MUST
+      //   convert the port component to be "443", or if the URI contains an
+      //   explicit port component that is not equal to "80", the port component
+      //   value MUST be preserved; otherwise, if the URI does not contain an
+      //   explicit port component, the UA MUST NOT add one.
+      const std::string& expected_https_url =
+          client::AsciiStrReplace(http_url_, "http:", "https:");
+      EXPECT_STREQ(expected_https_url.c_str(), new_url.ToString().c_str())
+          << nav_ct_;
+
+      // Redirect to the correct HTTPS URL instead.
+      new_url = https_url_;
+    }
+  }
+
+  void OnLoadEnd(CefRefPtr<CefBrowser> browser,
+                 CefRefPtr<CefFrame> frame,
+                 int httpStatusCode) override {
+    EXPECT_UI_THREAD();
+
+    TestHandler::OnLoadEnd(browser, frame, httpStatusCode);
+
+    EXPECT_FALSE(got_load_end_[nav_ct_]) << nav_ct_;
+    got_load_end_[nav_ct_].yes();
+
+    // Expect only the HTTPS URL to load.
+    EXPECT_STREQ(https_url_.c_str(), frame->GetURL().ToString().c_str())
+        << nav_ct_;
+
+    if (++nav_ct_ == kHSTSLoadCount) {
+      StopHttpServer();
+    } else {
+      // Load the same HTTP URL again.
+      browser->GetMainFrame()->LoadURL(http_url_);
+    }
+  }
+
+  void DestroyTest() override {
+    EXPECT_FALSE(http_server_);
+    EXPECT_FALSE(https_server_);
+
+    EXPECT_EQ(kHSTSLoadCount, nav_ct_);
+    for (size_t i = 0; i < kHSTSLoadCount; ++i) {
+      EXPECT_TRUE(got_redirect_[i]) << i;
+      EXPECT_TRUE(got_load_end_[i]) << i;
+    }
+
+    for (size_t i = 0; i < kHSTSLoadCount; ++i) {
+      // Should only see the 1st HTTP request due to the internal HSTS redirect
+      // for the 2nd+ requests.
+      EXPECT_EQ(i == 0, got_http_request_[i]) << i;
+
+      // Should see all HTTPS requests.
+      EXPECT_TRUE(got_https_request_[i]) << i;
+    }
+
+    TestHandler::DestroyTest();
+  }
+
+ private:
+  void StartHttpServer() {
+    EXPECT_UI_THREAD();
+
+    // Will delete itself after the server stops.
+    http_server_ = new HSTSTestServerObserver(
+        /*https_server=*/false, nav_ct_, got_http_request_,
+        base::BindOnce(&HSTSRedirectTest::StartedHttpServer, this),
+        base::BindOnce(&HSTSRedirectTest::StoppedHttpServer, this));
+  }
+
+  void StartedHttpServer(const std::string& url) {
+    EXPECT_UI_THREAD();
+
+    http_url_ = url;
+    EXPECT_TRUE(http_url_.find("http://localhost:") == 0);
+
+    // Start the HTTPS server. Will delete itself after the server stops.
+    https_server_ = new HSTSTestServerObserver(
+        /*https_server=*/true, nav_ct_, got_https_request_,
+        base::BindOnce(&HSTSRedirectTest::StartedHttpsServer, this),
+        base::BindOnce(&HSTSRedirectTest::StoppedHttpsServer, this));
+  }
+
+  void StartedHttpsServer(const std::string& url) {
+    EXPECT_UI_THREAD();
+
+    https_url_ = url;
+    EXPECT_TRUE(https_url_.find("https://localhost:") == 0);
+
+    // Create a new in-memory context so HSTS decisions aren't cached.
+    CreateTestRequestContext(
+        TEST_RC_MODE_CUSTOM_WITH_HANDLER, /*cache_path=*/std::string(),
+        base::BindOnce(&HSTSRedirectTest::StartedHttpsServerContinue, this));
+  }
+
+  void StartedHttpsServerContinue(
+      CefRefPtr<CefRequestContext> request_context) {
+    EXPECT_UI_THREAD();
+
+    CreateBrowser(http_url_, request_context);
+  }
+
+  void StopHttpServer() {
+    EXPECT_UI_THREAD();
+
+    // Results in a call to StoppedHttpServer().
+    http_server_->Shutdown();
+  }
+
+  void StoppedHttpServer() {
+    EXPECT_UI_THREAD();
+
+    http_server_ = nullptr;
+
+    // Stop the HTTPS server. Results in a call to StoppedHttpsServer().
+    https_server_->Shutdown();
+  }
+
+  void StoppedHttpsServer() {
+    EXPECT_UI_THREAD();
+
+    https_server_ = nullptr;
+
+    DestroyTest();
+  }
+
+  HSTSTestServerObserver* http_server_ = nullptr;
+  std::string http_url_;
+
+  HSTSTestServerObserver* https_server_ = nullptr;
+  std::string https_url_;
+
+  size_t nav_ct_ = 0U;
+  TrackCallback got_http_request_[kHSTSLoadCount];
+  TrackCallback got_https_request_[kHSTSLoadCount];
+  TrackCallback got_load_end_[kHSTSLoadCount];
+  TrackCallback got_redirect_[kHSTSLoadCount];
+
+  IMPLEMENT_REFCOUNTING(HSTSRedirectTest);
+};
+
+}  // namespace
+
+TEST(HSTSRedirectTest, Redirect) {
+  CefRefPtr<HSTSRedirectTest> handler = new HSTSRedirectTest();
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
diff --git a/src/tests/ceftests/image_unittest.cc b/src/tests/ceftests/image_unittest.cc
index dba6a7c..f41da5e 100644
--- a/src/tests/ceftests/image_unittest.cc
+++ b/src/tests/ceftests/image_unittest.cc
@@ -38,10 +38,11 @@
   int expected_pixel_size = kExpectedDIPSize * expected_scale_factor;
 
   // Only returns true for exact matches.
-  if (scale_factor == expected_scale_factor)
+  if (scale_factor == expected_scale_factor) {
     EXPECT_TRUE(image->HasRepresentation(scale_factor));
-  else
+  } else {
     EXPECT_FALSE(image->HasRepresentation(scale_factor));
+  }
 
   // Returns the closest match.
   EXPECT_TRUE(image->GetRepresentationInfo(scale_factor, actual_scale_factor,
diff --git a/src/tests/ceftests/image_util.cc b/src/tests/ceftests/image_util.cc
index 29b7618..c31d905 100644
--- a/src/tests/ceftests/image_util.cc
+++ b/src/tests/ceftests/image_util.cc
@@ -16,10 +16,11 @@
   std::string image_str;
 
   std::string name_str;
-  if (scale_factor == 1.0f)
+  if (scale_factor == 1.0f) {
     name_str = name + ".1x.png";
-  else if (scale_factor == 2.0f)
+  } else if (scale_factor == 2.0f) {
     name_str = name + ".2x.png";
+  }
 
   EXPECT_TRUE(client::LoadBinaryResource(name_str.c_str(), image_str));
   EXPECT_TRUE(image->AddPNG(scale_factor, image_str.c_str(), image_str.size()));
diff --git a/src/tests/ceftests/image_util.h b/src/tests/ceftests/image_util.h
index 709e764..823fc08 100644
--- a/src/tests/ceftests/image_util.h
+++ b/src/tests/ceftests/image_util.h
@@ -2,8 +2,8 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#ifndef CEF_TESTS_UNITTESTS_IMAGE_UTIL_H_
-#define CEF_TESTS_UNITTESTS_IMAGE_UTIL_H_
+#ifndef CEF_TESTS_CEFTESTS_IMAGE_UTIL_H_
+#define CEF_TESTS_CEFTESTS_IMAGE_UTIL_H_
 #pragma once
 
 #include "include/cef_image.h"
@@ -24,4 +24,4 @@
 
 }  // namespace image_util
 
-#endif  // CEF_TESTS_UNITTESTS_IMAGE_UTIL_H_
+#endif  // CEF_TESTS_CEFTESTS_IMAGE_UTIL_H_
diff --git a/src/tests/ceftests/jsdialog_unittest.cc b/src/tests/ceftests/jsdialog_unittest.cc
index ae645a1..610fe37 100644
--- a/src/tests/ceftests/jsdialog_unittest.cc
+++ b/src/tests/ceftests/jsdialog_unittest.cc
@@ -2,7 +2,7 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/test/cef_test_helpers.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "tests/ceftests/test_handler.h"
@@ -10,8 +10,8 @@
 
 namespace {
 
-const char* kStartUrl = "http://tests/JSDialogTestHandler.Start";
-const char* kEndUrl = "http://tests/JSDialogTestHandler.End?r=";
+const char* kStartUrl = "https://tests/JSDialogTestHandler.Start";
+const char* kEndUrl = "https://tests/JSDialogTestHandler.End?r=";
 
 class JSDialogTestHandler : public TestHandler {
  public:
@@ -75,8 +75,9 @@
   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
                  CefRefPtr<CefFrame> frame,
                  int httpStatusCode) override {
-    if (!frame->IsMain())
+    if (!frame->IsMain()) {
       return;
+    }
 
     std::string url = frame->GetURL();
     if (url.find(kEndUrl) == 0) {
@@ -136,8 +137,8 @@
       callback->Continue(success_, user_input_);
     } else if (mode_ == MODE_RUN_DELAYED) {
       // Continue asynchronously.
-      CefPostTask(TID_UI,
-                  base::Bind(&JSDialogTestHandler::Continue, this, callback));
+      CefPostTask(TID_UI, base::BindOnce(&JSDialogTestHandler::Continue, this,
+                                         callback));
     }
 
     return true;
@@ -151,7 +152,7 @@
 
     if (type_ == TYPE_ONBEFOREUNLOAD) {
       // The message is no longer configurable via JavaScript.
-      // See http://crbug.com/587940.
+      // See https://crbug.com/587940.
       EXPECT_STREQ("Is it OK to leave/reload this page?",
                    message_text.ToString().c_str());
       EXPECT_FALSE(is_reload);
@@ -162,8 +163,8 @@
       callback->Continue(success_, user_input_);
     } else if (mode_ == MODE_RUN_DELAYED) {
       // Continue asynchronously.
-      CefPostTask(TID_UI,
-                  base::Bind(&JSDialogTestHandler::Continue, this, callback));
+      CefPostTask(TID_UI, base::BindOnce(&JSDialogTestHandler::Continue, this,
+                                         callback));
     }
 
     return true;
diff --git a/src/tests/ceftests/life_span_unittest.cc b/src/tests/ceftests/life_span_unittest.cc
index 7e71d04..772b3f7 100644
--- a/src/tests/ceftests/life_span_unittest.cc
+++ b/src/tests/ceftests/life_span_unittest.cc
@@ -2,7 +2,7 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/test/cef_test_helpers.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "tests/ceftests/routing_test_handler.h"
@@ -10,7 +10,7 @@
 
 namespace {
 
-const char kLifeSpanUrl[] = "http://tests-life-span/test.html";
+const char kLifeSpanUrl[] = "https://tests-life-span/test.html";
 const char kUnloadDialogText[] = "Are you sure?";
 const char kUnloadMsg[] = "LifeSpanTestHandler.Unload";
 
@@ -63,8 +63,9 @@
   }
 
   bool DoClose(CefRefPtr<CefBrowser> browser) override {
-    if (executing_delay_close_)
+    if (executing_delay_close_) {
       return false;
+    }
 
     EXPECT_TRUE(browser->IsSame(GetBrowser()));
 
@@ -99,7 +100,7 @@
     EXPECT_TRUE(browser->IsSame(GetBrowser()));
 
     // The message is no longer configurable via JavaScript.
-    // See http://crbug.com/587940.
+    // See https://crbug.com/587940.
     EXPECT_STREQ("Is it OK to leave/reload this page?",
                  message_text.ToString().c_str());
 
@@ -134,13 +135,14 @@
 
   bool OnQuery(CefRefPtr<CefBrowser> browser,
                CefRefPtr<CefFrame> frame,
-               int64 query_id,
+               int64_t query_id,
                const CefString& request,
                bool persistent,
                CefRefPtr<Callback> callback) override {
     if (request.ToString() == kUnloadMsg) {
-      if (!executing_delay_close_)
+      if (!executing_delay_close_) {
         got_unload_message_.yes();
+      }
     }
     callback->Success("");
     return true;
@@ -161,8 +163,8 @@
     // This test will call DestroyTest().
     SetDestroyTestExpected(true);
 
-    CefPostDelayedTask(TID_UI,
-                       base::Bind(&LifeSpanTestHandler::DelayClose, this), 100);
+    CefPostDelayedTask(
+        TID_UI, base::BindOnce(&LifeSpanTestHandler::DelayClose, this), 100);
   }
 
   void DelayClose() {
diff --git a/src/tests/ceftests/media_access_unittest.cc b/src/tests/ceftests/media_access_unittest.cc
new file mode 100644
index 0000000..1dd6a86
--- /dev/null
+++ b/src/tests/ceftests/media_access_unittest.cc
@@ -0,0 +1,725 @@
+// Copyright 2022 The Chromium Embedded Framework Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be found
+// in the LICENSE file.
+
+#include <string>
+#include <vector>
+
+#include "include/base/cef_bind.h"
+#include "include/cef_parser.h"
+#include "include/cef_permission_handler.h"
+#include "include/cef_request_context_handler.h"
+#include "include/test/cef_test_helpers.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "include/wrapper/cef_stream_resource_handler.h"
+#include "tests/ceftests/test_handler.h"
+#include "tests/ceftests/test_suite.h"
+#include "tests/ceftests/test_util.h"
+#include "tests/gtest/include/gtest/gtest.h"
+#include "tests/shared/browser/client_app_browser.h"
+
+namespace {
+
+// Media access requires HTTPS.
+const char kMediaUrl[] = "https://media-access-test/media.html";
+const char kMediaOrigin[] = "https://media-access-test/";
+
+constexpr char kMediaNavUrl[] = "https://media-access-test/nav.html";
+
+// Browser-side app delegate.
+class MediaAccessBrowserTest : public client::ClientAppBrowser::Delegate,
+                               public CefPermissionHandler {
+ public:
+  MediaAccessBrowserTest() {}
+
+  void OnBeforeCommandLineProcessing(
+      CefRefPtr<client::ClientAppBrowser> app,
+      CefRefPtr<CefCommandLine> command_line) override {
+    // We might run tests on systems that don't have media device,
+    // so just use fake devices.
+    command_line->AppendSwitch("use-fake-device-for-media-stream");
+  }
+
+ private:
+  IMPLEMENT_REFCOUNTING(MediaAccessBrowserTest);
+};
+
+class TestSetup {
+ public:
+  TestSetup() {}
+
+  // CONFIGURATION
+
+  // True if a user gesture is required for the getDisplayMedia call.
+  bool needs_user_gesture = false;
+
+  // Deny the prompt by returning false in OnRequestMediaAccessPermission.
+  bool deny_implicitly = false;
+
+  // Deny the prompt by returning true in OnRequestMediaAccessPermission but
+  // then never calling CefMediaAccessCallback::Continue.
+  bool deny_with_navigation = false;
+
+  // Don't synchronously execute the callback in OnRequestMediaAccessPermission.
+  bool continue_async = false;
+
+  // RESULTS
+
+  // Method callbacks.
+  TrackCallback got_request;
+  TrackCallback got_change;
+
+  // JS success state.
+  TrackCallback got_js_success;
+  TrackCallback got_audio;
+  TrackCallback got_video;
+
+  // JS error state.
+  TrackCallback got_js_error;
+  std::string js_error_str;
+
+  // JS timeout state.
+  TrackCallback got_js_timeout;
+};
+
+class MediaAccessTestHandler : public TestHandler, public CefPermissionHandler {
+ public:
+  MediaAccessTestHandler(TestSetup* tr, uint32_t request, uint32_t response)
+      : test_setup_(tr), request_(request), response_(response) {}
+
+  cef_return_value_t OnBeforeResourceLoad(
+      CefRefPtr<CefBrowser> browser,
+      CefRefPtr<CefFrame> frame,
+      CefRefPtr<CefRequest> request,
+      CefRefPtr<CefCallback> callback) override {
+    std::string newUrl = request->GetURL();
+    if (newUrl.find("tests/exit") != std::string::npos) {
+      if (newUrl.find("SUCCESS") != std::string::npos) {
+        EXPECT_FALSE(test_setup_->got_js_success);
+        test_setup_->got_js_success.yes();
+
+        auto dict = ParseURLData(newUrl);
+        if (dict->GetBool("got_video_track")) {
+          test_setup_->got_video.yes();
+        }
+        if (dict->GetBool("got_audio_track")) {
+          test_setup_->got_audio.yes();
+        }
+      } else if (newUrl.find("ERROR") != std::string::npos) {
+        EXPECT_FALSE(test_setup_->got_js_error);
+        test_setup_->got_js_error.yes();
+
+        auto dict = ParseURLData(newUrl);
+        test_setup_->js_error_str = dict->GetString("error_str");
+      } else if (newUrl.find("TIMEOUT") != std::string::npos) {
+        EXPECT_FALSE(test_setup_->got_js_timeout);
+        test_setup_->got_js_timeout.yes();
+      }
+      DestroyTest();
+      return RV_CANCEL;
+    }
+
+    return RV_CONTINUE;
+  }
+
+  void RunTest() override {
+    std::string page =
+        "<html><head>"
+        "<script>"
+        "function onResult(val, data) {"
+        " if(!data) {"
+        "   data = {};"
+        " }"
+        " document.location = "
+        "`https://tests/"
+        "exit?result=${val}&data=${encodeURIComponent(JSON.stringify(data))}`;"
+        "}"
+        "function runTest() {";
+
+    if (want_audio_device() || want_video_device()) {
+      page += std::string("navigator.mediaDevices.getUserMedia({audio: ") +
+              (want_audio_device() ? "true" : "false") +
+              ", video: " + (want_video_device() ? "true" : "false") + "})";
+    } else {
+      page += std::string("navigator.mediaDevices.getDisplayMedia({audio: ") +
+              (want_audio_desktop() ? "true" : "false") +
+              ", video: " + (want_video_desktop() ? "true" : "false") + "})";
+    }
+
+    page +=
+        ".then(function(stream) {"
+        "  onResult(`SUCCESS`, {got_audio_track: "
+        "stream.getAudioTracks().length "
+        "> 0, got_video_track: stream.getVideoTracks().length > 0});"
+        "})"
+        ".catch(function(err) {"
+        "  console.log(err.toString());"
+        "  onResult(`ERROR`, {error_str: err.toString()});"
+        "});"
+        "}";
+
+    if (test_setup_->deny_implicitly && IsChromeRuntimeEnabled()) {
+      // Default behavior with the Chrome runtime is to show a UI prompt, so add
+      // a timeout.
+      page += "setTimeout(() => { onResult(`TIMEOUT`); }, 1000);";
+    } else if (test_setup_->deny_with_navigation) {
+      // Cancel the pending request by navigating.
+      page += "setTimeout(() => { document.location = '" +
+              std::string(kMediaNavUrl) + "'; }, 1000);";
+    }
+
+    page +=
+        "</script>"
+        "</head><body>";
+
+    if (!test_setup_->needs_user_gesture) {
+      page += "<script>runTest();</script>";
+    }
+
+    page += "MEDIA ACCESS TEST</body></html>";
+
+    // Create the request context that will use an in-memory cache.
+    CefRequestContextSettings settings;
+    CefRefPtr<CefRequestContext> request_context =
+        CefRequestContext::CreateContext(settings, nullptr);
+
+    AddResource(kMediaUrl, page, "text/html");
+
+    if (test_setup_->deny_with_navigation) {
+      AddResource(kMediaNavUrl, "<html><body>Navigated</body></html>",
+                  "text/html");
+    }
+
+    // Create the browser.
+    CreateBrowser(kMediaUrl, request_context);
+
+    // Time out the test after a reasonable period of time.
+    SetTestTimeout();
+  }
+
+  CefRefPtr<CefPermissionHandler> GetPermissionHandler() override {
+    return this;
+  }
+
+  void OnLoadEnd(CefRefPtr<CefBrowser> browser,
+                 CefRefPtr<CefFrame> frame,
+                 int httpStatusCode) override {
+    if (test_setup_->deny_with_navigation) {
+      if (frame->GetURL().ToString() == kMediaNavUrl) {
+        DestroyTest();
+      }
+    } else if (test_setup_->needs_user_gesture) {
+      CefExecuteJavaScriptWithUserGestureForTests(frame, "runTest()");
+    }
+  }
+
+  bool OnRequestMediaAccessPermission(
+      CefRefPtr<CefBrowser> browser,
+      CefRefPtr<CefFrame> frame,
+      const CefString& requesting_origin,
+      uint32_t requested_permissions,
+      CefRefPtr<CefMediaAccessCallback> callback) override {
+    EXPECT_UI_THREAD();
+    EXPECT_TRUE(frame->IsMain());
+
+    EXPECT_EQ(requested_permissions, request_);
+    EXPECT_STREQ(kMediaOrigin, requesting_origin.ToString().c_str());
+
+    EXPECT_FALSE(test_setup_->got_request);
+    test_setup_->got_request.yes();
+
+    if (test_setup_->deny_implicitly) {
+      return false;
+    }
+
+    if (test_setup_->deny_with_navigation) {
+      // Handle the request, but never execute the callback.
+      callback_ = callback;
+      return true;
+    }
+
+    if (test_setup_->continue_async) {
+      CefPostTask(TID_UI, base::BindOnce(&CefMediaAccessCallback::Continue,
+                                         callback, response_));
+    } else {
+      callback->Continue(response_);
+    }
+    return true;
+  }
+
+  void OnMediaAccessChange(CefRefPtr<CefBrowser> browser,
+                           bool has_video_access,
+                           bool has_audio_access) override {
+    EXPECT_UI_THREAD();
+    EXPECT_EQ(got_video_device() || got_video_desktop(), has_video_access);
+    EXPECT_EQ(got_audio_device() || got_audio_desktop(), has_audio_access);
+    EXPECT_FALSE(test_setup_->got_change);
+    test_setup_->got_change.yes();
+  }
+
+  void DestroyTest() override {
+    callback_ = nullptr;
+
+    const size_t js_outcome_ct = test_setup_->got_js_success +
+                                 test_setup_->got_js_error +
+                                 test_setup_->got_js_timeout;
+    if (test_setup_->deny_with_navigation) {
+      // Expect no JS outcome.
+      EXPECT_EQ(0U, js_outcome_ct);
+    } else {
+      // Expect a single JS outcome.
+      EXPECT_EQ(1U, js_outcome_ct);
+    }
+
+    TestHandler::DestroyTest();
+  }
+
+ private:
+  bool want_audio_device() const {
+    return request_ & CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE;
+  }
+  bool want_video_device() const {
+    return request_ & CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE;
+  }
+  bool want_audio_desktop() const {
+    return request_ & CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE;
+  }
+  bool want_video_desktop() const {
+    return request_ & CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE;
+  }
+
+  bool got_audio_device() const {
+    return response_ & CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE;
+  }
+  bool got_video_device() const {
+    return response_ & CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE;
+  }
+  bool got_audio_desktop() const {
+    return response_ & CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE;
+  }
+  bool got_video_desktop() const {
+    return response_ & CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE;
+  }
+
+  CefRefPtr<CefDictionaryValue> ParseURLData(const std::string& url) {
+    const std::string& find_str = "&data=";
+    const std::string& data_string =
+        url.substr(url.find(find_str) + std::string(find_str).length());
+    const std::string& data_string_decoded = CefURIDecode(
+        data_string, false,
+        static_cast<cef_uri_unescape_rule_t>(
+            UU_SPACES | UU_URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS));
+    auto obj =
+        CefParseJSON(data_string_decoded, JSON_PARSER_ALLOW_TRAILING_COMMAS);
+    return obj->GetDictionary();
+  }
+
+  TestSetup* const test_setup_;
+  const uint32_t request_;
+  const uint32_t response_;
+
+  CefRefPtr<CefMediaAccessCallback> callback_;
+
+  IMPLEMENT_REFCOUNTING(MediaAccessTestHandler);
+};
+}  // namespace
+
+// Capture device tests
+TEST(MediaAccessTest, DeviceFailureWhenReturningFalse) {
+  TestSetup test_setup;
+  test_setup.deny_implicitly = true;
+
+  CefRefPtr<MediaAccessTestHandler> handler =
+      new MediaAccessTestHandler(&test_setup,
+                                 CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
+                                     CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
+                                 CEF_MEDIA_PERMISSION_NONE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  if (IsChromeRuntimeEnabled()) {
+    // Chrome shows a UI prompt, so we time out.
+    EXPECT_TRUE(test_setup.got_js_timeout);
+  } else {
+    EXPECT_TRUE(test_setup.got_js_error);
+    EXPECT_STREQ("NotAllowedError: Permission denied",
+                 test_setup.js_error_str.c_str());
+  }
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DeviceFailureWhenNoCallback) {
+  TestSetup test_setup;
+  test_setup.deny_with_navigation = true;
+
+  CefRefPtr<MediaAccessTestHandler> handler =
+      new MediaAccessTestHandler(&test_setup,
+                                 CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
+                                     CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
+                                 CEF_MEDIA_PERMISSION_NONE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  // No JS result.
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DeviceFailureWhenReturningNoPermission) {
+  TestSetup test_setup;
+
+  CefRefPtr<MediaAccessTestHandler> handler =
+      new MediaAccessTestHandler(&test_setup,
+                                 CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
+                                     CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
+                                 CEF_MEDIA_PERMISSION_NONE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Permission denied",
+               test_setup.js_error_str.c_str());
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DeviceFailureWhenReturningNoPermissionAsync) {
+  TestSetup test_setup;
+  test_setup.continue_async = true;
+
+  CefRefPtr<MediaAccessTestHandler> handler =
+      new MediaAccessTestHandler(&test_setup,
+                                 CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
+                                     CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
+                                 CEF_MEDIA_PERMISSION_NONE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Permission denied",
+               test_setup.js_error_str.c_str());
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DeviceFailureWhenRequestingAudioButReturningVideo) {
+  TestSetup test_setup;
+
+  CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
+      &test_setup, CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
+      CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Invalid state",
+               test_setup.js_error_str.c_str());
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DeviceFailureWhenRequestingVideoButReturningAudio) {
+  TestSetup test_setup;
+
+  CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
+      &test_setup, CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
+      CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Invalid state",
+               test_setup.js_error_str.c_str());
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DevicePartialFailureReturningVideo) {
+  TestSetup test_setup;
+
+  CefRefPtr<MediaAccessTestHandler> handler =
+      new MediaAccessTestHandler(&test_setup,
+                                 CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
+                                     CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
+                                 CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Invalid state",
+               test_setup.js_error_str.c_str());
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DevicePartialFailureReturningAudio) {
+  TestSetup test_setup;
+
+  CefRefPtr<MediaAccessTestHandler> handler =
+      new MediaAccessTestHandler(&test_setup,
+                                 CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
+                                     CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
+                                 CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Invalid state",
+               test_setup.js_error_str.c_str());
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture1) {
+  TestSetup test_setup;
+
+  CefRefPtr<MediaAccessTestHandler> handler =
+      new MediaAccessTestHandler(&test_setup,
+                                 CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
+                                     CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
+                                 CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Invalid state",
+               test_setup.js_error_str.c_str());
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture2) {
+  TestSetup test_setup;
+
+  CefRefPtr<MediaAccessTestHandler> handler =
+      new MediaAccessTestHandler(&test_setup,
+                                 CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
+                                     CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
+                                 CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Invalid state",
+               test_setup.js_error_str.c_str());
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture3) {
+  TestSetup test_setup;
+
+  CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
+      &test_setup, CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
+      CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Invalid state",
+               test_setup.js_error_str.c_str());
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture4) {
+  TestSetup test_setup;
+
+  CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
+      &test_setup, CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
+      CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Invalid state",
+               test_setup.js_error_str.c_str());
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture5) {
+  TestSetup test_setup;
+
+  CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
+      &test_setup, CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
+      CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Invalid state",
+               test_setup.js_error_str.c_str());
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture6) {
+  TestSetup test_setup;
+
+  CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
+      &test_setup, CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
+      CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Invalid state",
+               test_setup.js_error_str.c_str());
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DeviceSuccessAudioOnly) {
+  TestSetup test_setup;
+
+  CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
+      &test_setup, CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
+      CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_success);
+  EXPECT_TRUE(test_setup.got_audio);
+  EXPECT_FALSE(test_setup.got_video);
+  EXPECT_TRUE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DeviceSuccessVideoOnly) {
+  TestSetup test_setup;
+
+  CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
+      &test_setup, CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
+      CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_success);
+  EXPECT_FALSE(test_setup.got_audio);
+  EXPECT_TRUE(test_setup.got_video);
+  EXPECT_TRUE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DeviceSuccessAudioVideo) {
+  TestSetup test_setup;
+
+  CefRefPtr<MediaAccessTestHandler> handler =
+      new MediaAccessTestHandler(&test_setup,
+                                 CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE |
+                                     CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
+                                 CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE |
+                                     CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_success);
+  EXPECT_TRUE(test_setup.got_audio);
+  EXPECT_TRUE(test_setup.got_video);
+  EXPECT_TRUE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DeviceSuccessAudioVideoAsync) {
+  TestSetup test_setup;
+  test_setup.continue_async = true;
+
+  CefRefPtr<MediaAccessTestHandler> handler =
+      new MediaAccessTestHandler(&test_setup,
+                                 CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE |
+                                     CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
+                                 CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE |
+                                     CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_success);
+  EXPECT_TRUE(test_setup.got_audio);
+  EXPECT_TRUE(test_setup.got_video);
+  EXPECT_TRUE(test_setup.got_change);
+}
+
+// Screen capture tests
+TEST(MediaAccessTest, DesktopFailureWhenReturningNoPermission) {
+  TestSetup test_setup;
+  test_setup.needs_user_gesture = true;
+
+  CefRefPtr<MediaAccessTestHandler> handler =
+      new MediaAccessTestHandler(&test_setup,
+                                 CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE |
+                                     CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE,
+                                 CEF_MEDIA_PERMISSION_NONE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Permission denied",
+               test_setup.js_error_str.c_str());
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DesktopFailureWhenRequestingVideoButReturningAudio) {
+  TestSetup test_setup;
+  test_setup.needs_user_gesture = true;
+
+  CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
+      &test_setup, CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE,
+      CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Invalid state",
+               test_setup.js_error_str.c_str());
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DesktopPartialSuccessReturningVideo) {
+  TestSetup test_setup;
+  test_setup.needs_user_gesture = true;
+
+  CefRefPtr<MediaAccessTestHandler> handler =
+      new MediaAccessTestHandler(&test_setup,
+                                 CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE |
+                                     CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE,
+                                 CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_success);
+  EXPECT_FALSE(test_setup.got_audio);
+  EXPECT_TRUE(test_setup.got_video);
+  EXPECT_TRUE(test_setup.got_change);
+}
+
+TEST(MediaAccessTest, DesktopPartialFailureReturningAudio) {
+  TestSetup test_setup;
+  test_setup.needs_user_gesture = true;
+
+  CefRefPtr<MediaAccessTestHandler> handler =
+      new MediaAccessTestHandler(&test_setup,
+                                 CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE |
+                                     CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE,
+                                 CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_request);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Invalid state",
+               test_setup.js_error_str.c_str());
+  EXPECT_FALSE(test_setup.got_change);
+}
+
+// Entry point for creating media access browser test objects.
+// Called from client_app_delegates.cc.
+void CreateMediaAccessBrowserTests(
+    client::ClientAppBrowser::DelegateSet& delegates) {
+  delegates.insert(new MediaAccessBrowserTest);
+}
diff --git a/src/tests/ceftests/message_router_binary_unittest.cc b/src/tests/ceftests/message_router_binary_unittest.cc
new file mode 100644
index 0000000..bcd4f0d
--- /dev/null
+++ b/src/tests/ceftests/message_router_binary_unittest.cc
@@ -0,0 +1,136 @@
+// Copyright (c) 2023 The Chromium Embedded Framework 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 "tests/ceftests/message_router_unittest_utils.h"
+
+namespace {
+
+constexpr size_t kMsgSizeThresholdInBytes = 16000;
+
+class BinaryTestHandler final : public SingleLoadTestHandler {
+ public:
+  explicit BinaryTestHandler(size_t message_size)
+      : message_size_(message_size) {}
+
+  std::string GetMainHTML() override {
+    return "<html><body><script>\n"
+           "function generateRandomArrayBuffer(size) {\n"
+           "  const buffer = new ArrayBuffer(size);\n"
+           "  const uint8Array = new Uint8Array(buffer);\n"
+           "  for (let i = 0; i < uint8Array.length; i++) {\n"
+           "    uint8Array[i] = Math.floor(Math.random() * 256);\n"
+           "  }\n"
+           "  return buffer;\n"
+           "}\n"
+           "function isEqualArrayBuffers(left, right) {\n"
+           "  if (left.byteLength !== right.byteLength) { return false; }\n"
+           "  const leftView = new DataView(left);\n"
+           "  const rightView = new DataView(right);\n"
+           "  for (let i = 0; i < left.byteLength; i++) {\n"
+           "    if (leftView.getUint8(i) !== rightView.getUint8(i)) {\n"
+           "      return false;\n"
+           "    }\n"
+           "  }\n"
+           "  return true;\n"
+           "}\n"
+           "const request = generateRandomArrayBuffer(" +
+           std::to_string(message_size_) +
+           ")\n"
+           "window." +
+           std::string(kJSQueryFunc) +
+           "({\n  request: request,\n"
+           "  persistent: false,\n"
+           "  onSuccess: (response) => {\n"
+           "    if (!isEqualArrayBuffers(request, response)) {\n"
+           "      window.mrtNotify('error-ArrayBuffersDiffer');\n"
+           "    } else {\n"
+           "      window.mrtNotify('success');\n"
+           "    }\n"
+           "  },\n"
+           "  onFailure: (errorCode, errorMessage) => {\n"
+           "    window.mrtNotify('error-onFailureCalled');\n"
+           "  }\n"
+           "});\n</script></body></html>";
+  }
+
+  void OnNotify(CefRefPtr<CefBrowser> browser,
+                CefRefPtr<CefFrame> frame,
+                const std::string& message) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+
+    // OnNotify only be called once.
+    EXPECT_FALSE(got_notify_);
+    got_notify_.yes();
+
+    EXPECT_EQ("success", message);
+
+    DestroyTest();
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               CefRefPtr<const CefBinaryBuffer> request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+    EXPECT_NE(0, query_id);
+    EXPECT_FALSE(persistent);
+    EXPECT_EQ(message_size_, request->GetSize());
+
+    got_on_query_.yes();
+
+    callback->Success(request->GetData(), request->GetSize());
+
+    return true;
+  }
+
+  void DestroyTest() override {
+    EXPECT_TRUE(got_notify_);
+    EXPECT_TRUE(got_on_query_);
+
+    TestHandler::DestroyTest();
+  }
+
+ private:
+  const size_t message_size_;
+  TrackCallback got_on_query_;
+  TrackCallback got_notify_;
+};
+
+using TestHandlerPtr = CefRefPtr<BinaryTestHandler>;
+
+}  // namespace
+
+TEST(MessageRouterTest, BinaryMessageEmpty) {
+  const auto message_size = 0;
+  TestHandlerPtr handler = new BinaryTestHandler(message_size);
+  handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
+
+  handler->ExecuteTest();
+
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(MessageRouterTest, BinaryMessageUnderThresholdSize) {
+  const auto under_threshold = kMsgSizeThresholdInBytes - 1;
+  TestHandlerPtr handler = new BinaryTestHandler(under_threshold);
+  handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
+
+  handler->ExecuteTest();
+
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(MessageRouterTest, BinaryMessageOverThresholdSize) {
+  const auto over_threshold = kMsgSizeThresholdInBytes + 1;
+  TestHandlerPtr handler = new BinaryTestHandler(over_threshold);
+  handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
+
+  handler->ExecuteTest();
+
+  ReleaseAndWaitForDestructor(handler);
+}
diff --git a/src/tests/ceftests/message_router_harness_unittest.cc b/src/tests/ceftests/message_router_harness_unittest.cc
new file mode 100644
index 0000000..42ac033
--- /dev/null
+++ b/src/tests/ceftests/message_router_harness_unittest.cc
@@ -0,0 +1,81 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "tests/ceftests/message_router_unittest_utils.h"
+
+namespace {
+
+// Used to verify that the test harness (bound functions) behave correctly.
+class HarnessTestHandler : public SingleLoadTestHandler {
+ public:
+  HarnessTestHandler(bool test_success) : test_success_(test_success) {}
+
+  std::string GetMainHTML() override {
+    std::string html;
+    if (test_success_) {
+      // All assertions should pass.
+      html =
+          "<html><body><script>\n"
+          "var fail_ct = 0;\n"
+          "try { window.mrtAssertTotalCount(" LINESTR
+          ",0); } catch (e) { fail_ct++; }\n"
+          "try { window.mrtAssertBrowserCount(" LINESTR
+          ",0); } catch (e) { fail_ct++; }\n"
+          "try { window.mrtAssertContextCount(" LINESTR
+          ",0); } catch (e) { fail_ct++; }\n"
+          "window.mrtNotify('' + (fail_ct == 0));"
+          "</script></body></html>";
+    } else {
+      // All assertions should fail.
+      html =
+          "<html><body><script>\n"
+          "var fail_ct = 0;\n"
+          "try { window.mrtAssertTotalCount(" LINESTR
+          ",1); } catch (e) { fail_ct++; }\n"
+          "try { window.mrtAssertBrowserCount(" LINESTR
+          ",1); } catch (e) { fail_ct++; }\n"
+          "try { window.mrtAssertContextCount(" LINESTR
+          ",1); } catch (e) { fail_ct++; }\n"
+          "window.mrtNotify('' + (fail_ct == 3));"
+          "</script></body></html>";
+    }
+    return html;
+  }
+
+  void OnNotify(CefRefPtr<CefBrowser> browser,
+                CefRefPtr<CefFrame> frame,
+                const std::string& message) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+
+    got_done_.yes();
+    EXPECT_STREQ("true", message.c_str());
+    DestroyTest();
+  }
+
+  void DestroyTest() override {
+    EXPECT_TRUE(got_done_);
+    TestHandler::DestroyTest();
+  }
+
+ private:
+  const bool test_success_;
+  TrackCallback got_done_;
+};
+
+}  // namespace
+
+// Verify that the test harness works with successful assertions.
+TEST(MessageRouterTest, HarnessSuccess) {
+  CefRefPtr<HarnessTestHandler> handler = new HarnessTestHandler(true);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Verify that the test harness works with failed assertions.
+TEST(MessageRouterTest, HarnessFailure) {
+  CefRefPtr<HarnessTestHandler> handler = new HarnessTestHandler(false);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
diff --git a/src/tests/ceftests/message_router_multi_query_unittest.cc b/src/tests/ceftests/message_router_multi_query_unittest.cc
new file mode 100644
index 0000000..01579cc
--- /dev/null
+++ b/src/tests/ceftests/message_router_multi_query_unittest.cc
@@ -0,0 +1,2114 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "tests/ceftests/message_router_unittest_utils.h"
+
+namespace {
+
+const char kTestDomain1[] = "https://tests-mr1.com/";
+const char kTestDomain2[] = "https://tests-mr2.com/";
+const char kTestDomain3[] = "https://tests-mr3.com/";
+
+const char kMultiQueryRequestId[] = "request_id";
+const char kMultiQueryRepeatCt[] = "repeat_ct";
+const char kMultiQueryRequest[] = "request";
+const char kMultiQueryResponse[] = "response";
+const char kMultiQuerySuccess[] = "success";
+const char kMultiQueryError[] = "error";
+const char kMultiQueryErrorMessage[] = "errormsg";
+const int kMultiQueryPersistentResponseCount = 5;
+
+template <typename T>
+constexpr bool IsCefString() {
+  return std::is_same_v<std::remove_cv_t<T>, CefString>;
+}
+
+enum class TransferType {
+  STRING,
+  BINARY,
+};
+
+// Generates HTML and verifies results for multiple simultanious queries.
+class MultiQueryManager {
+ public:
+  enum TestType {
+    // Initiates a non-persistent query with a successful response.
+    // OnQuery and OnNotify will be called.
+    SUCCESS,
+
+    // Initiates a non-persistent query with a failure response.
+    // OnQuery and OnNotify will be called.
+    FAILURE,
+
+    // Initiates a persistent query with multiple successful responses.
+    // OnQuery, OnNotify and OnQueryCanceled will be called.
+    PERSISTENT_SUCCESS,
+
+    // Initiates a persistent query with multiple successful responses and one
+    // failure response.
+    // OnQuery and OnNotify will be called.
+    PERSISTENT_FAILURE,
+
+    // Initiates a non-persistent query that will be canceled via JavaScript.
+    // No JavaScript callbacks will be executed.
+    // OnQuery and OnQueryCanceled will be called.
+    CANCEL,
+
+    // Initiates a non-persistent query that will not be manually canceled.
+    // No JavaScript callbacks will be executed.
+    // OnQuery and OnQueryCanceled will be called.
+    AUTOCANCEL,
+
+    // Initiates a persistent query with multiple successful responses that will
+    // not be manually canceled.
+    // OnQuery, OnNotify and OnQueryCanceled will be called.
+    PERSISTENT_AUTOCANCEL,
+  };
+
+  class Observer {
+   public:
+    // Called when all manual queries are complete.
+    virtual void OnManualQueriesCompleted(MultiQueryManager* manager) {}
+
+    // Called when all queries are complete.
+    virtual void OnAllQueriesCompleted(MultiQueryManager* manager) {}
+
+   protected:
+    virtual ~Observer() {}
+  };
+
+  MultiQueryManager(const std::string& label,
+                    bool synchronous,
+                    int id_offset = 0,
+                    TransferType transfer_type = TransferType::STRING)
+      : label_(label),
+        synchronous_(synchronous),
+        id_offset_(id_offset),
+        transfer_type_(transfer_type),
+        finalized_(false),
+        running_(false),
+        manual_total_(0),
+        received_count_(0),
+        manual_complete_count_(0),
+        auto_complete_count_(0),
+        will_cancel_by_removing_handler_(false),
+        weak_ptr_factory_(this) {}
+
+  std::string label() const { return label_; }
+
+  void AddObserver(Observer* observer) {
+    EXPECT_FALSE(running_);
+    observer_set_.insert(observer);
+  }
+
+  void RemoveObserver(Observer* observer) {
+    EXPECT_FALSE(running_);
+    EXPECT_TRUE(observer_set_.erase(observer));
+  }
+
+  // Can be called from any thread, but should always be called from the same
+  // thread.
+  void AddTestQuery(TestType type) {
+    EXPECT_FALSE(finalized_);
+    test_query_vector_.push_back(TestQuery(type));
+    if (!IsAuto(type)) {
+      manual_total_++;
+    }
+  }
+
+  // Must be called after AddTestQuery and before the manager is used.
+  void Finalize() {
+    EXPECT_FALSE(finalized_);
+    finalized_ = true;
+  }
+
+  // Call after all manual queries have completed if you intend to cancel auto
+  // queries by removing the handler.
+  void WillCancelByRemovingHandler() {
+    EXPECT_TRUE(IsManualComplete());
+    will_cancel_by_removing_handler_ = true;
+  }
+
+  std::string GetHTML(bool assert_total, bool assert_browser) const {
+    EXPECT_TRUE(finalized_);
+    EXPECT_FALSE(running_);
+
+    std::string html;
+
+    html = "<html><body>" + label_ + "<script>\n";
+
+    // No requests should exist.
+    if (assert_total) {
+      html += "window.mrtAssertTotalCount(" LINESTR ",0);\n";
+    }
+    if (assert_browser) {
+      html += "window.mrtAssertBrowserCount(" LINESTR ",0);\n";
+    }
+    html += "window.mrtAssertContextCount(" LINESTR ",0);\n";
+
+    if (synchronous_) {
+      // Run all of the queries synchronously. None will complete before the
+      // last one begins.
+      for (size_t i = 0; i < test_query_vector_.size(); ++i) {
+        const TestQuery& query = test_query_vector_[i];
+        html += GetQueryHTML(static_cast<int>(i), query);
+      }
+
+      const int total_ct = static_cast<int>(test_query_vector_.size());
+
+      // Pending requests should match the total created.
+      const std::string& total_val = GetIntString(total_ct);
+      if (assert_total) {
+        html += "window.mrtAssertTotalCount(" LINESTR "," + total_val + ");\n";
+      }
+      if (assert_browser) {
+        html +=
+            "window.mrtAssertBrowserCount(" LINESTR "," + total_val + ");\n";
+      }
+      html += "window.mrtAssertContextCount(" LINESTR "," + total_val + ");\n";
+
+      int cancel_ct = 0;
+
+      // Cancel all of the queries with type CANCEL.
+      for (size_t i = 0; i < test_query_vector_.size(); ++i) {
+        const TestQuery& query = test_query_vector_[i];
+        if (query.type == CANCEL) {
+          html += GetCancelHTML(static_cast<int>(i), query);
+          cancel_ct++;
+        }
+      }
+
+      if (cancel_ct > 0) {
+        // Pending requests should match the total not canceled.
+        const std::string& cancel_val = GetIntString(total_ct - cancel_ct);
+        if (assert_total) {
+          html +=
+              "window.mrtAssertTotalCount(" LINESTR "," + cancel_val + ");\n";
+        }
+        if (assert_browser) {
+          html +=
+              "window.mrtAssertBrowserCount(" LINESTR "," + cancel_val + ");\n";
+        }
+        html +=
+            "window.mrtAssertContextCount(" LINESTR "," + cancel_val + ");\n";
+      }
+    } else {
+      // Run all of the queries asynchronously. Some may complete before
+      // others begin.
+      for (size_t i = 0; i < test_query_vector_.size(); ++i) {
+        const TestQuery& query = test_query_vector_[i];
+
+        const int index = static_cast<int>(i);
+
+        // Each request is delayed by 10ms from the previous request.
+        const std::string& delay_val = GetIntString(index);
+        const std::string& query_html = GetQueryHTML(index, query);
+
+        html += "window.setTimeout(function() {\n" + query_html;
+
+        if (query.type == CANCEL) {
+          // Cancel the query asynchronously with a 10ms delay.
+          const std::string& request_id_var =
+              GetIDString(kMultiQueryRequestId, index);
+          html +=
+              "  window.setTimeout(function() {\n"
+              "    window.mrtQueryCancel(" +
+              request_id_var +
+              ");\n"
+              "  }, 1);\n";
+        }
+
+        html += "\n}, " + delay_val + ");\n";
+      }
+    }
+
+    html += "</script></body></html>";
+
+    return html;
+  }
+
+  void OnNotify(CefRefPtr<CefBrowser> browser,
+                CefRefPtr<CefFrame> frame,
+                const std::string& message) {
+    EXPECT_TRUE(finalized_);
+    EXPECT_UI_THREAD();
+
+    if (!running_) {
+      running_ = true;
+    }
+
+    EXPECT_TRUE(browser.get());
+    EXPECT_TRUE(frame.get());
+
+    std::string value;
+    int index = 0;
+    EXPECT_TRUE(SplitIDString(message, &value, &index));
+
+    TestQuery& query = test_query_vector_[index];
+
+    // Verify that browser and frame are the same.
+    EXPECT_EQ(query.browser_id, browser->GetIdentifier()) << index;
+    EXPECT_EQ(query.frame_id, frame->GetIdentifier()) << index;
+
+    // Verify a successful/expected result.
+    if (will_cancel_by_removing_handler_) {
+      // Auto queries receive an onFailure callback which will notify with error
+      // when the handler is removed.
+      EXPECT_STREQ(kMultiQueryError, value.c_str()) << index;
+      EXPECT_TRUE(IsAuto(query.type)) << index;
+      EXPECT_TRUE(query.got_query) << index;
+      if (query.type == PERSISTENT_AUTOCANCEL) {
+        EXPECT_TRUE(query.got_success) << index;
+      } else {
+        EXPECT_FALSE(query.got_success) << index;
+      }
+
+      query.got_error.yes();
+
+      // There's a race between OnQueryCanceled and OnNotification. Only call
+      // OnQueryCompleted a single time.
+      if (query.got_query_canceled) {
+        OnQueryCompleted(query.type);
+      }
+    } else {
+      EXPECT_STREQ(kMultiQuerySuccess, value.c_str()) << index;
+      EXPECT_TRUE(WillNotify(query.type)) << index;
+      EXPECT_TRUE(query.got_query) << index;
+      EXPECT_FALSE(query.got_query_canceled) << index;
+      EXPECT_FALSE(query.got_success) << index;
+
+      query.got_success.yes();
+
+      // PERSISTENT_AUTOCANCEL doesn't call OnReceiveCompleted from OnQuery.
+      if (query.type == PERSISTENT_AUTOCANCEL) {
+        OnReceiveCompleted(query.type);
+      }
+
+      // Call OnQueryCompleted for types that don't get OnQueryCanceled.
+      if (!WillCancel(query.type)) {
+        OnQueryCompleted(query.type);
+      }
+    }
+  }
+
+  template <class RequestType>
+  bool OnQueryImpl(CefRefPtr<CefBrowser> browser,
+                   CefRefPtr<CefFrame> frame,
+                   int64_t query_id,
+                   const RequestType& request,
+                   bool persistent,
+                   CefRefPtr<CefMessageRouterBrowserSide::Callback> callback) {
+    EXPECT_TRUE(finalized_);
+    EXPECT_UI_THREAD();
+
+    if (!running_) {
+      running_ = true;
+    }
+
+    EXPECT_TRUE(browser.get());
+    EXPECT_TRUE(frame.get());
+    EXPECT_NE(0, query_id);
+
+    std::string value;
+    int index = 0;
+    EXPECT_TRUE(SplitIDString(request, &value, &index));
+
+    TestQuery& query = test_query_vector_[index];
+
+    if (IsPersistent(query.type)) {
+      EXPECT_TRUE(persistent);
+    } else {
+      EXPECT_FALSE(persistent);
+    }
+
+    // Verify expected request.
+    EXPECT_STREQ(kMultiQueryRequest, value.c_str()) << index;
+
+    // Verify that call order is correct.
+    EXPECT_FALSE(query.got_query) << index;
+    EXPECT_FALSE(query.got_query_canceled) << index;
+    EXPECT_FALSE(query.got_success) << index;
+    EXPECT_FALSE(query.got_error) << index;
+
+    query.got_query.yes();
+
+    query.browser_id = browser->GetIdentifier();
+    query.frame_id = frame->GetIdentifier();
+    query.is_main_frame = frame->IsMain();
+
+    if (query.type == SUCCESS) {
+      // Send the single success response.
+      if constexpr (IsCefString<RequestType>()) {
+        const auto response = GetIDString(kMultiQueryResponse, index);
+        callback->Success(response);
+      } else {
+        const auto response = GetIDBinary(kMultiQueryResponse, index);
+        callback->Success(response.data(), response.size());
+      }
+    } else if (IsPersistent(query.type)) {
+      // Send the required number of successful responses.
+      if constexpr (IsCefString<RequestType>()) {
+        const auto response = GetIDString(kMultiQueryResponse, index);
+        for (int i = 0; i < kMultiQueryPersistentResponseCount; ++i) {
+          callback->Success(response);
+        }
+      } else {
+        const auto response = GetIDBinary(kMultiQueryResponse, index);
+        for (int i = 0; i < kMultiQueryPersistentResponseCount; ++i) {
+          callback->Success(response.data(), response.size());
+        }
+      }
+    }
+
+    if (WillFail(query.type)) {
+      // Send the single failure response.
+      callback->Failure(index, GetIDString(kMultiQueryErrorMessage, index));
+    }
+
+    if (WillCancel(query.type)) {
+      // Hold onto the callback until the query is canceled.
+      query.query_id = query_id;
+      query.callback = callback;
+    }
+
+    // PERSISTENT_AUTOCANCEL will call OnReceiveCompleted once the success
+    // notification is received.
+    if (query.type != PERSISTENT_AUTOCANCEL) {
+      OnReceiveCompleted(query.type);
+    }
+
+    return true;
+  }
+
+  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame,
+                       int64_t query_id) {
+    EXPECT_TRUE(finalized_);
+    EXPECT_UI_THREAD();
+
+    if (!running_) {
+      running_ = true;
+    }
+
+    EXPECT_TRUE(browser.get());
+    EXPECT_TRUE(frame.get());
+    EXPECT_NE(0, query_id);
+
+    bool found = false;
+    for (size_t i = 0; i < test_query_vector_.size(); ++i) {
+      TestQuery& query = test_query_vector_[i];
+      if (query.query_id == query_id) {
+        // Verify that browser and frame are the same.
+        EXPECT_EQ(query.browser_id, browser->GetIdentifier()) << i;
+        if (query.is_main_frame) {
+          EXPECT_TRUE(frame->IsMain()) << i;
+        } else {
+          EXPECT_FALSE(frame->IsMain()) << i;
+          EXPECT_EQ(query.frame_id, frame->GetIdentifier()) << i;
+        }
+
+        // Verify a successful/expected result.
+        EXPECT_TRUE(WillCancel(query.type)) << i;
+        EXPECT_TRUE(query.callback.get()) << i;
+
+        // Release the callback.
+        query.callback = nullptr;
+
+        // Verify that call order is correct.
+        EXPECT_TRUE(query.got_query) << i;
+
+        if (query.type == CANCEL || query.type == AUTOCANCEL) {
+          // No JavaScript onSuccess callback executes.
+          EXPECT_FALSE(query.got_success) << i;
+        } else {
+          // JavaScript onSuccess does execute before cancellation.
+          EXPECT_TRUE(query.got_success) << i;
+        }
+
+        query.got_query_canceled.yes();
+
+        if (will_cancel_by_removing_handler_) {
+          // There's a race between OnQueryCanceled and OnNotification. Only
+          // call OnQueryCompleted a single time.
+          if (query.got_error) {
+            OnQueryCompleted(query.type);
+          }
+        } else {
+          EXPECT_FALSE(query.got_error) << i;
+
+          // Cancellation is always completion.
+          OnQueryCompleted(query.type);
+        }
+
+        found = true;
+        break;
+      }
+    }
+    EXPECT_TRUE(found);
+  }
+
+  // Asserts that all queries have completed.
+  void AssertAllComplete() const {
+    EXPECT_TRUE(finalized_);
+    EXPECT_FALSE(running_);
+    EXPECT_UI_THREAD();
+
+    for (size_t i = 0; i < test_query_vector_.size(); ++i) {
+      const TestQuery& query = test_query_vector_[i];
+      EXPECT_TRUE(query.got_query) << i;
+
+      if (WillCancel(query.type)) {
+        EXPECT_TRUE(query.got_query_canceled) << i;
+      } else {
+        EXPECT_FALSE(query.got_query_canceled) << i;
+      }
+
+      if (WillNotify(query.type)) {
+        EXPECT_TRUE(query.got_success) << i;
+      } else {
+        EXPECT_FALSE(query.got_success) << i;
+      }
+
+      if (IsAuto(query.type) && will_cancel_by_removing_handler_) {
+        EXPECT_TRUE(query.got_error);
+      } else {
+        EXPECT_FALSE(query.got_error);
+      }
+
+      EXPECT_FALSE(query.callback.get()) << i;
+    }
+  }
+
+  // Returns true if all manual queries have completed.
+  bool IsManualComplete() const {
+    EXPECT_TRUE(finalized_);
+    EXPECT_UI_THREAD();
+
+    return (manual_complete_count_ == manual_total_);
+  }
+
+  // Returns true if all queries have completed.
+  bool IsAllComplete() const {
+    EXPECT_TRUE(finalized_);
+    EXPECT_UI_THREAD();
+
+    return (manual_complete_count_ + auto_complete_count_ ==
+            static_cast<int>(test_query_vector_.size()));
+  }
+
+  bool HasAutoQueries() const {
+    return (manual_total_ != static_cast<int>(test_query_vector_.size()));
+  }
+
+ private:
+  struct TestQuery {
+    explicit TestQuery(TestType test_type)
+        : type(test_type),
+          browser_id(0),
+          frame_id(0),
+          is_main_frame(false),
+          query_id(0) {}
+
+    TestType type;
+
+    // Set in OnQuery and verified in OnNotify or OnQueryCanceled.
+    int browser_id;
+    int64_t frame_id;
+    bool is_main_frame;
+
+    // Used when a query is canceled.
+    int64_t query_id;
+    CefRefPtr<CefMessageRouterBrowserSide::Callback> callback;
+
+    TrackCallback got_query;
+    TrackCallback got_query_canceled;
+    TrackCallback got_success;
+    TrackCallback got_error;
+  };
+
+  class NotifyTask : public CefTask {
+   public:
+    NotifyTask(base::WeakPtr<MultiQueryManager> weak_ptr, bool notify_all)
+        : weak_ptr_(weak_ptr), notify_all_(notify_all) {}
+
+    void Execute() override {
+      if (weak_ptr_) {
+        if (notify_all_) {
+          weak_ptr_->NotifyAllQueriesCompleted();
+        } else {
+          weak_ptr_->NotifyManualQueriesCompleted();
+        }
+      }
+    }
+
+   private:
+    base::WeakPtr<MultiQueryManager> weak_ptr_;
+    const bool notify_all_;
+
+    IMPLEMENT_REFCOUNTING(NotifyTask);
+  };
+
+  static bool IsAuto(TestType type) {
+    return (type == AUTOCANCEL || type == PERSISTENT_AUTOCANCEL);
+  }
+
+  static bool IsPersistent(TestType type) {
+    return (type == PERSISTENT_SUCCESS || type == PERSISTENT_FAILURE ||
+            type == PERSISTENT_AUTOCANCEL);
+  }
+
+  static bool WillFail(TestType type) {
+    return (type == FAILURE || type == PERSISTENT_FAILURE);
+  }
+
+  static bool WillCancel(TestType type) {
+    return (type == PERSISTENT_SUCCESS || type == CANCEL ||
+            type == AUTOCANCEL || type == PERSISTENT_AUTOCANCEL);
+  }
+
+  static bool WillNotify(TestType type) {
+    return (type == SUCCESS || type == PERSISTENT_SUCCESS || type == FAILURE ||
+            type == PERSISTENT_FAILURE || type == PERSISTENT_AUTOCANCEL);
+  }
+
+  void OnReceiveCompleted(TestType type) {
+    const int total_count = static_cast<int>(test_query_vector_.size());
+    if (++received_count_ == total_count && manual_total_ == 0) {
+      // There aren't any manual queries so notify here.
+      CefPostTask(TID_UI,
+                  new NotifyTask(weak_ptr_factory_.GetWeakPtr(), false));
+    }
+  }
+
+  void OnQueryCompleted(TestType type) {
+    const int total_count = static_cast<int>(test_query_vector_.size());
+    EXPECT_LT(manual_complete_count_ + auto_complete_count_, total_count);
+    EXPECT_LE(manual_complete_count_, manual_total_);
+
+    const bool is_auto = IsAuto(type);
+    if (is_auto) {
+      auto_complete_count_++;
+    } else if (++manual_complete_count_ == manual_total_) {
+      CefPostTask(TID_UI,
+                  new NotifyTask(weak_ptr_factory_.GetWeakPtr(), false));
+    }
+
+    if (auto_complete_count_ + manual_complete_count_ == total_count) {
+      running_ = false;
+      CefPostTask(TID_UI, new NotifyTask(weak_ptr_factory_.GetWeakPtr(), true));
+    }
+  }
+
+  void NotifyManualQueriesCompleted() {
+    if (observer_set_.empty()) {
+      return;
+    }
+
+    // Use a copy of the set in case an Observer is removed while we're
+    // iterating.
+    ObserverSet observer_set = observer_set_;
+
+    ObserverSet::const_iterator it = observer_set.begin();
+    for (; it != observer_set.end(); ++it) {
+      (*it)->OnManualQueriesCompleted(this);
+    }
+  }
+
+  void NotifyAllQueriesCompleted() {
+    if (observer_set_.empty()) {
+      return;
+    }
+
+    // Use a copy of the set in case an Observer is removed while we're
+    // iterating.
+    ObserverSet observer_set = observer_set_;
+
+    ObserverSet::const_iterator it = observer_set.begin();
+    for (; it != observer_set.end(); ++it) {
+      (*it)->OnAllQueriesCompleted(this);
+    }
+  }
+
+  std::string GetQueryHTML(const int index, const TestQuery& query) const {
+    const std::string& request_id_var =
+        GetIDString(kMultiQueryRequestId, index);
+    const std::string& repeat_ct_var = GetIDString(kMultiQueryRepeatCt, index);
+    const std::string& request_str =
+        GetIDString(std::string(kMultiQueryRequest) + ":", index);
+    const std::string& success_val =
+        GetIDString(std::string(kMultiQuerySuccess) + ":", index);
+    const std::string& error_val =
+        GetIDString(std::string(kMultiQueryError) + ":", index);
+
+    const std::string request_val =
+        transfer_type_ == TransferType::BINARY
+            ? ("new TextEncoder().encode('" + request_str + "').buffer")
+            : "'" + request_str + "'";
+
+    const std::string response_conversion =
+        transfer_type_ == TransferType::BINARY
+            ? "    const decoder = new TextDecoder('utf-8');\n"
+              "    const message = decoder.decode(response);\n"
+            : "    const message = response;\n";
+
+    std::string html;
+
+    const bool persistent = IsPersistent(query.type);
+
+    if (persistent) {
+      html += "var " + repeat_ct_var + " = 0;\n";
+    }
+
+    html += "var " + request_id_var +
+            " = window.mrtQuery({\n"
+            "  request: " +
+            request_val +
+            ",\n  persistent: " + (persistent ? "true" : "false") + ",\n";
+
+    if (query.type == SUCCESS) {
+      const std::string& response_val = GetIDString(kMultiQueryResponse, index);
+
+      html += "  onSuccess: function(response) {\n" + response_conversion +
+              "    if (message == '" + response_val +
+              "')\n"
+              "      window.mrtNotify('" +
+              success_val +
+              "');\n"
+              "    else\n"
+              "      window.mrtNotify('" +
+              error_val +
+              "');\n"
+              "  },\n"
+              "  onFailure: function(error_code, error_message) {\n"
+              "    window.mrtNotify('" +
+              error_val +
+              "');\n"
+              "  }\n";
+    } else if (query.type == FAILURE) {
+      const std::string& error_code_val = GetIntString(index);
+      const std::string& error_message_val =
+          GetIDString(kMultiQueryErrorMessage, index);
+
+      html +=
+          "  onSuccess: function(response) {\n"
+          "    window.mrtNotify('" +
+          error_val +
+          "');\n"
+          "  },\n"
+          "  onFailure: function(error_code, error_message) {\n"
+          "    if (error_code == " +
+          error_code_val + " && error_message == '" + error_message_val +
+          "')\n"
+          "      window.mrtNotify('" +
+          success_val +
+          "');\n"
+          "    else\n"
+          "      window.mrtNotify('" +
+          error_val +
+          "');\n"
+          "  }\n";
+    } else if (query.type == PERSISTENT_SUCCESS ||
+               query.type == PERSISTENT_AUTOCANCEL) {
+      const std::string& response_val = GetIDString(kMultiQueryResponse, index);
+      const std::string& repeat_ct =
+          GetIntString(kMultiQueryPersistentResponseCount);
+
+      html += "  onSuccess: function(response) {\n" + response_conversion +
+              "    if (message == '" + response_val +
+              "') {\n"
+              // Should get repeat_ct number of successful responses.
+              "      if (++" +
+              repeat_ct_var + " == " + repeat_ct +
+              ") {\n"
+              "        window.mrtNotify('" +
+              success_val + "');\n";
+
+      if (query.type == PERSISTENT_SUCCESS) {
+        // Manually cancel the request.
+        html += "        window.mrtQueryCancel(" + request_id_var + ");\n";
+      }
+
+      html +=
+          "      }\n"
+          "    } else {\n"
+          "      window.mrtNotify('" +
+          error_val +
+          "');\n"
+          "    }\n"
+          "  },\n"
+          "  onFailure: function(error_code, error_message) {\n"
+          "    window.mrtNotify('" +
+          error_val +
+          "');\n"
+          "  }\n";
+    } else if (query.type == PERSISTENT_FAILURE) {
+      const std::string& error_code_val = GetIntString(index);
+      const std::string& error_message_val =
+          GetIDString(kMultiQueryErrorMessage, index);
+      const std::string& repeat_ct =
+          GetIntString(kMultiQueryPersistentResponseCount);
+
+      html +=
+          "  onSuccess: function(response) {\n"
+          // Should get some successful responses before failure.
+          "    if (++" +
+          repeat_ct_var + " > " + repeat_ct +
+          ") {\n"
+          "      window.mrtNotify('" +
+          error_val +
+          "');\n"
+          "    }\n"
+          "  },\n"
+          "  onFailure: function(error_code, error_message) {\n"
+          "    if (error_code == " +
+          error_code_val + " && error_message == '" + error_message_val +
+          "'"
+          " && " +
+          repeat_ct_var + " == " + repeat_ct +
+          ")\n"
+          "      window.mrtNotify('" +
+          success_val +
+          "');\n"
+          "    else\n"
+          "      window.mrtNotify('" +
+          error_val +
+          "');\n"
+          "  }\n";
+    } else if (query.type == CANCEL || query.type == AUTOCANCEL) {
+      html +=
+          "  onSuccess: function(response) {\n"
+          "    window.mrtNotify('" +
+          error_val +
+          "');\n"
+          "  },\n"
+          "  onFailure: function(error_code, error_message) {\n"
+          "    window.mrtNotify('" +
+          error_val +
+          "');\n"
+          "  }\n";
+    }
+
+    html += "});\n";
+
+    return html;
+  }
+
+  std::string GetCancelHTML(const int index, const TestQuery& query) const {
+    const std::string& request_id_var =
+        GetIDString(kMultiQueryRequestId, index);
+    return "window.mrtQueryCancel(" + request_id_var + ");\n";
+  }
+
+  std::string GetIDString(const std::string& prefix, int index) const {
+    EXPECT_TRUE(!prefix.empty());
+    return prefix + std::to_string(GetIDFromIndex(index));
+  }
+
+  std::vector<uint8_t> GetIDBinary(const std::string& prefix, int index) const {
+    auto str = GetIDString(prefix, index);
+    return std::vector<uint8_t>(str.begin(), str.end());
+  }
+
+  bool SplitIDString(const std::string& str,
+                     std::string* value,
+                     int* index) const {
+    size_t pos = str.find(':');
+    if (pos != std::string::npos) {
+      *value = str.substr(0, pos);
+      *index = GetIndexFromID(atoi(str.substr(pos + 1).c_str()));
+      return (*index >= 0 &&
+              *index < static_cast<int>(test_query_vector_.size()));
+    }
+
+    return false;
+  }
+
+  bool SplitIDString(const CefRefPtr<const CefBinaryBuffer>& request,
+                     std::string* value,
+                     int* index) const {
+    const size_t string_len =
+        request->GetSize() / sizeof(std::string::value_type);
+    const auto* src =
+        static_cast<const std::string::value_type*>(request->GetData());
+    CefString result;
+    result.FromString(src, string_len);
+
+    return SplitIDString(result, value, index);
+  }
+
+  std::string GetIntString(int val) const {
+    std::stringstream ss;
+    ss << val;
+    return ss.str();
+  }
+
+  int GetIDFromIndex(int index) const { return id_offset_ + index; }
+  int GetIndexFromID(int id) const { return id - id_offset_; }
+
+  const std::string label_;
+  const bool synchronous_;
+  const int id_offset_;
+  const TransferType transfer_type_;
+
+  typedef std::vector<TestQuery> TestQueryVector;
+  TestQueryVector test_query_vector_;
+
+  typedef std::set<Observer*> ObserverSet;
+  ObserverSet observer_set_;
+
+  // Set to true after all queries have been added.
+  bool finalized_;
+  // Set to true while queries are pending.
+  bool running_;
+
+  // Total number of queries that will manually complete.
+  int manual_total_;
+
+  // Number of queries that have been received.
+  int received_count_;
+
+  // Number of queries that have completed successfully.
+  int manual_complete_count_;
+  int auto_complete_count_;
+
+  // If true any pending queries will receive an onFailure callback in addition
+  // to be canceled.
+  bool will_cancel_by_removing_handler_;
+
+  // Should always be the last member.
+  base::WeakPtrFactory<MultiQueryManager> weak_ptr_factory_;
+};
+
+void MakeTestQueries(MultiQueryManager* manager,
+                     bool some,
+                     int many_count = 200) {
+  if (some) {
+    // Test some queries of arbitrary types.
+    // Use a hard-coded list so the behavior is deterministic across test runs.
+    MultiQueryManager::TestType types[] = {
+        MultiQueryManager::PERSISTENT_AUTOCANCEL,
+        MultiQueryManager::SUCCESS,
+        MultiQueryManager::AUTOCANCEL,
+        MultiQueryManager::PERSISTENT_FAILURE,
+        MultiQueryManager::CANCEL,
+        MultiQueryManager::FAILURE,
+        MultiQueryManager::AUTOCANCEL,
+        MultiQueryManager::SUCCESS,
+        MultiQueryManager::PERSISTENT_SUCCESS,
+        MultiQueryManager::SUCCESS,
+        MultiQueryManager::PERSISTENT_AUTOCANCEL,
+        MultiQueryManager::CANCEL,
+        MultiQueryManager::PERSISTENT_SUCCESS,
+        MultiQueryManager::FAILURE,
+    };
+    for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) {
+      manager->AddTestQuery(types[i]);
+    }
+  } else {
+    // Test every type of query.
+    for (int i = 0; i < many_count; ++i) {
+      MultiQueryManager::TestType type = MultiQueryManager::SUCCESS;
+      switch (i % 7) {
+        case 0:
+          type = MultiQueryManager::SUCCESS;
+          break;
+        case 1:
+          type = MultiQueryManager::FAILURE;
+          break;
+        case 2:
+          type = MultiQueryManager::PERSISTENT_SUCCESS;
+          break;
+        case 3:
+          type = MultiQueryManager::PERSISTENT_FAILURE;
+          break;
+        case 4:
+          type = MultiQueryManager::CANCEL;
+          break;
+        case 5:
+          type = MultiQueryManager::AUTOCANCEL;
+          break;
+        case 6:
+          type = MultiQueryManager::PERSISTENT_AUTOCANCEL;
+          break;
+      }
+      manager->AddTestQuery(type);
+    }
+  }
+  manager->Finalize();
+}
+
+// Test multiple queries in a single page load with a single frame.
+class MultiQuerySingleFrameTestHandler : public SingleLoadTestHandler,
+                                         public MultiQueryManager::Observer {
+ public:
+  enum CancelType {
+    CANCEL_BY_NAVIGATION,
+    CANCEL_BY_REMOVING_HANDLER,
+    CANCEL_BY_CLOSING_BROWSER,
+  };
+
+  MultiQuerySingleFrameTestHandler(
+      bool synchronous,
+      TransferType transfer_type,
+      CancelType cancel_type = CANCEL_BY_NAVIGATION)
+      : manager_(std::string(), synchronous, 0, transfer_type),
+        cancel_type_(cancel_type) {
+    manager_.AddObserver(this);
+  }
+
+  std::string GetMainHTML() override { return manager_.GetHTML(true, true); }
+
+  void OnNotify(CefRefPtr<CefBrowser> browser,
+                CefRefPtr<CefFrame> frame,
+                const std::string& message) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+
+    manager_.OnNotify(browser, frame, message);
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               const CefString& request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+
+    return manager_.OnQueryImpl(browser, frame, query_id, request, persistent,
+                                callback);
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               CefRefPtr<const CefBinaryBuffer> request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+
+    return manager_.OnQueryImpl(browser, frame, query_id, request, persistent,
+                                callback);
+  }
+
+  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame,
+                       int64_t query_id) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+
+    manager_.OnQueryCanceled(browser, frame, query_id);
+  }
+
+  void OnManualQueriesCompleted(MultiQueryManager* manager) override {
+    EXPECT_EQ(manager, &manager_);
+    if (manager_.HasAutoQueries()) {
+      if (cancel_type_ == CANCEL_BY_NAVIGATION) {
+        // Navigate somewhere else to terminate the auto queries.
+        GetBrowser()->GetMainFrame()->LoadURL(std::string(kTestDomain1) +
+                                              "cancel.html");
+      } else if (cancel_type_ == CANCEL_BY_REMOVING_HANDLER) {
+        // Change the expected behavior in the manager.
+        manager_.WillCancelByRemovingHandler();
+        GetRouter()->RemoveHandler(this);
+        // All queries should be immediately canceled.
+        AssertQueryCount(nullptr, nullptr, 0);
+      } else if (cancel_type_ == CANCEL_BY_CLOSING_BROWSER) {
+        // Change the expected behavior in the handler.
+        SetSignalTestCompletionCount(1U);
+        CloseBrowser(GetBrowser(), false);
+      }
+    }
+  }
+
+  void OnAllQueriesCompleted(MultiQueryManager* manager) override {
+    EXPECT_EQ(manager, &manager_);
+
+    // All queries should be canceled.
+    AssertQueryCount(nullptr, nullptr, 0);
+
+    DestroyTest();
+
+    if (!AllowTestCompletionWhenAllBrowsersClose()) {
+      // Complete asynchronously so the call stack has a chance to unwind.
+      CefPostTask(
+          TID_UI,
+          base::BindOnce(
+              &MultiQuerySingleFrameTestHandler::SignalTestCompletion, this));
+    }
+  }
+
+  void DestroyTest() override {
+    manager_.AssertAllComplete();
+    TestHandler::DestroyTest();
+  }
+
+  MultiQueryManager* GetManager() { return &manager_; }
+
+ private:
+  MultiQueryManager manager_;
+  const CancelType cancel_type_;
+};
+
+}  // namespace
+
+#define MQSF_TYPE_TEST(name, type, synchronous)                     \
+  TEST(MessageRouterTest, MultiQuerySingleFrame##name##String) {    \
+    CefRefPtr<MultiQuerySingleFrameTestHandler> handler =           \
+        new MultiQuerySingleFrameTestHandler(synchronous,           \
+                                             TransferType::STRING); \
+    MultiQueryManager* manager = handler->GetManager();             \
+    manager->AddTestQuery(MultiQueryManager::type);                 \
+    manager->Finalize();                                            \
+    handler->ExecuteTest();                                         \
+    ReleaseAndWaitForDestructor(handler);                           \
+  }                                                                 \
+                                                                    \
+  TEST(MessageRouterTest, MultiQuerySingleFrame##name##Binary) {    \
+    CefRefPtr<MultiQuerySingleFrameTestHandler> handler =           \
+        new MultiQuerySingleFrameTestHandler(synchronous,           \
+                                             TransferType::BINARY); \
+    MultiQueryManager* manager = handler->GetManager();             \
+    manager->AddTestQuery(MultiQueryManager::type);                 \
+    manager->Finalize();                                            \
+    handler->ExecuteTest();                                         \
+    ReleaseAndWaitForDestructor(handler);                           \
+  }
+
+// Test the query types individually.
+MQSF_TYPE_TEST(SyncSuccess, SUCCESS, true)
+MQSF_TYPE_TEST(AsyncSuccess, SUCCESS, false)
+MQSF_TYPE_TEST(SyncFailure, FAILURE, true)
+MQSF_TYPE_TEST(AsyncFailure, FAILURE, false)
+MQSF_TYPE_TEST(SyncPersistentSuccess, PERSISTENT_SUCCESS, true)
+MQSF_TYPE_TEST(AsyncPersistentSuccess, PERSISTENT_SUCCESS, false)
+MQSF_TYPE_TEST(SyncPersistentFailure, PERSISTENT_FAILURE, true)
+MQSF_TYPE_TEST(AsyncPersistentFailure, PERSISTENT_FAILURE, false)
+MQSF_TYPE_TEST(Cancel, CANCEL, true)
+MQSF_TYPE_TEST(AutoCancel, AUTOCANCEL, true)
+MQSF_TYPE_TEST(PersistentAutoCancel, PERSISTENT_AUTOCANCEL, true)
+
+#define MQSF_QUERY_RANGE_TEST(name, some, synchronous)              \
+  TEST(MessageRouterTest, MultiQuerySingleFrame##name##String) {    \
+    CefRefPtr<MultiQuerySingleFrameTestHandler> handler =           \
+        new MultiQuerySingleFrameTestHandler(synchronous,           \
+                                             TransferType::STRING); \
+    MakeTestQueries(handler->GetManager(), some);                   \
+    handler->ExecuteTest();                                         \
+    ReleaseAndWaitForDestructor(handler);                           \
+  }                                                                 \
+                                                                    \
+  TEST(MessageRouterTest, MultiQuerySingleFrame##name##Binary) {    \
+    CefRefPtr<MultiQuerySingleFrameTestHandler> handler =           \
+        new MultiQuerySingleFrameTestHandler(synchronous,           \
+                                             TransferType::BINARY); \
+    MakeTestQueries(handler->GetManager(), some);                   \
+    handler->ExecuteTest();                                         \
+    ReleaseAndWaitForDestructor(handler);                           \
+  }
+
+// Test that one frame can run some queries successfully in a synchronous
+// manner
+MQSF_QUERY_RANGE_TEST(SyncSome, true, true)
+
+// Test that one frame can run some queries successfully in an asynchronous
+// manner.
+MQSF_QUERY_RANGE_TEST(AsyncSome, true, false)
+
+// Test that one frame can run many queries successfully in a synchronous
+// manner.
+MQSF_QUERY_RANGE_TEST(SyncMany, false, true)
+
+// Test that one frame can run many queries successfully in an asynchronous
+// manner.
+MQSF_QUERY_RANGE_TEST(AsyncMany, false, false)
+
+#define MQSF_QUERY_RANGE_CANCEL_TEST(name, cancelType)           \
+  TEST(MessageRouterTest, MultiQuerySingleFrame##name##String) { \
+    CefRefPtr<MultiQuerySingleFrameTestHandler> handler =        \
+        new MultiQuerySingleFrameTestHandler(                    \
+            false, TransferType::STRING,                         \
+            MultiQuerySingleFrameTestHandler::cancelType);       \
+    MakeTestQueries(handler->GetManager(), false);               \
+    handler->ExecuteTest();                                      \
+    ReleaseAndWaitForDestructor(handler);                        \
+  }                                                              \
+                                                                 \
+  TEST(MessageRouterTest, MultiQuerySingleFrame##name##Binary) { \
+    CefRefPtr<MultiQuerySingleFrameTestHandler> handler =        \
+        new MultiQuerySingleFrameTestHandler(                    \
+            false, TransferType::BINARY,                         \
+            MultiQuerySingleFrameTestHandler::cancelType);       \
+    MakeTestQueries(handler->GetManager(), false);               \
+    handler->ExecuteTest();                                      \
+    ReleaseAndWaitForDestructor(handler);                        \
+  }
+
+// Test that pending queries can be canceled by removing the handler.
+MQSF_QUERY_RANGE_CANCEL_TEST(CancelByRemovingHandler,
+                             CANCEL_BY_REMOVING_HANDLER)
+
+// Test that pending queries can be canceled by closing the browser.
+MQSF_QUERY_RANGE_CANCEL_TEST(CancelByClosingBrowser, CANCEL_BY_CLOSING_BROWSER)
+
+namespace {
+
+// Test multiple handlers.
+class MultiQueryMultiHandlerTestHandler : public SingleLoadTestHandler,
+                                          public MultiQueryManager::Observer {
+ public:
+  class Handler : public CefMessageRouterBrowserSide::Handler {
+   public:
+    Handler(MultiQueryMultiHandlerTestHandler* test_handler, int index)
+        : test_handler_(test_handler), index_(index), query_id_(0) {}
+
+    bool OnQuery(CefRefPtr<CefBrowser> browser,
+                 CefRefPtr<CefFrame> frame,
+                 int64_t query_id,
+                 const CefString& request,
+                 bool persistent,
+                 CefRefPtr<Callback> callback) override {
+      // Each handler only handles a single request.
+      std::stringstream ss;
+      ss << kMultiQueryRequest << ":" << index_;
+      const std::string& handled_request = ss.str();
+      if (request != handled_request) {
+        return false;
+      }
+
+      // Verify that handlers are called in the correct order.
+      if (index_ == 0) {
+        EXPECT_FALSE(test_handler_->got_query0_);
+        EXPECT_FALSE(test_handler_->got_query1_);
+        EXPECT_FALSE(test_handler_->got_query2_);
+
+        test_handler_->got_query0_.yes();
+      } else if (index_ == 1) {
+        EXPECT_TRUE(test_handler_->got_query0_);
+        EXPECT_FALSE(test_handler_->got_query1_);
+        EXPECT_FALSE(test_handler_->got_query2_);
+
+        test_handler_->got_query1_.yes();
+      } else if (index_ == 2) {
+        EXPECT_TRUE(test_handler_->got_query0_);
+        EXPECT_TRUE(test_handler_->got_query1_);
+        EXPECT_FALSE(test_handler_->got_query2_);
+
+        test_handler_->got_query2_.yes();
+      }
+
+      query_id_ = query_id;
+      return test_handler_->OnQuery(browser, frame, query_id, request,
+                                    persistent, callback);
+    }
+
+    void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
+                         CefRefPtr<CefFrame> frame,
+                         int64_t query_id) override {
+      // Verify that the correct handler is called for cancellation.
+      EXPECT_EQ(query_id_, query_id);
+
+      if (index_ == 0) {
+        EXPECT_FALSE(test_handler_->got_query_canceled0_);
+        test_handler_->got_query_canceled0_.yes();
+      } else if (index_ == 1) {
+        EXPECT_FALSE(test_handler_->got_query_canceled1_);
+        test_handler_->got_query_canceled1_.yes();
+      } else if (index_ == 2) {
+        EXPECT_FALSE(test_handler_->got_query_canceled2_);
+        test_handler_->got_query_canceled2_.yes();
+      }
+
+      test_handler_->OnQueryCanceled(browser, frame, query_id);
+    }
+
+   private:
+    MultiQueryMultiHandlerTestHandler* test_handler_;
+    const int index_;
+    int64_t query_id_;
+  };
+
+  MultiQueryMultiHandlerTestHandler(bool synchronous,
+                                    bool cancel_by_removing_handler)
+      : manager_(std::string(), synchronous, 0),
+        handler0_(this, 0),
+        handler1_(this, 1),
+        handler2_(this, 2),
+        cancel_by_removing_handler_(cancel_by_removing_handler) {
+    manager_.AddObserver(this);
+
+    // Each handler will handle one of the queries.
+    manager_.AddTestQuery(MultiQueryManager::PERSISTENT_AUTOCANCEL);
+    manager_.AddTestQuery(MultiQueryManager::PERSISTENT_AUTOCANCEL);
+    manager_.AddTestQuery(MultiQueryManager::PERSISTENT_AUTOCANCEL);
+    manager_.Finalize();
+  }
+
+  std::string GetMainHTML() override { return manager_.GetHTML(true, true); }
+
+  void OnNotify(CefRefPtr<CefBrowser> browser,
+                CefRefPtr<CefFrame> frame,
+                const std::string& message) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+
+    manager_.OnNotify(browser, frame, message);
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               const CefString& request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+
+    return manager_.OnQueryImpl(browser, frame, query_id, request, persistent,
+                                callback);
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               CefRefPtr<const CefBinaryBuffer> request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+
+    return manager_.OnQueryImpl(browser, frame, query_id, request, persistent,
+                                callback);
+  }
+
+  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame,
+                       int64_t query_id) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+
+    manager_.OnQueryCanceled(browser, frame, query_id);
+  }
+
+  void OnManualQueriesCompleted(MultiQueryManager* manager) override {
+    EXPECT_EQ(manager, &manager_);
+
+    EXPECT_TRUE(got_query0_);
+    EXPECT_TRUE(got_query1_);
+    EXPECT_TRUE(got_query2_);
+    EXPECT_FALSE(got_query_canceled0_);
+    EXPECT_FALSE(got_query_canceled1_);
+    EXPECT_FALSE(got_query_canceled2_);
+
+    EXPECT_TRUE(manager_.HasAutoQueries());
+
+    CefRefPtr<CefMessageRouterBrowserSide> router = GetRouter();
+
+    // Remove one handler to cancel a query.
+
+    if (cancel_by_removing_handler_) {
+      manager_.WillCancelByRemovingHandler();
+
+      // Each query should be canceled as the handler is removed.
+      EXPECT_TRUE(router->RemoveHandler(&handler1_));
+      EXPECT_FALSE(got_query_canceled0_);
+      EXPECT_TRUE(got_query_canceled1_);
+      EXPECT_FALSE(got_query_canceled2_);
+
+      EXPECT_TRUE(router->RemoveHandler(&handler2_));
+      EXPECT_FALSE(got_query_canceled0_);
+      EXPECT_TRUE(got_query_canceled2_);
+
+      EXPECT_TRUE(router->RemoveHandler(&handler0_));
+      EXPECT_TRUE(got_query_canceled0_);
+    } else {
+      GetBrowser()->GetMainFrame()->LoadURL(std::string(kTestDomain1) +
+                                            "cancel.html");
+    }
+  }
+
+  void OnAllQueriesCompleted(MultiQueryManager* manager) override {
+    EXPECT_EQ(manager, &manager_);
+
+    // All queries should be canceled.
+    AssertQueryCount(nullptr, nullptr, 0);
+
+    DestroyTest();
+  }
+
+  void DestroyTest() override {
+    EXPECT_TRUE(got_query0_);
+    EXPECT_TRUE(got_query1_);
+    EXPECT_TRUE(got_query2_);
+    EXPECT_TRUE(got_query_canceled0_);
+    EXPECT_TRUE(got_query_canceled1_);
+    EXPECT_TRUE(got_query_canceled2_);
+
+    manager_.AssertAllComplete();
+    TestHandler::DestroyTest();
+  }
+
+ protected:
+  void AddHandlers(
+      CefRefPtr<CefMessageRouterBrowserSide> message_router) override {
+    // OnQuery call order will verify that the first/last ordering works as
+    // expected.
+    EXPECT_TRUE(message_router->AddHandler(&handler1_, true));
+    EXPECT_TRUE(message_router->AddHandler(&handler0_, true));
+    EXPECT_TRUE(message_router->AddHandler(&handler2_, false));
+
+    // Can't add the same handler multiple times.
+    EXPECT_FALSE(message_router->AddHandler(&handler1_, true));
+  }
+
+ private:
+  MultiQueryManager manager_;
+  Handler handler0_;
+  Handler handler1_;
+  Handler handler2_;
+
+  const bool cancel_by_removing_handler_;
+
+  TrackCallback got_query0_;
+  TrackCallback got_query1_;
+  TrackCallback got_query2_;
+
+  TrackCallback got_query_canceled0_;
+  TrackCallback got_query_canceled1_;
+  TrackCallback got_query_canceled2_;
+};
+
+}  // namespace
+
+// Test that multiple handlers behave correctly.
+TEST(MessageRouterTest, MultiQueryMultiHandler) {
+  CefRefPtr<MultiQueryMultiHandlerTestHandler> handler =
+      new MultiQueryMultiHandlerTestHandler(false, false);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Test that multiple handlers behave correctly. Cancel by removing the
+// handlers.
+TEST(MessageRouterTest, MultiQueryMultiHandlerCancelByRemovingHandler) {
+  CefRefPtr<MultiQueryMultiHandlerTestHandler> handler =
+      new MultiQueryMultiHandlerTestHandler(false, true);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+namespace {
+
+// Map of managers on a per-URL basis.
+class MultiQueryManagerMap : public MultiQueryManager::Observer {
+ public:
+  class Observer {
+   public:
+    // Called when all manual queries are complete.
+    virtual void OnMapManualQueriesCompleted(MultiQueryManagerMap* map) {}
+
+    // Called when all queries are complete.
+    virtual void OnMapAllQueriesCompleted(MultiQueryManagerMap* map) {}
+
+   protected:
+    virtual ~Observer() {}
+  };
+
+  MultiQueryManagerMap()
+      : finalized_(false),
+        running_(false),
+        manual_complete_count_(0),
+        total_complete_count_(0) {}
+
+  virtual ~MultiQueryManagerMap() { RemoveAllManagers(); }
+
+  void AddObserver(Observer* observer) {
+    EXPECT_FALSE(running_);
+    observer_set_.insert(observer);
+  }
+
+  void RemoveObserver(Observer* observer) {
+    EXPECT_FALSE(running_);
+    EXPECT_TRUE(observer_set_.erase(observer));
+  }
+
+  MultiQueryManager* CreateManager(const std::string& url,
+                                   bool synchronous,
+                                   TransferType transfer_type) {
+    EXPECT_FALSE(finalized_);
+
+    MultiQueryManager* manager = new MultiQueryManager(
+        url, synchronous, static_cast<int>(manager_map_.size()) * 1000,
+        transfer_type);
+    manager->AddObserver(this);
+    all_managers_.push_back(manager);
+    pending_managers_.push_back(manager);
+
+    return manager;
+  }
+
+  void Finalize() {
+    EXPECT_FALSE(finalized_);
+    finalized_ = true;
+  }
+
+  std::string GetMainHTML() const {
+    EXPECT_TRUE(finalized_);
+    EXPECT_FALSE(running_);
+
+    std::string html = "<html><body>\n";
+
+    for (size_t i = 0; i < all_managers_.size(); ++i) {
+      const std::string& url = all_managers_[i]->label();
+      const std::string& name = GetNameForURL(url);
+      html += "<iframe id=\"" + name + "\" src=\"" + url + "\"></iframe>\n";
+    }
+
+    html += "</body></html>";
+    return html;
+  }
+
+  void OnNotify(CefRefPtr<CefBrowser> browser,
+                CefRefPtr<CefFrame> frame,
+                const std::string& message) {
+    EXPECT_TRUE(finalized_);
+    if (!running_) {
+      running_ = true;
+    }
+
+    MultiQueryManager* manager = GetManager(browser, frame);
+    manager->OnNotify(browser, frame, message);
+  }
+
+  template <class RequestType>
+  bool OnQueryImpl(CefRefPtr<CefBrowser> browser,
+                   CefRefPtr<CefFrame> frame,
+                   int64_t query_id,
+                   const RequestType& request,
+                   bool persistent,
+                   CefRefPtr<CefMessageRouterBrowserSide::Callback> callback) {
+    EXPECT_TRUE(finalized_);
+    if (!running_) {
+      running_ = true;
+    }
+
+    MultiQueryManager* manager = GetManager(browser, frame);
+    return manager->OnQueryImpl(browser, frame, query_id, request, persistent,
+                                callback);
+  }
+
+  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame,
+                       int64_t query_id) {
+    EXPECT_TRUE(finalized_);
+    if (!running_) {
+      running_ = true;
+    }
+
+    MultiQueryManager* manager = GetManager(browser, frame);
+    manager->OnQueryCanceled(browser, frame, query_id);
+  }
+
+  void OnManualQueriesCompleted(MultiQueryManager* manager) override {
+    const int size = static_cast<int>(all_managers_.size());
+    EXPECT_LT(manual_complete_count_, size);
+    if (++manual_complete_count_ == size) {
+      running_ = false;
+
+      // Notify observers.
+      if (!observer_set_.empty()) {
+        // Use a copy of the set in case an Observer is removed while we're
+        // iterating.
+        ObserverSet observer_set = observer_set_;
+
+        ObserverSet::const_iterator it = observer_set.begin();
+        for (; it != observer_set.end(); ++it) {
+          (*it)->OnMapManualQueriesCompleted(this);
+        }
+      }
+    }
+  }
+
+  void OnAllQueriesCompleted(MultiQueryManager* manager) override {
+    const int size = static_cast<int>(all_managers_.size());
+    EXPECT_LT(total_complete_count_, size);
+    if (++total_complete_count_ == size) {
+      running_ = false;
+
+      // Notify observers.
+      if (!observer_set_.empty()) {
+        // Use a copy of the set in case an Observer is removed while we're
+        // iterating.
+        ObserverSet observer_set = observer_set_;
+
+        ObserverSet::const_iterator it = observer_set.begin();
+        for (; it != observer_set.end(); ++it) {
+          (*it)->OnMapAllQueriesCompleted(this);
+        }
+      }
+    }
+  }
+
+  bool AllComplete() const {
+    EXPECT_TRUE(finalized_);
+
+    for (size_t i = 0; i < all_managers_.size(); ++i) {
+      if (!all_managers_[i]->IsAllComplete()) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  void AssertAllComplete() const {
+    EXPECT_TRUE(finalized_);
+    EXPECT_TRUE(pending_managers_.empty());
+    EXPECT_FALSE(running_);
+
+    for (size_t i = 0; i < all_managers_.size(); ++i) {
+      all_managers_[i]->AssertAllComplete();
+    }
+  }
+
+  bool HasAutoQueries() const {
+    for (size_t i = 0; i < all_managers_.size(); ++i) {
+      if (all_managers_[i]->HasAutoQueries()) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  void OnLoadStart(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame) {
+    if (pending_managers_.empty()) {
+      return;
+    }
+
+    const std::string& expected_url = frame->GetURL();
+    MultiQueryManager* next_manager = nullptr;
+
+    // Find the pending manager that matches the expected URL.
+    ManagerList::iterator it = pending_managers_.begin();
+    for (; it != pending_managers_.end(); ++it) {
+      if ((*it)->label() == expected_url) {
+        next_manager = *it;
+        pending_managers_.erase(it);
+        break;
+      }
+    }
+
+    EXPECT_TRUE(next_manager);
+
+    const int browser_id = browser->GetIdentifier();
+    // Always use the same ID for the main frame.
+    const int64_t frame_id = frame->IsMain() ? -1 : frame->GetIdentifier();
+
+    const std::pair<int, int64_t>& id = std::make_pair(browser_id, frame_id);
+
+    // Remove the currently active manager, if any.
+    ManagerMap::iterator it2 = manager_map_.find(id);
+    if (it2 != manager_map_.end()) {
+      manager_map_.erase(it2);
+    }
+
+    // Add the next manager to the active map.
+    manager_map_.insert(std::make_pair(id, next_manager));
+  }
+
+  MultiQueryManager* GetManager(CefRefPtr<CefBrowser> browser,
+                                CefRefPtr<CefFrame> frame) const {
+    const int browser_id = browser->GetIdentifier();
+    // Always use the same ID for the main frame.
+    const int64_t frame_id = frame->IsMain() ? -1 : frame->GetIdentifier();
+
+    // Find the manager in the active map.
+    ManagerMap::const_iterator it =
+        manager_map_.find(std::make_pair(browser_id, frame_id));
+    EXPECT_NE(it, manager_map_.end())
+        << "browser_id = " << browser_id << ", frame_id = " << frame_id;
+    return it->second;
+  }
+
+  void RemoveAllManagers() {
+    EXPECT_TRUE(pending_managers_.empty());
+    if (all_managers_.empty()) {
+      return;
+    }
+
+    for (size_t i = 0; i < all_managers_.size(); ++i) {
+      delete all_managers_[i];
+    }
+    all_managers_.clear();
+    manager_map_.clear();
+  }
+
+  static std::string GetNameForURL(const std::string& url) {
+    // Extract the file name without extension.
+    int pos1 = static_cast<int>(url.rfind("/"));
+    int pos2 = static_cast<int>(url.rfind("."));
+    EXPECT_TRUE(pos1 >= 0 && pos2 >= 0 && pos1 < pos2);
+    return url.substr(pos1 + 1, pos2 - pos1 - 1);
+  }
+
+ private:
+  typedef std::vector<MultiQueryManager*> ManagerList;
+  // Map of (browser ID, frame ID) to manager.
+  typedef std::map<std::pair<int, int64_t>, MultiQueryManager*> ManagerMap;
+
+  // All managers that have been created.
+  ManagerList all_managers_;
+  // Managers that have not yet associated with a frame.
+  ManagerList pending_managers_;
+  // Managers that are currently active.
+  ManagerMap manager_map_;
+
+  typedef std::set<Observer*> ObserverSet;
+  ObserverSet observer_set_;
+
+  // Set to true after all query managers have been added.
+  bool finalized_;
+  // Set to true while queries are pending.
+  bool running_;
+
+  // Number of managers that have completed.
+  int manual_complete_count_;
+  int total_complete_count_;
+};
+
+// Test multiple queries in a single page load with multiple frames.
+class MultiQueryMultiFrameTestHandler : public SingleLoadTestHandler,
+                                        public MultiQueryManagerMap::Observer {
+ public:
+  MultiQueryMultiFrameTestHandler(bool synchronous,
+                                  bool cancel_with_subnav,
+                                  TransferType transfer_type)
+      : synchronous_(synchronous),
+        cancel_with_subnav_(cancel_with_subnav),
+        transfer_type_(transfer_type) {
+    manager_map_.AddObserver(this);
+  }
+
+  void AddOtherResources() override {
+    AddSubFrameResource("sub1");
+    AddSubFrameResource("sub2");
+    AddSubFrameResource("sub3");
+    manager_map_.Finalize();
+
+    if (manager_map_.HasAutoQueries()) {
+      cancel_url_ = std::string(kTestDomain1) + "cancel.html";
+      AddResource(cancel_url_, "<html><body>cancel</body></html>", "text/html");
+    }
+  }
+
+  std::string GetMainHTML() override { return manager_map_.GetMainHTML(); }
+
+  void OnLoadStart(CefRefPtr<CefBrowser> browser,
+                   CefRefPtr<CefFrame> frame,
+                   TransitionType transition_type) override {
+    AssertMainBrowser(browser);
+    if (!frame->IsMain()) {
+      manager_map_.OnLoadStart(browser, frame);
+    }
+  }
+
+  void OnNotify(CefRefPtr<CefBrowser> browser,
+                CefRefPtr<CefFrame> frame,
+                const std::string& message) override {
+    AssertMainBrowser(browser);
+    EXPECT_FALSE(frame->IsMain());
+
+    manager_map_.OnNotify(browser, frame, message);
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               const CefString& request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    AssertMainBrowser(browser);
+    EXPECT_FALSE(frame->IsMain());
+
+    return manager_map_.OnQueryImpl(browser, frame, query_id, request,
+                                    persistent, callback);
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               CefRefPtr<const CefBinaryBuffer> request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    AssertMainBrowser(browser);
+    EXPECT_FALSE(frame->IsMain());
+
+    return manager_map_.OnQueryImpl(browser, frame, query_id, request,
+                                    persistent, callback);
+  }
+
+  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame,
+                       int64_t query_id) override {
+    AssertMainBrowser(browser);
+    EXPECT_FALSE(frame->IsMain());
+
+    manager_map_.OnQueryCanceled(browser, frame, query_id);
+  }
+
+  void OnMapManualQueriesCompleted(MultiQueryManagerMap* map) override {
+    EXPECT_EQ(map, &manager_map_);
+    if (manager_map_.HasAutoQueries()) {
+      CefRefPtr<CefFrame> frame = GetBrowser()->GetMainFrame();
+
+      // Navigate somewhere else to terminate the auto queries.
+      if (cancel_with_subnav_) {
+        // Navigate each subframe individually.
+        const std::string js = "document.getElementById('sub1').src = '" +
+                               cancel_url_ +
+                               "';"
+                               "document.getElementById('sub2').src = '" +
+                               cancel_url_ +
+                               "';"
+                               "document.getElementById('sub3').src = '" +
+                               cancel_url_ + "';";
+
+        frame->ExecuteJavaScript(js, frame->GetURL(), 0);
+      } else {
+        // Navigate the main frame.
+        frame->LoadURL(cancel_url_);
+      }
+    }
+  }
+
+  void OnMapAllQueriesCompleted(MultiQueryManagerMap* map) override {
+    EXPECT_EQ(map, &manager_map_);
+    DestroyTest();
+  }
+
+  void DestroyTest() override {
+    manager_map_.AssertAllComplete();
+    TestHandler::DestroyTest();
+  }
+
+ private:
+  void AddSubFrameResource(const std::string& name) {
+    const std::string& url = std::string(kTestDomain1) + name + ".html";
+
+    MultiQueryManager* manager =
+        manager_map_.CreateManager(url, synchronous_, transfer_type_);
+    MakeTestQueries(manager, false, 100);
+
+    const std::string& html = manager->GetHTML(false, false);
+    AddResource(url, html, "text/html");
+  }
+
+  const bool synchronous_;
+  const bool cancel_with_subnav_;
+  const TransferType transfer_type_;
+
+  MultiQueryManagerMap manager_map_;
+
+  std::string cancel_url_;
+};
+
+}  // namespace
+
+#define MQMF_TEST(name, sync, cancel_with_subnav)                     \
+  TEST(MessageRouterTest, MultiQueryMultiFrame##name##String) {       \
+    CefRefPtr<MultiQueryMultiFrameTestHandler> handler =              \
+        new MultiQueryMultiFrameTestHandler(sync, cancel_with_subnav, \
+                                            TransferType::STRING);    \
+    handler->ExecuteTest();                                           \
+    ReleaseAndWaitForDestructor(handler);                             \
+  }                                                                   \
+                                                                      \
+  TEST(MessageRouterTest, MultiQueryMultiFrame##name##Binary) {       \
+    CefRefPtr<MultiQueryMultiFrameTestHandler> handler =              \
+        new MultiQueryMultiFrameTestHandler(sync, cancel_with_subnav, \
+                                            TransferType::BINARY);    \
+    handler->ExecuteTest();                                           \
+    ReleaseAndWaitForDestructor(handler);                             \
+  }
+
+// Test that multiple frames can run many queries successfully in a synchronous
+// manner.
+MQMF_TEST(Sync, true, false)
+
+// Test that multiple frames can run many queries successfully in an
+// asynchronous manner.
+MQMF_TEST(Async, false, false)
+
+// Test that multiple frames can run many queries successfully in a synchronous
+// manner. Cancel auto queries with sub-frame navigation.
+MQMF_TEST(SyncSubnavCancel, true, true)
+
+// Test that multiple frames can run many queries successfully in an
+// asynchronous manner. Cancel auto queries with sub-frame navigation.
+MQMF_TEST(AsyncSubnavCancel, false, true)
+
+namespace {
+
+// Implementation of MRTestHandler that loads multiple pages and/or browsers and
+// executes multiple queries.
+class MultiQueryMultiLoadTestHandler
+    : public MRTestHandler,
+      public CefMessageRouterBrowserSide::Handler,
+      public MultiQueryManagerMap::Observer,
+      public MultiQueryManager::Observer {
+ public:
+  MultiQueryMultiLoadTestHandler(bool some,
+                                 bool synchronous,
+                                 TransferType transfer_type)
+      : some_(some), synchronous_(synchronous), transfer_type_(transfer_type) {
+    manager_map_.AddObserver(this);
+  }
+
+  void OnLoadStart(CefRefPtr<CefBrowser> browser,
+                   CefRefPtr<CefFrame> frame,
+                   TransitionType transition_type) override {
+    manager_map_.OnLoadStart(browser, frame);
+  }
+
+  void OnNotify(CefRefPtr<CefBrowser> browser,
+                CefRefPtr<CefFrame> frame,
+                const std::string& message) override {
+    manager_map_.OnNotify(browser, frame, message);
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               const CefString& request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    return manager_map_.OnQueryImpl(browser, frame, query_id, request,
+                                    persistent, callback);
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               CefRefPtr<const CefBinaryBuffer> request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    return manager_map_.OnQueryImpl(browser, frame, query_id, request,
+                                    persistent, callback);
+  }
+
+  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame,
+                       int64_t query_id) override {
+    manager_map_.OnQueryCanceled(browser, frame, query_id);
+  }
+
+  void OnMapManualQueriesCompleted(MultiQueryManagerMap* map) override {
+    EXPECT_EQ(map, &manager_map_);
+    if (manager_map_.HasAutoQueries()) {
+      // Navigate all browsers somewhere else to terminate the auto queries.
+      BrowserMap browser_map;
+      GetAllBrowsers(&browser_map);
+
+      BrowserMap::const_iterator it = browser_map.begin();
+      for (; it != browser_map.end(); ++it) {
+        it->second->GetMainFrame()->LoadURL(cancel_url_);
+      }
+    }
+  }
+
+  void OnMapAllQueriesCompleted(MultiQueryManagerMap* map) override {
+    EXPECT_EQ(map, &manager_map_);
+    DestroyTest();
+  }
+
+  void DestroyTest() override {
+    manager_map_.AssertAllComplete();
+    TestHandler::DestroyTest();
+  }
+
+ protected:
+  void AddHandlers(
+      CefRefPtr<CefMessageRouterBrowserSide> message_router) override {
+    message_router->AddHandler(this, false);
+  }
+
+  void AddManagedResource(const std::string& url,
+                          bool assert_total,
+                          bool assert_browser) {
+    MultiQueryManager* manager =
+        manager_map_.CreateManager(url, synchronous_, transfer_type_);
+    manager->AddObserver(this);
+    MakeTestQueries(manager, some_, 75);
+
+    const std::string& html = manager->GetHTML(assert_total, assert_browser);
+    AddResource(url, html, "text/html");
+  }
+
+  void Finalize() {
+    manager_map_.Finalize();
+
+    if (manager_map_.HasAutoQueries()) {
+      cancel_url_ = std::string(kTestDomain1) + "cancel.html";
+      AddResource(cancel_url_, "<html><body>cancel</body></html>", "text/html");
+    }
+  }
+
+  MultiQueryManagerMap manager_map_;
+
+ private:
+  const bool some_;
+  const bool synchronous_;
+  const TransferType transfer_type_;
+
+  std::string cancel_url_;
+};
+
+// Test multiple browsers that send queries at the same time.
+class MultiQueryMultiBrowserTestHandler
+    : public MultiQueryMultiLoadTestHandler {
+ public:
+  MultiQueryMultiBrowserTestHandler(bool synchronous,
+                                    bool same_origin,
+                                    TransferType transfer_type)
+      : MultiQueryMultiLoadTestHandler(false, synchronous, transfer_type),
+        same_origin_(same_origin) {}
+
+ protected:
+  void RunMRTest() override {
+    const std::string& url1 = std::string(kTestDomain1) + "browser1.html";
+    const std::string& url2 =
+        std::string(same_origin_ ? kTestDomain1 : kTestDomain2) +
+        "browser2.html";
+    const std::string& url3 =
+        std::string(same_origin_ ? kTestDomain1 : kTestDomain3) +
+        "browser3.html";
+
+    AddManagedResource(url1, false, true);
+    AddManagedResource(url2, false, true);
+    AddManagedResource(url3, false, true);
+    Finalize();
+
+    // Create 2 browsers simultaniously.
+    CreateBrowser(url1, nullptr);
+    CreateBrowser(url2, nullptr);
+    CreateBrowser(url3, nullptr);
+  }
+
+ private:
+  bool same_origin_;
+};
+
+}  // namespace
+
+#define MQMB_TEST(name, sync, same_origin)                           \
+  TEST(MessageRouterTest, MultiQueryMultiBrowser##name##String) {    \
+    CefRefPtr<MultiQueryMultiBrowserTestHandler> handler =           \
+        new MultiQueryMultiBrowserTestHandler(sync, same_origin,     \
+                                              TransferType::STRING); \
+    handler->ExecuteTest();                                          \
+    ReleaseAndWaitForDestructor(handler);                            \
+  }                                                                  \
+                                                                     \
+  TEST(MessageRouterTest, MultiQueryMultiBrowser##name##Binary) {    \
+    CefRefPtr<MultiQueryMultiBrowserTestHandler> handler =           \
+        new MultiQueryMultiBrowserTestHandler(sync, same_origin,     \
+                                              TransferType::BINARY); \
+    handler->ExecuteTest();                                          \
+    ReleaseAndWaitForDestructor(handler);                            \
+  }
+
+// Test that multiple browsers can query simultaniously from the same origin.
+MQMB_TEST(SameOriginSync, true, true)
+
+// Test that multiple browsers can query simultaniously from the same origin.
+MQMB_TEST(SameOriginAsync, false, true)
+
+// Test that multiple browsers can query simultaniously from different origins.
+MQMB_TEST(DifferentOriginSync, true, false)
+
+// Test that multiple browsers can query simultaniously from different origins.
+MQMB_TEST(DifferentOriginAsync, false, false)
+
+namespace {
+
+// Test multiple navigations that send queries sequentially.
+class MultiQueryMultiNavigateTestHandler
+    : public MultiQueryMultiLoadTestHandler {
+ public:
+  MultiQueryMultiNavigateTestHandler(bool synchronous,
+                                     bool same_origin,
+                                     TransferType transfer_type)
+      : MultiQueryMultiLoadTestHandler(false, synchronous, transfer_type),
+        same_origin_(same_origin) {}
+
+  void OnManualQueriesCompleted(MultiQueryManager* manager) override {
+    const std::string& url = manager->label();
+    if (url == url1_) {  // 2. Load the 2nd url.
+      GetBrowser()->GetMainFrame()->LoadURL(url2_);
+    } else if (url == url2_) {  // 3. Load the 3rd url.
+      GetBrowser()->GetMainFrame()->LoadURL(url3_);
+    }
+  }
+
+ protected:
+  void RunMRTest() override {
+    url1_ = std::string(kTestDomain1) + "browser1.html";
+    url2_ = std::string(same_origin_ ? kTestDomain1 : kTestDomain2) +
+            "browser2.html";
+    url3_ = std::string(same_origin_ ? kTestDomain1 : kTestDomain3) +
+            "browser3.html";
+
+    // With same-site BFCache enabled a new browser will be created for each
+    // same-site navigation in the renderer process, resulting in "total count"
+    // values that potentially span multiple navigations.
+    const bool should_assert = !(same_origin_ && IsSameSiteBFCacheEnabled());
+    AddManagedResource(url1_, should_assert, should_assert);
+    AddManagedResource(url2_, should_assert, should_assert);
+    AddManagedResource(url3_, should_assert, should_assert);
+    Finalize();
+
+    // 1. Load the 1st url.
+    CreateBrowser(url1_, nullptr);
+  }
+
+ private:
+  bool same_origin_;
+
+  std::string url1_;
+  std::string url2_;
+  std::string url3_;
+};
+
+}  // namespace
+
+#define MQMN_TEST(name, sync, same_origin)                            \
+  TEST(MessageRouterTest, MultiQueryMultiNavigate##name##String) {    \
+    CefRefPtr<MultiQueryMultiNavigateTestHandler> handler =           \
+        new MultiQueryMultiNavigateTestHandler(sync, same_origin,     \
+                                               TransferType::STRING); \
+    handler->ExecuteTest();                                           \
+    ReleaseAndWaitForDestructor(handler);                             \
+  }                                                                   \
+                                                                      \
+  TEST(MessageRouterTest, MultiQueryMultiNavigate##name##Binary) {    \
+    CefRefPtr<MultiQueryMultiNavigateTestHandler> handler =           \
+        new MultiQueryMultiNavigateTestHandler(sync, same_origin,     \
+                                               TransferType::BINARY); \
+    handler->ExecuteTest();                                           \
+    ReleaseAndWaitForDestructor(handler);                             \
+  }
+
+// Test that multiple navigations can query from the same origin.
+MQMN_TEST(SameOriginSync, true, true)
+
+// Test that multiple navigations can query from the same origin.
+MQMN_TEST(SameOriginAsync, false, true)
+
+// Test that multiple navigations can query from different origins.
+MQMN_TEST(DifferentOriginSync, true, false)
+
+// Test that multiple navigations can query from different origins.
+MQMN_TEST(DifferentOriginAsync, false, false)
diff --git a/src/tests/ceftests/message_router_single_query_unittest.cc b/src/tests/ceftests/message_router_single_query_unittest.cc
new file mode 100644
index 0000000..3612a83
--- /dev/null
+++ b/src/tests/ceftests/message_router_single_query_unittest.cc
@@ -0,0 +1,629 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "tests/ceftests/message_router_unittest_utils.h"
+
+namespace {
+
+const char kSingleQueryRequest[] = "request_context";
+const char kSingleQueryResponse[] = "success_response";
+const int kSingleQueryErrorCode = 5;
+const char kSingleQueryErrorMessage[] = "error_message";
+
+// Test a single query in a single page load.
+class SingleQueryTestHandler : public SingleLoadTestHandler {
+ public:
+  enum TestType {
+    SUCCESS,
+    FAILURE,
+    CANCEL,
+  };
+
+  SingleQueryTestHandler(TestType type, bool sync_callback)
+      : test_type_(type), sync_callback_(sync_callback), query_id_(0) {}
+
+  std::string GetMainHTML() override {
+    std::string html;
+
+    std::stringstream ss;
+    ss << kSingleQueryErrorCode;
+    const std::string& errorCodeStr = ss.str();
+
+    html =
+        "<html><body><script>\n"
+        // No requests should exist.
+        "window.mrtAssertTotalCount(" LINESTR
+        ",0);\n"
+        "window.mrtAssertBrowserCount(" LINESTR
+        ",0);\n"
+        "window.mrtAssertContextCount(" LINESTR
+        ",0);\n"
+        // Send the query.
+        "var request_id = window.mrtQuery({\n"
+        "  request: '" +
+        std::string(kSingleQueryRequest) +
+        "',\n"
+        "  persistent: false,\n"
+        "  onSuccess: function(response) {\n"
+        // Request should be removed before callback is executed.
+        "    window.mrtAssertTotalCount(" LINESTR
+        ",0);\n"
+        "    window.mrtAssertBrowserCount(" LINESTR
+        ",0);\n"
+        "    window.mrtAssertContextCount(" LINESTR
+        ",0);\n"
+        "    if (response == '" +
+        std::string(kSingleQueryResponse) +
+        "')\n"
+        "      window.mrtNotify('success');\n"
+        "    else\n"
+        "      window.mrtNotify('error-onSuccess');\n"
+        "  },\n"
+        "  onFailure: function(error_code, error_message) {\n"
+        // Request should be removed before callback is executed.
+        "    window.mrtAssertTotalCount(" LINESTR
+        ",0);\n"
+        "    window.mrtAssertBrowserCount(" LINESTR
+        ",0);\n"
+        "    window.mrtAssertContextCount(" LINESTR
+        ",0);\n"
+        "    if (error_code == " +
+        errorCodeStr + " && error_message == '" +
+        std::string(kSingleQueryErrorMessage) +
+        "')\n"
+        "      window.mrtNotify('failure');\n"
+        "    else\n"
+        "      window.mrtNotify('error-onFailure');\n"
+        "  }\n"
+        "});\n"
+        // Request should exist.
+        "window.mrtAssertTotalCount(" LINESTR
+        ",1);\n"
+        "window.mrtAssertBrowserCount(" LINESTR
+        ",1);\n"
+        "window.mrtAssertContextCount(" LINESTR ",1);\n";
+
+    if (test_type_ == CANCEL) {
+      html +=
+          "window.mrtQueryCancel(request_id);\n"
+          // Request should be removed immediately.
+          "window.mrtAssertTotalCount(" LINESTR
+          ",0);\n"
+          "window.mrtAssertBrowserCount(" LINESTR
+          ",0);\n"
+          "window.mrtAssertContextCount(" LINESTR
+          ",0);\n"
+          "window.mrtNotify('cancel');\n";
+    }
+
+    html += "</script></body></html>";
+    return html;
+  }
+
+  void OnNotify(CefRefPtr<CefBrowser> browser,
+                CefRefPtr<CefFrame> frame,
+                const std::string& message) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+
+    // OnNotify only be called once.
+    EXPECT_FALSE(got_notify_);
+    got_notify_.yes();
+
+    if (test_type_ == SUCCESS) {
+      EXPECT_STREQ("success", message.c_str());
+    } else if (test_type_ == FAILURE) {
+      EXPECT_STREQ("failure", message.c_str());
+    } else if (test_type_ == CANCEL) {
+      EXPECT_STREQ("cancel", message.c_str());
+    }
+
+    DestroyTestIfDone();
+  }
+
+  void ExecuteCallback() {
+    EXPECT_TRUE(callback_.get());
+    if (test_type_ == SUCCESS) {
+      callback_->Success(kSingleQueryResponse);
+    } else if (test_type_ == FAILURE) {
+      callback_->Failure(kSingleQueryErrorCode, kSingleQueryErrorMessage);
+    } else {
+      ADD_FAILURE();  // Not reached.
+    }
+    callback_ = nullptr;
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               const CefString& request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+    EXPECT_NE(0, query_id);
+    EXPECT_FALSE(persistent);
+    EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str());
+
+    got_on_query_.yes();
+
+    query_id_ = query_id;
+    callback_ = callback;
+
+    if (test_type_ == SUCCESS || test_type_ == FAILURE) {
+      if (sync_callback_) {
+        ExecuteCallback();
+      } else {
+        CefPostTask(
+            TID_UI,
+            base::BindOnce(&SingleQueryTestHandler::ExecuteCallback, this));
+      }
+    }
+
+    return true;
+  }
+
+  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame,
+                       int64_t query_id) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+    EXPECT_EQ(test_type_, CANCEL);
+    EXPECT_EQ(query_id_, query_id);
+    EXPECT_TRUE(got_on_query_);
+    EXPECT_TRUE(callback_.get());
+
+    got_on_query_canceled_.yes();
+    callback_ = nullptr;
+
+    DestroyTestIfDone();
+  }
+
+  void DestroyTestIfDone() {
+    bool destroy_test = false;
+    if (test_type_ == CANCEL) {
+      destroy_test = got_notify_ && got_on_query_canceled_;
+    } else {
+      destroy_test = got_notify_;
+    }
+    if (destroy_test) {
+      DestroyTest();
+    }
+  }
+
+  void DestroyTest() override {
+    EXPECT_TRUE(got_notify_);
+    EXPECT_TRUE(got_on_query_);
+    EXPECT_FALSE(callback_.get());
+
+    if (test_type_ == CANCEL) {
+      EXPECT_TRUE(got_on_query_canceled_);
+    } else {
+      EXPECT_FALSE(got_on_query_canceled_);
+    }
+
+    TestHandler::DestroyTest();
+  }
+
+ private:
+  const TestType test_type_;
+  const bool sync_callback_;
+
+  int64_t query_id_;
+  CefRefPtr<Callback> callback_;
+
+  TrackCallback got_on_query_;
+  TrackCallback got_on_query_canceled_;
+  TrackCallback got_notify_;
+};
+
+}  // namespace
+
+// Test that a single query with successful result delivered synchronously.
+TEST(MessageRouterTest, SingleQuerySuccessSyncCallback) {
+  CefRefPtr<SingleQueryTestHandler> handler =
+      new SingleQueryTestHandler(SingleQueryTestHandler::SUCCESS, true);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Test that a single query with successful result delivered asynchronously.
+TEST(MessageRouterTest, SingleQuerySuccessAsyncCallback) {
+  CefRefPtr<SingleQueryTestHandler> handler =
+      new SingleQueryTestHandler(SingleQueryTestHandler::SUCCESS, false);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Test that a single query with failure result delivered synchronously.
+TEST(MessageRouterTest, SingleQueryFailureSyncCallback) {
+  CefRefPtr<SingleQueryTestHandler> handler =
+      new SingleQueryTestHandler(SingleQueryTestHandler::FAILURE, true);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Test that a single query with failure result delivered asynchronously.
+TEST(MessageRouterTest, SingleQueryFailureAsyncCallback) {
+  CefRefPtr<SingleQueryTestHandler> handler =
+      new SingleQueryTestHandler(SingleQueryTestHandler::FAILURE, false);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Test that a single query with cancellation.
+TEST(MessageRouterTest, SingleQueryCancel) {
+  CefRefPtr<SingleQueryTestHandler> handler =
+      new SingleQueryTestHandler(SingleQueryTestHandler::CANCEL, true);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+namespace {
+
+const int kSinglePersistentQueryResponseCount = 10;
+
+// Test a single persistent query in a single page load.
+class SinglePersistentQueryTestHandler : public SingleLoadTestHandler {
+ public:
+  enum TestType {
+    SUCCESS,
+    FAILURE,
+  };
+
+  SinglePersistentQueryTestHandler(TestType test_type, bool sync_callback)
+      : test_type_(test_type), sync_callback_(sync_callback), query_id_(0) {}
+
+  std::string GetMainHTML() override {
+    std::string html;
+
+    std::stringstream ss;
+    ss << kSinglePersistentQueryResponseCount;
+    const std::string& responseCountStr = ss.str();
+    ss.str("");
+    ss << kSingleQueryErrorCode;
+    const std::string& errorCodeStr = ss.str();
+
+    html =
+        "<html><body><script>\n"
+        // No requests should exist.
+        "window.mrtAssertTotalCount(" LINESTR
+        ",0);\n"
+        "window.mrtAssertBrowserCount(" LINESTR
+        ",0);\n"
+        "window.mrtAssertContextCount(" LINESTR
+        ",0);\n"
+        // Keep track of the number of responses.
+        "var count = 0;\n"
+        // Send the query.
+        "var request_id = window.mrtQuery({\n"
+        "  request: '" +
+        std::string(kSingleQueryRequest) +
+        "',\n"
+        "  persistent: true,\n"
+        "  onSuccess: function(response) {\n"
+        // Request should not be removed.
+        "    window.mrtAssertTotalCount(" LINESTR
+        ",1);\n"
+        "    window.mrtAssertBrowserCount(" LINESTR
+        ",1);\n"
+        "    window.mrtAssertContextCount(" LINESTR
+        ",1);\n"
+        "    if (response == '" +
+        std::string(kSingleQueryResponse) +
+        "') {\n"
+        "      if (++count == " +
+        responseCountStr +
+        ") {\n"
+        "        window.mrtNotify('success');\n"
+        "        window.mrtQueryCancel(request_id);\n"
+        // Request should be removed immediately.
+        "        window.mrtAssertTotalCount(" LINESTR
+        ",0);\n"
+        "        window.mrtAssertBrowserCount(" LINESTR
+        ",0);\n"
+        "        window.mrtAssertContextCount(" LINESTR
+        ",0);\n"
+        "      }\n"
+        "    } else {\n"
+        "      window.mrtNotify('error-onSuccess');\n"
+        "    }\n"
+        "  },\n"
+        "  onFailure: function(error_code, error_message) {\n"
+        // Request should be removed before callback is executed.
+        "    window.mrtAssertTotalCount(" LINESTR
+        ",0);\n"
+        "    window.mrtAssertBrowserCount(" LINESTR
+        ",0);\n"
+        "    window.mrtAssertContextCount(" LINESTR
+        ",0);\n"
+        "    if (error_code == " +
+        errorCodeStr + " && error_message == '" +
+        std::string(kSingleQueryErrorMessage) +
+        "') {\n"
+        "      window.mrtNotify('failure');\n"
+        "    } else {\n"
+        "      window.mrtNotify('error-onFailure');\n"
+        "    }\n"
+        "  }\n"
+        "});\n"
+        // Request should exist.
+        "window.mrtAssertTotalCount(" LINESTR
+        ",1);\n"
+        "window.mrtAssertBrowserCount(" LINESTR
+        ",1);\n"
+        "window.mrtAssertContextCount(" LINESTR ",1);\n";
+
+    html += "</script></body></html>";
+    return html;
+  }
+
+  void OnNotify(CefRefPtr<CefBrowser> browser,
+                CefRefPtr<CefFrame> frame,
+                const std::string& message) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+
+    if (test_type_ == SUCCESS) {
+      EXPECT_STREQ("success", message.c_str());
+    } else if (test_type_ == FAILURE) {
+      EXPECT_STREQ("failure", message.c_str());
+    }
+
+    got_notify_.yes();
+
+    DestroyTestIfDone();
+  }
+
+  void ExecuteCallback() {
+    EXPECT_TRUE(callback_.get());
+    if (test_type_ == SUCCESS) {
+      callback_->Success(kSingleQueryResponse);
+    } else {
+      callback_->Failure(kSingleQueryErrorCode, kSingleQueryErrorMessage);
+      callback_ = nullptr;
+    }
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               const CefString& request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+    EXPECT_NE(0, query_id);
+    EXPECT_TRUE(persistent);
+    EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str());
+
+    got_on_query_.yes();
+
+    query_id_ = query_id;
+    callback_ = callback;
+
+    int repeat =
+        (test_type_ == SUCCESS ? kSinglePersistentQueryResponseCount : 1);
+
+    for (int i = 0; i < repeat; ++i) {
+      if (sync_callback_) {
+        ExecuteCallback();
+      } else {
+        CefPostTask(
+            TID_UI,
+            base::BindOnce(&SinglePersistentQueryTestHandler::ExecuteCallback,
+                           this));
+      }
+    }
+
+    return true;
+  }
+
+  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame,
+                       int64_t query_id) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+    EXPECT_EQ(query_id_, query_id);
+    EXPECT_TRUE(got_on_query_);
+    EXPECT_TRUE(callback_.get());
+
+    got_on_query_canceled_.yes();
+    callback_ = nullptr;
+
+    DestroyTestIfDone();
+  }
+
+  void DestroyTestIfDone() {
+    bool destroy_test = false;
+    if (test_type_ == SUCCESS) {
+      if (got_on_query_ && got_on_query_canceled_ && got_notify_) {
+        destroy_test = true;
+      }
+    } else if (got_on_query_ && got_notify_) {
+      destroy_test = true;
+    }
+
+    if (destroy_test) {
+      DestroyTest();
+    }
+  }
+
+  void DestroyTest() override {
+    EXPECT_TRUE(got_notify_);
+    EXPECT_TRUE(got_on_query_);
+    EXPECT_FALSE(callback_.get());
+
+    if (test_type_ == SUCCESS) {
+      EXPECT_TRUE(got_on_query_canceled_);
+    } else {
+      EXPECT_FALSE(got_on_query_canceled_);
+    }
+
+    TestHandler::DestroyTest();
+  }
+
+ private:
+  const TestType test_type_;
+  const bool sync_callback_;
+
+  int64_t query_id_;
+  CefRefPtr<Callback> callback_;
+
+  TrackCallback got_on_query_;
+  TrackCallback got_on_query_canceled_;
+  TrackCallback got_notify_;
+};
+
+}  // namespace
+
+// Test that a single query with successful result delivered synchronously.
+TEST(MessageRouterTest, SinglePersistentQuerySuccessSyncCallback) {
+  CefRefPtr<SinglePersistentQueryTestHandler> handler =
+      new SinglePersistentQueryTestHandler(
+          SinglePersistentQueryTestHandler::SUCCESS, true);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Test that a single query with successful result delivered asynchronously.
+TEST(MessageRouterTest, SinglePersistentQuerySuccessAsyncCallback) {
+  CefRefPtr<SinglePersistentQueryTestHandler> handler =
+      new SinglePersistentQueryTestHandler(
+          SinglePersistentQueryTestHandler::SUCCESS, false);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Test that a single query with failure result delivered synchronously.
+TEST(MessageRouterTest, SinglePersistentQueryFailureSyncCallback) {
+  CefRefPtr<SinglePersistentQueryTestHandler> handler =
+      new SinglePersistentQueryTestHandler(
+          SinglePersistentQueryTestHandler::FAILURE, true);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Test that a single query with failure result delivered asynchronously.
+TEST(MessageRouterTest, SinglePersistentQueryFailureAsyncCallback) {
+  CefRefPtr<SinglePersistentQueryTestHandler> handler =
+      new SinglePersistentQueryTestHandler(
+          SinglePersistentQueryTestHandler::FAILURE, false);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+namespace {
+
+// Test a single unhandled query in a single page load.
+class SingleUnhandledQueryTestHandler : public SingleLoadTestHandler {
+ public:
+  SingleUnhandledQueryTestHandler() {}
+
+  std::string GetMainHTML() override {
+    std::string html;
+
+    html =
+        "<html><body><script>\n"
+        // No requests should exist.
+        "window.mrtAssertTotalCount(" LINESTR
+        ",0);\n"
+        "window.mrtAssertBrowserCount(" LINESTR
+        ",0);\n"
+        "window.mrtAssertContextCount(" LINESTR
+        ",0);\n"
+        // Keep track of the number of responses.
+        "var count = 0;\n"
+        // Send the query.
+        "var request_id = window.mrtQuery({\n"
+        "  request: '" +
+        std::string(kSingleQueryRequest) +
+        "',\n"
+        "  persistent: false,\n"
+        "  onSuccess: function(response) {\n"
+        "    window.mrtNotify('error-onSuccess');\n"
+        "  },\n"
+        "  onFailure: function(error_code, error_message) {\n"
+        // Request should be removed before callback is executed.
+        "    window.mrtAssertTotalCount(" LINESTR
+        ",0);\n"
+        "    window.mrtAssertBrowserCount(" LINESTR
+        ",0);\n"
+        "    window.mrtAssertContextCount(" LINESTR
+        ",0);\n"
+        "    if (error_code == -1 && "
+        "error_message == 'The query has been canceled') {\n"
+        "      window.mrtNotify('failure');\n"
+        "    } else {\n"
+        "      window.mrtNotify('error-onFailure');\n"
+        "    }\n"
+        "  }\n"
+        "});\n"
+        // Request should exist.
+        "window.mrtAssertTotalCount(" LINESTR
+        ",1);\n"
+        "window.mrtAssertBrowserCount(" LINESTR
+        ",1);\n"
+        "window.mrtAssertContextCount(" LINESTR ",1);\n";
+
+    html += "</script></body></html>";
+    return html;
+  }
+
+  void OnNotify(CefRefPtr<CefBrowser> browser,
+                CefRefPtr<CefFrame> frame,
+                const std::string& message) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+    EXPECT_STREQ("failure", message.c_str());
+
+    got_notify_.yes();
+
+    DestroyTest();
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               const CefString& request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+    EXPECT_NE(0, query_id);
+    EXPECT_FALSE(persistent);
+    EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str());
+
+    got_on_query_.yes();
+
+    return false;
+  }
+
+  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
+                       CefRefPtr<CefFrame> frame,
+                       int64_t query_id) override {
+    EXPECT_FALSE(true);  // Not reached.
+  }
+
+  void DestroyTest() override {
+    EXPECT_TRUE(got_on_query_);
+    EXPECT_TRUE(got_notify_);
+
+    TestHandler::DestroyTest();
+  }
+
+ private:
+  TrackCallback got_on_query_;
+  TrackCallback got_notify_;
+};
+
+}  // namespace
+
+// Test that a single unhandled query results in a call to onFailure.
+TEST(MessageRouterTest, SingleUnhandledQuery) {
+  CefRefPtr<SingleUnhandledQueryTestHandler> handler =
+      new SingleUnhandledQueryTestHandler();
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
diff --git a/src/tests/ceftests/message_router_threshold_unittest.cc b/src/tests/ceftests/message_router_threshold_unittest.cc
new file mode 100644
index 0000000..24d96db
--- /dev/null
+++ b/src/tests/ceftests/message_router_threshold_unittest.cc
@@ -0,0 +1,230 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "tests/ceftests/message_router_unittest_utils.h"
+
+namespace {
+
+constexpr int kSingleQueryErrorCode = 5;
+constexpr size_t kMsgSizeThresholdInBytes = 16000;
+constexpr auto kCharSize = sizeof(CefString::char_type);
+
+enum class TestType { SUCCESS, FAILURE };
+
+CefString GenerateResponse(size_t count, char ch) {
+  return std::string(count, ch);
+}
+
+CefString GenerateResponse(size_t count, wchar_t ch) {
+  return std::wstring(count, ch);
+}
+
+template <class CharType>
+class ThresholdTestHandler final : public SingleLoadTestHandler {
+ public:
+  ThresholdTestHandler(TestType type, size_t string_length, CharType symbol)
+      : test_type_(type), string_length_(string_length), symbol_(symbol) {}
+
+  std::string GetMainHTML() override {
+    const std::string& errorCodeStr = std::to_string(kSingleQueryErrorCode);
+
+    std::string html =
+        "<html><body><script>\n"
+        // Send the query.
+        "var request_id = window." +
+        std::string(kJSQueryFunc) + "({\n request: '" +
+        std::to_string(string_length_) +
+        "',\n persistent: false,\n"
+        "  onSuccess: function(response) {\n"
+        "      window.mrtNotify(response);\n"
+        "  },\n"
+        "  onFailure: function(error_code, error_message) {\n"
+        "    if (error_code == " +
+        errorCodeStr +
+        ")\n"
+        "      window.mrtNotify(error_message);\n"
+        "    else\n"
+        "      window.mrtNotify('error-onFailure');\n"
+        "  }\n"
+        "});\n</script></body></html>";
+
+    return html;
+  }
+
+  void OnNotify(CefRefPtr<CefBrowser> browser,
+                CefRefPtr<CefFrame> frame,
+                const std::string& message) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+
+    // OnNotify only be called once.
+    EXPECT_FALSE(got_notify_);
+    got_notify_.yes();
+
+    auto expected = GenerateResponse(string_length_, symbol_);
+
+    switch (test_type_) {
+      case TestType::SUCCESS:
+        EXPECT_EQ(expected, message);
+        break;
+      case TestType::FAILURE:
+        EXPECT_EQ(expected, message);
+        break;
+      default:
+        ADD_FAILURE();
+        break;
+    }
+
+    DestroyTest();
+  }
+
+  void ExecuteCallback(size_t response_size) {
+    auto response = GenerateResponse(response_size, symbol_);
+
+    EXPECT_TRUE(callback_.get());
+    switch (test_type_) {
+      case TestType::SUCCESS:
+        callback_->Success(response);
+        break;
+      case TestType::FAILURE:
+        callback_->Failure(kSingleQueryErrorCode, response);
+        break;
+      default:
+        ADD_FAILURE();
+        break;
+    }
+    callback_ = nullptr;
+  }
+
+  bool OnQuery(CefRefPtr<CefBrowser> browser,
+               CefRefPtr<CefFrame> frame,
+               int64_t query_id,
+               const CefString& request,
+               bool persistent,
+               CefRefPtr<Callback> callback) override {
+    AssertMainBrowser(browser);
+    AssertMainFrame(frame);
+    EXPECT_NE(0, query_id);
+    EXPECT_FALSE(persistent);
+    EXPECT_EQ(std::to_string(string_length_), request.ToString());
+
+    const size_t message_size =
+        static_cast<size_t>(std::stoi(request.ToString()));
+    got_on_query_.yes();
+
+    callback_ = callback;
+    ExecuteCallback(message_size);
+
+    return true;
+  }
+
+  void DestroyTest() override {
+    EXPECT_TRUE(got_notify_);
+    EXPECT_TRUE(got_on_query_);
+    EXPECT_FALSE(callback_.get());
+
+    TestHandler::DestroyTest();
+  }
+
+ private:
+  const TestType test_type_;
+  const size_t string_length_;
+  const CharType symbol_;
+
+  CefRefPtr<Callback> callback_;
+
+  TrackCallback got_on_query_;
+  TrackCallback got_notify_;
+};
+
+using CharTestHandler = ThresholdTestHandler<char>;
+using CharTestHandlerPtr = CefRefPtr<CharTestHandler>;
+
+using WCharTestHandler = ThresholdTestHandler<wchar_t>;
+using WCharTestHandlerPtr = CefRefPtr<WCharTestHandler>;
+
+}  // namespace
+
+TEST(MessageRouterTest, ThresholdMessageUnderSuccessCallback) {
+  const auto under_threshold = kMsgSizeThresholdInBytes - kCharSize;
+  const auto string_length = under_threshold / kCharSize;
+  CharTestHandlerPtr handler =
+      new CharTestHandler(TestType::SUCCESS, string_length, 'A');
+  handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
+
+  handler->ExecuteTest();
+
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(MessageRouterTest, ThresholdMessageExactSuccessCallback) {
+  const auto string_length = kMsgSizeThresholdInBytes / kCharSize;
+  CharTestHandlerPtr handler =
+      new CharTestHandler(TestType::SUCCESS, string_length, 'A');
+  handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
+
+  handler->ExecuteTest();
+
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(MessageRouterTest, ThresholdMessageOverSuccessCallback) {
+  const auto over_threshold = kMsgSizeThresholdInBytes + kCharSize;
+  const auto string_length = over_threshold / kCharSize;
+  CharTestHandlerPtr handler =
+      new CharTestHandler(TestType::SUCCESS, string_length, 'A');
+  handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
+
+  handler->ExecuteTest();
+
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(MessageRouterTest, ThresholdMessageUnderFailureCallback) {
+  const auto under_threshold = kMsgSizeThresholdInBytes - kCharSize;
+  const auto string_length = under_threshold / kCharSize;
+  CharTestHandlerPtr handler =
+      new CharTestHandler(TestType::FAILURE, string_length, 'A');
+  handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
+
+  handler->ExecuteTest();
+
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(MessageRouterTest, ThresholdMessageOverFailureCallback) {
+  const auto over_threshold = kMsgSizeThresholdInBytes + kCharSize;
+  const auto string_length = over_threshold / kCharSize;
+  CharTestHandlerPtr handler =
+      new CharTestHandler(TestType::FAILURE, string_length, 'A');
+  handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
+
+  handler->ExecuteTest();
+
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(MessageRouterTest, ThresholdUtf8MessageUnderSuccessCallback) {
+  const auto under_threshold = kMsgSizeThresholdInBytes - kCharSize;
+  const auto string_length = under_threshold / kCharSize;
+  WCharTestHandlerPtr handler =
+      new WCharTestHandler(TestType::SUCCESS, string_length, L'\u304B');
+  handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
+
+  handler->ExecuteTest();
+
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(MessageRouterTest, ThresholdUtf8MessageOverSuccessCallback) {
+  const auto over_threshold = kMsgSizeThresholdInBytes + kCharSize;
+  const auto string_length = over_threshold / kCharSize;
+  WCharTestHandlerPtr handler =
+      new WCharTestHandler(TestType::SUCCESS, string_length, L'\u304B');
+  handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
+
+  handler->ExecuteTest();
+
+  ReleaseAndWaitForDestructor(handler);
+}
diff --git a/src/tests/ceftests/message_router_unittest.cc b/src/tests/ceftests/message_router_unittest.cc
deleted file mode 100644
index d904734..0000000
--- a/src/tests/ceftests/message_router_unittest.cc
+++ /dev/null
@@ -1,2927 +0,0 @@
-// Copyright (c) 2014 The Chromium Embedded Framework 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 <cstdlib>
-#include <set>
-#include <sstream>
-#include <vector>
-
-#include "include/base/cef_bind.h"
-#include "include/base/cef_weak_ptr.h"
-#include "include/cef_v8.h"
-#include "include/wrapper/cef_closure_task.h"
-#include "tests/ceftests/routing_test_handler.h"
-#include "tests/gtest/include/gtest/gtest.h"
-#include "tests/shared/renderer/client_app_renderer.h"
-
-using client::ClientAppRenderer;
-
-namespace {
-
-const char kTestDomainRoot[] = "http://tests-mr";
-const char kTestDomain1[] = "http://tests-mr1.com/";
-const char kTestDomain2[] = "http://tests-mr2.com/";
-const char kTestDomain3[] = "http://tests-mr3.com/";
-
-const char kDoneMessageName[] = "mrtNotifyMsg";
-
-const char kJSNotifyFunc[] = "mrtNotify";
-const char kJSAssertTotalCountFunc[] = "mrtAssertTotalCount";
-const char kJSAssertBrowserCountFunc[] = "mrtAssertBrowserCount";
-const char kJSAssertContextCountFunc[] = "mrtAssertContextCount";
-
-void SetRouterConfig(CefMessageRouterConfig& config) {
-  config.js_query_function = "mrtQuery";
-  config.js_cancel_function = "mrtQueryCancel";
-}
-
-// Handle the renderer side of the routing implementation.
-class MRRenderDelegate : public ClientAppRenderer::Delegate {
- public:
-  class V8HandlerImpl : public CefV8Handler {
-   public:
-    explicit V8HandlerImpl(CefRefPtr<MRRenderDelegate> delegate)
-        : delegate_(delegate) {}
-
-    bool Execute(const CefString& name,
-                 CefRefPtr<CefV8Value> object,
-                 const CefV8ValueList& arguments,
-                 CefRefPtr<CefV8Value>& retval,
-                 CefString& exception) override {
-      const std::string& message_name = name;
-      if (message_name == kJSNotifyFunc) {
-        EXPECT_EQ(1U, arguments.size());
-        EXPECT_TRUE(arguments[0]->IsString());
-
-        const CefString& msg = arguments[0]->GetStringValue();
-        CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
-        CefRefPtr<CefFrame> frame = context->GetFrame();
-
-        CefRefPtr<CefProcessMessage> message =
-            CefProcessMessage::Create(kDoneMessageName);
-        CefRefPtr<CefListValue> args = message->GetArgumentList();
-        args->SetString(0, msg);
-        frame->SendProcessMessage(PID_BROWSER, message);
-        return true;
-      } else {
-        EXPECT_EQ(1U, arguments.size());
-        EXPECT_TRUE(arguments[0]->IsInt());
-
-        const int expected_count = arguments[0]->GetIntValue();
-        int actual_count = -1;
-
-        CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
-        CefRefPtr<CefBrowser> browser = context->GetBrowser();
-
-        if (name == kJSAssertTotalCountFunc) {
-          actual_count =
-              delegate_->message_router_->GetPendingCount(nullptr, nullptr);
-        } else if (name == kJSAssertBrowserCountFunc) {
-          actual_count =
-              delegate_->message_router_->GetPendingCount(browser, nullptr);
-        } else if (name == kJSAssertContextCountFunc) {
-          actual_count =
-              delegate_->message_router_->GetPendingCount(browser, context);
-        }
-
-        if (expected_count != actual_count) {
-          std::stringstream ss;
-          ss << message_name << " failed; expected " << expected_count
-             << ", got " << actual_count;
-          exception = ss.str();
-        }
-      }
-
-      return true;
-    }
-
-   private:
-    CefRefPtr<MRRenderDelegate> delegate_;
-
-    IMPLEMENT_REFCOUNTING(V8HandlerImpl);
-  };
-
-  MRRenderDelegate() {}
-
-  void OnWebKitInitialized(CefRefPtr<ClientAppRenderer> app) override {
-    // Create the renderer-side router for query handling.
-    CefMessageRouterConfig config;
-    SetRouterConfig(config);
-    message_router_ = CefMessageRouterRendererSide::Create(config);
-  }
-
-  void OnContextCreated(CefRefPtr<ClientAppRenderer> app,
-                        CefRefPtr<CefBrowser> browser,
-                        CefRefPtr<CefFrame> frame,
-                        CefRefPtr<CefV8Context> context) override {
-    const std::string& url = frame->GetURL();
-    if (url.find(kTestDomainRoot) != 0)
-      return;
-
-    message_router_->OnContextCreated(browser, frame, context);
-
-    // Register function handlers with the 'window' object.
-    CefRefPtr<CefV8Value> window = context->GetGlobal();
-
-    CefRefPtr<V8HandlerImpl> handler = new V8HandlerImpl(this);
-    CefV8Value::PropertyAttribute attributes =
-        static_cast<CefV8Value::PropertyAttribute>(
-            V8_PROPERTY_ATTRIBUTE_READONLY | V8_PROPERTY_ATTRIBUTE_DONTENUM |
-            V8_PROPERTY_ATTRIBUTE_DONTDELETE);
-
-    CefRefPtr<CefV8Value> notify_func =
-        CefV8Value::CreateFunction(kJSNotifyFunc, handler.get());
-    window->SetValue(kJSNotifyFunc, notify_func, attributes);
-
-    CefRefPtr<CefV8Value> total_count_func =
-        CefV8Value::CreateFunction(kJSAssertTotalCountFunc, handler.get());
-    window->SetValue(kJSAssertTotalCountFunc, total_count_func, attributes);
-
-    CefRefPtr<CefV8Value> browser_count_func =
-        CefV8Value::CreateFunction(kJSAssertBrowserCountFunc, handler.get());
-    window->SetValue(kJSAssertBrowserCountFunc, browser_count_func, attributes);
-
-    CefRefPtr<CefV8Value> context_count_func =
-        CefV8Value::CreateFunction(kJSAssertContextCountFunc, handler.get());
-    window->SetValue(kJSAssertContextCountFunc, context_count_func, attributes);
-  }
-
-  void OnContextReleased(CefRefPtr<ClientAppRenderer> app,
-                         CefRefPtr<CefBrowser> browser,
-                         CefRefPtr<CefFrame> frame,
-                         CefRefPtr<CefV8Context> context) override {
-    const std::string& url = frame->GetURL();
-    if (url.find(kTestDomainRoot) != 0)
-      return;
-
-    message_router_->OnContextReleased(browser, frame, context);
-  }
-
-  bool OnProcessMessageReceived(CefRefPtr<ClientAppRenderer> app,
-                                CefRefPtr<CefBrowser> browser,
-                                CefRefPtr<CefFrame> frame,
-                                CefProcessId source_process,
-                                CefRefPtr<CefProcessMessage> message) override {
-    const std::string& url = browser->GetMainFrame()->GetURL();
-    if (url.find(kTestDomainRoot) != 0)
-      return false;
-
-    return message_router_->OnProcessMessageReceived(browser, frame,
-                                                     source_process, message);
-  }
-
- private:
-  CefRefPtr<CefMessageRouterRendererSide> message_router_;
-
-  IMPLEMENT_REFCOUNTING(MRRenderDelegate);
-};
-
-}  // namespace
-
-// Entry point for creating the test delegate.
-// Called from client_app_delegates.cc.
-void CreateMessageRouterRendererTests(
-    ClientAppRenderer::DelegateSet& delegates) {
-  delegates.insert(new MRRenderDelegate);
-}
-
-namespace {
-
-class MRTestHandler : public TestHandler {
- public:
-  MRTestHandler() {}
-
-  void RunTest() override {
-    RunMRTest();
-
-    // Time out the test after a reasonable period of time.
-    SetTestTimeout(10000);
-  }
-
-  void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
-    if (!message_router_.get()) {
-      // Create the browser-side router for query handling.
-      CefMessageRouterConfig config;
-      SetRouterConfig(config);
-      message_router_ = CefMessageRouterBrowserSide::Create(config);
-      AddHandlers(message_router_);
-    }
-    TestHandler::OnAfterCreated(browser);
-  }
-
-  void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
-    message_router_->OnBeforeClose(browser);
-    TestHandler::OnBeforeClose(browser);
-  }
-
-  void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
-                                 TerminationStatus status) override {
-    message_router_->OnRenderProcessTerminated(browser);
-  }
-
-  // Only call this method if the navigation isn't canceled.
-  bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
-                      CefRefPtr<CefFrame> frame,
-                      CefRefPtr<CefRequest> request,
-                      bool user_gesture,
-                      bool is_redirect) override {
-    message_router_->OnBeforeBrowse(browser, frame);
-    return false;
-  }
-
-  // Returns true if the router handled the navigation.
-  bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
-                                CefRefPtr<CefFrame> frame,
-                                CefProcessId source_process,
-                                CefRefPtr<CefProcessMessage> message) override {
-    const std::string& message_name = message->GetName();
-    if (message_name == kDoneMessageName) {
-      CefRefPtr<CefListValue> args = message->GetArgumentList();
-      EXPECT_EQ(1U, args->GetSize());
-      EXPECT_EQ(VTYPE_STRING, args->GetType(0));
-      OnNotify(browser, frame, args->GetString(0));
-      return true;
-    }
-
-    return message_router_->OnProcessMessageReceived(browser, frame,
-                                                     source_process, message);
-  }
-
-  CefRefPtr<CefMessageRouterBrowserSide> GetRouter() const {
-    return message_router_;
-  }
-
- protected:
-  virtual void RunMRTest() = 0;
-
-  virtual void AddHandlers(
-      CefRefPtr<CefMessageRouterBrowserSide> message_router) = 0;
-
-  virtual void OnNotify(CefRefPtr<CefBrowser> browser,
-                        CefRefPtr<CefFrame> frame,
-                        const std::string& message) = 0;
-
-  bool AssertQueryCount(CefRefPtr<CefBrowser> browser,
-                        CefMessageRouterBrowserSide::Handler* handler,
-                        int expected_count) {
-    int actual_count = message_router_->GetPendingCount(browser, handler);
-    EXPECT_EQ(expected_count, actual_count);
-    return (expected_count == actual_count);
-  }
-
-  void AssertMainBrowser(CefRefPtr<CefBrowser> browser) {
-    EXPECT_TRUE(browser.get());
-    EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
-  }
-
- private:
-  CefRefPtr<CefMessageRouterBrowserSide> message_router_;
-
-  IMPLEMENT_REFCOUNTING(MRTestHandler);
-};
-
-// Implementation of MRTestHandler that loads a single page.
-class SingleLoadTestHandler : public MRTestHandler,
-                              public CefMessageRouterBrowserSide::Handler {
- public:
-  SingleLoadTestHandler()
-      : main_url_(std::string(kTestDomain1) + "main.html") {}
-
-  const std::string& GetMainURL() { return main_url_; }
-
- protected:
-  void RunMRTest() override {
-    AddOtherResources();
-    AddResource(main_url_, GetMainHTML(), "text/html");
-
-    CreateBrowser(main_url_, nullptr);
-  }
-
-  void AddHandlers(
-      CefRefPtr<CefMessageRouterBrowserSide> message_router) override {
-    message_router->AddHandler(this, false);
-  }
-
-  virtual void AddOtherResources() {}
-
-  virtual std::string GetMainHTML() = 0;
-
-  void AssertMainFrame(CefRefPtr<CefFrame> frame) {
-    EXPECT_TRUE(frame.get());
-    EXPECT_TRUE(frame->IsMain());
-    EXPECT_STREQ(main_url_.c_str(), frame->GetURL().ToString().c_str());
-  }
-
- private:
-  const std::string main_url_;
-};
-
-// Used to verify that the test harness (bound functions) behave correctly.
-class HarnessTestHandler : public SingleLoadTestHandler {
- public:
-  HarnessTestHandler(bool test_success) : test_success_(test_success) {}
-
-  std::string GetMainHTML() override {
-    std::string html;
-    if (test_success_) {
-      // All assertions should pass.
-      html =
-          "<html><body><script>\n"
-          "var fail_ct = 0;\n"
-          "try { window.mrtAssertTotalCount(0); } catch (e) { fail_ct++; }\n"
-          "try { window.mrtAssertBrowserCount(0); } catch (e) { fail_ct++; }\n"
-          "try { window.mrtAssertContextCount(0); } catch (e) { fail_ct++; }\n"
-          "window.mrtNotify('' + (fail_ct == 0));"
-          "</script></body></html>";
-    } else {
-      // All assertions should fail.
-      html =
-          "<html><body><script>\n"
-          "var fail_ct = 0;\n"
-          "try { window.mrtAssertTotalCount(1); } catch (e) { fail_ct++; }\n"
-          "try { window.mrtAssertBrowserCount(1); } catch (e) { fail_ct++; }\n"
-          "try { window.mrtAssertContextCount(1); } catch (e) { fail_ct++; }\n"
-          "window.mrtNotify('' + (fail_ct == 3));"
-          "</script></body></html>";
-    }
-    return html;
-  }
-
-  void OnNotify(CefRefPtr<CefBrowser> browser,
-                CefRefPtr<CefFrame> frame,
-                const std::string& message) override {
-    AssertMainBrowser(browser);
-    AssertMainFrame(frame);
-
-    got_done_.yes();
-    EXPECT_STREQ("true", message.c_str());
-    DestroyTest();
-  }
-
-  void DestroyTest() override {
-    EXPECT_TRUE(got_done_);
-    TestHandler::DestroyTest();
-  }
-
- private:
-  const bool test_success_;
-  TrackCallback got_done_;
-};
-
-}  // namespace
-
-// Verify that the test harness works with successful assertions.
-TEST(MessageRouterTest, HarnessSuccess) {
-  CefRefPtr<HarnessTestHandler> handler = new HarnessTestHandler(true);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Verify that the test harness works with failed assertions.
-TEST(MessageRouterTest, HarnessFailure) {
-  CefRefPtr<HarnessTestHandler> handler = new HarnessTestHandler(false);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-namespace {
-
-const char kSingleQueryRequest[] = "request_context";
-const char kSingleQueryResponse[] = "success_response";
-const int kSingleQueryErrorCode = 5;
-const char kSingleQueryErrorMessage[] = "error_message";
-
-// Test a single query in a single page load.
-class SingleQueryTestHandler : public SingleLoadTestHandler {
- public:
-  enum TestType {
-    SUCCESS,
-    FAILURE,
-    CANCEL,
-  };
-
-  SingleQueryTestHandler(TestType type, bool sync_callback)
-      : test_type_(type), sync_callback_(sync_callback), query_id_(0) {}
-
-  std::string GetMainHTML() override {
-    std::string html;
-
-    std::stringstream ss;
-    ss << kSingleQueryErrorCode;
-    const std::string& errorCodeStr = ss.str();
-
-    html =
-        "<html><body><script>\n"
-        // No requests should exist.
-        "window.mrtAssertTotalCount(0);\n"
-        "window.mrtAssertBrowserCount(0);\n"
-        "window.mrtAssertContextCount(0);\n"
-        // Send the query.
-        "var request_id = window.mrtQuery({\n"
-        "  request: '" +
-        std::string(kSingleQueryRequest) +
-        "',\n"
-        "  persistent: false,\n"
-        "  onSuccess: function(response) {\n"
-        // Request should be removed before callback is executed.
-        "    window.mrtAssertTotalCount(0);\n"
-        "    window.mrtAssertBrowserCount(0);\n"
-        "    window.mrtAssertContextCount(0);\n"
-        "    if (response == '" +
-        std::string(kSingleQueryResponse) +
-        "')\n"
-        "      window.mrtNotify('success');\n"
-        "    else\n"
-        "      window.mrtNotify('error-onSuccess');\n"
-        "  },\n"
-        "  onFailure: function(error_code, error_message) {\n"
-        // Request should be removed before callback is executed.
-        "    window.mrtAssertTotalCount(0);\n"
-        "    window.mrtAssertBrowserCount(0);\n"
-        "    window.mrtAssertContextCount(0);\n"
-        "    if (error_code == " +
-        errorCodeStr + " && error_message == '" +
-        std::string(kSingleQueryErrorMessage) +
-        "')\n"
-        "      window.mrtNotify('failure');\n"
-        "    else\n"
-        "      window.mrtNotify('error-onFailure');\n"
-        "  }\n"
-        "});\n"
-        // Request should exist.
-        "window.mrtAssertTotalCount(1);\n"
-        "window.mrtAssertBrowserCount(1);\n"
-        "window.mrtAssertContextCount(1);\n";
-
-    if (test_type_ == CANCEL) {
-      html +=
-          "window.mrtQueryCancel(request_id);\n"
-          // Request should be removed immediately.
-          "window.mrtAssertTotalCount(0);\n"
-          "window.mrtAssertBrowserCount(0);\n"
-          "window.mrtAssertContextCount(0);\n"
-          "window.mrtNotify('cancel');\n";
-    }
-
-    html += "</script></body></html>";
-    return html;
-  }
-
-  void OnNotify(CefRefPtr<CefBrowser> browser,
-                CefRefPtr<CefFrame> frame,
-                const std::string& message) override {
-    AssertMainBrowser(browser);
-    AssertMainFrame(frame);
-
-    // OnNotify only be called once.
-    EXPECT_FALSE(got_notify_);
-    got_notify_.yes();
-
-    if (test_type_ == SUCCESS) {
-      EXPECT_STREQ("success", message.c_str());
-    } else if (test_type_ == FAILURE) {
-      EXPECT_STREQ("failure", message.c_str());
-    } else if (test_type_ == CANCEL) {
-      EXPECT_STREQ("cancel", message.c_str());
-    }
-
-    DestroyTestIfDone();
-  }
-
-  void ExecuteCallback() {
-    EXPECT_TRUE(callback_.get());
-    if (test_type_ == SUCCESS) {
-      callback_->Success(kSingleQueryResponse);
-    } else if (test_type_ == FAILURE) {
-      callback_->Failure(kSingleQueryErrorCode, kSingleQueryErrorMessage);
-    } else {
-      EXPECT_TRUE(false);  // Not reached.
-    }
-    callback_ = nullptr;
-  }
-
-  bool OnQuery(CefRefPtr<CefBrowser> browser,
-               CefRefPtr<CefFrame> frame,
-               int64 query_id,
-               const CefString& request,
-               bool persistent,
-               CefRefPtr<Callback> callback) override {
-    AssertMainBrowser(browser);
-    AssertMainFrame(frame);
-    EXPECT_NE(0, query_id);
-    EXPECT_FALSE(persistent);
-    EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str());
-
-    got_on_query_.yes();
-
-    query_id_ = query_id;
-    callback_ = callback;
-
-    if (test_type_ == SUCCESS || test_type_ == FAILURE) {
-      if (sync_callback_) {
-        ExecuteCallback();
-      } else {
-        CefPostTask(TID_UI,
-                    base::Bind(&SingleQueryTestHandler::ExecuteCallback, this));
-      }
-    }
-
-    return true;
-  }
-
-  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
-                       CefRefPtr<CefFrame> frame,
-                       int64 query_id) override {
-    AssertMainBrowser(browser);
-    AssertMainFrame(frame);
-    EXPECT_EQ(test_type_, CANCEL);
-    EXPECT_EQ(query_id_, query_id);
-    EXPECT_TRUE(got_on_query_);
-    EXPECT_TRUE(callback_.get());
-
-    got_on_query_canceled_.yes();
-    callback_ = nullptr;
-
-    DestroyTestIfDone();
-  }
-
-  void DestroyTestIfDone() {
-    bool destroy_test = false;
-    if (test_type_ == CANCEL)
-      destroy_test = got_notify_ && got_on_query_canceled_;
-    else
-      destroy_test = got_notify_;
-    if (destroy_test)
-      DestroyTest();
-  }
-
-  void DestroyTest() override {
-    EXPECT_TRUE(got_notify_);
-    EXPECT_TRUE(got_on_query_);
-    EXPECT_FALSE(callback_.get());
-
-    if (test_type_ == CANCEL)
-      EXPECT_TRUE(got_on_query_canceled_);
-    else
-      EXPECT_FALSE(got_on_query_canceled_);
-
-    TestHandler::DestroyTest();
-  }
-
- private:
-  const TestType test_type_;
-  const bool sync_callback_;
-
-  int64 query_id_;
-  CefRefPtr<Callback> callback_;
-
-  TrackCallback got_on_query_;
-  TrackCallback got_on_query_canceled_;
-  TrackCallback got_notify_;
-};
-
-}  // namespace
-
-// Test that a single query with successful result delivered synchronously.
-TEST(MessageRouterTest, SingleQuerySuccessSyncCallback) {
-  CefRefPtr<SingleQueryTestHandler> handler =
-      new SingleQueryTestHandler(SingleQueryTestHandler::SUCCESS, true);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that a single query with successful result delivered asynchronously.
-TEST(MessageRouterTest, SingleQuerySuccessAsyncCallback) {
-  CefRefPtr<SingleQueryTestHandler> handler =
-      new SingleQueryTestHandler(SingleQueryTestHandler::SUCCESS, false);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that a single query with failure result delivered synchronously.
-TEST(MessageRouterTest, SingleQueryFailureSyncCallback) {
-  CefRefPtr<SingleQueryTestHandler> handler =
-      new SingleQueryTestHandler(SingleQueryTestHandler::FAILURE, true);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that a single query with failure result delivered asynchronously.
-TEST(MessageRouterTest, SingleQueryFailureAsyncCallback) {
-  CefRefPtr<SingleQueryTestHandler> handler =
-      new SingleQueryTestHandler(SingleQueryTestHandler::FAILURE, false);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that a single query with cancellation.
-TEST(MessageRouterTest, SingleQueryCancel) {
-  CefRefPtr<SingleQueryTestHandler> handler =
-      new SingleQueryTestHandler(SingleQueryTestHandler::CANCEL, true);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-namespace {
-
-const int kSinglePersistentQueryResponseCount = 10;
-
-// Test a single persistent query in a single page load.
-class SinglePersistentQueryTestHandler : public SingleLoadTestHandler {
- public:
-  enum TestType {
-    SUCCESS,
-    FAILURE,
-  };
-
-  SinglePersistentQueryTestHandler(TestType test_type, bool sync_callback)
-      : test_type_(test_type), sync_callback_(sync_callback), query_id_(0) {}
-
-  std::string GetMainHTML() override {
-    std::string html;
-
-    std::stringstream ss;
-    ss << kSinglePersistentQueryResponseCount;
-    const std::string& responseCountStr = ss.str();
-    ss.str("");
-    ss << kSingleQueryErrorCode;
-    const std::string& errorCodeStr = ss.str();
-
-    html =
-        "<html><body><script>\n"
-        // No requests should exist.
-        "window.mrtAssertTotalCount(0);\n"
-        "window.mrtAssertBrowserCount(0);\n"
-        "window.mrtAssertContextCount(0);\n"
-        // Keep track of the number of responses.
-        "var count = 0;\n"
-        // Send the query.
-        "var request_id = window.mrtQuery({\n"
-        "  request: '" +
-        std::string(kSingleQueryRequest) +
-        "',\n"
-        "  persistent: true,\n"
-        "  onSuccess: function(response) {\n"
-        // Request should not be removed.
-        "    window.mrtAssertTotalCount(1);\n"
-        "    window.mrtAssertBrowserCount(1);\n"
-        "    window.mrtAssertContextCount(1);\n"
-        "    if (response == '" +
-        std::string(kSingleQueryResponse) +
-        "') {\n"
-        "      if (++count == " +
-        responseCountStr +
-        ") {\n"
-        "        window.mrtNotify('success');\n"
-        "        window.mrtQueryCancel(request_id);\n"
-        // Request should be removed immediately.
-        "        window.mrtAssertTotalCount(0);\n"
-        "        window.mrtAssertBrowserCount(0);\n"
-        "        window.mrtAssertContextCount(0);\n"
-        "      }\n"
-        "    } else {\n"
-        "      window.mrtNotify('error-onSuccess');\n"
-        "    }\n"
-        "  },\n"
-        "  onFailure: function(error_code, error_message) {\n"
-        // Request should be removed before callback is executed.
-        "    window.mrtAssertTotalCount(0);\n"
-        "    window.mrtAssertBrowserCount(0);\n"
-        "    window.mrtAssertContextCount(0);\n"
-        "    if (error_code == " +
-        errorCodeStr + " && error_message == '" +
-        std::string(kSingleQueryErrorMessage) +
-        "') {\n"
-        "      window.mrtNotify('failure');\n"
-        "    } else {\n"
-        "      window.mrtNotify('error-onFailure');\n"
-        "    }\n"
-        "  }\n"
-        "});\n"
-        // Request should exist.
-        "window.mrtAssertTotalCount(1);\n"
-        "window.mrtAssertBrowserCount(1);\n"
-        "window.mrtAssertContextCount(1);\n";
-
-    html += "</script></body></html>";
-    return html;
-  }
-
-  void OnNotify(CefRefPtr<CefBrowser> browser,
-                CefRefPtr<CefFrame> frame,
-                const std::string& message) override {
-    AssertMainBrowser(browser);
-    AssertMainFrame(frame);
-
-    if (test_type_ == SUCCESS) {
-      EXPECT_STREQ("success", message.c_str());
-    } else if (test_type_ == FAILURE) {
-      EXPECT_STREQ("failure", message.c_str());
-    }
-
-    got_notify_.yes();
-
-    DestroyTestIfDone();
-  }
-
-  void ExecuteCallback() {
-    EXPECT_TRUE(callback_.get());
-    if (test_type_ == SUCCESS) {
-      callback_->Success(kSingleQueryResponse);
-    } else {
-      callback_->Failure(kSingleQueryErrorCode, kSingleQueryErrorMessage);
-      callback_ = nullptr;
-    }
-  }
-
-  bool OnQuery(CefRefPtr<CefBrowser> browser,
-               CefRefPtr<CefFrame> frame,
-               int64 query_id,
-               const CefString& request,
-               bool persistent,
-               CefRefPtr<Callback> callback) override {
-    AssertMainBrowser(browser);
-    AssertMainFrame(frame);
-    EXPECT_NE(0, query_id);
-    EXPECT_TRUE(persistent);
-    EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str());
-
-    got_on_query_.yes();
-
-    query_id_ = query_id;
-    callback_ = callback;
-
-    int repeat =
-        (test_type_ == SUCCESS ? kSinglePersistentQueryResponseCount : 1);
-
-    for (int i = 0; i < repeat; ++i) {
-      if (sync_callback_) {
-        ExecuteCallback();
-      } else {
-        CefPostTask(
-            TID_UI,
-            base::Bind(&SinglePersistentQueryTestHandler::ExecuteCallback,
-                       this));
-      }
-    }
-
-    return true;
-  }
-
-  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
-                       CefRefPtr<CefFrame> frame,
-                       int64 query_id) override {
-    AssertMainBrowser(browser);
-    AssertMainFrame(frame);
-    EXPECT_EQ(query_id_, query_id);
-    EXPECT_TRUE(got_on_query_);
-    EXPECT_TRUE(callback_.get());
-
-    got_on_query_canceled_.yes();
-    callback_ = nullptr;
-
-    DestroyTestIfDone();
-  }
-
-  void DestroyTestIfDone() {
-    bool destroy_test = false;
-    if (test_type_ == SUCCESS) {
-      if (got_on_query_ && got_on_query_canceled_ && got_notify_)
-        destroy_test = true;
-    } else if (got_on_query_ && got_notify_) {
-      destroy_test = true;
-    }
-
-    if (destroy_test)
-      DestroyTest();
-  }
-
-  void DestroyTest() override {
-    EXPECT_TRUE(got_notify_);
-    EXPECT_TRUE(got_on_query_);
-    EXPECT_FALSE(callback_.get());
-
-    if (test_type_ == SUCCESS)
-      EXPECT_TRUE(got_on_query_canceled_);
-    else
-      EXPECT_FALSE(got_on_query_canceled_);
-
-    TestHandler::DestroyTest();
-  }
-
- private:
-  const TestType test_type_;
-  const bool sync_callback_;
-
-  int64 query_id_;
-  CefRefPtr<Callback> callback_;
-
-  TrackCallback got_on_query_;
-  TrackCallback got_on_query_canceled_;
-  TrackCallback got_notify_;
-};
-
-}  // namespace
-
-// Test that a single query with successful result delivered synchronously.
-TEST(MessageRouterTest, SinglePersistentQuerySuccessSyncCallback) {
-  CefRefPtr<SinglePersistentQueryTestHandler> handler =
-      new SinglePersistentQueryTestHandler(
-          SinglePersistentQueryTestHandler::SUCCESS, true);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that a single query with successful result delivered asynchronously.
-TEST(MessageRouterTest, SinglePersistentQuerySuccessAsyncCallback) {
-  CefRefPtr<SinglePersistentQueryTestHandler> handler =
-      new SinglePersistentQueryTestHandler(
-          SinglePersistentQueryTestHandler::SUCCESS, false);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that a single query with failure result delivered synchronously.
-TEST(MessageRouterTest, SinglePersistentQueryFailureSyncCallback) {
-  CefRefPtr<SinglePersistentQueryTestHandler> handler =
-      new SinglePersistentQueryTestHandler(
-          SinglePersistentQueryTestHandler::FAILURE, true);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that a single query with failure result delivered asynchronously.
-TEST(MessageRouterTest, SinglePersistentQueryFailureAsyncCallback) {
-  CefRefPtr<SinglePersistentQueryTestHandler> handler =
-      new SinglePersistentQueryTestHandler(
-          SinglePersistentQueryTestHandler::FAILURE, false);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-namespace {
-
-// Test a single unhandled query in a single page load.
-class SingleUnhandledQueryTestHandler : public SingleLoadTestHandler {
- public:
-  SingleUnhandledQueryTestHandler() {}
-
-  std::string GetMainHTML() override {
-    std::string html;
-
-    html =
-        "<html><body><script>\n"
-        // No requests should exist.
-        "window.mrtAssertTotalCount(0);\n"
-        "window.mrtAssertBrowserCount(0);\n"
-        "window.mrtAssertContextCount(0);\n"
-        // Keep track of the number of responses.
-        "var count = 0;\n"
-        // Send the query.
-        "var request_id = window.mrtQuery({\n"
-        "  request: '" +
-        std::string(kSingleQueryRequest) +
-        "',\n"
-        "  persistent: false,\n"
-        "  onSuccess: function(response) {\n"
-        "    window.mrtNotify('error-onSuccess');\n"
-        "  },\n"
-        "  onFailure: function(error_code, error_message) {\n"
-        // Request should be removed before callback is executed.
-        "    window.mrtAssertTotalCount(0);\n"
-        "    window.mrtAssertBrowserCount(0);\n"
-        "    window.mrtAssertContextCount(0);\n"
-        "    if (error_code == -1 && "
-        "error_message == 'The query has been canceled') {\n"
-        "      window.mrtNotify('failure');\n"
-        "    } else {\n"
-        "      window.mrtNotify('error-onFailure');\n"
-        "    }\n"
-        "  }\n"
-        "});\n"
-        // Request should exist.
-        "window.mrtAssertTotalCount(1);\n"
-        "window.mrtAssertBrowserCount(1);\n"
-        "window.mrtAssertContextCount(1);\n";
-
-    html += "</script></body></html>";
-    return html;
-  }
-
-  void OnNotify(CefRefPtr<CefBrowser> browser,
-                CefRefPtr<CefFrame> frame,
-                const std::string& message) override {
-    AssertMainBrowser(browser);
-    AssertMainFrame(frame);
-    EXPECT_STREQ("failure", message.c_str());
-
-    got_notify_.yes();
-
-    DestroyTest();
-  }
-
-  bool OnQuery(CefRefPtr<CefBrowser> browser,
-               CefRefPtr<CefFrame> frame,
-               int64 query_id,
-               const CefString& request,
-               bool persistent,
-               CefRefPtr<Callback> callback) override {
-    AssertMainBrowser(browser);
-    AssertMainFrame(frame);
-    EXPECT_NE(0, query_id);
-    EXPECT_FALSE(persistent);
-    EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str());
-
-    got_on_query_.yes();
-
-    return false;
-  }
-
-  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
-                       CefRefPtr<CefFrame> frame,
-                       int64 query_id) override {
-    EXPECT_FALSE(true);  // Not reached.
-  }
-
-  void DestroyTest() override {
-    EXPECT_TRUE(got_on_query_);
-    EXPECT_TRUE(got_notify_);
-
-    TestHandler::DestroyTest();
-  }
-
- private:
-  TrackCallback got_on_query_;
-  TrackCallback got_notify_;
-};
-
-}  // namespace
-
-// Test that a single unhandled query results in a call to onFailure.
-TEST(MessageRouterTest, SingleUnhandledQuery) {
-  CefRefPtr<SingleUnhandledQueryTestHandler> handler =
-      new SingleUnhandledQueryTestHandler();
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-namespace {
-
-const char kMultiQueryRequestId[] = "request_id";
-const char kMultiQueryRepeatCt[] = "repeat_ct";
-const char kMultiQueryRequest[] = "request";
-const char kMultiQueryResponse[] = "response";
-const char kMultiQuerySuccess[] = "success";
-const char kMultiQueryError[] = "error";
-const char kMultiQueryErrorMessage[] = "errormsg";
-const int kMultiQueryPersistentResponseCount = 5;
-
-// Generates HTML and verifies results for multiple simultanious queries.
-class MultiQueryManager : public CefMessageRouterBrowserSide::Handler {
- public:
-  enum TestType {
-    // Initiates a non-persistent query with a successful response.
-    // OnQuery and OnNotify will be called.
-    SUCCESS,
-
-    // Initiates a non-persistent query with a failure response.
-    // OnQuery and OnNotify will be called.
-    FAILURE,
-
-    // Initiates a persistent query with multiple successful responses.
-    // OnQuery, OnNotify and OnQueryCanceled will be called.
-    PERSISTENT_SUCCESS,
-
-    // Initiates a persistent query with multiple successful responses and one
-    // failure response.
-    // OnQuery and OnNotify will be called.
-    PERSISTENT_FAILURE,
-
-    // Initiates a non-persistent query that will be canceled via JavaScript.
-    // No JavaScript callbacks will be executed.
-    // OnQuery and OnQueryCanceled will be called.
-    CANCEL,
-
-    // Initiates a non-persistent query that will not be manually canceled.
-    // No JavaScript callbacks will be executed.
-    // OnQuery and OnQueryCanceled will be called.
-    AUTOCANCEL,
-
-    // Initiates a persistent query with multiple successful responses that will
-    // not be manually canceled.
-    // OnQuery, OnNotify and OnQueryCanceled will be called.
-    PERSISTENT_AUTOCANCEL,
-  };
-
-  class Observer {
-   public:
-    // Called when all manual queries are complete.
-    virtual void OnManualQueriesCompleted(MultiQueryManager* manager) {}
-
-    // Called when all queries are complete.
-    virtual void OnAllQueriesCompleted(MultiQueryManager* manager) {}
-
-   protected:
-    virtual ~Observer() {}
-  };
-
-  MultiQueryManager(const std::string& label,
-                    bool synchronous,
-                    int id_offset = 0)
-      : label_(label),
-        synchronous_(synchronous),
-        id_offset_(id_offset),
-        finalized_(false),
-        running_(false),
-        manual_total_(0),
-        received_count_(0),
-        manual_complete_count_(0),
-        auto_complete_count_(0),
-        will_cancel_by_removing_handler_(false),
-        weak_ptr_factory_(this) {}
-
-  virtual ~MultiQueryManager() {}
-
-  std::string label() const { return label_; }
-
-  void AddObserver(Observer* observer) {
-    EXPECT_FALSE(running_);
-    observer_set_.insert(observer);
-  }
-
-  void RemoveObserver(Observer* observer) {
-    EXPECT_FALSE(running_);
-    EXPECT_TRUE(observer_set_.erase(observer));
-  }
-
-  // Can be called from any thread, but should always be called from the same
-  // thread.
-  void AddTestQuery(TestType type) {
-    EXPECT_FALSE(finalized_);
-    test_query_vector_.push_back(TestQuery(type));
-    if (!IsAuto(type))
-      manual_total_++;
-  }
-
-  // Must be called after AddTestQuery and before the manager is used.
-  void Finalize() {
-    EXPECT_FALSE(finalized_);
-    finalized_ = true;
-  }
-
-  // Call after all manual queries have completed if you intend to cancel auto
-  // queries by removing the handler.
-  void WillCancelByRemovingHandler() {
-    EXPECT_TRUE(IsManualComplete());
-    will_cancel_by_removing_handler_ = true;
-  }
-
-  std::string GetHTML(bool assert_total, bool assert_browser) const {
-    EXPECT_TRUE(finalized_);
-    EXPECT_FALSE(running_);
-
-    std::string html;
-
-    html = "<html><body>" + label_ + "<script>\n";
-
-    // No requests should exist.
-    if (assert_total)
-      html += "window.mrtAssertTotalCount(0);\n";
-    if (assert_browser)
-      html += "window.mrtAssertBrowserCount(0);\n";
-    html += "window.mrtAssertContextCount(0);\n";
-
-    if (synchronous_) {
-      // Run all of the queries synchronously. None will complete before the
-      // last one begins.
-      for (size_t i = 0; i < test_query_vector_.size(); ++i) {
-        const TestQuery& query = test_query_vector_[i];
-        html += GetQueryHTML(static_cast<int>(i), query);
-      }
-
-      const int total_ct = static_cast<int>(test_query_vector_.size());
-
-      // Pending requests should match the total created.
-      const std::string& total_val = GetIntString(total_ct);
-      if (assert_total)
-        html += "window.mrtAssertTotalCount(" + total_val + ");\n";
-      if (assert_browser)
-        html += "window.mrtAssertBrowserCount(" + total_val + ");\n";
-      html += "window.mrtAssertContextCount(" + total_val + ");\n";
-
-      int cancel_ct = 0;
-
-      // Cancel all of the queries with type CANCEL.
-      for (size_t i = 0; i < test_query_vector_.size(); ++i) {
-        const TestQuery& query = test_query_vector_[i];
-        if (query.type == CANCEL) {
-          html += GetCancelHTML(static_cast<int>(i), query);
-          cancel_ct++;
-        }
-      }
-
-      if (cancel_ct > 0) {
-        // Pending requests should match the total not canceled.
-        const std::string& cancel_val = GetIntString(total_ct - cancel_ct);
-        if (assert_total)
-          html += "window.mrtAssertTotalCount(" + cancel_val + ");\n";
-        if (assert_browser)
-          html += "window.mrtAssertBrowserCount(" + cancel_val + ");\n";
-        html += "window.mrtAssertContextCount(" + cancel_val + ");\n";
-      }
-    } else {
-      // Run all of the queries asynchronously. Some may complete before
-      // others begin.
-      for (size_t i = 0; i < test_query_vector_.size(); ++i) {
-        const TestQuery& query = test_query_vector_[i];
-
-        const int index = static_cast<int>(i);
-
-        // Each request is delayed by 10ms from the previous request.
-        const std::string& delay_val = GetIntString(index);
-        const std::string& query_html = GetQueryHTML(index, query);
-
-        html += "window.setTimeout(function() {\n" + query_html;
-
-        if (query.type == CANCEL) {
-          // Cancel the query asynchronously with a 10ms delay.
-          const std::string& request_id_var =
-              GetIDString(kMultiQueryRequestId, index);
-          html +=
-              "  window.setTimeout(function() {\n"
-              "    window.mrtQueryCancel(" +
-              request_id_var +
-              ");\n"
-              "  }, 1);\n";
-        }
-
-        html += "\n}, " + delay_val + ");\n";
-      }
-    }
-
-    html += "</script></body></html>";
-
-    return html;
-  }
-
-  void OnNotify(CefRefPtr<CefBrowser> browser,
-                CefRefPtr<CefFrame> frame,
-                const std::string& message) {
-    EXPECT_TRUE(finalized_);
-    EXPECT_UI_THREAD();
-
-    if (!running_)
-      running_ = true;
-
-    EXPECT_TRUE(browser.get());
-    EXPECT_TRUE(frame.get());
-
-    std::string value;
-    int index = 0;
-    EXPECT_TRUE(SplitIDString(message, &value, &index));
-
-    TestQuery& query = test_query_vector_[index];
-
-    // Verify that browser and frame are the same.
-    EXPECT_EQ(query.browser_id, browser->GetIdentifier()) << index;
-    EXPECT_EQ(query.frame_id, frame->GetIdentifier()) << index;
-
-    // Verify a successful/expected result.
-    if (will_cancel_by_removing_handler_) {
-      // Auto queries receive an onFailure callback which will notify with error
-      // when the handler is removed.
-      EXPECT_STREQ(kMultiQueryError, value.c_str()) << index;
-      EXPECT_TRUE(IsAuto(query.type)) << index;
-      EXPECT_TRUE(query.got_query) << index;
-      if (query.type == PERSISTENT_AUTOCANCEL)
-        EXPECT_TRUE(query.got_success) << index;
-      else
-        EXPECT_FALSE(query.got_success) << index;
-
-      query.got_error.yes();
-
-      // There's a race between OnQueryCanceled and OnNotification. Only call
-      // OnQueryCompleted a single time.
-      if (query.got_query_canceled)
-        OnQueryCompleted(query.type);
-    } else {
-      EXPECT_STREQ(kMultiQuerySuccess, value.c_str()) << index;
-      EXPECT_TRUE(WillNotify(query.type)) << index;
-      EXPECT_TRUE(query.got_query) << index;
-      EXPECT_FALSE(query.got_query_canceled) << index;
-      EXPECT_FALSE(query.got_success) << index;
-
-      query.got_success.yes();
-
-      // PERSISTENT_AUTOCANCEL doesn't call OnReceiveCompleted from OnQuery.
-      if (query.type == PERSISTENT_AUTOCANCEL)
-        OnReceiveCompleted(query.type);
-
-      // Call OnQueryCompleted for types that don't get OnQueryCanceled.
-      if (!WillCancel(query.type))
-        OnQueryCompleted(query.type);
-    }
-  }
-
-  bool OnQuery(CefRefPtr<CefBrowser> browser,
-               CefRefPtr<CefFrame> frame,
-               int64 query_id,
-               const CefString& request,
-               bool persistent,
-               CefRefPtr<Callback> callback) override {
-    EXPECT_TRUE(finalized_);
-    EXPECT_UI_THREAD();
-
-    if (!running_)
-      running_ = true;
-
-    EXPECT_TRUE(browser.get());
-    EXPECT_TRUE(frame.get());
-    EXPECT_NE(0, query_id);
-
-    std::string value;
-    int index = 0;
-    EXPECT_TRUE(SplitIDString(request, &value, &index));
-
-    TestQuery& query = test_query_vector_[index];
-
-    if (IsPersistent(query.type))
-      EXPECT_TRUE(persistent);
-    else
-      EXPECT_FALSE(persistent);
-
-    // Verify expected request.
-    EXPECT_STREQ(kMultiQueryRequest, value.c_str()) << index;
-
-    // Verify that call order is correct.
-    EXPECT_FALSE(query.got_query) << index;
-    EXPECT_FALSE(query.got_query_canceled) << index;
-    EXPECT_FALSE(query.got_success) << index;
-    EXPECT_FALSE(query.got_error) << index;
-
-    query.got_query.yes();
-
-    query.browser_id = browser->GetIdentifier();
-    query.frame_id = frame->GetIdentifier();
-    query.is_main_frame = frame->IsMain();
-
-    if (query.type == SUCCESS) {
-      // Send the single success response.
-      callback->Success(GetIDString(kMultiQueryResponse, index));
-    } else if (IsPersistent(query.type)) {
-      // Send the required number of successful responses.
-      const std::string& response = GetIDString(kMultiQueryResponse, index);
-      for (int i = 0; i < kMultiQueryPersistentResponseCount; ++i)
-        callback->Success(response);
-    }
-
-    if (WillFail(query.type)) {
-      // Send the single failure response.
-      callback->Failure(index, GetIDString(kMultiQueryErrorMessage, index));
-    }
-
-    if (WillCancel(query.type)) {
-      // Hold onto the callback until the query is canceled.
-      query.query_id = query_id;
-      query.callback = callback;
-    }
-
-    // PERSISTENT_AUTOCANCEL will call OnReceiveCompleted once the success
-    // notification is received.
-    if (query.type != PERSISTENT_AUTOCANCEL)
-      OnReceiveCompleted(query.type);
-
-    return true;
-  }
-
-  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
-                       CefRefPtr<CefFrame> frame,
-                       int64 query_id) override {
-    EXPECT_TRUE(finalized_);
-    EXPECT_UI_THREAD();
-
-    if (!running_)
-      running_ = true;
-
-    EXPECT_TRUE(browser.get());
-    EXPECT_TRUE(frame.get());
-    EXPECT_NE(0, query_id);
-
-    bool found = false;
-    for (size_t i = 0; i < test_query_vector_.size(); ++i) {
-      TestQuery& query = test_query_vector_[i];
-      if (query.query_id == query_id) {
-        // Verify that browser and frame are the same.
-        EXPECT_EQ(query.browser_id, browser->GetIdentifier()) << i;
-        if (query.is_main_frame) {
-          EXPECT_TRUE(frame->IsMain()) << i;
-        } else {
-          EXPECT_FALSE(frame->IsMain()) << i;
-          EXPECT_EQ(query.frame_id, frame->GetIdentifier()) << i;
-        }
-
-        // Verify a successful/expected result.
-        EXPECT_TRUE(WillCancel(query.type)) << i;
-        EXPECT_TRUE(query.callback.get()) << i;
-
-        // Release the callback.
-        query.callback = nullptr;
-
-        // Verify that call order is correct.
-        EXPECT_TRUE(query.got_query) << i;
-
-        if (query.type == CANCEL || query.type == AUTOCANCEL) {
-          // No JavaScript onSuccess callback executes.
-          EXPECT_FALSE(query.got_success) << i;
-        } else {
-          // JavaScript onSuccess does execute before cancellation.
-          EXPECT_TRUE(query.got_success) << i;
-        }
-
-        query.got_query_canceled.yes();
-
-        if (will_cancel_by_removing_handler_) {
-          // There's a race between OnQueryCanceled and OnNotification. Only
-          // call OnQueryCompleted a single time.
-          if (query.got_error)
-            OnQueryCompleted(query.type);
-        } else {
-          EXPECT_FALSE(query.got_error) << i;
-
-          // Cancellation is always completion.
-          OnQueryCompleted(query.type);
-        }
-
-        found = true;
-        break;
-      }
-    }
-    EXPECT_TRUE(found);
-  }
-
-  // Asserts that all queries have completed.
-  void AssertAllComplete() const {
-    EXPECT_TRUE(finalized_);
-    EXPECT_FALSE(running_);
-    EXPECT_UI_THREAD();
-
-    for (size_t i = 0; i < test_query_vector_.size(); ++i) {
-      const TestQuery& query = test_query_vector_[i];
-      EXPECT_TRUE(query.got_query) << i;
-
-      if (WillCancel(query.type))
-        EXPECT_TRUE(query.got_query_canceled) << i;
-      else
-        EXPECT_FALSE(query.got_query_canceled) << i;
-
-      if (WillNotify(query.type))
-        EXPECT_TRUE(query.got_success) << i;
-      else
-        EXPECT_FALSE(query.got_success) << i;
-
-      if (IsAuto(query.type) && will_cancel_by_removing_handler_)
-        EXPECT_TRUE(query.got_error);
-      else
-        EXPECT_FALSE(query.got_error);
-
-      EXPECT_FALSE(query.callback.get()) << i;
-    }
-  }
-
-  // Returns true if all manual queries have completed.
-  bool IsManualComplete() const {
-    EXPECT_TRUE(finalized_);
-    EXPECT_UI_THREAD();
-
-    return (manual_complete_count_ == manual_total_);
-  }
-
-  // Returns true if all queries have completed.
-  bool IsAllComplete() const {
-    EXPECT_TRUE(finalized_);
-    EXPECT_UI_THREAD();
-
-    return (manual_complete_count_ + auto_complete_count_ ==
-            static_cast<int>(test_query_vector_.size()));
-  }
-
-  bool HasAutoQueries() const {
-    return (manual_total_ != static_cast<int>(test_query_vector_.size()));
-  }
-
- private:
-  struct TestQuery {
-    explicit TestQuery(TestType test_type)
-        : type(test_type),
-          browser_id(0),
-          frame_id(0),
-          is_main_frame(false),
-          query_id(0) {}
-
-    TestType type;
-
-    // Set in OnQuery and verified in OnNotify or OnQueryCanceled.
-    int browser_id;
-    int64 frame_id;
-    bool is_main_frame;
-
-    // Used when a query is canceled.
-    int64 query_id;
-    CefRefPtr<Callback> callback;
-
-    TrackCallback got_query;
-    TrackCallback got_query_canceled;
-    TrackCallback got_success;
-    TrackCallback got_error;
-  };
-
-  class NotifyTask : public CefTask {
-   public:
-    NotifyTask(base::WeakPtr<MultiQueryManager> weak_ptr, bool notify_all)
-        : weak_ptr_(weak_ptr), notify_all_(notify_all) {}
-
-    void Execute() override {
-      if (weak_ptr_) {
-        if (notify_all_)
-          weak_ptr_->NotifyAllQueriesCompleted();
-        else
-          weak_ptr_->NotifyManualQueriesCompleted();
-      }
-    }
-
-   private:
-    base::WeakPtr<MultiQueryManager> weak_ptr_;
-    const bool notify_all_;
-
-    IMPLEMENT_REFCOUNTING(NotifyTask);
-  };
-
-  static bool IsAuto(TestType type) {
-    return (type == AUTOCANCEL || type == PERSISTENT_AUTOCANCEL);
-  }
-
-  static bool IsPersistent(TestType type) {
-    return (type == PERSISTENT_SUCCESS || type == PERSISTENT_FAILURE ||
-            type == PERSISTENT_AUTOCANCEL);
-  }
-
-  static bool WillFail(TestType type) {
-    return (type == FAILURE || type == PERSISTENT_FAILURE);
-  }
-
-  static bool WillCancel(TestType type) {
-    return (type == PERSISTENT_SUCCESS || type == CANCEL ||
-            type == AUTOCANCEL || type == PERSISTENT_AUTOCANCEL);
-  }
-
-  static bool WillNotify(TestType type) {
-    return (type == SUCCESS || type == PERSISTENT_SUCCESS || type == FAILURE ||
-            type == PERSISTENT_FAILURE || type == PERSISTENT_AUTOCANCEL);
-  }
-
-  void OnReceiveCompleted(TestType type) {
-    const int total_count = static_cast<int>(test_query_vector_.size());
-    if (++received_count_ == total_count && manual_total_ == 0) {
-      // There aren't any manual queries so notify here.
-      CefPostTask(TID_UI,
-                  new NotifyTask(weak_ptr_factory_.GetWeakPtr(), false));
-    }
-  }
-
-  void OnQueryCompleted(TestType type) {
-    const int total_count = static_cast<int>(test_query_vector_.size());
-    EXPECT_LT(manual_complete_count_ + auto_complete_count_, total_count);
-    EXPECT_LE(manual_complete_count_, manual_total_);
-
-    const bool is_auto = IsAuto(type);
-    if (is_auto)
-      auto_complete_count_++;
-    else if (++manual_complete_count_ == manual_total_) {
-      CefPostTask(TID_UI,
-                  new NotifyTask(weak_ptr_factory_.GetWeakPtr(), false));
-    }
-
-    if (auto_complete_count_ + manual_complete_count_ == total_count) {
-      running_ = false;
-      CefPostTask(TID_UI, new NotifyTask(weak_ptr_factory_.GetWeakPtr(), true));
-    }
-  }
-
-  void NotifyManualQueriesCompleted() {
-    if (observer_set_.empty())
-      return;
-
-    // Use a copy of the set in case an Observer is removed while we're
-    // iterating.
-    ObserverSet observer_set = observer_set_;
-
-    ObserverSet::const_iterator it = observer_set.begin();
-    for (; it != observer_set.end(); ++it) {
-      (*it)->OnManualQueriesCompleted(this);
-    }
-  }
-
-  void NotifyAllQueriesCompleted() {
-    if (observer_set_.empty())
-      return;
-
-    // Use a copy of the set in case an Observer is removed while we're
-    // iterating.
-    ObserverSet observer_set = observer_set_;
-
-    ObserverSet::const_iterator it = observer_set.begin();
-    for (; it != observer_set.end(); ++it) {
-      (*it)->OnAllQueriesCompleted(this);
-    }
-  }
-
-  std::string GetQueryHTML(const int index, const TestQuery& query) const {
-    const std::string& request_id_var =
-        GetIDString(kMultiQueryRequestId, index);
-    const std::string& repeat_ct_var = GetIDString(kMultiQueryRepeatCt, index);
-    const std::string& request_val =
-        GetIDString(std::string(kMultiQueryRequest) + ":", index);
-    const std::string& success_val =
-        GetIDString(std::string(kMultiQuerySuccess) + ":", index);
-    const std::string& error_val =
-        GetIDString(std::string(kMultiQueryError) + ":", index);
-
-    std::string html;
-
-    const bool persistent = IsPersistent(query.type);
-
-    if (persistent)
-      html += "var " + repeat_ct_var + " = 0;\n";
-
-    html += "var " + request_id_var +
-            " = window.mrtQuery({\n"
-            "  request: '" +
-            request_val +
-            "',\n"
-            "  persistent: " +
-            (persistent ? "true" : "false") + ",\n";
-
-    if (query.type == SUCCESS) {
-      const std::string& response_val = GetIDString(kMultiQueryResponse, index);
-
-      html +=
-          "  onSuccess: function(response) {\n"
-          "    if (response == '" +
-          response_val +
-          "')\n"
-          "      window.mrtNotify('" +
-          success_val +
-          "');\n"
-          "    else\n"
-          "      window.mrtNotify('" +
-          error_val +
-          "');\n"
-          "  },\n"
-          "  onFailure: function(error_code, error_message) {\n"
-          "    window.mrtNotify('" +
-          error_val +
-          "');\n"
-          "  }\n";
-    } else if (query.type == FAILURE) {
-      const std::string& error_code_val = GetIntString(index);
-      const std::string& error_message_val =
-          GetIDString(kMultiQueryErrorMessage, index);
-
-      html +=
-          "  onSuccess: function(response) {\n"
-          "    window.mrtNotify('" +
-          error_val +
-          "');\n"
-          "  },\n"
-          "  onFailure: function(error_code, error_message) {\n"
-          "    if (error_code == " +
-          error_code_val + " && error_message == '" + error_message_val +
-          "')\n"
-          "      window.mrtNotify('" +
-          success_val +
-          "');\n"
-          "    else\n"
-          "      window.mrtNotify('" +
-          error_val +
-          "');\n"
-          "  }\n";
-    } else if (query.type == PERSISTENT_SUCCESS ||
-               query.type == PERSISTENT_AUTOCANCEL) {
-      const std::string& response_val = GetIDString(kMultiQueryResponse, index);
-      const std::string& repeat_ct =
-          GetIntString(kMultiQueryPersistentResponseCount);
-
-      html +=
-          "  onSuccess: function(response) {\n"
-          "    if (response == '" +
-          response_val +
-          "') {\n"
-          // Should get repeat_ct number of successful responses.
-          "      if (++" +
-          repeat_ct_var + " == " + repeat_ct +
-          ") {\n"
-          "        window.mrtNotify('" +
-          success_val + "');\n";
-
-      if (query.type == PERSISTENT_SUCCESS) {
-        // Manually cancel the request.
-        html += "        window.mrtQueryCancel(" + request_id_var + ");\n";
-      }
-
-      html +=
-          "      }\n"
-          "    } else {\n"
-          "      window.mrtNotify('" +
-          error_val +
-          "');\n"
-          "    }\n"
-          "  },\n"
-          "  onFailure: function(error_code, error_message) {\n"
-          "    window.mrtNotify('" +
-          error_val +
-          "');\n"
-          "  }\n";
-    } else if (query.type == PERSISTENT_FAILURE) {
-      const std::string& error_code_val = GetIntString(index);
-      const std::string& error_message_val =
-          GetIDString(kMultiQueryErrorMessage, index);
-      const std::string& repeat_ct =
-          GetIntString(kMultiQueryPersistentResponseCount);
-
-      html +=
-          "  onSuccess: function(response) {\n"
-          // Should get some successful responses before failure.
-          "    if (++" +
-          repeat_ct_var + " > " + repeat_ct +
-          ") {\n"
-          "      window.mrtNotify('" +
-          error_val +
-          "');\n"
-          "    }\n"
-          "  },\n"
-          "  onFailure: function(error_code, error_message) {\n"
-          "    if (error_code == " +
-          error_code_val + " && error_message == '" + error_message_val +
-          "'"
-          " && " +
-          repeat_ct_var + " == " + repeat_ct +
-          ")\n"
-          "      window.mrtNotify('" +
-          success_val +
-          "');\n"
-          "    else\n"
-          "      window.mrtNotify('" +
-          error_val +
-          "');\n"
-          "  }\n";
-    } else if (query.type == CANCEL || query.type == AUTOCANCEL) {
-      html +=
-          "  onSuccess: function(response) {\n"
-          "    window.mrtNotify('" +
-          error_val +
-          "');\n"
-          "  },\n"
-          "  onFailure: function(error_code, error_message) {\n"
-          "    window.mrtNotify('" +
-          error_val +
-          "');\n"
-          "  }\n";
-    }
-
-    html += "});\n";
-
-    return html;
-  }
-
-  std::string GetCancelHTML(const int index, const TestQuery& query) const {
-    const std::string& request_id_var =
-        GetIDString(kMultiQueryRequestId, index);
-    return "window.mrtQueryCancel(" + request_id_var + ");\n";
-  }
-
-  std::string GetIDString(const std::string& prefix, int index) const {
-    EXPECT_TRUE(!prefix.empty());
-    std::stringstream ss;
-    ss << prefix << GetIDFromIndex(index);
-    return ss.str();
-  }
-
-  bool SplitIDString(const std::string& str,
-                     std::string* value,
-                     int* index) const {
-    size_t pos = str.find(':');
-    if (pos != std::string::npos) {
-      *value = str.substr(0, pos);
-      *index = GetIndexFromID(atoi(str.substr(pos + 1).c_str()));
-      return (*index >= 0 &&
-              *index < static_cast<int>(test_query_vector_.size()));
-    }
-
-    return false;
-  }
-
-  std::string GetIntString(int val) const {
-    std::stringstream ss;
-    ss << val;
-    return ss.str();
-  }
-
-  int GetIDFromIndex(int index) const { return id_offset_ + index; }
-  int GetIndexFromID(int id) const { return id - id_offset_; }
-
-  const std::string label_;
-  const bool synchronous_;
-  const int id_offset_;
-
-  typedef std::vector<TestQuery> TestQueryVector;
-  TestQueryVector test_query_vector_;
-
-  typedef std::set<Observer*> ObserverSet;
-  ObserverSet observer_set_;
-
-  // Set to true after all queries have been added.
-  bool finalized_;
-  // Set to true while queries are pending.
-  bool running_;
-
-  // Total number of queries that will manually complete.
-  int manual_total_;
-
-  // Number of queries that have been received.
-  int received_count_;
-
-  // Number of queries that have completed successfully.
-  int manual_complete_count_;
-  int auto_complete_count_;
-
-  // If true any pending queries will receive an onFailure callback in addition
-  // to be canceled.
-  bool will_cancel_by_removing_handler_;
-
-  // Should always be the last member.
-  base::WeakPtrFactory<MultiQueryManager> weak_ptr_factory_;
-};
-
-void MakeTestQueries(MultiQueryManager* manager,
-                     bool some,
-                     int many_count = 200) {
-  if (some) {
-    // Test some queries of arbitrary types.
-    // Use a hard-coded list so the behavior is deterministic across test runs.
-    MultiQueryManager::TestType types[] = {
-        MultiQueryManager::PERSISTENT_AUTOCANCEL,
-        MultiQueryManager::SUCCESS,
-        MultiQueryManager::AUTOCANCEL,
-        MultiQueryManager::PERSISTENT_FAILURE,
-        MultiQueryManager::CANCEL,
-        MultiQueryManager::FAILURE,
-        MultiQueryManager::AUTOCANCEL,
-        MultiQueryManager::SUCCESS,
-        MultiQueryManager::PERSISTENT_SUCCESS,
-        MultiQueryManager::SUCCESS,
-        MultiQueryManager::PERSISTENT_AUTOCANCEL,
-        MultiQueryManager::CANCEL,
-        MultiQueryManager::PERSISTENT_SUCCESS,
-        MultiQueryManager::FAILURE,
-    };
-    for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) {
-      manager->AddTestQuery(types[i]);
-    }
-  } else {
-    // Test every type of query.
-    for (int i = 0; i < many_count; ++i) {
-      MultiQueryManager::TestType type = MultiQueryManager::SUCCESS;
-      switch (i % 7) {
-        case 0:
-          type = MultiQueryManager::SUCCESS;
-          break;
-        case 1:
-          type = MultiQueryManager::FAILURE;
-          break;
-        case 2:
-          type = MultiQueryManager::PERSISTENT_SUCCESS;
-          break;
-        case 3:
-          type = MultiQueryManager::PERSISTENT_FAILURE;
-          break;
-        case 4:
-          type = MultiQueryManager::CANCEL;
-          break;
-        case 5:
-          type = MultiQueryManager::AUTOCANCEL;
-          break;
-        case 6:
-          type = MultiQueryManager::PERSISTENT_AUTOCANCEL;
-          break;
-      }
-      manager->AddTestQuery(type);
-    }
-  }
-  manager->Finalize();
-}
-
-// Test multiple queries in a single page load with a single frame.
-class MultiQuerySingleFrameTestHandler : public SingleLoadTestHandler,
-                                         public MultiQueryManager::Observer {
- public:
-  enum CancelType {
-    CANCEL_BY_NAVIGATION,
-    CANCEL_BY_REMOVING_HANDLER,
-    CANCEL_BY_CLOSING_BROWSER,
-  };
-
-  MultiQuerySingleFrameTestHandler(
-      bool synchronous,
-      CancelType cancel_type = CANCEL_BY_NAVIGATION)
-      : manager_(std::string(), synchronous), cancel_type_(cancel_type) {
-    manager_.AddObserver(this);
-  }
-
-  std::string GetMainHTML() override { return manager_.GetHTML(true, true); }
-
-  void OnNotify(CefRefPtr<CefBrowser> browser,
-                CefRefPtr<CefFrame> frame,
-                const std::string& message) override {
-    AssertMainBrowser(browser);
-    AssertMainFrame(frame);
-
-    manager_.OnNotify(browser, frame, message);
-  }
-
-  bool OnQuery(CefRefPtr<CefBrowser> browser,
-               CefRefPtr<CefFrame> frame,
-               int64 query_id,
-               const CefString& request,
-               bool persistent,
-               CefRefPtr<Callback> callback) override {
-    AssertMainBrowser(browser);
-    AssertMainFrame(frame);
-
-    return manager_.OnQuery(browser, frame, query_id, request, persistent,
-                            callback);
-  }
-
-  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
-                       CefRefPtr<CefFrame> frame,
-                       int64 query_id) override {
-    AssertMainBrowser(browser);
-    AssertMainFrame(frame);
-
-    manager_.OnQueryCanceled(browser, frame, query_id);
-  }
-
-  void OnManualQueriesCompleted(MultiQueryManager* manager) override {
-    EXPECT_EQ(manager, &manager_);
-    if (manager_.HasAutoQueries()) {
-      if (cancel_type_ == CANCEL_BY_NAVIGATION) {
-        // Navigate somewhere else to terminate the auto queries.
-        GetBrowser()->GetMainFrame()->LoadURL(std::string(kTestDomain1) +
-                                              "cancel.html");
-      } else if (cancel_type_ == CANCEL_BY_REMOVING_HANDLER) {
-        // Change the expected behavior in the manager.
-        manager_.WillCancelByRemovingHandler();
-        GetRouter()->RemoveHandler(this);
-        // All queries should be immediately canceled.
-        AssertQueryCount(nullptr, nullptr, 0);
-      } else if (cancel_type_ == CANCEL_BY_CLOSING_BROWSER) {
-        // Change the expected behavior in the handler.
-        SetSignalCompletionWhenAllBrowsersClose(false);
-        CloseBrowser(GetBrowser(), false);
-      }
-    }
-  }
-
-  void OnAllQueriesCompleted(MultiQueryManager* manager) override {
-    EXPECT_EQ(manager, &manager_);
-
-    // All queries should be canceled.
-    AssertQueryCount(nullptr, nullptr, 0);
-
-    DestroyTest();
-
-    if (!SignalCompletionWhenAllBrowsersClose()) {
-      // Complete asynchronously so the call stack has a chance to unwind.
-      CefPostTask(
-          TID_UI,
-          base::Bind(&MultiQuerySingleFrameTestHandler::TestComplete, this));
-    }
-  }
-
-  void DestroyTest() override {
-    manager_.AssertAllComplete();
-    TestHandler::DestroyTest();
-  }
-
-  MultiQueryManager* GetManager() { return &manager_; }
-
- private:
-  MultiQueryManager manager_;
-  const CancelType cancel_type_;
-};
-
-}  // namespace
-
-#define MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(name, type, synchronous) \
-  TEST(MessageRouterTest, name) {                                   \
-    CefRefPtr<MultiQuerySingleFrameTestHandler> handler =           \
-        new MultiQuerySingleFrameTestHandler(synchronous);          \
-    MultiQueryManager* manager = handler->GetManager();             \
-    manager->AddTestQuery(MultiQueryManager::type);                 \
-    manager->Finalize();                                            \
-    handler->ExecuteTest();                                         \
-    ReleaseAndWaitForDestructor(handler);                           \
-  }
-
-// Test the query types individually.
-MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameSyncSuccess,
-                                   SUCCESS,
-                                   true)
-MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameAsyncSuccess,
-                                   SUCCESS,
-                                   false)
-MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameSyncFailure,
-                                   FAILURE,
-                                   true)
-MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameAsyncFailure,
-                                   FAILURE,
-                                   false)
-MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameSyncPersistentSuccess,
-                                   PERSISTENT_SUCCESS,
-                                   true)
-MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameAsyncPersistentSuccess,
-                                   PERSISTENT_SUCCESS,
-                                   false)
-MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameSyncPersistentFailure,
-                                   PERSISTENT_FAILURE,
-                                   true)
-MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameAsyncPersistentFailure,
-                                   PERSISTENT_FAILURE,
-                                   false)
-MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameCancel, CANCEL, true)
-MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFrameAutoCancel,
-                                   AUTOCANCEL,
-                                   true)
-MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(MultiQuerySingleFramePersistentAutoCancel,
-                                   PERSISTENT_AUTOCANCEL,
-                                   true)
-
-// Test that one frame can run some queries successfully in a synchronous
-// manner.
-TEST(MessageRouterTest, MultiQuerySingleFrameSyncSome) {
-  CefRefPtr<MultiQuerySingleFrameTestHandler> handler =
-      new MultiQuerySingleFrameTestHandler(true);
-  MakeTestQueries(handler->GetManager(), true);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that one frame can run some queries successfully in an asynchronous
-// manner.
-TEST(MessageRouterTest, MultiQuerySingleFrameAsyncSome) {
-  CefRefPtr<MultiQuerySingleFrameTestHandler> handler =
-      new MultiQuerySingleFrameTestHandler(false);
-  MakeTestQueries(handler->GetManager(), true);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that one frame can run many queries successfully in a synchronous
-// manner.
-TEST(MessageRouterTest, MultiQuerySingleFrameSyncMany) {
-  CefRefPtr<MultiQuerySingleFrameTestHandler> handler =
-      new MultiQuerySingleFrameTestHandler(true);
-  MakeTestQueries(handler->GetManager(), false);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that one frame can run many queries successfully in an asynchronous
-// manner.
-TEST(MessageRouterTest, MultiQuerySingleFrameAsyncMany) {
-  CefRefPtr<MultiQuerySingleFrameTestHandler> handler =
-      new MultiQuerySingleFrameTestHandler(false);
-  MakeTestQueries(handler->GetManager(), false);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that pending queries can be canceled by removing the handler.
-TEST(MessageRouterTest, MultiQuerySingleFrameCancelByRemovingHandler) {
-  CefRefPtr<MultiQuerySingleFrameTestHandler> handler =
-      new MultiQuerySingleFrameTestHandler(
-          false, MultiQuerySingleFrameTestHandler::CANCEL_BY_REMOVING_HANDLER);
-  MakeTestQueries(handler->GetManager(), false);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that pending queries can be canceled by closing the browser.
-TEST(MessageRouterTest, MultiQuerySingleFrameCancelByClosingBrowser) {
-  CefRefPtr<MultiQuerySingleFrameTestHandler> handler =
-      new MultiQuerySingleFrameTestHandler(
-          false, MultiQuerySingleFrameTestHandler::CANCEL_BY_CLOSING_BROWSER);
-  MakeTestQueries(handler->GetManager(), false);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-namespace {
-
-// Test multiple handlers.
-class MultiQueryMultiHandlerTestHandler : public SingleLoadTestHandler,
-                                          public MultiQueryManager::Observer {
- public:
-  class Handler : public CefMessageRouterBrowserSide::Handler {
-   public:
-    Handler(MultiQueryMultiHandlerTestHandler* test_handler, int index)
-        : test_handler_(test_handler), index_(index), query_id_(0) {}
-
-    bool OnQuery(CefRefPtr<CefBrowser> browser,
-                 CefRefPtr<CefFrame> frame,
-                 int64 query_id,
-                 const CefString& request,
-                 bool persistent,
-                 CefRefPtr<Callback> callback) override {
-      // Each handler only handles a single request.
-      std::stringstream ss;
-      ss << kMultiQueryRequest << ":" << index_;
-      const std::string& handled_request = ss.str();
-      if (request != handled_request)
-        return false;
-
-      // Verify that handlers are called in the correct order.
-      if (index_ == 0) {
-        EXPECT_FALSE(test_handler_->got_query0_);
-        EXPECT_FALSE(test_handler_->got_query1_);
-        EXPECT_FALSE(test_handler_->got_query2_);
-
-        test_handler_->got_query0_.yes();
-      } else if (index_ == 1) {
-        EXPECT_TRUE(test_handler_->got_query0_);
-        EXPECT_FALSE(test_handler_->got_query1_);
-        EXPECT_FALSE(test_handler_->got_query2_);
-
-        test_handler_->got_query1_.yes();
-      } else if (index_ == 2) {
-        EXPECT_TRUE(test_handler_->got_query0_);
-        EXPECT_TRUE(test_handler_->got_query1_);
-        EXPECT_FALSE(test_handler_->got_query2_);
-
-        test_handler_->got_query2_.yes();
-      }
-
-      query_id_ = query_id;
-      return test_handler_->OnQuery(browser, frame, query_id, request,
-                                    persistent, callback);
-    }
-
-    void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
-                         CefRefPtr<CefFrame> frame,
-                         int64 query_id) override {
-      // Verify that the correct handler is called for cancellation.
-      EXPECT_EQ(query_id_, query_id);
-
-      if (index_ == 0) {
-        EXPECT_FALSE(test_handler_->got_query_canceled0_);
-        test_handler_->got_query_canceled0_.yes();
-      } else if (index_ == 1) {
-        EXPECT_FALSE(test_handler_->got_query_canceled1_);
-        test_handler_->got_query_canceled1_.yes();
-      } else if (index_ == 2) {
-        EXPECT_FALSE(test_handler_->got_query_canceled2_);
-        test_handler_->got_query_canceled2_.yes();
-      }
-
-      test_handler_->OnQueryCanceled(browser, frame, query_id);
-    }
-
-   private:
-    MultiQueryMultiHandlerTestHandler* test_handler_;
-    const int index_;
-    int query_id_;
-  };
-
-  MultiQueryMultiHandlerTestHandler(bool synchronous,
-                                    bool cancel_by_removing_handler)
-      : manager_(std::string(), synchronous, 0),
-        handler0_(this, 0),
-        handler1_(this, 1),
-        handler2_(this, 2),
-        cancel_by_removing_handler_(cancel_by_removing_handler) {
-    manager_.AddObserver(this);
-
-    // Each handler will handle one of the queries.
-    manager_.AddTestQuery(MultiQueryManager::PERSISTENT_AUTOCANCEL);
-    manager_.AddTestQuery(MultiQueryManager::PERSISTENT_AUTOCANCEL);
-    manager_.AddTestQuery(MultiQueryManager::PERSISTENT_AUTOCANCEL);
-    manager_.Finalize();
-  }
-
-  std::string GetMainHTML() override { return manager_.GetHTML(true, true); }
-
-  void OnNotify(CefRefPtr<CefBrowser> browser,
-                CefRefPtr<CefFrame> frame,
-                const std::string& message) override {
-    AssertMainBrowser(browser);
-    AssertMainFrame(frame);
-
-    manager_.OnNotify(browser, frame, message);
-  }
-
-  bool OnQuery(CefRefPtr<CefBrowser> browser,
-               CefRefPtr<CefFrame> frame,
-               int64 query_id,
-               const CefString& request,
-               bool persistent,
-               CefRefPtr<Callback> callback) override {
-    AssertMainBrowser(browser);
-    AssertMainFrame(frame);
-
-    return manager_.OnQuery(browser, frame, query_id, request, persistent,
-                            callback);
-  }
-
-  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
-                       CefRefPtr<CefFrame> frame,
-                       int64 query_id) override {
-    AssertMainBrowser(browser);
-    AssertMainFrame(frame);
-
-    manager_.OnQueryCanceled(browser, frame, query_id);
-  }
-
-  void OnManualQueriesCompleted(MultiQueryManager* manager) override {
-    EXPECT_EQ(manager, &manager_);
-
-    EXPECT_TRUE(got_query0_);
-    EXPECT_TRUE(got_query1_);
-    EXPECT_TRUE(got_query2_);
-    EXPECT_FALSE(got_query_canceled0_);
-    EXPECT_FALSE(got_query_canceled1_);
-    EXPECT_FALSE(got_query_canceled2_);
-
-    EXPECT_TRUE(manager_.HasAutoQueries());
-
-    CefRefPtr<CefMessageRouterBrowserSide> router = GetRouter();
-
-    // Remove one handler to cancel a query.
-
-    if (cancel_by_removing_handler_) {
-      manager_.WillCancelByRemovingHandler();
-
-      // Each query should be canceled as the handler is removed.
-      EXPECT_TRUE(router->RemoveHandler(&handler1_));
-      EXPECT_FALSE(got_query_canceled0_);
-      EXPECT_TRUE(got_query_canceled1_);
-      EXPECT_FALSE(got_query_canceled2_);
-
-      EXPECT_TRUE(router->RemoveHandler(&handler2_));
-      EXPECT_FALSE(got_query_canceled0_);
-      EXPECT_TRUE(got_query_canceled2_);
-
-      EXPECT_TRUE(router->RemoveHandler(&handler0_));
-      EXPECT_TRUE(got_query_canceled0_);
-    } else {
-      GetBrowser()->GetMainFrame()->LoadURL(std::string(kTestDomain1) +
-                                            "cancel.html");
-    }
-  }
-
-  void OnAllQueriesCompleted(MultiQueryManager* manager) override {
-    EXPECT_EQ(manager, &manager_);
-
-    // All queries should be canceled.
-    AssertQueryCount(nullptr, nullptr, 0);
-
-    DestroyTest();
-  }
-
-  void DestroyTest() override {
-    EXPECT_TRUE(got_query0_);
-    EXPECT_TRUE(got_query1_);
-    EXPECT_TRUE(got_query2_);
-    EXPECT_TRUE(got_query_canceled0_);
-    EXPECT_TRUE(got_query_canceled1_);
-    EXPECT_TRUE(got_query_canceled2_);
-
-    manager_.AssertAllComplete();
-    TestHandler::DestroyTest();
-  }
-
- protected:
-  void AddHandlers(
-      CefRefPtr<CefMessageRouterBrowserSide> message_router) override {
-    // OnQuery call order will verify that the first/last ordering works as
-    // expected.
-    EXPECT_TRUE(message_router->AddHandler(&handler1_, true));
-    EXPECT_TRUE(message_router->AddHandler(&handler0_, true));
-    EXPECT_TRUE(message_router->AddHandler(&handler2_, false));
-
-    // Can't add the same handler multiple times.
-    EXPECT_FALSE(message_router->AddHandler(&handler1_, true));
-  }
-
- private:
-  MultiQueryManager manager_;
-  Handler handler0_;
-  Handler handler1_;
-  Handler handler2_;
-
-  const bool cancel_by_removing_handler_;
-
-  TrackCallback got_query0_;
-  TrackCallback got_query1_;
-  TrackCallback got_query2_;
-
-  TrackCallback got_query_canceled0_;
-  TrackCallback got_query_canceled1_;
-  TrackCallback got_query_canceled2_;
-};
-
-}  // namespace
-
-// Test that multiple handlers behave correctly.
-TEST(MessageRouterTest, MultiQueryMultiHandler) {
-  CefRefPtr<MultiQueryMultiHandlerTestHandler> handler =
-      new MultiQueryMultiHandlerTestHandler(false, false);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that multiple handlers behave correctly. Cancel by removing the
-// handlers.
-TEST(MessageRouterTest, MultiQueryMultiHandlerCancelByRemovingHandler) {
-  CefRefPtr<MultiQueryMultiHandlerTestHandler> handler =
-      new MultiQueryMultiHandlerTestHandler(false, true);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-namespace {
-
-// Map of managers on a per-URL basis.
-class MultiQueryManagerMap : public CefMessageRouterBrowserSide::Handler,
-                             public MultiQueryManager::Observer {
- public:
-  class Observer {
-   public:
-    // Called when all manual queries are complete.
-    virtual void OnMapManualQueriesCompleted(MultiQueryManagerMap* map) {}
-
-    // Called when all queries are complete.
-    virtual void OnMapAllQueriesCompleted(MultiQueryManagerMap* map) {}
-
-   protected:
-    virtual ~Observer() {}
-  };
-
-  MultiQueryManagerMap()
-      : finalized_(false),
-        running_(false),
-        manual_complete_count_(0),
-        total_complete_count_(0) {}
-
-  virtual ~MultiQueryManagerMap() { RemoveAllManagers(); }
-
-  void AddObserver(Observer* observer) {
-    EXPECT_FALSE(running_);
-    observer_set_.insert(observer);
-  }
-
-  void RemoveObserver(Observer* observer) {
-    EXPECT_FALSE(running_);
-    EXPECT_TRUE(observer_set_.erase(observer));
-  }
-
-  MultiQueryManager* CreateManager(const std::string& url, bool synchronous) {
-    EXPECT_FALSE(finalized_);
-
-    MultiQueryManager* manager = new MultiQueryManager(
-        url, synchronous, static_cast<int>(manager_map_.size()) * 1000);
-    manager->AddObserver(this);
-    all_managers_.push_back(manager);
-    pending_managers_.push_back(manager);
-
-    return manager;
-  }
-
-  void Finalize() {
-    EXPECT_FALSE(finalized_);
-    finalized_ = true;
-  }
-
-  std::string GetMainHTML() const {
-    EXPECT_TRUE(finalized_);
-    EXPECT_FALSE(running_);
-
-    std::string html = "<html><body>\n";
-
-    for (size_t i = 0; i < all_managers_.size(); ++i) {
-      const std::string& url = all_managers_[i]->label();
-      const std::string& name = GetNameForURL(url);
-      html += "<iframe id=\"" + name + "\" src=\"" + url + "\"></iframe>\n";
-    }
-
-    html += "</body></html>";
-    return html;
-  }
-
-  void OnNotify(CefRefPtr<CefBrowser> browser,
-                CefRefPtr<CefFrame> frame,
-                const std::string& message) {
-    EXPECT_TRUE(finalized_);
-    if (!running_)
-      running_ = true;
-
-    MultiQueryManager* manager = GetManager(browser, frame);
-    manager->OnNotify(browser, frame, message);
-  }
-
-  bool OnQuery(CefRefPtr<CefBrowser> browser,
-               CefRefPtr<CefFrame> frame,
-               int64 query_id,
-               const CefString& request,
-               bool persistent,
-               CefRefPtr<Callback> callback) override {
-    EXPECT_TRUE(finalized_);
-    if (!running_)
-      running_ = true;
-
-    MultiQueryManager* manager = GetManager(browser, frame);
-    return manager->OnQuery(browser, frame, query_id, request, persistent,
-                            callback);
-  }
-
-  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
-                       CefRefPtr<CefFrame> frame,
-                       int64 query_id) override {
-    EXPECT_TRUE(finalized_);
-    if (!running_)
-      running_ = true;
-
-    MultiQueryManager* manager = GetManager(browser, frame);
-    manager->OnQueryCanceled(browser, frame, query_id);
-  }
-
-  void OnManualQueriesCompleted(MultiQueryManager* manager) override {
-    const int size = static_cast<int>(all_managers_.size());
-    EXPECT_LT(manual_complete_count_, size);
-    if (++manual_complete_count_ == size) {
-      running_ = false;
-
-      // Notify observers.
-      if (!observer_set_.empty()) {
-        // Use a copy of the set in case an Observer is removed while we're
-        // iterating.
-        ObserverSet observer_set = observer_set_;
-
-        ObserverSet::const_iterator it = observer_set.begin();
-        for (; it != observer_set.end(); ++it) {
-          (*it)->OnMapManualQueriesCompleted(this);
-        }
-      }
-    }
-  }
-
-  void OnAllQueriesCompleted(MultiQueryManager* manager) override {
-    const int size = static_cast<int>(all_managers_.size());
-    EXPECT_LT(total_complete_count_, size);
-    if (++total_complete_count_ == size) {
-      running_ = false;
-
-      // Notify observers.
-      if (!observer_set_.empty()) {
-        // Use a copy of the set in case an Observer is removed while we're
-        // iterating.
-        ObserverSet observer_set = observer_set_;
-
-        ObserverSet::const_iterator it = observer_set.begin();
-        for (; it != observer_set.end(); ++it) {
-          (*it)->OnMapAllQueriesCompleted(this);
-        }
-      }
-    }
-  }
-
-  bool AllComplete() const {
-    EXPECT_TRUE(finalized_);
-
-    for (size_t i = 0; i < all_managers_.size(); ++i) {
-      if (!all_managers_[i]->IsAllComplete())
-        return false;
-    }
-    return true;
-  }
-
-  void AssertAllComplete() const {
-    EXPECT_TRUE(finalized_);
-    EXPECT_TRUE(pending_managers_.empty());
-    EXPECT_FALSE(running_);
-
-    for (size_t i = 0; i < all_managers_.size(); ++i) {
-      all_managers_[i]->AssertAllComplete();
-    }
-  }
-
-  bool HasAutoQueries() const {
-    for (size_t i = 0; i < all_managers_.size(); ++i) {
-      if (all_managers_[i]->HasAutoQueries())
-        return true;
-    }
-
-    return false;
-  }
-
-  void OnLoadStart(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame) {
-    if (pending_managers_.empty())
-      return;
-
-    const std::string& expected_url = frame->GetURL();
-    MultiQueryManager* next_manager = nullptr;
-
-    // Find the pending manager that matches the expected URL.
-    ManagerList::iterator it = pending_managers_.begin();
-    for (; it != pending_managers_.end(); ++it) {
-      if ((*it)->label() == expected_url) {
-        next_manager = *it;
-        pending_managers_.erase(it);
-        break;
-      }
-    }
-
-    EXPECT_TRUE(next_manager);
-
-    const int browser_id = browser->GetIdentifier();
-    // Always use the same ID for the main frame.
-    const int64 frame_id = frame->IsMain() ? -1 : frame->GetIdentifier();
-
-    const std::pair<int, int64>& id = std::make_pair(browser_id, frame_id);
-
-    // Remove the currently active manager, if any.
-    ManagerMap::iterator it2 = manager_map_.find(id);
-    if (it2 != manager_map_.end())
-      manager_map_.erase(it2);
-
-    // Add the next manager to the active map.
-    manager_map_.insert(std::make_pair(id, next_manager));
-  }
-
-  MultiQueryManager* GetManager(CefRefPtr<CefBrowser> browser,
-                                CefRefPtr<CefFrame> frame) const {
-    const int browser_id = browser->GetIdentifier();
-    // Always use the same ID for the main frame.
-    const int64 frame_id = frame->IsMain() ? -1 : frame->GetIdentifier();
-
-    // Find the manager in the active map.
-    ManagerMap::const_iterator it =
-        manager_map_.find(std::make_pair(browser_id, frame_id));
-    EXPECT_NE(it, manager_map_.end())
-        << "browser_id = " << browser_id << ", frame_id = " << frame_id;
-    return it->second;
-  }
-
-  void RemoveAllManagers() {
-    EXPECT_TRUE(pending_managers_.empty());
-    if (all_managers_.empty())
-      return;
-
-    for (size_t i = 0; i < all_managers_.size(); ++i) {
-      delete all_managers_[i];
-    }
-    all_managers_.clear();
-    manager_map_.clear();
-  }
-
-  static std::string GetNameForURL(const std::string& url) {
-    // Extract the file name without extension.
-    int pos1 = static_cast<int>(url.rfind("/"));
-    int pos2 = static_cast<int>(url.rfind("."));
-    EXPECT_TRUE(pos1 >= 0 && pos2 >= 0 && pos1 < pos2);
-    return url.substr(pos1 + 1, pos2 - pos1 - 1);
-  }
-
- private:
-  typedef std::vector<MultiQueryManager*> ManagerList;
-  // Map of (browser ID, frame ID) to manager.
-  typedef std::map<std::pair<int, int64>, MultiQueryManager*> ManagerMap;
-
-  // All managers that have been created.
-  ManagerList all_managers_;
-  // Managers that have not yet associated with a frame.
-  ManagerList pending_managers_;
-  // Managers that are currently active.
-  ManagerMap manager_map_;
-
-  typedef std::set<Observer*> ObserverSet;
-  ObserverSet observer_set_;
-
-  // Set to true after all query managers have been added.
-  bool finalized_;
-  // Set to true while queries are pending.
-  bool running_;
-
-  // Number of managers that have completed.
-  int manual_complete_count_;
-  int total_complete_count_;
-};
-
-// Test multiple queries in a single page load with multiple frames.
-class MultiQueryMultiFrameTestHandler : public SingleLoadTestHandler,
-                                        public MultiQueryManagerMap::Observer {
- public:
-  MultiQueryMultiFrameTestHandler(bool synchronous, bool cancel_with_subnav)
-      : synchronous_(synchronous), cancel_with_subnav_(cancel_with_subnav) {
-    manager_map_.AddObserver(this);
-  }
-
-  void AddOtherResources() override {
-    AddSubFrameResource("sub1");
-    AddSubFrameResource("sub2");
-    AddSubFrameResource("sub3");
-    manager_map_.Finalize();
-
-    if (manager_map_.HasAutoQueries()) {
-      cancel_url_ = std::string(kTestDomain1) + "cancel.html";
-      AddResource(cancel_url_, "<html><body>cancel</body></html>", "text/html");
-    }
-  }
-
-  std::string GetMainHTML() override { return manager_map_.GetMainHTML(); }
-
-  void OnLoadStart(CefRefPtr<CefBrowser> browser,
-                   CefRefPtr<CefFrame> frame,
-                   TransitionType transition_type) override {
-    AssertMainBrowser(browser);
-    if (!frame->IsMain())
-      manager_map_.OnLoadStart(browser, frame);
-  }
-
-  void OnNotify(CefRefPtr<CefBrowser> browser,
-                CefRefPtr<CefFrame> frame,
-                const std::string& message) override {
-    AssertMainBrowser(browser);
-    EXPECT_FALSE(frame->IsMain());
-
-    manager_map_.OnNotify(browser, frame, message);
-  }
-
-  bool OnQuery(CefRefPtr<CefBrowser> browser,
-               CefRefPtr<CefFrame> frame,
-               int64 query_id,
-               const CefString& request,
-               bool persistent,
-               CefRefPtr<Callback> callback) override {
-    AssertMainBrowser(browser);
-    EXPECT_FALSE(frame->IsMain());
-
-    return manager_map_.OnQuery(browser, frame, query_id, request, persistent,
-                                callback);
-  }
-
-  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
-                       CefRefPtr<CefFrame> frame,
-                       int64 query_id) override {
-    AssertMainBrowser(browser);
-    EXPECT_FALSE(frame->IsMain());
-
-    manager_map_.OnQueryCanceled(browser, frame, query_id);
-  }
-
-  void OnMapManualQueriesCompleted(MultiQueryManagerMap* map) override {
-    EXPECT_EQ(map, &manager_map_);
-    if (manager_map_.HasAutoQueries()) {
-      CefRefPtr<CefFrame> frame = GetBrowser()->GetMainFrame();
-
-      // Navigate somewhere else to terminate the auto queries.
-      if (cancel_with_subnav_) {
-        // Navigate each subframe individually.
-        const std::string js = "document.getElementById('sub1').src = '" +
-                               cancel_url_ +
-                               "';"
-                               "document.getElementById('sub2').src = '" +
-                               cancel_url_ +
-                               "';"
-                               "document.getElementById('sub3').src = '" +
-                               cancel_url_ + "';";
-
-        frame->ExecuteJavaScript(js, frame->GetURL(), 0);
-      } else {
-        // Navigate the main frame.
-        frame->LoadURL(cancel_url_);
-      }
-    }
-  }
-
-  void OnMapAllQueriesCompleted(MultiQueryManagerMap* map) override {
-    EXPECT_EQ(map, &manager_map_);
-    DestroyTest();
-  }
-
-  void DestroyTest() override {
-    manager_map_.AssertAllComplete();
-    TestHandler::DestroyTest();
-  }
-
- private:
-  void AddSubFrameResource(const std::string& name) {
-    const std::string& url = std::string(kTestDomain1) + name + ".html";
-
-    MultiQueryManager* manager = manager_map_.CreateManager(url, synchronous_);
-    MakeTestQueries(manager, false, 100);
-
-    const std::string& html = manager->GetHTML(false, false);
-    AddResource(url, html, "text/html");
-  }
-
-  const bool synchronous_;
-  const bool cancel_with_subnav_;
-
-  MultiQueryManagerMap manager_map_;
-
-  std::string cancel_url_;
-};
-
-}  // namespace
-
-// Test that multiple frames can run many queries successfully in a synchronous
-// manner.
-TEST(MessageRouterTest, MultiQueryMultiFrameSync) {
-  CefRefPtr<MultiQueryMultiFrameTestHandler> handler =
-      new MultiQueryMultiFrameTestHandler(true, false);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that multiple frames can run many queries successfully in an
-// asynchronous manner.
-TEST(MessageRouterTest, MultiQueryMultiFrameAsync) {
-  CefRefPtr<MultiQueryMultiFrameTestHandler> handler =
-      new MultiQueryMultiFrameTestHandler(false, false);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that multiple frames can run many queries successfully in a synchronous
-// manner. Cancel auto queries with sub-frame navigation.
-TEST(MessageRouterTest, MultiQueryMultiFrameSyncSubnavCancel) {
-  CefRefPtr<MultiQueryMultiFrameTestHandler> handler =
-      new MultiQueryMultiFrameTestHandler(true, true);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that multiple frames can run many queries successfully in an
-// asynchronous manner. Cancel auto queries with sub-frame navigation.
-TEST(MessageRouterTest, MultiQueryMultiFrameAsyncSubnavCancel) {
-  CefRefPtr<MultiQueryMultiFrameTestHandler> handler =
-      new MultiQueryMultiFrameTestHandler(false, true);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-namespace {
-
-// Implementation of MRTestHandler that loads multiple pages and/or browsers and
-// executes multiple queries.
-class MultiQueryMultiLoadTestHandler
-    : public MRTestHandler,
-      public CefMessageRouterBrowserSide::Handler,
-      public MultiQueryManagerMap::Observer,
-      public MultiQueryManager::Observer {
- public:
-  MultiQueryMultiLoadTestHandler(bool some, bool synchronous)
-      : some_(some), synchronous_(synchronous) {
-    manager_map_.AddObserver(this);
-  }
-
-  void OnLoadStart(CefRefPtr<CefBrowser> browser,
-                   CefRefPtr<CefFrame> frame,
-                   TransitionType transition_type) override {
-    manager_map_.OnLoadStart(browser, frame);
-  }
-
-  void OnNotify(CefRefPtr<CefBrowser> browser,
-                CefRefPtr<CefFrame> frame,
-                const std::string& message) override {
-    manager_map_.OnNotify(browser, frame, message);
-  }
-
-  bool OnQuery(CefRefPtr<CefBrowser> browser,
-               CefRefPtr<CefFrame> frame,
-               int64 query_id,
-               const CefString& request,
-               bool persistent,
-               CefRefPtr<Callback> callback) override {
-    return manager_map_.OnQuery(browser, frame, query_id, request, persistent,
-                                callback);
-  }
-
-  void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
-                       CefRefPtr<CefFrame> frame,
-                       int64 query_id) override {
-    manager_map_.OnQueryCanceled(browser, frame, query_id);
-  }
-
-  void OnMapManualQueriesCompleted(MultiQueryManagerMap* map) override {
-    EXPECT_EQ(map, &manager_map_);
-    if (manager_map_.HasAutoQueries()) {
-      // Navigate all browsers somewhere else to terminate the auto queries.
-      BrowserMap browser_map;
-      GetAllBrowsers(&browser_map);
-
-      BrowserMap::const_iterator it = browser_map.begin();
-      for (; it != browser_map.end(); ++it) {
-        it->second->GetMainFrame()->LoadURL(cancel_url_);
-      }
-    }
-  }
-
-  void OnMapAllQueriesCompleted(MultiQueryManagerMap* map) override {
-    EXPECT_EQ(map, &manager_map_);
-    DestroyTest();
-  }
-
-  void DestroyTest() override {
-    manager_map_.AssertAllComplete();
-    TestHandler::DestroyTest();
-  }
-
- protected:
-  void AddHandlers(
-      CefRefPtr<CefMessageRouterBrowserSide> message_router) override {
-    message_router->AddHandler(this, false);
-  }
-
-  void AddManagedResource(const std::string& url,
-                          bool assert_total,
-                          bool assert_browser) {
-    MultiQueryManager* manager = manager_map_.CreateManager(url, synchronous_);
-    manager->AddObserver(this);
-    MakeTestQueries(manager, some_, 75);
-
-    const std::string& html = manager->GetHTML(assert_total, assert_browser);
-    AddResource(url, html, "text/html");
-  }
-
-  void Finalize() {
-    manager_map_.Finalize();
-
-    if (manager_map_.HasAutoQueries()) {
-      cancel_url_ = std::string(kTestDomain1) + "cancel.html";
-      AddResource(cancel_url_, "<html><body>cancel</body></html>", "text/html");
-    }
-  }
-
-  MultiQueryManagerMap manager_map_;
-
- private:
-  const bool some_;
-  const bool synchronous_;
-
-  std::string cancel_url_;
-};
-
-// Test multiple browsers that send queries at the same time.
-class MultiQueryMultiBrowserTestHandler
-    : public MultiQueryMultiLoadTestHandler {
- public:
-  MultiQueryMultiBrowserTestHandler(bool synchronous, bool same_origin)
-      : MultiQueryMultiLoadTestHandler(false, synchronous),
-        same_origin_(same_origin) {}
-
- protected:
-  void RunMRTest() override {
-    const std::string& url1 = std::string(kTestDomain1) + "browser1.html";
-    const std::string& url2 =
-        std::string(same_origin_ ? kTestDomain1 : kTestDomain2) +
-        "browser2.html";
-    const std::string& url3 =
-        std::string(same_origin_ ? kTestDomain1 : kTestDomain3) +
-        "browser3.html";
-
-    AddManagedResource(url1, false, true);
-    AddManagedResource(url2, false, true);
-    AddManagedResource(url3, false, true);
-    Finalize();
-
-    // Create 2 browsers simultaniously.
-    CreateBrowser(url1, nullptr);
-    CreateBrowser(url2, nullptr);
-    CreateBrowser(url3, nullptr);
-  }
-
- private:
-  bool same_origin_;
-};
-
-}  // namespace
-
-// Test that multiple browsers can query simultaniously from the same origin.
-TEST(MessageRouterTest, MultiQueryMultiBrowserSameOriginSync) {
-  CefRefPtr<MultiQueryMultiBrowserTestHandler> handler =
-      new MultiQueryMultiBrowserTestHandler(true, true);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that multiple browsers can query simultaniously from the same origin.
-TEST(MessageRouterTest, MultiQueryMultiBrowserSameOriginAsync) {
-  CefRefPtr<MultiQueryMultiBrowserTestHandler> handler =
-      new MultiQueryMultiBrowserTestHandler(false, true);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that multiple browsers can query simultaniously from different origins.
-TEST(MessageRouterTest, MultiQueryMultiBrowserDifferentOriginSync) {
-  CefRefPtr<MultiQueryMultiBrowserTestHandler> handler =
-      new MultiQueryMultiBrowserTestHandler(true, false);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that multiple browsers can query simultaniously from different origins.
-TEST(MessageRouterTest, MultiQueryMultiBrowserDifferentOriginAsync) {
-  CefRefPtr<MultiQueryMultiBrowserTestHandler> handler =
-      new MultiQueryMultiBrowserTestHandler(false, false);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-namespace {
-
-// Test multiple navigations that send queries sequentially.
-class MultiQueryMultiNavigateTestHandler
-    : public MultiQueryMultiLoadTestHandler {
- public:
-  MultiQueryMultiNavigateTestHandler(bool synchronous, bool same_origin)
-      : MultiQueryMultiLoadTestHandler(false, synchronous),
-        same_origin_(same_origin) {}
-
-  void OnManualQueriesCompleted(MultiQueryManager* manager) override {
-    const std::string& url = manager->label();
-    if (url == url1_)  // 2. Load the 2nd url.
-      GetBrowser()->GetMainFrame()->LoadURL(url2_);
-    else if (url == url2_)  // 3. Load the 3rd url.
-      GetBrowser()->GetMainFrame()->LoadURL(url3_);
-  }
-
- protected:
-  void RunMRTest() override {
-    url1_ = std::string(kTestDomain1) + "browser1.html";
-    url2_ = std::string(same_origin_ ? kTestDomain1 : kTestDomain2) +
-            "browser2.html";
-    url3_ = std::string(same_origin_ ? kTestDomain1 : kTestDomain3) +
-            "browser3.html";
-
-    AddManagedResource(url1_, true, true);
-    AddManagedResource(url2_, true, true);
-    AddManagedResource(url3_, true, true);
-    Finalize();
-
-    // 1. Load the 1st url.
-    CreateBrowser(url1_, nullptr);
-  }
-
- private:
-  bool same_origin_;
-
-  std::string url1_;
-  std::string url2_;
-  std::string url3_;
-};
-
-}  // namespace
-
-// Test that multiple navigations can query from the same origin.
-TEST(MessageRouterTest, MultiQueryMultiNavigateSameOriginSync) {
-  CefRefPtr<MultiQueryMultiNavigateTestHandler> handler =
-      new MultiQueryMultiNavigateTestHandler(true, true);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that multiple navigations can query from the same origin.
-TEST(MessageRouterTest, MultiQueryMultiNavigateSameOriginAsync) {
-  CefRefPtr<MultiQueryMultiNavigateTestHandler> handler =
-      new MultiQueryMultiNavigateTestHandler(false, true);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that multiple navigations can query from different origins.
-TEST(MessageRouterTest, MultiQueryMultiNavigateDifferentOriginSync) {
-  CefRefPtr<MultiQueryMultiNavigateTestHandler> handler =
-      new MultiQueryMultiNavigateTestHandler(true, false);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
-
-// Test that multiple navigations can query from different origins.
-TEST(MessageRouterTest, MultiQueryMultiNavigateDifferentOriginAsync) {
-  CefRefPtr<MultiQueryMultiNavigateTestHandler> handler =
-      new MultiQueryMultiNavigateTestHandler(false, false);
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
diff --git a/src/tests/ceftests/message_router_unittest_utils.cc b/src/tests/ceftests/message_router_unittest_utils.cc
new file mode 100644
index 0000000..aff4183
--- /dev/null
+++ b/src/tests/ceftests/message_router_unittest_utils.cc
@@ -0,0 +1,260 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "tests/ceftests/message_router_unittest_utils.h"
+
+extern const char kJSQueryFunc[] = "mrtQuery";
+extern const char kJSQueryCancelFunc[] = "mrtQueryCancel";
+
+namespace {
+
+const char kTestDomainRoot[] = "https://tests-mr";
+const char kDoneMessageName[] = "mrtNotifyMsg";
+const char kJSNotifyFunc[] = "mrtNotify";
+const char kJSAssertTotalCountFunc[] = "mrtAssertTotalCount";
+const char kJSAssertBrowserCountFunc[] = "mrtAssertBrowserCount";
+const char kJSAssertContextCountFunc[] = "mrtAssertContextCount";
+
+void SetRouterConfig(CefMessageRouterConfig& config) {
+  config.js_query_function = kJSQueryFunc;
+  config.js_cancel_function = kJSQueryCancelFunc;
+}
+
+}  // namespace
+
+// Entry point for creating the test delegate.
+// Called from client_app_delegates.cc.
+void CreateMessageRouterRendererTests(
+    ClientAppRenderer::DelegateSet& delegates) {
+  delegates.insert(new MRRenderDelegate);
+}
+
+bool MRRenderDelegate::V8HandlerImpl::Execute(const CefString& name,
+                                              CefRefPtr<CefV8Value> object,
+                                              const CefV8ValueList& arguments,
+                                              CefRefPtr<CefV8Value>& retval,
+                                              CefString& exception) {
+  const std::string& message_name = name;
+  if (message_name == kJSNotifyFunc) {
+    EXPECT_EQ(1U, arguments.size());
+    EXPECT_TRUE(arguments[0]->IsString());
+
+    const CefString& msg = arguments[0]->GetStringValue();
+    CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
+    CefRefPtr<CefFrame> frame = context->GetFrame();
+
+    CefRefPtr<CefProcessMessage> message =
+        CefProcessMessage::Create(kDoneMessageName);
+    CefRefPtr<CefListValue> args = message->GetArgumentList();
+    args->SetString(0, msg);
+    frame->SendProcessMessage(PID_BROWSER, message);
+    return true;
+  } else {
+    EXPECT_EQ(2U, arguments.size());
+    EXPECT_TRUE(arguments[0]->IsInt());
+    EXPECT_TRUE(arguments[1]->IsInt());
+
+    const int line_no = arguments[0]->GetIntValue();
+    const int expected_count = arguments[1]->GetIntValue();
+    int actual_count = -1;
+
+    CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
+    CefRefPtr<CefBrowser> browser = context->GetBrowser();
+
+    if (name == kJSAssertTotalCountFunc) {
+      actual_count =
+          delegate_->message_router_->GetPendingCount(nullptr, nullptr);
+    } else if (name == kJSAssertBrowserCountFunc) {
+      actual_count =
+          delegate_->message_router_->GetPendingCount(browser, nullptr);
+    } else if (name == kJSAssertContextCountFunc) {
+      actual_count =
+          delegate_->message_router_->GetPendingCount(browser, context);
+    }
+
+    if (expected_count != actual_count) {
+      std::stringstream ss;
+      ss << message_name << " failed (line " << line_no << "); expected "
+         << expected_count << ", got " << actual_count;
+      exception = ss.str();
+    }
+  }
+
+  return true;
+}
+
+void MRRenderDelegate::OnWebKitInitialized(CefRefPtr<ClientAppRenderer> app) {
+  // Create the renderer-side router for query handling.
+  CefMessageRouterConfig config;
+  SetRouterConfig(config);
+  message_router_ = CefMessageRouterRendererSide::Create(config);
+}
+
+void MRRenderDelegate::OnContextCreated(CefRefPtr<ClientAppRenderer> app,
+                                        CefRefPtr<CefBrowser> browser,
+                                        CefRefPtr<CefFrame> frame,
+                                        CefRefPtr<CefV8Context> context) {
+  const std::string& url = frame->GetURL();
+  if (url.find(kTestDomainRoot) != 0) {
+    return;
+  }
+
+  message_router_->OnContextCreated(browser, frame, context);
+
+  // Register function handlers with the 'window' object.
+  CefRefPtr<CefV8Value> window = context->GetGlobal();
+
+  CefRefPtr<V8HandlerImpl> handler = new V8HandlerImpl(this);
+  CefV8Value::PropertyAttribute attributes =
+      static_cast<CefV8Value::PropertyAttribute>(
+          V8_PROPERTY_ATTRIBUTE_READONLY | V8_PROPERTY_ATTRIBUTE_DONTENUM |
+          V8_PROPERTY_ATTRIBUTE_DONTDELETE);
+
+  CefRefPtr<CefV8Value> notify_func =
+      CefV8Value::CreateFunction(kJSNotifyFunc, handler.get());
+  window->SetValue(kJSNotifyFunc, notify_func, attributes);
+
+  CefRefPtr<CefV8Value> total_count_func =
+      CefV8Value::CreateFunction(kJSAssertTotalCountFunc, handler.get());
+  window->SetValue(kJSAssertTotalCountFunc, total_count_func, attributes);
+
+  CefRefPtr<CefV8Value> browser_count_func =
+      CefV8Value::CreateFunction(kJSAssertBrowserCountFunc, handler.get());
+  window->SetValue(kJSAssertBrowserCountFunc, browser_count_func, attributes);
+
+  CefRefPtr<CefV8Value> context_count_func =
+      CefV8Value::CreateFunction(kJSAssertContextCountFunc, handler.get());
+  window->SetValue(kJSAssertContextCountFunc, context_count_func, attributes);
+}
+
+void MRRenderDelegate::OnContextReleased(CefRefPtr<ClientAppRenderer> app,
+                                         CefRefPtr<CefBrowser> browser,
+                                         CefRefPtr<CefFrame> frame,
+                                         CefRefPtr<CefV8Context> context) {
+  const std::string& url = frame->GetURL();
+  if (url.find(kTestDomainRoot) != 0) {
+    return;
+  }
+
+  message_router_->OnContextReleased(browser, frame, context);
+}
+
+bool MRRenderDelegate::OnProcessMessageReceived(
+    CefRefPtr<ClientAppRenderer> app,
+    CefRefPtr<CefBrowser> browser,
+    CefRefPtr<CefFrame> frame,
+    CefProcessId source_process,
+    CefRefPtr<CefProcessMessage> message) {
+  const std::string& url = frame->GetURL();
+  if (url.find(kTestDomainRoot) != 0) {
+    return false;
+  }
+
+  return message_router_->OnProcessMessageReceived(browser, frame,
+                                                   source_process, message);
+}
+
+void MRTestHandler::RunTest() {
+  RunMRTest();
+
+  // Time out the test after a reasonable period of time.
+  SetTestTimeout(10000);
+}
+
+void MRTestHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
+  if (!message_router_.get()) {
+    // Create the browser-side router for query handling.
+    CefMessageRouterConfig config;
+
+    SetRouterConfig(config);
+    if (message_size_threshold_) {
+      config.message_size_threshold = message_size_threshold_;
+    }
+
+    message_router_ = CefMessageRouterBrowserSide::Create(config);
+    AddHandlers(message_router_);
+  }
+  TestHandler::OnAfterCreated(browser);
+}
+
+void MRTestHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
+  message_router_->OnBeforeClose(browser);
+  TestHandler::OnBeforeClose(browser);
+}
+
+void MRTestHandler::OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
+                                              TerminationStatus status) {
+  message_router_->OnRenderProcessTerminated(browser);
+}
+
+bool MRTestHandler::OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
+                                   CefRefPtr<CefFrame> frame,
+                                   CefRefPtr<CefRequest> request,
+                                   bool user_gesture,
+                                   bool is_redirect) {
+  message_router_->OnBeforeBrowse(browser, frame);
+  return false;
+}
+
+// Returns true if the router handled the navigation.
+bool MRTestHandler::OnProcessMessageReceived(
+    CefRefPtr<CefBrowser> browser,
+    CefRefPtr<CefFrame> frame,
+    CefProcessId source_process,
+    CefRefPtr<CefProcessMessage> message) {
+  const std::string& message_name = message->GetName();
+  if (message_name == kDoneMessageName) {
+    CefRefPtr<CefListValue> args = message->GetArgumentList();
+    EXPECT_EQ(1U, args->GetSize());
+    EXPECT_EQ(VTYPE_STRING, args->GetType(0));
+    OnNotify(browser, frame, args->GetString(0));
+    return true;
+  }
+
+  return message_router_->OnProcessMessageReceived(browser, frame,
+                                                   source_process, message);
+}
+
+CefRefPtr<CefMessageRouterBrowserSide> MRTestHandler::GetRouter() const {
+  return message_router_;
+}
+
+void MRTestHandler::SetMessageSizeThreshold(size_t message_size_threshold) {
+  message_size_threshold_ = message_size_threshold;
+}
+
+bool MRTestHandler::AssertQueryCount(
+    CefRefPtr<CefBrowser> browser,
+    CefMessageRouterBrowserSide::Handler* handler,
+    int expected_count) {
+  int actual_count = message_router_->GetPendingCount(browser, handler);
+  EXPECT_EQ(expected_count, actual_count);
+  return (expected_count == actual_count);
+}
+
+void MRTestHandler::AssertMainBrowser(CefRefPtr<CefBrowser> browser) {
+  EXPECT_TRUE(browser.get());
+  EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
+}
+
+SingleLoadTestHandler::SingleLoadTestHandler()
+    : main_url_("https://tests-mr.com/main.html") {}
+
+void SingleLoadTestHandler::RunMRTest() {
+  AddOtherResources();
+  AddResource(main_url_, GetMainHTML(), "text/html");
+
+  CreateBrowser(main_url_, nullptr);
+}
+
+void SingleLoadTestHandler::AddHandlers(
+    CefRefPtr<CefMessageRouterBrowserSide> message_router) {
+  message_router->AddHandler(this, false);
+}
+
+void SingleLoadTestHandler::AssertMainFrame(CefRefPtr<CefFrame> frame) {
+  EXPECT_TRUE(frame.get());
+  EXPECT_TRUE(frame->IsMain());
+  EXPECT_STREQ(main_url_.c_str(), frame->GetURL().ToString().c_str());
+}
diff --git a/src/tests/ceftests/message_router_unittest_utils.h b/src/tests/ceftests/message_router_unittest_utils.h
new file mode 100644
index 0000000..25d5759
--- /dev/null
+++ b/src/tests/ceftests/message_router_unittest_utils.h
@@ -0,0 +1,137 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 CEF_TESTS_CEFTESTS_MESSAGE_ROUTER_UNITTEST_UTILS_H_
+#define CEF_TESTS_CEFTESTS_MESSAGE_ROUTER_UNITTEST_UTILS_H_
+#pragma once
+
+#include <cstdlib>
+
+#include "include/base/cef_callback.h"
+#include "include/base/cef_weak_ptr.h"
+#include "include/cef_v8.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "tests/ceftests/routing_test_handler.h"
+#include "tests/ceftests/test_util.h"
+#include "tests/gtest/include/gtest/gtest.h"
+#include "tests/shared/renderer/client_app_renderer.h"
+
+using client::ClientAppRenderer;
+
+extern const char kJSQueryFunc[];
+extern const char kJSQueryCancelFunc[];
+
+#define S1(N) #N
+#define S2(N) S1(N)
+#define LINESTR S2(__LINE__)
+
+// Handle the renderer side of the routing implementation.
+class MRRenderDelegate : public ClientAppRenderer::Delegate {
+ public:
+  class V8HandlerImpl : public CefV8Handler {
+   public:
+    explicit V8HandlerImpl(CefRefPtr<MRRenderDelegate> delegate)
+        : delegate_(delegate) {}
+
+    bool Execute(const CefString& name,
+                 CefRefPtr<CefV8Value> object,
+                 const CefV8ValueList& arguments,
+                 CefRefPtr<CefV8Value>& retval,
+                 CefString& exception) override;
+
+   private:
+    CefRefPtr<MRRenderDelegate> delegate_;
+
+    IMPLEMENT_REFCOUNTING(V8HandlerImpl);
+  };
+
+  void OnWebKitInitialized(CefRefPtr<ClientAppRenderer> app) override;
+
+  void OnContextCreated(CefRefPtr<ClientAppRenderer> app,
+                        CefRefPtr<CefBrowser> browser,
+                        CefRefPtr<CefFrame> frame,
+                        CefRefPtr<CefV8Context> context) override;
+
+  void OnContextReleased(CefRefPtr<ClientAppRenderer> app,
+                         CefRefPtr<CefBrowser> browser,
+                         CefRefPtr<CefFrame> frame,
+                         CefRefPtr<CefV8Context> context) override;
+
+  bool OnProcessMessageReceived(CefRefPtr<ClientAppRenderer> app,
+                                CefRefPtr<CefBrowser> browser,
+                                CefRefPtr<CefFrame> frame,
+                                CefProcessId source_process,
+                                CefRefPtr<CefProcessMessage> message) override;
+
+ private:
+  CefRefPtr<CefMessageRouterRendererSide> message_router_;
+
+  IMPLEMENT_REFCOUNTING(MRRenderDelegate);
+};
+
+class MRTestHandler : public TestHandler {
+ public:
+  void RunTest() override;
+  void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
+  void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
+  void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
+                                 TerminationStatus status) override;
+
+  // Only call this method if the navigation isn't canceled.
+  bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
+                      CefRefPtr<CefFrame> frame,
+                      CefRefPtr<CefRequest> request,
+                      bool user_gesture,
+                      bool is_redirect) override;
+  // Returns true if the router handled the navigation.
+  bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
+                                CefRefPtr<CefFrame> frame,
+                                CefProcessId source_process,
+                                CefRefPtr<CefProcessMessage> message) override;
+
+  CefRefPtr<CefMessageRouterBrowserSide> GetRouter() const;
+  void SetMessageSizeThreshold(size_t message_size_treshold);
+
+ protected:
+  virtual void RunMRTest() = 0;
+
+  virtual void AddHandlers(
+      CefRefPtr<CefMessageRouterBrowserSide> message_router) = 0;
+
+  virtual void OnNotify(CefRefPtr<CefBrowser> browser,
+                        CefRefPtr<CefFrame> frame,
+                        const std::string& message) = 0;
+
+  bool AssertQueryCount(CefRefPtr<CefBrowser> browser,
+                        CefMessageRouterBrowserSide::Handler* handler,
+                        int expected_count);
+  void AssertMainBrowser(CefRefPtr<CefBrowser> browser);
+
+ private:
+  CefRefPtr<CefMessageRouterBrowserSide> message_router_;
+  size_t message_size_threshold_ = 0;
+
+  IMPLEMENT_REFCOUNTING(MRTestHandler);
+};
+
+// Implementation of MRTestHandler that loads a single page.
+class SingleLoadTestHandler : public MRTestHandler,
+                              public CefMessageRouterBrowserSide::Handler {
+ public:
+  SingleLoadTestHandler();
+  const std::string& GetMainURL() { return main_url_; }
+
+ protected:
+  void RunMRTest() override;
+  void AddHandlers(
+      CefRefPtr<CefMessageRouterBrowserSide> message_router) override;
+  virtual void AddOtherResources() {}
+  virtual std::string GetMainHTML() = 0;
+  void AssertMainFrame(CefRefPtr<CefFrame> frame);
+
+ private:
+  const std::string main_url_;
+};
+
+#endif  // CEF_TESTS_CEFTESTS_MESSAGE_ROUTER_UNITTEST_UTILS_H_
diff --git a/src/tests/ceftests/navigation_unittest.cc b/src/tests/ceftests/navigation_unittest.cc
index b69100c..b1693fc 100644
--- a/src/tests/ceftests/navigation_unittest.cc
+++ b/src/tests/ceftests/navigation_unittest.cc
@@ -5,24 +5,30 @@
 #include <algorithm>
 #include <list>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_callback.h"
+#include "include/cef_request_context.h"
+#include "include/cef_request_context_handler.h"
 #include "include/cef_scheme.h"
 #include "include/wrapper/cef_closure_task.h"
+#include "include/wrapper/cef_scoped_temp_dir.h"
 #include "tests/ceftests/test_handler.h"
 #include "tests/ceftests/test_util.h"
 #include "tests/gtest/include/gtest/gtest.h"
 #include "tests/shared/browser/client_app_browser.h"
 #include "tests/shared/renderer/client_app_renderer.h"
 
+// Set to 1 to enable verbose debugging info logging.
+#define VERBOSE_DEBUGGING 0
+
 using client::ClientAppBrowser;
 using client::ClientAppRenderer;
 
 namespace {
 
-const char kHNav1[] = "http://tests-hnav.com/nav1.html";
-const char kHNav2[] = "http://tests-hnav.com/nav2.html";
-const char kHNav3[] = "http://tests-hnav.com/nav3.html";
+const char kHNav1[] = "https://tests-hnav.com/nav1.html";
+const char kHNav2[] = "https://tests-hnav.com/nav2.html";
+const char kHNav3[] = "https://tests-hnav.com/nav3.html";
 const char kHistoryNavMsg[] = "NavigationTest.HistoryNav";
 const char kHistoryNavTestCmdKey[] = "nav-history-test";
 
@@ -34,7 +40,28 @@
     static_cast<cef_transition_type_t>(kTransitionExplicitLoad |
                                        TT_FORWARD_BACK_FLAG);
 
-enum NavAction { NA_LOAD = 1, NA_BACK, NA_FORWARD, NA_CLEAR };
+enum NavAction { NA_LOAD = 1, NA_BACK, NA_FORWARD };
+
+#if VERBOSE_DEBUGGING
+const char* NavActionString(NavAction action) {
+  switch (action) {
+    case NA_LOAD:
+      return "LOAD";
+    case NA_BACK:
+      return "BACK";
+    case NA_FORWARD:
+      return "FORWARD";
+  }
+  return "INVALID";
+}
+#endif  // VERBOSE_DEBUGGING
+
+bool ExpectResourceLoadEvents(NavAction action) {
+  if (IsSameSiteBFCacheEnabled()) {
+    return action == NA_LOAD;
+  }
+  return true;
+}
 
 typedef struct {
   NavAction action;     // What to do
@@ -52,8 +79,6 @@
     {NA_FORWARD, kHNav2, true, false},  //   .        X
     {NA_LOAD, kHNav3, true, false},     //   .        .        X
     {NA_BACK, kHNav2, true, true},      //   .        X        .
-    // TODO(cef): Enable once ClearHistory is implemented
-    // {NA_CLEAR, kHNav2, false, false},   //            X
 };
 
 #define NAV_LIST_SIZE() (sizeof(kHNavList) / sizeof(NavListItem))
@@ -67,13 +92,14 @@
   void OnBrowserCreated(CefRefPtr<ClientAppRenderer> app,
                         CefRefPtr<CefBrowser> browser,
                         CefRefPtr<CefDictionaryValue> extra_info) override {
-    run_test_ = extra_info->HasKey(kHistoryNavTestCmdKey);
+    run_test_ = extra_info && extra_info->HasKey(kHistoryNavTestCmdKey);
   }
 
   CefRefPtr<CefLoadHandler> GetLoadHandler(
       CefRefPtr<ClientAppRenderer> app) override {
-    if (!run_test_)
+    if (!run_test_) {
       return nullptr;
+    }
 
     return this;
   }
@@ -83,6 +109,10 @@
                             bool canGoBack,
                             bool canGoForward) override {
     const NavListItem& item = kHNavList[nav_];
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "render nav=" << nav_ << " " << NavActionString(item.action)
+              << " OnLoadingStateChange isLoading=" << isLoading;
+#endif
 
     const std::string& url = browser->GetMainFrame()->GetURL();
     EXPECT_STREQ(item.target, url.c_str());
@@ -97,8 +127,10 @@
         << "nav: " << nav_ << " isLoading: " << isLoading;
 
     if (isLoading) {
+      EXPECT_FALSE(got_loading_state_start_);
       got_loading_state_start_.yes();
     } else {
+      EXPECT_FALSE(got_loading_state_end_);
       got_loading_state_end_.yes();
       SendTestResultsIfDone(browser, browser->GetMainFrame());
     }
@@ -108,7 +140,12 @@
                    CefRefPtr<CefFrame> frame,
                    TransitionType transition_type) override {
     const NavListItem& item = kHNavList[nav_];
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "render nav=" << nav_ << " " << NavActionString(item.action)
+              << " OnLoadStart";
+#endif
 
+    EXPECT_FALSE(got_load_start_);
     got_load_start_.yes();
 
     const std::string& url = frame->GetURL();
@@ -124,7 +161,12 @@
                  CefRefPtr<CefFrame> frame,
                  int httpStatusCode) override {
     const NavListItem& item = kHNavList[nav_];
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "render nav=" << nav_ << " " << NavActionString(item.action)
+              << " OnLoadEnd";
+#endif
 
+    EXPECT_FALSE(got_load_end_);
     got_load_end_.yes();
 
     const std::string& url = frame->GetURL();
@@ -139,13 +181,20 @@
  protected:
   void SendTestResultsIfDone(CefRefPtr<CefBrowser> browser,
                              CefRefPtr<CefFrame> frame) {
-    if (got_load_end_ && got_loading_state_end_)
+    if (got_load_end_ && got_loading_state_end_) {
       SendTestResults(browser, frame);
+    }
   }
 
   // Send the test results.
   void SendTestResults(CefRefPtr<CefBrowser> browser,
                        CefRefPtr<CefFrame> frame) {
+#if VERBOSE_DEBUGGING
+    const NavListItem& item = kHNavList[nav_];
+    LOG(INFO) << "render nav=" << nav_ << " " << NavActionString(item.action)
+              << " SendTestResults";
+#endif
+
     EXPECT_TRUE(got_loading_state_start_);
     EXPECT_TRUE(got_loading_state_end_);
     EXPECT_TRUE(got_load_start_);
@@ -246,13 +295,14 @@
     EXPECT_STREQ(expected_title.c_str(), entry->GetTitle().ToString().c_str());
 
     const auto transition_type = entry->GetTransitionType();
-    if (expected_forwardback_[index])
+    if (expected_forwardback_[index]) {
       EXPECT_EQ(kTransitionExplicitForwardBack, transition_type);
-    else
+    } else {
       EXPECT_EQ(kTransitionExplicitLoad, transition_type);
+    }
 
     EXPECT_FALSE(entry->HasPostData());
-    EXPECT_GT(entry->GetCompletionTime().GetTimeT(), 0);
+    EXPECT_GT(CefTimeFrom(entry->GetCompletionTime()).GetTimeT(), 0);
     EXPECT_EQ(200, entry->GetHttpStatusCode());
 
     callback_count_++;
@@ -273,11 +323,7 @@
 // Browser side.
 class HistoryNavTestHandler : public TestHandler {
  public:
-  HistoryNavTestHandler()
-      : nav_(0),
-        load_end_confirmation_(false),
-        load_state_change_loaded_confirmation_(false),
-        renderer_confirmation_(false) {}
+  HistoryNavTestHandler() = default;
 
   void RunTest() override {
     // Add the resources that we will navigate to/from.
@@ -322,19 +368,20 @@
       case NA_FORWARD:
         browser->GoForward();
         break;
-      case NA_CLEAR:
-        // TODO(cef): Enable once ClearHistory is implemented
-        // browser->GetHost()->ClearHistory();
-        // Not really a navigation action so go to the next one.
-        nav_++;
-        RunNav(browser);
-        break;
       default:
         break;
     }
   }
 
   void RunNextNavIfReady(CefRefPtr<CefBrowser> browser) {
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "browser nav=" << nav_
+              << " load_end_confirmation_=" << load_end_confirmation_
+              << " load_state_change_loaded_confirmation_="
+              << load_state_change_loaded_confirmation_
+              << " renderer_confirmation_=" << renderer_confirmation_;
+#endif
+
     if (load_end_confirmation_ && load_state_change_loaded_confirmation_ &&
         renderer_confirmation_) {
       load_end_confirmation_ = false;
@@ -358,6 +405,12 @@
                       bool is_redirect) override {
     const NavListItem& item = kHNavList[nav_];
 
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "browser nav=" << nav_ << " " << NavActionString(item.action)
+              << " OnBeforeBrowse";
+#endif
+
+    EXPECT_FALSE(got_before_browse_[nav_]);
     got_before_browse_[nav_].yes();
 
     std::string url = request->GetURL();
@@ -388,23 +441,33 @@
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) override {
-    const NavListItem& item = kHNavList[nav_];
+      CefRefPtr<CefCallback> callback) override {
+    if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
+      // Ignore favicon requests.
+      return RV_CANCEL;
+    }
 
-    EXPECT_EQ(RT_MAIN_FRAME, request->GetResourceType());
+    const NavListItem& item = kHNavList[nav_];
+    const std::string& url = request->GetURL();
+
+    EXPECT_EQ(RT_MAIN_FRAME, request->GetResourceType())
+        << "nav=" << nav_ << " url=" << url;
 
     const auto transition_type = request->GetTransitionType();
     if (item.action == NA_LOAD) {
-      EXPECT_EQ(kTransitionExplicitLoad, transition_type);
+      EXPECT_EQ(kTransitionExplicitLoad, transition_type)
+          << "nav=" << nav_ << " url=" << url;
     } else if (item.action == NA_BACK || item.action == NA_FORWARD) {
-      EXPECT_EQ(kTransitionExplicitForwardBack, transition_type);
+      EXPECT_EQ(kTransitionExplicitForwardBack, transition_type)
+          << "nav=" << nav_ << " url=" << url;
     }
 
+    EXPECT_FALSE(got_before_resource_load_[nav_]);
     got_before_resource_load_[nav_].yes();
 
-    std::string url = request->GetURL();
-    if (url == item.target)
+    if (url == item.target) {
       got_correct_target_[nav_].yes();
+    }
 
     return RV_CONTINUE;
   }
@@ -413,17 +476,28 @@
                             bool isLoading,
                             bool canGoBack,
                             bool canGoForward) override {
-    if (isLoading)
-      return;
-
     const NavListItem& item = kHNavList[nav_];
 
-    got_loading_state_change_[nav_].yes();
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "browser nav=" << nav_ << " " << NavActionString(item.action)
+              << " OnLoadingStateChange isLoading=" << isLoading;
+#endif
 
-    if (item.can_go_back == canGoBack)
+    if (isLoading) {
+      EXPECT_FALSE(got_loading_state_change_loading_[nav_]);
+      got_loading_state_change_loading_[nav_].yes();
+      return;
+    }
+
+    EXPECT_FALSE(got_loading_state_change_loaded_[nav_]);
+    got_loading_state_change_loaded_[nav_].yes();
+
+    if (item.can_go_back == canGoBack) {
       got_correct_can_go_back_[nav_].yes();
-    if (item.can_go_forward == canGoForward)
+    }
+    if (item.can_go_forward == canGoForward) {
       got_correct_can_go_forward_[nav_].yes();
+    }
 
     load_state_change_loaded_confirmation_ = true;
     RunNextNavIfReady(browser);
@@ -432,11 +506,18 @@
   void OnLoadStart(CefRefPtr<CefBrowser> browser,
                    CefRefPtr<CefFrame> frame,
                    TransitionType transition_type) override {
-    if (browser->IsPopup() || !frame->IsMain())
+    if (browser->IsPopup() || !frame->IsMain()) {
       return;
+    }
 
     const NavListItem& item = kHNavList[nav_];
 
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "browser nav=" << nav_ << " " << NavActionString(item.action)
+              << " OnLoadStart";
+#endif
+
+    EXPECT_FALSE(got_load_start_[nav_]);
     got_load_start_[nav_].yes();
 
     if (item.action == NA_LOAD) {
@@ -447,18 +528,26 @@
 
     std::string url1 = browser->GetMainFrame()->GetURL();
     std::string url2 = frame->GetURL();
-    if (url1 == item.target && url2 == item.target)
+    if (url1 == item.target && url2 == item.target) {
       got_correct_load_start_url_[nav_].yes();
+    }
   }
 
   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
                  CefRefPtr<CefFrame> frame,
                  int httpStatusCode) override {
-    if (browser->IsPopup() || !frame->IsMain())
+    if (browser->IsPopup() || !frame->IsMain()) {
       return;
+    }
 
     const NavListItem& item = kHNavList[nav_];
 
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "browser nav=" << nav_ << " " << NavActionString(item.action)
+              << " OnLoadEnd";
+#endif
+
+    EXPECT_FALSE(got_load_end_[nav_]);
     got_load_end_[nav_].yes();
 
     // Test that navigation entries are correct.
@@ -469,8 +558,9 @@
 
     std::string url1 = browser->GetMainFrame()->GetURL();
     std::string url2 = frame->GetURL();
-    if (url1 == item.target && url2 == item.target)
+    if (url1 == item.target && url2 == item.target) {
       got_correct_load_end_url_[nav_].yes();
+    }
 
     load_end_confirmation_ = true;
     RunNextNavIfReady(browser);
@@ -481,6 +571,7 @@
                                 CefProcessId source_process,
                                 CefRefPtr<CefProcessMessage> message) override {
     if (message->GetName().ToString() == kHistoryNavMsg) {
+      EXPECT_FALSE(got_before_navigation_[nav_]);
       got_before_navigation_[nav_].yes();
 
       // Test that the renderer side succeeded.
@@ -498,16 +589,17 @@
     return false;
   }
 
-  int nav_;
-  bool load_end_confirmation_;
-  bool load_state_change_loaded_confirmation_;
-  bool renderer_confirmation_;
+  int nav_ = 0;
+  bool load_end_confirmation_ = false;
+  bool load_state_change_loaded_confirmation_ = false;
+  bool renderer_confirmation_ = false;
 
   TrackCallback got_before_browse_[NAV_LIST_SIZE()];
   TrackCallback got_before_navigation_[NAV_LIST_SIZE()];
   TrackCallback got_before_resource_load_[NAV_LIST_SIZE()];
   TrackCallback got_correct_target_[NAV_LIST_SIZE()];
-  TrackCallback got_loading_state_change_[NAV_LIST_SIZE()];
+  TrackCallback got_loading_state_change_loading_[NAV_LIST_SIZE()];
+  TrackCallback got_loading_state_change_loaded_[NAV_LIST_SIZE()];
   TrackCallback got_correct_can_go_back_[NAV_LIST_SIZE()];
   TrackCallback got_correct_can_go_forward_[NAV_LIST_SIZE()];
   TrackCallback got_load_start_[NAV_LIST_SIZE()];
@@ -527,24 +619,27 @@
   handler->ExecuteTest();
 
   for (size_t i = 0; i < NAV_LIST_SIZE(); ++i) {
-    if (kHNavList[i].action != NA_CLEAR) {
-      ASSERT_TRUE(handler->got_before_browse_[i]) << "i = " << i;
-      ASSERT_TRUE(handler->got_before_navigation_[i]) << "i = " << i;
-      ASSERT_TRUE(handler->got_before_resource_load_[i]) << "i = " << i;
-      ASSERT_TRUE(handler->got_correct_target_[i]) << "i = " << i;
-      ASSERT_TRUE(handler->got_load_start_[i]) << "i = " << i;
-      ASSERT_TRUE(handler->got_correct_load_start_url_[i]) << "i = " << i;
+    if (ExpectResourceLoadEvents(kHNavList[i].action)) {
+      EXPECT_TRUE(handler->got_before_browse_[i]) << "i = " << i;
+      EXPECT_TRUE(handler->got_before_resource_load_[i]) << "i = " << i;
+      EXPECT_TRUE(handler->got_correct_target_[i]) << "i = " << i;
+    } else {
+      EXPECT_FALSE(handler->got_before_browse_[i]) << "i = " << i;
+      EXPECT_FALSE(handler->got_before_resource_load_[i]) << "i = " << i;
+      EXPECT_FALSE(handler->got_correct_target_[i]) << "i = " << i;
     }
 
-    ASSERT_TRUE(handler->got_loading_state_change_[i]) << "i = " << i;
-    ASSERT_TRUE(handler->got_correct_can_go_back_[i]) << "i = " << i;
-    ASSERT_TRUE(handler->got_correct_can_go_forward_[i]) << "i = " << i;
+    EXPECT_TRUE(handler->got_before_navigation_[i]) << "i = " << i;
+    EXPECT_TRUE(handler->got_load_start_[i]) << "i = " << i;
+    EXPECT_TRUE(handler->got_correct_load_start_url_[i]) << "i = " << i;
+    EXPECT_TRUE(handler->got_load_end_[i]) << "i = " << i;
+    EXPECT_TRUE(handler->got_correct_load_end_url_[i]) << "i = " << i;
+    EXPECT_TRUE(handler->got_correct_history_[i]) << "i = " << i;
 
-    if (kHNavList[i].action != NA_CLEAR) {
-      ASSERT_TRUE(handler->got_load_end_[i]) << "i = " << i;
-      ASSERT_TRUE(handler->got_correct_history_[i]) << "i = " << i;
-      ASSERT_TRUE(handler->got_correct_load_end_url_[i]) << "i = " << i;
-    }
+    EXPECT_TRUE(handler->got_loading_state_change_loading_[i]) << "i = " << i;
+    EXPECT_TRUE(handler->got_loading_state_change_loaded_[i]) << "i = " << i;
+    EXPECT_TRUE(handler->got_correct_can_go_back_[i]) << "i = " << i;
+    EXPECT_TRUE(handler->got_correct_can_go_forward_[i]) << "i = " << i;
   }
 
   ReleaseAndWaitForDestructor(handler);
@@ -552,8 +647,8 @@
 
 namespace {
 
-const char kDynIfrNav1[] = "http://tests-dynframe/nav1.html";
-const char kDynIfrNav2[] = "http://tests-dynframe/nav2.html";
+const char kDynIfrNav1[] = "https://tests-dynframe/nav1.html";
+const char kDynIfrNav2[] = "https://tests-dynframe/nav2.html";
 
 // Browser side.
 class HistoryDynamicIFramesNavTestHandler : public TestHandler {
@@ -636,16 +731,18 @@
   void OnLoadStart(CefRefPtr<CefBrowser> browser,
                    CefRefPtr<CefFrame> frame,
                    TransitionType transition_type) override {
-    if (!frame->IsMain())
+    if (!frame->IsMain()) {
       return;
+    }
     got_load_start_[nav_].yes();
   }
 
   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
                  CefRefPtr<CefFrame> frame,
                  int httpStatusCode) override {
-    if (!frame->IsMain())
+    if (!frame->IsMain()) {
       return;
+    }
     CefString url = browser->GetMainFrame()->GetURL();
     got_load_end_[nav_].yes();
 
@@ -685,10 +782,10 @@
 
 namespace {
 
-const char kRNav1[] = "http://tests/nav1.html";
-const char kRNav2[] = "http://tests/nav2.html";
-const char kRNav3[] = "http://tests/nav3.html";
-const char kRNav4[] = "http://tests/nav4.html";
+const char kRNav1[] = "https://tests/nav1.html";
+const char kRNav2[] = "https://tests/nav2.html";
+const char kRNav3[] = "https://tests/nav3.html";
+const char kRNav4[] = "https://tests/nav4.html";
 
 bool g_got_nav1_request = false;
 bool g_got_nav3_request = false;
@@ -736,7 +833,7 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
     EXPECT_TRUE(CefCurrentlyOn(TID_IO));
 
@@ -833,7 +930,12 @@
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) override {
+      CefRefPtr<CefCallback> callback) override {
+    if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
+      // Ignore favicon requests.
+      return RV_CANCEL;
+    }
+
     // Should be called for all but the second URL.
     std::string url = request->GetURL();
 
@@ -981,7 +1083,7 @@
 
 // Verify frame names and identifiers.
 TEST(NavigationTest, Redirect) {
-  CefRegisterSchemeHandlerFactory("http", "tests",
+  CefRegisterSchemeHandlerFactory("https", "tests",
                                   new RedirectSchemeHandlerFactory());
   WaitForIOThread();
 
@@ -991,22 +1093,22 @@
   CefClearSchemeHandlerFactories();
   WaitForIOThread();
 
-  ASSERT_TRUE(handler->got_nav1_before_resource_load_);
-  ASSERT_TRUE(handler->got_nav3_before_resource_load_);
-  ASSERT_TRUE(handler->got_nav4_before_resource_load_);
-  ASSERT_FALSE(handler->got_invalid_before_resource_load_);
-  ASSERT_TRUE(handler->got_nav4_load_start_);
-  ASSERT_FALSE(handler->got_invalid_load_start_);
-  ASSERT_TRUE(handler->got_nav4_load_end_);
-  ASSERT_FALSE(handler->got_invalid_load_end_);
-  ASSERT_TRUE(handler->got_nav1_redirect_);
-  ASSERT_FALSE(handler->got_nav2_redirect_);
-  ASSERT_TRUE(handler->got_nav3_redirect_);
-  ASSERT_FALSE(handler->got_invalid_redirect_);
-  ASSERT_TRUE(g_got_nav1_request);
-  ASSERT_TRUE(g_got_nav3_request);
-  ASSERT_TRUE(g_got_nav4_request);
-  ASSERT_FALSE(g_got_invalid_request);
+  EXPECT_TRUE(handler->got_nav1_before_resource_load_);
+  EXPECT_TRUE(handler->got_nav3_before_resource_load_);
+  EXPECT_TRUE(handler->got_nav4_before_resource_load_);
+  EXPECT_FALSE(handler->got_invalid_before_resource_load_);
+  EXPECT_TRUE(handler->got_nav4_load_start_);
+  EXPECT_FALSE(handler->got_invalid_load_start_);
+  EXPECT_TRUE(handler->got_nav4_load_end_);
+  EXPECT_FALSE(handler->got_invalid_load_end_);
+  EXPECT_TRUE(handler->got_nav1_redirect_);
+  EXPECT_FALSE(handler->got_nav2_redirect_);
+  EXPECT_TRUE(handler->got_nav3_redirect_);
+  EXPECT_FALSE(handler->got_invalid_redirect_);
+  EXPECT_TRUE(g_got_nav1_request);
+  EXPECT_TRUE(g_got_nav3_request);
+  EXPECT_TRUE(g_got_nav4_request);
+  EXPECT_FALSE(g_got_invalid_request);
 
   ReleaseAndWaitForDestructor(handler);
 }
@@ -1014,7 +1116,7 @@
 // Verify that destroying the WebContents while the redirect is in-progress does
 // not result in a crash.
 TEST(NavigationTest, RedirectDestroy) {
-  CefRegisterSchemeHandlerFactory("http", "tests",
+  CefRegisterSchemeHandlerFactory("https", "tests",
                                   new RedirectSchemeHandlerFactory());
   WaitForIOThread();
 
@@ -1025,52 +1127,23 @@
   CefClearSchemeHandlerFactories();
   WaitForIOThread();
 
-  ASSERT_TRUE(handler->got_nav1_redirect_);
-  ASSERT_TRUE(g_got_nav1_request);
-  ASSERT_FALSE(g_got_nav3_request);
-  ASSERT_FALSE(g_got_nav4_request);
-  ASSERT_FALSE(g_got_invalid_request);
+  EXPECT_TRUE(handler->got_nav1_redirect_);
+  EXPECT_TRUE(g_got_nav1_request);
+  EXPECT_FALSE(g_got_nav3_request);
+  EXPECT_FALSE(g_got_nav4_request);
+  EXPECT_FALSE(g_got_invalid_request);
 
   ReleaseAndWaitForDestructor(handler);
 }
 
 namespace {
 
-const char KONav1[] = "http://tests-onav.com/nav1.html";
-const char KONav2[] = "http://tests-onav.com/nav2.html";
+const char KONav1[] = "https://tests-onav.com/nav1.html";
+const char KONav2[] = "https://tests-onav.com/nav2.html";
 const char kOrderNavMsg[] = "NavigationTest.OrderNav";
 const char kOrderNavClosedMsg[] = "NavigationTest.OrderNavClosed";
 const char kOrderNavTestCmdKey[] = "nav-order-test";
 
-void SetOrderNavExtraInfo(CefRefPtr<CefListValue> extra_info) {
-  // Arbitrary data for testing.
-  extra_info->SetBool(0, true);
-  CefRefPtr<CefDictionaryValue> dict = CefDictionaryValue::Create();
-  dict->SetInt("key1", 5);
-  dict->SetString("key2", "test string");
-  extra_info->SetDictionary(1, dict);
-  extra_info->SetDouble(2, 5.43322);
-  extra_info->SetString(3, "some string");
-}
-
-// Browser side.
-class OrderNavBrowserTest : public ClientAppBrowser::Delegate {
- public:
-  OrderNavBrowserTest() {}
-
-  void OnRenderProcessThreadCreated(
-      CefRefPtr<ClientAppBrowser> app,
-      CefRefPtr<CefListValue> extra_info) override {
-    // Some data that we'll check for. Note that this leaks into all renderer
-    // process test cases, but that shouldn't be an issue since we only check
-    // the result in this test case.
-    SetOrderNavExtraInfo(extra_info);
-  }
-
- protected:
-  IMPLEMENT_REFCOUNTING(OrderNavBrowserTest);
-};
-
 class OrderNavLoadState {
  public:
   OrderNavLoadState(bool is_popup, bool browser_side)
@@ -1154,21 +1227,7 @@
         state_main_(false, false),
         state_popup_(true, false) {}
 
-  void OnRenderThreadCreated(CefRefPtr<ClientAppRenderer> app,
-                             CefRefPtr<CefListValue> extra_info) override {
-    EXPECT_FALSE(got_render_thread_created_);
-    EXPECT_FALSE(got_webkit_initialized_);
-
-    got_render_thread_created_.yes();
-
-    // Verify that |extra_info| transferred successfully.
-    CefRefPtr<CefListValue> expected = CefListValue::Create();
-    SetOrderNavExtraInfo(expected);
-    TestListEqual(expected, extra_info);
-  }
-
   void OnWebKitInitialized(CefRefPtr<ClientAppRenderer> app) override {
-    EXPECT_TRUE(got_render_thread_created_);
     EXPECT_FALSE(got_webkit_initialized_);
 
     got_webkit_initialized_.yes();
@@ -1177,11 +1236,11 @@
   void OnBrowserCreated(CefRefPtr<ClientAppRenderer> app,
                         CefRefPtr<CefBrowser> browser,
                         CefRefPtr<CefDictionaryValue> extra_info) override {
-    run_test_ = extra_info->HasKey(kOrderNavTestCmdKey);
-    if (!run_test_)
+    run_test_ = extra_info && extra_info->HasKey(kOrderNavTestCmdKey);
+    if (!run_test_) {
       return;
+    }
 
-    EXPECT_TRUE(got_render_thread_created_);
     EXPECT_TRUE(got_webkit_initialized_);
 
     if (browser->IsPopup()) {
@@ -1207,10 +1266,10 @@
 
   void OnBrowserDestroyed(CefRefPtr<ClientAppRenderer> app,
                           CefRefPtr<CefBrowser> browser) override {
-    if (!run_test_)
+    if (!run_test_) {
       return;
+    }
 
-    EXPECT_TRUE(got_render_thread_created_);
     EXPECT_TRUE(got_webkit_initialized_);
 
     if (browser->IsPopup()) {
@@ -1240,8 +1299,9 @@
 
   CefRefPtr<CefLoadHandler> GetLoadHandler(
       CefRefPtr<ClientAppRenderer> app) override {
-    if (!run_test_)
+    if (!run_test_) {
       return nullptr;
+    }
 
     return this;
   }
@@ -1250,7 +1310,6 @@
                             bool isLoading,
                             bool canGoBack,
                             bool canGoForward) override {
-    EXPECT_TRUE(got_render_thread_created_);
     EXPECT_TRUE(got_webkit_initialized_);
 
     if (browser->IsPopup()) {
@@ -1267,14 +1326,14 @@
                                        canGoForward);
     }
 
-    if (!isLoading)
+    if (!isLoading) {
       SendTestResultsIfDone(browser, browser->GetMainFrame());
+    }
   }
 
   void OnLoadStart(CefRefPtr<CefBrowser> browser,
                    CefRefPtr<CefFrame> frame,
                    TransitionType transition_type) override {
-    EXPECT_TRUE(got_render_thread_created_);
     EXPECT_TRUE(got_webkit_initialized_);
 
     if (browser->IsPopup()) {
@@ -1293,7 +1352,6 @@
   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
                  CefRefPtr<CefFrame> frame,
                  int httpStatusCode) override {
-    EXPECT_TRUE(got_render_thread_created_);
     EXPECT_TRUE(got_webkit_initialized_);
 
     if (browser->IsPopup()) {
@@ -1324,13 +1382,15 @@
   void SendTestResultsIfDone(CefRefPtr<CefBrowser> browser,
                              CefRefPtr<CefFrame> frame) {
     bool done = false;
-    if (browser->IsPopup())
+    if (browser->IsPopup()) {
       done = state_popup_.IsDone();
-    else
+    } else {
       done = state_main_.IsDone();
+    }
 
-    if (done)
+    if (done) {
       SendTestResults(browser, frame, kOrderNavMsg);
+    }
   }
 
   // Send the test results.
@@ -1346,10 +1406,11 @@
     CefRefPtr<CefListValue> args = return_msg->GetArgumentList();
     EXPECT_TRUE(args.get());
     EXPECT_TRUE(args->SetBool(0, result));
-    if (browser->IsPopup())
+    if (browser->IsPopup()) {
       EXPECT_TRUE(args->SetInt(1, browser_id_popup_));
-    else
+    } else {
       EXPECT_TRUE(args->SetInt(1, browser_id_main_));
+    }
     frame->SendProcessMessage(PID_BROWSER, return_msg);
   }
 
@@ -1358,7 +1419,6 @@
   int browser_id_main_;
   int browser_id_popup_;
   CefRefPtr<CefBrowser> browser_main_;
-  TrackCallback got_render_thread_created_;
   TrackCallback got_webkit_initialized_;
   TrackCallback got_browser_created_main_;
   TrackCallback got_browser_destroyed_main_;
@@ -1402,20 +1462,26 @@
   }
 
   void ContinueIfReady(CefRefPtr<CefBrowser> browser) {
-    if (!got_message_)
+    if (!got_message_) {
       return;
+    }
 
     bool done = false;
-    if (browser->IsPopup())
+    if (browser->IsPopup()) {
       done = state_popup_.IsDone();
-    else
+    } else {
       done = state_main_.IsDone();
-    if (!done)
+    }
+    if (!done) {
       return;
+    }
 
     got_message_ = false;
 
     if (!browser->IsPopup()) {
+      GrantPopupPermission(browser->GetHost()->GetRequestContext(),
+                           browser->GetMainFrame()->GetURL());
+
       // Create the popup window.
       browser->GetMainFrame()->ExecuteJavaScript(
           "window.open('" + std::string(KONav2) + "');", CefString(), 0);
@@ -1475,12 +1541,13 @@
     }
 
     std::string url = request->GetURL();
-    if (url == KONav1)
+    if (url == KONav1) {
       EXPECT_FALSE(browser->IsPopup());
-    else if (url == KONav2)
+    } else if (url == KONav2) {
       EXPECT_TRUE(browser->IsPopup());
-    else
+    } else {
       EXPECT_TRUE(false);  // not reached
+    }
 
     return false;
   }
@@ -1489,7 +1556,12 @@
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) override {
+      CefRefPtr<CefCallback> callback) override {
+    if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
+      // Ignore favicon requests.
+      return RV_CANCEL;
+    }
+
     EXPECT_EQ(RT_MAIN_FRAME, request->GetResourceType());
 
     if (browser->IsPopup()) {
@@ -1517,8 +1589,9 @@
                                        canGoForward);
     }
 
-    if (!isLoading)
+    if (!isLoading) {
       ContinueIfReady(browser);
+    }
   }
 
   void OnLoadStart(CefRefPtr<CefBrowser> browser,
@@ -1634,9 +1707,9 @@
 
 namespace {
 
-const char kLoadNav1[] = "http://tests-conav1.com/nav1.html";
-const char kLoadNavSameOrigin2[] = "http://tests-conav1.com/nav2.html";
-const char kLoadNavCrossOrigin2[] = "http://tests-conav2.com/nav2.html";
+const char kLoadNav1[] = "https://tests-conav1.com/nav1.html";
+const char kLoadNavSameOrigin2[] = "https://tests-conav1.com/nav2.html";
+const char kLoadNavCrossOrigin2[] = "https://tests-conav2.com/nav2.html";
 const char kLoadNavMsg[] = "NavigationTest.LoadNav";
 const char kLoadNavTestCmdKey[] = "nav-load-test";
 
@@ -1644,38 +1717,44 @@
 class LoadNavRendererTest : public ClientAppRenderer::Delegate,
                             public CefLoadHandler {
  public:
-  LoadNavRendererTest() : run_test_(false), browser_id_(0), load_ct_(0) {}
-  ~LoadNavRendererTest() override { EXPECT_EQ(0, browser_id_); }
+  LoadNavRendererTest() = default;
 
   void OnBrowserCreated(CefRefPtr<ClientAppRenderer> app,
                         CefRefPtr<CefBrowser> browser,
                         CefRefPtr<CefDictionaryValue> extra_info) override {
-    run_test_ = extra_info->HasKey(kLoadNavTestCmdKey);
-    if (!run_test_)
+    run_test_ = extra_info && extra_info->HasKey(kLoadNavTestCmdKey);
+    if (!run_test_) {
       return;
+    }
 
-    EXPECT_EQ(0, browser_id_);
-    browser_id_ = browser->GetIdentifier();
-    EXPECT_GT(browser_id_, 0);
-    got_browser_created_.yes();
+    // We'll get multiple calls to OnBrowserCreated for same-site navigations
+    // with same-site BFCache enabled.
+    const int new_browser_id = browser->GetIdentifier();
+    if (browser_id_ != 0) {
+      EXPECT_EQ(browser_id_, new_browser_id);
+    } else {
+      browser_id_ = new_browser_id;
+      EXPECT_GT(browser_id_, 0);
+    }
+    browser_created_ct_++;
   }
 
   void OnBrowserDestroyed(CefRefPtr<ClientAppRenderer> app,
                           CefRefPtr<CefBrowser> browser) override {
-    if (!run_test_)
+    if (!run_test_) {
       return;
+    }
 
-    EXPECT_TRUE(got_browser_created_);
-    EXPECT_TRUE(got_loading_state_end_);
-
+    EXPECT_GT(load_ct_, 0);
+    EXPECT_GT(browser_created_ct_, 0);
     EXPECT_EQ(browser_id_, browser->GetIdentifier());
-    browser_id_ = 0;
   }
 
   CefRefPtr<CefLoadHandler> GetLoadHandler(
       CefRefPtr<ClientAppRenderer> app) override {
-    if (!run_test_)
+    if (!run_test_) {
       return nullptr;
+    }
 
     return this;
   }
@@ -1685,10 +1764,7 @@
                             bool canGoBack,
                             bool canGoForward) override {
     if (!isLoading) {
-      EXPECT_TRUE(got_browser_created_);
-
-      got_loading_state_end_.yes();
-
+      EXPECT_GT(browser_created_ct_, 0);
       EXPECT_EQ(browser_id_, browser->GetIdentifier());
 
       load_ct_++;
@@ -1710,16 +1786,16 @@
     EXPECT_TRUE(args.get());
     EXPECT_TRUE(args->SetBool(0, result));
     EXPECT_TRUE(args->SetInt(1, browser->GetIdentifier()));
-    EXPECT_TRUE(args->SetInt(2, load_ct_));
+    EXPECT_TRUE(args->SetInt(2, browser_created_ct_));
+    EXPECT_TRUE(args->SetInt(3, load_ct_));
     frame->SendProcessMessage(PID_BROWSER, return_msg);
   }
 
-  bool run_test_;
+  bool run_test_ = false;
 
-  int browser_id_;
-  int load_ct_;
-  TrackCallback got_browser_created_;
-  TrackCallback got_loading_state_end_;
+  int browser_id_ = 0;
+  int load_ct_ = 0;
+  int browser_created_ct_ = 0;
 
   IMPLEMENT_REFCOUNTING(LoadNavRendererTest);
 };
@@ -1739,9 +1815,7 @@
                      bool cancel_in_open_url = false)
       : mode_(mode),
         same_origin_(same_origin),
-        cancel_in_open_url_(cancel_in_open_url),
-        browser_id_current_(0),
-        renderer_load_ct_(0) {}
+        cancel_in_open_url_(cancel_in_open_url) {}
 
   std::string GetURL2() const {
     return same_origin_ ? kLoadNavSameOrigin2 : kLoadNavCrossOrigin2;
@@ -1754,8 +1828,9 @@
   void RunTest() override {
     const std::string& url2 = GetURL2();
     std::string link;
-    if (mode_ != LOAD)
+    if (mode_ != LOAD) {
       link = "<a href=\"" + url2 + "\">CLICK ME</a>";
+    }
 
     // Add the resources that we will navigate to/from.
     AddResource(kLoadNav1,
@@ -1774,8 +1849,9 @@
   }
 
   void ContinueIfReady(CefRefPtr<CefBrowser> browser) {
-    if (!got_message_ || !got_load_end_)
+    if (!got_message_ || !got_load_end_) {
       return;
+    }
 
     std::string url = browser->GetMainFrame()->GetURL();
     if (url == kLoadNav1) {
@@ -1802,7 +1878,7 @@
         CefMouseEvent mouse_event;
         mouse_event.x = 20;
         mouse_event.y = 20;
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
         // Use cmd instead of ctrl on OS X.
         mouse_event.modifiers =
             (mode_ == CTRL_LEFT_CLICK ? EVENTFLAG_COMMAND_DOWN : 0);
@@ -1813,17 +1889,15 @@
 
         cef_mouse_button_type_t button_type =
             (mode_ == MIDDLE_CLICK ? MBT_MIDDLE : MBT_LEFT);
-        browser->GetHost()->SendMouseClickEvent(mouse_event, button_type, false,
-                                                1);
-        browser->GetHost()->SendMouseClickEvent(mouse_event, button_type, true,
-                                                1);
+        SendMouseClickEvent(browser, mouse_event, button_type);
       }
 
       if (cancel_in_open_url_) {
         // The next navigation should not occur. Therefore call DestroyTest()
         // after a reasonable timeout.
         CefPostDelayedTask(
-            TID_UI, base::Bind(&LoadNavTestHandler::DestroyTest, this), 500);
+            TID_UI, base::BindOnce(&LoadNavTestHandler::DestroyTest, this),
+            500);
       }
     } else {
       // Done with the test.
@@ -1839,6 +1913,14 @@
     EXPECT_GT(browser_id_current_, 0);
   }
 
+  cef_transition_type_t ExpectedOpenURLTransitionType() const {
+    if (mode_ != LEFT_CLICK && IsChromeRuntimeEnabled()) {
+      // Because we triggered the navigation with LoadURL in OnOpenURLFromTab.
+      return kTransitionExplicitLoad;
+    }
+    return TT_LINK;
+  }
+
   bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
                       CefRefPtr<CefFrame> frame,
                       CefRefPtr<CefRequest> request,
@@ -1847,11 +1929,17 @@
     EXPECT_EQ(RT_MAIN_FRAME, request->GetResourceType());
     if (mode_ == LOAD || request->GetURL() == kLoadNav1) {
       EXPECT_EQ(kTransitionExplicitLoad, request->GetTransitionType());
-      EXPECT_FALSE(user_gesture);
+      if (IsChromeRuntimeEnabled()) {
+        // With the Chrome runtime this is true on initial navigation via
+        // chrome::AddTabAt() and also true for clicked links.
+        EXPECT_TRUE(user_gesture);
+      } else {
+        EXPECT_FALSE(user_gesture);
+      }
     } else {
-      EXPECT_EQ(TT_LINK, request->GetTransitionType());
+      EXPECT_EQ(ExpectedOpenURLTransitionType(), request->GetTransitionType());
 
-      if (mode_ == LEFT_CLICK) {
+      if (mode_ == LEFT_CLICK || IsChromeRuntimeEnabled()) {
         EXPECT_TRUE(user_gesture);
       } else {
         EXPECT_FALSE(user_gesture);
@@ -1886,18 +1974,27 @@
     // OnOpenURLFromTab should only be called for the file URL.
     EXPECT_STREQ(GetURL2().c_str(), target_url.ToString().c_str());
 
-    if (mode_ == LOAD)
+    if (mode_ == LOAD) {
       EXPECT_FALSE(user_gesture);
-    else
+    } else {
       EXPECT_TRUE(user_gesture);
+    }
 
-    EXPECT_EQ(WOD_NEW_BACKGROUND_TAB, target_disposition);
+    EXPECT_EQ(CEF_WOD_NEW_BACKGROUND_TAB, target_disposition);
 
     // OnOpenURLFromTab should be called before OnBeforeBrowse for the file URL.
     EXPECT_FALSE(got_before_browse_);
 
     got_open_url_from_tab_.yes();
 
+    if (!cancel_in_open_url_ && IsChromeRuntimeEnabled()) {
+      // The chrome runtime may create a new popup window, which is not the
+      // behavior that this test expects. Instead, match the alloy runtime
+      // behavior by navigating in the current window.
+      browser->GetMainFrame()->LoadURL(target_url);
+      return true;
+    }
+
     return cancel_in_open_url_;
   }
 
@@ -1905,14 +2002,20 @@
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) override {
+      CefRefPtr<CefCallback> callback) override {
+    if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
+      // Ignore favicon requests.
+      return RV_CANCEL;
+    }
+
     EXPECT_EQ(RT_MAIN_FRAME, request->GetResourceType());
 
     const auto transition_type = request->GetTransitionType();
-    if (mode_ == LOAD || request->GetURL() == kLoadNav1)
+    if (mode_ == LOAD || request->GetURL() == kLoadNav1) {
       EXPECT_EQ(kTransitionExplicitLoad, transition_type);
-    else
-      EXPECT_EQ(TT_LINK, transition_type);
+    } else {
+      EXPECT_EQ(ExpectedOpenURLTransitionType(), transition_type);
+    }
 
     EXPECT_GT(browser_id_current_, 0);
     EXPECT_EQ(browser_id_current_, browser->GetIdentifier());
@@ -1928,10 +2031,11 @@
     EXPECT_GT(browser_id_current_, 0);
     EXPECT_EQ(browser_id_current_, browser->GetIdentifier());
 
-    if (mode_ == LOAD || frame->GetURL() == kLoadNav1)
+    if (mode_ == LOAD || frame->GetURL() == kLoadNav1) {
       EXPECT_EQ(kTransitionExplicitLoad, transition_type);
-    else
-      EXPECT_EQ(TT_LINK, transition_type);
+    } else {
+      EXPECT_EQ(ExpectedOpenURLTransitionType(), transition_type);
+    }
 
     got_load_start_.yes();
   }
@@ -1962,7 +2066,9 @@
 
       EXPECT_EQ(browser_id_current_, args->GetInt(1));
 
-      renderer_load_ct_ = args->GetInt(2);
+      renderer_browser_created_ct_ = args->GetInt(2);
+      EXPECT_GE(renderer_browser_created_ct_, 1);
+      renderer_load_ct_ = args->GetInt(3);
       EXPECT_GE(renderer_load_ct_, 1);
 
       // Continue with the test.
@@ -1986,6 +2092,7 @@
 
       // We should only navigate a single time if the 2nd load is canceled.
       EXPECT_EQ(1, renderer_load_ct_);
+      EXPECT_EQ(1, renderer_browser_created_ct_);
     } else {
       EXPECT_TRUE(got_before_browse_);
       EXPECT_TRUE(got_before_resource_load_);
@@ -1996,16 +2103,25 @@
       if (same_origin_) {
         // The renderer process should always be reused.
         EXPECT_EQ(2, renderer_load_ct_);
+        if (IsSameSiteBFCacheEnabled()) {
+          // We expect multiple calls to OnBrowserCreated for same-site
+          // navigations with same-site BFCache enabled.
+          EXPECT_EQ(2, renderer_browser_created_ct_);
+        } else {
+          EXPECT_EQ(1, renderer_browser_created_ct_);
+        }
       } else {
         // Each renderer process is only used for a single navigation.
         EXPECT_EQ(1, renderer_load_ct_);
+        EXPECT_EQ(1, renderer_browser_created_ct_);
       }
     }
 
-    if (ExpectOpenURL())
+    if (ExpectOpenURL()) {
       EXPECT_TRUE(got_open_url_from_tab_);
-    else
+    } else {
       EXPECT_FALSE(got_open_url_from_tab_);
+    }
 
     TestHandler::DestroyTest();
   }
@@ -2015,8 +2131,9 @@
   const bool same_origin_;
   const bool cancel_in_open_url_;
 
-  int browser_id_current_;
-  int renderer_load_ct_;
+  int browser_id_current_ = 0;
+  int renderer_browser_created_ct_ = 0;
+  int renderer_load_ct_ = 0;
 
   TrackCallback got_before_browse_;
   TrackCallback got_open_url_from_tab_;
@@ -2133,8 +2250,8 @@
 
 namespace {
 
-const char kSimultPopupMainUrl[] = "http://www.tests-sp.com/main.html";
-const char kSimultPopupPopupUrl[] = "http://www.tests-sp.com/popup";
+const char kSimultPopupMainUrl[] = "https://www.tests-sp.com/main.html";
+const char kSimultPopupPopupUrl[] = "https://www.tests-sp.com/popup";
 const size_t kSimultPopupCount = 5U;
 
 // Test multiple popups simultaniously.
@@ -2198,6 +2315,9 @@
       EXPECT_LT(after_created_ct_, kSimultPopupCount);
       browser_id_[after_created_ct_] = browser->GetIdentifier();
       after_created_ct_++;
+    } else {
+      GrantPopupPermission(browser->GetHost()->GetRequestContext(),
+                           kSimultPopupMainUrl);
     }
   }
 
@@ -2205,8 +2325,9 @@
                             bool isLoading,
                             bool canGoBack,
                             bool canGoForward) override {
-    if (isLoading)
+    if (isLoading) {
       return;
+    }
 
     if (browser->IsPopup()) {
       const std::string& url = browser->GetMainFrame()->GetURL();
@@ -2230,12 +2351,14 @@
       const std::string& url = browser->GetMainFrame()->GetURL();
       for (size_t i = 0; i < kSimultPopupCount; ++i) {
         if (browser->GetIdentifier() == browser_id_[i]) {
+          EXPECT_TRUE(got_loading_state_change_[i]);
           EXPECT_STREQ(popup_url_[i].c_str(), url.c_str()) << i;
 
           got_before_close_[i].yes();
 
-          if (++before_close_ct_ == kSimultPopupCount)
+          if (++before_close_ct_ == kSimultPopupCount) {
             DestroyTest();
+          }
           return;
         }
       }
@@ -2290,29 +2413,40 @@
 
 namespace {
 
-const char kPopupJSOpenMainUrl[] = "http://www.tests-pjso.com/main.html";
-const char kPopupJSOpenPopupUrl[] = "http://www.tests-pjso.com/popup.html";
+const char kPopupJSOpenMainUrl[] = "https://www.tests-pjso.com/main.html";
+const char kPopupJSOpenPopupUrl[] = "https://www.tests-pjso.com/popup.html";
 
 // Test a popup where the URL is a JavaScript URI that opens another popup.
 class PopupJSWindowOpenTestHandler : public TestHandler {
  public:
-  PopupJSWindowOpenTestHandler()
-      : before_popup_ct_(0U),
-        after_created_ct_(0U),
-        load_end_ct_(0U),
-        before_close_ct_(0U) {}
+  PopupJSWindowOpenTestHandler(TestRequestContextMode mode,
+                               const std::string& cache_path)
+      : mode_(mode), cache_path_(cache_path) {}
 
   void RunTest() override {
     AddResource(kPopupJSOpenMainUrl, "<html>Main</html>", "text/html");
     AddResource(kPopupJSOpenPopupUrl, "<html>Popup</html>", "text/html");
 
-    // Create the browser.
-    CreateBrowser(kPopupJSOpenMainUrl);
+    // Create a new disk-based request context so that we can grant default
+    // popup permission (used for the popup without a valid URL) without
+    // impacting the global context.
+    CreateTestRequestContext(
+        mode_, cache_path_,
+        base::BindOnce(&PopupJSWindowOpenTestHandler::RunTestContinue, this));
 
     // Time out the test after a reasonable period of time.
     SetTestTimeout();
   }
 
+  void RunTestContinue(CefRefPtr<CefRequestContext> request_context) {
+    EXPECT_UI_THREAD();
+
+    GrantPopupPermission(request_context, CefString());
+
+    // Create the browser.
+    CreateBrowser(kPopupJSOpenMainUrl, request_context);
+  }
+
   bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
                      CefRefPtr<CefFrame> frame,
                      const CefString& target_url,
@@ -2334,12 +2468,13 @@
 
     if (browser->IsPopup()) {
       after_created_ct_++;
-      if (!popup1_)
+      if (!popup1_) {
         popup1_ = browser;
-      else if (!popup2_)
+      } else if (!popup2_) {
         popup2_ = browser;
-      else
+      } else {
         ADD_FAILURE();
+      }
     }
   }
 
@@ -2347,8 +2482,9 @@
                             bool isLoading,
                             bool canGoBack,
                             bool canGoForward) override {
-    if (isLoading)
+    if (isLoading) {
       return;
+    }
 
     if (browser->IsPopup()) {
       const std::string& url = browser->GetMainFrame()->GetURL();
@@ -2371,6 +2507,10 @@
       load_end_ct_++;
       CloseBrowser(browser, true);
     } else if (browser->GetMainFrame()->GetURL() == kPopupJSOpenMainUrl) {
+      // For the popup that has a valid URL.
+      GrantPopupPermission(browser->GetHost()->GetRequestContext(),
+                           kPopupJSOpenMainUrl);
+
       // Load the problematic JS URI.
       // This will result in 2 popups being created:
       // - An empty popup
@@ -2394,8 +2534,9 @@
     TestHandler::OnBeforeClose(browser);
 
     before_close_ct_++;
-    if (before_close_ct_ == 2U)
+    if (before_close_ct_ == 2U) {
       DestroyTest();
+    }
   }
 
  private:
@@ -2411,13 +2552,16 @@
     TestHandler::DestroyTest();
   }
 
+  const TestRequestContextMode mode_;
+  const std::string cache_path_;
+
   CefRefPtr<CefBrowser> popup1_;
   CefRefPtr<CefBrowser> popup2_;
 
-  size_t before_popup_ct_;
-  size_t after_created_ct_;
-  size_t load_end_ct_;
-  size_t before_close_ct_;
+  size_t before_popup_ct_ = 0U;
+  size_t after_created_ct_ = 0U;
+  size_t load_end_ct_ = 0U;
+  size_t before_close_ct_ = 0U;
 
   IMPLEMENT_REFCOUNTING(PopupJSWindowOpenTestHandler);
 };
@@ -2425,16 +2569,15 @@
 }  // namespace
 
 // Test a popup where the URL is a JavaScript URI that opens another popup.
-TEST(NavigationTest, PopupJSWindowOpen) {
-  CefRefPtr<PopupJSWindowOpenTestHandler> handler =
-      new PopupJSWindowOpenTestHandler();
-  handler->ExecuteTest();
-  ReleaseAndWaitForDestructor(handler);
-}
+RC_TEST_SINGLE(NavigationTest,
+               PopupJSWindowOpen,
+               PopupJSWindowOpenTestHandler,
+               TEST_RC_MODE_CUSTOM_WITH_HANDLER,
+               /*with_cache_path*/ true)
 
 namespace {
 
-const char kPopupJSEmptyMainUrl[] = "http://www.tests-pjse.com/main.html";
+const char kPopupJSEmptyMainUrl[] = "https://www.tests-pjse.com/main.html";
 
 // Test creation of a popup where the URL is empty.
 class PopupJSWindowEmptyTestHandler : public TestHandler {
@@ -2479,13 +2622,17 @@
                             bool isLoading,
                             bool canGoBack,
                             bool canGoForward) override {
-    if (isLoading)
+    if (isLoading) {
       return;
+    }
 
     if (browser->IsPopup()) {
       got_load_end_popup_.yes();
       CloseBrowser(browser, true);
     } else {
+      GrantPopupPermission(browser->GetHost()->GetRequestContext(),
+                           browser->GetMainFrame()->GetURL());
+
       browser->GetMainFrame()->LoadURL("javascript:window.open('')");
     }
   }
@@ -2538,7 +2685,7 @@
 
 namespace {
 
-const char kBrowseNavPageUrl[] = "http://tests-browsenav/nav.html";
+const char kBrowseNavPageUrl[] = "https://tests-browsenav/nav.html";
 
 // Browser side.
 class BrowseNavTestHandler : public TestHandler {
@@ -2622,10 +2769,11 @@
 
       got_loading_state_changed_start_.yes();
     } else {
-      if (allow_)
+      if (allow_) {
         EXPECT_STREQ(kBrowseNavPageUrl, url.c_str());
-      else
+      } else {
         EXPECT_STREQ("", url.c_str());
+      }
 
       got_loading_state_changed_end_.yes();
       DestroyTestIfDone();
@@ -2634,13 +2782,15 @@
 
  private:
   void DestroyTestIfDone() {
-    if (destroyed_)
+    if (destroyed_) {
       return;
+    }
 
     if (got_loading_state_changed_end_) {
       if (allow_) {
-        if (got_load_end_)
+        if (got_load_end_) {
           DestroyTest();
+        }
       } else if (got_load_error_) {
         DestroyTest();
       }
@@ -2648,8 +2798,9 @@
   }
 
   void DestroyTest() override {
-    if (destroyed_)
+    if (destroyed_) {
       return;
+    }
     destroyed_ = true;
 
     EXPECT_TRUE(got_before_browse_);
@@ -2700,7 +2851,7 @@
 
 namespace {
 
-const char kSameNavPageUrl[] = "http://tests-samenav/nav.html";
+const char kSameNavPageUrl[] = "https://tests-samenav/nav.html";
 
 // Browser side.
 class SameNavTestHandler : public TestHandler {
@@ -2773,10 +2924,11 @@
 
     if (isLoading) {
       // Verify the previous URL.
-      if (step_ == 0)
+      if (step_ == 0) {
         EXPECT_TRUE(url.empty());
-      else
+      } else {
         EXPECT_STREQ(kSameNavPageUrl, url.c_str());
+      }
 
       got_loading_state_changed_start_.yes();
     } else {
@@ -2816,8 +2968,9 @@
   }
 
   void DestroyTest() override {
-    if (destroyed_)
+    if (destroyed_) {
       return;
+    }
     destroyed_ = true;
 
     EXPECT_EQ(2, step_);
@@ -2858,7 +3011,7 @@
 
 namespace {
 
-const char kCancelPageUrl[] = "http://tests-cancelnav/nav.html";
+const char kCancelPageUrl[] = "https://tests-cancelnav/nav.html";
 
 // A scheme handler that never starts sending data.
 class UnstartedSchemeHandler : public CefResourceHandler {
@@ -2876,7 +3029,7 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
     response->SetStatus(200);
     response->SetMimeType("text/html");
@@ -2963,7 +3116,7 @@
     got_get_resource_handler_.yes();
 
     CefPostTask(TID_UI,
-                base::Bind(&CancelBeforeNavTestHandler::CancelLoad, this));
+                base::BindOnce(&CancelBeforeNavTestHandler::CancelLoad, this));
 
     return new UnstartedSchemeHandler();
   }
@@ -3036,8 +3189,9 @@
   }
 
   void DestroyTest() override {
-    if (destroyed_)
+    if (destroyed_) {
       return;
+    }
     destroyed_ = true;
 
     EXPECT_TRUE(got_loading_state_changed_start_);
@@ -3095,7 +3249,7 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
     response->SetStatus(200);
     response->SetMimeType("text/html");
@@ -3208,7 +3362,8 @@
 
     // The required delay is longer when browser-side navigation is enabled.
     CefPostDelayedTask(
-        TID_UI, base::Bind(&CancelAfterNavTestHandler::CancelLoad, this), 1000);
+        TID_UI, base::BindOnce(&CancelAfterNavTestHandler::CancelLoad, this),
+        1000);
 
     return new StalledSchemeHandler();
   }
@@ -3320,13 +3475,15 @@
   }
 
   void DestroyTestIfDone() {
-    if (got_loading_state_changed_end_ && got_load_end_)
+    if (got_loading_state_changed_end_ && got_load_end_) {
       DestroyTest();
+    }
   }
 
   void DestroyTest() override {
-    if (destroyed_)
+    if (destroyed_) {
       return;
+    }
     destroyed_ = true;
 
     EXPECT_TRUE(got_loading_state_changed_start_);
@@ -3367,9 +3524,9 @@
 
 namespace {
 
-const char kExtraInfoUrl[] = "http://tests-extrainfonav.com/extra.html";
+const char kExtraInfoUrl[] = "https://tests-extrainfonav.com/extra.html";
 const char kExtraInfoPopupUrl[] =
-    "http://tests-extrainfonav.com/extra_popup.html";
+    "https://tests-extrainfonav.com/extra_popup.html";
 const char kExtraInfoNavMsg[] = "NavigationTest.ExtraInfoNav";
 const char kExtraInfoTestCmdKey[] = "nav-extra-info-test";
 
@@ -3395,9 +3552,10 @@
   void OnBrowserCreated(CefRefPtr<ClientAppRenderer> app,
                         CefRefPtr<CefBrowser> browser,
                         CefRefPtr<CefDictionaryValue> extra_info) override {
-    run_test_ = extra_info->HasKey(kExtraInfoTestCmdKey);
-    if (!run_test_)
+    run_test_ = extra_info && extra_info->HasKey(kExtraInfoTestCmdKey);
+    if (!run_test_) {
       return;
+    }
 
     CefRefPtr<CefDictionaryValue> expected = CefDictionaryValue::Create();
     SetBrowserExtraInfo(expected);
@@ -3453,6 +3611,9 @@
     if (popup_opened_) {
       DestroyTest();
     } else {
+      GrantPopupPermission(browser->GetHost()->GetRequestContext(),
+                           browser->GetMainFrame()->GetURL());
+
       browser->GetMainFrame()->ExecuteJavaScript(
           "window.open('" + std::string(kExtraInfoPopupUrl) + "');",
           CefString(), 0);
@@ -3522,6 +3683,7 @@
 
   IMPLEMENT_REFCOUNTING(ExtraInfoNavTestHandler);
 };
+
 }  // namespace
 
 TEST(NavigationTest, ExtraInfo) {
@@ -3530,12 +3692,6 @@
   ReleaseAndWaitForDestructor(handler);
 }
 
-// Entry point for creating navigation browser test objects.
-// Called from client_app_delegates.cc.
-void CreateNavigationBrowserTests(ClientAppBrowser::DelegateSet& delegates) {
-  delegates.insert(new OrderNavBrowserTest);
-}
-
 // Entry point for creating navigation renderer test objects.
 // Called from client_app_delegates.cc.
 void CreateNavigationRendererTests(ClientAppRenderer::DelegateSet& delegates) {
diff --git a/src/tests/ceftests/os_rendering_unittest.cc b/src/tests/ceftests/os_rendering_unittest.cc
index 37c7af5..d915517 100644
--- a/src/tests/ceftests/os_rendering_unittest.cc
+++ b/src/tests/ceftests/os_rendering_unittest.cc
@@ -2,18 +2,19 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/base/cef_logging.h"
 #include "include/cef_parser.h"
 #include "include/cef_v8.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "include/wrapper/cef_stream_resource_handler.h"
 #include "tests/ceftests/routing_test_handler.h"
+#include "tests/ceftests/test_util.h"
 #include "tests/gtest/include/gtest/gtest.h"
 #include "tests/shared/browser/geometry_util.h"
 #include "tests/shared/browser/resource_util.h"
 
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
 #include <Carbon/Carbon.h>  // For character codes.
 #include "tests/ceftests/os_rendering_unittest_mac.h"
 #elif defined(OS_LINUX)
@@ -23,21 +24,22 @@
 HINSTANCE hInst = ::GetModuleHandle(nullptr);
 #endif
 
+// Set to 1 to enable verbose debugging info logging.
+#define VERBOSE_DEBUGGING 0
+
 namespace {
 
-const char kTestUrl[] = "http://tests/osrtest";
+const char kTestUrl[] = "https://tests/osrtest";
 
-// this html should render on a 600 x 400 window with a little vertical
-// offset with scrollbar.
-
-// default osr widget size
+// Must be both large enough for the drag/drop region to be visible and small
+// enough for a little vertical offset with scrollbar.
 const int kOsrWidth = 600;
-const int kOsrHeight = 400;
+const int kOsrHeight = 450;
 
 // bounding client rects for edit box and navigate button
 #if defined(OS_WIN)
 const CefRect kExpandedSelectRect(462, 42, 81, 334);
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
 const CefRect kExpandedSelectRect(462, 42, 75, 334);
 #elif defined(OS_LINUX)
 const CefRect kExpandedSelectRect(462, 42, 79, 334);
@@ -48,6 +50,10 @@
 // word to be written into edit box
 const char kKeyTestWord[] = "done";
 
+constexpr uint32_t kAllTouchHandleFlags =
+    (CEF_THS_FLAG_ENABLED | CEF_THS_FLAG_ORIENTATION | CEF_THS_FLAG_ORIGIN |
+     CEF_THS_FLAG_ALPHA);
+
 #if defined(OS_LINUX)
 
 // From ui/events/keycodes/keyboard_codes_posix.h
@@ -63,7 +69,7 @@
 const unsigned int kNativeKeyEscape = XK_Escape;
 const unsigned int kNativeKeyTab = XK_Tab;
 
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
 
 // See kKeyCodesMap in ui/events/keycodes/keyboard_code_conversion_mac.mm
 #define VKEY_D 'd'
@@ -81,7 +87,7 @@
 
 #endif
 
-#if defined(OS_MACOSX) || defined(OS_LINUX)
+#if defined(OS_MAC) || defined(OS_LINUX)
 
 const unsigned int kKeyTestCodes[] = {VKEY_D, VKEY_O, VKEY_N, VKEY_E};
 
@@ -126,6 +132,9 @@
   // Right click will trigger a context menu, and on destroying the test, it
   // should not crash
   OSR_TEST_CONTEXT_MENU,
+  // In certain scenarios, the quick menu should be shown instead of the context
+  // menu
+  OSR_TEST_QUICK_MENU,
   // clicking on dropdown box, PET_POPUP OnPaint is triggered
   OSR_TEST_POPUP_PAINT,
   // clicking on dropdown box, a popup will show up
@@ -182,12 +191,7 @@
                        public CefContextMenuHandler {
  public:
   OSRTestHandler(OSRTestType test_type, float scale_factor)
-      : test_type_(test_type),
-        scale_factor_(scale_factor),
-        event_count_(0),
-        event_total_(1),
-        started_(false),
-        touch_state_(CEF_TET_CANCELLED) {}
+      : test_type_(test_type), scale_factor_(scale_factor) {}
 
   // TestHandler methods
   void RunTest() override {
@@ -205,11 +209,18 @@
     RoutingTestHandler::OnAfterCreated(browser);
   }
 
-  void OnLoadEnd(CefRefPtr<CefBrowser> browser,
-                 CefRefPtr<CefFrame> frame,
-                 int httpStatusCode) override {
-    if (!started())
+  void OnLoadStart(CefRefPtr<CefBrowser> browser,
+                   CefRefPtr<CefFrame> frame,
+                   TransitionType transition_type) override {
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "OnLoadStart started=" << started()
+              << " finished=" << finished();
+#endif
+
+    // Only interested in the 2nd+ load.
+    if (!started()) {
       return;
+    }
 
     switch (test_type_) {
       case OSR_TEST_KEY_EVENTS: {
@@ -241,36 +252,338 @@
     }
   }
 
+  void OnLoadEnd(CefRefPtr<CefBrowser> browser,
+                 CefRefPtr<CefFrame> frame,
+                 int httpStatusCode) override {
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "OnLoadEnd started=" << started()
+              << " finished=" << finished();
+#endif
+
+    // Only interested in the first load.
+    if (started()) {
+      return;
+    }
+
+    if (test_type_ >= OSR_TEST_POPUP_FIRST &&
+        test_type_ <= OSR_TEST_POPUP_LAST) {
+      StartTest();
+      ExpandDropDown();
+      return;
+    }
+
+    switch (test_type_) {
+      case OSR_TEST_TOOLTIP:
+        if (StartTest()) {
+          CefMouseEvent mouse_event;
+          const CefRect& expected_rect = GetElementBounds("LI10");
+          mouse_event.x = MiddleX(expected_rect);
+          mouse_event.y = MiddleY(expected_rect);
+          mouse_event.modifiers = 0;
+          browser->GetHost()->SendMouseMoveEvent(mouse_event, false);
+        }
+        break;
+      case OSR_TEST_FOCUS:
+        if (StartTest()) {
+          // body.onfocus will make LI00 red
+          browser->GetHost()->SetFocus(true);
+        }
+        break;
+      case OSR_TEST_TAKE_FOCUS:
+        if (StartTest()) {
+          // Give focus to the last input element.
+          browser->GetMainFrame()->ExecuteJavaScript(
+              "document.getElementById('email').focus()",
+              browser->GetMainFrame()->GetURL(), 0);
+
+          // Tab traversal across HTML element.
+#if defined(OS_WIN)
+          CefPostDelayedTask(TID_UI,
+                             base::BindOnce(&OSRTestHandler::SendKeyEvent, this,
+                                            browser, VK_TAB),
+                             50);
+#elif defined(OS_MAC) || defined(OS_LINUX)
+          CefPostDelayedTask(TID_UI,
+                             base::BindOnce(&OSRTestHandler::SendKeyEvent, this,
+                                            browser, kNativeKeyTab, VKEY_TAB),
+                             50);
+#else
+#error "Unsupported platform"
+#endif
+        }
+        break;
+      case OSR_TEST_GOT_FOCUS:
+        if (StartTest()) {
+          browser->GetHost()->SetFocus(true);
+        }
+        break;
+      case OSR_TEST_CURSOR:
+        if (StartTest()) {
+          // enter mouse in the LI2 element having hand cursor
+          CefMouseEvent mouse_event;
+          const CefRect& expected_rect = GetElementBounds("LI02");
+          mouse_event.x = MiddleX(expected_rect);
+          mouse_event.y = MiddleY(expected_rect);
+          browser->GetHost()->SendMouseMoveEvent(mouse_event, false);
+        }
+        break;
+      case OSR_TEST_MOUSE_MOVE:
+        if (StartTest()) {
+          CefMouseEvent mouse_event;
+          const CefRect& expected_rect = GetElementBounds("LI03");
+          mouse_event.x = MiddleX(expected_rect);
+          mouse_event.y = MiddleY(expected_rect);
+          mouse_event.modifiers = 0;
+          browser->GetHost()->SendMouseMoveEvent(mouse_event, false);
+        }
+        break;
+      case OSR_TEST_CLICK_RIGHT:
+      case OSR_TEST_SCREEN_POINT:
+      case OSR_TEST_CONTEXT_MENU:
+        if (StartTest()) {
+          CefMouseEvent mouse_event;
+          const CefRect& expected_rect = GetElementBounds("LI04");
+          mouse_event.x = MiddleX(expected_rect);
+          mouse_event.y = MiddleY(expected_rect);
+          mouse_event.modifiers = 0;
+          SendMouseClickEvent(browser, mouse_event, MBT_RIGHT);
+        }
+        break;
+      case OSR_TEST_QUICK_MENU:
+        if (StartTest()) {
+          CefTouchEvent touch_event_pressed;
+          touch_event_pressed.type = CEF_TET_PRESSED;
+          const CefRect& expected_rect = GetElementBounds("quickmenu");
+          touch_event_pressed.x = MiddleX(expected_rect);
+          touch_event_pressed.y = MiddleY(expected_rect);
+          browser->GetHost()->SendTouchEvent(touch_event_pressed);
+        }
+        break;
+      case OSR_TEST_CLICK_LEFT:
+        if (StartTest()) {
+          CefMouseEvent mouse_event;
+          const CefRect& expected_rect = GetElementBounds("LI00");
+          mouse_event.x = MiddleX(expected_rect);
+          mouse_event.y = MiddleY(expected_rect);
+          mouse_event.modifiers = 0;
+          SendMouseClickEvent(browser, mouse_event);
+        }
+        break;
+      case OSR_TEST_DRAG_DROP_START_DRAGGING:
+      case OSR_TEST_DRAG_DROP_UPDATE_CURSOR:
+      case OSR_TEST_DRAG_DROP_DROP: {
+        // trigger the StartDragging event
+        if (StartTest()) {
+          // move the mouse over the element to drag
+          CefMouseEvent mouse_event;
+          const CefRect& dragdiv = GetElementBounds("dragdiv");
+          mouse_event.x = MiddleX(dragdiv);
+          mouse_event.y = MiddleY(dragdiv);
+          mouse_event.modifiers = 0;
+
+          // The div drag point must be visible.
+          EXPECT_LT(mouse_event.y, kOsrHeight);
+
+          browser->GetHost()->SendMouseMoveEvent(mouse_event, false);
+          // click on the element to drag
+          mouse_event.modifiers = EVENTFLAG_LEFT_MOUSE_BUTTON;
+          CefPostDelayedTask(
+              TID_UI,
+              base::BindOnce(&CefBrowserHost::SendMouseClickEvent,
+                             browser->GetHost(), mouse_event, MBT_LEFT, false,
+                             1),
+              50);
+          // move the mouse to start dragging
+          mouse_event.x -= 5;
+          mouse_event.y -= 5;
+          CefPostDelayedTask(
+              TID_UI,
+              base::BindOnce(&CefBrowserHost::SendMouseMoveEvent,
+                             browser->GetHost(), mouse_event, false),
+              100);
+        }
+      } break;
+      case OSR_TEST_KEY_EVENTS:
+      case OSR_TEST_IME_COMMIT_TEXT:
+      case OSR_TEST_IME_FINISH_COMPOSITION:
+      case OSR_TEST_IME_CANCEL_COMPOSITION:
+      case OSR_TEST_IME_SET_COMPOSITION:
+        if (StartTest()) {
+          // Results in a call to OnQuery.
+          FocusEditBox(browser);
+        }
+        break;
+      case OSR_TEST_TEXT_SELECTION_CHANGE: {
+        // trigger the text selection changed event
+        if (StartTest()) {
+          // click inside list element so text range will be selected.
+          CefMouseEvent mouse_event;
+          const CefRect& expected_rect = GetElementBounds("LI11");
+          mouse_event.x = MiddleX(expected_rect);
+          mouse_event.y = MiddleY(expected_rect);
+          mouse_event.modifiers = 0;
+          SendMouseClickEvent(browser, mouse_event);
+        }
+      } break;
+      case OSR_TEST_VIRTUAL_KEYBOARD: {
+        if (StartTest()) {
+          CefMouseEvent mouse_event;
+          const CefRect& input = GetElementBounds("email");
+          mouse_event.x = MiddleX(input);
+          mouse_event.y = MiddleY(input);
+          mouse_event.modifiers = 0;
+          SendMouseClickEvent(browser, mouse_event);
+        }
+      } break;
+      case OSR_TEST_TOUCH_START:
+      case OSR_TEST_TOUCH_MOVE:
+      case OSR_TEST_TOUCH_END:
+      case OSR_TEST_TOUCH_CANCEL: {
+        // We trigger a valid Touch workflow sequence and close the tests
+        // at seperate points for the 4 cases
+        if (StartTest()) {
+          const CefRect& touchdiv = GetElementBounds("touchdiv");
+          std::vector<CefTouchEvent> touch_events;
+
+          // click inside edit box so that text could be entered
+          CefTouchEvent touch_event1;
+          touch_event1.id = 0;
+          touch_event1.x = MiddleX(touchdiv) - 45;
+          touch_event1.y = MiddleY(touchdiv);
+          touch_event1.modifiers = 0;
+          touch_event1.type = CEF_TET_PRESSED;
+          touch_events.push_back(touch_event1);
+
+          CefTouchEvent touch_event2;
+          touch_event2.id = 1;
+          touch_event2.x = MiddleX(touchdiv) + 45;
+          touch_event2.y = MiddleY(touchdiv);
+          touch_event2.modifiers = 0;
+          touch_event2.type = CEF_TET_PRESSED;
+          touch_events.push_back(touch_event2);
+
+          if (test_type_ >= OSR_TEST_TOUCH_MOVE) {
+            // Move the Touch fingers closer
+            touch_event1.type = touch_event2.type = CEF_TET_MOVED;
+            for (size_t i = 0; i < 40; i++) {
+              touch_event1.x++;
+              touch_event2.x--;
+              touch_events.push_back(touch_event1);
+              touch_events.push_back(touch_event2);
+            }
+          }
+
+          // Now release the Touch fingers or cancel them
+          if (test_type_ == OSR_TEST_TOUCH_CANCEL) {
+            touch_event1.type = touch_event2.type = CEF_TET_CANCELLED;
+          } else {
+            touch_event1.type = touch_event2.type = CEF_TET_RELEASED;
+          }
+          touch_events.push_back(touch_event1);
+          touch_events.push_back(touch_event2);
+
+          CefPostDelayedTask(TID_UI,
+                             base::BindOnce(&OSRTestHandler::SendTouchEvents,
+                                            this, std::move(touch_events)),
+                             100);
+        }
+      } break;
+      case OSR_TEST_PEN: {
+        if (StartTest()) {
+          const CefRect& pointerdiv = GetElementBounds("pointerdiv");
+          std::vector<CefTouchEvent> touch_events;
+
+          CefTouchEvent touch_event;
+          touch_event.x = MiddleX(pointerdiv) - 45;
+          touch_event.y = MiddleY(pointerdiv);
+          touch_event.type = CEF_TET_PRESSED;
+          touch_event.pointer_type = CEF_POINTER_TYPE_PEN;
+
+          touch_events.push_back(touch_event);
+
+          touch_event.type = CEF_TET_MOVED;
+          for (size_t i = 0; i < 40; i++) {
+            touch_event.x++;
+            touch_events.push_back(touch_event);
+          }
+
+          touch_event.type = CEF_TET_RELEASED;
+          touch_events.push_back(touch_event);
+
+          CefPostDelayedTask(TID_UI,
+                             base::BindOnce(&OSRTestHandler::SendTouchEvents,
+                                            this, std::move(touch_events)),
+                             100);
+        }
+      } break;
+      default:
+        break;
+    }
+  }
+
   bool OnQuery(CefRefPtr<CefBrowser> browser,
                CefRefPtr<CefFrame> frame,
-               int64 query_id,
+               int64_t query_id,
                const CefString& request,
                bool persistent,
                CefRefPtr<Callback> callback) override {
     EXPECT_TRUE(browser.get());
 
-    if (!started()) {
+    const std::string& messageStr = request;
+    if (messageStr.length() > 0 && messageStr[0] == '{') {
       return handleBoundsQuery(browser, frame, query_id, request, persistent,
                                callback);
     }
 
-    const std::string& messageStr = request;
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "OnQuery message=" << messageStr;
+#endif
+
     switch (test_type_) {
       case OSR_TEST_FOCUS:
-        EXPECT_STREQ(messageStr.c_str(), "osrfocus");
-        DestroySucceededTestSoon();
+        if (messageStr == "osrfocus") {
+          DestroySucceededTestSoon();
+        }
         break;
       case OSR_TEST_CLICK_LEFT:
-        EXPECT_STREQ(messageStr.c_str(), "osrclick0");
-        DestroySucceededTestSoon();
+        if (messageStr == "osrclick0") {
+          DestroySucceededTestSoon();
+        }
         break;
       case OSR_TEST_MOUSE_MOVE:
-        EXPECT_STREQ(messageStr.c_str(), "osrmousemove");
-        DestroySucceededTestSoon();
+        if (messageStr == "osrmousemove") {
+          DestroySucceededTestSoon();
+        }
         break;
       case OSR_TEST_DRAG_DROP_DROP:
-        EXPECT_STREQ(messageStr.c_str(), "osrdrop");
-        DestroySucceededTestSoon();
+        if (messageStr == "osrdrop") {
+          DestroySucceededTestSoon();
+        }
+        break;
+      case OSR_TEST_KEY_EVENTS:
+        if (messageStr == "osrfocuseditbox") {
+          SendKeyEvents();
+        }
+        break;
+      case OSR_TEST_IME_COMMIT_TEXT:
+        if (messageStr == "osrfocuseditbox") {
+          SendIMECommitText();
+        }
+        break;
+      case OSR_TEST_IME_FINISH_COMPOSITION:
+        if (messageStr == "osrfocuseditbox") {
+          SendIMEFinishComposition();
+        }
+        break;
+      case OSR_TEST_IME_CANCEL_COMPOSITION:
+        if (messageStr == "osrfocuseditbox") {
+          SendIMECancelComposition();
+        }
+        break;
+      case OSR_TEST_IME_SET_COMPOSITION:
+        if (messageStr == "osrfocuseditbox") {
+          SendIMESetComposition();
+        }
         break;
       case OSR_TEST_TOUCH_START:
       case OSR_TEST_TOUCH_MOVE:
@@ -281,8 +594,9 @@
             // The first message expected is touchstart.
             // We expect multitouch, so touches length should be 2.
             // Ignore intermediate touch start events.
-            if (messageStr == "osrtouchstart1")
+            if (messageStr == "osrtouchstart1") {
               break;
+            }
             EXPECT_STREQ(messageStr.c_str(), "osrtouchstart2");
             // Close Touch Start Tests.
             if (test_type_ == OSR_TEST_TOUCH_START) {
@@ -352,7 +666,7 @@
 
   bool handleBoundsQuery(CefRefPtr<CefBrowser> browser,
                          CefRefPtr<CefFrame> frame,
-                         int64 query_id,
+                         int64_t query_id,
                          const CefString& request,
                          bool persistent,
                          CefRefPtr<Callback> callback) {
@@ -439,26 +753,36 @@
     // position popups. If not overwritten in this function, the rectangle
     // returned from GetViewRect will be used to popuplate them.
     // The popup in the test fits without modifications in the test window, so
-    // setting the screen to the test window size does not affect its rectangle.
+    // setting the screen to the test window size does not affect its
+    // rectangle.
     screen_info.rect = CefRect(0, 0, kOsrWidth, kOsrHeight);
     screen_info.available_rect = screen_info.rect;
     return true;
   }
 
   void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) override {
-    if (show && started()) {
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "OnPopupShow show=" << show << " started=" << started()
+              << " finished=" << finished();
+#endif
+
+    if (finished()) {
+      // OnPopupShow(show=false) may arrive after DestroyTest.
+      EXPECT_FALSE(show);
+      return;
+    }
+
+    EXPECT_TRUE(started());
+
+    if (show) {
       switch (test_type_) {
         case OSR_TEST_POPUP_SHOW:
-          if (!succeeded()) {
-            EXPECT_TRUE(show);
-            DestroySucceededTestSoon();
-          }
+          DestroySucceededTestSoon();
           break;
         default:
           break;
       }
-    }
-    if (!show && started()) {
+    } else {
       switch (test_type_) {
         case OSR_TEST_POPUP_HIDE_ON_BLUR:
         case OSR_TEST_POPUP_HIDE_ON_CLICK:
@@ -474,23 +798,34 @@
 
   void OnPopupSize(CefRefPtr<CefBrowser> browser,
                    const CefRect& rect) override {
-    if (started()) {
-      switch (test_type_) {
-        case OSR_TEST_POPUP_SIZE:
-          EXPECT_EQ(kExpandedSelectRect.x, rect.x);
-          EXPECT_EQ(kExpandedSelectRect.y, rect.y);
-          if (ExpectComputedPopupSize()) {
-            EXPECT_EQ(kExpandedSelectRect.width, rect.width);
-            EXPECT_EQ(kExpandedSelectRect.height, rect.height);
-          } else {
-            EXPECT_GT(rect.width, kExpandedSelectRect.width);
-            EXPECT_GT(rect.height, kExpandedSelectRect.height);
-          }
-          DestroySucceededTestSoon();
-          break;
-        default:
-          break;
-      }
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "OnPopupSize started=" << started()
+              << " finished=" << finished();
+#endif
+
+    if (finished()) {
+      // For OSR_TEST_POPUP_SHOW, OnPopupSize may arrive after DestroyTest.
+      EXPECT_EQ(OSR_TEST_POPUP_SHOW, test_type_);
+      return;
+    }
+
+    EXPECT_TRUE(started());
+
+    switch (test_type_) {
+      case OSR_TEST_POPUP_SIZE:
+        EXPECT_EQ(kExpandedSelectRect.x, rect.x);
+        EXPECT_EQ(kExpandedSelectRect.y, rect.y);
+        if (ExpectComputedPopupSize()) {
+          EXPECT_EQ(kExpandedSelectRect.width, rect.width);
+          EXPECT_EQ(kExpandedSelectRect.height, rect.height);
+        } else {
+          EXPECT_GE(rect.width, kExpandedSelectRect.width);
+          EXPECT_GE(rect.height, kExpandedSelectRect.height);
+        }
+        DestroySucceededTestSoon();
+        break;
+      default:
+        break;
     }
   }
 
@@ -519,9 +854,10 @@
 
     // start test only when painting something else then background
     if (IsBackgroundInBuffer(
-            reinterpret_cast<const uint32*>(buffer), width * height,
-            test_type_ == OSR_TEST_TRANSPARENCY ? 0x00000000 : 0xFFFFFFFF))
+            reinterpret_cast<const uint32_t*>(buffer), width * height,
+            test_type_ == OSR_TEST_TRANSPARENCY ? 0x00000000 : 0xFFFFFFFF)) {
       return;
+    }
 
     // Send events after the first full repaint
     switch (test_type_) {
@@ -531,7 +867,7 @@
           EXPECT_EQ(dirtyRects.size(), 1U);
           EXPECT_TRUE(IsFullRepaint(dirtyRects[0], GetScaledInt(kOsrWidth),
                                     GetScaledInt(kOsrHeight)));
-          EXPECT_EQ(0xffff7f7fU, *(reinterpret_cast<const uint32*>(buffer)));
+          EXPECT_EQ(0xffff7f7fU, *(reinterpret_cast<const uint32_t*>(buffer)));
           DestroySucceededTestSoon();
         }
         break;
@@ -541,88 +877,10 @@
           EXPECT_EQ(dirtyRects.size(), 1U);
           EXPECT_TRUE(IsFullRepaint(dirtyRects[0], GetScaledInt(kOsrWidth),
                                     GetScaledInt(kOsrHeight)));
-          EXPECT_EQ(0x80800000U, *(reinterpret_cast<const uint32*>(buffer)));
+          EXPECT_EQ(0x80800000U, *(reinterpret_cast<const uint32_t*>(buffer)));
           DestroySucceededTestSoon();
         }
         break;
-      case OSR_TEST_FOCUS:
-        if (StartTest()) {
-          // body.onfocus will make LI00 red
-          browser->GetHost()->SendFocusEvent(true);
-        }
-        break;
-      case OSR_TEST_TAKE_FOCUS:
-        if (StartTest() || started()) {
-          // Tab traversal across HTML element
-
-#if defined(OS_WIN)
-          SendKeyEvent(browser, VK_TAB);
-#elif defined(OS_MACOSX) || defined(OS_LINUX)
-          SendKeyEvent(browser, kNativeKeyTab, VKEY_TAB);
-#else
-#error "Unsupported platform"
-#endif
-        }
-        break;
-      case OSR_TEST_GOT_FOCUS:
-        if (StartTest()) {
-          browser->GetHost()->SendFocusEvent(true);
-        }
-        break;
-      case OSR_TEST_CURSOR:
-        if (StartTest()) {
-          // make mouse leave first
-          CefMouseEvent mouse_event;
-          mouse_event.x = 0;
-          mouse_event.y = 0;
-          mouse_event.modifiers = 0;
-          browser->GetHost()->SendMouseMoveEvent(mouse_event, true);
-          // enter mouse in the LI2 element having hand cursor
-          const CefRect& expected_rect = GetElementBounds("LI02");
-          mouse_event.x = MiddleX(expected_rect);
-          mouse_event.y = MiddleY(expected_rect);
-          browser->GetHost()->SendMouseMoveEvent(mouse_event, false);
-        }
-        break;
-      case OSR_TEST_MOUSE_MOVE:
-        if (StartTest()) {
-          CefMouseEvent mouse_event;
-          const CefRect& expected_rect = GetElementBounds("LI03");
-          mouse_event.x = MiddleX(expected_rect);
-          mouse_event.y = MiddleY(expected_rect);
-          mouse_event.modifiers = 0;
-          browser->GetHost()->SendMouseMoveEvent(mouse_event, false);
-        }
-        break;
-      case OSR_TEST_CLICK_RIGHT:
-      case OSR_TEST_SCREEN_POINT:
-      case OSR_TEST_CONTEXT_MENU:
-        if (StartTest()) {
-          CefMouseEvent mouse_event;
-          const CefRect& expected_rect = GetElementBounds("LI04");
-          mouse_event.x = MiddleX(expected_rect);
-          mouse_event.y = MiddleY(expected_rect);
-          mouse_event.modifiers = 0;
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_RIGHT, false,
-                                                  1);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_RIGHT, true,
-                                                  1);
-        }
-        break;
-      case OSR_TEST_CLICK_LEFT:
-        if (StartTest()) {
-          CefMouseEvent mouse_event;
-          const CefRect& expected_rect = GetElementBounds("LI00");
-          mouse_event.x = MiddleX(expected_rect);
-          mouse_event.y = MiddleY(expected_rect);
-
-          mouse_event.modifiers = 0;
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false,
-                                                  1);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true,
-                                                  1);
-        }
-        break;
       case OSR_TEST_RESIZE:
         if (StartTest()) {
           browser->GetHost()->WasResized();
@@ -647,60 +905,12 @@
           const CefRect& expected_rect =
               GetScaledRect(CefRect(0, 0, kOsrWidth, kOsrHeight));
           // There may be some partial repaints before the full repaint.
-          if (dirtyRects[0] == expected_rect)
+          if (dirtyRects[0] == expected_rect) {
             DestroySucceededTestSoon();
+          }
         }
         break;
       }
-      case OSR_TEST_KEY_EVENTS:
-        if (StartTest()) {
-          // click inside edit box
-          CefMouseEvent mouse_event;
-          const CefRect& editbox = GetElementBounds("editbox");
-          mouse_event.x = MiddleX(editbox);
-          mouse_event.y = MiddleY(editbox);
-          mouse_event.modifiers = 0;
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false,
-                                                  1);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true,
-                                                  1);
-
-          // write "done" word
-          CefKeyEvent event;
-          event.is_system_key = false;
-          event.modifiers = 0;
-
-          size_t word_length = strlen(kKeyTestWord);
-          for (size_t i = 0; i < word_length; ++i) {
-#if defined(OS_WIN)
-            SendKeyEvent(browser, kKeyTestWord[i]);
-#elif defined(OS_MACOSX) || defined(OS_LINUX)
-            SendKeyEvent(browser, kNativeKeyTestCodes[i], kKeyTestCodes[i]);
-#else
-#error "Unsupported platform"
-#endif
-          }
-
-          // click button to navigate
-          const CefRect& btnnavigate = GetElementBounds("btnnavigate");
-          mouse_event.x = MiddleX(btnnavigate);
-          mouse_event.y = MiddleY(btnnavigate);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false,
-                                                  1);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true,
-                                                  1);
-        }
-        break;
-      case OSR_TEST_TOOLTIP:
-        if (StartTest()) {
-          CefMouseEvent mouse_event;
-          const CefRect& expected_rect = GetElementBounds("LI10");
-          mouse_event.x = MiddleX(expected_rect);
-          mouse_event.y = MiddleY(expected_rect);
-          mouse_event.modifiers = 0;
-          browser->GetHost()->SendMouseMoveEvent(mouse_event, false);
-        }
-        break;
       case OSR_TEST_SCROLLING: {
         static const int deltaY = 10;
         if (StartTest()) {
@@ -716,29 +926,25 @@
           const CefRect& expected_rect =
               GetScaledRect(CefRect(0, 0, kOsrWidth, kOsrHeight));
           // There may be some partial repaints before the full repaint.
-          if (dirtyRects[0] == expected_rect)
+          if (dirtyRects[0] == expected_rect) {
             DestroySucceededTestSoon();
+          }
         }
         break;
       }
       case OSR_TEST_POPUP_HIDE_ON_CLICK:
-        if (StartTest()) {
-          ExpandDropDown();
-          // Wait for the first popup paint to occur
-        } else if (type == PET_POPUP) {
+        // Wait for the first popup paint to occur
+        if (type == PET_POPUP) {
           CefMouseEvent mouse_event;
           mouse_event.x = 1;
           mouse_event.y = 1;
           mouse_event.modifiers = 0;
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false,
-                                                  1);
+          SendMouseClickEvent(browser, mouse_event);
         }
         break;
       case OSR_TEST_POPUP_HIDE_ON_SCROLL:
-        if (StartTest()) {
-          ExpandDropDown();
-          // Wait for the first popup paint to occur
-        } else if (type == PET_POPUP) {
+        // Wait for the first popup paint to occur
+        if (type == PET_POPUP) {
           CefMouseEvent mouse_event;
           mouse_event.x = mouse_event.y = 1;
           mouse_event.modifiers = 0;
@@ -746,37 +952,26 @@
         }
         break;
       case OSR_TEST_POPUP_HIDE_ON_BLUR:
-        if (StartTest()) {
-          ExpandDropDown();
-          // Wait for the first popup paint to occur
-        } else if (type == PET_POPUP) {
-          browser->GetHost()->SendFocusEvent(false);
+        // Wait for the first popup paint to occur
+        if (type == PET_POPUP) {
+          browser->GetHost()->SetFocus(false);
         }
         break;
       case OSR_TEST_POPUP_HIDE_ON_ESC:
-        if (StartTest()) {
-          ExpandDropDown();
-          // Wait for the first popup paint to occur
-        } else if (type == PET_POPUP) {
+        // Wait for the first popup paint to occur
+        if (type == PET_POPUP) {
 #if defined(OS_WIN)
           SendKeyEvent(browser, VK_ESCAPE);
-#elif defined(OS_MACOSX) || defined(OS_LINUX)
+#elif defined(OS_MAC) || defined(OS_LINUX)
           SendKeyEvent(browser, kNativeKeyEscape, VKEY_ESCAPE);
 #else
 #error "Unsupported platform"
 #endif
         }
         break;
-      case OSR_TEST_POPUP_SHOW:
-      case OSR_TEST_POPUP_SIZE:
-        if (StartTest()) {
-          ExpandDropDown();
-        }
-        break;
       case OSR_TEST_POPUP_PAINT:
-        if (StartTest()) {
-          ExpandDropDown();
-        } else if (type == PET_POPUP) {
+        // Wait for the first popup paint to occur
+        if (type == PET_POPUP) {
           EXPECT_EQ(dirtyRects.size(), 1U);
           const CefRect& expanded_select_rect =
               GetScaledRect(kExpandedSelectRect);
@@ -791,11 +986,11 @@
           }
 
           // Unselected option background color is cyan.
-          // Go down 100 pixels to skip the selected option and over 5 pixels to
-          // avoid hitting the border.
-          const uint32 offset = dirtyRects[0].width * 100 + 5;
+          // Go down 100 pixels to skip the selected option and over 5 pixels
+          // to avoid hitting the border.
+          const uint32_t offset = dirtyRects[0].width * 100 + 5;
           EXPECT_EQ(0xff00ffff,
-                    *(reinterpret_cast<const uint32*>(buffer) + offset));
+                    *(reinterpret_cast<const uint32_t*>(buffer) + offset));
 
           if (ExpectComputedPopupSize()) {
             EXPECT_EQ(expanded_select_rect.width, width);
@@ -808,15 +1003,9 @@
         }
         break;
       case OSR_TEST_POPUP_SCROLL_INSIDE: {
-        static enum {
-          NotStarted,
-          Started,
-          Scrolled
-        } scroll_inside_state = NotStarted;
-        if (StartTest()) {
-          ExpandDropDown();
-          scroll_inside_state = Started;
-        } else if (type == PET_POPUP) {
+        static enum { Started, Scrolled } scroll_inside_state = Started;
+        // Wait for the first popup paint to occur
+        if (type == PET_POPUP) {
           if (scroll_inside_state == Started) {
             CefMouseEvent mouse_event;
             mouse_event.x = MiddleX(kExpandedSelectRect);
@@ -845,288 +1034,24 @@
           }
         }
       } break;
-      case OSR_TEST_DRAG_DROP_START_DRAGGING:
-      case OSR_TEST_DRAG_DROP_UPDATE_CURSOR:
-      case OSR_TEST_DRAG_DROP_DROP: {
-        // trigger the StartDragging event
-        if (StartTest()) {
-          // move the mouse over the element to drag
-          CefMouseEvent mouse_event;
-          const CefRect& dragdiv = GetElementBounds("dragdiv");
-          mouse_event.x = MiddleX(dragdiv);
-          mouse_event.y = MiddleY(dragdiv);
-          mouse_event.modifiers = 0;
-          browser->GetHost()->SendMouseMoveEvent(mouse_event, false);
-          // click on the element to drag
-          mouse_event.modifiers = EVENTFLAG_LEFT_MOUSE_BUTTON;
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false,
-                                                  1);
-          // move the mouse to start dragging
-          mouse_event.x -= 5;
-          mouse_event.y -= 5;
-          browser->GetHost()->SendMouseMoveEvent(mouse_event, false);
-        }
-      } break;
-      case OSR_TEST_IME_COMMIT_TEXT: {
-        // trigger the IME Set Composition event
-        if (StartTest()) {
-          // click inside edit box so that text could be entered
-          CefMouseEvent mouse_event;
-          const CefRect& editbox = GetElementBounds("editbox");
-          mouse_event.x = MiddleX(editbox);
-          mouse_event.y = MiddleY(editbox);
-          mouse_event.modifiers = 0;
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false,
-                                                  1);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true,
-                                                  1);
-
-          size_t word_length = strlen(kKeyTestWord);
-          // Add some input keys to edit box
-          for (size_t i = 0; i < word_length; ++i) {
-#if defined(OS_WIN)
-            SendKeyEvent(browser, kKeyTestWord[i]);
-#elif defined(OS_MACOSX) || defined(OS_LINUX)
-            SendKeyEvent(browser, kNativeKeyTestCodes[i], kKeyTestCodes[i]);
-#else
-#error "Unsupported platform"
-#endif
-          }
-          // This text should be honored instead of 'ka' added via key events
-          CefString markedText("osrimecommit");
-
-          CefRange range(0, static_cast<int>(markedText.length()));
-          browser->GetHost()->ImeCommitText(markedText, range, 0);
-
-          // click button to navigate
-          const CefRect& btnnavigate = GetElementBounds("btnnavigate");
-          mouse_event.x = MiddleX(btnnavigate);
-          mouse_event.y = MiddleY(btnnavigate);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false,
-                                                  1);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true,
-                                                  1);
-        }
-      } break;
-      case OSR_TEST_IME_FINISH_COMPOSITION: {
-        // trigger the IME Set Composition event
-        if (StartTest()) {
-          // click inside edit box so that text could be entered
-          CefMouseEvent mouse_event;
-          const CefRect& editbox = GetElementBounds("editbox");
-          mouse_event.x = MiddleX(editbox);
-          mouse_event.y = MiddleY(editbox);
-          mouse_event.modifiers = 0;
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false,
-                                                  1);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true,
-                                                  1);
-
-          size_t word_length = strlen(kKeyTestWord);
-          // Add some input keys to edit box
-          for (size_t i = 0; i < word_length; ++i) {
-#if defined(OS_WIN)
-            SendKeyEvent(browser, kKeyTestWord[i]);
-#elif defined(OS_MACOSX) || defined(OS_LINUX)
-            SendKeyEvent(browser, kNativeKeyTestCodes[i], kKeyTestCodes[i]);
-#else
-#error "Unsupported platform"
-#endif
-          }
-
-          // Finish Composition should set the existing composition
-          browser->GetHost()->ImeFinishComposingText(true);
-
-          // click button to navigate
-          const CefRect& btnnavigate = GetElementBounds("btnnavigate");
-          mouse_event.x = MiddleX(btnnavigate);
-          mouse_event.y = MiddleY(btnnavigate);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false,
-                                                  1);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true,
-                                                  1);
-        }
-      } break;
-      case OSR_TEST_IME_CANCEL_COMPOSITION: {
-        // trigger the IME Set Composition event
-        if (StartTest()) {
-          // click inside edit box so that text could be entered
-          CefMouseEvent mouse_event;
-          const CefRect& editbox = GetElementBounds("editbox");
-          mouse_event.x = MiddleX(editbox);
-          mouse_event.y = MiddleY(editbox);
-          mouse_event.modifiers = 0;
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false,
-                                                  1);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true,
-                                                  1);
-          // Add some input keys to edit box
-          CefString markedText("か");
-          std::vector<CefCompositionUnderline> underlines;
-
-          // Use a thin black underline by default.
-          CefRange range(0, static_cast<int>(markedText.length()));
-          cef_composition_underline_t line = {range, 0xFF000000, 0, false};
-          underlines.push_back(line);
-
-          CefRange replacement_range(0, static_cast<int>(markedText.length()));
-          CefRange selection_range(0, static_cast<int>(markedText.length()));
-
-          // Composition should be updated
-          browser->GetHost()->ImeSetComposition(
-              markedText, underlines, replacement_range, selection_range);
-
-          // CancelComposition should clean up the edit text
-          browser->GetHost()->ImeCancelComposition();
-
-          // click button to navigate and verify
-          const CefRect& btnnavigate = GetElementBounds("btnnavigate");
-          mouse_event.x = MiddleX(btnnavigate);
-          mouse_event.y = MiddleY(btnnavigate);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false,
-                                                  1);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true,
-                                                  1);
-        }
-      } break;
-      case OSR_TEST_IME_SET_COMPOSITION: {
-        // trigger the IME Set Composition event
-        if (StartTest()) {
-          // click inside edit box so that text could be entered
-          CefMouseEvent mouse_event;
-          const CefRect& editbox = GetElementBounds("editbox");
-          mouse_event.x = MiddleX(editbox);
-          mouse_event.y = MiddleY(editbox);
-          mouse_event.modifiers = 0;
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false,
-                                                  1);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true,
-                                                  1);
-
-          // Now set some intermediate text composition
-          CefString markedText("か");
-          std::vector<CefCompositionUnderline> underlines;
-
-          // Use a thin black underline by default.
-          CefRange range(0, static_cast<int>(markedText.length()));
-          cef_composition_underline_t line = {range, 0xFF000000, 0, false};
-          underlines.push_back(line);
-
-          CefRange replacement_range(0, static_cast<int>(markedText.length()));
-          CefRange selection_range(0, static_cast<int>(markedText.length()));
-
-          // This should update composition range and
-          // trigger the compositionRangeChanged callback
-          browser->GetHost()->ImeSetComposition(
-              markedText, underlines, replacement_range, selection_range);
-        }
-      } break;
-      case OSR_TEST_TEXT_SELECTION_CHANGE: {
-        // trigger the text selection changed event
-        if (StartTest()) {
-          // click inside list element so text range will be selected.
-          CefMouseEvent mouse_event;
-          const CefRect& expected_rect = GetElementBounds("LI11");
-          mouse_event.x = MiddleX(expected_rect);
-          mouse_event.y = MiddleY(expected_rect);
-          mouse_event.modifiers = 0;
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false,
-                                                  1);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true,
-                                                  1);
-        }
-      } break;
-      case OSR_TEST_VIRTUAL_KEYBOARD: {
-        if (StartTest()) {
-          CefMouseEvent mouse_event;
-          const CefRect& input = GetElementBounds("email");
-          mouse_event.x = MiddleX(input);
-          mouse_event.y = MiddleY(input);
-          mouse_event.modifiers = 0;
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false,
-                                                  1);
-          browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true,
-                                                  1);
-        }
-      } break;
-      case OSR_TEST_TOUCH_START:
-      case OSR_TEST_TOUCH_MOVE:
-      case OSR_TEST_TOUCH_END:
-      case OSR_TEST_TOUCH_CANCEL: {
-        // We trigger a valid Touch workflow sequence and close the tests
-        // at seperate points for the 4 cases
-        if (StartTest()) {
-          const CefRect& touchdiv = GetElementBounds("touchdiv");
-          // click inside edit box so that text could be entered
-          CefTouchEvent touch_event1;
-          touch_event1.id = 0;
-          touch_event1.x = MiddleX(touchdiv) - 45;
-          touch_event1.y = MiddleY(touchdiv);
-          touch_event1.modifiers = 0;
-          touch_event1.type = CEF_TET_PRESSED;
-
-          CefTouchEvent touch_event2;
-          touch_event2.id = 1;
-          touch_event2.x = MiddleX(touchdiv) + 45;
-          touch_event2.y = MiddleY(touchdiv);
-          touch_event2.modifiers = 0;
-          touch_event2.type = CEF_TET_PRESSED;
-
-          browser->GetHost()->SendTouchEvent(touch_event1);
-          browser->GetHost()->SendTouchEvent(touch_event2);
-
-          // Move the Touch fingers closer
-          touch_event1.type = touch_event2.type = CEF_TET_MOVED;
-          for (size_t i = 0; i < 40; i++) {
-            touch_event1.x++;
-            touch_event2.x--;
-            browser->GetHost()->SendTouchEvent(touch_event1);
-            browser->GetHost()->SendTouchEvent(touch_event2);
-          }
-
-          // Now release the Touch fingers or cancel them
-          if (test_type_ == OSR_TEST_TOUCH_CANCEL)
-            touch_event1.type = touch_event2.type = CEF_TET_CANCELLED;
-          else
-            touch_event1.type = touch_event2.type = CEF_TET_RELEASED;
-          browser->GetHost()->SendTouchEvent(touch_event1);
-          browser->GetHost()->SendTouchEvent(touch_event2);
-        }
-      } break;
-      case OSR_TEST_PEN: {
-        if (StartTest()) {
-          const CefRect& pointerdiv = GetElementBounds("pointerdiv");
-          CefTouchEvent touch_event;
-          touch_event.x = MiddleX(pointerdiv) - 45;
-          touch_event.y = MiddleY(pointerdiv);
-          touch_event.type = CEF_TET_PRESSED;
-          touch_event.pointer_type = CEF_POINTER_TYPE_PEN;
-
-          browser->GetHost()->SendTouchEvent(touch_event);
-
-          touch_event.type = CEF_TET_MOVED;
-          for (size_t i = 0; i < 40; i++) {
-            touch_event.x++;
-            browser->GetHost()->SendTouchEvent(touch_event);
-          }
-
-          touch_event.type = CEF_TET_RELEASED;
-          browser->GetHost()->SendTouchEvent(touch_event);
-        }
-      } break;
       default:
         break;
     }
   }
 
   bool OnSetFocus(CefRefPtr<CefBrowser> browser, FocusSource source) override {
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "OnSetFocus started=" << started();
+#endif
+
     if (source == FOCUS_SOURCE_NAVIGATION) {
       got_navigation_focus_event_.yes();
 
       // Ignore focus from the original navigation when we're testing focus
       // event delivery.
-      if (test_type_ == OSR_TEST_FOCUS)
+      if (test_type_ == OSR_TEST_FOCUS) {
         return true;
+      }
       return false;
     }
 
@@ -1136,28 +1061,35 @@
   }
 
   void OnTakeFocus(CefRefPtr<CefBrowser> browser, bool next) override {
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "OnTakeFocus next=" << next << " started=" << started();
+#endif
+
     if (test_type_ == OSR_TEST_TAKE_FOCUS) {
-      EXPECT_TRUE(true);
       DestroySucceededTestSoon();
     }
   }
 
   void OnGotFocus(CefRefPtr<CefBrowser> browser) override {
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "OnGotFocus started=" << started();
+#endif
+
     if (test_type_ == OSR_TEST_GOT_FOCUS) {
-      EXPECT_TRUE(true);
       DestroySucceededTestSoon();
     }
   }
 
-  void OnCursorChange(CefRefPtr<CefBrowser> browser,
+  bool OnCursorChange(CefRefPtr<CefBrowser> browser,
                       CefCursorHandle cursor,
-                      CursorType type,
+                      cef_cursor_type_t type,
                       const CefCursorInfo& custom_cursor_info) override {
     if (test_type_ == OSR_TEST_CURSOR && started()) {
       EXPECT_EQ(CT_HAND, type);
       EXPECT_EQ(nullptr, custom_cursor_info.buffer);
       DestroySucceededTestSoon();
     }
+    return true;
   }
 
   void OnImeCompositionRangeChanged(
@@ -1165,8 +1097,8 @@
       const CefRange& range,
       const CefRenderHandler::RectList& bounds) override {
     if (test_type_ == OSR_TEST_IME_SET_COMPOSITION && started()) {
-      EXPECT_EQ(range.from, 0);
-      EXPECT_EQ(range.to, 1);
+      EXPECT_EQ(range.from, 0U);
+      EXPECT_EQ(range.to, 1U);
       EXPECT_EQ(1U, bounds.size());
       DestroySucceededTestSoon();
     }
@@ -1184,19 +1116,19 @@
       CefRefPtr<CefImage> image = drag_data->GetImage();
       EXPECT_TRUE(image.get() != nullptr);
       if (image.get()) {
-        // Drag image height seems to always be + 1px greater than the drag rect
-        // on Linux. Therefore allow it to be +/- 1px.
+        // Drag image height seems to always be + 1px greater than the drag
+        // rect on Linux. Therefore allow it to be +/- 1px.
         EXPECT_NEAR(static_cast<int>(image->GetWidth()), dragdiv.width, 1);
         EXPECT_NEAR(static_cast<int>(image->GetHeight()), dragdiv.height, 1);
       }
-      // During testing hotspot (x, y) was (15, 23) at 1x scale and (15, 18) at
-      // 2x scale. Since the mechanism for determining this position is unclear
-      // test only that it falls within the rect boundaries.
+      // During testing hotspot (x, y) was (15, 23) at 1x scale and (15, 18)
+      // at 2x scale. Since the mechanism for determining this position is
+      // unclear test only that it falls within the rect boundaries.
       CefPoint hotspot = drag_data->GetImageHotspot();
       EXPECT_GT(hotspot.x, 0);
-      EXPECT_LT(hotspot.x, GetScaledInt(dragdiv.width));
+      EXPECT_LE(hotspot.x, GetScaledInt(dragdiv.width));
       EXPECT_GT(hotspot.y, 0);
-      EXPECT_LT(hotspot.y, GetScaledInt(dragdiv.height));
+      EXPECT_LE(hotspot.y, GetScaledInt(dragdiv.height));
 
       DestroySucceededTestSoon();
       return false;
@@ -1230,18 +1162,21 @@
 
   void UpdateDragCursor(CefRefPtr<CefBrowser> browser,
                         DragOperation operation) override {
+    if (operation == DRAG_OPERATION_NONE) {
+      return;
+    }
+
     if (test_type_ == OSR_TEST_DRAG_DROP_UPDATE_CURSOR && started()) {
-      if (operation != DRAG_OPERATION_NONE) {
-        const CefRect& dropdiv = GetElementBounds("dropdiv");
-        browser->GetHost()->DragSourceEndedAt(
-            MiddleX(dropdiv), MiddleY(dropdiv), DRAG_OPERATION_NONE);
-        browser->GetHost()->DragSourceSystemDragEnded();
-        DestroySucceededTestSoon();
-      }
+      const CefRect& dropdiv = GetElementBounds("dropdiv");
+      browser->GetHost()->DragSourceEndedAt(MiddleX(dropdiv), MiddleY(dropdiv),
+                                            DRAG_OPERATION_NONE);
+      browser->GetHost()->DragSourceSystemDragEnded();
+      DestroySucceededTestSoon();
     } else if (test_type_ == OSR_TEST_DRAG_DROP_DROP && started()) {
       // Don't end the drag multiple times.
-      if (got_update_cursor_)
+      if (got_update_cursor_) {
         return;
+      }
       got_update_cursor_.yes();
 
       CefMouseEvent ev;
@@ -1281,9 +1216,7 @@
         mouse_event.x = MiddleX(input);
         mouse_event.y = MiddleY(input);
         mouse_event.modifiers = 0;
-        browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false,
-                                                1);
-        browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true, 1);
+        SendMouseClickEvent(browser, mouse_event);
       } else {
         EXPECT_EQ(CEF_TEXT_INPUT_MODE_NONE, input_mode);
         DestroySucceededTestSoon();
@@ -1303,8 +1236,9 @@
                            CefRefPtr<CefFrame> frame,
                            CefRefPtr<CefContextMenuParams> params,
                            CefRefPtr<CefMenuModel> model) override {
-    if (!started())
+    if (!started()) {
       return;
+    }
     if (test_type_ == OSR_TEST_CLICK_RIGHT) {
       const CefRect& expected_rect = GetElementBounds("LI04");
       EXPECT_EQ(params->GetXCoord(), MiddleX(expected_rect));
@@ -1316,6 +1250,214 @@
     }
   }
 
+  bool RunContextMenu(CefRefPtr<CefBrowser> browser,
+                      CefRefPtr<CefFrame> frame,
+                      CefRefPtr<CefContextMenuParams> params,
+                      CefRefPtr<CefMenuModel> model,
+                      CefRefPtr<CefRunContextMenuCallback> callback) override {
+    if (!started()) {
+      return false;
+    }
+
+    EXPECT_UI_THREAD();
+
+    auto current_browser = GetBrowser();
+    EXPECT_TRUE(current_browser->IsSame(browser));
+    EXPECT_EQ(current_browser->GetFocusedFrame()->GetIdentifier(),
+              frame->GetIdentifier());
+
+    if (test_type_ == OSR_TEST_QUICK_MENU) {
+      EXPECT_EQ(2U, got_touch_handle_enabled_ct_);
+      EXPECT_EQ(2U, got_touch_handle_size_ct_);
+      EXPECT_TRUE(got_quick_menu_);
+      EXPECT_TRUE(got_quick_menu_command_);
+      EXPECT_TRUE(got_quick_menu_dismissed_);
+      EXPECT_EQ(2U, got_touch_handle_disabled_ct_);
+      EXPECT_FALSE(got_context_menu_);
+
+      got_context_menu_.yes();
+
+      // Got all expected callbacks.
+      DestroySucceededTestSoon();
+
+      // Cancel the menu immediately.
+      callback->Cancel();
+      return true;
+    }
+
+    return false;
+  }
+
+  bool RunQuickMenu(CefRefPtr<CefBrowser> browser,
+                    CefRefPtr<CefFrame> frame,
+                    const CefPoint& location,
+                    const CefSize& size,
+                    QuickMenuEditStateFlags edit_state_flags,
+                    CefRefPtr<CefRunQuickMenuCallback> callback) override {
+    if (!started()) {
+      return false;
+    }
+
+    EXPECT_UI_THREAD();
+
+    auto current_browser = GetBrowser();
+    EXPECT_TRUE(current_browser->IsSame(browser));
+    EXPECT_EQ(current_browser->GetFocusedFrame()->GetIdentifier(),
+              frame->GetIdentifier());
+
+    EXPECT_EQ(OSR_TEST_QUICK_MENU, test_type_);
+
+    EXPECT_GT(location.x, 0);
+    EXPECT_GT(location.y, 0);
+    EXPECT_GT(size.width, 0);
+    EXPECT_GT(size.height, 0);
+    EXPECT_EQ(static_cast<QuickMenuEditStateFlags>(QM_EDITFLAG_CAN_ELLIPSIS |
+                                                   QM_EDITFLAG_CAN_COPY),
+              edit_state_flags);
+    EXPECT_TRUE(callback.get());
+
+    EXPECT_EQ(2U, got_touch_handle_enabled_ct_);
+    EXPECT_EQ(2U, got_touch_handle_size_ct_);
+    EXPECT_FALSE(got_quick_menu_);
+    EXPECT_FALSE(got_quick_menu_command_);
+    EXPECT_FALSE(got_quick_menu_dismissed_);
+    EXPECT_EQ(0U, got_touch_handle_disabled_ct_);
+    EXPECT_FALSE(got_context_menu_);
+
+    got_quick_menu_.yes();
+
+    // Proceed to OnQuickMenuCommand.
+    callback->Continue(QM_EDITFLAG_CAN_ELLIPSIS,
+                       static_cast<cef_event_flags_t>(EVENTFLAG_SHIFT_DOWN));
+    return true;
+  }
+
+  bool OnQuickMenuCommand(CefRefPtr<CefBrowser> browser,
+                          CefRefPtr<CefFrame> frame,
+                          int command_id,
+                          EventFlags event_flags) override {
+    EXPECT_UI_THREAD();
+
+    auto current_browser = GetBrowser();
+    EXPECT_TRUE(current_browser->IsSame(browser));
+    EXPECT_EQ(current_browser->GetFocusedFrame()->GetIdentifier(),
+              frame->GetIdentifier());
+
+    EXPECT_EQ(OSR_TEST_QUICK_MENU, test_type_);
+
+    // Values passed to Continue() in RunQuickMenu.
+    EXPECT_EQ(QM_EDITFLAG_CAN_ELLIPSIS, command_id);
+    EXPECT_EQ(EVENTFLAG_SHIFT_DOWN, event_flags);
+
+    EXPECT_EQ(2U, got_touch_handle_enabled_ct_);
+    EXPECT_EQ(2U, got_touch_handle_size_ct_);
+    EXPECT_TRUE(got_quick_menu_);
+    EXPECT_FALSE(got_quick_menu_command_);
+    EXPECT_FALSE(got_quick_menu_dismissed_);
+    EXPECT_EQ(0U, got_touch_handle_disabled_ct_);
+    EXPECT_FALSE(got_context_menu_);
+
+    got_quick_menu_command_.yes();
+
+    // Proceed to OnQuickMenuDismissed and RunContextMenu.
+    return false;
+  }
+
+  void OnQuickMenuDismissed(CefRefPtr<CefBrowser> browser,
+                            CefRefPtr<CefFrame> frame) override {
+    EXPECT_UI_THREAD();
+
+    auto current_browser = GetBrowser();
+    EXPECT_TRUE(current_browser->IsSame(browser));
+    EXPECT_EQ(current_browser->GetFocusedFrame()->GetIdentifier(),
+              frame->GetIdentifier());
+
+    EXPECT_EQ(OSR_TEST_QUICK_MENU, test_type_);
+
+    EXPECT_EQ(2U, got_touch_handle_enabled_ct_);
+    EXPECT_EQ(2U, got_touch_handle_size_ct_);
+    EXPECT_TRUE(got_quick_menu_);
+    EXPECT_TRUE(got_quick_menu_command_);
+    EXPECT_FALSE(got_quick_menu_dismissed_);
+    EXPECT_EQ(0U, got_touch_handle_disabled_ct_);
+    EXPECT_FALSE(got_context_menu_);
+
+    EXPECT_EQ(kAllTouchHandleFlags, touch_handle_flags_);
+
+    got_quick_menu_dismissed_.yes();
+  }
+
+  void GetTouchHandleSize(CefRefPtr<CefBrowser> browser,
+                          cef_horizontal_alignment_t orientation,
+                          CefSize& size) override {
+    size = CefSize(24, 24);
+    got_touch_handle_size_ct_++;
+  }
+
+  void OnTouchHandleStateChanged(CefRefPtr<CefBrowser> browser,
+                                 const CefTouchHandleState& state) override {
+    if (!started()) {
+      return;
+    }
+
+    EXPECT_UI_THREAD();
+
+    auto current_browser = GetBrowser();
+    EXPECT_TRUE(current_browser->IsSame(browser));
+
+    if (test_type_ == OSR_TEST_QUICK_MENU) {
+      if (state.flags & CEF_THS_FLAG_ENABLED) {
+        EXPECT_EQ(state.orientation, 0);
+        EXPECT_EQ(state.origin.x, 0);
+        EXPECT_EQ(state.origin.y, 0);
+        EXPECT_EQ(state.alpha, 0);
+
+        if (state.enabled) {
+          got_touch_handle_enabled_ct_++;
+          EXPECT_FALSE(got_quick_menu_);
+          EXPECT_FALSE(got_quick_menu_command_);
+          EXPECT_FALSE(got_quick_menu_dismissed_);
+          EXPECT_EQ(0U, got_touch_handle_disabled_ct_);
+          EXPECT_FALSE(got_context_menu_);
+
+          touch_handle_flags_ |= CEF_THS_FLAG_ENABLED;
+        } else {
+          got_touch_handle_disabled_ct_++;
+          EXPECT_EQ(2U, got_touch_handle_enabled_ct_);
+          EXPECT_EQ(2U, got_touch_handle_size_ct_);
+          EXPECT_TRUE(got_quick_menu_);
+          EXPECT_TRUE(got_quick_menu_command_);
+          EXPECT_TRUE(got_quick_menu_dismissed_);
+          EXPECT_FALSE(got_context_menu_);
+        }
+      }
+      if (state.flags & CEF_THS_FLAG_ORIENTATION) {
+        EXPECT_EQ(state.enabled, false);
+        EXPECT_GE(state.orientation, 0);
+        EXPECT_EQ(state.origin.x, 0);
+        EXPECT_EQ(state.origin.y, 0);
+        EXPECT_EQ(state.alpha, 0);
+        touch_handle_flags_ |= CEF_THS_FLAG_ORIENTATION;
+      }
+      if (state.flags & CEF_THS_FLAG_ORIGIN) {
+        EXPECT_EQ(state.enabled, false);
+        EXPECT_EQ(state.orientation, 0);
+        EXPECT_GT(state.origin.x, 0);
+        EXPECT_GT(state.origin.y, 0);
+        EXPECT_EQ(state.alpha, 0);
+        touch_handle_flags_ |= CEF_THS_FLAG_ORIGIN;
+      }
+      if (state.flags & CEF_THS_FLAG_ALPHA) {
+        EXPECT_EQ(state.enabled, false);
+        EXPECT_EQ(state.orientation, 0);
+        EXPECT_EQ(state.origin.x, 0);
+        EXPECT_EQ(state.origin.y, 0);
+        EXPECT_GE(state.alpha, 0);
+        touch_handle_flags_ |= CEF_THS_FLAG_ALPHA;
+      }
+    }
+  }
+
   // OSRTestHandler functions
   void CreateOSRBrowser(const CefString& url) {
     CefWindowInfo windowInfo;
@@ -1328,13 +1470,14 @@
 
 #if defined(OS_WIN)
     windowInfo.SetAsWindowless(GetDesktopWindow());
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
     // An actual vies is needed only for the ContextMenu test. The menu runner
     // checks if the view is not nil before showing the context menu.
-    if (test_type_ == OSR_TEST_CONTEXT_MENU)
+    if (test_type_ == OSR_TEST_CONTEXT_MENU) {
       windowInfo.SetAsWindowless(osr_unittests::GetFakeView());
-    else
+    } else {
       windowInfo.SetAsWindowless(kNullWindowHandle);
+    }
 #elif defined(OS_LINUX)
     windowInfo.SetAsWindowless(kNullWindowHandle);
 #else
@@ -1364,9 +1507,9 @@
     return rc.width == width && rc.height == height;
   }
 
-  static bool IsBackgroundInBuffer(const uint32* buffer,
+  static bool IsBackgroundInBuffer(const uint32_t* buffer,
                                    size_t size,
-                                   uint32 rgba) {
+                                   uint32_t rgba) {
     for (size_t i = 0; i < size; i++) {
       if (buffer[i] != rgba) {
         return false;
@@ -1384,33 +1527,168 @@
   }
 
   bool ExpectComputedPopupSize() const {
-#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX))
-    // On Windows the device scale factor is ignored in Blink when computing
+    // The device scale factor is ignored in Blink when computing
     // the default form control font size (see https://crbug.com/674663#c11).
     // This results in better font size display but also means that we won't
     // get the expected (scaled) width/height value for non-1.0 scale factor
     // select popups.
-    // On both Windows and Linux the non-1.0 scale factor size is off by a few
-    // pixels so we can't perform an exact comparison.
+    // The non-1.0 scale factor size is off by a few pixels so we can't
+    // perform an exact comparison.
     return scale_factor_ == 1.0;
+  }
+
+  static void FocusEditBox(CefRefPtr<CefBrowser> browser) {
+    browser->GetMainFrame()->ExecuteJavaScript(
+        "document.getElementById('editbox').focus()",
+        browser->GetMainFrame()->GetURL(), 0);
+  }
+
+  static void ClickButtonToNavigate(CefRefPtr<CefBrowser> browser) {
+    browser->GetMainFrame()->ExecuteJavaScript(
+        "document.getElementById('btnnavigate').click()",
+        browser->GetMainFrame()->GetURL(), 0);
+  }
+
+  void SendKeyEvents() {
+    auto browser = GetBrowser();
+
+    // write "done" word
+    CefKeyEvent event;
+    event.is_system_key = false;
+    event.modifiers = 0;
+
+    size_t word_length = strlen(kKeyTestWord);
+    for (size_t i = 0; i < word_length; ++i) {
+#if defined(OS_WIN)
+      SendKeyEvent(browser, kKeyTestWord[i]);
+#elif defined(OS_MAC) || defined(OS_LINUX)
+      SendKeyEvent(browser, kNativeKeyTestCodes[i], kKeyTestCodes[i]);
 #else
-    return true;
+#error "Unsupported platform"
 #endif
+    }
+
+    ClickButtonToNavigate(browser);
+  }
+
+  void SendIMECommitText() {
+    auto browser = GetBrowser();
+
+    size_t word_length = strlen(kKeyTestWord);
+    // Add some input keys to edit box
+    for (size_t i = 0; i < word_length; ++i) {
+#if defined(OS_WIN)
+      SendKeyEvent(browser, kKeyTestWord[i]);
+#elif defined(OS_MAC) || defined(OS_LINUX)
+      SendKeyEvent(browser, kNativeKeyTestCodes[i], kKeyTestCodes[i]);
+#else
+#error "Unsupported platform"
+#endif
+    }
+    // This text should be honored instead of 'ka' added via key events
+    CefString markedText("osrimecommit");
+
+    CefRange range(0, static_cast<uint32_t>(markedText.length()));
+    browser->GetHost()->ImeCommitText(markedText, range, 0);
+
+    ClickButtonToNavigate(browser);
+  }
+
+  void SendIMEFinishComposition() {
+    auto browser = GetBrowser();
+
+    size_t word_length = strlen(kKeyTestWord);
+    // Add some input keys to edit box
+    for (size_t i = 0; i < word_length; ++i) {
+#if defined(OS_WIN)
+      SendKeyEvent(browser, kKeyTestWord[i]);
+#elif defined(OS_MAC) || defined(OS_LINUX)
+      SendKeyEvent(browser, kNativeKeyTestCodes[i], kKeyTestCodes[i]);
+#else
+#error "Unsupported platform"
+#endif
+    }
+
+    // Finish Composition should set the existing composition
+    browser->GetHost()->ImeFinishComposingText(true);
+
+    ClickButtonToNavigate(browser);
+  }
+
+  void SendIMECancelComposition() {
+    auto browser = GetBrowser();
+
+    // Add some input keys to edit box
+    CefString markedText(L"\u304B");
+    std::vector<CefCompositionUnderline> underlines;
+
+    // Use a thin black underline by default.
+    CefRange range(0, static_cast<uint32_t>(markedText.length()));
+    cef_composition_underline_t line = {range, 0xFF000000, 0, false};
+    underlines.push_back(line);
+
+    CefRange replacement_range(0, static_cast<uint32_t>(markedText.length()));
+    CefRange selection_range(0, static_cast<uint32_t>(markedText.length()));
+
+    // Composition should be updated
+    browser->GetHost()->ImeSetComposition(markedText, underlines,
+                                          replacement_range, selection_range);
+
+    // CancelComposition should clean up the edit text
+    browser->GetHost()->ImeCancelComposition();
+
+    ClickButtonToNavigate(browser);
+  }
+
+  void SendIMESetComposition() {
+    auto browser = GetBrowser();
+
+    // Now set some intermediate text composition
+    CefString markedText(L"\u304B");
+    std::vector<CefCompositionUnderline> underlines;
+
+    // Use a thin black underline by default.
+    CefRange range(0, static_cast<uint32_t>(markedText.length()));
+    cef_composition_underline_t line = {range, 0xFF000000, 0, false};
+    underlines.push_back(line);
+
+    CefRange replacement_range(0, static_cast<uint32_t>(markedText.length()));
+    CefRange selection_range(0, static_cast<uint32_t>(markedText.length()));
+
+    // This should update composition range and
+    // trigger the compositionRangeChanged callback
+    browser->GetHost()->ImeSetComposition(markedText, underlines,
+                                          replacement_range, selection_range);
+  }
+
+  void SendTouchEvents(std::vector<CefTouchEvent> touch_events) {
+    auto host = GetBrowser()->GetHost();
+    for (const auto& te : touch_events) {
+      host->SendTouchEvent(te);
+    }
   }
 
   void DestroySucceededTestSoon() {
-    if (succeeded())
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "DestroySucceededTestSoon finished=" << finished();
+#endif
+
+    if (finished()) {
       return;
-    if (++event_count_ == event_total_)
-      CefPostTask(TID_UI, base::Bind(&OSRTestHandler::DestroyTest, this));
+    }
+    finished_ = true;
+    CefPostTask(TID_UI, base::BindOnce(&OSRTestHandler::DestroyTest, this));
   }
 
   void DestroyTest() override {
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "DestroyTest";
+#endif
+
     // Always get the OnSetFocus call for the initial navigation.
     EXPECT_TRUE(got_navigation_focus_event_);
 
-    if (test_type_ == OSR_TEST_FOCUS || (test_type_ >= OSR_TEST_POPUP_FIRST &&
-                                         test_type_ <= OSR_TEST_POPUP_LAST)) {
+    if (test_type_ == OSR_TEST_FOCUS) {
       // SetFocus is called by the system when we explicitly set the focus and
       // when popups are dismissed.
       EXPECT_TRUE(got_system_focus_event_);
@@ -1420,23 +1698,38 @@
       EXPECT_FALSE(got_system_focus_event_);
     }
 
+    if (test_type_ == OSR_TEST_QUICK_MENU) {
+      EXPECT_EQ(2U, got_touch_handle_enabled_ct_);
+      EXPECT_EQ(2U, got_touch_handle_size_ct_);
+      EXPECT_TRUE(got_quick_menu_);
+      EXPECT_TRUE(got_quick_menu_command_);
+      EXPECT_TRUE(got_quick_menu_dismissed_);
+      EXPECT_EQ(2U, got_touch_handle_disabled_ct_);
+      EXPECT_TRUE(got_context_menu_);
+      EXPECT_EQ(kAllTouchHandleFlags, touch_handle_flags_);
+    }
+
     RoutingTestHandler::DestroyTest();
   }
 
   void ExpandDropDown() {
-    GetBrowser()->GetHost()->SendFocusEvent(true);
-    CefMouseEvent mouse_event;
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << "ExpandDropDown";
+#endif
+
+    EXPECT_TRUE(started());
+    EXPECT_FALSE(finished());
 
     const CefRect& LI11select = GetElementBounds("LI11select");
+    CefMouseEvent mouse_event;
     mouse_event.x = MiddleX(LI11select);
     mouse_event.y = MiddleY(LI11select);
     mouse_event.modifiers = 0;
-    GetBrowser()->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false,
-                                                 1);
+    SendMouseClickEvent(GetBrowser(), mouse_event);
   }
 
   void SendKeyEvent(CefRefPtr<CefBrowser> browser,
-#if defined(OS_LINUX) || defined(OS_MACOSX)
+#if defined(OS_LINUX) || defined(OS_MAC)
                     unsigned int native_key_code,
 #endif
                     int key_code) {
@@ -1450,7 +1743,7 @@
     event.native_key_code = (scanCode << 16) |  // key scan code
                             1;                  // key repeat count
     event.windows_key_code = VkCode;
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
     event.native_key_code = native_key_code;
     // Note that this is only correct for lower-case characters. If |key_code|
     // was an upper-case character then |event.character| would be the upper-
@@ -1483,34 +1776,45 @@
   }
 
   // true if the events for this test are already sent
-  bool started() { return started_; }
+  bool started() const { return started_; }
 
   // true if the exit point was reached, even the result is not
   // the expected one
-  bool succeeded() { return (event_count_ == event_total_); }
+  bool finished() const { return finished_; }
 
   // will mark test as started and will return true only the first time
   // it is called
   bool StartTest() {
-    if (started_)
+    if (started_) {
       return false;
+    }
     started_ = true;
     return true;
   }
 
  private:
-  OSRTestType test_type_;
-  float scale_factor_;
-  int event_count_;
-  int event_total_;
-  bool started_;
-  cef_touch_event_type_t touch_state_;
+  const OSRTestType test_type_;
+  const float scale_factor_;
+
+  bool started_ = false;
+  bool finished_ = false;
+  cef_touch_event_type_t touch_state_ = CEF_TET_CANCELLED;
+
   TrackCallback got_update_cursor_;
   TrackCallback got_navigation_focus_event_;
   TrackCallback got_system_focus_event_;
   TrackCallback got_initial_text_selection_event_;
   TrackCallback got_virtual_keyboard_event_;
 
+  uint32_t touch_handle_flags_ = 0U;
+  size_t got_touch_handle_enabled_ct_ = 0U;
+  size_t got_touch_handle_size_ct_ = 0U;
+  TrackCallback got_quick_menu_;
+  TrackCallback got_quick_menu_command_;
+  TrackCallback got_quick_menu_dismissed_;
+  size_t got_touch_handle_disabled_ct_ = 0U;
+  TrackCallback got_context_menu_;
+
   typedef std::map<std::string, CefRect> ElementBoundsMap;
   ElementBoundsMap element_bounds_;
 
@@ -1525,7 +1829,7 @@
     CefRefPtr<OSRTestHandler> handler =              \
         new OSRTestHandler(test_mode, scale_factor); \
     handler->ExecuteTest();                          \
-    EXPECT_TRUE(handler->succeeded());               \
+    EXPECT_TRUE(handler->finished());                \
     ReleaseAndWaitForDestructor(handler);            \
   }
 
@@ -1564,6 +1868,8 @@
 OSR_TEST(Scrolling2x, OSR_TEST_SCROLLING, 2.0f)
 OSR_TEST(ContextMenu, OSR_TEST_CONTEXT_MENU, 1.0f)
 OSR_TEST(ContextMenu2x, OSR_TEST_CONTEXT_MENU, 2.0f)
+OSR_TEST(QuickMenu, OSR_TEST_QUICK_MENU, 1.0f)
+OSR_TEST(QuickMenu2x, OSR_TEST_CONTEXT_MENU, 2.0f)
 OSR_TEST(PopupPaint, OSR_TEST_POPUP_PAINT, 1.0f)
 OSR_TEST(PopupPaint2x, OSR_TEST_POPUP_PAINT, 2.0f)
 OSR_TEST(PopupShow, OSR_TEST_POPUP_SHOW, 1.0f)
@@ -1598,11 +1904,11 @@
 OSR_TEST(TextSelectionChanged2x, OSR_TEST_TEXT_SELECTION_CHANGE, 2.0f)
 OSR_TEST(VirtualKeyboard, OSR_TEST_VIRTUAL_KEYBOARD, 1.0f)
 OSR_TEST(TouchStart, OSR_TEST_TOUCH_START, 1.0f)
-OSR_TEST(TouchStart2X, OSR_TEST_TOUCH_START, 2.0f)
+OSR_TEST(TouchStart2x, OSR_TEST_TOUCH_START, 2.0f)
 OSR_TEST(TouchMove, OSR_TEST_TOUCH_MOVE, 1.0f)
-OSR_TEST(TouchMove2X, OSR_TEST_TOUCH_MOVE, 2.0f)
+OSR_TEST(TouchMove2x, OSR_TEST_TOUCH_MOVE, 2.0f)
 OSR_TEST(TouchEnd, OSR_TEST_TOUCH_END, 1.0f)
-OSR_TEST(TouchEnd2X, OSR_TEST_TOUCH_END, 2.0f)
+OSR_TEST(TouchEnd2x, OSR_TEST_TOUCH_END, 2.0f)
 OSR_TEST(TouchCancel, OSR_TEST_TOUCH_CANCEL, 1.0f)
-OSR_TEST(TouchCancel2X, OSR_TEST_TOUCH_CANCEL, 2.0f)
+OSR_TEST(TouchCancel2x, OSR_TEST_TOUCH_CANCEL, 2.0f)
 OSR_TEST(PenEvent, OSR_TEST_PEN, 1.0f)
diff --git a/src/tests/ceftests/os_rendering_unittest_mac.h b/src/tests/ceftests/os_rendering_unittest_mac.h
index b01cc0a..8a54bef 100644
--- a/src/tests/ceftests/os_rendering_unittest_mac.h
+++ b/src/tests/ceftests/os_rendering_unittest_mac.h
@@ -2,8 +2,8 @@
 // reserved. Use of this source code is governed by a BSD-style license
 // that can be found in the LICENSE file.
 
-#ifndef CEF_TESTS_UNITTESTS_OS_RENDERING_UNITTEST_MAC_H_
-#define CEF_TESTS_UNITTESTS_OS_RENDERING_UNITTEST_MAC_H_
+#ifndef CEF_TESTS_CEFTESTS_OS_RENDERING_UNITTEST_MAC_H_
+#define CEF_TESTS_CEFTESTS_OS_RENDERING_UNITTEST_MAC_H_
 
 #include "include/cef_base.h"
 
@@ -13,4 +13,4 @@
 
 }  // namespace osr_unittests
 
-#endif
+#endif  // CEF_TESTS_CEFTESTS_OS_RENDERING_UNITTEST_MAC_H_
diff --git a/src/tests/ceftests/osr_accessibility_unittest.cc b/src/tests/ceftests/osr_accessibility_unittest.cc
index 0cf10a4..abb10e0 100644
--- a/src/tests/ceftests/osr_accessibility_unittest.cc
+++ b/src/tests/ceftests/osr_accessibility_unittest.cc
@@ -2,7 +2,7 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_accessibility_handler.h"
 #include "include/cef_parser.h"
 #include "include/cef_waitable_event.h"
@@ -101,8 +101,8 @@
         // Post a delayed task to disable Accessibility
         CefPostDelayedTask(
             TID_UI,
-            base::Bind(&AccessibilityTestHandler::DisableAccessibility, this,
-                       browser),
+            base::BindOnce(&AccessibilityTestHandler::DisableAccessibility,
+                           this, browser),
             200);
       } break;
       // Delayed task will posted later after we have initial details
@@ -132,17 +132,18 @@
 
           // Ignore other events.
           if (!event.get() ||
-              event->GetString("event_type") != "layoutComplete") {
+              event->GetString("event_type") != "loadComplete") {
             break;
           }
 
           SetEditBoxIdAndRect(update);
           EXPECT_NE(edit_box_id_, -1);
           // Post a delayed task to hide the span and trigger location change
-          CefPostDelayedTask(TID_UI,
-                             base::Bind(&AccessibilityTestHandler::HideEditBox,
-                                        this, GetBrowser()),
-                             200);
+          CefPostDelayedTask(
+              TID_UI,
+              base::BindOnce(&AccessibilityTestHandler::HideEditBox, this,
+                             GetBrowser()),
+              200);
         }
       } break;
       case TEST_FOCUS_CHANGE: {
@@ -154,7 +155,7 @@
 
           // Ignore other events.
           if (!event.get() ||
-              event->GetString("event_type") != "layoutComplete") {
+              event->GetString("event_type") != "loadComplete") {
             break;
           }
 
@@ -164,14 +165,15 @@
 
           CefPostDelayedTask(
               TID_UI,
-              base::Bind(&AccessibilityTestHandler::SetFocusOnEditBox, this,
-                         GetBrowser()),
+              base::BindOnce(&AccessibilityTestHandler::SetFocusOnEditBox, this,
+                             GetBrowser()),
               200);
         } else {
           // Retrieve the "focus" event.
           CefRefPtr<CefDictionaryValue> event;
-          if (!GetFirstMatchingEvent(value, "focus", event))
+          if (!GetFirstMatchingEvent(value, "focus", event)) {
             return;
+          }
           EXPECT_TRUE(event.get());
 
           // Verify that focus is set to expected element edit_box.
@@ -180,7 +182,8 @@
           // Now Post a delayed task to destroy the test giving
           // sufficient time for any accessibility updates to come through
           CefPostDelayedTask(
-              TID_UI, base::Bind(&AccessibilityTestHandler::DestroyTest, this),
+              TID_UI,
+              base::BindOnce(&AccessibilityTestHandler::DestroyTest, this),
               500);
         }
       } break;
@@ -203,7 +206,7 @@
     if (got_hide_edit_box_) {
       // Now destroy the test.
       CefPostTask(TID_UI,
-                  base::Bind(&AccessibilityTestHandler::DestroyTest, this));
+                  base::BindOnce(&AccessibilityTestHandler::DestroyTest, this));
     }
   }
 
@@ -214,7 +217,7 @@
 
 #if defined(OS_WIN)
     windowInfo.SetAsWindowless(GetDesktopWindow());
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
     windowInfo.SetAsWindowless(kNullWindowHandle);
 #elif defined(OS_LINUX)
     windowInfo.SetAsWindowless(kNullWindowHandle);
@@ -251,7 +254,8 @@
     // Now Post a delayed task to destroy the test
     // giving sufficient time for any accessibility updates to come through
     CefPostDelayedTask(
-        TID_UI, base::Bind(&AccessibilityTestHandler::DestroyTest, this), 500);
+        TID_UI, base::BindOnce(&AccessibilityTestHandler::DestroyTest, this),
+        500);
   }
 
   static CefRefPtr<CefListValue> GetUpdateList(CefRefPtr<CefValue> value) {
@@ -265,16 +269,18 @@
 
   static size_t GetUpdateListSize(CefRefPtr<CefValue> value) {
     CefRefPtr<CefListValue> updates = GetUpdateList(value);
-    if (updates)
+    if (updates) {
       return updates->GetSize();
+    }
     return 0U;
   }
 
   static CefRefPtr<CefDictionaryValue> GetUpdateValue(CefRefPtr<CefValue> value,
                                                       size_t index) {
     CefRefPtr<CefListValue> updates = GetUpdateList(value);
-    if (!updates)
+    if (!updates) {
       return nullptr;
+    }
     EXPECT_LT(index, updates->GetSize());
     CefRefPtr<CefDictionaryValue> update = updates->GetDictionary(index);
     EXPECT_TRUE(update);
@@ -292,16 +298,18 @@
 
   static size_t GetEventListSize(CefRefPtr<CefValue> value) {
     CefRefPtr<CefListValue> events = GetEventList(value);
-    if (events)
+    if (events) {
       return events->GetSize();
+    }
     return 0U;
   }
 
   static CefRefPtr<CefDictionaryValue> GetEventValue(CefRefPtr<CefValue> value,
                                                      size_t index) {
     CefRefPtr<CefListValue> events = GetEventList(value);
-    if (!events)
+    if (!events) {
       return nullptr;
+    }
     EXPECT_LT(index, events->GetSize());
     CefRefPtr<CefDictionaryValue> event = events->GetDictionary(index);
     EXPECT_TRUE(event);
@@ -311,10 +319,12 @@
   static void GetFirstUpdateAndEvent(CefRefPtr<CefValue> value,
                                      CefRefPtr<CefDictionaryValue>& update,
                                      CefRefPtr<CefDictionaryValue>& event) {
-    if (GetUpdateListSize(value) > 0U)
+    if (GetUpdateListSize(value) > 0U) {
       update = GetUpdateValue(value, 0U);
-    if (GetEventListSize(value) > 0U)
+    }
+    if (GetEventListSize(value) > 0U) {
       event = GetEventValue(value, 0U);
+    }
   }
 
   static bool GetFirstMatchingEvent(CefRefPtr<CefValue> value,
@@ -339,7 +349,7 @@
     EXPECT_TRUE(update.get());
 
     // Ignore other events.
-    if (!event.get() || event->GetString("event_type") != "layoutComplete") {
+    if (!event.get() || event->GetString("event_type") != "loadComplete") {
       return;
     }
 
@@ -373,63 +383,11 @@
     EXPECT_TRUE(childIDs.get());
     EXPECT_EQ(1U, childIDs->GetSize());
 
-    // A parent Group div containing the child.
-    CefRefPtr<CefDictionaryValue> group;
-    for (size_t index = 0; index < nodes->GetSize(); index++) {
-      CefRefPtr<CefDictionaryValue> node = nodes->GetDictionary(index);
-      if (node->GetString("role").ToString() == "genericContainer") {
-        group = node;
-        break;
-      }
-    }
-    EXPECT_TRUE(group.get());
-    // Validate Group is child of root WebArea.
-    EXPECT_EQ(group->GetInt("id"), childIDs->GetInt(0));
-
-    CefRefPtr<CefListValue> parentdiv = group->GetList("child_ids");
-    EXPECT_TRUE(parentdiv.get());
-    EXPECT_EQ(3U, parentdiv->GetSize());
-
-    int tipId = parentdiv->GetInt(0);
-    int editBoxId = parentdiv->GetInt(1);
-    int buttonId = parentdiv->GetInt(2);
-
-    // A parent Group div containing the child.
-    CefRefPtr<CefDictionaryValue> tip, editbox, button;
-    for (size_t index = 0; index < nodes->GetSize(); index++) {
-      CefRefPtr<CefDictionaryValue> node = nodes->GetDictionary(index);
-      if (node->GetInt("id") == tipId) {
-        tip = node;
-      }
-      if (node->GetInt("id") == editBoxId) {
-        editbox = node;
-      }
-      if (node->GetInt("id") == buttonId) {
-        button = node;
-      }
-    }
-    EXPECT_TRUE(tip.get());
-    EXPECT_STREQ("tooltip", tip->GetString("role").ToString().c_str());
-    CefRefPtr<CefDictionaryValue> tipattr = tip->GetDictionary("attributes");
-    EXPECT_TRUE(tipattr.get());
-
-    EXPECT_TRUE(editbox.get());
-    EXPECT_STREQ("textField", editbox->GetString("role").ToString().c_str());
-    CefRefPtr<CefDictionaryValue> editattr =
-        editbox->GetDictionary("attributes");
-    // Validate ARIA Description tags for tipIdare associated with editbox.
-    EXPECT_TRUE(editattr.get());
-    EXPECT_EQ(tipId, editattr->GetList("describedbyIds")->GetInt(0));
-    EXPECT_STREQ(kTipText,
-                 editattr->GetString("description").ToString().c_str());
-
-    EXPECT_TRUE(button.get());
-    EXPECT_STREQ("button", button->GetString("role").ToString().c_str());
-
     // Now Post a delayed task to destroy the test
     // giving sufficient time for any accessibility updates to come through
     CefPostDelayedTask(
-        TID_UI, base::Bind(&AccessibilityTestHandler::DestroyTest, this), 500);
+        TID_UI, base::BindOnce(&AccessibilityTestHandler::DestroyTest, this),
+        500);
   }
 
   // Find Edit box Id in accessibility tree.
diff --git a/src/tests/ceftests/osr_display_unittest.cc b/src/tests/ceftests/osr_display_unittest.cc
index 0855726..3648b44 100644
--- a/src/tests/ceftests/osr_display_unittest.cc
+++ b/src/tests/ceftests/osr_display_unittest.cc
@@ -2,7 +2,7 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/wrapper/cef_closure_task.h"
 
 #include "tests/ceftests/routing_test_handler.h"
@@ -44,12 +44,14 @@
     if (!got_paint_[status_]) {
       got_paint_[status_].yes();
 
-      if (status_ == START)
+      if (status_ == START) {
         OnStartIfDone();
-      else if (status_ == SHOW)
-        CefPostTask(TID_UI, base::Bind(&DisplayTestHandler::DestroyTest, this));
-      else
-        EXPECT_FALSE(true);  // Not reached.
+      } else if (status_ == SHOW) {
+        CefPostTask(TID_UI,
+                    base::BindOnce(&DisplayTestHandler::DestroyTest, this));
+      } else {
+        ADD_FAILURE();
+      }
     }
   }
 
@@ -67,7 +69,7 @@
 
   bool OnQuery(CefRefPtr<CefBrowser> browser,
                CefRefPtr<CefFrame> frame,
-               int64 query_id,
+               int64_t query_id,
                const CefString& request,
                bool persistent,
                CefRefPtr<Callback> callback) override {
@@ -81,7 +83,7 @@
         got_navigate_msg_.yes();
         // Wait a bit to verify no OnPaint callback.
         CefPostDelayedTask(
-            TID_UI, base::Bind(&DisplayTestHandler::OnNavigate, this), 250);
+            TID_UI, base::BindOnce(&DisplayTestHandler::OnNavigate, this), 250);
       }
     }
     callback->Success("");
@@ -123,8 +125,9 @@
   }
 
   void OnStartIfDone() {
-    if (got_start_msg_ && got_paint_[START])
-      CefPostTask(TID_UI, base::Bind(&DisplayTestHandler::OnStart, this));
+    if (got_start_msg_ && got_paint_[START]) {
+      CefPostTask(TID_UI, base::BindOnce(&DisplayTestHandler::OnStart, this));
+    }
   }
 
   void OnStart() {
@@ -252,14 +255,16 @@
                             bool isLoading,
                             bool canGoBack,
                             bool canGoForward) override {
-    if (isLoading)
+    if (isLoading) {
       return;
+    }
 
     if (browser->IsPopup()) {
       got_load_end_popup_.yes();
       CefPostDelayedTask(
           TID_UI,
-          base::Bind(&OsrPopupJSOtherClientTestHandler::Close, this, browser),
+          base::BindOnce(&OsrPopupJSOtherClientTestHandler::Close, this,
+                         browser),
           100);
     } else {
       browser->GetMainFrame()->LoadURL("javascript:window.open('about:blank')");
@@ -312,7 +317,7 @@
                                  public CefLifeSpanHandler,
                                  public CefRenderHandler {
  public:
-  OsrPopupJSOtherCefClient() { handler_ = NULL; }
+  OsrPopupJSOtherCefClient() { handler_ = nullptr; }
 
   void SetHandler(CefRefPtr<OsrPopupJSOtherClientTestHandler> handler) {
     handler_ = handler;
diff --git a/src/tests/ceftests/parser_unittest.cc b/src/tests/ceftests/parser_unittest.cc
index cc5e6be..28c5cbc 100644
--- a/src/tests/ceftests/parser_unittest.cc
+++ b/src/tests/ceftests/parser_unittest.cc
@@ -264,6 +264,18 @@
   EXPECT_STREQ("ref", ref.ToString().c_str());
 }
 
+// Combine and parse an absolute and relative URL.
+TEST(ParserTest, ParseAbsoluteAndRelativeURL) {
+  CefString base_url;
+  base_url.FromASCII("https://www.example.com");
+  CefString relative_url;
+  relative_url.FromASCII("/example");
+  CefString resolved_url;
+  EXPECT_TRUE(CefResolveURL(base_url, relative_url, resolved_url));
+  EXPECT_STREQ("https://www.example.com/example",
+               resolved_url.ToString().c_str());
+}
+
 TEST(ParserTest, FormatUrlForSecurityDisplay) {
   CefString result;
 
@@ -464,25 +476,21 @@
 
 TEST(ParserTest, ParseJSONAndReturnErrorInvalid) {
   const char data[] = "This is my test data";
-  cef_json_parser_error_t error_code;
   CefString error_msg;
   CefRefPtr<CefValue> value =
-      CefParseJSONAndReturnError(data, JSON_PARSER_RFC, error_code, error_msg);
+      CefParseJSONAndReturnError(data, JSON_PARSER_RFC, error_msg);
   CefString expect_error_msg = "Line: 1, column: 1, Unexpected token.";
   EXPECT_FALSE(value.get());
-  EXPECT_EQ(JSON_UNEXPECTED_TOKEN, error_code);
   EXPECT_EQ(expect_error_msg, error_msg);
 }
 
 TEST(ParserTest, ParseJSONAndReturnErrorTrailingComma) {
   const char data[] = "{\"key1\":123,}";
-  cef_json_parser_error_t error_code;
   CefString error_msg;
   CefRefPtr<CefValue> value =
-      CefParseJSONAndReturnError(data, JSON_PARSER_RFC, error_code, error_msg);
+      CefParseJSONAndReturnError(data, JSON_PARSER_RFC, error_msg);
   CefString expect_error_msg =
       "Line: 1, column: 13, Trailing comma not allowed.";
   EXPECT_FALSE(value.get());
-  EXPECT_EQ(JSON_TRAILING_COMMA, error_code);
   EXPECT_EQ(expect_error_msg, error_msg);
 }
diff --git a/src/tests/ceftests/pdf_viewer_unittest.cc b/src/tests/ceftests/pdf_viewer_unittest.cc
new file mode 100644
index 0000000..f8cd605
--- /dev/null
+++ b/src/tests/ceftests/pdf_viewer_unittest.cc
@@ -0,0 +1,233 @@
+// Copyright (c) 2015 The Chromium Embedded Framework 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 "include/base/cef_callback.h"
+#include "include/cef_pack_resources.h"
+#include "include/cef_request_context_handler.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "include/wrapper/cef_stream_resource_handler.h"
+#include "tests/ceftests/test_handler.h"
+#include "tests/ceftests/test_util.h"
+#include "tests/gtest/include/gtest/gtest.h"
+#include "tests/shared/browser/client_app_browser.h"
+#include "tests/shared/browser/resource_util.h"
+
+namespace {
+
+const char kPdfHtmlUrl[] = "https://tests/pdf.html";
+const char kPdfDirectUrl[] = "https://tests/pdf.pdf";
+
+// Delay waiting for iframe tests to load the PDF file.
+#if defined(OS_LINUX)
+const int64_t kPdfLoadDelayMs = 7000;
+#else
+const int64_t kPdfLoadDelayMs = 5000;
+#endif
+
+// Browser-side test handler.
+class PdfViewerTestHandler : public TestHandler, public CefContextMenuHandler {
+ public:
+  enum Mode {
+    // No specified context or handler (implicitly uses the global context).
+    GLOBAL_DEFAULT,
+
+    // Global context with no handler.
+    GLOBAL_NO_HANDLER,
+
+    // Custom context with no handler.
+    CUSTOM_NO_HANDLER,
+  };
+
+  PdfViewerTestHandler(Mode mode, const std::string& url)
+      : mode_(mode), url_(url) {}
+
+  // Loading the PDF directly in the main frame instead of a sub-frame.
+  bool HasDirectPdfLoad() const { return url_ == kPdfDirectUrl; }
+
+  CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() override {
+    return this;
+  }
+
+  void RunTest() override {
+    CefRefPtr<CefRequestContext> request_context;
+
+    if (mode_ == GLOBAL_NO_HANDLER) {
+      // Use the global request context.
+      request_context = CefRequestContext::CreateContext(
+          CefRequestContext::GetGlobalContext(), nullptr);
+    } else if (mode_ == CUSTOM_NO_HANDLER) {
+      // Create the request context that will use an in-memory cache.
+      CefRequestContextSettings settings;
+      request_context = CefRequestContext::CreateContext(settings, nullptr);
+    }
+
+    // Create the browser.
+    CreateBrowser(url_, request_context);
+
+    // Time out the test after a reasonable period of time.
+    SetTestTimeout(5000 + kPdfLoadDelayMs);
+  }
+
+  CefRefPtr<CefResourceHandler> GetResourceHandler(
+      CefRefPtr<CefBrowser> browser,
+      CefRefPtr<CefFrame> frame,
+      CefRefPtr<CefRequest> request) override {
+    const std::string& url = request->GetURL();
+    if (url == kPdfHtmlUrl) {
+      CefRefPtr<CefStreamReader> stream =
+          client::GetBinaryResourceReader("pdf.html");
+      return new CefStreamResourceHandler("text/html", stream);
+    } else if (url == kPdfDirectUrl) {
+      CefRefPtr<CefStreamReader> stream =
+          client::GetBinaryResourceReader("pdf.pdf");
+      return new CefStreamResourceHandler("application/pdf", stream);
+    }
+
+    return nullptr;
+  }
+
+  void OnLoadEnd(CefRefPtr<CefBrowser> browser,
+                 CefRefPtr<CefFrame> frame,
+                 int httpStatusCode) override {
+    bool is_pdf1 = false;
+    const std::string& url = frame->GetURL();
+    if (url == "about:blank") {
+      return;
+    }
+
+    if (url == kPdfHtmlUrl) {
+      if (!got_on_load_end_html_) {
+        got_on_load_end_html_.yes();
+      } else {
+        NOTREACHED();
+      }
+    } else if (url == kPdfDirectUrl) {
+      if (!got_on_load_end_pdf1_) {
+        got_on_load_end_pdf1_.yes();
+        is_pdf1 = true;
+      } else if (!got_on_load_end_pdf2_) {
+        got_on_load_end_pdf2_.yes();
+      } else {
+        NOTREACHED();
+      }
+    } else {
+      NOTREACHED() << "url=" << url;
+    }
+
+    if (is_pdf1) {
+      // The first PDF document has loaded.
+      // TODO(chrome): Add support for custom context menus.
+      if (IsChromeRuntimeEnabled() || got_context_menu_dismissed_) {
+        // After context menu display. Destroy the test.
+        CefPostDelayedTask(
+            TID_UI, base::BindOnce(&PdfViewerTestHandler::DestroyTest, this),
+            kPdfLoadDelayMs);
+      } else {
+        // Trigger the context menu.
+        CefPostDelayedTask(
+            TID_UI,
+            base::BindOnce(&PdfViewerTestHandler::TriggerContextMenu, this,
+                           frame->GetBrowser()),
+            kPdfLoadDelayMs);
+      }
+    }
+  }
+
+  void TriggerContextMenu(CefRefPtr<CefBrowser> browser) {
+    CefMouseEvent mouse_event;
+
+    if (HasDirectPdfLoad()) {
+      // Somewhere in the main PDF viewing area (avoid left preview bar).
+      mouse_event.x = 400;
+      mouse_event.y = 200;
+    } else {
+      // Somewhere in the first PDF viewing area.
+      mouse_event.x = 100;
+      mouse_event.y = 100;
+    }
+
+    // Send right-click mouse down and mouse up to tigger context menu.
+    SendMouseClickEvent(browser, mouse_event, MBT_RIGHT);
+  }
+
+  bool RunContextMenu(CefRefPtr<CefBrowser> browser,
+                      CefRefPtr<CefFrame> frame,
+                      CefRefPtr<CefContextMenuParams> params,
+                      CefRefPtr<CefMenuModel> model,
+                      CefRefPtr<CefRunContextMenuCallback> callback) override {
+    EXPECT_FALSE(got_run_context_menu_);
+    got_run_context_menu_.yes();
+
+    // Do nothing with the context menu.
+    callback->Cancel();
+
+    return true;
+  }
+
+  void OnContextMenuDismissed(CefRefPtr<CefBrowser> browser,
+                              CefRefPtr<CefFrame> frame) override {
+    EXPECT_FALSE(got_context_menu_dismissed_);
+    got_context_menu_dismissed_.yes();
+
+    CefPostTask(TID_UI,
+                base::BindOnce(&PdfViewerTestHandler::DestroyTest, this));
+  }
+
+  void DestroyTest() override {
+    // TODO(chrome): Add support for custom context menus.
+    if (!IsChromeRuntimeEnabled()) {
+      EXPECT_TRUE(got_run_context_menu_);
+      EXPECT_TRUE(got_context_menu_dismissed_);
+    } else {
+      EXPECT_FALSE(got_run_context_menu_);
+      EXPECT_FALSE(got_context_menu_dismissed_);
+    }
+
+    if (url_ == kPdfHtmlUrl) {
+      // The HTML file will load the PDF twice in iframes.
+      EXPECT_TRUE(got_on_load_end_html_);
+      EXPECT_TRUE(got_on_load_end_pdf1_);
+      EXPECT_TRUE(got_on_load_end_pdf2_);
+    } else if (url_ == kPdfDirectUrl) {
+      // Load the PDF file directly.
+      EXPECT_FALSE(got_on_load_end_html_);
+      EXPECT_TRUE(got_on_load_end_pdf1_);
+      EXPECT_FALSE(got_on_load_end_pdf2_);
+    } else {
+      NOTREACHED();
+    }
+
+    TestHandler::DestroyTest();
+  }
+
+  const Mode mode_;
+  const std::string url_;
+
+  TrackCallback got_on_load_end_html_;
+  TrackCallback got_on_load_end_pdf1_;
+  TrackCallback got_on_load_end_pdf2_;
+  TrackCallback got_run_context_menu_;
+  TrackCallback got_context_menu_dismissed_;
+
+  IMPLEMENT_REFCOUNTING(PdfViewerTestHandler);
+};
+
+}  // namespace
+
+#define RUN_TEST(name, type, url)                                  \
+  TEST(PdfViewerTest, name) {                                      \
+    CefRefPtr<PdfViewerTestHandler> handler =                      \
+        new PdfViewerTestHandler(PdfViewerTestHandler::type, url); \
+    handler->ExecuteTest();                                        \
+    ReleaseAndWaitForDestructor(handler);                          \
+  }
+
+RUN_TEST(GlobalDefaultPdfDirect, GLOBAL_DEFAULT, kPdfDirectUrl)
+RUN_TEST(GlobalDefaultPdfHtml, GLOBAL_DEFAULT, kPdfHtmlUrl)
+
+RUN_TEST(GlobalNoHandlerPdfDirect, GLOBAL_NO_HANDLER, kPdfDirectUrl)
+RUN_TEST(GlobalNoHandlerPdfHtml, GLOBAL_NO_HANDLER, kPdfHtmlUrl)
+
+RUN_TEST(CustomNoHandlerPdfDirect, CUSTOM_NO_HANDLER, kPdfDirectUrl)
+RUN_TEST(CustomNoHandlerPdfHtml, CUSTOM_NO_HANDLER, kPdfHtmlUrl)
diff --git a/src/tests/ceftests/permission_prompt_unittest.cc b/src/tests/ceftests/permission_prompt_unittest.cc
new file mode 100644
index 0000000..3a1374b
--- /dev/null
+++ b/src/tests/ceftests/permission_prompt_unittest.cc
@@ -0,0 +1,486 @@
+// Copyright 2022 The Chromium Embedded Framework Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be found
+// in the LICENSE file.
+
+#include <string>
+#include <vector>
+
+#include "include/base/cef_callback.h"
+#include "include/cef_parser.h"
+#include "include/cef_permission_handler.h"
+#include "include/cef_request_context_handler.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "include/wrapper/cef_stream_resource_handler.h"
+#include "tests/ceftests/test_handler.h"
+#include "tests/ceftests/test_suite.h"
+#include "tests/ceftests/test_util.h"
+#include "tests/gtest/include/gtest/gtest.h"
+#include "tests/shared/browser/client_app_browser.h"
+
+namespace {
+
+// Most permissions require HTTPS.
+constexpr char kPromptUrl[] = "https://permission-prompt-test/prompt.html";
+constexpr char kPromptOrigin[] = "https://permission-prompt-test/";
+
+constexpr char kPromptNavUrl[] = "https://permission-prompt-test/nav.html";
+
+class TestSetup {
+ public:
+  TestSetup() {}
+
+  // CONFIGURATION
+
+  // Deny the prompt by returning false in OnShowPermissionPrompt.
+  bool deny_implicitly = false;
+
+  // Deny the prompt (implicitly) by not triggering it via a user gesture to
+  // begin with.
+  bool deny_no_gesture = false;
+
+  // Deny the prompt by returning true in OnShowPermissionPrompt but then never
+  // calling CefPermissionPromptCallback::Continue.
+  bool deny_with_navigation = false;
+
+  // Don't synchronously execute the callback in OnShowPermissionPrompt.
+  bool continue_async = false;
+
+  // RESULTS
+
+  // Method callbacks.
+  TrackCallback got_prompt;
+  TrackCallback got_dismiss;
+
+  // JS success state.
+  TrackCallback got_js_success;
+  TrackCallback got_js_success_data;
+
+  // JS error state.
+  TrackCallback got_js_error;
+  std::string js_error_str;
+
+  // JS timeout state.
+  TrackCallback got_js_timeout;
+};
+
+class PermissionPromptTestHandler : public TestHandler,
+                                    public CefPermissionHandler {
+ public:
+  PermissionPromptTestHandler(TestSetup* tr,
+                              uint32_t request,
+                              cef_permission_request_result_t result)
+      : test_setup_(tr), request_(request), result_(result) {}
+
+  cef_return_value_t OnBeforeResourceLoad(
+      CefRefPtr<CefBrowser> browser,
+      CefRefPtr<CefFrame> frame,
+      CefRefPtr<CefRequest> request,
+      CefRefPtr<CefCallback> callback) override {
+    std::string newUrl = request->GetURL();
+    if (newUrl.find("tests/exit") != std::string::npos) {
+      if (newUrl.find("SUCCESS") != std::string::npos) {
+        EXPECT_FALSE(test_setup_->got_js_success);
+        test_setup_->got_js_success.yes();
+
+        auto dict = ParseURLData(newUrl);
+        if (dict->GetBool("got_data")) {
+          test_setup_->got_js_success_data.yes();
+        }
+      } else if (newUrl.find("ERROR") != std::string::npos) {
+        EXPECT_FALSE(test_setup_->got_js_error);
+        test_setup_->got_js_error.yes();
+
+        auto dict = ParseURLData(newUrl);
+        test_setup_->js_error_str = dict->GetString("error_str");
+      } else if (newUrl.find("TIMEOUT") != std::string::npos) {
+        EXPECT_FALSE(test_setup_->got_js_timeout);
+        test_setup_->got_js_timeout.yes();
+      }
+
+      DestroyTest();
+      return RV_CANCEL;
+    }
+
+    return RV_CONTINUE;
+  }
+
+  void RunTest() override {
+    std::string page =
+        "<html><head>"
+        "<script>"
+        "function onResult(val, data) {"
+        " if(!data) {"
+        "   data = {};"
+        " }"
+        " document.location = "
+        "`https://tests/"
+        "exit?result=${val}&data=${encodeURIComponent(JSON.stringify(data))}`;"
+        "}"
+        "function makeRequest() {";
+
+    if (request_ == CEF_PERMISSION_TYPE_WINDOW_MANAGEMENT) {
+      page +=
+          "  window.getScreenDetails().then(function(details) {"
+          "    onResult(`SUCCESS`, {got_data: details.screens.length > 0});"
+          "  })";
+    }
+
+    page +=
+        "  .catch(function(err) {"
+        "    console.log(err.toString());"
+        "    onResult(`ERROR`, {error_str: err.toString()});"
+        "  });";
+
+    if (test_setup_->deny_implicitly) {
+      // Implicit IGNORE result means the promise will never resolve, so add a
+      // timeout.
+      page += "  setTimeout(() => { onResult(`TIMEOUT`); }, 1000);";
+    } else if (test_setup_->deny_with_navigation) {
+      // Cancel the pending permission request by navigating.
+      page += "  setTimeout(() => { document.location = '" +
+              std::string(kPromptNavUrl) + "'; }, 1000);";
+    }
+
+    page +=
+        "}"
+        "</script>"
+        "</head><body>";
+
+    if (test_setup_->deny_no_gesture) {
+      // Expect this request to be blocked. See comments on OnLoadEnd.
+      page += "<script>makeRequest();</script>";
+    } else {
+      page += "<a href='#' onclick='makeRequest(); return false;'>CLICK ME</a>";
+    }
+
+    page += "</body></html>";
+
+    // Create the request context that will use an in-memory cache.
+    CefRequestContextSettings settings;
+    CefRefPtr<CefRequestContext> request_context =
+        CefRequestContext::CreateContext(settings, nullptr);
+
+    AddResource(kPromptUrl, page, "text/html");
+
+    if (test_setup_->deny_with_navigation) {
+      AddResource(kPromptNavUrl, "<html><body>Navigated</body></html>",
+                  "text/html");
+    }
+
+    // Create the browser.
+    CreateBrowser(kPromptUrl, request_context);
+
+    // Time out the test after a reasonable period of time.
+    SetTestTimeout();
+  }
+
+  CefRefPtr<CefPermissionHandler> GetPermissionHandler() override {
+    return this;
+  }
+
+  void OnLoadEnd(CefRefPtr<CefBrowser> browser,
+                 CefRefPtr<CefFrame> frame,
+                 int httpStatusCode) override {
+    if (test_setup_->deny_no_gesture) {
+      return;
+    }
+
+    if (test_setup_->deny_with_navigation) {
+      if (frame->GetURL().ToString() == kPromptNavUrl) {
+        DestroyTest();
+        return;
+      }
+    }
+
+    // Begin the permissions request by clicking a link. This is necessary
+    // because some prompts may be blocked without a transient user activation
+    // (HasTransientUserActivation returning true in Chromium).
+    SendClick(browser);
+  }
+
+  bool OnShowPermissionPrompt(
+      CefRefPtr<CefBrowser> browser,
+      uint64_t prompt_id,
+      const CefString& requesting_origin,
+      uint32_t requested_permissions,
+      CefRefPtr<CefPermissionPromptCallback> callback) override {
+    EXPECT_UI_THREAD();
+
+    prompt_id_ = prompt_id;
+    EXPECT_GT(prompt_id, 0U);
+
+    EXPECT_EQ(request_, requested_permissions);
+    EXPECT_STREQ(kPromptOrigin, requesting_origin.ToString().c_str());
+
+    EXPECT_FALSE(test_setup_->got_prompt);
+    test_setup_->got_prompt.yes();
+
+    if (test_setup_->deny_implicitly) {
+      // Causes implicit IGNORE result for the permission request.
+      return false;
+    }
+
+    if (test_setup_->deny_with_navigation) {
+      // Handle the permission request, but never execute the callback.
+      return true;
+    }
+
+    if (test_setup_->continue_async) {
+      CefPostTask(TID_UI, base::BindOnce(&CefPermissionPromptCallback::Continue,
+                                         callback, result_));
+    } else {
+      callback->Continue(result_);
+    }
+    return true;
+  }
+
+  void OnDismissPermissionPrompt(
+      CefRefPtr<CefBrowser> browser,
+      uint64_t prompt_id,
+      cef_permission_request_result_t result) override {
+    EXPECT_UI_THREAD();
+    EXPECT_EQ(prompt_id_, prompt_id);
+    EXPECT_EQ(result_, result);
+    EXPECT_FALSE(test_setup_->got_dismiss);
+    test_setup_->got_dismiss.yes();
+  }
+
+  void DestroyTest() override {
+    const size_t js_outcome_ct = test_setup_->got_js_success +
+                                 test_setup_->got_js_error +
+                                 test_setup_->got_js_timeout;
+    if (test_setup_->deny_with_navigation) {
+      // Expect no JS outcome.
+      EXPECT_EQ(0U, js_outcome_ct);
+    } else {
+      // Expect a single JS outcome.
+      EXPECT_EQ(1U, js_outcome_ct);
+    }
+
+    TestHandler::DestroyTest();
+  }
+
+ private:
+  void SendClick(CefRefPtr<CefBrowser> browser) {
+    CefMouseEvent mouse_event;
+    mouse_event.x = 20;
+    mouse_event.y = 20;
+    SendMouseClickEvent(browser, mouse_event);
+  }
+
+  CefRefPtr<CefDictionaryValue> ParseURLData(const std::string& url) {
+    const std::string& find_str = "&data=";
+    const std::string& data_string =
+        url.substr(url.find(find_str) + std::string(find_str).length());
+    const std::string& data_string_decoded = CefURIDecode(
+        data_string, false,
+        static_cast<cef_uri_unescape_rule_t>(
+            UU_SPACES | UU_URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS));
+    auto obj =
+        CefParseJSON(data_string_decoded, JSON_PARSER_ALLOW_TRAILING_COMMAS);
+    return obj->GetDictionary();
+  }
+
+  TestSetup* const test_setup_;
+  const uint32_t request_;
+  const cef_permission_request_result_t result_;
+  uint64_t prompt_id_ = 0U;
+
+  IMPLEMENT_REFCOUNTING(PermissionPromptTestHandler);
+};
+
+}  // namespace
+
+// Window placement permission requests.
+TEST(PermissionPromptTest, WindowManagementReturningFalse) {
+  TestSetup test_setup;
+  test_setup.deny_implicitly = true;
+
+  CefRefPtr<PermissionPromptTestHandler> handler =
+      new PermissionPromptTestHandler(&test_setup,
+                                      CEF_PERMISSION_TYPE_WINDOW_MANAGEMENT,
+                                      CEF_PERMISSION_RESULT_IGNORE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  // No OnDismissPermissionPrompt callback for default handling.
+  EXPECT_TRUE(test_setup.got_prompt);
+  EXPECT_TRUE(test_setup.got_js_timeout);
+  EXPECT_FALSE(test_setup.got_dismiss);
+}
+
+TEST(PermissionPromptTest, WindowManagementNoGesture) {
+  TestSetup test_setup;
+  test_setup.deny_no_gesture = true;
+
+  CefRefPtr<PermissionPromptTestHandler> handler =
+      new PermissionPromptTestHandler(&test_setup,
+                                      CEF_PERMISSION_TYPE_WINDOW_MANAGEMENT,
+                                      CEF_PERMISSION_RESULT_IGNORE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  // No OnShowPermissionPrompt or OnDismissPermissionPrompt callbacks for
+  // prompts that are blocked.
+  EXPECT_FALSE(test_setup.got_prompt);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ(
+      "NotAllowedError: Transient activation is required to request "
+      "permission.",
+      test_setup.js_error_str.c_str());
+  EXPECT_FALSE(test_setup.got_dismiss);
+}
+
+TEST(PermissionPromptTest, WindowManagementNoContinue) {
+  TestSetup test_setup;
+  test_setup.deny_with_navigation = true;
+
+  CefRefPtr<PermissionPromptTestHandler> handler =
+      new PermissionPromptTestHandler(&test_setup,
+                                      CEF_PERMISSION_TYPE_WINDOW_MANAGEMENT,
+                                      CEF_PERMISSION_RESULT_IGNORE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  // Callbacks but no JS result.
+  EXPECT_TRUE(test_setup.got_prompt);
+  EXPECT_TRUE(test_setup.got_dismiss);
+}
+
+TEST(PermissionPromptTest, WindowManagementResultAccept) {
+  TestSetup test_setup;
+
+  CefRefPtr<PermissionPromptTestHandler> handler =
+      new PermissionPromptTestHandler(&test_setup,
+                                      CEF_PERMISSION_TYPE_WINDOW_MANAGEMENT,
+                                      CEF_PERMISSION_RESULT_ACCEPT);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_prompt);
+  EXPECT_TRUE(test_setup.got_js_success);
+  EXPECT_TRUE(test_setup.got_js_success_data);
+  EXPECT_TRUE(test_setup.got_dismiss);
+}
+
+TEST(PermissionPromptTest, WindowManagementResultAcceptAsync) {
+  TestSetup test_setup;
+  test_setup.continue_async = true;
+
+  CefRefPtr<PermissionPromptTestHandler> handler =
+      new PermissionPromptTestHandler(&test_setup,
+                                      CEF_PERMISSION_TYPE_WINDOW_MANAGEMENT,
+                                      CEF_PERMISSION_RESULT_ACCEPT);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_prompt);
+  EXPECT_TRUE(test_setup.got_js_success);
+  EXPECT_TRUE(test_setup.got_js_success_data);
+  EXPECT_TRUE(test_setup.got_dismiss);
+}
+
+TEST(PermissionPromptTest, WindowManagementResultDeny) {
+  TestSetup test_setup;
+
+  CefRefPtr<PermissionPromptTestHandler> handler =
+      new PermissionPromptTestHandler(&test_setup,
+                                      CEF_PERMISSION_TYPE_WINDOW_MANAGEMENT,
+                                      CEF_PERMISSION_RESULT_DENY);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_prompt);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Permission denied.",
+               test_setup.js_error_str.c_str());
+  EXPECT_TRUE(test_setup.got_dismiss);
+}
+
+TEST(PermissionPromptTest, WindowManagementResultDenyAsync) {
+  TestSetup test_setup;
+  test_setup.continue_async = true;
+
+  CefRefPtr<PermissionPromptTestHandler> handler =
+      new PermissionPromptTestHandler(&test_setup,
+                                      CEF_PERMISSION_TYPE_WINDOW_MANAGEMENT,
+                                      CEF_PERMISSION_RESULT_DENY);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_prompt);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Permission denied.",
+               test_setup.js_error_str.c_str());
+  EXPECT_TRUE(test_setup.got_dismiss);
+}
+
+TEST(PermissionPromptTest, WindowManagementResultDismiss) {
+  TestSetup test_setup;
+
+  CefRefPtr<PermissionPromptTestHandler> handler =
+      new PermissionPromptTestHandler(&test_setup,
+                                      CEF_PERMISSION_TYPE_WINDOW_MANAGEMENT,
+                                      CEF_PERMISSION_RESULT_DISMISS);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_prompt);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Permission denied.",
+               test_setup.js_error_str.c_str());
+  EXPECT_TRUE(test_setup.got_dismiss);
+}
+
+TEST(PermissionPromptTest, WindowManagementResultDismissAsync) {
+  TestSetup test_setup;
+  test_setup.continue_async = true;
+
+  CefRefPtr<PermissionPromptTestHandler> handler =
+      new PermissionPromptTestHandler(&test_setup,
+                                      CEF_PERMISSION_TYPE_WINDOW_MANAGEMENT,
+                                      CEF_PERMISSION_RESULT_DISMISS);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_prompt);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Permission denied.",
+               test_setup.js_error_str.c_str());
+  EXPECT_TRUE(test_setup.got_dismiss);
+}
+
+TEST(PermissionPromptTest, WindowManagementResultIgnore) {
+  TestSetup test_setup;
+
+  CefRefPtr<PermissionPromptTestHandler> handler =
+      new PermissionPromptTestHandler(&test_setup,
+                                      CEF_PERMISSION_TYPE_WINDOW_MANAGEMENT,
+                                      CEF_PERMISSION_RESULT_IGNORE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_prompt);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Permission denied.",
+               test_setup.js_error_str.c_str());
+  EXPECT_TRUE(test_setup.got_dismiss);
+}
+
+TEST(PermissionPromptTest, WindowManagementResultIgnoreAsync) {
+  TestSetup test_setup;
+  test_setup.continue_async = true;
+
+  CefRefPtr<PermissionPromptTestHandler> handler =
+      new PermissionPromptTestHandler(&test_setup,
+                                      CEF_PERMISSION_TYPE_WINDOW_MANAGEMENT,
+                                      CEF_PERMISSION_RESULT_IGNORE);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+
+  EXPECT_TRUE(test_setup.got_prompt);
+  EXPECT_TRUE(test_setup.got_js_error);
+  EXPECT_STREQ("NotAllowedError: Permission denied.",
+               test_setup.js_error_str.c_str());
+  EXPECT_TRUE(test_setup.got_dismiss);
+}
diff --git a/src/tests/ceftests/plugin_unittest.cc b/src/tests/ceftests/plugin_unittest.cc
deleted file mode 100644
index a030c52..0000000
--- a/src/tests/ceftests/plugin_unittest.cc
+++ /dev/null
@@ -1,626 +0,0 @@
-// Copyright (c) 2015 The Chromium Embedded Framework 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 "include/base/cef_bind.h"
-#include "include/cef_pack_resources.h"
-#include "include/cef_request_context_handler.h"
-#include "include/wrapper/cef_closure_task.h"
-#include "include/wrapper/cef_stream_resource_handler.h"
-#include "tests/ceftests/routing_test_handler.h"
-#include "tests/gtest/include/gtest/gtest.h"
-#include "tests/shared/browser/client_app_browser.h"
-#include "tests/shared/browser/resource_util.h"
-
-namespace {
-
-// Browser-side app delegate.
-class PluginBrowserTest : public client::ClientAppBrowser::Delegate {
- public:
-  PluginBrowserTest() {}
-
-  void OnBeforeCommandLineProcessing(
-      CefRefPtr<client::ClientAppBrowser> app,
-      CefRefPtr<CefCommandLine> command_line) override {
-    // Allow all plugin loading by default.
-    command_line->AppendSwitchWithValue("plugin-policy", "allow");
-  }
-
- private:
-  IMPLEMENT_REFCOUNTING(PluginBrowserTest);
-};
-
-const char kPdfTestOrigin[] = "http://tests/";
-const char kPdfHtmlUrl[] = "http://tests/pdf.html";
-const char kPdfDirectUrl[] = "http://tests/pdf.pdf";
-
-// Delay waiting for iframe tests to load the PDF file.
-#if defined(OS_LINUX)
-const int64 kPdfLoadDelayMs = 7000;
-#else
-const int64 kPdfLoadDelayMs = 5000;
-#endif
-
-// Browser-side test handler.
-class PluginTestHandler : public RoutingTestHandler,
-                          public CefContextMenuHandler {
- public:
-  enum Mode {
-    // No specified context or handler (implicitly uses the global context).
-    GLOBAL_DEFAULT,
-
-    // Global context with no handler.
-    GLOBAL_NO_HANDLER,
-
-    // Global context with handler that allows plugin load.
-    GLOBAL_ALLOW,
-
-    // Global context with handler that blocks plugin load. Then, load the
-    // plugin via the context menu.
-    GLOBAL_BLOCK_LOAD,
-
-    // Global context with handler that blocks plugin load. Then, hide the
-    // plugin via the context menu.
-    GLOBAL_BLOCK_HIDE,
-
-    // Global context with handler that disables plugin load. Then, hide the
-    // plugin via the context menu.
-    GLOBAL_DISABLE_HIDE,
-
-    // Global context with handler that removes the plugin from the
-    // `navigator.plugins` list and consequently disables plugin load.
-    GLOBAL_NO_LIST,
-
-    // Custom context with no handler.
-    CUSTOM_NO_HANDLER,
-
-    // Custom context with handler that allows plugin load.
-    CUSTOM_ALLOW,
-
-    // Custom context with handler that blocks plugin load. Then, load the
-    // plugin via the context menu.
-    CUSTOM_BLOCK_LOAD,
-
-    // Custom context with handler that blocks plugin load. Then, hide the
-    // plugin via the context menu.
-    CUSTOM_BLOCK_HIDE,
-
-    // Custom context with handler that disables plugin load. Then, hide the
-    // plugin via the context menu.
-    CUSTOM_DISABLE_HIDE,
-
-    // Custom context with handler that removes the plugin from the
-    // `navigator.plugins` list and consequently disables plugin load.
-    CUSTOM_NO_LIST,
-  };
-
-  class RequestContextHandler : public CefRequestContextHandler {
-   public:
-    explicit RequestContextHandler(PluginTestHandler* handler)
-        : handler_(handler) {}
-
-    bool OnBeforePluginLoad(const CefString& mime_type,
-                            const CefString& plugin_url,
-                            bool is_main_frame,
-                            const CefString& top_origin_url,
-                            CefRefPtr<CefWebPluginInfo> plugin_info,
-                            PluginPolicy* plugin_policy) override {
-      const std::string& mime_type_str = mime_type;
-      EXPECT_STREQ("application/pdf", mime_type_str.c_str());
-      EXPECT_STREQ("chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/",
-                   plugin_info->GetPath().ToString().c_str());
-
-      if (top_origin_url.empty()) {
-        if (!handler_->got_on_before_plugin_empty_origin_) {
-          // Checking for PDF support in the plugin frame (navigator.plugins
-          // listing, pdf load, etc).
-          handler_->got_on_before_plugin_empty_origin_.yes();
-        } else if (handler_->HasNoList()) {
-          // When listing is disabled there should be an additional check in the
-          // main frame for the navigator.plugins listing.
-          if (!handler_->got_on_before_plugin_empty_origin2_) {
-            EXPECT_TRUE(is_main_frame);
-            handler_->got_on_before_plugin_empty_origin2_.yes();
-          }
-        }
-
-        if (handler_->HasNoList()) {
-          // Remove the PDF plugin from the `navigator.plugins` list.
-          *plugin_policy = PLUGIN_POLICY_DISABLE;
-          return true;
-        }
-
-        // Ignore requests for building the plugin list.
-        return false;
-      }
-
-      // Should only get requests for the test origin.
-      EXPECT_STREQ(kPdfTestOrigin, top_origin_url.ToString().c_str());
-
-      if (!handler_->got_on_before_plugin_load_pdf_)
-        handler_->got_on_before_plugin_load_pdf_.yes();
-      else
-        NOTREACHED();
-
-      if (handler_->HasAllow()) {
-        *plugin_policy = PLUGIN_POLICY_ALLOW;
-        return true;
-      } else if (handler_->HasBlock()) {
-        *plugin_policy = PLUGIN_POLICY_BLOCK;
-        return true;
-      } else if (handler_->HasDisable()) {
-        *plugin_policy = PLUGIN_POLICY_DISABLE;
-        return true;
-      }
-
-      return false;
-    }
-
-    void Detach() { handler_ = nullptr; }
-
-   private:
-    PluginTestHandler* handler_;
-
-    IMPLEMENT_REFCOUNTING(RequestContextHandler);
-  };
-
-  PluginTestHandler(Mode mode, const std::string& url)
-      : mode_(mode), url_(url) {}
-
-  // Loading the PDF directly in the main frame instead of a sub-frame.
-  bool HasDirectPluginLoad() const { return url_ == kPdfDirectUrl; }
-
-  // Has a specified RequestContext but not necessarily a custom handler.
-  bool HasRequestContext() const { return mode_ != GLOBAL_DEFAULT; }
-
-  // Has a specified RequestContext and custom handler.
-  bool HasRequestContextHandler() const {
-    return mode_ != GLOBAL_DEFAULT && mode_ != GLOBAL_NO_HANDLER &&
-           mode_ != CUSTOM_NO_HANDLER;
-  }
-
-  // Using the global request context, either directly or with a custom handler.
-  bool HasGlobalRequestContext() const {
-    return mode_ >= GLOBAL_DEFAULT && mode_ <= GLOBAL_NO_LIST;
-  }
-
-  // Should allow the plugin load via the custom handler.
-  bool HasAllow() const {
-    return mode_ == GLOBAL_ALLOW || mode_ == CUSTOM_ALLOW;
-  }
-
-  // Should block the plugin load via the custom handler.
-  bool HasBlock() const {
-    return mode_ == GLOBAL_BLOCK_LOAD || mode_ == GLOBAL_BLOCK_HIDE ||
-           mode_ == CUSTOM_BLOCK_LOAD || mode_ == CUSTOM_BLOCK_HIDE;
-  }
-
-  // Should disable the plugin load via the custom handler.
-  bool HasDisable() const {
-    return mode_ == GLOBAL_DISABLE_HIDE || mode_ == CUSTOM_DISABLE_HIDE;
-  }
-
-  // Should exclude the plugin from the `navigator.plugins` list.
-  bool HasNoList() const {
-    return mode_ == GLOBAL_NO_LIST || mode_ == CUSTOM_NO_LIST;
-  }
-
-  // Should load the plugin via the context menu.
-  bool HasContextLoad() const {
-    return mode_ == GLOBAL_BLOCK_LOAD || mode_ == CUSTOM_BLOCK_LOAD;
-  }
-
-  // Should hide the plugin via the context menu.
-  bool HasContextHide() const {
-    return mode_ == GLOBAL_BLOCK_HIDE || mode_ == GLOBAL_DISABLE_HIDE ||
-           mode_ == CUSTOM_BLOCK_HIDE || mode_ == CUSTOM_DISABLE_HIDE;
-  }
-
-  std::string GetPluginNode() const {
-    return "document.getElementsByTagName('embed')[0]";
-  }
-
-  void WaitForNavigatorPlugins(CefRefPtr<CefFrame> frame) const {
-    // Test if the `navigator.plugins` list includes the PDF extension.
-    const std::string& code =
-        " if (navigator.plugins['Chrome PDF Viewer'].filename == "
-        "       'mhjfbmdgcfjbbpaeojofohoefgiehjai') {"
-        "  window.testQuery({request:'pdf_plugin_found'});"
-        "} else {"
-        "  window.testQuery({request:'pdf_plugin_missing'});"
-        "}";
-    frame->ExecuteJavaScript(code, frame->GetURL(), 0);
-  }
-
-  void WaitForPlaceholderLoad(CefRefPtr<CefFrame> frame) {
-    // Keep track of the frame that contains the placeholder.
-    placeholder_frame_ = frame;
-
-    // Waits for the placeholder to load. This is indicated by the presence
-    // of the plugin node.
-    const std::string& code =
-        "(function waitForNode(i) {"
-        "   setTimeout(function() {"
-        "     var plugin = " +
-        GetPluginNode() +
-        ";"
-        "     if (plugin) {"
-        "        window.testQuery({request:'placeholder_loaded'});"
-        "        return;"
-        "     }"
-        "     if (--i) {"
-        "       waitForNode(i);"
-        "     } else {"
-        "       console.log('Timeout waiting for plugin load');"
-        "     }"
-        "   }, 250)"
-        "})(4);";
-    frame->ExecuteJavaScript(code, frame->GetURL(), 0);
-  }
-
-  void WaitForPlaceholderHide() {
-    // Waits for the placeholder to be hidden (style set to display:none).
-    // See PluginPlaceholderBase::HidePlugin.
-    const std::string& code =
-        "var plugin = " + GetPluginNode() +
-        ";"
-        "var observer = new MutationObserver(function(mutations) {"
-        "  mutations.forEach(function(mutationRecord) {"
-        "    window.testQuery({request:'placeholder_hidden'});"
-        "    observer.disconnect();"
-        "  });"
-        "});"
-        "observer.observe(plugin, "
-        "  { attributes : true, attributeFilter : ['style'] });";
-    placeholder_frame_->ExecuteJavaScript(code, placeholder_frame_->GetURL(),
-                                          0);
-    placeholder_frame_ = nullptr;
-  }
-
-  void WaitForPluginLoad(CefRefPtr<CefFrame> frame) {
-    if (got_context_menu_dismissed_) {
-      // After context menu display. Destroy the test.
-      CefPostDelayedTask(TID_UI,
-                         base::Bind(&PluginTestHandler::DestroyTest, this),
-                         kPdfLoadDelayMs);
-    } else {
-      // Trigger the context menu.
-      CefPostDelayedTask(TID_UI,
-                         base::Bind(&PluginTestHandler::TriggerContextMenu,
-                                    this, frame->GetBrowser()),
-                         kPdfLoadDelayMs);
-    }
-  }
-
-  void EndTest() {
-    CefPostTask(TID_UI, base::Bind(&PluginTestHandler::DestroyTest, this));
-  }
-
-  CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() override {
-    return this;
-  }
-
-  void RunTest() override {
-    CefRefPtr<CefRequestContext> request_context;
-
-    if (HasRequestContext()) {
-      if (HasRequestContextHandler())
-        context_handler_ = new RequestContextHandler(this);
-
-      if (HasGlobalRequestContext()) {
-        // Use the global request context.
-        request_context = CefRequestContext::CreateContext(
-            CefRequestContext::GetGlobalContext(), context_handler_.get());
-      } else {
-        // Create the request context that will use an in-memory cache.
-        CefRequestContextSettings settings;
-        request_context =
-            CefRequestContext::CreateContext(settings, context_handler_.get());
-      }
-    }
-
-    // Create the browser.
-    CreateBrowser(url_, request_context);
-
-    // Time out the test after a reasonable period of time.
-    SetTestTimeout(5000 + kPdfLoadDelayMs);
-  }
-
-  CefRefPtr<CefResourceHandler> GetResourceHandler(
-      CefRefPtr<CefBrowser> browser,
-      CefRefPtr<CefFrame> frame,
-      CefRefPtr<CefRequest> request) override {
-    const std::string& url = request->GetURL();
-    if (url == kPdfHtmlUrl) {
-      CefRefPtr<CefStreamReader> stream =
-          client::GetBinaryResourceReader("pdf.html");
-      return new CefStreamResourceHandler("text/html", stream);
-    } else if (url == kPdfDirectUrl) {
-      CefRefPtr<CefStreamReader> stream =
-          client::GetBinaryResourceReader("pdf.pdf");
-      return new CefStreamResourceHandler("application/pdf", stream);
-    }
-
-    return nullptr;
-  }
-
-  void OnLoadEnd(CefRefPtr<CefBrowser> browser,
-                 CefRefPtr<CefFrame> frame,
-                 int httpStatusCode) override {
-    bool is_pdf1 = false;
-    const std::string& url = frame->GetURL();
-    if (url == kPdfHtmlUrl) {
-      if (!got_on_load_end_html_)
-        got_on_load_end_html_.yes();
-      else
-        NOTREACHED();
-    } else if (url == kPdfDirectUrl) {
-      if (!got_on_load_end_pdf1_) {
-        got_on_load_end_pdf1_.yes();
-        is_pdf1 = true;
-      } else if (!got_on_load_end_pdf2_) {
-        got_on_load_end_pdf2_.yes();
-      } else {
-        NOTREACHED();
-      }
-    } else {
-      NOTREACHED();
-    }
-
-    if (HasNoList()) {
-      // If the plugin is not listed then the PDF documents will never load.
-      EXPECT_STREQ(kPdfHtmlUrl, url.c_str());
-      WaitForNavigatorPlugins(frame);
-    } else if (is_pdf1) {
-      // The first PDF document has loaded.
-      WaitForNavigatorPlugins(frame);
-    }
-  }
-
-  bool OnQuery(CefRefPtr<CefBrowser> browser,
-               CefRefPtr<CefFrame> frame,
-               int64 query_id,
-               const CefString& request,
-               bool persistent,
-               CefRefPtr<Callback> callback) override {
-    if (request == "pdf_plugin_found" || request == "pdf_plugin_missing") {
-      if (request == "pdf_plugin_found")
-        got_pdf_plugin_found_.yes();
-      else
-        got_pdf_plugin_missing_.yes();
-
-      if (HasNoList()) {
-        // The plugin will not load. End the test.
-        EndTest();
-      } else if (HasBlock() || HasDisable()) {
-        // Wait for the plugin placeholder for the first PDF file to load. The
-        // test will continue from OnQuery.
-        WaitForPlaceholderLoad(frame);
-      } else {
-        // Wait for the first PDF file to load.
-        WaitForPluginLoad(frame);
-      }
-    } else if (request == "placeholder_loaded") {
-      EXPECT_FALSE(got_placeholder_loaded_);
-      EXPECT_FALSE(got_placeholder_hidden_);
-      got_placeholder_loaded_.yes();
-
-      // The plugin placeholder has loaded. Trigger the context menu.
-      TriggerContextMenu(frame->GetBrowser());
-    } else if (request == "placeholder_hidden") {
-      EXPECT_TRUE(got_placeholder_loaded_);
-      EXPECT_FALSE(got_placeholder_hidden_);
-      got_placeholder_hidden_.yes();
-
-      if (HasContextLoad()) {
-        // Wait for the PDF plugin to load.
-        WaitForPluginLoad(frame);
-      } else {
-        // The plugin placeholder has been hidden. End the test.
-        EndTest();
-      }
-    } else {
-      NOTREACHED();
-    }
-
-    return true;
-  }
-
-  void TriggerContextMenu(CefRefPtr<CefBrowser> browser) {
-    CefMouseEvent mouse_event;
-
-    // Somewhere in the first plugin.
-    mouse_event.x = 100;
-    mouse_event.y = 100;
-
-    // Send right-click mouse down and mouse up to tigger context menu.
-    browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_RIGHT, false, 1);
-    browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_RIGHT, true, 1);
-  }
-
-  bool RunContextMenu(CefRefPtr<CefBrowser> browser,
-                      CefRefPtr<CefFrame> frame,
-                      CefRefPtr<CefContextMenuParams> params,
-                      CefRefPtr<CefMenuModel> model,
-                      CefRefPtr<CefRunContextMenuCallback> callback) override {
-    EXPECT_FALSE(got_run_context_menu_);
-    got_run_context_menu_.yes();
-
-    if (HasContextLoad() || HasContextHide()) {
-      // Should have 4 elements -- plugin name, separator, run, hide.
-      EXPECT_EQ(4, model->GetCount());
-
-      // Wait for the placeholder to be hidden.
-      WaitForPlaceholderHide();
-
-      int command_id;
-      if (HasContextLoad()) {
-        // Execute the run command.
-        command_id = model->GetCommandIdAt(2);
-      } else {
-        // Execute the hide command.
-        command_id = model->GetCommandIdAt(3);
-      }
-
-      EXPECT_GE(command_id, MENU_ID_CUSTOM_FIRST);
-      EXPECT_LE(command_id, MENU_ID_CUSTOM_LAST);
-
-      callback->Continue(command_id, static_cast<EventFlags>(0));
-    } else {
-      // Do nothing with the context menu.
-      callback->Cancel();
-    }
-    return true;
-  }
-
-  void OnContextMenuDismissed(CefRefPtr<CefBrowser> browser,
-                              CefRefPtr<CefFrame> frame) override {
-    EXPECT_FALSE(got_context_menu_dismissed_);
-    got_context_menu_dismissed_.yes();
-
-    if (HasContextHide()) {
-      // Nothing to do here. The test will continue from OnQuery.
-      // TODO: Once block-then-load is working this should also be the case for
-      // HasContextLoad().
-      return;
-    }
-
-    EndTest();
-  }
-
-  void DestroyTest() override {
-    if (context_handler_.get()) {
-      context_handler_->Detach();
-      context_handler_ = nullptr;
-    }
-
-    if (HasContextLoad()) {
-      EXPECT_TRUE(got_placeholder_loaded_);
-      // TODO: Once block-then-load is working this value should be true.
-      EXPECT_FALSE(got_placeholder_hidden_);
-    } else if (HasContextHide()) {
-      EXPECT_TRUE(got_placeholder_loaded_);
-      EXPECT_TRUE(got_placeholder_hidden_);
-    } else {
-      EXPECT_FALSE(got_placeholder_loaded_);
-      EXPECT_FALSE(got_placeholder_hidden_);
-    }
-    EXPECT_FALSE(placeholder_frame_);
-
-    if (HasRequestContextHandler())
-      EXPECT_TRUE(got_on_before_plugin_empty_origin_);
-    else
-      EXPECT_FALSE(got_on_before_plugin_empty_origin_);
-
-    if (HasNoList()) {
-      EXPECT_TRUE(got_on_before_plugin_empty_origin2_);
-      EXPECT_FALSE(got_pdf_plugin_found_);
-      EXPECT_TRUE(got_pdf_plugin_missing_);
-      EXPECT_FALSE(got_run_context_menu_);
-      EXPECT_FALSE(got_context_menu_dismissed_);
-    } else {
-      EXPECT_FALSE(got_on_before_plugin_empty_origin2_);
-      EXPECT_TRUE(got_pdf_plugin_found_);
-      EXPECT_FALSE(got_pdf_plugin_missing_);
-      EXPECT_TRUE(got_run_context_menu_);
-      EXPECT_TRUE(got_context_menu_dismissed_);
-    }
-
-    if (url_ == kPdfHtmlUrl) {
-      // The HTML file will load the PDF twice in iframes.
-      EXPECT_TRUE(got_on_load_end_html_);
-
-      if (!HasNoList()) {
-        EXPECT_TRUE(got_on_load_end_pdf1_);
-        EXPECT_TRUE(got_on_load_end_pdf2_);
-
-        if (HasRequestContextHandler()) {
-          EXPECT_TRUE(got_on_before_plugin_load_pdf_);
-        }
-      }
-    } else if (url_ == kPdfDirectUrl) {
-      // Load the PDF file directly.
-      EXPECT_FALSE(got_on_load_end_html_);
-      EXPECT_TRUE(got_on_load_end_pdf1_);
-      EXPECT_FALSE(got_on_load_end_pdf2_);
-
-      if (HasRequestContextHandler()) {
-        EXPECT_TRUE(got_on_before_plugin_load_pdf_);
-      }
-    } else {
-      NOTREACHED();
-    }
-
-    if (!HasRequestContextHandler() || HasNoList()) {
-      EXPECT_FALSE(got_on_before_plugin_load_pdf_);
-    }
-
-    TestHandler::DestroyTest();
-  }
-
-  const Mode mode_;
-  const std::string url_;
-
-  CefRefPtr<CefFrame> placeholder_frame_;
-
-  TrackCallback got_on_before_plugin_empty_origin_;
-  TrackCallback got_on_before_plugin_empty_origin2_;
-  TrackCallback got_on_before_plugin_load_pdf_;
-  TrackCallback got_on_load_end_html_;
-  TrackCallback got_on_load_end_pdf1_;
-  TrackCallback got_on_load_end_pdf2_;
-  TrackCallback got_pdf_plugin_found_;
-  TrackCallback got_pdf_plugin_missing_;
-  TrackCallback got_placeholder_loaded_;
-  TrackCallback got_placeholder_hidden_;
-  TrackCallback got_run_context_menu_;
-  TrackCallback got_context_menu_dismissed_;
-
-  CefRefPtr<RequestContextHandler> context_handler_;
-
-  IMPLEMENT_REFCOUNTING(PluginTestHandler);
-};
-
-}  // namespace
-
-#define RUN_TEST(name, type, url)                            \
-  TEST(PluginTest, name) {                                   \
-    CefRefPtr<PluginTestHandler> handler =                   \
-        new PluginTestHandler(PluginTestHandler::type, url); \
-    handler->ExecuteTest();                                  \
-    ReleaseAndWaitForDestructor(handler);                    \
-  }
-
-RUN_TEST(GlobalDefaultPdfDirect, GLOBAL_DEFAULT, kPdfDirectUrl)
-RUN_TEST(GlobalDefaultPdfHtml, GLOBAL_DEFAULT, kPdfHtmlUrl)
-
-RUN_TEST(GlobalNoHandlerPdfDirect, GLOBAL_NO_HANDLER, kPdfDirectUrl)
-RUN_TEST(GlobalNoHandlerPdfHtml, GLOBAL_NO_HANDLER, kPdfHtmlUrl)
-RUN_TEST(GlobalAllowPdfDirect, GLOBAL_ALLOW, kPdfDirectUrl)
-RUN_TEST(GlobalAllowPdfHtml, GLOBAL_ALLOW, kPdfHtmlUrl)
-RUN_TEST(GlobalBlockThenLoadPdfDirect, GLOBAL_BLOCK_LOAD, kPdfDirectUrl)
-RUN_TEST(GlobalBlockThenLoadPdfHtml, GLOBAL_BLOCK_LOAD, kPdfHtmlUrl)
-RUN_TEST(GlobalBlockThenHidePdfDirect, GLOBAL_BLOCK_HIDE, kPdfDirectUrl)
-RUN_TEST(GlobalBlockThenHidePdfHtml, GLOBAL_BLOCK_HIDE, kPdfHtmlUrl)
-RUN_TEST(GlobalDisableThenHidePdfDirect, GLOBAL_DISABLE_HIDE, kPdfDirectUrl)
-RUN_TEST(GlobalDisableThenHidePdfHtml, GLOBAL_DISABLE_HIDE, kPdfHtmlUrl)
-RUN_TEST(GlobalNoListHtml, GLOBAL_NO_LIST, kPdfHtmlUrl)
-
-RUN_TEST(CustomNoHandlerPdfDirect, CUSTOM_NO_HANDLER, kPdfDirectUrl)
-RUN_TEST(CustomNoHandlerPdfHtml, CUSTOM_NO_HANDLER, kPdfHtmlUrl)
-RUN_TEST(CustomAllowPdfDirect, CUSTOM_ALLOW, kPdfDirectUrl)
-RUN_TEST(CustomAllowPdfHtml, CUSTOM_ALLOW, kPdfHtmlUrl)
-RUN_TEST(CustomBlockThenLoadPdfDirect, CUSTOM_BLOCK_LOAD, kPdfDirectUrl)
-RUN_TEST(CustomBlockThenLoadPdfHtml, CUSTOM_BLOCK_LOAD, kPdfHtmlUrl)
-RUN_TEST(CustomBlockThenHidePdfDirect, CUSTOM_BLOCK_HIDE, kPdfDirectUrl)
-RUN_TEST(CustomBlockThenHidePdfHtml, CUSTOM_BLOCK_HIDE, kPdfHtmlUrl)
-RUN_TEST(CustomDisableThenHidePdfDirect, CUSTOM_DISABLE_HIDE, kPdfDirectUrl)
-RUN_TEST(CustomDisableThenHidePdfHtml, CUSTOM_DISABLE_HIDE, kPdfHtmlUrl)
-RUN_TEST(CustomNoListHtml, CUSTOM_NO_LIST, kPdfHtmlUrl)
-
-// Entry point for creating plugin browser test objects.
-// Called from client_app_delegates.cc.
-void CreatePluginBrowserTests(
-    client::ClientAppBrowser::DelegateSet& delegates) {
-  delegates.insert(new PluginBrowserTest);
-}
diff --git a/src/tests/ceftests/preference_unittest.cc b/src/tests/ceftests/preference_unittest.cc
index 8c190d3..f04db95 100644
--- a/src/tests/ceftests/preference_unittest.cc
+++ b/src/tests/ceftests/preference_unittest.cc
@@ -2,7 +2,7 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_request_context_handler.h"
 #include "include/cef_waitable_event.h"
 #include "include/wrapper/cef_closure_task.h"
@@ -31,24 +31,72 @@
 const char kPrefList[] = "list";
 const char kPrefDict[] = "dict";
 
+std::string* PendingAction() {
+  static std::string str;
+  return &str;
+}
+
+CefRefPtr<CefValue> CreateBoolValue(bool value) {
+  auto val = CefValue::Create();
+  val->SetBool(value);
+  return val;
+}
+
+CefRefPtr<CefValue> CreateIntValue(int value) {
+  auto val = CefValue::Create();
+  val->SetInt(value);
+  return val;
+}
+
+CefRefPtr<CefValue> CreateDoubleValue(double value) {
+  auto val = CefValue::Create();
+  val->SetDouble(value);
+  return val;
+}
+
+CefRefPtr<CefValue> CreateStringValue(const std::string& value) {
+  auto val = CefValue::Create();
+  val->SetString(value);
+  return val;
+}
+
+CefRefPtr<CefValue> CreateListValue(CefRefPtr<CefListValue> value) {
+  auto val = CefValue::Create();
+  val->SetList(value);
+  return val;
+}
+
+CefRefPtr<CefValue> CreateDictionaryValue(CefRefPtr<CefDictionaryValue> value) {
+  auto val = CefValue::Create();
+  val->SetDictionary(value);
+  return val;
+}
+
 // Browser-side app delegate.
 class PreferenceBrowserTest : public client::ClientAppBrowser::Delegate {
  public:
   PreferenceBrowserTest() {}
 
-  void OnBeforeCommandLineProcessing(
+  void OnRegisterCustomPreferences(
       CefRefPtr<client::ClientAppBrowser> app,
-      CefRefPtr<CefCommandLine> command_line) override {
-    // Enables testing of preferences.
-    // See CefBrowserPrefStore::CreateService.
-    command_line->AppendSwitch("enable-preference-testing");
+      cef_preferences_type_t type,
+      CefRawPtr<CefPreferenceRegistrar> registrar) override {
+    // Register test preferences.
+    registrar->AddPreference(kPrefTestBool, CreateBoolValue(true));
+    registrar->AddPreference(kPrefTestInt, CreateIntValue(2));
+    registrar->AddPreference(kPrefTestDouble, CreateDoubleValue(5.0));
+    registrar->AddPreference(kPrefTestString, CreateStringValue("default"));
+    registrar->AddPreference(kPrefTestList,
+                             CreateListValue(CefListValue::Create()));
+    registrar->AddPreference(
+        kPrefTestDict, CreateDictionaryValue(CefDictionaryValue::Create()));
   }
 
  private:
   IMPLEMENT_REFCOUNTING(PreferenceBrowserTest);
 };
 
-void ValidateReset(CefRefPtr<CefRequestContext> context, const char* name) {
+void ValidateReset(CefRefPtr<CefPreferenceManager> context, const char* name) {
   EXPECT_TRUE(context->HasPreference(name));
   EXPECT_TRUE(context->CanSetPreference(name));
 
@@ -57,116 +105,99 @@
   EXPECT_TRUE(error.empty());
 }
 
-void ValidateBool(CefRefPtr<CefRequestContext> context,
+void ValidateBool(CefRefPtr<CefPreferenceManager> context,
                   bool set,
                   bool expected,
                   const char* name = kPrefTestBool) {
   EXPECT_TRUE(context->HasPreference(name));
   EXPECT_TRUE(context->CanSetPreference(name));
 
-  CefRefPtr<CefValue> value;
-
   if (set) {
-    value = CefValue::Create();
-    value->SetBool(expected);
     CefString error;
-    EXPECT_TRUE(context->SetPreference(name, value, error));
+    EXPECT_TRUE(context->SetPreference(name, CreateBoolValue(expected), error));
     EXPECT_TRUE(error.empty());
   }
 
-  value = context->GetPreference(name);
+  auto value = context->GetPreference(name);
   EXPECT_TRUE(value.get());
   EXPECT_EQ(VTYPE_BOOL, value->GetType());
-  EXPECT_EQ(expected, value->GetBool());
+  EXPECT_EQ(expected, value->GetBool()) << *PendingAction();
 }
 
-void ValidateInt(CefRefPtr<CefRequestContext> context,
+void ValidateInt(CefRefPtr<CefPreferenceManager> context,
                  bool set,
                  int expected,
                  const char* name = kPrefTestInt) {
   EXPECT_TRUE(context->HasPreference(name));
   EXPECT_TRUE(context->CanSetPreference(name));
 
-  CefRefPtr<CefValue> value;
-
   if (set) {
-    value = CefValue::Create();
-    value->SetInt(expected);
     CefString error;
-    EXPECT_TRUE(context->SetPreference(name, value, error));
+    EXPECT_TRUE(context->SetPreference(name, CreateIntValue(expected), error));
     EXPECT_TRUE(error.empty());
   }
 
-  value = context->GetPreference(name);
+  auto value = context->GetPreference(name);
   EXPECT_TRUE(value.get());
   EXPECT_EQ(VTYPE_INT, value->GetType());
-  EXPECT_EQ(expected, value->GetInt());
+  EXPECT_EQ(expected, value->GetInt()) << *PendingAction();
 }
 
-void ValidateDouble(CefRefPtr<CefRequestContext> context,
+void ValidateDouble(CefRefPtr<CefPreferenceManager> context,
                     bool set,
                     double expected,
                     const char* name = kPrefTestDouble) {
   EXPECT_TRUE(context->HasPreference(name));
   EXPECT_TRUE(context->CanSetPreference(name));
 
-  CefRefPtr<CefValue> value;
-
   if (set) {
-    value = CefValue::Create();
-    value->SetDouble(expected);
     CefString error;
-    EXPECT_TRUE(context->SetPreference(name, value, error));
+    EXPECT_TRUE(
+        context->SetPreference(name, CreateDoubleValue(expected), error));
     EXPECT_TRUE(error.empty());
   }
 
-  value = context->GetPreference(name);
+  auto value = context->GetPreference(name);
   EXPECT_TRUE(value.get());
   EXPECT_EQ(VTYPE_DOUBLE, value->GetType());
-  EXPECT_EQ(expected, value->GetDouble());
+  EXPECT_EQ(expected, value->GetDouble()) << *PendingAction();
 }
 
-void ValidateString(CefRefPtr<CefRequestContext> context,
+void ValidateString(CefRefPtr<CefPreferenceManager> context,
                     bool set,
                     const std::string& expected,
                     const char* name = kPrefTestString) {
   EXPECT_TRUE(context->HasPreference(name));
   EXPECT_TRUE(context->CanSetPreference(name));
 
-  CefRefPtr<CefValue> value;
-
   if (set) {
-    value = CefValue::Create();
-    value->SetString(expected);
     CefString error;
-    EXPECT_TRUE(context->SetPreference(name, value, error));
+    EXPECT_TRUE(
+        context->SetPreference(name, CreateStringValue(expected), error));
     EXPECT_TRUE(error.empty());
   }
 
-  value = context->GetPreference(name);
+  auto value = context->GetPreference(name);
   EXPECT_TRUE(value.get());
   EXPECT_EQ(VTYPE_STRING, value->GetType());
-  EXPECT_STREQ(expected.c_str(), value->GetString().ToString().c_str());
+  EXPECT_STREQ(expected.c_str(), value->GetString().ToString().c_str())
+      << *PendingAction();
 }
 
-void ValidateList(CefRefPtr<CefRequestContext> context,
+void ValidateList(CefRefPtr<CefPreferenceManager> context,
                   bool set,
                   CefRefPtr<CefListValue> expected,
                   const char* name = kPrefTestList) {
   EXPECT_TRUE(context->HasPreference(name));
   EXPECT_TRUE(context->CanSetPreference(name));
 
-  CefRefPtr<CefValue> value;
-
   if (set) {
-    value = CefValue::Create();
-    value->SetList(expected);
     CefString error;
-    EXPECT_TRUE(context->SetPreference(name, value, error));
+    EXPECT_TRUE(context->SetPreference(name, CreateListValue(expected), error));
     EXPECT_TRUE(error.empty());
   }
 
-  value = context->GetPreference(name);
+  auto value = context->GetPreference(name);
   EXPECT_TRUE(value.get());
   EXPECT_EQ(VTYPE_LIST, value->GetType());
   CefRefPtr<CefListValue> list_val = value->GetList();
@@ -174,24 +205,21 @@
   TestListEqual(expected, list_val);
 }
 
-void ValidateDict(CefRefPtr<CefRequestContext> context,
+void ValidateDict(CefRefPtr<CefPreferenceManager> context,
                   bool set,
                   CefRefPtr<CefDictionaryValue> expected,
                   const char* name = kPrefTestDict) {
   EXPECT_TRUE(context->HasPreference(name));
   EXPECT_TRUE(context->CanSetPreference(name));
 
-  CefRefPtr<CefValue> value;
-
   if (set) {
-    value = CefValue::Create();
-    value->SetDictionary(expected);
     CefString error;
-    EXPECT_TRUE(context->SetPreference(name, value, error));
+    EXPECT_TRUE(
+        context->SetPreference(name, CreateDictionaryValue(expected), error));
     EXPECT_TRUE(error.empty());
   }
 
-  value = context->GetPreference(name);
+  auto value = context->GetPreference(name);
   EXPECT_TRUE(value.get());
   EXPECT_EQ(VTYPE_DICTIONARY, value->GetType());
   CefRefPtr<CefDictionaryValue> dict_val = value->GetDictionary();
@@ -199,28 +227,24 @@
   TestDictionaryEqual(expected, dict_val);
 }
 
-void ValidateNoExist(CefRefPtr<CefRequestContext> context,
+void ValidateNoExist(CefRefPtr<CefPreferenceManager> context,
                      bool set,
                      const char* name = kPrefTestNoExist) {
   EXPECT_FALSE(context->HasPreference(name));
   EXPECT_FALSE(context->CanSetPreference(name));
 
-  CefRefPtr<CefValue> value;
-
   if (set) {
-    value = CefValue::Create();
-    value->SetBool(false);
     CefString error;
-    EXPECT_FALSE(context->SetPreference(name, value, error));
+    EXPECT_FALSE(context->SetPreference(name, CreateBoolValue(false), error));
     EXPECT_FALSE(error.empty());
   }
 
-  value = context->GetPreference(name);
-  EXPECT_FALSE(value.get());
+  auto value = context->GetPreference(name);
+  EXPECT_FALSE(value.get()) << *PendingAction();
 }
 
 void PopulateRootDefaults(CefRefPtr<CefDictionaryValue> val) {
-  // Should match the values in CefBrowserPrefStore::CreateService.
+  // Should match the values in OnRegisterCustomPreferences.
   val->SetBool(kPrefBool, true);
   val->SetInt(kPrefInt, 2);
   val->SetDouble(kPrefDouble, 5.0);
@@ -240,11 +264,12 @@
 }
 
 // Validate getting default values.
-void ValidateDefaults(CefRefPtr<CefRequestContext> context,
+void ValidateDefaults(CefRefPtr<CefPreferenceManager> context,
                       bool reset,
                       CefRefPtr<CefWaitableEvent> event) {
   if (!CefCurrentlyOn(TID_UI)) {
-    CefPostTask(TID_UI, base::Bind(ValidateDefaults, context, reset, event));
+    CefPostTask(TID_UI,
+                base::BindOnce(ValidateDefaults, context, reset, event));
     return;
   }
 
@@ -315,10 +340,10 @@
 }
 
 // Validate getting and setting values.
-void ValidateSetGet(CefRefPtr<CefRequestContext> context,
+void ValidateSetGet(CefRefPtr<CefPreferenceManager> context,
                     CefRefPtr<CefWaitableEvent> event) {
   if (!CefCurrentlyOn(TID_UI)) {
-    CefPostTask(TID_UI, base::Bind(ValidateSetGet, context, event));
+    CefPostTask(TID_UI, base::BindOnce(ValidateSetGet, context, event));
     return;
   }
 
@@ -352,10 +377,10 @@
 }
 
 // Validate getting values.
-void ValidateGet(CefRefPtr<CefRequestContext> context,
+void ValidateGet(CefRefPtr<CefPreferenceManager> context,
                  CefRefPtr<CefWaitableEvent> event) {
   if (!CefCurrentlyOn(TID_UI)) {
-    CefPostTask(TID_UI, base::Bind(ValidateGet, context, event));
+    CefPostTask(TID_UI, base::BindOnce(ValidateGet, context, event));
     return;
   }
 
@@ -392,30 +417,43 @@
 class TestRequestContextHandler : public CefRequestContextHandler {
  public:
   TestRequestContextHandler() {}
+  explicit TestRequestContextHandler(CefRefPtr<CefWaitableEvent> event)
+      : event_(event) {}
+
+  void OnRequestContextInitialized(
+      CefRefPtr<CefRequestContext> context) override {
+    if (event_) {
+      event_->Signal();
+      event_ = nullptr;
+    }
+  }
+
+ private:
+  CefRefPtr<CefWaitableEvent> event_;
 
   IMPLEMENT_REFCOUNTING(TestRequestContextHandler);
 };
 
 }  // namespace
 
-// Verify default preference values on the global context.
+// Verify default preference values on the global state.
 TEST(PreferenceTest, GlobalDefaults) {
   CefRefPtr<CefWaitableEvent> event =
       CefWaitableEvent::CreateWaitableEvent(true, false);
 
-  CefRefPtr<CefRequestContext> context = CefRequestContext::GetGlobalContext();
+  auto context = CefPreferenceManager::GetGlobalPreferenceManager();
   EXPECT_TRUE(context.get());
 
   ValidateDefaults(context, false, event);
   event->Wait();
 }
 
-// Verify setting/getting preference values on the global context.
+// Verify setting/getting preference values on the global state.
 TEST(PreferenceTest, GlobalSetGet) {
   CefRefPtr<CefWaitableEvent> event =
       CefWaitableEvent::CreateWaitableEvent(true, false);
 
-  CefRefPtr<CefRequestContext> context = CefRequestContext::GetGlobalContext();
+  auto context = CefPreferenceManager::GetGlobalPreferenceManager();
   EXPECT_TRUE(context.get());
 
   ValidateSetGet(context, event);
@@ -426,71 +464,24 @@
   event->Wait();
 }
 
-// Verify setting/getting preference values on shared global contexts.
-TEST(PreferenceTest, GlobalSetGetShared) {
+// Verify default preference values on the global request context.
+TEST(PreferenceTest, RequestContextGlobalDefaults) {
   CefRefPtr<CefWaitableEvent> event =
       CefWaitableEvent::CreateWaitableEvent(true, false);
 
   CefRefPtr<CefRequestContext> context = CefRequestContext::GetGlobalContext();
   EXPECT_TRUE(context.get());
 
-  // Sharing storage.
-  CefRefPtr<CefRequestContext> context2 =
-      CefRequestContext::CreateContext(context, nullptr);
-  EXPECT_TRUE(context2.get());
-
-  // Sharing storage.
-  CefRefPtr<CefRequestContext> context3 =
-      CefRequestContext::CreateContext(context, new TestRequestContextHandler);
-  EXPECT_TRUE(context3.get());
-
-  // Unassociated context.
-  CefRequestContextSettings settings;
-  CefRefPtr<CefRequestContext> context4 =
-      CefRequestContext::CreateContext(settings, nullptr);
-  EXPECT_TRUE(context.get());
-
-  // Set/get the values on the first context.
-  ValidateSetGet(context, event);
-  event->Wait();
-
-  // Get the values from the 2nd and 3rd contexts. They should be the same.
-  ValidateGet(context2, event);
-  event->Wait();
-  ValidateGet(context3, event);
-  event->Wait();
-
-  // Get the values from the 4th context. They should be at the default.
-  ValidateDefaults(context4, false, event);
-  event->Wait();
-
-  // Reset to the default values.
-  ValidateDefaults(context, true, event);
-  event->Wait();
-}
-
-// Verify default preference values on a custom context.
-TEST(PreferenceTest, CustomDefaults) {
-  CefRefPtr<CefWaitableEvent> event =
-      CefWaitableEvent::CreateWaitableEvent(true, false);
-
-  CefRequestContextSettings settings;
-  CefRefPtr<CefRequestContext> context =
-      CefRequestContext::CreateContext(settings, nullptr);
-  EXPECT_TRUE(context.get());
-
   ValidateDefaults(context, false, event);
   event->Wait();
 }
 
-// Verify setting/getting preference values on a custom context.
-TEST(PreferenceTest, CustomSetGet) {
+// Verify setting/getting preference values on the global request context.
+TEST(PreferenceTest, RequestContextGlobalSetGet) {
   CefRefPtr<CefWaitableEvent> event =
       CefWaitableEvent::CreateWaitableEvent(true, false);
 
-  CefRequestContextSettings settings;
-  CefRefPtr<CefRequestContext> context =
-      CefRequestContext::CreateContext(settings, nullptr);
+  CefRefPtr<CefRequestContext> context = CefRequestContext::GetGlobalContext();
   EXPECT_TRUE(context.get());
 
   ValidateSetGet(context, event);
@@ -501,14 +492,12 @@
   event->Wait();
 }
 
-// Verify setting/getting preference values on shared custom contexts.
-TEST(PreferenceTest, CustomSetGetShared) {
+// Verify setting/getting preference values on shared global request contexts.
+TEST(PreferenceTest, RequestContextGlobalSetGetShared) {
   CefRefPtr<CefWaitableEvent> event =
       CefWaitableEvent::CreateWaitableEvent(true, false);
 
-  CefRequestContextSettings settings;
-  CefRefPtr<CefRequestContext> context =
-      CefRequestContext::CreateContext(settings, nullptr);
+  CefRefPtr<CefRequestContext> context = CefRequestContext::GetGlobalContext();
   EXPECT_TRUE(context.get());
 
   // Sharing storage.
@@ -522,25 +511,133 @@
   EXPECT_TRUE(context3.get());
 
   // Unassociated context.
-  CefRefPtr<CefRequestContext> context4 =
-      CefRequestContext::CreateContext(settings, nullptr);
-  EXPECT_TRUE(context.get());
+  CefRequestContextSettings settings;
+  CefRefPtr<CefRequestContext> context4 = CefRequestContext::CreateContext(
+      settings, new TestRequestContextHandler(event));
+  EXPECT_TRUE(context4.get());
+  // Wait for the context to be fully initialized.
+  event->Wait();
 
   // Set/get the values on the first context.
+  *PendingAction() = "Set/get the values on the first context";
+  ValidateSetGet(context, event);
+  event->Wait();
+
+  // Get the values from the 2nd and 3rd contexts. They should be the same.
+  *PendingAction() = "Get the values from the 2nd context.";
+  ValidateGet(context2, event);
+  event->Wait();
+  *PendingAction() = "Get the values from the 3rd context.";
+  ValidateGet(context3, event);
+  event->Wait();
+
+  // Get the values from the 4th context.
+  *PendingAction() = "Get the values from the 4th context.";
+  if (IsChromeRuntimeEnabled()) {
+    // With the Chrome runtime, prefs set via an incognito profile will become
+    // an overlay on top of the global (parent) profile. The incognito profile
+    // shares the prefs in this case because they were set via the global
+    // profile.
+    ValidateGet(context4, event);
+  } else {
+    // They should be at the default.
+    ValidateDefaults(context4, false, event);
+  }
+  event->Wait();
+
+  // Reset to the default values.
+  *PendingAction() = "Reset to the default values.";
+  ValidateDefaults(context, true, event);
+  event->Wait();
+}
+
+// Verify default preference values on a custom request context.
+TEST(PreferenceTest, RequestContextCustomDefaults) {
+  CefRefPtr<CefWaitableEvent> event =
+      CefWaitableEvent::CreateWaitableEvent(true, false);
+
+  CefRequestContextSettings settings;
+  CefRefPtr<CefRequestContext> context = CefRequestContext::CreateContext(
+      settings, new TestRequestContextHandler(event));
+  EXPECT_TRUE(context.get());
+  // Wait for the context to be fully initialized.
+  event->Wait();
+
+  ValidateDefaults(context, false, event);
+  event->Wait();
+}
+
+// Verify setting/getting preference values on a custom request context.
+TEST(PreferenceTest, RequestContextCustomSetGet) {
+  CefRefPtr<CefWaitableEvent> event =
+      CefWaitableEvent::CreateWaitableEvent(true, false);
+
+  CefRequestContextSettings settings;
+  CefRefPtr<CefRequestContext> context = CefRequestContext::CreateContext(
+      settings, new TestRequestContextHandler(event));
+  EXPECT_TRUE(context.get());
+  // Wait for the context to be fully initialized.
+  event->Wait();
+
+  ValidateSetGet(context, event);
+  event->Wait();
+
+  // Reset to the default values.
+  ValidateDefaults(context, true, event);
+  event->Wait();
+}
+
+// Verify setting/getting preference values on shared custom request contexts.
+TEST(PreferenceTest, RequestContextCustomSetGetShared) {
+  CefRefPtr<CefWaitableEvent> event =
+      CefWaitableEvent::CreateWaitableEvent(true, false);
+
+  CefRequestContextSettings settings;
+  CefRefPtr<CefRequestContext> context = CefRequestContext::CreateContext(
+      settings, new TestRequestContextHandler(event));
+  EXPECT_TRUE(context.get());
+  // Wait for the context to be fully initialized.
+  event->Wait();
+
+  // Sharing storage.
+  CefRefPtr<CefRequestContext> context2 =
+      CefRequestContext::CreateContext(context, nullptr);
+  EXPECT_TRUE(context2.get());
+
+  // Sharing storage.
+  CefRefPtr<CefRequestContext> context3 =
+      CefRequestContext::CreateContext(context, new TestRequestContextHandler);
+  EXPECT_TRUE(context3.get());
+
+  // Unassociated context.
+  CefRefPtr<CefRequestContext> context4 = CefRequestContext::CreateContext(
+      settings, new TestRequestContextHandler(event));
+  EXPECT_TRUE(context4.get());
+  // Wait for the context to be fully initialized.
+  event->Wait();
+
+  // Set/get the values on the first context.
+  *PendingAction() = "Set/get the values on the first context";
   ValidateSetGet(context, event);
   event->Wait();
 
   // Get the values from the 2nd and 3d contexts. They should be the same.
+  *PendingAction() = "Get the values from the 2nd context.";
   ValidateGet(context2, event);
   event->Wait();
+  *PendingAction() = "Get the values from the 3rd context.";
   ValidateGet(context3, event);
   event->Wait();
 
   // Get the values from the 4th context. They should be at the default.
+  // This works with the Chrome runtime because the preference changes only
+  // exist in the other incognito profile's overlay.
+  *PendingAction() = "Get the values from the 4th context.";
   ValidateDefaults(context4, false, event);
   event->Wait();
 
   // Reset to the default values.
+  *PendingAction() = "Reset to the default values.";
   ValidateDefaults(context, true, event);
   event->Wait();
 }
diff --git a/src/tests/ceftests/print_unittest.cc b/src/tests/ceftests/print_unittest.cc
index 3a81edc..d05848c 100644
--- a/src/tests/ceftests/print_unittest.cc
+++ b/src/tests/ceftests/print_unittest.cc
@@ -38,8 +38,9 @@
   CefPrintSettings::PageRangeList page_ranges2;
   settings->GetPageRanges(page_ranges2);
   EXPECT_EQ(page_ranges.size(), page_ranges2.size());
-  for (size_t i = 0; i < page_ranges.size(); ++i)
+  for (size_t i = 0; i < page_ranges.size(); ++i) {
     EXPECT_EQ(page_ranges[i], page_ranges2[i]);
+  }
 
   bool selection_only = true;
   settings->SetSelectionOnly(selection_only);
diff --git a/src/tests/ceftests/process_message_unittest.cc b/src/tests/ceftests/process_message_unittest.cc
index 2626128..6da01ee 100644
--- a/src/tests/ceftests/process_message_unittest.cc
+++ b/src/tests/ceftests/process_message_unittest.cc
@@ -2,7 +2,7 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_process_message.h"
 #include "include/cef_task.h"
 #include "include/wrapper/cef_closure_task.h"
@@ -16,16 +16,20 @@
 namespace {
 
 // Unique values for the SendRecv test.
-const char kSendRecvUrl[] = "http://tests/ProcessMessageTest.SendRecv";
+const char kSendRecvUrl[] = "https://tests/ProcessMessageTest.SendRecv";
 const char kSendRecvMsg[] = "ProcessMessageTest.SendRecv";
 
 // Creates a test message.
 CefRefPtr<CefProcessMessage> CreateTestMessage() {
   CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create(kSendRecvMsg);
   EXPECT_TRUE(msg.get());
+  EXPECT_TRUE(msg->IsValid());
+  EXPECT_FALSE(msg->IsReadOnly());
 
   CefRefPtr<CefListValue> args = msg->GetArgumentList();
   EXPECT_TRUE(args.get());
+  EXPECT_TRUE(args->IsValid());
+  EXPECT_FALSE(args->IsReadOnly());
 
   size_t index = 0;
   args->SetNull(index++);
@@ -55,11 +59,14 @@
       EXPECT_TRUE(frame.get());
       EXPECT_EQ(PID_BROWSER, source_process);
       EXPECT_TRUE(message.get());
+      EXPECT_TRUE(message->IsValid());
+      EXPECT_TRUE(message->IsReadOnly());
 
       const std::string& url = frame->GetURL();
       if (url == kSendRecvUrl) {
         // Echo the message back to the sender natively.
         frame->SendProcessMessage(PID_BROWSER, message);
+        EXPECT_FALSE(message->IsValid());
         return true;
       }
     }
@@ -78,8 +85,6 @@
       : send_thread_(send_thread) {}
 
   void RunTest() override {
-    message_ = CreateTestMessage();
-
     AddResource(kSendRecvUrl, "<html><body>TEST</body></html>", "text/html");
     CreateBrowser(kSendRecvUrl);
 
@@ -94,8 +99,9 @@
 
     // Send the message to the renderer process.
     if (!CefCurrentlyOn(send_thread_)) {
-      CefPostTask(send_thread_, base::Bind(&SendRecvTestHandler::SendMessage,
-                                           this, browser, frame));
+      CefPostTask(send_thread_,
+                  base::BindOnce(&SendRecvTestHandler::SendMessage, this,
+                                 browser, frame));
     } else {
       SendMessage(browser, frame);
     }
@@ -110,10 +116,11 @@
     EXPECT_TRUE(frame.get());
     EXPECT_EQ(PID_RENDERER, source_process);
     EXPECT_TRUE(message.get());
+    EXPECT_TRUE(message->IsValid());
     EXPECT_TRUE(message->IsReadOnly());
 
     // Verify that the recieved message is the same as the sent message.
-    TestProcessMessageEqual(message_, message);
+    TestProcessMessageEqual(CreateTestMessage(), message);
 
     got_message_.yes();
 
@@ -132,12 +139,15 @@
  private:
   void SendMessage(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame) {
     EXPECT_TRUE(CefCurrentlyOn(send_thread_));
-    frame->SendProcessMessage(PID_RENDERER, message_);
+    auto message = CreateTestMessage();
+    frame->SendProcessMessage(PID_RENDERER, message);
+
+    // The message will be invalidated immediately, no matter what thread we
+    // send from.
+    EXPECT_FALSE(message->IsValid());
   }
 
   cef_thread_id_t send_thread_;
-
-  CefRefPtr<CefProcessMessage> message_;
   TrackCallback got_message_;
 
   IMPLEMENT_REFCOUNTING(SendRecvTestHandler);
@@ -171,7 +181,7 @@
   CefRefPtr<CefListValue> args = message->GetArgumentList();
   EXPECT_TRUE(args.get());
   EXPECT_TRUE(args->IsValid());
-  EXPECT_TRUE(args->IsOwned());
+  EXPECT_FALSE(args->IsOwned());
   EXPECT_FALSE(args->IsReadOnly());
 }
 
diff --git a/src/tests/ceftests/request_context_unittest.cc b/src/tests/ceftests/request_context_unittest.cc
index 5058ea9..d368d02 100644
--- a/src/tests/ceftests/request_context_unittest.cc
+++ b/src/tests/ceftests/request_context_unittest.cc
@@ -2,7 +2,7 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_request_context.h"
 #include "include/cef_request_context_handler.h"
 #include "include/wrapper/cef_closure_task.h"
@@ -136,7 +136,8 @@
 
 TEST(RequestContextTest, BasicCreateSharedOnDisk) {
   CefScopedTempDir tempdir;
-  EXPECT_TRUE(tempdir.CreateUniqueTempDir());
+  EXPECT_TRUE(tempdir.CreateUniqueTempDirUnderPath(
+      CefTestSuite::GetInstance()->root_cache_path()));
 
   CefRequestContextSettings settings;
   CefString(&settings.cache_path) = tempdir.GetPath();
@@ -205,11 +206,12 @@
   };
 
   PopupTestHandler(bool same_origin, Mode mode) : mode_(mode) {
-    url_ = "http://tests-simple-rch1.com/nav1.html";
-    if (same_origin)
-      popup_url_ = "http://tests-simple-rch1.com/pop1.html";
-    else
-      popup_url_ = "http://tests-simple-rch2.com/pop1.html";
+    url_ = "https://tests-simple-rch1.com/nav1.html";
+    if (same_origin) {
+      popup_url_ = "https://tests-simple-rch1.com/pop1.html";
+    } else {
+      popup_url_ = "https://tests-simple-rch2.com/pop1.html";
+    }
   }
 
   void RunTest() override {
@@ -247,6 +249,8 @@
     context_ = CefRequestContext::CreateContext(settings, nullptr);
     cookie_manager_ = context_->GetCookieManager(nullptr);
 
+    GrantPopupPermission(context_, url_);
+
     // Create browser that loads the 1st URL.
     CreateBrowser(url_, context_);
 
@@ -294,12 +298,13 @@
     const std::string& url = target_url;
     EXPECT_STREQ(url.c_str(), popup_url_.c_str());
 
-    EXPECT_EQ(WOD_NEW_FOREGROUND_TAB, target_disposition);
+    EXPECT_EQ(CEF_WOD_NEW_FOREGROUND_TAB, target_disposition);
 
-    if (mode_ == MODE_WINDOW_OPEN)
+    if (mode_ == MODE_WINDOW_OPEN) {
       EXPECT_FALSE(user_gesture);
-    else
+    } else {
       EXPECT_TRUE(user_gesture);
+    }
 
     return false;
   }
@@ -307,8 +312,9 @@
   void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
     TestHandler::OnBeforeClose(browser);
 
-    if (browser->IsPopup())
+    if (browser->IsPopup()) {
       FinishTest();
+    }
   }
 
  protected:
@@ -320,10 +326,9 @@
       mouse_event.x = 20;
       mouse_event.y = 20;
       mouse_event.modifiers = 0;
-      browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1);
-      browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true, 1);
+      SendMouseClickEvent(browser, mouse_event);
     } else {
-      EXPECT_TRUE(false);  // Not reached.
+      ADD_FAILURE();  // Not reached.
     }
   }
 
@@ -335,7 +340,7 @@
       ~TestVisitor() override {
         // Destroy the test.
         CefPostTask(TID_UI,
-                    base::Bind(&PopupTestHandler::DestroyTest, handler_));
+                    base::BindOnce(&PopupTestHandler::DestroyTest, handler_));
       }
 
       bool Visit(const CefCookie& cookie,
@@ -443,9 +448,9 @@
 
 namespace {
 
-const char kPopupNavPageUrl[] = "http://tests-popup.com/page.html";
-const char kPopupNavPopupUrl[] = "http://tests-popup.com/popup.html";
-const char kPopupNavPopupUrl2[] = "http://tests-popup2.com/popup.html";
+const char kPopupNavPageUrl[] = "https://tests-popup.com/page.html";
+const char kPopupNavPopupUrl[] = "https://tests-popup.com/popup.html";
+const char kPopupNavPopupUrl2[] = "https://tests-popup2.com/popup.html";
 const char kPopupNavPopupName[] = "my_popup";
 
 // Browser side.
@@ -477,19 +482,32 @@
                        "'); }</script>Page</html>";
     AddResource(kPopupNavPageUrl, page, "text/html");
     AddResource(kPopupNavPopupUrl, "<html>Popup</html>", "text/html");
-    if (mode_ == NAVIGATE_AFTER_CREATION)
+    if (mode_ == NAVIGATE_AFTER_CREATION) {
       AddResource(kPopupNavPopupUrl2, "<html>Popup2</html>", "text/html");
+    }
 
-    CefRefPtr<CefRequestContext> request_context =
-        CreateTestRequestContext(rc_mode_, rc_cache_path_);
-
-    // Create the browser.
-    CreateBrowser(kPopupNavPageUrl, request_context);
+    CreateTestRequestContext(
+        rc_mode_, rc_cache_path_,
+        base::BindOnce(&PopupNavTestHandler::RunTestContinue, this));
 
     // Time out the test after a reasonable period of time.
     SetTestTimeout();
   }
 
+  void RunTestContinue(CefRefPtr<CefRequestContext> request_context) {
+    EXPECT_UI_THREAD();
+
+    if (request_context) {
+      GrantPopupPermission(request_context, kPopupNavPageUrl);
+    } else {
+      GrantPopupPermission(CefRequestContext::GetGlobalContext(),
+                           kPopupNavPageUrl);
+    }
+
+    // Create the browser.
+    CreateBrowser(kPopupNavPageUrl, request_context);
+  }
+
   bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
                      CefRefPtr<CefFrame> frame,
                      const CefString& target_url,
@@ -510,7 +528,7 @@
     EXPECT_STREQ(kPopupNavPageUrl, frame->GetURL().ToString().c_str());
     EXPECT_STREQ(kPopupNavPopupUrl, target_url.ToString().c_str());
     EXPECT_STREQ(kPopupNavPopupName, target_frame_name.ToString().c_str());
-    EXPECT_EQ(WOD_NEW_FOREGROUND_TAB, target_disposition);
+    EXPECT_EQ(CEF_WOD_NEW_FOREGROUND_TAB, target_disposition);
     EXPECT_FALSE(user_gesture);
     EXPECT_FALSE(*no_javascript_access);
 
@@ -592,7 +610,8 @@
       if (mode_ == DENY) {
         // Wait a bit to make sure the popup window isn't created.
         CefPostDelayedTask(
-            TID_UI, base::Bind(&PopupNavTestHandler::DestroyTest, this), 200);
+            TID_UI, base::BindOnce(&PopupNavTestHandler::DestroyTest, this),
+            200);
       }
     } else if (url == kPopupNavPopupUrl) {
       EXPECT_FALSE(got_popup_load_end_);
@@ -628,8 +647,9 @@
     bool destroy_test = false;
     if (mode_ == ALLOW_CLOSE_POPUP_FIRST || mode_ == NAVIGATE_AFTER_CREATION) {
       // Destroy the test after the popup browser closes.
-      if (browser->IsPopup())
+      if (browser->IsPopup()) {
         destroy_test = true;
+      }
     } else if (mode_ == ALLOW_CLOSE_POPUP_LAST ||
                mode_ == DESTROY_PARENT_BEFORE_CREATION ||
                mode_ == DESTROY_PARENT_BEFORE_CREATION_FORCE ||
@@ -638,12 +658,14 @@
                mode_ == DESTROY_PARENT_AFTER_CREATION ||
                mode_ == DESTROY_PARENT_AFTER_CREATION_FORCE) {
       // Destroy the test after the main browser closes.
-      if (!browser->IsPopup())
+      if (!browser->IsPopup()) {
         destroy_test = true;
+      }
     }
 
     if (destroy_test) {
-      CefPostTask(TID_UI, base::Bind(&PopupNavTestHandler::DestroyTest, this));
+      CefPostTask(TID_UI,
+                  base::BindOnce(&PopupNavTestHandler::DestroyTest, this));
     }
   }
 
@@ -749,7 +771,7 @@
 
 namespace {
 
-const char kResolveOrigin[] = "http://www.google.com";
+const char kResolveOrigin[] = "https://www.google.com";
 
 class MethodTestHandler : public TestHandler {
  public:
@@ -800,7 +822,7 @@
       : global_context_(global_context), method_(method) {}
 
   void RunTest() override {
-    const char kUrl[] = "http://tests/method.html";
+    const char kUrl[] = "https://tests/method.html";
 
     AddResource(kUrl, "<html><body>Method</body></html>", "text/html");
 
@@ -823,12 +845,13 @@
         browser->GetHost()->GetRequestContext();
     CefRefPtr<CompletionCallback> callback =
         new CompletionCallback(this, browser);
-    if (method_ == METHOD_CLEAR_CERTIFICATE_EXCEPTIONS)
+    if (method_ == METHOD_CLEAR_CERTIFICATE_EXCEPTIONS) {
       context->ClearCertificateExceptions(callback);
-    else if (method_ == METHOD_CLOSE_ALL_CONNECTIONS)
+    } else if (method_ == METHOD_CLOSE_ALL_CONNECTIONS) {
       context->CloseAllConnections(callback);
-    else if (method_ == METHOD_RESOLVE_HOST)
+    } else if (method_ == METHOD_RESOLVE_HOST) {
       context->ResolveHost(kResolveOrigin, callback);
+    }
   }
 
   void OnCompleteCallback(CefRefPtr<CefBrowser> browser) {
diff --git a/src/tests/ceftests/request_handler_unittest.cc b/src/tests/ceftests/request_handler_unittest.cc
index 37aa65b..2bd1b56 100644
--- a/src/tests/ceftests/request_handler_unittest.cc
+++ b/src/tests/ceftests/request_handler_unittest.cc
@@ -4,12 +4,12 @@
 
 #include <algorithm>
 #include <cmath>
+#include <memory>
 #include <sstream>
 #include <string>
 #include <vector>
 
-#include "include/base/cef_bind.h"
-#include "include/base/cef_scoped_ptr.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_cookie.h"
 #include "include/cef_request_context_handler.h"
 #include "include/wrapper/cef_closure_task.h"
@@ -32,8 +32,8 @@
   NNTT_DELAYED_BROWSER,
 };
 
-const char kNetNotifyOrigin1[] = "http://tests-netnotify1/";
-const char kNetNotifyOrigin2[] = "http://tests-netnotify2/";
+const char kNetNotifyOrigin1[] = "https://tests-netnotify1/";
+const char kNetNotifyOrigin2[] = "https://tests-netnotify2/";
 const char kNetNotifyMsg[] = "RequestHandlerTest.NetNotify";
 const char kNetNotifyTestCmdKey[] = "rh-net-notify-test";
 
@@ -61,7 +61,7 @@
         "<head><script>document.cookie='name1=value1';</script></head>"
         "<body>Nav1</body>"
         "</html>";
-    response_length1_ = static_cast<int64>(resource1.size());
+    response_length1_ = static_cast<int64_t>(resource1.size());
     AddResource(url1_, resource1, "text/html");
 
     const std::string& resource2 =
@@ -69,7 +69,7 @@
         "<head><script>document.cookie='name2=value2';</script></head>"
         "<body>Nav2</body>"
         "</html>";
-    response_length2_ = static_cast<int64>(resource2.size());
+    response_length2_ = static_cast<int64_t>(resource2.size());
     AddResource(url2_, resource2, "text/html");
 
     // Create the request context that will use an in-memory cache.
@@ -97,16 +97,21 @@
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) override {
+      CefRefPtr<CefCallback> callback) override {
     EXPECT_TRUE(CefCurrentlyOn(TID_IO));
 
     const std::string& url = request->GetURL();
-    if (url.find(url1_) == 0)
+    if (IgnoreURL(url)) {
+      return RV_CONTINUE;
+    }
+
+    if (url.find(url1_) == 0) {
       got_before_resource_load1_.yes();
-    else if (url.find(url2_) == 0)
+    } else if (url.find(url2_) == 0) {
       got_before_resource_load2_.yes();
-    else
+    } else {
       EXPECT_TRUE(false);  // Not reached
+    }
 
     return RV_CONTINUE;
   }
@@ -118,12 +123,17 @@
     EXPECT_TRUE(CefCurrentlyOn(TID_IO));
 
     const std::string& url = request->GetURL();
-    if (url.find(url1_) == 0)
+    if (IgnoreURL(url)) {
+      return nullptr;
+    }
+
+    if (url.find(url1_) == 0) {
       got_get_resource_handler1_.yes();
-    else if (url.find(url2_) == 0)
+    } else if (url.find(url2_) == 0) {
       got_get_resource_handler2_.yes();
-    else
+    } else {
       EXPECT_TRUE(false);  // Not reached
+    }
 
     return TestHandler::GetResourceHandler(browser, frame, request);
   }
@@ -133,11 +143,15 @@
                               CefRefPtr<CefRequest> request,
                               CefRefPtr<CefResponse> response,
                               URLRequestStatus status,
-                              int64 received_content_length) override {
+                              int64_t received_content_length) override {
     EXPECT_TRUE(CefCurrentlyOn(TID_IO));
-    EXPECT_EQ(UR_SUCCESS, status);
 
     const std::string& url = request->GetURL();
+    if (IgnoreURL(url)) {
+      return;
+    }
+
+    EXPECT_EQ(UR_SUCCESS, status);
     if (url.find(url1_) == 0) {
       got_resource_load_complete1_.yes();
       EXPECT_EQ(response_length1_, received_content_length);
@@ -259,13 +273,15 @@
 
  protected:
   void SetupCompleteIfDone() {
-    if (got_load_end1_ && got_process_message1_)
+    if (got_load_end1_ && got_process_message1_) {
       SetupComplete();
+    }
   }
 
   void FinishTestIfDone() {
-    if (got_load_end2_ && got_process_message2_)
+    if (got_load_end2_ && got_process_message2_) {
       FinishTest();
+    }
   }
 
   void FinishTest() {
@@ -275,8 +291,8 @@
       explicit TestVisitor(NetNotifyTestHandler* handler) : handler_(handler) {}
       ~TestVisitor() override {
         // Destroy the test.
-        CefPostTask(TID_UI,
-                    base::Bind(&NetNotifyTestHandler::DestroyTest, handler_));
+        CefPostTask(TID_UI, base::BindOnce(&NetNotifyTestHandler::DestroyTest,
+                                           handler_));
       }
 
       bool Visit(const CefCookie& cookie,
@@ -377,8 +393,8 @@
   TrackCallback got_before_browse2_delayed_;
   int got_process_terminated_ct_ = 0;
 
-  int64 response_length1_;
-  int64 response_length2_;
+  int64_t response_length1_;
+  int64_t response_length2_;
 
   IMPLEMENT_REFCOUNTING(NetNotifyTestHandler);
 };
@@ -392,21 +408,23 @@
   void OnBrowserCreated(CefRefPtr<ClientAppRenderer> app,
                         CefRefPtr<CefBrowser> browser,
                         CefRefPtr<CefDictionaryValue> extra_info) override {
-    run_test_ = extra_info->HasKey(kNetNotifyTestCmdKey);
+    run_test_ = extra_info && extra_info->HasKey(kNetNotifyTestCmdKey);
   }
 
   CefRefPtr<CefLoadHandler> GetLoadHandler(
       CefRefPtr<ClientAppRenderer> app) override {
-    if (run_test_)
+    if (run_test_) {
       return this;
+    }
     return nullptr;
   }
 
   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
                  CefRefPtr<CefFrame> frame,
                  int httpStatusCode) override {
-    if (!run_test_)
+    if (!run_test_) {
       return;
+    }
 
     const std::string& url = frame->GetURL();
 
@@ -458,7 +476,7 @@
   for (size_t i = 0U; i < count; ++i) {
     CefRefPtr<NetNotifyTestHandler> handler =
         new NetNotifyTestHandler(&completion_state, test_type, same_origin);
-    collection.AddTestHandler(handler);
+    collection.AddTestHandler(handler.get());
     handlers.push_back(handler);
   }
 
diff --git a/src/tests/ceftests/request_unittest.cc b/src/tests/ceftests/request_unittest.cc
index 653c032..b218352 100644
--- a/src/tests/ceftests/request_unittest.cc
+++ b/src/tests/ceftests/request_unittest.cc
@@ -4,7 +4,7 @@
 
 #include <map>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_request.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "tests/ceftests/test_handler.h"
@@ -21,7 +21,7 @@
   EXPECT_TRUE(request.get() != nullptr);
   EXPECT_EQ(0U, request->GetIdentifier());
 
-  CefString url = "http://tests.com/run.html";
+  CefString url = "https://tests.com/run.html";
   CefString method = "POST";
   CefRequest::HeaderMap setHeaders, getHeaders;
   setHeaders.insert(std::make_pair("HeaderA", "ValueA"));
@@ -72,10 +72,11 @@
   postData->GetElements(elements);
   CefPostData::ElementVector::const_iterator it = elements.begin();
   for (size_t i = 0; it != elements.end(); ++it, ++i) {
-    if (i == 0)
+    if (i == 0) {
       TestPostDataElementEqual(element1, (*it).get());
-    else if (i == 1)
+    } else if (i == 1) {
       TestPostDataElementEqual(element2, (*it).get());
+    }
   }
 
   // CefRequest SetURL
@@ -87,10 +88,10 @@
   EXPECT_EQ(method, request->GetMethod());
 
   // CefRequest SetReferrer
-  CefString referrer = "http://tests.com/referrer.html";
+  CefString referrer = "https://tests.com/referrer.html";
   CefRequest::ReferrerPolicy policy = REFERRER_POLICY_ORIGIN;
   request->SetReferrer(referrer, policy);
-  EXPECT_STREQ("http://tests.com/",
+  EXPECT_STREQ("https://tests.com/",
                request->GetReferrerURL().ToString().c_str());
   EXPECT_EQ(policy, request->GetReferrerPolicy());
 
@@ -187,7 +188,7 @@
 
 namespace {
 
-const char kTestUrl[] = "http://tests.com/run.html";
+const char kTestUrl[] = "https://tests.com/run.html";
 
 void CreateRequest(CefRefPtr<CefRequest>& request) {
   request = CefRequest::Create();
@@ -196,7 +197,7 @@
   request->SetURL(kTestUrl);
   request->SetMethod("POST");
 
-  request->SetReferrer("http://tests.com/main.html", REFERRER_POLICY_DEFAULT);
+  request->SetReferrer("https://tests.com/main.html", REFERRER_POLICY_DEFAULT);
 
   CefRequest::HeaderMap headers;
   headers.insert(std::make_pair("HeaderA", "ValueA"));
@@ -224,7 +225,7 @@
     CreateRequest(request_);
 
     const std::string& resource = "<html><body>SendRecv Test</body></html>";
-    response_length_ = static_cast<int64>(resource.size());
+    response_length_ = static_cast<int64_t>(resource.size());
     AddResource(kTestUrl, resource, "text/html");
 
     // Create the browser.
@@ -245,7 +246,7 @@
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) override {
+      CefRefPtr<CefCallback> callback) override {
     EXPECT_IO_THREAD();
 
     request_id_ = request->GetIdentifier();
@@ -310,9 +311,14 @@
                               CefRefPtr<CefRequest> request,
                               CefRefPtr<CefResponse> response,
                               URLRequestStatus status,
-                              int64 received_content_length) override {
+                              int64_t received_content_length) override {
     EXPECT_IO_THREAD();
 
+    if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
+      // Ignore favicon requests.
+      return;
+    }
+
     TestRequest(request);
     EXPECT_TRUE(request->IsReadOnly());
     TestResponse(response);
@@ -350,8 +356,8 @@
   }
 
   CefRefPtr<CefRequest> request_;
-  int64 response_length_;
-  uint64 request_id_;
+  int64_t response_length_;
+  uint64_t request_id_;
 
   TrackCallback got_before_resource_load_;
   TrackCallback got_resource_handler_;
@@ -374,7 +380,7 @@
 
 namespace {
 
-const char kTypeTestOrigin[] = "http://tests-requesttt.com/";
+const char kTypeTestOrigin[] = "https://tests-requesttt.com/";
 const cef_transition_type_t kTransitionExplicitLoad =
     static_cast<cef_transition_type_t>(TT_EXPLICIT | TT_DIRECT_LOAD_FLAG);
 
@@ -414,8 +420,9 @@
     for (int i = 0;
          i < static_cast<int>(sizeof(g_type_expected) / sizeof(TypeExpected));
          ++i) {
-      if (navigation_ && g_type_expected[i].navigation != navigation_)
+      if (navigation_ && g_type_expected[i].navigation != navigation_) {
         continue;
+      }
 
       request_count_.insert(std::make_pair(i, 0));
     }
@@ -425,8 +432,9 @@
   // something we care about.
   bool GotRequest(CefRefPtr<CefRequest> request) {
     const std::string& url = request->GetURL();
-    if (url.find(kTypeTestOrigin) != 0)
+    if (url.find(kTypeTestOrigin) != 0) {
       return false;
+    }
 
     const std::string& file = url.substr(sizeof(kTypeTestOrigin) - 1);
     cef_transition_type_t transition_type = request->GetTransitionType();
@@ -456,8 +464,9 @@
     for (int i = 0;
          i < static_cast<int>(sizeof(g_type_expected) / sizeof(TypeExpected));
          ++i) {
-      if (navigation_ && g_type_expected[i].navigation != navigation_)
+      if (navigation_ && g_type_expected[i].navigation != navigation_) {
         continue;
+      }
 
       RequestCount::const_iterator it = request_count_.find(i);
       EXPECT_TRUE(it != request_count_.end());
@@ -567,7 +576,7 @@
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) override {
+      CefRefPtr<CefCallback> callback) override {
     load_expectations_.GotRequest(request);
 
     return RV_CONTINUE;
@@ -581,7 +590,7 @@
         get_expectations_.IsDone(false)) {
       completed_browser_side_ = true;
       // Destroy the test on the UI thread.
-      CefPostTask(TID_UI, base::Bind(&TypeTestHandler::DestroyTest, this));
+      CefPostTask(TID_UI, base::BindOnce(&TypeTestHandler::DestroyTest, this));
     }
 
     return TestHandler::GetResourceHandler(browser, frame, request);
@@ -589,8 +598,9 @@
 
  private:
   void DestroyTest() override {
-    if (destroyed_)
+    if (destroyed_) {
       return;
+    }
     destroyed_ = true;
 
     // Verify test expectations.
diff --git a/src/tests/ceftests/resource_manager_unittest.cc b/src/tests/ceftests/resource_manager_unittest.cc
index fff45e7..be68269 100644
--- a/src/tests/ceftests/resource_manager_unittest.cc
+++ b/src/tests/ceftests/resource_manager_unittest.cc
@@ -2,9 +2,11 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
+#include <memory>
 #include <vector>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
+#include "include/base/cef_lock.h"
 #include "include/cef_file_util.h"
 #include "include/cef_waitable_event.h"
 #include "include/wrapper/cef_closure_task.h"
@@ -12,6 +14,7 @@
 #include "include/wrapper/cef_scoped_temp_dir.h"
 #include "include/wrapper/cef_stream_resource_handler.h"
 #include "tests/ceftests/routing_test_handler.h"
+#include "tests/ceftests/test_util.h"
 #include "tests/gtest/include/gtest/gtest.h"
 #include "tests/shared/browser/file_util.h"
 
@@ -81,14 +84,19 @@
     // Create the browser.
     CreateBrowser(GetNextURL());
 
-    SetTestTimeout();
+    SetTestTimeout(5000);
   }
 
   cef_return_value_t OnBeforeResourceLoad(
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) override {
+      CefRefPtr<CefCallback> callback) override {
+    if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
+      // Ignore favicon requests.
+      return RV_CANCEL;
+    }
+
     return state_->manager_->OnBeforeResourceLoad(browser, frame, request,
                                                   callback);
   }
@@ -101,8 +109,9 @@
     if (state_->manager_) {
       CefRefPtr<CefResourceHandler> handler =
           state_->manager_->GetResourceHandler(browser, frame, request);
-      if (handler.get())
+      if (handler.get()) {
         return handler;
+      }
     }
 
     return CreateContentsResourceHandler(CreateMessage(kDoneMsg, kNotHandled));
@@ -110,15 +119,15 @@
 
   bool OnQuery(CefRefPtr<CefBrowser> browser,
                CefRefPtr<CefFrame> frame,
-               int64 query_id,
+               int64_t query_id,
                const CefString& request,
                bool persistent,
                CefRefPtr<Callback> callback) override {
     state_->messages_.push_back(request);
     callback->Success("");
 
-    CefPostTask(TID_UI, base::Bind(&ResourceManagerTestHandler::Continue, this,
-                                   browser));
+    CefPostTask(TID_UI, base::BindOnce(&ResourceManagerTestHandler::Continue,
+                                       this, browser));
 
     return true;
   }
@@ -126,7 +135,7 @@
   // Wait a bit before destroying the test. Used with ProviderDoNothing.
   void DelayedDestroyTest() {
     CefPostDelayedTask(
-        TID_UI, base::Bind(&ResourceManagerTestHandler::DestroyTest, this),
+        TID_UI, base::BindOnce(&ResourceManagerTestHandler::DestroyTest, this),
         100);
   }
 
@@ -135,18 +144,20 @@
     if (state_->expected_message_ct_ == 0) {
       // Load each URL sequentially.
       const std::string& next_url = GetNextURL();
-      if (next_url.empty())
+      if (next_url.empty()) {
         DestroyTest();
-      else
+      } else {
         browser->GetMainFrame()->LoadURL(next_url);
+      }
     } else if (state_->messages_.size() == state_->expected_message_ct_) {
       DestroyTest();
     }
   }
 
   std::string GetNextURL() {
-    if (current_url_ >= state_->urls_.size())
+    if (current_url_ >= state_->urls_.size()) {
       return std::string();
+    }
     return state_->urls_[current_url_++];
   }
 
@@ -160,7 +171,7 @@
 
 // Test with no providers.
 TEST(ResourceManagerTest, NoProviders) {
-  const char kUrl[] = "http://test.com/ResourceManagerTest";
+  const char kUrl[] = "https://test.com/ResourceManagerTest";
 
   ResourceManagerTestHandler::State state;
   state.urls_.push_back(kUrl);
@@ -188,7 +199,7 @@
     TrackCallback got_on_request_;
     TrackCallback got_on_request_canceled_;
     TrackCallback got_destruct_;
-    base::Closure destruct_callback_;
+    base::OnceClosure destruct_callback_;
     std::string request_url_;
   };
 
@@ -197,8 +208,9 @@
   ~TestProvider() {
     CEF_REQUIRE_IO_THREAD();
     state_->got_destruct_.yes();
-    if (!state_->destruct_callback_.is_null())
-      state_->destruct_callback_.Run();
+    if (!state_->destruct_callback_.is_null()) {
+      std::move(state_->destruct_callback_).Run();
+    }
   }
 
   bool OnRequest(scoped_refptr<CefResourceManager::Request> request) override {
@@ -231,33 +243,50 @@
 // Helper that blocks on destruction of 1 or more TestProviders.
 class ProviderDestructHelper {
  public:
-  explicit ProviderDestructHelper(int expected_count) : current_count_(0) {
-    event_ = CefWaitableEvent::CreateWaitableEvent(true, false);
-    callback_ =
-        base::Bind(&DestructCallback, expected_count, &current_count_, event_);
+  explicit ProviderDestructHelper(int expected_count)
+      : expected_count_(expected_count),
+        event_(CefWaitableEvent::CreateWaitableEvent(true, false)) {
+    CHECK_GT(expected_count_, 0);
   }
 
-  const base::Closure& callback() const { return callback_; }
+  base::OnceClosure callback() {
+    return base::BindOnce(
+        [](ProviderDestructHelper* self) { self->DestructCallback(); },
+        base::Unretained(this));
+  }
 
   void Wait() { event_->Wait(); }
 
  private:
-  static void DestructCallback(int expected_count,
-                               int* current_count,
-                               CefRefPtr<CefWaitableEvent> event) {
-    if (++(*current_count) == expected_count)
+  void DestructCallback() {
+    bool signal = false;
+
+    {
+      base::AutoLock lock_scope(lock_);
+      CHECK_LT(current_count_, expected_count_);
+      if (++current_count_ == expected_count_) {
+        signal = true;
+      }
+    }
+
+    if (signal) {
+      // Don't access any members after calling Signal(), which causes |this| to
+      // be deleted on a different thread.
+      auto event = event_;
       event->Signal();
+    }
   }
 
-  int current_count_;
+  const int expected_count_;
+  int current_count_ = 0;
   CefRefPtr<CefWaitableEvent> event_;
-  base::Closure callback_;
+  base::Lock lock_;
 };
 
 // Test that that the URL retrieved via Request::url() is parsed as expected.
 // Fragment or query components in any order should be removed.
 void TestUrlParsing(const char* kUrl) {
-  const char kRequestUrl[] = "http://test.com/ResourceManagerTest";
+  const char kRequestUrl[] = "https://test.com/ResourceManagerTest";
 
   ResourceManagerTestHandler::State state;
   state.urls_.push_back(kUrl);
@@ -297,23 +326,23 @@
 }  // namespace
 
 TEST(ResourceManagerTest, UrlParsingNoQueryOrFragment) {
-  TestUrlParsing("http://test.com/ResourceManagerTest");
+  TestUrlParsing("https://test.com/ResourceManagerTest");
 }
 
 TEST(ResourceManagerTest, UrlParsingWithQuery) {
-  TestUrlParsing("http://test.com/ResourceManagerTest?foo=bar&choo=too");
+  TestUrlParsing("https://test.com/ResourceManagerTest?foo=bar&choo=too");
 }
 
 TEST(ResourceManagerTest, UrlParsingWithFragment) {
-  TestUrlParsing("http://test.com/ResourceManagerTest#some/fragment");
+  TestUrlParsing("https://test.com/ResourceManagerTest#some/fragment");
 }
 
 TEST(ResourceManagerTest, UrlParsingWithQueryAndFragment) {
-  TestUrlParsing("http://test.com/ResourceManagerTest?foo=bar#some/fragment");
+  TestUrlParsing("https://test.com/ResourceManagerTest?foo=bar#some/fragment");
 }
 
 TEST(ResourceManagerTest, UrlParsingWithFragmentAndQuery) {
-  TestUrlParsing("http://test.com/ResourceManagerTest#some/fragment?foo=bar");
+  TestUrlParsing("https://test.com/ResourceManagerTest#some/fragment?foo=bar");
 }
 
 namespace {
@@ -338,29 +367,28 @@
   SimpleTestProvider(State* state,
                      Mode mode,
                      CefResourceManager* manager,
-                     base::Closure do_nothing_callback)
+                     base::OnceClosure do_nothing_callback)
       : TestProvider(state),
         mode_(mode),
         manager_(manager),
-        do_nothing_callback_(do_nothing_callback) {}
+        do_nothing_callback_(std::move(do_nothing_callback)) {}
 
   bool OnRequest(scoped_refptr<CefResourceManager::Request> request) override {
     TestProvider::OnRequest(request);
 
-    if (mode_ == NOT_HANDLED)
+    if (mode_ == NOT_HANDLED) {
       return false;
-    else if (mode_ == CONTINUE)
+    } else if (mode_ == CONTINUE) {
       request->Continue(nullptr);
-    else if (mode_ == STOP)
+    } else if (mode_ == STOP) {
       request->Stop();
-    else if (mode_ == REMOVE)
+    } else if (mode_ == REMOVE) {
       manager_->RemoveProviders(kProviderId);
-    else if (mode_ == REMOVE_ALL)
+    } else if (mode_ == REMOVE_ALL) {
       manager_->RemoveAllProviders();
-    else if (mode_ == DO_NOTHING) {
+    } else if (mode_ == DO_NOTHING) {
       EXPECT_FALSE(do_nothing_callback_.is_null());
-      do_nothing_callback_.Run();
-      do_nothing_callback_.Reset();
+      std::move(do_nothing_callback_).Run();
     }
 
     return true;
@@ -369,7 +397,7 @@
  private:
   Mode mode_;
   CefResourceManager* manager_;  // Weak reference.
-  base::Closure do_nothing_callback_;
+  base::OnceClosure do_nothing_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(SimpleTestProvider);
 };
@@ -378,7 +406,7 @@
 
 // Test with multiple providers that do not handle the request.
 TEST(ResourceManagerTest, ProviderNotHandled) {
-  const char kUrl[] = "http://test.com/ResourceManagerTest";
+  const char kUrl[] = "https://test.com/ResourceManagerTest";
 
   ResourceManagerTestHandler::State state;
   state.urls_.push_back(kUrl);
@@ -425,7 +453,7 @@
 
 // Test with multiple providers that all continue.
 TEST(ResourceManagerTest, ProviderContinue) {
-  const char kUrl[] = "http://test.com/ResourceManagerTest";
+  const char kUrl[] = "https://test.com/ResourceManagerTest";
 
   ResourceManagerTestHandler::State state;
   state.urls_.push_back(kUrl);
@@ -472,7 +500,7 @@
 
 // Test with multiple providers where the first one stops.
 TEST(ResourceManagerTest, ProviderStop) {
-  const char kUrl[] = "http://test.com/ResourceManagerTest";
+  const char kUrl[] = "https://test.com/ResourceManagerTest";
 
   ResourceManagerTestHandler::State state;
   state.urls_.push_back(kUrl);
@@ -521,7 +549,7 @@
 // Test with multiple providers where the first one removes multiple providers
 // including itself.
 TEST(ResourceManagerTest, ProviderRemove) {
-  const char kUrl[] = "http://test.com/ResourceManagerTest";
+  const char kUrl[] = "https://test.com/ResourceManagerTest";
 
   ResourceManagerTestHandler::State state;
   state.urls_.push_back(kUrl);
@@ -581,7 +609,7 @@
 
 // Test with multiple providers where the first provider removes all.
 TEST(ResourceManagerTest, ProviderRemoveAll) {
-  const char kUrl[] = "http://test.com/ResourceManagerTest";
+  const char kUrl[] = "https://test.com/ResourceManagerTest";
 
   ResourceManagerTestHandler::State state;
   state.urls_.push_back(kUrl);
@@ -640,7 +668,7 @@
 // Test with multiple providers that do not continue and will be destroyed when
 // the manager is destroyed.
 TEST(ResourceManagerTest, ProviderDoNothing) {
-  const char kUrl[] = "http://test.com/ResourceManagerTest";
+  const char kUrl[] = "https://test.com/ResourceManagerTest";
 
   ResourceManagerTestHandler::State state;
   state.urls_.push_back(kUrl);
@@ -659,7 +687,8 @@
   state.manager_->AddProvider(
       new SimpleTestProvider(
           &provider_state1, SimpleTestProvider::DO_NOTHING, nullptr,
-          base::Bind(&ResourceManagerTestHandler::DelayedDestroyTest, handler)),
+          base::BindOnce(&ResourceManagerTestHandler::DelayedDestroyTest,
+                         handler)),
       0, std::string());
   state.manager_->AddProvider(
       new SimpleTestProvider(&provider_state2, SimpleTestProvider::DO_NOTHING,
@@ -694,9 +723,9 @@
 
 // Test AddContentProvider.
 TEST(ResourceManagerTest, ContentProvider) {
-  const char kUrl1[] = "http://test.com/ResourceManagerTest1";
-  const char kUrl2[] = "http://test.com/ResourceManagerTest2";
-  const char kUrl3[] = "http://test.com/ResourceManagerTest3";
+  const char kUrl1[] = "https://test.com/ResourceManagerTest1";
+  const char kUrl2[] = "https://test.com/ResourceManagerTest2";
+  const char kUrl3[] = "https://test.com/ResourceManagerTest3";
 
   const std::string& success1_message = CreateMessage(kDoneMsg, "Success1");
   const std::string& success2_message = CreateMessage(kDoneMsg, "Success2");
@@ -733,7 +762,7 @@
 
 // Test AddDirectoryProvider.
 TEST(ResourceManagerTest, DirectoryProvider) {
-  const char kUrlBase[] = "http://test.com/ResourceManager";
+  const char kUrlBase[] = "https://test.com/ResourceManager";
   const char kFile1[] = "File1.html";
   const char kFile2[] = "File2.html";
   const char kFile3[] = "File3.html";
@@ -791,7 +820,7 @@
 
 // Test AddArchiveProvider.
 TEST(ResourceManagerTest, ArchiveProvider) {
-  const char kUrlBase[] = "http://test.com/ResourceManager";
+  const char kUrlBase[] = "https://test.com/ResourceManager";
   const char kFile1[] = "File1.html";
   const char kFile2[] = "File2.html";
   const char kFile3[] = "File3.html";
@@ -864,14 +893,16 @@
 class OneShotProvider : public CefResourceManager::Provider {
  public:
   OneShotProvider(const std::string& content,
-                  const base::Closure& destruct_callback)
-      : done_(false), content_(content), destruct_callback_(destruct_callback) {
+                  base::OnceClosure destruct_callback)
+      : done_(false),
+        content_(content),
+        destruct_callback_(std::move(destruct_callback)) {
     EXPECT_FALSE(content.empty());
   }
 
   ~OneShotProvider() {
     CEF_REQUIRE_IO_THREAD();
-    destruct_callback_.Run();
+    std::move(destruct_callback_).Run();
   }
 
   bool OnRequest(scoped_refptr<CefResourceManager::Request> request) override {
@@ -895,7 +926,7 @@
  private:
   bool done_;
   std::string content_;
-  base::Closure destruct_callback_;
+  base::OnceClosure destruct_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(OneShotProvider);
 };
@@ -905,11 +936,11 @@
 // Test that providers are called in the expected order and return expected
 // results.
 TEST(ResourceManagerTest, ProviderOrder) {
-  const char kUrl1[] = "http://test.com/ResourceManagerTest1";
-  const char kUrl2[] = "http://test.com/ResourceManagerTest2";
-  const char kUrl3[] = "http://test.com/ResourceManagerTest3";
-  const char kUrl4[] = "http://test.com/ResourceManagerTest4";
-  const char kUrl5[] = "http://test.com/ResourceManagerTest5";
+  const char kUrl1[] = "https://test.com/ResourceManagerTest1";
+  const char kUrl2[] = "https://test.com/ResourceManagerTest2";
+  const char kUrl3[] = "https://test.com/ResourceManagerTest3";
+  const char kUrl4[] = "https://test.com/ResourceManagerTest4";
+  const char kUrl5[] = "https://test.com/ResourceManagerTest5";
 
   const std::string& success1_message = CreateMessage(kDoneMsg, "Success1");
   const std::string& success2_message = CreateMessage(kDoneMsg, "Success2");
@@ -991,11 +1022,12 @@
         static_cast<void*>(const_cast<char*>(content.data())),
         content.length());
 
-    CefPostDelayedTask(
-        TID_IO,
-        base::Bind(&CefResourceManager::Request::Continue, request,
-                   new CefStreamResourceHandler("text/html", stream)),
-        delay);
+    CefRefPtr<CefStreamResourceHandler> handler(
+        new CefStreamResourceHandler("text/html", stream));
+    CefPostDelayedTask(TID_IO,
+                       base::BindOnce(&CefResourceManager::Request::Continue,
+                                      request, handler),
+                       delay);
 
     return true;
   }
@@ -1011,8 +1043,8 @@
 // Test that many requests pending at the same time complete in the expected
 // order and return correct results.
 TEST(ResourceManagerTest, ManyRequests) {
-  const char kUrl[] = "http://test.com/ResourceManagerTest";
-  const char kBaseUrl[] = "http://test.com/ResourceManagerSubTest/";
+  const char kUrl[] = "https://test.com/ResourceManagerTest";
+  const char kBaseUrl[] = "https://test.com/ResourceManagerSubTest/";
 
   ResourceManagerTestHandler::State state;
   state.urls_.push_back(kUrl);
@@ -1081,20 +1113,22 @@
     if (remove_before_continue_) {
       // Removing the provider before continuing should trigger a call to
       // OnRequestCanceled.
-      if (identifier_.empty())
+      if (identifier_.empty()) {
         manager_->RemoveAllProviders();
-      else
+      } else {
         manager_->RemoveProviders(identifier_);
+      }
     }
 
     request->Continue(new CefStreamResourceHandler("text/html", stream));
 
     if (!remove_before_continue_) {
       // The request has already completed so OnRequestCanceled is not called.
-      if (identifier_.empty())
+      if (identifier_.empty()) {
         manager_->RemoveAllProviders();
-      else
+      } else {
         manager_->RemoveProviders(identifier_);
+      }
     }
 
     return true;
@@ -1114,10 +1148,10 @@
 // Test that removal of the current provider after continue has the expected
 // results.
 TEST(ResourceManagerTest, RemoveProviderAfterContinue) {
-  const char kUrl1[] = "http://test.com/ResourceManagerTest1";
-  const char kUrl2[] = "http://test.com/ResourceManagerTest2";
-  const char kUrl3[] = "http://test.com/ResourceManagerTest3";
-  const char kUrl4[] = "http://test.com/ResourceManagerTest4";
+  const char kUrl1[] = "https://test.com/ResourceManagerTest1";
+  const char kUrl2[] = "https://test.com/ResourceManagerTest2";
+  const char kUrl3[] = "https://test.com/ResourceManagerTest3";
+  const char kUrl4[] = "https://test.com/ResourceManagerTest4";
 
   const std::string& success1_message = CreateMessage(kDoneMsg, "Success1");
   const std::string& success2_message = CreateMessage(kDoneMsg, "Success2");
@@ -1209,10 +1243,10 @@
 // Test that removal of the current provider before continue has the expected
 // results.
 TEST(ResourceManagerTest, RemoveProviderBeforeContinue) {
-  const char kUrl1[] = "http://test.com/ResourceManagerTest1";
-  const char kUrl2[] = "http://test.com/ResourceManagerTest2";
-  const char kUrl3[] = "http://test.com/ResourceManagerTest3";
-  const char kUrl4[] = "http://test.com/ResourceManagerTest4";
+  const char kUrl1[] = "https://test.com/ResourceManagerTest1";
+  const char kUrl2[] = "https://test.com/ResourceManagerTest2";
+  const char kUrl3[] = "https://test.com/ResourceManagerTest3";
+  const char kUrl4[] = "https://test.com/ResourceManagerTest4";
 
   const std::string& success1_message = CreateMessage(kDoneMsg, "Success1");
   const std::string& success2_message = CreateMessage(kDoneMsg, "Success2");
@@ -1302,10 +1336,10 @@
 
 // Test that removal of all providers after continue has the expected results.
 TEST(ResourceManagerTest, RemoveAllProvidersAfterContinue) {
-  const char kUrl1[] = "http://test.com/ResourceManagerTest1";
-  const char kUrl2[] = "http://test.com/ResourceManagerTest2";
-  const char kUrl3[] = "http://test.com/ResourceManagerTest3";
-  const char kUrl4[] = "http://test.com/ResourceManagerTest4";
+  const char kUrl1[] = "https://test.com/ResourceManagerTest1";
+  const char kUrl2[] = "https://test.com/ResourceManagerTest2";
+  const char kUrl3[] = "https://test.com/ResourceManagerTest3";
+  const char kUrl4[] = "https://test.com/ResourceManagerTest4";
 
   const std::string& success1_message = CreateMessage(kDoneMsg, "Success1");
   const std::string& success2_message = CreateMessage(kDoneMsg, "Success2");
@@ -1390,10 +1424,10 @@
 
 // Test that removal of all providers before continue has the expected results.
 TEST(ResourceManagerTest, RemoveAllProvidersBeforeContinue) {
-  const char kUrl1[] = "http://test.com/ResourceManagerTest1";
-  const char kUrl2[] = "http://test.com/ResourceManagerTest2";
-  const char kUrl3[] = "http://test.com/ResourceManagerTest3";
-  const char kUrl4[] = "http://test.com/ResourceManagerTest4";
+  const char kUrl1[] = "https://test.com/ResourceManagerTest1";
+  const char kUrl2[] = "https://test.com/ResourceManagerTest2";
+  const char kUrl3[] = "https://test.com/ResourceManagerTest3";
+  const char kUrl4[] = "https://test.com/ResourceManagerTest4";
 
   const std::string& success1_message = CreateMessage(kDoneMsg, "Success1");
   const std::string& success2_message = CreateMessage(kDoneMsg, "Success2");
@@ -1517,16 +1551,18 @@
 // Add to the URL but keep the query component.
 std::string TestUrlFilterWithQuery(const std::string& url) {
   size_t pos = url.find('?');
-  if (pos == std::string::npos)
+  if (pos == std::string::npos) {
     return url;
+  }
   return url.substr(0, pos) + "Rewrite" + url.substr(pos);
 }
 
 // Add to the URL but keep the fragment component.
 std::string TestUrlFilterWithFragment(const std::string& url) {
   size_t pos = url.find('#');
-  if (pos == std::string::npos)
+  if (pos == std::string::npos) {
     return url;
+  }
   return url.substr(0, pos) + "Rewrite" + url.substr(pos);
 }
 
@@ -1534,14 +1570,14 @@
 
 // Test the URL filter capability.
 TEST(ResourceManagerTest, UrlFilter) {
-  const char kUrl[] = "http://test.com/ResourceManagerTest";
-  const char kExpectedUrl[] = "http://test.com/ResourceManagerTestRewrite";
+  const char kUrl[] = "https://test.com/ResourceManagerTest";
+  const char kExpectedUrl[] = "https://test.com/ResourceManagerTestRewrite";
 
   ResourceManagerTestHandler::State state;
   state.urls_.push_back(kUrl);
 
   // Set the URL filter.
-  state.manager_->SetUrlFilter(base::Bind(TestUrlFilter));
+  state.manager_->SetUrlFilter(base::BindRepeating(TestUrlFilter));
 
   TestProvider::State provider_state1;
   TestProvider::State provider_state2;
@@ -1583,16 +1619,16 @@
 
 // Test the URL filter capability with a query component.
 TEST(ResourceManagerTest, UrlFilterWithQuery) {
-  const char kUrl[] = "http://test.com/ResourceManagerTest?foo=bar";
-  const char kExpectedUrl[] = "http://test.com/ResourceManagerTestRewrite";
+  const char kUrl[] = "https://test.com/ResourceManagerTest?foo=bar";
+  const char kExpectedUrl[] = "https://test.com/ResourceManagerTestRewrite";
   const char kExpectedUrlAfterFilter[] =
-      "http://test.com/ResourceManagerTestRewrite?foo=bar";
+      "https://test.com/ResourceManagerTestRewrite?foo=bar";
 
   ResourceManagerTestHandler::State state;
   state.urls_.push_back(kUrl);
 
   // Set the URL filter.
-  state.manager_->SetUrlFilter(base::Bind(TestUrlFilterWithQuery));
+  state.manager_->SetUrlFilter(base::BindRepeating(TestUrlFilterWithQuery));
 
   TestProvider::State provider_state1;
   TestProvider::State provider_state2;
@@ -1637,16 +1673,16 @@
 // Test the URL filter capability with a fragment component.
 TEST(ResourceManagerTest, UrlFilterWithFragment) {
   // Fragment components will not be passed with the request.
-  const char kUrl[] = "http://test.com/ResourceManagerTest#fragment";
-  const char kExpectedUrl[] = "http://test.com/ResourceManagerTestRewrite";
+  const char kUrl[] = "https://test.com/ResourceManagerTest#fragment";
+  const char kExpectedUrl[] = "https://test.com/ResourceManagerTestRewrite";
   const char kExpectedUrlAfterFilter[] =
-      "http://test.com/ResourceManagerTestRewrite#fragment";
+      "https://test.com/ResourceManagerTestRewrite#fragment";
 
   ResourceManagerTestHandler::State state;
   state.urls_.push_back(kUrl);
 
   // Set the URL filter.
-  state.manager_->SetUrlFilter(base::Bind(TestUrlFilterWithFragment));
+  state.manager_->SetUrlFilter(base::BindRepeating(TestUrlFilterWithFragment));
 
   TestProvider::State provider_state1;
   TestProvider::State provider_state2;
@@ -1722,13 +1758,14 @@
 
 // Test the mime type resolver capability.
 TEST(ResourceManagerTest, MimeTypeResolver) {
-  const char kUrl[] = "http://test.com/ResourceManagerTest";
+  const char kUrl[] = "https://test.com/ResourceManagerTest";
 
   ResourceManagerTestHandler::State state;
   state.urls_.push_back(kUrl);
 
   // Set the mime type resolver.
-  state.manager_->SetMimeTypeResolver(base::Bind(TestMimeTypeResolver));
+  state.manager_->SetMimeTypeResolver(
+      base::BindRepeating(TestMimeTypeResolver));
 
   TestProvider::State provider_state1;
   TestProvider::State provider_state2;
@@ -1807,7 +1844,7 @@
 
 // Test adding a new provider after the current provider.
 TEST(ResourceManagerTest, AddProviderAfter) {
-  const char kUrl[] = "http://test.com/ResourceManagerTest";
+  const char kUrl[] = "https://test.com/ResourceManagerTest";
 
   ResourceManagerTestHandler::State state;
   state.urls_.push_back(kUrl);
@@ -1850,7 +1887,7 @@
 
 // Test adding a new provider before the current provider.
 TEST(ResourceManagerTest, AddProviderBefore) {
-  const char kUrl[] = "http://test.com/ResourceManagerTest";
+  const char kUrl[] = "https://test.com/ResourceManagerTest";
 
   ResourceManagerTestHandler::State state;
   state.urls_.push_back(kUrl);
diff --git a/src/tests/ceftests/resource_request_handler_unittest.cc b/src/tests/ceftests/resource_request_handler_unittest.cc
index 300692f..9212cee 100644
--- a/src/tests/ceftests/resource_request_handler_unittest.cc
+++ b/src/tests/ceftests/resource_request_handler_unittest.cc
@@ -4,11 +4,11 @@
 
 #include <algorithm>
 #include <cmath>
+#include <memory>
 #include <sstream>
 #include <string>
 
-#include "include/base/cef_bind.h"
-#include "include/base/cef_scoped_ptr.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_request_context_handler.h"
 #include "include/cef_scheme.h"
 #include "include/wrapper/cef_closure_task.h"
@@ -30,17 +30,17 @@
                         const CefString& mime_type,
                         CefResponse::HeaderMap header_map,
                         CefRefPtr<CefStreamReader> stream,
-                        const base::Closure& destroy_callback)
+                        base::OnceClosure destroy_callback)
       : CefStreamResourceHandler(status_code,
                                  status_text,
                                  mime_type,
                                  header_map,
                                  stream),
-        destroy_callback_(destroy_callback) {}
+        destroy_callback_(std::move(destroy_callback)) {}
 
   ~NormalResourceHandler() override {
     EXPECT_EQ(1, cancel_ct_);
-    destroy_callback_.Run();
+    std::move(destroy_callback_).Run();
   }
 
   void Cancel() override {
@@ -49,7 +49,7 @@
   }
 
  private:
-  const base::Closure destroy_callback_;
+  base::OnceClosure destroy_callback_;
   int cancel_ct_ = 0;
 };
 
@@ -88,21 +88,21 @@
                           const CefString& mime_type,
                           CefResponse::HeaderMap header_map,
                           CefRefPtr<CefStreamReader> stream,
-                          const base::Closure& destroy_callback)
+                          base::OnceClosure destroy_callback)
       : mode_(mode),
         status_code_(status_code),
         status_text_(status_text),
         mime_type_(mime_type),
         header_map_(header_map),
         stream_(stream),
-        destroy_callback_(destroy_callback) {
+        destroy_callback_(std::move(destroy_callback)) {
     DCHECK(!mime_type_.empty());
     DCHECK(stream_.get());
   }
 
   ~CallbackResourceHandler() override {
     EXPECT_EQ(1, cancel_ct_);
-    destroy_callback_.Run();
+    std::move(destroy_callback_).Run();
   }
 
   bool Open(CefRefPtr<CefRequest> request,
@@ -113,7 +113,7 @@
     if (IsDelayedOpen()) {
       // Continue the request asynchronously by executing the callback.
       CefPostTask(TID_FILE_USER_VISIBLE,
-                  base::Bind(&CefCallback::Continue, callback));
+                  base::BindOnce(&CefCallback::Continue, callback));
       handle_request = false;
       return true;
     } else if (IsImmediateOpen()) {
@@ -129,14 +129,15 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
     response->SetStatus(status_code_);
     response->SetStatusText(status_text_);
     response->SetMimeType(mime_type_);
 
-    if (!header_map_.empty())
+    if (!header_map_.empty()) {
       response->SetHeaderMap(header_map_);
+    }
 
     response_length = -1;
   }
@@ -153,8 +154,8 @@
     if (IsDelayedRead()) {
       // Continue the request asynchronously by executing the callback.
       CefPostTask(TID_FILE_USER_VISIBLE,
-                  base::Bind(&CallbackResourceHandler::ContinueRead, this,
-                             data_out, bytes_to_read, callback));
+                  base::BindOnce(&CallbackResourceHandler::ContinueRead, this,
+                                 data_out, bytes_to_read, callback));
       return true;
     } else if (IsImmediateRead()) {
       // Continue the request immediately be executing the callback.
@@ -183,7 +184,7 @@
   }
 
   bool DoRead(void* data_out, int bytes_to_read, int& bytes_read) {
-    DCHECK_GT(bytes_to_read, 0);
+    EXPECT_GT(bytes_to_read, 0);
 
     // Read until the buffer is full or until Read() returns 0 to indicate no
     // more data.
@@ -207,7 +208,7 @@
   const CefResponse::HeaderMap header_map_;
   const CefRefPtr<CefStreamReader> stream_;
 
-  const base::Closure destroy_callback_;
+  base::OnceClosure destroy_callback_;
   int cancel_ct_ = 0;
 
   IMPLEMENT_REFCOUNTING(CallbackResourceHandler);
@@ -225,10 +226,10 @@
 
   IncompleteResourceHandlerOld(TestMode test_mode,
                                const std::string& mime_type,
-                               const base::Closure& destroy_callback)
+                               base::OnceClosure destroy_callback)
       : test_mode_(test_mode),
         mime_type_(mime_type),
-        destroy_callback_(destroy_callback) {}
+        destroy_callback_(std::move(destroy_callback)) {}
 
   ~IncompleteResourceHandlerOld() override {
     EXPECT_EQ(1, process_request_ct_);
@@ -243,7 +244,7 @@
       EXPECT_EQ(0, read_response_ct_);
     }
 
-    destroy_callback_.Run();
+    std::move(destroy_callback_).Run();
   }
 
   bool ProcessRequest(CefRefPtr<CefRequest> request,
@@ -262,7 +263,7 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
     EXPECT_IO_THREAD();
     EXPECT_EQ(test_mode_, BLOCK_READ_RESPONSE);
@@ -298,7 +299,7 @@
  private:
   const TestMode test_mode_;
   const std::string mime_type_;
-  const base::Closure destroy_callback_;
+  base::OnceClosure destroy_callback_;
 
   int process_request_ct_ = 0;
   int get_response_headers_ct_ = 0;
@@ -320,10 +321,10 @@
 
   IncompleteResourceHandler(TestMode test_mode,
                             const std::string& mime_type,
-                            const base::Closure& destroy_callback)
+                            base::OnceClosure destroy_callback)
       : test_mode_(test_mode),
         mime_type_(mime_type),
-        destroy_callback_(destroy_callback) {}
+        destroy_callback_(std::move(destroy_callback)) {}
 
   ~IncompleteResourceHandler() override {
     EXPECT_EQ(1, open_ct_);
@@ -338,7 +339,7 @@
       EXPECT_EQ(0, read_ct_);
     }
 
-    destroy_callback_.Run();
+    std::move(destroy_callback_).Run();
   }
 
   bool Open(CefRefPtr<CefRequest> request,
@@ -365,7 +366,7 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
     EXPECT_IO_THREAD();
     EXPECT_EQ(test_mode_, BLOCK_READ);
@@ -410,7 +411,7 @@
  private:
   const TestMode test_mode_;
   const std::string mime_type_;
-  const base::Closure destroy_callback_;
+  base::OnceClosure destroy_callback_;
 
   int open_ct_ = 0;
   int get_response_headers_ct_ = 0;
@@ -499,7 +500,7 @@
     TestHandler::OnAfterCreated(browser);
 
     if (mode_ == ABORT_AFTER_CREATED) {
-      SetSignalCompletionWhenAllBrowsersClose(false);
+      SetSignalTestCompletionCount(1U);
       CloseBrowser(browser, false);
     }
   }
@@ -528,7 +529,13 @@
     }
     EXPECT_TRUE(frame->IsMain());
 
-    EXPECT_FALSE(user_gesture);
+    if (IsChromeRuntimeEnabled()) {
+      // With the Chrome runtime this is true on initial navigation via
+      // chrome::AddTabAt() and also true for clicked links.
+      EXPECT_TRUE(user_gesture);
+    } else {
+      EXPECT_FALSE(user_gesture);
+    }
     if (on_before_browse_ct_ == 0 || mode_ == RESTART_RESOURCE_RESPONSE) {
       EXPECT_FALSE(is_redirect) << on_before_browse_ct_;
     } else {
@@ -540,7 +547,7 @@
     VerifyState(kOnBeforeBrowse, request, nullptr);
 
     if (mode_ == ABORT_BEFORE_BROWSE) {
-      SetSignalCompletionWhenAllBrowsersClose(false);
+      SetSignalTestCompletionCount(1U);
       CloseBrowser(browser, false);
     }
 
@@ -606,8 +613,13 @@
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) override {
+      CefRefPtr<CefCallback> callback) override {
     EXPECT_IO_THREAD();
+    if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
+      // Ignore favicon requests.
+      return RV_CANCEL;
+    }
+
     EXPECT_EQ(browser_id_, browser->GetIdentifier());
     EXPECT_TRUE(frame->IsMain());
 
@@ -661,13 +673,15 @@
         return GetOKResource();
       } else {
         // Restarted request.
-        if (unhandled_)
+        if (unhandled_) {
           return nullptr;
+        }
         return GetOKResource();
       }
     } else if (url == GetURL(RESULT_HTML)) {
-      if (unhandled_)
+      if (unhandled_) {
         return nullptr;
+      }
       return GetOKResource();
     } else if (url == GetURL(REDIRECT_HTML) &&
                mode_ == REDIRECT_RESOURCE_RESPONSE) {
@@ -676,8 +690,9 @@
         return GetOKResource();
       } else {
         // Redirected request.
-        if (unhandled_)
+        if (unhandled_) {
           return nullptr;
+        }
         return GetOKResource();
       }
     } else if (url == GetURL(REDIRECT_HTML) || url == GetURL(REDIRECT2_HTML)) {
@@ -777,19 +792,25 @@
                               CefRefPtr<CefRequest> request,
                               CefRefPtr<CefResponse> response,
                               URLRequestStatus status,
-                              int64 received_content_length) override {
+                              int64_t received_content_length) override {
     EXPECT_IO_THREAD();
+
+    if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
+      // Ignore favicon requests.
+      return;
+    }
+
     EXPECT_EQ(browser_id_, browser->GetIdentifier());
     EXPECT_TRUE(frame->IsMain());
 
     VerifyState(kOnResourceLoadComplete, request, response);
 
-    if (unhandled_ || IsIncomplete() || IsAborted()) {
+    if (unhandled_ || IsIncomplete() || (IsAborted() && status == UR_FAILED)) {
       EXPECT_EQ(UR_FAILED, status);
       EXPECT_EQ(0, received_content_length);
     } else {
       EXPECT_EQ(UR_SUCCESS, status);
-      EXPECT_EQ(static_cast<int64>(GetResponseBody().length()),
+      EXPECT_EQ(static_cast<int64_t>(GetResponseBody().length()),
                 received_content_length);
     }
 
@@ -825,10 +846,15 @@
     EXPECT_EQ(browser_id_, browser->GetIdentifier());
     EXPECT_TRUE(frame->IsMain());
 
-    if (unhandled_)
-      EXPECT_EQ(httpStatusCode, 0);
-    else
+    if (unhandled_) {
+      if (IsRedirect()) {
+        EXPECT_EQ(httpStatusCode, 307);
+      } else {
+        EXPECT_EQ(httpStatusCode, 0);
+      }
+    } else {
       EXPECT_EQ(httpStatusCode, 200);
+    }
 
     on_load_end_ct_++;
 
@@ -928,46 +954,50 @@
       }
     } else if (IsAborted()) {
       EXPECT_EQ(1, on_before_browse_ct_);
-      if (custom_scheme_) {
-        EXPECT_EQ(0, get_resource_request_handler_ct_);
-        EXPECT_EQ(0, get_cookie_access_filter_ct_);
-      } else {
-        // The callbacks executed for standard schemes may vary based on timing.
-      }
-      EXPECT_EQ(0, on_before_resource_load_ct_);
-      EXPECT_EQ(0, get_resource_handler_ct_);
+      // The callbacks executed may vary based on timing.
+      EXPECT_NEAR(0, get_resource_request_handler_ct_, 1);
+      EXPECT_NEAR(0, get_cookie_access_filter_ct_, 1);
+      EXPECT_NEAR(0, on_before_resource_load_ct_, 1);
+      EXPECT_NEAR(0, get_resource_handler_ct_, 1);
+      EXPECT_NEAR(0, get_resource_response_filter_ct_, 1);
+      EXPECT_NEAR(0, on_resource_response_ct_, 1);
       EXPECT_EQ(0, on_resource_redirect_ct_);
-      EXPECT_EQ(0, get_resource_response_filter_ct_);
-      EXPECT_EQ(0, on_resource_response_ct_);
     } else {
       NOTREACHED();
     }
 
-    EXPECT_EQ(resource_handler_created_ct_, resource_handler_destroyed_ct_);
-
     if (IsAborted()) {
-      EXPECT_EQ(0, on_resource_load_complete_ct_);
+      // The callbacks executed may vary based on timing.
+      EXPECT_NEAR(0, on_load_end_ct_, 1);
+      EXPECT_NEAR(resource_handler_created_ct_, resource_handler_destroyed_ct_,
+                  1);
+      EXPECT_NEAR(0, on_resource_load_complete_ct_, 1);
     } else {
+      EXPECT_EQ(resource_handler_created_ct_, resource_handler_destroyed_ct_);
       EXPECT_EQ(1, on_resource_load_complete_ct_);
     }
 
-    if (IsIncomplete() || IsAborted()) {
+    if (IsIncomplete()) {
       EXPECT_EQ(0, on_load_end_ct_);
-    } else {
+    } else if (!IsAborted()) {
       EXPECT_EQ(1, on_load_end_ct_);
     }
 
     if (custom_scheme_ && unhandled_ && !(IsIncomplete() || IsAborted())) {
       EXPECT_EQ(1, on_protocol_execution_ct_);
+    } else if (IsAborted()) {
+      // The callbacks executed may vary based on timing.
+      EXPECT_NEAR(0, on_protocol_execution_ct_, 1);
     } else {
       EXPECT_EQ(0, on_protocol_execution_ct_);
     }
 
     TestHandler::DestroyTest();
 
-    if (!SignalCompletionWhenAllBrowsersClose()) {
+    if (!AllowTestCompletionWhenAllBrowsersClose()) {
       // Complete asynchronously so the call stack has a chance to unwind.
-      CefPostTask(TID_UI, base::Bind(&BasicResponseTest::TestComplete, this));
+      CefPostTask(TID_UI, base::BindOnce(
+                              &BasicResponseTest::SignalTestCompletion, this));
     }
   }
 
@@ -980,19 +1010,25 @@
 
   const char* GetURL(TestUrl url) const {
     if (custom_scheme_) {
-      if (url == RESULT_HTML)
+      if (url == RESULT_HTML) {
         return "rrhcustom://test.com/result.html";
-      if (url == REDIRECT_HTML)
+      }
+      if (url == REDIRECT_HTML) {
         return "rrhcustom://test.com/redirect.html";
-      if (url == REDIRECT2_HTML)
+      }
+      if (url == REDIRECT2_HTML) {
         return "rrhcustom://test.com/redirect2.html";
+      }
     } else {
-      if (url == RESULT_HTML)
-        return "http://test.com/result.html";
-      if (url == REDIRECT_HTML)
-        return "http://test.com/redirect.html";
-      if (url == REDIRECT2_HTML)
-        return "http://test.com/redirect2.html";
+      if (url == RESULT_HTML) {
+        return "https://test.com/result.html";
+      }
+      if (url == REDIRECT_HTML) {
+        return "https://test.com/redirect.html";
+      }
+      if (url == REDIRECT2_HTML) {
+        return "https://test.com/redirect2.html";
+      }
     }
 
     NOTREACHED();
@@ -1019,9 +1055,9 @@
     return "<html><body>Redirect</body></html>";
   }
 
-  base::Closure GetResourceDestroyCallback() {
+  base::OnceClosure GetResourceDestroyCallback() {
     resource_handler_created_ct_++;
-    return base::Bind(&BasicResponseTest::MaybeDestroyTest, this, true);
+    return base::BindOnce(&BasicResponseTest::MaybeDestroyTest, this, true);
   }
 
   bool GetCallbackResourceHandlerMode(CallbackResourceHandler::Mode& mode) {
@@ -1208,8 +1244,9 @@
         EXPECT_STREQ("", custom_header.c_str()) << callback;
       }
 
-      if (response)
+      if (response) {
         VerifyOKResponse(callback, response);
+      }
     } else if (IsRedirect()) {
       EXPECT_STREQ("GET", request->GetMethod().ToString().c_str()) << callback;
       if (on_before_browse_ct_ == 1) {
@@ -1240,6 +1277,8 @@
 
   void VerifyOKResponse(Callback callback,
                         CefRefPtr<CefResponse> response) const {
+    const auto error_code = response->GetError();
+
     // True for the first response in cases where we're redirecting/restarting
     // from inside OnResourceResponse (e.g. the first response always succeeds).
     const bool override_unhandled = unhandled_ &&
@@ -1252,14 +1291,12 @@
     const bool incomplete_unhandled =
         (mode_ == INCOMPLETE_BEFORE_RESOURCE_LOAD ||
          mode_ == INCOMPLETE_REQUEST_HANDLER_OPEN ||
-         (IsAborted() && !custom_scheme_));
+         (IsAborted() && !custom_scheme_ && error_code != ERR_NONE));
 
     if ((unhandled_ && !override_unhandled) || incomplete_unhandled) {
-      if (incomplete_unhandled) {
-        EXPECT_EQ(ERR_ABORTED, response->GetError()) << callback;
-      } else {
-        EXPECT_EQ(ERR_UNKNOWN_URL_SCHEME, response->GetError()) << callback;
-      }
+      EXPECT_TRUE(ERR_ABORTED == error_code ||
+                  ERR_UNKNOWN_URL_SCHEME == error_code)
+          << callback << error_code;
       EXPECT_EQ(0, response->GetStatus()) << callback;
       EXPECT_STREQ("", response->GetStatusText().ToString().c_str())
           << callback;
@@ -1268,7 +1305,8 @@
       EXPECT_STREQ("", response->GetCharset().ToString().c_str()) << callback;
     } else {
       if ((mode_ == INCOMPLETE_REQUEST_HANDLER_READ || IsAborted()) &&
-          callback == kOnResourceLoadComplete) {
+          callback == kOnResourceLoadComplete &&
+          response->GetError() != ERR_NONE) {
         // We got a response, but we also got aborted.
         EXPECT_EQ(ERR_ABORTED, response->GetError()) << callback;
       } else {
@@ -1299,16 +1337,16 @@
 
   void CloseBrowserAsync() {
     EXPECT_TRUE(IsIncomplete());
-    SetSignalCompletionWhenAllBrowsersClose(false);
+    SetSignalTestCompletionCount(1U);
     CefPostDelayedTask(
-        TID_UI, base::Bind(&TestHandler::CloseBrowser, GetBrowser(), false),
+        TID_UI, base::BindOnce(&TestHandler::CloseBrowser, GetBrowser(), false),
         100);
   }
 
   void MaybeDestroyTest(bool from_handler) {
     if (!CefCurrentlyOn(TID_UI)) {
-      CefPostTask(TID_UI, base::Bind(&BasicResponseTest::MaybeDestroyTest, this,
-                                     from_handler));
+      CefPostTask(TID_UI, base::BindOnce(&BasicResponseTest::MaybeDestroyTest,
+                                         this, from_handler));
       return;
     }
 
@@ -1341,7 +1379,7 @@
   const bool unhandled_;
 
   int browser_id_ = 0;
-  uint64 request_id_ = 0U;
+  uint64_t request_id_ = 0U;
 
   int resource_handler_created_ct_ = 0;
 
@@ -1360,7 +1398,7 @@
   int resource_handler_destroyed_ct_ = 0;
 
   // Used with INCOMPLETE_BEFORE_RESOURCE_LOAD.
-  CefRefPtr<CefRequestCallback> incomplete_callback_;
+  CefRefPtr<CefCallback> incomplete_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(BasicResponseTest);
   IMPLEMENT_REFCOUNTING(BasicResponseTest);
@@ -1509,16 +1547,24 @@
       EXPECT_EQ(browser_id_, browser->GetIdentifier());
     }
 
-    if (IsMainURL(request->GetURL())) {
+    const std::string& url = request->GetURL();
+    if (IsMainURL(url)) {
       EXPECT_TRUE(frame->IsMain());
-    } else if (IsSubURL(request->GetURL())) {
+    } else if (IsSubURL(url)) {
       EXPECT_FALSE(frame->IsMain());
       EXPECT_TRUE(subframe_);
     } else {
       EXPECT_FALSE(true);  // Not reached.
     }
 
-    EXPECT_FALSE(user_gesture);
+    if (IsChromeRuntimeEnabled() && IsMainURL(url)) {
+      // With the Chrome runtime this is true on initial navigation via
+      // chrome::AddTabAt() and also true for clicked links.
+      EXPECT_TRUE(user_gesture);
+    } else {
+      EXPECT_FALSE(user_gesture);
+    }
+
     EXPECT_FALSE(is_redirect);
 
     on_before_browse_ct_++;
@@ -1536,21 +1582,30 @@
     EXPECT_IO_THREAD();
     EXPECT_EQ(browser_id_, browser->GetIdentifier());
 
-    if (IsMainURL(request->GetURL())) {
+    const std::string& url = request->GetURL();
+    if (IgnoreURL(url)) {
+      return nullptr;
+    }
+
+    const bool is_main_url = IsMainURL(url);
+    const bool is_sub_url = IsSubURL(url);
+
+    if (is_main_url) {
       EXPECT_TRUE(frame->IsMain());
-    } else if (IsSubURL(request->GetURL())) {
+    } else if (is_sub_url) {
       EXPECT_FALSE(frame->IsMain());
       EXPECT_TRUE(subframe_);
     }
 
-    if (IsMainURL(request->GetURL()) || IsSubURL(request->GetURL())) {
+    if (is_main_url || is_sub_url) {
       // Track the frame ID that we'll expect for resource callbacks.
       // Do this here instead of OnBeforeBrowse because OnBeforeBrowse may
       // return -4 (kInvalidFrameId) for the initial navigation.
       if (frame_id_ == 0) {
         if (subframe_) {
-          if (IsSubURL(request->GetURL()))
+          if (is_sub_url) {
             frame_id_ = frame->GetIdentifier();
+          }
         } else {
           frame_id_ = frame->GetIdentifier();
         }
@@ -1595,10 +1650,15 @@
     EXPECT_IO_THREAD();
     EXPECT_EQ(browser_id_, browser->GetIdentifier());
 
-    if (IsMainURL(request->GetURL())) {
+    const std::string& url = request->GetURL();
+    if (IgnoreURL(url)) {
+      return nullptr;
+    }
+
+    if (IsMainURL(url)) {
       EXPECT_TRUE(frame->IsMain());
       return nullptr;
-    } else if (IsSubURL(request->GetURL())) {
+    } else if (IsSubURL(url)) {
       EXPECT_FALSE(frame->IsMain());
       EXPECT_TRUE(subframe_);
       return nullptr;
@@ -1617,8 +1677,14 @@
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) override {
+      CefRefPtr<CefCallback> callback) override {
     EXPECT_IO_THREAD();
+
+    if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
+      // Ignore favicon requests.
+      return RV_CANCEL;
+    }
+
     EXPECT_EQ(browser_id_, browser->GetIdentifier());
 
     if (IsMainURL(request->GetURL())) {
@@ -1692,13 +1758,15 @@
         return GetOKResource();
       } else {
         // Restarted request.
-        if (unhandled_)
+        if (unhandled_) {
           return nullptr;
+        }
         return GetOKResource();
       }
     } else if (url == GetURL(RESULT_JS)) {
-      if (unhandled_)
+      if (unhandled_) {
         return nullptr;
+      }
       return GetOKResource();
     } else if (url == GetURL(REDIRECT_JS) &&
                mode_ == REDIRECT_RESOURCE_RESPONSE) {
@@ -1707,8 +1775,9 @@
         return GetOKResource();
       } else {
         // Redirected request.
-        if (unhandled_)
+        if (unhandled_) {
           return nullptr;
+        }
         return GetOKResource();
       }
     } else if (url == GetURL(REDIRECT_JS) || url == GetURL(REDIRECT2_JS)) {
@@ -1834,20 +1903,26 @@
                               CefRefPtr<CefRequest> request,
                               CefRefPtr<CefResponse> response,
                               URLRequestStatus status,
-                              int64 received_content_length) override {
+                              int64_t received_content_length) override {
     EXPECT_IO_THREAD();
+
+    if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
+      // Ignore favicon requests.
+      return;
+    }
+
     EXPECT_EQ(browser_id_, browser->GetIdentifier());
 
     if (IsMainURL(request->GetURL())) {
       EXPECT_TRUE(frame->IsMain());
       EXPECT_EQ(UR_SUCCESS, status);
-      EXPECT_EQ(static_cast<int64>(GetMainResponseBody().length()),
+      EXPECT_EQ(static_cast<int64_t>(GetMainResponseBody().length()),
                 received_content_length);
       return;
     } else if (IsSubURL(request->GetURL())) {
       EXPECT_FALSE(frame->IsMain());
       EXPECT_EQ(UR_SUCCESS, status);
-      EXPECT_EQ(static_cast<int64>(GetSubResponseBody().length()),
+      EXPECT_EQ(static_cast<int64_t>(GetSubResponseBody().length()),
                 received_content_length);
       EXPECT_TRUE(subframe_);
       return;
@@ -1862,7 +1937,7 @@
       EXPECT_EQ(0, received_content_length);
     } else {
       EXPECT_EQ(UR_SUCCESS, status);
-      EXPECT_EQ(static_cast<int64>(GetResponseBody().length()),
+      EXPECT_EQ(static_cast<int64_t>(GetResponseBody().length()),
                 received_content_length);
     }
 
@@ -1913,7 +1988,7 @@
 
   bool OnQuery(CefRefPtr<CefBrowser> browser,
                CefRefPtr<CefFrame> frame,
-               int64 query_id,
+               int64_t query_id,
                const CefString& request,
                bool persistent,
                CefRefPtr<Callback> callback) override {
@@ -1983,23 +2058,26 @@
       EXPECT_EQ(1, on_resource_redirect_ct_);
 
       // Unhandled requests won't see a call to GetResourceResponseFilter.
-      if (unhandled_)
+      if (unhandled_) {
         EXPECT_EQ(0, get_resource_response_filter_ct_);
-      else
+      } else {
         EXPECT_EQ(1, get_resource_response_filter_ct_);
+      }
 
       // Unhandled requests won't see a call to OnResourceResponse.
       if (mode_ == REDIRECT_RESOURCE_RESPONSE) {
         // In this case we're redirecting from inside OnResourceResponse.
-        if (unhandled_)
+        if (unhandled_) {
           EXPECT_EQ(1, on_resource_response_ct_);
-        else
+        } else {
           EXPECT_EQ(2, on_resource_response_ct_);
+        }
       } else {
-        if (unhandled_)
+        if (unhandled_) {
           EXPECT_EQ(0, on_resource_response_ct_);
-        else
+        } else {
           EXPECT_EQ(1, on_resource_response_ct_);
+        }
       }
     } else if (IsIncomplete()) {
       EXPECT_EQ(1, get_resource_request_handler_ct_);
@@ -2053,10 +2131,11 @@
 
     TestHandler::DestroyTest();
 
-    if (!SignalCompletionWhenAllBrowsersClose()) {
+    if (!AllowTestCompletionWhenAllBrowsersClose()) {
       // Complete asynchronously so the call stack has a chance to unwind.
-      CefPostTask(TID_UI,
-                  base::Bind(&SubresourceResponseTest::TestComplete, this));
+      CefPostTask(
+          TID_UI,
+          base::BindOnce(&SubresourceResponseTest::SignalTestCompletion, this));
     }
   }
 
@@ -2065,7 +2144,7 @@
     if (custom_scheme_) {
       return "rrhcustom://test.com/main.html";
     } else {
-      return "http://test.com/main.html";
+      return "https://test.com/main.html";
     }
   }
 
@@ -2073,7 +2152,7 @@
     if (custom_scheme_) {
       return "rrhcustom://test.com/subframe.html";
     } else {
-      return "http://test.com/subframe.html";
+      return "https://test.com/subframe.html";
     }
   }
 
@@ -2081,7 +2160,7 @@
     if (custom_scheme_) {
       return "rrhcustom://test.com";
     } else {
-      return "http://test.com";
+      return "https://test.com";
     }
   }
 
@@ -2096,19 +2175,25 @@
 
   const char* GetURL(TestUrl url) const {
     if (custom_scheme_) {
-      if (url == RESULT_JS)
+      if (url == RESULT_JS) {
         return "rrhcustom://test.com/result.js";
-      if (url == REDIRECT_JS)
+      }
+      if (url == REDIRECT_JS) {
         return "rrhcustom://test.com/redirect.js";
-      if (url == REDIRECT2_JS)
+      }
+      if (url == REDIRECT2_JS) {
         return "rrhcustom://test.com/redirect2.js";
+      }
     } else {
-      if (url == RESULT_JS)
-        return "http://test.com/result.js";
-      if (url == REDIRECT_JS)
-        return "http://test.com/redirect.js";
-      if (url == REDIRECT2_JS)
-        return "http://test.com/redirect2.js";
+      if (url == RESULT_JS) {
+        return "https://test.com/result.js";
+      }
+      if (url == REDIRECT_JS) {
+        return "https://test.com/redirect.js";
+      }
+      if (url == REDIRECT2_JS) {
+        return "https://test.com/redirect2.js";
+      }
     }
 
     NOTREACHED();
@@ -2146,7 +2231,7 @@
   }
 
   std::string GetSubResponseBody() const {
-    DCHECK(subframe_);
+    EXPECT_TRUE(subframe_);
 
     std::stringstream html;
     html << "<html><head>";
@@ -2166,9 +2251,10 @@
     return "<html><body>Redirect</body></html>";
   }
 
-  base::Closure GetResourceDestroyCallback() {
+  base::OnceClosure GetResourceDestroyCallback() {
     resource_handler_created_ct_++;
-    return base::Bind(&SubresourceResponseTest::MaybeDestroyTest, this, true);
+    return base::BindOnce(&SubresourceResponseTest::MaybeDestroyTest, this,
+                          true);
   }
 
   bool GetCallbackResourceHandlerMode(CallbackResourceHandler::Mode& mode) {
@@ -2320,10 +2406,11 @@
   void VerifyFrame(Callback callback, CefRefPtr<CefFrame> frame) const {
     EXPECT_TRUE(frame);
 
-    if (subframe_)
+    if (subframe_) {
       EXPECT_FALSE(frame->IsMain()) << callback;
-    else
+    } else {
       EXPECT_TRUE(frame->IsMain()) << callback;
+    }
 
     EXPECT_EQ(frame_id_, frame->GetIdentifier()) << callback;
   }
@@ -2366,8 +2453,9 @@
         EXPECT_STREQ("", custom_header.c_str()) << callback;
       }
 
-      if (response)
+      if (response) {
         VerifyOKResponse(callback, response);
+      }
     } else if (IsRedirect()) {
       EXPECT_STREQ("GET", request->GetMethod().ToString().c_str()) << callback;
       // Subresource loads don't get OnBeforeBrowse calls, so this check is a
@@ -2457,16 +2545,17 @@
 
   void CloseBrowserAsync() {
     EXPECT_TRUE(IsIncomplete());
-    SetSignalCompletionWhenAllBrowsersClose(false);
+    SetSignalTestCompletionCount(1U);
     CefPostDelayedTask(
-        TID_UI, base::Bind(&TestHandler::CloseBrowser, GetBrowser(), false),
+        TID_UI, base::BindOnce(&TestHandler::CloseBrowser, GetBrowser(), false),
         100);
   }
 
   void MaybeDestroyTest(bool from_handler) {
     if (!CefCurrentlyOn(TID_UI)) {
-      CefPostTask(TID_UI, base::Bind(&SubresourceResponseTest::MaybeDestroyTest,
-                                     this, from_handler));
+      CefPostTask(TID_UI,
+                  base::BindOnce(&SubresourceResponseTest::MaybeDestroyTest,
+                                 this, from_handler));
       return;
     }
 
@@ -2502,8 +2591,8 @@
   const bool subframe_;
 
   int browser_id_ = 0;
-  int64 frame_id_ = 0;
-  uint64 request_id_ = 0U;
+  int64_t frame_id_ = 0;
+  uint64_t request_id_ = 0U;
 
   int resource_handler_created_ct_ = 0;
 
@@ -2523,7 +2612,7 @@
   int resource_handler_destroyed_ct_ = 0;
 
   // Used with INCOMPLETE_BEFORE_RESOURCE_LOAD.
-  CefRefPtr<CefRequestCallback> incomplete_callback_;
+  CefRefPtr<CefCallback> incomplete_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(SubresourceResponseTest);
   IMPLEMENT_REFCOUNTING(SubresourceResponseTest);
@@ -2593,7 +2682,7 @@
 
 namespace {
 
-const char kResourceTestHtml[] = "http://test.com/resource.html";
+const char kResourceTestHtml[] = "https://test.com/resource.html";
 
 class RedirectResponseTest : public TestHandler {
  public:
@@ -2605,12 +2694,13 @@
 
   RedirectResponseTest(TestMode mode, bool via_request_context_handler)
       : via_request_context_handler_(via_request_context_handler) {
-    if (mode == URL)
+    if (mode == URL) {
       resource_test_.reset(new UrlResourceTest);
-    else if (mode == HEADER)
+    } else if (mode == HEADER) {
       resource_test_.reset(new HeaderResourceTest);
-    else
+    } else {
       resource_test_.reset(new PostResourceTest);
+    }
   }
 
   void RunTest() override {
@@ -2777,7 +2867,7 @@
                                 CefRefPtr<CefRequest> request,
                                 CefRefPtr<CefResponse> response,
                                 URLRequestStatus status,
-                                int64 received_content_length) {
+                                int64_t received_content_length) {
       EXPECT_TRUE(CheckUrl(request->GetURL()));
 
       // Verify the response returned by GetResourceHandler.
@@ -2845,13 +2935,14 @@
     // With NetworkService we don't get an additional (unnecessary) redirect
     // callback.
     UrlResourceTest()
-        : ResourceTest("http://test.com/start_url.js", 2U, 2U, 1U) {
-      redirect_url_ = "http://test.com/redirect_url.js";
+        : ResourceTest("https://test.com/start_url.js", 2U, 2U, 1U) {
+      redirect_url_ = "https://test.com/redirect_url.js";
     }
 
     bool CheckUrl(const std::string& url) const override {
-      if (url == redirect_url_)
+      if (url == redirect_url_) {
         return true;
+      }
 
       return ResourceTest::CheckUrl(url);
     }
@@ -2892,7 +2983,7 @@
     // With NetworkService we restart the request, so we get another call to
     // OnBeforeResourceLoad.
     HeaderResourceTest()
-        : ResourceTest("http://test.com/start_header.js", 2U, 2U) {
+        : ResourceTest("https://test.com/start_header.js", 2U, 2U) {
       expected_headers_.insert(std::make_pair("Test-Key1", "Value1"));
       expected_headers_.insert(std::make_pair("Test-Key2", "Value2"));
     }
@@ -2923,7 +3014,8 @@
    public:
     // With NetworkService we restart the request, so we get another call to
     // OnBeforeResourceLoad.
-    PostResourceTest() : ResourceTest("http://test.com/start_post.js", 2U, 2U) {
+    PostResourceTest()
+        : ResourceTest("https://test.com/start_post.js", 2U, 2U) {
       CefRefPtr<CefPostDataElement> elem = CefPostDataElement::Create();
       const std::string data("Test Post Data");
       elem->SetToBytes(data.size(), data.c_str());
@@ -2985,8 +3077,15 @@
         CefRefPtr<CefBrowser> browser,
         CefRefPtr<CefFrame> frame,
         CefRefPtr<CefRequest> request,
-        CefRefPtr<CefRequestCallback> callback) override {
+        CefRefPtr<CefCallback> callback) override {
       EXPECT_IO_THREAD();
+
+      if (IsChromeRuntimeEnabled() &&
+          request->GetResourceType() == RT_FAVICON) {
+        // Ignore favicon requests.
+        return RV_CANCEL;
+      }
+
       EXPECT_EQ(test_->browser_id_, browser->GetIdentifier());
 
       if (request->GetURL() == kResourceTestHtml) {
@@ -3087,8 +3186,15 @@
                                 CefRefPtr<CefRequest> request,
                                 CefRefPtr<CefResponse> response,
                                 URLRequestStatus status,
-                                int64 received_content_length) override {
+                                int64_t received_content_length) override {
       EXPECT_IO_THREAD();
+
+      if (IsChromeRuntimeEnabled() &&
+          request->GetResourceType() == RT_FAVICON) {
+        // Ignore favicon requests.
+        return;
+      }
+
       EXPECT_TRUE(browser.get());
       EXPECT_EQ(test_->browser_id_, browser->GetIdentifier());
 
@@ -3108,8 +3214,8 @@
    private:
     RedirectResponseTest* const test_;
 
-    uint64 main_request_id_ = 0U;
-    uint64 sub_request_id_ = 0U;
+    uint64_t main_request_id_ = 0U;
+    uint64_t sub_request_id_ = 0U;
 
     IMPLEMENT_REFCOUNTING(ResourceRequestHandler);
     DISALLOW_COPY_AND_ASSIGN(ResourceRequestHandler);
@@ -3118,7 +3224,7 @@
   const bool via_request_context_handler_;
 
   int browser_id_ = 0;
-  scoped_ptr<ResourceTest> resource_test_;
+  std::unique_ptr<ResourceTest> resource_test_;
   CefRefPtr<ResourceRequestHandler> resource_request_handler_;
 
   IMPLEMENT_REFCOUNTING(RedirectResponseTest);
@@ -3176,7 +3282,7 @@
 
 namespace {
 
-const char kResourceTestHtml2[] = "http://test.com/resource2.html";
+const char kResourceTestHtml2[] = "https://test.com/resource2.html";
 
 class BeforeResourceLoadTest : public TestHandler {
  public:
@@ -3203,9 +3309,14 @@
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) override {
+      CefRefPtr<CefCallback> callback) override {
     EXPECT_IO_THREAD();
 
+    if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
+      // Ignore favicon requests.
+      return RV_CANCEL;
+    }
+
     // Allow the 2nd navigation to continue.
     const std::string& url = request->GetURL();
     if (url == kResourceTestHtml2) {
@@ -3227,11 +3338,14 @@
       if (test_mode_ == CANCEL_NAV) {
         // Cancel the request by navigating to a new URL.
         browser->GetMainFrame()->LoadURL(kResourceTestHtml2);
-      } else {
-        // Continue or cancel asynchronously.
+      } else if (test_mode_ == CONTINUE_ASYNC) {
+        // Continue asynchronously.
         CefPostTask(TID_UI,
-                    base::Bind(&CefRequestCallback::Continue, callback.get(),
-                               test_mode_ == CONTINUE_ASYNC));
+                    base::BindOnce(&CefCallback::Continue, callback.get()));
+      } else {
+        // Cancel asynchronously.
+        CefPostTask(TID_UI,
+                    base::BindOnce(&CefCallback::Cancel, callback.get()));
       }
       return RV_CONTINUE_ASYNC;
     }
@@ -3246,10 +3360,11 @@
     got_load_end_.yes();
 
     const std::string& url = frame->GetURL();
-    if (test_mode_ == CANCEL_NAV)
+    if (test_mode_ == CANCEL_NAV) {
       EXPECT_STREQ(kResourceTestHtml2, url.data());
-    else
+    } else {
       EXPECT_STREQ(kResourceTestHtml, url.data());
+    }
 
     TestHandler::OnLoadEnd(browser, frame, httpStatusCode);
     DestroyTest();
@@ -3269,17 +3384,19 @@
     EXPECT_STREQ(kResourceTestHtml, url.data());
 
     TestHandler::OnLoadError(browser, frame, errorCode, errorText, failedUrl);
-    if (test_mode_ != CANCEL_NAV)
+    if (test_mode_ != CANCEL_NAV) {
       DestroyTest();
+    }
   }
 
   void DestroyTest() override {
     EXPECT_TRUE(got_before_resource_load_);
 
-    if (test_mode_ == CANCEL_NAV)
+    if (test_mode_ == CANCEL_NAV) {
       EXPECT_TRUE(got_before_resource_load2_);
-    else
+    } else {
       EXPECT_FALSE(got_before_resource_load2_);
+    }
 
     if (test_mode_ == CONTINUE || test_mode_ == CONTINUE_ASYNC) {
       EXPECT_TRUE(got_load_end_);
@@ -3349,7 +3466,7 @@
 // - Needing more input and not getting it.
 // - Filter error.
 
-const char kResponseFilterTestUrl[] = "http://tests.com/response_filter.html";
+const char kResponseFilterTestUrl[] = "https://test.com/response_filter.html";
 
 size_t GetResponseBufferSize() {
   // Match the default |capacity_num_bytes| value from
@@ -3361,8 +3478,8 @@
 const char kInputFooter[] = "</body></html>";
 
 // Repeat |content| the minimum number of times necessary to satisfy
-// |desired_min_size|. If |calculated_repeat_ct| is non-NULL it will be set to
-// the number of times that |content| was repeated.
+// |desired_min_size|. If |calculated_repeat_ct| is non-nullptr it will be set
+// to the number of times that |content| was repeated.
 std::string CreateInput(const std::string& content,
                         size_t desired_min_size,
                         size_t* calculated_repeat_ct = nullptr) {
@@ -3374,15 +3491,17 @@
   size_t repeat_ct =
       static_cast<size_t>(std::ceil(static_cast<double>(desired_min_size) /
                                     static_cast<double>(content.size())));
-  if (calculated_repeat_ct)
+  if (calculated_repeat_ct) {
     *calculated_repeat_ct = repeat_ct;
+  }
 
   std::string result;
   result.reserve(header_footer_size + (content.size() * repeat_ct));
 
   result = kInputHeader;
-  while (repeat_ct--)
+  while (repeat_ct--) {
     result += content;
+  }
   result += kInputFooter;
 
   return result;
@@ -3396,8 +3515,9 @@
   result.reserve(header_footer_size + (content.size() * repeat_ct));
 
   result = kInputHeader;
-  while (repeat_ct--)
+  while (repeat_ct--) {
     result += content;
+  }
   result += kInputFooter;
 
   return result;
@@ -3420,10 +3540,11 @@
                       void* data_out,
                       size_t data_out_size,
                       size_t& data_out_written) override {
-    if (data_in_size == 0U)
+    if (data_in_size == 0U) {
       EXPECT_FALSE(data_in);
-    else
+    } else {
       EXPECT_TRUE(data_in);
+    }
     EXPECT_EQ(data_in_read, 0U);
     EXPECT_TRUE(data_out);
     EXPECT_GT(data_out_size, 0U);
@@ -3437,7 +3558,7 @@
 
   // Verify the output from the filter.
   virtual void VerifyOutput(cef_urlrequest_status_t status,
-                            int64 received_content_length,
+                            int64_t received_content_length,
                             const std::string& received_content) {
     EXPECT_TRUE(got_init_filter_);
     EXPECT_GT(filter_count_, 0U);
@@ -3488,16 +3609,16 @@
   }
 
   void VerifyOutput(cef_urlrequest_status_t status,
-                    int64 received_content_length,
+                    int64_t received_content_length,
                     const std::string& received_content) override {
     ResponseFilterTestBase::VerifyOutput(status, received_content_length,
                                          received_content);
 
-    if (limit_read_)
+    if (limit_read_) {
       // Expected to read 2 full buffers of GetResponseBufferSize() at 1kb
       // increments and one partial buffer.
       EXPECT_EQ(2U * (GetResponseBufferSize() / 1024) + 1U, filter_count_);
-    else {
+    } else {
       // Expected to read 2 full buffers of GetResponseBufferSize() and one
       // partial buffer.
       EXPECT_EQ(3U, filter_count_);
@@ -3613,14 +3734,15 @@
     const size_t replace_size = sizeof(kReplaceString) - 1;
 
     // Determine a reasonable amount of space for find/replace overflow.
-    if (replace_size > find_size)
+    if (replace_size > find_size) {
       replace_overflow_size_ = (replace_size - find_size) * repeat_ct_;
+    }
 
     return input;
   }
 
   void VerifyOutput(cef_urlrequest_status_t status,
-                    int64 received_content_length,
+                    int64_t received_content_length,
                     const std::string& received_content) override {
     ResponseFilterTestBase::VerifyOutput(status, received_content_length,
                                          received_content);
@@ -3708,7 +3830,7 @@
   }
 
   void VerifyOutput(cef_urlrequest_status_t status,
-                    int64 received_content_length,
+                    int64_t received_content_length,
                     const std::string& received_content) override {
     ResponseFilterTestBase::VerifyOutput(status, received_content_length,
                                          received_content);
@@ -3752,7 +3874,7 @@
       CefRefPtr<CefResponse> response) override {
     EXPECT_IO_THREAD();
 
-    DCHECK(!got_resource_response_filter_);
+    EXPECT_FALSE(got_resource_response_filter_);
     got_resource_response_filter_.yes();
     return response_filter_;
   }
@@ -3762,10 +3884,15 @@
                               CefRefPtr<CefRequest> request,
                               CefRefPtr<CefResponse> response,
                               URLRequestStatus status,
-                              int64 received_content_length) override {
+                              int64_t received_content_length) override {
     EXPECT_IO_THREAD();
 
-    DCHECK(!got_resource_load_complete_);
+    if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
+      // Ignore favicon requests.
+      return;
+    }
+
+    EXPECT_FALSE(got_resource_load_complete_);
     got_resource_load_complete_.yes();
 
     status_ = status;
@@ -3775,7 +3902,7 @@
   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
                  CefRefPtr<CefFrame> frame,
                  int httpStatusCode) override {
-    DCHECK(!got_load_end_);
+    EXPECT_FALSE(got_load_end_);
     got_load_end_.yes();
 
     response_filter_->VerifyStatusCode(httpStatusCode);
@@ -3790,15 +3917,14 @@
   void GetOutputContent(CefRefPtr<CefFrame> frame) {
     class StringVisitor : public CefStringVisitor {
      public:
-      typedef base::Callback<void(const std::string& /*received_content*/)>
-          VisitorCallback;
+      using VisitorCallback =
+          base::OnceCallback<void(const std::string& /*received_content*/)>;
 
-      explicit StringVisitor(const VisitorCallback& callback)
-          : callback_(callback) {}
+      explicit StringVisitor(VisitorCallback callback)
+          : callback_(std::move(callback)) {}
 
       void Visit(const CefString& string) override {
-        callback_.Run(string);
-        callback_.Reset();
+        std::move(callback_).Run(string);
       }
 
      private:
@@ -3808,7 +3934,7 @@
     };
 
     frame->GetSource(new StringVisitor(
-        base::Bind(&ResponseFilterTestHandler::VerifyOutput, this)));
+        base::BindOnce(&ResponseFilterTestHandler::VerifyOutput, this)));
   }
 
   void VerifyOutput(const std::string& received_content) {
@@ -3834,7 +3960,7 @@
   TrackCallback got_load_end_;
 
   URLRequestStatus status_;
-  int64 received_content_length_;
+  int64_t received_content_length_;
 
   IMPLEMENT_REFCOUNTING(ResponseFilterTestHandler);
 };
@@ -3876,8 +4002,7 @@
 // Entry point for registering custom schemes.
 // Called from client_app_delegates.cc.
 void RegisterResourceRequestHandlerCustomSchemes(
-    CefRawPtr<CefSchemeRegistrar> registrar,
-    std::vector<CefString>& cookiable_schemes) {
+    CefRawPtr<CefSchemeRegistrar> registrar) {
   // Add a custom standard scheme.
   registrar->AddCustomScheme(
       "rrhcustom", CEF_SCHEME_OPTION_STANDARD | CEF_SCHEME_OPTION_CORS_ENABLED);
diff --git a/src/tests/ceftests/resource_util_linux.cc b/src/tests/ceftests/resource_util_linux.cc
index 6409a0d..110d09b 100644
--- a/src/tests/ceftests/resource_util_linux.cc
+++ b/src/tests/ceftests/resource_util_linux.cc
@@ -16,15 +16,17 @@
 
   // Retrieve the executable path.
   ssize_t len = readlink("/proc/self/exe", buff, sizeof(buff) - 1);
-  if (len == -1)
+  if (len == -1) {
     return false;
+  }
 
   buff[len] = 0;
 
   // Remove the executable name from the path.
   char* pos = strrchr(buff, '/');
-  if (!pos)
+  if (!pos) {
     return false;
+  }
 
   // Add "ceftests_files" to the path.
   strcpy(pos + 1, "ceftests_files");
diff --git a/src/tests/ceftests/resource_util_win_dir.cc b/src/tests/ceftests/resource_util_win_dir.cc
new file mode 100644
index 0000000..3df18d5
--- /dev/null
+++ b/src/tests/ceftests/resource_util_win_dir.cc
@@ -0,0 +1,36 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "tests/shared/browser/resource_util.h"
+
+#include <windows.h>
+
+#include "include/internal/cef_string_wrappers.h"
+
+namespace client {
+
+bool GetResourceDir(std::string& dir) {
+  wchar_t buff[MAX_PATH];
+
+  // Retrieve the executable path.
+  auto len = GetModuleFileName(nullptr, buff, MAX_PATH);
+  if (len == 0) {
+    return false;
+  }
+
+  buff[len] = 0;
+
+  // Remove the executable name from the path.
+  auto* pos = wcsrchr(buff, L'\\');
+  if (!pos) {
+    return false;
+  }
+
+  // Add "ceftests_files" to the path.
+  wcscpy(pos + 1, L"ceftests_files");
+  dir = CefStringWide(buff).ToString();
+  return true;
+}
+
+}  // namespace client
diff --git a/src/tests/ceftests/resource_util_win_idmap.cc b/src/tests/ceftests/resource_util_win_idmap.cc
index cd54dba..33a684b 100644
--- a/src/tests/ceftests/resource_util_win_idmap.cc
+++ b/src/tests/ceftests/resource_util_win_idmap.cc
@@ -22,8 +22,9 @@
   };
 
   for (size_t i = 0; i < sizeof(resource_map) / sizeof(_resource_map); ++i) {
-    if (!strcmp(resource_map[i].name, resource_name))
+    if (!strcmp(resource_map[i].name, resource_name)) {
       return resource_map[i].id;
+    }
   }
 
   return 0;
diff --git a/src/tests/ceftests/resources/mac/Info.plist b/src/tests/ceftests/resources/mac/Info.plist
index 18c373b..7103cad 100644
--- a/src/tests/ceftests/resources/mac/Info.plist
+++ b/src/tests/ceftests/resources/mac/Info.plist
@@ -25,9 +25,13 @@
 		<key>MallocNanoZone</key>
 		<string>0</string>
 	</dict>
+	<key>LSMinimumSystemVersion</key>
+	<string>10.13.0</string>
 	<key>NSMainNibFile</key>
 	<string>MainMenu</string>
 	<key>NSPrincipalClass</key>
 	<string>NSApplication</string>
+	<key>NSSupportsAutomaticGraphicsSwitching</key>
+	<true/>
 </dict>
 </plist>
diff --git a/src/tests/ceftests/resources/mac/helper-Info.plist b/src/tests/ceftests/resources/mac/helper-Info.plist
index d2359cc..d44d0d0 100644
--- a/src/tests/ceftests/resources/mac/helper-Info.plist
+++ b/src/tests/ceftests/resources/mac/helper-Info.plist
@@ -26,7 +26,7 @@
 	<key>LSFileQuarantineEnabled</key>
 	<true/>
 	<key>LSMinimumSystemVersion</key>
-	<string>10.9.0</string>
+	<string>10.13.0</string>
 	<key>LSUIElement</key>
 	<string>1</string>
 	<key>NSSupportsAutomaticGraphicsSwitching</key>
diff --git a/src/tests/ceftests/routing_test_handler.cc b/src/tests/ceftests/routing_test_handler.cc
index 0f02ced..7702aaf 100644
--- a/src/tests/ceftests/routing_test_handler.cc
+++ b/src/tests/ceftests/routing_test_handler.cc
@@ -57,7 +57,8 @@
 
 }  // namespace
 
-RoutingTestHandler::RoutingTestHandler() {}
+RoutingTestHandler::RoutingTestHandler(CompletionState* completion_state)
+    : TestHandler(completion_state) {}
 
 void RoutingTestHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
   if (!message_router_.get()) {
diff --git a/src/tests/ceftests/routing_test_handler.h b/src/tests/ceftests/routing_test_handler.h
index 89f820c..431772d 100644
--- a/src/tests/ceftests/routing_test_handler.h
+++ b/src/tests/ceftests/routing_test_handler.h
@@ -2,8 +2,8 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#ifndef CEF_TESTS_UNITTESTS_ROUTING_TEST_HANDLER_H_
-#define CEF_TESTS_UNITTESTS_ROUTING_TEST_HANDLER_H_
+#ifndef CEF_TESTS_CEFTESTS_ROUTING_TEST_HANDLER_H_
+#define CEF_TESTS_CEFTESTS_ROUTING_TEST_HANDLER_H_
 #pragma once
 
 #include "include/wrapper/cef_message_router.h"
@@ -15,7 +15,7 @@
 class RoutingTestHandler : public TestHandler,
                            public CefMessageRouterBrowserSide::Handler {
  public:
-  RoutingTestHandler();
+  RoutingTestHandler(CompletionState* completion_state = nullptr);
 
   void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
   void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
@@ -39,4 +39,4 @@
   CefRefPtr<CefMessageRouterBrowserSide> message_router_;
 };
 
-#endif  // CEF_TESTS_UNITTESTS_ROUTING_TEST_HANDLER_H_
+#endif  // CEF_TESTS_CEFTESTS_ROUTING_TEST_HANDLER_H_
diff --git a/src/tests/ceftests/run_all_unittests.cc b/src/tests/ceftests/run_all_unittests.cc
index 4c46abd..dd37370 100644
--- a/src/tests/ceftests/run_all_unittests.cc
+++ b/src/tests/ceftests/run_all_unittests.cc
@@ -16,13 +16,15 @@
 #include <unistd.h>
 #endif
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_app.h"
 #include "include/cef_task.h"
 #include "include/cef_thread.h"
+#include "include/cef_waitable_event.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "include/wrapper/cef_helpers.h"
 #include "tests/ceftests/test_handler.h"
+#include "tests/ceftests/test_server.h"
 #include "tests/ceftests/test_suite.h"
 #include "tests/shared/browser/client_app_browser.h"
 #include "tests/shared/browser/main_message_loop_external_pump.h"
@@ -30,7 +32,7 @@
 #include "tests/shared/common/client_app_other.h"
 #include "tests/shared/renderer/client_app_renderer.h"
 
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
 #include "include/wrapper/cef_library_loader.h"
 #endif
 
@@ -48,18 +50,20 @@
 namespace {
 
 void QuitMessageLoop() {
+  CEF_REQUIRE_UI_THREAD();
   client::MainMessageLoop* message_loop = client::MainMessageLoop::Get();
-  if (message_loop)
+  if (message_loop) {
     message_loop->Quit();
-  else
+  } else {
     CefQuitMessageLoop();
+  }
 }
 
-void sleep(int64 ms) {
+void sleep(int64_t ms) {
 #if defined(OS_WIN)
   Sleep(ms);
 #elif defined(OS_POSIX)
-  usleep(ms * 1000);
+  usleep(static_cast<useconds_t>(ms * 1000));
 #else
 #error Unsupported platform
 #endif
@@ -70,19 +74,20 @@
   // Run the test suite.
   CefTestSuite::GetInstance()->Run();
 
-  // Wait for all browsers to exit.
-  while (TestHandler::HasBrowser())
+  // Wait for all TestHandlers to be destroyed.
+  while (TestHandler::HasTestHandler()) {
     sleep(100);
+  }
 
-  // Quit the CEF message loop.
-  CefPostTask(TID_UI, base::Bind(&QuitMessageLoop));
+  // Wait for the test server to stop, and then quit the CEF message loop.
+  test_server::Stop(base::BindOnce(QuitMessageLoop));
 }
 
 // Called on the UI thread.
 void ContinueOnUIThread(CefRefPtr<CefTaskRunner> test_task_runner) {
   // Run the test suite on the test thread.
   test_task_runner->PostTask(
-      CefCreateClosureTask(base::Bind(&RunTestsOnTestThread)));
+      CefCreateClosureTask(base::BindOnce(&RunTestsOnTestThread)));
 }
 
 #if defined(OS_LINUX) && defined(CEF_X11)
@@ -105,23 +110,38 @@
 }  // namespace
 
 int main(int argc, char* argv[]) {
-#if defined(OS_MACOSX)
+#if !defined(OS_MAC)
+  int exit_code;
+#endif
+
+#if defined(OS_WIN) && defined(ARCH_CPU_32_BITS)
+  // Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
+  // stack size. This function must be called at the top of the executable entry
+  // point function (`main()` or `wWinMain()`). It is used in combination with
+  // the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
+  // flag on executable targets. This saves significant memory on threads (like
+  // those in the Windows thread pool, and others) whose stack size can only be
+  // controlled via the linker flag.
+  exit_code = CefRunMainWithPreferredStackSize(main, argc, argv);
+  if (exit_code >= 0) {
+    // The fiber has completed so return here.
+    return exit_code;
+  }
+#endif
+
+#if defined(OS_MAC)
   // Load the CEF framework library at runtime instead of linking directly
   // as required by the macOS sandbox implementation.
   CefScopedLibraryLoader library_loader;
-  if (!library_loader.LoadInMain())
+  if (!library_loader.LoadInMain()) {
     return 1;
+  }
 #endif
 
   // Create the singleton test suite object.
   CefTestSuite test_suite(argc, argv);
 
 #if defined(OS_WIN)
-  if (test_suite.command_line()->HasSwitch("enable-high-dpi-support")) {
-    // Enable High-DPI support on Windows 7 and newer.
-    CefEnableHighDPISupport();
-  }
-
   CefMainArgs main_args(::GetModuleHandle(nullptr));
 #else
   CefMainArgs main_args(argc, argv);
@@ -141,7 +161,7 @@
       client::ClientApp::GetProcessType(test_suite.command_line());
   if (process_type == client::ClientApp::BrowserProcess) {
     app = new client::ClientAppBrowser();
-#if !defined(OS_MACOSX)
+#if !defined(OS_MAC)
   } else if (process_type == client::ClientApp::RendererProcess ||
              process_type == client::ClientApp::ZygoteProcess) {
     app = new client::ClientAppRenderer();
@@ -150,9 +170,10 @@
   }
 
   // Execute the secondary process, if any.
-  int exit_code = CefExecuteProcess(main_args, app, windows_sandbox_info);
-  if (exit_code >= 0)
+  exit_code = CefExecuteProcess(main_args, app, windows_sandbox_info);
+  if (exit_code >= 0) {
     return exit_code;
+  }
 #else
   } else {
     // On OS X this executable is only used for the main process.
@@ -166,9 +187,11 @@
   settings.no_sandbox = true;
 #endif
 
+  client::ClientAppBrowser::PopulateSettings(test_suite.command_line(),
+                                             settings);
   test_suite.GetSettings(settings);
 
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
   // Platform-specific initialization.
   extern void PlatformInit();
   PlatformInit();
@@ -182,12 +205,13 @@
 #endif
 
   // Create the MessageLoop.
-  scoped_ptr<client::MainMessageLoop> message_loop;
+  std::unique_ptr<client::MainMessageLoop> message_loop;
   if (!settings.multi_threaded_message_loop) {
-    if (settings.external_message_pump)
+    if (settings.external_message_pump) {
       message_loop = client::MainMessageLoopExternalPump::Create();
-    else
+    } else {
       message_loop.reset(new client::MainMessageLoopStd);
+    }
   }
 
   // Initialize CEF.
@@ -201,16 +225,23 @@
   if (settings.multi_threaded_message_loop) {
     // Run the test suite on the main thread.
     retval = test_suite.Run();
+
+    // Wait for the test server to stop.
+    CefRefPtr<CefWaitableEvent> event =
+        CefWaitableEvent::CreateWaitableEvent(true, false);
+    test_server::Stop(base::BindOnce(&CefWaitableEvent::Signal, event));
+    event->Wait();
   } else {
     // Create and start the test thread.
     CefRefPtr<CefThread> thread = CefThread::CreateThread("test_thread");
-    if (!thread)
+    if (!thread) {
       return 1;
+    }
 
     // Start the tests from the UI thread so that any pending UI tasks get a
     // chance to execute first.
     CefPostTask(TID_UI,
-                base::Bind(&ContinueOnUIThread, thread->GetTaskRunner()));
+                base::BindOnce(&ContinueOnUIThread, thread->GetTaskRunner()));
 
     // Run the CEF message loop.
     message_loop->Run();
@@ -231,7 +262,7 @@
   // Destroy the MessageLoop.
   message_loop.reset(nullptr);
 
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
   // Platform-specific cleanup.
   extern void PlatformCleanup();
   PlatformCleanup();
diff --git a/src/tests/ceftests/run_all_unittests_mac.mm b/src/tests/ceftests/run_all_unittests_mac.mm
index 2c8c17b..e9f92d2 100644
--- a/src/tests/ceftests/run_all_unittests_mac.mm
+++ b/src/tests/ceftests/run_all_unittests_mac.mm
@@ -5,11 +5,13 @@
 #include "include/cef_app.h"
 #import "include/cef_application_mac.h"
 
+#if !__has_feature(objc_arc)
 // Memory AutoRelease pool.
 static NSAutoreleasePool* g_autopool = nil;
+#endif
 
 // Provide the CefAppProtocol implementation required by CEF.
-@interface TestApplication : NSApplication<CefAppProtocol> {
+@interface TestApplication : NSApplication <CefAppProtocol> {
  @private
   BOOL handlingSendEvent_;
 }
@@ -31,14 +33,18 @@
 @end
 
 void PlatformInit() {
+#if !__has_feature(objc_arc)
   // Initialize the AutoRelease pool.
   g_autopool = [[NSAutoreleasePool alloc] init];
+#endif
 
   // Initialize the TestApplication instance.
   [TestApplication sharedApplication];
 }
 
 void PlatformCleanup() {
+#if !__has_feature(objc_arc)
   // Release the AutoRelease pool.
   [g_autopool release];
+#endif
 }
diff --git a/src/tests/ceftests/scheme_handler_unittest.cc b/src/tests/ceftests/scheme_handler_unittest.cc
index 4fd4d07..7389d0b 100644
--- a/src/tests/ceftests/scheme_handler_unittest.cc
+++ b/src/tests/ceftests/scheme_handler_unittest.cc
@@ -3,10 +3,13 @@
 // can be found in the LICENSE file.
 
 #include <algorithm>
+#include <vector>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_callback.h"
 #include "include/cef_origin_whitelist.h"
+#include "include/cef_request_context.h"
+#include "include/cef_request_context_handler.h"
 #include "include/cef_scheme.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "tests/ceftests/test_handler.h"
@@ -17,43 +20,19 @@
 
 class TestResults {
  public:
-  TestResults() : status_code(200), sub_status_code(200), delay(0) {}
+  TestResults() = default;
 
-  void reset() {
-    url.clear();
-    html.clear();
-    status_code = 200;
-    response_error_code = ERR_NONE;
-    expected_error_code = ERR_NONE;
-    redirect_url.clear();
-    sub_url.clear();
-    sub_html.clear();
-    sub_status_code = 200;
-    sub_allow_origin.clear();
-    exit_url.clear();
-    accept_language.clear();
-    delay = 0;
-    got_request.reset();
-    got_read.reset();
-    got_output.reset();
-    got_sub_output.reset();
-    got_redirect.reset();
-    got_error.reset();
-    got_sub_error.reset();
-    got_sub_request.reset();
-    got_sub_read.reset();
-    got_sub_success.reset();
-    got_exit_request.reset();
-  }
+  // Used for running tests in a custom request context.
+  CefRefPtr<CefRequestContext> request_context;
 
   std::string url;
   std::string html;
-  int status_code;
+  int status_code = 200;
 
   // Error code set on the response.
-  cef_errorcode_t response_error_code;
+  cef_errorcode_t response_error_code = ERR_NONE;
   // Error code expected in OnLoadError.
-  cef_errorcode_t expected_error_code;
+  cef_errorcode_t expected_error_code = ERR_NONE;
 
   // Used for testing redirects
   std::string redirect_url;
@@ -61,20 +40,26 @@
   // Used for testing XHR requests
   std::string sub_url;
   std::string sub_html;
-  int sub_status_code;
+  int sub_status_code = 200;
   std::string sub_allow_origin;
   std::string sub_redirect_url;
   std::string exit_url;
 
-  // Used for testing per-browser Accept-Language.
+  // Used for testing XSS requests
+  bool needs_same_origin_policy_relaxation = false;
+
+  // Used for testing Accept-Language.
   std::string accept_language;
 
+  // Used for testing received console messages.
+  std::vector<std::string> console_messages;
+
   // Delay for returning scheme handler results.
-  int delay;
+  int delay = 0;
 
   TrackCallback got_request, got_read, got_output, got_sub_output, got_redirect,
       got_error, got_sub_error, got_sub_redirect, got_sub_request, got_sub_read,
-      got_sub_success, got_exit_request;
+      git_exit_success, got_exit_request;
 };
 
 // Current scheme handler object. Used when destroying the test from
@@ -88,15 +73,8 @@
     g_current_handler = this;
   }
 
-  void PopulateBrowserSettings(CefBrowserSettings* settings) override {
-    if (!test_results_->accept_language.empty()) {
-      CefString(&settings->accept_language_list) =
-          test_results_->accept_language;
-    }
-  }
-
   void RunTest() override {
-    CreateBrowser(test_results_->url);
+    CreateBrowser(test_results_->url, test_results_->request_context);
 
     // Time out the test after a reasonable period of time.
     SetTestTimeout();
@@ -104,7 +82,13 @@
 
   // Necessary to make the method public in order to destroy the test from
   // ClientSchemeHandler::ProcessRequest().
-  void DestroyTest() override { TestHandler::DestroyTest(); }
+  void DestroyTest() override {
+    EXPECT_TRUE(test_results_->console_messages.empty())
+        << "Did not receive expected console message: "
+        << test_results_->console_messages.front();
+
+    TestHandler::DestroyTest();
+  }
 
   void DestroyTestIfDone() {
     if (!test_results_->exit_url.empty() && !test_results_->got_exit_request) {
@@ -133,13 +117,19 @@
       CefRefPtr<CefBrowser> browser,
       CefRefPtr<CefFrame> frame,
       CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) override {
+      CefRefPtr<CefCallback> callback) override {
+    if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
+      // Ignore favicon requests.
+      return RV_CANCEL;
+    }
+
     const std::string& newUrl = request->GetURL();
     if (IsExitURL(newUrl)) {
       test_results_->got_exit_request.yes();
       // XHR tests use an exit URL to destroy the test.
-      if (newUrl.find("SUCCESS") != std::string::npos)
-        test_results_->got_sub_success.yes();
+      if (newUrl.find("SUCCESS") != std::string::npos) {
+        test_results_->git_exit_success.yes();
+      }
       DestroyTestIfDone();
       return RV_CANCEL;
     }
@@ -168,12 +158,13 @@
                  CefRefPtr<CefFrame> frame,
                  int httpStatusCode) override {
     const std::string& url = frame->GetURL();
-    if (url == test_results_->url)
+    if (url == test_results_->url) {
       test_results_->got_output.yes();
-    else if (url == test_results_->sub_url)
+    } else if (url == test_results_->sub_url) {
       test_results_->got_sub_output.yes();
-    else if (IsExitURL(url))
+    } else if (IsExitURL(url)) {
       return;
+    }
 
     if (url == test_results_->url || test_results_->status_code != 200) {
       // Test that the status code is correct.
@@ -189,16 +180,17 @@
                    const CefString& errorText,
                    const CefString& failedUrl) override {
     const std::string& url = failedUrl;
-    if (url == test_results_->url)
+    if (url == test_results_->url) {
       test_results_->got_error.yes();
-    else if (url == test_results_->sub_url)
+    } else if (url == test_results_->sub_url) {
       test_results_->got_sub_error.yes();
-    else if (IsExitURL(url))
+    } else if (IsExitURL(url)) {
       return;
+    }
 
-    // Tests sometimes also fail with ERR_ABORTED.
+    // Tests sometimes also fail with ERR_ABORTED or ERR_UNKNOWN_URL_SCHEME.
     if (!(test_results_->expected_error_code == 0 &&
-          errorCode == ERR_ABORTED)) {
+          (errorCode == ERR_ABORTED || errorCode == ERR_UNKNOWN_URL_SCHEME))) {
       EXPECT_EQ(test_results_->expected_error_code, errorCode)
           << failedUrl.ToString();
     }
@@ -206,8 +198,33 @@
     DestroyTestIfDone();
   }
 
+  bool OnConsoleMessage(CefRefPtr<CefBrowser> browser,
+                        cef_log_severity_t level,
+                        const CefString& message,
+                        const CefString& source,
+                        int line) override {
+    bool expected = false;
+    if (!test_results_->console_messages.empty()) {
+      std::vector<std::string>::iterator it =
+          test_results_->console_messages.begin();
+      for (; it != test_results_->console_messages.end(); ++it) {
+        const std::string& possible = *it;
+        const std::string& actual = message.ToString();
+        if (actual.find(possible) == 0U) {
+          expected = true;
+          test_results_->console_messages.erase(it);
+          break;
+        }
+      }
+    }
+
+    EXPECT_TRUE(expected) << "Unexpected console message: "
+                          << message.ToString();
+    return false;
+  }
+
  protected:
-  TestResults* test_results_;
+  TestResults* const test_results_;
 
   IMPLEMENT_REFCOUNTING(TestSchemeHandler);
 };
@@ -230,15 +247,17 @@
     if (is_sub_) {
       test_results_->got_sub_request.yes();
 
-      if (!test_results_->sub_html.empty())
+      if (!test_results_->sub_html.empty()) {
         handled = true;
+      }
     } else {
       EXPECT_EQ(url, test_results_->url);
 
       test_results_->got_request.yes();
 
-      if (!test_results_->html.empty())
+      if (!test_results_->html.empty()) {
         handled = true;
+      }
     }
 
     std::string accept_language;
@@ -246,13 +265,13 @@
     CefRequest::HeaderMap::iterator headerIter;
     request->GetHeaderMap(headerMap);
     headerIter = headerMap.find("Accept-Language");
-    if (headerIter != headerMap.end())
+    if (headerIter != headerMap.end()) {
       accept_language = headerIter->second;
+    }
     EXPECT_TRUE(!accept_language.empty());
 
     if (!test_results_->accept_language.empty()) {
-      // Value from CefBrowserSettings.accept_language set in
-      // PopulateBrowserSettings().
+      // Value from CefRequestContextSettings.accept_language_list.
       EXPECT_STREQ(test_results_->accept_language.data(),
                    accept_language.data());
     } else {
@@ -265,9 +284,9 @@
     if (handled) {
       if (test_results_->delay > 0) {
         // Continue after the delay.
-        CefPostDelayedTask(TID_IO,
-                           base::Bind(&CefCallback::Continue, callback.get()),
-                           test_results_->delay);
+        CefPostDelayedTask(
+            TID_IO, base::BindOnce(&CefCallback::Continue, callback.get()),
+            test_results_->delay);
       } else {
         // Continue immediately.
         callback->Continue();
@@ -280,24 +299,25 @@
     }
 
     // Response was canceled.
-    if (g_current_handler)
+    if (g_current_handler) {
       g_current_handler->DestroyTest();
+    }
     return false;
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
+    CefResponse::HeaderMap headers;
+
     if (is_sub_) {
       response->SetStatus(test_results_->sub_status_code);
 
       if (!test_results_->sub_allow_origin.empty()) {
         // Set the Access-Control-Allow-Origin header to allow cross-domain
         // scripting.
-        CefResponse::HeaderMap headers;
         headers.insert(std::make_pair("Access-Control-Allow-Origin",
                                       test_results_->sub_allow_origin));
-        response->SetHeaderMap(headers);
       }
 
       if (!test_results_->sub_html.empty()) {
@@ -316,6 +336,15 @@
         response_length = test_results_->html.size();
       }
     }
+
+    if (test_results_->needs_same_origin_policy_relaxation) {
+      // Apply same-origin policy relaxation for document.domain.
+      headers.insert(std::make_pair("Origin-Agent-Cluster", "?0"));
+    }
+
+    if (!headers.empty()) {
+      response->SetHeaderMap(headers);
+    }
   }
 
   void Cancel() override { EXPECT_TRUE(CefCurrentlyOn(TID_IO)); }
@@ -331,8 +360,8 @@
         // Continue after a delay.
         CefPostDelayedTask(
             TID_IO,
-            base::Bind(&ClientSchemeHandlerOld::ContinueAfterDelay, this,
-                       callback),
+            base::BindOnce(&ClientSchemeHandlerOld::ContinueAfterDelay, this,
+                           callback),
             test_results_->delay);
         bytes_read = 0;
         return true;
@@ -374,7 +403,7 @@
     callback->Continue();
   }
 
-  TestResults* test_results_;
+  TestResults* const test_results_;
   size_t offset_;
   bool is_sub_;
   bool has_delayed_;
@@ -393,6 +422,11 @@
             CefRefPtr<CefCallback> callback) override {
     EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
 
+    if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
+      // Ignore favicon requests.
+      return false;
+    }
+
     bool handled = false;
 
     std::string url = request->GetURL();
@@ -402,15 +436,17 @@
     if (is_sub_) {
       test_results_->got_sub_request.yes();
 
-      if (!test_results_->sub_html.empty())
+      if (!test_results_->sub_html.empty()) {
         handled = true;
+      }
     } else {
       EXPECT_EQ(url, test_results_->url);
 
       test_results_->got_request.yes();
 
-      if (!test_results_->html.empty())
+      if (!test_results_->html.empty()) {
         handled = true;
+      }
     }
 
     std::string accept_language;
@@ -418,13 +454,13 @@
     CefRequest::HeaderMap::iterator headerIter;
     request->GetHeaderMap(headerMap);
     headerIter = headerMap.find("Accept-Language");
-    if (headerIter != headerMap.end())
+    if (headerIter != headerMap.end()) {
       accept_language = headerIter->second;
+    }
     EXPECT_TRUE(!accept_language.empty());
 
     if (!test_results_->accept_language.empty()) {
-      // Value from CefBrowserSettings.accept_language set in
-      // PopulateBrowserSettings().
+      // Value from CefRequestContextSettings.accept_language_list.
       EXPECT_STREQ(test_results_->accept_language.data(),
                    accept_language.data());
     } else {
@@ -441,9 +477,10 @@
       if (test_results_->delay > 0) {
         // Continue after the delay.
         handle_request = false;
-        CefPostDelayedTask(TID_FILE_USER_BLOCKING,
-                           base::Bind(&CefCallback::Continue, callback.get()),
-                           test_results_->delay);
+        CefPostDelayedTask(
+            TID_FILE_USER_BLOCKING,
+            base::BindOnce(&CefCallback::Continue, callback.get()),
+            test_results_->delay);
       }
       return true;
     } else if (test_results_->response_error_code != ERR_NONE) {
@@ -452,30 +489,36 @@
     }
 
     // Response was canceled.
-    if (g_current_handler)
+    if (g_current_handler) {
       g_current_handler->DestroyTest();
+    }
     return false;
   }
 
   bool ProcessRequest(CefRefPtr<CefRequest> request,
                       CefRefPtr<CefCallback> callback) override {
+    if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
+      // Ignore favicon requests.
+      return false;
+    }
+
     EXPECT_TRUE(false);  // Not reached.
     return false;
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
+    CefResponse::HeaderMap headers;
+
     if (is_sub_) {
       response->SetStatus(test_results_->sub_status_code);
 
       if (!test_results_->sub_allow_origin.empty()) {
         // Set the Access-Control-Allow-Origin header to allow cross-domain
         // scripting.
-        CefResponse::HeaderMap headers;
         headers.insert(std::make_pair("Access-Control-Allow-Origin",
                                       test_results_->sub_allow_origin));
-        response->SetHeaderMap(headers);
       }
 
       if (!test_results_->sub_html.empty()) {
@@ -494,6 +537,15 @@
         response_length = test_results_->html.size();
       }
     }
+
+    if (test_results_->needs_same_origin_policy_relaxation) {
+      // Apply same-origin policy relaxation for document.domain.
+      headers.insert(std::make_pair("Origin-Agent-Cluster", "?0"));
+    }
+
+    if (!headers.empty()) {
+      response->SetHeaderMap(headers);
+    }
   }
 
   void Cancel() override { EXPECT_TRUE(CefCurrentlyOn(TID_IO)); }
@@ -507,10 +559,11 @@
     if (test_results_->delay > 0) {
       if (!has_delayed_) {
         // Continue after a delay.
-        CefPostDelayedTask(TID_FILE_USER_BLOCKING,
-                           base::Bind(&ClientSchemeHandler::ContinueAfterDelay,
-                                      this, data_out, bytes_to_read, callback),
-                           test_results_->delay);
+        CefPostDelayedTask(
+            TID_FILE_USER_BLOCKING,
+            base::BindOnce(&ClientSchemeHandler::ContinueAfterDelay, this,
+                           data_out, bytes_to_read, callback),
+            test_results_->delay);
         bytes_read = 0;
         return true;
       }
@@ -572,7 +625,7 @@
     return has_data;
   }
 
-  TestResults* test_results_;
+  TestResults* const test_results_;
   size_t offset_;
   bool is_sub_;
   bool has_delayed_;
@@ -596,57 +649,64 @@
     return new ClientSchemeHandler(test_results_);
   }
 
-  TestResults* test_results_;
+  TestResults* const test_results_;
 
   IMPLEMENT_REFCOUNTING(ClientSchemeHandlerFactory);
   DISALLOW_COPY_AND_ASSIGN(ClientSchemeHandlerFactory);
 };
 
-// Global test results object.
-TestResults g_TestResults;
-
 // If |domain| is empty the scheme will be registered as non-standard.
-void RegisterTestScheme(const std::string& scheme, const std::string& domain) {
-  g_TestResults.reset();
-
-  EXPECT_TRUE(CefRegisterSchemeHandlerFactory(
-      scheme, domain, new ClientSchemeHandlerFactory(&g_TestResults)));
+void RegisterTestScheme(TestResults* test_results,
+                        const std::string& scheme,
+                        const std::string& domain) {
+  if (test_results->request_context) {
+    EXPECT_TRUE(test_results->request_context->RegisterSchemeHandlerFactory(
+        scheme, domain, new ClientSchemeHandlerFactory(test_results)));
+  } else {
+    EXPECT_TRUE(CefRegisterSchemeHandlerFactory(
+        scheme, domain, new ClientSchemeHandlerFactory(test_results)));
+  }
   WaitForIOThread();
 }
 
-void ClearTestSchemes() {
-  EXPECT_TRUE(CefClearSchemeHandlerFactories());
+void ClearTestSchemes(TestResults* test_results) {
+  if (test_results->request_context) {
+    EXPECT_TRUE(test_results->request_context->ClearSchemeHandlerFactories());
+  } else {
+    EXPECT_TRUE(CefClearSchemeHandlerFactories());
+  }
   WaitForIOThread();
 }
 
 struct XHRTestSettings {
-  XHRTestSettings() : synchronous(true) {}
+  XHRTestSettings() = default;
 
   std::string url;
   std::string sub_url;
   std::string sub_allow_origin;
   std::string sub_redirect_url;
-  bool synchronous;
+  bool synchronous = true;
 };
 
-void SetUpXHR(const XHRTestSettings& settings) {
-  g_TestResults.sub_url = settings.sub_url;
-  g_TestResults.sub_html = "SUCCESS";
-  g_TestResults.sub_allow_origin = settings.sub_allow_origin;
-  g_TestResults.sub_redirect_url = settings.sub_redirect_url;
+void SetUpXHR(TestResults* test_results, const XHRTestSettings& settings) {
+  test_results->sub_url = settings.sub_url;
+  test_results->sub_html = "SUCCESS";
+  test_results->sub_allow_origin = settings.sub_allow_origin;
+  test_results->sub_redirect_url = settings.sub_redirect_url;
 
   std::string request_url;
-  if (!settings.sub_redirect_url.empty())
+  if (!settings.sub_redirect_url.empty()) {
     request_url = settings.sub_redirect_url;
-  else
+  } else {
     request_url = settings.sub_url;
+  }
 
-  g_TestResults.url = settings.url;
+  test_results->url = settings.url;
   std::stringstream ss;
   ss << "<html><head>"
         "<script language=\"JavaScript\">"
         "function onResult(val) {"
-        "  document.location = \"http://tests/exit?result=\"+val;"
+        "  document.location = \"https://tests/exit?result=\"+val;"
         "}"
         "function execXMLHttpRequest() {";
   if (settings.synchronous) {
@@ -677,7 +737,6 @@
           "  }"
           "};"
           "xhr.onerror = function(e) {"
-          "  console.log('XMLHttpRequest failed with error ' + e);"
           "  onResult('FAILURE');"
           "};"
           "xhr.send()";
@@ -687,13 +746,13 @@
         "</head><body onload=\"execXMLHttpRequest();\">"
         "Running execXMLHttpRequest..."
         "</body></html>";
-  g_TestResults.html = ss.str();
+  test_results->html = ss.str();
 
-  g_TestResults.exit_url = "http://tests/exit";
+  test_results->exit_url = "https://tests/exit";
 }
 
 struct FetchTestSettings {
-  FetchTestSettings() {}
+  FetchTestSettings() = default;
 
   std::string url;
   std::string sub_url;
@@ -701,24 +760,25 @@
   std::string sub_redirect_url;
 };
 
-void SetUpFetch(const FetchTestSettings& settings) {
-  g_TestResults.sub_url = settings.sub_url;
-  g_TestResults.sub_html = "SUCCESS";
-  g_TestResults.sub_allow_origin = settings.sub_allow_origin;
-  g_TestResults.sub_redirect_url = settings.sub_redirect_url;
+void SetUpFetch(TestResults* test_results, const FetchTestSettings& settings) {
+  test_results->sub_url = settings.sub_url;
+  test_results->sub_html = "SUCCESS";
+  test_results->sub_allow_origin = settings.sub_allow_origin;
+  test_results->sub_redirect_url = settings.sub_redirect_url;
 
   std::string request_url;
-  if (!settings.sub_redirect_url.empty())
+  if (!settings.sub_redirect_url.empty()) {
     request_url = settings.sub_redirect_url;
-  else
+  } else {
     request_url = settings.sub_url;
+  }
 
-  g_TestResults.url = settings.url;
+  test_results->url = settings.url;
   std::stringstream ss;
   ss << "<html><head>"
         "<script language=\"JavaScript\">"
         "function onResult(val) {"
-        "  document.location = \"http://tests/exit?result=\"+val;"
+        "  document.location = \"https://tests/exit?result=\"+val;"
         "}"
         "function execFetchHttpRequest() {";
   ss << "fetch('" << request_url.c_str()
@@ -728,16 +788,12 @@
         "      response.text().then(function(text) {"
         "          onResult(text);"
         "      }).catch(function(e) {"
-        "          console.log('FetchHttpRequest failed with error ' + e);"
         "          onResult('FAILURE');        "
         "      });"
         "  } else {"
-        "      console.log('XMLHttpRequest failed with status ' + "
-        "      response.status);"
         "      onResult('FAILURE');"
         "  }"
         "}).catch(function(e) {"
-        "  console.log('FetchHttpRequest failed with error ' + e);"
         "  onResult('FAILURE');"
         "});"
      << "}"
@@ -745,12 +801,13 @@
         "</head><body onload=\"execFetchHttpRequest();\">"
         "Running execFetchHttpRequest..."
         "</body></html>";
-  g_TestResults.html = ss.str();
+  test_results->html = ss.str();
 
-  g_TestResults.exit_url = "http://tests/exit";
+  test_results->exit_url = "https://tests/exit";
 }  // namespace
 
-void SetUpXSS(const std::string& url,
+void SetUpXSS(TestResults* test_results,
+              const std::string& url,
               const std::string& sub_url,
               const std::string& domain = std::string()) {
   // 1. Load |url| which contains an iframe.
@@ -760,10 +817,14 @@
 
   std::stringstream ss;
   std::string domain_line;
-  if (!domain.empty())
+  if (!domain.empty()) {
     domain_line = "document.domain = '" + domain + "';";
+    if (url.find("http") == 0 && sub_url.find("http") == 0) {
+      test_results->needs_same_origin_policy_relaxation = true;
+    }
+  }
 
-  g_TestResults.sub_url = sub_url;
+  test_results->sub_url = sub_url;
   ss << "<html><head>"
         "<script language=\"JavaScript\">"
      << domain_line
@@ -775,15 +836,15 @@
         "  try {"
         "    result = parent.getResult();"
         "  } catch(e) { console.log(e.stack); }"
-        "  document.location = \"http://tests/exit?result=\"+result;"
+        "  document.location = \"https://tests/exit?result=\"+result;"
         "}"
         "</script>"
         "</head><body onload=\"execXSSRequest();\">"
         "Running execXSSRequest..."
         "</body></html>";
-  g_TestResults.sub_html = ss.str();
+  test_results->sub_html = ss.str();
 
-  g_TestResults.url = url;
+  test_results->url = url;
   ss.str("");
   ss << "<html><head>"
         "<script language=\"JavaScript\">"
@@ -801,1640 +862,1855 @@
      << sub_url.c_str()
      << "\" id=\"s\">"
         "</body></html>";
-  g_TestResults.html = ss.str();
+  test_results->html = ss.str();
 
-  g_TestResults.exit_url = "http://tests/exit";
+  test_results->exit_url = "https://tests/exit";
 }
 
 }  // namespace
 
 // Test that scheme registration/unregistration works as expected.
 TEST(SchemeHandlerTest, Registration) {
-  RegisterTestScheme("customstd", "test");
-  g_TestResults.url = "customstd://test/run.html";
-  g_TestResults.html =
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test");
+  test_results.url = "customstd://test/run.html";
+  test_results.html =
       "<html><head></head><body><h1>Success!</h1></body></html>";
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
 
   // Unregister the handler.
   EXPECT_TRUE(CefRegisterSchemeHandlerFactory("customstd", "test", nullptr));
   WaitForIOThread();
 
-  g_TestResults.got_request.reset();
-  g_TestResults.got_read.reset();
-  g_TestResults.got_output.reset();
-  g_TestResults.expected_error_code = ERR_UNKNOWN_URL_SCHEME;
+  test_results.got_request.reset();
+  test_results.got_read.reset();
+  test_results.got_output.reset();
+  test_results.expected_error_code = ERR_UNKNOWN_URL_SCHEME;
   handler->ExecuteTest();
 
-  EXPECT_TRUE(g_TestResults.got_error);
-  EXPECT_FALSE(g_TestResults.got_request);
-  EXPECT_FALSE(g_TestResults.got_read);
-  EXPECT_FALSE(g_TestResults.got_output);
+  EXPECT_TRUE(test_results.got_error);
+  EXPECT_FALSE(test_results.got_request);
+  EXPECT_FALSE(test_results.got_read);
+  EXPECT_FALSE(test_results.got_output);
 
   // Re-register the handler.
   EXPECT_TRUE(CefRegisterSchemeHandlerFactory(
-      "customstd", "test", new ClientSchemeHandlerFactory(&g_TestResults)));
+      "customstd", "test", new ClientSchemeHandlerFactory(&test_results)));
   WaitForIOThread();
 
-  g_TestResults.got_error.reset();
-  g_TestResults.expected_error_code = ERR_NONE;
+  test_results.got_error.reset();
+  test_results.expected_error_code = ERR_NONE;
   handler->ExecuteTest();
 
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_FALSE(g_TestResults.got_error);
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
+  EXPECT_FALSE(test_results.got_error);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can return normal results.
 TEST(SchemeHandlerTest, CustomStandardNormalResponse) {
-  RegisterTestScheme("customstd", "test");
-  g_TestResults.url = "customstd://test/run.html";
-  g_TestResults.html =
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test");
+  test_results.url = "customstd://test/run.html";
+  test_results.html =
       "<html><head></head><body><h1>Success!</h1></body></html>";
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can return normal results with delayed
 // responses.
 TEST(SchemeHandlerTest, CustomStandardNormalResponseDelayed) {
-  RegisterTestScheme("customstd", "test");
-  g_TestResults.url = "customstd://test/run.html";
-  g_TestResults.html =
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test");
+  test_results.url = "customstd://test/run.html";
+  test_results.html =
       "<html><head></head><body><h1>Success!</h1></body></html>";
-  g_TestResults.delay = 100;
+  test_results.delay = 100;
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom nonstandard scheme can return normal results.
 TEST(SchemeHandlerTest, CustomNonStandardNormalResponse) {
-  RegisterTestScheme("customnonstd", std::string());
-  g_TestResults.url = "customnonstd:some%20value";
-  g_TestResults.html =
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customnonstd", std::string());
+  test_results.url = "customnonstd:some%20value";
+  test_results.html =
       "<html><head></head><body><h1>Success!</h1></body></html>";
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can return an error code.
 TEST(SchemeHandlerTest, CustomStandardErrorResponse) {
-  RegisterTestScheme("customstd", "test");
-  g_TestResults.url = "customstd://test/run.html";
-  g_TestResults.html = "<html><head></head><body><h1>404</h1></body></html>";
-  g_TestResults.status_code = 404;
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test");
+  test_results.url = "customstd://test/run.html";
+  test_results.html = "<html><head></head><body><h1>404</h1></body></html>";
+  test_results.status_code = 404;
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can return a CEF error code in the
 // response.
 TEST(SchemeHandlerTest, CustomStandardErrorCodeResponse) {
-  RegisterTestScheme("customstd", "test");
-  g_TestResults.url = "customstd://test/run.html";
-  g_TestResults.response_error_code = ERR_FILE_TOO_BIG;
-  g_TestResults.expected_error_code = ERR_FILE_TOO_BIG;
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test");
+  test_results.url = "customstd://test/run.html";
+  test_results.response_error_code = ERR_FILE_TOO_BIG;
+  test_results.expected_error_code = ERR_FILE_TOO_BIG;
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_FALSE(g_TestResults.got_read);
-  EXPECT_FALSE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_error);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_FALSE(test_results.got_read);
+  EXPECT_FALSE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_error);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom nonstandard scheme can return an error code.
 TEST(SchemeHandlerTest, CustomNonStandardErrorResponse) {
-  RegisterTestScheme("customnonstd", std::string());
-  g_TestResults.url = "customnonstd:some%20value";
-  g_TestResults.html = "<html><head></head><body><h1>404</h1></body></html>";
-  g_TestResults.status_code = 404;
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customnonstd", std::string());
+  test_results.url = "customnonstd:some%20value";
+  test_results.html = "<html><head></head><body><h1>404</h1></body></html>";
+  test_results.status_code = 404;
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that custom standard scheme handling fails when the scheme name is
 // incorrect.
 TEST(SchemeHandlerTest, CustomStandardNameNotHandled) {
-  RegisterTestScheme("customstd", "test");
-  g_TestResults.url = "customstd2://test/run.html";
-  g_TestResults.expected_error_code = ERR_UNKNOWN_URL_SCHEME;
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test");
+  test_results.url = "customstd2://test/run.html";
+  test_results.expected_error_code = ERR_UNKNOWN_URL_SCHEME;
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_FALSE(g_TestResults.got_request);
-  EXPECT_FALSE(g_TestResults.got_read);
-  EXPECT_FALSE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_error);
+  EXPECT_FALSE(test_results.got_request);
+  EXPECT_FALSE(test_results.got_read);
+  EXPECT_FALSE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_error);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that custom nonstandard scheme handling fails when the scheme name is
 // incorrect.
 TEST(SchemeHandlerTest, CustomNonStandardNameNotHandled) {
-  RegisterTestScheme("customnonstd", std::string());
-  g_TestResults.url = "customnonstd2:some%20value";
-  g_TestResults.expected_error_code = ERR_UNKNOWN_URL_SCHEME;
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customnonstd", std::string());
+  test_results.url = "customnonstd2:some%20value";
+  test_results.expected_error_code = ERR_UNKNOWN_URL_SCHEME;
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_FALSE(g_TestResults.got_request);
-  EXPECT_FALSE(g_TestResults.got_read);
-  EXPECT_FALSE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_error);
+  EXPECT_FALSE(test_results.got_request);
+  EXPECT_FALSE(test_results.got_read);
+  EXPECT_FALSE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_error);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that custom standard scheme handling fails when the domain name is
 // incorrect.
 TEST(SchemeHandlerTest, CustomStandardDomainNotHandled) {
-  RegisterTestScheme("customstd", "test");
-  g_TestResults.url = "customstd://noexist/run.html";
-  g_TestResults.expected_error_code = ERR_UNKNOWN_URL_SCHEME;
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test");
+  test_results.url = "customstd://noexist/run.html";
+  test_results.expected_error_code = ERR_UNKNOWN_URL_SCHEME;
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_FALSE(g_TestResults.got_request);
-  EXPECT_FALSE(g_TestResults.got_read);
-  EXPECT_FALSE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_error);
+  EXPECT_FALSE(test_results.got_request);
+  EXPECT_FALSE(test_results.got_read);
+  EXPECT_FALSE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_error);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can return no response.
 TEST(SchemeHandlerTest, CustomStandardNoResponse) {
-  RegisterTestScheme("customstd", "test");
-  g_TestResults.url = "customstd://test/run.html";
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test");
+  test_results.url = "customstd://test/run.html";
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_FALSE(g_TestResults.got_read);
-  EXPECT_FALSE(g_TestResults.got_output);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_FALSE(test_results.got_read);
+  EXPECT_FALSE(test_results.got_output);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom nonstandard scheme can return no response.
 TEST(SchemeHandlerTest, CustomNonStandardNoResponse) {
-  RegisterTestScheme("customnonstd", std::string());
-  g_TestResults.url = "customnonstd:some%20value";
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customnonstd", std::string());
+  test_results.url = "customnonstd:some%20value";
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_FALSE(g_TestResults.got_read);
-  EXPECT_FALSE(g_TestResults.got_output);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_FALSE(test_results.got_read);
+  EXPECT_FALSE(test_results.got_output);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can generate redirects.
 TEST(SchemeHandlerTest, CustomStandardRedirect) {
-  RegisterTestScheme("customstd", "test");
-  g_TestResults.url = "customstd://test/run.html";
-  g_TestResults.redirect_url = "customstd://test/redirect.html";
-  g_TestResults.html =
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test");
+  test_results.url = "customstd://test/run.html";
+  test_results.redirect_url = "customstd://test/redirect.html";
+  test_results.html =
       "<html><head></head><body><h1>Redirected</h1></body></html>";
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_redirect);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_redirect);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom nonstandard scheme can generate redirects.
 TEST(SchemeHandlerTest, CustomNonStandardRedirect) {
-  RegisterTestScheme("customnonstd", std::string());
-  g_TestResults.url = "customnonstd:some%20value";
-  g_TestResults.redirect_url = "customnonstd:some%20other%20value";
-  g_TestResults.html =
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customnonstd", std::string());
+  test_results.url = "customnonstd:some%20value";
+  test_results.redirect_url = "customnonstd:some%20other%20value";
+  test_results.html =
       "<html><head></head><body><h1>Redirected</h1></body></html>";
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_redirect);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_redirect);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can generate same origin XHR requests.
 TEST(SchemeHandlerTest, CustomStandardXHRSameOriginSync) {
-  RegisterTestScheme("customstd", "test");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test");
 
   XHRTestSettings settings;
   settings.url = "customstd://test/run.html";
   settings.sub_url = "customstd://test/xhr.html";
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can generate same origin XHR requests.
 TEST(SchemeHandlerTest, CustomStandardXHRSameOriginAsync) {
-  RegisterTestScheme("customstd", "test");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test");
 
   XHRTestSettings settings;
   settings.url = "customstd://test/run.html";
   settings.sub_url = "customstd://test/xhr.html";
   settings.synchronous = false;
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that custom nonstandard schemes are treated as unique origins that
 // cannot generate XHR requests.
 TEST(SchemeHandlerTest, CustomNonStandardXHRSameOriginSync) {
-  RegisterTestScheme("customnonstd", std::string());
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customnonstd", std::string());
 
   XHRTestSettings settings;
   settings.url = "customnonstd:some%20value";
   settings.sub_url = "customnonstd:xhr%20value";
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Access to XMLHttpRequest at 'customnonstd:xhr%20value' from origin "
+      "'null' has been blocked by CORS policy: Cross origin requests are only "
+      "supported for protocol schemes:");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_FALSE(g_TestResults.got_sub_request);
-  EXPECT_FALSE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_FALSE(test_results.got_sub_request);
+  EXPECT_FALSE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that custom nonstandard schemes are treated as unique origins that
 // cannot generate XHR requests.
 TEST(SchemeHandlerTest, CustomNonStandardXHRSameOriginAsync) {
-  RegisterTestScheme("customnonstd", std::string());
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customnonstd", std::string());
 
   XHRTestSettings settings;
   settings.url = "customnonstd:some%20value";
   settings.sub_url = "customnonstd:xhr%20value";
   settings.synchronous = false;
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Access to XMLHttpRequest at 'customnonstd:xhr%20value' from origin "
+      "'null' has been blocked by CORS policy: Cross origin requests are only "
+      "supported for protocol schemes:");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_FALSE(g_TestResults.got_sub_request);
-  EXPECT_FALSE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_FALSE(test_results.got_sub_request);
+  EXPECT_FALSE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a non fetch enabled custom standard scheme can't generate same
 // origin Fetch requests.
 TEST(SchemeHandlerTest, CustomStandardFetchSameOrigin) {
-  RegisterTestScheme("customstd", "test");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test");
 
   FetchTestSettings settings;
   settings.url = "customstd://test/run.html";
   settings.sub_url = "customstd://test/fetch.html";
-  SetUpFetch(settings);
+  SetUpFetch(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Fetch API cannot load customstd://test/fetch.html. URL scheme "
+      "\"customstd\" is not supported.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_FALSE(g_TestResults.got_sub_request);
-  EXPECT_FALSE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_FALSE(test_results.got_sub_request);
+  EXPECT_FALSE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a fetch enabled custom standard scheme can generate same origin
 // Fetch requests.
 TEST(SchemeHandlerTest, FetchCustomStandardFetchSameOrigin) {
-  RegisterTestScheme("customstdfetch", "test");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstdfetch", "test");
 
   FetchTestSettings settings;
   settings.url = "customstdfetch://test/run.html";
   settings.sub_url = "customstdfetch://test/fetch.html";
-  SetUpFetch(settings);
+  SetUpFetch(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that custom nonstandard schemes are treated as unique origins that
 // cannot generate Fetch requests.
 TEST(SchemeHandlerTest, CustomNonStandardFetchSameOrigin) {
-  RegisterTestScheme("customnonstd", std::string());
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customnonstd", std::string());
 
   FetchTestSettings settings;
   settings.url = "customnonstd:some%20value";
   settings.sub_url = "customnonstd:xhr%20value";
-  SetUpFetch(settings);
+  SetUpFetch(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Fetch API cannot load customnonstd:xhr%20value. URL scheme "
+      "\"customnonstd\" is not supported.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_FALSE(g_TestResults.got_sub_request);
-  EXPECT_FALSE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_FALSE(test_results.got_sub_request);
+  EXPECT_FALSE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can generate same origin XSS requests.
 TEST(SchemeHandlerTest, CustomStandardXSSSameOrigin) {
-  RegisterTestScheme("customstd", "test");
-  SetUpXSS("customstd://test/run.html", "customstd://test/iframe.html");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test");
+  SetUpXSS(&test_results, "customstd://test/run.html",
+           "customstd://test/iframe.html");
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that custom nonstandard schemes are treated as unique origins that
 // cannot generate XSS requests.
 TEST(SchemeHandlerTest, CustomNonStandardXSSSameOrigin) {
-  RegisterTestScheme("customnonstd", std::string());
-  SetUpXSS("customnonstd:some%20value", "customnonstd:xhr%20value");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customnonstd", std::string());
+  SetUpXSS(&test_results, "customnonstd:some%20value",
+           "customnonstd:xhr%20value");
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Error: Failed to read a named property 'getResult' from 'Window': "
+      "Blocked a frame with origin \"null\" from accessing a "
+      "cross-origin frame.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme cannot generate cross-domain XHR requests
 // by default. Behavior should be the same as with HTTP.
 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginSync) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "test2");
 
   XHRTestSettings settings;
   settings.url = "customstd://test1/run.html";
   settings.sub_url = "customstd://test2/xhr.html";
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Access to XMLHttpRequest at 'customstd://test2/xhr.html' from origin "
+      "'customstd://test1' has been blocked by CORS policy: No "
+      "'Access-Control-Allow-Origin' header is present on the requested "
+      "resource.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme cannot generate cross-domain XHR requests
 // by default. Behavior should be the same as with HTTP.
 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginAsync) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "test2");
 
   XHRTestSettings settings;
   settings.url = "customstd://test1/run.html";
   settings.sub_url = "customstd://test2/xhr.html";
   settings.synchronous = false;
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Access to XMLHttpRequest at 'customstd://test2/xhr.html' from origin "
+      "'customstd://test1' has been blocked by CORS policy: No "
+      "'Access-Control-Allow-Origin' header is present on the requested "
+      "resource.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme cannot generate cross-domain Fetch
 // requests by default. Behavior should be the same as with HTTP.
 TEST(SchemeHandlerTest, CustomStandardFetchDifferentOrigin) {
-  RegisterTestScheme("customstdfetch", "test1");
-  RegisterTestScheme("customstdfetch", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstdfetch", "test1");
+  RegisterTestScheme(&test_results, "customstdfetch", "test2");
 
   FetchTestSettings settings;
   settings.url = "customstdfetch://test1/run.html";
   settings.sub_url = "customstdfetch://test2/fetch.html";
-  SetUpFetch(settings);
+  SetUpFetch(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Access to fetch at 'customstdfetch://test2/fetch.html' from origin "
+      "'customstdfetch://test1' has been blocked by CORS policy: No "
+      "'Access-Control-Allow-Origin' header is present on the requested "
+      "resource. If an opaque response serves your needs, set the request's "
+      "mode to 'no-cors' to fetch the resource with CORS disabled.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme cannot generate cross-domain XSS requests
 // by default.
 TEST(SchemeHandlerTest, CustomStandardXSSDifferentOrigin) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "test2");
-  SetUpXSS("customstd://test1/run.html", "customstd://test2/iframe.html");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "test2");
+  SetUpXSS(&test_results, "customstd://test1/run.html",
+           "customstd://test2/iframe.html");
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Error: Failed to read a named property 'getResult' from 'Window': "
+      "Blocked a frame with origin \"customstd://test2\" from accessing "
+      "a cross-origin frame.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a cross-protocol iframe load succeeds, and that the custom
 // standard scheme cannot generate XSS requests to the HTTP protocol by default.
 TEST(SchemeHandlerTest, CustomStandardXSSDifferentProtocolHttp) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("http", "test2");
-  SetUpXSS("customstd://test1/run.html", "http://test2/iframe.html");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "https", "test2");
+  SetUpXSS(&test_results, "customstd://test1/run.html",
+           "https://test2/iframe.html");
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Error: Failed to read a named property 'getResult' from 'Window': "
+      "Blocked a frame with origin \"https://test2\" from accessing a "
+      "cross-origin frame.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a cross-protocol iframe load succeeds, and that the custom
 // standard scheme cannot generate XSS requests to a non-standard scheme by
 // default.
 TEST(SchemeHandlerTest, CustomStandardXSSDifferentProtocolCustomNonStandard) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customnonstd", std::string());
-  SetUpXSS("customstd://test1/run.html", "customnonstd:some%20value");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customnonstd", std::string());
+  SetUpXSS(&test_results, "customstd://test1/run.html",
+           "customnonstd:some%20value");
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Error: Failed to read a named property 'getResult' from 'Window': "
+      "Blocked a frame with origin \"null\" from accessing a "
+      "cross-origin frame.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a cross-protocol iframe load succeeds, and that the HTTP protocol
 // cannot generate XSS requests to the custom standard scheme by default.
 TEST(SchemeHandlerTest, HttpXSSDifferentProtocolCustomStandard) {
-  RegisterTestScheme("http", "test1");
-  RegisterTestScheme("customstd", "test2");
-  SetUpXSS("http://test1/run.html", "customstd://test2/iframe.html");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "https", "test1");
+  RegisterTestScheme(&test_results, "customstd", "test2");
+  SetUpXSS(&test_results, "https://test1/run.html",
+           "customstd://test2/iframe.html");
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Error: Failed to read a named property 'getResult' from 'Window': "
+      "Blocked a frame with origin \"customstd://test2\" from accessing "
+      "a cross-origin frame.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a cross-protocol iframe load succeeds, and that the HTTP protocol
 // cannot generate XSS requests to the custom non-standard scheme by default.
 TEST(SchemeHandlerTest, HttpXSSDifferentProtocolCustomNonStandard) {
-  RegisterTestScheme("http", "test1");
-  RegisterTestScheme("customnonstd", std::string());
-  SetUpXSS("http://test1/run.html", "customnonstd:some%20value");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "https", "test1");
+  RegisterTestScheme(&test_results, "customnonstd", std::string());
+  SetUpXSS(&test_results, "https://test1/run.html",
+           "customnonstd:some%20value");
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Error: Failed to read a named property 'getResult' from 'Window': "
+      "Blocked a frame with origin \"null\" from accessing a "
+      "cross-origin frame.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that an HTTP scheme cannot generate cross-domain XHR requests by
 // default.
 TEST(SchemeHandlerTest, HttpXHRDifferentOriginSync) {
-  RegisterTestScheme("http", "test1");
-  RegisterTestScheme("http", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "https", "test1");
+  RegisterTestScheme(&test_results, "https", "test2");
 
   XHRTestSettings settings;
-  settings.url = "http://test1/run.html";
-  settings.sub_url = "http://test2/xhr.html";
-  SetUpXHR(settings);
+  settings.url = "https://test1/run.html";
+  settings.sub_url = "https://test2/xhr.html";
+  SetUpXHR(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Access to XMLHttpRequest at 'https://test2/xhr.html' from origin "
+      "'https://test1' has been blocked by CORS policy: No "
+      "'Access-Control-Allow-Origin' header is present on the requested "
+      "resource.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that an HTTP scheme cannot generate cross-domain XHR requests by
 // default.
 TEST(SchemeHandlerTest, HttpXHRDifferentOriginAsync) {
-  RegisterTestScheme("http", "test1");
-  RegisterTestScheme("http", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "https", "test1");
+  RegisterTestScheme(&test_results, "https", "test2");
 
   XHRTestSettings settings;
-  settings.url = "http://test1/run.html";
-  settings.sub_url = "http://test2/xhr.html";
+  settings.url = "https://test1/run.html";
+  settings.sub_url = "https://test2/xhr.html";
   settings.synchronous = false;
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Access to XMLHttpRequest at 'https://test2/xhr.html' from origin "
+      "'https://test1' has been blocked by CORS policy: No "
+      "'Access-Control-Allow-Origin' header is present on the requested "
+      "resource.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that an HTTP scheme cannot generate cross-domain Fetch requests by
 // default.
 TEST(SchemeHandlerTest, HttpFetchDifferentOriginAsync) {
-  RegisterTestScheme("http", "test1");
-  RegisterTestScheme("http", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "https", "test1");
+  RegisterTestScheme(&test_results, "https", "test2");
 
   FetchTestSettings settings;
-  settings.url = "http://test1/run.html";
-  settings.sub_url = "http://test2/fetch.html";
-  SetUpFetch(settings);
+  settings.url = "https://test1/run.html";
+  settings.sub_url = "https://test2/fetch.html";
+  SetUpFetch(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Access to fetch at 'https://test2/fetch.html' from origin "
+      "'https://test1' "
+      "has been blocked by CORS policy: No 'Access-Control-Allow-Origin' "
+      "header is present on the requested resource. If an opaque response "
+      "serves your needs, set the request's mode to 'no-cors' to fetch the "
+      "resource with CORS disabled.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that an HTTP scheme cannot generate cross-domain XSS requests by
 // default.
 TEST(SchemeHandlerTest, HttpXSSDifferentOrigin) {
-  RegisterTestScheme("http", "test1");
-  RegisterTestScheme("http", "test2");
-  SetUpXSS("http://test1/run.html", "http://test2/xss.html");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "https", "test1");
+  RegisterTestScheme(&test_results, "https", "test2");
+  SetUpXSS(&test_results, "https://test1/run.html", "https://test2/xss.html");
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Error: Failed to read a named property 'getResult' from 'Window': "
+      "Blocked a frame with origin \"https://test2\" from accessing a "
+      "cross-origin frame.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can generate cross-domain XHR requests
 // when setting the Access-Control-Allow-Origin header. Should behave the same
 // as HTTP.
 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithHeaderSync) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "test2");
 
   XHRTestSettings settings;
   settings.url = "customstd://test1/run.html";
   settings.sub_url = "customstd://test2/xhr.html";
   settings.sub_allow_origin = "customstd://test1";
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can generate cross-domain XHR requests
 // when setting the Access-Control-Allow-Origin header. Should behave the same
 // as HTTP.
 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithHeaderAsync) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "test2");
 
   XHRTestSettings settings;
   settings.url = "customstd://test1/run.html";
   settings.sub_url = "customstd://test2/xhr.html";
   settings.sub_allow_origin = "customstd://test1";
   settings.synchronous = false;
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can generate cross-domain Fetch requests
 // when setting the Access-Control-Allow-Origin header. Should behave the same
 // as HTTP.
 TEST(SchemeHandlerTest, CustomStandardFetchDifferentOriginWithHeader) {
-  RegisterTestScheme("customstdfetch", "test1");
-  RegisterTestScheme("customstdfetch", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstdfetch", "test1");
+  RegisterTestScheme(&test_results, "customstdfetch", "test2");
 
   FetchTestSettings settings;
   settings.url = "customstdfetch://test1/run.html";
   settings.sub_url = "customstdfetch://test2/fetch.html";
   settings.sub_allow_origin = "customstdfetch://test1";
-  SetUpFetch(settings);
+  SetUpFetch(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can generate cross-domain XHR requests
 // when using the cross-origin whitelist.
 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithWhitelistSync1) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "test2");
 
   XHRTestSettings settings;
   settings.url = "customstd://test1/run.html";
   settings.sub_url = "customstd://test2/xhr.html";
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
                                               "test2", false));
   WaitForUIThread();
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
   EXPECT_TRUE(CefClearCrossOriginWhitelist());
   WaitForUIThread();
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Same as above but origin whitelist matches any domain.
 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithWhitelistSync2) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "test2");
 
   XHRTestSettings settings;
   settings.url = "customstd://test1/run.html";
   settings.sub_url = "customstd://test2/xhr.html";
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
                                               CefString(), true));
   WaitForUIThread();
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
   EXPECT_TRUE(CefClearCrossOriginWhitelist());
   WaitForUIThread();
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Same as above but origin whitelist matches sub-domains.
 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithWhitelistSync3) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "a.test2.foo");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "a.test2.foo");
 
   XHRTestSettings settings;
   settings.url = "customstd://test1/run.html";
   settings.sub_url = "customstd://a.test2.foo/xhr.html";
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
                                               "test2.foo", true));
   WaitForUIThread();
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
   EXPECT_TRUE(CefClearCrossOriginWhitelist());
   WaitForUIThread();
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can generate cross-domain XHR requests
 // when using the cross-origin whitelist.
 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithWhitelistAsync1) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "test2");
 
   XHRTestSettings settings;
   settings.url = "customstd://test1/run.html";
   settings.sub_url = "customstd://test2/xhr.html";
   settings.synchronous = false;
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
                                               "test2", false));
   WaitForUIThread();
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
   EXPECT_TRUE(CefClearCrossOriginWhitelist());
   WaitForUIThread();
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Same as above but origin whitelist matches any domain.
 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithWhitelistAsync2) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "test2");
 
   XHRTestSettings settings;
   settings.url = "customstd://test1/run.html";
   settings.sub_url = "customstd://test2/xhr.html";
   settings.synchronous = false;
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
                                               CefString(), true));
   WaitForUIThread();
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
   EXPECT_TRUE(CefClearCrossOriginWhitelist());
   WaitForUIThread();
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Same as above but origin whitelist matches sub-domains.
 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginWithWhitelistAsync3) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "a.test2.foo");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "a.test2.foo");
 
   XHRTestSettings settings;
   settings.url = "customstd://test1/run.html";
   settings.sub_url = "customstd://a.test2.foo/xhr.html";
   settings.synchronous = false;
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
                                               "test2.foo", true));
   WaitForUIThread();
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
   EXPECT_TRUE(CefClearCrossOriginWhitelist());
   WaitForUIThread();
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can generate cross-domain Fetch requests
 // when using the cross-origin whitelist.
 TEST(SchemeHandlerTest, CustomStandardFetchDifferentOriginWithWhitelist1) {
-  RegisterTestScheme("customstdfetch", "test1");
-  RegisterTestScheme("customstdfetch", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstdfetch", "test1");
+  RegisterTestScheme(&test_results, "customstdfetch", "test2");
 
   FetchTestSettings settings;
   settings.url = "customstdfetch://test1/run.html";
   settings.sub_url = "customstdfetch://test2/fetch.html";
-  SetUpFetch(settings);
+  SetUpFetch(&test_results, settings);
 
   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry(
       "customstdfetch://test1", "customstdfetch", "test2", false));
   WaitForUIThread();
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
   EXPECT_TRUE(CefClearCrossOriginWhitelist());
   WaitForUIThread();
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Same as above but origin whitelist matches any domain.
 TEST(SchemeHandlerTest, CustomStandardFetchDifferentOriginWithWhitelist2) {
-  RegisterTestScheme("customstdfetch", "test1");
-  RegisterTestScheme("customstdfetch", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstdfetch", "test1");
+  RegisterTestScheme(&test_results, "customstdfetch", "test2");
 
   FetchTestSettings settings;
   settings.url = "customstdfetch://test1/run.html";
   settings.sub_url = "customstdfetch://test2/fetch.html";
-  SetUpFetch(settings);
+  SetUpFetch(&test_results, settings);
 
   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry(
       "customstdfetch://test1", "customstdfetch", CefString(), true));
   WaitForUIThread();
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
   EXPECT_TRUE(CefClearCrossOriginWhitelist());
   WaitForUIThread();
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Same as above but origin whitelist matches sub-domains.
 TEST(SchemeHandlerTest, CustomStandardFetchDifferentOriginWithWhitelist3) {
-  RegisterTestScheme("customstdfetch", "test1");
-  RegisterTestScheme("customstdfetch", "a.test2.foo");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstdfetch", "test1");
+  RegisterTestScheme(&test_results, "customstdfetch", "a.test2.foo");
 
   FetchTestSettings settings;
   settings.url = "customstdfetch://test1/run.html";
   settings.sub_url = "customstdfetch://a.test2.foo/fetch.html";
-  SetUpFetch(settings);
+  SetUpFetch(&test_results, settings);
 
   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry(
       "customstdfetch://test1", "customstdfetch", "test2.foo", true));
   WaitForUIThread();
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
   EXPECT_TRUE(CefClearCrossOriginWhitelist());
   WaitForUIThread();
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that an HTTP scheme can generate cross-domain XHR requests when setting
 // the Access-Control-Allow-Origin header.
 TEST(SchemeHandlerTest, HttpXHRDifferentOriginWithHeaderSync) {
-  RegisterTestScheme("http", "test1");
-  RegisterTestScheme("http", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "https", "test1");
+  RegisterTestScheme(&test_results, "https", "test2");
 
   XHRTestSettings settings;
-  settings.url = "http://test1/run.html";
-  settings.sub_url = "http://test2/xhr.html";
-  settings.sub_allow_origin = "http://test1";
-  SetUpXHR(settings);
+  settings.url = "https://test1/run.html";
+  settings.sub_url = "https://test2/xhr.html";
+  settings.sub_allow_origin = "https://test1";
+  SetUpXHR(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that an HTTP scheme can generate cross-domain XHR requests when setting
 // the Access-Control-Allow-Origin header.
 TEST(SchemeHandlerTest, HttpXHRDifferentOriginWithHeaderAsync) {
-  RegisterTestScheme("http", "test1");
-  RegisterTestScheme("http", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "https", "test1");
+  RegisterTestScheme(&test_results, "https", "test2");
 
   XHRTestSettings settings;
-  settings.url = "http://test1/run.html";
-  settings.sub_url = "http://test2/xhr.html";
-  settings.sub_allow_origin = "http://test1";
+  settings.url = "https://test1/run.html";
+  settings.sub_url = "https://test2/xhr.html";
+  settings.sub_allow_origin = "https://test1";
   settings.synchronous = false;
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that an HTTP scheme can generate cross-domain XHR requests when setting
 // the Access-Control-Allow-Origin header.
 TEST(SchemeHandlerTest, HttpFetchDifferentOriginWithHeader) {
-  RegisterTestScheme("http", "test1");
-  RegisterTestScheme("http", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "https", "test1");
+  RegisterTestScheme(&test_results, "https", "test2");
 
   FetchTestSettings settings;
-  settings.url = "http://test1/run.html";
-  settings.sub_url = "http://test2/fetch.html";
-  settings.sub_allow_origin = "http://test1";
-  SetUpFetch(settings);
+  settings.url = "https://test1/run.html";
+  settings.sub_url = "https://test2/fetch.html";
+  settings.sub_allow_origin = "https://test1";
+  SetUpFetch(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can generate cross-domain XSS requests
 // when using document.domain.
 TEST(SchemeHandlerTest, CustomStandardXSSDifferentOriginWithDomain) {
-  RegisterTestScheme("customstd", "a.test.com");
-  RegisterTestScheme("customstd", "b.test.com");
-  SetUpXSS("customstd://a.test.com/run.html",
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "a.test.com");
+  RegisterTestScheme(&test_results, "customstd", "b.test.com");
+  SetUpXSS(&test_results, "customstd://a.test.com/run.html",
            "customstd://b.test.com/iframe.html", "test.com");
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that an HTTP scheme can generate cross-domain XSS requests when using
 // document.domain.
 TEST(SchemeHandlerTest, HttpXSSDifferentOriginWithDomain) {
-  RegisterTestScheme("http", "a.test.com");
-  RegisterTestScheme("http", "b.test.com");
-  SetUpXSS("http://a.test.com/run.html", "http://b.test.com/iframe.html",
-           "test.com");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "https", "a.test.com");
+  RegisterTestScheme(&test_results, "https", "b.test.com");
+  SetUpXSS(&test_results, "https://a.test.com/run.html",
+           "https://b.test.com/iframe.html", "test.com");
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme cannot generate cross-domain XHR requests
 // that perform redirects.
 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginRedirectSync) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "test2");
 
   XHRTestSettings settings;
   settings.url = "customstd://test1/run.html";
   settings.sub_url = "customstd://test2/xhr.html";
   settings.sub_redirect_url = "customstd://test1/xhr.html";
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Access to XMLHttpRequest at 'customstd://test2/xhr.html' (redirected "
+      "from 'customstd://test1/xhr.html') from origin 'customstd://test1' has "
+      "been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is "
+      "present on the requested resource.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_redirect);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_redirect);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme cannot generate cross-domain XHR requests
 // that perform redirects.
 TEST(SchemeHandlerTest, CustomStandardXHRDifferentOriginRedirectAsync) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "test2");
 
   XHRTestSettings settings;
   settings.url = "customstd://test1/run.html";
   settings.sub_url = "customstd://test2/xhr.html";
   settings.sub_redirect_url = "customstd://test1/xhr.html";
   settings.synchronous = false;
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Access to XMLHttpRequest at 'customstd://test2/xhr.html' (redirected "
+      "from 'customstd://test1/xhr.html') from origin 'customstd://test1' has "
+      "been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is "
+      "present on the requested resource.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_redirect);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_redirect);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme cannot generate cross-domain Fetch
 // requests that perform redirects.
 TEST(SchemeHandlerTest, CustomStandardFetchDifferentOriginRedirect) {
-  RegisterTestScheme("customstdfetch", "test1");
-  RegisterTestScheme("customstdfetch", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstdfetch", "test1");
+  RegisterTestScheme(&test_results, "customstdfetch", "test2");
 
   FetchTestSettings settings;
   settings.url = "customstdfetch://test1/run.html";
   settings.sub_url = "customstdfetch://test2/fetch.html";
   settings.sub_redirect_url = "customstdfetch://test1/fetch.html";
-  SetUpFetch(settings);
+  SetUpFetch(&test_results, settings);
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  test_results.console_messages.push_back(
+      "Access to fetch at 'customstdfetch://test2/fetch.html' (redirected from "
+      "'customstdfetch://test1/fetch.html') from origin "
+      "'customstdfetch://test1' has been blocked by CORS policy: No "
+      "'Access-Control-Allow-Origin' header is present on the requested "
+      "resource. If an opaque response serves your needs, set the request's "
+      "mode to 'no-cors' to fetch the resource with CORS disabled.");
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_redirect);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_FALSE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_redirect);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_FALSE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can generate cross-domain XHR requests
 // that perform redirects when using the cross-origin whitelist.
 TEST(SchemeHandlerTest,
      CustomStandardXHRDifferentOriginRedirectWithWhitelistSync) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "test2");
 
   XHRTestSettings settings;
   settings.url = "customstd://test1/run.html";
   settings.sub_url = "customstd://test2/xhr.html";
   settings.sub_redirect_url = "customstd://test1/xhr.html";
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
                                               "test2", false));
   WaitForUIThread();
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_redirect);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_redirect);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
   EXPECT_TRUE(CefClearCrossOriginWhitelist());
   WaitForUIThread();
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can generate cross-domain XHR requests
 // that perform redirects when using the cross-origin whitelist.
 TEST(SchemeHandlerTest,
      CustomStandardXHRDifferentOriginRedirectWithWhitelistAsync1) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "test2");
 
   XHRTestSettings settings;
   settings.url = "customstd://test1/run.html";
   settings.sub_url = "customstd://test2/xhr.html";
   settings.sub_redirect_url = "customstd://test1/xhr.html";
   settings.synchronous = false;
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
                                               "test2", false));
   WaitForUIThread();
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_redirect);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_redirect);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
   EXPECT_TRUE(CefClearCrossOriginWhitelist());
   WaitForUIThread();
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Same as above but origin whitelist matches any domain.
 TEST(SchemeHandlerTest,
      CustomStandardXHRDifferentOriginRedirectWithWhitelistAsync2) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "test2");
 
   XHRTestSettings settings;
   settings.url = "customstd://test1/run.html";
   settings.sub_url = "customstd://test2/xhr.html";
   settings.sub_redirect_url = "customstd://test1/xhr.html";
   settings.synchronous = false;
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
                                               CefString(), true));
   WaitForUIThread();
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_redirect);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_redirect);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
   EXPECT_TRUE(CefClearCrossOriginWhitelist());
   WaitForUIThread();
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Same as above but origin whitelist matches sub-domains.
 TEST(SchemeHandlerTest,
      CustomStandardXHRDifferentOriginRedirectWithWhitelistAsync3) {
-  RegisterTestScheme("customstd", "test1");
-  RegisterTestScheme("customstd", "a.test2.foo");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstd", "test1");
+  RegisterTestScheme(&test_results, "customstd", "a.test2.foo");
 
   XHRTestSettings settings;
   settings.url = "customstd://test1/run.html";
   settings.sub_url = "customstd://a.test2.foo/xhr.html";
   settings.sub_redirect_url = "customstd://test1/xhr.html";
   settings.synchronous = false;
-  SetUpXHR(settings);
+  SetUpXHR(&test_results, settings);
 
   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry("customstd://test1", "customstd",
                                               "test2.foo", true));
   WaitForUIThread();
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_redirect);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_redirect);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
   EXPECT_TRUE(CefClearCrossOriginWhitelist());
   WaitForUIThread();
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Test that a custom standard scheme can generate cross-domain Fetch requests
 // that perform redirects when using the cross-origin whitelist.
 TEST(SchemeHandlerTest,
      CustomStandardFetchDifferentOriginRedirectWithWhitelist1) {
-  RegisterTestScheme("customstdfetch", "test1");
-  RegisterTestScheme("customstdfetch", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstdfetch", "test1");
+  RegisterTestScheme(&test_results, "customstdfetch", "test2");
 
   FetchTestSettings settings;
   settings.url = "customstdfetch://test1/run.html";
   settings.sub_url = "customstdfetch://test2/fetch.html";
   settings.sub_redirect_url = "customstdfetch://test1/fetch.html";
-  SetUpFetch(settings);
+  SetUpFetch(&test_results, settings);
 
   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry(
       "customstdfetch://test1", "customstdfetch", "test2", false));
   WaitForUIThread();
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_redirect);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_redirect);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
   EXPECT_TRUE(CefClearCrossOriginWhitelist());
   WaitForUIThread();
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Same as above but origin whitelist matches any domain.
 TEST(SchemeHandlerTest,
      CustomStandardFetchDifferentOriginRedirectWithWhitelist2) {
-  RegisterTestScheme("customstdfetch", "test1");
-  RegisterTestScheme("customstdfetch", "test2");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstdfetch", "test1");
+  RegisterTestScheme(&test_results, "customstdfetch", "test2");
 
   FetchTestSettings settings;
   settings.url = "customstdfetch://test1/run.html";
   settings.sub_url = "customstdfetch://test2/fetch.html";
   settings.sub_redirect_url = "customstdfetch://test1/fetch.html";
-  SetUpFetch(settings);
+  SetUpFetch(&test_results, settings);
 
   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry(
       "customstdfetch://test1", "customstdfetch", CefString(), true));
   WaitForUIThread();
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_redirect);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_redirect);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
   EXPECT_TRUE(CefClearCrossOriginWhitelist());
   WaitForUIThread();
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Same as above but origin whitelist matches sub-domains.
 TEST(SchemeHandlerTest,
      CustomStandardFetchDifferentOriginRedirectWithWhitelist3) {
-  RegisterTestScheme("customstdfetch", "test1");
-  RegisterTestScheme("customstdfetch", "a.test2.foo");
+  TestResults test_results;
+  RegisterTestScheme(&test_results, "customstdfetch", "test1");
+  RegisterTestScheme(&test_results, "customstdfetch", "a.test2.foo");
 
   FetchTestSettings settings;
   settings.url = "customstdfetch://test1/run.html";
   settings.sub_url = "customstdfetch://a.test2.foo/fetch.html";
   settings.sub_redirect_url = "customstdfetch://test1/fetch.html";
-  SetUpFetch(settings);
+  SetUpFetch(&test_results, settings);
 
   EXPECT_TRUE(CefAddCrossOriginWhitelistEntry(
       "customstdfetch://test1", "customstdfetch", "test2.foo", true));
   WaitForUIThread();
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
-  EXPECT_TRUE(g_TestResults.got_sub_redirect);
-  EXPECT_TRUE(g_TestResults.got_sub_request);
-  EXPECT_TRUE(g_TestResults.got_sub_read);
-  EXPECT_TRUE(g_TestResults.got_sub_success);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.got_sub_redirect);
+  EXPECT_TRUE(test_results.got_sub_request);
+  EXPECT_TRUE(test_results.got_sub_read);
+  EXPECT_TRUE(test_results.git_exit_success);
 
   EXPECT_TRUE(CefClearCrossOriginWhitelist());
   WaitForUIThread();
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
-// Test per-browser setting of Accept-Language.
+// Test that CefRequestContextSettings.accept_language_list configures both
+// the Accept-Language request header and `navigator.language` JS attribute.
 TEST(SchemeHandlerTest, AcceptLanguage) {
-  RegisterTestScheme("customstd", "test");
-  g_TestResults.url = "customstd://test/run.html";
-  g_TestResults.html =
-      "<html><head></head><body><h1>Success!</h1></body></html>";
+  TestResults test_results;
 
-  // Value that will be set via CefBrowserSettings.accept_language in
-  // PopulateBrowserSettings().
-  g_TestResults.accept_language = "uk";
+  // Value that will be set via CefRequestContextSettings.accept_language_list.
+  test_results.accept_language = "uk";
 
-  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&g_TestResults);
+  // Create an in-memory request context with custom settings.
+  CefRequestContextSettings settings;
+  CefString(&settings.accept_language_list) = test_results.accept_language;
+  test_results.request_context =
+      CefRequestContext::CreateContext(settings, nullptr);
+
+  RegisterTestScheme(&test_results, "customstd", "test");
+  test_results.url = "customstd://test/run.html";
+  test_results.html =
+      "<html><head></head><body>"
+      "<script>"
+      "if (navigator.language == 'uk') {"
+      "  result = 'SUCCESS';"
+      "} else {"
+      "  result = 'FAILURE';"
+      "  console.log('navigator.language: '+navigator.language+' != uk');"
+      "}"
+      "document.location = 'https://tests/exit?result='+result;"
+      "</script>"
+      "</body></html>";
+  test_results.exit_url = "https://tests/exit";
+
+  CefRefPtr<TestSchemeHandler> handler = new TestSchemeHandler(&test_results);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 
-  EXPECT_TRUE(g_TestResults.got_request);
-  EXPECT_TRUE(g_TestResults.got_read);
-  EXPECT_TRUE(g_TestResults.got_output);
+  EXPECT_TRUE(test_results.got_request);
+  EXPECT_TRUE(test_results.got_read);
+  EXPECT_TRUE(test_results.got_output);
+  EXPECT_TRUE(test_results.git_exit_success);
 
-  ClearTestSchemes();
+  ClearTestSchemes(&test_results);
 }
 
 // Entry point for registering custom schemes.
 // Called from client_app_delegates.cc.
 void RegisterSchemeHandlerCustomSchemes(
-    CefRawPtr<CefSchemeRegistrar> registrar,
-    std::vector<CefString>& cookiable_schemes) {
+    CefRawPtr<CefSchemeRegistrar> registrar) {
+  // Registering the custom standard schemes as secure because requests from
+  // non-secure origins to the loopback address will be blocked by
+  // https://chromestatus.com/feature/5436853517811712.
+
   // Add a custom standard scheme.
+  registrar->AddCustomScheme("customstd", CEF_SCHEME_OPTION_STANDARD |
+                                              CEF_SCHEME_OPTION_SECURE |
+                                              CEF_SCHEME_OPTION_CORS_ENABLED);
+  // Also used in cors_unittest.cc.
   registrar->AddCustomScheme(
-      "customstd", CEF_SCHEME_OPTION_STANDARD | CEF_SCHEME_OPTION_CORS_ENABLED);
-  registrar->AddCustomScheme("customstdfetch",
-                             CEF_SCHEME_OPTION_STANDARD |
-                                 CEF_SCHEME_OPTION_CORS_ENABLED |
-                                 CEF_SCHEME_OPTION_FETCH_ENABLED);
+      "customstdfetch", CEF_SCHEME_OPTION_STANDARD | CEF_SCHEME_OPTION_SECURE |
+                            CEF_SCHEME_OPTION_CORS_ENABLED |
+                            CEF_SCHEME_OPTION_FETCH_ENABLED);
   // Add a custom non-standard scheme.
   registrar->AddCustomScheme("customnonstd", CEF_SCHEME_OPTION_NONE);
   registrar->AddCustomScheme("customnonstdfetch",
                              CEF_SCHEME_OPTION_FETCH_ENABLED);
 }
+
+// Entry point for registering cookieable schemes.
+// Called from client_app_delegates.cc.
+void RegisterSchemeHandlerCookieableSchemes(
+    std::vector<std::string>& cookieable_schemes) {
+  cookieable_schemes.push_back("customstd");
+  // Also used in cors_unittest.cc.
+  cookieable_schemes.push_back("customstdfetch");
+}
diff --git a/src/tests/ceftests/send_shared_process_message_unittest.cc b/src/tests/ceftests/send_shared_process_message_unittest.cc
new file mode 100644
index 0000000..76c2a93
--- /dev/null
+++ b/src/tests/ceftests/send_shared_process_message_unittest.cc
@@ -0,0 +1,173 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "include/base/cef_callback.h"
+#include "include/cef_shared_process_message_builder.h"
+#include "include/cef_task.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "tests/ceftests/test_handler.h"
+#include "tests/gtest/include/gtest/gtest.h"
+#include "tests/shared/renderer/client_app_renderer.h"
+
+#include <array>
+
+using client::ClientAppRenderer;
+
+namespace {
+
+struct TestData {
+  bool flag = true;
+  int value = 1;
+  double d_value = 77.77;
+  std::array<size_t, 50> buffer{};
+};
+
+const char kSharedMessageUrl[] = "https://tests/SendSharedProcessMessageTest";
+const char kSharedMessageName[] = "SendSharedProcessMessageTest";
+
+CefRefPtr<CefProcessMessage> CreateTestMessage(const TestData& data) {
+  auto builder =
+      CefSharedProcessMessageBuilder::Create(kSharedMessageName, sizeof(data));
+  std::memcpy(builder->Memory(), reinterpret_cast<const void*>(&data),
+              sizeof(data));
+  return builder->Build();
+}
+
+// Renderer side.
+class SharedMessageRendererTest final : public ClientAppRenderer::Delegate {
+ public:
+  bool OnProcessMessageReceived(CefRefPtr<ClientAppRenderer> app,
+                                CefRefPtr<CefBrowser> browser,
+                                CefRefPtr<CefFrame> frame,
+                                CefProcessId source_process,
+                                CefRefPtr<CefProcessMessage> message) override {
+    if (message->GetName() == kSharedMessageName) {
+      EXPECT_TRUE(browser.get());
+      EXPECT_TRUE(frame.get());
+      EXPECT_EQ(PID_BROWSER, source_process);
+      EXPECT_TRUE(message.get());
+      EXPECT_TRUE(message->IsValid());
+      EXPECT_TRUE(message->IsReadOnly());
+      EXPECT_EQ(message->GetArgumentList(), nullptr);
+
+      const std::string& url = frame->GetURL();
+      if (url == kSharedMessageUrl) {
+        // Echo the message back to the sender natively.
+        frame->SendProcessMessage(PID_BROWSER, message);
+        EXPECT_FALSE(message->IsValid());
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  IMPLEMENT_REFCOUNTING(SharedMessageRendererTest);
+};
+
+// Browser side.
+class SharedMessageTestHandler final : public TestHandler {
+ public:
+  explicit SharedMessageTestHandler(cef_thread_id_t send_thread)
+      : send_thread_(send_thread) {}
+
+  void RunTest() override {
+    AddResource(kSharedMessageUrl, "<html><body>TEST</body></html>",
+                "text/html");
+    CreateBrowser(kSharedMessageUrl);
+
+    // Time out the test after a reasonable period of time.
+    SetTestTimeout();
+  }
+
+  void OnLoadEnd(CefRefPtr<CefBrowser> browser,
+                 CefRefPtr<CefFrame> frame,
+                 int httpStatusCode) override {
+    EXPECT_TRUE(CefCurrentlyOn(TID_UI));
+
+    // Send the message to the renderer process.
+    if (!CefCurrentlyOn(send_thread_)) {
+      CefPostTask(send_thread_,
+                  base::BindOnce(&SharedMessageTestHandler::SendProcessMessage,
+                                 this, browser, frame));
+    } else {
+      SendProcessMessage(browser, frame);
+    }
+  }
+
+  bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
+                                CefRefPtr<CefFrame> frame,
+                                CefProcessId source_process,
+                                CefRefPtr<CefProcessMessage> message) override {
+    EXPECT_TRUE(CefCurrentlyOn(TID_UI));
+    EXPECT_TRUE(browser.get());
+    EXPECT_TRUE(frame.get());
+    EXPECT_EQ(PID_RENDERER, source_process);
+    EXPECT_TRUE(message.get());
+    EXPECT_TRUE(message->IsValid());
+    EXPECT_TRUE(message->IsReadOnly());
+    EXPECT_EQ(message->GetArgumentList(), nullptr);
+
+    // Verify that the recieved message is the same as the sent message.
+    auto region = message->GetSharedMemoryRegion();
+    const TestData* received = static_cast<const TestData*>(region->Memory());
+    EXPECT_EQ(data_.flag, received->flag);
+    EXPECT_EQ(data_.value, received->value);
+    EXPECT_EQ(data_.d_value, received->d_value);
+
+    got_message_.yes();
+
+    // Test is complete.
+    DestroyTest();
+
+    return true;
+  }
+
+ protected:
+  void DestroyTest() override {
+    EXPECT_TRUE(got_message_);
+    TestHandler::DestroyTest();
+  }
+
+ private:
+  void SendProcessMessage(const CefRefPtr<CefBrowser>& browser,
+                          const CefRefPtr<CefFrame>& frame) {
+    EXPECT_TRUE(CefCurrentlyOn(send_thread_));
+
+    auto message = CreateTestMessage(data_);
+    frame->SendProcessMessage(PID_RENDERER, message);
+
+    // The message is invalidated immediately
+    EXPECT_FALSE(message->IsValid());
+  }
+
+  cef_thread_id_t send_thread_;
+  TrackCallback got_message_;
+  const TestData data_;
+
+  IMPLEMENT_REFCOUNTING(SharedMessageTestHandler);
+};
+
+}  // namespace
+
+TEST(SendSharedProcessMessageTest, CanSendAndReceiveFromUiThread) {
+  CefRefPtr<SharedMessageTestHandler> handler =
+      new SharedMessageTestHandler(TID_UI);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+TEST(SendSharedProcessMessageTest, CanSendAndReceiveFromIoThread) {
+  CefRefPtr<SharedMessageTestHandler> handler =
+      new SharedMessageTestHandler(TID_IO);
+  handler->ExecuteTest();
+  ReleaseAndWaitForDestructor(handler);
+}
+
+// Entry point for creating shared process message renderer test objects.
+// Called from client_app_delegates.cc.
+void CreateSharedProcessMessageTests(
+    ClientAppRenderer::DelegateSet& delegates) {
+  delegates.insert(new SharedMessageRendererTest());
+}
diff --git a/src/tests/ceftests/server_unittest.cc b/src/tests/ceftests/server_unittest.cc
index b3f8c2a..96642e0 100644
--- a/src/tests/ceftests/server_unittest.cc
+++ b/src/tests/ceftests/server_unittest.cc
@@ -4,11 +4,11 @@
 
 #include <list>
 #include <map>
+#include <memory>
 #include <set>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/base/cef_ref_counted.h"
-#include "include/base/cef_scoped_ptr.h"
 #include "include/cef_command_line.h"
 #include "include/cef_server.h"
 #include "include/cef_task.h"
@@ -20,14 +20,15 @@
 
 namespace {
 
+// Must use a different port than test_server.cc.
 const char kTestServerAddress[] = "127.0.0.1";
-const uint16 kTestServerPort = 8099;
+const uint16_t kTestServerPort = 8099;
 const int kTestTimeout = 5000;
 
 std::string GetTestServerOrigin(bool is_websocket) {
   std::stringstream ss;
   ss << (is_websocket ? "ws://" : "http://") << kTestServerAddress << ":"
-     << kTestServerPort << "/";
+     << kTestServerPort;
   return ss.str();
 }
 
@@ -71,11 +72,11 @@
   // started.
   // |destroy_callback| will be executed on the UI thread after this handler
   // object is destroyed.
-  TestServerHandler(const base::Closure& start_callback,
-                    const base::Closure& destroy_callback)
+  TestServerHandler(base::OnceClosure start_callback,
+                    base::OnceClosure destroy_callback)
       : initialized_(false),
-        start_callback_(start_callback),
-        destroy_callback_(destroy_callback),
+        start_callback_(std::move(start_callback)),
+        destroy_callback_(std::move(destroy_callback)),
         expected_connection_ct_(0),
         actual_connection_ct_(0),
         expected_http_request_ct_(0),
@@ -95,18 +96,20 @@
     if (!http_request_handler_list_.empty()) {
       HttpRequestHandlerList::const_iterator it =
           http_request_handler_list_.begin();
-      for (; it != http_request_handler_list_.end(); ++it)
+      for (; it != http_request_handler_list_.end(); ++it) {
         delete *it;
+      }
     }
 
     if (!ws_request_handler_list_.empty()) {
       WsRequestHandlerList::const_iterator it =
           ws_request_handler_list_.begin();
-      for (; it != ws_request_handler_list_.end(); ++it)
+      for (; it != ws_request_handler_list_.end(); ++it) {
         delete *it;
+      }
     }
 
-    destroy_callback_.Run();
+    std::move(destroy_callback_).Run();
   }
 
   // Must be called before CreateServer().
@@ -116,7 +119,8 @@
   }
 
   // Must be called before CreateServer().
-  void AddHttpRequestHandler(scoped_ptr<HttpRequestHandler> request_handler) {
+  void AddHttpRequestHandler(
+      std::unique_ptr<HttpRequestHandler> request_handler) {
     EXPECT_FALSE(initialized_);
     EXPECT_TRUE(request_handler);
     http_request_handler_list_.push_back(request_handler.release());
@@ -129,7 +133,7 @@
   }
 
   // Must be called before CreateServer().
-  void AddWsRequestHandler(scoped_ptr<WsRequestHandler> request_handler) {
+  void AddWsRequestHandler(std::unique_ptr<WsRequestHandler> request_handler) {
     EXPECT_FALSE(initialized_);
     EXPECT_TRUE(request_handler);
     ws_request_handler_list_.push_back(request_handler.release());
@@ -163,8 +167,9 @@
   // |destroy_callback|.
   void ShutdownServer() {
     EXPECT_TRUE(server_);
-    if (server_)
+    if (server_) {
       server_->Shutdown();
+    }
   }
 
   void OnServerCreated(CefRefPtr<CefServer> server) override {
@@ -222,8 +227,9 @@
     connection_id_set_.erase(it);
 
     ConnectionIdSet::iterator it2 = ws_connection_id_set_.find(connection_id);
-    if (it2 != ws_connection_id_set_.end())
+    if (it2 != ws_connection_id_set_.end()) {
       ws_connection_id_set_.erase(it2);
+    }
 
     if (connection_id_set_.empty()) {
       EXPECT_TRUE(ws_connection_id_set_.empty());
@@ -246,8 +252,9 @@
     for (; it != http_request_handler_list_.end(); ++it) {
       handled =
           (*it)->HandleRequest(server, connection_id, client_address, request);
-      if (handled)
+      if (handled) {
         break;
+      }
     }
     EXPECT_TRUE(handled) << "missing HttpRequestHandler for "
                          << request->GetURL().ToString();
@@ -274,8 +281,9 @@
     for (; it != ws_request_handler_list_.end(); ++it) {
       handled = (*it)->HandleRequest(server, connection_id, client_address,
                                      request, callback);
-      if (handled)
+      if (handled) {
         break;
+      }
     }
     EXPECT_TRUE(handled) << "missing WsRequestHandler for "
                          << request->GetURL().ToString();
@@ -295,8 +303,9 @@
     WsRequestHandlerList::const_iterator it = ws_request_handler_list_.begin();
     for (; it != ws_request_handler_list_.end(); ++it) {
       handled = (*it)->HandleConnected(server, connection_id);
-      if (handled)
+      if (handled) {
         break;
+      }
     }
     EXPECT_TRUE(handled) << "missing WsRequestHandler for " << connection_id;
 
@@ -319,8 +328,9 @@
     WsRequestHandlerList::const_iterator it = ws_request_handler_list_.begin();
     for (; it != ws_request_handler_list_.end(); ++it) {
       handled = (*it)->HandleMessage(server, connection_id, data, data_size);
-      if (handled)
+      if (handled) {
         break;
+      }
     }
     EXPECT_TRUE(handled) << "missing WsRequestHandler for " << connection_id;
 
@@ -409,13 +419,12 @@
   void RunStartCallback() {
     if (!CefCurrentlyOn(TID_UI)) {
       CefPostTask(TID_UI,
-                  base::Bind(&TestServerHandler::RunStartCallback, this));
+                  base::BindOnce(&TestServerHandler::RunStartCallback, this));
       return;
     }
 
     EXPECT_FALSE(start_callback_.is_null());
-    start_callback_.Run();
-    start_callback_.Reset();
+    std::move(start_callback_).Run();
   }
 
   CefRefPtr<CefServer> server_;
@@ -423,8 +432,8 @@
   bool initialized_;
 
   // After initialization only accessed on the UI thread.
-  base::Closure start_callback_;
-  base::Closure destroy_callback_;
+  base::OnceClosure start_callback_;
+  base::OnceClosure destroy_callback_;
 
   // After initialization the below members are only accessed on the server
   // thread.
@@ -478,11 +487,11 @@
     virtual ~RequestRunner() {}
 
     // Create the server-side handler for the request.
-    virtual scoped_ptr<TestServerHandler::HttpRequestHandler>
+    virtual std::unique_ptr<TestServerHandler::HttpRequestHandler>
     CreateHttpRequestHandler() = 0;
 
     // Run the request and execute |complete_callback| on completion.
-    virtual void RunRequest(const base::Closure& complete_callback) = 0;
+    virtual void RunRequest(base::OnceClosure complete_callback) = 0;
 
     virtual bool VerifyResults() = 0;
     virtual std::string ToString() = 0;
@@ -493,18 +502,15 @@
   HttpTestRunner(bool parallel_requests)
       : parallel_requests_(parallel_requests),
         initialized_(false),
-        next_request_id_(0) {
-    handler_ = new TestServerHandler(
-        base::Bind(&HttpTestRunner::OnServerStarted, this),
-        base::Bind(&HttpTestRunner::OnServerDestroyed, this));
-  }
+        next_request_id_(0) {}
 
   virtual ~HttpTestRunner() {
-    if (destroy_event_)
+    if (destroy_event_) {
       destroy_event_->Signal();
+    }
   }
 
-  void AddRequestRunner(scoped_ptr<RequestRunner> request_runner) {
+  void AddRequestRunner(std::unique_ptr<RequestRunner> request_runner) {
     EXPECT_FALSE(initialized_);
     request_runner_map_.insert(
         std::make_pair(++next_request_id_, request_runner.release()));
@@ -514,9 +520,13 @@
   void ExecuteTest() {
     EXPECT_FALSE(CefCurrentlyOn(TID_UI));
 
+    handler_ = new TestServerHandler(
+        base::BindOnce(&HttpTestRunner::OnServerStarted, this),
+        base::BindOnce(&HttpTestRunner::OnServerDestroyed, this));
+
     run_event_ = CefWaitableEvent::CreateWaitableEvent(false, false);
 
-    CefPostTask(TID_UI, base::Bind(&HttpTestRunner::RunTest, this));
+    CefPostTask(TID_UI, base::BindOnce(&HttpTestRunner::RunTest, this));
 
     // Block until test completion.
     run_event_->Wait();
@@ -565,7 +575,7 @@
     got_server_destroyed_.yes();
 
     // Allow the call stack to unwind.
-    CefPostTask(TID_UI, base::Bind(&HttpTestRunner::DestroyTest, this));
+    CefPostTask(TID_UI, base::BindOnce(&HttpTestRunner::DestroyTest, this));
   }
 
   // Run all requests in parallel.
@@ -573,7 +583,7 @@
     RequestRunnerMap::const_iterator it = request_runner_map_.begin();
     for (; it != request_runner_map_.end(); ++it) {
       it->second->RunRequest(
-          base::Bind(&HttpTestRunner::OnRequestComplete, this, it->first));
+          base::BindOnce(&HttpTestRunner::OnRequestComplete, this, it->first));
     }
   }
 
@@ -581,14 +591,15 @@
   void RunNextRequest() {
     RequestRunnerMap::const_iterator it = request_runner_map_.begin();
     it->second->RunRequest(
-        base::Bind(&HttpTestRunner::OnRequestComplete, this, it->first));
+        base::BindOnce(&HttpTestRunner::OnRequestComplete, this, it->first));
   }
 
   void OnRequestComplete(int request_id) {
     EXPECT_UI_THREAD()
     // Allow the call stack to unwind.
-    CefPostTask(TID_UI, base::Bind(&HttpTestRunner::OnRequestCompleteContinue,
-                                   this, request_id));
+    CefPostTask(TID_UI,
+                base::BindOnce(&HttpTestRunner::OnRequestCompleteContinue, this,
+                               request_id));
   }
 
   void OnRequestCompleteContinue(int request_id) {
@@ -622,8 +633,9 @@
     EXPECT_TRUE(request_runner_map_.empty());
 
     // Cancel the timeout, if any.
-    if (ui_thread_helper_)
+    if (ui_thread_helper_) {
       ui_thread_helper_.reset();
+    }
 
     // Signal test completion.
     run_event_->Signal();
@@ -631,24 +643,25 @@
 
   TestHandler::UIThreadHelper* GetUIThreadHelper() {
     EXPECT_UI_THREAD();
-    if (!ui_thread_helper_)
+    if (!ui_thread_helper_) {
       ui_thread_helper_.reset(new TestHandler::UIThreadHelper());
+    }
     return ui_thread_helper_.get();
   }
 
   void SetTestTimeout(int timeout_ms) {
     EXPECT_UI_THREAD();
-    if (CefCommandLine::GetGlobalCommandLine()->HasSwitch(
-            "disable-test-timeout")) {
+    const auto timeout = GetConfiguredTestTimeout(timeout_ms);
+    if (!timeout) {
       return;
     }
 
     // Use a weak reference to |this| via UIThreadHelper so that the
     // test runner can be destroyed before the timeout expires.
     GetUIThreadHelper()->PostDelayedTask(
-        base::Bind(&HttpTestRunner::OnTestTimeout, base::Unretained(this),
-                   timeout_ms),
-        timeout_ms);
+        base::BindOnce(&HttpTestRunner::OnTestTimeout, base::Unretained(this),
+                       *timeout),
+        *timeout);
   }
 
   void OnTestTimeout(int timeout_ms) {
@@ -674,7 +687,7 @@
   TrackCallback got_all_requests_;
   TrackCallback got_server_destroyed_;
 
-  scoped_ptr<TestHandler::UIThreadHelper> ui_thread_helper_;
+  std::unique_ptr<TestHandler::UIThreadHelper> ui_thread_helper_;
 
   DISALLOW_COPY_AND_ASSIGN(HttpTestRunner);
 };
@@ -727,7 +740,7 @@
           connection_id, response.response_code, response.content_type,
           response.no_content_length
               ? -1
-              : static_cast<int64>(response.content.size()),
+              : static_cast<int64_t>(response.content.size()),
           response.extra_headers);
       if (!response.content.empty()) {
         server->SendRawData(connection_id, response.content.data(),
@@ -747,8 +760,9 @@
 std::string GetHeaderValue(const CefServer::HeaderMap& header_map,
                            const std::string& header_name) {
   CefServer::HeaderMap::const_iterator it = header_map.find(header_name);
-  if (it != header_map.end())
+  if (it != header_map.end()) {
     return it->second;
+  }
   return std::string();
 }
 
@@ -793,7 +807,7 @@
     const std::string& content_type = std::string(),
     const CefRequest::HeaderMap& extra_headers = CefRequest::HeaderMap()) {
   CefRefPtr<CefRequest> request = CefRequest::Create();
-  request->SetURL(GetTestServerOrigin(false) + path);
+  request->SetURL(GetTestServerOrigin(false) + "/" + path);
   request->SetMethod(method);
 
   CefRequest::HeaderMap header_map;
@@ -809,8 +823,9 @@
     header_map.insert(std::make_pair("content-type", content_type));
   }
 
-  if (!extra_headers.empty())
+  if (!extra_headers.empty()) {
     header_map.insert(extra_headers.begin(), extra_headers.end());
+  }
   request->SetHeaderMap(header_map);
 
   return request;
@@ -864,16 +879,16 @@
 // response.
 class StaticHttpURLRequestClient : public CefURLRequestClient {
  public:
-  typedef base::Callback<void(cef_errorcode_t /* error */,
+  using ResponseCallback =
+      base::OnceCallback<void(cef_errorcode_t /* error */,
                               CefRefPtr<CefResponse> /* response */,
-                              const std::string& /* data */)>
-      ResponseCallback;
+                              const std::string& /* data */)>;
 
   // |response_callback| will be executed on the UI thread when the response
   // is complete.
   StaticHttpURLRequestClient(CefRefPtr<CefRequest> request,
-                             const ResponseCallback& response_callback)
-      : request_(request), response_callback_(response_callback) {
+                             ResponseCallback response_callback)
+      : request_(request), response_callback_(std::move(response_callback)) {
     EXPECT_TRUE(request_);
     EXPECT_FALSE(response_callback_.is_null());
   }
@@ -885,18 +900,17 @@
 
   void OnRequestComplete(CefRefPtr<CefURLRequest> request) override {
     EXPECT_FALSE(response_callback_.is_null());
-    response_callback_.Run(request->GetRequestError(), request->GetResponse(),
-                           data_);
-    response_callback_.Reset();
+    std::move(response_callback_)
+        .Run(request->GetRequestError(), request->GetResponse(), data_);
   }
 
   void OnUploadProgress(CefRefPtr<CefURLRequest> request,
-                        int64 current,
-                        int64 total) override {}
+                        int64_t current,
+                        int64_t total) override {}
 
   void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
-                          int64 current,
-                          int64 total) override {}
+                          int64_t current,
+                          int64_t total) override {}
 
   void OnDownloadData(CefRefPtr<CefURLRequest> request,
                       const void* data,
@@ -929,38 +943,36 @@
                           const HttpServerResponse& response)
       : request_(request), response_(response) {}
 
-  static scoped_ptr<HttpTestRunner::RequestRunner> Create200(
+  static std::unique_ptr<HttpTestRunner::RequestRunner> Create200(
       const std::string& path,
       bool with_content = true) {
     CefRefPtr<CefRequest> request = CreateTestServerRequest(path, "GET");
     HttpServerResponse response(HttpServerResponse::TYPE_200);
     response.content_type = "text/html";
-    if (with_content)
+    if (with_content) {
       response.content = "<html>200 response content</html>";
-    return make_scoped_ptr<HttpTestRunner::RequestRunner>(
-        new StaticHttpRequestRunner(request, response));
+    }
+    return std::make_unique<StaticHttpRequestRunner>(request, response);
   }
 
-  static scoped_ptr<HttpTestRunner::RequestRunner> Create404(
+  static std::unique_ptr<HttpTestRunner::RequestRunner> Create404(
       const std::string& path) {
     CefRefPtr<CefRequest> request = CreateTestServerRequest(path, "GET");
     HttpServerResponse response(HttpServerResponse::TYPE_404);
-    return make_scoped_ptr<HttpTestRunner::RequestRunner>(
-        new StaticHttpRequestRunner(request, response));
+    return std::make_unique<StaticHttpRequestRunner>(request, response);
   }
 
-  static scoped_ptr<HttpTestRunner::RequestRunner> Create500(
+  static std::unique_ptr<HttpTestRunner::RequestRunner> Create500(
       const std::string& path) {
     CefRefPtr<CefRequest> request = CreateTestServerRequest(path, "GET");
     // Don't retry the request.
     request->SetFlags(UR_FLAG_NO_RETRY_ON_5XX);
     HttpServerResponse response(HttpServerResponse::TYPE_500);
     response.error_message = "Something went wrong!";
-    return make_scoped_ptr<HttpTestRunner::RequestRunner>(
-        new StaticHttpRequestRunner(request, response));
+    return std::make_unique<StaticHttpRequestRunner>(request, response);
   }
 
-  static scoped_ptr<HttpTestRunner::RequestRunner> CreateCustom(
+  static std::unique_ptr<HttpTestRunner::RequestRunner> CreateCustom(
       const std::string& path,
       bool with_content = true,
       bool with_content_length = true) {
@@ -974,39 +986,40 @@
 
     HttpServerResponse response(HttpServerResponse::TYPE_CUSTOM);
     response.response_code = 202;
-    if (with_content)
+    if (with_content) {
       response.content = "BlahBlahBlah";
-    if (!with_content_length)
+    }
+    if (!with_content_length) {
       response.no_content_length = true;
+    }
     response.content_type = "application/x-blah-blah";
     response.extra_headers.insert(
         std::make_pair("x-response-custom1", "My Value 1"));
     response.extra_headers.insert(
         std::make_pair("x-response-custom2", "My Value 2"));
 
-    return make_scoped_ptr<HttpTestRunner::RequestRunner>(
-        new StaticHttpRequestRunner(request, response));
+    return std::make_unique<StaticHttpRequestRunner>(request, response);
   }
 
-  scoped_ptr<TestServerHandler::HttpRequestHandler> CreateHttpRequestHandler()
-      override {
+  std::unique_ptr<TestServerHandler::HttpRequestHandler>
+  CreateHttpRequestHandler() override {
     EXPECT_FALSE(got_create_handler_);
     got_create_handler_.yes();
-    return make_scoped_ptr<TestServerHandler::HttpRequestHandler>(
-        new StaticHttpServerRequestHandler(request_, 1, response_));
+    return std::make_unique<StaticHttpServerRequestHandler>(request_, 1,
+                                                            response_);
   }
 
-  void RunRequest(const base::Closure& complete_callback) override {
+  void RunRequest(base::OnceClosure complete_callback) override {
     EXPECT_UI_THREAD();
 
     EXPECT_FALSE(got_run_request_);
     got_run_request_.yes();
 
-    complete_callback_ = complete_callback;
+    complete_callback_ = std::move(complete_callback);
 
     request_client_ = new StaticHttpURLRequestClient(
-        request_, base::Bind(&StaticHttpRequestRunner::OnResponseComplete,
-                             base::Unretained(this)));
+        request_, base::BindOnce(&StaticHttpRequestRunner::OnResponseComplete,
+                                 base::Unretained(this)));
     request_client_->RunRequest();
   }
 
@@ -1031,18 +1044,18 @@
 
     EXPECT_EQ(error, ERR_NONE)
         << "OnResponseComplete for " << request_->GetURL().ToString();
-    if (error == ERR_NONE)
+    if (error == ERR_NONE) {
       VerifyHttpServerResponse(response_, response, data);
+    }
 
-    complete_callback_.Run();
-    complete_callback_.Reset();
+    std::move(complete_callback_).Run();
   }
 
   CefRefPtr<CefRequest> request_;
   HttpServerResponse response_;
 
   CefRefPtr<StaticHttpURLRequestClient> request_client_;
-  base::Closure complete_callback_;
+  base::OnceClosure complete_callback_;
 
   TrackCallback got_run_request_;
   TrackCallback got_create_handler_;
@@ -1178,8 +1191,8 @@
 
   void RunTest() override {
     handler_ = new TestServerHandler(
-        base::Bind(&WebSocketTestHandler::OnServerStarted, this),
-        base::Bind(&WebSocketTestHandler::OnServerDestroyed, this));
+        base::BindOnce(&WebSocketTestHandler::OnServerStarted, this),
+        base::BindOnce(&WebSocketTestHandler::OnServerDestroyed, this));
     OnHandlerCreated(handler_);
 
     handler_->CreateServer();
@@ -1190,7 +1203,7 @@
 
   bool OnQuery(CefRefPtr<CefBrowser> browser,
                CefRefPtr<CefFrame> frame,
-               int64 query_id,
+               int64_t query_id,
                const CefString& request,
                bool persistent,
                CefRefPtr<Callback> callback) override {
@@ -1258,7 +1271,8 @@
   void DestroyTestIfDone() {
     if (got_server_destroyed_ && got_done_message_) {
       // Allow the call stack to unwind.
-      CefPostTask(TID_UI, base::Bind(&WebSocketTestHandler::DestroyTest, this));
+      CefPostTask(TID_UI,
+                  base::BindOnce(&WebSocketTestHandler::DestroyTest, this));
     }
   }
 
@@ -1277,7 +1291,7 @@
   explicit EchoWebSocketRequestHandler(int expected_message_ct)
       : expected_message_ct_(expected_message_ct), actual_message_ct_(0) {}
 
-  std::string GetWebSocketUrl() { return GetTestServerOrigin(true) + "echo"; }
+  std::string GetWebSocketUrl() { return GetTestServerOrigin(true) + "/echo"; }
 
   bool HandleRequest(CefRefPtr<CefServer> server,
                      int connection_id,
@@ -1427,11 +1441,10 @@
     handler->SetExpectedWsConnectedCount(connection_ct_);
     handler->SetExpectedWsMessageCount(connection_ct_ * message_ct_);
 
-    EchoWebSocketRequestHandler* echo_handler =
-        new EchoWebSocketRequestHandler(connection_ct_ * message_ct_);
+    auto echo_handler = std::make_unique<EchoWebSocketRequestHandler>(
+        connection_ct_ * message_ct_);
     ws_url_ = echo_handler->GetWebSocketUrl();
-    handler->AddWsRequestHandler(
-        make_scoped_ptr<TestServerHandler::WsRequestHandler>(echo_handler));
+    handler->AddWsRequestHandler(std::move(echo_handler));
   }
 
   void OnDoneMessage(const std::string& result) override {
diff --git a/src/tests/ceftests/shared_process_message_unittest.cc b/src/tests/ceftests/shared_process_message_unittest.cc
new file mode 100644
index 0000000..7a517ae
--- /dev/null
+++ b/src/tests/ceftests/shared_process_message_unittest.cc
@@ -0,0 +1,128 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "include/cef_shared_process_message_builder.h"
+
+#include "tests/gtest/include/gtest/gtest.h"
+
+#include <array>
+#include <type_traits>
+
+namespace {
+
+constexpr bool kTestFlag = true;
+constexpr int kTestValue = 42;
+constexpr double kTestDoubleValue = 123.456;
+
+struct TestData {
+  bool flag = kTestFlag;
+  int value = kTestValue;
+  double doubleValue = kTestDoubleValue;
+  std::array<size_t, 50> buffer{};
+};
+
+const char kSharedMessageName[] = "SharedProcessMessageTest";
+
+CefRefPtr<CefSharedProcessMessageBuilder> CreateTestBuilder() {
+  auto builder = CefSharedProcessMessageBuilder::Create(kSharedMessageName,
+                                                        sizeof(TestData));
+  EXPECT_NE(builder, nullptr);
+  EXPECT_TRUE(builder->IsValid());
+
+  static_assert(
+      std::is_trivially_copyable_v<TestData>,
+      "Do not copy non-trivially-copyable object across memory spaces");
+  auto data = static_cast<TestData*>(builder->Memory());
+  EXPECT_NE(data, nullptr);
+
+  data->value = kTestValue;
+  data->doubleValue = kTestDoubleValue;
+  data->flag = kTestFlag;
+  for (size_t i = 0; i < data->buffer.size(); ++i) {
+    data->buffer[i] = i;
+  }
+
+  return builder;
+}
+
+}  // namespace
+
+TEST(SharedProcessMessageTest, CanBuildSharedMessageUsingBuilder) {
+  auto builder = CreateTestBuilder();
+
+  auto message = builder->Build();
+  EXPECT_FALSE(builder->IsValid());
+  EXPECT_NE(message, nullptr);
+  EXPECT_TRUE(message->IsValid());
+  EXPECT_TRUE(message->IsReadOnly());
+
+  auto region = message->GetSharedMemoryRegion();
+  EXPECT_TRUE(region->IsValid());
+  auto read_data = static_cast<const TestData*>(region->Memory());
+
+  EXPECT_EQ(read_data->flag, kTestFlag);
+  EXPECT_EQ(read_data->value, kTestValue);
+  EXPECT_EQ(read_data->doubleValue, kTestDoubleValue);
+  for (size_t i = 0; i < read_data->buffer.size(); ++i) {
+    EXPECT_EQ(read_data->buffer[i], i);
+  }
+}
+
+TEST(SharedProcessMessageTest, CopyingIsNotSupportedBySharedMessage) {
+  auto builder = CefSharedProcessMessageBuilder::Create(kSharedMessageName,
+                                                        sizeof(TestData));
+  CefRefPtr<CefProcessMessage> message = builder->Build();
+  CefRefPtr<CefProcessMessage> message_copy = message->Copy();
+  EXPECT_EQ(message_copy, nullptr);
+}
+
+TEST(SharedProcessMessageTest,
+     RegionRemainsValidAfterSharedMessageDestruction) {
+  CefRefPtr<CefSharedMemoryRegion> region;
+  {
+    auto builder = CreateTestBuilder();
+    auto message = builder->Build();
+    region = message->GetSharedMemoryRegion();
+  }
+
+  EXPECT_TRUE(region->IsValid());
+  auto read_data = static_cast<const TestData*>(region->Memory());
+
+  EXPECT_EQ(read_data->flag, kTestFlag);
+  EXPECT_EQ(read_data->value, kTestValue);
+  EXPECT_EQ(read_data->doubleValue, kTestDoubleValue);
+  for (size_t i = 0; i < read_data->buffer.size(); ++i) {
+    EXPECT_EQ(read_data->buffer[i], i);
+  }
+}
+
+TEST(SharedProcessMessageTest, WrittenValuesVisibleInOtherRegion) {
+  CefRefPtr<CefSharedMemoryRegion> read_region;
+  CefRefPtr<CefSharedMemoryRegion> write_region;
+  {
+    auto builder = CreateTestBuilder();
+    auto message = builder->Build();
+    read_region = message->GetSharedMemoryRegion();
+    write_region = message->GetSharedMemoryRegion();
+  }
+
+  EXPECT_TRUE(write_region->IsValid());
+  auto write_data = static_cast<TestData*>(write_region->Memory());
+  write_data->flag = !kTestFlag;
+  write_data->value = kTestValue * 2;
+  auto new_double_value = kTestDoubleValue * 3;
+  write_data->doubleValue = new_double_value;
+  for (size_t i = 0; i < write_data->buffer.size(); ++i) {
+    write_data->buffer[i] = i + 1;
+  }
+
+  EXPECT_TRUE(read_region->IsValid());
+  auto read_data = static_cast<const TestData*>(read_region->Memory());
+  EXPECT_EQ(read_data->flag, !kTestFlag);
+  EXPECT_EQ(read_data->value, kTestValue * 2);
+  EXPECT_EQ(read_data->doubleValue, new_double_value);
+  for (size_t i = 0; i < read_data->buffer.size(); ++i) {
+    EXPECT_EQ(read_data->buffer[i], i + 1);
+  }
+}
diff --git a/src/tests/ceftests/stream_resource_handler_unittest.cc b/src/tests/ceftests/stream_resource_handler_unittest.cc
index 462f418..8745193 100644
--- a/src/tests/ceftests/stream_resource_handler_unittest.cc
+++ b/src/tests/ceftests/stream_resource_handler_unittest.cc
@@ -6,7 +6,7 @@
 #include <cstdlib>
 #include <string>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_stream.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "include/wrapper/cef_stream_resource_handler.h"
@@ -15,7 +15,7 @@
 
 namespace {
 
-const char kTestUrl[] = "http://tests-srh/test.html";
+const char kTestUrl[] = "https://tests-srh/test.html";
 const size_t kReadBlockSize = 1024U;  // 1k.
 
 // The usual network buffer size is about 32k. Choose a value that's larger.
@@ -58,12 +58,12 @@
     return read_bytes;
   }
 
-  int Seek(int64 offset, int whence) override {
+  int Seek(int64_t offset, int whence) override {
     EXPECT_TRUE(false);  // Not reached.
     return 0;
   }
 
-  int64 Tell() override {
+  int64_t Tell() override {
     EXPECT_TRUE(false);  // Not reached.
     return 0;
   }
@@ -117,7 +117,7 @@
 
   bool OnQuery(CefRefPtr<CefBrowser> browser,
                CefRefPtr<CefFrame> frame,
-               int64 query_id,
+               int64_t query_id,
                const CefString& request,
                bool persistent,
                CefRefPtr<Callback> callback) override {
@@ -143,8 +143,9 @@
 
  private:
   void DestroyTestIfDone() {
-    if (got_on_query_ && got_on_loading_state_change_done_)
+    if (got_on_query_ && got_on_loading_state_change_done_) {
       DestroyTest();
+    }
   }
 
   void DestroyTest() override {
diff --git a/src/tests/ceftests/stream_unittest.cc b/src/tests/ceftests/stream_unittest.cc
index 89c7df9..a996b2e 100644
--- a/src/tests/ceftests/stream_unittest.cc
+++ b/src/tests/ceftests/stream_unittest.cc
@@ -181,14 +181,14 @@
     return 10;
   }
 
-  int Seek(int64 offset, int whence) override {
+  int Seek(int64_t offset, int whence) override {
     seek_called_ = true;
     seek_offset_ = offset;
     seek_whence_ = whence;
     return 10;
   }
 
-  int64 Tell() override {
+  int64_t Tell() override {
     tell_called_ = true;
     return 10;
   }
@@ -206,7 +206,7 @@
   size_t read_n_;
 
   bool seek_called_;
-  int64 seek_offset_;
+  int64_t seek_offset_;
   int seek_whence_;
 
   bool tell_called_;
@@ -237,7 +237,7 @@
   ASSERT_EQ(read_n, handler->read_n_);
 
   // CefReadHandler Seek
-  int64 seek_offset = 10;
+  int64_t seek_offset = 10;
   int seek_whence = SEEK_CUR;
   int seek_res = stream->Seek(seek_offset, seek_whence);
   ASSERT_TRUE(handler->seek_called_);
@@ -246,7 +246,7 @@
   ASSERT_EQ(seek_whence, handler->seek_whence_);
 
   // CefReadHandler Tell
-  int64 tell_res = stream->Tell();
+  int64_t tell_res = stream->Tell();
   ASSERT_TRUE(handler->tell_called_);
   ASSERT_EQ(10, tell_res);
 
@@ -286,14 +286,14 @@
     return 10;
   }
 
-  int Seek(int64 offset, int whence) override {
+  int Seek(int64_t offset, int whence) override {
     seek_called_ = true;
     seek_offset_ = offset;
     seek_whence_ = whence;
     return 10;
   }
 
-  int64 Tell() override {
+  int64_t Tell() override {
     tell_called_ = true;
     return 10;
   }
@@ -311,7 +311,7 @@
   size_t write_n_;
 
   bool seek_called_;
-  int64 seek_offset_;
+  int64_t seek_offset_;
   int seek_whence_;
 
   bool tell_called_;
@@ -341,7 +341,7 @@
   ASSERT_EQ(write_n, handler->write_n_);
 
   // CefWriteHandler Seek
-  int64 seek_offset = 10;
+  int64_t seek_offset = 10;
   int seek_whence = SEEK_CUR;
   int seek_res = stream->Seek(seek_offset, seek_whence);
   ASSERT_TRUE(handler->seek_called_);
@@ -350,7 +350,7 @@
   ASSERT_EQ(seek_whence, handler->seek_whence_);
 
   // CefWriteHandler Tell
-  int64 tell_res = stream->Tell();
+  int64_t tell_res = stream->Tell();
   ASSERT_TRUE(handler->tell_called_);
   ASSERT_EQ(10, tell_res);
 
diff --git a/src/tests/ceftests/string_unittest.cc b/src/tests/ceftests/string_unittest.cc
index a260960..3e77616 100644
--- a/src/tests/ceftests/string_unittest.cc
+++ b/src/tests/ceftests/string_unittest.cc
@@ -5,7 +5,6 @@
 #include <map>
 #include <vector>
 
-#include "include/base/cef_string16.h"
 #include "include/internal/cef_string.h"
 #include "include/internal/cef_string_list.h"
 #include "include/internal/cef_string_map.h"
@@ -126,12 +125,12 @@
   EXPECT_EQ(str1, str2);
 }
 
-// Test base::string16 convertion to/from CefString types.
+// Test std::u16string convertion to/from CefString types.
 TEST(StringTest, string16) {
   CefStringUTF8 str8("Test String 1"), str8b;
   CefStringUTF16 str16("Test String 2"), str16b;
   CefStringWide strwide("Test String 3"), strwideb;
-  base::string16 base_str;
+  std::u16string base_str;
 
   base_str = str8;
   str8b = base_str;
@@ -164,8 +163,9 @@
   cef_string_list_t listPtr = cef_string_list_alloc();
   EXPECT_TRUE(listPtr != nullptr);
   ListType::const_iterator it = list.begin();
-  for (; it != list.end(); ++it)
+  for (; it != list.end(); ++it) {
     cef_string_list_append(listPtr, it->GetStruct());
+  }
 
   CefString str;
   int ret;
@@ -363,3 +363,123 @@
 
   cef_string_multimap_free(mapPtr);
 }
+
+// Test that CefString ownership behaves as expected.
+TEST(StringTest, Ownership) {
+  const char* test_cstr = "Test string";
+
+  // Initial owner makes a copy of |test_cstr|.
+  CefStringUTF8 str(test_cstr);
+  EXPECT_TRUE(str.IsOwner());
+  EXPECT_STREQ(test_cstr, str.c_str());
+  const char* str_str = str.c_str();
+  const auto str_struct = str.GetStruct();
+  EXPECT_NE(test_cstr, str_str);
+
+  // REFERENCE CREATION
+
+  // Take a reference (requires explicit use of GetStruct).
+  CefStringUTF8 str_ref(str.GetStruct());
+
+  // Nothing changes with |str|.
+  EXPECT_TRUE(str.IsOwner());
+  EXPECT_STREQ(test_cstr, str.c_str());
+  EXPECT_EQ(str.GetStruct(), str_struct);
+  EXPECT_EQ(str.c_str(), str_str);
+
+  // |str_ref| has the same value.
+  EXPECT_FALSE(str_ref.IsOwner());
+  EXPECT_STREQ(test_cstr, str_ref.c_str());
+  // Referencing the same structure and string.
+  EXPECT_EQ(str.GetStruct(), str_ref.GetStruct());
+  EXPECT_EQ(str.c_str(), str_ref.c_str());
+
+  // REFERENCE DETACH/ATTACH
+
+  // DetachToUserFree. |str_ref| loses its reference.
+  auto userfree = str_ref.DetachToUserFree();
+
+  // Nothing changes with |str|.
+  EXPECT_TRUE(str.IsOwner());
+  EXPECT_STREQ(test_cstr, str.c_str());
+  EXPECT_EQ(str.GetStruct(), str_struct);
+  EXPECT_EQ(str.c_str(), str_str);
+
+  // |str_ref| is now empty.
+  EXPECT_FALSE(str_ref.IsOwner());
+  EXPECT_TRUE(str_ref.empty());
+  EXPECT_EQ(nullptr, str_ref.GetStruct());
+
+  // AttachToUserFree. |str2| becomes an owner of the copy.
+  CefStringUTF8 str2;
+  str2.AttachToUserFree(userfree);
+
+  // Nothing changes with |str|.
+  EXPECT_TRUE(str.IsOwner());
+  EXPECT_STREQ(test_cstr, str.c_str());
+  EXPECT_EQ(str.GetStruct(), str_struct);
+  EXPECT_EQ(str.c_str(), str_str);
+
+  // |str2| is now an owner of a copy.
+  EXPECT_TRUE(str2.IsOwner());
+  EXPECT_STREQ(test_cstr, str2.c_str());
+  // Not referencing the same structure or string.
+  EXPECT_NE(str.GetStruct(), str2.GetStruct());
+  EXPECT_NE(str.c_str(), str2.c_str());
+
+  // |str_ref| is still empty.
+  EXPECT_FALSE(str_ref.IsOwner());
+  EXPECT_TRUE(str_ref.empty());
+  EXPECT_EQ(nullptr, str_ref.GetStruct());
+
+  // OWNER COPY CREATION
+
+  // Making a copy (default copy constructor behavior).
+  CefStringUTF8 str3(str);
+
+  // Nothing changes with |str|.
+  EXPECT_TRUE(str.IsOwner());
+  EXPECT_STREQ(test_cstr, str.c_str());
+  EXPECT_EQ(str.GetStruct(), str_struct);
+  EXPECT_EQ(str.c_str(), str_str);
+
+  // |str3| is now an owner of a copy.
+  EXPECT_TRUE(str3.IsOwner());
+  EXPECT_STREQ(test_cstr, str3.c_str());
+  // Not referencing the same structure or string.
+  EXPECT_NE(str.GetStruct(), str3.GetStruct());
+  EXPECT_NE(str.c_str(), str3.c_str());
+
+  // OWNER DETACH/ATTACH
+
+  // DetachToUserFree. |str3| loses its ownership.
+  const char* str3_str = str3.c_str();
+  auto userfree3 = str3.DetachToUserFree();
+
+  // Nothing changes with |str|.
+  EXPECT_TRUE(str.IsOwner());
+  EXPECT_STREQ(test_cstr, str.c_str());
+  EXPECT_EQ(str.GetStruct(), str_struct);
+  EXPECT_EQ(str.c_str(), str_str);
+
+  // |str3| is now empty.
+  EXPECT_FALSE(str3.IsOwner());
+  EXPECT_TRUE(str3.empty());
+  EXPECT_EQ(nullptr, str3.GetStruct());
+
+  // AttachToUserFree. |str3| regains its ownership.
+  str3.AttachToUserFree(userfree3);
+
+  // Nothing changes with |str|.
+  EXPECT_TRUE(str.IsOwner());
+  EXPECT_STREQ(test_cstr, str.c_str());
+  EXPECT_EQ(str.GetStruct(), str_struct);
+  EXPECT_EQ(str.c_str(), str_str);
+
+  // |str3| is now an owner of the same string that it had previously.
+  // The structure will also be re-allocated, but we don't test that because
+  // the same address might be reused.
+  EXPECT_TRUE(str3.IsOwner());
+  EXPECT_STREQ(test_cstr, str3.c_str());
+  EXPECT_EQ(str3_str, str3.c_str());
+}
diff --git a/src/tests/ceftests/task_unittest.cc b/src/tests/ceftests/task_unittest.cc
index 24a39cb..b413fa9 100644
--- a/src/tests/ceftests/task_unittest.cc
+++ b/src/tests/ceftests/task_unittest.cc
@@ -2,21 +2,22 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_command_line.h"
 #include "include/cef_task.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "tests/ceftests/test_handler.h"
+#include "tests/ceftests/test_util.h"
 #include "tests/gtest/include/gtest/gtest.h"
 
 namespace {
 
 void WaitForEvent(CefRefPtr<CefWaitableEvent> event) {
-  if (CefCommandLine::GetGlobalCommandLine()->HasSwitch(
-          "disable-test-timeout")) {
+  const auto timeout = GetConfiguredTestTimeout(/*timeout_ms=*/1000);
+  if (!timeout) {
     event->Wait();
   } else {
-    EXPECT_TRUE(event->TimedWait(1000));
+    EXPECT_TRUE(event->TimedWait(*timeout));
   }
 }
 
@@ -25,7 +26,7 @@
   CefRefPtr<CefTaskRunner> runner = CefTaskRunner::GetForCurrentThread();
   EXPECT_TRUE(runner.get());
   EXPECT_TRUE(runner->BelongsToCurrentThread());
-  EXPECT_TRUE(runner->BelongsToThread(TID_FILE));
+  EXPECT_TRUE(runner->BelongsToThread(TID_FILE_USER_VISIBLE));
   EXPECT_FALSE(runner->BelongsToThread(TID_IO));
   EXPECT_TRUE(runner->IsSame(runner));
 
@@ -50,7 +51,7 @@
   EXPECT_TRUE(runner.get());
   EXPECT_FALSE(runner->BelongsToCurrentThread());
   EXPECT_TRUE(runner->BelongsToThread(TID_IO));
-  EXPECT_FALSE(runner->BelongsToThread(TID_FILE));
+  EXPECT_FALSE(runner->BelongsToThread(TID_FILE_USER_VISIBLE));
   EXPECT_TRUE(runner->IsSame(runner));
 
   CefRefPtr<CefTaskRunner> runner2 = CefTaskRunner::GetForThread(TID_IO);
@@ -58,7 +59,8 @@
   EXPECT_TRUE(runner->IsSame(runner2));
   EXPECT_TRUE(runner2->IsSame(runner));
 
-  CefRefPtr<CefTaskRunner> runner3 = CefTaskRunner::GetForThread(TID_FILE);
+  CefRefPtr<CefTaskRunner> runner3 =
+      CefTaskRunner::GetForThread(TID_FILE_USER_VISIBLE);
   EXPECT_TRUE(runner3.get());
   EXPECT_FALSE(runner->IsSame(runner3));
   EXPECT_FALSE(runner3->IsSame(runner));
@@ -73,14 +75,14 @@
   // Currently on the IO thread.
   EXPECT_TRUE(runner->BelongsToCurrentThread());
   EXPECT_TRUE(runner->BelongsToThread(TID_IO));
-  EXPECT_FALSE(runner->BelongsToThread(TID_FILE));
+  EXPECT_FALSE(runner->BelongsToThread(TID_FILE_USER_VISIBLE));
 
   // Current thread should be the IO thread.
   CefRefPtr<CefTaskRunner> runner2 = CefTaskRunner::GetForCurrentThread();
   EXPECT_TRUE(runner2.get());
   EXPECT_TRUE(runner2->BelongsToCurrentThread());
   EXPECT_TRUE(runner2->BelongsToThread(TID_IO));
-  EXPECT_FALSE(runner2->BelongsToThread(TID_FILE));
+  EXPECT_FALSE(runner2->BelongsToThread(TID_FILE_USER_VISIBLE));
   EXPECT_TRUE(runner->IsSame(runner2));
   EXPECT_TRUE(runner2->IsSame(runner));
 
@@ -89,16 +91,17 @@
   EXPECT_TRUE(runner3.get());
   EXPECT_TRUE(runner3->BelongsToCurrentThread());
   EXPECT_TRUE(runner3->BelongsToThread(TID_IO));
-  EXPECT_FALSE(runner3->BelongsToThread(TID_FILE));
+  EXPECT_FALSE(runner3->BelongsToThread(TID_FILE_USER_VISIBLE));
   EXPECT_TRUE(runner->IsSame(runner3));
   EXPECT_TRUE(runner3->IsSame(runner));
 
   // Current thread should not be the FILE thread.
-  CefRefPtr<CefTaskRunner> runner4 = CefTaskRunner::GetForThread(TID_FILE);
+  CefRefPtr<CefTaskRunner> runner4 =
+      CefTaskRunner::GetForThread(TID_FILE_USER_VISIBLE);
   EXPECT_TRUE(runner4.get());
   EXPECT_FALSE(runner4->BelongsToCurrentThread());
   EXPECT_FALSE(runner4->BelongsToThread(TID_IO));
-  EXPECT_TRUE(runner4->BelongsToThread(TID_FILE));
+  EXPECT_TRUE(runner4->BelongsToThread(TID_FILE_USER_VISIBLE));
   EXPECT_FALSE(runner->IsSame(runner4));
   EXPECT_FALSE(runner4->IsSame(runner));
 
@@ -106,7 +109,7 @@
   event->Signal();
 }
 
-void PostTask1(bool* ran_test, CefRefPtr<CefWaitableEvent> event) {
+void PostOnceTask1(bool* ran_test, CefRefPtr<CefWaitableEvent> event) {
   // Currently on the FILE thread.
   CefRefPtr<CefTaskRunner> runner = CefTaskRunner::GetForThread(TID_IO);
   EXPECT_TRUE(runner.get());
@@ -114,104 +117,216 @@
   EXPECT_TRUE(runner->BelongsToThread(TID_IO));
 
   runner->PostTask(CefCreateClosureTask(
-      base::Bind(&PostTaskEvent1, ran_test, event, runner)));
+      base::BindOnce(&PostTaskEvent1, ran_test, event, runner)));
 }
 
-void PostDelayedTask1(bool* ran_test, CefRefPtr<CefWaitableEvent> event) {
+void PostRepeatingTask1(bool* ran_test, CefRefPtr<CefWaitableEvent> event) {
   // Currently on the FILE thread.
   CefRefPtr<CefTaskRunner> runner = CefTaskRunner::GetForThread(TID_IO);
   EXPECT_TRUE(runner.get());
   EXPECT_FALSE(runner->BelongsToCurrentThread());
   EXPECT_TRUE(runner->BelongsToThread(TID_IO));
 
-  runner->PostDelayedTask(CefCreateClosureTask(base::Bind(
+  runner->PostTask(CefCreateClosureTask(
+      base::BindRepeating(&PostTaskEvent1, ran_test, event, runner)));
+}
+
+void PostOnceDelayedTask1(bool* ran_test, CefRefPtr<CefWaitableEvent> event) {
+  // Currently on the FILE thread.
+  CefRefPtr<CefTaskRunner> runner = CefTaskRunner::GetForThread(TID_IO);
+  EXPECT_TRUE(runner.get());
+  EXPECT_FALSE(runner->BelongsToCurrentThread());
+  EXPECT_TRUE(runner->BelongsToThread(TID_IO));
+
+  runner->PostDelayedTask(CefCreateClosureTask(base::BindOnce(
+                              &PostTaskEvent1, ran_test, event, runner)),
+                          0);
+}
+
+void PostRepeatingDelayedTask1(bool* ran_test,
+                               CefRefPtr<CefWaitableEvent> event) {
+  // Currently on the FILE thread.
+  CefRefPtr<CefTaskRunner> runner = CefTaskRunner::GetForThread(TID_IO);
+  EXPECT_TRUE(runner.get());
+  EXPECT_FALSE(runner->BelongsToCurrentThread());
+  EXPECT_TRUE(runner->BelongsToThread(TID_IO));
+
+  runner->PostDelayedTask(CefCreateClosureTask(base::BindRepeating(
                               &PostTaskEvent1, ran_test, event, runner)),
                           0);
 }
 
 void PostTaskEvent2(bool* ran_test, CefRefPtr<CefWaitableEvent> event) {
   EXPECT_TRUE(CefCurrentlyOn(TID_IO));
-  EXPECT_FALSE(CefCurrentlyOn(TID_FILE));
+  EXPECT_FALSE(CefCurrentlyOn(TID_FILE_USER_VISIBLE));
 
   *ran_test = true;
   event->Signal();
 }
 
-void PostTask2(bool* ran_test, CefRefPtr<CefWaitableEvent> event) {
+void PostOnceTask2(bool* ran_test, CefRefPtr<CefWaitableEvent> event) {
   // Currently on the FILE thread.
   EXPECT_FALSE(CefCurrentlyOn(TID_IO));
 
   CefPostTask(TID_IO, CefCreateClosureTask(
-                          base::Bind(&PostTaskEvent2, ran_test, event)));
+                          base::BindOnce(&PostTaskEvent2, ran_test, event)));
 }
 
-void PostDelayedTask2(bool* ran_test, CefRefPtr<CefWaitableEvent> event) {
+void PostRepeatingTask2(bool* ran_test, CefRefPtr<CefWaitableEvent> event) {
+  // Currently on the FILE thread.
+  EXPECT_FALSE(CefCurrentlyOn(TID_IO));
+
+  CefPostTask(TID_IO, CefCreateClosureTask(base::BindRepeating(
+                          &PostTaskEvent2, ran_test, event)));
+}
+
+void PostOnceDelayedTask2(bool* ran_test, CefRefPtr<CefWaitableEvent> event) {
   // Currently on the FILE thread.
   EXPECT_FALSE(CefCurrentlyOn(TID_IO));
 
   CefPostDelayedTask(
       TID_IO,
-      CefCreateClosureTask(base::Bind(&PostTaskEvent2, ran_test, event)), 0);
+      CefCreateClosureTask(base::BindOnce(&PostTaskEvent2, ran_test, event)),
+      0);
+}
+
+void PostRepeatingDelayedTask2(bool* ran_test,
+                               CefRefPtr<CefWaitableEvent> event) {
+  // Currently on the FILE thread.
+  EXPECT_FALSE(CefCurrentlyOn(TID_IO));
+
+  CefPostDelayedTask(TID_IO,
+                     CefCreateClosureTask(
+                         base::BindRepeating(&PostTaskEvent2, ran_test, event)),
+                     0);
 }
 
 }  // namespace
 
-TEST(TaskTest, GetForCurrentThread) {
+TEST(TaskTest, GetOnceForCurrentThread) {
   bool ran_test = false;
   CefRefPtr<CefWaitableEvent> event =
       CefWaitableEvent::CreateWaitableEvent(true, false);
-  CefPostTask(TID_FILE, CefCreateClosureTask(base::Bind(&GetForCurrentThread,
-                                                        &ran_test, event)));
+  CefPostTask(TID_FILE_USER_VISIBLE,
+              CefCreateClosureTask(
+                  base::BindOnce(&GetForCurrentThread, &ran_test, event)));
   WaitForEvent(event);
   EXPECT_TRUE(ran_test);
 }
 
-TEST(TaskTest, GetForThread) {
+TEST(TaskTest, GetRepeatingForCurrentThread) {
   bool ran_test = false;
   CefRefPtr<CefWaitableEvent> event =
       CefWaitableEvent::CreateWaitableEvent(true, false);
-  CefPostTask(TID_FILE, CefCreateClosureTask(
-                            base::Bind(&GetForThread, &ran_test, event)));
+  CefPostTask(TID_FILE_USER_VISIBLE,
+              CefCreateClosureTask(
+                  base::BindRepeating(&GetForCurrentThread, &ran_test, event)));
   WaitForEvent(event);
   EXPECT_TRUE(ran_test);
 }
 
-TEST(TaskTest, PostTask1) {
+TEST(TaskTest, GetOnceForThread) {
   bool ran_test = false;
   CefRefPtr<CefWaitableEvent> event =
       CefWaitableEvent::CreateWaitableEvent(true, false);
-  CefPostTask(TID_FILE,
-              CefCreateClosureTask(base::Bind(&PostTask1, &ran_test, event)));
+  CefPostTask(TID_FILE_USER_VISIBLE, CefCreateClosureTask(base::BindOnce(
+                                         &GetForThread, &ran_test, event)));
   WaitForEvent(event);
   EXPECT_TRUE(ran_test);
 }
 
-TEST(TaskTest, PostDelayedTask1) {
+TEST(TaskTest, GetRepeatingForThread) {
   bool ran_test = false;
   CefRefPtr<CefWaitableEvent> event =
       CefWaitableEvent::CreateWaitableEvent(true, false);
-  CefPostTask(TID_FILE, CefCreateClosureTask(
-                            base::Bind(&PostDelayedTask1, &ran_test, event)));
+  CefPostTask(TID_FILE_USER_VISIBLE, CefCreateClosureTask(base::BindRepeating(
+                                         &GetForThread, &ran_test, event)));
   WaitForEvent(event);
   EXPECT_TRUE(ran_test);
 }
 
-TEST(TaskTest, PostTask2) {
+TEST(TaskTest, PostOnceTask1) {
   bool ran_test = false;
   CefRefPtr<CefWaitableEvent> event =
       CefWaitableEvent::CreateWaitableEvent(true, false);
-  CefPostTask(TID_FILE,
-              CefCreateClosureTask(base::Bind(&PostTask2, &ran_test, event)));
+  CefPostTask(TID_FILE_USER_VISIBLE, CefCreateClosureTask(base::BindOnce(
+                                         &PostOnceTask1, &ran_test, event)));
   WaitForEvent(event);
   EXPECT_TRUE(ran_test);
 }
 
-TEST(TaskTest, PostDelayedTask2) {
+TEST(TaskTest, PostRepeatingTask1) {
   bool ran_test = false;
   CefRefPtr<CefWaitableEvent> event =
       CefWaitableEvent::CreateWaitableEvent(true, false);
-  CefPostTask(TID_FILE, CefCreateClosureTask(
-                            base::Bind(&PostDelayedTask2, &ran_test, event)));
+  CefPostTask(TID_FILE_USER_VISIBLE,
+              CefCreateClosureTask(
+                  base::BindRepeating(&PostRepeatingTask1, &ran_test, event)));
+  WaitForEvent(event);
+  EXPECT_TRUE(ran_test);
+}
+
+TEST(TaskTest, PostOnceDelayedTask1) {
+  bool ran_test = false;
+  CefRefPtr<CefWaitableEvent> event =
+      CefWaitableEvent::CreateWaitableEvent(true, false);
+  CefPostTask(TID_FILE_USER_VISIBLE,
+              CefCreateClosureTask(
+                  base::BindOnce(&PostOnceDelayedTask1, &ran_test, event)));
+  WaitForEvent(event);
+  EXPECT_TRUE(ran_test);
+}
+
+TEST(TaskTest, PostRepeatingDelayedTask1) {
+  bool ran_test = false;
+  CefRefPtr<CefWaitableEvent> event =
+      CefWaitableEvent::CreateWaitableEvent(true, false);
+  CefPostTask(TID_FILE_USER_VISIBLE,
+              CefCreateClosureTask(base::BindRepeating(
+                  &PostRepeatingDelayedTask1, &ran_test, event)));
+  WaitForEvent(event);
+  EXPECT_TRUE(ran_test);
+}
+
+TEST(TaskTest, PostOnceTask2) {
+  bool ran_test = false;
+  CefRefPtr<CefWaitableEvent> event =
+      CefWaitableEvent::CreateWaitableEvent(true, false);
+  CefPostTask(TID_FILE_USER_VISIBLE, CefCreateClosureTask(base::BindOnce(
+                                         &PostOnceTask2, &ran_test, event)));
+  WaitForEvent(event);
+  EXPECT_TRUE(ran_test);
+}
+
+TEST(TaskTest, PostRepeatingTask2) {
+  bool ran_test = false;
+  CefRefPtr<CefWaitableEvent> event =
+      CefWaitableEvent::CreateWaitableEvent(true, false);
+  CefPostTask(TID_FILE_USER_VISIBLE,
+              CefCreateClosureTask(
+                  base::BindRepeating(&PostRepeatingTask2, &ran_test, event)));
+  WaitForEvent(event);
+  EXPECT_TRUE(ran_test);
+}
+
+TEST(TaskTest, PostOnceDelayedTask2) {
+  bool ran_test = false;
+  CefRefPtr<CefWaitableEvent> event =
+      CefWaitableEvent::CreateWaitableEvent(true, false);
+  CefPostTask(TID_FILE_USER_VISIBLE,
+              CefCreateClosureTask(
+                  base::BindOnce(&PostOnceDelayedTask2, &ran_test, event)));
+  WaitForEvent(event);
+  EXPECT_TRUE(ran_test);
+}
+
+TEST(TaskTest, PostRepeatingDelayedTask2) {
+  bool ran_test = false;
+  CefRefPtr<CefWaitableEvent> event =
+      CefWaitableEvent::CreateWaitableEvent(true, false);
+  CefPostTask(TID_FILE_USER_VISIBLE,
+              CefCreateClosureTask(base::BindRepeating(
+                  &PostRepeatingDelayedTask2, &ran_test, event)));
   WaitForEvent(event);
   EXPECT_TRUE(ran_test);
 }
diff --git a/src/tests/ceftests/test_handler.cc b/src/tests/ceftests/test_handler.cc
index ff064bf..547f66d 100644
--- a/src/tests/ceftests/test_handler.cc
+++ b/src/tests/ceftests/test_handler.cc
@@ -4,32 +4,43 @@
 
 #include "tests/ceftests/test_handler.h"
 
-#include "include/base/cef_bind.h"
+#include <sstream>
+
+#include "include/base/cef_callback.h"
 #include "include/base/cef_logging.h"
 #include "include/cef_command_line.h"
 #include "include/cef_stream.h"
-#include "include/wrapper/cef_closure_task.h"
-#include "include/wrapper/cef_stream_resource_handler.h"
-#include "tests/shared/common/client_switches.h"
-
-#if defined(USE_AURA)
 #include "include/views/cef_browser_view.h"
 #include "include/views/cef_window.h"
-#endif
+#include "include/wrapper/cef_closure_task.h"
+#include "include/wrapper/cef_stream_resource_handler.h"
+#include "tests/ceftests/test_request.h"
+#include "tests/ceftests/test_util.h"
+#include "tests/shared/common/client_switches.h"
+
+// Set to 1 to enable verbose debugging info logging.
+#define VERBOSE_DEBUGGING 0
 
 namespace {
 
-#if defined(USE_AURA)
+bool UseViewsGlobal() {
+  static bool use_views = []() {
+    return CefCommandLine::GetGlobalCommandLine()->HasSwitch(
+        client::switches::kUseViews);
+  }();
+  return use_views;
+}
 
 // Delegate implementation for the CefWindow that will host the Views-based
 // browser.
 class TestWindowDelegate : public CefWindowDelegate {
  public:
   // Create a new top-level Window hosting |browser_view|.
-  static void CreateBrowserWindow(CefRefPtr<CefBrowserView> browser_view,
+  static void CreateBrowserWindow(TestHandler* handler,
+                                  CefRefPtr<CefBrowserView> browser_view,
                                   const std::string& title) {
-    CefWindow::CreateTopLevelWindow(
-        new TestWindowDelegate(browser_view, "CefUnitTestViews " + title));
+    CefWindow::CreateTopLevelWindow(new TestWindowDelegate(
+        handler, browser_view, "CefUnitTestViews " + title));
   }
 
   // CefWindowDelegate methods:
@@ -40,26 +51,37 @@
     window->SetTitle(title_);
     window->AddChildView(browser_view_);
     window->Show();
+
+    // With Chrome runtime, the Browser is not created until after the
+    // BrowserView is assigned to the Window.
+    browser_id_ = browser_view_->GetBrowser()->GetIdentifier();
+    handler_->OnWindowCreated(browser_id_);
   }
 
   void OnWindowDestroyed(CefRefPtr<CefWindow> window) override {
+    auto browser = browser_view_->GetBrowser();
     browser_view_ = nullptr;
+    handler_->OnWindowDestroyed(browser_id_);
   }
 
   bool CanClose(CefRefPtr<CefWindow> window) override {
     // Allow the window to close if the browser says it's OK.
     CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
-    if (browser)
+    if (browser) {
       return browser->GetHost()->TryCloseBrowser();
+    }
     return true;
   }
 
  private:
-  TestWindowDelegate(CefRefPtr<CefBrowserView> browser_view,
+  TestWindowDelegate(TestHandler* handler,
+                     CefRefPtr<CefBrowserView> browser_view,
                      const CefString& title)
-      : browser_view_(browser_view), title_(title) {}
+      : handler_(handler), browser_view_(browser_view), title_(title) {}
 
+  TestHandler* const handler_;
   CefRefPtr<CefBrowserView> browser_view_;
+  int browser_id_ = 0;
   CefString title_;
 
   IMPLEMENT_REFCOUNTING(TestWindowDelegate);
@@ -69,26 +91,61 @@
 // Delegate implementation for the CefBrowserView.
 class TestBrowserViewDelegate : public CefBrowserViewDelegate {
  public:
-  TestBrowserViewDelegate() {}
+  explicit TestBrowserViewDelegate(TestHandler* handler) : handler_(handler) {}
 
   // CefBrowserViewDelegate methods:
 
+  void OnBrowserDestroyed(CefRefPtr<CefBrowserView> browser_view,
+                          CefRefPtr<CefBrowser> browser) override {
+#if VERBOSE_DEBUGGING
+    LOG(INFO) << handler_->debug_string_prefix() << browser->GetIdentifier()
+              << ": OnBrowserDestroyed";
+#endif
+    // Always close the containing Window when the browser is destroyed.
+    if (auto window = browser_view->GetWindow()) {
+#if VERBOSE_DEBUGGING
+      LOG(INFO) << handler_->debug_string_prefix() << browser->GetIdentifier()
+                << ": OnBrowserDestroyed Close";
+#endif
+      window->Close();
+    }
+  }
+
+  CefRefPtr<CefBrowserViewDelegate> GetDelegateForPopupBrowserView(
+      CefRefPtr<CefBrowserView> browser_view,
+      const CefBrowserSettings& settings,
+      CefRefPtr<CefClient> client,
+      bool is_devtools) override {
+    if (client.get() == handler_) {
+      // Use the same Delegate when using the same TestHandler instance.
+      return this;
+    }
+
+    // Return a new Delegate when using a different TestHandler instance.
+    auto* handler = static_cast<TestHandler*>(client.get());
+    return new TestBrowserViewDelegate(handler);
+  }
+
   bool OnPopupBrowserViewCreated(CefRefPtr<CefBrowserView> browser_view,
                                  CefRefPtr<CefBrowserView> popup_browser_view,
                                  bool is_devtools) override {
+    // The popup may use a different TestHandler instance.
+    auto* handler = static_cast<TestHandler*>(
+        popup_browser_view->GetBrowser()->GetHost()->GetClient().get());
+
     // Create our own Window for popups. It will show itself after creation.
-    TestWindowDelegate::CreateBrowserWindow(popup_browser_view,
+    TestWindowDelegate::CreateBrowserWindow(handler, popup_browser_view,
                                             is_devtools ? "DevTools" : "Popup");
     return true;
   }
 
  private:
+  TestHandler* const handler_;
+
   IMPLEMENT_REFCOUNTING(TestBrowserViewDelegate);
   DISALLOW_COPY_AND_ASSIGN(TestBrowserViewDelegate);
 };
 
-#endif  // defined(USE_AURA)
-
 }  // namespace
 
 // TestHandler::CompletionState
@@ -134,14 +191,16 @@
   TestHandlerList::const_iterator it;
 
   it = handler_list_.begin();
-  for (; it != handler_list_.end(); ++it)
+  for (; it != handler_list_.end(); ++it) {
     (*it)->SetupTest();
+  }
 
   completion_state_->WaitForTests();
 
   it = handler_list_.begin();
-  for (; it != handler_list_.end(); ++it)
+  for (; it != handler_list_.end(); ++it) {
     (*it)->RunTest();
+  }
 
   completion_state_->WaitForTests();
 }
@@ -150,36 +209,38 @@
 
 TestHandler::UIThreadHelper::UIThreadHelper() : weak_ptr_factory_(this) {}
 
-void TestHandler::UIThreadHelper::PostTask(const base::Closure& task) {
+void TestHandler::UIThreadHelper::PostTask(base::OnceClosure task) {
   EXPECT_UI_THREAD();
-  CefPostTask(TID_UI, base::Bind(&UIThreadHelper::TaskHelper,
-                                 weak_ptr_factory_.GetWeakPtr(), task));
+  CefPostTask(TID_UI,
+              base::BindOnce(&UIThreadHelper::TaskHelper,
+                             weak_ptr_factory_.GetWeakPtr(), std::move(task)));
 }
 
-void TestHandler::UIThreadHelper::PostDelayedTask(const base::Closure& task,
+void TestHandler::UIThreadHelper::PostDelayedTask(base::OnceClosure task,
                                                   int delay_ms) {
   EXPECT_UI_THREAD();
-  CefPostDelayedTask(TID_UI,
-                     base::Bind(&UIThreadHelper::TaskHelper,
-                                weak_ptr_factory_.GetWeakPtr(), task),
-                     delay_ms);
+  CefPostDelayedTask(
+      TID_UI,
+      base::BindOnce(&UIThreadHelper::TaskHelper,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(task)),
+      delay_ms);
 }
 
-void TestHandler::UIThreadHelper::TaskHelper(const base::Closure& task) {
+void TestHandler::UIThreadHelper::TaskHelper(base::OnceClosure task) {
   EXPECT_UI_THREAD();
-  task.Run();
+  std::move(task).Run();
 }
 
 // TestHandler
 
-int TestHandler::browser_count_ = 0;
+// static
+std::atomic<size_t> TestHandler::test_handler_count_{0U};
 
 TestHandler::TestHandler(CompletionState* completion_state)
-    : first_browser_id_(0),
-      signal_completion_when_all_browsers_close_(true),
-      destroy_event_(nullptr),
-      destroy_test_expected_(true),
-      destroy_test_called_(false) {
+    : debug_string_prefix_(MakeDebugStringPrefix()),
+      use_views_(UseViewsGlobal()) {
+  test_handler_count_++;
+
   if (completion_state) {
     completion_state_ = completion_state;
     completion_state_owned_ = false;
@@ -191,24 +252,28 @@
 
 TestHandler::~TestHandler() {
   DCHECK(!ui_thread_helper_.get());
-  if (destroy_test_expected_)
+  if (destroy_test_expected_) {
     EXPECT_TRUE(destroy_test_called_);
-  else
+  } else {
     EXPECT_FALSE(destroy_test_called_);
+  }
   EXPECT_TRUE(browser_map_.empty());
+  EXPECT_TRUE(browser_status_map_.empty());
 
-  if (completion_state_owned_)
+  if (completion_state_owned_) {
     delete completion_state_;
+  }
 
-  if (destroy_event_)
+  if (destroy_event_) {
     destroy_event_->Signal();
+  }
+
+  test_handler_count_--;
 }
 
 void TestHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
   EXPECT_UI_THREAD();
 
-  browser_count_++;
-
   const int browser_id = browser->GetIdentifier();
   EXPECT_EQ(browser_map_.find(browser_id), browser_map_.end());
   if (browser_map_.empty()) {
@@ -216,6 +281,9 @@
     first_browser_ = browser;
   }
   browser_map_.insert(std::make_pair(browser_id, browser));
+
+  const bool views_hosted = !!CefBrowserView::GetForBrowser(browser);
+  OnCreated(browser_id, NT_BROWSER, views_hosted);
 }
 
 void TestHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
@@ -232,12 +300,103 @@
     first_browser_ = nullptr;
   }
 
-  if (browser_map_.empty() && signal_completion_when_all_browsers_close_) {
-    // Signal that the test is now complete.
-    TestComplete();
+  OnClosed(browser_id, NT_BROWSER);
+}
+
+void TestHandler::OnWindowCreated(int browser_id) {
+  CHECK(use_views_);
+  EXPECT_UI_THREAD();
+  OnCreated(browser_id, NT_WINDOW, /*views_hosted=*/true);
+}
+
+void TestHandler::OnWindowDestroyed(int browser_id) {
+  CHECK(use_views_);
+  EXPECT_UI_THREAD();
+  OnClosed(browser_id, NT_WINDOW);
+}
+
+void TestHandler::OnCreated(int browser_id,
+                            NotifyType type,
+                            bool views_hosted) {
+  CHECK(use_views_ || !views_hosted);
+
+  const bool has_value =
+      browser_status_map_.find(browser_id) != browser_status_map_.end();
+
+  auto& browser_status = browser_status_map_[browser_id];
+  if (has_value) {
+    CHECK_EQ(browser_status.views_hosted, views_hosted);
+  } else {
+    browser_status.views_hosted = views_hosted;
   }
 
-  browser_count_--;
+  EXPECT_FALSE(browser_status.got_created[type])
+      << "Duplicate call to OnCreated(" << browser_id << ", "
+      << (type == NT_BROWSER ? "BROWSER" : "WINDOW") << ")";
+  browser_status.got_created[type].yes();
+
+#if VERBOSE_DEBUGGING
+  bool creation_complete = false;
+
+  // When using Views, wait for both Browser and Window notifications.
+  if (browser_status.views_hosted) {
+    creation_complete = browser_status.got_created[NT_BROWSER] &&
+                        browser_status.got_created[NT_WINDOW];
+  } else {
+    creation_complete = browser_status.got_created[NT_BROWSER];
+  }
+
+  LOG(INFO) << debug_string_prefix_ << browser_id << ": OnCreated type="
+            << (type == NT_BROWSER ? "BROWSER" : "WINDOW")
+            << " creation_complete=" << creation_complete;
+#endif  // VERBOSE_DEBUGGING
+}
+
+void TestHandler::OnClosed(int browser_id, NotifyType type) {
+  bool close_complete = false;
+
+  auto& browser_status = browser_status_map_[browser_id];
+  EXPECT_FALSE(browser_status.got_closed[type])
+      << "Duplicate call to OnClosed(" << browser_id << ", "
+      << (type == NT_BROWSER ? "BROWSER" : "WINDOW") << ")";
+  browser_status.got_closed[type].yes();
+
+  // When using Views, wait for both Browser and Window notifications.
+  if (browser_status.views_hosted) {
+    close_complete = browser_status.got_closed[NT_BROWSER] &&
+                     browser_status.got_closed[NT_WINDOW];
+  } else {
+    close_complete = browser_status.got_closed[NT_BROWSER];
+  }
+
+  if (close_complete) {
+    browser_status_map_.erase(browser_id);
+  }
+
+  // Test may be complete if no Browsers/Windows are remaining.
+  const bool all_browsers_closed = AllBrowsersClosed();
+
+#if VERBOSE_DEBUGGING
+  LOG(INFO) << debug_string_prefix_ << browser_id
+            << ": OnClosed type=" << (type == NT_BROWSER ? "BROWSER" : "WINDOW")
+            << " close_complete=" << close_complete
+            << " all_browsers_closed=" << all_browsers_closed;
+#endif
+
+  if (all_browsers_closed) {
+    // May result in |this| being deleted.
+    MaybeTestComplete();
+  }
+}
+
+std::string TestHandler::MakeDebugStringPrefix() const {
+#if VERBOSE_DEBUGGING
+  std::stringstream ss;
+  ss << "TestHandler [0x" << std::hex << this << "]: ";
+  return ss.str();
+#else
+  return std::string();
+#endif
 }
 
 namespace {
@@ -261,15 +420,8 @@
   EXPECT_IO_THREAD();
 
   if (resource_map_.size() > 0) {
-    CefString url = request->GetURL();
-
-    // Ignore the query component, if any.
-    std::string urlStr = url;
-    size_t idx = urlStr.find('?');
-    if (idx > 0)
-      urlStr = urlStr.substr(0, idx);
-
-    ResourceMap::const_iterator it = resource_map_.find(urlStr);
+    const std::string& url = test_request::GetPathURL(request->GetURL());
+    ResourceMap::const_iterator it = resource_map_.find(url);
     if (it != resource_map_.end()) {
       // Return the previously mapped resource
       CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData(
@@ -289,11 +441,11 @@
   LOG(WARNING) << "OnRenderProcessTerminated: status = " << status << ".";
 }
 
-CefRefPtr<CefBrowser> TestHandler::GetBrowser() {
+CefRefPtr<CefBrowser> TestHandler::GetBrowser() const {
   return first_browser_;
 }
 
-int TestHandler::GetBrowserId() {
+int TestHandler::GetBrowserId() const {
   return first_browser_id_;
 }
 
@@ -307,8 +459,12 @@
   EXPECT_EQ(completion_state_->total(), 1);
 
   // Reset any state from the previous run.
-  if (destroy_test_called_)
+  if (test_timeout_called_) {
+    test_timeout_called_ = false;
+  }
+  if (destroy_test_called_) {
     destroy_test_called_ = false;
+  }
 
   // Run the test.
   RunTest();
@@ -324,13 +480,14 @@
 
 void TestHandler::DestroyTest() {
   if (!CefCurrentlyOn(TID_UI)) {
-    CefPostTask(TID_UI, base::Bind(&TestHandler::DestroyTest, this));
+    CefPostTask(TID_UI, base::BindOnce(&TestHandler::DestroyTest, this));
     return;
   }
 
   EXPECT_TRUE(destroy_test_expected_);
-  if (destroy_test_called_)
+  if (destroy_test_called_) {
     return;
+  }
   destroy_test_called_ = true;
 
   if (!browser_map_.empty()) {
@@ -340,52 +497,59 @@
 
     // Tell all browsers to close.
     BrowserMap::const_iterator it = browser_map.begin();
-    for (; it != browser_map.end(); ++it)
+    for (; it != browser_map.end(); ++it) {
       CloseBrowser(it->second, false);
+    }
   }
-
-  if (ui_thread_helper_.get())
-    ui_thread_helper_.reset(nullptr);
 }
 
 void TestHandler::OnTestTimeout(int timeout_ms, bool treat_as_error) {
   EXPECT_UI_THREAD();
+
+  EXPECT_FALSE(test_timeout_called_);
+  test_timeout_called_ = true;
+
   if (treat_as_error) {
     EXPECT_TRUE(false) << "Test timed out after " << timeout_ms << "ms";
   }
+
+  EXPECT_FALSE(AllBrowsersClosed() && AllowTestCompletionWhenAllBrowsersClose())
+      << "Test timed out unexpectedly; should be complete";
+
+  // Keep |this| alive until after the method completes.
+  CefRefPtr<TestHandler> self(this);
+
+  // Close any remaining browsers.
   DestroyTest();
+
+  // Reset signal completion count.
+  if (signal_completion_count_ > 0) {
+    signal_completion_count_ = 0;
+    MaybeTestComplete();
+  }
 }
 
 void TestHandler::CreateBrowser(const CefString& url,
                                 CefRefPtr<CefRequestContext> request_context,
                                 CefRefPtr<CefDictionaryValue> extra_info) {
-#if defined(USE_AURA)
-  const bool use_views = CefCommandLine::GetGlobalCommandLine()->HasSwitch(
-      client::switches::kUseViews);
-  if (use_views && !CefCurrentlyOn(TID_UI)) {
-    // Views classes must be accessed on the UI thread.
-    CefPostTask(TID_UI, base::Bind(&TestHandler::CreateBrowser, this, url,
-                                   request_context, extra_info));
+  if (!CefCurrentlyOn(TID_UI)) {
+    CefPostTask(TID_UI, base::BindOnce(&TestHandler::CreateBrowser, this, url,
+                                       request_context, extra_info));
     return;
   }
-#endif  // defined(USE_AURA)
 
   CefWindowInfo windowInfo;
   CefBrowserSettings settings;
-  PopulateBrowserSettings(&settings);
 
-#if defined(USE_AURA)
-  if (use_views) {
+  if (use_views_) {
     // Create the BrowserView.
     CefRefPtr<CefBrowserView> browser_view = CefBrowserView::CreateBrowserView(
         this, url, settings, extra_info, request_context,
-        new TestBrowserViewDelegate());
+        new TestBrowserViewDelegate(this));
 
     // Create the Window. It will show itself after creation.
-    TestWindowDelegate::CreateBrowserWindow(browser_view, std::string());
-  } else
-#endif  // defined(USE_AURA)
-  {
+    TestWindowDelegate::CreateBrowserWindow(this, browser_view, std::string());
+  } else {
 #if defined(OS_WIN)
     windowInfo.SetAsPopup(nullptr, "CefUnitTest");
     windowInfo.style |= WS_VISIBLE;
@@ -398,19 +562,15 @@
 // static
 void TestHandler::CloseBrowser(CefRefPtr<CefBrowser> browser,
                                bool force_close) {
+#if VERBOSE_DEBUGGING
+  LOG(INFO) << "TestHandler: " << browser->GetIdentifier()
+            << ": CloseBrowser force_close=" << force_close;
+#endif
   browser->GetHost()->CloseBrowser(force_close);
 }
 
 void TestHandler::AddResource(const std::string& url,
                               const std::string& content,
-                              const std::string& mime_type) {
-  ResourceContent::HeaderMap headerMap = ResourceContent::HeaderMap();
-  ResourceContent rc = ResourceContent(content, mime_type, headerMap);
-  AddResourceEx(url, rc);
-}
-
-void TestHandler::AddResource(const std::string& url,
-                              const std::string& content,
                               const std::string& mime_type,
                               const ResourceContent::HeaderMap& header_map) {
   ResourceContent rc = ResourceContent(content, mime_type, header_map);
@@ -420,23 +580,24 @@
 void TestHandler::AddResourceEx(const std::string& url,
                                 const ResourceContent& content) {
   if (!CefCurrentlyOn(TID_IO)) {
-    CefPostTask(TID_IO,
-                base::Bind(&TestHandler::AddResourceEx, this, url, content));
+    CefPostTask(TID_IO, base::BindOnce(&TestHandler::AddResourceEx, this, url,
+                                       content));
     return;
   }
 
   // Ignore the query component, if any.
   std::string urlStr = url;
   size_t idx = urlStr.find('?');
-  if (idx > 0)
+  if (idx > 0) {
     urlStr = urlStr.substr(0, idx);
+  }
 
   resource_map_.insert(std::make_pair(urlStr, content));
 }
 
 void TestHandler::ClearResources() {
   if (!CefCurrentlyOn(TID_IO)) {
-    CefPostTask(TID_IO, base::Bind(&TestHandler::ClearResources, this));
+    CefPostTask(TID_IO, base::BindOnce(&TestHandler::ClearResources, this));
     return;
   }
 
@@ -445,8 +606,8 @@
 
 void TestHandler::SetTestTimeout(int timeout_ms, bool treat_as_error) {
   if (!CefCurrentlyOn(TID_UI)) {
-    CefPostTask(TID_UI, base::Bind(&TestHandler::SetTestTimeout, this,
-                                   timeout_ms, treat_as_error));
+    CefPostTask(TID_UI, base::BindOnce(&TestHandler::SetTestTimeout, this,
+                                       timeout_ms, treat_as_error));
     return;
   }
 
@@ -455,26 +616,102 @@
     return;
   }
 
-  if (treat_as_error && CefCommandLine::GetGlobalCommandLine()->HasSwitch(
-                            "disable-test-timeout")) {
+  const auto timeout = GetConfiguredTestTimeout(timeout_ms);
+  if (treat_as_error && !timeout) {
     return;
   }
 
   // Use a weak reference to |this| via UIThreadHelper so that the TestHandler
   // can be destroyed before the timeout expires.
   GetUIThreadHelper()->PostDelayedTask(
-      base::Bind(&TestHandler::OnTestTimeout, base::Unretained(this),
-                 timeout_ms, treat_as_error),
-      timeout_ms);
+      base::BindOnce(&TestHandler::OnTestTimeout, base::Unretained(this),
+                     *timeout, treat_as_error),
+      *timeout);
 }
 
-void TestHandler::TestComplete() {
+void TestHandler::SetUseViews(bool use_views) {
   if (!CefCurrentlyOn(TID_UI)) {
-    CefPostTask(TID_UI, base::Bind(&TestHandler::TestComplete, this));
+    CefPostTask(TID_UI,
+                base::BindOnce(&TestHandler::SetUseViews, this, use_views));
     return;
   }
 
-  EXPECT_TRUE(browser_map_.empty());
+  use_views_ = use_views;
+}
+
+void TestHandler::SetSignalTestCompletionCount(size_t count) {
+#if VERBOSE_DEBUGGING
+  LOG(INFO) << debug_string_prefix_
+            << "SetSignalTestCompletionCount count=" << count;
+#endif
+  signal_completion_count_ = count;
+}
+
+void TestHandler::SignalTestCompletion() {
+  if (!CefCurrentlyOn(TID_UI)) {
+    CefPostTask(TID_UI,
+                base::BindOnce(&TestHandler::SignalTestCompletion, this));
+    return;
+  }
+
+  if (test_timeout_called_) {
+    // Ignore any signals that arrive after test timeout.
+    return;
+  }
+
+  CHECK_GT(signal_completion_count_, 0U);
+  signal_completion_count_--;
+
+#if VERBOSE_DEBUGGING
+  LOG(INFO) << debug_string_prefix_
+            << "SignalTestComplete remaining=" << signal_completion_count_;
+#endif
+
+  if (signal_completion_count_ == 0) {
+    // May result in |this| being deleted.
+    MaybeTestComplete();
+  }
+}
+
+bool TestHandler::AllowTestCompletionWhenAllBrowsersClose() const {
+  EXPECT_UI_THREAD();
+  return signal_completion_count_ == 0U;
+}
+
+bool TestHandler::AllBrowsersClosed() const {
+  EXPECT_UI_THREAD();
+  return browser_status_map_.empty();
+}
+
+void TestHandler::MaybeTestComplete() {
+  EXPECT_UI_THREAD();
+
+  const bool all_browsers_closed = AllBrowsersClosed();
+  const bool allow_test_completion = AllowTestCompletionWhenAllBrowsersClose();
+
+#if VERBOSE_DEBUGGING
+  LOG(INFO) << debug_string_prefix_
+            << "MaybeTestComplete all_browsers_closed=" << all_browsers_closed
+            << " allow_test_completion=" << allow_test_completion;
+#endif
+
+  if (all_browsers_closed && allow_test_completion) {
+    TestComplete();
+  }
+}
+
+void TestHandler::TestComplete() {
+  EXPECT_UI_THREAD();
+  EXPECT_TRUE(AllBrowsersClosed());
+  EXPECT_TRUE(AllowTestCompletionWhenAllBrowsersClose());
+
+#if VERBOSE_DEBUGGING
+  LOG(INFO) << debug_string_prefix_ << "TestComplete";
+#endif
+
+  // Cancel any pending tasks posted via UIThreadHelper.
+  ui_thread_helper_.reset();
+
   completion_state_->TestComplete();
 }
 
@@ -482,8 +719,9 @@
   EXPECT_UI_THREAD();
   CHECK(!destroy_test_called_);
 
-  if (!ui_thread_helper_.get())
+  if (!ui_thread_helper_.get()) {
     ui_thread_helper_.reset(new UIThreadHelper());
+  }
   return ui_thread_helper_.get();
 }
 
diff --git a/src/tests/ceftests/test_handler.h b/src/tests/ceftests/test_handler.h
index 0c7c514..ef6910a 100644
--- a/src/tests/ceftests/test_handler.h
+++ b/src/tests/ceftests/test_handler.h
@@ -2,37 +2,27 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#ifndef CEF_TESTS_UNITTESTS_TEST_HANDLER_H_
-#define CEF_TESTS_UNITTESTS_TEST_HANDLER_H_
+#ifndef CEF_TESTS_CEFTESTS_TEST_HANDLER_H_
+#define CEF_TESTS_CEFTESTS_TEST_HANDLER_H_
 #pragma once
 
+#include <atomic>
 #include <list>
 #include <map>
+#include <memory>
 #include <string>
 #include <utility>
 
-#include "include/base/cef_bind.h"
-#include "include/base/cef_scoped_ptr.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_browser.h"
 #include "include/cef_client.h"
 #include "include/cef_frame.h"
 #include "include/cef_task.h"
 #include "include/cef_waitable_event.h"
 #include "tests/ceftests/thread_helper.h"
+#include "tests/ceftests/track_callback.h"
 #include "tests/gtest/include/gtest/gtest.h"
 
-class TrackCallback {
- public:
-  TrackCallback() : gotit_(false) {}
-  void yes() { gotit_ = true; }
-  bool isSet() { return gotit_; }
-  void reset() { gotit_ = false; }
-  operator bool() const { return gotit_; }
-
- protected:
-  bool gotit_;
-};
-
 class ResourceContent {
  public:
   typedef std::multimap<std::string, std::string> HeaderMap;
@@ -127,12 +117,13 @@
     // be executed only if TestHandler::DestroyTest has not yet been called.
     // For example:
     //    GetUIThreadHelper()->PostTask(
-    //        base::Bind(&TestHandler::DoSomething, base::Unretained(this)));
-    void PostTask(const base::Closure& task);
-    void PostDelayedTask(const base::Closure& task, int delay_ms);
+    //        base::BindOnce(&TestHandler::DoSomething,
+    //        base::Unretained(this)));
+    void PostTask(base::OnceClosure task);
+    void PostDelayedTask(base::OnceClosure task, int delay_ms);
 
    private:
-    void TaskHelper(const base::Closure& task);
+    void TaskHelper(base::OnceClosure task);
 
     // Must be the last member.
     base::WeakPtrFactory<UIThreadHelper> weak_ptr_factory_;
@@ -192,8 +183,8 @@
                                  TerminationStatus status) override;
 
   // These methods should only be used if at most one non-popup browser exists.
-  CefRefPtr<CefBrowser> GetBrowser();
-  int GetBrowserId();
+  CefRefPtr<CefBrowser> GetBrowser() const;
+  int GetBrowserId() const;
 
   // Copies the map of all the currently existing browsers into |map|. Must be
   // called on the UI thread.
@@ -216,28 +207,30 @@
     destroy_test_expected_ = expected;
   }
 
-  // Returns true if a browser currently exists.
-  static bool HasBrowser() { return browser_count_ > 0; }
+  // Called from TestWindowDelegate when Views is enabled.
+  void OnWindowCreated(int browser_id);
+  void OnWindowDestroyed(int browser_id);
+
+  // Returns true if a TestHandler currently exists.
+  static bool HasTestHandler() {
+    return test_handler_count_.load(std::memory_order_relaxed) > 0U;
+  }
+
+  std::string debug_string_prefix() const { return debug_string_prefix_; }
 
  protected:
   // Indicate that test setup is complete. Only used in combination with a
   // Collection.
   virtual void SetupComplete();
 
-  // Close any existing non-popup browsers. Test completion will be signaled
-  // once all the browsers have closed if
-  // |signal_completion_when_all_browsers_close_| is true (default value).
-  // If no browsers exist then this method will do nothing and
-  // TestComplete() must be called manually.
+  // Close any remaining browsers. This may result in a call to TestComplete(),
+  // depending on the configuration of SetSignalCompletionCount().
   virtual void DestroyTest();
 
   // Called on the UI thread if the test times out as a result of calling
   // SetTestTimeout(). Calls DestroyTest() by default.
   virtual void OnTestTimeout(int timeout_ms, bool treat_as_error);
 
-  // Called from CreateBrowser() to optionally set per-browser settings.
-  virtual void PopulateBrowserSettings(CefBrowserSettings* settings) {}
-
   void CreateBrowser(const CefString& url,
                      CefRefPtr<CefRequestContext> request_context = nullptr,
                      CefRefPtr<CefDictionaryValue> extra_info = nullptr);
@@ -245,49 +238,95 @@
 
   void AddResource(const std::string& url,
                    const std::string& content,
-                   const std::string& mime_type);
-
-  void AddResource(const std::string& url,
-                   const std::string& content,
                    const std::string& mime_type,
-                   const ResourceContent::HeaderMap& header_map);
+                   const ResourceContent::HeaderMap& header_map = {});
 
   void AddResourceEx(const std::string& url, const ResourceContent& content);
 
   void ClearResources();
 
-  void SetSignalCompletionWhenAllBrowsersClose(bool val) {
-    signal_completion_when_all_browsers_close_ = val;
-  }
-  bool SignalCompletionWhenAllBrowsersClose() const {
-    return signal_completion_when_all_browsers_close_;
-  }
+  // Specify the number of times that SignalTestCompletion() needs to be
+  // explicitly called for test completion. Must be configured during test
+  // initialization before any browsers are created.
+  // - If the test creates browsers and does not explicitly call
+  //   SignalTestCompletion() then the default value (0) can be used.
+  // - If the test creates browsers and explicitly calls SignalTestCompletion()
+  //   then set a value >= 1.
+  // - If the test does not create browsers then it must explicitly call
+  //   SignalTestCompletion() and set a value >= 1.
+  void SetSignalTestCompletionCount(size_t count);
+
+  // Explicitly signal test completion a single time. Used in combination with
+  // SetSignalTestCompletionCount(). Results in a call to TestComplete() if
+  // all browsers have closed and this method has been called the expected
+  // number of times.
+  void SignalTestCompletion();
+
+  // Returns true if SignalTestCompletion() has been called the necessary
+  // number of times (may be 0), in which case TestComplete() will be called
+  // automatically when all browsers have closed. Must be called on the
+  // UI thread.
+  bool AllowTestCompletionWhenAllBrowsersClose() const;
+
+  // Returns true if all browsers have closed. Must be called on the UI
+  // thread.
+  bool AllBrowsersClosed() const;
 
   // Call OnTestTimeout() after the specified amount of time.
   void SetTestTimeout(int timeout_ms = 5000, bool treat_as_error = true);
 
-  // Signal that the test is complete. This will be called automatically when
-  // all existing non-popup browsers are closed if
-  // |signal_completion_when_all_browsers_close_| is true (default value). It
-  // is an error to call this method before all browsers have closed.
-  void TestComplete();
+  // Call prior to CreateBrowser() to configure whether browsers will be created
+  // as Views-hosted. Defaults to false unless the `--use-views` command-line
+  // flag is specified.
+  void SetUseViews(bool use_views);
 
   // Returns the single UIThreadHelper instance, creating it if necessary. Must
   // be called on the UI thread.
   UIThreadHelper* GetUIThreadHelper();
 
  private:
+  void MaybeTestComplete();
+
+  // Complete the test. It is an error to call this method before all browsers
+  // have closed.
+  void TestComplete();
+
+  enum NotifyType {
+    NT_BROWSER,
+    NT_WINDOW,
+  };
+  void OnCreated(int browser_id, NotifyType type, bool views_hosted);
+  void OnClosed(int browser_id, NotifyType type);
+
+  std::string MakeDebugStringPrefix() const;
+  const std::string debug_string_prefix_;
+
   // Used to notify when the test is complete. Can be accessed on any thread.
   CompletionState* completion_state_;
   bool completion_state_owned_;
 
-  // Map browser ID to browser object for non-popup browsers. Only accessed on
-  // the UI thread.
+  bool use_views_;
+
+  // Map of browser ID to browser object. Only accessed on the UI thread.
   BrowserMap browser_map_;
 
+  struct NotifyStatus {
+    // True if this particular browser window is Views-hosted (see SetUseViews).
+    // Some tests create popup or DevTools windows with default handling (e.g.
+    // not Views-hosted).
+    bool views_hosted;
+
+    // Keyed by NotifyType.
+    TrackCallback got_created[2];
+    TrackCallback got_closed[2];
+  };
+
+  // Map of browser ID to current status. Only accessed on the UI thread.
+  std::map<int, NotifyStatus> browser_status_map_;
+
   // Values for the first created browser. Modified on the UI thread but can be
   // accessed on any thread.
-  int first_browser_id_;
+  int first_browser_id_ = 0;
   CefRefPtr<CefBrowser> first_browser_;
 
   // Map of resources that can be automatically loaded. Only accessed on the
@@ -295,19 +334,22 @@
   typedef std::map<std::string, ResourceContent> ResourceMap;
   ResourceMap resource_map_;
 
-  // If true test completion will be signaled when all browsers have closed.
-  bool signal_completion_when_all_browsers_close_;
+  // Number of times that SignalTestCompletion() must be called.
+  size_t signal_completion_count_ = 0U;
 
   CefRefPtr<CefWaitableEvent> destroy_event_;
 
+  // Tracks whether OnTestTimeout() has been called.
+  bool test_timeout_called_ = false;
+
   // Tracks whether DestroyTest() is expected or has been called.
-  bool destroy_test_expected_;
-  bool destroy_test_called_;
+  bool destroy_test_expected_ = true;
+  bool destroy_test_called_ = false;
 
-  scoped_ptr<UIThreadHelper> ui_thread_helper_;
+  std::unique_ptr<UIThreadHelper> ui_thread_helper_;
 
-  // Used to track the number of currently existing browser windows.
-  static int browser_count_;
+  // Used to track the number of currently existing TestHandlers.
+  static std::atomic<size_t> test_handler_count_;
 
   DISALLOW_COPY_AND_ASSIGN(TestHandler);
 };
@@ -363,4 +405,4 @@
   GTEST_TEST_BOOLEAN_(!(__result), #condition, true, false, \
                       GTEST_NONFATAL_FAILURE_)
 
-#endif  // CEF_TESTS_UNITTESTS_TEST_HANDLER_H_
+#endif  // CEF_TESTS_CEFTESTS_TEST_HANDLER_H_
diff --git a/src/tests/ceftests/test_request.cc b/src/tests/ceftests/test_request.cc
new file mode 100644
index 0000000..344fa58
--- /dev/null
+++ b/src/tests/ceftests/test_request.cc
@@ -0,0 +1,206 @@
+// Copyright (c) 2020 The Chromium Embedded Framework 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 "tests/ceftests/test_request.h"
+
+#include <algorithm>
+#include <memory>
+
+#include "include/cef_stream.h"
+#include "include/cef_urlrequest.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "include/wrapper/cef_helpers.h"
+#include "include/wrapper/cef_stream_resource_handler.h"
+
+namespace test_request {
+
+namespace {
+
+// Implementation of CefURLRequestClient that stores response information.
+class RequestClient : public CefURLRequestClient, public State {
+ public:
+  RequestClient(const bool has_credentials,
+                const std::string& username,
+                const std::string& password,
+                RequestDoneCallback done_callback)
+      : has_credentials_(has_credentials),
+        username_(username),
+        password_(password),
+        done_callback_(std::move(done_callback)) {
+    DCHECK(!done_callback_.is_null());
+  }
+
+  void OnUploadProgress(CefRefPtr<CefURLRequest> request,
+                        int64_t current,
+                        int64_t total) override {
+    upload_progress_ct_++;
+    upload_total_ = total;
+  }
+
+  void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
+                          int64_t current,
+                          int64_t total) override {
+    response_ = request->GetResponse();
+    DCHECK(response_.get());
+    DCHECK(response_->IsReadOnly());
+    download_progress_ct_++;
+    download_total_ = total;
+  }
+
+  void OnDownloadData(CefRefPtr<CefURLRequest> request,
+                      const void* data,
+                      size_t data_length) override {
+    response_ = request->GetResponse();
+    DCHECK(response_.get());
+    DCHECK(response_->IsReadOnly());
+    download_data_ct_++;
+    download_data_ += std::string(static_cast<const char*>(data), data_length);
+  }
+
+  bool GetAuthCredentials(bool isProxy,
+                          const CefString& host,
+                          int port,
+                          const CefString& realm,
+                          const CefString& scheme,
+                          CefRefPtr<CefAuthCallback> callback) override {
+    auth_credentials_ct_++;
+    if (has_credentials_) {
+      callback->Continue(username_, password_);
+      return true;
+    }
+    return false;
+  }
+
+  void OnRequestComplete(CefRefPtr<CefURLRequest> request) override {
+    request_complete_ct_++;
+
+    request_ = request->GetRequest();
+    DCHECK(request_->IsReadOnly());
+    status_ = request->GetRequestStatus();
+    error_code_ = request->GetRequestError();
+    response_was_cached_ = request->ResponseWasCached();
+    response_ = request->GetResponse();
+    if (response_) {
+      DCHECK(response_->IsReadOnly());
+    }
+
+    std::move(done_callback_).Run(*this);
+  }
+
+ private:
+  const bool has_credentials_;
+  const std::string username_;
+  const std::string password_;
+  RequestDoneCallback done_callback_;
+
+  IMPLEMENT_REFCOUNTING(RequestClient);
+  DISALLOW_COPY_AND_ASSIGN(RequestClient);
+};
+
+// Implementation that collects all cookies, and optionally deletes them.
+class CookieVisitor : public CefCookieVisitor {
+ public:
+  CookieVisitor(bool deleteCookies, CookieDoneCallback callback)
+      : delete_cookies_(deleteCookies), callback_(std::move(callback)) {
+    DCHECK(!callback_.is_null());
+  }
+
+  ~CookieVisitor() override {
+    CEF_REQUIRE_UI_THREAD();
+    std::move(callback_).Run(cookies_);
+  }
+
+  bool Visit(const CefCookie& cookie,
+             int count,
+             int total,
+             bool& deleteCookie) override {
+    CEF_REQUIRE_UI_THREAD();
+    cookies_.push_back(cookie);
+    if (delete_cookies_) {
+      deleteCookie = true;
+    }
+    return true;
+  }
+
+ private:
+  CookieVector cookies_;
+  bool delete_cookies_;
+  CookieDoneCallback callback_;
+
+  IMPLEMENT_REFCOUNTING(CookieVisitor);
+  DISALLOW_COPY_AND_ASSIGN(CookieVisitor);
+};
+
+}  // namespace
+
+void Send(const SendConfig& config, RequestDoneCallback callback) {
+  DCHECK(config.request_);
+  CefRefPtr<RequestClient> client =
+      new RequestClient(config.has_credentials_, config.username_,
+                        config.password_, std::move(callback));
+  if (config.frame_) {
+    config.frame_->CreateURLRequest(config.request_, client.get());
+  } else {
+    CefURLRequest::Create(config.request_, client.get(),
+                          config.request_context_);
+  }
+}
+
+std::string GetPathURL(const std::string& url) {
+  const size_t index1 = url.find('?');
+  const size_t index2 = url.find('#');
+  size_t index = std::string::npos;
+  if (index1 != std::string::npos && index2 != std::string::npos) {
+    index = std::min(index1, index2);
+  } else if (index1 != std::string::npos) {
+    index = index1;
+  } else if (index2 != std::string::npos) {
+    index = index2;
+  }
+  if (index != std::string::npos) {
+    return url.substr(0, index);
+  }
+  return url;
+}
+
+CefRefPtr<CefResourceHandler> CreateResourceHandler(
+    CefRefPtr<CefResponse> response,
+    const std::string& response_data) {
+  CefRefPtr<CefStreamReader> stream;
+  if (!response_data.empty()) {
+    stream = CefStreamReader::CreateForData(
+        static_cast<void*>(const_cast<char*>(response_data.c_str())),
+        response_data.length());
+  }
+
+  CefResponse::HeaderMap headerMap;
+  response->GetHeaderMap(headerMap);
+
+  return new CefStreamResourceHandler(
+      response->GetStatus(), response->GetStatusText(), response->GetMimeType(),
+      headerMap, stream);
+}
+
+void GetAllCookies(CefRefPtr<CefCookieManager> manager,
+                   bool deleteCookies,
+                   CookieDoneCallback callback) {
+  bool result = manager->VisitAllCookies(
+      new CookieVisitor(deleteCookies, std::move(callback)));
+  DCHECK(result);
+}
+
+// Retrieves URL cookies from |manager| and executes |callback| upon completion.
+// If |deleteCookies| is true the cookies will also be deleted.
+void GetUrlCookies(CefRefPtr<CefCookieManager> manager,
+                   const CefString& url,
+                   bool includeHttpOnly,
+                   bool deleteCookies,
+                   CookieDoneCallback callback) {
+  bool result = manager->VisitUrlCookies(
+      url, includeHttpOnly,
+      new CookieVisitor(deleteCookies, std::move(callback)));
+  DCHECK(result);
+}
+
+}  // namespace test_request
diff --git a/src/tests/ceftests/test_request.h b/src/tests/ceftests/test_request.h
new file mode 100644
index 0000000..904a00d
--- /dev/null
+++ b/src/tests/ceftests/test_request.h
@@ -0,0 +1,97 @@
+// Copyright (c) 2020 The Chromium Embedded Framework 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 CEF_TESTS_CEFTESTS_TEST_REQUEST_H_
+#define CEF_TESTS_CEFTESTS_TEST_REQUEST_H_
+#pragma once
+
+#include <string>
+
+#include "include/base/cef_callback.h"
+#include "include/cef_cookie.h"
+#include "include/cef_frame.h"
+#include "include/cef_request.h"
+#include "include/cef_request_context.h"
+#include "include/cef_resource_handler.h"
+#include "include/cef_response.h"
+
+namespace test_request {
+
+// Stores all state passed to CefURLRequestClient.
+struct State {
+ public:
+  // Number of times each callback is executed.
+  int upload_progress_ct_ = 0;
+  int download_progress_ct_ = 0;
+  int download_data_ct_ = 0;
+  int auth_credentials_ct_ = 0;
+  int request_complete_ct_ = 0;
+
+  // From OnUploadProgress.
+  int64_t upload_total_ = 0;
+
+  // From OnDownloadProgress.
+  int64_t download_total_ = 0;
+
+  // From OnDownloadData.
+  std::string download_data_;
+
+  // From OnRequestComplete.
+  CefRefPtr<CefRequest> request_;
+  cef_urlrequest_status_t status_ = UR_UNKNOWN;
+  cef_errorcode_t error_code_ = ERR_NONE;
+  CefRefPtr<CefResponse> response_;
+  bool response_was_cached_ = false;
+};
+
+using RequestDoneCallback = base::OnceCallback<void(const State& state)>;
+
+struct SendConfig {
+  // Send using |frame_| or |request_context_| if non-nullptr.
+  // Sends using the global request context if both are nullptr.
+  CefRefPtr<CefFrame> frame_;
+  CefRefPtr<CefRequestContext> request_context_;
+
+  // The request to send.
+  CefRefPtr<CefRequest> request_;
+
+  // Returned via GetAuthCredentials if |has_credentials_| is true.
+  bool has_credentials_ = false;
+  std::string username_;
+  std::string password_;
+};
+
+// Send a request. |callback| will be executed on the calling thread after the
+// request completes.
+void Send(const SendConfig& config, RequestDoneCallback callback);
+
+// Removes query and/or fragment components from |url|.
+std::string GetPathURL(const std::string& url);
+
+// Creates a new resource handler that returns the specified response.
+CefRefPtr<CefResourceHandler> CreateResourceHandler(
+    CefRefPtr<CefResponse> response,
+    const std::string& response_data);
+
+using CookieVector = std::vector<CefCookie>;
+using CookieDoneCallback =
+    base::OnceCallback<void(const CookieVector& cookies)>;
+
+// Retrieves all cookies from |manager| and executes |callback| upon completion.
+// If |deleteCookies| is true the cookies will also be deleted.
+void GetAllCookies(CefRefPtr<CefCookieManager> manager,
+                   bool deleteCookies,
+                   CookieDoneCallback callback);
+
+// Retrieves URL cookies from |manager| and executes |callback| upon completion.
+// If |deleteCookies| is true the cookies will also be deleted.
+void GetUrlCookies(CefRefPtr<CefCookieManager> manager,
+                   const CefString& url,
+                   bool includeHttpOnly,
+                   bool deleteCookies,
+                   CookieDoneCallback callback);
+
+}  // namespace test_request
+
+#endif  // CEF_TESTS_CEFTESTS_TEST_REQUEST_H_
diff --git a/src/tests/ceftests/test_server.cc b/src/tests/ceftests/test_server.cc
new file mode 100644
index 0000000..f92d0fc
--- /dev/null
+++ b/src/tests/ceftests/test_server.cc
@@ -0,0 +1,58 @@
+// Copyright (c) 2020 The Chromium Embedded Framework 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 "tests/ceftests/test_server.h"
+
+#include "tests/ceftests/test_server_manager.h"
+
+#include <vector>
+
+namespace test_server {
+
+// Must use a different port than server_unittest.cc.
+const char kHttpServerAddress[] = "127.0.0.1";
+const uint16_t kHttpServerPort = 8098;
+
+const char kIncompleteDoNotSendData[] = "DO NOT SEND";
+
+CefRefPtr<CefResponse> Create404Response() {
+  auto response = CefResponse::Create();
+  response->SetStatus(404);
+  response->SetMimeType("text/html");
+  return response;
+}
+
+void Stop(base::OnceClosure callback) {
+  // Stop both HTTPS and HTTP servers in a chain.
+  Manager::Stop(base::BindOnce(
+                    [](base::OnceClosure callback) {
+                      Manager::Stop(std::move(callback),
+                                    /*https_server=*/false);
+                    },
+                    std::move(callback)),
+                /*https_server=*/true);
+}
+
+std::string GetOrigin(bool https_server) {
+  return Manager::GetOrigin(https_server);
+}
+
+std::string GetScheme(bool https_server) {
+  return https_server ? "https" : "http";
+}
+
+std::string GetHost(bool https_server, bool include_port) {
+  const auto& origin = GetOrigin(https_server);
+
+  const auto scheme_offset = origin.find("//");
+  const auto& origin_without_scheme = origin.substr(scheme_offset + 2);
+  if (include_port) {
+    return origin_without_scheme;
+  }
+
+  const auto port_offset = origin_without_scheme.find(':');
+  return origin_without_scheme.substr(0, port_offset);
+}
+
+}  // namespace test_server
diff --git a/src/tests/ceftests/test_server.h b/src/tests/ceftests/test_server.h
new file mode 100644
index 0000000..79d0c81
--- /dev/null
+++ b/src/tests/ceftests/test_server.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2020 The Chromium Embedded Framework 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 CEF_TESTS_CEFTESTS_TEST_SERVER_H_
+#define CEF_TESTS_CEFTESTS_TEST_SERVER_H_
+#pragma once
+
+#include <string>
+
+#include "include/base/cef_callback.h"
+#include "include/cef_registration.h"
+#include "include/cef_request.h"
+#include "include/cef_response.h"
+
+namespace test_server {
+
+// Use of these values is deprecated. Instead use GetOrigin/GetHost in the
+// browser process after server initialization.
+extern const char kHttpServerAddress[];
+extern const uint16_t kHttpServerPort;
+
+// Used with incomplete tests for data that should not be sent.
+extern const char kIncompleteDoNotSendData[];
+
+// Create a 404 response for passing to ResponseCallback.
+CefRefPtr<CefResponse> Create404Response();
+
+using ResponseCallback =
+    base::RepeatingCallback<void(CefRefPtr<CefResponse> response,
+                                 const std::string& response_data)>;
+
+// Stops all servers that are currently running and executes |callback| on the
+// UI thread. This method will be called by the test framework on shutdown.
+void Stop(base::OnceClosure callback);
+
+// Returns the origin for the currently running server (e.g.
+// "[http|https]://127.0.0.1:<port>").
+std::string GetOrigin(bool https_server);
+
+// Returns the scheme for the currently running server (e.g. "http" or "https").
+std::string GetScheme(bool https_server);
+
+// Returns the host for the currently running server (e.g.
+// "127.0.0.1[:<port>]").
+std::string GetHost(bool https_server, bool include_port);
+
+}  // namespace test_server
+
+#endif  // CEF_TESTS_CEFTESTS_TEST_SERVER_H_
diff --git a/src/tests/ceftests/test_server_manager.cc b/src/tests/ceftests/test_server_manager.cc
new file mode 100644
index 0000000..df6d96f
--- /dev/null
+++ b/src/tests/ceftests/test_server_manager.cc
@@ -0,0 +1,303 @@
+// Copyright (c) 2020 The Chromium Embedded Framework 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 "tests/ceftests/test_server_manager.h"
+
+#include "include/wrapper/cef_closure_task.h"
+#include "include/wrapper/cef_helpers.h"
+#include "tests/gtest/include/gtest/gtest.h"
+
+namespace test_server {
+
+namespace {
+
+Manager* g_http_manager = nullptr;
+Manager* g_https_manager = nullptr;
+
+}  // namespace
+
+// May be created on any thread but will be destroyed on the UI thread.
+class ObserverRegistration : public CefRegistration {
+ public:
+  ObserverRegistration(Observer* observer, bool https_server)
+      : observer_(observer), https_server_(https_server) {
+    EXPECT_TRUE(observer_);
+  }
+
+  ~ObserverRegistration() override {
+    CEF_REQUIRE_UI_THREAD();
+
+    if (auto manager = Manager::GetInstance(https_server_)) {
+      manager->RemoveObserver(
+          observer_,
+          base::BindOnce([](Observer* observer) { observer->OnUnregistered(); },
+                         base::Unretained(observer_)));
+    }
+  }
+
+  void Initialize() {
+    CEF_REQUIRE_UI_THREAD();
+    Manager::GetOrCreateInstance(https_server_)->AddObserver(observer_);
+    observer_->OnRegistered();
+  }
+
+  static void InitializeRegistration(
+      CefRefPtr<ObserverRegistration> registration,
+      Manager::DoneCallback callback) {
+    if (!CefCurrentlyOn(TID_UI)) {
+      CefPostTask(TID_UI, base::BindOnce(InitializeRegistration, registration,
+                                         std::move(callback)));
+      return;
+    }
+
+    registration->Initialize();
+    if (!callback.is_null()) {
+      std::move(callback).Run();
+    }
+  }
+
+ private:
+  Observer* const observer_;
+  const bool https_server_;
+
+  IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(ObserverRegistration);
+  DISALLOW_COPY_AND_ASSIGN(ObserverRegistration);
+};
+
+Manager::Manager(bool https_server) : https_server_(https_server) {
+  CEF_REQUIRE_UI_THREAD();
+
+  if (https_server) {
+    DCHECK(!g_https_manager);
+    g_https_manager = this;
+  } else {
+    DCHECK(!g_http_manager);
+    g_http_manager = this;
+  }
+}
+
+Manager::~Manager() {
+  CEF_REQUIRE_UI_THREAD();
+  EXPECT_TRUE(observer_list_.empty());
+  EXPECT_TRUE(start_callback_list_.empty());
+  EXPECT_TRUE(stop_callback_.is_null());
+
+  if (https_server_) {
+    g_https_manager = nullptr;
+  } else {
+    g_http_manager = nullptr;
+  }
+}
+
+// static
+Manager* Manager::GetInstance(bool https_server) {
+  return https_server ? g_https_manager : g_http_manager;
+}
+
+// static
+Manager* Manager::GetOrCreateInstance(bool https_server) {
+  if (auto manager = GetInstance(https_server)) {
+    return manager;
+  }
+
+  new Manager(https_server);
+  auto manager = GetInstance(https_server);
+  DCHECK(manager);
+  return manager;
+}
+
+// static
+void Manager::Start(StartDoneCallback callback, bool https_server) {
+  EXPECT_FALSE(callback.is_null());
+  if (!CefCurrentlyOn(TID_UI)) {
+    CefPostTask(TID_UI, base::BindOnce(Manager::Start, std::move(callback),
+                                       https_server));
+    return;
+  }
+
+  Manager::GetOrCreateInstance(https_server)->StartImpl(std::move(callback));
+}
+
+// static
+void Manager::Stop(DoneCallback callback, bool https_server) {
+  EXPECT_FALSE(callback.is_null());
+  if (!CefCurrentlyOn(TID_UI)) {
+    CefPostTask(TID_UI, base::BindOnce(Manager::Stop, std::move(callback),
+                                       https_server));
+    return;
+  }
+
+  if (auto manager = Manager::GetInstance(https_server)) {
+    manager->StopImpl(std::move(callback));
+  } else {
+    std::move(callback).Run();
+  }
+}
+
+// static
+CefRefPtr<CefRegistration> Manager::AddObserver(Observer* observer,
+                                                DoneCallback callback,
+                                                bool https_server) {
+  EXPECT_TRUE(observer);
+  CefRefPtr<ObserverRegistration> registration =
+      new ObserverRegistration(observer, https_server);
+  ObserverRegistration::InitializeRegistration(registration,
+                                               std::move(callback));
+  return registration.get();
+}
+
+// static
+CefRefPtr<CefRegistration> Manager::AddObserverAndStart(
+    Observer* observer,
+    StartDoneCallback callback,
+    bool https_server) {
+  return AddObserver(
+      observer,
+      base::BindOnce(Manager::Start, std::move(callback), https_server),
+      https_server);
+}
+
+// static
+std::string Manager::GetOrigin(bool https_server) {
+  if (auto manager = Manager::GetInstance(https_server)) {
+    return manager->origin_;
+  }
+  NOTREACHED();
+  return std::string();
+}
+
+void Manager::StartImpl(StartDoneCallback callback) {
+  CEF_REQUIRE_UI_THREAD();
+  EXPECT_FALSE(stopping_);
+
+  if (!origin_.empty()) {
+    // The server is already running.
+    std::move(callback).Run(origin_);
+    return;
+  }
+
+  // If tests run in parallel, and the server is starting, then there may be
+  // multiple pending callbacks.
+  start_callback_list_.push_back(std::move(callback));
+
+  // Only create the runner a single time.
+  if (!runner_) {
+    runner_ = Runner::Create(this, https_server_);
+    runner_->StartServer();
+  }
+}
+
+void Manager::StopImpl(DoneCallback callback) {
+  CEF_REQUIRE_UI_THREAD();
+  if (!runner_) {
+    // The server is not currently running.
+    std::move(callback).Run();
+    return;
+  }
+
+  // Stop will be called one time on test framework shutdown.
+  EXPECT_FALSE(stopping_);
+  stopping_ = true;
+
+  // Only 1 stop callback supported.
+  EXPECT_TRUE(stop_callback_.is_null());
+  stop_callback_ = std::move(callback);
+
+  runner_->ShutdownServer();
+}
+
+void Manager::AddObserver(Observer* observer) {
+  CEF_REQUIRE_UI_THREAD();
+  EXPECT_FALSE(stopping_);
+  observer_list_.push_back(observer);
+}
+
+void Manager::RemoveObserver(Observer* observer, DoneCallback callback) {
+  CEF_REQUIRE_UI_THREAD();
+  bool found = false;
+  ObserverList::iterator it = observer_list_.begin();
+  for (; it != observer_list_.end(); ++it) {
+    if (*it == observer) {
+      observer_list_.erase(it);
+      found = true;
+      break;
+    }
+  }
+  EXPECT_TRUE(found);
+
+  if (observer_list_.empty() && https_server_ && !stopping_) {
+    // Stop the HTTPS server when the last Observer is removed. We can't
+    // currently reuse the HTTPS server between tests due to
+    // https://crrev.com/dd2a57d753 causing cert registration issues.
+    StopImpl(std::move(callback));
+  } else {
+    std::move(callback).Run();
+  }
+}
+
+void Manager::OnServerCreated(const std::string& server_origin) {
+  CEF_REQUIRE_UI_THREAD();
+
+  EXPECT_TRUE(origin_.empty());
+  origin_ = server_origin;
+
+  for (auto& callback : start_callback_list_) {
+    std::move(callback).Run(origin_);
+  }
+  start_callback_list_.clear();
+}
+
+void Manager::OnServerDestroyed() {
+  CEF_REQUIRE_UI_THREAD();
+
+  origin_.clear();
+  runner_.reset();
+}
+
+// All server-related objects have been torn down.
+void Manager::OnServerHandlerDeleted() {
+  CEF_REQUIRE_UI_THREAD();
+
+  EXPECT_FALSE(stop_callback_.is_null());
+  std::move(stop_callback_).Run();
+
+  delete this;
+}
+
+void Manager::OnTestServerRequest(CefRefPtr<CefRequest> request,
+                                  const ResponseCallback& response_callback) {
+  CEF_REQUIRE_UI_THREAD();
+
+  // TODO(chrome-runtime): Debug why favicon requests don't always have the
+  // correct resource type.
+  const std::string& url = request->GetURL();
+  if (request->GetResourceType() == RT_FAVICON ||
+      url.find("/favicon.ico") != std::string::npos) {
+    // We don't currently handle favicon requests.
+    response_callback.Run(Create404Response(), std::string());
+    return;
+  }
+
+  EXPECT_FALSE(observer_list_.empty()) << url;
+
+  // Use a copy in case |observer_list_| is modified during iteration.
+  ObserverList list = observer_list_;
+
+  bool handled = false;
+
+  ObserverList::const_iterator it = list.begin();
+  for (; it != list.end(); ++it) {
+    if ((*it)->OnTestServerRequest(request, response_callback)) {
+      handled = true;
+      break;
+    }
+  }
+
+  if (!handled) {
+    LOG(WARNING) << "Unhandled request for: " << url;
+    response_callback.Run(Create404Response(), std::string());
+  }
+}
+
+}  // namespace test_server
diff --git a/src/tests/ceftests/test_server_manager.h b/src/tests/ceftests/test_server_manager.h
new file mode 100644
index 0000000..30d6c65
--- /dev/null
+++ b/src/tests/ceftests/test_server_manager.h
@@ -0,0 +1,101 @@
+// Copyright (c) 2020 The Chromium Embedded Framework 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 CEF_TESTS_CEFTESTS_TEST_SERVER_MANAGER_H_
+#define CEF_TESTS_CEFTESTS_TEST_SERVER_MANAGER_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "include/base/cef_callback.h"
+#include "include/cef_registration.h"
+#include "include/cef_request.h"
+#include "include/cef_response.h"
+#include "tests/ceftests/test_server_observer.h"
+#include "tests/ceftests/test_server_runner.h"
+
+namespace test_server {
+
+class ObserverRegistration;
+
+// Static methods are safe to call on any thread. Non-static methods are only
+// called on the UI thread. Deletes itself after the server is stopped. Use
+// ObserverHelper instead of calling these methods directly.
+class Manager : public Runner::Delegate {
+ public:
+  using StartDoneCallback =
+      base::OnceCallback<void(const std::string& server_origin)>;
+  using DoneCallback = base::OnceClosure;
+
+  // Starts the server if it is not currently running, and executes |callback|
+  // on the UI thread.
+  static void Start(StartDoneCallback callback, bool https_server);
+
+  // Stops the server if it is currently running, and executes |callback| on the
+  // UI thread. This method will be called by the test framework on shutdown.
+  static void Stop(DoneCallback callback, bool https_server);
+
+  // Add an observer for server callbacks. Remains registered until the returned
+  // CefRegistration object is destroyed. Registered observers will be executed
+  // in the order of registration until one returns true to indicate that it
+  // handled the callback. |callback| will be executed on the UI thread after
+  // registration is complete.
+  static CefRefPtr<CefRegistration> AddObserver(Observer* observer,
+                                                DoneCallback callback,
+                                                bool https_server);
+
+  // Combination of AddObserver() followed by Start().
+  static CefRefPtr<CefRegistration> AddObserverAndStart(
+      Observer* observer,
+      StartDoneCallback callback,
+      bool https_server);
+
+  // Returns the origin for an existing server.
+  static std::string GetOrigin(bool https_server);
+
+ private:
+  friend class ObserverRegistration;
+
+  explicit Manager(bool https_server);
+  ~Manager();
+
+  static Manager* GetInstance(bool https_server);
+  static Manager* GetOrCreateInstance(bool https_server);
+
+  void StartImpl(StartDoneCallback callback);
+  void StopImpl(DoneCallback callback);
+
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer, DoneCallback callback);
+
+  // Runner::Delegate methods:
+  void OnServerCreated(const std::string& server_origin) override;
+  void OnServerDestroyed() override;
+  void OnServerHandlerDeleted() override;
+  void OnTestServerRequest(CefRefPtr<CefRequest> request,
+                           const ResponseCallback& response_callback) override;
+
+ private:
+  const bool https_server_;
+
+  std::unique_ptr<Runner> runner_;
+  std::string origin_;
+
+  using StartDoneCallbackList = std::vector<StartDoneCallback>;
+  StartDoneCallbackList start_callback_list_;
+
+  DoneCallback stop_callback_;
+
+  using ObserverList = std::vector<Observer*>;
+  ObserverList observer_list_;
+
+  bool stopping_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(Manager);
+};
+
+}  // namespace test_server
+
+#endif  // CEF_TESTS_CEFTESTS_TEST_SERVER_MANAGER_H_
diff --git a/src/tests/ceftests/test_server_observer.cc b/src/tests/ceftests/test_server_observer.cc
new file mode 100644
index 0000000..9422e40
--- /dev/null
+++ b/src/tests/ceftests/test_server_observer.cc
@@ -0,0 +1,57 @@
+// Copyright (c) 2020 The Chromium Embedded Framework 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 "tests/ceftests/test_server.h"
+
+#include "include/wrapper/cef_helpers.h"
+#include "tests/ceftests/test_server_manager.h"
+#include "tests/gtest/include/gtest/gtest.h"
+
+#include <vector>
+
+namespace test_server {
+
+ObserverHelper::ObserverHelper() : weak_ptr_factory_(this) {
+  CEF_REQUIRE_UI_THREAD();
+}
+
+ObserverHelper::~ObserverHelper() {
+  EXPECT_TRUE(state_ == State::NONE);
+}
+
+void ObserverHelper::Initialize(bool https_server) {
+  CEF_REQUIRE_UI_THREAD();
+  EXPECT_TRUE(state_ == State::NONE);
+  state_ = State::INITIALIZING;
+  registration_ = Manager::AddObserverAndStart(
+      this,
+      base::BindOnce(&ObserverHelper::OnStartDone,
+                     weak_ptr_factory_.GetWeakPtr()),
+      https_server);
+}
+
+void ObserverHelper::Shutdown() {
+  CEF_REQUIRE_UI_THREAD();
+  EXPECT_TRUE(state_ == State::INITIALIZED);
+  state_ = State::SHUTTINGDOWN;
+  registration_ = nullptr;
+}
+
+void ObserverHelper::OnStartDone(const std::string& server_origin) {
+  EXPECT_TRUE(state_ == State::INITIALIZING);
+  state_ = State::INITIALIZED;
+  OnInitialized(server_origin);
+}
+
+void ObserverHelper::OnRegistered() {
+  EXPECT_TRUE(state_ == State::INITIALIZING);
+}
+
+void ObserverHelper::OnUnregistered() {
+  EXPECT_TRUE(state_ == State::SHUTTINGDOWN);
+  state_ = State::NONE;
+  OnShutdown();
+}
+
+}  // namespace test_server
diff --git a/src/tests/ceftests/test_server_observer.h b/src/tests/ceftests/test_server_observer.h
new file mode 100644
index 0000000..75d4070
--- /dev/null
+++ b/src/tests/ceftests/test_server_observer.h
@@ -0,0 +1,84 @@
+// Copyright (c) 2020 The Chromium Embedded Framework 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 CEF_TESTS_CEFTESTS_TEST_SERVER_OBSERVER_H_
+#define CEF_TESTS_CEFTESTS_TEST_SERVER_OBSERVER_H_
+#pragma once
+
+#include <string>
+
+#include "include/base/cef_callback.h"
+#include "include/base/cef_weak_ptr.h"
+#include "include/cef_registration.h"
+#include "include/cef_request.h"
+#include "tests/ceftests/test_server.h"
+
+namespace test_server {
+
+// Observer for server callbacks. Methods will be called on the UI thread.
+class Observer {
+ public:
+  using ResponseCallback = test_server::ResponseCallback;
+
+  // Called when this Observer is registered.
+  virtual void OnRegistered() = 0;
+
+  // Called when this Observer is unregistered.
+  virtual void OnUnregistered() = 0;
+
+  // Return true and execute |response_callback| either synchronously or
+  // asynchronously if the request was handled. Do not execute
+  // |response_callback| when returning false.
+  virtual bool OnTestServerRequest(
+      CefRefPtr<CefRequest> request,
+      const ResponseCallback& response_callback) = 0;
+
+ protected:
+  virtual ~Observer() = default;
+};
+
+// Helper for managing Observer registration and callbacks. Only used on the UI
+// thread.
+class ObserverHelper : public Observer {
+ public:
+  ObserverHelper();
+  ~ObserverHelper() override;
+
+  // Initialize the registration. If |https_server| is true an HTTPS server will
+  // be used, otherwise an HTTP server will be used. Results in a call to
+  // OnInitialized().
+  void Initialize(bool https_server);
+
+  // Shut down the registration. Results in a call to OnShutdown().
+  void Shutdown();
+
+  // Implement this method to start sending server requests after Initialize().
+  // |server_origin| will be value like "http://127.0.0.1:<port>".
+  virtual void OnInitialized(const std::string& server_origin) = 0;
+
+  // Implement this method to continue the test after Shutdown().
+  virtual void OnShutdown() = 0;
+
+ private:
+  void OnStartDone(const std::string& server_origin);
+  void OnRegistered() override;
+  void OnUnregistered() override;
+
+  CefRefPtr<CefRegistration> registration_;
+
+  enum class State {
+    NONE,
+    INITIALIZING,
+    INITIALIZED,
+    SHUTTINGDOWN,
+  } state_ = State::NONE;
+
+  base::WeakPtrFactory<ObserverHelper> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(ObserverHelper);
+};
+
+}  // namespace test_server
+
+#endif  // CEF_TESTS_CEFTESTS_TEST_SERVER_OBSERVER_H_
diff --git a/src/tests/ceftests/test_server_observer_unittest.cc b/src/tests/ceftests/test_server_observer_unittest.cc
new file mode 100644
index 0000000..dca9556
--- /dev/null
+++ b/src/tests/ceftests/test_server_observer_unittest.cc
@@ -0,0 +1,232 @@
+// Copyright (c) 2020 The Chromium Embedded Framework 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 <sstream>
+
+#include "include/cef_command_line.h"
+#include "include/cef_task.h"
+#include "include/cef_waitable_event.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "include/wrapper/cef_helpers.h"
+#include "tests/ceftests/test_request.h"
+#include "tests/ceftests/test_server_observer.h"
+#include "tests/ceftests/test_util.h"
+#include "tests/ceftests/track_callback.h"
+#include "tests/gtest/include/gtest/gtest.h"
+
+namespace {
+
+struct TestState {
+  bool https_server = false;
+
+  TrackCallback got_initialized_;
+  TrackCallback got_request_;
+  TrackCallback got_response_;
+  TrackCallback got_shutdown_;
+
+  bool ExpectAll() {
+    EXPECT_TRUE(got_initialized_);
+    EXPECT_TRUE(got_request_);
+    EXPECT_TRUE(got_response_);
+    EXPECT_TRUE(got_shutdown_);
+    return got_initialized_ && got_request_ && got_response_ && got_shutdown_;
+  }
+};
+
+const char kResponseData[] = "Test data";
+
+class TestServerObserver : public test_server::ObserverHelper {
+ public:
+  TestServerObserver(TestState* state,
+                     const std::string& path,
+                     base::OnceClosure done_callback)
+      : state_(state),
+        path_(path),
+        done_callback_(std::move(done_callback)),
+        weak_ptr_factory_(this) {
+    DCHECK(state);
+    DCHECK(!path.empty());
+    DCHECK(!done_callback_.is_null());
+    Initialize(state_->https_server);
+  }
+
+  ~TestServerObserver() override { std::move(done_callback_).Run(); }
+
+  void OnInitialized(const std::string& server_origin) override {
+    CEF_REQUIRE_UI_THREAD();
+    EXPECT_FALSE(state_->got_initialized_);
+    EXPECT_FALSE(state_->got_request_);
+    EXPECT_FALSE(state_->got_response_);
+    EXPECT_FALSE(state_->got_shutdown_);
+
+    state_->got_initialized_.yes();
+
+    url_ = server_origin + path_;
+
+    // Send a request to the server.
+    test_request::SendConfig config;
+    config.request_ = CefRequest::Create();
+    config.request_->SetURL(url_);
+    test_request::Send(config,
+                       base::BindOnce(&TestServerObserver::OnRequestResponse,
+                                      weak_ptr_factory_.GetWeakPtr()));
+  }
+
+  bool OnTestServerRequest(CefRefPtr<CefRequest> request,
+                           const ResponseCallback& response_callback) override {
+    CEF_REQUIRE_UI_THREAD();
+    const std::string& url = request->GetURL();
+    if (url != url_) {
+      return false;
+    }
+
+    EXPECT_TRUE(state_->got_initialized_);
+    EXPECT_FALSE(state_->got_request_);
+    EXPECT_FALSE(state_->got_response_);
+    EXPECT_FALSE(state_->got_shutdown_);
+
+    state_->got_request_.yes();
+
+    auto response = CefResponse::Create();
+    response->SetStatus(200);
+    response->SetMimeType("text/plain");
+
+    response_callback.Run(response, kResponseData);
+
+    // Stop propagating the callback.
+    return true;
+  }
+
+  void OnRequestResponse(const test_request::State& state) {
+    CEF_REQUIRE_UI_THREAD();
+    // Don't test for disconnected, which may race response.
+    EXPECT_TRUE(state_->got_initialized_);
+    EXPECT_TRUE(state_->got_request_);
+    EXPECT_FALSE(state_->got_response_);
+    EXPECT_FALSE(state_->got_shutdown_);
+
+    state_->got_response_.yes();
+
+    EXPECT_STREQ(url_.c_str(), state.request_->GetURL().ToString().c_str());
+    EXPECT_EQ(UR_SUCCESS, state.status_);
+    EXPECT_EQ(ERR_NONE, state.error_code_);
+    EXPECT_EQ(200, state.response_->GetStatus());
+    EXPECT_STREQ(kResponseData, state.download_data_.c_str());
+
+    // Trigger shutdown asynchronously.
+    CefPostTask(TID_UI, base::BindOnce(&TestServerObserver::Shutdown,
+                                       weak_ptr_factory_.GetWeakPtr()));
+  }
+
+  void OnShutdown() override {
+    CEF_REQUIRE_UI_THREAD();
+    EXPECT_TRUE(state_->got_initialized_);
+    EXPECT_TRUE(state_->got_request_);
+    EXPECT_TRUE(state_->got_response_);
+    EXPECT_FALSE(state_->got_shutdown_);
+
+    state_->got_shutdown_.yes();
+
+    // End the test.
+    delete this;
+  }
+
+ private:
+  TestState* const state_;
+  const std::string path_;
+  base::OnceClosure done_callback_;
+
+  std::string url_;
+
+  base::WeakPtrFactory<TestServerObserver> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestServerObserver);
+};
+
+void CreateObserverOnUIThread(TestState* state,
+                              const std::string& path,
+                              base::OnceClosure done_callback) {
+  if (!CefCurrentlyOn(TID_UI)) {
+    CefPostTask(TID_UI, base::BindOnce(CreateObserverOnUIThread,
+                                       base::Unretained(state), path,
+                                       std::move(done_callback)));
+    return;
+  }
+
+  new TestServerObserver(state, path, std::move(done_callback));
+}
+
+void SignalIfDone(CefRefPtr<CefWaitableEvent> event,
+                  size_t* count,
+                  size_t total) {
+  if (++(*count) == total) {
+    event->Signal();
+  }
+}
+
+void Wait(CefRefPtr<CefWaitableEvent> event) {
+  const auto timeout = GetConfiguredTestTimeout(/*timeout_ms=*/2000);
+  if (!timeout) {
+    event->Wait();
+  } else {
+    event->TimedWait(*timeout);
+  }
+}
+
+void RunHelperSingle(bool https_server) {
+  CefRefPtr<CefWaitableEvent> event =
+      CefWaitableEvent::CreateWaitableEvent(true, false);
+
+  TestState state;
+  state.https_server = https_server;
+  CreateObserverOnUIThread(&state, "/TestServerTest.ObserverHelperSingle",
+                           base::BindOnce(&CefWaitableEvent::Signal, event));
+
+  Wait(event);
+
+  EXPECT_TRUE(state.ExpectAll());
+}
+
+void RunHelperMultiple(bool https_server) {
+  CefRefPtr<CefWaitableEvent> event =
+      CefWaitableEvent::CreateWaitableEvent(true, false);
+
+  TestState states[3];
+  size_t count = 0;
+  const size_t size = std::size(states);
+
+  for (size_t i = 0; i < size; ++i) {
+    std::stringstream ss;
+    ss << "/TestServerTest.ObserverHelperMultiple" << i;
+    auto done_callback =
+        base::BindOnce(SignalIfDone, event, base::Unretained(&count), size);
+    states[i].https_server = https_server;
+    CreateObserverOnUIThread(&states[i], ss.str(), std::move(done_callback));
+  }
+
+  Wait(event);
+
+  EXPECT_EQ(size, count);
+  for (size_t i = 0; i < size; ++i) {
+    EXPECT_TRUE(states[i].ExpectAll()) << i;
+  }
+}
+
+}  // namespace
+
+TEST(TestServerObserverTest, HelperSingleHttp) {
+  RunHelperSingle(/*https_server=*/false);
+}
+
+TEST(TestServerObserverTest, HelperMultipleHttp) {
+  RunHelperMultiple(/*https_server=*/false);
+}
+
+TEST(TestServerObserverTest, HelperSingleHttps) {
+  RunHelperSingle(/*https_server=*/true);
+}
+
+TEST(TestServerObserverTest, HelperMultipleHttps) {
+  RunHelperMultiple(/*https_server=*/true);
+}
diff --git a/src/tests/ceftests/test_server_runner.cc b/src/tests/ceftests/test_server_runner.cc
new file mode 100644
index 0000000..1980bba
--- /dev/null
+++ b/src/tests/ceftests/test_server_runner.cc
@@ -0,0 +1,33 @@
+// Copyright (c) 2020 The Chromium Embedded Framework 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 "tests/ceftests/test_server_runner.h"
+
+#include "tests/shared/common/client_switches.h"
+
+#include "include/base/cef_logging.h"
+#include "include/cef_command_line.h"
+
+namespace test_server {
+
+Runner::Runner(Delegate* delegate) : delegate_(delegate) {
+  DCHECK(delegate_);
+}
+
+// static
+std::unique_ptr<Runner> Runner::Create(Runner::Delegate* delegate,
+                                       bool https_server) {
+  static bool use_test_http_server = [] {
+    auto command_line = CefCommandLine::GetGlobalCommandLine();
+    return command_line->HasSwitch(client::switches::kUseTestHttpServer);
+  }();
+
+  if (https_server || use_test_http_server) {
+    return CreateTest(delegate, https_server);
+  }
+
+  return CreateNormal(delegate);
+}
+
+}  // namespace test_server
diff --git a/src/tests/ceftests/test_server_runner.h b/src/tests/ceftests/test_server_runner.h
new file mode 100644
index 0000000..0454170
--- /dev/null
+++ b/src/tests/ceftests/test_server_runner.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2020 The Chromium Embedded Framework 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 CEF_TESTS_CEFTESTS_TEST_SERVER_RUNNER_H_
+#define CEF_TESTS_CEFTESTS_TEST_SERVER_RUNNER_H_
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "include/cef_request.h"
+#include "include/internal/cef_types.h"
+#include "tests/ceftests/test_server.h"
+
+namespace test_server {
+
+// Runs the server. All methods will be called on the UI thread.
+class Runner {
+ public:
+  // Interface implemented by the Manager that creates/owns the Runner.
+  class Delegate {
+   public:
+    // Server created notification.
+    virtual void OnServerCreated(const std::string& server_origin) = 0;
+
+    // Server destroyed notification. May delete the Runner.
+    virtual void OnServerDestroyed() = 0;
+
+    // Server handler deleted notification. May delete the Manager.
+    virtual void OnServerHandlerDeleted() = 0;
+
+    // Server request notification.
+    virtual void OnTestServerRequest(
+        CefRefPtr<CefRequest> request,
+        const ResponseCallback& response_callback) = 0;
+
+   protected:
+    virtual ~Delegate() = default;
+  };
+
+  // |delegate| will outlive this object.
+  explicit Runner(Delegate* delegate);
+  virtual ~Runner() = default;
+
+  // Called by the Manager to create the Runner.
+  static std::unique_ptr<Runner> Create(Delegate* delegate, bool https_server);
+
+  // Called by the Manager to create/destroy the server handler.
+  virtual void StartServer() = 0;
+  virtual void ShutdownServer() = 0;
+
+ private:
+  // Create a Runner based on CefServer.
+  static std::unique_ptr<Runner> CreateNormal(Delegate* delegate);
+
+  // Create a Runner based on CefTestServer.
+  static std::unique_ptr<Runner> CreateTest(Delegate* delegate,
+                                            bool https_server);
+
+ protected:
+  Delegate* const delegate_;
+
+  DISALLOW_COPY_AND_ASSIGN(Runner);
+};
+
+}  // namespace test_server
+
+#endif  // CEF_TESTS_CEFTESTS_TEST_SERVER_RUNNER_H_
diff --git a/src/tests/ceftests/test_server_runner_normal.cc b/src/tests/ceftests/test_server_runner_normal.cc
new file mode 100644
index 0000000..cfe40c2
--- /dev/null
+++ b/src/tests/ceftests/test_server_runner_normal.cc
@@ -0,0 +1,198 @@
+// Copyright (c) 2020 The Chromium Embedded Framework 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 "tests/ceftests/test_server_runner.h"
+
+#include "include/cef_server.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "include/wrapper/cef_helpers.h"
+#include "tests/gtest/include/gtest/gtest.h"
+
+namespace test_server {
+
+namespace {
+
+const int kHttpServerBacklog = 10;
+
+// Created on the UI thread and called on the dedicated server thread.
+class ServerHandler : public CefServerHandler {
+ public:
+  explicit ServerHandler(Runner::Delegate* delegate) : delegate_(delegate) {}
+
+  ~ServerHandler() override {
+    CEF_REQUIRE_UI_THREAD();
+    EXPECT_FALSE(server_);
+    delegate_->OnServerHandlerDeleted();
+  }
+
+  void Shutdown() { server_->Shutdown(); }
+
+  // CefServerHandler methods:
+  void OnServerCreated(CefRefPtr<CefServer> server) override {
+    EXPECT_TRUE(server->GetTaskRunner()->BelongsToCurrentThread());
+    server_ = server;
+    NotifyServerCreated("http://" + server->GetAddress().ToString());
+  }
+
+  void OnServerDestroyed(CefRefPtr<CefServer> server) override {
+    EXPECT_TRUE(server->GetTaskRunner()->BelongsToCurrentThread());
+    server_ = nullptr;
+    NotifyServerDestroyed();
+  }
+
+  void OnClientConnected(CefRefPtr<CefServer> server,
+                         int connection_id) override {
+    EXPECT_TRUE(server->GetTaskRunner()->BelongsToCurrentThread());
+    EXPECT_TRUE(server->HasConnection());
+    EXPECT_TRUE(server->IsValidConnection(connection_id));
+  }
+
+  void OnClientDisconnected(CefRefPtr<CefServer> server,
+                            int connection_id) override {
+    EXPECT_TRUE(server->GetTaskRunner()->BelongsToCurrentThread());
+    EXPECT_FALSE(server->IsValidConnection(connection_id));
+  }
+
+  void OnHttpRequest(CefRefPtr<CefServer> server,
+                     int connection_id,
+                     const CefString& client_address,
+                     CefRefPtr<CefRequest> request) override {
+    EXPECT_TRUE(server->GetTaskRunner()->BelongsToCurrentThread());
+    NotifyTestServerRequest(server, connection_id, client_address, request);
+  }
+
+  void OnWebSocketRequest(CefRefPtr<CefServer> server,
+                          int connection_id,
+                          const CefString& client_address,
+                          CefRefPtr<CefRequest> request,
+                          CefRefPtr<CefCallback> callback) override {}
+  void OnWebSocketConnected(CefRefPtr<CefServer> server,
+                            int connection_id) override {}
+  void OnWebSocketMessage(CefRefPtr<CefServer> server,
+                          int connection_id,
+                          const void* data,
+                          size_t data_size) override {}
+
+ private:
+  void NotifyServerCreated(const std::string& server_origin) {
+    if (!CefCurrentlyOn(TID_UI)) {
+      CefPostTask(TID_UI, base::BindOnce(&ServerHandler::NotifyServerCreated,
+                                         this, server_origin));
+      return;
+    }
+
+    delegate_->OnServerCreated(server_origin);
+  }
+
+  void NotifyServerDestroyed() {
+    if (!CefCurrentlyOn(TID_UI)) {
+      CefPostTask(TID_UI,
+                  base::BindOnce(&ServerHandler::NotifyServerDestroyed, this));
+      return;
+    }
+
+    delegate_->OnServerDestroyed();
+  }
+
+  void NotifyTestServerRequest(CefRefPtr<CefServer> server,
+                               int connection_id,
+                               const CefString& client_address,
+                               CefRefPtr<CefRequest> request) {
+    if (!CefCurrentlyOn(TID_UI)) {
+      CefPostTask(TID_UI, base::BindOnce(
+                              &ServerHandler::NotifyTestServerRequest, this,
+                              server, connection_id, client_address, request));
+      return;
+    }
+
+    auto response_callback = base::BindRepeating(&ServerHandler::SendResponse,
+                                                 server, connection_id);
+    delegate_->OnTestServerRequest(request, response_callback);
+  }
+
+  static void SendResponse(CefRefPtr<CefServer> server,
+                           int connection_id,
+                           CefRefPtr<CefResponse> response,
+                           const std::string& response_data) {
+    // Execute on the server thread because some methods require it.
+    CefRefPtr<CefTaskRunner> task_runner = server->GetTaskRunner();
+    if (!task_runner->BelongsToCurrentThread()) {
+      task_runner->PostTask(CefCreateClosureTask(
+          base::BindOnce(ServerHandler::SendResponse, server, connection_id,
+                         response, response_data)));
+      return;
+    }
+
+    if (!server->IsValidConnection(connection_id)) {
+      // This can occur if the connected browser has already closed.
+      return;
+    }
+
+    const int response_code = response->GetStatus();
+    if (response_code <= 0) {
+      // Intentionally not responding for incomplete request tests.
+      return;
+    }
+
+    const CefString& content_type = response->GetMimeType();
+    int64_t content_length = static_cast<int64_t>(response_data.size());
+
+    CefResponse::HeaderMap extra_headers;
+    response->GetHeaderMap(extra_headers);
+
+    server->SendHttpResponse(connection_id, response_code, content_type,
+                             content_length, extra_headers);
+
+    if (response_data == kIncompleteDoNotSendData) {
+      // Intentionally not sending data for incomplete request tests.
+      return;
+    }
+
+    if (content_length != 0) {
+      server->SendRawData(connection_id, response_data.data(),
+                          response_data.size());
+      server->CloseConnection(connection_id);
+    }
+
+    // The connection should be closed.
+    EXPECT_FALSE(server->IsValidConnection(connection_id));
+  }
+
+  Runner::Delegate* const delegate_;
+  CefRefPtr<CefServer> server_;
+
+  IMPLEMENT_REFCOUNTING(ServerHandler);
+  DISALLOW_COPY_AND_ASSIGN(ServerHandler);
+};
+
+class ServerRunner : public Runner {
+ public:
+  explicit ServerRunner(Delegate* delegate) : Runner(delegate) {}
+
+  void StartServer() override {
+    CEF_REQUIRE_UI_THREAD();
+    DCHECK(!handler_);
+    handler_ = new ServerHandler(delegate_);
+    CefServer::CreateServer(kHttpServerAddress, kHttpServerPort,
+                            kHttpServerBacklog, handler_);
+  }
+
+  void ShutdownServer() override {
+    CEF_REQUIRE_UI_THREAD();
+    DCHECK(handler_);
+    handler_->Shutdown();
+    handler_ = nullptr;
+  }
+
+ private:
+  CefRefPtr<ServerHandler> handler_;
+};
+
+}  // namespace
+
+std::unique_ptr<Runner> Runner::CreateNormal(Delegate* delegate) {
+  return std::make_unique<ServerRunner>(delegate);
+}
+
+}  // namespace test_server
diff --git a/src/tests/ceftests/test_server_runner_test.cc b/src/tests/ceftests/test_server_runner_test.cc
new file mode 100644
index 0000000..f88788f
--- /dev/null
+++ b/src/tests/ceftests/test_server_runner_test.cc
@@ -0,0 +1,155 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "tests/ceftests/test_server_runner.h"
+
+#include "include/test/cef_test_server.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "include/wrapper/cef_helpers.h"
+#include "tests/gtest/include/gtest/gtest.h"
+
+namespace test_server {
+
+namespace {
+
+// Created on the UI thread and called on the dedicated server thread.
+class ServerHandler : public CefTestServerHandler {
+ public:
+  ServerHandler(Runner::Delegate* delegate, bool https_server)
+      : delegate_(delegate), https_server_(https_server) {}
+
+  ~ServerHandler() override {
+    CEF_REQUIRE_UI_THREAD();
+
+    EXPECT_FALSE(server_);
+    delegate_->OnServerHandlerDeleted();
+  }
+
+  void Start() {
+    CEF_REQUIRE_UI_THREAD();
+
+    // Use any available port number for HTTPS and the legacy port number for
+    // HTTP.
+    const uint16_t port = https_server_ ? 0 : kHttpServerPort;
+
+    // Use a "localhost" domain certificate instead of IP address. This is
+    // required for HSTS tests (see https://crbug.com/456712).
+    const auto cert_type = CEF_TEST_CERT_OK_DOMAIN;
+
+    server_ =
+        CefTestServer::CreateAndStart(port, https_server_, cert_type, this);
+
+    // Always execute asynchronously.
+    CefPostTask(TID_UI, base::BindOnce(&ServerHandler::NotifyServerCreated,
+                                       this, server_->GetOrigin()));
+  }
+
+  void Shutdown() {
+    CEF_REQUIRE_UI_THREAD();
+
+    server_->Stop();
+    server_ = nullptr;
+
+    // Always execute asynchronously.
+    CefPostTask(TID_UI,
+                base::BindOnce(&ServerHandler::NotifyServerDestroyed, this));
+  }
+
+  bool OnTestServerRequest(
+      CefRefPtr<CefTestServer> server,
+      CefRefPtr<CefRequest> request,
+      CefRefPtr<CefTestServerConnection> connection) override {
+    NotifyTestServerRequest(request, connection);
+    return true;
+  }
+
+ private:
+  void NotifyServerCreated(const std::string& server_origin) {
+    CEF_REQUIRE_UI_THREAD();
+    delegate_->OnServerCreated(server_origin);
+  }
+
+  void NotifyServerDestroyed() {
+    CEF_REQUIRE_UI_THREAD();
+    delegate_->OnServerDestroyed();
+  }
+
+  void NotifyTestServerRequest(CefRefPtr<CefRequest> request,
+                               CefRefPtr<CefTestServerConnection> connection) {
+    if (!CefCurrentlyOn(TID_UI)) {
+      CefPostTask(TID_UI,
+                  base::BindOnce(&ServerHandler::NotifyTestServerRequest, this,
+                                 request, connection));
+      return;
+    }
+
+    auto response_callback =
+        base::BindRepeating(&ServerHandler::SendResponse, connection);
+    delegate_->OnTestServerRequest(request, response_callback);
+  }
+
+  static void SendResponse(CefRefPtr<CefTestServerConnection> connection,
+                           CefRefPtr<CefResponse> response,
+                           const std::string& response_data) {
+    const int response_code = response->GetStatus();
+    if (response_code <= 0) {
+      // Intentionally not responding for incomplete request tests.
+      return;
+    }
+
+    // Incomplete response data is not supported.
+    EXPECT_NE(kIncompleteDoNotSendData, response_data.c_str());
+
+    const CefString& content_type = response->GetMimeType();
+    EXPECT_TRUE(!content_type.empty());
+
+    CefResponse::HeaderMap extra_headers;
+    response->GetHeaderMap(extra_headers);
+
+    connection->SendHttpResponse(response_code, content_type,
+                                 response_data.c_str(), response_data.size(),
+                                 extra_headers);
+  }
+
+  Runner::Delegate* const delegate_;
+  const bool https_server_;
+
+  CefRefPtr<CefTestServer> server_;
+
+  IMPLEMENT_REFCOUNTING(ServerHandler);
+  DISALLOW_COPY_AND_ASSIGN(ServerHandler);
+};
+
+class ServerRunner : public Runner {
+ public:
+  ServerRunner(Delegate* delegate, bool https_server)
+      : Runner(delegate), https_server_(https_server) {}
+
+  void StartServer() override {
+    CEF_REQUIRE_UI_THREAD();
+    DCHECK(!handler_);
+    handler_ = new ServerHandler(delegate_, https_server_);
+    handler_->Start();
+  }
+
+  void ShutdownServer() override {
+    CEF_REQUIRE_UI_THREAD();
+    DCHECK(handler_);
+    handler_->Shutdown();
+    handler_ = nullptr;
+  }
+
+ private:
+  const bool https_server_;
+  CefRefPtr<ServerHandler> handler_;
+};
+
+}  // namespace
+
+std::unique_ptr<Runner> Runner::CreateTest(Delegate* delegate,
+                                           bool https_server) {
+  return std::make_unique<ServerRunner>(delegate, https_server);
+}
+
+}  // namespace test_server
diff --git a/src/tests/ceftests/test_server_unittest.cc b/src/tests/ceftests/test_server_unittest.cc
new file mode 100644
index 0000000..e2343ac
--- /dev/null
+++ b/src/tests/ceftests/test_server_unittest.cc
@@ -0,0 +1,977 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 <list>
+#include <map>
+#include <memory>
+#include <set>
+
+#include "include/base/cef_callback.h"
+#include "include/base/cef_ref_counted.h"
+#include "include/cef_command_line.h"
+#include "include/cef_task.h"
+#include "include/cef_urlrequest.h"
+#include "include/test/cef_test_server.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "tests/ceftests/routing_test_handler.h"
+#include "tests/ceftests/test_util.h"
+#include "tests/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const char kPlaceholderOrigin[] = "http://placeholder/";
+const int kTestTimeout = 5000;
+
+// Handles the test server. Used for both HTTP and HTTPS tests.
+class TestServerHandler : public CefTestServerHandler {
+ public:
+  // HTTP test handler.
+  // The methods of this class are always executed on the server thread.
+  class HttpRequestHandler {
+   public:
+    virtual ~HttpRequestHandler() {}
+    virtual bool HandleRequest(
+        CefRefPtr<CefTestServer> server,
+        CefRefPtr<CefRequest> request,
+        CefRefPtr<CefTestServerConnection> connection) = 0;
+    virtual bool VerifyResults() = 0;
+    virtual std::string ToString() = 0;
+  };
+
+  using StartCallback =
+      base::OnceCallback<void(const std::string& server_origin)>;
+
+  // |start_callback| will be executed on the UI thread after the server is
+  // started.
+  // |destroy_callback| will be executed on the UI thread after this handler
+  // object is destroyed.
+  TestServerHandler(StartCallback start_callback,
+                    base::OnceClosure destroy_callback)
+      : initialized_(false),
+        start_callback_(std::move(start_callback)),
+        destroy_callback_(std::move(destroy_callback)),
+        expected_http_request_ct_(0),
+        actual_http_request_ct_(0) {
+    EXPECT_FALSE(destroy_callback_.is_null());
+  }
+
+  virtual ~TestServerHandler() {
+    EXPECT_UI_THREAD();
+    std::move(destroy_callback_).Run();
+  }
+
+  // Must be called before CreateServer().
+  void AddHttpRequestHandler(
+      std::unique_ptr<HttpRequestHandler> request_handler) {
+    EXPECT_FALSE(initialized_);
+    EXPECT_TRUE(request_handler);
+    http_request_handler_list_.push_back(std::move(request_handler));
+  }
+
+  // Must be called before CreateServer().
+  void SetExpectedHttpRequestCount(int expected) {
+    EXPECT_FALSE(initialized_);
+    expected_http_request_ct_ = expected;
+  }
+
+  void CreateServer(bool https_server) {
+    EXPECT_FALSE(initialized_);
+    initialized_ = true;
+    https_server_ = https_server;
+
+    // Blocks until the server is created.
+    server_ = CefTestServer::CreateAndStart(/*port=*/0, https_server,
+                                            CEF_TEST_CERT_OK_DOMAIN, this);
+
+    origin_ = server_->GetOrigin();
+    EXPECT_TRUE(VerifyOrigin(origin_));
+
+    RunStartCallback();
+  }
+
+  // Results in a call to VerifyResults() and eventual execution of the
+  // |destroy_callback|.
+  void ShutdownServer() {
+    EXPECT_TRUE(server_);
+    server_->Stop();
+    server_ = nullptr;
+    VerifyResults();
+  }
+
+  bool OnTestServerRequest(
+      CefRefPtr<CefTestServer> server,
+      CefRefPtr<CefRequest> request,
+      CefRefPtr<CefTestServerConnection> connection) override {
+    EXPECT_TRUE(server);
+    EXPECT_STREQ(origin_.c_str(), server->GetOrigin().ToString().c_str());
+
+    EXPECT_TRUE(request);
+    EXPECT_TRUE(VerifyRequest(request));
+
+    EXPECT_TRUE(connection);
+
+    bool handled = false;
+    for (const auto& handler : http_request_handler_list_) {
+      handled = handler->HandleRequest(server, request, connection);
+      if (handled) {
+        break;
+      }
+    }
+    EXPECT_TRUE(handled) << "missing HttpRequestHandler for "
+                         << request->GetURL().ToString();
+
+    actual_http_request_ct_++;
+
+    return handled;
+  }
+
+ private:
+  bool VerifyOrigin(const std::string& origin) const {
+    V_DECLARE();
+    V_EXPECT_TRUE(origin.find(https_server_ ? "https://" : "http://") == 0)
+        << "origin " << origin_;
+    V_RETURN();
+  }
+
+  bool VerifyRequest(CefRefPtr<CefRequest> request) const {
+    V_DECLARE();
+
+    V_EXPECT_FALSE(request->GetMethod().empty());
+
+    const std::string& url = request->GetURL();
+    V_EXPECT_FALSE(url.empty());
+    V_EXPECT_TRUE(VerifyOrigin(url)) << "url " << url;
+
+    CefRefPtr<CefPostData> post_data = request->GetPostData();
+    if (post_data) {
+      CefPostData::ElementVector elements;
+      post_data->GetElements(elements);
+      V_EXPECT_TRUE(elements.size() == 1);
+      V_EXPECT_TRUE(elements[0]->GetBytesCount() > 0U);
+    }
+
+    V_RETURN();
+  }
+
+  void VerifyResults() const {
+    EXPECT_EQ(expected_http_request_ct_, actual_http_request_ct_);
+
+    for (const auto& handler : http_request_handler_list_) {
+      EXPECT_TRUE(handler->VerifyResults())
+          << "HttpRequestHandler for " << handler->ToString();
+    }
+  }
+
+ private:
+  void RunStartCallback() {
+    if (!CefCurrentlyOn(TID_UI)) {
+      CefPostTask(TID_UI,
+                  base::BindOnce(&TestServerHandler::RunStartCallback, this));
+      return;
+    }
+
+    EXPECT_FALSE(start_callback_.is_null());
+    std::move(start_callback_).Run(server_->GetOrigin());
+  }
+
+  CefRefPtr<CefTestServer> server_;
+  bool initialized_;
+
+  // After initialization only accessed on the UI thread.
+  StartCallback start_callback_;
+  base::OnceClosure destroy_callback_;
+
+  bool https_server_ = false;
+  std::string origin_;
+
+  // After initialization the below members are only accessed on the server
+  // thread.
+
+  std::list<std::unique_ptr<HttpRequestHandler>> http_request_handler_list_;
+
+  int expected_http_request_ct_;
+  int actual_http_request_ct_;
+
+  IMPLEMENT_REFCOUNTING(TestServerHandler);
+  DISALLOW_COPY_AND_ASSIGN(TestServerHandler);
+};
+
+// HTTP TESTS
+
+// Test runner for 1 or more HTTP requests/responses.
+// Works similarly to TestHandler but without the CefClient dependencies.
+class HttpTestRunner : public base::RefCountedThreadSafe<HttpTestRunner> {
+ public:
+  // The methods of this class are always executed on the UI thread.
+  class RequestRunner {
+   public:
+    virtual ~RequestRunner() {}
+
+    // Create the server-side handler for the request.
+    virtual std::unique_ptr<TestServerHandler::HttpRequestHandler>
+    CreateHttpRequestHandler() = 0;
+
+    // Run the request and execute |complete_callback| on completion.
+    virtual void RunRequest(const std::string& server_origin,
+                            base::OnceClosure complete_callback) = 0;
+
+    virtual bool VerifyResults() = 0;
+    virtual std::string ToString() = 0;
+  };
+
+  // If |parallel_requests| is true all requests will be run at the same time,
+  // otherwise one request will be run at a time.
+  HttpTestRunner(bool https_server, bool parallel_requests)
+      : https_server_(https_server), parallel_requests_(parallel_requests) {}
+
+  virtual ~HttpTestRunner() {
+    if (destroy_event_) {
+      destroy_event_->Signal();
+    }
+  }
+
+  void AddRequestRunner(std::unique_ptr<RequestRunner> request_runner) {
+    EXPECT_FALSE(initialized_);
+    request_runner_map_.insert(
+        std::make_pair(++next_request_id_, request_runner.release()));
+  }
+
+  // Blocks until the test has completed or timed out.
+  void ExecuteTest() {
+    EXPECT_FALSE(CefCurrentlyOn(TID_UI));
+
+    handler_ = new TestServerHandler(
+        base::BindOnce(&HttpTestRunner::OnServerStarted, this),
+        base::BindOnce(&HttpTestRunner::OnServerDestroyed, this));
+
+    run_event_ = CefWaitableEvent::CreateWaitableEvent(false, false);
+
+    CefPostTask(TID_UI, base::BindOnce(&HttpTestRunner::RunTest, this));
+
+    // Block until test completion.
+    run_event_->Wait();
+  }
+
+  // Event that will be signaled from the HttpTestRunner destructor.
+  // Used by ReleaseAndWaitForDestructor.
+  void SetDestroyEvent(CefRefPtr<CefWaitableEvent> event) {
+    destroy_event_ = event;
+  }
+
+ private:
+  void RunTest() {
+    EXPECT_UI_THREAD();
+    EXPECT_FALSE(initialized_);
+    initialized_ = true;
+
+    EXPECT_FALSE(request_runner_map_.empty());
+    RequestRunnerMap::const_iterator it = request_runner_map_.begin();
+    for (; it != request_runner_map_.end(); ++it) {
+      handler_->AddHttpRequestHandler(it->second->CreateHttpRequestHandler());
+    }
+
+    handler_->SetExpectedHttpRequestCount(
+        static_cast<int>(request_runner_map_.size()));
+
+    handler_->CreateServer(https_server_);
+
+    SetTestTimeout(kTestTimeout);
+  }
+
+  void OnServerStarted(const std::string& server_origin) {
+    EXPECT_UI_THREAD();
+    server_origin_ = server_origin;
+    if (parallel_requests_) {
+      RunAllRequests();
+    } else {
+      RunNextRequest();
+    }
+  }
+
+  void OnServerDestroyed() {
+    EXPECT_UI_THREAD();
+    EXPECT_FALSE(got_server_destroyed_);
+    got_server_destroyed_.yes();
+
+    // Allow the call stack to unwind.
+    CefPostTask(TID_UI, base::BindOnce(&HttpTestRunner::DestroyTest, this));
+  }
+
+  // Run all requests in parallel.
+  void RunAllRequests() {
+    RequestRunnerMap::const_iterator it = request_runner_map_.begin();
+    for (; it != request_runner_map_.end(); ++it) {
+      it->second->RunRequest(
+          server_origin_,
+          base::BindOnce(&HttpTestRunner::OnRequestComplete, this, it->first));
+    }
+  }
+
+  // Run one request at a time.
+  void RunNextRequest() {
+    RequestRunnerMap::const_iterator it = request_runner_map_.begin();
+    it->second->RunRequest(
+        server_origin_,
+        base::BindOnce(&HttpTestRunner::OnRequestComplete, this, it->first));
+  }
+
+  void OnRequestComplete(int request_id) {
+    EXPECT_UI_THREAD()
+    // Allow the call stack to unwind.
+    CefPostTask(TID_UI,
+                base::BindOnce(&HttpTestRunner::OnRequestCompleteContinue, this,
+                               request_id));
+  }
+
+  void OnRequestCompleteContinue(int request_id) {
+    RequestRunnerMap::iterator it = request_runner_map_.find(request_id);
+    EXPECT_TRUE(it != request_runner_map_.end());
+
+    // Verify the request results.
+    EXPECT_TRUE(it->second->VerifyResults())
+        << "request_id " << request_id << " RequestRunner for "
+        << it->second->ToString();
+    delete it->second;
+    request_runner_map_.erase(it);
+
+    if (request_runner_map_.empty()) {
+      got_all_requests_.yes();
+
+      // Will trigger TestServerHandler::HttpRequestHandler verification and a
+      // call to OnServerDestroyed().
+      handler_->ShutdownServer();
+      handler_ = nullptr;
+    } else if (!parallel_requests_) {
+      RunNextRequest();
+    }
+  }
+
+  void DestroyTest() {
+    EXPECT_UI_THREAD();
+
+    EXPECT_TRUE(got_all_requests_);
+    EXPECT_TRUE(got_server_destroyed_);
+    EXPECT_TRUE(request_runner_map_.empty());
+
+    // Cancel the timeout, if any.
+    if (ui_thread_helper_) {
+      ui_thread_helper_.reset();
+    }
+
+    // Signal test completion.
+    run_event_->Signal();
+  }
+
+  TestHandler::UIThreadHelper* GetUIThreadHelper() {
+    EXPECT_UI_THREAD();
+    if (!ui_thread_helper_) {
+      ui_thread_helper_.reset(new TestHandler::UIThreadHelper());
+    }
+    return ui_thread_helper_.get();
+  }
+
+  void SetTestTimeout(int timeout_ms) {
+    EXPECT_UI_THREAD();
+    const auto timeout = GetConfiguredTestTimeout(timeout_ms);
+    if (!timeout) {
+      return;
+    }
+
+    // Use a weak reference to |this| via UIThreadHelper so that the
+    // test runner can be destroyed before the timeout expires.
+    GetUIThreadHelper()->PostDelayedTask(
+        base::BindOnce(&HttpTestRunner::OnTestTimeout, base::Unretained(this),
+                       *timeout),
+        *timeout);
+  }
+
+  void OnTestTimeout(int timeout_ms) {
+    EXPECT_UI_THREAD();
+    EXPECT_TRUE(false) << "Test timed out after " << timeout_ms << "ms";
+    DestroyTest();
+  }
+
+  const bool https_server_;
+  const bool parallel_requests_;
+  CefRefPtr<CefWaitableEvent> run_event_;
+  CefRefPtr<CefWaitableEvent> destroy_event_;
+  CefRefPtr<TestServerHandler> handler_;
+  bool initialized_ = false;
+
+  // After initialization the below members are only accessed on the UI thread.
+
+  std::string server_origin_;
+  int next_request_id_ = 0;
+
+  // Map of request ID to RequestRunner.
+  typedef std::map<int, RequestRunner*> RequestRunnerMap;
+  RequestRunnerMap request_runner_map_;
+
+  TrackCallback got_all_requests_;
+  TrackCallback got_server_destroyed_;
+
+  std::unique_ptr<TestHandler::UIThreadHelper> ui_thread_helper_;
+
+  DISALLOW_COPY_AND_ASSIGN(HttpTestRunner);
+};
+
+// Structure representing the data that can be sent via
+// CefServer::SendHttp*Response().
+struct HttpServerResponse {
+  enum Type { TYPE_200, TYPE_404, TYPE_500, TYPE_CUSTOM };
+
+  explicit HttpServerResponse(Type response_type) : type(response_type) {}
+
+  Type type;
+
+  // Used with 200 and CUSTOM response type.
+  std::string content;
+  std::string content_type;
+
+  // Used with 500 response type.
+  std::string error_message;
+
+  // Used with CUSTOM response type.
+  int response_code;
+  CefRequest::HeaderMap extra_headers;
+};
+
+void SendHttpServerResponse(CefRefPtr<CefTestServerConnection> connection,
+                            const HttpServerResponse& response) {
+  switch (response.type) {
+    case HttpServerResponse::TYPE_200:
+      EXPECT_TRUE(!response.content_type.empty());
+      connection->SendHttp200Response(response.content_type,
+                                      response.content.data(),
+                                      response.content.size());
+      break;
+    case HttpServerResponse::TYPE_404:
+      connection->SendHttp404Response();
+      break;
+    case HttpServerResponse::TYPE_500:
+      connection->SendHttp500Response(response.error_message);
+      break;
+    case HttpServerResponse::TYPE_CUSTOM:
+      EXPECT_TRUE(!response.content_type.empty());
+      connection->SendHttpResponse(
+          response.response_code, response.content_type,
+          response.content.data(), response.content.size(),
+          response.extra_headers);
+      break;
+  }
+}
+
+std::string GetHeaderValue(const CefRequest::HeaderMap& header_map,
+                           const std::string& header_name) {
+  CefRequest::HeaderMap::const_iterator it = header_map.find(header_name);
+  if (it != header_map.end()) {
+    return it->second;
+  }
+  return std::string();
+}
+
+void VerifyHttpServerResponse(const HttpServerResponse& expected_response,
+                              CefRefPtr<CefResponse> response,
+                              const std::string& data) {
+  CefRequest::HeaderMap header_map;
+  response->GetHeaderMap(header_map);
+
+  switch (expected_response.type) {
+    case HttpServerResponse::TYPE_200:
+      EXPECT_EQ(200, response->GetStatus());
+      EXPECT_STREQ(expected_response.content_type.c_str(),
+                   GetHeaderValue(header_map, "Content-Type").c_str());
+      EXPECT_STREQ(expected_response.content.c_str(), data.c_str());
+      break;
+    case HttpServerResponse::TYPE_404:
+      EXPECT_EQ(404, response->GetStatus());
+      break;
+    case HttpServerResponse::TYPE_500:
+      EXPECT_EQ(500, response->GetStatus());
+      break;
+    case HttpServerResponse::TYPE_CUSTOM:
+      EXPECT_EQ(expected_response.response_code, response->GetStatus());
+      EXPECT_STREQ(expected_response.content_type.c_str(),
+                   GetHeaderValue(header_map, "Content-Type").c_str());
+      EXPECT_EQ(static_cast<int>(expected_response.content.size()),
+                atoi(GetHeaderValue(header_map, "Content-Length").c_str()));
+      EXPECT_STREQ(expected_response.content.c_str(), data.c_str());
+      TestMapEqual(expected_response.extra_headers, header_map, true);
+      break;
+  }
+}
+
+CefRefPtr<CefRequest> CreateTestServerRequest(
+    const std::string& path,
+    const std::string& method,
+    const std::string& data = std::string(),
+    const std::string& content_type = std::string(),
+    const CefRequest::HeaderMap& extra_headers = CefRequest::HeaderMap()) {
+  CefRefPtr<CefRequest> request = CefRequest::Create();
+
+  request->SetURL(kPlaceholderOrigin + path);
+  request->SetMethod(method);
+
+  CefRequest::HeaderMap header_map;
+
+  if (!data.empty()) {
+    CefRefPtr<CefPostData> post_data = CefPostData::Create();
+    CefRefPtr<CefPostDataElement> post_element = CefPostDataElement::Create();
+    post_element->SetToBytes(data.size(), data.data());
+    post_data->AddElement(post_element);
+    request->SetPostData(post_data);
+
+    EXPECT_FALSE(content_type.empty());
+    header_map.insert(std::make_pair("content-type", content_type));
+  }
+
+  if (!extra_headers.empty()) {
+    header_map.insert(extra_headers.begin(), extra_headers.end());
+  }
+  request->SetHeaderMap(header_map);
+
+  return request;
+}
+
+// RequestHandler that returns a static response for 1 or more requests.
+class StaticHttpServerRequestHandler
+    : public TestServerHandler::HttpRequestHandler {
+ public:
+  StaticHttpServerRequestHandler(CefRefPtr<CefRequest> expected_request,
+                                 int expected_request_ct,
+                                 const HttpServerResponse& response)
+      : expected_request_(expected_request),
+        expected_request_ct_(expected_request_ct),
+        actual_request_ct_(0),
+        response_(response) {}
+
+  bool HandleRequest(CefRefPtr<CefTestServer> server,
+                     CefRefPtr<CefRequest> request,
+                     CefRefPtr<CefTestServerConnection> connection) override {
+    if (request->GetURL() == expected_request_->GetURL() &&
+        request->GetMethod() == expected_request_->GetMethod()) {
+      TestRequestEqual(expected_request_, request, true);
+      actual_request_ct_++;
+
+      SendHttpServerResponse(connection, response_);
+      return true;
+    }
+
+    return false;
+  }
+
+  bool VerifyResults() override {
+    EXPECT_EQ(expected_request_ct_, actual_request_ct_);
+    return expected_request_ct_ == actual_request_ct_;
+  }
+
+  std::string ToString() override { return expected_request_->GetURL(); }
+
+ private:
+  CefRefPtr<CefRequest> expected_request_;
+  int expected_request_ct_;
+  int actual_request_ct_;
+  HttpServerResponse response_;
+
+  DISALLOW_COPY_AND_ASSIGN(StaticHttpServerRequestHandler);
+};
+
+// URLRequestClient that runs a single request and executes a callback with the
+// response.
+class StaticHttpURLRequestClient : public CefURLRequestClient {
+ public:
+  using ResponseCallback =
+      base::OnceCallback<void(cef_errorcode_t /* error */,
+                              CefRefPtr<CefResponse> /* response */,
+                              const std::string& /* data */)>;
+
+  // |response_callback| will be executed on the UI thread when the response
+  // is complete.
+  StaticHttpURLRequestClient(CefRefPtr<CefRequest> request,
+                             ResponseCallback response_callback)
+      : request_(request), response_callback_(std::move(response_callback)) {
+    EXPECT_TRUE(request_);
+    EXPECT_FALSE(response_callback_.is_null());
+  }
+
+  void RunRequest() {
+    EXPECT_UI_THREAD();
+    CefURLRequest::Create(request_, this, nullptr);
+  }
+
+  void OnRequestComplete(CefRefPtr<CefURLRequest> request) override {
+    EXPECT_FALSE(response_callback_.is_null());
+    std::move(response_callback_)
+        .Run(request->GetRequestError(), request->GetResponse(), data_);
+  }
+
+  void OnUploadProgress(CefRefPtr<CefURLRequest> request,
+                        int64_t current,
+                        int64_t total) override {}
+
+  void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
+                          int64_t current,
+                          int64_t total) override {}
+
+  void OnDownloadData(CefRefPtr<CefURLRequest> request,
+                      const void* data,
+                      size_t data_length) override {
+    data_.append(static_cast<const char*>(data), data_length);
+  }
+
+  bool GetAuthCredentials(bool isProxy,
+                          const CefString& host,
+                          int port,
+                          const CefString& realm,
+                          const CefString& scheme,
+                          CefRefPtr<CefAuthCallback> callback) override {
+    return false;
+  }
+
+ private:
+  CefRefPtr<CefRequest> request_;
+  ResponseCallback response_callback_;
+  std::string data_;
+
+  IMPLEMENT_REFCOUNTING(StaticHttpURLRequestClient);
+  DISALLOW_COPY_AND_ASSIGN(StaticHttpURLRequestClient);
+};
+
+// RequestRunner that will manage a single static HTTP request/response.
+class StaticHttpRequestRunner : public HttpTestRunner::RequestRunner {
+ public:
+  StaticHttpRequestRunner(CefRefPtr<CefRequest> request,
+                          const HttpServerResponse& response)
+      : request_(request), response_(response) {}
+
+  static std::unique_ptr<HttpTestRunner::RequestRunner> Create200(
+      const std::string& path,
+      bool with_content = true) {
+    CefRefPtr<CefRequest> request = CreateTestServerRequest(path, "GET");
+    HttpServerResponse response(HttpServerResponse::TYPE_200);
+    response.content_type = "text/html";
+    if (with_content) {
+      response.content = "<html>200 response content</html>";
+    }
+    return std::make_unique<StaticHttpRequestRunner>(request, response);
+  }
+
+  static std::unique_ptr<HttpTestRunner::RequestRunner> Create404(
+      const std::string& path) {
+    CefRefPtr<CefRequest> request = CreateTestServerRequest(path, "GET");
+    HttpServerResponse response(HttpServerResponse::TYPE_404);
+    return std::make_unique<StaticHttpRequestRunner>(request, response);
+  }
+
+  static std::unique_ptr<HttpTestRunner::RequestRunner> Create500(
+      const std::string& path) {
+    CefRefPtr<CefRequest> request = CreateTestServerRequest(path, "GET");
+    // Don't retry the request.
+    request->SetFlags(UR_FLAG_NO_RETRY_ON_5XX);
+    HttpServerResponse response(HttpServerResponse::TYPE_500);
+    response.error_message = "Something went wrong!";
+    return std::make_unique<StaticHttpRequestRunner>(request, response);
+  }
+
+  static std::unique_ptr<HttpTestRunner::RequestRunner> CreateCustom(
+      const std::string& path,
+      bool with_content = true) {
+    CefRequest::HeaderMap request_headers;
+    request_headers.insert(std::make_pair("x-request-custom1", "My Value A"));
+    request_headers.insert(std::make_pair("x-request-custom2", "My Value B"));
+    CefRefPtr<CefRequest> request = CreateTestServerRequest(
+        path, "POST", "foo=bar&choo=too", "application/x-www-form-urlencoded",
+        request_headers);
+    request->SetReferrer("http://tests/referer.html", REFERRER_POLICY_DEFAULT);
+
+    HttpServerResponse response(HttpServerResponse::TYPE_CUSTOM);
+    response.response_code = 202;
+    if (with_content) {
+      response.content = "BlahBlahBlah";
+    }
+    response.content_type = "application/x-blah-blah";
+    response.extra_headers.insert(
+        std::make_pair("x-response-custom1", "My Value 1"));
+    response.extra_headers.insert(
+        std::make_pair("x-response-custom2", "My Value 2"));
+
+    return std::make_unique<StaticHttpRequestRunner>(request, response);
+  }
+
+  std::unique_ptr<TestServerHandler::HttpRequestHandler>
+  CreateHttpRequestHandler() override {
+    EXPECT_FALSE(got_create_handler_);
+    got_create_handler_.yes();
+    return std::make_unique<StaticHttpServerRequestHandler>(request_, 1,
+                                                            response_);
+  }
+
+  void RunRequest(const std::string& server_origin,
+                  base::OnceClosure complete_callback) override {
+    EXPECT_UI_THREAD();
+
+    EXPECT_FALSE(got_run_request_);
+    got_run_request_.yes();
+
+    complete_callback_ = std::move(complete_callback);
+
+    // Replace the placeholder with the actual server origin.
+    const std::string& url = request_->GetURL();
+    EXPECT_TRUE(url.find(kPlaceholderOrigin) == 0);
+    const std::string& real_url =
+        server_origin + "/" + url.substr(sizeof(kPlaceholderOrigin) - 1);
+    request_->SetURL(real_url);
+
+    request_client_ = new StaticHttpURLRequestClient(
+        request_, base::BindOnce(&StaticHttpRequestRunner::OnResponseComplete,
+                                 base::Unretained(this)));
+    request_client_->RunRequest();
+  }
+
+  bool VerifyResults() override {
+    V_DECLARE();
+    V_EXPECT_TRUE(got_create_handler_);
+    V_EXPECT_TRUE(got_run_request_);
+    V_EXPECT_TRUE(got_response_complete_);
+    V_RETURN();
+  }
+
+  std::string ToString() override { return request_->GetURL(); }
+
+ private:
+  void OnResponseComplete(cef_errorcode_t error,
+                          CefRefPtr<CefResponse> response,
+                          const std::string& data) {
+    EXPECT_UI_THREAD();
+
+    EXPECT_FALSE(got_response_complete_);
+    got_response_complete_.yes();
+
+    EXPECT_EQ(error, ERR_NONE)
+        << "OnResponseComplete for " << request_->GetURL().ToString();
+    if (error == ERR_NONE) {
+      VerifyHttpServerResponse(response_, response, data);
+    }
+
+    std::move(complete_callback_).Run();
+  }
+
+  CefRefPtr<CefRequest> request_;
+  HttpServerResponse response_;
+
+  CefRefPtr<StaticHttpURLRequestClient> request_client_;
+  base::OnceClosure complete_callback_;
+
+  TrackCallback got_run_request_;
+  TrackCallback got_create_handler_;
+  TrackCallback got_response_complete_;
+
+  DISALLOW_COPY_AND_ASSIGN(StaticHttpRequestRunner);
+};
+
+}  // namespace
+
+// Verify handling of a single HTTP 200 request.
+TEST(TestServerTest, HttpSingle200) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/false, /*parallel_requests=*/false);
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200.html"));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of a single HTTPS 200 request.
+TEST(TestServerTest, HttpsSingle200) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/true, /*parallel_requests=*/false);
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200.html"));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of a single HTTP 200 request with no content.
+TEST(TestServerTest, HttpSingle200NoContent) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/false, /*parallel_requests=*/false);
+  runner->AddRequestRunner(
+      StaticHttpRequestRunner::Create200("200.html", false));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of a single HTTPS 200 request with no content.
+TEST(TestServerTest, HttpsSingle200NoContent) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/true, /*parallel_requests=*/false);
+  runner->AddRequestRunner(
+      StaticHttpRequestRunner::Create200("200.html", false));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of a single HTTP 404 request.
+TEST(TestServerTest, HttpSingle404) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/false, /*parallel_requests=*/false);
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create404("404.html"));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of a single HTTPS 404 request.
+TEST(TestServerTest, HttpsSingle404) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/true, /*parallel_requests=*/false);
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create404("404.html"));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of a single HTTP 500 request.
+TEST(TestServerTest, HttpSingle500) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/false, /*parallel_requests=*/false);
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create500("500.html"));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of a single HTTPS 500 request.
+TEST(TestServerTest, HttpsSingle500) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/true, /*parallel_requests=*/false);
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create500("500.html"));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of a single HTTP custom request.
+TEST(TestServerTest, HttpSingleCustom) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/false, /*parallel_requests=*/false);
+  runner->AddRequestRunner(StaticHttpRequestRunner::CreateCustom("202.html"));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of a single HTTP custom request.
+TEST(TestServerTest, HttpsSingleCustom) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/true, /*parallel_requests=*/false);
+  runner->AddRequestRunner(StaticHttpRequestRunner::CreateCustom("202.html"));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of a single HTTP custom request with no content.
+TEST(TestServerTest, HttpSingleCustomNoContent) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/false, /*parallel_requests=*/false);
+  runner->AddRequestRunner(StaticHttpRequestRunner::CreateCustom(
+      "202.html", /*with_content=*/false));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of a single HTTPS custom request with no content.
+TEST(TestServerTest, HttpsSingleCustomNoContent) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/true, /*parallel_requests=*/false);
+  runner->AddRequestRunner(StaticHttpRequestRunner::CreateCustom(
+      "202.html", /*with_content=*/false));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of multiple HTTP requests in parallel.
+TEST(TestServerTest, HttpMultipleParallel200) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/false, /*parallel_requests=*/true);
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200a.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200b.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200c.html"));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of multiple HTTPS requests in parallel.
+TEST(TestServerTest, HttpsMultipleParallel200) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/true, /*parallel_requests=*/true);
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200a.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200b.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200c.html"));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of multiple HTTP requests in serial.
+TEST(TestServerTest, HttpMultipleSerial200) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/false, /*parallel_requests=*/false);
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200a.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200b.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200c.html"));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of multiple HTTPS requests in serial.
+TEST(TestServerTest, HttpsMultipleSerial200) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/true, /*parallel_requests=*/false);
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200a.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200b.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200c.html"));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of multiple HTTP requests in parallel.
+TEST(TestServerTest, HttpMultipleParallelMixed) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/false, /*parallel_requests=*/true);
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create404("404.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create500("500.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::CreateCustom("202.html"));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of multiple HTTPS requests in parallel.
+TEST(TestServerTest, HttpsMultipleParallelMixed) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/true, /*parallel_requests=*/true);
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create404("404.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create500("500.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::CreateCustom("202.html"));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of multiple HTTP requests in serial.
+TEST(TestServerTest, HttpMultipleSerialMixed) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/false, /*parallel_requests=*/false);
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create404("404.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create500("500.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::CreateCustom("202.html"));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
+
+// Verify handling of multiple HTTPS requests in serial.
+TEST(TestServerTest, HttpsMultipleSerialMixed) {
+  CefRefPtr<HttpTestRunner> runner =
+      new HttpTestRunner(/*https_server=*/true, /*parallel_requests=*/false);
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create404("404.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::Create500("500.html"));
+  runner->AddRequestRunner(StaticHttpRequestRunner::CreateCustom("202.html"));
+  runner->ExecuteTest();
+  ReleaseAndWaitForDestructor(runner);
+}
diff --git a/src/tests/ceftests/test_suite.cc b/src/tests/ceftests/test_suite.cc
index d96eefd..1f95506 100644
--- a/src/tests/ceftests/test_suite.cc
+++ b/src/tests/ceftests/test_suite.cc
@@ -4,8 +4,13 @@
 
 #include "tests/ceftests/test_suite.h"
 
+#include "include/base/cef_logging.h"
 #include "include/cef_file_util.h"
+#include "include/test/cef_test_helpers.h"
+#include "include/wrapper/cef_scoped_temp_dir.h"
 #include "tests/gtest/include/gtest/gtest.h"
+#include "tests/gtest/teamcity/include/teamcity_gtest.h"
+#include "tests/shared/browser/resource_util.h"
 #include "tests/shared/common/client_switches.h"
 
 namespace {
@@ -38,12 +43,14 @@
   if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
     unsigned int result = GetLastError();
     // Was probably already attached.
-    if (result == ERROR_ACCESS_DENIED)
+    if (result == ERROR_ACCESS_DENIED) {
       return;
+    }
     // Don't bother creating a new console for each child process if the
     // parent process is invalid (eg: crashed).
-    if (result == ERROR_GEN_FAILURE)
+    if (result == ERROR_GEN_FAILURE) {
       return;
+    }
     if (create_console_if_not_found) {
       // Make a new console if attaching to parent fails with any other error.
       // It should be ERROR_INVALID_HANDLE at this point, which means the
@@ -92,6 +99,18 @@
 #else
   command_line_->InitFromArgv(argc, argv);
 #endif
+
+  if (!command_line_->HasSwitch("type")) {
+    // Initialize in the main process only.
+    root_cache_path_ =
+        command_line_->GetSwitchValue(client::switches::kCachePath);
+    if (root_cache_path_.empty()) {
+      CefScopedTempDir temp_dir;
+      CHECK(temp_dir.CreateUniqueTempDir());
+      root_cache_path_ = temp_dir.Take();
+      RegisterTempDirectory(root_cache_path_);
+    }
+  }
 }
 
 CefTestSuite::~CefTestSuite() {
@@ -108,6 +127,12 @@
 
   // This will modify |argc_| and |argv_|.
   testing::InitGoogleTest(&argc_, argv_.array());
+
+  if (jetbrains::teamcity::underTeamcity()) {
+    auto& listeners = ::testing::UnitTest::GetInstance()->listeners();
+    listeners.Append(
+        new jetbrains::teamcity::TeamcityGoogleTestEventListener());
+  }
 }
 
 // Don't add additional code to this method. Instead add it to Initialize().
@@ -119,18 +144,12 @@
 }
 
 void CefTestSuite::GetSettings(CefSettings& settings) const {
-#if (defined(OS_WIN) || defined(OS_LINUX))
-  settings.multi_threaded_message_loop =
-      command_line_->HasSwitch(client::switches::kMultiThreadedMessageLoop);
-#endif
+  // Enable the experimental Chrome runtime. See issue #2969 for details.
+  settings.chrome_runtime =
+      command_line_->HasSwitch(client::switches::kEnableChromeRuntime);
 
-  if (!settings.multi_threaded_message_loop) {
-    settings.external_message_pump =
-        command_line_->HasSwitch(client::switches::kExternalMessagePump);
-  }
-
-  CefString(&settings.cache_path) =
-      command_line_->GetSwitchValue(client::switches::kCachePath);
+  CefString(&settings.cache_path) = root_cache_path_;
+  CefString(&settings.root_cache_path) = root_cache_path_;
 
   // Always expose the V8 gc() function to give tests finer-grained control over
   // memory management.
@@ -138,8 +157,9 @@
   // Value of kJavascriptFlags switch.
   std::string other_javascript_flags =
       command_line_->GetSwitchValue("js-flags");
-  if (!other_javascript_flags.empty())
+  if (!other_javascript_flags.empty()) {
     javascript_flags += " " + other_javascript_flags;
+  }
   CefString(&settings.javascript_flags) = javascript_flags;
 
   // Necessary for V8Test.OnUncaughtException tests.
@@ -152,17 +172,6 @@
   CefString(&settings.accept_language_list) = CEF_SETTINGS_ACCEPT_LANGUAGE;
 }
 
-// static
-bool CefTestSuite::GetCachePath(std::string& path) const {
-  if (command_line_->HasSwitch(client::switches::kCachePath)) {
-    // Set the cache_path value.
-    path = command_line_->GetSwitchValue(client::switches::kCachePath);
-    return true;
-  }
-
-  return false;
-}
-
 void CefTestSuite::RegisterTempDirectory(const CefString& directory) {
   base::AutoLock lock_scope(temp_directories_lock_);
   temp_directories_.push_back(directory);
@@ -185,12 +194,12 @@
   HeapSetInformation(nullptr, HeapEnableTerminationOnCorruption, nullptr, 0);
 #endif
 
-#if defined(OS_LINUX) && defined(USE_AURA)
+#if defined(OS_LINUX)
   // When calling native char conversion functions (e.g wrctomb) we need to
   // have the locale set. In the absence of such a call the "C" locale is the
   // default. In the gtk code (below) gtk_init() implicitly sets a locale.
   setlocale(LC_ALL, "");
-#endif  // defined(OS_LINUX) && defined(USE_AURA)
+#endif  // defined(OS_LINUX)
 
   // Don't add additional code to this function. Instead add it to Initialize().
 }
@@ -199,6 +208,14 @@
 #if defined(OS_WIN)
   RouteStdioToConsole(true);
 #endif  // defined(OS_WIN)
+
+#if !defined(CEF_TESTS_IN_SRC_DIRECTORY)
+  // Configure the directory that contains test data resources.
+  std::string resource_dir;
+  bool result = client::GetResourceDir(resource_dir);
+  CHECK(result && !resource_dir.empty());
+  CefSetDataDirectoryForTests(resource_dir);
+#endif  // !defined(CEF_TESTS_IN_SRC_DIRECTORY)
 }
 
 void CefTestSuite::Shutdown() {}
diff --git a/src/tests/ceftests/test_suite.h b/src/tests/ceftests/test_suite.h
index 77ce333..ccae2d9 100644
--- a/src/tests/ceftests/test_suite.h
+++ b/src/tests/ceftests/test_suite.h
@@ -2,8 +2,8 @@
 // 2012 The Chromium Authors. All rights reserved. Use of this source code is
 // governed by a BSD-style license that can be found in the LICENSE file.
 
-#ifndef CEF_TESTS_UNITTESTS_TEST_SUITE_H_
-#define CEF_TESTS_UNITTESTS_TEST_SUITE_H_
+#ifndef CEF_TESTS_CEFTESTS_TEST_SUITE_H_
+#define CEF_TESTS_CEFTESTS_TEST_SUITE_H_
 #pragma once
 
 #include <string>
@@ -25,7 +25,6 @@
   int Run();
 
   void GetSettings(CefSettings& settings) const;
-  bool GetCachePath(std::string& path) const;
 
   // Register a temp directory that should be deleted on shutdown.
   void RegisterTempDirectory(const CefString& directory);
@@ -34,6 +33,7 @@
   void DeleteTempDirectories();
 
   CefRefPtr<CefCommandLine> command_line() const { return command_line_; }
+  CefString root_cache_path() const { return root_cache_path_; }
 
   // The return value from Run().
   int retval() const { return retval_; }
@@ -50,9 +50,11 @@
   std::vector<CefString> temp_directories_;
   base::Lock temp_directories_lock_;
 
+  CefString root_cache_path_;
+
   int retval_;
 };
 
 #define CEF_SETTINGS_ACCEPT_LANGUAGE "en-GB"
 
-#endif  // CEF_TESTS_UNITTESTS_TEST_SUITE_H_
+#endif  // CEF_TESTS_CEFTESTS_TEST_SUITE_H_
diff --git a/src/tests/ceftests/test_util.cc b/src/tests/ceftests/test_util.cc
index 5058b1f..aaa65bc 100644
--- a/src/tests/ceftests/test_util.cc
+++ b/src/tests/ceftests/test_util.cc
@@ -3,9 +3,19 @@
 // can be found in the LICENSE file.
 
 #include "tests/ceftests/test_util.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstdlib>
+
+#include "include/base/cef_callback.h"
+#include "include/cef_base.h"
 #include "include/cef_command_line.h"
 #include "include/cef_request_context_handler.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "include/wrapper/cef_helpers.h"
 #include "tests/gtest/include/gtest/gtest.h"
+#include "tests/shared/common/string_util.h"
 
 void TestMapEqual(const CefRequest::HeaderMap& map1,
                   const CefRequest::HeaderMap& map2,
@@ -21,11 +31,9 @@
 
   for (it1 = map1.begin(); it1 != map1.end(); ++it1) {
     bool found = false;
-    std::string name1 = it1->first;
-    std::transform(name1.begin(), name1.end(), name1.begin(), ::tolower);
+    std::string name1 = client::AsciiStrToLower(it1->first);
     for (it2 = map2.begin(); it2 != map2.end(); ++it2) {
-      std::string name2 = it2->first;
-      std::transform(name2.begin(), name2.end(), name2.begin(), ::tolower);
+      std::string name2 = client::AsciiStrToLower(it2->first);
       if (name1 == name2 && it1->second == it2->second) {
         found = true;
         break;
@@ -88,8 +96,9 @@
 
   CefPostData::ElementVector::const_iterator it1 = ev1.begin();
   CefPostData::ElementVector::const_iterator it2 = ev2.begin();
-  for (; it1 != ev1.end() && it2 != ev2.end(); ++it1, ++it2)
+  for (; it1 != ev1.end() && it2 != ev2.end(); ++it1, ++it2) {
     TestPostDataElementEqual((*it1), (*it2));
+  }
 }
 
 void TestRequestEqual(CefRefPtr<CefRequest> request1,
@@ -115,8 +124,9 @@
   CefRefPtr<CefPostData> postData1 = request1->GetPostData();
   CefRefPtr<CefPostData> postData2 = request2->GetPostData();
   EXPECT_EQ(!!(postData1.get()), !!(postData2.get()));
-  if (postData1.get() && postData2.get())
+  if (postData1.get() && postData2.get()) {
     TestPostDataEqual(postData1, postData2);
+  }
 }
 
 void TestResponseEqual(CefRefPtr<CefResponse> response1,
@@ -267,52 +277,174 @@
                            const std::vector<CefString>& val2) {
   EXPECT_EQ(val1.size(), val2.size());
 
-  for (size_t i = 0; i < val1.size(); ++i)
+  for (size_t i = 0; i < val1.size(); ++i) {
     EXPECT_STREQ(val1[i].ToString().c_str(), val2[i].ToString().c_str());
+  }
 }
 
 bool TestOldResourceAPI() {
-  static int state = -1;
-  if (state == -1) {
-    CefRefPtr<CefCommandLine> command_line =
-        CefCommandLine::GetGlobalCommandLine();
-    state = command_line->HasSwitch("test-old-resource-api") ? 1 : 0;
-  }
-  return state ? true : false;
+  static bool state = []() {
+    return CefCommandLine::GetGlobalCommandLine()->HasSwitch(
+        "test-old-resource-api");
+  }();
+  return state;
 }
 
-CefRefPtr<CefRequestContext> CreateTestRequestContext(
-    TestRequestContextMode mode,
-    const std::string& cache_path) {
-  EXPECT_TRUE(cache_path.empty() || mode == TEST_RC_MODE_CUSTOM ||
-              mode == TEST_RC_MODE_CUSTOM_WITH_HANDLER);
+bool IsChromeRuntimeEnabled() {
+  static bool state = []() {
+    return CefCommandLine::GetGlobalCommandLine()->HasSwitch(
+        "enable-chrome-runtime");
+  }();
+  return state;
+}
 
-  if (mode == TEST_RC_MODE_NONE)
-    return nullptr;
-  if (mode == TEST_RC_MODE_GLOBAL)
-    return CefRequestContext::GetGlobalContext();
-
-  CefRefPtr<CefRequestContextHandler> rc_handler;
-  if (mode == TEST_RC_MODE_GLOBAL_WITH_HANDLER ||
-      mode == TEST_RC_MODE_CUSTOM_WITH_HANDLER) {
-    class Handler : public CefRequestContextHandler {
-     public:
-      Handler() {}
-
-     private:
-      IMPLEMENT_REFCOUNTING(Handler);
-    };
-    rc_handler = new Handler();
+bool IsBFCacheEnabled() {
+  // Supported by the Chrome runtime only, see issue #3237.
+  if (!IsChromeRuntimeEnabled()) {
+    return false;
   }
 
-  if (mode == TEST_RC_MODE_CUSTOM || mode == TEST_RC_MODE_CUSTOM_WITH_HANDLER) {
+  static bool state = []() {
+    const std::string& value =
+        CefCommandLine::GetGlobalCommandLine()->GetSwitchValue(
+            "disable-features");
+    return value.find("BackForwardCache") == std::string::npos;
+  }();
+  return state;
+}
+
+bool IsSameSiteBFCacheEnabled() {
+  // Same-site BFCache is enabled by default starting in M101 and does not have
+  // a separate configuration flag.
+  return IsBFCacheEnabled();
+}
+
+bool IgnoreURL(const std::string& url) {
+  return IsChromeRuntimeEnabled() &&
+         url.find("/favicon.ico") != std::string::npos;
+}
+
+std::optional<int> GetConfiguredTestTimeout(int timeout_ms) {
+  static std::optional<double> multiplier = []() -> std::optional<double> {
+    auto command_line = CefCommandLine::GetGlobalCommandLine();
+    if (command_line->HasSwitch("disable-test-timeout")) {
+      return std::nullopt;
+    }
+    const std::string& sval =
+        command_line->GetSwitchValue("test-timeout-multiplier");
+    if (!sval.empty()) {
+      if (double dval = std::atof(sval.c_str())) {
+        return dval;
+      }
+    }
+    return IsChromeRuntimeEnabled() ? 2.0 : 1.0;
+  }();
+
+  if (!multiplier) {
+    // Test timeout is disabled.
+    return std::nullopt;
+  }
+
+  return static_cast<int>(
+      std::round(static_cast<double>(timeout_ms) * (*multiplier)));
+}
+
+void SendMouseClickEvent(CefRefPtr<CefBrowser> browser,
+                         const CefMouseEvent& mouse_event,
+                         cef_mouse_button_type_t mouse_button_type) {
+  auto host = browser->GetHost();
+  CefPostDelayedTask(TID_UI,
+                     base::BindOnce(&CefBrowserHost::SendMouseClickEvent, host,
+                                    mouse_event, mouse_button_type, false, 1),
+                     50);
+  CefPostDelayedTask(TID_UI,
+                     base::BindOnce(&CefBrowserHost::SendMouseClickEvent, host,
+                                    mouse_event, mouse_button_type, true, 1),
+                     100);
+}
+
+void GrantPopupPermission(CefRefPtr<CefRequestContext> request_context,
+                          const std::string& parent_url) {
+  if (IsChromeRuntimeEnabled()) {
+    static bool test_website_setting = []() {
+      return CefCommandLine::GetGlobalCommandLine()->HasSwitch(
+          "test-website-setting");
+    }();
+
+    // The below calls are equivalent.
+    // NOTE: If the popup allow functionality stops working, debug the code in
+    // components/blocked_content/popup_blocker.cc
+    if (test_website_setting) {
+      auto value = CefValue::Create();
+      value->SetInt(CEF_CONTENT_SETTING_VALUE_ALLOW);
+      request_context->SetWebsiteSetting(
+          parent_url, parent_url, CEF_CONTENT_SETTING_TYPE_POPUPS, value);
+    } else {
+      request_context->SetContentSetting(parent_url, parent_url,
+                                         CEF_CONTENT_SETTING_TYPE_POPUPS,
+                                         CEF_CONTENT_SETTING_VALUE_ALLOW);
+    }
+  }
+}
+
+void CreateTestRequestContext(TestRequestContextMode mode,
+                              const std::string& cache_path,
+                              RCInitCallback init_callback) {
+  DCHECK(!init_callback.is_null());
+  EXPECT_TRUE(cache_path.empty() || mode == TEST_RC_MODE_CUSTOM_WITH_HANDLER);
+
+  if (mode == TEST_RC_MODE_NONE || mode == TEST_RC_MODE_GLOBAL) {
+    // Global contexts are initialized synchronously during startup, so we can
+    // execute the callback immediately.
+    CefRefPtr<CefRequestContext> request_context;
+    if (mode == TEST_RC_MODE_GLOBAL) {
+      request_context = CefRequestContext::GetGlobalContext();
+    }
+
+    CefPostTask(TID_UI,
+                base::BindOnce(std::move(init_callback), request_context));
+    return;
+  }
+
+  class Handler : public CefRequestContextHandler {
+   public:
+    explicit Handler(RCInitCallback init_callback)
+        : init_callback_(std::move(init_callback)) {}
+
+    void OnRequestContextInitialized(
+        CefRefPtr<CefRequestContext> request_context) override {
+      CEF_REQUIRE_UI_THREAD();
+      std::move(init_callback_).Run(request_context);
+    }
+
+   private:
+    RCInitCallback init_callback_;
+    IMPLEMENT_REFCOUNTING(Handler);
+  };
+
+  CefRefPtr<CefRequestContextHandler> rc_handler =
+      new Handler(std::move(init_callback));
+
+  if (mode == TEST_RC_MODE_CUSTOM_WITH_HANDLER) {
     CefRequestContextSettings settings;
-    if (!cache_path.empty())
+    if (!cache_path.empty()) {
       CefString(&settings.cache_path) = cache_path;
-    return CefRequestContext::CreateContext(settings, rc_handler);
+    }
+    CefRequestContext::CreateContext(settings, rc_handler);
+  } else {
+    CefRequestContext::CreateContext(CefRequestContext::GetGlobalContext(),
+                                     rc_handler);
   }
+}
 
-  EXPECT_EQ(mode, TEST_RC_MODE_GLOBAL_WITH_HANDLER);
-  return CefRequestContext::CreateContext(CefRequestContext::GetGlobalContext(),
-                                          rc_handler);
+CefTime CefTimeFrom(CefBaseTime value) {
+  CefTime time;
+  cef_time_from_basetime(value, &time);
+  return time;
+}
+
+CefBaseTime CefBaseTimeFrom(const CefTime& value) {
+  cef_basetime_t temp;
+  cef_time_to_basetime(&value, &temp);
+  return CefBaseTime(temp);
 }
diff --git a/src/tests/ceftests/test_util.h b/src/tests/ceftests/test_util.h
index 7f0fe4a..2c024f8 100644
--- a/src/tests/ceftests/test_util.h
+++ b/src/tests/ceftests/test_util.h
@@ -2,10 +2,13 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#ifndef CEF_TESTS_UNITTESTS_TEST_UTIL_H_
-#define CEF_TESTS_UNITTESTS_TEST_UTIL_H_
+#ifndef CEF_TESTS_CEFTESTS_TEST_UTIL_H_
+#define CEF_TESTS_CEFTESTS_TEST_UTIL_H_
 #pragma once
 
+#include <optional>
+
+#include "include/base/cef_callback.h"
 #include "include/cef_process_message.h"
 #include "include/cef_request.h"
 #include "include/cef_request_context.h"
@@ -13,6 +16,9 @@
 #include "include/cef_values.h"
 #include "tests/ceftests/test_suite.h"
 
+CefTime CefTimeFrom(CefBaseTime value);
+CefBaseTime CefBaseTimeFrom(const CefTime& value);
+
 // Test that CefRequest::HeaderMap objects are equal. Multiple values with the
 // same key are allowed, but not duplicate entries with the same key/value. If
 // |allowExtras| is true then additional header fields will be allowed in
@@ -69,24 +75,71 @@
   TEST_RC_MODE_NONE,
   TEST_RC_MODE_GLOBAL,
   TEST_RC_MODE_GLOBAL_WITH_HANDLER,
-  TEST_RC_MODE_CUSTOM,
   TEST_RC_MODE_CUSTOM_WITH_HANDLER,
 };
 
 inline bool IsTestRequestContextModeCustom(TestRequestContextMode mode) {
-  return mode == TEST_RC_MODE_CUSTOM ||
-         mode == TEST_RC_MODE_CUSTOM_WITH_HANDLER;
+  return mode == TEST_RC_MODE_CUSTOM_WITH_HANDLER;
 }
 
 // Returns true if the old CefResourceHandler API should be tested.
 bool TestOldResourceAPI();
 
-// Return a RequestContext object matching the specified |mode|.
-// |cache_path| may be specified for CUSTOM modes.
-// Use the RC_TEST_GROUP_BASE macro to test all valid combinations.
-CefRefPtr<CefRequestContext> CreateTestRequestContext(
-    TestRequestContextMode mode,
-    const std::string& cache_path);
+// Returns true if the Chrome runtime is enabled.
+bool IsChromeRuntimeEnabled();
+
+// Returns true if BFCache is enabled.
+bool IsBFCacheEnabled();
+
+// Returns true if same-site BFCache is enabled.
+bool IsSameSiteBFCacheEnabled();
+
+// Returns true if requests for |url| should be ignored by tests.
+bool IgnoreURL(const std::string& url);
+
+// Returns |timeout_ms| as scaled by the current configuration, or std::nullopt
+// if timeouts are disabled.
+std::optional<int> GetConfiguredTestTimeout(int timeout_ms);
+
+// Send a mouse click event with the necessary delay to avoid having events
+// dropped or rate limited.
+void SendMouseClickEvent(CefRefPtr<CefBrowser> browser,
+                         const CefMouseEvent& mouse_event,
+                         cef_mouse_button_type_t mouse_button_type = MBT_LEFT);
+
+// Allow |parent_url| to create popups that bypass the popup blocker. If
+// |parent_url| is empty the default value will be configured. This method only
+// applies for the Chrome runtime.
+void GrantPopupPermission(CefRefPtr<CefRequestContext> request_context,
+                          const std::string& parent_url);
+
+// Create a CefRequestContext object matching the specified |mode|. |cache_path|
+// may be specified for CUSTOM modes. |init_callback| will be executed
+// asynchronously on the UI thread. Use the RC_TEST_GROUP_ALL macro to test all
+// valid combinations.
+using RCInitCallback = base::OnceCallback<void(CefRefPtr<CefRequestContext>)>;
+void CreateTestRequestContext(TestRequestContextMode mode,
+                              const std::string& cache_path,
+                              RCInitCallback init_callback);
+
+// Run a single test without additional test modes.
+#define RC_TEST_SINGLE(test_case_name, test_name, test_class, rc_mode,   \
+                       with_cache_path)                                  \
+  TEST(test_case_name, test_name) {                                      \
+    CefScopedTempDir scoped_temp_dir;                                    \
+    std::string cache_path;                                              \
+    if (with_cache_path) {                                               \
+      EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDirUnderPath(          \
+          CefTestSuite::GetInstance()->root_cache_path()));              \
+      cache_path = scoped_temp_dir.GetPath();                            \
+    }                                                                    \
+    CefRefPtr<test_class> handler = new test_class(rc_mode, cache_path); \
+    handler->ExecuteTest();                                              \
+    ReleaseAndWaitForDestructor(handler);                                \
+    if (!scoped_temp_dir.IsEmpty()) {                                    \
+      scoped_temp_dir.Take();                                            \
+    }                                                                    \
+  }
 
 // Helper macro for testing a single RequestContextMode value.
 // See RC_TEST_GROUP_ALL documentation for example usage.
@@ -96,7 +149,8 @@
     CefScopedTempDir scoped_temp_dir;                                  \
     std::string cache_path;                                            \
     if (with_cache_path) {                                             \
-      EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir());              \
+      EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDirUnderPath(        \
+          CefTestSuite::GetInstance()->root_cache_path()));            \
       cache_path = scoped_temp_dir.GetPath();                          \
     }                                                                  \
     CefRefPtr<test_class> handler =                                    \
@@ -104,8 +158,7 @@
     handler->ExecuteTest();                                            \
     ReleaseAndWaitForDestructor(handler);                              \
     if (!scoped_temp_dir.IsEmpty()) {                                  \
-      CefTestSuite::GetInstance()->RegisterTempDirectory(              \
-          scoped_temp_dir.Take());                                     \
+      scoped_temp_dir.Take();                                          \
     }                                                                  \
   }
 
@@ -118,17 +171,13 @@
                TEST_RC_MODE_GLOBAL, false)                                 \
   RC_TEST_BASE(test_case_name, test_name##RCGlobalWithHandler, test_class, \
                test_mode, TEST_RC_MODE_GLOBAL_WITH_HANDLER, false)         \
-  RC_TEST_BASE(test_case_name, test_name##RCCustomInMemory, test_class,    \
-               test_mode, TEST_RC_MODE_CUSTOM, false)                      \
   RC_TEST_BASE(test_case_name, test_name##RCCustomInMemoryWithHandler,     \
                test_class, test_mode, TEST_RC_MODE_CUSTOM_WITH_HANDLER, false)
 
 // RequestContextModes that operate on disk.
-#define RC_TEST_GROUP_ON_DISK(test_case_name, test_name, test_class,  \
-                              test_mode)                              \
-  RC_TEST_BASE(test_case_name, test_name##RCCustomOnDisk, test_class, \
-               test_mode, TEST_RC_MODE_CUSTOM, true)                  \
-  RC_TEST_BASE(test_case_name, test_name##RCCustomOnDiskWithHandler,  \
+#define RC_TEST_GROUP_ON_DISK(test_case_name, test_name, test_class, \
+                              test_mode)                             \
+  RC_TEST_BASE(test_case_name, test_name##RCCustomOnDiskWithHandler, \
                test_class, test_mode, TEST_RC_MODE_CUSTOM_WITH_HANDLER, true)
 
 // Helper macro for testing all valid combinations of RequestContextMode values.
@@ -152,9 +201,11 @@
 //
 //     void RunTest() override {
 //        // Create a RequestContext with the specified attributes.
-//        CefRefPtr<CefRequestContext> request_context =
-//            CreateTestRequestContext(rc_mode_, rc_cache_path_);
+//        CreateTestRequestContext(rc_mode_, rc_cache_path_,
+//            base::BindOnce(&MyTestHandler::RunTestContinue, this));
+//     }
 //
+//     void RunTestContinue(CefRefPtr<CefRequestContext> request_context) {
 //        // Do something with |test_mode_| and |request_context|...
 //     }
 //
@@ -179,4 +230,4 @@
   RC_TEST_GROUP_IN_MEMORY(test_case_name, test_name, test_class, test_mode) \
   RC_TEST_GROUP_ON_DISK(test_case_name, test_name, test_class, test_mode)
 
-#endif  // CEF_TESTS_UNITTESTS_TEST_UTIL_H_
+#endif  // CEF_TESTS_CEFTESTS_TEST_UTIL_H_
diff --git a/src/tests/ceftests/thread_helper.cc b/src/tests/ceftests/thread_helper.cc
index dffac1b..64bd17f 100644
--- a/src/tests/ceftests/thread_helper.cc
+++ b/src/tests/ceftests/thread_helper.cc
@@ -4,49 +4,51 @@
 
 #include "tests/ceftests/thread_helper.h"
 
+#include <memory>
+
 #include "include/wrapper/cef_closure_task.h"
 
 void SignalEvent(CefRefPtr<CefWaitableEvent> event) {
   event->Signal();
 }
 
-void WaitForThread(CefThreadId thread_id, int64 delay_ms) {
+void WaitForThread(CefThreadId thread_id, int64_t delay_ms) {
   CefRefPtr<CefWaitableEvent> event =
       CefWaitableEvent::CreateWaitableEvent(true, false);
-  CefPostDelayedTask(thread_id, base::Bind(SignalEvent, event), delay_ms);
+  CefPostDelayedTask(thread_id, base::BindOnce(SignalEvent, event), delay_ms);
   event->Wait();
 }
 
-void WaitForThread(CefRefPtr<CefTaskRunner> task_runner, int64 delay_ms) {
+void WaitForThread(CefRefPtr<CefTaskRunner> task_runner, int64_t delay_ms) {
   CefRefPtr<CefWaitableEvent> event =
       CefWaitableEvent::CreateWaitableEvent(true, false);
   task_runner->PostDelayedTask(
-      CefCreateClosureTask(base::Bind(SignalEvent, event)), delay_ms);
+      CefCreateClosureTask(base::BindOnce(SignalEvent, event)), delay_ms);
   event->Wait();
 }
 
 void RunOnThread(CefThreadId thread_id,
-                 const base::Callback<void(void)>& test_impl,
+                 base::OnceClosure test_impl,
                  CefRefPtr<CefWaitableEvent> event) {
   if (!CefCurrentlyOn(thread_id)) {
-    CefPostTask(thread_id,
-                base::Bind(RunOnThread, thread_id, test_impl, event));
+    CefPostTask(thread_id, base::BindOnce(RunOnThread, thread_id,
+                                          std::move(test_impl), event));
     return;
   }
 
-  test_impl.Run();
+  std::move(test_impl).Run();
   SignalEvent(event);
 }
 
 void RunOnThreadAsync(
     CefThreadId thread_id,
-    const base::Callback<void(CefRefPtr<CefWaitableEvent>)>& test_impl,
+    base::OnceCallback<void(CefRefPtr<CefWaitableEvent>)> test_impl,
     CefRefPtr<CefWaitableEvent> event) {
   if (!CefCurrentlyOn(thread_id)) {
-    CefPostTask(thread_id,
-                base::Bind(RunOnThreadAsync, thread_id, test_impl, event));
+    CefPostTask(thread_id, base::BindOnce(RunOnThreadAsync, thread_id,
+                                          std::move(test_impl), event));
     return;
   }
 
-  test_impl.Run(event);
+  std::move(test_impl).Run(event);
 }
diff --git a/src/tests/ceftests/thread_helper.h b/src/tests/ceftests/thread_helper.h
index abc332b..3222598 100644
--- a/src/tests/ceftests/thread_helper.h
+++ b/src/tests/ceftests/thread_helper.h
@@ -2,11 +2,11 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#ifndef CEF_TESTS_UNITTESTS_THREAD_HELPER_H_
-#define CEF_TESTS_UNITTESTS_THREAD_HELPER_H_
+#ifndef CEF_TESTS_CEFTESTS_THREAD_HELPER_H_
+#define CEF_TESTS_CEFTESTS_THREAD_HELPER_H_
 #pragma once
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_task.h"
 #include "include/cef_waitable_event.h"
 
@@ -15,34 +15,35 @@
 
 // Post a task to the specified thread and wait for the task to execute as
 // indication that all previously pending tasks on that thread have completed.
-void WaitForThread(CefThreadId thread_id, int64 delay_ms = 0);
-void WaitForThread(CefRefPtr<CefTaskRunner> task_runner, int64 delay_ms = 0);
+void WaitForThread(CefThreadId thread_id, int64_t delay_ms = 0);
+void WaitForThread(CefRefPtr<CefTaskRunner> task_runner, int64_t delay_ms = 0);
 
 #define WaitForIOThread() WaitForThread(TID_IO)
 #define WaitForUIThread() WaitForThread(TID_UI)
-#define WaitForFILEThread() WaitForThread(TID_FILE)
+#define WaitForFILEThread() WaitForThread(TID_FILE_USER_VISIBLE)
 #define WaitForIOThreadWithDelay(delay_ms) WaitForThread(TID_IO, delay_ms)
 #define WaitForUIThreadWithDelay(delay_ms) WaitForThread(TID_UI, delay_ms)
-#define WaitForFILEThreadWithDelay(delay_ms) WaitForThread(TID_FILE, delay_ms)
+#define WaitForFILEThreadWithDelay(delay_ms) \
+  WaitForThread(TID_FILE_USER_VISIBLE, delay_ms)
 
 // Assert that execution is occuring on the named thread.
 #define EXPECT_UI_THREAD() EXPECT_TRUE(CefCurrentlyOn(TID_UI));
 #define EXPECT_IO_THREAD() EXPECT_TRUE(CefCurrentlyOn(TID_IO));
-#define EXPECT_FILE_THREAD() EXPECT_TRUE(CefCurrentlyOn(TID_FILE));
+#define EXPECT_FILE_THREAD() EXPECT_TRUE(CefCurrentlyOn(TID_FILE_USER_VISIBLE));
 #define EXPECT_RENDERER_THREAD() EXPECT_TRUE(CefCurrentlyOn(TID_RENDERER));
 
 // Executes |test_impl| on the specified |thread_id|. |event| will be signaled
 // once execution is complete.
 void RunOnThread(CefThreadId thread_id,
-                 const base::Callback<void(void)>& test_impl,
+                 base::OnceClosure test_impl,
                  CefRefPtr<CefWaitableEvent> event);
 
-#define NAMED_THREAD_TEST(thread_id, test_case_name, test_name) \
-  TEST(test_case_name, test_name) {                             \
-    CefRefPtr<CefWaitableEvent> event =                         \
-        CefWaitableEvent::CreateWaitableEvent(true, false);     \
-    RunOnThread(thread_id, base::Bind(test_name##Impl), event); \
-    event->Wait();                                              \
+#define NAMED_THREAD_TEST(thread_id, test_case_name, test_name)     \
+  TEST(test_case_name, test_name) {                                 \
+    CefRefPtr<CefWaitableEvent> event =                             \
+        CefWaitableEvent::CreateWaitableEvent(true, false);         \
+    RunOnThread(thread_id, base::BindOnce(test_name##Impl), event); \
+    event->Wait();                                                  \
   }
 
 // Execute "test_case_name.test_name" test on the named thread. The test
@@ -53,15 +54,15 @@
 // Like RunOnThread() but |test_impl| is responsible for signaling |event|.
 void RunOnThreadAsync(
     CefThreadId thread_id,
-    const base::Callback<void(CefRefPtr<CefWaitableEvent>)>& test_impl,
+    base::OnceCallback<void(CefRefPtr<CefWaitableEvent>)> test_impl,
     CefRefPtr<CefWaitableEvent>);
 
-#define NAMED_THREAD_TEST_ASYNC(thread_id, test_case_name, test_name) \
-  TEST(test_case_name, test_name) {                                   \
-    CefRefPtr<CefWaitableEvent> event =                               \
-        CefWaitableEvent::CreateWaitableEvent(true, false);           \
-    RunOnThreadAsync(thread_id, base::Bind(test_name##Impl), event);  \
-    event->Wait();                                                    \
+#define NAMED_THREAD_TEST_ASYNC(thread_id, test_case_name, test_name)    \
+  TEST(test_case_name, test_name) {                                      \
+    CefRefPtr<CefWaitableEvent> event =                                  \
+        CefWaitableEvent::CreateWaitableEvent(true, false);              \
+    RunOnThreadAsync(thread_id, base::BindOnce(test_name##Impl), event); \
+    event->Wait();                                                       \
   }
 
 // Execute "test_case_name.test_name" test on the named thread. The test
@@ -69,4 +70,4 @@
 #define UI_THREAD_TEST_ASYNC(test_case_name, test_name) \
   NAMED_THREAD_TEST_ASYNC(TID_UI, test_case_name, test_name)
 
-#endif  // CEF_TESTS_UNITTESTS_THREAD_HELPER_H_
+#endif  // CEF_TESTS_CEFTESTS_THREAD_HELPER_H_
diff --git a/src/tests/ceftests/thread_unittest.cc b/src/tests/ceftests/thread_unittest.cc
index db23909..51acc6b 100644
--- a/src/tests/ceftests/thread_unittest.cc
+++ b/src/tests/ceftests/thread_unittest.cc
@@ -2,7 +2,8 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
+#include "include/base/cef_callback_helpers.h"
 #include "include/cef_task.h"
 #include "include/cef_thread.h"
 #include "include/wrapper/cef_closure_task.h"
@@ -60,13 +61,13 @@
   // Execute |test_task| on the test thread. After execution |callback| will be
   // posted to |callback_task_runner|.
   void PostOnTestThreadAndCallback(
-      const base::Closure& test_task,
+      base::OnceClosure test_task,
       CefRefPtr<CefTaskRunner> callback_task_runner,
-      const base::Closure& callback) {
+      base::OnceClosure callback) {
     EXPECT_TRUE(thread_.get());
-    thread_task_runner_->PostTask(CefCreateClosureTask(
-        base::Bind(&ThreadTest::ExecuteOnTestThread, this, test_task,
-                   callback_task_runner, callback)));
+    thread_task_runner_->PostTask(CefCreateClosureTask(base::BindOnce(
+        &ThreadTest::ExecuteOnTestThread, this, std::move(test_task),
+        callback_task_runner, std::move(callback))));
   }
 
   CefRefPtr<CefTaskRunner> owner_task_runner() const {
@@ -94,14 +95,14 @@
 
  private:
   // Helper for PostOnTestThreadAndCallback().
-  void ExecuteOnTestThread(const base::Closure& test_task,
+  void ExecuteOnTestThread(base::OnceClosure test_task,
                            CefRefPtr<CefTaskRunner> callback_task_runner,
-                           const base::Closure& callback) {
+                           base::OnceClosure callback) {
     AssertTestThread();
 
-    test_task.Run();
+    std::move(test_task).Run();
 
-    callback_task_runner->PostTask(CefCreateClosureTask(callback));
+    callback_task_runner->PostTask(CefCreateClosureTask(std::move(callback)));
   }
 
   CefRefPtr<CefTaskRunner> owner_task_runner_;
@@ -130,11 +131,11 @@
 class SimpleThreadTest : public ThreadTest {
  public:
   SimpleThreadTest(size_t expected_task_count,
-                   const base::Closure& task_callback,
-                   const base::Closure& done_callback)
+                   base::OnceClosure task_callback,
+                   base::OnceClosure done_callback)
       : expected_task_count_(expected_task_count),
-        task_callback_(task_callback),
-        done_callback_(done_callback),
+        task_callback_(std::move(task_callback)),
+        done_callback_(std::move(done_callback)),
         got_task_count_(0U),
         got_done_count_(0U) {}
 
@@ -144,9 +145,9 @@
 
     for (size_t i = 0U; i < expected_task_count_; ++i) {
       // Execute Task() on the test thread and then call Done() on this thread.
-      PostOnTestThreadAndCallback(base::Bind(&SimpleThreadTest::Task, this),
-                                  owner_task_runner(),
-                                  base::Bind(&SimpleThreadTest::Done, this));
+      PostOnTestThreadAndCallback(
+          base::BindOnce(&SimpleThreadTest::Task, this), owner_task_runner(),
+          base::BindOnce(&SimpleThreadTest::Done, this));
     }
   }
 
@@ -162,19 +163,22 @@
   void Task() {
     AssertTestThread();
     got_task_count_++;
-    if (!task_callback_.is_null())
-      task_callback_.Run();
+    if (!task_callback_.is_null()) {
+      std::move(task_callback_).Run();
+    }
   }
 
   void Done() {
     AssertOwnerThread();
-    if (++got_done_count_ == expected_task_count_ && !done_callback_.is_null())
-      done_callback_.Run();
+    if (++got_done_count_ == expected_task_count_ &&
+        !done_callback_.is_null()) {
+      std::move(done_callback_).Run();
+    }
   }
 
   const size_t expected_task_count_;
-  base::Closure task_callback_;
-  base::Closure done_callback_;
+  base::OnceClosure task_callback_;
+  base::OnceClosure done_callback_;
 
   size_t got_task_count_;
   size_t got_done_count_;
@@ -184,7 +188,7 @@
 
 // Test creation/execution of threads in the browser process.
 
-const char kBrowserThreadTestHtml[] = "http://test.com/browserthread.html";
+const char kBrowserThreadTestHtml[] = "https://test.com/browserthread.html";
 
 // Browser side.
 class BrowserThreadTestHandler : public TestHandler {
@@ -207,23 +211,23 @@
       // Run the test on the desired owner thread.
       CefPostTask(
           owner_thread_id_,
-          base::Bind(&BrowserThreadTestHandler::RunThreadTestOnOwnerThread,
-                     this));
+          base::BindOnce(&BrowserThreadTestHandler::RunThreadTestOnOwnerThread,
+                         this));
       return;
     }
 
     EXPECT_FALSE(thread_test_.get());
     thread_test_ = new SimpleThreadTest(
-        3, base::Closure(),
-        base::Bind(&BrowserThreadTestHandler::DoneOnOwnerThread, this));
+        3, base::DoNothing(),
+        base::BindOnce(&BrowserThreadTestHandler::DoneOnOwnerThread, this));
     thread_test_->RunTest();
   }
 
   void DoneOnOwnerThread() {
     // Let the call stack unwind before destroying |thread_test_|.
-    CefPostTask(
-        owner_thread_id_,
-        base::Bind(&BrowserThreadTestHandler::DestroyTestOnOwnerThread, this));
+    CefPostTask(owner_thread_id_,
+                base::BindOnce(
+                    &BrowserThreadTestHandler::DestroyTestOnOwnerThread, this));
   }
 
   void DestroyTestOnOwnerThread() {
@@ -239,15 +243,16 @@
 
     // Call DestroyTest() on the UI thread.
     CefPostTask(TID_UI,
-                base::Bind(&BrowserThreadTestHandler::DestroyTest, this));
+                base::BindOnce(&BrowserThreadTestHandler::DestroyTest, this));
   }
 
   void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
                             bool isLoading,
                             bool canGoBack,
                             bool canGoForward) override {
-    if (!isLoading)
+    if (!isLoading) {
       RunThreadTestOnOwnerThread();
+    }
   }
 
  private:
@@ -287,8 +292,9 @@
 
 // Test creation of new threads from the browser FILE thread.
 TEST(ThreadTest, CreateFromBrowserFILEThread) {
+  // Use a FILE thread that will run tasks relatively quickly.
   CefRefPtr<BrowserThreadTestHandler> handler =
-      new BrowserThreadTestHandler(TID_FILE);
+      new BrowserThreadTestHandler(TID_FILE_USER_VISIBLE);
   handler->ExecuteTest();
   ReleaseAndWaitForDestructor(handler);
 }
@@ -297,7 +303,7 @@
 
 // Test creation/execution of threads in the render process.
 
-const char kRenderThreadTestHtml[] = "http://test.com/renderthread.html";
+const char kRenderThreadTestHtml[] = "https://test.com/renderthread.html";
 const char kRenderThreadTestMsg[] = "ThreadTest.RenderThreadTest";
 
 // Browser side.
@@ -342,8 +348,9 @@
 
     got_message_.yes();
 
-    if (message->GetArgumentList()->GetBool(0))
+    if (message->GetArgumentList()->GetBool(0)) {
       got_success_.yes();
+    }
 
     // Test is complete.
     DestroyTest();
@@ -380,8 +387,8 @@
       browser_ = browser;
       EXPECT_FALSE(thread_test_.get());
       thread_test_ = new SimpleThreadTest(
-          3, base::Closure(),
-          base::Bind(&RenderThreadRendererTest::Done, this));
+          3, base::DoNothing(),
+          base::BindOnce(&RenderThreadRendererTest::Done, this));
       thread_test_->RunTest();
       return true;
     }
@@ -394,7 +401,7 @@
   void Done() {
     // Let the call stack unwind before destroying |thread_test_|.
     CefPostTask(TID_RENDERER,
-                base::Bind(&RenderThreadRendererTest::DestroyTest, this));
+                base::BindOnce(&RenderThreadRendererTest::DestroyTest, this));
   }
 
   void DestroyTest() {
diff --git a/src/tests/ceftests/time_unittest.cc b/src/tests/ceftests/time_unittest.cc
new file mode 100644
index 0000000..e604972
--- /dev/null
+++ b/src/tests/ceftests/time_unittest.cc
@@ -0,0 +1,85 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "include/internal/cef_time_wrappers.h"
+#include "tests/gtest/include/gtest/gtest.h"
+
+TEST(TimeTest, Now) {
+  // Sanity check, what it returns something.
+  cef_basetime_t now = cef_basetime_now();
+  EXPECT_NE(now.val, 0);
+}
+
+TEST(TimeTest, TimeToBaseTime) {
+  // Choosing some date which should be always representable on any platform.
+  cef_time_t date{};
+  date.year = 2001;
+  date.month = 2;
+  date.day_of_week = 1;
+  date.day_of_month = 5;
+  date.hour = 6;
+  date.minute = 7;
+  date.second = 8;
+  date.millisecond = 9;
+
+  cef_basetime_t basetime{};
+
+  // Null parameter handling.
+  ASSERT_FALSE(cef_time_to_basetime(nullptr, nullptr));
+  ASSERT_FALSE(cef_time_to_basetime(&date, nullptr));
+  ASSERT_FALSE(cef_time_to_basetime(nullptr, &basetime));
+
+  ASSERT_TRUE(cef_time_to_basetime(&date, &basetime));
+  ASSERT_EQ(basetime.val, 12625826828009000);
+}
+
+TEST(TimeTest, BaseTimeToTime) {
+  cef_basetime_t basetime{12625826828009000};
+
+  // Choosing some date which should be always representable on any platform.
+  cef_time_t date{};
+
+  ASSERT_TRUE(cef_time_from_basetime(basetime, &date) != 0);
+
+  EXPECT_EQ(date.year, 2001);
+  EXPECT_EQ(date.month, 2);
+  EXPECT_EQ(date.day_of_week, 1);
+  EXPECT_EQ(date.day_of_month, 5);
+  EXPECT_EQ(date.hour, 6);
+  EXPECT_EQ(date.minute, 7);
+  EXPECT_EQ(date.second, 8);
+  EXPECT_EQ(date.millisecond, 9);
+}
+
+TEST(TimeTest, InvalidTimeToBaseTime) {
+  // Some time which can't be represented
+  cef_time_t date{};
+  date.year = 90000;
+  cef_basetime_t basetime{999999999};
+
+  ASSERT_FALSE(cef_time_to_basetime(&date, &basetime) != 0);
+  ASSERT_EQ(basetime.val, 0);  // Output should always be set.
+}
+
+// Only run on Windows because POSIX supports a wider range of dates.
+#if defined(OS_WIN)
+TEST(TimeTest, InvalidBaseTimeToTime) {
+  // Unrepresentable.
+  cef_basetime_t basetime{std::numeric_limits<int64_t>::max()};
+  cef_time_t date{};
+  date.year = 999999999;
+
+  ASSERT_FALSE(cef_time_from_basetime(basetime, &date) != 0);
+
+  // Output should always be set.
+  EXPECT_EQ(date.year, 0);
+  EXPECT_EQ(date.month, 0);
+  EXPECT_EQ(date.day_of_week, 0);
+  EXPECT_EQ(date.day_of_month, 0);
+  EXPECT_EQ(date.hour, 0);
+  EXPECT_EQ(date.minute, 0);
+  EXPECT_EQ(date.second, 0);
+  EXPECT_EQ(date.millisecond, 0);
+}
+#endif  // defined(OS_WIN)
diff --git a/src/tests/ceftests/tracing_unittest.cc b/src/tests/ceftests/tracing_unittest.cc
index caa3942..347d951 100644
--- a/src/tests/ceftests/tracing_unittest.cc
+++ b/src/tests/ceftests/tracing_unittest.cc
@@ -2,7 +2,7 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_file_util.h"
 #include "include/cef_task.h"
 #include "include/cef_trace.h"
@@ -23,49 +23,26 @@
   TT_TRACE_EVENT_INSTANT0,
   TT_TRACE_EVENT_INSTANT1,
   TT_TRACE_EVENT_INSTANT2,
-  TT_TRACE_EVENT_COPY_INSTANT0,
-  TT_TRACE_EVENT_COPY_INSTANT1,
-  TT_TRACE_EVENT_COPY_INSTANT2,
   TT_TRACE_EVENT_BEGIN0,
   TT_TRACE_EVENT_BEGIN1,
   TT_TRACE_EVENT_BEGIN2,
-  TT_TRACE_EVENT_COPY_BEGIN0,
-  TT_TRACE_EVENT_COPY_BEGIN1,
-  TT_TRACE_EVENT_COPY_BEGIN2,
   TT_TRACE_EVENT_END0,
   TT_TRACE_EVENT_END1,
   TT_TRACE_EVENT_END2,
-  TT_TRACE_EVENT_COPY_END0,
-  TT_TRACE_EVENT_COPY_END1,
-  TT_TRACE_EVENT_COPY_END2,
   TT_TRACE_COUNTER1,
-  TT_TRACE_COPY_COUNTER1,
   TT_TRACE_COUNTER2,
-  TT_TRACE_COPY_COUNTER2,
   TT_TRACE_COUNTER_ID1,
-  TT_TRACE_COPY_COUNTER_ID1,
   TT_TRACE_COUNTER_ID2,
-  TT_TRACE_COPY_COUNTER_ID2,
   TT_TRACE_EVENT_ASYNC_BEGIN0,
   TT_TRACE_EVENT_ASYNC_BEGIN1,
   TT_TRACE_EVENT_ASYNC_BEGIN2,
-  TT_TRACE_EVENT_COPY_ASYNC_BEGIN0,
-  TT_TRACE_EVENT_COPY_ASYNC_BEGIN1,
-  TT_TRACE_EVENT_COPY_ASYNC_BEGIN2,
   TT_TRACE_EVENT_ASYNC_STEP_INTO0,
   TT_TRACE_EVENT_ASYNC_STEP_INTO1,
-  TT_TRACE_EVENT_COPY_ASYNC_STEP_INTO0,
-  TT_TRACE_EVENT_COPY_ASYNC_STEP_INTO1,
   TT_TRACE_EVENT_ASYNC_STEP_PAST0,
   TT_TRACE_EVENT_ASYNC_STEP_PAST1,
-  TT_TRACE_EVENT_COPY_ASYNC_STEP_PAST0,
-  TT_TRACE_EVENT_COPY_ASYNC_STEP_PAST1,
   TT_TRACE_EVENT_ASYNC_END0,
   TT_TRACE_EVENT_ASYNC_END1,
   TT_TRACE_EVENT_ASYNC_END2,
-  TT_TRACE_EVENT_COPY_ASYNC_END0,
-  TT_TRACE_EVENT_COPY_ASYNC_END1,
-  TT_TRACE_EVENT_COPY_ASYNC_END2
 };
 
 const char kTraceTestCategory[] = "cef.client";
@@ -80,7 +57,8 @@
 
   void ExecuteTest() {
     // Run the test.
-    CefPostTask(TID_UI, base::Bind(&TracingTestHandler::BeginTracing, this));
+    CefPostTask(TID_UI,
+                base::BindOnce(&TracingTestHandler::BeginTracing, this));
 
     // Wait for the test to complete.
     completion_event_->Wait();
@@ -102,8 +80,8 @@
     EXPECT_UI_THREAD();
 
     // Add some delay to avoid timing-related test failures.
-    CefPostDelayedTask(TID_UI,
-                       base::Bind(&TracingTestHandler::TestTracing, this), 50);
+    CefPostDelayedTask(
+        TID_UI, base::BindOnce(&TracingTestHandler::TestTracing, this), 50);
   }
 
   void TestTracing() {
@@ -131,19 +109,6 @@
         TRACE_EVENT_INSTANT2(kTraceTestCategory, "TT_TRACE_EVENT_INSTANT2",
                              "arg1", 1, "arg2", 2);
         break;
-      case TT_TRACE_EVENT_COPY_INSTANT0:
-        TRACE_EVENT_COPY_INSTANT0(kTraceTestCategory,
-                                  "TT_TRACE_EVENT_COPY_INSTANT0");
-        break;
-      case TT_TRACE_EVENT_COPY_INSTANT1:
-        TRACE_EVENT_COPY_INSTANT1(kTraceTestCategory,
-                                  "TT_TRACE_EVENT_COPY_INSTANT1", "arg1", 1);
-        break;
-      case TT_TRACE_EVENT_COPY_INSTANT2:
-        TRACE_EVENT_COPY_INSTANT2(kTraceTestCategory,
-                                  "TT_TRACE_EVENT_COPY_INSTANT2", "arg1", 1,
-                                  "arg2", 2);
-        break;
       case TT_TRACE_EVENT_BEGIN0:
         TRACE_EVENT_BEGIN0(kTraceTestCategory, "TT_TRACE_EVENT_BEGIN0");
         break;
@@ -155,19 +120,6 @@
         TRACE_EVENT_BEGIN2(kTraceTestCategory, "TT_TRACE_EVENT_BEGIN2", "arg1",
                            1, "arg2", 2);
         break;
-      case TT_TRACE_EVENT_COPY_BEGIN0:
-        TRACE_EVENT_COPY_BEGIN0(kTraceTestCategory,
-                                "TT_TRACE_EVENT_COPY_BEGIN0");
-        break;
-      case TT_TRACE_EVENT_COPY_BEGIN1:
-        TRACE_EVENT_COPY_BEGIN1(kTraceTestCategory,
-                                "TT_TRACE_EVENT_COPY_BEGIN1", "arg1", 1);
-        break;
-      case TT_TRACE_EVENT_COPY_BEGIN2:
-        TRACE_EVENT_COPY_BEGIN2(kTraceTestCategory,
-                                "TT_TRACE_EVENT_COPY_BEGIN2", "arg1", 1, "arg2",
-                                2);
-        break;
       case TT_TRACE_EVENT_END0:
         TRACE_EVENT_BEGIN0(kTraceTestCategory, "TT_TRACE_EVENT_END0");
         TRACE_EVENT_END0(kTraceTestCategory, "TT_TRACE_EVENT_END0");
@@ -183,51 +135,20 @@
         TRACE_EVENT_END2(kTraceTestCategory, "TT_TRACE_EVENT_END2", "arg1", 1,
                          "arg2", 2);
         break;
-      case TT_TRACE_EVENT_COPY_END0:
-        TRACE_EVENT_COPY_BEGIN0(kTraceTestCategory, "TT_TRACE_EVENT_COPY_END0");
-        TRACE_EVENT_COPY_END0(kTraceTestCategory, "TT_TRACE_EVENT_COPY_END0");
-        break;
-      case TT_TRACE_EVENT_COPY_END1:
-        TRACE_EVENT_COPY_BEGIN1(kTraceTestCategory, "TT_TRACE_EVENT_COPY_END1",
-                                "arg1", 1);
-        TRACE_EVENT_COPY_END1(kTraceTestCategory, "TT_TRACE_EVENT_COPY_END1",
-                              "arg1", 1);
-        break;
-      case TT_TRACE_EVENT_COPY_END2:
-        TRACE_EVENT_COPY_BEGIN2(kTraceTestCategory, "TT_TRACE_EVENT_COPY_END2",
-                                "arg1", 1, "arg2", 2);
-        TRACE_EVENT_COPY_END2(kTraceTestCategory, "TT_TRACE_EVENT_COPY_END2",
-                              "arg1", 1, "arg2", 2);
-        break;
       case TT_TRACE_COUNTER1:
         TRACE_COUNTER1(kTraceTestCategory, "TT_TRACE_COUNTER1", 5);
         break;
-      case TT_TRACE_COPY_COUNTER1:
-        TRACE_COPY_COUNTER1(kTraceTestCategory, "TT_TRACE_COPY_COUNTER1", 5);
-        break;
       case TT_TRACE_COUNTER2:
         TRACE_COUNTER2(kTraceTestCategory, "TT_TRACE_COUNTER2", "val1", 5,
                        "val2", 10);
         break;
-      case TT_TRACE_COPY_COUNTER2:
-        TRACE_COPY_COUNTER2(kTraceTestCategory, "TT_TRACE_COPY_COUNTER2",
-                            "val1", 5, "val2", 10);
-        break;
       case TT_TRACE_COUNTER_ID1:
         TRACE_COUNTER_ID1(kTraceTestCategory, "TT_TRACE_COUNTER_ID1", 100, 5);
         break;
-      case TT_TRACE_COPY_COUNTER_ID1:
-        TRACE_COPY_COUNTER_ID1(kTraceTestCategory, "TT_TRACE_COPY_COUNTER_ID1",
-                               100, 5);
-        break;
       case TT_TRACE_COUNTER_ID2:
         TRACE_COUNTER_ID2(kTraceTestCategory, "TT_TRACE_COUNTER_ID2", 100,
                           "val1", 5, "val2", 10);
         break;
-      case TT_TRACE_COPY_COUNTER_ID2:
-        TRACE_COPY_COUNTER_ID2(kTraceTestCategory, "TT_TRACE_COPY_COUNTER_ID2",
-                               100, "val1", 5, "val2", 10);
-        break;
       case TT_TRACE_EVENT_ASYNC_BEGIN0:
         TRACE_EVENT_ASYNC_BEGIN0(kTraceTestCategory,
                                  "TT_TRACE_EVENT_ASYNC_BEGIN0", 100);
@@ -241,20 +162,6 @@
                                  "TT_TRACE_EVENT_ASYNC_BEGIN2", 100, "arg1", 1,
                                  "arg2", 2);
         break;
-      case TT_TRACE_EVENT_COPY_ASYNC_BEGIN0:
-        TRACE_EVENT_COPY_ASYNC_BEGIN0(kTraceTestCategory,
-                                      "TT_TRACE_EVENT_COPY_ASYNC_BEGIN0", 100);
-        break;
-      case TT_TRACE_EVENT_COPY_ASYNC_BEGIN1:
-        TRACE_EVENT_COPY_ASYNC_BEGIN1(kTraceTestCategory,
-                                      "TT_TRACE_EVENT_COPY_ASYNC_BEGIN1", 100,
-                                      "arg1", 1);
-        break;
-      case TT_TRACE_EVENT_COPY_ASYNC_BEGIN2:
-        TRACE_EVENT_COPY_ASYNC_BEGIN2(kTraceTestCategory,
-                                      "TT_TRACE_EVENT_COPY_ASYNC_BEGIN2", 100,
-                                      "arg1", 1, "arg2", 2);
-        break;
       case TT_TRACE_EVENT_ASYNC_STEP_INTO0:
         TRACE_EVENT_ASYNC_STEP_INTO0(
             kTraceTestCategory, "TT_TRACE_EVENT_ASYNC_STEP_INTO0", 100, 1000);
@@ -264,16 +171,6 @@
                                      "TT_TRACE_EVENT_ASYNC_STEP_INTO1", 100,
                                      1000, "arg1", 1);
         break;
-      case TT_TRACE_EVENT_COPY_ASYNC_STEP_INTO0:
-        TRACE_EVENT_COPY_ASYNC_STEP_INTO0(
-            kTraceTestCategory, "TT_TRACE_EVENT_COPY_ASYNC_STEP_INTO0", 100,
-            1000);
-        break;
-      case TT_TRACE_EVENT_COPY_ASYNC_STEP_INTO1:
-        TRACE_EVENT_COPY_ASYNC_STEP_INTO1(
-            kTraceTestCategory, "TT_TRACE_EVENT_COPY_ASYNC_STEP_INTO1", 100,
-            1000, "arg1", 1);
-        break;
       case TT_TRACE_EVENT_ASYNC_STEP_PAST0:
         TRACE_EVENT_ASYNC_STEP_PAST0(
             kTraceTestCategory, "TT_TRACE_EVENT_ASYNC_STEP_PAST0", 100, 1000);
@@ -283,42 +180,25 @@
                                      "TT_TRACE_EVENT_ASYNC_STEP_PAST1", 100,
                                      1000, "arg1", 1);
         break;
-      case TT_TRACE_EVENT_COPY_ASYNC_STEP_PAST0:
-        TRACE_EVENT_COPY_ASYNC_STEP_PAST0(
-            kTraceTestCategory, "TT_TRACE_EVENT_COPY_ASYNC_STEP_PAST0", 100,
-            1000);
-        break;
-      case TT_TRACE_EVENT_COPY_ASYNC_STEP_PAST1:
-        TRACE_EVENT_COPY_ASYNC_STEP_PAST1(
-            kTraceTestCategory, "TT_TRACE_EVENT_COPY_ASYNC_STEP_PAST1", 100,
-            1000, "arg1", 1);
-        break;
       case TT_TRACE_EVENT_ASYNC_END0:
+        TRACE_EVENT_ASYNC_BEGIN0(kTraceTestCategory,
+                                 "TT_TRACE_EVENT_ASYNC_END0", 100);
         TRACE_EVENT_ASYNC_END0(kTraceTestCategory, "TT_TRACE_EVENT_ASYNC_END0",
                                100);
         break;
       case TT_TRACE_EVENT_ASYNC_END1:
+        TRACE_EVENT_ASYNC_BEGIN1(kTraceTestCategory,
+                                 "TT_TRACE_EVENT_ASYNC_END1", 100, "arg1", 1);
         TRACE_EVENT_ASYNC_END1(kTraceTestCategory, "TT_TRACE_EVENT_ASYNC_END1",
                                100, "arg1", 1);
         break;
       case TT_TRACE_EVENT_ASYNC_END2:
+        TRACE_EVENT_ASYNC_BEGIN2(kTraceTestCategory,
+                                 "TT_TRACE_EVENT_ASYNC_END2", 100, "arg1", 1,
+                                 "arg2", 2);
         TRACE_EVENT_ASYNC_END2(kTraceTestCategory, "TT_TRACE_EVENT_ASYNC_END2",
                                100, "arg1", 1, "arg2", 2);
         break;
-      case TT_TRACE_EVENT_COPY_ASYNC_END0:
-        TRACE_EVENT_COPY_ASYNC_END0(kTraceTestCategory,
-                                    "TT_TRACE_EVENT_COPY_ASYNC_END0", 100);
-        break;
-      case TT_TRACE_EVENT_COPY_ASYNC_END1:
-        TRACE_EVENT_COPY_ASYNC_END1(kTraceTestCategory,
-                                    "TT_TRACE_EVENT_COPY_ASYNC_END1", 100,
-                                    "arg1", 1);
-        break;
-      case TT_TRACE_EVENT_COPY_ASYNC_END2:
-        TRACE_EVENT_COPY_ASYNC_END2(kTraceTestCategory,
-                                    "TT_TRACE_EVENT_COPY_ASYNC_END2", 100,
-                                    "arg1", 1, "arg2", 2);
-        break;
     }
 
     // Results in a call to OnEndTracingComplete.
@@ -328,8 +208,9 @@
   void OnEndTracingComplete(const CefString& tracing_file) override {
     EXPECT_UI_THREAD();
 
-    CefPostTask(TID_FILE, base::Bind(&TracingTestHandler::ReadTracingFile, this,
-                                     tracing_file));
+    CefPostTask(TID_FILE_USER_VISIBLE,
+                base::BindOnce(&TracingTestHandler::ReadTracingFile, this,
+                               tracing_file));
   }
 
   void ReadTracingFile(const std::string& file_path) {
@@ -369,49 +250,28 @@
 TRACING_TEST(TraceEventInstant0, TT_TRACE_EVENT_INSTANT0)
 TRACING_TEST(TraceEventInstant1, TT_TRACE_EVENT_INSTANT1)
 TRACING_TEST(TraceEventInstant2, TT_TRACE_EVENT_INSTANT2)
-TRACING_TEST(TraceEventCopyInstant0, TT_TRACE_EVENT_COPY_INSTANT0)
-TRACING_TEST(TraceEventCopyInstant1, TT_TRACE_EVENT_COPY_INSTANT1)
-TRACING_TEST(TraceEventCopyInstant2, TT_TRACE_EVENT_COPY_INSTANT2)
 TRACING_TEST(TraceEventBegin0, TT_TRACE_EVENT_BEGIN0)
 TRACING_TEST(TraceEventBegin1, TT_TRACE_EVENT_BEGIN1)
 TRACING_TEST(TraceEventBegin2, TT_TRACE_EVENT_BEGIN2)
-TRACING_TEST(TraceEventCopyBegin0, TT_TRACE_EVENT_COPY_BEGIN0)
-TRACING_TEST(TraceEventCopyBegin1, TT_TRACE_EVENT_COPY_BEGIN1)
-TRACING_TEST(TraceEventCopyBegin2, TT_TRACE_EVENT_COPY_BEGIN2)
 TRACING_TEST(TraceEventEnd0, TT_TRACE_EVENT_END0)
 TRACING_TEST(TraceEventEnd1, TT_TRACE_EVENT_END1)
 TRACING_TEST(TraceEventEnd2, TT_TRACE_EVENT_END2)
-TRACING_TEST(TraceEventCopyEnd0, TT_TRACE_EVENT_COPY_END0)
-TRACING_TEST(TraceEventCopyEnd1, TT_TRACE_EVENT_COPY_END1)
-TRACING_TEST(TraceEventCopyEnd2, TT_TRACE_EVENT_COPY_END1)
 TRACING_TEST(TraceCounter1, TT_TRACE_COUNTER1)
-TRACING_TEST(TraceCopyCounter1, TT_TRACE_COPY_COUNTER1)
 TRACING_TEST(TraceCounter2, TT_TRACE_COUNTER2)
-TRACING_TEST(TraceCopyCounter2, TT_TRACE_COPY_COUNTER2)
 TRACING_TEST(TraceCounterId1, TT_TRACE_COUNTER_ID1)
-TRACING_TEST(TraceCopyCounterId1, TT_TRACE_COPY_COUNTER_ID1)
 TRACING_TEST(TraceCounterId2, TT_TRACE_COUNTER_ID2)
-TRACING_TEST(TraceCopyCounterId2, TT_TRACE_COPY_COUNTER_ID1)
 TRACING_TEST(TraceEventAsyncBegin0, TT_TRACE_EVENT_ASYNC_BEGIN0)
 TRACING_TEST(TraceEventAsyncBegin1, TT_TRACE_EVENT_ASYNC_BEGIN1)
 TRACING_TEST(TraceEventAsyncBegin2, TT_TRACE_EVENT_ASYNC_BEGIN2)
-TRACING_TEST(TraceEventCopyAsyncBegin0, TT_TRACE_EVENT_COPY_ASYNC_BEGIN0)
-TRACING_TEST(TraceEventCopyAsyncBegin1, TT_TRACE_EVENT_COPY_ASYNC_BEGIN1)
-TRACING_TEST(TraceEventCopyAsyncBegin2, TT_TRACE_EVENT_COPY_ASYNC_BEGIN2)
 TRACING_TEST(TraceEventAsyncStepInto0, TT_TRACE_EVENT_ASYNC_STEP_INTO0)
 TRACING_TEST(TraceEventAsyncStepInto1, TT_TRACE_EVENT_ASYNC_STEP_INTO1)
-TRACING_TEST(TraceEventCopyAsyncStepInto0, TT_TRACE_EVENT_COPY_ASYNC_STEP_INTO0)
-TRACING_TEST(TraceEventCopyAsyncStepInto1, TT_TRACE_EVENT_COPY_ASYNC_STEP_INTO1)
 TRACING_TEST(TraceEventAsyncStepPast0, TT_TRACE_EVENT_ASYNC_STEP_PAST0)
 TRACING_TEST(TraceEventAsyncStepPast1, TT_TRACE_EVENT_ASYNC_STEP_PAST1)
-TRACING_TEST(TraceEventCopyAsyncStepPast0, TT_TRACE_EVENT_COPY_ASYNC_STEP_PAST0)
-TRACING_TEST(TraceEventCopyAsyncStepPast1, TT_TRACE_EVENT_COPY_ASYNC_STEP_PAST1)
 TRACING_TEST(TraceEventAsyncEnd0, TT_TRACE_EVENT_ASYNC_END0)
 TRACING_TEST(TraceEventAsyncEnd1, TT_TRACE_EVENT_ASYNC_END1)
 TRACING_TEST(TraceEventAsyncEnd2, TT_TRACE_EVENT_ASYNC_END2)
-TRACING_TEST(TraceEventCopyAsyncEnd0, TT_TRACE_EVENT_COPY_ASYNC_END0)
 
 TEST(TracingTest, NowFromSystemTraceTime) {
-  int64 val = CefNowFromSystemTraceTime();
+  int64_t val = CefNowFromSystemTraceTime();
   EXPECT_NE(val, 0);
 }
diff --git a/src/tests/ceftests/track_callback.h b/src/tests/ceftests/track_callback.h
new file mode 100644
index 0000000..7601302
--- /dev/null
+++ b/src/tests/ceftests/track_callback.h
@@ -0,0 +1,21 @@
+// Copyright (c) 2013 The Chromium Embedded Framework 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 CEF_TESTS_CEFTESTS_TRACK_CALLBACK_H_
+#define CEF_TESTS_CEFTESTS_TRACK_CALLBACK_H_
+#pragma once
+
+class TrackCallback {
+ public:
+  TrackCallback() : gotit_(false) {}
+  void yes() { gotit_ = true; }
+  bool isSet() { return gotit_; }
+  void reset() { gotit_ = false; }
+  operator bool() const { return gotit_; }
+
+ protected:
+  bool gotit_;
+};
+
+#endif  // CEF_TESTS_CEFTESTS_TRACK_CALLBACK_H_
diff --git a/src/tests/ceftests/translator_unittest.cc b/src/tests/ceftests/translator_unittest.cc
index b039cbc..12e05ec 100644
--- a/src/tests/ceftests/translator_unittest.cc
+++ b/src/tests/ceftests/translator_unittest.cc
@@ -394,7 +394,7 @@
       CefTranslatorTestScopedLibrary::Create(kTestVal);
   EXPECT_TRUE(test_obj.get());
   EXPECT_EQ(kTestVal, test_obj->GetValue());
-  int retval = obj->SetOwnPtrLibrary(test_obj.Pass());
+  int retval = obj->SetOwnPtrLibrary(std::move(test_obj));
   EXPECT_EQ(kTestVal, retval);
   EXPECT_FALSE(test_obj.get());
 
@@ -403,7 +403,7 @@
       obj->GetOwnPtrLibrary(kTestVal2);
   EXPECT_TRUE(test_obj2.get());
   EXPECT_EQ(kTestVal2, test_obj2->GetValue());
-  int retval2 = obj->SetOwnPtrLibrary(test_obj2.Pass());
+  int retval2 = obj->SetOwnPtrLibrary(std::move(test_obj2));
   EXPECT_EQ(kTestVal2, retval2);
   EXPECT_FALSE(test_obj2.get());
 
@@ -422,20 +422,19 @@
   EXPECT_TRUE(test_obj.get());
   EXPECT_EQ(kTestVal, test_obj->GetValue());
   EXPECT_EQ(kTestVal2, test_obj->GetOtherValue());
-  int retval =
-      obj->SetOwnPtrLibrary(test_obj.PassAs<CefTranslatorTestScopedLibrary>());
+  int retval = obj->SetOwnPtrLibrary(std::move(test_obj));
   EXPECT_EQ(kTestVal, retval);
   EXPECT_FALSE(test_obj.get());
 
   test_obj = CefTranslatorTestScopedLibraryChild::Create(kTestVal, kTestVal2);
   EXPECT_TRUE(test_obj.get());
-  EXPECT_EQ(kTestVal, obj->SetChildOwnPtrLibrary(test_obj.Pass()));
+  EXPECT_EQ(kTestVal, obj->SetChildOwnPtrLibrary(std::move(test_obj)));
   EXPECT_FALSE(test_obj.get());
 
   test_obj = CefTranslatorTestScopedLibraryChild::Create(kTestVal, kTestVal2);
   EXPECT_TRUE(test_obj.get());
   CefOwnPtr<CefTranslatorTestScopedLibrary> test_obj_parent =
-      obj->SetChildOwnPtrLibraryAndReturnParent(test_obj.Pass());
+      obj->SetChildOwnPtrLibraryAndReturnParent(std::move(test_obj));
   EXPECT_FALSE(test_obj.get());
   EXPECT_TRUE(test_obj_parent.get());
   EXPECT_EQ(kTestVal, test_obj_parent->GetValue());
@@ -448,22 +447,19 @@
   EXPECT_EQ(kTestVal, test_obj2->GetValue());
   EXPECT_EQ(kTestVal2, test_obj2->GetOtherValue());
   EXPECT_EQ(kTestVal3, test_obj2->GetOtherOtherValue());
-  int retval2 =
-      obj->SetOwnPtrLibrary(test_obj2.PassAs<CefTranslatorTestScopedLibrary>());
+  int retval2 = obj->SetOwnPtrLibrary(std::move(test_obj2));
   EXPECT_EQ(kTestVal, retval2);
   EXPECT_FALSE(test_obj2.get());
 
   test_obj2 = CefTranslatorTestScopedLibraryChildChild::Create(
       kTestVal, kTestVal2, kTestVal3);
-  EXPECT_EQ(kTestVal,
-            obj->SetChildOwnPtrLibrary(
-                test_obj2.PassAs<CefTranslatorTestScopedLibraryChild>()));
+  EXPECT_EQ(kTestVal, obj->SetChildOwnPtrLibrary(std::move(test_obj2)));
   EXPECT_FALSE(test_obj2.get());
 
   test_obj2 = CefTranslatorTestScopedLibraryChildChild::Create(
       kTestVal, kTestVal2, kTestVal3);
-  test_obj_parent = obj->SetChildOwnPtrLibraryAndReturnParent(
-      test_obj2.PassAs<CefTranslatorTestScopedLibraryChild>());
+  test_obj_parent =
+      obj->SetChildOwnPtrLibraryAndReturnParent(std::move(test_obj2));
   EXPECT_FALSE(test_obj2.get());
   EXPECT_TRUE(test_obj_parent.get());
   EXPECT_EQ(kTestVal, test_obj_parent->GetValue());
@@ -523,14 +519,14 @@
   CefOwnPtr<CefTranslatorTestScopedClient> test_obj(
       new TranslatorTestScopedClient(kTestVal, &got_delete));
   EXPECT_EQ(kTestVal, test_obj->GetValue());
-  EXPECT_EQ(kTestVal, obj->SetOwnPtrClient(test_obj.Pass()));
+  EXPECT_EQ(kTestVal, obj->SetOwnPtrClient(std::move(test_obj)));
   EXPECT_FALSE(test_obj.get());
   EXPECT_TRUE(got_delete);
 
   got_delete.reset();
   test_obj.reset(new TranslatorTestScopedClient(kTestVal, &got_delete));
   CefOwnPtr<CefTranslatorTestScopedClient> handler =
-      obj->SetOwnPtrClientAndReturn(test_obj.Pass());
+      obj->SetOwnPtrClientAndReturn(std::move(test_obj));
   EXPECT_FALSE(test_obj.get());
   EXPECT_TRUE(handler.get());
   EXPECT_FALSE(got_delete);
@@ -554,15 +550,14 @@
       new TranslatorTestScopedClientChild(kTestVal, kTestVal2, &got_delete));
   EXPECT_EQ(kTestVal, test_obj->GetValue());
   EXPECT_EQ(kTestVal2, test_obj->GetOtherValue());
-  EXPECT_EQ(kTestVal, obj->SetOwnPtrClient(
-                          test_obj.PassAs<CefTranslatorTestScopedClient>()));
+  EXPECT_EQ(kTestVal, obj->SetOwnPtrClient(std::move(test_obj)));
   EXPECT_FALSE(test_obj.get());
   EXPECT_TRUE(got_delete);
 
   got_delete.reset();
   test_obj.reset(
       new TranslatorTestScopedClientChild(kTestVal, kTestVal2, &got_delete));
-  EXPECT_EQ(kTestVal, obj->SetChildOwnPtrClient(test_obj.Pass()));
+  EXPECT_EQ(kTestVal, obj->SetChildOwnPtrClient(std::move(test_obj)));
   EXPECT_FALSE(test_obj.get());
   EXPECT_TRUE(got_delete);
 
@@ -570,7 +565,7 @@
   test_obj.reset(
       new TranslatorTestScopedClientChild(kTestVal, kTestVal2, &got_delete));
   CefOwnPtr<CefTranslatorTestScopedClient> handler(
-      obj->SetChildOwnPtrClientAndReturnParent(test_obj.Pass()));
+      obj->SetChildOwnPtrClientAndReturnParent(std::move(test_obj)));
   EXPECT_EQ(kTestVal, handler->GetValue());
   EXPECT_FALSE(test_obj.get());
   EXPECT_FALSE(got_delete);
diff --git a/src/tests/ceftests/urlrequest_unittest.cc b/src/tests/ceftests/urlrequest_unittest.cc
index a7e8fec..a3c033a 100644
--- a/src/tests/ceftests/urlrequest_unittest.cc
+++ b/src/tests/ceftests/urlrequest_unittest.cc
@@ -4,9 +4,10 @@
 
 #include <algorithm>
 #include <map>
+#include <memory>
 #include <sstream>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_parser.h"
 #include "include/cef_request_context_handler.h"
 #include "include/cef_scheme.h"
@@ -17,13 +18,14 @@
 #include "include/wrapper/cef_closure_task.h"
 #include "include/wrapper/cef_scoped_temp_dir.h"
 #include "tests/ceftests/test_handler.h"
+#include "tests/ceftests/test_request.h"
+#include "tests/ceftests/test_server_observer.h"
 #include "tests/ceftests/test_suite.h"
 #include "tests/ceftests/test_util.h"
 #include "tests/gtest/include/gtest/gtest.h"
+#include "tests/shared/browser/client_app_browser.h"
 #include "tests/shared/browser/file_util.h"
-#include "tests/shared/renderer/client_app_renderer.h"
-
-using client::ClientAppRenderer;
+#include "tests/shared/common/string_util.h"
 
 // How to add a new test:
 // 1. Add a new value to the RequestTestMode enumeration.
@@ -34,9 +36,26 @@
 
 namespace {
 
-// Unique values for URLRequest tests.
-const char kRequestTestMsg[] = "URLRequestTest.Test";
-const char kIncompleteRequestTestMsg[] = "URLRequestTest.IncompleteRequestTest";
+// Browser-side app delegate.
+class URLRequestBrowserTest : public client::ClientAppBrowser::Delegate {
+ public:
+  URLRequestBrowserTest() {}
+
+  void OnBeforeCommandLineProcessing(
+      CefRefPtr<client::ClientAppBrowser> app,
+      CefRefPtr<CefCommandLine> command_line) override {
+    // Delegate auth callbacks to GetAuthCredentials with the chrome runtime.
+    command_line->AppendSwitch("disable-chrome-login-prompt");
+
+    // Disable component extensions that require creation of a background
+    // WebContents because they slow down test runs.
+    command_line->AppendSwitch(
+        "disable-component-extensions-with-background-pages");
+  }
+
+ private:
+  IMPLEMENT_REFCOUNTING(URLRequestBrowserTest);
+};
 
 // TEST DATA
 
@@ -45,8 +64,8 @@
 const char kRequestHostCustom[] = "test";
 
 // Server backend.
-const char kRequestAddressServer[] = "127.0.0.1";
-const uint16 kRequestPortServer = 8099;
+const char* kRequestAddressServer = test_server::kHttpServerAddress;
+const uint16_t kRequestPortServer = test_server::kHttpServerPort;
 const char kRequestSchemeServer[] = "http";
 
 const char kRequestSendCookieName[] = "urcookie_send";
@@ -54,9 +73,6 @@
 
 const char kCacheControlHeader[] = "cache-control";
 
-// Used with incomplete tests for data that should not be sent.
-const char kIncompleteDoNotSendData[] = "DO NOT SEND";
-
 enum RequestTestMode {
   REQTEST_GET = 0,
   REQTEST_GET_NODATA,
@@ -177,9 +193,9 @@
   // Used only with the server backend.
   int expected_receive_count = -1;
 
-  typedef base::Callback<void(int /* next_send_count */,
-                              const base::Closure& /* complete_callback */)>
-      NextRequestCallback;
+  using NextRequestCallback =
+      base::OnceCallback<void(int /* next_send_count */,
+                              base::OnceClosure /* complete_callback */)>;
 
   // If non-null this callback will be executed before subsequent requests are
   // sent.
@@ -283,18 +299,15 @@
 
 class TestCompletionCallback : public CefCompletionCallback {
  public:
-  explicit TestCompletionCallback(const base::Closure& complete_callback)
-      : complete_callback_(complete_callback) {
+  explicit TestCompletionCallback(base::OnceClosure complete_callback)
+      : complete_callback_(std::move(complete_callback)) {
     EXPECT_FALSE(complete_callback_.is_null());
   }
 
-  void OnComplete() override {
-    complete_callback_.Run();
-    complete_callback_.Reset();
-  }
+  void OnComplete() override { std::move(complete_callback_).Run(); }
 
  private:
-  base::Closure complete_callback_;
+  base::OnceClosure complete_callback_;
 
   IMPLEMENT_REFCOUNTING(TestCompletionCallback);
 };
@@ -357,21 +370,21 @@
 // Set a cookie so that we can test if it's sent with the request.
 void SetTestCookie(CefRefPtr<CefRequestContext> request_context,
                    bool server_backend,
-                   const base::Closure& callback) {
+                   base::OnceClosure callback) {
   class Callback : public CefSetCookieCallback {
    public:
-    explicit Callback(const base::Closure& callback) : callback_(callback) {
+    explicit Callback(base::OnceClosure callback)
+        : callback_(std::move(callback)) {
       EXPECT_FALSE(callback_.is_null());
     }
 
     void OnComplete(bool success) override {
       EXPECT_TRUE(success);
-      callback_.Run();
-      callback_.Reset();
+      std::move(callback_).Run();
     }
 
    private:
-    base::Closure callback_;
+    base::OnceClosure callback_;
 
     IMPLEMENT_REFCOUNTING(Callback);
   };
@@ -383,23 +396,25 @@
   CefString(&cookie.path) = "/";
   cookie.has_expires = false;
   EXPECT_TRUE(request_context->GetCookieManager(nullptr)->SetCookie(
-      GetRequestOrigin(server_backend), cookie, new Callback(callback)));
+      GetRequestOrigin(server_backend), cookie,
+      new Callback(std::move(callback))));
 }
 
-typedef base::Callback<void(bool /* cookie exists */)> GetTestCookieCallback;
+using GetTestCookieCallback =
+    base::OnceCallback<void(bool /* cookie exists */)>;
 
 // Tests if the save cookie has been set. If set, it will be deleted at the same
 // time.
 void GetTestCookie(CefRefPtr<CefRequestContext> request_context,
                    bool server_backend,
-                   const GetTestCookieCallback& callback) {
+                   GetTestCookieCallback callback) {
   class Visitor : public CefCookieVisitor {
    public:
-    explicit Visitor(const GetTestCookieCallback& callback)
-        : callback_(callback), cookie_exists_(false) {
+    explicit Visitor(GetTestCookieCallback callback)
+        : callback_(std::move(callback)), cookie_exists_(false) {
       EXPECT_FALSE(callback_.is_null());
     }
-    ~Visitor() override { callback_.Run(cookie_exists_); }
+    ~Visitor() override { std::move(callback_).Run(cookie_exists_); }
 
     bool Visit(const CefCookie& cookie,
                int count,
@@ -424,17 +439,17 @@
   CefRefPtr<CefCookieManager> cookie_manager =
       request_context->GetCookieManager(nullptr);
   cookie_manager->VisitUrlCookies(GetRequestOrigin(server_backend), true,
-                                  new Visitor(callback));
+                                  new Visitor(std::move(callback)));
 }
 
 std::string GetHeaderValue(const CefRequest::HeaderMap& header_map,
                            const std::string& header_name_lower) {
   CefRequest::HeaderMap::const_iterator it = header_map.begin();
   for (; it != header_map.end(); ++it) {
-    std::string name = it->first;
-    std::transform(name.begin(), name.end(), name.begin(), ::tolower);
-    if (name == header_name_lower)
+    std::string name = client::AsciiStrToLower(it->first);
+    if (name == header_name_lower) {
       return it->second;
+    }
   }
   return std::string();
 }
@@ -482,8 +497,9 @@
 void GetNormalResponse(const RequestRunSettings* settings,
                        CefRefPtr<CefResponse> response) {
   EXPECT_TRUE(settings->response);
-  if (!settings->response)
+  if (!settings->response) {
     return;
+  }
 
   response->SetStatus(settings->response->GetStatus());
   response->SetStatusText(settings->response->GetStatusText());
@@ -518,8 +534,9 @@
                   const std::string& username,
                   const std::string& password) {
   const std::string& authHeader = request->GetHeaderByName("Authorization");
-  if (authHeader.empty())
+  if (authHeader.empty()) {
     return false;
+  }
 
   if (authHeader.find("Basic ") == 0) {
     const std::string& base64 = authHeader.substr(6);
@@ -549,12 +566,12 @@
 class RequestSchemeHandlerOld : public CefResourceHandler {
  public:
   RequestSchemeHandlerOld(RequestRunSettings* settings,
-                          const base::Closure& destroy_callback)
-      : settings_(settings), destroy_callback_(destroy_callback) {}
+                          base::OnceClosure destroy_callback)
+      : settings_(settings), destroy_callback_(std::move(destroy_callback)) {}
 
   ~RequestSchemeHandlerOld() override {
     EXPECT_EQ(1, cancel_ct_);
-    destroy_callback_.Run();
+    std::move(destroy_callback_).Run();
   }
 
   bool ProcessRequest(CefRefPtr<CefRequest> request,
@@ -564,8 +581,9 @@
 
     // HEAD requests are identical to GET requests except no response data is
     // sent.
-    if (request->GetMethod() != "HEAD")
+    if (request->GetMethod() != "HEAD") {
       response_data_ = settings_->response_data;
+    }
 
     // Continue immediately.
     callback->Continue();
@@ -573,7 +591,7 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
     EXPECT_IO_THREAD();
     GetNormalResponse(settings_, response);
@@ -611,7 +629,7 @@
  private:
   // |settings_| is not owned by this object.
   RequestRunSettings* settings_;
-  base::Closure destroy_callback_;
+  base::OnceClosure destroy_callback_;
 
   std::string response_data_;
   size_t offset_ = 0;
@@ -625,12 +643,12 @@
 class RequestSchemeHandler : public CefResourceHandler {
  public:
   RequestSchemeHandler(RequestRunSettings* settings,
-                       const base::Closure& destroy_callback)
-      : settings_(settings), destroy_callback_(destroy_callback) {}
+                       base::OnceClosure destroy_callback)
+      : settings_(settings), destroy_callback_(std::move(destroy_callback)) {}
 
   ~RequestSchemeHandler() override {
     EXPECT_EQ(1, cancel_ct_);
-    destroy_callback_.Run();
+    std::move(destroy_callback_).Run();
   }
 
   bool Open(CefRefPtr<CefRequest> request,
@@ -641,8 +659,9 @@
 
     // HEAD requests are identical to GET requests except no response data is
     // sent.
-    if (request->GetMethod() != "HEAD")
+    if (request->GetMethod() != "HEAD") {
       response_data_ = settings_->response_data;
+    }
 
     // Continue immediately.
     handle_request = true;
@@ -656,20 +675,20 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
     EXPECT_IO_THREAD();
     GetNormalResponse(settings_, response);
     response_length = response_data_.length() - offset_;
   }
 
-  bool Skip(int64 bytes_to_skip,
-            int64& bytes_skipped,
+  bool Skip(int64_t bytes_to_skip,
+            int64_t& bytes_skipped,
             CefRefPtr<CefResourceSkipCallback> callback) override {
     size_t size = response_data_.length();
     if (offset_ < size) {
       bytes_skipped =
-          std::min(bytes_to_skip, static_cast<int64>(size - offset_));
+          std::min(bytes_to_skip, static_cast<int64_t>(size - offset_));
       offset_ += bytes_skipped;
     } else {
       bytes_skipped = ERR_FAILED;
@@ -719,7 +738,7 @@
  private:
   // |settings_| is not owned by this object.
   RequestRunSettings* settings_;
-  base::Closure destroy_callback_;
+  base::OnceClosure destroy_callback_;
 
   std::string response_data_;
   size_t offset_ = 0;
@@ -735,14 +754,14 @@
  public:
   RequestRedirectSchemeHandlerOld(CefRefPtr<CefRequest> request,
                                   CefRefPtr<CefResponse> response,
-                                  const base::Closure& destroy_callback)
+                                  base::OnceClosure destroy_callback)
       : request_(request),
         response_(response),
-        destroy_callback_(destroy_callback) {}
+        destroy_callback_(std::move(destroy_callback)) {}
 
   ~RequestRedirectSchemeHandlerOld() override {
     EXPECT_EQ(1, cancel_ct_);
-    destroy_callback_.Run();
+    std::move(destroy_callback_).Run();
   }
 
   bool ProcessRequest(CefRefPtr<CefRequest> request,
@@ -758,7 +777,7 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
     EXPECT_IO_THREAD();
 
@@ -790,7 +809,7 @@
  private:
   CefRefPtr<CefRequest> request_;
   CefRefPtr<CefResponse> response_;
-  base::Closure destroy_callback_;
+  base::OnceClosure destroy_callback_;
 
   int cancel_ct_ = 0;
 
@@ -802,14 +821,14 @@
  public:
   RequestRedirectSchemeHandler(CefRefPtr<CefRequest> request,
                                CefRefPtr<CefResponse> response,
-                               const base::Closure& destroy_callback)
+                               base::OnceClosure destroy_callback)
       : request_(request),
         response_(response),
-        destroy_callback_(destroy_callback) {}
+        destroy_callback_(std::move(destroy_callback)) {}
 
   ~RequestRedirectSchemeHandler() override {
     EXPECT_EQ(1, cancel_ct_);
-    destroy_callback_.Run();
+    std::move(destroy_callback_).Run();
   }
 
   bool Open(CefRefPtr<CefRequest> request,
@@ -832,7 +851,7 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
     EXPECT_IO_THREAD();
 
@@ -873,7 +892,7 @@
  private:
   CefRefPtr<CefRequest> request_;
   CefRefPtr<CefResponse> response_;
-  base::Closure destroy_callback_;
+  base::OnceClosure destroy_callback_;
 
   int cancel_ct_ = 0;
 
@@ -886,8 +905,8 @@
 class IncompleteSchemeHandlerOld : public CefResourceHandler {
  public:
   IncompleteSchemeHandlerOld(RequestRunSettings* settings,
-                             const base::Closure& destroy_callback)
-      : settings_(settings), destroy_callback_(destroy_callback) {
+                             base::OnceClosure destroy_callback)
+      : settings_(settings), destroy_callback_(std::move(destroy_callback)) {
     EXPECT_NE(settings_->incomplete_type, RequestRunSettings::INCOMPLETE_NONE);
   }
 
@@ -904,7 +923,7 @@
       EXPECT_EQ(0, read_response_ct_);
     }
 
-    destroy_callback_.Run();
+    std::move(destroy_callback_).Run();
   }
 
   bool ProcessRequest(CefRefPtr<CefRequest> request,
@@ -924,7 +943,7 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
     EXPECT_IO_THREAD();
     EXPECT_EQ(settings_->incomplete_type,
@@ -940,7 +959,7 @@
     settings_->response->GetHeaderMap(headerMap);
     settings_->response->SetHeaderMap(headerMap);
 
-    response_length = static_cast<int64>(settings_->response_data.size());
+    response_length = static_cast<int64_t>(settings_->response_data.size());
   }
 
   bool ReadResponse(void* data_out,
@@ -966,7 +985,7 @@
 
  private:
   RequestRunSettings* const settings_;
-  const base::Closure destroy_callback_;
+  base::OnceClosure destroy_callback_;
 
   int process_request_ct_ = 0;
   int get_response_headers_ct_ = 0;
@@ -982,8 +1001,8 @@
 class IncompleteSchemeHandler : public CefResourceHandler {
  public:
   IncompleteSchemeHandler(RequestRunSettings* settings,
-                          const base::Closure& destroy_callback)
-      : settings_(settings), destroy_callback_(destroy_callback) {
+                          base::OnceClosure destroy_callback)
+      : settings_(settings), destroy_callback_(std::move(destroy_callback)) {
     EXPECT_NE(settings_->incomplete_type, RequestRunSettings::INCOMPLETE_NONE);
   }
 
@@ -1000,7 +1019,7 @@
       EXPECT_EQ(0, read_ct_);
     }
 
-    destroy_callback_.Run();
+    std::move(destroy_callback_).Run();
   }
 
   bool Open(CefRefPtr<CefRequest> request,
@@ -1028,7 +1047,7 @@
   }
 
   void GetResponseHeaders(CefRefPtr<CefResponse> response,
-                          int64& response_length,
+                          int64_t& response_length,
                           CefString& redirectUrl) override {
     EXPECT_IO_THREAD();
     EXPECT_EQ(settings_->incomplete_type,
@@ -1044,7 +1063,7 @@
     settings_->response->GetHeaderMap(headerMap);
     settings_->response->SetHeaderMap(headerMap);
 
-    response_length = static_cast<int64>(settings_->response_data.size());
+    response_length = static_cast<int64_t>(settings_->response_data.size());
   }
 
   bool Read(void* data_out,
@@ -1079,7 +1098,7 @@
 
  private:
   RequestRunSettings* const settings_;
-  const base::Closure destroy_callback_;
+  base::OnceClosure destroy_callback_;
 
   int open_ct_ = 0;
   int get_response_headers_ct_ = 0;
@@ -1104,30 +1123,36 @@
     EXPECT_IO_THREAD();
 
     handler_create_ct_++;
-    const base::Closure destroy_callback =
-        base::Bind(&RequestSchemeHandlerFactory::OnHandlerDestroyed, this);
+    auto destroy_callback =
+        base::BindOnce(&RequestSchemeHandlerFactory::OnHandlerDestroyed, this);
 
     RequestDataMap::Entry entry = data_map_.Find(request->GetURL());
     if (entry.type == RequestDataMap::Entry::TYPE_NORMAL) {
       if (entry.settings->incomplete_type ==
           RequestRunSettings::INCOMPLETE_NONE) {
         if (TestOldResourceAPI()) {
-          return new RequestSchemeHandlerOld(entry.settings, destroy_callback);
+          return new RequestSchemeHandlerOld(entry.settings,
+                                             std::move(destroy_callback));
         }
-        return new RequestSchemeHandler(entry.settings, destroy_callback);
+        return new RequestSchemeHandler(entry.settings,
+                                        std::move(destroy_callback));
       }
 
       if (TestOldResourceAPI()) {
-        return new IncompleteSchemeHandlerOld(entry.settings, destroy_callback);
+        return new IncompleteSchemeHandlerOld(entry.settings,
+                                              std::move(destroy_callback));
       }
-      return new IncompleteSchemeHandler(entry.settings, destroy_callback);
+      return new IncompleteSchemeHandler(entry.settings,
+                                         std::move(destroy_callback));
     } else if (entry.type == RequestDataMap::Entry::TYPE_REDIRECT) {
       if (TestOldResourceAPI()) {
-        return new RequestRedirectSchemeHandlerOld(
-            entry.redirect_request, entry.redirect_response, destroy_callback);
+        return new RequestRedirectSchemeHandlerOld(entry.redirect_request,
+                                                   entry.redirect_response,
+                                                   std::move(destroy_callback));
       }
-      return new RequestRedirectSchemeHandler(
-          entry.redirect_request, entry.redirect_response, destroy_callback);
+      return new RequestRedirectSchemeHandler(entry.redirect_request,
+                                              entry.redirect_response,
+                                              std::move(destroy_callback));
     }
 
     // Unknown test.
@@ -1157,9 +1182,9 @@
 
   void OnHandlerDestroyed() {
     if (!CefCurrentlyOn(TID_IO)) {
-      CefPostTask(
-          TID_IO,
-          base::Bind(&RequestSchemeHandlerFactory::OnHandlerDestroyed, this));
+      CefPostTask(TID_IO,
+                  base::BindOnce(
+                      &RequestSchemeHandlerFactory::OnHandlerDestroyed, this));
       return;
     }
 
@@ -1168,15 +1193,15 @@
     MaybeShutdown();
   }
 
-  void Shutdown(const base::Closure& complete_callback) {
+  void Shutdown(base::OnceClosure complete_callback) {
     if (!CefCurrentlyOn(TID_IO)) {
-      CefPostTask(TID_IO, base::Bind(&RequestSchemeHandlerFactory::Shutdown,
-                                     this, complete_callback));
+      CefPostTask(TID_IO, base::BindOnce(&RequestSchemeHandlerFactory::Shutdown,
+                                         this, std::move(complete_callback)));
       return;
     }
 
     EXPECT_TRUE(shutdown_callback_.is_null());
-    shutdown_callback_ = complete_callback;
+    shutdown_callback_ = std::move(complete_callback);
 
     data_map_.SetOwnerTaskRunner(nullptr);
 
@@ -1187,8 +1212,7 @@
   void MaybeShutdown() {
     if (!shutdown_callback_.is_null() &&
         handler_create_ct_ == handler_destroy_ct_) {
-      shutdown_callback_.Run();
-      shutdown_callback_.Reset();
+      std::move(shutdown_callback_).Run();
     }
   }
 
@@ -1196,7 +1220,7 @@
 
   int handler_create_ct_ = 0;
   int handler_destroy_ct_ = 0;
-  base::Closure shutdown_callback_;
+  base::OnceClosure shutdown_callback_;
 
   IMPLEMENT_REFCOUNTING(RequestSchemeHandlerFactory);
   DISALLOW_COPY_AND_ASSIGN(RequestSchemeHandlerFactory);
@@ -1205,12 +1229,10 @@
 // SERVER BACKEND
 
 // HTTP server handler.
-class RequestServerHandler : public CefServerHandler {
+class RequestServerHandler : public test_server::ObserverHelper {
  public:
   RequestServerHandler()
       : initialized_(false),
-        expected_connection_ct_(-1),
-        actual_connection_ct_(0),
         expected_http_request_ct_(-1),
         actual_http_request_ct_(0) {}
 
@@ -1225,15 +1247,15 @@
   // Must be called before CreateServer().
   void SetExpectedRequestCount(int count) {
     EXPECT_FALSE(initialized_);
-    expected_connection_ct_ = expected_http_request_ct_ = count;
+    expected_http_request_ct_ = count;
   }
 
   // |complete_callback| will be executed on the UI thread after the server is
   // started.
-  void CreateServer(const base::Closure& complete_callback) {
+  void CreateServer(base::OnceClosure complete_callback) {
     EXPECT_UI_THREAD();
 
-    if (expected_connection_ct_ < 0) {
+    if (expected_http_request_ct_ < 0) {
       // Default to the assumption of one request per registered URL.
       SetExpectedRequestCount(static_cast<int>(data_map_.size()));
     }
@@ -1242,185 +1264,98 @@
     initialized_ = true;
 
     EXPECT_TRUE(complete_callback_.is_null());
-    complete_callback_ = complete_callback;
+    complete_callback_ = std::move(complete_callback);
 
-    CefServer::CreateServer(kRequestAddressServer, kRequestPortServer, 10,
-                            this);
+    Initialize(/*https_server=*/false);
   }
 
   // Results in a call to VerifyResults() and eventual execution of the
   // |complete_callback| on the UI thread via RequestServerHandler destruction.
-  void ShutdownServer(const base::Closure& complete_callback) {
+  void ShutdownServer(base::OnceClosure complete_callback) {
     EXPECT_UI_THREAD();
 
     EXPECT_TRUE(complete_callback_.is_null());
-    complete_callback_ = complete_callback;
+    complete_callback_ = std::move(complete_callback);
 
-    EXPECT_TRUE(server_);
-    if (server_)
-      server_->Shutdown();
+    Shutdown();
   }
 
-  void OnServerCreated(CefRefPtr<CefServer> server) override {
-    EXPECT_TRUE(server);
-    EXPECT_TRUE(server->IsRunning());
-    EXPECT_FALSE(server->HasConnection());
+  void OnInitialized(const std::string& server_origin) override {
+    EXPECT_UI_THREAD();
+    EXPECT_STREQ(server_origin.c_str(), GetRequestOrigin(true).c_str());
+    EXPECT_FALSE(got_initialized_);
+    got_initialized_.yes();
 
-    EXPECT_FALSE(got_server_created_);
-    got_server_created_.yes();
-
-    EXPECT_FALSE(server_);
-    server_ = server;
-
-    EXPECT_FALSE(server_runner_);
-    server_runner_ = server_->GetTaskRunner();
-    EXPECT_TRUE(server_runner_);
-    EXPECT_TRUE(server_runner_->BelongsToCurrentThread());
-
-    CefPostTask(TID_UI, base::Bind(&RequestServerHandler::RunCompleteCallback,
-                                   this, true));
+    RunCompleteCallback(true);
   }
 
-  void OnServerDestroyed(CefRefPtr<CefServer> server) override {
-    EXPECT_TRUE(VerifyServer(server));
-    EXPECT_FALSE(server->IsRunning());
-    EXPECT_FALSE(server->HasConnection());
-
-    EXPECT_FALSE(got_server_destroyed_);
-    got_server_destroyed_.yes();
+  void OnShutdown() override {
+    EXPECT_UI_THREAD();
+    EXPECT_FALSE(got_shutdown_);
+    got_shutdown_.yes();
 
     data_map_.SetOwnerTaskRunner(nullptr);
-    server_ = nullptr;
 
     VerifyResults();
+
+    delete this;
   }
 
-  void OnClientConnected(CefRefPtr<CefServer> server,
-                         int connection_id) override {
-    EXPECT_TRUE(VerifyServer(server));
-    EXPECT_TRUE(server->HasConnection());
-    EXPECT_TRUE(server->IsValidConnection(connection_id));
-
-    EXPECT_TRUE(connection_id_set_.find(connection_id) ==
-                connection_id_set_.end());
-    connection_id_set_.insert(connection_id);
-
-    actual_connection_ct_++;
-  }
-
-  void OnClientDisconnected(CefRefPtr<CefServer> server,
-                            int connection_id) override {
-    EXPECT_TRUE(VerifyServer(server));
-    EXPECT_FALSE(server->IsValidConnection(connection_id));
-
-    ConnectionIdSet::iterator it = connection_id_set_.find(connection_id);
-    EXPECT_TRUE(it != connection_id_set_.end());
-    connection_id_set_.erase(it);
-  }
-
-  void OnHttpRequest(CefRefPtr<CefServer> server,
-                     int connection_id,
-                     const CefString& client_address,
-                     CefRefPtr<CefRequest> request) override {
-    EXPECT_TRUE(VerifyServer(server));
-    EXPECT_TRUE(VerifyConnection(connection_id));
-    EXPECT_FALSE(client_address.empty());
+  bool OnTestServerRequest(CefRefPtr<CefRequest> request,
+                           const ResponseCallback& response_callback) override {
+    EXPECT_UI_THREAD();
 
     // Log the requests for better error reporting.
     request_log_ += request->GetMethod().ToString() + " " +
                     request->GetURL().ToString() + "\n";
 
-    HandleRequest(server, connection_id, request);
-
     actual_http_request_ct_++;
-  }
 
-  void OnWebSocketRequest(CefRefPtr<CefServer> server,
-                          int connection_id,
-                          const CefString& client_address,
-                          CefRefPtr<CefRequest> request,
-                          CefRefPtr<CefCallback> callback) override {
-    NOTREACHED();
-  }
-
-  void OnWebSocketConnected(CefRefPtr<CefServer> server,
-                            int connection_id) override {
-    NOTREACHED();
-  }
-
-  void OnWebSocketMessage(CefRefPtr<CefServer> server,
-                          int connection_id,
-                          const void* data,
-                          size_t data_size) override {
-    NOTREACHED();
+    return HandleRequest(request, response_callback);
   }
 
  private:
-  bool RunningOnServerThread() {
-    return server_runner_ && server_runner_->BelongsToCurrentThread();
-  }
-
-  bool VerifyServer(CefRefPtr<CefServer> server) {
-    V_DECLARE();
-    V_EXPECT_TRUE(RunningOnServerThread());
-    V_EXPECT_TRUE(server);
-    V_EXPECT_TRUE(server_);
-    V_EXPECT_TRUE(server->GetAddress().ToString() ==
-                  server_->GetAddress().ToString());
-    V_RETURN();
-  }
-
-  bool VerifyConnection(int connection_id) {
-    return connection_id_set_.find(connection_id) != connection_id_set_.end();
-  }
-
   void VerifyResults() {
-    EXPECT_TRUE(RunningOnServerThread());
-
-    EXPECT_TRUE(got_server_created_);
-    EXPECT_TRUE(got_server_destroyed_);
-    EXPECT_TRUE(connection_id_set_.empty());
-    EXPECT_EQ(expected_connection_ct_, actual_connection_ct_) << request_log_;
+    EXPECT_TRUE(got_initialized_);
+    EXPECT_TRUE(got_shutdown_);
     EXPECT_EQ(expected_http_request_ct_, actual_http_request_ct_)
         << request_log_;
   }
 
-  void HandleRequest(CefRefPtr<CefServer> server,
-                     int connection_id,
-                     CefRefPtr<CefRequest> request) {
+  bool HandleRequest(CefRefPtr<CefRequest> request,
+                     const ResponseCallback& response_callback) {
     RequestDataMap::Entry entry = data_map_.Find(request->GetURL());
     if (entry.type == RequestDataMap::Entry::TYPE_NORMAL) {
       const bool needs_auth = entry.settings->expect_authentication &&
                               !IsAuthorized(request, entry.settings->username,
                                             entry.settings->password);
       if (needs_auth) {
-        HandleAuthRequest(server, connection_id, request);
-        return;
+        return HandleAuthRequest(request, response_callback);
       }
 
-      HandleNormalRequest(server, connection_id, request, entry.settings);
+      return HandleNormalRequest(request, response_callback, entry.settings);
     } else if (entry.type == RequestDataMap::Entry::TYPE_REDIRECT) {
-      HandleRedirectRequest(server, connection_id, request,
-                            entry.redirect_request, entry.redirect_response);
+      return HandleRedirectRequest(request, response_callback,
+                                   entry.redirect_request,
+                                   entry.redirect_response);
     } else {
       // Unknown test.
       ADD_FAILURE() << "url: " << request->GetURL().ToString();
-      server->SendHttp500Response(connection_id, "Unknown test");
     }
+    return false;
   }
 
-  void HandleAuthRequest(CefRefPtr<CefServer> server,
-                         int connection_id,
-                         CefRefPtr<CefRequest> request) {
+  static bool HandleAuthRequest(CefRefPtr<CefRequest> request,
+                                const ResponseCallback& response_callback) {
     CefRefPtr<CefResponse> response = CefResponse::Create();
     GetAuthResponse(response);
-    SendResponse(server, connection_id, response, std::string());
+    response_callback.Run(response, std::string());
+    return true;
   }
 
-  void HandleNormalRequest(CefRefPtr<CefServer> server,
-                           int connection_id,
-                           CefRefPtr<CefRequest> request,
-                           RequestRunSettings* settings) {
+  static bool HandleNormalRequest(CefRefPtr<CefRequest> request,
+                                  const ResponseCallback& response_callback,
+                                  RequestRunSettings* settings) {
     VerifyNormalRequest(settings, request, true);
 
     CefRefPtr<CefResponse> response = CefResponse::Create();
@@ -1434,14 +1369,14 @@
       response_data = settings->response_data.substr(expected_offset);
     }
 
-    SendResponse(server, connection_id, response, response_data);
+    response_callback.Run(response, response_data);
+    return true;
   }
 
-  void HandleRedirectRequest(CefRefPtr<CefServer> server,
-                             int connection_id,
-                             CefRefPtr<CefRequest> request,
-                             CefRefPtr<CefRequest> redirect_request,
-                             CefRefPtr<CefResponse> redirect_response) {
+  static bool HandleRedirectRequest(CefRefPtr<CefRequest> request,
+                                    const ResponseCallback& response_callback,
+                                    CefRefPtr<CefRequest> redirect_request,
+                                    CefRefPtr<CefResponse> redirect_response) {
     if (redirect_response->GetStatus() == 302) {
       // Simulate wrong copying of POST-specific headers Content-Type and
       // Content-Length. A 302 redirect should end up in a GET request and
@@ -1457,180 +1392,39 @@
     // Verify that the request was sent correctly.
     TestRequestEqual(redirect_request, request, true);
 
-    SendResponse(server, connection_id, redirect_response, std::string());
-  }
-
-  void SendResponse(CefRefPtr<CefServer> server,
-                    int connection_id,
-                    CefRefPtr<CefResponse> response,
-                    const std::string& response_data) {
-    const int response_code = response->GetStatus();
-    if (response_code <= 0) {
-      // Intentionally not responding for incomplete request tests.
-      return;
-    }
-
-    const CefString& content_type = response->GetMimeType();
-    int64 content_length = static_cast<int64>(response_data.size());
-
-    CefResponse::HeaderMap extra_headers;
-    response->GetHeaderMap(extra_headers);
-
-    server->SendHttpResponse(connection_id, response_code, content_type,
-                             content_length, extra_headers);
-
-    if (response_data == kIncompleteDoNotSendData) {
-      // Intentionally not sending data for incomplete request tests.
-      return;
-    }
-
-    if (content_length != 0) {
-      server->SendRawData(connection_id, response_data.data(),
-                          response_data.size());
-      server->CloseConnection(connection_id);
-    }
-
-    // The connection should be closed.
-    EXPECT_FALSE(server->IsValidConnection(connection_id));
+    response_callback.Run(redirect_response, std::string());
+    return true;
   }
 
   void RunCompleteCallback(bool startup) {
     EXPECT_UI_THREAD();
 
     if (startup) {
-      // Transfer DataMap ownership to the server thread.
-      data_map_.SetOwnerTaskRunner(server_->GetTaskRunner());
+      // Transfer DataMap ownership to the UI thread.
+      data_map_.SetOwnerTaskRunner(CefTaskRunner::GetForCurrentThread());
     }
 
     EXPECT_FALSE(complete_callback_.is_null());
-    complete_callback_.Run();
-    complete_callback_.Reset();
+    std::move(complete_callback_).Run();
   }
 
   RequestDataMap data_map_;
 
-  CefRefPtr<CefServer> server_;
-  CefRefPtr<CefTaskRunner> server_runner_;
   bool initialized_;
 
   // Only accessed on the UI thread.
-  base::Closure complete_callback_;
+  base::OnceClosure complete_callback_;
 
   // After initialization the below members are only accessed on the server
   // thread.
 
-  TrackCallback got_server_created_;
-  TrackCallback got_server_destroyed_;
+  TrackCallback got_initialized_;
+  TrackCallback got_shutdown_;
 
-  typedef std::set<int> ConnectionIdSet;
-  ConnectionIdSet connection_id_set_;
-
-  int expected_connection_ct_;
-  int actual_connection_ct_;
   int expected_http_request_ct_;
   int actual_http_request_ct_;
 
   std::string request_log_;
-
-  IMPLEMENT_REFCOUNTING(RequestServerHandler);
-  DISALLOW_COPY_AND_ASSIGN(RequestServerHandler);
-};
-
-// URLREQUEST CLIENT
-
-// Implementation of CefURLRequestClient that stores response information.
-class RequestClient : public CefURLRequestClient {
- public:
-  typedef base::Callback<void(CefRefPtr<RequestClient>)>
-      RequestCompleteCallback;
-
-  explicit RequestClient(const RequestCompleteCallback& complete_callback)
-      : complete_callback_(complete_callback) {
-    EXPECT_FALSE(complete_callback_.is_null());
-  }
-
-  void OnRequestComplete(CefRefPtr<CefURLRequest> request) override {
-    request_complete_ct_++;
-
-    request_ = request->GetRequest();
-    EXPECT_TRUE(request_->IsReadOnly());
-    status_ = request->GetRequestStatus();
-    error_code_ = request->GetRequestError();
-    response_was_cached_ = request->ResponseWasCached();
-    response_ = request->GetResponse();
-    if (response_) {
-      EXPECT_TRUE(response_->IsReadOnly());
-    }
-
-    complete_callback_.Run(this);
-  }
-
-  void OnUploadProgress(CefRefPtr<CefURLRequest> request,
-                        int64 current,
-                        int64 total) override {
-    upload_progress_ct_++;
-    upload_total_ = total;
-  }
-
-  void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
-                          int64 current,
-                          int64 total) override {
-    response_ = request->GetResponse();
-    EXPECT_TRUE(response_.get());
-    EXPECT_TRUE(response_->IsReadOnly());
-    download_progress_ct_++;
-    download_total_ = total;
-  }
-
-  void OnDownloadData(CefRefPtr<CefURLRequest> request,
-                      const void* data,
-                      size_t data_length) override {
-    response_ = request->GetResponse();
-    EXPECT_TRUE(response_.get());
-    EXPECT_TRUE(response_->IsReadOnly());
-    download_data_ct_++;
-    download_data_ += std::string(static_cast<const char*>(data), data_length);
-  }
-
-  bool GetAuthCredentials(bool isProxy,
-                          const CefString& host,
-                          int port,
-                          const CefString& realm,
-                          const CefString& scheme,
-                          CefRefPtr<CefAuthCallback> callback) override {
-    auth_credentials_ct_++;
-    if (has_authentication_) {
-      callback->Continue(username_, password_);
-      return true;
-    }
-    return false;
-  }
-
- private:
-  const RequestCompleteCallback complete_callback_;
-
- public:
-  bool has_authentication_ = false;
-  std::string username_;
-  std::string password_;
-
-  int request_complete_ct_ = 0;
-  int upload_progress_ct_ = 0;
-  int download_progress_ct_ = 0;
-  int download_data_ct_ = 0;
-  int auth_credentials_ct_ = 0;
-
-  int64 upload_total_ = 0;
-  int64 download_total_ = 0;
-  std::string download_data_;
-  CefRefPtr<CefRequest> request_;
-  CefURLRequest::Status status_ = UR_UNKNOWN;
-  CefURLRequest::ErrorCode error_code_ = ERR_NONE;
-  CefRefPtr<CefResponse> response_;
-  bool response_was_cached_ = false;
-
- private:
-  IMPLEMENT_REFCOUNTING(RequestClient);
 };
 
 // SHARED TEST RUNNER
@@ -1638,26 +1432,25 @@
 // Executes the tests.
 class RequestTestRunner : public base::RefCountedThreadSafe<RequestTestRunner> {
  public:
-  typedef base::Callback<void(const base::Closure&)> TestCallback;
+  using TestCallback = base::RepeatingCallback<void(base::OnceClosure)>;
 
-  RequestTestRunner(bool is_browser_process,
-                    bool is_server_backend,
+  RequestTestRunner(bool is_server_backend,
                     bool use_frame_method,
-                    bool run_in_browser_process,
-                    const base::Closure& incomplete_request_callback)
-      : is_browser_process_(is_browser_process),
-        is_server_backend_(is_server_backend),
+                    base::OnceClosure incomplete_request_callback)
+      : is_server_backend_(is_server_backend),
         use_frame_method_(use_frame_method),
-        run_in_browser_process_(run_in_browser_process),
-        incomplete_request_callback_(incomplete_request_callback) {
+        incomplete_request_callback_(std::move(incomplete_request_callback)) {
     owner_task_runner_ = CefTaskRunner::GetForCurrentThread();
     EXPECT_TRUE(owner_task_runner_.get());
     EXPECT_TRUE(owner_task_runner_->BelongsToCurrentThread());
+  }
 
+  void Initialize() {
 // Helper macro for registering test callbacks.
-#define REGISTER_TEST(test_mode, setup_method, run_method)                    \
-  RegisterTest(test_mode, base::Bind(&RequestTestRunner::setup_method, this), \
-               base::Bind(&RequestTestRunner::run_method, this));
+#define REGISTER_TEST(test_mode, setup_method, run_method)                  \
+  RegisterTest(test_mode,                                                   \
+               base::BindRepeating(&RequestTestRunner::setup_method, this), \
+               base::BindRepeating(&RequestTestRunner::run_method, this));
 
     // Register the test callbacks.
     REGISTER_TEST(REQTEST_GET, SetupGetTest, SingleRunTest);
@@ -1722,84 +1515,81 @@
     return request_context_;
   }
 
-  // Called in both the browser and render process to setup the test.
+  // Called to setup the test.
   void SetupTest(RequestTestMode test_mode,
-                 const base::Closure& complete_callback) {
+                 base::OnceClosure complete_callback) {
     EXPECT_TRUE(owner_task_runner_->BelongsToCurrentThread());
 
-    const base::Closure& safe_complete_callback = base::Bind(
-        &RequestTestRunner::CompleteOnCorrectThread, this, complete_callback);
-
     TestMap::const_iterator it = test_map_.find(test_mode);
     if (it != test_map_.end()) {
-      it->second.setup.Run(base::Bind(&RequestTestRunner::SetupContinue, this,
-                                      safe_complete_callback));
+      auto safe_complete_callback =
+          base::BindOnce(&RequestTestRunner::CompleteOnCorrectThread, this,
+                         std::move(complete_callback));
+      it->second.setup.Run(base::BindOnce(&RequestTestRunner::SetupContinue,
+                                          this,
+                                          std::move(safe_complete_callback)));
     } else {
       // Unknown test.
       ADD_FAILURE();
-      complete_callback.Run();
+      std::move(complete_callback).Run();
     }
   }
 
-  // Called in either the browser or render process to run the test.
+  // Called to run the test.
   void RunTest(RequestTestMode test_mode,
                CefRefPtr<CefFrame> frame,
-               const base::Closure& complete_callback) {
+               base::OnceClosure complete_callback) {
     EXPECT_TRUE(owner_task_runner_->BelongsToCurrentThread());
 
     frame_ = frame;
 
-    const base::Closure& safe_complete_callback = base::Bind(
-        &RequestTestRunner::CompleteOnCorrectThread, this, complete_callback);
-
     TestMap::const_iterator it = test_map_.find(test_mode);
     if (it != test_map_.end()) {
-      it->second.run.Run(safe_complete_callback);
+      auto safe_complete_callback =
+          base::BindOnce(&RequestTestRunner::CompleteOnCorrectThread, this,
+                         std::move(complete_callback));
+      it->second.run.Run(std::move(safe_complete_callback));
     } else {
       // Unknown test.
       ADD_FAILURE();
-      complete_callback.Run();
+      std::move(complete_callback).Run();
     }
   }
 
-  // Called in both the browser and render process to shut down the test.
-  void ShutdownTest(const base::Closure& complete_callback) {
+  // Called to shut down the test.
+  void ShutdownTest(base::OnceClosure complete_callback) {
     EXPECT_TRUE(owner_task_runner_->BelongsToCurrentThread());
 
-    const base::Closure& safe_complete_callback = base::Bind(
-        &RequestTestRunner::CompleteOnCorrectThread, this, complete_callback);
+    auto safe_complete_callback =
+        base::BindOnce(&RequestTestRunner::CompleteOnCorrectThread, this,
+                       std::move(complete_callback));
 
     if (!post_file_tmpdir_.IsEmpty()) {
-      EXPECT_TRUE(is_browser_process_);
-      CefPostTask(TID_FILE,
-                  base::Bind(&RequestTestRunner::RunDeleteTempDirectory, this,
-                             safe_complete_callback));
+      CefPostTask(TID_FILE_USER_VISIBLE,
+                  base::BindOnce(&RequestTestRunner::RunDeleteTempDirectory,
+                                 this, std::move(safe_complete_callback)));
       return;
     }
 
     // Continue with test shutdown.
-    RunShutdown(safe_complete_callback);
+    RunShutdown(std::move(safe_complete_callback));
   }
 
  private:
   // Continued after |settings_| is populated for the test.
-  void SetupContinue(const base::Closure& complete_callback) {
+  void SetupContinue(base::OnceClosure complete_callback) {
     if (!owner_task_runner_->BelongsToCurrentThread()) {
-      owner_task_runner_->PostTask(CefCreateClosureTask(base::Bind(
-          &RequestTestRunner::SetupContinue, this, complete_callback)));
+      owner_task_runner_->PostTask(CefCreateClosureTask(
+          base::BindOnce(&RequestTestRunner::SetupContinue, this,
+                         std::move(complete_callback))));
       return;
     }
 
-    if (is_browser_process_) {
-      SetupTestBackend(complete_callback);
-    } else {
-      complete_callback.Run();
-    }
+    SetupTestBackend(std::move(complete_callback));
   }
 
   std::string GetTestPath(const std::string& name) {
-    return std::string(run_in_browser_process_ ? "/Browser" : "/Renderer") +
-           name;
+    return std::string("/Browser") + name;
   }
 
   std::string GetTestURL(const std::string& name) {
@@ -1822,12 +1612,12 @@
     settings_.response_data = "GET TEST SUCCESS";
   }
 
-  void SetupGetTest(const base::Closure& complete_callback) {
+  void SetupGetTest(base::OnceClosure complete_callback) {
     SetupGetTestShared();
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupGetNoDataTest(const base::Closure& complete_callback) {
+  void SetupGetNoDataTest(base::OnceClosure complete_callback) {
     // Start with the normal get test.
     SetupGetTestShared();
 
@@ -1836,10 +1626,10 @@
 
     settings_.expect_download_data = false;
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupGetPartialContentTest(const base::Closure& complete_callback) {
+  void SetupGetPartialContentTest(base::OnceClosure complete_callback) {
     // Start with the normal get test.
     SetupGetTestShared();
 
@@ -1850,10 +1640,10 @@
     settings_.response->SetStatusText("Partial Content");
     settings_.expected_download_offset = 4;
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupGetAllowCookiesTest(const base::Closure& complete_callback) {
+  void SetupGetAllowCookiesTest(base::OnceClosure complete_callback) {
     // Start with the normal get test.
     SetupGetTestShared();
 
@@ -1863,10 +1653,10 @@
     settings_.expect_save_cookie = true;
     settings_.expect_send_cookie = true;
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupGetRedirectTest(const base::Closure& complete_callback) {
+  void SetupGetRedirectTest(base::OnceClosure complete_callback) {
     // Start with the normal get test.
     SetupGetTestShared();
 
@@ -1884,10 +1674,10 @@
     headerMap.insert(std::make_pair("Location", settings_.request->GetURL()));
     settings_.redirect_response->SetHeaderMap(headerMap);
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupGetRedirectStopTest(const base::Closure& complete_callback) {
+  void SetupGetRedirectStopTest(base::OnceClosure complete_callback) {
     settings_.request = CefRequest::Create();
     settings_.request->SetURL(GetTestURL("GetTest.html"));
     settings_.request->SetMethod("GET");
@@ -1896,9 +1686,7 @@
     // on stop redirects.
     settings_.response = CefResponse::Create();
     settings_.response->SetStatus(302);
-    if (is_browser_process_) {
-      settings_.response->SetStatusText("Found");
-    }
+    settings_.response->SetStatusText("Found");
 
     // Add a redirect request.
     settings_.redirect_request = CefRequest::Create();
@@ -1922,10 +1710,10 @@
     settings_.expected_send_count = 1;
     settings_.expected_receive_count = 1;
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupGetRedirectLocationTest(const base::Closure& complete_callback) {
+  void SetupGetRedirectLocationTest(base::OnceClosure complete_callback) {
     // Start with the normal get test.
     SetupGetTestShared();
 
@@ -1943,17 +1731,17 @@
     headerMap.insert(std::make_pair("LoCaTioN", GetTestPath("GetTest.html")));
     settings_.redirect_response->SetHeaderMap(headerMap);
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupGetReferrerTest(const base::Closure& complete_callback) {
+  void SetupGetReferrerTest(base::OnceClosure complete_callback) {
     settings_.request = CefRequest::Create();
     settings_.request->SetURL(GetTestURL("GetTest.html"));
     settings_.request->SetMethod("GET");
 
     // The referrer URL must be HTTP or HTTPS. This is enforced by
     // GURL::GetAsReferrer() called from URLRequest::SetReferrer().
-    settings_.request->SetReferrer("http://tests.com/referrer.html",
+    settings_.request->SetReferrer("https://tests.com/referrer.html",
                                    REFERRER_POLICY_DEFAULT);
 
     settings_.response = CefResponse::Create();
@@ -1963,10 +1751,10 @@
 
     settings_.response_data = "GET TEST SUCCESS";
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupGetAuthTest(const base::Closure& complete_callback) {
+  void SetupGetAuthTest(base::OnceClosure complete_callback) {
     // Start with the normal get test.
     SetupGetTestShared();
 
@@ -1985,7 +1773,7 @@
     settings_.expected_receive_count = 2;
     settings_.expected_send_count = 2;
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
   void SetupPostTestShared() {
@@ -2002,15 +1790,12 @@
     settings_.response_data = "POST TEST SUCCESS";
   }
 
-  void SetupPostTest(const base::Closure& complete_callback) {
+  void SetupPostTest(base::OnceClosure complete_callback) {
     SetupPostTestShared();
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupPostFileTest(const base::Closure& complete_callback) {
-    // This test is only supported in the browser process.
-    EXPECT_TRUE(is_browser_process_);
-
+  void SetupPostFileTest(base::OnceClosure complete_callback) {
     settings_.request = CefRequest::Create();
     settings_.request->SetURL(GetTestURL("PostFileTest.html"));
     settings_.request->SetMethod("POST");
@@ -2022,13 +1807,13 @@
 
     settings_.response_data = "POST TEST SUCCESS";
 
-    CefPostTask(TID_FILE,
-                base::Bind(&RequestTestRunner::SetupPostFileTestContinue, this,
-                           complete_callback));
+    CefPostTask(TID_FILE_USER_VISIBLE,
+                base::BindOnce(&RequestTestRunner::SetupPostFileTestContinue,
+                               this, std::move(complete_callback)));
   }
 
-  void SetupPostFileTestContinue(const base::Closure& complete_callback) {
-    EXPECT_TRUE(CefCurrentlyOn(TID_FILE));
+  void SetupPostFileTestContinue(base::OnceClosure complete_callback) {
+    EXPECT_TRUE(CefCurrentlyOn(TID_FILE_USER_VISIBLE));
 
     EXPECT_TRUE(post_file_tmpdir_.CreateUniqueTempDir());
     const std::string& path =
@@ -2039,10 +1824,10 @@
     EXPECT_EQ(static_cast<int>(sizeof(content) - 1), write_ct);
     SetUploadFile(settings_.request, path);
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupPostWithProgressTest(const base::Closure& complete_callback) {
+  void SetupPostWithProgressTest(base::OnceClosure complete_callback) {
     // Start with the normal post test.
     SetupPostTestShared();
 
@@ -2051,10 +1836,10 @@
 
     settings_.expect_upload_progress = true;
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupPostRedirectTest(const base::Closure& complete_callback) {
+  void SetupPostRedirectTest(base::OnceClosure complete_callback) {
     // Start with the normal post test.
     SetupPostTestShared();
 
@@ -2074,10 +1859,10 @@
     headerMap.insert(std::make_pair("Location", settings_.request->GetURL()));
     settings_.redirect_response->SetHeaderMap(headerMap);
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupPostRedirectToGetTest(const base::Closure& complete_callback) {
+  void SetupPostRedirectToGetTest(base::OnceClosure complete_callback) {
     // Start with the normal post test.
     SetupPostTestShared();
 
@@ -2103,10 +1888,10 @@
     headerMap.insert(std::make_pair("Location", settings_.request->GetURL()));
     settings_.redirect_response->SetHeaderMap(headerMap);
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupHeadTest(const base::Closure& complete_callback) {
+  void SetupHeadTest(base::OnceClosure complete_callback) {
     settings_.request = CefRequest::Create();
     settings_.request->SetURL(GetTestURL("HeadTest.html"));
     settings_.request->SetMethod("HEAD");
@@ -2122,7 +1907,7 @@
     settings_.expect_download_progress = false;
     settings_.expect_download_data = false;
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
   void SetupCacheShared(const std::string& name, bool with_cache_control) {
@@ -2140,7 +1925,7 @@
     }
   }
 
-  void SetupCacheWithControlTest(const base::Closure& complete_callback) {
+  void SetupCacheWithControlTest(base::OnceClosure complete_callback) {
     SetupCacheShared("CacheWithControlTest.html", true);
 
     // Send multiple requests. With the Cache-Control response header the 2nd+
@@ -2148,24 +1933,24 @@
     settings_.expected_send_count = 3;
     settings_.expected_receive_count = 1;
     settings_.setup_next_request =
-        base::Bind(&RequestTestRunner::SetupCacheWithControlTestNext, this);
+        base::BindOnce(&RequestTestRunner::SetupCacheWithControlTestNext, this);
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
   void SetupCacheWithControlTestNext(int next_send_count,
-                                     const base::Closure& complete_callback) {
+                                     base::OnceClosure complete_callback) {
     // Only handle from the cache.
     settings_.expect_response_was_cached = true;
 
     // The following requests will use the same setup, so no more callbacks
     // are required.
-    settings_.setup_next_request.Reset();
+    EXPECT_TRUE(settings_.setup_next_request.is_null());
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupCacheWithoutControlTest(const base::Closure& complete_callback) {
+  void SetupCacheWithoutControlTest(base::OnceClosure complete_callback) {
     SetupCacheShared("CacheWithoutControlTest.html", false);
 
     // Send multiple requests. Without the Cache-Control response header all
@@ -2173,10 +1958,10 @@
     settings_.expected_send_count = 3;
     settings_.expected_receive_count = 3;
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupCacheSkipFlagTest(const base::Closure& complete_callback) {
+  void SetupCacheSkipFlagTest(base::OnceClosure complete_callback) {
     SetupCacheShared("CacheSkipFlagTest.html", true);
 
     // Skip the cache despite the the Cache-Control response header.
@@ -2190,13 +1975,13 @@
     settings_.expected_send_count = 3;
     settings_.expected_receive_count = 2;
     settings_.setup_next_request =
-        base::Bind(&RequestTestRunner::SetupCacheSkipFlagTestNext, this);
+        base::BindOnce(&RequestTestRunner::SetupCacheSkipFlagTestNext, this);
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
   void SetupCacheSkipFlagTestNext(int next_send_count,
-                                  const base::Closure& complete_callback) {
+                                  base::OnceClosure complete_callback) {
     // Recreate the request object because the existing object will now be
     // read-only.
     EXPECT_TRUE(settings_.request->IsReadOnly());
@@ -2205,13 +1990,13 @@
     // Expect a cached response.
     settings_.expect_response_was_cached = true;
     settings_.setup_next_request =
-        base::Bind(&RequestTestRunner::SetupCacheSkipFlagTestLast, this);
+        base::BindOnce(&RequestTestRunner::SetupCacheSkipFlagTestLast, this);
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
   void SetupCacheSkipFlagTestLast(int next_send_count,
-                                  const base::Closure& complete_callback) {
+                                  base::OnceClosure complete_callback) {
     // Recreate the request object because the existing object will now be
     // read-only.
     EXPECT_TRUE(settings_.request->IsReadOnly());
@@ -2222,12 +2007,12 @@
 
     // Expect the cache to be skipped.
     settings_.expect_response_was_cached = false;
-    settings_.setup_next_request.Reset();
+    EXPECT_TRUE(settings_.setup_next_request.is_null());
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupCacheSkipHeaderTest(const base::Closure& complete_callback) {
+  void SetupCacheSkipHeaderTest(base::OnceClosure complete_callback) {
     SetupCacheShared("CacheSkipHeaderTest.html", true);
 
     // Skip the cache despite the the Cache-Control response header.
@@ -2243,13 +2028,13 @@
     settings_.expected_send_count = 3;
     settings_.expected_receive_count = 2;
     settings_.setup_next_request =
-        base::Bind(&RequestTestRunner::SetupCacheSkipHeaderTestNext, this);
+        base::BindOnce(&RequestTestRunner::SetupCacheSkipHeaderTestNext, this);
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
   void SetupCacheSkipHeaderTestNext(int next_send_count,
-                                    const base::Closure& complete_callback) {
+                                    base::OnceClosure complete_callback) {
     // Recreate the request object because the existing object will now be
     // read-only.
     EXPECT_TRUE(settings_.request->IsReadOnly());
@@ -2258,13 +2043,13 @@
     // Expect a cached response.
     settings_.expect_response_was_cached = true;
     settings_.setup_next_request =
-        base::Bind(&RequestTestRunner::SetupCacheSkipHeaderTestLast, this);
+        base::BindOnce(&RequestTestRunner::SetupCacheSkipHeaderTestLast, this);
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
   void SetupCacheSkipHeaderTestLast(int next_send_count,
-                                    const base::Closure& complete_callback) {
+                                    base::OnceClosure complete_callback) {
     // Recreate the request object because the existing object will now be
     // read-only.
     EXPECT_TRUE(settings_.request->IsReadOnly());
@@ -2275,12 +2060,12 @@
 
     // Expect the cache to be skipped.
     settings_.expect_response_was_cached = false;
-    settings_.setup_next_request.Reset();
+    EXPECT_TRUE(settings_.setup_next_request.is_null());
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupCacheOnlyFailureFlagTest(const base::Closure& complete_callback) {
+  void SetupCacheOnlyFailureFlagTest(base::OnceClosure complete_callback) {
     SetupCacheShared("CacheOnlyFailureFlagTest.html", true);
 
     // Only handle from the cache.
@@ -2294,10 +2079,10 @@
     // The request is expected to fail.
     settings_.SetRequestFailureExpected(ERR_CACHE_MISS);
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupCacheOnlyFailureHeaderTest(const base::Closure& complete_callback) {
+  void SetupCacheOnlyFailureHeaderTest(base::OnceClosure complete_callback) {
     SetupCacheShared("CacheOnlyFailureFlagTest.html", true);
 
     // Only handle from the cache.
@@ -2313,10 +2098,10 @@
     // The request is expected to fail.
     settings_.SetRequestFailureExpected(ERR_CACHE_MISS);
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupCacheOnlySuccessFlagTest(const base::Closure& complete_callback) {
+  void SetupCacheOnlySuccessFlagTest(base::OnceClosure complete_callback) {
     SetupCacheShared("CacheOnlySuccessFlagTest.html", false);
 
     // Send multiple requests. The 1st request will be handled normally. The
@@ -2325,13 +2110,13 @@
     settings_.expected_send_count = 3;
     settings_.expected_receive_count = 1;
     settings_.setup_next_request =
-        base::Bind(&RequestTestRunner::SetupCacheOnlySuccessFlagNext, this);
+        base::BindOnce(&RequestTestRunner::SetupCacheOnlySuccessFlagNext, this);
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
   void SetupCacheOnlySuccessFlagNext(int next_send_count,
-                                     const base::Closure& complete_callback) {
+                                     base::OnceClosure complete_callback) {
     // Recreate the request object because the existing object will now be
     // read-only.
     EXPECT_TRUE(settings_.request->IsReadOnly());
@@ -2343,12 +2128,12 @@
 
     // The following requests will use the same setup, so no more callbacks
     // are required.
-    settings_.setup_next_request.Reset();
+    EXPECT_TRUE(settings_.setup_next_request.is_null());
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupCacheOnlySuccessHeaderTest(const base::Closure& complete_callback) {
+  void SetupCacheOnlySuccessHeaderTest(base::OnceClosure complete_callback) {
     SetupCacheShared("CacheOnlySuccessHeaderTest.html", false);
 
     // Send multiple requests. The 1st request will be handled normally. The
@@ -2356,14 +2141,14 @@
     // require cached data.
     settings_.expected_send_count = 3;
     settings_.expected_receive_count = 1;
-    settings_.setup_next_request =
-        base::Bind(&RequestTestRunner::SetupCacheOnlySuccessHeaderNext, this);
+    settings_.setup_next_request = base::BindOnce(
+        &RequestTestRunner::SetupCacheOnlySuccessHeaderNext, this);
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
   void SetupCacheOnlySuccessHeaderNext(int next_send_count,
-                                       const base::Closure& complete_callback) {
+                                       base::OnceClosure complete_callback) {
     // Recreate the request object because the existing object will now be
     // read-only.
     EXPECT_TRUE(settings_.request->IsReadOnly());
@@ -2377,12 +2162,12 @@
 
     // The following requests will use the same setup, so no more callbacks
     // are required.
-    settings_.setup_next_request.Reset();
+    EXPECT_TRUE(settings_.setup_next_request.is_null());
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupCacheDisableFlagTest(const base::Closure& complete_callback) {
+  void SetupCacheDisableFlagTest(base::OnceClosure complete_callback) {
     SetupCacheShared("CacheDisableFlagTest.html", true);
 
     // Disable the cache despite the the Cache-Control response header.
@@ -2395,13 +2180,13 @@
     settings_.expected_send_count = 3;
     settings_.expected_receive_count = 1;
     settings_.setup_next_request =
-        base::Bind(&RequestTestRunner::SetupCacheDisableFlagTestNext, this);
+        base::BindOnce(&RequestTestRunner::SetupCacheDisableFlagTestNext, this);
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
   void SetupCacheDisableFlagTestNext(int next_send_count,
-                                     const base::Closure& complete_callback) {
+                                     base::OnceClosure complete_callback) {
     // Recreate the request object because the existing object will now be
     // read-only.
     EXPECT_TRUE(settings_.request->IsReadOnly());
@@ -2415,12 +2200,12 @@
 
     // The following requests will use the same setup, so no more callbacks
     // are required.
-    settings_.setup_next_request.Reset();
+    EXPECT_TRUE(settings_.setup_next_request.is_null());
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupCacheDisableHeaderTest(const base::Closure& complete_callback) {
+  void SetupCacheDisableHeaderTest(base::OnceClosure complete_callback) {
     SetupCacheShared("CacheDisableHeaderTest.html", true);
 
     // Disable the cache despite the the Cache-Control response header.
@@ -2434,14 +2219,14 @@
     // from the cache should fail.
     settings_.expected_send_count = 3;
     settings_.expected_receive_count = 1;
-    settings_.setup_next_request =
-        base::Bind(&RequestTestRunner::SetupCacheDisableHeaderTestNext, this);
+    settings_.setup_next_request = base::BindOnce(
+        &RequestTestRunner::SetupCacheDisableHeaderTestNext, this);
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
   void SetupCacheDisableHeaderTestNext(int next_send_count,
-                                       const base::Closure& complete_callback) {
+                                       base::OnceClosure complete_callback) {
     // Recreate the request object because the existing object will now be
     // read-only.
     EXPECT_TRUE(settings_.request->IsReadOnly());
@@ -2457,13 +2242,12 @@
 
     // The following requests will use the same setup, so no more callbacks
     // are required.
-    settings_.setup_next_request.Reset();
+    EXPECT_TRUE(settings_.setup_next_request.is_null());
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupIncompleteProcessRequestTest(
-      const base::Closure& complete_callback) {
+  void SetupIncompleteProcessRequestTest(base::OnceClosure complete_callback) {
     // Start with the normal get test.
     SetupGetTestShared();
 
@@ -2477,10 +2261,10 @@
     settings_.expect_download_progress = false;
     settings_.expect_download_data = false;
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void SetupIncompleteReadResponseTest(const base::Closure& complete_callback) {
+  void SetupIncompleteReadResponseTest(base::OnceClosure complete_callback) {
     // Start with the normal get test.
     SetupGetTestShared();
 
@@ -2488,59 +2272,57 @@
 
     // There will be a response but the request will be aborted without
     // receiving any data.
-    settings_.response_data = kIncompleteDoNotSendData;
+    settings_.response_data = test_server::kIncompleteDoNotSendData;
     settings_.expected_error_code = ERR_ABORTED;
     settings_.expected_status = UR_FAILED;
-    // TODO(network): Download progress notifications are sent for incomplete
-    // (with no data sent) requests in the browser process but not the renderer
-    // process. Consider standardizing this behavior.
-    settings_.expect_download_progress = is_browser_process_;
+    settings_.expect_download_progress = true;
     settings_.expect_download_data = false;
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
   // Send a request. |complete_callback| will be executed on request completion.
-  void SendRequest(
-      const RequestClient::RequestCompleteCallback& complete_callback) {
-    CefRefPtr<CefRequest> request;
-    if (settings_.redirect_request)
-      request = settings_.redirect_request;
-    else
-      request = settings_.request;
-    EXPECT_TRUE(request.get());
+  void SendRequest(test_request::RequestDoneCallback done_callback) {
+    test_request::SendConfig config;
 
-    CefRefPtr<RequestClient> client = new RequestClient(complete_callback);
+    if (settings_.redirect_request) {
+      config.request_ = settings_.redirect_request;
+    } else {
+      config.request_ = settings_.request;
+    }
+    EXPECT_TRUE(config.request_.get());
 
     // Not delegating to CefRequestHandler::GetAuthCredentials.
     if (!use_frame_method_ && settings_.expect_authentication) {
-      client->has_authentication_ = true;
-      client->username_ = settings_.username;
-      client->password_ = settings_.password;
+      config.has_credentials_ = true;
+      config.username_ = settings_.username;
+      config.password_ = settings_.password;
     }
 
     if (use_frame_method_) {
       EXPECT_TRUE(frame_);
-      frame_->CreateURLRequest(request, client.get());
+      config.frame_ = frame_;
     } else {
-      CefURLRequest::Create(request, client.get(), request_context_);
+      config.request_context_ = request_context_;
     }
 
+    test_request::Send(config, std::move(done_callback));
+
     if (settings_.incomplete_type != RequestRunSettings::INCOMPLETE_NONE) {
-      incomplete_request_callback_.Run();
-      incomplete_request_callback_.Reset();
+      std::move(incomplete_request_callback_).Run();
     }
   }
 
   // Verify a response.
-  void VerifyResponse(CefRefPtr<RequestClient> client) {
+  void VerifyResponse(const test_request::State* const client) {
     CefRefPtr<CefRequest> expected_request;
     CefRefPtr<CefResponse> expected_response;
 
-    if (settings_.redirect_request)
+    if (settings_.redirect_request) {
       expected_request = settings_.redirect_request;
-    else
+    } else {
       expected_request = settings_.request;
+    }
 
     if (settings_.redirect_response && !settings_.expect_follow_redirect) {
       // A redirect response was sent but the redirect is not expected to be
@@ -2554,8 +2336,9 @@
 
     EXPECT_EQ(settings_.expected_status, client->status_);
     EXPECT_EQ(settings_.expected_error_code, client->error_code_);
-    if (expected_response && client->response_)
+    if (expected_response && client->response_) {
       TestResponseEqual(expected_response, client->response_, true);
+    }
 
     EXPECT_EQ(settings_.expect_response_was_cached,
               client->response_was_cached_);
@@ -2567,7 +2350,7 @@
 
       std::string upload_data;
       GetUploadData(expected_request, upload_data);
-      EXPECT_EQ((int64)upload_data.size(), client->upload_total_);
+      EXPECT_EQ((int64_t)upload_data.size(), client->upload_total_);
     } else {
       EXPECT_EQ(0, client->upload_progress_ct_);
       EXPECT_EQ(0, client->upload_total_);
@@ -2575,8 +2358,8 @@
 
     if (settings_.expect_download_progress) {
       EXPECT_LE(1, client->download_progress_ct_);
-      EXPECT_EQ((int64)(settings_.response_data.size() -
-                        settings_.expected_download_offset),
+      EXPECT_EQ((int64_t)(settings_.response_data.size() -
+                          settings_.expected_download_offset),
                 client->download_total_);
     } else {
       EXPECT_EQ(0, client->download_progress_ct_);
@@ -2601,57 +2384,54 @@
   }
 
   // Run a test with a single request.
-  void SingleRunTest(const base::Closure& complete_callback) {
-    SendRequest(base::Bind(&RequestTestRunner::SingleRunTestComplete, this,
-                           complete_callback));
+  void SingleRunTest(base::OnceClosure complete_callback) {
+    SendRequest(base::BindOnce(&RequestTestRunner::SingleRunTestComplete, this,
+                               std::move(complete_callback)));
   }
 
-  void SingleRunTestComplete(const base::Closure& complete_callback,
-                             CefRefPtr<RequestClient> completed_client) {
-    VerifyResponse(completed_client);
-    complete_callback.Run();
+  void SingleRunTestComplete(base::OnceClosure complete_callback,
+                             const test_request::State& completed_client) {
+    VerifyResponse(&completed_client);
+    std::move(complete_callback).Run();
   }
 
   // Run a test with multiple requests.
-  void MultipleRunTest(const base::Closure& complete_callback) {
+  void MultipleRunTest(base::OnceClosure complete_callback) {
     EXPECT_GT(settings_.expected_send_count, 0);
     EXPECT_GE(settings_.expected_receive_count, 0);
-    MultipleRunTestContinue(complete_callback, 1);
+    MultipleRunTestContinue(std::move(complete_callback), 1);
   }
 
-  void MultipleRunTestContinue(const base::Closure& complete_callback,
+  void MultipleRunTestContinue(base::OnceClosure complete_callback,
                                int send_count) {
     // Send the next request.
-    SendRequest(base::Bind(&RequestTestRunner::MultipleRunTestNext, this,
-                           complete_callback, send_count));
+    SendRequest(base::BindOnce(&RequestTestRunner::MultipleRunTestNext, this,
+                               std::move(complete_callback), send_count));
   }
 
-  void MultipleRunTestNext(const base::Closure& complete_callback,
+  void MultipleRunTestNext(base::OnceClosure complete_callback,
                            int send_count,
-                           CefRefPtr<RequestClient> completed_client) {
+                           const test_request::State& completed_client) {
     // Verify the completed request.
-    VerifyResponse(completed_client);
+    VerifyResponse(&completed_client);
 
     if (send_count == settings_.expected_send_count) {
       // All requests complete.
-      complete_callback.Run();
+      std::move(complete_callback).Run();
       return;
     }
 
     const int next_send_count = send_count + 1;
-    const base::Closure& continue_callback =
-        base::Bind(&RequestTestRunner::MultipleRunTestContinue, this,
-                   complete_callback, next_send_count);
+    auto continue_callback =
+        base::BindOnce(&RequestTestRunner::MultipleRunTestContinue, this,
+                       std::move(complete_callback), next_send_count);
 
     if (!settings_.setup_next_request.is_null()) {
       // Provide an opportunity to modify expectations before the next request.
-      // Copy the callback object in case |settings_.setup_next_request| is
-      // modified as a result of the call.
-      RequestRunSettings::NextRequestCallback next_callback =
-          settings_.setup_next_request;
-      next_callback.Run(next_send_count, continue_callback);
+      std::move(settings_.setup_next_request)
+          .Run(next_send_count, std::move(continue_callback));
     } else {
-      continue_callback.Run();
+      std::move(continue_callback).Run();
     }
   }
 
@@ -2663,57 +2443,52 @@
     test_map_.insert(std::make_pair(test_mode, entry));
   }
 
-  void CompleteOnCorrectThread(const base::Closure& complete_callback) {
+  void CompleteOnCorrectThread(base::OnceClosure complete_callback) {
     if (!owner_task_runner_->BelongsToCurrentThread()) {
       owner_task_runner_->PostTask(CefCreateClosureTask(
-          base::Bind(&RequestTestRunner::CompleteOnCorrectThread, this,
-                     complete_callback)));
+          base::BindOnce(&RequestTestRunner::CompleteOnCorrectThread, this,
+                         std::move(complete_callback))));
       return;
     }
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
-  void RunDeleteTempDirectory(const base::Closure& complete_callback) {
-    EXPECT_TRUE(CefCurrentlyOn(TID_FILE));
+  void RunDeleteTempDirectory(base::OnceClosure complete_callback) {
+    EXPECT_TRUE(CefCurrentlyOn(TID_FILE_USER_VISIBLE));
 
     EXPECT_TRUE(post_file_tmpdir_.Delete());
     EXPECT_TRUE(post_file_tmpdir_.IsEmpty());
 
     // Continue with test shutdown.
-    RunShutdown(complete_callback);
+    RunShutdown(std::move(complete_callback));
   }
 
-  void RunShutdown(const base::Closure& complete_callback) {
+  void RunShutdown(base::OnceClosure complete_callback) {
     if (!owner_task_runner_->BelongsToCurrentThread()) {
-      owner_task_runner_->PostTask(CefCreateClosureTask(base::Bind(
-          &RequestTestRunner::RunShutdown, this, complete_callback)));
+      owner_task_runner_->PostTask(CefCreateClosureTask(
+          base::BindOnce(&RequestTestRunner::RunShutdown, this,
+                         std::move(complete_callback))));
       return;
     }
 
-    if (is_browser_process_) {
-      ShutdownTestBackend(complete_callback);
-    } else {
-      complete_callback.Run();
-    }
+    ShutdownTestBackend(std::move(complete_callback));
   }
 
   // Create the backend for the current test. Called during test setup.
-  void SetupTestBackend(const base::Closure& complete_callback) {
-    // Backends are only created in the browser process.
-    EXPECT_TRUE(is_browser_process_);
-
+  void SetupTestBackend(base::OnceClosure complete_callback) {
     EXPECT_TRUE(settings_.request.get());
     EXPECT_TRUE(settings_.response.get() ||
                 settings_.expected_status == UR_FAILED);
 
-    if (is_server_backend_)
-      StartServer(complete_callback);
-    else
-      AddSchemeHandler(complete_callback);
+    if (is_server_backend_) {
+      StartServer(std::move(complete_callback));
+    } else {
+      AddSchemeHandler(std::move(complete_callback));
+    }
   }
 
-  void StartServer(const base::Closure& complete_callback) {
+  void StartServer(base::OnceClosure complete_callback) {
     EXPECT_FALSE(server_handler_);
 
     server_handler_ = new RequestServerHandler();
@@ -2724,10 +2499,10 @@
           settings_.expected_receive_count);
     }
 
-    server_handler_->CreateServer(complete_callback);
+    server_handler_->CreateServer(std::move(complete_callback));
   }
 
-  void AddSchemeHandler(const base::Closure& complete_callback) {
+  void AddSchemeHandler(base::OnceClosure complete_callback) {
     EXPECT_FALSE(scheme_factory_);
 
     // Add the factory registration.
@@ -2741,47 +2516,43 @@
     // Any further calls will come from the IO thread.
     scheme_factory_->SetOwnerTaskRunner(CefTaskRunner::GetForThread(TID_IO));
 
-    complete_callback.Run();
+    std::move(complete_callback).Run();
   }
 
   // Shutdown the backend for the current test. Called during test shutdown.
-  void ShutdownTestBackend(const base::Closure& complete_callback) {
-    // Backends are only created in the browser process.
-    EXPECT_TRUE(is_browser_process_);
-    if (is_server_backend_)
-      ShutdownServer(complete_callback);
-    else
-      RemoveSchemeHandler(complete_callback);
+  void ShutdownTestBackend(base::OnceClosure complete_callback) {
+    if (is_server_backend_) {
+      ShutdownServer(std::move(complete_callback));
+    } else {
+      RemoveSchemeHandler(std::move(complete_callback));
+    }
   }
 
-  void ShutdownServer(const base::Closure& complete_callback) {
+  void ShutdownServer(base::OnceClosure complete_callback) {
     EXPECT_TRUE(server_handler_);
 
-    server_handler_->ShutdownServer(complete_callback);
+    // |server_handler_| will delete itself after shutdown.
+    server_handler_->ShutdownServer(std::move(complete_callback));
     server_handler_ = nullptr;
   }
 
-  void RemoveSchemeHandler(const base::Closure& complete_callback) {
+  void RemoveSchemeHandler(base::OnceClosure complete_callback) {
     EXPECT_TRUE(scheme_factory_);
 
     // Remove the factory registration.
     request_context_->RegisterSchemeHandlerFactory(
         GetRequestScheme(false), GetRequestHost(false, false), nullptr);
-    scheme_factory_->Shutdown(complete_callback);
+    scheme_factory_->Shutdown(std::move(complete_callback));
     scheme_factory_ = nullptr;
   }
 
-  const bool is_browser_process_;
   const bool is_server_backend_;
   const bool use_frame_method_;
-  const bool run_in_browser_process_;
 
   // Used with incomplete request tests.
-  base::Closure incomplete_request_callback_;
+  base::OnceClosure incomplete_request_callback_;
 
-  // Primary thread runner for the object that owns us. In the browser process
-  // this will be the UI thread and in the renderer process this will be the
-  // RENDERER thread.
+  // Primary thread runner (UI thread) for the object that owns us.
   CefRefPtr<CefTaskRunner> owner_task_runner_;
 
   CefRefPtr<CefRequestContext> request_context_;
@@ -2797,7 +2568,7 @@
   TestMap test_map_;
 
   // Server backend.
-  CefRefPtr<RequestServerHandler> server_handler_;
+  RequestServerHandler* server_handler_ = nullptr;
 
   // Scheme handler backend.
   std::string scheme_name_;
@@ -2809,169 +2580,65 @@
   RequestRunSettings settings_;
 };
 
-// RENDERER-SIDE TEST HARNESS
-
-class RequestRendererTest : public ClientAppRenderer::Delegate {
- public:
-  RequestRendererTest() {}
-
-  bool OnProcessMessageReceived(CefRefPtr<ClientAppRenderer> app,
-                                CefRefPtr<CefBrowser> browser,
-                                CefRefPtr<CefFrame> frame,
-                                CefProcessId source_process,
-                                CefRefPtr<CefProcessMessage> message) override {
-    if (message->GetName() == kRequestTestMsg) {
-      EXPECT_TRUE(CefCurrentlyOn(TID_RENDERER));
-      EXPECT_TRUE(frame->IsMain());
-
-      app_ = app;
-      browser_ = browser;
-      frame_ = nullptr;
-
-      CefRefPtr<CefListValue> args = message->GetArgumentList();
-
-      const bool use_frame_method = args->GetBool(2);
-      if (use_frame_method)
-        frame_ = frame;
-
-      test_mode_ = static_cast<RequestTestMode>(args->GetInt(0));
-      test_runner_ = new RequestTestRunner(
-          false, args->GetBool(1), use_frame_method, false,
-          base::Bind(&RequestRendererTest::OnIncompleteRequest, this));
-
-      // Setup the test. This will create the objects that we test against but
-      // not register any backend (because we're in the render process).
-      test_runner_->SetupTest(
-          test_mode_, base::Bind(&RequestRendererTest::OnSetupComplete, this));
-
-      return true;
-    }
-
-    // Message not handled.
-    return false;
-  }
-
- private:
-  void OnSetupComplete() {
-    EXPECT_TRUE(CefCurrentlyOn(TID_RENDERER));
-
-    // Run the test.
-    test_runner_->RunTest(
-        test_mode_, frame_,
-        base::Bind(&RequestRendererTest::OnRunComplete, this));
-  }
-
-  void OnRunComplete() {
-    EXPECT_TRUE(CefCurrentlyOn(TID_RENDERER));
-
-    // Shutdown the test.
-    test_runner_->ShutdownTest(
-        base::Bind(&RequestRendererTest::OnShutdownComplete, this));
-  }
-
-  void OnIncompleteRequest() {
-    EXPECT_TRUE(CefCurrentlyOn(TID_RENDERER));
-
-    // This method will only be called for incomplete requests.
-    EXPECT_NE(test_runner_->settings_.incomplete_type,
-              RequestRunSettings::INCOMPLETE_NONE);
-
-    // Check if the test has failed.
-    bool result = !TestFailed();
-
-    // The browser will be closed to abort in-progress requests.
-    CefRefPtr<CefProcessMessage> return_msg =
-        CefProcessMessage::Create(kIncompleteRequestTestMsg);
-    EXPECT_TRUE(return_msg->GetArgumentList()->SetBool(0, result));
-    browser_->GetMainFrame()->SendProcessMessage(PID_BROWSER, return_msg);
-  }
-
-  void OnShutdownComplete() {
-    EXPECT_TRUE(CefCurrentlyOn(TID_RENDERER));
-
-    if (test_runner_->settings_.incomplete_type !=
-        RequestRunSettings::INCOMPLETE_NONE) {
-      // For incomplete tests there's a race between process destruction due to
-      // the browser closing, and the test possibly completing due to request
-      // cancellation. We therefore ignore test completion in this case.
-      return;
-    }
-
-    // Check if the test has failed.
-    bool result = !TestFailed();
-
-    // Return the result to the browser process.
-    CefRefPtr<CefProcessMessage> return_msg =
-        CefProcessMessage::Create(kRequestTestMsg);
-    EXPECT_TRUE(return_msg->GetArgumentList()->SetBool(0, result));
-    browser_->GetMainFrame()->SendProcessMessage(PID_BROWSER, return_msg);
-
-    app_ = nullptr;
-    browser_ = nullptr;
-  }
-
-  CefRefPtr<ClientAppRenderer> app_;
-  CefRefPtr<CefBrowser> browser_;
-  CefRefPtr<CefFrame> frame_;
-  RequestTestMode test_mode_;
-
-  scoped_refptr<RequestTestRunner> test_runner_;
-
-  IMPLEMENT_REFCOUNTING(RequestRendererTest);
-};
-
-// BROWSER-SIDE TEST HARNESS
-
 class RequestTestHandler : public TestHandler {
  public:
   RequestTestHandler(RequestTestMode test_mode,
                      ContextTestMode context_mode,
-                     bool test_in_browser,
                      bool test_server_backend,
                      bool test_frame_method)
       : test_mode_(test_mode),
         context_mode_(context_mode),
-        test_in_browser_(test_in_browser),
         test_server_backend_(test_server_backend),
         test_frame_method_(test_frame_method),
-        // Must use the request origin to avoid failures in
-        // CorsURLLoaderFactory::IsSane for requests originating from the
-        // renderer process.
         test_url_(GetRequestOrigin(test_server_backend) +
                   "/URLRequestTest.Test") {}
 
   void RunTest() override {
     // Time out the test after a reasonable period of time.
-    SetTestTimeout();
+    SetTestTimeout(5000);
 
     // Start pre-setup actions.
     PreSetupStart();
   }
 
   void PreSetupStart() {
-    CefPostTask(TID_FILE,
-                base::Bind(&RequestTestHandler::PreSetupFileTasks, this));
+    CefPostTask(TID_FILE_USER_VISIBLE,
+                base::BindOnce(&RequestTestHandler::PreSetupFileTasks, this));
   }
 
   void PreSetupFileTasks() {
-    EXPECT_TRUE(CefCurrentlyOn(TID_FILE));
+    EXPECT_TRUE(CefCurrentlyOn(TID_FILE_USER_VISIBLE));
 
     if (context_mode_ == CONTEXT_ONDISK) {
-      EXPECT_TRUE(context_tmpdir_.CreateUniqueTempDir());
+      EXPECT_TRUE(context_tmpdir_.CreateUniqueTempDirUnderPath(
+          CefTestSuite::GetInstance()->root_cache_path()));
       context_tmpdir_path_ = context_tmpdir_.GetPath();
       EXPECT_FALSE(context_tmpdir_path_.empty());
     }
 
     CefPostTask(TID_UI,
-                base::Bind(&RequestTestHandler::PreSetupContinue, this));
+                base::BindOnce(&RequestTestHandler::PreSetupContinue, this));
   }
 
   void PreSetupContinue() {
     EXPECT_TRUE(CefCurrentlyOn(TID_UI));
 
     test_runner_ = new RequestTestRunner(
-        true, test_server_backend_, test_frame_method_, test_in_browser_,
-        base::Bind(&RequestTestHandler::OnIncompleteRequest, this));
+        test_server_backend_, test_frame_method_,
+        base::BindOnce(&RequestTestHandler::OnIncompleteRequest, this));
+    test_runner_->Initialize();
+
+    // Configure the number of times that SignalTestCompletion() will be called.
+    // We need to call it at least 1 time if we don't create a browser.
+    size_t completion_count = test_frame_method_ ? 0U : 1U;
+    if (context_mode_ != CONTEXT_GLOBAL) {
+      // Don't end the test until the temporary request context has been
+      // destroyed.
+      completion_count++;
+    }
+    if (completion_count > 0U) {
+      SetSignalTestCompletionCount(completion_count);
+    }
 
     // Get or create the request context.
     if (context_mode_ == CONTEXT_GLOBAL) {
@@ -2982,10 +2649,6 @@
 
       PreSetupComplete();
     } else {
-      // Don't end the test until the temporary request context has been
-      // destroyed.
-      SetSignalCompletionWhenAllBrowsersClose(false);
-
       CefRequestContextSettings settings;
 
       if (context_mode_ == CONTEXT_ONDISK) {
@@ -2993,83 +2656,70 @@
         CefString(&settings.cache_path) = context_tmpdir_path_;
       }
 
-      // Create a new temporary request context.
-      CefRefPtr<CefRequestContext> request_context =
-          CefRequestContext::CreateContext(settings,
-                                           new RequestContextHandler(this));
-      EXPECT_TRUE(request_context.get());
-      test_runner_->SetRequestContext(request_context);
-
       if (!test_server_backend_) {
         // Set the schemes that are allowed to store cookies.
-        std::vector<CefString> supported_schemes;
-        supported_schemes.push_back(GetRequestScheme(false));
-
-        // Continue the test once supported schemes has been set.
-        request_context->GetCookieManager(nullptr)->SetSupportedSchemes(
-            supported_schemes, true,
-            new TestCompletionCallback(
-                base::Bind(&RequestTestHandler::PreSetupComplete, this)));
-      } else {
-        PreSetupComplete();
+        CefString(&settings.cookieable_schemes_list) = GetRequestScheme(false);
       }
+
+      // Create a new temporary request context. Calls OnContextInitialized.
+      CefRequestContext::CreateContext(settings,
+                                       new RequestContextHandler(this));
     }
   }
 
+  void OnContextInitialized(CefRefPtr<CefRequestContext> request_context) {
+    EXPECT_TRUE(CefCurrentlyOn(TID_UI));
+    EXPECT_TRUE(request_context.get());
+    test_runner_->SetRequestContext(request_context);
+    PreSetupComplete();
+  }
+
   void PreSetupComplete() {
     if (!CefCurrentlyOn(TID_UI)) {
       CefPostTask(TID_UI,
-                  base::Bind(&RequestTestHandler::PreSetupComplete, this));
+                  base::BindOnce(&RequestTestHandler::PreSetupComplete, this));
       return;
     }
 
     // Setup the test. This will create the objects that we test against and
     // register the backend.
     test_runner_->SetupTest(
-        test_mode_, base::Bind(&RequestTestHandler::OnSetupComplete, this));
+        test_mode_, base::BindOnce(&RequestTestHandler::OnSetupComplete, this));
   }
 
   // Browser process setup is complete.
   void OnSetupComplete() {
     // Start post-setup actions.
     SetTestCookie(test_runner_->GetRequestContext(), test_server_backend_,
-                  base::Bind(&RequestTestHandler::PostSetupComplete, this));
+                  base::BindOnce(&RequestTestHandler::PostSetupComplete, this));
   }
 
   void PostSetupComplete() {
     if (!CefCurrentlyOn(TID_UI)) {
       CefPostTask(TID_UI,
-                  base::Bind(&RequestTestHandler::PostSetupComplete, this));
+                  base::BindOnce(&RequestTestHandler::PostSetupComplete, this));
       return;
     }
 
-    if (test_in_browser_) {
-      if (test_frame_method_) {
-        AddResource(test_url_, "<html><body>TEST</body></html>", "text/html");
-
-        // Create the browser who's main frame will be the initiator for the
-        // request.
-        CreateBrowser(test_url_, test_runner_->GetRequestContext());
-      } else {
-        // Run the test now.
-        test_running_ = true;
-        test_runner_->RunTest(
-            test_mode_, nullptr /* frame */,
-            base::Bind(&RequestTestHandler::OnRunComplete, this));
-      }
-    } else {
+    if (test_frame_method_) {
       AddResource(test_url_, "<html><body>TEST</body></html>", "text/html");
 
-      // Create a browser to run the test in the renderer process.
+      // Create the browser who's main frame will be the initiator for the
+      // request.
       CreateBrowser(test_url_, test_runner_->GetRequestContext());
+    } else {
+      // Run the test now.
+      test_running_ = true;
+      test_runner_->RunTest(
+          test_mode_, nullptr /* frame */,
+          base::BindOnce(&RequestTestHandler::OnRunComplete, this));
     }
   }
 
-  ReturnValue OnBeforeResourceLoad(
-      CefRefPtr<CefBrowser> browser,
-      CefRefPtr<CefFrame> frame,
-      CefRefPtr<CefRequest> request,
-      CefRefPtr<CefRequestCallback> callback) override {
+  ReturnValue OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser,
+                                   CefRefPtr<CefFrame> frame,
+                                   CefRefPtr<CefRequest> request,
+                                   CefRefPtr<CefCallback> callback) override {
     if (test_running_ && test_frame_method_) {
       EXPECT_TRUE(frame);
       EXPECT_EQ(test_frame_->GetIdentifier(), frame->GetIdentifier());
@@ -3087,7 +2737,6 @@
                           const CefString& realm,
                           const CefString& scheme,
                           CefRefPtr<CefAuthCallback> callback) override {
-    EXPECT_TRUE(test_in_browser_);
     EXPECT_TRUE(test_frame_method_);
     auth_credentials_ct_++;
     if (test_runner_->settings_.expect_authentication) {
@@ -3101,81 +2750,23 @@
   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
                  CefRefPtr<CefFrame> frame,
                  int httpStatusCode) override {
-    if (test_in_browser_ && test_frame_method_) {
+    if (test_frame_method_) {
       // Run the test now.
       test_frame_ = frame;
       test_running_ = true;
       test_runner_->RunTest(
           test_mode_, frame,
-          base::Bind(&RequestTestHandler::OnRunComplete, this));
+          base::BindOnce(&RequestTestHandler::OnRunComplete, this));
       return;
     }
-
-    EXPECT_FALSE(test_in_browser_);
-    if (frame->IsMain()) {
-      CefRefPtr<CefProcessMessage> test_message =
-          CefProcessMessage::Create(kRequestTestMsg);
-      CefRefPtr<CefListValue> args = test_message->GetArgumentList();
-      EXPECT_TRUE(args->SetInt(0, test_mode_));
-      EXPECT_TRUE(args->SetBool(1, test_server_backend_));
-      EXPECT_TRUE(args->SetBool(2, test_frame_method_));
-
-      if (test_frame_method_)
-        test_frame_ = frame;
-      test_running_ = true;
-
-      // Send a message to the renderer process to run the test.
-      frame->SendProcessMessage(PID_RENDERER, test_message);
-    }
-  }
-
-  bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
-                                CefRefPtr<CefFrame> frame,
-                                CefProcessId source_process,
-                                CefRefPtr<CefProcessMessage> message) override {
-    EXPECT_TRUE(browser.get());
-    EXPECT_TRUE(frame.get());
-    EXPECT_EQ(PID_RENDERER, source_process);
-    EXPECT_TRUE(message.get());
-    EXPECT_TRUE(message->IsReadOnly());
-    EXPECT_FALSE(test_in_browser_);
-
-    EXPECT_FALSE(got_message_);
-    got_message_.yes();
-
-    if (message->GetArgumentList()->GetBool(0))
-      got_success_.yes();
-
-    const std::string& message_name = message->GetName();
-    if (message_name == kRequestTestMsg) {
-      // Renderer process test is complete.
-      OnRunComplete();
-    } else if (message_name == kIncompleteRequestTestMsg) {
-      // Incomplete renderer tests will not complete normally. Instead, trigger
-      // browser close and then signal completion from OnBeforeClose.
-      OnIncompleteRequest();
-    }
-
-    return true;
-  }
-
-  void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
-    if (!test_in_browser_ && test_runner_->settings_.incomplete_type !=
-                                 RequestRunSettings::INCOMPLETE_NONE) {
-      // Incomplete tests running in the renderer process will never recieve the
-      // test complete process message, so call the method here.
-      OnRunComplete();
-    }
-
-    TestHandler::OnBeforeClose(browser);
   }
 
   // Incomplete tests will not complete normally. Instead, we trigger a browser
   // close to abort in-progress requests.
   void OnIncompleteRequest() {
     if (!CefCurrentlyOn(TID_UI)) {
-      CefPostTask(TID_UI,
-                  base::Bind(&RequestTestHandler::OnIncompleteRequest, this));
+      CefPostTask(TID_UI, base::BindOnce(
+                              &RequestTestHandler::OnIncompleteRequest, this));
       return;
     }
 
@@ -3185,22 +2776,21 @@
 
     // TestComplete will eventually be called from DestroyTest instead of being
     // triggered by browser destruction.
-    SetSignalCompletionWhenAllBrowsersClose(false);
     CefPostDelayedTask(
-        TID_UI, base::Bind(&TestHandler::CloseBrowser, GetBrowser(), false),
+        TID_UI, base::BindOnce(&TestHandler::CloseBrowser, GetBrowser(), false),
         1000);
   }
 
-  // Test run is complete. It ran in either the browser or render process.
+  // Test run is complete.
   void OnRunComplete() {
     GetTestCookie(test_runner_->GetRequestContext(), test_server_backend_,
-                  base::Bind(&RequestTestHandler::PostRunComplete, this));
+                  base::BindOnce(&RequestTestHandler::PostRunComplete, this));
   }
 
   void PostRunComplete(bool has_save_cookie) {
     if (!CefCurrentlyOn(TID_UI)) {
-      CefPostTask(TID_UI, base::Bind(&RequestTestHandler::PostRunComplete, this,
-                                     has_save_cookie));
+      CefPostTask(TID_UI, base::BindOnce(&RequestTestHandler::PostRunComplete,
+                                         this, has_save_cookie));
       return;
     }
 
@@ -3208,7 +2798,7 @@
 
     // Shut down the browser side of the test.
     test_runner_->ShutdownTest(
-        base::Bind(&RequestTestHandler::MaybeClearAuthCredentials, this));
+        base::BindOnce(&RequestTestHandler::MaybeClearAuthCredentials, this));
   }
 
   void MaybeClearAuthCredentials() {
@@ -3218,7 +2808,7 @@
       // test runs when using the global request context.
       test_runner_->GetRequestContext()->ClearHttpAuthCredentials(
           new TestCompletionCallback(
-              base::Bind(&RequestTestHandler::DestroyTest, this)));
+              base::BindOnce(&RequestTestHandler::DestroyTest, this)));
       return;
     }
 
@@ -3226,11 +2816,6 @@
   }
 
   void DestroyTest() override {
-    if (!test_in_browser_) {
-      EXPECT_TRUE(got_message_);
-      EXPECT_TRUE(got_success_);
-    }
-
     if (test_frame_method_) {
       // Expect at least 1 call to OnBeforeResourceLoad for every test.
       // Redirect tests may get multiple calls.
@@ -3240,8 +2825,7 @@
     // CefRequestHandler::GetAuthCredentials should be called after
     // CefURLRequestClient::GetAuthCredentials when the request has an
     // associated frame.
-    if (test_in_browser_ && test_frame_method_ &&
-        test_runner_->settings_.expect_authentication) {
+    if (test_frame_method_ && test_runner_->settings_.expect_authentication) {
       EXPECT_EQ(1, auth_credentials_ct_);
     } else {
       EXPECT_EQ(0, auth_credentials_ct_);
@@ -3249,56 +2833,28 @@
 
     TestHandler::DestroyTest();
 
-    // For non-global contexts OnTestComplete() will be called when the
-    // RequestContextHandler is destroyed.
-    bool call_test_complete = false;
-    if (context_mode_ == CONTEXT_GLOBAL) {
-      if (test_in_browser_ && !test_frame_method_) {
-        // These tests don't create a browser that would signal implicitly.
-        call_test_complete = true;
-      } else if (!SignalCompletionWhenAllBrowsersClose()) {
-        // These tests close the browser to terminate in-progress requests
-        // before test completion.
-        call_test_complete = true;
-      }
-    }
-
     // Release references to the context and handler.
     test_runner_->Destroy();
 
-    if (call_test_complete)
+    // These tests don't create a browser that would signal implicitly.
+    if (!test_frame_method_) {
       OnTestComplete();
+    }
   }
 
   void OnTestComplete() {
     if (!CefCurrentlyOn(TID_UI)) {
       CefPostTask(TID_UI,
-                  base::Bind(&RequestTestHandler::OnTestComplete, this));
+                  base::BindOnce(&RequestTestHandler::OnTestComplete, this));
       return;
     }
 
-    EXPECT_FALSE(got_on_test_complete_);
-    got_on_test_complete_.yes();
-
     if (!context_tmpdir_.IsEmpty()) {
-      // Wait a bit for cache file handles to close after browser or request
-      // context destruction.
-      CefPostDelayedTask(
-          TID_FILE,
-          base::Bind(&RequestTestHandler::PostTestCompleteFileTasks, this),
-          100);
-    } else {
-      TestComplete();
+      // Temp directory will be deleted on application shutdown.
+      context_tmpdir_.Take();
     }
-  }
 
-  void PostTestCompleteFileTasks() {
-    EXPECT_TRUE(CefCurrentlyOn(TID_FILE));
-
-    EXPECT_TRUE(context_tmpdir_.Delete());
-    EXPECT_TRUE(context_tmpdir_.IsEmpty());
-
-    CefPostTask(TID_UI, base::Bind(&RequestTestHandler::TestComplete, this));
+    SignalTestCompletion();
   }
 
  private:
@@ -3310,6 +2866,11 @@
         : test_handler_(test_handler) {}
     ~RequestContextHandler() override { test_handler_->OnTestComplete(); }
 
+    void OnRequestContextInitialized(
+        CefRefPtr<CefRequestContext> request_context) override {
+      test_handler_->OnContextInitialized(request_context);
+    }
+
    private:
     CefRefPtr<RequestTestHandler> test_handler_;
 
@@ -3318,7 +2879,6 @@
 
   const RequestTestMode test_mode_;
   const ContextTestMode context_mode_;
-  const bool test_in_browser_;
   const bool test_server_backend_;
   const bool test_frame_method_;
   const std::string test_url_;
@@ -3334,123 +2894,69 @@
   CefString context_tmpdir_path_;
 
  public:
-  // Only used when the test runs in the render process.
-  TrackCallback got_message_;
-  TrackCallback got_success_;
-
   int auth_credentials_ct_ = 0;
-  TrackCallback got_on_test_complete_;
 
   IMPLEMENT_REFCOUNTING(RequestTestHandler);
 };
 
-bool IsTestSupported(RequestTestMode test_mode,
-                     ContextTestMode context_mode,
-                     bool test_in_browser,
-                     bool test_server_backend,
-                     bool test_frame_method) {
-  if (!test_in_browser && !test_server_backend && !test_frame_method) {
-    // Requests from the render process can only reach non-server backends when
-    // using the CefFrame::CreateURLRequest method.
-    return false;
-  }
-
-  return true;
-}
-
 }  // namespace
 
-// Entry point for creating URLRequest renderer test objects.
-// Called from client_app_delegates.cc.
-void CreateURLRequestRendererTests(ClientAppRenderer::DelegateSet& delegates) {
-  delegates.insert(new RequestRendererTest);
-}
-
 // Entry point for registering custom schemes.
 // Called from client_app_delegates.cc.
-void RegisterURLRequestCustomSchemes(
-    CefRawPtr<CefSchemeRegistrar> registrar,
-    std::vector<CefString>& cookiable_schemes) {
+void RegisterURLRequestCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar) {
   const std::string& scheme = GetRequestScheme(false);
   registrar->AddCustomScheme(
       scheme, CEF_SCHEME_OPTION_STANDARD | CEF_SCHEME_OPTION_CORS_ENABLED);
-  cookiable_schemes.push_back(scheme);
+}
+
+// Entry point for registering cookieable schemes.
+// Called from client_app_delegates.cc.
+void RegisterURLRequestCookieableSchemes(
+    std::vector<std::string>& cookieable_schemes) {
+  const std::string& scheme = GetRequestScheme(false);
+  cookieable_schemes.push_back(scheme);
 }
 
 // Helpers for defining URLRequest tests.
-#define REQ_TEST_EX(name, test_mode, context_mode, test_in_browser,      \
-                    test_server_backend, test_frame_method)              \
-  TEST(URLRequestTest, name) {                                           \
-    if (!IsTestSupported(test_mode, context_mode, test_in_browser,       \
-                         test_server_backend, test_frame_method)) {      \
-      return;                                                            \
-    }                                                                    \
-    CefRefPtr<RequestTestHandler> handler =                              \
-        new RequestTestHandler(test_mode, context_mode, test_in_browser, \
-                               test_server_backend, test_frame_method);  \
-    handler->ExecuteTest();                                              \
-    ReleaseAndWaitForDestructor(handler);                                \
+#define REQ_TEST(name, test_mode, context_mode, test_server_backend,      \
+                 test_frame_method)                                       \
+  TEST(URLRequestTest, name) {                                            \
+    CefRefPtr<RequestTestHandler> handler = new RequestTestHandler(       \
+        test_mode, context_mode, test_server_backend, test_frame_method); \
+    handler->ExecuteTest();                                               \
+    ReleaseAndWaitForDestructor(handler);                                 \
   }
 
-#define REQ_TEST(name, test_mode, context_mode, test_in_browser, \
-                 test_server_backend, test_frame_method)         \
-  REQ_TEST_EX(name, test_mode, context_mode, test_in_browser,    \
-              test_server_backend, test_frame_method)
-
 // Define the tests.
 #define REQ_TEST_SET_EX(suffix, context_mode, test_server_backend,             \
                         test_frame_method)                                     \
-  REQ_TEST(BrowserGET##suffix, REQTEST_GET, context_mode, true,                \
-           test_server_backend, test_frame_method)                             \
-  REQ_TEST(BrowserGETNoData##suffix, REQTEST_GET_NODATA, context_mode, true,   \
+  REQ_TEST(BrowserGET##suffix, REQTEST_GET, context_mode, test_server_backend, \
+           test_frame_method)                                                  \
+  REQ_TEST(BrowserGETNoData##suffix, REQTEST_GET_NODATA, context_mode,         \
            test_server_backend, test_frame_method)                             \
   REQ_TEST(BrowserGETPartialContent##suffix, REQTEST_GET_PARTIAL_CONTENT,      \
-           context_mode, true, test_server_backend, test_frame_method)         \
+           context_mode, test_server_backend, test_frame_method)               \
   REQ_TEST(BrowserGETAllowCookies##suffix, REQTEST_GET_ALLOWCOOKIES,           \
-           context_mode, true, test_server_backend, test_frame_method)         \
+           context_mode, test_server_backend, test_frame_method)               \
   REQ_TEST(BrowserGETRedirect##suffix, REQTEST_GET_REDIRECT, context_mode,     \
-           true, test_server_backend, test_frame_method)                       \
-  REQ_TEST(BrowserGETRedirectStop##suffix, REQTEST_GET_REDIRECT_STOP,          \
-           context_mode, true, test_server_backend, test_frame_method)         \
-  REQ_TEST(BrowserGETRedirectLocation##suffix, REQTEST_GET_REDIRECT_LOCATION,  \
-           context_mode, true, test_server_backend, test_frame_method)         \
-  REQ_TEST(BrowserGETReferrer##suffix, REQTEST_GET_REFERRER, context_mode,     \
-           true, test_server_backend, test_frame_method)                       \
-  REQ_TEST(BrowserPOST##suffix, REQTEST_POST, context_mode, true,              \
            test_server_backend, test_frame_method)                             \
-  REQ_TEST(BrowserPOSTFile##suffix, REQTEST_POST_FILE, context_mode, true,     \
+  REQ_TEST(BrowserGETRedirectStop##suffix, REQTEST_GET_REDIRECT_STOP,          \
+           context_mode, test_server_backend, test_frame_method)               \
+  REQ_TEST(BrowserGETRedirectLocation##suffix, REQTEST_GET_REDIRECT_LOCATION,  \
+           context_mode, test_server_backend, test_frame_method)               \
+  REQ_TEST(BrowserGETReferrer##suffix, REQTEST_GET_REFERRER, context_mode,     \
+           test_server_backend, test_frame_method)                             \
+  REQ_TEST(BrowserPOST##suffix, REQTEST_POST, context_mode,                    \
+           test_server_backend, test_frame_method)                             \
+  REQ_TEST(BrowserPOSTFile##suffix, REQTEST_POST_FILE, context_mode,           \
            test_server_backend, test_frame_method)                             \
   REQ_TEST(BrowserPOSTWithProgress##suffix, REQTEST_POST_WITHPROGRESS,         \
-           context_mode, true, test_server_backend, test_frame_method)         \
+           context_mode, test_server_backend, test_frame_method)               \
   REQ_TEST(BrowserPOSTRedirect##suffix, REQTEST_POST_REDIRECT, context_mode,   \
-           true, test_server_backend, test_frame_method)                       \
+           test_server_backend, test_frame_method)                             \
   REQ_TEST(BrowserPOSTRedirectToGET##suffix, REQTEST_POST_REDIRECT_TOGET,      \
-           context_mode, true, test_server_backend, test_frame_method)         \
-  REQ_TEST(BrowserHEAD##suffix, REQTEST_HEAD, context_mode, true,              \
-           test_server_backend, test_frame_method)                             \
-  REQ_TEST(RendererGET##suffix, REQTEST_GET, context_mode, false,              \
-           test_server_backend, test_frame_method)                             \
-  REQ_TEST(RendererGETNoData##suffix, REQTEST_GET_NODATA, context_mode, false, \
-           test_server_backend, test_frame_method)                             \
-  REQ_TEST(RendererGETAllowCookies##suffix, REQTEST_GET_ALLOWCOOKIES,          \
-           context_mode, false, test_server_backend, test_frame_method)        \
-  REQ_TEST(RendererGETRedirect##suffix, REQTEST_GET_REDIRECT, context_mode,    \
-           false, test_server_backend, test_frame_method)                      \
-  REQ_TEST(RendererGETRedirectStop##suffix, REQTEST_GET_REDIRECT_STOP,         \
-           context_mode, false, test_server_backend, test_frame_method)        \
-  REQ_TEST(RendererGETRedirectLocation##suffix, REQTEST_GET_REDIRECT_LOCATION, \
-           context_mode, false, test_server_backend, test_frame_method)        \
-  REQ_TEST(RendererGETReferrer##suffix, REQTEST_GET_REFERRER, context_mode,    \
-           false, test_server_backend, test_frame_method)                      \
-  REQ_TEST(RendererPOST##suffix, REQTEST_POST, context_mode, false,            \
-           test_server_backend, test_frame_method)                             \
-  REQ_TEST(RendererPOSTWithProgress##suffix, REQTEST_POST_WITHPROGRESS,        \
-           context_mode, false, test_server_backend, test_frame_method)        \
-  REQ_TEST(RendererPOSTRedirect##suffix, REQTEST_POST_REDIRECT, context_mode,  \
-           false, test_server_backend, test_frame_method)                      \
-  REQ_TEST(RendererPOSTRedirectToGET##suffix, REQTEST_POST_REDIRECT_TOGET,     \
-           context_mode, false, test_server_backend, test_frame_method)        \
-  REQ_TEST(RendererHEAD##suffix, REQTEST_HEAD, context_mode, false,            \
+           context_mode, test_server_backend, test_frame_method)               \
+  REQ_TEST(BrowserHEAD##suffix, REQTEST_HEAD, context_mode,                    \
            test_server_backend, test_frame_method)
 
 #define REQ_TEST_SET(suffix, test_frame_method)                           \
@@ -3473,16 +2979,10 @@
 // Define tests that can only run with a frame.
 #define REQ_TEST_FRAME_SET_EX(suffix, context_mode, test_server_backend) \
   REQ_TEST(BrowserIncompleteProcessRequest##suffix,                      \
-           REQTEST_INCOMPLETE_PROCESS_REQUEST, context_mode, true,       \
+           REQTEST_INCOMPLETE_PROCESS_REQUEST, context_mode,             \
            test_server_backend, true)                                    \
   REQ_TEST(BrowserIncompleteReadResponse##suffix,                        \
-           REQTEST_INCOMPLETE_READ_RESPONSE, context_mode, true,         \
-           test_server_backend, true)                                    \
-  REQ_TEST(RendererIncompleteProcessRequest##suffix,                     \
-           REQTEST_INCOMPLETE_PROCESS_REQUEST, context_mode, false,      \
-           test_server_backend, true)                                    \
-  REQ_TEST(RendererIncompleteReadResponse##suffix,                       \
-           REQTEST_INCOMPLETE_READ_RESPONSE, context_mode, false,        \
+           REQTEST_INCOMPLETE_READ_RESPONSE, context_mode,               \
            test_server_backend, true)
 
 #define REQ_TEST_FRAME_SET()                                                 \
@@ -3500,57 +3000,31 @@
 // Cache and authentication tests can only be run with the server backend.
 #define REQ_TEST_CACHE_SET_EX(suffix, context_mode, test_frame_method)         \
   REQ_TEST(BrowserGETCacheWithControl##suffix, REQTEST_CACHE_WITH_CONTROL,     \
-           context_mode, true, true, test_frame_method)                        \
+           context_mode, true, test_frame_method)                              \
   REQ_TEST(BrowserGETCacheWithoutControl##suffix,                              \
-           REQTEST_CACHE_WITHOUT_CONTROL, context_mode, true, true,            \
+           REQTEST_CACHE_WITHOUT_CONTROL, context_mode, true,                  \
            test_frame_method)                                                  \
   REQ_TEST(BrowserGETCacheSkipFlag##suffix, REQTEST_CACHE_SKIP_FLAG,           \
-           context_mode, true, true, test_frame_method)                        \
+           context_mode, true, test_frame_method)                              \
   REQ_TEST(BrowserGETCacheSkipHeader##suffix, REQTEST_CACHE_SKIP_HEADER,       \
-           context_mode, true, true, test_frame_method)                        \
+           context_mode, true, test_frame_method)                              \
   REQ_TEST(BrowserGETCacheOnlyFailureFlag##suffix,                             \
-           REQTEST_CACHE_ONLY_FAILURE_FLAG, context_mode, true, true,          \
+           REQTEST_CACHE_ONLY_FAILURE_FLAG, context_mode, true,                \
            test_frame_method)                                                  \
   REQ_TEST(BrowserGETCacheOnlyFailureHeader##suffix,                           \
-           REQTEST_CACHE_ONLY_FAILURE_HEADER, context_mode, true, true,        \
+           REQTEST_CACHE_ONLY_FAILURE_HEADER, context_mode, true,              \
            test_frame_method)                                                  \
   REQ_TEST(BrowserGETCacheOnlySuccessFlag##suffix,                             \
-           REQTEST_CACHE_ONLY_SUCCESS_FLAG, context_mode, true, true,          \
+           REQTEST_CACHE_ONLY_SUCCESS_FLAG, context_mode, true,                \
            test_frame_method)                                                  \
   REQ_TEST(BrowserGETCacheOnlySuccessHeader##suffix,                           \
-           REQTEST_CACHE_ONLY_SUCCESS_HEADER, context_mode, true, true,        \
+           REQTEST_CACHE_ONLY_SUCCESS_HEADER, context_mode, true,              \
            test_frame_method)                                                  \
   REQ_TEST(BrowserGETCacheDisableFlag##suffix, REQTEST_CACHE_DISABLE_FLAG,     \
-           context_mode, true, true, test_frame_method)                        \
+           context_mode, true, test_frame_method)                              \
   REQ_TEST(BrowserGETCacheDisableHeader##suffix, REQTEST_CACHE_DISABLE_HEADER, \
-           context_mode, true, true, test_frame_method)                        \
-  REQ_TEST(RendererGETCacheWithControl##suffix, REQTEST_CACHE_WITH_CONTROL,    \
-           context_mode, false, true, test_frame_method)                       \
-  REQ_TEST(RendererGETCacheWithoutControl##suffix,                             \
-           REQTEST_CACHE_WITHOUT_CONTROL, context_mode, false, true,           \
-           test_frame_method)                                                  \
-  REQ_TEST(BrowserGETAuth##suffix, REQTEST_GET_AUTH, context_mode, true, true, \
-           test_frame_method)                                                  \
-  REQ_TEST(RendererGETCacheSkipFlag##suffix, REQTEST_CACHE_SKIP_FLAG,          \
-           context_mode, false, true, test_frame_method)                       \
-  REQ_TEST(RendererGETCacheSkipHeader##suffix, REQTEST_CACHE_SKIP_HEADER,      \
-           context_mode, false, true, test_frame_method)                       \
-  REQ_TEST(RendererGETCacheOnlyFailureFlag##suffix,                            \
-           REQTEST_CACHE_ONLY_FAILURE_FLAG, context_mode, false, true,         \
-           test_frame_method)                                                  \
-  REQ_TEST(RendererGETCacheOnlyFailureHeader##suffix,                          \
-           REQTEST_CACHE_ONLY_FAILURE_HEADER, context_mode, false, true,       \
-           test_frame_method)                                                  \
-  REQ_TEST(RendererGETCacheOnlySuccessFlag##suffix,                            \
-           REQTEST_CACHE_ONLY_SUCCESS_FLAG, context_mode, false, true,         \
-           test_frame_method)                                                  \
-  REQ_TEST(RendererGETCacheOnlySuccessHeader##suffix,                          \
-           REQTEST_CACHE_ONLY_SUCCESS_HEADER, context_mode, false, true,       \
-           test_frame_method)                                                  \
-  REQ_TEST(RendererGETCacheDisableFlag##suffix, REQTEST_CACHE_DISABLE_FLAG,    \
-           context_mode, false, true, test_frame_method)                       \
-  REQ_TEST(RendererGETCacheDisableHeader##suffix,                              \
-           REQTEST_CACHE_DISABLE_HEADER, context_mode, false, true,            \
+           context_mode, true, test_frame_method)                              \
+  REQ_TEST(BrowserGETAuth##suffix, REQTEST_GET_AUTH, context_mode, true,       \
            test_frame_method)
 
 #define REQ_TEST_CACHE_SET(suffix, test_frame_method)                    \
@@ -3573,7 +3047,8 @@
   }
 
   void RunTest() {
-    CefPostTask(TID_UI, base::Bind(&InvalidURLTestClient::RunOnUIThread, this));
+    CefPostTask(TID_UI,
+                base::BindOnce(&InvalidURLTestClient::RunOnUIThread, this));
 
     // Wait for the test to complete.
     event_->Wait();
@@ -3584,19 +3059,19 @@
     EXPECT_EQ(ERR_UNKNOWN_URL_SCHEME, client->GetRequestError());
 
     // Let the call stack unwind before signaling completion.
-    CefPostTask(TID_UI,
-                base::Bind(&InvalidURLTestClient::CompleteOnUIThread, this));
+    CefPostTask(TID_UI, base::BindOnce(
+                            &InvalidURLTestClient::CompleteOnUIThread, this));
   }
 
   void OnUploadProgress(CefRefPtr<CefURLRequest> request,
-                        int64 current,
-                        int64 total) override {
+                        int64_t current,
+                        int64_t total) override {
     EXPECT_TRUE(false);  // Not reached.
   }
 
   void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
-                          int64 current,
-                          int64 total) override {
+                          int64_t current,
+                          int64_t total) override {
     EXPECT_TRUE(false);  // Not reached.
   }
 
@@ -3644,3 +3119,10 @@
   CefRefPtr<InvalidURLTestClient> client = new InvalidURLTestClient();
   client->RunTest();
 }
+
+// Entry point for creating URLRequest browser test objects.
+// Called from client_app_delegates.cc.
+void CreateURLRequestBrowserTests(
+    client::ClientAppBrowser::DelegateSet& delegates) {
+  delegates.insert(new URLRequestBrowserTest);
+}
diff --git a/src/tests/ceftests/v8_unittest.cc b/src/tests/ceftests/v8_unittest.cc
index f720603..7ed16a1 100644
--- a/src/tests/ceftests/v8_unittest.cc
+++ b/src/tests/ceftests/v8_unittest.cc
@@ -4,16 +4,15 @@
 
 #include <sstream>
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_task.h"
 #include "include/cef_v8.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "tests/ceftests/test_handler.h"
+#include "tests/ceftests/test_util.h"
 #include "tests/gtest/include/gtest/gtest.h"
-#include "tests/shared/browser/client_app_browser.h"
 #include "tests/shared/renderer/client_app_renderer.h"
 
-using client::ClientAppBrowser;
 using client::ClientAppRenderer;
 
 // How to add a new test:
@@ -26,21 +25,21 @@
 namespace {
 
 // Unique values for V8 tests.
-const char kV8TestUrl[] = "http://tests/V8Test.Test";
-const char kV8BindingTestUrl[] = "http://tests/V8Test.BindingTest";
-const char kV8ContextParentTestUrl[] = "http://tests/V8Test.ContextParentTest";
-const char kV8ContextChildTestUrl[] = "http://tests/V8Test.ContextChildTest";
-const char kV8NavTestUrl[] = "http://tests/V8Test.NavTest";
+const char kV8TestUrl[] = "https://tests/V8Test.Test";
+const char kV8BindingTestUrl[] = "https://tests/V8Test.BindingTest";
+const char kV8ContextParentTestUrl[] = "https://tests/V8Test.ContextParentTest";
+const char kV8ContextChildTestUrl[] = "https://tests/V8Test.ContextChildTest";
+const char kV8NavTestUrl[] = "https://tests/V8Test.NavTest";
 const char kV8ContextEvalCspBypassUnsafeEval[] =
-    "http://tests/V8Test.ContextEvalCspBypassUnsafeEval";
+    "https://tests/V8Test.ContextEvalCspBypassUnsafeEval";
 const char kV8ContextEvalCspBypassSandbox[] =
-    "http://tests/V8Test.ContextEvalCspBypassSandbox";
+    "https://tests/V8Test.ContextEvalCspBypassSandbox";
 const char kV8OnUncaughtExceptionTestUrl[] =
-    "http://tests/V8Test.OnUncaughtException";
+    "https://tests/V8Test.OnUncaughtException";
 const char kV8HandlerCallOnReleasedContextUrl[] =
-    "http://tests/V8Test.HandlerCallOnReleasedContext/main.html";
+    "https://tests/V8Test.HandlerCallOnReleasedContext/main.html";
 const char kV8HandlerCallOnReleasedContextChildUrl[] =
-    "http://tests/V8Test.HandlerCallOnReleasedContext/child.html";
+    "https://tests/V8Test.HandlerCallOnReleasedContext/child.html";
 const char kV8TestMsg[] = "V8Test.Test";
 const char kV8TestCmdKey[] = "v8-test";
 const char kV8RunTestMsg[] = "V8Test.RunTest";
@@ -58,6 +57,7 @@
   V8TEST_ARRAY_CREATE,
   V8TEST_ARRAY_VALUE,
   V8TEST_ARRAY_BUFFER,
+  V8TEST_ARRAY_BUFFER_CREATE_EMPTY,
   V8TEST_ARRAY_BUFFER_VALUE,
   V8TEST_OBJECT_CREATE,
   V8TEST_OBJECT_USERDATA,
@@ -83,6 +83,12 @@
   V8TEST_FUNCTION_HANDLER_NO_OBJECT,
   V8TEST_FUNCTION_HANDLER_WITH_CONTEXT,
   V8TEST_FUNCTION_HANDLER_EMPTY_STRING,
+  V8TEST_PROMISE_CREATE,
+  V8TEST_PROMISE_RESOLVE,
+  V8TEST_PROMISE_RESOLVE_NO_ARGUMENT,
+  V8TEST_PROMISE_RESOLVE_HANDLER,
+  V8TEST_PROMISE_REJECT,
+  V8TEST_PROMISE_REJECT_HANDLER,
   V8TEST_CONTEXT_EVAL,
   V8TEST_CONTEXT_EVAL_EXCEPTION,
   V8TEST_CONTEXT_EVAL_CSP_BYPASS_UNSAFE_EVAL,
@@ -138,6 +144,9 @@
       case V8TEST_ARRAY_BUFFER:
         RunArrayBufferTest();
         break;
+      case V8TEST_ARRAY_BUFFER_CREATE_EMPTY:
+        RunArrayBufferCreateEmptyTest();
+        break;
       case V8TEST_ARRAY_BUFFER_VALUE:
         RunArrayBufferValueTest();
         break;
@@ -213,6 +222,24 @@
       case V8TEST_FUNCTION_HANDLER_EMPTY_STRING:
         RunFunctionHandlerEmptyStringTest();
         break;
+      case V8TEST_PROMISE_CREATE:
+        RunPromiseCreateTest();
+        break;
+      case V8TEST_PROMISE_RESOLVE:
+        RunPromiseResolveTest();
+        break;
+      case V8TEST_PROMISE_RESOLVE_NO_ARGUMENT:
+        RunPromiseResolveNoArgumentTest();
+        break;
+      case V8TEST_PROMISE_RESOLVE_HANDLER:
+        RunPromiseResolveHandlerTest();
+        break;
+      case V8TEST_PROMISE_REJECT:
+        RunPromiseRejectTest();
+        break;
+      case V8TEST_PROMISE_REJECT_HANDLER:
+        RunPromiseRejectHandlerTest();
+        break;
       case V8TEST_CONTEXT_EVAL:
         RunContextEvalTest();
         break;
@@ -272,6 +299,7 @@
     EXPECT_FALSE(value->IsInt());
     EXPECT_FALSE(value->IsUInt());
     EXPECT_FALSE(value->IsObject());
+    EXPECT_FALSE(value->IsPromise());
     EXPECT_FALSE(value->IsString());
 
     DestroyTest();
@@ -292,6 +320,7 @@
     EXPECT_FALSE(value->IsUInt());
     EXPECT_FALSE(value->IsNull());
     EXPECT_FALSE(value->IsObject());
+    EXPECT_FALSE(value->IsPromise());
     EXPECT_FALSE(value->IsString());
 
     DestroyTest();
@@ -304,7 +333,7 @@
     EXPECT_TRUE(value->IsUInt());
     EXPECT_TRUE(value->IsDouble());
     EXPECT_EQ(12, value->GetIntValue());
-    EXPECT_EQ((uint32)12, value->GetUIntValue());
+    EXPECT_EQ((uint32_t)12, value->GetUIntValue());
     EXPECT_EQ(12, value->GetDoubleValue());
 
     EXPECT_FALSE(value->IsUndefined());
@@ -314,6 +343,7 @@
     EXPECT_FALSE(value->IsFunction());
     EXPECT_FALSE(value->IsNull());
     EXPECT_FALSE(value->IsObject());
+    EXPECT_FALSE(value->IsPromise());
     EXPECT_FALSE(value->IsString());
 
     DestroyTest();
@@ -326,7 +356,7 @@
     EXPECT_TRUE(value->IsUInt());
     EXPECT_TRUE(value->IsDouble());
     EXPECT_EQ(12, value->GetIntValue());
-    EXPECT_EQ((uint32)12, value->GetUIntValue());
+    EXPECT_EQ((uint32_t)12, value->GetUIntValue());
     EXPECT_EQ(12, value->GetDoubleValue());
 
     EXPECT_FALSE(value->IsUndefined());
@@ -336,6 +366,7 @@
     EXPECT_FALSE(value->IsFunction());
     EXPECT_FALSE(value->IsNull());
     EXPECT_FALSE(value->IsObject());
+    EXPECT_FALSE(value->IsPromise());
     EXPECT_FALSE(value->IsString());
 
     DestroyTest();
@@ -356,6 +387,7 @@
     EXPECT_FALSE(value->IsUInt());
     EXPECT_FALSE(value->IsNull());
     EXPECT_FALSE(value->IsObject());
+    EXPECT_FALSE(value->IsPromise());
     EXPECT_FALSE(value->IsString());
 
     DestroyTest();
@@ -367,7 +399,7 @@
     CefTime date;
     date.year = 2200;
     date.month = 4;
-#if !defined(OS_MACOSX)
+#if !defined(OS_MAC)
     date.day_of_week = 5;
 #endif
     date.day_of_month = 11;
@@ -378,10 +410,10 @@
     // Enter the V8 context.
     EXPECT_TRUE(context->Enter());
 
-    CefRefPtr<CefV8Value> value = CefV8Value::CreateDate(date);
+    CefRefPtr<CefV8Value> value = CefV8Value::CreateDate(CefBaseTimeFrom(date));
     EXPECT_TRUE(value.get());
     EXPECT_TRUE(value->IsDate());
-    EXPECT_EQ(date.GetTimeT(), value->GetDateValue().GetTimeT());
+    EXPECT_EQ(date.GetTimeT(), CefTimeFrom(value->GetDateValue()).GetTimeT());
 
     // Exit the V8 context.
     EXPECT_TRUE(context->Exit());
@@ -395,6 +427,7 @@
     EXPECT_FALSE(value->IsUInt());
     EXPECT_FALSE(value->IsObject());
     EXPECT_FALSE(value->IsNull());
+    EXPECT_FALSE(value->IsPromise());
     EXPECT_FALSE(value->IsString());
 
     DestroyTest();
@@ -415,6 +448,7 @@
     EXPECT_FALSE(value->IsInt());
     EXPECT_FALSE(value->IsUInt());
     EXPECT_FALSE(value->IsNull());
+    EXPECT_FALSE(value->IsPromise());
     EXPECT_FALSE(value->IsObject());
 
     DestroyTest();
@@ -436,6 +470,7 @@
     EXPECT_FALSE(value->IsUInt());
     EXPECT_FALSE(value->IsNull());
     EXPECT_FALSE(value->IsObject());
+    EXPECT_FALSE(value->IsPromise());
 
     DestroyTest();
   }
@@ -465,6 +500,7 @@
     EXPECT_FALSE(value->IsInt());
     EXPECT_FALSE(value->IsUInt());
     EXPECT_FALSE(value->IsNull());
+    EXPECT_FALSE(value->IsPromise());
     EXPECT_FALSE(value->IsString());
 
     DestroyTest();
@@ -547,43 +583,35 @@
 
     bool destructorCalled = false;
     bool releaseBufferCalled = false;
-
-    bool neuteredDestructorCalled = false;
-    bool neuteredReleaseBufferCalled = false;
     // Enter the V8 context.
     EXPECT_TRUE(context->Enter());
     {
       int static_data[16];
-      CefRefPtr<CefV8Value> value;
       CefRefPtr<TestArrayBufferReleaseCallback> release_callback =
           new TestArrayBufferReleaseCallback(&destructorCalled,
                                              &releaseBufferCalled);
-
-      CefRefPtr<CefV8Value> neuteredValue;
-      CefRefPtr<TestArrayBufferReleaseCallback> neuteredReleaseCallback =
-          new TestArrayBufferReleaseCallback(&neuteredDestructorCalled,
-                                             &neuteredReleaseBufferCalled);
-      value = CefV8Value::CreateArrayBuffer(static_data, sizeof(static_data),
-                                            release_callback);
-      neuteredValue = CefV8Value::CreateArrayBuffer(
-          static_data, sizeof(static_data), neuteredReleaseCallback);
+      CefRefPtr<CefV8Value> value = CefV8Value::CreateArrayBuffer(
+          static_data, sizeof(static_data), release_callback);
       EXPECT_TRUE(value.get());
       EXPECT_TRUE(value->IsArrayBuffer());
       EXPECT_TRUE(value->IsObject());
+      EXPECT_EQ(value->GetArrayBufferByteLength(), sizeof(static_data));
+      void* data = value->GetArrayBufferData();
+      EXPECT_EQ(static_cast<int*>(data), static_data);
       EXPECT_FALSE(value->HasValue(0));
-      EXPECT_FALSE(destructorCalled);
       EXPECT_TRUE(value->GetArrayBufferReleaseCallback().get() != nullptr);
       EXPECT_TRUE(((TestArrayBufferReleaseCallback*)value
                        ->GetArrayBufferReleaseCallback()
                        .get()) == release_callback);
 
-      EXPECT_TRUE(neuteredValue->NeuterArrayBuffer());
+      // |Value| buffer is explicitly freed by NeuterArrayBuffer().
+      EXPECT_FALSE(destructorCalled);
+      EXPECT_FALSE(releaseBufferCalled);
+      EXPECT_TRUE(value->NeuterArrayBuffer());
+      EXPECT_TRUE(releaseBufferCalled);
     }
     // Exit the V8 context.
     EXPECT_TRUE(destructorCalled);
-    EXPECT_TRUE(releaseBufferCalled);
-    EXPECT_TRUE(neuteredDestructorCalled);
-    EXPECT_FALSE(neuteredReleaseBufferCalled);
     EXPECT_TRUE(context->Exit());
     DestroyTest();
   }
@@ -613,6 +641,9 @@
     static_data[0] = 3;
     value =
         CefV8Value::CreateArrayBuffer(static_data, sizeof(static_data), owner);
+    EXPECT_EQ(value->GetArrayBufferByteLength(), sizeof(static_data));
+    void* data = value->GetArrayBufferData();
+    EXPECT_EQ(static_cast<int*>(data), static_data);
 
     CefRefPtr<CefV8Value> object = context->GetGlobal();
     EXPECT_TRUE(object.get());
@@ -622,11 +653,47 @@
     CefRefPtr<CefV8Value> retval;
     CefRefPtr<CefV8Exception> exception;
     EXPECT_TRUE(context->Eval(test, CefString(), 0, retval, exception));
-    if (exception.get())
+    if (exception.get()) {
       ADD_FAILURE() << exception->GetMessage().c_str();
+    }
 
-    EXPECT_TRUE(static_data[0] == 19);
-    EXPECT_TRUE(value->GetArrayBufferReleaseCallback().get() != nullptr);
+    EXPECT_EQ(static_data[0], 19);
+    EXPECT_NE(value->GetArrayBufferReleaseCallback().get(), nullptr);
+    EXPECT_TRUE(value->NeuterArrayBuffer());
+
+    // Exit the V8 context.
+    EXPECT_TRUE(context->Exit());
+    DestroyTest();
+  }
+
+  void RunArrayBufferCreateEmptyTest() {
+    class TestArrayBufferReleaseCallback
+        : public CefV8ArrayBufferReleaseCallback {
+     public:
+      void ReleaseBuffer(void* buffer) override {}
+
+      IMPLEMENT_REFCOUNTING(TestArrayBufferReleaseCallback);
+    };
+
+    CefRefPtr<TestArrayBufferReleaseCallback> owner =
+        new TestArrayBufferReleaseCallback();
+
+    // Enter the V8 context
+    CefRefPtr<CefV8Context> context = GetContext();
+    EXPECT_TRUE(context->Enter());
+
+    const size_t zero_size = 0;
+    void* null_data = nullptr;
+
+    CefRefPtr<CefV8Value> value =
+        CefV8Value::CreateArrayBuffer(null_data, zero_size, owner);
+    EXPECT_EQ(value->GetArrayBufferByteLength(), zero_size);
+    EXPECT_EQ(value->GetArrayBufferData(), null_data);
+
+    CefRefPtr<CefV8Value> object = context->GetGlobal();
+    EXPECT_TRUE(object.get());
+    EXPECT_TRUE(object->SetValue("arr", value, V8_PROPERTY_ATTRIBUTE_NONE));
+    EXPECT_NE(value->GetArrayBufferReleaseCallback().get(), nullptr);
     EXPECT_TRUE(value->NeuterArrayBuffer());
 
     // Exit the V8 context.
@@ -655,6 +722,7 @@
     EXPECT_FALSE(value->IsInt());
     EXPECT_FALSE(value->IsUInt());
     EXPECT_FALSE(value->IsNull());
+    EXPECT_FALSE(value->IsPromise());
     EXPECT_FALSE(value->IsString());
 
     // Exit the V8 context.
@@ -997,7 +1065,7 @@
     static const char* kName3 = "val3";
 
     static const int kValue1 = 20;
-    static const uint32 kValue2 = 30u;
+    static const uint32_t kValue2 = 30u;
     static const char* kValue3 = "40";
 
     static const int kArray[] = {50, 60, 70};
@@ -1008,7 +1076,7 @@
       virtual bool Get(const CefString& name,
                        const CefRefPtr<CefV8Value> object,
                        CefRefPtr<CefV8Value>& retval,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         EXPECT_TRUE(name.ToString() == kName1 || name.ToString() == kName2 ||
                     name.ToString() == kName3);
 
@@ -1035,7 +1103,7 @@
       virtual bool Get(int index,
                        const CefRefPtr<CefV8Value> object,
                        CefRefPtr<CefV8Value>& retval,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         EXPECT_TRUE(index >= 0 && index < 3);
 
         EXPECT_TRUE(object.get());
@@ -1053,7 +1121,7 @@
       virtual bool Set(const CefString& name,
                        const CefRefPtr<CefV8Value> object,
                        const CefRefPtr<CefV8Value> value,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         EXPECT_TRUE(name.ToString() == kName1 || name.ToString() == kName2 ||
                     name.ToString() == kName3);
 
@@ -1080,7 +1148,7 @@
       virtual bool Set(int index,
                        const CefRefPtr<CefV8Value> object,
                        const CefRefPtr<CefV8Value> value,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         EXPECT_TRUE(index >= 0 && index < 3);
 
         EXPECT_TRUE(object.get());
@@ -1210,7 +1278,7 @@
       virtual bool Get(const CefString& name,
                        const CefRefPtr<CefV8Value> object,
                        CefRefPtr<CefV8Value>& retval,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         got_get_byname_.yes();
         StringMap::iterator it = string_map_.find(name.ToString());
         if (it != string_map_.end()) {
@@ -1222,7 +1290,7 @@
       virtual bool Get(int index,
                        const CefRefPtr<CefV8Value> object,
                        CefRefPtr<CefV8Value>& retval,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         got_get_byindex_.yes();
         IntMap::iterator it = int_map_.find(index);
         if (it != int_map_.end()) {
@@ -1234,7 +1302,7 @@
       virtual bool Set(const CefString& name,
                        const CefRefPtr<CefV8Value> object,
                        const CefRefPtr<CefV8Value> value,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         EXPECT_TRUE(value->IsInt());
         got_set_byname_.yes();
         string_map_[name.ToString()] = value->GetIntValue();
@@ -1244,7 +1312,7 @@
       virtual bool Set(int index,
                        const CefRefPtr<CefV8Value> object,
                        const CefRefPtr<CefV8Value> value,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         EXPECT_TRUE(value->IsInt());
         got_set_byindex_.yes();
         int_map_[index] = value->GetIntValue();
@@ -1348,7 +1416,7 @@
       virtual bool Get(const CefString& name,
                        const CefRefPtr<CefV8Value> object,
                        CefRefPtr<CefV8Value>& retval,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         got_get_byname_.yes();
         exception = kGetByNameException;
         return true;
@@ -1357,7 +1425,7 @@
       virtual bool Get(int index,
                        const CefRefPtr<CefV8Value> object,
                        CefRefPtr<CefV8Value>& retval,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         got_get_byindex_.yes();
         exception = kGetByIndexException;
         return true;
@@ -1366,7 +1434,7 @@
       virtual bool Set(const CefString& name,
                        const CefRefPtr<CefV8Value> object,
                        const CefRefPtr<CefV8Value> value,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         got_set_byname_.yes();
         exception = kSetByNameException;
         return true;
@@ -1375,7 +1443,7 @@
       virtual bool Set(int index,
                        const CefRefPtr<CefV8Value> object,
                        const CefRefPtr<CefV8Value> value,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         got_set_byindex_.yes();
         exception = kSetByIndexException;
         return true;
@@ -1464,7 +1532,7 @@
       virtual bool Get(const CefString& name,
                        const CefRefPtr<CefV8Value> object,
                        CefRefPtr<CefV8Value>& retval,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         EXPECT_FALSE(retval.get());
         got_get_byname_.yes();
         if (name.ToString() == kInterceptorName) {
@@ -1476,7 +1544,7 @@
       virtual bool Get(int index,
                        const CefRefPtr<CefV8Value> object,
                        CefRefPtr<CefV8Value>& retval,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         got_get_byindex_.yes();
         return true;
       }
@@ -1484,7 +1552,7 @@
       virtual bool Set(const CefString& name,
                        const CefRefPtr<CefV8Value> object,
                        const CefRefPtr<CefV8Value> value,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         got_set_byname_.yes();
         return true;
       }
@@ -1492,7 +1560,7 @@
       virtual bool Set(int index,
                        const CefRefPtr<CefV8Value> object,
                        const CefRefPtr<CefV8Value> value,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         got_set_byindex_.yes();
         return true;
       }
@@ -1511,7 +1579,7 @@
       virtual bool Get(const CefString& name,
                        const CefRefPtr<CefV8Value> object,
                        CefRefPtr<CefV8Value>& retval,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         got_get_.yes();
         retval = CefV8Value::CreateInt(kAccessorValue);
         return true;
@@ -1520,7 +1588,7 @@
       virtual bool Set(const CefString& name,
                        const CefRefPtr<CefV8Value> object,
                        const CefRefPtr<CefV8Value> value,
-                       CefString& exception) OVERRIDE {
+                       CefString& exception) override {
         got_set_.yes();
         return true;
       }
@@ -1620,8 +1688,9 @@
     CefRefPtr<CefV8Exception> exception;
 
     EXPECT_TRUE(context->Eval(test.str(), CefString(), 0, retval, exception));
-    if (exception.get())
+    if (exception.get()) {
       ADD_FAILURE() << exception->GetMessage().c_str();
+    }
 
     CefRefPtr<CefV8Value> newval = object->GetValue(kName);
     EXPECT_TRUE(newval.get());
@@ -1658,8 +1727,9 @@
     CefRefPtr<CefV8Exception> exception;
 
     EXPECT_TRUE(context->Eval(test.str(), CefString(), 0, retval, exception));
-    if (exception.get())
+    if (exception.get()) {
       ADD_FAILURE() << exception->GetMessage().c_str();
+    }
 
     CefRefPtr<CefV8Value> newval = object->GetValue(kName);
     EXPECT_TRUE(newval.get());
@@ -1702,8 +1772,9 @@
     CefRefPtr<CefV8Exception> exception;
 
     EXPECT_TRUE(context->Eval(test.str(), CefString(), 0, retval, exception));
-    if (exception.get())
+    if (exception.get()) {
       ADD_FAILURE() << exception->GetMessage().c_str();
+    }
 
     CefRefPtr<CefV8Value> newval = obj1->GetValue(kArgName);
     EXPECT_TRUE(newval.get());
@@ -1746,8 +1817,9 @@
     CefRefPtr<CefV8Exception> exception;
 
     EXPECT_TRUE(context->Eval(test.str(), CefString(), 0, retval, exception));
-    if (exception.get())
+    if (exception.get()) {
       ADD_FAILURE() << exception->GetMessage().c_str();
+    }
 
     CefRefPtr<CefV8Value> newval = obj1->GetValue(kArgName);
     EXPECT_TRUE(newval.get());
@@ -1787,8 +1859,9 @@
     CefRefPtr<CefV8Exception> exception;
 
     EXPECT_TRUE(context->Eval(test.str(), CefString(), 0, retval, exception));
-    if (exception.get())
+    if (exception.get()) {
       ADD_FAILURE() << exception->GetMessage().c_str();
+    }
 
     CefRefPtr<CefV8Value> newval = object->GetValue(kName);
     EXPECT_TRUE(newval.get());
@@ -1828,8 +1901,9 @@
     CefRefPtr<CefV8Exception> exception;
 
     EXPECT_TRUE(context->Eval(test.str(), CefString(), 0, retval, exception));
-    if (exception.get())
+    if (exception.get()) {
       ADD_FAILURE() << exception->GetMessage().c_str();
+    }
 
     CefRefPtr<CefV8Value> newval = object->GetValue(kName);
     EXPECT_TRUE(newval.get());
@@ -1910,6 +1984,7 @@
     EXPECT_FALSE(value->IsInt());
     EXPECT_FALSE(value->IsUInt());
     EXPECT_FALSE(value->IsNull());
+    EXPECT_FALSE(value->IsPromise());
     EXPECT_FALSE(value->IsString());
 
     DestroyTest();
@@ -2238,6 +2313,248 @@
     DestroyTest();
   }
 
+  void RunPromiseCreateTest() {
+    CefRefPtr<CefV8Context> context = GetContext();
+
+    // Enter the V8 context.
+    EXPECT_TRUE(context->Enter());
+
+    CefRefPtr<CefV8Value> value = CefV8Value::CreatePromise();
+
+    // Exit the V8 context.
+    EXPECT_TRUE(context->Exit());
+
+    EXPECT_TRUE(value.get());
+    EXPECT_TRUE(value->IsPromise());
+    EXPECT_TRUE(value->IsObject());
+
+    EXPECT_FALSE(value->IsUndefined());
+    EXPECT_FALSE(value->IsArray());
+    EXPECT_FALSE(value->IsBool());
+    EXPECT_FALSE(value->IsDate());
+    EXPECT_FALSE(value->IsDouble());
+    EXPECT_FALSE(value->IsFunction());
+    EXPECT_FALSE(value->IsInt());
+    EXPECT_FALSE(value->IsUInt());
+    EXPECT_FALSE(value->IsNull());
+    EXPECT_FALSE(value->IsString());
+
+    DestroyTest();
+  }
+
+  void RunPromiseResolveTest() {
+    CefRefPtr<CefV8Context> context = GetContext();
+
+    // Enter the V8 context.
+    EXPECT_TRUE(context->Enter());
+
+    CefRefPtr<CefV8Value> value = CefV8Value::CreatePromise();
+    CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(nullptr, nullptr);
+
+    EXPECT_TRUE(value.get());
+    EXPECT_TRUE(value->ResolvePromise(obj));
+
+    // Exit the V8 context.
+    EXPECT_TRUE(context->Exit());
+
+    DestroyTest();
+  }
+
+  void RunPromiseResolveNoArgumentTest() {
+    CefRefPtr<CefV8Context> context = GetContext();
+
+    // Enter the V8 context.
+    EXPECT_TRUE(context->Enter());
+
+    CefRefPtr<CefV8Value> value = CefV8Value::CreatePromise();
+
+    EXPECT_TRUE(value.get());
+    EXPECT_TRUE(value->ResolvePromise(nullptr));
+
+    // Exit the V8 context.
+    EXPECT_TRUE(context->Exit());
+
+    DestroyTest();
+  }
+
+  void RunPromiseResolveHandlerTest() {
+    CefRefPtr<CefV8Context> context = GetContext();
+
+    static const char* kPromiseName = "myprom";
+    static const char* kResolveName = "myresolve";
+    static const char* kRejectName = "myreject";
+    static const int kVal1 = 32;
+
+    class Handler : public CefV8Handler {
+     public:
+      Handler() {}
+      bool Execute(const CefString& name,
+                   CefRefPtr<CefV8Value> object,
+                   const CefV8ValueList& arguments,
+                   CefRefPtr<CefV8Value>& retval,
+                   CefString& exception) override {
+        EXPECT_STREQ(kResolveName, name.ToString().c_str());
+        EXPECT_EQ((size_t)1, arguments.size());
+        EXPECT_TRUE(arguments[0]->IsInt());
+        EXPECT_EQ(kVal1, arguments[0]->GetIntValue());
+
+        got_execute_.yes();
+
+        return false;
+      }
+
+      TrackCallback got_execute_;
+
+      IMPLEMENT_REFCOUNTING(Handler);
+    };
+
+    // Enter the V8 context.
+    EXPECT_TRUE(context->Enter());
+
+    Handler* resolveHandler = new Handler;
+    Handler* rejectHandler = new Handler;
+
+    CefRefPtr<CefV8Handler> resolveHandlerPtr(resolveHandler);
+    CefRefPtr<CefV8Handler> rejectHandlerPtr(rejectHandler);
+
+    CefRefPtr<CefV8Value> resolveFunc =
+        CefV8Value::CreateFunction(kResolveName, resolveHandler);
+    EXPECT_TRUE(resolveFunc.get());
+    EXPECT_TRUE(context->GetGlobal()->SetValue(kResolveName, resolveFunc,
+                                               V8_PROPERTY_ATTRIBUTE_NONE));
+
+    CefRefPtr<CefV8Value> rejectFunc =
+        CefV8Value::CreateFunction(kRejectName, rejectHandler);
+    EXPECT_TRUE(rejectFunc.get());
+    EXPECT_TRUE(context->GetGlobal()->SetValue(kRejectName, rejectFunc,
+                                               V8_PROPERTY_ATTRIBUTE_NONE));
+
+    CefRefPtr<CefV8Value> value = CefV8Value::CreatePromise();
+
+    EXPECT_TRUE(value.get());
+    EXPECT_TRUE(context->GetGlobal()->SetValue(kPromiseName, value,
+                                               V8_PROPERTY_ATTRIBUTE_NONE));
+
+    CefRefPtr<CefV8Value> retval;
+    CefRefPtr<CefV8Exception> exception;
+
+    std::stringstream test;
+    test << "window." << kPromiseName << ".then(" << kResolveName << ").catch("
+         << kRejectName << ")";
+
+    EXPECT_TRUE(context->Eval(test.str(), CefString(), 0, retval, exception));
+    EXPECT_TRUE(retval.get());
+    EXPECT_TRUE(retval->IsPromise());
+    EXPECT_FALSE(exception.get());
+
+    CefRefPtr<CefV8Value> arg = CefV8Value::CreateInt(kVal1);
+    EXPECT_TRUE(value->ResolvePromise(arg));
+
+    // Exit the V8 context.
+    EXPECT_TRUE(context->Exit());
+
+    EXPECT_TRUE(resolveHandler->got_execute_);
+    EXPECT_FALSE(rejectHandler->got_execute_);
+
+    DestroyTest();
+  }
+
+  void RunPromiseRejectTest() {
+    CefRefPtr<CefV8Context> context = GetContext();
+
+    // Enter the V8 context.
+    EXPECT_TRUE(context->Enter());
+
+    CefRefPtr<CefV8Value> value = CefV8Value::CreatePromise();
+
+    EXPECT_TRUE(value.get());
+    EXPECT_TRUE(value->RejectPromise("Error: Unknown"));
+
+    // Exit the V8 context.
+    EXPECT_TRUE(context->Exit());
+
+    DestroyTest();
+  }
+
+  void RunPromiseRejectHandlerTest() {
+    CefRefPtr<CefV8Context> context = GetContext();
+
+    static const char* kPromiseName = "myprom";
+    static const char* kResolveName = "myresolve";
+    static const char* kRejectName = "myreject";
+
+    class Handler : public CefV8Handler {
+     public:
+      Handler() {}
+      bool Execute(const CefString& name,
+                   CefRefPtr<CefV8Value> object,
+                   const CefV8ValueList& arguments,
+                   CefRefPtr<CefV8Value>& retval,
+                   CefString& exception) override {
+        EXPECT_STREQ(kRejectName, name.ToString().c_str());
+        EXPECT_EQ((size_t)1, arguments.size());
+        EXPECT_TRUE(arguments[0]->IsObject());
+
+        got_execute_.yes();
+
+        return false;
+      }
+
+      TrackCallback got_execute_;
+
+      IMPLEMENT_REFCOUNTING(Handler);
+    };
+
+    // Enter the V8 context.
+    EXPECT_TRUE(context->Enter());
+
+    Handler* resolveHandler = new Handler;
+    Handler* rejectHandler = new Handler;
+
+    CefRefPtr<CefV8Handler> resolveHandlerPtr(resolveHandler);
+    CefRefPtr<CefV8Handler> rejectHandlerPtr(rejectHandler);
+
+    CefRefPtr<CefV8Value> resolveFunc =
+        CefV8Value::CreateFunction(kResolveName, resolveHandler);
+    EXPECT_TRUE(resolveFunc.get());
+    EXPECT_TRUE(context->GetGlobal()->SetValue(kResolveName, resolveFunc,
+                                               V8_PROPERTY_ATTRIBUTE_NONE));
+
+    CefRefPtr<CefV8Value> rejectFunc =
+        CefV8Value::CreateFunction(kRejectName, rejectHandler);
+    EXPECT_TRUE(rejectFunc.get());
+    EXPECT_TRUE(context->GetGlobal()->SetValue(kRejectName, rejectFunc,
+                                               V8_PROPERTY_ATTRIBUTE_NONE));
+
+    CefRefPtr<CefV8Value> value = CefV8Value::CreatePromise();
+
+    EXPECT_TRUE(value.get());
+    EXPECT_TRUE(context->GetGlobal()->SetValue(kPromiseName, value,
+                                               V8_PROPERTY_ATTRIBUTE_NONE));
+
+    CefRefPtr<CefV8Value> retval;
+    CefRefPtr<CefV8Exception> exception;
+
+    std::stringstream test;
+    test << "window." << kPromiseName << ".then(" << kResolveName << ").catch("
+         << kRejectName << ")";
+
+    EXPECT_TRUE(context->Eval(test.str(), CefString(), 0, retval, exception));
+    EXPECT_TRUE(retval.get());
+    EXPECT_TRUE(retval->IsPromise());
+    EXPECT_FALSE(exception.get());
+
+    EXPECT_TRUE(value->RejectPromise("Error: Unknown"));
+
+    // Exit the V8 context.
+    EXPECT_TRUE(context->Exit());
+
+    EXPECT_FALSE(resolveHandler->got_execute_);
+    EXPECT_TRUE(rejectHandler->got_execute_);
+
+    DestroyTest();
+  }
+
   void RunContextEvalTest() {
     CefRefPtr<CefV8Context> context = GetContext();
 
@@ -2326,8 +2643,9 @@
     EXPECT_TRUE(context->Eval(
         "document.getElementById('f').contentWindow.v8_context_entered_test()",
         CefString(), 0, retval, exception));
-    if (exception.get())
+    if (exception.get()) {
       ADD_FAILURE() << exception->GetMessage().c_str();
+    }
 
     EXPECT_TRUE(retval.get());
     EXPECT_TRUE(retval->IsInt());
@@ -2478,11 +2796,12 @@
   void OnBrowserCreated(CefRefPtr<ClientAppRenderer> app,
                         CefRefPtr<CefBrowser> browser,
                         CefRefPtr<CefDictionaryValue> extra_info) override {
-    if (extra_info->HasKey(kV8TestCmdKey)) {
+    if (extra_info && extra_info->HasKey(kV8TestCmdKey)) {
       test_mode_ = static_cast<V8TestMode>(extra_info->GetInt(kV8TestCmdKey));
     }
-    if (test_mode_ > V8TEST_NONE)
+    if (test_mode_ > V8TEST_NONE) {
       RunStartupTest();
+    }
     if (test_mode_ == V8TEST_CONTEXT_EVAL_CSP_BYPASS_UNSAFE_EVAL ||
         test_mode_ == V8TEST_CONTEXT_EVAL_CSP_BYPASS_SANDBOX) {
       browser_ = browser;
@@ -2491,8 +2810,9 @@
 
   CefRefPtr<CefLoadHandler> GetLoadHandler(
       CefRefPtr<ClientAppRenderer> app) override {
-    if (test_mode_ == V8TEST_NONE)
+    if (test_mode_ == V8TEST_NONE) {
       return nullptr;
+    }
 
     return this;
   }
@@ -2510,8 +2830,9 @@
                         CefRefPtr<CefBrowser> browser,
                         CefRefPtr<CefFrame> frame,
                         CefRefPtr<CefV8Context> context) override {
-    if (test_mode_ == V8TEST_NONE)
+    if (test_mode_ == V8TEST_NONE) {
       return;
+    }
 
     if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
       if (!browser->IsPopup()) {
@@ -2591,10 +2912,10 @@
                      CefRefPtr<CefV8Value>& retval,
                      CefString& exception) override {
           if (name == "notify_test_done") {
-            CefPostDelayedTask(
-                TID_RENDERER,
-                base::Bind(&V8RendererTest::DestroyTest, renderer_test_.get()),
-                1000);
+            CefPostDelayedTask(TID_RENDERER,
+                               base::BindOnce(&V8RendererTest::DestroyTest,
+                                              renderer_test_.get()),
+                               1000);
             return true;
           }
 
@@ -2660,8 +2981,9 @@
                            CefRefPtr<CefV8Context> context,
                            CefRefPtr<CefV8Exception> exception,
                            CefRefPtr<CefV8StackTrace> stackTrace) override {
-    if (test_mode_ == V8TEST_NONE)
+    if (test_mode_ == V8TEST_NONE) {
       return;
+    }
 
     if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION ||
         test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
@@ -2678,8 +3000,8 @@
                        << stackTrace->GetFrame(i)->GetLineNumber() << "\n";
       }
       const char* stackFormattedShouldBe =
-          "at test2() in http://tests/V8Test.OnUncaughtException on line 3\n"
-          "at test() in http://tests/V8Test.OnUncaughtException on line 2\n";
+          "at test2() in https://tests/V8Test.OnUncaughtException on line 3\n"
+          "at test() in https://tests/V8Test.OnUncaughtException on line 2\n";
       EXPECT_STREQ(stackFormattedShouldBe, stackFormatted.str().c_str());
       DestroyTest();
     }
@@ -2690,13 +3012,14 @@
                                 CefRefPtr<CefFrame> frame,
                                 CefProcessId source_process,
                                 CefRefPtr<CefProcessMessage> message) override {
-    if (test_mode_ == V8TEST_NONE)
+    if (test_mode_ == V8TEST_NONE) {
       return false;
+    }
 
     const std::string& message_name = message->GetName();
     if (message_name == kV8RunTestMsg) {
       // Run the test asynchronously.
-      CefPostTask(TID_RENDERER, base::Bind(&V8RendererTest::RunTest, this));
+      CefPostTask(TID_RENDERER, base::BindOnce(&V8RendererTest::RunTest, this));
       return true;
     }
     return false;
@@ -2747,8 +3070,8 @@
     // is no longer possible.
     CefPostDelayedTask(
         TID_RENDERER,
-        base::Bind(&CefFrame::ExecuteJavaScript, frame.get(),
-                   "window.DevToolsLoaded()", frame->GetURL(), 0),
+        base::BindOnce(&CefFrame::ExecuteJavaScript, frame.get(),
+                       "window.DevToolsLoaded()", frame->GetURL(), 0),
         500);
   }
 
@@ -2927,7 +3250,8 @@
     }
 
     // Time out the test after a reasonable period of time.
-    SetTestTimeout();
+    SetTestTimeout(test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS ? 10000
+                                                                        : 5000);
   }
 
   void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
@@ -2954,8 +3278,7 @@
         CefBrowserSettings settings;
 
 #if defined(OS_WIN)
-        windowInfo.SetAsPopup(browser->GetHost()->GetWindowHandle(),
-                              "DevTools");
+        windowInfo.SetAsPopup(nullptr, "DevTools");
 #endif
 
         browser->GetHost()->ShowDevTools(windowInfo, this, settings,
@@ -2966,7 +3289,7 @@
 
     const std::string& url = frame->GetURL();
     if (url != kV8NavTestUrl && url != kV8ContextParentTestUrl &&
-        url.find("http://tests/") != std::string::npos) {
+        url.find("https://tests/") != std::string::npos) {
       // Run the test.
       CefRefPtr<CefProcessMessage> return_msg =
           CefProcessMessage::Create(kV8RunTestMsg);
@@ -2990,8 +3313,9 @@
 
     got_message_.yes();
 
-    if (message->GetArgumentList()->GetBool(0))
+    if (message->GetArgumentList()->GetBool(0)) {
       got_success_.yes();
+    }
 
     // Test is complete.
     DestroyTest();
@@ -3039,6 +3363,7 @@
 V8_TEST(ArrayCreate, V8TEST_ARRAY_CREATE)
 V8_TEST(ArrayValue, V8TEST_ARRAY_VALUE)
 V8_TEST(ArrayBuffer, V8TEST_ARRAY_BUFFER)
+V8_TEST(ArrayBufferCreateEmpty, V8TEST_ARRAY_BUFFER_CREATE_EMPTY)
 V8_TEST(ArrayBufferValue, V8TEST_ARRAY_BUFFER_VALUE)
 V8_TEST(ObjectCreate, V8TEST_OBJECT_CREATE)
 V8_TEST(ObjectUserData, V8TEST_OBJECT_USERDATA)
@@ -3064,6 +3389,12 @@
 V8_TEST(FunctionHandlerNoObject, V8TEST_FUNCTION_HANDLER_NO_OBJECT)
 V8_TEST(FunctionHandlerWithContext, V8TEST_FUNCTION_HANDLER_WITH_CONTEXT)
 V8_TEST(FunctionHandlerEmptyString, V8TEST_FUNCTION_HANDLER_EMPTY_STRING)
+V8_TEST(PromiseCreate, V8TEST_PROMISE_CREATE)
+V8_TEST(PromiseResolve, V8TEST_PROMISE_RESOLVE)
+V8_TEST(PromiseResolveNoArgument, V8TEST_PROMISE_RESOLVE_NO_ARGUMENT)
+V8_TEST(PromiseResolveHandler, V8TEST_PROMISE_RESOLVE_HANDLER)
+V8_TEST(PromiseReject, V8TEST_PROMISE_REJECT)
+V8_TEST(PromiseRejectHandler, V8TEST_PROMISE_REJECT_HANDLER)
 V8_TEST(ContextEval, V8TEST_CONTEXT_EVAL)
 V8_TEST(ContextEvalException, V8TEST_CONTEXT_EVAL_EXCEPTION)
 V8_TEST_EX(ContextEvalCspBypassUnsafeEval,
diff --git a/src/tests/ceftests/values_unittest.cc b/src/tests/ceftests/values_unittest.cc
index fa91ad9..565674e 100644
--- a/src/tests/ceftests/values_unittest.cc
+++ b/src/tests/ceftests/values_unittest.cc
@@ -44,12 +44,12 @@
 void TestBinary(CefRefPtr<CefBinaryValue> value, char* data, size_t data_size) {
   // Testing requires strings longer than 15 characters.
   EXPECT_GT(data_size, 15U);
-
   EXPECT_EQ(data_size, value->GetSize());
 
-  char* buff = new char[data_size + 1];
-  char old_char;
+  // Test direct access.
+  EXPECT_EQ(memcmp(value->GetRawData(), data, data_size), 0);
 
+  char* buff = new char[data_size + 1];
   // Test full read.
   memset(buff, 0, data_size + 1);
   EXPECT_EQ(data_size, value->GetData(buff, data_size, 0));
@@ -57,7 +57,7 @@
 
   // Test partial read with offset.
   memset(buff, 0, data_size + 1);
-  old_char = data[15];
+  char old_char = data[15];
   data[15] = 0;
   EXPECT_EQ(10U, value->GetData(buff, 10, 5));
   EXPECT_TRUE(!strcmp(buff, data + 5));
diff --git a/src/tests/ceftests/views/button_unittest.cc b/src/tests/ceftests/views/button_unittest.cc
index 1bd6363..5c0c73b 100644
--- a/src/tests/ceftests/views/button_unittest.cc
+++ b/src/tests/ceftests/views/button_unittest.cc
@@ -2,7 +2,7 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/views/cef_button.h"
 #include "include/views/cef_button_delegate.h"
 #include "include/views/cef_label_button.h"
@@ -115,31 +115,47 @@
   DISALLOW_COPY_AND_ASSIGN(EmptyMenuButtonDelegate);
 };
 
-void LabelButtonStyle() {
+void RunLabelButtonStyle(CefRefPtr<CefWindow> window) {
   CefRefPtr<CefLabelButton> button = CefLabelButton::CreateLabelButton(
       new EmptyMenuButtonDelegate(), kButtonText);
+
+  // Must be added to a parent window before retrieving the style to avoid
+  // a CHECK() in View::GetNativeTheme(). See https://crbug.com/1056756.
+  window->AddChildView(button);
+  window->Layout();
+
   VerifyLabelButtonStyle(button);
 }
 
-void LabelButtonStyleFramelessImpl() {
-  LabelButtonStyle();
+void LabelButtonStyleImpl(CefRefPtr<CefWaitableEvent> event) {
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created = base::BindOnce(RunLabelButtonStyle);
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
-void MenuButtonStyle() {
+void RunMenuButtonStyle(CefRefPtr<CefWindow> window) {
   CefRefPtr<CefMenuButton> button = CefMenuButton::CreateMenuButton(
       new EmptyMenuButtonDelegate(), kButtonText);
+
+  // Must be added to a parent window before retrieving the style to avoid
+  // a CHECK() in View::GetNativeTheme(). See https://crbug.com/1056756.
+  window->AddChildView(button);
+  window->Layout();
+
   VerifyMenuButtonStyle(button);
 }
 
-void MenuButtonStyleFramelessImpl() {
-  MenuButtonStyle();
+void MenuButtonStyleImpl(CefRefPtr<CefWaitableEvent> event) {
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created = base::BindOnce(RunMenuButtonStyle);
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 }  // namespace
 
 // Test Button getters/setters.
-BUTTON_TEST(LabelButtonStyleFrameless)
-BUTTON_TEST(MenuButtonStyleFrameless)
+BUTTON_TEST_ASYNC(LabelButtonStyle)
+BUTTON_TEST_ASYNC(MenuButtonStyle)
 
 namespace {
 
@@ -197,13 +213,15 @@
   EXPECT_TRUE(button->IsVisible());
   EXPECT_FALSE(button->IsDrawn());
 
-  if (with_text)
+  if (with_text) {
     EXPECT_STREQ(kButtonText, button->GetText().ToString().c_str());
-  else
+  } else {
     EXPECT_TRUE(button->GetText().empty());
+  }
 
-  if (with_image)
+  if (with_image) {
     AddImage(button);
+  }
 
   window->AddChildView(button);
   window->Layout();
@@ -217,7 +235,7 @@
   window->Show();
 
   // Wait a bit before trying to click the button.
-  CefPostDelayedTask(TID_UI, base::Bind(ClickButton, window, kButtonID),
+  CefPostDelayedTask(TID_UI, base::BindOnce(ClickButton, window, kButtonID),
                      kClickDelayMS);
 }
 
@@ -225,12 +243,12 @@
                       bool with_button_frame,
                       bool with_button_text,
                       bool with_button_image) {
-  TestWindowDelegate::Config config;
-  config.on_window_created =
-      base::Bind(RunLabelButtonClick, with_button_text, with_button_image);
-  config.frameless = false;
-  config.close_window = false;
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created =
+      base::BindOnce(RunLabelButtonClick, with_button_text, with_button_image);
+  config->frameless = false;
+  config->close_window = false;
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 void LabelButtonClickFramedWithTextWithImageFramelessWindowImpl(
@@ -393,7 +411,7 @@
     EXPECT_FALSE(model->SetFontList(4, font));
 
     // Wait a bit before trying to click the menu item.
-    CefPostDelayedTask(TID_UI, base::Bind(ClickMenuItem, menu_button),
+    CefPostDelayedTask(TID_UI, base::BindOnce(ClickMenuItem, menu_button),
                        kClickDelayMS);
 
     menu_button->ShowMenu(model, screen_point, CEF_MENU_ANCHOR_TOPLEFT);
@@ -433,13 +451,15 @@
   EXPECT_TRUE(button->IsVisible());
   EXPECT_FALSE(button->IsDrawn());
 
-  if (with_text)
+  if (with_text) {
     EXPECT_STREQ(kButtonText, button->GetText().ToString().c_str());
-  else
+  } else {
     EXPECT_TRUE(button->GetText().empty());
+  }
 
-  if (with_image)
+  if (with_image) {
     AddImage(button);
+  }
 
   window->AddChildView(button);
   window->Layout();
@@ -453,7 +473,7 @@
   window->Show();
 
   // Wait a bit before trying to click the button.
-  CefPostDelayedTask(TID_UI, base::Bind(ClickButton, window, kButtonID),
+  CefPostDelayedTask(TID_UI, base::BindOnce(ClickButton, window, kButtonID),
                      kClickDelayMS);
 }
 
@@ -461,12 +481,12 @@
                      bool with_button_frame,
                      bool with_button_text,
                      bool with_button_image) {
-  TestWindowDelegate::Config config;
-  config.on_window_created =
-      base::Bind(RunMenuButtonClick, with_button_text, with_button_image);
-  config.frameless = false;
-  config.close_window = false;
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created =
+      base::BindOnce(RunMenuButtonClick, with_button_text, with_button_image);
+  config->frameless = false;
+  config->close_window = false;
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 void MenuButtonClickFramedWithTextWithImageFramelessWindowImpl(
@@ -549,7 +569,7 @@
     popup_window_->Show();
 
     // Wait a bit before trying to click the popup button.
-    CefPostDelayedTask(TID_UI, base::Bind(ClickMenuItem, menu_button),
+    CefPostDelayedTask(TID_UI, base::BindOnce(ClickMenuItem, menu_button),
                        kClickDelayMS);
   }
 
@@ -579,10 +599,11 @@
   }
 
   void OnWindowDestroyed(CefRefPtr<CefWindow> window) override {
-    if (can_activate_)
+    if (can_activate_) {
       EXPECT_TRUE(got_focus_);
-    else
+    } else {
       EXPECT_FALSE(got_focus_);
+    }
 
     // Complete the test by closing the parent window.
     parent_window_->Close();
@@ -614,17 +635,17 @@
   window->Show();
 
   // Wait a bit before trying to click the button.
-  CefPostDelayedTask(TID_UI, base::Bind(ClickButton, window, kButtonID),
+  CefPostDelayedTask(TID_UI, base::BindOnce(ClickButton, window, kButtonID),
                      kClickDelayMS);
 }
 
 void MenuButtonCustomPopupClick(CefRefPtr<CefWaitableEvent> event,
                                 bool can_activate) {
-  TestWindowDelegate::Config config;
-  config.on_window_created =
-      base::Bind(RunMenuButtonCustomPopupClick, can_activate);
-  config.close_window = false;
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created =
+      base::BindOnce(RunMenuButtonCustomPopupClick, can_activate);
+  config->close_window = false;
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 void MenuButtonCustomPopupActivateImpl(CefRefPtr<CefWaitableEvent> event) {
diff --git a/src/tests/ceftests/views/panel_unittest.cc b/src/tests/ceftests/views/panel_unittest.cc
index 5cd1954..370635e 100644
--- a/src/tests/ceftests/views/panel_unittest.cc
+++ b/src/tests/ceftests/views/panel_unittest.cc
@@ -37,10 +37,11 @@
   EXPECT_STREQ("Panel", panel->GetTypeString().ToString().c_str());
   EXPECT_TRUE(panel->IsValid());
   EXPECT_FALSE(panel->IsAttached());
-  if (delegate)
+  if (delegate) {
     EXPECT_EQ(delegate.get(), panel->GetDelegate().get());
-  else
+  } else {
     EXPECT_FALSE(panel->GetDelegate().get());
+  }
   EXPECT_EQ(0, panel->GetID());
   EXPECT_FALSE(panel->GetParentView().get());
   EXPECT_EQ(CefRect(0, 0, 0, 0), panel->GetBounds());
@@ -292,10 +293,11 @@
   EXPECT_TRUE(child_delegate->IsReset());
 
   // Remove the child view.
-  if (remove_all)
+  if (remove_all) {
     parent_panel->RemoveAllChildViews();
-  else
+  } else {
     parent_panel->RemoveChildView(child_panel);
+  }
 
   // Verify final callback state.
   ChildVerifyFinalCallbackState(parent_delegate, parent_panel, child_delegate,
@@ -850,10 +852,11 @@
   EXPECT_EQ(CefRect(0, 0, 0, 0), panel_child->GetBounds());
 
   // With delegates the size can come from either the parent or child.
-  if (size_from_parent)
+  if (size_from_parent) {
     delegate_parent->preferred_size_ = expected_size;
-  else
+  } else {
     delegate_child->preferred_size_ = expected_size;
+  }
 
   // FillLayout is the default Layout. Both panels should end up with the same
   // size.
@@ -944,8 +947,9 @@
                             int child1_flex = 0,
                             int child2_flex = 0) {
   CefRefPtr<SizingPanelDelegate> delegate_parent;
-  if (with_delegate)
+  if (with_delegate) {
     delegate_parent = new SizingPanelDelegate();
+  }
   CefRefPtr<CefPanel> panel_parent = CefPanel::CreatePanel(delegate_parent);
 
   CefRefPtr<SizingPanelDelegate> delegate_child1, delegate_child2;
@@ -963,10 +967,11 @@
 
   // Give the parent a size.
   CefSize initial_parent_size(kBLParentSize, kBLParentSize);
-  if (with_delegate)
+  if (with_delegate) {
     delegate_parent->preferred_size_ = initial_parent_size;
-  else
+  } else {
     panel_parent->SetSize(initial_parent_size);
+  }
 
   // Give the children a size smaller than the parent.
   CefSize initial_child_size(kBLChildSize, kBLChildSize);
@@ -987,10 +992,12 @@
   if (child1_flex > 0 || child2_flex > 0) {
     // Flex will apply relative stretch in the main axis direction.
     CefRefPtr<CefBoxLayout> layout = panel_parent->GetLayout()->AsBoxLayout();
-    if (child1_flex > 0)
+    if (child1_flex > 0) {
       layout->SetFlexForView(panel_child1, child1_flex);
-    if (child2_flex > 0)
+    }
+    if (child2_flex > 0) {
       layout->SetFlexForView(panel_child2, child2_flex);
+    }
   }
 
   if (with_delegate) {
diff --git a/src/tests/ceftests/views/scroll_view_unittest.cc b/src/tests/ceftests/views/scroll_view_unittest.cc
index 5896211..67c4b1d 100644
--- a/src/tests/ceftests/views/scroll_view_unittest.cc
+++ b/src/tests/ceftests/views/scroll_view_unittest.cc
@@ -2,7 +2,7 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_pack_strings.h"
 #include "include/views/cef_panel.h"
 #include "include/views/cef_panel_delegate.h"
@@ -101,7 +101,9 @@
   EXPECT_TRUE(scroll_view->HasVerticalScrollbar());
 
   if (with_delegate) {
-    EXPECT_TRUE(scroll_view_delegate->got_get_preferred_size_);
+    // Layout() of the ScrollView no longer needs to call us for the size,
+    // see https://crrev.com/2701734b44.
+    EXPECT_FALSE(scroll_view_delegate->got_get_preferred_size_);
     EXPECT_TRUE(panel_delegate->got_get_preferred_size_);
   }
 
@@ -130,9 +132,10 @@
 }
 
 void ScrollViewLayout(CefRefPtr<CefWaitableEvent> event, bool with_delegate) {
-  TestWindowDelegate::Config config;
-  config.on_window_created = base::Bind(RunScrollViewLayout, with_delegate);
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created =
+      base::BindOnce(RunScrollViewLayout, with_delegate);
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 void ScrollViewLayoutWithDelegateImpl(CefRefPtr<CefWaitableEvent> event) {
diff --git a/src/tests/ceftests/views/test_window_delegate.cc b/src/tests/ceftests/views/test_window_delegate.cc
index 95c4ede..e0d1016 100644
--- a/src/tests/ceftests/views/test_window_delegate.cc
+++ b/src/tests/ceftests/views/test_window_delegate.cc
@@ -8,11 +8,14 @@
 #include "include/views/cef_window.h"
 #include "include/views/cef_window_delegate.h"
 #include "include/wrapper/cef_closure_task.h"
+#include "tests/ceftests/test_util.h"
 #include "tests/ceftests/thread_helper.h"
 #include "tests/gtest/include/gtest/gtest.h"
 
 #if defined(OS_WIN)
 #include <windows.h>
+#include "tests/shared/browser/geometry_util.h"
+#include "tests/shared/browser/util_win.h"
 #endif
 
 namespace {
@@ -20,6 +23,11 @@
 // Test timeout in MS.
 const int kTestTimeout = 5000;
 
+#if defined(OS_MAC)
+// Match the value in view_util_mac.mm.
+constexpr float kDefaultTitleBarHeight = 30;
+#endif
+
 }  // namespace
 
 // static
@@ -27,22 +35,37 @@
 
 // static
 void TestWindowDelegate::RunTest(CefRefPtr<CefWaitableEvent> event,
-                                 const Config& config) {
+                                 std::unique_ptr<Config> config) {
+  CefSize window_size{config->window_size, config->window_size};
+
+  if (!config->frameless) {
 #if defined(OS_WIN)
-  RECT rect = {0, 0, config.window_size, config.window_size};
-  if (!config.frameless) {
-    // The size value is for the client area. Calculate the whole window size
-    // based on the default frame window style.
+    // Expand the client area size to full window size based on the default
+    // frame window style. AdjustWindowRect expects pixel coordinates, so
+    // perform the necessary conversions.
+    auto scale_factor = client::GetDeviceScaleFactor();
+    auto scaled_size =
+        client::LogicalToDevice(config->window_size, scale_factor);
+
+    // Convert from DIP to pixel coords.
+    RECT rect = {0, 0, scaled_size, scaled_size};
+
     AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
                      false /* has_menu */);
-  }
-  CefSize window_size = CefSize(rect.right - rect.left, rect.bottom - rect.top);
-#else
-  CefSize window_size = CefSize(config.window_size, config.window_size);
+
+    // Convert from pixel to DIP coords.
+    auto scaled_rect = client::DeviceToLogical(
+        {rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top},
+        scale_factor);
+    window_size = {scaled_rect.width, scaled_rect.height};
+#elif defined(OS_MAC)
+    // Expand client area size to include the default titlebar height.
+    window_size.height += kDefaultTitleBarHeight;
 #endif
+  }
 
   CefWindow::CreateTopLevelWindow(
-      new TestWindowDelegate(event, config, window_size));
+      new TestWindowDelegate(event, std::move(config), window_size));
 }
 
 void TestWindowDelegate::OnWindowCreated(CefRefPtr<CefWindow> window) {
@@ -52,14 +75,8 @@
   EXPECT_TRUE(window->IsValid());
   EXPECT_FALSE(window->IsClosed());
 
-  EXPECT_FALSE(window->IsVisible());
-  EXPECT_FALSE(window->IsDrawn());
-
   EXPECT_FALSE(window->IsActive());
   EXPECT_FALSE(window->IsAlwaysOnTop());
-  EXPECT_FALSE(window->IsMaximized());
-  EXPECT_FALSE(window->IsMinimized());
-  EXPECT_FALSE(window->IsFullscreen());
 
   const char* title = "ViewsTest";
   window->SetTitle(title);
@@ -68,37 +85,69 @@
   EXPECT_FALSE(window->GetWindowIcon().get());
   EXPECT_FALSE(window->GetWindowAppIcon().get());
 
-  EXPECT_TRUE(window->GetDisplay().get());
+  auto display = window->GetDisplay();
+  EXPECT_TRUE(display.get());
 
-  // Size will come from GetPreferredSize() on initial Window creation.
-  EXPECT_TRUE(got_get_preferred_size_);
-  CefRect client_bounds = window->GetBounds();
-  if (config_.frameless) {
-    EXPECT_EQ(config_.window_size, client_bounds.width);
-    EXPECT_EQ(config_.window_size, client_bounds.height);
+  // Size will come from GetGetInitialBounds() or GetPreferredSize() on
+  // initial Window creation.
+  EXPECT_TRUE(got_get_initial_bounds_);
+  if (config_->window_origin.IsEmpty()) {
+    EXPECT_TRUE(got_get_preferred_size_);
   } else {
-    // Client area bounds calculation might have off-by-one errors on Windows
-    // due to non-client frame size being calculated internally in pixels and
-    // then converted to DIPs. See http://crbug.com/602692.
-    EXPECT_TRUE(abs(client_bounds.width - window_size_.width) <= 1);
-    EXPECT_TRUE(abs(client_bounds.height - window_size_.height) <= 1);
+    EXPECT_FALSE(got_get_preferred_size_);
+  }
+
+  // Expectations for the default |initial_show_state| value.
+  if (config_->initial_show_state == CEF_SHOW_STATE_NORMAL) {
+    EXPECT_FALSE(window->IsVisible());
+    EXPECT_FALSE(window->IsDrawn());
+
+    EXPECT_FALSE(window->IsMaximized());
+    EXPECT_FALSE(window->IsMinimized());
+    EXPECT_FALSE(window->IsFullscreen());
+
+    CefRect client_bounds = window->GetBounds();
+    if (!config_->window_origin.IsEmpty()) {
+      EXPECT_EQ(config_->window_origin.x, client_bounds.x);
+      EXPECT_EQ(config_->window_origin.y, client_bounds.y);
+    } else {
+      // Default origin is the upper-left corner of the display's work area.
+      auto work_area = display->GetWorkArea();
+      EXPECT_NEAR(work_area.x, client_bounds.x, 1);
+      EXPECT_NEAR(work_area.y, client_bounds.y, 1);
+    }
+
+    if (config_->frameless) {
+      EXPECT_NEAR(config_->window_size, client_bounds.width, 2);
+      EXPECT_NEAR(config_->window_size, client_bounds.height, 2);
+    } else {
+      // Client area bounds calculation might have off-by-one errors on Windows
+      // due to non-client frame size being calculated internally in pixels and
+      // then converted to DIPs. See https://crbug.com/602692.
+      EXPECT_NEAR(client_bounds.width, window_size_.width, 2);
+      EXPECT_NEAR(client_bounds.height, window_size_.height, 2);
+    }
   }
 
   // Run the callback.
-  if (!config_.on_window_created.is_null())
-    config_.on_window_created.Run(window);
+  if (!config_->on_window_created.is_null()) {
+    std::move(config_->on_window_created).Run(window);
+  }
 
-  if (config_.close_window) {
+  if (config_->close_window) {
     // Close the window asynchronously.
-    CefPostTask(TID_UI, base::Bind(&TestWindowDelegate::OnCloseWindow, this));
-  } else if (!CefCommandLine::GetGlobalCommandLine()->HasSwitch(
-                 "disable-test-timeout")) {
-    // Timeout the test after a reasonable delay. Use a WeakPtr so that the
-    // delayed task doesn't keep this object alive.
-    CefPostDelayedTask(TID_UI,
-                       base::Bind(&TestWindowDelegate::OnTimeoutWindow,
-                                  weak_ptr_factory_.GetWeakPtr()),
-                       kTestTimeout);
+    CefPostTask(TID_UI,
+                base::BindOnce(&TestWindowDelegate::OnCloseWindow, this));
+  } else {
+    const auto timeout = GetConfiguredTestTimeout(kTestTimeout);
+    if (timeout) {
+      // Timeout the test after a reasonable delay. Use a WeakPtr so that the
+      // delayed task doesn't keep this object alive.
+      CefPostDelayedTask(TID_UI,
+                         base::BindOnce(&TestWindowDelegate::OnTimeoutWindow,
+                                        weak_ptr_factory_.GetWeakPtr()),
+                         *timeout);
+    }
   }
 }
 
@@ -111,8 +160,9 @@
   EXPECT_FALSE(window->IsDrawn());
 
   // Run the callback.
-  if (!config_.on_window_destroyed.is_null())
-    config_.on_window_destroyed.Run(window);
+  if (!config_->on_window_destroyed.is_null()) {
+    std::move(config_->on_window_destroyed).Run(window);
+  }
 
   window_ = nullptr;
 
@@ -120,8 +170,59 @@
   weak_ptr_factory_.InvalidateWeakPtrs();
 }
 
+void TestWindowDelegate::OnWindowFullscreenTransition(
+    CefRefPtr<CefWindow> window,
+    bool is_completed) {
+  EXPECT_TRUE(window->IsSame(window_));
+
+  EXPECT_TRUE(window->IsValid());
+  EXPECT_FALSE(window->IsClosed());
+  EXPECT_TRUE(window->IsVisible());
+  EXPECT_TRUE(window->IsDrawn());
+
+  fullscreen_transition_callback_count_++;
+
+#if defined(OS_MAC)
+  // Two callbacks on MacOS.
+  EXPECT_EQ(is_completed ? 2U : 1U, fullscreen_transition_callback_count_);
+#else
+  // Single callback on other platforms.
+  EXPECT_TRUE(is_completed);
+  EXPECT_EQ(1U, fullscreen_transition_callback_count_);
+#endif
+
+  if (is_completed) {
+    fullscreen_transition_complete_count_++;
+
+    // Reset intermediate state.
+    fullscreen_transition_callback_count_ = 0;
+
+    // Run the callback.
+    if (!config_->on_window_fullscreen_transition_complete.is_null()) {
+      config_->on_window_fullscreen_transition_complete.Run(
+          window, fullscreen_transition_complete_count_);
+    }
+  }
+}
+
 bool TestWindowDelegate::IsFrameless(CefRefPtr<CefWindow> window) {
-  return config_.frameless;
+  return config_->frameless;
+}
+
+CefRect TestWindowDelegate::GetInitialBounds(CefRefPtr<CefWindow> window) {
+  got_get_initial_bounds_ = true;
+  if (!config_->window_origin.IsEmpty()) {
+    return CefRect(config_->window_origin.x, config_->window_origin.y,
+                   window_size_.width, window_size_.height);
+  }
+
+  // Call GetPreferredSize().
+  return CefRect();
+}
+
+cef_show_state_t TestWindowDelegate::GetInitialShowState(
+    CefRefPtr<CefWindow> window) {
+  return config_->initial_show_state;
 }
 
 CefSize TestWindowDelegate::GetPreferredSize(CefRefPtr<CefView> view) {
@@ -131,35 +232,38 @@
 
 bool TestWindowDelegate::OnAccelerator(CefRefPtr<CefWindow> window,
                                        int command_id) {
-  if (!config_.on_accelerator.is_null())
-    return config_.on_accelerator.Run(window_, command_id);
+  if (!config_->on_accelerator.is_null()) {
+    return config_->on_accelerator.Run(window_, command_id);
+  }
   return false;
 }
 
 bool TestWindowDelegate::OnKeyEvent(CefRefPtr<CefWindow> window,
                                     const CefKeyEvent& event) {
-  if (!config_.on_key_event.is_null())
-    return config_.on_key_event.Run(window_, event);
+  if (!config_->on_key_event.is_null()) {
+    return config_->on_key_event.Run(window_, event);
+  }
   return false;
 }
 
 TestWindowDelegate::TestWindowDelegate(CefRefPtr<CefWaitableEvent> event,
-                                       const Config& config,
+                                       std::unique_ptr<Config> config,
                                        const CefSize& window_size)
     : event_(event),
-      config_(config),
+      config_(std::move(config)),
       window_size_(window_size),
       weak_ptr_factory_(this) {}
 
 TestWindowDelegate::~TestWindowDelegate() {
   // Complete the test (signal the event) asynchronously so objects on the call
   // stack have a chance to unwind.
-  CefPostTask(TID_UI, base::Bind(SignalEvent, event_));
+  CefPostTask(TID_UI, base::BindOnce(SignalEvent, event_));
 }
 
 void TestWindowDelegate::OnCloseWindow() {
-  if (!window_)
+  if (!window_) {
     return;
+  }
 
   EXPECT_TRUE(window_->IsValid());
   EXPECT_FALSE(window_->IsClosed());
diff --git a/src/tests/ceftests/views/test_window_delegate.h b/src/tests/ceftests/views/test_window_delegate.h
index 2f0519b..1fba567 100644
--- a/src/tests/ceftests/views/test_window_delegate.h
+++ b/src/tests/ceftests/views/test_window_delegate.h
@@ -2,6 +2,8 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
+#include <memory>
+
 #include "include/base/cef_callback.h"
 #include "include/base/cef_weak_ptr.h"
 #include "include/cef_waitable_event.h"
@@ -14,20 +16,29 @@
   static const int kWSize;
 
   // Test execution callback.
-  typedef base::Callback<void(CefRefPtr<CefWindow>)> OnWindowCreatedCallback;
-  typedef base::Callback<void(CefRefPtr<CefWindow>)> OnWindowDestroyedCallback;
-  typedef base::Callback<bool(CefRefPtr<CefWindow>, int)> OnAcceleratorCallback;
-  typedef base::Callback<bool(CefRefPtr<CefWindow>, const CefKeyEvent&)>
-      OnKeyEventCallback;
+  using OnWindowCreatedCallback =
+      base::OnceCallback<void(CefRefPtr<CefWindow>)>;
+  using OnWindowDestroyedCallback =
+      base::OnceCallback<void(CefRefPtr<CefWindow>)>;
+  using OnWindowFullscreenTransitionCompleteCallback =
+      base::RepeatingCallback<void(CefRefPtr<CefWindow>, size_t /*count*/)>;
+  using OnAcceleratorCallback =
+      base::RepeatingCallback<bool(CefRefPtr<CefWindow>, int)>;
+  using OnKeyEventCallback =
+      base::RepeatingCallback<bool(CefRefPtr<CefWindow>, const CefKeyEvent&)>;
 
   struct Config {
     OnWindowCreatedCallback on_window_created;
     OnWindowDestroyedCallback on_window_destroyed;
+    OnWindowFullscreenTransitionCompleteCallback
+        on_window_fullscreen_transition_complete;
     OnAcceleratorCallback on_accelerator;
     OnKeyEventCallback on_key_event;
     bool frameless = false;
     bool close_window = true;
     int window_size = kWSize;
+    CefPoint window_origin = {};
+    cef_show_state_t initial_show_state = CEF_SHOW_STATE_NORMAL;
   };
 
   // Creates a Window with a new TestWindowDelegate instance and executes
@@ -36,12 +47,17 @@
   // without a frame. If |close_window| is true the Window will be closed
   // immediately after |window_test| returns. Otherwise, the caller is
   // responsible for closing the Window passed to |window_test|.
-  static void RunTest(CefRefPtr<CefWaitableEvent> event, const Config& config);
+  static void RunTest(CefRefPtr<CefWaitableEvent> event,
+                      std::unique_ptr<Config> config);
 
   // CefWindowDelegate methods:
   void OnWindowCreated(CefRefPtr<CefWindow> window) override;
   void OnWindowDestroyed(CefRefPtr<CefWindow> window) override;
+  void OnWindowFullscreenTransition(CefRefPtr<CefWindow> window,
+                                    bool is_completed) override;
   bool IsFrameless(CefRefPtr<CefWindow> window) override;
+  CefRect GetInitialBounds(CefRefPtr<CefWindow> window) override;
+  cef_show_state_t GetInitialShowState(CefRefPtr<CefWindow> window) override;
   CefSize GetPreferredSize(CefRefPtr<CefView> view) override;
   bool OnAccelerator(CefRefPtr<CefWindow> window, int command_id) override;
   bool OnKeyEvent(CefRefPtr<CefWindow> window,
@@ -49,7 +65,7 @@
 
  private:
   TestWindowDelegate(CefRefPtr<CefWaitableEvent> event,
-                     const Config& config,
+                     std::unique_ptr<Config> config,
                      const CefSize& window_size);
   ~TestWindowDelegate() override;
 
@@ -57,13 +73,17 @@
   void OnTimeoutWindow();
 
   CefRefPtr<CefWaitableEvent> event_;
-  const Config config_;
+  std::unique_ptr<Config> config_;
   const CefSize window_size_;
 
   CefRefPtr<CefWindow> window_;
 
+  bool got_get_initial_bounds_ = false;
   bool got_get_preferred_size_ = false;
 
+  size_t fullscreen_transition_callback_count_ = 0;
+  size_t fullscreen_transition_complete_count_ = 0;
+
   // Must be the last member.
   base::WeakPtrFactory<TestWindowDelegate> weak_ptr_factory_;
 
diff --git a/src/tests/ceftests/views/textfield_unittest.cc b/src/tests/ceftests/views/textfield_unittest.cc
index a5b6b1a..aba9118 100644
--- a/src/tests/ceftests/views/textfield_unittest.cc
+++ b/src/tests/ceftests/views/textfield_unittest.cc
@@ -2,7 +2,7 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_pack_strings.h"
 #include "include/views/cef_textfield.h"
 #include "include/views/cef_textfield_delegate.h"
@@ -31,11 +31,16 @@
 
 namespace {
 
-void TextfieldContentsImpl() {
+void RunTextfieldContents(CefRefPtr<CefWindow> window) {
   CefRefPtr<CefTextfield> textfield = CefTextfield::CreateTextfield(nullptr);
   EXPECT_TRUE(textfield.get());
   EXPECT_TRUE(textfield->AsTextfield().get());
 
+  // Must be added to a parent window before retrieving the style to avoid
+  // a CHECK() in View::GetNativeTheme(). See https://crbug.com/1056756.
+  window->AddChildView(textfield);
+  window->Layout();
+
   // Test defaults.
   EXPECT_TRUE(textfield->GetText().empty());
   EXPECT_FALSE(textfield->HasSelection());
@@ -59,12 +64,12 @@
 
   // Test select range.
   EXPECT_FALSE(textfield->HasSelection());
-  EXPECT_EQ(
-      CefRange(static_cast<int>(cursor_pos), static_cast<int>(cursor_pos)),
-      textfield->GetSelectedRange());
-  textfield->SelectRange(CefRange(0, static_cast<int>(cursor_pos)));
+  EXPECT_EQ(CefRange(static_cast<uint32_t>(cursor_pos),
+                     static_cast<uint32_t>(cursor_pos)),
+            textfield->GetSelectedRange());
+  textfield->SelectRange(CefRange(0, static_cast<uint32_t>(cursor_pos)));
   EXPECT_TRUE(textfield->HasSelection());
-  EXPECT_EQ(CefRange(0, static_cast<int>(cursor_pos)),
+  EXPECT_EQ(CefRange(0, static_cast<uint32_t>(cursor_pos)),
             textfield->GetSelectedRange());
   EXPECT_STREQ(kText, textfield->GetSelectedText().ToString().c_str());
   EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
@@ -84,33 +89,44 @@
   EXPECT_TRUE(textfield->HasSelection());
 
   cursor_pos = sizeof(kReplaceText) + sizeof(kAppendText) - 2;
-  EXPECT_EQ(CefRange(0, static_cast<int>(cursor_pos)),
+  EXPECT_EQ(CefRange(0, static_cast<uint32_t>(cursor_pos)),
             textfield->GetSelectedRange());
   EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
 
   // Test clear selection.
   textfield->ClearSelection();
   EXPECT_FALSE(textfield->HasSelection());
-  EXPECT_EQ(
-      CefRange(static_cast<int>(cursor_pos), static_cast<int>(cursor_pos)),
-      textfield->GetSelectedRange());
+  EXPECT_EQ(CefRange(static_cast<uint32_t>(cursor_pos),
+                     static_cast<uint32_t>(cursor_pos)),
+            textfield->GetSelectedRange());
   EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
 
   // Test selection with command.
-  EXPECT_TRUE(textfield->IsCommandEnabled(IDS_APP_SELECT_ALL));
-  textfield->ExecuteCommand(IDS_APP_SELECT_ALL);
+  EXPECT_TRUE(textfield->IsCommandEnabled(CEF_TFC_SELECT_ALL));
+  textfield->ExecuteCommand(CEF_TFC_SELECT_ALL);
   EXPECT_TRUE(textfield->HasSelection());
-  EXPECT_EQ(CefRange(0, static_cast<int>(cursor_pos)),
+  EXPECT_EQ(CefRange(0, static_cast<uint32_t>(cursor_pos)),
             textfield->GetSelectedRange());
   EXPECT_EQ(cursor_pos, textfield->GetCursorPosition());
 
   textfield->ClearEditHistory();
 }
 
-void TextfieldStyleImpl() {
+void TextfieldContentsImpl(CefRefPtr<CefWaitableEvent> event) {
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created = base::BindOnce(RunTextfieldContents);
+  TestWindowDelegate::RunTest(event, std::move(config));
+}
+
+void RunTextfieldStyle(CefRefPtr<CefWindow> window) {
   CefRefPtr<CefTextfield> textfield = CefTextfield::CreateTextfield(nullptr);
   EXPECT_TRUE(textfield.get());
 
+  // Must be added to a parent window before retrieving the style to avoid
+  // a CHECK() in View::GetNativeTheme(). See https://crbug.com/1056756.
+  window->AddChildView(textfield);
+  window->Layout();
+
   // Test defaults.
   EXPECT_FALSE(textfield->IsPasswordInput());
   EXPECT_FALSE(textfield->IsReadOnly());
@@ -160,11 +176,17 @@
   textfield->SetAccessibleName("MyTextfield");
 }
 
+void TextfieldStyleImpl(CefRefPtr<CefWaitableEvent> event) {
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created = base::BindOnce(RunTextfieldStyle);
+  TestWindowDelegate::RunTest(event, std::move(config));
+}
+
 }  // namespace
 
 // Test Textfield getters/setters.
-TEXTFIELD_TEST(TextfieldContents)
-TEXTFIELD_TEST(TextfieldStyle)
+TEXTFIELD_TEST_ASYNC(TextfieldContents)
+TEXTFIELD_TEST_ASYNC(TextfieldStyle)
 
 namespace {
 
@@ -173,7 +195,7 @@
 // Contents need to be supported by the TranslateKey function.
 const char kTestInputMessage[] = "Test Message";
 
-void TranslateKey(int c, int* keycode, uint32* modifiers) {
+void TranslateKey(int c, int* keycode, uint32_t* modifiers) {
   *keycode = VKEY_UNKNOWN;
   *modifiers = 0;
 
@@ -199,14 +221,14 @@
     if (event.type == KEYEVENT_RAWKEYDOWN &&
         event.windows_key_code == VKEY_RETURN) {
       // Got the whole string. Finish the test asynchronously.
-      CefPostTask(TID_UI, base::Bind(&TestTextfieldDelegate::FinishTest, this,
-                                     textfield));
+      CefPostTask(TID_UI, base::BindOnce(&TestTextfieldDelegate::FinishTest,
+                                         this, textfield));
       return true;
     }
 
     if (event.type == KEYEVENT_CHAR) {
       int keycode;
-      uint32 modifiers;
+      uint32_t modifiers;
       TranslateKey(kTestInputMessage[index_++], &keycode, &modifiers);
 
       EXPECT_EQ(keycode, event.windows_key_code);
@@ -266,7 +288,7 @@
   // Send the contents of |kTestInputMessage| to the textfield.
   for (size_t i = 0; i < sizeof(kTestInputMessage) - 1; ++i) {
     int keycode;
-    uint32 modifiers;
+    uint32_t modifiers;
     TranslateKey(kTestInputMessage[i], &keycode, &modifiers);
     window->SendKeyPress(keycode, modifiers);
   }
@@ -276,10 +298,10 @@
 }
 
 void TextfieldKeyEventImpl(CefRefPtr<CefWaitableEvent> event) {
-  TestWindowDelegate::Config config;
-  config.on_window_created = base::Bind(RunTextfieldKeyEvent);
-  config.close_window = false;
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created = base::BindOnce(RunTextfieldKeyEvent);
+  config->close_window = false;
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 }  // namespace
diff --git a/src/tests/ceftests/views/window_unittest.cc b/src/tests/ceftests/views/window_unittest.cc
index a2be321..75b267c 100644
--- a/src/tests/ceftests/views/window_unittest.cc
+++ b/src/tests/ceftests/views/window_unittest.cc
@@ -2,7 +2,7 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/views/cef_box_layout.h"
 #include "include/views/cef_layout.h"
 #include "include/views/cef_panel.h"
@@ -36,39 +36,142 @@
   EXPECT_LE(abs(expected.height - actual.height), allowed_deviance);
 }
 
+void ExpectClosePoints(const CefPoint& expected,
+                       const CefPoint& actual,
+                       int allowed_deviance) {
+  EXPECT_LE(abs(expected.x - actual.x), allowed_deviance);
+  EXPECT_LE(abs(expected.y - actual.y), allowed_deviance);
+}
+
 void WindowCreateImpl(CefRefPtr<CefWaitableEvent> event) {
-  TestWindowDelegate::Config config;
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 void WindowCreateFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
-  TestWindowDelegate::Config config;
-  config.frameless = true;
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->frameless = true;
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
-void RunWindowShowHide(CefRefPtr<CefWindow> window) {
-  EXPECT_FALSE(window->IsVisible());
-  EXPECT_FALSE(window->IsDrawn());
-  window->Show();
-  EXPECT_TRUE(window->IsVisible());
-  EXPECT_TRUE(window->IsDrawn());
+void RunWindowShow(cef_show_state_t initial_show_state,
+                   CefRefPtr<CefWindow> window) {
+#if defined(OS_MAC)
+  if (initial_show_state == CEF_SHOW_STATE_FULLSCREEN) {
+    // On MacOS, starting in fullscreen mode also shows the window on creation.
+    EXPECT_TRUE(window->IsVisible());
+    EXPECT_TRUE(window->IsDrawn());
+  } else
+#endif
+  {
+    EXPECT_FALSE(window->IsVisible());
+    EXPECT_FALSE(window->IsDrawn());
+    window->Show();
+  }
+
+  if (initial_show_state == CEF_SHOW_STATE_MINIMIZED) {
+#if !defined(OS_MAC)
+    // This result is a bit unexpected, but I guess the platform considers a
+    // window to be visible even when it's minimized.
+    EXPECT_TRUE(window->IsVisible());
+    EXPECT_TRUE(window->IsDrawn());
+#else
+    EXPECT_FALSE(window->IsVisible());
+    EXPECT_FALSE(window->IsDrawn());
+#endif
+  } else {
+    EXPECT_TRUE(window->IsVisible());
+    EXPECT_TRUE(window->IsDrawn());
+  }
+
+  switch (initial_show_state) {
+    case CEF_SHOW_STATE_NORMAL:
+      EXPECT_FALSE(window->IsMaximized());
+      EXPECT_FALSE(window->IsMinimized());
+      EXPECT_FALSE(window->IsFullscreen());
+      break;
+    case CEF_SHOW_STATE_MINIMIZED:
+      EXPECT_FALSE(window->IsMaximized());
+#if defined(OS_WIN)
+      // On MacOS, IsMinimized() state isn't reliable in this callback due to a
+      // timing issue between NativeWidgetMac::Minimize requesting the minimize
+      // state change (before this callback) and
+      // NativeWidgetMacNSWindowHost::OnWindowMiniaturizedChanged indicating the
+      // completed state change (after this callback).
+      // On Linux, there's likely a similar timing issue.
+      EXPECT_TRUE(window->IsMinimized());
+#endif
+      EXPECT_FALSE(window->IsFullscreen());
+      break;
+    case CEF_SHOW_STATE_MAXIMIZED:
+#if !defined(OS_LINUX)
+      // On Linux, there's likely a similar timing issue.
+      EXPECT_TRUE(window->IsMaximized());
+#endif
+      EXPECT_FALSE(window->IsMinimized());
+      EXPECT_FALSE(window->IsFullscreen());
+      break;
+    case CEF_SHOW_STATE_FULLSCREEN:
+      EXPECT_FALSE(window->IsMaximized());
+      EXPECT_FALSE(window->IsMinimized());
+      EXPECT_TRUE(window->IsFullscreen());
+      break;
+  }
+}
+
+void WindowCreateWithOriginImpl(CefRefPtr<CefWaitableEvent> event) {
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->window_origin = {100, 200};
+  config->on_window_created =
+      base::BindOnce(RunWindowShow, config->initial_show_state);
+  TestWindowDelegate::RunTest(event, std::move(config));
+}
+
+void WindowCreateMinimizedImpl(CefRefPtr<CefWaitableEvent> event) {
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->initial_show_state = CEF_SHOW_STATE_MINIMIZED;
+  config->on_window_created =
+      base::BindOnce(RunWindowShow, config->initial_show_state);
+  TestWindowDelegate::RunTest(event, std::move(config));
+}
+
+void WindowCreateMaximizedImpl(CefRefPtr<CefWaitableEvent> event) {
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->initial_show_state = CEF_SHOW_STATE_MAXIMIZED;
+  config->on_window_created =
+      base::BindOnce(RunWindowShow, config->initial_show_state);
+  TestWindowDelegate::RunTest(event, std::move(config));
+}
+
+void WindowCreateFullscreenImpl(CefRefPtr<CefWaitableEvent> event) {
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->initial_show_state = CEF_SHOW_STATE_FULLSCREEN;
+  config->on_window_created =
+      base::BindOnce(RunWindowShow, config->initial_show_state);
+  TestWindowDelegate::RunTest(event, std::move(config));
+}
+
+void RunWindowShowHide(cef_show_state_t initial_show_state,
+                       CefRefPtr<CefWindow> window) {
+  RunWindowShow(initial_show_state, window);
   window->Hide();
   EXPECT_FALSE(window->IsVisible());
   EXPECT_FALSE(window->IsDrawn());
 }
 
 void WindowShowHideImpl(CefRefPtr<CefWaitableEvent> event) {
-  TestWindowDelegate::Config config;
-  config.on_window_created = base::Bind(RunWindowShowHide);
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created =
+      base::BindOnce(RunWindowShowHide, config->initial_show_state);
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 void WindowShowHideFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
-  TestWindowDelegate::Config config;
-  config.on_window_created = base::Bind(RunWindowShowHide);
-  config.frameless = true;
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created =
+      base::BindOnce(RunWindowShowHide, config->initial_show_state);
+  config->frameless = true;
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 const int kWPanel1ID = 1;
@@ -110,9 +213,9 @@
 
   // The children should each take up 50% of the client area.
   ExpectCloseRects(CefRect(0, 0, kWSize, kWSize / 2), panel_child1->GetBounds(),
-                   1);
+                   2);
   ExpectCloseRects(CefRect(0, kWSize / 2, kWSize, kWSize / 2),
-                   panel_child2->GetBounds(), 1);
+                   panel_child2->GetBounds(), 2);
 }
 
 void RunWindowLayoutAndCoords(CefRefPtr<CefWindow> window) {
@@ -135,9 +238,9 @@
             point);
   point = CefPoint(0, 0);
   EXPECT_TRUE(view2->ConvertPointToScreen(point));
-  EXPECT_EQ(CefPoint(client_bounds_in_screen.x,
-                     client_bounds_in_screen.y + kWSize / 2),
-            point);
+  ExpectClosePoints(CefPoint(client_bounds_in_screen.x,
+                             client_bounds_in_screen.y + kWSize / 2),
+                    point, 1);
 
   // Test view from screen coordinate conversions.
   point = CefPoint(client_bounds_in_screen.x, client_bounds_in_screen.y);
@@ -146,7 +249,7 @@
   point = CefPoint(client_bounds_in_screen.x,
                    client_bounds_in_screen.y + kWSize / 2);
   EXPECT_TRUE(view2->ConvertPointFromScreen(point));
-  EXPECT_EQ(CefPoint(0, 0), point);
+  ExpectClosePoints(CefPoint(0, 0), point, 1);
 
   // Test view to window coordinate conversions.
   point = CefPoint(0, 0);
@@ -154,7 +257,7 @@
   EXPECT_EQ(CefPoint(0, 0), point);
   point = CefPoint(0, 0);
   EXPECT_TRUE(view2->ConvertPointToWindow(point));
-  EXPECT_EQ(CefPoint(0, kWSize / 2), point);
+  ExpectClosePoints(CefPoint(0, kWSize / 2), point, 1);
 
   // Test view from window coordinate conversions.
   point = CefPoint(0, 0);
@@ -162,23 +265,23 @@
   EXPECT_EQ(CefPoint(0, 0), point);
   point = CefPoint(0, kWSize / 2);
   EXPECT_TRUE(view2->ConvertPointFromWindow(point));
-  EXPECT_EQ(CefPoint(0, 0), point);
+  ExpectClosePoints(CefPoint(0, 0), point, 1);
 
   // Test view to view coordinate conversions.
   point = CefPoint(0, 0);
   EXPECT_TRUE(view1->ConvertPointToView(view2, point));
-  EXPECT_EQ(CefPoint(0, -kWSize / 2), point);
+  ExpectClosePoints(CefPoint(0, -kWSize / 2), point, 1);
   point = CefPoint(0, 0);
   EXPECT_TRUE(view2->ConvertPointToView(view1, point));
-  EXPECT_EQ(CefPoint(0, kWSize / 2), point);
+  ExpectClosePoints(CefPoint(0, kWSize / 2), point, 1);
 
   // Test view from view coordinate conversions.
   point = CefPoint(0, -kWSize / 2);
   EXPECT_TRUE(view1->ConvertPointFromView(view2, point));
-  EXPECT_EQ(CefPoint(0, 0), point);
+  ExpectClosePoints(CefPoint(0, 0), point, 1);
   point = CefPoint(0, kWSize / 2);
   EXPECT_TRUE(view2->ConvertPointFromView(view1, point));
-  EXPECT_EQ(CefPoint(0, 0), point);
+  ExpectClosePoints(CefPoint(0, 0), point, 1);
 
   CefRefPtr<CefDisplay> display = window->GetDisplay();
   EXPECT_TRUE(display.get());
@@ -187,21 +290,27 @@
   point = CefPoint(client_bounds_in_screen.x, client_bounds_in_screen.y);
   display->ConvertPointToPixels(point);
   display->ConvertPointFromPixels(point);
-  EXPECT_EQ(CefPoint(client_bounds_in_screen.x, client_bounds_in_screen.y),
-            point);
+  ExpectClosePoints(
+      CefPoint(client_bounds_in_screen.x, client_bounds_in_screen.y), point, 1);
+
+  // We don't know what the pixel values will be, but they should be reversable.
+  point = CefPoint(client_bounds_in_screen.x, client_bounds_in_screen.y);
+  const auto pixels = CefDisplay::ConvertScreenPointToPixels(point);
+  const auto dip = CefDisplay::ConvertScreenPointFromPixels(pixels);
+  EXPECT_EQ(point, dip);
 }
 
 void WindowLayoutAndCoordsImpl(CefRefPtr<CefWaitableEvent> event) {
-  TestWindowDelegate::Config config;
-  config.on_window_created = base::Bind(RunWindowLayoutAndCoords);
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created = base::BindOnce(RunWindowLayoutAndCoords);
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 void WindowLayoutAndCoordsFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
-  TestWindowDelegate::Config config;
-  config.on_window_created = base::Bind(RunWindowLayoutAndCoords);
-  config.frameless = true;
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created = base::BindOnce(RunWindowLayoutAndCoords);
+  config->frameless = true;
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 void VerifyRestore(CefRefPtr<CefWindow> window) {
@@ -223,7 +332,8 @@
   EXPECT_TRUE(window->IsDrawn());
 
   window->Restore();
-  CefPostDelayedTask(TID_UI, base::Bind(VerifyRestore, window), kStateDelayMS);
+  CefPostDelayedTask(TID_UI, base::BindOnce(VerifyRestore, window),
+                     kStateDelayMS);
 }
 
 void RunWindowMaximize(CefRefPtr<CefWindow> window) {
@@ -236,22 +346,23 @@
   EXPECT_TRUE(window->IsDrawn());
 
   window->Maximize();
-  CefPostDelayedTask(TID_UI, base::Bind(VerifyMaximize, window), kStateDelayMS);
+  CefPostDelayedTask(TID_UI, base::BindOnce(VerifyMaximize, window),
+                     kStateDelayMS);
 }
 
 void WindowMaximizeImpl(CefRefPtr<CefWaitableEvent> event) {
-  TestWindowDelegate::Config config;
-  config.on_window_created = base::Bind(RunWindowMaximize);
-  config.close_window = false;
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created = base::BindOnce(RunWindowMaximize);
+  config->close_window = false;
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 void WindowMaximizeFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
-  TestWindowDelegate::Config config;
-  config.on_window_created = base::Bind(RunWindowMaximize);
-  config.frameless = true;
-  config.close_window = false;
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created = base::BindOnce(RunWindowMaximize);
+  config->frameless = true;
+  config->close_window = false;
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 void VerifyMinimize(CefRefPtr<CefWindow> window) {
@@ -259,13 +370,19 @@
   EXPECT_FALSE(window->IsMaximized());
   EXPECT_FALSE(window->IsFullscreen());
 
+#if defined(OS_WIN)
   // This result is a bit unexpected, but I guess the platform considers a
   // window to be visible even when it's minimized.
   EXPECT_TRUE(window->IsVisible());
   EXPECT_TRUE(window->IsDrawn());
+#else
+  EXPECT_FALSE(window->IsVisible());
+  EXPECT_FALSE(window->IsDrawn());
+#endif
 
   window->Restore();
-  CefPostDelayedTask(TID_UI, base::Bind(VerifyRestore, window), kStateDelayMS);
+  CefPostDelayedTask(TID_UI, base::BindOnce(VerifyRestore, window),
+                     kStateDelayMS);
 }
 
 void RunWindowMinimize(CefRefPtr<CefWindow> window) {
@@ -278,45 +395,44 @@
   EXPECT_TRUE(window->IsDrawn());
 
   window->Minimize();
-  CefPostDelayedTask(TID_UI, base::Bind(VerifyMinimize, window), kStateDelayMS);
+  CefPostDelayedTask(TID_UI, base::BindOnce(VerifyMinimize, window),
+                     kStateDelayMS);
 }
 
 void WindowMinimizeImpl(CefRefPtr<CefWaitableEvent> event) {
-  TestWindowDelegate::Config config;
-  config.on_window_created = base::Bind(RunWindowMinimize);
-  config.close_window = false;
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created = base::BindOnce(RunWindowMinimize);
+  config->close_window = false;
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 void WindowMinimizeFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
-  TestWindowDelegate::Config config;
-  config.on_window_created = base::Bind(RunWindowMinimize);
-  config.frameless = true;
-  config.close_window = false;
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created = base::BindOnce(RunWindowMinimize);
+  config->frameless = true;
+  config->close_window = false;
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
-
-void VerifyFullscreenExit(CefRefPtr<CefWindow> window) {
+void WindowFullscreenTransitionComplete(CefRefPtr<CefWindow> window,
+                                        size_t count) {
   EXPECT_FALSE(window->IsMinimized());
+
+#if defined(OS_MAC)
+  // On MacOS, IsMaximized() returns true when IsFullscreen() returns true.
+  EXPECT_EQ(window->IsFullscreen(), window->IsMaximized());
+#else
   EXPECT_FALSE(window->IsMaximized());
-  EXPECT_FALSE(window->IsFullscreen());
-  EXPECT_TRUE(window->IsVisible());
-  EXPECT_TRUE(window->IsDrawn());
+#endif
 
-  // End the test by closing the Window.
-  window->Close();
-}
+  if (window->IsFullscreen()) {
+    EXPECT_EQ(1U, count);
+    window->SetFullscreen(false);
+  } else {
+    EXPECT_EQ(2U, count);
 
-void VerifyFullscreen(CefRefPtr<CefWindow> window) {
-  EXPECT_FALSE(window->IsMinimized());
-  EXPECT_FALSE(window->IsMaximized());
-  EXPECT_TRUE(window->IsFullscreen());
-  EXPECT_TRUE(window->IsVisible());
-  EXPECT_TRUE(window->IsDrawn());
-
-  window->SetFullscreen(false);
-  CefPostDelayedTask(TID_UI, base::Bind(VerifyFullscreenExit, window),
-                     kStateDelayMS);
+    // End the test by closing the Window.
+    window->Close();
+  }
 }
 
 void RunWindowFullscreen(CefRefPtr<CefWindow> window) {
@@ -329,23 +445,25 @@
   EXPECT_TRUE(window->IsDrawn());
 
   window->SetFullscreen(true);
-  CefPostDelayedTask(TID_UI, base::Bind(VerifyFullscreen, window),
-                     kStateDelayMS);
 }
 
 void WindowFullscreenImpl(CefRefPtr<CefWaitableEvent> event) {
-  TestWindowDelegate::Config config;
-  config.on_window_created = base::Bind(RunWindowFullscreen);
-  config.close_window = false;
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created = base::BindOnce(RunWindowFullscreen);
+  config->on_window_fullscreen_transition_complete =
+      base::BindRepeating(WindowFullscreenTransitionComplete);
+  config->close_window = false;
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 void WindowFullscreenFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
-  TestWindowDelegate::Config config;
-  config.on_window_created = base::Bind(RunWindowFullscreen);
-  config.frameless = true;
-  config.close_window = false;
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created = base::BindOnce(RunWindowFullscreen);
+  config->on_window_fullscreen_transition_complete =
+      base::BindRepeating(WindowFullscreenTransitionComplete);
+  config->frameless = true;
+  config->close_window = false;
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 void RunWindowIcon(CefRefPtr<CefWindow> window) {
@@ -365,16 +483,16 @@
 }
 
 void WindowIconImpl(CefRefPtr<CefWaitableEvent> event) {
-  TestWindowDelegate::Config config;
-  config.on_window_created = base::Bind(RunWindowIcon);
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created = base::BindOnce(RunWindowIcon);
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 void WindowIconFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
-  TestWindowDelegate::Config config;
-  config.on_window_created = base::Bind(RunWindowIcon);
-  config.frameless = true;
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created = base::BindOnce(RunWindowIcon);
+  config->frameless = true;
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 const int kChar = 'A';
@@ -388,16 +506,18 @@
 }
 
 bool OnKeyEvent(CefRefPtr<CefWindow> window, const CefKeyEvent& event) {
-  if (event.type != KEYEVENT_RAWKEYDOWN)
+  if (event.type != KEYEVENT_RAWKEYDOWN) {
     return false;
+  }
 
   if (event.windows_key_code == VK_MENU) {
     // First we get the ALT key press in all cases.
     EXPECT_FALSE(got_key_event_char);
-    if (got_key_event_alt_count == 0)
+    if (got_key_event_alt_count == 0) {
       EXPECT_FALSE(got_accelerator);
-    else
+    } else {
       EXPECT_TRUE(got_accelerator);
+    }
 
     EXPECT_EQ(EVENTFLAG_ALT_DOWN, static_cast<int>(event.modifiers));
     got_key_event_alt_count++;
@@ -442,10 +562,10 @@
 }
 
 void RunWindowAccelerator(CefRefPtr<CefWindow> window) {
-  window->SetAccelerator(kCloseWindowId, kChar, false, false, true);
+  window->SetAccelerator(kCloseWindowId, kChar, false, false, true, false);
   window->Show();
 
-  CefPostDelayedTask(TID_UI, base::Bind(TriggerAccelerator, window),
+  CefPostDelayedTask(TID_UI, base::BindOnce(TriggerAccelerator, window),
                      kStateDelayMS);
 }
 
@@ -465,13 +585,13 @@
   got_key_event_alt_count = 0;
   got_key_event_char = false;
 
-  TestWindowDelegate::Config config;
-  config.on_window_created = base::Bind(RunWindowAccelerator);
-  config.on_window_destroyed = base::Bind(VerifyWindowAccelerator);
-  config.on_accelerator = base::Bind(OnAccelerator);
-  config.on_key_event = base::Bind(OnKeyEvent);
-  config.close_window = false;
-  TestWindowDelegate::RunTest(event, config);
+  auto config = std::make_unique<TestWindowDelegate::Config>();
+  config->on_window_created = base::BindOnce(RunWindowAccelerator);
+  config->on_window_destroyed = base::BindOnce(VerifyWindowAccelerator);
+  config->on_accelerator = base::BindRepeating(OnAccelerator);
+  config->on_key_event = base::BindRepeating(OnKeyEvent);
+  config->close_window = false;
+  TestWindowDelegate::RunTest(event, std::move(config));
 }
 
 }  // namespace
@@ -481,6 +601,10 @@
 // we presume that Chromium is testing).
 WINDOW_TEST_ASYNC(WindowCreate)
 WINDOW_TEST_ASYNC(WindowCreateFrameless)
+WINDOW_TEST_ASYNC(WindowCreateWithOrigin)
+WINDOW_TEST_ASYNC(WindowCreateMinimized)
+WINDOW_TEST_ASYNC(WindowCreateMaximized)
+WINDOW_TEST_ASYNC(WindowCreateFullscreen)
 WINDOW_TEST_ASYNC(WindowShowHide)
 WINDOW_TEST_ASYNC(WindowShowHideFrameless)
 WINDOW_TEST_ASYNC(WindowLayoutAndCoords)
diff --git a/src/tests/ceftests/waitable_event_unittest.cc b/src/tests/ceftests/waitable_event_unittest.cc
index 4e55655..abda266 100644
--- a/src/tests/ceftests/waitable_event_unittest.cc
+++ b/src/tests/ceftests/waitable_event_unittest.cc
@@ -2,7 +2,7 @@
 // 2012 The Chromium Authors. All rights reserved. Use of this source code is
 // governed by a BSD-style license that can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include "include/base/cef_callback.h"
 #include "include/cef_thread.h"
 #include "include/cef_waitable_event.h"
 #include "include/wrapper/cef_closure_task.h"
@@ -68,7 +68,7 @@
   CefRefPtr<CefThread> thread = CefThread::CreateThread("waitable_event_test");
   thread->GetTaskRunner()->PostDelayedTask(
       CefCreateClosureTask(
-          base::Bind(SignalEvent, base::Unretained(event.get()))),
+          base::BindOnce(SignalEvent, base::Unretained(event.get()))),
       10);
 
   event->Wait();
diff --git a/src/tests/ceftests/webui_unittest.cc b/src/tests/ceftests/webui_unittest.cc
index 7c69d86..c02acf9 100644
--- a/src/tests/ceftests/webui_unittest.cc
+++ b/src/tests/ceftests/webui_unittest.cc
@@ -2,7 +2,10 @@
 // reserved. Use of this source code is governed by a BSD-style license that
 // can be found in the LICENSE file.
 
-#include "include/base/cef_bind.h"
+#include <algorithm>
+#include <memory>
+
+#include "include/base/cef_callback.h"
 #include "include/cef_callback.h"
 #include "include/cef_parser.h"
 #include "include/wrapper/cef_closure_task.h"
@@ -37,18 +40,18 @@
   }
 
   void NextNav() {
-    base::Closure next_action;
+    base::OnceClosure next_action;
 
     if (++url_index_ < url_list_.size()) {
-      next_action =
-          base::Bind(&WebUITestHandler::LoadURL, this, url_list_[url_index_]);
+      next_action = base::BindOnce(&WebUITestHandler::LoadURL, this,
+                                   url_list_[url_index_]);
     } else {
-      next_action = base::Bind(&WebUITestHandler::DestroyTest, this);
+      next_action = base::BindOnce(&WebUITestHandler::DestroyTest, this);
     }
 
     // Wait a bit for the WebUI content to finish loading before performing the
     // next action.
-    CefPostDelayedTask(TID_UI, next_action, 200);
+    CefPostDelayedTask(TID_UI, std::move(next_action), 200);
   }
 
   void LoadURL(const std::string& url) {
@@ -78,10 +81,11 @@
 
   void DestroyTest() override {
     EXPECT_TRUE(got_loading_state_done_);
-    if (expected_error_code_ == ERR_NONE)
+    if (expected_error_code_ == ERR_NONE) {
       EXPECT_FALSE(got_load_error_);
-    else
+    } else {
       EXPECT_TRUE(got_load_error_);
+    }
 
     TestHandler::DestroyTest();
   }
@@ -90,8 +94,9 @@
   void NextNavIfDone(const std::string& url) {
     bool done = false;
     if (expected_error_code_ == ERR_NONE) {
-      if (got_loading_state_done_)
+      if (got_loading_state_done_) {
         done = true;
+      }
     } else if (got_load_error_ && got_loading_state_done_) {
       done = true;
     }
@@ -99,8 +104,9 @@
     if (done) {
       // Verify that we navigated to the expected URL.
       std::string expected_url = expected_url_;
-      if (expected_url.empty() && url_index_ < url_list_.size())
+      if (expected_url.empty() && url_index_ < url_list_.size()) {
         expected_url = url_list_[url_index_];
+      }
       EXPECT_STREQ(expected_url.c_str(), url.c_str());
 
       NextNav();
@@ -169,7 +175,6 @@
     RunWebUITest("chrome://" + name_str + "/");               \
   }
 
-WEBUI_TEST(appcache_internals)
 WEBUI_TEST(accessibility)
 WEBUI_TEST(blob_internals)
 WEBUI_TEST(extensions_support)
diff --git a/src/tests/gtest/CMakeLists.txt.in b/src/tests/gtest/CMakeLists.txt.in
index 32fcc87..84fbf4d 100644
--- a/src/tests/gtest/CMakeLists.txt.in
+++ b/src/tests/gtest/CMakeLists.txt.in
@@ -6,6 +6,10 @@
 
 set(GTEST_SRCS
   src/gtest-all.cc
+  teamcity/include/teamcity_gtest.h
+  teamcity/src/teamcity_gtest.cpp
+  teamcity/src/teamcity_messages.cpp
+  teamcity/src/teamcity_messages.h
   )
 source_group(cef_gtest FILES ${GTEST_SRCS})
 
diff --git a/src/tests/gtest/teamcity/README.cef b/src/tests/gtest/teamcity/README.cef
new file mode 100644
index 0000000..d86ec37
--- /dev/null
+++ b/src/tests/gtest/teamcity/README.cef
@@ -0,0 +1,14 @@
+Name: TeamCity C++ Unit Test Reporting 
+Short Name: teamcity-cpp
+URL: https://github.com/JetBrains/teamcity-cpp
+Version: 1.8 (commit b2c95c5)
+License: Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+
+Description:
+GTest integration for reporting to TeamCity Continuous Integration Server.
+
+See the project URL for related documentation.
+
+Local Modifications:
+1. Copy necessary C++ files only.
+1. Use absolute include paths.
diff --git a/src/tests/gtest/teamcity/include/teamcity_gtest.h b/src/tests/gtest/teamcity/include/teamcity_gtest.h
new file mode 100644
index 0000000..236f6f9
--- /dev/null
+++ b/src/tests/gtest/teamcity/include/teamcity_gtest.h
@@ -0,0 +1,55 @@
+/* Copyright 2015 Paul Shmakov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef H_TEAMCITY_GTEST
+#define H_TEAMCITY_GTEST
+
+#include <string>
+
+#include "tests/gtest/include/gtest/gtest.h"
+#include "tests/gtest/teamcity/src/teamcity_messages.h"
+
+namespace jetbrains {
+namespace teamcity {
+
+class TeamcityGoogleTestEventListener
+    : public ::testing::EmptyTestEventListener {
+ public:
+  TeamcityGoogleTestEventListener(const std::string& flowid);
+  TeamcityGoogleTestEventListener();
+
+  // Fired before the test case starts.
+  virtual void OnTestCaseStart(const ::testing::TestCase& test_case);
+  // Fired before the test starts.
+  virtual void OnTestStart(const ::testing::TestInfo& test_info);
+  // Fired after the test ends.
+  virtual void OnTestEnd(const ::testing::TestInfo& test_info);
+  // Fired after the test case ends.
+  virtual void OnTestCaseEnd(const ::testing::TestCase& test_case);
+
+ private:
+  TeamcityMessages messages;
+  std::string flowid;
+
+  // Prevent copying.
+  TeamcityGoogleTestEventListener(const TeamcityGoogleTestEventListener&);
+  void operator=(const TeamcityGoogleTestEventListener&);
+};
+
+}  // namespace teamcity
+}  // namespace jetbrains
+
+#endif /* H_TEAMCITY_GTEST */
diff --git a/src/tests/gtest/teamcity/src/teamcity_gtest.cpp b/src/tests/gtest/teamcity/src/teamcity_gtest.cpp
new file mode 100644
index 0000000..fb4dc67
--- /dev/null
+++ b/src/tests/gtest/teamcity/src/teamcity_gtest.cpp
@@ -0,0 +1,85 @@
+/* Copyright 2015 Paul Shmakov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "tests/gtest/teamcity/include/teamcity_gtest.h"
+
+namespace jetbrains {
+namespace teamcity {
+
+using namespace testing;
+
+TeamcityGoogleTestEventListener::TeamcityGoogleTestEventListener() {
+  flowid = getFlowIdFromEnvironment();
+}
+
+TeamcityGoogleTestEventListener::TeamcityGoogleTestEventListener(
+    const std::string& flowid_)
+    : flowid(flowid_) {}
+
+// Fired before the test case starts.
+void TeamcityGoogleTestEventListener::OnTestCaseStart(
+    const TestCase& test_case) {
+  messages.suiteStarted(test_case.name(), flowid);
+}
+
+// Fired before the test starts.
+void TeamcityGoogleTestEventListener::OnTestStart(const TestInfo& test_info) {
+  messages.testStarted(test_info.name(), flowid);
+}
+
+// Fired after the test ends.
+void TeamcityGoogleTestEventListener::OnTestEnd(const TestInfo& test_info) {
+  const TestResult* result = test_info.result();
+  if (result->Failed()) {
+    std::string message;
+    std::string details;
+    for (int i = 0; i < result->total_part_count(); ++i) {
+      const TestPartResult& partResult = result->GetTestPartResult(i);
+      if (partResult.passed()) {
+        continue;
+      }
+
+      if (message.empty()) {
+        message = partResult.summary();
+      }
+
+      if (!details.empty()) {
+        details.append("\n");
+      }
+      details.append(partResult.message());
+
+      if (partResult.file_name() && partResult.line_number() >= 0) {
+        std::stringstream ss;
+        ss << "\n at " << partResult.file_name() << ":"
+           << partResult.line_number();
+        details.append(ss.str());
+      }
+    }
+
+    messages.testFailed(test_info.name(), !message.empty() ? message : "failed",
+                        details, flowid);
+  }
+  messages.testFinished(test_info.name(),
+                        static_cast<int>(result->elapsed_time()), flowid);
+}
+
+// Fired after the test case ends.
+void TeamcityGoogleTestEventListener::OnTestCaseEnd(const TestCase& test_case) {
+  messages.suiteFinished(test_case.name(), flowid);
+}
+
+}  // namespace teamcity
+}  // namespace jetbrains
diff --git a/src/tests/gtest/teamcity/src/teamcity_messages.cpp b/src/tests/gtest/teamcity/src/teamcity_messages.cpp
new file mode 100644
index 0000000..284f8b4
--- /dev/null
+++ b/src/tests/gtest/teamcity/src/teamcity_messages.cpp
@@ -0,0 +1,215 @@
+/* Copyright 2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Revision: 88625 $
+ */
+
+#include "tests/gtest/teamcity/src/teamcity_messages.h"
+
+#include <cstdlib>
+#include <sstream>
+
+namespace jetbrains {
+namespace teamcity {
+
+std::string getFlowIdFromEnvironment() {
+#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && \
+    !defined(__CYGWIN__) && !defined(__MINGW32__)
+  char* flowId = NULL;
+  size_t sz = 0;
+  std::string result;
+  if (!_dupenv_s(&flowId, &sz, "TEAMCITY_PROCESS_FLOW_ID")) {
+    result = flowId != NULL ? flowId : "";
+    free(flowId);
+  }
+
+  return result;
+#else
+  const char* flowId = getenv("TEAMCITY_PROCESS_FLOW_ID");
+  return flowId == NULL ? "" : flowId;
+#endif
+}
+
+bool underTeamcity() {
+#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && \
+    !defined(__CYGWIN__) && !defined(__MINGW32__)
+  char* teamCityProjectName = 0;
+  size_t sz = 0;
+  bool result = false;
+  if (!_dupenv_s(&teamCityProjectName, &sz, "TEAMCITY_PROJECT_NAME")) {
+    result = teamCityProjectName != NULL;
+    free(teamCityProjectName);
+  }
+
+  return result;
+#else
+  return getenv("TEAMCITY_PROJECT_NAME") != NULL;
+#endif
+}
+
+TeamcityMessages::TeamcityMessages() : m_out(&std::cout) {}
+
+void TeamcityMessages::setOutput(std::ostream& out) {
+  m_out = &out;
+}
+
+std::string TeamcityMessages::escape(const std::string& s) {
+  std::string result;
+  result.reserve(s.length());
+
+  for (size_t i = 0; i < s.length(); i++) {
+    char c = s[i];
+
+    switch (c) {
+      case '\n':
+        result.append("|n");
+        break;
+      case '\r':
+        result.append("|r");
+        break;
+      case '\'':
+        result.append("|'");
+        break;
+      case '|':
+        result.append("||");
+        break;
+      case ']':
+        result.append("|]");
+        break;
+      default:
+        result.append(&c, 1);
+    }
+  }
+
+  return result;
+}
+
+void TeamcityMessages::openMsg(const std::string& name) {
+  // endl for http://jetbrains.net/tracker/issue/TW-4412
+  *m_out << std::endl << "##teamcity[" << name;
+}
+
+void TeamcityMessages::closeMsg() {
+  *m_out << "]";
+  // endl for http://jetbrains.net/tracker/issue/TW-4412
+  *m_out << std::endl;
+}
+
+void TeamcityMessages::writeProperty(const std::string& name,
+                                     const std::string& value) {
+  *m_out << " " << name << "='" << escape(value) << "'";
+}
+
+void TeamcityMessages::suiteStarted(const std::string& name,
+                                    const std::string& flowid) {
+  openMsg("testSuiteStarted");
+  writeProperty("name", name);
+  if (flowid.length() > 0) {
+    writeProperty("flowId", flowid);
+  }
+
+  closeMsg();
+}
+
+void TeamcityMessages::suiteFinished(const std::string& name,
+                                     const std::string& flowid) {
+  openMsg("testSuiteFinished");
+  writeProperty("name", name);
+  if (flowid.length() > 0) {
+    writeProperty("flowId", flowid);
+  }
+
+  closeMsg();
+}
+
+void TeamcityMessages::testStarted(const std::string& name,
+                                   const std::string& flowid,
+                                   bool captureStandardOutput) {
+  openMsg("testStarted");
+  writeProperty("name", name);
+  if (flowid.length() > 0) {
+    writeProperty("flowId", flowid);
+  }
+
+  if (captureStandardOutput) {
+    writeProperty("captureStandardOutput", "true");  // false by default
+  }
+
+  closeMsg();
+}
+
+void TeamcityMessages::testFinished(const std::string& name,
+                                    int durationMs,
+                                    const std::string& flowid) {
+  openMsg("testFinished");
+
+  writeProperty("name", name);
+
+  if (flowid.length() > 0) {
+    writeProperty("flowId", flowid);
+  }
+
+  if (durationMs >= 0) {
+    std::stringstream out(std::ios_base::out);
+    out << durationMs;
+    writeProperty("duration", out.str());
+  }
+
+  closeMsg();
+}
+
+void TeamcityMessages::testFailed(const std::string& name,
+                                  const std::string& message,
+                                  const std::string& details,
+                                  const std::string& flowid) {
+  openMsg("testFailed");
+  writeProperty("name", name);
+  writeProperty("message", message);
+  writeProperty("details", details);
+  if (flowid.length() > 0) {
+    writeProperty("flowId", flowid);
+  }
+
+  closeMsg();
+}
+
+void TeamcityMessages::testIgnored(const std::string& name,
+                                   const std::string& message,
+                                   const std::string& flowid) {
+  openMsg("testIgnored");
+  writeProperty("name", name);
+  writeProperty("message", message);
+  if (flowid.length() > 0) {
+    writeProperty("flowId", flowid);
+  }
+
+  closeMsg();
+}
+
+void TeamcityMessages::testOutput(const std::string& name,
+                                  const std::string& output,
+                                  const std::string& flowid,
+                                  bool isStdError) {
+  openMsg(isStdError ? "testStdErr" : "testStdOut");
+  writeProperty("name", name);
+  writeProperty("out", output);
+  if (flowid.length() > 0) {
+    writeProperty("flowId", flowid);
+  }
+
+  closeMsg();
+}
+
+}  // namespace teamcity
+}  // namespace jetbrains
diff --git a/src/tests/gtest/teamcity/src/teamcity_messages.h b/src/tests/gtest/teamcity/src/teamcity_messages.h
new file mode 100644
index 0000000..409cb83
--- /dev/null
+++ b/src/tests/gtest/teamcity/src/teamcity_messages.h
@@ -0,0 +1,75 @@
+/* Copyright 2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Revision: 88625 $
+ */
+
+#ifndef H_TEAMCITY_MESSAGES
+#define H_TEAMCITY_MESSAGES
+
+#include <iostream>
+#include <string>
+
+namespace jetbrains {
+namespace teamcity {
+
+std::string getFlowIdFromEnvironment();
+bool underTeamcity();
+
+class TeamcityMessages {
+  std::ostream* m_out;
+
+ protected:
+  std::string escape(const std::string& s);
+
+  void openMsg(const std::string& name);
+  void writeProperty(const std::string& name, const std::string& value);
+  void closeMsg();
+
+ public:
+  static const bool StdErr = true;
+  static const bool StdOut = false;
+
+  TeamcityMessages();
+
+  void setOutput(std::ostream&);
+
+  void suiteStarted(const std::string& name,
+                    const std::string& flowid = std::string());
+  void suiteFinished(const std::string& name,
+                     const std::string& flowid = std::string());
+
+  void testStarted(const std::string& name,
+                   const std::string& flowid = std::string(),
+                   bool captureStandardOutput = false);
+  void testFailed(const std::string& name,
+                  const std::string& message,
+                  const std::string& details,
+                  const std::string& flowid = std::string());
+  void testIgnored(const std::string& name,
+                   const std::string& message,
+                   const std::string& flowid = std::string());
+  void testOutput(const std::string& name,
+                  const std::string& output,
+                  const std::string& flowid,
+                  bool isStdErr = StdOut);
+  void testFinished(const std::string& name,
+                    int durationMs = -1,
+                    const std::string& flowid = std::string());
+};
+
+}  // namespace teamcity
+}  // namespace jetbrains
+
+#endif /* H_TEAMCITY_MESSAGES */
diff --git a/src/tests/shared/browser/client_app_browser.cc b/src/tests/shared/browser/client_app_browser.cc
index adf2fff..f37f3d9 100644
--- a/src/tests/shared/browser/client_app_browser.cc
+++ b/src/tests/shared/browser/client_app_browser.cc
@@ -15,6 +15,33 @@
   CreateDelegates(delegates_);
 }
 
+// static
+void ClientAppBrowser::PopulateSettings(CefRefPtr<CefCommandLine> command_line,
+                                        CefSettings& settings) {
+#if (defined(OS_WIN) || defined(OS_LINUX))
+  settings.multi_threaded_message_loop =
+      command_line->HasSwitch(client::switches::kMultiThreadedMessageLoop);
+#endif
+
+  if (!settings.multi_threaded_message_loop) {
+    settings.external_message_pump =
+        command_line->HasSwitch(client::switches::kExternalMessagePump);
+  }
+
+  std::vector<std::string> cookieable_schemes;
+  RegisterCookieableSchemes(cookieable_schemes);
+  if (!cookieable_schemes.empty()) {
+    std::string list_str;
+    for (const auto& scheme : cookieable_schemes) {
+      if (!list_str.empty()) {
+        list_str += ",";
+      }
+      list_str += scheme;
+    }
+    CefString(&settings.cookieable_schemes_list) = list_str;
+  }
+}
+
 void ClientAppBrowser::OnBeforeCommandLineProcessing(
     const CefString& process_type,
     CefRefPtr<CefCommandLine> command_line) {
@@ -26,7 +53,7 @@
       // Use software rendering and compositing (disable GPU) for increased FPS
       // and decreased CPU usage. This will also disable WebGL so remove these
       // switches if you need that capability.
-      // See https://bitbucket.org/chromiumembedded/cef/issues/1257 for details.
+      // See https://github.com/chromiumembedded/cef/issues/1257 for details.
       if (!command_line->HasSwitch(switches::kEnableGPU)) {
         command_line->AppendSwitch("disable-gpu");
         command_line->AppendSwitch("disable-gpu-compositing");
@@ -41,59 +68,55 @@
       command_line->AppendSwitchWithValue("top-chrome-md", "non-material");
     }
 
-    if (!command_line->HasSwitch(switches::kCachePath) &&
-        !command_line->HasSwitch("disable-gpu-shader-disk-cache")) {
-      // Don't create a "GPUCache" directory when cache-path is unspecified.
-      command_line->AppendSwitch("disable-gpu-shader-disk-cache");
-    }
-
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
     // Disable the toolchain prompt on macOS.
     command_line->AppendSwitch("use-mock-keychain");
 #endif
 
     DelegateSet::iterator it = delegates_.begin();
-    for (; it != delegates_.end(); ++it)
+    for (; it != delegates_.end(); ++it) {
       (*it)->OnBeforeCommandLineProcessing(this, command_line);
+    }
+  }
+}
+
+void ClientAppBrowser::OnRegisterCustomPreferences(
+    cef_preferences_type_t type,
+    CefRawPtr<CefPreferenceRegistrar> registrar) {
+  for (auto& delegate : delegates_) {
+    delegate->OnRegisterCustomPreferences(this, type, registrar);
   }
 }
 
 void ClientAppBrowser::OnContextInitialized() {
-  if (!cookieable_schemes_.empty()) {
-    // Register cookieable schemes with the global cookie manager.
-    CefRefPtr<CefCookieManager> manager =
-        CefCookieManager::GetGlobalManager(nullptr);
-    DCHECK(manager.get());
-    manager->SetSupportedSchemes(cookieable_schemes_, true, nullptr);
+  for (auto& delegate : delegates_) {
+    delegate->OnContextInitialized(this);
   }
-
-  print_handler_ = CreatePrintHandler();
-
-  DelegateSet::iterator it = delegates_.begin();
-  for (; it != delegates_.end(); ++it)
-    (*it)->OnContextInitialized(this);
 }
 
 void ClientAppBrowser::OnBeforeChildProcessLaunch(
     CefRefPtr<CefCommandLine> command_line) {
-  DelegateSet::iterator it = delegates_.begin();
-  for (; it != delegates_.end(); ++it)
-    (*it)->OnBeforeChildProcessLaunch(this, command_line);
+  for (auto& delegate : delegates_) {
+    delegate->OnBeforeChildProcessLaunch(this, command_line);
+  }
 }
 
-void ClientAppBrowser::OnRenderProcessThreadCreated(
-    CefRefPtr<CefListValue> extra_info) {
-  DelegateSet::iterator it = delegates_.begin();
-  for (; it != delegates_.end(); ++it)
-    (*it)->OnRenderProcessThreadCreated(this, extra_info);
-}
-
-void ClientAppBrowser::OnScheduleMessagePumpWork(int64 delay) {
+void ClientAppBrowser::OnScheduleMessagePumpWork(int64_t delay) {
   // Only used when `--external-message-pump` is passed via the command-line.
   MainMessageLoopExternalPump* message_pump =
       MainMessageLoopExternalPump::Get();
-  if (message_pump)
+  if (message_pump) {
     message_pump->OnScheduleMessagePumpWork(delay);
+  }
+}
+
+CefRefPtr<CefClient> ClientAppBrowser::GetDefaultClient() {
+  for (auto& delegate : delegates_) {
+    if (auto client = delegate->GetDefaultClient(this)) {
+      return client;
+    }
+  }
+  return nullptr;
 }
 
 }  // namespace client
diff --git a/src/tests/shared/browser/client_app_browser.h b/src/tests/shared/browser/client_app_browser.h
index 1f25994..469d18b 100644
--- a/src/tests/shared/browser/client_app_browser.h
+++ b/src/tests/shared/browser/client_app_browser.h
@@ -24,54 +24,63 @@
         CefRefPtr<ClientAppBrowser> app,
         CefRefPtr<CefCommandLine> command_line) {}
 
+    virtual void OnRegisterCustomPreferences(
+        CefRefPtr<ClientAppBrowser> app,
+        cef_preferences_type_t type,
+        CefRawPtr<CefPreferenceRegistrar> registrar) {}
+
     virtual void OnContextInitialized(CefRefPtr<ClientAppBrowser> app) {}
 
     virtual void OnBeforeChildProcessLaunch(
         CefRefPtr<ClientAppBrowser> app,
         CefRefPtr<CefCommandLine> command_line) {}
 
-    virtual void OnRenderProcessThreadCreated(
-        CefRefPtr<ClientAppBrowser> app,
-        CefRefPtr<CefListValue> extra_info) {}
+    virtual CefRefPtr<CefClient> GetDefaultClient(
+        CefRefPtr<ClientAppBrowser> app) {
+      return nullptr;
+    }
   };
 
   typedef std::set<CefRefPtr<Delegate>> DelegateSet;
 
   ClientAppBrowser();
 
+  // Called to populate |settings| based on |command_line| and other global
+  // state.
+  static void PopulateSettings(CefRefPtr<CefCommandLine> command_line,
+                               CefSettings& settings);
+
  private:
+  // Registers cookieable schemes. Implemented by cefclient in
+  // client_app_delegates_browser.cc
+  static void RegisterCookieableSchemes(
+      std::vector<std::string>& cookieable_schemes);
+
   // Creates all of the Delegate objects. Implemented by cefclient in
   // client_app_delegates_browser.cc
   static void CreateDelegates(DelegateSet& delegates);
 
-  // Create the Linux print handler. Implemented by cefclient in
-  // client_app_delegates_browser.cc
-  static CefRefPtr<CefPrintHandler> CreatePrintHandler();
-
   // CefApp methods.
   void OnBeforeCommandLineProcessing(
       const CefString& process_type,
-      CefRefPtr<CefCommandLine> command_line) OVERRIDE;
-  CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() OVERRIDE {
+      CefRefPtr<CefCommandLine> command_line) override;
+  CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() override {
     return this;
   }
 
   // CefBrowserProcessHandler methods.
-  void OnContextInitialized() OVERRIDE;
+  void OnRegisterCustomPreferences(
+      cef_preferences_type_t type,
+      CefRawPtr<CefPreferenceRegistrar> registrar) override;
+  void OnContextInitialized() override;
   void OnBeforeChildProcessLaunch(
-      CefRefPtr<CefCommandLine> command_line) OVERRIDE;
-  void OnRenderProcessThreadCreated(
-      CefRefPtr<CefListValue> extra_info) OVERRIDE;
-  CefRefPtr<CefPrintHandler> GetPrintHandler() OVERRIDE {
-    return print_handler_;
-  }
-  void OnScheduleMessagePumpWork(int64 delay) OVERRIDE;
+      CefRefPtr<CefCommandLine> command_line) override;
+  void OnScheduleMessagePumpWork(int64_t delay) override;
+  CefRefPtr<CefClient> GetDefaultClient() override;
 
   // Set of supported Delegates.
   DelegateSet delegates_;
 
-  CefRefPtr<CefPrintHandler> print_handler_;
-
   IMPLEMENT_REFCOUNTING(ClientAppBrowser);
   DISALLOW_COPY_AND_ASSIGN(ClientAppBrowser);
 };
diff --git a/src/tests/shared/browser/extension_util.cc b/src/tests/shared/browser/extension_util.cc
index 5d2e535..088316e 100644
--- a/src/tests/shared/browser/extension_util.cc
+++ b/src/tests/shared/browser/extension_util.cc
@@ -4,12 +4,16 @@
 
 #include "tests/shared/browser/extension_util.h"
 
-#include "include/base/cef_bind.h"
+#include <algorithm>
+#include <memory>
+
+#include "include/base/cef_callback.h"
 #include "include/cef_parser.h"
 #include "include/cef_path_util.h"
 #include "include/wrapper/cef_closure_task.h"
 #include "tests/shared/browser/file_util.h"
 #include "tests/shared/browser/resource_util.h"
+#include "tests/shared/common/string_util.h"
 
 namespace client {
 namespace extension_util {
@@ -32,10 +36,8 @@
 
 #if defined(OS_WIN)
   // Convert to lower-case, since Windows paths are case-insensitive.
-  std::transform(resources_path_lower.begin(), resources_path_lower.end(),
-                 resources_path_lower.begin(), ::tolower);
-  std::transform(extension_path_lower.begin(), extension_path_lower.end(),
-                 extension_path_lower.begin(), ::tolower);
+  resources_path_lower = AsciiStrToLower(resources_path_lower);
+  extension_path_lower = AsciiStrToLower(extension_path_lower);
 #endif
 
   std::string internal_path;
@@ -54,26 +56,27 @@
   return internal_path;
 }
 
-typedef base::Callback<void(CefRefPtr<CefDictionaryValue> /*manifest*/)>
-    ManifestCallback;
+using ManifestCallback =
+    base::OnceCallback<void(CefRefPtr<CefDictionaryValue> /*manifest*/)>;
 
-void RunManifestCallback(const ManifestCallback& callback,
+void RunManifestCallback(ManifestCallback callback,
                          CefRefPtr<CefDictionaryValue> manifest) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute on the browser UI thread.
-    CefPostTask(TID_UI, base::Bind(RunManifestCallback, callback, manifest));
+    CefPostTask(TID_UI, base::BindOnce(std::move(callback), manifest));
     return;
   }
-  callback.Run(manifest);
+  std::move(callback).Run(manifest);
 }
 
 // Asynchronously reads the manifest and executes |callback| on the UI thread.
 void GetInternalManifest(const std::string& extension_path,
-                         const ManifestCallback& callback) {
-  if (!CefCurrentlyOn(TID_FILE)) {
+                         ManifestCallback callback) {
+  if (!CefCurrentlyOn(TID_FILE_USER_BLOCKING)) {
     // Execute on the browser FILE thread.
-    CefPostTask(TID_FILE,
-                base::Bind(GetInternalManifest, extension_path, callback));
+    CefPostTask(TID_FILE_USER_BLOCKING,
+                base::BindOnce(GetInternalManifest, extension_path,
+                               std::move(callback)));
     return;
   }
 
@@ -83,24 +86,24 @@
   if (!LoadBinaryResource(manifest_path.c_str(), manifest_contents) ||
       manifest_contents.empty()) {
     LOG(ERROR) << "Failed to load manifest from " << manifest_path;
-    RunManifestCallback(callback, nullptr);
+    RunManifestCallback(std::move(callback), nullptr);
     return;
   }
 
-  cef_json_parser_error_t error_code;
   CefString error_msg;
-  CefRefPtr<CefValue> value = CefParseJSONAndReturnError(
-      manifest_contents, JSON_PARSER_RFC, error_code, error_msg);
+  CefRefPtr<CefValue> value =
+      CefParseJSONAndReturnError(manifest_contents, JSON_PARSER_RFC, error_msg);
   if (!value || value->GetType() != VTYPE_DICTIONARY) {
-    if (error_msg.empty())
+    if (error_msg.empty()) {
       error_msg = "Incorrectly formatted dictionary contents.";
+    }
     LOG(ERROR) << "Failed to parse manifest from " << manifest_path << "; "
                << error_msg.ToString();
-    RunManifestCallback(callback, nullptr);
+    RunManifestCallback(std::move(callback), nullptr);
     return;
   }
 
-  RunManifestCallback(callback, value->GetDictionary());
+  RunManifestCallback(std::move(callback), value->GetDictionary());
 }
 
 void LoadExtensionWithManifest(CefRefPtr<CefRequestContext> request_context,
@@ -121,7 +124,7 @@
   static const char* extensions[] = {"set_page_color"};
 
   const std::string& internal_path = GetInternalPath(extension_path);
-  for (size_t i = 0; i < arraysize(extensions); ++i) {
+  for (size_t i = 0; i < std::size(extensions); ++i) {
     // Exact match or first directory component.
     const std::string& extension = extensions[i];
     if (internal_path == extension ||
@@ -141,16 +144,18 @@
 std::string GetExtensionResourcePath(const std::string& extension_path,
                                      bool* internal) {
   const bool is_internal = IsInternalExtension(extension_path);
-  if (internal)
+  if (internal) {
     *internal = is_internal;
-  if (is_internal)
+  }
+  if (is_internal) {
     return GetInternalExtensionResourcePath(extension_path);
+  }
   return extension_path;
 }
 
 bool GetExtensionResourceContents(const std::string& extension_path,
                                   std::string& contents) {
-  CEF_REQUIRE_FILE_THREAD();
+  CEF_REQUIRE_FILE_USER_BLOCKING_THREAD();
 
   if (IsInternalExtension(extension_path)) {
     const std::string& contents_path =
@@ -166,16 +171,17 @@
                    CefRefPtr<CefExtensionHandler> handler) {
   if (!CefCurrentlyOn(TID_UI)) {
     // Execute on the browser UI thread.
-    CefPostTask(TID_UI, base::Bind(LoadExtension, request_context,
-                                   extension_path, handler));
+    CefPostTask(TID_UI, base::BindOnce(LoadExtension, request_context,
+                                       extension_path, handler));
     return;
   }
 
   if (IsInternalExtension(extension_path)) {
     // Read the extension manifest and load asynchronously.
-    GetInternalManifest(extension_path,
-                        base::Bind(LoadExtensionWithManifest, request_context,
-                                   extension_path, handler));
+    GetInternalManifest(
+        extension_path,
+        base::BindOnce(LoadExtensionWithManifest, request_context,
+                       extension_path, handler));
   } else {
     // Load the extension from disk.
     request_context->LoadExtension(extension_path, nullptr, handler);
@@ -189,8 +195,8 @@
 
   if (!CefCurrentlyOn(TID_IO)) {
     // Execute on the browser IO thread.
-    CefPostTask(TID_IO, base::Bind(AddInternalExtensionToResourceManager,
-                                   extension, resource_manager));
+    CefPostTask(TID_IO, base::BindOnce(AddInternalExtensionToResourceManager,
+                                       extension, resource_manager));
     return;
   }
 
@@ -224,8 +230,9 @@
   if (browser_action) {
     const std::string& default_popup =
         browser_action->GetString("default_popup");
-    if (!default_popup.empty())
+    if (!default_popup.empty()) {
       return GetExtensionOrigin(extension->GetIdentifier()) + default_popup;
+    }
   }
 
   return std::string();
diff --git a/src/tests/shared/browser/extension_util.h b/src/tests/shared/browser/extension_util.h
index f3e643a..10b3511 100644
--- a/src/tests/shared/browser/extension_util.h
+++ b/src/tests/shared/browser/extension_util.h
@@ -33,8 +33,8 @@
 // will be the full file path on disk. For internal extensions this will be the
 // relative path expected by LoadBinaryResource (uses '/' as path separator on
 // all platforms). Internal extensions must be on the hard-coded list enforced
-// by IsInternalExtension. If |internal| is non-NULL it will be set to true if
-// the extension is handled internally.
+// by IsInternalExtension. If |internal| is non-nullptr it will be set to true
+// if the extension is handled internally.
 std::string GetExtensionResourcePath(const std::string& extension_path,
                                      bool* internal);
 
@@ -69,7 +69,7 @@
 std::string GetExtensionURL(CefRefPtr<CefExtension> extension);
 
 // Look for a browser_action.default_icon manifest value and return the resource
-// path. If |internal| is non-NULL it will be set to true if the extension is
+// path. If |internal| is non-nullptr it will be set to true if the extension is
 // handled internally.
 std::string GetExtensionIconPath(CefRefPtr<CefExtension> extension,
                                  bool* internal);
diff --git a/src/tests/shared/browser/file_util.cc b/src/tests/shared/browser/file_util.cc
index 73c4159..d1ccaac 100644
--- a/src/tests/shared/browser/file_util.cc
+++ b/src/tests/shared/browser/file_util.cc
@@ -4,14 +4,13 @@
 
 #include "tests/shared/browser/file_util.h"
 
-#include "include/base/cef_build.h"
-#include "include/base/cef_scoped_ptr.h"
-#include "include/cef_task.h"
-
 #include <algorithm>
 #include <cstdio>
 #include <memory>
 
+#include "include/base/cef_build.h"
+#include "include/cef_task.h"
+
 namespace client {
 namespace file_util {
 
@@ -36,17 +35,20 @@
 bool ReadFileToString(const std::string& path,
                       std::string* contents,
                       size_t max_size) {
-  if (!AllowFileIO())
+  if (!AllowFileIO()) {
     return false;
+  }
 
-  if (contents)
+  if (contents) {
     contents->clear();
+  }
   FILE* file = fopen(path.c_str(), "rb");
-  if (!file)
+  if (!file) {
     return false;
+  }
 
   const size_t kBufferSize = 1 << 16;
-  scoped_ptr<char[]> buf(new char[kBufferSize]);
+  std::unique_ptr<char[]> buf(new char[kBufferSize]);
   size_t len;
   size_t size = 0;
   bool read_status = true;
@@ -54,8 +56,9 @@
   // Many files supplied in |path| have incorrect size (proc files etc).
   // Hence, the file is read sequentially as opposed to a one-shot read.
   while ((len = fread(buf.get(), 1, kBufferSize, file)) > 0) {
-    if (contents)
+    if (contents) {
       contents->append(buf.get(), std::min(len, max_size - size));
+    }
 
     if ((max_size - size) < len) {
       read_status = false;
@@ -71,19 +74,22 @@
 }
 
 int WriteFile(const std::string& path, const char* data, int size) {
-  if (!AllowFileIO())
+  if (!AllowFileIO()) {
     return -1;
+  }
 
   FILE* file = fopen(path.c_str(), "wb");
-  if (!file)
+  if (!file) {
     return -1;
+  }
 
   int written = 0;
 
   do {
     size_t write = fwrite(data + written, 1, size - written, file);
-    if (write == 0)
+    if (write == 0) {
       break;
+    }
     written += static_cast<int>(write);
   } while (written < size);
 
@@ -93,27 +99,33 @@
 }
 
 std::string JoinPath(const std::string& path1, const std::string& path2) {
-  if (path1.empty() && path2.empty())
+  if (path1.empty() && path2.empty()) {
     return std::string();
-  if (path1.empty())
+  }
+  if (path1.empty()) {
     return path2;
-  if (path2.empty())
+  }
+  if (path2.empty()) {
     return path1;
+  }
 
   std::string result = path1;
-  if (result[result.size() - 1] != kPathSep)
+  if (result[result.size() - 1] != kPathSep) {
     result += kPathSep;
-  if (path2[0] == kPathSep)
+  }
+  if (path2[0] == kPathSep) {
     result += path2.substr(1);
-  else
+  } else {
     result += path2;
+  }
   return result;
 }
 
 std::string GetFileExtension(const std::string& path) {
   size_t sep = path.find_last_of(".");
-  if (sep != std::string::npos)
+  if (sep != std::string::npos) {
     return path.substr(sep + 1);
+  }
   return std::string();
 }
 
diff --git a/src/tests/shared/browser/file_util.h b/src/tests/shared/browser/file_util.h
index cc484b7..b08d7dc 100644
--- a/src/tests/shared/browser/file_util.h
+++ b/src/tests/shared/browser/file_util.h
@@ -19,10 +19,10 @@
 // false on error.  In case of I/O error, |contents| holds the data that could
 // be read from the file before the error occurred.  When the file size exceeds
 // max_size|, the function returns false with |contents| holding the file
-// truncated to |max_size|. |contents| may be NULL, in which case this function
-// is useful for its side effect of priming the disk cache (could be used for
-// unit tests). Calling this function on the browser process UI or IO threads is
-// not allowed.
+// truncated to |max_size|. |contents| may be nullptr, in which case this
+// function is useful for its side effect of priming the disk cache (could be
+// used for unit tests). Calling this function on the browser process UI or IO
+// threads is not allowed.
 bool ReadFileToString(const std::string& path,
                       std::string* contents,
                       size_t max_size = std::numeric_limits<size_t>::max());
diff --git a/src/tests/shared/browser/geometry_util.cc b/src/tests/shared/browser/geometry_util.cc
index 206edbc..60962b2 100644
--- a/src/tests/shared/browser/geometry_util.cc
+++ b/src/tests/shared/browser/geometry_util.cc
@@ -25,9 +25,21 @@
   return static_cast<int>(std::floor(scaled_val));
 }
 
+CefRect DeviceToLogical(const CefRect& value, float device_scale_factor) {
+  return CefRect(DeviceToLogical(value.x, device_scale_factor),
+                 DeviceToLogical(value.y, device_scale_factor),
+                 DeviceToLogical(value.width, device_scale_factor),
+                 DeviceToLogical(value.height, device_scale_factor));
+}
+
 void DeviceToLogical(CefMouseEvent& value, float device_scale_factor) {
   value.x = DeviceToLogical(value.x, device_scale_factor);
   value.y = DeviceToLogical(value.y, device_scale_factor);
 }
 
+void DeviceToLogical(CefTouchEvent& value, float device_scale_factor) {
+  value.x = DeviceToLogical(value.x, device_scale_factor);
+  value.y = DeviceToLogical(value.y, device_scale_factor);
+}
+
 }  // namespace client
diff --git a/src/tests/shared/browser/geometry_util.h b/src/tests/shared/browser/geometry_util.h
index 1f1e188..1853aa0 100644
--- a/src/tests/shared/browser/geometry_util.h
+++ b/src/tests/shared/browser/geometry_util.h
@@ -16,7 +16,9 @@
 
 // Convert |value| from device coordinates to logical coordinates.
 int DeviceToLogical(int value, float device_scale_factor);
+CefRect DeviceToLogical(const CefRect& value, float device_scale_factor);
 void DeviceToLogical(CefMouseEvent& value, float device_scale_factor);
+void DeviceToLogical(CefTouchEvent& value, float device_scale_factor);
 
 }  // namespace client
 
diff --git a/src/tests/shared/browser/main_message_loop.cc b/src/tests/shared/browser/main_message_loop.cc
index 481e2b4..23446e0 100644
--- a/src/tests/shared/browser/main_message_loop.cc
+++ b/src/tests/shared/browser/main_message_loop.cc
@@ -30,7 +30,11 @@
   return g_main_message_loop;
 }
 
-void MainMessageLoop::PostClosure(const base::Closure& closure) {
+void MainMessageLoop::PostClosure(base::OnceClosure closure) {
+  PostTask(CefCreateClosureTask(std::move(closure)));
+}
+
+void MainMessageLoop::PostClosure(const base::RepeatingClosure& closure) {
   PostTask(CefCreateClosureTask(closure));
 }
 
diff --git a/src/tests/shared/browser/main_message_loop.h b/src/tests/shared/browser/main_message_loop.h
index 90edd8d..8d8903f 100644
--- a/src/tests/shared/browser/main_message_loop.h
+++ b/src/tests/shared/browser/main_message_loop.h
@@ -6,8 +6,9 @@
 #define CEF_TESTS_SHARED_BROWSER_MAIN_MESSAGE_LOOP_H_
 #pragma once
 
-#include "include/base/cef_bind.h"
-#include "include/base/cef_scoped_ptr.h"
+#include <memory>
+
+#include "include/base/cef_callback.h"
 #include "include/cef_task.h"
 
 #if defined(OS_WIN)
@@ -47,11 +48,12 @@
 #endif
 
   // Post a closure for execution on the main message loop.
-  void PostClosure(const base::Closure& closure);
+  void PostClosure(base::OnceClosure closure);
+  void PostClosure(const base::RepeatingClosure& closure);
 
  protected:
-  // Only allow deletion via scoped_ptr.
-  friend struct base::DefaultDeleter<MainMessageLoop>;
+  // Only allow deletion via std::unique_ptr.
+  friend std::default_delete<MainMessageLoop>;
 
   MainMessageLoop();
   virtual ~MainMessageLoop();
@@ -96,8 +98,8 @@
     if (CURRENTLY_ON_MAIN_THREAD()) {
       delete x;
     } else {
-      client::MainMessageLoop::Get()->PostClosure(
-          base::Bind(&DeleteOnMainThread::Destruct<T>, x));
+      client::MainMessageLoop::Get()->PostClosure(base::BindOnce(
+          &DeleteOnMainThread::Destruct<T>, base::Unretained(x)));
     }
   }
 };
diff --git a/src/tests/shared/browser/main_message_loop_external_pump.cc b/src/tests/shared/browser/main_message_loop_external_pump.cc
index b589f66..fa16774 100644
--- a/src/tests/shared/browser/main_message_loop_external_pump.cc
+++ b/src/tests/shared/browser/main_message_loop_external_pump.cc
@@ -16,11 +16,11 @@
 
 // Special timer delay placeholder value. Intentionally 32-bit for Windows and
 // OS X platform API compatibility.
-const int32 kTimerDelayPlaceholder = INT_MAX;
+const int32_t kTimerDelayPlaceholder = INT_MAX;
 
 // The maximum number of milliseconds we're willing to wait between calls to
 // DoWork().
-const int64 kMaxTimerDelay = 1000 / 30;  // 30fps
+const int64_t kMaxTimerDelay = 1000 / 30;  // 30fps
 
 client::MainMessageLoopExternalPump* g_external_message_pump = nullptr;
 
@@ -40,7 +40,7 @@
   return g_external_message_pump;
 }
 
-void MainMessageLoopExternalPump::OnScheduleWork(int64 delay_ms) {
+void MainMessageLoopExternalPump::OnScheduleWork(int64_t delay_ms) {
   REQUIRE_MAIN_THREAD();
 
   if (delay_ms == kTimerDelayPlaceholder && IsTimerPending()) {
@@ -56,8 +56,9 @@
     DoWork();
   } else {
     // Never wait longer than the maximum allowed time.
-    if (delay_ms > kMaxTimerDelay)
+    if (delay_ms > kMaxTimerDelay) {
       delay_ms = kMaxTimerDelay;
+    }
 
     // Results in call to OnTimerTimeout() after the specified delay.
     SetTimer(delay_ms);
diff --git a/src/tests/shared/browser/main_message_loop_external_pump.h b/src/tests/shared/browser/main_message_loop_external_pump.h
index a25af46..c64a5c4 100644
--- a/src/tests/shared/browser/main_message_loop_external_pump.h
+++ b/src/tests/shared/browser/main_message_loop_external_pump.h
@@ -23,7 +23,7 @@
  public:
   // Creates the singleton instance of this object. Must be called on the main
   // application thread.
-  static scoped_ptr<MainMessageLoopExternalPump> Create();
+  static std::unique_ptr<MainMessageLoopExternalPump> Create();
 
   // Returns the singleton instance of this object. Safe to call from any
   // thread.
@@ -32,11 +32,11 @@
   // Called from CefBrowserProcessHandler::OnScheduleMessagePumpWork() on any
   // thread. The platform subclass must implement this method and schedule a
   // call to OnScheduleWork() on the main application thread.
-  virtual void OnScheduleMessagePumpWork(int64 delay_ms) = 0;
+  virtual void OnScheduleMessagePumpWork(int64_t delay_ms) = 0;
 
  protected:
-  // Only allow deletion via scoped_ptr.
-  friend struct base::DefaultDeleter<MainMessageLoopExternalPump>;
+  // Only allow deletion via std::unique_ptr.
+  friend std::default_delete<MainMessageLoopExternalPump>;
 
   // Construct and destruct this object on the main application thread.
   MainMessageLoopExternalPump();
@@ -44,7 +44,7 @@
 
   // The platform subclass calls this method on the main application thread in
   // response to the OnScheduleMessagePumpWork() call.
-  void OnScheduleWork(int64 delay_ms);
+  void OnScheduleWork(int64_t delay_ms);
 
   // The platform subclass calls this method on the main application thread when
   // the pending work timer times out.
@@ -52,7 +52,7 @@
 
   // Control the pending work timer in the platform subclass. Only called on
   // the main application thread.
-  virtual void SetTimer(int64 delay_ms) = 0;
+  virtual void SetTimer(int64_t delay_ms) = 0;
   virtual void KillTimer() = 0;
   virtual bool IsTimerPending() = 0;
 
diff --git a/src/tests/shared/browser/main_message_loop_external_pump_linux.cc b/src/tests/shared/browser/main_message_loop_external_pump_linux.cc
index 1afe8fe..332b502 100644
--- a/src/tests/shared/browser/main_message_loop_external_pump_linux.cc
+++ b/src/tests/shared/browser/main_message_loop_external_pump_linux.cc
@@ -6,9 +6,10 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <glib.h>
 #include <math.h>
 
-#include <glib.h>
+#include <memory>
 
 #include "include/base/cef_logging.h"
 #include "include/cef_app.h"
@@ -57,11 +58,11 @@
   ~MainMessageLoopExternalPumpLinux();
 
   // MainMessageLoopStd methods:
-  void Quit() OVERRIDE;
-  int Run() OVERRIDE;
+  void Quit() override;
+  int Run() override;
 
   // MainMessageLoopExternalPump methods:
-  void OnScheduleMessagePumpWork(int64 delay_ms) OVERRIDE;
+  void OnScheduleMessagePumpWork(int64_t delay_ms) override;
 
   // Internal methods used for processing the pump callbacks. They are public
   // for simplicity but should not be used directly. HandlePrepare is called
@@ -75,9 +76,9 @@
 
  protected:
   // MainMessageLoopExternalPump methods:
-  void SetTimer(int64 delay_ms) OVERRIDE;
-  void KillTimer() OVERRIDE;
-  bool IsTimerPending() OVERRIDE;
+  void SetTimer(int64_t delay_ms) override;
+  void KillTimer() override;
+  bool IsTimerPending() override;
 
  private:
   // Used to flag that the Run() invocation should return ASAP.
@@ -100,15 +101,17 @@
   int wakeup_pipe_read_;
   int wakeup_pipe_write_;
 
-  // Use a scoped_ptr to avoid needing the definition of GPollFD in the header.
-  scoped_ptr<GPollFD> wakeup_gpollfd_;
+  // Use a std::unique_ptr to avoid needing the definition of GPollFD in the
+  // header.
+  std::unique_ptr<GPollFD> wakeup_gpollfd_;
 };
 
 // Return a timeout suitable for the glib loop, -1 to block forever,
 // 0 to return right away, or a timeout in milliseconds from now.
 int GetTimeIntervalMilliseconds(const CefTime& from) {
-  if (from.GetDoubleT() == 0.0)
+  if (from.GetDoubleT() == 0.0) {
     return -1;
+  }
 
   CefTime now;
   now.Now();
@@ -150,7 +153,7 @@
 
 // I wish these could be const, but g_source_new wants non-const.
 GSourceFuncs WorkSourceFuncs = {WorkSourcePrepare, WorkSourceCheck,
-                                WorkSourceDispatch, NULL};
+                                WorkSourceDispatch, nullptr};
 
 MainMessageLoopExternalPumpLinux::MainMessageLoopExternalPumpLinux()
     : should_quit_(false),
@@ -204,8 +207,9 @@
     bool block = !more_work_is_plausible;
 
     more_work_is_plausible = g_main_context_iteration(context_, block);
-    if (should_quit_)
+    if (should_quit_) {
       break;
+    }
   }
 
   // We need to run the message pump until it is idle. However we don't have
@@ -222,12 +226,12 @@
 }
 
 void MainMessageLoopExternalPumpLinux::OnScheduleMessagePumpWork(
-    int64 delay_ms) {
+    int64_t delay_ms) {
   // This can be called on any thread, so we don't want to touch any state
   // variables as we would then need locks all over. This ensures that if we
   // are sleeping in a poll that we will wake up.
-  if (HANDLE_EINTR(write(wakeup_pipe_write_, &delay_ms, sizeof(int64))) !=
-      sizeof(int64)) {
+  if (HANDLE_EINTR(write(wakeup_pipe_write_, &delay_ms, sizeof(int64_t))) !=
+      sizeof(int64_t)) {
     NOTREACHED() << "Could not write to the UI message loop wakeup pipe!";
   }
 }
@@ -246,16 +250,18 @@
   // The glib poll will tell us whether there was data, so this read shouldn't
   // block.
   if (wakeup_gpollfd_->revents & G_IO_IN) {
-    int64 delay_ms[2];
+    int64_t delay_ms[2];
     const size_t num_bytes =
-        HANDLE_EINTR(read(wakeup_pipe_read_, delay_ms, sizeof(int64) * 2));
-    if (num_bytes < sizeof(int64)) {
+        HANDLE_EINTR(read(wakeup_pipe_read_, delay_ms, sizeof(int64_t) * 2));
+    if (num_bytes < sizeof(int64_t)) {
       NOTREACHED() << "Error reading from the wakeup pipe.";
     }
-    if (num_bytes == sizeof(int64))
+    if (num_bytes == sizeof(int64_t)) {
       OnScheduleWork(delay_ms[0]);
-    if (num_bytes == sizeof(int64) * 2)
+    }
+    if (num_bytes == sizeof(int64_t) * 2) {
       OnScheduleWork(delay_ms[1]);
+    }
   }
 
   if (GetTimeIntervalMilliseconds(delayed_work_time_) == 0) {
@@ -271,7 +277,7 @@
   OnTimerTimeout();
 }
 
-void MainMessageLoopExternalPumpLinux::SetTimer(int64 delay_ms) {
+void MainMessageLoopExternalPumpLinux::SetTimer(int64_t delay_ms) {
   DCHECK_GT(delay_ms, 0);
 
   CefTime now;
@@ -292,9 +298,9 @@
 }  // namespace
 
 // static
-scoped_ptr<MainMessageLoopExternalPump> MainMessageLoopExternalPump::Create() {
-  return scoped_ptr<MainMessageLoopExternalPump>(
-      new MainMessageLoopExternalPumpLinux());
+std::unique_ptr<MainMessageLoopExternalPump>
+MainMessageLoopExternalPump::Create() {
+  return std::make_unique<MainMessageLoopExternalPumpLinux>();
 }
 
 }  // namespace client
diff --git a/src/tests/shared/browser/main_message_loop_external_pump_mac.mm b/src/tests/shared/browser/main_message_loop_external_pump_mac.mm
index f88361b..c896b61 100644
--- a/src/tests/shared/browser/main_message_loop_external_pump_mac.mm
+++ b/src/tests/shared/browser/main_message_loop_external_pump_mac.mm
@@ -7,6 +7,8 @@
 #import <AppKit/AppKit.h>
 #import <Foundation/Foundation.h>
 
+#include <memory>
+
 #include "include/cef_app.h"
 
 @class EventHandler;
@@ -19,22 +21,22 @@
   ~MainMessageLoopExternalPumpMac();
 
   // MainMessageLoopStd methods:
-  void Quit() OVERRIDE;
-  int Run() OVERRIDE;
+  void Quit() override;
+  int Run() override;
 
   // MainMessageLoopExternalPump methods:
-  void OnScheduleMessagePumpWork(int64 delay_ms) OVERRIDE;
+  void OnScheduleMessagePumpWork(int64_t delay_ms) override;
 
   // Internal methods used for processing the event callbacks. They are public
   // for simplicity but should not be used directly.
-  void HandleScheduleWork(int64 delay_ms);
+  void HandleScheduleWork(int64_t delay_ms);
   void HandleTimerTimeout();
 
  protected:
   // MainMessageLoopExternalPump methods:
-  void SetTimer(int64 delay_ms) OVERRIDE;
-  void KillTimer() OVERRIDE;
-  bool IsTimerPending() OVERRIDE { return timer_ != nil; }
+  void SetTimer(int64_t delay_ms) override;
+  void KillTimer() override;
+  bool IsTimerPending() override { return timer_ != nil; }
 
  private:
   // Owner thread that will run events.
@@ -125,7 +127,8 @@
   return 0;
 }
 
-void MainMessageLoopExternalPumpMac::OnScheduleMessagePumpWork(int64 delay_ms) {
+void MainMessageLoopExternalPumpMac::OnScheduleMessagePumpWork(
+    int64_t delay_ms) {
   // This method may be called on any thread.
   NSNumber* number = [NSNumber numberWithInt:static_cast<int>(delay_ms)];
   [event_handler_ performSelector:@selector(scheduleWork:)
@@ -134,7 +137,7 @@
                     waitUntilDone:NO];
 }
 
-void MainMessageLoopExternalPumpMac::HandleScheduleWork(int64 delay_ms) {
+void MainMessageLoopExternalPumpMac::HandleScheduleWork(int64_t delay_ms) {
   OnScheduleWork(delay_ms);
 }
 
@@ -142,7 +145,7 @@
   OnTimerTimeout();
 }
 
-void MainMessageLoopExternalPumpMac::SetTimer(int64 delay_ms) {
+void MainMessageLoopExternalPumpMac::SetTimer(int64_t delay_ms) {
   DCHECK_GT(delay_ms, 0);
   DCHECK(!timer_);
 
@@ -173,9 +176,9 @@
 }
 
 // static
-scoped_ptr<MainMessageLoopExternalPump> MainMessageLoopExternalPump::Create() {
-  return scoped_ptr<MainMessageLoopExternalPump>(
-      new MainMessageLoopExternalPumpMac());
+std::unique_ptr<MainMessageLoopExternalPump>
+MainMessageLoopExternalPump::Create() {
+  return std::make_unique<MainMessageLoopExternalPumpMac>();
 }
 
 }  // namespace client
diff --git a/src/tests/shared/browser/main_message_loop_external_pump_win.cc b/src/tests/shared/browser/main_message_loop_external_pump_win.cc
index 496bcdd..9063ac7 100644
--- a/src/tests/shared/browser/main_message_loop_external_pump_win.cc
+++ b/src/tests/shared/browser/main_message_loop_external_pump_win.cc
@@ -6,6 +6,8 @@
 
 #include <CommCtrl.h>
 
+#include <memory>
+
 #include "include/cef_app.h"
 #include "tests/shared/browser/util_win.h"
 
@@ -23,17 +25,17 @@
   ~MainMessageLoopExternalPumpWin();
 
   // MainMessageLoopStd methods:
-  void Quit() OVERRIDE;
-  int Run() OVERRIDE;
+  void Quit() override;
+  int Run() override;
 
   // MainMessageLoopExternalPump methods:
-  void OnScheduleMessagePumpWork(int64 delay_ms) OVERRIDE;
+  void OnScheduleMessagePumpWork(int64_t delay_ms) override;
 
  protected:
   // MainMessageLoopExternalPump methods:
-  void SetTimer(int64 delay_ms) OVERRIDE;
-  void KillTimer() OVERRIDE;
-  bool IsTimerPending() OVERRIDE { return timer_pending_; }
+  void SetTimer(int64_t delay_ms) override;
+  void KillTimer() override;
+  bool IsTimerPending() override { return timer_pending_; }
 
  private:
   static LRESULT CALLBACK WndProc(HWND hwnd,
@@ -49,8 +51,8 @@
 };
 
 MainMessageLoopExternalPumpWin::MainMessageLoopExternalPumpWin()
-    : timer_pending_(false), main_thread_target_(NULL) {
-  HINSTANCE hInstance = GetModuleHandle(NULL);
+    : timer_pending_(false), main_thread_target_(nullptr) {
+  HINSTANCE hInstance = GetModuleHandle(nullptr);
   const wchar_t* const kClassName = L"CEFMainTargetHWND";
 
   WNDCLASSEX wcex = {};
@@ -62,26 +64,27 @@
 
   // Create the message handling window.
   main_thread_target_ =
-      CreateWindowW(kClassName, NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0,
-                    HWND_MESSAGE, NULL, hInstance, NULL);
+      CreateWindowW(kClassName, nullptr, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0,
+                    HWND_MESSAGE, nullptr, hInstance, nullptr);
   DCHECK(main_thread_target_);
   SetUserDataPtr(main_thread_target_, this);
 }
 
 MainMessageLoopExternalPumpWin::~MainMessageLoopExternalPumpWin() {
   KillTimer();
-  if (main_thread_target_)
+  if (main_thread_target_) {
     DestroyWindow(main_thread_target_);
+  }
 }
 
 void MainMessageLoopExternalPumpWin::Quit() {
-  PostMessage(NULL, WM_QUIT, 0, 0);
+  PostMessage(nullptr, WM_QUIT, 0, 0);
 }
 
 int MainMessageLoopExternalPumpWin::Run() {
   // Run the message loop.
   MSG msg;
-  while (GetMessage(&msg, NULL, 0, 0)) {
+  while (GetMessage(&msg, nullptr, 0, 0)) {
     TranslateMessage(&msg);
     DispatchMessage(&msg);
   }
@@ -101,17 +104,18 @@
   return 0;
 }
 
-void MainMessageLoopExternalPumpWin::OnScheduleMessagePumpWork(int64 delay_ms) {
+void MainMessageLoopExternalPumpWin::OnScheduleMessagePumpWork(
+    int64_t delay_ms) {
   // This method may be called on any thread.
   PostMessage(main_thread_target_, kMsgHaveWork, 0,
               static_cast<LPARAM>(delay_ms));
 }
 
-void MainMessageLoopExternalPumpWin::SetTimer(int64 delay_ms) {
+void MainMessageLoopExternalPumpWin::SetTimer(int64_t delay_ms) {
   DCHECK(!timer_pending_);
   DCHECK_GT(delay_ms, 0);
   timer_pending_ = true;
-  ::SetTimer(main_thread_target_, 1, static_cast<UINT>(delay_ms), NULL);
+  ::SetTimer(main_thread_target_, 1, static_cast<UINT>(delay_ms), nullptr);
 }
 
 void MainMessageLoopExternalPumpWin::KillTimer() {
@@ -131,7 +135,7 @@
         GetUserDataPtr<MainMessageLoopExternalPumpWin*>(hwnd);
     if (msg == kMsgHaveWork) {
       // OnScheduleMessagePumpWork() request.
-      const int64 delay_ms = static_cast<int64>(lparam);
+      const int64_t delay_ms = static_cast<int64_t>(lparam);
       message_loop->OnScheduleWork(delay_ms);
     } else {
       // Timer timed out.
@@ -144,9 +148,9 @@
 }  // namespace
 
 // static
-scoped_ptr<MainMessageLoopExternalPump> MainMessageLoopExternalPump::Create() {
-  return scoped_ptr<MainMessageLoopExternalPump>(
-      new MainMessageLoopExternalPumpWin());
+std::unique_ptr<MainMessageLoopExternalPump>
+MainMessageLoopExternalPump::Create() {
+  return std::make_unique<MainMessageLoopExternalPumpWin>();
 }
 
 }  // namespace client
diff --git a/src/tests/shared/browser/main_message_loop_std.h b/src/tests/shared/browser/main_message_loop_std.h
index 22b34a5..3bded74 100644
--- a/src/tests/shared/browser/main_message_loop_std.h
+++ b/src/tests/shared/browser/main_message_loop_std.h
@@ -17,13 +17,13 @@
   MainMessageLoopStd();
 
   // MainMessageLoop methods.
-  int Run() OVERRIDE;
-  void Quit() OVERRIDE;
-  void PostTask(CefRefPtr<CefTask> task) OVERRIDE;
-  bool RunsTasksOnCurrentThread() const OVERRIDE;
+  int Run() override;
+  void Quit() override;
+  void PostTask(CefRefPtr<CefTask> task) override;
+  bool RunsTasksOnCurrentThread() const override;
 
 #if defined(OS_WIN)
-  void SetCurrentModelessDialog(HWND hWndDialog) OVERRIDE;
+  void SetCurrentModelessDialog(HWND hWndDialog) override;
 #endif
 
  private:
diff --git a/src/tests/shared/browser/resource_util.h b/src/tests/shared/browser/resource_util.h
index cf4e5af..0e03eb7 100644
--- a/src/tests/shared/browser/resource_util.h
+++ b/src/tests/shared/browser/resource_util.h
@@ -16,10 +16,8 @@
 
 namespace client {
 
-#if defined(OS_POSIX)
 // Returns the directory containing resource files.
 bool GetResourceDir(std::string& dir);
-#endif
 
 // Retrieve a resource as a string.
 bool LoadBinaryResource(const char* resource_name, std::string& resource_data);
diff --git a/src/tests/shared/browser/resource_util_linux.cc b/src/tests/shared/browser/resource_util_linux.cc
index 7ec263e..97d69ca 100644
--- a/src/tests/shared/browser/resource_util_linux.cc
+++ b/src/tests/shared/browser/resource_util_linux.cc
@@ -16,15 +16,17 @@
 
   // Retrieve the executable path.
   ssize_t len = readlink("/proc/self/exe", buff, sizeof(buff) - 1);
-  if (len == -1)
+  if (len == -1) {
     return false;
+  }
 
   buff[len] = 0;
 
   // Remove the executable name from the path.
   char* pos = strrchr(buff, '/');
-  if (!pos)
+  if (!pos) {
     return false;
+  }
 
   // Add "files" to the path.
   strcpy(pos + 1, "files");
diff --git a/src/tests/shared/browser/resource_util_mac.mm b/src/tests/shared/browser/resource_util_mac.mm
index 219f12b..72e88d9 100644
--- a/src/tests/shared/browser/resource_util_mac.mm
+++ b/src/tests/shared/browser/resource_util_mac.mm
@@ -31,7 +31,7 @@
 bool GetResourceDir(std::string& dir) {
   // Retrieve the executable directory.
   uint32_t pathSize = 0;
-  _NSGetExecutablePath(NULL, &pathSize);
+  _NSGetExecutablePath(nullptr, &pathSize);
   if (pathSize > 0) {
     dir.resize(pathSize);
     _NSGetExecutablePath(const_cast<char*>(dir.c_str()), &pathSize);
@@ -39,10 +39,11 @@
 
   if (AmIBundled()) {
     // Trim executable name up to the last separator.
-    std::string::size_type last_separator = dir.find_last_of("/");
+    auto last_separator = dir.find_last_of("/");
     dir.resize(last_separator);
-    dir.append("/../Resources");
-    return true;
+    // Trim directory ("MacOS") up to the last separator.
+    last_separator = dir.find_last_of("/");
+    dir.resize(last_separator);
   }
 
   dir.append("/Resources");
diff --git a/src/tests/shared/browser/resource_util_posix.cc b/src/tests/shared/browser/resource_util_posix.cc
index 71e73ea..5c76b40 100644
--- a/src/tests/shared/browser/resource_util_posix.cc
+++ b/src/tests/shared/browser/resource_util_posix.cc
@@ -22,13 +22,15 @@
 bool ReadFileToString(const char* path, std::string& data) {
   // Implementation adapted from base/file_util.cc
   FILE* file = fopen(path, "rb");
-  if (!file)
+  if (!file) {
     return false;
+  }
 
   char buf[1 << 16];
   size_t len;
-  while ((len = fread(buf, 1, sizeof(buf), file)) > 0)
+  while ((len = fread(buf, 1, sizeof(buf), file)) > 0) {
     data.append(buf, len);
+  }
   fclose(file);
 
   return true;
@@ -38,8 +40,9 @@
 
 bool LoadBinaryResource(const char* resource_name, std::string& resource_data) {
   std::string path;
-  if (!GetResourceDir(path))
+  if (!GetResourceDir(path)) {
     return false;
+  }
 
   path.append("/");
   path.append(resource_name);
@@ -49,14 +52,16 @@
 
 CefRefPtr<CefStreamReader> GetBinaryResourceReader(const char* resource_name) {
   std::string path;
-  if (!GetResourceDir(path))
+  if (!GetResourceDir(path)) {
     return nullptr;
+  }
 
   path.append("/");
   path.append(resource_name);
 
-  if (!FileExists(path.c_str()))
+  if (!FileExists(path.c_str())) {
     return nullptr;
+  }
 
   return CefStreamReader::CreateForFile(path);
 }
diff --git a/src/tests/shared/browser/resource_util_win.cc b/src/tests/shared/browser/resource_util_win.cc
index 055288c..df61ca1 100644
--- a/src/tests/shared/browser/resource_util_win.cc
+++ b/src/tests/shared/browser/resource_util_win.cc
@@ -14,7 +14,7 @@
 namespace {
 
 bool LoadBinaryResource(int binaryId, DWORD& dwSize, LPBYTE& pBytes) {
-  HINSTANCE hInst = GetModuleHandle(NULL);
+  HINSTANCE hInst = GetModuleHandle(nullptr);
   HRSRC hRes =
       FindResource(hInst, MAKEINTRESOURCE(binaryId), MAKEINTRESOURCE(256));
   if (hRes) {
@@ -22,8 +22,9 @@
     if (hGlob) {
       dwSize = SizeofResource(hInst, hRes);
       pBytes = (LPBYTE)LockResource(hGlob);
-      if (dwSize > 0 && pBytes)
+      if (dwSize > 0 && pBytes) {
         return true;
+      }
     }
   }
 
@@ -43,7 +44,7 @@
     }
   }
 
-  bool OnRequest(scoped_refptr<CefResourceManager::Request> request) OVERRIDE {
+  bool OnRequest(scoped_refptr<CefResourceManager::Request> request) override {
     CEF_REQUIRE_IO_THREAD();
 
     const std::string& url = request->url();
@@ -56,8 +57,9 @@
 
     std::string relative_path = url.substr(url_path_.length());
     if (!relative_path.empty()) {
-      if (!resource_path_prefix_.empty())
+      if (!resource_path_prefix_.empty()) {
         relative_path = resource_path_prefix_ + relative_path;
+      }
 
       CefRefPtr<CefStreamReader> stream =
           GetBinaryResourceReader(relative_path.data());
@@ -85,8 +87,9 @@
 
 bool LoadBinaryResource(const char* resource_name, std::string& resource_data) {
   int resource_id = GetResourceId(resource_name);
-  if (resource_id == 0)
+  if (resource_id == 0) {
     return false;
+  }
 
   DWORD dwSize;
   LPBYTE pBytes;
@@ -102,8 +105,9 @@
 
 CefRefPtr<CefStreamReader> GetBinaryResourceReader(const char* resource_name) {
   int resource_id = GetResourceId(resource_name);
-  if (resource_id == 0)
+  if (resource_id == 0) {
     return nullptr;
+  }
 
   DWORD dwSize;
   LPBYTE pBytes;
diff --git a/src/tests/shared/browser/util_win.cc b/src/tests/shared/browser/util_win.cc
index 0be060f..4db8201 100644
--- a/src/tests/shared/browser/util_win.cc
+++ b/src/tests/shared/browser/util_win.cc
@@ -34,7 +34,7 @@
 WNDPROC SetWndProcPtr(HWND hWnd, WNDPROC wndProc) {
   WNDPROC old =
       reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hWnd, GWLP_WNDPROC));
-  CHECK(old != NULL);
+  CHECK(old != nullptr);
   LONG_PTR result = ::SetWindowLongPtr(hWnd, GWLP_WNDPROC,
                                        reinterpret_cast<LONG_PTR>(wndProc));
   CHECK(result != 0 || GetLastError() == ERROR_SUCCESS);
@@ -44,52 +44,66 @@
 std::wstring GetResourceString(UINT id) {
 #define MAX_LOADSTRING 100
   TCHAR buff[MAX_LOADSTRING] = {0};
-  LoadString(::GetModuleHandle(NULL), id, buff, MAX_LOADSTRING);
+  LoadString(::GetModuleHandle(nullptr), id, buff, MAX_LOADSTRING);
   return buff;
 }
 
 int GetCefMouseModifiers(WPARAM wparam) {
   int modifiers = 0;
-  if (wparam & MK_CONTROL)
+  if (wparam & MK_CONTROL) {
     modifiers |= EVENTFLAG_CONTROL_DOWN;
-  if (wparam & MK_SHIFT)
+  }
+  if (wparam & MK_SHIFT) {
     modifiers |= EVENTFLAG_SHIFT_DOWN;
-  if (IsKeyDown(VK_MENU))
+  }
+  if (IsKeyDown(VK_MENU)) {
     modifiers |= EVENTFLAG_ALT_DOWN;
-  if (wparam & MK_LBUTTON)
+  }
+  if (wparam & MK_LBUTTON) {
     modifiers |= EVENTFLAG_LEFT_MOUSE_BUTTON;
-  if (wparam & MK_MBUTTON)
+  }
+  if (wparam & MK_MBUTTON) {
     modifiers |= EVENTFLAG_MIDDLE_MOUSE_BUTTON;
-  if (wparam & MK_RBUTTON)
+  }
+  if (wparam & MK_RBUTTON) {
     modifiers |= EVENTFLAG_RIGHT_MOUSE_BUTTON;
+  }
 
   // Low bit set from GetKeyState indicates "toggled".
-  if (::GetKeyState(VK_NUMLOCK) & 1)
+  if (::GetKeyState(VK_NUMLOCK) & 1) {
     modifiers |= EVENTFLAG_NUM_LOCK_ON;
-  if (::GetKeyState(VK_CAPITAL) & 1)
+  }
+  if (::GetKeyState(VK_CAPITAL) & 1) {
     modifiers |= EVENTFLAG_CAPS_LOCK_ON;
+  }
   return modifiers;
 }
 
 int GetCefKeyboardModifiers(WPARAM wparam, LPARAM lparam) {
   int modifiers = 0;
-  if (IsKeyDown(VK_SHIFT))
+  if (IsKeyDown(VK_SHIFT)) {
     modifiers |= EVENTFLAG_SHIFT_DOWN;
-  if (IsKeyDown(VK_CONTROL))
+  }
+  if (IsKeyDown(VK_CONTROL)) {
     modifiers |= EVENTFLAG_CONTROL_DOWN;
-  if (IsKeyDown(VK_MENU))
+  }
+  if (IsKeyDown(VK_MENU)) {
     modifiers |= EVENTFLAG_ALT_DOWN;
+  }
 
   // Low bit set from GetKeyState indicates "toggled".
-  if (::GetKeyState(VK_NUMLOCK) & 1)
+  if (::GetKeyState(VK_NUMLOCK) & 1) {
     modifiers |= EVENTFLAG_NUM_LOCK_ON;
-  if (::GetKeyState(VK_CAPITAL) & 1)
+  }
+  if (::GetKeyState(VK_CAPITAL) & 1) {
     modifiers |= EVENTFLAG_CAPS_LOCK_ON;
+  }
 
   switch (wparam) {
     case VK_RETURN:
-      if ((lparam >> 16) & KF_EXTENDED)
+      if ((lparam >> 16) & KF_EXTENDED) {
         modifiers |= EVENTFLAG_IS_KEY_PAD;
+      }
       break;
     case VK_INSERT:
     case VK_DELETE:
@@ -101,8 +115,9 @@
     case VK_DOWN:
     case VK_LEFT:
     case VK_RIGHT:
-      if (!((lparam >> 16) & KF_EXTENDED))
+      if (!((lparam >> 16) & KF_EXTENDED)) {
         modifiers |= EVENTFLAG_IS_KEY_PAD;
+      }
       break;
     case VK_NUMLOCK:
     case VK_NUMPAD0:
@@ -124,22 +139,25 @@
       modifiers |= EVENTFLAG_IS_KEY_PAD;
       break;
     case VK_SHIFT:
-      if (IsKeyDown(VK_LSHIFT))
+      if (IsKeyDown(VK_LSHIFT)) {
         modifiers |= EVENTFLAG_IS_LEFT;
-      else if (IsKeyDown(VK_RSHIFT))
+      } else if (IsKeyDown(VK_RSHIFT)) {
         modifiers |= EVENTFLAG_IS_RIGHT;
+      }
       break;
     case VK_CONTROL:
-      if (IsKeyDown(VK_LCONTROL))
+      if (IsKeyDown(VK_LCONTROL)) {
         modifiers |= EVENTFLAG_IS_LEFT;
-      else if (IsKeyDown(VK_RCONTROL))
+      } else if (IsKeyDown(VK_RCONTROL)) {
         modifiers |= EVENTFLAG_IS_RIGHT;
+      }
       break;
     case VK_MENU:
-      if (IsKeyDown(VK_LMENU))
+      if (IsKeyDown(VK_LMENU)) {
         modifiers |= EVENTFLAG_IS_LEFT;
-      else if (IsKeyDown(VK_RMENU))
+      } else if (IsKeyDown(VK_RMENU)) {
         modifiers |= EVENTFLAG_IS_RIGHT;
+      }
       break;
     case VK_LWIN:
       modifiers |= EVENTFLAG_IS_LEFT;
@@ -163,10 +181,10 @@
     // This value is safe to cache for the life time of the app since the user
     // must logout to change the DPI setting. This value also applies to all
     // screens.
-    HDC screen_dc = ::GetDC(NULL);
+    HDC screen_dc = ::GetDC(nullptr);
     int dpi_x = GetDeviceCaps(screen_dc, LOGPIXELSX);
     scale_factor = static_cast<float>(dpi_x) / 96.0f;
-    ::ReleaseDC(NULL, screen_dc);
+    ::ReleaseDC(nullptr, screen_dc);
     initialized = true;
   }
 
diff --git a/src/tests/shared/common/binary_value_utils.cc b/src/tests/shared/common/binary_value_utils.cc
new file mode 100644
index 0000000..8b16ed7
--- /dev/null
+++ b/src/tests/shared/common/binary_value_utils.cc
@@ -0,0 +1,48 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "tests/shared/common/binary_value_utils.h"
+
+namespace bv_utils {
+
+const char kTestSendProcessMessage[] = "testSendProcessMessage";
+const char kTestSendSMRProcessMessage[] = "testSendSMRProcessMessage";
+
+TimePoint Now() {
+  return std::chrono::high_resolution_clock::now();
+}
+
+CefRefPtr<CefBinaryValue> CreateCefBinaryValue(
+    const std::vector<uint8_t>& data) {
+  return CefBinaryValue::Create(data.data(), data.size());
+}
+
+void CopyDataIntoMemory(const std::vector<uint8_t>& data, void* dst) {
+  memcpy(dst, data.data(), data.size());
+}
+
+RendererMessage GetRendererMsgFromBinary(
+    const CefRefPtr<CefBinaryValue>& value) {
+  DCHECK_GE(value->GetSize(), sizeof(RendererMessage));
+  std::vector<uint8_t> data(value->GetSize());
+  value->GetData(data.data(), data.size(), 0);
+  return *reinterpret_cast<const RendererMessage*>(data.data());
+}
+
+BrowserMessage GetBrowserMsgFromBinary(const CefRefPtr<CefBinaryValue>& value) {
+  DCHECK_GE(value->GetSize(), sizeof(BrowserMessage));
+  std::vector<uint8_t> data(value->GetSize());
+  value->GetData(data.data(), data.size(), 0);
+  return *reinterpret_cast<const BrowserMessage*>(data.data());
+}
+
+std::string ToMicroSecString(const Duration& duration) {
+  const auto ms =
+      std::chrono::duration_cast<std::chrono::duration<double, std::micro>>(
+          duration);
+
+  return std::to_string(ms.count());
+}
+
+}  // namespace bv_utils
diff --git a/src/tests/shared/common/binary_value_utils.h b/src/tests/shared/common/binary_value_utils.h
new file mode 100644
index 0000000..73b0465
--- /dev/null
+++ b/src/tests/shared/common/binary_value_utils.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 CEF_TESTS_SHARED_COMMON_BINARY_VALUE_UTILS
+#define CEF_TESTS_SHARED_COMMON_BINARY_VALUE_UTILS
+#pragma once
+
+#include <chrono>
+#include <cstdint>
+#include <vector>
+#include "include/cef_values.h"
+
+namespace bv_utils {
+
+extern const char kTestSendProcessMessage[];
+extern const char kTestSendSMRProcessMessage[];
+
+using TimePoint = std::chrono::high_resolution_clock::time_point;
+using Duration = std::chrono::high_resolution_clock::duration;
+
+struct RendererMessage {
+  int test_id;
+  TimePoint start_time;
+};
+
+struct BrowserMessage {
+  int test_id;
+  Duration duration;
+  TimePoint start_time;
+};
+
+TimePoint Now();
+
+CefRefPtr<CefBinaryValue> CreateCefBinaryValue(
+    const std::vector<uint8_t>& data);
+
+void CopyDataIntoMemory(const std::vector<uint8_t>& data, void* dst);
+
+RendererMessage GetRendererMsgFromBinary(
+    const CefRefPtr<CefBinaryValue>& value);
+
+BrowserMessage GetBrowserMsgFromBinary(const CefRefPtr<CefBinaryValue>& value);
+
+std::string ToMicroSecString(const Duration& duration);
+
+}  // namespace bv_utils
+
+#endif  // CEF_TESTS_SHARED_COMMON_BINARY_VALUE_UTILS
diff --git a/src/tests/shared/common/client_app.cc b/src/tests/shared/common/client_app.cc
index 1a76d4b..76ecde7 100644
--- a/src/tests/shared/common/client_app.cc
+++ b/src/tests/shared/common/client_app.cc
@@ -25,15 +25,18 @@
 ClientApp::ProcessType ClientApp::GetProcessType(
     CefRefPtr<CefCommandLine> command_line) {
   // The command-line flag won't be specified for the browser process.
-  if (!command_line->HasSwitch(kProcessType))
+  if (!command_line->HasSwitch(kProcessType)) {
     return BrowserProcess;
+  }
 
   const std::string& process_type = command_line->GetSwitchValue(kProcessType);
-  if (process_type == kRendererProcess)
+  if (process_type == kRendererProcess) {
     return RendererProcess;
+  }
 #if defined(OS_LINUX)
-  else if (process_type == kZygoteProcess)
+  else if (process_type == kZygoteProcess) {
     return ZygoteProcess;
+  }
 #endif
 
   return OtherProcess;
@@ -41,7 +44,7 @@
 
 void ClientApp::OnRegisterCustomSchemes(
     CefRawPtr<CefSchemeRegistrar> registrar) {
-  RegisterCustomSchemes(registrar, cookieable_schemes_);
+  RegisterCustomSchemes(registrar);
 }
 
 }  // namespace client
diff --git a/src/tests/shared/common/client_app.h b/src/tests/shared/common/client_app.h
index 225f808..553f0d4 100644
--- a/src/tests/shared/common/client_app.h
+++ b/src/tests/shared/common/client_app.h
@@ -27,19 +27,14 @@
   // Determine the process type based on command-line arguments.
   static ProcessType GetProcessType(CefRefPtr<CefCommandLine> command_line);
 
- protected:
-  // Schemes that will be registered with the global cookie manager.
-  std::vector<CefString> cookieable_schemes_;
-
  private:
   // Registers custom schemes. Implemented by cefclient in
   // client_app_delegates_common.cc
-  static void RegisterCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar,
-                                    std::vector<CefString>& cookiable_schemes);
+  static void RegisterCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar);
 
   // CefApp methods.
   void OnRegisterCustomSchemes(
-      CefRawPtr<CefSchemeRegistrar> registrar) OVERRIDE;
+      CefRawPtr<CefSchemeRegistrar> registrar) override;
 
   DISALLOW_COPY_AND_ASSIGN(ClientApp);
 };
diff --git a/src/tests/shared/common/client_switches.cc b/src/tests/shared/common/client_switches.cc
index 9feef7c..822a738 100644
--- a/src/tests/shared/common/client_switches.cc
+++ b/src/tests/shared/common/client_switches.cc
@@ -29,21 +29,34 @@
 const char kExternalBeginFrameEnabled[] = "external-begin-frame-enabled";
 const char kMouseCursorChangeDisabled[] = "mouse-cursor-change-disabled";
 const char kOffline[] = "offline";
+const char kFilterChromeCommands[] = "filter-chrome-commands";
 const char kRequestContextPerBrowser[] = "request-context-per-browser";
 const char kRequestContextSharedCache[] = "request-context-shared-cache";
 const char kBackgroundColor[] = "background-color";
 const char kEnableGPU[] = "enable-gpu";
 const char kFilterURL[] = "filter-url";
 const char kUseViews[] = "use-views";
+const char kUseNative[] = "use-native";
 const char kHideFrame[] = "hide-frame";
 const char kHideControls[] = "hide-controls";
+const char kHideOverlays[] = "hide-overlays";
 const char kAlwaysOnTop[] = "always-on-top";
 const char kHideTopMenu[] = "hide-top-menu";
-const char kWidevineCdmPath[] = "widevine-cdm-path";
 const char kSslClientCertificate[] = "ssl-client-certificate";
 const char kCRLSetsPath[] = "crl-sets-path";
 const char kLoadExtension[] = "load-extension";
 const char kNoActivate[] = "no-activate";
+const char kEnableChromeRuntime[] = "enable-chrome-runtime";
+const char kShowChromeToolbar[] = "show-chrome-toolbar";
+const char kInitialShowState[] = "initial-show-state";
+const char kUseDefaultPopup[] = "use-default-popup";
+const char kUseClientDialogs[] = "use-client-dialogs";
+const char kUseTestHttpServer[] = "use-test-http-server";
+const char kShowWindowButtons[] = "show-window-buttons";
+const char kUseWindowModalDialog[] = "use-window-modal-dialog";
+const char kUseBottomControls[] = "use-bottom-controls";
+const char kHidePipFrame[] = "hide-pip-frame";
+const char kHideChromeBubbles[] = "hide-chrome-bubbles";
 
 }  // namespace switches
 }  // namespace client
diff --git a/src/tests/shared/common/client_switches.h b/src/tests/shared/common/client_switches.h
index 0ff5938..63e43e0 100644
--- a/src/tests/shared/common/client_switches.h
+++ b/src/tests/shared/common/client_switches.h
@@ -23,21 +23,34 @@
 extern const char kExternalBeginFrameEnabled[];
 extern const char kMouseCursorChangeDisabled[];
 extern const char kOffline[];
+extern const char kFilterChromeCommands[];
 extern const char kRequestContextPerBrowser[];
 extern const char kRequestContextSharedCache[];
 extern const char kBackgroundColor[];
 extern const char kEnableGPU[];
 extern const char kFilterURL[];
 extern const char kUseViews[];
+extern const char kUseNative[];
 extern const char kHideFrame[];
 extern const char kHideControls[];
+extern const char kHideOverlays[];
 extern const char kAlwaysOnTop[];
 extern const char kHideTopMenu[];
-extern const char kWidevineCdmPath[];
 extern const char kSslClientCertificate[];
 extern const char kCRLSetsPath[];
 extern const char kLoadExtension[];
 extern const char kNoActivate[];
+extern const char kEnableChromeRuntime[];
+extern const char kShowChromeToolbar[];
+extern const char kInitialShowState[];
+extern const char kUseDefaultPopup[];
+extern const char kUseClientDialogs[];
+extern const char kUseTestHttpServer[];
+extern const char kShowWindowButtons[];
+extern const char kUseWindowModalDialog[];
+extern const char kUseBottomControls[];
+extern const char kHidePipFrame[];
+extern const char kHideChromeBubbles[];
 
 }  // namespace switches
 }  // namespace client
diff --git a/src/tests/shared/common/string_util.cc b/src/tests/shared/common/string_util.cc
new file mode 100644
index 0000000..7bd5ada
--- /dev/null
+++ b/src/tests/shared/common/string_util.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 "tests/shared/common/string_util.h"
+
+#include <algorithm>
+
+namespace client {
+
+std::string AsciiStrToLower(const std::string& str) {
+  std::string lowerStr = str;
+  std::transform(lowerStr.begin(), lowerStr.end(), lowerStr.begin(), ::tolower);
+  return lowerStr;
+}
+
+std::string AsciiStrReplace(const std::string& str,
+                            const std::string& from,
+                            const std::string& to) {
+  std::string result = str;
+  std::string::size_type pos = 0;
+  std::string::size_type from_len = from.length();
+  std::string::size_type to_len = to.length();
+  do {
+    pos = result.find(from, pos);
+    if (pos != std::string::npos) {
+      result.replace(pos, from_len, to);
+      pos += to_len;
+    }
+  } while (pos != std::string::npos);
+  return result;
+}
+
+}  // namespace client
diff --git a/src/tests/shared/common/string_util.h b/src/tests/shared/common/string_util.h
new file mode 100644
index 0000000..5ae4e2c
--- /dev/null
+++ b/src/tests/shared/common/string_util.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2022 The Chromium Embedded Framework 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 CEF_TESTS_SHARED_COMMON_STRING_UTIL_H_
+#define CEF_TESTS_SHARED_COMMON_STRING_UTIL_H_
+#pragma once
+
+#include <string>
+
+namespace client {
+
+// Convert |str| to lowercase.
+std::string AsciiStrToLower(const std::string& str);
+
+// Replace all instances of |from| with |to| in |str|.
+std::string AsciiStrReplace(const std::string& str,
+                            const std::string& from,
+                            const std::string& to);
+
+}  // namespace client
+
+#endif  // CEF_TESTS_SHARED_COMMON_STRING_UTIL_H_
diff --git a/src/tests/shared/process_helper_mac.cc b/src/tests/shared/process_helper_mac.cc
index 9efa2e3..cce48e5 100644
--- a/src/tests/shared/process_helper_mac.cc
+++ b/src/tests/shared/process_helper_mac.cc
@@ -21,15 +21,17 @@
 #if defined(CEF_USE_SANDBOX)
   // Initialize the macOS sandbox for this helper process.
   CefScopedSandboxContext sandbox_context;
-  if (!sandbox_context.Initialize(argc, argv))
+  if (!sandbox_context.Initialize(argc, argv)) {
     return 1;
+  }
 #endif
 
   // Load the CEF framework library at runtime instead of linking directly
   // as required by the macOS sandbox implementation.
   CefScopedLibraryLoader library_loader;
-  if (!library_loader.LoadInHelper())
+  if (!library_loader.LoadInHelper()) {
     return 1;
+  }
 
   CefMainArgs main_args(argc, argv);
 
@@ -40,10 +42,11 @@
   // Create a ClientApp of the correct type.
   CefRefPtr<CefApp> app;
   ClientApp::ProcessType process_type = ClientApp::GetProcessType(command_line);
-  if (process_type == ClientApp::RendererProcess)
+  if (process_type == ClientApp::RendererProcess) {
     app = new ClientAppRenderer();
-  else if (process_type == ClientApp::OtherProcess)
+  } else if (process_type == ClientApp::OtherProcess) {
     app = new ClientAppOther();
+  }
 
   // Execute the secondary process.
   return CefExecuteProcess(main_args, app, nullptr);
diff --git a/src/tests/shared/renderer/client_app_renderer.cc b/src/tests/shared/renderer/client_app_renderer.cc
index b2020a5..9347051 100644
--- a/src/tests/shared/renderer/client_app_renderer.cc
+++ b/src/tests/shared/renderer/client_app_renderer.cc
@@ -12,38 +12,35 @@
   CreateDelegates(delegates_);
 }
 
-void ClientAppRenderer::OnRenderThreadCreated(
-    CefRefPtr<CefListValue> extra_info) {
-  DelegateSet::iterator it = delegates_.begin();
-  for (; it != delegates_.end(); ++it)
-    (*it)->OnRenderThreadCreated(this, extra_info);
-}
-
 void ClientAppRenderer::OnWebKitInitialized() {
   DelegateSet::iterator it = delegates_.begin();
-  for (; it != delegates_.end(); ++it)
+  for (; it != delegates_.end(); ++it) {
     (*it)->OnWebKitInitialized(this);
+  }
 }
 
 void ClientAppRenderer::OnBrowserCreated(
     CefRefPtr<CefBrowser> browser,
     CefRefPtr<CefDictionaryValue> extra_info) {
   DelegateSet::iterator it = delegates_.begin();
-  for (; it != delegates_.end(); ++it)
+  for (; it != delegates_.end(); ++it) {
     (*it)->OnBrowserCreated(this, browser, extra_info);
+  }
 }
 
 void ClientAppRenderer::OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) {
   DelegateSet::iterator it = delegates_.begin();
-  for (; it != delegates_.end(); ++it)
+  for (; it != delegates_.end(); ++it) {
     (*it)->OnBrowserDestroyed(this, browser);
+  }
 }
 
 CefRefPtr<CefLoadHandler> ClientAppRenderer::GetLoadHandler() {
   CefRefPtr<CefLoadHandler> load_handler;
   DelegateSet::iterator it = delegates_.begin();
-  for (; it != delegates_.end() && !load_handler.get(); ++it)
+  for (; it != delegates_.end() && !load_handler.get(); ++it) {
     load_handler = (*it)->GetLoadHandler(this);
+  }
 
   return load_handler;
 }
@@ -52,16 +49,18 @@
                                          CefRefPtr<CefFrame> frame,
                                          CefRefPtr<CefV8Context> context) {
   DelegateSet::iterator it = delegates_.begin();
-  for (; it != delegates_.end(); ++it)
+  for (; it != delegates_.end(); ++it) {
     (*it)->OnContextCreated(this, browser, frame, context);
+  }
 }
 
 void ClientAppRenderer::OnContextReleased(CefRefPtr<CefBrowser> browser,
                                           CefRefPtr<CefFrame> frame,
                                           CefRefPtr<CefV8Context> context) {
   DelegateSet::iterator it = delegates_.begin();
-  for (; it != delegates_.end(); ++it)
+  for (; it != delegates_.end(); ++it) {
     (*it)->OnContextReleased(this, browser, frame, context);
+  }
 }
 
 void ClientAppRenderer::OnUncaughtException(
@@ -81,8 +80,9 @@
                                              CefRefPtr<CefFrame> frame,
                                              CefRefPtr<CefDOMNode> node) {
   DelegateSet::iterator it = delegates_.begin();
-  for (; it != delegates_.end(); ++it)
+  for (; it != delegates_.end(); ++it) {
     (*it)->OnFocusedNodeChanged(this, browser, frame, node);
+  }
 }
 
 bool ClientAppRenderer::OnProcessMessageReceived(
diff --git a/src/tests/shared/renderer/client_app_renderer.h b/src/tests/shared/renderer/client_app_renderer.h
index ce206b9..e458e35 100644
--- a/src/tests/shared/renderer/client_app_renderer.h
+++ b/src/tests/shared/renderer/client_app_renderer.h
@@ -20,9 +20,6 @@
   // constructor. See CefRenderProcessHandler for documentation.
   class Delegate : public virtual CefBaseRefCounted {
    public:
-    virtual void OnRenderThreadCreated(CefRefPtr<ClientAppRenderer> app,
-                                       CefRefPtr<CefListValue> extra_info) {}
-
     virtual void OnWebKitInitialized(CefRefPtr<ClientAppRenderer> app) {}
 
     virtual void OnBrowserCreated(CefRefPtr<ClientAppRenderer> app,
@@ -83,35 +80,34 @@
   static void CreateDelegates(DelegateSet& delegates);
 
   // CefApp methods.
-  CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() OVERRIDE {
+  CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() override {
     return this;
   }
 
   // CefRenderProcessHandler methods.
-  void OnRenderThreadCreated(CefRefPtr<CefListValue> extra_info) OVERRIDE;
-  void OnWebKitInitialized() OVERRIDE;
+  void OnWebKitInitialized() override;
   void OnBrowserCreated(CefRefPtr<CefBrowser> browser,
-                        CefRefPtr<CefDictionaryValue> extra_info) OVERRIDE;
-  void OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) OVERRIDE;
-  CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE;
+                        CefRefPtr<CefDictionaryValue> extra_info) override;
+  void OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) override;
+  CefRefPtr<CefLoadHandler> GetLoadHandler() override;
   void OnContextCreated(CefRefPtr<CefBrowser> browser,
                         CefRefPtr<CefFrame> frame,
-                        CefRefPtr<CefV8Context> context) OVERRIDE;
+                        CefRefPtr<CefV8Context> context) override;
   void OnContextReleased(CefRefPtr<CefBrowser> browser,
                          CefRefPtr<CefFrame> frame,
-                         CefRefPtr<CefV8Context> context) OVERRIDE;
+                         CefRefPtr<CefV8Context> context) override;
   void OnUncaughtException(CefRefPtr<CefBrowser> browser,
                            CefRefPtr<CefFrame> frame,
                            CefRefPtr<CefV8Context> context,
                            CefRefPtr<CefV8Exception> exception,
-                           CefRefPtr<CefV8StackTrace> stackTrace) OVERRIDE;
+                           CefRefPtr<CefV8StackTrace> stackTrace) override;
   void OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
                             CefRefPtr<CefFrame> frame,
-                            CefRefPtr<CefDOMNode> node) OVERRIDE;
+                            CefRefPtr<CefDOMNode> node) override;
   bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
                                 CefRefPtr<CefFrame> frame,
                                 CefProcessId source_process,
-                                CefRefPtr<CefProcessMessage> message) OVERRIDE;
+                                CefRefPtr<CefProcessMessage> message) override;
 
  private:
   // Set of supported Delegates.
diff --git a/src/tests/shared/resources/osr_test.html b/src/tests/shared/resources/osr_test.html
index a91c585..7cec2d5 100644
--- a/src/tests/shared/resources/osr_test.html
+++ b/src/tests/shared/resources/osr_test.html
@@ -57,6 +57,7 @@
     elems.push(getElementBounds('LI11'));
     elems.push(getElementBounds('LI11select'));
     elems.push(getElementBounds('email'));
+    elems.push(getElementBounds('quickmenu'));
     elems.push(getElementBounds('editbox'));
     elems.push(getElementBounds('btnnavigate'));
     elems.push(getElementBounds('dropdiv'));
@@ -99,6 +100,11 @@
       window.testQuery({request: param});
   }
 
+  function onFocusTest(ev) {
+    if (window.testQuery)
+      window.testQuery({request: "osrfocus" + ev.target.id});
+  }
+
   function allowDrop(ev) {
     ev.preventDefault();
   }
@@ -168,7 +174,7 @@
       </li>
   <li id='LI07'>Invalidate should trigger OnPaint once</li>
   <li id='LI08'>Click and write here with SendKeyEvent to trigger repaints:
-      <input id='editbox' type='text' value='' size="5"></li>
+      <input id='editbox' type='text' value='' size="5" onfocus="onFocusTest(event)"></li>
   <li id='LI09'>Click here with SendMouseClickEvent to navigate:
       <input id='btnnavigate' type='button' onclick='navigate()'
       value='Click here to navigate' /></li>
@@ -176,6 +182,7 @@
       trigger show a tooltip</li>
   <li id='LI11' onclick='selectText(event)'>SELECTED_TEXT_RANGE</li>
   <li><input id='email' type='text' size=10 inputmode='email'></li>
+  <li id="quickmenu">Long touch press should trigger quick menu</li>
   </ol>
 
   <div class="dropdiv" id="dropdiv" ondrop="drop(event)" ondragover="allowDrop(event)">
diff --git a/src/tools/automate/automate-git.py b/src/tools/automate/automate-git.py
index b33e4a5..f1ec60b 100644
--- a/src/tools/automate/automate-git.py
+++ b/src/tools/automate/automate-git.py
@@ -5,7 +5,6 @@
 from __future__ import absolute_import
 from __future__ import print_function
 from datetime import datetime
-import json
 from io import open
 from optparse import OptionParser
 import os
@@ -34,8 +33,6 @@
 
 cef_git_url = 'https://bitbucket.org/chromiumembedded/cef.git'
 
-chromium_channel_json_url = 'https://omahaproxy.appspot.com/all.json'
-
 ##
 # Global system variables.
 ##
@@ -159,16 +156,6 @@
   return 'Unknown'
 
 
-def get_git_date(path, branch):
-  """ Returns the date for the specified branch/tag/hash. """
-  cmd = "%s show -s --format=%%ct %s" % (git_exe, branch)
-  result = exec_cmd(cmd, path)
-  if result['out'] != '':
-    return datetime.utcfromtimestamp(
-        int(result['out'].strip())).strftime('%Y-%m-%d %H:%M:%S UTC')
-  return 'Unknown'
-
-
 def get_git_url(path):
   """ Returns the origin url for the specified path. """
   cmd = "%s config --get remote.origin.url" % (git_exe)
@@ -326,66 +313,23 @@
     raise
 
 
-def read_json_url(url):
-  """ Read a JSON URL. """
-  msg('Downloading %s' % url)
-  return json.loads(urlopen(url).read())
-
-
-g_channel_data = None
-
-
-def get_chromium_channel_data(os, channel, param=None):
-  """ Returns all data for the specified Chromium channel. """
-  global g_channel_data
-
-  if g_channel_data is None:
-    g_channel_data = read_json_url(chromium_channel_json_url)
-    assert len(g_channel_data) > 0, 'Failed to load Chromium channel data'
-
-  for oses in g_channel_data:
-    if oses['os'] == os:
-      for version in oses['versions']:
-        if version['channel'] == channel:
-          assert version['os'] == os
-          assert version['channel'] == channel
-          if param is None:
-            return version
-          else:
-            assert param in version, 'Missing parameter %s for Chromium channel %s %s' % (
-                param, os, channel)
-            return version[param]
-      raise Exception("Invalid Chromium channel value: %s" % channel)
-  raise Exception("Invalid Chromium os value: %s" % os)
-
-
-def get_chromium_channel_commit(os, channel):
-  """ Returns the current branch commit for the specified Chromium channel. """
-  return get_chromium_channel_data(os, channel, 'branch_commit')
-
-
-def get_chromium_channel_version(os, channel):
-  """ Returns the current version for the specified Chromium channel. """
-  return get_chromium_channel_data(os, channel, 'current_version')
-
-
-def get_chromium_master_position(commit):
-  """ Returns the closest master position for the specified Chromium commit. """
+def get_chromium_main_position(commit):
+  """ Returns the closest main position for the specified Chromium commit. """
   # Using -2 because a "Publish DEPS" commit which does not have a master
   # position may be first.
   cmd = "%s log -2 %s" % (git_exe, commit)
   result = exec_cmd(cmd, chromium_src_dir)
   if result['out'] != '':
-    match = re.search(r'refs/heads/master@{#([\d]+)}', result['out'])
+    match = re.search(r'refs/heads/(?:master|main)@{#([\d]+)}', result['out'])
     assert match != None, 'Failed to find position'
     return int(match.groups()[0])
   return None
 
 
-def get_chromium_master_commit(position):
-  """ Returns the master commit for the specified Chromium commit position. """
-  cmd = '%s log -1 --grep=refs/heads/master@{#%s} origin/master' % (
-      git_exe, str(position))
+def get_chromium_main_commit(position):
+  """ Returns the main commit for the specified Chromium commit position. """
+  cmd = '%s log -1 --grep=refs/heads/master@{#%s} --grep=refs/heads/main@{#%s} origin/main' % (
+      git_exe, str(position), str(position))
   result = exec_cmd(cmd, chromium_src_dir)
   if result['out'] != '':
     match = re.search(r'^commit ([a-f0-9]+)', result['out'])
@@ -394,16 +338,6 @@
   return None
 
 
-def get_chromium_versions(commit):
-  """ Returns the list of Chromium versions that contain the specified commit.
-      Versions are listed oldest to newest. """
-  cmd = '%s tag --contains %s' % (git_exe, commit)
-  result = exec_cmd(cmd, chromium_src_dir)
-  if result['out'] != '':
-    return [line.strip() for line in result['out'].strip().split('\n')]
-  return None
-
-
 def get_build_compat_versions():
   """ Returns the compatible Chromium and (optionally) depot_tools versions
       specified by the CEF checkout. """
@@ -416,68 +350,6 @@
   return config
 
 
-def get_chromium_target_version(os='win', channel='canary', target_distance=0):
-  """ Returns the target Chromium version based on a heuristic. """
-  # The current compatible version from CEF.
-  compat_version = chromium_compat_version
-  compat_commit = get_git_hash(chromium_src_dir, compat_version)
-  if compat_version == compat_commit:
-    versions = get_chromium_versions(compat_commit)
-    if len(versions) > 0:
-      compat_version = 'refs/tags/' + versions[0]
-      # Closest version may not align with the compat position, so adjust the
-      # commit to match.
-      compat_commit = get_git_hash(chromium_src_dir, compat_version)
-  compat_position = get_chromium_master_position(compat_commit)
-  compat_date = get_git_date(chromium_src_dir, compat_commit)
-
-  # The most recent channel version from the Chromium website.
-  channel_version = 'refs/tags/' + get_chromium_channel_version(os, channel)
-  channel_commit = get_chromium_channel_commit(os, channel)
-  channel_position = get_chromium_master_position(channel_commit)
-  channel_date = get_git_date(chromium_src_dir, channel_commit)
-
-  if compat_position >= channel_position:
-    # Already compatible with the channel version or newer.
-    target_version = compat_version
-    target_commit = compat_commit
-    target_position = compat_position
-    target_date = compat_date
-  elif target_distance <= 0 or compat_position + target_distance >= channel_position:
-    # Channel version is within the target distance.
-    target_version = channel_version
-    target_commit = channel_commit
-    target_position = channel_position
-    target_date = channel_date
-  else:
-    # Find an intermediary version that's within the target distance.
-    target_position = compat_position + target_distance
-    target_commit = get_chromium_master_commit(target_position)
-    versions = get_chromium_versions(target_commit)
-    if len(versions) > 0:
-      target_version = 'refs/tags/' + versions[0]
-      # Closest version may not align with the target position, so adjust the
-      # commit and position to match.
-      target_commit = get_git_hash(chromium_src_dir, target_version)
-      target_position = get_chromium_master_position(target_commit)
-    else:
-      target_version = target_commit
-    target_date = get_git_date(chromium_src_dir, target_commit)
-
-  msg("")
-  msg("Computed Chromium update for %s %s at distance %d" % (os, channel,
-                                                             target_distance))
-  msg("Compat:  %s %s %s (#%d)" % (compat_date, compat_version, compat_commit,
-                                   compat_position))
-  msg("Target:  %s %s %s (#%d)" % (target_date, target_version, target_commit,
-                                   target_position))
-  msg("Channel: %s %s %s (#%d)" % (channel_date, channel_version,
-                                   channel_commit, channel_position))
-  msg("")
-
-  return target_version
-
-
 def get_build_directory_name(is_debug):
   build_dir = ('Debug' if is_debug else 'Release') + '_'
 
@@ -516,10 +388,10 @@
     if os.path.exists(out_file):
       os.remove(out_file)
 
-    old_commit = get_chromium_master_commit(
-        get_chromium_master_position(chromium_compat_version))
-    new_commit = get_chromium_master_commit(
-        get_chromium_master_position(chromium_checkout))
+    old_commit = get_chromium_main_commit(
+        get_chromium_main_position(chromium_compat_version))
+    new_commit = get_chromium_main_commit(
+        get_chromium_main_position(chromium_checkout))
 
     cmd = '%s diff --relative --no-prefix %s..%s -- %s' % (
         git_exe, old_commit, new_commit, ' '.join(config['files']))
@@ -589,6 +461,11 @@
       # Don't continue when we know the build will be wrong.
       sys.exit(1)
 
+def invalid_options_combination(a, b):
+  print("Invalid combination of options: '%s' and '%s'" % (a, b))
+  parser.print_help(sys.stderr)
+  sys.exit(1)
+
 
 ##
 # Program entry point.
@@ -597,7 +474,7 @@
 # Cannot be loaded as a module.
 if __name__ != "__main__":
   sys.stderr.write('This file cannot be loaded as a module!')
-  sys.exit()
+  sys.exit(1)
 
 # Parse command-line options.
 disc = """
@@ -645,16 +522,6 @@
                        'branch/hash/tag). This overrides the value specified '+\
                        'by CEF in CHROMIUM_BUILD_COMPATIBILITY.txt.',
                   default='')
-parser.add_option('--chromium-channel', dest='chromiumchannel',
-                  help='Chromium channel to check out (canary, dev, beta or '+\
-                       'stable). This overrides the value specified by CEF '+\
-                       'in CHROMIUM_BUILD_COMPATIBILITY.txt.',
-                  default='')
-parser.add_option('--chromium-channel-distance', dest='chromiumchanneldistance',
-                  help='The target number of commits to step in the '+\
-                       'channel, or 0 to use the newest channel version. '+\
-                       'Used in combination with --chromium-channel.',
-                  default='')
 
 # Miscellaneous options.
 parser.add_option(
@@ -679,7 +546,7 @@
     help="Output commands without executing them.")
 parser.add_option('--dry-run-platform', dest='dryrunplatform', default=None,
                   help='Simulate a dry run on the specified platform '+\
-                       '(windows, macosx, linux). Must be used in combination'+\
+                       '(windows, mac, linux). Must be used in combination'+\
                        ' with the --dry-run flag.')
 
 # Update-related options.
@@ -809,6 +676,12 @@
     dest='arm64build',
     default=False,
     help='Create an ARM64 build.')
+parser.add_option(
+    '--with-pgo-profiles',
+    action='store_true',
+    dest='withpgoprofiles',
+    default=False,
+    help='Download PGO profiles for the build.')
 
 # Test-related options.
 parser.add_option(
@@ -912,17 +785,24 @@
     dest='cleanartifacts',
     default=False,
     help='Clean the artifacts output directory.')
-parser.add_option('--distrib-subdir', dest='distribsubdir',
-                  help='CEF distrib dir name, child of '+\
-                       'chromium/src/cef/binary_distrib',
-                  default='')
+parser.add_option(
+    '--distrib-subdir',
+    dest='distribsubdir',
+    default='',
+    help='CEF distrib dir name, child of chromium/src/cef/binary_distrib')
+parser.add_option(
+    '--distrib-subdir-suffix',
+    dest='distribsubdirsuffix',
+    default='',
+    help='CEF distrib dir name suffix, child of chromium/src/cef/binary_distrib'
+)
 
 (options, args) = parser.parse_args()
 
 if options.downloaddir is None:
   print("The --download-dir option is required.")
   parser.print_help(sys.stderr)
-  sys.exit()
+  sys.exit(1)
 
 # Opt into component-specific flags for later use.
 if options.noupdate:
@@ -933,15 +813,18 @@
 if options.runtests:
   options.buildtests = True
 
-if (options.nochromiumupdate and options.forceupdate) or \
-   (options.nocefupdate and options.forceupdate) or \
-   (options.nobuild and options.forcebuild) or \
-   (options.nodistrib and options.forcedistrib) or \
-   ((options.forceclean or options.forcecleandeps) and options.fastupdate) or \
-   (options.chromiumcheckout and options.chromiumchannel):
-  print("Invalid combination of options.")
-  parser.print_help(sys.stderr)
-  sys.exit()
+if (options.nochromiumupdate and options.forceupdate):
+    invalid_options_combination('--no-chromium-update', '--force-update')
+if (options.nocefupdate and options.forceupdate):
+    invalid_options_combination('--no-cef-update', '--force-update')
+if (options.nobuild and options.forcebuild):
+    invalid_options_combination('--no-build', '--force-build')
+if (options.nodistrib and options.forcedistrib):
+    invalid_options_combination('--no-distrib', '--force-distrib')
+if (options.forceclean and options.fastupdate):
+    invalid_options_combination('--force-clean', '--fast-update')
+if (options.forcecleandeps and options.fastupdate):
+    invalid_options_combination('--force-clean-deps', '--fast-update')
 
 if (options.noreleasebuild and \
      (options.minimaldistrib or options.minimaldistribonly or \
@@ -949,36 +832,36 @@
    (options.minimaldistribonly + options.clientdistribonly + options.sandboxdistribonly > 1):
   print('Invalid combination of options.')
   parser.print_help(sys.stderr)
-  sys.exit()
+  sys.exit(1)
 
 if options.x64build + options.armbuild + options.arm64build > 1:
   print('Invalid combination of options.')
   parser.print_help(sys.stderr)
-  sys.exit()
+  sys.exit(1)
 
 if (options.buildtests or options.runtests) and len(options.testtarget) == 0:
   print("A test target must be specified via --test-target.")
   parser.print_help(sys.stderr)
-  sys.exit()
+  sys.exit(1)
 
 # Operating system.
 if options.dryrun and options.dryrunplatform is not None:
   platform = options.dryrunplatform
-  if not platform in ['windows', 'macosx', 'linux']:
+  if not platform in ['windows', 'mac', 'linux']:
     print('Invalid dry-run-platform value: %s' % (platform))
-    sys.exit()
+    sys.exit(1)
 elif sys.platform == 'win32':
   platform = 'windows'
 elif sys.platform == 'darwin':
-  platform = 'macosx'
+  platform = 'mac'
 elif sys.platform.startswith('linux'):
   platform = 'linux'
 else:
   print('Unknown operating system platform')
-  sys.exit()
+  sys.exit(1)
 
 if options.clientdistrib or options.clientdistribonly:
-  if platform == 'linux':
+  if platform == 'linux' or (platform == 'windows' and options.arm64build):
     client_app = 'cefsimple'
   else:
     client_app = 'cefclient'
@@ -986,7 +869,7 @@
     print('A client distribution cannot be generated if --build-target ' +
           'excludes %s.' % client_app)
     parser.print_help(sys.stderr)
-    sys.exit()
+    sys.exit(1)
 
 # CEF branch.
 cef_branch = options.branch
@@ -996,13 +879,13 @@
   # Verify that the branch value is numeric.
   if not cef_branch.isdigit():
     print('Invalid branch value: %s' % cef_branch)
-    sys.exit()
+    sys.exit(1)
 
   # Verify the minimum supported branch number.
   if int(cef_branch) < 3071:
     print('The requested branch (%s) is too old to build using this tool. ' +
           'The minimum supported branch is 3071.' % cef_branch)
-    sys.exit()
+    sys.exit(1)
 
 # True if the requested branch is 3538 or newer.
 branch_is_3538_or_newer = (branch_is_master or int(cef_branch) >= 3538)
@@ -1019,34 +902,29 @@
   (not is_python2 or bool(int(os.environ.get('GCLIENT_PY3', '0')))):
   print('Python 3 is not supported with branch 3904 and older ' +
         '(set GCLIENT_PY3=0 and run with Python 2 executable).')
-  sys.exit()
+  sys.exit(1)
 
 if options.armbuild:
   if platform != 'linux':
     print('The ARM build option is only supported on Linux.')
-    sys.exit()
-
-if options.arm64build:
-  if platform != 'linux' and platform != 'windows':
-    print('The ARM64 build option is only supported on Linux and Windows.')
-    sys.exit()
+    sys.exit(1)
 
 deps_file = 'DEPS'
 
-if platform == 'macosx' and not options.x64build:
-  print('32-bit Mac OS X builds are not supported. ' +
-        'Add --x64-build flag to generate a 64-bit build.')
-  sys.exit()
+if platform == 'mac' and not (options.x64build or options.arm64build):
+  print('32-bit MacOS builds are not supported. ' +
+        'Add --x64-build or --arm64-build flag to generate a 64-bit build.')
+  sys.exit(1)
 
 # Platforms that build a cef_sandbox library.
 sandbox_lib_platforms = ['windows']
 if branch_is_3538_or_newer:
-  sandbox_lib_platforms.append('macosx')
+  sandbox_lib_platforms.append('mac')
 
 if not platform in sandbox_lib_platforms and (options.sandboxdistrib or
                                               options.sandboxdistribonly):
   print('The sandbox distribution is not supported on this platform.')
-  sys.exit()
+  sys.exit(1)
 
 # Options that force the sources to change.
 force_change = options.forceclean or options.forceupdate
@@ -1058,7 +936,7 @@
   print('--resave cannot be combined with options that modify or discard ' +
         'patches.')
   parser.print_help(sys.stderr)
-  sys.exit()
+  sys.exit(1)
 
 if platform == 'windows':
   # Avoid errors when the "vs_toolchain.py update" Chromium hook runs.
@@ -1259,6 +1137,9 @@
         "'managed': False,"+\
         "'name': 'src', "+\
         "'url': '" + chromium_url + "', "+\
+        "'custom_vars': {"+\
+          "'checkout_pgo_profiles': " + ('True' if options.withpgoprofiles else 'False') + ", "+\
+        "}, "+\
         "'custom_deps': {"+\
           "'build': None, "+\
           "'build/scripts/command_wrapper/bin': None, "+\
@@ -1309,11 +1190,6 @@
 chromium_compat_version = build_compat_versions['chromium_checkout']
 if len(options.chromiumcheckout) > 0:
   chromium_checkout = options.chromiumcheckout
-elif len(options.chromiumchannel) > 0:
-  target_distance = int(options.chromiumchanneldistance
-                       ) if len(options.chromiumchanneldistance) > 0 else 0
-  chromium_checkout = get_chromium_target_version(
-      channel=options.chromiumchannel, target_distance=target_distance)
 else:
   chromium_checkout = chromium_compat_version
 
@@ -1525,7 +1401,7 @@
 if options.runtests:
   if platform == 'windows':
     test_exe = '%s.exe' % options.testtarget
-  elif platform == 'macosx':
+  elif platform == 'mac':
     test_exe = '%s.app/Contents/MacOS/%s' % (options.testtarget,
                                              options.testtarget)
   elif platform == 'linux':
@@ -1620,6 +1496,8 @@
     # Override the subdirectory name of binary_distrib if the caller requested.
     if options.distribsubdir != '':
       path += ' --distrib-subdir=' + options.distribsubdir
+    if options.distribsubdirsuffix != '':
+      path += ' --distrib-subdir-suffix=' + options.distribsubdirsuffix
 
     # Create the distribution.
     run(path, cef_tools_dir, depot_tools_dir)
diff --git a/src/tools/cef_api_hash.py b/src/tools/cef_api_hash.py
index 2ef6237..39eefa0 100644
--- a/src/tools/cef_api_hash.py
+++ b/src/tools/cef_api_hash.py
@@ -15,6 +15,12 @@
 import itertools
 import hashlib
 
+# Determines string type for python 2 and python 3.
+if sys.version_info[0] == 3:
+  string_type = str
+else:
+  string_type = basestring
+
 
 class cef_api_hash:
   """ CEF API hash calculator """
@@ -29,15 +35,16 @@
     self.__debug_enabled = not (self.__debugdir is
                                 None) and len(self.__debugdir) > 0
 
-    self.platforms = ["windows", "macosx", "linux"]
+    self.platforms = ["windows", "mac", "linux"]
 
     self.platform_files = {
         # List of includes_win_capi from cef_paths2.gypi.
         "windows": [
+            "internal/cef_app_win.h",
             "internal/cef_types_win.h",
         ],
         # List of includes_mac_capi from cef_paths2.gypi.
-        "macosx": [
+        "mac": [
             "internal/cef_types_mac.h",
         ],
         # List of includes_linux_capi from cef_paths2.gypi.
@@ -58,6 +65,7 @@
         "internal/cef_export.h",
         "internal/cef_ptr.h",
         "internal/cef_string_wrappers.h",
+        "internal/cef_time_wrappers.h",
         "internal/cef_types_wrappers.h",
         # includes_win
         "cef_sandbox_win.h",
@@ -145,7 +153,7 @@
 
     # enums
     for m in re.finditer(
-        "\nenum\s+?(\w+)\s+?\{.*?\}\s*?;", content, flags=re.DOTALL):
+        "\ntypedef\s+?enum\s+?\{.*?\}\s+?(\w+)\s*?;", content, flags=re.DOTALL):
       object = {"name": m.group(1), "text": m.group(0).strip()}
       objects.append(object)
 
@@ -190,8 +198,16 @@
         os.path.join(self.__headerdir, filename)
         for filename in self.included_files
     ]
-    headers = itertools.chain(
-        headers, get_files(os.path.join(self.__headerdir, "capi", "*.h")))
+
+    capi_dir = os.path.join(self.__headerdir, "capi")
+    headers = itertools.chain(headers, get_files(os.path.join(capi_dir, "*.h")))
+
+    # Also include capi sub-directories.
+    for root, dirs, files in os.walk(capi_dir):
+      for name in dirs:
+        headers = itertools.chain(headers,
+                                  get_files(os.path.join(root, name, "*.h")))
+
     headers = itertools.chain(
         headers, get_files(os.path.join(self.__headerdir, "internal", "*.h")))
 
@@ -225,7 +241,7 @@
     outfile = os.path.join(self.__debugdir, filename)
     dir = os.path.dirname(outfile)
     make_dir(dir)
-    if not isinstance(content, basestring):
+    if not isinstance(content, string_type):
       content = "\n".join(content)
     write_file(outfile, content)
 
diff --git a/src/tools/cef_parser.py b/src/tools/cef_parser.py
index dd80aed..3e0e219 100644
--- a/src/tools/cef_parser.py
+++ b/src/tools/cef_parser.py
@@ -99,13 +99,7 @@
     line = data['line'].strip()
     pos = data['start']
     if len(line) == 0:
-      # check if the next previous line is a comment
-      prevdata = get_prev_line(body, pos)
-      prevline = prevdata['line'].strip()
-      if prevline[0:2] == '//' and prevline[0:3] != '///':
-        result.append(None)
-      else:
-        break
+      break
     # single line /*--cef()--*/
     elif line[0:2] == '/*' and line[-2:] == '*/':
       continue
@@ -119,9 +113,9 @@
       continue
     elif in_block_comment:
       continue
-    elif line[0:2] == '//':
+    elif line[0:3] == '///':
       # keep the comment line including any leading spaces
-      result.append(line[2:])
+      result.append(line[3:])
     else:
       break
 
@@ -132,15 +126,9 @@
 def validate_comment(file, name, comment):
   """ Validate the comment array returned by get_comment(). """
   # Verify that the comment contains beginning and ending '///' as required by
-  # CppDoc (the leading '//' from each line will already have been removed by
-  # the get_comment() logic). There may be additional comments proceeding the
-  # CppDoc block so we look at the quantity of lines equaling '/' and expect
-  # the last line to be '/'.
-  docct = 0
-  for line in comment:
-    if not line is None and len(line) > 0 and line == '/':
-      docct = docct + 1
-  if docct != 2 or len(comment) < 3 or comment[len(comment) - 1] != '/':
+  # Doxygen (the leading '///' from each line will already have been removed by
+  # the get_comment() logic).
+  if len(comment) < 3 or len(comment[0]) != 0 or len(comment[-1]) != 0:
     raise Exception('Missing or incorrect comment in %s for: %s' % \
         (file, name))
 
@@ -157,14 +145,13 @@
   hasemptyline = False
   for line in comment:
     # if the line starts with a leading space, remove that space
-    if not line is None and len(line) > 0 and line[0:1] == ' ':
+    if not line is None and len(line) > 0 and line[0] == ' ':
       line = line[1:]
       didremovespace = True
     else:
       didremovespace = False
 
-    if line is None or len(line) == 0 or line[0:1] == ' ' \
-        or line[0:1] == '/':
+    if line is None or len(line) == 0 or line[0] == ' ':
       # the previous paragraph, if any, has ended
       if len(wrapme) > 0:
         if not translate_map is None:
@@ -172,14 +159,14 @@
           for key in translate_keys:
             wrapme = wrapme.replace(key, translate_map[key])
         # output the previous paragraph
-        result += wrap_text(wrapme, indent + '// ', maxchars)
+        result += wrap_text(wrapme, indent + '/// ', maxchars)
         wrapme = ''
 
     if not line is None:
-      if len(line) == 0 or line[0:1] == ' ' or line[0:1] == '/':
+      if len(line) == 0 or line[0] == ' ':
         # blank lines or anything that's further indented should be
         # output as-is
-        result += indent + '//'
+        result += indent + '///'
         if len(line) > 0:
           if didremovespace:
             result += ' ' + line
@@ -200,7 +187,7 @@
       for key in translate_map.keys():
         wrapme = wrapme.replace(key, translate_map[key])
     # output the previous paragraph
-    result += wrap_text(wrapme, indent + '// ', maxchars)
+    result += wrap_text(wrapme, indent + '/// ', maxchars)
 
   if hasemptyline:
     # an empty line means a break between comments, so the comment is
@@ -247,7 +234,7 @@
               '\n  //   NOW: '+new['retval']
 
   if changed:
-    result += '\n  #pragma message("Warning: "__FILE__": '+new['name']+ \
+    result += '\n  #pragma message("Warning: " __FILE__ ": '+new['name']+ \
               ' prototype has changed")\n'
 
   return result
@@ -266,6 +253,9 @@
   if body.find('cef_api_hash(') > 0:
     result += '#include "include/cef_api_hash.h"\n'
 
+  if body.find('template_util::has_valid_size(') > 0:
+    result += '#include "libcef_dll/template_util.h"\n'
+
   # identify what CppToC classes are being used
   p = re.compile('([A-Za-z0-9_]{1,})CppToC')
   list = sorted(set(p.findall(body)))
@@ -354,8 +344,6 @@
 _cre_cfname = '([A-Za-z0-9_]{1,})'
 # regex for matching class and function names including path separators
 _cre_cfnameorpath = '([A-Za-z0-9_\/]{1,})'
-# regex for matching function return values
-_cre_retval = '([A-Za-z0-9_<>:,\*\&]{1,})'
 # regex for matching typedef value and name combination
 _cre_typedef = '([A-Za-z0-9_<>:,\*\&\s]{1,})'
 # regex for matching function return value and name combination
@@ -373,12 +361,12 @@
     'void': ['void', ''],
     'void*': ['void*', 'NULL'],
     'int': ['int', '0'],
-    'int16': ['int16', '0'],
-    'uint16': ['uint16', '0'],
-    'int32': ['int32', '0'],
-    'uint32': ['uint32', '0'],
-    'int64': ['int64', '0'],
-    'uint64': ['uint64', '0'],
+    'int16_t': ['int16_t', '0'],
+    'uint16_t': ['uint16_t', '0'],
+    'int32_t': ['int32_t', '0'],
+    'uint32_t': ['uint32_t', '0'],
+    'int64_t': ['int64_t', '0'],
+    'uint64_t': ['uint64_t', '0'],
     'double': ['double', '0'],
     'float': ['float', '0'],
     'float*': ['float*', 'NULL'],
@@ -391,21 +379,35 @@
     'char* const': ['char* const', 'NULL'],
     'cef_color_t': ['cef_color_t', '0'],
     'cef_json_parser_error_t': ['cef_json_parser_error_t', 'JSON_NO_ERROR'],
-    'cef_plugin_policy_t': ['cef_plugin_policy_t', 'PLUGIN_POLICY_ALLOW'],
-    'CefCursorHandle': ['cef_cursor_handle_t', 'kNullCursorHandle'],
+    'CefAudioParameters': ['cef_audio_parameters_t', 'CefAudioParameters()'],
+    'CefBaseTime': ['cef_basetime_t', 'CefBaseTime()'],
+    'CefBoxLayoutSettings': [
+        'cef_box_layout_settings_t', 'CefBoxLayoutSettings()'
+    ],
     'CefCompositionUnderline': [
         'cef_composition_underline_t', 'CefCompositionUnderline()'
     ],
-    'CefEventHandle': ['cef_event_handle_t', 'kNullEventHandle'],
-    'CefWindowHandle': ['cef_window_handle_t', 'kNullWindowHandle'],
-    'CefPoint': ['cef_point_t', 'CefPoint()'],
-    'CefRect': ['cef_rect_t', 'CefRect()'],
-    'CefSize': ['cef_size_t', 'CefSize()'],
-    'CefRange': ['cef_range_t', 'CefRange()'],
+    'CefCursorHandle': ['cef_cursor_handle_t', 'kNullCursorHandle'],
+    'CefCursorInfo': ['cef_cursor_info_t', 'CefCursorInfo()'],
     'CefDraggableRegion': ['cef_draggable_region_t', 'CefDraggableRegion()'],
+    'CefEventHandle': ['cef_event_handle_t', 'kNullEventHandle'],
+    'CefInsets': ['cef_insets_t', 'CefInsets()'],
+    'CefKeyEvent': ['cef_key_event_t', 'CefKeyEvent()'],
+    'CefMainArgs': ['cef_main_args_t', 'CefMainArgs()'],
+    'CefMouseEvent': ['cef_mouse_event_t', 'CefMouseEvent()'],
+    'CefPoint': ['cef_point_t', 'CefPoint()'],
+    'CefPopupFeatures': ['cef_popup_features_t', 'CefPopupFeatures()'],
+    'CefRange': ['cef_range_t', 'CefRange()'],
+    'CefRect': ['cef_rect_t', 'CefRect()'],
+    'CefScreenInfo': ['cef_screen_info_t', 'CefScreenInfo()'],
+    'CefSize': ['cef_size_t', 'CefSize()'],
+    'CefTouchEvent': ['cef_touch_event_t', 'CefTouchEvent()'],
+    'CefTouchHandleState': [
+        'cef_touch_handle_state_t', 'CefTouchHandleState()'
+    ],
     'CefThreadId': ['cef_thread_id_t', 'TID_UI'],
     'CefTime': ['cef_time_t', 'CefTime()'],
-    'CefAudioParameters': ['cef_audio_parameters_t', 'CefAudioParameters()']
+    'CefWindowHandle': ['cef_window_handle_t', 'kNullWindowHandle'],
 }
 
 
@@ -414,6 +416,10 @@
     return value, name, arguments and body. Ident must occur somewhere in
     the value.
     """
+  # Remove prefix from methods in CToCpp files.
+  content = content.replace('NO_SANITIZE("cfi-icall") ', '')
+  content = content.replace('NO_SANITIZE("cfi-icall")\n', '')
+
   # extract the functions
   find_regex = '\n' + _cre_func + '\((.*?)\)([A-Za-z0-9_\s]{0,})'
   if has_impl:
@@ -445,10 +451,11 @@
 
     # parse the arguments
     args = []
-    for v in argval.split(','):
-      v = v.strip()
-      if len(v) > 0:
-        args.append(v)
+    if argval != 'void':
+      for v in argval.split(','):
+        v = v.strip()
+        if len(v) > 0:
+          args.append(v)
 
     result.append({
         'retval': retval.strip(),
@@ -564,8 +571,12 @@
       filename = os.path.relpath(filepath, self.root_directory)
       filename = filename.replace('\\', '/')
 
-    # read the input file into memory
-    self.add_data(filename, read_file(filepath))
+    try:
+      # read the input file into memory
+      self.add_data(filename, read_file(filepath))
+    except Exception:
+      print('Exception while parsing %s' % filepath)
+      raise
 
   def add_data(self, filename, data):
     """ Add header file contents. """
@@ -1204,7 +1215,7 @@
     for cls in self.arguments:
       cls.get_types(list)
 
-  def get_capi_parts(self, defined_structs=[], prefix=None):
+  def get_capi_parts(self, defined_structs=[], isimpl=False, prefix=None):
     """ Return the parts of the C API function definition. """
     retval = ''
     dict = self.retval.get_type().get_capi(defined_structs)
@@ -1221,6 +1232,8 @@
         # const virtual functions get const self pointers
         str = 'const ' + str
       args.append(str)
+    elif not isimpl and len(self.arguments) == 0:
+      args.append('void')
 
     if len(self.arguments) > 0:
       for cls in self.arguments:
@@ -1241,9 +1254,9 @@
 
     return {'retval': retval, 'name': name, 'args': args}
 
-  def get_capi_proto(self, defined_structs=[], prefix=None):
+  def get_capi_proto(self, defined_structs=[], isimpl=False, prefix=None):
     """ Return the prototype of the C API function. """
-    parts = self.get_capi_parts(defined_structs, prefix)
+    parts = self.get_capi_parts(defined_structs, isimpl, prefix)
     result = parts['retval']+' '+parts['name']+ \
              '('+', '.join(parts['args'])+')'
     return result
@@ -2094,7 +2107,7 @@
   funcs = header.get_funcs()
   if len(funcs) > 0:
     for func in funcs:
-      result += func.get_capi_proto(defined_names) + ';\n'
+      result += func.get_capi_proto(defined_names, True) + ';\n'
     result += '\n'
 
   classes = header.get_classes()
@@ -2104,7 +2117,7 @@
     funcs = cls.get_virtual_funcs()
     if len(funcs) > 0:
       for func in funcs:
-        result += '\t' + func.get_capi_proto(defined_names) + ';\n'
+        result += '\t' + func.get_capi_proto(defined_names, True) + ';\n'
     result += '}\n\n'
 
     defined_names.append(cls.get_capi_name())
@@ -2113,6 +2126,6 @@
     funcs = cls.get_static_funcs()
     if len(funcs) > 0:
       for func in funcs:
-        result += func.get_capi_proto(defined_names) + ';\n'
+        result += func.get_capi_proto(defined_names, True) + ';\n'
       result += '\n'
   sys.stdout.write(result)
diff --git a/src/tools/cefbuilds/cef_html_builder.py b/src/tools/cefbuilds/cef_html_builder.py
deleted file mode 100644
index f8fbc2a..0000000
--- a/src/tools/cefbuilds/cef_html_builder.py
+++ /dev/null
@@ -1,323 +0,0 @@
-# Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
-# reserved. Use of this source code is governed by a BSD-style license that
-# can be found in the LICENSE file.
-
-from __future__ import absolute_import
-from __future__ import print_function
-from cef_json_builder import cef_json_builder
-import datetime
-import math
-import os
-import sys
-
-# Class used to build the cefbuilds HTML file. Generate an index.json file using
-# the cef_json_builder_example.py tool (or some other means) and then run:
-# > python cef_html_builder.py index.json index.html.in index.html
-#
-# Expected HTML template format is:
-#
-# Header
-# <section:platform_link>
-#  $platform_name$
-# </section:platform_link>
-# <section:platform>
-#   $platform_name$ Builds:
-#   <section:version>
-#     CEF version $cef_version$ Files:
-#     <section:file>
-#       File $file$ size $size$ sha1 $sha1$
-#     </section:file>
-#   </section:version>
-# </section:platform>
-# Footer
-#
-# Notes:
-# - The variables ("$key$") available in each section generally match the key
-#   names that exist in the JSON file for that section. Additional variables are
-#   exposed where needed.
-# - Some global variables like "$year$" will be replaced in the whole template
-#   before further parsing occurs.
-
-
-class cef_html_builder:
-  """ Class used to build the cefbuilds HTML file. """
-
-  def __init__(self, branding=''):
-    """ Create a new cef_html_builder object. """
-    self.clear()
-    self._branding = branding
-
-  def clear(self):
-    """ Clear the contents of this object. """
-    self._parts = {}
-    return
-
-  @staticmethod
-  def _token(key):
-    # Returns the token representation of |key|
-    return '$' + key + '$'
-
-  @staticmethod
-  def _section_tags(section):
-    # Returns the start and end tags for |section|
-    return ('<section:' + section + '>', '</section:' + section + '>')
-
-  @staticmethod
-  def _section_key(section):
-    # Returns the replacement key for |section|
-    return section + '_section'
-
-  @staticmethod
-  def _replace(str, key, value):
-    # Replaces all instances of |key| with |value| in |str|.
-    return str.replace(cef_html_builder._token(key), value)
-
-  @staticmethod
-  def _replace_all(str, dict):
-    for (key, value) in dict.items():
-      str = cef_html_builder._replace(str, key, value)
-    return str
-
-  @staticmethod
-  def _extract(str, section):
-    # Extracts the |section| region and replaces it with a token named
-    # "<section>_section".
-    (start_tag, end_tag) = cef_html_builder._section_tags(section)
-    start_pos = str.find(start_tag)
-    end_pos = str.rfind(end_tag)
-    if start_pos < 0 or end_pos < 0:
-      raise Exception('Failed to find section %s' % section)
-    top = str[:start_pos]
-    middle = str[start_pos + len(start_tag):end_pos]
-    bottom = str[end_pos + len(end_tag):]
-    return (
-        top + cef_html_builder._token(cef_html_builder._section_key(section)) +
-        bottom, middle)
-
-  def load(self, html_template):
-    """ Load the specified |html_template| string. """
-    self.clear()
-    root = html_template
-
-    # Extract the platform link section from root.
-    (root, platform_link) = self._extract(root, 'platform_link')
-
-    # Extract platform section from root.
-    (root, platform) = self._extract(root, 'platform')
-
-    # Extract version section from platform.
-    (platform, version) = self._extract(platform, 'version')
-
-    # Extract file section from version.
-    (version, file) = self._extract(version, 'file')
-
-    self._parts = {
-        'root': root,
-        'platform_link': platform_link,
-        'platform': platform,
-        'version': version,
-        'file': file
-    }
-
-  @staticmethod
-  def _get_platform_name(platform):
-    return {
-        'linux32': 'Linux 32-bit',
-        'linux64': 'Linux 64-bit',
-        'linuxarm': 'Linux ARM',
-        'linuxarm64': 'Linux ARM64',
-        'macosx64': 'Mac OS X 64-bit',
-        'windows32': 'Windows 32-bit',
-        'windows64': 'Windows 64-bit'
-    }[platform]
-
-  @staticmethod
-  def _get_type_name(type):
-    return {
-        'standard': 'Standard Distribution',
-        'minimal': 'Minimal Distribution',
-        'client': 'Sample Application',
-        'debug_symbols': 'Debug Symbols',
-        'release_symbols': 'Release Symbols'
-    }[type]
-
-  @staticmethod
-  def _get_date(date):
-    return date.strftime('%m/%d/%Y')
-
-  @staticmethod
-  def _get_file_size(size):
-    if (size == 0):
-      return '0B'
-    size_name = ('B', 'KB', 'MB', 'GB')
-    i = int(math.floor(math.log(size, 1024)))
-    p = math.pow(1024, i)
-    s = round(size / p, 2)
-    return '%.2f %s' % (s, size_name[i])
-
-  @staticmethod
-  def _get_cef_source_url(cef_version):
-    if cef_version.find('+chromium') > 0:
-      # New-style CEF version numbers include the Chromium version number.
-      # Example: 74.0.1+g62d140e+chromium-74.0.3729.6
-      chromium_version = cef_version[cef_version.rfind('-') + 1:]
-      branch = chromium_version.split('.')[2]
-    else:
-      branch = cef_version.split('.')[1]
-    return 'https://bitbucket.org/chromiumembedded/cef/get/%s.tar.bz2' % branch
-
-  @staticmethod
-  def _get_chromium_source_url(chromium_version):
-    if chromium_version == 'master':
-      return 'https://chromium.googlesource.com/chromium/src.git'
-    return 'https://gsdview.appspot.com/chromium-browser-official/chromium-%s.tar.xz' % chromium_version
-
-  @staticmethod
-  def _get_file_url(platform, cef_version, file):
-    return file['name'].replace('+', '%2B')
-
-  @staticmethod
-  def _get_sha1_url(platform, cef_version, file):
-    return cef_html_builder._get_file_url(platform, cef_version, file) + '.sha1'
-
-  @staticmethod
-  def _get_tooltip_text(platform, cef_version, file):
-    if platform.startswith('linux'):
-      sample_app = 'cefsimple'
-    else:
-      sample_app = 'cefclient'
-    return {
-        'standard':
-            'Standard binary distribution. Includes header files, libcef_dll_wrapper source code, binary files, CMake configuration files and source code for the cefclient and cefsimple sample applications. See the included README.txt file for usage and build requirements.',
-        'minimal':
-            'Minimal binary distribution. Includes header files, libcef_dll_wrapper source code, Release build binary files and CMake configuration files. Does not include Debug build binary files or sample application source code. See the included README.txt file for usage and build requirements.',
-        'client':
-            'Release build of the ' + sample_app +
-            ' sample application. See the included README.txt file for usage requirements.',
-        'debug_symbols':
-            'Debug build symbols. Must be extracted and placed next to the CEF Debug binary file with the same name and version.',
-        'release_symbols':
-            'Release build symbols. Must be extracted and placed next to the CEF Release binary file with the same name and version.'
-    }[file['type']]
-
-  def generate(self, json_builder):
-    """ Generate HTML output based on the contents of |json_builder|. """
-    if not isinstance(json_builder, cef_json_builder):
-      raise Exception('Invalid argument')
-
-    # Substitution values are augmented at each nesting level.
-    subs = {
-        'year': '2016',
-        'branding': self._branding,
-    }
-
-    # Substitute variables.
-    root_str = self._replace_all(self._parts['root'], subs)
-
-    platform_link_strs = []
-    platform_strs = []
-    for platform in json_builder.get_platforms():
-      subs['platform'] = platform
-      subs['platform_name'] = self._get_platform_name(platform)
-
-      # Substitute variables.
-      platform_link_str = self._replace_all(self._parts['platform_link'], subs)
-      platform_str = self._replace_all(self._parts['platform'], subs)
-
-      version_strs = []
-      for version in json_builder.get_versions(platform):
-        subs['cef_version'] = version['cef_version']
-        subs['chromium_version'] = version['chromium_version']
-        subs['last_modified'] = self._get_date(
-            version['files'][0]['last_modified'])
-        subs['cef_source_url'] = self._get_cef_source_url(
-            version['cef_version'])
-        subs['chromium_source_url'] = self._get_chromium_source_url(
-            version['chromium_version'])
-
-        # Substitute variables.
-        version_str = self._replace_all(self._parts['version'], subs)
-
-        file_strs = {}
-        for file in version['files']:
-          subs['last_modified'] = self._get_date(file['last_modified'])
-          subs['name'] = file['name']
-          subs['sha1'] = file['sha1']
-          subs['size'] = self._get_file_size(file['size'])
-          subs['type'] = file['type']
-          subs['type_name'] = self._get_type_name(file['type'])
-          subs['file_url'] = self._get_file_url(platform,
-                                                version['cef_version'], file)
-          subs['sha1_url'] = self._get_sha1_url(platform,
-                                                version['cef_version'], file)
-          subs['tooltip_text'] = self._get_tooltip_text(
-              platform, version['cef_version'], file)
-
-          # Substitute variables.
-          file_str = self._replace_all(self._parts['file'], subs)
-          file_strs[file['type']] = file_str
-
-        if len(file_strs) > 0:
-          # Always output file types in the same order.
-          file_out = ''
-          type_order = [
-              'standard', 'minimal', 'client', 'debug_symbols',
-              'release_symbols'
-          ]
-          for type in type_order:
-            if type in file_strs:
-              file_out = file_out + file_strs[type]
-
-          # Insert files.
-          version_str = self._replace(version_str,
-                                      self._section_key('file'), file_out)
-          version_strs.append(version_str)
-
-      if len(version_strs) > 0:
-        # Insert versions.
-        platform_str = self._replace(platform_str,
-                                     self._section_key('version'),
-                                     "".join(version_strs))
-        platform_strs.append(platform_str)
-        platform_link_strs.append(platform_link_str)
-
-    if len(platform_strs) > 0:
-      # Insert platforms.
-      root_str = self._replace(root_str,
-                               self._section_key('platform_link'),
-                               "".join(platform_link_strs))
-      root_str = self._replace(root_str,
-                               self._section_key('platform'),
-                               "".join(platform_strs))
-
-    return root_str
-
-
-# Program entry point.
-if __name__ == '__main__':
-  # Verify command-line arguments.
-  if len(sys.argv) < 4:
-    sys.stderr.write('Usage: %s <json_file_in> <html_file_in> <html_file_out>\n'
-                     % sys.argv[0])
-    sys.exit()
-
-  json_file_in = sys.argv[1]
-  html_file_in = sys.argv[2]
-  html_file_out = sys.argv[3]
-
-  # Create the HTML builder and load the HTML template.
-  print('--> Reading %s' % html_file_in)
-  html_builder = cef_html_builder()
-  with open(html_file_in, 'r') as f:
-    html_builder.load(f.read())
-
-  # Create the JSON builder and load the JSON file.
-  print('--> Reading %s' % json_file_in)
-  json_builder = cef_json_builder(silent=False)
-  with open(json_file_in, 'r') as f:
-    json_builder.load(f.read())
-
-  # Write the HTML output file.
-  print('--> Writing %s' % html_file_out)
-  with open(html_file_out, 'w') as f:
-    f.write(html_builder.generate(json_builder))
diff --git a/src/tools/cefbuilds/cef_json_builder.py b/src/tools/cefbuilds/cef_json_builder.py
index 6d41d3f..2ac6eb4 100644
--- a/src/tools/cefbuilds/cef_json_builder.py
+++ b/src/tools/cefbuilds/cef_json_builder.py
@@ -99,8 +99,8 @@
   @staticmethod
   def get_platforms():
     """ Returns the list of supported platforms. """
-    return ('linux32', 'linux64', 'linuxarm', 'linuxarm64', 'macosx64',
-            'windows32', 'windows64')
+    return ('linux32', 'linux64', 'linuxarm', 'linuxarm64', 'macosarm64', 'macosx64',
+            'windows32', 'windows64', 'windowsarm64')
 
   @staticmethod
   def get_distrib_types():
@@ -125,14 +125,12 @@
         bool(re.compile('^' + _chromium_version_regex + '$').match(version))
 
   @staticmethod
-  def get_file_name(version, platform, type):
+  def get_file_name(version, platform, type, channel='stable'):
     """ Returns the expected distribution file name excluding extension based on
         the input parameters. """
-    if type != 'standard':
-      type_str = '_' + type
-    else:
-      type_str = ''
-    return 'cef_binary_%s_%s%s' % (version, platform, type_str)
+    type_str = '_' + type if type != 'standard' else ''
+    channel_str = '_' + channel if channel != 'stable' else ''
+    return 'cef_binary_%s_%s%s%s' % (version, platform, channel_str, type_str)
 
   def clear(self):
     """ Clear the contents of this object. """
@@ -246,7 +244,8 @@
     # Validate the new data's structure.
     for platform in self._data.keys():
       if not platform in new_data:
-        self._print('load: Platform %s not found' % platform)
+        if not self._silent:
+          print('load: Platform %s not found' % platform)
         continue
       if not 'versions' in new_data[platform]:
         self._print('load: Missing platform key(s) for %s' % platform)
@@ -271,8 +270,8 @@
             self._print('load: Missing file key(s) for %s %s' %
                         (platform, version['cef_version']))
             continue
-          (expected_platform, expected_version,
-           expected_type) = self._parse_name(file['name'])
+          (expected_platform, expected_version, expected_type,
+           expected_channel) = self._parse_name(file['name'])
           if expected_platform != platform or \
               expected_version != version['cef_version'] or \
               expected_type != file['type']:
@@ -301,6 +300,8 @@
               'chromium_version':
                   self.set_chromium_version(version['cef_version'],
                                             version['chromium_version']),
+              'channel':
+                  version.get('channel', 'stable'),
               'files':
                   self._sort_files(valid_files)
           })
@@ -340,6 +341,7 @@
     del name_parts[0]
 
     type = None
+    channel = 'stable'
 
     # Might be '<version>_<platform>_[debug|release]_symbols'.
     if name_parts[-1] == 'symbols':
@@ -358,6 +360,11 @@
       type = 'client'
       del name_parts[-1]
 
+    # Might be '<version>_<platform>_beta'.
+    if name_parts[-1] == 'beta':
+      del name_parts[-1]
+      channel = 'beta'
+
     # Remainder must be '<version>_<platform>'.
     if len(name_parts) != 2:
       raise Exception('Invalid filename: %s' % name)
@@ -368,7 +375,7 @@
     version = name_parts[0]
     platform = name_parts[1]
 
-    return [platform, version, type]
+    return [platform, version, type, channel]
 
   @staticmethod
   def _validate_args(platform, version, type, size, last_modified, sha1):
@@ -397,7 +404,7 @@
         file is added or False if a file with the same |name| and |sha1|
         already exists. """
     # Parse the file name.
-    (platform, version, type) = self._parse_name(name)
+    (platform, version, type, channel) = self._parse_name(name)
 
     if not isinstance(size, int):
       size = int(size)
@@ -418,10 +425,11 @@
 
     if version_idx == -1:
       # Add a new version record.
-      self._print('add_file: Add %s %s' % (platform, version))
+      self._print('add_file: Add %s %s %s' % (platform, version, channel))
       self._data[platform]['versions'].append({
           'cef_version': version,
           'chromium_version': self.get_chromium_version(version),
+          'channel': channel,
           'files': []
       })
       version_idx = len(self._data[platform]['versions']) - 1
@@ -480,6 +488,7 @@
               result_obj['platform'] = platform
               result_obj['cef_version'] = version_obj['cef_version']
               result_obj['chromium_version'] = version_obj['chromium_version']
+              result_obj['channel'] = version_obj['channel']
               results.append(result_obj)
 
     return results
diff --git a/src/tools/cefbuilds/cef_json_builder_example.py b/src/tools/cefbuilds/cef_json_builder_example.py
index 1403edb..2033775 100644
--- a/src/tools/cefbuilds/cef_json_builder_example.py
+++ b/src/tools/cefbuilds/cef_json_builder_example.py
@@ -12,9 +12,6 @@
 # > python cef_json_builder_example.py add all 3.2704.1416.g185cd6c 51.0.2704.47
 #
 # See cef_json_builder.get_platforms() for the list of supported platforms.
-#
-# After creating an index.json file you can use the cef_html_builder.py tool to
-# create an HTML file.
 
 from __future__ import absolute_import
 from __future__ import print_function
diff --git a/src/tools/cefbuilds/cef_json_builder_test.py b/src/tools/cefbuilds/cef_json_builder_test.py
index 44eb756..f8080d8 100644
--- a/src/tools/cefbuilds/cef_json_builder_test.py
+++ b/src/tools/cefbuilds/cef_json_builder_test.py
@@ -76,9 +76,11 @@
                      platform='linux32',
                      version='3.2704.1414.g185cd6c',
                      type='standard',
+                     channel='stable',
                      attrib_idx=0,
                      shouldfail=False):
-    name = cef_json_builder.get_file_name(version, platform, type) + '.tar.gz'
+    name = cef_json_builder.get_file_name(version, platform, type,
+                                          channel) + '.tar.gz'
 
     # Some random attribute information. sha1 must be different to trigger replacement.
     attribs = [{
@@ -113,6 +115,7 @@
         'platform': platform,
         'last_modified': attribs[attrib_idx]['date_val'],
         'cef_version': version,
+        'channel': channel,
         'type': type,
         'size': attribs[attrib_idx]['size']
     }
@@ -127,10 +130,10 @@
     self.assertEqual(len(files), 0)
 
   # Test add/get of a single file with the specified type.
-  def _test_add_file(self, type):
+  def _test_add_file(self, type, channel='stable'):
     builder = cef_json_builder()
 
-    expected = self._add_test_file(builder, type=type)
+    expected = self._add_test_file(builder, type=type, channel=channel)
     self._verify_write_read(builder)
 
     files = builder.get_files()
@@ -157,6 +160,26 @@
   def test_add_release_symbols_file(self):
     self._test_add_file('release_symbols')
 
+  # Test add/get of a standard type file in beta channel.
+  def test_add_standard_file_beta(self):
+    self._test_add_file('standard', channel='beta')
+
+  # Test add/get of a minimal type file in beta channel.
+  def test_add_minimal_file_beta(self):
+    self._test_add_file('minimal', channel='beta')
+
+  # Test add/get of a client type file in beta channel.
+  def test_add_client_file_beta(self):
+    self._test_add_file('client', channel='beta')
+
+  # Test add/get of a debug_symbols type file in beta channel.
+  def test_add_debug_symbols_file_beta(self):
+    self._test_add_file('debug_symbols', channel='beta')
+
+  # Test add/get of a release_symbols type file in beta channel.
+  def test_add_release_symbols_file_beta(self):
+    self._test_add_file('release_symbols', channel='beta')
+
   # Test get_files() behavior with a single file.
   def test_get_files_single(self):
     # yapf: disable
diff --git a/src/tools/cefbuilds/index.html.in b/src/tools/cefbuilds/index.html.in
deleted file mode 100644
index 9b0adec..0000000
--- a/src/tools/cefbuilds/index.html.in
+++ /dev/null
@@ -1,178 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
-<head>
-  <title>CEF Automated Builds</title>
-  <meta name="author" content="The Chromium Embedded Framework Authors" />
-  <meta name="copyright" content="$year$ The Chromium Embedded Framework Authors. All rights reserved." />
-  <style type="text/css">
-    body {font-family: Verdana,Arial; font-size: 10pt}
-    table.top {border-spacing: 0; border: 0px; padding: 0px}
-    table.top td.logo {padding-right: 10px}
-    table.top td.header {font-size: 14pt; white-space: nowrap; padding-right: 10px}
-    table.top td.header .links {font-size: 10pt}
-    table.top td.branding {font-size: 8pt; white-space: nowrap; text-align: center}
-    table.top td.filters {font-size: 10pt}
-    table.list {border-spacing: 0; border: 0px; margin-left: 20px; font-size: 10pt}
-    table.list tr.topheader td {border-bottom: 1px solid black; padding: 5px; padding-top: 4px; font-size: 9pt}
-    table.list tr.toprow:nth-child(even) {color: #000; background: #FFF}
-    table.list tr.toprow:nth-child(odd) {color: #000; background: #DDD}
-    table.version {border-spacing: 0; border: 0px; padding: 4px 4px; font-size: 10pt}
-    table.version td.header {font-weight: bold; font-size: 9pt}
-    table.version td.links {font-size: 8pt}
-    table.files {border-spacing: 0; border: 0px; font-size: 10pt}
-    table.files td {padding-top: 5px; padding-left: 20px; font-size: 10pt; white-space: nowrap}
-    table.files td.first {padding-left: 0px;}
-    .text_header {font-size: 12pt; font-weight: bold}
-    .bullet {font-size: 8pt; vertical-align: top}
-    .footer {font-size: 8pt; text-align: center}
-    .tooltip {position: relative; display: inline-block; border-bottom: 1px dotted black}
-    .tooltip .tooltiptext {visibility: hidden; width: 500px; background-color: black; color: #FFF; text-align: left; border-radius: 6px; padding: 5px; position: absolute; z-index: 1; top: -5px; left: 105%}
-    .tooltip:hover .tooltiptext {visibility: visible;}
-    .tooltiptext {white-space: normal}
-  </style>
-  <script>
-    var version_filter = ''
-
-    // Show more rows and change related UI.
-    function show(platform, showmore) {
-      var more = document.getElementById(platform).getElementsByClassName('showmore')[0]
-      var less = document.getElementById(platform).getElementsByClassName('showless')[0]
-      var notes = document.getElementById(platform).getElementsByClassName('shownotes')[0]
-
-      var rows = document.getElementById(platform).getElementsByClassName('toprow')
-
-      // Number of rows we would like to display.
-      var desired_ct = showmore ? rows.length : 1
-      // Number of rows allowed by the version filter.
-      var allowed_ct = 0
-      // Number of rows actually displayed.
-      var displayed_ct = 0
-
-      for (var i = 0; i < rows.length; ++i) {
-        var version = rows[i].getAttribute('data-version')
-        var allow = (version_filter == '' || version.indexOf(version_filter) == 0)
-        var display = (allow && displayed_ct < desired_ct)
-        rows[i].style.display = (display ? '' : 'none')
-        rows[i].style.background = (displayed_ct % 2 == 0 ? '#FFF' : '#DDD')
-        allowed_ct += allow
-        displayed_ct += display
-      }
-
-      if (allowed_ct <= 1) {
-        // One or less rows. No need for controls.
-        more.style.display = 'none'
-        less.style.display = 'none'
-      } else if (showmore) {
-        more.style.display = 'none'
-        less.style.display = ''
-      } else {
-        less.style.display = 'none'
-        more.style.display = ''
-      }
-
-      var notes_str = ''
-      if (allowed_ct != rows.length) {
-        var hidden_ct = rows.length - allowed_ct
-        notes_str += '(' + hidden_ct + ' build' + (hidden_ct == 1 ? '' : 's') + ' hidden, <a href="#" onclick="resetVersionFilter(); return false;">reset filter</a> to restore)'
-      }
-      notes.innerHTML = notes_str
-      notes.style.display = (notes_str == '' ? 'none' : '')
-    }
-
-    // Shrink all lists on page load.
-    function shrinkAll() {
-      var platforms = document.getElementsByClassName('list')
-      for (var i = 0; i < platforms.length; ++i)
-        show(platforms[i].id, false)
-    }
-
-    // Only show rows that start with the version string.
-    function applyVersionFilter() {
-      version_filter = document.getElementById('version_filter').value
-      shrinkAll()
-    }
-    function resetVersionFilter() {
-      version_filter = ''
-      document.getElementById('version_filter').value = ''
-      shrinkAll()
-    }
-
-    function onLoad() {
-      document.getElementById('version_filter_div').style.display = ''
-      shrinkAll()
-    }
-  </script>
-</head>
-<body onload="onLoad()">
-  <table class="top">
-    <tr>
-      <td class="logo"><img width="66" height="50" alt="CEF Logo" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEIAAAAyCAIAAABnFJp+AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAABA0SURBVHjaYvz//z/D0AcAAcRCmfb/P3///fr997efv7///PPz9z9WZkZeLnZ+HnYONhZmJka6eQMggMjxxqsP3248fvPw5cdnb768/vjty4/ff//+//P3359//5gZGFlYmDjZWPi52cUEuWRE+DTkhFWlBVlZmGnqDYAAYiQ+UQFV3nv+4eCFh0euPv3689e/fwyszMzAMGcChjojEEDV/P8HhP///vv3G+izf/9ZWZgUJQR8LFQNVMS5OVhp5A2AACLWG1cfvl598PrtJ++AKYeNjZkV6HYkwMzwn4GR4R8DI9BvEL+AvQMm//3/9ecPkC0uwONlpuxtoQL1MVUBQAAR9sb7z9/XHr5x4OIjYB7g5GBhYgR5ABoBcAAxCeSN///AqQuUxv6CPAL0FFAtUBbIA8qaakhFOGoDkxl1vQEQQAS8cfPx20nrTz94+ZGHHZiCmKAOZmRAiQuw4K/ff4Hu5mRn5uFkF+bjFOBmA+ZyYD758/sfsAD48OXHqw9fP3z5CSRF+DkLgs2stGWp6A2AAMLnjd1n78/bceHbj98c7CzA8GSC+gHkbEY4G+iBP3+B+UNTTkRPURSYoaWEgR5hRSumgDHx4+ffZ+8+33j45tSN5+fvvvAxV0n0NGCjUtYHCCCc3th07ObUDWeADmJjZYImIFA0MDBCIJgPzMJ//zEoSPAH26qba0iBJIkD5++8mLLhtLGaZJafCVW8ARBA2L2x6sDV2VvPs7Iys7MwszAxg7MCKBODPAR2KzBmfv75A8wjiR56biZKLExMpFoMzCq7Tt8V4OWw1JKh3BsAAYTFG6duPK2YvRcoDExLwOIUiICuZAJHCTgmgAwmYGUnI8qT6GFgoiZJft35nwGYnYAlMuXeAAggdG88fPEho2/T5x9/2dlYgM4GeoAZFBmg7M0MyddMoMwgKchXEm6hIiXIMDgAQACh1+J7Lr++9/idmAgvsCYAlo+/gYn/PyhN/WNm/PsPFCe/f/wT4eeqi7OREuYFBijx+YGmACCAULxx6/nX2++ZdHU0bt+4wS/Ix8bGCvTJnz//GRn/gP3wDwiATabcIBOwHxggfgDG56NXHy/ffwUsl998+Pbj1x9gBAOTCh8Xm7gAt5aimL6yOLBEuvXk7dErj4FxC05PcM//h5QaYCHG33/+KUsJ2OsrQDLP1hO33336zoRc6EEt/A8s/r0t1IBNHogwQACxIJWJ/zecefnt5y81NaXnT5++f/tRSFiAhZUFXBcz/P377+9fhs/ff6V4G5mqS8N1Xbj7Yv6OC9cfvv7yHdiy+gevRkAGArX8/w+0aXaJj5Kk0JUHr/vXnOBgxd2KY2T4+uM30HEwb/xbuufSrcdvgSUNA2r+/Q+qpv4AyWhnXYgIQACxIEXFt6fvf7CzMbOxsenpaR87cvLTx898grzAsgqSf4CNWWCp4mepDlEPjKCNR2/O3XH+45efPJxsAjwcIKf/A9XWoLbUP1CMAHORvDi/rKgAUApYlfBwsLGzskC8Ca1HoQ0xBrANoDjiYEXUJFwcrECT0ZqVYIX/f7EwrT10zcNUWZiPCygAEECIUuLIzXdAD4KKzn//FBRkFBRkf/z4+eXTN2BCAgYwMK6A6STeXZ+THerzpXsu96w+AXSwKD83N7B6AVnGCKy5+bjZgV7i4mQDOvLj1x/K0kLIZRGoBcDEyMrKxAKq44HNYWYQBJYeQGvBBRcwFJBTECjNAdWzMLEBkxEIgIocRnB58+jlZ2D9A1EJEEBQN91/9e3yo88crOAWE7BsZfivraP28NHjXz9/AeOEX4AP2FzVUhA1UJGAqN9w9MbiPZeAjQ5gIgE66/uvP7ycbIGmysaqEkJ8XMAQ//bjz+sPX0/ffKYqI4TsB2DzBBi6wLB3N1G20Jb59esvOIChTUmgLRJCPMhhzwpu9gO1SonwRjlpA338D9bo/P37rxKsqAQIIKg3br34+vPfP3YmcLiAwv6fqLiQvoH2mdOX/vz+8+njF2BSAyZZSBPj7cdvK/ZfBYYOyA/MoHxpoCyR4K6njFz+8jMAk5OJutR/pKAF+gGYqIDx9vPPX2UZQXDFj7f8YWZmZ2UFFv1//v4HxrCtrhzQfVhVAgQQVPTB6+/A6gFU2QEjA9wIB3pXS1uFn58X2CX69u0nNxuTh6kKRPGhy4/efvrOzcEGVA2UlRDiLQo1V8ZRh8BLGWDwANMRKG2wMDIxEdVYBzUjWEFdGlDwMTLgacMCBBDIGz9+/X367gewCGGCpCjG/5D2EhcXh4am0t8/wO7CXyVxfmDLFKj4+6/f207eBsUDC7SpFeGoJQjO3/gBKEuAWgWgGpQZknbxV8zgUoGRGVzlgrXgqaIAAgiUqB6++f7h2x9gExDc8oM2wsFl0R91TcX7957ce/hMXkIAmouef3jx7iuw+ADmVWBUKEkKWhHXKAK6A+ILoHOAqeXp689X7r8Gln6QvAGqbcFllqYcsOxhh0cgOD+DqixQXwCYkVgZ4M2O/+DMxgpKZowAAQTyxp2XwAz5j4OdGdaQBfkG6CdgN4ebh8PKzuDB0peSwnwQzU/ffgaWTkzgoAFWFMDmLfGNIkZYWxlo1+HLjw9feQzpbf0H9bWA9RKoem1IsNdREIWVCJA+ASMw1F5/+Naw6DA4ZhjhnWQhXo6KSEtg/gEIIJA3Pnz7jT05MzD8/vNHQkpESVmaDeZWYPfjH6zEBzZ6gTmE6OYboryCpDFwJgSVs8BqEuwfaF8A0yFAhcC2xKuP3xnAYQfsXQL9DWwugNMOyGEAAQTyBrD1wATrTEBLaxBghLCAIhY2esLC0NT/H+iJf+Q3aSHNEEZQiv3/9/cfUHIBRgU4IoBZENzPRc/J0OoS1lcDuhzsChBHXJAbUjkCBBALpPXCwIDkCQYGRK//PyOwbyoswi8jDyuhmYElwD9QyIF9/vnbT6I9wQCNQgam33//6SmLqUoJ/f4LqZTBwyngrruoABdyhf0f6nlQCgfbCanzQT18YEtHRhSa1AECCOQNFibG/xDlUBWIOIV4Chjpf2CCQnyczODi+B8o1zI+ef0ZWPWyMBOTPUANlH/gcQdgvWGoLA5sShDhd1DCAHbR5ET5Mn2NgfkQHF0Qo/6L8EH9DBBAIG8AK29I+w9aaECiHymVAjV8+fUHwpYR4QPWLkCPMYF6IYz3n787feOpJRHjA//+gRqL0NAEpx4itEDHvf7+ATZpmeTF+XBVfwABBBIV52dnZISWerDGFwN0aAYcHMCcCCyRIRrkxPmtdKQ///gFGZL68+//4j1XXrz/QrjX+v8fsKUILKOBjL+g0PxPMB5AA3Z/oUnuD94hHIAAAnlDRRzYkGP+C26VgsIMpIERlilB6Q2YiV59+Q0slCGCnqYqwCLhNyhLMgAjBFgEd688ef/FBxyuQSQpYFr69Qfolf/gookwAHrjB9Cav//BRTG+ggUggECJSkKQXZSX7dWnn9BxPnCkAyse8PgZuFfDyPDh++8br74aSIF6S8AGIrA5tO/CQ2DTENTsYWa++/Rt9dz92goihioSylJCwE78p68/7z5/e/r6c0cDBRdjJYh//v4BlZLA4AKWHKdvPAOW3b9BQQO28T+4hQ8eofO2VJUUAlkE9MHPX7+BhQqooviDzxsAAcQC6QnICXM8ef+DAzRWCW1tAgvk/4yQMU1IYcJw89U3iDeAoCDE4v2XH2dvPxfi4QQNnjAxfPv5++iVJ8BKDdQxYgRVL1+///zw+QewxQrxBqREAo+D/gcWCUeuPDpw8SGkSPwHrvvAA40guwzVJCHe+A/u1fz8CYp3YLTg8QZAAEFzjJI4F7jz/Q8y6gopB+ClFihdMTI8//Tzxedf0PKKl7MqytZETerD1x+fvv349hPYDv4LKdy+/vj1GdiL+/MX2Jjl4+Z4/u4LWvICjer+BvUMgQUd0FgwArYambnYgZ0kUD+JGd7cYoQWMMBIA2rBkzkAAgjaUNeW4eHnYvkBmqD4D8keTH8hJS4jRDMwZf36/f/Eww8BOmIQLZLCPP1ZbsAO4KKdl159+ApMvozgBjLEvWBD/gGbTE9efwR6CVhJ/fr779P3Xxx//uFp20Lqvr+QbPCf4ev335+//QI17H//AfbxGXCXCgABBPWGABero5bQxrOv2Fn/Mf8DNr/BI2z/GJkgdS44zwOD7caLb5eFv+hK8kAaZsCWXpCtpr2Bwtlbz+48eQcMeKCtP3/9AeZ7YKDy83BICfMaKItDKlpteeGcABNgBwUSKv9RBgmQ67v/kuDxCqAhYQ5awB4B0BZg0gJWi8y4B/UAAggxTvX+6++OTXd//vnPyQHq2YB6mMDQZWGEegXUemcEJmxBLuZwI3F+ThZcxeRfUA3/n4mRCoNoxAOAAEJYBmyeuOuJgvLZH9DYOGgoBJTzIF1GWMnLyPj2y991F15//vEXV/sP3H+kqx+AACCAUOxz0hbWkuH59vMveDjnPzDT/gOX8f//wT0Dark8/fBr06U3X37+pYoLwJUJpUYBBBB6sLnrigKD8ycoQkCl+G8wAnX/QKU6KMUAsyE7E+P919+Xn3z56vNvCq3/8fvv9effGCmOPYAAQtevLM4VYioBLJSABdxvsGf+/PkPakH8BZV6v8FFOxABtT15/3PRkWcXH38m2+6XH3/tvf6ek5WZlZnSEVSAAMI+MbDo8LMTd94BS3BgIcMMnqRkgk2UQZsp/yBtnv+///3Tk+Fx0RES42Mn3i3ff/299fLbxcdfBLlYvPRFmCmeDQQIIOzeAAotO/ps//V3wFY5ZK6VCdwtRu4Z/gN3AYA15s9foMF9OUEOYyU+EyV+Ntx9WqBVwCz18O3Ppx9+AKNCnI/dTUeYk5UK5QFAAOGcbQJWhVvPv9p//S0wq4BGKEC9cyZ4L/M/uKr6D67jgJUVMIt+/wkqCsKsJDWkeIBphA0yFAhuyoCbEv+AhRuwmfzmy++vP/9++/VXnI/NTk1QgIuFKuUEQAARmMI8evP98mPPfv//z8XKzIjU0QV1nf/+h/QegNkG2NQDlgrSwhw+RqL/wVU4tKf3n+H3X1BZ9OMPuEHx9983kB/+a0lz26kKUHEZA0AAEZ5Qvv/q2+Zzr64++QKMC9A4MiOshw5qOTBC+lvAWoWZmcHDQERaiB3YhAPFALAVCOpeAxvn/4GuB3a6gIUSMB54OJmN5fm0JLmoOzECEEDETu8fuPZ296U3rz79YgANDcFzOhQAW9/ACsdWU+jb739/QL08UNYHVvnA5tyv36AU9Q28nERRhNNKhZ+LjfoLLwACiITFFkDXXHnyad/Vd3defAXP3TBAhiVBtTvTf1ttEX5O1l9/QGkN4oGfv4FNQ1AHiYudWUeaW02cC2cThmIAEECMpC5EAjr0wZtvQJ88evP9xcdf7z6DsqySBLeSBBfID+CeLbCjw87CxM3ODMzBEvzsUgJstIgBZAAQQIyUrKcC1oMvP/589uEnJ3jE8S9oMQwDJxsTMNR52YGdKbTRMxoCgABiHB7LwgACDACHKi6GTvcogQAAAABJRU5ErkJggg=="></td>
-      <td class="header" width="100%">
-        Chromium Embedded Framework (CEF) Automated Builds
-        <br/><span class="links">[
-          <a href="https://bitbucket.org/chromiumembedded/cef/">Project Page</a> |
-          <a href="http://www.magpcss.org/ceforum">Support Forum</a>
-        ]</span></td>
-      <td class="branding" rowspan="2" valign="top">
-        $branding$
-      </td>
-    </tr>
-    <tr>
-      <td class="filters" colspan="2">
-        <br/>
-        Builds:
-<section:platform_link>
-        <span class="bullet">&#9654;</span> <a href="#$platform$_builds">$platform_name$</a>
-</section:platform_link>
-        <br/><br/>
-        <div id="version_filter_div" style="display:none">
-          <div class="tooltip">Version Filter<span class="tooltiptext">Optionally filter builds by version number. The filter supports partial matching. For example, enter "3.2704" to only show builds for the 2704 branch.</span></div>:
-          <input type="text" size="20" id="version_filter"/><input type="button" value="Apply" onclick="applyVersionFilter();"/>
-        </div>
-      </td>
-    </tr>
-  </table>
-  <br/><br/>
-<section:platform>
-  <a name="$platform$_builds"></a>
-  <span class="text_header">$platform_name$ Builds</span>
-  <table id="$platform$" class="list" width="825">
-    <tr class="topheader">
-      <td>
-        <span class="showmore" style="display:none"><a href="#" onclick="show('$platform$', true); return false;">Show more builds</a></span>
-        <span class="showless" style="display:none"><a href="#" onclick="show('$platform$', false); return false;">Show less builds</a></span>
-        <span class="shownotes" style="display:none"></span>
-      </td>
-    </tr>
-<section:version>
-    <tr class="toprow" data-version="$cef_version$">
-      <td width="100%">
-        <table class="version" width="100%">
-          <tr>
-            <td class="header">$last_modified$ - CEF $cef_version$ / Chromium $chromium_version$</td>
-            <td class="links" align="right"><a href="$cef_source_url$">CEF source</a> | <a href="$chromium_source_url$">Chromium source</a></td>
-          </tr>
-          <tr>
-            <td colspan="2">
-              <table class="files" width="100%">
-<section:file>
-                <tr>
-                  <td class="first"><span class="bullet">&#9654;</span> <div class="tooltip">$type_name$<span class="tooltiptext">$tooltip_text$</span></div></td>
-                  <td width="100%"><a href="$file_url$">$name$</a></td>
-                  <td align="right">$size$</td>
-                  <td><a href="$sha1_url$">sha1</a></td>
-                </tr>
-</section:file>
-              </table>
-            </td>
-          </tr>
-        </table>
-      </td>
-    </tr>
-</section:version>
-  </table>
-  <br/>
-</section:platform>
-  <p class="footer">Copyright &copy; $year$ The Chromium Embedded Framework Authors. All rights reserved.</p>
-</body>
-</html>
diff --git a/src/tools/combine_libs.py b/src/tools/combine_libs.py
index ec3fb6c..3e7b115 100644
--- a/src/tools/combine_libs.py
+++ b/src/tools/combine_libs.py
@@ -30,11 +30,11 @@
   return output
 
 
-def CollectRemovals(remove_re, inputs):
+def CollectRemovals(remove_re, build_dir, inputs):
   '''Returns a list of all object files in inputs that match remove_re.'''
   removals = []
   for input in inputs:
-    output = Shell('lib.exe', '/list', input)
+    output = Shell('lib.exe', '/list', os.path.join(build_dir, input))
 
     for line in output:
       line = line.rstrip()
@@ -44,20 +44,20 @@
   return removals
 
 
-def CombineLibraries(output, remove_re, inputs):
+def CombineLibraries(build_dir, output, remove_re, inputs):
   '''Combines all the libraries and objects in inputs, while removing any
   object files that match remove_re.
   '''
   removals = []
   if remove_re:
-    removals = CollectRemovals(remove_re, inputs)
+    removals = CollectRemovals(remove_re, build_dir, inputs)
 
   if len(removals) > 0:
     print('Removals: ', removals)
 
   args = ['lib.exe', '/out:%s' % output]
   args += ['/remove:%s' % obj for obj in removals]
-  args += inputs
+  args += [os.path.join(build_dir, input) for input in inputs]
   Shell(*args)
 
 
@@ -72,6 +72,8 @@
 def GetOptionParser():
   parser = optparse.OptionParser(USAGE)
   parser.add_option(
+      '-b', '--build-dir', dest='build_dir', help='build directory')
+  parser.add_option(
       '-o', '--output', dest='output', help='write to this output library')
   parser.add_option(
       '-r',
@@ -86,6 +88,7 @@
   '''Main function for this script'''
   parser = GetOptionParser()
   (opt, args) = parser.parse_args()
+  build_dir = opt.build_dir
   output = opt.output
   remove = opt.remove
   if not output:
@@ -113,7 +116,7 @@
   if 'VS_UNICODE_OUTPUT' in os.environ:
     del os.environ['VS_UNICODE_OUTPUT']
 
-  CombineLibraries(output, remove_re, args)
+  CombineLibraries(build_dir, output, remove_re, args)
   return 0
 
 
diff --git a/src/tools/compile_ib_files.py b/src/tools/compile_ib_files.py
index eb4980a..d0b19b4 100644
--- a/src/tools/compile_ib_files.py
+++ b/src/tools/compile_ib_files.py
@@ -33,8 +33,8 @@
       os.path.abspath(args.output),
       os.path.abspath(args.input)
   ]
-  ibtool_section_re = re.compile(r'/\*.*\*/')
-  ibtool_re = re.compile(r'.*note:.*is clipping its content')
+  ibtool_section_re = re.compile(rb'/\*.*\*/')
+  ibtool_re = re.compile(rb'.*note:.*is clipping its content')
   try:
     stdout = subprocess.check_output(ibtool_args)
   except subprocess.CalledProcessError as e:
diff --git a/src/tools/crash_server.py b/src/tools/crash_server.py
index e10273e..a05e800 100644
--- a/src/tools/crash_server.py
+++ b/src/tools/crash_server.py
@@ -175,7 +175,6 @@
       size_str += self.rfile.read(1)

     # Remove the trailing "\r\n".

     size_str = size_str[:-2]

-    assert len(size_str) <= 4

     return int(size_str, 16)

 

   def _get_chunk_data(self, chunk_size):

diff --git a/src/tools/distrib/gtest/LICENSE b/src/tools/distrib/gtest/LICENSE
new file mode 100644
index 0000000..1941a11
--- /dev/null
+++ b/src/tools/distrib/gtest/LICENSE
@@ -0,0 +1,28 @@
+Copyright 2008, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/tests/gtest/README.cef.in b/src/tools/distrib/gtest/README.cef
similarity index 65%
rename from src/tests/gtest/README.cef.in
rename to src/tools/distrib/gtest/README.cef
index 5b0b472..2a10881 100644
--- a/src/tests/gtest/README.cef.in
+++ b/src/tools/distrib/gtest/README.cef
@@ -4,11 +4,14 @@
 License: BSD (see LICENSE file)
 
 Description:
-Fuzed (single header/source file) version of GoogleTest. Generated from the
-Chromium source checkout with the following command:
+Fuzed (single header/source file) version of GoogleTest. Generated from a
+Chromium version 93.0.4577.51 source checkout with the following command:
 
 cd /path/to/chromium/src/third_party/googletest/src/googletest/scripts
 ./fuse_gtest_files.py <out_directory>
 
+This script was removed from GTest in
+https://github.com/google/googletest/commit/47f819c3ca.
+
 Local Modifications:
 None.
diff --git a/src/tools/distrib/gtest/gtest-all.cc b/src/tools/distrib/gtest/gtest-all.cc
new file mode 100644
index 0000000..5aaebc6
--- /dev/null
+++ b/src/tools/distrib/gtest/gtest-all.cc
@@ -0,0 +1,12501 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Google C++ Testing and Mocking Framework (Google Test)
+//
+// Sometimes it's desirable to build Google Test by compiling a single file.
+// This file serves this purpose.
+
+// This line ensures that gtest.h can be compiled on its own, even
+// when it's fused.
+#include "gtest/gtest.h"
+
+// The following lines pull in the real gtest *.cc files.
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// The Google C++ Testing and Mocking Framework (Google Test)
+
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Utilities for testing Google Test itself and code that uses Google Test
+// (e.g. frameworks built on top of Google Test).
+
+// GOOGLETEST_CM0004 DO NOT DELETE
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
+
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+namespace testing {
+
+// This helper class can be used to mock out Google Test failure reporting
+// so that we can test Google Test or code that builds on Google Test.
+//
+// An object of this class appends a TestPartResult object to the
+// TestPartResultArray object given in the constructor whenever a Google Test
+// failure is reported. It can either intercept only failures that are
+// generated in the same thread that created this object or it can intercept
+// all generated failures. The scope of this mock object can be controlled with
+// the second argument to the two arguments constructor.
+class GTEST_API_ ScopedFakeTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  // The two possible mocking modes of this object.
+  enum InterceptMode {
+    INTERCEPT_ONLY_CURRENT_THREAD,  // Intercepts only thread local failures.
+    INTERCEPT_ALL_THREADS           // Intercepts all failures.
+  };
+
+  // The c'tor sets this object as the test part result reporter used
+  // by Google Test.  The 'result' parameter specifies where to report the
+  // results. This reporter will only catch failures generated in the current
+  // thread. DEPRECATED
+  explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
+
+  // Same as above, but you can choose the interception scope of this object.
+  ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
+                                   TestPartResultArray* result);
+
+  // The d'tor restores the previous test part result reporter.
+  ~ScopedFakeTestPartResultReporter() override;
+
+  // Appends the TestPartResult object to the TestPartResultArray
+  // received in the constructor.
+  //
+  // This method is from the TestPartResultReporterInterface
+  // interface.
+  void ReportTestPartResult(const TestPartResult& result) override;
+
+ private:
+  void Init();
+
+  const InterceptMode intercept_mode_;
+  TestPartResultReporterInterface* old_reporter_;
+  TestPartResultArray* const result_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
+};
+
+namespace internal {
+
+// A helper class for implementing EXPECT_FATAL_FAILURE() and
+// EXPECT_NONFATAL_FAILURE().  Its destructor verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring.  If that's not the case, a
+// non-fatal failure will be generated.
+class GTEST_API_ SingleFailureChecker {
+ public:
+  // The constructor remembers the arguments.
+  SingleFailureChecker(const TestPartResultArray* results,
+                       TestPartResult::Type type, const std::string& substr);
+  ~SingleFailureChecker();
+ private:
+  const TestPartResultArray* const results_;
+  const TestPartResult::Type type_;
+  const std::string substr_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+// A set of macros for testing Google Test assertions or code that's expected
+// to generate Google Test fatal failures.  It verifies that the given
+// statement will cause exactly one fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+//   - 'statement' cannot reference local non-static variables or
+//     non-static members of the current object.
+//   - 'statement' cannot return a value.
+//   - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works.  The AcceptsMacroThatExpandsToUnprotectedComma test in
+// gtest_unittest.cc will fail to compile if we do that.
+#define EXPECT_FATAL_FAILURE(statement, substr) \
+  do { \
+    class GTestExpectFatalFailureHelper {\
+     public:\
+      static void Execute() { statement; }\
+    };\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+      GTestExpectFatalFailureHelper::Execute();\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+  do { \
+    class GTestExpectFatalFailureHelper {\
+     public:\
+      static void Execute() { statement; }\
+    };\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ALL_THREADS, &gtest_failures);\
+      GTestExpectFatalFailureHelper::Execute();\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+// A macro for testing Google Test assertions or code that's expected to
+// generate Google Test non-fatal failures.  It asserts that the given
+// statement will cause exactly one non-fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// 'statement' is allowed to reference local variables and members of
+// the current object.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+//   - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works.  If we do that, the code won't compile when the user gives
+// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
+// expands to code containing an unprotected comma.  The
+// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
+// catches that.
+//
+// For the same reason, we have to write
+//   if (::testing::internal::AlwaysTrue()) { statement; }
+// instead of
+//   GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+// to avoid an MSVC warning on unreachable code.
+#define EXPECT_NONFATAL_FAILURE(statement, substr) \
+  do {\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+        (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+      if (::testing::internal::AlwaysTrue()) { statement; }\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+  do {\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+        (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
+          &gtest_failures);\
+      if (::testing::internal::AlwaysTrue()) { statement; }\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include <algorithm>
+#include <chrono>  // NOLINT
+#include <cmath>
+#include <cstdint>
+#include <iomanip>
+#include <limits>
+#include <list>
+#include <map>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <vector>
+
+#if GTEST_OS_LINUX
+
+# include <fcntl.h>  // NOLINT
+# include <limits.h>  // NOLINT
+# include <sched.h>  // NOLINT
+// Declares vsnprintf().  This header is not available on Windows.
+# include <strings.h>  // NOLINT
+# include <sys/mman.h>  // NOLINT
+# include <sys/time.h>  // NOLINT
+# include <unistd.h>  // NOLINT
+# include <string>
+
+#elif GTEST_OS_ZOS
+# include <sys/time.h>  // NOLINT
+
+// On z/OS we additionally need strings.h for strcasecmp.
+# include <strings.h>  // NOLINT
+
+#elif GTEST_OS_WINDOWS_MOBILE  // We are on Windows CE.
+
+# include <windows.h>  // NOLINT
+# undef min
+
+#elif GTEST_OS_WINDOWS  // We are on Windows proper.
+
+# include <windows.h>  // NOLINT
+# undef min
+
+#ifdef _MSC_VER
+# include <crtdbg.h>  // NOLINT
+#endif
+
+# include <io.h>  // NOLINT
+# include <sys/timeb.h>  // NOLINT
+# include <sys/types.h>  // NOLINT
+# include <sys/stat.h>  // NOLINT
+
+# if GTEST_OS_WINDOWS_MINGW
+#  include <sys/time.h>  // NOLINT
+# endif  // GTEST_OS_WINDOWS_MINGW
+
+#else
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+# include <sys/time.h>  // NOLINT
+# include <unistd.h>  // NOLINT
+
+#endif  // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+# include <stdexcept>
+#endif
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h>  // NOLINT
+# include <netdb.h>  // NOLINT
+# include <sys/socket.h>  // NOLINT
+# include <sys/types.h>  // NOLINT
+#endif
+
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Utility functions and classes used by the Google C++ testing framework.//
+// This file contains purely Google Test's internal implementation.  Please
+// DO NOT #INCLUDE IT IN A USER PROGRAM.
+
+#ifndef GOOGLETEST_SRC_GTEST_INTERNAL_INL_H_
+#define GOOGLETEST_SRC_GTEST_INTERNAL_INL_H_
+
+#ifndef _WIN32_WCE
+# include <errno.h>
+#endif  // !_WIN32_WCE
+#include <stddef.h>
+#include <stdlib.h>  // For strtoll/_strtoul64/malloc/free.
+#include <string.h>  // For memmove.
+
+#include <algorithm>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <vector>
+
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h>  // NOLINT
+# include <netdb.h>  // NOLINT
+#endif
+
+#if GTEST_OS_WINDOWS
+# include <windows.h>  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+namespace testing {
+
+// Declares the flags.
+//
+// We don't want the users to modify this flag in the code, but want
+// Google Test's own unit tests to be able to access it. Therefore we
+// declare it here as opposed to in gtest.h.
+GTEST_DECLARE_bool_(death_test_use_fork);
+
+namespace internal {
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library.  This is solely for testing GetTestTypeId().
+GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest;
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests";
+const char kBreakOnFailureFlag[] = "break_on_failure";
+const char kCatchExceptionsFlag[] = "catch_exceptions";
+const char kColorFlag[] = "color";
+const char kFailFast[] = "fail_fast";
+const char kFilterFlag[] = "filter";
+const char kListTestsFlag[] = "list_tests";
+const char kOutputFlag[] = "output";
+const char kBriefFlag[] = "brief";
+const char kPrintTimeFlag[] = "print_time";
+const char kPrintUTF8Flag[] = "print_utf8";
+const char kRandomSeedFlag[] = "random_seed";
+const char kRepeatFlag[] = "repeat";
+const char kShuffleFlag[] = "shuffle";
+const char kStackTraceDepthFlag[] = "stack_trace_depth";
+const char kStreamResultToFlag[] = "stream_result_to";
+const char kThrowOnFailureFlag[] = "throw_on_failure";
+const char kFlagfileFlag[] = "flagfile";
+
+// A valid random seed must be in [1, kMaxRandomSeed].
+const int kMaxRandomSeed = 99999;
+
+// g_help_flag is true if and only if the --help flag or an equivalent form
+// is specified on the command line.
+GTEST_API_ extern bool g_help_flag;
+
+// Returns the current time in milliseconds.
+GTEST_API_ TimeInMillis GetTimeInMillis();
+
+// Returns true if and only if Google Test should use colors in the output.
+GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
+
+// Formats the given time in milliseconds as seconds.
+GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms);
+
+// Converts the given time in milliseconds to a date string in the ISO 8601
+// format, without the timezone information.  N.B.: due to the use the
+// non-reentrant localtime() function, this function is not thread safe.  Do
+// not use it in any code that can be called from multiple threads.
+GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms);
+
+// Parses a string for an Int32 flag, in the form of "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+GTEST_API_ bool ParseInt32Flag(
+    const char* str, const char* flag, int32_t* value);
+
+// Returns a random seed in range [1, kMaxRandomSeed] based on the
+// given --gtest_random_seed flag value.
+inline int GetRandomSeedFromFlag(int32_t random_seed_flag) {
+  const unsigned int raw_seed = (random_seed_flag == 0) ?
+      static_cast<unsigned int>(GetTimeInMillis()) :
+      static_cast<unsigned int>(random_seed_flag);
+
+  // Normalizes the actual seed to range [1, kMaxRandomSeed] such that
+  // it's easy to type.
+  const int normalized_seed =
+      static_cast<int>((raw_seed - 1U) %
+                       static_cast<unsigned int>(kMaxRandomSeed)) + 1;
+  return normalized_seed;
+}
+
+// Returns the first valid random seed after 'seed'.  The behavior is
+// undefined if 'seed' is invalid.  The seed after kMaxRandomSeed is
+// considered to be 1.
+inline int GetNextRandomSeed(int seed) {
+  GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed)
+      << "Invalid random seed " << seed << " - must be in [1, "
+      << kMaxRandomSeed << "].";
+  const int next_seed = seed + 1;
+  return (next_seed > kMaxRandomSeed) ? 1 : next_seed;
+}
+
+// This class saves the values of all Google Test flags in its c'tor, and
+// restores them in its d'tor.
+class GTestFlagSaver {
+ public:
+  // The c'tor.
+  GTestFlagSaver() {
+    also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests);
+    break_on_failure_ = GTEST_FLAG(break_on_failure);
+    catch_exceptions_ = GTEST_FLAG(catch_exceptions);
+    color_ = GTEST_FLAG(color);
+    death_test_style_ = GTEST_FLAG(death_test_style);
+    death_test_use_fork_ = GTEST_FLAG(death_test_use_fork);
+    fail_fast_ = GTEST_FLAG(fail_fast);
+    filter_ = GTEST_FLAG(filter);
+    internal_run_death_test_ = GTEST_FLAG(internal_run_death_test);
+    list_tests_ = GTEST_FLAG(list_tests);
+    output_ = GTEST_FLAG(output);
+    brief_ = GTEST_FLAG(brief);
+    print_time_ = GTEST_FLAG(print_time);
+    print_utf8_ = GTEST_FLAG(print_utf8);
+    random_seed_ = GTEST_FLAG(random_seed);
+    repeat_ = GTEST_FLAG(repeat);
+    shuffle_ = GTEST_FLAG(shuffle);
+    stack_trace_depth_ = GTEST_FLAG(stack_trace_depth);
+    stream_result_to_ = GTEST_FLAG(stream_result_to);
+    throw_on_failure_ = GTEST_FLAG(throw_on_failure);
+  }
+
+  // The d'tor is not virtual.  DO NOT INHERIT FROM THIS CLASS.
+  ~GTestFlagSaver() {
+    GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_;
+    GTEST_FLAG(break_on_failure) = break_on_failure_;
+    GTEST_FLAG(catch_exceptions) = catch_exceptions_;
+    GTEST_FLAG(color) = color_;
+    GTEST_FLAG(death_test_style) = death_test_style_;
+    GTEST_FLAG(death_test_use_fork) = death_test_use_fork_;
+    GTEST_FLAG(filter) = filter_;
+    GTEST_FLAG(fail_fast) = fail_fast_;
+    GTEST_FLAG(internal_run_death_test) = internal_run_death_test_;
+    GTEST_FLAG(list_tests) = list_tests_;
+    GTEST_FLAG(output) = output_;
+    GTEST_FLAG(brief) = brief_;
+    GTEST_FLAG(print_time) = print_time_;
+    GTEST_FLAG(print_utf8) = print_utf8_;
+    GTEST_FLAG(random_seed) = random_seed_;
+    GTEST_FLAG(repeat) = repeat_;
+    GTEST_FLAG(shuffle) = shuffle_;
+    GTEST_FLAG(stack_trace_depth) = stack_trace_depth_;
+    GTEST_FLAG(stream_result_to) = stream_result_to_;
+    GTEST_FLAG(throw_on_failure) = throw_on_failure_;
+  }
+
+ private:
+  // Fields for saving the original values of flags.
+  bool also_run_disabled_tests_;
+  bool break_on_failure_;
+  bool catch_exceptions_;
+  std::string color_;
+  std::string death_test_style_;
+  bool death_test_use_fork_;
+  bool fail_fast_;
+  std::string filter_;
+  std::string internal_run_death_test_;
+  bool list_tests_;
+  std::string output_;
+  bool brief_;
+  bool print_time_;
+  bool print_utf8_;
+  int32_t random_seed_;
+  int32_t repeat_;
+  bool shuffle_;
+  int32_t stack_trace_depth_;
+  std::string stream_result_to_;
+  bool throw_on_failure_;
+} GTEST_ATTRIBUTE_UNUSED_;
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted
+// to "(Invalid Unicode 0xXXXXXXXX)".
+GTEST_API_ std::string CodePointToUtf8(uint32_t code_point);
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+//   UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin)
+//   UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+GTEST_API_ std::string WideStringToUtf8(const wchar_t* str, int num_chars);
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded();
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (e.g., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+GTEST_API_ bool ShouldShard(const char* total_shards_str,
+                            const char* shard_index_str,
+                            bool in_subprocess_for_death_test);
+
+// Parses the environment variable var as a 32-bit integer. If it is unset,
+// returns default_val. If it is not a 32-bit integer, prints an error and
+// and aborts.
+GTEST_API_ int32_t Int32FromEnvOrDie(const char* env_var, int32_t default_val);
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true if and only if the test should be run on this shard. The test id
+// is some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+GTEST_API_ bool ShouldRunTestOnShard(
+    int total_shards, int shard_index, int test_id);
+
+// STL container utilities.
+
+// Returns the number of elements in the given container that satisfy
+// the given predicate.
+template <class Container, typename Predicate>
+inline int CountIf(const Container& c, Predicate predicate) {
+  // Implemented as an explicit loop since std::count_if() in libCstd on
+  // Solaris has a non-standard signature.
+  int count = 0;
+  for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) {
+    if (predicate(*it))
+      ++count;
+  }
+  return count;
+}
+
+// Applies a function/functor to each element in the container.
+template <class Container, typename Functor>
+void ForEach(const Container& c, Functor functor) {
+  std::for_each(c.begin(), c.end(), functor);
+}
+
+// Returns the i-th element of the vector, or default_value if i is not
+// in range [0, v.size()).
+template <typename E>
+inline E GetElementOr(const std::vector<E>& v, int i, E default_value) {
+  return (i < 0 || i >= static_cast<int>(v.size())) ? default_value
+                                                    : v[static_cast<size_t>(i)];
+}
+
+// Performs an in-place shuffle of a range of the vector's elements.
+// 'begin' and 'end' are element indices as an STL-style range;
+// i.e. [begin, end) are shuffled, where 'end' == size() means to
+// shuffle to the end of the vector.
+template <typename E>
+void ShuffleRange(internal::Random* random, int begin, int end,
+                  std::vector<E>* v) {
+  const int size = static_cast<int>(v->size());
+  GTEST_CHECK_(0 <= begin && begin <= size)
+      << "Invalid shuffle range start " << begin << ": must be in range [0, "
+      << size << "].";
+  GTEST_CHECK_(begin <= end && end <= size)
+      << "Invalid shuffle range finish " << end << ": must be in range ["
+      << begin << ", " << size << "].";
+
+  // Fisher-Yates shuffle, from
+  // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
+  for (int range_width = end - begin; range_width >= 2; range_width--) {
+    const int last_in_range = begin + range_width - 1;
+    const int selected =
+        begin +
+        static_cast<int>(random->Generate(static_cast<uint32_t>(range_width)));
+    std::swap((*v)[static_cast<size_t>(selected)],
+              (*v)[static_cast<size_t>(last_in_range)]);
+  }
+}
+
+// Performs an in-place shuffle of the vector's elements.
+template <typename E>
+inline void Shuffle(internal::Random* random, std::vector<E>* v) {
+  ShuffleRange(random, 0, static_cast<int>(v->size()), v);
+}
+
+// A function for deleting an object.  Handy for being used as a
+// functor.
+template <typename T>
+static void Delete(T* x) {
+  delete x;
+}
+
+// A predicate that checks the key of a TestProperty against a known key.
+//
+// TestPropertyKeyIs is copyable.
+class TestPropertyKeyIs {
+ public:
+  // Constructor.
+  //
+  // TestPropertyKeyIs has NO default constructor.
+  explicit TestPropertyKeyIs(const std::string& key) : key_(key) {}
+
+  // Returns true if and only if the test name of test property matches on key_.
+  bool operator()(const TestProperty& test_property) const {
+    return test_property.key() == key_;
+  }
+
+ private:
+  std::string key_;
+};
+
+// Class UnitTestOptions.
+//
+// This class contains functions for processing options the user
+// specifies when running the tests.  It has only static members.
+//
+// In most cases, the user can specify an option using either an
+// environment variable or a command line flag.  E.g. you can set the
+// test filter using either GTEST_FILTER or --gtest_filter.  If both
+// the variable and the flag are present, the latter overrides the
+// former.
+class GTEST_API_ UnitTestOptions {
+ public:
+  // Functions for processing the gtest_output flag.
+
+  // Returns the output format, or "" for normal printed output.
+  static std::string GetOutputFormat();
+
+  // Returns the absolute path of the requested output file, or the
+  // default (test_detail.xml in the original working directory) if
+  // none was explicitly specified.
+  static std::string GetAbsolutePathToOutputFile();
+
+  // Functions for processing the gtest_filter flag.
+
+  // Returns true if and only if the user-specified filter matches the test
+  // suite name and the test name.
+  static bool FilterMatchesTest(const std::string& test_suite_name,
+                                const std::string& test_name);
+
+#if GTEST_OS_WINDOWS
+  // Function for supporting the gtest_catch_exception flag.
+
+  // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
+  // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+  // This function is useful as an __except condition.
+  static int GTestShouldProcessSEH(DWORD exception_code);
+#endif  // GTEST_OS_WINDOWS
+
+  // Returns true if "name" matches the ':' separated list of glob-style
+  // filters in "filter".
+  static bool MatchesFilter(const std::string& name, const char* filter);
+};
+
+// Returns the current application's name, removing directory path if that
+// is present.  Used by UnitTestOptions::GetOutputFile.
+GTEST_API_ FilePath GetCurrentExecutableName();
+
+// The role interface for getting the OS stack trace as a string.
+class OsStackTraceGetterInterface {
+ public:
+  OsStackTraceGetterInterface() {}
+  virtual ~OsStackTraceGetterInterface() {}
+
+  // Returns the current OS stack trace as an std::string.  Parameters:
+  //
+  //   max_depth  - the maximum number of stack frames to be included
+  //                in the trace.
+  //   skip_count - the number of top frames to be skipped; doesn't count
+  //                against max_depth.
+  virtual std::string CurrentStackTrace(int max_depth, int skip_count) = 0;
+
+  // UponLeavingGTest() should be called immediately before Google Test calls
+  // user code. It saves some information about the current stack that
+  // CurrentStackTrace() will use to find and hide Google Test stack frames.
+  virtual void UponLeavingGTest() = 0;
+
+  // This string is inserted in place of stack frames that are part of
+  // Google Test's implementation.
+  static const char* const kElidedFramesMarker;
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface);
+};
+
+// A working implementation of the OsStackTraceGetterInterface interface.
+class OsStackTraceGetter : public OsStackTraceGetterInterface {
+ public:
+  OsStackTraceGetter() {}
+
+  std::string CurrentStackTrace(int max_depth, int skip_count) override;
+  void UponLeavingGTest() override;
+
+ private:
+#if GTEST_HAS_ABSL
+  Mutex mutex_;  // Protects all internal state.
+
+  // We save the stack frame below the frame that calls user code.
+  // We do this because the address of the frame immediately below
+  // the user code changes between the call to UponLeavingGTest()
+  // and any calls to the stack trace code from within the user code.
+  void* caller_frame_ = nullptr;
+#endif  // GTEST_HAS_ABSL
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter);
+};
+
+// Information about a Google Test trace point.
+struct TraceInfo {
+  const char* file;
+  int line;
+  std::string message;
+};
+
+// This is the default global test part result reporter used in UnitTestImpl.
+// This class should only be used by UnitTestImpl.
+class DefaultGlobalTestPartResultReporter
+  : public TestPartResultReporterInterface {
+ public:
+  explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
+  // Implements the TestPartResultReporterInterface. Reports the test part
+  // result in the current test.
+  void ReportTestPartResult(const TestPartResult& result) override;
+
+ private:
+  UnitTestImpl* const unit_test_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter);
+};
+
+// This is the default per thread test part result reporter used in
+// UnitTestImpl. This class should only be used by UnitTestImpl.
+class DefaultPerThreadTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test);
+  // Implements the TestPartResultReporterInterface. The implementation just
+  // delegates to the current global test part result reporter of *unit_test_.
+  void ReportTestPartResult(const TestPartResult& result) override;
+
+ private:
+  UnitTestImpl* const unit_test_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter);
+};
+
+// The private implementation of the UnitTest class.  We don't protect
+// the methods under a mutex, as this class is not accessible by a
+// user and the UnitTest class that delegates work to this class does
+// proper locking.
+class GTEST_API_ UnitTestImpl {
+ public:
+  explicit UnitTestImpl(UnitTest* parent);
+  virtual ~UnitTestImpl();
+
+  // There are two different ways to register your own TestPartResultReporter.
+  // You can register your own repoter to listen either only for test results
+  // from the current thread or for results from all threads.
+  // By default, each per-thread test result repoter just passes a new
+  // TestPartResult to the global test result reporter, which registers the
+  // test part result for the currently running test.
+
+  // Returns the global test part result reporter.
+  TestPartResultReporterInterface* GetGlobalTestPartResultReporter();
+
+  // Sets the global test part result reporter.
+  void SetGlobalTestPartResultReporter(
+      TestPartResultReporterInterface* reporter);
+
+  // Returns the test part result reporter for the current thread.
+  TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread();
+
+  // Sets the test part result reporter for the current thread.
+  void SetTestPartResultReporterForCurrentThread(
+      TestPartResultReporterInterface* reporter);
+
+  // Gets the number of successful test suites.
+  int successful_test_suite_count() const;
+
+  // Gets the number of failed test suites.
+  int failed_test_suite_count() const;
+
+  // Gets the number of all test suites.
+  int total_test_suite_count() const;
+
+  // Gets the number of all test suites that contain at least one test
+  // that should run.
+  int test_suite_to_run_count() const;
+
+  // Gets the number of successful tests.
+  int successful_test_count() const;
+
+  // Gets the number of skipped tests.
+  int skipped_test_count() const;
+
+  // Gets the number of failed tests.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests that will be reported in the XML report.
+  int reportable_disabled_test_count() const;
+
+  // Gets the number of disabled tests.
+  int disabled_test_count() const;
+
+  // Gets the number of tests to be printed in the XML report.
+  int reportable_test_count() const;
+
+  // Gets the number of all tests.
+  int total_test_count() const;
+
+  // Gets the number of tests that should run.
+  int test_to_run_count() const;
+
+  // Gets the time of the test program start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp() const { return start_timestamp_; }
+
+  // Gets the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns true if and only if the unit test passed (i.e. all test suites
+  // passed).
+  bool Passed() const { return !Failed(); }
+
+  // Returns true if and only if the unit test failed (i.e. some test suite
+  // failed or something outside of all tests failed).
+  bool Failed() const {
+    return failed_test_suite_count() > 0 || ad_hoc_test_result()->Failed();
+  }
+
+  // Gets the i-th test suite among all the test suites. i can range from 0 to
+  // total_test_suite_count() - 1. If i is not in that range, returns NULL.
+  const TestSuite* GetTestSuite(int i) const {
+    const int index = GetElementOr(test_suite_indices_, i, -1);
+    return index < 0 ? nullptr : test_suites_[static_cast<size_t>(i)];
+  }
+
+  //  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  const TestCase* GetTestCase(int i) const { return GetTestSuite(i); }
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // Gets the i-th test suite among all the test suites. i can range from 0 to
+  // total_test_suite_count() - 1. If i is not in that range, returns NULL.
+  TestSuite* GetMutableSuiteCase(int i) {
+    const int index = GetElementOr(test_suite_indices_, i, -1);
+    return index < 0 ? nullptr : test_suites_[static_cast<size_t>(index)];
+  }
+
+  // Provides access to the event listener list.
+  TestEventListeners* listeners() { return &listeners_; }
+
+  // Returns the TestResult for the test that's currently running, or
+  // the TestResult for the ad hoc test if no test is running.
+  TestResult* current_test_result();
+
+  // Returns the TestResult for the ad hoc test.
+  const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; }
+
+  // Sets the OS stack trace getter.
+  //
+  // Does nothing if the input and the current OS stack trace getter
+  // are the same; otherwise, deletes the old getter and makes the
+  // input the current getter.
+  void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter);
+
+  // Returns the current OS stack trace getter if it is not NULL;
+  // otherwise, creates an OsStackTraceGetter, makes it the current
+  // getter, and returns it.
+  OsStackTraceGetterInterface* os_stack_trace_getter();
+
+  // Returns the current OS stack trace as an std::string.
+  //
+  // The maximum number of stack frames to be included is specified by
+  // the gtest_stack_trace_depth flag.  The skip_count parameter
+  // specifies the number of top frames to be skipped, which doesn't
+  // count against the number of frames to be included.
+  //
+  // For example, if Foo() calls Bar(), which in turn calls
+  // CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+  // trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+  std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_;
+
+  // Finds and returns a TestSuite with the given name.  If one doesn't
+  // exist, creates one and returns it.
+  //
+  // Arguments:
+  //
+  //   test_suite_name: name of the test suite
+  //   type_param:      the name of the test's type parameter, or NULL if
+  //                    this is not a typed or a type-parameterized test.
+  //   set_up_tc:       pointer to the function that sets up the test suite
+  //   tear_down_tc:    pointer to the function that tears down the test suite
+  TestSuite* GetTestSuite(const char* test_suite_name, const char* type_param,
+                          internal::SetUpTestSuiteFunc set_up_tc,
+                          internal::TearDownTestSuiteFunc tear_down_tc);
+
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  TestCase* GetTestCase(const char* test_case_name, const char* type_param,
+                        internal::SetUpTestSuiteFunc set_up_tc,
+                        internal::TearDownTestSuiteFunc tear_down_tc) {
+    return GetTestSuite(test_case_name, type_param, set_up_tc, tear_down_tc);
+  }
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // Adds a TestInfo to the unit test.
+  //
+  // Arguments:
+  //
+  //   set_up_tc:    pointer to the function that sets up the test suite
+  //   tear_down_tc: pointer to the function that tears down the test suite
+  //   test_info:    the TestInfo object
+  void AddTestInfo(internal::SetUpTestSuiteFunc set_up_tc,
+                   internal::TearDownTestSuiteFunc tear_down_tc,
+                   TestInfo* test_info) {
+#if GTEST_HAS_DEATH_TEST
+    // In order to support thread-safe death tests, we need to
+    // remember the original working directory when the test program
+    // was first invoked.  We cannot do this in RUN_ALL_TESTS(), as
+    // the user may have changed the current directory before calling
+    // RUN_ALL_TESTS().  Therefore we capture the current directory in
+    // AddTestInfo(), which is called to register a TEST or TEST_F
+    // before main() is reached.
+    if (original_working_dir_.IsEmpty()) {
+      original_working_dir_.Set(FilePath::GetCurrentDir());
+      GTEST_CHECK_(!original_working_dir_.IsEmpty())
+          << "Failed to get the current working directory.";
+    }
+#endif  // GTEST_HAS_DEATH_TEST
+
+    GetTestSuite(test_info->test_suite_name(), test_info->type_param(),
+                 set_up_tc, tear_down_tc)
+        ->AddTestInfo(test_info);
+  }
+
+  // Returns ParameterizedTestSuiteRegistry object used to keep track of
+  // value-parameterized tests and instantiate and register them.
+  internal::ParameterizedTestSuiteRegistry& parameterized_test_registry() {
+    return parameterized_test_registry_;
+  }
+
+  std::set<std::string>* ignored_parameterized_test_suites() {
+    return &ignored_parameterized_test_suites_;
+  }
+
+  // Returns TypeParameterizedTestSuiteRegistry object used to keep track of
+  // type-parameterized tests and instantiations of them.
+  internal::TypeParameterizedTestSuiteRegistry&
+  type_parameterized_test_registry() {
+    return type_parameterized_test_registry_;
+  }
+
+  // Sets the TestSuite object for the test that's currently running.
+  void set_current_test_suite(TestSuite* a_current_test_suite) {
+    current_test_suite_ = a_current_test_suite;
+  }
+
+  // Sets the TestInfo object for the test that's currently running.  If
+  // current_test_info is NULL, the assertion results will be stored in
+  // ad_hoc_test_result_.
+  void set_current_test_info(TestInfo* a_current_test_info) {
+    current_test_info_ = a_current_test_info;
+  }
+
+  // Registers all parameterized tests defined using TEST_P and
+  // INSTANTIATE_TEST_SUITE_P, creating regular tests for each test/parameter
+  // combination. This method can be called more then once; it has guards
+  // protecting from registering the tests more then once.  If
+  // value-parameterized tests are disabled, RegisterParameterizedTests is
+  // present but does nothing.
+  void RegisterParameterizedTests();
+
+  // Runs all tests in this UnitTest object, prints the result, and
+  // returns true if all tests are successful.  If any exception is
+  // thrown during a test, this test is considered to be failed, but
+  // the rest of the tests will still be run.
+  bool RunAllTests();
+
+  // Clears the results of all tests, except the ad hoc tests.
+  void ClearNonAdHocTestResult() {
+    ForEach(test_suites_, TestSuite::ClearTestSuiteResult);
+  }
+
+  // Clears the results of ad-hoc test assertions.
+  void ClearAdHocTestResult() {
+    ad_hoc_test_result_.Clear();
+  }
+
+  // Adds a TestProperty to the current TestResult object when invoked in a
+  // context of a test or a test suite, or to the global property set. If the
+  // result already contains a property with the same key, the value will be
+  // updated.
+  void RecordProperty(const TestProperty& test_property);
+
+  enum ReactionToSharding {
+    HONOR_SHARDING_PROTOCOL,
+    IGNORE_SHARDING_PROTOCOL
+  };
+
+  // Matches the full name of each test against the user-specified
+  // filter to decide whether the test should run, then records the
+  // result in each TestSuite and TestInfo object.
+  // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests
+  // based on sharding variables in the environment.
+  // Returns the number of tests that should run.
+  int FilterTests(ReactionToSharding shard_tests);
+
+  // Prints the names of the tests matching the user-specified filter flag.
+  void ListTestsMatchingFilter();
+
+  const TestSuite* current_test_suite() const { return current_test_suite_; }
+  TestInfo* current_test_info() { return current_test_info_; }
+  const TestInfo* current_test_info() const { return current_test_info_; }
+
+  // Returns the vector of environments that need to be set-up/torn-down
+  // before/after the tests are run.
+  std::vector<Environment*>& environments() { return environments_; }
+
+  // Getters for the per-thread Google Test trace stack.
+  std::vector<TraceInfo>& gtest_trace_stack() {
+    return *(gtest_trace_stack_.pointer());
+  }
+  const std::vector<TraceInfo>& gtest_trace_stack() const {
+    return gtest_trace_stack_.get();
+  }
+
+#if GTEST_HAS_DEATH_TEST
+  void InitDeathTestSubprocessControlInfo() {
+    internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
+  }
+  // Returns a pointer to the parsed --gtest_internal_run_death_test
+  // flag, or NULL if that flag was not specified.
+  // This information is useful only in a death test child process.
+  // Must not be called before a call to InitGoogleTest.
+  const InternalRunDeathTestFlag* internal_run_death_test_flag() const {
+    return internal_run_death_test_flag_.get();
+  }
+
+  // Returns a pointer to the current death test factory.
+  internal::DeathTestFactory* death_test_factory() {
+    return death_test_factory_.get();
+  }
+
+  void SuppressTestEventsIfInSubprocess();
+
+  friend class ReplaceDeathTestFactory;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // Initializes the event listener performing XML output as specified by
+  // UnitTestOptions. Must not be called before InitGoogleTest.
+  void ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+  // Initializes the event listener for streaming test results to a socket.
+  // Must not be called before InitGoogleTest.
+  void ConfigureStreamingOutput();
+#endif
+
+  // Performs initialization dependent upon flag values obtained in
+  // ParseGoogleTestFlagsOnly.  Is called from InitGoogleTest after the call to
+  // ParseGoogleTestFlagsOnly.  In case a user neglects to call InitGoogleTest
+  // this function is also called from RunAllTests.  Since this function can be
+  // called more than once, it has to be idempotent.
+  void PostFlagParsingInit();
+
+  // Gets the random seed used at the start of the current test iteration.
+  int random_seed() const { return random_seed_; }
+
+  // Gets the random number generator.
+  internal::Random* random() { return &random_; }
+
+  // Shuffles all test suites, and the tests within each test suite,
+  // making sure that death tests are still run first.
+  void ShuffleTests();
+
+  // Restores the test suites and tests to their order before the first shuffle.
+  void UnshuffleTests();
+
+  // Returns the value of GTEST_FLAG(catch_exceptions) at the moment
+  // UnitTest::Run() starts.
+  bool catch_exceptions() const { return catch_exceptions_; }
+
+ private:
+  friend class ::testing::UnitTest;
+
+  // Used by UnitTest::Run() to capture the state of
+  // GTEST_FLAG(catch_exceptions) at the moment it starts.
+  void set_catch_exceptions(bool value) { catch_exceptions_ = value; }
+
+  // The UnitTest object that owns this implementation object.
+  UnitTest* const parent_;
+
+  // The working directory when the first TEST() or TEST_F() was
+  // executed.
+  internal::FilePath original_working_dir_;
+
+  // The default test part result reporters.
+  DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_;
+  DefaultPerThreadTestPartResultReporter
+      default_per_thread_test_part_result_reporter_;
+
+  // Points to (but doesn't own) the global test part result reporter.
+  TestPartResultReporterInterface* global_test_part_result_repoter_;
+
+  // Protects read and write access to global_test_part_result_reporter_.
+  internal::Mutex global_test_part_result_reporter_mutex_;
+
+  // Points to (but doesn't own) the per-thread test part result reporter.
+  internal::ThreadLocal<TestPartResultReporterInterface*>
+      per_thread_test_part_result_reporter_;
+
+  // The vector of environments that need to be set-up/torn-down
+  // before/after the tests are run.
+  std::vector<Environment*> environments_;
+
+  // The vector of TestSuites in their original order.  It owns the
+  // elements in the vector.
+  std::vector<TestSuite*> test_suites_;
+
+  // Provides a level of indirection for the test suite list to allow
+  // easy shuffling and restoring the test suite order.  The i-th
+  // element of this vector is the index of the i-th test suite in the
+  // shuffled order.
+  std::vector<int> test_suite_indices_;
+
+  // ParameterizedTestRegistry object used to register value-parameterized
+  // tests.
+  internal::ParameterizedTestSuiteRegistry parameterized_test_registry_;
+  internal::TypeParameterizedTestSuiteRegistry
+      type_parameterized_test_registry_;
+
+  // The set holding the name of parameterized
+  // test suites that may go uninstantiated.
+  std::set<std::string> ignored_parameterized_test_suites_;
+
+  // Indicates whether RegisterParameterizedTests() has been called already.
+  bool parameterized_tests_registered_;
+
+  // Index of the last death test suite registered.  Initially -1.
+  int last_death_test_suite_;
+
+  // This points to the TestSuite for the currently running test.  It
+  // changes as Google Test goes through one test suite after another.
+  // When no test is running, this is set to NULL and Google Test
+  // stores assertion results in ad_hoc_test_result_.  Initially NULL.
+  TestSuite* current_test_suite_;
+
+  // This points to the TestInfo for the currently running test.  It
+  // changes as Google Test goes through one test after another.  When
+  // no test is running, this is set to NULL and Google Test stores
+  // assertion results in ad_hoc_test_result_.  Initially NULL.
+  TestInfo* current_test_info_;
+
+  // Normally, a user only writes assertions inside a TEST or TEST_F,
+  // or inside a function called by a TEST or TEST_F.  Since Google
+  // Test keeps track of which test is current running, it can
+  // associate such an assertion with the test it belongs to.
+  //
+  // If an assertion is encountered when no TEST or TEST_F is running,
+  // Google Test attributes the assertion result to an imaginary "ad hoc"
+  // test, and records the result in ad_hoc_test_result_.
+  TestResult ad_hoc_test_result_;
+
+  // The list of event listeners that can be used to track events inside
+  // Google Test.
+  TestEventListeners listeners_;
+
+  // The OS stack trace getter.  Will be deleted when the UnitTest
+  // object is destructed.  By default, an OsStackTraceGetter is used,
+  // but the user can set this field to use a custom getter if that is
+  // desired.
+  OsStackTraceGetterInterface* os_stack_trace_getter_;
+
+  // True if and only if PostFlagParsingInit() has been called.
+  bool post_flag_parse_init_performed_;
+
+  // The random number seed used at the beginning of the test run.
+  int random_seed_;
+
+  // Our random number generator.
+  internal::Random random_;
+
+  // The time of the test program start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp_;
+
+  // How long the test took to run, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+#if GTEST_HAS_DEATH_TEST
+  // The decomposed components of the gtest_internal_run_death_test flag,
+  // parsed when RUN_ALL_TESTS is called.
+  std::unique_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
+  std::unique_ptr<internal::DeathTestFactory> death_test_factory_;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // A per-thread stack of traces created by the SCOPED_TRACE() macro.
+  internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_;
+
+  // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests()
+  // starts.
+  bool catch_exceptions_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl);
+};  // class UnitTestImpl
+
+// Convenience function for accessing the global UnitTest
+// implementation object.
+inline UnitTestImpl* GetUnitTestImpl() {
+  return UnitTest::GetInstance()->impl();
+}
+
+#if GTEST_USES_SIMPLE_RE
+
+// Internal helper functions for implementing the simple regular
+// expression matcher.
+GTEST_API_ bool IsInSet(char ch, const char* str);
+GTEST_API_ bool IsAsciiDigit(char ch);
+GTEST_API_ bool IsAsciiPunct(char ch);
+GTEST_API_ bool IsRepeat(char ch);
+GTEST_API_ bool IsAsciiWhiteSpace(char ch);
+GTEST_API_ bool IsAsciiWordChar(char ch);
+GTEST_API_ bool IsValidEscape(char ch);
+GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
+GTEST_API_ bool ValidateRegex(const char* regex);
+GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str);
+GTEST_API_ bool MatchRepetitionAndRegexAtHead(
+    bool escaped, char ch, char repeat, const char* regex, const char* str);
+GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
+
+#endif  // GTEST_USES_SIMPLE_RE
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv);
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
+
+#if GTEST_HAS_DEATH_TEST
+
+// Returns the message describing the last system error, regardless of the
+// platform.
+GTEST_API_ std::string GetLastErrnoDescription();
+
+// Attempts to parse a string into a positive integer pointed to by the
+// number parameter.  Returns true if that is possible.
+// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use
+// it here.
+template <typename Integer>
+bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
+  // Fail fast if the given string does not begin with a digit;
+  // this bypasses strtoXXX's "optional leading whitespace and plus
+  // or minus sign" semantics, which are undesirable here.
+  if (str.empty() || !IsDigit(str[0])) {
+    return false;
+  }
+  errno = 0;
+
+  char* end;
+  // BiggestConvertible is the largest integer type that system-provided
+  // string-to-number conversion routines can return.
+  using BiggestConvertible = unsigned long long;  // NOLINT
+
+  const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);  // NOLINT
+  const bool parse_success = *end == '\0' && errno == 0;
+
+  GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
+
+  const Integer result = static_cast<Integer>(parsed);
+  if (parse_success && static_cast<BiggestConvertible>(result) == parsed) {
+    *number = result;
+    return true;
+  }
+  return false;
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// TestResult contains some private methods that should be hidden from
+// Google Test user but are required for testing. This class allow our tests
+// to access them.
+//
+// This class is supplied only for the purpose of testing Google Test's own
+// constructs. Do not use it in user tests, either directly or indirectly.
+class TestResultAccessor {
+ public:
+  static void RecordProperty(TestResult* test_result,
+                             const std::string& xml_element,
+                             const TestProperty& property) {
+    test_result->RecordProperty(xml_element, property);
+  }
+
+  static void ClearTestPartResults(TestResult* test_result) {
+    test_result->ClearTestPartResults();
+  }
+
+  static const std::vector<testing::TestPartResult>& test_part_results(
+      const TestResult& test_result) {
+    return test_result.test_part_results();
+  }
+};
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Streams test results to the given port on the given host machine.
+class StreamingListener : public EmptyTestEventListener {
+ public:
+  // Abstract base class for writing strings to a socket.
+  class AbstractSocketWriter {
+   public:
+    virtual ~AbstractSocketWriter() {}
+
+    // Sends a string to the socket.
+    virtual void Send(const std::string& message) = 0;
+
+    // Closes the socket.
+    virtual void CloseConnection() {}
+
+    // Sends a string and a newline to the socket.
+    void SendLn(const std::string& message) { Send(message + "\n"); }
+  };
+
+  // Concrete class for actually writing strings to a socket.
+  class SocketWriter : public AbstractSocketWriter {
+   public:
+    SocketWriter(const std::string& host, const std::string& port)
+        : sockfd_(-1), host_name_(host), port_num_(port) {
+      MakeConnection();
+    }
+
+    ~SocketWriter() override {
+      if (sockfd_ != -1)
+        CloseConnection();
+    }
+
+    // Sends a string to the socket.
+    void Send(const std::string& message) override {
+      GTEST_CHECK_(sockfd_ != -1)
+          << "Send() can be called only when there is a connection.";
+
+      const auto len = static_cast<size_t>(message.length());
+      if (write(sockfd_, message.c_str(), len) != static_cast<ssize_t>(len)) {
+        GTEST_LOG_(WARNING)
+            << "stream_result_to: failed to stream to "
+            << host_name_ << ":" << port_num_;
+      }
+    }
+
+   private:
+    // Creates a client socket and connects to the server.
+    void MakeConnection();
+
+    // Closes the socket.
+    void CloseConnection() override {
+      GTEST_CHECK_(sockfd_ != -1)
+          << "CloseConnection() can be called only when there is a connection.";
+
+      close(sockfd_);
+      sockfd_ = -1;
+    }
+
+    int sockfd_;  // socket file descriptor
+    const std::string host_name_;
+    const std::string port_num_;
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter);
+  };  // class SocketWriter
+
+  // Escapes '=', '&', '%', and '\n' characters in str as "%xx".
+  static std::string UrlEncode(const char* str);
+
+  StreamingListener(const std::string& host, const std::string& port)
+      : socket_writer_(new SocketWriter(host, port)) {
+    Start();
+  }
+
+  explicit StreamingListener(AbstractSocketWriter* socket_writer)
+      : socket_writer_(socket_writer) { Start(); }
+
+  void OnTestProgramStart(const UnitTest& /* unit_test */) override {
+    SendLn("event=TestProgramStart");
+  }
+
+  void OnTestProgramEnd(const UnitTest& unit_test) override {
+    // Note that Google Test current only report elapsed time for each
+    // test iteration, not for the entire test program.
+    SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed()));
+
+    // Notify the streaming server to stop.
+    socket_writer_->CloseConnection();
+  }
+
+  void OnTestIterationStart(const UnitTest& /* unit_test */,
+                            int iteration) override {
+    SendLn("event=TestIterationStart&iteration=" +
+           StreamableToString(iteration));
+  }
+
+  void OnTestIterationEnd(const UnitTest& unit_test,
+                          int /* iteration */) override {
+    SendLn("event=TestIterationEnd&passed=" +
+           FormatBool(unit_test.Passed()) + "&elapsed_time=" +
+           StreamableToString(unit_test.elapsed_time()) + "ms");
+  }
+
+  // Note that "event=TestCaseStart" is a wire format and has to remain
+  // "case" for compatibility
+  void OnTestCaseStart(const TestCase& test_case) override {
+    SendLn(std::string("event=TestCaseStart&name=") + test_case.name());
+  }
+
+  // Note that "event=TestCaseEnd" is a wire format and has to remain
+  // "case" for compatibility
+  void OnTestCaseEnd(const TestCase& test_case) override {
+    SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) +
+           "&elapsed_time=" + StreamableToString(test_case.elapsed_time()) +
+           "ms");
+  }
+
+  void OnTestStart(const TestInfo& test_info) override {
+    SendLn(std::string("event=TestStart&name=") + test_info.name());
+  }
+
+  void OnTestEnd(const TestInfo& test_info) override {
+    SendLn("event=TestEnd&passed=" +
+           FormatBool((test_info.result())->Passed()) +
+           "&elapsed_time=" +
+           StreamableToString((test_info.result())->elapsed_time()) + "ms");
+  }
+
+  void OnTestPartResult(const TestPartResult& test_part_result) override {
+    const char* file_name = test_part_result.file_name();
+    if (file_name == nullptr) file_name = "";
+    SendLn("event=TestPartResult&file=" + UrlEncode(file_name) +
+           "&line=" + StreamableToString(test_part_result.line_number()) +
+           "&message=" + UrlEncode(test_part_result.message()));
+  }
+
+ private:
+  // Sends the given message and a newline to the socket.
+  void SendLn(const std::string& message) { socket_writer_->SendLn(message); }
+
+  // Called at the start of streaming to notify the receiver what
+  // protocol we are using.
+  void Start() { SendLn("gtest_streaming_protocol_version=1.0"); }
+
+  std::string FormatBool(bool value) { return value ? "1" : "0"; }
+
+  const std::unique_ptr<AbstractSocketWriter> socket_writer_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener);
+};  // class StreamingListener
+
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+}  // namespace internal
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+#endif  // GOOGLETEST_SRC_GTEST_INTERNAL_INL_H_
+
+#if GTEST_OS_WINDOWS
+# define vsnprintf _vsnprintf
+#endif  // GTEST_OS_WINDOWS
+
+#if GTEST_OS_MAC
+#ifndef GTEST_OS_IOS
+#include <crt_externs.h>
+#endif
+#endif
+
+#if GTEST_HAS_ABSL
+#include "absl/debugging/failure_signal_handler.h"
+#include "absl/debugging/stacktrace.h"
+#include "absl/debugging/symbolize.h"
+#include "absl/strings/str_cat.h"
+#endif  // GTEST_HAS_ABSL
+
+namespace testing {
+
+using internal::CountIf;
+using internal::ForEach;
+using internal::GetElementOr;
+using internal::Shuffle;
+
+// Constants.
+
+// A test whose test suite name or test name matches this filter is
+// disabled and not run.
+static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*";
+
+// A test suite whose name matches this filter is considered a death
+// test suite and will be run before test suites whose name doesn't
+// match this filter.
+static const char kDeathTestSuiteFilter[] = "*DeathTest:*DeathTest/*";
+
+// A test filter that matches everything.
+static const char kUniversalFilter[] = "*";
+
+// The default output format.
+static const char kDefaultOutputFormat[] = "xml";
+// The default output file.
+static const char kDefaultOutputFile[] = "test_detail";
+
+// The environment variable name for the test shard index.
+static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
+// The environment variable name for the total number of test shards.
+static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
+// The environment variable name for the test shard status file.
+static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE";
+
+namespace internal {
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+const char kStackTraceMarker[] = "\nStack trace:\n";
+
+// g_help_flag is true if and only if the --help flag or an equivalent form
+// is specified on the command line.
+bool g_help_flag = false;
+
+// Utilty function to Open File for Writing
+static FILE* OpenFileForWriting(const std::string& output_file) {
+  FILE* fileout = nullptr;
+  FilePath output_file_path(output_file);
+  FilePath output_dir(output_file_path.RemoveFileName());
+
+  if (output_dir.CreateDirectoriesRecursively()) {
+    fileout = posix::FOpen(output_file.c_str(), "w");
+  }
+  if (fileout == nullptr) {
+    GTEST_LOG_(FATAL) << "Unable to open file \"" << output_file << "\"";
+  }
+  return fileout;
+}
+
+}  // namespace internal
+
+// Bazel passes in the argument to '--test_filter' via the TESTBRIDGE_TEST_ONLY
+// environment variable.
+static const char* GetDefaultFilter() {
+  const char* const testbridge_test_only =
+      internal::posix::GetEnv("TESTBRIDGE_TEST_ONLY");
+  if (testbridge_test_only != nullptr) {
+    return testbridge_test_only;
+  }
+  return kUniversalFilter;
+}
+
+// Bazel passes in the argument to '--test_runner_fail_fast' via the
+// TESTBRIDGE_TEST_RUNNER_FAIL_FAST environment variable.
+static bool GetDefaultFailFast() {
+  const char* const testbridge_test_runner_fail_fast =
+      internal::posix::GetEnv("TESTBRIDGE_TEST_RUNNER_FAIL_FAST");
+  if (testbridge_test_runner_fail_fast != nullptr) {
+    return strcmp(testbridge_test_runner_fail_fast, "1") == 0;
+  }
+  return false;
+}
+
+GTEST_DEFINE_bool_(
+    fail_fast, internal::BoolFromGTestEnv("fail_fast", GetDefaultFailFast()),
+    "True if and only if a test failure should stop further test execution.");
+
+GTEST_DEFINE_bool_(
+    also_run_disabled_tests,
+    internal::BoolFromGTestEnv("also_run_disabled_tests", false),
+    "Run disabled tests too, in addition to the tests normally being run.");
+
+GTEST_DEFINE_bool_(
+    break_on_failure, internal::BoolFromGTestEnv("break_on_failure", false),
+    "True if and only if a failed assertion should be a debugger "
+    "break-point.");
+
+GTEST_DEFINE_bool_(catch_exceptions,
+                   internal::BoolFromGTestEnv("catch_exceptions", true),
+                   "True if and only if " GTEST_NAME_
+                   " should catch exceptions and treat them as test failures.");
+
+GTEST_DEFINE_string_(
+    color,
+    internal::StringFromGTestEnv("color", "auto"),
+    "Whether to use colors in the output.  Valid values: yes, no, "
+    "and auto.  'auto' means to use colors if the output is "
+    "being sent to a terminal and the TERM environment variable "
+    "is set to a terminal type that supports colors.");
+
+GTEST_DEFINE_string_(
+    filter,
+    internal::StringFromGTestEnv("filter", GetDefaultFilter()),
+    "A colon-separated list of glob (not regex) patterns "
+    "for filtering the tests to run, optionally followed by a "
+    "'-' and a : separated list of negative patterns (tests to "
+    "exclude).  A test is run if it matches one of the positive "
+    "patterns and does not match any of the negative patterns.");
+
+GTEST_DEFINE_bool_(
+    install_failure_signal_handler,
+    internal::BoolFromGTestEnv("install_failure_signal_handler", false),
+    "If true and supported on the current platform, " GTEST_NAME_ " should "
+    "install a signal handler that dumps debugging information when fatal "
+    "signals are raised.");
+
+GTEST_DEFINE_bool_(list_tests, false,
+                   "List all tests without running them.");
+
+// The net priority order after flag processing is thus:
+//   --gtest_output command line flag
+//   GTEST_OUTPUT environment variable
+//   XML_OUTPUT_FILE environment variable
+//   ''
+GTEST_DEFINE_string_(
+    output,
+    internal::StringFromGTestEnv("output",
+      internal::OutputFlagAlsoCheckEnvVar().c_str()),
+    "A format (defaults to \"xml\" but can be specified to be \"json\"), "
+    "optionally followed by a colon and an output file name or directory. "
+    "A directory is indicated by a trailing pathname separator. "
+    "Examples: \"xml:filename.xml\", \"xml::directoryname/\". "
+    "If a directory is specified, output files will be created "
+    "within that directory, with file-names based on the test "
+    "executable's name and, if necessary, made unique by adding "
+    "digits.");
+
+GTEST_DEFINE_bool_(
+    brief, internal::BoolFromGTestEnv("brief", false),
+    "True if only test failures should be displayed in text output.");
+
+GTEST_DEFINE_bool_(print_time, internal::BoolFromGTestEnv("print_time", true),
+                   "True if and only if " GTEST_NAME_
+                   " should display elapsed time in text output.");
+
+GTEST_DEFINE_bool_(print_utf8, internal::BoolFromGTestEnv("print_utf8", true),
+                   "True if and only if " GTEST_NAME_
+                   " prints UTF8 characters as text.");
+
+GTEST_DEFINE_int32_(
+    random_seed,
+    internal::Int32FromGTestEnv("random_seed", 0),
+    "Random number seed to use when shuffling test orders.  Must be in range "
+    "[1, 99999], or 0 to use a seed based on the current time.");
+
+GTEST_DEFINE_int32_(
+    repeat,
+    internal::Int32FromGTestEnv("repeat", 1),
+    "How many times to repeat each test.  Specify a negative number "
+    "for repeating forever.  Useful for shaking out flaky tests.");
+
+GTEST_DEFINE_bool_(show_internal_stack_frames, false,
+                   "True if and only if " GTEST_NAME_
+                   " should include internal stack frames when "
+                   "printing test failure stack traces.");
+
+GTEST_DEFINE_bool_(shuffle, internal::BoolFromGTestEnv("shuffle", false),
+                   "True if and only if " GTEST_NAME_
+                   " should randomize tests' order on every run.");
+
+GTEST_DEFINE_int32_(
+    stack_trace_depth,
+    internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth),
+    "The maximum number of stack frames to print when an "
+    "assertion fails.  The valid range is 0 through 100, inclusive.");
+
+GTEST_DEFINE_string_(
+    stream_result_to,
+    internal::StringFromGTestEnv("stream_result_to", ""),
+    "This flag specifies the host name and the port number on which to stream "
+    "test results. Example: \"localhost:555\". The flag is effective only on "
+    "Linux.");
+
+GTEST_DEFINE_bool_(
+    throw_on_failure,
+    internal::BoolFromGTestEnv("throw_on_failure", false),
+    "When this flag is specified, a failed assertion will throw an exception "
+    "if exceptions are enabled or exit the program with a non-zero code "
+    "otherwise. For use with an external test framework.");
+
+#if GTEST_USE_OWN_FLAGFILE_FLAG_
+GTEST_DEFINE_string_(
+    flagfile,
+    internal::StringFromGTestEnv("flagfile", ""),
+    "This flag specifies the flagfile to read command-line flags from.");
+#endif  // GTEST_USE_OWN_FLAGFILE_FLAG_
+
+namespace internal {
+
+// Generates a random number from [0, range), using a Linear
+// Congruential Generator (LCG).  Crashes if 'range' is 0 or greater
+// than kMaxRange.
+uint32_t Random::Generate(uint32_t range) {
+  // These constants are the same as are used in glibc's rand(3).
+  // Use wider types than necessary to prevent unsigned overflow diagnostics.
+  state_ = static_cast<uint32_t>(1103515245ULL*state_ + 12345U) % kMaxRange;
+
+  GTEST_CHECK_(range > 0)
+      << "Cannot generate a number in the range [0, 0).";
+  GTEST_CHECK_(range <= kMaxRange)
+      << "Generation of a number in [0, " << range << ") was requested, "
+      << "but this can only generate numbers in [0, " << kMaxRange << ").";
+
+  // Converting via modulus introduces a bit of downward bias, but
+  // it's simple, and a linear congruential generator isn't too good
+  // to begin with.
+  return state_ % range;
+}
+
+// GTestIsInitialized() returns true if and only if the user has initialized
+// Google Test.  Useful for catching the user mistake of not initializing
+// Google Test before calling RUN_ALL_TESTS().
+static bool GTestIsInitialized() { return GetArgvs().size() > 0; }
+
+// Iterates over a vector of TestSuites, keeping a running sum of the
+// results of calling a given int-returning method on each.
+// Returns the sum.
+static int SumOverTestSuiteList(const std::vector<TestSuite*>& case_list,
+                                int (TestSuite::*method)() const) {
+  int sum = 0;
+  for (size_t i = 0; i < case_list.size(); i++) {
+    sum += (case_list[i]->*method)();
+  }
+  return sum;
+}
+
+// Returns true if and only if the test suite passed.
+static bool TestSuitePassed(const TestSuite* test_suite) {
+  return test_suite->should_run() && test_suite->Passed();
+}
+
+// Returns true if and only if the test suite failed.
+static bool TestSuiteFailed(const TestSuite* test_suite) {
+  return test_suite->should_run() && test_suite->Failed();
+}
+
+// Returns true if and only if test_suite contains at least one test that
+// should run.
+static bool ShouldRunTestSuite(const TestSuite* test_suite) {
+  return test_suite->should_run();
+}
+
+// AssertHelper constructor.
+AssertHelper::AssertHelper(TestPartResult::Type type,
+                           const char* file,
+                           int line,
+                           const char* message)
+    : data_(new AssertHelperData(type, file, line, message)) {
+}
+
+AssertHelper::~AssertHelper() {
+  delete data_;
+}
+
+// Message assignment, for assertion streaming support.
+void AssertHelper::operator=(const Message& message) const {
+  UnitTest::GetInstance()->
+    AddTestPartResult(data_->type, data_->file, data_->line,
+                      AppendUserMessage(data_->message, message),
+                      UnitTest::GetInstance()->impl()
+                      ->CurrentOsStackTraceExceptTop(1)
+                      // Skips the stack frame for this function itself.
+                      );  // NOLINT
+}
+
+namespace {
+
+// When TEST_P is found without a matching INSTANTIATE_TEST_SUITE_P
+// to creates test cases for it, a syntetic test case is
+// inserted to report ether an error or a log message.
+//
+// This configuration bit will likely be removed at some point.
+constexpr bool kErrorOnUninstantiatedParameterizedTest = true;
+constexpr bool kErrorOnUninstantiatedTypeParameterizedTest = true;
+
+// A test that fails at a given file/line location with a given message.
+class FailureTest : public Test {
+ public:
+  explicit FailureTest(const CodeLocation& loc, std::string error_message,
+                       bool as_error)
+      : loc_(loc),
+        error_message_(std::move(error_message)),
+        as_error_(as_error) {}
+
+  void TestBody() override {
+    if (as_error_) {
+      AssertHelper(TestPartResult::kNonFatalFailure, loc_.file.c_str(),
+                   loc_.line, "") = Message() << error_message_;
+    } else {
+      std::cout << error_message_ << std::endl;
+    }
+  }
+
+ private:
+  const CodeLocation loc_;
+  const std::string error_message_;
+  const bool as_error_;
+};
+
+
+}  // namespace
+
+std::set<std::string>* GetIgnoredParameterizedTestSuites() {
+  return UnitTest::GetInstance()->impl()->ignored_parameterized_test_suites();
+}
+
+// Add a given test_suit to the list of them allow to go un-instantiated.
+MarkAsIgnored::MarkAsIgnored(const char* test_suite) {
+  GetIgnoredParameterizedTestSuites()->insert(test_suite);
+}
+
+// If this parameterized test suite has no instantiations (and that
+// has not been marked as okay), emit a test case reporting that.
+void InsertSyntheticTestCase(const std::string& name, CodeLocation location,
+                             bool has_test_p) {
+  const auto& ignored = *GetIgnoredParameterizedTestSuites();
+  if (ignored.find(name) != ignored.end()) return;
+
+  const char kMissingInstantiation[] =  //
+      " is defined via TEST_P, but never instantiated. None of the test cases "
+      "will run. Either no INSTANTIATE_TEST_SUITE_P is provided or the only "
+      "ones provided expand to nothing."
+      "\n\n"
+      "Ideally, TEST_P definitions should only ever be included as part of "
+      "binaries that intend to use them. (As opposed to, for example, being "
+      "placed in a library that may be linked in to get other utilities.)";
+
+  const char kMissingTestCase[] =  //
+      " is instantiated via INSTANTIATE_TEST_SUITE_P, but no tests are "
+      "defined via TEST_P . No test cases will run."
+      "\n\n"
+      "Ideally, INSTANTIATE_TEST_SUITE_P should only ever be invoked from "
+      "code that always depend on code that provides TEST_P. Failing to do "
+      "so is often an indication of dead code, e.g. the last TEST_P was "
+      "removed but the rest got left behind.";
+
+  std::string message =
+      "Parameterized test suite " + name +
+      (has_test_p ? kMissingInstantiation : kMissingTestCase) +
+      "\n\n"
+      "To suppress this error for this test suite, insert the following line "
+      "(in a non-header) in the namespace it is defined in:"
+      "\n\n"
+      "GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(" + name + ");";
+
+  std::string full_name = "UninstantiatedParameterizedTestSuite<" + name + ">";
+  RegisterTest(  //
+      "GoogleTestVerification", full_name.c_str(),
+      nullptr,  // No type parameter.
+      nullptr,  // No value parameter.
+      location.file.c_str(), location.line, [message, location] {
+        return new FailureTest(location, message,
+                               kErrorOnUninstantiatedParameterizedTest);
+      });
+}
+
+void RegisterTypeParameterizedTestSuite(const char* test_suite_name,
+                                        CodeLocation code_location) {
+  GetUnitTestImpl()->type_parameterized_test_registry().RegisterTestSuite(
+      test_suite_name, code_location);
+}
+
+void RegisterTypeParameterizedTestSuiteInstantiation(const char* case_name) {
+  GetUnitTestImpl()
+      ->type_parameterized_test_registry()
+      .RegisterInstantiation(case_name);
+}
+
+void TypeParameterizedTestSuiteRegistry::RegisterTestSuite(
+    const char* test_suite_name, CodeLocation code_location) {
+  suites_.emplace(std::string(test_suite_name),
+                 TypeParameterizedTestSuiteInfo(code_location));
+}
+
+void TypeParameterizedTestSuiteRegistry::RegisterInstantiation(
+        const char* test_suite_name) {
+  auto it = suites_.find(std::string(test_suite_name));
+  if (it != suites_.end()) {
+    it->second.instantiated = true;
+  } else {
+    GTEST_LOG_(ERROR) << "Unknown type parameterized test suit '"
+                      << test_suite_name << "'";
+  }
+}
+
+void TypeParameterizedTestSuiteRegistry::CheckForInstantiations() {
+  const auto& ignored = *GetIgnoredParameterizedTestSuites();
+  for (const auto& testcase : suites_) {
+    if (testcase.second.instantiated) continue;
+    if (ignored.find(testcase.first) != ignored.end()) continue;
+
+    std::string message =
+        "Type parameterized test suite " + testcase.first +
+        " is defined via REGISTER_TYPED_TEST_SUITE_P, but never instantiated "
+        "via INSTANTIATE_TYPED_TEST_SUITE_P. None of the test cases will run."
+        "\n\n"
+        "Ideally, TYPED_TEST_P definitions should only ever be included as "
+        "part of binaries that intend to use them. (As opposed to, for "
+        "example, being placed in a library that may be linked in to get other "
+        "utilities.)"
+        "\n\n"
+        "To suppress this error for this test suite, insert the following line "
+        "(in a non-header) in the namespace it is defined in:"
+        "\n\n"
+        "GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(" +
+        testcase.first + ");";
+
+    std::string full_name =
+        "UninstantiatedTypeParameterizedTestSuite<" + testcase.first + ">";
+    RegisterTest(  //
+        "GoogleTestVerification", full_name.c_str(),
+        nullptr,  // No type parameter.
+        nullptr,  // No value parameter.
+        testcase.second.code_location.file.c_str(),
+        testcase.second.code_location.line, [message, testcase] {
+          return new FailureTest(testcase.second.code_location, message,
+                                 kErrorOnUninstantiatedTypeParameterizedTest);
+        });
+  }
+}
+
+// A copy of all command line arguments.  Set by InitGoogleTest().
+static ::std::vector<std::string> g_argvs;
+
+::std::vector<std::string> GetArgvs() {
+#if defined(GTEST_CUSTOM_GET_ARGVS_)
+  // GTEST_CUSTOM_GET_ARGVS_() may return a container of std::string or
+  // ::string. This code converts it to the appropriate type.
+  const auto& custom = GTEST_CUSTOM_GET_ARGVS_();
+  return ::std::vector<std::string>(custom.begin(), custom.end());
+#else   // defined(GTEST_CUSTOM_GET_ARGVS_)
+  return g_argvs;
+#endif  // defined(GTEST_CUSTOM_GET_ARGVS_)
+}
+
+// Returns the current application's name, removing directory path if that
+// is present.
+FilePath GetCurrentExecutableName() {
+  FilePath result;
+
+#if GTEST_OS_WINDOWS || GTEST_OS_OS2
+  result.Set(FilePath(GetArgvs()[0]).RemoveExtension("exe"));
+#else
+  result.Set(FilePath(GetArgvs()[0]));
+#endif  // GTEST_OS_WINDOWS
+
+  return result.RemoveDirectoryName();
+}
+
+// Functions for processing the gtest_output flag.
+
+// Returns the output format, or "" for normal printed output.
+std::string UnitTestOptions::GetOutputFormat() {
+  const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+  const char* const colon = strchr(gtest_output_flag, ':');
+  return (colon == nullptr)
+             ? std::string(gtest_output_flag)
+             : std::string(gtest_output_flag,
+                           static_cast<size_t>(colon - gtest_output_flag));
+}
+
+// Returns the name of the requested output file, or the default if none
+// was explicitly specified.
+std::string UnitTestOptions::GetAbsolutePathToOutputFile() {
+  const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+
+  std::string format = GetOutputFormat();
+  if (format.empty())
+    format = std::string(kDefaultOutputFormat);
+
+  const char* const colon = strchr(gtest_output_flag, ':');
+  if (colon == nullptr)
+    return internal::FilePath::MakeFileName(
+        internal::FilePath(
+            UnitTest::GetInstance()->original_working_dir()),
+        internal::FilePath(kDefaultOutputFile), 0,
+        format.c_str()).string();
+
+  internal::FilePath output_name(colon + 1);
+  if (!output_name.IsAbsolutePath())
+    output_name = internal::FilePath::ConcatPaths(
+        internal::FilePath(UnitTest::GetInstance()->original_working_dir()),
+        internal::FilePath(colon + 1));
+
+  if (!output_name.IsDirectory())
+    return output_name.string();
+
+  internal::FilePath result(internal::FilePath::GenerateUniqueFileName(
+      output_name, internal::GetCurrentExecutableName(),
+      GetOutputFormat().c_str()));
+  return result.string();
+}
+
+// Returns true if and only if the wildcard pattern matches the string. Each
+// pattern consists of regular characters, single-character wildcards (?), and
+// multi-character wildcards (*).
+//
+// This function implements a linear-time string globbing algorithm based on
+// https://research.swtch.com/glob.
+static bool PatternMatchesString(const std::string& name_str,
+                                 const char* pattern, const char* pattern_end) {
+  const char* name = name_str.c_str();
+  const char* const name_begin = name;
+  const char* const name_end = name + name_str.size();
+
+  const char* pattern_next = pattern;
+  const char* name_next = name;
+
+  while (pattern < pattern_end || name < name_end) {
+    if (pattern < pattern_end) {
+      switch (*pattern) {
+        default:  // Match an ordinary character.
+          if (name < name_end && *name == *pattern) {
+            ++pattern;
+            ++name;
+            continue;
+          }
+          break;
+        case '?':  // Match any single character.
+          if (name < name_end) {
+            ++pattern;
+            ++name;
+            continue;
+          }
+          break;
+        case '*':
+          // Match zero or more characters. Start by skipping over the wildcard
+          // and matching zero characters from name. If that fails, restart and
+          // match one more character than the last attempt.
+          pattern_next = pattern;
+          name_next = name + 1;
+          ++pattern;
+          continue;
+      }
+    }
+    // Failed to match a character. Restart if possible.
+    if (name_begin < name_next && name_next <= name_end) {
+      pattern = pattern_next;
+      name = name_next;
+      continue;
+    }
+    return false;
+  }
+  return true;
+}
+
+bool UnitTestOptions::MatchesFilter(const std::string& name_str,
+                                    const char* filter) {
+  // The filter is a list of patterns separated by colons (:).
+  const char* pattern = filter;
+  while (true) {
+    // Find the bounds of this pattern.
+    const char* const next_sep = strchr(pattern, ':');
+    const char* const pattern_end =
+        next_sep != nullptr ? next_sep : pattern + strlen(pattern);
+
+    // Check if this pattern matches name_str.
+    if (PatternMatchesString(name_str, pattern, pattern_end)) {
+      return true;
+    }
+
+    // Give up on this pattern. However, if we found a pattern separator (:),
+    // advance to the next pattern (skipping over the separator) and restart.
+    if (next_sep == nullptr) {
+      return false;
+    }
+    pattern = next_sep + 1;
+  }
+  return true;
+}
+
+// Returns true if and only if the user-specified filter matches the test
+// suite name and the test name.
+bool UnitTestOptions::FilterMatchesTest(const std::string& test_suite_name,
+                                        const std::string& test_name) {
+  const std::string& full_name = test_suite_name + "." + test_name.c_str();
+
+  // Split --gtest_filter at '-', if there is one, to separate into
+  // positive filter and negative filter portions
+  const char* const p = GTEST_FLAG(filter).c_str();
+  const char* const dash = strchr(p, '-');
+  std::string positive;
+  std::string negative;
+  if (dash == nullptr) {
+    positive = GTEST_FLAG(filter).c_str();  // Whole string is a positive filter
+    negative = "";
+  } else {
+    positive = std::string(p, dash);   // Everything up to the dash
+    negative = std::string(dash + 1);  // Everything after the dash
+    if (positive.empty()) {
+      // Treat '-test1' as the same as '*-test1'
+      positive = kUniversalFilter;
+    }
+  }
+
+  // A filter is a colon-separated list of patterns.  It matches a
+  // test if any pattern in it matches the test.
+  return (MatchesFilter(full_name, positive.c_str()) &&
+          !MatchesFilter(full_name, negative.c_str()));
+}
+
+#if GTEST_HAS_SEH
+// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
+// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+// This function is useful as an __except condition.
+int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
+  // Google Test should handle a SEH exception if:
+  //   1. the user wants it to, AND
+  //   2. this is not a breakpoint exception, AND
+  //   3. this is not a C++ exception (VC++ implements them via SEH,
+  //      apparently).
+  //
+  // SEH exception code for C++ exceptions.
+  // (see http://support.microsoft.com/kb/185294 for more information).
+  const DWORD kCxxExceptionCode = 0xe06d7363;
+
+  bool should_handle = true;
+
+  if (!GTEST_FLAG(catch_exceptions))
+    should_handle = false;
+  else if (exception_code == EXCEPTION_BREAKPOINT)
+    should_handle = false;
+  else if (exception_code == kCxxExceptionCode)
+    should_handle = false;
+
+  return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
+}
+#endif  // GTEST_HAS_SEH
+
+}  // namespace internal
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test.  The 'result' parameter specifies where to report the
+// results. Intercepts only failures from the current thread.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+    TestPartResultArray* result)
+    : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD),
+      result_(result) {
+  Init();
+}
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test.  The 'result' parameter specifies where to report the
+// results.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+    InterceptMode intercept_mode, TestPartResultArray* result)
+    : intercept_mode_(intercept_mode),
+      result_(result) {
+  Init();
+}
+
+void ScopedFakeTestPartResultReporter::Init() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+    old_reporter_ = impl->GetGlobalTestPartResultReporter();
+    impl->SetGlobalTestPartResultReporter(this);
+  } else {
+    old_reporter_ = impl->GetTestPartResultReporterForCurrentThread();
+    impl->SetTestPartResultReporterForCurrentThread(this);
+  }
+}
+
+// The d'tor restores the test part result reporter used by Google Test
+// before.
+ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+    impl->SetGlobalTestPartResultReporter(old_reporter_);
+  } else {
+    impl->SetTestPartResultReporterForCurrentThread(old_reporter_);
+  }
+}
+
+// Increments the test part result count and remembers the result.
+// This method is from the TestPartResultReporterInterface interface.
+void ScopedFakeTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  result_->Append(result);
+}
+
+namespace internal {
+
+// Returns the type ID of ::testing::Test.  We should always call this
+// instead of GetTypeId< ::testing::Test>() to get the type ID of
+// testing::Test.  This is to work around a suspected linker bug when
+// using Google Test as a framework on Mac OS X.  The bug causes
+// GetTypeId< ::testing::Test>() to return different values depending
+// on whether the call is from the Google Test framework itself or
+// from user test code.  GetTestTypeId() is guaranteed to always
+// return the same value, as it always calls GetTypeId<>() from the
+// gtest.cc, which is within the Google Test framework.
+TypeId GetTestTypeId() {
+  return GetTypeId<Test>();
+}
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library.  This is solely for testing GetTestTypeId().
+extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId();
+
+// This predicate-formatter checks that 'results' contains a test part
+// failure of the given type and that the failure message contains the
+// given substring.
+static AssertionResult HasOneFailure(const char* /* results_expr */,
+                                     const char* /* type_expr */,
+                                     const char* /* substr_expr */,
+                                     const TestPartResultArray& results,
+                                     TestPartResult::Type type,
+                                     const std::string& substr) {
+  const std::string expected(type == TestPartResult::kFatalFailure ?
+                        "1 fatal failure" :
+                        "1 non-fatal failure");
+  Message msg;
+  if (results.size() != 1) {
+    msg << "Expected: " << expected << "\n"
+        << "  Actual: " << results.size() << " failures";
+    for (int i = 0; i < results.size(); i++) {
+      msg << "\n" << results.GetTestPartResult(i);
+    }
+    return AssertionFailure() << msg;
+  }
+
+  const TestPartResult& r = results.GetTestPartResult(0);
+  if (r.type() != type) {
+    return AssertionFailure() << "Expected: " << expected << "\n"
+                              << "  Actual:\n"
+                              << r;
+  }
+
+  if (strstr(r.message(), substr.c_str()) == nullptr) {
+    return AssertionFailure() << "Expected: " << expected << " containing \""
+                              << substr << "\"\n"
+                              << "  Actual:\n"
+                              << r;
+  }
+
+  return AssertionSuccess();
+}
+
+// The constructor of SingleFailureChecker remembers where to look up
+// test part results, what type of failure we expect, and what
+// substring the failure message should contain.
+SingleFailureChecker::SingleFailureChecker(const TestPartResultArray* results,
+                                           TestPartResult::Type type,
+                                           const std::string& substr)
+    : results_(results), type_(type), substr_(substr) {}
+
+// The destructor of SingleFailureChecker verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring.  If that's not the case, a
+// non-fatal failure will be generated.
+SingleFailureChecker::~SingleFailureChecker() {
+  EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_);
+}
+
+DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
+    UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultGlobalTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  unit_test_->current_test_result()->AddTestPartResult(result);
+  unit_test_->listeners()->repeater()->OnTestPartResult(result);
+}
+
+DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter(
+    UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultPerThreadTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result);
+}
+
+// Returns the global test part result reporter.
+TestPartResultReporterInterface*
+UnitTestImpl::GetGlobalTestPartResultReporter() {
+  internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+  return global_test_part_result_repoter_;
+}
+
+// Sets the global test part result reporter.
+void UnitTestImpl::SetGlobalTestPartResultReporter(
+    TestPartResultReporterInterface* reporter) {
+  internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+  global_test_part_result_repoter_ = reporter;
+}
+
+// Returns the test part result reporter for the current thread.
+TestPartResultReporterInterface*
+UnitTestImpl::GetTestPartResultReporterForCurrentThread() {
+  return per_thread_test_part_result_reporter_.get();
+}
+
+// Sets the test part result reporter for the current thread.
+void UnitTestImpl::SetTestPartResultReporterForCurrentThread(
+    TestPartResultReporterInterface* reporter) {
+  per_thread_test_part_result_reporter_.set(reporter);
+}
+
+// Gets the number of successful test suites.
+int UnitTestImpl::successful_test_suite_count() const {
+  return CountIf(test_suites_, TestSuitePassed);
+}
+
+// Gets the number of failed test suites.
+int UnitTestImpl::failed_test_suite_count() const {
+  return CountIf(test_suites_, TestSuiteFailed);
+}
+
+// Gets the number of all test suites.
+int UnitTestImpl::total_test_suite_count() const {
+  return static_cast<int>(test_suites_.size());
+}
+
+// Gets the number of all test suites that contain at least one test
+// that should run.
+int UnitTestImpl::test_suite_to_run_count() const {
+  return CountIf(test_suites_, ShouldRunTestSuite);
+}
+
+// Gets the number of successful tests.
+int UnitTestImpl::successful_test_count() const {
+  return SumOverTestSuiteList(test_suites_, &TestSuite::successful_test_count);
+}
+
+// Gets the number of skipped tests.
+int UnitTestImpl::skipped_test_count() const {
+  return SumOverTestSuiteList(test_suites_, &TestSuite::skipped_test_count);
+}
+
+// Gets the number of failed tests.
+int UnitTestImpl::failed_test_count() const {
+  return SumOverTestSuiteList(test_suites_, &TestSuite::failed_test_count);
+}
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int UnitTestImpl::reportable_disabled_test_count() const {
+  return SumOverTestSuiteList(test_suites_,
+                              &TestSuite::reportable_disabled_test_count);
+}
+
+// Gets the number of disabled tests.
+int UnitTestImpl::disabled_test_count() const {
+  return SumOverTestSuiteList(test_suites_, &TestSuite::disabled_test_count);
+}
+
+// Gets the number of tests to be printed in the XML report.
+int UnitTestImpl::reportable_test_count() const {
+  return SumOverTestSuiteList(test_suites_, &TestSuite::reportable_test_count);
+}
+
+// Gets the number of all tests.
+int UnitTestImpl::total_test_count() const {
+  return SumOverTestSuiteList(test_suites_, &TestSuite::total_test_count);
+}
+
+// Gets the number of tests that should run.
+int UnitTestImpl::test_to_run_count() const {
+  return SumOverTestSuiteList(test_suites_, &TestSuite::test_to_run_count);
+}
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) {
+  return os_stack_trace_getter()->CurrentStackTrace(
+      static_cast<int>(GTEST_FLAG(stack_trace_depth)),
+      skip_count + 1
+      // Skips the user-specified number of frames plus this function
+      // itself.
+      );  // NOLINT
+}
+
+// A helper class for measuring elapsed times.
+class Timer {
+ public:
+  Timer() : start_(std::chrono::steady_clock::now()) {}
+
+  // Return time elapsed in milliseconds since the timer was created.
+  TimeInMillis Elapsed() {
+    return std::chrono::duration_cast<std::chrono::milliseconds>(
+               std::chrono::steady_clock::now() - start_)
+        .count();
+  }
+
+ private:
+  std::chrono::steady_clock::time_point start_;
+};
+
+// Returns a timestamp as milliseconds since the epoch. Note this time may jump
+// around subject to adjustments by the system, to measure elapsed time use
+// Timer instead.
+TimeInMillis GetTimeInMillis() {
+  return std::chrono::duration_cast<std::chrono::milliseconds>(
+             std::chrono::system_clock::now() -
+             std::chrono::system_clock::from_time_t(0))
+      .count();
+}
+
+// Utilities
+
+// class String.
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Creates a UTF-16 wide string from the given ANSI string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the wide string, or NULL if the
+// input is NULL.
+LPCWSTR String::AnsiToUtf16(const char* ansi) {
+  if (!ansi) return nullptr;
+  const int length = strlen(ansi);
+  const int unicode_length =
+      MultiByteToWideChar(CP_ACP, 0, ansi, length, nullptr, 0);
+  WCHAR* unicode = new WCHAR[unicode_length + 1];
+  MultiByteToWideChar(CP_ACP, 0, ansi, length,
+                      unicode, unicode_length);
+  unicode[unicode_length] = 0;
+  return unicode;
+}
+
+// Creates an ANSI string from the given wide string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the ANSI string, or NULL if the
+// input is NULL.
+const char* String::Utf16ToAnsi(LPCWSTR utf16_str)  {
+  if (!utf16_str) return nullptr;
+  const int ansi_length = WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, nullptr,
+                                              0, nullptr, nullptr);
+  char* ansi = new char[ansi_length + 1];
+  WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, ansi, ansi_length, nullptr,
+                      nullptr);
+  ansi[ansi_length] = 0;
+  return ansi;
+}
+
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Compares two C strings.  Returns true if and only if they have the same
+// content.
+//
+// Unlike strcmp(), this function can handle NULL argument(s).  A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CStringEquals(const char * lhs, const char * rhs) {
+  if (lhs == nullptr) return rhs == nullptr;
+
+  if (rhs == nullptr) return false;
+
+  return strcmp(lhs, rhs) == 0;
+}
+
+#if GTEST_HAS_STD_WSTRING
+
+// Converts an array of wide chars to a narrow string using the UTF-8
+// encoding, and streams the result to the given Message object.
+static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length,
+                                     Message* msg) {
+  for (size_t i = 0; i != length; ) {  // NOLINT
+    if (wstr[i] != L'\0') {
+      *msg << WideStringToUtf8(wstr + i, static_cast<int>(length - i));
+      while (i != length && wstr[i] != L'\0')
+        i++;
+    } else {
+      *msg << '\0';
+      i++;
+    }
+  }
+}
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+void SplitString(const ::std::string& str, char delimiter,
+                 ::std::vector< ::std::string>* dest) {
+  ::std::vector< ::std::string> parsed;
+  ::std::string::size_type pos = 0;
+  while (::testing::internal::AlwaysTrue()) {
+    const ::std::string::size_type colon = str.find(delimiter, pos);
+    if (colon == ::std::string::npos) {
+      parsed.push_back(str.substr(pos));
+      break;
+    } else {
+      parsed.push_back(str.substr(pos, colon - pos));
+      pos = colon + 1;
+    }
+  }
+  dest->swap(parsed);
+}
+
+}  // namespace internal
+
+// Constructs an empty Message.
+// We allocate the stringstream separately because otherwise each use of
+// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
+// stack frame leading to huge stack frames in some cases; gcc does not reuse
+// the stack space.
+Message::Message() : ss_(new ::std::stringstream) {
+  // By default, we want there to be enough precision when printing
+  // a double to a Message.
+  *ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
+}
+
+// These two overloads allow streaming a wide C string to a Message
+// using the UTF-8 encoding.
+Message& Message::operator <<(const wchar_t* wide_c_str) {
+  return *this << internal::String::ShowWideCString(wide_c_str);
+}
+Message& Message::operator <<(wchar_t* wide_c_str) {
+  return *this << internal::String::ShowWideCString(wide_c_str);
+}
+
+#if GTEST_HAS_STD_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::std::wstring& wstr) {
+  internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+  return *this;
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+// Gets the text streamed to this object so far as an std::string.
+// Each '\0' character in the buffer is replaced with "\\0".
+std::string Message::GetString() const {
+  return internal::StringStreamToString(ss_.get());
+}
+
+// AssertionResult constructors.
+// Used in EXPECT_TRUE/FALSE(assertion_result).
+AssertionResult::AssertionResult(const AssertionResult& other)
+    : success_(other.success_),
+      message_(other.message_.get() != nullptr
+                   ? new ::std::string(*other.message_)
+                   : static_cast< ::std::string*>(nullptr)) {}
+
+// Swaps two AssertionResults.
+void AssertionResult::swap(AssertionResult& other) {
+  using std::swap;
+  swap(success_, other.success_);
+  swap(message_, other.message_);
+}
+
+// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+AssertionResult AssertionResult::operator!() const {
+  AssertionResult negation(!success_);
+  if (message_.get() != nullptr) negation << *message_;
+  return negation;
+}
+
+// Makes a successful assertion result.
+AssertionResult AssertionSuccess() {
+  return AssertionResult(true);
+}
+
+// Makes a failed assertion result.
+AssertionResult AssertionFailure() {
+  return AssertionResult(false);
+}
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << message.
+AssertionResult AssertionFailure(const Message& message) {
+  return AssertionFailure() << message;
+}
+
+namespace internal {
+
+namespace edit_distance {
+std::vector<EditType> CalculateOptimalEdits(const std::vector<size_t>& left,
+                                            const std::vector<size_t>& right) {
+  std::vector<std::vector<double> > costs(
+      left.size() + 1, std::vector<double>(right.size() + 1));
+  std::vector<std::vector<EditType> > best_move(
+      left.size() + 1, std::vector<EditType>(right.size() + 1));
+
+  // Populate for empty right.
+  for (size_t l_i = 0; l_i < costs.size(); ++l_i) {
+    costs[l_i][0] = static_cast<double>(l_i);
+    best_move[l_i][0] = kRemove;
+  }
+  // Populate for empty left.
+  for (size_t r_i = 1; r_i < costs[0].size(); ++r_i) {
+    costs[0][r_i] = static_cast<double>(r_i);
+    best_move[0][r_i] = kAdd;
+  }
+
+  for (size_t l_i = 0; l_i < left.size(); ++l_i) {
+    for (size_t r_i = 0; r_i < right.size(); ++r_i) {
+      if (left[l_i] == right[r_i]) {
+        // Found a match. Consume it.
+        costs[l_i + 1][r_i + 1] = costs[l_i][r_i];
+        best_move[l_i + 1][r_i + 1] = kMatch;
+        continue;
+      }
+
+      const double add = costs[l_i + 1][r_i];
+      const double remove = costs[l_i][r_i + 1];
+      const double replace = costs[l_i][r_i];
+      if (add < remove && add < replace) {
+        costs[l_i + 1][r_i + 1] = add + 1;
+        best_move[l_i + 1][r_i + 1] = kAdd;
+      } else if (remove < add && remove < replace) {
+        costs[l_i + 1][r_i + 1] = remove + 1;
+        best_move[l_i + 1][r_i + 1] = kRemove;
+      } else {
+        // We make replace a little more expensive than add/remove to lower
+        // their priority.
+        costs[l_i + 1][r_i + 1] = replace + 1.00001;
+        best_move[l_i + 1][r_i + 1] = kReplace;
+      }
+    }
+  }
+
+  // Reconstruct the best path. We do it in reverse order.
+  std::vector<EditType> best_path;
+  for (size_t l_i = left.size(), r_i = right.size(); l_i > 0 || r_i > 0;) {
+    EditType move = best_move[l_i][r_i];
+    best_path.push_back(move);
+    l_i -= move != kAdd;
+    r_i -= move != kRemove;
+  }
+  std::reverse(best_path.begin(), best_path.end());
+  return best_path;
+}
+
+namespace {
+
+// Helper class to convert string into ids with deduplication.
+class InternalStrings {
+ public:
+  size_t GetId(const std::string& str) {
+    IdMap::iterator it = ids_.find(str);
+    if (it != ids_.end()) return it->second;
+    size_t id = ids_.size();
+    return ids_[str] = id;
+  }
+
+ private:
+  typedef std::map<std::string, size_t> IdMap;
+  IdMap ids_;
+};
+
+}  // namespace
+
+std::vector<EditType> CalculateOptimalEdits(
+    const std::vector<std::string>& left,
+    const std::vector<std::string>& right) {
+  std::vector<size_t> left_ids, right_ids;
+  {
+    InternalStrings intern_table;
+    for (size_t i = 0; i < left.size(); ++i) {
+      left_ids.push_back(intern_table.GetId(left[i]));
+    }
+    for (size_t i = 0; i < right.size(); ++i) {
+      right_ids.push_back(intern_table.GetId(right[i]));
+    }
+  }
+  return CalculateOptimalEdits(left_ids, right_ids);
+}
+
+namespace {
+
+// Helper class that holds the state for one hunk and prints it out to the
+// stream.
+// It reorders adds/removes when possible to group all removes before all
+// adds. It also adds the hunk header before printint into the stream.
+class Hunk {
+ public:
+  Hunk(size_t left_start, size_t right_start)
+      : left_start_(left_start),
+        right_start_(right_start),
+        adds_(),
+        removes_(),
+        common_() {}
+
+  void PushLine(char edit, const char* line) {
+    switch (edit) {
+      case ' ':
+        ++common_;
+        FlushEdits();
+        hunk_.push_back(std::make_pair(' ', line));
+        break;
+      case '-':
+        ++removes_;
+        hunk_removes_.push_back(std::make_pair('-', line));
+        break;
+      case '+':
+        ++adds_;
+        hunk_adds_.push_back(std::make_pair('+', line));
+        break;
+    }
+  }
+
+  void PrintTo(std::ostream* os) {
+    PrintHeader(os);
+    FlushEdits();
+    for (std::list<std::pair<char, const char*> >::const_iterator it =
+             hunk_.begin();
+         it != hunk_.end(); ++it) {
+      *os << it->first << it->second << "\n";
+    }
+  }
+
+  bool has_edits() const { return adds_ || removes_; }
+
+ private:
+  void FlushEdits() {
+    hunk_.splice(hunk_.end(), hunk_removes_);
+    hunk_.splice(hunk_.end(), hunk_adds_);
+  }
+
+  // Print a unified diff header for one hunk.
+  // The format is
+  //   "@@ -<left_start>,<left_length> +<right_start>,<right_length> @@"
+  // where the left/right parts are omitted if unnecessary.
+  void PrintHeader(std::ostream* ss) const {
+    *ss << "@@ ";
+    if (removes_) {
+      *ss << "-" << left_start_ << "," << (removes_ + common_);
+    }
+    if (removes_ && adds_) {
+      *ss << " ";
+    }
+    if (adds_) {
+      *ss << "+" << right_start_ << "," << (adds_ + common_);
+    }
+    *ss << " @@\n";
+  }
+
+  size_t left_start_, right_start_;
+  size_t adds_, removes_, common_;
+  std::list<std::pair<char, const char*> > hunk_, hunk_adds_, hunk_removes_;
+};
+
+}  // namespace
+
+// Create a list of diff hunks in Unified diff format.
+// Each hunk has a header generated by PrintHeader above plus a body with
+// lines prefixed with ' ' for no change, '-' for deletion and '+' for
+// addition.
+// 'context' represents the desired unchanged prefix/suffix around the diff.
+// If two hunks are close enough that their contexts overlap, then they are
+// joined into one hunk.
+std::string CreateUnifiedDiff(const std::vector<std::string>& left,
+                              const std::vector<std::string>& right,
+                              size_t context) {
+  const std::vector<EditType> edits = CalculateOptimalEdits(left, right);
+
+  size_t l_i = 0, r_i = 0, edit_i = 0;
+  std::stringstream ss;
+  while (edit_i < edits.size()) {
+    // Find first edit.
+    while (edit_i < edits.size() && edits[edit_i] == kMatch) {
+      ++l_i;
+      ++r_i;
+      ++edit_i;
+    }
+
+    // Find the first line to include in the hunk.
+    const size_t prefix_context = std::min(l_i, context);
+    Hunk hunk(l_i - prefix_context + 1, r_i - prefix_context + 1);
+    for (size_t i = prefix_context; i > 0; --i) {
+      hunk.PushLine(' ', left[l_i - i].c_str());
+    }
+
+    // Iterate the edits until we found enough suffix for the hunk or the input
+    // is over.
+    size_t n_suffix = 0;
+    for (; edit_i < edits.size(); ++edit_i) {
+      if (n_suffix >= context) {
+        // Continue only if the next hunk is very close.
+        auto it = edits.begin() + static_cast<int>(edit_i);
+        while (it != edits.end() && *it == kMatch) ++it;
+        if (it == edits.end() ||
+            static_cast<size_t>(it - edits.begin()) - edit_i >= context) {
+          // There is no next edit or it is too far away.
+          break;
+        }
+      }
+
+      EditType edit = edits[edit_i];
+      // Reset count when a non match is found.
+      n_suffix = edit == kMatch ? n_suffix + 1 : 0;
+
+      if (edit == kMatch || edit == kRemove || edit == kReplace) {
+        hunk.PushLine(edit == kMatch ? ' ' : '-', left[l_i].c_str());
+      }
+      if (edit == kAdd || edit == kReplace) {
+        hunk.PushLine('+', right[r_i].c_str());
+      }
+
+      // Advance indices, depending on edit type.
+      l_i += edit != kAdd;
+      r_i += edit != kRemove;
+    }
+
+    if (!hunk.has_edits()) {
+      // We are done. We don't want this hunk.
+      break;
+    }
+
+    hunk.PrintTo(&ss);
+  }
+  return ss.str();
+}
+
+}  // namespace edit_distance
+
+namespace {
+
+// The string representation of the values received in EqFailure() are already
+// escaped. Split them on escaped '\n' boundaries. Leave all other escaped
+// characters the same.
+std::vector<std::string> SplitEscapedString(const std::string& str) {
+  std::vector<std::string> lines;
+  size_t start = 0, end = str.size();
+  if (end > 2 && str[0] == '"' && str[end - 1] == '"') {
+    ++start;
+    --end;
+  }
+  bool escaped = false;
+  for (size_t i = start; i + 1 < end; ++i) {
+    if (escaped) {
+      escaped = false;
+      if (str[i] == 'n') {
+        lines.push_back(str.substr(start, i - start - 1));
+        start = i + 1;
+      }
+    } else {
+      escaped = str[i] == '\\';
+    }
+  }
+  lines.push_back(str.substr(start, end - start));
+  return lines;
+}
+
+}  // namespace
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings.  For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+//   lhs_expression: "foo"
+//   rhs_expression: "bar"
+//   lhs_value:      "5"
+//   rhs_value:      "6"
+//
+// The ignoring_case parameter is true if and only if the assertion is a
+// *_STRCASEEQ*.  When it's true, the string "Ignoring case" will
+// be inserted into the message.
+AssertionResult EqFailure(const char* lhs_expression,
+                          const char* rhs_expression,
+                          const std::string& lhs_value,
+                          const std::string& rhs_value,
+                          bool ignoring_case) {
+  Message msg;
+  msg << "Expected equality of these values:";
+  msg << "\n  " << lhs_expression;
+  if (lhs_value != lhs_expression) {
+    msg << "\n    Which is: " << lhs_value;
+  }
+  msg << "\n  " << rhs_expression;
+  if (rhs_value != rhs_expression) {
+    msg << "\n    Which is: " << rhs_value;
+  }
+
+  if (ignoring_case) {
+    msg << "\nIgnoring case";
+  }
+
+  if (!lhs_value.empty() && !rhs_value.empty()) {
+    const std::vector<std::string> lhs_lines =
+        SplitEscapedString(lhs_value);
+    const std::vector<std::string> rhs_lines =
+        SplitEscapedString(rhs_value);
+    if (lhs_lines.size() > 1 || rhs_lines.size() > 1) {
+      msg << "\nWith diff:\n"
+          << edit_distance::CreateUnifiedDiff(lhs_lines, rhs_lines);
+    }
+  }
+
+  return AssertionFailure() << msg;
+}
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+std::string GetBoolAssertionFailureMessage(
+    const AssertionResult& assertion_result,
+    const char* expression_text,
+    const char* actual_predicate_value,
+    const char* expected_predicate_value) {
+  const char* actual_message = assertion_result.message();
+  Message msg;
+  msg << "Value of: " << expression_text
+      << "\n  Actual: " << actual_predicate_value;
+  if (actual_message[0] != '\0')
+    msg << " (" << actual_message << ")";
+  msg << "\nExpected: " << expected_predicate_value;
+  return msg.GetString();
+}
+
+// Helper function for implementing ASSERT_NEAR.
+AssertionResult DoubleNearPredFormat(const char* expr1,
+                                     const char* expr2,
+                                     const char* abs_error_expr,
+                                     double val1,
+                                     double val2,
+                                     double abs_error) {
+  const double diff = fabs(val1 - val2);
+  if (diff <= abs_error) return AssertionSuccess();
+
+  // Find the value which is closest to zero.
+  const double min_abs = std::min(fabs(val1), fabs(val2));
+  // Find the distance to the next double from that value.
+  const double epsilon =
+      nextafter(min_abs, std::numeric_limits<double>::infinity()) - min_abs;
+  // Detect the case where abs_error is so small that EXPECT_NEAR is
+  // effectively the same as EXPECT_EQUAL, and give an informative error
+  // message so that the situation can be more easily understood without
+  // requiring exotic floating-point knowledge.
+  // Don't do an epsilon check if abs_error is zero because that implies
+  // that an equality check was actually intended.
+  if (!(std::isnan)(val1) && !(std::isnan)(val2) && abs_error > 0 &&
+      abs_error < epsilon) {
+    return AssertionFailure()
+           << "The difference between " << expr1 << " and " << expr2 << " is "
+           << diff << ", where\n"
+           << expr1 << " evaluates to " << val1 << ",\n"
+           << expr2 << " evaluates to " << val2 << ".\nThe abs_error parameter "
+           << abs_error_expr << " evaluates to " << abs_error
+           << " which is smaller than the minimum distance between doubles for "
+              "numbers of this magnitude which is "
+           << epsilon
+           << ", thus making this EXPECT_NEAR check equivalent to "
+              "EXPECT_EQUAL. Consider using EXPECT_DOUBLE_EQ instead.";
+  }
+  return AssertionFailure()
+      << "The difference between " << expr1 << " and " << expr2
+      << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n"
+      << expr1 << " evaluates to " << val1 << ",\n"
+      << expr2 << " evaluates to " << val2 << ", and\n"
+      << abs_error_expr << " evaluates to " << abs_error << ".";
+}
+
+
+// Helper template for implementing FloatLE() and DoubleLE().
+template <typename RawType>
+AssertionResult FloatingPointLE(const char* expr1,
+                                const char* expr2,
+                                RawType val1,
+                                RawType val2) {
+  // Returns success if val1 is less than val2,
+  if (val1 < val2) {
+    return AssertionSuccess();
+  }
+
+  // or if val1 is almost equal to val2.
+  const FloatingPoint<RawType> lhs(val1), rhs(val2);
+  if (lhs.AlmostEquals(rhs)) {
+    return AssertionSuccess();
+  }
+
+  // Note that the above two checks will both fail if either val1 or
+  // val2 is NaN, as the IEEE floating-point standard requires that
+  // any predicate involving a NaN must return false.
+
+  ::std::stringstream val1_ss;
+  val1_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+          << val1;
+
+  ::std::stringstream val2_ss;
+  val2_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+          << val2;
+
+  return AssertionFailure()
+      << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
+      << "  Actual: " << StringStreamToString(&val1_ss) << " vs "
+      << StringStreamToString(&val2_ss);
+}
+
+}  // namespace internal
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+AssertionResult FloatLE(const char* expr1, const char* expr2,
+                        float val1, float val2) {
+  return internal::FloatingPointLE<float>(expr1, expr2, val1, val2);
+}
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+AssertionResult DoubleLE(const char* expr1, const char* expr2,
+                         double val1, double val2) {
+  return internal::FloatingPointLE<double>(expr1, expr2, val1, val2);
+}
+
+namespace internal {
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+AssertionResult CmpHelperSTREQ(const char* lhs_expression,
+                               const char* rhs_expression,
+                               const char* lhs,
+                               const char* rhs) {
+  if (String::CStringEquals(lhs, rhs)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(lhs_expression,
+                   rhs_expression,
+                   PrintToString(lhs),
+                   PrintToString(rhs),
+                   false);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+AssertionResult CmpHelperSTRCASEEQ(const char* lhs_expression,
+                                   const char* rhs_expression,
+                                   const char* lhs,
+                                   const char* rhs) {
+  if (String::CaseInsensitiveCStringEquals(lhs, rhs)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(lhs_expression,
+                   rhs_expression,
+                   PrintToString(lhs),
+                   PrintToString(rhs),
+                   true);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                               const char* s2_expression,
+                               const char* s1,
+                               const char* s2) {
+  if (!String::CStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  } else {
+    return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+                              << s2_expression << "), actual: \""
+                              << s1 << "\" vs \"" << s2 << "\"";
+  }
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+                                   const char* s2_expression,
+                                   const char* s1,
+                                   const char* s2) {
+  if (!String::CaseInsensitiveCStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  } else {
+    return AssertionFailure()
+        << "Expected: (" << s1_expression << ") != ("
+        << s2_expression << ") (ignoring case), actual: \""
+        << s1 << "\" vs \"" << s2 << "\"";
+  }
+}
+
+}  // namespace internal
+
+namespace {
+
+// Helper functions for implementing IsSubString() and IsNotSubstring().
+
+// This group of overloaded functions return true if and only if needle
+// is a substring of haystack.  NULL is considered a substring of
+// itself only.
+
+bool IsSubstringPred(const char* needle, const char* haystack) {
+  if (needle == nullptr || haystack == nullptr) return needle == haystack;
+
+  return strstr(haystack, needle) != nullptr;
+}
+
+bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) {
+  if (needle == nullptr || haystack == nullptr) return needle == haystack;
+
+  return wcsstr(haystack, needle) != nullptr;
+}
+
+// StringType here can be either ::std::string or ::std::wstring.
+template <typename StringType>
+bool IsSubstringPred(const StringType& needle,
+                     const StringType& haystack) {
+  return haystack.find(needle) != StringType::npos;
+}
+
+// This function implements either IsSubstring() or IsNotSubstring(),
+// depending on the value of the expected_to_be_substring parameter.
+// StringType here can be const char*, const wchar_t*, ::std::string,
+// or ::std::wstring.
+template <typename StringType>
+AssertionResult IsSubstringImpl(
+    bool expected_to_be_substring,
+    const char* needle_expr, const char* haystack_expr,
+    const StringType& needle, const StringType& haystack) {
+  if (IsSubstringPred(needle, haystack) == expected_to_be_substring)
+    return AssertionSuccess();
+
+  const bool is_wide_string = sizeof(needle[0]) > 1;
+  const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
+  return AssertionFailure()
+      << "Value of: " << needle_expr << "\n"
+      << "  Actual: " << begin_string_quote << needle << "\"\n"
+      << "Expected: " << (expected_to_be_substring ? "" : "not ")
+      << "a substring of " << haystack_expr << "\n"
+      << "Which is: " << begin_string_quote << haystack << "\"";
+}
+
+}  // namespace
+
+// IsSubstring() and IsNotSubstring() check whether needle is a
+// substring of haystack (NULL is considered a substring of itself
+// only), and return an appropriate error message when they fail.
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+#if GTEST_HAS_STD_WSTRING
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+
+namespace {
+
+// Helper function for IsHRESULT{SuccessFailure} predicates
+AssertionResult HRESULTFailureHelper(const char* expr,
+                                     const char* expected,
+                                     long hr) {  // NOLINT
+# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_TV_TITLE
+
+  // Windows CE doesn't support FormatMessage.
+  const char error_text[] = "";
+
+# else
+
+  // Looks up the human-readable system message for the HRESULT code
+  // and since we're not passing any params to FormatMessage, we don't
+  // want inserts expanded.
+  const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM |
+                       FORMAT_MESSAGE_IGNORE_INSERTS;
+  const DWORD kBufSize = 4096;
+  // Gets the system's human readable message string for this HRESULT.
+  char error_text[kBufSize] = { '\0' };
+  DWORD message_length = ::FormatMessageA(kFlags,
+                                          0,   // no source, we're asking system
+                                          static_cast<DWORD>(hr),  // the error
+                                          0,   // no line width restrictions
+                                          error_text,  // output buffer
+                                          kBufSize,    // buf size
+                                          nullptr);  // no arguments for inserts
+  // Trims tailing white space (FormatMessage leaves a trailing CR-LF)
+  for (; message_length && IsSpace(error_text[message_length - 1]);
+          --message_length) {
+    error_text[message_length - 1] = '\0';
+  }
+
+# endif  // GTEST_OS_WINDOWS_MOBILE
+
+  const std::string error_hex("0x" + String::FormatHexInt(hr));
+  return ::testing::AssertionFailure()
+      << "Expected: " << expr << " " << expected << ".\n"
+      << "  Actual: " << error_hex << " " << error_text << "\n";
+}
+
+}  // namespace
+
+AssertionResult IsHRESULTSuccess(const char* expr, long hr) {  // NOLINT
+  if (SUCCEEDED(hr)) {
+    return AssertionSuccess();
+  }
+  return HRESULTFailureHelper(expr, "succeeds", hr);
+}
+
+AssertionResult IsHRESULTFailure(const char* expr, long hr) {  // NOLINT
+  if (FAILED(hr)) {
+    return AssertionSuccess();
+  }
+  return HRESULTFailureHelper(expr, "fails", hr);
+}
+
+#endif  // GTEST_OS_WINDOWS
+
+// Utility functions for encoding Unicode text (wide strings) in
+// UTF-8.
+
+// A Unicode code-point can have up to 21 bits, and is encoded in UTF-8
+// like this:
+//
+// Code-point length   Encoding
+//   0 -  7 bits       0xxxxxxx
+//   8 - 11 bits       110xxxxx 10xxxxxx
+//  12 - 16 bits       1110xxxx 10xxxxxx 10xxxxxx
+//  17 - 21 bits       11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+
+// The maximum code-point a one-byte UTF-8 sequence can represent.
+constexpr uint32_t kMaxCodePoint1 = (static_cast<uint32_t>(1) <<  7) - 1;
+
+// The maximum code-point a two-byte UTF-8 sequence can represent.
+constexpr uint32_t kMaxCodePoint2 = (static_cast<uint32_t>(1) << (5 + 6)) - 1;
+
+// The maximum code-point a three-byte UTF-8 sequence can represent.
+constexpr uint32_t kMaxCodePoint3 = (static_cast<uint32_t>(1) << (4 + 2*6)) - 1;
+
+// The maximum code-point a four-byte UTF-8 sequence can represent.
+constexpr uint32_t kMaxCodePoint4 = (static_cast<uint32_t>(1) << (3 + 3*6)) - 1;
+
+// Chops off the n lowest bits from a bit pattern.  Returns the n
+// lowest bits.  As a side effect, the original bit pattern will be
+// shifted to the right by n bits.
+inline uint32_t ChopLowBits(uint32_t* bits, int n) {
+  const uint32_t low_bits = *bits & ((static_cast<uint32_t>(1) << n) - 1);
+  *bits >>= n;
+  return low_bits;
+}
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type uint32_t because wchar_t may not be
+// wide enough to contain a code point.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted
+// to "(Invalid Unicode 0xXXXXXXXX)".
+std::string CodePointToUtf8(uint32_t code_point) {
+  if (code_point > kMaxCodePoint4) {
+    return "(Invalid Unicode 0x" + String::FormatHexUInt32(code_point) + ")";
+  }
+
+  char str[5];  // Big enough for the largest valid code point.
+  if (code_point <= kMaxCodePoint1) {
+    str[1] = '\0';
+    str[0] = static_cast<char>(code_point);                          // 0xxxxxxx
+  } else if (code_point <= kMaxCodePoint2) {
+    str[2] = '\0';
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xC0 | code_point);                   // 110xxxxx
+  } else if (code_point <= kMaxCodePoint3) {
+    str[3] = '\0';
+    str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xE0 | code_point);                   // 1110xxxx
+  } else {  // code_point <= kMaxCodePoint4
+    str[4] = '\0';
+    str[3] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xF0 | code_point);                   // 11110xxx
+  }
+  return str;
+}
+
+// The following two functions only make sense if the system
+// uses UTF-16 for wide string encoding. All supported systems
+// with 16 bit wchar_t (Windows, Cygwin) do use UTF-16.
+
+// Determines if the arguments constitute UTF-16 surrogate pair
+// and thus should be combined into a single Unicode code point
+// using CreateCodePointFromUtf16SurrogatePair.
+inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) {
+  return sizeof(wchar_t) == 2 &&
+      (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00;
+}
+
+// Creates a Unicode code point from UTF16 surrogate pair.
+inline uint32_t CreateCodePointFromUtf16SurrogatePair(wchar_t first,
+                                                      wchar_t second) {
+  const auto first_u = static_cast<uint32_t>(first);
+  const auto second_u = static_cast<uint32_t>(second);
+  const uint32_t mask = (1 << 10) - 1;
+  return (sizeof(wchar_t) == 2)
+             ? (((first_u & mask) << 10) | (second_u & mask)) + 0x10000
+             :
+             // This function should not be called when the condition is
+             // false, but we provide a sensible default in case it is.
+             first_u;
+}
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+//   UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin)
+//   UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+std::string WideStringToUtf8(const wchar_t* str, int num_chars) {
+  if (num_chars == -1)
+    num_chars = static_cast<int>(wcslen(str));
+
+  ::std::stringstream stream;
+  for (int i = 0; i < num_chars; ++i) {
+    uint32_t unicode_code_point;
+
+    if (str[i] == L'\0') {
+      break;
+    } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) {
+      unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i],
+                                                                 str[i + 1]);
+      i++;
+    } else {
+      unicode_code_point = static_cast<uint32_t>(str[i]);
+    }
+
+    stream << CodePointToUtf8(unicode_code_point);
+  }
+  return StringStreamToString(&stream);
+}
+
+// Converts a wide C string to an std::string using the UTF-8 encoding.
+// NULL will be converted to "(null)".
+std::string String::ShowWideCString(const wchar_t * wide_c_str) {
+  if (wide_c_str == nullptr) return "(null)";
+
+  return internal::WideStringToUtf8(wide_c_str, -1);
+}
+
+// Compares two wide C strings.  Returns true if and only if they have the
+// same content.
+//
+// Unlike wcscmp(), this function can handle NULL argument(s).  A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) {
+  if (lhs == nullptr) return rhs == nullptr;
+
+  if (rhs == nullptr) return false;
+
+  return wcscmp(lhs, rhs) == 0;
+}
+
+// Helper function for *_STREQ on wide strings.
+AssertionResult CmpHelperSTREQ(const char* lhs_expression,
+                               const char* rhs_expression,
+                               const wchar_t* lhs,
+                               const wchar_t* rhs) {
+  if (String::WideCStringEquals(lhs, rhs)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(lhs_expression,
+                   rhs_expression,
+                   PrintToString(lhs),
+                   PrintToString(rhs),
+                   false);
+}
+
+// Helper function for *_STRNE on wide strings.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                               const char* s2_expression,
+                               const wchar_t* s1,
+                               const wchar_t* s2) {
+  if (!String::WideCStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  }
+
+  return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+                            << s2_expression << "), actual: "
+                            << PrintToString(s1)
+                            << " vs " << PrintToString(s2);
+}
+
+// Compares two C strings, ignoring case.  Returns true if and only if they have
+// the same content.
+//
+// Unlike strcasecmp(), this function can handle NULL argument(s).  A
+// NULL C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) {
+  if (lhs == nullptr) return rhs == nullptr;
+  if (rhs == nullptr) return false;
+  return posix::StrCaseCmp(lhs, rhs) == 0;
+}
+
+// Compares two wide C strings, ignoring case.  Returns true if and only if they
+// have the same content.
+//
+// Unlike wcscasecmp(), this function can handle NULL argument(s).
+// A NULL C string is considered different to any non-NULL wide C string,
+// including the empty string.
+// NB: The implementations on different platforms slightly differ.
+// On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+// environment variable. On GNU platform this method uses wcscasecmp
+// which compares according to LC_CTYPE category of the current locale.
+// On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+// current locale.
+bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+                                              const wchar_t* rhs) {
+  if (lhs == nullptr) return rhs == nullptr;
+
+  if (rhs == nullptr) return false;
+
+#if GTEST_OS_WINDOWS
+  return _wcsicmp(lhs, rhs) == 0;
+#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID
+  return wcscasecmp(lhs, rhs) == 0;
+#else
+  // Android, Mac OS X and Cygwin don't define wcscasecmp.
+  // Other unknown OSes may not define it either.
+  wint_t left, right;
+  do {
+    left = towlower(static_cast<wint_t>(*lhs++));
+    right = towlower(static_cast<wint_t>(*rhs++));
+  } while (left && left == right);
+  return left == right;
+#endif  // OS selector
+}
+
+// Returns true if and only if str ends with the given suffix, ignoring case.
+// Any string is considered to end with an empty suffix.
+bool String::EndsWithCaseInsensitive(
+    const std::string& str, const std::string& suffix) {
+  const size_t str_len = str.length();
+  const size_t suffix_len = suffix.length();
+  return (str_len >= suffix_len) &&
+         CaseInsensitiveCStringEquals(str.c_str() + str_len - suffix_len,
+                                      suffix.c_str());
+}
+
+// Formats an int value as "%02d".
+std::string String::FormatIntWidth2(int value) {
+  return FormatIntWidthN(value, 2);
+}
+
+// Formats an int value to given width with leading zeros.
+std::string String::FormatIntWidthN(int value, int width) {
+  std::stringstream ss;
+  ss << std::setfill('0') << std::setw(width) << value;
+  return ss.str();
+}
+
+// Formats an int value as "%X".
+std::string String::FormatHexUInt32(uint32_t value) {
+  std::stringstream ss;
+  ss << std::hex << std::uppercase << value;
+  return ss.str();
+}
+
+// Formats an int value as "%X".
+std::string String::FormatHexInt(int value) {
+  return FormatHexUInt32(static_cast<uint32_t>(value));
+}
+
+// Formats a byte as "%02X".
+std::string String::FormatByte(unsigned char value) {
+  std::stringstream ss;
+  ss << std::setfill('0') << std::setw(2) << std::hex << std::uppercase
+     << static_cast<unsigned int>(value);
+  return ss.str();
+}
+
+// Converts the buffer in a stringstream to an std::string, converting NUL
+// bytes to "\\0" along the way.
+std::string StringStreamToString(::std::stringstream* ss) {
+  const ::std::string& str = ss->str();
+  const char* const start = str.c_str();
+  const char* const end = start + str.length();
+
+  std::string result;
+  result.reserve(static_cast<size_t>(2 * (end - start)));
+  for (const char* ch = start; ch != end; ++ch) {
+    if (*ch == '\0') {
+      result += "\\0";  // Replaces NUL with "\\0";
+    } else {
+      result += *ch;
+    }
+  }
+
+  return result;
+}
+
+// Appends the user-supplied message to the Google-Test-generated message.
+std::string AppendUserMessage(const std::string& gtest_msg,
+                              const Message& user_msg) {
+  // Appends the user message if it's non-empty.
+  const std::string user_msg_string = user_msg.GetString();
+  if (user_msg_string.empty()) {
+    return gtest_msg;
+  }
+  if (gtest_msg.empty()) {
+    return user_msg_string;
+  }
+  return gtest_msg + "\n" + user_msg_string;
+}
+
+}  // namespace internal
+
+// class TestResult
+
+// Creates an empty TestResult.
+TestResult::TestResult()
+    : death_test_count_(0), start_timestamp_(0), elapsed_time_(0) {}
+
+// D'tor.
+TestResult::~TestResult() {
+}
+
+// Returns the i-th test part result among all the results. i can
+// range from 0 to total_part_count() - 1. If i is not in that range,
+// aborts the program.
+const TestPartResult& TestResult::GetTestPartResult(int i) const {
+  if (i < 0 || i >= total_part_count())
+    internal::posix::Abort();
+  return test_part_results_.at(static_cast<size_t>(i));
+}
+
+// Returns the i-th test property. i can range from 0 to
+// test_property_count() - 1. If i is not in that range, aborts the
+// program.
+const TestProperty& TestResult::GetTestProperty(int i) const {
+  if (i < 0 || i >= test_property_count())
+    internal::posix::Abort();
+  return test_properties_.at(static_cast<size_t>(i));
+}
+
+// Clears the test part results.
+void TestResult::ClearTestPartResults() {
+  test_part_results_.clear();
+}
+
+// Adds a test part result to the list.
+void TestResult::AddTestPartResult(const TestPartResult& test_part_result) {
+  test_part_results_.push_back(test_part_result);
+}
+
+// Adds a test property to the list. If a property with the same key as the
+// supplied property is already represented, the value of this test_property
+// replaces the old value for that key.
+void TestResult::RecordProperty(const std::string& xml_element,
+                                const TestProperty& test_property) {
+  if (!ValidateTestProperty(xml_element, test_property)) {
+    return;
+  }
+  internal::MutexLock lock(&test_properties_mutex_);
+  const std::vector<TestProperty>::iterator property_with_matching_key =
+      std::find_if(test_properties_.begin(), test_properties_.end(),
+                   internal::TestPropertyKeyIs(test_property.key()));
+  if (property_with_matching_key == test_properties_.end()) {
+    test_properties_.push_back(test_property);
+    return;
+  }
+  property_with_matching_key->SetValue(test_property.value());
+}
+
+// The list of reserved attributes used in the <testsuites> element of XML
+// output.
+static const char* const kReservedTestSuitesAttributes[] = {
+  "disabled",
+  "errors",
+  "failures",
+  "name",
+  "random_seed",
+  "tests",
+  "time",
+  "timestamp"
+};
+
+// The list of reserved attributes used in the <testsuite> element of XML
+// output.
+static const char* const kReservedTestSuiteAttributes[] = {
+    "disabled", "errors", "failures",  "name",
+    "tests",    "time",   "timestamp", "skipped"};
+
+// The list of reserved attributes used in the <testcase> element of XML output.
+static const char* const kReservedTestCaseAttributes[] = {
+    "classname",   "name", "status", "time",  "type_param",
+    "value_param", "file", "line"};
+
+// Use a slightly different set for allowed output to ensure existing tests can
+// still RecordProperty("result") or "RecordProperty(timestamp")
+static const char* const kReservedOutputTestCaseAttributes[] = {
+    "classname",   "name", "status", "time",   "type_param",
+    "value_param", "file", "line",   "result", "timestamp"};
+
+template <size_t kSize>
+std::vector<std::string> ArrayAsVector(const char* const (&array)[kSize]) {
+  return std::vector<std::string>(array, array + kSize);
+}
+
+static std::vector<std::string> GetReservedAttributesForElement(
+    const std::string& xml_element) {
+  if (xml_element == "testsuites") {
+    return ArrayAsVector(kReservedTestSuitesAttributes);
+  } else if (xml_element == "testsuite") {
+    return ArrayAsVector(kReservedTestSuiteAttributes);
+  } else if (xml_element == "testcase") {
+    return ArrayAsVector(kReservedTestCaseAttributes);
+  } else {
+    GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element;
+  }
+  // This code is unreachable but some compilers may not realizes that.
+  return std::vector<std::string>();
+}
+
+// TODO(jdesprez): Merge the two getReserved attributes once skip is improved
+static std::vector<std::string> GetReservedOutputAttributesForElement(
+    const std::string& xml_element) {
+  if (xml_element == "testsuites") {
+    return ArrayAsVector(kReservedTestSuitesAttributes);
+  } else if (xml_element == "testsuite") {
+    return ArrayAsVector(kReservedTestSuiteAttributes);
+  } else if (xml_element == "testcase") {
+    return ArrayAsVector(kReservedOutputTestCaseAttributes);
+  } else {
+    GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element;
+  }
+  // This code is unreachable but some compilers may not realizes that.
+  return std::vector<std::string>();
+}
+
+static std::string FormatWordList(const std::vector<std::string>& words) {
+  Message word_list;
+  for (size_t i = 0; i < words.size(); ++i) {
+    if (i > 0 && words.size() > 2) {
+      word_list << ", ";
+    }
+    if (i == words.size() - 1) {
+      word_list << "and ";
+    }
+    word_list << "'" << words[i] << "'";
+  }
+  return word_list.GetString();
+}
+
+static bool ValidateTestPropertyName(
+    const std::string& property_name,
+    const std::vector<std::string>& reserved_names) {
+  if (std::find(reserved_names.begin(), reserved_names.end(), property_name) !=
+          reserved_names.end()) {
+    ADD_FAILURE() << "Reserved key used in RecordProperty(): " << property_name
+                  << " (" << FormatWordList(reserved_names)
+                  << " are reserved by " << GTEST_NAME_ << ")";
+    return false;
+  }
+  return true;
+}
+
+// Adds a failure if the key is a reserved attribute of the element named
+// xml_element.  Returns true if the property is valid.
+bool TestResult::ValidateTestProperty(const std::string& xml_element,
+                                      const TestProperty& test_property) {
+  return ValidateTestPropertyName(test_property.key(),
+                                  GetReservedAttributesForElement(xml_element));
+}
+
+// Clears the object.
+void TestResult::Clear() {
+  test_part_results_.clear();
+  test_properties_.clear();
+  death_test_count_ = 0;
+  elapsed_time_ = 0;
+}
+
+// Returns true off the test part was skipped.
+static bool TestPartSkipped(const TestPartResult& result) {
+  return result.skipped();
+}
+
+// Returns true if and only if the test was skipped.
+bool TestResult::Skipped() const {
+  return !Failed() && CountIf(test_part_results_, TestPartSkipped) > 0;
+}
+
+// Returns true if and only if the test failed.
+bool TestResult::Failed() const {
+  for (int i = 0; i < total_part_count(); ++i) {
+    if (GetTestPartResult(i).failed())
+      return true;
+  }
+  return false;
+}
+
+// Returns true if and only if the test part fatally failed.
+static bool TestPartFatallyFailed(const TestPartResult& result) {
+  return result.fatally_failed();
+}
+
+// Returns true if and only if the test fatally failed.
+bool TestResult::HasFatalFailure() const {
+  return CountIf(test_part_results_, TestPartFatallyFailed) > 0;
+}
+
+// Returns true if and only if the test part non-fatally failed.
+static bool TestPartNonfatallyFailed(const TestPartResult& result) {
+  return result.nonfatally_failed();
+}
+
+// Returns true if and only if the test has a non-fatal failure.
+bool TestResult::HasNonfatalFailure() const {
+  return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0;
+}
+
+// Gets the number of all test parts.  This is the sum of the number
+// of successful test parts and the number of failed test parts.
+int TestResult::total_part_count() const {
+  return static_cast<int>(test_part_results_.size());
+}
+
+// Returns the number of the test properties.
+int TestResult::test_property_count() const {
+  return static_cast<int>(test_properties_.size());
+}
+
+// class Test
+
+// Creates a Test object.
+
+// The c'tor saves the states of all flags.
+Test::Test()
+    : gtest_flag_saver_(new GTEST_FLAG_SAVER_) {
+}
+
+// The d'tor restores the states of all flags.  The actual work is
+// done by the d'tor of the gtest_flag_saver_ field, and thus not
+// visible here.
+Test::~Test() {
+}
+
+// Sets up the test fixture.
+//
+// A sub-class may override this.
+void Test::SetUp() {
+}
+
+// Tears down the test fixture.
+//
+// A sub-class may override this.
+void Test::TearDown() {
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const std::string& key, const std::string& value) {
+  UnitTest::GetInstance()->RecordProperty(key, value);
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const std::string& key, int value) {
+  Message value_message;
+  value_message << value;
+  RecordProperty(key, value_message.GetString().c_str());
+}
+
+namespace internal {
+
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+                                    const std::string& message) {
+  // This function is a friend of UnitTest and as such has access to
+  // AddTestPartResult.
+  UnitTest::GetInstance()->AddTestPartResult(
+      result_type,
+      nullptr,  // No info about the source file where the exception occurred.
+      -1,       // We have no info on which line caused the exception.
+      message,
+      "");  // No stack trace, either.
+}
+
+}  // namespace internal
+
+// Google Test requires all tests in the same test suite to use the same test
+// fixture class.  This function checks if the current test has the
+// same fixture class as the first test in the current test suite.  If
+// yes, it returns true; otherwise it generates a Google Test failure and
+// returns false.
+bool Test::HasSameFixtureClass() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  const TestSuite* const test_suite = impl->current_test_suite();
+
+  // Info about the first test in the current test suite.
+  const TestInfo* const first_test_info = test_suite->test_info_list()[0];
+  const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_;
+  const char* const first_test_name = first_test_info->name();
+
+  // Info about the current test.
+  const TestInfo* const this_test_info = impl->current_test_info();
+  const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_;
+  const char* const this_test_name = this_test_info->name();
+
+  if (this_fixture_id != first_fixture_id) {
+    // Is the first test defined using TEST?
+    const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId();
+    // Is this test defined using TEST?
+    const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId();
+
+    if (first_is_TEST || this_is_TEST) {
+      // Both TEST and TEST_F appear in same test suite, which is incorrect.
+      // Tell the user how to fix this.
+
+      // Gets the name of the TEST and the name of the TEST_F.  Note
+      // that first_is_TEST and this_is_TEST cannot both be true, as
+      // the fixture IDs are different for the two tests.
+      const char* const TEST_name =
+          first_is_TEST ? first_test_name : this_test_name;
+      const char* const TEST_F_name =
+          first_is_TEST ? this_test_name : first_test_name;
+
+      ADD_FAILURE()
+          << "All tests in the same test suite must use the same test fixture\n"
+          << "class, so mixing TEST_F and TEST in the same test suite is\n"
+          << "illegal.  In test suite " << this_test_info->test_suite_name()
+          << ",\n"
+          << "test " << TEST_F_name << " is defined using TEST_F but\n"
+          << "test " << TEST_name << " is defined using TEST.  You probably\n"
+          << "want to change the TEST to TEST_F or move it to another test\n"
+          << "case.";
+    } else {
+      // Two fixture classes with the same name appear in two different
+      // namespaces, which is not allowed. Tell the user how to fix this.
+      ADD_FAILURE()
+          << "All tests in the same test suite must use the same test fixture\n"
+          << "class.  However, in test suite "
+          << this_test_info->test_suite_name() << ",\n"
+          << "you defined test " << first_test_name << " and test "
+          << this_test_name << "\n"
+          << "using two different test fixture classes.  This can happen if\n"
+          << "the two classes are from different namespaces or translation\n"
+          << "units and have the same name.  You should probably rename one\n"
+          << "of the classes to put the tests into different test suites.";
+    }
+    return false;
+  }
+
+  return true;
+}
+
+#if GTEST_HAS_SEH
+
+// Adds an "exception thrown" fatal failure to the current test.  This
+// function returns its result via an output parameter pointer because VC++
+// prohibits creation of objects with destructors on stack in functions
+// using __try (see error C2712).
+static std::string* FormatSehExceptionMessage(DWORD exception_code,
+                                              const char* location) {
+  Message message;
+  message << "SEH exception with code 0x" << std::setbase(16) <<
+    exception_code << std::setbase(10) << " thrown in " << location << ".";
+
+  return new std::string(message.GetString());
+}
+
+#endif  // GTEST_HAS_SEH
+
+namespace internal {
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Adds an "exception thrown" fatal failure to the current test.
+static std::string FormatCxxExceptionMessage(const char* description,
+                                             const char* location) {
+  Message message;
+  if (description != nullptr) {
+    message << "C++ exception with description \"" << description << "\"";
+  } else {
+    message << "Unknown C++ exception";
+  }
+  message << " thrown in " << location << ".";
+
+  return message.GetString();
+}
+
+static std::string PrintTestPartResultToString(
+    const TestPartResult& test_part_result);
+
+GoogleTestFailureException::GoogleTestFailureException(
+    const TestPartResult& failure)
+    : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// We put these helper functions in the internal namespace as IBM's xlC
+// compiler rejects the code if they were declared static.
+
+// Runs the given method and handles SEH exceptions it throws, when
+// SEH is supported; returns the 0-value for type Result in case of an
+// SEH exception.  (Microsoft compilers cannot handle SEH and C++
+// exceptions in the same function.  Therefore, we provide a separate
+// wrapper function for handling SEH exceptions.)
+template <class T, typename Result>
+Result HandleSehExceptionsInMethodIfSupported(
+    T* object, Result (T::*method)(), const char* location) {
+#if GTEST_HAS_SEH
+  __try {
+    return (object->*method)();
+  } __except (internal::UnitTestOptions::GTestShouldProcessSEH(  // NOLINT
+      GetExceptionCode())) {
+    // We create the exception message on the heap because VC++ prohibits
+    // creation of objects with destructors on stack in functions using __try
+    // (see error C2712).
+    std::string* exception_message = FormatSehExceptionMessage(
+        GetExceptionCode(), location);
+    internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
+                                             *exception_message);
+    delete exception_message;
+    return static_cast<Result>(0);
+  }
+#else
+  (void)location;
+  return (object->*method)();
+#endif  // GTEST_HAS_SEH
+}
+
+// Runs the given method and catches and reports C++ and/or SEH-style
+// exceptions, if they are supported; returns the 0-value for type
+// Result in case of an SEH exception.
+template <class T, typename Result>
+Result HandleExceptionsInMethodIfSupported(
+    T* object, Result (T::*method)(), const char* location) {
+  // NOTE: The user code can affect the way in which Google Test handles
+  // exceptions by setting GTEST_FLAG(catch_exceptions), but only before
+  // RUN_ALL_TESTS() starts. It is technically possible to check the flag
+  // after the exception is caught and either report or re-throw the
+  // exception based on the flag's value:
+  //
+  // try {
+  //   // Perform the test method.
+  // } catch (...) {
+  //   if (GTEST_FLAG(catch_exceptions))
+  //     // Report the exception as failure.
+  //   else
+  //     throw;  // Re-throws the original exception.
+  // }
+  //
+  // However, the purpose of this flag is to allow the program to drop into
+  // the debugger when the exception is thrown. On most platforms, once the
+  // control enters the catch block, the exception origin information is
+  // lost and the debugger will stop the program at the point of the
+  // re-throw in this function -- instead of at the point of the original
+  // throw statement in the code under test.  For this reason, we perform
+  // the check early, sacrificing the ability to affect Google Test's
+  // exception handling in the method where the exception is thrown.
+  if (internal::GetUnitTestImpl()->catch_exceptions()) {
+#if GTEST_HAS_EXCEPTIONS
+    try {
+      return HandleSehExceptionsInMethodIfSupported(object, method, location);
+    } catch (const AssertionException&) {  // NOLINT
+      // This failure was reported already.
+    } catch (const internal::GoogleTestFailureException&) {  // NOLINT
+      // This exception type can only be thrown by a failed Google
+      // Test assertion with the intention of letting another testing
+      // framework catch it.  Therefore we just re-throw it.
+      throw;
+    } catch (const std::exception& e) {  // NOLINT
+      internal::ReportFailureInUnknownLocation(
+          TestPartResult::kFatalFailure,
+          FormatCxxExceptionMessage(e.what(), location));
+    } catch (...) {  // NOLINT
+      internal::ReportFailureInUnknownLocation(
+          TestPartResult::kFatalFailure,
+          FormatCxxExceptionMessage(nullptr, location));
+    }
+    return static_cast<Result>(0);
+#else
+    return HandleSehExceptionsInMethodIfSupported(object, method, location);
+#endif  // GTEST_HAS_EXCEPTIONS
+  } else {
+    return (object->*method)();
+  }
+}
+
+}  // namespace internal
+
+// Runs the test and updates the test result.
+void Test::Run() {
+  if (!HasSameFixtureClass()) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
+  // We will run the test only if SetUp() was successful and didn't call
+  // GTEST_SKIP().
+  if (!HasFatalFailure() && !IsSkipped()) {
+    impl->os_stack_trace_getter()->UponLeavingGTest();
+    internal::HandleExceptionsInMethodIfSupported(
+        this, &Test::TestBody, "the test body");
+  }
+
+  // However, we want to clean up as much as possible.  Hence we will
+  // always call TearDown(), even if SetUp() or the test body has
+  // failed.
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &Test::TearDown, "TearDown()");
+}
+
+// Returns true if and only if the current test has a fatal failure.
+bool Test::HasFatalFailure() {
+  return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
+}
+
+// Returns true if and only if the current test has a non-fatal failure.
+bool Test::HasNonfatalFailure() {
+  return internal::GetUnitTestImpl()->current_test_result()->
+      HasNonfatalFailure();
+}
+
+// Returns true if and only if the current test was skipped.
+bool Test::IsSkipped() {
+  return internal::GetUnitTestImpl()->current_test_result()->Skipped();
+}
+
+// class TestInfo
+
+// Constructs a TestInfo object. It assumes ownership of the test factory
+// object.
+TestInfo::TestInfo(const std::string& a_test_suite_name,
+                   const std::string& a_name, const char* a_type_param,
+                   const char* a_value_param,
+                   internal::CodeLocation a_code_location,
+                   internal::TypeId fixture_class_id,
+                   internal::TestFactoryBase* factory)
+    : test_suite_name_(a_test_suite_name),
+      name_(a_name),
+      type_param_(a_type_param ? new std::string(a_type_param) : nullptr),
+      value_param_(a_value_param ? new std::string(a_value_param) : nullptr),
+      location_(a_code_location),
+      fixture_class_id_(fixture_class_id),
+      should_run_(false),
+      is_disabled_(false),
+      matches_filter_(false),
+      is_in_another_shard_(false),
+      factory_(factory),
+      result_() {}
+
+// Destructs a TestInfo object.
+TestInfo::~TestInfo() { delete factory_; }
+
+namespace internal {
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+//   test_suite_name:  name of the test suite
+//   name:             name of the test
+//   type_param:       the name of the test's type parameter, or NULL if
+//                     this is not a typed or a type-parameterized test.
+//   value_param:      text representation of the test's value parameter,
+//                     or NULL if this is not a value-parameterized test.
+//   code_location:    code location where the test is defined
+//   fixture_class_id: ID of the test fixture class
+//   set_up_tc:        pointer to the function that sets up the test suite
+//   tear_down_tc:     pointer to the function that tears down the test suite
+//   factory:          pointer to the factory that creates a test object.
+//                     The newly created TestInfo instance will assume
+//                     ownership of the factory object.
+TestInfo* MakeAndRegisterTestInfo(
+    const char* test_suite_name, const char* name, const char* type_param,
+    const char* value_param, CodeLocation code_location,
+    TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc,
+    TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory) {
+  TestInfo* const test_info =
+      new TestInfo(test_suite_name, name, type_param, value_param,
+                   code_location, fixture_class_id, factory);
+  GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
+  return test_info;
+}
+
+void ReportInvalidTestSuiteType(const char* test_suite_name,
+                                CodeLocation code_location) {
+  Message errors;
+  errors
+      << "Attempted redefinition of test suite " << test_suite_name << ".\n"
+      << "All tests in the same test suite must use the same test fixture\n"
+      << "class.  However, in test suite " << test_suite_name << ", you tried\n"
+      << "to define a test using a fixture class different from the one\n"
+      << "used earlier. This can happen if the two fixture classes are\n"
+      << "from different namespaces and have the same name. You should\n"
+      << "probably rename one of the classes to put the tests into different\n"
+      << "test suites.";
+
+  GTEST_LOG_(ERROR) << FormatFileLocation(code_location.file.c_str(),
+                                          code_location.line)
+                    << " " << errors.GetString();
+}
+}  // namespace internal
+
+namespace {
+
+// A predicate that checks the test name of a TestInfo against a known
+// value.
+//
+// This is used for implementation of the TestSuite class only.  We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestNameIs is copyable.
+class TestNameIs {
+ public:
+  // Constructor.
+  //
+  // TestNameIs has NO default constructor.
+  explicit TestNameIs(const char* name)
+      : name_(name) {}
+
+  // Returns true if and only if the test name of test_info matches name_.
+  bool operator()(const TestInfo * test_info) const {
+    return test_info && test_info->name() == name_;
+  }
+
+ private:
+  std::string name_;
+};
+
+}  // namespace
+
+namespace internal {
+
+// This method expands all parameterized tests registered with macros TEST_P
+// and INSTANTIATE_TEST_SUITE_P into regular tests and registers those.
+// This will be done just once during the program runtime.
+void UnitTestImpl::RegisterParameterizedTests() {
+  if (!parameterized_tests_registered_) {
+    parameterized_test_registry_.RegisterTests();
+    type_parameterized_test_registry_.CheckForInstantiations();
+    parameterized_tests_registered_ = true;
+  }
+}
+
+}  // namespace internal
+
+// Creates the test object, runs it, records its result, and then
+// deletes it.
+void TestInfo::Run() {
+  if (!should_run_) return;
+
+  // Tells UnitTest where to store test result.
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->set_current_test_info(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  // Notifies the unit test event listeners that a test is about to start.
+  repeater->OnTestStart(*this);
+
+  result_.set_start_timestamp(internal::GetTimeInMillis());
+  internal::Timer timer;
+
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+
+  // Creates the test object.
+  Test* const test = internal::HandleExceptionsInMethodIfSupported(
+      factory_, &internal::TestFactoryBase::CreateTest,
+      "the test fixture's constructor");
+
+  // Runs the test if the constructor didn't generate a fatal failure or invoke
+  // GTEST_SKIP().
+  // Note that the object will not be null
+  if (!Test::HasFatalFailure() && !Test::IsSkipped()) {
+    // This doesn't throw as all user code that can throw are wrapped into
+    // exception handling code.
+    test->Run();
+  }
+
+  if (test != nullptr) {
+    // Deletes the test object.
+    impl->os_stack_trace_getter()->UponLeavingGTest();
+    internal::HandleExceptionsInMethodIfSupported(
+        test, &Test::DeleteSelf_, "the test fixture's destructor");
+  }
+
+  result_.set_elapsed_time(timer.Elapsed());
+
+  // Notifies the unit test event listener that a test has just finished.
+  repeater->OnTestEnd(*this);
+
+  // Tells UnitTest to stop associating assertion results to this
+  // test.
+  impl->set_current_test_info(nullptr);
+}
+
+// Skip and records a skipped test result for this object.
+void TestInfo::Skip() {
+  if (!should_run_) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->set_current_test_info(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  // Notifies the unit test event listeners that a test is about to start.
+  repeater->OnTestStart(*this);
+
+  const TestPartResult test_part_result =
+      TestPartResult(TestPartResult::kSkip, this->file(), this->line(), "");
+  impl->GetTestPartResultReporterForCurrentThread()->ReportTestPartResult(
+      test_part_result);
+
+  // Notifies the unit test event listener that a test has just finished.
+  repeater->OnTestEnd(*this);
+  impl->set_current_test_info(nullptr);
+}
+
+// class TestSuite
+
+// Gets the number of successful tests in this test suite.
+int TestSuite::successful_test_count() const {
+  return CountIf(test_info_list_, TestPassed);
+}
+
+// Gets the number of successful tests in this test suite.
+int TestSuite::skipped_test_count() const {
+  return CountIf(test_info_list_, TestSkipped);
+}
+
+// Gets the number of failed tests in this test suite.
+int TestSuite::failed_test_count() const {
+  return CountIf(test_info_list_, TestFailed);
+}
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int TestSuite::reportable_disabled_test_count() const {
+  return CountIf(test_info_list_, TestReportableDisabled);
+}
+
+// Gets the number of disabled tests in this test suite.
+int TestSuite::disabled_test_count() const {
+  return CountIf(test_info_list_, TestDisabled);
+}
+
+// Gets the number of tests to be printed in the XML report.
+int TestSuite::reportable_test_count() const {
+  return CountIf(test_info_list_, TestReportable);
+}
+
+// Get the number of tests in this test suite that should run.
+int TestSuite::test_to_run_count() const {
+  return CountIf(test_info_list_, ShouldRunTest);
+}
+
+// Gets the number of all tests.
+int TestSuite::total_test_count() const {
+  return static_cast<int>(test_info_list_.size());
+}
+
+// Creates a TestSuite with the given name.
+//
+// Arguments:
+//
+//   a_name:       name of the test suite
+//   a_type_param: the name of the test suite's type parameter, or NULL if
+//                 this is not a typed or a type-parameterized test suite.
+//   set_up_tc:    pointer to the function that sets up the test suite
+//   tear_down_tc: pointer to the function that tears down the test suite
+TestSuite::TestSuite(const char* a_name, const char* a_type_param,
+                     internal::SetUpTestSuiteFunc set_up_tc,
+                     internal::TearDownTestSuiteFunc tear_down_tc)
+    : name_(a_name),
+      type_param_(a_type_param ? new std::string(a_type_param) : nullptr),
+      set_up_tc_(set_up_tc),
+      tear_down_tc_(tear_down_tc),
+      should_run_(false),
+      start_timestamp_(0),
+      elapsed_time_(0) {}
+
+// Destructor of TestSuite.
+TestSuite::~TestSuite() {
+  // Deletes every Test in the collection.
+  ForEach(test_info_list_, internal::Delete<TestInfo>);
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+const TestInfo* TestSuite::GetTestInfo(int i) const {
+  const int index = GetElementOr(test_indices_, i, -1);
+  return index < 0 ? nullptr : test_info_list_[static_cast<size_t>(index)];
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+TestInfo* TestSuite::GetMutableTestInfo(int i) {
+  const int index = GetElementOr(test_indices_, i, -1);
+  return index < 0 ? nullptr : test_info_list_[static_cast<size_t>(index)];
+}
+
+// Adds a test to this test suite.  Will delete the test upon
+// destruction of the TestSuite object.
+void TestSuite::AddTestInfo(TestInfo* test_info) {
+  test_info_list_.push_back(test_info);
+  test_indices_.push_back(static_cast<int>(test_indices_.size()));
+}
+
+// Runs every test in this TestSuite.
+void TestSuite::Run() {
+  if (!should_run_) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->set_current_test_suite(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  // Call both legacy and the new API
+  repeater->OnTestSuiteStart(*this);
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  repeater->OnTestCaseStart(*this);
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &TestSuite::RunSetUpTestSuite, "SetUpTestSuite()");
+
+  start_timestamp_ = internal::GetTimeInMillis();
+  internal::Timer timer;
+  for (int i = 0; i < total_test_count(); i++) {
+    GetMutableTestInfo(i)->Run();
+    if (GTEST_FLAG(fail_fast) && GetMutableTestInfo(i)->result()->Failed()) {
+      for (int j = i + 1; j < total_test_count(); j++) {
+        GetMutableTestInfo(j)->Skip();
+      }
+      break;
+    }
+  }
+  elapsed_time_ = timer.Elapsed();
+
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &TestSuite::RunTearDownTestSuite, "TearDownTestSuite()");
+
+  // Call both legacy and the new API
+  repeater->OnTestSuiteEnd(*this);
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  repeater->OnTestCaseEnd(*this);
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  impl->set_current_test_suite(nullptr);
+}
+
+// Skips all tests under this TestSuite.
+void TestSuite::Skip() {
+  if (!should_run_) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->set_current_test_suite(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  // Call both legacy and the new API
+  repeater->OnTestSuiteStart(*this);
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  repeater->OnTestCaseStart(*this);
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  for (int i = 0; i < total_test_count(); i++) {
+    GetMutableTestInfo(i)->Skip();
+  }
+
+  // Call both legacy and the new API
+  repeater->OnTestSuiteEnd(*this);
+  // Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  repeater->OnTestCaseEnd(*this);
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  impl->set_current_test_suite(nullptr);
+}
+
+// Clears the results of all tests in this test suite.
+void TestSuite::ClearResult() {
+  ad_hoc_test_result_.Clear();
+  ForEach(test_info_list_, TestInfo::ClearTestResult);
+}
+
+// Shuffles the tests in this test suite.
+void TestSuite::ShuffleTests(internal::Random* random) {
+  Shuffle(random, &test_indices_);
+}
+
+// Restores the test order to before the first shuffle.
+void TestSuite::UnshuffleTests() {
+  for (size_t i = 0; i < test_indices_.size(); i++) {
+    test_indices_[i] = static_cast<int>(i);
+  }
+}
+
+// Formats a countable noun.  Depending on its quantity, either the
+// singular form or the plural form is used. e.g.
+//
+// FormatCountableNoun(1, "formula", "formuli") returns "1 formula".
+// FormatCountableNoun(5, "book", "books") returns "5 books".
+static std::string FormatCountableNoun(int count,
+                                       const char * singular_form,
+                                       const char * plural_form) {
+  return internal::StreamableToString(count) + " " +
+      (count == 1 ? singular_form : plural_form);
+}
+
+// Formats the count of tests.
+static std::string FormatTestCount(int test_count) {
+  return FormatCountableNoun(test_count, "test", "tests");
+}
+
+// Formats the count of test suites.
+static std::string FormatTestSuiteCount(int test_suite_count) {
+  return FormatCountableNoun(test_suite_count, "test suite", "test suites");
+}
+
+// Converts a TestPartResult::Type enum to human-friendly string
+// representation.  Both kNonFatalFailure and kFatalFailure are translated
+// to "Failure", as the user usually doesn't care about the difference
+// between the two when viewing the test result.
+static const char * TestPartResultTypeToString(TestPartResult::Type type) {
+  switch (type) {
+    case TestPartResult::kSkip:
+      return "Skipped\n";
+    case TestPartResult::kSuccess:
+      return "Success";
+
+    case TestPartResult::kNonFatalFailure:
+    case TestPartResult::kFatalFailure:
+#ifdef _MSC_VER
+      return "error: ";
+#else
+      return "Failure\n";
+#endif
+    default:
+      return "Unknown result type";
+  }
+}
+
+namespace internal {
+namespace {
+enum class GTestColor { kDefault, kRed, kGreen, kYellow };
+}  // namespace
+
+// Prints a TestPartResult to an std::string.
+static std::string PrintTestPartResultToString(
+    const TestPartResult& test_part_result) {
+  return (Message()
+          << internal::FormatFileLocation(test_part_result.file_name(),
+                                          test_part_result.line_number())
+          << " " << TestPartResultTypeToString(test_part_result.type())
+          << test_part_result.message()).GetString();
+}
+
+// Prints a TestPartResult.
+static void PrintTestPartResult(const TestPartResult& test_part_result) {
+  const std::string& result =
+      PrintTestPartResultToString(test_part_result);
+  printf("%s\n", result.c_str());
+  fflush(stdout);
+  // If the test program runs in Visual Studio or a debugger, the
+  // following statements add the test part result message to the Output
+  // window such that the user can double-click on it to jump to the
+  // corresponding source code location; otherwise they do nothing.
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  // We don't call OutputDebugString*() on Windows Mobile, as printing
+  // to stdout is done by OutputDebugString() there already - we don't
+  // want the same message printed twice.
+  ::OutputDebugStringA(result.c_str());
+  ::OutputDebugStringA("\n");
+#endif
+}
+
+// class PrettyUnitTestResultPrinter
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE && \
+    !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT && !GTEST_OS_WINDOWS_MINGW
+
+// Returns the character attribute for the given color.
+static WORD GetColorAttribute(GTestColor color) {
+  switch (color) {
+    case GTestColor::kRed:
+      return FOREGROUND_RED;
+    case GTestColor::kGreen:
+      return FOREGROUND_GREEN;
+    case GTestColor::kYellow:
+      return FOREGROUND_RED | FOREGROUND_GREEN;
+    default:           return 0;
+  }
+}
+
+static int GetBitOffset(WORD color_mask) {
+  if (color_mask == 0) return 0;
+
+  int bitOffset = 0;
+  while ((color_mask & 1) == 0) {
+    color_mask >>= 1;
+    ++bitOffset;
+  }
+  return bitOffset;
+}
+
+static WORD GetNewColor(GTestColor color, WORD old_color_attrs) {
+  // Let's reuse the BG
+  static const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN |
+                                      BACKGROUND_RED | BACKGROUND_INTENSITY;
+  static const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN |
+                                      FOREGROUND_RED | FOREGROUND_INTENSITY;
+  const WORD existing_bg = old_color_attrs & background_mask;
+
+  WORD new_color =
+      GetColorAttribute(color) | existing_bg | FOREGROUND_INTENSITY;
+  static const int bg_bitOffset = GetBitOffset(background_mask);
+  static const int fg_bitOffset = GetBitOffset(foreground_mask);
+
+  if (((new_color & background_mask) >> bg_bitOffset) ==
+      ((new_color & foreground_mask) >> fg_bitOffset)) {
+    new_color ^= FOREGROUND_INTENSITY;  // invert intensity
+  }
+  return new_color;
+}
+
+#else
+
+// Returns the ANSI color code for the given color. GTestColor::kDefault is
+// an invalid input.
+static const char* GetAnsiColorCode(GTestColor color) {
+  switch (color) {
+    case GTestColor::kRed:
+      return "1";
+    case GTestColor::kGreen:
+      return "2";
+    case GTestColor::kYellow:
+      return "3";
+    default:
+      return nullptr;
+  }
+}
+
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns true if and only if Google Test should use colors in the output.
+bool ShouldUseColor(bool stdout_is_tty) {
+  const char* const gtest_color = GTEST_FLAG(color).c_str();
+
+  if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) {
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW
+    // On Windows the TERM variable is usually not set, but the
+    // console there does support colors.
+    return stdout_is_tty;
+#else
+    // On non-Windows platforms, we rely on the TERM variable.
+    const char* const term = posix::GetEnv("TERM");
+    const bool term_supports_color =
+        String::CStringEquals(term, "xterm") ||
+        String::CStringEquals(term, "xterm-color") ||
+        String::CStringEquals(term, "xterm-256color") ||
+        String::CStringEquals(term, "screen") ||
+        String::CStringEquals(term, "screen-256color") ||
+        String::CStringEquals(term, "tmux") ||
+        String::CStringEquals(term, "tmux-256color") ||
+        String::CStringEquals(term, "rxvt-unicode") ||
+        String::CStringEquals(term, "rxvt-unicode-256color") ||
+        String::CStringEquals(term, "linux") ||
+        String::CStringEquals(term, "cygwin");
+    return stdout_is_tty && term_supports_color;
+#endif  // GTEST_OS_WINDOWS
+  }
+
+  return String::CaseInsensitiveCStringEquals(gtest_color, "yes") ||
+      String::CaseInsensitiveCStringEquals(gtest_color, "true") ||
+      String::CaseInsensitiveCStringEquals(gtest_color, "t") ||
+      String::CStringEquals(gtest_color, "1");
+  // We take "yes", "true", "t", and "1" as meaning "yes".  If the
+  // value is neither one of these nor "auto", we treat it as "no" to
+  // be conservative.
+}
+
+// Helpers for printing colored strings to stdout. Note that on Windows, we
+// cannot simply emit special characters and have the terminal change colors.
+// This routine must actually emit the characters rather than return a string
+// that would be colored when printed, as can be done on Linux.
+
+GTEST_ATTRIBUTE_PRINTF_(2, 3)
+static void ColoredPrintf(GTestColor color, const char *fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+
+#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_ZOS || GTEST_OS_IOS || \
+    GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT || defined(ESP_PLATFORM)
+  const bool use_color = AlwaysFalse();
+#else
+  static const bool in_color_mode =
+      ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0);
+  const bool use_color = in_color_mode && (color != GTestColor::kDefault);
+#endif  // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_ZOS
+
+  if (!use_color) {
+    vprintf(fmt, args);
+    va_end(args);
+    return;
+  }
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE && \
+    !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT && !GTEST_OS_WINDOWS_MINGW
+  const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
+
+  // Gets the current text color.
+  CONSOLE_SCREEN_BUFFER_INFO buffer_info;
+  GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
+  const WORD old_color_attrs = buffer_info.wAttributes;
+  const WORD new_color = GetNewColor(color, old_color_attrs);
+
+  // We need to flush the stream buffers into the console before each
+  // SetConsoleTextAttribute call lest it affect the text that is already
+  // printed but has not yet reached the console.
+  fflush(stdout);
+  SetConsoleTextAttribute(stdout_handle, new_color);
+
+  vprintf(fmt, args);
+
+  fflush(stdout);
+  // Restores the text color.
+  SetConsoleTextAttribute(stdout_handle, old_color_attrs);
+#else
+  printf("\033[0;3%sm", GetAnsiColorCode(color));
+  vprintf(fmt, args);
+  printf("\033[m");  // Resets the terminal to default.
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  va_end(args);
+}
+
+// Text printed in Google Test's text output and --gtest_list_tests
+// output to label the type parameter and value parameter for a test.
+static const char kTypeParamLabel[] = "TypeParam";
+static const char kValueParamLabel[] = "GetParam()";
+
+static void PrintFullTestCommentIfPresent(const TestInfo& test_info) {
+  const char* const type_param = test_info.type_param();
+  const char* const value_param = test_info.value_param();
+
+  if (type_param != nullptr || value_param != nullptr) {
+    printf(", where ");
+    if (type_param != nullptr) {
+      printf("%s = %s", kTypeParamLabel, type_param);
+      if (value_param != nullptr) printf(" and ");
+    }
+    if (value_param != nullptr) {
+      printf("%s = %s", kValueParamLabel, value_param);
+    }
+  }
+}
+
+// This class implements the TestEventListener interface.
+//
+// Class PrettyUnitTestResultPrinter is copyable.
+class PrettyUnitTestResultPrinter : public TestEventListener {
+ public:
+  PrettyUnitTestResultPrinter() {}
+  static void PrintTestName(const char* test_suite, const char* test) {
+    printf("%s.%s", test_suite, test);
+  }
+
+  // The following methods override what's in the TestEventListener class.
+  void OnTestProgramStart(const UnitTest& /*unit_test*/) override {}
+  void OnTestIterationStart(const UnitTest& unit_test, int iteration) override;
+  void OnEnvironmentsSetUpStart(const UnitTest& unit_test) override;
+  void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {}
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseStart(const TestCase& test_case) override;
+#else
+  void OnTestSuiteStart(const TestSuite& test_suite) override;
+#endif  // OnTestCaseStart
+
+  void OnTestStart(const TestInfo& test_info) override;
+
+  void OnTestPartResult(const TestPartResult& result) override;
+  void OnTestEnd(const TestInfo& test_info) override;
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseEnd(const TestCase& test_case) override;
+#else
+  void OnTestSuiteEnd(const TestSuite& test_suite) override;
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  void OnEnvironmentsTearDownStart(const UnitTest& unit_test) override;
+  void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {}
+  void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override;
+  void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {}
+
+ private:
+  static void PrintFailedTests(const UnitTest& unit_test);
+  static void PrintFailedTestSuites(const UnitTest& unit_test);
+  static void PrintSkippedTests(const UnitTest& unit_test);
+};
+
+  // Fired before each iteration of tests starts.
+void PrettyUnitTestResultPrinter::OnTestIterationStart(
+    const UnitTest& unit_test, int iteration) {
+  if (GTEST_FLAG(repeat) != 1)
+    printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1);
+
+  const char* const filter = GTEST_FLAG(filter).c_str();
+
+  // Prints the filter if it's not *.  This reminds the user that some
+  // tests may be skipped.
+  if (!String::CStringEquals(filter, kUniversalFilter)) {
+    ColoredPrintf(GTestColor::kYellow, "Note: %s filter = %s\n", GTEST_NAME_,
+                  filter);
+  }
+
+  if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) {
+    const int32_t shard_index = Int32FromEnvOrDie(kTestShardIndex, -1);
+    ColoredPrintf(GTestColor::kYellow, "Note: This is test shard %d of %s.\n",
+                  static_cast<int>(shard_index) + 1,
+                  internal::posix::GetEnv(kTestTotalShards));
+  }
+
+  if (GTEST_FLAG(shuffle)) {
+    ColoredPrintf(GTestColor::kYellow,
+                  "Note: Randomizing tests' orders with a seed of %d .\n",
+                  unit_test.random_seed());
+  }
+
+  ColoredPrintf(GTestColor::kGreen, "[==========] ");
+  printf("Running %s from %s.\n",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestSuiteCount(unit_test.test_suite_to_run_count()).c_str());
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart(
+    const UnitTest& /*unit_test*/) {
+  ColoredPrintf(GTestColor::kGreen, "[----------] ");
+  printf("Global test environment set-up.\n");
+  fflush(stdout);
+}
+
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
+  const std::string counts =
+      FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+  ColoredPrintf(GTestColor::kGreen, "[----------] ");
+  printf("%s from %s", counts.c_str(), test_case.name());
+  if (test_case.type_param() == nullptr) {
+    printf("\n");
+  } else {
+    printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param());
+  }
+  fflush(stdout);
+}
+#else
+void PrettyUnitTestResultPrinter::OnTestSuiteStart(
+    const TestSuite& test_suite) {
+  const std::string counts =
+      FormatCountableNoun(test_suite.test_to_run_count(), "test", "tests");
+  ColoredPrintf(GTestColor::kGreen, "[----------] ");
+  printf("%s from %s", counts.c_str(), test_suite.name());
+  if (test_suite.type_param() == nullptr) {
+    printf("\n");
+  } else {
+    printf(", where %s = %s\n", kTypeParamLabel, test_suite.type_param());
+  }
+  fflush(stdout);
+}
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) {
+  ColoredPrintf(GTestColor::kGreen, "[ RUN      ] ");
+  PrintTestName(test_info.test_suite_name(), test_info.name());
+  printf("\n");
+  fflush(stdout);
+}
+
+// Called after an assertion failure.
+void PrettyUnitTestResultPrinter::OnTestPartResult(
+    const TestPartResult& result) {
+  switch (result.type()) {
+    // If the test part succeeded, we don't need to do anything.
+    case TestPartResult::kSuccess:
+      return;
+    default:
+      // Print failure message from the assertion
+      // (e.g. expected this and got that).
+      PrintTestPartResult(result);
+      fflush(stdout);
+  }
+}
+
+void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
+  if (test_info.result()->Passed()) {
+    ColoredPrintf(GTestColor::kGreen, "[       OK ] ");
+  } else if (test_info.result()->Skipped()) {
+    ColoredPrintf(GTestColor::kGreen, "[  SKIPPED ] ");
+  } else {
+    ColoredPrintf(GTestColor::kRed, "[  FAILED  ] ");
+  }
+  PrintTestName(test_info.test_suite_name(), test_info.name());
+  if (test_info.result()->Failed())
+    PrintFullTestCommentIfPresent(test_info);
+
+  if (GTEST_FLAG(print_time)) {
+    printf(" (%s ms)\n", internal::StreamableToString(
+           test_info.result()->elapsed_time()).c_str());
+  } else {
+    printf("\n");
+  }
+  fflush(stdout);
+}
+
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) {
+  if (!GTEST_FLAG(print_time)) return;
+
+  const std::string counts =
+      FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+  ColoredPrintf(GTestColor::kGreen, "[----------] ");
+  printf("%s from %s (%s ms total)\n\n", counts.c_str(), test_case.name(),
+         internal::StreamableToString(test_case.elapsed_time()).c_str());
+  fflush(stdout);
+}
+#else
+void PrettyUnitTestResultPrinter::OnTestSuiteEnd(const TestSuite& test_suite) {
+  if (!GTEST_FLAG(print_time)) return;
+
+  const std::string counts =
+      FormatCountableNoun(test_suite.test_to_run_count(), "test", "tests");
+  ColoredPrintf(GTestColor::kGreen, "[----------] ");
+  printf("%s from %s (%s ms total)\n\n", counts.c_str(), test_suite.name(),
+         internal::StreamableToString(test_suite.elapsed_time()).c_str());
+  fflush(stdout);
+}
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart(
+    const UnitTest& /*unit_test*/) {
+  ColoredPrintf(GTestColor::kGreen, "[----------] ");
+  printf("Global test environment tear-down\n");
+  fflush(stdout);
+}
+
+// Internal helper for printing the list of failed tests.
+void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) {
+  const int failed_test_count = unit_test.failed_test_count();
+  ColoredPrintf(GTestColor::kRed, "[  FAILED  ] ");
+  printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str());
+
+  for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
+    const TestSuite& test_suite = *unit_test.GetTestSuite(i);
+    if (!test_suite.should_run() || (test_suite.failed_test_count() == 0)) {
+      continue;
+    }
+    for (int j = 0; j < test_suite.total_test_count(); ++j) {
+      const TestInfo& test_info = *test_suite.GetTestInfo(j);
+      if (!test_info.should_run() || !test_info.result()->Failed()) {
+        continue;
+      }
+      ColoredPrintf(GTestColor::kRed, "[  FAILED  ] ");
+      printf("%s.%s", test_suite.name(), test_info.name());
+      PrintFullTestCommentIfPresent(test_info);
+      printf("\n");
+    }
+  }
+  printf("\n%2d FAILED %s\n", failed_test_count,
+         failed_test_count == 1 ? "TEST" : "TESTS");
+}
+
+// Internal helper for printing the list of test suite failures not covered by
+// PrintFailedTests.
+void PrettyUnitTestResultPrinter::PrintFailedTestSuites(
+    const UnitTest& unit_test) {
+  int suite_failure_count = 0;
+  for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
+    const TestSuite& test_suite = *unit_test.GetTestSuite(i);
+    if (!test_suite.should_run()) {
+      continue;
+    }
+    if (test_suite.ad_hoc_test_result().Failed()) {
+      ColoredPrintf(GTestColor::kRed, "[  FAILED  ] ");
+      printf("%s: SetUpTestSuite or TearDownTestSuite\n", test_suite.name());
+      ++suite_failure_count;
+    }
+  }
+  if (suite_failure_count > 0) {
+    printf("\n%2d FAILED TEST %s\n", suite_failure_count,
+           suite_failure_count == 1 ? "SUITE" : "SUITES");
+  }
+}
+
+// Internal helper for printing the list of skipped tests.
+void PrettyUnitTestResultPrinter::PrintSkippedTests(const UnitTest& unit_test) {
+  const int skipped_test_count = unit_test.skipped_test_count();
+  if (skipped_test_count == 0) {
+    return;
+  }
+
+  for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
+    const TestSuite& test_suite = *unit_test.GetTestSuite(i);
+    if (!test_suite.should_run() || (test_suite.skipped_test_count() == 0)) {
+      continue;
+    }
+    for (int j = 0; j < test_suite.total_test_count(); ++j) {
+      const TestInfo& test_info = *test_suite.GetTestInfo(j);
+      if (!test_info.should_run() || !test_info.result()->Skipped()) {
+        continue;
+      }
+      ColoredPrintf(GTestColor::kGreen, "[  SKIPPED ] ");
+      printf("%s.%s", test_suite.name(), test_info.name());
+      printf("\n");
+    }
+  }
+}
+
+void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                     int /*iteration*/) {
+  ColoredPrintf(GTestColor::kGreen, "[==========] ");
+  printf("%s from %s ran.",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestSuiteCount(unit_test.test_suite_to_run_count()).c_str());
+  if (GTEST_FLAG(print_time)) {
+    printf(" (%s ms total)",
+           internal::StreamableToString(unit_test.elapsed_time()).c_str());
+  }
+  printf("\n");
+  ColoredPrintf(GTestColor::kGreen, "[  PASSED  ] ");
+  printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str());
+
+  const int skipped_test_count = unit_test.skipped_test_count();
+  if (skipped_test_count > 0) {
+    ColoredPrintf(GTestColor::kGreen, "[  SKIPPED ] ");
+    printf("%s, listed below:\n", FormatTestCount(skipped_test_count).c_str());
+    PrintSkippedTests(unit_test);
+  }
+
+  if (!unit_test.Passed()) {
+    PrintFailedTests(unit_test);
+    PrintFailedTestSuites(unit_test);
+  }
+
+  int num_disabled = unit_test.reportable_disabled_test_count();
+  if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) {
+    if (unit_test.Passed()) {
+      printf("\n");  // Add a spacer if no FAILURE banner is displayed.
+    }
+    ColoredPrintf(GTestColor::kYellow, "  YOU HAVE %d DISABLED %s\n\n",
+                  num_disabled, num_disabled == 1 ? "TEST" : "TESTS");
+  }
+  // Ensure that Google Test output is printed before, e.g., heapchecker output.
+  fflush(stdout);
+}
+
+// End PrettyUnitTestResultPrinter
+
+// This class implements the TestEventListener interface.
+//
+// Class BriefUnitTestResultPrinter is copyable.
+class BriefUnitTestResultPrinter : public TestEventListener {
+ public:
+  BriefUnitTestResultPrinter() {}
+  static void PrintTestName(const char* test_suite, const char* test) {
+    printf("%s.%s", test_suite, test);
+  }
+
+  // The following methods override what's in the TestEventListener class.
+  void OnTestProgramStart(const UnitTest& /*unit_test*/) override {}
+  void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                            int /*iteration*/) override {}
+  void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) override {}
+  void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {}
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseStart(const TestCase& /*test_case*/) override {}
+#else
+  void OnTestSuiteStart(const TestSuite& /*test_suite*/) override {}
+#endif  // OnTestCaseStart
+
+  void OnTestStart(const TestInfo& /*test_info*/) override {}
+
+  void OnTestPartResult(const TestPartResult& result) override;
+  void OnTestEnd(const TestInfo& test_info) override;
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseEnd(const TestCase& /*test_case*/) override {}
+#else
+  void OnTestSuiteEnd(const TestSuite& /*test_suite*/) override {}
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) override {}
+  void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {}
+  void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override;
+  void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {}
+};
+
+// Called after an assertion failure.
+void BriefUnitTestResultPrinter::OnTestPartResult(
+    const TestPartResult& result) {
+  switch (result.type()) {
+    // If the test part succeeded, we don't need to do anything.
+    case TestPartResult::kSuccess:
+      return;
+    default:
+      // Print failure message from the assertion
+      // (e.g. expected this and got that).
+      PrintTestPartResult(result);
+      fflush(stdout);
+  }
+}
+
+void BriefUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
+  if (test_info.result()->Failed()) {
+    ColoredPrintf(GTestColor::kRed, "[  FAILED  ] ");
+    PrintTestName(test_info.test_suite_name(), test_info.name());
+    PrintFullTestCommentIfPresent(test_info);
+
+    if (GTEST_FLAG(print_time)) {
+      printf(" (%s ms)\n",
+             internal::StreamableToString(test_info.result()->elapsed_time())
+                 .c_str());
+    } else {
+      printf("\n");
+    }
+    fflush(stdout);
+  }
+}
+
+void BriefUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                    int /*iteration*/) {
+  ColoredPrintf(GTestColor::kGreen, "[==========] ");
+  printf("%s from %s ran.",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestSuiteCount(unit_test.test_suite_to_run_count()).c_str());
+  if (GTEST_FLAG(print_time)) {
+    printf(" (%s ms total)",
+           internal::StreamableToString(unit_test.elapsed_time()).c_str());
+  }
+  printf("\n");
+  ColoredPrintf(GTestColor::kGreen, "[  PASSED  ] ");
+  printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str());
+
+  const int skipped_test_count = unit_test.skipped_test_count();
+  if (skipped_test_count > 0) {
+    ColoredPrintf(GTestColor::kGreen, "[  SKIPPED ] ");
+    printf("%s.\n", FormatTestCount(skipped_test_count).c_str());
+  }
+
+  int num_disabled = unit_test.reportable_disabled_test_count();
+  if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) {
+    if (unit_test.Passed()) {
+      printf("\n");  // Add a spacer if no FAILURE banner is displayed.
+    }
+    ColoredPrintf(GTestColor::kYellow, "  YOU HAVE %d DISABLED %s\n\n",
+                  num_disabled, num_disabled == 1 ? "TEST" : "TESTS");
+  }
+  // Ensure that Google Test output is printed before, e.g., heapchecker output.
+  fflush(stdout);
+}
+
+// End BriefUnitTestResultPrinter
+
+// class TestEventRepeater
+//
+// This class forwards events to other event listeners.
+class TestEventRepeater : public TestEventListener {
+ public:
+  TestEventRepeater() : forwarding_enabled_(true) {}
+  ~TestEventRepeater() override;
+  void Append(TestEventListener *listener);
+  TestEventListener* Release(TestEventListener* listener);
+
+  // Controls whether events will be forwarded to listeners_. Set to false
+  // in death test child processes.
+  bool forwarding_enabled() const { return forwarding_enabled_; }
+  void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; }
+
+  void OnTestProgramStart(const UnitTest& unit_test) override;
+  void OnTestIterationStart(const UnitTest& unit_test, int iteration) override;
+  void OnEnvironmentsSetUpStart(const UnitTest& unit_test) override;
+  void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) override;
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseStart(const TestSuite& parameter) override;
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestSuiteStart(const TestSuite& parameter) override;
+  void OnTestStart(const TestInfo& test_info) override;
+  void OnTestPartResult(const TestPartResult& result) override;
+  void OnTestEnd(const TestInfo& test_info) override;
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseEnd(const TestCase& parameter) override;
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestSuiteEnd(const TestSuite& parameter) override;
+  void OnEnvironmentsTearDownStart(const UnitTest& unit_test) override;
+  void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) override;
+  void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override;
+  void OnTestProgramEnd(const UnitTest& unit_test) override;
+
+ private:
+  // Controls whether events will be forwarded to listeners_. Set to false
+  // in death test child processes.
+  bool forwarding_enabled_;
+  // The list of listeners that receive events.
+  std::vector<TestEventListener*> listeners_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater);
+};
+
+TestEventRepeater::~TestEventRepeater() {
+  ForEach(listeners_, Delete<TestEventListener>);
+}
+
+void TestEventRepeater::Append(TestEventListener *listener) {
+  listeners_.push_back(listener);
+}
+
+TestEventListener* TestEventRepeater::Release(TestEventListener *listener) {
+  for (size_t i = 0; i < listeners_.size(); ++i) {
+    if (listeners_[i] == listener) {
+      listeners_.erase(listeners_.begin() + static_cast<int>(i));
+      return listener;
+    }
+  }
+
+  return nullptr;
+}
+
+// Since most methods are very similar, use macros to reduce boilerplate.
+// This defines a member that forwards the call to all listeners.
+#define GTEST_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+  if (forwarding_enabled_) { \
+    for (size_t i = 0; i < listeners_.size(); i++) { \
+      listeners_[i]->Name(parameter); \
+    } \
+  } \
+}
+// This defines a member that forwards the call to all listeners in reverse
+// order.
+#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type)      \
+  void TestEventRepeater::Name(const Type& parameter) { \
+    if (forwarding_enabled_) {                          \
+      for (size_t i = listeners_.size(); i != 0; i--) { \
+        listeners_[i - 1]->Name(parameter);             \
+      }                                                 \
+    }                                                   \
+  }
+
+GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest)
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+GTEST_REPEATER_METHOD_(OnTestCaseStart, TestSuite)
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+GTEST_REPEATER_METHOD_(OnTestSuiteStart, TestSuite)
+GTEST_REPEATER_METHOD_(OnTestStart, TestInfo)
+GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult)
+GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo)
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestSuite)
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+GTEST_REVERSE_REPEATER_METHOD_(OnTestSuiteEnd, TestSuite)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest)
+
+#undef GTEST_REPEATER_METHOD_
+#undef GTEST_REVERSE_REPEATER_METHOD_
+
+void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test,
+                                             int iteration) {
+  if (forwarding_enabled_) {
+    for (size_t i = 0; i < listeners_.size(); i++) {
+      listeners_[i]->OnTestIterationStart(unit_test, iteration);
+    }
+  }
+}
+
+void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test,
+                                           int iteration) {
+  if (forwarding_enabled_) {
+    for (size_t i = listeners_.size(); i > 0; i--) {
+      listeners_[i - 1]->OnTestIterationEnd(unit_test, iteration);
+    }
+  }
+}
+
+// End TestEventRepeater
+
+// This class generates an XML output file.
+class XmlUnitTestResultPrinter : public EmptyTestEventListener {
+ public:
+  explicit XmlUnitTestResultPrinter(const char* output_file);
+
+  void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override;
+  void ListTestsMatchingFilter(const std::vector<TestSuite*>& test_suites);
+
+  // Prints an XML summary of all unit tests.
+  static void PrintXmlTestsList(std::ostream* stream,
+                                const std::vector<TestSuite*>& test_suites);
+
+ private:
+  // Is c a whitespace character that is normalized to a space character
+  // when it appears in an XML attribute value?
+  static bool IsNormalizableWhitespace(char c) {
+    return c == 0x9 || c == 0xA || c == 0xD;
+  }
+
+  // May c appear in a well-formed XML document?
+  static bool IsValidXmlCharacter(char c) {
+    return IsNormalizableWhitespace(c) || c >= 0x20;
+  }
+
+  // Returns an XML-escaped copy of the input string str.  If
+  // is_attribute is true, the text is meant to appear as an attribute
+  // value, and normalizable whitespace is preserved by replacing it
+  // with character references.
+  static std::string EscapeXml(const std::string& str, bool is_attribute);
+
+  // Returns the given string with all characters invalid in XML removed.
+  static std::string RemoveInvalidXmlCharacters(const std::string& str);
+
+  // Convenience wrapper around EscapeXml when str is an attribute value.
+  static std::string EscapeXmlAttribute(const std::string& str) {
+    return EscapeXml(str, true);
+  }
+
+  // Convenience wrapper around EscapeXml when str is not an attribute value.
+  static std::string EscapeXmlText(const char* str) {
+    return EscapeXml(str, false);
+  }
+
+  // Verifies that the given attribute belongs to the given element and
+  // streams the attribute as XML.
+  static void OutputXmlAttribute(std::ostream* stream,
+                                 const std::string& element_name,
+                                 const std::string& name,
+                                 const std::string& value);
+
+  // Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+  static void OutputXmlCDataSection(::std::ostream* stream, const char* data);
+
+  // Streams a test suite XML stanza containing the given test result.
+  //
+  // Requires: result.Failed()
+  static void OutputXmlTestSuiteForTestResult(::std::ostream* stream,
+                                              const TestResult& result);
+
+  // Streams an XML representation of a TestResult object.
+  static void OutputXmlTestResult(::std::ostream* stream,
+                                  const TestResult& result);
+
+  // Streams an XML representation of a TestInfo object.
+  static void OutputXmlTestInfo(::std::ostream* stream,
+                                const char* test_suite_name,
+                                const TestInfo& test_info);
+
+  // Prints an XML representation of a TestSuite object
+  static void PrintXmlTestSuite(::std::ostream* stream,
+                                const TestSuite& test_suite);
+
+  // Prints an XML summary of unit_test to output stream out.
+  static void PrintXmlUnitTest(::std::ostream* stream,
+                               const UnitTest& unit_test);
+
+  // Produces a string representing the test properties in a result as space
+  // delimited XML attributes based on the property key="value" pairs.
+  // When the std::string is not empty, it includes a space at the beginning,
+  // to delimit this attribute from prior attributes.
+  static std::string TestPropertiesAsXmlAttributes(const TestResult& result);
+
+  // Streams an XML representation of the test properties of a TestResult
+  // object.
+  static void OutputXmlTestProperties(std::ostream* stream,
+                                      const TestResult& result);
+
+  // The output file.
+  const std::string output_file_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
+};
+
+// Creates a new XmlUnitTestResultPrinter.
+XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
+    : output_file_(output_file) {
+  if (output_file_.empty()) {
+    GTEST_LOG_(FATAL) << "XML output file may not be null";
+  }
+}
+
+// Called after the unit test ends.
+void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                  int /*iteration*/) {
+  FILE* xmlout = OpenFileForWriting(output_file_);
+  std::stringstream stream;
+  PrintXmlUnitTest(&stream, unit_test);
+  fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());
+  fclose(xmlout);
+}
+
+void XmlUnitTestResultPrinter::ListTestsMatchingFilter(
+    const std::vector<TestSuite*>& test_suites) {
+  FILE* xmlout = OpenFileForWriting(output_file_);
+  std::stringstream stream;
+  PrintXmlTestsList(&stream, test_suites);
+  fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());
+  fclose(xmlout);
+}
+
+// Returns an XML-escaped copy of the input string str.  If is_attribute
+// is true, the text is meant to appear as an attribute value, and
+// normalizable whitespace is preserved by replacing it with character
+// references.
+//
+// Invalid XML characters in str, if any, are stripped from the output.
+// It is expected that most, if not all, of the text processed by this
+// module will consist of ordinary English text.
+// If this module is ever modified to produce version 1.1 XML output,
+// most invalid characters can be retained using character references.
+std::string XmlUnitTestResultPrinter::EscapeXml(
+    const std::string& str, bool is_attribute) {
+  Message m;
+
+  for (size_t i = 0; i < str.size(); ++i) {
+    const char ch = str[i];
+    switch (ch) {
+      case '<':
+        m << "&lt;";
+        break;
+      case '>':
+        m << "&gt;";
+        break;
+      case '&':
+        m << "&amp;";
+        break;
+      case '\'':
+        if (is_attribute)
+          m << "&apos;";
+        else
+          m << '\'';
+        break;
+      case '"':
+        if (is_attribute)
+          m << "&quot;";
+        else
+          m << '"';
+        break;
+      default:
+        if (IsValidXmlCharacter(ch)) {
+          if (is_attribute && IsNormalizableWhitespace(ch))
+            m << "&#x" << String::FormatByte(static_cast<unsigned char>(ch))
+              << ";";
+          else
+            m << ch;
+        }
+        break;
+    }
+  }
+
+  return m.GetString();
+}
+
+// Returns the given string with all characters invalid in XML removed.
+// Currently invalid characters are dropped from the string. An
+// alternative is to replace them with certain characters such as . or ?.
+std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(
+    const std::string& str) {
+  std::string output;
+  output.reserve(str.size());
+  for (std::string::const_iterator it = str.begin(); it != str.end(); ++it)
+    if (IsValidXmlCharacter(*it))
+      output.push_back(*it);
+
+  return output;
+}
+
+// The following routines generate an XML representation of a UnitTest
+// object.
+// GOOGLETEST_CM0009 DO NOT DELETE
+//
+// This is how Google Test concepts map to the DTD:
+//
+// <testsuites name="AllTests">        <-- corresponds to a UnitTest object
+//   <testsuite name="testcase-name">  <-- corresponds to a TestSuite object
+//     <testcase name="test-name">     <-- corresponds to a TestInfo object
+//       <failure message="...">...</failure>
+//       <failure message="...">...</failure>
+//       <failure message="...">...</failure>
+//                                     <-- individual assertion failures
+//     </testcase>
+//   </testsuite>
+// </testsuites>
+
+// Formats the given time in milliseconds as seconds.
+std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
+  ::std::stringstream ss;
+  ss << (static_cast<double>(ms) * 1e-3);
+  return ss.str();
+}
+
+static bool PortableLocaltime(time_t seconds, struct tm* out) {
+#if defined(_MSC_VER)
+  return localtime_s(out, &seconds) == 0;
+#elif defined(__MINGW32__) || defined(__MINGW64__)
+  // MINGW <time.h> provides neither localtime_r nor localtime_s, but uses
+  // Windows' localtime(), which has a thread-local tm buffer.
+  struct tm* tm_ptr = localtime(&seconds);  // NOLINT
+  if (tm_ptr == nullptr) return false;
+  *out = *tm_ptr;
+  return true;
+#elif defined(__STDC_LIB_EXT1__)
+  // Uses localtime_s when available as localtime_r is only available from
+  // C23 standard.
+  return localtime_s(&seconds, out) != nullptr;
+#else
+  return localtime_r(&seconds, out) != nullptr;
+#endif
+}
+
+// Converts the given epoch time in milliseconds to a date string in the ISO
+// 8601 format, without the timezone information.
+std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) {
+  struct tm time_struct;
+  if (!PortableLocaltime(static_cast<time_t>(ms / 1000), &time_struct))
+    return "";
+  // YYYY-MM-DDThh:mm:ss.sss
+  return StreamableToString(time_struct.tm_year + 1900) + "-" +
+      String::FormatIntWidth2(time_struct.tm_mon + 1) + "-" +
+      String::FormatIntWidth2(time_struct.tm_mday) + "T" +
+      String::FormatIntWidth2(time_struct.tm_hour) + ":" +
+      String::FormatIntWidth2(time_struct.tm_min) + ":" +
+      String::FormatIntWidth2(time_struct.tm_sec) + "." +
+      String::FormatIntWidthN(static_cast<int>(ms % 1000), 3);
+}
+
+// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
+                                                     const char* data) {
+  const char* segment = data;
+  *stream << "<![CDATA[";
+  for (;;) {
+    const char* const next_segment = strstr(segment, "]]>");
+    if (next_segment != nullptr) {
+      stream->write(
+          segment, static_cast<std::streamsize>(next_segment - segment));
+      *stream << "]]>]]&gt;<![CDATA[";
+      segment = next_segment + strlen("]]>");
+    } else {
+      *stream << segment;
+      break;
+    }
+  }
+  *stream << "]]>";
+}
+
+void XmlUnitTestResultPrinter::OutputXmlAttribute(
+    std::ostream* stream,
+    const std::string& element_name,
+    const std::string& name,
+    const std::string& value) {
+  const std::vector<std::string>& allowed_names =
+      GetReservedOutputAttributesForElement(element_name);
+
+  GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) !=
+                   allowed_names.end())
+      << "Attribute " << name << " is not allowed for element <" << element_name
+      << ">.";
+
+  *stream << " " << name << "=\"" << EscapeXmlAttribute(value) << "\"";
+}
+
+// Streams a test suite XML stanza containing the given test result.
+void XmlUnitTestResultPrinter::OutputXmlTestSuiteForTestResult(
+    ::std::ostream* stream, const TestResult& result) {
+  // Output the boilerplate for a minimal test suite with one test.
+  *stream << "  <testsuite";
+  OutputXmlAttribute(stream, "testsuite", "name", "NonTestSuiteFailure");
+  OutputXmlAttribute(stream, "testsuite", "tests", "1");
+  OutputXmlAttribute(stream, "testsuite", "failures", "1");
+  OutputXmlAttribute(stream, "testsuite", "disabled", "0");
+  OutputXmlAttribute(stream, "testsuite", "skipped", "0");
+  OutputXmlAttribute(stream, "testsuite", "errors", "0");
+  OutputXmlAttribute(stream, "testsuite", "time",
+                     FormatTimeInMillisAsSeconds(result.elapsed_time()));
+  OutputXmlAttribute(
+      stream, "testsuite", "timestamp",
+      FormatEpochTimeInMillisAsIso8601(result.start_timestamp()));
+  *stream << ">";
+
+  // Output the boilerplate for a minimal test case with a single test.
+  *stream << "    <testcase";
+  OutputXmlAttribute(stream, "testcase", "name", "");
+  OutputXmlAttribute(stream, "testcase", "status", "run");
+  OutputXmlAttribute(stream, "testcase", "result", "completed");
+  OutputXmlAttribute(stream, "testcase", "classname", "");
+  OutputXmlAttribute(stream, "testcase", "time",
+                     FormatTimeInMillisAsSeconds(result.elapsed_time()));
+  OutputXmlAttribute(
+      stream, "testcase", "timestamp",
+      FormatEpochTimeInMillisAsIso8601(result.start_timestamp()));
+
+  // Output the actual test result.
+  OutputXmlTestResult(stream, result);
+
+  // Complete the test suite.
+  *stream << "  </testsuite>\n";
+}
+
+// Prints an XML representation of a TestInfo object.
+void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
+                                                 const char* test_suite_name,
+                                                 const TestInfo& test_info) {
+  const TestResult& result = *test_info.result();
+  const std::string kTestsuite = "testcase";
+
+  if (test_info.is_in_another_shard()) {
+    return;
+  }
+
+  *stream << "    <testcase";
+  OutputXmlAttribute(stream, kTestsuite, "name", test_info.name());
+
+  if (test_info.value_param() != nullptr) {
+    OutputXmlAttribute(stream, kTestsuite, "value_param",
+                       test_info.value_param());
+  }
+  if (test_info.type_param() != nullptr) {
+    OutputXmlAttribute(stream, kTestsuite, "type_param",
+                       test_info.type_param());
+  }
+  if (GTEST_FLAG(list_tests)) {
+    OutputXmlAttribute(stream, kTestsuite, "file", test_info.file());
+    OutputXmlAttribute(stream, kTestsuite, "line",
+                       StreamableToString(test_info.line()));
+    *stream << " />\n";
+    return;
+  }
+
+  OutputXmlAttribute(stream, kTestsuite, "status",
+                     test_info.should_run() ? "run" : "notrun");
+  OutputXmlAttribute(stream, kTestsuite, "result",
+                     test_info.should_run()
+                         ? (result.Skipped() ? "skipped" : "completed")
+                         : "suppressed");
+  OutputXmlAttribute(stream, kTestsuite, "time",
+                     FormatTimeInMillisAsSeconds(result.elapsed_time()));
+  OutputXmlAttribute(
+      stream, kTestsuite, "timestamp",
+      FormatEpochTimeInMillisAsIso8601(result.start_timestamp()));
+  OutputXmlAttribute(stream, kTestsuite, "classname", test_suite_name);
+
+  OutputXmlTestResult(stream, result);
+}
+
+void XmlUnitTestResultPrinter::OutputXmlTestResult(::std::ostream* stream,
+                                                   const TestResult& result) {
+  int failures = 0;
+  int skips = 0;
+  for (int i = 0; i < result.total_part_count(); ++i) {
+    const TestPartResult& part = result.GetTestPartResult(i);
+    if (part.failed()) {
+      if (++failures == 1 && skips == 0) {
+        *stream << ">\n";
+      }
+      const std::string location =
+          internal::FormatCompilerIndependentFileLocation(part.file_name(),
+                                                          part.line_number());
+      const std::string summary = location + "\n" + part.summary();
+      *stream << "      <failure message=\""
+              << EscapeXmlAttribute(summary)
+              << "\" type=\"\">";
+      const std::string detail = location + "\n" + part.message();
+      OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str());
+      *stream << "</failure>\n";
+    } else if (part.skipped()) {
+      if (++skips == 1 && failures == 0) {
+        *stream << ">\n";
+      }
+      const std::string location =
+          internal::FormatCompilerIndependentFileLocation(part.file_name(),
+                                                          part.line_number());
+      const std::string summary = location + "\n" + part.summary();
+      *stream << "      <skipped message=\""
+              << EscapeXmlAttribute(summary.c_str()) << "\">";
+      const std::string detail = location + "\n" + part.message();
+      OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str());
+      *stream << "</skipped>\n";
+    }
+  }
+
+  if (failures == 0 && skips == 0 && result.test_property_count() == 0) {
+    *stream << " />\n";
+  } else {
+    if (failures == 0 && skips == 0) {
+      *stream << ">\n";
+    }
+    OutputXmlTestProperties(stream, result);
+    *stream << "    </testcase>\n";
+  }
+}
+
+// Prints an XML representation of a TestSuite object
+void XmlUnitTestResultPrinter::PrintXmlTestSuite(std::ostream* stream,
+                                                 const TestSuite& test_suite) {
+  const std::string kTestsuite = "testsuite";
+  *stream << "  <" << kTestsuite;
+  OutputXmlAttribute(stream, kTestsuite, "name", test_suite.name());
+  OutputXmlAttribute(stream, kTestsuite, "tests",
+                     StreamableToString(test_suite.reportable_test_count()));
+  if (!GTEST_FLAG(list_tests)) {
+    OutputXmlAttribute(stream, kTestsuite, "failures",
+                       StreamableToString(test_suite.failed_test_count()));
+    OutputXmlAttribute(
+        stream, kTestsuite, "disabled",
+        StreamableToString(test_suite.reportable_disabled_test_count()));
+    OutputXmlAttribute(stream, kTestsuite, "skipped",
+                       StreamableToString(test_suite.skipped_test_count()));
+
+    OutputXmlAttribute(stream, kTestsuite, "errors", "0");
+
+    OutputXmlAttribute(stream, kTestsuite, "time",
+                       FormatTimeInMillisAsSeconds(test_suite.elapsed_time()));
+    OutputXmlAttribute(
+        stream, kTestsuite, "timestamp",
+        FormatEpochTimeInMillisAsIso8601(test_suite.start_timestamp()));
+    *stream << TestPropertiesAsXmlAttributes(test_suite.ad_hoc_test_result());
+  }
+  *stream << ">\n";
+  for (int i = 0; i < test_suite.total_test_count(); ++i) {
+    if (test_suite.GetTestInfo(i)->is_reportable())
+      OutputXmlTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i));
+  }
+  *stream << "  </" << kTestsuite << ">\n";
+}
+
+// Prints an XML summary of unit_test to output stream out.
+void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream,
+                                                const UnitTest& unit_test) {
+  const std::string kTestsuites = "testsuites";
+
+  *stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+  *stream << "<" << kTestsuites;
+
+  OutputXmlAttribute(stream, kTestsuites, "tests",
+                     StreamableToString(unit_test.reportable_test_count()));
+  OutputXmlAttribute(stream, kTestsuites, "failures",
+                     StreamableToString(unit_test.failed_test_count()));
+  OutputXmlAttribute(
+      stream, kTestsuites, "disabled",
+      StreamableToString(unit_test.reportable_disabled_test_count()));
+  OutputXmlAttribute(stream, kTestsuites, "errors", "0");
+  OutputXmlAttribute(stream, kTestsuites, "time",
+                     FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
+  OutputXmlAttribute(
+      stream, kTestsuites, "timestamp",
+      FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp()));
+
+  if (GTEST_FLAG(shuffle)) {
+    OutputXmlAttribute(stream, kTestsuites, "random_seed",
+                       StreamableToString(unit_test.random_seed()));
+  }
+  *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result());
+
+  OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
+  *stream << ">\n";
+
+  for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
+    if (unit_test.GetTestSuite(i)->reportable_test_count() > 0)
+      PrintXmlTestSuite(stream, *unit_test.GetTestSuite(i));
+  }
+
+  // If there was a test failure outside of one of the test suites (like in a
+  // test environment) include that in the output.
+  if (unit_test.ad_hoc_test_result().Failed()) {
+    OutputXmlTestSuiteForTestResult(stream, unit_test.ad_hoc_test_result());
+  }
+
+  *stream << "</" << kTestsuites << ">\n";
+}
+
+void XmlUnitTestResultPrinter::PrintXmlTestsList(
+    std::ostream* stream, const std::vector<TestSuite*>& test_suites) {
+  const std::string kTestsuites = "testsuites";
+
+  *stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+  *stream << "<" << kTestsuites;
+
+  int total_tests = 0;
+  for (auto test_suite : test_suites) {
+    total_tests += test_suite->total_test_count();
+  }
+  OutputXmlAttribute(stream, kTestsuites, "tests",
+                     StreamableToString(total_tests));
+  OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
+  *stream << ">\n";
+
+  for (auto test_suite : test_suites) {
+    PrintXmlTestSuite(stream, *test_suite);
+  }
+  *stream << "</" << kTestsuites << ">\n";
+}
+
+// Produces a string representing the test properties in a result as space
+// delimited XML attributes based on the property key="value" pairs.
+std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
+    const TestResult& result) {
+  Message attributes;
+  for (int i = 0; i < result.test_property_count(); ++i) {
+    const TestProperty& property = result.GetTestProperty(i);
+    attributes << " " << property.key() << "="
+        << "\"" << EscapeXmlAttribute(property.value()) << "\"";
+  }
+  return attributes.GetString();
+}
+
+void XmlUnitTestResultPrinter::OutputXmlTestProperties(
+    std::ostream* stream, const TestResult& result) {
+  const std::string kProperties = "properties";
+  const std::string kProperty = "property";
+
+  if (result.test_property_count() <= 0) {
+    return;
+  }
+
+  *stream << "<" << kProperties << ">\n";
+  for (int i = 0; i < result.test_property_count(); ++i) {
+    const TestProperty& property = result.GetTestProperty(i);
+    *stream << "<" << kProperty;
+    *stream << " name=\"" << EscapeXmlAttribute(property.key()) << "\"";
+    *stream << " value=\"" << EscapeXmlAttribute(property.value()) << "\"";
+    *stream << "/>\n";
+  }
+  *stream << "</" << kProperties << ">\n";
+}
+
+// End XmlUnitTestResultPrinter
+
+// This class generates an JSON output file.
+class JsonUnitTestResultPrinter : public EmptyTestEventListener {
+ public:
+  explicit JsonUnitTestResultPrinter(const char* output_file);
+
+  void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override;
+
+  // Prints an JSON summary of all unit tests.
+  static void PrintJsonTestList(::std::ostream* stream,
+                                const std::vector<TestSuite*>& test_suites);
+
+ private:
+  // Returns an JSON-escaped copy of the input string str.
+  static std::string EscapeJson(const std::string& str);
+
+  //// Verifies that the given attribute belongs to the given element and
+  //// streams the attribute as JSON.
+  static void OutputJsonKey(std::ostream* stream,
+                            const std::string& element_name,
+                            const std::string& name,
+                            const std::string& value,
+                            const std::string& indent,
+                            bool comma = true);
+  static void OutputJsonKey(std::ostream* stream,
+                            const std::string& element_name,
+                            const std::string& name,
+                            int value,
+                            const std::string& indent,
+                            bool comma = true);
+
+  // Streams a test suite JSON stanza containing the given test result.
+  //
+  // Requires: result.Failed()
+  static void OutputJsonTestSuiteForTestResult(::std::ostream* stream,
+                                               const TestResult& result);
+
+  // Streams a JSON representation of a TestResult object.
+  static void OutputJsonTestResult(::std::ostream* stream,
+                                   const TestResult& result);
+
+  // Streams a JSON representation of a TestInfo object.
+  static void OutputJsonTestInfo(::std::ostream* stream,
+                                 const char* test_suite_name,
+                                 const TestInfo& test_info);
+
+  // Prints a JSON representation of a TestSuite object
+  static void PrintJsonTestSuite(::std::ostream* stream,
+                                 const TestSuite& test_suite);
+
+  // Prints a JSON summary of unit_test to output stream out.
+  static void PrintJsonUnitTest(::std::ostream* stream,
+                                const UnitTest& unit_test);
+
+  // Produces a string representing the test properties in a result as
+  // a JSON dictionary.
+  static std::string TestPropertiesAsJson(const TestResult& result,
+                                          const std::string& indent);
+
+  // The output file.
+  const std::string output_file_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(JsonUnitTestResultPrinter);
+};
+
+// Creates a new JsonUnitTestResultPrinter.
+JsonUnitTestResultPrinter::JsonUnitTestResultPrinter(const char* output_file)
+    : output_file_(output_file) {
+  if (output_file_.empty()) {
+    GTEST_LOG_(FATAL) << "JSON output file may not be null";
+  }
+}
+
+void JsonUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                  int /*iteration*/) {
+  FILE* jsonout = OpenFileForWriting(output_file_);
+  std::stringstream stream;
+  PrintJsonUnitTest(&stream, unit_test);
+  fprintf(jsonout, "%s", StringStreamToString(&stream).c_str());
+  fclose(jsonout);
+}
+
+// Returns an JSON-escaped copy of the input string str.
+std::string JsonUnitTestResultPrinter::EscapeJson(const std::string& str) {
+  Message m;
+
+  for (size_t i = 0; i < str.size(); ++i) {
+    const char ch = str[i];
+    switch (ch) {
+      case '\\':
+      case '"':
+      case '/':
+        m << '\\' << ch;
+        break;
+      case '\b':
+        m << "\\b";
+        break;
+      case '\t':
+        m << "\\t";
+        break;
+      case '\n':
+        m << "\\n";
+        break;
+      case '\f':
+        m << "\\f";
+        break;
+      case '\r':
+        m << "\\r";
+        break;
+      default:
+        if (ch < ' ') {
+          m << "\\u00" << String::FormatByte(static_cast<unsigned char>(ch));
+        } else {
+          m << ch;
+        }
+        break;
+    }
+  }
+
+  return m.GetString();
+}
+
+// The following routines generate an JSON representation of a UnitTest
+// object.
+
+// Formats the given time in milliseconds as seconds.
+static std::string FormatTimeInMillisAsDuration(TimeInMillis ms) {
+  ::std::stringstream ss;
+  ss << (static_cast<double>(ms) * 1e-3) << "s";
+  return ss.str();
+}
+
+// Converts the given epoch time in milliseconds to a date string in the
+// RFC3339 format, without the timezone information.
+static std::string FormatEpochTimeInMillisAsRFC3339(TimeInMillis ms) {
+  struct tm time_struct;
+  if (!PortableLocaltime(static_cast<time_t>(ms / 1000), &time_struct))
+    return "";
+  // YYYY-MM-DDThh:mm:ss
+  return StreamableToString(time_struct.tm_year + 1900) + "-" +
+      String::FormatIntWidth2(time_struct.tm_mon + 1) + "-" +
+      String::FormatIntWidth2(time_struct.tm_mday) + "T" +
+      String::FormatIntWidth2(time_struct.tm_hour) + ":" +
+      String::FormatIntWidth2(time_struct.tm_min) + ":" +
+      String::FormatIntWidth2(time_struct.tm_sec) + "Z";
+}
+
+static inline std::string Indent(size_t width) {
+  return std::string(width, ' ');
+}
+
+void JsonUnitTestResultPrinter::OutputJsonKey(
+    std::ostream* stream,
+    const std::string& element_name,
+    const std::string& name,
+    const std::string& value,
+    const std::string& indent,
+    bool comma) {
+  const std::vector<std::string>& allowed_names =
+      GetReservedOutputAttributesForElement(element_name);
+
+  GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) !=
+                   allowed_names.end())
+      << "Key \"" << name << "\" is not allowed for value \"" << element_name
+      << "\".";
+
+  *stream << indent << "\"" << name << "\": \"" << EscapeJson(value) << "\"";
+  if (comma)
+    *stream << ",\n";
+}
+
+void JsonUnitTestResultPrinter::OutputJsonKey(
+    std::ostream* stream,
+    const std::string& element_name,
+    const std::string& name,
+    int value,
+    const std::string& indent,
+    bool comma) {
+  const std::vector<std::string>& allowed_names =
+      GetReservedOutputAttributesForElement(element_name);
+
+  GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) !=
+                   allowed_names.end())
+      << "Key \"" << name << "\" is not allowed for value \"" << element_name
+      << "\".";
+
+  *stream << indent << "\"" << name << "\": " << StreamableToString(value);
+  if (comma)
+    *stream << ",\n";
+}
+
+// Streams a test suite JSON stanza containing the given test result.
+void JsonUnitTestResultPrinter::OutputJsonTestSuiteForTestResult(
+    ::std::ostream* stream, const TestResult& result) {
+  // Output the boilerplate for a new test suite.
+  *stream << Indent(4) << "{\n";
+  OutputJsonKey(stream, "testsuite", "name", "NonTestSuiteFailure", Indent(6));
+  OutputJsonKey(stream, "testsuite", "tests", 1, Indent(6));
+  if (!GTEST_FLAG(list_tests)) {
+    OutputJsonKey(stream, "testsuite", "failures", 1, Indent(6));
+    OutputJsonKey(stream, "testsuite", "disabled", 0, Indent(6));
+    OutputJsonKey(stream, "testsuite", "skipped", 0, Indent(6));
+    OutputJsonKey(stream, "testsuite", "errors", 0, Indent(6));
+    OutputJsonKey(stream, "testsuite", "time",
+                  FormatTimeInMillisAsDuration(result.elapsed_time()),
+                  Indent(6));
+    OutputJsonKey(stream, "testsuite", "timestamp",
+                  FormatEpochTimeInMillisAsRFC3339(result.start_timestamp()),
+                  Indent(6));
+  }
+  *stream << Indent(6) << "\"testsuite\": [\n";
+
+  // Output the boilerplate for a new test case.
+  *stream << Indent(8) << "{\n";
+  OutputJsonKey(stream, "testcase", "name", "", Indent(10));
+  OutputJsonKey(stream, "testcase", "status", "RUN", Indent(10));
+  OutputJsonKey(stream, "testcase", "result", "COMPLETED", Indent(10));
+  OutputJsonKey(stream, "testcase", "timestamp",
+                FormatEpochTimeInMillisAsRFC3339(result.start_timestamp()),
+                Indent(10));
+  OutputJsonKey(stream, "testcase", "time",
+                FormatTimeInMillisAsDuration(result.elapsed_time()),
+                Indent(10));
+  OutputJsonKey(stream, "testcase", "classname", "", Indent(10), false);
+  *stream << TestPropertiesAsJson(result, Indent(10));
+
+  // Output the actual test result.
+  OutputJsonTestResult(stream, result);
+
+  // Finish the test suite.
+  *stream << "\n" << Indent(6) << "]\n" << Indent(4) << "}";
+}
+
+// Prints a JSON representation of a TestInfo object.
+void JsonUnitTestResultPrinter::OutputJsonTestInfo(::std::ostream* stream,
+                                                   const char* test_suite_name,
+                                                   const TestInfo& test_info) {
+  const TestResult& result = *test_info.result();
+  const std::string kTestsuite = "testcase";
+  const std::string kIndent = Indent(10);
+
+  *stream << Indent(8) << "{\n";
+  OutputJsonKey(stream, kTestsuite, "name", test_info.name(), kIndent);
+
+  if (test_info.value_param() != nullptr) {
+    OutputJsonKey(stream, kTestsuite, "value_param", test_info.value_param(),
+                  kIndent);
+  }
+  if (test_info.type_param() != nullptr) {
+    OutputJsonKey(stream, kTestsuite, "type_param", test_info.type_param(),
+                  kIndent);
+  }
+  if (GTEST_FLAG(list_tests)) {
+    OutputJsonKey(stream, kTestsuite, "file", test_info.file(), kIndent);
+    OutputJsonKey(stream, kTestsuite, "line", test_info.line(), kIndent, false);
+    *stream << "\n" << Indent(8) << "}";
+    return;
+  }
+
+  OutputJsonKey(stream, kTestsuite, "status",
+                test_info.should_run() ? "RUN" : "NOTRUN", kIndent);
+  OutputJsonKey(stream, kTestsuite, "result",
+                test_info.should_run()
+                    ? (result.Skipped() ? "SKIPPED" : "COMPLETED")
+                    : "SUPPRESSED",
+                kIndent);
+  OutputJsonKey(stream, kTestsuite, "timestamp",
+                FormatEpochTimeInMillisAsRFC3339(result.start_timestamp()),
+                kIndent);
+  OutputJsonKey(stream, kTestsuite, "time",
+                FormatTimeInMillisAsDuration(result.elapsed_time()), kIndent);
+  OutputJsonKey(stream, kTestsuite, "classname", test_suite_name, kIndent,
+                false);
+  *stream << TestPropertiesAsJson(result, kIndent);
+
+  OutputJsonTestResult(stream, result);
+}
+
+void JsonUnitTestResultPrinter::OutputJsonTestResult(::std::ostream* stream,
+                                                     const TestResult& result) {
+  const std::string kIndent = Indent(10);
+
+  int failures = 0;
+  for (int i = 0; i < result.total_part_count(); ++i) {
+    const TestPartResult& part = result.GetTestPartResult(i);
+    if (part.failed()) {
+      *stream << ",\n";
+      if (++failures == 1) {
+        *stream << kIndent << "\"" << "failures" << "\": [\n";
+      }
+      const std::string location =
+          internal::FormatCompilerIndependentFileLocation(part.file_name(),
+                                                          part.line_number());
+      const std::string message = EscapeJson(location + "\n" + part.message());
+      *stream << kIndent << "  {\n"
+              << kIndent << "    \"failure\": \"" << message << "\",\n"
+              << kIndent << "    \"type\": \"\"\n"
+              << kIndent << "  }";
+    }
+  }
+
+  if (failures > 0)
+    *stream << "\n" << kIndent << "]";
+  *stream << "\n" << Indent(8) << "}";
+}
+
+// Prints an JSON representation of a TestSuite object
+void JsonUnitTestResultPrinter::PrintJsonTestSuite(
+    std::ostream* stream, const TestSuite& test_suite) {
+  const std::string kTestsuite = "testsuite";
+  const std::string kIndent = Indent(6);
+
+  *stream << Indent(4) << "{\n";
+  OutputJsonKey(stream, kTestsuite, "name", test_suite.name(), kIndent);
+  OutputJsonKey(stream, kTestsuite, "tests", test_suite.reportable_test_count(),
+                kIndent);
+  if (!GTEST_FLAG(list_tests)) {
+    OutputJsonKey(stream, kTestsuite, "failures",
+                  test_suite.failed_test_count(), kIndent);
+    OutputJsonKey(stream, kTestsuite, "disabled",
+                  test_suite.reportable_disabled_test_count(), kIndent);
+    OutputJsonKey(stream, kTestsuite, "errors", 0, kIndent);
+    OutputJsonKey(
+        stream, kTestsuite, "timestamp",
+        FormatEpochTimeInMillisAsRFC3339(test_suite.start_timestamp()),
+        kIndent);
+    OutputJsonKey(stream, kTestsuite, "time",
+                  FormatTimeInMillisAsDuration(test_suite.elapsed_time()),
+                  kIndent, false);
+    *stream << TestPropertiesAsJson(test_suite.ad_hoc_test_result(), kIndent)
+            << ",\n";
+  }
+
+  *stream << kIndent << "\"" << kTestsuite << "\": [\n";
+
+  bool comma = false;
+  for (int i = 0; i < test_suite.total_test_count(); ++i) {
+    if (test_suite.GetTestInfo(i)->is_reportable()) {
+      if (comma) {
+        *stream << ",\n";
+      } else {
+        comma = true;
+      }
+      OutputJsonTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i));
+    }
+  }
+  *stream << "\n" << kIndent << "]\n" << Indent(4) << "}";
+}
+
+// Prints a JSON summary of unit_test to output stream out.
+void JsonUnitTestResultPrinter::PrintJsonUnitTest(std::ostream* stream,
+                                                  const UnitTest& unit_test) {
+  const std::string kTestsuites = "testsuites";
+  const std::string kIndent = Indent(2);
+  *stream << "{\n";
+
+  OutputJsonKey(stream, kTestsuites, "tests", unit_test.reportable_test_count(),
+                kIndent);
+  OutputJsonKey(stream, kTestsuites, "failures", unit_test.failed_test_count(),
+                kIndent);
+  OutputJsonKey(stream, kTestsuites, "disabled",
+                unit_test.reportable_disabled_test_count(), kIndent);
+  OutputJsonKey(stream, kTestsuites, "errors", 0, kIndent);
+  if (GTEST_FLAG(shuffle)) {
+    OutputJsonKey(stream, kTestsuites, "random_seed", unit_test.random_seed(),
+                  kIndent);
+  }
+  OutputJsonKey(stream, kTestsuites, "timestamp",
+                FormatEpochTimeInMillisAsRFC3339(unit_test.start_timestamp()),
+                kIndent);
+  OutputJsonKey(stream, kTestsuites, "time",
+                FormatTimeInMillisAsDuration(unit_test.elapsed_time()), kIndent,
+                false);
+
+  *stream << TestPropertiesAsJson(unit_test.ad_hoc_test_result(), kIndent)
+          << ",\n";
+
+  OutputJsonKey(stream, kTestsuites, "name", "AllTests", kIndent);
+  *stream << kIndent << "\"" << kTestsuites << "\": [\n";
+
+  bool comma = false;
+  for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
+    if (unit_test.GetTestSuite(i)->reportable_test_count() > 0) {
+      if (comma) {
+        *stream << ",\n";
+      } else {
+        comma = true;
+      }
+      PrintJsonTestSuite(stream, *unit_test.GetTestSuite(i));
+    }
+  }
+
+  // If there was a test failure outside of one of the test suites (like in a
+  // test environment) include that in the output.
+  if (unit_test.ad_hoc_test_result().Failed()) {
+    OutputJsonTestSuiteForTestResult(stream, unit_test.ad_hoc_test_result());
+  }
+
+  *stream << "\n" << kIndent << "]\n" << "}\n";
+}
+
+void JsonUnitTestResultPrinter::PrintJsonTestList(
+    std::ostream* stream, const std::vector<TestSuite*>& test_suites) {
+  const std::string kTestsuites = "testsuites";
+  const std::string kIndent = Indent(2);
+  *stream << "{\n";
+  int total_tests = 0;
+  for (auto test_suite : test_suites) {
+    total_tests += test_suite->total_test_count();
+  }
+  OutputJsonKey(stream, kTestsuites, "tests", total_tests, kIndent);
+
+  OutputJsonKey(stream, kTestsuites, "name", "AllTests", kIndent);
+  *stream << kIndent << "\"" << kTestsuites << "\": [\n";
+
+  for (size_t i = 0; i < test_suites.size(); ++i) {
+    if (i != 0) {
+      *stream << ",\n";
+    }
+    PrintJsonTestSuite(stream, *test_suites[i]);
+  }
+
+  *stream << "\n"
+          << kIndent << "]\n"
+          << "}\n";
+}
+// Produces a string representing the test properties in a result as
+// a JSON dictionary.
+std::string JsonUnitTestResultPrinter::TestPropertiesAsJson(
+    const TestResult& result, const std::string& indent) {
+  Message attributes;
+  for (int i = 0; i < result.test_property_count(); ++i) {
+    const TestProperty& property = result.GetTestProperty(i);
+    attributes << ",\n" << indent << "\"" << property.key() << "\": "
+               << "\"" << EscapeJson(property.value()) << "\"";
+  }
+  return attributes.GetString();
+}
+
+// End JsonUnitTestResultPrinter
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Checks if str contains '=', '&', '%' or '\n' characters. If yes,
+// replaces them by "%xx" where xx is their hexadecimal value. For
+// example, replaces "=" with "%3D".  This algorithm is O(strlen(str))
+// in both time and space -- important as the input str may contain an
+// arbitrarily long test failure message and stack trace.
+std::string StreamingListener::UrlEncode(const char* str) {
+  std::string result;
+  result.reserve(strlen(str) + 1);
+  for (char ch = *str; ch != '\0'; ch = *++str) {
+    switch (ch) {
+      case '%':
+      case '=':
+      case '&':
+      case '\n':
+        result.append("%" + String::FormatByte(static_cast<unsigned char>(ch)));
+        break;
+      default:
+        result.push_back(ch);
+        break;
+    }
+  }
+  return result;
+}
+
+void StreamingListener::SocketWriter::MakeConnection() {
+  GTEST_CHECK_(sockfd_ == -1)
+      << "MakeConnection() can't be called when there is already a connection.";
+
+  addrinfo hints;
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = AF_UNSPEC;    // To allow both IPv4 and IPv6 addresses.
+  hints.ai_socktype = SOCK_STREAM;
+  addrinfo* servinfo = nullptr;
+
+  // Use the getaddrinfo() to get a linked list of IP addresses for
+  // the given host name.
+  const int error_num = getaddrinfo(
+      host_name_.c_str(), port_num_.c_str(), &hints, &servinfo);
+  if (error_num != 0) {
+    GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: "
+                        << gai_strerror(error_num);
+  }
+
+  // Loop through all the results and connect to the first we can.
+  for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != nullptr;
+       cur_addr = cur_addr->ai_next) {
+    sockfd_ = socket(
+        cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol);
+    if (sockfd_ != -1) {
+      // Connect the client socket to the server socket.
+      if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) {
+        close(sockfd_);
+        sockfd_ = -1;
+      }
+    }
+  }
+
+  freeaddrinfo(servinfo);  // all done with this structure
+
+  if (sockfd_ == -1) {
+    GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to "
+                        << host_name_ << ":" << port_num_;
+  }
+}
+
+// End of class Streaming Listener
+#endif  // GTEST_CAN_STREAM_RESULTS__
+
+// class OsStackTraceGetter
+
+const char* const OsStackTraceGetterInterface::kElidedFramesMarker =
+    "... " GTEST_NAME_ " internal frames ...";
+
+std::string OsStackTraceGetter::CurrentStackTrace(int max_depth, int skip_count)
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+#if GTEST_HAS_ABSL
+  std::string result;
+
+  if (max_depth <= 0) {
+    return result;
+  }
+
+  max_depth = std::min(max_depth, kMaxStackTraceDepth);
+
+  std::vector<void*> raw_stack(max_depth);
+  // Skips the frames requested by the caller, plus this function.
+  const int raw_stack_size =
+      absl::GetStackTrace(&raw_stack[0], max_depth, skip_count + 1);
+
+  void* caller_frame = nullptr;
+  {
+    MutexLock lock(&mutex_);
+    caller_frame = caller_frame_;
+  }
+
+  for (int i = 0; i < raw_stack_size; ++i) {
+    if (raw_stack[i] == caller_frame &&
+        !GTEST_FLAG(show_internal_stack_frames)) {
+      // Add a marker to the trace and stop adding frames.
+      absl::StrAppend(&result, kElidedFramesMarker, "\n");
+      break;
+    }
+
+    char tmp[1024];
+    const char* symbol = "(unknown)";
+    if (absl::Symbolize(raw_stack[i], tmp, sizeof(tmp))) {
+      symbol = tmp;
+    }
+
+    char line[1024];
+    snprintf(line, sizeof(line), "  %p: %s\n", raw_stack[i], symbol);
+    result += line;
+  }
+
+  return result;
+
+#else  // !GTEST_HAS_ABSL
+  static_cast<void>(max_depth);
+  static_cast<void>(skip_count);
+  return "";
+#endif  // GTEST_HAS_ABSL
+}
+
+void OsStackTraceGetter::UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_) {
+#if GTEST_HAS_ABSL
+  void* caller_frame = nullptr;
+  if (absl::GetStackTrace(&caller_frame, 1, 3) <= 0) {
+    caller_frame = nullptr;
+  }
+
+  MutexLock lock(&mutex_);
+  caller_frame_ = caller_frame;
+#endif  // GTEST_HAS_ABSL
+}
+
+// A helper class that creates the premature-exit file in its
+// constructor and deletes the file in its destructor.
+class ScopedPrematureExitFile {
+ public:
+  explicit ScopedPrematureExitFile(const char* premature_exit_filepath)
+      : premature_exit_filepath_(premature_exit_filepath ?
+                                 premature_exit_filepath : "") {
+    // If a path to the premature-exit file is specified...
+    if (!premature_exit_filepath_.empty()) {
+      // create the file with a single "0" character in it.  I/O
+      // errors are ignored as there's nothing better we can do and we
+      // don't want to fail the test because of this.
+      FILE* pfile = posix::FOpen(premature_exit_filepath, "w");
+      fwrite("0", 1, 1, pfile);
+      fclose(pfile);
+    }
+  }
+
+  ~ScopedPrematureExitFile() {
+#if !defined GTEST_OS_ESP8266
+    if (!premature_exit_filepath_.empty()) {
+      int retval = remove(premature_exit_filepath_.c_str());
+      if (retval) {
+        GTEST_LOG_(ERROR) << "Failed to remove premature exit filepath \""
+                          << premature_exit_filepath_ << "\" with error "
+                          << retval;
+      }
+    }
+#endif
+  }
+
+ private:
+  const std::string premature_exit_filepath_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedPrematureExitFile);
+};
+
+}  // namespace internal
+
+// class TestEventListeners
+
+TestEventListeners::TestEventListeners()
+    : repeater_(new internal::TestEventRepeater()),
+      default_result_printer_(nullptr),
+      default_xml_generator_(nullptr) {}
+
+TestEventListeners::~TestEventListeners() { delete repeater_; }
+
+// Returns the standard listener responsible for the default console
+// output.  Can be removed from the listeners list to shut down default
+// console output.  Note that removing this object from the listener list
+// with Release transfers its ownership to the user.
+void TestEventListeners::Append(TestEventListener* listener) {
+  repeater_->Append(listener);
+}
+
+// Removes the given event listener from the list and returns it.  It then
+// becomes the caller's responsibility to delete the listener. Returns
+// NULL if the listener is not found in the list.
+TestEventListener* TestEventListeners::Release(TestEventListener* listener) {
+  if (listener == default_result_printer_)
+    default_result_printer_ = nullptr;
+  else if (listener == default_xml_generator_)
+    default_xml_generator_ = nullptr;
+  return repeater_->Release(listener);
+}
+
+// Returns repeater that broadcasts the TestEventListener events to all
+// subscribers.
+TestEventListener* TestEventListeners::repeater() { return repeater_; }
+
+// Sets the default_result_printer attribute to the provided listener.
+// The listener is also added to the listener list and previous
+// default_result_printer is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) {
+  if (default_result_printer_ != listener) {
+    // It is an error to pass this method a listener that is already in the
+    // list.
+    delete Release(default_result_printer_);
+    default_result_printer_ = listener;
+    if (listener != nullptr) Append(listener);
+  }
+}
+
+// Sets the default_xml_generator attribute to the provided listener.  The
+// listener is also added to the listener list and previous
+// default_xml_generator is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) {
+  if (default_xml_generator_ != listener) {
+    // It is an error to pass this method a listener that is already in the
+    // list.
+    delete Release(default_xml_generator_);
+    default_xml_generator_ = listener;
+    if (listener != nullptr) Append(listener);
+  }
+}
+
+// Controls whether events will be forwarded by the repeater to the
+// listeners in the list.
+bool TestEventListeners::EventForwardingEnabled() const {
+  return repeater_->forwarding_enabled();
+}
+
+void TestEventListeners::SuppressEventForwarding() {
+  repeater_->set_forwarding_enabled(false);
+}
+
+// class UnitTest
+
+// Gets the singleton UnitTest object.  The first time this method is
+// called, a UnitTest object is constructed and returned.  Consecutive
+// calls will return the same object.
+//
+// We don't protect this under mutex_ as a user is not supposed to
+// call this before main() starts, from which point on the return
+// value will never change.
+UnitTest* UnitTest::GetInstance() {
+  // CodeGear C++Builder insists on a public destructor for the
+  // default implementation.  Use this implementation to keep good OO
+  // design with private destructor.
+
+#if defined(__BORLANDC__)
+  static UnitTest* const instance = new UnitTest;
+  return instance;
+#else
+  static UnitTest instance;
+  return &instance;
+#endif  // defined(__BORLANDC__)
+}
+
+// Gets the number of successful test suites.
+int UnitTest::successful_test_suite_count() const {
+  return impl()->successful_test_suite_count();
+}
+
+// Gets the number of failed test suites.
+int UnitTest::failed_test_suite_count() const {
+  return impl()->failed_test_suite_count();
+}
+
+// Gets the number of all test suites.
+int UnitTest::total_test_suite_count() const {
+  return impl()->total_test_suite_count();
+}
+
+// Gets the number of all test suites that contain at least one test
+// that should run.
+int UnitTest::test_suite_to_run_count() const {
+  return impl()->test_suite_to_run_count();
+}
+
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+int UnitTest::successful_test_case_count() const {
+  return impl()->successful_test_suite_count();
+}
+int UnitTest::failed_test_case_count() const {
+  return impl()->failed_test_suite_count();
+}
+int UnitTest::total_test_case_count() const {
+  return impl()->total_test_suite_count();
+}
+int UnitTest::test_case_to_run_count() const {
+  return impl()->test_suite_to_run_count();
+}
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+// Gets the number of successful tests.
+int UnitTest::successful_test_count() const {
+  return impl()->successful_test_count();
+}
+
+// Gets the number of skipped tests.
+int UnitTest::skipped_test_count() const {
+  return impl()->skipped_test_count();
+}
+
+// Gets the number of failed tests.
+int UnitTest::failed_test_count() const { return impl()->failed_test_count(); }
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int UnitTest::reportable_disabled_test_count() const {
+  return impl()->reportable_disabled_test_count();
+}
+
+// Gets the number of disabled tests.
+int UnitTest::disabled_test_count() const {
+  return impl()->disabled_test_count();
+}
+
+// Gets the number of tests to be printed in the XML report.
+int UnitTest::reportable_test_count() const {
+  return impl()->reportable_test_count();
+}
+
+// Gets the number of all tests.
+int UnitTest::total_test_count() const { return impl()->total_test_count(); }
+
+// Gets the number of tests that should run.
+int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); }
+
+// Gets the time of the test program start, in ms from the start of the
+// UNIX epoch.
+internal::TimeInMillis UnitTest::start_timestamp() const {
+    return impl()->start_timestamp();
+}
+
+// Gets the elapsed time, in milliseconds.
+internal::TimeInMillis UnitTest::elapsed_time() const {
+  return impl()->elapsed_time();
+}
+
+// Returns true if and only if the unit test passed (i.e. all test suites
+// passed).
+bool UnitTest::Passed() const { return impl()->Passed(); }
+
+// Returns true if and only if the unit test failed (i.e. some test suite
+// failed or something outside of all tests failed).
+bool UnitTest::Failed() const { return impl()->Failed(); }
+
+// Gets the i-th test suite among all the test suites. i can range from 0 to
+// total_test_suite_count() - 1. If i is not in that range, returns NULL.
+const TestSuite* UnitTest::GetTestSuite(int i) const {
+  return impl()->GetTestSuite(i);
+}
+
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+const TestCase* UnitTest::GetTestCase(int i) const {
+  return impl()->GetTestCase(i);
+}
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+// Returns the TestResult containing information on test failures and
+// properties logged outside of individual test suites.
+const TestResult& UnitTest::ad_hoc_test_result() const {
+  return *impl()->ad_hoc_test_result();
+}
+
+// Gets the i-th test suite among all the test suites. i can range from 0 to
+// total_test_suite_count() - 1. If i is not in that range, returns NULL.
+TestSuite* UnitTest::GetMutableTestSuite(int i) {
+  return impl()->GetMutableSuiteCase(i);
+}
+
+// Returns the list of event listeners that can be used to track events
+// inside Google Test.
+TestEventListeners& UnitTest::listeners() {
+  return *impl()->listeners();
+}
+
+// Registers and returns a global test environment.  When a test
+// program is run, all global test environments will be set-up in the
+// order they were registered.  After all tests in the program have
+// finished, all global test environments will be torn-down in the
+// *reverse* order they were registered.
+//
+// The UnitTest object takes ownership of the given environment.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+Environment* UnitTest::AddEnvironment(Environment* env) {
+  if (env == nullptr) {
+    return nullptr;
+  }
+
+  impl_->environments().push_back(env);
+  return env;
+}
+
+// Adds a TestPartResult to the current TestResult object.  All Google Test
+// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
+// this to report their results.  The user code should use the
+// assertion macros instead of calling this directly.
+void UnitTest::AddTestPartResult(
+    TestPartResult::Type result_type,
+    const char* file_name,
+    int line_number,
+    const std::string& message,
+    const std::string& os_stack_trace) GTEST_LOCK_EXCLUDED_(mutex_) {
+  Message msg;
+  msg << message;
+
+  internal::MutexLock lock(&mutex_);
+  if (impl_->gtest_trace_stack().size() > 0) {
+    msg << "\n" << GTEST_NAME_ << " trace:";
+
+    for (size_t i = impl_->gtest_trace_stack().size(); i > 0; --i) {
+      const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1];
+      msg << "\n" << internal::FormatFileLocation(trace.file, trace.line)
+          << " " << trace.message;
+    }
+  }
+
+  if (os_stack_trace.c_str() != nullptr && !os_stack_trace.empty()) {
+    msg << internal::kStackTraceMarker << os_stack_trace;
+  }
+
+  const TestPartResult result = TestPartResult(
+      result_type, file_name, line_number, msg.GetString().c_str());
+  impl_->GetTestPartResultReporterForCurrentThread()->
+      ReportTestPartResult(result);
+
+  if (result_type != TestPartResult::kSuccess &&
+      result_type != TestPartResult::kSkip) {
+    // gtest_break_on_failure takes precedence over
+    // gtest_throw_on_failure.  This allows a user to set the latter
+    // in the code (perhaps in order to use Google Test assertions
+    // with another testing framework) and specify the former on the
+    // command line for debugging.
+    if (GTEST_FLAG(break_on_failure)) {
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
+      // Using DebugBreak on Windows allows gtest to still break into a debugger
+      // when a failure happens and both the --gtest_break_on_failure and
+      // the --gtest_catch_exceptions flags are specified.
+      DebugBreak();
+#elif (!defined(__native_client__)) &&            \
+    ((defined(__clang__) || defined(__GNUC__)) && \
+     (defined(__x86_64__) || defined(__i386__)))
+      // with clang/gcc we can achieve the same effect on x86 by invoking int3
+      asm("int3");
+#else
+      // Dereference nullptr through a volatile pointer to prevent the compiler
+      // from removing. We use this rather than abort() or __builtin_trap() for
+      // portability: some debuggers don't correctly trap abort().
+      *static_cast<volatile int*>(nullptr) = 1;
+#endif  // GTEST_OS_WINDOWS
+    } else if (GTEST_FLAG(throw_on_failure)) {
+#if GTEST_HAS_EXCEPTIONS
+      throw internal::GoogleTestFailureException(result);
+#else
+      // We cannot call abort() as it generates a pop-up in debug mode
+      // that cannot be suppressed in VC 7.1 or below.
+      exit(1);
+#endif
+    }
+  }
+}
+
+// Adds a TestProperty to the current TestResult object when invoked from
+// inside a test, to current TestSuite's ad_hoc_test_result_ when invoked
+// from SetUpTestSuite or TearDownTestSuite, or to the global property set
+// when invoked elsewhere.  If the result already contains a property with
+// the same key, the value will be updated.
+void UnitTest::RecordProperty(const std::string& key,
+                              const std::string& value) {
+  impl_->RecordProperty(TestProperty(key, value));
+}
+
+// Runs all tests in this UnitTest object and prints the result.
+// Returns 0 if successful, or 1 otherwise.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+int UnitTest::Run() {
+  const bool in_death_test_child_process =
+      internal::GTEST_FLAG(internal_run_death_test).length() > 0;
+
+  // Google Test implements this protocol for catching that a test
+  // program exits before returning control to Google Test:
+  //
+  //   1. Upon start, Google Test creates a file whose absolute path
+  //      is specified by the environment variable
+  //      TEST_PREMATURE_EXIT_FILE.
+  //   2. When Google Test has finished its work, it deletes the file.
+  //
+  // This allows a test runner to set TEST_PREMATURE_EXIT_FILE before
+  // running a Google-Test-based test program and check the existence
+  // of the file at the end of the test execution to see if it has
+  // exited prematurely.
+
+  // If we are in the child process of a death test, don't
+  // create/delete the premature exit file, as doing so is unnecessary
+  // and will confuse the parent process.  Otherwise, create/delete
+  // the file upon entering/leaving this function.  If the program
+  // somehow exits before this function has a chance to return, the
+  // premature-exit file will be left undeleted, causing a test runner
+  // that understands the premature-exit-file protocol to report the
+  // test as having failed.
+  const internal::ScopedPrematureExitFile premature_exit_file(
+      in_death_test_child_process
+          ? nullptr
+          : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE"));
+
+  // Captures the value of GTEST_FLAG(catch_exceptions).  This value will be
+  // used for the duration of the program.
+  impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions));
+
+#if GTEST_OS_WINDOWS
+  // Either the user wants Google Test to catch exceptions thrown by the
+  // tests or this is executing in the context of death test child
+  // process. In either case the user does not want to see pop-up dialogs
+  // about crashes - they are expected.
+  if (impl()->catch_exceptions() || in_death_test_child_process) {
+# if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
+    // SetErrorMode doesn't exist on CE.
+    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
+                 SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
+# endif  // !GTEST_OS_WINDOWS_MOBILE
+
+# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE
+    // Death test children can be terminated with _abort().  On Windows,
+    // _abort() can show a dialog with a warning message.  This forces the
+    // abort message to go to stderr instead.
+    _set_error_mode(_OUT_TO_STDERR);
+# endif
+
+# if defined(_MSC_VER) && !GTEST_OS_WINDOWS_MOBILE
+    // In the debug version, Visual Studio pops up a separate dialog
+    // offering a choice to debug the aborted program. We need to suppress
+    // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement
+    // executed. Google Test will notify the user of any unexpected
+    // failure via stderr.
+    if (!GTEST_FLAG(break_on_failure))
+      _set_abort_behavior(
+          0x0,                                    // Clear the following flags:
+          _WRITE_ABORT_MSG | _CALL_REPORTFAULT);  // pop-up window, core dump.
+
+    // In debug mode, the Windows CRT can crash with an assertion over invalid
+    // input (e.g. passing an invalid file descriptor).  The default handling
+    // for these assertions is to pop up a dialog and wait for user input.
+    // Instead ask the CRT to dump such assertions to stderr non-interactively.
+    if (!IsDebuggerPresent()) {
+      (void)_CrtSetReportMode(_CRT_ASSERT,
+                              _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+      (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
+    }
+# endif
+  }
+#endif  // GTEST_OS_WINDOWS
+
+  return internal::HandleExceptionsInMethodIfSupported(
+      impl(),
+      &internal::UnitTestImpl::RunAllTests,
+      "auxiliary test code (environments or event listeners)") ? 0 : 1;
+}
+
+// Returns the working directory when the first TEST() or TEST_F() was
+// executed.
+const char* UnitTest::original_working_dir() const {
+  return impl_->original_working_dir_.c_str();
+}
+
+// Returns the TestSuite object for the test that's currently running,
+// or NULL if no test is running.
+const TestSuite* UnitTest::current_test_suite() const
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_suite();
+}
+
+// Legacy API is still available but deprecated
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+const TestCase* UnitTest::current_test_case() const
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_suite();
+}
+#endif
+
+// Returns the TestInfo object for the test that's currently running,
+// or NULL if no test is running.
+const TestInfo* UnitTest::current_test_info() const
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_info();
+}
+
+// Returns the random seed used at the start of the current test run.
+int UnitTest::random_seed() const { return impl_->random_seed(); }
+
+// Returns ParameterizedTestSuiteRegistry object used to keep track of
+// value-parameterized tests and instantiate and register them.
+internal::ParameterizedTestSuiteRegistry&
+UnitTest::parameterized_test_registry() GTEST_LOCK_EXCLUDED_(mutex_) {
+  return impl_->parameterized_test_registry();
+}
+
+// Creates an empty UnitTest.
+UnitTest::UnitTest() {
+  impl_ = new internal::UnitTestImpl(this);
+}
+
+// Destructor of UnitTest.
+UnitTest::~UnitTest() {
+  delete impl_;
+}
+
+// Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+// Google Test trace stack.
+void UnitTest::PushGTestTrace(const internal::TraceInfo& trace)
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  impl_->gtest_trace_stack().push_back(trace);
+}
+
+// Pops a trace from the per-thread Google Test trace stack.
+void UnitTest::PopGTestTrace()
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  impl_->gtest_trace_stack().pop_back();
+}
+
+namespace internal {
+
+UnitTestImpl::UnitTestImpl(UnitTest* parent)
+    : parent_(parent),
+      GTEST_DISABLE_MSC_WARNINGS_PUSH_(4355 /* using this in initializer */)
+          default_global_test_part_result_reporter_(this),
+      default_per_thread_test_part_result_reporter_(this),
+      GTEST_DISABLE_MSC_WARNINGS_POP_() global_test_part_result_repoter_(
+          &default_global_test_part_result_reporter_),
+      per_thread_test_part_result_reporter_(
+          &default_per_thread_test_part_result_reporter_),
+      parameterized_test_registry_(),
+      parameterized_tests_registered_(false),
+      last_death_test_suite_(-1),
+      current_test_suite_(nullptr),
+      current_test_info_(nullptr),
+      ad_hoc_test_result_(),
+      os_stack_trace_getter_(nullptr),
+      post_flag_parse_init_performed_(false),
+      random_seed_(0),  // Will be overridden by the flag before first use.
+      random_(0),       // Will be reseeded before first use.
+      start_timestamp_(0),
+      elapsed_time_(0),
+#if GTEST_HAS_DEATH_TEST
+      death_test_factory_(new DefaultDeathTestFactory),
+#endif
+      // Will be overridden by the flag before first use.
+      catch_exceptions_(false) {
+  listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
+}
+
+UnitTestImpl::~UnitTestImpl() {
+  // Deletes every TestSuite.
+  ForEach(test_suites_, internal::Delete<TestSuite>);
+
+  // Deletes every Environment.
+  ForEach(environments_, internal::Delete<Environment>);
+
+  delete os_stack_trace_getter_;
+}
+
+// Adds a TestProperty to the current TestResult object when invoked in a
+// context of a test, to current test suite's ad_hoc_test_result when invoke
+// from SetUpTestSuite/TearDownTestSuite, or to the global property set
+// otherwise.  If the result already contains a property with the same key,
+// the value will be updated.
+void UnitTestImpl::RecordProperty(const TestProperty& test_property) {
+  std::string xml_element;
+  TestResult* test_result;  // TestResult appropriate for property recording.
+
+  if (current_test_info_ != nullptr) {
+    xml_element = "testcase";
+    test_result = &(current_test_info_->result_);
+  } else if (current_test_suite_ != nullptr) {
+    xml_element = "testsuite";
+    test_result = &(current_test_suite_->ad_hoc_test_result_);
+  } else {
+    xml_element = "testsuites";
+    test_result = &ad_hoc_test_result_;
+  }
+  test_result->RecordProperty(xml_element, test_property);
+}
+
+#if GTEST_HAS_DEATH_TEST
+// Disables event forwarding if the control is currently in a death test
+// subprocess. Must not be called before InitGoogleTest.
+void UnitTestImpl::SuppressTestEventsIfInSubprocess() {
+  if (internal_run_death_test_flag_.get() != nullptr)
+    listeners()->SuppressEventForwarding();
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Initializes event listeners performing XML output as specified by
+// UnitTestOptions. Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureXmlOutput() {
+  const std::string& output_format = UnitTestOptions::GetOutputFormat();
+  if (output_format == "xml") {
+    listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter(
+        UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
+  } else if (output_format == "json") {
+    listeners()->SetDefaultXmlGenerator(new JsonUnitTestResultPrinter(
+        UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
+  } else if (output_format != "") {
+    GTEST_LOG_(WARNING) << "WARNING: unrecognized output format \""
+                        << output_format << "\" ignored.";
+  }
+}
+
+#if GTEST_CAN_STREAM_RESULTS_
+// Initializes event listeners for streaming test results in string form.
+// Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureStreamingOutput() {
+  const std::string& target = GTEST_FLAG(stream_result_to);
+  if (!target.empty()) {
+    const size_t pos = target.find(':');
+    if (pos != std::string::npos) {
+      listeners()->Append(new StreamingListener(target.substr(0, pos),
+                                                target.substr(pos+1)));
+    } else {
+      GTEST_LOG_(WARNING) << "unrecognized streaming target \"" << target
+                          << "\" ignored.";
+    }
+  }
+}
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+// Performs initialization dependent upon flag values obtained in
+// ParseGoogleTestFlagsOnly.  Is called from InitGoogleTest after the call to
+// ParseGoogleTestFlagsOnly.  In case a user neglects to call InitGoogleTest
+// this function is also called from RunAllTests.  Since this function can be
+// called more than once, it has to be idempotent.
+void UnitTestImpl::PostFlagParsingInit() {
+  // Ensures that this function does not execute more than once.
+  if (!post_flag_parse_init_performed_) {
+    post_flag_parse_init_performed_ = true;
+
+#if defined(GTEST_CUSTOM_TEST_EVENT_LISTENER_)
+    // Register to send notifications about key process state changes.
+    listeners()->Append(new GTEST_CUSTOM_TEST_EVENT_LISTENER_());
+#endif  // defined(GTEST_CUSTOM_TEST_EVENT_LISTENER_)
+
+#if GTEST_HAS_DEATH_TEST
+    InitDeathTestSubprocessControlInfo();
+    SuppressTestEventsIfInSubprocess();
+#endif  // GTEST_HAS_DEATH_TEST
+
+    // Registers parameterized tests. This makes parameterized tests
+    // available to the UnitTest reflection API without running
+    // RUN_ALL_TESTS.
+    RegisterParameterizedTests();
+
+    // Configures listeners for XML output. This makes it possible for users
+    // to shut down the default XML output before invoking RUN_ALL_TESTS.
+    ConfigureXmlOutput();
+
+    if (GTEST_FLAG(brief)) {
+      listeners()->SetDefaultResultPrinter(new BriefUnitTestResultPrinter);
+    }
+
+#if GTEST_CAN_STREAM_RESULTS_
+    // Configures listeners for streaming test results to the specified server.
+    ConfigureStreamingOutput();
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+#if GTEST_HAS_ABSL
+    if (GTEST_FLAG(install_failure_signal_handler)) {
+      absl::FailureSignalHandlerOptions options;
+      absl::InstallFailureSignalHandler(options);
+    }
+#endif  // GTEST_HAS_ABSL
+  }
+}
+
+// A predicate that checks the name of a TestSuite against a known
+// value.
+//
+// This is used for implementation of the UnitTest class only.  We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestSuiteNameIs is copyable.
+class TestSuiteNameIs {
+ public:
+  // Constructor.
+  explicit TestSuiteNameIs(const std::string& name) : name_(name) {}
+
+  // Returns true if and only if the name of test_suite matches name_.
+  bool operator()(const TestSuite* test_suite) const {
+    return test_suite != nullptr &&
+           strcmp(test_suite->name(), name_.c_str()) == 0;
+  }
+
+ private:
+  std::string name_;
+};
+
+// Finds and returns a TestSuite with the given name.  If one doesn't
+// exist, creates one and returns it.  It's the CALLER'S
+// RESPONSIBILITY to ensure that this function is only called WHEN THE
+// TESTS ARE NOT SHUFFLED.
+//
+// Arguments:
+//
+//   test_suite_name: name of the test suite
+//   type_param:      the name of the test suite's type parameter, or NULL if
+//                    this is not a typed or a type-parameterized test suite.
+//   set_up_tc:       pointer to the function that sets up the test suite
+//   tear_down_tc:    pointer to the function that tears down the test suite
+TestSuite* UnitTestImpl::GetTestSuite(
+    const char* test_suite_name, const char* type_param,
+    internal::SetUpTestSuiteFunc set_up_tc,
+    internal::TearDownTestSuiteFunc tear_down_tc) {
+  // Can we find a TestSuite with the given name?
+  const auto test_suite =
+      std::find_if(test_suites_.rbegin(), test_suites_.rend(),
+                   TestSuiteNameIs(test_suite_name));
+
+  if (test_suite != test_suites_.rend()) return *test_suite;
+
+  // No.  Let's create one.
+  auto* const new_test_suite =
+      new TestSuite(test_suite_name, type_param, set_up_tc, tear_down_tc);
+
+  // Is this a death test suite?
+  if (internal::UnitTestOptions::MatchesFilter(test_suite_name,
+                                               kDeathTestSuiteFilter)) {
+    // Yes.  Inserts the test suite after the last death test suite
+    // defined so far.  This only works when the test suites haven't
+    // been shuffled.  Otherwise we may end up running a death test
+    // after a non-death test.
+    ++last_death_test_suite_;
+    test_suites_.insert(test_suites_.begin() + last_death_test_suite_,
+                        new_test_suite);
+  } else {
+    // No.  Appends to the end of the list.
+    test_suites_.push_back(new_test_suite);
+  }
+
+  test_suite_indices_.push_back(static_cast<int>(test_suite_indices_.size()));
+  return new_test_suite;
+}
+
+// Helpers for setting up / tearing down the given environment.  They
+// are for use in the ForEach() function.
+static void SetUpEnvironment(Environment* env) { env->SetUp(); }
+static void TearDownEnvironment(Environment* env) { env->TearDown(); }
+
+// Runs all tests in this UnitTest object, prints the result, and
+// returns true if all tests are successful.  If any exception is
+// thrown during a test, the test is considered to be failed, but the
+// rest of the tests will still be run.
+//
+// When parameterized tests are enabled, it expands and registers
+// parameterized tests first in RegisterParameterizedTests().
+// All other functions called from RunAllTests() may safely assume that
+// parameterized tests are ready to be counted and run.
+bool UnitTestImpl::RunAllTests() {
+  // True if and only if Google Test is initialized before RUN_ALL_TESTS() is
+  // called.
+  const bool gtest_is_initialized_before_run_all_tests = GTestIsInitialized();
+
+  // Do not run any test if the --help flag was specified.
+  if (g_help_flag)
+    return true;
+
+  // Repeats the call to the post-flag parsing initialization in case the
+  // user didn't call InitGoogleTest.
+  PostFlagParsingInit();
+
+  // Even if sharding is not on, test runners may want to use the
+  // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
+  // protocol.
+  internal::WriteToShardStatusFileIfNeeded();
+
+  // True if and only if we are in a subprocess for running a thread-safe-style
+  // death test.
+  bool in_subprocess_for_death_test = false;
+
+#if GTEST_HAS_DEATH_TEST
+  in_subprocess_for_death_test =
+      (internal_run_death_test_flag_.get() != nullptr);
+# if defined(GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_)
+  if (in_subprocess_for_death_test) {
+    GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_();
+  }
+# endif  // defined(GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_)
+#endif  // GTEST_HAS_DEATH_TEST
+
+  const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
+                                        in_subprocess_for_death_test);
+
+  // Compares the full test names with the filter to decide which
+  // tests to run.
+  const bool has_tests_to_run = FilterTests(should_shard
+                                              ? HONOR_SHARDING_PROTOCOL
+                                              : IGNORE_SHARDING_PROTOCOL) > 0;
+
+  // Lists the tests and exits if the --gtest_list_tests flag was specified.
+  if (GTEST_FLAG(list_tests)) {
+    // This must be called *after* FilterTests() has been called.
+    ListTestsMatchingFilter();
+    return true;
+  }
+
+  random_seed_ = GTEST_FLAG(shuffle) ?
+      GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0;
+
+  // True if and only if at least one test has failed.
+  bool failed = false;
+
+  TestEventListener* repeater = listeners()->repeater();
+
+  start_timestamp_ = GetTimeInMillis();
+  repeater->OnTestProgramStart(*parent_);
+
+  // How many times to repeat the tests?  We don't want to repeat them
+  // when we are inside the subprocess of a death test.
+  const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat);
+  // Repeats forever if the repeat count is negative.
+  const bool gtest_repeat_forever = repeat < 0;
+  for (int i = 0; gtest_repeat_forever || i != repeat; i++) {
+    // We want to preserve failures generated by ad-hoc test
+    // assertions executed before RUN_ALL_TESTS().
+    ClearNonAdHocTestResult();
+
+    Timer timer;
+
+    // Shuffles test suites and tests if requested.
+    if (has_tests_to_run && GTEST_FLAG(shuffle)) {
+      random()->Reseed(static_cast<uint32_t>(random_seed_));
+      // This should be done before calling OnTestIterationStart(),
+      // such that a test event listener can see the actual test order
+      // in the event.
+      ShuffleTests();
+    }
+
+    // Tells the unit test event listeners that the tests are about to start.
+    repeater->OnTestIterationStart(*parent_, i);
+
+    // Runs each test suite if there is at least one test to run.
+    if (has_tests_to_run) {
+      // Sets up all environments beforehand.
+      repeater->OnEnvironmentsSetUpStart(*parent_);
+      ForEach(environments_, SetUpEnvironment);
+      repeater->OnEnvironmentsSetUpEnd(*parent_);
+
+      // Runs the tests only if there was no fatal failure or skip triggered
+      // during global set-up.
+      if (Test::IsSkipped()) {
+        // Emit diagnostics when global set-up calls skip, as it will not be
+        // emitted by default.
+        TestResult& test_result =
+            *internal::GetUnitTestImpl()->current_test_result();
+        for (int j = 0; j < test_result.total_part_count(); ++j) {
+          const TestPartResult& test_part_result =
+              test_result.GetTestPartResult(j);
+          if (test_part_result.type() == TestPartResult::kSkip) {
+            const std::string& result = test_part_result.message();
+            printf("%s\n", result.c_str());
+          }
+        }
+        fflush(stdout);
+      } else if (!Test::HasFatalFailure()) {
+        for (int test_index = 0; test_index < total_test_suite_count();
+             test_index++) {
+          GetMutableSuiteCase(test_index)->Run();
+          if (GTEST_FLAG(fail_fast) &&
+              GetMutableSuiteCase(test_index)->Failed()) {
+            for (int j = test_index + 1; j < total_test_suite_count(); j++) {
+              GetMutableSuiteCase(j)->Skip();
+            }
+            break;
+          }
+        }
+      } else if (Test::HasFatalFailure()) {
+        // If there was a fatal failure during the global setup then we know we
+        // aren't going to run any tests. Explicitly mark all of the tests as
+        // skipped to make this obvious in the output.
+        for (int test_index = 0; test_index < total_test_suite_count();
+             test_index++) {
+          GetMutableSuiteCase(test_index)->Skip();
+        }
+      }
+
+      // Tears down all environments in reverse order afterwards.
+      repeater->OnEnvironmentsTearDownStart(*parent_);
+      std::for_each(environments_.rbegin(), environments_.rend(),
+                    TearDownEnvironment);
+      repeater->OnEnvironmentsTearDownEnd(*parent_);
+    }
+
+    elapsed_time_ = timer.Elapsed();
+
+    // Tells the unit test event listener that the tests have just finished.
+    repeater->OnTestIterationEnd(*parent_, i);
+
+    // Gets the result and clears it.
+    if (!Passed()) {
+      failed = true;
+    }
+
+    // Restores the original test order after the iteration.  This
+    // allows the user to quickly repro a failure that happens in the
+    // N-th iteration without repeating the first (N - 1) iterations.
+    // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in
+    // case the user somehow changes the value of the flag somewhere
+    // (it's always safe to unshuffle the tests).
+    UnshuffleTests();
+
+    if (GTEST_FLAG(shuffle)) {
+      // Picks a new random seed for each iteration.
+      random_seed_ = GetNextRandomSeed(random_seed_);
+    }
+  }
+
+  repeater->OnTestProgramEnd(*parent_);
+
+  if (!gtest_is_initialized_before_run_all_tests) {
+    ColoredPrintf(
+        GTestColor::kRed,
+        "\nIMPORTANT NOTICE - DO NOT IGNORE:\n"
+        "This test program did NOT call " GTEST_INIT_GOOGLE_TEST_NAME_
+        "() before calling RUN_ALL_TESTS(). This is INVALID. Soon " GTEST_NAME_
+        " will start to enforce the valid usage. "
+        "Please fix it ASAP, or IT WILL START TO FAIL.\n");  // NOLINT
+#if GTEST_FOR_GOOGLE_
+    ColoredPrintf(GTestColor::kRed,
+                  "For more details, see http://wiki/Main/ValidGUnitMain.\n");
+#endif  // GTEST_FOR_GOOGLE_
+  }
+
+  return !failed;
+}
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded() {
+  const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile);
+  if (test_shard_file != nullptr) {
+    FILE* const file = posix::FOpen(test_shard_file, "w");
+    if (file == nullptr) {
+      ColoredPrintf(GTestColor::kRed,
+                    "Could not write to the test shard status file \"%s\" "
+                    "specified by the %s environment variable.\n",
+                    test_shard_file, kTestShardStatusFile);
+      fflush(stdout);
+      exit(EXIT_FAILURE);
+    }
+    fclose(file);
+  }
+}
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (i.e., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+bool ShouldShard(const char* total_shards_env,
+                 const char* shard_index_env,
+                 bool in_subprocess_for_death_test) {
+  if (in_subprocess_for_death_test) {
+    return false;
+  }
+
+  const int32_t total_shards = Int32FromEnvOrDie(total_shards_env, -1);
+  const int32_t shard_index = Int32FromEnvOrDie(shard_index_env, -1);
+
+  if (total_shards == -1 && shard_index == -1) {
+    return false;
+  } else if (total_shards == -1 && shard_index != -1) {
+    const Message msg = Message()
+      << "Invalid environment variables: you have "
+      << kTestShardIndex << " = " << shard_index
+      << ", but have left " << kTestTotalShards << " unset.\n";
+    ColoredPrintf(GTestColor::kRed, "%s", msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  } else if (total_shards != -1 && shard_index == -1) {
+    const Message msg = Message()
+      << "Invalid environment variables: you have "
+      << kTestTotalShards << " = " << total_shards
+      << ", but have left " << kTestShardIndex << " unset.\n";
+    ColoredPrintf(GTestColor::kRed, "%s", msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  } else if (shard_index < 0 || shard_index >= total_shards) {
+    const Message msg = Message()
+      << "Invalid environment variables: we require 0 <= "
+      << kTestShardIndex << " < " << kTestTotalShards
+      << ", but you have " << kTestShardIndex << "=" << shard_index
+      << ", " << kTestTotalShards << "=" << total_shards << ".\n";
+    ColoredPrintf(GTestColor::kRed, "%s", msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  }
+
+  return total_shards > 1;
+}
+
+// Parses the environment variable var as an Int32. If it is unset,
+// returns default_val. If it is not an Int32, prints an error
+// and aborts.
+int32_t Int32FromEnvOrDie(const char* var, int32_t default_val) {
+  const char* str_val = posix::GetEnv(var);
+  if (str_val == nullptr) {
+    return default_val;
+  }
+
+  int32_t result;
+  if (!ParseInt32(Message() << "The value of environment variable " << var,
+                  str_val, &result)) {
+    exit(EXIT_FAILURE);
+  }
+  return result;
+}
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true if and only if the test should be run on this shard. The test id
+// is some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) {
+  return (test_id % total_shards) == shard_index;
+}
+
+// Compares the name of each test with the user-specified filter to
+// decide whether the test should be run, then records the result in
+// each TestSuite and TestInfo object.
+// If shard_tests == true, further filters tests based on sharding
+// variables in the environment - see
+// https://github.com/google/googletest/blob/master/googletest/docs/advanced.md
+// . Returns the number of tests that should run.
+int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
+  const int32_t total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ?
+      Int32FromEnvOrDie(kTestTotalShards, -1) : -1;
+  const int32_t shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ?
+      Int32FromEnvOrDie(kTestShardIndex, -1) : -1;
+
+  // num_runnable_tests are the number of tests that will
+  // run across all shards (i.e., match filter and are not disabled).
+  // num_selected_tests are the number of tests to be run on
+  // this shard.
+  int num_runnable_tests = 0;
+  int num_selected_tests = 0;
+  for (auto* test_suite : test_suites_) {
+    const std::string& test_suite_name = test_suite->name();
+    test_suite->set_should_run(false);
+
+    for (size_t j = 0; j < test_suite->test_info_list().size(); j++) {
+      TestInfo* const test_info = test_suite->test_info_list()[j];
+      const std::string test_name(test_info->name());
+      // A test is disabled if test suite name or test name matches
+      // kDisableTestFilter.
+      const bool is_disabled = internal::UnitTestOptions::MatchesFilter(
+                                   test_suite_name, kDisableTestFilter) ||
+                               internal::UnitTestOptions::MatchesFilter(
+                                   test_name, kDisableTestFilter);
+      test_info->is_disabled_ = is_disabled;
+
+      const bool matches_filter = internal::UnitTestOptions::FilterMatchesTest(
+          test_suite_name, test_name);
+      test_info->matches_filter_ = matches_filter;
+
+      const bool is_runnable =
+          (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) &&
+          matches_filter;
+
+      const bool is_in_another_shard =
+          shard_tests != IGNORE_SHARDING_PROTOCOL &&
+          !ShouldRunTestOnShard(total_shards, shard_index, num_runnable_tests);
+      test_info->is_in_another_shard_ = is_in_another_shard;
+      const bool is_selected = is_runnable && !is_in_another_shard;
+
+      num_runnable_tests += is_runnable;
+      num_selected_tests += is_selected;
+
+      test_info->should_run_ = is_selected;
+      test_suite->set_should_run(test_suite->should_run() || is_selected);
+    }
+  }
+  return num_selected_tests;
+}
+
+// Prints the given C-string on a single line by replacing all '\n'
+// characters with string "\\n".  If the output takes more than
+// max_length characters, only prints the first max_length characters
+// and "...".
+static void PrintOnOneLine(const char* str, int max_length) {
+  if (str != nullptr) {
+    for (int i = 0; *str != '\0'; ++str) {
+      if (i >= max_length) {
+        printf("...");
+        break;
+      }
+      if (*str == '\n') {
+        printf("\\n");
+        i += 2;
+      } else {
+        printf("%c", *str);
+        ++i;
+      }
+    }
+  }
+}
+
+// Prints the names of the tests matching the user-specified filter flag.
+void UnitTestImpl::ListTestsMatchingFilter() {
+  // Print at most this many characters for each type/value parameter.
+  const int kMaxParamLength = 250;
+
+  for (auto* test_suite : test_suites_) {
+    bool printed_test_suite_name = false;
+
+    for (size_t j = 0; j < test_suite->test_info_list().size(); j++) {
+      const TestInfo* const test_info = test_suite->test_info_list()[j];
+      if (test_info->matches_filter_) {
+        if (!printed_test_suite_name) {
+          printed_test_suite_name = true;
+          printf("%s.", test_suite->name());
+          if (test_suite->type_param() != nullptr) {
+            printf("  # %s = ", kTypeParamLabel);
+            // We print the type parameter on a single line to make
+            // the output easy to parse by a program.
+            PrintOnOneLine(test_suite->type_param(), kMaxParamLength);
+          }
+          printf("\n");
+        }
+        printf("  %s", test_info->name());
+        if (test_info->value_param() != nullptr) {
+          printf("  # %s = ", kValueParamLabel);
+          // We print the value parameter on a single line to make the
+          // output easy to parse by a program.
+          PrintOnOneLine(test_info->value_param(), kMaxParamLength);
+        }
+        printf("\n");
+      }
+    }
+  }
+  fflush(stdout);
+  const std::string& output_format = UnitTestOptions::GetOutputFormat();
+  if (output_format == "xml" || output_format == "json") {
+    FILE* fileout = OpenFileForWriting(
+        UnitTestOptions::GetAbsolutePathToOutputFile().c_str());
+    std::stringstream stream;
+    if (output_format == "xml") {
+      XmlUnitTestResultPrinter(
+          UnitTestOptions::GetAbsolutePathToOutputFile().c_str())
+          .PrintXmlTestsList(&stream, test_suites_);
+    } else if (output_format == "json") {
+      JsonUnitTestResultPrinter(
+          UnitTestOptions::GetAbsolutePathToOutputFile().c_str())
+          .PrintJsonTestList(&stream, test_suites_);
+    }
+    fprintf(fileout, "%s", StringStreamToString(&stream).c_str());
+    fclose(fileout);
+  }
+}
+
+// Sets the OS stack trace getter.
+//
+// Does nothing if the input and the current OS stack trace getter are
+// the same; otherwise, deletes the old getter and makes the input the
+// current getter.
+void UnitTestImpl::set_os_stack_trace_getter(
+    OsStackTraceGetterInterface* getter) {
+  if (os_stack_trace_getter_ != getter) {
+    delete os_stack_trace_getter_;
+    os_stack_trace_getter_ = getter;
+  }
+}
+
+// Returns the current OS stack trace getter if it is not NULL;
+// otherwise, creates an OsStackTraceGetter, makes it the current
+// getter, and returns it.
+OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() {
+  if (os_stack_trace_getter_ == nullptr) {
+#ifdef GTEST_OS_STACK_TRACE_GETTER_
+    os_stack_trace_getter_ = new GTEST_OS_STACK_TRACE_GETTER_;
+#else
+    os_stack_trace_getter_ = new OsStackTraceGetter;
+#endif  // GTEST_OS_STACK_TRACE_GETTER_
+  }
+
+  return os_stack_trace_getter_;
+}
+
+// Returns the most specific TestResult currently running.
+TestResult* UnitTestImpl::current_test_result() {
+  if (current_test_info_ != nullptr) {
+    return &current_test_info_->result_;
+  }
+  if (current_test_suite_ != nullptr) {
+    return &current_test_suite_->ad_hoc_test_result_;
+  }
+  return &ad_hoc_test_result_;
+}
+
+// Shuffles all test suites, and the tests within each test suite,
+// making sure that death tests are still run first.
+void UnitTestImpl::ShuffleTests() {
+  // Shuffles the death test suites.
+  ShuffleRange(random(), 0, last_death_test_suite_ + 1, &test_suite_indices_);
+
+  // Shuffles the non-death test suites.
+  ShuffleRange(random(), last_death_test_suite_ + 1,
+               static_cast<int>(test_suites_.size()), &test_suite_indices_);
+
+  // Shuffles the tests inside each test suite.
+  for (auto& test_suite : test_suites_) {
+    test_suite->ShuffleTests(random());
+  }
+}
+
+// Restores the test suites and tests to their order before the first shuffle.
+void UnitTestImpl::UnshuffleTests() {
+  for (size_t i = 0; i < test_suites_.size(); i++) {
+    // Unshuffles the tests in each test suite.
+    test_suites_[i]->UnshuffleTests();
+    // Resets the index of each test suite.
+    test_suite_indices_[i] = static_cast<int>(i);
+  }
+}
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+std::string GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/,
+                                            int skip_count) {
+  // We pass skip_count + 1 to skip this wrapper function in addition
+  // to what the user really wants to skip.
+  return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1);
+}
+
+// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to
+// suppress unreachable code warnings.
+namespace {
+class ClassUniqueToAlwaysTrue {};
+}
+
+bool IsTrue(bool condition) { return condition; }
+
+bool AlwaysTrue() {
+#if GTEST_HAS_EXCEPTIONS
+  // This condition is always false so AlwaysTrue() never actually throws,
+  // but it makes the compiler think that it may throw.
+  if (IsTrue(false))
+    throw ClassUniqueToAlwaysTrue();
+#endif  // GTEST_HAS_EXCEPTIONS
+  return true;
+}
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false.  None of pstr, *pstr, and prefix can be NULL.
+bool SkipPrefix(const char* prefix, const char** pstr) {
+  const size_t prefix_len = strlen(prefix);
+  if (strncmp(*pstr, prefix, prefix_len) == 0) {
+    *pstr += prefix_len;
+    return true;
+  }
+  return false;
+}
+
+// Parses a string as a command line flag.  The string should have
+// the format "--flag=value".  When def_optional is true, the "=value"
+// part can be omitted.
+//
+// Returns the value of the flag, or NULL if the parsing failed.
+static const char* ParseFlagValue(const char* str, const char* flag,
+                                  bool def_optional) {
+  // str and flag must not be NULL.
+  if (str == nullptr || flag == nullptr) return nullptr;
+
+  // The flag must start with "--" followed by GTEST_FLAG_PREFIX_.
+  const std::string flag_str = std::string("--") + GTEST_FLAG_PREFIX_ + flag;
+  const size_t flag_len = flag_str.length();
+  if (strncmp(str, flag_str.c_str(), flag_len) != 0) return nullptr;
+
+  // Skips the flag name.
+  const char* flag_end = str + flag_len;
+
+  // When def_optional is true, it's OK to not have a "=value" part.
+  if (def_optional && (flag_end[0] == '\0')) {
+    return flag_end;
+  }
+
+  // If def_optional is true and there are more characters after the
+  // flag name, or if def_optional is false, there must be a '=' after
+  // the flag name.
+  if (flag_end[0] != '=') return nullptr;
+
+  // Returns the string after "=".
+  return flag_end + 1;
+}
+
+// Parses a string for a bool flag, in the form of either
+// "--flag=value" or "--flag".
+//
+// In the former case, the value is taken as true as long as it does
+// not start with '0', 'f', or 'F'.
+//
+// In the latter case, the value is taken as true.
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+static bool ParseBoolFlag(const char* str, const char* flag, bool* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, true);
+
+  // Aborts if the parsing failed.
+  if (value_str == nullptr) return false;
+
+  // Converts the string value to a bool.
+  *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
+  return true;
+}
+
+// Parses a string for an int32_t flag, in the form of "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseInt32Flag(const char* str, const char* flag, int32_t* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == nullptr) return false;
+
+  // Sets *value to the value of the flag.
+  return ParseInt32(Message() << "The value of flag --" << flag,
+                    value_str, value);
+}
+
+// Parses a string for a string flag, in the form of "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+template <typename String>
+static bool ParseStringFlag(const char* str, const char* flag, String* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == nullptr) return false;
+
+  // Sets *value to the value of the flag.
+  *value = value_str;
+  return true;
+}
+
+// Determines whether a string has a prefix that Google Test uses for its
+// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_.
+// If Google Test detects that a command line flag has its prefix but is not
+// recognized, it will print its help message. Flags starting with
+// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test
+// internal flags and do not trigger the help message.
+static bool HasGoogleTestFlagPrefix(const char* str) {
+  return (SkipPrefix("--", &str) ||
+          SkipPrefix("-", &str) ||
+          SkipPrefix("/", &str)) &&
+         !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) &&
+         (SkipPrefix(GTEST_FLAG_PREFIX_, &str) ||
+          SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str));
+}
+
+// Prints a string containing code-encoded text.  The following escape
+// sequences can be used in the string to control the text color:
+//
+//   @@    prints a single '@' character.
+//   @R    changes the color to red.
+//   @G    changes the color to green.
+//   @Y    changes the color to yellow.
+//   @D    changes to the default terminal text color.
+//
+static void PrintColorEncoded(const char* str) {
+  GTestColor color = GTestColor::kDefault;  // The current color.
+
+  // Conceptually, we split the string into segments divided by escape
+  // sequences.  Then we print one segment at a time.  At the end of
+  // each iteration, the str pointer advances to the beginning of the
+  // next segment.
+  for (;;) {
+    const char* p = strchr(str, '@');
+    if (p == nullptr) {
+      ColoredPrintf(color, "%s", str);
+      return;
+    }
+
+    ColoredPrintf(color, "%s", std::string(str, p).c_str());
+
+    const char ch = p[1];
+    str = p + 2;
+    if (ch == '@') {
+      ColoredPrintf(color, "@");
+    } else if (ch == 'D') {
+      color = GTestColor::kDefault;
+    } else if (ch == 'R') {
+      color = GTestColor::kRed;
+    } else if (ch == 'G') {
+      color = GTestColor::kGreen;
+    } else if (ch == 'Y') {
+      color = GTestColor::kYellow;
+    } else {
+      --str;
+    }
+  }
+}
+
+static const char kColorEncodedHelpMessage[] =
+    "This program contains tests written using " GTEST_NAME_
+    ". You can use the\n"
+    "following command line flags to control its behavior:\n"
+    "\n"
+    "Test Selection:\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "list_tests@D\n"
+    "      List the names of all tests instead of running them. The name of\n"
+    "      TEST(Foo, Bar) is \"Foo.Bar\".\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "filter=@YPOSITIVE_PATTERNS"
+    "[@G-@YNEGATIVE_PATTERNS]@D\n"
+    "      Run only the tests whose name matches one of the positive patterns "
+    "but\n"
+    "      none of the negative patterns. '?' matches any single character; "
+    "'*'\n"
+    "      matches any substring; ':' separates two patterns.\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "also_run_disabled_tests@D\n"
+    "      Run all disabled tests too.\n"
+    "\n"
+    "Test Execution:\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "repeat=@Y[COUNT]@D\n"
+    "      Run the tests repeatedly; use a negative count to repeat forever.\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "shuffle@D\n"
+    "      Randomize tests' orders on every iteration.\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "random_seed=@Y[NUMBER]@D\n"
+    "      Random number seed to use for shuffling test orders (between 1 and\n"
+    "      99999, or 0 to use a seed based on the current time).\n"
+    "\n"
+    "Test Output:\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n"
+    "      Enable/disable colored output. The default is @Gauto@D.\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "brief=1@D\n"
+    "      Only print test failures.\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "print_time=0@D\n"
+    "      Don't print the elapsed time of each test.\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "output=@Y(@Gjson@Y|@Gxml@Y)[@G:@YDIRECTORY_PATH@G" GTEST_PATH_SEP_
+    "@Y|@G:@YFILE_PATH]@D\n"
+    "      Generate a JSON or XML report in the given directory or with the "
+    "given\n"
+    "      file name. @YFILE_PATH@D defaults to @Gtest_detail.xml@D.\n"
+# if GTEST_CAN_STREAM_RESULTS_
+    "  @G--" GTEST_FLAG_PREFIX_
+    "stream_result_to=@YHOST@G:@YPORT@D\n"
+    "      Stream test results to the given server.\n"
+# endif  // GTEST_CAN_STREAM_RESULTS_
+    "\n"
+    "Assertion Behavior:\n"
+# if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+    "  @G--" GTEST_FLAG_PREFIX_
+    "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n"
+    "      Set the default death test style.\n"
+# endif  // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+    "  @G--" GTEST_FLAG_PREFIX_
+    "break_on_failure@D\n"
+    "      Turn assertion failures into debugger break-points.\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "throw_on_failure@D\n"
+    "      Turn assertion failures into C++ exceptions for use by an external\n"
+    "      test framework.\n"
+    "  @G--" GTEST_FLAG_PREFIX_
+    "catch_exceptions=0@D\n"
+    "      Do not report exceptions as test failures. Instead, allow them\n"
+    "      to crash the program or throw a pop-up (on Windows).\n"
+    "\n"
+    "Except for @G--" GTEST_FLAG_PREFIX_
+    "list_tests@D, you can alternatively set "
+    "the corresponding\n"
+    "environment variable of a flag (all letters in upper-case). For example, "
+    "to\n"
+    "disable colored text output, you can either specify "
+    "@G--" GTEST_FLAG_PREFIX_
+    "color=no@D or set\n"
+    "the @G" GTEST_FLAG_PREFIX_UPPER_
+    "COLOR@D environment variable to @Gno@D.\n"
+    "\n"
+    "For more information, please read the " GTEST_NAME_
+    " documentation at\n"
+    "@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_
+    "\n"
+    "(not one in your own code or tests), please report it to\n"
+    "@G<" GTEST_DEV_EMAIL_ ">@D.\n";
+
+static bool ParseGoogleTestFlag(const char* const arg) {
+  return ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag,
+                       &GTEST_FLAG(also_run_disabled_tests)) ||
+         ParseBoolFlag(arg, kBreakOnFailureFlag,
+                       &GTEST_FLAG(break_on_failure)) ||
+         ParseBoolFlag(arg, kCatchExceptionsFlag,
+                       &GTEST_FLAG(catch_exceptions)) ||
+         ParseStringFlag(arg, kColorFlag, &GTEST_FLAG(color)) ||
+         ParseStringFlag(arg, kDeathTestStyleFlag,
+                         &GTEST_FLAG(death_test_style)) ||
+         ParseBoolFlag(arg, kDeathTestUseFork,
+                       &GTEST_FLAG(death_test_use_fork)) ||
+         ParseBoolFlag(arg, kFailFast, &GTEST_FLAG(fail_fast)) ||
+         ParseStringFlag(arg, kFilterFlag, &GTEST_FLAG(filter)) ||
+         ParseStringFlag(arg, kInternalRunDeathTestFlag,
+                         &GTEST_FLAG(internal_run_death_test)) ||
+         ParseBoolFlag(arg, kListTestsFlag, &GTEST_FLAG(list_tests)) ||
+         ParseStringFlag(arg, kOutputFlag, &GTEST_FLAG(output)) ||
+         ParseBoolFlag(arg, kBriefFlag, &GTEST_FLAG(brief)) ||
+         ParseBoolFlag(arg, kPrintTimeFlag, &GTEST_FLAG(print_time)) ||
+         ParseBoolFlag(arg, kPrintUTF8Flag, &GTEST_FLAG(print_utf8)) ||
+         ParseInt32Flag(arg, kRandomSeedFlag, &GTEST_FLAG(random_seed)) ||
+         ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat)) ||
+         ParseBoolFlag(arg, kShuffleFlag, &GTEST_FLAG(shuffle)) ||
+         ParseInt32Flag(arg, kStackTraceDepthFlag,
+                        &GTEST_FLAG(stack_trace_depth)) ||
+         ParseStringFlag(arg, kStreamResultToFlag,
+                         &GTEST_FLAG(stream_result_to)) ||
+         ParseBoolFlag(arg, kThrowOnFailureFlag, &GTEST_FLAG(throw_on_failure));
+}
+
+#if GTEST_USE_OWN_FLAGFILE_FLAG_
+static void LoadFlagsFromFile(const std::string& path) {
+  FILE* flagfile = posix::FOpen(path.c_str(), "r");
+  if (!flagfile) {
+    GTEST_LOG_(FATAL) << "Unable to open file \"" << GTEST_FLAG(flagfile)
+                      << "\"";
+  }
+  std::string contents(ReadEntireFile(flagfile));
+  posix::FClose(flagfile);
+  std::vector<std::string> lines;
+  SplitString(contents, '\n', &lines);
+  for (size_t i = 0; i < lines.size(); ++i) {
+    if (lines[i].empty())
+      continue;
+    if (!ParseGoogleTestFlag(lines[i].c_str()))
+      g_help_flag = true;
+  }
+}
+#endif  // GTEST_USE_OWN_FLAGFILE_FLAG_
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.  The type parameter CharType can be
+// instantiated to either char or wchar_t.
+template <typename CharType>
+void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
+  for (int i = 1; i < *argc; i++) {
+    const std::string arg_string = StreamableToString(argv[i]);
+    const char* const arg = arg_string.c_str();
+
+    using internal::ParseBoolFlag;
+    using internal::ParseInt32Flag;
+    using internal::ParseStringFlag;
+
+    bool remove_flag = false;
+    if (ParseGoogleTestFlag(arg)) {
+      remove_flag = true;
+#if GTEST_USE_OWN_FLAGFILE_FLAG_
+    } else if (ParseStringFlag(arg, kFlagfileFlag, &GTEST_FLAG(flagfile))) {
+      LoadFlagsFromFile(GTEST_FLAG(flagfile));
+      remove_flag = true;
+#endif  // GTEST_USE_OWN_FLAGFILE_FLAG_
+    } else if (arg_string == "--help" || arg_string == "-h" ||
+               arg_string == "-?" || arg_string == "/?" ||
+               HasGoogleTestFlagPrefix(arg)) {
+      // Both help flag and unrecognized Google Test flags (excluding
+      // internal ones) trigger help display.
+      g_help_flag = true;
+    }
+
+    if (remove_flag) {
+      // Shift the remainder of the argv list left by one.  Note
+      // that argv has (*argc + 1) elements, the last one always being
+      // NULL.  The following loop moves the trailing NULL element as
+      // well.
+      for (int j = i; j != *argc; j++) {
+        argv[j] = argv[j + 1];
+      }
+
+      // Decrements the argument count.
+      (*argc)--;
+
+      // We also need to decrement the iterator as we just removed
+      // an element.
+      i--;
+    }
+  }
+
+  if (g_help_flag) {
+    // We print the help here instead of in RUN_ALL_TESTS(), as the
+    // latter may not be called at all if the user is using Google
+    // Test with another testing framework.
+    PrintColorEncoded(kColorEncodedHelpMessage);
+  }
+}
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+void ParseGoogleTestFlagsOnly(int* argc, char** argv) {
+  ParseGoogleTestFlagsOnlyImpl(argc, argv);
+
+  // Fix the value of *_NSGetArgc() on macOS, but if and only if
+  // *_NSGetArgv() == argv
+  // Only applicable to char** version of argv
+#if GTEST_OS_MAC
+#ifndef GTEST_OS_IOS
+  if (*_NSGetArgv() == argv) {
+    *_NSGetArgc() = *argc;
+  }
+#endif
+#endif
+}
+void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) {
+  ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+
+// The internal implementation of InitGoogleTest().
+//
+// The type parameter CharType can be instantiated to either char or
+// wchar_t.
+template <typename CharType>
+void InitGoogleTestImpl(int* argc, CharType** argv) {
+  // We don't want to run the initialization code twice.
+  if (GTestIsInitialized()) return;
+
+  if (*argc <= 0) return;
+
+  g_argvs.clear();
+  for (int i = 0; i != *argc; i++) {
+    g_argvs.push_back(StreamableToString(argv[i]));
+  }
+
+#if GTEST_HAS_ABSL
+  absl::InitializeSymbolizer(g_argvs[0].c_str());
+#endif  // GTEST_HAS_ABSL
+
+  ParseGoogleTestFlagsOnly(argc, argv);
+  GetUnitTestImpl()->PostFlagParsingInit();
+}
+
+}  // namespace internal
+
+// Initializes Google Test.  This must be called before calling
+// RUN_ALL_TESTS().  In particular, it parses a command line for the
+// flags that Google Test recognizes.  Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+void InitGoogleTest(int* argc, char** argv) {
+#if defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+  GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_(argc, argv);
+#else  // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+  internal::InitGoogleTestImpl(argc, argv);
+#endif  // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+}
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+void InitGoogleTest(int* argc, wchar_t** argv) {
+#if defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+  GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_(argc, argv);
+#else  // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+  internal::InitGoogleTestImpl(argc, argv);
+#endif  // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+}
+
+// This overloaded version can be used on Arduino/embedded platforms where
+// there is no argc/argv.
+void InitGoogleTest() {
+  // Since Arduino doesn't have a command line, fake out the argc/argv arguments
+  int argc = 1;
+  const auto arg0 = "dummy";
+  char* argv0 = const_cast<char*>(arg0);
+  char** argv = &argv0;
+
+#if defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+  GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_(&argc, argv);
+#else  // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+  internal::InitGoogleTestImpl(&argc, argv);
+#endif  // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+}
+
+std::string TempDir() {
+#if defined(GTEST_CUSTOM_TEMPDIR_FUNCTION_)
+  return GTEST_CUSTOM_TEMPDIR_FUNCTION_();
+#elif GTEST_OS_WINDOWS_MOBILE
+  return "\\temp\\";
+#elif GTEST_OS_WINDOWS
+  const char* temp_dir = internal::posix::GetEnv("TEMP");
+  if (temp_dir == nullptr || temp_dir[0] == '\0') {
+    return "\\temp\\";
+  } else if (temp_dir[strlen(temp_dir) - 1] == '\\') {
+    return temp_dir;
+  } else {
+    return std::string(temp_dir) + "\\";
+  }
+#elif GTEST_OS_LINUX_ANDROID
+  const char* temp_dir = internal::posix::GetEnv("TEST_TMPDIR");
+  if (temp_dir == nullptr || temp_dir[0] == '\0') {
+    return "/data/local/tmp/";
+  } else {
+    return temp_dir;
+  }
+#elif GTEST_OS_LINUX
+  const char* temp_dir = internal::posix::GetEnv("TEST_TMPDIR");
+  if (temp_dir == nullptr || temp_dir[0] == '\0') {
+    return "/tmp/";
+  } else {
+    return temp_dir;
+  }
+#else
+  return "/tmp/";
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Class ScopedTrace
+
+// Pushes the given source file location and message onto a per-thread
+// trace stack maintained by Google Test.
+void ScopedTrace::PushTrace(const char* file, int line, std::string message) {
+  internal::TraceInfo trace;
+  trace.file = file;
+  trace.line = line;
+  trace.message.swap(message);
+
+  UnitTest::GetInstance()->PushGTestTrace(trace);
+}
+
+// Pops the info pushed by the c'tor.
+ScopedTrace::~ScopedTrace()
+    GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) {
+  UnitTest::GetInstance()->PopGTestTrace();
+}
+
+}  // namespace testing
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// This file implements death tests.
+
+
+#include <functional>
+#include <utility>
+
+
+#if GTEST_HAS_DEATH_TEST
+
+# if GTEST_OS_MAC
+#  include <crt_externs.h>
+# endif  // GTEST_OS_MAC
+
+# include <errno.h>
+# include <fcntl.h>
+# include <limits.h>
+
+# if GTEST_OS_LINUX
+#  include <signal.h>
+# endif  // GTEST_OS_LINUX
+
+# include <stdarg.h>
+
+# if GTEST_OS_WINDOWS
+#  include <windows.h>
+# else
+#  include <sys/mman.h>
+#  include <sys/wait.h>
+# endif  // GTEST_OS_WINDOWS
+
+# if GTEST_OS_QNX
+#  include <spawn.h>
+# endif  // GTEST_OS_QNX
+
+# if GTEST_OS_FUCHSIA
+#  include <lib/fdio/fd.h>
+#  include <lib/fdio/io.h>
+#  include <lib/fdio/spawn.h>
+#  include <lib/zx/channel.h>
+#  include <lib/zx/port.h>
+#  include <lib/zx/process.h>
+#  include <lib/zx/socket.h>
+#  include <zircon/processargs.h>
+#  include <zircon/syscalls.h>
+#  include <zircon/syscalls/policy.h>
+#  include <zircon/syscalls/port.h>
+# endif  // GTEST_OS_FUCHSIA
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+
+namespace testing {
+
+// Constants.
+
+// The default death test style.
+//
+// This is defined in internal/gtest-port.h as "fast", but can be overridden by
+// a definition in internal/custom/gtest-port.h. The recommended value, which is
+// used internally at Google, is "threadsafe".
+static const char kDefaultDeathTestStyle[] = GTEST_DEFAULT_DEATH_TEST_STYLE;
+
+GTEST_DEFINE_string_(
+    death_test_style,
+    internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle),
+    "Indicates how to run a death test in a forked child process: "
+    "\"threadsafe\" (child process re-executes the test binary "
+    "from the beginning, running only the specific death test) or "
+    "\"fast\" (child process runs the death test immediately "
+    "after forking).");
+
+GTEST_DEFINE_bool_(
+    death_test_use_fork,
+    internal::BoolFromGTestEnv("death_test_use_fork", false),
+    "Instructs to use fork()/_exit() instead of clone() in death tests. "
+    "Ignored and always uses fork() on POSIX systems where clone() is not "
+    "implemented. Useful when running under valgrind or similar tools if "
+    "those do not support clone(). Valgrind 3.3.1 will just fail if "
+    "it sees an unsupported combination of clone() flags. "
+    "It is not recommended to use this flag w/o valgrind though it will "
+    "work in 99% of the cases. Once valgrind is fixed, this flag will "
+    "most likely be removed.");
+
+namespace internal {
+GTEST_DEFINE_string_(
+    internal_run_death_test, "",
+    "Indicates the file, line number, temporal index of "
+    "the single death test to run, and a file descriptor to "
+    "which a success code may be sent, all separated by "
+    "the '|' characters.  This flag is specified if and only if the "
+    "current process is a sub-process launched for running a thread-safe "
+    "death test.  FOR INTERNAL USE ONLY.");
+}  // namespace internal
+
+#if GTEST_HAS_DEATH_TEST
+
+namespace internal {
+
+// Valid only for fast death tests. Indicates the code is running in the
+// child process of a fast style death test.
+# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
+static bool g_in_fast_death_test_child = false;
+# endif
+
+// Returns a Boolean value indicating whether the caller is currently
+// executing in the context of the death test child process.  Tools such as
+// Valgrind heap checkers may need this to modify their behavior in death
+// tests.  IMPORTANT: This is an internal utility.  Using it may break the
+// implementation of death tests.  User code MUST NOT use it.
+bool InDeathTestChild() {
+# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
+
+  // On Windows and Fuchsia, death tests are thread-safe regardless of the value
+  // of the death_test_style flag.
+  return !GTEST_FLAG(internal_run_death_test).empty();
+
+# else
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe")
+    return !GTEST_FLAG(internal_run_death_test).empty();
+  else
+    return g_in_fast_death_test_child;
+#endif
+}
+
+}  // namespace internal
+
+// ExitedWithCode constructor.
+ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
+}
+
+// ExitedWithCode function-call operator.
+bool ExitedWithCode::operator()(int exit_status) const {
+# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
+
+  return exit_status == exit_code_;
+
+# else
+
+  return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
+
+# endif  // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
+}
+
+# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
+// KilledBySignal constructor.
+KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
+}
+
+// KilledBySignal function-call operator.
+bool KilledBySignal::operator()(int exit_status) const {
+#  if defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
+  {
+    bool result;
+    if (GTEST_KILLED_BY_SIGNAL_OVERRIDE_(signum_, exit_status, &result)) {
+      return result;
+    }
+  }
+#  endif  // defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
+  return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
+}
+# endif  // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
+
+namespace internal {
+
+// Utilities needed for death tests.
+
+// Generates a textual description of a given exit code, in the format
+// specified by wait(2).
+static std::string ExitSummary(int exit_code) {
+  Message m;
+
+# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
+
+  m << "Exited with exit status " << exit_code;
+
+# else
+
+  if (WIFEXITED(exit_code)) {
+    m << "Exited with exit status " << WEXITSTATUS(exit_code);
+  } else if (WIFSIGNALED(exit_code)) {
+    m << "Terminated by signal " << WTERMSIG(exit_code);
+  }
+#  ifdef WCOREDUMP
+  if (WCOREDUMP(exit_code)) {
+    m << " (core dumped)";
+  }
+#  endif
+# endif  // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
+
+  return m.GetString();
+}
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+bool ExitedUnsuccessfully(int exit_status) {
+  return !ExitedWithCode(0)(exit_status);
+}
+
+# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
+// Generates a textual failure message when a death test finds more than
+// one thread running, or cannot determine the number of threads, prior
+// to executing the given statement.  It is the responsibility of the
+// caller not to pass a thread_count of 1.
+static std::string DeathTestThreadWarning(size_t thread_count) {
+  Message msg;
+  msg << "Death tests use fork(), which is unsafe particularly"
+      << " in a threaded context. For this test, " << GTEST_NAME_ << " ";
+  if (thread_count == 0) {
+    msg << "couldn't detect the number of threads.";
+  } else {
+    msg << "detected " << thread_count << " threads.";
+  }
+  msg << " See "
+         "https://github.com/google/googletest/blob/master/docs/"
+         "advanced.md#death-tests-and-threads"
+      << " for more explanation and suggested solutions, especially if"
+      << " this is the last message you see before your test times out.";
+  return msg.GetString();
+}
+# endif  // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
+
+// Flag characters for reporting a death test that did not die.
+static const char kDeathTestLived = 'L';
+static const char kDeathTestReturned = 'R';
+static const char kDeathTestThrew = 'T';
+static const char kDeathTestInternalError = 'I';
+
+#if GTEST_OS_FUCHSIA
+
+// File descriptor used for the pipe in the child process.
+static const int kFuchsiaReadPipeFd = 3;
+
+#endif
+
+// An enumeration describing all of the possible ways that a death test can
+// conclude.  DIED means that the process died while executing the test
+// code; LIVED means that process lived beyond the end of the test code;
+// RETURNED means that the test statement attempted to execute a return
+// statement, which is not allowed; THREW means that the test statement
+// returned control by throwing an exception.  IN_PROGRESS means the test
+// has not yet concluded.
+enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
+
+// Routine for aborting the program which is safe to call from an
+// exec-style death test child process, in which case the error
+// message is propagated back to the parent process.  Otherwise, the
+// message is simply printed to stderr.  In either case, the program
+// then exits with status 1.
+static void DeathTestAbort(const std::string& message) {
+  // On a POSIX system, this function may be called from a threadsafe-style
+  // death test child process, which operates on a very small stack.  Use
+  // the heap for any additional non-minuscule memory requirements.
+  const InternalRunDeathTestFlag* const flag =
+      GetUnitTestImpl()->internal_run_death_test_flag();
+  if (flag != nullptr) {
+    FILE* parent = posix::FDOpen(flag->write_fd(), "w");
+    fputc(kDeathTestInternalError, parent);
+    fprintf(parent, "%s", message.c_str());
+    fflush(parent);
+    _exit(1);
+  } else {
+    fprintf(stderr, "%s", message.c_str());
+    fflush(stderr);
+    posix::Abort();
+  }
+}
+
+// A replacement for CHECK that calls DeathTestAbort if the assertion
+// fails.
+# define GTEST_DEATH_TEST_CHECK_(expression) \
+  do { \
+    if (!::testing::internal::IsTrue(expression)) { \
+      DeathTestAbort( \
+          ::std::string("CHECK failed: File ") + __FILE__ +  ", line " \
+          + ::testing::internal::StreamableToString(__LINE__) + ": " \
+          + #expression); \
+    } \
+  } while (::testing::internal::AlwaysFalse())
+
+// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for
+// evaluating any system call that fulfills two conditions: it must return
+// -1 on failure, and set errno to EINTR when it is interrupted and
+// should be tried again.  The macro expands to a loop that repeatedly
+// evaluates the expression as long as it evaluates to -1 and sets
+// errno to EINTR.  If the expression evaluates to -1 but errno is
+// something other than EINTR, DeathTestAbort is called.
+# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
+  do { \
+    int gtest_retval; \
+    do { \
+      gtest_retval = (expression); \
+    } while (gtest_retval == -1 && errno == EINTR); \
+    if (gtest_retval == -1) { \
+      DeathTestAbort( \
+          ::std::string("CHECK failed: File ") + __FILE__ + ", line " \
+          + ::testing::internal::StreamableToString(__LINE__) + ": " \
+          + #expression + " != -1"); \
+    } \
+  } while (::testing::internal::AlwaysFalse())
+
+// Returns the message describing the last system error in errno.
+std::string GetLastErrnoDescription() {
+    return errno == 0 ? "" : posix::StrError(errno);
+}
+
+// This is called from a death test parent process to read a failure
+// message from the death test child process and log it with the FATAL
+// severity. On Windows, the message is read from a pipe handle. On other
+// platforms, it is read from a file descriptor.
+static void FailFromInternalError(int fd) {
+  Message error;
+  char buffer[256];
+  int num_read;
+
+  do {
+    while ((num_read = posix::Read(fd, buffer, 255)) > 0) {
+      buffer[num_read] = '\0';
+      error << buffer;
+    }
+  } while (num_read == -1 && errno == EINTR);
+
+  if (num_read == 0) {
+    GTEST_LOG_(FATAL) << error.GetString();
+  } else {
+    const int last_error = errno;
+    GTEST_LOG_(FATAL) << "Error while reading death test internal: "
+                      << GetLastErrnoDescription() << " [" << last_error << "]";
+  }
+}
+
+// Death test constructor.  Increments the running death test count
+// for the current test.
+DeathTest::DeathTest() {
+  TestInfo* const info = GetUnitTestImpl()->current_test_info();
+  if (info == nullptr) {
+    DeathTestAbort("Cannot run a death test outside of a TEST or "
+                   "TEST_F construct");
+  }
+}
+
+// Creates and returns a death test by dispatching to the current
+// death test factory.
+bool DeathTest::Create(const char* statement,
+                       Matcher<const std::string&> matcher, const char* file,
+                       int line, DeathTest** test) {
+  return GetUnitTestImpl()->death_test_factory()->Create(
+      statement, std::move(matcher), file, line, test);
+}
+
+const char* DeathTest::LastMessage() {
+  return last_death_test_message_.c_str();
+}
+
+void DeathTest::set_last_death_test_message(const std::string& message) {
+  last_death_test_message_ = message;
+}
+
+std::string DeathTest::last_death_test_message_;
+
+// Provides cross platform implementation for some death functionality.
+class DeathTestImpl : public DeathTest {
+ protected:
+  DeathTestImpl(const char* a_statement, Matcher<const std::string&> matcher)
+      : statement_(a_statement),
+        matcher_(std::move(matcher)),
+        spawned_(false),
+        status_(-1),
+        outcome_(IN_PROGRESS),
+        read_fd_(-1),
+        write_fd_(-1) {}
+
+  // read_fd_ is expected to be closed and cleared by a derived class.
+  ~DeathTestImpl() override { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
+
+  void Abort(AbortReason reason) override;
+  bool Passed(bool status_ok) override;
+
+  const char* statement() const { return statement_; }
+  bool spawned() const { return spawned_; }
+  void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
+  int status() const { return status_; }
+  void set_status(int a_status) { status_ = a_status; }
+  DeathTestOutcome outcome() const { return outcome_; }
+  void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; }
+  int read_fd() const { return read_fd_; }
+  void set_read_fd(int fd) { read_fd_ = fd; }
+  int write_fd() const { return write_fd_; }
+  void set_write_fd(int fd) { write_fd_ = fd; }
+
+  // Called in the parent process only. Reads the result code of the death
+  // test child process via a pipe, interprets it to set the outcome_
+  // member, and closes read_fd_.  Outputs diagnostics and terminates in
+  // case of unexpected codes.
+  void ReadAndInterpretStatusByte();
+
+  // Returns stderr output from the child process.
+  virtual std::string GetErrorLogs();
+
+ private:
+  // The textual content of the code this object is testing.  This class
+  // doesn't own this string and should not attempt to delete it.
+  const char* const statement_;
+  // A matcher that's expected to match the stderr output by the child process.
+  Matcher<const std::string&> matcher_;
+  // True if the death test child process has been successfully spawned.
+  bool spawned_;
+  // The exit status of the child process.
+  int status_;
+  // How the death test concluded.
+  DeathTestOutcome outcome_;
+  // Descriptor to the read end of the pipe to the child process.  It is
+  // always -1 in the child process.  The child keeps its write end of the
+  // pipe in write_fd_.
+  int read_fd_;
+  // Descriptor to the child's write end of the pipe to the parent process.
+  // It is always -1 in the parent process.  The parent keeps its end of the
+  // pipe in read_fd_.
+  int write_fd_;
+};
+
+// Called in the parent process only. Reads the result code of the death
+// test child process via a pipe, interprets it to set the outcome_
+// member, and closes read_fd_.  Outputs diagnostics and terminates in
+// case of unexpected codes.
+void DeathTestImpl::ReadAndInterpretStatusByte() {
+  char flag;
+  int bytes_read;
+
+  // The read() here blocks until data is available (signifying the
+  // failure of the death test) or until the pipe is closed (signifying
+  // its success), so it's okay to call this in the parent before
+  // the child process has exited.
+  do {
+    bytes_read = posix::Read(read_fd(), &flag, 1);
+  } while (bytes_read == -1 && errno == EINTR);
+
+  if (bytes_read == 0) {
+    set_outcome(DIED);
+  } else if (bytes_read == 1) {
+    switch (flag) {
+      case kDeathTestReturned:
+        set_outcome(RETURNED);
+        break;
+      case kDeathTestThrew:
+        set_outcome(THREW);
+        break;
+      case kDeathTestLived:
+        set_outcome(LIVED);
+        break;
+      case kDeathTestInternalError:
+        FailFromInternalError(read_fd());  // Does not return.
+        break;
+      default:
+        GTEST_LOG_(FATAL) << "Death test child process reported "
+                          << "unexpected status byte ("
+                          << static_cast<unsigned int>(flag) << ")";
+    }
+  } else {
+    GTEST_LOG_(FATAL) << "Read from death test child process failed: "
+                      << GetLastErrnoDescription();
+  }
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd()));
+  set_read_fd(-1);
+}
+
+std::string DeathTestImpl::GetErrorLogs() {
+  return GetCapturedStderr();
+}
+
+// Signals that the death test code which should have exited, didn't.
+// Should be called only in a death test child process.
+// Writes a status byte to the child's status file descriptor, then
+// calls _exit(1).
+void DeathTestImpl::Abort(AbortReason reason) {
+  // The parent process considers the death test to be a failure if
+  // it finds any data in our pipe.  So, here we write a single flag byte
+  // to the pipe, then exit.
+  const char status_ch =
+      reason == TEST_DID_NOT_DIE ? kDeathTestLived :
+      reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned;
+
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
+  // We are leaking the descriptor here because on some platforms (i.e.,
+  // when built as Windows DLL), destructors of global objects will still
+  // run after calling _exit(). On such systems, write_fd_ will be
+  // indirectly closed from the destructor of UnitTestImpl, causing double
+  // close if it is also closed here. On debug configurations, double close
+  // may assert. As there are no in-process buffers to flush here, we are
+  // relying on the OS to close the descriptor after the process terminates
+  // when the destructors are not run.
+  _exit(1);  // Exits w/o any normal exit hooks (we were supposed to crash)
+}
+
+// Returns an indented copy of stderr output for a death test.
+// This makes distinguishing death test output lines from regular log lines
+// much easier.
+static ::std::string FormatDeathTestOutput(const ::std::string& output) {
+  ::std::string ret;
+  for (size_t at = 0; ; ) {
+    const size_t line_end = output.find('\n', at);
+    ret += "[  DEATH   ] ";
+    if (line_end == ::std::string::npos) {
+      ret += output.substr(at);
+      break;
+    }
+    ret += output.substr(at, line_end + 1 - at);
+    at = line_end + 1;
+  }
+  return ret;
+}
+
+// Assesses the success or failure of a death test, using both private
+// members which have previously been set, and one argument:
+//
+// Private data members:
+//   outcome:  An enumeration describing how the death test
+//             concluded: DIED, LIVED, THREW, or RETURNED.  The death test
+//             fails in the latter three cases.
+//   status:   The exit status of the child process. On *nix, it is in the
+//             in the format specified by wait(2). On Windows, this is the
+//             value supplied to the ExitProcess() API or a numeric code
+//             of the exception that terminated the program.
+//   matcher_: A matcher that's expected to match the stderr output by the child
+//             process.
+//
+// Argument:
+//   status_ok: true if exit_status is acceptable in the context of
+//              this particular death test, which fails if it is false
+//
+// Returns true if and only if all of the above conditions are met.  Otherwise,
+// the first failing condition, in the order given above, is the one that is
+// reported. Also sets the last death test message string.
+bool DeathTestImpl::Passed(bool status_ok) {
+  if (!spawned())
+    return false;
+
+  const std::string error_message = GetErrorLogs();
+
+  bool success = false;
+  Message buffer;
+
+  buffer << "Death test: " << statement() << "\n";
+  switch (outcome()) {
+    case LIVED:
+      buffer << "    Result: failed to die.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case THREW:
+      buffer << "    Result: threw an exception.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case RETURNED:
+      buffer << "    Result: illegal return in test statement.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case DIED:
+      if (status_ok) {
+        if (matcher_.Matches(error_message)) {
+          success = true;
+        } else {
+          std::ostringstream stream;
+          matcher_.DescribeTo(&stream);
+          buffer << "    Result: died but not with expected error.\n"
+                 << "  Expected: " << stream.str() << "\n"
+                 << "Actual msg:\n"
+                 << FormatDeathTestOutput(error_message);
+        }
+      } else {
+        buffer << "    Result: died but not with expected exit code:\n"
+               << "            " << ExitSummary(status()) << "\n"
+               << "Actual msg:\n" << FormatDeathTestOutput(error_message);
+      }
+      break;
+    case IN_PROGRESS:
+    default:
+      GTEST_LOG_(FATAL)
+          << "DeathTest::Passed somehow called before conclusion of test";
+  }
+
+  DeathTest::set_last_death_test_message(buffer.GetString());
+  return success;
+}
+
+# if GTEST_OS_WINDOWS
+// WindowsDeathTest implements death tests on Windows. Due to the
+// specifics of starting new processes on Windows, death tests there are
+// always threadsafe, and Google Test considers the
+// --gtest_death_test_style=fast setting to be equivalent to
+// --gtest_death_test_style=threadsafe there.
+//
+// A few implementation notes:  Like the Linux version, the Windows
+// implementation uses pipes for child-to-parent communication. But due to
+// the specifics of pipes on Windows, some extra steps are required:
+//
+// 1. The parent creates a communication pipe and stores handles to both
+//    ends of it.
+// 2. The parent starts the child and provides it with the information
+//    necessary to acquire the handle to the write end of the pipe.
+// 3. The child acquires the write end of the pipe and signals the parent
+//    using a Windows event.
+// 4. Now the parent can release the write end of the pipe on its side. If
+//    this is done before step 3, the object's reference count goes down to
+//    0 and it is destroyed, preventing the child from acquiring it. The
+//    parent now has to release it, or read operations on the read end of
+//    the pipe will not return when the child terminates.
+// 5. The parent reads child's output through the pipe (outcome code and
+//    any possible error messages) from the pipe, and its stderr and then
+//    determines whether to fail the test.
+//
+// Note: to distinguish Win32 API calls from the local method and function
+// calls, the former are explicitly resolved in the global namespace.
+//
+class WindowsDeathTest : public DeathTestImpl {
+ public:
+  WindowsDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
+                   const char* file, int line)
+      : DeathTestImpl(a_statement, std::move(matcher)),
+        file_(file),
+        line_(line) {}
+
+  // All of these virtual functions are inherited from DeathTest.
+  virtual int Wait();
+  virtual TestRole AssumeRole();
+
+ private:
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+  // Handle to the write end of the pipe to the child process.
+  AutoHandle write_handle_;
+  // Child process handle.
+  AutoHandle child_handle_;
+  // Event the child process uses to signal the parent that it has
+  // acquired the handle to the write end of the pipe. After seeing this
+  // event the parent can release its own handles to make sure its
+  // ReadFile() calls return when the child terminates.
+  AutoHandle event_handle_;
+};
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int WindowsDeathTest::Wait() {
+  if (!spawned())
+    return 0;
+
+  // Wait until the child either signals that it has acquired the write end
+  // of the pipe or it dies.
+  const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() };
+  switch (::WaitForMultipleObjects(2,
+                                   wait_handles,
+                                   FALSE,  // Waits for any of the handles.
+                                   INFINITE)) {
+    case WAIT_OBJECT_0:
+    case WAIT_OBJECT_0 + 1:
+      break;
+    default:
+      GTEST_DEATH_TEST_CHECK_(false);  // Should not get here.
+  }
+
+  // The child has acquired the write end of the pipe or exited.
+  // We release the handle on our side and continue.
+  write_handle_.Reset();
+  event_handle_.Reset();
+
+  ReadAndInterpretStatusByte();
+
+  // Waits for the child process to exit if it haven't already. This
+  // returns immediately if the child has already exited, regardless of
+  // whether previous calls to WaitForMultipleObjects synchronized on this
+  // handle or not.
+  GTEST_DEATH_TEST_CHECK_(
+      WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(),
+                                             INFINITE));
+  DWORD status_code;
+  GTEST_DEATH_TEST_CHECK_(
+      ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
+  child_handle_.Reset();
+  set_status(static_cast<int>(status_code));
+  return status();
+}
+
+// The AssumeRole process for a Windows death test.  It creates a child
+// process with the same executable as the current process to run the
+// death test.  The child process is given the --gtest_filter and
+// --gtest_internal_run_death_test flags such that it knows to run the
+// current death test only.
+DeathTest::TestRole WindowsDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != nullptr) {
+    // ParseInternalRunDeathTestFlag() has performed all the necessary
+    // processing.
+    set_write_fd(flag->write_fd());
+    return EXECUTE_TEST;
+  }
+
+  // WindowsDeathTest uses an anonymous pipe to communicate results of
+  // a death test.
+  SECURITY_ATTRIBUTES handles_are_inheritable = {sizeof(SECURITY_ATTRIBUTES),
+                                                 nullptr, TRUE};
+  HANDLE read_handle, write_handle;
+  GTEST_DEATH_TEST_CHECK_(
+      ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
+                   0)  // Default buffer size.
+      != FALSE);
+  set_read_fd(::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle),
+                                O_RDONLY));
+  write_handle_.Reset(write_handle);
+  event_handle_.Reset(::CreateEvent(
+      &handles_are_inheritable,
+      TRUE,       // The event will automatically reset to non-signaled state.
+      FALSE,      // The initial state is non-signalled.
+      nullptr));  // The even is unnamed.
+  GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != nullptr);
+  const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
+                                  kFilterFlag + "=" + info->test_suite_name() +
+                                  "." + info->name();
+  const std::string internal_flag =
+      std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag +
+      "=" + file_ + "|" + StreamableToString(line_) + "|" +
+      StreamableToString(death_test_index) + "|" +
+      StreamableToString(static_cast<unsigned int>(::GetCurrentProcessId())) +
+      // size_t has the same width as pointers on both 32-bit and 64-bit
+      // Windows platforms.
+      // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
+      "|" + StreamableToString(reinterpret_cast<size_t>(write_handle)) +
+      "|" + StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
+
+  char executable_path[_MAX_PATH + 1];  // NOLINT
+  GTEST_DEATH_TEST_CHECK_(_MAX_PATH + 1 != ::GetModuleFileNameA(nullptr,
+                                                                executable_path,
+                                                                _MAX_PATH));
+
+  std::string command_line =
+      std::string(::GetCommandLineA()) + " " + filter_flag + " \"" +
+      internal_flag + "\"";
+
+  DeathTest::set_last_death_test_message("");
+
+  CaptureStderr();
+  // Flush the log buffers since the log streams are shared with the child.
+  FlushInfoLog();
+
+  // The child process will share the standard handles with the parent.
+  STARTUPINFOA startup_info;
+  memset(&startup_info, 0, sizeof(STARTUPINFO));
+  startup_info.dwFlags = STARTF_USESTDHANDLES;
+  startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
+  startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
+  startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
+
+  PROCESS_INFORMATION process_info;
+  GTEST_DEATH_TEST_CHECK_(
+      ::CreateProcessA(
+          executable_path, const_cast<char*>(command_line.c_str()),
+          nullptr,  // Retuned process handle is not inheritable.
+          nullptr,  // Retuned thread handle is not inheritable.
+          TRUE,  // Child inherits all inheritable handles (for write_handle_).
+          0x0,   // Default creation flags.
+          nullptr,  // Inherit the parent's environment.
+          UnitTest::GetInstance()->original_working_dir(), &startup_info,
+          &process_info) != FALSE);
+  child_handle_.Reset(process_info.hProcess);
+  ::CloseHandle(process_info.hThread);
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+
+# elif GTEST_OS_FUCHSIA
+
+class FuchsiaDeathTest : public DeathTestImpl {
+ public:
+  FuchsiaDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
+                   const char* file, int line)
+      : DeathTestImpl(a_statement, std::move(matcher)),
+        file_(file),
+        line_(line) {}
+
+  // All of these virtual functions are inherited from DeathTest.
+  int Wait() override;
+  TestRole AssumeRole() override;
+  std::string GetErrorLogs() override;
+
+ private:
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+  // The stderr data captured by the child process.
+  std::string captured_stderr_;
+
+  zx::process child_process_;
+  zx::channel exception_channel_;
+  zx::socket stderr_socket_;
+};
+
+// Utility class for accumulating command-line arguments.
+class Arguments {
+ public:
+  Arguments() { args_.push_back(nullptr); }
+
+  ~Arguments() {
+    for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
+         ++i) {
+      free(*i);
+    }
+  }
+  void AddArgument(const char* argument) {
+    args_.insert(args_.end() - 1, posix::StrDup(argument));
+  }
+
+  template <typename Str>
+  void AddArguments(const ::std::vector<Str>& arguments) {
+    for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
+         i != arguments.end();
+         ++i) {
+      args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
+    }
+  }
+  char* const* Argv() {
+    return &args_[0];
+  }
+
+  int size() {
+    return static_cast<int>(args_.size()) - 1;
+  }
+
+ private:
+  std::vector<char*> args_;
+};
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int FuchsiaDeathTest::Wait() {
+  const int kProcessKey = 0;
+  const int kSocketKey = 1;
+  const int kExceptionKey = 2;
+
+  if (!spawned())
+    return 0;
+
+  // Create a port to wait for socket/task/exception events.
+  zx_status_t status_zx;
+  zx::port port;
+  status_zx = zx::port::create(0, &port);
+  GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+
+  // Register to wait for the child process to terminate.
+  status_zx = child_process_.wait_async(
+      port, kProcessKey, ZX_PROCESS_TERMINATED, 0);
+  GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+
+  // Register to wait for the socket to be readable or closed.
+  status_zx = stderr_socket_.wait_async(
+      port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, 0);
+  GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+
+  // Register to wait for an exception.
+  status_zx = exception_channel_.wait_async(
+      port, kExceptionKey, ZX_CHANNEL_READABLE, 0);
+  GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+
+  bool process_terminated = false;
+  bool socket_closed = false;
+  do {
+    zx_port_packet_t packet = {};
+    status_zx = port.wait(zx::time::infinite(), &packet);
+    GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+
+    if (packet.key == kExceptionKey) {
+      // Process encountered an exception. Kill it directly rather than
+      // letting other handlers process the event. We will get a kProcessKey
+      // event when the process actually terminates.
+      status_zx = child_process_.kill();
+      GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+    } else if (packet.key == kProcessKey) {
+      // Process terminated.
+      GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
+      GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_PROCESS_TERMINATED);
+      process_terminated = true;
+    } else if (packet.key == kSocketKey) {
+      GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
+      if (packet.signal.observed & ZX_SOCKET_READABLE) {
+        // Read data from the socket.
+        constexpr size_t kBufferSize = 1024;
+        do {
+          size_t old_length = captured_stderr_.length();
+          size_t bytes_read = 0;
+          captured_stderr_.resize(old_length + kBufferSize);
+          status_zx = stderr_socket_.read(
+              0, &captured_stderr_.front() + old_length, kBufferSize,
+              &bytes_read);
+          captured_stderr_.resize(old_length + bytes_read);
+        } while (status_zx == ZX_OK);
+        if (status_zx == ZX_ERR_PEER_CLOSED) {
+          socket_closed = true;
+        } else {
+          GTEST_DEATH_TEST_CHECK_(status_zx == ZX_ERR_SHOULD_WAIT);
+          status_zx = stderr_socket_.wait_async(
+              port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, 0);
+          GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+        }
+      } else {
+        GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_SOCKET_PEER_CLOSED);
+        socket_closed = true;
+      }
+    }
+  } while (!process_terminated && !socket_closed);
+
+  ReadAndInterpretStatusByte();
+
+  zx_info_process_t buffer;
+  status_zx = child_process_.get_info(ZX_INFO_PROCESS, &buffer, sizeof(buffer),
+                                      nullptr, nullptr);
+  GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+
+  GTEST_DEATH_TEST_CHECK_(buffer.flags & ZX_INFO_PROCESS_FLAG_EXITED);
+  set_status(static_cast<int>(buffer.return_code));
+  return status();
+}
+
+// The AssumeRole process for a Fuchsia death test.  It creates a child
+// process with the same executable as the current process to run the
+// death test.  The child process is given the --gtest_filter and
+// --gtest_internal_run_death_test flags such that it knows to run the
+// current death test only.
+DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != nullptr) {
+    // ParseInternalRunDeathTestFlag() has performed all the necessary
+    // processing.
+    set_write_fd(kFuchsiaReadPipeFd);
+    return EXECUTE_TEST;
+  }
+
+  // Flush the log buffers since the log streams are shared with the child.
+  FlushInfoLog();
+
+  // Build the child process command line.
+  const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
+                                  kFilterFlag + "=" + info->test_suite_name() +
+                                  "." + info->name();
+  const std::string internal_flag =
+      std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
+      + file_ + "|"
+      + StreamableToString(line_) + "|"
+      + StreamableToString(death_test_index);
+  Arguments args;
+  args.AddArguments(GetInjectableArgvs());
+  args.AddArgument(filter_flag.c_str());
+  args.AddArgument(internal_flag.c_str());
+
+  // Build the pipe for communication with the child.
+  zx_status_t status;
+  zx_handle_t child_pipe_handle;
+  int child_pipe_fd;
+  status = fdio_pipe_half(&child_pipe_fd, &child_pipe_handle);
+  GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
+  set_read_fd(child_pipe_fd);
+
+  // Set the pipe handle for the child.
+  fdio_spawn_action_t spawn_actions[2] = {};
+  fdio_spawn_action_t* add_handle_action = &spawn_actions[0];
+  add_handle_action->action = FDIO_SPAWN_ACTION_ADD_HANDLE;
+  add_handle_action->h.id = PA_HND(PA_FD, kFuchsiaReadPipeFd);
+  add_handle_action->h.handle = child_pipe_handle;
+
+  // Create a socket pair will be used to receive the child process' stderr.
+  zx::socket stderr_producer_socket;
+  status =
+      zx::socket::create(0, &stderr_producer_socket, &stderr_socket_);
+  GTEST_DEATH_TEST_CHECK_(status >= 0);
+  int stderr_producer_fd = -1;
+  status =
+      fdio_fd_create(stderr_producer_socket.release(), &stderr_producer_fd);
+  GTEST_DEATH_TEST_CHECK_(status >= 0);
+
+  // Make the stderr socket nonblocking.
+  GTEST_DEATH_TEST_CHECK_(fcntl(stderr_producer_fd, F_SETFL, 0) == 0);
+
+  fdio_spawn_action_t* add_stderr_action = &spawn_actions[1];
+  add_stderr_action->action = FDIO_SPAWN_ACTION_CLONE_FD;
+  add_stderr_action->fd.local_fd = stderr_producer_fd;
+  add_stderr_action->fd.target_fd = STDERR_FILENO;
+
+  // Create a child job.
+  zx_handle_t child_job = ZX_HANDLE_INVALID;
+  status = zx_job_create(zx_job_default(), 0, & child_job);
+  GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
+  zx_policy_basic_t policy;
+  policy.condition = ZX_POL_NEW_ANY;
+  policy.policy = ZX_POL_ACTION_ALLOW;
+  status = zx_job_set_policy(
+      child_job, ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC, &policy, 1);
+  GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
+
+  // Create an exception channel attached to the |child_job|, to allow
+  // us to suppress the system default exception handler from firing.
+  status =
+      zx_task_create_exception_channel(
+          child_job, 0, exception_channel_.reset_and_get_address());
+  GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
+
+  // Spawn the child process.
+  status = fdio_spawn_etc(
+      child_job, FDIO_SPAWN_CLONE_ALL, args.Argv()[0], args.Argv(), nullptr,
+      2, spawn_actions, child_process_.reset_and_get_address(), nullptr);
+  GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
+
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+
+std::string FuchsiaDeathTest::GetErrorLogs() {
+  return captured_stderr_;
+}
+
+#else  // We are neither on Windows, nor on Fuchsia.
+
+// ForkingDeathTest provides implementations for most of the abstract
+// methods of the DeathTest interface.  Only the AssumeRole method is
+// left undefined.
+class ForkingDeathTest : public DeathTestImpl {
+ public:
+  ForkingDeathTest(const char* statement, Matcher<const std::string&> matcher);
+
+  // All of these virtual functions are inherited from DeathTest.
+  int Wait() override;
+
+ protected:
+  void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
+
+ private:
+  // PID of child process during death test; 0 in the child process itself.
+  pid_t child_pid_;
+};
+
+// Constructs a ForkingDeathTest.
+ForkingDeathTest::ForkingDeathTest(const char* a_statement,
+                                   Matcher<const std::string&> matcher)
+    : DeathTestImpl(a_statement, std::move(matcher)), child_pid_(-1) {}
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int ForkingDeathTest::Wait() {
+  if (!spawned())
+    return 0;
+
+  ReadAndInterpretStatusByte();
+
+  int status_value;
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0));
+  set_status(status_value);
+  return status_value;
+}
+
+// A concrete death test class that forks, then immediately runs the test
+// in the child process.
+class NoExecDeathTest : public ForkingDeathTest {
+ public:
+  NoExecDeathTest(const char* a_statement, Matcher<const std::string&> matcher)
+      : ForkingDeathTest(a_statement, std::move(matcher)) {}
+  TestRole AssumeRole() override;
+};
+
+// The AssumeRole process for a fork-and-run death test.  It implements a
+// straightforward fork, with a simple pipe to transmit the status byte.
+DeathTest::TestRole NoExecDeathTest::AssumeRole() {
+  const size_t thread_count = GetThreadCount();
+  if (thread_count != 1) {
+    GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count);
+  }
+
+  int pipe_fd[2];
+  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+
+  DeathTest::set_last_death_test_message("");
+  CaptureStderr();
+  // When we fork the process below, the log file buffers are copied, but the
+  // file descriptors are shared.  We flush all log files here so that closing
+  // the file descriptors in the child process doesn't throw off the
+  // synchronization between descriptors and buffers in the parent process.
+  // This is as close to the fork as possible to avoid a race condition in case
+  // there are multiple threads running before the death test, and another
+  // thread writes to the log file.
+  FlushInfoLog();
+
+  const pid_t child_pid = fork();
+  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+  set_child_pid(child_pid);
+  if (child_pid == 0) {
+    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0]));
+    set_write_fd(pipe_fd[1]);
+    // Redirects all logging to stderr in the child process to prevent
+    // concurrent writes to the log files.  We capture stderr in the parent
+    // process and append the child process' output to a log.
+    LogToStderr();
+    // Event forwarding to the listeners of event listener API mush be shut
+    // down in death test subprocesses.
+    GetUnitTestImpl()->listeners()->SuppressEventForwarding();
+    g_in_fast_death_test_child = true;
+    return EXECUTE_TEST;
+  } else {
+    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+    set_read_fd(pipe_fd[0]);
+    set_spawned(true);
+    return OVERSEE_TEST;
+  }
+}
+
+// A concrete death test class that forks and re-executes the main
+// program from the beginning, with command-line flags set that cause
+// only this specific death test to be run.
+class ExecDeathTest : public ForkingDeathTest {
+ public:
+  ExecDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
+                const char* file, int line)
+      : ForkingDeathTest(a_statement, std::move(matcher)),
+        file_(file),
+        line_(line) {}
+  TestRole AssumeRole() override;
+
+ private:
+  static ::std::vector<std::string> GetArgvsForDeathTestChildProcess() {
+    ::std::vector<std::string> args = GetInjectableArgvs();
+#  if defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
+    ::std::vector<std::string> extra_args =
+        GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_();
+    args.insert(args.end(), extra_args.begin(), extra_args.end());
+#  endif  // defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
+    return args;
+  }
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+};
+
+// Utility class for accumulating command-line arguments.
+class Arguments {
+ public:
+  Arguments() { args_.push_back(nullptr); }
+
+  ~Arguments() {
+    for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
+         ++i) {
+      free(*i);
+    }
+  }
+  void AddArgument(const char* argument) {
+    args_.insert(args_.end() - 1, posix::StrDup(argument));
+  }
+
+  template <typename Str>
+  void AddArguments(const ::std::vector<Str>& arguments) {
+    for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
+         i != arguments.end();
+         ++i) {
+      args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
+    }
+  }
+  char* const* Argv() {
+    return &args_[0];
+  }
+
+ private:
+  std::vector<char*> args_;
+};
+
+// A struct that encompasses the arguments to the child process of a
+// threadsafe-style death test process.
+struct ExecDeathTestArgs {
+  char* const* argv;  // Command-line arguments for the child's call to exec
+  int close_fd;       // File descriptor to close; the read end of a pipe
+};
+
+#  if GTEST_OS_QNX
+extern "C" char** environ;
+#  else  // GTEST_OS_QNX
+// The main function for a threadsafe-style death test child process.
+// This function is called in a clone()-ed process and thus must avoid
+// any potentially unsafe operations like malloc or libc functions.
+static int ExecDeathTestChildMain(void* child_arg) {
+  ExecDeathTestArgs* const args = static_cast<ExecDeathTestArgs*>(child_arg);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd));
+
+  // We need to execute the test program in the same environment where
+  // it was originally invoked.  Therefore we change to the original
+  // working directory first.
+  const char* const original_dir =
+      UnitTest::GetInstance()->original_working_dir();
+  // We can safely call chdir() as it's a direct system call.
+  if (chdir(original_dir) != 0) {
+    DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " +
+                   GetLastErrnoDescription());
+    return EXIT_FAILURE;
+  }
+
+  // We can safely call execv() as it's almost a direct system call. We
+  // cannot use execvp() as it's a libc function and thus potentially
+  // unsafe.  Since execv() doesn't search the PATH, the user must
+  // invoke the test program via a valid path that contains at least
+  // one path separator.
+  execv(args->argv[0], args->argv);
+  DeathTestAbort(std::string("execv(") + args->argv[0] + ", ...) in " +
+                 original_dir + " failed: " +
+                 GetLastErrnoDescription());
+  return EXIT_FAILURE;
+}
+#  endif  // GTEST_OS_QNX
+
+#  if GTEST_HAS_CLONE
+// Two utility routines that together determine the direction the stack
+// grows.
+// This could be accomplished more elegantly by a single recursive
+// function, but we want to guard against the unlikely possibility of
+// a smart compiler optimizing the recursion away.
+//
+// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
+// StackLowerThanAddress into StackGrowsDown, which then doesn't give
+// correct answer.
+static void StackLowerThanAddress(const void* ptr,
+                                  bool* result) GTEST_NO_INLINE_;
+// Make sure sanitizers do not tamper with the stack here.
+// Ideally, we want to use `__builtin_frame_address` instead of a local variable
+// address with sanitizer disabled, but it does not work when the
+// compiler optimizes the stack frame out, which happens on PowerPC targets.
+// HWAddressSanitizer add a random tag to the MSB of the local variable address,
+// making comparison result unpredictable.
+GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
+static void StackLowerThanAddress(const void* ptr, bool* result) {
+  int dummy = 0;
+  *result = std::less<const void*>()(&dummy, ptr);
+}
+
+// Make sure AddressSanitizer does not tamper with the stack here.
+GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
+static bool StackGrowsDown() {
+  int dummy = 0;
+  bool result;
+  StackLowerThanAddress(&dummy, &result);
+  return result;
+}
+#  endif  // GTEST_HAS_CLONE
+
+// Spawns a child process with the same executable as the current process in
+// a thread-safe manner and instructs it to run the death test.  The
+// implementation uses fork(2) + exec.  On systems where clone(2) is
+// available, it is used instead, being slightly more thread-safe.  On QNX,
+// fork supports only single-threaded environments, so this function uses
+// spawn(2) there instead.  The function dies with an error message if
+// anything goes wrong.
+static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
+  ExecDeathTestArgs args = { argv, close_fd };
+  pid_t child_pid = -1;
+
+#  if GTEST_OS_QNX
+  // Obtains the current directory and sets it to be closed in the child
+  // process.
+  const int cwd_fd = open(".", O_RDONLY);
+  GTEST_DEATH_TEST_CHECK_(cwd_fd != -1);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC));
+  // We need to execute the test program in the same environment where
+  // it was originally invoked.  Therefore we change to the original
+  // working directory first.
+  const char* const original_dir =
+      UnitTest::GetInstance()->original_working_dir();
+  // We can safely call chdir() as it's a direct system call.
+  if (chdir(original_dir) != 0) {
+    DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " +
+                   GetLastErrnoDescription());
+    return EXIT_FAILURE;
+  }
+
+  int fd_flags;
+  // Set close_fd to be closed after spawn.
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD));
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD,
+                                        fd_flags | FD_CLOEXEC));
+  struct inheritance inherit = {0};
+  // spawn is a system call.
+  child_pid = spawn(args.argv[0], 0, nullptr, &inherit, args.argv, environ);
+  // Restores the current working directory.
+  GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
+
+#  else   // GTEST_OS_QNX
+#   if GTEST_OS_LINUX
+  // When a SIGPROF signal is received while fork() or clone() are executing,
+  // the process may hang. To avoid this, we ignore SIGPROF here and re-enable
+  // it after the call to fork()/clone() is complete.
+  struct sigaction saved_sigprof_action;
+  struct sigaction ignore_sigprof_action;
+  memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action));
+  sigemptyset(&ignore_sigprof_action.sa_mask);
+  ignore_sigprof_action.sa_handler = SIG_IGN;
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction(
+      SIGPROF, &ignore_sigprof_action, &saved_sigprof_action));
+#   endif  // GTEST_OS_LINUX
+
+#   if GTEST_HAS_CLONE
+  const bool use_fork = GTEST_FLAG(death_test_use_fork);
+
+  if (!use_fork) {
+    static const bool stack_grows_down = StackGrowsDown();
+    const auto stack_size = static_cast<size_t>(getpagesize() * 2);
+    // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
+    void* const stack = mmap(nullptr, stack_size, PROT_READ | PROT_WRITE,
+                             MAP_ANON | MAP_PRIVATE, -1, 0);
+    GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
+
+    // Maximum stack alignment in bytes:  For a downward-growing stack, this
+    // amount is subtracted from size of the stack space to get an address
+    // that is within the stack space and is aligned on all systems we care
+    // about.  As far as I know there is no ABI with stack alignment greater
+    // than 64.  We assume stack and stack_size already have alignment of
+    // kMaxStackAlignment.
+    const size_t kMaxStackAlignment = 64;
+    void* const stack_top =
+        static_cast<char*>(stack) +
+            (stack_grows_down ? stack_size - kMaxStackAlignment : 0);
+    GTEST_DEATH_TEST_CHECK_(
+        static_cast<size_t>(stack_size) > kMaxStackAlignment &&
+        reinterpret_cast<uintptr_t>(stack_top) % kMaxStackAlignment == 0);
+
+    child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
+
+    GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
+  }
+#   else
+  const bool use_fork = true;
+#   endif  // GTEST_HAS_CLONE
+
+  if (use_fork && (child_pid = fork()) == 0) {
+      ExecDeathTestChildMain(&args);
+      _exit(0);
+  }
+#  endif  // GTEST_OS_QNX
+#  if GTEST_OS_LINUX
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(
+      sigaction(SIGPROF, &saved_sigprof_action, nullptr));
+#  endif  // GTEST_OS_LINUX
+
+  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+  return child_pid;
+}
+
+// The AssumeRole process for a fork-and-exec death test.  It re-executes the
+// main program from the beginning, setting the --gtest_filter
+// and --gtest_internal_run_death_test flags to cause only the current
+// death test to be re-run.
+DeathTest::TestRole ExecDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != nullptr) {
+    set_write_fd(flag->write_fd());
+    return EXECUTE_TEST;
+  }
+
+  int pipe_fd[2];
+  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+  // Clear the close-on-exec flag on the write end of the pipe, lest
+  // it be closed when the child process does an exec:
+  GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
+
+  const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
+                                  kFilterFlag + "=" + info->test_suite_name() +
+                                  "." + info->name();
+  const std::string internal_flag =
+      std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
+      + file_ + "|" + StreamableToString(line_) + "|"
+      + StreamableToString(death_test_index) + "|"
+      + StreamableToString(pipe_fd[1]);
+  Arguments args;
+  args.AddArguments(GetArgvsForDeathTestChildProcess());
+  args.AddArgument(filter_flag.c_str());
+  args.AddArgument(internal_flag.c_str());
+
+  DeathTest::set_last_death_test_message("");
+
+  CaptureStderr();
+  // See the comment in NoExecDeathTest::AssumeRole for why the next line
+  // is necessary.
+  FlushInfoLog();
+
+  const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+  set_child_pid(child_pid);
+  set_read_fd(pipe_fd[0]);
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+
+# endif  // !GTEST_OS_WINDOWS
+
+// Creates a concrete DeathTest-derived class that depends on the
+// --gtest_death_test_style flag, and sets the pointer pointed to
+// by the "test" argument to its address.  If the test should be
+// skipped, sets that pointer to NULL.  Returns true, unless the
+// flag is set to an invalid value.
+bool DefaultDeathTestFactory::Create(const char* statement,
+                                     Matcher<const std::string&> matcher,
+                                     const char* file, int line,
+                                     DeathTest** test) {
+  UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const int death_test_index = impl->current_test_info()
+      ->increment_death_test_count();
+
+  if (flag != nullptr) {
+    if (death_test_index > flag->index()) {
+      DeathTest::set_last_death_test_message(
+          "Death test count (" + StreamableToString(death_test_index)
+          + ") somehow exceeded expected maximum ("
+          + StreamableToString(flag->index()) + ")");
+      return false;
+    }
+
+    if (!(flag->file() == file && flag->line() == line &&
+          flag->index() == death_test_index)) {
+      *test = nullptr;
+      return true;
+    }
+  }
+
+# if GTEST_OS_WINDOWS
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe" ||
+      GTEST_FLAG(death_test_style) == "fast") {
+    *test = new WindowsDeathTest(statement, std::move(matcher), file, line);
+  }
+
+# elif GTEST_OS_FUCHSIA
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe" ||
+      GTEST_FLAG(death_test_style) == "fast") {
+    *test = new FuchsiaDeathTest(statement, std::move(matcher), file, line);
+  }
+
+# else
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe") {
+    *test = new ExecDeathTest(statement, std::move(matcher), file, line);
+  } else if (GTEST_FLAG(death_test_style) == "fast") {
+    *test = new NoExecDeathTest(statement, std::move(matcher));
+  }
+
+# endif  // GTEST_OS_WINDOWS
+
+  else {  // NOLINT - this is more readable than unbalanced brackets inside #if.
+    DeathTest::set_last_death_test_message(
+        "Unknown death test style \"" + GTEST_FLAG(death_test_style)
+        + "\" encountered");
+    return false;
+  }
+
+  return true;
+}
+
+# if GTEST_OS_WINDOWS
+// Recreates the pipe and event handles from the provided parameters,
+// signals the event, and returns a file descriptor wrapped around the pipe
+// handle. This function is called in the child process only.
+static int GetStatusFileDescriptor(unsigned int parent_process_id,
+                            size_t write_handle_as_size_t,
+                            size_t event_handle_as_size_t) {
+  AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
+                                                   FALSE,  // Non-inheritable.
+                                                   parent_process_id));
+  if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) {
+    DeathTestAbort("Unable to open parent process " +
+                   StreamableToString(parent_process_id));
+  }
+
+  GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
+
+  const HANDLE write_handle =
+      reinterpret_cast<HANDLE>(write_handle_as_size_t);
+  HANDLE dup_write_handle;
+
+  // The newly initialized handle is accessible only in the parent
+  // process. To obtain one accessible within the child, we need to use
+  // DuplicateHandle.
+  if (!::DuplicateHandle(parent_process_handle.Get(), write_handle,
+                         ::GetCurrentProcess(), &dup_write_handle,
+                         0x0,    // Requested privileges ignored since
+                                 // DUPLICATE_SAME_ACCESS is used.
+                         FALSE,  // Request non-inheritable handler.
+                         DUPLICATE_SAME_ACCESS)) {
+    DeathTestAbort("Unable to duplicate the pipe handle " +
+                   StreamableToString(write_handle_as_size_t) +
+                   " from the parent process " +
+                   StreamableToString(parent_process_id));
+  }
+
+  const HANDLE event_handle = reinterpret_cast<HANDLE>(event_handle_as_size_t);
+  HANDLE dup_event_handle;
+
+  if (!::DuplicateHandle(parent_process_handle.Get(), event_handle,
+                         ::GetCurrentProcess(), &dup_event_handle,
+                         0x0,
+                         FALSE,
+                         DUPLICATE_SAME_ACCESS)) {
+    DeathTestAbort("Unable to duplicate the event handle " +
+                   StreamableToString(event_handle_as_size_t) +
+                   " from the parent process " +
+                   StreamableToString(parent_process_id));
+  }
+
+  const int write_fd =
+      ::_open_osfhandle(reinterpret_cast<intptr_t>(dup_write_handle), O_APPEND);
+  if (write_fd == -1) {
+    DeathTestAbort("Unable to convert pipe handle " +
+                   StreamableToString(write_handle_as_size_t) +
+                   " to a file descriptor");
+  }
+
+  // Signals the parent that the write end of the pipe has been acquired
+  // so the parent can release its own write end.
+  ::SetEvent(dup_event_handle);
+
+  return write_fd;
+}
+# endif  // GTEST_OS_WINDOWS
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
+  if (GTEST_FLAG(internal_run_death_test) == "") return nullptr;
+
+  // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
+  // can use it here.
+  int line = -1;
+  int index = -1;
+  ::std::vector< ::std::string> fields;
+  SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields);
+  int write_fd = -1;
+
+# if GTEST_OS_WINDOWS
+
+  unsigned int parent_process_id = 0;
+  size_t write_handle_as_size_t = 0;
+  size_t event_handle_as_size_t = 0;
+
+  if (fields.size() != 6
+      || !ParseNaturalNumber(fields[1], &line)
+      || !ParseNaturalNumber(fields[2], &index)
+      || !ParseNaturalNumber(fields[3], &parent_process_id)
+      || !ParseNaturalNumber(fields[4], &write_handle_as_size_t)
+      || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
+    DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
+                   GTEST_FLAG(internal_run_death_test));
+  }
+  write_fd = GetStatusFileDescriptor(parent_process_id,
+                                     write_handle_as_size_t,
+                                     event_handle_as_size_t);
+
+# elif GTEST_OS_FUCHSIA
+
+  if (fields.size() != 3
+      || !ParseNaturalNumber(fields[1], &line)
+      || !ParseNaturalNumber(fields[2], &index)) {
+    DeathTestAbort("Bad --gtest_internal_run_death_test flag: "
+        + GTEST_FLAG(internal_run_death_test));
+  }
+
+# else
+
+  if (fields.size() != 4
+      || !ParseNaturalNumber(fields[1], &line)
+      || !ParseNaturalNumber(fields[2], &index)
+      || !ParseNaturalNumber(fields[3], &write_fd)) {
+    DeathTestAbort("Bad --gtest_internal_run_death_test flag: "
+        + GTEST_FLAG(internal_run_death_test));
+  }
+
+# endif  // GTEST_OS_WINDOWS
+
+  return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
+}
+
+}  // namespace internal
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace testing
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+#include <stdlib.h>
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>
+#elif GTEST_OS_WINDOWS
+# include <direct.h>
+# include <io.h>
+#else
+# include <limits.h>
+# include <climits>  // Some Linux distributions define PATH_MAX here.
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+
+#if GTEST_OS_WINDOWS
+# define GTEST_PATH_MAX_ _MAX_PATH
+#elif defined(PATH_MAX)
+# define GTEST_PATH_MAX_ PATH_MAX
+#elif defined(_XOPEN_PATH_MAX)
+# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
+#else
+# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
+#endif  // GTEST_OS_WINDOWS
+
+namespace testing {
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+// On Windows, '\\' is the standard path separator, but many tools and the
+// Windows API also accept '/' as an alternate path separator. Unless otherwise
+// noted, a file path can contain either kind of path separators, or a mixture
+// of them.
+const char kPathSeparator = '\\';
+const char kAlternatePathSeparator = '/';
+const char kAlternatePathSeparatorString[] = "/";
+# if GTEST_OS_WINDOWS_MOBILE
+// Windows CE doesn't have a current directory. You should not use
+// the current directory in tests on Windows CE, but this at least
+// provides a reasonable fallback.
+const char kCurrentDirectoryString[] = "\\";
+// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
+const DWORD kInvalidFileAttributes = 0xffffffff;
+# else
+const char kCurrentDirectoryString[] = ".\\";
+# endif  // GTEST_OS_WINDOWS_MOBILE
+#else
+const char kPathSeparator = '/';
+const char kCurrentDirectoryString[] = "./";
+#endif  // GTEST_OS_WINDOWS
+
+// Returns whether the given character is a valid path separator.
+static bool IsPathSeparator(char c) {
+#if GTEST_HAS_ALT_PATH_SEP_
+  return (c == kPathSeparator) || (c == kAlternatePathSeparator);
+#else
+  return c == kPathSeparator;
+#endif
+}
+
+// Returns the current working directory, or "" if unsuccessful.
+FilePath FilePath::GetCurrentDir() {
+#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE ||         \
+    GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_ESP32 || \
+    GTEST_OS_XTENSA
+  // These platforms do not have a current directory, so we just return
+  // something reasonable.
+  return FilePath(kCurrentDirectoryString);
+#elif GTEST_OS_WINDOWS
+  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+  return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd);
+#else
+  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+  char* result = getcwd(cwd, sizeof(cwd));
+# if GTEST_OS_NACL
+  // getcwd will likely fail in NaCl due to the sandbox, so return something
+  // reasonable. The user may have provided a shim implementation for getcwd,
+  // however, so fallback only when failure is detected.
+  return FilePath(result == nullptr ? kCurrentDirectoryString : cwd);
+# endif  // GTEST_OS_NACL
+  return FilePath(result == nullptr ? "" : cwd);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns a copy of the FilePath with the case-insensitive extension removed.
+// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+// FilePath("dir/file"). If a case-insensitive extension is not
+// found, returns a copy of the original FilePath.
+FilePath FilePath::RemoveExtension(const char* extension) const {
+  const std::string dot_extension = std::string(".") + extension;
+  if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) {
+    return FilePath(pathname_.substr(
+        0, pathname_.length() - dot_extension.length()));
+  }
+  return *this;
+}
+
+// Returns a pointer to the last occurrence of a valid path separator in
+// the FilePath. On Windows, for example, both '/' and '\' are valid path
+// separators. Returns NULL if no path separator was found.
+const char* FilePath::FindLastPathSeparator() const {
+  const char* const last_sep = strrchr(c_str(), kPathSeparator);
+#if GTEST_HAS_ALT_PATH_SEP_
+  const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
+  // Comparing two pointers of which only one is NULL is undefined.
+  if (last_alt_sep != nullptr &&
+      (last_sep == nullptr || last_alt_sep > last_sep)) {
+    return last_alt_sep;
+  }
+#endif
+  return last_sep;
+}
+
+// Returns a copy of the FilePath with the directory part removed.
+// Example: FilePath("path/to/file").RemoveDirectoryName() returns
+// FilePath("file"). If there is no directory part ("just_a_file"), it returns
+// the FilePath unmodified. If there is no file part ("just_a_dir/") it
+// returns an empty FilePath ("").
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveDirectoryName() const {
+  const char* const last_sep = FindLastPathSeparator();
+  return last_sep ? FilePath(last_sep + 1) : *this;
+}
+
+// RemoveFileName returns the directory path with the filename removed.
+// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveFileName() const {
+  const char* const last_sep = FindLastPathSeparator();
+  std::string dir;
+  if (last_sep) {
+    dir = std::string(c_str(), static_cast<size_t>(last_sep + 1 - c_str()));
+  } else {
+    dir = kCurrentDirectoryString;
+  }
+  return FilePath(dir);
+}
+
+// Helper functions for naming files in a directory for xml output.
+
+// Given directory = "dir", base_name = "test", number = 0,
+// extension = "xml", returns "dir/test.xml". If number is greater
+// than zero (e.g., 12), returns "dir/test_12.xml".
+// On Windows platform, uses \ as the separator rather than /.
+FilePath FilePath::MakeFileName(const FilePath& directory,
+                                const FilePath& base_name,
+                                int number,
+                                const char* extension) {
+  std::string file;
+  if (number == 0) {
+    file = base_name.string() + "." + extension;
+  } else {
+    file = base_name.string() + "_" + StreamableToString(number)
+        + "." + extension;
+  }
+  return ConcatPaths(directory, FilePath(file));
+}
+
+// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
+// On Windows, uses \ as the separator rather than /.
+FilePath FilePath::ConcatPaths(const FilePath& directory,
+                               const FilePath& relative_path) {
+  if (directory.IsEmpty())
+    return relative_path;
+  const FilePath dir(directory.RemoveTrailingPathSeparator());
+  return FilePath(dir.string() + kPathSeparator + relative_path.string());
+}
+
+// Returns true if pathname describes something findable in the file-system,
+// either a file, directory, or whatever.
+bool FilePath::FileOrDirectoryExists() const {
+#if GTEST_OS_WINDOWS_MOBILE
+  LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
+  const DWORD attributes = GetFileAttributes(unicode);
+  delete [] unicode;
+  return attributes != kInvalidFileAttributes;
+#else
+  posix::StatStruct file_stat{};
+  return posix::Stat(pathname_.c_str(), &file_stat) == 0;
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns true if pathname describes a directory in the file-system
+// that exists.
+bool FilePath::DirectoryExists() const {
+  bool result = false;
+#if GTEST_OS_WINDOWS
+  // Don't strip off trailing separator if path is a root directory on
+  // Windows (like "C:\\").
+  const FilePath& path(IsRootDirectory() ? *this :
+                                           RemoveTrailingPathSeparator());
+#else
+  const FilePath& path(*this);
+#endif
+
+#if GTEST_OS_WINDOWS_MOBILE
+  LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
+  const DWORD attributes = GetFileAttributes(unicode);
+  delete [] unicode;
+  if ((attributes != kInvalidFileAttributes) &&
+      (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
+    result = true;
+  }
+#else
+  posix::StatStruct file_stat{};
+  result = posix::Stat(path.c_str(), &file_stat) == 0 &&
+      posix::IsDir(file_stat);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  return result;
+}
+
+// Returns true if pathname describes a root directory. (Windows has one
+// root directory per disk drive.)
+bool FilePath::IsRootDirectory() const {
+#if GTEST_OS_WINDOWS
+  return pathname_.length() == 3 && IsAbsolutePath();
+#else
+  return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
+#endif
+}
+
+// Returns true if pathname describes an absolute path.
+bool FilePath::IsAbsolutePath() const {
+  const char* const name = pathname_.c_str();
+#if GTEST_OS_WINDOWS
+  return pathname_.length() >= 3 &&
+     ((name[0] >= 'a' && name[0] <= 'z') ||
+      (name[0] >= 'A' && name[0] <= 'Z')) &&
+     name[1] == ':' &&
+     IsPathSeparator(name[2]);
+#else
+  return IsPathSeparator(name[0]);
+#endif
+}
+
+// Returns a pathname for a file that does not currently exist. The pathname
+// will be directory/base_name.extension or
+// directory/base_name_<number>.extension if directory/base_name.extension
+// already exists. The number will be incremented until a pathname is found
+// that does not already exist.
+// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+// There could be a race condition if two or more processes are calling this
+// function at the same time -- they could both pick the same filename.
+FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
+                                          const FilePath& base_name,
+                                          const char* extension) {
+  FilePath full_pathname;
+  int number = 0;
+  do {
+    full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
+  } while (full_pathname.FileOrDirectoryExists());
+  return full_pathname;
+}
+
+// Returns true if FilePath ends with a path separator, which indicates that
+// it is intended to represent a directory. Returns false otherwise.
+// This does NOT check that a directory (or file) actually exists.
+bool FilePath::IsDirectory() const {
+  return !pathname_.empty() &&
+         IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
+}
+
+// Create directories so that path exists. Returns true if successful or if
+// the directories already exist; returns false if unable to create directories
+// for any reason.
+bool FilePath::CreateDirectoriesRecursively() const {
+  if (!this->IsDirectory()) {
+    return false;
+  }
+
+  if (pathname_.length() == 0 || this->DirectoryExists()) {
+    return true;
+  }
+
+  const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
+  return parent.CreateDirectoriesRecursively() && this->CreateFolder();
+}
+
+// Create the directory so that path exists. Returns true if successful or
+// if the directory already exists; returns false if unable to create the
+// directory for any reason, including if the parent directory does not
+// exist. Not named "CreateDirectory" because that's a macro on Windows.
+bool FilePath::CreateFolder() const {
+#if GTEST_OS_WINDOWS_MOBILE
+  FilePath removed_sep(this->RemoveTrailingPathSeparator());
+  LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
+  int result = CreateDirectory(unicode, nullptr) ? 0 : -1;
+  delete [] unicode;
+#elif GTEST_OS_WINDOWS
+  int result = _mkdir(pathname_.c_str());
+#elif GTEST_OS_ESP8266 || GTEST_OS_XTENSA
+  // do nothing
+  int result = 0;
+#else
+  int result = mkdir(pathname_.c_str(), 0777);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  if (result == -1) {
+    return this->DirectoryExists();  // An error is OK if the directory exists.
+  }
+  return true;  // No error.
+}
+
+// If input name has a trailing separator character, remove it and return the
+// name, otherwise return the name string unmodified.
+// On Windows platform, uses \ as the separator, other platforms use /.
+FilePath FilePath::RemoveTrailingPathSeparator() const {
+  return IsDirectory()
+      ? FilePath(pathname_.substr(0, pathname_.length() - 1))
+      : *this;
+}
+
+// Removes any redundant separators that might be in the pathname.
+// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+// redundancies that might be in a pathname involving "." or "..".
+void FilePath::Normalize() {
+  auto out = pathname_.begin();
+
+  for (const char character : pathname_) {
+    if (!IsPathSeparator(character)) {
+      *(out++) = character;
+    } else if (out == pathname_.begin() || *std::prev(out) != kPathSeparator) {
+      *(out++) = kPathSeparator;
+    } else {
+      continue;
+    }
+  }
+
+  pathname_.erase(out, pathname_.end());
+}
+
+}  // namespace internal
+}  // namespace testing
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This file implements just enough of the matcher interface to allow
+// EXPECT_DEATH and friends to accept a matcher argument.
+
+
+#include <string>
+
+namespace testing {
+
+// Constructs a matcher that matches a const std::string& whose value is
+// equal to s.
+Matcher<const std::string&>::Matcher(const std::string& s) { *this = Eq(s); }
+
+// Constructs a matcher that matches a const std::string& whose value is
+// equal to s.
+Matcher<const std::string&>::Matcher(const char* s) {
+  *this = Eq(std::string(s));
+}
+
+// Constructs a matcher that matches a std::string whose value is equal to
+// s.
+Matcher<std::string>::Matcher(const std::string& s) { *this = Eq(s); }
+
+// Constructs a matcher that matches a std::string whose value is equal to
+// s.
+Matcher<std::string>::Matcher(const char* s) { *this = Eq(std::string(s)); }
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+// Constructs a matcher that matches a const StringView& whose value is
+// equal to s.
+Matcher<const internal::StringView&>::Matcher(const std::string& s) {
+  *this = Eq(s);
+}
+
+// Constructs a matcher that matches a const StringView& whose value is
+// equal to s.
+Matcher<const internal::StringView&>::Matcher(const char* s) {
+  *this = Eq(std::string(s));
+}
+
+// Constructs a matcher that matches a const StringView& whose value is
+// equal to s.
+Matcher<const internal::StringView&>::Matcher(internal::StringView s) {
+  *this = Eq(std::string(s));
+}
+
+// Constructs a matcher that matches a StringView whose value is equal to
+// s.
+Matcher<internal::StringView>::Matcher(const std::string& s) { *this = Eq(s); }
+
+// Constructs a matcher that matches a StringView whose value is equal to
+// s.
+Matcher<internal::StringView>::Matcher(const char* s) {
+  *this = Eq(std::string(s));
+}
+
+// Constructs a matcher that matches a StringView whose value is equal to
+// s.
+Matcher<internal::StringView>::Matcher(internal::StringView s) {
+  *this = Eq(std::string(s));
+}
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+}  // namespace testing
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cstdint>
+#include <fstream>
+#include <memory>
+
+#if GTEST_OS_WINDOWS
+# include <windows.h>
+# include <io.h>
+# include <sys/stat.h>
+# include <map>  // Used in ThreadLocal.
+# ifdef _MSC_VER
+#  include <crtdbg.h>
+# endif  // _MSC_VER
+#else
+# include <unistd.h>
+#endif  // GTEST_OS_WINDOWS
+
+#if GTEST_OS_MAC
+# include <mach/mach_init.h>
+# include <mach/task.h>
+# include <mach/vm_map.h>
+#endif  // GTEST_OS_MAC
+
+#if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
+    GTEST_OS_NETBSD || GTEST_OS_OPENBSD
+# include <sys/sysctl.h>
+# if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD
+#  include <sys/user.h>
+# endif
+#endif
+
+#if GTEST_OS_QNX
+# include <devctl.h>
+# include <fcntl.h>
+# include <sys/procfs.h>
+#endif  // GTEST_OS_QNX
+
+#if GTEST_OS_AIX
+# include <procinfo.h>
+# include <sys/types.h>
+#endif  // GTEST_OS_AIX
+
+#if GTEST_OS_FUCHSIA
+# include <zircon/process.h>
+# include <zircon/syscalls.h>
+#endif  // GTEST_OS_FUCHSIA
+
+
+namespace testing {
+namespace internal {
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
+const int kStdOutFileno = 1;
+const int kStdErrFileno = 2;
+#else
+const int kStdOutFileno = STDOUT_FILENO;
+const int kStdErrFileno = STDERR_FILENO;
+#endif  // _MSC_VER
+
+#if GTEST_OS_LINUX || GTEST_OS_GNU_HURD
+
+namespace {
+template <typename T>
+T ReadProcFileField(const std::string& filename, int field) {
+  std::string dummy;
+  std::ifstream file(filename.c_str());
+  while (field-- > 0) {
+    file >> dummy;
+  }
+  T output = 0;
+  file >> output;
+  return output;
+}
+}  // namespace
+
+// Returns the number of active threads, or 0 when there is an error.
+size_t GetThreadCount() {
+  const std::string filename =
+      (Message() << "/proc/" << getpid() << "/stat").GetString();
+  return ReadProcFileField<size_t>(filename, 19);
+}
+
+#elif GTEST_OS_MAC
+
+size_t GetThreadCount() {
+  const task_t task = mach_task_self();
+  mach_msg_type_number_t thread_count;
+  thread_act_array_t thread_list;
+  const kern_return_t status = task_threads(task, &thread_list, &thread_count);
+  if (status == KERN_SUCCESS) {
+    // task_threads allocates resources in thread_list and we need to free them
+    // to avoid leaks.
+    vm_deallocate(task,
+                  reinterpret_cast<vm_address_t>(thread_list),
+                  sizeof(thread_t) * thread_count);
+    return static_cast<size_t>(thread_count);
+  } else {
+    return 0;
+  }
+}
+
+#elif GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
+      GTEST_OS_NETBSD
+
+#if GTEST_OS_NETBSD
+#undef KERN_PROC
+#define KERN_PROC KERN_PROC2
+#define kinfo_proc kinfo_proc2
+#endif
+
+#if GTEST_OS_DRAGONFLY
+#define KP_NLWP(kp) (kp.kp_nthreads)
+#elif GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD
+#define KP_NLWP(kp) (kp.ki_numthreads)
+#elif GTEST_OS_NETBSD
+#define KP_NLWP(kp) (kp.p_nlwps)
+#endif
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+  int mib[] = {
+    CTL_KERN,
+    KERN_PROC,
+    KERN_PROC_PID,
+    getpid(),
+#if GTEST_OS_NETBSD
+    sizeof(struct kinfo_proc),
+    1,
+#endif
+  };
+  u_int miblen = sizeof(mib) / sizeof(mib[0]);
+  struct kinfo_proc info;
+  size_t size = sizeof(info);
+  if (sysctl(mib, miblen, &info, &size, NULL, 0)) {
+    return 0;
+  }
+  return static_cast<size_t>(KP_NLWP(info));
+}
+#elif GTEST_OS_OPENBSD
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+  int mib[] = {
+    CTL_KERN,
+    KERN_PROC,
+    KERN_PROC_PID | KERN_PROC_SHOW_THREADS,
+    getpid(),
+    sizeof(struct kinfo_proc),
+    0,
+  };
+  u_int miblen = sizeof(mib) / sizeof(mib[0]);
+
+  // get number of structs
+  size_t size;
+  if (sysctl(mib, miblen, NULL, &size, NULL, 0)) {
+    return 0;
+  }
+
+  mib[5] = static_cast<int>(size / static_cast<size_t>(mib[4]));
+
+  // populate array of structs
+  struct kinfo_proc info[mib[5]];
+  if (sysctl(mib, miblen, &info, &size, NULL, 0)) {
+    return 0;
+  }
+
+  // exclude empty members
+  size_t nthreads = 0;
+  for (size_t i = 0; i < size / static_cast<size_t>(mib[4]); i++) {
+    if (info[i].p_tid != -1)
+      nthreads++;
+  }
+  return nthreads;
+}
+
+#elif GTEST_OS_QNX
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+  const int fd = open("/proc/self/as", O_RDONLY);
+  if (fd < 0) {
+    return 0;
+  }
+  procfs_info process_info;
+  const int status =
+      devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), nullptr);
+  close(fd);
+  if (status == EOK) {
+    return static_cast<size_t>(process_info.num_threads);
+  } else {
+    return 0;
+  }
+}
+
+#elif GTEST_OS_AIX
+
+size_t GetThreadCount() {
+  struct procentry64 entry;
+  pid_t pid = getpid();
+  int status = getprocs64(&entry, sizeof(entry), nullptr, 0, &pid, 1);
+  if (status == 1) {
+    return entry.pi_thcount;
+  } else {
+    return 0;
+  }
+}
+
+#elif GTEST_OS_FUCHSIA
+
+size_t GetThreadCount() {
+  int dummy_buffer;
+  size_t avail;
+  zx_status_t status = zx_object_get_info(
+      zx_process_self(),
+      ZX_INFO_PROCESS_THREADS,
+      &dummy_buffer,
+      0,
+      nullptr,
+      &avail);
+  if (status == ZX_OK) {
+    return avail;
+  } else {
+    return 0;
+  }
+}
+
+#else
+
+size_t GetThreadCount() {
+  // There's no portable way to detect the number of threads, so we just
+  // return 0 to indicate that we cannot detect it.
+  return 0;
+}
+
+#endif  // GTEST_OS_LINUX
+
+#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
+
+void SleepMilliseconds(int n) {
+  ::Sleep(static_cast<DWORD>(n));
+}
+
+AutoHandle::AutoHandle()
+    : handle_(INVALID_HANDLE_VALUE) {}
+
+AutoHandle::AutoHandle(Handle handle)
+    : handle_(handle) {}
+
+AutoHandle::~AutoHandle() {
+  Reset();
+}
+
+AutoHandle::Handle AutoHandle::Get() const {
+  return handle_;
+}
+
+void AutoHandle::Reset() {
+  Reset(INVALID_HANDLE_VALUE);
+}
+
+void AutoHandle::Reset(HANDLE handle) {
+  // Resetting with the same handle we already own is invalid.
+  if (handle_ != handle) {
+    if (IsCloseable()) {
+      ::CloseHandle(handle_);
+    }
+    handle_ = handle;
+  } else {
+    GTEST_CHECK_(!IsCloseable())
+        << "Resetting a valid handle to itself is likely a programmer error "
+            "and thus not allowed.";
+  }
+}
+
+bool AutoHandle::IsCloseable() const {
+  // Different Windows APIs may use either of these values to represent an
+  // invalid handle.
+  return handle_ != nullptr && handle_ != INVALID_HANDLE_VALUE;
+}
+
+Notification::Notification()
+    : event_(::CreateEvent(nullptr,     // Default security attributes.
+                           TRUE,        // Do not reset automatically.
+                           FALSE,       // Initially unset.
+                           nullptr)) {  // Anonymous event.
+  GTEST_CHECK_(event_.Get() != nullptr);
+}
+
+void Notification::Notify() {
+  GTEST_CHECK_(::SetEvent(event_.Get()) != FALSE);
+}
+
+void Notification::WaitForNotification() {
+  GTEST_CHECK_(
+      ::WaitForSingleObject(event_.Get(), INFINITE) == WAIT_OBJECT_0);
+}
+
+Mutex::Mutex()
+    : owner_thread_id_(0),
+      type_(kDynamic),
+      critical_section_init_phase_(0),
+      critical_section_(new CRITICAL_SECTION) {
+  ::InitializeCriticalSection(critical_section_);
+}
+
+Mutex::~Mutex() {
+  // Static mutexes are leaked intentionally. It is not thread-safe to try
+  // to clean them up.
+  if (type_ == kDynamic) {
+    ::DeleteCriticalSection(critical_section_);
+    delete critical_section_;
+    critical_section_ = nullptr;
+  }
+}
+
+void Mutex::Lock() {
+  ThreadSafeLazyInit();
+  ::EnterCriticalSection(critical_section_);
+  owner_thread_id_ = ::GetCurrentThreadId();
+}
+
+void Mutex::Unlock() {
+  ThreadSafeLazyInit();
+  // We don't protect writing to owner_thread_id_ here, as it's the
+  // caller's responsibility to ensure that the current thread holds the
+  // mutex when this is called.
+  owner_thread_id_ = 0;
+  ::LeaveCriticalSection(critical_section_);
+}
+
+// Does nothing if the current thread holds the mutex. Otherwise, crashes
+// with high probability.
+void Mutex::AssertHeld() {
+  ThreadSafeLazyInit();
+  GTEST_CHECK_(owner_thread_id_ == ::GetCurrentThreadId())
+      << "The current thread is not holding the mutex @" << this;
+}
+
+namespace {
+
+#ifdef _MSC_VER
+// Use the RAII idiom to flag mem allocs that are intentionally never
+// deallocated. The motivation is to silence the false positive mem leaks
+// that are reported by the debug version of MS's CRT which can only detect
+// if an alloc is missing a matching deallocation.
+// Example:
+//    MemoryIsNotDeallocated memory_is_not_deallocated;
+//    critical_section_ = new CRITICAL_SECTION;
+//
+class MemoryIsNotDeallocated
+{
+ public:
+  MemoryIsNotDeallocated() : old_crtdbg_flag_(0) {
+    old_crtdbg_flag_ = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
+    // Set heap allocation block type to _IGNORE_BLOCK so that MS debug CRT
+    // doesn't report mem leak if there's no matching deallocation.
+    _CrtSetDbgFlag(old_crtdbg_flag_ & ~_CRTDBG_ALLOC_MEM_DF);
+  }
+
+  ~MemoryIsNotDeallocated() {
+    // Restore the original _CRTDBG_ALLOC_MEM_DF flag
+    _CrtSetDbgFlag(old_crtdbg_flag_);
+  }
+
+ private:
+  int old_crtdbg_flag_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MemoryIsNotDeallocated);
+};
+#endif  // _MSC_VER
+
+}  // namespace
+
+// Initializes owner_thread_id_ and critical_section_ in static mutexes.
+void Mutex::ThreadSafeLazyInit() {
+  // Dynamic mutexes are initialized in the constructor.
+  if (type_ == kStatic) {
+    switch (
+        ::InterlockedCompareExchange(&critical_section_init_phase_, 1L, 0L)) {
+      case 0:
+        // If critical_section_init_phase_ was 0 before the exchange, we
+        // are the first to test it and need to perform the initialization.
+        owner_thread_id_ = 0;
+        {
+          // Use RAII to flag that following mem alloc is never deallocated.
+#ifdef _MSC_VER
+          MemoryIsNotDeallocated memory_is_not_deallocated;
+#endif  // _MSC_VER
+          critical_section_ = new CRITICAL_SECTION;
+        }
+        ::InitializeCriticalSection(critical_section_);
+        // Updates the critical_section_init_phase_ to 2 to signal
+        // initialization complete.
+        GTEST_CHECK_(::InterlockedCompareExchange(
+                          &critical_section_init_phase_, 2L, 1L) ==
+                      1L);
+        break;
+      case 1:
+        // Somebody else is already initializing the mutex; spin until they
+        // are done.
+        while (::InterlockedCompareExchange(&critical_section_init_phase_,
+                                            2L,
+                                            2L) != 2L) {
+          // Possibly yields the rest of the thread's time slice to other
+          // threads.
+          ::Sleep(0);
+        }
+        break;
+
+      case 2:
+        break;  // The mutex is already initialized and ready for use.
+
+      default:
+        GTEST_CHECK_(false)
+            << "Unexpected value of critical_section_init_phase_ "
+            << "while initializing a static mutex.";
+    }
+  }
+}
+
+namespace {
+
+class ThreadWithParamSupport : public ThreadWithParamBase {
+ public:
+  static HANDLE CreateThread(Runnable* runnable,
+                             Notification* thread_can_start) {
+    ThreadMainParam* param = new ThreadMainParam(runnable, thread_can_start);
+    DWORD thread_id;
+    HANDLE thread_handle = ::CreateThread(
+        nullptr,  // Default security.
+        0,        // Default stack size.
+        &ThreadWithParamSupport::ThreadMain,
+        param,        // Parameter to ThreadMainStatic
+        0x0,          // Default creation flags.
+        &thread_id);  // Need a valid pointer for the call to work under Win98.
+    GTEST_CHECK_(thread_handle != nullptr)
+        << "CreateThread failed with error " << ::GetLastError() << ".";
+    if (thread_handle == nullptr) {
+      delete param;
+    }
+    return thread_handle;
+  }
+
+ private:
+  struct ThreadMainParam {
+    ThreadMainParam(Runnable* runnable, Notification* thread_can_start)
+        : runnable_(runnable),
+          thread_can_start_(thread_can_start) {
+    }
+    std::unique_ptr<Runnable> runnable_;
+    // Does not own.
+    Notification* thread_can_start_;
+  };
+
+  static DWORD WINAPI ThreadMain(void* ptr) {
+    // Transfers ownership.
+    std::unique_ptr<ThreadMainParam> param(static_cast<ThreadMainParam*>(ptr));
+    if (param->thread_can_start_ != nullptr)
+      param->thread_can_start_->WaitForNotification();
+    param->runnable_->Run();
+    return 0;
+  }
+
+  // Prohibit instantiation.
+  ThreadWithParamSupport();
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParamSupport);
+};
+
+}  // namespace
+
+ThreadWithParamBase::ThreadWithParamBase(Runnable *runnable,
+                                         Notification* thread_can_start)
+      : thread_(ThreadWithParamSupport::CreateThread(runnable,
+                                                     thread_can_start)) {
+}
+
+ThreadWithParamBase::~ThreadWithParamBase() {
+  Join();
+}
+
+void ThreadWithParamBase::Join() {
+  GTEST_CHECK_(::WaitForSingleObject(thread_.Get(), INFINITE) == WAIT_OBJECT_0)
+      << "Failed to join the thread with error " << ::GetLastError() << ".";
+}
+
+// Maps a thread to a set of ThreadIdToThreadLocals that have values
+// instantiated on that thread and notifies them when the thread exits.  A
+// ThreadLocal instance is expected to persist until all threads it has
+// values on have terminated.
+class ThreadLocalRegistryImpl {
+ public:
+  // Registers thread_local_instance as having value on the current thread.
+  // Returns a value that can be used to identify the thread from other threads.
+  static ThreadLocalValueHolderBase* GetValueOnCurrentThread(
+      const ThreadLocalBase* thread_local_instance) {
+#ifdef _MSC_VER
+    MemoryIsNotDeallocated memory_is_not_deallocated;
+#endif  // _MSC_VER
+    DWORD current_thread = ::GetCurrentThreadId();
+    MutexLock lock(&mutex_);
+    ThreadIdToThreadLocals* const thread_to_thread_locals =
+        GetThreadLocalsMapLocked();
+    ThreadIdToThreadLocals::iterator thread_local_pos =
+        thread_to_thread_locals->find(current_thread);
+    if (thread_local_pos == thread_to_thread_locals->end()) {
+      thread_local_pos = thread_to_thread_locals->insert(
+          std::make_pair(current_thread, ThreadLocalValues())).first;
+      StartWatcherThreadFor(current_thread);
+    }
+    ThreadLocalValues& thread_local_values = thread_local_pos->second;
+    ThreadLocalValues::iterator value_pos =
+        thread_local_values.find(thread_local_instance);
+    if (value_pos == thread_local_values.end()) {
+      value_pos =
+          thread_local_values
+              .insert(std::make_pair(
+                  thread_local_instance,
+                  std::shared_ptr<ThreadLocalValueHolderBase>(
+                      thread_local_instance->NewValueForCurrentThread())))
+              .first;
+    }
+    return value_pos->second.get();
+  }
+
+  static void OnThreadLocalDestroyed(
+      const ThreadLocalBase* thread_local_instance) {
+    std::vector<std::shared_ptr<ThreadLocalValueHolderBase> > value_holders;
+    // Clean up the ThreadLocalValues data structure while holding the lock, but
+    // defer the destruction of the ThreadLocalValueHolderBases.
+    {
+      MutexLock lock(&mutex_);
+      ThreadIdToThreadLocals* const thread_to_thread_locals =
+          GetThreadLocalsMapLocked();
+      for (ThreadIdToThreadLocals::iterator it =
+          thread_to_thread_locals->begin();
+          it != thread_to_thread_locals->end();
+          ++it) {
+        ThreadLocalValues& thread_local_values = it->second;
+        ThreadLocalValues::iterator value_pos =
+            thread_local_values.find(thread_local_instance);
+        if (value_pos != thread_local_values.end()) {
+          value_holders.push_back(value_pos->second);
+          thread_local_values.erase(value_pos);
+          // This 'if' can only be successful at most once, so theoretically we
+          // could break out of the loop here, but we don't bother doing so.
+        }
+      }
+    }
+    // Outside the lock, let the destructor for 'value_holders' deallocate the
+    // ThreadLocalValueHolderBases.
+  }
+
+  static void OnThreadExit(DWORD thread_id) {
+    GTEST_CHECK_(thread_id != 0) << ::GetLastError();
+    std::vector<std::shared_ptr<ThreadLocalValueHolderBase> > value_holders;
+    // Clean up the ThreadIdToThreadLocals data structure while holding the
+    // lock, but defer the destruction of the ThreadLocalValueHolderBases.
+    {
+      MutexLock lock(&mutex_);
+      ThreadIdToThreadLocals* const thread_to_thread_locals =
+          GetThreadLocalsMapLocked();
+      ThreadIdToThreadLocals::iterator thread_local_pos =
+          thread_to_thread_locals->find(thread_id);
+      if (thread_local_pos != thread_to_thread_locals->end()) {
+        ThreadLocalValues& thread_local_values = thread_local_pos->second;
+        for (ThreadLocalValues::iterator value_pos =
+            thread_local_values.begin();
+            value_pos != thread_local_values.end();
+            ++value_pos) {
+          value_holders.push_back(value_pos->second);
+        }
+        thread_to_thread_locals->erase(thread_local_pos);
+      }
+    }
+    // Outside the lock, let the destructor for 'value_holders' deallocate the
+    // ThreadLocalValueHolderBases.
+  }
+
+ private:
+  // In a particular thread, maps a ThreadLocal object to its value.
+  typedef std::map<const ThreadLocalBase*,
+                   std::shared_ptr<ThreadLocalValueHolderBase> >
+      ThreadLocalValues;
+  // Stores all ThreadIdToThreadLocals having values in a thread, indexed by
+  // thread's ID.
+  typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals;
+
+  // Holds the thread id and thread handle that we pass from
+  // StartWatcherThreadFor to WatcherThreadFunc.
+  typedef std::pair<DWORD, HANDLE> ThreadIdAndHandle;
+
+  static void StartWatcherThreadFor(DWORD thread_id) {
+    // The returned handle will be kept in thread_map and closed by
+    // watcher_thread in WatcherThreadFunc.
+    HANDLE thread = ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
+                                 FALSE,
+                                 thread_id);
+    GTEST_CHECK_(thread != nullptr);
+    // We need to pass a valid thread ID pointer into CreateThread for it
+    // to work correctly under Win98.
+    DWORD watcher_thread_id;
+    HANDLE watcher_thread = ::CreateThread(
+        nullptr,  // Default security.
+        0,        // Default stack size
+        &ThreadLocalRegistryImpl::WatcherThreadFunc,
+        reinterpret_cast<LPVOID>(new ThreadIdAndHandle(thread_id, thread)),
+        CREATE_SUSPENDED, &watcher_thread_id);
+    GTEST_CHECK_(watcher_thread != nullptr);
+    // Give the watcher thread the same priority as ours to avoid being
+    // blocked by it.
+    ::SetThreadPriority(watcher_thread,
+                        ::GetThreadPriority(::GetCurrentThread()));
+    ::ResumeThread(watcher_thread);
+    ::CloseHandle(watcher_thread);
+  }
+
+  // Monitors exit from a given thread and notifies those
+  // ThreadIdToThreadLocals about thread termination.
+  static DWORD WINAPI WatcherThreadFunc(LPVOID param) {
+    const ThreadIdAndHandle* tah =
+        reinterpret_cast<const ThreadIdAndHandle*>(param);
+    GTEST_CHECK_(
+        ::WaitForSingleObject(tah->second, INFINITE) == WAIT_OBJECT_0);
+    OnThreadExit(tah->first);
+    ::CloseHandle(tah->second);
+    delete tah;
+    return 0;
+  }
+
+  // Returns map of thread local instances.
+  static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() {
+    mutex_.AssertHeld();
+#ifdef _MSC_VER
+    MemoryIsNotDeallocated memory_is_not_deallocated;
+#endif  // _MSC_VER
+    static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals();
+    return map;
+  }
+
+  // Protects access to GetThreadLocalsMapLocked() and its return value.
+  static Mutex mutex_;
+  // Protects access to GetThreadMapLocked() and its return value.
+  static Mutex thread_map_mutex_;
+};
+
+Mutex ThreadLocalRegistryImpl::mutex_(Mutex::kStaticMutex);  // NOLINT
+Mutex ThreadLocalRegistryImpl::thread_map_mutex_(Mutex::kStaticMutex);  // NOLINT
+
+ThreadLocalValueHolderBase* ThreadLocalRegistry::GetValueOnCurrentThread(
+      const ThreadLocalBase* thread_local_instance) {
+  return ThreadLocalRegistryImpl::GetValueOnCurrentThread(
+      thread_local_instance);
+}
+
+void ThreadLocalRegistry::OnThreadLocalDestroyed(
+      const ThreadLocalBase* thread_local_instance) {
+  ThreadLocalRegistryImpl::OnThreadLocalDestroyed(thread_local_instance);
+}
+
+#endif  // GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
+
+#if GTEST_USES_POSIX_RE
+
+// Implements RE.  Currently only needed for death tests.
+
+RE::~RE() {
+  if (is_valid_) {
+    // regfree'ing an invalid regex might crash because the content
+    // of the regex is undefined. Since the regex's are essentially
+    // the same, one cannot be valid (or invalid) without the other
+    // being so too.
+    regfree(&partial_regex_);
+    regfree(&full_regex_);
+  }
+  free(const_cast<char*>(pattern_));
+}
+
+// Returns true if and only if regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+  if (!re.is_valid_) return false;
+
+  regmatch_t match;
+  return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
+}
+
+// Returns true if and only if regular expression re matches a substring of
+// str (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+  if (!re.is_valid_) return false;
+
+  regmatch_t match;
+  return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+  pattern_ = posix::StrDup(regex);
+
+  // Reserves enough bytes to hold the regular expression used for a
+  // full match.
+  const size_t full_regex_len = strlen(regex) + 10;
+  char* const full_pattern = new char[full_regex_len];
+
+  snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
+  is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
+  // We want to call regcomp(&partial_regex_, ...) even if the
+  // previous expression returns false.  Otherwise partial_regex_ may
+  // not be properly initialized can may cause trouble when it's
+  // freed.
+  //
+  // Some implementation of POSIX regex (e.g. on at least some
+  // versions of Cygwin) doesn't accept the empty string as a valid
+  // regex.  We change it to an equivalent form "()" to be safe.
+  if (is_valid_) {
+    const char* const partial_regex = (*regex == '\0') ? "()" : regex;
+    is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
+  }
+  EXPECT_TRUE(is_valid_)
+      << "Regular expression \"" << regex
+      << "\" is not a valid POSIX Extended regular expression.";
+
+  delete[] full_pattern;
+}
+
+#elif GTEST_USES_SIMPLE_RE
+
+// Returns true if and only if ch appears anywhere in str (excluding the
+// terminating '\0' character).
+bool IsInSet(char ch, const char* str) {
+  return ch != '\0' && strchr(str, ch) != nullptr;
+}
+
+// Returns true if and only if ch belongs to the given classification.
+// Unlike similar functions in <ctype.h>, these aren't affected by the
+// current locale.
+bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
+bool IsAsciiPunct(char ch) {
+  return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
+}
+bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
+bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
+bool IsAsciiWordChar(char ch) {
+  return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
+      ('0' <= ch && ch <= '9') || ch == '_';
+}
+
+// Returns true if and only if "\\c" is a supported escape sequence.
+bool IsValidEscape(char c) {
+  return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
+}
+
+// Returns true if and only if the given atom (specified by escaped and
+// pattern) matches ch.  The result is undefined if the atom is invalid.
+bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
+  if (escaped) {  // "\\p" where p is pattern_char.
+    switch (pattern_char) {
+      case 'd': return IsAsciiDigit(ch);
+      case 'D': return !IsAsciiDigit(ch);
+      case 'f': return ch == '\f';
+      case 'n': return ch == '\n';
+      case 'r': return ch == '\r';
+      case 's': return IsAsciiWhiteSpace(ch);
+      case 'S': return !IsAsciiWhiteSpace(ch);
+      case 't': return ch == '\t';
+      case 'v': return ch == '\v';
+      case 'w': return IsAsciiWordChar(ch);
+      case 'W': return !IsAsciiWordChar(ch);
+    }
+    return IsAsciiPunct(pattern_char) && pattern_char == ch;
+  }
+
+  return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
+}
+
+// Helper function used by ValidateRegex() to format error messages.
+static std::string FormatRegexSyntaxError(const char* regex, int index) {
+  return (Message() << "Syntax error at index " << index
+          << " in simple regular expression \"" << regex << "\": ").GetString();
+}
+
+// Generates non-fatal failures and returns false if regex is invalid;
+// otherwise returns true.
+bool ValidateRegex(const char* regex) {
+  if (regex == nullptr) {
+    ADD_FAILURE() << "NULL is not a valid simple regular expression.";
+    return false;
+  }
+
+  bool is_valid = true;
+
+  // True if and only if ?, *, or + can follow the previous atom.
+  bool prev_repeatable = false;
+  for (int i = 0; regex[i]; i++) {
+    if (regex[i] == '\\') {  // An escape sequence
+      i++;
+      if (regex[i] == '\0') {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+                      << "'\\' cannot appear at the end.";
+        return false;
+      }
+
+      if (!IsValidEscape(regex[i])) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+                      << "invalid escape sequence \"\\" << regex[i] << "\".";
+        is_valid = false;
+      }
+      prev_repeatable = true;
+    } else {  // Not an escape sequence.
+      const char ch = regex[i];
+
+      if (ch == '^' && i > 0) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'^' can only appear at the beginning.";
+        is_valid = false;
+      } else if (ch == '$' && regex[i + 1] != '\0') {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'$' can only appear at the end.";
+        is_valid = false;
+      } else if (IsInSet(ch, "()[]{}|")) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'" << ch << "' is unsupported.";
+        is_valid = false;
+      } else if (IsRepeat(ch) && !prev_repeatable) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'" << ch << "' can only follow a repeatable token.";
+        is_valid = false;
+      }
+
+      prev_repeatable = !IsInSet(ch, "^$?*+");
+    }
+  }
+
+  return is_valid;
+}
+
+// Matches a repeated regex atom followed by a valid simple regular
+// expression.  The regex atom is defined as c if escaped is false,
+// or \c otherwise.  repeat is the repetition meta character (?, *,
+// or +).  The behavior is undefined if str contains too many
+// characters to be indexable by size_t, in which case the test will
+// probably time out anyway.  We are fine with this limitation as
+// std::string has it too.
+bool MatchRepetitionAndRegexAtHead(
+    bool escaped, char c, char repeat, const char* regex,
+    const char* str) {
+  const size_t min_count = (repeat == '+') ? 1 : 0;
+  const size_t max_count = (repeat == '?') ? 1 :
+      static_cast<size_t>(-1) - 1;
+  // We cannot call numeric_limits::max() as it conflicts with the
+  // max() macro on Windows.
+
+  for (size_t i = 0; i <= max_count; ++i) {
+    // We know that the atom matches each of the first i characters in str.
+    if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
+      // We have enough matches at the head, and the tail matches too.
+      // Since we only care about *whether* the pattern matches str
+      // (as opposed to *how* it matches), there is no need to find a
+      // greedy match.
+      return true;
+    }
+    if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
+      return false;
+  }
+  return false;
+}
+
+// Returns true if and only if regex matches a prefix of str. regex must
+// be a valid simple regular expression and not start with "^", or the
+// result is undefined.
+bool MatchRegexAtHead(const char* regex, const char* str) {
+  if (*regex == '\0')  // An empty regex matches a prefix of anything.
+    return true;
+
+  // "$" only matches the end of a string.  Note that regex being
+  // valid guarantees that there's nothing after "$" in it.
+  if (*regex == '$')
+    return *str == '\0';
+
+  // Is the first thing in regex an escape sequence?
+  const bool escaped = *regex == '\\';
+  if (escaped)
+    ++regex;
+  if (IsRepeat(regex[1])) {
+    // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
+    // here's an indirect recursion.  It terminates as the regex gets
+    // shorter in each recursion.
+    return MatchRepetitionAndRegexAtHead(
+        escaped, regex[0], regex[1], regex + 2, str);
+  } else {
+    // regex isn't empty, isn't "$", and doesn't start with a
+    // repetition.  We match the first atom of regex with the first
+    // character of str and recurse.
+    return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
+        MatchRegexAtHead(regex + 1, str + 1);
+  }
+}
+
+// Returns true if and only if regex matches any substring of str.  regex must
+// be a valid simple regular expression, or the result is undefined.
+//
+// The algorithm is recursive, but the recursion depth doesn't exceed
+// the regex length, so we won't need to worry about running out of
+// stack space normally.  In rare cases the time complexity can be
+// exponential with respect to the regex length + the string length,
+// but usually it's must faster (often close to linear).
+bool MatchRegexAnywhere(const char* regex, const char* str) {
+  if (regex == nullptr || str == nullptr) return false;
+
+  if (*regex == '^')
+    return MatchRegexAtHead(regex + 1, str);
+
+  // A successful match can be anywhere in str.
+  do {
+    if (MatchRegexAtHead(regex, str))
+      return true;
+  } while (*str++ != '\0');
+  return false;
+}
+
+// Implements the RE class.
+
+RE::~RE() {
+  free(const_cast<char*>(pattern_));
+  free(const_cast<char*>(full_pattern_));
+}
+
+// Returns true if and only if regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+  return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
+}
+
+// Returns true if and only if regular expression re matches a substring of
+// str (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+  return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+  pattern_ = full_pattern_ = nullptr;
+  if (regex != nullptr) {
+    pattern_ = posix::StrDup(regex);
+  }
+
+  is_valid_ = ValidateRegex(regex);
+  if (!is_valid_) {
+    // No need to calculate the full pattern when the regex is invalid.
+    return;
+  }
+
+  const size_t len = strlen(regex);
+  // Reserves enough bytes to hold the regular expression used for a
+  // full match: we need space to prepend a '^', append a '$', and
+  // terminate the string with '\0'.
+  char* buffer = static_cast<char*>(malloc(len + 3));
+  full_pattern_ = buffer;
+
+  if (*regex != '^')
+    *buffer++ = '^';  // Makes sure full_pattern_ starts with '^'.
+
+  // We don't use snprintf or strncpy, as they trigger a warning when
+  // compiled with VC++ 8.0.
+  memcpy(buffer, regex, len);
+  buffer += len;
+
+  if (len == 0 || regex[len - 1] != '$')
+    *buffer++ = '$';  // Makes sure full_pattern_ ends with '$'.
+
+  *buffer = '\0';
+}
+
+#endif  // GTEST_USES_POSIX_RE
+
+const char kUnknownFile[] = "unknown file";
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
+  const std::string file_name(file == nullptr ? kUnknownFile : file);
+
+  if (line < 0) {
+    return file_name + ":";
+  }
+#ifdef _MSC_VER
+  return file_name + "(" + StreamableToString(line) + "):";
+#else
+  return file_name + ":" + StreamableToString(line) + ":";
+#endif  // _MSC_VER
+}
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+// Note that FormatCompilerIndependentFileLocation() does NOT append colon
+// to the file location it produces, unlike FormatFileLocation().
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
+    const char* file, int line) {
+  const std::string file_name(file == nullptr ? kUnknownFile : file);
+
+  if (line < 0)
+    return file_name;
+  else
+    return file_name + ":" + StreamableToString(line);
+}
+
+GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
+    : severity_(severity) {
+  const char* const marker =
+      severity == GTEST_INFO ?    "[  INFO ]" :
+      severity == GTEST_WARNING ? "[WARNING]" :
+      severity == GTEST_ERROR ?   "[ ERROR ]" : "[ FATAL ]";
+  GetStream() << ::std::endl << marker << " "
+              << FormatFileLocation(file, line).c_str() << ": ";
+}
+
+// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+GTestLog::~GTestLog() {
+  GetStream() << ::std::endl;
+  if (severity_ == GTEST_FATAL) {
+    fflush(stderr);
+    posix::Abort();
+  }
+}
+
+// Disable Microsoft deprecation warnings for POSIX functions called from
+// this class (creat, dup, dup2, and close)
+GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Object that captures an output stream (stdout/stderr).
+class CapturedStream {
+ public:
+  // The ctor redirects the stream to a temporary file.
+  explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
+# if GTEST_OS_WINDOWS
+    char temp_dir_path[MAX_PATH + 1] = { '\0' };  // NOLINT
+    char temp_file_path[MAX_PATH + 1] = { '\0' };  // NOLINT
+
+    ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
+    const UINT success = ::GetTempFileNameA(temp_dir_path,
+                                            "gtest_redir",
+                                            0,  // Generate unique file name.
+                                            temp_file_path);
+    GTEST_CHECK_(success != 0)
+        << "Unable to create a temporary file in " << temp_dir_path;
+    const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
+    GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
+                                    << temp_file_path;
+    filename_ = temp_file_path;
+# else
+    // There's no guarantee that a test has write access to the current
+    // directory, so we create the temporary file in a temporary directory.
+    std::string name_template;
+
+#  if GTEST_OS_LINUX_ANDROID
+    // Note: Android applications are expected to call the framework's
+    // Context.getExternalStorageDirectory() method through JNI to get
+    // the location of the world-writable SD Card directory. However,
+    // this requires a Context handle, which cannot be retrieved
+    // globally from native code. Doing so also precludes running the
+    // code as part of a regular standalone executable, which doesn't
+    // run in a Dalvik process (e.g. when running it through 'adb shell').
+    //
+    // The location /data/local/tmp is directly accessible from native code.
+    // '/sdcard' and other variants cannot be relied on, as they are not
+    // guaranteed to be mounted, or may have a delay in mounting.
+    name_template = "/data/local/tmp/";
+#  elif GTEST_OS_IOS
+    char user_temp_dir[PATH_MAX + 1];
+
+    // Documented alternative to NSTemporaryDirectory() (for obtaining creating
+    // a temporary directory) at
+    // https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/RaceConditions.html#//apple_ref/doc/uid/TP40002585-SW10
+    //
+    // _CS_DARWIN_USER_TEMP_DIR (as well as _CS_DARWIN_USER_CACHE_DIR) is not
+    // documented in the confstr() man page at
+    // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/confstr.3.html#//apple_ref/doc/man/3/confstr
+    // but are still available, according to the WebKit patches at
+    // https://trac.webkit.org/changeset/262004/webkit
+    // https://trac.webkit.org/changeset/263705/webkit
+    //
+    // The confstr() implementation falls back to getenv("TMPDIR"). See
+    // https://opensource.apple.com/source/Libc/Libc-1439.100.3/gen/confstr.c.auto.html
+    ::confstr(_CS_DARWIN_USER_TEMP_DIR, user_temp_dir, sizeof(user_temp_dir));
+
+    name_template = user_temp_dir;
+    if (name_template.back() != GTEST_PATH_SEP_[0])
+      name_template.push_back(GTEST_PATH_SEP_[0]);
+#  else
+    name_template = "/tmp/";
+#  endif
+    name_template.append("gtest_captured_stream.XXXXXX");
+
+    // mkstemp() modifies the string bytes in place, and does not go beyond the
+    // string's length. This results in well-defined behavior in C++17.
+    //
+    // The const_cast is needed below C++17. The constraints on std::string
+    // implementations in C++11 and above make assumption behind the const_cast
+    // fairly safe.
+    const int captured_fd = ::mkstemp(const_cast<char*>(name_template.data()));
+    if (captured_fd == -1) {
+      GTEST_LOG_(WARNING)
+          << "Failed to create tmp file " << name_template
+          << " for test; does the test have access to the /tmp directory?";
+    }
+    filename_ = std::move(name_template);
+# endif  // GTEST_OS_WINDOWS
+    fflush(nullptr);
+    dup2(captured_fd, fd_);
+    close(captured_fd);
+  }
+
+  ~CapturedStream() {
+    remove(filename_.c_str());
+  }
+
+  std::string GetCapturedString() {
+    if (uncaptured_fd_ != -1) {
+      // Restores the original stream.
+      fflush(nullptr);
+      dup2(uncaptured_fd_, fd_);
+      close(uncaptured_fd_);
+      uncaptured_fd_ = -1;
+    }
+
+    FILE* const file = posix::FOpen(filename_.c_str(), "r");
+    if (file == nullptr) {
+      GTEST_LOG_(FATAL) << "Failed to open tmp file " << filename_
+                        << " for capturing stream.";
+    }
+    const std::string content = ReadEntireFile(file);
+    posix::FClose(file);
+    return content;
+  }
+
+ private:
+  const int fd_;  // A stream to capture.
+  int uncaptured_fd_;
+  // Name of the temporary file holding the stderr output.
+  ::std::string filename_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
+};
+
+GTEST_DISABLE_MSC_DEPRECATED_POP_()
+
+static CapturedStream* g_captured_stderr = nullptr;
+static CapturedStream* g_captured_stdout = nullptr;
+
+// Starts capturing an output stream (stdout/stderr).
+static void CaptureStream(int fd, const char* stream_name,
+                          CapturedStream** stream) {
+  if (*stream != nullptr) {
+    GTEST_LOG_(FATAL) << "Only one " << stream_name
+                      << " capturer can exist at a time.";
+  }
+  *stream = new CapturedStream(fd);
+}
+
+// Stops capturing the output stream and returns the captured string.
+static std::string GetCapturedStream(CapturedStream** captured_stream) {
+  const std::string content = (*captured_stream)->GetCapturedString();
+
+  delete *captured_stream;
+  *captured_stream = nullptr;
+
+  return content;
+}
+
+// Starts capturing stdout.
+void CaptureStdout() {
+  CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
+}
+
+// Starts capturing stderr.
+void CaptureStderr() {
+  CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
+}
+
+// Stops capturing stdout and returns the captured string.
+std::string GetCapturedStdout() {
+  return GetCapturedStream(&g_captured_stdout);
+}
+
+// Stops capturing stderr and returns the captured string.
+std::string GetCapturedStderr() {
+  return GetCapturedStream(&g_captured_stderr);
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+
+
+
+
+size_t GetFileSize(FILE* file) {
+  fseek(file, 0, SEEK_END);
+  return static_cast<size_t>(ftell(file));
+}
+
+std::string ReadEntireFile(FILE* file) {
+  const size_t file_size = GetFileSize(file);
+  char* const buffer = new char[file_size];
+
+  size_t bytes_last_read = 0;  // # of bytes read in the last fread()
+  size_t bytes_read = 0;       // # of bytes read so far
+
+  fseek(file, 0, SEEK_SET);
+
+  // Keeps reading the file until we cannot read further or the
+  // pre-determined file size is reached.
+  do {
+    bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
+    bytes_read += bytes_last_read;
+  } while (bytes_last_read > 0 && bytes_read < file_size);
+
+  const std::string content(buffer, bytes_read);
+  delete[] buffer;
+
+  return content;
+}
+
+#if GTEST_HAS_DEATH_TEST
+static const std::vector<std::string>* g_injected_test_argvs =
+    nullptr;  // Owned.
+
+std::vector<std::string> GetInjectableArgvs() {
+  if (g_injected_test_argvs != nullptr) {
+    return *g_injected_test_argvs;
+  }
+  return GetArgvs();
+}
+
+void SetInjectableArgvs(const std::vector<std::string>* new_argvs) {
+  if (g_injected_test_argvs != new_argvs) delete g_injected_test_argvs;
+  g_injected_test_argvs = new_argvs;
+}
+
+void SetInjectableArgvs(const std::vector<std::string>& new_argvs) {
+  SetInjectableArgvs(
+      new std::vector<std::string>(new_argvs.begin(), new_argvs.end()));
+}
+
+void ClearInjectableArgvs() {
+  delete g_injected_test_argvs;
+  g_injected_test_argvs = nullptr;
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+#if GTEST_OS_WINDOWS_MOBILE
+namespace posix {
+void Abort() {
+  DebugBreak();
+  TerminateProcess(GetCurrentProcess(), 1);
+}
+}  // namespace posix
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Returns the name of the environment variable corresponding to the
+// given flag.  For example, FlagToEnvVar("foo") will return
+// "GTEST_FOO" in the open-source version.
+static std::string FlagToEnvVar(const char* flag) {
+  const std::string full_flag =
+      (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
+
+  Message env_var;
+  for (size_t i = 0; i != full_flag.length(); i++) {
+    env_var << ToUpper(full_flag.c_str()[i]);
+  }
+
+  return env_var.GetString();
+}
+
+// Parses 'str' for a 32-bit signed integer.  If successful, writes
+// the result to *value and returns true; otherwise leaves *value
+// unchanged and returns false.
+bool ParseInt32(const Message& src_text, const char* str, int32_t* value) {
+  // Parses the environment variable as a decimal integer.
+  char* end = nullptr;
+  const long long_value = strtol(str, &end, 10);  // NOLINT
+
+  // Has strtol() consumed all characters in the string?
+  if (*end != '\0') {
+    // No - an invalid character was encountered.
+    Message msg;
+    msg << "WARNING: " << src_text
+        << " is expected to be a 32-bit integer, but actually"
+        << " has value \"" << str << "\".\n";
+    printf("%s", msg.GetString().c_str());
+    fflush(stdout);
+    return false;
+  }
+
+  // Is the parsed value in the range of an int32_t?
+  const auto result = static_cast<int32_t>(long_value);
+  if (long_value == LONG_MAX || long_value == LONG_MIN ||
+      // The parsed value overflows as a long.  (strtol() returns
+      // LONG_MAX or LONG_MIN when the input overflows.)
+      result != long_value
+      // The parsed value overflows as an int32_t.
+      ) {
+    Message msg;
+    msg << "WARNING: " << src_text
+        << " is expected to be a 32-bit integer, but actually"
+        << " has value " << str << ", which overflows.\n";
+    printf("%s", msg.GetString().c_str());
+    fflush(stdout);
+    return false;
+  }
+
+  *value = result;
+  return true;
+}
+
+// Reads and returns the Boolean environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+//
+// The value is considered true if and only if it's not "0".
+bool BoolFromGTestEnv(const char* flag, bool default_value) {
+#if defined(GTEST_GET_BOOL_FROM_ENV_)
+  return GTEST_GET_BOOL_FROM_ENV_(flag, default_value);
+#else
+  const std::string env_var = FlagToEnvVar(flag);
+  const char* const string_value = posix::GetEnv(env_var.c_str());
+  return string_value == nullptr ? default_value
+                                 : strcmp(string_value, "0") != 0;
+#endif  // defined(GTEST_GET_BOOL_FROM_ENV_)
+}
+
+// Reads and returns a 32-bit integer stored in the environment
+// variable corresponding to the given flag; if it isn't set or
+// doesn't represent a valid 32-bit integer, returns default_value.
+int32_t Int32FromGTestEnv(const char* flag, int32_t default_value) {
+#if defined(GTEST_GET_INT32_FROM_ENV_)
+  return GTEST_GET_INT32_FROM_ENV_(flag, default_value);
+#else
+  const std::string env_var = FlagToEnvVar(flag);
+  const char* const string_value = posix::GetEnv(env_var.c_str());
+  if (string_value == nullptr) {
+    // The environment variable is not set.
+    return default_value;
+  }
+
+  int32_t result = default_value;
+  if (!ParseInt32(Message() << "Environment variable " << env_var,
+                  string_value, &result)) {
+    printf("The default value %s is used.\n",
+           (Message() << default_value).GetString().c_str());
+    fflush(stdout);
+    return default_value;
+  }
+
+  return result;
+#endif  // defined(GTEST_GET_INT32_FROM_ENV_)
+}
+
+// As a special case for the 'output' flag, if GTEST_OUTPUT is not
+// set, we look for XML_OUTPUT_FILE, which is set by the Bazel build
+// system.  The value of XML_OUTPUT_FILE is a filename without the
+// "xml:" prefix of GTEST_OUTPUT.
+// Note that this is meant to be called at the call site so it does
+// not check that the flag is 'output'
+// In essence this checks an env variable called XML_OUTPUT_FILE
+// and if it is set we prepend "xml:" to its value, if it not set we return ""
+std::string OutputFlagAlsoCheckEnvVar(){
+  std::string default_value_for_output_flag = "";
+  const char* xml_output_file_env = posix::GetEnv("XML_OUTPUT_FILE");
+  if (nullptr != xml_output_file_env) {
+    default_value_for_output_flag = std::string("xml:") + xml_output_file_env;
+  }
+  return default_value_for_output_flag;
+}
+
+// Reads and returns the string environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+const char* StringFromGTestEnv(const char* flag, const char* default_value) {
+#if defined(GTEST_GET_STRING_FROM_ENV_)
+  return GTEST_GET_STRING_FROM_ENV_(flag, default_value);
+#else
+  const std::string env_var = FlagToEnvVar(flag);
+  const char* const value = posix::GetEnv(env_var.c_str());
+  return value == nullptr ? default_value : value;
+#endif  // defined(GTEST_GET_STRING_FROM_ENV_)
+}
+
+}  // namespace internal
+}  // namespace testing
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+// Google Test - The Google C++ Testing and Mocking Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// It uses the << operator when possible, and prints the bytes in the
+// object otherwise.  A user can override its behavior for a class
+// type Foo by defining either operator<<(::std::ostream&, const Foo&)
+// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
+// defines Foo.
+
+
+#include <stdio.h>
+
+#include <cctype>
+#include <cstdint>
+#include <cwchar>
+#include <ostream>  // NOLINT
+#include <string>
+#include <type_traits>
+
+
+namespace testing {
+
+namespace {
+
+using ::std::ostream;
+
+// Prints a segment of bytes in the given object.
+GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
+GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
+GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
+void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
+                                size_t count, ostream* os) {
+  char text[5] = "";
+  for (size_t i = 0; i != count; i++) {
+    const size_t j = start + i;
+    if (i != 0) {
+      // Organizes the bytes into groups of 2 for easy parsing by
+      // human.
+      if ((j % 2) == 0)
+        *os << ' ';
+      else
+        *os << '-';
+    }
+    GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]);
+    *os << text;
+  }
+}
+
+// Prints the bytes in the given value to the given ostream.
+void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
+                              ostream* os) {
+  // Tells the user how big the object is.
+  *os << count << "-byte object <";
+
+  const size_t kThreshold = 132;
+  const size_t kChunkSize = 64;
+  // If the object size is bigger than kThreshold, we'll have to omit
+  // some details by printing only the first and the last kChunkSize
+  // bytes.
+  if (count < kThreshold) {
+    PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
+  } else {
+    PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
+    *os << " ... ";
+    // Rounds up to 2-byte boundary.
+    const size_t resume_pos = (count - kChunkSize + 1)/2*2;
+    PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
+  }
+  *os << ">";
+}
+
+// Helpers for widening a character to char32_t. Since the standard does not
+// specify if char / wchar_t is signed or unsigned, it is important to first
+// convert it to the unsigned type of the same width before widening it to
+// char32_t.
+template <typename CharType>
+char32_t ToChar32(CharType in) {
+  return static_cast<char32_t>(
+      static_cast<typename std::make_unsigned<CharType>::type>(in));
+}
+
+}  // namespace
+
+namespace internal {
+
+// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
+// given object.  The delegation simplifies the implementation, which
+// uses the << operator and thus is easier done outside of the
+// ::testing::internal namespace, which contains a << operator that
+// sometimes conflicts with the one in STL.
+void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
+                          ostream* os) {
+  PrintBytesInObjectToImpl(obj_bytes, count, os);
+}
+
+// Depending on the value of a char (or wchar_t), we print it in one
+// of three formats:
+//   - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
+//   - as a hexadecimal escape sequence (e.g. '\x7F'), or
+//   - as a special escape sequence (e.g. '\r', '\n').
+enum CharFormat {
+  kAsIs,
+  kHexEscape,
+  kSpecialEscape
+};
+
+// Returns true if c is a printable ASCII character.  We test the
+// value of c directly instead of calling isprint(), which is buggy on
+// Windows Mobile.
+inline bool IsPrintableAscii(char32_t c) { return 0x20 <= c && c <= 0x7E; }
+
+// Prints c (of type char, char8_t, char16_t, char32_t, or wchar_t) as a
+// character literal without the quotes, escaping it when necessary; returns how
+// c was formatted.
+template <typename Char>
+static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
+  const char32_t u_c = ToChar32(c);
+  switch (u_c) {
+    case L'\0':
+      *os << "\\0";
+      break;
+    case L'\'':
+      *os << "\\'";
+      break;
+    case L'\\':
+      *os << "\\\\";
+      break;
+    case L'\a':
+      *os << "\\a";
+      break;
+    case L'\b':
+      *os << "\\b";
+      break;
+    case L'\f':
+      *os << "\\f";
+      break;
+    case L'\n':
+      *os << "\\n";
+      break;
+    case L'\r':
+      *os << "\\r";
+      break;
+    case L'\t':
+      *os << "\\t";
+      break;
+    case L'\v':
+      *os << "\\v";
+      break;
+    default:
+      if (IsPrintableAscii(u_c)) {
+        *os << static_cast<char>(c);
+        return kAsIs;
+      } else {
+        ostream::fmtflags flags = os->flags();
+        *os << "\\x" << std::hex << std::uppercase << static_cast<int>(u_c);
+        os->flags(flags);
+        return kHexEscape;
+      }
+  }
+  return kSpecialEscape;
+}
+
+// Prints a char32_t c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsStringLiteralTo(char32_t c, ostream* os) {
+  switch (c) {
+    case L'\'':
+      *os << "'";
+      return kAsIs;
+    case L'"':
+      *os << "\\\"";
+      return kSpecialEscape;
+    default:
+      return PrintAsCharLiteralTo(c, os);
+  }
+}
+
+static const char* GetCharWidthPrefix(char) {
+  return "";
+}
+
+static const char* GetCharWidthPrefix(signed char) {
+  return "";
+}
+
+static const char* GetCharWidthPrefix(unsigned char) {
+  return "";
+}
+
+#ifdef __cpp_char8_t
+static const char* GetCharWidthPrefix(char8_t) {
+  return "u8";
+}
+#endif
+
+static const char* GetCharWidthPrefix(char16_t) {
+  return "u";
+}
+
+static const char* GetCharWidthPrefix(char32_t) {
+  return "U";
+}
+
+static const char* GetCharWidthPrefix(wchar_t) {
+  return "L";
+}
+
+// Prints a char c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
+  return PrintAsStringLiteralTo(ToChar32(c), os);
+}
+
+#ifdef __cpp_char8_t
+static CharFormat PrintAsStringLiteralTo(char8_t c, ostream* os) {
+  return PrintAsStringLiteralTo(ToChar32(c), os);
+}
+#endif
+
+static CharFormat PrintAsStringLiteralTo(char16_t c, ostream* os) {
+  return PrintAsStringLiteralTo(ToChar32(c), os);
+}
+
+static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
+  return PrintAsStringLiteralTo(ToChar32(c), os);
+}
+
+// Prints a character c (of type char, char8_t, char16_t, char32_t, or wchar_t)
+// and its code. '\0' is printed as "'\\0'", other unprintable characters are
+// also properly escaped using the standard C++ escape sequence.
+template <typename Char>
+void PrintCharAndCodeTo(Char c, ostream* os) {
+  // First, print c as a literal in the most readable form we can find.
+  *os << GetCharWidthPrefix(c) << "'";
+  const CharFormat format = PrintAsCharLiteralTo(c, os);
+  *os << "'";
+
+  // To aid user debugging, we also print c's code in decimal, unless
+  // it's 0 (in which case c was printed as '\\0', making the code
+  // obvious).
+  if (c == 0)
+    return;
+  *os << " (" << static_cast<int>(c);
+
+  // For more convenience, we print c's code again in hexadecimal,
+  // unless c was already printed in the form '\x##' or the code is in
+  // [1, 9].
+  if (format == kHexEscape || (1 <= c && c <= 9)) {
+    // Do nothing.
+  } else {
+    *os << ", 0x" << String::FormatHexInt(static_cast<int>(c));
+  }
+  *os << ")";
+}
+
+void PrintTo(unsigned char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); }
+void PrintTo(signed char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); }
+
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its code.  L'\0' is printed as "L'\\0'".
+void PrintTo(wchar_t wc, ostream* os) { PrintCharAndCodeTo(wc, os); }
+
+// TODO(dcheng): Consider making this delegate to PrintCharAndCodeTo() as well.
+void PrintTo(char32_t c, ::std::ostream* os) {
+  *os << std::hex << "U+" << std::uppercase << std::setfill('0') << std::setw(4)
+      << static_cast<uint32_t>(c);
+}
+
+// Prints the given array of characters to the ostream.  CharType must be either
+// char, char8_t, char16_t, char32_t, or wchar_t.
+// The array starts at begin, the length is len, it may include '\0' characters
+// and may not be NUL-terminated.
+template <typename CharType>
+GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
+GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
+GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
+static CharFormat PrintCharsAsStringTo(
+    const CharType* begin, size_t len, ostream* os) {
+  const char* const quote_prefix = GetCharWidthPrefix(*begin);
+  *os << quote_prefix << "\"";
+  bool is_previous_hex = false;
+  CharFormat print_format = kAsIs;
+  for (size_t index = 0; index < len; ++index) {
+    const CharType cur = begin[index];
+    if (is_previous_hex && IsXDigit(cur)) {
+      // Previous character is of '\x..' form and this character can be
+      // interpreted as another hexadecimal digit in its number. Break string to
+      // disambiguate.
+      *os << "\" " << quote_prefix << "\"";
+    }
+    is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
+    // Remember if any characters required hex escaping.
+    if (is_previous_hex) {
+      print_format = kHexEscape;
+    }
+  }
+  *os << "\"";
+  return print_format;
+}
+
+// Prints a (const) char/wchar_t array of 'len' elements, starting at address
+// 'begin'.  CharType must be either char or wchar_t.
+template <typename CharType>
+GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
+GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
+GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
+static void UniversalPrintCharArray(
+    const CharType* begin, size_t len, ostream* os) {
+  // The code
+  //   const char kFoo[] = "foo";
+  // generates an array of 4, not 3, elements, with the last one being '\0'.
+  //
+  // Therefore when printing a char array, we don't print the last element if
+  // it's '\0', such that the output matches the string literal as it's
+  // written in the source code.
+  if (len > 0 && begin[len - 1] == '\0') {
+    PrintCharsAsStringTo(begin, len - 1, os);
+    return;
+  }
+
+  // If, however, the last element in the array is not '\0', e.g.
+  //    const char kFoo[] = { 'f', 'o', 'o' };
+  // we must print the entire array.  We also print a message to indicate
+  // that the array is not NUL-terminated.
+  PrintCharsAsStringTo(begin, len, os);
+  *os << " (no terminating NUL)";
+}
+
+// Prints a (const) char array of 'len' elements, starting at address 'begin'.
+void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
+  UniversalPrintCharArray(begin, len, os);
+}
+
+#ifdef __cpp_char8_t
+// Prints a (const) char8_t array of 'len' elements, starting at address
+// 'begin'.
+void UniversalPrintArray(const char8_t* begin, size_t len, ostream* os) {
+  UniversalPrintCharArray(begin, len, os);
+}
+#endif
+
+// Prints a (const) char16_t array of 'len' elements, starting at address
+// 'begin'.
+void UniversalPrintArray(const char16_t* begin, size_t len, ostream* os) {
+  UniversalPrintCharArray(begin, len, os);
+}
+
+// Prints a (const) char32_t array of 'len' elements, starting at address
+// 'begin'.
+void UniversalPrintArray(const char32_t* begin, size_t len, ostream* os) {
+  UniversalPrintCharArray(begin, len, os);
+}
+
+// Prints a (const) wchar_t array of 'len' elements, starting at address
+// 'begin'.
+void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
+  UniversalPrintCharArray(begin, len, os);
+}
+
+namespace {
+
+// Prints a null-terminated C-style string to the ostream.
+template <typename Char>
+void PrintCStringTo(const Char* s, ostream* os) {
+  if (s == nullptr) {
+    *os << "NULL";
+  } else {
+    *os << ImplicitCast_<const void*>(s) << " pointing to ";
+    PrintCharsAsStringTo(s, std::char_traits<Char>::length(s), os);
+  }
+}
+
+}  // anonymous namespace
+
+void PrintTo(const char* s, ostream* os) { PrintCStringTo(s, os); }
+
+#ifdef __cpp_char8_t
+void PrintTo(const char8_t* s, ostream* os) { PrintCStringTo(s, os); }
+#endif
+
+void PrintTo(const char16_t* s, ostream* os) { PrintCStringTo(s, os); }
+
+void PrintTo(const char32_t* s, ostream* os) { PrintCStringTo(s, os); }
+
+// MSVC compiler can be configured to define whar_t as a typedef
+// of unsigned short. Defining an overload for const wchar_t* in that case
+// would cause pointers to unsigned shorts be printed as wide strings,
+// possibly accessing more memory than intended and causing invalid
+// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
+// wchar_t is implemented as a native type.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Prints the given wide C string to the ostream.
+void PrintTo(const wchar_t* s, ostream* os) { PrintCStringTo(s, os); }
+#endif  // wchar_t is native
+
+namespace {
+
+bool ContainsUnprintableControlCodes(const char* str, size_t length) {
+  const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
+
+  for (size_t i = 0; i < length; i++) {
+    unsigned char ch = *s++;
+    if (std::iscntrl(ch)) {
+        switch (ch) {
+        case '\t':
+        case '\n':
+        case '\r':
+          break;
+        default:
+          return true;
+        }
+      }
+  }
+  return false;
+}
+
+bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t<= 0xbf; }
+
+bool IsValidUTF8(const char* str, size_t length) {
+  const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
+
+  for (size_t i = 0; i < length;) {
+    unsigned char lead = s[i++];
+
+    if (lead <= 0x7f) {
+      continue;  // single-byte character (ASCII) 0..7F
+    }
+    if (lead < 0xc2) {
+      return false;  // trail byte or non-shortest form
+    } else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) {
+      ++i;  // 2-byte character
+    } else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length &&
+               IsUTF8TrailByte(s[i]) &&
+               IsUTF8TrailByte(s[i + 1]) &&
+               // check for non-shortest form and surrogate
+               (lead != 0xe0 || s[i] >= 0xa0) &&
+               (lead != 0xed || s[i] < 0xa0)) {
+      i += 2;  // 3-byte character
+    } else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length &&
+               IsUTF8TrailByte(s[i]) &&
+               IsUTF8TrailByte(s[i + 1]) &&
+               IsUTF8TrailByte(s[i + 2]) &&
+               // check for non-shortest form
+               (lead != 0xf0 || s[i] >= 0x90) &&
+               (lead != 0xf4 || s[i] < 0x90)) {
+      i += 3;  // 4-byte character
+    } else {
+      return false;
+    }
+  }
+  return true;
+}
+
+void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
+  if (!ContainsUnprintableControlCodes(str, length) &&
+      IsValidUTF8(str, length)) {
+    *os << "\n    As Text: \"" << str << "\"";
+  }
+}
+
+}  // anonymous namespace
+
+void PrintStringTo(const ::std::string& s, ostream* os) {
+  if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
+    if (GTEST_FLAG(print_utf8)) {
+      ConditionalPrintAsText(s.data(), s.size(), os);
+    }
+  }
+}
+
+#ifdef __cpp_char8_t
+void PrintU8StringTo(const ::std::u8string& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif
+
+void PrintU16StringTo(const ::std::u16string& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+
+void PrintU32StringTo(const ::std::u32string& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+
+#if GTEST_HAS_STD_WSTRING
+void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+}  // namespace internal
+
+}  // namespace testing
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// The Google C++ Testing and Mocking Framework (Google Test)
+
+
+
+namespace testing {
+
+using internal::GetUnitTestImpl;
+
+// Gets the summary of the failure message by omitting the stack trace
+// in it.
+std::string TestPartResult::ExtractSummary(const char* message) {
+  const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
+  return stack_trace == nullptr ? message : std::string(message, stack_trace);
+}
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
+  return os << internal::FormatFileLocation(result.file_name(),
+                                            result.line_number())
+            << " "
+            << (result.type() == TestPartResult::kSuccess
+                    ? "Success"
+                    : result.type() == TestPartResult::kSkip
+                          ? "Skipped"
+                          : result.type() == TestPartResult::kFatalFailure
+                                ? "Fatal failure"
+                                : "Non-fatal failure")
+            << ":\n"
+            << result.message() << std::endl;
+}
+
+// Appends a TestPartResult to the array.
+void TestPartResultArray::Append(const TestPartResult& result) {
+  array_.push_back(result);
+}
+
+// Returns the TestPartResult at the given index (0-based).
+const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
+  if (index < 0 || index >= size()) {
+    printf("\nInvalid index (%d) into TestPartResultArray.\n", index);
+    internal::posix::Abort();
+  }
+
+  return array_[static_cast<size_t>(index)];
+}
+
+// Returns the number of TestPartResult objects in the array.
+int TestPartResultArray::size() const {
+  return static_cast<int>(array_.size());
+}
+
+namespace internal {
+
+HasNewFatalFailureHelper::HasNewFatalFailureHelper()
+    : has_new_fatal_failure_(false),
+      original_reporter_(GetUnitTestImpl()->
+                         GetTestPartResultReporterForCurrentThread()) {
+  GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
+}
+
+HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
+  GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
+      original_reporter_);
+}
+
+void HasNewFatalFailureHelper::ReportTestPartResult(
+    const TestPartResult& result) {
+  if (result.fatally_failed())
+    has_new_fatal_failure_ = true;
+  original_reporter_->ReportTestPartResult(result);
+}
+
+}  // namespace internal
+
+}  // namespace testing
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+
+namespace testing {
+namespace internal {
+
+// Skips to the first non-space char in str. Returns an empty string if str
+// contains only whitespace characters.
+static const char* SkipSpaces(const char* str) {
+  while (IsSpace(*str))
+    str++;
+  return str;
+}
+
+static std::vector<std::string> SplitIntoTestNames(const char* src) {
+  std::vector<std::string> name_vec;
+  src = SkipSpaces(src);
+  for (; src != nullptr; src = SkipComma(src)) {
+    name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src)));
+  }
+  return name_vec;
+}
+
+// Verifies that registered_tests match the test names in
+// registered_tests_; returns registered_tests if successful, or
+// aborts the program otherwise.
+const char* TypedTestSuitePState::VerifyRegisteredTestNames(
+    const char* test_suite_name, const char* file, int line,
+    const char* registered_tests) {
+  RegisterTypeParameterizedTestSuite(test_suite_name, CodeLocation(file, line));
+
+  typedef RegisteredTestsMap::const_iterator RegisteredTestIter;
+  registered_ = true;
+
+  std::vector<std::string> name_vec = SplitIntoTestNames(registered_tests);
+
+  Message errors;
+
+  std::set<std::string> tests;
+  for (std::vector<std::string>::const_iterator name_it = name_vec.begin();
+       name_it != name_vec.end(); ++name_it) {
+    const std::string& name = *name_it;
+    if (tests.count(name) != 0) {
+      errors << "Test " << name << " is listed more than once.\n";
+      continue;
+    }
+
+    if (registered_tests_.count(name) != 0) {
+      tests.insert(name);
+    } else {
+      errors << "No test named " << name
+             << " can be found in this test suite.\n";
+    }
+  }
+
+  for (RegisteredTestIter it = registered_tests_.begin();
+       it != registered_tests_.end();
+       ++it) {
+    if (tests.count(it->first) == 0) {
+      errors << "You forgot to list test " << it->first << ".\n";
+    }
+  }
+
+  const std::string& errors_str = errors.GetString();
+  if (errors_str != "") {
+    fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+            errors_str.c_str());
+    fflush(stderr);
+    posix::Abort();
+  }
+
+  return registered_tests;
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/src/tools/distrib/gtest/gtest.h b/src/tools/distrib/gtest/gtest.h
new file mode 100644
index 0000000..cca4267
--- /dev/null
+++ b/src/tools/distrib/gtest/gtest.h
@@ -0,0 +1,12380 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This header file defines the public API for Google Test.  It should be
+// included by any test program that uses Google Test.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
+// program!
+//
+// Acknowledgment: Google Test borrowed the idea of automatic test
+// registration from Barthelemy Dagenais' (barthelemy@prologique.com)
+// easyUnit framework.
+
+// GOOGLETEST_CM0001 DO NOT DELETE
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_H_
+
+#include <cstddef>
+#include <limits>
+#include <memory>
+#include <ostream>
+#include <type_traits>
+#include <vector>
+
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This header file declares functions and macros used internally by
+// Google Test.  They are subject to change without notice.
+
+// GOOGLETEST_CM0001 DO NOT DELETE
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Low-level types and utilities for porting Google Test to various
+// platforms.  All macros ending with _ and symbols defined in an
+// internal namespace are subject to change without notice.  Code
+// outside Google Test MUST NOT USE THEM DIRECTLY.  Macros that don't
+// end with _ are part of Google Test's public API and can be used by
+// code outside Google Test.
+//
+// This file is fundamental to Google Test.  All other Google Test source
+// files are expected to #include this.  Therefore, it cannot #include
+// any other Google Test header.
+
+// GOOGLETEST_CM0001 DO NOT DELETE
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+
+// Environment-describing macros
+// -----------------------------
+//
+// Google Test can be used in many different environments.  Macros in
+// this section tell Google Test what kind of environment it is being
+// used in, such that Google Test can provide environment-specific
+// features and implementations.
+//
+// Google Test tries to automatically detect the properties of its
+// environment, so users usually don't need to worry about these
+// macros.  However, the automatic detection is not perfect.
+// Sometimes it's necessary for a user to define some of the following
+// macros in the build script to override Google Test's decisions.
+//
+// If the user doesn't define a macro in the list, Google Test will
+// provide a default definition.  After this header is #included, all
+// macros in this list will be defined to either 1 or 0.
+//
+// Notes to maintainers:
+//   - Each macro here is a user-tweakable knob; do not grow the list
+//     lightly.
+//   - Use #if to key off these macros.  Don't use #ifdef or "#if
+//     defined(...)", which will not work as these macros are ALWAYS
+//     defined.
+//
+//   GTEST_HAS_CLONE          - Define it to 1/0 to indicate that clone(2)
+//                              is/isn't available.
+//   GTEST_HAS_EXCEPTIONS     - Define it to 1/0 to indicate that exceptions
+//                              are enabled.
+//   GTEST_HAS_POSIX_RE       - Define it to 1/0 to indicate that POSIX regular
+//                              expressions are/aren't available.
+//   GTEST_HAS_PTHREAD        - Define it to 1/0 to indicate that <pthread.h>
+//                              is/isn't available.
+//   GTEST_HAS_RTTI           - Define it to 1/0 to indicate that RTTI is/isn't
+//                              enabled.
+//   GTEST_HAS_STD_WSTRING    - Define it to 1/0 to indicate that
+//                              std::wstring does/doesn't work (Google Test can
+//                              be used where std::wstring is unavailable).
+//   GTEST_HAS_SEH            - Define it to 1/0 to indicate whether the
+//                              compiler supports Microsoft's "Structured
+//                              Exception Handling".
+//   GTEST_HAS_STREAM_REDIRECTION
+//                            - Define it to 1/0 to indicate whether the
+//                              platform supports I/O stream redirection using
+//                              dup() and dup2().
+//   GTEST_LINKED_AS_SHARED_LIBRARY
+//                            - Define to 1 when compiling tests that use
+//                              Google Test as a shared library (known as
+//                              DLL on Windows).
+//   GTEST_CREATE_SHARED_LIBRARY
+//                            - Define to 1 when compiling Google Test itself
+//                              as a shared library.
+//   GTEST_DEFAULT_DEATH_TEST_STYLE
+//                            - The default value of --gtest_death_test_style.
+//                              The legacy default has been "fast" in the open
+//                              source version since 2008. The recommended value
+//                              is "threadsafe", and can be set in
+//                              custom/gtest-port.h.
+
+// Platform-indicating macros
+// --------------------------
+//
+// Macros indicating the platform on which Google Test is being used
+// (a macro is defined to 1 if compiled on the given platform;
+// otherwise UNDEFINED -- it's never defined to 0.).  Google Test
+// defines these macros automatically.  Code outside Google Test MUST
+// NOT define them.
+//
+//   GTEST_OS_AIX      - IBM AIX
+//   GTEST_OS_CYGWIN   - Cygwin
+//   GTEST_OS_DRAGONFLY - DragonFlyBSD
+//   GTEST_OS_FREEBSD  - FreeBSD
+//   GTEST_OS_FUCHSIA  - Fuchsia
+//   GTEST_OS_GNU_HURD - GNU/Hurd
+//   GTEST_OS_GNU_KFREEBSD - GNU/kFreeBSD
+//   GTEST_OS_HAIKU    - Haiku
+//   GTEST_OS_HPUX     - HP-UX
+//   GTEST_OS_LINUX    - Linux
+//     GTEST_OS_LINUX_ANDROID - Google Android
+//   GTEST_OS_MAC      - Mac OS X
+//     GTEST_OS_IOS    - iOS
+//   GTEST_OS_NACL     - Google Native Client (NaCl)
+//   GTEST_OS_NETBSD   - NetBSD
+//   GTEST_OS_OPENBSD  - OpenBSD
+//   GTEST_OS_OS2      - OS/2
+//   GTEST_OS_QNX      - QNX
+//   GTEST_OS_SOLARIS  - Sun Solaris
+//   GTEST_OS_WINDOWS  - Windows (Desktop, MinGW, or Mobile)
+//     GTEST_OS_WINDOWS_DESKTOP  - Windows Desktop
+//     GTEST_OS_WINDOWS_MINGW    - MinGW
+//     GTEST_OS_WINDOWS_MOBILE   - Windows Mobile
+//     GTEST_OS_WINDOWS_PHONE    - Windows Phone
+//     GTEST_OS_WINDOWS_RT       - Windows Store App/WinRT
+//   GTEST_OS_ZOS      - z/OS
+//
+// Among the platforms, Cygwin, Linux, Mac OS X, and Windows have the
+// most stable support.  Since core members of the Google Test project
+// don't have access to other platforms, support for them may be less
+// stable.  If you notice any problems on your platform, please notify
+// googletestframework@googlegroups.com (patches for fixing them are
+// even more welcome!).
+//
+// It is possible that none of the GTEST_OS_* macros are defined.
+
+// Feature-indicating macros
+// -------------------------
+//
+// Macros indicating which Google Test features are available (a macro
+// is defined to 1 if the corresponding feature is supported;
+// otherwise UNDEFINED -- it's never defined to 0.).  Google Test
+// defines these macros automatically.  Code outside Google Test MUST
+// NOT define them.
+//
+// These macros are public so that portable tests can be written.
+// Such tests typically surround code using a feature with an #if
+// which controls that code.  For example:
+//
+// #if GTEST_HAS_DEATH_TEST
+//   EXPECT_DEATH(DoSomethingDeadly());
+// #endif
+//
+//   GTEST_HAS_DEATH_TEST   - death tests
+//   GTEST_HAS_TYPED_TEST   - typed tests
+//   GTEST_HAS_TYPED_TEST_P - type-parameterized tests
+//   GTEST_IS_THREADSAFE    - Google Test is thread-safe.
+//   GOOGLETEST_CM0007 DO NOT DELETE
+//   GTEST_USES_POSIX_RE    - enhanced POSIX regex is used. Do not confuse with
+//                            GTEST_HAS_POSIX_RE (see above) which users can
+//                            define themselves.
+//   GTEST_USES_SIMPLE_RE   - our own simple regex is used;
+//                            the above RE\b(s) are mutually exclusive.
+
+// Misc public macros
+// ------------------
+//
+//   GTEST_FLAG(flag_name)  - references the variable corresponding to
+//                            the given Google Test flag.
+
+// Internal utilities
+// ------------------
+//
+// The following macros and utilities are for Google Test's INTERNAL
+// use only.  Code outside Google Test MUST NOT USE THEM DIRECTLY.
+//
+// Macros for basic C++ coding:
+//   GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
+//   GTEST_ATTRIBUTE_UNUSED_  - declares that a class' instances or a
+//                              variable don't have to be used.
+//   GTEST_DISALLOW_ASSIGN_   - disables copy operator=.
+//   GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=.
+//   GTEST_DISALLOW_MOVE_ASSIGN_   - disables move operator=.
+//   GTEST_DISALLOW_MOVE_AND_ASSIGN_ - disables move ctor and operator=.
+//   GTEST_MUST_USE_RESULT_   - declares that a function's result must be used.
+//   GTEST_INTENTIONAL_CONST_COND_PUSH_ - start code section where MSVC C4127 is
+//                                        suppressed (constant conditional).
+//   GTEST_INTENTIONAL_CONST_COND_POP_  - finish code section where MSVC C4127
+//                                        is suppressed.
+//   GTEST_INTERNAL_HAS_ANY - for enabling UniversalPrinter<std::any> or
+//                            UniversalPrinter<absl::any> specializations.
+//   GTEST_INTERNAL_HAS_OPTIONAL - for enabling UniversalPrinter<std::optional>
+//   or
+//                                 UniversalPrinter<absl::optional>
+//                                 specializations.
+//   GTEST_INTERNAL_HAS_STRING_VIEW - for enabling Matcher<std::string_view> or
+//                                    Matcher<absl::string_view>
+//                                    specializations.
+//   GTEST_INTERNAL_HAS_VARIANT - for enabling UniversalPrinter<std::variant> or
+//                                UniversalPrinter<absl::variant>
+//                                specializations.
+//
+// Synchronization:
+//   Mutex, MutexLock, ThreadLocal, GetThreadCount()
+//                            - synchronization primitives.
+//
+// Regular expressions:
+//   RE             - a simple regular expression class using the POSIX
+//                    Extended Regular Expression syntax on UNIX-like platforms
+//                    GOOGLETEST_CM0008 DO NOT DELETE
+//                    or a reduced regular exception syntax on other
+//                    platforms, including Windows.
+// Logging:
+//   GTEST_LOG_()   - logs messages at the specified severity level.
+//   LogToStderr()  - directs all log messages to stderr.
+//   FlushInfoLog() - flushes informational log messages.
+//
+// Stdout and stderr capturing:
+//   CaptureStdout()     - starts capturing stdout.
+//   GetCapturedStdout() - stops capturing stdout and returns the captured
+//                         string.
+//   CaptureStderr()     - starts capturing stderr.
+//   GetCapturedStderr() - stops capturing stderr and returns the captured
+//                         string.
+//
+// Integer types:
+//   TypeWithSize   - maps an integer to a int type.
+//   TimeInMillis   - integers of known sizes.
+//   BiggestInt     - the biggest signed integer type.
+//
+// Command-line utilities:
+//   GTEST_DECLARE_*()  - declares a flag.
+//   GTEST_DEFINE_*()   - defines a flag.
+//   GetInjectableArgvs() - returns the command line as a vector of strings.
+//
+// Environment variable utilities:
+//   GetEnv()             - gets the value of an environment variable.
+//   BoolFromGTestEnv()   - parses a bool environment variable.
+//   Int32FromGTestEnv()  - parses an int32_t environment variable.
+//   StringFromGTestEnv() - parses a string environment variable.
+//
+// Deprecation warnings:
+//   GTEST_INTERNAL_DEPRECATED(message) - attribute marking a function as
+//                                        deprecated; calling a marked function
+//                                        should generate a compiler warning
+
+#include <ctype.h>   // for isspace, etc
+#include <stddef.h>  // for ptrdiff_t
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cerrno>
+#include <cstdint>
+#include <limits>
+#include <type_traits>
+
+#ifndef _WIN32_WCE
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif  // !_WIN32_WCE
+
+#if defined __APPLE__
+# include <AvailabilityMacros.h>
+# include <TargetConditionals.h>
+#endif
+
+#include <iostream>  // NOLINT
+#include <locale>
+#include <memory>
+#include <string>  // NOLINT
+#include <tuple>
+#include <vector>  // NOLINT
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Injection point for custom user configurations. See README for details
+//
+// ** Custom implementation starts here **
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This header file defines the GTEST_OS_* macro.
+// It is separate from gtest-port.h so that custom/gtest-port.h can include it.
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
+
+// Determines the platform on which Google Test is compiled.
+#ifdef __CYGWIN__
+# define GTEST_OS_CYGWIN 1
+# elif defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__)
+#  define GTEST_OS_WINDOWS_MINGW 1
+#  define GTEST_OS_WINDOWS 1
+#elif defined _WIN32
+# define GTEST_OS_WINDOWS 1
+# ifdef _WIN32_WCE
+#  define GTEST_OS_WINDOWS_MOBILE 1
+# elif defined(WINAPI_FAMILY)
+#  include <winapifamily.h>
+#  if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+#   define GTEST_OS_WINDOWS_DESKTOP 1
+#  elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
+#   define GTEST_OS_WINDOWS_PHONE 1
+#  elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+#   define GTEST_OS_WINDOWS_RT 1
+#  elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
+#   define GTEST_OS_WINDOWS_PHONE 1
+#   define GTEST_OS_WINDOWS_TV_TITLE 1
+#  else
+    // WINAPI_FAMILY defined but no known partition matched.
+    // Default to desktop.
+#   define GTEST_OS_WINDOWS_DESKTOP 1
+#  endif
+# else
+#  define GTEST_OS_WINDOWS_DESKTOP 1
+# endif  // _WIN32_WCE
+#elif defined __OS2__
+# define GTEST_OS_OS2 1
+#elif defined __APPLE__
+# define GTEST_OS_MAC 1
+# include <TargetConditionals.h>
+# if TARGET_OS_IPHONE
+#  define GTEST_OS_IOS 1
+# endif
+#elif defined __DragonFly__
+# define GTEST_OS_DRAGONFLY 1
+#elif defined __FreeBSD__
+# define GTEST_OS_FREEBSD 1
+#elif defined __Fuchsia__
+# define GTEST_OS_FUCHSIA 1
+#elif defined(__GNU__)
+# define GTEST_OS_GNU_HURD 1
+#elif defined(__GLIBC__) && defined(__FreeBSD_kernel__)
+# define GTEST_OS_GNU_KFREEBSD 1
+#elif defined __linux__
+# define GTEST_OS_LINUX 1
+# if defined __ANDROID__
+#  define GTEST_OS_LINUX_ANDROID 1
+# endif
+#elif defined __MVS__
+# define GTEST_OS_ZOS 1
+#elif defined(__sun) && defined(__SVR4)
+# define GTEST_OS_SOLARIS 1
+#elif defined(_AIX)
+# define GTEST_OS_AIX 1
+#elif defined(__hpux)
+# define GTEST_OS_HPUX 1
+#elif defined __native_client__
+# define GTEST_OS_NACL 1
+#elif defined __NetBSD__
+# define GTEST_OS_NETBSD 1
+#elif defined __OpenBSD__
+# define GTEST_OS_OPENBSD 1
+#elif defined __QNX__
+# define GTEST_OS_QNX 1
+#elif defined(__HAIKU__)
+#define GTEST_OS_HAIKU 1
+#elif defined ESP8266
+#define GTEST_OS_ESP8266 1
+#elif defined ESP32
+#define GTEST_OS_ESP32 1
+#elif defined(__XTENSA__)
+#define GTEST_OS_XTENSA 1
+#endif  // __CYGWIN__
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
+
+#if !defined(GTEST_DEV_EMAIL_)
+# define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com"
+# define GTEST_FLAG_PREFIX_ "gtest_"
+# define GTEST_FLAG_PREFIX_DASH_ "gtest-"
+# define GTEST_FLAG_PREFIX_UPPER_ "GTEST_"
+# define GTEST_NAME_ "Google Test"
+# define GTEST_PROJECT_URL_ "https://github.com/google/googletest/"
+#endif  // !defined(GTEST_DEV_EMAIL_)
+
+#if !defined(GTEST_INIT_GOOGLE_TEST_NAME_)
+# define GTEST_INIT_GOOGLE_TEST_NAME_ "testing::InitGoogleTest"
+#endif  // !defined(GTEST_INIT_GOOGLE_TEST_NAME_)
+
+// Determines the version of gcc that is used to compile this.
+#ifdef __GNUC__
+// 40302 means version 4.3.2.
+# define GTEST_GCC_VER_ \
+    (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
+#endif  // __GNUC__
+
+// Macros for disabling Microsoft Visual C++ warnings.
+//
+//   GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 4385)
+//   /* code that triggers warnings C4800 and C4385 */
+//   GTEST_DISABLE_MSC_WARNINGS_POP_()
+#if defined(_MSC_VER)
+# define GTEST_DISABLE_MSC_WARNINGS_PUSH_(warnings) \
+    __pragma(warning(push))                        \
+    __pragma(warning(disable: warnings))
+# define GTEST_DISABLE_MSC_WARNINGS_POP_()          \
+    __pragma(warning(pop))
+#else
+// Not all compilers are MSVC
+# define GTEST_DISABLE_MSC_WARNINGS_PUSH_(warnings)
+# define GTEST_DISABLE_MSC_WARNINGS_POP_()
+#endif
+
+// Clang on Windows does not understand MSVC's pragma warning.
+// We need clang-specific way to disable function deprecation warning.
+#ifdef __clang__
+# define GTEST_DISABLE_MSC_DEPRECATED_PUSH_()                         \
+    _Pragma("clang diagnostic push")                                  \
+    _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") \
+    _Pragma("clang diagnostic ignored \"-Wdeprecated-implementations\"")
+#define GTEST_DISABLE_MSC_DEPRECATED_POP_() \
+    _Pragma("clang diagnostic pop")
+#else
+# define GTEST_DISABLE_MSC_DEPRECATED_PUSH_() \
+    GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996)
+# define GTEST_DISABLE_MSC_DEPRECATED_POP_() \
+    GTEST_DISABLE_MSC_WARNINGS_POP_()
+#endif
+
+// Brings in definitions for functions used in the testing::internal::posix
+// namespace (read, write, close, chdir, isatty, stat). We do not currently
+// use them on Windows Mobile.
+#if GTEST_OS_WINDOWS
+# if !GTEST_OS_WINDOWS_MOBILE
+#  include <direct.h>
+#  include <io.h>
+# endif
+// In order to avoid having to include <windows.h>, use forward declaration
+#if GTEST_OS_WINDOWS_MINGW && !defined(__MINGW64_VERSION_MAJOR)
+// MinGW defined _CRITICAL_SECTION and _RTL_CRITICAL_SECTION as two
+// separate (equivalent) structs, instead of using typedef
+typedef struct _CRITICAL_SECTION GTEST_CRITICAL_SECTION;
+#else
+// Assume CRITICAL_SECTION is a typedef of _RTL_CRITICAL_SECTION.
+// This assumption is verified by
+// WindowsTypesTest.CRITICAL_SECTIONIs_RTL_CRITICAL_SECTION.
+typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
+#endif
+#elif GTEST_OS_XTENSA
+#include <unistd.h>
+// Xtensa toolchains define strcasecmp in the string.h header instead of
+// strings.h. string.h is already included.
+#else
+// This assumes that non-Windows OSes provide unistd.h. For OSes where this
+// is not the case, we need to include headers that provide the functions
+// mentioned above.
+# include <unistd.h>
+# include <strings.h>
+#endif  // GTEST_OS_WINDOWS
+
+#if GTEST_OS_LINUX_ANDROID
+// Used to define __ANDROID_API__ matching the target NDK API level.
+#  include <android/api-level.h>  // NOLINT
+#endif
+
+// Defines this to true if and only if Google Test can use POSIX regular
+// expressions.
+#ifndef GTEST_HAS_POSIX_RE
+# if GTEST_OS_LINUX_ANDROID
+// On Android, <regex.h> is only available starting with Gingerbread.
+#  define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9)
+# else
+#define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS && !GTEST_OS_XTENSA)
+# endif
+#endif
+
+#if GTEST_USES_PCRE
+// The appropriate headers have already been included.
+
+#elif GTEST_HAS_POSIX_RE
+
+// On some platforms, <regex.h> needs someone to define size_t, and
+// won't compile otherwise.  We can #include it here as we already
+// included <stdlib.h>, which is guaranteed to define size_t through
+// <stddef.h>.
+# include <regex.h>  // NOLINT
+
+# define GTEST_USES_POSIX_RE 1
+
+#elif GTEST_OS_WINDOWS
+
+// <regex.h> is not available on Windows.  Use our own simple regex
+// implementation instead.
+# define GTEST_USES_SIMPLE_RE 1
+
+#else
+
+// <regex.h> may not be available on this platform.  Use our own
+// simple regex implementation instead.
+# define GTEST_USES_SIMPLE_RE 1
+
+#endif  // GTEST_USES_PCRE
+
+#ifndef GTEST_HAS_EXCEPTIONS
+// The user didn't tell us whether exceptions are enabled, so we need
+// to figure it out.
+# if defined(_MSC_VER) && defined(_CPPUNWIND)
+// MSVC defines _CPPUNWIND to 1 if and only if exceptions are enabled.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__BORLANDC__)
+// C++Builder's implementation of the STL uses the _HAS_EXCEPTIONS
+// macro to enable exceptions, so we'll do the same.
+// Assumes that exceptions are enabled by default.
+#  ifndef _HAS_EXCEPTIONS
+#   define _HAS_EXCEPTIONS 1
+#  endif  // _HAS_EXCEPTIONS
+#  define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
+# elif defined(__clang__)
+// clang defines __EXCEPTIONS if and only if exceptions are enabled before clang
+// 220714, but if and only if cleanups are enabled after that. In Obj-C++ files,
+// there can be cleanups for ObjC exceptions which also need cleanups, even if
+// C++ exceptions are disabled. clang has __has_feature(cxx_exceptions) which
+// checks for C++ exceptions starting at clang r206352, but which checked for
+// cleanups prior to that. To reliably check for C++ exception availability with
+// clang, check for
+// __EXCEPTIONS && __has_feature(cxx_exceptions).
+#  define GTEST_HAS_EXCEPTIONS (__EXCEPTIONS && __has_feature(cxx_exceptions))
+# elif defined(__GNUC__) && __EXCEPTIONS
+// gcc defines __EXCEPTIONS to 1 if and only if exceptions are enabled.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__SUNPRO_CC)
+// Sun Pro CC supports exceptions.  However, there is no compile-time way of
+// detecting whether they are enabled or not.  Therefore, we assume that
+// they are enabled unless the user tells us otherwise.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__IBMCPP__) && __EXCEPTIONS
+// xlC defines __EXCEPTIONS to 1 if and only if exceptions are enabled.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__HP_aCC)
+// Exception handling is in effect by default in HP aCC compiler. It has to
+// be turned of by +noeh compiler option if desired.
+#  define GTEST_HAS_EXCEPTIONS 1
+# else
+// For other compilers, we assume exceptions are disabled to be
+// conservative.
+#  define GTEST_HAS_EXCEPTIONS 0
+# endif  // defined(_MSC_VER) || defined(__BORLANDC__)
+#endif  // GTEST_HAS_EXCEPTIONS
+
+#ifndef GTEST_HAS_STD_WSTRING
+// The user didn't tell us whether ::std::wstring is available, so we need
+// to figure it out.
+// Cygwin 1.7 and below doesn't support ::std::wstring.
+// Solaris' libc++ doesn't support it either.  Android has
+// no support for it at least as recent as Froyo (2.2).
+#define GTEST_HAS_STD_WSTRING                                         \
+  (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
+     GTEST_OS_HAIKU || GTEST_OS_ESP32 || GTEST_OS_ESP8266 || GTEST_OS_XTENSA))
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+// Determines whether RTTI is available.
+#ifndef GTEST_HAS_RTTI
+// The user didn't tell us whether RTTI is enabled, so we need to
+// figure it out.
+
+# ifdef _MSC_VER
+
+#ifdef _CPPRTTI  // MSVC defines this macro if and only if RTTI is enabled.
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif
+
+// Starting with version 4.3.2, gcc defines __GXX_RTTI if and only if RTTI is
+// enabled.
+# elif defined(__GNUC__)
+
+#  ifdef __GXX_RTTI
+// When building against STLport with the Android NDK and with
+// -frtti -fno-exceptions, the build fails at link time with undefined
+// references to __cxa_bad_typeid. Note sure if STL or toolchain bug,
+// so disable RTTI when detected.
+#   if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) && \
+       !defined(__EXCEPTIONS)
+#    define GTEST_HAS_RTTI 0
+#   else
+#    define GTEST_HAS_RTTI 1
+#   endif  // GTEST_OS_LINUX_ANDROID && __STLPORT_MAJOR && !__EXCEPTIONS
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif  // __GXX_RTTI
+
+// Clang defines __GXX_RTTI starting with version 3.0, but its manual recommends
+// using has_feature instead. has_feature(cxx_rtti) is supported since 2.7, the
+// first version with C++ support.
+# elif defined(__clang__)
+
+#  define GTEST_HAS_RTTI __has_feature(cxx_rtti)
+
+// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if
+// both the typeid and dynamic_cast features are present.
+# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900)
+
+#  ifdef __RTTI_ALL__
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif
+
+# else
+
+// For all other compilers, we assume RTTI is enabled.
+#  define GTEST_HAS_RTTI 1
+
+# endif  // _MSC_VER
+
+#endif  // GTEST_HAS_RTTI
+
+// It's this header's responsibility to #include <typeinfo> when RTTI
+// is enabled.
+#if GTEST_HAS_RTTI
+# include <typeinfo>
+#endif
+
+// Determines whether Google Test can use the pthreads library.
+#ifndef GTEST_HAS_PTHREAD
+// The user didn't tell us explicitly, so we make reasonable assumptions about
+// which platforms have pthreads support.
+//
+// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
+// to your compiler flags.
+#define GTEST_HAS_PTHREAD                                                      \
+  (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX || GTEST_OS_QNX ||          \
+   GTEST_OS_FREEBSD || GTEST_OS_NACL || GTEST_OS_NETBSD || GTEST_OS_FUCHSIA || \
+   GTEST_OS_DRAGONFLY || GTEST_OS_GNU_KFREEBSD || GTEST_OS_OPENBSD ||          \
+   GTEST_OS_HAIKU || GTEST_OS_GNU_HURD)
+#endif  // GTEST_HAS_PTHREAD
+
+#if GTEST_HAS_PTHREAD
+// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
+// true.
+# include <pthread.h>  // NOLINT
+
+// For timespec and nanosleep, used below.
+# include <time.h>  // NOLINT
+#endif
+
+// Determines whether clone(2) is supported.
+// Usually it will only be available on Linux, excluding
+// Linux on the Itanium architecture.
+// Also see http://linux.die.net/man/2/clone.
+#ifndef GTEST_HAS_CLONE
+// The user didn't tell us, so we need to figure it out.
+
+# if GTEST_OS_LINUX && !defined(__ia64__)
+#  if GTEST_OS_LINUX_ANDROID
+// On Android, clone() became available at different API levels for each 32-bit
+// architecture.
+#    if defined(__LP64__) || \
+        (defined(__arm__) && __ANDROID_API__ >= 9) || \
+        (defined(__mips__) && __ANDROID_API__ >= 12) || \
+        (defined(__i386__) && __ANDROID_API__ >= 17)
+#     define GTEST_HAS_CLONE 1
+#    else
+#     define GTEST_HAS_CLONE 0
+#    endif
+#  else
+#   define GTEST_HAS_CLONE 1
+#  endif
+# else
+#  define GTEST_HAS_CLONE 0
+# endif  // GTEST_OS_LINUX && !defined(__ia64__)
+
+#endif  // GTEST_HAS_CLONE
+
+// Determines whether to support stream redirection. This is used to test
+// output correctness and to implement death tests.
+#ifndef GTEST_HAS_STREAM_REDIRECTION
+// By default, we assume that stream redirection is supported on all
+// platforms except known mobile ones.
+#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \
+    GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_XTENSA
+#  define GTEST_HAS_STREAM_REDIRECTION 0
+# else
+#  define GTEST_HAS_STREAM_REDIRECTION 1
+# endif  // !GTEST_OS_WINDOWS_MOBILE
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Determines whether to support death tests.
+// pops up a dialog window that cannot be suppressed programmatically.
+#if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS ||             \
+     (GTEST_OS_MAC && !GTEST_OS_IOS) ||                                   \
+     (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER) || GTEST_OS_WINDOWS_MINGW ||  \
+     GTEST_OS_AIX || GTEST_OS_HPUX || GTEST_OS_OPENBSD || GTEST_OS_QNX || \
+     GTEST_OS_FREEBSD || GTEST_OS_NETBSD || GTEST_OS_FUCHSIA ||           \
+     GTEST_OS_DRAGONFLY || GTEST_OS_GNU_KFREEBSD || GTEST_OS_HAIKU ||     \
+     GTEST_OS_GNU_HURD)
+# define GTEST_HAS_DEATH_TEST 1
+#endif
+
+// Determines whether to support type-driven tests.
+
+// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0,
+// Sun Pro CC, IBM Visual Age, and HP aCC support.
+#if defined(__GNUC__) || defined(_MSC_VER) || defined(__SUNPRO_CC) || \
+    defined(__IBMCPP__) || defined(__HP_aCC)
+# define GTEST_HAS_TYPED_TEST 1
+# define GTEST_HAS_TYPED_TEST_P 1
+#endif
+
+// Determines whether the system compiler uses UTF-16 for encoding wide strings.
+#define GTEST_WIDE_STRING_USES_UTF16_ \
+  (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_AIX || GTEST_OS_OS2)
+
+// Determines whether test results can be streamed to a socket.
+#if GTEST_OS_LINUX || GTEST_OS_GNU_KFREEBSD || GTEST_OS_DRAGONFLY || \
+    GTEST_OS_FREEBSD || GTEST_OS_NETBSD || GTEST_OS_OPENBSD ||       \
+    GTEST_OS_GNU_HURD
+# define GTEST_CAN_STREAM_RESULTS_ 1
+#endif
+
+// Defines some utility macros.
+
+// The GNU compiler emits a warning if nested "if" statements are followed by
+// an "else" statement and braces are not used to explicitly disambiguate the
+// "else" binding.  This leads to problems with code like:
+//
+//   if (gate)
+//     ASSERT_*(condition) << "Some message";
+//
+// The "switch (0) case 0:" idiom is used to suppress this.
+#ifdef __INTEL_COMPILER
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_
+#else
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default:  // NOLINT
+#endif
+
+// Use this annotation at the end of a struct/class definition to
+// prevent the compiler from optimizing away instances that are never
+// used.  This is useful when all interesting logic happens inside the
+// c'tor and / or d'tor.  Example:
+//
+//   struct Foo {
+//     Foo() { ... }
+//   } GTEST_ATTRIBUTE_UNUSED_;
+//
+// Also use it after a variable or parameter declaration to tell the
+// compiler the variable/parameter does not have to be used.
+#if defined(__GNUC__) && !defined(COMPILER_ICC)
+# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
+#elif defined(__clang__)
+# if __has_attribute(unused)
+#  define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
+# endif
+#endif
+#ifndef GTEST_ATTRIBUTE_UNUSED_
+# define GTEST_ATTRIBUTE_UNUSED_
+#endif
+
+// Use this annotation before a function that takes a printf format string.
+#if (defined(__GNUC__) || defined(__clang__)) && !defined(COMPILER_ICC)
+# if defined(__MINGW_PRINTF_FORMAT)
+// MinGW has two different printf implementations. Ensure the format macro
+// matches the selected implementation. See
+// https://sourceforge.net/p/mingw-w64/wiki2/gnu%20printf/.
+#  define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check) \
+       __attribute__((__format__(__MINGW_PRINTF_FORMAT, string_index, \
+                                 first_to_check)))
+# else
+#  define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check) \
+       __attribute__((__format__(__printf__, string_index, first_to_check)))
+# endif
+#else
+# define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check)
+#endif
+
+
+// A macro to disallow copy operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_ASSIGN_(type) \
+  type& operator=(type const &) = delete
+
+// A macro to disallow copy constructor and operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type) \
+  type(type const&) = delete;                 \
+  type& operator=(type const&) = delete
+
+// A macro to disallow move operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_MOVE_ASSIGN_(type) \
+  type& operator=(type &&) noexcept = delete
+
+// A macro to disallow move constructor and operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_MOVE_AND_ASSIGN_(type) \
+  type(type&&) noexcept = delete;             \
+  type& operator=(type&&) noexcept = delete
+
+// Tell the compiler to warn about unused return values for functions declared
+// with this macro.  The macro should be used on function declarations
+// following the argument list:
+//
+//   Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
+#if defined(__GNUC__) && !defined(COMPILER_ICC)
+# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result))
+#else
+# define GTEST_MUST_USE_RESULT_
+#endif  // __GNUC__ && !COMPILER_ICC
+
+// MS C++ compiler emits warning when a conditional expression is compile time
+// constant. In some contexts this warning is false positive and needs to be
+// suppressed. Use the following two macros in such cases:
+//
+// GTEST_INTENTIONAL_CONST_COND_PUSH_()
+// while (true) {
+// GTEST_INTENTIONAL_CONST_COND_POP_()
+// }
+# define GTEST_INTENTIONAL_CONST_COND_PUSH_() \
+    GTEST_DISABLE_MSC_WARNINGS_PUSH_(4127)
+# define GTEST_INTENTIONAL_CONST_COND_POP_() \
+    GTEST_DISABLE_MSC_WARNINGS_POP_()
+
+// Determine whether the compiler supports Microsoft's Structured Exception
+// Handling.  This is supported by several Windows compilers but generally
+// does not exist on any other system.
+#ifndef GTEST_HAS_SEH
+// The user didn't tell us, so we need to figure it out.
+
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+// These two compilers are known to support SEH.
+#  define GTEST_HAS_SEH 1
+# else
+// Assume no SEH.
+#  define GTEST_HAS_SEH 0
+# endif
+
+#endif  // GTEST_HAS_SEH
+
+#ifndef GTEST_IS_THREADSAFE
+
+#define GTEST_IS_THREADSAFE                                                 \
+  (GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ ||                                     \
+   (GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT) || \
+   GTEST_HAS_PTHREAD)
+
+#endif  // GTEST_IS_THREADSAFE
+
+// GTEST_API_ qualifies all symbols that must be exported. The definitions below
+// are guarded by #ifndef to give embedders a chance to define GTEST_API_ in
+// gtest/internal/custom/gtest-port.h
+#ifndef GTEST_API_
+
+#ifdef _MSC_VER
+# if GTEST_LINKED_AS_SHARED_LIBRARY
+#  define GTEST_API_ __declspec(dllimport)
+# elif GTEST_CREATE_SHARED_LIBRARY
+#  define GTEST_API_ __declspec(dllexport)
+# endif
+#elif __GNUC__ >= 4 || defined(__clang__)
+# define GTEST_API_ __attribute__((visibility ("default")))
+#endif  // _MSC_VER
+
+#endif  // GTEST_API_
+
+#ifndef GTEST_API_
+# define GTEST_API_
+#endif  // GTEST_API_
+
+#ifndef GTEST_DEFAULT_DEATH_TEST_STYLE
+# define GTEST_DEFAULT_DEATH_TEST_STYLE  "fast"
+#endif  // GTEST_DEFAULT_DEATH_TEST_STYLE
+
+#ifdef __GNUC__
+// Ask the compiler to never inline a given function.
+# define GTEST_NO_INLINE_ __attribute__((noinline))
+#else
+# define GTEST_NO_INLINE_
+#endif
+
+// _LIBCPP_VERSION is defined by the libc++ library from the LLVM project.
+#if !defined(GTEST_HAS_CXXABI_H_)
+# if defined(__GLIBCXX__) || (defined(_LIBCPP_VERSION) && !defined(_MSC_VER))
+#  define GTEST_HAS_CXXABI_H_ 1
+# else
+#  define GTEST_HAS_CXXABI_H_ 0
+# endif
+#endif
+
+// A function level attribute to disable checking for use of uninitialized
+// memory when built with MemorySanitizer.
+#if defined(__clang__)
+# if __has_feature(memory_sanitizer)
+#  define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ \
+       __attribute__((no_sanitize_memory))
+# else
+#  define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
+# endif  // __has_feature(memory_sanitizer)
+#else
+# define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
+#endif  // __clang__
+
+// A function level attribute to disable AddressSanitizer instrumentation.
+#if defined(__clang__)
+# if __has_feature(address_sanitizer)
+#  define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ \
+       __attribute__((no_sanitize_address))
+# else
+#  define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+# endif  // __has_feature(address_sanitizer)
+#else
+# define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
+#endif  // __clang__
+
+// A function level attribute to disable HWAddressSanitizer instrumentation.
+#if defined(__clang__)
+# if __has_feature(hwaddress_sanitizer)
+#  define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ \
+       __attribute__((no_sanitize("hwaddress")))
+# else
+#  define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
+# endif  // __has_feature(hwaddress_sanitizer)
+#else
+# define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
+#endif  // __clang__
+
+// A function level attribute to disable ThreadSanitizer instrumentation.
+#if defined(__clang__)
+# if __has_feature(thread_sanitizer)
+#  define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ \
+       __attribute__((no_sanitize_thread))
+# else
+#  define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
+# endif  // __has_feature(thread_sanitizer)
+#else
+# define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
+#endif  // __clang__
+
+namespace testing {
+
+class Message;
+
+// Legacy imports for backwards compatibility.
+// New code should use std:: names directly.
+using std::get;
+using std::make_tuple;
+using std::tuple;
+using std::tuple_element;
+using std::tuple_size;
+
+namespace internal {
+
+// A secret type that Google Test users don't know about.  It has no
+// definition on purpose.  Therefore it's impossible to create a
+// Secret object, which is what we want.
+class Secret;
+
+// The GTEST_COMPILE_ASSERT_ is a legacy macro used to verify that a compile
+// time expression is true (in new code, use static_assert instead). For
+// example, you could use it to verify the size of a static array:
+//
+//   GTEST_COMPILE_ASSERT_(GTEST_ARRAY_SIZE_(names) == NUM_NAMES,
+//                         names_incorrect_size);
+//
+// The second argument to the macro must be a valid C++ identifier. If the
+// expression is false, compiler will issue an error containing this identifier.
+#define GTEST_COMPILE_ASSERT_(expr, msg) static_assert(expr, #msg)
+
+// A helper for suppressing warnings on constant condition.  It just
+// returns 'condition'.
+GTEST_API_ bool IsTrue(bool condition);
+
+// Defines RE.
+
+#if GTEST_USES_PCRE
+// if used, PCRE is injected by custom/gtest-port.h
+#elif GTEST_USES_POSIX_RE || GTEST_USES_SIMPLE_RE
+
+// A simple C++ wrapper for <regex.h>.  It uses the POSIX Extended
+// Regular Expression syntax.
+class GTEST_API_ RE {
+ public:
+  // A copy constructor is required by the Standard to initialize object
+  // references from r-values.
+  RE(const RE& other) { Init(other.pattern()); }
+
+  // Constructs an RE from a string.
+  RE(const ::std::string& regex) { Init(regex.c_str()); }  // NOLINT
+
+  RE(const char* regex) { Init(regex); }  // NOLINT
+  ~RE();
+
+  // Returns the string representation of the regex.
+  const char* pattern() const { return pattern_; }
+
+  // FullMatch(str, re) returns true if and only if regular expression re
+  // matches the entire str.
+  // PartialMatch(str, re) returns true if and only if regular expression re
+  // matches a substring of str (including str itself).
+  static bool FullMatch(const ::std::string& str, const RE& re) {
+    return FullMatch(str.c_str(), re);
+  }
+  static bool PartialMatch(const ::std::string& str, const RE& re) {
+    return PartialMatch(str.c_str(), re);
+  }
+
+  static bool FullMatch(const char* str, const RE& re);
+  static bool PartialMatch(const char* str, const RE& re);
+
+ private:
+  void Init(const char* regex);
+  const char* pattern_;
+  bool is_valid_;
+
+# if GTEST_USES_POSIX_RE
+
+  regex_t full_regex_;     // For FullMatch().
+  regex_t partial_regex_;  // For PartialMatch().
+
+# else  // GTEST_USES_SIMPLE_RE
+
+  const char* full_pattern_;  // For FullMatch();
+
+# endif
+};
+
+#endif  // GTEST_USES_PCRE
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line);
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file,
+                                                               int line);
+
+// Defines logging utilities:
+//   GTEST_LOG_(severity) - logs messages at the specified severity level. The
+//                          message itself is streamed into the macro.
+//   LogToStderr()  - directs all log messages to stderr.
+//   FlushInfoLog() - flushes informational log messages.
+
+enum GTestLogSeverity {
+  GTEST_INFO,
+  GTEST_WARNING,
+  GTEST_ERROR,
+  GTEST_FATAL
+};
+
+// Formats log entry severity, provides a stream object for streaming the
+// log message, and terminates the message with a newline when going out of
+// scope.
+class GTEST_API_ GTestLog {
+ public:
+  GTestLog(GTestLogSeverity severity, const char* file, int line);
+
+  // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+  ~GTestLog();
+
+  ::std::ostream& GetStream() { return ::std::cerr; }
+
+ private:
+  const GTestLogSeverity severity_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog);
+};
+
+#if !defined(GTEST_LOG_)
+
+# define GTEST_LOG_(severity) \
+    ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \
+                                  __FILE__, __LINE__).GetStream()
+
+inline void LogToStderr() {}
+inline void FlushInfoLog() { fflush(nullptr); }
+
+#endif  // !defined(GTEST_LOG_)
+
+#if !defined(GTEST_CHECK_)
+// INTERNAL IMPLEMENTATION - DO NOT USE.
+//
+// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition
+// is not satisfied.
+//  Synopsys:
+//    GTEST_CHECK_(boolean_condition);
+//     or
+//    GTEST_CHECK_(boolean_condition) << "Additional message";
+//
+//    This checks the condition and if the condition is not satisfied
+//    it prints message about the condition violation, including the
+//    condition itself, plus additional message streamed into it, if any,
+//    and then it aborts the program. It aborts the program irrespective of
+//    whether it is built in the debug mode or not.
+# define GTEST_CHECK_(condition) \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+    if (::testing::internal::IsTrue(condition)) \
+      ; \
+    else \
+      GTEST_LOG_(FATAL) << "Condition " #condition " failed. "
+#endif  // !defined(GTEST_CHECK_)
+
+// An all-mode assert to verify that the given POSIX-style function
+// call returns 0 (indicating success).  Known limitation: this
+// doesn't expand to a balanced 'if' statement, so enclose the macro
+// in {} if you need to use it as the only statement in an 'if'
+// branch.
+#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \
+  if (const int gtest_error = (posix_call)) \
+    GTEST_LOG_(FATAL) << #posix_call << "failed with error " \
+                      << gtest_error
+
+// Transforms "T" into "const T&" according to standard reference collapsing
+// rules (this is only needed as a backport for C++98 compilers that do not
+// support reference collapsing). Specifically, it transforms:
+//
+//   char         ==> const char&
+//   const char   ==> const char&
+//   char&        ==> char&
+//   const char&  ==> const char&
+//
+// Note that the non-const reference will not have "const" added. This is
+// standard, and necessary so that "T" can always bind to "const T&".
+template <typename T>
+struct ConstRef { typedef const T& type; };
+template <typename T>
+struct ConstRef<T&> { typedef T& type; };
+
+// The argument T must depend on some template parameters.
+#define GTEST_REFERENCE_TO_CONST_(T) \
+  typename ::testing::internal::ConstRef<T>::type
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Use ImplicitCast_ as a safe version of static_cast for upcasting in
+// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a
+// const Foo*).  When you use ImplicitCast_, the compiler checks that
+// the cast is safe.  Such explicit ImplicitCast_s are necessary in
+// surprisingly many situations where C++ demands an exact type match
+// instead of an argument type convertable to a target type.
+//
+// The syntax for using ImplicitCast_ is the same as for static_cast:
+//
+//   ImplicitCast_<ToType>(expr)
+//
+// ImplicitCast_ would have been part of the C++ standard library,
+// but the proposal was submitted too late.  It will probably make
+// its way into the language in the future.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., implicit_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To>
+inline To ImplicitCast_(To x) { return x; }
+
+// When you upcast (that is, cast a pointer from type Foo to type
+// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts
+// always succeed.  When you downcast (that is, cast a pointer from
+// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
+// how do you know the pointer is really of type SubclassOfFoo?  It
+// could be a bare Foo, or of type DifferentSubclassOfFoo.  Thus,
+// when you downcast, you should use this macro.  In debug mode, we
+// use dynamic_cast<> to double-check the downcast is legal (we die
+// if it's not).  In normal mode, we do the efficient static_cast<>
+// instead.  Thus, it's important to test in debug mode to make sure
+// the cast is legal!
+//    This is the only place in the code we should use dynamic_cast<>.
+// In particular, you SHOULDN'T be using dynamic_cast<> in order to
+// do RTTI (eg code like this:
+//    if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
+//    if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
+// You should design the code some other way not to need this.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., down_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To, typename From>  // use like this: DownCast_<T*>(foo);
+inline To DownCast_(From* f) {  // so we only accept pointers
+  // Ensures that To is a sub-type of From *.  This test is here only
+  // for compile-time type checking, and has no overhead in an
+  // optimized build at run-time, as it will be optimized away
+  // completely.
+  GTEST_INTENTIONAL_CONST_COND_PUSH_()
+  if (false) {
+  GTEST_INTENTIONAL_CONST_COND_POP_()
+  const To to = nullptr;
+  ::testing::internal::ImplicitCast_<From*>(to);
+  }
+
+#if GTEST_HAS_RTTI
+  // RTTI: debug mode only!
+  GTEST_CHECK_(f == nullptr || dynamic_cast<To>(f) != nullptr);
+#endif
+  return static_cast<To>(f);
+}
+
+// Downcasts the pointer of type Base to Derived.
+// Derived must be a subclass of Base. The parameter MUST
+// point to a class of type Derived, not any subclass of it.
+// When RTTI is available, the function performs a runtime
+// check to enforce this.
+template <class Derived, class Base>
+Derived* CheckedDowncastToActualType(Base* base) {
+#if GTEST_HAS_RTTI
+  GTEST_CHECK_(typeid(*base) == typeid(Derived));
+#endif
+
+#if GTEST_HAS_DOWNCAST_
+  return ::down_cast<Derived*>(base);
+#elif GTEST_HAS_RTTI
+  return dynamic_cast<Derived*>(base);  // NOLINT
+#else
+  return static_cast<Derived*>(base);  // Poor man's downcast.
+#endif
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Defines the stderr capturer:
+//   CaptureStdout     - starts capturing stdout.
+//   GetCapturedStdout - stops capturing stdout and returns the captured string.
+//   CaptureStderr     - starts capturing stderr.
+//   GetCapturedStderr - stops capturing stderr and returns the captured string.
+//
+GTEST_API_ void CaptureStdout();
+GTEST_API_ std::string GetCapturedStdout();
+GTEST_API_ void CaptureStderr();
+GTEST_API_ std::string GetCapturedStderr();
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+// Returns the size (in bytes) of a file.
+GTEST_API_ size_t GetFileSize(FILE* file);
+
+// Reads the entire content of a file as a string.
+GTEST_API_ std::string ReadEntireFile(FILE* file);
+
+// All command line arguments.
+GTEST_API_ std::vector<std::string> GetArgvs();
+
+#if GTEST_HAS_DEATH_TEST
+
+std::vector<std::string> GetInjectableArgvs();
+// Deprecated: pass the args vector by value instead.
+void SetInjectableArgvs(const std::vector<std::string>* new_argvs);
+void SetInjectableArgvs(const std::vector<std::string>& new_argvs);
+void ClearInjectableArgvs();
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Defines synchronization primitives.
+#if GTEST_IS_THREADSAFE
+# if GTEST_HAS_PTHREAD
+// Sleeps for (roughly) n milliseconds.  This function is only for testing
+// Google Test's own constructs.  Don't use it in user tests, either
+// directly or indirectly.
+inline void SleepMilliseconds(int n) {
+  const timespec time = {
+    0,                  // 0 seconds.
+    n * 1000L * 1000L,  // And n ms.
+  };
+  nanosleep(&time, nullptr);
+}
+# endif  // GTEST_HAS_PTHREAD
+
+# if GTEST_HAS_NOTIFICATION_
+// Notification has already been imported into the namespace.
+// Nothing to do here.
+
+# elif GTEST_HAS_PTHREAD
+// Allows a controller thread to pause execution of newly created
+// threads until notified.  Instances of this class must be created
+// and destroyed in the controller thread.
+//
+// This class is only for testing Google Test's own constructs. Do not
+// use it in user tests, either directly or indirectly.
+class Notification {
+ public:
+  Notification() : notified_(false) {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, nullptr));
+  }
+  ~Notification() {
+    pthread_mutex_destroy(&mutex_);
+  }
+
+  // Notifies all threads created with this notification to start. Must
+  // be called from the controller thread.
+  void Notify() {
+    pthread_mutex_lock(&mutex_);
+    notified_ = true;
+    pthread_mutex_unlock(&mutex_);
+  }
+
+  // Blocks until the controller thread notifies. Must be called from a test
+  // thread.
+  void WaitForNotification() {
+    for (;;) {
+      pthread_mutex_lock(&mutex_);
+      const bool notified = notified_;
+      pthread_mutex_unlock(&mutex_);
+      if (notified)
+        break;
+      SleepMilliseconds(10);
+    }
+  }
+
+ private:
+  pthread_mutex_t mutex_;
+  bool notified_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
+};
+
+# elif GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
+
+GTEST_API_ void SleepMilliseconds(int n);
+
+// Provides leak-safe Windows kernel handle ownership.
+// Used in death tests and in threading support.
+class GTEST_API_ AutoHandle {
+ public:
+  // Assume that Win32 HANDLE type is equivalent to void*. Doing so allows us to
+  // avoid including <windows.h> in this header file. Including <windows.h> is
+  // undesirable because it defines a lot of symbols and macros that tend to
+  // conflict with client code. This assumption is verified by
+  // WindowsTypesTest.HANDLEIsVoidStar.
+  typedef void* Handle;
+  AutoHandle();
+  explicit AutoHandle(Handle handle);
+
+  ~AutoHandle();
+
+  Handle Get() const;
+  void Reset();
+  void Reset(Handle handle);
+
+ private:
+  // Returns true if and only if the handle is a valid handle object that can be
+  // closed.
+  bool IsCloseable() const;
+
+  Handle handle_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
+};
+
+// Allows a controller thread to pause execution of newly created
+// threads until notified.  Instances of this class must be created
+// and destroyed in the controller thread.
+//
+// This class is only for testing Google Test's own constructs. Do not
+// use it in user tests, either directly or indirectly.
+class GTEST_API_ Notification {
+ public:
+  Notification();
+  void Notify();
+  void WaitForNotification();
+
+ private:
+  AutoHandle event_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
+};
+# endif  // GTEST_HAS_NOTIFICATION_
+
+// On MinGW, we can have both GTEST_OS_WINDOWS and GTEST_HAS_PTHREAD
+// defined, but we don't want to use MinGW's pthreads implementation, which
+// has conformance problems with some versions of the POSIX standard.
+# if GTEST_HAS_PTHREAD && !GTEST_OS_WINDOWS_MINGW
+
+// As a C-function, ThreadFuncWithCLinkage cannot be templated itself.
+// Consequently, it cannot select a correct instantiation of ThreadWithParam
+// in order to call its Run(). Introducing ThreadWithParamBase as a
+// non-templated base class for ThreadWithParam allows us to bypass this
+// problem.
+class ThreadWithParamBase {
+ public:
+  virtual ~ThreadWithParamBase() {}
+  virtual void Run() = 0;
+};
+
+// pthread_create() accepts a pointer to a function type with the C linkage.
+// According to the Standard (7.5/1), function types with different linkages
+// are different even if they are otherwise identical.  Some compilers (for
+// example, SunStudio) treat them as different types.  Since class methods
+// cannot be defined with C-linkage we need to define a free C-function to
+// pass into pthread_create().
+extern "C" inline void* ThreadFuncWithCLinkage(void* thread) {
+  static_cast<ThreadWithParamBase*>(thread)->Run();
+  return nullptr;
+}
+
+// Helper class for testing Google Test's multi-threading constructs.
+// To use it, write:
+//
+//   void ThreadFunc(int param) { /* Do things with param */ }
+//   Notification thread_can_start;
+//   ...
+//   // The thread_can_start parameter is optional; you can supply NULL.
+//   ThreadWithParam<int> thread(&ThreadFunc, 5, &thread_can_start);
+//   thread_can_start.Notify();
+//
+// These classes are only for testing Google Test's own constructs. Do
+// not use them in user tests, either directly or indirectly.
+template <typename T>
+class ThreadWithParam : public ThreadWithParamBase {
+ public:
+  typedef void UserThreadFunc(T);
+
+  ThreadWithParam(UserThreadFunc* func, T param, Notification* thread_can_start)
+      : func_(func),
+        param_(param),
+        thread_can_start_(thread_can_start),
+        finished_(false) {
+    ThreadWithParamBase* const base = this;
+    // The thread can be created only after all fields except thread_
+    // have been initialized.
+    GTEST_CHECK_POSIX_SUCCESS_(
+        pthread_create(&thread_, nullptr, &ThreadFuncWithCLinkage, base));
+  }
+  ~ThreadWithParam() override { Join(); }
+
+  void Join() {
+    if (!finished_) {
+      GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, nullptr));
+      finished_ = true;
+    }
+  }
+
+  void Run() override {
+    if (thread_can_start_ != nullptr) thread_can_start_->WaitForNotification();
+    func_(param_);
+  }
+
+ private:
+  UserThreadFunc* const func_;  // User-supplied thread function.
+  const T param_;  // User-supplied parameter to the thread function.
+  // When non-NULL, used to block execution until the controller thread
+  // notifies.
+  Notification* const thread_can_start_;
+  bool finished_;  // true if and only if we know that the thread function has
+                   // finished.
+  pthread_t thread_;  // The native thread object.
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
+};
+# endif  // !GTEST_OS_WINDOWS && GTEST_HAS_PTHREAD ||
+         // GTEST_HAS_MUTEX_AND_THREAD_LOCAL_
+
+# if GTEST_HAS_MUTEX_AND_THREAD_LOCAL_
+// Mutex and ThreadLocal have already been imported into the namespace.
+// Nothing to do here.
+
+# elif GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
+
+// Mutex implements mutex on Windows platforms.  It is used in conjunction
+// with class MutexLock:
+//
+//   Mutex mutex;
+//   ...
+//   MutexLock lock(&mutex);  // Acquires the mutex and releases it at the
+//                            // end of the current scope.
+//
+// A static Mutex *must* be defined or declared using one of the following
+// macros:
+//   GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
+//   GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
+//
+// (A non-static Mutex is defined/declared in the usual way).
+class GTEST_API_ Mutex {
+ public:
+  enum MutexType { kStatic = 0, kDynamic = 1 };
+  // We rely on kStaticMutex being 0 as it is to what the linker initializes
+  // type_ in static mutexes.  critical_section_ will be initialized lazily
+  // in ThreadSafeLazyInit().
+  enum StaticConstructorSelector { kStaticMutex = 0 };
+
+  // This constructor intentionally does nothing.  It relies on type_ being
+  // statically initialized to 0 (effectively setting it to kStatic) and on
+  // ThreadSafeLazyInit() to lazily initialize the rest of the members.
+  explicit Mutex(StaticConstructorSelector /*dummy*/) {}
+
+  Mutex();
+  ~Mutex();
+
+  void Lock();
+
+  void Unlock();
+
+  // Does nothing if the current thread holds the mutex. Otherwise, crashes
+  // with high probability.
+  void AssertHeld();
+
+ private:
+  // Initializes owner_thread_id_ and critical_section_ in static mutexes.
+  void ThreadSafeLazyInit();
+
+  // Per https://blogs.msdn.microsoft.com/oldnewthing/20040223-00/?p=40503,
+  // we assume that 0 is an invalid value for thread IDs.
+  unsigned int owner_thread_id_;
+
+  // For static mutexes, we rely on these members being initialized to zeros
+  // by the linker.
+  MutexType type_;
+  long critical_section_init_phase_;  // NOLINT
+  GTEST_CRITICAL_SECTION* critical_section_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
+};
+
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+    extern ::testing::internal::Mutex mutex
+
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
+    ::testing::internal::Mutex mutex(::testing::internal::Mutex::kStaticMutex)
+
+// We cannot name this class MutexLock because the ctor declaration would
+// conflict with a macro named MutexLock, which is defined on some
+// platforms. That macro is used as a defensive measure to prevent against
+// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
+// "MutexLock l(&mu)".  Hence the typedef trick below.
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(Mutex* mutex)
+      : mutex_(mutex) { mutex_->Lock(); }
+
+  ~GTestMutexLock() { mutex_->Unlock(); }
+
+ private:
+  Mutex* const mutex_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock);
+};
+
+typedef GTestMutexLock MutexLock;
+
+// Base class for ValueHolder<T>.  Allows a caller to hold and delete a value
+// without knowing its type.
+class ThreadLocalValueHolderBase {
+ public:
+  virtual ~ThreadLocalValueHolderBase() {}
+};
+
+// Provides a way for a thread to send notifications to a ThreadLocal
+// regardless of its parameter type.
+class ThreadLocalBase {
+ public:
+  // Creates a new ValueHolder<T> object holding a default value passed to
+  // this ThreadLocal<T>'s constructor and returns it.  It is the caller's
+  // responsibility not to call this when the ThreadLocal<T> instance already
+  // has a value on the current thread.
+  virtual ThreadLocalValueHolderBase* NewValueForCurrentThread() const = 0;
+
+ protected:
+  ThreadLocalBase() {}
+  virtual ~ThreadLocalBase() {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocalBase);
+};
+
+// Maps a thread to a set of ThreadLocals that have values instantiated on that
+// thread and notifies them when the thread exits.  A ThreadLocal instance is
+// expected to persist until all threads it has values on have terminated.
+class GTEST_API_ ThreadLocalRegistry {
+ public:
+  // Registers thread_local_instance as having value on the current thread.
+  // Returns a value that can be used to identify the thread from other threads.
+  static ThreadLocalValueHolderBase* GetValueOnCurrentThread(
+      const ThreadLocalBase* thread_local_instance);
+
+  // Invoked when a ThreadLocal instance is destroyed.
+  static void OnThreadLocalDestroyed(
+      const ThreadLocalBase* thread_local_instance);
+};
+
+class GTEST_API_ ThreadWithParamBase {
+ public:
+  void Join();
+
+ protected:
+  class Runnable {
+   public:
+    virtual ~Runnable() {}
+    virtual void Run() = 0;
+  };
+
+  ThreadWithParamBase(Runnable *runnable, Notification* thread_can_start);
+  virtual ~ThreadWithParamBase();
+
+ private:
+  AutoHandle thread_;
+};
+
+// Helper class for testing Google Test's multi-threading constructs.
+template <typename T>
+class ThreadWithParam : public ThreadWithParamBase {
+ public:
+  typedef void UserThreadFunc(T);
+
+  ThreadWithParam(UserThreadFunc* func, T param, Notification* thread_can_start)
+      : ThreadWithParamBase(new RunnableImpl(func, param), thread_can_start) {
+  }
+  virtual ~ThreadWithParam() {}
+
+ private:
+  class RunnableImpl : public Runnable {
+   public:
+    RunnableImpl(UserThreadFunc* func, T param)
+        : func_(func),
+          param_(param) {
+    }
+    virtual ~RunnableImpl() {}
+    virtual void Run() {
+      func_(param_);
+    }
+
+   private:
+    UserThreadFunc* const func_;
+    const T param_;
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(RunnableImpl);
+  };
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
+};
+
+// Implements thread-local storage on Windows systems.
+//
+//   // Thread 1
+//   ThreadLocal<int> tl(100);  // 100 is the default value for each thread.
+//
+//   // Thread 2
+//   tl.set(150);  // Changes the value for thread 2 only.
+//   EXPECT_EQ(150, tl.get());
+//
+//   // Thread 1
+//   EXPECT_EQ(100, tl.get());  // In thread 1, tl has the original value.
+//   tl.set(200);
+//   EXPECT_EQ(200, tl.get());
+//
+// The template type argument T must have a public copy constructor.
+// In addition, the default ThreadLocal constructor requires T to have
+// a public default constructor.
+//
+// The users of a TheadLocal instance have to make sure that all but one
+// threads (including the main one) using that instance have exited before
+// destroying it. Otherwise, the per-thread objects managed for them by the
+// ThreadLocal instance are not guaranteed to be destroyed on all platforms.
+//
+// Google Test only uses global ThreadLocal objects.  That means they
+// will die after main() has returned.  Therefore, no per-thread
+// object managed by Google Test will be leaked as long as all threads
+// using Google Test have exited when main() returns.
+template <typename T>
+class ThreadLocal : public ThreadLocalBase {
+ public:
+  ThreadLocal() : default_factory_(new DefaultValueHolderFactory()) {}
+  explicit ThreadLocal(const T& value)
+      : default_factory_(new InstanceValueHolderFactory(value)) {}
+
+  ~ThreadLocal() { ThreadLocalRegistry::OnThreadLocalDestroyed(this); }
+
+  T* pointer() { return GetOrCreateValue(); }
+  const T* pointer() const { return GetOrCreateValue(); }
+  const T& get() const { return *pointer(); }
+  void set(const T& value) { *pointer() = value; }
+
+ private:
+  // Holds a value of T.  Can be deleted via its base class without the caller
+  // knowing the type of T.
+  class ValueHolder : public ThreadLocalValueHolderBase {
+   public:
+    ValueHolder() : value_() {}
+    explicit ValueHolder(const T& value) : value_(value) {}
+
+    T* pointer() { return &value_; }
+
+   private:
+    T value_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder);
+  };
+
+
+  T* GetOrCreateValue() const {
+    return static_cast<ValueHolder*>(
+        ThreadLocalRegistry::GetValueOnCurrentThread(this))->pointer();
+  }
+
+  virtual ThreadLocalValueHolderBase* NewValueForCurrentThread() const {
+    return default_factory_->MakeNewHolder();
+  }
+
+  class ValueHolderFactory {
+   public:
+    ValueHolderFactory() {}
+    virtual ~ValueHolderFactory() {}
+    virtual ValueHolder* MakeNewHolder() const = 0;
+
+   private:
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolderFactory);
+  };
+
+  class DefaultValueHolderFactory : public ValueHolderFactory {
+   public:
+    DefaultValueHolderFactory() {}
+    ValueHolder* MakeNewHolder() const override { return new ValueHolder(); }
+
+   private:
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultValueHolderFactory);
+  };
+
+  class InstanceValueHolderFactory : public ValueHolderFactory {
+   public:
+    explicit InstanceValueHolderFactory(const T& value) : value_(value) {}
+    ValueHolder* MakeNewHolder() const override {
+      return new ValueHolder(value_);
+    }
+
+   private:
+    const T value_;  // The value for each thread.
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(InstanceValueHolderFactory);
+  };
+
+  std::unique_ptr<ValueHolderFactory> default_factory_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
+};
+
+# elif GTEST_HAS_PTHREAD
+
+// MutexBase and Mutex implement mutex on pthreads-based platforms.
+class MutexBase {
+ public:
+  // Acquires this mutex.
+  void Lock() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_));
+    owner_ = pthread_self();
+    has_owner_ = true;
+  }
+
+  // Releases this mutex.
+  void Unlock() {
+    // Since the lock is being released the owner_ field should no longer be
+    // considered valid. We don't protect writing to has_owner_ here, as it's
+    // the caller's responsibility to ensure that the current thread holds the
+    // mutex when this is called.
+    has_owner_ = false;
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_));
+  }
+
+  // Does nothing if the current thread holds the mutex. Otherwise, crashes
+  // with high probability.
+  void AssertHeld() const {
+    GTEST_CHECK_(has_owner_ && pthread_equal(owner_, pthread_self()))
+        << "The current thread is not holding the mutex @" << this;
+  }
+
+  // A static mutex may be used before main() is entered.  It may even
+  // be used before the dynamic initialization stage.  Therefore we
+  // must be able to initialize a static mutex object at link time.
+  // This means MutexBase has to be a POD and its member variables
+  // have to be public.
+ public:
+  pthread_mutex_t mutex_;  // The underlying pthread mutex.
+  // has_owner_ indicates whether the owner_ field below contains a valid thread
+  // ID and is therefore safe to inspect (e.g., to use in pthread_equal()). All
+  // accesses to the owner_ field should be protected by a check of this field.
+  // An alternative might be to memset() owner_ to all zeros, but there's no
+  // guarantee that a zero'd pthread_t is necessarily invalid or even different
+  // from pthread_self().
+  bool has_owner_;
+  pthread_t owner_;  // The thread holding the mutex.
+};
+
+// Forward-declares a static mutex.
+#  define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+     extern ::testing::internal::MutexBase mutex
+
+// Defines and statically (i.e. at link time) initializes a static mutex.
+// The initialization list here does not explicitly initialize each field,
+// instead relying on default initialization for the unspecified fields. In
+// particular, the owner_ field (a pthread_t) is not explicitly initialized.
+// This allows initialization to work whether pthread_t is a scalar or struct.
+// The flag -Wmissing-field-initializers must not be specified for this to work.
+#define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
+  ::testing::internal::MutexBase mutex = {PTHREAD_MUTEX_INITIALIZER, false, 0}
+
+// The Mutex class can only be used for mutexes created at runtime. It
+// shares its API with MutexBase otherwise.
+class Mutex : public MutexBase {
+ public:
+  Mutex() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, nullptr));
+    has_owner_ = false;
+  }
+  ~Mutex() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_));
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
+};
+
+// We cannot name this class MutexLock because the ctor declaration would
+// conflict with a macro named MutexLock, which is defined on some
+// platforms. That macro is used as a defensive measure to prevent against
+// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
+// "MutexLock l(&mu)".  Hence the typedef trick below.
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(MutexBase* mutex)
+      : mutex_(mutex) { mutex_->Lock(); }
+
+  ~GTestMutexLock() { mutex_->Unlock(); }
+
+ private:
+  MutexBase* const mutex_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock);
+};
+
+typedef GTestMutexLock MutexLock;
+
+// Helpers for ThreadLocal.
+
+// pthread_key_create() requires DeleteThreadLocalValue() to have
+// C-linkage.  Therefore it cannot be templatized to access
+// ThreadLocal<T>.  Hence the need for class
+// ThreadLocalValueHolderBase.
+class ThreadLocalValueHolderBase {
+ public:
+  virtual ~ThreadLocalValueHolderBase() {}
+};
+
+// Called by pthread to delete thread-local data stored by
+// pthread_setspecific().
+extern "C" inline void DeleteThreadLocalValue(void* value_holder) {
+  delete static_cast<ThreadLocalValueHolderBase*>(value_holder);
+}
+
+// Implements thread-local storage on pthreads-based systems.
+template <typename T>
+class GTEST_API_ ThreadLocal {
+ public:
+  ThreadLocal()
+      : key_(CreateKey()), default_factory_(new DefaultValueHolderFactory()) {}
+  explicit ThreadLocal(const T& value)
+      : key_(CreateKey()),
+        default_factory_(new InstanceValueHolderFactory(value)) {}
+
+  ~ThreadLocal() {
+    // Destroys the managed object for the current thread, if any.
+    DeleteThreadLocalValue(pthread_getspecific(key_));
+
+    // Releases resources associated with the key.  This will *not*
+    // delete managed objects for other threads.
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_));
+  }
+
+  T* pointer() { return GetOrCreateValue(); }
+  const T* pointer() const { return GetOrCreateValue(); }
+  const T& get() const { return *pointer(); }
+  void set(const T& value) { *pointer() = value; }
+
+ private:
+  // Holds a value of type T.
+  class ValueHolder : public ThreadLocalValueHolderBase {
+   public:
+    ValueHolder() : value_() {}
+    explicit ValueHolder(const T& value) : value_(value) {}
+
+    T* pointer() { return &value_; }
+
+   private:
+    T value_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder);
+  };
+
+  static pthread_key_t CreateKey() {
+    pthread_key_t key;
+    // When a thread exits, DeleteThreadLocalValue() will be called on
+    // the object managed for that thread.
+    GTEST_CHECK_POSIX_SUCCESS_(
+        pthread_key_create(&key, &DeleteThreadLocalValue));
+    return key;
+  }
+
+  T* GetOrCreateValue() const {
+    ThreadLocalValueHolderBase* const holder =
+        static_cast<ThreadLocalValueHolderBase*>(pthread_getspecific(key_));
+    if (holder != nullptr) {
+      return CheckedDowncastToActualType<ValueHolder>(holder)->pointer();
+    }
+
+    ValueHolder* const new_holder = default_factory_->MakeNewHolder();
+    ThreadLocalValueHolderBase* const holder_base = new_holder;
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base));
+    return new_holder->pointer();
+  }
+
+  class ValueHolderFactory {
+   public:
+    ValueHolderFactory() {}
+    virtual ~ValueHolderFactory() {}
+    virtual ValueHolder* MakeNewHolder() const = 0;
+
+   private:
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolderFactory);
+  };
+
+  class DefaultValueHolderFactory : public ValueHolderFactory {
+   public:
+    DefaultValueHolderFactory() {}
+    ValueHolder* MakeNewHolder() const override { return new ValueHolder(); }
+
+   private:
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultValueHolderFactory);
+  };
+
+  class InstanceValueHolderFactory : public ValueHolderFactory {
+   public:
+    explicit InstanceValueHolderFactory(const T& value) : value_(value) {}
+    ValueHolder* MakeNewHolder() const override {
+      return new ValueHolder(value_);
+    }
+
+   private:
+    const T value_;  // The value for each thread.
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(InstanceValueHolderFactory);
+  };
+
+  // A key pthreads uses for looking up per-thread values.
+  const pthread_key_t key_;
+  std::unique_ptr<ValueHolderFactory> default_factory_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
+};
+
+# endif  // GTEST_HAS_MUTEX_AND_THREAD_LOCAL_
+
+#else  // GTEST_IS_THREADSAFE
+
+// A dummy implementation of synchronization primitives (mutex, lock,
+// and thread-local variable).  Necessary for compiling Google Test where
+// mutex is not supported - using Google Test in multiple threads is not
+// supported on such platforms.
+
+class Mutex {
+ public:
+  Mutex() {}
+  void Lock() {}
+  void Unlock() {}
+  void AssertHeld() const {}
+};
+
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+  extern ::testing::internal::Mutex mutex
+
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
+
+// We cannot name this class MutexLock because the ctor declaration would
+// conflict with a macro named MutexLock, which is defined on some
+// platforms. That macro is used as a defensive measure to prevent against
+// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
+// "MutexLock l(&mu)".  Hence the typedef trick below.
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(Mutex*) {}  // NOLINT
+};
+
+typedef GTestMutexLock MutexLock;
+
+template <typename T>
+class GTEST_API_ ThreadLocal {
+ public:
+  ThreadLocal() : value_() {}
+  explicit ThreadLocal(const T& value) : value_(value) {}
+  T* pointer() { return &value_; }
+  const T* pointer() const { return &value_; }
+  const T& get() const { return value_; }
+  void set(const T& value) { value_ = value; }
+ private:
+  T value_;
+};
+
+#endif  // GTEST_IS_THREADSAFE
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+GTEST_API_ size_t GetThreadCount();
+
+#if GTEST_OS_WINDOWS
+# define GTEST_PATH_SEP_ "\\"
+# define GTEST_HAS_ALT_PATH_SEP_ 1
+#else
+# define GTEST_PATH_SEP_ "/"
+# define GTEST_HAS_ALT_PATH_SEP_ 0
+#endif  // GTEST_OS_WINDOWS
+
+// Utilities for char.
+
+// isspace(int ch) and friends accept an unsigned char or EOF.  char
+// may be signed, depending on the compiler (or compiler flags).
+// Therefore we need to cast a char to unsigned char before calling
+// isspace(), etc.
+
+inline bool IsAlpha(char ch) {
+  return isalpha(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsAlNum(char ch) {
+  return isalnum(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsDigit(char ch) {
+  return isdigit(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsLower(char ch) {
+  return islower(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsSpace(char ch) {
+  return isspace(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsUpper(char ch) {
+  return isupper(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsXDigit(char ch) {
+  return isxdigit(static_cast<unsigned char>(ch)) != 0;
+}
+#ifdef __cpp_char8_t
+inline bool IsXDigit(char8_t ch) {
+  return isxdigit(static_cast<unsigned char>(ch)) != 0;
+}
+#endif
+inline bool IsXDigit(char16_t ch) {
+  const unsigned char low_byte = static_cast<unsigned char>(ch);
+  return ch == low_byte && isxdigit(low_byte) != 0;
+}
+inline bool IsXDigit(char32_t ch) {
+  const unsigned char low_byte = static_cast<unsigned char>(ch);
+  return ch == low_byte && isxdigit(low_byte) != 0;
+}
+inline bool IsXDigit(wchar_t ch) {
+  const unsigned char low_byte = static_cast<unsigned char>(ch);
+  return ch == low_byte && isxdigit(low_byte) != 0;
+}
+
+inline char ToLower(char ch) {
+  return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
+}
+inline char ToUpper(char ch) {
+  return static_cast<char>(toupper(static_cast<unsigned char>(ch)));
+}
+
+inline std::string StripTrailingSpaces(std::string str) {
+  std::string::iterator it = str.end();
+  while (it != str.begin() && IsSpace(*--it))
+    it = str.erase(it);
+  return str;
+}
+
+// The testing::internal::posix namespace holds wrappers for common
+// POSIX functions.  These wrappers hide the differences between
+// Windows/MSVC and POSIX systems.  Since some compilers define these
+// standard functions as macros, the wrapper cannot have the same name
+// as the wrapped function.
+
+namespace posix {
+
+// Functions with a different name on Windows.
+
+#if GTEST_OS_WINDOWS
+
+typedef struct _stat StatStruct;
+
+# ifdef __BORLANDC__
+inline int DoIsATTY(int fd) { return isatty(fd); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return stricmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+# else  // !__BORLANDC__
+#  if GTEST_OS_WINDOWS_MOBILE
+inline int DoIsATTY(int /* fd */) { return 0; }
+#  else
+inline int DoIsATTY(int fd) { return _isatty(fd); }
+#  endif  // GTEST_OS_WINDOWS_MOBILE
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return _stricmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return _strdup(src); }
+# endif  // __BORLANDC__
+
+# if GTEST_OS_WINDOWS_MOBILE
+inline int FileNo(FILE* file) { return reinterpret_cast<int>(_fileno(file)); }
+// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this
+// time and thus not defined there.
+# else
+inline int FileNo(FILE* file) { return _fileno(file); }
+inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); }
+inline int RmDir(const char* dir) { return _rmdir(dir); }
+inline bool IsDir(const StatStruct& st) {
+  return (_S_IFDIR & st.st_mode) != 0;
+}
+# endif  // GTEST_OS_WINDOWS_MOBILE
+
+#elif GTEST_OS_ESP8266
+typedef struct stat StatStruct;
+
+inline int FileNo(FILE* file) { return fileno(file); }
+inline int DoIsATTY(int fd) { return isatty(fd); }
+inline int Stat(const char* path, StatStruct* buf) {
+  // stat function not implemented on ESP8266
+  return 0;
+}
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return strcasecmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+inline int RmDir(const char* dir) { return rmdir(dir); }
+inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
+
+#else
+
+typedef struct stat StatStruct;
+
+inline int FileNo(FILE* file) { return fileno(file); }
+inline int DoIsATTY(int fd) { return isatty(fd); }
+inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return strcasecmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+inline int RmDir(const char* dir) { return rmdir(dir); }
+inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
+
+#endif  // GTEST_OS_WINDOWS
+
+inline int IsATTY(int fd) {
+  // DoIsATTY might change errno (for example ENOTTY in case you redirect stdout
+  // to a file on Linux), which is unexpected, so save the previous value, and
+  // restore it after the call.
+  int savedErrno = errno;
+  int isAttyValue = DoIsATTY(fd);
+  errno = savedErrno;
+
+  return isAttyValue;
+}
+
+// Functions deprecated by MSVC 8.0.
+
+GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
+
+// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and
+// StrError() aren't needed on Windows CE at this time and thus not
+// defined there.
+
+#if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && \
+    !GTEST_OS_WINDOWS_RT && !GTEST_OS_ESP8266 && !GTEST_OS_XTENSA
+inline int ChDir(const char* dir) { return chdir(dir); }
+#endif
+inline FILE* FOpen(const char* path, const char* mode) {
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW
+  struct wchar_codecvt : public std::codecvt<wchar_t, char, std::mbstate_t> {};
+  std::wstring_convert<wchar_codecvt> converter;
+  std::wstring wide_path = converter.from_bytes(path);
+  std::wstring wide_mode = converter.from_bytes(mode);
+  return _wfopen(wide_path.c_str(), wide_mode.c_str());
+#else  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW
+  return fopen(path, mode);
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW
+}
+#if !GTEST_OS_WINDOWS_MOBILE
+inline FILE *FReopen(const char* path, const char* mode, FILE* stream) {
+  return freopen(path, mode, stream);
+}
+inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); }
+#endif
+inline int FClose(FILE* fp) { return fclose(fp); }
+#if !GTEST_OS_WINDOWS_MOBILE
+inline int Read(int fd, void* buf, unsigned int count) {
+  return static_cast<int>(read(fd, buf, count));
+}
+inline int Write(int fd, const void* buf, unsigned int count) {
+  return static_cast<int>(write(fd, buf, count));
+}
+inline int Close(int fd) { return close(fd); }
+inline const char* StrError(int errnum) { return strerror(errnum); }
+#endif
+inline const char* GetEnv(const char* name) {
+#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \
+    GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_XTENSA
+  // We are on an embedded platform, which has no environment variables.
+  static_cast<void>(name);  // To prevent 'unused argument' warning.
+  return nullptr;
+#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
+  // Environment variables which we programmatically clear will be set to the
+  // empty string rather than unset (NULL).  Handle that case.
+  const char* const env = getenv(name);
+  return (env != nullptr && env[0] != '\0') ? env : nullptr;
+#else
+  return getenv(name);
+#endif
+}
+
+GTEST_DISABLE_MSC_DEPRECATED_POP_()
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Windows CE has no C library. The abort() function is used in
+// several places in Google Test. This implementation provides a reasonable
+// imitation of standard behaviour.
+[[noreturn]] void Abort();
+#else
+[[noreturn]] inline void Abort() { abort(); }
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+}  // namespace posix
+
+// MSVC "deprecates" snprintf and issues warnings wherever it is used.  In
+// order to avoid these warnings, we need to use _snprintf or _snprintf_s on
+// MSVC-based platforms.  We map the GTEST_SNPRINTF_ macro to the appropriate
+// function in order to achieve that.  We use macro definition here because
+// snprintf is a variadic function.
+#if _MSC_VER && !GTEST_OS_WINDOWS_MOBILE
+// MSVC 2005 and above support variadic macros.
+# define GTEST_SNPRINTF_(buffer, size, format, ...) \
+     _snprintf_s(buffer, size, size, format, __VA_ARGS__)
+#elif defined(_MSC_VER)
+// Windows CE does not define _snprintf_s
+# define GTEST_SNPRINTF_ _snprintf
+#else
+# define GTEST_SNPRINTF_ snprintf
+#endif
+
+// The biggest signed integer type the compiler supports.
+//
+// long long is guaranteed to be at least 64-bits in C++11.
+using BiggestInt = long long;  // NOLINT
+
+// The maximum number a BiggestInt can represent.
+constexpr BiggestInt kMaxBiggestInt = (std::numeric_limits<BiggestInt>::max)();
+
+// This template class serves as a compile-time function from size to
+// type.  It maps a size in bytes to a primitive type with that
+// size. e.g.
+//
+//   TypeWithSize<4>::UInt
+//
+// is typedef-ed to be unsigned int (unsigned integer made up of 4
+// bytes).
+//
+// Such functionality should belong to STL, but I cannot find it
+// there.
+//
+// Google Test uses this class in the implementation of floating-point
+// comparison.
+//
+// For now it only handles UInt (unsigned int) as that's all Google Test
+// needs.  Other types can be easily added in the future if need
+// arises.
+template <size_t size>
+class TypeWithSize {
+ public:
+  // This prevents the user from using TypeWithSize<N> with incorrect
+  // values of N.
+  using UInt = void;
+};
+
+// The specialization for size 4.
+template <>
+class TypeWithSize<4> {
+ public:
+  using Int = std::int32_t;
+  using UInt = std::uint32_t;
+};
+
+// The specialization for size 8.
+template <>
+class TypeWithSize<8> {
+ public:
+  using Int = std::int64_t;
+  using UInt = std::uint64_t;
+};
+
+// Integer types of known sizes.
+using TimeInMillis = int64_t;  // Represents time in milliseconds.
+
+// Utilities for command line flags and environment variables.
+
+// Macro for referencing flags.
+#if !defined(GTEST_FLAG)
+# define GTEST_FLAG(name) FLAGS_gtest_##name
+#endif  // !defined(GTEST_FLAG)
+
+#if !defined(GTEST_USE_OWN_FLAGFILE_FLAG_)
+# define GTEST_USE_OWN_FLAGFILE_FLAG_ 1
+#endif  // !defined(GTEST_USE_OWN_FLAGFILE_FLAG_)
+
+#if !defined(GTEST_DECLARE_bool_)
+# define GTEST_FLAG_SAVER_ ::testing::internal::GTestFlagSaver
+
+// Macros for declaring flags.
+# define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name)
+# define GTEST_DECLARE_int32_(name) \
+    GTEST_API_ extern std::int32_t GTEST_FLAG(name)
+# define GTEST_DECLARE_string_(name) \
+    GTEST_API_ extern ::std::string GTEST_FLAG(name)
+
+// Macros for defining flags.
+# define GTEST_DEFINE_bool_(name, default_val, doc) \
+    GTEST_API_ bool GTEST_FLAG(name) = (default_val)
+# define GTEST_DEFINE_int32_(name, default_val, doc) \
+    GTEST_API_ std::int32_t GTEST_FLAG(name) = (default_val)
+# define GTEST_DEFINE_string_(name, default_val, doc) \
+    GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val)
+
+#endif  // !defined(GTEST_DECLARE_bool_)
+
+// Thread annotations
+#if !defined(GTEST_EXCLUSIVE_LOCK_REQUIRED_)
+# define GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)
+# define GTEST_LOCK_EXCLUDED_(locks)
+#endif  // !defined(GTEST_EXCLUSIVE_LOCK_REQUIRED_)
+
+// Parses 'str' for a 32-bit signed integer.  If successful, writes the result
+// to *value and returns true; otherwise leaves *value unchanged and returns
+// false.
+GTEST_API_ bool ParseInt32(const Message& src_text, const char* str,
+                           int32_t* value);
+
+// Parses a bool/int32_t/string from the environment variable
+// corresponding to the given Google Test flag.
+bool BoolFromGTestEnv(const char* flag, bool default_val);
+GTEST_API_ int32_t Int32FromGTestEnv(const char* flag, int32_t default_val);
+std::string OutputFlagAlsoCheckEnvVar();
+const char* StringFromGTestEnv(const char* flag, const char* default_val);
+
+}  // namespace internal
+}  // namespace testing
+
+#if !defined(GTEST_INTERNAL_DEPRECATED)
+
+// Internal Macro to mark an API deprecated, for googletest usage only
+// Usage: class GTEST_INTERNAL_DEPRECATED(message) MyClass or
+// GTEST_INTERNAL_DEPRECATED(message) <return_type> myFunction(); Every usage of
+// a deprecated entity will trigger a warning when compiled with
+// `-Wdeprecated-declarations` option (clang, gcc, any __GNUC__ compiler).
+// For msvc /W3 option will need to be used
+// Note that for 'other' compilers this macro evaluates to nothing to prevent
+// compilations errors.
+#if defined(_MSC_VER)
+#define GTEST_INTERNAL_DEPRECATED(message) __declspec(deprecated(message))
+#elif defined(__GNUC__)
+#define GTEST_INTERNAL_DEPRECATED(message) __attribute__((deprecated(message)))
+#else
+#define GTEST_INTERNAL_DEPRECATED(message)
+#endif
+
+#endif  // !defined(GTEST_INTERNAL_DEPRECATED)
+
+#if GTEST_HAS_ABSL
+// Always use absl::any for UniversalPrinter<> specializations if googletest
+// is built with absl support.
+#define GTEST_INTERNAL_HAS_ANY 1
+#include "absl/types/any.h"
+namespace testing {
+namespace internal {
+using Any = ::absl::any;
+}  // namespace internal
+}  // namespace testing
+#else
+#ifdef __has_include
+#if __has_include(<any>) && __cplusplus >= 201703L
+// Otherwise for C++17 and higher use std::any for UniversalPrinter<>
+// specializations.
+#define GTEST_INTERNAL_HAS_ANY 1
+#include <any>
+namespace testing {
+namespace internal {
+using Any = ::std::any;
+}  // namespace internal
+}  // namespace testing
+// The case where absl is configured NOT to alias std::any is not
+// supported.
+#endif  // __has_include(<any>) && __cplusplus >= 201703L
+#endif  // __has_include
+#endif  // GTEST_HAS_ABSL
+
+#if GTEST_HAS_ABSL
+// Always use absl::optional for UniversalPrinter<> specializations if
+// googletest is built with absl support.
+#define GTEST_INTERNAL_HAS_OPTIONAL 1
+#include "absl/types/optional.h"
+namespace testing {
+namespace internal {
+template <typename T>
+using Optional = ::absl::optional<T>;
+}  // namespace internal
+}  // namespace testing
+#else
+#ifdef __has_include
+#if __has_include(<optional>) && __cplusplus >= 201703L
+// Otherwise for C++17 and higher use std::optional for UniversalPrinter<>
+// specializations.
+#define GTEST_INTERNAL_HAS_OPTIONAL 1
+#include <optional>
+namespace testing {
+namespace internal {
+template <typename T>
+using Optional = ::std::optional<T>;
+}  // namespace internal
+}  // namespace testing
+// The case where absl is configured NOT to alias std::optional is not
+// supported.
+#endif  // __has_include(<optional>) && __cplusplus >= 201703L
+#endif  // __has_include
+#endif  // GTEST_HAS_ABSL
+
+#if GTEST_HAS_ABSL
+// Always use absl::string_view for Matcher<> specializations if googletest
+// is built with absl support.
+# define GTEST_INTERNAL_HAS_STRING_VIEW 1
+#include "absl/strings/string_view.h"
+namespace testing {
+namespace internal {
+using StringView = ::absl::string_view;
+}  // namespace internal
+}  // namespace testing
+#else
+# ifdef __has_include
+#   if __has_include(<string_view>) && __cplusplus >= 201703L
+// Otherwise for C++17 and higher use std::string_view for Matcher<>
+// specializations.
+#   define GTEST_INTERNAL_HAS_STRING_VIEW 1
+#include <string_view>
+namespace testing {
+namespace internal {
+using StringView = ::std::string_view;
+}  // namespace internal
+}  // namespace testing
+// The case where absl is configured NOT to alias std::string_view is not
+// supported.
+#  endif  // __has_include(<string_view>) && __cplusplus >= 201703L
+# endif  // __has_include
+#endif  // GTEST_HAS_ABSL
+
+#if GTEST_HAS_ABSL
+// Always use absl::variant for UniversalPrinter<> specializations if googletest
+// is built with absl support.
+#define GTEST_INTERNAL_HAS_VARIANT 1
+#include "absl/types/variant.h"
+namespace testing {
+namespace internal {
+template <typename... T>
+using Variant = ::absl::variant<T...>;
+}  // namespace internal
+}  // namespace testing
+#else
+#ifdef __has_include
+#if __has_include(<variant>) && __cplusplus >= 201703L
+// Otherwise for C++17 and higher use std::variant for UniversalPrinter<>
+// specializations.
+#define GTEST_INTERNAL_HAS_VARIANT 1
+#include <variant>
+namespace testing {
+namespace internal {
+template <typename... T>
+using Variant = ::std::variant<T...>;
+}  // namespace internal
+}  // namespace testing
+// The case where absl is configured NOT to alias std::variant is not supported.
+#endif  // __has_include(<variant>) && __cplusplus >= 201703L
+#endif  // __has_include
+#endif  // GTEST_HAS_ABSL
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+
+#if GTEST_OS_LINUX
+# include <stdlib.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <unistd.h>
+#endif  // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+# include <stdexcept>
+#endif
+
+#include <ctype.h>
+#include <float.h>
+#include <string.h>
+#include <cstdint>
+#include <iomanip>
+#include <limits>
+#include <map>
+#include <set>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This header file defines the Message class.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
+// program!
+
+// GOOGLETEST_CM0001 DO NOT DELETE
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+
+#include <limits>
+#include <memory>
+#include <sstream>
+
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+// Ensures that there is at least one operator<< in the global namespace.
+// See Message& operator<<(...) below for why.
+void operator<<(const testing::internal::Secret&, int);
+
+namespace testing {
+
+// The Message class works like an ostream repeater.
+//
+// Typical usage:
+//
+//   1. You stream a bunch of values to a Message object.
+//      It will remember the text in a stringstream.
+//   2. Then you stream the Message object to an ostream.
+//      This causes the text in the Message to be streamed
+//      to the ostream.
+//
+// For example;
+//
+//   testing::Message foo;
+//   foo << 1 << " != " << 2;
+//   std::cout << foo;
+//
+// will print "1 != 2".
+//
+// Message is not intended to be inherited from.  In particular, its
+// destructor is not virtual.
+//
+// Note that stringstream behaves differently in gcc and in MSVC.  You
+// can stream a NULL char pointer to it in the former, but not in the
+// latter (it causes an access violation if you do).  The Message
+// class hides this difference by treating a NULL char pointer as
+// "(null)".
+class GTEST_API_ Message {
+ private:
+  // The type of basic IO manipulators (endl, ends, and flush) for
+  // narrow streams.
+  typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
+
+ public:
+  // Constructs an empty Message.
+  Message();
+
+  // Copy constructor.
+  Message(const Message& msg) : ss_(new ::std::stringstream) {  // NOLINT
+    *ss_ << msg.GetString();
+  }
+
+  // Constructs a Message from a C-string.
+  explicit Message(const char* str) : ss_(new ::std::stringstream) {
+    *ss_ << str;
+  }
+
+  // Streams a non-pointer value to this object.
+  template <typename T>
+  inline Message& operator <<(const T& val) {
+    // Some libraries overload << for STL containers.  These
+    // overloads are defined in the global namespace instead of ::std.
+    //
+    // C++'s symbol lookup rule (i.e. Koenig lookup) says that these
+    // overloads are visible in either the std namespace or the global
+    // namespace, but not other namespaces, including the testing
+    // namespace which Google Test's Message class is in.
+    //
+    // To allow STL containers (and other types that has a << operator
+    // defined in the global namespace) to be used in Google Test
+    // assertions, testing::Message must access the custom << operator
+    // from the global namespace.  With this using declaration,
+    // overloads of << defined in the global namespace and those
+    // visible via Koenig lookup are both exposed in this function.
+    using ::operator <<;
+    *ss_ << val;
+    return *this;
+  }
+
+  // Streams a pointer value to this object.
+  //
+  // This function is an overload of the previous one.  When you
+  // stream a pointer to a Message, this definition will be used as it
+  // is more specialized.  (The C++ Standard, section
+  // [temp.func.order].)  If you stream a non-pointer, then the
+  // previous definition will be used.
+  //
+  // The reason for this overload is that streaming a NULL pointer to
+  // ostream is undefined behavior.  Depending on the compiler, you
+  // may get "0", "(nil)", "(null)", or an access violation.  To
+  // ensure consistent result across compilers, we always treat NULL
+  // as "(null)".
+  template <typename T>
+  inline Message& operator <<(T* const& pointer) {  // NOLINT
+    if (pointer == nullptr) {
+      *ss_ << "(null)";
+    } else {
+      *ss_ << pointer;
+    }
+    return *this;
+  }
+
+  // Since the basic IO manipulators are overloaded for both narrow
+  // and wide streams, we have to provide this specialized definition
+  // of operator <<, even though its body is the same as the
+  // templatized version above.  Without this definition, streaming
+  // endl or other basic IO manipulators to Message will confuse the
+  // compiler.
+  Message& operator <<(BasicNarrowIoManip val) {
+    *ss_ << val;
+    return *this;
+  }
+
+  // Instead of 1/0, we want to see true/false for bool values.
+  Message& operator <<(bool b) {
+    return *this << (b ? "true" : "false");
+  }
+
+  // These two overloads allow streaming a wide C string to a Message
+  // using the UTF-8 encoding.
+  Message& operator <<(const wchar_t* wide_c_str);
+  Message& operator <<(wchar_t* wide_c_str);
+
+#if GTEST_HAS_STD_WSTRING
+  // Converts the given wide string to a narrow string using the UTF-8
+  // encoding, and streams the result to this Message object.
+  Message& operator <<(const ::std::wstring& wstr);
+#endif  // GTEST_HAS_STD_WSTRING
+
+  // Gets the text streamed to this object so far as an std::string.
+  // Each '\0' character in the buffer is replaced with "\\0".
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  std::string GetString() const;
+
+ private:
+  // We'll hold the text streamed to this object here.
+  const std::unique_ptr< ::std::stringstream> ss_;
+
+  // We declare (but don't implement) this to prevent the compiler
+  // from implementing the assignment operator.
+  void operator=(const Message&);
+};
+
+// Streams a Message to an ostream.
+inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
+  return os << sb.GetString();
+}
+
+namespace internal {
+
+// Converts a streamable value to an std::string.  A NULL pointer is
+// converted to "(null)".  When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+template <typename T>
+std::string StreamableToString(const T& streamable) {
+  return (Message() << streamable).GetString();
+}
+
+}  // namespace internal
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Google Test filepath utilities
+//
+// This header file declares classes and functions used internally by
+// Google Test.  They are subject to change without notice.
+//
+// This file is #included in gtest/internal/gtest-internal.h.
+// Do not include this header file separately!
+
+// GOOGLETEST_CM0001 DO NOT DELETE
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This header file declares the String class and functions used internally by
+// Google Test.  They are subject to change without notice. They should not used
+// by code external to Google Test.
+//
+// This header file is #included by gtest-internal.h.
+// It should not be #included by other files.
+
+// GOOGLETEST_CM0001 DO NOT DELETE
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+
+#ifdef __BORLANDC__
+// string.h is not guaranteed to provide strcpy on C++ Builder.
+# include <mem.h>
+#endif
+
+#include <string.h>
+#include <cstdint>
+#include <string>
+
+
+namespace testing {
+namespace internal {
+
+// String - an abstract class holding static string utilities.
+class GTEST_API_ String {
+ public:
+  // Static utility methods
+
+  // Clones a 0-terminated C string, allocating memory using new.  The
+  // caller is responsible for deleting the return value using
+  // delete[].  Returns the cloned string, or NULL if the input is
+  // NULL.
+  //
+  // This is different from strdup() in string.h, which allocates
+  // memory using malloc().
+  static const char* CloneCString(const char* c_str);
+
+#if GTEST_OS_WINDOWS_MOBILE
+  // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be
+  // able to pass strings to Win32 APIs on CE we need to convert them
+  // to 'Unicode', UTF-16.
+
+  // Creates a UTF-16 wide string from the given ANSI string, allocating
+  // memory using new. The caller is responsible for deleting the return
+  // value using delete[]. Returns the wide string, or NULL if the
+  // input is NULL.
+  //
+  // The wide string is created using the ANSI codepage (CP_ACP) to
+  // match the behaviour of the ANSI versions of Win32 calls and the
+  // C runtime.
+  static LPCWSTR AnsiToUtf16(const char* c_str);
+
+  // Creates an ANSI string from the given wide string, allocating
+  // memory using new. The caller is responsible for deleting the return
+  // value using delete[]. Returns the ANSI string, or NULL if the
+  // input is NULL.
+  //
+  // The returned string is created using the ANSI codepage (CP_ACP) to
+  // match the behaviour of the ANSI versions of Win32 calls and the
+  // C runtime.
+  static const char* Utf16ToAnsi(LPCWSTR utf16_str);
+#endif
+
+  // Compares two C strings.  Returns true if and only if they have the same
+  // content.
+  //
+  // Unlike strcmp(), this function can handle NULL argument(s).  A
+  // NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool CStringEquals(const char* lhs, const char* rhs);
+
+  // Converts a wide C string to a String using the UTF-8 encoding.
+  // NULL will be converted to "(null)".  If an error occurred during
+  // the conversion, "(failed to convert from wide string)" is
+  // returned.
+  static std::string ShowWideCString(const wchar_t* wide_c_str);
+
+  // Compares two wide C strings.  Returns true if and only if they have the
+  // same content.
+  //
+  // Unlike wcscmp(), this function can handle NULL argument(s).  A
+  // NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
+
+  // Compares two C strings, ignoring case.  Returns true if and only if
+  // they have the same content.
+  //
+  // Unlike strcasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool CaseInsensitiveCStringEquals(const char* lhs,
+                                           const char* rhs);
+
+  // Compares two wide C strings, ignoring case.  Returns true if and only if
+  // they have the same content.
+  //
+  // Unlike wcscasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL wide C string,
+  // including the empty string.
+  // NB: The implementations on different platforms slightly differ.
+  // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+  // environment variable. On GNU platform this method uses wcscasecmp
+  // which compares according to LC_CTYPE category of the current locale.
+  // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+  // current locale.
+  static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+                                               const wchar_t* rhs);
+
+  // Returns true if and only if the given string ends with the given suffix,
+  // ignoring case. Any string is considered to end with an empty suffix.
+  static bool EndsWithCaseInsensitive(
+      const std::string& str, const std::string& suffix);
+
+  // Formats an int value as "%02d".
+  static std::string FormatIntWidth2(int value);  // "%02d" for width == 2
+
+  // Formats an int value to given width with leading zeros.
+  static std::string FormatIntWidthN(int value, int width);
+
+  // Formats an int value as "%X".
+  static std::string FormatHexInt(int value);
+
+  // Formats an int value as "%X".
+  static std::string FormatHexUInt32(uint32_t value);
+
+  // Formats a byte as "%02X".
+  static std::string FormatByte(unsigned char value);
+
+ private:
+  String();  // Not meant to be instantiated.
+};  // class String
+
+// Gets the content of the stringstream's buffer as an std::string.  Each '\0'
+// character in the buffer is replaced with "\\0".
+GTEST_API_ std::string StringStreamToString(::std::stringstream* stream);
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+namespace testing {
+namespace internal {
+
+// FilePath - a class for file and directory pathname manipulation which
+// handles platform-specific conventions (like the pathname separator).
+// Used for helper functions for naming files in a directory for xml output.
+// Except for Set methods, all methods are const or static, which provides an
+// "immutable value object" -- useful for peace of mind.
+// A FilePath with a value ending in a path separator ("like/this/") represents
+// a directory, otherwise it is assumed to represent a file. In either case,
+// it may or may not represent an actual file or directory in the file system.
+// Names are NOT checked for syntax correctness -- no checking for illegal
+// characters, malformed paths, etc.
+
+class GTEST_API_ FilePath {
+ public:
+  FilePath() : pathname_("") { }
+  FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
+
+  explicit FilePath(const std::string& pathname) : pathname_(pathname) {
+    Normalize();
+  }
+
+  FilePath& operator=(const FilePath& rhs) {
+    Set(rhs);
+    return *this;
+  }
+
+  void Set(const FilePath& rhs) {
+    pathname_ = rhs.pathname_;
+  }
+
+  const std::string& string() const { return pathname_; }
+  const char* c_str() const { return pathname_.c_str(); }
+
+  // Returns the current working directory, or "" if unsuccessful.
+  static FilePath GetCurrentDir();
+
+  // Given directory = "dir", base_name = "test", number = 0,
+  // extension = "xml", returns "dir/test.xml". If number is greater
+  // than zero (e.g., 12), returns "dir/test_12.xml".
+  // On Windows platform, uses \ as the separator rather than /.
+  static FilePath MakeFileName(const FilePath& directory,
+                               const FilePath& base_name,
+                               int number,
+                               const char* extension);
+
+  // Given directory = "dir", relative_path = "test.xml",
+  // returns "dir/test.xml".
+  // On Windows, uses \ as the separator rather than /.
+  static FilePath ConcatPaths(const FilePath& directory,
+                              const FilePath& relative_path);
+
+  // Returns a pathname for a file that does not currently exist. The pathname
+  // will be directory/base_name.extension or
+  // directory/base_name_<number>.extension if directory/base_name.extension
+  // already exists. The number will be incremented until a pathname is found
+  // that does not already exist.
+  // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+  // There could be a race condition if two or more processes are calling this
+  // function at the same time -- they could both pick the same filename.
+  static FilePath GenerateUniqueFileName(const FilePath& directory,
+                                         const FilePath& base_name,
+                                         const char* extension);
+
+  // Returns true if and only if the path is "".
+  bool IsEmpty() const { return pathname_.empty(); }
+
+  // If input name has a trailing separator character, removes it and returns
+  // the name, otherwise return the name string unmodified.
+  // On Windows platform, uses \ as the separator, other platforms use /.
+  FilePath RemoveTrailingPathSeparator() const;
+
+  // Returns a copy of the FilePath with the directory part removed.
+  // Example: FilePath("path/to/file").RemoveDirectoryName() returns
+  // FilePath("file"). If there is no directory part ("just_a_file"), it returns
+  // the FilePath unmodified. If there is no file part ("just_a_dir/") it
+  // returns an empty FilePath ("").
+  // On Windows platform, '\' is the path separator, otherwise it is '/'.
+  FilePath RemoveDirectoryName() const;
+
+  // RemoveFileName returns the directory path with the filename removed.
+  // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+  // If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+  // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+  // not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+  // On Windows platform, '\' is the path separator, otherwise it is '/'.
+  FilePath RemoveFileName() const;
+
+  // Returns a copy of the FilePath with the case-insensitive extension removed.
+  // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+  // FilePath("dir/file"). If a case-insensitive extension is not
+  // found, returns a copy of the original FilePath.
+  FilePath RemoveExtension(const char* extension) const;
+
+  // Creates directories so that path exists. Returns true if successful or if
+  // the directories already exist; returns false if unable to create
+  // directories for any reason. Will also return false if the FilePath does
+  // not represent a directory (that is, it doesn't end with a path separator).
+  bool CreateDirectoriesRecursively() const;
+
+  // Create the directory so that path exists. Returns true if successful or
+  // if the directory already exists; returns false if unable to create the
+  // directory for any reason, including if the parent directory does not
+  // exist. Not named "CreateDirectory" because that's a macro on Windows.
+  bool CreateFolder() const;
+
+  // Returns true if FilePath describes something in the file-system,
+  // either a file, directory, or whatever, and that something exists.
+  bool FileOrDirectoryExists() const;
+
+  // Returns true if pathname describes a directory in the file-system
+  // that exists.
+  bool DirectoryExists() const;
+
+  // Returns true if FilePath ends with a path separator, which indicates that
+  // it is intended to represent a directory. Returns false otherwise.
+  // This does NOT check that a directory (or file) actually exists.
+  bool IsDirectory() const;
+
+  // Returns true if pathname describes a root directory. (Windows has one
+  // root directory per disk drive.)
+  bool IsRootDirectory() const;
+
+  // Returns true if pathname describes an absolute path.
+  bool IsAbsolutePath() const;
+
+ private:
+  // Replaces multiple consecutive separators with a single separator.
+  // For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+  // redundancies that might be in a pathname involving "." or "..".
+  //
+  // A pathname with multiple consecutive separators may occur either through
+  // user error or as a result of some scripts or APIs that generate a pathname
+  // with a trailing separator. On other platforms the same API or script
+  // may NOT generate a pathname with a trailing "/". Then elsewhere that
+  // pathname may have another "/" and pathname components added to it,
+  // without checking for the separator already being there.
+  // The script language and operating system may allow paths like "foo//bar"
+  // but some of the functions in FilePath will not handle that correctly. In
+  // particular, RemoveTrailingPathSeparator() only removes one separator, and
+  // it is called in CreateDirectoriesRecursively() assuming that it will change
+  // a pathname from directory syntax (trailing separator) to filename syntax.
+  //
+  // On Windows this method also replaces the alternate path separator '/' with
+  // the primary path separator '\\', so that for example "bar\\/\\foo" becomes
+  // "bar\\foo".
+
+  void Normalize();
+
+  // Returns a pointer to the last occurrence of a valid path separator in
+  // the FilePath. On Windows, for example, both '/' and '\' are valid path
+  // separators. Returns NULL if no path separator was found.
+  const char* FindLastPathSeparator() const;
+
+  std::string pathname_;
+};  // class FilePath
+
+}  // namespace internal
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Type utilities needed for implementing typed and type-parameterized
+// tests.
+
+// GOOGLETEST_CM0001 DO NOT DELETE
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+
+
+// #ifdef __GNUC__ is too general here.  It is possible to use gcc without using
+// libstdc++ (which is where cxxabi.h comes from).
+# if GTEST_HAS_CXXABI_H_
+#  include <cxxabi.h>
+# elif defined(__HP_aCC)
+#  include <acxx_demangle.h>
+# endif  // GTEST_HASH_CXXABI_H_
+
+namespace testing {
+namespace internal {
+
+// Canonicalizes a given name with respect to the Standard C++ Library.
+// This handles removing the inline namespace within `std` that is
+// used by various standard libraries (e.g., `std::__1`).  Names outside
+// of namespace std are returned unmodified.
+inline std::string CanonicalizeForStdLibVersioning(std::string s) {
+  static const char prefix[] = "std::__";
+  if (s.compare(0, strlen(prefix), prefix) == 0) {
+    std::string::size_type end = s.find("::", strlen(prefix));
+    if (end != s.npos) {
+      // Erase everything between the initial `std` and the second `::`.
+      s.erase(strlen("std"), end - strlen("std"));
+    }
+  }
+  return s;
+}
+
+#if GTEST_HAS_RTTI
+// GetTypeName(const std::type_info&) returns a human-readable name of type T.
+inline std::string GetTypeName(const std::type_info& type) {
+  const char* const name = type.name();
+#if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
+  int status = 0;
+  // gcc's implementation of typeid(T).name() mangles the type name,
+  // so we have to demangle it.
+#if GTEST_HAS_CXXABI_H_
+  using abi::__cxa_demangle;
+#endif  // GTEST_HAS_CXXABI_H_
+  char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status);
+  const std::string name_str(status == 0 ? readable_name : name);
+  free(readable_name);
+  return CanonicalizeForStdLibVersioning(name_str);
+#else
+  return name;
+#endif  // GTEST_HAS_CXXABI_H_ || __HP_aCC
+}
+#endif  // GTEST_HAS_RTTI
+
+// GetTypeName<T>() returns a human-readable name of type T if and only if
+// RTTI is enabled, otherwise it returns a dummy type name.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
+template <typename T>
+std::string GetTypeName() {
+#if GTEST_HAS_RTTI
+  return GetTypeName(typeid(T));
+#else
+  return "<type>";
+#endif  // GTEST_HAS_RTTI
+}
+
+// A unique type indicating an empty node
+struct None {};
+
+# define GTEST_TEMPLATE_ template <typename T> class
+
+// The template "selector" struct TemplateSel<Tmpl> is used to
+// represent Tmpl, which must be a class template with one type
+// parameter, as a type.  TemplateSel<Tmpl>::Bind<T>::type is defined
+// as the type Tmpl<T>.  This allows us to actually instantiate the
+// template "selected" by TemplateSel<Tmpl>.
+//
+// This trick is necessary for simulating typedef for class templates,
+// which C++ doesn't support directly.
+template <GTEST_TEMPLATE_ Tmpl>
+struct TemplateSel {
+  template <typename T>
+  struct Bind {
+    typedef Tmpl<T> type;
+  };
+};
+
+# define GTEST_BIND_(TmplSel, T) \
+  TmplSel::template Bind<T>::type
+
+template <GTEST_TEMPLATE_ Head_, GTEST_TEMPLATE_... Tail_>
+struct Templates {
+  using Head = TemplateSel<Head_>;
+  using Tail = Templates<Tail_...>;
+};
+
+template <GTEST_TEMPLATE_ Head_>
+struct Templates<Head_> {
+  using Head = TemplateSel<Head_>;
+  using Tail = None;
+};
+
+// Tuple-like type lists
+template <typename Head_, typename... Tail_>
+struct Types {
+  using Head = Head_;
+  using Tail = Types<Tail_...>;
+};
+
+template <typename Head_>
+struct Types<Head_> {
+  using Head = Head_;
+  using Tail = None;
+};
+
+// Helper metafunctions to tell apart a single type from types
+// generated by ::testing::Types
+template <typename... Ts>
+struct ProxyTypeList {
+  using type = Types<Ts...>;
+};
+
+template <typename>
+struct is_proxy_type_list : std::false_type {};
+
+template <typename... Ts>
+struct is_proxy_type_list<ProxyTypeList<Ts...>> : std::true_type {};
+
+// Generator which conditionally creates type lists.
+// It recognizes if a requested type list should be created
+// and prevents creating a new type list nested within another one.
+template <typename T>
+struct GenerateTypeList {
+ private:
+  using proxy = typename std::conditional<is_proxy_type_list<T>::value, T,
+                                          ProxyTypeList<T>>::type;
+
+ public:
+  using type = typename proxy::type;
+};
+
+}  // namespace internal
+
+template <typename... Ts>
+using Types = internal::ProxyTypeList<Ts...>;
+
+}  // namespace testing
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+
+// Due to C++ preprocessor weirdness, we need double indirection to
+// concatenate two tokens when one of them is __LINE__.  Writing
+//
+//   foo ## __LINE__
+//
+// will result in the token foo__LINE__, instead of foo followed by
+// the current line number.  For more details, see
+// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
+#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
+#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
+
+// Stringifies its argument.
+// Work around a bug in visual studio which doesn't accept code like this:
+//
+//   #define GTEST_STRINGIFY_(name) #name
+//   #define MACRO(a, b, c) ... GTEST_STRINGIFY_(a) ...
+//   MACRO(, x, y)
+//
+// Complaining about the argument to GTEST_STRINGIFY_ being empty.
+// This is allowed by the spec.
+#define GTEST_STRINGIFY_HELPER_(name, ...) #name
+#define GTEST_STRINGIFY_(...) GTEST_STRINGIFY_HELPER_(__VA_ARGS__, )
+
+namespace proto2 {
+class MessageLite;
+}
+
+namespace testing {
+
+// Forward declarations.
+
+class AssertionResult;                 // Result of an assertion.
+class Message;                         // Represents a failure message.
+class Test;                            // Represents a test.
+class TestInfo;                        // Information about a test.
+class TestPartResult;                  // Result of a test part.
+class UnitTest;                        // A collection of test suites.
+
+template <typename T>
+::std::string PrintToString(const T& value);
+
+namespace internal {
+
+struct TraceInfo;                      // Information about a trace point.
+class TestInfoImpl;                    // Opaque implementation of TestInfo
+class UnitTestImpl;                    // Opaque implementation of UnitTest
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+GTEST_API_ extern const char kStackTraceMarker[];
+
+// An IgnoredValue object can be implicitly constructed from ANY value.
+class IgnoredValue {
+  struct Sink {};
+ public:
+  // This constructor template allows any value to be implicitly
+  // converted to IgnoredValue.  The object has no data member and
+  // doesn't try to remember anything about the argument.  We
+  // deliberately omit the 'explicit' keyword in order to allow the
+  // conversion to be implicit.
+  // Disable the conversion if T already has a magical conversion operator.
+  // Otherwise we get ambiguity.
+  template <typename T,
+            typename std::enable_if<!std::is_convertible<T, Sink>::value,
+                                    int>::type = 0>
+  IgnoredValue(const T& /* ignored */) {}  // NOLINT(runtime/explicit)
+};
+
+// Appends the user-supplied message to the Google-Test-generated message.
+GTEST_API_ std::string AppendUserMessage(
+    const std::string& gtest_msg, const Message& user_msg);
+
+#if GTEST_HAS_EXCEPTIONS
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4275 \
+/* an exported class was derived from a class that was not exported */)
+
+// This exception is thrown by (and only by) a failed Google Test
+// assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions
+// are enabled).  We derive it from std::runtime_error, which is for
+// errors presumably detectable only at run time.  Since
+// std::runtime_error inherits from std::exception, many testing
+// frameworks know how to extract and print the message inside it.
+class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error {
+ public:
+  explicit GoogleTestFailureException(const TestPartResult& failure);
+};
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4275
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+namespace edit_distance {
+// Returns the optimal edits to go from 'left' to 'right'.
+// All edits cost the same, with replace having lower priority than
+// add/remove.
+// Simple implementation of the Wagner-Fischer algorithm.
+// See http://en.wikipedia.org/wiki/Wagner-Fischer_algorithm
+enum EditType { kMatch, kAdd, kRemove, kReplace };
+GTEST_API_ std::vector<EditType> CalculateOptimalEdits(
+    const std::vector<size_t>& left, const std::vector<size_t>& right);
+
+// Same as above, but the input is represented as strings.
+GTEST_API_ std::vector<EditType> CalculateOptimalEdits(
+    const std::vector<std::string>& left,
+    const std::vector<std::string>& right);
+
+// Create a diff of the input strings in Unified diff format.
+GTEST_API_ std::string CreateUnifiedDiff(const std::vector<std::string>& left,
+                                         const std::vector<std::string>& right,
+                                         size_t context = 2);
+
+}  // namespace edit_distance
+
+// Calculate the diff between 'left' and 'right' and return it in unified diff
+// format.
+// If not null, stores in 'total_line_count' the total number of lines found
+// in left + right.
+GTEST_API_ std::string DiffStrings(const std::string& left,
+                                   const std::string& right,
+                                   size_t* total_line_count);
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings.  For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+//   expected_expression: "foo"
+//   actual_expression:   "bar"
+//   expected_value:      "5"
+//   actual_value:        "6"
+//
+// The ignoring_case parameter is true if and only if the assertion is a
+// *_STRCASEEQ*.  When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
+                                     const char* actual_expression,
+                                     const std::string& expected_value,
+                                     const std::string& actual_value,
+                                     bool ignoring_case);
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+GTEST_API_ std::string GetBoolAssertionFailureMessage(
+    const AssertionResult& assertion_result,
+    const char* expression_text,
+    const char* actual_predicate_value,
+    const char* expected_predicate_value);
+
+// This template class represents an IEEE floating-point number
+// (either single-precision or double-precision, depending on the
+// template parameters).
+//
+// The purpose of this class is to do more sophisticated number
+// comparison.  (Due to round-off error, etc, it's very unlikely that
+// two floating-points will be equal exactly.  Hence a naive
+// comparison by the == operation often doesn't work.)
+//
+// Format of IEEE floating-point:
+//
+//   The most-significant bit being the leftmost, an IEEE
+//   floating-point looks like
+//
+//     sign_bit exponent_bits fraction_bits
+//
+//   Here, sign_bit is a single bit that designates the sign of the
+//   number.
+//
+//   For float, there are 8 exponent bits and 23 fraction bits.
+//
+//   For double, there are 11 exponent bits and 52 fraction bits.
+//
+//   More details can be found at
+//   http://en.wikipedia.org/wiki/IEEE_floating-point_standard.
+//
+// Template parameter:
+//
+//   RawType: the raw floating-point type (either float or double)
+template <typename RawType>
+class FloatingPoint {
+ public:
+  // Defines the unsigned integer type that has the same size as the
+  // floating point number.
+  typedef typename TypeWithSize<sizeof(RawType)>::UInt Bits;
+
+  // Constants.
+
+  // # of bits in a number.
+  static const size_t kBitCount = 8*sizeof(RawType);
+
+  // # of fraction bits in a number.
+  static const size_t kFractionBitCount =
+    std::numeric_limits<RawType>::digits - 1;
+
+  // # of exponent bits in a number.
+  static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;
+
+  // The mask for the sign bit.
+  static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
+
+  // The mask for the fraction bits.
+  static const Bits kFractionBitMask =
+    ~static_cast<Bits>(0) >> (kExponentBitCount + 1);
+
+  // The mask for the exponent bits.
+  static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
+
+  // How many ULP's (Units in the Last Place) we want to tolerate when
+  // comparing two numbers.  The larger the value, the more error we
+  // allow.  A 0 value means that two numbers must be exactly the same
+  // to be considered equal.
+  //
+  // The maximum error of a single floating-point operation is 0.5
+  // units in the last place.  On Intel CPU's, all floating-point
+  // calculations are done with 80-bit precision, while double has 64
+  // bits.  Therefore, 4 should be enough for ordinary use.
+  //
+  // See the following article for more details on ULP:
+  // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
+  static const uint32_t kMaxUlps = 4;
+
+  // Constructs a FloatingPoint from a raw floating-point number.
+  //
+  // On an Intel CPU, passing a non-normalized NAN (Not a Number)
+  // around may change its bits, although the new value is guaranteed
+  // to be also a NAN.  Therefore, don't expect this constructor to
+  // preserve the bits in x when x is a NAN.
+  explicit FloatingPoint(const RawType& x) { u_.value_ = x; }
+
+  // Static methods
+
+  // Reinterprets a bit pattern as a floating-point number.
+  //
+  // This function is needed to test the AlmostEquals() method.
+  static RawType ReinterpretBits(const Bits bits) {
+    FloatingPoint fp(0);
+    fp.u_.bits_ = bits;
+    return fp.u_.value_;
+  }
+
+  // Returns the floating-point number that represent positive infinity.
+  static RawType Infinity() {
+    return ReinterpretBits(kExponentBitMask);
+  }
+
+  // Returns the maximum representable finite floating-point number.
+  static RawType Max();
+
+  // Non-static methods
+
+  // Returns the bits that represents this number.
+  const Bits &bits() const { return u_.bits_; }
+
+  // Returns the exponent bits of this number.
+  Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
+
+  // Returns the fraction bits of this number.
+  Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }
+
+  // Returns the sign bit of this number.
+  Bits sign_bit() const { return kSignBitMask & u_.bits_; }
+
+  // Returns true if and only if this is NAN (not a number).
+  bool is_nan() const {
+    // It's a NAN if the exponent bits are all ones and the fraction
+    // bits are not entirely zeros.
+    return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
+  }
+
+  // Returns true if and only if this number is at most kMaxUlps ULP's away
+  // from rhs.  In particular, this function:
+  //
+  //   - returns false if either number is (or both are) NAN.
+  //   - treats really large numbers as almost equal to infinity.
+  //   - thinks +0.0 and -0.0 are 0 DLP's apart.
+  bool AlmostEquals(const FloatingPoint& rhs) const {
+    // The IEEE standard says that any comparison operation involving
+    // a NAN must return false.
+    if (is_nan() || rhs.is_nan()) return false;
+
+    return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_)
+        <= kMaxUlps;
+  }
+
+ private:
+  // The data type used to store the actual floating-point number.
+  union FloatingPointUnion {
+    RawType value_;  // The raw floating-point number.
+    Bits bits_;      // The bits that represent the number.
+  };
+
+  // Converts an integer from the sign-and-magnitude representation to
+  // the biased representation.  More precisely, let N be 2 to the
+  // power of (kBitCount - 1), an integer x is represented by the
+  // unsigned number x + N.
+  //
+  // For instance,
+  //
+  //   -N + 1 (the most negative number representable using
+  //          sign-and-magnitude) is represented by 1;
+  //   0      is represented by N; and
+  //   N - 1  (the biggest number representable using
+  //          sign-and-magnitude) is represented by 2N - 1.
+  //
+  // Read http://en.wikipedia.org/wiki/Signed_number_representations
+  // for more details on signed number representations.
+  static Bits SignAndMagnitudeToBiased(const Bits &sam) {
+    if (kSignBitMask & sam) {
+      // sam represents a negative number.
+      return ~sam + 1;
+    } else {
+      // sam represents a positive number.
+      return kSignBitMask | sam;
+    }
+  }
+
+  // Given two numbers in the sign-and-magnitude representation,
+  // returns the distance between them as an unsigned number.
+  static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
+                                                     const Bits &sam2) {
+    const Bits biased1 = SignAndMagnitudeToBiased(sam1);
+    const Bits biased2 = SignAndMagnitudeToBiased(sam2);
+    return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
+  }
+
+  FloatingPointUnion u_;
+};
+
+// We cannot use std::numeric_limits<T>::max() as it clashes with the max()
+// macro defined by <windows.h>.
+template <>
+inline float FloatingPoint<float>::Max() { return FLT_MAX; }
+template <>
+inline double FloatingPoint<double>::Max() { return DBL_MAX; }
+
+// Typedefs the instances of the FloatingPoint template class that we
+// care to use.
+typedef FloatingPoint<float> Float;
+typedef FloatingPoint<double> Double;
+
+// In order to catch the mistake of putting tests that use different
+// test fixture classes in the same test suite, we need to assign
+// unique IDs to fixture classes and compare them.  The TypeId type is
+// used to hold such IDs.  The user should treat TypeId as an opaque
+// type: the only operation allowed on TypeId values is to compare
+// them for equality using the == operator.
+typedef const void* TypeId;
+
+template <typename T>
+class TypeIdHelper {
+ public:
+  // dummy_ must not have a const type.  Otherwise an overly eager
+  // compiler (e.g. MSVC 7.1 & 8.0) may try to merge
+  // TypeIdHelper<T>::dummy_ for different Ts as an "optimization".
+  static bool dummy_;
+};
+
+template <typename T>
+bool TypeIdHelper<T>::dummy_ = false;
+
+// GetTypeId<T>() returns the ID of type T.  Different values will be
+// returned for different types.  Calling the function twice with the
+// same type argument is guaranteed to return the same ID.
+template <typename T>
+TypeId GetTypeId() {
+  // The compiler is required to allocate a different
+  // TypeIdHelper<T>::dummy_ variable for each T used to instantiate
+  // the template.  Therefore, the address of dummy_ is guaranteed to
+  // be unique.
+  return &(TypeIdHelper<T>::dummy_);
+}
+
+// Returns the type ID of ::testing::Test.  Always call this instead
+// of GetTypeId< ::testing::Test>() to get the type ID of
+// ::testing::Test, as the latter may give the wrong result due to a
+// suspected linker bug when compiling Google Test as a Mac OS X
+// framework.
+GTEST_API_ TypeId GetTestTypeId();
+
+// Defines the abstract factory interface that creates instances
+// of a Test object.
+class TestFactoryBase {
+ public:
+  virtual ~TestFactoryBase() {}
+
+  // Creates a test instance to run. The instance is both created and destroyed
+  // within TestInfoImpl::Run()
+  virtual Test* CreateTest() = 0;
+
+ protected:
+  TestFactoryBase() {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase);
+};
+
+// This class provides implementation of TeastFactoryBase interface.
+// It is used in TEST and TEST_F macros.
+template <class TestClass>
+class TestFactoryImpl : public TestFactoryBase {
+ public:
+  Test* CreateTest() override { return new TestClass; }
+};
+
+#if GTEST_OS_WINDOWS
+
+// Predicate-formatters for implementing the HRESULT checking macros
+// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}
+// We pass a long instead of HRESULT to avoid causing an
+// include dependency for the HRESULT type.
+GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr,
+                                            long hr);  // NOLINT
+GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
+                                            long hr);  // NOLINT
+
+#endif  // GTEST_OS_WINDOWS
+
+// Types of SetUpTestSuite() and TearDownTestSuite() functions.
+using SetUpTestSuiteFunc = void (*)();
+using TearDownTestSuiteFunc = void (*)();
+
+struct CodeLocation {
+  CodeLocation(const std::string& a_file, int a_line)
+      : file(a_file), line(a_line) {}
+
+  std::string file;
+  int line;
+};
+
+//  Helper to identify which setup function for TestCase / TestSuite to call.
+//  Only one function is allowed, either TestCase or TestSute but not both.
+
+// Utility functions to help SuiteApiResolver
+using SetUpTearDownSuiteFuncType = void (*)();
+
+inline SetUpTearDownSuiteFuncType GetNotDefaultOrNull(
+    SetUpTearDownSuiteFuncType a, SetUpTearDownSuiteFuncType def) {
+  return a == def ? nullptr : a;
+}
+
+template <typename T>
+//  Note that SuiteApiResolver inherits from T because
+//  SetUpTestSuite()/TearDownTestSuite() could be protected. Ths way
+//  SuiteApiResolver can access them.
+struct SuiteApiResolver : T {
+  // testing::Test is only forward declared at this point. So we make it a
+  // dependend class for the compiler to be OK with it.
+  using Test =
+      typename std::conditional<sizeof(T) != 0, ::testing::Test, void>::type;
+
+  static SetUpTearDownSuiteFuncType GetSetUpCaseOrSuite(const char* filename,
+                                                        int line_num) {
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+    SetUpTearDownSuiteFuncType test_case_fp =
+        GetNotDefaultOrNull(&T::SetUpTestCase, &Test::SetUpTestCase);
+    SetUpTearDownSuiteFuncType test_suite_fp =
+        GetNotDefaultOrNull(&T::SetUpTestSuite, &Test::SetUpTestSuite);
+
+    GTEST_CHECK_(!test_case_fp || !test_suite_fp)
+        << "Test can not provide both SetUpTestSuite and SetUpTestCase, please "
+           "make sure there is only one present at "
+        << filename << ":" << line_num;
+
+    return test_case_fp != nullptr ? test_case_fp : test_suite_fp;
+#else
+    (void)(filename);
+    (void)(line_num);
+    return &T::SetUpTestSuite;
+#endif
+  }
+
+  static SetUpTearDownSuiteFuncType GetTearDownCaseOrSuite(const char* filename,
+                                                           int line_num) {
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+    SetUpTearDownSuiteFuncType test_case_fp =
+        GetNotDefaultOrNull(&T::TearDownTestCase, &Test::TearDownTestCase);
+    SetUpTearDownSuiteFuncType test_suite_fp =
+        GetNotDefaultOrNull(&T::TearDownTestSuite, &Test::TearDownTestSuite);
+
+    GTEST_CHECK_(!test_case_fp || !test_suite_fp)
+        << "Test can not provide both TearDownTestSuite and TearDownTestCase,"
+           " please make sure there is only one present at"
+        << filename << ":" << line_num;
+
+    return test_case_fp != nullptr ? test_case_fp : test_suite_fp;
+#else
+    (void)(filename);
+    (void)(line_num);
+    return &T::TearDownTestSuite;
+#endif
+  }
+};
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+//   test_suite_name:  name of the test suite
+//   name:             name of the test
+//   type_param:       the name of the test's type parameter, or NULL if
+//                     this is not a typed or a type-parameterized test.
+//   value_param:      text representation of the test's value parameter,
+//                     or NULL if this is not a type-parameterized test.
+//   code_location:    code location where the test is defined
+//   fixture_class_id: ID of the test fixture class
+//   set_up_tc:        pointer to the function that sets up the test suite
+//   tear_down_tc:     pointer to the function that tears down the test suite
+//   factory:          pointer to the factory that creates a test object.
+//                     The newly created TestInfo instance will assume
+//                     ownership of the factory object.
+GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
+    const char* test_suite_name, const char* name, const char* type_param,
+    const char* value_param, CodeLocation code_location,
+    TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc,
+    TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory);
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false.  None of pstr, *pstr, and prefix can be NULL.
+GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr);
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+// State of the definition of a type-parameterized test suite.
+class GTEST_API_ TypedTestSuitePState {
+ public:
+  TypedTestSuitePState() : registered_(false) {}
+
+  // Adds the given test name to defined_test_names_ and return true
+  // if the test suite hasn't been registered; otherwise aborts the
+  // program.
+  bool AddTestName(const char* file, int line, const char* case_name,
+                   const char* test_name) {
+    if (registered_) {
+      fprintf(stderr,
+              "%s Test %s must be defined before "
+              "REGISTER_TYPED_TEST_SUITE_P(%s, ...).\n",
+              FormatFileLocation(file, line).c_str(), test_name, case_name);
+      fflush(stderr);
+      posix::Abort();
+    }
+    registered_tests_.insert(
+        ::std::make_pair(test_name, CodeLocation(file, line)));
+    return true;
+  }
+
+  bool TestExists(const std::string& test_name) const {
+    return registered_tests_.count(test_name) > 0;
+  }
+
+  const CodeLocation& GetCodeLocation(const std::string& test_name) const {
+    RegisteredTestsMap::const_iterator it = registered_tests_.find(test_name);
+    GTEST_CHECK_(it != registered_tests_.end());
+    return it->second;
+  }
+
+  // Verifies that registered_tests match the test names in
+  // defined_test_names_; returns registered_tests if successful, or
+  // aborts the program otherwise.
+  const char* VerifyRegisteredTestNames(const char* test_suite_name,
+                                        const char* file, int line,
+                                        const char* registered_tests);
+
+ private:
+  typedef ::std::map<std::string, CodeLocation> RegisteredTestsMap;
+
+  bool registered_;
+  RegisteredTestsMap registered_tests_;
+};
+
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+using TypedTestCasePState = TypedTestSuitePState;
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+// Skips to the first non-space char after the first comma in 'str';
+// returns NULL if no comma is found in 'str'.
+inline const char* SkipComma(const char* str) {
+  const char* comma = strchr(str, ',');
+  if (comma == nullptr) {
+    return nullptr;
+  }
+  while (IsSpace(*(++comma))) {}
+  return comma;
+}
+
+// Returns the prefix of 'str' before the first comma in it; returns
+// the entire string if it contains no comma.
+inline std::string GetPrefixUntilComma(const char* str) {
+  const char* comma = strchr(str, ',');
+  return comma == nullptr ? str : std::string(str, comma);
+}
+
+// Splits a given string on a given delimiter, populating a given
+// vector with the fields.
+void SplitString(const ::std::string& str, char delimiter,
+                 ::std::vector< ::std::string>* dest);
+
+// The default argument to the template below for the case when the user does
+// not provide a name generator.
+struct DefaultNameGenerator {
+  template <typename T>
+  static std::string GetName(int i) {
+    return StreamableToString(i);
+  }
+};
+
+template <typename Provided = DefaultNameGenerator>
+struct NameGeneratorSelector {
+  typedef Provided type;
+};
+
+template <typename NameGenerator>
+void GenerateNamesRecursively(internal::None, std::vector<std::string>*, int) {}
+
+template <typename NameGenerator, typename Types>
+void GenerateNamesRecursively(Types, std::vector<std::string>* result, int i) {
+  result->push_back(NameGenerator::template GetName<typename Types::Head>(i));
+  GenerateNamesRecursively<NameGenerator>(typename Types::Tail(), result,
+                                          i + 1);
+}
+
+template <typename NameGenerator, typename Types>
+std::vector<std::string> GenerateNames() {
+  std::vector<std::string> result;
+  GenerateNamesRecursively<NameGenerator>(Types(), &result, 0);
+  return result;
+}
+
+// TypeParameterizedTest<Fixture, TestSel, Types>::Register()
+// registers a list of type-parameterized tests with Google Test.  The
+// return value is insignificant - we just need to return something
+// such that we can call this function in a namespace scope.
+//
+// Implementation note: The GTEST_TEMPLATE_ macro declares a template
+// template parameter.  It's defined in gtest-type-util.h.
+template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
+class TypeParameterizedTest {
+ public:
+  // 'index' is the index of the test in the type list 'Types'
+  // specified in INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, TestSuite,
+  // Types).  Valid values for 'index' are [0, N - 1] where N is the
+  // length of Types.
+  static bool Register(const char* prefix, const CodeLocation& code_location,
+                       const char* case_name, const char* test_names, int index,
+                       const std::vector<std::string>& type_names =
+                           GenerateNames<DefaultNameGenerator, Types>()) {
+    typedef typename Types::Head Type;
+    typedef Fixture<Type> FixtureClass;
+    typedef typename GTEST_BIND_(TestSel, Type) TestClass;
+
+    // First, registers the first type-parameterized test in the type
+    // list.
+    MakeAndRegisterTestInfo(
+        (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name +
+         "/" + type_names[static_cast<size_t>(index)])
+            .c_str(),
+        StripTrailingSpaces(GetPrefixUntilComma(test_names)).c_str(),
+        GetTypeName<Type>().c_str(),
+        nullptr,  // No value parameter.
+        code_location, GetTypeId<FixtureClass>(),
+        SuiteApiResolver<TestClass>::GetSetUpCaseOrSuite(
+            code_location.file.c_str(), code_location.line),
+        SuiteApiResolver<TestClass>::GetTearDownCaseOrSuite(
+            code_location.file.c_str(), code_location.line),
+        new TestFactoryImpl<TestClass>);
+
+    // Next, recurses (at compile time) with the tail of the type list.
+    return TypeParameterizedTest<Fixture, TestSel,
+                                 typename Types::Tail>::Register(prefix,
+                                                                 code_location,
+                                                                 case_name,
+                                                                 test_names,
+                                                                 index + 1,
+                                                                 type_names);
+  }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, class TestSel>
+class TypeParameterizedTest<Fixture, TestSel, internal::None> {
+ public:
+  static bool Register(const char* /*prefix*/, const CodeLocation&,
+                       const char* /*case_name*/, const char* /*test_names*/,
+                       int /*index*/,
+                       const std::vector<std::string>& =
+                           std::vector<std::string>() /*type_names*/) {
+    return true;
+  }
+};
+
+GTEST_API_ void RegisterTypeParameterizedTestSuite(const char* test_suite_name,
+                                                   CodeLocation code_location);
+GTEST_API_ void RegisterTypeParameterizedTestSuiteInstantiation(
+    const char* case_name);
+
+// TypeParameterizedTestSuite<Fixture, Tests, Types>::Register()
+// registers *all combinations* of 'Tests' and 'Types' with Google
+// Test.  The return value is insignificant - we just need to return
+// something such that we can call this function in a namespace scope.
+template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
+class TypeParameterizedTestSuite {
+ public:
+  static bool Register(const char* prefix, CodeLocation code_location,
+                       const TypedTestSuitePState* state, const char* case_name,
+                       const char* test_names,
+                       const std::vector<std::string>& type_names =
+                           GenerateNames<DefaultNameGenerator, Types>()) {
+    RegisterTypeParameterizedTestSuiteInstantiation(case_name);
+    std::string test_name = StripTrailingSpaces(
+        GetPrefixUntilComma(test_names));
+    if (!state->TestExists(test_name)) {
+      fprintf(stderr, "Failed to get code location for test %s.%s at %s.",
+              case_name, test_name.c_str(),
+              FormatFileLocation(code_location.file.c_str(),
+                                 code_location.line).c_str());
+      fflush(stderr);
+      posix::Abort();
+    }
+    const CodeLocation& test_location = state->GetCodeLocation(test_name);
+
+    typedef typename Tests::Head Head;
+
+    // First, register the first test in 'Test' for each type in 'Types'.
+    TypeParameterizedTest<Fixture, Head, Types>::Register(
+        prefix, test_location, case_name, test_names, 0, type_names);
+
+    // Next, recurses (at compile time) with the tail of the test list.
+    return TypeParameterizedTestSuite<Fixture, typename Tests::Tail,
+                                      Types>::Register(prefix, code_location,
+                                                       state, case_name,
+                                                       SkipComma(test_names),
+                                                       type_names);
+  }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, typename Types>
+class TypeParameterizedTestSuite<Fixture, internal::None, Types> {
+ public:
+  static bool Register(const char* /*prefix*/, const CodeLocation&,
+                       const TypedTestSuitePState* /*state*/,
+                       const char* /*case_name*/, const char* /*test_names*/,
+                       const std::vector<std::string>& =
+                           std::vector<std::string>() /*type_names*/) {
+    return true;
+  }
+};
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+GTEST_API_ std::string GetCurrentOsStackTraceExceptTop(
+    UnitTest* unit_test, int skip_count);
+
+// Helpers for suppressing warnings on unreachable code or constant
+// condition.
+
+// Always returns true.
+GTEST_API_ bool AlwaysTrue();
+
+// Always returns false.
+inline bool AlwaysFalse() { return !AlwaysTrue(); }
+
+// Helper for suppressing false warning from Clang on a const char*
+// variable declared in a conditional expression always being NULL in
+// the else branch.
+struct GTEST_API_ ConstCharPtr {
+  ConstCharPtr(const char* str) : value(str) {}
+  operator bool() const { return true; }
+  const char* value;
+};
+
+// Helper for declaring std::string within 'if' statement
+// in pre C++17 build environment.
+struct TrueWithString {
+  TrueWithString() = default;
+  explicit TrueWithString(const char* str) : value(str) {}
+  explicit TrueWithString(const std::string& str) : value(str) {}
+  explicit operator bool() const { return true; }
+  std::string value;
+};
+
+// A simple Linear Congruential Generator for generating random
+// numbers with a uniform distribution.  Unlike rand() and srand(), it
+// doesn't use global state (and therefore can't interfere with user
+// code).  Unlike rand_r(), it's portable.  An LCG isn't very random,
+// but it's good enough for our purposes.
+class GTEST_API_ Random {
+ public:
+  static const uint32_t kMaxRange = 1u << 31;
+
+  explicit Random(uint32_t seed) : state_(seed) {}
+
+  void Reseed(uint32_t seed) { state_ = seed; }
+
+  // Generates a random number from [0, range).  Crashes if 'range' is
+  // 0 or greater than kMaxRange.
+  uint32_t Generate(uint32_t range);
+
+ private:
+  uint32_t state_;
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
+};
+
+// Turns const U&, U&, const U, and U all into U.
+#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
+  typename std::remove_const<typename std::remove_reference<T>::type>::type
+
+// HasDebugStringAndShortDebugString<T>::value is a compile-time bool constant
+// that's true if and only if T has methods DebugString() and ShortDebugString()
+// that return std::string.
+template <typename T>
+class HasDebugStringAndShortDebugString {
+ private:
+  template <typename C>
+  static auto CheckDebugString(C*) -> typename std::is_same<
+      std::string, decltype(std::declval<const C>().DebugString())>::type;
+  template <typename>
+  static std::false_type CheckDebugString(...);
+
+  template <typename C>
+  static auto CheckShortDebugString(C*) -> typename std::is_same<
+      std::string, decltype(std::declval<const C>().ShortDebugString())>::type;
+  template <typename>
+  static std::false_type CheckShortDebugString(...);
+
+  using HasDebugStringType = decltype(CheckDebugString<T>(nullptr));
+  using HasShortDebugStringType = decltype(CheckShortDebugString<T>(nullptr));
+
+ public:
+  static constexpr bool value =
+      HasDebugStringType::value && HasShortDebugStringType::value;
+};
+
+template <typename T>
+constexpr bool HasDebugStringAndShortDebugString<T>::value;
+
+// When the compiler sees expression IsContainerTest<C>(0), if C is an
+// STL-style container class, the first overload of IsContainerTest
+// will be viable (since both C::iterator* and C::const_iterator* are
+// valid types and NULL can be implicitly converted to them).  It will
+// be picked over the second overload as 'int' is a perfect match for
+// the type of argument 0.  If C::iterator or C::const_iterator is not
+// a valid type, the first overload is not viable, and the second
+// overload will be picked.  Therefore, we can determine whether C is
+// a container class by checking the type of IsContainerTest<C>(0).
+// The value of the expression is insignificant.
+//
+// In C++11 mode we check the existence of a const_iterator and that an
+// iterator is properly implemented for the container.
+//
+// For pre-C++11 that we look for both C::iterator and C::const_iterator.
+// The reason is that C++ injects the name of a class as a member of the
+// class itself (e.g. you can refer to class iterator as either
+// 'iterator' or 'iterator::iterator').  If we look for C::iterator
+// only, for example, we would mistakenly think that a class named
+// iterator is an STL container.
+//
+// Also note that the simpler approach of overloading
+// IsContainerTest(typename C::const_iterator*) and
+// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
+typedef int IsContainer;
+template <class C,
+          class Iterator = decltype(::std::declval<const C&>().begin()),
+          class = decltype(::std::declval<const C&>().end()),
+          class = decltype(++::std::declval<Iterator&>()),
+          class = decltype(*::std::declval<Iterator>()),
+          class = typename C::const_iterator>
+IsContainer IsContainerTest(int /* dummy */) {
+  return 0;
+}
+
+typedef char IsNotContainer;
+template <class C>
+IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
+
+// Trait to detect whether a type T is a hash table.
+// The heuristic used is that the type contains an inner type `hasher` and does
+// not contain an inner type `reverse_iterator`.
+// If the container is iterable in reverse, then order might actually matter.
+template <typename T>
+struct IsHashTable {
+ private:
+  template <typename U>
+  static char test(typename U::hasher*, typename U::reverse_iterator*);
+  template <typename U>
+  static int test(typename U::hasher*, ...);
+  template <typename U>
+  static char test(...);
+
+ public:
+  static const bool value = sizeof(test<T>(nullptr, nullptr)) == sizeof(int);
+};
+
+template <typename T>
+const bool IsHashTable<T>::value;
+
+template <typename C,
+          bool = sizeof(IsContainerTest<C>(0)) == sizeof(IsContainer)>
+struct IsRecursiveContainerImpl;
+
+template <typename C>
+struct IsRecursiveContainerImpl<C, false> : public std::false_type {};
+
+// Since the IsRecursiveContainerImpl depends on the IsContainerTest we need to
+// obey the same inconsistencies as the IsContainerTest, namely check if
+// something is a container is relying on only const_iterator in C++11 and
+// is relying on both const_iterator and iterator otherwise
+template <typename C>
+struct IsRecursiveContainerImpl<C, true> {
+  using value_type = decltype(*std::declval<typename C::const_iterator>());
+  using type =
+      std::is_same<typename std::remove_const<
+                       typename std::remove_reference<value_type>::type>::type,
+                   C>;
+};
+
+// IsRecursiveContainer<Type> is a unary compile-time predicate that
+// evaluates whether C is a recursive container type. A recursive container
+// type is a container type whose value_type is equal to the container type
+// itself. An example for a recursive container type is
+// boost::filesystem::path, whose iterator has a value_type that is equal to
+// boost::filesystem::path.
+template <typename C>
+struct IsRecursiveContainer : public IsRecursiveContainerImpl<C>::type {};
+
+// Utilities for native arrays.
+
+// ArrayEq() compares two k-dimensional native arrays using the
+// elements' operator==, where k can be any integer >= 0.  When k is
+// 0, ArrayEq() degenerates into comparing a single pair of values.
+
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
+  return internal::ArrayEq(lhs, N, rhs);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous ArrayEq() function, arrays with different sizes would
+// lead to different copies of the template code.
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
+  for (size_t i = 0; i != size; i++) {
+    if (!internal::ArrayEq(lhs[i], rhs[i]))
+      return false;
+  }
+  return true;
+}
+
+// Finds the first element in the iterator range [begin, end) that
+// equals elem.  Element may be a native array type itself.
+template <typename Iter, typename Element>
+Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
+  for (Iter it = begin; it != end; ++it) {
+    if (internal::ArrayEq(*it, elem))
+      return it;
+  }
+  return end;
+}
+
+// CopyArray() copies a k-dimensional native array using the elements'
+// operator=, where k can be any integer >= 0.  When k is 0,
+// CopyArray() degenerates into copying a single value.
+
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline void CopyArray(const T& from, U* to) { *to = from; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline void CopyArray(const T(&from)[N], U(*to)[N]) {
+  internal::CopyArray(from, N, *to);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous CopyArray() function, arrays with different sizes
+// would lead to different copies of the template code.
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to) {
+  for (size_t i = 0; i != size; i++) {
+    internal::CopyArray(from[i], to + i);
+  }
+}
+
+// The relation between an NativeArray object (see below) and the
+// native array it represents.
+// We use 2 different structs to allow non-copyable types to be used, as long
+// as RelationToSourceReference() is passed.
+struct RelationToSourceReference {};
+struct RelationToSourceCopy {};
+
+// Adapts a native array to a read-only STL-style container.  Instead
+// of the complete STL container concept, this adaptor only implements
+// members useful for Google Mock's container matchers.  New members
+// should be added as needed.  To simplify the implementation, we only
+// support Element being a raw type (i.e. having no top-level const or
+// reference modifier).  It's the client's responsibility to satisfy
+// this requirement.  Element can be an array type itself (hence
+// multi-dimensional arrays are supported).
+template <typename Element>
+class NativeArray {
+ public:
+  // STL-style container typedefs.
+  typedef Element value_type;
+  typedef Element* iterator;
+  typedef const Element* const_iterator;
+
+  // Constructs from a native array. References the source.
+  NativeArray(const Element* array, size_t count, RelationToSourceReference) {
+    InitRef(array, count);
+  }
+
+  // Constructs from a native array. Copies the source.
+  NativeArray(const Element* array, size_t count, RelationToSourceCopy) {
+    InitCopy(array, count);
+  }
+
+  // Copy constructor.
+  NativeArray(const NativeArray& rhs) {
+    (this->*rhs.clone_)(rhs.array_, rhs.size_);
+  }
+
+  ~NativeArray() {
+    if (clone_ != &NativeArray::InitRef)
+      delete[] array_;
+  }
+
+  // STL-style container methods.
+  size_t size() const { return size_; }
+  const_iterator begin() const { return array_; }
+  const_iterator end() const { return array_ + size_; }
+  bool operator==(const NativeArray& rhs) const {
+    return size() == rhs.size() &&
+        ArrayEq(begin(), size(), rhs.begin());
+  }
+
+ private:
+  static_assert(!std::is_const<Element>::value, "Type must not be const");
+  static_assert(!std::is_reference<Element>::value,
+                "Type must not be a reference");
+
+  // Initializes this object with a copy of the input.
+  void InitCopy(const Element* array, size_t a_size) {
+    Element* const copy = new Element[a_size];
+    CopyArray(array, a_size, copy);
+    array_ = copy;
+    size_ = a_size;
+    clone_ = &NativeArray::InitCopy;
+  }
+
+  // Initializes this object with a reference of the input.
+  void InitRef(const Element* array, size_t a_size) {
+    array_ = array;
+    size_ = a_size;
+    clone_ = &NativeArray::InitRef;
+  }
+
+  const Element* array_;
+  size_t size_;
+  void (NativeArray::*clone_)(const Element*, size_t);
+};
+
+// Backport of std::index_sequence.
+template <size_t... Is>
+struct IndexSequence {
+  using type = IndexSequence;
+};
+
+// Double the IndexSequence, and one if plus_one is true.
+template <bool plus_one, typename T, size_t sizeofT>
+struct DoubleSequence;
+template <size_t... I, size_t sizeofT>
+struct DoubleSequence<true, IndexSequence<I...>, sizeofT> {
+  using type = IndexSequence<I..., (sizeofT + I)..., 2 * sizeofT>;
+};
+template <size_t... I, size_t sizeofT>
+struct DoubleSequence<false, IndexSequence<I...>, sizeofT> {
+  using type = IndexSequence<I..., (sizeofT + I)...>;
+};
+
+// Backport of std::make_index_sequence.
+// It uses O(ln(N)) instantiation depth.
+template <size_t N>
+struct MakeIndexSequenceImpl
+    : DoubleSequence<N % 2 == 1, typename MakeIndexSequenceImpl<N / 2>::type,
+                     N / 2>::type {};
+
+template <>
+struct MakeIndexSequenceImpl<0> : IndexSequence<> {};
+
+template <size_t N>
+using MakeIndexSequence = typename MakeIndexSequenceImpl<N>::type;
+
+template <typename... T>
+using IndexSequenceFor = typename MakeIndexSequence<sizeof...(T)>::type;
+
+template <size_t>
+struct Ignore {
+  Ignore(...);  // NOLINT
+};
+
+template <typename>
+struct ElemFromListImpl;
+template <size_t... I>
+struct ElemFromListImpl<IndexSequence<I...>> {
+  // We make Ignore a template to solve a problem with MSVC.
+  // A non-template Ignore would work fine with `decltype(Ignore(I))...`, but
+  // MSVC doesn't understand how to deal with that pack expansion.
+  // Use `0 * I` to have a single instantiation of Ignore.
+  template <typename R>
+  static R Apply(Ignore<0 * I>..., R (*)(), ...);
+};
+
+template <size_t N, typename... T>
+struct ElemFromList {
+  using type =
+      decltype(ElemFromListImpl<typename MakeIndexSequence<N>::type>::Apply(
+          static_cast<T (*)()>(nullptr)...));
+};
+
+struct FlatTupleConstructTag {};
+
+template <typename... T>
+class FlatTuple;
+
+template <typename Derived, size_t I>
+struct FlatTupleElemBase;
+
+template <typename... T, size_t I>
+struct FlatTupleElemBase<FlatTuple<T...>, I> {
+  using value_type = typename ElemFromList<I, T...>::type;
+  FlatTupleElemBase() = default;
+  template <typename Arg>
+  explicit FlatTupleElemBase(FlatTupleConstructTag, Arg&& t)
+      : value(std::forward<Arg>(t)) {}
+  value_type value;
+};
+
+template <typename Derived, typename Idx>
+struct FlatTupleBase;
+
+template <size_t... Idx, typename... T>
+struct FlatTupleBase<FlatTuple<T...>, IndexSequence<Idx...>>
+    : FlatTupleElemBase<FlatTuple<T...>, Idx>... {
+  using Indices = IndexSequence<Idx...>;
+  FlatTupleBase() = default;
+  template <typename... Args>
+  explicit FlatTupleBase(FlatTupleConstructTag, Args&&... args)
+      : FlatTupleElemBase<FlatTuple<T...>, Idx>(FlatTupleConstructTag{},
+                                                std::forward<Args>(args))... {}
+
+  template <size_t I>
+  const typename ElemFromList<I, T...>::type& Get() const {
+    return FlatTupleElemBase<FlatTuple<T...>, I>::value;
+  }
+
+  template <size_t I>
+  typename ElemFromList<I, T...>::type& Get() {
+    return FlatTupleElemBase<FlatTuple<T...>, I>::value;
+  }
+
+  template <typename F>
+  auto Apply(F&& f) -> decltype(std::forward<F>(f)(this->Get<Idx>()...)) {
+    return std::forward<F>(f)(Get<Idx>()...);
+  }
+
+  template <typename F>
+  auto Apply(F&& f) const -> decltype(std::forward<F>(f)(this->Get<Idx>()...)) {
+    return std::forward<F>(f)(Get<Idx>()...);
+  }
+};
+
+// Analog to std::tuple but with different tradeoffs.
+// This class minimizes the template instantiation depth, thus allowing more
+// elements than std::tuple would. std::tuple has been seen to require an
+// instantiation depth of more than 10x the number of elements in some
+// implementations.
+// FlatTuple and ElemFromList are not recursive and have a fixed depth
+// regardless of T...
+// MakeIndexSequence, on the other hand, it is recursive but with an
+// instantiation depth of O(ln(N)).
+template <typename... T>
+class FlatTuple
+    : private FlatTupleBase<FlatTuple<T...>,
+                            typename MakeIndexSequence<sizeof...(T)>::type> {
+  using Indices = typename FlatTupleBase<
+      FlatTuple<T...>, typename MakeIndexSequence<sizeof...(T)>::type>::Indices;
+
+ public:
+  FlatTuple() = default;
+  template <typename... Args>
+  explicit FlatTuple(FlatTupleConstructTag tag, Args&&... args)
+      : FlatTuple::FlatTupleBase(tag, std::forward<Args>(args)...) {}
+
+  using FlatTuple::FlatTupleBase::Apply;
+  using FlatTuple::FlatTupleBase::Get;
+};
+
+// Utility functions to be called with static_assert to induce deprecation
+// warnings.
+GTEST_INTERNAL_DEPRECATED(
+    "INSTANTIATE_TEST_CASE_P is deprecated, please use "
+    "INSTANTIATE_TEST_SUITE_P")
+constexpr bool InstantiateTestCase_P_IsDeprecated() { return true; }
+
+GTEST_INTERNAL_DEPRECATED(
+    "TYPED_TEST_CASE_P is deprecated, please use "
+    "TYPED_TEST_SUITE_P")
+constexpr bool TypedTestCase_P_IsDeprecated() { return true; }
+
+GTEST_INTERNAL_DEPRECATED(
+    "TYPED_TEST_CASE is deprecated, please use "
+    "TYPED_TEST_SUITE")
+constexpr bool TypedTestCaseIsDeprecated() { return true; }
+
+GTEST_INTERNAL_DEPRECATED(
+    "REGISTER_TYPED_TEST_CASE_P is deprecated, please use "
+    "REGISTER_TYPED_TEST_SUITE_P")
+constexpr bool RegisterTypedTestCase_P_IsDeprecated() { return true; }
+
+GTEST_INTERNAL_DEPRECATED(
+    "INSTANTIATE_TYPED_TEST_CASE_P is deprecated, please use "
+    "INSTANTIATE_TYPED_TEST_SUITE_P")
+constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; }
+
+}  // namespace internal
+}  // namespace testing
+
+namespace std {
+// Some standard library implementations use `struct tuple_size` and some use
+// `class tuple_size`. Clang warns about the mismatch.
+// https://reviews.llvm.org/D55466
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmismatched-tags"
+#endif
+template <typename... Ts>
+struct tuple_size<testing::internal::FlatTuple<Ts...>>
+    : std::integral_constant<size_t, sizeof...(Ts)> {};
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+}  // namespace std
+
+#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
+  ::testing::internal::AssertHelper(result_type, file, line, message) \
+    = ::testing::Message()
+
+#define GTEST_MESSAGE_(message, result_type) \
+  GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
+
+#define GTEST_FATAL_FAILURE_(message) \
+  return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
+
+#define GTEST_NONFATAL_FAILURE_(message) \
+  GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
+
+#define GTEST_SUCCESS_(message) \
+  GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess)
+
+#define GTEST_SKIP_(message) \
+  return GTEST_MESSAGE_(message, ::testing::TestPartResult::kSkip)
+
+// Suppress MSVC warning 4072 (unreachable code) for the code following
+// statement if it returns or throws (or doesn't return or throw in some
+// situations).
+// NOTE: The "else" is important to keep this expansion to prevent a top-level
+// "else" from attaching to our "if".
+#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
+  if (::testing::internal::AlwaysTrue()) {                        \
+    statement;                                                    \
+  } else                     /* NOLINT */                         \
+    static_assert(true, "")  // User must have a semicolon after expansion.
+
+#if GTEST_HAS_EXCEPTIONS
+
+namespace testing {
+namespace internal {
+
+class NeverThrown {
+ public:
+  const char* what() const noexcept {
+    return "this exception should never be thrown";
+  }
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#if GTEST_HAS_RTTI
+
+#define GTEST_EXCEPTION_TYPE_(e) ::testing::internal::GetTypeName(typeid(e))
+
+#else  // GTEST_HAS_RTTI
+
+#define GTEST_EXCEPTION_TYPE_(e) \
+  std::string { "an std::exception-derived error" }
+
+#endif  // GTEST_HAS_RTTI
+
+#define GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception)   \
+  catch (typename std::conditional<                                            \
+         std::is_same<typename std::remove_cv<typename std::remove_reference<  \
+                          expected_exception>::type>::type,                    \
+                      std::exception>::value,                                  \
+         const ::testing::internal::NeverThrown&, const std::exception&>::type \
+             e) {                                                              \
+    gtest_msg.value = "Expected: " #statement                                  \
+                      " throws an exception of type " #expected_exception      \
+                      ".\n  Actual: it throws ";                               \
+    gtest_msg.value += GTEST_EXCEPTION_TYPE_(e);                               \
+    gtest_msg.value += " with description \"";                                 \
+    gtest_msg.value += e.what();                                               \
+    gtest_msg.value += "\".";                                                  \
+    goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__);                \
+  }
+
+#else  // GTEST_HAS_EXCEPTIONS
+
+#define GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception)
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+#define GTEST_TEST_THROW_(statement, expected_exception, fail)              \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                             \
+  if (::testing::internal::TrueWithString gtest_msg{}) {                    \
+    bool gtest_caught_expected = false;                                     \
+    try {                                                                   \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);            \
+    } catch (expected_exception const&) {                                   \
+      gtest_caught_expected = true;                                         \
+    }                                                                       \
+    GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception)    \
+    catch (...) {                                                           \
+      gtest_msg.value = "Expected: " #statement                             \
+                        " throws an exception of type " #expected_exception \
+                        ".\n  Actual: it throws a different type.";         \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__);           \
+    }                                                                       \
+    if (!gtest_caught_expected) {                                           \
+      gtest_msg.value = "Expected: " #statement                             \
+                        " throws an exception of type " #expected_exception \
+                        ".\n  Actual: it throws nothing.";                  \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__);           \
+    }                                                                       \
+  } else /*NOLINT*/                                                         \
+    GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__)                   \
+        : fail(gtest_msg.value.c_str())
+
+#if GTEST_HAS_EXCEPTIONS
+
+#define GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_()                \
+  catch (std::exception const& e) {                               \
+    gtest_msg.value = "it throws ";                               \
+    gtest_msg.value += GTEST_EXCEPTION_TYPE_(e);                  \
+    gtest_msg.value += " with description \"";                    \
+    gtest_msg.value += e.what();                                  \
+    gtest_msg.value += "\".";                                     \
+    goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
+  }
+
+#else  // GTEST_HAS_EXCEPTIONS
+
+#define GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_()
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+#define GTEST_TEST_NO_THROW_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::TrueWithString gtest_msg{}) { \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() \
+    catch (...) { \
+      gtest_msg.value = "it throws."; \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
+      fail(("Expected: " #statement " doesn't throw an exception.\n" \
+            "  Actual: " + gtest_msg.value).c_str())
+
+#define GTEST_TEST_ANY_THROW_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    bool gtest_caught_any = false; \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (...) { \
+      gtest_caught_any = true; \
+    } \
+    if (!gtest_caught_any) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \
+      fail("Expected: " #statement " throws an exception.\n" \
+           "  Actual: it doesn't.")
+
+
+// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
+// either a boolean expression or an AssertionResult. text is a textual
+// representation of expression as it was passed into the EXPECT_TRUE.
+#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (const ::testing::AssertionResult gtest_ar_ = \
+      ::testing::AssertionResult(expression)) \
+    ; \
+  else \
+    fail(::testing::internal::GetBoolAssertionFailureMessage(\
+        gtest_ar_, text, #actual, #expected).c_str())
+
+#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \
+      fail("Expected: " #statement " doesn't generate new fatal " \
+           "failures in the current thread.\n" \
+           "  Actual: it does.")
+
+// Expands to the name of the class that implements the given test.
+#define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
+  test_suite_name##_##test_name##_Test
+
+// Helper macro for defining tests.
+#define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id)      \
+  static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1,                \
+                "test_suite_name must not be empty");                         \
+  static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1,                      \
+                "test_name must not be empty");                               \
+  class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)                    \
+      : public parent_class {                                                 \
+   public:                                                                    \
+    GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() = default;           \
+    ~GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() override = default; \
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name,   \
+                                                           test_name));       \
+    GTEST_DISALLOW_MOVE_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name,   \
+                                                           test_name));       \
+                                                                              \
+   private:                                                                   \
+    void TestBody() override;                                                 \
+    static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;     \
+  };                                                                          \
+                                                                              \
+  ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name,          \
+                                                    test_name)::test_info_ =  \
+      ::testing::internal::MakeAndRegisterTestInfo(                           \
+          #test_suite_name, #test_name, nullptr, nullptr,                     \
+          ::testing::internal::CodeLocation(__FILE__, __LINE__), (parent_id), \
+          ::testing::internal::SuiteApiResolver<                              \
+              parent_class>::GetSetUpCaseOrSuite(__FILE__, __LINE__),         \
+          ::testing::internal::SuiteApiResolver<                              \
+              parent_class>::GetTearDownCaseOrSuite(__FILE__, __LINE__),      \
+          new ::testing::internal::TestFactoryImpl<GTEST_TEST_CLASS_NAME_(    \
+              test_suite_name, test_name)>);                                  \
+  void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This header file defines the public API for death tests.  It is
+// #included by gtest.h so a user doesn't need to include this
+// directly.
+// GOOGLETEST_CM0001 DO NOT DELETE
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This header file defines internal utilities needed for implementing
+// death tests.  They are subject to change without notice.
+// GOOGLETEST_CM0001 DO NOT DELETE
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The Google C++ Testing and Mocking Framework (Google Test)
+//
+// This file implements just enough of the matcher interface to allow
+// EXPECT_DEATH and friends to accept a matcher argument.
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
+
+#include <atomic>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <type_traits>
+
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+// Google Test - The Google C++ Testing and Mocking Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// A user can teach this function how to print a class type T by
+// defining either operator<<() or PrintTo() in the namespace that
+// defines T.  More specifically, the FIRST defined function in the
+// following list will be used (assuming T is defined in namespace
+// foo):
+//
+//   1. foo::PrintTo(const T&, ostream*)
+//   2. operator<<(ostream&, const T&) defined in either foo or the
+//      global namespace.
+//
+// However if T is an STL-style container then it is printed element-wise
+// unless foo::PrintTo(const T&, ostream*) is defined. Note that
+// operator<<() is ignored for container types.
+//
+// If none of the above is defined, it will print the debug string of
+// the value if it is a protocol buffer, or print the raw bytes in the
+// value otherwise.
+//
+// To aid debugging: when T is a reference type, the address of the
+// value is also printed; when T is a (const) char pointer, both the
+// pointer value and the NUL-terminated string it points to are
+// printed.
+//
+// We also provide some convenient wrappers:
+//
+//   // Prints a value to a string.  For a (const or not) char
+//   // pointer, the NUL-terminated string (but not the pointer) is
+//   // printed.
+//   std::string ::testing::PrintToString(const T& value);
+//
+//   // Prints a value tersely: for a reference type, the referenced
+//   // value (but not the address) is printed; for a (const or not) char
+//   // pointer, the NUL-terminated string (but not the pointer) is
+//   // printed.
+//   void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
+//
+//   // Prints value using the type inferred by the compiler.  The difference
+//   // from UniversalTersePrint() is that this function prints both the
+//   // pointer and the NUL-terminated string for a (const or not) char pointer.
+//   void ::testing::internal::UniversalPrint(const T& value, ostream*);
+//
+//   // Prints the fields of a tuple tersely to a string vector, one
+//   // element for each field. Tuple support must be enabled in
+//   // gtest-port.h.
+//   std::vector<string> UniversalTersePrintTupleFieldsToStrings(
+//       const Tuple& value);
+//
+// Known limitation:
+//
+// The print primitives print the elements of an STL-style container
+// using the compiler-inferred type of *iter where iter is a
+// const_iterator of the container.  When const_iterator is an input
+// iterator but not a forward iterator, this inferred type may not
+// match value_type, and the print output may be incorrect.  In
+// practice, this is rarely a problem as for most containers
+// const_iterator is a forward iterator.  We'll fix this if there's an
+// actual need for it.  Note that this fix cannot rely on value_type
+// being defined as many user-defined container types don't have
+// value_type.
+
+// GOOGLETEST_CM0001 DO NOT DELETE
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+
+#include <functional>
+#include <memory>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+
+namespace testing {
+
+// Definitions in the internal* namespaces are subject to change without notice.
+// DO NOT USE THEM IN USER CODE!
+namespace internal {
+
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os);
+
+// Used to print an STL-style container when the user doesn't define
+// a PrintTo() for it.
+struct ContainerPrinter {
+  template <typename T,
+            typename = typename std::enable_if<
+                (sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) &&
+                !IsRecursiveContainer<T>::value>::type>
+  static void PrintValue(const T& container, std::ostream* os) {
+    const size_t kMaxCount = 32;  // The maximum number of elements to print.
+    *os << '{';
+    size_t count = 0;
+    for (auto&& elem : container) {
+      if (count > 0) {
+        *os << ',';
+        if (count == kMaxCount) {  // Enough has been printed.
+          *os << " ...";
+          break;
+        }
+      }
+      *os << ' ';
+      // We cannot call PrintTo(elem, os) here as PrintTo() doesn't
+      // handle `elem` being a native array.
+      internal::UniversalPrint(elem, os);
+      ++count;
+    }
+
+    if (count > 0) {
+      *os << ' ';
+    }
+    *os << '}';
+  }
+};
+
+// Used to print a pointer that is neither a char pointer nor a member
+// pointer, when the user doesn't define PrintTo() for it.  (A member
+// variable pointer or member function pointer doesn't really point to
+// a location in the address space.  Their representation is
+// implementation-defined.  Therefore they will be printed as raw
+// bytes.)
+struct FunctionPointerPrinter {
+  template <typename T, typename = typename std::enable_if<
+                            std::is_function<T>::value>::type>
+  static void PrintValue(T* p, ::std::ostream* os) {
+    if (p == nullptr) {
+      *os << "NULL";
+    } else {
+      // T is a function type, so '*os << p' doesn't do what we want
+      // (it just prints p as bool).  We want to print p as a const
+      // void*.
+      *os << reinterpret_cast<const void*>(p);
+    }
+  }
+};
+
+struct PointerPrinter {
+  template <typename T>
+  static void PrintValue(T* p, ::std::ostream* os) {
+    if (p == nullptr) {
+      *os << "NULL";
+    } else {
+      // T is not a function type.  We just call << to print p,
+      // relying on ADL to pick up user-defined << for their pointer
+      // types, if any.
+      *os << p;
+    }
+  }
+};
+
+namespace internal_stream_operator_without_lexical_name_lookup {
+
+// The presence of an operator<< here will terminate lexical scope lookup
+// straight away (even though it cannot be a match because of its argument
+// types). Thus, the two operator<< calls in StreamPrinter will find only ADL
+// candidates.
+struct LookupBlocker {};
+void operator<<(LookupBlocker, LookupBlocker);
+
+struct StreamPrinter {
+  template <typename T,
+            // Don't accept member pointers here. We'd print them via implicit
+            // conversion to bool, which isn't useful.
+            typename = typename std::enable_if<
+                !std::is_member_pointer<T>::value>::type,
+            // Only accept types for which we can find a streaming operator via
+            // ADL (possibly involving implicit conversions).
+            typename = decltype(std::declval<std::ostream&>()
+                                << std::declval<const T&>())>
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    // Call streaming operator found by ADL, possibly with implicit conversions
+    // of the arguments.
+    *os << value;
+  }
+};
+
+}  // namespace internal_stream_operator_without_lexical_name_lookup
+
+struct ProtobufPrinter {
+  // We print a protobuf using its ShortDebugString() when the string
+  // doesn't exceed this many characters; otherwise we print it using
+  // DebugString() for better readability.
+  static const size_t kProtobufOneLinerMaxLength = 50;
+
+  template <typename T,
+            typename = typename std::enable_if<
+                internal::HasDebugStringAndShortDebugString<T>::value>::type>
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    std::string pretty_str = value.ShortDebugString();
+    if (pretty_str.length() > kProtobufOneLinerMaxLength) {
+      pretty_str = "\n" + value.DebugString();
+    }
+    *os << ("<" + pretty_str + ">");
+  }
+};
+
+struct ConvertibleToIntegerPrinter {
+  // Since T has no << operator or PrintTo() but can be implicitly
+  // converted to BiggestInt, we print it as a BiggestInt.
+  //
+  // Most likely T is an enum type (either named or unnamed), in which
+  // case printing it as an integer is the desired behavior.  In case
+  // T is not an enum, printing it as an integer is the best we can do
+  // given that it has no user-defined printer.
+  static void PrintValue(internal::BiggestInt value, ::std::ostream* os) {
+    *os << value;
+  }
+};
+
+struct ConvertibleToStringViewPrinter {
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  static void PrintValue(internal::StringView value, ::std::ostream* os) {
+    internal::UniversalPrint(value, os);
+  }
+#endif
+};
+
+
+// Prints the given number of bytes in the given object to the given
+// ostream.
+GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
+                                     size_t count,
+                                     ::std::ostream* os);
+struct RawBytesPrinter {
+  // SFINAE on `sizeof` to make sure we have a complete type.
+  template <typename T, size_t = sizeof(T)>
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    PrintBytesInObjectTo(
+        static_cast<const unsigned char*>(
+            // Load bearing cast to void* to support iOS
+            reinterpret_cast<const void*>(std::addressof(value))),
+        sizeof(value), os);
+  }
+};
+
+struct FallbackPrinter {
+  template <typename T>
+  static void PrintValue(const T&, ::std::ostream* os) {
+    *os << "(incomplete type)";
+  }
+};
+
+// Try every printer in order and return the first one that works.
+template <typename T, typename E, typename Printer, typename... Printers>
+struct FindFirstPrinter : FindFirstPrinter<T, E, Printers...> {};
+
+template <typename T, typename Printer, typename... Printers>
+struct FindFirstPrinter<
+    T, decltype(Printer::PrintValue(std::declval<const T&>(), nullptr)),
+    Printer, Printers...> {
+  using type = Printer;
+};
+
+// Select the best printer in the following order:
+//  - Print containers (they have begin/end/etc).
+//  - Print function pointers.
+//  - Print object pointers.
+//  - Use the stream operator, if available.
+//  - Print protocol buffers.
+//  - Print types convertible to BiggestInt.
+//  - Print types convertible to StringView, if available.
+//  - Fallback to printing the raw bytes of the object.
+template <typename T>
+void PrintWithFallback(const T& value, ::std::ostream* os) {
+  using Printer = typename FindFirstPrinter<
+      T, void, ContainerPrinter, FunctionPointerPrinter, PointerPrinter,
+      internal_stream_operator_without_lexical_name_lookup::StreamPrinter,
+      ProtobufPrinter, ConvertibleToIntegerPrinter,
+      ConvertibleToStringViewPrinter, RawBytesPrinter, FallbackPrinter>::type;
+  Printer::PrintValue(value, os);
+}
+
+// FormatForComparison<ToPrint, OtherOperand>::Format(value) formats a
+// value of type ToPrint that is an operand of a comparison assertion
+// (e.g. ASSERT_EQ).  OtherOperand is the type of the other operand in
+// the comparison, and is used to help determine the best way to
+// format the value.  In particular, when the value is a C string
+// (char pointer) and the other operand is an STL string object, we
+// want to format the C string as a string, since we know it is
+// compared by value with the string object.  If the value is a char
+// pointer but the other operand is not an STL string object, we don't
+// know whether the pointer is supposed to point to a NUL-terminated
+// string, and thus want to print it as a pointer to be safe.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+// The default case.
+template <typename ToPrint, typename OtherOperand>
+class FormatForComparison {
+ public:
+  static ::std::string Format(const ToPrint& value) {
+    return ::testing::PrintToString(value);
+  }
+};
+
+// Array.
+template <typename ToPrint, size_t N, typename OtherOperand>
+class FormatForComparison<ToPrint[N], OtherOperand> {
+ public:
+  static ::std::string Format(const ToPrint* value) {
+    return FormatForComparison<const ToPrint*, OtherOperand>::Format(value);
+  }
+};
+
+// By default, print C string as pointers to be safe, as we don't know
+// whether they actually point to a NUL-terminated string.
+
+#define GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(CharType)                \
+  template <typename OtherOperand>                                      \
+  class FormatForComparison<CharType*, OtherOperand> {                  \
+   public:                                                              \
+    static ::std::string Format(CharType* value) {                      \
+      return ::testing::PrintToString(static_cast<const void*>(value)); \
+    }                                                                   \
+  }
+
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t);
+#ifdef __cpp_lib_char8_t
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char8_t);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char8_t);
+#endif
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char16_t);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char16_t);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char32_t);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char32_t);
+
+#undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_
+
+// If a C string is compared with an STL string object, we know it's meant
+// to point to a NUL-terminated string, and thus can print it as a string.
+
+#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \
+  template <>                                                           \
+  class FormatForComparison<CharType*, OtherStringType> {               \
+   public:                                                              \
+    static ::std::string Format(CharType* value) {                      \
+      return ::testing::PrintToString(value);                           \
+    }                                                                   \
+  }
+
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string);
+#ifdef __cpp_char8_t
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char8_t, ::std::u8string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char8_t, ::std::u8string);
+#endif
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char16_t, ::std::u16string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char16_t, ::std::u16string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char32_t, ::std::u32string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char32_t, ::std::u32string);
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring);
+#endif
+
+#undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_
+
+// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc)
+// operand to be used in a failure message.  The type (but not value)
+// of the other operand may affect the format.  This allows us to
+// print a char* as a raw pointer when it is compared against another
+// char* or void*, and print it as a C string when it is compared
+// against an std::string object, for example.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename T1, typename T2>
+std::string FormatForComparisonFailureMessage(
+    const T1& value, const T2& /* other_operand */) {
+  return FormatForComparison<T1, T2>::Format(value);
+}
+
+// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
+// value to the given ostream.  The caller must ensure that
+// 'ostream_ptr' is not NULL, or the behavior is undefined.
+//
+// We define UniversalPrinter as a class template (as opposed to a
+// function template), as we need to partially specialize it for
+// reference types, which cannot be done with function templates.
+template <typename T>
+class UniversalPrinter;
+
+// Prints the given value using the << operator if it has one;
+// otherwise prints the bytes in it.  This is what
+// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
+// or overloaded for type T.
+//
+// A user can override this behavior for a class type Foo by defining
+// an overload of PrintTo() in the namespace where Foo is defined.  We
+// give the user this option as sometimes defining a << operator for
+// Foo is not desirable (e.g. the coding style may prevent doing it,
+// or there is already a << operator but it doesn't do what the user
+// wants).
+template <typename T>
+void PrintTo(const T& value, ::std::ostream* os) {
+  internal::PrintWithFallback(value, os);
+}
+
+// The following list of PrintTo() overloads tells
+// UniversalPrinter<T>::Print() how to print standard types (built-in
+// types, strings, plain arrays, and pointers).
+
+// Overloads for various char types.
+GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os);
+GTEST_API_ void PrintTo(signed char c, ::std::ostream* os);
+inline void PrintTo(char c, ::std::ostream* os) {
+  // When printing a plain char, we always treat it as unsigned.  This
+  // way, the output won't be affected by whether the compiler thinks
+  // char is signed or not.
+  PrintTo(static_cast<unsigned char>(c), os);
+}
+
+// Overloads for other simple built-in types.
+inline void PrintTo(bool x, ::std::ostream* os) {
+  *os << (x ? "true" : "false");
+}
+
+// Overload for wchar_t type.
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its decimal code (except for L'\0').
+// The L'\0' char is printed as "L'\\0'". The decimal code is printed
+// as signed integer when wchar_t is implemented by the compiler
+// as a signed type and is printed as an unsigned integer when wchar_t
+// is implemented as an unsigned type.
+GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
+
+GTEST_API_ void PrintTo(char32_t c, ::std::ostream* os);
+inline void PrintTo(char16_t c, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<char32_t>(c), os);
+}
+#ifdef __cpp_char8_t
+inline void PrintTo(char8_t c, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<char32_t>(c), os);
+}
+#endif
+
+// Overloads for C strings.
+GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
+inline void PrintTo(char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const char*>(s), os);
+}
+
+// signed/unsigned char is often used for representing binary data, so
+// we print pointers to it as void* to be safe.
+inline void PrintTo(const signed char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(signed char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(const unsigned char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(unsigned char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+#ifdef __cpp_char8_t
+// Overloads for u8 strings.
+GTEST_API_ void PrintTo(const char8_t* s, ::std::ostream* os);
+inline void PrintTo(char8_t* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const char8_t*>(s), os);
+}
+#endif
+// Overloads for u16 strings.
+GTEST_API_ void PrintTo(const char16_t* s, ::std::ostream* os);
+inline void PrintTo(char16_t* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const char16_t*>(s), os);
+}
+// Overloads for u32 strings.
+GTEST_API_ void PrintTo(const char32_t* s, ::std::ostream* os);
+inline void PrintTo(char32_t* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const char32_t*>(s), os);
+}
+
+// MSVC can be configured to define wchar_t as a typedef of unsigned
+// short.  It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
+// type.  When wchar_t is a typedef, defining an overload for const
+// wchar_t* would cause unsigned short* be printed as a wide string,
+// possibly causing invalid memory accesses.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Overloads for wide C strings
+GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
+inline void PrintTo(wchar_t* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const wchar_t*>(s), os);
+}
+#endif
+
+// Overload for C arrays.  Multi-dimensional arrays are printed
+// properly.
+
+// Prints the given number of elements in an array, without printing
+// the curly braces.
+template <typename T>
+void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
+  UniversalPrint(a[0], os);
+  for (size_t i = 1; i != count; i++) {
+    *os << ", ";
+    UniversalPrint(a[i], os);
+  }
+}
+
+// Overloads for ::std::string.
+GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
+inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
+  PrintStringTo(s, os);
+}
+
+// Overloads for ::std::u8string
+#ifdef __cpp_char8_t
+GTEST_API_ void PrintU8StringTo(const ::std::u8string& s, ::std::ostream* os);
+inline void PrintTo(const ::std::u8string& s, ::std::ostream* os) {
+  PrintU8StringTo(s, os);
+}
+#endif
+
+// Overloads for ::std::u16string
+GTEST_API_ void PrintU16StringTo(const ::std::u16string& s, ::std::ostream* os);
+inline void PrintTo(const ::std::u16string& s, ::std::ostream* os) {
+  PrintU16StringTo(s, os);
+}
+
+// Overloads for ::std::u32string
+GTEST_API_ void PrintU32StringTo(const ::std::u32string& s, ::std::ostream* os);
+inline void PrintTo(const ::std::u32string& s, ::std::ostream* os) {
+  PrintU32StringTo(s, os);
+}
+
+// Overloads for ::std::wstring.
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
+  PrintWideStringTo(s, os);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+// Overload for internal::StringView.
+inline void PrintTo(internal::StringView sp, ::std::ostream* os) {
+  PrintTo(::std::string(sp), os);
+}
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; }
+
+template <typename T>
+void PrintTo(std::reference_wrapper<T> ref, ::std::ostream* os) {
+  UniversalPrinter<T&>::Print(ref.get(), os);
+}
+
+inline const void* VoidifyPointer(const void* p) { return p; }
+inline const void* VoidifyPointer(volatile const void* p) {
+  return const_cast<const void*>(p);
+}
+
+template <typename T, typename Ptr>
+void PrintSmartPointer(const Ptr& ptr, std::ostream* os, char) {
+  if (ptr == nullptr) {
+    *os << "(nullptr)";
+  } else {
+    // We can't print the value. Just print the pointer..
+    *os << "(" << (VoidifyPointer)(ptr.get()) << ")";
+  }
+}
+template <typename T, typename Ptr,
+          typename = typename std::enable_if<!std::is_void<T>::value &&
+                                             !std::is_array<T>::value>::type>
+void PrintSmartPointer(const Ptr& ptr, std::ostream* os, int) {
+  if (ptr == nullptr) {
+    *os << "(nullptr)";
+  } else {
+    *os << "(ptr = " << (VoidifyPointer)(ptr.get()) << ", value = ";
+    UniversalPrinter<T>::Print(*ptr, os);
+    *os << ")";
+  }
+}
+
+template <typename T, typename D>
+void PrintTo(const std::unique_ptr<T, D>& ptr, std::ostream* os) {
+  (PrintSmartPointer<T>)(ptr, os, 0);
+}
+
+template <typename T>
+void PrintTo(const std::shared_ptr<T>& ptr, std::ostream* os) {
+  (PrintSmartPointer<T>)(ptr, os, 0);
+}
+
+// Helper function for printing a tuple.  T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T&, std::integral_constant<size_t, 0>,
+                  ::std::ostream*) {}
+
+template <typename T, size_t I>
+void PrintTupleTo(const T& t, std::integral_constant<size_t, I>,
+                  ::std::ostream* os) {
+  PrintTupleTo(t, std::integral_constant<size_t, I - 1>(), os);
+  GTEST_INTENTIONAL_CONST_COND_PUSH_()
+  if (I > 1) {
+    GTEST_INTENTIONAL_CONST_COND_POP_()
+    *os << ", ";
+  }
+  UniversalPrinter<typename std::tuple_element<I - 1, T>::type>::Print(
+      std::get<I - 1>(t), os);
+}
+
+template <typename... Types>
+void PrintTo(const ::std::tuple<Types...>& t, ::std::ostream* os) {
+  *os << "(";
+  PrintTupleTo(t, std::integral_constant<size_t, sizeof...(Types)>(), os);
+  *os << ")";
+}
+
+// Overload for std::pair.
+template <typename T1, typename T2>
+void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
+  *os << '(';
+  // We cannot use UniversalPrint(value.first, os) here, as T1 may be
+  // a reference type.  The same for printing value.second.
+  UniversalPrinter<T1>::Print(value.first, os);
+  *os << ", ";
+  UniversalPrinter<T2>::Print(value.second, os);
+  *os << ')';
+}
+
+// Implements printing a non-reference type T by letting the compiler
+// pick the right overload of PrintTo() for T.
+template <typename T>
+class UniversalPrinter {
+ public:
+  // MSVC warns about adding const to a function type, so we want to
+  // disable the warning.
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4180)
+
+  // Note: we deliberately don't call this PrintTo(), as that name
+  // conflicts with ::testing::internal::PrintTo in the body of the
+  // function.
+  static void Print(const T& value, ::std::ostream* os) {
+    // By default, ::testing::internal::PrintTo() is used for printing
+    // the value.
+    //
+    // Thanks to Koenig look-up, if T is a class and has its own
+    // PrintTo() function defined in its namespace, that function will
+    // be visible here.  Since it is more specific than the generic ones
+    // in ::testing::internal, it will be picked by the compiler in the
+    // following statement - exactly what we want.
+    PrintTo(value, os);
+  }
+
+  GTEST_DISABLE_MSC_WARNINGS_POP_()
+};
+
+// Remove any const-qualifiers before passing a type to UniversalPrinter.
+template <typename T>
+class UniversalPrinter<const T> : public UniversalPrinter<T> {};
+
+#if GTEST_INTERNAL_HAS_ANY
+
+// Printer for std::any / absl::any
+
+template <>
+class UniversalPrinter<Any> {
+ public:
+  static void Print(const Any& value, ::std::ostream* os) {
+    if (value.has_value()) {
+      *os << "value of type " << GetTypeName(value);
+    } else {
+      *os << "no value";
+    }
+  }
+
+ private:
+  static std::string GetTypeName(const Any& value) {
+#if GTEST_HAS_RTTI
+    return internal::GetTypeName(value.type());
+#else
+    static_cast<void>(value);  // possibly unused
+    return "<unknown_type>";
+#endif  // GTEST_HAS_RTTI
+  }
+};
+
+#endif  // GTEST_INTERNAL_HAS_ANY
+
+#if GTEST_INTERNAL_HAS_OPTIONAL
+
+// Printer for std::optional / absl::optional
+
+template <typename T>
+class UniversalPrinter<Optional<T>> {
+ public:
+  static void Print(const Optional<T>& value, ::std::ostream* os) {
+    *os << '(';
+    if (!value) {
+      *os << "nullopt";
+    } else {
+      UniversalPrint(*value, os);
+    }
+    *os << ')';
+  }
+};
+
+#endif  // GTEST_INTERNAL_HAS_OPTIONAL
+
+#if GTEST_INTERNAL_HAS_VARIANT
+
+// Printer for std::variant / absl::variant
+
+template <typename... T>
+class UniversalPrinter<Variant<T...>> {
+ public:
+  static void Print(const Variant<T...>& value, ::std::ostream* os) {
+    *os << '(';
+#if GTEST_HAS_ABSL
+    absl::visit(Visitor{os, value.index()}, value);
+#else
+    std::visit(Visitor{os, value.index()}, value);
+#endif  // GTEST_HAS_ABSL
+    *os << ')';
+  }
+
+ private:
+  struct Visitor {
+    template <typename U>
+    void operator()(const U& u) const {
+      *os << "'" << GetTypeName<U>() << "(index = " << index
+          << ")' with value ";
+      UniversalPrint(u, os);
+    }
+    ::std::ostream* os;
+    std::size_t index;
+  };
+};
+
+#endif  // GTEST_INTERNAL_HAS_VARIANT
+
+// UniversalPrintArray(begin, len, os) prints an array of 'len'
+// elements, starting at address 'begin'.
+template <typename T>
+void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
+  if (len == 0) {
+    *os << "{}";
+  } else {
+    *os << "{ ";
+    const size_t kThreshold = 18;
+    const size_t kChunkSize = 8;
+    // If the array has more than kThreshold elements, we'll have to
+    // omit some details by printing only the first and the last
+    // kChunkSize elements.
+    if (len <= kThreshold) {
+      PrintRawArrayTo(begin, len, os);
+    } else {
+      PrintRawArrayTo(begin, kChunkSize, os);
+      *os << ", ..., ";
+      PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
+    }
+    *os << " }";
+  }
+}
+// This overload prints a (const) char array compactly.
+GTEST_API_ void UniversalPrintArray(
+    const char* begin, size_t len, ::std::ostream* os);
+
+#ifdef __cpp_char8_t
+// This overload prints a (const) char8_t array compactly.
+GTEST_API_ void UniversalPrintArray(const char8_t* begin, size_t len,
+                                    ::std::ostream* os);
+#endif
+
+// This overload prints a (const) char16_t array compactly.
+GTEST_API_ void UniversalPrintArray(const char16_t* begin, size_t len,
+                                    ::std::ostream* os);
+
+// This overload prints a (const) char32_t array compactly.
+GTEST_API_ void UniversalPrintArray(const char32_t* begin, size_t len,
+                                    ::std::ostream* os);
+
+// This overload prints a (const) wchar_t array compactly.
+GTEST_API_ void UniversalPrintArray(
+    const wchar_t* begin, size_t len, ::std::ostream* os);
+
+// Implements printing an array type T[N].
+template <typename T, size_t N>
+class UniversalPrinter<T[N]> {
+ public:
+  // Prints the given array, omitting some elements when there are too
+  // many.
+  static void Print(const T (&a)[N], ::std::ostream* os) {
+    UniversalPrintArray(a, N, os);
+  }
+};
+
+// Implements printing a reference type T&.
+template <typename T>
+class UniversalPrinter<T&> {
+ public:
+  // MSVC warns about adding const to a function type, so we want to
+  // disable the warning.
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4180)
+
+  static void Print(const T& value, ::std::ostream* os) {
+    // Prints the address of the value.  We use reinterpret_cast here
+    // as static_cast doesn't compile when T is a function type.
+    *os << "@" << reinterpret_cast<const void*>(&value) << " ";
+
+    // Then prints the value itself.
+    UniversalPrint(value, os);
+  }
+
+  GTEST_DISABLE_MSC_WARNINGS_POP_()
+};
+
+// Prints a value tersely: for a reference type, the referenced value
+// (but not the address) is printed; for a (const) char pointer, the
+// NUL-terminated string (but not the pointer) is printed.
+
+template <typename T>
+class UniversalTersePrinter {
+ public:
+  static void Print(const T& value, ::std::ostream* os) {
+    UniversalPrint(value, os);
+  }
+};
+template <typename T>
+class UniversalTersePrinter<T&> {
+ public:
+  static void Print(const T& value, ::std::ostream* os) {
+    UniversalPrint(value, os);
+  }
+};
+template <typename T, size_t N>
+class UniversalTersePrinter<T[N]> {
+ public:
+  static void Print(const T (&value)[N], ::std::ostream* os) {
+    UniversalPrinter<T[N]>::Print(value, os);
+  }
+};
+template <>
+class UniversalTersePrinter<const char*> {
+ public:
+  static void Print(const char* str, ::std::ostream* os) {
+    if (str == nullptr) {
+      *os << "NULL";
+    } else {
+      UniversalPrint(std::string(str), os);
+    }
+  }
+};
+template <>
+class UniversalTersePrinter<char*> : public UniversalTersePrinter<const char*> {
+};
+
+#ifdef __cpp_char8_t
+template <>
+class UniversalTersePrinter<const char8_t*> {
+ public:
+  static void Print(const char8_t* str, ::std::ostream* os) {
+    if (str == nullptr) {
+      *os << "NULL";
+    } else {
+      UniversalPrint(::std::u8string(str), os);
+    }
+  }
+};
+template <>
+class UniversalTersePrinter<char8_t*>
+    : public UniversalTersePrinter<const char8_t*> {};
+#endif
+
+template <>
+class UniversalTersePrinter<const char16_t*> {
+ public:
+  static void Print(const char16_t* str, ::std::ostream* os) {
+    if (str == nullptr) {
+      *os << "NULL";
+    } else {
+      UniversalPrint(::std::u16string(str), os);
+    }
+  }
+};
+template <>
+class UniversalTersePrinter<char16_t*>
+    : public UniversalTersePrinter<const char16_t*> {};
+
+template <>
+class UniversalTersePrinter<const char32_t*> {
+ public:
+  static void Print(const char32_t* str, ::std::ostream* os) {
+    if (str == nullptr) {
+      *os << "NULL";
+    } else {
+      UniversalPrint(::std::u32string(str), os);
+    }
+  }
+};
+template <>
+class UniversalTersePrinter<char32_t*>
+    : public UniversalTersePrinter<const char32_t*> {};
+
+#if GTEST_HAS_STD_WSTRING
+template <>
+class UniversalTersePrinter<const wchar_t*> {
+ public:
+  static void Print(const wchar_t* str, ::std::ostream* os) {
+    if (str == nullptr) {
+      *os << "NULL";
+    } else {
+      UniversalPrint(::std::wstring(str), os);
+    }
+  }
+};
+#endif
+
+template <>
+class UniversalTersePrinter<wchar_t*> {
+ public:
+  static void Print(wchar_t* str, ::std::ostream* os) {
+    UniversalTersePrinter<const wchar_t*>::Print(str, os);
+  }
+};
+
+template <typename T>
+void UniversalTersePrint(const T& value, ::std::ostream* os) {
+  UniversalTersePrinter<T>::Print(value, os);
+}
+
+// Prints a value using the type inferred by the compiler.  The
+// difference between this and UniversalTersePrint() is that for a
+// (const) char pointer, this prints both the pointer and the
+// NUL-terminated string.
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os) {
+  // A workarond for the bug in VC++ 7.1 that prevents us from instantiating
+  // UniversalPrinter with T directly.
+  typedef T T1;
+  UniversalPrinter<T1>::Print(value, os);
+}
+
+typedef ::std::vector< ::std::string> Strings;
+
+  // Tersely prints the first N fields of a tuple to a string vector,
+  // one element for each field.
+template <typename Tuple>
+void TersePrintPrefixToStrings(const Tuple&, std::integral_constant<size_t, 0>,
+                               Strings*) {}
+template <typename Tuple, size_t I>
+void TersePrintPrefixToStrings(const Tuple& t,
+                               std::integral_constant<size_t, I>,
+                               Strings* strings) {
+  TersePrintPrefixToStrings(t, std::integral_constant<size_t, I - 1>(),
+                            strings);
+  ::std::stringstream ss;
+  UniversalTersePrint(std::get<I - 1>(t), &ss);
+  strings->push_back(ss.str());
+}
+
+// Prints the fields of a tuple tersely to a string vector, one
+// element for each field.  See the comment before
+// UniversalTersePrint() for how we define "tersely".
+template <typename Tuple>
+Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
+  Strings result;
+  TersePrintPrefixToStrings(
+      value, std::integral_constant<size_t, std::tuple_size<Tuple>::value>(),
+      &result);
+  return result;
+}
+
+}  // namespace internal
+
+template <typename T>
+::std::string PrintToString(const T& value) {
+  ::std::stringstream ss;
+  internal::UniversalTersePrinter<T>::Print(value, &ss);
+  return ss.str();
+}
+
+}  // namespace testing
+
+// Include any custom printer added by the local installation.
+// We must include this header at the end to make sure it can use the
+// declarations from this file.
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// This file provides an injection point for custom printers in a local
+// installation of gTest.
+// It will be included from gtest-printers.h and the overrides in this file
+// will be visible to everyone.
+//
+// Injection point for custom user configurations. See README for details
+//
+// ** Custom implementation starts here **
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+
+// MSVC warning C5046 is new as of VS2017 version 15.8.
+#if defined(_MSC_VER) && _MSC_VER >= 1915
+#define GTEST_MAYBE_5046_ 5046
+#else
+#define GTEST_MAYBE_5046_
+#endif
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(
+    4251 GTEST_MAYBE_5046_ /* class A needs to have dll-interface to be used by
+                              clients of class B */
+    /* Symbol involving type with internal linkage not defined */)
+
+namespace testing {
+
+// To implement a matcher Foo for type T, define:
+//   1. a class FooMatcherMatcher that implements the matcher interface:
+//     using is_gtest_matcher = void;
+//     bool MatchAndExplain(const T&, std::ostream*);
+//       (MatchResultListener* can also be used instead of std::ostream*)
+//     void DescribeTo(std::ostream*);
+//     void DescribeNegationTo(std::ostream*);
+//
+//   2. a factory function that creates a Matcher<T> object from a
+//      FooMatcherMatcher.
+
+class MatchResultListener {
+ public:
+  // Creates a listener object with the given underlying ostream.  The
+  // listener does not own the ostream, and does not dereference it
+  // in the constructor or destructor.
+  explicit MatchResultListener(::std::ostream* os) : stream_(os) {}
+  virtual ~MatchResultListener() = 0;  // Makes this class abstract.
+
+  // Streams x to the underlying ostream; does nothing if the ostream
+  // is NULL.
+  template <typename T>
+  MatchResultListener& operator<<(const T& x) {
+    if (stream_ != nullptr) *stream_ << x;
+    return *this;
+  }
+
+  // Returns the underlying ostream.
+  ::std::ostream* stream() { return stream_; }
+
+  // Returns true if and only if the listener is interested in an explanation
+  // of the match result.  A matcher's MatchAndExplain() method can use
+  // this information to avoid generating the explanation when no one
+  // intends to hear it.
+  bool IsInterested() const { return stream_ != nullptr; }
+
+ private:
+  ::std::ostream* const stream_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener);
+};
+
+inline MatchResultListener::~MatchResultListener() {
+}
+
+// An instance of a subclass of this knows how to describe itself as a
+// matcher.
+class GTEST_API_ MatcherDescriberInterface {
+ public:
+  virtual ~MatcherDescriberInterface() {}
+
+  // Describes this matcher to an ostream.  The function should print
+  // a verb phrase that describes the property a value matching this
+  // matcher should have.  The subject of the verb phrase is the value
+  // being matched.  For example, the DescribeTo() method of the Gt(7)
+  // matcher prints "is greater than 7".
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+
+  // Describes the negation of this matcher to an ostream.  For
+  // example, if the description of this matcher is "is greater than
+  // 7", the negated description could be "is not greater than 7".
+  // You are not required to override this when implementing
+  // MatcherInterface, but it is highly advised so that your matcher
+  // can produce good error messages.
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "not (";
+    DescribeTo(os);
+    *os << ")";
+  }
+};
+
+// The implementation of a matcher.
+template <typename T>
+class MatcherInterface : public MatcherDescriberInterface {
+ public:
+  // Returns true if and only if the matcher matches x; also explains the
+  // match result to 'listener' if necessary (see the next paragraph), in
+  // the form of a non-restrictive relative clause ("which ...",
+  // "whose ...", etc) that describes x.  For example, the
+  // MatchAndExplain() method of the Pointee(...) matcher should
+  // generate an explanation like "which points to ...".
+  //
+  // Implementations of MatchAndExplain() should add an explanation of
+  // the match result *if and only if* they can provide additional
+  // information that's not already present (or not obvious) in the
+  // print-out of x and the matcher's description.  Whether the match
+  // succeeds is not a factor in deciding whether an explanation is
+  // needed, as sometimes the caller needs to print a failure message
+  // when the match succeeds (e.g. when the matcher is used inside
+  // Not()).
+  //
+  // For example, a "has at least 10 elements" matcher should explain
+  // what the actual element count is, regardless of the match result,
+  // as it is useful information to the reader; on the other hand, an
+  // "is empty" matcher probably only needs to explain what the actual
+  // size is when the match fails, as it's redundant to say that the
+  // size is 0 when the value is already known to be empty.
+  //
+  // You should override this method when defining a new matcher.
+  //
+  // It's the responsibility of the caller (Google Test) to guarantee
+  // that 'listener' is not NULL.  This helps to simplify a matcher's
+  // implementation when it doesn't care about the performance, as it
+  // can talk to 'listener' without checking its validity first.
+  // However, in order to implement dummy listeners efficiently,
+  // listener->stream() may be NULL.
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0;
+
+  // Inherits these methods from MatcherDescriberInterface:
+  //   virtual void DescribeTo(::std::ostream* os) const = 0;
+  //   virtual void DescribeNegationTo(::std::ostream* os) const;
+};
+
+namespace internal {
+
+struct AnyEq {
+  template <typename A, typename B>
+  bool operator()(const A& a, const B& b) const { return a == b; }
+};
+struct AnyNe {
+  template <typename A, typename B>
+  bool operator()(const A& a, const B& b) const { return a != b; }
+};
+struct AnyLt {
+  template <typename A, typename B>
+  bool operator()(const A& a, const B& b) const { return a < b; }
+};
+struct AnyGt {
+  template <typename A, typename B>
+  bool operator()(const A& a, const B& b) const { return a > b; }
+};
+struct AnyLe {
+  template <typename A, typename B>
+  bool operator()(const A& a, const B& b) const { return a <= b; }
+};
+struct AnyGe {
+  template <typename A, typename B>
+  bool operator()(const A& a, const B& b) const { return a >= b; }
+};
+
+// A match result listener that ignores the explanation.
+class DummyMatchResultListener : public MatchResultListener {
+ public:
+  DummyMatchResultListener() : MatchResultListener(nullptr) {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DummyMatchResultListener);
+};
+
+// A match result listener that forwards the explanation to a given
+// ostream.  The difference between this and MatchResultListener is
+// that the former is concrete.
+class StreamMatchResultListener : public MatchResultListener {
+ public:
+  explicit StreamMatchResultListener(::std::ostream* os)
+      : MatchResultListener(os) {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener);
+};
+
+struct SharedPayloadBase {
+  std::atomic<int> ref{1};
+  void Ref() { ref.fetch_add(1, std::memory_order_relaxed); }
+  bool Unref() { return ref.fetch_sub(1, std::memory_order_acq_rel) == 1; }
+};
+
+template <typename T>
+struct SharedPayload : SharedPayloadBase {
+  explicit SharedPayload(const T& v) : value(v) {}
+  explicit SharedPayload(T&& v) : value(std::move(v)) {}
+
+  static void Destroy(SharedPayloadBase* shared) {
+    delete static_cast<SharedPayload*>(shared);
+  }
+
+  T value;
+};
+
+// An internal class for implementing Matcher<T>, which will derive
+// from it.  We put functionalities common to all Matcher<T>
+// specializations here to avoid code duplication.
+template <typename T>
+class MatcherBase : private MatcherDescriberInterface {
+ public:
+  // Returns true if and only if the matcher matches x; also explains the
+  // match result to 'listener'.
+  bool MatchAndExplain(const T& x, MatchResultListener* listener) const {
+    GTEST_CHECK_(vtable_ != nullptr);
+    return vtable_->match_and_explain(*this, x, listener);
+  }
+
+  // Returns true if and only if this matcher matches x.
+  bool Matches(const T& x) const {
+    DummyMatchResultListener dummy;
+    return MatchAndExplain(x, &dummy);
+  }
+
+  // Describes this matcher to an ostream.
+  void DescribeTo(::std::ostream* os) const final {
+    GTEST_CHECK_(vtable_ != nullptr);
+    vtable_->describe(*this, os, false);
+  }
+
+  // Describes the negation of this matcher to an ostream.
+  void DescribeNegationTo(::std::ostream* os) const final {
+    GTEST_CHECK_(vtable_ != nullptr);
+    vtable_->describe(*this, os, true);
+  }
+
+  // Explains why x matches, or doesn't match, the matcher.
+  void ExplainMatchResultTo(const T& x, ::std::ostream* os) const {
+    StreamMatchResultListener listener(os);
+    MatchAndExplain(x, &listener);
+  }
+
+  // Returns the describer for this matcher object; retains ownership
+  // of the describer, which is only guaranteed to be alive when
+  // this matcher object is alive.
+  const MatcherDescriberInterface* GetDescriber() const {
+    if (vtable_ == nullptr) return nullptr;
+    return vtable_->get_describer(*this);
+  }
+
+ protected:
+  MatcherBase() : vtable_(nullptr) {}
+
+  // Constructs a matcher from its implementation.
+  template <typename U>
+  explicit MatcherBase(const MatcherInterface<U>* impl) {
+    Init(impl);
+  }
+
+  template <typename M, typename = typename std::remove_reference<
+                            M>::type::is_gtest_matcher>
+  MatcherBase(M&& m) {  // NOLINT
+    Init(std::forward<M>(m));
+  }
+
+  MatcherBase(const MatcherBase& other)
+      : vtable_(other.vtable_), buffer_(other.buffer_) {
+    if (IsShared()) buffer_.shared->Ref();
+  }
+
+  MatcherBase& operator=(const MatcherBase& other) {
+    if (this == &other) return *this;
+    Destroy();
+    vtable_ = other.vtable_;
+    buffer_ = other.buffer_;
+    if (IsShared()) buffer_.shared->Ref();
+    return *this;
+  }
+
+  MatcherBase(MatcherBase&& other)
+      : vtable_(other.vtable_), buffer_(other.buffer_) {
+    other.vtable_ = nullptr;
+  }
+
+  MatcherBase& operator=(MatcherBase&& other) {
+    if (this == &other) return *this;
+    Destroy();
+    vtable_ = other.vtable_;
+    buffer_ = other.buffer_;
+    other.vtable_ = nullptr;
+    return *this;
+  }
+
+  ~MatcherBase() override { Destroy(); }
+
+ private:
+  struct VTable {
+    bool (*match_and_explain)(const MatcherBase&, const T&,
+                              MatchResultListener*);
+    void (*describe)(const MatcherBase&, std::ostream*, bool negation);
+    // Returns the captured object if it implements the interface, otherwise
+    // returns the MatcherBase itself.
+    const MatcherDescriberInterface* (*get_describer)(const MatcherBase&);
+    // Called on shared instances when the reference count reaches 0.
+    void (*shared_destroy)(SharedPayloadBase*);
+  };
+
+  bool IsShared() const {
+    return vtable_ != nullptr && vtable_->shared_destroy != nullptr;
+  }
+
+  // If the implementation uses a listener, call that.
+  template <typename P>
+  static auto MatchAndExplainImpl(const MatcherBase& m, const T& value,
+                                  MatchResultListener* listener)
+      -> decltype(P::Get(m).MatchAndExplain(value, listener->stream())) {
+    return P::Get(m).MatchAndExplain(value, listener->stream());
+  }
+
+  template <typename P>
+  static auto MatchAndExplainImpl(const MatcherBase& m, const T& value,
+                                  MatchResultListener* listener)
+      -> decltype(P::Get(m).MatchAndExplain(value, listener)) {
+    return P::Get(m).MatchAndExplain(value, listener);
+  }
+
+  template <typename P>
+  static void DescribeImpl(const MatcherBase& m, std::ostream* os,
+                           bool negation) {
+    if (negation) {
+      P::Get(m).DescribeNegationTo(os);
+    } else {
+      P::Get(m).DescribeTo(os);
+    }
+  }
+
+  template <typename P>
+  static const MatcherDescriberInterface* GetDescriberImpl(
+      const MatcherBase& m) {
+    // If the impl is a MatcherDescriberInterface, then return it.
+    // Otherwise use MatcherBase itself.
+    // This allows us to implement the GetDescriber() function without support
+    // from the impl, but some users really want to get their impl back when
+    // they call GetDescriber().
+    // We use std::get on a tuple as a workaround of not having `if constexpr`.
+    return std::get<(
+        std::is_convertible<decltype(&P::Get(m)),
+                            const MatcherDescriberInterface*>::value
+            ? 1
+            : 0)>(std::make_tuple(&m, &P::Get(m)));
+  }
+
+  template <typename P>
+  const VTable* GetVTable() {
+    static constexpr VTable kVTable = {&MatchAndExplainImpl<P>,
+                                       &DescribeImpl<P>, &GetDescriberImpl<P>,
+                                       P::shared_destroy};
+    return &kVTable;
+  }
+
+  union Buffer {
+    // Add some types to give Buffer some common alignment/size use cases.
+    void* ptr;
+    double d;
+    int64_t i;
+    // And add one for the out-of-line cases.
+    SharedPayloadBase* shared;
+  };
+
+  void Destroy() {
+    if (IsShared() && buffer_.shared->Unref()) {
+      vtable_->shared_destroy(buffer_.shared);
+    }
+  }
+
+  template <typename M>
+  static constexpr bool IsInlined() {
+    return sizeof(M) <= sizeof(Buffer) && alignof(M) <= alignof(Buffer) &&
+           std::is_trivially_copy_constructible<M>::value &&
+           std::is_trivially_destructible<M>::value;
+  }
+
+  template <typename M, bool = MatcherBase::IsInlined<M>()>
+  struct ValuePolicy {
+    static const M& Get(const MatcherBase& m) {
+      // When inlined along with Init, need to be explicit to avoid violating
+      // strict aliasing rules.
+      const M *ptr = static_cast<const M*>(
+          static_cast<const void*>(&m.buffer_));
+      return *ptr;
+    }
+    static void Init(MatcherBase& m, M impl) {
+      ::new (static_cast<void*>(&m.buffer_)) M(impl);
+    }
+    static constexpr auto shared_destroy = nullptr;
+  };
+
+  template <typename M>
+  struct ValuePolicy<M, false> {
+    using Shared = SharedPayload<M>;
+    static const M& Get(const MatcherBase& m) {
+      return static_cast<Shared*>(m.buffer_.shared)->value;
+    }
+    template <typename Arg>
+    static void Init(MatcherBase& m, Arg&& arg) {
+      m.buffer_.shared = new Shared(std::forward<Arg>(arg));
+    }
+    static constexpr auto shared_destroy = &Shared::Destroy;
+  };
+
+  template <typename U, bool B>
+  struct ValuePolicy<const MatcherInterface<U>*, B> {
+    using M = const MatcherInterface<U>;
+    using Shared = SharedPayload<std::unique_ptr<M>>;
+    static const M& Get(const MatcherBase& m) {
+      return *static_cast<Shared*>(m.buffer_.shared)->value;
+    }
+    static void Init(MatcherBase& m, M* impl) {
+      m.buffer_.shared = new Shared(std::unique_ptr<M>(impl));
+    }
+
+    static constexpr auto shared_destroy = &Shared::Destroy;
+  };
+
+  template <typename M>
+  void Init(M&& m) {
+    using MM = typename std::decay<M>::type;
+    using Policy = ValuePolicy<MM>;
+    vtable_ = GetVTable<Policy>();
+    Policy::Init(*this, std::forward<M>(m));
+  }
+
+  const VTable* vtable_;
+  Buffer buffer_;
+};
+
+}  // namespace internal
+
+// A Matcher<T> is a copyable and IMMUTABLE (except by assignment)
+// object that can check whether a value of type T matches.  The
+// implementation of Matcher<T> is just a std::shared_ptr to const
+// MatcherInterface<T>.  Don't inherit from Matcher!
+template <typename T>
+class Matcher : public internal::MatcherBase<T> {
+ public:
+  // Constructs a null matcher.  Needed for storing Matcher objects in STL
+  // containers.  A default-constructed matcher is not yet initialized.  You
+  // cannot use it until a valid value has been assigned to it.
+  explicit Matcher() {}  // NOLINT
+
+  // Constructs a matcher from its implementation.
+  explicit Matcher(const MatcherInterface<const T&>* impl)
+      : internal::MatcherBase<T>(impl) {}
+
+  template <typename U>
+  explicit Matcher(
+      const MatcherInterface<U>* impl,
+      typename std::enable_if<!std::is_same<U, const U&>::value>::type* =
+          nullptr)
+      : internal::MatcherBase<T>(impl) {}
+
+  template <typename M, typename = typename std::remove_reference<
+                            M>::type::is_gtest_matcher>
+  Matcher(M&& m) : internal::MatcherBase<T>(std::forward<M>(m)) {}  // NOLINT
+
+  // Implicit constructor here allows people to write
+  // EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes
+  Matcher(T value);  // NOLINT
+};
+
+// The following two specializations allow the user to write str
+// instead of Eq(str) and "foo" instead of Eq("foo") when a std::string
+// matcher is expected.
+template <>
+class GTEST_API_ Matcher<const std::string&>
+    : public internal::MatcherBase<const std::string&> {
+ public:
+  Matcher() {}
+
+  explicit Matcher(const MatcherInterface<const std::string&>* impl)
+      : internal::MatcherBase<const std::string&>(impl) {}
+
+  template <typename M, typename = typename std::remove_reference<
+                            M>::type::is_gtest_matcher>
+  Matcher(M&& m)  // NOLINT
+      : internal::MatcherBase<const std::string&>(std::forward<M>(m)) {}
+
+  // Allows the user to write str instead of Eq(str) sometimes, where
+  // str is a std::string object.
+  Matcher(const std::string& s);  // NOLINT
+
+  // Allows the user to write "foo" instead of Eq("foo") sometimes.
+  Matcher(const char* s);  // NOLINT
+};
+
+template <>
+class GTEST_API_ Matcher<std::string>
+    : public internal::MatcherBase<std::string> {
+ public:
+  Matcher() {}
+
+  explicit Matcher(const MatcherInterface<const std::string&>* impl)
+      : internal::MatcherBase<std::string>(impl) {}
+  explicit Matcher(const MatcherInterface<std::string>* impl)
+      : internal::MatcherBase<std::string>(impl) {}
+
+  template <typename M, typename = typename std::remove_reference<
+                            M>::type::is_gtest_matcher>
+  Matcher(M&& m)  // NOLINT
+      : internal::MatcherBase<std::string>(std::forward<M>(m)) {}
+
+  // Allows the user to write str instead of Eq(str) sometimes, where
+  // str is a string object.
+  Matcher(const std::string& s);  // NOLINT
+
+  // Allows the user to write "foo" instead of Eq("foo") sometimes.
+  Matcher(const char* s);  // NOLINT
+};
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+// The following two specializations allow the user to write str
+// instead of Eq(str) and "foo" instead of Eq("foo") when a absl::string_view
+// matcher is expected.
+template <>
+class GTEST_API_ Matcher<const internal::StringView&>
+    : public internal::MatcherBase<const internal::StringView&> {
+ public:
+  Matcher() {}
+
+  explicit Matcher(const MatcherInterface<const internal::StringView&>* impl)
+      : internal::MatcherBase<const internal::StringView&>(impl) {}
+
+  template <typename M, typename = typename std::remove_reference<
+                            M>::type::is_gtest_matcher>
+  Matcher(M&& m)  // NOLINT
+      : internal::MatcherBase<const internal::StringView&>(std::forward<M>(m)) {
+  }
+
+  // Allows the user to write str instead of Eq(str) sometimes, where
+  // str is a std::string object.
+  Matcher(const std::string& s);  // NOLINT
+
+  // Allows the user to write "foo" instead of Eq("foo") sometimes.
+  Matcher(const char* s);  // NOLINT
+
+  // Allows the user to pass absl::string_views or std::string_views directly.
+  Matcher(internal::StringView s);  // NOLINT
+};
+
+template <>
+class GTEST_API_ Matcher<internal::StringView>
+    : public internal::MatcherBase<internal::StringView> {
+ public:
+  Matcher() {}
+
+  explicit Matcher(const MatcherInterface<const internal::StringView&>* impl)
+      : internal::MatcherBase<internal::StringView>(impl) {}
+  explicit Matcher(const MatcherInterface<internal::StringView>* impl)
+      : internal::MatcherBase<internal::StringView>(impl) {}
+
+  template <typename M, typename = typename std::remove_reference<
+                            M>::type::is_gtest_matcher>
+  Matcher(M&& m)  // NOLINT
+      : internal::MatcherBase<internal::StringView>(std::forward<M>(m)) {}
+
+  // Allows the user to write str instead of Eq(str) sometimes, where
+  // str is a std::string object.
+  Matcher(const std::string& s);  // NOLINT
+
+  // Allows the user to write "foo" instead of Eq("foo") sometimes.
+  Matcher(const char* s);  // NOLINT
+
+  // Allows the user to pass absl::string_views or std::string_views directly.
+  Matcher(internal::StringView s);  // NOLINT
+};
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+// Prints a matcher in a human-readable format.
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const Matcher<T>& matcher) {
+  matcher.DescribeTo(&os);
+  return os;
+}
+
+// The PolymorphicMatcher class template makes it easy to implement a
+// polymorphic matcher (i.e. a matcher that can match values of more
+// than one type, e.g. Eq(n) and NotNull()).
+//
+// To define a polymorphic matcher, a user should provide an Impl
+// class that has a DescribeTo() method and a DescribeNegationTo()
+// method, and define a member function (or member function template)
+//
+//   bool MatchAndExplain(const Value& value,
+//                        MatchResultListener* listener) const;
+//
+// See the definition of NotNull() for a complete example.
+template <class Impl>
+class PolymorphicMatcher {
+ public:
+  explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {}
+
+  // Returns a mutable reference to the underlying matcher
+  // implementation object.
+  Impl& mutable_impl() { return impl_; }
+
+  // Returns an immutable reference to the underlying matcher
+  // implementation object.
+  const Impl& impl() const { return impl_; }
+
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new MonomorphicImpl<const T&>(impl_));
+  }
+
+ private:
+  template <typename T>
+  class MonomorphicImpl : public MatcherInterface<T> {
+   public:
+    explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
+
+    void DescribeTo(::std::ostream* os) const override { impl_.DescribeTo(os); }
+
+    void DescribeNegationTo(::std::ostream* os) const override {
+      impl_.DescribeNegationTo(os);
+    }
+
+    bool MatchAndExplain(T x, MatchResultListener* listener) const override {
+      return impl_.MatchAndExplain(x, listener);
+    }
+
+   private:
+    const Impl impl_;
+  };
+
+  Impl impl_;
+};
+
+// Creates a matcher from its implementation.
+// DEPRECATED: Especially in the generic code, prefer:
+//   Matcher<T>(new MyMatcherImpl<const T&>(...));
+//
+// MakeMatcher may create a Matcher that accepts its argument by value, which
+// leads to unnecessary copies & lack of support for non-copyable types.
+template <typename T>
+inline Matcher<T> MakeMatcher(const MatcherInterface<T>* impl) {
+  return Matcher<T>(impl);
+}
+
+// Creates a polymorphic matcher from its implementation.  This is
+// easier to use than the PolymorphicMatcher<Impl> constructor as it
+// doesn't require you to explicitly write the template argument, e.g.
+//
+//   MakePolymorphicMatcher(foo);
+// vs
+//   PolymorphicMatcher<TypeOfFoo>(foo);
+template <class Impl>
+inline PolymorphicMatcher<Impl> MakePolymorphicMatcher(const Impl& impl) {
+  return PolymorphicMatcher<Impl>(impl);
+}
+
+namespace internal {
+// Implements a matcher that compares a given value with a
+// pre-supplied value using one of the ==, <=, <, etc, operators.  The
+// two values being compared don't have to have the same type.
+//
+// The matcher defined here is polymorphic (for example, Eq(5) can be
+// used to match an int, a short, a double, etc).  Therefore we use
+// a template type conversion operator in the implementation.
+//
+// The following template definition assumes that the Rhs parameter is
+// a "bare" type (i.e. neither 'const T' nor 'T&').
+template <typename D, typename Rhs, typename Op>
+class ComparisonBase {
+ public:
+  explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {}
+
+  using is_gtest_matcher = void;
+
+  template <typename Lhs>
+  bool MatchAndExplain(const Lhs& lhs, std::ostream*) const {
+    return Op()(lhs, Unwrap(rhs_));
+  }
+  void DescribeTo(std::ostream* os) const {
+    *os << D::Desc() << " ";
+    UniversalPrint(Unwrap(rhs_), os);
+  }
+  void DescribeNegationTo(std::ostream* os) const {
+    *os << D::NegatedDesc() << " ";
+    UniversalPrint(Unwrap(rhs_), os);
+  }
+
+ private:
+  template <typename T>
+  static const T& Unwrap(const T& v) {
+    return v;
+  }
+  template <typename T>
+  static const T& Unwrap(std::reference_wrapper<T> v) {
+    return v;
+  }
+
+  Rhs rhs_;
+};
+
+template <typename Rhs>
+class EqMatcher : public ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq> {
+ public:
+  explicit EqMatcher(const Rhs& rhs)
+      : ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq>(rhs) { }
+  static const char* Desc() { return "is equal to"; }
+  static const char* NegatedDesc() { return "isn't equal to"; }
+};
+template <typename Rhs>
+class NeMatcher : public ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe> {
+ public:
+  explicit NeMatcher(const Rhs& rhs)
+      : ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe>(rhs) { }
+  static const char* Desc() { return "isn't equal to"; }
+  static const char* NegatedDesc() { return "is equal to"; }
+};
+template <typename Rhs>
+class LtMatcher : public ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt> {
+ public:
+  explicit LtMatcher(const Rhs& rhs)
+      : ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt>(rhs) { }
+  static const char* Desc() { return "is <"; }
+  static const char* NegatedDesc() { return "isn't <"; }
+};
+template <typename Rhs>
+class GtMatcher : public ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt> {
+ public:
+  explicit GtMatcher(const Rhs& rhs)
+      : ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt>(rhs) { }
+  static const char* Desc() { return "is >"; }
+  static const char* NegatedDesc() { return "isn't >"; }
+};
+template <typename Rhs>
+class LeMatcher : public ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe> {
+ public:
+  explicit LeMatcher(const Rhs& rhs)
+      : ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe>(rhs) { }
+  static const char* Desc() { return "is <="; }
+  static const char* NegatedDesc() { return "isn't <="; }
+};
+template <typename Rhs>
+class GeMatcher : public ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe> {
+ public:
+  explicit GeMatcher(const Rhs& rhs)
+      : ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe>(rhs) { }
+  static const char* Desc() { return "is >="; }
+  static const char* NegatedDesc() { return "isn't >="; }
+};
+
+template <typename T, typename = typename std::enable_if<
+                          std::is_constructible<std::string, T>::value>::type>
+using StringLike = T;
+
+// Implements polymorphic matchers MatchesRegex(regex) and
+// ContainsRegex(regex), which can be used as a Matcher<T> as long as
+// T can be converted to a string.
+class MatchesRegexMatcher {
+ public:
+  MatchesRegexMatcher(const RE* regex, bool full_match)
+      : regex_(regex), full_match_(full_match) {}
+
+#if GTEST_INTERNAL_HAS_STRING_VIEW
+  bool MatchAndExplain(const internal::StringView& s,
+                       MatchResultListener* listener) const {
+    return MatchAndExplain(std::string(s), listener);
+  }
+#endif  // GTEST_INTERNAL_HAS_STRING_VIEW
+
+  // Accepts pointer types, particularly:
+  //   const char*
+  //   char*
+  //   const wchar_t*
+  //   wchar_t*
+  template <typename CharType>
+  bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
+    return s != nullptr && MatchAndExplain(std::string(s), listener);
+  }
+
+  // Matches anything that can convert to std::string.
+  //
+  // This is a template, not just a plain function with const std::string&,
+  // because absl::string_view has some interfering non-explicit constructors.
+  template <class MatcheeStringType>
+  bool MatchAndExplain(const MatcheeStringType& s,
+                       MatchResultListener* /* listener */) const {
+    const std::string& s2(s);
+    return full_match_ ? RE::FullMatch(s2, *regex_)
+                       : RE::PartialMatch(s2, *regex_);
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << (full_match_ ? "matches" : "contains") << " regular expression ";
+    UniversalPrinter<std::string>::Print(regex_->pattern(), os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't " << (full_match_ ? "match" : "contain")
+        << " regular expression ";
+    UniversalPrinter<std::string>::Print(regex_->pattern(), os);
+  }
+
+ private:
+  const std::shared_ptr<const RE> regex_;
+  const bool full_match_;
+};
+}  // namespace internal
+
+// Matches a string that fully matches regular expression 'regex'.
+// The matcher takes ownership of 'regex'.
+inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
+    const internal::RE* regex) {
+  return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true));
+}
+template <typename T = std::string>
+PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
+    const internal::StringLike<T>& regex) {
+  return MatchesRegex(new internal::RE(std::string(regex)));
+}
+
+// Matches a string that contains regular expression 'regex'.
+// The matcher takes ownership of 'regex'.
+inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
+    const internal::RE* regex) {
+  return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false));
+}
+template <typename T = std::string>
+PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
+    const internal::StringLike<T>& regex) {
+  return ContainsRegex(new internal::RE(std::string(regex)));
+}
+
+// Creates a polymorphic matcher that matches anything equal to x.
+// Note: if the parameter of Eq() were declared as const T&, Eq("foo")
+// wouldn't compile.
+template <typename T>
+inline internal::EqMatcher<T> Eq(T x) { return internal::EqMatcher<T>(x); }
+
+// Constructs a Matcher<T> from a 'value' of type T.  The constructed
+// matcher matches any value that's equal to 'value'.
+template <typename T>
+Matcher<T>::Matcher(T value) { *this = Eq(value); }
+
+// Creates a monomorphic matcher that matches anything with type Lhs
+// and equal to rhs.  A user may need to use this instead of Eq(...)
+// in order to resolve an overloading ambiguity.
+//
+// TypedEq<T>(x) is just a convenient short-hand for Matcher<T>(Eq(x))
+// or Matcher<T>(x), but more readable than the latter.
+//
+// We could define similar monomorphic matchers for other comparison
+// operations (e.g. TypedLt, TypedGe, and etc), but decided not to do
+// it yet as those are used much less than Eq() in practice.  A user
+// can always write Matcher<T>(Lt(5)) to be explicit about the type,
+// for example.
+template <typename Lhs, typename Rhs>
+inline Matcher<Lhs> TypedEq(const Rhs& rhs) { return Eq(rhs); }
+
+// Creates a polymorphic matcher that matches anything >= x.
+template <typename Rhs>
+inline internal::GeMatcher<Rhs> Ge(Rhs x) {
+  return internal::GeMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything > x.
+template <typename Rhs>
+inline internal::GtMatcher<Rhs> Gt(Rhs x) {
+  return internal::GtMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything <= x.
+template <typename Rhs>
+inline internal::LeMatcher<Rhs> Le(Rhs x) {
+  return internal::LeMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything < x.
+template <typename Rhs>
+inline internal::LtMatcher<Rhs> Lt(Rhs x) {
+  return internal::LtMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything != x.
+template <typename Rhs>
+inline internal::NeMatcher<Rhs> Ne(Rhs x) {
+  return internal::NeMatcher<Rhs>(x);
+}
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251 5046
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
+
+#include <stdio.h>
+#include <memory>
+
+namespace testing {
+namespace internal {
+
+GTEST_DECLARE_string_(internal_run_death_test);
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kDeathTestStyleFlag[] = "death_test_style";
+const char kDeathTestUseFork[] = "death_test_use_fork";
+const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
+
+#if GTEST_HAS_DEATH_TEST
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+// DeathTest is a class that hides much of the complexity of the
+// GTEST_DEATH_TEST_ macro.  It is abstract; its static Create method
+// returns a concrete class that depends on the prevailing death test
+// style, as defined by the --gtest_death_test_style and/or
+// --gtest_internal_run_death_test flags.
+
+// In describing the results of death tests, these terms are used with
+// the corresponding definitions:
+//
+// exit status:  The integer exit information in the format specified
+//               by wait(2)
+// exit code:    The integer code passed to exit(3), _exit(2), or
+//               returned from main()
+class GTEST_API_ DeathTest {
+ public:
+  // Create returns false if there was an error determining the
+  // appropriate action to take for the current death test; for example,
+  // if the gtest_death_test_style flag is set to an invalid value.
+  // The LastMessage method will return a more detailed message in that
+  // case.  Otherwise, the DeathTest pointer pointed to by the "test"
+  // argument is set.  If the death test should be skipped, the pointer
+  // is set to NULL; otherwise, it is set to the address of a new concrete
+  // DeathTest object that controls the execution of the current test.
+  static bool Create(const char* statement, Matcher<const std::string&> matcher,
+                     const char* file, int line, DeathTest** test);
+  DeathTest();
+  virtual ~DeathTest() { }
+
+  // A helper class that aborts a death test when it's deleted.
+  class ReturnSentinel {
+   public:
+    explicit ReturnSentinel(DeathTest* test) : test_(test) { }
+    ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
+   private:
+    DeathTest* const test_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
+  } GTEST_ATTRIBUTE_UNUSED_;
+
+  // An enumeration of possible roles that may be taken when a death
+  // test is encountered.  EXECUTE means that the death test logic should
+  // be executed immediately.  OVERSEE means that the program should prepare
+  // the appropriate environment for a child process to execute the death
+  // test, then wait for it to complete.
+  enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
+
+  // An enumeration of the three reasons that a test might be aborted.
+  enum AbortReason {
+    TEST_ENCOUNTERED_RETURN_STATEMENT,
+    TEST_THREW_EXCEPTION,
+    TEST_DID_NOT_DIE
+  };
+
+  // Assumes one of the above roles.
+  virtual TestRole AssumeRole() = 0;
+
+  // Waits for the death test to finish and returns its status.
+  virtual int Wait() = 0;
+
+  // Returns true if the death test passed; that is, the test process
+  // exited during the test, its exit status matches a user-supplied
+  // predicate, and its stderr output matches a user-supplied regular
+  // expression.
+  // The user-supplied predicate may be a macro expression rather
+  // than a function pointer or functor, or else Wait and Passed could
+  // be combined.
+  virtual bool Passed(bool exit_status_ok) = 0;
+
+  // Signals that the death test did not die as expected.
+  virtual void Abort(AbortReason reason) = 0;
+
+  // Returns a human-readable outcome message regarding the outcome of
+  // the last death test.
+  static const char* LastMessage();
+
+  static void set_last_death_test_message(const std::string& message);
+
+ private:
+  // A string containing a description of the outcome of the last death test.
+  static std::string last_death_test_message_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
+};
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+// Factory interface for death tests.  May be mocked out for testing.
+class DeathTestFactory {
+ public:
+  virtual ~DeathTestFactory() { }
+  virtual bool Create(const char* statement,
+                      Matcher<const std::string&> matcher, const char* file,
+                      int line, DeathTest** test) = 0;
+};
+
+// A concrete DeathTestFactory implementation for normal use.
+class DefaultDeathTestFactory : public DeathTestFactory {
+ public:
+  bool Create(const char* statement, Matcher<const std::string&> matcher,
+              const char* file, int line, DeathTest** test) override;
+};
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
+
+// A string passed to EXPECT_DEATH (etc.) is caught by one of these overloads
+// and interpreted as a regex (rather than an Eq matcher) for legacy
+// compatibility.
+inline Matcher<const ::std::string&> MakeDeathTestMatcher(
+    ::testing::internal::RE regex) {
+  return ContainsRegex(regex.pattern());
+}
+inline Matcher<const ::std::string&> MakeDeathTestMatcher(const char* regex) {
+  return ContainsRegex(regex);
+}
+inline Matcher<const ::std::string&> MakeDeathTestMatcher(
+    const ::std::string& regex) {
+  return ContainsRegex(regex);
+}
+
+// If a Matcher<const ::std::string&> is passed to EXPECT_DEATH (etc.), it's
+// used directly.
+inline Matcher<const ::std::string&> MakeDeathTestMatcher(
+    Matcher<const ::std::string&> matcher) {
+  return matcher;
+}
+
+// Traps C++ exceptions escaping statement and reports them as test
+// failures. Note that trapping SEH exceptions is not implemented here.
+# if GTEST_HAS_EXCEPTIONS
+#  define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+  try { \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+  } catch (const ::std::exception& gtest_exception) { \
+    fprintf(\
+        stderr, \
+        "\n%s: Caught std::exception-derived exception escaping the " \
+        "death test statement. Exception message: %s\n", \
+        ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
+        gtest_exception.what()); \
+    fflush(stderr); \
+    death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+  } catch (...) { \
+    death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+  }
+
+# else
+#  define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+  GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+
+# endif
+
+// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
+// ASSERT_EXIT*, and EXPECT_EXIT*.
+#define GTEST_DEATH_TEST_(statement, predicate, regex_or_matcher, fail)        \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                                \
+  if (::testing::internal::AlwaysTrue()) {                                     \
+    ::testing::internal::DeathTest* gtest_dt;                                  \
+    if (!::testing::internal::DeathTest::Create(                               \
+            #statement,                                                        \
+            ::testing::internal::MakeDeathTestMatcher(regex_or_matcher),       \
+            __FILE__, __LINE__, &gtest_dt)) {                                  \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__);                        \
+    }                                                                          \
+    if (gtest_dt != nullptr) {                                                 \
+      std::unique_ptr< ::testing::internal::DeathTest> gtest_dt_ptr(gtest_dt); \
+      switch (gtest_dt->AssumeRole()) {                                        \
+        case ::testing::internal::DeathTest::OVERSEE_TEST:                     \
+          if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) {                \
+            goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__);                  \
+          }                                                                    \
+          break;                                                               \
+        case ::testing::internal::DeathTest::EXECUTE_TEST: {                   \
+          ::testing::internal::DeathTest::ReturnSentinel gtest_sentinel(       \
+              gtest_dt);                                                       \
+          GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt);            \
+          gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE);   \
+          break;                                                               \
+        }                                                                      \
+      }                                                                        \
+    }                                                                          \
+  } else                                                                       \
+    GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__)                                \
+        : fail(::testing::internal::DeathTest::LastMessage())
+// The symbol "fail" here expands to something into which a message
+// can be streamed.
+
+// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in
+// NDEBUG mode. In this case we need the statements to be executed and the macro
+// must accept a streamed message even though the message is never printed.
+// The regex object is not evaluated, but it is used to prevent "unused"
+// warnings and to avoid an expression that doesn't compile in debug mode.
+#define GTEST_EXECUTE_STATEMENT_(statement, regex_or_matcher)    \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                  \
+  if (::testing::internal::AlwaysTrue()) {                       \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);   \
+  } else if (!::testing::internal::AlwaysTrue()) {               \
+    ::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \
+  } else                                                         \
+    ::testing::Message()
+
+// A class representing the parsed contents of the
+// --gtest_internal_run_death_test flag, as it existed when
+// RUN_ALL_TESTS was called.
+class InternalRunDeathTestFlag {
+ public:
+  InternalRunDeathTestFlag(const std::string& a_file,
+                           int a_line,
+                           int an_index,
+                           int a_write_fd)
+      : file_(a_file), line_(a_line), index_(an_index),
+        write_fd_(a_write_fd) {}
+
+  ~InternalRunDeathTestFlag() {
+    if (write_fd_ >= 0)
+      posix::Close(write_fd_);
+  }
+
+  const std::string& file() const { return file_; }
+  int line() const { return line_; }
+  int index() const { return index_; }
+  int write_fd() const { return write_fd_; }
+
+ private:
+  std::string file_;
+  int line_;
+  int index_;
+  int write_fd_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
+};
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+
+namespace testing {
+
+// This flag controls the style of death tests.  Valid values are "threadsafe",
+// meaning that the death test child process will re-execute the test binary
+// from the start, running only a single death test, or "fast",
+// meaning that the child process will execute the test logic immediately
+// after forking.
+GTEST_DECLARE_string_(death_test_style);
+
+#if GTEST_HAS_DEATH_TEST
+
+namespace internal {
+
+// Returns a Boolean value indicating whether the caller is currently
+// executing in the context of the death test child process.  Tools such as
+// Valgrind heap checkers may need this to modify their behavior in death
+// tests.  IMPORTANT: This is an internal utility.  Using it may break the
+// implementation of death tests.  User code MUST NOT use it.
+GTEST_API_ bool InDeathTestChild();
+
+}  // namespace internal
+
+// The following macros are useful for writing death tests.
+
+// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is
+// executed:
+//
+//   1. It generates a warning if there is more than one active
+//   thread.  This is because it's safe to fork() or clone() only
+//   when there is a single thread.
+//
+//   2. The parent process clone()s a sub-process and runs the death
+//   test in it; the sub-process exits with code 0 at the end of the
+//   death test, if it hasn't exited already.
+//
+//   3. The parent process waits for the sub-process to terminate.
+//
+//   4. The parent process checks the exit code and error message of
+//   the sub-process.
+//
+// Examples:
+//
+//   ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number");
+//   for (int i = 0; i < 5; i++) {
+//     EXPECT_DEATH(server.ProcessRequest(i),
+//                  "Invalid request .* in ProcessRequest()")
+//                  << "Failed to die on request " << i;
+//   }
+//
+//   ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting");
+//
+//   bool KilledBySIGHUP(int exit_code) {
+//     return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP;
+//   }
+//
+//   ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
+//
+// The final parameter to each of these macros is a matcher applied to any data
+// the sub-process wrote to stderr.  For compatibility with existing tests, a
+// bare string is interpreted as a regular expression matcher.
+//
+// On the regular expressions used in death tests:
+//
+//   GOOGLETEST_CM0005 DO NOT DELETE
+//   On POSIX-compliant systems (*nix), we use the <regex.h> library,
+//   which uses the POSIX extended regex syntax.
+//
+//   On other platforms (e.g. Windows or Mac), we only support a simple regex
+//   syntax implemented as part of Google Test.  This limited
+//   implementation should be enough most of the time when writing
+//   death tests; though it lacks many features you can find in PCRE
+//   or POSIX extended regex syntax.  For example, we don't support
+//   union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
+//   repetition count ("x{5,7}"), among others.
+//
+//   Below is the syntax that we do support.  We chose it to be a
+//   subset of both PCRE and POSIX extended regex, so it's easy to
+//   learn wherever you come from.  In the following: 'A' denotes a
+//   literal character, period (.), or a single \\ escape sequence;
+//   'x' and 'y' denote regular expressions; 'm' and 'n' are for
+//   natural numbers.
+//
+//     c     matches any literal character c
+//     \\d   matches any decimal digit
+//     \\D   matches any character that's not a decimal digit
+//     \\f   matches \f
+//     \\n   matches \n
+//     \\r   matches \r
+//     \\s   matches any ASCII whitespace, including \n
+//     \\S   matches any character that's not a whitespace
+//     \\t   matches \t
+//     \\v   matches \v
+//     \\w   matches any letter, _, or decimal digit
+//     \\W   matches any character that \\w doesn't match
+//     \\c   matches any literal character c, which must be a punctuation
+//     .     matches any single character except \n
+//     A?    matches 0 or 1 occurrences of A
+//     A*    matches 0 or many occurrences of A
+//     A+    matches 1 or many occurrences of A
+//     ^     matches the beginning of a string (not that of each line)
+//     $     matches the end of a string (not that of each line)
+//     xy    matches x followed by y
+//
+//   If you accidentally use PCRE or POSIX extended regex features
+//   not implemented by us, you will get a run-time failure.  In that
+//   case, please try to rewrite your regular expression within the
+//   above syntax.
+//
+//   This implementation is *not* meant to be as highly tuned or robust
+//   as a compiled regex library, but should perform well enough for a
+//   death test, which already incurs significant overhead by launching
+//   a child process.
+//
+// Known caveats:
+//
+//   A "threadsafe" style death test obtains the path to the test
+//   program from argv[0] and re-executes it in the sub-process.  For
+//   simplicity, the current implementation doesn't search the PATH
+//   when launching the sub-process.  This means that the user must
+//   invoke the test program via a path that contains at least one
+//   path separator (e.g. path/to/foo_test and
+//   /absolute/path/to/bar_test are fine, but foo_test is not).  This
+//   is rarely a problem as people usually don't put the test binary
+//   directory in PATH.
+//
+
+// Asserts that a given `statement` causes the program to exit, with an
+// integer exit status that satisfies `predicate`, and emitting error output
+// that matches `matcher`.
+# define ASSERT_EXIT(statement, predicate, matcher) \
+    GTEST_DEATH_TEST_(statement, predicate, matcher, GTEST_FATAL_FAILURE_)
+
+// Like `ASSERT_EXIT`, but continues on to successive tests in the
+// test suite, if any:
+# define EXPECT_EXIT(statement, predicate, matcher) \
+    GTEST_DEATH_TEST_(statement, predicate, matcher, GTEST_NONFATAL_FAILURE_)
+
+// Asserts that a given `statement` causes the program to exit, either by
+// explicitly exiting with a nonzero exit code or being killed by a
+// signal, and emitting error output that matches `matcher`.
+# define ASSERT_DEATH(statement, matcher) \
+    ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, matcher)
+
+// Like `ASSERT_DEATH`, but continues on to successive tests in the
+// test suite, if any:
+# define EXPECT_DEATH(statement, matcher) \
+    EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, matcher)
+
+// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
+
+// Tests that an exit code describes a normal exit with a given exit code.
+class GTEST_API_ ExitedWithCode {
+ public:
+  explicit ExitedWithCode(int exit_code);
+  ExitedWithCode(const ExitedWithCode&) = default;
+  void operator=(const ExitedWithCode& other) = delete;
+  bool operator()(int exit_status) const;
+ private:
+  const int exit_code_;
+};
+
+# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
+// Tests that an exit code describes an exit due to termination by a
+// given signal.
+// GOOGLETEST_CM0006 DO NOT DELETE
+class GTEST_API_ KilledBySignal {
+ public:
+  explicit KilledBySignal(int signum);
+  bool operator()(int exit_status) const;
+ private:
+  const int signum_;
+};
+# endif  // !GTEST_OS_WINDOWS
+
+// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
+// The death testing framework causes this to have interesting semantics,
+// since the sideeffects of the call are only visible in opt mode, and not
+// in debug mode.
+//
+// In practice, this can be used to test functions that utilize the
+// LOG(DFATAL) macro using the following style:
+//
+// int DieInDebugOr12(int* sideeffect) {
+//   if (sideeffect) {
+//     *sideeffect = 12;
+//   }
+//   LOG(DFATAL) << "death";
+//   return 12;
+// }
+//
+// TEST(TestSuite, TestDieOr12WorksInDgbAndOpt) {
+//   int sideeffect = 0;
+//   // Only asserts in dbg.
+//   EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
+//
+// #ifdef NDEBUG
+//   // opt-mode has sideeffect visible.
+//   EXPECT_EQ(12, sideeffect);
+// #else
+//   // dbg-mode no visible sideeffect.
+//   EXPECT_EQ(0, sideeffect);
+// #endif
+// }
+//
+// This will assert that DieInDebugReturn12InOpt() crashes in debug
+// mode, usually due to a DCHECK or LOG(DFATAL), but returns the
+// appropriate fallback value (12 in this case) in opt mode. If you
+// need to test that a function has appropriate side-effects in opt
+// mode, include assertions against the side-effects.  A general
+// pattern for this is:
+//
+// EXPECT_DEBUG_DEATH({
+//   // Side-effects here will have an effect after this statement in
+//   // opt mode, but none in debug mode.
+//   EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
+// }, "death");
+//
+# ifdef NDEBUG
+
+#  define EXPECT_DEBUG_DEATH(statement, regex) \
+  GTEST_EXECUTE_STATEMENT_(statement, regex)
+
+#  define ASSERT_DEBUG_DEATH(statement, regex) \
+  GTEST_EXECUTE_STATEMENT_(statement, regex)
+
+# else
+
+#  define EXPECT_DEBUG_DEATH(statement, regex) \
+  EXPECT_DEATH(statement, regex)
+
+#  define ASSERT_DEBUG_DEATH(statement, regex) \
+  ASSERT_DEATH(statement, regex)
+
+# endif  // NDEBUG for EXPECT_DEBUG_DEATH
+#endif  // GTEST_HAS_DEATH_TEST
+
+// This macro is used for implementing macros such as
+// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
+// death tests are not supported. Those macros must compile on such systems
+// if and only if EXPECT_DEATH and ASSERT_DEATH compile with the same parameters
+// on systems that support death tests. This allows one to write such a macro on
+// a system that does not support death tests and be sure that it will compile
+// on a death-test supporting system. It is exposed publicly so that systems
+// that have death-tests with stricter requirements than GTEST_HAS_DEATH_TEST
+// can write their own equivalent of EXPECT_DEATH_IF_SUPPORTED and
+// ASSERT_DEATH_IF_SUPPORTED.
+//
+// Parameters:
+//   statement -  A statement that a macro such as EXPECT_DEATH would test
+//                for program termination. This macro has to make sure this
+//                statement is compiled but not executed, to ensure that
+//                EXPECT_DEATH_IF_SUPPORTED compiles with a certain
+//                parameter if and only if EXPECT_DEATH compiles with it.
+//   regex     -  A regex that a macro such as EXPECT_DEATH would use to test
+//                the output of statement.  This parameter has to be
+//                compiled but not evaluated by this macro, to ensure that
+//                this macro only accepts expressions that a macro such as
+//                EXPECT_DEATH would accept.
+//   terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
+//                and a return statement for ASSERT_DEATH_IF_SUPPORTED.
+//                This ensures that ASSERT_DEATH_IF_SUPPORTED will not
+//                compile inside functions where ASSERT_DEATH doesn't
+//                compile.
+//
+//  The branch that has an always false condition is used to ensure that
+//  statement and regex are compiled (and thus syntactically correct) but
+//  never executed. The unreachable code macro protects the terminator
+//  statement from generating an 'unreachable code' warning in case
+//  statement unconditionally returns or throws. The Message constructor at
+//  the end allows the syntax of streaming additional messages into the
+//  macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
+# define GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, terminator) \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+    if (::testing::internal::AlwaysTrue()) { \
+      GTEST_LOG_(WARNING) \
+          << "Death tests are not supported on this platform.\n" \
+          << "Statement '" #statement "' cannot be verified."; \
+    } else if (::testing::internal::AlwaysFalse()) { \
+      ::testing::internal::RE::PartialMatch(".*", (regex)); \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+      terminator; \
+    } else \
+      ::testing::Message()
+
+// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
+// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
+// death tests are supported; otherwise they just issue a warning.  This is
+// useful when you are combining death test assertions with normal test
+// assertions in one test.
+#if GTEST_HAS_DEATH_TEST
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+    EXPECT_DEATH(statement, regex)
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+    ASSERT_DEATH(statement, regex)
+#else
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+    GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, )
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+    GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, return)
+#endif
+
+}  // namespace testing
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Macros and functions for implementing parameterized tests
+// in Google C++ Testing and Mocking Framework (Google Test)
+//
+// GOOGLETEST_CM0001 DO NOT DELETE
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+
+// Value-parameterized tests allow you to test your code with different
+// parameters without writing multiple copies of the same test.
+//
+// Here is how you use value-parameterized tests:
+
+#if 0
+
+// To write value-parameterized tests, first you should define a fixture
+// class. It is usually derived from testing::TestWithParam<T> (see below for
+// another inheritance scheme that's sometimes useful in more complicated
+// class hierarchies), where the type of your parameter values.
+// TestWithParam<T> is itself derived from testing::Test. T can be any
+// copyable type. If it's a raw pointer, you are responsible for managing the
+// lifespan of the pointed values.
+
+class FooTest : public ::testing::TestWithParam<const char*> {
+  // You can implement all the usual class fixture members here.
+};
+
+// Then, use the TEST_P macro to define as many parameterized tests
+// for this fixture as you want. The _P suffix is for "parameterized"
+// or "pattern", whichever you prefer to think.
+
+TEST_P(FooTest, DoesBlah) {
+  // Inside a test, access the test parameter with the GetParam() method
+  // of the TestWithParam<T> class:
+  EXPECT_TRUE(foo.Blah(GetParam()));
+  ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+  ...
+}
+
+// Finally, you can use INSTANTIATE_TEST_SUITE_P to instantiate the test
+// case with any set of parameters you want. Google Test defines a number
+// of functions for generating test parameters. They return what we call
+// (surprise!) parameter generators. Here is a summary of them, which
+// are all in the testing namespace:
+//
+//
+//  Range(begin, end [, step]) - Yields values {begin, begin+step,
+//                               begin+step+step, ...}. The values do not
+//                               include end. step defaults to 1.
+//  Values(v1, v2, ..., vN)    - Yields values {v1, v2, ..., vN}.
+//  ValuesIn(container)        - Yields values from a C-style array, an STL
+//  ValuesIn(begin,end)          container, or an iterator range [begin, end).
+//  Bool()                     - Yields sequence {false, true}.
+//  Combine(g1, g2, ..., gN)   - Yields all combinations (the Cartesian product
+//                               for the math savvy) of the values generated
+//                               by the N generators.
+//
+// For more details, see comments at the definitions of these functions below
+// in this file.
+//
+// The following statement will instantiate tests from the FooTest test suite
+// each with parameter values "meeny", "miny", and "moe".
+
+INSTANTIATE_TEST_SUITE_P(InstantiationName,
+                         FooTest,
+                         Values("meeny", "miny", "moe"));
+
+// To distinguish different instances of the pattern, (yes, you
+// can instantiate it more than once) the first argument to the
+// INSTANTIATE_TEST_SUITE_P macro is a prefix that will be added to the
+// actual test suite name. Remember to pick unique prefixes for different
+// instantiations. The tests from the instantiation above will have
+// these names:
+//
+//    * InstantiationName/FooTest.DoesBlah/0 for "meeny"
+//    * InstantiationName/FooTest.DoesBlah/1 for "miny"
+//    * InstantiationName/FooTest.DoesBlah/2 for "moe"
+//    * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
+//    * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
+//    * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
+//
+// You can use these names in --gtest_filter.
+//
+// This statement will instantiate all tests from FooTest again, each
+// with parameter values "cat" and "dog":
+
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_SUITE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
+
+// The tests from the instantiation above will have these names:
+//
+//    * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
+//
+// Please note that INSTANTIATE_TEST_SUITE_P will instantiate all tests
+// in the given test suite, whether their definitions come before or
+// AFTER the INSTANTIATE_TEST_SUITE_P statement.
+//
+// Please also note that generator expressions (including parameters to the
+// generators) are evaluated in InitGoogleTest(), after main() has started.
+// This allows the user on one hand, to adjust generator parameters in order
+// to dynamically determine a set of tests to run and on the other hand,
+// give the user a chance to inspect the generated tests with Google Test
+// reflection API before RUN_ALL_TESTS() is executed.
+//
+// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
+// for more examples.
+//
+// In the future, we plan to publish the API for defining new parameter
+// generators. But for now this interface remains part of the internal
+// implementation and is subject to change.
+//
+//
+// A parameterized test fixture must be derived from testing::Test and from
+// testing::WithParamInterface<T>, where T is the type of the parameter
+// values. Inheriting from TestWithParam<T> satisfies that requirement because
+// TestWithParam<T> inherits from both Test and WithParamInterface. In more
+// complicated hierarchies, however, it is occasionally useful to inherit
+// separately from Test and WithParamInterface. For example:
+
+class BaseTest : public ::testing::Test {
+  // You can inherit all the usual members for a non-parameterized test
+  // fixture here.
+};
+
+class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
+  // The usual test fixture members go here too.
+};
+
+TEST_F(BaseTest, HasFoo) {
+  // This is an ordinary non-parameterized test.
+}
+
+TEST_P(DerivedTest, DoesBlah) {
+  // GetParam works just the same here as if you inherit from TestWithParam.
+  EXPECT_TRUE(foo.Blah(GetParam()));
+}
+
+#endif  // 0
+
+#include <iterator>
+#include <utility>
+
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+// Type and function utilities for implementing parameterized tests.
+
+// GOOGLETEST_CM0001 DO NOT DELETE
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+
+#include <ctype.h>
+
+#include <cassert>
+#include <iterator>
+#include <memory>
+#include <set>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// GOOGLETEST_CM0001 DO NOT DELETE
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+
+#include <iosfwd>
+#include <vector>
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+namespace testing {
+
+// A copyable object representing the result of a test part (i.e. an
+// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
+//
+// Don't inherit from TestPartResult as its destructor is not virtual.
+class GTEST_API_ TestPartResult {
+ public:
+  // The possible outcomes of a test part (i.e. an assertion or an
+  // explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
+  enum Type {
+    kSuccess,          // Succeeded.
+    kNonFatalFailure,  // Failed but the test can continue.
+    kFatalFailure,     // Failed and the test should be terminated.
+    kSkip              // Skipped.
+  };
+
+  // C'tor.  TestPartResult does NOT have a default constructor.
+  // Always use this constructor (with parameters) to create a
+  // TestPartResult object.
+  TestPartResult(Type a_type, const char* a_file_name, int a_line_number,
+                 const char* a_message)
+      : type_(a_type),
+        file_name_(a_file_name == nullptr ? "" : a_file_name),
+        line_number_(a_line_number),
+        summary_(ExtractSummary(a_message)),
+        message_(a_message) {}
+
+  // Gets the outcome of the test part.
+  Type type() const { return type_; }
+
+  // Gets the name of the source file where the test part took place, or
+  // NULL if it's unknown.
+  const char* file_name() const {
+    return file_name_.empty() ? nullptr : file_name_.c_str();
+  }
+
+  // Gets the line in the source file where the test part took place,
+  // or -1 if it's unknown.
+  int line_number() const { return line_number_; }
+
+  // Gets the summary of the failure message.
+  const char* summary() const { return summary_.c_str(); }
+
+  // Gets the message associated with the test part.
+  const char* message() const { return message_.c_str(); }
+
+  // Returns true if and only if the test part was skipped.
+  bool skipped() const { return type_ == kSkip; }
+
+  // Returns true if and only if the test part passed.
+  bool passed() const { return type_ == kSuccess; }
+
+  // Returns true if and only if the test part non-fatally failed.
+  bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
+
+  // Returns true if and only if the test part fatally failed.
+  bool fatally_failed() const { return type_ == kFatalFailure; }
+
+  // Returns true if and only if the test part failed.
+  bool failed() const { return fatally_failed() || nonfatally_failed(); }
+
+ private:
+  Type type_;
+
+  // Gets the summary of the failure message by omitting the stack
+  // trace in it.
+  static std::string ExtractSummary(const char* message);
+
+  // The name of the source file where the test part took place, or
+  // "" if the source file is unknown.
+  std::string file_name_;
+  // The line in the source file where the test part took place, or -1
+  // if the line number is unknown.
+  int line_number_;
+  std::string summary_;  // The test failure summary.
+  std::string message_;  // The test failure message.
+};
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
+
+// An array of TestPartResult objects.
+//
+// Don't inherit from TestPartResultArray as its destructor is not
+// virtual.
+class GTEST_API_ TestPartResultArray {
+ public:
+  TestPartResultArray() {}
+
+  // Appends the given TestPartResult to the array.
+  void Append(const TestPartResult& result);
+
+  // Returns the TestPartResult at the given index (0-based).
+  const TestPartResult& GetTestPartResult(int index) const;
+
+  // Returns the number of TestPartResult objects in the array.
+  int size() const;
+
+ private:
+  std::vector<TestPartResult> array_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
+};
+
+// This interface knows how to report a test part result.
+class GTEST_API_ TestPartResultReporterInterface {
+ public:
+  virtual ~TestPartResultReporterInterface() {}
+
+  virtual void ReportTestPartResult(const TestPartResult& result) = 0;
+};
+
+namespace internal {
+
+// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a
+// statement generates new fatal failures. To do so it registers itself as the
+// current test part result reporter. Besides checking if fatal failures were
+// reported, it only delegates the reporting to the former result reporter.
+// The original result reporter is restored in the destructor.
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+class GTEST_API_ HasNewFatalFailureHelper
+    : public TestPartResultReporterInterface {
+ public:
+  HasNewFatalFailureHelper();
+  ~HasNewFatalFailureHelper() override;
+  void ReportTestPartResult(const TestPartResult& result) override;
+  bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
+ private:
+  bool has_new_fatal_failure_;
+  TestPartResultReporterInterface* original_reporter_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+
+namespace testing {
+// Input to a parameterized test name generator, describing a test parameter.
+// Consists of the parameter value and the integer parameter index.
+template <class ParamType>
+struct TestParamInfo {
+  TestParamInfo(const ParamType& a_param, size_t an_index) :
+    param(a_param),
+    index(an_index) {}
+  ParamType param;
+  size_t index;
+};
+
+// A builtin parameterized test name generator which returns the result of
+// testing::PrintToString.
+struct PrintToStringParamName {
+  template <class ParamType>
+  std::string operator()(const TestParamInfo<ParamType>& info) const {
+    return PrintToString(info.param);
+  }
+};
+
+namespace internal {
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+// Utility Functions
+
+// Outputs a message explaining invalid registration of different
+// fixture class for the same test suite. This may happen when
+// TEST_P macro is used to define two tests with the same name
+// but in different namespaces.
+GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name,
+                                           CodeLocation code_location);
+
+template <typename> class ParamGeneratorInterface;
+template <typename> class ParamGenerator;
+
+// Interface for iterating over elements provided by an implementation
+// of ParamGeneratorInterface<T>.
+template <typename T>
+class ParamIteratorInterface {
+ public:
+  virtual ~ParamIteratorInterface() {}
+  // A pointer to the base generator instance.
+  // Used only for the purposes of iterator comparison
+  // to make sure that two iterators belong to the same generator.
+  virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
+  // Advances iterator to point to the next element
+  // provided by the generator. The caller is responsible
+  // for not calling Advance() on an iterator equal to
+  // BaseGenerator()->End().
+  virtual void Advance() = 0;
+  // Clones the iterator object. Used for implementing copy semantics
+  // of ParamIterator<T>.
+  virtual ParamIteratorInterface* Clone() const = 0;
+  // Dereferences the current iterator and provides (read-only) access
+  // to the pointed value. It is the caller's responsibility not to call
+  // Current() on an iterator equal to BaseGenerator()->End().
+  // Used for implementing ParamGenerator<T>::operator*().
+  virtual const T* Current() const = 0;
+  // Determines whether the given iterator and other point to the same
+  // element in the sequence generated by the generator.
+  // Used for implementing ParamGenerator<T>::operator==().
+  virtual bool Equals(const ParamIteratorInterface& other) const = 0;
+};
+
+// Class iterating over elements provided by an implementation of
+// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
+// and implements the const forward iterator concept.
+template <typename T>
+class ParamIterator {
+ public:
+  typedef T value_type;
+  typedef const T& reference;
+  typedef ptrdiff_t difference_type;
+
+  // ParamIterator assumes ownership of the impl_ pointer.
+  ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
+  ParamIterator& operator=(const ParamIterator& other) {
+    if (this != &other)
+      impl_.reset(other.impl_->Clone());
+    return *this;
+  }
+
+  const T& operator*() const { return *impl_->Current(); }
+  const T* operator->() const { return impl_->Current(); }
+  // Prefix version of operator++.
+  ParamIterator& operator++() {
+    impl_->Advance();
+    return *this;
+  }
+  // Postfix version of operator++.
+  ParamIterator operator++(int /*unused*/) {
+    ParamIteratorInterface<T>* clone = impl_->Clone();
+    impl_->Advance();
+    return ParamIterator(clone);
+  }
+  bool operator==(const ParamIterator& other) const {
+    return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
+  }
+  bool operator!=(const ParamIterator& other) const {
+    return !(*this == other);
+  }
+
+ private:
+  friend class ParamGenerator<T>;
+  explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
+  std::unique_ptr<ParamIteratorInterface<T> > impl_;
+};
+
+// ParamGeneratorInterface<T> is the binary interface to access generators
+// defined in other translation units.
+template <typename T>
+class ParamGeneratorInterface {
+ public:
+  typedef T ParamType;
+
+  virtual ~ParamGeneratorInterface() {}
+
+  // Generator interface definition
+  virtual ParamIteratorInterface<T>* Begin() const = 0;
+  virtual ParamIteratorInterface<T>* End() const = 0;
+};
+
+// Wraps ParamGeneratorInterface<T> and provides general generator syntax
+// compatible with the STL Container concept.
+// This class implements copy initialization semantics and the contained
+// ParamGeneratorInterface<T> instance is shared among all copies
+// of the original object. This is possible because that instance is immutable.
+template<typename T>
+class ParamGenerator {
+ public:
+  typedef ParamIterator<T> iterator;
+
+  explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
+  ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
+
+  ParamGenerator& operator=(const ParamGenerator& other) {
+    impl_ = other.impl_;
+    return *this;
+  }
+
+  iterator begin() const { return iterator(impl_->Begin()); }
+  iterator end() const { return iterator(impl_->End()); }
+
+ private:
+  std::shared_ptr<const ParamGeneratorInterface<T> > impl_;
+};
+
+// Generates values from a range of two comparable values. Can be used to
+// generate sequences of user-defined types that implement operator+() and
+// operator<().
+// This class is used in the Range() function.
+template <typename T, typename IncrementT>
+class RangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+  RangeGenerator(T begin, T end, IncrementT step)
+      : begin_(begin), end_(end),
+        step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
+  ~RangeGenerator() override {}
+
+  ParamIteratorInterface<T>* Begin() const override {
+    return new Iterator(this, begin_, 0, step_);
+  }
+  ParamIteratorInterface<T>* End() const override {
+    return new Iterator(this, end_, end_index_, step_);
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<T> {
+   public:
+    Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
+             IncrementT step)
+        : base_(base), value_(value), index_(index), step_(step) {}
+    ~Iterator() override {}
+
+    const ParamGeneratorInterface<T>* BaseGenerator() const override {
+      return base_;
+    }
+    void Advance() override {
+      value_ = static_cast<T>(value_ + step_);
+      index_++;
+    }
+    ParamIteratorInterface<T>* Clone() const override {
+      return new Iterator(*this);
+    }
+    const T* Current() const override { return &value_; }
+    bool Equals(const ParamIteratorInterface<T>& other) const override {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const int other_index =
+          CheckedDowncastToActualType<const Iterator>(&other)->index_;
+      return index_ == other_index;
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : ParamIteratorInterface<T>(),
+          base_(other.base_), value_(other.value_), index_(other.index_),
+          step_(other.step_) {}
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<T>* const base_;
+    T value_;
+    int index_;
+    const IncrementT step_;
+  };  // class RangeGenerator::Iterator
+
+  static int CalculateEndIndex(const T& begin,
+                               const T& end,
+                               const IncrementT& step) {
+    int end_index = 0;
+    for (T i = begin; i < end; i = static_cast<T>(i + step))
+      end_index++;
+    return end_index;
+  }
+
+  // No implementation - assignment is unsupported.
+  void operator=(const RangeGenerator& other);
+
+  const T begin_;
+  const T end_;
+  const IncrementT step_;
+  // The index for the end() iterator. All the elements in the generated
+  // sequence are indexed (0-based) to aid iterator comparison.
+  const int end_index_;
+};  // class RangeGenerator
+
+
+// Generates values from a pair of STL-style iterators. Used in the
+// ValuesIn() function. The elements are copied from the source range
+// since the source can be located on the stack, and the generator
+// is likely to persist beyond that stack frame.
+template <typename T>
+class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+  template <typename ForwardIterator>
+  ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
+      : container_(begin, end) {}
+  ~ValuesInIteratorRangeGenerator() override {}
+
+  ParamIteratorInterface<T>* Begin() const override {
+    return new Iterator(this, container_.begin());
+  }
+  ParamIteratorInterface<T>* End() const override {
+    return new Iterator(this, container_.end());
+  }
+
+ private:
+  typedef typename ::std::vector<T> ContainerType;
+
+  class Iterator : public ParamIteratorInterface<T> {
+   public:
+    Iterator(const ParamGeneratorInterface<T>* base,
+             typename ContainerType::const_iterator iterator)
+        : base_(base), iterator_(iterator) {}
+    ~Iterator() override {}
+
+    const ParamGeneratorInterface<T>* BaseGenerator() const override {
+      return base_;
+    }
+    void Advance() override {
+      ++iterator_;
+      value_.reset();
+    }
+    ParamIteratorInterface<T>* Clone() const override {
+      return new Iterator(*this);
+    }
+    // We need to use cached value referenced by iterator_ because *iterator_
+    // can return a temporary object (and of type other then T), so just
+    // having "return &*iterator_;" doesn't work.
+    // value_ is updated here and not in Advance() because Advance()
+    // can advance iterator_ beyond the end of the range, and we cannot
+    // detect that fact. The client code, on the other hand, is
+    // responsible for not calling Current() on an out-of-range iterator.
+    const T* Current() const override {
+      if (value_.get() == nullptr) value_.reset(new T(*iterator_));
+      return value_.get();
+    }
+    bool Equals(const ParamIteratorInterface<T>& other) const override {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      return iterator_ ==
+          CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
+    }
+
+   private:
+    Iterator(const Iterator& other)
+          // The explicit constructor call suppresses a false warning
+          // emitted by gcc when supplied with the -Wextra option.
+        : ParamIteratorInterface<T>(),
+          base_(other.base_),
+          iterator_(other.iterator_) {}
+
+    const ParamGeneratorInterface<T>* const base_;
+    typename ContainerType::const_iterator iterator_;
+    // A cached value of *iterator_. We keep it here to allow access by
+    // pointer in the wrapping iterator's operator->().
+    // value_ needs to be mutable to be accessed in Current().
+    // Use of std::unique_ptr helps manage cached value's lifetime,
+    // which is bound by the lifespan of the iterator itself.
+    mutable std::unique_ptr<const T> value_;
+  };  // class ValuesInIteratorRangeGenerator::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const ValuesInIteratorRangeGenerator& other);
+
+  const ContainerType container_;
+};  // class ValuesInIteratorRangeGenerator
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Default parameterized test name generator, returns a string containing the
+// integer test parameter index.
+template <class ParamType>
+std::string DefaultParamName(const TestParamInfo<ParamType>& info) {
+  Message name_stream;
+  name_stream << info.index;
+  return name_stream.GetString();
+}
+
+template <typename T = int>
+void TestNotEmpty() {
+  static_assert(sizeof(T) == 0, "Empty arguments are not allowed.");
+}
+template <typename T = int>
+void TestNotEmpty(const T&) {}
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Stores a parameter value and later creates tests parameterized with that
+// value.
+template <class TestClass>
+class ParameterizedTestFactory : public TestFactoryBase {
+ public:
+  typedef typename TestClass::ParamType ParamType;
+  explicit ParameterizedTestFactory(ParamType parameter) :
+      parameter_(parameter) {}
+  Test* CreateTest() override {
+    TestClass::SetParam(&parameter_);
+    return new TestClass();
+  }
+
+ private:
+  const ParamType parameter_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactoryBase is a base class for meta-factories that create
+// test factories for passing into MakeAndRegisterTestInfo function.
+template <class ParamType>
+class TestMetaFactoryBase {
+ public:
+  virtual ~TestMetaFactoryBase() {}
+
+  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactory creates test factories for passing into
+// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
+// ownership of test factory pointer, same factory object cannot be passed
+// into that method twice. But ParameterizedTestSuiteInfo is going to call
+// it for each Test/Parameter value combination. Thus it needs meta factory
+// creator class.
+template <class TestSuite>
+class TestMetaFactory
+    : public TestMetaFactoryBase<typename TestSuite::ParamType> {
+ public:
+  using ParamType = typename TestSuite::ParamType;
+
+  TestMetaFactory() {}
+
+  TestFactoryBase* CreateTestFactory(ParamType parameter) override {
+    return new ParameterizedTestFactory<TestSuite>(parameter);
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestSuiteInfoBase is a generic interface
+// to ParameterizedTestSuiteInfo classes. ParameterizedTestSuiteInfoBase
+// accumulates test information provided by TEST_P macro invocations
+// and generators provided by INSTANTIATE_TEST_SUITE_P macro invocations
+// and uses that information to register all resulting test instances
+// in RegisterTests method. The ParameterizeTestSuiteRegistry class holds
+// a collection of pointers to the ParameterizedTestSuiteInfo objects
+// and calls RegisterTests() on each of them when asked.
+class ParameterizedTestSuiteInfoBase {
+ public:
+  virtual ~ParameterizedTestSuiteInfoBase() {}
+
+  // Base part of test suite name for display purposes.
+  virtual const std::string& GetTestSuiteName() const = 0;
+  // Test suite id to verify identity.
+  virtual TypeId GetTestSuiteTypeId() const = 0;
+  // UnitTest class invokes this method to register tests in this
+  // test suite right before running them in RUN_ALL_TESTS macro.
+  // This method should not be called more than once on any single
+  // instance of a ParameterizedTestSuiteInfoBase derived class.
+  virtual void RegisterTests() = 0;
+
+ protected:
+  ParameterizedTestSuiteInfoBase() {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Report a the name of a test_suit as safe to ignore
+// as the side effect of construction of this type.
+struct GTEST_API_ MarkAsIgnored {
+  explicit MarkAsIgnored(const char* test_suite);
+};
+
+GTEST_API_ void InsertSyntheticTestCase(const std::string& name,
+                                        CodeLocation location, bool has_test_p);
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestSuiteInfo accumulates tests obtained from TEST_P
+// macro invocations for a particular test suite and generators
+// obtained from INSTANTIATE_TEST_SUITE_P macro invocations for that
+// test suite. It registers tests with all values generated by all
+// generators when asked.
+template <class TestSuite>
+class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
+ public:
+  // ParamType and GeneratorCreationFunc are private types but are required
+  // for declarations of public methods AddTestPattern() and
+  // AddTestSuiteInstantiation().
+  using ParamType = typename TestSuite::ParamType;
+  // A function that returns an instance of appropriate generator type.
+  typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
+  using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&);
+
+  explicit ParameterizedTestSuiteInfo(const char* name,
+                                      CodeLocation code_location)
+      : test_suite_name_(name), code_location_(code_location) {}
+
+  // Test suite base name for display purposes.
+  const std::string& GetTestSuiteName() const override {
+    return test_suite_name_;
+  }
+  // Test suite id to verify identity.
+  TypeId GetTestSuiteTypeId() const override { return GetTypeId<TestSuite>(); }
+  // TEST_P macro uses AddTestPattern() to record information
+  // about a single test in a LocalTestInfo structure.
+  // test_suite_name is the base name of the test suite (without invocation
+  // prefix). test_base_name is the name of an individual test without
+  // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
+  // test suite base name and DoBar is test base name.
+  void AddTestPattern(const char* test_suite_name, const char* test_base_name,
+                      TestMetaFactoryBase<ParamType>* meta_factory,
+                      CodeLocation code_location) {
+    tests_.push_back(std::shared_ptr<TestInfo>(new TestInfo(
+        test_suite_name, test_base_name, meta_factory, code_location)));
+  }
+  // INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information
+  // about a generator.
+  int AddTestSuiteInstantiation(const std::string& instantiation_name,
+                                GeneratorCreationFunc* func,
+                                ParamNameGeneratorFunc* name_func,
+                                const char* file, int line) {
+    instantiations_.push_back(
+        InstantiationInfo(instantiation_name, func, name_func, file, line));
+    return 0;  // Return value used only to run this method in namespace scope.
+  }
+  // UnitTest class invokes this method to register tests in this test suite
+  // right before running tests in RUN_ALL_TESTS macro.
+  // This method should not be called more than once on any single
+  // instance of a ParameterizedTestSuiteInfoBase derived class.
+  // UnitTest has a guard to prevent from calling this method more than once.
+  void RegisterTests() override {
+    bool generated_instantiations = false;
+
+    for (typename TestInfoContainer::iterator test_it = tests_.begin();
+         test_it != tests_.end(); ++test_it) {
+      std::shared_ptr<TestInfo> test_info = *test_it;
+      for (typename InstantiationContainer::iterator gen_it =
+               instantiations_.begin(); gen_it != instantiations_.end();
+               ++gen_it) {
+        const std::string& instantiation_name = gen_it->name;
+        ParamGenerator<ParamType> generator((*gen_it->generator)());
+        ParamNameGeneratorFunc* name_func = gen_it->name_func;
+        const char* file = gen_it->file;
+        int line = gen_it->line;
+
+        std::string test_suite_name;
+        if ( !instantiation_name.empty() )
+          test_suite_name = instantiation_name + "/";
+        test_suite_name += test_info->test_suite_base_name;
+
+        size_t i = 0;
+        std::set<std::string> test_param_names;
+        for (typename ParamGenerator<ParamType>::iterator param_it =
+                 generator.begin();
+             param_it != generator.end(); ++param_it, ++i) {
+          generated_instantiations = true;
+
+          Message test_name_stream;
+
+          std::string param_name = name_func(
+              TestParamInfo<ParamType>(*param_it, i));
+
+          GTEST_CHECK_(IsValidParamName(param_name))
+              << "Parameterized test name '" << param_name
+              << "' is invalid, in " << file
+              << " line " << line << std::endl;
+
+          GTEST_CHECK_(test_param_names.count(param_name) == 0)
+              << "Duplicate parameterized test name '" << param_name
+              << "', in " << file << " line " << line << std::endl;
+
+          test_param_names.insert(param_name);
+
+          if (!test_info->test_base_name.empty()) {
+            test_name_stream << test_info->test_base_name << "/";
+          }
+          test_name_stream << param_name;
+          MakeAndRegisterTestInfo(
+              test_suite_name.c_str(), test_name_stream.GetString().c_str(),
+              nullptr,  // No type parameter.
+              PrintToString(*param_it).c_str(), test_info->code_location,
+              GetTestSuiteTypeId(),
+              SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line),
+              SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line),
+              test_info->test_meta_factory->CreateTestFactory(*param_it));
+        }  // for param_it
+      }  // for gen_it
+    }  // for test_it
+
+    if (!generated_instantiations) {
+      // There are no generaotrs, or they all generate nothing ...
+      InsertSyntheticTestCase(GetTestSuiteName(), code_location_,
+                              !tests_.empty());
+    }
+  }    // RegisterTests
+
+ private:
+  // LocalTestInfo structure keeps information about a single test registered
+  // with TEST_P macro.
+  struct TestInfo {
+    TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name,
+             TestMetaFactoryBase<ParamType>* a_test_meta_factory,
+             CodeLocation a_code_location)
+        : test_suite_base_name(a_test_suite_base_name),
+          test_base_name(a_test_base_name),
+          test_meta_factory(a_test_meta_factory),
+          code_location(a_code_location) {}
+
+    const std::string test_suite_base_name;
+    const std::string test_base_name;
+    const std::unique_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
+    const CodeLocation code_location;
+  };
+  using TestInfoContainer = ::std::vector<std::shared_ptr<TestInfo> >;
+  // Records data received from INSTANTIATE_TEST_SUITE_P macros:
+  //  <Instantiation name, Sequence generator creation function,
+  //     Name generator function, Source file, Source line>
+  struct InstantiationInfo {
+      InstantiationInfo(const std::string &name_in,
+                        GeneratorCreationFunc* generator_in,
+                        ParamNameGeneratorFunc* name_func_in,
+                        const char* file_in,
+                        int line_in)
+          : name(name_in),
+            generator(generator_in),
+            name_func(name_func_in),
+            file(file_in),
+            line(line_in) {}
+
+      std::string name;
+      GeneratorCreationFunc* generator;
+      ParamNameGeneratorFunc* name_func;
+      const char* file;
+      int line;
+  };
+  typedef ::std::vector<InstantiationInfo> InstantiationContainer;
+
+  static bool IsValidParamName(const std::string& name) {
+    // Check for empty string
+    if (name.empty())
+      return false;
+
+    // Check for invalid characters
+    for (std::string::size_type index = 0; index < name.size(); ++index) {
+      if (!IsAlNum(name[index]) && name[index] != '_')
+        return false;
+    }
+
+    return true;
+  }
+
+  const std::string test_suite_name_;
+  CodeLocation code_location_;
+  TestInfoContainer tests_;
+  InstantiationContainer instantiations_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfo);
+};  // class ParameterizedTestSuiteInfo
+
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+template <class TestCase>
+using ParameterizedTestCaseInfo = ParameterizedTestSuiteInfo<TestCase>;
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestSuiteRegistry contains a map of
+// ParameterizedTestSuiteInfoBase classes accessed by test suite names. TEST_P
+// and INSTANTIATE_TEST_SUITE_P macros use it to locate their corresponding
+// ParameterizedTestSuiteInfo descriptors.
+class ParameterizedTestSuiteRegistry {
+ public:
+  ParameterizedTestSuiteRegistry() {}
+  ~ParameterizedTestSuiteRegistry() {
+    for (auto& test_suite_info : test_suite_infos_) {
+      delete test_suite_info;
+    }
+  }
+
+  // Looks up or creates and returns a structure containing information about
+  // tests and instantiations of a particular test suite.
+  template <class TestSuite>
+  ParameterizedTestSuiteInfo<TestSuite>* GetTestSuitePatternHolder(
+      const char* test_suite_name, CodeLocation code_location) {
+    ParameterizedTestSuiteInfo<TestSuite>* typed_test_info = nullptr;
+    for (auto& test_suite_info : test_suite_infos_) {
+      if (test_suite_info->GetTestSuiteName() == test_suite_name) {
+        if (test_suite_info->GetTestSuiteTypeId() != GetTypeId<TestSuite>()) {
+          // Complain about incorrect usage of Google Test facilities
+          // and terminate the program since we cannot guaranty correct
+          // test suite setup and tear-down in this case.
+          ReportInvalidTestSuiteType(test_suite_name, code_location);
+          posix::Abort();
+        } else {
+          // At this point we are sure that the object we found is of the same
+          // type we are looking for, so we downcast it to that type
+          // without further checks.
+          typed_test_info = CheckedDowncastToActualType<
+              ParameterizedTestSuiteInfo<TestSuite> >(test_suite_info);
+        }
+        break;
+      }
+    }
+    if (typed_test_info == nullptr) {
+      typed_test_info = new ParameterizedTestSuiteInfo<TestSuite>(
+          test_suite_name, code_location);
+      test_suite_infos_.push_back(typed_test_info);
+    }
+    return typed_test_info;
+  }
+  void RegisterTests() {
+    for (auto& test_suite_info : test_suite_infos_) {
+      test_suite_info->RegisterTests();
+    }
+  }
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  template <class TestCase>
+  ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
+      const char* test_case_name, CodeLocation code_location) {
+    return GetTestSuitePatternHolder<TestCase>(test_case_name, code_location);
+  }
+
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+ private:
+  using TestSuiteInfoContainer = ::std::vector<ParameterizedTestSuiteInfoBase*>;
+
+  TestSuiteInfoContainer test_suite_infos_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteRegistry);
+};
+
+// Keep track of what type-parameterized test suite are defined and
+// where as well as which are intatiated. This allows susequently
+// identifying suits that are defined but never used.
+class TypeParameterizedTestSuiteRegistry {
+ public:
+  // Add a suite definition
+  void RegisterTestSuite(const char* test_suite_name,
+                         CodeLocation code_location);
+
+  // Add an instantiation of a suit.
+  void RegisterInstantiation(const char* test_suite_name);
+
+  // For each suit repored as defined but not reported as instantiation,
+  // emit a test that reports that fact (configurably, as an error).
+  void CheckForInstantiations();
+
+ private:
+  struct TypeParameterizedTestSuiteInfo {
+    explicit TypeParameterizedTestSuiteInfo(CodeLocation c)
+        : code_location(c), instantiated(false) {}
+
+    CodeLocation code_location;
+    bool instantiated;
+  };
+
+  std::map<std::string, TypeParameterizedTestSuiteInfo> suites_;
+};
+
+}  // namespace internal
+
+// Forward declarations of ValuesIn(), which is implemented in
+// include/gtest/gtest-param-test.h.
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container);
+
+namespace internal {
+// Used in the Values() function to provide polymorphic capabilities.
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4100)
+#endif
+
+template <typename... Ts>
+class ValueArray {
+ public:
+  explicit ValueArray(Ts... v) : v_(FlatTupleConstructTag{}, std::move(v)...) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {  // NOLINT
+    return ValuesIn(MakeVector<T>(MakeIndexSequence<sizeof...(Ts)>()));
+  }
+
+ private:
+  template <typename T, size_t... I>
+  std::vector<T> MakeVector(IndexSequence<I...>) const {
+    return std::vector<T>{static_cast<T>(v_.template Get<I>())...};
+  }
+
+  FlatTuple<Ts...> v_;
+};
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+template <typename... T>
+class CartesianProductGenerator
+    : public ParamGeneratorInterface<::std::tuple<T...>> {
+ public:
+  typedef ::std::tuple<T...> ParamType;
+
+  CartesianProductGenerator(const std::tuple<ParamGenerator<T>...>& g)
+      : generators_(g) {}
+  ~CartesianProductGenerator() override {}
+
+  ParamIteratorInterface<ParamType>* Begin() const override {
+    return new Iterator(this, generators_, false);
+  }
+  ParamIteratorInterface<ParamType>* End() const override {
+    return new Iterator(this, generators_, true);
+  }
+
+ private:
+  template <class I>
+  class IteratorImpl;
+  template <size_t... I>
+  class IteratorImpl<IndexSequence<I...>>
+      : public ParamIteratorInterface<ParamType> {
+   public:
+    IteratorImpl(const ParamGeneratorInterface<ParamType>* base,
+             const std::tuple<ParamGenerator<T>...>& generators, bool is_end)
+        : base_(base),
+          begin_(std::get<I>(generators).begin()...),
+          end_(std::get<I>(generators).end()...),
+          current_(is_end ? end_ : begin_) {
+      ComputeCurrentValue();
+    }
+    ~IteratorImpl() override {}
+
+    const ParamGeneratorInterface<ParamType>* BaseGenerator() const override {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    void Advance() override {
+      assert(!AtEnd());
+      // Advance the last iterator.
+      ++std::get<sizeof...(T) - 1>(current_);
+      // if that reaches end, propagate that up.
+      AdvanceIfEnd<sizeof...(T) - 1>();
+      ComputeCurrentValue();
+    }
+    ParamIteratorInterface<ParamType>* Clone() const override {
+      return new IteratorImpl(*this);
+    }
+
+    const ParamType* Current() const override { return current_value_.get(); }
+
+    bool Equals(const ParamIteratorInterface<ParamType>& other) const override {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const IteratorImpl* typed_other =
+          CheckedDowncastToActualType<const IteratorImpl>(&other);
+
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      if (AtEnd() && typed_other->AtEnd()) return true;
+
+      bool same = true;
+      bool dummy[] = {
+          (same = same && std::get<I>(current_) ==
+                              std::get<I>(typed_other->current_))...};
+      (void)dummy;
+      return same;
+    }
+
+   private:
+    template <size_t ThisI>
+    void AdvanceIfEnd() {
+      if (std::get<ThisI>(current_) != std::get<ThisI>(end_)) return;
+
+      bool last = ThisI == 0;
+      if (last) {
+        // We are done. Nothing else to propagate.
+        return;
+      }
+
+      constexpr size_t NextI = ThisI - (ThisI != 0);
+      std::get<ThisI>(current_) = std::get<ThisI>(begin_);
+      ++std::get<NextI>(current_);
+      AdvanceIfEnd<NextI>();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = std::make_shared<ParamType>(*std::get<I>(current_)...);
+    }
+    bool AtEnd() const {
+      bool at_end = false;
+      bool dummy[] = {
+          (at_end = at_end || std::get<I>(current_) == std::get<I>(end_))...};
+      (void)dummy;
+      return at_end;
+    }
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    std::tuple<typename ParamGenerator<T>::iterator...> begin_;
+    std::tuple<typename ParamGenerator<T>::iterator...> end_;
+    std::tuple<typename ParamGenerator<T>::iterator...> current_;
+    std::shared_ptr<ParamType> current_value_;
+  };
+
+  using Iterator = IteratorImpl<typename MakeIndexSequence<sizeof...(T)>::type>;
+
+  std::tuple<ParamGenerator<T>...> generators_;
+};
+
+template <class... Gen>
+class CartesianProductHolder {
+ public:
+  CartesianProductHolder(const Gen&... g) : generators_(g...) {}
+  template <typename... T>
+  operator ParamGenerator<::std::tuple<T...>>() const {
+    return ParamGenerator<::std::tuple<T...>>(
+        new CartesianProductGenerator<T...>(generators_));
+  }
+
+ private:
+  std::tuple<Gen...> generators_;
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+
+namespace testing {
+
+// Functions producing parameter generators.
+//
+// Google Test uses these generators to produce parameters for value-
+// parameterized tests. When a parameterized test suite is instantiated
+// with a particular generator, Google Test creates and runs tests
+// for each element in the sequence produced by the generator.
+//
+// In the following sample, tests from test suite FooTest are instantiated
+// each three times with parameter values 3, 5, and 8:
+//
+// class FooTest : public TestWithParam<int> { ... };
+//
+// TEST_P(FooTest, TestThis) {
+// }
+// TEST_P(FooTest, TestThat) {
+// }
+// INSTANTIATE_TEST_SUITE_P(TestSequence, FooTest, Values(3, 5, 8));
+//
+
+// Range() returns generators providing sequences of values in a range.
+//
+// Synopsis:
+// Range(start, end)
+//   - returns a generator producing a sequence of values {start, start+1,
+//     start+2, ..., }.
+// Range(start, end, step)
+//   - returns a generator producing a sequence of values {start, start+step,
+//     start+step+step, ..., }.
+// Notes:
+//   * The generated sequences never include end. For example, Range(1, 5)
+//     returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
+//     returns a generator producing {1, 3, 5, 7}.
+//   * start and end must have the same type. That type may be any integral or
+//     floating-point type or a user defined type satisfying these conditions:
+//     * It must be assignable (have operator=() defined).
+//     * It must have operator+() (operator+(int-compatible type) for
+//       two-operand version).
+//     * It must have operator<() defined.
+//     Elements in the resulting sequences will also have that type.
+//   * Condition start < end must be satisfied in order for resulting sequences
+//     to contain any elements.
+//
+template <typename T, typename IncrementT>
+internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
+  return internal::ParamGenerator<T>(
+      new internal::RangeGenerator<T, IncrementT>(start, end, step));
+}
+
+template <typename T>
+internal::ParamGenerator<T> Range(T start, T end) {
+  return Range(start, end, 1);
+}
+
+// ValuesIn() function allows generation of tests with parameters coming from
+// a container.
+//
+// Synopsis:
+// ValuesIn(const T (&array)[N])
+//   - returns a generator producing sequences with elements from
+//     a C-style array.
+// ValuesIn(const Container& container)
+//   - returns a generator producing sequences with elements from
+//     an STL-style container.
+// ValuesIn(Iterator begin, Iterator end)
+//   - returns a generator producing sequences with elements from
+//     a range [begin, end) defined by a pair of STL-style iterators. These
+//     iterators can also be plain C pointers.
+//
+// Please note that ValuesIn copies the values from the containers
+// passed in and keeps them to generate tests in RUN_ALL_TESTS().
+//
+// Examples:
+//
+// This instantiates tests from test suite StringTest
+// each with C-string values of "foo", "bar", and "baz":
+//
+// const char* strings[] = {"foo", "bar", "baz"};
+// INSTANTIATE_TEST_SUITE_P(StringSequence, StringTest, ValuesIn(strings));
+//
+// This instantiates tests from test suite StlStringTest
+// each with STL strings with values "a" and "b":
+//
+// ::std::vector< ::std::string> GetParameterStrings() {
+//   ::std::vector< ::std::string> v;
+//   v.push_back("a");
+//   v.push_back("b");
+//   return v;
+// }
+//
+// INSTANTIATE_TEST_SUITE_P(CharSequence,
+//                          StlStringTest,
+//                          ValuesIn(GetParameterStrings()));
+//
+//
+// This will also instantiate tests from CharTest
+// each with parameter values 'a' and 'b':
+//
+// ::std::list<char> GetParameterChars() {
+//   ::std::list<char> list;
+//   list.push_back('a');
+//   list.push_back('b');
+//   return list;
+// }
+// ::std::list<char> l = GetParameterChars();
+// INSTANTIATE_TEST_SUITE_P(CharSequence2,
+//                          CharTest,
+//                          ValuesIn(l.begin(), l.end()));
+//
+template <typename ForwardIterator>
+internal::ParamGenerator<
+    typename std::iterator_traits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end) {
+  typedef typename std::iterator_traits<ForwardIterator>::value_type ParamType;
+  return internal::ParamGenerator<ParamType>(
+      new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
+}
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
+  return ValuesIn(array, array + N);
+}
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container) {
+  return ValuesIn(container.begin(), container.end());
+}
+
+// Values() allows generating tests from explicitly specified list of
+// parameters.
+//
+// Synopsis:
+// Values(T v1, T v2, ..., T vN)
+//   - returns a generator producing sequences with elements v1, v2, ..., vN.
+//
+// For example, this instantiates tests from test suite BarTest each
+// with values "one", "two", and "three":
+//
+// INSTANTIATE_TEST_SUITE_P(NumSequence,
+//                          BarTest,
+//                          Values("one", "two", "three"));
+//
+// This instantiates tests from test suite BazTest each with values 1, 2, 3.5.
+// The exact type of values will depend on the type of parameter in BazTest.
+//
+// INSTANTIATE_TEST_SUITE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
+//
+//
+template <typename... T>
+internal::ValueArray<T...> Values(T... v) {
+  return internal::ValueArray<T...>(std::move(v)...);
+}
+
+// Bool() allows generating tests with parameters in a set of (false, true).
+//
+// Synopsis:
+// Bool()
+//   - returns a generator producing sequences with elements {false, true}.
+//
+// It is useful when testing code that depends on Boolean flags. Combinations
+// of multiple flags can be tested when several Bool()'s are combined using
+// Combine() function.
+//
+// In the following example all tests in the test suite FlagDependentTest
+// will be instantiated twice with parameters false and true.
+//
+// class FlagDependentTest : public testing::TestWithParam<bool> {
+//   virtual void SetUp() {
+//     external_flag = GetParam();
+//   }
+// }
+// INSTANTIATE_TEST_SUITE_P(BoolSequence, FlagDependentTest, Bool());
+//
+inline internal::ParamGenerator<bool> Bool() {
+  return Values(false, true);
+}
+
+// Combine() allows the user to combine two or more sequences to produce
+// values of a Cartesian product of those sequences' elements.
+//
+// Synopsis:
+// Combine(gen1, gen2, ..., genN)
+//   - returns a generator producing sequences with elements coming from
+//     the Cartesian product of elements from the sequences generated by
+//     gen1, gen2, ..., genN. The sequence elements will have a type of
+//     std::tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
+//     of elements from sequences produces by gen1, gen2, ..., genN.
+//
+// Example:
+//
+// This will instantiate tests in test suite AnimalTest each one with
+// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
+// tuple("dog", BLACK), and tuple("dog", WHITE):
+//
+// enum Color { BLACK, GRAY, WHITE };
+// class AnimalTest
+//     : public testing::TestWithParam<std::tuple<const char*, Color> > {...};
+//
+// TEST_P(AnimalTest, AnimalLooksNice) {...}
+//
+// INSTANTIATE_TEST_SUITE_P(AnimalVariations, AnimalTest,
+//                          Combine(Values("cat", "dog"),
+//                                  Values(BLACK, WHITE)));
+//
+// This will instantiate tests in FlagDependentTest with all variations of two
+// Boolean flags:
+//
+// class FlagDependentTest
+//     : public testing::TestWithParam<std::tuple<bool, bool> > {
+//   virtual void SetUp() {
+//     // Assigns external_flag_1 and external_flag_2 values from the tuple.
+//     std::tie(external_flag_1, external_flag_2) = GetParam();
+//   }
+// };
+//
+// TEST_P(FlagDependentTest, TestFeature1) {
+//   // Test your code using external_flag_1 and external_flag_2 here.
+// }
+// INSTANTIATE_TEST_SUITE_P(TwoBoolSequence, FlagDependentTest,
+//                          Combine(Bool(), Bool()));
+//
+template <typename... Generator>
+internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
+  return internal::CartesianProductHolder<Generator...>(g...);
+}
+
+#define TEST_P(test_suite_name, test_name)                                     \
+  class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)                     \
+      : public test_suite_name {                                               \
+   public:                                                                     \
+    GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {}                    \
+    void TestBody() override;                                                  \
+                                                                               \
+   private:                                                                    \
+    static int AddToRegistry() {                                               \
+      ::testing::UnitTest::GetInstance()                                       \
+          ->parameterized_test_registry()                                      \
+          .GetTestSuitePatternHolder<test_suite_name>(                         \
+              GTEST_STRINGIFY_(test_suite_name),                               \
+              ::testing::internal::CodeLocation(__FILE__, __LINE__))           \
+          ->AddTestPattern(                                                    \
+              GTEST_STRINGIFY_(test_suite_name), GTEST_STRINGIFY_(test_name),  \
+              new ::testing::internal::TestMetaFactory<GTEST_TEST_CLASS_NAME_( \
+                  test_suite_name, test_name)>(),                              \
+              ::testing::internal::CodeLocation(__FILE__, __LINE__));          \
+      return 0;                                                                \
+    }                                                                          \
+    static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_;               \
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name,    \
+                                                           test_name));        \
+  };                                                                           \
+  int GTEST_TEST_CLASS_NAME_(test_suite_name,                                  \
+                             test_name)::gtest_registering_dummy_ =            \
+      GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::AddToRegistry();     \
+  void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()
+
+// The last argument to INSTANTIATE_TEST_SUITE_P allows the user to specify
+// generator and an optional function or functor that generates custom test name
+// suffixes based on the test parameters. Such a function or functor should
+// accept one argument of type testing::TestParamInfo<class ParamType>, and
+// return std::string.
+//
+// testing::PrintToStringParamName is a builtin test suffix generator that
+// returns the value of testing::PrintToString(GetParam()).
+//
+// Note: test names must be non-empty, unique, and may only contain ASCII
+// alphanumeric characters or underscore. Because PrintToString adds quotes
+// to std::string and C strings, it won't work for these types.
+
+#define GTEST_EXPAND_(arg) arg
+#define GTEST_GET_FIRST_(first, ...) first
+#define GTEST_GET_SECOND_(first, second, ...) second
+
+#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...)                \
+  static ::testing::internal::ParamGenerator<test_suite_name::ParamType>      \
+      gtest_##prefix##test_suite_name##_EvalGenerator_() {                    \
+    return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_));        \
+  }                                                                           \
+  static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_(   \
+      const ::testing::TestParamInfo<test_suite_name::ParamType>& info) {     \
+    if (::testing::internal::AlwaysFalse()) {                                 \
+      ::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_(      \
+          __VA_ARGS__,                                                        \
+          ::testing::internal::DefaultParamName<test_suite_name::ParamType>,  \
+          DUMMY_PARAM_)));                                                    \
+      auto t = std::make_tuple(__VA_ARGS__);                                  \
+      static_assert(std::tuple_size<decltype(t)>::value <= 2,                 \
+                    "Too Many Args!");                                        \
+    }                                                                         \
+    return ((GTEST_EXPAND_(GTEST_GET_SECOND_(                                 \
+        __VA_ARGS__,                                                          \
+        ::testing::internal::DefaultParamName<test_suite_name::ParamType>,    \
+        DUMMY_PARAM_))))(info);                                               \
+  }                                                                           \
+  static int gtest_##prefix##test_suite_name##_dummy_                         \
+      GTEST_ATTRIBUTE_UNUSED_ =                                               \
+          ::testing::UnitTest::GetInstance()                                  \
+              ->parameterized_test_registry()                                 \
+              .GetTestSuitePatternHolder<test_suite_name>(                    \
+                  GTEST_STRINGIFY_(test_suite_name),                          \
+                  ::testing::internal::CodeLocation(__FILE__, __LINE__))      \
+              ->AddTestSuiteInstantiation(                                    \
+                  GTEST_STRINGIFY_(prefix),                                   \
+                  &gtest_##prefix##test_suite_name##_EvalGenerator_,          \
+                  &gtest_##prefix##test_suite_name##_EvalGenerateName_,       \
+                  __FILE__, __LINE__)
+
+
+// Allow Marking a Parameterized test class as not needing to be instantiated.
+#define GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(T)                   \
+  namespace gtest_do_not_use_outside_namespace_scope {}                   \
+  static const ::testing::internal::MarkAsIgnored gtest_allow_ignore_##T( \
+      GTEST_STRINGIFY_(T))
+
+// Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+#define INSTANTIATE_TEST_CASE_P                                            \
+  static_assert(::testing::internal::InstantiateTestCase_P_IsDeprecated(), \
+                "");                                                       \
+  INSTANTIATE_TEST_SUITE_P
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+}  // namespace testing
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// Google C++ Testing and Mocking Framework definitions useful in production code.
+// GOOGLETEST_CM0003 DO NOT DELETE
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
+
+// When you need to test the private or protected members of a class,
+// use the FRIEND_TEST macro to declare your tests as friends of the
+// class.  For example:
+//
+// class MyClass {
+//  private:
+//   void PrivateMethod();
+//   FRIEND_TEST(MyClassTest, PrivateMethodWorks);
+// };
+//
+// class MyClassTest : public testing::Test {
+//   // ...
+// };
+//
+// TEST_F(MyClassTest, PrivateMethodWorks) {
+//   // Can call MyClass::PrivateMethod() here.
+// }
+//
+// Note: The test class must be in the same namespace as the class being tested.
+// For example, putting MyClassTest in an anonymous namespace will not work.
+
+#define FRIEND_TEST(test_case_name, test_name)\
+friend class test_case_name##_##test_name##_Test
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// GOOGLETEST_CM0001 DO NOT DELETE
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+
+// This header implements typed tests and type-parameterized tests.
+
+// Typed (aka type-driven) tests repeat the same test for types in a
+// list.  You must know which types you want to test with when writing
+// typed tests. Here's how you do it:
+
+#if 0
+
+// First, define a fixture class template.  It should be parameterized
+// by a type.  Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+ public:
+  ...
+  typedef std::list<T> List;
+  static T shared_;
+  T value_;
+};
+
+// Next, associate a list of types with the test suite, which will be
+// repeated for each type in the list.  The typedef is necessary for
+// the macro to parse correctly.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+TYPED_TEST_SUITE(FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+//   TYPED_TEST_SUITE(FooTest, int);
+
+// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
+// tests for this test suite as you want.
+TYPED_TEST(FooTest, DoesBlah) {
+  // Inside a test, refer to the special name TypeParam to get the type
+  // parameter.  Since we are inside a derived class template, C++ requires
+  // us to visit the members of FooTest via 'this'.
+  TypeParam n = this->value_;
+
+  // To visit static members of the fixture, add the TestFixture::
+  // prefix.
+  n += TestFixture::shared_;
+
+  // To refer to typedefs in the fixture, add the "typename
+  // TestFixture::" prefix.
+  typename TestFixture::List values;
+  values.push_back(n);
+  ...
+}
+
+TYPED_TEST(FooTest, HasPropertyA) { ... }
+
+// TYPED_TEST_SUITE takes an optional third argument which allows to specify a
+// class that generates custom test name suffixes based on the type. This should
+// be a class which has a static template function GetName(int index) returning
+// a string for each type. The provided integer index equals the index of the
+// type in the provided type list. In many cases the index can be ignored.
+//
+// For example:
+//   class MyTypeNames {
+//    public:
+//     template <typename T>
+//     static std::string GetName(int) {
+//       if (std::is_same<T, char>()) return "char";
+//       if (std::is_same<T, int>()) return "int";
+//       if (std::is_same<T, unsigned int>()) return "unsignedInt";
+//     }
+//   };
+//   TYPED_TEST_SUITE(FooTest, MyTypes, MyTypeNames);
+
+#endif  // 0
+
+// Type-parameterized tests are abstract test patterns parameterized
+// by a type.  Compared with typed tests, type-parameterized tests
+// allow you to define the test pattern without knowing what the type
+// parameters are.  The defined pattern can be instantiated with
+// different types any number of times, in any number of translation
+// units.
+//
+// If you are designing an interface or concept, you can define a
+// suite of type-parameterized tests to verify properties that any
+// valid implementation of the interface/concept should have.  Then,
+// each implementation can easily instantiate the test suite to verify
+// that it conforms to the requirements, without having to write
+// similar tests repeatedly.  Here's an example:
+
+#if 0
+
+// First, define a fixture class template.  It should be parameterized
+// by a type.  Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+  ...
+};
+
+// Next, declare that you will define a type-parameterized test suite
+// (the _P suffix is for "parameterized" or "pattern", whichever you
+// prefer):
+TYPED_TEST_SUITE_P(FooTest);
+
+// Then, use TYPED_TEST_P() to define as many type-parameterized tests
+// for this type-parameterized test suite as you want.
+TYPED_TEST_P(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  TypeParam n = 0;
+  ...
+}
+
+TYPED_TEST_P(FooTest, HasPropertyA) { ... }
+
+// Now the tricky part: you need to register all test patterns before
+// you can instantiate them.  The first argument of the macro is the
+// test suite name; the rest are the names of the tests in this test
+// case.
+REGISTER_TYPED_TEST_SUITE_P(FooTest,
+                            DoesBlah, HasPropertyA);
+
+// Finally, you are free to instantiate the pattern with the types you
+// want.  If you put the above code in a header file, you can #include
+// it in multiple C++ source files and instantiate it multiple times.
+//
+// To distinguish different instances of the pattern, the first
+// argument to the INSTANTIATE_* macro is a prefix that will be added
+// to the actual test suite name.  Remember to pick unique prefixes for
+// different instances.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+//   INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, int);
+//
+// Similar to the optional argument of TYPED_TEST_SUITE above,
+// INSTANTIATE_TEST_SUITE_P takes an optional fourth argument which allows to
+// generate custom names.
+//   INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes, MyTypeNames);
+
+#endif  // 0
+
+
+// Implements typed tests.
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the typedef for the type parameters of the
+// given test suite.
+#define GTEST_TYPE_PARAMS_(TestSuiteName) gtest_type_params_##TestSuiteName##_
+
+// Expands to the name of the typedef for the NameGenerator, responsible for
+// creating the suffixes of the name.
+#define GTEST_NAME_GENERATOR_(TestSuiteName) \
+  gtest_type_params_##TestSuiteName##_NameGenerator
+
+#define TYPED_TEST_SUITE(CaseName, Types, ...)                          \
+  typedef ::testing::internal::GenerateTypeList<Types>::type            \
+      GTEST_TYPE_PARAMS_(CaseName);                                     \
+  typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
+      GTEST_NAME_GENERATOR_(CaseName)
+
+#define TYPED_TEST(CaseName, TestName)                                        \
+  static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1,                       \
+                "test-name must not be empty");                               \
+  template <typename gtest_TypeParam_>                                        \
+  class GTEST_TEST_CLASS_NAME_(CaseName, TestName)                            \
+      : public CaseName<gtest_TypeParam_> {                                   \
+   private:                                                                   \
+    typedef CaseName<gtest_TypeParam_> TestFixture;                           \
+    typedef gtest_TypeParam_ TypeParam;                                       \
+    void TestBody() override;                                                 \
+  };                                                                          \
+  static bool gtest_##CaseName##_##TestName##_registered_                     \
+      GTEST_ATTRIBUTE_UNUSED_ = ::testing::internal::TypeParameterizedTest<   \
+          CaseName,                                                           \
+          ::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_(CaseName,   \
+                                                                  TestName)>, \
+          GTEST_TYPE_PARAMS_(                                                 \
+              CaseName)>::Register("",                                        \
+                                   ::testing::internal::CodeLocation(         \
+                                       __FILE__, __LINE__),                   \
+                                   GTEST_STRINGIFY_(CaseName),                \
+                                   GTEST_STRINGIFY_(TestName), 0,             \
+                                   ::testing::internal::GenerateNames<        \
+                                       GTEST_NAME_GENERATOR_(CaseName),       \
+                                       GTEST_TYPE_PARAMS_(CaseName)>());      \
+  template <typename gtest_TypeParam_>                                        \
+  void GTEST_TEST_CLASS_NAME_(CaseName,                                       \
+                              TestName)<gtest_TypeParam_>::TestBody()
+
+// Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+#define TYPED_TEST_CASE                                                \
+  static_assert(::testing::internal::TypedTestCaseIsDeprecated(), ""); \
+  TYPED_TEST_SUITE
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+// Implements type-parameterized tests.
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the namespace name that the type-parameterized tests for
+// the given type-parameterized test suite are defined in.  The exact
+// name of the namespace is subject to change without notice.
+#define GTEST_SUITE_NAMESPACE_(TestSuiteName) gtest_suite_##TestSuiteName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the variable used to remember the names of
+// the defined tests in the given test suite.
+#define GTEST_TYPED_TEST_SUITE_P_STATE_(TestSuiteName) \
+  gtest_typed_test_suite_p_state_##TestSuiteName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
+//
+// Expands to the name of the variable used to remember the names of
+// the registered tests in the given test suite.
+#define GTEST_REGISTERED_TEST_NAMES_(TestSuiteName) \
+  gtest_registered_test_names_##TestSuiteName##_
+
+// The variables defined in the type-parameterized test macros are
+// static as typically these macros are used in a .h file that can be
+// #included in multiple translation units linked together.
+#define TYPED_TEST_SUITE_P(SuiteName)              \
+  static ::testing::internal::TypedTestSuitePState \
+      GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName)
+
+// Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+#define TYPED_TEST_CASE_P                                                 \
+  static_assert(::testing::internal::TypedTestCase_P_IsDeprecated(), ""); \
+  TYPED_TEST_SUITE_P
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+#define TYPED_TEST_P(SuiteName, TestName)                             \
+  namespace GTEST_SUITE_NAMESPACE_(SuiteName) {                       \
+    template <typename gtest_TypeParam_>                              \
+    class TestName : public SuiteName<gtest_TypeParam_> {             \
+     private:                                                         \
+      typedef SuiteName<gtest_TypeParam_> TestFixture;                \
+      typedef gtest_TypeParam_ TypeParam;                             \
+      void TestBody() override;                                       \
+    };                                                                \
+    static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
+        GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName(       \
+            __FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName),          \
+            GTEST_STRINGIFY_(TestName));                              \
+  }                                                                   \
+  template <typename gtest_TypeParam_>                                \
+  void GTEST_SUITE_NAMESPACE_(                                        \
+      SuiteName)::TestName<gtest_TypeParam_>::TestBody()
+
+// Note: this won't work correctly if the trailing arguments are macros.
+#define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...)                         \
+  namespace GTEST_SUITE_NAMESPACE_(SuiteName) {                             \
+    typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_;    \
+  }                                                                         \
+  static const char* const GTEST_REGISTERED_TEST_NAMES_(                    \
+      SuiteName) GTEST_ATTRIBUTE_UNUSED_ =                                  \
+      GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \
+          GTEST_STRINGIFY_(SuiteName), __FILE__, __LINE__, #__VA_ARGS__)
+
+// Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+#define REGISTER_TYPED_TEST_CASE_P                                           \
+  static_assert(::testing::internal::RegisterTypedTestCase_P_IsDeprecated(), \
+                "");                                                         \
+  REGISTER_TYPED_TEST_SUITE_P
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...)       \
+  static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1,                       \
+                "test-suit-prefix must not be empty");                      \
+  static bool gtest_##Prefix##_##SuiteName GTEST_ATTRIBUTE_UNUSED_ =        \
+      ::testing::internal::TypeParameterizedTestSuite<                      \
+          SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_,    \
+          ::testing::internal::GenerateTypeList<Types>::type>::             \
+          Register(GTEST_STRINGIFY_(Prefix),                                \
+                   ::testing::internal::CodeLocation(__FILE__, __LINE__),   \
+                   &GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName),             \
+                   GTEST_STRINGIFY_(SuiteName),                             \
+                   GTEST_REGISTERED_TEST_NAMES_(SuiteName),                 \
+                   ::testing::internal::GenerateNames<                      \
+                       ::testing::internal::NameGeneratorSelector<          \
+                           __VA_ARGS__>::type,                              \
+                       ::testing::internal::GenerateTypeList<Types>::type>())
+
+// Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+#define INSTANTIATE_TYPED_TEST_CASE_P                                      \
+  static_assert(                                                           \
+      ::testing::internal::InstantiateTypedTestCase_P_IsDeprecated(), ""); \
+  INSTANTIATE_TYPED_TEST_SUITE_P
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+
+GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
+/* class A needs to have dll-interface to be used by clients of class B */)
+
+namespace testing {
+
+// Silence C4100 (unreferenced formal parameter) and 4805
+// unsafe mix of type 'const int' and type 'const bool'
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4805)
+# pragma warning(disable:4100)
+#endif
+
+
+// Declares the flags.
+
+// This flag temporary enables the disabled tests.
+GTEST_DECLARE_bool_(also_run_disabled_tests);
+
+// This flag brings the debugger on an assertion failure.
+GTEST_DECLARE_bool_(break_on_failure);
+
+// This flag controls whether Google Test catches all test-thrown exceptions
+// and logs them as failures.
+GTEST_DECLARE_bool_(catch_exceptions);
+
+// This flag enables using colors in terminal output. Available values are
+// "yes" to enable colors, "no" (disable colors), or "auto" (the default)
+// to let Google Test decide.
+GTEST_DECLARE_string_(color);
+
+// This flag controls whether the test runner should continue execution past
+// first failure.
+GTEST_DECLARE_bool_(fail_fast);
+
+// This flag sets up the filter to select by name using a glob pattern
+// the tests to run. If the filter is not given all tests are executed.
+GTEST_DECLARE_string_(filter);
+
+// This flag controls whether Google Test installs a signal handler that dumps
+// debugging information when fatal signals are raised.
+GTEST_DECLARE_bool_(install_failure_signal_handler);
+
+// This flag causes the Google Test to list tests. None of the tests listed
+// are actually run if the flag is provided.
+GTEST_DECLARE_bool_(list_tests);
+
+// This flag controls whether Google Test emits a detailed XML report to a file
+// in addition to its normal textual output.
+GTEST_DECLARE_string_(output);
+
+// This flags control whether Google Test prints only test failures.
+GTEST_DECLARE_bool_(brief);
+
+// This flags control whether Google Test prints the elapsed time for each
+// test.
+GTEST_DECLARE_bool_(print_time);
+
+// This flags control whether Google Test prints UTF8 characters as text.
+GTEST_DECLARE_bool_(print_utf8);
+
+// This flag specifies the random number seed.
+GTEST_DECLARE_int32_(random_seed);
+
+// This flag sets how many times the tests are repeated. The default value
+// is 1. If the value is -1 the tests are repeating forever.
+GTEST_DECLARE_int32_(repeat);
+
+// This flag controls whether Google Test includes Google Test internal
+// stack frames in failure stack traces.
+GTEST_DECLARE_bool_(show_internal_stack_frames);
+
+// When this flag is specified, tests' order is randomized on every iteration.
+GTEST_DECLARE_bool_(shuffle);
+
+// This flag specifies the maximum number of stack frames to be
+// printed in a failure message.
+GTEST_DECLARE_int32_(stack_trace_depth);
+
+// When this flag is specified, a failed assertion will throw an
+// exception if exceptions are enabled, or exit the program with a
+// non-zero code otherwise. For use with an external test framework.
+GTEST_DECLARE_bool_(throw_on_failure);
+
+// When this flag is set with a "host:port" string, on supported
+// platforms test results are streamed to the specified port on
+// the specified host machine.
+GTEST_DECLARE_string_(stream_result_to);
+
+#if GTEST_USE_OWN_FLAGFILE_FLAG_
+GTEST_DECLARE_string_(flagfile);
+#endif  // GTEST_USE_OWN_FLAGFILE_FLAG_
+
+// The upper limit for valid stack trace depths.
+const int kMaxStackTraceDepth = 100;
+
+namespace internal {
+
+class AssertHelper;
+class DefaultGlobalTestPartResultReporter;
+class ExecDeathTest;
+class NoExecDeathTest;
+class FinalSuccessChecker;
+class GTestFlagSaver;
+class StreamingListenerTest;
+class TestResultAccessor;
+class TestEventListenersAccessor;
+class TestEventRepeater;
+class UnitTestRecordPropertyTestHelper;
+class WindowsDeathTest;
+class FuchsiaDeathTest;
+class UnitTestImpl* GetUnitTestImpl();
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+                                    const std::string& message);
+std::set<std::string>* GetIgnoredParameterizedTestSuites();
+
+}  // namespace internal
+
+// The friend relationship of some of these classes is cyclic.
+// If we don't forward declare them the compiler might confuse the classes
+// in friendship clauses with same named classes on the scope.
+class Test;
+class TestSuite;
+
+// Old API is still available but deprecated
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+using TestCase = TestSuite;
+#endif
+class TestInfo;
+class UnitTest;
+
+// A class for indicating whether an assertion was successful.  When
+// the assertion wasn't successful, the AssertionResult object
+// remembers a non-empty message that describes how it failed.
+//
+// To create an instance of this class, use one of the factory functions
+// (AssertionSuccess() and AssertionFailure()).
+//
+// This class is useful for two purposes:
+//   1. Defining predicate functions to be used with Boolean test assertions
+//      EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts
+//   2. Defining predicate-format functions to be
+//      used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
+//
+// For example, if you define IsEven predicate:
+//
+//   testing::AssertionResult IsEven(int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess();
+//     else
+//       return testing::AssertionFailure() << n << " is odd";
+//   }
+//
+// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5)))
+// will print the message
+//
+//   Value of: IsEven(Fib(5))
+//     Actual: false (5 is odd)
+//   Expected: true
+//
+// instead of a more opaque
+//
+//   Value of: IsEven(Fib(5))
+//     Actual: false
+//   Expected: true
+//
+// in case IsEven is a simple Boolean predicate.
+//
+// If you expect your predicate to be reused and want to support informative
+// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up
+// about half as often as positive ones in our tests), supply messages for
+// both success and failure cases:
+//
+//   testing::AssertionResult IsEven(int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess() << n << " is even";
+//     else
+//       return testing::AssertionFailure() << n << " is odd";
+//   }
+//
+// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print
+//
+//   Value of: IsEven(Fib(6))
+//     Actual: true (8 is even)
+//   Expected: false
+//
+// NB: Predicates that support negative Boolean assertions have reduced
+// performance in positive ones so be careful not to use them in tests
+// that have lots (tens of thousands) of positive Boolean assertions.
+//
+// To use this class with EXPECT_PRED_FORMAT assertions such as:
+//
+//   // Verifies that Foo() returns an even number.
+//   EXPECT_PRED_FORMAT1(IsEven, Foo());
+//
+// you need to define:
+//
+//   testing::AssertionResult IsEven(const char* expr, int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess();
+//     else
+//       return testing::AssertionFailure()
+//         << "Expected: " << expr << " is even\n  Actual: it's " << n;
+//   }
+//
+// If Foo() returns 5, you will see the following message:
+//
+//   Expected: Foo() is even
+//     Actual: it's 5
+//
+class GTEST_API_ AssertionResult {
+ public:
+  // Copy constructor.
+  // Used in EXPECT_TRUE/FALSE(assertion_result).
+  AssertionResult(const AssertionResult& other);
+
+// C4800 is a level 3 warning in Visual Studio 2015 and earlier.
+// This warning is not emitted in Visual Studio 2017.
+// This warning is off by default starting in Visual Studio 2019 but can be
+// enabled with command-line options.
+#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920)
+  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */)
+#endif
+
+  // Used in the EXPECT_TRUE/FALSE(bool_expression).
+  //
+  // T must be contextually convertible to bool.
+  //
+  // The second parameter prevents this overload from being considered if
+  // the argument is implicitly convertible to AssertionResult. In that case
+  // we want AssertionResult's copy constructor to be used.
+  template <typename T>
+  explicit AssertionResult(
+      const T& success,
+      typename std::enable_if<
+          !std::is_convertible<T, AssertionResult>::value>::type*
+      /*enabler*/
+      = nullptr)
+      : success_(success) {}
+
+#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920)
+  GTEST_DISABLE_MSC_WARNINGS_POP_()
+#endif
+
+  // Assignment operator.
+  AssertionResult& operator=(AssertionResult other) {
+    swap(other);
+    return *this;
+  }
+
+  // Returns true if and only if the assertion succeeded.
+  operator bool() const { return success_; }  // NOLINT
+
+  // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+  AssertionResult operator!() const;
+
+  // Returns the text streamed into this AssertionResult. Test assertions
+  // use it when they fail (i.e., the predicate's outcome doesn't match the
+  // assertion's expectation). When nothing has been streamed into the
+  // object, returns an empty string.
+  const char* message() const {
+    return message_.get() != nullptr ? message_->c_str() : "";
+  }
+  // Deprecated; please use message() instead.
+  const char* failure_message() const { return message(); }
+
+  // Streams a custom failure message into this object.
+  template <typename T> AssertionResult& operator<<(const T& value) {
+    AppendMessage(Message() << value);
+    return *this;
+  }
+
+  // Allows streaming basic output manipulators such as endl or flush into
+  // this object.
+  AssertionResult& operator<<(
+      ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) {
+    AppendMessage(Message() << basic_manipulator);
+    return *this;
+  }
+
+ private:
+  // Appends the contents of message to message_.
+  void AppendMessage(const Message& a_message) {
+    if (message_.get() == nullptr) message_.reset(new ::std::string);
+    message_->append(a_message.GetString().c_str());
+  }
+
+  // Swap the contents of this AssertionResult with other.
+  void swap(AssertionResult& other);
+
+  // Stores result of the assertion predicate.
+  bool success_;
+  // Stores the message describing the condition in case the expectation
+  // construct is not satisfied with the predicate's outcome.
+  // Referenced via a pointer to avoid taking too much stack frame space
+  // with test assertions.
+  std::unique_ptr< ::std::string> message_;
+};
+
+// Makes a successful assertion result.
+GTEST_API_ AssertionResult AssertionSuccess();
+
+// Makes a failed assertion result.
+GTEST_API_ AssertionResult AssertionFailure();
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << msg.
+GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
+
+}  // namespace testing
+
+// Includes the auto-generated header that implements a family of generic
+// predicate assertion macros. This include comes late because it relies on
+// APIs declared above.
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file is AUTOMATICALLY GENERATED on 01/02/2019 by command
+// 'gen_gtest_pred_impl.py 5'.  DO NOT EDIT BY HAND!
+//
+// Implements a family of generic predicate assertion macros.
+// GOOGLETEST_CM0001 DO NOT DELETE
+
+#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+
+
+namespace testing {
+
+// This header implements a family of generic predicate assertion
+// macros:
+//
+//   ASSERT_PRED_FORMAT1(pred_format, v1)
+//   ASSERT_PRED_FORMAT2(pred_format, v1, v2)
+//   ...
+//
+// where pred_format is a function or functor that takes n (in the
+// case of ASSERT_PRED_FORMATn) values and their source expression
+// text, and returns a testing::AssertionResult.  See the definition
+// of ASSERT_EQ in gtest.h for an example.
+//
+// If you don't care about formatting, you can use the more
+// restrictive version:
+//
+//   ASSERT_PRED1(pred, v1)
+//   ASSERT_PRED2(pred, v1, v2)
+//   ...
+//
+// where pred is an n-ary function or functor that returns bool,
+// and the values v1, v2, ..., must support the << operator for
+// streaming to std::ostream.
+//
+// We also define the EXPECT_* variations.
+//
+// For now we only support predicates whose arity is at most 5.
+// Please email googletestframework@googlegroups.com if you need
+// support for higher arities.
+
+// GTEST_ASSERT_ is the basic statement to which all of the assertions
+// in this file reduce.  Don't use this in your code.
+
+#define GTEST_ASSERT_(expression, on_failure) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (const ::testing::AssertionResult gtest_ar = (expression)) \
+    ; \
+  else \
+    on_failure(gtest_ar.failure_message())
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED1.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1>
+AssertionResult AssertPred1Helper(const char* pred_text,
+                                  const char* e1,
+                                  Pred pred,
+                                  const T1& v1) {
+  if (pred(v1)) return AssertionSuccess();
+
+  return AssertionFailure()
+         << pred_text << "(" << e1 << ") evaluates to false, where"
+         << "\n"
+         << e1 << " evaluates to " << ::testing::PrintToString(v1);
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, v1), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED1.  Don't use
+// this in your code.
+#define GTEST_PRED1_(pred, v1, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
+                                             #v1, \
+                                             pred, \
+                                             v1), on_failure)
+
+// Unary predicate assertion macros.
+#define EXPECT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED1(pred, v1) \
+  GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED1(pred, v1) \
+  GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED2.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2>
+AssertionResult AssertPred2Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2) {
+  if (pred(v1, v2)) return AssertionSuccess();
+
+  return AssertionFailure()
+         << pred_text << "(" << e1 << ", " << e2
+         << ") evaluates to false, where"
+         << "\n"
+         << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
+         << e2 << " evaluates to " << ::testing::PrintToString(v2);
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED2.  Don't use
+// this in your code.
+#define GTEST_PRED2_(pred, v1, v2, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             pred, \
+                                             v1, \
+                                             v2), on_failure)
+
+// Binary predicate assertion macros.
+#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
+  GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED2(pred, v1, v2) \
+  GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
+  GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED2(pred, v1, v2) \
+  GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED3.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3>
+AssertionResult AssertPred3Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3) {
+  if (pred(v1, v2, v3)) return AssertionSuccess();
+
+  return AssertionFailure()
+         << pred_text << "(" << e1 << ", " << e2 << ", " << e3
+         << ") evaluates to false, where"
+         << "\n"
+         << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
+         << e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
+         << e3 << " evaluates to " << ::testing::PrintToString(v3);
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED3.  Don't use
+// this in your code.
+#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3), on_failure)
+
+// Ternary predicate assertion macros.
+#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+  GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED3(pred, v1, v2, v3) \
+  GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+  GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED3(pred, v1, v2, v3) \
+  GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED4.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3,
+          typename T4>
+AssertionResult AssertPred4Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  const char* e4,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3,
+                                  const T4& v4) {
+  if (pred(v1, v2, v3, v4)) return AssertionSuccess();
+
+  return AssertionFailure()
+         << pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4
+         << ") evaluates to false, where"
+         << "\n"
+         << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
+         << e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
+         << e3 << " evaluates to " << ::testing::PrintToString(v3) << "\n"
+         << e4 << " evaluates to " << ::testing::PrintToString(v4);
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED4.  Don't use
+// this in your code.
+#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             #v4, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3, \
+                                             v4), on_failure)
+
+// 4-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+  GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED4(pred, v1, v2, v3, v4) \
+  GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+  GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
+  GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED5.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3,
+          typename T4,
+          typename T5>
+AssertionResult AssertPred5Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  const char* e4,
+                                  const char* e5,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3,
+                                  const T4& v4,
+                                  const T5& v5) {
+  if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
+
+  return AssertionFailure()
+         << pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4
+         << ", " << e5 << ") evaluates to false, where"
+         << "\n"
+         << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
+         << e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
+         << e3 << " evaluates to " << ::testing::PrintToString(v3) << "\n"
+         << e4 << " evaluates to " << ::testing::PrintToString(v4) << "\n"
+         << e5 << " evaluates to " << ::testing::PrintToString(v5);
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED5.  Don't use
+// this in your code.
+#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             #v4, \
+                                             #v5, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3, \
+                                             v4, \
+                                             v5), on_failure)
+
+// 5-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+  GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \
+  GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+  GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
+  GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+
+
+
+}  // namespace testing
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+
+namespace testing {
+
+// The abstract class that all tests inherit from.
+//
+// In Google Test, a unit test program contains one or many TestSuites, and
+// each TestSuite contains one or many Tests.
+//
+// When you define a test using the TEST macro, you don't need to
+// explicitly derive from Test - the TEST macro automatically does
+// this for you.
+//
+// The only time you derive from Test is when defining a test fixture
+// to be used in a TEST_F.  For example:
+//
+//   class FooTest : public testing::Test {
+//    protected:
+//     void SetUp() override { ... }
+//     void TearDown() override { ... }
+//     ...
+//   };
+//
+//   TEST_F(FooTest, Bar) { ... }
+//   TEST_F(FooTest, Baz) { ... }
+//
+// Test is not copyable.
+class GTEST_API_ Test {
+ public:
+  friend class TestInfo;
+
+  // The d'tor is virtual as we intend to inherit from Test.
+  virtual ~Test();
+
+  // Sets up the stuff shared by all tests in this test suite.
+  //
+  // Google Test will call Foo::SetUpTestSuite() before running the first
+  // test in test suite Foo.  Hence a sub-class can define its own
+  // SetUpTestSuite() method to shadow the one defined in the super
+  // class.
+  static void SetUpTestSuite() {}
+
+  // Tears down the stuff shared by all tests in this test suite.
+  //
+  // Google Test will call Foo::TearDownTestSuite() after running the last
+  // test in test suite Foo.  Hence a sub-class can define its own
+  // TearDownTestSuite() method to shadow the one defined in the super
+  // class.
+  static void TearDownTestSuite() {}
+
+  // Legacy API is deprecated but still available. Use SetUpTestSuite and
+  // TearDownTestSuite instead.
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  static void TearDownTestCase() {}
+  static void SetUpTestCase() {}
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // Returns true if and only if the current test has a fatal failure.
+  static bool HasFatalFailure();
+
+  // Returns true if and only if the current test has a non-fatal failure.
+  static bool HasNonfatalFailure();
+
+  // Returns true if and only if the current test was skipped.
+  static bool IsSkipped();
+
+  // Returns true if and only if the current test has a (either fatal or
+  // non-fatal) failure.
+  static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); }
+
+  // Logs a property for the current test, test suite, or for the entire
+  // invocation of the test program when used outside of the context of a
+  // test suite.  Only the last value for a given key is remembered.  These
+  // are public static so they can be called from utility functions that are
+  // not members of the test fixture.  Calls to RecordProperty made during
+  // lifespan of the test (from the moment its constructor starts to the
+  // moment its destructor finishes) will be output in XML as attributes of
+  // the <testcase> element.  Properties recorded from fixture's
+  // SetUpTestSuite or TearDownTestSuite are logged as attributes of the
+  // corresponding <testsuite> element.  Calls to RecordProperty made in the
+  // global context (before or after invocation of RUN_ALL_TESTS and from
+  // SetUp/TearDown method of Environment objects registered with Google
+  // Test) will be output as attributes of the <testsuites> element.
+  static void RecordProperty(const std::string& key, const std::string& value);
+  static void RecordProperty(const std::string& key, int value);
+
+ protected:
+  // Creates a Test object.
+  Test();
+
+  // Sets up the test fixture.
+  virtual void SetUp();
+
+  // Tears down the test fixture.
+  virtual void TearDown();
+
+ private:
+  // Returns true if and only if the current test has the same fixture class
+  // as the first test in the current test suite.
+  static bool HasSameFixtureClass();
+
+  // Runs the test after the test fixture has been set up.
+  //
+  // A sub-class must implement this to define the test logic.
+  //
+  // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM.
+  // Instead, use the TEST or TEST_F macro.
+  virtual void TestBody() = 0;
+
+  // Sets up, executes, and tears down the test.
+  void Run();
+
+  // Deletes self.  We deliberately pick an unusual name for this
+  // internal method to avoid clashing with names used in user TESTs.
+  void DeleteSelf_() { delete this; }
+
+  const std::unique_ptr<GTEST_FLAG_SAVER_> gtest_flag_saver_;
+
+  // Often a user misspells SetUp() as Setup() and spends a long time
+  // wondering why it is never called by Google Test.  The declaration of
+  // the following method is solely for catching such an error at
+  // compile time:
+  //
+  //   - The return type is deliberately chosen to be not void, so it
+  //   will be a conflict if void Setup() is declared in the user's
+  //   test fixture.
+  //
+  //   - This method is private, so it will be another compiler error
+  //   if the method is called from the user's test fixture.
+  //
+  // DO NOT OVERRIDE THIS FUNCTION.
+  //
+  // If you see an error about overriding the following function or
+  // about it being private, you have mis-spelled SetUp() as Setup().
+  struct Setup_should_be_spelled_SetUp {};
+  virtual Setup_should_be_spelled_SetUp* Setup() { return nullptr; }
+
+  // We disallow copying Tests.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Test);
+};
+
+typedef internal::TimeInMillis TimeInMillis;
+
+// A copyable object representing a user specified test property which can be
+// output as a key/value string pair.
+//
+// Don't inherit from TestProperty as its destructor is not virtual.
+class TestProperty {
+ public:
+  // C'tor.  TestProperty does NOT have a default constructor.
+  // Always use this constructor (with parameters) to create a
+  // TestProperty object.
+  TestProperty(const std::string& a_key, const std::string& a_value) :
+    key_(a_key), value_(a_value) {
+  }
+
+  // Gets the user supplied key.
+  const char* key() const {
+    return key_.c_str();
+  }
+
+  // Gets the user supplied value.
+  const char* value() const {
+    return value_.c_str();
+  }
+
+  // Sets a new value, overriding the one supplied in the constructor.
+  void SetValue(const std::string& new_value) {
+    value_ = new_value;
+  }
+
+ private:
+  // The key supplied by the user.
+  std::string key_;
+  // The value supplied by the user.
+  std::string value_;
+};
+
+// The result of a single Test.  This includes a list of
+// TestPartResults, a list of TestProperties, a count of how many
+// death tests there are in the Test, and how much time it took to run
+// the Test.
+//
+// TestResult is not copyable.
+class GTEST_API_ TestResult {
+ public:
+  // Creates an empty TestResult.
+  TestResult();
+
+  // D'tor.  Do not inherit from TestResult.
+  ~TestResult();
+
+  // Gets the number of all test parts.  This is the sum of the number
+  // of successful test parts and the number of failed test parts.
+  int total_part_count() const;
+
+  // Returns the number of the test properties.
+  int test_property_count() const;
+
+  // Returns true if and only if the test passed (i.e. no test part failed).
+  bool Passed() const { return !Skipped() && !Failed(); }
+
+  // Returns true if and only if the test was skipped.
+  bool Skipped() const;
+
+  // Returns true if and only if the test failed.
+  bool Failed() const;
+
+  // Returns true if and only if the test fatally failed.
+  bool HasFatalFailure() const;
+
+  // Returns true if and only if the test has a non-fatal failure.
+  bool HasNonfatalFailure() const;
+
+  // Returns the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Gets the time of the test case start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp() const { return start_timestamp_; }
+
+  // Returns the i-th test part result among all the results. i can range from 0
+  // to total_part_count() - 1. If i is not in that range, aborts the program.
+  const TestPartResult& GetTestPartResult(int i) const;
+
+  // Returns the i-th test property. i can range from 0 to
+  // test_property_count() - 1. If i is not in that range, aborts the
+  // program.
+  const TestProperty& GetTestProperty(int i) const;
+
+ private:
+  friend class TestInfo;
+  friend class TestSuite;
+  friend class UnitTest;
+  friend class internal::DefaultGlobalTestPartResultReporter;
+  friend class internal::ExecDeathTest;
+  friend class internal::TestResultAccessor;
+  friend class internal::UnitTestImpl;
+  friend class internal::WindowsDeathTest;
+  friend class internal::FuchsiaDeathTest;
+
+  // Gets the vector of TestPartResults.
+  const std::vector<TestPartResult>& test_part_results() const {
+    return test_part_results_;
+  }
+
+  // Gets the vector of TestProperties.
+  const std::vector<TestProperty>& test_properties() const {
+    return test_properties_;
+  }
+
+  // Sets the start time.
+  void set_start_timestamp(TimeInMillis start) { start_timestamp_ = start; }
+
+  // Sets the elapsed time.
+  void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; }
+
+  // Adds a test property to the list. The property is validated and may add
+  // a non-fatal failure if invalid (e.g., if it conflicts with reserved
+  // key names). If a property is already recorded for the same key, the
+  // value will be updated, rather than storing multiple values for the same
+  // key.  xml_element specifies the element for which the property is being
+  // recorded and is used for validation.
+  void RecordProperty(const std::string& xml_element,
+                      const TestProperty& test_property);
+
+  // Adds a failure if the key is a reserved attribute of Google Test
+  // testsuite tags.  Returns true if the property is valid.
+  // FIXME: Validate attribute names are legal and human readable.
+  static bool ValidateTestProperty(const std::string& xml_element,
+                                   const TestProperty& test_property);
+
+  // Adds a test part result to the list.
+  void AddTestPartResult(const TestPartResult& test_part_result);
+
+  // Returns the death test count.
+  int death_test_count() const { return death_test_count_; }
+
+  // Increments the death test count, returning the new count.
+  int increment_death_test_count() { return ++death_test_count_; }
+
+  // Clears the test part results.
+  void ClearTestPartResults();
+
+  // Clears the object.
+  void Clear();
+
+  // Protects mutable state of the property vector and of owned
+  // properties, whose values may be updated.
+  internal::Mutex test_properties_mutex_;
+
+  // The vector of TestPartResults
+  std::vector<TestPartResult> test_part_results_;
+  // The vector of TestProperties
+  std::vector<TestProperty> test_properties_;
+  // Running count of death tests.
+  int death_test_count_;
+  // The start time, in milliseconds since UNIX Epoch.
+  TimeInMillis start_timestamp_;
+  // The elapsed time, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+  // We disallow copying TestResult.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult);
+};  // class TestResult
+
+// A TestInfo object stores the following information about a test:
+//
+//   Test suite name
+//   Test name
+//   Whether the test should be run
+//   A function pointer that creates the test object when invoked
+//   Test result
+//
+// The constructor of TestInfo registers itself with the UnitTest
+// singleton such that the RUN_ALL_TESTS() macro knows which tests to
+// run.
+class GTEST_API_ TestInfo {
+ public:
+  // Destructs a TestInfo object.  This function is not virtual, so
+  // don't inherit from TestInfo.
+  ~TestInfo();
+
+  // Returns the test suite name.
+  const char* test_suite_name() const { return test_suite_name_.c_str(); }
+
+// Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  const char* test_case_name() const { return test_suite_name(); }
+#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // Returns the test name.
+  const char* name() const { return name_.c_str(); }
+
+  // Returns the name of the parameter type, or NULL if this is not a typed
+  // or a type-parameterized test.
+  const char* type_param() const {
+    if (type_param_.get() != nullptr) return type_param_->c_str();
+    return nullptr;
+  }
+
+  // Returns the text representation of the value parameter, or NULL if this
+  // is not a value-parameterized test.
+  const char* value_param() const {
+    if (value_param_.get() != nullptr) return value_param_->c_str();
+    return nullptr;
+  }
+
+  // Returns the file name where this test is defined.
+  const char* file() const { return location_.file.c_str(); }
+
+  // Returns the line where this test is defined.
+  int line() const { return location_.line; }
+
+  // Return true if this test should not be run because it's in another shard.
+  bool is_in_another_shard() const { return is_in_another_shard_; }
+
+  // Returns true if this test should run, that is if the test is not
+  // disabled (or it is disabled but the also_run_disabled_tests flag has
+  // been specified) and its full name matches the user-specified filter.
+  //
+  // Google Test allows the user to filter the tests by their full names.
+  // The full name of a test Bar in test suite Foo is defined as
+  // "Foo.Bar".  Only the tests that match the filter will run.
+  //
+  // A filter is a colon-separated list of glob (not regex) patterns,
+  // optionally followed by a '-' and a colon-separated list of
+  // negative patterns (tests to exclude).  A test is run if it
+  // matches one of the positive patterns and does not match any of
+  // the negative patterns.
+  //
+  // For example, *A*:Foo.* is a filter that matches any string that
+  // contains the character 'A' or starts with "Foo.".
+  bool should_run() const { return should_run_; }
+
+  // Returns true if and only if this test will appear in the XML report.
+  bool is_reportable() const {
+    // The XML report includes tests matching the filter, excluding those
+    // run in other shards.
+    return matches_filter_ && !is_in_another_shard_;
+  }
+
+  // Returns the result of the test.
+  const TestResult* result() const { return &result_; }
+
+ private:
+#if GTEST_HAS_DEATH_TEST
+  friend class internal::DefaultDeathTestFactory;
+#endif  // GTEST_HAS_DEATH_TEST
+  friend class Test;
+  friend class TestSuite;
+  friend class internal::UnitTestImpl;
+  friend class internal::StreamingListenerTest;
+  friend TestInfo* internal::MakeAndRegisterTestInfo(
+      const char* test_suite_name, const char* name, const char* type_param,
+      const char* value_param, internal::CodeLocation code_location,
+      internal::TypeId fixture_class_id, internal::SetUpTestSuiteFunc set_up_tc,
+      internal::TearDownTestSuiteFunc tear_down_tc,
+      internal::TestFactoryBase* factory);
+
+  // Constructs a TestInfo object. The newly constructed instance assumes
+  // ownership of the factory object.
+  TestInfo(const std::string& test_suite_name, const std::string& name,
+           const char* a_type_param,   // NULL if not a type-parameterized test
+           const char* a_value_param,  // NULL if not a value-parameterized test
+           internal::CodeLocation a_code_location,
+           internal::TypeId fixture_class_id,
+           internal::TestFactoryBase* factory);
+
+  // Increments the number of death tests encountered in this test so
+  // far.
+  int increment_death_test_count() {
+    return result_.increment_death_test_count();
+  }
+
+  // Creates the test object, runs it, records its result, and then
+  // deletes it.
+  void Run();
+
+  // Skip and records the test result for this object.
+  void Skip();
+
+  static void ClearTestResult(TestInfo* test_info) {
+    test_info->result_.Clear();
+  }
+
+  // These fields are immutable properties of the test.
+  const std::string test_suite_name_;    // test suite name
+  const std::string name_;               // Test name
+  // Name of the parameter type, or NULL if this is not a typed or a
+  // type-parameterized test.
+  const std::unique_ptr<const ::std::string> type_param_;
+  // Text representation of the value parameter, or NULL if this is not a
+  // value-parameterized test.
+  const std::unique_ptr<const ::std::string> value_param_;
+  internal::CodeLocation location_;
+  const internal::TypeId fixture_class_id_;  // ID of the test fixture class
+  bool should_run_;           // True if and only if this test should run
+  bool is_disabled_;          // True if and only if this test is disabled
+  bool matches_filter_;       // True if this test matches the
+                              // user-specified filter.
+  bool is_in_another_shard_;  // Will be run in another shard.
+  internal::TestFactoryBase* const factory_;  // The factory that creates
+                                              // the test object
+
+  // This field is mutable and needs to be reset before running the
+  // test for the second time.
+  TestResult result_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo);
+};
+
+// A test suite, which consists of a vector of TestInfos.
+//
+// TestSuite is not copyable.
+class GTEST_API_ TestSuite {
+ public:
+  // Creates a TestSuite with the given name.
+  //
+  // TestSuite does NOT have a default constructor.  Always use this
+  // constructor to create a TestSuite object.
+  //
+  // Arguments:
+  //
+  //   name:         name of the test suite
+  //   a_type_param: the name of the test's type parameter, or NULL if
+  //                 this is not a type-parameterized test.
+  //   set_up_tc:    pointer to the function that sets up the test suite
+  //   tear_down_tc: pointer to the function that tears down the test suite
+  TestSuite(const char* name, const char* a_type_param,
+            internal::SetUpTestSuiteFunc set_up_tc,
+            internal::TearDownTestSuiteFunc tear_down_tc);
+
+  // Destructor of TestSuite.
+  virtual ~TestSuite();
+
+  // Gets the name of the TestSuite.
+  const char* name() const { return name_.c_str(); }
+
+  // Returns the name of the parameter type, or NULL if this is not a
+  // type-parameterized test suite.
+  const char* type_param() const {
+    if (type_param_.get() != nullptr) return type_param_->c_str();
+    return nullptr;
+  }
+
+  // Returns true if any test in this test suite should run.
+  bool should_run() const { return should_run_; }
+
+  // Gets the number of successful tests in this test suite.
+  int successful_test_count() const;
+
+  // Gets the number of skipped tests in this test suite.
+  int skipped_test_count() const;
+
+  // Gets the number of failed tests in this test suite.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests that will be reported in the XML report.
+  int reportable_disabled_test_count() const;
+
+  // Gets the number of disabled tests in this test suite.
+  int disabled_test_count() const;
+
+  // Gets the number of tests to be printed in the XML report.
+  int reportable_test_count() const;
+
+  // Get the number of tests in this test suite that should run.
+  int test_to_run_count() const;
+
+  // Gets the number of all tests in this test suite.
+  int total_test_count() const;
+
+  // Returns true if and only if the test suite passed.
+  bool Passed() const { return !Failed(); }
+
+  // Returns true if and only if the test suite failed.
+  bool Failed() const {
+    return failed_test_count() > 0 || ad_hoc_test_result().Failed();
+  }
+
+  // Returns the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Gets the time of the test suite start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp() const { return start_timestamp_; }
+
+  // Returns the i-th test among all the tests. i can range from 0 to
+  // total_test_count() - 1. If i is not in that range, returns NULL.
+  const TestInfo* GetTestInfo(int i) const;
+
+  // Returns the TestResult that holds test properties recorded during
+  // execution of SetUpTestSuite and TearDownTestSuite.
+  const TestResult& ad_hoc_test_result() const { return ad_hoc_test_result_; }
+
+ private:
+  friend class Test;
+  friend class internal::UnitTestImpl;
+
+  // Gets the (mutable) vector of TestInfos in this TestSuite.
+  std::vector<TestInfo*>& test_info_list() { return test_info_list_; }
+
+  // Gets the (immutable) vector of TestInfos in this TestSuite.
+  const std::vector<TestInfo*>& test_info_list() const {
+    return test_info_list_;
+  }
+
+  // Returns the i-th test among all the tests. i can range from 0 to
+  // total_test_count() - 1. If i is not in that range, returns NULL.
+  TestInfo* GetMutableTestInfo(int i);
+
+  // Sets the should_run member.
+  void set_should_run(bool should) { should_run_ = should; }
+
+  // Adds a TestInfo to this test suite.  Will delete the TestInfo upon
+  // destruction of the TestSuite object.
+  void AddTestInfo(TestInfo * test_info);
+
+  // Clears the results of all tests in this test suite.
+  void ClearResult();
+
+  // Clears the results of all tests in the given test suite.
+  static void ClearTestSuiteResult(TestSuite* test_suite) {
+    test_suite->ClearResult();
+  }
+
+  // Runs every test in this TestSuite.
+  void Run();
+
+  // Skips the execution of tests under this TestSuite
+  void Skip();
+
+  // Runs SetUpTestSuite() for this TestSuite.  This wrapper is needed
+  // for catching exceptions thrown from SetUpTestSuite().
+  void RunSetUpTestSuite() {
+    if (set_up_tc_ != nullptr) {
+      (*set_up_tc_)();
+    }
+  }
+
+  // Runs TearDownTestSuite() for this TestSuite.  This wrapper is
+  // needed for catching exceptions thrown from TearDownTestSuite().
+  void RunTearDownTestSuite() {
+    if (tear_down_tc_ != nullptr) {
+      (*tear_down_tc_)();
+    }
+  }
+
+  // Returns true if and only if test passed.
+  static bool TestPassed(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Passed();
+  }
+
+  // Returns true if and only if test skipped.
+  static bool TestSkipped(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Skipped();
+  }
+
+  // Returns true if and only if test failed.
+  static bool TestFailed(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Failed();
+  }
+
+  // Returns true if and only if the test is disabled and will be reported in
+  // the XML report.
+  static bool TestReportableDisabled(const TestInfo* test_info) {
+    return test_info->is_reportable() && test_info->is_disabled_;
+  }
+
+  // Returns true if and only if test is disabled.
+  static bool TestDisabled(const TestInfo* test_info) {
+    return test_info->is_disabled_;
+  }
+
+  // Returns true if and only if this test will appear in the XML report.
+  static bool TestReportable(const TestInfo* test_info) {
+    return test_info->is_reportable();
+  }
+
+  // Returns true if the given test should run.
+  static bool ShouldRunTest(const TestInfo* test_info) {
+    return test_info->should_run();
+  }
+
+  // Shuffles the tests in this test suite.
+  void ShuffleTests(internal::Random* random);
+
+  // Restores the test order to before the first shuffle.
+  void UnshuffleTests();
+
+  // Name of the test suite.
+  std::string name_;
+  // Name of the parameter type, or NULL if this is not a typed or a
+  // type-parameterized test.
+  const std::unique_ptr<const ::std::string> type_param_;
+  // The vector of TestInfos in their original order.  It owns the
+  // elements in the vector.
+  std::vector<TestInfo*> test_info_list_;
+  // Provides a level of indirection for the test list to allow easy
+  // shuffling and restoring the test order.  The i-th element in this
+  // vector is the index of the i-th test in the shuffled test list.
+  std::vector<int> test_indices_;
+  // Pointer to the function that sets up the test suite.
+  internal::SetUpTestSuiteFunc set_up_tc_;
+  // Pointer to the function that tears down the test suite.
+  internal::TearDownTestSuiteFunc tear_down_tc_;
+  // True if and only if any test in this test suite should run.
+  bool should_run_;
+  // The start time, in milliseconds since UNIX Epoch.
+  TimeInMillis start_timestamp_;
+  // Elapsed time, in milliseconds.
+  TimeInMillis elapsed_time_;
+  // Holds test properties recorded during execution of SetUpTestSuite and
+  // TearDownTestSuite.
+  TestResult ad_hoc_test_result_;
+
+  // We disallow copying TestSuites.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestSuite);
+};
+
+// An Environment object is capable of setting up and tearing down an
+// environment.  You should subclass this to define your own
+// environment(s).
+//
+// An Environment object does the set-up and tear-down in virtual
+// methods SetUp() and TearDown() instead of the constructor and the
+// destructor, as:
+//
+//   1. You cannot safely throw from a destructor.  This is a problem
+//      as in some cases Google Test is used where exceptions are enabled, and
+//      we may want to implement ASSERT_* using exceptions where they are
+//      available.
+//   2. You cannot use ASSERT_* directly in a constructor or
+//      destructor.
+class Environment {
+ public:
+  // The d'tor is virtual as we need to subclass Environment.
+  virtual ~Environment() {}
+
+  // Override this to define how to set up the environment.
+  virtual void SetUp() {}
+
+  // Override this to define how to tear down the environment.
+  virtual void TearDown() {}
+ private:
+  // If you see an error about overriding the following function or
+  // about it being private, you have mis-spelled SetUp() as Setup().
+  struct Setup_should_be_spelled_SetUp {};
+  virtual Setup_should_be_spelled_SetUp* Setup() { return nullptr; }
+};
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Exception which can be thrown from TestEventListener::OnTestPartResult.
+class GTEST_API_ AssertionException
+    : public internal::GoogleTestFailureException {
+ public:
+  explicit AssertionException(const TestPartResult& result)
+      : GoogleTestFailureException(result) {}
+};
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// The interface for tracing execution of tests. The methods are organized in
+// the order the corresponding events are fired.
+class TestEventListener {
+ public:
+  virtual ~TestEventListener() {}
+
+  // Fired before any test activity starts.
+  virtual void OnTestProgramStart(const UnitTest& unit_test) = 0;
+
+  // Fired before each iteration of tests starts.  There may be more than
+  // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration
+  // index, starting from 0.
+  virtual void OnTestIterationStart(const UnitTest& unit_test,
+                                    int iteration) = 0;
+
+  // Fired before environment set-up for each iteration of tests starts.
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0;
+
+  // Fired after environment set-up for each iteration of tests ends.
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0;
+
+  // Fired before the test suite starts.
+  virtual void OnTestSuiteStart(const TestSuite& /*test_suite*/) {}
+
+  //  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // Fired before the test starts.
+  virtual void OnTestStart(const TestInfo& test_info) = 0;
+
+  // Fired after a failed assertion or a SUCCEED() invocation.
+  // If you want to throw an exception from this function to skip to the next
+  // TEST, it must be AssertionException defined above, or inherited from it.
+  virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
+
+  // Fired after the test ends.
+  virtual void OnTestEnd(const TestInfo& test_info) = 0;
+
+  // Fired after the test suite ends.
+  virtual void OnTestSuiteEnd(const TestSuite& /*test_suite*/) {}
+
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {}
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // Fired before environment tear-down for each iteration of tests starts.
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0;
+
+  // Fired after environment tear-down for each iteration of tests ends.
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0;
+
+  // Fired after each iteration of tests finishes.
+  virtual void OnTestIterationEnd(const UnitTest& unit_test,
+                                  int iteration) = 0;
+
+  // Fired after all test activities have ended.
+  virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0;
+};
+
+// The convenience class for users who need to override just one or two
+// methods and are not concerned that a possible change to a signature of
+// the methods they override will not be caught during the build.  For
+// comments about each method please see the definition of TestEventListener
+// above.
+class EmptyTestEventListener : public TestEventListener {
+ public:
+  void OnTestProgramStart(const UnitTest& /*unit_test*/) override {}
+  void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                            int /*iteration*/) override {}
+  void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) override {}
+  void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {}
+  void OnTestSuiteStart(const TestSuite& /*test_suite*/) override {}
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseStart(const TestCase& /*test_case*/) override {}
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  void OnTestStart(const TestInfo& /*test_info*/) override {}
+  void OnTestPartResult(const TestPartResult& /*test_part_result*/) override {}
+  void OnTestEnd(const TestInfo& /*test_info*/) override {}
+  void OnTestSuiteEnd(const TestSuite& /*test_suite*/) override {}
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  void OnTestCaseEnd(const TestCase& /*test_case*/) override {}
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) override {}
+  void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {}
+  void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+                          int /*iteration*/) override {}
+  void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {}
+};
+
+// TestEventListeners lets users add listeners to track events in Google Test.
+class GTEST_API_ TestEventListeners {
+ public:
+  TestEventListeners();
+  ~TestEventListeners();
+
+  // Appends an event listener to the end of the list. Google Test assumes
+  // the ownership of the listener (i.e. it will delete the listener when
+  // the test program finishes).
+  void Append(TestEventListener* listener);
+
+  // Removes the given event listener from the list and returns it.  It then
+  // becomes the caller's responsibility to delete the listener. Returns
+  // NULL if the listener is not found in the list.
+  TestEventListener* Release(TestEventListener* listener);
+
+  // Returns the standard listener responsible for the default console
+  // output.  Can be removed from the listeners list to shut down default
+  // console output.  Note that removing this object from the listener list
+  // with Release transfers its ownership to the caller and makes this
+  // function return NULL the next time.
+  TestEventListener* default_result_printer() const {
+    return default_result_printer_;
+  }
+
+  // Returns the standard listener responsible for the default XML output
+  // controlled by the --gtest_output=xml flag.  Can be removed from the
+  // listeners list by users who want to shut down the default XML output
+  // controlled by this flag and substitute it with custom one.  Note that
+  // removing this object from the listener list with Release transfers its
+  // ownership to the caller and makes this function return NULL the next
+  // time.
+  TestEventListener* default_xml_generator() const {
+    return default_xml_generator_;
+  }
+
+ private:
+  friend class TestSuite;
+  friend class TestInfo;
+  friend class internal::DefaultGlobalTestPartResultReporter;
+  friend class internal::NoExecDeathTest;
+  friend class internal::TestEventListenersAccessor;
+  friend class internal::UnitTestImpl;
+
+  // Returns repeater that broadcasts the TestEventListener events to all
+  // subscribers.
+  TestEventListener* repeater();
+
+  // Sets the default_result_printer attribute to the provided listener.
+  // The listener is also added to the listener list and previous
+  // default_result_printer is removed from it and deleted. The listener can
+  // also be NULL in which case it will not be added to the list. Does
+  // nothing if the previous and the current listener objects are the same.
+  void SetDefaultResultPrinter(TestEventListener* listener);
+
+  // Sets the default_xml_generator attribute to the provided listener.  The
+  // listener is also added to the listener list and previous
+  // default_xml_generator is removed from it and deleted. The listener can
+  // also be NULL in which case it will not be added to the list. Does
+  // nothing if the previous and the current listener objects are the same.
+  void SetDefaultXmlGenerator(TestEventListener* listener);
+
+  // Controls whether events will be forwarded by the repeater to the
+  // listeners in the list.
+  bool EventForwardingEnabled() const;
+  void SuppressEventForwarding();
+
+  // The actual list of listeners.
+  internal::TestEventRepeater* repeater_;
+  // Listener responsible for the standard result output.
+  TestEventListener* default_result_printer_;
+  // Listener responsible for the creation of the XML output file.
+  TestEventListener* default_xml_generator_;
+
+  // We disallow copying TestEventListeners.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners);
+};
+
+// A UnitTest consists of a vector of TestSuites.
+//
+// This is a singleton class.  The only instance of UnitTest is
+// created when UnitTest::GetInstance() is first called.  This
+// instance is never deleted.
+//
+// UnitTest is not copyable.
+//
+// This class is thread-safe as long as the methods are called
+// according to their specification.
+class GTEST_API_ UnitTest {
+ public:
+  // Gets the singleton UnitTest object.  The first time this method
+  // is called, a UnitTest object is constructed and returned.
+  // Consecutive calls will return the same object.
+  static UnitTest* GetInstance();
+
+  // Runs all tests in this UnitTest object and prints the result.
+  // Returns 0 if successful, or 1 otherwise.
+  //
+  // This method can only be called from the main thread.
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  int Run() GTEST_MUST_USE_RESULT_;
+
+  // Returns the working directory when the first TEST() or TEST_F()
+  // was executed.  The UnitTest object owns the string.
+  const char* original_working_dir() const;
+
+  // Returns the TestSuite object for the test that's currently running,
+  // or NULL if no test is running.
+  const TestSuite* current_test_suite() const GTEST_LOCK_EXCLUDED_(mutex_);
+
+// Legacy API is still available but deprecated
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  const TestCase* current_test_case() const GTEST_LOCK_EXCLUDED_(mutex_);
+#endif
+
+  // Returns the TestInfo object for the test that's currently running,
+  // or NULL if no test is running.
+  const TestInfo* current_test_info() const
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Returns the random seed used at the start of the current test run.
+  int random_seed() const;
+
+  // Returns the ParameterizedTestSuiteRegistry object used to keep track of
+  // value-parameterized tests and instantiate and register them.
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  internal::ParameterizedTestSuiteRegistry& parameterized_test_registry()
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Gets the number of successful test suites.
+  int successful_test_suite_count() const;
+
+  // Gets the number of failed test suites.
+  int failed_test_suite_count() const;
+
+  // Gets the number of all test suites.
+  int total_test_suite_count() const;
+
+  // Gets the number of all test suites that contain at least one test
+  // that should run.
+  int test_suite_to_run_count() const;
+
+  //  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  int successful_test_case_count() const;
+  int failed_test_case_count() const;
+  int total_test_case_count() const;
+  int test_case_to_run_count() const;
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // Gets the number of successful tests.
+  int successful_test_count() const;
+
+  // Gets the number of skipped tests.
+  int skipped_test_count() const;
+
+  // Gets the number of failed tests.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests that will be reported in the XML report.
+  int reportable_disabled_test_count() const;
+
+  // Gets the number of disabled tests.
+  int disabled_test_count() const;
+
+  // Gets the number of tests to be printed in the XML report.
+  int reportable_test_count() const;
+
+  // Gets the number of all tests.
+  int total_test_count() const;
+
+  // Gets the number of tests that should run.
+  int test_to_run_count() const;
+
+  // Gets the time of the test program start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp() const;
+
+  // Gets the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const;
+
+  // Returns true if and only if the unit test passed (i.e. all test suites
+  // passed).
+  bool Passed() const;
+
+  // Returns true if and only if the unit test failed (i.e. some test suite
+  // failed or something outside of all tests failed).
+  bool Failed() const;
+
+  // Gets the i-th test suite among all the test suites. i can range from 0 to
+  // total_test_suite_count() - 1. If i is not in that range, returns NULL.
+  const TestSuite* GetTestSuite(int i) const;
+
+//  Legacy API is deprecated but still available
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+  const TestCase* GetTestCase(int i) const;
+#endif  //  GTEST_REMOVE_LEGACY_TEST_CASEAPI_
+
+  // Returns the TestResult containing information on test failures and
+  // properties logged outside of individual test suites.
+  const TestResult& ad_hoc_test_result() const;
+
+  // Returns the list of event listeners that can be used to track events
+  // inside Google Test.
+  TestEventListeners& listeners();
+
+ private:
+  // Registers and returns a global test environment.  When a test
+  // program is run, all global test environments will be set-up in
+  // the order they were registered.  After all tests in the program
+  // have finished, all global test environments will be torn-down in
+  // the *reverse* order they were registered.
+  //
+  // The UnitTest object takes ownership of the given environment.
+  //
+  // This method can only be called from the main thread.
+  Environment* AddEnvironment(Environment* env);
+
+  // Adds a TestPartResult to the current TestResult object.  All
+  // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc)
+  // eventually call this to report their results.  The user code
+  // should use the assertion macros instead of calling this directly.
+  void AddTestPartResult(TestPartResult::Type result_type,
+                         const char* file_name,
+                         int line_number,
+                         const std::string& message,
+                         const std::string& os_stack_trace)
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Adds a TestProperty to the current TestResult object when invoked from
+  // inside a test, to current TestSuite's ad_hoc_test_result_ when invoked
+  // from SetUpTestSuite or TearDownTestSuite, or to the global property set
+  // when invoked elsewhere.  If the result already contains a property with
+  // the same key, the value will be updated.
+  void RecordProperty(const std::string& key, const std::string& value);
+
+  // Gets the i-th test suite among all the test suites. i can range from 0 to
+  // total_test_suite_count() - 1. If i is not in that range, returns NULL.
+  TestSuite* GetMutableTestSuite(int i);
+
+  // Accessors for the implementation object.
+  internal::UnitTestImpl* impl() { return impl_; }
+  const internal::UnitTestImpl* impl() const { return impl_; }
+
+  // These classes and functions are friends as they need to access private
+  // members of UnitTest.
+  friend class ScopedTrace;
+  friend class Test;
+  friend class internal::AssertHelper;
+  friend class internal::StreamingListenerTest;
+  friend class internal::UnitTestRecordPropertyTestHelper;
+  friend Environment* AddGlobalTestEnvironment(Environment* env);
+  friend std::set<std::string>* internal::GetIgnoredParameterizedTestSuites();
+  friend internal::UnitTestImpl* internal::GetUnitTestImpl();
+  friend void internal::ReportFailureInUnknownLocation(
+      TestPartResult::Type result_type,
+      const std::string& message);
+
+  // Creates an empty UnitTest.
+  UnitTest();
+
+  // D'tor
+  virtual ~UnitTest();
+
+  // Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+  // Google Test trace stack.
+  void PushGTestTrace(const internal::TraceInfo& trace)
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Pops a trace from the per-thread Google Test trace stack.
+  void PopGTestTrace()
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Protects mutable state in *impl_.  This is mutable as some const
+  // methods need to lock it too.
+  mutable internal::Mutex mutex_;
+
+  // Opaque implementation object.  This field is never changed once
+  // the object is constructed.  We don't mark it as const here, as
+  // doing so will cause a warning in the constructor of UnitTest.
+  // Mutable state in *impl_ is protected by mutex_.
+  internal::UnitTestImpl* impl_;
+
+  // We disallow copying UnitTest.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest);
+};
+
+// A convenient wrapper for adding an environment for the test
+// program.
+//
+// You should call this before RUN_ALL_TESTS() is called, probably in
+// main().  If you use gtest_main, you need to call this before main()
+// starts for it to take effect.  For example, you can define a global
+// variable like this:
+//
+//   testing::Environment* const foo_env =
+//       testing::AddGlobalTestEnvironment(new FooEnvironment);
+//
+// However, we strongly recommend you to write your own main() and
+// call AddGlobalTestEnvironment() there, as relying on initialization
+// of global variables makes the code harder to read and may cause
+// problems when you register multiple environments from different
+// translation units and the environments have dependencies among them
+// (remember that the compiler doesn't guarantee the order in which
+// global variables from different translation units are initialized).
+inline Environment* AddGlobalTestEnvironment(Environment* env) {
+  return UnitTest::GetInstance()->AddEnvironment(env);
+}
+
+// Initializes Google Test.  This must be called before calling
+// RUN_ALL_TESTS().  In particular, it parses a command line for the
+// flags that Google Test recognizes.  Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+GTEST_API_ void InitGoogleTest(int* argc, char** argv);
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv);
+
+// This overloaded version can be used on Arduino/embedded platforms where
+// there is no argc/argv.
+GTEST_API_ void InitGoogleTest();
+
+namespace internal {
+
+// Separate the error generating code from the code path to reduce the stack
+// frame size of CmpHelperEQ. This helps reduce the overhead of some sanitizers
+// when calling EXPECT_* in a tight loop.
+template <typename T1, typename T2>
+AssertionResult CmpHelperEQFailure(const char* lhs_expression,
+                                   const char* rhs_expression,
+                                   const T1& lhs, const T2& rhs) {
+  return EqFailure(lhs_expression,
+                   rhs_expression,
+                   FormatForComparisonFailureMessage(lhs, rhs),
+                   FormatForComparisonFailureMessage(rhs, lhs),
+                   false);
+}
+
+// This block of code defines operator==/!=
+// to block lexical scope lookup.
+// It prevents using invalid operator==/!= defined at namespace scope.
+struct faketype {};
+inline bool operator==(faketype, faketype) { return true; }
+inline bool operator!=(faketype, faketype) { return false; }
+
+// The helper function for {ASSERT|EXPECT}_EQ.
+template <typename T1, typename T2>
+AssertionResult CmpHelperEQ(const char* lhs_expression,
+                            const char* rhs_expression,
+                            const T1& lhs,
+                            const T2& rhs) {
+  if (lhs == rhs) {
+    return AssertionSuccess();
+  }
+
+  return CmpHelperEQFailure(lhs_expression, rhs_expression, lhs, rhs);
+}
+
+class EqHelper {
+ public:
+  // This templatized version is for the general case.
+  template <
+      typename T1, typename T2,
+      // Disable this overload for cases where one argument is a pointer
+      // and the other is the null pointer constant.
+      typename std::enable_if<!std::is_integral<T1>::value ||
+                              !std::is_pointer<T2>::value>::type* = nullptr>
+  static AssertionResult Compare(const char* lhs_expression,
+                                 const char* rhs_expression, const T1& lhs,
+                                 const T2& rhs) {
+    return CmpHelperEQ(lhs_expression, rhs_expression, lhs, rhs);
+  }
+
+  // With this overloaded version, we allow anonymous enums to be used
+  // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous
+  // enums can be implicitly cast to BiggestInt.
+  //
+  // Even though its body looks the same as the above version, we
+  // cannot merge the two, as it will make anonymous enums unhappy.
+  static AssertionResult Compare(const char* lhs_expression,
+                                 const char* rhs_expression,
+                                 BiggestInt lhs,
+                                 BiggestInt rhs) {
+    return CmpHelperEQ(lhs_expression, rhs_expression, lhs, rhs);
+  }
+
+  template <typename T>
+  static AssertionResult Compare(
+      const char* lhs_expression, const char* rhs_expression,
+      // Handle cases where '0' is used as a null pointer literal.
+      std::nullptr_t /* lhs */, T* rhs) {
+    // We already know that 'lhs' is a null pointer.
+    return CmpHelperEQ(lhs_expression, rhs_expression, static_cast<T*>(nullptr),
+                       rhs);
+  }
+};
+
+// Separate the error generating code from the code path to reduce the stack
+// frame size of CmpHelperOP. This helps reduce the overhead of some sanitizers
+// when calling EXPECT_OP in a tight loop.
+template <typename T1, typename T2>
+AssertionResult CmpHelperOpFailure(const char* expr1, const char* expr2,
+                                   const T1& val1, const T2& val2,
+                                   const char* op) {
+  return AssertionFailure()
+         << "Expected: (" << expr1 << ") " << op << " (" << expr2
+         << "), actual: " << FormatForComparisonFailureMessage(val1, val2)
+         << " vs " << FormatForComparisonFailureMessage(val2, val1);
+}
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_??.  It is here just to avoid copy-and-paste
+// of similar code.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+template <typename T1, typename T2>\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+                                   const T1& val1, const T2& val2) {\
+  if (val1 op val2) {\
+    return AssertionSuccess();\
+  } else {\
+    return CmpHelperOpFailure(expr1, expr2, val1, val2, #op);\
+  }\
+}
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+// Implements the helper function for {ASSERT|EXPECT}_NE
+GTEST_IMPL_CMP_HELPER_(NE, !=)
+// Implements the helper function for {ASSERT|EXPECT}_LE
+GTEST_IMPL_CMP_HELPER_(LE, <=)
+// Implements the helper function for {ASSERT|EXPECT}_LT
+GTEST_IMPL_CMP_HELPER_(LT, <)
+// Implements the helper function for {ASSERT|EXPECT}_GE
+GTEST_IMPL_CMP_HELPER_(GE, >=)
+// Implements the helper function for {ASSERT|EXPECT}_GT
+GTEST_IMPL_CMP_HELPER_(GT, >)
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const char* s1,
+                                          const char* s2);
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* s1_expression,
+                                              const char* s2_expression,
+                                              const char* s1,
+                                              const char* s2);
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const char* s1,
+                                          const char* s2);
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+                                              const char* s2_expression,
+                                              const char* s1,
+                                              const char* s2);
+
+
+// Helper function for *_STREQ on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const wchar_t* s1,
+                                          const wchar_t* s2);
+
+// Helper function for *_STRNE on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const wchar_t* s1,
+                                          const wchar_t* s2);
+
+}  // namespace internal
+
+// IsSubstring() and IsNotSubstring() are intended to be used as the
+// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by
+// themselves.  They check whether needle is a substring of haystack
+// (NULL is considered a substring of itself only), and return an
+// appropriate error message when they fail.
+//
+// The {needle,haystack}_expr arguments are the stringified
+// expressions that generated the two real arguments.
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack);
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack);
+#endif  // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+// Helper template function for comparing floating-points.
+//
+// Template parameter:
+//
+//   RawType: the raw floating-point type (either float or double)
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename RawType>
+AssertionResult CmpHelperFloatingPointEQ(const char* lhs_expression,
+                                         const char* rhs_expression,
+                                         RawType lhs_value,
+                                         RawType rhs_value) {
+  const FloatingPoint<RawType> lhs(lhs_value), rhs(rhs_value);
+
+  if (lhs.AlmostEquals(rhs)) {
+    return AssertionSuccess();
+  }
+
+  ::std::stringstream lhs_ss;
+  lhs_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+         << lhs_value;
+
+  ::std::stringstream rhs_ss;
+  rhs_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+         << rhs_value;
+
+  return EqFailure(lhs_expression,
+                   rhs_expression,
+                   StringStreamToString(&lhs_ss),
+                   StringStreamToString(&rhs_ss),
+                   false);
+}
+
+// Helper function for implementing ASSERT_NEAR.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
+                                                const char* expr2,
+                                                const char* abs_error_expr,
+                                                double val1,
+                                                double val2,
+                                                double abs_error);
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+// A class that enables one to stream messages to assertion macros
+class GTEST_API_ AssertHelper {
+ public:
+  // Constructor.
+  AssertHelper(TestPartResult::Type type,
+               const char* file,
+               int line,
+               const char* message);
+  ~AssertHelper();
+
+  // Message assignment is a semantic trick to enable assertion
+  // streaming; see the GTEST_MESSAGE_ macro below.
+  void operator=(const Message& message) const;
+
+ private:
+  // We put our data in a struct so that the size of the AssertHelper class can
+  // be as small as possible.  This is important because gcc is incapable of
+  // re-using stack space even for temporary variables, so every EXPECT_EQ
+  // reserves stack space for another AssertHelper.
+  struct AssertHelperData {
+    AssertHelperData(TestPartResult::Type t,
+                     const char* srcfile,
+                     int line_num,
+                     const char* msg)
+        : type(t), file(srcfile), line(line_num), message(msg) { }
+
+    TestPartResult::Type const type;
+    const char* const file;
+    int const line;
+    std::string const message;
+
+   private:
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData);
+  };
+
+  AssertHelperData* const data_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper);
+};
+
+}  // namespace internal
+
+// The pure interface class that all value-parameterized tests inherit from.
+// A value-parameterized class must inherit from both ::testing::Test and
+// ::testing::WithParamInterface. In most cases that just means inheriting
+// from ::testing::TestWithParam, but more complicated test hierarchies
+// may need to inherit from Test and WithParamInterface at different levels.
+//
+// This interface has support for accessing the test parameter value via
+// the GetParam() method.
+//
+// Use it with one of the parameter generator defining functions, like Range(),
+// Values(), ValuesIn(), Bool(), and Combine().
+//
+// class FooTest : public ::testing::TestWithParam<int> {
+//  protected:
+//   FooTest() {
+//     // Can use GetParam() here.
+//   }
+//   ~FooTest() override {
+//     // Can use GetParam() here.
+//   }
+//   void SetUp() override {
+//     // Can use GetParam() here.
+//   }
+//   void TearDown override {
+//     // Can use GetParam() here.
+//   }
+// };
+// TEST_P(FooTest, DoesBar) {
+//   // Can use GetParam() method here.
+//   Foo foo;
+//   ASSERT_TRUE(foo.DoesBar(GetParam()));
+// }
+// INSTANTIATE_TEST_SUITE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
+
+template <typename T>
+class WithParamInterface {
+ public:
+  typedef T ParamType;
+  virtual ~WithParamInterface() {}
+
+  // The current parameter value. Is also available in the test fixture's
+  // constructor.
+  static const ParamType& GetParam() {
+    GTEST_CHECK_(parameter_ != nullptr)
+        << "GetParam() can only be called inside a value-parameterized test "
+        << "-- did you intend to write TEST_P instead of TEST_F?";
+    return *parameter_;
+  }
+
+ private:
+  // Sets parameter value. The caller is responsible for making sure the value
+  // remains alive and unchanged throughout the current test.
+  static void SetParam(const ParamType* parameter) {
+    parameter_ = parameter;
+  }
+
+  // Static value used for accessing parameter during a test lifetime.
+  static const ParamType* parameter_;
+
+  // TestClass must be a subclass of WithParamInterface<T> and Test.
+  template <class TestClass> friend class internal::ParameterizedTestFactory;
+};
+
+template <typename T>
+const T* WithParamInterface<T>::parameter_ = nullptr;
+
+// Most value-parameterized classes can ignore the existence of
+// WithParamInterface, and can just inherit from ::testing::TestWithParam.
+
+template <typename T>
+class TestWithParam : public Test, public WithParamInterface<T> {
+};
+
+// Macros for indicating success/failure in test code.
+
+// Skips test in runtime.
+// Skipping test aborts current function.
+// Skipped tests are neither successful nor failed.
+#define GTEST_SKIP() GTEST_SKIP_("")
+
+// ADD_FAILURE unconditionally adds a failure to the current test.
+// SUCCEED generates a success - it doesn't automatically make the
+// current test successful, as a test is only successful when it has
+// no failure.
+//
+// EXPECT_* verifies that a certain condition is satisfied.  If not,
+// it behaves like ADD_FAILURE.  In particular:
+//
+//   EXPECT_TRUE  verifies that a Boolean condition is true.
+//   EXPECT_FALSE verifies that a Boolean condition is false.
+//
+// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except
+// that they will also abort the current function on failure.  People
+// usually want the fail-fast behavior of FAIL and ASSERT_*, but those
+// writing data-driven tests often find themselves using ADD_FAILURE
+// and EXPECT_* more.
+
+// Generates a nonfatal failure with a generic message.
+#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed")
+
+// Generates a nonfatal failure at the given source file location with
+// a generic message.
+#define ADD_FAILURE_AT(file, line) \
+  GTEST_MESSAGE_AT_(file, line, "Failed", \
+                    ::testing::TestPartResult::kNonFatalFailure)
+
+// Generates a fatal failure with a generic message.
+#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed")
+
+// Like GTEST_FAIL(), but at the given source file location.
+#define GTEST_FAIL_AT(file, line)         \
+  GTEST_MESSAGE_AT_(file, line, "Failed", \
+                    ::testing::TestPartResult::kFatalFailure)
+
+// Define this macro to 1 to omit the definition of FAIL(), which is a
+// generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_FAIL
+# define FAIL() GTEST_FAIL()
+#endif
+
+// Generates a success with a generic message.
+#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded")
+
+// Define this macro to 1 to omit the definition of SUCCEED(), which
+// is a generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_SUCCEED
+# define SUCCEED() GTEST_SUCCEED()
+#endif
+
+// Macros for testing exceptions.
+//
+//    * {ASSERT|EXPECT}_THROW(statement, expected_exception):
+//         Tests that the statement throws the expected exception.
+//    * {ASSERT|EXPECT}_NO_THROW(statement):
+//         Tests that the statement doesn't throw any exception.
+//    * {ASSERT|EXPECT}_ANY_THROW(statement):
+//         Tests that the statement throws an exception.
+
+#define EXPECT_THROW(statement, expected_exception) \
+  GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_NO_THROW(statement) \
+  GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_ANY_THROW(statement) \
+  GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_THROW(statement, expected_exception) \
+  GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_)
+#define ASSERT_NO_THROW(statement) \
+  GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_)
+#define ASSERT_ANY_THROW(statement) \
+  GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_)
+
+// Boolean assertions. Condition can be either a Boolean expression or an
+// AssertionResult. For more information on how to use AssertionResult with
+// these macros see comments on that class.
+#define GTEST_EXPECT_TRUE(condition) \
+  GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+                      GTEST_NONFATAL_FAILURE_)
+#define GTEST_EXPECT_FALSE(condition) \
+  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+                      GTEST_NONFATAL_FAILURE_)
+#define GTEST_ASSERT_TRUE(condition) \
+  GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+                      GTEST_FATAL_FAILURE_)
+#define GTEST_ASSERT_FALSE(condition) \
+  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+                      GTEST_FATAL_FAILURE_)
+
+// Define these macros to 1 to omit the definition of the corresponding
+// EXPECT or ASSERT, which clashes with some users' own code.
+
+#if !GTEST_DONT_DEFINE_EXPECT_TRUE
+#define EXPECT_TRUE(condition) GTEST_EXPECT_TRUE(condition)
+#endif
+
+#if !GTEST_DONT_DEFINE_EXPECT_FALSE
+#define EXPECT_FALSE(condition) GTEST_EXPECT_FALSE(condition)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_TRUE
+#define ASSERT_TRUE(condition) GTEST_ASSERT_TRUE(condition)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_FALSE
+#define ASSERT_FALSE(condition) GTEST_ASSERT_FALSE(condition)
+#endif
+
+// Macros for testing equalities and inequalities.
+//
+//    * {ASSERT|EXPECT}_EQ(v1, v2): Tests that v1 == v2
+//    * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2
+//    * {ASSERT|EXPECT}_LT(v1, v2): Tests that v1 < v2
+//    * {ASSERT|EXPECT}_LE(v1, v2): Tests that v1 <= v2
+//    * {ASSERT|EXPECT}_GT(v1, v2): Tests that v1 > v2
+//    * {ASSERT|EXPECT}_GE(v1, v2): Tests that v1 >= v2
+//
+// When they are not, Google Test prints both the tested expressions and
+// their actual values.  The values must be compatible built-in types,
+// or you will get a compiler error.  By "compatible" we mean that the
+// values can be compared by the respective operator.
+//
+// Note:
+//
+//   1. It is possible to make a user-defined type work with
+//   {ASSERT|EXPECT}_??(), but that requires overloading the
+//   comparison operators and is thus discouraged by the Google C++
+//   Usage Guide.  Therefore, you are advised to use the
+//   {ASSERT|EXPECT}_TRUE() macro to assert that two objects are
+//   equal.
+//
+//   2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on
+//   pointers (in particular, C strings).  Therefore, if you use it
+//   with two C strings, you are testing how their locations in memory
+//   are related, not how their content is related.  To compare two C
+//   strings by content, use {ASSERT|EXPECT}_STR*().
+//
+//   3. {ASSERT|EXPECT}_EQ(v1, v2) is preferred to
+//   {ASSERT|EXPECT}_TRUE(v1 == v2), as the former tells you
+//   what the actual value is when it fails, and similarly for the
+//   other comparisons.
+//
+//   4. Do not depend on the order in which {ASSERT|EXPECT}_??()
+//   evaluate their arguments, which is undefined.
+//
+//   5. These macros evaluate their arguments exactly once.
+//
+// Examples:
+//
+//   EXPECT_NE(Foo(), 5);
+//   EXPECT_EQ(a_pointer, NULL);
+//   ASSERT_LT(i, array_size);
+//   ASSERT_GT(records.size(), 0) << "There is no record left.";
+
+#define EXPECT_EQ(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2)
+#define EXPECT_NE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
+#define EXPECT_LE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define EXPECT_LT(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define EXPECT_GE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define EXPECT_GT(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+#define GTEST_ASSERT_EQ(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2)
+#define GTEST_ASSERT_NE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
+#define GTEST_ASSERT_LE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define GTEST_ASSERT_LT(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define GTEST_ASSERT_GE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define GTEST_ASSERT_GT(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of
+// ASSERT_XY(), which clashes with some users' own code.
+
+#if !GTEST_DONT_DEFINE_ASSERT_EQ
+# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_NE
+# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LE
+# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LT
+# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GE
+# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GT
+# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
+#endif
+
+// C-string Comparisons.  All tests treat NULL and any non-NULL string
+// as different.  Two NULLs are equal.
+//
+//    * {ASSERT|EXPECT}_STREQ(s1, s2):     Tests that s1 == s2
+//    * {ASSERT|EXPECT}_STRNE(s1, s2):     Tests that s1 != s2
+//    * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case
+//    * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case
+//
+// For wide or narrow string objects, you can use the
+// {ASSERT|EXPECT}_??() macros.
+//
+// Don't depend on the order in which the arguments are evaluated,
+// which is undefined.
+//
+// These macros evaluate their arguments exactly once.
+
+#define EXPECT_STREQ(s1, s2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, s1, s2)
+#define EXPECT_STRNE(s1, s2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define EXPECT_STRCASEEQ(s1, s2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, s1, s2)
+#define EXPECT_STRCASENE(s1, s2)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+#define ASSERT_STREQ(s1, s2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, s1, s2)
+#define ASSERT_STRNE(s1, s2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define ASSERT_STRCASEEQ(s1, s2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, s1, s2)
+#define ASSERT_STRCASENE(s1, s2)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+// Macros for comparing floating-point numbers.
+//
+//    * {ASSERT|EXPECT}_FLOAT_EQ(val1, val2):
+//         Tests that two float values are almost equal.
+//    * {ASSERT|EXPECT}_DOUBLE_EQ(val1, val2):
+//         Tests that two double values are almost equal.
+//    * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error):
+//         Tests that v1 and v2 are within the given distance to each other.
+//
+// Google Test uses ULP-based comparison to automatically pick a default
+// error bound that is appropriate for the operands.  See the
+// FloatingPoint template class in gtest-internal.h if you are
+// interested in the implementation details.
+
+#define EXPECT_FLOAT_EQ(val1, val2)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+                      val1, val2)
+
+#define EXPECT_DOUBLE_EQ(val1, val2)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+                      val1, val2)
+
+#define ASSERT_FLOAT_EQ(val1, val2)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+                      val1, val2)
+
+#define ASSERT_DOUBLE_EQ(val1, val2)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+                      val1, val2)
+
+#define EXPECT_NEAR(val1, val2, abs_error)\
+  EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+                      val1, val2, abs_error)
+
+#define ASSERT_NEAR(val1, val2, abs_error)\
+  ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+                      val1, val2, abs_error)
+
+// These predicate format functions work on floating-point values, and
+// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g.
+//
+//   EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0);
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2,
+                                   float val1, float val2);
+GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
+                                    double val1, double val2);
+
+
+#if GTEST_OS_WINDOWS
+
+// Macros that test for HRESULT failure and success, these are only useful
+// on Windows, and rely on Windows SDK macros and APIs to compile.
+//
+//    * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr)
+//
+// When expr unexpectedly fails or succeeds, Google Test prints the
+// expected result and the actual result with both a human-readable
+// string representation of the error, if available, as well as the
+// hex result code.
+# define EXPECT_HRESULT_SUCCEEDED(expr) \
+    EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+# define ASSERT_HRESULT_SUCCEEDED(expr) \
+    ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+# define EXPECT_HRESULT_FAILED(expr) \
+    EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+# define ASSERT_HRESULT_FAILED(expr) \
+    ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+#endif  // GTEST_OS_WINDOWS
+
+// Macros that execute statement and check that it doesn't generate new fatal
+// failures in the current thread.
+//
+//   * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement);
+//
+// Examples:
+//
+//   EXPECT_NO_FATAL_FAILURE(Process());
+//   ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed";
+//
+#define ASSERT_NO_FATAL_FAILURE(statement) \
+    GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_)
+#define EXPECT_NO_FATAL_FAILURE(statement) \
+    GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_)
+
+// Causes a trace (including the given source file path and line number,
+// and the given message) to be included in every test failure message generated
+// by code in the scope of the lifetime of an instance of this class. The effect
+// is undone with the destruction of the instance.
+//
+// The message argument can be anything streamable to std::ostream.
+//
+// Example:
+//   testing::ScopedTrace trace("file.cc", 123, "message");
+//
+class GTEST_API_ ScopedTrace {
+ public:
+  // The c'tor pushes the given source file location and message onto
+  // a trace stack maintained by Google Test.
+
+  // Template version. Uses Message() to convert the values into strings.
+  // Slow, but flexible.
+  template <typename T>
+  ScopedTrace(const char* file, int line, const T& message) {
+    PushTrace(file, line, (Message() << message).GetString());
+  }
+
+  // Optimize for some known types.
+  ScopedTrace(const char* file, int line, const char* message) {
+    PushTrace(file, line, message ? message : "(null)");
+  }
+
+  ScopedTrace(const char* file, int line, const std::string& message) {
+    PushTrace(file, line, message);
+  }
+
+  // The d'tor pops the info pushed by the c'tor.
+  //
+  // Note that the d'tor is not virtual in order to be efficient.
+  // Don't inherit from ScopedTrace!
+  ~ScopedTrace();
+
+ private:
+  void PushTrace(const char* file, int line, std::string message);
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace);
+} GTEST_ATTRIBUTE_UNUSED_;  // A ScopedTrace object does its job in its
+                            // c'tor and d'tor.  Therefore it doesn't
+                            // need to be used otherwise.
+
+// Causes a trace (including the source file path, the current line
+// number, and the given message) to be included in every test failure
+// message generated by code in the current scope.  The effect is
+// undone when the control leaves the current scope.
+//
+// The message argument can be anything streamable to std::ostream.
+//
+// In the implementation, we include the current line number as part
+// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s
+// to appear in the same block - as long as they are on different
+// lines.
+//
+// Assuming that each thread maintains its own stack of traces.
+// Therefore, a SCOPED_TRACE() would (correctly) only affect the
+// assertions in its own thread.
+#define SCOPED_TRACE(message) \
+  ::testing::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
+    __FILE__, __LINE__, (message))
+
+// Compile-time assertion for type equality.
+// StaticAssertTypeEq<type1, type2>() compiles if and only if type1 and type2
+// are the same type.  The value it returns is not interesting.
+//
+// Instead of making StaticAssertTypeEq a class template, we make it a
+// function template that invokes a helper class template.  This
+// prevents a user from misusing StaticAssertTypeEq<T1, T2> by
+// defining objects of that type.
+//
+// CAVEAT:
+//
+// When used inside a method of a class template,
+// StaticAssertTypeEq<T1, T2>() is effective ONLY IF the method is
+// instantiated.  For example, given:
+//
+//   template <typename T> class Foo {
+//    public:
+//     void Bar() { testing::StaticAssertTypeEq<int, T>(); }
+//   };
+//
+// the code:
+//
+//   void Test1() { Foo<bool> foo; }
+//
+// will NOT generate a compiler error, as Foo<bool>::Bar() is never
+// actually instantiated.  Instead, you need:
+//
+//   void Test2() { Foo<bool> foo; foo.Bar(); }
+//
+// to cause a compiler error.
+template <typename T1, typename T2>
+constexpr bool StaticAssertTypeEq() noexcept {
+  static_assert(std::is_same<T1, T2>::value, "T1 and T2 are not the same type");
+  return true;
+}
+
+// Defines a test.
+//
+// The first parameter is the name of the test suite, and the second
+// parameter is the name of the test within the test suite.
+//
+// The convention is to end the test suite name with "Test".  For
+// example, a test suite for the Foo class can be named FooTest.
+//
+// Test code should appear between braces after an invocation of
+// this macro.  Example:
+//
+//   TEST(FooTest, InitializesCorrectly) {
+//     Foo foo;
+//     EXPECT_TRUE(foo.StatusIsOK());
+//   }
+
+// Note that we call GetTestTypeId() instead of GetTypeId<
+// ::testing::Test>() here to get the type ID of testing::Test.  This
+// is to work around a suspected linker bug when using Google Test as
+// a framework on Mac OS X.  The bug causes GetTypeId<
+// ::testing::Test>() to return different values depending on whether
+// the call is from the Google Test framework itself or from user test
+// code.  GetTestTypeId() is guaranteed to always return the same
+// value, as it always calls GetTypeId<>() from the Google Test
+// framework.
+#define GTEST_TEST(test_suite_name, test_name)             \
+  GTEST_TEST_(test_suite_name, test_name, ::testing::Test, \
+              ::testing::internal::GetTestTypeId())
+
+// Define this macro to 1 to omit the definition of TEST(), which
+// is a generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_TEST
+#define TEST(test_suite_name, test_name) GTEST_TEST(test_suite_name, test_name)
+#endif
+
+// Defines a test that uses a test fixture.
+//
+// The first parameter is the name of the test fixture class, which
+// also doubles as the test suite name.  The second parameter is the
+// name of the test within the test suite.
+//
+// A test fixture class must be declared earlier.  The user should put
+// the test code between braces after using this macro.  Example:
+//
+//   class FooTest : public testing::Test {
+//    protected:
+//     void SetUp() override { b_.AddElement(3); }
+//
+//     Foo a_;
+//     Foo b_;
+//   };
+//
+//   TEST_F(FooTest, InitializesCorrectly) {
+//     EXPECT_TRUE(a_.StatusIsOK());
+//   }
+//
+//   TEST_F(FooTest, ReturnsElementCountCorrectly) {
+//     EXPECT_EQ(a_.size(), 0);
+//     EXPECT_EQ(b_.size(), 1);
+//   }
+//
+// GOOGLETEST_CM0011 DO NOT DELETE
+#if !GTEST_DONT_DEFINE_TEST
+#define TEST_F(test_fixture, test_name)\
+  GTEST_TEST_(test_fixture, test_name, test_fixture, \
+              ::testing::internal::GetTypeId<test_fixture>())
+#endif  // !GTEST_DONT_DEFINE_TEST
+
+// Returns a path to temporary directory.
+// Tries to determine an appropriate directory for the platform.
+GTEST_API_ std::string TempDir();
+
+#ifdef _MSC_VER
+#  pragma warning(pop)
+#endif
+
+// Dynamically registers a test with the framework.
+//
+// This is an advanced API only to be used when the `TEST` macros are
+// insufficient. The macros should be preferred when possible, as they avoid
+// most of the complexity of calling this function.
+//
+// The `factory` argument is a factory callable (move-constructible) object or
+// function pointer that creates a new instance of the Test object. It
+// handles ownership to the caller. The signature of the callable is
+// `Fixture*()`, where `Fixture` is the test fixture class for the test. All
+// tests registered with the same `test_suite_name` must return the same
+// fixture type. This is checked at runtime.
+//
+// The framework will infer the fixture class from the factory and will call
+// the `SetUpTestSuite` and `TearDownTestSuite` for it.
+//
+// Must be called before `RUN_ALL_TESTS()` is invoked, otherwise behavior is
+// undefined.
+//
+// Use case example:
+//
+// class MyFixture : public ::testing::Test {
+//  public:
+//   // All of these optional, just like in regular macro usage.
+//   static void SetUpTestSuite() { ... }
+//   static void TearDownTestSuite() { ... }
+//   void SetUp() override { ... }
+//   void TearDown() override { ... }
+// };
+//
+// class MyTest : public MyFixture {
+//  public:
+//   explicit MyTest(int data) : data_(data) {}
+//   void TestBody() override { ... }
+//
+//  private:
+//   int data_;
+// };
+//
+// void RegisterMyTests(const std::vector<int>& values) {
+//   for (int v : values) {
+//     ::testing::RegisterTest(
+//         "MyFixture", ("Test" + std::to_string(v)).c_str(), nullptr,
+//         std::to_string(v).c_str(),
+//         __FILE__, __LINE__,
+//         // Important to use the fixture type as the return type here.
+//         [=]() -> MyFixture* { return new MyTest(v); });
+//   }
+// }
+// ...
+// int main(int argc, char** argv) {
+//   std::vector<int> values_to_test = LoadValuesFromConfig();
+//   RegisterMyTests(values_to_test);
+//   ...
+//   return RUN_ALL_TESTS();
+// }
+//
+template <int&... ExplicitParameterBarrier, typename Factory>
+TestInfo* RegisterTest(const char* test_suite_name, const char* test_name,
+                       const char* type_param, const char* value_param,
+                       const char* file, int line, Factory factory) {
+  using TestT = typename std::remove_pointer<decltype(factory())>::type;
+
+  class FactoryImpl : public internal::TestFactoryBase {
+   public:
+    explicit FactoryImpl(Factory f) : factory_(std::move(f)) {}
+    Test* CreateTest() override { return factory_(); }
+
+   private:
+    Factory factory_;
+  };
+
+  return internal::MakeAndRegisterTestInfo(
+      test_suite_name, test_name, type_param, value_param,
+      internal::CodeLocation(file, line), internal::GetTypeId<TestT>(),
+      internal::SuiteApiResolver<TestT>::GetSetUpCaseOrSuite(file, line),
+      internal::SuiteApiResolver<TestT>::GetTearDownCaseOrSuite(file, line),
+      new FactoryImpl{std::move(factory)});
+}
+
+}  // namespace testing
+
+// Use this function in main() to run all tests.  It returns 0 if all
+// tests are successful, or 1 otherwise.
+//
+// RUN_ALL_TESTS() should be invoked after the command line has been
+// parsed by InitGoogleTest().
+//
+// This function was formerly a macro; thus, it is in the global
+// namespace and has an all-caps name.
+int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_;
+
+inline int RUN_ALL_TESTS() {
+  return ::testing::UnitTest::GetInstance()->Run();
+}
+
+GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
+
+#endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_H_
diff --git a/src/tools/distrib/linux/README.redistrib.txt b/src/tools/distrib/linux/README.redistrib.txt
index 29c5120..0f44208 100644
--- a/src/tools/distrib/linux/README.redistrib.txt
+++ b/src/tools/distrib/linux/README.redistrib.txt
@@ -41,30 +41,23 @@
   CefSettings.pack_loading_disabled. The resources directory path can be
   customized using CefSettings.resources_dir_path.
 
-  * cef.pak
-  * cef_100_percent.pak
-  * cef_200_percent.pak
+  * chrome_100_percent.pak
+  * chrome_200_percent.pak
+  * resources.pak
     These files contain non-localized resources used by CEF, Chromium and Blink.
     Without these files arbitrary Web components may display incorrectly.
 
-  * cef_extensions.pak
-    This file contains non-localized resources required for extension loading.
-    Pass the `--disable-extensions` command-line flag to disable use of this
-    file. Without this file components that depend on the extension system,
-    such as the PDF viewer, will not function.
-
-  * devtools_resources.pak
-    This file contains non-localized resources required for Chrome Developer
-    Tools. Without this file Chrome Developer Tools will not function.
-
-* Angle support.
+* ANGLE support.
   * libEGL.so
   * libGLESv2.so
-  Without these files HTML5 accelerated content like 2D canvas, 3D CSS and WebGL
-  will not function.
+  Support for rendering of HTML5 content like 2D canvas, 3D CSS and WebGL.
+  Without these files the aforementioned capabilities may fail.
 
-* SwiftShader support.
-  * swiftshader/libEGL.so
-  * swiftshader/libGLESv2.so
-  Without these files WebGL will not function in software-only mode when the GPU
-  is not available or disabled.
+* SwANGLE support.
+  * libvk_swiftshader.so
+  * libvulkan.so.1
+  * vk_swiftshader_icd.json
+  Support for software rendering of HTML5 content like 2D canvas, 3D CSS and
+  WebGL using SwiftShader's Vulkan library as ANGLE's Vulkan backend. Without
+  these files the aforementioned capabilities may fail when GPU acceleration is
+  disabled or unavailable.
diff --git a/src/tools/distrib/mac/README.redistrib.txt b/src/tools/distrib/mac/README.redistrib.txt
index 5a9fdef..a66f27c 100644
--- a/src/tools/distrib/mac/README.redistrib.txt
+++ b/src/tools/distrib/mac/README.redistrib.txt
@@ -15,18 +15,17 @@
       Chromium Embedded Framework.framework/
         Chromium Embedded Framework <= main application library
         Libraries/
-          libEGL.dylib <= angle support libraries
+          libEGL.dylib <= ANGLE support libraries
           libGLESv2.dylib <=^
-          libswiftshader_libEGL.dylib <= swiftshader support libraries
-          libswiftshader_libGLESv2.dylib <=^
+          libvk_swiftshader.dylib <= SwANGLE support libraries
+          vk_swiftshader_icd.json <=^
         Resources/
-          cef.pak <= non-localized resources and strings
-          cef_100_percent.pak <====^
-          cef_200_percent.pak <====^
-          cef_extensions.pak <=====^
-          devtools_resources.pak <=^
+          chrome_100_percent.pak <= non-localized resources and strings
+          chrome_200_percent.pak <=^
+          resources.pak          <=^
+          gpu_shader_cache.bin <= ANGLE-Metal shader cache
           icudtl.dat <= unicode support
-          snapshot_blob.bin, v8_context_snapshot.bin <= V8 initial snapshot
+          snapshot_blob.bin, v8_context_snapshot.[x86_64|arm64].bin <= V8 initial snapshot
           en.lproj/, ... <= locale-specific resources and strings
           Info.plist
       cefclient Helper.app/
@@ -87,30 +86,23 @@
   Pack file loading can be disabled completely using
   CefSettings.pack_loading_disabled.
 
-  * Chromium Embedded Framework.framework/Resources/cef.pak
-  * Chromium Embedded Framework.framework/Resources/cef_100_percent.pak
-  * Chromium Embedded Framework.framework/Resources/cef_200_percent.pak
+  * Chromium Embedded Framework.framework/Resources/chrome_100_percent.pak
+  * Chromium Embedded Framework.framework/Resources/chrome_200_percent.pak
+  * Chromium Embedded Framework.framework/Resources/resources.pak
     These files contain non-localized resources used by CEF, Chromium and Blink.
     Without these files arbitrary Web components may display incorrectly.
 
-  * Chromium Embedded Framework.framework/Resources/cef_extensions.pak
-    This file contains non-localized resources required for extension loading.
-    Pass the `--disable-extensions` command-line flag to disable use of this
-    file. Without this file components that depend on the extension system,
-    such as the PDF viewer, will not function.
-
-  * Chromium Embedded Framework.framework/Resources/devtools_resources.pak
-    This file contains non-localized resources required for Chrome Developer
-    Tools. Without this file Chrome Developer Tools will not function.
-
-* Angle support.
+* ANGLE support.
   * Chromium Embedded Framework.framework/Libraries/libEGL.dylib
   * Chromium Embedded Framework.framework/Libraries/libGLESv2.dylib
-  Without these files HTML5 accelerated content like 2D canvas, 3D CSS and WebGL
-  will not function.
+  * Chromium Embedded Framework.framework/Resources/gpu_shader_cache.bin
+  Support for rendering of HTML5 content like 2D canvas, 3D CSS and WebGL.
+  Without these files the aforementioned capabilities may fail.
 
-* SwiftShader support.
-  * Chromium Embedded Framework.framework/Libraries/libswiftshader_libEGL.dylib
-  * Chromium Embedded Framework.framework/Libraries/libswiftshader_libGLESv2.dylib
-  Without these files WebGL will not function in software-only mode when the GPU
-  is not available or disabled.
+* SwANGLE support.
+  * Chromium Embedded Framework.framework/Libraries/libvk_swiftshader.dylib
+  * Chromium Embedded Framework.framework/Libraries/vk_swiftshader_icd.json
+  Support for software rendering of HTML5 content like 2D canvas, 3D CSS and
+  WebGL using SwiftShader's Vulkan library as ANGLE's Vulkan backend. Without
+  these files the aforementioned capabilities may fail when GPU acceleration is
+  disabled or unavailable.
diff --git a/src/tools/distrib/mac/README.sandbox.txt b/src/tools/distrib/mac/README.sandbox.txt
new file mode 100644
index 0000000..8d2258d
--- /dev/null
+++ b/src/tools/distrib/mac/README.sandbox.txt
@@ -0,0 +1,14 @@
+CONTENTS
+--------
+
+Debug       Contains the Debug build of cef_sandbox.a.
+
+Release     Contains the Release build of cef_sandbox.a.
+
+
+USAGE
+-----
+
+Please visit the CEF Website for usage information.
+
+https://bitbucket.org/chromiumembedded/cef/
diff --git a/src/tools/distrib/transfer.cfg b/src/tools/distrib/transfer.cfg
index 6b8a5cd..d3a65ea 100644
--- a/src/tools/distrib/transfer.cfg
+++ b/src/tools/distrib/transfer.cfg
@@ -14,4 +14,4 @@
     'source' : '../net/base/net_error_list.h',
     'target' : 'include/base/internal/cef_net_error_list.h',
   },
-]
\ No newline at end of file
+]
diff --git a/src/tools/distrib/transfer_standard.cfg b/src/tools/distrib/transfer_standard.cfg
new file mode 100644
index 0000000..2ea2f07
--- /dev/null
+++ b/src/tools/distrib/transfer_standard.cfg
@@ -0,0 +1,29 @@
+# Additional handling of transfer files.
+# target: Target location relative to the target release directory. This
+#     value is required.
+# source: Source location relative to the CEF root directory. This value
+#     is optional. If specified the source file will be copied to the target
+#     location and a TRANSFER-README.txt file will be created.
+# post-process: Post-processing operation to perform. This value is
+#     optional and may be any one of the following:
+#   'normalize_headers': Replace fully-qualified project header paths with
+#     the optionally specified 'new_header_path' value.
+
+[
+  {
+    'source' : '../net/data/ssl/certificates/expired_cert.pem',
+    'target' : 'tests/ceftests/resources/net/data/ssl/certificates/expired_cert.pem',
+  },
+  {
+    'source' : '../net/data/ssl/certificates/localhost_cert.pem',
+    'target' : 'tests/ceftests/resources/net/data/ssl/certificates/localhost_cert.pem',
+  },
+  {
+    'source' : '../net/data/ssl/certificates/ok_cert.pem',
+    'target' : 'tests/ceftests/resources/net/data/ssl/certificates/ok_cert.pem',
+  },
+  {
+    'source' : '../net/data/ssl/certificates/root_ca_cert.pem',
+    'target' : 'tests/ceftests/resources/net/data/ssl/certificates/root_ca_cert.pem',
+  },
+]
diff --git a/src/tools/distrib/win/README.redistrib.txt b/src/tools/distrib/win/README.redistrib.txt
index b96ab35..29675cb 100644
--- a/src/tools/distrib/win/README.redistrib.txt
+++ b/src/tools/distrib/win/README.redistrib.txt
@@ -42,31 +42,31 @@
   CefSettings.pack_loading_disabled. The resources directory path can be
   customized using CefSettings.resources_dir_path.
 
-  * cef.pak
-  * cef_100_percent.pak
-  * cef_200_percent.pak
+  * chrome_100_percent.pak
+  * chrome_200_percent.pak
+  * resources.pak
     These files contain non-localized resources used by CEF, Chromium and Blink.
     Without these files arbitrary Web components may display incorrectly.
 
-  * cef_extensions.pak
-    This file contains non-localized resources required for extension loading.
-    Pass the `--disable-extensions` command-line flag to disable use of this
-    file. Without this file components that depend on the extension system,
-    such as the PDF viewer, will not function.
+* Direct3D support.
+  * d3dcompiler_47.dll
+  Support for GPU accelerated rendering of HTML5 content like 2D canvas, 3D CSS
+  and WebGL. Without this file the aforementioned capabilities may fail when GPU
+  acceleration is enabled (default in most cases). Use of this bundled version
+  is recommended instead of relying on the possibly old and untested system
+  installed version.
 
-  * devtools_resources.pak
-    This file contains non-localized resources required for Chrome Developer
-    Tools. Without this file Chrome Developer Tools will not function.
-
-* Angle and Direct3D support.
-  * d3dcompiler_47.dll (required for Windows Vista and newer)
+* ANGLE support.
   * libEGL.dll
   * libGLESv2.dll
-  Without these files HTML5 accelerated content like 2D canvas, 3D CSS and WebGL
-  will not function.
+  Support for rendering of HTML5 content like 2D canvas, 3D CSS and WebGL.
+  Without these files the aforementioned capabilities may fail.
 
-* SwiftShader support.
-  * swiftshader/libEGL.dll
-  * swiftshader/libGLESv2.dll
-  Without these files WebGL will not function in software-only mode when the GPU
-  is not available or disabled.
+* SwANGLE support.
+  * vk_swiftshader.dll
+  * vk_swiftshader_icd.json
+  * vulkan-1.dll
+  Support for software rendering of HTML5 content like 2D canvas, 3D CSS and
+  WebGL using SwiftShader's Vulkan library as ANGLE's Vulkan backend. Without
+  these files the aforementioned capabilities may fail when GPU acceleration is
+  disabled or unavailable.
diff --git a/src/tools/distrib/win/x64/d3dcompiler_47.dll b/src/tools/distrib/win/x64/d3dcompiler_47.dll
deleted file mode 100644
index b120261..0000000
--- a/src/tools/distrib/win/x64/d3dcompiler_47.dll
+++ /dev/null
Binary files differ
diff --git a/src/tools/distrib/win/x86/d3dcompiler_47.dll b/src/tools/distrib/win/x86/d3dcompiler_47.dll
deleted file mode 100644
index 967ee40..0000000
--- a/src/tools/distrib/win/x86/d3dcompiler_47.dll
+++ /dev/null
Binary files differ
diff --git a/src/tools/file_util.py b/src/tools/file_util.py
index 54d79ee..810aed9 100644
--- a/src/tools/file_util.py
+++ b/src/tools/file_util.py
@@ -6,6 +6,7 @@
 from glob import iglob
 from io import open
 import os
+import fnmatch
 import shutil
 import sys
 import time
@@ -155,9 +156,28 @@
 
 
 def get_files(search_glob):
-  """ Returns all files matching the search glob. """
+  """ Returns all files matching |search_glob|. """
+  recursive_glob = '**' + os.path.sep
+  if recursive_glob in search_glob:
+    if sys.version_info >= (3, 5):
+      result = iglob(search_glob, recursive=True)
+    else:
+      # Polyfill for recursive glob pattern matching added in Python 3.5.
+      result = get_files_recursive(*search_glob.split(recursive_glob))
+  else:
+    result = iglob(search_glob)
+
   # Sort the result for consistency across platforms.
-  return sorted(iglob(search_glob))
+  return sorted(result)
+
+
+def get_files_recursive(directory, pattern):
+  """ Returns all files in |directory| matching |pattern| recursively. """
+  for root, dirs, files in os.walk(directory):
+    for basename in files:
+      if fnmatch.fnmatch(basename, pattern):
+        filename = os.path.join(root, basename)
+        yield filename
 
 
 def read_version_file(file, args):
diff --git a/src/tools/fix_style.sh b/src/tools/fix_style.sh
index c466ab0..042c01f 100755
--- a/src/tools/fix_style.sh
+++ b/src/tools/fix_style.sh
@@ -1,2 +1,2 @@
 #!/bin/sh
-python tools/fix_style.py $@
+python3 tools/fix_style.py $@
diff --git a/src/tools/gclient_hook.py b/src/tools/gclient_hook.py
index f0be2d4..c525984 100644
--- a/src/tools/gclient_hook.py
+++ b/src/tools/gclient_hook.py
@@ -21,7 +21,7 @@
 if sys.platform == 'win32':
   platform = 'windows'
 elif sys.platform == 'darwin':
-  platform = 'macosx'
+  platform = 'mac'
 elif sys.platform.startswith('linux'):
   platform = 'linux'
 else:
@@ -56,10 +56,10 @@
   if not 'DEPOT_TOOLS_WIN_TOOLCHAIN' in os.environ:
     os.environ['DEPOT_TOOLS_WIN_TOOLCHAIN'] = '0'
 
-  # By default GN+Ninja on Windows expects Visual Studio to be installed on
-  # the local machine. To build when Visual Studio is extracted to a directory
-  # but not installed (e.g. via a custom toolchain) set the following
-  # environment variables:
+  # By default GN+Ninja on Windows expects Visual Studio and Windows SDK to be
+  # installed on the local machine. To build when Visual Studio and/or SDK is
+  # extracted to a directory but not installed (e.g. via a custom toolchain) set
+  # the following environment variables:
   #
   # o Enable use of a custom toolchain on Windows.
   #
@@ -78,10 +78,11 @@
   #   should instead be discoverable via the PATH env variable.
   #   (b) build/toolchain/win/setup_toolchain.py _LoadToolchainEnv when
   #   writing environment.* files that specify INCLUDE/LIB/PATH values. If
-  #   "%GYP_MSVS_OVERRIDE_PATH%\VC\vcvarsall.bat" exists then environment
-  #   variables will be derived from there and the specified INCLUDE/LIB/PATH
-  #   values will be ignored by Chromium. If this file does not exist then the
-  #   INCLUDE/LIB/PATH values are also required by Chromium.
+  #   vcvarsall.bat [1] exists then environment variables will be derived from
+  #   there and the specified INCLUDE/LIB values will be ignored by Chromium
+  #   (PATH is retained because it might contain required VS runtime libraries).
+  #   If this file does not exist then the INCLUDE/LIB/PATH values are also
+  #   required by Chromium.
   #   TODO(cef): Rename to VS_ROOT and VS_VERSION after Chromium cleans up GYP
   #   dependencies.
   #
@@ -92,11 +93,10 @@
   #
   #   set VS_CRT_ROOT=<VS CRT root directory>
   #   set SDK_ROOT=<Platform SDK root directory>
+  #   set SDK_VERSION=<Platform SDK version>
   #
-  # o Used by various scripts as described above.
-  #   TODO(cef): Make these values optional when
-  #   "%GYP_MSVS_OVERRIDE_PATH%\VC\vcvarsall.bat" exists (use values from that
-  #   script instead).
+  # o Used by various scripts as described above. These values are optional when
+  #   vcvarsall.bat [1] exists.
   #
   #   set INCLUDE=<VS include paths>
   #   set LIB=<VS library paths>
@@ -106,6 +106,13 @@
   # packaging script along with required directory contents and INCLUDE/LIB/PATH
   # values.
   #
+  # [1] The vcvarsall.bat script must exist in "%GYP_MSVS_OVERRIDE_PATH%\VC\" or
+  #     "%GYP_MSVS_OVERRIDE_PATH%\VC\Auxiliary\Build\". If the Windows SDK is not
+  #     installed (e.g. not discoverable via the Windows registry) then
+  #     "%GYP_MSVS_OVERRIDE_PATH%\Common7\Tools\vsdevcmd\core\winsdk.bat" must be
+  #     patched to support discovery via SDK_ROOT as described in
+  #     https://github.com/chromiumembedded/cef/issues/2773#issuecomment-1465019898.
+  #
   if bool(int(os.environ.get('WIN_CUSTOM_TOOLCHAIN', '0'))):
     required_vars = [
         'CEF_VCVARS',
@@ -113,9 +120,7 @@
         'GYP_MSVS_VERSION',
         'VS_CRT_ROOT',
         'SDK_ROOT',
-        'INCLUDE',
-        'LIB',
-        'PATH',
+        'SDK_VERSION',
     ]
     for var in required_vars:
       if not var in os.environ.keys():
@@ -126,6 +131,7 @@
     gn_args['visual_studio_version'] = os.environ['GYP_MSVS_VERSION']
     gn_args['visual_studio_runtime_dirs'] = os.environ['VS_CRT_ROOT']
     gn_args['windows_sdk_path'] = os.environ['SDK_ROOT']
+    gn_args['windows_sdk_version'] = os.environ['SDK_VERSION']
 
 configs = GetAllPlatformConfigs(gn_args)
 for dir, config in configs.items():
@@ -143,14 +149,3 @@
   RunAction(src_dir, cmd)
   if platform == 'windows':
     issue_1999.apply(out_path)
-
-gn_dir = list(configs.keys())[0]
-out_gn_path = os.path.join(src_dir, 'out', gn_dir)
-gn_path = os.path.join(out_gn_path, 'args.gn')
-print("\nGenerating CEF buildinfo header file...")
-cmd = [
-    sys.executable, 'tools/make_config_header.py', '--header',
-    'include/cef_config.h', '--cef_gn_config', gn_path
-]
-
-RunAction(cef_dir, cmd)
diff --git a/src/tools/git_util.py b/src/tools/git_util.py
index 3a3abb4..886d827 100644
--- a/src/tools/git_util.py
+++ b/src/tools/git_util.py
@@ -16,7 +16,7 @@
 
 def is_checkout(path):
   """ Returns true if the path represents a git checkout. """
-  return os.path.isdir(os.path.join(path, '.git'))
+  return os.path.exists(os.path.join(path, '.git'))
 
 
 def is_ancestor(path='.', commit1='HEAD', commit2='master'):
diff --git a/src/tools/gn_args.py b/src/tools/gn_args.py
index 1d118f9..c1acac1 100644
--- a/src/tools/gn_args.py
+++ b/src/tools/gn_args.py
@@ -63,6 +63,7 @@
 from __future__ import absolute_import
 from __future__ import print_function
 import os
+import platform as python_platform
 import shlex
 import sys
 
@@ -74,8 +75,12 @@
 # Determine the platform.
 if sys.platform == 'win32':
   platform = 'windows'
+  # Windows machines report 'ARM64' or 'AMD64'.
+  machine = 'arm64' if python_platform.machine() == 'ARM64' else 'amd64'
 elif sys.platform == 'darwin':
-  platform = 'macosx'
+  platform = 'mac'
+  # Mac machines report 'arm64' or 'x86_64'.
+  machine = 'arm64' if python_platform.machine() == 'arm64' else 'amd64'
 elif sys.platform.startswith('linux'):
   platform = 'linux'
 else:
@@ -178,6 +183,7 @@
     defaults['visual_studio_version'] = ''
     defaults['visual_studio_runtime_dirs'] = ''
     defaults['windows_sdk_path'] = ''
+    defaults['windows_sdk_version'] = ''
 
   return defaults
 
@@ -207,10 +213,34 @@
       # distribution.
       'is_component_build': False,
 
-      # Don't enforce component builds in debug mode
-      'forbid_non_component_debug_builds': False,
+      # Disable support for background apps, which don't make sense with CEF.
+      # Default is enabled on desktop platforms. This feature was also causing
+      # strange shutdown crashes when using the Chrome runtime with a Debug
+      # component build on Windows.
+      'enable_background_mode': False,
+
+      # Disable support for resource allowlist generation. When enabled this
+      # introduces a Windows official build dependency on the
+      # "//chrome:chrome_dll" target, which will fail to build with CEF.
+      'enable_resource_allowlist_generation': False,
+
+      # Disable V8 sandboxed pointers to avoid crashing when using
+      # CefV8Value::CreateArrayBuffer with memory allocated outside of the V8
+      # sandbox. See https://github.com/chromiumembedded/cef/issues/3332.
+      'v8_enable_sandbox': False,
   }
 
+  if platform == 'windows' or platform == 'mac':
+    # A browser specific value of at least 32 characters that will be used in
+    # the computation of the CDM storage ID.
+    result['alternate_cdm_storage_id_key'] = '968b476909da4373b08903c28e859454'
+
+  if platform != 'windows':
+    # Only allow non-component Debug builds on non-Windows platforms. These
+    # builds will fail on Windows due to linker issues (running out of memory,
+    # etc). See https://github.com/chromiumembedded/cef/issues/2679.
+    result['forbid_non_component_debug_builds'] = False
+
   if platform == 'linux':
     # Use a sysroot environment. Default is true. False is recommended for local
     # builds.
@@ -219,12 +249,22 @@
     # x86 or x64 build: $ gclient runhooks
     result['use_sysroot'] = False
 
-    # Don't add the `-Wl,--fatal-warnings` linker flag when building on Ubuntu
-    # 14 (Trusty) host systems. It results in errors like the following:
-    # ld.lld: error: found local symbol '__bss_start' in global part of symbol
-    # table in file /usr/lib/x86_64-linux-gnu/libGL.so
-    # TODO(cef): Remove this flag once we require a newer host system.
-    result['fatal_linker_warnings'] = False
+    # Disable QT by default because we don't want to introduce the build
+    # dependencies at this time. For background see
+    # https://groups.google.com/a/chromium.org/g/chromium-packagers/c/-2VGexQAK6w/m/5K5ppK9WBAAJ
+    result['use_qt'] = False
+
+  if platform == 'mac':
+    # Disable the allocator shim. Default is True. See issue #3061.
+    result['use_allocator_shim'] = False
+
+  if platform == 'mac' or platform == 'linux':
+    # Use the system allocator instead of PartitionAlloc. Default is True with
+    # the allocator shim enabled. See issues #3061 and #3095.
+    result['use_partition_alloc_as_malloc'] = False
+
+    # These require use_partition_alloc_as_malloc=true, so disable them.
+    result['enable_backup_ref_ptr_support'] = False
 
   return result
 
@@ -253,6 +293,14 @@
       'clang_use_chrome_plugins': False,
   }
 
+  if platform == 'windows' or platform == 'mac':
+    # Enable Widevine CDM host verification and storage ID.
+    result['enable_cdm_host_verification'] = True
+    result['enable_cdm_storage_id'] = True
+
+    # Enable use of the RLZ library as required by CDM storage ID.
+    result['enable_rlz'] = True
+
   if platform == 'linux':
     # Don't generate Chromium installer packages. This avoids GN dependency
     # errors with CEF (see issue #2301).
@@ -260,14 +308,6 @@
     # can't be enforced by assert().
     result['enable_linux_installer'] = False
 
-    # Build without GTK dependencies (see issue #2014).
-    result['use_gtk'] = False
-
-  if platform == 'macosx':
-    # Always generate dSYM files. The make_distrib script will fail if
-    # enable_dsyms=true is not explicitly set when is_official_build=false.
-    result['enable_dsyms'] = True
-
   return result
 
 
@@ -307,16 +347,17 @@
     visual_studio_version = GetArgValue(args, 'visual_studio_version')
     visual_studio_runtime_dirs = GetArgValue(args, 'visual_studio_runtime_dirs')
     windows_sdk_path = GetArgValue(args, 'windows_sdk_path')
+    windows_sdk_version = GetArgValue(args, 'windows_sdk_version')
 
   # Target CPU architecture.
-  # - Windows supports "x86" and "x64".
-  # - Mac supports only "x64".
+  # - Windows supports "x86", "x64" and "arm64".
+  # - Mac supports "x64" and "arm64".
   # - Linux supports only "x64" unless using a sysroot environment.
-  if platform == 'macosx':
-    assert target_cpu == 'x64', 'target_cpu must be "x64"'
+  if platform == 'mac':
+    assert target_cpu in ('x64', 'arm64'), 'target_cpu must be "x64" or "arm64"'
   elif platform == 'windows':
-    assert target_cpu in (
-        'x86', 'x64', 'arm64'), 'target_cpu must be "x86", "x64" or "arm64"'
+    assert target_cpu in ('x86', 'x64',
+                          'arm64'), 'target_cpu must be "x86", "x64" or "arm64"'
   elif platform == 'linux':
     assert target_cpu in (
         'x86', 'x64', 'arm',
@@ -360,12 +401,16 @@
     #   windows_sdk_path="<path to WinSDK>"
     #     The directory that contains the Win SDK. For example, a subset of
     #     "C:\Program Files (x86)\Windows Kits\10".
+    #   windows_sdk_version="<WinSDK version>"
+    #     The WinSDK version. For example, "10.0.22621.0".
     #
     # Required environment variables:
     #   DEPOT_TOOLS_WIN_TOOLCHAIN=0
     #   GYP_MSVS_OVERRIDE_PATH=<path to VS root, must match visual_studio_path>
     #   GYP_MSVS_VERSION=<VS version, must match visual_studio_version>
     #   CEF_VCVARS=none
+    #
+    # Optional environment variables (required if vcvarsall.bat does not exist):
     #   INCLUDE=<VS include paths>
     #   LIB=<VS library paths>
     #   PATH=<VS executable paths>
@@ -376,6 +421,7 @@
       assert visual_studio_version != '', 'visual_studio_path requires visual_studio_version'
       assert visual_studio_runtime_dirs != '', 'visual_studio_path requires visual_studio_runtime_dirs'
       assert windows_sdk_path != '', 'visual_studio_path requires windows_sdk_path'
+      assert windows_sdk_version != '', 'visual_studio_path requires windows_sdk_version'
 
       assert os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '') == '0', \
         "visual_studio_path requires DEPOT_TOOLS_WIN_TOOLCHAIN=0 env variable"
@@ -391,18 +437,27 @@
       assert os.environ.get('CEF_VCVARS', '') == 'none', \
         "visual_studio_path requires CEF_VCVARS=none env variable"
 
-      assert 'INCLUDE' in os.environ \
-        and 'LIB' in os.environ \
-        and 'PATH' in os.environ, \
-        "visual_studio_path requires INCLUDE, LIB and PATH env variables"
-
-      # If "%GYP_MSVS_OVERRIDE_PATH%\VC\vcvarsall.bat" exists then environment
-      # variables will be derived from there and the specified INCLUDE/LIB/PATH
-      # values will be ignored by Chromium. If this file does not exist then the
-      # INCLUDE/LIB/PATH values are also required by Chromium.
+      # If vcvarsall.bat exists then environment variables will be derived from
+      # there and any specified INCLUDE/LIB values will be ignored by Chromium
+      # (PATH is retained because it might contain required VS runtime
+      # libraries). If this file does not exist then the INCLUDE/LIB/PATH values
+      # are also required by Chromium.
       vcvars_path = os.path.join(msvs_path, 'VC', 'vcvarsall.bat')
-      if (os.path.exists(vcvars_path)):
-        msg('INCLUDE/LIB/PATH values will be derived from %s' % vcvars_path)
+      if not os.path.exists(vcvars_path):
+        vcvars_path = os.path.join(msvs_path, 'VC', 'Auxiliary', 'Build',
+                                   'vcvarsall.bat')
+      if os.path.exists(vcvars_path):
+        if 'INCLUDE' in os.environ:
+          del os.environ['INCLUDE']
+        if 'LIB' in os.environ:
+          del os.environ['LIB']
+        if 'LIBPATH' in os.environ:
+          del os.environ['LIBPATH']
+      else:
+        assert 'INCLUDE' in os.environ \
+          and 'LIB' in os.environ \
+          and 'PATH' in os.environ, \
+          "visual_studio_path requires INCLUDE, LIB and PATH env variables"
 
 
 def GetConfigArgs(args, is_debug, cpu):
@@ -411,14 +466,18 @@
   """
   add_args = {}
 
-  # Cannot create is_official_build=true is_debug=true builds.
-  # This restriction is enforced in //build/config/BUILDCONFIG.gn.
-  # Instead, our "official Debug" build is a Release build with dchecks and
-  # symbols. Symbols will be generated by default for official builds; see the
-  # definition of 'symbol_level' in //build/config/compiler/compiler.gni.
-  if is_debug and GetArgValue(args, 'is_official_build'):
-    is_debug = False
-    add_args['dcheck_always_on'] = True
+  if GetArgValue(args, 'is_official_build'):
+    # Disable Chromium field trials in official builds.
+    add_args['disable_fieldtrial_testing_config'] = True
+
+    # Cannot create is_official_build=true is_debug=true builds.
+    # This restriction is enforced in //build/config/BUILDCONFIG.gn.
+    # Instead, our "official Debug" build is a Release build with dchecks and
+    # symbols. Symbols will be generated by default for official builds; see the
+    # definition of 'symbol_level' in //build/config/compiler/compiler.gni.
+    if is_debug:
+      is_debug = False
+      add_args['dcheck_always_on'] = True
 
   result = MergeDicts(args, add_args, {
       'is_debug': is_debug,
@@ -443,22 +502,40 @@
       # Avoid libucrt.lib linker errors.
       'use_allocator_shim': False,
 
+      # PartitionAlloc is selected as the default allocator in some cases.
+      # We can't use it because it requires use_allocator_shim=true.
+      'use_partition_alloc_as_malloc': False,
+      'use_partition_alloc': False,
+
+      # These require use_partition_alloc_as_malloc=true, so disable them.
+      'enable_backup_ref_ptr_support': False,
+
       # Avoid /LTCG linker warnings and generate smaller lib files.
       'is_official_build': False,
 
       # Enable base target customizations necessary for distribution of the
       # cef_sandbox static library.
       'is_cef_sandbox_build': True,
-  }
 
-  if is_debug:
-    # Enable iterator debugging (_ITERATOR_DEBUG_LEVEL=2).
-    add_args['enable_iterator_debugging'] = True
+      # Disable Rust dependencies.
+      'enable_rust': False,
+  }
 
   if platform == 'windows':
     # Avoid Debug build linker errors caused by custom libc++.
     add_args['use_custom_libcxx'] = False
 
+    # Avoid dependency on //third_party/perfetto:libperfetto which fails to
+    # build with MSVC libc++.
+    add_args['enable_base_tracing'] = False
+
+    # Allow non-component Debug builds for the sandbox.
+    add_args['forbid_non_component_debug_builds'] = False
+
+  if not is_debug:
+    # Disable DCHECKs in Release builds.
+    add_args['dcheck_always_on'] = False
+
   result = MergeDicts(args, add_args, {
       'is_debug': is_debug,
       'target_cpu': cpu,
@@ -476,14 +553,13 @@
   sysroot_root = os.path.join(src_dir, 'build', 'linux')
   # CPU-specific sysroot directory names.
   # Should match the values in build/config/sysroot.gni.
-  if cpu == 'x86':
-    sysroot_name = 'debian_sid_i386-sysroot'
-  elif cpu == 'x64':
-    sysroot_name = 'debian_sid_amd64-sysroot'
+  release = 'bullseye'
+  if cpu == 'x64':
+    sysroot_name = 'debian_%s_amd64-sysroot' % release
   elif cpu == 'arm':
-    sysroot_name = 'debian_sid_arm-sysroot'
+    sysroot_name = 'debian_%s_armhf-sysroot' % release
   elif cpu == 'arm64':
-    sysroot_name = 'debian_sid_arm64-sysroot'
+    sysroot_name = 'debian_%s_arm64-sysroot' % release
   else:
     raise Exception('Unrecognized sysroot CPU: %s' % cpu)
 
@@ -512,7 +588,7 @@
     use_sysroot = GetArgValue(args, 'use_sysroot')
     if use_sysroot:
       # Only generate configurations for sysroots that have been installed.
-      for cpu in ('x86', 'x64', 'arm', 'arm64'):
+      for cpu in ('x64', 'arm', 'arm64'):
         if LinuxSysrootExists(cpu):
           supported_cpus.append(cpu)
         else:
@@ -520,22 +596,26 @@
               % cpu)
     else:
       supported_cpus = ['x64']
-  elif platform == 'windows':
-    supported_cpus = ['x86', 'x64']
-    if os.environ.get('CEF_ENABLE_ARM64', '') == '1':
+  elif platform in ('windows', 'mac'):
+    if machine == 'amd64' or os.environ.get('CEF_ENABLE_AMD64', '') == '1':
+      supported_cpus.append('x64')
+      if platform == 'windows':
+        supported_cpus.append('x86')
+    if machine == 'arm64' or os.environ.get('CEF_ENABLE_ARM64', '') == '1':
       supported_cpus.append('arm64')
-  elif platform == 'macosx':
-    supported_cpus = ['x64']
   else:
     raise Exception('Unsupported platform')
 
+  if len(supported_cpus) == 0:
+    raise Exception('No supported architectures')
+
   for cpu in supported_cpus:
     if create_debug:
       result['Debug_GN_' + cpu] = GetConfigArgs(args, True, cpu)
     result['Release_GN_' + cpu] = GetConfigArgs(args, False, cpu)
 
-    if platform in ('windows', 'macosx') and GetArgValue(
-        args, 'is_official_build'):
+    if platform in ('windows', 'mac') and GetArgValue(args,
+                                                      'is_official_build'):
       # Build cef_sandbox.lib with a different configuration.
       if create_debug:
         result['Debug_GN_' + cpu + '_sandbox'] = GetConfigArgsSandbox(
@@ -563,7 +643,7 @@
   # Allow override of the platform via the command-line for testing.
   if len(sys.argv) > 1:
     platform = sys.argv[1]
-    if not platform in ('linux', 'macosx', 'windows'):
+    if not platform in ('linux', 'mac', 'windows'):
       sys.stderr.write('Usage: %s <platform>\n' % sys.argv[0])
       sys.exit()
 
diff --git a/src/tools/issue_1999.py b/src/tools/issue_1999.py
index 0143690..c44a135 100644
--- a/src/tools/issue_1999.py
+++ b/src/tools/issue_1999.py
@@ -4,7 +4,7 @@
 #
 # Resort order of object files in libcef.ninja file.
 #
-# See: https://bitbucket.org/chromiumembedded/cef/issues/1999
+# See: https://github.com/chromiumembedded/cef/issues/1999
 #
 # Usage:
 #   import issue_1999
diff --git a/src/tools/make_api_hash_header.py b/src/tools/make_api_hash_header.py
index 2d565f8..6c79efc 100644
--- a/src/tools/make_api_hash_header.py
+++ b/src/tools/make_api_hash_header.py
@@ -35,8 +35,8 @@
 #define CEF_API_HASH_UNIVERSAL "$UNIVERSAL$"
 #if defined(OS_WIN)
 #define CEF_API_HASH_PLATFORM "$WINDOWS$"
-#elif defined(OS_MACOSX)
-#define CEF_API_HASH_PLATFORM "$MACOSX$"
+#elif defined(OS_MAC)
+#define CEF_API_HASH_PLATFORM "$MAC$"
 #elif defined(OS_LINUX)
 #define CEF_API_HASH_PLATFORM "$LINUX$"
 #endif
diff --git a/src/tools/make_capi_header.py b/src/tools/make_capi_header.py
index 52f99b9..6f11286 100644
--- a/src/tools/make_capi_header.py
+++ b/src/tools/make_capi_header.py
@@ -163,7 +163,7 @@
     result += '\n' + format_comment(cls.get_comment(), '', translate_map)
     result += 'typedef struct _'+classname+' {\n'+\
               '  ///\n'+\
-              '  // Base structure.\n'+\
+              '  /// Base structure.\n'+\
               '  ///\n'+\
               '  '+cls.get_parent_capi_name()+' base;\n'
     funcs = cls.get_virtual_funcs()
diff --git a/src/tools/make_cmake.py b/src/tools/make_cmake.py
index 5e4d2d2..b81c396 100644
--- a/src/tools/make_cmake.py
+++ b/src/tools/make_cmake.py
@@ -114,7 +114,7 @@
   #  'includes': [
   #    'cefsimple_sources_common',
   #    'cefsimple_sources_win:WINDOWS',
-  #    'cefsimple_sources_mac:MACOSX',
+  #    'cefsimple_sources_mac:MAC',
   #    'cefsimple_sources_linux:LINUX',
   #  ],
   values = eval('{' + segment + '}', {'__builtins__': None}, None)
diff --git a/src/tools/make_config_header.py b/src/tools/make_config_header.py
index 0930192..e5d98ed 100644
--- a/src/tools/make_config_header.py
+++ b/src/tools/make_config_header.py
@@ -3,122 +3,58 @@
 # can be found in the LICENSE file.
 
 from __future__ import absolute_import
-from date_util import *
+from cef_parser import get_copyright
 from file_util import *
-from optparse import OptionParser
 import sys
 
-# cannot be loaded as a module
-if __name__ != "__main__":
-  sys.stderr.write('This file cannot be loaded as a module!')
-  sys.exit()
 
-# parse command-line options
-disc = """
-This utility creates the config header file.
+def make_config_header(gn_config):
+  """ Creates the header file contents for the cef build configuration. """
+
+  if not path_exists(gn_config):
+    raise Exception('File ' + gn_config + ' does not exist.')
+
+  defines = []
+
+  if sys.platform.startswith('linux'):
+    lines = read_file(gn_config).split("\n")
+
+    # All Linux builds use Ozone, and the X11 platform is enabled by default.
+    # Check if the config is explicitly disabling it.
+    if not 'ozone_platform_x11=false' in lines:
+      defines.append('#define CEF_X11 1')
+
+  result = get_copyright(full=True, translator=False) + \
+"""//
+// ---------------------------------------------------------------------------
+//
+// This file is generated by the make_config_header.py tool.
+//
+
+#ifndef CEF_INCLUDE_CEF_CONFIG_H_
+#define CEF_INCLUDE_CEF_CONFIG_H_
+
+$DEFINES$
+
+#endif  // CEF_INCLUDE_CEF_CONFIG_H_
 """
-parser = OptionParser(description=disc)
-parser.add_option(
-    '--header',
-    dest='header',
-    metavar='FILE',
-    help='output config header file [required]')
-parser.add_option(
-    '--cef_gn_config',
-    dest='cef_gn_config',
-    metavar='FILE',
-    help='input CEF gn config file [required]')
-parser.add_option(
-    '-q',
-    '--quiet',
-    action='store_true',
-    dest='quiet',
-    default=False,
-    help='do not output detailed status information')
-(options, args) = parser.parse_args()
 
-# the header option is required
-if options.header is None or options.cef_gn_config is None:
-  parser.print_help(sys.stdout)
-  sys.exit()
+  result = result.replace('$DEFINES$', "\n".join(defines))
+  return result
 
 
-def check_x11_build(gn_config):
-  """ Scan gn configuration file and decide whether it's x11 build or not """
-  lines = read_file(gn_config).split("\n")
-  for line in lines:
-    parts = line.split('=', 1)
-    if (parts[0] == "use_x11" and
-        parts[1] == "false") or (parts[0] == "use_ozone" and
-                                 parts[1] == "true"):
-      return False
-
-  return True
+def write_config_header(output, gn_config):
+  output = os.path.abspath(output)
+  result = make_config_header(gn_config)
+  return write_file_if_changed(output, result)
 
 
-def write_config_header(header, cef_gn_config):
-  """ Creates the header file for the cef build configuration
-       if the information has changed or if the file doesn't already exist. """
-
-  if not path_exists(cef_gn_config):
-    raise Exception('file ' + cef_gn_config + ' does not exist.')
-
-  if path_exists(header):
-    oldcontents = read_file(header)
-  else:
-    oldcontents = ''
-
-  year = get_year()
-
-  cef_x11_defines = "#define CEF_X11 1" if check_x11_build(
-      cef_gn_config) else ""
-
-  newcontents = '// Copyright (c) '+year+' Marshall A. Greenblatt. All rights reserved.\n'+\
-                '//\n'+\
-                '// Redistribution and use in source and binary forms, with or without\n'+\
-                '// modification, are permitted provided that the following conditions are\n'+\
-                '// met:\n'+\
-                '//\n'+\
-                '//    * Redistributions of source code must retain the above copyright\n'+\
-                '// notice, this list of conditions and the following disclaimer.\n'+\
-                '//    * Redistributions in binary form must reproduce the above\n'+\
-                '// copyright notice, this list of conditions and the following disclaimer\n'+\
-                '// in the documentation and/or other materials provided with the\n'+\
-                '// distribution.\n'+\
-                '//    * Neither the name of Google Inc. nor the name Chromium Embedded\n'+\
-                '// Framework nor the names of its contributors may be used to endorse\n'+\
-                '// or promote products derived from this software without specific prior\n'+\
-                '// written permission.\n'+\
-                '//\n'+\
-                '// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n'+\
-                '// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n'+\
-                '// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n'+\
-                '// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n'+\
-                '// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n'+\
-                '// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n'+\
-                '// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n'+\
-                '// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n'+\
-                '// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n'+\
-                '// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n'+\
-                '// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n'+\
-                '//\n'+\
-                '// ---------------------------------------------------------------------------\n'+\
-                '//\n'+\
-                '// This file is generated by the make_config_header.py tool.\n'+\
-                '//\n\n'+\
-                '#ifndef CEF_INCLUDE_CEF_CONFIG_H_\n'+\
-                '#define CEF_INCLUDE_CEF_CONFIG_H_\n\n'+\
-                '' + cef_x11_defines + '\n'+\
-                '#endif  // CEF_INCLUDE_CEF_CONFIG_H_\n'
-  if newcontents != oldcontents:
-    write_file(header, newcontents)
-    return True
-  return False
+def main(argv):
+  if len(argv) < 3:
+    print(("Usage:\n  %s <output_header_file> <input_args_gn_file>" % argv[0]))
+    sys.exit(-1)
+  write_config_header(argv[1], argv[2])
 
 
-written = write_config_header(options.header, options.cef_gn_config)
-if not options.quiet:
-  if written:
-    sys.stdout.write('File ' + options.header + ' updated.\n')
-  else:
-    sys.stdout.write('File ' + options.header + ' is already up to date.\n')
+if '__main__' == __name__:
+  main(sys.argv)
diff --git a/src/tools/make_cppdocs.bat b/src/tools/make_cppdocs.bat
index dd9809c..d2eae34 100644
--- a/src/tools/make_cppdocs.bat
+++ b/src/tools/make_cppdocs.bat
@@ -1,18 +1,44 @@
 @echo off

+:: Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights

+:: reserved. Use of this source code is governed by a BSD-style license

+:: that can be found in the LICENSE file.

+

+set RC=

+

 setlocal

 

-if "%1"=="" (

-set CPPDOC_EXE="C:\Program Files (x86)\richfeit\CppDoc\CppDoc.exe"

-set CPPDOC_REV="XXX"

-) else (

-set CPPDOC_EXE="C:\Program Files (x86)\richfeit\CppDoc\cppdoc_cmd.exe"

-set CPPDOC_REV="%1"

+:: Check if DOXYGEN_EXE is already provided via the environment.

+if exist "%DOXYGEN_EXE%" goto found_exe

+set DOXYGEN_EXE="C:\Program Files\doxygen\bin\doxygen.exe"

+if not exist %DOXYGEN_EXE% (

+echo ERROR: Please install Doxygen from https://doxygen.nl/ 1>&2

+set ERRORLEVEL=1

+goto end

 )

 

-if not exist %CPPDOC_EXE% (

-echo ERROR: Please install CppDoc from http://www.cppdoc.com/

-) else (

-%CPPDOC_EXE% -overwrite -title="CEF3 C++ API Docs - Revision %CPPDOC_REV%"  -footer="<center><a href="https://bitbucket.org/chromiumembedded/cef" target="_top">Chromium Embedded Framework (CEF)</a> Copyright &copy 2016 Marshall A. Greenblatt</center>" -namespace-as-project -comment-format="///;//;///" -classdir=projects -module="cppdoc-standard" -extensions=h -languages="c=cpp,cc=cpp,cpp=cpp,cs=csharp,cxx=cpp,h=cpp,hpp=cpp,hxx=cpp,java=java" -D"OS_WIN" -D"USING_CEF_SHARED" -D"__cplusplus" -D"CEF_STRING_TYPE_UTF16" -enable-author=false -enable-deprecations=true -enable-since=true -enable-version=false -file-links-for-globals=false -generate-deprecations-list=false -generate-hierarchy=true -header-background-dark="#ccccff" -header-background-light="#eeeeff" -include-private=false -include-protected=true -index-file-base=index -overview-html=overview.html -reduce-summary-font=true -selected-text-background=navy -selected-text-foreground=white -separate-index-pages=false -show-cppdoc-version=false -show-timestamp=false -summary-html=project.html -suppress-details=false -suppress-frames-links=false -table-background=white -wrap-long-lines=false ..\include #capi "..\docs\index.html"

-)

+:found_exe

 

-endlocal
\ No newline at end of file
+:: Environment variables inserted into the Doxyfile via `$(VAR_NAME)` syntax.

+for /F %%i in ('python.bat %~dp0\cef_version.py current') do set PROJECT_NUMBER=%%i

+

+:: Run from the top-level CEF directory so that relative paths resolve correctly.

+set CURRENT_PATH="%CD%"

+cd "%~dp0\.."

+

+:: Generate documentation in the docs/html directory.

+%DOXYGEN_EXE% Doxyfile

+

+:: Write a docs/index.html file.

+echo|set /p="<html><head><meta http-equiv="refresh" content="0;URL='html/index.html'"/></head></html>" > docs/index.html

+

+cd "%CURRENT_PATH%"

+

+:end

+endlocal & set RC=%ERRORLEVEL%

+goto omega

+

+:returncode

+exit /B %RC%

+

+:omega

+call :returncode %RC%
\ No newline at end of file
diff --git a/src/tools/make_cppdocs.sh b/src/tools/make_cppdocs.sh
new file mode 100755
index 0000000..724d7b8
--- /dev/null
+++ b/src/tools/make_cppdocs.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights
+# reserved. Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file.
+
+if ! command -v doxygen &> /dev/null
+then
+  echo "ERROR: Please install Doxygen" 1>&2
+  exit 1
+fi
+
+# Determine the absolute path to the script directory.
+SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )"
+
+# Determine the top-level CEF directory.
+CEF_DIR="${SCRIPT_DIR}/.."
+
+# Environment variables inserted into the Doxyfile via `$(VAR_NAME)` syntax.
+export PROJECT_NUMBER=$(python3 ${SCRIPT_DIR}/cef_version.py current)
+
+# Generate documentation in the docs/html directory.
+# Run from the top-level CEF directory so that relative paths resolve correctly.
+( cd ${CEF_DIR} && doxygen Doxyfile )
+
+# Write a docs/index.html file.
+echo "<html><head><meta http-equiv=\"refresh\" content=\"0;URL='html/index.html'\"/></head></html>" > ${CEF_DIR}/docs/index.html
+
diff --git a/src/tools/make_cpptoc_impl.py b/src/tools/make_cpptoc_impl.py
index 305244b..2645447 100644
--- a/src/tools/make_cpptoc_impl.py
+++ b/src/tools/make_cpptoc_impl.py
@@ -20,7 +20,7 @@
   notify(name + ' has manual edits')
 
   # retrieve the C API prototype parts
-  parts = func.get_capi_parts(defined_names)
+  parts = func.get_capi_parts(defined_names, True)
 
   changes = format_translation_changes(impl, parts)
   if len(changes) > 0:
@@ -36,7 +36,7 @@
       func.parent, obj_header)
 
   # retrieve the C API prototype parts
-  parts = func.get_capi_parts(defined_names)
+  parts = func.get_capi_parts(defined_names, True)
   result = make_cpptoc_impl_proto(name, func, parts) + ' {'
 
   if isinstance(func.parent, obj_class) and \
@@ -71,7 +71,7 @@
     result += '\n  // BEGIN DELETE BEFORE MODIFYING'
     result += '\n  // AUTO-GENERATED CONTENT'
     result += '\n  // COULD NOT IMPLEMENT DUE TO: ' + ', '.join(invalid)
-    result += '\n  #pragma message("Warning: "__FILE__": ' + name + ' is not implemented")'
+    result += '\n  #pragma message("Warning: " __FILE__ ": ' + name + ' is not implemented")'
     result += '\n  // END DELETE BEFORE MODIFYING'
     result += '\n}\n\n'
     return result
@@ -85,8 +85,9 @@
   # parameter verification
   if isinstance(func, obj_function_virtual):
     result += '\n  DCHECK(self);'\
-              '\n  if (!self)'\
-              '\n    return'+retval_default+';'
+              '\n  if (!self) {'\
+              '\n    return'+retval_default+';'\
+              '\n  }'
 
   for arg in args:
     arg_type = arg.get_arg_type()
@@ -115,32 +116,42 @@
        arg_type == 'string_map_multi_byref' or arg_type == 'string_map_multi_byref_const':
       result += comment+\
                 '\n  DCHECK('+arg_name+');'\
-                '\n  if (!'+arg_name+')'\
-                '\n    return'+retval_default+';'
+                '\n  if (!'+arg_name+') {'\
+                '\n    return'+retval_default+';'\
+                '\n  }'
+      if arg_type == 'struct_byref_const' or arg_type == 'struct_byref':
+        result +=\
+                '\n  if (!template_util::has_valid_size('+arg_name+')) {'\
+                '\n    DCHECK(false) << "invalid '+arg_name+'->[base.]size";'\
+                '\n    return'+retval_default+';'\
+                '\n  }'
     elif arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref' or \
         arg_type == 'refptr_vec_same_byref' or arg_type == 'refptr_vec_diff_byref' or \
         arg_type == 'ownptr_vec_same_byref' or arg_type == 'ownptr_vec_diff_byref' or \
         arg_type == 'rawptr_vec_same_byref' or arg_type == 'rawptr_vec_diff_byref':
       result += comment+\
                 '\n  DCHECK('+arg_name+'Count && (*'+arg_name+'Count == 0 || '+arg_name+'));'\
-                '\n  if (!'+arg_name+'Count || (*'+arg_name+'Count > 0 && !'+arg_name+'))'\
-                '\n    return'+retval_default+';'
+                '\n  if (!'+arg_name+'Count || (*'+arg_name+'Count > 0 && !'+arg_name+')) {'\
+                '\n    return'+retval_default+';'\
+                '\n  }'
     elif arg_type == 'simple_vec_byref_const' or arg_type == 'bool_vec_byref_const' or \
         arg_type == 'refptr_vec_same_byref_const' or arg_type == 'refptr_vec_diff_byref_const' or \
         arg_type == 'ownptr_vec_same_byref_const' or arg_type == 'ownptr_vec_diff_byref_const' or \
         arg_type == 'rawptr_vec_same_byref_const' or arg_type == 'rawptr_vec_diff_byref_const':
       result += comment+\
                 '\n  DCHECK('+arg_name+'Count == 0 || '+arg_name+');'\
-                '\n  if ('+arg_name+'Count > 0 && !'+arg_name+')'\
-                '\n    return'+retval_default+';'
+                '\n  if ('+arg_name+'Count > 0 && !'+arg_name+') {'\
+                '\n    return'+retval_default+';'\
+                '\n  }'
 
     # check index params
     index_params = arg.parent.get_attrib_list('index_param')
     if not index_params is None and arg_name in index_params:
       result += comment+\
                 '\n  DCHECK_GE('+arg_name+', 0);'\
-                '\n  if ('+arg_name+' < 0)'\
-                '\n    return'+retval_default+';'
+                '\n  if ('+arg_name+' < 0) {'\
+                '\n    return'+retval_default+';'\
+                '\n  }'
 
   if len(optional) > 0:
     # Wrap the comment at 80 characters.
@@ -187,15 +198,17 @@
       struct_type = arg.get_type().get_type()
       result += comment+\
                 '\n  '+struct_type+' '+arg_name+'Obj;'\
-                '\n  if ('+arg_name+')'\
-                '\n    '+arg_name+'Obj.Set(*'+arg_name+', false);'
+                '\n  if ('+arg_name+') {'\
+                '\n    '+arg_name+'Obj.Set(*'+arg_name+', false);'\
+                '\n  }'
       params.append(arg_name + 'Obj')
     elif arg_type == 'struct_byref':
       struct_type = arg.get_type().get_type()
       result += comment+\
                 '\n  '+struct_type+' '+arg_name+'Obj;'\
-                '\n  if ('+arg_name+')'\
-                '\n    '+arg_name+'Obj.AttachTo(*'+arg_name+');'
+                '\n  if ('+arg_name+') {'\
+                '\n    '+arg_name+'Obj.AttachTo(*'+arg_name+');'\
+                '\n  }'
       params.append(arg_name + 'Obj')
     elif arg_type == 'string_byref_const':
       params.append('CefString(' + arg_name + ')')
@@ -220,7 +233,7 @@
       result += comment+\
                 '\n  CefOwnPtr<'+ptr_class+'> '+arg_name+'Ptr('+ptr_class+'CToCpp::Wrap('+arg_name+'));'
       if arg_type == 'ownptr_diff':
-        params.append('OWN_PASS(' + arg_name + 'Ptr)')
+        params.append('std::move(' + arg_name + 'Ptr)')
       else:
         params.append(arg_name + 'Ptr.get()')
     elif arg_type == 'refptr_same_byref' or arg_type == 'refptr_diff_byref':
@@ -231,8 +244,9 @@
         assign = ptr_class + 'CToCpp::Wrap(*' + arg_name + ')'
       result += comment+\
                 '\n  CefRefPtr<'+ptr_class+'> '+arg_name+'Ptr;'\
-                '\n  if ('+arg_name+' && *'+arg_name+')'\
+                '\n  if ('+arg_name+' && *'+arg_name+') {'\
                 '\n    '+arg_name+'Ptr = '+assign+';'\
+                '\n  }'\
                 '\n  '+ptr_class+'* '+arg_name+'Orig = '+arg_name+'Ptr.get();'
       params.append(arg_name + 'Ptr')
     elif arg_type == 'string_vec_byref' or arg_type == 'string_vec_byref_const':
@@ -352,16 +366,19 @@
 
     if arg_type == 'simple_byref':
       result += comment+\
-                '\n  if ('+arg_name+')'\
-                '\n    *'+arg_name+' = '+arg_name+'Val;'
+                '\n  if ('+arg_name+') {'\
+                '\n    *'+arg_name+' = '+arg_name+'Val;'\
+                '\n  }'
     elif arg_type == 'bool_byref' or arg_type == 'bool_byaddr':
       result += comment+\
-                '\n  if ('+arg_name+')'\
-                '\n    *'+arg_name+' = '+arg_name+'Bool?true:false;'
+                '\n  if ('+arg_name+') {'\
+                '\n    *'+arg_name+' = '+arg_name+'Bool?true:false;'\
+                '\n  }'
     elif arg_type == 'struct_byref':
       result += comment+\
-                '\n  if ('+arg_name+')'\
-                '\n    '+arg_name+'Obj.DetachTo(*'+arg_name+');'
+                '\n  if ('+arg_name+') {'\
+                '\n    '+arg_name+'Obj.DetachTo(*'+arg_name+');'\
+                '\n  }'
     elif arg_type == 'refptr_same_byref' or arg_type == 'refptr_diff_byref':
       ptr_class = arg.get_type().get_ptr_type()
       if arg_type == 'refptr_same_byref':
@@ -441,10 +458,10 @@
       result += '\n  return ' + ptr_class + 'CToCpp::Unwrap(_retval);'
     elif retval_type == 'ownptr_same':
       ptr_class = retval.get_type().get_ptr_type()
-      result += '\n  return ' + ptr_class + 'CppToC::WrapOwn(OWN_PASS(_retval));'
+      result += '\n  return ' + ptr_class + 'CppToC::WrapOwn(std::move(_retval));'
     elif retval_type == 'ownptr_diff':
       ptr_class = retval.get_type().get_ptr_type()
-      result += '\n  return ' + ptr_class + 'CToCpp::UnwrapOwn(OWN_PASS(_retval));'
+      result += '\n  return ' + ptr_class + 'CToCpp::UnwrapOwn(std::move(_retval));'
     else:
       raise Exception('Unsupported return type %s in %s' % (retval_type, name))
 
@@ -545,8 +562,8 @@
     impl = ['', '']
     for clsname in derived_classes:
       impl[0] += '  if (type == '+get_wrapper_type_enum(clsname)+') {\n'+\
-                 '    return OWN_RETURN_AS('+clsname+'CppToC::UnwrapOwn(reinterpret_cast<'+\
-                 get_capi_name(clsname, True)+'*>(s)), '+cur_clsname+');\n'+\
+                 '    return '+clsname+'CppToC::UnwrapOwn(reinterpret_cast<'+\
+                 get_capi_name(clsname, True)+'*>(s));\n'+\
                  '  }\n'
       impl[1] += '  if (type == '+get_wrapper_type_enum(clsname)+') {\n'+\
                  '    return '+clsname+'CppToC::UnwrapRaw(reinterpret_cast<'+\
@@ -637,18 +654,18 @@
   if base_scoped:
     const += 'template<> CefOwnPtr<'+clsname+'> '+parent_sig+'::UnwrapDerivedOwn(CefWrapperType type, '+capiname+'* s) {\n' + \
              unwrapderived[0] + \
-             '  NOTREACHED() << "Unexpected class type: " << type;\n'+ \
+             '  DCHECK(false) << "Unexpected class type: " << type;\n'+ \
              '  return CefOwnPtr<'+clsname+'>();\n'+ \
              '}\n\n' + \
              'template<> CefRawPtr<'+clsname+'> '+parent_sig+'::UnwrapDerivedRaw(CefWrapperType type, '+capiname+'* s) {\n' + \
              unwrapderived[1] + \
-             '  NOTREACHED() << "Unexpected class type: " << type;\n'+ \
+             '  DCHECK(false) << "Unexpected class type: " << type;\n'+ \
              '  return nullptr;\n'+ \
              '}\n\n'
   else:
     const += 'template<> CefRefPtr<'+clsname+'> '+parent_sig+'::UnwrapDerived(CefWrapperType type, '+capiname+'* s) {\n' + \
              unwrapderived + \
-             '  NOTREACHED() << "Unexpected class type: " << type;\n'+ \
+             '  DCHECK(false) << "Unexpected class type: " << type;\n'+ \
              '  return nullptr;\n'+ \
              '}\n\n'
 
diff --git a/src/tools/make_ctocpp_header.py b/src/tools/make_ctocpp_header.py
index 2218198..708d7d6 100644
--- a/src/tools/make_ctocpp_header.py
+++ b/src/tools/make_ctocpp_header.py
@@ -15,7 +15,7 @@
     if cls.is_client_side():
       impl += ' override;\n'
     else:
-      impl += ' OVERRIDE;\n'
+      impl += ' override;\n'
 
   return impl
 
diff --git a/src/tools/make_ctocpp_impl.py b/src/tools/make_ctocpp_impl.py
index 52dd9c5..07c4cf8 100644
--- a/src/tools/make_ctocpp_impl.py
+++ b/src/tools/make_ctocpp_impl.py
@@ -88,15 +88,15 @@
     result += '\n  const char* api_hash = cef_api_hash(0);'\
               '\n  if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) {'\
               '\n    // The libcef API hash does not match the current header API hash.'\
-              '\n    NOTREACHED();'\
+              '\n    DCHECK(false);'\
               '\n    return'+retval_default+';'\
               '\n  }\n'
 
   if isinstance(func, obj_function_virtual):
     # add the structure size check
-    result += '\n  if (CEF_MEMBER_MISSING(_struct, ' + func.get_capi_name(
-    ) + '))'
-    result += '\n    return' + retval_default + ';\n'
+    result += '\n  if (CEF_MEMBER_MISSING(_struct, ' + func.get_capi_name() + ')) {'\
+              '\n    return' + retval_default + ';\n'\
+              '\n  }\n'
 
   if len(invalid) > 0:
     notify(name + ' could not be autogenerated')
@@ -104,7 +104,7 @@
     result += '\n  // BEGIN DELETE BEFORE MODIFYING'
     result += '\n  // AUTO-GENERATED CONTENT'
     result += '\n  // COULD NOT IMPLEMENT DUE TO: ' + ', '.join(invalid)
-    result += '\n  #pragma message("Warning: "__FILE__": ' + name + ' is not implemented")'
+    result += '\n  #pragma message("Warning: " __FILE__ ": ' + name + ' is not implemented")'
     result += '\n  // END DELETE BEFORE MODIFYING'
     result += '\n}\n\n'
     return result
@@ -131,32 +131,37 @@
     if arg_type == 'simple_byaddr' or arg_type == 'bool_byaddr':
       result += comment+\
                 '\n  DCHECK('+arg_name+');'\
-                '\n  if (!'+arg_name+')'\
-                '\n    return'+retval_default+';'
+                '\n  if (!'+arg_name+') {'\
+                '\n    return'+retval_default+';'\
+                '\n  }'
     elif arg_type == 'refptr_same' or arg_type == 'refptr_diff' or \
          arg_type == 'ownptr_same' or arg_type == 'ownptr_diff':
       result += comment+\
                 '\n  DCHECK('+arg_name+'.get());'\
-                '\n  if (!'+arg_name+'.get())'\
-                '\n    return'+retval_default+';'
+                '\n  if (!'+arg_name+'.get()) {'\
+                '\n    return'+retval_default+';'\
+                '\n  }'
     elif arg_type == 'rawptr_same' or arg_type == 'rawptr_diff':
       result += comment+\
                 '\n  DCHECK('+arg_name+');'\
-                '\n  if (!'+arg_name+')'\
-                '\n    return'+retval_default+';'
+                '\n  if (!'+arg_name+') {'\
+                '\n    return'+retval_default+';'\
+                '\n  }'
     elif arg_type == 'string_byref_const':
       result += comment+\
                 '\n  DCHECK(!'+arg_name+'.empty());'\
-                '\n  if ('+arg_name+'.empty())'\
-                '\n    return'+retval_default+';'
+                '\n  if ('+arg_name+'.empty()) {'\
+                '\n    return'+retval_default+';'\
+                '\n  }'
 
     # check index params
     index_params = arg.parent.get_attrib_list('index_param')
     if not index_params is None and arg_name in index_params:
       result += comment+\
                 '\n  DCHECK_GE('+arg_name+', 0);'\
-                '\n  if ('+arg_name+' < 0)'\
-                '\n    return'+retval_default+';'
+                '\n  if ('+arg_name+' < 0) {'\
+                '\n    return'+retval_default+';'\
+                '\n  }'
 
   if len(optional) > 0:
     # Wrap the comment at 80 characters.
@@ -207,7 +212,8 @@
       params.append(ptr_class + 'CToCpp::Unwrap(' + arg_name + ')')
     elif arg_type == 'ownptr_same':
       ptr_class = arg.get_type().get_ptr_type()
-      params.append(ptr_class + 'CToCpp::UnwrapOwn(OWN_PASS(' + arg_name + '))')
+      params.append(ptr_class + 'CToCpp::UnwrapOwn(std::move(' + arg_name +
+                    '))')
     elif arg_type == 'rawptr_same':
       ptr_class = arg.get_type().get_ptr_type()
       params.append(ptr_class + 'CToCpp::UnwrapRaw(' + arg_name + ')')
@@ -216,7 +222,7 @@
       params.append(ptr_class + 'CppToC::Wrap(' + arg_name + ')')
     elif arg_type == 'ownptr_diff':
       ptr_class = arg.get_type().get_ptr_type()
-      params.append(ptr_class + 'CppToC::WrapOwn(OWN_PASS(' + arg_name + '))')
+      params.append(ptr_class + 'CppToC::WrapOwn(std::move(' + arg_name + '))')
     elif arg_type == 'rawptr_diff':
       ptr_class = arg.get_type().get_ptr_type()
       result += comment+\
@@ -231,30 +237,34 @@
         assign = ptr_class + 'CppToC::Wrap(' + arg_name + ')'
       result += comment+\
                 '\n  '+ptr_struct+'* '+arg_name+'Struct = NULL;'\
-                '\n  if ('+arg_name+'.get())'\
+                '\n  if ('+arg_name+'.get()) {'\
                 '\n    '+arg_name+'Struct = '+assign+';'\
+                '\n  }'\
                 '\n  '+ptr_struct+'* '+arg_name+'Orig = '+arg_name+'Struct;'
       params.append('&' + arg_name + 'Struct')
     elif arg_type == 'string_vec_byref' or arg_type == 'string_vec_byref_const':
       result += comment+\
                 '\n  cef_string_list_t '+arg_name+'List = cef_string_list_alloc();'\
                 '\n  DCHECK('+arg_name+'List);'\
-                '\n  if ('+arg_name+'List)'\
-                '\n    transfer_string_list_contents('+arg_name+', '+arg_name+'List);'
+                '\n  if ('+arg_name+'List) {'\
+                '\n    transfer_string_list_contents('+arg_name+', '+arg_name+'List);'\
+                '\n  }'
       params.append(arg_name + 'List')
     elif arg_type == 'string_map_single_byref' or arg_type == 'string_map_single_byref_const':
       result += comment+\
                 '\n  cef_string_map_t '+arg_name+'Map = cef_string_map_alloc();'\
                 '\n  DCHECK('+arg_name+'Map);'\
-                '\n  if ('+arg_name+'Map)'\
-                '\n    transfer_string_map_contents('+arg_name+', '+arg_name+'Map);'
+                '\n  if ('+arg_name+'Map) {'\
+                '\n    transfer_string_map_contents('+arg_name+', '+arg_name+'Map);'\
+                '\n  }'
       params.append(arg_name + 'Map')
     elif arg_type == 'string_map_multi_byref' or arg_type == 'string_map_multi_byref_const':
       result += comment+\
                 '\n  cef_string_multimap_t '+arg_name+'Multimap = cef_string_multimap_alloc();'\
                 '\n  DCHECK('+arg_name+'Multimap);'\
-                '\n  if ('+arg_name+'Multimap)'\
-                '\n    transfer_string_multimap_contents('+arg_name+', '+arg_name+'Multimap);'
+                '\n  if ('+arg_name+'Multimap) {'\
+                '\n    transfer_string_multimap_contents('+arg_name+', '+arg_name+'Multimap);'\
+                '\n  }'
       params.append(arg_name + 'Multimap')
     elif arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref' or \
          arg_type == 'refptr_vec_same_byref' or arg_type == 'refptr_vec_diff_byref':
@@ -373,8 +383,9 @@
                 '\n  '+arg_name+' = '+arg_name+'Int?true:false;'
     elif arg_type == 'bool_byaddr':
       result += comment+\
-                '\n  if ('+arg_name+')'\
-                '\n    *'+arg_name+' = '+arg_name+'Int?true:false;'
+                '\n  if ('+arg_name+') {'\
+                '\n    *'+arg_name+' = '+arg_name+'Int?true:false;'\
+                '\n  }'
     elif arg_type == 'refptr_same_byref' or arg_type == 'refptr_diff_byref':
       ptr_class = arg.get_type().get_ptr_type()
       ptr_struct = arg.get_type().get_result_ptr_type_root()
@@ -399,8 +410,9 @@
                 '\n  }'
     elif arg_type == 'string_vec_byref_const':
       result += comment+\
-                '\n  if ('+arg_name+'List)'\
-                '\n    cef_string_list_free('+arg_name+'List);'
+                '\n  if ('+arg_name+'List) {'\
+                '\n    cef_string_list_free('+arg_name+'List);'\
+                '\n  }'
     elif arg_type == 'string_map_single_byref':
       result += comment+\
                 '\n  if ('+arg_name+'Map) {'\
@@ -410,8 +422,9 @@
                 '\n  }'
     elif arg_type == 'string_map_single_byref_const':
       result += comment+\
-                '\n  if ('+arg_name+'Map)'\
-                '\n    cef_string_map_free('+arg_name+'Map);'
+                '\n  if ('+arg_name+'Map) {'\
+                '\n    cef_string_map_free('+arg_name+'Map);'\
+                '\n  }'
     elif arg_type == 'string_map_multi_byref':
       result += comment+\
                 '\n  if ('+arg_name+'Multimap) {'\
@@ -421,8 +434,9 @@
                 '\n  }'
     elif arg_type == 'string_map_multi_byref_const':
       result += comment+\
-                '\n  if ('+arg_name+'Multimap)'\
-                '\n    cef_string_multimap_free('+arg_name+'Multimap);'
+                '\n  if ('+arg_name+'Multimap) {'\
+                '\n    cef_string_multimap_free('+arg_name+'Multimap);'\
+                '\n  }'
     elif arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref' or \
          arg_type == 'refptr_vec_same_byref' or arg_type == 'refptr_vec_diff_byref':
       count_func = arg.get_attrib_count_func()
@@ -455,8 +469,9 @@
                   '\n      delete '+ptr_class+'CppToC::GetWrapper('+arg_name+'List[i]);'\
                   '\n    }'\
                   '\n  }'
-      result += '\n  if ('+arg_name+'List)'\
-                '\n    delete [] '+arg_name+'List;'
+      result += '\n  if ('+arg_name+'List) {'\
+                '\n    delete [] '+arg_name+'List;'\
+                '\n  }'
 
   if len(result) != result_len:
     result += '\n'
@@ -557,7 +572,7 @@
                  '  }\n'
       impl[1] += '  if (type == '+get_wrapper_type_enum(clsname)+') {\n'+\
                  '    return reinterpret_cast<'+get_capi_name(cls.get_name(), True)+'*>('+\
-                 clsname+'CToCpp::UnwrapRaw(CefRawPtr<'+clsname+'>(reinterpret_cast<'+clsname+'*>(CEF_RAW_PTR_GET(c)))));\n'+\
+                 clsname+'CToCpp::UnwrapRaw(CefRawPtr<'+clsname+'>(reinterpret_cast<'+clsname+'*>(c))));\n'+\
                  '  }\n'
   else:
     impl = ''
@@ -634,18 +649,18 @@
   if base_scoped:
     const += 'template<> '+capiname+'* '+parent_sig+'::UnwrapDerivedOwn(CefWrapperType type, CefOwnPtr<'+clsname+'> c) {\n'+ \
              unwrapderived[0] + \
-             '  NOTREACHED() << "Unexpected class type: " << type;\n'+ \
+             '  DCHECK(false) << "Unexpected class type: " << type;\n'+ \
              '  return nullptr;\n'+ \
              '}\n\n' + \
              'template<> '+capiname+'* '+parent_sig+'::UnwrapDerivedRaw(CefWrapperType type, CefRawPtr<'+clsname+'> c) {\n'+ \
              unwrapderived[1] + \
-             '  NOTREACHED() << "Unexpected class type: " << type;\n'+ \
+             '  DCHECK(false) << "Unexpected class type: " << type;\n'+ \
              '  return nullptr;\n'+ \
              '}\n\n'
   else:
     const += 'template<> '+capiname+'* '+parent_sig+'::UnwrapDerived(CefWrapperType type, '+clsname+'* c) {\n'+ \
              unwrapderived + \
-             '  NOTREACHED() << "Unexpected class type: " << type;\n'+ \
+             '  DCHECK(false) << "Unexpected class type: " << type;\n'+ \
              '  return nullptr;\n'+ \
              '}\n\n'
 
diff --git a/src/tools/make_distrib.py b/src/tools/make_distrib.py
index 80ab514..9c2fdf0 100644
--- a/src/tools/make_distrib.py
+++ b/src/tools/make_distrib.py
@@ -94,7 +94,7 @@
   # platform directory
   if platform == 'windows':
     platform_cmp = 'win'
-  elif platform == 'macosx':
+  elif platform == 'mac':
     platform_cmp = 'mac'
   elif platform == 'linux':
     platform_cmp = 'linux'
@@ -135,8 +135,8 @@
 
   if platform == 'windows':
     platform_str = 'Windows'
-  elif platform == 'macosx':
-    platform_str = 'Mac OS-X'
+  elif platform == 'mac':
+    platform_str = 'MacOS'
   elif platform == 'linux':
     platform_str = 'Linux'
 
@@ -149,7 +149,7 @@
                    'section of this document for licensing terms and conditions.'
   elif mode == 'minimal':
     distrib_type = 'Minimal'
-    distrib_desc = 'This distribution contains the minimial components necessary to build and\n' \
+    distrib_desc = 'This distribution contains the minimal components necessary to build and\n' \
                    'distribute an application using CEF on the ' + platform_str + ' platform. Please see\n' \
                    'the LICENSING section of this document for licensing terms and conditions.'
   elif mode == 'client':
@@ -174,34 +174,27 @@
     sys.stdout.write('Creating README.TXT file.\n')
 
 
-def create_fuzed_gtest(tests_dir):
-  """ Generate a fuzed version of gtest and build the expected directory structure. """
-  src_gtest_dir = os.path.join(src_dir, 'third_party', 'googletest', 'src',
-                               'googletest')
-  run('%s fuse_gtest_files.py \"%s\"' % (sys.executable, tests_dir),
-      os.path.join(src_gtest_dir, 'scripts'))
-
+def copy_gtest(tests_dir):
+  """ Copy GTest files to the expected directory structure. """
   if not options.quiet:
     sys.stdout.write('Building gtest directory structure.\n')
 
+  src_gtest_dir = os.path.join(cef_dir, 'tools', 'distrib', 'gtest')
   target_gtest_dir = os.path.join(tests_dir, 'gtest')
-  gtest_header = os.path.join(target_gtest_dir, 'gtest.h')
-  gtest_cpp = os.path.join(target_gtest_dir, 'gtest-all.cc')
-
-  if not os.path.exists(gtest_header):
-    raise Exception('Generated file not found: %s' % gtest_header)
-  if not os.path.exists(gtest_cpp):
-    raise Exception('Generated file not found: %s' % gtest_cpp)
 
   # gtest header file at tests/gtest/include/gtest/gtest.h
   target_gtest_header_dir = os.path.join(target_gtest_dir, 'include', 'gtest')
   make_dir(target_gtest_header_dir, options.quiet)
-  move_file(gtest_header, target_gtest_header_dir, options.quiet)
+  copy_file(
+      os.path.join(src_gtest_dir, 'gtest.h'), target_gtest_header_dir,
+      options.quiet)
 
   # gtest source file at tests/gtest/src/gtest-all.cc
   target_gtest_cpp_dir = os.path.join(target_gtest_dir, 'src')
   make_dir(target_gtest_cpp_dir, options.quiet)
-  move_file(gtest_cpp, target_gtest_cpp_dir, options.quiet)
+  copy_file(
+      os.path.join(src_gtest_dir, 'gtest-all.cc'), target_gtest_cpp_dir,
+      options.quiet)
 
   # gtest LICENSE file at tests/gtest/LICENSE
   copy_file(
@@ -209,9 +202,25 @@
 
   # CEF README file at tests/gtest/README.cef
   copy_file(
-      os.path.join(cef_dir, 'tests', 'gtest', 'README.cef.in'),
+      os.path.join(src_gtest_dir, 'README.cef'),
       os.path.join(target_gtest_dir, 'README.cef'), options.quiet)
 
+  # Copy tests/gtest/teamcity files
+  copy_dir(
+      os.path.join(cef_dir, 'tests', 'gtest', 'teamcity'),
+      os.path.join(target_gtest_dir, 'teamcity'), options.quiet)
+
+
+def transfer_doxyfile(dst_dir, quiet):
+  """ Transfer and post-process the Doxyfile. """
+  src_file = os.path.join(cef_dir, 'Doxyfile')
+  if os.path.isfile(src_file):
+    data = read_file(src_file)
+    data = data.replace("$(PROJECT_NUMBER)", cef_ver)
+    write_file(os.path.join(dst_dir, 'Doxyfile'), data)
+    if not quiet:
+      sys.stdout.write('Creating Doxyfile file.\n')
+
 
 def transfer_gypi_files(src_dir, gypi_paths, gypi_path_prefix, dst_dir, quiet):
   """ Transfer files from one location to another. """
@@ -358,9 +367,9 @@
   """ Combine multiple static libraries into a single static library. """
   intermediate_obj = None
   if platform == 'windows':
-    cmdline = 'msvs_env.bat win%s "%s" combine_libs.py -o "%s"' % (
-        platform_arch, sys.executable, dest_lib)
-  elif platform == 'macosx':
+    cmdline = 'msvs_env.bat win%s "%s" combine_libs.py -b "%s" -o "%s"' % (
+        platform_arch, sys.executable, build_dir, dest_lib)
+  elif platform == 'mac':
     # Find CEF_EXPORT symbols from libcef_sandbox.a (include/cef_sandbox_mac.h)
     # Export only symbols that include these strings.
     symbol_match = [
@@ -381,7 +390,8 @@
     # Create an intermediate object file that combines all other object files.
     # Symbols not identified above will be made private (local).
     intermediate_obj = os.path.splitext(dest_lib)[0] + '.o'
-    cmdline = 'ld -arch x86_64 -r -o "%s"' % intermediate_obj
+    arch = 'arm64' if options.arm64build else 'x86_64'
+    cmdline = 'ld -arch %s -r -o "%s"' % (arch, intermediate_obj)
     for symbol in symbols:
       cmdline += ' -exported_symbol %s' % symbol
 
@@ -390,6 +400,8 @@
     for path in get_files(lib_path):  # Expand wildcards in |lib_path|.
       if not path_exists(path):
         raise Exception('File not found: ' + path)
+      if platform == 'windows':
+        path = os.path.relpath(path, build_dir)
       cmdline += ' "%s"' % path
   run(cmdline, os.path.join(cef_dir, 'tools'))
 
@@ -410,6 +422,10 @@
     # Verify that no C++ symbols are imported by the archive file. If the
     # archive imports C++ symbols and the client app links an incompatible C++
     # library, the result will be undefined behavior.
+    # For example, to avoid importing libc++ symbols the cef_sandbox target
+    # should have a dependency on libc++abi. This dependency can be verified
+    # with the following command:
+    # gn path out/[config] //cef:cef_sandbox //buildtools/third_party/libc++abi
     print('Verifying imported (undefined) symbols...')
     undefined_symbols = get_undefined_symbols(dest_lib)
     cpp_symbols = list(
@@ -454,6 +470,11 @@
     help='name of the subdirectory for the distribution',
     default='')
 parser.add_option(
+    '--distrib-subdir-suffix',
+    dest='distribsubdirsuffix',
+    help='suffix added to name of the subdirectory for the distribution',
+    default='')
+parser.add_option(
     '--allow-partial',
     action='store_true',
     dest='allowpartial',
@@ -539,7 +560,7 @@
 if sys.platform == 'win32':
   platform = 'windows'
 elif sys.platform == 'darwin':
-  platform = 'macosx'
+  platform = 'mac'
 elif sys.platform.startswith('linux'):
   platform = 'linux'
 
@@ -560,11 +581,7 @@
   print_error('--arm-build is only supported on Linux.')
   sys.exit()
 
-if options.arm64build and not platform in ('linux', 'windows'):
-  print_error('--arm64-build is only supported on Linux and Windows.')
-  sys.exit()
-
-if options.sandbox and not platform in ('macosx', 'windows'):
+if options.sandbox and not platform in ('mac', 'windows'):
   print_error('--sandbox is only supported on macOS and Windows.')
   sys.exit()
 
@@ -627,7 +644,15 @@
 output_dir_base = 'cef_binary_' + cef_ver
 
 if options.distribsubdir == '':
-  output_dir_name = output_dir_base + '_' + platform + platform_arch
+  if platform == 'mac':
+    # For backwards compatibility keep the old default directory name on mac.
+    platform_name = 'macos' + ('x' if platform_arch == '64' else '')
+  else:
+    platform_name = platform
+
+  output_dir_name = output_dir_base + '_' + platform_name + platform_arch
+  if options.distribsubdirsuffix != '':
+    output_dir_name += '_' + options.distribsubdirsuffix
 else:
   output_dir_name = options.distribsubdir
 
@@ -707,6 +732,8 @@
 
   # Transfer generated include files.
   generated_includes = [
+      'cef_command_ids.h',
+      'cef_config.h',
       'cef_pack_resources.h',
       'cef_pack_strings.h',
   ]
@@ -804,8 +831,8 @@
   transfer_gypi_files(cef_dir, cef_paths2['ceftests_sources_common'], \
                       'tests/ceftests/', ceftests_dir, options.quiet)
 
-  # create the fuzed gtest version
-  create_fuzed_gtest(tests_dir)
+  # copy GTest files
+  copy_gtest(tests_dir)
 
   # process cmake templates
   if not options.ozone:
@@ -828,6 +855,33 @@
   copy_file(os.path.join(cef_dir, 'cef_paths2.gypi'), \
             os.path.join(output_dir, 'cef_paths2.gypi'), options.quiet)
 
+  # transfer Doxyfile
+  transfer_doxyfile(output_dir, options.quiet)
+
+  # transfer README.md
+  copy_file(os.path.join(cef_dir, 'README.md'), \
+            os.path.join(output_dir, 'README.md'), options.quiet)
+
+if not options.nodocs:
+  # generate doc files
+  sys.stdout.write("Generating docs...\n")
+  result = exec_cmd(
+      os.path.join('tools', 'make_cppdocs.%s' %
+                   ('bat' if platform == 'windows' else 'sh')), cef_dir)
+  if (len(result['err']) > 0):
+    sys.stdout.write(result['err'])
+  sys.stdout.write(result['out'])
+
+  src_dir = os.path.join(cef_dir, 'docs')
+  if path_exists(src_dir):
+    # create the docs output directory
+    docs_output_dir = create_output_dir(output_dir_base + '_docs',
+                                        options.outputdir)
+    # transfer contents
+    copy_dir(src_dir, docs_output_dir, options.quiet)
+  else:
+    sys.stdout.write("ERROR: No docs generated.\n")
+
 if platform == 'windows':
   libcef_dll = 'libcef.dll'
   libcef_dll_lib = '%s.lib' % libcef_dll
@@ -835,28 +889,30 @@
   # yapf: disable
   binaries = [
       {'path': 'chrome_elf.dll'},
+      {'path': 'd3dcompiler_47.dll'},
       {'path': libcef_dll},
       {'path': 'libEGL.dll'},
       {'path': 'libGLESv2.dll'},
       {'path': 'snapshot_blob.bin', 'conditional': True},
       {'path': 'v8_context_snapshot.bin', 'conditional': True},
-      {'path': 'swiftshader\\libEGL.dll'},
-      {'path': 'swiftshader\\libGLESv2.dll'},
+      {'path': 'vk_swiftshader.dll'},
+      {'path': 'vk_swiftshader_icd.json'},
+      {'path': 'vulkan-1.dll'},
   ]
   # yapf: enable
 
   if mode == 'client':
-    binaries.append({'path': 'cefclient.exe'})
+    binaries.append({
+        'path': 'cefsimple.exe' if platform_arch == 'arm64' else 'cefclient.exe'
+    })
   else:
     binaries.append({'path': libcef_dll_lib, 'out_path': 'libcef.lib'})
 
   # yapf: disable
   resources = [
-      {'path': 'cef.pak'},
-      {'path': 'cef_100_percent.pak'},
-      {'path': 'cef_200_percent.pak'},
-      {'path': 'cef_extensions.pak'},
-      {'path': 'devtools_resources.pak'},
+      {'path': 'chrome_100_percent.pak'},
+      {'path': 'chrome_200_percent.pak'},
+      {'path': 'resources.pak'},
       {'path': 'icudtl.dat'},
       {'path': 'locales', 'delete': '*.info'},
   ]
@@ -870,7 +926,15 @@
       'obj\\base\\third_party\\dynamic_annotations\\dynamic_annotations.lib',
       'obj\\base\\win\\pe_image.lib',
       cef_sandbox_lib,
+      'obj\\sandbox\\common\\*.obj',
       'obj\\sandbox\\win\\sandbox.lib',
+      'obj\\sandbox\\win\\service_resolver\\*.obj',
+      'obj\\third_party\\abseil-cpp\\absl\\base\\**\\*.obj',
+      'obj\\third_party\\abseil-cpp\\absl\\debugging\\**\\*.obj',
+      'obj\\third_party\\abseil-cpp\\absl\\numeric\\**\\*.obj',
+      'obj\\third_party\\abseil-cpp\\absl\\synchronization\\**\\*.obj',
+      'obj\\third_party\\abseil-cpp\\absl\\time\\**\\*.obj',
+      'obj\\third_party\\abseil-cpp\\absl\\types\\**\\*.obj',
   ]
 
   # Generate the cef_sandbox.lib merged library. A separate *_sandbox build
@@ -899,9 +963,6 @@
       valid_build_dir = build_dir
       dst_dir = os.path.join(output_dir, 'Debug')
       copy_files_list(build_dir, dst_dir, binaries)
-      copy_files(
-          os.path.join(script_dir, 'distrib/win/%s/*.dll' % binary_arch),
-          dst_dir, options.quiet)
 
       if not options.nosymbols:
         # create the symbol output directory
@@ -922,9 +983,6 @@
       valid_build_dir = build_dir
       dst_dir = os.path.join(output_dir, 'Release')
       copy_files_list(build_dir, dst_dir, binaries)
-      copy_files(
-          os.path.join(script_dir, 'distrib/win/%s/*.dll' % binary_arch),
-          dst_dir, options.quiet)
 
       if not options.nosymbols:
         # create the symbol output directory
@@ -979,22 +1037,8 @@
                         'tests/ceftests/', ceftests_dir, options.quiet)
     transfer_gypi_files(cef_dir, cef_paths2['ceftests_sources_resources_win'], \
                         'tests/ceftests/', ceftests_dir, options.quiet)
-    transfer_gypi_files(cef_dir, cef_paths2['ceftests_sources_views'], \
-                        'tests/ceftests/', ceftests_dir, options.quiet)
 
-  if not options.nodocs:
-    # generate doc files
-    os.popen('make_cppdocs.bat ' + cef_rev)
-
-    src_dir = os.path.join(cef_dir, 'docs')
-    if path_exists(src_dir):
-      # create the docs output directory
-      docs_output_dir = create_output_dir(output_dir_base + '_docs',
-                                          options.outputdir)
-      # transfer contents
-      copy_dir(src_dir, docs_output_dir, options.quiet)
-
-elif platform == 'macosx':
+elif platform == 'mac':
   framework_name = 'Chromium Embedded Framework'
   framework_dsym = '%s.dSYM' % framework_name
   cefclient_app = 'cefclient.app'
@@ -1157,10 +1201,11 @@
       {'path': libcef_so},
       {'path': 'libEGL.so'},
       {'path': 'libGLESv2.so'},
+      {'path': 'libvk_swiftshader.so'},
+      {'path': 'libvulkan.so.1'},
       {'path': 'snapshot_blob.bin', 'conditional': True},
       {'path': 'v8_context_snapshot.bin', 'conditional': True},
-      {'path': 'swiftshader/libEGL.so'},
-      {'path': 'swiftshader/libGLESv2.so'},
+      {'path': 'vk_swiftshader_icd.json'},
   ]
   # yapf: enable
   if options.ozone:
@@ -1171,11 +1216,9 @@
 
   # yapf: disable
   resources = [
-      {'path': 'cef.pak'},
-      {'path': 'cef_100_percent.pak'},
-      {'path': 'cef_200_percent.pak'},
-      {'path': 'cef_extensions.pak'},
-      {'path': 'devtools_resources.pak'},
+      {'path': 'chrome_100_percent.pak'},
+      {'path': 'chrome_200_percent.pak'},
+      {'path': 'resources.pak'},
       {'path': 'icudtl.dat'},
       {'path': 'locales', 'delete': '*.info'},
   ]
@@ -1241,8 +1284,6 @@
     # transfer ceftests files
     transfer_gypi_files(cef_dir, cef_paths2['ceftests_sources_linux'], \
                         'tests/ceftests/', ceftests_dir, options.quiet)
-    transfer_gypi_files(cef_dir, cef_paths2['ceftests_sources_views'], \
-                        'tests/ceftests/', ceftests_dir, options.quiet)
 
 if not options.noarchive:
   # create an archive for each output directory
diff --git a/src/tools/make_distrib.sh b/src/tools/make_distrib.sh
index 273a3e1..4b71cf4 100755
--- a/src/tools/make_distrib.sh
+++ b/src/tools/make_distrib.sh
@@ -1,2 +1,2 @@
 #!/bin/sh
-python make_distrib.py --output-dir ../binary_distrib/ $@
+python3 make_distrib.py --output-dir ../binary_distrib/ $@
diff --git a/src/tools/make_libcef_dll_dylib_impl.py b/src/tools/make_libcef_dll_dylib_impl.py
index 14e3696..d117798 100644
--- a/src/tools/make_libcef_dll_dylib_impl.py
+++ b/src/tools/make_libcef_dll_dylib_impl.py
@@ -34,9 +34,7 @@
     arg_types += arg[0:pos]
     arg_names += arg[pos + 1:]
 
-  typedef = 'typedef %s (*%s_ptr)(%s);\n' % (retval, name, arg_types)
-
-  declare = '%s_ptr %s;\n' % (name, name)
+  declare = 'decltype(&%s) %s;\n' % (name, name)
 
   init = '  INIT_ENTRY(%s);' % name
 
@@ -47,12 +45,12 @@
 """ % (retval, name, ', '.join(args), 'return '
        if retval != 'void' else '', name, arg_names)
 
-  return (typedef, declare, init, impl)
+  return (declare, init, impl)
 
 
 def make_libcef_dll_dylib_impl_func(func):
   name = func.get_capi_name()
-  parts = func.get_capi_parts([])
+  parts = func.get_capi_parts([], True)
   retval = parts['retval']
   args = parts['args']
   return make_libcef_dll_dylib_impl_parts(name, retval, args)
@@ -60,16 +58,17 @@
 
 def make_libcef_dll_dylib_impl(header):
   filenames = []
-  includes = []
-  ptr_typedef = ''
+  includes = [
+      '#include "include/base/cef_compiler_specific.h"',
+      '#include "include/wrapper/cef_library_loader.h"',
+  ]
   ptr_declare = ''
   ptr_init = ''
   ptr_impl = ''
 
   # Include required headers for global functions.
   for func in header.get_funcs():
-    typedef, declare, init, impl = make_libcef_dll_dylib_impl_func(func)
-    ptr_typedef += typedef
+    declare, init, impl = make_libcef_dll_dylib_impl_func(func)
     ptr_declare += declare
     ptr_init += init
     ptr_impl += impl
@@ -84,8 +83,7 @@
   for cls in allclasses:
     funcs = cls.get_static_funcs()
     for func in funcs:
-      typedef, declare, init, impl = make_libcef_dll_dylib_impl_func(func)
-      ptr_typedef += typedef
+      declare, init, impl = make_libcef_dll_dylib_impl_func(func)
       ptr_declare += declare
       ptr_init += init
       ptr_impl += impl
@@ -103,9 +101,8 @@
     content = read_file(path)
     funcs = get_function_impls(content, 'CEF_EXPORT', False)
     for func in funcs:
-      typedef, declare, init, impl = make_libcef_dll_dylib_impl_parts(
+      declare, init, impl = make_libcef_dll_dylib_impl_parts(
           func['name'], func['retval'], func['args'])
-      ptr_typedef += typedef
       ptr_declare += declare
       ptr_init += init
       ptr_impl += impl
@@ -119,7 +116,6 @@
 #include <stdio.h>
 
 """ + "\n".join(sorted(includes)) + """
-#include "include/wrapper/cef_library_loader.h"
 
 // GLOBAL WRAPPER FUNCTIONS - Do not edit by hand.
 
@@ -135,14 +131,12 @@
   return ptr;
 }
 
-""" + ptr_typedef + """
-
 struct libcef_pointers {
 """ + ptr_declare + """
 } g_libcef_pointers = {0};
 
 #define INIT_ENTRY(name) \
-  g_libcef_pointers.name = (name##_ptr)libcef_get_ptr(path, #name); \
+  g_libcef_pointers.name = (decltype(&name))libcef_get_ptr(path, #name); \
   if (!g_libcef_pointers.name) { \
     return 0; \
   }
diff --git a/src/tools/make_pack_header.py b/src/tools/make_pack_header.py
index 4f65d76..1afe8d0 100644
--- a/src/tools/make_pack_header.py
+++ b/src/tools/make_pack_header.py
@@ -34,7 +34,7 @@
   #   #define IDR_RESOURCE_NAME 12345
   # [1] See https://crbug.com/684788#c18
 
-  regex = '#define\s([A-Za-z0-9_]{1,})\s'
+  regex = '#define\s([A-Za-z0-9_]{1,})\s+'
   if contents.find('ui::WhitelistedResource') > 0:
     regex += '.*<'
   regex += '([0-9]{1,})'
diff --git a/src/tools/make_version_header.sh b/src/tools/make_version_header.sh
index 50f83fc..30e00b2 100755
--- a/src/tools/make_version_header.sh
+++ b/src/tools/make_version_header.sh
@@ -1,2 +1,2 @@
 #!/bin/sh
-python tools/make_version_header.py include/cef_version.h
+python3 tools/make_version_header.py include/cef_version.h
diff --git a/src/tools/make_views_stub_impl.py b/src/tools/make_views_stub_impl.py
deleted file mode 100644
index 5302b86..0000000
--- a/src/tools/make_views_stub_impl.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
-# reserved. Use of this source code is governed by a BSD-style license that
-# can be found in the LICENSE file.
-
-from __future__ import absolute_import
-from cef_parser import *
-from make_ctocpp_impl import *
-
-
-def make_views_function_stub_impl(clsname, func):
-  name = func.get_name()
-
-  # Build the C++ prototype.
-  parts = func.get_cpp_parts(True)
-  result = make_ctocpp_impl_proto(clsname, name, func, parts) + ' {'
-
-  # Retrieve the function return value.
-  retval = func.get_retval()
-  retval_type = retval.get_retval_type()
-  if retval_type == 'invalid':
-    notify(name + ' could not be autogenerated')
-    # Code could not be auto-generated.
-    result += '\n  // COULD NOT IMPLEMENT DUE TO: (return value)'
-    result += '\n  #pragma message("Warning: "__FILE__": ' + name + ' is not implemented")'
-    retval_default = ''
-  else:
-    retval_default = retval.get_retval_default(False)
-
-  result += '\n  NOTIMPLEMENTED();'
-  if retval_default != '':
-    result += '\n  return ' + retval_default + ';'
-
-  result += '\n}\n\n'
-
-  return result
-
-
-def make_views_class_stub_impl(header, cls):
-  impl = ''
-
-  clsname = cls.get_name()
-  funcs = cls.get_static_funcs()
-  for func in funcs:
-    impl += make_views_function_stub_impl(clsname, func)
-
-  return impl
-
-
-def make_views_stub_impl(header):
-  includes = ''
-  impl = ''
-
-  allclasses = header.get_classes()
-  for cls in allclasses:
-    dir = cls.get_file_directory()
-    # Only process files in the views/ directory.
-    if dir != None and dir.find('views') == 0:
-      cls_impl = make_views_class_stub_impl(header, cls)
-      if cls_impl != '':
-        impl += cls_impl
-        includes += '#include "include/' + cls.get_file_name() + '"\n'
-
-  includes += '\n#include "base/logging.h"\n'
-
-  # Build the final output.
-  result = get_copyright() + includes
-  result += '\n\n// STATIC STUB METHODS - Do not edit by hand.\n\n'
-  result += impl
-  return result
-
-
-def write_views_stub_impl(header, file):
-  newcontents = make_views_stub_impl(header)
-  return (file, newcontents)
-
-
-# Test the module.
-if __name__ == "__main__":
-  import sys
-
-  # Verify that the correct number of command-line arguments are provided.
-  if len(sys.argv) < 2:
-    sys.stderr.write('Usage: ' + sys.argv[0] + ' <cpp_header_dir>\n')
-    sys.exit()
-
-  cpp_header_dir = sys.argv[1]
-
-  # Create the header object. Should match the logic in translator.py.
-  header = obj_header()
-  header.set_root_directory(cpp_header_dir)
-  excluded_files = ['cef_api_hash.h', 'cef_application_mac.h', 'cef_version.h']
-  header.add_directory(cpp_header_dir, excluded_files)
-  header.add_directory(os.path.join(cpp_header_dir, 'views'))
-
-  # Dump the result to stdout.
-  sys.stdout.write(make_views_stub_impl(header))
diff --git a/src/tools/msvs_env.bat b/src/tools/msvs_env.bat
index 0e797c3..8329b72 100644
--- a/src/tools/msvs_env.bat
+++ b/src/tools/msvs_env.bat
@@ -30,10 +30,10 @@
 if exist %vcvars% goto found_vcvars

 

 :: Search for the default VS installation path.

-for %%x in ("%PROGRAMFILES(X86)%" "%PROGRAMFILES%") do (

-  for %%y in (2019 2017) do (

+for %%x in (2022) do (

+  for %%y in ("%PROGRAMFILES%" "%PROGRAMFILES(X86)%") do (

     for %%z in (Professional Enterprise Community BuildTools) do (

-      set vcvars="%%~x\Microsoft Visual Studio\%%y\%%z\VC\Auxiliary\Build\%vcvarsbat%"

+      set vcvars="%%~y\Microsoft Visual Studio\%%x\%%z\VC\Auxiliary\Build\%vcvarsbat%"

       if exist !vcvars! goto found_vcvars

     )

   )

diff --git a/src/tools/patch.sh b/src/tools/patch.sh
index eb97c53..c7d3ee1 100755
--- a/src/tools/patch.sh
+++ b/src/tools/patch.sh
@@ -1,2 +1,2 @@
 #!/bin/sh
-python tools/patcher.py
+python3 tools/patcher.py
diff --git a/src/tools/patch_updater.py b/src/tools/patch_updater.py
index b636c3d..b7e64ba 100644
--- a/src/tools/patch_updater.py
+++ b/src/tools/patch_updater.py
@@ -166,6 +166,14 @@
     msg('Reading patch file %s' % patch_file)
     if 'path' in patch:
       patch_root_abs = os.path.abspath(os.path.join(src_dir, patch['path']))
+      if not os.path.isdir(patch_root_abs):
+        line = 'Target directory does not exist: %s' % patch_root_abs
+        msg(line)
+        if options.resave:
+          # Report as a fatal error for manual resave only, as the missing
+          # directory may be platform-specific.
+          failed_patches[patch['name']] = [line]
+        continue
     else:
       patch_root_abs = src_dir
 
diff --git a/src/tools/patch_updater.sh b/src/tools/patch_updater.sh
index 17b3413..4c3cb12 100755
--- a/src/tools/patch_updater.sh
+++ b/src/tools/patch_updater.sh
@@ -1,2 +1,2 @@
 #!/bin/sh
-python tools/patch_updater.py $@
+python3 tools/patch_updater.py $@
diff --git a/src/tools/patcher.py b/src/tools/patcher.py
index 0ac98ea..023e91d 100644
--- a/src/tools/patcher.py
+++ b/src/tools/patcher.py
@@ -30,7 +30,8 @@
 
 def apply_patch_file(patch_file, patch_dir):
   ''' Apply a specific patch file in optional patch directory. '''
-  patch_path = os.path.join(cef_patch_dir, 'patches', patch_file + '.patch')
+  patch_name = patch_file + '.patch'
+  patch_path = os.path.join(cef_patch_dir, 'patches', patch_name)
 
   if patch_dir is None or len(patch_dir) == 0:
     patch_dir = src_dir
@@ -39,6 +40,10 @@
       # Apply patch relative to the Chromium 'src' directory.
       patch_dir = os.path.join(src_dir, patch_dir)
     patch_dir = os.path.abspath(patch_dir)
+    if not os.path.isdir(patch_dir):
+      sys.stdout.write('\nApply %s in %s\n' % (patch_name, patch_dir))
+      sys.stdout.write('... target directory does not exist (skipping).\n')
+      return 'skip'
 
   result = git_apply_patch_file(patch_path, patch_dir)
   if result == 'fail':
@@ -58,7 +63,7 @@
   exec (compile(open(config_file, "rb").read(), config_file, 'exec'), scope)
   patches = scope["patches"]
 
-  results = {'apply': 0, 'skip': 0, 'fail': 0}
+  results = {'apply': [], 'skip': [], 'fail': []}
 
   for patch in patches:
     patch_file = patch['name']
@@ -73,21 +78,24 @@
     if dopatch:
       result = apply_patch_file(patch_file, patch['path']
                                 if 'path' in patch else None)
-      results[result] += 1
+      results[result].append(patch_file)
 
       if 'note' in patch:
         write_note('NOTE', patch['note'])
     else:
-      results['skip'] += 1
+      results['skip'].append(patch_file)
 
   sys.stdout.write('\n%d patches total (%d applied, %d skipped, %d failed)\n' % \
-      (len(patches), results['apply'], results['skip'], results['fail']))
+      (len(patches), len(results['apply']), len(results['skip']), len(results['fail'])))
 
-  if results['fail'] > 0:
+  if len(results['fail']) > 0:
     sys.stdout.write('\n')
     write_note('ERROR',
                '%d patches failed to apply. Your build will not be correct.' %
-               results['fail'])
+               len(results['fail']))
+    sys.stdout.write('\nTo manually revert failed patches run:' \
+                     '\n$ %s ./tools/patch_updater.py --revert --patch %s\n' %
+                     (os.path.basename(sys.executable), ' --patch '.join(results['fail'])))
     sys.exit(1)
 
 
diff --git a/src/tools/translator.README.txt b/src/tools/translator.README.txt
index 2be478f..4199d32 100644
--- a/src/tools/translator.README.txt
+++ b/src/tools/translator.README.txt
@@ -30,7 +30,7 @@
    // WARNING - CHANGED RETURN VALUE
    //   WAS: void
    //   NOW: int
-   #pragma message("Warning: "__FILE__": MyFunction prototype has changed")
+   #pragma message("Warning: " __FILE__ ": MyFunction prototype has changed")
 
 Auto-generated implementations will be added in the new output file for any
 methods/functions that exist in the CEF header file but did not exist in the
@@ -43,7 +43,7 @@
    {
      // BEGIN DELETE BEFORE MODIFYING
      // AUTO-GENERATED CONTENT
-     #pragma message("Warning: "__FILE__": frame_new_func is not implemented")
+     #pragma message("Warning: " __FILE__ ": frame_new_func is not implemented")
      // END DELETE BEFORE MODIFYING
    }
 
diff --git a/src/tools/translator.py b/src/tools/translator.py
index a2bfd89..1d8552c 100644
--- a/src/tools/translator.py
+++ b/src/tools/translator.py
@@ -16,7 +16,6 @@
 from make_ctocpp_impl import *
 from make_gypi_file import *
 from make_libcef_dll_dylib_impl import *
-from make_views_stub_impl import *
 from make_wrapper_types_header import *
 from optparse import OptionParser
 
@@ -83,7 +82,6 @@
 cpptoc_dir = os.path.join(libcef_dll_dir, 'cpptoc')
 ctocpp_dir = os.path.join(libcef_dll_dir, 'ctocpp')
 gypi_file = os.path.join(root_dir, 'cef_paths.gypi')
-views_stub_impl = os.path.join(libcef_dll_dir, 'views_stub.cc')
 libcef_dll_dylib_impl = os.path.join(libcef_dll_dir, 'wrapper',
                                      'libcef_dll_dylib.cc')
 
@@ -228,11 +226,6 @@
   sys.stdout.write('Generating ' + gypi_file + ' file...\n')
 update_file(*write_gypi_file(header, gypi_file))
 
-# output the views stub file
-if not options.quiet:
-  sys.stdout.write('Generating ' + views_stub_impl + ' file...\n')
-update_file(*write_views_stub_impl(header, views_stub_impl))
-
 # output the libcef dll dylib file
 if not options.quiet:
   sys.stdout.write('Generating ' + libcef_dll_dylib_impl + ' file...\n')
diff --git a/src/tools/translator.sh b/src/tools/translator.sh
index 9304a9f..9cdb1e0 100755
--- a/src/tools/translator.sh
+++ b/src/tools/translator.sh
@@ -1,2 +1,2 @@
 #!/bin/sh
-python translator.py --root-dir .. $@
+python3 translator.py --root-dir .. $@
diff --git a/tools/automate-git.py b/tools/automate-git.py
index 0d02b60..34cf985 100644
--- a/tools/automate-git.py
+++ b/tools/automate-git.py
@@ -1,4 +1,4 @@
-# Based on 2a64387259cf14412e24c3267c8a1eb3b99a54e3
+# Based on 2f0b00f8f59b1a9114fcd855fd7fef37c6ee24ea
 
 # Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
 # reserved. Use of this source code is governed by a BSD-style license that
@@ -8,7 +8,6 @@
 from __future__ import print_function
 import ast
 from datetime import datetime
-import json
 from io import open
 from optparse import OptionParser
 import os
@@ -37,8 +36,6 @@
 
 cef_git_url = 'https://bitbucket.org/chromiumembedded/cef.git'
 
-chromium_channel_json_url = 'https://omahaproxy.appspot.com/all.json'
-
 ##
 # Global system variables.
 ##
@@ -56,7 +53,8 @@
   sys.stdout.write('--> ' + message + "\n")
 
 
-def run(command_line, working_dir, depot_tools_dir=None, output_file=None):
+def run(command_line, working_dir, depot_tools_dir=None, output_file=None,
+        return_output=False):
   """ Runs the specified command. """
   # add depot_tools to the path
   env = os.environ
@@ -69,8 +67,13 @@
     args = shlex.split(command_line.replace('\\', '\\\\'))
 
     if not output_file:
-      return subprocess.check_call(
-          args, cwd=working_dir, env=env, shell=(sys.platform == 'win32'))
+      if return_output:
+        return subprocess.check_output(
+            args, cwd=working_dir, env=env, shell=(sys.platform == 'win32'),
+            universal_newlines=True)
+      else:
+        return subprocess.check_call(
+            args, cwd=working_dir, env=env, shell=(sys.platform == 'win32'))
     try:
       msg('Writing %s' % output_file)
       with open(output_file, 'w', encoding='utf-8') as fp:
@@ -102,6 +105,18 @@
       shutil.rmtree(path, onerror=onerror)
 
 
+def delete_git_directories(path):
+  if os.path.exists(path):
+    if not options.dryrun:
+      git_directory = os.path.join(path, '.git')
+      if os.path.exists(git_directory):
+        msg('Removing git directory under %s' % path)
+        shutil.rmtree(git_directory, onerror=onerror)
+      for child in os.listdir(path):
+        if os.path.isdir(child):
+          delete_git_directories(child)
+
+
 def copy_directory(source, target, allow_overwrite=False):
   """ Copies a directory from source to target. """
   if not options.dryrun and os.path.exists(target):
@@ -162,16 +177,6 @@
   return 'Unknown'
 
 
-def get_git_date(path, branch):
-  """ Returns the date for the specified branch/tag/hash. """
-  cmd = "%s show -s --format=%%ct %s" % (git_exe, branch)
-  result = exec_cmd(cmd, path)
-  if result['out'] != '':
-    return datetime.utcfromtimestamp(
-        int(result['out'].strip())).strftime('%Y-%m-%d %H:%M:%S UTC')
-  return 'Unknown'
-
-
 def get_git_url(path):
   """ Returns the origin url for the specified path. """
   cmd = "%s config --get remote.origin.url" % (git_exe)
@@ -318,7 +323,9 @@
     fp.write(content)
 
 
-def apply_google_patch(name):
+def apply_google_patch(name, patch_dir=None):
+  if not patch_dir:
+    patch_dir = chromium_src_dir
   # Root location of Google-specific patches.
   google_patch_path = os.path.abspath(
       os.path.join(os.path.dirname(__file__), '..', 'patch'))
@@ -328,7 +335,7 @@
     patch_tool = os.path.join(cef_dir, 'tools', 'patcher.py')
     run('%s %s --patch-file "%s" --patch-dir "%s"' %
         (python_exe, patch_tool, patch_file,
-         chromium_src_dir), chromium_src_dir, depot_tools_dir)
+         patch_dir), patch_dir, depot_tools_dir)
 
 
 def add_google_patches():
@@ -433,66 +440,23 @@
     raise
 
 
-def read_json_url(url):
-  """ Read a JSON URL. """
-  msg('Downloading %s' % url)
-  return json.loads(urlopen(url).read())
-
-
-g_channel_data = None
-
-
-def get_chromium_channel_data(os, channel, param=None):
-  """ Returns all data for the specified Chromium channel. """
-  global g_channel_data
-
-  if g_channel_data is None:
-    g_channel_data = read_json_url(chromium_channel_json_url)
-    assert len(g_channel_data) > 0, 'Failed to load Chromium channel data'
-
-  for oses in g_channel_data:
-    if oses['os'] == os:
-      for version in oses['versions']:
-        if version['channel'] == channel:
-          assert version['os'] == os
-          assert version['channel'] == channel
-          if param is None:
-            return version
-          else:
-            assert param in version, 'Missing parameter %s for Chromium channel %s %s' % (
-                param, os, channel)
-            return version[param]
-      raise Exception("Invalid Chromium channel value: %s" % channel)
-  raise Exception("Invalid Chromium os value: %s" % os)
-
-
-def get_chromium_channel_commit(os, channel):
-  """ Returns the current branch commit for the specified Chromium channel. """
-  return get_chromium_channel_data(os, channel, 'branch_commit')
-
-
-def get_chromium_channel_version(os, channel):
-  """ Returns the current version for the specified Chromium channel. """
-  return get_chromium_channel_data(os, channel, 'current_version')
-
-
-def get_chromium_master_position(commit):
-  """ Returns the closest master position for the specified Chromium commit. """
+def get_chromium_main_position(commit):
+  """ Returns the closest main position for the specified Chromium commit. """
   # Using -2 because a "Publish DEPS" commit which does not have a master
   # position may be first.
   cmd = "%s log -2 %s" % (git_exe, commit)
   result = exec_cmd(cmd, chromium_src_dir)
   if result['out'] != '':
-    match = re.search(r'refs/heads/master@{#([\d]+)}', result['out'])
+    match = re.search(r'refs/heads/(?:master|main)@{#([\d]+)}', result['out'])
     assert match != None, 'Failed to find position'
     return int(match.groups()[0])
   return None
 
 
-def get_chromium_master_commit(position):
-  """ Returns the master commit for the specified Chromium commit position. """
-  cmd = '%s log -1 --grep=refs/heads/master@{#%s} origin/master' % (
-      git_exe, str(position))
+def get_chromium_main_commit(position):
+  """ Returns the main commit for the specified Chromium commit position. """
+  cmd = '%s log -1 --grep=refs/heads/master@{#%s} --grep=refs/heads/main@{#%s} origin/main' % (
+      git_exe, str(position), str(position))
   result = exec_cmd(cmd, chromium_src_dir)
   if result['out'] != '':
     match = re.search(r'^commit ([a-f0-9]+)', result['out'])
@@ -501,16 +465,6 @@
   return None
 
 
-def get_chromium_versions(commit):
-  """ Returns the list of Chromium versions that contain the specified commit.
-      Versions are listed oldest to newest. """
-  cmd = '%s tag --contains %s' % (git_exe, commit)
-  result = exec_cmd(cmd, chromium_src_dir)
-  if result['out'] != '':
-    return [line.strip() for line in result['out'].strip().split('\n')]
-  return None
-
-
 def get_build_compat_versions():
   """ Returns the compatible Chromium and (optionally) depot_tools versions
       specified by the CEF checkout. """
@@ -523,68 +477,6 @@
   return config
 
 
-def get_chromium_target_version(os='win', channel='canary', target_distance=0):
-  """ Returns the target Chromium version based on a heuristic. """
-  # The current compatible version from CEF.
-  compat_version = chromium_compat_version
-  compat_commit = get_git_hash(chromium_src_dir, compat_version)
-  if compat_version == compat_commit:
-    versions = get_chromium_versions(compat_commit)
-    if len(versions) > 0:
-      compat_version = 'refs/tags/' + versions[0]
-      # Closest version may not align with the compat position, so adjust the
-      # commit to match.
-      compat_commit = get_git_hash(chromium_src_dir, compat_version)
-  compat_position = get_chromium_master_position(compat_commit)
-  compat_date = get_git_date(chromium_src_dir, compat_commit)
-
-  # The most recent channel version from the Chromium website.
-  channel_version = 'refs/tags/' + get_chromium_channel_version(os, channel)
-  channel_commit = get_chromium_channel_commit(os, channel)
-  channel_position = get_chromium_master_position(channel_commit)
-  channel_date = get_git_date(chromium_src_dir, channel_commit)
-
-  if compat_position >= channel_position:
-    # Already compatible with the channel version or newer.
-    target_version = compat_version
-    target_commit = compat_commit
-    target_position = compat_position
-    target_date = compat_date
-  elif target_distance <= 0 or compat_position + target_distance >= channel_position:
-    # Channel version is within the target distance.
-    target_version = channel_version
-    target_commit = channel_commit
-    target_position = channel_position
-    target_date = channel_date
-  else:
-    # Find an intermediary version that's within the target distance.
-    target_position = compat_position + target_distance
-    target_commit = get_chromium_master_commit(target_position)
-    versions = get_chromium_versions(target_commit)
-    if len(versions) > 0:
-      target_version = 'refs/tags/' + versions[0]
-      # Closest version may not align with the target position, so adjust the
-      # commit and position to match.
-      target_commit = get_git_hash(chromium_src_dir, target_version)
-      target_position = get_chromium_master_position(target_commit)
-    else:
-      target_version = target_commit
-    target_date = get_git_date(chromium_src_dir, target_commit)
-
-  msg("")
-  msg("Computed Chromium update for %s %s at distance %d" % (os, channel,
-                                                             target_distance))
-  msg("Compat:  %s %s %s (#%d)" % (compat_date, compat_version, compat_commit,
-                                   compat_position))
-  msg("Target:  %s %s %s (#%d)" % (target_date, target_version, target_commit,
-                                   target_position))
-  msg("Channel: %s %s %s (#%d)" % (channel_date, channel_version,
-                                   channel_commit, channel_position))
-  msg("")
-
-  return target_version
-
-
 def get_build_directory_name(is_debug):
   build_dir = ('Debug' if is_debug else 'Release') + '_'
 
@@ -623,10 +515,10 @@
     if os.path.exists(out_file):
       os.remove(out_file)
 
-    old_commit = get_chromium_master_commit(
-        get_chromium_master_position(chromium_compat_version))
-    new_commit = get_chromium_master_commit(
-        get_chromium_master_position(chromium_checkout))
+    old_commit = get_chromium_main_commit(
+        get_chromium_main_position(chromium_compat_version))
+    new_commit = get_chromium_main_commit(
+        get_chromium_main_position(chromium_checkout))
 
     cmd = '%s diff --relative --no-prefix %s..%s -- %s' % (
         git_exe, old_commit, new_commit, ' '.join(config['files']))
@@ -697,6 +589,12 @@
       sys.exit(1)
 
 
+def invalid_options_combination(a, b):
+  print("Invalid combination of options: '%s' and '%s'" % (a, b))
+  parser.print_help(sys.stderr)
+  sys.exit(1)
+
+
 ##
 # Program entry point.
 ##
@@ -704,7 +602,7 @@
 # Cannot be loaded as a module.
 if __name__ != "__main__":
   sys.stderr.write('This file cannot be loaded as a module!')
-  sys.exit()
+  sys.exit(1)
 
 # Parse command-line options.
 disc = """
@@ -752,16 +650,6 @@
                        'branch/hash/tag). This overrides the value specified '+\
                        'by CEF in CHROMIUM_BUILD_COMPATIBILITY.txt.',
                   default='')
-parser.add_option('--chromium-channel', dest='chromiumchannel',
-                  help='Chromium channel to check out (canary, dev, beta or '+\
-                       'stable). This overrides the value specified by CEF '+\
-                       'in CHROMIUM_BUILD_COMPATIBILITY.txt.',
-                  default='')
-parser.add_option('--chromium-channel-distance', dest='chromiumchanneldistance',
-                  help='The target number of commits to step in the '+\
-                       'channel, or 0 to use the newest channel version. '+\
-                       'Used in combination with --chromium-channel.',
-                  default='')
 
 # Miscellaneous options.
 parser.add_option(
@@ -774,6 +662,12 @@
                   action='store_true', dest='forceclean', default=False,
                   help='Force a clean checkout of Chromium and CEF. This will'+\
                        ' trigger a new update, build and distribution.')
+parser.add_option('--disposable-chromium-checkout',
+                  action='store_true', dest='disposablecheckout', default=False,
+                  help='Clean up unneeded parts of the Chromium checkout as'+\
+                       ' the build proceeds. This reduces the amount of disk'+\
+                       ' space needed for the build, but makes the checkout'+\
+                       ' unusable for later builds.')
 parser.add_option('--force-clean-deps',
                   action='store_true', dest='forcecleandeps', default=False,
                   help='Force a clean checkout of Chromium dependencies. Used'+\
@@ -816,6 +710,12 @@
     default=False,
     help='Do not update Chromium.')
 parser.add_option(
+    '--no-chromium-history',
+    action='store_true',
+    dest='nochromiumhistory',
+    default=False,
+    help='Do not keep Chromium history.')
+parser.add_option(
     '--no-depot-tools-update',
     action='store_true',
     dest='nodepottoolsupdate',
@@ -922,6 +822,12 @@
     dest='arm64build',
     default=False,
     help='Create an ARM64 build.')
+parser.add_option(
+    '--with-pgo-profiles',
+    action='store_true',
+    dest='withpgoprofiles',
+    default=False,
+    help='Download PGO profiles for the build.')
 
 # Test-related options.
 parser.add_option(
@@ -1042,7 +948,7 @@
 if options.downloaddir is None:
   print("The --download-dir option is required.")
   parser.print_help(sys.stderr)
-  sys.exit()
+  sys.exit(1)
 
 # Opt into component-specific flags for later use.
 if options.noupdate:
@@ -1053,15 +959,18 @@
 if options.runtests:
   options.buildtests = True
 
-if (options.nochromiumupdate and options.forceupdate) or \
-   (options.nocefupdate and options.forceupdate) or \
-   (options.nobuild and options.forcebuild) or \
-   (options.nodistrib and options.forcedistrib) or \
-   ((options.forceclean or options.forcecleandeps) and options.fastupdate) or \
-   (options.chromiumcheckout and options.chromiumchannel):
-  print("Invalid combination of options.")
-  parser.print_help(sys.stderr)
-  sys.exit()
+if options.nochromiumupdate and options.forceupdate:
+  invalid_options_combination('--no-chromium-update', '--force-update')
+if options.nocefupdate and options.forceupdate:
+  invalid_options_combination('--no-cef-update', '--force-update')
+if options.nobuild and options.forcebuild:
+  invalid_options_combination('--no-build', '--force-build')
+if options.nodistrib and options.forcedistrib:
+  invalid_options_combination('--no-distrib', '--force-distrib')
+if options.forceclean and options.fastupdate:
+  invalid_options_combination('--force-clean', '--fast-update')
+if options.forcecleandeps and options.fastupdate:
+  invalid_options_combination('--force-clean-deps', '--fast-update')
 
 if (options.noreleasebuild and \
      (options.minimaldistrib or options.minimaldistribonly or \
@@ -1069,24 +978,24 @@
    (options.minimaldistribonly + options.clientdistribonly + options.sandboxdistribonly > 1):
   print('Invalid combination of options.')
   parser.print_help(sys.stderr)
-  sys.exit()
+  sys.exit(1)
 
 if options.x64build + options.armbuild + options.arm64build > 1:
   print('Invalid combination of options.')
   parser.print_help(sys.stderr)
-  sys.exit()
+  sys.exit(1)
 
 if (options.buildtests or options.runtests) and len(options.testtarget) == 0:
   print("A test target must be specified via --test-target.")
   parser.print_help(sys.stderr)
-  sys.exit()
+  sys.exit(1)
 
 # Operating system.
 if options.dryrun and options.dryrunplatform is not None:
   platform = options.dryrunplatform
   if not platform in ['windows', 'mac', 'linux']:
     print('Invalid dry-run-platform value: %s' % (platform))
-    sys.exit()
+    sys.exit(1)
 elif sys.platform == 'win32':
   platform = 'windows'
 elif sys.platform == 'darwin':
@@ -1095,10 +1004,10 @@
   platform = 'linux'
 else:
   print('Unknown operating system platform')
-  sys.exit()
+  sys.exit(1)
 
 if options.clientdistrib or options.clientdistribonly:
-  if platform == 'linux':
+  if platform == 'linux' or (platform == 'windows' and options.arm64build):
     client_app = 'cefsimple'
   else:
     client_app = 'cefclient'
@@ -1106,7 +1015,7 @@
     print('A client distribution cannot be generated if --build-target ' +
           'excludes %s.' % client_app)
     parser.print_help(sys.stderr)
-    sys.exit()
+    sys.exit(1)
 
 # CEF branch.
 cef_branch = options.branch
@@ -1116,13 +1025,13 @@
   # Verify that the branch value is numeric.
   if not cef_branch.isdigit():
     print('Invalid branch value: %s' % cef_branch)
-    sys.exit()
+    sys.exit(1)
 
   # Verify the minimum supported branch number.
   if int(cef_branch) < 3071:
     print('The requested branch (%s) is too old to build using this tool. ' +
           'The minimum supported branch is 3071.' % cef_branch)
-    sys.exit()
+    sys.exit(1)
 
 # True if the requested branch is 3538 or newer.
 branch_is_3538_or_newer = (branch_is_master or int(cef_branch) >= 3538)
@@ -1139,19 +1048,19 @@
   (not is_python2 or bool(int(os.environ.get('GCLIENT_PY3', '0')))):
   print('Python 3 is not supported with branch 3904 and older ' +
         '(set GCLIENT_PY3=0 and run with Python 2 executable).')
-  sys.exit()
+  sys.exit(1)
 
 if options.armbuild:
   if platform != 'linux':
     print('The ARM build option is only supported on Linux.')
-    sys.exit()
+    sys.exit(1)
 
 deps_file = 'DEPS'
 
 if platform == 'mac' and not (options.x64build or options.arm64build):
   print('32-bit MacOS builds are not supported. ' +
         'Add --x64-build or --arm64-build flag to generate a 64-bit build.')
-  sys.exit()
+  sys.exit(1)
 
 # Platforms that build a cef_sandbox library.
 sandbox_lib_platforms = ['windows']
@@ -1161,7 +1070,7 @@
 if not platform in sandbox_lib_platforms and (options.sandboxdistrib or
                                               options.sandboxdistribonly):
   print('The sandbox distribution is not supported on this platform.')
-  sys.exit()
+  sys.exit(1)
 
 # Options that force the sources to change.
 force_change = options.forceclean or options.forceupdate
@@ -1173,7 +1082,7 @@
   print('--resave cannot be combined with options that modify or discard ' +
         'patches.')
   parser.print_help(sys.stderr)
-  sys.exit()
+  sys.exit(1)
 
 download_dir = os.path.abspath(options.downloaddir)
 chromium_dir = os.path.join(download_dir, 'chromium')
@@ -1232,10 +1141,16 @@
   else:
     run('update_depot_tools', depot_tools_dir, depot_tools_dir)
 
+# Point Python to the version provided by depot_tools
+os.environ['PATH'] = os.path.join(depot_tools_dir, 'python-bin') \
+    + os.pathsep + os.environ['PATH']
+
 # Determine the executables to use.
 if platform == 'windows':
   # Force use of the version bundled with depot_tools.
   git_exe = os.path.join(depot_tools_dir, 'git.bat')
+  run('%s config --system core.longpaths true' % (git_exe),
+      download_dir, depot_tools_dir)
   python_bat = 'python.bat' if is_python2 else 'python3.bat'
   python_exe = os.path.join(depot_tools_dir, python_bat)
   if options.dryrun and not os.path.exists(git_exe):
@@ -1246,7 +1161,10 @@
     python_exe = python_bat
 else:
   git_exe = 'git'
-  python_exe = sys.executable
+  if is_python2:
+    python_exe = os.path.join(depot_tools_dir, 'python2-bin', 'python2')
+  else:
+    python_exe = os.path.join(depot_tools_dir, 'python-bin', 'python3')
 
 ##
 # Manage the cef directory.
@@ -1345,6 +1263,9 @@
 # Disable further depot_tools updates.
 os.environ['DEPOT_TOOLS_UPDATE'] = '0'
 
+# Enable bare clones in gclient
+apply_google_patch('bare_clone', patch_dir=depot_tools_dir)
+
 ##
 # Manage the out directory.
 ##
@@ -1371,6 +1292,7 @@
 
 # Create gclient configuration file.
 gclient_file = os.path.join(chromium_dir, '.gclient')
+
 if not os.path.exists(gclient_file) or options.forceconfig:
   # Exclude unnecessary directories. Intentionally written without newlines.
   gclient_spec = \
@@ -1392,6 +1314,11 @@
           "'src/chrome/tools/test/reference_build/chrome_mac': None, "+\
           "'src/chrome/tools/test/reference_build/chrome_win': None, "+\
         "}, "+\
+        "'custom_vars': {"+\
+          "'checkout_pgo_profiles': " + ('True' if options.withpgoprofiles else 'False') + ", "+\
+          "'checkout_nacl': False, "+\
+          "'download_remoteexec_cfg': True, "+\
+        "}, "+\
         "'deps_file': '" + deps_file + "', "+\
         "'safesync_url': ''"+\
       "}]"
@@ -1404,7 +1331,13 @@
 # Initial Chromium checkout.
 if not options.nochromiumupdate and not os.path.exists(chromium_src_dir):
   chromium_checkout_new = True
-  run("gclient sync --nohooks --with_branch_heads --jobs 16", \
+  nohistoryopts = ""
+  if options.nochromiumhistory:
+    revision = build_compat_versions['chromium_checkout']
+    if len(options.chromiumcheckout) > 0:
+      revision = options.chromiumcheckout
+    nohistoryopts = " --no-history --revision src@" + revision
+  run("gclient sync --nohooks --with_branch_heads --jobs 16" + nohistoryopts, \
       chromium_dir, depot_tools_dir)
 else:
   chromium_checkout_new = False
@@ -1418,7 +1351,8 @@
 
 # Fetch Chromium changes so that we can perform the necessary calculations using
 # local history.
-if not options.nochromiumupdate and os.path.exists(chromium_src_dir):
+if not options.nochromiumupdate and not options.nochromiumhistory \
+    and os.path.exists(chromium_src_dir):
   # Fetch updated sources.
   run("%s fetch" % (git_exe), chromium_src_dir, depot_tools_dir)
   # Also fetch tags, which are required for release branch builds.
@@ -1428,11 +1362,6 @@
 chromium_compat_version = build_compat_versions['chromium_checkout']
 if len(options.chromiumcheckout) > 0:
   chromium_checkout = options.chromiumcheckout
-elif len(options.chromiumchannel) > 0:
-  target_distance = int(options.chromiumchanneldistance
-                       ) if len(options.chromiumchanneldistance) > 0 else 0
-  chromium_checkout = get_chromium_target_version(
-      channel=options.chromiumchannel, target_distance=target_distance)
 else:
   chromium_checkout = chromium_compat_version
 
@@ -1498,6 +1427,8 @@
   # Patch the Chromium runhooks scripts if necessary.
   apply_runhooks_patch()
   apply_google_patch('mac_toolchain_creds')
+  apply_google_patch('skip_numpy')
+  apply_google_patch('skip_snapcraft')
 
   # Runs hooks for files that have been modified in the local working copy.
   run("gclient runhooks --jobs 16", chromium_dir, depot_tools_dir)
@@ -1591,6 +1522,20 @@
   tool = os.path.join(cef_src_dir, 'tools', 'gclient_hook.py')
   run('%s %s' % (python_exe, tool), cef_src_dir, depot_tools_dir)
 
+  # Retrieve Chromium checkout information for later use
+  chromium_url = run('%s config --get remote.origin.url' % git_exe,
+                     chromium_src_dir, return_output=True)
+  chromium_rev = run('%s rev-parse %s' % (git_exe, 'HEAD'), chromium_src_dir,
+                     return_output=True)
+
+  chromium_url = 'Unknown' if not chromium_url else chromium_url.strip()
+  chromium_rev = 'Unknown' if not chromium_rev else chromium_rev.strip()
+  print('Chromium URL: %s\nChromium Rev: %s\n' % (chromium_url, chromium_rev))
+
+  if options.disposablecheckout:
+    # Remove Chromium git repo information to save space on the build machine
+    delete_git_directories(chromium_src_dir)
+
   # Build using Ninja.
   command = 'autoninja '
   if options.verbosebuild:
@@ -1755,5 +1700,10 @@
     if options.distribsubdirsuffix != '':
       path += ' --distrib-subdir-suffix=' + options.distribsubdirsuffix
 
+    # Use the already-fetched Chromium checkout information if deleted.
+    if options.disposablecheckout:
+      path += ' --chromium-url=' + chromium_url
+      path += ' --chromium-rev=' + chromium_rev
+
     # Create the distribution.
     run(path, cef_tools_dir, depot_tools_dir)